Skip to content

Feat/macos intel and full system info - #35

Merged
manupawickramasinghe merged 4 commits into
masterfrom
feat/macos-intel-and-full-system-info
Oct 13, 2026
Merged

manupawickramasinghe merged 4 commits into
masterfrom
feat/macos-intel-and-full-system-info

Conversation

@manupawickramasinghe

Copy link
Copy Markdown
Member

No description provided.

manupawickramasinghe and others added 4 commits October 14, 2026 01:34
The macOS backend claimed AppleSMC does not exist on M-series Macs. It
does: it registers as AppleSMCKeysEndpoint, a subclass, so `ioreg -n
AppleSMC` (an exact name match) finds nothing while
IOServiceMatching("AppleSMC") finds it. On this M5 it opens unprivileged
and publishes 2,294 keys.

New `smc.rs` speaks the 80-byte SMCParamStruct protocol (layout pinned by
a test), enumerates keys once, and polls only the chosen ones:

  - Fans (FNum / F#Ac / F#Tg) on Macs that have them.
  - System Total (PSTR), DC In power/voltage/current (PDTR/VD0R/ID0R),
    Wi-Fi module and airflow probes, on a new board-level node.
  - CPU Die and GPU Die, average and hottest, from the Tp/Te and Tg key
    families — the prefixes that stay stable across M1–M5, which is how
    macmon and Stats derive CPU/GPU temperature. Per-core naming is
    avoided because every chip variant renumbers those keys.

On Apple Silicon only `flt ` and single-byte keys are trusted: integer
keys are labelled big-endian but are mostly little-endian (B0AV reads
12526 mV as little-endian, matching AppleSmartBattery's Voltage).

Intel Macs get a curated named-key table (CPU proximity/die/cores,
package power, voltages, board probes) decoded from the big-endian
sp78/fpe2 fixed-point formats. Intel vs ARM is decided at runtime from
hw.optional.arm64, so an x86_64 build under Rosetta takes the ARM path.

GPU collection now returns every IOAccelerator with statistics (an
Intel Mac's integrated + discrete pair), classified by driver class,
with the AMD/Intel driver keys for temperature, clocks and VRAM.

Verified on an M5 MacBook Air:
  - DC In power == V x I on every poll (19.71 V x 0.428 A = 8.44 W vs
    8.42 W); System Total tracks DC In on AC with the battery idle.
  - 10-thread CPU load: CPU Die avg 47.7 -> 74 C, hottest 80 C.
  - 20-poll soak: sensor set stable, no NaN.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The macOS Summary was built for one Apple Silicon laptop and left a lot
on the table. Verified against System Information, csrutil and ioreg on
an M5 MacBook Air, it now shows:

  - Memory: the real technology and vendor ("LPDDR5", "Samsung") from
    /chosen dram-type/dram-vendor, instead of a generic "LPDDR
    (on-package)". Unified memory is an explicit flag, not a substring.
  - Board: model id (Mac17,3), board id (J813) and the SoC as chipset
    ("Apple M5 (T8142)"). The CPU codename is now the SoC part number
    (T8142) rather than the board id.
  - OS: Secure Boot from /chosen secure-boot, and SIP via
    csr_get_active_config (resolved at runtime; it is SPI).
  - Displays (new): native panel resolution, "looks like" size, refresh
    and diagonal, joined to EDID product names. Native size comes from
    the mode flagged native — the current mode on a Retina panel is the
    scaled backing store (2940x1912 for a 2560x1664 panel).
  - Battery (new): full/design capacity, health, cycles of rated
    cycles, charge, and power source with adapter wattage.
  - Drives: every physical disk, internal or external, via whole-disk
    IOMedia and its IOBlockStorageDevice ancestor, so SATA, USB and
    Thunderbolt drives appear and sizes are no longer paired by
    position. Disk images and APFS containers are skipped.

Intel Macs take their own branch (decided at runtime): base clock from
hw.cpufrequency, L3, Hyper-Threading thread count, UEFI boot, GPUs from
PCI display controllers with VRAM, and memory modules plus firmware
version/date parsed from the SMBIOS table AppleSMBIOS publishes. The
new `smbios` parser is pure and tested on every platform; the same
table feeds the Hex Viewer on Intel Macs.

`sensorview info`, the text report (which now reuses the CLI renderer
so the two cannot drift) and the GUI Summary all render the new fields.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds a native `macos-15-intel` leg to CI and to the release matrix. The
macOS backend chooses its Intel paths at runtime, so the only way to run
them is on Intel hardware; GitHub's Intel macOS runners are VMs, and the
live tests already treat a missing SMC/battery/GPU as absent rather than
failing. Both macOS legs can share the `*.dmg` release glob because
cargo-packager names images by architecture (`_aarch64.dmg` / `_x64.dmg`,
checked in its dmg packager source).

Docs catch up with the code:

  - README platform table gains an Intel column; fans, system power and
    SMBIOS are no longer listed as missing on macOS, with footnotes
    saying exactly what was verified where (fans: decoder only, fanless
    dev machine; Intel: CI VMs only, not physical hardware).
  - The "AppleSMC does not exist on M-series" claim is corrected in the
    README, hid.rs and iokit.rs.
  - TODO.md records the two things still unverified on real hardware.
  - The Intel CPU "socket" row stays blank: a package count is not a
    socket designation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Walking all 2,294 SMC keys at startup took ~0.7 s on an M5 — paid by
every GUI launch and every one-shot `sensorview get`. Curated keys are
now looked up by name (one call each), and the Tp/Te/Tg families are
found by binary search: the SMC returns keys by index in strictly
ascending order (verified across all 2,294). The order is spot-checked
first and the full walk remains as a fallback, and a test pins that the
search returns exactly what a full walk does. SmcSensors::new: 697 ms
-> 37 ms.

Also hardens what a CI virtual machine can legitimately do differently:

  - An unrecognised GPU driver on Apple Silicon is Apple's (a VM's
    paravirtualized GPU), so it still gets the GPU node.
  - With no Apple GPU node, the GPU's DVFS clock, IOReport power and
    SMC die temperature stay on the SoC node instead of being dropped.
  - soc_part() only returns a value shaped like a part number (T8142),
    so a VM's platform-name never shows as chipset or codename.
  - Live tests treat a virtual SMC without index lookup, unusual DRAM
    strings and EDID panel sizes as absence, not failure.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@manupawickramasinghe
manupawickramasinghe merged commit 5547f6d into master Oct 13, 2026
5 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