@@ -233,38 +233,71 @@ impl Debug for BasicMemoryInfoTag {
233
233
}
234
234
}
235
235
236
+ const EFI_METADATA_SIZE : usize = mem:: size_of :: < TagTypeId > ( ) + 3 * mem:: size_of :: < u32 > ( ) ;
237
+
236
238
/// EFI memory map as per EFI specification.
237
- #[ derive( Debug ) ]
239
+ #[ derive( Debug , ptr_meta :: Pointee ) ]
238
240
#[ repr( C ) ]
239
241
pub struct EFIMemoryMapTag {
240
242
typ : TagTypeId ,
241
243
size : u32 ,
242
244
desc_size : u32 ,
243
245
desc_version : u32 ,
244
- first_desc : [ EFIMemoryDesc ; 0 ] ,
246
+ descs : [ EFIMemoryDesc ] ,
245
247
}
246
248
247
249
impl EFIMemoryMapTag {
250
+ #[ cfg( feature = "builder" ) ]
251
+ /// Create a new EFI memory map tag with the given memory descriptors.
252
+ /// Version and size can't be set because you're passing a slice of
253
+ /// EFIMemoryDescs, not the ones you might have gotten from the firmware.
254
+ pub fn new ( descs : & [ EFIMemoryDesc ] ) -> Box < Self > {
255
+ // update this when updating EFIMemoryDesc
256
+ const MEMORY_DESCRIPTOR_VERSION : u32 = 1 ;
257
+ let mut bytes = [
258
+ ( mem:: size_of :: < EFIMemoryDesc > ( ) as u32 ) . to_le_bytes ( ) ,
259
+ MEMORY_DESCRIPTOR_VERSION . to_le_bytes ( ) ,
260
+ ]
261
+ . concat ( ) ;
262
+ for desc in descs {
263
+ bytes. extend ( desc. struct_as_bytes ( ) ) ;
264
+ }
265
+ boxed_dst_tag ( TagType :: EfiMmap , bytes. as_slice ( ) )
266
+ }
267
+
248
268
/// Return an iterator over ALL marked memory areas.
249
269
///
250
270
/// This differs from `MemoryMapTag` as for UEFI, the OS needs some non-
251
271
/// available memory areas for tables and such.
252
272
pub fn memory_areas ( & self ) -> EFIMemoryAreaIter {
253
273
let self_ptr = self as * const EFIMemoryMapTag ;
254
- let start_area = self . first_desc . as_ptr ( ) ;
274
+ let start_area = ( & self . descs [ 0 ] ) as * const EFIMemoryDesc ;
255
275
EFIMemoryAreaIter {
256
276
current_area : start_area as u64 ,
257
277
// NOTE: `last_area` is only a bound, it doesn't necessarily point exactly to the last element
258
- last_area : ( self_ptr as u64
259
- + ( self . size as u64 - core:: mem:: size_of :: < EFIMemoryMapTag > ( ) as u64 ) ) ,
278
+ last_area : ( self_ptr as * const ( ) as u64 + self . size as u64 ) ,
260
279
entry_size : self . desc_size ,
261
280
phantom : PhantomData ,
262
281
}
263
282
}
264
283
}
265
284
285
+ impl TagTrait for EFIMemoryMapTag {
286
+ fn dst_size ( base_tag : & Tag ) -> usize {
287
+ assert ! ( base_tag. size as usize >= EFI_METADATA_SIZE ) ;
288
+ base_tag. size as usize - EFI_METADATA_SIZE
289
+ }
290
+ }
291
+
292
+ #[ cfg( feature = "builder" ) ]
293
+ impl StructAsBytes for EFIMemoryMapTag {
294
+ fn byte_size ( & self ) -> usize {
295
+ self . size . try_into ( ) . unwrap ( )
296
+ }
297
+ }
298
+
266
299
/// EFI Boot Memory Map Descriptor
267
- #[ derive( Debug ) ]
300
+ #[ derive( Debug , Clone ) ]
268
301
#[ repr( C ) ]
269
302
pub struct EFIMemoryDesc {
270
303
typ : u32 ,
@@ -275,6 +308,13 @@ pub struct EFIMemoryDesc {
275
308
attr : u64 ,
276
309
}
277
310
311
+ #[ cfg( feature = "builder" ) ]
312
+ impl StructAsBytes for EFIMemoryDesc {
313
+ fn byte_size ( & self ) -> usize {
314
+ mem:: size_of :: < Self > ( )
315
+ }
316
+ }
317
+
278
318
/// An enum of possible reported region types.
279
319
#[ derive( Debug , PartialEq , Eq ) ]
280
320
pub enum EFIMemoryAreaType {
@@ -329,6 +369,29 @@ pub enum EFIMemoryAreaType {
329
369
EfiUnknown ,
330
370
}
331
371
372
+ impl From < EFIMemoryAreaType > for u32 {
373
+ fn from ( area : EFIMemoryAreaType ) -> Self {
374
+ match area {
375
+ EFIMemoryAreaType :: EfiReservedMemoryType => 0 ,
376
+ EFIMemoryAreaType :: EfiLoaderCode => 1 ,
377
+ EFIMemoryAreaType :: EfiLoaderData => 2 ,
378
+ EFIMemoryAreaType :: EfiBootServicesCode => 3 ,
379
+ EFIMemoryAreaType :: EfiBootServicesData => 4 ,
380
+ EFIMemoryAreaType :: EfiRuntimeServicesCode => 5 ,
381
+ EFIMemoryAreaType :: EfiRuntimeServicesData => 6 ,
382
+ EFIMemoryAreaType :: EfiConventionalMemory => 7 ,
383
+ EFIMemoryAreaType :: EfiUnusableMemory => 8 ,
384
+ EFIMemoryAreaType :: EfiACPIReclaimMemory => 9 ,
385
+ EFIMemoryAreaType :: EfiACPIMemoryNVS => 10 ,
386
+ EFIMemoryAreaType :: EfiMemoryMappedIO => 11 ,
387
+ EFIMemoryAreaType :: EfiMemoryMappedIOPortSpace => 12 ,
388
+ EFIMemoryAreaType :: EfiPalCode => 13 ,
389
+ EFIMemoryAreaType :: EfiPersistentMemory => 14 ,
390
+ EFIMemoryAreaType :: EfiUnknown => panic ! ( "unknown type" ) ,
391
+ }
392
+ }
393
+ }
394
+
332
395
impl EFIMemoryDesc {
333
396
/// The physical address of the memory region.
334
397
pub fn physical_address ( & self ) -> u64 {
@@ -369,6 +432,19 @@ impl EFIMemoryDesc {
369
432
}
370
433
}
371
434
435
+ impl Default for EFIMemoryDesc {
436
+ fn default ( ) -> Self {
437
+ Self {
438
+ typ : EFIMemoryAreaType :: EfiReservedMemoryType . into ( ) ,
439
+ _padding : 0 ,
440
+ phys_addr : 0 ,
441
+ virt_addr : 0 ,
442
+ num_pages : 0 ,
443
+ attr : 0 ,
444
+ }
445
+ }
446
+ }
447
+
372
448
/// EFI ExitBootServices was not called
373
449
#[ derive( Debug ) ]
374
450
#[ repr( C ) ]
0 commit comments