@@ -266,28 +266,69 @@ pub struct EFIMemoryMapTag {
266
266
size : u32 ,
267
267
desc_size : u32 ,
268
268
desc_version : u32 ,
269
- first_desc : EFIMemoryDesc ,
269
+ descs : [ EFIMemoryDesc ] ,
270
270
}
271
271
272
272
impl EFIMemoryMapTag {
273
+ #[ cfg( feature = "builder" ) ]
274
+ /// Create a new EFI memory map tag with the given memory descriptors.
275
+ /// Version and size can't be set because you're passing a slice of
276
+ /// EFIMemoryDescs, not the ones you might have gotten from the firmware.
277
+ pub fn new ( descs : & [ EFIMemoryDesc ] ) -> Box < Self > {
278
+ // update this when updating EFIMemoryDesc
279
+ const MEMORY_DESCRIPTOR_VERSION : u32 = 1 ;
280
+ let mut bytes = [
281
+ ( mem:: size_of :: < EFIMemoryDesc > ( ) as u32 ) . to_le_bytes ( ) ,
282
+ MEMORY_DESCRIPTOR_VERSION . to_le_bytes ( ) ,
283
+ ] . concat ( ) ;
284
+ for desc in descs {
285
+ bytes. extend ( desc. struct_as_bytes ( ) ) ;
286
+ }
287
+ let tag = boxed_dst_tag ( TagType :: EfiMmap , bytes. as_slice ( ) ) ;
288
+ unsafe { Box :: from_raw ( Box :: into_raw ( tag) as * mut Self ) }
289
+ }
290
+
273
291
/// Return an iterator over ALL marked memory areas.
274
292
///
275
293
/// This differs from `MemoryMapTag` as for UEFI, the OS needs some non-
276
294
/// available memory areas for tables and such.
277
295
pub fn memory_areas ( & self ) -> EFIMemoryAreaIter {
278
296
let self_ptr = self as * const EFIMemoryMapTag ;
279
- let start_area = ( & self . first_desc ) as * const EFIMemoryDesc ;
297
+ let start_area = ( & self . descs [ 0 ] ) as * const EFIMemoryDesc ;
280
298
EFIMemoryAreaIter {
281
299
current_area : start_area as u64 ,
282
- last_area : ( self_ptr as u64 + self . size as u64 ) ,
300
+ last_area : ( self_ptr as * const ( ) as u64 + self . size as u64 ) ,
301
+ entry_size : self . desc_size ,
302
+ phantom : PhantomData ,
303
+ }
304
+ }
305
+
306
+ #[ cfg( feature = "builder" ) ]
307
+ /// Return an iterator over ALL marked memory areas, mutably.
308
+ ///
309
+ /// This differs from `MemoryMapTag` as for UEFI, the OS needs some non-
310
+ /// available memory areas for tables and such.
311
+ pub fn memory_areas_mut ( & mut self ) -> EFIMemoryAreaIterMut {
312
+ let self_ptr = self as * const EFIMemoryMapTag ;
313
+ let start_area = ( & self . descs [ 0 ] ) as * const EFIMemoryDesc ;
314
+ EFIMemoryAreaIterMut {
315
+ current_area : start_area as u64 ,
316
+ last_area : ( self_ptr as * const ( ) as u64 + self . size as u64 ) ,
283
317
entry_size : self . desc_size ,
284
318
phantom : PhantomData ,
285
319
}
286
320
}
287
321
}
288
322
323
+ #[ cfg( feature = "builder" ) ]
324
+ impl StructAsBytes for EFIMemoryMapTag {
325
+ fn byte_size ( & self ) -> usize {
326
+ self . size . try_into ( ) . unwrap ( )
327
+ }
328
+ }
329
+
289
330
/// EFI Boot Memory Map Descriptor
290
- #[ derive( Debug ) ]
331
+ #[ derive( Debug , Clone ) ]
291
332
#[ repr( C ) ]
292
333
pub struct EFIMemoryDesc {
293
334
typ : u32 ,
@@ -298,6 +339,13 @@ pub struct EFIMemoryDesc {
298
339
attr : u64 ,
299
340
}
300
341
342
+ #[ cfg( feature = "builder" ) ]
343
+ impl StructAsBytes for EFIMemoryDesc {
344
+ fn byte_size ( & self ) -> usize {
345
+ mem:: size_of :: < Self > ( )
346
+ }
347
+ }
348
+
301
349
/// An enum of possible reported region types.
302
350
#[ derive( Debug , PartialEq , Eq ) ]
303
351
pub enum EFIMemoryAreaType {
@@ -352,6 +400,29 @@ pub enum EFIMemoryAreaType {
352
400
EfiUnknown ,
353
401
}
354
402
403
+ impl Into < u32 > for EFIMemoryAreaType {
404
+ fn into ( self ) -> u32 {
405
+ match self {
406
+ EFIMemoryAreaType :: EfiReservedMemoryType => 0 ,
407
+ EFIMemoryAreaType :: EfiLoaderCode => 1 ,
408
+ EFIMemoryAreaType :: EfiLoaderData => 2 ,
409
+ EFIMemoryAreaType :: EfiBootServicesCode => 3 ,
410
+ EFIMemoryAreaType :: EfiBootServicesData => 4 ,
411
+ EFIMemoryAreaType :: EfiRuntimeServicesCode => 5 ,
412
+ EFIMemoryAreaType :: EfiRuntimeServicesData => 6 ,
413
+ EFIMemoryAreaType :: EfiConventionalMemory => 7 ,
414
+ EFIMemoryAreaType :: EfiUnusableMemory => 8 ,
415
+ EFIMemoryAreaType :: EfiACPIReclaimMemory => 9 ,
416
+ EFIMemoryAreaType :: EfiACPIMemoryNVS => 10 ,
417
+ EFIMemoryAreaType :: EfiMemoryMappedIO => 11 ,
418
+ EFIMemoryAreaType :: EfiMemoryMappedIOPortSpace => 12 ,
419
+ EFIMemoryAreaType :: EfiPalCode => 13 ,
420
+ EFIMemoryAreaType :: EfiPersistentMemory => 14 ,
421
+ EFIMemoryAreaType :: EfiUnknown => panic ! ( "unknown type" ) ,
422
+ }
423
+ }
424
+ }
425
+
355
426
impl EFIMemoryDesc {
356
427
/// The physical address of the memory region.
357
428
pub fn physical_address ( & self ) -> u64 {
@@ -392,6 +463,19 @@ impl EFIMemoryDesc {
392
463
}
393
464
}
394
465
466
+ impl Default for EFIMemoryDesc {
467
+ fn default ( ) -> Self {
468
+ Self {
469
+ typ : EFIMemoryAreaType :: EfiReservedMemoryType . into ( ) ,
470
+ _padding : 0 ,
471
+ phys_addr : 0 ,
472
+ virt_addr : 0 ,
473
+ num_pages : 0 ,
474
+ attr : 0 ,
475
+ }
476
+ }
477
+ }
478
+
395
479
/// EFI ExitBootServices was not called
396
480
#[ derive( Debug ) ]
397
481
#[ repr( C ) ]
@@ -421,3 +505,25 @@ impl<'a> Iterator for EFIMemoryAreaIter<'a> {
421
505
}
422
506
}
423
507
}
508
+
509
+ /// An iterator over ALL EFI memory areas, mutably.
510
+ #[ derive( Clone , Debug ) ]
511
+ pub struct EFIMemoryAreaIterMut < ' a > {
512
+ current_area : u64 ,
513
+ last_area : u64 ,
514
+ entry_size : u32 ,
515
+ phantom : PhantomData < & ' a mut EFIMemoryDesc > ,
516
+ }
517
+
518
+ impl < ' a > Iterator for EFIMemoryAreaIterMut < ' a > {
519
+ type Item = & ' a mut EFIMemoryDesc ;
520
+ fn next ( & mut self ) -> Option < & ' a mut EFIMemoryDesc > {
521
+ if self . current_area > self . last_area {
522
+ None
523
+ } else {
524
+ let area = unsafe { & mut * ( self . current_area as * mut EFIMemoryDesc ) } ;
525
+ self . current_area += self . entry_size as u64 ;
526
+ Some ( area)
527
+ }
528
+ }
529
+ }
0 commit comments