multiboot2: add the basic memory info tag

Signed-off-by: Andy-Python-Programmer <andypythonappdeveloper@gmail.com>
This commit is contained in:
Andy-Python-Programmer 2021-10-07 13:04:41 +11:00
parent 2b88de7568
commit 0dd2bc6224
No known key found for this signature in database
GPG Key ID: 80E0357347554B89
4 changed files with 70 additions and 22 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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
//////////////////////////////////////////////