On 11/30/20 10:47 AM, Ilias Apalodimas wrote: > In the previous patches we only introduced a minimal subset of the > EFI_TCG2_PROTOCOL protocol implementing GetCapability(). > So let's continue adding features to it, introducing the > GetEventLog() and HashLogExtendEvent() functions. > > In order to do that we first need to construct the eventlog in memory, > specifically in EFI_BOOT_SERVICES_DATA memory and a configuration table > from EFI_ACPI_MEMORY_NVS. > U-Boot won't currently add any events to the log or measure any > components, but will expose the necessary EFI APIs for applications > to do so. > > Signed-off-by: Ilias Apalodimas <ilias.apalodi...@linaro.org> > --- > include/efi_api.h | 4 + > include/efi_tcg2.h | 71 ++++- > lib/efi_loader/Kconfig | 9 + > lib/efi_loader/efi_setup.c | 12 +- > lib/efi_loader/efi_tcg2.c | 553 +++++++++++++++++++++++++++++++++++-- > 5 files changed, 625 insertions(+), 24 deletions(-) > > diff --git a/include/efi_api.h b/include/efi_api.h > index 5744f6aed86d..364c578a3b1b 100644 > --- a/include/efi_api.h > +++ b/include/efi_api.h > @@ -356,6 +356,10 @@ struct efi_runtime_services { > EFI_GUID(0x4006c0c1, 0xfcb3, 0x403e, \ > 0x99, 0x6d, 0x4a, 0x6c, 0x87, 0x24, 0xe0, 0x6d) > > +#define EFI_TCG2_FINAL_EVENTS_TABLE_GUID \ > + EFI_GUID(0x1e2ed096, 0x30e2, 0x4254, 0xbd, \ > + 0x89, 0x86, 0x3b, 0xbe, 0xf8, 0x23, 0x25) > + > struct efi_configuration_table { > efi_guid_t guid; > void *table; > diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h > index 86b8fe4c01af..40e241ce315c 100644 > --- a/include/efi_tcg2.h > +++ b/include/efi_tcg2.h > @@ -17,6 +17,8 @@ > > /* TPMV2 only */ > #define TCG2_EVENT_LOG_FORMAT_TCG_2 0x00000002 > +#define EFI_TCG2_EXTEND_ONLY 0x0000000000000001 > +#define PE_COFF_IMAGE 0x0000000000000010 > > /* Algorithm Registry */ > #define EFI_TCG2_BOOT_HASH_ALG_SHA1 0x00000001 > @@ -25,6 +27,10 @@ > #define EFI_TCG2_BOOT_HASH_ALG_SHA512 0x00000008 > #define EFI_TCG2_BOOT_HASH_ALG_SM3_256 0x00000010 > > +#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; > @@ -65,6 +71,68 @@ struct efi_tcg2_boot_service_capability { > sizeof(struct efi_tcg2_boot_service_capability) - \ > offsetof(struct efi_tcg2_boot_service_capability, number_of_pcr_banks) > > +#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03 "Spec ID Event03" > +#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2 2 > +#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 0 > +#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2 2 > + > +/** > + * struct TCG_EfiSpecIdEventAlgorithmSize > + * > + * @algorithm_id: algorithm defined in enum tpm2_algorithms > + * @digest_size: size of the algorithm > + */ > +struct tcg_efi_spec_id_event_algorithm_size { > + u16 algorithm_id; > + u16 digest_size; > +} __packed; > + > +/** > + * struct TCG_EfiSpecIDEventStruct > + * > + * @signature: signature, set to Spec ID Event03 > + * @platform_class: class defined in TCG ACPI Specification > + * Client Common Header. > + * @spec_version_minor: minor version > + * @spec_version_major: major version > + * @spec_version_errata: major version > + * @uintn_size: size of the efi_uintn_t fields used in > various > + * data structures used in this specification. > + * 0x01 indicates u32 and 0x02 indicates u64 > + * @number_of_algorithms: hashing algorithms used in this event log > + * @digest_sizes: array of number_of_algorithms pairs > + * 1st member defines the algorithm id > + * 2nd member defines the algorithm size > + * @vendor_info_size: size in bytes for vendor specific info > + * @vendor_info: vendor specific info > + */ > +struct tcg_efi_spec_id_event { > + u8 signature[16]; > + u32 platform_class; > + u8 spec_version_minor; > + u8 spec_version_major; > + u8 spec_errata; > + u8 uintn_size; > + u32 number_of_algorithms; > + struct tcg_efi_spec_id_event_algorithm_size > digest_sizes[TPM2_NUM_PCR_BANKS]; > + u8 vendor_info_size; > + /* U-Boot does not provide any vendor info */ > + u8 vendor_info[]; > +} __packed; > + > +/** > + * struct tdEFI_TCG2_FINAL_EVENTS_TABLE > + * @version: version number for this structure > + * @number_of_events: number of events recorded after invocation of > + * GetEventLog() > + * @event: List of events of type tcg_pcr_event2 > + */ > +struct efi_tcg2_final_events_table { > + u64 version; > + u64 number_of_events; > + struct tcg_pcr_event2 event[]; > +}; > + > struct efi_tcg2_protocol { > efi_status_t (EFIAPI * get_capability)(struct efi_tcg2_protocol *this, > struct > efi_tcg2_boot_service_capability *capability); > @@ -73,7 +141,8 @@ struct efi_tcg2_protocol { > u64 *event_log_location, u64 > *event_log_last_entry, > bool *event_log_truncated); > efi_status_t (EFIAPI * hash_log_extend_event)(struct efi_tcg2_protocol > *this, > - u64 flags, u64 > data_to_hash, > + u64 flags, > + efi_physical_addr_t > data_to_hash, > u64 data_to_hash_len, > struct efi_tcg2_event > *efi_tcg_event); > efi_status_t (EFIAPI * submit_command)(struct efi_tcg2_protocol *this, > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig > index 29ea14b2ee2a..42970b652641 100644 > --- a/lib/efi_loader/Kconfig > +++ b/lib/efi_loader/Kconfig > @@ -191,6 +191,15 @@ 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 4096 > + 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_LOAD_FILE2_INITRD > bool "EFI_FILE_LOAD2_PROTOCOL for Linux initial ramdisk" > default n > diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c > index e206b60bb82c..2bb2c3c7aafa 100644 > --- a/lib/efi_loader/efi_setup.c > +++ b/lib/efi_loader/efi_setup.c > @@ -157,12 +157,6 @@ efi_status_t efi_init_obj_list(void) > goto out; > } > > - if (IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL)) { > - ret = efi_tcg2_register(); > - if (ret != EFI_SUCCESS) > - goto out; > - } > - > /* Initialize variable services */ > ret = efi_init_variables(); > if (ret != EFI_SUCCESS) > @@ -189,6 +183,12 @@ efi_status_t efi_init_obj_list(void) > if (ret != EFI_SUCCESS) > goto out; > > + if (IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL)) { > + ret = efi_tcg2_register(); > + if (ret != EFI_SUCCESS) > + goto out; > + } > + > /* Secure boot */ > ret = efi_init_secure_boot(); > if (ret != EFI_SUCCESS) > diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c > index 62f2f9427b6e..b0ed76f6653d 100644 > --- a/lib/efi_loader/efi_tcg2.c > +++ b/lib/efi_loader/efi_tcg2.c > @@ -14,11 +14,24 @@ > #include <efi_tcg2.h> > #include <log.h> > #include <tpm-v2.h> > +#include <u-boot/sha1.h> > +#include <u-boot/sha256.h> > +#include <u-boot/sha512.h> > #include <linux/unaligned/access_ok.h> > #include <linux/unaligned/generic.h> > +#include <hexdump.h> > + > +struct event_log_buffer { > + void *buffer; > + void *final_buffer; > + size_t pos; /* eventlog position */ > + size_t final_pos; /* final events config table position */ > + size_t last_event_size; > + bool get_event_called; > + bool truncated; > +}; > > -DECLARE_GLOBAL_DATA_PTR; > - > +static struct event_log_buffer event_log; > /* > * When requesting TPM2_CAP_TPM_PROPERTIES the value is on a standard offset. > * Since the current tpm2_get_capability() response buffers starts at > @@ -30,33 +43,40 @@ DECLARE_GLOBAL_DATA_PTR; > #define properties_offset (offsetof(struct tpml_tagged_tpm_property, > tpm_property) + \ > offsetof(struct tpms_tagged_property, value)) > > -struct { > +static const efi_guid_t efi_guid_tcg2_protocol = EFI_TCG2_PROTOCOL_GUID; > +static const efi_guid_t efi_guid_final_events = > EFI_TCG2_FINAL_EVENTS_TABLE_GUID; > + > +struct digest_info { > u16 hash_alg; > u32 hash_mask; > -} hash_algo_list[] = { > + u16 hash_len; > +}; > + > +const static struct digest_info hash_algo_list[] = { > { > TPM2_ALG_SHA1, > EFI_TCG2_BOOT_HASH_ALG_SHA1, > + TPM2_SHA1_DIGEST_SIZE, > }, > { > TPM2_ALG_SHA256, > EFI_TCG2_BOOT_HASH_ALG_SHA256, > + TPM2_SHA256_DIGEST_SIZE, > }, > { > TPM2_ALG_SHA384, > EFI_TCG2_BOOT_HASH_ALG_SHA384, > + TPM2_SHA384_DIGEST_SIZE, > }, > { > TPM2_ALG_SHA512, > EFI_TCG2_BOOT_HASH_ALG_SHA512, > - }, > - { > - TPM2_ALG_SM3_256, > - EFI_TCG2_BOOT_HASH_ALG_SM3_256, > + TPM2_SHA512_DIGEST_SIZE, > }, > }; > > #define MAX_HASH_COUNT ARRAY_SIZE(hash_algo_list) > + > /** > * alg_to_mask - Get a TCG hash mask for algorithms > * > @@ -76,7 +96,146 @@ static u32 alg_to_mask(u16 hash_alg) > return 0; > } > > -const efi_guid_t efi_guid_tcg2_protocol = EFI_TCG2_PROTOCOL_GUID; > +/** > + * alg_to_len - Get a TCG hash len for algorithms > + * > + * @hash_alg: TCG defined algorithm > + * > + * @Return: len of chosen algorithm, 0 if the algorithm is not supported > + */ > +static u16 alg_to_len(u16 hash_alg) > +{ > + int i; > + > + for (i = 0; i < MAX_HASH_COUNT; i++) { > + if (hash_algo_list[i].hash_alg == hash_alg) > + return hash_algo_list[i].hash_len; > + } > + > + return 0; > +} > + > +static u32 tcg_event_final_size(struct tpml_digest_values *digest_list) > +{ > + u32 len; > + int i; > + > + len = offsetof(struct tcg_pcr_event2, digests); > + len += offsetof(struct tpml_digest_values, digests); > + for (i = 0; i < digest_list->count; i++) { > + u16 hash_alg = digest_list->digests[i].hash_alg; > + > + len += offsetof(struct tpmt_ha, digest); > + len += alg_to_len(hash_alg); > + } > + len += sizeof(u32); /* tcg_pcr_event2 event_size*/ > + > + return len; > +} > + > +/* tcg2_pcr_extend - Extend PCRs for a TPM2 device for a given > tpml_digest_values > + * > + * @dev: device > + * @digest_list: list of digest algorithms to extend > + * > + * @Return: status code > + */ > +static efi_status_t tcg2_pcr_extend(struct udevice *dev, u32 pcr_index, > + struct tpml_digest_values *digest_list) > +{ > + u32 rc; > + int i; > + > + for (i = 0; i < digest_list->count; i++) { > + u32 alg = digest_list->digests[i].hash_alg; > + > + rc = tpm2_pcr_extend(dev, pcr_index, alg,
This does not compile with sandbox_defconfig lib/efi_loader/efi_tcg2.c: In function ‘tcg2_pcr_extend’: lib/efi_loader/efi_tcg2.c:152:40: warning: passing argument 3 of ‘tpm2_pcr_extend’ makes pointer from integer without a cast [-Wint-conversion] 152 | rc = tpm2_pcr_extend(dev, pcr_index, alg, | ^~~ | | | u32 {aka unsigned int} In file included from include/efi_tcg2.h:12, from lib/efi_loader/efi_tcg2.c:14: include/tpm-v2.h:398:68: note: expected ‘const uint8_t *’ {aka ‘const unsigned char *’} but argument is of type ‘u32’ {aka ‘unsigned int’} 398 | u32 tpm2_pcr_extend(struct udevice *dev, u32 index, const uint8_t *digest); | ~~~~~~~~~~~~~~~^~~~~~ lib/efi_loader/efi_tcg2.c:152:8: error: too many arguments to function ‘tpm2_pcr_extend’ 152 | rc = tpm2_pcr_extend(dev, pcr_index, alg, | ^~~~~~~~~~~~~~~ In file included from include/efi_tcg2.h:12, from lib/efi_loader/efi_tcg2.c:14: include/tpm-v2.h:398:5: note: declared here 398 | u32 tpm2_pcr_extend(struct udevice *dev, u32 index, const uint8_t *digest); | ^~~~~~~~~~~~~~~ Best regards Heinrich > + (u8 *)&digest_list->digests[i].digest, > + alg_to_len(alg)); > + if (rc) { > + EFI_PRINT("Failed to extend PCR\n"); > + return EFI_DEVICE_ERROR; > + } > + } > + > + return EFI_SUCCESS; > +} > + > +/* tcg2_agile_log_append - Append an agile event to out 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 > + * > + * @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 = event_log.buffer + event_log.pos; > + size_t pos; > + int i; > + u32 event_size; > + > + if (event_log.get_event_called) > + log = 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); > + put_unaligned_le32(event_type, log + pos); > + pos = offsetof(struct tcg_pcr_event2, digests); /* count */ > + put_unaligned_le32(digest_list->count, log + pos); > + > + pos += offsetof(struct tpml_digest_values, digests); > + for (i = 0; i < digest_list->count; i++) { > + u16 hash_alg = digest_list->digests[i].hash_alg; > + u8 *digest = (u8 *)&digest_list->digests[i].digest; > + > + put_unaligned_le16(hash_alg, log + pos); > + pos += offsetof(struct tpmt_ha, digest); > + memcpy(log + pos, digest, alg_to_len(hash_alg)); > + pos += alg_to_len(hash_alg); > + } > + > + put_unaligned_le32(size, log + pos); > + pos += sizeof(u32); /* tcg_pcr_event2 event_size*/ > + memcpy(log + pos, event, size); > + pos += size; > + > + /* make sure the calculated buffer is what we checked against */ > + if (pos != event_size) > + return EFI_INVALID_PARAMETER; > + > + /* 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; > + > + final_event = > + (struct efi_tcg2_final_events_table > *)(event_log.final_buffer); > + final_event->number_of_events++; > + event_log.final_pos += pos; > + } > + > + return EFI_SUCCESS; > +} > > /** > * platform_get_tpm_device() - retrieve TPM device > @@ -208,7 +367,7 @@ static int tpm2_get_num_pcr(struct udevice *dev, u32 > *num_pcr) > * > * Return: true if PCR is active > */ > -bool is_active_pcr(struct tpms_pcr_selection *selection) > +static bool is_active_pcr(struct tpms_pcr_selection *selection) > { > int i; > /* > @@ -308,6 +467,103 @@ out: > return -1; > } > > +/** > + * __get_active_pcr_banks() - returns the currently active PCR banks > + * > + * @active_pcr_banks: pointer for receiving the bitmap of > currently > + * active PCR banks > + * > + * Return: status code > + */ > +static efi_status_t __get_active_pcr_banks(u32 *active_pcr_banks) > +{ > + struct udevice *dev; > + u32 active, supported, pcr_banks; > + efi_status_t ret; > + int err; > + > + ret = platform_get_tpm2_device(&dev); > + if (ret != EFI_SUCCESS) > + goto out; > + > + err = tpm2_get_pcr_info(dev, &supported, &active, &pcr_banks); > + if (err) { > + ret = EFI_DEVICE_ERROR; > + goto out; > + } > + > + *active_pcr_banks = active; > + > +out: > + return ret; > +} > + > +/* tcg2_create_digest - create a list of digests of the supported PCR banks > + * for a given memory range > + * > + * @input: input memory > + * @length: length of buffer to calculate the digest > + * @digest_list: list of digests to fill in > + * > + * Return: status code > + */ > +static efi_status_t tcg2_create_digest(const u8 *input, u32 length, > + struct tpml_digest_values *digest_list) > +{ > + sha1_context ctx; > + sha256_context ctx_256; > + sha512_context ctx_512; > + u8 final[TPM2_ALG_SHA512]; > + efi_status_t ret; > + u32 active; > + int i; > + > + ret = __get_active_pcr_banks(&active); > + if (ret != EFI_SUCCESS) > + return ret; > + > + digest_list->count = 0; > + for (i = 0; i < MAX_HASH_COUNT; i++) { > + u16 hash_alg = hash_algo_list[i].hash_alg; > + > + if (!(active & alg_to_mask(hash_alg))) > + continue; > + switch (hash_alg) { > + case TPM2_ALG_SHA1: > + sha1_starts(&ctx); > + sha1_update(&ctx, input, length); > + sha1_finish(&ctx, final); > + digest_list->count++; > + break; > + case TPM2_ALG_SHA256: > + sha256_starts(&ctx_256); > + sha256_update(&ctx_256, input, length); > + sha256_finish(&ctx_256, final); > + digest_list->count++; > + break; > + case TPM2_ALG_SHA384: > + sha384_starts(&ctx_512); > + sha384_update(&ctx_512, input, length); > + sha384_finish(&ctx_512, final); > + digest_list->count++; > + break; > + case TPM2_ALG_SHA512: > + sha512_starts(&ctx_512); > + sha512_update(&ctx_512, input, length); > + sha512_finish(&ctx_512, final); > + digest_list->count++; > + break; > + default: > + EFI_PRINT("Unsupported algorithm %x\n", hash_alg); > + return EFI_INVALID_PARAMETER; > + } > + digest_list->digests[i].hash_alg = hash_alg; > + memcpy(&digest_list->digests[i].digest, final, > (u32)alg_to_len(hash_alg)); > + } > + > + return EFI_SUCCESS; > +} > + > /** > * efi_tcg2_get_capability() - protocol capability information and state > information > * > @@ -427,7 +683,28 @@ efi_tcg2_get_eventlog(struct efi_tcg2_protocol *this, > u64 *event_log_location, u64 *event_log_last_entry, > bool *event_log_truncated) > { > - return EFI_UNSUPPORTED; > + efi_status_t ret = EFI_SUCCESS; > + struct udevice *dev; > + > + EFI_ENTRY("%p, %u, %p, %p, %p", this, log_format, event_log_location, > + event_log_last_entry, event_log_truncated); > + > + ret = platform_get_tpm2_device(&dev); > + if (ret != EFI_SUCCESS) { > + event_log_location = NULL; > + event_log_last_entry = NULL; > + *event_log_truncated = false; > + ret = EFI_SUCCESS; > + goto out; > + } > + *event_log_location = (uintptr_t)event_log.buffer; > + *event_log_last_entry = (uintptr_t)(event_log.buffer + event_log.pos - > + event_log.last_event_size); > + *event_log_truncated = event_log.truncated; > + event_log.get_event_called = true; > + > +out: > + return EFI_EXIT(ret); > } > > /** > @@ -450,7 +727,76 @@ efi_tcg2_hash_log_extend_event(struct efi_tcg2_protocol > *this, u64 flags, > u64 data_to_hash, u64 data_to_hash_len, > struct efi_tcg2_event *efi_tcg_event) > { > - return EFI_UNSUPPORTED; > + struct udevice *dev; > + efi_status_t ret; > + u32 event_type, pcr_index, event_size; > + struct tpml_digest_values digest_list; > + > + EFI_ENTRY("%p, %llu, %llu, %llu, %p", this, flags, data_to_hash, > + data_to_hash_len, efi_tcg_event); > + > + if (!this || !data_to_hash || !efi_tcg_event) { > + ret = EFI_INVALID_PARAMETER; > + goto out; > + } > + > + ret = platform_get_tpm2_device(&dev); > + if (ret != EFI_SUCCESS) > + goto out; > + > + if (efi_tcg_event->size < efi_tcg_event->header.header_size + > + sizeof(u32)) { > + ret = EFI_INVALID_PARAMETER; > + goto out; > + } > + > + if (efi_tcg_event->header.pcr_index < 0 || > + efi_tcg_event->header.pcr_index > TPM2_MAX_PCRS) { > + ret = EFI_INVALID_PARAMETER; > + goto out; > + } > + > + /* > + * if PE_COFF_IMAGE is set we need to make sure the image is not > + * corrupted, verify it and hash the PE/COFF image in accordance with > + * the procedure specified in "Calculating the PE Image Hash" > + * section of the "Windows Authenticode Portable Executable Signature > + * Format" > + * Not supported for now > + */ > + if (flags & PE_COFF_IMAGE) { > + ret = EFI_UNSUPPORTED; > + goto out; > + } > + > + pcr_index = efi_tcg_event->header.pcr_index; > + event_type = efi_tcg_event->header.event_type; > + > + ret = tcg2_create_digest((u8 *)data_to_hash, data_to_hash_len, > + &digest_list); > + if (ret != EFI_SUCCESS) > + goto out; > + > + ret = tcg2_pcr_extend(dev, pcr_index, &digest_list); > + if (ret != EFI_SUCCESS) > + goto out; > + > + if (flags & EFI_TCG2_EXTEND_ONLY) { > + if (event_log.truncated) > + ret = EFI_VOLUME_FULL; > + goto out; > + } > + > + /* > + * The efi_tcg_event size includes the size component and the > + * headersize > + */ > + event_size = efi_tcg_event->size - sizeof(efi_tcg_event->size) - > + efi_tcg_event->header.header_size; > + ret = tcg2_agile_log_append(pcr_index, event_type, &digest_list, > + event_size, efi_tcg_event->event); > +out: > + return EFI_EXIT(ret); > } > > /** > @@ -464,7 +810,7 @@ efi_tcg2_hash_log_extend_event(struct efi_tcg2_protocol > *this, u64 flags, > * > * Return: status code > */ > -efi_status_t EFIAPI > +static efi_status_t EFIAPI > efi_tcg2_submit_command(struct efi_tcg2_protocol *this, > u32 input_param_block_size, u8 *input_param_block, > u32 output_param_block_size, u8 *output_param_block) > @@ -481,11 +827,16 @@ efi_tcg2_submit_command(struct efi_tcg2_protocol *this, > * > * Return: status code > */ > -efi_status_t EFIAPI > +static efi_status_t EFIAPI > efi_tcg2_get_active_pcr_banks(struct efi_tcg2_protocol *this, > u32 *active_pcr_banks) > { > - return EFI_UNSUPPORTED; > + efi_status_t ret; > + > + EFI_ENTRY("%p, %p", this, active_pcr_banks); > + ret = __get_active_pcr_banks(active_pcr_banks); > + > + return EFI_EXIT(ret); > } > > /** > @@ -496,7 +847,7 @@ efi_tcg2_get_active_pcr_banks(struct efi_tcg2_protocol > *this, > * > * Return: status code > */ > -efi_status_t EFIAPI > +static efi_status_t EFIAPI > efi_tcg2_set_active_pcr_banks(struct efi_tcg2_protocol *this, > u32 active_pcr_banks) > { > @@ -515,7 +866,7 @@ efi_tcg2_set_active_pcr_banks(struct efi_tcg2_protocol > *this, > * > * Return: status code > */ > -efi_status_t EFIAPI > +static efi_status_t EFIAPI > efi_tcg2_get_result_of_set_active_pcr_banks(struct efi_tcg2_protocol *this, > u32 *operation_present, u32 > *response) > { > @@ -532,6 +883,169 @@ static const struct efi_tcg2_protocol efi_tcg2_protocol > = { > .get_result_of_set_active_pcr_banks = > efi_tcg2_get_result_of_set_active_pcr_banks, > }; > > +/** > + * create_specid_event() - Create the first event in the eventlog > + * > + * @dev: tpm device > + * @event_header: Pointer to the final event header > + * @event_size: final spec event size > + * > + * Return: status code > + */ > +static efi_status_t create_specid_event(struct udevice *dev, void *buffer, > + size_t *event_size) > +{ > + struct tcg_efi_spec_id_event *spec_event; > + size_t spec_event_size; > + efi_status_t ret = EFI_DEVICE_ERROR; > + u32 active, supported; > + int err, i; > + > + /* > + * Create Spec event. This needs to be the first event in the log > + * according to the TCG EFI protocol spec > + */ > + > + /* Setup specID event data */ > + spec_event = (struct tcg_efi_spec_id_event *)buffer; > + memcpy(spec_event->signature, TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03, > + sizeof(spec_event->signature)); > + put_unaligned_le32(0, &spec_event->platform_class); /* type client */ > + spec_event->spec_version_minor = > + TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2; > + spec_event->spec_version_major = > + TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2; > + spec_event->spec_errata = > + TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2; > + spec_event->uintn_size = sizeof(efi_uintn_t) / sizeof(u32); > + > + err = tpm2_get_pcr_info(dev, &supported, &active, > + &spec_event->number_of_algorithms); > + if (err) > + goto out; > + if (spec_event->number_of_algorithms > MAX_HASH_COUNT || > + spec_event->number_of_algorithms < 1) > + goto out; > + > + for (i = 0; i < spec_event->number_of_algorithms; i++) { > + u16 hash_alg = hash_algo_list[i].hash_alg; > + u16 hash_len = hash_algo_list[i].hash_len; > + > + if (active && alg_to_mask(hash_alg)) { > + put_unaligned_le16(hash_alg, > + > &spec_event->digest_sizes[i].algorithm_id); > + put_unaligned_le16(hash_len, > + > &spec_event->digest_sizes[i].digest_size); > + } > + } > + /* > + * the size of the spec event and placement of vendor_info_size > + * depends on supported algoriths > + */ > + spec_event_size = > + offsetof(struct tcg_efi_spec_id_event, digest_sizes) + > + spec_event->number_of_algorithms * > sizeof(spec_event->digest_sizes[0]); > + /* no vendor info for us */ > + memset(buffer + spec_event_size, 0, > + sizeof(spec_event->vendor_info_size)); > + spec_event_size += sizeof(spec_event->vendor_info_size); > + *event_size = spec_event_size; > + > + return EFI_SUCCESS; > + > +out: > + return ret; > +} > + > +/** > + * create_final_event() - Create the final event and install the config > + * defined by the TCG EFI spec > + */ > +static efi_status_t create_final_event(void) > +{ > + struct efi_tcg2_final_events_table *final_event; > + efi_status_t ret; > + > + /* > + * All events generated after the invocation of > + * 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, > + &event_log.final_buffer); > + if (ret != EFI_SUCCESS) > + goto out; > + > + memset(event_log.final_buffer, 0xff, 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; > + event_log.final_pos = sizeof(*final_event); > + ret = efi_install_configuration_table(&efi_guid_final_events, > + final_event); > + if (ret != EFI_SUCCESS) > + goto out; > + > + return EFI_SUCCESS; > +out: > + return ret; > +} > + > +/** > + * efi_init_event_log() - initialize an eventlog > + */ > +static efi_status_t efi_init_event_log(void) > +{ > + /* > + * vendor_info_size is currently set to 0, we need to change the length > + * and allocate the flexible array member if this changes > + */ > + struct tcg_pcr_event *event_header = NULL; > + struct udevice *dev; > + size_t spec_event_size; > + efi_status_t ret; > + > + ret = platform_get_tpm2_device(&dev); > + if (ret != EFI_SUCCESS) > + goto out; > + > + ret = efi_allocate_pool(EFI_BOOT_SERVICES_DATA, TPM2_EVENT_LOG_SIZE, > + (void **)&event_log.buffer); > + if (ret != EFI_SUCCESS) > + goto out; > + > + /* > + * 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); > + event_log.pos = 0; > + event_log.last_event_size = 0; > + event_log.get_event_called = false; > + event_log.truncated = false; > + > + /* > + * The log header is defined to be in SHA1 event log entry format. > + * Setup event header > + */ > + event_header = (struct tcg_pcr_event *)event_log.buffer; > + put_unaligned_le32(0, &event_header->pcr_index); > + put_unaligned_le32(EV_NO_ACTION, &event_header->event_type); > + memset(&event_header->digest, 0, sizeof(event_header->digest)); > + ret = create_specid_event(dev, event_log.buffer + sizeof(*event_header), > + &spec_event_size); > + if (ret != EFI_SUCCESS) > + goto out; > + put_unaligned_le32(spec_event_size, &event_header->event_size); > + event_log.pos = spec_event_size + sizeof(*event_header); > + event_log.last_event_size = event_log.pos; > + > + ret = create_final_event(); > + > +out: > + return ret; > +} > + > /** > * efi_tcg2_register() - register EFI_TCG2_PROTOCOL > * > @@ -549,6 +1063,11 @@ efi_status_t efi_tcg2_register(void) > log_warning("Unable to find TPMv2 device\n"); > return EFI_SUCCESS; > } > + > + ret = efi_init_event_log(); > + if (ret != EFI_SUCCESS) > + return ret; > + > ret = efi_add_protocol(efi_root, &efi_guid_tcg2_protocol, > (void *)&efi_tcg2_protocol); > if (ret != EFI_SUCCESS) >