From: Andreas Reichel <[email protected]>

If one environment is found on the boot device, only use environments
from there and ignore all other devices. This way, one can boot from a
memory stick without messing around with already installed efibootguard
configs on the harddrive for example.

Also simplify error handling in config loading and writing.

Signed-off-by: Andreas Reichel <[email protected]>
---
 env/fatvars.c     | 84 +++++++++++++++++++++++++----------------------
 env/syspart.c     | 50 ++++++++++++++++++++++++++--
 include/syspart.h |  3 +-
 3 files changed, 94 insertions(+), 43 deletions(-)

diff --git a/env/fatvars.c b/env/fatvars.c
index d51956c..99ac37e 100644
--- a/env/fatvars.c
+++ b/env/fatvars.c
@@ -21,44 +21,43 @@ static BG_ENVDATA env[ENV_NUM_CONFIG_PARTS];
 
 BG_STATUS save_current_config(void)
 {
-       BG_STATUS result = BG_SUCCESS;
+       BG_STATUS result = BG_CONFIG_ERROR;
        EFI_STATUS efistatus;
        UINTN numHandles = volume_count;
-       EFI_FILE_HANDLE *roots;
+       UINTN *config_volumes;
 
-       roots = (EFI_FILE_HANDLE *)mmalloc(sizeof(EFI_FILE_HANDLE) *
-                                          volume_count);
-       if (!roots) {
+       config_volumes = (UINTN *)mmalloc(sizeof(UINTN) *  volume_count);
+       if (!config_volumes) {
                Print(L"Error, could not allocate memory for config partition "
-                     L"handles.\n");
-               return BG_CONFIG_ERROR;
+                     L"mapping.\n");
+               return result;
        }
 
-       if (EFI_ERROR(enumerate_cfg_parts(roots, &numHandles))) {
-               Print(L"Error, could not enumerate config partitions.");
-               mfree(roots);
-               return BG_CONFIG_ERROR;
+       if (EFI_ERROR(enumerate_cfg_parts(config_volumes, &numHandles))) {
+               Print(L"Error, could not enumerate config partitions.\n");
+               goto scc_cleanup;
        }
 
+       numHandles = filter_cfg_parts(config_volumes, numHandles);
+
        if (numHandles != ENV_NUM_CONFIG_PARTS) {
                Print(L"Error, unexpected number of config partitions: found "
                      L"%d, but expected %d.\n",
                      numHandles, ENV_NUM_CONFIG_PARTS);
                /* In case of saving, this must be treated as error, to not
                 * overwrite another partition's config file. */
-               mfree(roots);
-               return BG_CONFIG_ERROR;
+               goto scc_cleanup;
        }
 
+       VOLUME_DESC *v = &volumes[config_volumes[current_partition]];
        EFI_FILE_HANDLE fh = NULL;
-       efistatus = open_cfg_file(roots[current_partition], &fh,
-                                 EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ);
+       efistatus = open_cfg_file(v->root, &fh, EFI_FILE_MODE_WRITE |
+                                 EFI_FILE_MODE_READ);
        if (EFI_ERROR(efistatus)) {
                Print(L"Error, could not open environment file on system "
                      L"partition %d: %r\n",
                      current_partition, efistatus);
-               mfree(roots);
-               return BG_CONFIG_ERROR;
+               goto scc_cleanup;
        }
 
        UINTN writelen = sizeof(BG_ENVDATA);
@@ -70,43 +69,46 @@ BG_STATUS save_current_config(void)
                                      (VOID *)&env[current_partition]);
        if (EFI_ERROR(efistatus)) {
                Print(L"Error writing environment to file: %r\n", efistatus);
-               result = BG_CONFIG_ERROR;
+               (VOID) close_cfg_file(v->root, fh);
+               goto scc_cleanup;
        }
 
-       if (EFI_ERROR(close_cfg_file(roots[current_partition], fh))) {
+       if (EFI_ERROR(close_cfg_file(v->root, fh))) {
                Print(L"Error, could not close environment config file.\n");
-               result = BG_CONFIG_ERROR;
+               goto scc_cleanup;
        }
-       mfree(roots);
+
+       result = BG_SUCCESS;
+scc_cleanup:
+       mfree(config_volumes);
        return result;
 }
 
 BG_STATUS load_config(BG_LOADER_PARAMS *bglp)
 {
-       BG_STATUS result = BG_SUCCESS;
+       BG_STATUS result = BG_CONFIG_ERROR;
        UINTN numHandles = volume_count;
-       EFI_FILE_HANDLE *roots;
+       UINTN *config_volumes;
        UINTN i;
        int env_invalid[ENV_NUM_CONFIG_PARTS] = {0};
 
-       roots = (EFI_FILE_HANDLE *)mmalloc(sizeof(EFI_FILE_HANDLE) *
-                                          volume_count);
-       if (!roots) {
+       config_volumes = (UINTN *)mmalloc(sizeof(UINTN) * volume_count);
+       if (!config_volumes) {
                Print(L"Error, could not allocate memory for config partition "
-                     L"handles.\n");
-               return BG_CONFIG_ERROR;
+                     L"mapping.\n");
+               return result;
        }
 
-       if (EFI_ERROR(enumerate_cfg_parts(roots, &numHandles))) {
-               Print(L"Error, could not enumerate config partitions.");
-               mfree(roots);
-               return BG_CONFIG_ERROR;
+       if (EFI_ERROR(enumerate_cfg_parts(config_volumes, &numHandles))) {
+               Print(L"Error, could not enumerate config partitions.\n");
+               goto lc_cleanup;
        }
 
+       numHandles = filter_cfg_parts(config_volumes, numHandles);
+
        if (numHandles > ENV_NUM_CONFIG_PARTS) {
                Print(L"Error, too many config partitions found. Aborting.\n");
-               mfree(roots);
-               return BG_CONFIG_ERROR;
+               goto lc_cleanup;
        }
 
        if (numHandles < ENV_NUM_CONFIG_PARTS) {
@@ -121,8 +123,9 @@ BG_STATUS load_config(BG_LOADER_PARAMS *bglp)
        /* Load all config data */
        for (i = 0; i < numHandles; i++) {
                EFI_FILE_HANDLE fh = NULL;
-               if (EFI_ERROR(open_cfg_file(roots[i], &fh,
-                                           EFI_FILE_MODE_READ))) {
+               VOLUME_DESC *v = &volumes[config_volumes[i]];
+               if (EFI_ERROR(open_cfg_file(v->root, &fh,
+                                           EFI_FILE_MODE_READ))) {
                        Print(L"Warning, could not open environment file on "
                              L"config partition %d\n",
                              i);
@@ -135,7 +138,7 @@ BG_STATUS load_config(BG_LOADER_PARAMS *bglp)
                              L"partition %d.\n",
                              i);
                        env_invalid[i] = 1;
-                       if (EFI_ERROR(close_cfg_file(roots[i], fh))) {
+                       if (EFI_ERROR(close_cfg_file(v->root, fh))) {
                                Print(L"Error, could not close environment "
                                      L"config file.\n");
                        }
@@ -158,7 +161,7 @@ BG_STATUS load_config(BG_LOADER_PARAMS *bglp)
                        result = BG_CONFIG_PARTIALLY_CORRUPTED;
                }
 
-               if (EFI_ERROR(uefi_call_wrapper(fh->Close, 1, fh))) {
+               if (EFI_ERROR(close_cfg_file(v->root, fh))) {
                        Print(L"Error, could not close environment config "
                              L"file.\n");
                        /* Don't abort, so we may still be able to boot a
@@ -223,7 +226,10 @@ BG_STATUS load_config(BG_LOADER_PARAMS *bglp)
        Print(L" kernel: %s\n", bglp->payload_path);
        Print(L" args: %s\n", bglp->payload_options);
        Print(L" timeout: %d seconds\n", bglp->timeout);
-       mfree(roots);
+
+       result = BG_SUCCESS;
+lc_cleanup:
+       mfree(config_volumes);
        return result;
 }
 
diff --git a/env/syspart.c b/env/syspart.c
index 29124dd..0cfeb79 100644
--- a/env/syspart.c
+++ b/env/syspart.c
@@ -14,15 +14,16 @@
 
 #include <syspart.h>
 #include <utils.h>
+#include <envdata.h>
 
 #define MAX_INFO_SIZE 1024
 
-EFI_STATUS enumerate_cfg_parts(EFI_FILE_HANDLE *roots, UINTN *numHandles)
+EFI_STATUS enumerate_cfg_parts(UINTN *config_volumes, UINTN *numHandles)
 {
        EFI_STATUS status;
        UINTN rootCount = 0;
 
-       if (!roots || !numHandles) {
+       if (!config_volumes || !numHandles) {
                Print(L"Invalid parameter in system partition enumeration.\n");
                return EFI_INVALID_PARAMETER;
        }
@@ -36,7 +37,7 @@ EFI_STATUS enumerate_cfg_parts(EFI_FILE_HANDLE *roots, UINTN 
*numHandles)
                                       EFI_FILE_MODE_READ);
                if (status == EFI_SUCCESS) {
                        Print(L"Config file found on volume %d.\n", index);
-                       roots[rootCount] = volumes[index].root;
+                       config_volumes[rootCount] = index;
                        rootCount++;
                        status = close_cfg_file(volumes[index].root, fh);
                        if (EFI_ERROR(status)) {
@@ -50,3 +51,46 @@ EFI_STATUS enumerate_cfg_parts(EFI_FILE_HANDLE *roots, UINTN 
*numHandles)
        Print(L"%d config partitions detected.\n", rootCount);
        return EFI_SUCCESS;
 }
+
+static void swap_uintn(UINTN *a, UINTN *b)
+{
+       UINTN tmp;
+       tmp = *a;
+       *a = *b;
+       *b = tmp;
+}
+
+UINTN filter_cfg_parts(UINTN *config_volumes, UINTN numHandles)
+{
+       BOOLEAN use_envs_on_bootdevice_only = FALSE;
+
+       Print(L"Config filter: \n");
+       for (UINTN index = 0; index < numHandles; index++) {
+               VOLUME_DESC *v = &volumes[config_volumes[index]];
+
+               if (IsOnBootDevice(v->devpath)) {
+                       use_envs_on_bootdevice_only = TRUE;
+               };
+       }
+
+       if (!use_envs_on_bootdevice_only) {
+               // nothing to do
+               return numHandles;
+       }
+
+       Print(L"Booting with environments from boot device only.\n");
+       UINTN num_sorted = 0;
+       for (UINTN j = 0; j < numHandles; j++) {
+               UINTN cvi = config_volumes[j];
+               VOLUME_DESC *v = &volumes[cvi];
+
+               if (IsOnBootDevice(v->devpath)) {
+                       swap_uintn(&config_volumes[j],
+                                  &config_volumes[num_sorted++]);
+               } else {
+                       Print(L"Ignoring config on volume #%d\n", cvi);
+               }
+       }
+
+       return num_sorted;
+}
diff --git a/include/syspart.h b/include/syspart.h
index 502d1f1..b22577b 100644
--- a/include/syspart.h
+++ b/include/syspart.h
@@ -32,6 +32,7 @@
 #define read_cfg_file(file, len, buffer)                                     \
        uefi_call_wrapper((file)->Read, 3, (file), (len), (buffer))
 
-EFI_STATUS enumerate_cfg_parts(EFI_FILE_HANDLE *roots, UINTN *maxHandles);
+EFI_STATUS enumerate_cfg_parts(UINTN *config_volumes, UINTN *maxHandles);
+UINTN filter_cfg_parts(UINTN *config_volumes, UINTN maxHandles);
 
 #endif // __H_SYSPART__
-- 
2.18.0

-- 
You received this message because you are subscribed to the Google Groups "EFI 
Boot Guard" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/efibootguard-dev/20180905162030.28077-5-andreas.reichel.ext%40siemens.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to