| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 | 
							- From ce2e6db554fad444fa0b3904fc3015336e0ef765 Mon Sep 17 00:00:00 2001
 
- From: Hans de Goede <[email protected]>
 
- Date: Thu, 11 Oct 2018 11:51:06 +0200
 
- Subject: [PATCH] brcmfmac: Add support for getting nvram contents from EFI
 
-  variables
 
- Various X86 laptops with a SDIO attached brcmfmac wifi chip, store the
 
- nvram contents in a special EFI variable. This commit adds support for
 
- getting nvram directly from this EFI variable, without the user needing
 
- to manually copy it.
 
- This makes Wifi / Bluetooth work out of the box on these devices instead of
 
- requiring manual setup.
 
- This has been tested on the following models: Acer Iconia Tab8 w1-810,
 
- Acer One 10, Asus T100CHI, Asus T100HA, Asus T100TA, Asus T200TA and a
 
- Lenovo Mixx 2 8.
 
- Tested-by: Hans de Goede <[email protected]>
 
- Signed-off-by: Hans de Goede <[email protected]>
 
- Signed-off-by: Kalle Valo <[email protected]>
 
- ---
 
-  .../broadcom/brcm80211/brcmfmac/firmware.c         | 63 +++++++++++++++++++---
 
-  1 file changed, 57 insertions(+), 6 deletions(-)
 
- --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
 
- +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
 
- @@ -14,6 +14,7 @@
 
-   * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-   */
 
-  
 
- +#include <linux/efi.h>
 
-  #include <linux/kernel.h>
 
-  #include <linux/slab.h>
 
-  #include <linux/device.h>
 
- @@ -445,6 +446,51 @@ struct brcmf_fw {
 
-  
 
-  static void brcmf_fw_request_done(const struct firmware *fw, void *ctx);
 
-  
 
- +#ifdef CONFIG_EFI
 
- +static u8 *brcmf_fw_nvram_from_efi(size_t *data_len_ret)
 
- +{
 
- +	const u16 name[] = { 'n', 'v', 'r', 'a', 'm', 0 };
 
- +	struct efivar_entry *nvram_efivar;
 
- +	unsigned long data_len = 0;
 
- +	u8 *data = NULL;
 
- +	int err;
 
- +
 
- +	nvram_efivar = kzalloc(sizeof(*nvram_efivar), GFP_KERNEL);
 
- +	if (!nvram_efivar)
 
- +		return NULL;
 
- +
 
- +	memcpy(&nvram_efivar->var.VariableName, name, sizeof(name));
 
- +	nvram_efivar->var.VendorGuid = EFI_GUID(0x74b00bd9, 0x805a, 0x4d61,
 
- +						0xb5, 0x1f, 0x43, 0x26,
 
- +						0x81, 0x23, 0xd1, 0x13);
 
- +
 
- +	err = efivar_entry_size(nvram_efivar, &data_len);
 
- +	if (err)
 
- +		goto fail;
 
- +
 
- +	data = kmalloc(data_len, GFP_KERNEL);
 
- +	if (!data)
 
- +		goto fail;
 
- +
 
- +	err = efivar_entry_get(nvram_efivar, NULL, &data_len, data);
 
- +	if (err)
 
- +		goto fail;
 
- +
 
- +	brcmf_info("Using nvram EFI variable\n");
 
- +
 
- +	kfree(nvram_efivar);
 
- +	*data_len_ret = data_len;
 
- +	return data;
 
- +
 
- +fail:
 
- +	kfree(data);
 
- +	kfree(nvram_efivar);
 
- +	return NULL;
 
- +}
 
- +#else
 
- +static u8 *brcmf_fw_nvram_from_efi(size_t *data_len) { return NULL; }
 
- +#endif
 
- +
 
-  static void brcmf_fw_free_request(struct brcmf_fw_request *req)
 
-  {
 
-  	struct brcmf_fw_item *item;
 
- @@ -463,11 +509,12 @@ static int brcmf_fw_request_nvram_done(c
 
-  {
 
-  	struct brcmf_fw *fwctx = ctx;
 
-  	struct brcmf_fw_item *cur;
 
- +	bool free_bcm47xx_nvram = false;
 
- +	bool kfree_nvram = false;
 
-  	u32 nvram_length = 0;
 
-  	void *nvram = NULL;
 
-  	u8 *data = NULL;
 
-  	size_t data_len;
 
- -	bool raw_nvram;
 
-  
 
-  	brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev));
 
-  
 
- @@ -476,12 +523,13 @@ static int brcmf_fw_request_nvram_done(c
 
-  	if (fw && fw->data) {
 
-  		data = (u8 *)fw->data;
 
-  		data_len = fw->size;
 
- -		raw_nvram = false;
 
-  	} else {
 
- -		data = bcm47xx_nvram_get_contents(&data_len);
 
- -		if (!data && !(cur->flags & BRCMF_FW_REQF_OPTIONAL))
 
- +		if ((data = bcm47xx_nvram_get_contents(&data_len)))
 
- +			free_bcm47xx_nvram = true;
 
- +		else if ((data = brcmf_fw_nvram_from_efi(&data_len)))
 
- +			kfree_nvram = true;
 
- +		else if (!(cur->flags & BRCMF_FW_REQF_OPTIONAL))
 
-  			goto fail;
 
- -		raw_nvram = true;
 
-  	}
 
-  
 
-  	if (data)
 
- @@ -489,8 +537,11 @@ static int brcmf_fw_request_nvram_done(c
 
-  					     fwctx->req->domain_nr,
 
-  					     fwctx->req->bus_nr);
 
-  
 
- -	if (raw_nvram)
 
- +	if (free_bcm47xx_nvram)
 
-  		bcm47xx_nvram_release_contents(data);
 
- +	if (kfree_nvram)
 
- +		kfree(data);
 
- +
 
-  	release_firmware(fw);
 
-  	if (!nvram && !(cur->flags & BRCMF_FW_REQF_OPTIONAL))
 
-  		goto fail;
 
 
  |