summaryrefslogtreecommitdiff
path: root/lib/efi_loader
diff options
context:
space:
mode:
Diffstat (limited to 'lib/efi_loader')
-rw-r--r--lib/efi_loader/Kconfig2
-rw-r--r--lib/efi_loader/Makefile1
-rw-r--r--lib/efi_loader/capsule_esl.dtsi.in4
-rw-r--r--lib/efi_loader/efi_bootbin.c2
-rw-r--r--lib/efi_loader/efi_bootmgr.c81
-rw-r--r--lib/efi_loader/efi_boottime.c3
-rw-r--r--lib/efi_loader/efi_capsule.c14
-rw-r--r--lib/efi_loader/efi_device_path.c40
-rw-r--r--lib/efi_loader/efi_device_path_utilities.c2
-rw-r--r--lib/efi_loader/efi_fdt.c117
-rw-r--r--lib/efi_loader/efi_helper.c44
-rw-r--r--lib/efi_loader/efi_image_loader.c13
-rw-r--r--lib/efi_loader/efi_load_initrd.c2
-rw-r--r--lib/efi_loader/efi_runtime.c7
-rw-r--r--lib/efi_loader/efi_signature.c1
-rw-r--r--lib/efi_loader/efi_tcg2.c140
-rw-r--r--lib/efi_loader/efi_variable.c6
-rw-r--r--lib/efi_loader/initrddump.c2
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,