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