From db31205a9fe3825962fcc94215bac8ee43eb6375 Mon Sep 17 00:00:00 2001 From: kettenis Date: Sat, 23 Oct 2021 12:48:17 +0000 Subject: [PATCH] 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@ --- sys/dev/ic/bwfm.c | 82 ++++++++++++++++++++++++------------ sys/dev/ic/bwfmvar.h | 5 ++- sys/dev/pci/if_bwfm_pci.c | 6 ++- 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 @@ -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 @@ -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 @@ -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 @@ -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, -- 2.20.1