@@ -1478,6 +1478,7 @@ pub mod formats {
14781478
14791479 pub const ACPI_TABLE_HEADER_SIZE : usize = 36 ;
14801480 const ACPI_TABLE_LENGTH_OFFSET : usize = 4 ;
1481+ pub const ACPI_TABLE_CHECKSUM_OFF : usize = 9 ;
14811482
14821483 #[ derive( Copy , Clone , IntoBytes , Immutable ) ]
14831484 #[ repr( C , packed) ]
@@ -1551,7 +1552,7 @@ pub mod formats {
15511552
15521553 pub fn add_entry ( & mut self ) -> u32 {
15531554 let offset = self . data . len ( ) as u32 ;
1554- self . data . extend_from_slice ( & [ 0u8 ; 8 ] ) ;
1555+ self . data . extend_from_slice ( & [ 0u8 ; size_of :: < u64 > ( ) ] ) ;
15551556 offset
15561557 }
15571558
@@ -2004,6 +2005,238 @@ pub mod formats {
20042005 }
20052006 }
20062007
2008+ pub struct AcpiConfig {
2009+ pub num_cpus : u8 ,
2010+ pub local_apic_addr : u32 ,
2011+ pub io_apic_id : u8 ,
2012+ pub io_apic_addr : u32 ,
2013+ pub pcie_ecam_base : u64 ,
2014+ pub pcie_ecam_size : u64 ,
2015+ pub pcie_bus_start : u8 ,
2016+ pub pcie_bus_end : u8 ,
2017+ pub pcie_mmio32_base : u64 ,
2018+ pub pcie_mmio32_limit : u64 ,
2019+ pub pcie_mmio64_base : u64 ,
2020+ pub pcie_mmio64_limit : u64 ,
2021+ pub com_ports : Vec < ( u16 , u8 ) > ,
2022+ }
2023+
2024+ impl Default for AcpiConfig {
2025+ fn default ( ) -> Self {
2026+ Self {
2027+ num_cpus : 1 ,
2028+ local_apic_addr : 0xfee0_0000 ,
2029+ io_apic_id : 0 ,
2030+ io_apic_addr : 0xfec0_0000 ,
2031+ pcie_ecam_base : 0xe000_0000 ,
2032+ pcie_ecam_size : 0x1000_0000 ,
2033+ pcie_bus_start : 0 ,
2034+ pcie_bus_end : 255 ,
2035+ pcie_mmio32_base : 0xc000_0000 ,
2036+ pcie_mmio32_limit : 0xfbff_ffff ,
2037+ pcie_mmio64_base : 0x1_0000_0000 ,
2038+ pcie_mmio64_limit : 0xf_ffff_ffff ,
2039+ com_ports : Vec :: new ( ) ,
2040+ }
2041+ }
2042+ }
2043+
2044+ pub struct AcpiTables {
2045+ pub tables : Vec < u8 > ,
2046+ pub rsdp : Vec < u8 > ,
2047+ pub loader : Vec < u8 > ,
2048+ }
2049+
2050+ pub fn build_acpi_tables ( config : & AcpiConfig ) -> AcpiTables {
2051+ use crate :: firmware:: acpi:: {
2052+ build_dsdt_aml, ComPortConfig , DsdtConfig , PcieConfig ,
2053+ } ;
2054+
2055+ let mut tables = Vec :: new ( ) ;
2056+ let mut loader = TableLoader :: new ( ) ;
2057+
2058+ let dsdt_config = DsdtConfig {
2059+ pcie : Some ( PcieConfig {
2060+ ecam_base : config. pcie_ecam_base ,
2061+ ecam_size : config. pcie_ecam_size ,
2062+ bus_start : config. pcie_bus_start ,
2063+ bus_end : config. pcie_bus_end ,
2064+ mmio32_base : config. pcie_mmio32_base ,
2065+ mmio32_limit : config. pcie_mmio32_limit ,
2066+ mmio64_base : config. pcie_mmio64_base ,
2067+ mmio64_limit : config. pcie_mmio64_limit ,
2068+ } ) ,
2069+ com_ports : config
2070+ . com_ports
2071+ . iter ( )
2072+ . map ( |& ( io_base, irq) | ComPortConfig { io_base, irq } )
2073+ . collect ( ) ,
2074+ } ;
2075+ let aml = build_dsdt_aml ( & dsdt_config) ;
2076+ let mut dsdt = Dsdt :: new ( ) ;
2077+ dsdt. append_aml ( & aml) ;
2078+ let dsdt_offset = tables. len ( ) ;
2079+ tables. extend_from_slice ( & dsdt. finish ( ) ) ;
2080+
2081+ let fadt = Fadt :: new ( ) ;
2082+ let fadt_offset = tables. len ( ) ;
2083+ tables. extend_from_slice ( & fadt. finish ( ) ) ;
2084+
2085+ let mut madt = Madt :: new ( config. local_apic_addr ) ;
2086+ for i in 0 ..config. num_cpus {
2087+ madt. add_local_apic ( i, i, MADT_LAPIC_ENABLED ) ;
2088+ }
2089+ madt. add_io_apic ( config. io_apic_id , config. io_apic_addr , 0 ) ;
2090+ madt. add_int_src_override ( ISA_BUS , ISA_IRQ_TIMER , GSI_TIMER , 0 ) ;
2091+ madt. add_int_src_override (
2092+ ISA_BUS ,
2093+ ISA_IRQ_SCI ,
2094+ GSI_SCI ,
2095+ MADT_INT_LEVEL_ACTIVE_HIGH ,
2096+ ) ;
2097+ madt. add_lapic_nmi ( ACPI_PROCESSOR_ALL , MADT_INT_FLAGS_DEFAULT , LINT1 ) ;
2098+ let madt_offset = tables. len ( ) ;
2099+ tables. extend_from_slice ( & madt. finish ( ) ) ;
2100+
2101+ let mut mcfg = Mcfg :: new ( ) ;
2102+ mcfg. add_allocation (
2103+ config. pcie_ecam_base ,
2104+ 0 ,
2105+ config. pcie_bus_start ,
2106+ config. pcie_bus_end ,
2107+ ) ;
2108+ let mcfg_offset = tables. len ( ) ;
2109+ tables. extend_from_slice ( & mcfg. finish ( ) ) ;
2110+
2111+ let hpet = Hpet :: new ( ) ;
2112+ let hpet_offset = tables. len ( ) ;
2113+ tables. extend_from_slice ( & hpet. finish ( ) ) ;
2114+
2115+ let mut xsdt = Xsdt :: new ( ) ;
2116+ let xsdt_fadt_off = xsdt. add_entry ( ) ;
2117+ let xsdt_madt_off = xsdt. add_entry ( ) ;
2118+ let xsdt_mcfg_off = xsdt. add_entry ( ) ;
2119+ let xsdt_hpet_off = xsdt. add_entry ( ) ;
2120+ let xsdt_offset = tables. len ( ) ;
2121+ tables. extend_from_slice ( & xsdt. finish ( ) ) ;
2122+
2123+ let facs = Facs :: new ( ) ;
2124+ let facs_offset = tables. len ( ) ;
2125+ tables. extend_from_slice ( & facs. finish ( ) ) ;
2126+
2127+ let rsdp_data = Rsdp :: new ( ) . finish ( ) ;
2128+
2129+ tables[ fadt_offset + FADT_OFF_FACS32
2130+ ..fadt_offset + FADT_OFF_FACS32 + size_of :: < u32 > ( ) ]
2131+ . copy_from_slice ( & ( facs_offset as u32 ) . to_le_bytes ( ) ) ;
2132+
2133+ tables[ fadt_offset + FADT_OFF_DSDT32
2134+ ..fadt_offset + FADT_OFF_DSDT32 + size_of :: < u32 > ( ) ]
2135+ . copy_from_slice ( & ( dsdt_offset as u32 ) . to_le_bytes ( ) ) ;
2136+ tables[ fadt_offset + FADT_OFF_DSDT64
2137+ ..fadt_offset + FADT_OFF_DSDT64 + size_of :: < u64 > ( ) ]
2138+ . copy_from_slice ( & ( dsdt_offset as u64 ) . to_le_bytes ( ) ) ;
2139+
2140+ let xsdt_entries = [
2141+ ( xsdt_fadt_off, fadt_offset) ,
2142+ ( xsdt_madt_off, madt_offset) ,
2143+ ( xsdt_mcfg_off, mcfg_offset) ,
2144+ ( xsdt_hpet_off, hpet_offset) ,
2145+ ] ;
2146+ for ( entry_off, table_offset) in xsdt_entries {
2147+ let off = xsdt_offset + entry_off as usize ;
2148+ tables[ off..off + size_of :: < u64 > ( ) ]
2149+ . copy_from_slice ( & ( table_offset as u64 ) . to_le_bytes ( ) ) ;
2150+ }
2151+
2152+ loader
2153+ . add_allocate ( ACPI_TABLES_FWCFG_NAME , 64 , AllocZone :: High )
2154+ . unwrap ( ) ;
2155+ loader. add_allocate ( ACPI_RSDP_FWCFG_NAME , 16 , AllocZone :: FSeg ) . unwrap ( ) ;
2156+
2157+ let table_pointers: & [ ( u32 , u8 ) ] = & [
2158+ (
2159+ fadt_offset as u32 + FADT_OFF_FACS32 as u32 ,
2160+ size_of :: < u32 > ( ) as u8 ,
2161+ ) ,
2162+ (
2163+ fadt_offset as u32 + FADT_OFF_DSDT32 as u32 ,
2164+ size_of :: < u32 > ( ) as u8 ,
2165+ ) ,
2166+ (
2167+ fadt_offset as u32 + FADT_OFF_DSDT64 as u32 ,
2168+ size_of :: < u64 > ( ) as u8 ,
2169+ ) ,
2170+ ( xsdt_offset as u32 + xsdt_fadt_off, size_of :: < u64 > ( ) as u8 ) ,
2171+ ( xsdt_offset as u32 + xsdt_madt_off, size_of :: < u64 > ( ) as u8 ) ,
2172+ ( xsdt_offset as u32 + xsdt_mcfg_off, size_of :: < u64 > ( ) as u8 ) ,
2173+ ( xsdt_offset as u32 + xsdt_hpet_off, size_of :: < u64 > ( ) as u8 ) ,
2174+ ] ;
2175+ for & ( offset, size) in table_pointers {
2176+ loader
2177+ . add_pointer (
2178+ ACPI_TABLES_FWCFG_NAME ,
2179+ ACPI_TABLES_FWCFG_NAME ,
2180+ offset,
2181+ size,
2182+ )
2183+ . unwrap ( ) ;
2184+ }
2185+
2186+ loader
2187+ . add_pointer (
2188+ ACPI_RSDP_FWCFG_NAME ,
2189+ ACPI_TABLES_FWCFG_NAME ,
2190+ RSDP_XSDT_ADDR_OFFSET as u32 ,
2191+ size_of :: < u64 > ( ) as u8 ,
2192+ )
2193+ . unwrap ( ) ;
2194+
2195+ let table_offsets = [
2196+ dsdt_offset,
2197+ fadt_offset,
2198+ madt_offset,
2199+ mcfg_offset,
2200+ hpet_offset,
2201+ xsdt_offset,
2202+ facs_offset,
2203+ ] ;
2204+ for pair in table_offsets. windows ( 2 ) {
2205+ let ( start, end) = ( pair[ 0 ] as u32 , pair[ 1 ] as u32 ) ;
2206+ loader
2207+ . add_checksum (
2208+ ACPI_TABLES_FWCFG_NAME ,
2209+ start + ACPI_TABLE_CHECKSUM_OFF as u32 ,
2210+ start,
2211+ end - start,
2212+ )
2213+ . unwrap ( ) ;
2214+ }
2215+
2216+ let rsdp_checksums = [
2217+ ( RSDP_CHECKSUM_OFFSET , RSDP_V1_SIZE ) ,
2218+ ( RSDP_EXT_CHECKSUM_OFFSET , RSDP_SIZE ) ,
2219+ ] ;
2220+ for ( checksum_off, length) in rsdp_checksums {
2221+ loader
2222+ . add_checksum (
2223+ ACPI_RSDP_FWCFG_NAME ,
2224+ checksum_off as u32 ,
2225+ 0 ,
2226+ length as u32 ,
2227+ )
2228+ . unwrap ( ) ;
2229+ }
2230+
2231+ let loader_entry = loader. finish ( ) ;
2232+ let loader_bytes = match loader_entry {
2233+ super :: Entry :: Bytes ( b) => b,
2234+ _ => unreachable ! ( ) ,
2235+ } ;
2236+
2237+ AcpiTables { tables, rsdp : rsdp_data, loader : loader_bytes }
2238+ }
2239+
20072240 #[ cfg( test) ]
20082241 mod test_table_loader {
20092242 use super :: * ;
0 commit comments