[esp32] Apply custom eFuse MAC as base MAC for all interfaces (#18452)

This commit is contained in:
Keith Burzinski
2026-08-25 23:59:37 -05:00
committed by GitHub
parent 9baff76520
commit e37a540fb7
4 changed files with 30 additions and 13 deletions
+8
View File
@@ -2,6 +2,7 @@
#include "esphome/core/application.h"
#include "esphome/core/defines.h"
#include "esphome/core/helpers.h"
#include "preferences.h"
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
@@ -29,6 +30,13 @@ void loop_task(void *pv_params) {
}
extern "C" void app_main() {
// Apply the custom eFuse MAC (if burned and valid) as the base MAC before any
// interface (Wi-Fi, Ethernet, Bluetooth, 802.15.4) derives its address from it.
// The logger does not exist yet, so only log-free helpers may be used here.
uint8_t mac[MAC_ADDRESS_SIZE];
if (get_custom_mac_address(mac)) {
set_mac_address(mac);
}
initArduino();
esp32::setup_preferences();
#if CONFIG_FREERTOS_UNICORE
+17 -8
View File
@@ -71,23 +71,32 @@ static bool read_valid_mac(uint8_t *mac, esp_err_t err) { return err == ESP_OK &
static constexpr size_t MAC_ADDRESS_SIZE_BITS = MAC_ADDRESS_SIZE * 8; // 48 bits
// Must not use the ESPHome logger (may run before it exists, e.g. from app_main()).
bool get_custom_mac_address(uint8_t *mac) {
// has_custom_mac_address() checks the raw eFuse field, while the reads below select their
// method differently and may still fail (CRC), so the result must be validated again.
if (!has_custom_mac_address())
return false;
#if defined(CONFIG_SOC_IEEE802154_SUPPORTED)
return read_valid_mac(mac, esp_efuse_read_field_blob(ESP_EFUSE_MAC_CUSTOM, mac, MAC_ADDRESS_SIZE_BITS));
#else
return read_valid_mac(mac, esp_efuse_mac_get_custom(mac));
#endif
}
void get_mac_address_raw(uint8_t *mac) { // NOLINT(readability-non-const-parameter)
if (get_custom_mac_address(mac)) {
return;
}
#if defined(CONFIG_SOC_IEEE802154_SUPPORTED)
// When CONFIG_SOC_IEEE802154_SUPPORTED is defined, esp_efuse_mac_get_default
// returns the 802.15.4 EUI-64 address, so we read directly from eFuse instead.
// Both paths already read raw eFuse bytes, so there is no CRC-bypass fallback
// This already reads raw eFuse bytes, so there is no CRC-bypass fallback
// (unlike the non-IEEE802154 path where esp_efuse_mac_get_default does CRC checks).
if (has_custom_mac_address() &&
read_valid_mac(mac, esp_efuse_read_field_blob(ESP_EFUSE_MAC_CUSTOM, mac, MAC_ADDRESS_SIZE_BITS))) {
return;
}
if (read_valid_mac(mac, esp_efuse_read_field_blob(ESP_EFUSE_MAC_FACTORY, mac, MAC_ADDRESS_SIZE_BITS))) {
return;
}
#else
if (has_custom_mac_address() && read_valid_mac(mac, esp_efuse_mac_get_custom(mac))) {
return;
}
if (read_valid_mac(mac, esp_efuse_mac_get_default(mac))) {
return;
}
@@ -140,11 +140,6 @@ void event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, voi
}
void WiFiComponent::wifi_pre_setup_() {
uint8_t mac[MAC_ADDRESS_SIZE];
if (has_custom_mac_address()) {
get_mac_address_raw(mac);
set_mac_address(mac);
}
// Network interface setup handled by network component
s_wifi_event_group = xEventGroupCreate();
if (s_wifi_event_group == nullptr) {
+5
View File
@@ -2089,6 +2089,11 @@ const char *get_mac_address_pretty_into_buffer(std::span<char, MAC_ADDRESS_PRETT
#ifdef USE_ESP32
/// Set the MAC address to use from the provided byte array (6 bytes).
void set_mac_address(uint8_t *mac);
/// Read the custom MAC address from eFuse into the provided byte array (6 bytes).
/// Must not use the ESPHome logger (may run before it is initialized); IDF itself may still log.
/// @return True if a valid custom MAC address was read; on false, the contents of mac are undefined.
bool get_custom_mac_address(uint8_t *mac);
#endif
/// Check if a custom MAC address is set (ESP32 & variants)