summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2021-10-23 12:48:18 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2021-10-23 12:48:18 +0000
commit3b0cd2fbb992969c63d80909b59cfaa929e37814 (patch)
treef0106c6e7d88a1b8246ab34e6a24e53cb507d059 /sys
parent8ae17e2ccb76b9f1e0678fb0baf4cfd57c74c373 (diff)
Make sure we have enough space to add padding and final token to the nvram
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@
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/ic/bwfm.c82
-rw-r--r--sys/dev/ic/bwfmvar.h5
-rw-r--r--sys/dev/pci/if_bwfm_pci.c6
-rw-r--r--sys/dev/sdmmc/if_bwfm_sdio.c9
4 files changed, 66 insertions, 36 deletions
diff --git a/sys/dev/ic/bwfm.c b/sys/dev/ic/bwfm.c
index 654e2e05c66..5670fea971a 100644
--- a/sys/dev/ic/bwfm.c
+++ b/sys/dev/ic/bwfm.c
@@ -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;
}
}
diff --git a/sys/dev/ic/bwfmvar.h b/sys/dev/ic/bwfmvar.h
index c7226607a81..a641a74fa3b 100644
--- a/sys/dev/ic/bwfmvar.h
+++ b/sys/dev/ic/bwfmvar.h
@@ -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 *);
diff --git a/sys/dev/pci/if_bwfm_pci.c b/sys/dev/pci/if_bwfm_pci.c
index 3bf557862d5..e39163f1550 100644
--- a/sys/dev/pci/if_bwfm_pci.c
+++ b/sys/dev/pci/if_bwfm_pci.c
@@ -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);
diff --git a/sys/dev/sdmmc/if_bwfm_sdio.c b/sys/dev/sdmmc/if_bwfm_sdio.c
index be86f50a752..2ea9e267ae0 100644
--- a/sys/dev/sdmmc/if_bwfm_sdio.c
+++ b/sys/dev/sdmmc/if_bwfm_sdio.c
@@ -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,