Message ID | 20201230150722.154663-8-ilias.apalodimas@linaro.org |
---|---|
State | New |
Headers | show |
Series | Change logic of EFI LoadFile2 protocol for initrd loading | expand |
On 12/30/20 4:07 PM, Ilias Apalodimas wrote: > We changed the logic of the initrd discovery and the installation of the > protocol in the previous patch. > Instead of a config now option it now resides in an EFI variable. Adjust > the existing tests accordingly and add self-tests which will cover the new > features. A full test would comprise installing a block device of type EFI containing a binary and an initial ram disk. The loaded binary could check the content of the ram disk. E.g. the CRC32 and the length could be returned via exit data by the binary. Have a look at lib/efi_selftest/efi_selftest_block_device.c. Best regards Heinrich > > Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org> > --- > lib/efi_selftest/efi_selftest_load_initrd.c | 100 +++++++++++++++++++- > 1 file changed, 97 insertions(+), 3 deletions(-) > > diff --git a/lib/efi_selftest/efi_selftest_load_initrd.c b/lib/efi_selftest/efi_selftest_load_initrd.c > index fe060a664402..1534c2ba24fa 100644 > --- a/lib/efi_selftest/efi_selftest_load_initrd.c > +++ b/lib/efi_selftest/efi_selftest_load_initrd.c > @@ -14,10 +14,12 @@ > * > * CONFIG_EFI_SELFTEST=y > * CONFIG_EFI_LOAD_FILE2_INITRD=y > - * CONFIG_EFI_INITRD_FILESPEC="host 0:1 initrd" > * > - * * Run ./u-boot and execute > + * * Create files > + * mkdir init_test && cp initrd init_test/ > + * virt-make-fs -t ext4 init_test test.img > * > + * * Run ./u-boot and execute > * host bind 0 image > * setenv efi_selftest load initrd > * bootefi selftest > @@ -43,6 +45,7 @@ > #include <efi_load_initrd.h> > > static struct efi_boot_services *boottime; > +static struct efi_runtime_services *runtime; > > static struct efi_initrd_dp dp = { > .vendor = { > @@ -76,10 +79,13 @@ static struct efi_initrd_dp dp_invalid = { > } > }; > > +static efi_handle_t handle; > + > static int setup(const efi_handle_t handle, > const struct efi_system_table *systable) > { > boottime = systable->boottime; > + runtime = systable->runtime; > > return EFI_ST_SUCCESS; > } > @@ -87,16 +93,97 @@ static int setup(const efi_handle_t handle, > static int execute(void) > { > efi_guid_t lf2_proto_guid = EFI_LOAD_FILE2_PROTOCOL_GUID; > + efi_guid_t efi_global_variable_guid = EFI_GLOBAL_VARIABLE_GUID; > struct efi_load_file_protocol *lf2; > struct efi_device_path *dp2, *dp2_invalid; > efi_status_t status; > - efi_handle_t handle; > char buffer[64]; > efi_uintn_t buffer_size; > void *buf; > u32 crc32; > + u16 boot_current = 0; > + efi_uintn_t boot_current_size = sizeof(boot_current); > + char path[] = "host 0 initrd"; > + char invalid_path[] = "host 1 initrd"; > + efi_uintn_t path_size = sizeof(path); > + efi_uintn_t invalid_path_size = sizeof(invalid_path); > + u32 attrs = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS; > > memset(buffer, 0, sizeof(buffer)); > + /* Set variable BootCurrent and Initrd#### to a wrong value */ > + status = runtime->set_variable(L"BootCurrent", &efi_global_variable_guid, > + attrs, boot_current_size, &boot_current); > + if (status != EFI_SUCCESS) { > + efi_st_error("SetVariable for BootCurrent failed\n"); > + return EFI_ST_FAILURE; > + } > + > + /* > + * We don't need NV for Initrd here. > + * Set the file to an invalid file path > + */ > + status = runtime->set_variable(L"Initrd0010", &efi_global_variable_guid, > + attrs, invalid_path_size, invalid_path); > + if (status != EFI_SUCCESS) { > + efi_st_error("SetVariable for Initrd failed\n"); > + return EFI_ST_FAILURE; > + } > + > + /* We only install the protocol during efibootmgr */ > + status = efi_initrd_register(&handle); > + if (status != EFI_SUCCESS) { > + efi_st_error("Failed to install initrd protocol\n"); > + return EFI_ST_FAILURE; > + } > + > + /* > + * We should only install the protocol if the file's found > + * Right now both BootCurrent and file path are invalid > + */ > + dp2 = (struct efi_device_path *)&dp; > + status = boottime->locate_device_path(&lf2_proto_guid, &dp2, &handle); > + if (status != EFI_NOT_FOUND) { > + efi_st_error("Initrd protocol should't be installed\n"); > + return EFI_ST_FAILURE; > + } > + > + /* Update BootCurrent to the correct value */ > + boot_current = 0x0010; > + status = runtime->set_variable(L"BootCurrent", &efi_global_variable_guid, > + attrs, boot_current_size, &boot_current); > + if (status != EFI_SUCCESS) { > + efi_st_error("SetVariable for BootCurrent failed\n"); > + return EFI_ST_FAILURE; > + } > + > + /* re-install with invalid file path */ > + status = efi_initrd_register(&handle); > + if (status != EFI_SUCCESS) { > + efi_st_error("Failed to install initrd protocol\n"); > + return EFI_ST_FAILURE; > + } > + > + /* file path is invalid */ > + dp2 = (struct efi_device_path *)&dp; > + status = boottime->locate_device_path(&lf2_proto_guid, &dp2, &handle); > + if (status != EFI_NOT_FOUND) { > + efi_st_error("Initrd protocol should't be installed\n"); > + return EFI_ST_FAILURE; > + } > + > + /* re-install with correct values now */ > + status = runtime->set_variable(L"Initrd0010", &efi_global_variable_guid, > + attrs, path_size, path); > + if (status != EFI_SUCCESS) { > + efi_st_error("SetVariable for Initrd failed\n"); > + return EFI_ST_FAILURE; > + } > + > + status = efi_initrd_register(&handle); > + if (status != EFI_SUCCESS) { > + efi_st_error("Failed to install initrd protocol\n"); > + return EFI_ST_FAILURE; > + } > > dp2 = (struct efi_device_path *)&dp; > status = boottime->locate_device_path(&lf2_proto_guid, &dp2, &handle); > @@ -211,10 +298,17 @@ static int execute(void) > return EFI_ST_SUCCESS; > } > > +static int teardown(void) > +{ > + efi_delete_handle(handle); > + return EFI_ST_SUCCESS; > +} > + > EFI_UNIT_TEST(load_initrd) = { > .name = "load initrd", > .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, > .setup = setup, > .execute = execute, > + .teardown = teardown, > .on_request = true, > }; >
diff --git a/lib/efi_selftest/efi_selftest_load_initrd.c b/lib/efi_selftest/efi_selftest_load_initrd.c index fe060a664402..1534c2ba24fa 100644 --- a/lib/efi_selftest/efi_selftest_load_initrd.c +++ b/lib/efi_selftest/efi_selftest_load_initrd.c @@ -14,10 +14,12 @@ * * CONFIG_EFI_SELFTEST=y * CONFIG_EFI_LOAD_FILE2_INITRD=y - * CONFIG_EFI_INITRD_FILESPEC="host 0:1 initrd" * - * * Run ./u-boot and execute + * * Create files + * mkdir init_test && cp initrd init_test/ + * virt-make-fs -t ext4 init_test test.img * + * * Run ./u-boot and execute * host bind 0 image * setenv efi_selftest load initrd * bootefi selftest @@ -43,6 +45,7 @@ #include <efi_load_initrd.h> static struct efi_boot_services *boottime; +static struct efi_runtime_services *runtime; static struct efi_initrd_dp dp = { .vendor = { @@ -76,10 +79,13 @@ static struct efi_initrd_dp dp_invalid = { } }; +static efi_handle_t handle; + static int setup(const efi_handle_t handle, const struct efi_system_table *systable) { boottime = systable->boottime; + runtime = systable->runtime; return EFI_ST_SUCCESS; } @@ -87,16 +93,97 @@ static int setup(const efi_handle_t handle, static int execute(void) { efi_guid_t lf2_proto_guid = EFI_LOAD_FILE2_PROTOCOL_GUID; + efi_guid_t efi_global_variable_guid = EFI_GLOBAL_VARIABLE_GUID; struct efi_load_file_protocol *lf2; struct efi_device_path *dp2, *dp2_invalid; efi_status_t status; - efi_handle_t handle; char buffer[64]; efi_uintn_t buffer_size; void *buf; u32 crc32; + u16 boot_current = 0; + efi_uintn_t boot_current_size = sizeof(boot_current); + char path[] = "host 0 initrd"; + char invalid_path[] = "host 1 initrd"; + efi_uintn_t path_size = sizeof(path); + efi_uintn_t invalid_path_size = sizeof(invalid_path); + u32 attrs = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS; memset(buffer, 0, sizeof(buffer)); + /* Set variable BootCurrent and Initrd#### to a wrong value */ + status = runtime->set_variable(L"BootCurrent", &efi_global_variable_guid, + attrs, boot_current_size, &boot_current); + if (status != EFI_SUCCESS) { + efi_st_error("SetVariable for BootCurrent failed\n"); + return EFI_ST_FAILURE; + } + + /* + * We don't need NV for Initrd here. + * Set the file to an invalid file path + */ + status = runtime->set_variable(L"Initrd0010", &efi_global_variable_guid, + attrs, invalid_path_size, invalid_path); + if (status != EFI_SUCCESS) { + efi_st_error("SetVariable for Initrd failed\n"); + return EFI_ST_FAILURE; + } + + /* We only install the protocol during efibootmgr */ + status = efi_initrd_register(&handle); + if (status != EFI_SUCCESS) { + efi_st_error("Failed to install initrd protocol\n"); + return EFI_ST_FAILURE; + } + + /* + * We should only install the protocol if the file's found + * Right now both BootCurrent and file path are invalid + */ + dp2 = (struct efi_device_path *)&dp; + status = boottime->locate_device_path(&lf2_proto_guid, &dp2, &handle); + if (status != EFI_NOT_FOUND) { + efi_st_error("Initrd protocol should't be installed\n"); + return EFI_ST_FAILURE; + } + + /* Update BootCurrent to the correct value */ + boot_current = 0x0010; + status = runtime->set_variable(L"BootCurrent", &efi_global_variable_guid, + attrs, boot_current_size, &boot_current); + if (status != EFI_SUCCESS) { + efi_st_error("SetVariable for BootCurrent failed\n"); + return EFI_ST_FAILURE; + } + + /* re-install with invalid file path */ + status = efi_initrd_register(&handle); + if (status != EFI_SUCCESS) { + efi_st_error("Failed to install initrd protocol\n"); + return EFI_ST_FAILURE; + } + + /* file path is invalid */ + dp2 = (struct efi_device_path *)&dp; + status = boottime->locate_device_path(&lf2_proto_guid, &dp2, &handle); + if (status != EFI_NOT_FOUND) { + efi_st_error("Initrd protocol should't be installed\n"); + return EFI_ST_FAILURE; + } + + /* re-install with correct values now */ + status = runtime->set_variable(L"Initrd0010", &efi_global_variable_guid, + attrs, path_size, path); + if (status != EFI_SUCCESS) { + efi_st_error("SetVariable for Initrd failed\n"); + return EFI_ST_FAILURE; + } + + status = efi_initrd_register(&handle); + if (status != EFI_SUCCESS) { + efi_st_error("Failed to install initrd protocol\n"); + return EFI_ST_FAILURE; + } dp2 = (struct efi_device_path *)&dp; status = boottime->locate_device_path(&lf2_proto_guid, &dp2, &handle); @@ -211,10 +298,17 @@ static int execute(void) return EFI_ST_SUCCESS; } +static int teardown(void) +{ + efi_delete_handle(handle); + return EFI_ST_SUCCESS; +} + EFI_UNIT_TEST(load_initrd) = { .name = "load initrd", .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, .setup = setup, .execute = execute, + .teardown = teardown, .on_request = true, };
We changed the logic of the initrd discovery and the installation of the protocol in the previous patch. Instead of a config now option it now resides in an EFI variable. Adjust the existing tests accordingly and add self-tests which will cover the new features. Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org> --- lib/efi_selftest/efi_selftest_load_initrd.c | 100 +++++++++++++++++++- 1 file changed, 97 insertions(+), 3 deletions(-) -- 2.30.0