PCs actually do need a device tree.
They just call it something else.
It is not correct to say that operating systems for the descendents of PC/AT compatibles assume the existence of things such as a PCI bus. They do not.
Nor do they probe. Probing for hardware, just poking some I/O or memory addresses to see whether they work, has not been necessary since the middle 1990s.
Rather, they enumerate a root bus.
This is a bus that is not enumerable by communicating with bus controller device hardware, as with other enumerable buses. This is a bus that exists purely as a construct of the system firmware and operating system. It is enumerated by querying the system firmware, and what is present on it is baked into the system firmware by the mainboard manufacturer, to match what is on the mainboard.
There is little difference in concept between this and a device tree. Just like a device tree, it has to be created to match the actual board. Just like a device tree, it is a list of device nodes with resource information (amongst other things) attached to them. Just like a device tree, it is exterior to the operating system and is not a list of things to probe for hardwired into the operating system's own code.
The Plug and Play BIOS Specification has the firmware provide a simple device tree in memory to an operating system, one of the nodes of which will be (for example) a PNP0A03
node designating a PCI bus, giving the I/O and memory resources that it is assigned and thus where it is to be found.
ACPI supersedes this, but the idea remains the same. In ACPI there is a table called the Differentiated System Description Table, augmented by a Secondary System Descriptor Table, which (with information from a few other ACPI tables) provide much the same thing.
(If you want to see this from the firmware developers' side, look at Coreboot for one example. It has a large body of ACPI Source Language files, a selection of which are compiled into a bytecode binary image that is incorporated into the firmware. The selection is controlled by a configuration tool that prompts one for the specific mainboard being targetted.)
On FreeBSD, for example, the Plug and Play BIOS Specification information was enumerated by a pnpbios
bus driver within the kernel (that has since been removed), and (nowadays) the ACPI information is enumerated by an acpi
bus driver. In Linux, there is (still) a drivers/pnp/pnpbios
bus driver that reads the Plug and Play BIOS tables, and the ACPI tables are read by code scattered throughout arch/arm64/kernel/
and arch/x86/kernel/
.
The enumerable root bus can, but generally does not (pace some encroachments by ACPI) overlap with things enumerable on the buses that are devices on the root bus. For example, whilst there are PNPxxxx
IDs for ATA buses, system firmware will not list PCI-to-ATA bridge devices on the root bus, using them. Such devices are found by finding the PCI bus when enumerating the root bus, and then finding the PCI-to-ATA bridge when enumerating the PCI bus.
The simple fact of the matter is that on wildly divergent platforms with different names for the concepts, the same basic principle is in operation. There is a baked-in list of devices that match the otherwise non-enumerable devices in the system, and the firmware or whatever boot loader is in use provides a mechanism for the operating system to read that list and configure the devices on it, allowing the operating system to then enumerate those devices in their turns.
Further reading