在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; 是干什么用的
参考:
1. http://blog.fpmurphy.com/2012/08/uefi-memory-v-e820-memory.html
可以在附件中找到该网页。它使用的是EFI_Toolkit 我没有编译过
《Step to UEFI Shell (5)----获得Shell下内存分配状况》有2个想法