diff --git a/stage23/mm/pmm.h b/stage23/mm/pmm.h index 5c789c13..5f6bcfa4 100644 --- a/stage23/mm/pmm.h +++ b/stage23/mm/pmm.h @@ -17,6 +17,13 @@ #define MEMMAP_EFI_RECLAIMABLE 0x2000 #define MEMMAP_EFI_BOOTSERVICES 0x2001 +struct meminfo { + size_t uppermem; + size_t lowermem; +}; + +struct meminfo mmap_get_info(size_t mmap_count, struct e820_entry_t *mmap); + #if bios == 1 extern struct e820_entry_t memmap[]; extern size_t memmap_entries; diff --git a/stage23/mm/pmm.s2.c b/stage23/mm/pmm.s2.c index fb073684..7dc7341f 100644 --- a/stage23/mm/pmm.s2.c +++ b/stage23/mm/pmm.s2.c @@ -611,6 +611,35 @@ void *ext_mem_alloc_type(size_t count, uint32_t type) { panic("High memory allocator: Out of memory"); } + +/// Compute and returns the amount of upper and lower memory till +/// the first hole. +struct meminfo mmap_get_info(size_t mmap_count, struct e820_entry_t *mmap) { + struct meminfo info = {0}; + + for (size_t i = 0; i < mmap_count; i++) { + if (mmap[i].type == MEMMAP_USABLE) { + // NOTE: Upper memory starts at address 1MiB and the + // value of uppermem is the address of the first upper memory + // hole minus 1MiB. + if (mmap[i].base < 0x100000) { + if (mmap[i].base + mmap[i].length > 0x100000) { + size_t low_len = 0x100000 - mmap[i].base; + + info.lowermem += low_len; + info.uppermem += mmap[i].length - low_len; + } else { + info.lowermem += mmap[i].length; + } + } else { + info.uppermem += mmap[i].length; + } + } + } + + return info; +} + bool memmap_alloc_range(uint64_t base, uint64_t length, uint32_t type, bool free_only, bool do_panic, bool simulation, bool new_entry) { if (length == 0) return true; diff --git a/stage23/protos/multiboot1.c b/stage23/protos/multiboot1.c index c9828652..71eac9aa 100644 --- a/stage23/protos/multiboot1.c +++ b/stage23/protos/multiboot1.c @@ -246,32 +246,22 @@ nofb:; 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; - // 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 += mmap[i].len - low_len; - } else { - memory_lower += mmap[i].len; - } - } else { - memory_upper += mmap[i].len; - } - } } - multiboot1_info.mem_lower = memory_lower / 1024; - multiboot1_info.mem_upper = memory_upper / 1024; + { + struct meminfo memory_info = mmap_get_info(mb_mmap_count, raw_memmap); + + // Convert the uppermem and lowermem fields from bytes to + // KiB. + multiboot1_info.mem_lower = memory_info.lowermem / 1024; + multiboot1_info.mem_upper = memory_info.uppermem / 1024; + } multiboot1_info.mmap_length = mb_mmap_len; multiboot1_info.mmap_addr = ((uint32_t)(size_t)mmap); diff --git a/stage23/protos/multiboot2.c b/stage23/protos/multiboot2.c index a03b1a45..4e80da34 100644 --- a/stage23/protos/multiboot2.c +++ b/stage23/protos/multiboot2.c @@ -59,6 +59,7 @@ static size_t get_multiboot2_info_size( ALIGN_UP(sizeof(struct multiboot_tag_old_acpi) + 20, MULTIBOOT_TAG_ALIGN) + // old ACPI info ALIGN_UP(sizeof(struct multiboot_tag_elf_sections) + section_hdr_size, MULTIBOOT_TAG_ALIGN) + // ELF info ALIGN_UP(modules_size, MULTIBOOT_TAG_ALIGN) + // modules + ALIGN_UP(sizeof(struct multiboot_tag_basic_meminfo), MULTIBOOT_TAG_ALIGN) + // basic memory info ALIGN_UP(sizeof(struct multiboot_tag_mmap) + sizeof(struct multiboot_mmap_entry) * 256, MULTIBOOT_TAG_ALIGN) + // MMAP #if uefi == 1 ALIGN_UP(sizeof(struct multiboot_tag_efi_mmap) + (efi_desc_size * 256), MULTIBOOT_TAG_ALIGN) + // EFI MMAP @@ -120,12 +121,15 @@ void multiboot2_load(char *config, char* cmdline) { case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME: case MULTIBOOT_TAG_TYPE_MODULE: case MULTIBOOT_TAG_TYPE_MMAP: + case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO: #if uefi == 1 case MULTIBOOT_TAG_TYPE_EFI_MMAP: #if defined (__i386__) case MULTIBOOT_TAG_TYPE_EFI32: + case MULTIBOOT_TAG_TYPE_EFI32_IH: #elif defined (__x86_64__) case MULTIBOOT_TAG_TYPE_EFI64: + case MULTIBOOT_TAG_TYPE_EFI64_IH: #endif #endif case MULTIBOOT_TAG_TYPE_FRAMEBUFFER: @@ -430,7 +434,7 @@ void multiboot2_load(char *config, char* cmdline) { // Create new ACPI info tag ////////////////////////////////////////////// { - void *new_rsdp = acpi_get_rsdp(); + void *new_rsdp = acpi_get_rsdp_v2(); if (new_rsdp != NULL) { uint32_t size = sizeof(struct multiboot_tag_new_acpi) + sizeof(struct rsdp); // XSDP is 36 bytes wide @@ -518,13 +522,13 @@ void multiboot2_load(char *config, char* cmdline) { efi_exit_boot_services(); #endif + size_t mb_mmap_count; + struct e820_entry_t *raw_memmap = get_raw_memmap(&mb_mmap_count); + ////////////////////////////////////////////// // Create memory map tag ////////////////////////////////////////////// { - size_t mb_mmap_count; - struct e820_entry_t *raw_memmap = get_raw_memmap(&mb_mmap_count); - if (mb_mmap_count > 256) { panic("multiboot2: too many memory map entries"); } @@ -549,6 +553,24 @@ void multiboot2_load(char *config, char* cmdline) { append_tag(info_idx, mmap_tag); } + ////////////////////////////////////////////// + // Create basic memory info tag + ////////////////////////////////////////////// + { + struct meminfo meminfo = mmap_get_info(mb_mmap_count, raw_memmap); + struct multiboot_tag_basic_meminfo *tag = (struct multiboot_tag_basic_meminfo *)(mb2_info + info_idx); + + tag->type = MULTIBOOT_TAG_TYPE_BASIC_MEMINFO; + tag->size = sizeof(struct multiboot_tag_basic_meminfo); + + // Convert the uppermem and lowermem fields from bytes to + // KiB. + tag->mem_upper = (uint32_t)(meminfo.uppermem / 1024); + tag->mem_lower = (uint32_t)(meminfo.lowermem / 1024); + + append_tag(info_idx, tag); + } + ////////////////////////////////////////////// // Create EFI memory map tag //////////////////////////////////////////////