diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2021-10-23 12:48:18 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2021-10-23 12:48:18 +0000 |
commit | 3b0cd2fbb992969c63d80909b59cfaa929e37814 (patch) | |
tree | f0106c6e7d88a1b8246ab34e6a24e53cb507d059 /sys | |
parent | 8ae17e2ccb76b9f1e0678fb0baf4cfd57c74c373 (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.c | 82 | ||||
-rw-r--r-- | sys/dev/ic/bwfmvar.h | 5 | ||||
-rw-r--r-- | sys/dev/pci/if_bwfm_pci.c | 6 | ||||
-rw-r--r-- | sys/dev/sdmmc/if_bwfm_sdio.c | 9 |
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, |