Skip to content

zephyr-cp: fall back to the WiFi MAC for cpu.uid on siwx91x - #11246

Merged
tannewt merged 1 commit into
adafruit:mainfrom
mikeysklar:zephyr-cp/cpu-uid-mac-fallback
Aug 26, 2026
Merged

zephyr-cp: fall back to the WiFi MAC for cpu.uid on siwx91x#11246
tannewt merged 1 commit into
adafruit:mainfrom
mikeysklar:zephyr-cp/cpu-uid-mac-fallback

Conversation

@mikeysklar

Copy link
Copy Markdown
Collaborator

What

cpu.uid reads as all zeros on siwx91x. Falls back to the WiFi MAC when hwinfo has nothing, matching how Silicon Labs' own tooling defines this part's unique ID.

Why

Zephyr has no hwinfo driver for siwx91x, so hwinfo_get_device_id() returns -ENOSYS, common_hal_mcu_processor_get_uid() zero-fills, and both microcontroller.cpu.uid and the web workflow's version.json UID field come back as zeros.

Writing an hwinfo driver against the efuse controller would not fix it. The efuse identity region (0x020..0x02F of the array behind TA_EFUSE_IO_BASE_ADDR) is unprogrammed on this silicon. I read it on two independent dies, on two separate benches, and both carry only four nonzero calibration bytes at 0x3A..0x3D and zeros where the MACs would live. The MACs are only in the flash-resident config space, and Simplicity Commander's own "Unique ID" for this part is the WiFi MAC zero-extended to eight bytes.

So this matches that definition rather than inventing a second one: when hwinfo yields nothing, build the UID as 00 00 | mac[6] from the wifi net_if link address. That address is populated at driver init, before the radio is enabled, so it is available whenever this function can be called.

Caveat, stated in the code comment as well: unlike a burned-in serial, this is whatever the WiFi MAC currently is, and Silicon Labs' mfg917 tool can reprogram it. Nothing on this silicon offers an immutable per-device ID, so cpu.uid should not be treated as tamper-proof on this port.

The change is additive and guarded on CONFIG_SOC_FAMILY_SILABS_SIWX91X. The two existing diagnostic printk lines are untouched and still fire on any board where nothing supplies a UID; on siwx91x they now stay quiet because the fallback succeeds.

Hardware tested

Silicon Labs SiWx917-DK2605A (Zephyr board siwx917_dk2605a, SoC SiWG917M111MGTBA), zephyr-cp, built on current main.

  • Before: version.json UID field all zeros.
  • After: UID 0000C09B9EC39910, matching commander device info for the same board byte for byte.

Flash cost 64 bytes: 799136 B (76.21%) on main, 799200 B (76.22%) with this change.

Not tested on other zephyr-cp boards; the new code is inside #if CONFIG_SOC_FAMILY_SILABS_SIWX91X and compiles out everywhere else.

AI assistance

Written with Claude Code. I read the efuse arrays on the two boards, ran the before/after comparison against Simplicity Commander, and reviewed the diff myself.

@mikeysklar

Copy link
Copy Markdown
Collaborator Author

Now verified on two boards rather than one, each a different die with a different MAC:

board J-Link commander device info Unique ID microcontroller.cpu.uid
A (macOS 15) 440353836 0000c09b9ec2eec8 0000c09b9ec2eec8
B (Ubuntu 24.04) 440353787 0000c09b9ec39910 0000c09b9ec39910

Both match byte for byte, and the two boards give different values, so this is reading real per-die data rather than a constant.

Read from the REPL with:

import microcontroller, binascii
print(binascii.hexlify(microcontroller.cpu.uid).decode())

Test images were main + #11230 + this patch. #11230 is needed only because main currently panics at boot on this board without it (see my comment there); it does not touch this code path.

Unrelated observation while I was in there, filed here only so it is written down somewhere: wifi.radio.mac_address returned 28:ae:00:00:01:00 on both boards with the radio not yet started, which is not the real MAC. Different code path from this one, and I will look at it separately.

@tannewt tannewt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is too SoC specific for here.

ssize_t len = hwinfo_get_device_id(raw_id, COMMON_HAL_MCU_PROCESSOR_UID_LENGTH);
#if defined(CONFIG_SOC_FAMILY_SILABS_SIWX91X)
if (len < 0) {
ssize_t mac_len = siwx91x_uid_from_wifi_mac(raw_id);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't there a generic way to do this? Seems like a reasonable fallback to do in a generic way.

Board and SoC specific stuff shouldn't be done here.

You could also modify the zephyr side of this.

hwinfo_get_device_id() returns -ENOSYS on any SoC without an hwinfo driver,
so cpu.uid, and the web workflow's version.json UID field, read as all zeros.

When that happens and the board has WiFi, derive the UID from the WiFi
interface link address instead. A link address is per-device, so it is a
better answer than nothing. It is also what at least one vendor already means
by the part's unique ID: Simplicity Commander reports the siwx91x unique ID as
the WiFi MAC zero-extended to eight bytes, and this produces the same value.

Unlike a burned-in serial this can generally be reprogrammed by vendor
tooling, so cpu.uid must not be relied on as tamper proof where it comes from
this path. Boards whose SoC has a real hwinfo driver never reach it.

Gated on CONFIG_WIFI, and purely additive: the existing diagnostics still fire
on any board where nothing supplies a UID.

Verified on two SiWx917-DK2605A boards, each a different die:

    board A  commander 0000c09b9ec2eec8   cpu.uid 0000c09b9ec2eec8
    board B  commander 0000c09b9ec39910   cpu.uid 0000c09b9ec39910
@mikeysklar
mikeysklar force-pushed the zephyr-cp/cpu-uid-mac-fallback branch from f1bb58c to 3dbb714 Compare August 25, 2026 17:17
@mikeysklar

Copy link
Copy Markdown
Collaborator Author

Made it generic, no SoC references left. Gated on CONFIG_WIFI, so any board whose SoC has no hwinfo driver but does have WiFi gets the link address instead of zeros. Still matches commander on both boards after the rewrite.

An hwinfo driver upstream would be the cleaner home, but it would have nothing to read: the efuse identity region is unprogrammed on this silicon, verified on both dies, so the MAC in flash config space is the only per-device value there is.

@tannewt tannewt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@tannewt
tannewt merged commit 1d9be31 into adafruit:main Aug 26, 2026
43 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants