@@ -1477,6 +1477,241 @@ pub mod formats {
14771477 pub const ACPI_RSDP_FWCFG_NAME : & str = "etc/acpi/rsdp" ;
14781478
14791479 pub use crate :: firmware:: acpi:: { Dsdt , Facs , Fadt , Hpet , Madt , Mcfg , Rsdt , Rsdp , Xsdt } ;
1480+ use crate :: firmware:: acpi:: tables:: {
1481+ ACPI_PROCESSOR_ALL , ACPI_TABLE_CHECKSUM_OFF , FADT_OFF_DSDT32 ,
1482+ FADT_OFF_DSDT64 , FADT_OFF_FACS32 , GSI_SCI , GSI_TIMER , ISA_BUS ,
1483+ ISA_IRQ_SCI , ISA_IRQ_TIMER , LINT1 , MADT_INT_FLAGS_DEFAULT ,
1484+ MADT_INT_LEVEL_ACTIVE_HIGH , MADT_LAPIC_ENABLED , RSDP_CHECKSUM_OFFSET ,
1485+ RSDP_EXT_CHECKSUM_OFFSET , RSDP_SIZE , RSDP_V1_SIZE , RSDP_XSDT_ADDR_OFFSET ,
1486+ } ;
1487+
1488+ use std:: mem:: size_of;
1489+
1490+ pub struct AcpiConfig {
1491+ pub num_cpus : u8 ,
1492+ pub local_apic_addr : u32 ,
1493+ pub io_apic_id : u8 ,
1494+ pub io_apic_addr : u32 ,
1495+ pub pcie_ecam_base : u64 ,
1496+ pub pcie_ecam_size : u64 ,
1497+ pub pcie_bus_start : u8 ,
1498+ pub pcie_bus_end : u8 ,
1499+ pub pcie_mmio32_base : u64 ,
1500+ pub pcie_mmio32_limit : u64 ,
1501+ pub pcie_mmio64_base : u64 ,
1502+ pub pcie_mmio64_limit : u64 ,
1503+ }
1504+
1505+ impl Default for AcpiConfig {
1506+ fn default ( ) -> Self {
1507+ Self {
1508+ num_cpus : 1 ,
1509+ local_apic_addr : 0xfee0_0000 ,
1510+ io_apic_id : 0 ,
1511+ io_apic_addr : 0xfec0_0000 ,
1512+ pcie_ecam_base : 0xe000_0000 ,
1513+ pcie_ecam_size : 0x1000_0000 ,
1514+ pcie_bus_start : 0 ,
1515+ pcie_bus_end : 255 ,
1516+ pcie_mmio32_base : 0xc000_0000 ,
1517+ pcie_mmio32_limit : 0xfbff_ffff ,
1518+ pcie_mmio64_base : 0x1_0000_0000 ,
1519+ pcie_mmio64_limit : 0xf_ffff_ffff ,
1520+ }
1521+ }
1522+ }
1523+
1524+ pub struct AcpiTables {
1525+ pub tables : Vec < u8 > ,
1526+ pub rsdp : Vec < u8 > ,
1527+ pub loader : Vec < u8 > ,
1528+ }
1529+
1530+ pub fn build_acpi_tables (
1531+ config : & AcpiConfig ,
1532+ generators : & [ & dyn crate :: firmware:: acpi:: DsdtGenerator ] ,
1533+ ) -> AcpiTables {
1534+ use crate :: firmware:: acpi:: { build_dsdt_aml, DsdtConfig , PcieConfig } ;
1535+
1536+ let mut tables = Vec :: new ( ) ;
1537+ let mut loader = TableLoader :: new ( ) ;
1538+
1539+ let dsdt_config = DsdtConfig {
1540+ pcie : Some ( PcieConfig {
1541+ ecam_base : config. pcie_ecam_base ,
1542+ ecam_size : config. pcie_ecam_size ,
1543+ bus_start : config. pcie_bus_start ,
1544+ bus_end : config. pcie_bus_end ,
1545+ mmio32_base : config. pcie_mmio32_base ,
1546+ mmio32_limit : config. pcie_mmio32_limit ,
1547+ mmio64_base : config. pcie_mmio64_base ,
1548+ mmio64_limit : config. pcie_mmio64_limit ,
1549+ } ) ,
1550+ } ;
1551+ let aml = build_dsdt_aml ( & dsdt_config, generators) ;
1552+ let mut dsdt = Dsdt :: new ( ) ;
1553+ dsdt. append_aml ( & aml) ;
1554+ let dsdt_offset = tables. len ( ) ;
1555+ tables. extend_from_slice ( & dsdt. finish ( ) ) ;
1556+
1557+ let fadt = Fadt :: new ( ) ;
1558+ let fadt_offset = tables. len ( ) ;
1559+ tables. extend_from_slice ( & fadt. finish ( ) ) ;
1560+
1561+ let mut madt = Madt :: new ( config. local_apic_addr ) ;
1562+ for i in 0 ..config. num_cpus {
1563+ madt. add_local_apic ( i, i, MADT_LAPIC_ENABLED ) ;
1564+ }
1565+ madt. add_io_apic ( config. io_apic_id , config. io_apic_addr , 0 ) ;
1566+ madt. add_int_src_override ( ISA_BUS , ISA_IRQ_TIMER , GSI_TIMER , 0 ) ;
1567+ madt. add_int_src_override (
1568+ ISA_BUS ,
1569+ ISA_IRQ_SCI ,
1570+ GSI_SCI ,
1571+ MADT_INT_LEVEL_ACTIVE_HIGH ,
1572+ ) ;
1573+ madt. add_lapic_nmi ( ACPI_PROCESSOR_ALL , MADT_INT_FLAGS_DEFAULT , LINT1 ) ;
1574+ let madt_offset = tables. len ( ) ;
1575+ tables. extend_from_slice ( & madt. finish ( ) ) ;
1576+
1577+ let mut mcfg = Mcfg :: new ( ) ;
1578+ mcfg. add_allocation (
1579+ config. pcie_ecam_base ,
1580+ 0 ,
1581+ config. pcie_bus_start ,
1582+ config. pcie_bus_end ,
1583+ ) ;
1584+ let mcfg_offset = tables. len ( ) ;
1585+ tables. extend_from_slice ( & mcfg. finish ( ) ) ;
1586+
1587+ let hpet = Hpet :: new ( ) ;
1588+ let hpet_offset = tables. len ( ) ;
1589+ tables. extend_from_slice ( & hpet. finish ( ) ) ;
1590+
1591+ let mut xsdt = Xsdt :: new ( ) ;
1592+ let xsdt_fadt_off = xsdt. add_entry ( ) ;
1593+ let xsdt_madt_off = xsdt. add_entry ( ) ;
1594+ let xsdt_mcfg_off = xsdt. add_entry ( ) ;
1595+ let xsdt_hpet_off = xsdt. add_entry ( ) ;
1596+ let xsdt_offset = tables. len ( ) ;
1597+ tables. extend_from_slice ( & xsdt. finish ( ) ) ;
1598+
1599+ let facs = Facs :: new ( ) ;
1600+ let facs_offset = tables. len ( ) ;
1601+ tables. extend_from_slice ( & facs. finish ( ) ) ;
1602+
1603+ let rsdp_data = Rsdp :: new ( ) . finish ( ) ;
1604+
1605+ tables[ fadt_offset + FADT_OFF_FACS32
1606+ ..fadt_offset + FADT_OFF_FACS32 + size_of :: < u32 > ( ) ]
1607+ . copy_from_slice ( & ( facs_offset as u32 ) . to_le_bytes ( ) ) ;
1608+
1609+ tables[ fadt_offset + FADT_OFF_DSDT32
1610+ ..fadt_offset + FADT_OFF_DSDT32 + size_of :: < u32 > ( ) ]
1611+ . copy_from_slice ( & ( dsdt_offset as u32 ) . to_le_bytes ( ) ) ;
1612+ tables[ fadt_offset + FADT_OFF_DSDT64
1613+ ..fadt_offset + FADT_OFF_DSDT64 + size_of :: < u64 > ( ) ]
1614+ . copy_from_slice ( & ( dsdt_offset as u64 ) . to_le_bytes ( ) ) ;
1615+
1616+ let xsdt_entries = [
1617+ ( xsdt_fadt_off, fadt_offset) ,
1618+ ( xsdt_madt_off, madt_offset) ,
1619+ ( xsdt_mcfg_off, mcfg_offset) ,
1620+ ( xsdt_hpet_off, hpet_offset) ,
1621+ ] ;
1622+ for ( entry_off, table_offset) in xsdt_entries {
1623+ let off = xsdt_offset + entry_off as usize ;
1624+ tables[ off..off + size_of :: < u64 > ( ) ]
1625+ . copy_from_slice ( & ( table_offset as u64 ) . to_le_bytes ( ) ) ;
1626+ }
1627+
1628+ loader
1629+ . add_allocate ( ACPI_TABLES_FWCFG_NAME , 64 , AllocZone :: High )
1630+ . unwrap ( ) ;
1631+ loader. add_allocate ( ACPI_RSDP_FWCFG_NAME , 16 , AllocZone :: FSeg ) . unwrap ( ) ;
1632+
1633+ let table_pointers: & [ ( u32 , u8 ) ] = & [
1634+ (
1635+ fadt_offset as u32 + FADT_OFF_FACS32 as u32 ,
1636+ size_of :: < u32 > ( ) as u8 ,
1637+ ) ,
1638+ (
1639+ fadt_offset as u32 + FADT_OFF_DSDT32 as u32 ,
1640+ size_of :: < u32 > ( ) as u8 ,
1641+ ) ,
1642+ (
1643+ fadt_offset as u32 + FADT_OFF_DSDT64 as u32 ,
1644+ size_of :: < u64 > ( ) as u8 ,
1645+ ) ,
1646+ ( xsdt_offset as u32 + xsdt_fadt_off, size_of :: < u64 > ( ) as u8 ) ,
1647+ ( xsdt_offset as u32 + xsdt_madt_off, size_of :: < u64 > ( ) as u8 ) ,
1648+ ( xsdt_offset as u32 + xsdt_mcfg_off, size_of :: < u64 > ( ) as u8 ) ,
1649+ ( xsdt_offset as u32 + xsdt_hpet_off, size_of :: < u64 > ( ) as u8 ) ,
1650+ ] ;
1651+ for & ( offset, size) in table_pointers {
1652+ loader
1653+ . add_pointer (
1654+ ACPI_TABLES_FWCFG_NAME ,
1655+ ACPI_TABLES_FWCFG_NAME ,
1656+ offset,
1657+ size,
1658+ )
1659+ . unwrap ( ) ;
1660+ }
1661+
1662+ loader
1663+ . add_pointer (
1664+ ACPI_RSDP_FWCFG_NAME ,
1665+ ACPI_TABLES_FWCFG_NAME ,
1666+ RSDP_XSDT_ADDR_OFFSET as u32 ,
1667+ size_of :: < u64 > ( ) as u8 ,
1668+ )
1669+ . unwrap ( ) ;
1670+
1671+ let table_offsets = [
1672+ dsdt_offset,
1673+ fadt_offset,
1674+ madt_offset,
1675+ mcfg_offset,
1676+ hpet_offset,
1677+ xsdt_offset,
1678+ facs_offset,
1679+ ] ;
1680+ for pair in table_offsets. windows ( 2 ) {
1681+ let ( start, end) = ( pair[ 0 ] as u32 , pair[ 1 ] as u32 ) ;
1682+ loader
1683+ . add_checksum (
1684+ ACPI_TABLES_FWCFG_NAME ,
1685+ start + ACPI_TABLE_CHECKSUM_OFF as u32 ,
1686+ start,
1687+ end - start,
1688+ )
1689+ . unwrap ( ) ;
1690+ }
1691+
1692+ let rsdp_checksums = [
1693+ ( RSDP_CHECKSUM_OFFSET , RSDP_V1_SIZE ) ,
1694+ ( RSDP_EXT_CHECKSUM_OFFSET , RSDP_SIZE ) ,
1695+ ] ;
1696+ for ( checksum_off, length) in rsdp_checksums {
1697+ loader
1698+ . add_checksum (
1699+ ACPI_RSDP_FWCFG_NAME ,
1700+ checksum_off as u32 ,
1701+ 0 ,
1702+ length as u32 ,
1703+ )
1704+ . unwrap ( ) ;
1705+ }
1706+
1707+ let loader_entry = loader. finish ( ) ;
1708+ let loader_bytes = match loader_entry {
1709+ super :: Entry :: Bytes ( b) => b,
1710+ _ => unreachable ! ( ) ,
1711+ } ;
1712+
1713+ AcpiTables { tables, rsdp : rsdp_data, loader : loader_bytes }
1714+ }
14801715
14811716 #[ cfg( test) ]
14821717 mod test_table_loader {
0 commit comments