@@ -145,6 +145,43 @@ pub enum AcpiError {
145145 AllocError ,
146146}
147147
148+ macro_rules! read_root_table {
149+ ( $signature_name: ident, $address: ident, $acpi_handler: ident) => { {
150+ #[ repr( transparent) ]
151+ struct RootTable {
152+ header: SdtHeader ,
153+ }
154+
155+ unsafe impl AcpiTable for RootTable {
156+ const SIGNATURE : Signature = Signature :: $signature_name;
157+
158+ fn header( & self ) -> & SdtHeader {
159+ & self . header
160+ }
161+ }
162+
163+ // Map and validate root table
164+ // SAFETY: Addresses from a validated RSDP are also guaranteed to be valid.
165+ let table_mapping = unsafe { read_table:: <_, RootTable >( $acpi_handler. clone( ) , $address) } ?;
166+
167+ // Convert `table_mapping` to header mapping for storage
168+ // Avoid requesting table unmap twice (from both original and converted `table_mapping`s)
169+ let table_mapping = mem:: ManuallyDrop :: new( table_mapping) ;
170+ // SAFETY: `SdtHeader` is equivalent to `Sdt` memory-wise
171+ let table_mapping = unsafe {
172+ PhysicalMapping :: new(
173+ table_mapping. physical_start( ) ,
174+ table_mapping. virtual_start( ) . cast:: <SdtHeader >( ) ,
175+ table_mapping. region_length( ) ,
176+ table_mapping. mapped_length( ) ,
177+ $acpi_handler. clone( ) ,
178+ )
179+ } ;
180+
181+ table_mapping
182+ } } ;
183+ }
184+
148185/// Type capable of enumerating the existing ACPI tables on the system.
149186///
150187///
@@ -189,61 +226,44 @@ where
189226 ///
190227 /// ### Safety: Caller must ensure that the provided mapping is a fully validated RSDP.
191228 pub unsafe fn from_validated_rsdp ( handler : H , rsdp_mapping : PhysicalMapping < H , Rsdp > ) -> AcpiResult < Self > {
192- macro_rules! read_root_table {
193- ( $signature_name: ident, $address_getter: ident) => { {
194- #[ repr( transparent) ]
195- struct RootTable {
196- header: SdtHeader ,
197- }
198-
199- unsafe impl AcpiTable for RootTable {
200- const SIGNATURE : Signature = Signature :: $signature_name;
201-
202- fn header( & self ) -> & SdtHeader {
203- & self . header
204- }
205- }
229+ let revision = rsdp_mapping. revision ( ) ;
230+ let root_table_mapping = if revision == 0 {
231+ /*
232+ * We're running on ACPI Version 1.0. We should use the 32-bit RSDT address.
233+ */
234+ let table_phys_start = rsdp_mapping. rsdt_address ( ) as usize ;
235+ drop ( rsdp_mapping) ;
236+ read_root_table ! ( RSDT , table_phys_start, handler)
237+ } else {
238+ /*
239+ * We're running on ACPI Version 2.0+. We should use the 64-bit XSDT address, truncated
240+ * to 32 bits on x86.
241+ */
242+ let table_phys_start = rsdp_mapping. xsdt_address ( ) as usize ;
243+ drop ( rsdp_mapping) ;
244+ read_root_table ! ( XSDT , table_phys_start, handler)
245+ } ;
206246
207- // Unmap RSDP as soon as possible
208- let table_phys_start = rsdp_mapping. $address_getter( ) as usize ;
209- drop( rsdp_mapping) ;
210-
211- // Map and validate root table
212- // SAFETY: Addresses from a validated RSDP are also guaranteed to be valid.
213- let table_mapping = unsafe { read_table:: <_, RootTable >( handler. clone( ) , table_phys_start) } ?;
214-
215- // Convert `table_mapping` to header mapping for storage
216- // Avoid requesting table unmap twice (from both original and converted `table_mapping`s)
217- let table_mapping = mem:: ManuallyDrop :: new( table_mapping) ;
218- // SAFETY: `SdtHeader` is equivalent to `Sdt` memory-wise
219- let table_mapping = unsafe {
220- PhysicalMapping :: new(
221- table_mapping. physical_start( ) ,
222- table_mapping. virtual_start( ) . cast:: <SdtHeader >( ) ,
223- table_mapping. region_length( ) ,
224- table_mapping. mapped_length( ) ,
225- handler. clone( ) ,
226- )
227- } ;
228-
229- table_mapping
230- } } ;
231- }
247+ Ok ( Self { mapping : root_table_mapping, revision, handler } )
248+ }
232249
233- let revision = rsdp_mapping. revision ( ) ;
250+ /// Create an `AcpiTables` if you have the physical address of the RSDT/XSDT.
251+ ///
252+ /// ### Safety: Caller must ensure the provided address is valid RSDT/XSDT address.
253+ pub unsafe fn from_rsdt ( handler : H , revision : u8 , address : usize ) -> AcpiResult < Self > {
234254 let root_table_mapping = if revision == 0 {
235255 /*
236256 * We're running on ACPI Version 1.0. We should use the 32-bit RSDT address.
237257 */
238258
239- read_root_table ! ( RSDT , rsdt_address )
259+ read_root_table ! ( RSDT , address , handler )
240260 } else {
241261 /*
242262 * We're running on ACPI Version 2.0+. We should use the 64-bit XSDT address, truncated
243263 * to 32 bits on x86.
244264 */
245265
246- read_root_table ! ( XSDT , xsdt_address )
266+ read_root_table ! ( XSDT , address , handler )
247267 } ;
248268
249269 Ok ( Self { mapping : root_table_mapping, revision, handler } )
@@ -480,9 +500,7 @@ where
480500 log:: warn!( "Found invalid SDT at physical address {:p}: {:?}" , table_phys_ptr, r) ;
481501 continue ;
482502 }
483- let result = header_mapping. clone ( ) ;
484- drop ( header_mapping) ;
485- return Some ( result) ;
503+ return Some ( * header_mapping) ;
486504 }
487505 }
488506}
0 commit comments