diff options
Diffstat (limited to 'lib/efi_loader')
-rw-r--r-- | lib/efi_loader/Kconfig | 19 | ||||
-rw-r--r-- | lib/efi_loader/Makefile | 1 | ||||
-rw-r--r-- | lib/efi_loader/capsule_esl.dtsi.in | 4 | ||||
-rw-r--r-- | lib/efi_loader/dtbdump.c | 261 | ||||
-rw-r--r-- | lib/efi_loader/efi_bootbin.c | 2 | ||||
-rw-r--r-- | lib/efi_loader/efi_bootmgr.c | 81 | ||||
-rw-r--r-- | lib/efi_loader/efi_boottime.c | 9 | ||||
-rw-r--r-- | lib/efi_loader/efi_capsule.c | 15 | ||||
-rw-r--r-- | lib/efi_loader/efi_console.c | 1 | ||||
-rw-r--r-- | lib/efi_loader/efi_device_path.c | 40 | ||||
-rw-r--r-- | lib/efi_loader/efi_device_path_utilities.c | 2 | ||||
-rw-r--r-- | lib/efi_loader/efi_dt_fixup.c | 2 | ||||
-rw-r--r-- | lib/efi_loader/efi_fdt.c | 125 | ||||
-rw-r--r-- | lib/efi_loader/efi_helper.c | 51 | ||||
-rw-r--r-- | lib/efi_loader/efi_image_loader.c | 15 | ||||
-rw-r--r-- | lib/efi_loader/efi_load_initrd.c | 2 | ||||
-rw-r--r-- | lib/efi_loader/efi_memory.c | 33 | ||||
-rw-r--r-- | lib/efi_loader/efi_runtime.c | 7 | ||||
-rw-r--r-- | lib/efi_loader/efi_signature.c | 1 | ||||
-rw-r--r-- | lib/efi_loader/efi_tcg2.c | 140 | ||||
-rw-r--r-- | lib/efi_loader/efi_variable.c | 7 | ||||
-rw-r--r-- | lib/efi_loader/initrddump.c | 2 |
22 files changed, 671 insertions, 149 deletions
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index 430bb7f0f7d..6ffefa9103f 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -10,9 +10,9 @@ config EFI_LOADER depends on !EFI_STUB || !X86_64 || EFI_STUB_64BIT # We need EFI_STUB_32BIT to be set on x86_32 with EFI_STUB depends on !EFI_STUB || !X86 || X86_64 || EFI_STUB_32BIT - depends on BLK depends on !EFI_APP default y if !ARM || SYS_CPU = armv7 || SYS_CPU = armv8 + select BLK select CHARSET # We need to send DM events, dynamically, in the EFI block driver select DM_EVENT @@ -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 @@ -220,6 +220,7 @@ config EFI_CAPSULE_ON_DISK config EFI_IGNORE_OSINDICATIONS bool "Ignore OsIndications for CapsuleUpdate on-disk" depends on EFI_CAPSULE_ON_DISK + default y if !EFI_RT_VOLATILE_STORE help There are boards where U-Boot does not support SetVariable at runtime. Select this option if you want to use the capsule-on-disk feature @@ -298,13 +299,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" @@ -361,7 +364,6 @@ endif config EFI_LOADER_BOUNCE_BUFFER bool "EFI Applications use bounce buffers for DMA operations" - depends on ARM64 help Some hardware does not support DMA to full 64bit addresses. For this hardware we can create a bounce buffer so that payloads don't have to @@ -484,6 +486,7 @@ config EFI_ECPT config EFI_EBBR_2_1_CONFORMANCE bool "Add the EBBRv2.1 conformance entry to the ECPT table" + depends on BOOTMETH_EFI_BOOTMGR depends on EFI_ECPT depends on EFI_LOADER_HII depends on EFI_RISCV_BOOT_PROTOCOL || !RISCV diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index 034e366967f..2af6f2066b5 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -59,6 +59,7 @@ obj-y += efi_device_path.o obj-$(CONFIG_EFI_DEVICE_PATH_TO_TEXT) += efi_device_path_to_text.o obj-$(CONFIG_EFI_DEVICE_PATH_UTIL) += efi_device_path_utilities.o obj-y += efi_dt_fixup.o +obj-y += efi_fdt.o obj-y += efi_file.o obj-$(CONFIG_EFI_LOADER_HII) += efi_hii.o obj-y += efi_image_loader.o diff --git a/lib/efi_loader/capsule_esl.dtsi.in b/lib/efi_loader/capsule_esl.dtsi.in index 61a9f2b25e9..bc7db836faa 100644 --- a/lib/efi_loader/capsule_esl.dtsi.in +++ b/lib/efi_loader/capsule_esl.dtsi.in @@ -1,9 +1,9 @@ // SPDX-License-Identifier: GPL-2.0+ -/** +/* * Devicetree file with the public key EFI Signature List(ESL) * node. This file is used to generate the dtsi file to be * included into the DTB. -*/ + */ / { signature { capsule-key = /incbin/("ESL_BIN_FILE"); 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_bootbin.c b/lib/efi_loader/efi_bootbin.c index b7910f78fb6..a87006b3c0e 100644 --- a/lib/efi_loader/efi_bootbin.c +++ b/lib/efi_loader/efi_bootbin.c @@ -150,7 +150,7 @@ efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size) msg_path = file_path; } else { file_path = efi_dp_concat(bootefi_device_path, - bootefi_image_path, false); + bootefi_image_path, 0); msg_path = bootefi_image_path; log_debug("Loaded from disk\n"); } diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c index 7da3139f917..589d3996b68 100644 --- a/lib/efi_loader/efi_bootmgr.c +++ b/lib/efi_loader/efi_bootmgr.c @@ -130,7 +130,7 @@ static efi_status_t try_load_from_file_path(efi_handle_t *fs_handles, if (!dp) continue; - dp = efi_dp_concat(dp, fp, false); + dp = efi_dp_concat(dp, fp, 0); if (!dp) continue; @@ -1186,6 +1186,59 @@ out: } /** + * load_fdt_from_load_option - load device-tree from load option + * + * @fdt: pointer to loaded device-tree or NULL + * Return: status code + */ +static efi_status_t load_fdt_from_load_option(void **fdt) +{ + struct efi_device_path *dp = NULL; + struct efi_file_handle *f = NULL; + efi_uintn_t filesize; + efi_status_t ret; + + *fdt = NULL; + + dp = efi_get_dp_from_boot(&efi_guid_fdt); + if (!dp) + return EFI_SUCCESS; + + /* Open file */ + f = efi_file_from_path(dp); + if (!f) { + log_err("Can't find %pD specified in Boot####\n", dp); + ret = EFI_NOT_FOUND; + goto out; + } + + /* Get file size */ + ret = efi_file_size(f, &filesize); + if (ret != EFI_SUCCESS) + goto out; + + *fdt = calloc(1, filesize); + if (!*fdt) { + log_err("Out of memory\n"); + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + ret = EFI_CALL(f->read(f, &filesize, *fdt)); + if (ret != EFI_SUCCESS) { + log_err("Can't read fdt\n"); + free(*fdt); + *fdt = NULL; + } + +out: + efi_free_pool(dp); + if (f) + EFI_CALL(f->close(f)); + + return ret; +} + +/** * efi_bootmgr_run() - execute EFI boot manager * @fdt: Flat device tree * @@ -1200,6 +1253,8 @@ efi_status_t efi_bootmgr_run(void *fdt) efi_handle_t handle; void *load_options; efi_status_t ret; + void *fdt_lo, *fdt_distro = NULL; + efi_uintn_t fdt_size; /* Initialize EFI drivers */ ret = efi_init_obj_list(); @@ -1215,7 +1270,31 @@ efi_status_t efi_bootmgr_run(void *fdt) return ret; } + if (!IS_ENABLED(CONFIG_GENERATE_ACPI_TABLE)) { + ret = load_fdt_from_load_option(&fdt_lo); + if (ret != EFI_SUCCESS) + return ret; + if (fdt_lo) + fdt = fdt_lo; + if (!fdt) { + efi_load_distro_fdt(handle, &fdt_distro, &fdt_size); + fdt = fdt_distro; + } + } + + /* + * Needed in ACPI case to create reservations based on + * control device-tree. + */ ret = efi_install_fdt(fdt); + + if (!IS_ENABLED(CONFIG_GENERATE_ACPI_TABLE)) { + free(fdt_lo); + if (fdt_distro) + efi_free_pages((uintptr_t)fdt_distro, + efi_size_in_pages(fdt_size)); + } + if (ret != EFI_SUCCESS) { if (EFI_CALL(efi_unload_image(handle)) == EFI_SUCCESS) free(load_options); diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 1951291747c..4f52284b4c6 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1816,7 +1816,7 @@ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path, if (device_path) { info->device_handle = efi_dp_find_obj(device_path, NULL, NULL); - dp = efi_dp_concat(device_path, file_path, false); + dp = efi_dp_concat(device_path, file_path, 0); if (!dp) { ret = EFI_OUT_OF_RESOURCES; goto failure; @@ -1996,7 +1996,6 @@ error: * @size: size of the loaded image * Return: status code */ -static efi_status_t efi_load_image_from_path(bool boot_policy, struct efi_device_path *file_path, void **buffer, efi_uintn_t *size) @@ -2510,16 +2509,12 @@ static efi_status_t EFIAPI efi_protocols_per_handle( return EFI_EXIT(EFI_INVALID_PARAMETER); *protocol_buffer = NULL; - *protocol_buffer_count = 0; efiobj = efi_search_obj(handle); if (!efiobj) return EFI_EXIT(EFI_INVALID_PARAMETER); - /* Count protocols */ - list_for_each(protocol_handle, &efiobj->protocols) { - ++*protocol_buffer_count; - } + *protocol_buffer_count = list_count_nodes(&efiobj->protocols); /* Copy GUIDs */ if (*protocol_buffer_count) { diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c index de0d49ebebd..635088f25a1 100644 --- a/lib/efi_loader/efi_capsule.c +++ b/lib/efi_loader/efi_capsule.c @@ -480,6 +480,11 @@ static __maybe_unused efi_status_t fwu_empty_capsule_process( if (ret != EFI_SUCCESS) log_err("Unable to set the Accept bit for the image %pUs\n", image_guid); + + status = fwu_state_machine_updates(0, active_idx); + if (status < 0) + ret = EFI_DEVICE_ERROR; + } return ret; @@ -521,11 +526,10 @@ static __maybe_unused efi_status_t fwu_post_update_process(bool fw_accept_os) log_err("Failed to update FWU metadata index values\n"); } else { log_debug("Successfully updated the active_index\n"); - if (fw_accept_os) { - status = fwu_trial_state_ctr_start(); - if (status < 0) - ret = EFI_DEVICE_ERROR; - } + status = fwu_state_machine_updates(fw_accept_os ? 1 : 0, + update_index); + if (status < 0) + ret = EFI_DEVICE_ERROR; } return ret; @@ -568,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_device_path.c b/lib/efi_loader/efi_device_path.c index aec224d8466..0f684590f22 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -276,10 +276,11 @@ struct efi_device_path *efi_dp_dup(const struct efi_device_path *dp) * * @dp1: First device path * @dp2: Second device path - * @split_end_node: If true the two device paths will be concatenated and - * separated by an end node (DEVICE_PATH_SUB_TYPE_END). - * If false the second device path will be concatenated to the - * first one as-is. + * @split_end_node: + * * 0 to concatenate + * * 1 to concatenate with end node added as separator + * * size of dp1 excluding last end node to concatenate with end node as + * separator in case dp1 contains an end node * * Return: * concatenated device path or NULL. Caller must free the returned value @@ -287,7 +288,7 @@ struct efi_device_path *efi_dp_dup(const struct efi_device_path *dp) struct efi_device_path *efi_dp_concat(const struct efi_device_path *dp1, const struct efi_device_path *dp2, - bool split_end_node) + size_t split_end_node) { struct efi_device_path *ret; size_t end_size; @@ -301,10 +302,15 @@ efi_device_path *efi_dp_concat(const struct efi_device_path *dp1, ret = efi_dp_dup(dp1); } else { /* both dp1 and dp2 are non-null */ - unsigned sz1 = efi_dp_size(dp1); - unsigned sz2 = efi_dp_size(dp2); + size_t sz1; + size_t sz2 = efi_dp_size(dp2); void *p; + if (split_end_node < sizeof(struct efi_device_path)) + sz1 = efi_dp_size(dp1); + else + sz1 = split_end_node; + if (split_end_node) end_size = 2 * sizeof(END); else @@ -1127,17 +1133,18 @@ ssize_t efi_dp_check_length(const struct efi_device_path *dp, } /** - * 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 + * efi_dp_from_lo() - get device-path from load option * - * @lo: EFI_LOAD_OPTION containing a valid device path - * @guid: guid to search for + * The load options in U-Boot may contain multiple concatenated device-paths. + * The first device-path indicates the EFI binary to execute. Subsequent + * device-paths start with a VenMedia node where the GUID identifies the + * function (initrd or fdt). + * + * @lo: EFI load option containing a valid device path + * @guid: GUID identifying device-path or NULL for the EFI binary * * Return: - * device path including the VenMedia node or NULL. + * device path excluding the matched VenMedia node or NULL. * Caller must free the returned value. */ struct @@ -1148,6 +1155,9 @@ efi_device_path *efi_dp_from_lo(struct efi_load_option *lo, struct efi_device_path_vendor *vendor; int lo_len = lo->file_path_length; + if (!guid) + return efi_dp_dup(fp); + 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) diff --git a/lib/efi_loader/efi_device_path_utilities.c b/lib/efi_loader/efi_device_path_utilities.c index c95dbfa9b5f..ac250bbfcc9 100644 --- a/lib/efi_loader/efi_device_path_utilities.c +++ b/lib/efi_loader/efi_device_path_utilities.c @@ -76,7 +76,7 @@ static struct efi_device_path * EFIAPI append_device_path( const struct efi_device_path *src2) { EFI_ENTRY("%pD, %pD", src1, src2); - return EFI_EXIT(efi_dp_concat(src1, src2, false)); + return EFI_EXIT(efi_dp_concat(src1, src2, 0)); } /* diff --git a/lib/efi_loader/efi_dt_fixup.c b/lib/efi_loader/efi_dt_fixup.c index 9886e6897cd..9d017804eea 100644 --- a/lib/efi_loader/efi_dt_fixup.c +++ b/lib/efi_loader/efi_dt_fixup.c @@ -172,7 +172,7 @@ efi_dt_fixup(struct efi_dt_fixup_protocol *this, void *dtb, } fdt_set_totalsize(dtb, *buffer_size); - if (image_setup_libfdt(&img, dtb, NULL)) { + if (image_setup_libfdt(&img, dtb, false)) { log_err("failed to process device tree\n"); ret = EFI_INVALID_PARAMETER; goto out; diff --git a/lib/efi_loader/efi_fdt.c b/lib/efi_loader/efi_fdt.c new file mode 100644 index 00000000000..f882622fdad --- /dev/null +++ b/lib/efi_loader/efi_fdt.c @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Bootmethod for distro boot via EFI + * + * Copyright 2021 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#include <efi_loader.h> +#include <env.h> +#include <errno.h> +#include <log.h> +#include <string.h> +#include <vsprintf.h> + +/** + * efi_get_distro_fdt_name() - get the filename for reading the .dtb file + * + * @fname: buffer for filename + * @size: buffer size + * @seq: sequence number, to cycle through options (0=first) + * + * Returns: + * 0 on success, + * -ENOENT if the "fdtfile" env var does not exist, + * -EINVAL if there are no more options, + * -EALREADY if the control FDT should be used + */ +int efi_get_distro_fdt_name(char *fname, int size, int seq) +{ + const char *fdt_fname; + const char *prefix; + + /* select the prefix */ + switch (seq) { + case 0: + /* this is the default */ + prefix = "/dtb"; + break; + case 1: + prefix = ""; + break; + case 2: + prefix = "/dtb/current"; + break; + case 3: + prefix = "/dtbs"; + break; + default: + return log_msg_ret("pref", -EINVAL); + } + + fdt_fname = env_get("fdtfile"); + if (fdt_fname) { + snprintf(fname, size, "%s/%s", prefix, fdt_fname); + log_debug("Using device tree: %s\n", fname); + } else if (IS_ENABLED(CONFIG_OF_HAS_PRIOR_STAGE)) { + strcpy(fname, "<prior>"); + return log_msg_ret("pref", -EALREADY); + /* Use this fallback only for 32-bit ARM */ + } else if (IS_ENABLED(CONFIG_ARM) && !IS_ENABLED(CONFIG_ARM64)) { + const char *soc = env_get("soc"); + const char *board = env_get("board"); + const char *boardver = env_get("boardver"); + + /* cf the code in label_boot() which seems very complex */ + snprintf(fname, size, "%s/%s%s%s%s.dtb", prefix, + soc ? soc : "", soc ? "-" : "", board ? board : "", + boardver ? boardver : ""); + log_debug("Using default device tree: %s\n", fname); + } else { + return log_msg_ret("env", -ENOENT); + } + + return 0; +} + +/** + * 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(efi_handle_t handle, void **fdt, efi_uintn_t *fdt_size) +{ + 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; + + /* Get boot device from loaded image protocol */ + ret = efi_search_protocol(handle, &efi_guid_loaded_image, &handler); + if (ret != EFI_SUCCESS) + return; + 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) + return; + dp = handler->protocol_interface; + + /* Try the various available names */ + for (int seq = 0; ; ++seq) { + struct efi_device_path *file; + char buf[255]; + + if (efi_get_distro_fdt_name(buf, sizeof(buf), seq)) + break; + file = efi_dp_from_file(dp, buf); + if (!file) + break; + ret = efi_load_image_from_path(true, file, fdt, fdt_size); + efi_free_pool(file); + if (ret == EFI_SUCCESS) { + log_debug("Fdt %pD loaded\n", file); + break; + } + } +} diff --git a/lib/efi_loader/efi_helper.c b/lib/efi_loader/efi_helper.c index 73d0279e843..96f847652ec 100644 --- a/lib/efi_loader/efi_helper.c +++ b/lib/efi_loader/efi_helper.c @@ -74,6 +74,7 @@ out: */ struct efi_device_path *efi_get_dp_from_boot(const efi_guid_t *guid) { + struct efi_device_path *file_path = NULL; struct efi_load_option lo; void *var_value; efi_uintn_t size; @@ -92,11 +93,55 @@ struct efi_device_path *efi_get_dp_from_boot(const efi_guid_t *guid) if (ret != EFI_SUCCESS) goto err; - return efi_dp_from_lo(&lo, guid); + file_path = efi_dp_from_lo(&lo, guid); err: free(var_value); - return NULL; + return file_path; +} + +/** + * efi_load_option_dp_join() - join device-paths for load option + * + * @dp: in: binary device-path, out: joined device-path + * @dp_size: size of joined device-path + * @initrd_dp: initrd device-path or NULL + * @fdt_dp: device-tree device-path or NULL + * Return: status_code + */ +efi_status_t efi_load_option_dp_join(struct efi_device_path **dp, + size_t *dp_size, + struct efi_device_path *initrd_dp, + struct efi_device_path *fdt_dp) +{ + if (!dp) + return EFI_INVALID_PARAMETER; + + *dp_size = efi_dp_size(*dp); + + if (initrd_dp) { + struct efi_device_path *tmp_dp = *dp; + + *dp = efi_dp_concat(tmp_dp, initrd_dp, *dp_size); + efi_free_pool(tmp_dp); + if (!*dp) + return EFI_OUT_OF_RESOURCES; + *dp_size += efi_dp_size(initrd_dp) + sizeof(END); + } + + if (fdt_dp) { + struct efi_device_path *tmp_dp = *dp; + + *dp = efi_dp_concat(tmp_dp, fdt_dp, *dp_size); + efi_free_pool(tmp_dp); + if (!*dp) + return EFI_OUT_OF_RESOURCES; + *dp_size += efi_dp_size(fdt_dp) + sizeof(END); + } + + *dp_size += sizeof(END); + + return EFI_SUCCESS; } const struct guid_to_hash_map { @@ -469,7 +514,7 @@ efi_status_t efi_install_fdt(void *fdt) return EFI_OUT_OF_RESOURCES; } - if (image_setup_libfdt(&img, fdt, NULL)) { + if (image_setup_libfdt(&img, fdt, false)) { log_err("ERROR: failed to process device tree\n"); return EFI_LOAD_ERROR; } diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c index 60424360328..0ddf69a0918 100644 --- a/lib/efi_loader/efi_image_loader.c +++ b/lib/efi_loader/efi_image_loader.c @@ -173,11 +173,6 @@ static efi_status_t efi_loader_relocate(const IMAGE_BASE_RELOCATION *rel, return EFI_SUCCESS; } -void __weak invalidate_icache_all(void) -{ - /* If the system doesn't support icache_all flush, cross our fingers */ -} - /** * efi_set_code_and_data_type() - determine the memory types to be used for code * and data. @@ -743,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; @@ -766,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 * @@ -986,7 +979,13 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, /* Flush cache */ flush_cache((ulong)efi_reloc, ALIGN(virt_size, EFI_CACHELINE_SIZE)); - invalidate_icache_all(); + + /* + * If on x86 a write affects a prefetched instruction, + * the prefetch queue is invalidated. + */ + if (!CONFIG_IS_ENABLED(X86)) + invalidate_icache_all(); /* Populate the loaded image interface bits */ loaded_image_info->image_base = efi_reloc; diff --git a/lib/efi_loader/efi_load_initrd.c b/lib/efi_loader/efi_load_initrd.c index d91135436c4..23508431c83 100644 --- a/lib/efi_loader/efi_load_initrd.c +++ b/lib/efi_loader/efi_load_initrd.c @@ -24,7 +24,7 @@ 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_lf2_handle = { +static const struct efi_lo_dp_prefix dp_lf2_handle = { .vendor = { { DEVICE_PATH_TYPE_MEDIA_DEVICE, diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index 12cf23fa3fa..c6f1dd09456 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -127,7 +127,7 @@ static uint64_t desc_get_end(struct efi_mem_desc *desc) */ static void efi_mem_sort(void) { - struct list_head *lhandle; + struct efi_mem_list *lmem; struct efi_mem_list *prevmem = NULL; bool merge_again = true; @@ -136,19 +136,18 @@ static void efi_mem_sort(void) /* Now merge entries that can be merged */ while (merge_again) { merge_again = false; - list_for_each(lhandle, &efi_mem) { - struct efi_mem_list *lmem; - struct efi_mem_desc *prev = &prevmem->desc; + list_for_each_entry(lmem, &efi_mem, link) { + struct efi_mem_desc *prev; struct efi_mem_desc *cur; uint64_t pages; - lmem = list_entry(lhandle, struct efi_mem_list, link); if (!prevmem) { prevmem = lmem; continue; } cur = &lmem->desc; + prev = &prevmem->desc; if ((desc_get_end(cur) == prev->physical_start) && (prev->type == cur->type) && @@ -268,7 +267,7 @@ static efi_status_t efi_add_memory_map_pg(u64 start, u64 pages, int memory_type, bool overlap_only_ram) { - struct list_head *lhandle; + struct efi_mem_list *lmem; struct efi_mem_list *newlist; bool carve_again; uint64_t carved_pages = 0; @@ -308,11 +307,9 @@ static efi_status_t efi_add_memory_map_pg(u64 start, u64 pages, /* Add our new map */ do { carve_again = false; - list_for_each(lhandle, &efi_mem) { - struct efi_mem_list *lmem; + list_for_each_entry(lmem, &efi_mem, link) { s64 r; - lmem = list_entry(lhandle, struct efi_mem_list, link); r = efi_mem_carve_out(lmem, &newlist->desc, overlap_only_ram); switch (r) { @@ -444,7 +441,7 @@ static efi_status_t efi_check_allocated(u64 addr, bool must_be_allocated) */ static uint64_t efi_find_free_memory(uint64_t len, uint64_t max_addr) { - struct list_head *lhandle; + struct efi_mem_list *lmem; /* * Prealign input max address, so we simplify our matching @@ -452,9 +449,7 @@ static uint64_t efi_find_free_memory(uint64_t len, uint64_t max_addr) */ max_addr &= ~EFI_PAGE_MASK; - list_for_each(lhandle, &efi_mem) { - struct efi_mem_list *lmem = list_entry(lhandle, - struct efi_mem_list, link); + list_for_each_entry(lmem, &efi_mem, link) { struct efi_mem_desc *desc = &lmem->desc; uint64_t desc_len = desc->num_pages << EFI_PAGE_SHIFT; uint64_t desc_end = desc->physical_start + desc_len; @@ -742,9 +737,9 @@ efi_status_t efi_get_memory_map(efi_uintn_t *memory_map_size, efi_uintn_t *descriptor_size, uint32_t *descriptor_version) { + size_t map_entries; efi_uintn_t map_size = 0; - int map_entries = 0; - struct list_head *lhandle; + struct efi_mem_list *lmem; efi_uintn_t provided_map_size; if (!memory_map_size) @@ -752,8 +747,7 @@ efi_status_t efi_get_memory_map(efi_uintn_t *memory_map_size, provided_map_size = *memory_map_size; - list_for_each(lhandle, &efi_mem) - map_entries++; + map_entries = list_count_nodes(&efi_mem); map_size = map_entries * sizeof(struct efi_mem_desc); @@ -774,10 +768,7 @@ efi_status_t efi_get_memory_map(efi_uintn_t *memory_map_size, /* Copy list into array */ /* Return the list in ascending order */ memory_map = &memory_map[map_entries - 1]; - list_for_each(lhandle, &efi_mem) { - struct efi_mem_list *lmem; - - lmem = list_entry(lhandle, struct efi_mem_list, link); + list_for_each_entry(lmem, &efi_mem, link) { *memory_map = lmem->desc; memory_map--; } diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c index 011bcd04836..05369c47b01 100644 --- a/lib/efi_loader/efi_runtime.c +++ b/lib/efi_loader/efi_runtime.c @@ -783,7 +783,12 @@ void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map) lastoff = offset; #endif - invalidate_icache_all(); + /* + * If on x86 a write affects a prefetched instruction, + * the prefetch queue is invalidated. + */ + if (!CONFIG_IS_ENABLED(X86)) + invalidate_icache_all(); } /** diff --git a/lib/efi_loader/efi_signature.c b/lib/efi_loader/efi_signature.c index f338e732759..184eac8cddb 100644 --- a/lib/efi_loader/efi_signature.c +++ b/lib/efi_loader/efi_signature.c @@ -17,7 +17,6 @@ #include <linux/oid_registry.h> #include <u-boot/hash-checksum.h> #include <u-boot/rsa.h> -#include <u-boot/sha256.h> const efi_guid_t efi_guid_sha256 = EFI_CERT_SHA256_GUID; const efi_guid_t efi_guid_cert_rsa2048 = EFI_CERT_RSA2048_GUID; diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c index b07e0099c27..45f451ef6b6 100644 --- a/lib/efi_loader/efi_tcg2.c +++ b/lib/efi_loader/efi_tcg2.c @@ -16,12 +16,8 @@ #include <malloc.h> #include <smbios.h> #include <version_string.h> -#include <tpm-v2.h> #include <tpm_api.h> #include <u-boot/hash-checksum.h> -#include <u-boot/sha1.h> -#include <u-boot/sha256.h> -#include <u-boot/sha512.h> #include <linux/unaligned/be_byteshift.h> #include <linux/unaligned/le_byteshift.h> #include <linux/unaligned/generic.h> @@ -257,8 +253,8 @@ efi_tcg2_get_capability(struct efi_tcg2_protocol *this, capability->protocol_version.major = 1; capability->protocol_version.minor = 1; - efi_ret = tcg2_platform_get_tpm2(&dev); - if (efi_ret != EFI_SUCCESS) { + ret = tcg2_platform_get_tpm2(&dev); + if (ret) { capability->supported_event_logs = 0; capability->hash_algorithm_bitmap = 0; capability->tpm_present_flag = false; @@ -280,7 +276,7 @@ efi_tcg2_get_capability(struct efi_tcg2_protocol *this, /* Supported and active PCRs */ capability->hash_algorithm_bitmap = 0; capability->active_pcr_banks = 0; - ret = tpm2_get_pcr_info(dev, &capability->hash_algorithm_bitmap, + ret = tcg2_get_pcr_info(dev, &capability->hash_algorithm_bitmap, &capability->active_pcr_banks, &capability->number_of_pcr_banks); if (ret) { @@ -353,8 +349,7 @@ efi_tcg2_get_eventlog(struct efi_tcg2_protocol *this, goto out; } - ret = tcg2_platform_get_tpm2(&dev); - if (ret != EFI_SUCCESS) { + if (tcg2_platform_get_tpm2(&dev)) { event_log_location = NULL; event_log_last_entry = NULL; *event_log_truncated = false; @@ -389,7 +384,7 @@ static efi_status_t tcg2_hash_pe_image(void *efi, u64 efi_size, void *new_efi = NULL; u8 hash[TPM2_SHA512_DIGEST_SIZE]; struct udevice *dev; - efi_status_t ret; + efi_status_t ret = EFI_SUCCESS; u32 active; int i; @@ -404,20 +399,21 @@ static efi_status_t tcg2_hash_pe_image(void *efi, u64 efi_size, goto out; } - ret = tcg2_platform_get_tpm2(&dev); - if (ret != EFI_SUCCESS) + if (tcg2_platform_get_tpm2(&dev)) { + ret = EFI_DEVICE_ERROR; goto out; + } - ret = tcg2_get_active_pcr_banks(dev, &active); - if (ret != EFI_SUCCESS) { + if (tcg2_get_active_pcr_banks(dev, &active)) { + ret = EFI_DEVICE_ERROR; goto out; } digest_list->count = 0; - for (i = 0; i < ARRAY_SIZE(tpm2_supported_algorithms); i++) { - u16 hash_alg = tpm2_supported_algorithms[i]; + for (i = 0; i < ARRAY_SIZE(hash_algo_list); i++) { + u16 hash_alg = hash_algo_list[i].hash_alg; - if (!(active & tpm2_algorithm_to_mask(hash_alg))) + if (!(active & hash_algo_list[i].hash_mask)) continue; switch (hash_alg) { case TPM2_ALG_SHA1: @@ -473,12 +469,12 @@ efi_status_t tcg2_measure_pe_image(void *efi, u64 efi_size, IMAGE_DOS_HEADER *dos; IMAGE_NT_HEADERS32 *nt; struct efi_handler *handler; + int rc; if (!is_tcg2_protocol_installed()) return EFI_SUCCESS; - ret = tcg2_platform_get_tpm2(&dev); - if (ret != EFI_SUCCESS) + if (tcg2_platform_get_tpm2(&dev)) return EFI_SECURITY_VIOLATION; switch (handle->image_type) { @@ -502,9 +498,9 @@ efi_status_t tcg2_measure_pe_image(void *efi, u64 efi_size, if (ret != EFI_SUCCESS) return ret; - ret = tcg2_pcr_extend(dev, pcr_index, &digest_list); - if (ret != EFI_SUCCESS) - return ret; + rc = tcg2_pcr_extend(dev, pcr_index, &digest_list); + if (rc) + return EFI_DEVICE_ERROR; ret = efi_search_protocol(&handle->header, &efi_guid_loaded_image_device_path, &handler); @@ -574,9 +570,10 @@ efi_tcg2_hash_log_extend_event(struct efi_tcg2_protocol *this, u64 flags, struct efi_tcg2_event *efi_tcg_event) { struct udevice *dev; - efi_status_t ret; + efi_status_t ret = EFI_SUCCESS; u32 event_type, pcr_index, event_size; struct tpml_digest_values digest_list; + int rc = 0; EFI_ENTRY("%p, %llu, %llu, %llu, %p", this, flags, data_to_hash, data_to_hash_len, efi_tcg_event); @@ -586,9 +583,10 @@ efi_tcg2_hash_log_extend_event(struct efi_tcg2_protocol *this, u64 flags, goto out; } - ret = tcg2_platform_get_tpm2(&dev); - if (ret != EFI_SUCCESS) + if (tcg2_platform_get_tpm2(&dev)) { + ret = EFI_DEVICE_ERROR; goto out; + } if (efi_tcg_event->size < efi_tcg_event->header.header_size + sizeof(u32)) { @@ -621,8 +619,10 @@ efi_tcg2_hash_log_extend_event(struct efi_tcg2_protocol *this, u64 flags, ret = tcg2_hash_pe_image((void *)(uintptr_t)data_to_hash, data_to_hash_len, &digest_list); } else { - ret = tcg2_create_digest(dev, (u8 *)(uintptr_t)data_to_hash, - data_to_hash_len, &digest_list); + rc = tcg2_create_digest(dev, (u8 *)(uintptr_t)data_to_hash, + data_to_hash_len, &digest_list); + if (rc) + ret = EFI_DEVICE_ERROR; } if (ret != EFI_SUCCESS) @@ -631,9 +631,11 @@ efi_tcg2_hash_log_extend_event(struct efi_tcg2_protocol *this, u64 flags, pcr_index = efi_tcg_event->header.pcr_index; event_type = efi_tcg_event->header.event_type; - ret = tcg2_pcr_extend(dev, pcr_index, &digest_list); - if (ret != EFI_SUCCESS) + rc = tcg2_pcr_extend(dev, pcr_index, &digest_list); + if (rc) { + ret = EFI_DEVICE_ERROR; goto out; + } if (flags & EFI_TCG2_EXTEND_ONLY) { if (event_log.truncated) @@ -672,7 +674,7 @@ efi_tcg2_submit_command(struct efi_tcg2_protocol *this, u8 *output_param_block) { struct udevice *dev; - efi_status_t ret; + efi_status_t ret = EFI_SUCCESS; u32 rc; size_t resp_buf_size = output_param_block_size; @@ -684,9 +686,10 @@ efi_tcg2_submit_command(struct efi_tcg2_protocol *this, goto out; } - ret = tcg2_platform_get_tpm2(&dev); - if (ret != EFI_SUCCESS) + if (tcg2_platform_get_tpm2(&dev)) { + ret = EFI_DEVICE_ERROR; goto out; + } rc = tpm2_submit_command(dev, input_param_block, output_param_block, &resp_buf_size); @@ -714,19 +717,25 @@ efi_tcg2_get_active_pcr_banks(struct efi_tcg2_protocol *this, u32 *active_pcr_banks) { struct udevice *dev; - efi_status_t ret; + efi_status_t ret = EFI_INVALID_PARAMETER; EFI_ENTRY("%p, %p", this, active_pcr_banks); - if (!this || !active_pcr_banks) { - ret = EFI_INVALID_PARAMETER; + if (!this || !active_pcr_banks) goto out; - } - ret = tcg2_platform_get_tpm2(&dev); - if (ret != EFI_SUCCESS) + + if (tcg2_platform_get_tpm2(&dev)) + goto out; + + /* + * EFI_INVALID_PARAMETER does not convey the problem type. + * but that's what currently the spec specifies. + * EFI_DEVICE_ERROR would be better + */ + if (tcg2_get_active_pcr_banks(dev, active_pcr_banks)) goto out; - ret = tcg2_get_active_pcr_banks(dev, active_pcr_banks); + ret = EFI_SUCCESS; out: return EFI_EXIT(ret); @@ -852,14 +861,15 @@ static efi_status_t measure_event(struct udevice *dev, u32 pcr_index, u32 event_type, u32 size, u8 event[]) { struct tpml_digest_values digest_list; - efi_status_t ret; + efi_status_t ret = EFI_DEVICE_ERROR; + int rc; - ret = tcg2_create_digest(dev, event, size, &digest_list); - if (ret != EFI_SUCCESS) + rc = tcg2_create_digest(dev, event, size, &digest_list); + if (rc) goto out; - ret = tcg2_pcr_extend(dev, pcr_index, &digest_list); - if (ret != EFI_SUCCESS) + rc = tcg2_pcr_extend(dev, pcr_index, &digest_list); + if (rc) goto out; ret = tcg2_agile_log_append(pcr_index, event_type, &digest_list, @@ -901,10 +911,10 @@ static efi_status_t efi_init_event_log(void) struct tcg2_event_log elog; struct udevice *dev; efi_status_t ret; + int rc; - ret = tcg2_platform_get_tpm2(&dev); - if (ret != EFI_SUCCESS) - return ret; + if (tcg2_platform_get_tpm2(&dev)) + return EFI_DEVICE_ERROR; ret = efi_allocate_pool(EFI_BOOT_SERVICES_DATA, TPM2_EVENT_LOG_SIZE, (void **)&event_log.buffer); @@ -933,9 +943,11 @@ static efi_status_t efi_init_event_log(void) */ elog.log = event_log.buffer; elog.log_size = TPM2_EVENT_LOG_SIZE; - ret = tcg2_log_prepare_buffer(dev, &elog, false); - if (ret != EFI_SUCCESS) + rc = tcg2_log_prepare_buffer(dev, &elog, false); + if (rc) { + ret = (rc == -ENOBUFS) ? EFI_BUFFER_TOO_SMALL : EFI_DEVICE_ERROR; goto free_pool; + } event_log.pos = elog.log_position; @@ -1306,8 +1318,7 @@ efi_status_t efi_tcg2_measure_dtb(void *dtb) if (!is_tcg2_protocol_installed()) return EFI_SUCCESS; - ret = tcg2_platform_get_tpm2(&dev); - if (ret != EFI_SUCCESS) + if (tcg2_platform_get_tpm2(&dev)) return EFI_SECURITY_VIOLATION; rsvmap_size = size_of_rsvmap(dtb); @@ -1331,7 +1342,7 @@ efi_status_t efi_tcg2_measure_dtb(void *dtb) sha256_update(&hash_ctx, (u8 *)dtb + fdt_off_mem_rsvmap(dtb), rsvmap_size); sha256_finish(&hash_ctx, blob->data + blob->blob_description_size); - ret = measure_event(dev, 0, EV_POST_CODE, event_size, (u8 *)blob); + ret = measure_event(dev, 1, EV_POST_CODE, event_size, (u8 *)blob); free(blob); return ret; @@ -1356,8 +1367,7 @@ efi_status_t efi_tcg2_measure_efi_app_invocation(struct efi_loaded_image_obj *ha if (tcg2_efi_app_invoked) return EFI_SUCCESS; - ret = tcg2_platform_get_tpm2(&dev); - if (ret != EFI_SUCCESS) + if (tcg2_platform_get_tpm2(&dev)) return EFI_SECURITY_VIOLATION; ret = tcg2_measure_boot_variable(dev); @@ -1406,9 +1416,8 @@ efi_status_t efi_tcg2_measure_efi_app_exit(void) if (!is_tcg2_protocol_installed()) return EFI_SUCCESS; - ret = tcg2_platform_get_tpm2(&dev); - if (ret != EFI_SUCCESS) - return ret; + if (tcg2_platform_get_tpm2(&dev)) + return EFI_SECURITY_VIOLATION; ret = measure_event(dev, 4, EV_EFI_ACTION, strlen(EFI_RETURNING_FROM_EFI_APPLICATION), @@ -1437,9 +1446,10 @@ efi_tcg2_notify_exit_boot_services(struct efi_event *event, void *context) goto out; } - ret = tcg2_platform_get_tpm2(&dev); - if (ret != EFI_SUCCESS) + if (tcg2_platform_get_tpm2(&dev)) { + ret = EFI_SECURITY_VIOLATION; goto out; + } ret = measure_event(dev, 5, EV_EFI_ACTION, strlen(EFI_EXIT_BOOT_SERVICES_INVOCATION), @@ -1469,9 +1479,8 @@ efi_status_t efi_tcg2_notify_exit_boot_services_failed(void) if (!is_tcg2_protocol_installed()) return EFI_SUCCESS; - ret = tcg2_platform_get_tpm2(&dev); - if (ret != EFI_SUCCESS) - goto out; + if (tcg2_platform_get_tpm2(&dev)) + return EFI_SECURITY_VIOLATION; ret = measure_event(dev, 5, EV_EFI_ACTION, strlen(EFI_EXIT_BOOT_SERVICES_INVOCATION), @@ -1551,8 +1560,7 @@ efi_status_t efi_tcg2_do_initial_measurement(void) if (!is_tcg2_protocol_installed()) return EFI_SUCCESS; - ret = tcg2_platform_get_tpm2(&dev); - if (ret != EFI_SUCCESS) + if (tcg2_platform_get_tpm2(&dev)) return EFI_SECURITY_VIOLATION; ret = tcg2_measure_secure_boot_variable(dev); @@ -1577,8 +1585,7 @@ efi_status_t efi_tcg2_register(void) struct efi_event *event; u32 err; - ret = tcg2_platform_get_tpm2(&dev); - if (ret != EFI_SUCCESS) { + if (tcg2_platform_get_tpm2(&dev)) { log_warning("Missing TPMv2 device for EFI_TCG_PROTOCOL\n"); return EFI_SUCCESS; } @@ -1586,6 +1593,7 @@ efi_status_t efi_tcg2_register(void) /* initialize the TPM as early as possible. */ err = tpm_auto_start(dev); if (err) { + ret = EFI_DEVICE_ERROR; log_err("TPM startup failed\n"); goto fail; } diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index 1cc02acb3b2..e888c52efe3 100644 --- a/lib/efi_loader/efi_variable.c +++ b/lib/efi_loader/efi_variable.c @@ -288,7 +288,6 @@ efi_status_t efi_set_variable_int(const u16 *variable_name, /* check if a variable exists */ var = efi_var_mem_find(vendor, variable_name, NULL); append = !!(attributes & EFI_VARIABLE_APPEND_WRITE); - attributes &= ~EFI_VARIABLE_APPEND_WRITE; delete = !append && (!data_size || !attributes); /* check attributes */ @@ -304,7 +303,7 @@ efi_status_t efi_set_variable_int(const u16 *variable_name, /* attributes won't be changed */ if (!delete && - ((ro_check && var->attr != attributes) || + ((ro_check && var->attr != (attributes & ~EFI_VARIABLE_APPEND_WRITE)) || (!ro_check && ((var->attr & ~EFI_VARIABLE_READ_ONLY) != (attributes & ~EFI_VARIABLE_READ_ONLY))))) { return EFI_INVALID_PARAMETER; @@ -378,7 +377,8 @@ efi_status_t efi_set_variable_int(const u16 *variable_name, for (; *old_data; ++old_data) ; ++old_data; - ret = efi_var_mem_ins(variable_name, vendor, attributes, + ret = efi_var_mem_ins(variable_name, vendor, + attributes & ~EFI_VARIABLE_APPEND_WRITE, var->length, old_data, data_size, data, time); } else { @@ -604,6 +604,5 @@ efi_status_t efi_init_variables(void) log_err("Invalid EFI variable seed\n"); } - return efi_init_secure_state(); } diff --git a/lib/efi_loader/initrddump.c b/lib/efi_loader/initrddump.c index 0004b6b042b..615119043d1 100644 --- a/lib/efi_loader/initrddump.c +++ b/lib/efi_loader/initrddump.c @@ -33,7 +33,7 @@ static bool nocolor; * 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 initrd_dp = { +static const struct efi_lo_dp_prefix initrd_dp = { .vendor = { { DEVICE_PATH_TYPE_MEDIA_DEVICE, |