drivers/firmware/efi/libstub/tpm.c

Source file repositories/reference/linux-study-clean/drivers/firmware/efi/libstub/tpm.c

File Facts

System
Linux kernel
Corpus path
drivers/firmware/efi/libstub/tpm.c
Extension
.c
Size
5895 bytes
Lines
197
Domain
Driver Families
Bucket
drivers/firmware
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (version > EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2) {
			/*
			 * The TCG2 log format has variable length entries,
			 * and the information to decode the hash algorithms
			 * back into a size is contained in the first entry -
			 * pass a pointer to the final entry (to calculate its
			 * size) and the first entry (so we know how long each
			 * digest is)
			 */
			last_entry_size =
				__calc_tpm2_event_size((void *)last_entry_addr,
						    (void *)(long)log_location,
						    false);
		} else {
			last_entry_size = sizeof(struct tcpa_event) +
			   ((struct tcpa_event *) last_entry_addr)->event_size;
		}
		log_size = log_last_entry - log_location + last_entry_size;
	}

	/* Allocate space for the logs and copy them. */
	status = efi_bs_call(allocate_pool, EFI_ACPI_RECLAIM_MEMORY,
			     sizeof(*log_tbl) + log_size, (void **)&log_tbl);

	if (status != EFI_SUCCESS) {
		efi_err("Unable to allocate memory for event log\n");
		return;
	}

	/*
	 * Figure out whether any events have already been logged to the
	 * final events structure, and if so how much space they take up
	 */
	if (final_events_table && final_events_table->nr_events) {
		struct tcg_pcr_event2_head *header;
		u32 offset;
		void *data;
		u32 event_size;
		int i = final_events_table->nr_events;

		data = (void *)final_events_table;
		offset = sizeof(final_events_table->version) +
			sizeof(final_events_table->nr_events);

		while (i > 0) {
			header = data + offset + final_events_size;
			event_size = __calc_tpm2_event_size(header,
						   (void *)(long)log_location,
						   false);
			/* If calc fails this is a malformed log */
			if (!event_size)
				break;
			final_events_size += event_size;
			i--;
		}
	}

	memset(log_tbl, 0, sizeof(*log_tbl) + log_size);
	log_tbl->size = log_size;
	log_tbl->final_events_preboot_size = final_events_size;
	log_tbl->version = version;
	memcpy(log_tbl->log, (void *) first_entry_addr, log_size);

	status = efi_bs_call(install_configuration_table,
			     &linux_eventlog_guid, log_tbl);
	if (status != EFI_SUCCESS)
		goto err_free;
	return;

err_free:
	efi_bs_call(free_pool, log_tbl);
}

void efi_retrieve_eventlog(void)
{
	struct efi_tcg2_final_events_table *final_events_table = NULL;
	efi_physical_addr_t log_location = 0, log_last_entry = 0;
	efi_guid_t tpm2_guid = EFI_TCG2_PROTOCOL_GUID;
	int version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
	efi_tcg2_protocol_t *tpm2 = NULL;
	efi_bool_t truncated;
	efi_status_t status;

	status = efi_bs_call(locate_protocol, &tpm2_guid, NULL, (void **)&tpm2);
	if (status == EFI_SUCCESS) {
		status = efi_call_proto(tpm2, get_event_log, version, &log_location,
					&log_last_entry, &truncated);

		if (status != EFI_SUCCESS || !log_location) {
			version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;

Annotation

Implementation Notes