Skip to content

emOS: make /dev from sysfs, not from biscuit's numbers - #1034

Merged
wilbowes merged 1 commit into
mainfrom
feat/emos-nodes-by-name
Oct 24, 2026
Merged

wilbowes merged 1 commit into
mainfrom
feat/emos-nodes-by-name

Conversation

@wilbowes

Copy link
Copy Markdown
Owner

emOS's init now makes /dev from what the kernel lists in sysfs instead of a table of numbers read off a biscuit. That table was wrong on the Echo Dot 3, where it left the USB console silent. Tested on 41C8 (Dot 3), C95, 15LE and 035T (radar).

Why

Device majors such as ttyGS's are allocated at boot. On the Dot 3 ttyGS0 is 246:0 and 247:0 is the jack detector, so the console's shell opened that and sat silent. The sound minors differ by board as well. This is step 3a of emOS on the Dot 3 (donut).

What changed

  • mknodes() reads /sys/dev/{char,block}/*/uevent (MAJOR, MINOR, DEVNAME, DEVMODE), the same source devtmpfs uses, and makes each node. DEVMODE gives exactly the 0666 set the old hand-written calls chose.
  • The scan runs again where drivers register late: while waiting for the gadget's tty, after wmt_loader, and before the wmtWifi write. A scan only adds nodes, so repeating it is safe.
  • Names that are absolute or contain a .. component are refused.
  • devcheck.c, a new off-target check, runs the real parser against uevent text read off VVV (3.18) and 41C8 (4.4), the format's edge cases, and a full scan over a fake /sys/dev with mknod intercepted, so it needs no root. Breaking the default mode or the .. guard makes it fail. It's wired into ci.yml and the emOS release checks.

Partitions by name are not in this PR. They wait for the packer's boot-partition stamp (3b), because biscuit's partition names carry an _x suffix that varies by device.

Tested on hardware

Each device got its own boot image with only /init swapped, repacked with em_emos_build.pack after a byte-exact roundtrip, and the write was read back before rebooting.

Echo Base Result
41C8 Dot 3, 4.4 arm64 kernel console shell, ttyGS0 246:0, /dev/null 0666, snd/input/all partitions, system_b and /data mounted
C95 biscuit, FireOS 5 kernel console, ttyGS0 247:0, WMT nodes, WiFi, registered with the dev controller; trial-timer reboot once, then confirmed
15LE biscuit, FireOS 6 32-bit kernel console, WMT nodes, WiFi, registered, boot confirmed
035T radar console, WMT nodes, WiFi, registered with the EA controller, boot confirmed

All eight existing emOS checks still pass.

🤖 Generated with Claude Code

https://claude.ai/code/session_01BofN7aQbgNvVKNVXdGNR2f

init mknod'd every node from a table read off a biscuit. Majors such as
ttyGS's are allocated at boot, so on the Echo Dot 3 (donut, 41C8) ttyGS0
is 246:0 and 247:0 is the jack detector: the console's shell opened that,
`svc console failing fast` in the trail, and the USB console sat silent.
The sound minors differ by board too.

init now reads what ueventd would: /sys/dev/{char,block}/*/uevent, making
/dev/<DEVNAME> (block under /dev/block) with DEVMODE where the kernel gives
one, which is exactly the 0666 set the hand-written calls chose. A walk only
adds nodes, so it runs again where drivers appear late: while waiting for
the gadget's tty, after wmt_loader registers stpwmt/stpbt, and before the
wmtWifi write. Names that are absolute or contain a `..` component are
refused. The umask handling moves into the walk, since rescans run after
PID 1 is back at 022.

devcheck.c drives the real parser with uevent text read off biscuit (VVV,
3.18) and the Dot 3 (41C8, 4.4), the format's edges, and the whole walk
over a fake /sys/dev with mknod intercepted so CI needs no root. Mutating
the default mode or the `..` guard fails it. Wired into ci.yml and the
emOS release checks.

On 41C8 under emOS: shell on the console, ttyGS0 246:0, /dev/null 0666,
snd, input and every mmcblk0p* node present, system_b and /data mounted.
Partitions by name waits for the packer's boot-partition stamp, because
biscuit's names carry an _x suffix that varies by device.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BofN7aQbgNvVKNVXdGNR2f
@wilbowes
wilbowes merged commit f154031 into main Oct 24, 2026
13 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.

1 participant