From e6dcdda6b9302f9bb72db70022a13248839615f2 Mon Sep 17 00:00:00 2001 From: "Justin C. Miller" Date: Mon, 20 Feb 2017 22:12:11 -0800 Subject: [PATCH] Added memory.c Includes routine replacing efilib's LibMemoryMap, and a debug function for dumping the map to the console. Currently get_memory_map() is only used for the debug function dump_memory_map. Thanks to Finnbar Murphy for the blog post that helped me figure out why my memory map iteration was wrong. http://blog.fpmurphy.com/2012/08/uefi-memory-v-e820-memory.html --- src/arch/x86_64/main.c | 19 +++++++++ src/arch/x86_64/memory.c | 84 ++++++++++++++++++++++++++++++++++++++++ src/arch/x86_64/memory.h | 13 +++++++ 3 files changed, 116 insertions(+) create mode 100644 src/arch/x86_64/memory.c create mode 100644 src/arch/x86_64/memory.h diff --git a/src/arch/x86_64/main.c b/src/arch/x86_64/main.c index e582301..1d481e2 100644 --- a/src/arch/x86_64/main.c +++ b/src/arch/x86_64/main.c @@ -2,6 +2,7 @@ #include #include "console.h" +#include "memory.h" #include "utility.h" #ifndef GIT_VERSION @@ -30,6 +31,24 @@ efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) if (SystemTable->ConOut) Print(L"OutputString: %x\n", SystemTable->ConOut->OutputString); + dump_memory_map(); + + UINTN memmap_size = 0; + EFI_MEMORY_DESCRIPTOR *memmap; + UINTN memmap_key; + UINTN desc_size; + UINT32 desc_version; + + memmap = LibMemoryMap(&memmap_size, &memmap_key, + &desc_size, &desc_version); + + status = ST->BootServices->ExitBootServices(ImageHandle, memmap_key); + CHECK_EFI_STATUS_OR_RETURN(status, "Exiting boot services"); + + status = ST->RuntimeServices->SetVirtualAddressMap( + memmap_size, desc_size, desc_version, memmap); + CHECK_EFI_STATUS_OR_RETURN(status, "Setting memory map"); + while (1) __asm__("hlt"); return status; } diff --git a/src/arch/x86_64/memory.c b/src/arch/x86_64/memory.c new file mode 100644 index 0000000..60d84b3 --- /dev/null +++ b/src/arch/x86_64/memory.c @@ -0,0 +1,84 @@ +#include +#include + +#include "memory.h" +#include "utility.h" + +const UINTN PAGE_SIZE = 4096; + +const CHAR16 *memory_type_names[] = { + 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"EfiPersistentMemory", +}; + +const CHAR16 *memory_type_name(UINT32 value) { + if (value >= (sizeof(memory_type_names)/sizeof(CHAR16*))) + return L"Bad Type Value"; + return memory_type_names[value]; +} + +EFI_STATUS get_memory_map(EFI_MEMORY_DESCRIPTOR **buffer, UINTN *buffer_size, + UINTN *key, UINTN *desc_size, UINT32 *desc_version) { + EFI_STATUS status; + + UINTN needs_size = 0; + status = BS->GetMemoryMap(&needs_size, 0, key, desc_size, desc_version); + if (status != EFI_BUFFER_TOO_SMALL) { + CHECK_EFI_STATUS_OR_RETURN(status, "Failed to load memory map"); + } + + // Give some extra buffer to account for changes. + *buffer_size = needs_size + 256; + Print(L"Trying to load memory map with size %d.\n", *buffer_size); + status = BS->AllocatePool(EfiLoaderData, *buffer_size, (void**)buffer); + CHECK_EFI_STATUS_OR_RETURN(status, "Failed to allocate space for memory map"); + + status = BS->GetMemoryMap(buffer_size, *buffer, key, desc_size, desc_version); + CHECK_EFI_STATUS_OR_RETURN(status, "Failed to load memory map"); + return EFI_SUCCESS; +} + +EFI_STATUS dump_memory_map() { + EFI_MEMORY_DESCRIPTOR *buffer; + UINTN buffer_size, desc_size, key; + UINT32 desc_version; + + EFI_STATUS status = get_memory_map(&buffer, &buffer_size, &key, + &desc_size, &desc_version); + CHECK_EFI_STATUS_OR_RETURN(status, "Failed to get memory map"); + + const UINTN count = buffer_size / desc_size; + + Print(L"Memory map:\n"); + Print(L"\t Descriptor Count: %d (%d bytes)\n", count, buffer_size); + Print(L"\t Version Key: %d\n", key); + Print(L"\tDescriptor Version: %d (%d bytes)\n\n", desc_version, desc_size); + + EFI_MEMORY_DESCRIPTOR *end = (EFI_MEMORY_DESCRIPTOR *)((uint8_t *)buffer + buffer_size); + EFI_MEMORY_DESCRIPTOR *d = buffer; + while (d < end) { + UINTN size_bytes = d->NumberOfPages * PAGE_SIZE; + + Print(L"Type: %s Attr: 0x%x\n", memory_type_name(d->Type), d->Attribute); + Print(L"\t Physical %016llx - %016llx\n", d->PhysicalStart, d->PhysicalStart + size_bytes); + Print(L"\t Virtual %016llx - %016llx\n\n", d->VirtualStart, d->VirtualStart + size_bytes); + + d = (EFI_MEMORY_DESCRIPTOR *)((uint8_t *)d + desc_size); + } + + BS->FreePool(buffer); + return EFI_SUCCESS; +} \ No newline at end of file diff --git a/src/arch/x86_64/memory.h b/src/arch/x86_64/memory.h new file mode 100644 index 0000000..970345b --- /dev/null +++ b/src/arch/x86_64/memory.h @@ -0,0 +1,13 @@ +#pragma once +#include + +const CHAR16 *memory_type_name(UINT32 value); + +EFI_STATUS get_memory_map( + EFI_MEMORY_DESCRIPTOR **buffer, + UINTN *buffer_size, + UINTN *key, + UINTN *desc_size, + UINT32 *desc_version); + +EFI_STATUS dump_memory_map(); \ No newline at end of file