multiboot2: add the basic memory info tag
Signed-off-by: Andy-Python-Programmer <andypythonappdeveloper@gmail.com>
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
//////////////////////////////////////////////
