drivers/net/wireless/intel/iwlwifi/fw/uefi.c

Source file repositories/reference/linux-study-clean/drivers/net/wireless/intel/iwlwifi/fw/uefi.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/intel/iwlwifi/fw/uefi.c
Extension
.c
Size
26018 bytes
Lines
1052
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 iwl_uefi_pnvm_mem_desc {
	__le32 addr;
	__le32 size;
	const u8 data[];
} __packed;

static void *iwl_uefi_get_variable(efi_char16_t *name, efi_guid_t *guid,
				   unsigned long *data_size)
{
	efi_status_t status;
	void *data;

	if (!data_size)
		return ERR_PTR(-EINVAL);

	if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE))
		return ERR_PTR(-ENODEV);

	/* first call with NULL data to get the exact entry size */
	*data_size = 0;
	status = efi.get_variable(name, guid, NULL, data_size, NULL);
	if (status != EFI_BUFFER_TOO_SMALL || !*data_size)
		return ERR_PTR(-EIO);

	data = kmalloc(*data_size, GFP_KERNEL);
	if (!data)
		return ERR_PTR(-ENOMEM);

	status = efi.get_variable(name, guid, NULL, data_size, data);
	if (status != EFI_SUCCESS) {
		kfree(data);
		return ERR_PTR(-ENOENT);
	}

	return data;
}

void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
{
	unsigned long package_size;
	void *data;

	*len = 0;

	data = iwl_uefi_get_variable(IWL_UEFI_OEM_PNVM_NAME, &IWL_EFI_WIFI_GUID,
				     &package_size);
	if (IS_ERR(data)) {
		IWL_DEBUG_FW(trans,
			     "PNVM UEFI variable not found 0x%lx (len %lu)\n",
			     PTR_ERR(data), package_size);
		return data;
	}

	IWL_DEBUG_FW(trans, "Read PNVM from UEFI with size %lu\n", package_size);
	*len = package_size;

	return data;
}

static void *
iwl_uefi_get_verified_variable_guid(struct iwl_trans *trans,
				    efi_guid_t *guid,
				    efi_char16_t *uefi_var_name,
				    char *var_name,
				    unsigned int expected_size,
				    unsigned long *size)
{
	void *var;
	unsigned long var_size;

	var = iwl_uefi_get_variable(uefi_var_name, guid, &var_size);

	if (IS_ERR(var)) {
		IWL_DEBUG_RADIO(trans,
				"%s UEFI variable not found 0x%lx\n", var_name,
				PTR_ERR(var));
		return var;
	}

	if (var_size < expected_size) {
		IWL_DEBUG_RADIO(trans,
				"Invalid %s UEFI variable len (%lu)\n",
				var_name, var_size);
		kfree(var);
		return ERR_PTR(-EINVAL);
	}

	IWL_DEBUG_RADIO(trans, "%s from UEFI with size %lu\n", var_name,
			var_size);

Annotation

Implementation Notes