From ac7606af7d4a91d6bad0e5de51b72a513e6ae440 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 14 Nov 2021 09:38:53 +0100 Subject: lmb: fix typo 'commun' %s/commun/common/ Signed-off-by: Heinrich Schuchardt Acked-by: Ilias Apalodimas --- lib/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/Kconfig b/lib/Kconfig index 70bf8e7a464..807a4c6ade0 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -793,7 +793,7 @@ config LMB Support the library logical memory blocks. config LMB_USE_MAX_REGIONS - bool "Use a commun number of memory and reserved regions in lmb lib" + bool "Use a common number of memory and reserved regions in lmb lib" depends on LMB default y help -- cgit v1.2.3 From 3961bd9b552bfb3c08664fb09f18744c6f691456 Mon Sep 17 00:00:00 2001 From: Masahisa Kojima Date: Tue, 9 Nov 2021 20:35:53 +0900 Subject: efi_loader: Reduce efi_tcg2 logging statement log_info() is used for the debug level logging statement which should use log_debug() instead. Convert it to reduce the log output. Signed-off-by: Masahisa Kojima Reviewed-by: Heinrich Schuchardt Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_tcg2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c index 189e4a5ba59..2771fd6b5fc 100644 --- a/lib/efi_loader/efi_tcg2.c +++ b/lib/efi_loader/efi_tcg2.c @@ -1472,7 +1472,7 @@ static efi_status_t tcg2_measure_boot_variable(struct udevice *dev) &var_data_size); if (!bootvar) { - log_info("%ls not found\n", boot_name); + log_debug("%ls not found\n", boot_name); continue; } -- cgit v1.2.3 From 5d49b32f0a34cc4c23da8060ac18345984c9b96c Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Fri, 12 Nov 2021 22:05:15 +0900 Subject: efi_loader: capsule: Record capsule result only if capsule is read Record capsule update result only if the capsule file is successfully read, because the capsule GUID is not sure when the file can not be read or the file is not a capsule. Without this fix, if user puts a dummy (non-capsule) file under (ESP)EFI/UpdateCapsule, U-Boot causes a synchronous abort. This also fixes use-after-free bug of the 'capsule' variable. Fixes: c74cd8bd08d1 ("efi_loader: capsule: add capsule_on_disk support") Signed-off-by: Masami Hiramatsu Reviewed-by: Ilias Apalodimas --- lib/efi_loader/efi_capsule.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c index 850937fd120..502bcfca6ec 100644 --- a/lib/efi_loader/efi_capsule.c +++ b/lib/efi_loader/efi_capsule.c @@ -1108,13 +1108,13 @@ efi_status_t efi_launch_capsules(void) log_err("Applying capsule %ls failed\n", files[i]); + /* create CapsuleXXXX */ + set_capsule_result(index, capsule, ret); + free(capsule); } else { log_err("Reading capsule %ls failed\n", files[i]); } - /* create CapsuleXXXX */ - set_capsule_result(index, capsule, ret); - /* delete a capsule either in case of success or failure */ ret = efi_capsule_delete_file(files[i]); if (ret != EFI_SUCCESS) -- cgit v1.2.3 From 43eaf5b13f31395afbef3ff89d99a4f6c1a2ba63 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Tue, 16 Nov 2021 18:46:27 +0100 Subject: efi_loader: EFI_EVENT_GROUP_BEFORE_EXIT_BOOT_SERVICES Implement the EFI_EVENT_GROUP_BEFORE_EXIT_BOOT_SERVICES event group handling. Add the definition of EFI_EVENT_GROUP_AFTER_READY_TO_BOOT. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_boottime.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'lib') diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 1823990d9bd..6fdd0ef77a9 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -71,6 +71,9 @@ const efi_guid_t efi_guid_driver_binding_protocol = /* event group ExitBootServices() invoked */ const efi_guid_t efi_guid_event_group_exit_boot_services = EFI_EVENT_GROUP_EXIT_BOOT_SERVICES; +/* event group before ExitBootServices() invoked */ +const efi_guid_t efi_guid_event_group_before_exit_boot_services = + EFI_EVENT_GROUP_BEFORE_EXIT_BOOT_SERVICES; /* event group SetVirtualAddressMap() invoked */ const efi_guid_t efi_guid_event_group_virtual_address_change = EFI_EVENT_GROUP_VIRTUAL_ADDRESS_CHANGE; @@ -2123,6 +2126,16 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle, if (!systab.boottime) goto out; + /* Notify EFI_EVENT_GROUP_BEFORE_EXIT_BOOT_SERVICES event group. */ + list_for_each_entry(evt, &efi_events, link) { + if (evt->group && + !guidcmp(evt->group, + &efi_guid_event_group_before_exit_boot_services)) { + efi_signal_event(evt); + break; + } + } + /* Stop all timer related activities */ timers_enabled = false; -- cgit v1.2.3 From 22ad3f5f7b31e2ff3e3415047c584dfdff388aea Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Wed, 17 Nov 2021 18:52:35 +0100 Subject: efi_selftest: unit test for EFI_GROUP_BEFORE_EXIT_BOOT_SERVICE Add a test for the EFI_GROUP_BEFORE_EXIT_BOOT_SERVICE event group. Signed-off-by: Heinrich Schuchardt --- lib/efi_selftest/efi_selftest_exitbootservices.c | 67 ++++++++++++++++++++---- 1 file changed, 56 insertions(+), 11 deletions(-) (limited to 'lib') diff --git a/lib/efi_selftest/efi_selftest_exitbootservices.c b/lib/efi_selftest/efi_selftest_exitbootservices.c index 4fecd1b4151..59ab15407a0 100644 --- a/lib/efi_selftest/efi_selftest_exitbootservices.c +++ b/lib/efi_selftest/efi_selftest_exitbootservices.c @@ -10,9 +10,34 @@ #include +static efi_guid_t guid_before_exit_boot_services = + EFI_GUID(0x8be0e274, 0x3970, 0x4b44, 0x80, 0xc5, + 0x1a, 0xb9, 0x50, 0x2f, 0x3b, 0xfc); +#define CAPACITY 4 + +struct notification_record { + unsigned int count; + unsigned int type[CAPACITY]; +}; + +struct notification_context { + struct notification_record *record; + unsigned int type; +}; + static struct efi_boot_services *boottime; static struct efi_event *event_notify; -static unsigned int notification_count; +struct notification_record record; + +struct notification_context context_before = { + .record = &record, + .type = 1, +}; + +struct notification_context context = { + .record = &record, + .type = 2, +}; /* * Notification function, increments the notification count. @@ -20,11 +45,15 @@ static unsigned int notification_count; * @event notified event * @context pointer to the notification count */ -static void EFIAPI notify(struct efi_event *event, void *context) +static void EFIAPI ebs_notify(struct efi_event *event, void *context) { - unsigned int *count = context; + struct notification_context *ctx = context; + + if (ctx->record->count >= CAPACITY) + return; - ++*count; + ctx->record->type[ctx->record->count] = ctx->type; + ctx->record->count++; } /* @@ -43,15 +72,23 @@ static int setup(const efi_handle_t handle, boottime = systable->boottime; - notification_count = 0; ret = boottime->create_event(EVT_SIGNAL_EXIT_BOOT_SERVICES, - TPL_CALLBACK, notify, - (void *)¬ification_count, + TPL_CALLBACK, ebs_notify, + &context, &event_notify); if (ret != EFI_SUCCESS) { efi_st_error("could not create event\n"); return EFI_ST_FAILURE; } + ret = boottime->create_event_ex(0, TPL_CALLBACK, ebs_notify, + &context_before, + &guid_before_exit_boot_services, + &event_notify); + if (ret != EFI_SUCCESS) { + efi_st_error("could not create event\n"); + return EFI_ST_FAILURE; + } + return EFI_ST_SUCCESS; } @@ -68,13 +105,21 @@ static int setup(const efi_handle_t handle, */ static int execute(void) { - if (notification_count != 1) { - efi_st_error("ExitBootServices was not notified\n"); + if (record.count != 2) { + efi_st_error("Incorrect event count %u\n", record.count); + return EFI_ST_FAILURE; + } + if (record.type[0] != 1) { + efi_st_error("EFI_GROUP_BEFORE_EXIT_BOOT_SERVICE not notified\n"); + return EFI_ST_FAILURE; + } + if (record.type[1] != 2) { + efi_st_error("EVT_SIGNAL_EXIT_BOOT_SERVICES was not notified\n"); return EFI_ST_FAILURE; } efi_st_exit_boot_services(); - if (notification_count != 1) { - efi_st_error("ExitBootServices was notified twice\n"); + if (record.count != 2) { + efi_st_error("Incorrect event count %u\n", record.count); return EFI_ST_FAILURE; } return EFI_ST_SUCCESS; -- cgit v1.2.3 From 5ba0397049b4ad5e2e23e47a8ae412e2d9044c67 Mon Sep 17 00:00:00 2001 From: Ilias Apalodimas Date: Thu, 18 Nov 2021 09:03:39 +0200 Subject: efi_loader: fix FinalEvents table if an EFI app invoked GetEventLog As described in the TCG spec [1] in sections 7.1.1 and 7.1.2 the FinalEvent table should include events after GetEventLog has been called. This currently works for us as long as the kernel is the only EFI application calling that. Specifically we only implement what's described in 7.1.1. So refactor the code a bit and support EFI application(s) calling GetEventLog. Events will now be logged in both the EventLog and FinalEvent table as long as ExitBootServices haven't been invoked. [1] https://trustedcomputinggroup.org/wp-content/uploads/EFI-Protocol-Specification-rev13-160330final.pdf Signed-off-by: Ilias Apalodimas --- lib/efi_loader/efi_tcg2.c | 99 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 70 insertions(+), 29 deletions(-) (limited to 'lib') diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c index 2771fd6b5fc..6e32f520895 100644 --- a/lib/efi_loader/efi_tcg2.c +++ b/lib/efi_loader/efi_tcg2.c @@ -27,6 +27,17 @@ #include #include +/** + * struct event_log_buffer - internal eventlog management structure + * + * @buffer: eventlog buffer + * @final_buffer: finalevent config table buffer + * @pos: current position of 'buffer' + * @final_pos: current position of 'final_buffer' + * @get_event_called: true if GetEventLog has been invoked at least once + * @ebs_called: true if ExitBootServices has been invoked + * @truncated: true if the 'buffer' is truncated + */ struct event_log_buffer { void *buffer; void *final_buffer; @@ -34,6 +45,7 @@ struct event_log_buffer { size_t final_pos; /* final events config table position */ size_t last_event_size; bool get_event_called; + bool ebs_called; bool truncated; }; @@ -186,39 +198,29 @@ static efi_status_t tcg2_pcr_extend(struct udevice *dev, u32 pcr_index, return EFI_SUCCESS; } -/* tcg2_agile_log_append - Append an agile event to out eventlog +/* put_event - Append an agile event to an eventlog * * @pcr_index: PCR index * @event_type: type of event added * @digest_list: list of digest algorithms to add * @size: size of event * @event: event to add + * @log: log buffer to append the event * - * @Return: status code */ -static efi_status_t tcg2_agile_log_append(u32 pcr_index, u32 event_type, - struct tpml_digest_values *digest_list, - u32 size, u8 event[]) +static void put_event(u32 pcr_index, u32 event_type, + struct tpml_digest_values *digest_list, u32 size, + u8 event[], void *log) { - void *log = (void *)((uintptr_t)event_log.buffer + event_log.pos); size_t pos; size_t i; u32 event_size; - if (event_log.get_event_called) - log = (void *)((uintptr_t)event_log.final_buffer + - event_log.final_pos); - /* * size refers to the length of event[] only, we need to check against * the final tcg_pcr_event2 size */ event_size = size + tcg_event_final_size(digest_list); - if (event_log.pos + event_size > TPM2_EVENT_LOG_SIZE || - event_log.final_pos + event_size > TPM2_EVENT_LOG_SIZE) { - event_log.truncated = true; - return EFI_VOLUME_FULL; - } put_unaligned_le32(pcr_index, log); pos = offsetof(struct tcg_pcr_event2, event_type); @@ -242,25 +244,62 @@ static efi_status_t tcg2_agile_log_append(u32 pcr_index, u32 event_type, memcpy((void *)((uintptr_t)log + pos), event, size); pos += size; - /* make sure the calculated buffer is what we checked against */ + /* + * make sure the calculated buffer is what we checked against + * This check should never fail. It checks the code above is + * calculating the right length for the event we are adding + */ if (pos != event_size) - return EFI_INVALID_PARAMETER; + log_err("Appending to the EventLog failed\n"); +} - /* if GetEventLog hasn't been called update the normal log */ - if (!event_log.get_event_called) { - event_log.pos += pos; - event_log.last_event_size = pos; - } else { - /* if GetEventLog has been called update config table log */ - struct efi_tcg2_final_events_table *final_event; +/* tcg2_agile_log_append - Append an agile event to an eventlog + * + * @pcr_index: PCR index + * @event_type: type of event added + * @digest_list: list of digest algorithms to add + * @size: size of event + * @event: event to add + * @log: log buffer to append the event + * + * @Return: status code + */ +static efi_status_t tcg2_agile_log_append(u32 pcr_index, u32 event_type, + struct tpml_digest_values *digest_list, + u32 size, u8 event[]) +{ + void *log = (void *)((uintptr_t)event_log.buffer + event_log.pos); + u32 event_size = size + tcg_event_final_size(digest_list); + struct efi_tcg2_final_events_table *final_event; + efi_status_t ret = EFI_SUCCESS; - final_event = - (struct efi_tcg2_final_events_table *)(event_log.final_buffer); - final_event->number_of_events++; - event_log.final_pos += pos; + /* if ExitBootServices hasn't been called update the normal log */ + if (!event_log.ebs_called) { + if (event_log.truncated || + event_log.pos + event_size > TPM2_EVENT_LOG_SIZE) { + event_log.truncated = true; + return EFI_VOLUME_FULL; + } + put_event(pcr_index, event_type, digest_list, size, event, log); + event_log.pos += event_size; + event_log.last_event_size = event_size; } - return EFI_SUCCESS; + if (!event_log.get_event_called) + return ret; + + /* if GetEventLog has been called update FinalEventLog as well */ + if (event_log.final_pos + event_size > TPM2_EVENT_LOG_SIZE) + return EFI_VOLUME_FULL; + + log = (void *)((uintptr_t)event_log.final_buffer + event_log.final_pos); + put_event(pcr_index, event_type, digest_list, size, event, log); + + final_event = event_log.final_buffer; + final_event->number_of_events++; + event_log.final_pos += event_size; + + return ret; } /** @@ -1303,6 +1342,7 @@ static efi_status_t efi_init_event_log(void) event_log.pos = 0; event_log.last_event_size = 0; event_log.get_event_called = false; + event_log.ebs_called = false; event_log.truncated = false; /* @@ -1792,6 +1832,7 @@ efi_tcg2_notify_exit_boot_services(struct efi_event *event, void *context) EFI_ENTRY("%p, %p", event, context); + event_log.ebs_called = true; ret = platform_get_tpm2_device(&dev); if (ret != EFI_SUCCESS) goto out; -- cgit v1.2.3 From d6b55a420cfce660343cc1f60e68fcad0157925a Mon Sep 17 00:00:00 2001 From: Ilias Apalodimas Date: Thu, 18 Nov 2021 10:13:42 +0200 Subject: efi_loader: startup the tpm device when installing the protocol Due to U-Boot's lazy binding mentality the TPM is probed but not properly initialized. The user can startup the device from the command line e.g 'tpm2 startup TPM2_SU_CLEAR'. However we can initialize the TPM during the TCG protocol installation, which is easier to use overall. Signed-off-by: Ilias Apalodimas Reviewed-by: Heinrich Schuchardt --- lib/efi_loader/efi_tcg2.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'lib') diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c index 6e32f520895..8c1f22e3377 100644 --- a/lib/efi_loader/efi_tcg2.c +++ b/lib/efi_loader/efi_tcg2.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -1943,6 +1944,7 @@ efi_status_t efi_tcg2_register(void) efi_status_t ret = EFI_SUCCESS; struct udevice *dev; struct efi_event *event; + u32 err; ret = platform_get_tpm2_device(&dev); if (ret != EFI_SUCCESS) { @@ -1950,6 +1952,13 @@ efi_status_t efi_tcg2_register(void) return EFI_SUCCESS; } + /* initialize the TPM as early as possible. */ + err = tpm_startup(dev, TPM_ST_CLEAR); + if (err) { + log_err("TPM startup failed\n"); + goto fail; + } + ret = efi_init_event_log(); if (ret != EFI_SUCCESS) goto fail; -- cgit v1.2.3