@@ -233,38 +233,71 @@ impl Debug for BasicMemoryInfoTag {
233233 }
234234}
235235
236+ const EFI_METADATA_SIZE : usize = mem:: size_of :: < TagTypeId > ( ) + 3 * mem:: size_of :: < u32 > ( ) ;
237+
236238/// EFI memory map as per EFI specification.
237- #[ derive( Debug ) ]
239+ #[ derive( Debug , ptr_meta :: Pointee ) ]
238240#[ repr( C ) ]
239241pub struct EFIMemoryMapTag {
240242 typ : TagTypeId ,
241243 size : u32 ,
242244 desc_size : u32 ,
243245 desc_version : u32 ,
244- first_desc : [ EFIMemoryDesc ; 0 ] ,
246+ descs : [ EFIMemoryDesc ] ,
245247}
246248
247249impl 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+
248268 /// Return an iterator over ALL marked memory areas.
249269 ///
250270 /// This differs from `MemoryMapTag` as for UEFI, the OS needs some non-
251271 /// available memory areas for tables and such.
252272 pub fn memory_areas ( & self ) -> EFIMemoryAreaIter {
253273 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 ;
255275 EFIMemoryAreaIter {
256276 current_area : start_area as u64 ,
257277 // 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 ) ,
260279 entry_size : self . desc_size ,
261280 phantom : PhantomData ,
262281 }
263282 }
264283}
265284
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+
266299/// EFI Boot Memory Map Descriptor
267- #[ derive( Debug ) ]
300+ #[ derive( Debug , Clone ) ]
268301#[ repr( C ) ]
269302pub struct EFIMemoryDesc {
270303 typ : u32 ,
@@ -275,6 +308,13 @@ pub struct EFIMemoryDesc {
275308 attr : u64 ,
276309}
277310
311+ #[ cfg( feature = "builder" ) ]
312+ impl StructAsBytes for EFIMemoryDesc {
313+ fn byte_size ( & self ) -> usize {
314+ mem:: size_of :: < Self > ( )
315+ }
316+ }
317+
278318/// An enum of possible reported region types.
279319#[ derive( Debug , PartialEq , Eq ) ]
280320pub enum EFIMemoryAreaType {
@@ -329,6 +369,29 @@ pub enum EFIMemoryAreaType {
329369 EfiUnknown ,
330370}
331371
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+
332395impl EFIMemoryDesc {
333396 /// The physical address of the memory region.
334397 pub fn physical_address ( & self ) -> u64 {
@@ -369,6 +432,19 @@ impl EFIMemoryDesc {
369432 }
370433}
371434
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+
372448/// EFI ExitBootServices was not called
373449#[ derive( Debug ) ]
374450#[ repr( C ) ]
0 commit comments