summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2021-03-25 22:45:43 -0400
committerTom Rini <trini@konsulko.com>2021-03-25 22:45:43 -0400
commit4be994b0e1f006c271e0791a60b6363137542090 (patch)
tree4a880a9274c31963b1a330520c5dd99916164db7
parent874dcedee92a828b03c8d3146dccfaa8b709618b (diff)
parentac30aad21076e9eeb460af2865b863f3ae3d2eaa (diff)
downloadu-boot-WIP/25Mar2021-next.tar.gz
Merge tag 'efi-next' of https://source.denx.de/u-boot/custodians/u-boot-efi into nextWIP/25Mar2021-next
Pull request for efi-next New: provide EFI ESRT table initrd via Load_File2_Protocol uses boot options create an S-CRTM event for measured boot Bug fixes: avoid double free of SPI device in dfu_free_entity() avoid memory leak in TCG2 protocol
-rw-r--r--cmd/bootefi.c3
-rw-r--r--cmd/efidebug.c281
-rw-r--r--cmd/load.c10
-rw-r--r--doc/board/emulation/qemu_capsule_update.rst4
-rw-r--r--doc/uefi/uefi.rst2
-rw-r--r--drivers/dfu/dfu_sf.c18
-rw-r--r--include/efi_api.h31
-rw-r--r--include/efi_loader.h36
-rw-r--r--include/efi_selftest.h7
-rw-r--r--lib/efi_loader/Kconfig26
-rw-r--r--lib/efi_loader/Makefile2
-rw-r--r--lib/efi_loader/efi_bootmgr.c19
-rw-r--r--lib/efi_loader/efi_boottime.c23
-rw-r--r--lib/efi_loader/efi_capsule.c12
-rw-r--r--lib/efi_loader/efi_console.c51
-rw-r--r--lib/efi_loader/efi_device_path.c151
-rw-r--r--lib/efi_loader/efi_device_path_to_text.c13
-rw-r--r--lib/efi_loader/efi_dt_fixup.c2
-rw-r--r--lib/efi_loader/efi_esrt.c510
-rw-r--r--lib/efi_loader/efi_file.c39
-rw-r--r--lib/efi_loader/efi_firmware.c4
-rw-r--r--lib/efi_loader/efi_helper.c98
-rw-r--r--lib/efi_loader/efi_load_initrd.c202
-rw-r--r--lib/efi_loader/efi_setup.c6
-rw-r--r--lib/efi_loader/efi_tcg2.c75
-rw-r--r--lib/efi_loader/efi_var_common.c33
-rw-r--r--lib/efi_selftest/Makefile3
-rw-r--r--lib/efi_selftest/efi_selftest.c11
-rw-r--r--lib/efi_selftest/efi_selftest_esrt.c291
-rw-r--r--lib/efi_selftest/efi_selftest_load_initrd.c221
-rw-r--r--lib/efi_selftest/efi_selftest_set_virtual_address_map.c2
-rw-r--r--lib/efi_selftest/initrddump.c2
-rw-r--r--test/py/tests/test_efi_capsule/test_capsule_firmware.py14
-rw-r--r--test/py/tests/test_efi_secboot/test_signed.py16
-rw-r--r--test/py/tests/test_efi_secboot/test_signed_intca.py8
-rw-r--r--test/py/tests/test_efi_secboot/test_unsigned.py8
36 files changed, 1781 insertions, 453 deletions
diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index 271b385ede..cba81ffe75 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -358,6 +358,9 @@ static efi_status_t do_bootefi_exec(efi_handle_t handle, void *load_options)
free(load_options);
+ if (IS_ENABLED(CONFIG_EFI_LOAD_FILE2_INITRD))
+ efi_initrd_deregister();
+
return ret;
}
diff --git a/cmd/efidebug.c b/cmd/efidebug.c
index e4030f514a..6e36575a94 100644
--- a/cmd/efidebug.c
+++ b/cmd/efidebug.c
@@ -9,6 +9,7 @@
#include <common.h>
#include <command.h>
#include <efi_dt_fixup.h>
+#include <efi_load_initrd.h>
#include <efi_loader.h>
#include <efi_rng.h>
#include <exports.h>
@@ -19,6 +20,7 @@
#include <part.h>
#include <search.h>
#include <linux/ctype.h>
+#include <linux/err.h>
#define BS systab.boottime
#define RT systab.runtime
@@ -72,7 +74,7 @@ static int do_efi_capsule_update(struct cmd_tbl *cmdtp, int flag,
capsule->capsule_image_size);
}
- ret = EFI_CALL(RT->update_capsule(&capsule, 1, (u64)NULL));
+ ret = EFI_CALL(RT->update_capsule(&capsule, 1, 0));
if (ret) {
printf("Cannot handle a capsule at %p", capsule);
return CMD_RET_FAILURE;
@@ -129,6 +131,82 @@ static int do_efi_capsule_show(struct cmd_tbl *cmdtp, int flag,
return CMD_RET_SUCCESS;
}
+#ifdef CONFIG_EFI_ESRT
+
+#define EFI_ESRT_FW_TYPE_NUM 4
+char *efi_fw_type_str[EFI_ESRT_FW_TYPE_NUM] = {"unknown", "system FW", "device FW",
+ "UEFI driver"};
+
+#define EFI_ESRT_UPDATE_STATUS_NUM 9
+char *efi_update_status_str[EFI_ESRT_UPDATE_STATUS_NUM] = {"success", "unsuccessful",
+ "insufficient resources", "incorrect version", "invalid format",
+ "auth error", "power event (AC)", "power event (batt)",
+ "unsatisfied dependencies"};
+
+#define EFI_FW_TYPE_STR_GET(idx) (\
+EFI_ESRT_FW_TYPE_NUM > (idx) ? efi_fw_type_str[(idx)] : "error"\
+)
+
+#define EFI_FW_STATUS_STR_GET(idx) (\
+EFI_ESRT_UPDATE_STATUS_NUM > (idx) ? efi_update_status_str[(idx)] : "error"\
+)
+
+/**
+ * do_efi_capsule_esrt() - manage UEFI capsules
+ *
+ * @cmdtp: Command table
+ * @flag: Command flag
+ * @argc: Number of arguments
+ * @argv: Argument array
+ * Return: CMD_RET_SUCCESS on success,
+ * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
+ *
+ * Implement efidebug "capsule esrt" sub-command.
+ * The prints the current ESRT table.
+ *
+ * efidebug capsule esrt
+ */
+static int do_efi_capsule_esrt(struct cmd_tbl *cmdtp, int flag,
+ int argc, char * const argv[])
+{
+ struct efi_system_resource_table *esrt = NULL;
+
+ if (argc != 1)
+ return CMD_RET_USAGE;
+
+ for (int idx = 0; idx < systab.nr_tables; idx++)
+ if (!guidcmp(&efi_esrt_guid, &systab.tables[idx].guid))
+ esrt = (struct efi_system_resource_table *)systab.tables[idx].table;
+
+ if (!esrt) {
+ log_info("ESRT: table not present\n");
+ return CMD_RET_SUCCESS;
+ }
+
+ printf("========================================\n");
+ printf("ESRT: fw_resource_count=%d\n", esrt->fw_resource_count);
+ printf("ESRT: fw_resource_count_max=%d\n", esrt->fw_resource_count_max);
+ printf("ESRT: fw_resource_version=%lld\n", esrt->fw_resource_version);
+
+ for (int idx = 0; idx < esrt->fw_resource_count; idx++) {
+ printf("[entry %d]==============================\n", idx);
+ printf("ESRT: fw_class=%pUL\n", &esrt->entries[idx].fw_class);
+ printf("ESRT: fw_type=%s\n", EFI_FW_TYPE_STR_GET(esrt->entries[idx].fw_type));
+ printf("ESRT: fw_version=%d\n", esrt->entries[idx].fw_version);
+ printf("ESRT: lowest_supported_fw_version=%d\n",
+ esrt->entries[idx].lowest_supported_fw_version);
+ printf("ESRT: capsule_flags=%d\n",
+ esrt->entries[idx].capsule_flags);
+ printf("ESRT: last_attempt_version=%d\n",
+ esrt->entries[idx].last_attempt_version);
+ printf("ESRT: last_attempt_status=%s\n",
+ EFI_FW_STATUS_STR_GET(esrt->entries[idx].last_attempt_status));
+ }
+ printf("========================================\n");
+
+ return CMD_RET_SUCCESS;
+}
+#endif /* CONFIG_EFI_ESRT */
/**
* do_efi_capsule_res() - show a capsule update result
*
@@ -221,6 +299,10 @@ static struct cmd_tbl cmd_efidebug_capsule_sub[] = {
"", ""),
U_BOOT_CMD_MKENT(show, CONFIG_SYS_MAXARGS, 1, do_efi_capsule_show,
"", ""),
+#ifdef CONFIG_EFI_ESRT
+ U_BOOT_CMD_MKENT(esrt, CONFIG_SYS_MAXARGS, 1, do_efi_capsule_esrt,
+ "", ""),
+#endif
U_BOOT_CMD_MKENT(disk-update, 0, 0, do_efi_capsule_on_disk_update,
"", ""),
U_BOOT_CMD_MKENT(result, CONFIG_SYS_MAXARGS, 1, do_efi_capsule_res,
@@ -517,6 +599,10 @@ static const struct {
EFI_ACPI_TABLE_GUID,
},
{
+ "EFI System Resource Table",
+ EFI_SYSTEM_RESOURCE_TABLE_GUID,
+ },
+ {
"device tree",
EFI_FDT_GUID,
},
@@ -799,6 +885,54 @@ static int do_efi_show_tables(struct cmd_tbl *cmdtp, int flag,
}
/**
+ * create_initrd_dp() - Create a special device for our Boot### option
+ *
+ * @dev: Device
+ * @part: Disk partition
+ * @file: Filename
+ * Return: Pointer to the device path or ERR_PTR
+ *
+ */
+static
+struct efi_device_path *create_initrd_dp(const char *dev, const char *part,
+ const char *file)
+
+{
+ struct efi_device_path *tmp_dp = NULL, *tmp_fp = NULL;
+ struct efi_device_path *initrd_dp = NULL;
+ efi_status_t ret;
+ const struct efi_initrd_dp id_dp = {
+ .vendor = {
+ {
+ DEVICE_PATH_TYPE_MEDIA_DEVICE,
+ DEVICE_PATH_SUB_TYPE_VENDOR_PATH,
+ sizeof(id_dp.vendor),
+ },
+ EFI_INITRD_MEDIA_GUID,
+ },
+ .end = {
+ DEVICE_PATH_TYPE_END,
+ DEVICE_PATH_SUB_TYPE_END,
+ sizeof(id_dp.end),
+ }
+ };
+
+ ret = efi_dp_from_name(dev, part, file, &tmp_dp, &tmp_fp);
+ if (ret != EFI_SUCCESS) {
+ printf("Cannot create device path for \"%s %s\"\n", part, file);
+ goto out;
+ }
+
+ initrd_dp = efi_dp_append((const struct efi_device_path *)&id_dp,
+ tmp_fp);
+
+out:
+ efi_free_pool(tmp_dp);
+ efi_free_pool(tmp_fp);
+ return initrd_dp;
+}
+
+/**
* do_efi_boot_add() - set UEFI load option
*
* @cmdtp: Command table
@@ -810,7 +944,9 @@ static int do_efi_show_tables(struct cmd_tbl *cmdtp, int flag,
*
* Implement efidebug "boot add" sub-command. Create or change UEFI load option.
*
- * efidebug boot add <id> <label> <interface> <devnum>[:<part>] <file> <options>
+ * efidebug boot add -b <id> <label> <interface> <devnum>[:<part>] <file>
+ * -i <file> <interface2> <devnum2>[:<part>] <initrd>
+ * -s '<options>'
*/
static int do_efi_boot_add(struct cmd_tbl *cmdtp, int flag,
int argc, char *const argv[])
@@ -823,55 +959,105 @@ static int do_efi_boot_add(struct cmd_tbl *cmdtp, int flag,
size_t label_len, label_len16;
u16 *label;
struct efi_device_path *device_path = NULL, *file_path = NULL;
+ struct efi_device_path *final_fp = NULL;
+ struct efi_device_path *initrd_dp = NULL;
struct efi_load_option lo;
void *data = NULL;
efi_uintn_t size;
+ efi_uintn_t fp_size = 0;
efi_status_t ret;
int r = CMD_RET_SUCCESS;
- if (argc < 6 || argc > 7)
- return CMD_RET_USAGE;
-
- id = (int)simple_strtoul(argv[1], &endp, 16);
- if (*endp != '\0' || id > 0xffff)
- return CMD_RET_USAGE;
-
- sprintf(var_name, "Boot%04X", id);
- p = var_name16;
- utf8_utf16_strncpy(&p, var_name, 9);
-
guid = efi_global_variable_guid;
/* attributes */
lo.attributes = LOAD_OPTION_ACTIVE; /* always ACTIVE */
+ lo.optional_data = NULL;
+ lo.label = NULL;
- /* label */
- label_len = strlen(argv[2]);
- label_len16 = utf8_utf16_strnlen(argv[2], label_len);
- label = malloc((label_len16 + 1) * sizeof(u16));
- if (!label)
- return CMD_RET_FAILURE;
- lo.label = label; /* label will be changed below */
- utf8_utf16_strncpy(&label, argv[2], label_len);
+ argc--;
+ argv++; /* 'add' */
+ for (; argc > 0; argc--, argv++) {
+ if (!strcmp(argv[0], "-b")) {
+ if (argc < 5 || lo.label) {
+ r = CMD_RET_USAGE;
+ goto out;
+ }
+ id = (int)simple_strtoul(argv[1], &endp, 16);
+ if (*endp != '\0' || id > 0xffff)
+ return CMD_RET_USAGE;
+
+ sprintf(var_name, "Boot%04X", id);
+ p = var_name16;
+ utf8_utf16_strncpy(&p, var_name, 9);
+
+ /* label */
+ label_len = strlen(argv[2]);
+ label_len16 = utf8_utf16_strnlen(argv[2], label_len);
+ label = malloc((label_len16 + 1) * sizeof(u16));
+ if (!label)
+ return CMD_RET_FAILURE;
+ lo.label = label; /* label will be changed below */
+ utf8_utf16_strncpy(&label, argv[2], label_len);
+
+ /* file path */
+ ret = efi_dp_from_name(argv[3], argv[4], argv[5],
+ &device_path, &file_path);
+ if (ret != EFI_SUCCESS) {
+ printf("Cannot create device path for \"%s %s\"\n",
+ argv[3], argv[4]);
+ r = CMD_RET_FAILURE;
+ goto out;
+ }
+ fp_size += efi_dp_size(file_path) +
+ sizeof(struct efi_device_path);
+ argc -= 5;
+ argv += 5;
+ } else if (!strcmp(argv[0], "-i")) {
+ if (argc < 3 || initrd_dp) {
+ r = CMD_RET_USAGE;
+ goto out;
+ }
- /* file path */
- ret = efi_dp_from_name(argv[3], argv[4], argv[5], &device_path,
- &file_path);
- if (ret != EFI_SUCCESS) {
- printf("Cannot create device path for \"%s %s\"\n",
- argv[3], argv[4]);
+ initrd_dp = create_initrd_dp(argv[1], argv[2], argv[3]);
+ if (!initrd_dp) {
+ printf("Cannot add an initrd\n");
+ r = CMD_RET_FAILURE;
+ goto out;
+ }
+ argc -= 3;
+ argv += 3;
+ fp_size += efi_dp_size(initrd_dp) +
+ sizeof(struct efi_device_path);
+ } else if (!strcmp(argv[0], "-s")) {
+ if (argc < 1 || lo.optional_data) {
+ r = CMD_RET_USAGE;
+ goto out;
+ }
+ lo.optional_data = (const u8 *)argv[1];
+ argc -= 1;
+ argv += 1;
+ } else {
+ r = CMD_RET_USAGE;
+ goto out;
+ }
+ }
+
+ if (!file_path) {
+ printf("Missing binary\n");
+ r = CMD_RET_USAGE;
+ goto out;
+ }
+
+ final_fp = efi_dp_concat(file_path, initrd_dp);
+ if (!final_fp) {
+ printf("Cannot create final device path\n");
r = CMD_RET_FAILURE;
goto out;
}
- lo.file_path = file_path;
- lo.file_path_length = efi_dp_size(file_path)
- + sizeof(struct efi_device_path); /* for END */
- /* optional data */
- if (argc == 6)
- lo.optional_data = NULL;
- else
- lo.optional_data = (const u8 *)argv[6];
+ lo.file_path = final_fp;
+ lo.file_path_length = fp_size;
size = efi_serialize_load_option(&lo, (u8 **)&data);
if (!size) {
@@ -888,8 +1074,11 @@ static int do_efi_boot_add(struct cmd_tbl *cmdtp, int flag,
printf("Cannot set %ls\n", var_name16);
r = CMD_RET_FAILURE;
}
+
out:
free(data);
+ efi_free_pool(final_fp);
+ efi_free_pool(initrd_dp);
efi_free_pool(device_path);
efi_free_pool(file_path);
free(lo.label);
@@ -955,11 +1144,14 @@ static int do_efi_boot_rm(struct cmd_tbl *cmdtp, int flag,
*/
static void show_efi_boot_opt_data(u16 *varname16, void *data, size_t *size)
{
+ struct efi_device_path *initrd_path = NULL;
struct efi_load_option lo;
char *label, *p;
size_t label_len16, label_len;
u16 *dp_str;
efi_status_t ret;
+ efi_uintn_t initrd_dp_size;
+ const efi_guid_t lf2_initrd_guid = EFI_INITRD_MEDIA_GUID;
ret = efi_deserialize_load_option(&lo, data, size);
if (ret != EFI_SUCCESS) {
@@ -990,6 +1182,14 @@ static void show_efi_boot_opt_data(u16 *varname16, void *data, size_t *size)
printf(" file_path: %ls\n", dp_str);
efi_free_pool(dp_str);
+ initrd_path = efi_dp_from_lo(&lo, &initrd_dp_size, lf2_initrd_guid);
+ if (initrd_path) {
+ dp_str = efi_dp_str(initrd_path);
+ printf(" initrd_path: %ls\n", dp_str);
+ efi_free_pool(dp_str);
+ efi_free_pool(initrd_path);
+ }
+
printf(" data:\n");
print_hex_dump(" ", DUMP_PREFIX_OFFSET, 16, 1,
lo.optional_data, *size, true);
@@ -1559,7 +1759,10 @@ static int do_efidebug(struct cmd_tbl *cmdtp, int flag,
static char efidebug_help_text[] =
" - UEFI Shell-like interface to configure UEFI environment\n"
"\n"
- "efidebug boot add <bootid> <label> <interface> <devnum>[:<part>] <file path> [<load options>]\n"
+ "efidebug boot add "
+ "-b <bootid> <label> <interface> <devnum>[:<part>] <file path> "
+ "-i <interface> <devnum>[:<part>] <initrd file path> "
+ "-s '<optional data>'\n"
" - set UEFI BootXXXX variable\n"
" <load options> will be passed to UEFI application\n"
"efidebug boot rm <bootid#1> [<bootid#2> [<bootid#3> [...]]]\n"
@@ -1580,6 +1783,10 @@ static char efidebug_help_text[] =
" - show capsule information\n"
"efidebug capsule result [<capsule result var>]\n"
" - show a capsule update result\n"
+#ifdef CONFIG_EFI_ESRT
+ "efidebug capsule esrt\n"
+ " - print the ESRT\n"
+#endif
"\n"
#endif
"efidebug devices\n"
@@ -1603,7 +1810,7 @@ static char efidebug_help_text[] =
#endif
U_BOOT_CMD(
- efidebug, 10, 0, do_efidebug,
+ efidebug, CONFIG_SYS_MAXARGS, 0, do_efidebug,
"Configure UEFI environment",
efidebug_help_text
);
diff --git a/cmd/load.c b/cmd/load.c
index 5bbc39baea..b7894d7db0 100644
--- a/cmd/load.c
+++ b/cmd/load.c
@@ -11,12 +11,14 @@
#include <command.h>
#include <console.h>
#include <cpu_func.h>
+#include <efi_loader.h>
#include <env.h>
+#include <exports.h>
#include <flash.h>
#include <image.h>
-#include <s_record.h>
+#include <mapmem.h>
#include <net.h>
-#include <exports.h>
+#include <s_record.h>
#include <serial.h>
#include <xyzModem.h>
#include <asm/cache.h>
@@ -996,6 +998,10 @@ static ulong load_serial_ymodem(ulong offset, int mode)
}
}
+ if (IS_ENABLED(CONFIG_CMD_BOOTEFI))
+ efi_set_bootdev("Uart", "", "",
+ map_sysmem(offset, 0), size);
+
} else {
printf("%s\n", xyzModem_error(err));
}
diff --git a/doc/board/emulation/qemu_capsule_update.rst b/doc/board/emulation/qemu_capsule_update.rst
index 9fec75f8f1..33ce4bcd32 100644
--- a/doc/board/emulation/qemu_capsule_update.rst
+++ b/doc/board/emulation/qemu_capsule_update.rst
@@ -60,7 +60,7 @@ to be pointing to the EFI System Partition which contains the capsule
file. The BootNext, BootXXXX and OsIndications variables can be set
using the following commands::
- => efidebug boot add 0 Boot0000 virtio 0:1 <capsule_file_name>
+ => efidebug boot add -b 0 Boot0000 virtio 0:1 <capsule_file_name>
=> efidebug boot next 0
=> setenv -e -nv -bs -rt -v OsIndications =0x04
=> saveenv
@@ -198,7 +198,7 @@ command line::
3. Set the following environment and UEFI boot variables
=> setenv -e -nv -bs -rt -v OsIndications =0x04
- => efidebug boot add 0 Boot0000 virtio 0:1 <capsule_file_name>
+ => efidebug boot add -b 0 Boot0000 virtio 0:1 <capsule_file_name>
=> efidebug boot next 0
=> saveenv
diff --git a/doc/uefi/uefi.rst b/doc/uefi/uefi.rst
index 5a67737c15..b3494c22e0 100644
--- a/doc/uefi/uefi.rst
+++ b/doc/uefi/uefi.rst
@@ -178,7 +178,7 @@ Now in U-Boot install the keys on your board::
Set up boot parameters on your board::
- efidebug boot add 1 HELLO mmc 0:1 /helloworld.efi.signed ""
+ efidebug boot add -b 1 HELLO mmc 0:1 /helloworld.efi.signed ""
Now your board can run the signed image via the boot manager (see below).
You can also try this sequence by running Pytest, test_efi_secboot,
diff --git a/drivers/dfu/dfu_sf.c b/drivers/dfu/dfu_sf.c
index 76b629a334..8f8c425977 100644
--- a/drivers/dfu/dfu_sf.c
+++ b/drivers/dfu/dfu_sf.c
@@ -87,7 +87,23 @@ static unsigned int dfu_polltimeout_sf(struct dfu_entity *dfu)
static void dfu_free_entity_sf(struct dfu_entity *dfu)
{
- spi_flash_free(dfu->data.sf.dev);
+ /*
+ * In the DM case it is not necessary to free the SPI device.
+ * For the non-DM case we must ensure that the the SPI device is only
+ * freed once.
+ */
+ if (!CONFIG_IS_ENABLED(DM_SPI_FLASH)) {
+ struct spi_flash *dev = dfu->data.sf.dev;
+
+ if (!dev)
+ return;
+ dfu->data.sf.dev = NULL;
+ list_for_each_entry(dfu, &dfu_list, list) {
+ if (dfu->data.sf.dev == dev)
+ dfu->data.sf.dev = NULL;
+ }
+ spi_flash_free(dev);
+ }
}
static struct spi_flash *parse_dev(char *devstr)
diff --git a/include/efi_api.h b/include/efi_api.h
index 48e48a6263..18a1adf023 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -523,6 +523,7 @@ struct efi_device_path_acpi_path {
# define DEVICE_PATH_SUB_TYPE_MSG_SCSI 0x02
# define DEVICE_PATH_SUB_TYPE_MSG_USB 0x05
# define DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR 0x0b
+# define DEVICE_PATH_SUB_TYPE_MSG_UART 0x0e
# define DEVICE_PATH_SUB_TYPE_MSG_USB_CLASS 0x0f
# define DEVICE_PATH_SUB_TYPE_MSG_SATA 0x12
# define DEVICE_PATH_SUB_TYPE_MSG_NVME 0x17
@@ -542,6 +543,15 @@ struct efi_device_path_scsi {
u16 logical_unit_number;
} __packed;
+struct efi_device_path_uart {
+ struct efi_device_path dp;
+ u32 reserved;
+ u64 baud_rate;
+ u8 data_bits;
+ u8 parity;
+ u8 stop_bits;
+} __packed;
+
struct efi_device_path_usb {
struct efi_device_path dp;
u8 parent_port_number;
@@ -1722,6 +1732,23 @@ struct efi_load_file_protocol {
void *buffer);
};
+struct efi_system_resource_entry {
+ efi_guid_t fw_class;
+ u32 fw_type;
+ u32 fw_version;
+ u32 lowest_supported_fw_version;
+ u32 capsule_flags;
+ u32 last_attempt_version;
+ u32 last_attempt_status;
+} __packed;
+
+struct efi_system_resource_table {
+ u32 fw_resource_count;
+ u32 fw_resource_count_max;
+ u64 fw_resource_version;
+ struct efi_system_resource_entry entries[];
+} __packed;
+
/* Boot manager load options */
#define LOAD_OPTION_ACTIVE 0x00000001
#define LOAD_OPTION_FORCE_RECONNECT 0x00000002
@@ -1740,6 +1767,10 @@ struct efi_load_file_protocol {
#define ESRT_FW_TYPE_DEVICEFIRMWARE 0x00000002
#define ESRT_FW_TYPE_UEFIDRIVER 0x00000003
+#define EFI_SYSTEM_RESOURCE_TABLE_GUID\
+ EFI_GUID(0xb122a263, 0x3661, 0x4f68,\
+ 0x99, 0x29, 0x78, 0xf8, 0xb0, 0xd6, 0x21, 0x80)
+
/* Last Attempt Status Values */
#define LAST_ATTEMPT_STATUS_SUCCESS 0x00000000
#define LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL 0x00000001
diff --git a/include/efi_loader.h b/include/efi_loader.h
index 68daa1a4a9..de1a496a97 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -214,6 +214,8 @@ extern const efi_guid_t efi_guid_rng_protocol;
extern const efi_guid_t efi_guid_capsule_report;
/* GUID of firmware management protocol */
extern const efi_guid_t efi_guid_firmware_management_protocol;
+/* GUID for the ESRT */
+extern const efi_guid_t efi_esrt_guid;
extern unsigned int __efi_runtime_start, __efi_runtime_stop;
extern unsigned int __efi_runtime_rel_start, __efi_runtime_rel_stop;
@@ -437,6 +439,7 @@ efi_status_t efi_net_register(void);
/* Called by bootefi to make the watchdog available */
efi_status_t efi_watchdog_register(void);
efi_status_t efi_initrd_register(void);
+void efi_initrd_deregister(void);
/* Called by bootefi to make SMBIOS tables available */
/**
* efi_acpi_register() - write out ACPI tables
@@ -558,6 +561,15 @@ struct efi_simple_file_system_protocol *efi_simple_file_system(
/* open file from device-path: */
struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp);
+/* Registers a callback function for a notification event. */
+efi_status_t EFIAPI efi_register_protocol_notify(const efi_guid_t *protocol,
+ struct efi_event *event,
+ void **registration);
+efi_status_t efi_file_size(struct efi_file_handle *fh, efi_uintn_t *size);
+
+/* get a device path from a Boot#### option */
+struct efi_device_path *efi_get_dp_from_boot(const efi_guid_t guid);
+
/**
* efi_size_in_pages() - convert size in bytes to size in pages
*
@@ -723,6 +735,8 @@ efi_status_t EFIAPI efi_query_variable_info(
u64 *remaining_variable_storage_size,
u64 *maximum_variable_size);
+void *efi_get_var(u16 *name, const efi_guid_t *vendor, efi_uintn_t *size);
+
/*
* See section 3.1.3 in the v2.7 UEFI spec for more details on
* the layout of EFI_LOAD_OPTION. In short it is:
@@ -744,6 +758,10 @@ struct efi_load_option {
const u8 *optional_data;
};
+struct efi_device_path *efi_dp_from_lo(struct efi_load_option *lo,
+ efi_uintn_t *size, efi_guid_t guid);
+struct efi_device_path *efi_dp_concat(const struct efi_device_path *dp1,
+ const struct efi_device_path *dp2);
efi_status_t efi_deserialize_load_option(struct efi_load_option *lo, u8 *data,
efi_uintn_t *size);
unsigned long efi_serialize_load_option(struct efi_load_option *lo, u8 **data);
@@ -890,4 +908,22 @@ static inline efi_status_t efi_launch_capsules(void)
#endif /* CONFIG_IS_ENABLED(EFI_LOADER) */
+/**
+ * Install the ESRT system table.
+ *
+ * @return status code
+ */
+efi_status_t efi_esrt_register(void);
+
+/**
+ * efi_esrt_populate() - Populates the ESRT entries from the FMP instances
+ * present in the system.
+ * If an ESRT already exists, the old ESRT is replaced in the system table.
+ * The memory of the old ESRT is deallocated.
+ *
+ * Return:
+ * - EFI_SUCCESS if the ESRT is correctly created
+ * - error code otherwise.
+ */
+efi_status_t efi_esrt_populate(void);
#endif /* _EFI_LOADER_H */
diff --git a/include/efi_selftest.h b/include/efi_selftest.h
index 1515fdaa02..07b619901c 100644
--- a/include/efi_selftest.h
+++ b/include/efi_selftest.h
@@ -66,11 +66,10 @@ enum efi_test_phase {
*/
EFI_SETUP_BEFORE_BOOTTIME_EXIT,
/**
- * @EFI_SETUP_AFTER_BOOTTIME_EXIT: - setup after ExitBootServices
- *
- * Setup, execute, and teardown are executed after ExitBootServices().
+ * @EFI_SETTING_VIRTUAL_ADDRESS_MAP - calls SetVirtualAddressMap()
+ * Execute calls SetVirtualAddressMap().
*/
- EFI_SETUP_AFTER_BOOTTIME_EXIT,
+ EFI_SETTING_VIRTUAL_ADDRESS_MAP,
};
extern struct efi_simple_text_output_protocol *con_out;
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index e729f727df..e44f004f3f 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -281,7 +281,7 @@ config EFI_HAVE_RUNTIME_RESET
config EFI_GRUB_ARM32_WORKAROUND
bool "Workaround for GRUB on 32bit ARM"
- default n if ARCH_QEMU
+ default n if ARCH_BCM283X || ARCH_SUNXI || ARCH_QEMU
default y
depends on ARM && !ARM64
help
@@ -315,18 +315,13 @@ config EFI_TCG2_PROTOCOL_EVENTLOG_SIZE
config EFI_LOAD_FILE2_INITRD
bool "EFI_FILE_LOAD2_PROTOCOL for Linux initial ramdisk"
- default n
- help
- Expose a EFI_FILE_LOAD2_PROTOCOL that the Linux UEFI stub can
- use to load the initial ramdisk. Once this is enabled using
- initrd=<ramdisk> will stop working.
-
-config EFI_INITRD_FILESPEC
- string "initramfs path"
- default "host 0:1 initrd"
- depends on EFI_LOAD_FILE2_INITRD
+ default y
help
- Full path of the initramfs file, e.g. mmc 0:2 initramfs.cpio.gz.
+ Linux v5.7 and later can make use of this option. If the boot option
+ selected by the UEFI boot manager specifies an existing file to be used
+ as initial RAM disk, a Linux specific Load File2 protocol will be
+ installed and Linux 5.7+ will ignore any initrd=<ramdisk> command line
+ argument.
config EFI_SECURE_BOOT
bool "Enable EFI secure boot support"
@@ -347,4 +342,11 @@ config EFI_SECURE_BOOT
it is signed with a trusted key. To do that, you need to install,
at least, PK, KEK and db.
+config EFI_ESRT
+ bool "Enable the UEFI ESRT generation"
+ depends on EFI_CAPSULE_FIRMWARE_MANAGEMENT
+ default y
+ help
+ Enabling this option creates the ESRT UEFI system table.
+
endif
diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile
index 10b42e8847..8bd343e258 100644
--- a/lib/efi_loader/Makefile
+++ b/lib/efi_loader/Makefile
@@ -23,6 +23,7 @@ endif
obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o
obj-$(CONFIG_CMD_BOOTEFI_BOOTMGR) += efi_bootmgr.o
obj-y += efi_boottime.o
+obj-y += efi_helper.o
obj-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += efi_capsule.o
obj-$(CONFIG_EFI_CAPSULE_FIRMWARE) += efi_firmware.o
obj-y += efi_console.o
@@ -52,6 +53,7 @@ obj-y += efi_variable.o
obj-$(CONFIG_EFI_VARIABLES_PRESEED) += efi_var_seed.o
endif
obj-y += efi_watchdog.o
+obj-$(CONFIG_EFI_ESRT) += efi_esrt.o
obj-$(CONFIG_LCD) += efi_gop.o
obj-$(CONFIG_DM_VIDEO) += efi_gop.o
obj-$(CONFIG_PARTITIONS) += efi_disk.o
diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c
index 25f5cebfdb..46c8011344 100644
--- a/lib/efi_loader/efi_bootmgr.c
+++ b/lib/efi_loader/efi_bootmgr.c
@@ -118,11 +118,13 @@ static efi_status_t try_load_entry(u16 n, efi_handle_t *handle,
ret = efi_set_variable_int(L"BootCurrent",
&efi_global_variable_guid,
attributes, sizeof(n), &n, false);
- if (ret != EFI_SUCCESS) {
- if (EFI_CALL(efi_unload_image(*handle))
- != EFI_SUCCESS)
- log_err("Unloading image failed\n");
- goto error;
+ if (ret != EFI_SUCCESS)
+ goto unload;
+ /* try to register load file2 for initrd's */
+ if (IS_ENABLED(CONFIG_EFI_LOAD_FILE2_INITRD)) {
+ ret = efi_initrd_register();
+ if (ret != EFI_SUCCESS)
+ goto unload;
}
log_info("Booting: %ls\n", lo.label);
@@ -147,6 +149,13 @@ error:
free(load_option);
return ret;
+
+unload:
+ if (EFI_CALL(efi_unload_image(*handle)) != EFI_SUCCESS)
+ log_err("Unloading image failed\n");
+ free(load_option);
+
+ return ret;
}
/**
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 41b8949b04..4777b35fd4 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -1406,10 +1406,9 @@ out:
*
* Return: status code
*/
-static efi_status_t EFIAPI efi_register_protocol_notify(
- const efi_guid_t *protocol,
- struct efi_event *event,
- void **registration)
+efi_status_t EFIAPI efi_register_protocol_notify(const efi_guid_t *protocol,
+ struct efi_event *event,
+ void **registration)
{
struct efi_register_notify_event *item;
efi_status_t ret = EFI_SUCCESS;
@@ -1877,7 +1876,6 @@ static
efi_status_t efi_load_image_from_file(struct efi_device_path *file_path,
void **buffer, efi_uintn_t *size)
{
- struct efi_file_info *info = NULL;
struct efi_file_handle *f;
efi_status_t ret;
u64 addr;
@@ -1888,18 +1886,7 @@ efi_status_t efi_load_image_from_file(struct efi_device_path *file_path,
if (!f)
return EFI_NOT_FOUND;
- /* Get file size */
- bs = 0;
- EFI_CALL(ret = f->getinfo(f, (efi_guid_t *)&efi_file_info_guid,
- &bs, info));
- if (ret != EFI_BUFFER_TOO_SMALL) {
- ret = EFI_DEVICE_ERROR;
- goto error;
- }
-
- info = malloc(bs);
- EFI_CALL(ret = f->getinfo(f, (efi_guid_t *)&efi_file_info_guid, &bs,
- info));
+ ret = efi_file_size(f, &bs);
if (ret != EFI_SUCCESS)
goto error;
@@ -1909,7 +1896,6 @@ efi_status_t efi_load_image_from_file(struct efi_device_path *file_path,
* allocate a buffer as EFI_BOOT_SERVICES_DATA. The caller has to
* update the reservation according to the image type.
*/
- bs = info->file_size;
ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
EFI_BOOT_SERVICES_DATA,
efi_size_in_pages(bs), &addr);
@@ -1926,7 +1912,6 @@ efi_status_t efi_load_image_from_file(struct efi_device_path *file_path,
*size = bs;
error:
EFI_CALL(f->close(f));
- free(info);
return ret;
}
diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
index b57f0302c5..9df9c35084 100644
--- a/lib/efi_loader/efi_capsule.c
+++ b/lib/efi_loader/efi_capsule.c
@@ -449,7 +449,7 @@ efi_status_t EFIAPI efi_update_capsule(
unsigned int i;
efi_status_t ret;
- EFI_ENTRY("%p, %lu, %llu\n", capsule_header_array, capsule_count,
+ EFI_ENTRY("%p, %zu, %llu\n", capsule_header_array, capsule_count,
scatter_gather_list);
if (!capsule_count) {
@@ -482,6 +482,14 @@ efi_status_t EFIAPI efi_update_capsule(
goto out;
}
out:
+
+ if (IS_ENABLED(CONFIG_EFI_ESRT)) {
+ /* Rebuild the ESRT to reflect any updated FW images. */
+ ret = efi_esrt_populate();
+ if (ret != EFI_SUCCESS)
+ log_warning("EFI Capsule: failed to update ESRT\n");
+ }
+
return EFI_EXIT(ret);
}
@@ -509,7 +517,7 @@ efi_status_t EFIAPI efi_query_capsule_caps(
unsigned int i;
efi_status_t ret;
- EFI_ENTRY("%p, %lu, %p, %p\n", capsule_header_array, capsule_count,
+ EFI_ENTRY("%p, %zu, %p, %p\n", capsule_header_array, capsule_count,
maximum_capsule_size, reset_type);
if (!maximum_capsule_size) {
diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c
index c4003554c2..6040f3a99a 100644
--- a/lib/efi_loader/efi_console.c
+++ b/lib/efi_loader/efi_console.c
@@ -254,7 +254,7 @@ static bool cout_mode_matches(struct cout_mode *mode, int rows, int cols)
}
/**
- * query_console_serial() - query console size
+ * query_console_serial() - query serial console size
*
* When using a serial console or the net console we can only devise the
* terminal size by querying the terminal using ECMA-48 control sequences.
@@ -300,6 +300,37 @@ out:
}
/**
+ * query_vidconsole() - query video console size
+ *
+ *
+ * @rows: pointer to return number of rows
+ * @cols: pointer to return number of columns
+ * Returns: 0 on success
+ */
+static int __maybe_unused query_vidconsole(int *rows, int *cols)
+{
+ const char *stdout_name = env_get("stdout");
+ struct stdio_dev *stdout_dev;
+ struct udevice *dev;
+ struct vidconsole_priv *priv;
+
+ if (!stdout_name || strncmp(stdout_name, "vidconsole", 10))
+ return -ENODEV;
+ stdout_dev = stdio_get_by_name("vidconsole");
+ if (!stdout_dev)
+ return -ENODEV;
+ dev = stdout_dev->priv;
+ if (!dev)
+ return -ENODEV;
+ priv = dev_get_uclass_priv(dev);
+ if (!priv)
+ return -ENODEV;
+ *rows = priv->rows;
+ *cols = priv->cols;
+ return 0;
+}
+
+/**
* query_console_size() - update the mode table.
*
* By default the only mode available is 80x25. If the console has at least 50
@@ -308,21 +339,15 @@ out:
*/
static void query_console_size(void)
{
- const char *stdout_name = env_get("stdout");
int rows = 25, cols = 80;
+ int ret = -ENODEV;
- if (stdout_name && !strncmp(stdout_name, "vidconsole", 10) &&
- IS_ENABLED(CONFIG_DM_VIDEO)) {
- struct stdio_dev *stdout_dev =
- stdio_get_by_name("vidconsole");
- struct udevice *dev = stdout_dev->priv;
- struct vidconsole_priv *priv =
- dev_get_uclass_priv(dev);
- rows = priv->rows;
- cols = priv->cols;
- } else if (query_console_serial(&rows, &cols)) {
+ if IS_ENABLED(CONFIG_DM_VIDEO)
+ ret = query_vidconsole(&rows, &cols);
+ if (ret)
+ ret = query_console_serial(&rows, &cols);
+ if (ret)
return;
- }
/* Test if we can have Mode 1 */
if (cols >= 80 && rows >= 50) {
diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c
index c9315dd458..4b20859b25 100644
--- a/lib/efi_loader/efi_device_path.c
+++ b/lib/efi_loader/efi_device_path.c
@@ -282,11 +282,31 @@ struct efi_device_path *efi_dp_dup(const struct efi_device_path *dp)
return ndp;
}
-struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1,
- const struct efi_device_path *dp2)
+/**
+ * efi_dp_append_or_concatenate() - Append or concatenate two device paths.
+ * Concatenated device path will be separated
+ * by a sub-type 0xff end node
+ *
+ * @dp1: First device path
+ * @dp2: Second device path
+ * @concat: If true the two device paths will be concatenated and separated
+ * by an end of entrire device path sub-type 0xff end node.
+ * If true the second device path will be appended to the first and
+ * terminated by an end node
+ *
+ * Return:
+ * concatenated device path or NULL. Caller must free the returned value
+ */
+static struct
+efi_device_path *efi_dp_append_or_concatenate(const struct efi_device_path *dp1,
+ const struct efi_device_path *dp2,
+ bool concat)
{
struct efi_device_path *ret;
+ size_t end_size = sizeof(END);
+ if (concat)
+ end_size = 2 * sizeof(END);
if (!dp1 && !dp2) {
/* return an end node */
ret = efi_dp_dup(&END);
@@ -298,18 +318,58 @@ struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1,
/* both dp1 and dp2 are non-null */
unsigned sz1 = efi_dp_size(dp1);
unsigned sz2 = efi_dp_size(dp2);
- void *p = dp_alloc(sz1 + sz2 + sizeof(END));
+ void *p = dp_alloc(sz1 + sz2 + end_size);
if (!p)
return NULL;
+ ret = p;
memcpy(p, dp1, sz1);
+ p += sz1;
+
+ if (concat) {
+ memcpy(p, &END, sizeof(END));
+ p += sizeof(END);
+ }
+
/* the end node of the second device path has to be retained */
- memcpy(p + sz1, dp2, sz2 + sizeof(END));
- ret = p;
+ memcpy(p, dp2, sz2);
+ p += sz2;
+ memcpy(p, &END, sizeof(END));
}
return ret;
}
+/**
+ * efi_dp_append() - Append a device to an existing device path.
+ *
+ * @dp1: First device path
+ * @dp2: Second device path
+ *
+ * Return:
+ * concatenated device path or NULL. Caller must free the returned value
+ */
+struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1,
+ const struct efi_device_path *dp2)
+{
+ return efi_dp_append_or_concatenate(dp1, dp2, false);
+}
+
+/**
+ * efi_dp_concat() - Concatenate 2 device paths. The final device path will
+ * contain two device paths separated by and end node (0xff).
+ *
+ * @dp1: First device path
+ * @dp2: Second device path
+ *
+ * Return:
+ * concatenated device path or NULL. Caller must free the returned value
+ */
+struct efi_device_path *efi_dp_concat(const struct efi_device_path *dp1,
+ const struct efi_device_path *dp2)
+{
+ return efi_dp_append_or_concatenate(dp1, dp2, true);
+}
+
struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp,
const struct efi_device_path *node)
{
@@ -960,6 +1020,28 @@ struct efi_device_path *efi_dp_from_file(struct blk_desc *desc, int part,
return start;
}
+struct efi_device_path *efi_dp_from_uart(void)
+{
+ void *buf, *pos;
+ struct efi_device_path_uart *uart;
+ size_t dpsize = sizeof(ROOT) + sizeof(*uart) + sizeof(END);
+
+ buf = dp_alloc(dpsize);
+ if (!buf)
+ return NULL;
+ pos = buf;
+ memcpy(pos, &ROOT, sizeof(ROOT));
+ pos += sizeof(ROOT);
+ uart = pos;
+ uart->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
+ uart->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_UART;
+ uart->dp.length = sizeof(*uart);
+ pos += sizeof(*uart);
+ memcpy(pos, &END, sizeof(END));
+
+ return buf;
+}
+
#ifdef CONFIG_NET
struct efi_device_path *efi_dp_from_eth(void)
{
@@ -1086,7 +1168,6 @@ efi_status_t efi_dp_from_name(const char *dev, const char *devnr,
struct efi_device_path **device,
struct efi_device_path **file)
{
- int is_net;
struct blk_desc *desc = NULL;
struct disk_partition fs_partition;
int part = 0;
@@ -1096,8 +1177,15 @@ efi_status_t efi_dp_from_name(const char *dev, const char *devnr,
if (path && !file)
return EFI_INVALID_PARAMETER;
- is_net = !strcmp(dev, "Net");
- if (!is_net) {
+ if (!strcmp(dev, "Net")) {
+#ifdef CONFIG_NET
+ if (device)
+ *device = efi_dp_from_eth();
+#endif
+ } else if (!strcmp(dev, "Uart")) {
+ if (device)
+ *device = efi_dp_from_uart();
+ } else {
part = blk_get_device_part_str(dev, devnr, &desc, &fs_partition,
1);
if (part < 0 || !desc)
@@ -1105,11 +1193,6 @@ efi_status_t efi_dp_from_name(const char *dev, const char *devnr,
if (device)
*device = efi_dp_from_part(desc, part);
- } else {
-#ifdef CONFIG_NET
- if (device)
- *device = efi_dp_from_eth();
-#endif
}
if (!path)
@@ -1120,7 +1203,7 @@ efi_status_t efi_dp_from_name(const char *dev, const char *devnr,
s = filename;
while ((s = strchr(s, '/')))
*s++ = '\\';
- *file = efi_dp_from_file(is_net ? NULL : desc, part, filename);
+ *file = efi_dp_from_file(desc, part, filename);
if (!*file)
return EFI_INVALID_PARAMETER;
@@ -1160,3 +1243,43 @@ ssize_t efi_dp_check_length(const struct efi_device_path *dp,
dp = (const struct efi_device_path *)((const u8 *)dp + len);
}
}
+
+/**
+ * efi_dp_from_lo() - Get the instance of a VenMedia node in a
+ * multi-instance device path that matches
+ * a specific GUID. This kind of device paths
+ * is found in Boot#### options describing an
+ * initrd location
+ *
+ * @lo: EFI_LOAD_OPTION containing a valid device path
+ * @size: size of the discovered device path
+ * @guid: guid to search for
+ *
+ * Return:
+ * device path including the VenMedia node or NULL.
+ * Caller must free the returned value.
+ */
+struct
+efi_device_path *efi_dp_from_lo(struct efi_load_option *lo,
+ efi_uintn_t *size, efi_guid_t guid)
+{
+ struct efi_device_path *fp = lo->file_path;
+ struct efi_device_path_vendor *vendor;
+ int lo_len = lo->file_path_length;
+
+ for (; lo_len >= sizeof(struct efi_device_path);
+ lo_len -= fp->length, fp = (void *)fp + fp->length) {
+ if (lo_len < 0 || efi_dp_check_length(fp, lo_len) < 0)
+ break;
+ if (fp->type != DEVICE_PATH_TYPE_MEDIA_DEVICE ||
+ fp->sub_type != DEVICE_PATH_SUB_TYPE_VENDOR_PATH)
+ continue;
+
+ vendor = (struct efi_device_path_vendor *)fp;
+ if (!guidcmp(&vendor->guid, &guid))
+ return efi_dp_dup(fp);
+ }
+ log_debug("VenMedia(%pUl) not found in %ls\n", &guid, lo->label);
+
+ return NULL;
+}
diff --git a/lib/efi_loader/efi_device_path_to_text.c b/lib/efi_loader/efi_device_path_to_text.c
index edc9fdc387..43554cd771 100644
--- a/lib/efi_loader/efi_device_path_to_text.c
+++ b/lib/efi_loader/efi_device_path_to_text.c
@@ -118,6 +118,19 @@ static char *dp_msging(char *s, struct efi_device_path *dp)
ide->logical_unit_number);
break;
}
+ case DEVICE_PATH_SUB_TYPE_MSG_UART: {
+ struct efi_device_path_uart *uart =
+ (struct efi_device_path_uart *)dp;
+ s += sprintf(s, "Uart(%lld,%d,%d,", uart->baud_rate,
+ uart->data_bits, uart->parity);
+ switch (uart->stop_bits) {
+ case 2:
+ s += sprintf(s, "1.5)");
+ default:
+ s += sprintf(s, "%d)", uart->stop_bits);
+ }
+ break;
+ }
case DEVICE_PATH_SUB_TYPE_MSG_USB: {
struct efi_device_path_usb *udp =
(struct efi_device_path_usb *)dp;
diff --git a/lib/efi_loader/efi_dt_fixup.c b/lib/efi_loader/efi_dt_fixup.c
index a4529ee3ef..b6fe5d2e5a 100644
--- a/lib/efi_loader/efi_dt_fixup.c
+++ b/lib/efi_loader/efi_dt_fixup.c
@@ -61,7 +61,7 @@ void efi_carve_out_dt_rsv(void *fdt)
for (i = 0; i < nr_rsv; i++) {
if (fdt_get_mem_rsv(fdt, i, &addr, &size) != 0)
continue;
- efi_reserve_memory(addr, size, false);
+ efi_reserve_memory(addr, size, true);
}
/* process reserved-memory */
diff --git a/lib/efi_loader/efi_esrt.c b/lib/efi_loader/efi_esrt.c
new file mode 100644
index 0000000000..947bdb5e95
--- /dev/null
+++ b/lib/efi_loader/efi_esrt.c
@@ -0,0 +1,510 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * EFI application ESRT tables support
+ *
+ * Copyright (C) 2021 Arm Ltd.
+ */
+
+#include <common.h>
+#include <efi_loader.h>
+#include <log.h>
+#include <efi_api.h>
+#include <malloc.h>
+
+const efi_guid_t efi_esrt_guid = EFI_SYSTEM_RESOURCE_TABLE_GUID;
+
+static struct efi_system_resource_table *esrt;
+
+#define EFI_ESRT_VERSION 1
+
+/**
+ * efi_esrt_image_info_to_entry() - copy the information present in a fw image
+ * descriptor to a ESRT entry.
+ * The function ensures the ESRT entry matches the image_type_id in @img_info.
+ * In case of a mismatch we leave the entry unchanged.
+ *
+ * @img_info: the source image info descriptor
+ * @entry: pointer to the ESRT entry to be filled
+ * @desc_version: the version of the elements in img_info
+ * @image_type: the image type value to be set in the ESRT entry
+ * @flags: the capsule flags value to be set in the ESRT entry
+ *
+ * Return:
+ * - EFI_SUCCESS if the entry is correctly updated
+ * - EFI_INVALID_PARAMETER if entry does not match image_type_id in @img_info.
+ */
+static efi_status_t
+efi_esrt_image_info_to_entry(struct efi_firmware_image_descriptor *img_info,
+ struct efi_system_resource_entry *entry,
+ u32 desc_version, u32 image_type, u32 flags)
+{
+ if (guidcmp(&entry->fw_class, &img_info->image_type_id)) {
+ EFI_PRINT("ESRT entry %pUL mismatches img_type_id %pUL\n",
+ &entry->fw_class, &img_info->image_type_id);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ entry->fw_version = img_info->version;
+
+ entry->fw_type = image_type;
+ entry->capsule_flags = flags;
+
+ /*
+ * The field lowest_supported_image_version is only present
+ * on image info structure of version 2 or greater.
+ * See the EFI_FIRMWARE_IMAGE_DESCRIPTOR definition in UEFI.
+ */
+ if (desc_version >= 2)
+ entry->lowest_supported_fw_version =
+ img_info->lowest_supported_image_version;
+ else
+ entry->lowest_supported_fw_version = 0;
+
+ /*
+ * The fields last_attempt_version and last_attempt_status
+ * are only present on image info structure of version 3 or
+ * greater.
+ * See the EFI_FIRMWARE_IMAGE_DESCRIPTOR definition in UEFI.
+ */
+ if (desc_version >= 3) {
+ entry->last_attempt_version =
+ img_info->last_attempt_version;
+
+ entry->last_attempt_status =
+ img_info->last_attempt_status;
+ } else {
+ entry->last_attempt_version = 0;
+ entry->last_attempt_status = LAST_ATTEMPT_STATUS_SUCCESS;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ * efi_esrt_entries_to_size() - Obtain the bytes used by an ESRT
+ * datastructure with @num_entries.
+ *
+ * @num_entries: the number of entries in the ESRT.
+ *
+ * Return: the number of bytes an ESRT with @num_entries occupies in memory.
+ */
+static
+inline u32 efi_esrt_entries_to_size(u32 num_entries)
+{
+ u32 esrt_size = sizeof(struct efi_system_resource_table) +
+ num_entries * sizeof(struct efi_system_resource_entry);
+
+ return esrt_size;
+}
+
+/**
+ * efi_esrt_allocate_install() - Allocates @num_entries for the ESRT and
+ * performs basic ESRT initialization.
+ *
+ * @num_entries: the number of entries that the ESRT will hold.
+ *
+ * Return:
+ * - pointer to the ESRT if successful.
+ * - NULL otherwise.
+ */
+static
+efi_status_t efi_esrt_allocate_install(u32 num_entries)
+{
+ efi_status_t ret;
+ struct efi_system_resource_table *new_esrt;
+ u32 size = efi_esrt_entries_to_size(num_entries);
+ efi_guid_t esrt_guid = efi_esrt_guid;
+
+ /* Reserve num_pages for ESRT */
+ ret = efi_allocate_pool(EFI_BOOT_SERVICES_DATA, size,
+ (void **)&new_esrt);
+
+ if (ret != EFI_SUCCESS) {
+ EFI_PRINT("ESRT cannot allocate memory for %d entries (%d bytes)\n",
+ num_entries, efi_esrt_entries_to_size(num_entries));
+
+ return ret;
+ }
+
+ new_esrt->fw_resource_count_max = num_entries;
+ new_esrt->fw_resource_count = 0;
+ new_esrt->fw_resource_version = EFI_ESRT_VERSION;
+
+ /* Install the ESRT in the system configuration table. */
+ ret = efi_install_configuration_table(&esrt_guid, (void *)new_esrt);
+ if (ret != EFI_SUCCESS) {
+ EFI_PRINT("ESRT failed to install the ESRT in the system table\n");
+ return ret;
+ }
+
+ /* If there was a previous ESRT, deallocate its memory now. */
+ if (esrt)
+ ret = EFI_CALL(efi_free_pool(esrt));
+
+ esrt = new_esrt;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ * esrt_find_entry() - Obtain the ESRT entry for the image with GUID
+ * @img_fw_class.
+ *
+ * If the img_fw_class is not yet present in the ESRT, this function
+ * reserves the tail element of the current ESRT as the entry for that fw_class.
+ * The number of elements in the ESRT is updated in that case.
+ *
+ * @img_fw_class: the GUID of the FW image which ESRT entry we want to obtain.
+ *
+ * Return:
+ * - A pointer to the ESRT entry for the image with GUID img_fw_class,
+ * - NULL if:
+ * - there is no more space in the ESRT,
+ * - ESRT is not initialized,
+ */
+static
+struct efi_system_resource_entry *esrt_find_entry(efi_guid_t *img_fw_class)
+{
+ u32 filled_entries;
+ u32 max_entries;
+ struct efi_system_resource_entry *entry;
+
+ if (!esrt) {
+ EFI_PRINT("ESRT access before initialized\n");
+ return NULL;
+ }
+
+ filled_entries = esrt->fw_resource_count;
+ entry = esrt->entries;
+
+ /* Check if the image with img_fw_class is already in the ESRT. */
+ for (u32 idx = 0; idx < filled_entries; idx++) {
+ if (!guidcmp(&entry[idx].fw_class, img_fw_class)) {
+ EFI_PRINT("ESRT found entry for image %pUl at index %d\n",
+ img_fw_class, idx);
+ return &entry[idx];
+ }
+ }
+
+ max_entries = esrt->fw_resource_count_max;
+ /*
+ * Since the image with img_fw_class is not present in the ESRT, check
+ * if ESRT is full before appending the new entry to it.
+ */
+ if (filled_entries == max_entries) {
+ EFI_PRINT("ESRT full, this should not happen\n");
+ return NULL;
+ }
+
+ /*
+ * This is a new entry for a fw image, increment the element
+ * number in the table and set the fw_class field.
+ */
+ esrt->fw_resource_count++;
+ entry[filled_entries].fw_class = *img_fw_class;
+ EFI_PRINT("ESRT allocated new entry for image %pUl at index %d\n",
+ img_fw_class, filled_entries);
+
+ return &entry[filled_entries];
+}
+
+/**
+ * efi_esrt_add_from_fmp() - Populates a sequence of ESRT entries from the FW
+ * images in the FMP.
+ *
+ * @fmp: the FMP instance from which FW images are added to the ESRT
+ *
+ * Return:
+ * - EFI_SUCCESS if all the FW images in the FMP are added to the ESRT
+ * - Error status otherwise
+ */
+static
+efi_status_t efi_esrt_add_from_fmp(struct efi_firmware_management_protocol *fmp)
+{
+ struct efi_system_resource_entry *entry = NULL;
+ size_t info_size = 0;
+ struct efi_firmware_image_descriptor *img_info = NULL;
+ u32 desc_version;
+ u8 desc_count;
+ size_t desc_size;
+ u32 package_version;
+ u16 *package_version_name;
+ efi_status_t ret = EFI_SUCCESS;
+
+ /*
+ * TODO: set the field image_type depending on the FW image type
+ * defined in a platform basis.
+ */
+ u32 image_type = ESRT_FW_TYPE_UNKNOWN;
+
+ /* TODO: set the capsule flags as a function of the FW image type. */
+ u32 flags = 0;
+
+ ret = EFI_CALL(fmp->get_image_info(fmp, &info_size, img_info,
+ &desc_version, &desc_count,
+ &desc_size, NULL, NULL));
+
+ if (ret != EFI_BUFFER_TOO_SMALL) {
+ /*
+ * An input of info_size=0 should always lead
+ * fmp->get_image_info to return BUFFER_TO_SMALL.
+ */
+ EFI_PRINT("Erroneous FMP implementation\n");
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ret = EFI_CALL(efi_allocate_pool(EFI_BOOT_SERVICES_DATA, info_size,
+ (void **)&img_info));
+ if (ret != EFI_SUCCESS) {
+ EFI_PRINT("ESRT failed to allocate memory for image info.\n");
+ return ret;
+ }
+
+ ret = EFI_CALL(fmp->get_image_info(fmp, &info_size, img_info,
+ &desc_version, &desc_count,
+ &desc_size, &package_version,
+ &package_version_name));
+ if (ret != EFI_SUCCESS) {
+ EFI_PRINT("ESRT failed to obtain the FMP image info\n");
+ goto out;
+ }
+
+ /*
+ * Iterate over all the FW images in the FMP.
+ */
+ for (u32 desc_idx = 0; desc_idx < desc_count; desc_idx++) {
+ struct efi_firmware_image_descriptor *cur_img_info =
+ (struct efi_firmware_image_descriptor *)
+ ((uintptr_t)img_info + desc_idx * desc_size);
+
+ /*
+ * Obtain the ESRT entry for the FW image with fw_class
+ * equal to cur_img_info->image_type_id.
+ */
+ entry = esrt_find_entry(&cur_img_info->image_type_id);
+
+ if (entry) {
+ ret = efi_esrt_image_info_to_entry(cur_img_info, entry,
+ desc_version,
+ image_type, flags);
+ if (ret != EFI_SUCCESS)
+ EFI_PRINT("ESRT entry mismatches image_type\n");
+
+ } else {
+ EFI_PRINT("ESRT failed to add entry for %pUl\n",
+ &cur_img_info->image_type_id);
+ continue;
+ }
+ }
+
+out:
+ EFI_CALL(efi_free_pool(img_info));
+ return EFI_SUCCESS;
+}
+
+/**
+ * efi_esrt_populate() - Populates the ESRT entries from the FMP instances
+ * present in the system.
+ * If an ESRT already exists, the old ESRT is replaced in the system table.
+ * The memory of the old ESRT is deallocated.
+ *
+ * Return:
+ * - EFI_SUCCESS if the ESRT is correctly created
+ * - error code otherwise.
+ */
+efi_status_t efi_esrt_populate(void)
+{
+ efi_handle_t *base_handle = NULL;
+ efi_handle_t *it_handle;
+ size_t no_handles = 0;
+ struct efi_firmware_management_protocol *fmp;
+ efi_status_t ret;
+ u32 num_entries = 0;
+ struct efi_handler *handler;
+
+ /*
+ * Obtain the number of registered FMP handles.
+ */
+ ret = EFI_CALL(efi_locate_handle_buffer(BY_PROTOCOL,
+ &efi_guid_firmware_management_protocol,
+ NULL, &no_handles,
+ (efi_handle_t **)&base_handle));
+
+ if (ret != EFI_SUCCESS) {
+ EFI_PRINT("ESRT There are no FMP instances\n");
+
+ ret = efi_esrt_allocate_install(0);
+ if (ret != EFI_SUCCESS) {
+ EFI_PRINT("ESRT failed to create table with 0 entries\n");
+ return ret;
+ }
+ return EFI_SUCCESS;
+ }
+
+ EFI_PRINT("ESRT populate esrt from (%ld) available FMP handles\n",
+ no_handles);
+
+ /*
+ * Iterate over all FMPs to determine an upper bound on the number of
+ * ESRT entries.
+ */
+ it_handle = base_handle;
+ for (u32 idx = 0; idx < no_handles; idx++, it_handle++) {
+ struct efi_firmware_image_descriptor *img_info = NULL;
+ size_t info_size = 0;
+ u32 desc_version = 0;
+ u8 desc_count = 0;
+ size_t desc_size = 0;
+ u32 package_version;
+ u16 *package_version_name;
+
+ ret = efi_search_protocol(*it_handle,
+ &efi_guid_firmware_management_protocol,
+ &handler);
+
+ if (ret != EFI_SUCCESS) {
+ EFI_PRINT("ESRT Unable to find FMP handle (%d)\n",
+ idx);
+ goto out;
+ }
+ fmp = handler->protocol_interface;
+
+ ret = EFI_CALL(fmp->get_image_info(fmp, &info_size, NULL,
+ &desc_version, &desc_count,
+ &desc_size, &package_version,
+ &package_version_name));
+
+ if (ret != EFI_BUFFER_TOO_SMALL) {
+ /*
+ * An input of info_size=0 should always lead
+ * fmp->get_image_info to return BUFFER_TO_SMALL.
+ */
+ EFI_PRINT("ESRT erroneous FMP implementation\n");
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ ret = EFI_CALL(efi_allocate_pool(EFI_BOOT_SERVICES_DATA, info_size,
+ (void **)&img_info));
+ if (ret != EFI_SUCCESS) {
+ EFI_PRINT("ESRT failed to allocate memory for image info\n");
+ goto out;
+ }
+
+ /*
+ * Calls to a FMP get_image_info method do not return the
+ * desc_count value if the return status differs from EFI_SUCCESS.
+ * We need to repeat the call to get_image_info with a properly
+ * sized buffer in order to obtain the real number of images
+ * handled by the FMP.
+ */
+ ret = EFI_CALL(fmp->get_image_info(fmp, &info_size, img_info,
+ &desc_version, &desc_count,
+ &desc_size, &package_version,
+ &package_version_name));
+
+ if (ret != EFI_SUCCESS) {
+ EFI_PRINT("ESRT failed to obtain image info from FMP\n");
+ EFI_CALL(efi_free_pool(img_info));
+ goto out;
+ }
+
+ num_entries += desc_count;
+
+ EFI_CALL(efi_free_pool(img_info));
+ }
+
+ EFI_PRINT("ESRT create table with %d entries\n", num_entries);
+ /*
+ * Allocate an ESRT with the sufficient number of entries to accommodate
+ * all the FMPs in the system.
+ */
+ ret = efi_esrt_allocate_install(num_entries);
+ if (ret != EFI_SUCCESS) {
+ EFI_PRINT("ESRT failed to initialize table\n");
+ goto out;
+ }
+
+ /*
+ * Populate the ESRT entries with all existing FMP.
+ */
+ it_handle = base_handle;
+ for (u32 idx = 0; idx < no_handles; idx++, it_handle++) {
+ ret = EFI_CALL(efi_search_protocol(*it_handle,
+ &efi_guid_firmware_management_protocol,
+ &handler));
+
+ if (ret != EFI_SUCCESS) {
+ EFI_PRINT("ESRT unable to find FMP handle (%d)\n",
+ idx);
+ break;
+ }
+ fmp = handler->protocol_interface;
+
+ ret = efi_esrt_add_from_fmp(fmp);
+ if (ret != EFI_SUCCESS)
+ EFI_PRINT("ESRT failed to add FMP to the table\n");
+ }
+
+out:
+
+ EFI_CALL(efi_free_pool(base_handle));
+
+ return ret;
+}
+
+/**
+ * efi_esrt_new_fmp_notify() - Callback for the EVT_NOTIFY_SIGNAL event raised
+ * when a new FMP protocol instance is registered in the system.
+ */
+static void EFIAPI efi_esrt_new_fmp_notify(struct efi_event *event,
+ void *context)
+{
+ efi_status_t ret;
+
+ EFI_ENTRY();
+
+ ret = efi_esrt_populate();
+ if (ret != EFI_SUCCESS)
+ EFI_PRINT("ESRT failed to populate ESRT entry\n");
+
+ EFI_EXIT(ret);
+}
+
+/**
+ * efi_esrt_register() - Install the ESRT system table.
+ *
+ * Return: status code
+ */
+efi_status_t efi_esrt_register(void)
+{
+ struct efi_event *ev = NULL;
+ void *registration;
+ efi_status_t ret;
+
+ EFI_PRINT("ESRT creation start\n");
+
+ ret = efi_esrt_populate();
+ if (ret != EFI_SUCCESS) {
+ EFI_PRINT("ESRT failed to initiate the table\n");
+ return ret;
+ }
+
+ ret = EFI_CALL(efi_create_event(EVT_NOTIFY_SIGNAL, TPL_CALLBACK,
+ efi_esrt_new_fmp_notify, NULL, NULL, &ev));
+ if (ret != EFI_SUCCESS) {
+ EFI_PRINT("ESRT failed to create event\n");
+ return ret;
+ }
+
+ ret = EFI_CALL(efi_register_protocol_notify(&efi_guid_firmware_management_protocol,
+ ev, &registration));
+ if (ret != EFI_SUCCESS) {
+ EFI_PRINT("ESRT failed to register FMP callback\n");
+ return ret;
+ }
+
+ EFI_PRINT("ESRT table created\n");
+
+ return ret;
+}
diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c
index 8ece8e71ee..204105e25a 100644
--- a/lib/efi_loader/efi_file.c
+++ b/lib/efi_loader/efi_file.c
@@ -409,6 +409,45 @@ static efi_status_t efi_get_file_size(struct file_handle *fh,
return EFI_SUCCESS;
}
+/**
+ * efi_file_size() - Get the size of a file using an EFI file handle
+ *
+ * @fh: EFI file handle
+ * @size: buffer to fill in the discovered size
+ *
+ * Return: size of the file
+ */
+efi_status_t efi_file_size(struct efi_file_handle *fh, efi_uintn_t *size)
+{
+ struct efi_file_info *info = NULL;
+ efi_uintn_t bs = 0;
+ efi_status_t ret;
+
+ *size = 0;
+ ret = EFI_CALL(fh->getinfo(fh, (efi_guid_t *)&efi_file_info_guid, &bs,
+ info));
+ if (ret != EFI_BUFFER_TOO_SMALL) {
+ ret = EFI_DEVICE_ERROR;
+ goto out;
+ }
+
+ info = malloc(bs);
+ if (!info) {
+ ret = EFI_OUT_OF_RESOURCES;
+ goto out;
+ }
+ ret = EFI_CALL(fh->getinfo(fh, (efi_guid_t *)&efi_file_info_guid, &bs,
+ info));
+ if (ret != EFI_SUCCESS)
+ goto out;
+
+ *size = info->file_size;
+
+out:
+ free(info);
+ return ret;
+}
+
static efi_status_t file_read(struct file_handle *fh, u64 *buffer_size,
void *buffer)
{
diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c
index 5e401bbca2..7a3cca2793 100644
--- a/lib/efi_loader/efi_firmware.c
+++ b/lib/efi_loader/efi_firmware.c
@@ -299,7 +299,7 @@ efi_status_t EFIAPI efi_firmware_fit_set_image(
efi_status_t (*progress)(efi_uintn_t completion),
u16 **abort_reason)
{
- EFI_ENTRY("%p %d %p %ld %p %p %p\n", this, image_index, image,
+ EFI_ENTRY("%p %d %p %zd %p %p %p\n", this, image_index, image,
image_size, vendor_code, progress, abort_reason);
if (!image || image_index != 1)
@@ -414,7 +414,7 @@ efi_status_t EFIAPI efi_firmware_raw_set_image(
efi_status_t status;
efi_uintn_t capsule_payload_size;
- EFI_ENTRY("%p %d %p %ld %p %p %p\n", this, image_index, image,
+ EFI_ENTRY("%p %d %p %zd %p %p %p\n", this, image_index, image,
image_size, vendor_code, progress, abort_reason);
if (!image)
diff --git a/lib/efi_loader/efi_helper.c b/lib/efi_loader/efi_helper.c
new file mode 100644
index 0000000000..d03a736461
--- /dev/null
+++ b/lib/efi_loader/efi_helper.c
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2020, Linaro Limited
+ */
+
+#define LOG_CATEGORY LOGC_EFI
+#include <common.h>
+#include <env.h>
+#include <malloc.h>
+#include <dm.h>
+#include <fs.h>
+#include <efi_load_initrd.h>
+#include <efi_loader.h>
+#include <efi_variable.h>
+
+/**
+ * efi_create_current_boot_var() - Return Boot#### name were #### is replaced by
+ * the value of BootCurrent
+ *
+ * @var_name: variable name
+ * @var_name_size: size of var_name
+ *
+ * Return: Status code
+ */
+static efi_status_t efi_create_current_boot_var(u16 var_name[],
+ size_t var_name_size)
+{
+ efi_uintn_t boot_current_size;
+ efi_status_t ret;
+ u16 boot_current;
+ u16 *pos;
+
+ boot_current_size = sizeof(boot_current);
+ ret = efi_get_variable_int(L"BootCurrent",
+ &efi_global_variable_guid, NULL,
+ &boot_current_size, &boot_current, NULL);
+ if (ret != EFI_SUCCESS)
+ goto out;
+
+ pos = efi_create_indexed_name(var_name, var_name_size, "Boot",
+ boot_current);
+ if (!pos) {
+ ret = EFI_OUT_OF_RESOURCES;
+ goto out;
+ }
+
+out:
+ return ret;
+}
+
+/**
+ * efi_get_dp_from_boot() - Retrieve and return a device path from an EFI
+ * Boot### variable.
+ * A boot option may contain an array of device paths.
+ * We use a VenMedia() with a specific GUID to identify
+ * the usage of the array members. This function is
+ * used to extract a specific device path
+ *
+ * @guid: vendor GUID of the VenMedia() device path node identifying the
+ * device path
+ *
+ * Return: device path or NULL. Caller must free the returned value
+ */
+struct efi_device_path *efi_get_dp_from_boot(const efi_guid_t guid)
+{
+ struct efi_device_path *file_path = NULL;
+ struct efi_device_path *tmp = NULL;
+ struct efi_load_option lo;
+ void *var_value = NULL;
+ efi_uintn_t size;
+ efi_status_t ret;
+ u16 var_name[16];
+
+ ret = efi_create_current_boot_var(var_name, sizeof(var_name));
+ if (ret != EFI_SUCCESS)
+ return NULL;
+
+ var_value = efi_get_var(var_name, &efi_global_variable_guid, &size);
+ if (!var_value)
+ return NULL;
+
+ ret = efi_deserialize_load_option(&lo, var_value, &size);
+ if (ret != EFI_SUCCESS)
+ goto out;
+
+ tmp = efi_dp_from_lo(&lo, &size, guid);
+ if (!tmp)
+ goto out;
+
+ /* efi_dp_dup will just return NULL if efi_dp_next is NULL */
+ file_path = efi_dp_dup(efi_dp_next(tmp));
+
+out:
+ efi_free_pool(tmp);
+ free(var_value);
+
+ return file_path;
+}
diff --git a/lib/efi_loader/efi_load_initrd.c b/lib/efi_loader/efi_load_initrd.c
index b9ee883905..e2a8063023 100644
--- a/lib/efi_loader/efi_load_initrd.c
+++ b/lib/efi_loader/efi_load_initrd.c
@@ -3,9 +3,11 @@
* Copyright (c) 2020, Linaro Limited
*/
+#define LOG_CATEGORY LOGC_EFI
#include <common.h>
#include <efi_loader.h>
#include <efi_load_initrd.h>
+#include <efi_variable.h>
#include <fs.h>
#include <malloc.h>
#include <mapmem.h>
@@ -23,57 +25,56 @@ static const struct efi_load_file_protocol efi_lf2_protocol = {
* Device path defined by Linux to identify the handle providing the
* EFI_LOAD_FILE2_PROTOCOL used for loading the initial ramdisk.
*/
-static const struct efi_initrd_dp dp = {
+static const struct efi_initrd_dp dp_lf2_handle = {
.vendor = {
{
DEVICE_PATH_TYPE_MEDIA_DEVICE,
DEVICE_PATH_SUB_TYPE_VENDOR_PATH,
- sizeof(dp.vendor),
+ sizeof(dp_lf2_handle.vendor),
},
EFI_INITRD_MEDIA_GUID,
},
.end = {
DEVICE_PATH_TYPE_END,
DEVICE_PATH_SUB_TYPE_END,
- sizeof(dp.end),
+ sizeof(dp_lf2_handle.end),
}
};
+static efi_handle_t efi_initrd_handle;
+
/**
- * get_file_size() - retrieve the size of initramfs, set efi status on error
+ * get_initrd_fp() - Get initrd device path from a FilePathList device path
*
- * @dev: device to read from, e.g. "mmc"
- * @part: device partition, e.g. "0:1"
- * @file: name of file
- * @status: EFI exit code in case of failure
+ * @initrd_fp: the final initrd filepath
*
- * Return: size of file
+ * Return: status code. Caller must free initrd_fp
*/
-static loff_t get_file_size(const char *dev, const char *part, const char *file,
- efi_status_t *status)
+static efi_status_t get_initrd_fp(struct efi_device_path **initrd_fp)
{
- loff_t sz = 0;
- int ret;
-
- ret = fs_set_blk_dev(dev, part, FS_TYPE_ANY);
- if (ret) {
- *status = EFI_NO_MEDIA;
- goto out;
- }
+ const efi_guid_t lf2_initrd_guid = EFI_INITRD_MEDIA_GUID;
+ struct efi_device_path *dp = NULL;
- ret = fs_size(file, &sz);
- if (ret) {
- sz = 0;
- *status = EFI_NOT_FOUND;
- goto out;
- }
+ /*
+ * if bootmgr is setup with and initrd, the device path will be
+ * in the FilePathList[] of our load options in Boot####.
+ * The first device path of the multi instance device path will
+ * start with a VenMedia and the initrds will follow.
+ *
+ * If the device path is not found return EFI_INVALID_PARAMETER.
+ * We can then use this specific return value and not install the
+ * protocol, while allowing the boot to continue
+ */
+ dp = efi_get_dp_from_boot(lf2_initrd_guid);
+ if (!dp)
+ return EFI_INVALID_PARAMETER;
-out:
- return sz;
+ *initrd_fp = dp;
+ return EFI_SUCCESS;
}
/**
- * efi_load_file2initrd() - load initial RAM disk
+ * efi_load_file2_initrd() - load initial RAM disk
*
* This function implements the LoadFile service of the EFI_LOAD_FILE2_PROTOCOL
* in order to load an initial RAM disk requested by the Linux kernel stub.
@@ -93,102 +94,125 @@ efi_load_file2_initrd(struct efi_load_file_protocol *this,
struct efi_device_path *file_path, bool boot_policy,
efi_uintn_t *buffer_size, void *buffer)
{
- char *filespec;
- efi_status_t status = EFI_NOT_FOUND;
- loff_t file_sz = 0, read_sz = 0;
- char *dev, *part, *file;
- char *pos;
- int ret;
+ struct efi_device_path *initrd_fp = NULL;
+ efi_status_t ret = EFI_NOT_FOUND;
+ struct efi_file_handle *f = NULL;
+ efi_uintn_t bs;
EFI_ENTRY("%p, %p, %d, %p, %p", this, file_path, boot_policy,
buffer_size, buffer);
- filespec = strdup(CONFIG_EFI_INITRD_FILESPEC);
- if (!filespec)
- goto out;
- pos = filespec;
-
if (!this || this != &efi_lf2_protocol ||
!buffer_size) {
- status = EFI_INVALID_PARAMETER;
+ ret = EFI_INVALID_PARAMETER;
goto out;
}
- if (file_path->type != dp.end.type ||
- file_path->sub_type != dp.end.sub_type) {
- status = EFI_INVALID_PARAMETER;
+ if (file_path->type != dp_lf2_handle.end.type ||
+ file_path->sub_type != dp_lf2_handle.end.sub_type) {
+ ret = EFI_INVALID_PARAMETER;
goto out;
}
if (boot_policy) {
- status = EFI_UNSUPPORTED;
+ ret = EFI_UNSUPPORTED;
goto out;
}
- /*
- * expect a string with three space separated parts:
- *
- * * a block device type, e.g. "mmc"
- * * a device and partition identifier, e.g. "0:1"
- * * a file path on the block device, e.g. "/boot/initrd.cpio.gz"
- */
- dev = strsep(&pos, " ");
- if (!dev)
+ ret = get_initrd_fp(&initrd_fp);
+ if (ret != EFI_SUCCESS)
goto out;
- part = strsep(&pos, " ");
- if (!part)
- goto out;
- file = strsep(&pos, " ");
- if (!file)
+
+ /* Open file */
+ f = efi_file_from_path(initrd_fp);
+ if (!f) {
+ log_err("Can't find initrd specified in Boot####\n");
+ ret = EFI_NOT_FOUND;
goto out;
+ }
- file_sz = get_file_size(dev, part, file, &status);
- if (!file_sz)
+ /* Get file size */
+ ret = efi_file_size(f, &bs);
+ if (ret != EFI_SUCCESS)
goto out;
- if (!buffer || *buffer_size < file_sz) {
- status = EFI_BUFFER_TOO_SMALL;
- *buffer_size = file_sz;
+ if (!buffer || *buffer_size < bs) {
+ ret = EFI_BUFFER_TOO_SMALL;
+ *buffer_size = bs;
} else {
- ret = fs_set_blk_dev(dev, part, FS_TYPE_ANY);
- if (ret) {
- status = EFI_NO_MEDIA;
- goto out;
- }
-
- ret = fs_read(file, map_to_sysmem(buffer), 0, *buffer_size,
- &read_sz);
- if (ret || read_sz != file_sz)
- goto out;
- *buffer_size = read_sz;
-
- status = EFI_SUCCESS;
+ ret = EFI_CALL(f->read(f, &bs, (void *)(uintptr_t)buffer));
+ *buffer_size = bs;
+ }
+
+out:
+ efi_free_pool(initrd_fp);
+ if (f)
+ EFI_CALL(f->close(f));
+ return EFI_EXIT(ret);
+}
+
+/**
+ * check_initrd() - Determine if the file defined as an initrd in Boot####
+ * load_options device path is present
+ *
+ * Return: status code
+ */
+static efi_status_t check_initrd(void)
+{
+ struct efi_device_path *initrd_fp = NULL;
+ struct efi_file_handle *f;
+ efi_status_t ret;
+
+ ret = get_initrd_fp(&initrd_fp);
+ if (ret != EFI_SUCCESS)
+ goto out;
+
+ /*
+ * If the file is not found, but the file path is set, return an error
+ * and trigger the bootmgr fallback
+ */
+ f = efi_file_from_path(initrd_fp);
+ if (!f) {
+ log_err("Can't find initrd specified in Boot####\n");
+ ret = EFI_NOT_FOUND;
+ goto out;
}
+ EFI_CALL(f->close(f));
+
out:
- free(filespec);
- return EFI_EXIT(status);
+ efi_free_pool(initrd_fp);
+ return ret;
}
/**
* efi_initrd_register() - create handle for loading initial RAM disk
*
* This function creates a new handle and installs a Linux specific vendor
- * device path and an EFI_LOAD_FILE_2_PROTOCOL. Linux uses the device path
+ * device path and an EFI_LOAD_FILE2_PROTOCOL. Linux uses the device path
* to identify the handle and then calls the LoadFile service of the
- * EFI_LOAD_FILE_2_PROTOCOL to read the initial RAM disk.
+ * EFI_LOAD_FILE2_PROTOCOL to read the initial RAM disk.
*
* Return: status code
*/
efi_status_t efi_initrd_register(void)
{
- efi_handle_t efi_initrd_handle = NULL;
efi_status_t ret;
+ /*
+ * Allow the user to continue if Boot#### file path is not set for
+ * an initrd
+ */
+ ret = check_initrd();
+ if (ret == EFI_INVALID_PARAMETER)
+ return EFI_SUCCESS;
+ if (ret != EFI_SUCCESS)
+ return ret;
+
ret = EFI_CALL(efi_install_multiple_protocol_interfaces
(&efi_initrd_handle,
/* initramfs */
- &efi_guid_device_path, &dp,
+ &efi_guid_device_path, &dp_lf2_handle,
/* LOAD_FILE2 */
&efi_guid_load_file2_protocol,
(void *)&efi_lf2_protocol,
@@ -196,3 +220,17 @@ efi_status_t efi_initrd_register(void)
return ret;
}
+
+/**
+ * efi_initrd_deregister() - delete the handle for loading initial RAM disk
+ *
+ * This will delete the handle containing the Linux specific vendor device
+ * path and EFI_LOAD_FILE2_PROTOCOL for loading an initrd
+ *
+ * Return: status code
+ */
+void efi_initrd_deregister(void)
+{
+ efi_delete_handle(efi_initrd_handle);
+ efi_initrd_handle = NULL;
+}
diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c
index b1c5125032..3c5cf9a435 100644
--- a/lib/efi_loader/efi_setup.c
+++ b/lib/efi_loader/efi_setup.c
@@ -227,6 +227,12 @@ efi_status_t efi_init_obj_list(void)
if (ret != EFI_SUCCESS)
goto out;
+ if (IS_ENABLED(CONFIG_EFI_ESRT)) {
+ ret = efi_esrt_register();
+ if (ret != EFI_SUCCESS)
+ goto out;
+ }
+
if (IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL)) {
ret = efi_tcg2_register();
if (ret != EFI_SUCCESS)
diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
index 797d6eb134..09046844c7 100644
--- a/lib/efi_loader/efi_tcg2.c
+++ b/lib/efi_loader/efi_tcg2.c
@@ -13,6 +13,7 @@
#include <efi_loader.h>
#include <efi_tcg2.h>
#include <log.h>
+#include <version.h>
#include <tpm-v2.h>
#include <u-boot/sha1.h>
#include <u-boot/sha256.h>
@@ -958,6 +959,23 @@ out:
}
/**
+ * tcg2_uninit - remove the final event table and free efi memory on failures
+ */
+void tcg2_uninit(void)
+{
+ efi_status_t ret;
+
+ ret = efi_install_configuration_table(&efi_guid_final_events, NULL);
+ if (ret != EFI_SUCCESS)
+ log_err("Failed to delete final events config table\n");
+
+ efi_free_pool(event_log.buffer);
+ event_log.buffer = NULL;
+ efi_free_pool(event_log.final_buffer);
+ event_log.final_buffer = NULL;
+}
+
+/**
* create_final_event() - Create the final event and install the config
* defined by the TCG EFI spec
*/
@@ -983,10 +1001,6 @@ static efi_status_t create_final_event(void)
event_log.final_pos = sizeof(*final_event);
ret = efi_install_configuration_table(&efi_guid_final_events,
final_event);
- if (ret != EFI_SUCCESS)
- goto out;
-
- return EFI_SUCCESS;
out:
return ret;
}
@@ -1041,6 +1055,40 @@ static efi_status_t efi_init_event_log(void)
event_log.last_event_size = event_log.pos;
ret = create_final_event();
+ if (ret != EFI_SUCCESS)
+ goto out;
+
+ return EFI_SUCCESS;
+out:
+ tcg2_uninit();
+ return ret;
+}
+
+/**
+ * efi_append_scrtm_version - Append an S-CRTM EV_S_CRTM_VERSION event on the
+ * eventlog and extend the PCRs
+ *
+ * @dev: TPM device
+ *
+ * @Return: status code
+ */
+static efi_status_t efi_append_scrtm_version(struct udevice *dev)
+{
+ struct tpml_digest_values digest_list;
+ u8 ver[] = U_BOOT_VERSION_STRING;
+ const int pcr_index = 0;
+ efi_status_t ret;
+
+ ret = tcg2_create_digest(ver, sizeof(ver), &digest_list);
+ if (ret != EFI_SUCCESS)
+ goto out;
+
+ ret = tcg2_pcr_extend(dev, pcr_index, &digest_list);
+ if (ret != EFI_SUCCESS)
+ goto out;
+
+ ret = tcg2_agile_log_append(pcr_index, EV_S_CRTM_VERSION, &digest_list,
+ sizeof(ver), ver);
out:
return ret;
@@ -1055,23 +1103,34 @@ out:
*/
efi_status_t efi_tcg2_register(void)
{
- efi_status_t ret;
+ efi_status_t ret = EFI_SUCCESS;
struct udevice *dev;
ret = platform_get_tpm2_device(&dev);
if (ret != EFI_SUCCESS) {
log_warning("Unable to find TPMv2 device\n");
- return EFI_SUCCESS;
+ ret = EFI_SUCCESS;
+ goto out;
}
ret = efi_init_event_log();
if (ret != EFI_SUCCESS)
- return ret;
+ goto fail;
+
+ ret = efi_append_scrtm_version(dev);
+ if (ret != EFI_SUCCESS)
+ goto out;
ret = efi_add_protocol(efi_root, &efi_guid_tcg2_protocol,
(void *)&efi_tcg2_protocol);
- if (ret != EFI_SUCCESS)
+ if (ret != EFI_SUCCESS) {
log_err("Cannot install EFI_TCG2_PROTOCOL\n");
+ goto fail;
+ }
+out:
+ return ret;
+fail:
+ tcg2_uninit();
return ret;
}
diff --git a/lib/efi_loader/efi_var_common.c b/lib/efi_loader/efi_var_common.c
index 1c7459266a..b11ed91a74 100644
--- a/lib/efi_loader/efi_var_common.c
+++ b/lib/efi_loader/efi_var_common.c
@@ -9,6 +9,7 @@
#include <common.h>
#include <efi_loader.h>
#include <efi_variable.h>
+#include <stdlib.h>
enum efi_secure_mode {
EFI_MODE_SETUP,
@@ -343,3 +344,35 @@ enum efi_auth_var_type efi_auth_var_get_type(u16 *name, const efi_guid_t *guid)
}
return EFI_AUTH_VAR_NONE;
}
+
+/**
+ * efi_get_var() - read value of an EFI variable
+ *
+ * @name: variable name
+ * @start: vendor GUID
+ * @size: size of allocated buffer
+ *
+ * Return: buffer with variable data or NULL
+ */
+void *efi_get_var(u16 *name, const efi_guid_t *vendor, efi_uintn_t *size)
+{
+ efi_status_t ret;
+ void *buf = NULL;
+
+ *size = 0;
+ ret = efi_get_variable_int(name, vendor, NULL, size, buf, NULL);
+ if (ret == EFI_BUFFER_TOO_SMALL) {
+ buf = malloc(*size);
+ if (!buf)
+ return NULL;
+ ret = efi_get_variable_int(name, vendor, NULL, size, buf, NULL);
+ }
+
+ if (ret != EFI_SUCCESS) {
+ free(buf);
+ *size = 0;
+ return NULL;
+ }
+
+ return buf;
+}
diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile
index b02fd56e0a..aa71d0995c 100644
--- a/lib/efi_selftest/Makefile
+++ b/lib/efi_selftest/Makefile
@@ -61,7 +61,6 @@ obj-$(CONFIG_CPU_V7) += efi_selftest_unaligned.o
obj-$(CONFIG_EFI_LOADER_HII) += efi_selftest_hii.o
obj-$(CONFIG_EFI_RNG_PROTOCOL) += efi_selftest_rng.o
obj-$(CONFIG_EFI_GET_TIME) += efi_selftest_rtc.o
-obj-$(CONFIG_EFI_LOAD_FILE2_INITRD) += efi_selftest_load_initrd.o
obj-$(CONFIG_EFI_TCG2_PROTOCOL) += efi_selftest_tcg2.o
ifeq ($(CONFIG_GENERATE_ACPI_TABLE),)
@@ -72,6 +71,8 @@ ifeq ($(CONFIG_BLK)$(CONFIG_DOS_PARTITION),yy)
obj-y += efi_selftest_block_device.o
endif
+obj-$(CONFIG_EFI_ESRT) += efi_selftest_esrt.o
+
targets += \
efi_miniapp_file_image_exception.h \
efi_miniapp_file_image_exit.h \
diff --git a/lib/efi_selftest/efi_selftest.c b/lib/efi_selftest/efi_selftest.c
index b8eed048c2..39ee2edf5d 100644
--- a/lib/efi_selftest/efi_selftest.c
+++ b/lib/efi_selftest/efi_selftest.c
@@ -160,7 +160,7 @@ static bool need_reset(const u16 *testname)
if (testname && efi_st_strcmp_16_8(testname, test->name))
continue;
if (test->phase == EFI_SETUP_BEFORE_BOOTTIME_EXIT ||
- test->phase == EFI_SETUP_AFTER_BOOTTIME_EXIT)
+ test->phase == EFI_SETTING_VIRTUAL_ADDRESS_MAP)
return true;
}
return false;
@@ -327,15 +327,16 @@ efi_status_t EFIAPI efi_selftest(efi_handle_t image_handle,
/* Execute mixed tests */
efi_st_do_tests(testname, EFI_SETUP_BEFORE_BOOTTIME_EXIT,
EFI_ST_SETUP, &failures);
+ efi_st_do_tests(testname, EFI_SETTING_VIRTUAL_ADDRESS_MAP,
+ EFI_ST_SETUP, &failures);
efi_st_exit_boot_services();
efi_st_do_tests(testname, EFI_SETUP_BEFORE_BOOTTIME_EXIT,
EFI_ST_EXECUTE | EFI_ST_TEARDOWN, &failures);
-
- /* Execute runtime tests */
- efi_st_do_tests(testname, EFI_SETUP_AFTER_BOOTTIME_EXIT,
- EFI_ST_SETUP | EFI_ST_EXECUTE | EFI_ST_TEARDOWN,
+ /* Execute test setting the virtual address map */
+ efi_st_do_tests(testname, EFI_SETTING_VIRTUAL_ADDRESS_MAP,
+ EFI_ST_EXECUTE | EFI_ST_TEARDOWN,
&failures);
/* Give feedback */
diff --git a/lib/efi_selftest/efi_selftest_esrt.c b/lib/efi_selftest/efi_selftest_esrt.c
new file mode 100644
index 0000000000..99251f22a5
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_esrt.c
@@ -0,0 +1,291 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Test ESRT tables support
+ *
+ * Copyright (C) 2021 Arm Ltd.
+ */
+#include <common.h>
+#include <efi_loader.h>
+#include <efi_selftest.h>
+
+// This value must not exceed 255.
+// An FMP cannot contain more than 255 FW images.
+#define TEST_ESRT_NUM_ENTRIES 255
+
+static
+struct efi_firmware_image_descriptor static_img_info[TEST_ESRT_NUM_ENTRIES];
+
+static const struct efi_system_table *local_systable;
+
+static efi_handle_t fmp_handle;
+
+static const efi_guid_t efi_fmp_guid =
+ EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GUID;
+
+static void efi_test_esrt_init_info(void)
+{
+ for (int idx = 0; idx < TEST_ESRT_NUM_ENTRIES; idx++) {
+ static_img_info[idx].image_index = idx;
+
+ // Note: the 16 byte value present in
+ // static_img_info[idx].image_type_id is not strictly a GUID.
+ // The value is used for the sake of code testing.
+ static_img_info[idx].image_type_id.b[0] = idx;
+
+ static_img_info[idx].image_id = 0;
+ static_img_info[idx].image_id_name = NULL;
+ static_img_info[idx].version = 0;
+ static_img_info[idx].version_name = NULL;
+ static_img_info[idx].size = 0;
+ static_img_info[idx].lowest_supported_image_version = 1;
+ static_img_info[idx].last_attempt_version = 2;
+ static_img_info[idx].last_attempt_status = 3;
+ static_img_info[idx].hardware_instance = 1;
+ }
+}
+
+static efi_status_t
+EFIAPI efi_test_fmp_get_image_info(struct efi_firmware_management_protocol *this,
+ efi_uintn_t *image_info_size,
+ struct efi_firmware_image_descriptor *image_info,
+ u32 *descriptor_version,
+ u8 *descriptor_count,
+ efi_uintn_t *descriptor_size,
+ u32 *package_version,
+ u16 **package_version_name)
+{
+ efi_status_t ret = EFI_SUCCESS;
+
+ if (!image_info_size)
+ return EFI_INVALID_PARAMETER;
+
+ if (descriptor_version)
+ *descriptor_version = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION;
+ if (descriptor_count)
+ *descriptor_count = TEST_ESRT_NUM_ENTRIES;
+ if (descriptor_size)
+ *descriptor_size = sizeof(*image_info);
+ if (package_version)
+ *package_version = 0xffffffff;
+ if (package_version_name)
+ *package_version_name = NULL;
+
+ if (*image_info_size < sizeof(*image_info)) {
+ *image_info_size = *descriptor_size * *descriptor_count;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ for (int idx = 0; idx < TEST_ESRT_NUM_ENTRIES; idx++)
+ image_info[idx] = static_img_info[idx];
+
+ return ret;
+}
+
+static struct efi_firmware_management_protocol efi_test_fmp = {
+ .get_image_info = efi_test_fmp_get_image_info,
+ .get_image = NULL,
+ .set_image = NULL,
+ .check_image = NULL,
+ .get_package_info = NULL,
+ .set_package_info = NULL,
+};
+
+static void *lib_test_get_esrt(void)
+{
+ for (int idx = 0; idx < local_systable->nr_tables; idx++)
+ if (!guidcmp(&efi_esrt_guid, &local_systable->tables[idx].guid))
+ return local_systable->tables[idx].table;
+
+ return NULL;
+}
+
+/**
+ * lib_test_check_uuid_entry: Find an ESRT entry for which the fw_calss field matches
+ * the image_type_id in the @img_info.
+ * Ensure that all of the field in the ESRT entry have the same value as the corresponding
+ * fields in the @img_info.
+ *
+ * @esrt: pointer to the ESRT
+ * @img_info: an image_info_descriptor output by the FMP get_image_info
+ *
+ * @return: true if matching ESRT entry is found and if all the ESRT entry fields match the
+ * corresponding @img_info fields.
+ */
+static bool lib_test_check_uuid_entry(struct efi_system_resource_table *esrt,
+ struct efi_firmware_image_descriptor
+ *img_info)
+{
+ const u32 filled_entries = esrt->fw_resource_count;
+ struct efi_system_resource_entry *entry = esrt->entries;
+
+ for (u32 idx = 0; idx < filled_entries; idx++) {
+ if (!guidcmp(&entry[idx].fw_class, &img_info->image_type_id)) {
+ if (entry[idx].fw_version != img_info->version) {
+ efi_st_error("ESRT field mismatch for entry with fw_class=%pUl\n",
+ &img_info->image_type_id);
+ return false;
+ }
+
+ if (entry[idx].lowest_supported_fw_version !=
+ img_info->lowest_supported_image_version) {
+ efi_st_error("ESRT field mismatch for entry with fw_class=%pUl\n",
+ &img_info->image_type_id);
+ return false;
+ }
+
+ if (entry[idx].last_attempt_version !=
+ img_info->last_attempt_version) {
+ efi_st_error("ESRT field mismatch for entry with fw_class=%pUl\n",
+ &img_info->image_type_id);
+ return false;
+ }
+
+ if (entry[idx].last_attempt_status !=
+ img_info->last_attempt_status) {
+ efi_st_error("ESRT field mismatch for entry with fw_class=%pUl\n",
+ &img_info->image_type_id);
+ return false;
+ }
+
+ /*
+ * The entry with fw_class = img_uuid matches with the
+ * remainder fmp input.
+ */
+ return true;
+ }
+ }
+
+ /* There exists no entry with fw_class equal to img_uuid in the ESRT. */
+ efi_st_error("ESRT no entry with fw_class= %pUl\n", &img_info->image_type_id);
+
+ return false;
+}
+
+/*
+ * Setup unit test.
+ *
+ * Initialize the test FMP datastructure.
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+ const struct efi_system_table *systable)
+{
+ local_systable = systable;
+
+ efi_test_esrt_init_info();
+
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Tear down unit test.
+ *
+ * Uninstall the test FMP.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int teardown(void)
+{
+ efi_status_t ret = EFI_SUCCESS;
+ struct efi_boot_services *bt;
+
+ bt = local_systable->boottime;
+
+ if (!bt) {
+ efi_st_error("Cannot find boottime services structure\n");
+ return EFI_ST_FAILURE;
+ }
+
+ ret = bt->uninstall_multiple_protocol_interfaces
+ (fmp_handle, &efi_fmp_guid,
+ &efi_test_fmp, NULL);
+
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to uninstall FMP\n");
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Perform the test
+ *
+ * The test consists of the following steps:
+ *
+ * 1) Obtain the ESRT
+ * 2) Record the number of ESRT entries prior to test start
+ * 3) Install the test FMP
+ * 4) Re-obtain the ESRT (the ESRT pointer may have changed with the FMP install)
+ * 5) verify that the ESRT entries have increased by the number of entries in the
+ * test FMP.
+ * 6) Traverse all the elements used as the test FMP input and verify that each
+ * has a corresponding ESRT entry and that the fields are correctly set.
+ *
+ * The failure of any of the above steps results in a test failure.
+ *
+ */
+static int execute(void)
+{
+ struct efi_system_resource_table *esrt;
+ efi_status_t ret = EFI_SUCCESS;
+ u32 base_entry_count;
+ u32 entry_delta;
+ struct efi_boot_services *bt;
+
+ bt = local_systable->boottime;
+
+ if (!bt) {
+ efi_st_error("Cannot find boottime services structure\n");
+ return EFI_ST_FAILURE;
+ }
+
+ esrt = lib_test_get_esrt();
+ if (!esrt) {
+ efi_st_error("ESRT table not present\n");
+ return EFI_ST_FAILURE;
+ }
+ base_entry_count = esrt->fw_resource_count;
+
+ ret = bt->install_multiple_protocol_interfaces(&fmp_handle,
+ &efi_fmp_guid,
+ &efi_test_fmp,
+ NULL);
+
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to install FMP\n");
+ return EFI_ST_FAILURE;
+ }
+
+ esrt = lib_test_get_esrt();
+ if (!esrt) {
+ efi_st_error("ESRT table not present\n");
+ return EFI_ST_FAILURE;
+ }
+
+ entry_delta = esrt->fw_resource_count - base_entry_count;
+ if (entry_delta != TEST_ESRT_NUM_ENTRIES) {
+ efi_st_error("ESRT mismatch in new entry count (%d), expected (%d).\n",
+ entry_delta, TEST_ESRT_NUM_ENTRIES);
+ return EFI_ST_FAILURE;
+ }
+
+ for (u32 idx = 0; idx < TEST_ESRT_NUM_ENTRIES; idx++)
+ if (!lib_test_check_uuid_entry(esrt, &static_img_info[idx])) {
+ efi_st_error("ESRT entry mismatch\n");
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(esrt) = {
+ .name = "esrt",
+ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+ .teardown = teardown,
+};
diff --git a/lib/efi_selftest/efi_selftest_load_initrd.c b/lib/efi_selftest/efi_selftest_load_initrd.c
deleted file mode 100644
index f591dcd211..0000000000
--- a/lib/efi_selftest/efi_selftest_load_initrd.c
+++ /dev/null
@@ -1,221 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * efi_selftest_load_initrd
- *
- * Copyright (c) 2020 Ilias Apalodimas <ilias.apalodimas@linaro.org>
- *
- * This test checks the FileLoad2 protocol.
- * A known file is read from the file system and verified.
- *
- * An example usage - given a file image with a file system in partition 1
- * holding file initrd - is:
- *
- * * Configure the sandbox with
- *
- * CONFIG_EFI_SELFTEST=y
- * CONFIG_EFI_LOAD_FILE2_INITRD=y
- * CONFIG_EFI_INITRD_FILESPEC="host 0:1 initrd"
- *
- * * Run ./u-boot and execute
- *
- * host bind 0 image
- * setenv efi_selftest load initrd
- * bootefi selftest
- *
- * This would provide a test output like:
- *
- * Testing EFI API implementation
- *
- * Selected test: 'load initrd'
- *
- * Setting up 'load initrd'
- * Setting up 'load initrd' succeeded
- *
- * Executing 'load initrd'
- * Loaded 12378613 bytes
- * CRC32 2997478465
- *
- * Now the size and CRC32 can be compared to the provided file.
- */
-
-#include <efi_selftest.h>
-#include <efi_loader.h>
-#include <efi_load_initrd.h>
-
-static struct efi_boot_services *boottime;
-
-static struct efi_initrd_dp dp = {
- .vendor = {
- {
- DEVICE_PATH_TYPE_MEDIA_DEVICE,
- DEVICE_PATH_SUB_TYPE_VENDOR_PATH,
- sizeof(dp.vendor),
- },
- EFI_INITRD_MEDIA_GUID,
- },
- .end = {
- DEVICE_PATH_TYPE_END,
- DEVICE_PATH_SUB_TYPE_END,
- sizeof(dp.end),
- }
-};
-
-static struct efi_initrd_dp dp_invalid = {
- .vendor = {
- {
- DEVICE_PATH_TYPE_MEDIA_DEVICE,
- DEVICE_PATH_SUB_TYPE_VENDOR_PATH,
- sizeof(dp.vendor),
- },
- EFI_INITRD_MEDIA_GUID,
- },
- .end = {
- 0x8f, /* invalid */
- 0xfe, /* invalid */
- sizeof(dp.end),
- }
-};
-
-static int setup(const efi_handle_t handle,
- const struct efi_system_table *systable)
-{
- boottime = systable->boottime;
-
- return EFI_ST_SUCCESS;
-}
-
-static int execute(void)
-{
- 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;
-
- memset(buffer, 0, sizeof(buffer));
-
- dp2 = (struct efi_device_path *)&dp;
- status = boottime->locate_device_path(&efi_guid_load_file2_protocol,
- &dp2, &handle);
- if (status != EFI_SUCCESS) {
- efi_st_error("Unable to locate device path\n");
- return EFI_ST_FAILURE;
- }
-
- status = boottime->handle_protocol(handle,
- &efi_guid_load_file2_protocol,
- (void **)&lf2);
- if (status != EFI_SUCCESS) {
- efi_st_error("Unable to locate protocol\n");
- return EFI_ST_FAILURE;
- }
-
- /* Case 1:
- * buffer_size can't be NULL
- * protocol can't be NULL
- */
- status = lf2->load_file(lf2, dp2, false, NULL, &buffer);
- if (status != EFI_INVALID_PARAMETER) {
- efi_st_error("Buffer size can't be NULL\n");
- return EFI_ST_FAILURE;
- }
- buffer_size = sizeof(buffer);
- status = lf2->load_file(NULL, dp2, false, &buffer_size, &buffer);
- if (status != EFI_INVALID_PARAMETER) {
- efi_st_error("Protocol can't be NULL\n");
- return EFI_ST_FAILURE;
- }
-
- /*
- * Case 2: Match end node type/sub-type on device path
- */
- dp2_invalid = (struct efi_device_path *)&dp_invalid;
- buffer_size = sizeof(buffer);
- status = lf2->load_file(lf2, dp2_invalid, false, &buffer_size, &buffer);
- if (status != EFI_INVALID_PARAMETER) {
- efi_st_error("Invalid device path type must return EFI_INVALID_PARAMETER\n");
- return EFI_ST_FAILURE;
- }
-
- status = lf2->load_file(lf2, dp2_invalid, false, &buffer_size, &buffer);
- if (status != EFI_INVALID_PARAMETER) {
- efi_st_error("Invalid device path sub-type must return EFI_INVALID_PARAMETER\n");
- return EFI_ST_FAILURE;
- }
-
- /*
- * Case 3:
- * BootPolicy 'true' must return EFI_UNSUPPORTED
- */
- buffer_size = sizeof(buffer);
- status = lf2->load_file(lf2, dp2, true, &buffer_size, &buffer);
- if (status != EFI_UNSUPPORTED) {
- efi_st_error("BootPolicy true must return EFI_UNSUPPORTED\n");
- return EFI_ST_FAILURE;
- }
-
- /*
- * Case: Pass buffer size as zero, firmware must return
- * EFI_BUFFER_TOO_SMALL and an appropriate size
- */
- buffer_size = 0;
- status = lf2->load_file(lf2, dp2, false, &buffer_size, NULL);
- if (status != EFI_BUFFER_TOO_SMALL || !buffer_size) {
- efi_st_printf("buffer_size: %u\n", (unsigned int)buffer_size);
- efi_st_printf("status: %x\n", (unsigned int)status);
- efi_st_error("Buffer size not updated\n");
- return EFI_ST_FAILURE;
- }
-
- /*
- * Case: Pass buffer size as smaller than the file_size,
- * firmware must return * EFI_BUFFER_TOO_SMALL and an appropriate size
- */
- buffer_size = 1;
- status = lf2->load_file(lf2, dp2, false, &buffer_size, &buffer);
- if (status != EFI_BUFFER_TOO_SMALL || buffer_size <= 1) {
- efi_st_error("Buffer size not updated\n");
- return EFI_ST_FAILURE;
- }
-
- status = boottime->allocate_pool(EFI_BOOT_SERVICES_DATA, buffer_size,
- &buf);
- if (status != EFI_SUCCESS) {
- efi_st_error("Cannot allocate buffer\n");
- return EFI_ST_FAILURE;
- }
-
- /* Case: Pass correct buffer, load the file and verify checksum*/
- status = lf2->load_file(lf2, dp2, false, &buffer_size, buf);
- if (status != EFI_SUCCESS) {
- efi_st_error("Loading initrd failed\n");
- return EFI_ST_FAILURE;
- }
-
- efi_st_printf("Loaded %u bytes\n", (unsigned int)buffer_size);
- status = boottime->calculate_crc32(buf, buffer_size, &crc32);
- if (status != EFI_SUCCESS) {
- efi_st_error("Could not determine CRC32\n");
- return EFI_ST_FAILURE;
- }
- efi_st_printf("CRC32 %.8x\n", (unsigned int)crc32);
-
- status = boottime->free_pool(buf);
- if (status != EFI_SUCCESS) {
- efi_st_error("Cannot free buffer\n");
- return EFI_ST_FAILURE;
- }
-
- return EFI_ST_SUCCESS;
-}
-
-EFI_UNIT_TEST(load_initrd) = {
- .name = "load initrd",
- .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
- .setup = setup,
- .execute = execute,
- .on_request = true,
-};
diff --git a/lib/efi_selftest/efi_selftest_set_virtual_address_map.c b/lib/efi_selftest/efi_selftest_set_virtual_address_map.c
index b097a81136..8e2e8ba172 100644
--- a/lib/efi_selftest/efi_selftest_set_virtual_address_map.c
+++ b/lib/efi_selftest/efi_selftest_set_virtual_address_map.c
@@ -201,7 +201,7 @@ static int execute(void)
EFI_UNIT_TEST(virtaddrmap) = {
.name = "virtual address map",
- .phase = EFI_SETUP_BEFORE_BOOTTIME_EXIT,
+ .phase = EFI_SETTING_VIRTUAL_ADDRESS_MAP,
.setup = setup,
.execute = execute,
};
diff --git a/lib/efi_selftest/initrddump.c b/lib/efi_selftest/initrddump.c
index c23a05c718..325951b498 100644
--- a/lib/efi_selftest/initrddump.c
+++ b/lib/efi_selftest/initrddump.c
@@ -272,7 +272,7 @@ static efi_status_t get_initrd(void **initrd, efi_uintn_t *initrd_size)
error(L"Out of memory\r\n");
return ret;
}
- *initrd = (void *)buffer;
+ *initrd = (void *)(uintptr_t)buffer;
ret = load_file2_prot->load_file(load_file2_prot, dp, false,
initrd_size, *initrd);
if (ret != EFI_SUCCESS) {
diff --git a/test/py/tests/test_efi_capsule/test_capsule_firmware.py b/test/py/tests/test_efi_capsule/test_capsule_firmware.py
index f006fa95d6..160a64a14b 100644
--- a/test/py/tests/test_efi_capsule/test_capsule_firmware.py
+++ b/test/py/tests/test_efi_capsule/test_capsule_firmware.py
@@ -39,7 +39,7 @@ class TestEfiCapsuleFirmwareFit(object):
with u_boot_console.log.section('Test Case 1-a, before reboot'):
output = u_boot_console.run_command_list([
'host bind 0 %s' % disk_img,
- 'efidebug boot add 1 TEST host 0:1 /helloworld.efi ""',
+ 'efidebug boot add -b 1 TEST host 0:1 /helloworld.efi ""',
'efidebug boot order 1',
'env set -e OsIndications',
'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
@@ -114,7 +114,7 @@ class TestEfiCapsuleFirmwareFit(object):
with u_boot_console.log.section('Test Case 2-a, before reboot'):
output = u_boot_console.run_command_list([
'host bind 0 %s' % disk_img,
- 'efidebug boot add 1 TEST host 0:1 /helloworld.efi ""',
+ 'efidebug boot add -b 1 TEST host 0:1 /helloworld.efi ""',
'efidebug boot order 1',
'env set -e -nv -bs -rt OsIndications =0x0000000000000004',
'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
@@ -188,7 +188,7 @@ class TestEfiCapsuleFirmwareFit(object):
with u_boot_console.log.section('Test Case 3-a, before reboot'):
output = u_boot_console.run_command_list([
'host bind 0 %s' % disk_img,
- 'efidebug boot add 1 TEST host 0:1 /helloworld.efi ""',
+ 'efidebug boot add -b 1 TEST host 0:1 /helloworld.efi ""',
'efidebug boot order 1',
'env set -e -nv -bs -rt OsIndications =0x0000000000000004',
'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
@@ -229,6 +229,14 @@ class TestEfiCapsuleFirmwareFit(object):
output = u_boot_console.run_command(
'env print -e -all Capsule0000')
+ output = u_boot_console.run_command_list(['efidebug capsule esrt'])
+
+ # ensure that EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID is in the ESRT.
+ assert 'AE13FF2D-9AD4-4E25-9AC8-6D80B3B22147' in ''.join(output)
+
+ # ensure that EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID is in the ESRT.
+ assert 'E2BB9C06-70E9-4B14-97A3-5A7913176E3F' in ''.join(output)
+
output = u_boot_console.run_command_list([
'host bind 0 %s' % disk_img,
'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
diff --git a/test/py/tests/test_efi_secboot/test_signed.py b/test/py/tests/test_efi_secboot/test_signed.py
index 863685e215..75f5ea7723 100644
--- a/test/py/tests/test_efi_secboot/test_signed.py
+++ b/test/py/tests/test_efi_secboot/test_signed.py
@@ -28,7 +28,7 @@ class TestEfiSignedImage(object):
# Test Case 1a, run signed image if no PK
output = u_boot_console.run_command_list([
'host bind 0 %s' % disk_img,
- 'efidebug boot add 1 HELLO1 host 0:1 /helloworld.efi.signed ""',
+ 'efidebug boot add -b 1 HELLO1 host 0:1 /helloworld.efi.signed ""',
'efidebug boot next 1',
'bootefi bootmgr'])
assert 'Hello, world!' in ''.join(output)
@@ -36,7 +36,7 @@ class TestEfiSignedImage(object):
with u_boot_console.log.section('Test Case 1b'):
# Test Case 1b, run unsigned image if no PK
output = u_boot_console.run_command_list([
- 'efidebug boot add 2 HELLO2 host 0:1 /helloworld.efi ""',
+ 'efidebug boot add -b 2 HELLO2 host 0:1 /helloworld.efi ""',
'efidebug boot next 2',
'bootefi bootmgr'])
assert 'Hello, world!' in ''.join(output)
@@ -58,13 +58,13 @@ class TestEfiSignedImage(object):
'setenv -e -nv -bs -rt -at -i 4000000:$filesize PK'])
assert 'Failed to set EFI variable' not in ''.join(output)
output = u_boot_console.run_command_list([
- 'efidebug boot add 1 HELLO1 host 0:1 /helloworld.efi.signed ""',
+ 'efidebug boot add -b 1 HELLO1 host 0:1 /helloworld.efi.signed ""',
'efidebug boot next 1',
'efidebug test bootmgr'])
assert('\'HELLO1\' failed' in ''.join(output))
assert('efi_start_image() returned: 26' in ''.join(output))
output = u_boot_console.run_command_list([
- 'efidebug boot add 2 HELLO2 host 0:1 /helloworld.efi ""',
+ 'efidebug boot add -b 2 HELLO2 host 0:1 /helloworld.efi ""',
'efidebug boot next 2',
'efidebug test bootmgr'])
assert '\'HELLO2\' failed' in ''.join(output)
@@ -104,7 +104,7 @@ class TestEfiSignedImage(object):
'setenv -e -nv -bs -rt -at -i 4000000:$filesize PK'])
assert 'Failed to set EFI variable' not in ''.join(output)
output = u_boot_console.run_command_list([
- 'efidebug boot add 1 HELLO host 0:1 /helloworld.efi.signed ""',
+ 'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi.signed ""',
'efidebug boot next 1',
'efidebug test bootmgr'])
assert '\'HELLO\' failed' in ''.join(output)
@@ -142,7 +142,7 @@ class TestEfiSignedImage(object):
'setenv -e -nv -bs -rt -at -i 4000000:$filesize PK'])
assert 'Failed to set EFI variable' not in ''.join(output)
output = u_boot_console.run_command_list([
- 'efidebug boot add 1 HELLO host 0:1 /helloworld.efi.signed ""',
+ 'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi.signed ""',
'efidebug boot next 1',
'efidebug test bootmgr'])
assert '\'HELLO\' failed' in ''.join(output)
@@ -169,7 +169,7 @@ class TestEfiSignedImage(object):
'setenv -e -nv -bs -rt -at -i 4000000:$filesize PK'])
assert 'Failed to set EFI variable' not in ''.join(output)
output = u_boot_console.run_command_list([
- 'efidebug boot add 1 HELLO host 0:1 /helloworld.efi.signed_2sigs ""',
+ 'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi.signed_2sigs ""',
'efidebug boot next 1',
'efidebug test bootmgr'])
assert 'Hello, world!' in ''.join(output)
@@ -227,7 +227,7 @@ class TestEfiSignedImage(object):
'setenv -e -nv -bs -rt -at -i 4000000:$filesize PK'])
assert 'Failed to set EFI variable' not in ''.join(output)
output = u_boot_console.run_command_list([
- 'efidebug boot add 1 HELLO host 0:1 /helloworld.efi.signed ""',
+ 'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi.signed ""',
'efidebug boot next 1',
'bootefi bootmgr'])
assert 'Hello, world!' in ''.join(output)
diff --git a/test/py/tests/test_efi_secboot/test_signed_intca.py b/test/py/tests/test_efi_secboot/test_signed_intca.py
index 70d6be00e8..0849572a51 100644
--- a/test/py/tests/test_efi_secboot/test_signed_intca.py
+++ b/test/py/tests/test_efi_secboot/test_signed_intca.py
@@ -39,7 +39,7 @@ class TestEfiSignedImageIntca(object):
assert 'Failed to set EFI variable' not in ''.join(output)
output = u_boot_console.run_command_list([
- 'efidebug boot add 1 HELLO_a host 0:1 /helloworld.efi.signed_a ""',
+ 'efidebug boot add -b 1 HELLO_a host 0:1 /helloworld.efi.signed_a ""',
'efidebug boot next 1',
'efidebug test bootmgr'])
assert '\'HELLO_a\' failed' in ''.join(output)
@@ -48,7 +48,7 @@ class TestEfiSignedImageIntca(object):
with u_boot_console.log.section('Test Case 1b'):
# Test Case 1b, signed and authenticated by root CA
output = u_boot_console.run_command_list([
- 'efidebug boot add 2 HELLO_ab host 0:1 /helloworld.efi.signed_ab ""',
+ 'efidebug boot add -b 2 HELLO_ab host 0:1 /helloworld.efi.signed_ab ""',
'efidebug boot next 2',
'bootefi bootmgr'])
assert 'Hello, world!' in ''.join(output)
@@ -70,7 +70,7 @@ class TestEfiSignedImageIntca(object):
assert 'Failed to set EFI variable' not in ''.join(output)
output = u_boot_console.run_command_list([
- 'efidebug boot add 1 HELLO_abc host 0:1 /helloworld.efi.signed_abc ""',
+ 'efidebug boot add -b 1 HELLO_abc host 0:1 /helloworld.efi.signed_abc ""',
'efidebug boot next 1',
'efidebug test bootmgr'])
assert '\'HELLO_abc\' failed' in ''.join(output)
@@ -116,7 +116,7 @@ class TestEfiSignedImageIntca(object):
assert 'Failed to set EFI variable' not in ''.join(output)
output = u_boot_console.run_command_list([
- 'efidebug boot add 1 HELLO_abc host 0:1 /helloworld.efi.signed_abc ""',
+ 'efidebug boot add -b 1 HELLO_abc host 0:1 /helloworld.efi.signed_abc ""',
'efidebug boot next 1',
'efidebug test bootmgr'])
assert 'Hello, world!' in ''.join(output)
diff --git a/test/py/tests/test_efi_secboot/test_unsigned.py b/test/py/tests/test_efi_secboot/test_unsigned.py
index 56f56e19eb..8e026f7566 100644
--- a/test/py/tests/test_efi_secboot/test_unsigned.py
+++ b/test/py/tests/test_efi_secboot/test_unsigned.py
@@ -35,7 +35,7 @@ class TestEfiUnsignedImage(object):
assert 'Failed to set EFI variable' not in ''.join(output)
output = u_boot_console.run_command_list([
- 'efidebug boot add 1 HELLO host 0:1 /helloworld.efi ""',
+ 'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi ""',
'efidebug boot next 1',
'bootefi bootmgr'])
assert '\'HELLO\' failed' in ''.join(output)
@@ -64,7 +64,7 @@ class TestEfiUnsignedImage(object):
assert 'Failed to set EFI variable' not in ''.join(output)
output = u_boot_console.run_command_list([
- 'efidebug boot add 1 HELLO host 0:1 /helloworld.efi ""',
+ 'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi ""',
'efidebug boot next 1',
'bootefi bootmgr'])
assert 'Hello, world!' in ''.join(output)
@@ -88,7 +88,7 @@ class TestEfiUnsignedImage(object):
assert 'Failed to set EFI variable' not in ''.join(output)
output = u_boot_console.run_command_list([
- 'efidebug boot add 1 HELLO host 0:1 /helloworld.efi ""',
+ 'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi ""',
'efidebug boot next 1',
'bootefi bootmgr'])
assert '\'HELLO\' failed' in ''.join(output)
@@ -106,7 +106,7 @@ class TestEfiUnsignedImage(object):
assert 'Failed to set EFI variable' not in ''.join(output)
output = u_boot_console.run_command_list([
- 'efidebug boot add 1 HELLO host 0:1 /helloworld.efi ""',
+ 'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi ""',
'efidebug boot next 1',
'bootefi bootmgr'])
assert '\'HELLO\' failed' in ''.join(output)