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
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEbcT5xx8ppvoGt20zxIHbvCwFGsQFAmBc/6QACgkQxIHbvCwF
 GsTZkBAAg2I6PuJV4n7Y5qsJOBCe49u3E0oIXZQBdJ459MEeY5kxXmm2D7jXA3ir
 RXJJIPK9BEOYSV3yLpSMj/jLMd+i777qcU63Sf4MKVMEAK7stv50QIcY6Jz2Lb9c
 /S0SDlqwtU9rq9mXHi/Vn6ky37S/gVD+N+8w18UHa3qyo3/b8TesPUcF10IhMaOM
 BOG4Wi5PwMre65OTBH6KvD7KPIuUwS0E1NCVEuAHMND2ueE9AAh+d4FvA43ejNZt
 Hw/gZh1siXzf2OnnF+zVpVuj5slZ7fVBhHNDjmNKAPI6dd2+5oDDWu/OavM3z3OS
 HX4MdLQWAQQiI3NI2ZIZ9xipC033cd3X2IzOX2LlSxq6+zm/ovAMXUHrPF4+erBz
 zatnKZczLPsBKgRbPZzv3LOgWDnroXkT12er/T8RTX0jPCLqloxpQp9261HHjYR+
 zM1LYowjTOiEBMAQVuM9koQ2NhcQbcsr6uZmo22LcvUjWZIEVYhEI5mnXmQRBmR6
 LeQbrSG68NbtaBNKPqsUy1GAC4WgCzLJ8fUOlaW8But/tnWzGxCPY3XgdtFMfkcj
 HIn28ihDMTtInUPhK7qIPuQRyAIA7LStYIOEBdBSlbKq+aiK1r98gjcshMM5LAtn
 RdZq2WSM6gvWH2qV/cEeGSzjd7SdqMGBkFds0GcluOpDBoX1+pk=
 =l6aM
 -----END PGP SIGNATURE-----

Merge tag 'efi-next' of https://source.denx.de/u-boot/custodians/u-boot-efi into 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
This commit is contained in:
Tom Rini 2021-03-25 22:45:43 -04:00
commit 4be994b0e1
36 changed files with 1783 additions and 455 deletions

View File

@ -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;
}

View File

@ -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,
@ -516,6 +598,10 @@ static const struct {
"ACPI table",
EFI_ACPI_TABLE_GUID,
},
{
"EFI System Resource Table",
EFI_SYSTEM_RESOURCE_TABLE_GUID,
},
{
"device tree",
EFI_FDT_GUID,
@ -798,6 +884,54 @@ static int do_efi_show_tables(struct cmd_tbl *cmdtp, int flag,
return CMD_RET_SUCCESS;
}
/**
* 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
*
@ -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;
/* 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]);
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;
}
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
);

View File

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

View File

@ -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

View File

@ -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,

View File

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

View File

@ -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

View File

@ -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 */

View File

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

View File

@ -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
default y
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
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

View File

@ -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

View File

@ -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);
@ -146,6 +148,13 @@ static efi_status_t try_load_entry(u16 n, efi_handle_t *handle,
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;
}

View File

@ -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;
}

View File

@ -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) {

View File

@ -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.
@ -299,6 +299,37 @@ out:
return ret;
}
/**
* 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.
*
@ -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) {

View File

@ -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;
memcpy(p, dp1, sz1);
/* the end node of the second device path has to be retained */
memcpy(p + sz1, dp2, sz2 + sizeof(END));
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, 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;
}

View File

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

View File

@ -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 */

510
lib/efi_loader/efi_esrt.c Normal file
View File

@ -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;
}

View File

@ -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)
{

View File

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

View File

@ -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;
}

View File

@ -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;
const efi_guid_t lf2_initrd_guid = EFI_INITRD_MEDIA_GUID;
struct efi_device_path *dp = NULL;
ret = fs_set_blk_dev(dev, part, FS_TYPE_ANY);
if (ret) {
*status = EFI_NO_MEDIA;
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;
ret = fs_size(file, &sz);
if (ret) {
sz = 0;
*status = EFI_NOT_FOUND;
goto out;
}
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)
goto out;
part = strsep(&pos, " ");
if (!part)
goto out;
file = strsep(&pos, " ");
if (!file)
ret = get_initrd_fp(&initrd_fp);
if (ret != EFI_SUCCESS)
goto out;
file_sz = get_file_size(dev, part, file, &status);
if (!file_sz)
/* 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;
}
/* 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:
free(filespec);
return EFI_EXIT(status);
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:
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;
}

View File

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

View File

@ -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>
@ -957,6 +958,23 @@ out:
return ret;
}
/**
* 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;
}

View File

@ -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;
}

View File

@ -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 \

View File

@ -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 */

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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) {

View File

@ -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])

View File

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

View File

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

View File

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