[PATCH 0/2] efi_loader: make the UEFI boot manager configurable

Some boards are very tight on the binary size. Booting via UEFI is possible without using the boot manager.
Provide a configuration option to make the boot manager available.
Heinrich Schuchardt (2): efi_loader: move load options to new module efi_loader: make the UEFI boot manager configurable
cmd/bootefi.c | 13 ++- cmd/efidebug.c | 8 +- lib/efi_loader/Kconfig | 8 ++ lib/efi_loader/Makefile | 3 +- lib/efi_loader/efi_bootmgr.c | 135 -------------------------- lib/efi_loader/efi_load_options.c | 151 ++++++++++++++++++++++++++++++ 6 files changed, 176 insertions(+), 142 deletions(-) create mode 100644 lib/efi_loader/efi_load_options.c
-- 2.29.2

Move all load options related functions to a new module. So that they can be compiled independently.
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de --- lib/efi_loader/efi_load_options.c | 151 ++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 lib/efi_loader/efi_load_options.c
diff --git a/lib/efi_loader/efi_load_options.c b/lib/efi_loader/efi_load_options.c new file mode 100644 index 0000000000..9f0e25b6e9 --- /dev/null +++ b/lib/efi_loader/efi_load_options.c @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * EFI boot manager + * + * Copyright (c) 2017 Rob Clark + */ + +#define LOG_CATEGORY LOGC_EFI + +#include <common.h> +#include <charset.h> +#include <log.h> +#include <malloc.h> +#include <efi_loader.h> +//#include <efi_variable.h> +#include <asm/unaligned.h> + +/** + * efi_set_load_options() - set the load options of a loaded image + * + * @handle: the image handle + * @load_options_size: size of load options + * @load_options: pointer to load options + * Return: status code + */ +efi_status_t efi_set_load_options(efi_handle_t handle, + efi_uintn_t load_options_size, + void *load_options) +{ + struct efi_loaded_image *loaded_image_info; + efi_status_t ret; + + ret = EFI_CALL(systab.boottime->open_protocol( + handle, + &efi_guid_loaded_image, + (void **)&loaded_image_info, + efi_root, NULL, + EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL)); + if (ret != EFI_SUCCESS) + return EFI_INVALID_PARAMETER; + + loaded_image_info->load_options = load_options; + loaded_image_info->load_options_size = load_options_size; + + return EFI_CALL(systab.boottime->close_protocol(handle, + &efi_guid_loaded_image, + efi_root, NULL)); +} + +/** + * efi_deserialize_load_option() - parse serialized data + * + * Parse serialized data describing a load option and transform it to the + * efi_load_option structure. + * + * @lo: pointer to target + * @data: serialized data + * @size: size of the load option, on return size of the optional data + * Return: status code + */ +efi_status_t efi_deserialize_load_option(struct efi_load_option *lo, u8 *data, + efi_uintn_t *size) +{ + efi_uintn_t len; + + len = sizeof(u32); + if (*size < len + 2 * sizeof(u16)) + return EFI_INVALID_PARAMETER; + lo->attributes = get_unaligned_le32(data); + data += len; + *size -= len; + + len = sizeof(u16); + lo->file_path_length = get_unaligned_le16(data); + data += len; + *size -= len; + + lo->label = (u16 *)data; + len = u16_strnlen(lo->label, *size / sizeof(u16) - 1); + if (lo->label[len]) + return EFI_INVALID_PARAMETER; + len = (len + 1) * sizeof(u16); + if (*size < len) + return EFI_INVALID_PARAMETER; + data += len; + *size -= len; + + len = lo->file_path_length; + if (*size < len) + return EFI_INVALID_PARAMETER; + lo->file_path = (struct efi_device_path *)data; + if (efi_dp_check_length(lo->file_path, len) < 0) + return EFI_INVALID_PARAMETER; + data += len; + *size -= len; + + lo->optional_data = data; + + return EFI_SUCCESS; +} + +/** + * efi_serialize_load_option() - serialize load option + * + * Serialize efi_load_option structure into byte stream for BootXXXX. + * + * @data: buffer for serialized data + * @lo: load option + * Return: size of allocated buffer + */ +unsigned long efi_serialize_load_option(struct efi_load_option *lo, u8 **data) +{ + unsigned long label_len; + unsigned long size; + u8 *p; + + label_len = (u16_strlen(lo->label) + 1) * sizeof(u16); + + /* total size */ + size = sizeof(lo->attributes); + size += sizeof(lo->file_path_length); + size += label_len; + size += lo->file_path_length; + if (lo->optional_data) + size += (utf8_utf16_strlen((const char *)lo->optional_data) + + 1) * sizeof(u16); + p = malloc(size); + if (!p) + return 0; + + /* copy data */ + *data = p; + memcpy(p, &lo->attributes, sizeof(lo->attributes)); + p += sizeof(lo->attributes); + + memcpy(p, &lo->file_path_length, sizeof(lo->file_path_length)); + p += sizeof(lo->file_path_length); + + memcpy(p, lo->label, label_len); + p += label_len; + + memcpy(p, lo->file_path, lo->file_path_length); + p += lo->file_path_length; + + if (lo->optional_data) { + utf8_utf16_strcpy((u16 **)&p, (const char *)lo->optional_data); + p += sizeof(u16); /* size of trailing \0 */ + } + return size; +} + -- 2.29.2

On Fri, Jan 15, 2021 at 07:02:49PM +0100, Heinrich Schuchardt wrote:
Move all load options related functions to a new module. So that they can be compiled independently.
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de
lib/efi_loader/efi_load_options.c | 151 ++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 lib/efi_loader/efi_load_options.c
diff --git a/lib/efi_loader/efi_load_options.c b/lib/efi_loader/efi_load_options.c new file mode 100644 index 0000000000..9f0e25b6e9 --- /dev/null +++ b/lib/efi_loader/efi_load_options.c @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- EFI boot manager
- Copyright (c) 2017 Rob Clark
Some part of the code in this file was originally written by me.
-Takahiro Akashi
- */
+#define LOG_CATEGORY LOGC_EFI
+#include <common.h> +#include <charset.h> +#include <log.h> +#include <malloc.h> +#include <efi_loader.h> +//#include <efi_variable.h> +#include <asm/unaligned.h>
+/**
- efi_set_load_options() - set the load options of a loaded image
- @handle: the image handle
- @load_options_size: size of load options
- @load_options: pointer to load options
- Return: status code
- */
+efi_status_t efi_set_load_options(efi_handle_t handle,
efi_uintn_t load_options_size,
void *load_options)
+{
- struct efi_loaded_image *loaded_image_info;
- efi_status_t ret;
- ret = EFI_CALL(systab.boottime->open_protocol(
handle,
&efi_guid_loaded_image,
(void **)&loaded_image_info,
efi_root, NULL,
EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL));
- if (ret != EFI_SUCCESS)
return EFI_INVALID_PARAMETER;
- loaded_image_info->load_options = load_options;
- loaded_image_info->load_options_size = load_options_size;
- return EFI_CALL(systab.boottime->close_protocol(handle,
&efi_guid_loaded_image,
efi_root, NULL));
+}
+/**
- efi_deserialize_load_option() - parse serialized data
- Parse serialized data describing a load option and transform it to the
- efi_load_option structure.
- @lo: pointer to target
- @data: serialized data
- @size: size of the load option, on return size of the optional data
- Return: status code
- */
+efi_status_t efi_deserialize_load_option(struct efi_load_option *lo, u8 *data,
efi_uintn_t *size)
+{
- efi_uintn_t len;
- len = sizeof(u32);
- if (*size < len + 2 * sizeof(u16))
return EFI_INVALID_PARAMETER;
- lo->attributes = get_unaligned_le32(data);
- data += len;
- *size -= len;
- len = sizeof(u16);
- lo->file_path_length = get_unaligned_le16(data);
- data += len;
- *size -= len;
- lo->label = (u16 *)data;
- len = u16_strnlen(lo->label, *size / sizeof(u16) - 1);
- if (lo->label[len])
return EFI_INVALID_PARAMETER;
- len = (len + 1) * sizeof(u16);
- if (*size < len)
return EFI_INVALID_PARAMETER;
- data += len;
- *size -= len;
- len = lo->file_path_length;
- if (*size < len)
return EFI_INVALID_PARAMETER;
- lo->file_path = (struct efi_device_path *)data;
- if (efi_dp_check_length(lo->file_path, len) < 0)
return EFI_INVALID_PARAMETER;
- data += len;
- *size -= len;
- lo->optional_data = data;
- return EFI_SUCCESS;
+}
+/**
- efi_serialize_load_option() - serialize load option
- Serialize efi_load_option structure into byte stream for BootXXXX.
- @data: buffer for serialized data
- @lo: load option
- Return: size of allocated buffer
- */
+unsigned long efi_serialize_load_option(struct efi_load_option *lo, u8 **data) +{
- unsigned long label_len;
- unsigned long size;
- u8 *p;
- label_len = (u16_strlen(lo->label) + 1) * sizeof(u16);
- /* total size */
- size = sizeof(lo->attributes);
- size += sizeof(lo->file_path_length);
- size += label_len;
- size += lo->file_path_length;
- if (lo->optional_data)
size += (utf8_utf16_strlen((const char *)lo->optional_data)
+ 1) * sizeof(u16);
- p = malloc(size);
- if (!p)
return 0;
- /* copy data */
- *data = p;
- memcpy(p, &lo->attributes, sizeof(lo->attributes));
- p += sizeof(lo->attributes);
- memcpy(p, &lo->file_path_length, sizeof(lo->file_path_length));
- p += sizeof(lo->file_path_length);
- memcpy(p, lo->label, label_len);
- p += label_len;
- memcpy(p, lo->file_path, lo->file_path_length);
- p += lo->file_path_length;
- if (lo->optional_data) {
utf8_utf16_strcpy((u16 **)&p, (const char *)lo->optional_data);
p += sizeof(u16); /* size of trailing \0 */
- }
- return size;
+}
-- 2.29.2

On 1/18/21 3:17 AM, AKASHI Takahiro wrote:
On Fri, Jan 15, 2021 at 07:02:49PM +0100, Heinrich Schuchardt wrote:
Move all load options related functions to a new module. So that they can be compiled independently.
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de
lib/efi_loader/efi_load_options.c | 151 ++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 lib/efi_loader/efi_load_options.c
diff --git a/lib/efi_loader/efi_load_options.c b/lib/efi_loader/efi_load_options.c new file mode 100644 index 0000000000..9f0e25b6e9 --- /dev/null +++ b/lib/efi_loader/efi_load_options.c @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- EFI boot manager
- Copyright (c) 2017 Rob Clark
Some part of the code in this file was originally written by me.
I will add your name. Other projects simply say don't put names into the text because their will be further contributors anyways.
Best regards
Heinrich
-Takahiro Akashi
- */
+#define LOG_CATEGORY LOGC_EFI
+#include <common.h> +#include <charset.h> +#include <log.h> +#include <malloc.h> +#include <efi_loader.h> +//#include <efi_variable.h> +#include <asm/unaligned.h>
+/**
- efi_set_load_options() - set the load options of a loaded image
- @handle: the image handle
- @load_options_size: size of load options
- @load_options: pointer to load options
- Return: status code
- */
+efi_status_t efi_set_load_options(efi_handle_t handle,
efi_uintn_t load_options_size,
void *load_options)
+{
- struct efi_loaded_image *loaded_image_info;
- efi_status_t ret;
- ret = EFI_CALL(systab.boottime->open_protocol(
handle,
&efi_guid_loaded_image,
(void **)&loaded_image_info,
efi_root, NULL,
EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL));
- if (ret != EFI_SUCCESS)
return EFI_INVALID_PARAMETER;
- loaded_image_info->load_options = load_options;
- loaded_image_info->load_options_size = load_options_size;
- return EFI_CALL(systab.boottime->close_protocol(handle,
&efi_guid_loaded_image,
efi_root, NULL));
+}
+/**
- efi_deserialize_load_option() - parse serialized data
- Parse serialized data describing a load option and transform it to the
- efi_load_option structure.
- @lo: pointer to target
- @data: serialized data
- @size: size of the load option, on return size of the optional data
- Return: status code
- */
+efi_status_t efi_deserialize_load_option(struct efi_load_option *lo, u8 *data,
efi_uintn_t *size)
+{
- efi_uintn_t len;
- len = sizeof(u32);
- if (*size < len + 2 * sizeof(u16))
return EFI_INVALID_PARAMETER;
- lo->attributes = get_unaligned_le32(data);
- data += len;
- *size -= len;
- len = sizeof(u16);
- lo->file_path_length = get_unaligned_le16(data);
- data += len;
- *size -= len;
- lo->label = (u16 *)data;
- len = u16_strnlen(lo->label, *size / sizeof(u16) - 1);
- if (lo->label[len])
return EFI_INVALID_PARAMETER;
- len = (len + 1) * sizeof(u16);
- if (*size < len)
return EFI_INVALID_PARAMETER;
- data += len;
- *size -= len;
- len = lo->file_path_length;
- if (*size < len)
return EFI_INVALID_PARAMETER;
- lo->file_path = (struct efi_device_path *)data;
- if (efi_dp_check_length(lo->file_path, len) < 0)
return EFI_INVALID_PARAMETER;
- data += len;
- *size -= len;
- lo->optional_data = data;
- return EFI_SUCCESS;
+}
+/**
- efi_serialize_load_option() - serialize load option
- Serialize efi_load_option structure into byte stream for BootXXXX.
- @data: buffer for serialized data
- @lo: load option
- Return: size of allocated buffer
- */
+unsigned long efi_serialize_load_option(struct efi_load_option *lo, u8 **data) +{
- unsigned long label_len;
- unsigned long size;
- u8 *p;
- label_len = (u16_strlen(lo->label) + 1) * sizeof(u16);
- /* total size */
- size = sizeof(lo->attributes);
- size += sizeof(lo->file_path_length);
- size += label_len;
- size += lo->file_path_length;
- if (lo->optional_data)
size += (utf8_utf16_strlen((const char *)lo->optional_data)
+ 1) * sizeof(u16);
- p = malloc(size);
- if (!p)
return 0;
- /* copy data */
- *data = p;
- memcpy(p, &lo->attributes, sizeof(lo->attributes));
- p += sizeof(lo->attributes);
- memcpy(p, &lo->file_path_length, sizeof(lo->file_path_length));
- p += sizeof(lo->file_path_length);
- memcpy(p, lo->label, label_len);
- p += label_len;
- memcpy(p, lo->file_path, lo->file_path_length);
- p += lo->file_path_length;
- if (lo->optional_data) {
utf8_utf16_strcpy((u16 **)&p, (const char *)lo->optional_data);
p += sizeof(u16); /* size of trailing \0 */
- }
- return size;
+}
-- 2.29.2

Hi Heinrich,
Overall the patch and idea seem fine. Would it make sense to name the file differently? Something similar to what I did on my initrd patches, i.e efi_helper.c, so we can start adding helper functions that have a wider usage?
Thanks /Ilias
On Fri, Jan 15, 2021 at 07:02:49PM +0100, Heinrich Schuchardt wrote:
Move all load options related functions to a new module. So that they can be compiled independently.
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de
lib/efi_loader/efi_load_options.c | 151 ++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 lib/efi_loader/efi_load_options.c
diff --git a/lib/efi_loader/efi_load_options.c b/lib/efi_loader/efi_load_options.c new file mode 100644 index 0000000000..9f0e25b6e9 --- /dev/null +++ b/lib/efi_loader/efi_load_options.c @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- EFI boot manager
- Copyright (c) 2017 Rob Clark
- */
+#define LOG_CATEGORY LOGC_EFI
+#include <common.h> +#include <charset.h> +#include <log.h> +#include <malloc.h> +#include <efi_loader.h> +//#include <efi_variable.h> +#include <asm/unaligned.h>
+/**
- efi_set_load_options() - set the load options of a loaded image
- @handle: the image handle
- @load_options_size: size of load options
- @load_options: pointer to load options
- Return: status code
- */
+efi_status_t efi_set_load_options(efi_handle_t handle,
efi_uintn_t load_options_size,
void *load_options)
+{
- struct efi_loaded_image *loaded_image_info;
- efi_status_t ret;
- ret = EFI_CALL(systab.boottime->open_protocol(
handle,
&efi_guid_loaded_image,
(void **)&loaded_image_info,
efi_root, NULL,
EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL));
- if (ret != EFI_SUCCESS)
return EFI_INVALID_PARAMETER;
- loaded_image_info->load_options = load_options;
- loaded_image_info->load_options_size = load_options_size;
- return EFI_CALL(systab.boottime->close_protocol(handle,
&efi_guid_loaded_image,
efi_root, NULL));
+}
+/**
- efi_deserialize_load_option() - parse serialized data
- Parse serialized data describing a load option and transform it to the
- efi_load_option structure.
- @lo: pointer to target
- @data: serialized data
- @size: size of the load option, on return size of the optional data
- Return: status code
- */
+efi_status_t efi_deserialize_load_option(struct efi_load_option *lo, u8 *data,
efi_uintn_t *size)
+{
- efi_uintn_t len;
- len = sizeof(u32);
- if (*size < len + 2 * sizeof(u16))
return EFI_INVALID_PARAMETER;
- lo->attributes = get_unaligned_le32(data);
- data += len;
- *size -= len;
- len = sizeof(u16);
- lo->file_path_length = get_unaligned_le16(data);
- data += len;
- *size -= len;
- lo->label = (u16 *)data;
- len = u16_strnlen(lo->label, *size / sizeof(u16) - 1);
- if (lo->label[len])
return EFI_INVALID_PARAMETER;
- len = (len + 1) * sizeof(u16);
- if (*size < len)
return EFI_INVALID_PARAMETER;
- data += len;
- *size -= len;
- len = lo->file_path_length;
- if (*size < len)
return EFI_INVALID_PARAMETER;
- lo->file_path = (struct efi_device_path *)data;
- if (efi_dp_check_length(lo->file_path, len) < 0)
return EFI_INVALID_PARAMETER;
- data += len;
- *size -= len;
- lo->optional_data = data;
- return EFI_SUCCESS;
+}
+/**
- efi_serialize_load_option() - serialize load option
- Serialize efi_load_option structure into byte stream for BootXXXX.
- @data: buffer for serialized data
- @lo: load option
- Return: size of allocated buffer
- */
+unsigned long efi_serialize_load_option(struct efi_load_option *lo, u8 **data) +{
- unsigned long label_len;
- unsigned long size;
- u8 *p;
- label_len = (u16_strlen(lo->label) + 1) * sizeof(u16);
- /* total size */
- size = sizeof(lo->attributes);
- size += sizeof(lo->file_path_length);
- size += label_len;
- size += lo->file_path_length;
- if (lo->optional_data)
size += (utf8_utf16_strlen((const char *)lo->optional_data)
+ 1) * sizeof(u16);
- p = malloc(size);
- if (!p)
return 0;
- /* copy data */
- *data = p;
- memcpy(p, &lo->attributes, sizeof(lo->attributes));
- p += sizeof(lo->attributes);
- memcpy(p, &lo->file_path_length, sizeof(lo->file_path_length));
- p += sizeof(lo->file_path_length);
- memcpy(p, lo->label, label_len);
- p += label_len;
- memcpy(p, lo->file_path, lo->file_path_length);
- p += lo->file_path_length;
- if (lo->optional_data) {
utf8_utf16_strcpy((u16 **)&p, (const char *)lo->optional_data);
p += sizeof(u16); /* size of trailing \0 */
- }
- return size;
+}
-- 2.29.2

On 19.01.21 08:42, Ilias Apalodimas wrote:
Hi Heinrich,
Overall the patch and idea seem fine. Would it make sense to name the file differently? Something similar to what I did on my initrd patches, i.e efi_helper.c, so we can start adding helper functions that have a wider usage?
efi_helper.c as a name does not convey which functions to find there.
Concerning your initrd patch series:
efi_get_var() would fit into efi_var_common.c. efi_dp_instance_by_idx() would fit into efi_device_path.c. create_boot_var_indexed() seems to duplicate efi_create_indexed_name() which is in efi_string.c. Leaves us only with efi_get_fp_from_boot() which is only relevant for the boot manager.
Best regards
Heinrich
Thanks /Ilias
On Fri, Jan 15, 2021 at 07:02:49PM +0100, Heinrich Schuchardt wrote:
Move all load options related functions to a new module. So that they can be compiled independently.
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de
lib/efi_loader/efi_load_options.c | 151 ++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 lib/efi_loader/efi_load_options.c

Some boards are very tight on the binary size. Booting via UEFI is possible without using the boot manager.
Provide a configuration option to make the boot manager available.
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de --- cmd/bootefi.c | 13 ++-- cmd/efidebug.c | 8 ++- lib/efi_loader/Kconfig | 8 +++ lib/efi_loader/Makefile | 3 +- lib/efi_loader/efi_bootmgr.c | 135 ----------------------------------- 5 files changed, 25 insertions(+), 142 deletions(-)
diff --git a/cmd/bootefi.c b/cmd/bootefi.c index fe70eec625..c8eb5c32b0 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -631,10 +631,12 @@ static int do_bootefi(struct cmd_tbl *cmdtp, int flag, int argc, else if (ret != EFI_SUCCESS) return CMD_RET_FAILURE;
- if (!strcmp(argv[1], "bootmgr")) - return do_efibootmgr(); + if (IS_ENABLED(CONFIG_CMD_BOOTEFI_BOOTMGR)) { + if (!strcmp(argv[1], "bootmgr")) + return do_efibootmgr(); + } #ifdef CONFIG_CMD_BOOTEFI_SELFTEST - else if (!strcmp(argv[1], "selftest")) + if (!strcmp(argv[1], "selftest")) return do_efi_selftest(); #endif
@@ -657,11 +659,14 @@ static char bootefi_help_text[] = " Use environment variable efi_selftest to select a single test.\n" " Use 'setenv efi_selftest list' to enumerate all tests.\n" #endif +#ifdef CONFIG_CMD_BOOTEFI_BOOTMGR "bootefi bootmgr [fdt address]\n" " - load and boot EFI payload based on BootOrder/BootXXXX variables.\n" "\n" " If specified, the device tree located at <fdt address> gets\n" - " exposed as EFI configuration table.\n"; + " exposed as EFI configuration table.\n" +#endif + ; #endif
U_BOOT_CMD( diff --git a/cmd/efidebug.c b/cmd/efidebug.c index 6de81cab00..9a2d4ddd5e 100644 --- a/cmd/efidebug.c +++ b/cmd/efidebug.c @@ -1367,8 +1367,8 @@ static int do_efi_boot_opt(struct cmd_tbl *cmdtp, int flag, * * efidebug test bootmgr */ -static int do_efi_test_bootmgr(struct cmd_tbl *cmdtp, int flag, - int argc, char * const argv[]) +static __maybe_unused int do_efi_test_bootmgr(struct cmd_tbl *cmdtp, int flag, + int argc, char * const argv[]) { efi_handle_t image; efi_uintn_t exit_data_size = 0; @@ -1392,8 +1392,10 @@ static int do_efi_test_bootmgr(struct cmd_tbl *cmdtp, int flag, }
static struct cmd_tbl cmd_efidebug_test_sub[] = { +#ifdef CONFIG_CMD_BOOTEFI_BOOTMGR U_BOOT_CMD_MKENT(bootmgr, CONFIG_SYS_MAXARGS, 1, do_efi_test_bootmgr, "", ""), +#endif };
/** @@ -1581,8 +1583,10 @@ static char efidebug_help_text[] = " - show UEFI memory map\n" "efidebug tables\n" " - show UEFI configuration tables\n" +#ifdef CONFIG_CMD_BOOTEFI_BOOTMGR "efidebug test bootmgr\n" " - run simple bootmgr for test\n" +#endif "efidebug query [-nv][-bs][-rt][-at]\n" " - show size of UEFI variables store\n"; #endif diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index fdf245dea3..106f789b4d 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -27,6 +27,14 @@ config EFI_LOADER
if EFI_LOADER
+config CMD_BOOTEFI_BOOTMGR + bool "UEFI Boot Manager" + default y + help + Select this option if you want to select the UEFI binary to be booted + via UEFI variables Boot####, BootOrder, and BootNext. This enables the + 'bootefi bootmgr' command. + config EFI_SETUP_EARLY bool default n diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index 412fa88245..a6355d240a 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -21,7 +21,7 @@ targets += helloworld.o endif
obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o -obj-y += efi_bootmgr.o +obj-$(CONFIG_CMD_BOOTEFI_BOOTMGR) += efi_bootmgr.o obj-y += efi_boottime.o obj-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += efi_capsule.o obj-$(CONFIG_EFI_CAPSULE_FIRMWARE) += efi_firmware.o @@ -35,6 +35,7 @@ endif obj-y += efi_file.o obj-$(CONFIG_EFI_LOADER_HII) += efi_hii.o obj-y += efi_image_loader.o +obj-y += efi_load_options.o obj-y += efi_memory.o obj-y += efi_root_node.o obj-y += efi_runtime.o diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c index d3be2f94c6..25f5cebfdb 100644 --- a/lib/efi_loader/efi_bootmgr.c +++ b/lib/efi_loader/efi_bootmgr.c @@ -30,141 +30,6 @@ static const struct efi_runtime_services *rs; * should do normal or recovery boot. */
-/** - * efi_set_load_options() - set the load options of a loaded image - * - * @handle: the image handle - * @load_options_size: size of load options - * @load_options: pointer to load options - * Return: status code - */ -efi_status_t efi_set_load_options(efi_handle_t handle, - efi_uintn_t load_options_size, - void *load_options) -{ - struct efi_loaded_image *loaded_image_info; - efi_status_t ret; - - ret = EFI_CALL(systab.boottime->open_protocol( - handle, - &efi_guid_loaded_image, - (void **)&loaded_image_info, - efi_root, NULL, - EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL)); - if (ret != EFI_SUCCESS) - return EFI_INVALID_PARAMETER; - - loaded_image_info->load_options = load_options; - loaded_image_info->load_options_size = load_options_size; - - return EFI_CALL(systab.boottime->close_protocol(handle, - &efi_guid_loaded_image, - efi_root, NULL)); -} - - -/** - * efi_deserialize_load_option() - parse serialized data - * - * Parse serialized data describing a load option and transform it to the - * efi_load_option structure. - * - * @lo: pointer to target - * @data: serialized data - * @size: size of the load option, on return size of the optional data - * Return: status code - */ -efi_status_t efi_deserialize_load_option(struct efi_load_option *lo, u8 *data, - efi_uintn_t *size) -{ - efi_uintn_t len; - - len = sizeof(u32); - if (*size < len + 2 * sizeof(u16)) - return EFI_INVALID_PARAMETER; - lo->attributes = get_unaligned_le32(data); - data += len; - *size -= len; - - len = sizeof(u16); - lo->file_path_length = get_unaligned_le16(data); - data += len; - *size -= len; - - lo->label = (u16 *)data; - len = u16_strnlen(lo->label, *size / sizeof(u16) - 1); - if (lo->label[len]) - return EFI_INVALID_PARAMETER; - len = (len + 1) * sizeof(u16); - if (*size < len) - return EFI_INVALID_PARAMETER; - data += len; - *size -= len; - - len = lo->file_path_length; - if (*size < len) - return EFI_INVALID_PARAMETER; - lo->file_path = (struct efi_device_path *)data; - if (efi_dp_check_length(lo->file_path, len) < 0) - return EFI_INVALID_PARAMETER; - data += len; - *size -= len; - - lo->optional_data = data; - - return EFI_SUCCESS; -} - -/** - * efi_serialize_load_option() - serialize load option - * - * Serialize efi_load_option structure into byte stream for BootXXXX. - * - * @data: buffer for serialized data - * @lo: load option - * Return: size of allocated buffer - */ -unsigned long efi_serialize_load_option(struct efi_load_option *lo, u8 **data) -{ - unsigned long label_len; - unsigned long size; - u8 *p; - - label_len = (u16_strlen(lo->label) + 1) * sizeof(u16); - - /* total size */ - size = sizeof(lo->attributes); - size += sizeof(lo->file_path_length); - size += label_len; - size += lo->file_path_length; - if (lo->optional_data) - size += (utf8_utf16_strlen((const char *)lo->optional_data) - + 1) * sizeof(u16); - p = malloc(size); - if (!p) - return 0; - - /* copy data */ - *data = p; - memcpy(p, &lo->attributes, sizeof(lo->attributes)); - p += sizeof(lo->attributes); - - memcpy(p, &lo->file_path_length, sizeof(lo->file_path_length)); - p += sizeof(lo->file_path_length); - - memcpy(p, lo->label, label_len); - p += label_len; - - memcpy(p, lo->file_path, lo->file_path_length); - p += lo->file_path_length; - - if (lo->optional_data) { - utf8_utf16_strcpy((u16 **)&p, (const char *)lo->optional_data); - p += sizeof(u16); /* size of trailing \0 */ - } - return size; -} - /** * get_var() - get UEFI variable * -- 2.29.2

On Fri, Jan 15, 2021 at 07:02:50PM +0100, Heinrich Schuchardt wrote:
Some boards are very tight on the binary size. Booting via UEFI is possible without using the boot manager.
While I don't think we need to re-word this part, for the record my concern is global, not specific platforms. To re-iterate something we talked about on IRC, I think it's important to be able to select and have a default UEFI implementation that covers as many common use cases as possible, while also being as small as possible.
Provide a configuration option to make the boot manager available.
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de
[snip]
+config CMD_BOOTEFI_BOOTMGR
- bool "UEFI Boot Manager"
- default y
- help
Select this option if you want to select the UEFI binary to be booted
via UEFI variables Boot####, BootOrder, and BootNext. This enables the
'bootefi bootmgr' command.
I'm not sure this should be default y. My concern is that the default set of options is growing so that every possible case has support in the binary but the hardware and practical use means we don't need all of that. This should perhaps be "default y if DISTRO_DEFAULTS" at least.

On 1/15/21 7:43 PM, Tom Rini wrote:
On Fri, Jan 15, 2021 at 07:02:50PM +0100, Heinrich Schuchardt wrote:
Some boards are very tight on the binary size. Booting via UEFI is possible without using the boot manager.
While I don't think we need to re-word this part, for the record my concern is global, not specific platforms. To re-iterate something we talked about on IRC, I think it's important to be able to select and have a default UEFI implementation that covers as many common use cases as possible, while also being as small as possible.
Provide a configuration option to make the boot manager available.
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de
[snip]
+config CMD_BOOTEFI_BOOTMGR
- bool "UEFI Boot Manager"
- default y
- help
Select this option if you want to select the UEFI binary to be booted
via UEFI variables Boot####, BootOrder, and BootNext. This enables the
'bootefi bootmgr' command.
I'm not sure this should be default y. My concern is that the default set of options is growing so that every possible case has support in the binary but the hardware and practical use means we don't need all of that. This should perhaps be "default y if DISTRO_DEFAULTS" at least.
If you want to default something to no, I think that EFI_UNICODE_CAPITALIZATION is a better candidate.
On wandboard_defconfig:
683976 - 680228 = 3748 bytes saved.
Best regards
Heinrich

On Fri, Jan 15, 2021 at 09:31:19PM +0100, Heinrich Schuchardt wrote:
On 1/15/21 7:43 PM, Tom Rini wrote:
On Fri, Jan 15, 2021 at 07:02:50PM +0100, Heinrich Schuchardt wrote:
Some boards are very tight on the binary size. Booting via UEFI is possible without using the boot manager.
While I don't think we need to re-word this part, for the record my concern is global, not specific platforms. To re-iterate something we talked about on IRC, I think it's important to be able to select and have a default UEFI implementation that covers as many common use cases as possible, while also being as small as possible.
Provide a configuration option to make the boot manager available.
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de
[snip]
+config CMD_BOOTEFI_BOOTMGR
- bool "UEFI Boot Manager"
- default y
- help
Select this option if you want to select the UEFI binary to be booted
via UEFI variables Boot####, BootOrder, and BootNext. This enables the
'bootefi bootmgr' command.
I'm not sure this should be default y. My concern is that the default set of options is growing so that every possible case has support in the binary but the hardware and practical use means we don't need all of that. This should perhaps be "default y if DISTRO_DEFAULTS" at least.
If you want to default something to no, I think that EFI_UNICODE_CAPITALIZATION is a better candidate.
On wandboard_defconfig:
683976 - 680228 = 3748 bytes saved.
OK, thanks. Can you make up a patch with sufficient explanation of why it's OK to not support this by default?

Heinrich,
On Fri, Jan 15, 2021 at 07:02:48PM +0100, Heinrich Schuchardt wrote:
Some boards are very tight on the binary size. Booting via UEFI is possible without using the boot manager.
Provide a configuration option to make the boot manager available.
Heinrich Schuchardt (2): efi_loader: move load options to new module efi_loader: make the UEFI boot manager configurable
cmd/bootefi.c | 13 ++- cmd/efidebug.c | 8 +- lib/efi_loader/Kconfig | 8 ++ lib/efi_loader/Makefile | 3 +- lib/efi_loader/efi_bootmgr.c | 135 --------------------------
"efidebug" command also has some related code in that "BootXXXX" variables are handled solely by boot manager. You can opt it out for the sake of consistency.
-Takahiro Akashi
lib/efi_loader/efi_load_options.c | 151 ++++++++++++++++++++++++++++++ 6 files changed, 176 insertions(+), 142 deletions(-) create mode 100644 lib/efi_loader/efi_load_options.c
-- 2.29.2

On 18.01.21 03:33, AKASHI Takahiro wrote:
Heinrich,
On Fri, Jan 15, 2021 at 07:02:48PM +0100, Heinrich Schuchardt wrote:
Some boards are very tight on the binary size. Booting via UEFI is possible without using the boot manager.
Provide a configuration option to make the boot manager available.
Heinrich Schuchardt (2): efi_loader: move load options to new module efi_loader: make the UEFI boot manager configurable
cmd/bootefi.c | 13 ++- cmd/efidebug.c | 8 +- lib/efi_loader/Kconfig | 8 ++ lib/efi_loader/Makefile | 3 +- lib/efi_loader/efi_bootmgr.c | 135 --------------------------
"efidebug" command also has some related code in that "BootXXXX" variables are handled solely by boot manager. You can opt it out for the sake of consistency.
As we discussed with Ilias that part will be split off into a separate command anyway. So this will be done in a later patch.
Best regards
Heinrich
-Takahiro Akashi
lib/efi_loader/efi_load_options.c | 151 ++++++++++++++++++++++++++++++ 6 files changed, 176 insertions(+), 142 deletions(-) create mode 100644 lib/efi_loader/efi_load_options.c
-- 2.29.2
participants (4)
-
AKASHI Takahiro
-
Heinrich Schuchardt
-
Ilias Apalodimas
-
Tom Rini