Commit 84c3c995 authored by Luca Coelho's avatar Luca Coelho
Browse files

iwlwifi: move UEFI code to a separate file



We are going to read more variables from UEFI, so it's cleaner to have
all the code that handles UEFI variables in a separate file.

Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/iwlwifi.20210621103449.c705ac86f2e9.Ia7421c17fe52929e4098b4f0cf070809ed3ef906@changeid


Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent 5c157941
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ iwlwifi-objs += fw/img.o fw/notif-wait.o
iwlwifi-objs		+= fw/dbg.o fw/pnvm.o
iwlwifi-$(CONFIG_IWLMVM) += fw/paging.o fw/smem.o fw/init.o
iwlwifi-$(CONFIG_ACPI) += fw/acpi.o
iwlwifi-$(CONFIG_EFI)	+= fw/uefi.o
iwlwifi-$(CONFIG_IWLWIFI_DEBUGFS) += fw/debugfs.o

iwlwifi-objs += $(iwlwifi-m)
+24 −81
Original line number Diff line number Diff line
@@ -10,13 +10,22 @@
#include "fw/api/commands.h"
#include "fw/api/nvm-reg.h"
#include "fw/api/alive.h"
#include <linux/efi.h>
#include "fw/uefi.h"

struct iwl_pnvm_section {
	__le32 offset;
	const u8 data[];
} __packed;

struct pnvm_sku_package {
	u8 rev;
	u8 reserved1[3];
	u32 total_size;
	u8 n_skus;
	u8 reserved2[11];
	u8 data[];
};

static bool iwl_pnvm_complete_fn(struct iwl_notif_wait_data *notif_wait,
				 struct iwl_rx_packet *pkt, void *data)
{
@@ -220,83 +229,6 @@ static int iwl_pnvm_parse(struct iwl_trans *trans, const u8 *data,
	return -ENOENT;
}

#if defined(CONFIG_EFI)

#define IWL_EFI_VAR_GUID EFI_GUID(0x92daaf2f, 0xc02b, 0x455b,	\
				  0xb2, 0xec, 0xf5, 0xa3,	\
				  0x59, 0x4f, 0x4a, 0xea)

#define IWL_UEFI_OEM_PNVM_NAME	L"UefiCnvWlanOemSignedPnvm"

#define IWL_HARDCODED_PNVM_SIZE 4096

struct pnvm_sku_package {
	u8 rev;
	u8 reserved1[3];
	u32 total_size;
	u8 n_skus;
	u8 reserved2[11];
	u8 data[];
};

static int iwl_pnvm_get_from_efi(struct iwl_trans *trans,
				 u8 **data, size_t *len)
{
	struct efivar_entry *pnvm_efivar;
	struct pnvm_sku_package *package;
	unsigned long package_size;
	int err;

	pnvm_efivar = kzalloc(sizeof(*pnvm_efivar), GFP_KERNEL);
	if (!pnvm_efivar)
		return -ENOMEM;

	memcpy(&pnvm_efivar->var.VariableName, IWL_UEFI_OEM_PNVM_NAME,
	       sizeof(IWL_UEFI_OEM_PNVM_NAME));
	pnvm_efivar->var.VendorGuid = IWL_EFI_VAR_GUID;

	/*
	 * TODO: we hardcode a maximum length here, because reading
	 * from the UEFI is not working.  To implement this properly,
	 * we have to call efivar_entry_size().
	 */
	package_size = IWL_HARDCODED_PNVM_SIZE;

	package = kmalloc(package_size, GFP_KERNEL);
	if (!package) {
		err = -ENOMEM;
		goto out;
	}

	err = efivar_entry_get(pnvm_efivar, NULL, &package_size, package);
	if (err) {
		IWL_DEBUG_FW(trans,
			     "PNVM UEFI variable not found %d (len %lu)\n",
			     err, package_size);
		goto out;
	}

	IWL_DEBUG_FW(trans, "Read PNVM fro UEFI with size %lu\n", package_size);

	*data = kmemdup(package->data, *len, GFP_KERNEL);
	if (!*data)
		err = -ENOMEM;
	*len = package_size - sizeof(*package);

out:
	kfree(package);
	kfree(pnvm_efivar);

	return err;
}
#else /* CONFIG_EFI */
static inline int iwl_pnvm_get_from_efi(struct iwl_trans *trans,
					u8 **data, size_t *len)
{
	return -EOPNOTSUPP;
}
#endif /* CONFIG_EFI */

static int iwl_pnvm_get_from_fs(struct iwl_trans *trans, u8 **data, size_t *len)
{
	const struct firmware *pnvm;
@@ -335,6 +267,7 @@ int iwl_pnvm_load(struct iwl_trans *trans,
{
	u8 *data;
	size_t len;
	struct pnvm_sku_package *package;
	struct iwl_notification_wait pnvm_wait;
	static const u16 ntf_cmds[] = { WIDE_ID(REGULATORY_AND_NVM_GROUP,
						PNVM_INIT_COMPLETE_NTFY) };
@@ -356,9 +289,19 @@ int iwl_pnvm_load(struct iwl_trans *trans,
	}

	/* First attempt to get the PNVM from BIOS */
	ret = iwl_pnvm_get_from_efi(trans, &data, &len);
	if (!ret)
	package = iwl_uefi_get_pnvm(trans, &len);
	if (!IS_ERR_OR_NULL(package)) {
		data = kmemdup(package->data, len, GFP_KERNEL);

		/* free package regardless of whether kmemdup succeeded */
		kfree(package);

		if (data) {
			/* we need only the data size */
			len -= sizeof(*package);
			goto parse;
		}
	}

	/* If it's not available, try from the filesystem */
	ret = iwl_pnvm_get_from_fs(trans, &data, &len);
+64 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
 * Copyright(c) 2021 Intel Corporation
 */

#include "iwl-drv.h"
#include "pnvm.h"
#include "iwl-prph.h"
#include "iwl-io.h"

#include "fw/uefi.h"
#include <linux/efi.h>

#define IWL_EFI_VAR_GUID EFI_GUID(0x92daaf2f, 0xc02b, 0x455b,	\
				  0xb2, 0xec, 0xf5, 0xa3,	\
				  0x59, 0x4f, 0x4a, 0xea)

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

	pnvm_efivar = kzalloc(sizeof(*pnvm_efivar), GFP_KERNEL);
	if (!pnvm_efivar)
		return ERR_PTR(-ENOMEM);

	memcpy(&pnvm_efivar->var.VariableName, IWL_UEFI_OEM_PNVM_NAME,
	       sizeof(IWL_UEFI_OEM_PNVM_NAME));
	pnvm_efivar->var.VendorGuid = IWL_EFI_VAR_GUID;

	/*
	 * TODO: we hardcode a maximum length here, because reading
	 * from the UEFI is not working.  To implement this properly,
	 * we have to call efivar_entry_size().
	 */
	package_size = IWL_HARDCODED_PNVM_SIZE;

	data = kmalloc(package_size, GFP_KERNEL);
	if (!data) {
		data = ERR_PTR(-ENOMEM);
		*len = 0;
		goto out;
	}

	err = efivar_entry_get(pnvm_efivar, NULL, &package_size, data);
	if (err) {
		IWL_DEBUG_FW(trans,
			     "PNVM UEFI variable not found %d (len %zd)\n",
			     err, package_size);
		kfree(data);
		data = ERR_PTR(err);
		goto out;
	}

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

out:
	kfree(pnvm_efivar);

	return data;
}
+25 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
 * Copyright(c) 2021 Intel Corporation
 */


#define IWL_UEFI_OEM_PNVM_NAME	L"UefiCnvWlanOemSignedPnvm"

/*
 * TODO: we have these hardcoded values that the caller must pass,
 * because reading from the UEFI is not working.  To implement this
 * properly, we have to change iwl_pnvm_get_from_uefi() to call
 * efivar_entry_size() and return the value to the caller instead.
 */
#define IWL_HARDCODED_PNVM_SIZE 4096

#ifdef CONFIG_EFI
void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len);
#else /* CONFIG_EFI */
static inline
void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
{
	return ERR_PTR(-EOPNOTSUPP);
}
#endif /* CONFIG_EFI */