Page 1 of 1

UEFI Memory Descriptor Definition

Posted: Fri Dec 11, 2020 11:35 am
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?

Re: UEFI Memory Descriptor Definition

Posted: Fri Dec 11, 2020 1:22 pm
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

Re: UEFI Memory Descriptor Definition

Posted: Fri Dec 11, 2020 5:39 pm
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

Re: UEFI Memory Descriptor Definition

Posted: Fri Dec 11, 2020 7:03 pm
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.