@@ -271,30 +271,72 @@ pub struct EFIMemoryMapTag {
271
271
size : u32 ,
272
272
desc_size : u32 ,
273
273
desc_version : u32 ,
274
- first_desc : [ EFIMemoryDesc ; 0 ] ,
274
+ descs : [ EFIMemoryDesc ] ,
275
275
}
276
276
277
277
impl EFIMemoryMapTag {
278
+ #[ cfg( feature = "builder" ) ]
279
+ /// Create a new EFI memory map tag with the given memory descriptors.
280
+ /// Version and size can't be set because you're passing a slice of
281
+ /// EFIMemoryDescs, not the ones you might have gotten from the firmware.
282
+ pub fn new ( descs : & [ EFIMemoryDesc ] ) -> Box < Self > {
283
+ // update this when updating EFIMemoryDesc
284
+ const MEMORY_DESCRIPTOR_VERSION : u32 = 1 ;
285
+ let mut bytes = [
286
+ ( mem:: size_of :: < EFIMemoryDesc > ( ) as u32 ) . to_le_bytes ( ) ,
287
+ MEMORY_DESCRIPTOR_VERSION . to_le_bytes ( ) ,
288
+ ]
289
+ . concat ( ) ;
290
+ for desc in descs {
291
+ bytes. extend ( desc. struct_as_bytes ( ) ) ;
292
+ }
293
+ let tag = boxed_dst_tag ( TagType :: EfiMmap . into ( ) , bytes. as_slice ( ) ) ;
294
+ unsafe { Box :: from_raw ( Box :: into_raw ( tag) as * mut Self ) }
295
+ }
296
+
278
297
/// Return an iterator over ALL marked memory areas.
279
298
///
280
299
/// This differs from `MemoryMapTag` as for UEFI, the OS needs some non-
281
300
/// available memory areas for tables and such.
282
301
pub fn memory_areas ( & self ) -> EFIMemoryAreaIter {
283
302
let self_ptr = self as * const EFIMemoryMapTag ;
284
- let start_area = self . first_desc . as_ptr ( ) ;
303
+ let start_area = ( & self . descs [ 0 ] ) as * const EFIMemoryDesc ;
285
304
EFIMemoryAreaIter {
286
305
current_area : start_area as u64 ,
287
306
// NOTE: `last_area` is only a bound, it doesn't necessarily point exactly to the last element
288
- last_area : ( self_ptr as u64
289
- + ( self . size as u64 - core:: mem:: size_of :: < EFIMemoryMapTag > ( ) as u64 ) ) ,
307
+ last_area : ( self_ptr as * const ( ) as u64 + self . size as u64 ) ,
308
+ entry_size : self . desc_size ,
309
+ phantom : PhantomData ,
310
+ }
311
+ }
312
+
313
+ #[ cfg( feature = "builder" ) ]
314
+ /// Return an iterator over ALL marked memory areas, mutably.
315
+ ///
316
+ /// This differs from `MemoryMapTag` as for UEFI, the OS needs some non-
317
+ /// available memory areas for tables and such.
318
+ pub fn memory_areas_mut ( & mut self ) -> EFIMemoryAreaIterMut {
319
+ let self_ptr = self as * const EFIMemoryMapTag ;
320
+ let start_area = ( & self . descs [ 0 ] ) as * const EFIMemoryDesc ;
321
+ EFIMemoryAreaIterMut {
322
+ current_area : start_area as u64 ,
323
+ // NOTE: `last_area` is only a bound, it doesn't necessarily point exactly to the last element
324
+ last_area : ( self_ptr as * const ( ) as u64 + self . size as u64 ) ,
290
325
entry_size : self . desc_size ,
291
326
phantom : PhantomData ,
292
327
}
293
328
}
294
329
}
295
330
331
+ #[ cfg( feature = "builder" ) ]
332
+ impl StructAsBytes for EFIMemoryMapTag {
333
+ fn byte_size ( & self ) -> usize {
334
+ self . size . try_into ( ) . unwrap ( )
335
+ }
336
+ }
337
+
296
338
/// EFI Boot Memory Map Descriptor
297
- #[ derive( Debug ) ]
339
+ #[ derive( Debug , Clone ) ]
298
340
#[ repr( C ) ]
299
341
pub struct EFIMemoryDesc {
300
342
typ : u32 ,
@@ -305,6 +347,13 @@ pub struct EFIMemoryDesc {
305
347
attr : u64 ,
306
348
}
307
349
350
+ #[ cfg( feature = "builder" ) ]
351
+ impl StructAsBytes for EFIMemoryDesc {
352
+ fn byte_size ( & self ) -> usize {
353
+ mem:: size_of :: < Self > ( )
354
+ }
355
+ }
356
+
308
357
/// An enum of possible reported region types.
309
358
#[ derive( Debug , PartialEq , Eq ) ]
310
359
pub enum EFIMemoryAreaType {
@@ -359,6 +408,29 @@ pub enum EFIMemoryAreaType {
359
408
EfiUnknown ,
360
409
}
361
410
411
+ impl From < EFIMemoryAreaType > for u32 {
412
+ fn from ( area : EFIMemoryAreaType ) -> Self {
413
+ match area {
414
+ EFIMemoryAreaType :: EfiReservedMemoryType => 0 ,
415
+ EFIMemoryAreaType :: EfiLoaderCode => 1 ,
416
+ EFIMemoryAreaType :: EfiLoaderData => 2 ,
417
+ EFIMemoryAreaType :: EfiBootServicesCode => 3 ,
418
+ EFIMemoryAreaType :: EfiBootServicesData => 4 ,
419
+ EFIMemoryAreaType :: EfiRuntimeServicesCode => 5 ,
420
+ EFIMemoryAreaType :: EfiRuntimeServicesData => 6 ,
421
+ EFIMemoryAreaType :: EfiConventionalMemory => 7 ,
422
+ EFIMemoryAreaType :: EfiUnusableMemory => 8 ,
423
+ EFIMemoryAreaType :: EfiACPIReclaimMemory => 9 ,
424
+ EFIMemoryAreaType :: EfiACPIMemoryNVS => 10 ,
425
+ EFIMemoryAreaType :: EfiMemoryMappedIO => 11 ,
426
+ EFIMemoryAreaType :: EfiMemoryMappedIOPortSpace => 12 ,
427
+ EFIMemoryAreaType :: EfiPalCode => 13 ,
428
+ EFIMemoryAreaType :: EfiPersistentMemory => 14 ,
429
+ EFIMemoryAreaType :: EfiUnknown => panic ! ( "unknown type" ) ,
430
+ }
431
+ }
432
+ }
433
+
362
434
impl EFIMemoryDesc {
363
435
/// The physical address of the memory region.
364
436
pub fn physical_address ( & self ) -> u64 {
@@ -399,6 +471,19 @@ impl EFIMemoryDesc {
399
471
}
400
472
}
401
473
474
+ impl Default for EFIMemoryDesc {
475
+ fn default ( ) -> Self {
476
+ Self {
477
+ typ : EFIMemoryAreaType :: EfiReservedMemoryType . into ( ) ,
478
+ _padding : 0 ,
479
+ phys_addr : 0 ,
480
+ virt_addr : 0 ,
481
+ num_pages : 0 ,
482
+ attr : 0 ,
483
+ }
484
+ }
485
+ }
486
+
402
487
/// EFI ExitBootServices was not called
403
488
#[ derive( Debug ) ]
404
489
#[ repr( C ) ]
@@ -428,3 +513,25 @@ impl<'a> Iterator for EFIMemoryAreaIter<'a> {
428
513
}
429
514
}
430
515
}
516
+
517
+ /// An iterator over ALL EFI memory areas, mutably.
518
+ #[ derive( Clone , Debug ) ]
519
+ pub struct EFIMemoryAreaIterMut < ' a > {
520
+ current_area : u64 ,
521
+ last_area : u64 ,
522
+ entry_size : u32 ,
523
+ phantom : PhantomData < & ' a mut EFIMemoryDesc > ,
524
+ }
525
+
526
+ impl < ' a > Iterator for EFIMemoryAreaIterMut < ' a > {
527
+ type Item = & ' a mut EFIMemoryDesc ;
528
+ fn next ( & mut self ) -> Option < & ' a mut EFIMemoryDesc > {
529
+ if self . current_area > self . last_area {
530
+ None
531
+ } else {
532
+ let area = unsafe { & mut * ( self . current_area as * mut EFIMemoryDesc ) } ;
533
+ self . current_area += self . entry_size as u64 ;
534
+ Some ( area)
535
+ }
536
+ }
537
+ }
0 commit comments