drivers/firmware/efi/libstub/efi-stub-helper.c

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

File Facts

System
Linux kernel
Corpus path
drivers/firmware/efi/libstub/efi-stub-helper.c
Extension
.c
Size
22778 bytes
Lines
777
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

struct efistub_measured_event {
	union efistub_event	event_data;
	TCG_PCClientTaggedEvent tagged_event __packed;
};

static efi_status_t efi_measure_tagged_event(unsigned long load_addr,
					     unsigned long load_size,
					     enum efistub_event_type event)
{
	union {
		efi_status_t
		(__efiapi *hash_log_extend_event)(void *, u64, efi_physical_addr_t,
						  u64, const union efistub_event *);
		struct { u32 hash_log_extend_event; } mixed_mode;
	} method;
	struct efistub_measured_event *evt __free(efi_pool) = NULL;
	int size = struct_size(evt, tagged_event.tagged_event_data,
			       events[event].event_data_len);
	efi_guid_t tcg2_guid = EFI_TCG2_PROTOCOL_GUID;
	efi_tcg2_protocol_t *tcg2 = NULL;
	union efistub_event ev;
	efi_status_t status;
	void *protocol;

	efi_bs_call(locate_protocol, &tcg2_guid, NULL, (void **)&tcg2);
	if (tcg2) {
		ev.tcg2_data = (struct efi_tcg2_event){
			.event_size			= size,
			.event_header.header_size	= sizeof(ev.tcg2_data.event_header),
			.event_header.header_version	= EFI_TCG2_EVENT_HEADER_VERSION,
			.event_header.pcr_index		= events[event].pcr_index,
			.event_header.event_type	= EV_EVENT_TAG,
		};
		protocol = tcg2;
		method.hash_log_extend_event =
			(void *)efi_table_attr(tcg2, hash_log_extend_event);
	} else {
		efi_guid_t cc_guid = EFI_CC_MEASUREMENT_PROTOCOL_GUID;
		efi_cc_protocol_t *cc = NULL;

		efi_bs_call(locate_protocol, &cc_guid, NULL, (void **)&cc);
		if (!cc)
			return EFI_UNSUPPORTED;

		ev.cc_data = (struct efi_cc_event){
			.event_size			= size,
			.event_header.header_size	= sizeof(ev.cc_data.event_header),
			.event_header.header_version	= EFI_CC_EVENT_HEADER_VERSION,
			.event_header.event_type	= EV_EVENT_TAG,
		};

		status = efi_call_proto(cc, map_pcr_to_mr_index,
					events[event].pcr_index,
					&ev.cc_data.event_header.mr_index);
		if (status != EFI_SUCCESS)
			goto fail;

		protocol = cc;
		method.hash_log_extend_event =
			(void *)efi_table_attr(cc, hash_log_extend_event);
	}

	status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, size, (void **)&evt);
	if (status != EFI_SUCCESS)
		goto fail;

	*evt = (struct efistub_measured_event) {
		.event_data			     = ev,
		.tagged_event.tagged_event_id	     = events[event].event_id,
		.tagged_event.tagged_event_data_size = events[event].event_data_len,
	};

	memcpy(evt->tagged_event.tagged_event_data, events[event].event_data,
	       events[event].event_data_len);

	status = efi_fn_call(&method, hash_log_extend_event, protocol, 0,
			     load_addr, load_size, &evt->event_data);

	if (status == EFI_SUCCESS)
		return EFI_SUCCESS;

fail:
	efi_warn("Failed to measure data for event %d: 0x%lx\n", event, status);
	return status;
}

/*
 * Convert the unicode UEFI command line to ASCII to pass to kernel.
 * Size of memory allocated return in *cmd_line_len.
 * Returns NULL on error.

Annotation

Implementation Notes