在Shell下面可以使用 memmap 命令查看到当前的内存状况:

UEFI下面没有了E820 Table。取而代之的是GetMemoryMap()。UEFI spec Version 2.4 中 P143有如下的描述,实际上是一个长得和E820很像的东西。

在网上可以搜索到一个示例[参考1],原文是用Toolkit 写成的,经过一些改造成为可以直接在EDK2下面的编译的代码。
GetMap.c:
#include <Uefi.h>
#include <Library/PcdLib.h>
#include <Library/UefiLib.h>
#include <Library/UefiApplicationEntryPoint.h>
#define PAGE_SIZE 4096
const CHAR16 *memory_types[] = {
L"EfiReservedMemoryType",
L"EfiLoaderCode",
L"EfiLoaderData",
L"EfiBootServicesCode",
L"EfiBootServicesData",
L"EfiRuntimeServicesCode",
L"EfiRuntimeServicesData",
L"EfiConventionalMemory",
L"EfiUnusableMemory",
L"EfiACPIReclaimMemory",
L"EfiACPIMemoryNVS",
L"EfiMemoryMappedIO",
L"EfiMemoryMappedIOPortSpace",
L"EfiPalCode",
L"EfiMaxMemoryType"
};
EFI_BOOT_SERVICES *gBS;
const CHAR16 *
memory_type_to_str(UINT32 type)
{
if (type > sizeof(memory_types)/sizeof(CHAR16 *))
return L"Unknown";
return memory_types[type];
}
EFI_STATUS
memory_map(EFI_MEMORY_DESCRIPTOR **map_buf, UINTN *map_size,
UINTN *map_key, UINTN *desc_size, UINT32 *desc_version)
{
EFI_STATUS err = EFI_SUCCESS;
*map_size = sizeof(**map_buf) * 31;
get_map:
*map_size += sizeof(**map_buf);
err = gBS->AllocatePool(EfiLoaderData, *map_size, (void **)map_buf);
if (err != EFI_SUCCESS) {
Print(L"ERROR: Failed to allocate pool for memory map");
return err;
}
err = gBS->GetMemoryMap(map_size, *map_buf, map_key, desc_size, desc_version);
if (err != EFI_SUCCESS) {
if (err == EFI_BUFFER_TOO_SMALL) {
gBS->FreePool((void *)*map_buf);
goto get_map;
}
Print(L"ERROR: Failed to get memory map");
}
return err;
}
GetMap.inf
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = GetMap
FILE_GUID = 6987936E-ED34-44db-AE97-1FA5E4ED2318
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 1.0
ENTRY_POINT = UefiMain
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
[Sources]
GetMap.c
[Packages]
MdePkg/MdePkg.dec
ShellPkg/ShellPkg.dec
MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
UefiApplicationEntryPoint
UefiLib
PcdLib
ShellCEntryLib
ShellLib
[FeaturePcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdHelloWorldPrintEnable
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdHelloWorldPrintString || gEfiMdeModulePkgTokenSpaceGuid.PcdHelloWorldPrintEnable ## Valid when gEfiMdeModulePkgTokenSpaceGuid.PcdHelloWorldPrintEnable
gEfiMdeModulePkgTokenSpaceGuid.PcdHelloWorldPrintTimes || gEfiMdeModulePkgTokenSpaceGuid.PcdHelloWorldPrintEnable ## Valid when gEfiMdeModulePkgTokenSpaceGuid.PcdHelloWorldPrintEnable
EFI_STATUS
print_memory_map(void)
{
EFI_MEMORY_DESCRIPTOR *buf;
UINTN desc_size;
UINT32 desc_version;
UINTN size, map_key, mapping_size;
EFI_MEMORY_DESCRIPTOR *desc;
EFI_STATUS err = EFI_SUCCESS;
int i = 0;
err = memory_map(&buf, &size, &map_key, &desc_size, &desc_version);
if (err != EFI_SUCCESS)
return err;
Print(L"Memory Map Size: %d\n", size);
Print(L"Map Key: %d\n", map_key);
Print(L"Descriptor Version: %d\n", desc_version);
Print(L"Descriptor Size: %d\n\n", desc_size);
Print(L"Descriptor Size: %d\n\n", sizeof(EFI_MEMORY_DESCRIPTOR));
desc = buf;
while ((UINT8 *)desc < (UINT8 *)buf + size) {
mapping_size =(UINTN) desc->NumberOfPages * PAGE_SIZE;
Print(L"[#%02d] Type: %s Attr: 0x%x\n", i, memory_type_to_str(desc->Type), desc->Attribute);
Print(L" Phys: %016llx-%016llx\n", desc->PhysicalStart, desc->PhysicalStart + mapping_size -1 );
desc = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)desc + desc_size);
i++;
}
gBS->FreePool (buf);
return err;
}
EFI_STATUS
EFIAPI
UefiMain(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
{
print_memory_map();
return EFI_SUCCESS;
}
运行结果如下:

我们使用 GetMap >> result.txt 得到完整的输出结果如下:
Memory Map Size: 960
Map Key: 2841
Descriptor Version: 1
Descriptor Size: 48
Descriptor Size: 40
[#00] Type: EfiBootServicesData Attr: 0xF
Phys: 0000000000CB0000-0000000000CCFFFF
[#01] Type: EfiConventionalMemory Attr: 0xF
Phys: 0000000000CD0000-000000000383FFFF
[#02] Type: EfiLoaderData Attr: 0xF
Phys: 0000000003840000-0000000003841FFF
[#03] Type: EfiLoaderCode Attr: 0xF
Phys: 0000000003842000-0000000003848FFF
[#04] Type: EfiLoaderData Attr: 0xF
Phys: 0000000003849000-000000000385EFFF
[#05] Type: EfiLoaderCode Attr: 0xF
Phys: 000000000385F000-00000000038ABFFF
[#06] Type: EfiConventionalMemory Attr: 0xF
Phys: 00000000038AC000-0000000003B09FFF
[#07] Type: EfiBootServicesData Attr: 0xF
Phys: 0000000003B0A000-0000000003B56FFF
[#08] Type: EfiConventionalMemory Attr: 0xF
Phys: 0000000003B57000-0000000003B74FFF
[#09] Type: EfiBootServicesData Attr: 0xF
Phys: 0000000003B75000-0000000003B75FFF
[#10] Type: EfiConventionalMemory Attr: 0xF
Phys: 0000000003B76000-0000000003B76FFF
[#11] Type: EfiBootServicesData Attr: 0xF
Phys: 0000000003B77000-00000000048ABFFF
[#12] Type: EfiConventionalMemory Attr: 0xF
Phys: 00000000048AC000-0000000004990FFF
[#13] Type: EfiBootServicesCode Attr: 0xF
Phys: 0000000004991000-0000000004BABFFF
[#14] Type: EfiRuntimeServicesData Attr: 0xF
Phys: 0000000004BAC000-0000000004BEBFFF
[#15] Type: EfiRuntimeServicesCode Attr: 0xF
Phys: 0000000004BEC000-0000000004C2BFFF
[#16] Type: EfiReservedMemoryType Attr: 0xF
Phys: 0000000004C2C000-0000000004C2FFFF
[#17] Type: EfiBootServicesData Attr: 0xF
Phys: 0000000004C30000-0000000004CAFFFF
[#18] Type: EfiConventionalMemory Attr: 0xF
Phys: 0000000004CB0000-0000000008CAFFFF
[#19] Type: EfiMemoryMappedIO Attr: 0x0
Phys: 0000000000BE0000-0000000000BEBFFF
和直接使用memmap取得的结果相同。需要注意的是:
1. 返回的Descriptor Size 并不是 sizeof(EFI_MEMORY_DESCRIPTOR)
2. 不知道EFI_VIRTUAL_ADDRESS VirtualStart; 是干什么用的
GetMap
参考:
1. http://blog.fpmurphy.com/2012/08/uefi-memory-v-e820-memory.html
可以在附件中找到该网页。它使用的是EFI_Toolkit 我没有编译过