1*84c3c995SLuca Coelho // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2*84c3c995SLuca Coelho /*
3*84c3c995SLuca Coelho  * Copyright(c) 2021 Intel Corporation
4*84c3c995SLuca Coelho  */
5*84c3c995SLuca Coelho 
6*84c3c995SLuca Coelho #include "iwl-drv.h"
7*84c3c995SLuca Coelho #include "pnvm.h"
8*84c3c995SLuca Coelho #include "iwl-prph.h"
9*84c3c995SLuca Coelho #include "iwl-io.h"
10*84c3c995SLuca Coelho 
11*84c3c995SLuca Coelho #include "fw/uefi.h"
12*84c3c995SLuca Coelho #include <linux/efi.h>
13*84c3c995SLuca Coelho 
14*84c3c995SLuca Coelho #define IWL_EFI_VAR_GUID EFI_GUID(0x92daaf2f, 0xc02b, 0x455b,	\
15*84c3c995SLuca Coelho 				  0xb2, 0xec, 0xf5, 0xa3,	\
16*84c3c995SLuca Coelho 				  0x59, 0x4f, 0x4a, 0xea)
17*84c3c995SLuca Coelho 
18*84c3c995SLuca Coelho void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
19*84c3c995SLuca Coelho {
20*84c3c995SLuca Coelho 	struct efivar_entry *pnvm_efivar;
21*84c3c995SLuca Coelho 	void *data;
22*84c3c995SLuca Coelho 	unsigned long package_size;
23*84c3c995SLuca Coelho 	int err;
24*84c3c995SLuca Coelho 
25*84c3c995SLuca Coelho 	pnvm_efivar = kzalloc(sizeof(*pnvm_efivar), GFP_KERNEL);
26*84c3c995SLuca Coelho 	if (!pnvm_efivar)
27*84c3c995SLuca Coelho 		return ERR_PTR(-ENOMEM);
28*84c3c995SLuca Coelho 
29*84c3c995SLuca Coelho 	memcpy(&pnvm_efivar->var.VariableName, IWL_UEFI_OEM_PNVM_NAME,
30*84c3c995SLuca Coelho 	       sizeof(IWL_UEFI_OEM_PNVM_NAME));
31*84c3c995SLuca Coelho 	pnvm_efivar->var.VendorGuid = IWL_EFI_VAR_GUID;
32*84c3c995SLuca Coelho 
33*84c3c995SLuca Coelho 	/*
34*84c3c995SLuca Coelho 	 * TODO: we hardcode a maximum length here, because reading
35*84c3c995SLuca Coelho 	 * from the UEFI is not working.  To implement this properly,
36*84c3c995SLuca Coelho 	 * we have to call efivar_entry_size().
37*84c3c995SLuca Coelho 	 */
38*84c3c995SLuca Coelho 	package_size = IWL_HARDCODED_PNVM_SIZE;
39*84c3c995SLuca Coelho 
40*84c3c995SLuca Coelho 	data = kmalloc(package_size, GFP_KERNEL);
41*84c3c995SLuca Coelho 	if (!data) {
42*84c3c995SLuca Coelho 		data = ERR_PTR(-ENOMEM);
43*84c3c995SLuca Coelho 		*len = 0;
44*84c3c995SLuca Coelho 		goto out;
45*84c3c995SLuca Coelho 	}
46*84c3c995SLuca Coelho 
47*84c3c995SLuca Coelho 	err = efivar_entry_get(pnvm_efivar, NULL, &package_size, data);
48*84c3c995SLuca Coelho 	if (err) {
49*84c3c995SLuca Coelho 		IWL_DEBUG_FW(trans,
50*84c3c995SLuca Coelho 			     "PNVM UEFI variable not found %d (len %zd)\n",
51*84c3c995SLuca Coelho 			     err, package_size);
52*84c3c995SLuca Coelho 		kfree(data);
53*84c3c995SLuca Coelho 		data = ERR_PTR(err);
54*84c3c995SLuca Coelho 		goto out;
55*84c3c995SLuca Coelho 	}
56*84c3c995SLuca Coelho 
57*84c3c995SLuca Coelho 	IWL_DEBUG_FW(trans, "Read PNVM from UEFI with size %zd\n", package_size);
58*84c3c995SLuca Coelho 	*len = package_size;
59*84c3c995SLuca Coelho 
60*84c3c995SLuca Coelho out:
61*84c3c995SLuca Coelho 	kfree(pnvm_efivar);
62*84c3c995SLuca Coelho 
63*84c3c995SLuca Coelho 	return data;
64*84c3c995SLuca Coelho }
65