@@ -367,6 +367,43 @@ where
367367 SsdtIterator { tables_phys_ptrs : self . tables_phys_ptrs ( ) , handler : self . handler . clone ( ) }
368368 }
369369
370+ /// Add a new SSDT to the list of tables.
371+ /// Sould edit the XSDT or RSDT to include the new table.
372+ /// Safety: The address must be valid for reading as an SSDT. And must match the revision of the tables.
373+ /// The address must be 8-byte aligned and the 8-byte after xsdt must be not used.
374+ pub unsafe fn add_ssdt ( & mut self , address : usize ) -> AcpiResult < ( ) > {
375+ #[ repr( transparent) ]
376+ struct Xsdt {
377+ header : SdtHeader ,
378+ }
379+
380+ unsafe impl AcpiTable for Xsdt {
381+ const SIGNATURE : Signature = Signature :: XSDT ;
382+
383+ fn header ( & self ) -> & SdtHeader {
384+ & self . header
385+ }
386+ }
387+
388+ let mut xsdt =
389+ unsafe { read_table :: < H , Xsdt > ( self . handler . clone ( ) , self . mapping . physical_start ( ) ) . unwrap ( ) } ;
390+
391+ xsdt. write :: < u64 > ( xsdt. header . length as usize , address as u64 ) ;
392+
393+ xsdt. write :: < u32 > ( 4 , xsdt. header . length + 8 ) ; // length of the table
394+ xsdt. write :: < u8 > ( 9 , 0 ) ; // checksum
395+ let mut sum = 0u8 ;
396+ for i in 0 ..xsdt. header . length as usize {
397+ sum = sum. wrapping_add ( xsdt. read :: < u8 > ( i) ) ;
398+ }
399+ xsdt. write :: < u8 > ( 9 , ( !sum) . wrapping_add ( 1 ) ) ; // checksum
400+
401+ let address = xsdt. physical_start ( ) ;
402+ let handler = xsdt. handler ( ) . clone ( ) ;
403+ self . mapping = read_root_table ! ( XSDT , address, handler) ;
404+ Ok ( ( ) )
405+ }
406+
370407 /// Convenience method for contructing a [`PlatformInfo`](crate::platform::PlatformInfo). This is one of the
371408 /// first things you should usually do with an `AcpiTables`, and allows to collect helpful information about
372409 /// the platform from the ACPI tables.
0 commit comments