Skip to content

intel_hfsts(4) / hfstsfd(4)

Source: sys/dev/intel/intel_hfsts.c, sys/dev/intel/intel_hfsts_isa.c, sys/dev/intel/intel_hfsts.h, sys/modules/intel_hfsts/. amd64 only, wired into sys/conf/files.amd64.

A diagnostic driver that answers one question: what state is the Management Engine in? It reads the Host Firmware Status registers, HFSTS1 through HFSTS6, which live entirely in PCI configuration space. BAR0 stays unmapped and the messaging ring stays untouched. Register counts and layout follow Linux drivers/misc/mei/hw-me.c.

There are two attach paths, because the ME is not always visible:

DriverBusHandles
intel_hfstspciMEI/HECI function enumerated normally, so decode HFS1-6
hfstsfdisaMEI function is missing, so check whether firmware hid it

hfs_count decides which OIDs get created, so a Cougar Point box never grows an hfs4 node that would read a reserved offset:

Nothing is cached. The ME moves around after boot, on watchdog resets, HAP toggles, S0i3, and M0 to M3 power events, so an attach-time snapshot would go stale under a running system. Every read goes back to PCI config space.

All three table-driven handlers share the same shape. arg1 is the softc and arg2 indexes a static descriptor table, so adding a field is a table row rather than a new function.

The other registers in play are HFSTS2 bits 27:24 for PM_EVENT and HFSTS3 bits 6:4 for FW_SKU. HFSTS4, 5 and 6 are exposed raw only, with no field decode.

hfsts_state_summary folds eight HFS1 fields into a single word. The tests run in this order and the first match wins:

Absent is the useful tell that the config read came back as garbage. A dead function reads 0xffffffff, which decodes to CWS 15, and nothing in the table sits at 15.

Once coreboot’s PCH_DISABLE_MEI1 or PCH_DISABLE_MEI2 has run, the MEI PCI function never enumerates, so there is no device_t for hfsts_attach to run against at all. That is why hfstsfd is an identify-style isa driver. It is modeled on ichwd_identify, which faces the same problem for the ICH watchdog.

The mapping is page-aligned by hand. HFSTS_FD_FD2_PAGE masks off the page offset because pmap_mapdev wants a page base, and HFSTS_FD_FD2_PAGE_OFF re-applies it inside the mapped page. The mapping is torn down immediately after that single 4-byte read, so nothing stays mapped.

RCBA and FD2 only sit at this layout on Ibex Peak, Cougar Point, Panther Point, Lynx Point and Wildcat Point. hfsts_fd_lpc_ids lists those LPC device IDs, reusing the DEVICEID_* values from dev/ichwd/ichwd.h. Anything else is skipped.

ObservationMeaning
dev.intel_hfsts.0.summary is NormalME is up, steady, no error
it is Activebusy, transitional, manufacturing mode, bad FPT, failed BUP, update running, or an exceptional opmode
it is DisabledME explicitly off, HAP or soft-disable
it is Absentthe read never landed on a real state, so the function is dead or hidden
no intel_hfsts device and dev.hfstsfd.0.mei1_disabled is 1silicon is there, firmware hid it with Function Disable
no intel_hfsts device and mei1_disabled is 0MEI should have enumerated, so something else is wrong
dev.hfstsfd.0.status is rcba-disabledRCBA is locked or disabled and FD2 cannot be read
neither device shows upthis PCH generation is in neither table
  • Read-only. Every access is a read, and detach is a no-op that returns 0, since all the sysctls belong to the device’s own sysctl context and newbus tears them down.
  • ICH devices with no defined HFS register are skipped.
  • ICH10 and PCH5 through PCH7 never get HFS3-6 OIDs, so sysctl -a stays clear of reserved config offsets.
Terminal window
kldload intel_hfsts
sysctl dev.intel_hfsts # decoded ME state, read live
sysctl dev.hfstsfd # only exists when MEI is firmware-hidden

Booting with -v adds the full field dump at attach time: state, opstate, opmode, error, mfg_mode, fpt_bad, fw_init_complete, update_in_progress and boot_options_present.