On 2018-09-03 16:09, [ext] Andreas J. Reichel wrote:
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     | 90 +++++++++++++++++++++++++++--------------------
  env/syspart.c     | 48 +++++++++++++++++++++++--
  include/syspart.h |  3 +-
  3 files changed, 98 insertions(+), 43 deletions(-)

diff --git a/env/fatvars.c b/env/fatvars.c
index d51956c..d1e5ecb 100644
--- a/env/fatvars.c
+++ b/env/fatvars.c
@@ -21,23 +21,26 @@ 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;
+       }
+
+       if (EFI_ERROR(filter_cfg_parts(&config_volumes, &numHandles))) {
+               Print(L"Error, could not filter config partitions.\n");
+               goto scc_cleanup;
        }
if (numHandles != ENV_NUM_CONFIG_PARTS) {
@@ -46,19 +49,18 @@ BG_STATUS save_current_config(void)
                      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 +72,49 @@ 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;
+       }
+
+       if (EFI_ERROR(filter_cfg_parts(&config_volumes, &numHandles))) {
+               Print(L"Error, could not filter config partitions.\n");
+               goto lc_cleanup;
        }
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 +129,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 +144,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 +167,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 +232,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..8a792df 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,44 @@ EFI_STATUS enumerate_cfg_parts(EFI_FILE_HANDLE *roots, UINTN 
*numHandles)
        Print(L"%d config partitions detected.\n", rootCount);
        return EFI_SUCCESS;
  }
+
+EFI_STATUS filter_cfg_parts(UINTN **config_volumes, UINTN *numHandles)
+{
+       BOOLEAN use_envs_on_bootdevice_only = FALSE;
+       UINTN *filtered_volumes;
+
+       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 EFI_SUCCESS;
+       }
+
+       filtered_volumes = mmalloc(sizeof(UINTN) * *numHandles);

Missing NULL check. That will actually give the function an error path.

Alternatively, you could sort all volumes you want to keep to the beginning of the existing array and only adjust *numHandles. Then you could actually return that value because there will be no error code anymore, and that would simplify also the caller.

+
+       Print(L"Booting with environments from boot device only.\n");
+       UINTN index = 0;
+       for (UINTN j = 0; j < *numHandles; j++) {
+               UINTN cvi = (*config_volumes)[j];
+               VOLUME_DESC *v = &volumes[cvi];
+
+               if (IsOnBootDevice(v->devpath)) {
+                       filtered_volumes[index++] = (*config_volumes)[j];
+               } else {
+                       Print(L"Filtered out config on volume #%d\n", cvi);

Maybe "Ignoring config on..."?

+               }
+       }
+       *numHandles = index;
+
+       mfree(*config_volumes);
+       *config_volumes = filtered_volumes;
+       Print(L"Remaining Config Partitions: %d\n", *numHandles);

Do we need that verbosity level? I don't see the value for the user yet.

+       return EFI_SUCCESS;
+}
diff --git a/include/syspart.h b/include/syspart.h
index 502d1f1..308668c 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);
+EFI_STATUS filter_cfg_parts(UINTN **config_volumes, UINTN *maxHandles);
#endif // __H_SYSPART__


Jan

--
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/03370dc8-1851-4521-eb75-0066e706fa7f%40siemens.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to