From mboxrd@z Thu Jan 1 00:00:00 1970 From: Heinrich Schuchardt Date: Thu, 12 Nov 2020 20:26:38 +0100 Subject: [PATCH 2/2 v4] efi: Add basic EFI_TCG2_PROTOCOL support In-Reply-To: <20201111091812.400969-2-ilias.apalodimas@linaro.org> References: <20201111091812.400969-1-ilias.apalodimas@linaro.org> <20201111091812.400969-2-ilias.apalodimas@linaro.org> Message-ID: <53ba8a04-ddd3-a718-b59a-1a8aab5ce41e@gmx.de> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de On 11/11/20 10:18 AM, Ilias Apalodimas wrote: > Since U-boot EFI implementation is getting richer it makes sense to > add support for EFI_TCG2_PROTOCOL taking advantage of any hardware TPM > available on the device. > > This is the initial implementation of the protocol which only adds > support for GetCapability(). It's limited in the newer and safer > TPMv2 devices. > > Signed-off-by: Ilias Apalodimas > --- > * changes since v3: > - added check for maximum number of PCRs allowed > - replaced multiple return Xl with goto out tags > * changes since v2: > - added description about include/efi_tcg2.h > - switch bool to u8 for tpm_present_flag > - removed superfluous 'default n' from Kconfig > - use 'goto 'tag' when possible > > * changes since v1: > - change return variable of platform_get_tpm2_device() when used > - since more headers were included in patch #2 use them in offset > calculations for all tpm commands > - change the size of the response buffer regardless of what > tpm2_get_capability() is doing > include/efi_loader.h | 2 + > include/efi_tcg2.h | 94 +++++++ > lib/efi_loader/Kconfig | 7 + > lib/efi_loader/Makefile | 1 + > lib/efi_loader/efi_setup.c | 7 + > lib/efi_loader/efi_tcg2.c | 539 +++++++++++++++++++++++++++++++++++++ > 6 files changed, 650 insertions(+) > create mode 100644 include/efi_tcg2.h > create mode 100644 lib/efi_loader/efi_tcg2.c > > diff --git a/include/efi_loader.h b/include/efi_loader.h > index f550ced56876..e5015d865ec9 100644 > --- a/include/efi_loader.h > +++ b/include/efi_loader.h > @@ -405,6 +405,8 @@ efi_status_t efi_console_register(void); > efi_status_t efi_disk_register(void); > /* Called by efi_init_obj_list() to install EFI_RNG_PROTOCOL */ > efi_status_t efi_rng_register(void); > +/* Called by efi_init_obj_list() to install EFI_TCG2_PROTOCOL */ > +efi_status_t efi_tcg2_register(void); > /* Create handles and protocols for the partitions of a block device */ > int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc, > const char *if_typename, int diskid, > diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h > new file mode 100644 > index 000000000000..4214f767eaba > --- /dev/null > +++ b/include/efi_tcg2.h > @@ -0,0 +1,94 @@ > +/* SPDX-License-Identifier: GPL-2.0+ */ > +/* > + * Defines data structures and APIs that allow an OS to interact with UEFI > + * firmware to query information about the device > + * > + * Copyright (c) 2020, Linaro Limited > + */ > + > +#if !defined _EFI_TCG2_PROTOCOL_H_ > +#define _EFI_TCG2_PROTOCOL_H_ > + > +#include > + > +#define EFI_TCG2_PROTOCOL_GUID \ > + EFI_GUID(0x607f766c, 0x7455, 0x42be, 0x93, \ > + 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f) > + > +/* TPMV2 only */ > +#define TCG2_EVENT_LOG_FORMAT_TCG_2 0x00000002 > + > +/* SHA1, SHA256, SHA384, SHA512, TPM_ALG_SM3_256 */ > +#define MAX_HASH_COUNT 5 > +/* Algorithm Registry */ > +#define EFI_TCG2_BOOT_HASH_ALG_SHA1 0x00000001 > +#define EFI_TCG2_BOOT_HASH_ALG_SHA256 0x00000002 > +#define EFI_TCG2_BOOT_HASH_ALG_SHA384 0x00000004 > +#define EFI_TCG2_BOOT_HASH_ALG_SHA512 0x00000008 > +#define EFI_TCG2_BOOT_HASH_ALG_SM3_256 0x00000010 > + > +typedef u32 efi_tcg_event_log_bitmap; > +typedef u32 efi_tcg_event_log_format; > +typedef u32 efi_tcg_event_algorithm_bitmap; > + > +struct efi_tcg2_version { > + u8 major; > + u8 minor; > +}; > + > +struct efi_tcg2_event_header { > + u32 header_size; > + u16 header_version; > + u32 pcr_index; > + u32 event_type; > +} __packed; > + > +struct efi_tcg2_event { > + u32 size; > + struct efi_tcg2_event_header header; > + u8 event[]; > +} __packed; > + > +struct efi_tcg2_boot_service_capability { > + u8 size; > + struct efi_tcg2_version structure_version; > + struct efi_tcg2_version protocol_version; > + efi_tcg_event_algorithm_bitmap hash_algorithm_bitmap; > + efi_tcg_event_log_bitmap supported_event_logs; > + u8 tpm_present_flag; > + u16 max_command_size; > + u16 max_response_size; > + u32 manufacturer_id; > + u32 number_of_pcr_banks; > + efi_tcg_event_algorithm_bitmap active_pcr_banks; > +}; > + > +#define boot_service_capability_min \ > + sizeof(struct efi_tcg2_boot_service_capability) - \ > + offsetof(struct efi_tcg2_boot_service_capability, number_of_pcr_banks) > + > +struct efi_tcg2_protocol { > + efi_status_t (EFIAPI * get_capability)(struct efi_tcg2_protocol *this, > + struct efi_tcg2_boot_service_capability *capability); > + efi_status_t (EFIAPI * get_eventlog)(struct efi_tcg2_protocol *this, > + efi_tcg_event_log_format log_format, > + 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 data_to_hash_len, > + struct efi_tcg2_event *efi_tcg_event); > + efi_status_t (EFIAPI * submit_command)(struct efi_tcg2_protocol *this, > + u32 input_parameter_block_size, > + u8 *input_parameter_block, > + u32 output_parameter_block_size, > + u8 *output_parameter_block); > + efi_status_t (EFIAPI * get_active_pcr_banks)(struct efi_tcg2_protocol *this, > + u32 *active_pcr_banks); > + efi_status_t (EFIAPI * set_active_pcr_banks)(struct efi_tcg2_protocol *this, > + u32 active_pcr_banks); > + efi_status_t (EFIAPI * get_result_of_set_active_pcr_banks)(struct efi_tcg2_protocol *this, > + u32 *operation_present, > + u32 *response); > +}; > +#endif > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig > index 075481428cdf..29ea14b2ee2a 100644 > --- a/lib/efi_loader/Kconfig > +++ b/lib/efi_loader/Kconfig > @@ -184,6 +184,13 @@ config EFI_RNG_PROTOCOL > Provide a EFI_RNG_PROTOCOL implementation using the hardware random > number generator of the platform. > > +config EFI_TCG2_PROTOCOL > + bool "EFI_TCG2_PROTOCOL support" > + depends on TPM_V2 > + help > + Provide a EFI_TCG2_PROTOCOL implementation using the TPM hardware > + of the platform. > + > config EFI_LOAD_FILE2_INITRD > bool "EFI_FILE_LOAD2_PROTOCOL for Linux initial ramdisk" > default n > diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile > index 8892fb01e125..cd4b252a417c 100644 > --- a/lib/efi_loader/Makefile > +++ b/lib/efi_loader/Makefile > @@ -53,6 +53,7 @@ obj-$(CONFIG_NET) += efi_net.o > obj-$(CONFIG_GENERATE_ACPI_TABLE) += efi_acpi.o > obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += efi_smbios.o > obj-$(CONFIG_EFI_RNG_PROTOCOL) += efi_rng.o > +obj-$(CONFIG_EFI_TCG2_PROTOCOL) += efi_tcg2.o > obj-$(CONFIG_EFI_LOAD_FILE2_INITRD) += efi_load_initrd.o > obj-y += efi_signature.o > > diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c > index 45226c5c1a53..e206b60bb82c 100644 > --- a/lib/efi_loader/efi_setup.c > +++ b/lib/efi_loader/efi_setup.c > @@ -156,6 +156,13 @@ 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; > + } > + > /* Initialize variable services */ > ret = efi_init_variables(); > if (ret != EFI_SUCCESS) > diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c > new file mode 100644 > index 000000000000..d600cff66af1 > --- /dev/null > +++ b/lib/efi_loader/efi_tcg2.c > @@ -0,0 +1,539 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * Defines APIs that allow an OS to interact with UEFI firmware to query > + * information about the device. > + * https://trustedcomputinggroup.org/resource/tcg-efi-protocol-specification/ > + * > + * Copyright (c) 2020, Linaro Limited > + */ > + > +#define LOG_CATEGORY LOGC_EFI > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +DECLARE_GLOBAL_DATA_PTR; > + > +/* > + * When requesting TPM2_CAP_TPM_PROPERTIES the value is on a standard offset. > + * Since the current tpm2_get_capability() response buffers starts at > + * 'union tpmu_capabilities data' of 'struct tpms_capability_data', calculate > + * the response size and offset once for all consumers > + */ > +#define TPM2_RESPONSE_BUFFER_SIZE (sizeof(struct tpms_capability_data) - \ > + offsetof(struct tpms_capability_data, data)) > +#define properties_offset (offsetof(struct tpml_tagged_tpm_property, tpm_property) + \ > + offsetof(struct tpms_tagged_property, value)) > + > +const efi_guid_t efi_guid_tcg2_protocol = EFI_TCG2_PROTOCOL_GUID; > + > +/** > + * platform_get_tpm_device() - retrieve TPM device > + * > + * This function retrieves the udevice implementing a TPM > + * > + * This function may be overridden if special initialization is needed. > + * > + * @dev: udevice > + * Return: status code > + */ > +__weak efi_status_t platform_get_tpm2_device(struct udevice **dev) > +{ > + int ret; > + struct udevice *devp; > + > + ret = uclass_get_device(UCLASS_TPM, 0, &devp); > + if (ret) > + return EFI_DEVICE_ERROR; > + > + *dev = devp; > + > + return EFI_SUCCESS; > +} > + > +/** > + * tpm2_get_max_command_size() - get the supported max command size > + * > + * @dev: TPM device > + * @max_command_size: output buffer for the size > + * > + * Return: 0 on success, -1 on error > + */ > +static int tpm2_get_max_command_size(struct udevice *dev, u16 *max_command_size) > +{ > + u8 response[TPM2_RESPONSE_BUFFER_SIZE]; > + u32 ret; > + > + memset(response, 0, sizeof(response)); > + ret = tpm2_get_capability(dev, TPM2_CAP_TPM_PROPERTIES, > + TPM2_PT_MAX_COMMAND_SIZE, response, 1); > + if (ret) > + return -1; > + > + *max_command_size = (uint16_t)get_unaligned_be32(response + > + properties_offset); > + > + return 0; > +} > + > +/** > + * tpm2_get_max_response_size() - get the supported max response size > + * > + * @dev: TPM device > + * @max_response_size: output buffer for the size > + * > + * Return: 0 on success, -1 on error > + */ > +static int tpm2_get_max_response_size(struct udevice *dev, > + u16 *max_response_size) > +{ > + u8 response[TPM2_RESPONSE_BUFFER_SIZE]; > + u32 ret; > + > + memset(response, 0, sizeof(response)); > + ret = tpm2_get_capability(dev, TPM2_CAP_TPM_PROPERTIES, > + TPM2_PT_MAX_RESPONSE_SIZE, response, 1); > + if (ret) > + return -1; > + > + *max_response_size = (uint16_t)get_unaligned_be32(response + > + properties_offset); > + > + return 0; > +} > + > +/** > + * tpm2_get_manufacturer_id() - get the manufacturer ID > + * > + * @dev: TPM device > + * @manufacturer_id: output buffer for the id > + * > + * Return: 0 on success, -1 on error > + */ > +static int tpm2_get_manufacturer_id(struct udevice *dev, u32 *manufacturer_id) > +{ > + u8 response[TPM2_RESPONSE_BUFFER_SIZE]; > + u32 ret; > + > + memset(response, 0, sizeof(response)); > + ret = tpm2_get_capability(dev, TPM2_CAP_TPM_PROPERTIES, > + TPM2_PT_MANUFACTURER, response, 1); > + if (ret) > + return -1; > + > + *manufacturer_id = get_unaligned_be32(response + properties_offset); > + > + return 0; > +} > + > +/** > + * tpm2_get_num_pcr() - get the number of PCRs > + * > + * @dev: TPM device > + * @manufacturer_id: output buffer for the number > + * > + * Return: 0 on success, -1 on error > + */ > +static int tpm2_get_num_pcr(struct udevice *dev, u32 *num_pcr) > +{ > + u8 response[TPM2_RESPONSE_BUFFER_SIZE]; > + u32 ret; > + > + memset(response, 0, sizeof(response)); > + ret = tpm2_get_capability(dev, TPM2_CAP_TPM_PROPERTIES, > + TPM2_PT_PCR_COUNT, response, 1); > + if (ret) > + return -1; > + > + *num_pcr = get_unaligned_be32(response + properties_offset); > + if (*num_pcr > TPM2_MAX_PCRS) > + return -1; > + > + return 0; > +} > + > +/** > + * is_active_pcr() - Check if a supported algorithm is active > + * > + * @dev: TPM device > + * @selection: struct of PCR information > + * > + * Return: true if PCR is active > + */ > +bool is_active_pcr(struct tpms_pcr_selection *selection) > +{ > + int i; > + /* > + * check the pcr_select. If at least one of the PCRs supports the > + * algorithm add it on the active ones > + */ > + for (i = 0; i < selection->size_of_select; i++) { > + if (selection->pcr_select[i]) > + return true; > + } > + > + return false; > +} > + > +/** > + * tpm2_get_pcr_info() - get the supported, active PCRs and number of banks > + * > + * @dev: TPM device > + * @supported_pcr: bitmask with the algorithms supported > + * @active_pcr: bitmask with the active algorithms > + * @pcr_banks: number of PCR banks > + * > + * Return: 0 on success, -1 on error > + */ > +static int tpm2_get_pcr_info(struct udevice *dev, u32 *supported_pcr, > + u32 *active_pcr, u32 *pcr_banks) > +{ > + u8 response[TPM2_RESPONSE_BUFFER_SIZE]; > + struct tpml_pcr_selection pcrs; > + u32 ret, num_pcr; > + int i, tpm_ret; > + > + memset(response, 0, sizeof(response)); > + ret = tpm2_get_capability(dev, TPM2_CAP_PCRS, 0, response, 1); > + if (ret) > + goto out; > + > + pcrs.count = get_unaligned_be32(response); > + /* > + * We only support 5 algorithms for now so check against that > + * instead of TPM2_NUM_PCR_BANKS > + */ > + if (pcrs.count > MAX_HASH_COUNT || pcrs.count < 1) > + goto out; > + > + tpm_ret = tpm2_get_num_pcr(dev, &num_pcr); > + if (tpm_ret) > + goto out; > + > + for (i = 0; i < pcrs.count; i++) { > + /* > + * Definition of TPMS_PCR_SELECTION Structure > + * hash: u16 > + * size_of_select: u8 > + * pcr_select: u8 array > + * > + * The offsets depend on the number of the device PCRs > + * so we have to calculate them based on that > + */ > + u32 hash_offset = offsetof(struct tpml_pcr_selection, selection) + > + i * offsetof(struct tpms_pcr_selection, pcr_select) + > + i * ((num_pcr + 7) / 8); > + u32 size_select_offset = > + hash_offset + offsetof(struct tpms_pcr_selection, > + size_of_select); > + u32 pcr_select_offset = > + hash_offset + offsetof(struct tpms_pcr_selection, > + pcr_select); > + > + pcrs.selection[i].hash = > + get_unaligned_be16(response + hash_offset); > + pcrs.selection[i].size_of_select = > + __get_unaligned_be(response + size_select_offset); > + if (pcrs.selection[i].size_of_select > TPM2_PCR_SELECT_MAX) > + goto out; > + /* copy the array of pcr_select */ > + memcpy(pcrs.selection[i].pcr_select, response + pcr_select_offset, > + pcrs.selection[i].size_of_select); > + } > + > + for (i = 0; i < pcrs.count; i++) { > + switch (pcrs.selection[i].hash) { > + case TPM2_ALG_SHA1: > + *supported_pcr |= EFI_TCG2_BOOT_HASH_ALG_SHA1; > + if (is_active_pcr(&pcrs.selection[i])) > + *active_pcr |= EFI_TCG2_BOOT_HASH_ALG_SHA1; > + break; > + case TPM2_ALG_SHA256: > + *supported_pcr |= EFI_TCG2_BOOT_HASH_ALG_SHA256; > + if (is_active_pcr(&pcrs.selection[i])) > + *active_pcr |= EFI_TCG2_BOOT_HASH_ALG_SHA256; > + break; > + case TPM2_ALG_SHA384: > + *supported_pcr |= EFI_TCG2_BOOT_HASH_ALG_SHA384; > + if (is_active_pcr(&pcrs.selection[i])) > + *active_pcr |= EFI_TCG2_BOOT_HASH_ALG_SHA384; > + break; > + case TPM2_ALG_SHA512: > + *supported_pcr |= EFI_TCG2_BOOT_HASH_ALG_SHA512; > + if (is_active_pcr(&pcrs.selection[i])) > + *active_pcr |= EFI_TCG2_BOOT_HASH_ALG_SHA512; > + break; > + case TPM2_ALG_SM3_256: > + *supported_pcr |= EFI_TCG2_BOOT_HASH_ALG_SM3_256; > + if (is_active_pcr(&pcrs.selection[i])) > + *active_pcr |= EFI_TCG2_BOOT_HASH_ALG_SM3_256; > + break; > + default: > + EFI_PRINT("Unknown algorithm %x\n", > + pcrs.selection[i].hash); > + break; > + } > + } > + > + *pcr_banks = pcrs.count; > + > + return 0; > +out: > + return -1; > +} > + > +/** > + * get_capability() - protocol capability information and state information > + * > + * @this: TCG2 protocol instance > + * @capability: caller allocated memory with size field to the size of > + * the structure allocated > + > + * Return: status code > + */ > +static efi_status_t EFIAPI > +get_capability(struct efi_tcg2_protocol *this, Please, use unique function names. That makes setting breakpoints in gdb much easier. How about: efi_tcg2_get_capability()? Same for all other functions. Regards Heinrich > + struct efi_tcg2_boot_service_capability *capability) > +{ > + struct udevice *dev; > + efi_status_t efi_ret; > + int ret; > + > + EFI_ENTRY("%p, %p", this, capability); > + > + if (!this || !capability) { > + efi_ret = EFI_INVALID_PARAMETER; > + goto out; > + } > + > + if (capability->size < boot_service_capability_min) { > + capability->size = boot_service_capability_min; > + efi_ret = EFI_BUFFER_TOO_SMALL; > + goto out; > + } > + > + if (capability->size < sizeof(*capability)) { > + capability->size = sizeof(*capability); > + efi_ret = EFI_BUFFER_TOO_SMALL; > + goto out; > + } > + > + capability->structure_version.major = 1; > + capability->structure_version.minor = 1; > + capability->protocol_version.major = 1; > + capability->protocol_version.minor = 1; > + > + efi_ret = platform_get_tpm2_device(&dev); > + if (efi_ret != EFI_SUCCESS) { > + capability->supported_event_logs = 0; > + capability->hash_algorithm_bitmap = 0; > + capability->tpm_present_flag = false; > + capability->max_command_size = 0; > + capability->max_response_size = 0; > + capability->manufacturer_id = 0; > + capability->number_of_pcr_banks = 0; > + capability->active_pcr_banks = 0; > + > + efi_ret = EFI_SUCCESS; > + goto out; > + } > + > + /* We only allow a TPMv2 device to register the EFI protocol */ > + capability->supported_event_logs = TCG2_EVENT_LOG_FORMAT_TCG_2; > + > + capability->tpm_present_flag = true; > + > + /* Supported and active PCRs */ > + capability->hash_algorithm_bitmap = 0; > + capability->active_pcr_banks = 0; > + ret = tpm2_get_pcr_info(dev, &capability->hash_algorithm_bitmap, > + &capability->active_pcr_banks, > + &capability->number_of_pcr_banks); > + if (ret) { > + efi_ret = EFI_DEVICE_ERROR; > + goto out; > + } > + > + /* Max command size */ > + ret = tpm2_get_max_command_size(dev, &capability->max_command_size); > + if (ret) { > + efi_ret = EFI_DEVICE_ERROR; > + goto out; > + } > + > + /* Max response size */ > + ret = tpm2_get_max_response_size(dev, &capability->max_response_size); > + if (ret) { > + efi_ret = EFI_DEVICE_ERROR; > + goto out; > + } > + > + /* Manufacturer ID */ > + ret = tpm2_get_manufacturer_id(dev, &capability->manufacturer_id); > + if (ret) { > + efi_ret = EFI_DEVICE_ERROR; > + goto out; > + } > + > + return EFI_EXIT(EFI_SUCCESS); > +out: > + return EFI_EXIT(efi_ret); > +} > + > +/** > + * get_eventlog() - retrieve the the address of an event log and its last entry > + * > + * @this: TCG2 protocol instance > + * @log_format: type of event log format > + * @event_log_location: pointer to the memory address of the event log > + * @event_log_last_entry: pointer to the address of the start of the last > + * entry in the event log in memory, if log contains > + * more than 1 entry > + * @event_log_truncated: set to true, if the Event Log is missing at i > + * least one entry > + * > + * Return: status code > + */ > +static efi_status_t EFIAPI > +get_eventlog(struct efi_tcg2_protocol *this, > + efi_tcg_event_log_format log_format, u64 *event_log_location, > + u64 *event_log_last_entry, bool *event_log_truncated) > +{ > + return EFI_UNSUPPORTED; > +} > + > +/** > + * hash_log_extend_event()- extend and optionally log events > + * > + * @this: TCG2 protocol instance > + * @flags: bitmap providing additional information on the > + * operation > + * @data_to_hash: physical address of the start of the data buffer > + * to be hashed > + * @data_to_hash_len: the length in bytes of the buffer referenced by > + * data_to_hash > + * @efi_tcg_event: pointer to data buffer containing information > + * about the event > + * > + * Return: status code > + */ > +static efi_status_t EFIAPI > +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; > +} > + > +/** > + * submit_command() - Send command to the TPM > + * > + * @this: TCG2 protocol instance > + * @input_param_block_size: size of the TPM input parameter block > + * @input_param_block: pointer to the TPM input parameter block > + * @output_param_block_size: size of the TPM output parameter block > + * @output_param_block: pointer to the TPM output parameter block > + * > + * Return: status code > + */ > +efi_status_t EFIAPI > +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) > +{ > + return EFI_UNSUPPORTED; > +} > + > +/** > + * get_active_pcr_banks() - returns the currently active PCR banks > + * > + * @this: TCG2 protocol instance > + * @active_pcr_banks: pointer for receiving the bitmap of currently > + * active PCR banks > + * > + * Return: status code > + */ > +efi_status_t EFIAPI > +get_active_pcr_banks(struct efi_tcg2_protocol *this, u32 *active_pcr_banks) > +{ > + return EFI_UNSUPPORTED; > +} > + > +/** > + * set_active_pcr_banks() - sets the currently active PCR banks > + * > + * @this: TCG2 protocol instance > + * @active_pcr_banks: bitmap of the requested active PCR banks > + * > + * Return: status code > + */ > +efi_status_t EFIAPI > +set_active_pcr_banks(struct efi_tcg2_protocol *this, u32 active_pcr_banks) > +{ > + return EFI_UNSUPPORTED; > +} > + > +/** > + * get_result_of_set_active_pcr_banks() - retrieves the result of a previous > + * set_active_pcr_banks() > + * > + * @this: TCG2 protocol instance > + * @operation_present: non-zero value to indicate a > + * set_active_pcr_banks operation was > + * invoked during last boot > + * @response: result value could be returned > + * > + * Return: status code > + */ > +efi_status_t EFIAPI > +get_result_of_set_active_pcr_banks(struct efi_tcg2_protocol *this, > + u32 *operation_present, u32 *response) > +{ > + return EFI_UNSUPPORTED; > +} > + > +static const struct efi_tcg2_protocol efi_tcg2_protocol = { > + .get_capability = get_capability, > + .get_eventlog = get_eventlog, > + .hash_log_extend_event = hash_log_extend_event, > + .submit_command = submit_command, > + .get_active_pcr_banks = get_active_pcr_banks, > + .set_active_pcr_banks = set_active_pcr_banks, > + .get_result_of_set_active_pcr_banks = get_result_of_set_active_pcr_banks, > +}; > + > +/** > + * efi_tcg2_register() - register EFI_TCG2_PROTOCOL > + * > + * If a TPM2 device is available, the TPM TCG2 Protocol is registered > + * > + * Return: An error status is only returned if adding the protocol fails. > + */ > +efi_status_t efi_tcg2_register(void) > +{ > + efi_status_t ret; > + struct udevice *dev; > + enum tpm_version tpm_ver; > + > + ret = platform_get_tpm2_device(&dev); > + if (ret != EFI_SUCCESS) > + return EFI_SUCCESS; > + > + tpm_ver = tpm_get_version(dev); > + if (tpm_ver != TPM_V2) { > + log_warning("Only TPMv2 supported for EFI_TCG2_PROTOCOL"); > + return EFI_SUCCESS; > + } > + > + ret = efi_add_protocol(efi_root, &efi_guid_tcg2_protocol, > + (void *)&efi_tcg2_protocol); > + if (ret != EFI_SUCCESS) > + log_err("Cannot install EFI_TCG2_PROTOCOL"); > + > + return ret; > +} >