//! The firmware-agnostic discovery facade. //! //! The kernel calls `platform.discover()` and gets back a generic `DeviceTree` //! without ever naming ACPI or device-tree — the same way it imports `architecture` //! without naming x86_64. Which backend runs is decided *at runtime* from what //! the bootloader handed us (an ACPI RSDP today, a device-tree blob later), //! because a single image — a future ARM kernel especially — may boot under //! either firmware. That's a deliberate divergence from `architecture`, which is a //! compile-time choice. const std = @import("std"); const boot_handoff = @import("boot-handoff"); const device_model = @import("device-model.zig"); const acpi = @import("acpi.zig"); const power = @import("power.zig"); const devicetree = @import("device-tree.zig"); pub const DeviceTree = device_model.DeviceTree; pub const Device = device_model.Device; pub const DeviceClass = device_model.DeviceClass; pub const Resource = device_model.Resource; pub const ResourceKind = device_model.ResourceKind; pub const Hal = device_model.Hal; pub const PowerInformation = acpi.PowerInformation; pub const AmlStats = acpi.AmlStats; pub const PlatformInformation = acpi.PlatformInformation; pub const RegisterAccess = acpi.RegisterAccess; pub const IsoEntry = acpi.IsoEntry; pub const Cpu = acpi.Cpu; /// The register map + sleep types discovery extracted, for logging/diagnostics. pub fn powerInformation() PowerInformation { return acpi.power_information; } /// The scalar firmware facts the architecture layer needs to avoid legacy assumptions /// (8259 presence, LAPIC base, PM timer, SPCR UART, IRQ overrides). pub fn platformInformation() PlatformInformation { return acpi.platform_information; } /// AML parse integrity/diagnostics (namespace node count, bytes consumed). pub fn amlStats() AmlStats { return acpi.aml_stats; } /// The usable logical processors discovered during enumeration — one entry per /// core danos may schedule on, each carrying the Local APIC ID an SMP wake targets. /// `len` is the hardware's degree of parallelism: how many tasks *could* run at the /// same instant once the application processors are started. Today only the /// bootstrap processor is actually running, so starting the rest is the pending SMP /// step (see docs/smp.md). Borrowed from static storage populated by `discover`. pub fn cpus() []const Cpu { return acpi.cpu_information.cpus[0..acpi.cpu_information.count]; } /// Non-zero only if enumeration found more processors than the static pool holds /// (the surplus were dropped from `cpus()`); surfaced so the cap is never silent. pub fn cpusDropped() usize { return acpi.cpu_information.dropped; } /// Enumerate hardware into a fresh device tree. `hal` supplies the hardware /// primitives the backend needs (MMIO mapping for PCIe configuration space, port I/O for /// ACPI registers); pass the architecture implementation. Errors leave nothing to clean up /// beyond the tree's own allocations. pub fn discover( boot_information: *const boot_handoff.BootInformation, allocator: std.mem.Allocator, hal: Hal, ) !DeviceTree { var device_tree = try DeviceTree.init(allocator); if (boot_information.acpi_rsdp != 0) { try acpi.discover(boot_information.acpi_rsdp, &device_tree, hal); } else { // No ACPI RSDP. A device-tree boot would parse its blob here; today that // path is a stub, so this reports the machine described itself no way we // understand yet. try devicetree.discover(&device_tree); } return device_tree; } /// Restart the machine. Never returns on success; returns only if no reset method /// worked (extremely unlikely). Backend-agnostic entry the kernel calls. pub fn reboot(hal: Hal) void { power.reboot(hal); } /// Power the machine off (ACPI S5). Never returns on success. pub fn shutdown(hal: Hal) void { power.shutdown(hal); }