pmm: Implement get_raw_memmap() and use it in mb1 proto

This commit is contained in:
mintsuki 2021-07-06 03:01:07 +02:00
parent 572bcdae3b
commit 449df1d547
3 changed files with 81 additions and 22 deletions

View File

@ -21,6 +21,7 @@ extern size_t memmap_entries;
void init_memmap(void);
struct e820_entry_t *get_memmap(size_t *entries);
struct e820_entry_t *get_raw_memmap(size_t *entry_count);
void print_memmap(struct e820_entry_t *mm, size_t size);
bool memmap_alloc_range(uint64_t base, uint64_t length, uint32_t type, bool free_only, bool panic, bool simulation, bool new_entry);

View File

@ -357,6 +357,67 @@ void pmm_release_uefi_mem(void) {
}
#endif
#if defined (bios)
struct e820_entry_t *get_raw_memmap(size_t *entry_count) {
size_t mmap_count = e820_entries;
size_t mmap_len = mmap_count * sizeof(struct e820_entry_t);
struct e820_entry_t *mmap = conv_mem_alloc(mmap_len);
for (size_t i = 0; i < mmap_count; i++) {
mmap[i].base = e820_map[i].base;
mmap[i].length = e820_map[i].length;
mmap[i].type = e820_map[i].type;
}
*entry_count = mmap_count;
return mmap;
}
#endif
#if defined (uefi)
struct e820_entry_t *get_raw_memmap(size_t *entry_count) {
size_t mmap_count = efi_mmap_size / efi_desc_size;
size_t mmap_len = mmap_count * sizeof(struct e820_entry_t);
struct e820_entry_t *mmap = conv_mem_alloc(mmap_len);
for (size_t i = 0; i < mmap_count; i++) {
EFI_MEMORY_DESCRIPTOR *entry = (void *)efi_mmap + i * efi_desc_size;
uint32_t our_type;
switch (entry->Type) {
case EfiReservedMemoryType:
case EfiRuntimeServicesCode:
case EfiRuntimeServicesData:
case EfiUnusableMemory:
case EfiMemoryMappedIO:
case EfiMemoryMappedIOPortSpace:
case EfiPalCode:
case EfiLoaderCode:
case EfiLoaderData:
default:
our_type = MEMMAP_RESERVED; break;
case EfiACPIReclaimMemory:
our_type = MEMMAP_ACPI_RECLAIMABLE; break;
case EfiACPIMemoryNVS:
our_type = MEMMAP_ACPI_NVS; break;
case EfiBootServicesCode:
case EfiBootServicesData:
case EfiConventionalMemory:
our_type = MEMMAP_USABLE; break;
}
mmap[i].base = entry->PhysicalStart;
mmap[i].length = entry->NumberOfPages * 4096;
mmap[i].type = our_type;
}
*entry_count = mmap_count;
return mmap;
}
#endif
void *ext_mem_alloc(size_t count) {
return ext_mem_alloc_type(count, MEMMAP_BOOTLOADER_RECLAIMABLE);
}

View File

@ -119,7 +119,7 @@ void multiboot1_load(char *config, char *cmdline) {
}
if (n_modules) {
struct multiboot1_module *mods = ext_mem_alloc(sizeof(*mods) * n_modules);
struct multiboot1_module *mods = conv_mem_alloc(sizeof(*mods) * n_modules);
multiboot1_info.mods_count = n_modules;
multiboot1_info.mods_addr = (uint32_t)(size_t)mods;
@ -229,35 +229,32 @@ void multiboot1_load(char *config, char *cmdline) {
efi_exit_boot_services();
#endif
size_t memmap_entries;
struct e820_entry_t *memmap = get_memmap(&memmap_entries);
size_t mb_mmap_count;
struct e820_entry_t *raw_memmap = get_raw_memmap(&mb_mmap_count);
// The layouts of the e820_entry_t and multiboot1_mmap_entry structs match almost perfectly
// apart from the padding/size being in the wrong place (at the end and beginning respectively).
// To be able to use the memmap directly, we offset it back by 4 so the fields align properly.
// Since we're about to exit we don't really care about what we've clobbered by doing this.
struct multiboot1_mmap_entry *mmap = (void *)((size_t)memmap - 4);
size_t mb_mmap_len = mb_mmap_count * sizeof(struct multiboot1_mmap_entry);
struct multiboot1_mmap_entry *mmap = conv_mem_alloc(mb_mmap_len);
size_t memory_lower = 0, memory_upper = 0;
for (size_t i = 0; i < memmap_entries; i++ ){
mmap[i].size = sizeof(*mmap) - 4;
// Multiboot is bad and passes raw memmap. We do the same to support it.
for (size_t i = 0; i < mb_mmap_count; i++) {
mmap[i].size = sizeof(struct multiboot1_mmap_entry) - 4;
mmap[i].addr = raw_memmap[i].base;
mmap[i].len = raw_memmap[i].length;
mmap[i].type = raw_memmap[i].type;
if (memmap[i].type == MEMMAP_BOOTLOADER_RECLAIMABLE
|| memmap[i].type == MEMMAP_KERNEL_AND_MODULES)
memmap[i].type = MEMMAP_USABLE;
if (memmap[i].type == MEMMAP_USABLE) {
if (memmap[i].base < 0x100000) {
if (memmap[i].base + memmap[i].length > 0x100000) {
size_t low_len = 0x100000 - memmap[i].base;
if (mmap[i].type == MEMMAP_USABLE) {
if (mmap[i].addr < 0x100000) {
if (mmap[i].addr + mmap[i].len > 0x100000) {
size_t low_len = 0x100000 - mmap[i].addr;
memory_lower += low_len;
memory_upper += memmap[i].length - low_len;
memory_upper += mmap[i].len - low_len;
} else {
memory_lower += memmap[i].length;
memory_lower += mmap[i].len;
}
} else {
memory_upper += memmap[i].length;
memory_upper += mmap[i].len;
}
}
}
@ -265,7 +262,7 @@ void multiboot1_load(char *config, char *cmdline) {
multiboot1_info.mem_lower = memory_lower / 1024;
multiboot1_info.mem_upper = memory_upper / 1024;
multiboot1_info.mmap_length = sizeof(*mmap) * memmap_entries;
multiboot1_info.mmap_length = mb_mmap_len;
multiboot1_info.mmap_addr = ((uint32_t)(size_t)mmap);
multiboot1_info.flags |= (1 << 0) | (1 << 6);