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);