summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/efi_loader/Kconfig19
-rw-r--r--lib/efi_loader/efi_capsule.c48
-rw-r--r--lib/efi_loader/efi_setup.c7
-rw-r--r--lib/efi_loader/efi_tcg2.c73
-rw-r--r--lib/efi_loader/efi_var_mem.c4
-rw-r--r--lib/efi_loader/efi_variable.c3
6 files changed, 135 insertions, 19 deletions
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index c56904afc2..c5835e6ef6 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -226,6 +226,14 @@ config EFI_CAPSULE_AUTHENTICATE
Select this option if you want to enable capsule
authentication
+config EFI_CAPSULE_MAX
+ int "Max value for capsule index"
+ default 15
+ range 0 65535
+ help
+ Select the max capsule index value used for capsule report
+ variables. This value is used to create CapsuleMax variable.
+
config EFI_DEVICE_PATH_TO_TEXT
bool "Device path to text protocol"
default y
@@ -346,6 +354,17 @@ config EFI_TCG2_PROTOCOL_EVENTLOG_SIZE
this is going to be allocated twice. One for the eventlog it self
and one for the configuration table that is required from the spec
+config EFI_TCG2_PROTOCOL_MEASURE_DTB
+ bool "Measure DTB with EFI_TCG2_PROTOCOL"
+ depends on EFI_TCG2_PROTOCOL
+ help
+ When enabled, the DTB image passed to the booted EFI image is
+ measured using the EFI TCG2 protocol. Do not enable this feature if
+ the passed DTB contains data that change across platform reboots
+ and cannot be used has a predictable measurement. Otherwise
+ this feature allows better measurement of the system boot
+ sequence.
+
config EFI_LOAD_FILE2_INITRD
bool "EFI_FILE_LOAD2_PROTOCOL for Linux initial ramdisk"
default y
diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
index 0997cd248f..d5d3ede7ae 100644
--- a/lib/efi_loader/efi_capsule.c
+++ b/lib/efi_loader/efi_capsule.c
@@ -45,17 +45,7 @@ const efi_guid_t fwu_guid_os_request_fw_accept =
static struct efi_file_handle *bootdev_root;
#endif
-/**
- * get_last_capsule - get the last capsule index
- *
- * Retrieve the index of the capsule invoked last time from "CapsuleLast"
- * variable.
- *
- * Return:
- * * > 0 - the last capsule index invoked
- * * 0xffff - on error, or no capsule invoked yet
- */
-static __maybe_unused unsigned int get_last_capsule(void)
+static __maybe_unused unsigned int get_capsule_index(const u16 *variable_name)
{
u16 value16[11]; /* "CapsuleXXXX": non-null-terminated */
char value[5];
@@ -65,7 +55,7 @@ static __maybe_unused unsigned int get_last_capsule(void)
int i;
size = sizeof(value16);
- ret = efi_get_variable_int(u"CapsuleLast", &efi_guid_capsule_report,
+ ret = efi_get_variable_int(variable_name, &efi_guid_capsule_report,
NULL, &size, value16, NULL);
if (ret != EFI_SUCCESS || size != 22 ||
u16_strncmp(value16, u"Capsule", 7))
@@ -85,6 +75,35 @@ err:
}
/**
+ * get_last_capsule - get the last capsule index
+ *
+ * Retrieve the index of the capsule invoked last time from "CapsuleLast"
+ * variable.
+ *
+ * Return:
+ * * > 0 - the last capsule index invoked
+ * * 0xffff - on error, or no capsule invoked yet
+ */
+static __maybe_unused unsigned int get_last_capsule(void)
+{
+ return get_capsule_index(u"CapsuleLast");
+}
+
+/**
+ * get_max_capsule - get the max capsule index
+ *
+ * Retrieve the max capsule index value from "CapsuleMax" variable.
+ *
+ * Return:
+ * * > 0 - the max capsule index
+ * * 0xffff - on error, or "CapsuleMax" variable does not exist
+ */
+static __maybe_unused unsigned int get_max_capsule(void)
+{
+ return get_capsule_index(u"CapsuleMax");
+}
+
+/**
* set_capsule_result - set a result variable
* @capsule: Capsule
* @return_status: Return status
@@ -1290,7 +1309,7 @@ efi_status_t efi_launch_capsules(void)
{
struct efi_capsule_header *capsule = NULL;
u16 **files;
- unsigned int nfiles, index, i;
+ unsigned int nfiles, index, index_max, i;
efi_status_t ret;
bool capsule_update = true;
bool update_status = true;
@@ -1299,6 +1318,7 @@ efi_status_t efi_launch_capsules(void)
if (check_run_capsules() != EFI_SUCCESS)
return EFI_SUCCESS;
+ index_max = get_max_capsule();
index = get_last_capsule();
/*
@@ -1317,7 +1337,7 @@ efi_status_t efi_launch_capsules(void)
/* Launch capsules */
for (i = 0, ++index; i < nfiles; i++, index++) {
log_debug("Applying %ls\n", files[i]);
- if (index > 0xffff)
+ if (index > index_max)
index = 0;
ret = efi_capsule_read_file(files[i], &capsule);
if (ret == EFI_SUCCESS) {
diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c
index 69aaefab63..58d4e13402 100644
--- a/lib/efi_loader/efi_setup.c
+++ b/lib/efi_loader/efi_setup.c
@@ -130,12 +130,17 @@ static efi_status_t efi_init_capsule(void)
efi_status_t ret = EFI_SUCCESS;
if (IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT)) {
+ u16 var_name16[12];
+
+ efi_create_indexed_name(var_name16, sizeof(var_name16),
+ "Capsule", CONFIG_EFI_CAPSULE_MAX);
+
ret = efi_set_variable_int(u"CapsuleMax",
&efi_guid_capsule_report,
EFI_VARIABLE_READ_ONLY |
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS,
- 22, u"CapsuleFFFF", false);
+ 22, var_name16, false);
if (ret != EFI_SUCCESS)
printf("EFI: cannot initialize CapsuleMax variable\n");
}
diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
index 918e9a2686..2dcc317157 100644
--- a/lib/efi_loader/efi_tcg2.c
+++ b/lib/efi_loader/efi_tcg2.c
@@ -2175,6 +2175,79 @@ out1:
return ret;
}
+/* Return the byte size of reserved map area in DTB or -1 upon error */
+static ssize_t size_of_rsvmap(void *dtb)
+{
+ struct fdt_reserve_entry e;
+ ssize_t size_max;
+ ssize_t size;
+ u8 *rsvmap_base;
+
+ rsvmap_base = (u8 *)dtb + fdt_off_mem_rsvmap(dtb);
+ size_max = fdt_totalsize(dtb) - fdt_off_mem_rsvmap(dtb);
+ size = 0;
+
+ do {
+ memcpy(&e, rsvmap_base + size, sizeof(e));
+ size += sizeof(e);
+ if (size > size_max)
+ return -1;
+ } while (e.size);
+
+ return size;
+}
+
+/**
+ * efi_tcg2_measure_dtb() - measure DTB passed to the OS
+ *
+ * @dtb: pointer to the device tree blob
+ *
+ * Return: status code
+ */
+efi_status_t efi_tcg2_measure_dtb(void *dtb)
+{
+ struct uefi_platform_firmware_blob2 *blob;
+ struct fdt_header *header;
+ sha256_context hash_ctx;
+ struct udevice *dev;
+ ssize_t rsvmap_size;
+ efi_status_t ret;
+ u32 event_size;
+
+ if (!is_tcg2_protocol_installed())
+ return EFI_SUCCESS;
+
+ ret = platform_get_tpm2_device(&dev);
+ if (ret != EFI_SUCCESS)
+ return EFI_SECURITY_VIOLATION;
+
+ rsvmap_size = size_of_rsvmap(dtb);
+ if (rsvmap_size < 0)
+ return EFI_SECURITY_VIOLATION;
+
+ event_size = sizeof(*blob) + sizeof(EFI_DTB_EVENT_STRING) + SHA256_SUM_LEN;
+ blob = calloc(1, event_size);
+ if (!blob)
+ return EFI_OUT_OF_RESOURCES;
+
+ blob->blob_description_size = sizeof(EFI_DTB_EVENT_STRING);
+ memcpy(blob->data, EFI_DTB_EVENT_STRING, blob->blob_description_size);
+
+ /* Measure populated areas of the DTB */
+ header = dtb;
+ sha256_starts(&hash_ctx);
+ sha256_update(&hash_ctx, (u8 *)header, sizeof(struct fdt_header));
+ sha256_update(&hash_ctx, (u8 *)dtb + fdt_off_dt_struct(dtb), fdt_size_dt_strings(dtb));
+ sha256_update(&hash_ctx, (u8 *)dtb + fdt_off_dt_strings(dtb), fdt_size_dt_struct(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 = tcg2_measure_event(dev, 0, EV_POST_CODE, event_size, (u8 *)blob);
+
+ free(blob);
+ return ret;
+}
+
/**
* efi_tcg2_measure_efi_app_invocation() - measure efi app invocation
*
diff --git a/lib/efi_loader/efi_var_mem.c b/lib/efi_loader/efi_var_mem.c
index e1058e3c6a..d6b65aed12 100644
--- a/lib/efi_loader/efi_var_mem.c
+++ b/lib/efi_loader/efi_var_mem.c
@@ -41,11 +41,13 @@ efi_var_mem_compare(struct efi_var_entry *var, const efi_guid_t *guid,
i < sizeof(efi_guid_t) && match; ++i)
match = (guid1[i] == guid2[i]);
- for (data = var->name, var_name = name;; ++data, ++var_name) {
+ for (data = var->name, var_name = name;; ++data) {
if (match)
match = (*data == *var_name);
if (!*data)
break;
+ if (*var_name)
+ ++var_name;
}
++data;
diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c
index 4c85cfa607..5804f69954 100644
--- a/lib/efi_loader/efi_variable.c
+++ b/lib/efi_loader/efi_variable.c
@@ -366,9 +366,6 @@ efi_status_t efi_query_variable_info_int(u32 attributes,
EFI_VARIABLE_RUNTIME_ACCESS)
return EFI_INVALID_PARAMETER;
- if (attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD)
- return EFI_UNSUPPORTED;
-
if (attributes & ~(u32)EFI_VARIABLE_MASK)
return EFI_INVALID_PARAMETER;