@@ -145,6 +145,43 @@ pub enum AcpiError {
145
145
AllocError ,
146
146
}
147
147
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
+
148
185
/// Type capable of enumerating the existing ACPI tables on the system.
149
186
///
150
187
///
@@ -189,61 +226,44 @@ where
189
226
///
190
227
/// ### Safety: Caller must ensure that the provided mapping is a fully validated RSDP.
191
228
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
+ } ;
206
246
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
+ }
232
249
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 > {
234
254
let root_table_mapping = if revision == 0 {
235
255
/*
236
256
* We're running on ACPI Version 1.0. We should use the 32-bit RSDT address.
237
257
*/
238
258
239
- read_root_table ! ( RSDT , rsdt_address )
259
+ read_root_table ! ( RSDT , address , handler )
240
260
} else {
241
261
/*
242
262
* We're running on ACPI Version 2.0+. We should use the 64-bit XSDT address, truncated
243
263
* to 32 bits on x86.
244
264
*/
245
265
246
- read_root_table ! ( XSDT , xsdt_address )
266
+ read_root_table ! ( XSDT , address , handler )
247
267
} ;
248
268
249
269
Ok ( Self { mapping : root_table_mapping, revision, handler } )
@@ -480,9 +500,7 @@ where
480
500
log:: warn!( "Found invalid SDT at physical address {:p}: {:?}" , table_phys_ptr, r) ;
481
501
continue ;
482
502
}
483
- let result = header_mapping. clone ( ) ;
484
- drop ( header_mapping) ;
485
- return Some ( result) ;
503
+ return Some ( * header_mapping) ;
486
504
}
487
505
}
488
506
}
0 commit comments