Introduction
Device configuration is provided to macOS with a dedicated buffer, called EfiDevicePathPropertyDatabase
. This buffer is a serialised map of DevicePaths to a map of property names and their values.
Property data can be debugged with gfxutil. To obtain current property data, use the following command in macOS:
ioreg -lw0 -p IODeviceTree -n efi -r -x | grep device-properties |
sed 's/.*<//;s/>.*//' > /tmp/device-properties.hex &&
gfxutil /tmp/device-properties.hex /tmp/device-properties.plist &&
cat /tmp/device-properties.plist
Device properties are part of the IODeviceTree
(gIODT
) plane of the macOS I/O Registry. This plane has several construction stages relevant for the platform initialisation. While the early construction stage is performed by the XNU kernel in the IODeviceTreeAlloc
method, the majority of the construction is performed by the platform expert, implemented in AppleACPIPlatformExpert.kext
.
AppleACPIPlatformExpert incorporates two stages of IODeviceTree
construction implemented by calling AppleACPIPlatformExpert::mergeDeviceProperties
:
- During ACPI table initialisation through the recursive ACPI namespace scanning by the calls to
AppleACPIPlatformExpert::createDTNubs
. - During IOService registration (
IOServices::registerService
) callbacks implemented as a part ofAppleACPIPlatformExpert::platformAdjustService
function and its private worker methodAppleACPIPlatformExpert::platformAdjustPCIDevice
specific to the PCI devices.
The application of the stages depends on the device presence in ACPI tables. The first stage applies very early but exclusively to the devices present in ACPI tables. The second stage applies to all devices much later after the PCI configuration and may repeat the first stage if the device was not present in ACPI.
For all kernel extensions that may inspect the IODeviceTree
plane without probing, such as Lilu
and its plugins (e.g. WhateverGreen
), it is especially important to ensure device presence in the ACPI tables. A failure to do so may result in erratic behaviour caused by ignoring the injected device properties as they were not constructed at the first stage. See SSDT-IMEI.dsl
and SSDT-BRG0.dsl
for an example.