[PATCH v7 1/3] bloblist: add api to get blob with size

bloblist_find function only returns the pointer of blob data, which is fine for those self-describing data like FDT. But as a common scenario, an interface is needed to retrieve both the pointer and the size of the blob data.
Add a few ut test cases for the new api.
Signed-off-by: Raymond Mao raymond.mao@linaro.org Reviewed-by: Simon Glass sjg@chromium.org Reviewed-by: Ilias Apalodimas ilias.apalodimas@linaro.org --- Changes in v2 - Rename function argument. - Add ut tests. Changes in v3 - None. Changes in v4 - None. Changes in v5 - None. Changes in v6 - None. Changes in v7 - None.
common/bloblist.c | 17 +++++++++++++++-- include/bloblist.h | 18 ++++++++++++++++++ test/common/bloblist.c | 4 ++++ 3 files changed, 37 insertions(+), 2 deletions(-)
diff --git a/common/bloblist.c b/common/bloblist.c index 110bb9dc44..ab48a3cdb9 100644 --- a/common/bloblist.c +++ b/common/bloblist.c @@ -222,14 +222,27 @@ static int bloblist_ensurerec(uint tag, struct bloblist_rec **recp, int size, }
void *bloblist_find(uint tag, int size) +{ + void *blob = NULL; + int blob_size; + + blob = bloblist_get_blob(tag, &blob_size); + + if (size && size != blob_size) + return NULL; + + return blob; +} + +void *bloblist_get_blob(uint tag, int *sizep) { struct bloblist_rec *rec;
rec = bloblist_findrec(tag); if (!rec) return NULL; - if (size && size != rec->size) - return NULL; + + *sizep = rec->size;
return (void *)rec + rec_hdr_size(rec); } diff --git a/include/bloblist.h b/include/bloblist.h index f999391f74..52ba0ddcf8 100644 --- a/include/bloblist.h +++ b/include/bloblist.h @@ -250,6 +250,24 @@ static inline void *bloblist_check_magic(ulong addr) return ptr; }
+#if CONFIG_IS_ENABLED(BLOBLIST) +/** + * bloblist_get_blob() - Find a blob and get the size of it + * + * Searches the bloblist and returns the blob with the matching tag + * + * @tag: Tag to search for (enum bloblist_tag_t) + * @sizep: Size of the blob found + * Return: pointer to bloblist if found, or NULL if not found + */ +void *bloblist_get_blob(uint tag, int *sizep); +#else +static inline void *bloblist_get_blob(uint tag, int *sizep) +{ + return NULL; +} +#endif + /** * bloblist_find() - Find a blob * diff --git a/test/common/bloblist.c b/test/common/bloblist.c index 4bca62110a..324127596f 100644 --- a/test/common/bloblist.c +++ b/test/common/bloblist.c @@ -98,10 +98,12 @@ static int bloblist_test_blob(struct unit_test_state *uts) struct bloblist_hdr *hdr; struct bloblist_rec *rec, *rec2; char *data; + int size = 0;
/* At the start there should be no records */ hdr = clear_bloblist(); ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE)); + ut_assertnull(bloblist_get_blob(TEST_TAG, &size)); ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0)); ut_asserteq(sizeof(struct bloblist_hdr), bloblist_get_size()); ut_asserteq(TEST_BLOBLIST_SIZE, bloblist_get_total_size()); @@ -114,6 +116,8 @@ static int bloblist_test_blob(struct unit_test_state *uts) ut_asserteq_addr(rec + 1, data); data = bloblist_find(TEST_TAG, TEST_SIZE); ut_asserteq_addr(rec + 1, data); + ut_asserteq_addr(bloblist_get_blob(TEST_TAG, &size), data); + ut_asserteq(size, TEST_SIZE);
/* Check the data is zeroed */ ut_assertok(check_zero(data, TEST_SIZE));

Move default eventlog size from efi to tpm for using in both efi and measured boot.
Signed-off-by: Raymond Mao raymond.mao@linaro.org Reviewed-by: Ilias Apalodimas ilias.apalodimas@linaro.org --- Changes in v5 - Move eventlog size kconfig from EFI to TPM2, so that it can be used by both EFI and MEASURED_BOOT. Changes in v6 - None. Changes in v7 - None.
doc/usage/measured_boot.rst | 1 - drivers/tpm/Kconfig | 9 +++++++++ include/efi_tcg2.h | 2 -- lib/efi_loader/Kconfig | 9 --------- lib/efi_loader/efi_tcg2.c | 15 ++++++++------- 5 files changed, 17 insertions(+), 19 deletions(-)
diff --git a/doc/usage/measured_boot.rst b/doc/usage/measured_boot.rst index 05c439e9ac..488dd546f1 100644 --- a/doc/usage/measured_boot.rst +++ b/doc/usage/measured_boot.rst @@ -24,7 +24,6 @@ Requirements
* A hardware TPM 2.0 supported by an enabled U-Boot driver * CONFIG_EFI_TCG2_PROTOCOL=y -* CONFIG_EFI_TCG2_PROTOCOL_EVENTLOG_SIZE=y * optional CONFIG_EFI_TCG2_PROTOCOL_MEASURE_DTB=y will measure the loaded DTB in PCR 1
diff --git a/drivers/tpm/Kconfig b/drivers/tpm/Kconfig index d59102d9a6..01bc686d36 100644 --- a/drivers/tpm/Kconfig +++ b/drivers/tpm/Kconfig @@ -209,6 +209,15 @@ config TPM2_MMIO to the device using the standard TPM Interface Specification (TIS) protocol.
+config TPM2_EVENT_LOG_SIZE + int "EventLog size" + depends on TPM_V2 + default 65536 + help + Define the size of the EventLog. Note that this is going to be + allocated twice. One for the eventlog it self and one for the + configuration table that is required from the TCG2 spec + endif # TPM_V2
endmenu diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h index 8dfb1bc952..7ed8880991 100644 --- a/include/efi_tcg2.h +++ b/include/efi_tcg2.h @@ -28,8 +28,6 @@ #define EFI_TCG2_MAX_PCR_INDEX 23 #define EFI_TCG2_FINAL_EVENTS_TABLE_VERSION 1
-#define TPM2_EVENT_LOG_SIZE CONFIG_EFI_TCG2_PROTOCOL_EVENTLOG_SIZE - typedef u32 efi_tcg_event_log_bitmap; typedef u32 efi_tcg_event_log_format; typedef u32 efi_tcg_event_algorithm_bitmap; diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index c46ffe3a9d..d703e901ed 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -437,15 +437,6 @@ config EFI_TCG2_PROTOCOL Provide a EFI_TCG2_PROTOCOL implementation using the TPM hardware of the platform.
-config EFI_TCG2_PROTOCOL_EVENTLOG_SIZE - int "EFI_TCG2_PROTOCOL EventLog size" - depends on EFI_TCG2_PROTOCOL - default 65536 - help - Define the size of the EventLog for EFI_TCG2_PROTOCOL. Note that - 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 diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c index a15c73162e..6dba8b1406 100644 --- a/lib/efi_loader/efi_tcg2.c +++ b/lib/efi_loader/efi_tcg2.c @@ -111,7 +111,7 @@ static efi_status_t tcg2_agile_log_append(u32 pcr_index, u32 event_type, /* 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.pos + event_size > CONFIG_TPM2_EVENT_LOG_SIZE) { event_log.truncated = true; return EFI_VOLUME_FULL; } @@ -124,7 +124,7 @@ static efi_status_t tcg2_agile_log_append(u32 pcr_index, u32 event_type, return ret;
/* if GetEventLog has been called update FinalEventLog as well */ - if (event_log.final_pos + event_size > TPM2_EVENT_LOG_SIZE) + if (event_log.final_pos + event_size > CONFIG_TPM2_EVENT_LOG_SIZE) return EFI_VOLUME_FULL;
log = (void *)((uintptr_t)event_log.final_buffer + event_log.final_pos); @@ -822,12 +822,12 @@ static efi_status_t create_final_event(void) * EFI_TCG2_GET_EVENT_LOGS need to be stored in an instance of an * EFI_CONFIGURATION_TABLE */ - ret = efi_allocate_pool(EFI_ACPI_MEMORY_NVS, TPM2_EVENT_LOG_SIZE, + ret = efi_allocate_pool(EFI_ACPI_MEMORY_NVS, CONFIG_TPM2_EVENT_LOG_SIZE, &event_log.final_buffer); if (ret != EFI_SUCCESS) goto out;
- memset(event_log.final_buffer, 0xff, TPM2_EVENT_LOG_SIZE); + memset(event_log.final_buffer, 0xff, CONFIG_TPM2_EVENT_LOG_SIZE); final_event = event_log.final_buffer; final_event->number_of_events = 0; final_event->version = EFI_TCG2_FINAL_EVENTS_TABLE_VERSION; @@ -913,7 +913,8 @@ static efi_status_t efi_init_event_log(void) if (tcg2_platform_get_tpm2(&dev)) return EFI_DEVICE_ERROR;
- ret = efi_allocate_pool(EFI_BOOT_SERVICES_DATA, TPM2_EVENT_LOG_SIZE, + ret = efi_allocate_pool(EFI_BOOT_SERVICES_DATA, + CONFIG_TPM2_EVENT_LOG_SIZE, (void **)&event_log.buffer); if (ret != EFI_SUCCESS) return ret; @@ -922,7 +923,7 @@ static efi_status_t efi_init_event_log(void) * initialize log area as 0xff so the OS can easily figure out the * last log entry */ - memset(event_log.buffer, 0xff, TPM2_EVENT_LOG_SIZE); + memset(event_log.buffer, 0xff, CONFIG_TPM2_EVENT_LOG_SIZE);
/* * The log header is defined to be in SHA1 event log entry format. @@ -939,7 +940,7 @@ static efi_status_t efi_init_event_log(void) * platforms can use different ways to do so. */ elog.log = event_log.buffer; - elog.log_size = TPM2_EVENT_LOG_SIZE; + elog.log_size = CONFIG_TPM2_EVENT_LOG_SIZE; rc = tcg2_log_prepare_buffer(dev, &elog, false); if (rc) { ret = (rc == -ENOBUFS) ? EFI_BUFFER_TOO_SMALL : EFI_DEVICE_ERROR;

Get tpm event log from bloblist instead of FDT when bloblist is enabled and valid from previous boot stage.
Signed-off-by: Raymond Mao raymond.mao@linaro.org --- Changes in v2 - Remove patch dependency. - Remove the fallback to FDT when BLOBLIST is selected. Changes in v3 - Malloc an 8KB buffer when user eventlog buffer does not exist. Changes in v4 - Replace the default eventlog size with TPM2_EVENT_LOG_SIZE. Changes in v5 - Replace TPM2_EVENT_LOG_SIZE with CONFIG_TPM2_EVENT_LOG_SIZE. - Add an inline TODO comment. Changes in v6 - Remove the malloc and keep the buffer pointed by "sml" for the fallback as it is the right place for linux to discover the eventlog. Changes in v7 - Remove '#include <malloc.h>'. - Add mapping for the blob address.
lib/tpm_tcg2.c | 59 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 20 deletions(-)
diff --git a/lib/tpm_tcg2.c b/lib/tpm_tcg2.c index 4134d93a35..adb32a14f0 100644 --- a/lib/tpm_tcg2.c +++ b/lib/tpm_tcg2.c @@ -19,6 +19,7 @@ #include <linux/unaligned/generic.h> #include <linux/unaligned/le_byteshift.h> #include "tpm-utils.h" +#include <bloblist.h>
int tcg2_get_pcr_info(struct udevice *dev, u32 *supported_bank, u32 *active_bank, u32 *bank_num) @@ -672,21 +673,42 @@ void tcg2_measurement_term(struct udevice *dev, struct tcg2_event_log *elog,
__weak int tcg2_platform_get_log(struct udevice *dev, void **addr, u32 *size) { - const __be32 *addr_prop; - const __be32 *size_prop; + const __be32 *addr_prop = NULL; + const __be32 *size_prop = NULL; int asize; int ssize; + struct ofnode_phandle_args args; + phys_addr_t a; + fdt_size_t s;
*addr = NULL; *size = 0;
- addr_prop = dev_read_prop(dev, "tpm_event_log_addr", &asize); - if (!addr_prop) - addr_prop = dev_read_prop(dev, "linux,sml-base", &asize); + *addr = bloblist_get_blob(BLOBLISTT_TPM_EVLOG, size); + if (*addr && *size) { + *addr = map_physmem((uintptr_t)(*addr), *size, MAP_NOCACHE); + return 0; + }
- size_prop = dev_read_prop(dev, "tpm_event_log_size", &ssize); - if (!size_prop) + /* + * TODO: + * Replace BLOBLIST with a new kconfig for handoff all components + * (fdt, tpm event log, etc...) from previous boot stage via bloblist + * mandatorily following Firmware Handoff spec. + */ + if (!CONFIG_IS_ENABLED(BLOBLIST)) { + addr_prop = dev_read_prop(dev, "tpm_event_log_addr", &asize); + size_prop = dev_read_prop(dev, "tpm_event_log_size", &ssize); + } + + /* + * If no eventlog was observed, a sml buffer is required for the kernel + * to discover the eventlog. + */ + if (!addr_prop || !size_prop) { + addr_prop = dev_read_prop(dev, "linux,sml-base", &asize); size_prop = dev_read_prop(dev, "linux,sml-size", &ssize); + }
if (addr_prop && size_prop) { u64 a = of_read_number(addr_prop, asize / sizeof(__be32)); @@ -694,22 +716,19 @@ __weak int tcg2_platform_get_log(struct udevice *dev, void **addr, u32 *size)
*addr = map_physmem(a, s, MAP_NOCACHE); *size = (u32)s; - } else { - struct ofnode_phandle_args args; - phys_addr_t a; - fdt_size_t s;
- if (dev_read_phandle_with_args(dev, "memory-region", NULL, 0, - 0, &args)) - return -ENODEV; + return 0; + }
- a = ofnode_get_addr_size(args.node, "reg", &s); - if (a == FDT_ADDR_T_NONE) - return -ENOMEM; + if (dev_read_phandle_with_args(dev, "memory-region", NULL, 0, 0, &args)) + return -ENODEV;
- *addr = map_physmem(a, s, MAP_NOCACHE); - *size = (u32)s; - } + a = ofnode_get_addr_size(args.node, "reg", &s); + if (a == FDT_ADDR_T_NONE) + return -ENOMEM; + + *addr = map_physmem(a, s, MAP_NOCACHE); + *size = (u32)s;
return 0; }

On Mon, 27 Jan 2025 at 16:50, Raymond Mao raymond.mao@linaro.org wrote:
Get tpm event log from bloblist instead of FDT when bloblist is enabled and valid from previous boot stage.
Signed-off-by: Raymond Mao raymond.mao@linaro.org
Changes in v2
- Remove patch dependency.
- Remove the fallback to FDT when BLOBLIST is selected.
Changes in v3
- Malloc an 8KB buffer when user eventlog buffer does not exist.
Changes in v4
- Replace the default eventlog size with TPM2_EVENT_LOG_SIZE.
Changes in v5
- Replace TPM2_EVENT_LOG_SIZE with CONFIG_TPM2_EVENT_LOG_SIZE.
- Add an inline TODO comment.
Changes in v6
- Remove the malloc and keep the buffer pointed by "sml" for the fallback as it is the right place for linux to discover the eventlog.
Changes in v7
- Remove '#include <malloc.h>'.
- Add mapping for the blob address.
lib/tpm_tcg2.c | 59 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 20 deletions(-)
diff --git a/lib/tpm_tcg2.c b/lib/tpm_tcg2.c index 4134d93a35..adb32a14f0 100644 --- a/lib/tpm_tcg2.c +++ b/lib/tpm_tcg2.c @@ -19,6 +19,7 @@ #include <linux/unaligned/generic.h> #include <linux/unaligned/le_byteshift.h> #include "tpm-utils.h" +#include <bloblist.h>
int tcg2_get_pcr_info(struct udevice *dev, u32 *supported_bank, u32 *active_bank, u32 *bank_num) @@ -672,21 +673,42 @@ void tcg2_measurement_term(struct udevice *dev, struct tcg2_event_log *elog,
__weak int tcg2_platform_get_log(struct udevice *dev, void **addr, u32 *size) {
const __be32 *addr_prop;
const __be32 *size_prop;
const __be32 *addr_prop = NULL;
const __be32 *size_prop = NULL; int asize; int ssize;
struct ofnode_phandle_args args;
phys_addr_t a;
fdt_size_t s; *addr = NULL; *size = 0;
addr_prop = dev_read_prop(dev, "tpm_event_log_addr", &asize);
if (!addr_prop)
addr_prop = dev_read_prop(dev, "linux,sml-base", &asize);
*addr = bloblist_get_blob(BLOBLISTT_TPM_EVLOG, size);
if (*addr && *size) {
*addr = map_physmem((uintptr_t)(*addr), *size, MAP_NOCACHE);
return 0;
}
size_prop = dev_read_prop(dev, "tpm_event_log_size", &ssize);
if (!size_prop)
/*
* TODO:
* Replace BLOBLIST with a new kconfig for handoff all components
* (fdt, tpm event log, etc...) from previous boot stage via bloblist
* mandatorily following Firmware Handoff spec.
*/
if (!CONFIG_IS_ENABLED(BLOBLIST)) {
addr_prop = dev_read_prop(dev, "tpm_event_log_addr", &asize);
size_prop = dev_read_prop(dev, "tpm_event_log_size", &ssize);
}
/*
* If no eventlog was observed, a sml buffer is required for the kernel
* to discover the eventlog.
*/
if (!addr_prop || !size_prop) {
addr_prop = dev_read_prop(dev, "linux,sml-base", &asize); size_prop = dev_read_prop(dev, "linux,sml-size", &ssize);
} if (addr_prop && size_prop) { u64 a = of_read_number(addr_prop, asize / sizeof(__be32));
@@ -694,22 +716,19 @@ __weak int tcg2_platform_get_log(struct udevice *dev, void **addr, u32 *size)
*addr = map_physmem(a, s, MAP_NOCACHE); *size = (u32)s;
} else {
struct ofnode_phandle_args args;
phys_addr_t a;
fdt_size_t s;
if (dev_read_phandle_with_args(dev, "memory-region", NULL, 0,
0, &args))
return -ENODEV;
return 0;
}
a = ofnode_get_addr_size(args.node, "reg", &s);
if (a == FDT_ADDR_T_NONE)
return -ENOMEM;
if (dev_read_phandle_with_args(dev, "memory-region", NULL, 0, 0, &args))
return -ENODEV;
*addr = map_physmem(a, s, MAP_NOCACHE);
*size = (u32)s;
}
a = ofnode_get_addr_size(args.node, "reg", &s);
if (a == FDT_ADDR_T_NONE)
return -ENOMEM;
*addr = map_physmem(a, s, MAP_NOCACHE);
*size = (u32)s; return 0;
}
2.25.1
Reviewed-by: Ilias Apalodimas ilias.apalodimas@linaro.org
participants (2)
-
Ilias Apalodimas
-
Raymond Mao