Search code examples
uefiedk2

AllocatePages return EFI_INVALID_PARAMETER for memory type as EfiConventionalMemory?


Hi I'm using edk2 to write a boot service for a kernel and need to apply AllocatePages service to apply memory with type as EfiConventionalMemory.

However, it returns an error code of EFI_INVALID_PARAMETER.

I looked into the source code from git, the actual function is as follow:

EFI_STATUS
EFIAPI
CoreAllocatePages (
  IN  EFI_ALLOCATE_TYPE     Type,
  IN  EFI_MEMORY_TYPE       MemoryType,
  IN  UINTN                 NumberOfPages,
  OUT EFI_PHYSICAL_ADDRESS  *Memory
  )
{
  EFI_STATUS  Status;
  BOOLEAN     NeedGuard;

  NeedGuard = IsPageTypeToGuard (MemoryType, Type) && !mOnGuarding;
  Status = CoreInternalAllocatePages (Type, MemoryType, NumberOfPages, Memory,
                                      NeedGuard);
  if (!EFI_ERROR (Status)) {
    CoreUpdateProfile (
      (EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0),
      MemoryProfileActionAllocatePages,
      MemoryType,
      EFI_PAGES_TO_SIZE (NumberOfPages),
      (VOID *) (UINTN) *Memory,
      NULL
      );
    InstallMemoryAttributesTableOnMemoryAllocation (MemoryType);
    ApplyMemoryProtectionPolicy (EfiConventionalMemory, MemoryType, *Memory,
      EFI_PAGES_TO_SIZE (NumberOfPages));
  }
  return Status;
}

It calls the function CoreInternalAllocatePages, which is as follow:

EFI_STATUS
EFIAPI
CoreInternalAllocatePages (
  IN EFI_ALLOCATE_TYPE      Type,
  IN EFI_MEMORY_TYPE        MemoryType,
  IN UINTN                  NumberOfPages,
  IN OUT EFI_PHYSICAL_ADDRESS  *Memory,
  IN BOOLEAN                NeedGuard
  )
{
  EFI_STATUS       Status;
  UINT64           Start;
  UINT64           NumberOfBytes;
  UINT64           End;
  UINT64           MaxAddress;
  UINTN            Alignment;
  EFI_MEMORY_TYPE  CheckType;

  if ((UINT32)Type >= MaxAllocateType) {
    return EFI_INVALID_PARAMETER;
  }

  if ((MemoryType >= EfiMaxMemoryType && MemoryType < MEMORY_TYPE_OEM_RESERVED_MIN) ||
       (MemoryType == EfiConventionalMemory) || (MemoryType == EfiPersistentMemory)) {
    return EFI_INVALID_PARAMETER;
  }

So it actually returns EFI_INVALID_PARAMETER if memory type is EfiConventionalMemory.

I also read the UEFI spec which define EfiConventionalMemory as type of "Free (unallocated) memory" before ExitBootServices() is called and "Memory available for general use" after.

So I'm kind of confused if it is normal that I got EFI_INVALID_PARAMETER, if not, what should I do to get the right memory allocation??

Thanks a lot!


Solution

  • The memory type parameter specifies the type the memory should have after allocation. Obviously the memory cannot be free after allocation, so that’s why EfiConventionalMemory is an invalid parameter.

    The source of memory for the allocation is always EfiConventionalMemory.

    Typically you would use BootServicesData as the requested memory type.