diff options
Diffstat (limited to 'lib/efi_loader')
-rw-r--r-- | lib/efi_loader/Kconfig | 2 | ||||
-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/efi_bootbin.c | 2 | ||||
-rw-r--r-- | lib/efi_loader/efi_bootmgr.c | 81 | ||||
-rw-r--r-- | lib/efi_loader/efi_boottime.c | 3 | ||||
-rw-r--r-- | lib/efi_loader/efi_capsule.c | 14 | ||||
-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_fdt.c | 117 | ||||
-rw-r--r-- | lib/efi_loader/efi_helper.c | 44 | ||||
-rw-r--r-- | lib/efi_loader/efi_image_loader.c | 13 | ||||
-rw-r--r-- | lib/efi_loader/efi_load_initrd.c | 2 | ||||
-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 | 6 | ||||
-rw-r--r-- | lib/efi_loader/initrddump.c | 2 |
18 files changed, 374 insertions, 107 deletions
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index 430bb7f0f7d..ee71f417147 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 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/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..304ed43595c 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(&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..eedc5f39549 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) diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c index de0d49ebebd..0937800e588 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; 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_fdt.c b/lib/efi_loader/efi_fdt.c new file mode 100644 index 00000000000..86ba00c2bdd --- /dev/null +++ b/lib/efi_loader/efi_fdt.c @@ -0,0 +1,117 @@ +// 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> + +/** + * distro_efi_get_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; + 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 + * + * @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) +{ + struct efi_device_path *rem, *dp; + efi_status_t ret; + efi_handle_t device; + + *fdt = NULL; + + dp = efi_get_dp_from_boot(NULL); + if (!dp) + return; + device = efi_dp_find_obj(dp, NULL, &rem); + ret = efi_search_protocol(device, &efi_simple_file_system_protocol_guid, + NULL); + if (ret != EFI_SUCCESS) + goto err; + memcpy(rem, &END, sizeof(END)); + + /* 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) + break; + } + +err: + efi_free_pool(dp); +} diff --git a/lib/efi_loader/efi_helper.c b/lib/efi_loader/efi_helper.c index 73d0279e843..348612c3dad 100644 --- a/lib/efi_loader/efi_helper.c +++ b/lib/efi_loader/efi_helper.c @@ -99,6 +99,50 @@ err: return NULL; } +/** + * 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 { efi_guid_t guid; const char algo[32]; diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c index 60424360328..45dc5b6b244 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. @@ -986,7 +981,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_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..09651d4675b 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 { 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, |