From ea92f6c34cb8a88c7f6bfdf1317f9ec3c4c2da85 Mon Sep 17 00:00:00 2001 From: patrick Date: Mon, 27 Dec 2021 17:12:34 +0000 Subject: [PATCH] Support reading OTP information from a few more chips, necessary to learn firmare names on Apple M1 Pro/Max and Apple T2 Macs. --- sys/dev/ic/bwfmreg.h | 9 ++--- sys/dev/pci/if_bwfm_pci.c | 78 ++++++++++++++++++++++++++++++++------- 2 files changed, 68 insertions(+), 19 deletions(-) diff --git a/sys/dev/ic/bwfmreg.h b/sys/dev/ic/bwfmreg.h index 0f728a06c0a..417b3235a50 100644 --- a/sys/dev/ic/bwfmreg.h +++ b/sys/dev/ic/bwfmreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bwfmreg.h,v 1.23 2021/12/27 10:59:20 patrick Exp $ */ +/* $OpenBSD: bwfmreg.h,v 1.24 2021/12/27 17:12:34 patrick Exp $ */ /* * Copyright (c) 2010-2016 Broadcom Corporation * Copyright (c) 2016,2017 Patrick Wildt @@ -32,6 +32,9 @@ #define BWFM_CHIP_REG_CAPABILITIES_EXT_AOB_PRESENT 0x00000040 #define BWFM_CHIP_REG_WATCHDOG 0x00000080 #define BWFM_CHIP_REG_EROMPTR 0x000000FC +#define BWFM_CHIP_REG_SROMCONTROL 0x00000190 +#define BWFM_CHIP_REG_SROMCONTROL_OTPSEL (1 << 4) +#define BWFM_CHIP_REG_SROMCONTROL_OTP_PRESENT (1 << 5) #define BWFM_CHIP_REG_SR_CAPABILITY 0x00000500 #define BWFM_CHIP_REG_SR_CONTROL0 0x00000504 #define BWFM_CHIP_REG_SR_CONTROL0_ENABLE (1 << 0) @@ -91,10 +94,6 @@ #define BWFM_ARMCR4_BANKINFO_BLK_1K_MASK 0x200 #define BWFM_ARMCR4_BANKPDA 0x004C -/* GCI (OTP) registers */ -#define BWFM_OTP_SIZE 64 -#define BWFM_OTP_4378_BASE 0x1120 - /* SOCRAM registers */ #define BWFM_SOCRAM_COREINFO 0x0000 #define BWFM_SOCRAM_COREINFO_SRBSZ_BASE 14 diff --git a/sys/dev/pci/if_bwfm_pci.c b/sys/dev/pci/if_bwfm_pci.c index c8d326a6ae8..173db2d4008 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.61 2021/12/27 13:54:39 patrick Exp $ */ +/* $OpenBSD: if_bwfm_pci.c,v 1.62 2021/12/27 17:12:34 patrick Exp $ */ /* * Copyright (c) 2010-2016 Broadcom Corporation * Copyright (c) 2017 Patrick Wildt @@ -942,32 +942,82 @@ bwfm_pci_read_otp(struct bwfm_pci_softc *sc) { struct bwfm_softc *bwfm = (void *)sc; struct bwfm_core *core; - uint8_t otp[BWFM_OTP_SIZE]; + uint32_t coreid, base, words; + uint32_t page, offset, sromctl; + uint8_t *otp; int i; - if (bwfm->sc_chip.ch_chip != BRCM_CC_4378_CHIP_ID) + switch (bwfm->sc_chip.ch_chip) { + case BRCM_CC_4355_CHIP_ID: + coreid = BWFM_AGENT_CORE_CHIPCOMMON; + base = 0x8c0; + words = 0xb2; + break; + case BRCM_CC_4364_CHIP_ID: + coreid = BWFM_AGENT_CORE_CHIPCOMMON; + base = 0x8c0; + words = 0x1a0; + break; + case BRCM_CC_4377_CHIP_ID: + case BRCM_CC_4378_CHIP_ID: + coreid = BWFM_AGENT_CORE_GCI; + base = 0x1120; + words = 0x170; + break; + case BRCM_CC_4387_CHIP_ID: + coreid = BWFM_AGENT_CORE_GCI; + base = 0x113c; + words = 0x170; + break; + default: return 0; + } - core = bwfm_chip_get_core(bwfm, BWFM_AGENT_CORE_GCI); + core = bwfm_chip_get_core(bwfm, coreid); if (core == NULL) return 1; - for (i = 0; i < (sizeof(otp) / sizeof(uint32_t)); i++) - ((uint32_t *)otp)[i] = bwfm_pci_buscore_read(bwfm, - core->co_base + BWFM_OTP_4378_BASE + i * sizeof(uint32_t)); + /* Map OTP to shadow area */ + if (coreid == BWFM_AGENT_CORE_CHIPCOMMON) { + bwfm_pci_select_core(sc, coreid); + sromctl = bus_space_read_4(sc->sc_reg_iot, sc->sc_reg_ioh, + BWFM_CHIP_REG_SROMCONTROL); - for (i = 0; i < BWFM_OTP_SIZE - 1; ) { - if (otp[i + 0] == 0) { - i++; - continue; - } - if (i + otp[i + 1] > BWFM_OTP_SIZE) + if (!(sromctl & BWFM_CHIP_REG_SROMCONTROL_OTP_PRESENT)) + return 0; + + bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh, + BWFM_CHIP_REG_SROMCONTROL, sromctl | + BWFM_CHIP_REG_SROMCONTROL_OTPSEL); + } + + /* Map bus window to SROM/OTP shadow area */ + page = (core->co_base + base) & ~(BWFM_PCI_BAR0_REG_SIZE - 1); + offset = (core->co_base + base) & (BWFM_PCI_BAR0_REG_SIZE - 1); + pci_conf_write(sc->sc_pc, sc->sc_tag, BWFM_PCI_BAR0_WINDOW, page); + + otp = mallocarray(words, sizeof(uint16_t), M_TEMP, M_WAITOK); + for (i = 0; i < words; i++) + ((uint16_t *)otp)[i] = bus_space_read_2(sc->sc_reg_iot, + sc->sc_reg_ioh, offset + i * sizeof(uint16_t)); + + /* Unmap OTP */ + if (coreid == BWFM_AGENT_CORE_CHIPCOMMON) { + bwfm_pci_select_core(sc, coreid); + bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh, + BWFM_CHIP_REG_SROMCONTROL, sromctl); + } + + for (i = 0; i < (words * sizeof(uint16_t)) - 1; i += otp[i + 1]) { + if (otp[i + 0] == 0) + break; + if (i + otp[i + 1] > words * sizeof(uint16_t)) break; bwfm_pci_process_otp_tuple(sc, otp[i + 0], otp[i + 1], &otp[i + 2]); - i += otp[i + 1]; } + free(otp, M_TEMP, words * sizeof(uint16_t)); return 0; } -- 2.20.1