Make sure we have enough space to add padding and final token to the nvram
authorkettenis <kettenis@openbsd.org>
Sat, 23 Oct 2021 12:48:17 +0000 (12:48 +0000)
committerkettenis <kettenis@openbsd.org>
Sat, 23 Oct 2021 12:48:17 +0000 (12:48 +0000)
data.  Also add the MAC address to the nvram data when there is a
"local-mac-address" property in the device tree.  This makes bwfm(4) work
with the firmware/nvram/clm_blob files provided with MacOS on the Apple
M1 Macs.

ok patrick@

sys/dev/ic/bwfm.c
sys/dev/ic/bwfmvar.h
sys/dev/pci/if_bwfm_pci.c
sys/dev/sdmmc/if_bwfm_sdio.c

index 654e2e0..5670fea 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: bwfm.c,v 1.90 2021/08/31 23:05:11 patrick Exp $ */
+/* $OpenBSD: bwfm.c,v 1.91 2021/10/23 12:48:17 kettenis Exp $ */
 /*
  * Copyright (c) 2010-2016 Broadcom Corporation
  * Copyright (c) 2016,2017 Patrick Wildt <patrick@blueri.se>
@@ -2859,14 +2859,23 @@ bwfm_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
 }
 
 int
-bwfm_nvram_convert(u_char *buf, size_t len, size_t *newlenp)
+bwfm_nvram_convert(int node, u_char **bufp, size_t *sizep, size_t *newlenp)
 {
-       u_char *src, *dst, *end = buf + len;
-       size_t count = 0, pad;
+       u_char *src, *dst, *end = *bufp + *sizep, *newbuf;
+       size_t count = 0, newsize, pad;
        uint32_t token;
        int skip = 0;
 
-       for (src = buf, dst = buf; src != end; ++src) {
+       /*
+        * Allocate a new buffer with enough space for the MAC
+        * address, padding and final token.
+        */
+       newsize = *sizep + 64;
+       newbuf = malloc(newsize, M_DEVBUF, M_NOWAIT);
+       if (newbuf == NULL)
+               return 1;
+
+       for (src = *bufp, dst = newbuf; src != end; ++src) {
                if (*src == '\n') {
                        if (count > 0)
                                *dst++ = '\0';
@@ -2886,11 +2895,31 @@ bwfm_nvram_convert(u_char *buf, size_t len, size_t *newlenp)
                ++count;
        }
 
-       count = dst - buf;
-       pad = roundup(count + 1, 4) - count;
+#if defined(__HAVE_FDT)
+       /*
+        * Append MAC address if one is provided in the device tree.
+        * This is needed on Apple Silicon Macs.
+        */
+       if (node) {
+               u_char enaddr[ETHER_ADDR_LEN];
+               char macaddr[32];
+
+               if (OF_getprop(node, "local-mac-address",
+                   enaddr, sizeof(enaddr))) {
+                       snprintf(macaddr, sizeof(macaddr),
+                           "macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
+                           enaddr[0], enaddr[1], enaddr[2], enaddr[3],
+                           enaddr[4], enaddr[5]);
+                       if (*dst)
+                               *dst++ = '\0';
+                       memcpy(dst, macaddr, strlen(macaddr));
+                       dst += strlen(macaddr);
+               }
+       }
+#endif
 
-       if (count + pad + sizeof(token) > len)
-               return 1;
+       count = dst - newbuf;
+       pad = roundup(count + 1, 4) - count;
 
        memset(dst, 0, pad);
        count += pad;
@@ -2903,6 +2932,9 @@ bwfm_nvram_convert(u_char *buf, size_t len, size_t *newlenp)
        memcpy(dst, &token, sizeof(token));
        count += sizeof(token);
 
+       free(*bufp, M_DEVBUF, *sizep);
+       *bufp = newbuf;
+       *sizep = newsize;
        *newlenp = count;
        return 0;
 }
@@ -3010,28 +3042,22 @@ bwfm_loadfirmware(struct bwfm_softc *sc, const char *chip, const char *bus,
        if (sysname != NULL) {
                r = snprintf(name, sizeof(name), "brcmfmac%s%s.%s.txt", chip,
                    bus, sysname);
-               if ((r > 0 && r < sizeof(name)) &&
-                   loadfirmware(name, nvram, nvsize) == 0) {
-                       if (bwfm_nvram_convert(*nvram, *nvsize, nvlen) != 0) {
-                               printf("%s: failed to process file %s\n",
-                                   DEVNAME(sc), name);
-                               free(*ucode, M_DEVBUF, *size);
-                               free(*nvram, M_DEVBUF, *nvsize);
-                               return 1;
-                       }
-               }
+               if (r > 0 && r < sizeof(name))
+                       loadfirmware(name, nvram, nvsize);
        }
 
-       if (*nvlen == 0) {
+       if (*nvsize == 0) {
                snprintf(name, sizeof(name), "brcmfmac%s%s.txt", chip, bus);
-               if (loadfirmware(name, nvram, nvsize) == 0) {
-                       if (bwfm_nvram_convert(*nvram, *nvsize, nvlen) != 0) {
-                               printf("%s: failed to process file %s\n",
-                                   DEVNAME(sc), name);
-                               free(*ucode, M_DEVBUF, *size);
-                               free(*nvram, M_DEVBUF, *nvsize);
-                               return 1;
-                       }
+               loadfirmware(name, nvram, nvsize);
+       }
+
+       if (*nvsize != 0) {
+               if (bwfm_nvram_convert(sc->sc_node, nvram, nvsize, nvlen)) {
+                       printf("%s: failed to process file %s\n",
+                           DEVNAME(sc), name);
+                       free(*ucode, M_DEVBUF, *size);
+                       free(*nvram, M_DEVBUF, *nvsize);
+                       return 1;
                }
        }
 
index c722660..a641a74 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: bwfmvar.h,v 1.24 2021/08/31 23:05:11 patrick Exp $ */
+/* $OpenBSD: bwfmvar.h,v 1.25 2021/10/23 12:48:17 kettenis Exp $ */
 /*
  * Copyright (c) 2010-2016 Broadcom Corporation
  * Copyright (c) 2016,2017 Patrick Wildt <patrick@blueri.se>
@@ -158,6 +158,7 @@ struct bwfm_softc {
 #define                BWFM_IO_TYPE_D11N               1
 #define                BWFM_IO_TYPE_D11AC              2
 
+       int                      sc_node;
        int                      sc_initialized;
        int                      sc_tx_timer;
 
@@ -191,6 +192,6 @@ struct bwfm_core *bwfm_chip_get_pmu(struct bwfm_softc *);
 void bwfm_rx(struct bwfm_softc *, struct mbuf *, struct mbuf_list *);
 void bwfm_do_async(struct bwfm_softc *, void (*)(struct bwfm_softc *, void *),
     void *, int);
-int bwfm_nvram_convert(u_char *, size_t, size_t *);
+int bwfm_nvram_convert(int, u_char **, size_t *, size_t *);
 int bwfm_loadfirmware(struct bwfm_softc *, const char *, const char *,
     u_char **, size_t *, u_char **, size_t *, size_t *);
index 3bf5578..e39163f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_bwfm_pci.c,v 1.56 2021/08/31 23:05:11 patrick Exp $        */
+/*     $OpenBSD: if_bwfm_pci.c,v 1.57 2021/10/23 12:48:17 kettenis Exp $       */
 /*
  * Copyright (c) 2010-2016 Broadcom Corporation
  * Copyright (c) 2017 Patrick Wildt <patrick@blueri.se>
@@ -396,6 +396,10 @@ bwfm_pci_attach(struct device *parent, struct device *self, void *aux)
        }
        printf(": %s\n", intrstr);
 
+#if defined(__HAVE_FDT)
+       sc->sc_sc.sc_node = PCITAG_NODE(pa->pa_tag);
+#endif
+
        sc->sc_sc.sc_bus_ops = &bwfm_pci_bus_ops;
        sc->sc_sc.sc_proto_ops = &bwfm_pci_msgbuf_ops;
        bwfm_attach(&sc->sc_sc);
index be86f50..2ea9e26 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_bwfm_sdio.c,v 1.40 2021/06/06 10:48:30 aoyama Exp $ */
+/* $OpenBSD: if_bwfm_sdio.c,v 1.41 2021/10/23 12:48:17 kettenis Exp $ */
 /*
  * Copyright (c) 2010-2016 Broadcom Corporation
  * Copyright (c) 2016,2017 Patrick Wildt <patrick@blueri.se>
@@ -84,7 +84,6 @@ struct bwfm_sdio_softc {
        struct sdmmc_function   **sc_sf;
        struct rwlock            *sc_lock;
        void                     *sc_ih;
-       int                       sc_node;
        int                       sc_oob;
 
        int                       sc_initialized;
@@ -258,7 +257,7 @@ bwfm_sdio_attach(struct device *parent, struct device *self, void *aux)
 
 #if defined(__HAVE_FDT)
        if (sf->cookie)
-               sc->sc_node = *(int *)sf->cookie;
+               sc->sc_sc.sc_node = *(int *)sf->cookie;
 #endif
 
        task_set(&sc->sc_task, bwfm_sdio_task, sc);
@@ -462,8 +461,8 @@ bwfm_sdio_preinit(struct bwfm_softc *bwfm)
        }
 
 #if defined(__HAVE_FDT)
-       if (sc->sc_node) {
-               sc->sc_ih = fdt_intr_establish(sc->sc_node,
+       if (sc->sc_sc.sc_node) {
+               sc->sc_ih = fdt_intr_establish(sc->sc_sc.sc_node,
                    IPL_NET, bwfm_sdio_oob_intr, sc, DEVNAME(sc));
                if (sc->sc_ih != NULL) {
                        bwfm_sdio_write_1(sc, BWFM_SDIO_CCCR_SEPINT,