UEFI Memory Descriptor Definition

All about the OSDev Wiki. Discussions about the organization and general structure of articles and how to use the wiki. Request changes here if you don't know how to use the wiki.
Post Reply
adamfc2000
Posts: 6
Joined: Thu Apr 06, 2017 2:59 pm

UEFI Memory Descriptor Definition

Post by adamfc2000 »

The wiki article gives the structure as follows:

Code: Select all

typedef struct {
    UINT32                          Type;           // EFI_MEMORY_TYPE, Field size is 32 bits followed by 32 bit pad
    UINT32                          Pad;
    EFI_PHYSICAL_ADDRESS            PhysicalStart;  // Field size is 64 bits
    EFI_VIRTUAL_ADDRESS             VirtualStart;   // Field size is 64 bits
    UINT64                          NumberOfPages;  // Field size is 64 bits
    UINT64                          Attribute;      // Field size is 64 bits
} EFI_MEMORY_DESCRIPTOR;


The UEFI spec I found (page 160) online gives the definition (without the second UINT32 as padding):

Code: Select all

typedef struct {
UINT32 Type;
EFI_PHYSICAL_ADDRESS PhysicalStart;
EFI_VIRTUAL_ADDRESS VirtualStart;
UINT64 NumberOfPages;
UINT64 Attribute;
} EFI_MEMORY_DESCRIPTOR;


Maybe an error in the wiki?
User avatar
BenLunt
Member
Member
Posts: 934
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: UEFI Memory Descriptor Definition

Post by BenLunt »

Hi,

adamfc2000 wrote:Maybe an error in the wiki?

No, not necessarily. The members of the structure are aligned per their size. For example, in 64-bit mode, the 8-byte member:

Code: Select all

EFI_PHYSICAL_ADDRESS            PhysicalStart

will be aligned on the next 8-byte alignment, which is four bytes past where the "Type" member left off.

The first block of code is just accounting for this. The second block of code is assuming that the compiler was told to self align each member.

In my opinion, the first block of code is best, not only because it accounts for this, but is much more "self documenting" along with the comments given.

Ben
User avatar
zaval
Member
Member
Posts: 645
Joined: Fri Feb 17, 2017 4:01 pm
Location: Ukraine, Bachmut
Contact:

Re: UEFI Memory Descriptor Definition

Post by zaval »

UINT64 will be aligned not only in 64 bit mode, in 32 bit too. it's not the error in the wiki. UEFI specification is full of such misaligned gotchas (EFI_LOADED_IMAGE_PROTOCOL structure is a striking example). It's just a "leave it to the compiler to handle" kind of attitude. I, when was writing my own headers for UEFI, inserted padding members explicitly. hopefully, I did that right. :D
ANT - NT-like OS for x64 and arm64.
efify - UEFI for a couple of boards (mips and arm). suspended due to lost of all the target park boards (russians destroyed our town).
kzinti
Member
Member
Posts: 898
Joined: Mon Feb 02, 2015 7:11 pm

Re: UEFI Memory Descriptor Definition

Post by kzinti »

I remember running into this very issue with Intel's UEFI headers where the definition of EFI_MEMORY_DESCRIPTOR wouldn't compile properly on GCC (it didn't have the padding field).

I fixed the issue by adding that uint32_t padding after "Type".

I also added this in my source code to make sure such problems don't happen again:

Code: Select all

// Intel's UEFI header do not properly define EFI_MEMORY_DESCRIPTOR for GCC.
// This check ensures that it is.
static_assert(offsetof(EFI_MEMORY_DESCRIPTOR, PhysicalStart) == 8);


This fix isn't needed when using MS packing rules as PhysicalStart will be 64-bits aligned (VS, Mingw) but is required with GCC in 32 bits mode at least.
Post Reply