pmm: Implement get_raw_memmap() and use it in mb1 proto
diff --git a/stage23/mm/pmm.h b/stage23/mm/pmm.h
index bef06a3a..f0b8a30d 100644
--- a/stage23/mm/pmm.h
+++ b/stage23/mm/pmm.h
@@ -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);
diff --git a/stage23/mm/pmm.s2.c b/stage23/mm/pmm.s2.c
index 02a5937f..cd2f8a7e 100644
--- a/stage23/mm/pmm.s2.c
+++ b/stage23/mm/pmm.s2.c
@@ -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);
}
diff --git a/stage23/protos/multiboot1.c b/stage23/protos/multiboot1.c
index 4420f16f..35777d64 100644
--- a/stage23/protos/multiboot1.c
+++ b/stage23/protos/multiboot1.c
@@ -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;
-
- 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;
+ // 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 (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);
