diff mbox series

[v2,17/35] brcmfmac: pcie: Provide a buffer of random bytes to the device

Message ID 20220104072658.69756-18-marcan@marcan.st (mailing list archive)
State Awaiting Upstream
Delegated to: Netdev Maintainers
Headers show
Series brcmfmac: Support Apple T2 and M1 platforms | expand

Checks

Context Check Description
netdev/tree_selection success Not a local patch

Commit Message

Hector Martin Jan. 4, 2022, 7:26 a.m. UTC
Newer Apple firmwares on chipsets without a hardware RNG require the
host to provide a buffer of 256 random bytes to the device on
initialization. This buffer is present immediately before NVRAM,
suffixed by a footer containing a magic number and the buffer length.

This won't affect chips/firmwares that do not use this feature, so do it
unconditionally.

Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Hector Martin <marcan@marcan.st>
---
 .../broadcom/brcm80211/brcmfmac/pcie.c        | 30 +++++++++++++++++++
 1 file changed, 30 insertions(+)

Comments

Arend van Spriel Jan. 10, 2022, 9:11 a.m. UTC | #1
On 1/4/2022 8:26 AM, Hector Martin wrote:
> Newer Apple firmwares on chipsets without a hardware RNG require the
> host to provide a buffer of 256 random bytes to the device on
> initialization. This buffer is present immediately before NVRAM,
> suffixed by a footer containing a magic number and the buffer length.
> 
> This won't affect chips/firmwares that do not use this feature, so do it
> unconditionally.

Not sure what the general opinion is here, but pulling random bytes for 
naught seems wasteful to me. So if there is a way of knowing it is 
needed please make it conditional.

Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
> Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
> Signed-off-by: Hector Martin <marcan@marcan.st>
> ---
>   .../broadcom/brcm80211/brcmfmac/pcie.c        | 30 +++++++++++++++++++
>   1 file changed, 30 insertions(+)
Hector Martin Jan. 10, 2022, 11:09 a.m. UTC | #2
On 2022/01/10 18:11, Arend van Spriel wrote:
> On 1/4/2022 8:26 AM, Hector Martin wrote:
>> Newer Apple firmwares on chipsets without a hardware RNG require the
>> host to provide a buffer of 256 random bytes to the device on
>> initialization. This buffer is present immediately before NVRAM,
>> suffixed by a footer containing a magic number and the buffer length.
>>
>> This won't affect chips/firmwares that do not use this feature, so do it
>> unconditionally.
> 
> Not sure what the general opinion is here, but pulling random bytes for 
> naught seems wasteful to me. So if there is a way of knowing it is 
> needed please make it conditional.

We could gate it on specific chips only, if you don't mind maintaining a
list of those. AIUI that would be all the T2 platform chips or so (the
newer two don't seem to need it).

Alternatively we could just do this only if an Apple OTP is detected.
That is already implicitly gated by the OTP offset chip list.
Arend van Spriel Jan. 10, 2022, 11:28 a.m. UTC | #3
On 1/10/2022 12:09 PM, Hector Martin wrote:
> On 2022/01/10 18:11, Arend van Spriel wrote:
>> On 1/4/2022 8:26 AM, Hector Martin wrote:
>>> Newer Apple firmwares on chipsets without a hardware RNG require the
>>> host to provide a buffer of 256 random bytes to the device on
>>> initialization. This buffer is present immediately before NVRAM,
>>> suffixed by a footer containing a magic number and the buffer length.
>>>
>>> This won't affect chips/firmwares that do not use this feature, so do it
>>> unconditionally.
>>
>> Not sure what the general opinion is here, but pulling random bytes for
>> naught seems wasteful to me. So if there is a way of knowing it is
>> needed please make it conditional.
> 
> We could gate it on specific chips only, if you don't mind maintaining a
> list of those. AIUI that would be all the T2 platform chips or so (the
> newer two don't seem to need it).
> 
> Alternatively we could just do this only if an Apple OTP is detected.
> That is already implicitly gated by the OTP offset chip list.

That sounds like a good approach.

Regards,
Arend
diff mbox series

Patch

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
index cc76f00724e6..a8cccfbea20b 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
@@ -12,6 +12,7 @@ 
 #include <linux/interrupt.h>
 #include <linux/bcma/bcma.h>
 #include <linux/sched.h>
+#include <linux/random.h>
 #include <asm/unaligned.h>
 
 #include <soc.h>
@@ -1662,6 +1663,13 @@  brcmf_pcie_init_share_ram_info(struct brcmf_pciedev_info *devinfo,
 	return 0;
 }
 
+struct brcmf_random_seed_footer {
+	__le32 length;
+	__le32 magic;
+};
+
+#define BRCMF_RANDOM_SEED_MAGIC		0xfeedc0de
+#define BRCMF_RANDOM_SEED_LENGTH	0x100
 
 static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
 					const struct firmware *fw, void *nvram,
@@ -1693,11 +1701,33 @@  static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
 	brcmf_pcie_write_ram32(devinfo, devinfo->ci->ramsize - 4, 0);
 
 	if (nvram) {
+		size_t rand_len = BRCMF_RANDOM_SEED_LENGTH;
+		struct brcmf_random_seed_footer footer = {
+			.length = cpu_to_le32(rand_len),
+			.magic = cpu_to_le32(BRCMF_RANDOM_SEED_MAGIC),
+		};
+		void *randbuf;
+
 		brcmf_dbg(PCIE, "Download NVRAM %s\n", devinfo->nvram_name);
 		address = devinfo->ci->rambase + devinfo->ci->ramsize -
 			  nvram_len;
 		brcmf_pcie_copy_mem_todev(devinfo, address, nvram, nvram_len);
 		brcmf_fw_nvram_free(nvram);
+
+		/* Some Apple chips/firmwares expect a buffer of random data
+		 * to be present before NVRAM
+		 */
+		brcmf_dbg(PCIE, "Download random seed\n");
+
+		address -= sizeof(footer);
+		brcmf_pcie_copy_mem_todev(devinfo, address, &footer,
+					  sizeof(footer));
+
+		address -= rand_len;
+		randbuf = kzalloc(rand_len, GFP_KERNEL);
+		get_random_bytes(randbuf, rand_len);
+		brcmf_pcie_copy_mem_todev(devinfo, address, randbuf, rand_len);
+		kfree(randbuf);
 	} else {
 		brcmf_dbg(PCIE, "No matching NVRAM file found %s\n",
 			  devinfo->nvram_name);