@@ -149,6 +149,43 @@ pub enum AcpiError {
149
149
AllocError ,
150
150
}
151
151
152
+ macro_rules! read_root_table {
153
+ ( $signature_name: ident, $address: ident, $acpi_handler: ident) => { {
154
+ #[ repr( transparent) ]
155
+ struct RootTable {
156
+ header: SdtHeader ,
157
+ }
158
+
159
+ unsafe impl AcpiTable for RootTable {
160
+ const SIGNATURE : Signature = Signature :: $signature_name;
161
+
162
+ fn header( & self ) -> & SdtHeader {
163
+ & self . header
164
+ }
165
+ }
166
+
167
+ // Map and validate root table
168
+ // SAFETY: Addresses from a validated RSDP are also guaranteed to be valid.
169
+ let table_mapping = unsafe { read_table:: <_, RootTable >( $acpi_handler. clone( ) , $address) } ?;
170
+
171
+ // Convert `table_mapping` to header mapping for storage
172
+ // Avoid requesting table unmap twice (from both original and converted `table_mapping`s)
173
+ let table_mapping = mem:: ManuallyDrop :: new( table_mapping) ;
174
+ // SAFETY: `SdtHeader` is equivalent to `Sdt` memory-wise
175
+ let table_mapping = unsafe {
176
+ PhysicalMapping :: new(
177
+ table_mapping. physical_start( ) ,
178
+ table_mapping. virtual_start( ) . cast:: <SdtHeader >( ) ,
179
+ table_mapping. region_length( ) ,
180
+ table_mapping. mapped_length( ) ,
181
+ $acpi_handler. clone( ) ,
182
+ )
183
+ } ;
184
+
185
+ table_mapping
186
+ } } ;
187
+ }
188
+
152
189
/// Type capable of enumerating the existing ACPI tables on the system.
153
190
///
154
191
///
@@ -199,61 +236,44 @@ where
199
236
///
200
237
/// ### Safety: Caller must ensure that the provided mapping is a fully validated RSDP.
201
238
pub unsafe fn from_validated_rsdp ( handler : H , rsdp_mapping : PhysicalMapping < H , Rsdp > ) -> AcpiResult < Self > {
202
- macro_rules! read_root_table {
203
- ( $signature_name: ident, $address_getter: ident) => { {
204
- #[ repr( transparent) ]
205
- struct RootTable {
206
- header: SdtHeader ,
207
- }
208
-
209
- unsafe impl AcpiTable for RootTable {
210
- const SIGNATURE : Signature = Signature :: $signature_name;
211
-
212
- fn header( & self ) -> & SdtHeader {
213
- & self . header
214
- }
215
- }
239
+ let revision = rsdp_mapping. revision ( ) ;
240
+ let root_table_mapping = if revision == 0 {
241
+ /*
242
+ * We're running on ACPI Version 1.0. We should use the 32-bit RSDT address.
243
+ */
244
+ let table_phys_start = rsdp_mapping. rsdt_address ( ) as usize ;
245
+ drop ( rsdp_mapping) ;
246
+ read_root_table ! ( RSDT , table_phys_start, handler)
247
+ } else {
248
+ /*
249
+ * We're running on ACPI Version 2.0+. We should use the 64-bit XSDT address, truncated
250
+ * to 32 bits on x86.
251
+ */
252
+ let table_phys_start = rsdp_mapping. xsdt_address ( ) as usize ;
253
+ drop ( rsdp_mapping) ;
254
+ read_root_table ! ( XSDT , table_phys_start, handler)
255
+ } ;
216
256
217
- // Unmap RSDP as soon as possible
218
- let table_phys_start = rsdp_mapping. $address_getter( ) as usize ;
219
- drop( rsdp_mapping) ;
220
-
221
- // Map and validate root table
222
- // SAFETY: Addresses from a validated RSDP are also guaranteed to be valid.
223
- let table_mapping = unsafe { read_table:: <_, RootTable >( handler. clone( ) , table_phys_start) } ?;
224
-
225
- // Convert `table_mapping` to header mapping for storage
226
- // Avoid requesting table unmap twice (from both original and converted `table_mapping`s)
227
- let table_mapping = mem:: ManuallyDrop :: new( table_mapping) ;
228
- // SAFETY: `SdtHeader` is equivalent to `Sdt` memory-wise
229
- let table_mapping = unsafe {
230
- PhysicalMapping :: new(
231
- table_mapping. physical_start( ) ,
232
- table_mapping. virtual_start( ) . cast:: <SdtHeader >( ) ,
233
- table_mapping. region_length( ) ,
234
- table_mapping. mapped_length( ) ,
235
- handler. clone( ) ,
236
- )
237
- } ;
238
-
239
- table_mapping
240
- } } ;
241
- }
257
+ Ok ( Self { mapping : root_table_mapping, revision, handler } )
258
+ }
242
259
243
- let revision = rsdp_mapping. revision ( ) ;
260
+ /// Create an `AcpiTables` if you have the physical address of the RSDT/XSDT.
261
+ ///
262
+ /// ### Safety: Caller must ensure the provided address is valid RSDT/XSDT address.
263
+ pub unsafe fn from_rsdt ( handler : H , revision : u8 , address : usize ) -> AcpiResult < Self > {
244
264
let root_table_mapping = if revision == 0 {
245
265
/*
246
266
* We're running on ACPI Version 1.0. We should use the 32-bit RSDT address.
247
267
*/
248
268
249
- read_root_table ! ( RSDT , rsdt_address )
269
+ read_root_table ! ( RSDT , address , handler )
250
270
} else {
251
271
/*
252
272
* We're running on ACPI Version 2.0+. We should use the 64-bit XSDT address, truncated
253
273
* to 32 bits on x86.
254
274
*/
255
275
256
- read_root_table ! ( XSDT , xsdt_address )
276
+ read_root_table ! ( XSDT , address , handler )
257
277
} ;
258
278
259
279
Ok ( Self { mapping : root_table_mapping, revision, handler } )
@@ -490,9 +510,7 @@ where
490
510
log:: warn!( "Found invalid SDT at physical address {:p}: {:?}" , table_phys_ptr, r) ;
491
511
continue ;
492
512
}
493
- let result = header_mapping. clone ( ) ;
494
- drop ( header_mapping) ;
495
- return Some ( result) ;
513
+ return Some ( * header_mapping) ;
496
514
}
497
515
}
498
516
}
0 commit comments