Implement UEFI to Limine memory map conversion

This commit is contained in:
mintsuki 2021-03-05 04:20:58 +01:00
parent 8939c3421c
commit a81f094d1d
5 changed files with 107 additions and 4 deletions

View File

@ -28,6 +28,7 @@ EFI_STATUS EFIAPI efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable
gST = SystemTable;
gBS = SystemTable->BootServices;
gRT = SystemTable->RuntimeServices;
efi_image_handle = ImageHandle;
print("Limine " LIMINE_VERSION "\n\n", print);
@ -87,6 +88,10 @@ void stage3_common(struct volume *boot_volume) {
char *cmdline;
char *config = menu(&cmdline);
#if defined (uefi)
efi_exit_boot_services();
#endif
char *proto = config_get_value(config, 0, "PROTOCOL");
if (proto == NULL) {
panic("PROTOCOL not specified");

View File

@ -7,11 +7,13 @@
#include <lib/trace.h>
#include <lib/real.h>
#include <fs/file.h>
#include <mm/pmm.h>
#if defined (uefi)
EFI_SYSTEM_TABLE *gST;
EFI_BOOT_SERVICES *gBS;
EFI_RUNTIME_SERVICES *gRT;
EFI_HANDLE efi_image_handle;
#endif
bool parse_resolution(int *width, int *height, int *bpp, const char *buf) {
@ -63,3 +65,33 @@ uint64_t sqrt(uint64_t a_nInput) {
return res;
}
#if defined (uefi)
bool efi_boot_services_exited = false;
bool efi_exit_boot_services(void) {
EFI_MEMORY_DESCRIPTOR tmp_mmap[1];
UINTN mmap_size = sizeof(tmp_mmap);
UINTN mmap_key = 0, desc_size = 0, desc_ver = 0;
uefi_call_wrapper(gBS->GetMemoryMap, 5,
&mmap_size, tmp_mmap, &mmap_key, &desc_size, &desc_ver);
EFI_MEMORY_DESCRIPTOR *efi_mmap = ext_mem_alloc(mmap_size);
uefi_call_wrapper(gBS->GetMemoryMap, 5,
&mmap_size, efi_mmap, &mmap_key, &desc_size, &desc_ver);
uefi_call_wrapper(gBS->ExitBootServices, 2, efi_image_handle, mmap_key);
pmm_mmap_efi2ours(efi_mmap, desc_size, mmap_size / desc_size);
efi_boot_services_exited = true;
print("efi: Exited boot services.\n");
return true;
}
#endif

View File

@ -14,6 +14,10 @@
extern EFI_SYSTEM_TABLE *gST;
extern EFI_BOOT_SERVICES *gBS;
extern EFI_RUNTIME_SERVICES *gRT;
extern EFI_HANDLE efi_image_handle;
extern bool efi_boot_services_exited;
bool efi_exit_boot_services(void);
#endif
extern int boot_drive;

View File

@ -17,6 +17,13 @@
extern struct e820_entry_t memmap[];
extern size_t memmap_entries;
#if defined (uefi)
#include <efi.h>
bool pmm_mmap_efi2ours(EFI_MEMORY_DESCRIPTOR *efi_mmap,
size_t desc_size, size_t entry_count);
#endif
void init_memmap(void);
struct e820_entry_t *get_memmap(size_t *entries);
void print_memmap(struct e820_entry_t *mm, size_t size);

View File

@ -214,9 +214,8 @@ void *ext_mem_alloc_type(size_t count, uint32_t type) {
return ext_mem_alloc_aligned_type(count, 4, type);
}
#if defined (bios)
// Allocate memory top down, hopefully without bumping into kernel or modules
void *ext_mem_alloc_aligned_type(size_t count, size_t alignment, uint32_t type) {
static void *_ext_mem_alloc_aligned_type(size_t count, size_t alignment, uint32_t type) {
if (allocations_disallowed)
panic("Extended memory allocations disallowed");
@ -257,11 +256,63 @@ void *ext_mem_alloc_aligned_type(size_t count, size_t alignment, uint32_t type)
panic("High memory allocator: Out of memory");
}
#if defined (bios)
void *ext_mem_alloc_aligned_type(size_t count, size_t alignment, uint32_t type) {
return _ext_mem_alloc_aligned_type(count, alignment, type);
}
#endif
#if defined (uefi)
bool pmm_mmap_efi2ours(EFI_MEMORY_DESCRIPTOR *efi_mmap,
size_t desc_size, size_t entry_count) {
for (size_t i = 0; i < entry_count; i++) {
EFI_MEMORY_DESCRIPTOR *entry = (void *)efi_mmap + i * desc_size;
uint32_t our_type;
switch (entry->Type) {
case EfiReservedMemoryType:
case EfiRuntimeServicesCode:
case EfiRuntimeServicesData:
case EfiUnusableMemory:
case EfiMemoryMappedIO:
case EfiMemoryMappedIOPortSpace:
case EfiPalCode:
default:
our_type = MEMMAP_RESERVED; break;
case EfiBootServicesCode:
case EfiBootServicesData:
case EfiLoaderCode:
case EfiLoaderData:
our_type = MEMMAP_BOOTLOADER_RECLAIMABLE; break;
case EfiACPIReclaimMemory:
our_type = MEMMAP_ACPI_RECLAIMABLE; break;
case EfiACPIMemoryNVS:
our_type = MEMMAP_ACPI_NVS; break;
case EfiConventionalMemory:
our_type = MEMMAP_USABLE; break;
}
memmap[memmap_entries].type = our_type;
memmap[memmap_entries].base = entry->PhysicalStart;
memmap[memmap_entries].length = entry->NumberOfPages * 4096;
memmap_entries++;
}
sanitise_entries(false);
print_memmap(memmap, memmap_entries);
allocations_disallowed = false;
return true;
}
void *ext_mem_alloc_aligned_type(size_t count, size_t alignment, uint32_t type) {
(void)type;
if (efi_boot_services_exited) {
return _ext_mem_alloc_aligned_type(count, alignment, type);
}
EFI_STATUS status;
@ -275,7 +326,11 @@ void *ext_mem_alloc_aligned_type(size_t count, size_t alignment, uint32_t type)
}
if (status) {
panic("Memory allocation error %x\n", status);
panic("Memory allocation error %x", status);
}
if ((uintptr_t)ret % alignment) {
panic("Memory alloc align bad");
}
memset(ret, 0, count);