bge: read MAC from loader hint for boards without NVRAM/EEPROM

BCM57766 on Apple T2 Macs (Macmini8,1) has no dedicated EEPROM and the
chip firmware handshake fails (the T2 intercepts PCI config space),
leaving the SRAM mailbox unpopulated.  All four existing MAC retrieval
paths (SRAM mailbox, NVRAM, EEPROM, firmware stub) fail, causing bge to
abort attach with "failed to read station address".

Work around this with two changes:

  1. Tolerate EEPROM read failure on BCM57766.  The chip is copper-only
     so hwcfg=0 is correct; skip the fatal error that aborts attach
     before bge_get_eaddr() is ever called.

  2. Implement bge_get_eaddr_fw() to read a "hint.bge.N.mac" string
     (e.g. "f0:18:98:f4:1e:2f") from loader(8) tunable / kenv.

This is a workaround until the T2 BCE API is understood well enough to
either poke the chip firmware into completing its handshake or read the
MAC from the T2 directly.

Reviewed by:	adrian
Differential Revision:	https://reviews.freebsd.org/D57090
This commit is contained in:
Abdelkader Boudih
2026-06-14 13:55:33 -07:00
committed by Adrian Chadd
parent e37e49bfaa
commit 142cba958b
+31 -1
View File
@@ -3766,10 +3766,18 @@ bge_attach(device_t dev)
(sc->bge_asicrev != BGE_ASICREV_BCM5906)) {
if (bge_read_eeprom(sc, (caddr_t)&hwcfg, BGE_EE_HWCFG_OFFSET,
sizeof(hwcfg))) {
device_printf(sc->bge_dev, "failed to read EEPROM\n");
/*
* BCM57766 on Apple T2 Macs has no dedicated EEPROM;
* the chip is copper-only so hwcfg=0 is correct.
*/
if (sc->bge_asicrev != BGE_ASICREV_BCM57766) {
device_printf(sc->bge_dev,
"failed to read EEPROM\n");
error = ENXIO;
goto fail;
}
hwcfg = 0;
} else
hwcfg = ntohl(hwcfg);
}
@@ -6677,7 +6685,29 @@ bge_sysctl_mem_read(SYSCTL_HANDLER_ARGS)
static int
bge_get_eaddr_fw(struct bge_softc *sc, uint8_t ether_addr[])
{
const char *mac_str;
unsigned int o[ETHER_ADDR_LEN];
char trail;
int i, n, unit;
unit = device_get_unit(sc->bge_dev);
if (resource_string_value("bge", unit, "mac", &mac_str) != 0)
return (1);
/* Parse and validate; trailing-char check rejects garbage. */
n = sscanf(mac_str, "%x:%x:%x:%x:%x:%x%c",
&o[0], &o[1], &o[2], &o[3], &o[4], &o[5], &trail);
if (n != 6)
return (1);
for (i = 0; i < ETHER_ADDR_LEN; i++) {
if (o[i] > 0xff)
return (1);
ether_addr[i] = (uint8_t)o[i];
}
if (ETHER_IS_MULTICAST(ether_addr) ||
ETHER_IS_ZERO(ether_addr))
return (1);
return (0);
}
static int