diff options
Diffstat (limited to 'lib/efi_loader')
-rw-r--r-- | lib/efi_loader/Kconfig | 14 | ||||
-rw-r--r-- | lib/efi_loader/dtbdump.c | 261 | ||||
-rw-r--r-- | lib/efi_loader/efi_bootmgr.c | 2 | ||||
-rw-r--r-- | lib/efi_loader/efi_capsule.c | 1 | ||||
-rw-r--r-- | lib/efi_loader/efi_console.c | 1 | ||||
-rw-r--r-- | lib/efi_loader/efi_fdt.c | 33 | ||||
-rw-r--r-- | lib/efi_loader/efi_image_loader.c | 2 | ||||
-rw-r--r-- | lib/efi_loader/efi_variable.c | 1 |
8 files changed, 289 insertions, 26 deletions
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index ee71f417147..38e64af2531 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -67,7 +67,7 @@ config EFI_RT_VOLATILE_STORE depends on EFI_VARIABLE_FILE_STORE help When EFI variables are stored on file we don't allow SetVariableRT, - since the OS doesn't know how to write that file. At he same time + since the OS doesn't know how to write that file. At the same time we copy runtime variables in DRAM and support GetVariableRT Enable this option to allow SetVariableRT on the RAM backend of @@ -298,13 +298,15 @@ config EFI_CAPSULE_MAX Select the max capsule index value used for capsule report variables. This value is used to create CapsuleMax variable. -config EFI_CAPSULE_ESL_FILE - string "Path to the EFI Signature List File" +config EFI_CAPSULE_CRT_FILE + string "Path to the EFI capsule public key certificate" depends on EFI_CAPSULE_AUTHENTICATE help - Provides the path to the EFI Signature List file which will - be embedded in the platform's device tree and used for - capsule authentication at the time of capsule update. + Provides the path to the EFI capsule public key certificate that + corresponds to the capsule signing key. This certificate will be used + to generate the EFI capsule ESL (signature list file) that gets + embedded in the platform's device tree and used for capsule + authentication at the time of capsule update. config EFI_DEVICE_PATH_TO_TEXT bool "Device path to text protocol" diff --git a/lib/efi_loader/dtbdump.c b/lib/efi_loader/dtbdump.c index 5f39cf22da7..9f1d8fb82cb 100644 --- a/lib/efi_loader/dtbdump.c +++ b/lib/efi_loader/dtbdump.c @@ -41,6 +41,53 @@ static void print(u16 *string) } /** + * print_char() - print character + * + * 0x00 is replaced by '", "'. + * + * @c: - character + */ +static void print_char(unsigned char c) +{ + u16 out[2] = u"?"; + + if (!c) { + print(u"\", \""); + return; + } + + if (c > 0x1f && c < 0x80) + out[0] = c; + + print(out); +} + +/** + * print_hex_digit() - print hexadecimal digit + * + * @digit: digit to print + */ +static void print_hex_digit(unsigned char digit) +{ + if (digit < 10) + digit += '0'; + else + digit += 'a' - 10; + print_char(digit); +} + +/** + * printx() - print hexadecimal byte + * + * @val: value to print + */ +static void printx(unsigned char val) +{ + print_hex_digit(val >> 4); + print_hex_digit(val & 0xf); +} + +/** * error() - print error string * * @string: error text @@ -227,6 +274,7 @@ bool starts_with(u16 *string, u16 *keyword) */ void do_help(void) { + error(u"dump - print device-tree\r\n"); error(u"load <dtb> - load device-tree from file\r\n"); error(u"save <dtb> - save device-tree to file\r\n"); error(u"exit - exit the shell\r\n"); @@ -490,6 +538,217 @@ efi_status_t do_save(u16 *filename) } /** + * indent() - print a number of tabstops + * + * @level: indentation level + */ +static void indent(u32 level) +{ + for (; level; --level) + print(u"\t"); +} + +/** + * is_string_value() - determine if property is a string + * + * If a property is a string, an x-string, or a u32 cannot be deducted + * from the device-tree. Therefore a heuristic is used. + * + * @str: pointer to device-tree property + * @len: length of the device-tree property + * Return: 1 for string, 0 otherwise + */ +static int is_string_value(const unsigned char *str, u32 len) +{ + int nonzero_flag = 0; + + /* Zero length or not ending with 0x00 */ + if (!len || str[len - 1]) + return 0; + + for (u32 i = 0; i < len; ++i) { + if (!str[i]) { + /* Zero length string or two consecutive 0x00 */ + if (!nonzero_flag) + return 0; + + nonzero_flag = 0; + + continue; + } + /* Non-printable */ + if (str[i] < 0x20 || str[i] >= 0x80) + return 0; + + nonzero_flag = 1; + } + + return 1; +} + +/** + * print_property() - print device-tree property + * + * If a property is a string, an x-string, or a u32 cannot be deducted + * from the device-tree. Therefore a heuristic is used. + * + * @str: property value + * @len: length of property value + */ +static void print_property(const unsigned char *val, u32 len) +{ + if (is_string_value(val, len)) { + /* string */ + print(u"\""); + for (int i = 0; i < len - 1; ++i) + print_char(val[i]); + print(u"\""); + } else if (len & 0x3) { + /* byte string */ + print(u"["); + for (int i = 0; i < len; ++i) { + if (i) + print(u" "); + printx(val[i]); + } + print(u"]\""); + } else { + /* cell list */ + print(u"<"); + for (u32 i = 0; i < len; ++i) { + if ((i & 0x3) == 0) { + if (i > 0) + print(u" "); + print(u"0x"); + } + printx(val[i]); + } + print(u">"); + } +} + +/** + * print_mem_res_block() - print memory reservation block + * + * @rsvblk: memory reservation block + */ +static void print_mem_res_block(const struct fdt_reserve_entry *rsvblk) +{ + for (; rsvblk->address || rsvblk->size; ++rsvblk) { + const unsigned char *val; + + print(u"/memreserve/ 0x"); + val = (const unsigned char *)&rsvblk->address; + for (u32 i = 0; i < sizeof(u64); ++i) + printx(val[i]); + print(u" 0x"); + val = (const unsigned char *)&rsvblk->size; + for (u32 i = 0; i < sizeof(u64); ++i) + printx(val[i]); + print(u";\r\n"); + } +} + +/** + * do_dump() - print device-tree + */ +static efi_status_t do_dump(void) +{ + const unsigned char *fdt; + struct fdt_header *header; + const u32 *end; + const u32 *pos; + const char *strings; + u32 level = 0; + + fdt = get_dtb(systable); + if (!fdt) { + error(u"DTB not found\r\n"); + return EFI_NOT_FOUND; + } + + header = (struct fdt_header *)fdt; + if (f2h(header->magic) != FDT_MAGIC) { + error(u"Wrong device tree magic\r\n"); + error(u"Not a device-tree\r\n"); + return EFI_LOAD_ERROR; + } + + pos = (u32 *)(fdt + f2h(header->off_dt_struct)); + end = &pos[f2h(header->totalsize) >> 2]; + strings = fdt + f2h(header->off_dt_strings); + + print(u"/dts-v1/;\r\n"); + + print_mem_res_block((const struct fdt_reserve_entry *) + (fdt + f2h(header->off_mem_rsvmap))); + + print(u"/"); + for (; pos < end;) { + switch (f2h(pos[0])) { + case FDT_BEGIN_NODE: { + const char *c = (char *)&pos[1]; + size_t i; + + indent(level); + for (i = 0; c[i]; ++i) + print_char(c[i]); + print(u" {\n\r"); + + ++level; + pos = &pos[2 + (i >> 2)]; + break; + } + case FDT_PROP: { + struct fdt_property *prop = (struct fdt_property *)pos; + const unsigned char *label = &strings[f2h(prop->nameoff)]; + u32 len = f2h(prop->len); + const unsigned char *str = (unsigned char *)&pos[3]; + + indent(level); + for (int i = 0; label[i]; ++i) + print_char(label[i]); + + if (len) { + print(u" = "); + print_property(str, len); + } + print(u";\r\n"); + + pos = &pos[3 + ((f2h(prop->len) + 3) >> 2)]; + break; + } + case FDT_NOP: + ++pos; + break; + case FDT_END_NODE: + if (!level) { + error(u"Extraneous end node\r\n"); + return EFI_LOAD_ERROR; + } + + --level; + indent(level); + print(u"};\n\r"); + ++pos; + break; + case FDT_END: + if (level) { + error(u"Missing end node\r\n"); + return EFI_LOAD_ERROR; + } + return EFI_SUCCESS; + default: + error(u"Invalid device tree token\r\n"); + return EFI_LOAD_ERROR; + } + } + error(u"Overrun\r\n"); + + return EFI_LOAD_ERROR; +} + +/** * efi_main() - entry point of the EFI application. * * @handle: handle of the loaded image @@ -524,6 +783,8 @@ efi_status_t EFIAPI efi_main(efi_handle_t image_handle, pos = skip_whitespace(command); if (starts_with(pos, u"exit")) break; + else if (starts_with(pos, u"dump")) + do_dump(); else if (starts_with(pos, u"load ")) do_load(pos + 5); else if (starts_with(pos, u"save ")) diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c index 304ed43595c..589d3996b68 100644 --- a/lib/efi_loader/efi_bootmgr.c +++ b/lib/efi_loader/efi_bootmgr.c @@ -1277,7 +1277,7 @@ efi_status_t efi_bootmgr_run(void *fdt) if (fdt_lo) fdt = fdt_lo; if (!fdt) { - efi_load_distro_fdt(&fdt_distro, &fdt_size); + efi_load_distro_fdt(handle, &fdt_distro, &fdt_size); fdt = fdt_distro; } } diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c index 0937800e588..635088f25a1 100644 --- a/lib/efi_loader/efi_capsule.c +++ b/lib/efi_loader/efi_capsule.c @@ -572,7 +572,6 @@ static efi_status_t efi_capsule_update_firmware( return EFI_INVALID_PARAMETER; } - /* Obtain the update_index from the platform */ status = fwu_plat_get_update_index(&update_index); if (status < 0) { diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index 03dece51aea..c944c10b216 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -1176,7 +1176,6 @@ out: return EFI_EXIT(ret); } - /** * efi_cin_reset() - drain the input buffer * diff --git a/lib/efi_loader/efi_fdt.c b/lib/efi_loader/efi_fdt.c index 86ba00c2bdd..4ccf2055be3 100644 --- a/lib/efi_loader/efi_fdt.c +++ b/lib/efi_loader/efi_fdt.c @@ -75,28 +75,34 @@ int efi_get_distro_fdt_name(char *fname, int size, int seq) /** * efi_load_distro_fdt() - load distro device-tree * + * @handle: handle of loaded image * @fdt: on return device-tree, must be freed via efi_free_pages() * @fdt_size: buffer size */ -void efi_load_distro_fdt(void **fdt, efi_uintn_t *fdt_size) +void efi_load_distro_fdt(efi_handle_t handle, void **fdt, efi_uintn_t *fdt_size) { - struct efi_device_path *rem, *dp; + struct efi_device_path *dp; efi_status_t ret; + struct efi_handler *handler; + struct efi_loaded_image *loaded_image; efi_handle_t device; *fdt = NULL; - dp = efi_get_dp_from_boot(NULL); - if (!dp) + /* Get boot device from loaded image protocol */ + ret = efi_search_protocol(handle, &efi_guid_loaded_image, &handler); + if (ret != EFI_SUCCESS) return; - device = efi_dp_find_obj(dp, NULL, &rem); - ret = efi_search_protocol(device, &efi_simple_file_system_protocol_guid, - NULL); + loaded_image = handler->protocol_interface; + device = loaded_image->device_handle; + + /* Get device path of boot device */ + ret = efi_search_protocol(device, &efi_guid_device_path, &handler); if (ret != EFI_SUCCESS) - goto err; - memcpy(rem, &END, sizeof(END)); + return; + dp = handler->protocol_interface; - /* try the various available names */ + /* Try the various available names */ for (int seq = 0; ; ++seq) { struct efi_device_path *file; char buf[255]; @@ -108,10 +114,9 @@ void efi_load_distro_fdt(void **fdt, efi_uintn_t *fdt_size) break; ret = efi_load_image_from_path(true, file, fdt, fdt_size); efi_free_pool(file); - if (ret == EFI_SUCCESS) + if (ret == EFI_SUCCESS) { + log_debug("Fdt %pD loaded\n", file); break; + } } - -err: - efi_free_pool(dp); } diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c index 45dc5b6b244..0ddf69a0918 100644 --- a/lib/efi_loader/efi_image_loader.c +++ b/lib/efi_loader/efi_image_loader.c @@ -738,7 +738,6 @@ static bool efi_image_authenticate(void *efi, size_t efi_size) log_debug("Message digest doesn't match\n"); } - /* last resort try the image sha256 hash in db */ if (!ret && efi_signature_lookup_digest(regs, db, false)) ret = true; @@ -761,7 +760,6 @@ static bool efi_image_authenticate(void *efi, size_t efi_size) } #endif /* CONFIG_EFI_SECURE_BOOT */ - /** * efi_check_pe() - check if a memory buffer contains a PE-COFF image * diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index 09651d4675b..e888c52efe3 100644 --- a/lib/efi_loader/efi_variable.c +++ b/lib/efi_loader/efi_variable.c @@ -604,6 +604,5 @@ efi_status_t efi_init_variables(void) log_err("Invalid EFI variable seed\n"); } - return efi_init_secure_state(); } |