Reading Invalid Memory Map Data from Grub2

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
InfoBroad
Posts: 5
Joined: Sun Jul 19, 2026 3:30 pm

Reading Invalid Memory Map Data from Grub2

Post by InfoBroad »

I have been working off of the Meaty Skeleton Project, and have gotten to the point where paging is set up with the first 4MB Identity-Mapped and the kernel also mapped to higher-half. I tried to get a memory map from Grub2, but when printing the info out to the vga terminal, I got back invalid data (type 0 memory).

I did split my length and address parameters in my mmap entry struct. No compiler errors or warnings show up. If I could get some pointers on how to get and print the correct data, that would be great!

Also, the project can be found at https://github.com/ResistingGuide4/rOSes

earlyinit.c:

Code: Select all

#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>

#include <kernel/multiboot2.h>
#include <kernel/testing.h>

struct multiboot_tag *multiboot_find_tag(void *mbd, uint32_t type) {
    /* The multiboot info structure begins with a 32-bit integer
    *  indicating the total size of the structure. This is then
    *  followed by a 32-bit reserved region and then by the tags. */
	struct multiboot_tag *tag = (void *)mbd + 8;
	while ((void *)tag < (void *)mbd + *((uint32_t *)mbd)) {
		if (tag->type == type) {
			return tag;
		}
		tag = (void *)tag + tag->size;
		/* Tags are always aligned on 8-byte boundaries. */
		if ((uintptr_t)tag % 8 > 0) {
			tag = (void *)tag + 8 - ((uintptr_t)tag % 8);
		}
	}
	return 0;
}

struct multiboot_tag_mmap *memory_map;
uint32_t multiboot_magic;

//Called after higher half far jump
void heap_init(void *mbd, uint32_t magic) {
    asm volatile("testing:");
    if (magic != MULTIBOOT2_BOOTLOADER_MAGIC) {
        abort();
    }
    
    struct multiboot_tag_mmap *tag_mmap =
	    (struct multiboot_tag_mmap *)multiboot_find_tag(
		mbd, MULTIBOOT_TAG_TYPE_MMAP);

	if (!tag_mmap) {
		abort();
	}

	memory_map = tag_mmap;
	multiboot_magic = magic;
}

//Called during main function
void readMMap() {
	printf("Magic: %d\n", multiboot_magic);
	struct multiboot_mmap_entry *entry =
	    (struct multiboot_mmap_entry *)(uintptr_t)memory_map->entries;
	while ((void *)entry < (void *)memory_map + memory_map->size) {
		printf("Start Addr Low: %d | Start Addr High: %d | Length Low: %d | Length High: %d | Type: %d.\n",
		    (unsigned int)entry->addr_low, (unsigned int)entry->addr_high, 
			(unsigned int)entry->len_low, (unsigned int)entry->len_high, (unsigned int)entry->type);
        
		entry = (void *)entry + memory_map->entry_size;
	}
}
Start of boot.S:

Code: Select all

# Declare constants for the multiboot 2 header.
.set FLAGS,    0  # this is the Multiboot 'flag' field
.set MAGIC,    0xE85250D6       # 'magic number' lets bootloader find the header
.set SIZE, header_end - header_start
.set CHECKSUM, -(MAGIC + FLAGS + SIZE) # checksum of above, to prove we are multiboot

# Declare a header as in the Multiboot Standard.
.section .multiboot,"a",@progbits
.align 8
header_start:
.long MAGIC
.long FLAGS
.long SIZE
.long CHECKSUM
# Tags go here
.align 8
.short 1
.short 0
.long 12
.long 6
# Ending tag
.align 8
.short 0
.short 0
.long 8
header_end:
Excerpt from multiboot2.h:

Code: Select all

struct multiboot_mmap_entry
{
  multiboot_uint32_t size;
  multiboot_uint32_t addr_low;
  multiboot_uint32_t addr_high;
  multiboot_uint32_t len_low;
  multiboot_uint32_t len_high;
#define MULTIBOOT_MEMORY_AVAILABLE              1
#define MULTIBOOT_MEMORY_RESERVED               2
#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE       3
#define MULTIBOOT_MEMORY_NVS                    4
#define MULTIBOOT_MEMORY_BADRAM                 5
  multiboot_uint32_t type;
} __attribute__((packed));
typedef struct multiboot_mmap_entry multiboot_memory_map_t;
VGA Output:
Screenshot From 2026-08-15 21-35-28.png
Screenshot From 2026-08-15 21-35-28.png (10 KiB) Viewed 2014 times
Octocontrabass
Member
Member
Posts: 6275
Joined: Mon Mar 25, 2013 7:01 pm

Re: Reading Invalid Memory Map Data from Grub2

Post by Octocontrabass »

InfoBroad wrote: ↑Sat Aug 15, 2026 7:47 pmI did split my length and address parameters in my mmap entry struct.
Why?
InfoBroad wrote: ↑Sat Aug 15, 2026 7:47 pmExcerpt from multiboot2.h:
Your struct definition doesn't match the layout described in the Multiboot2 specification.
InfoBroad
Posts: 5
Joined: Sun Jul 19, 2026 3:30 pm

Re: Reading Invalid Memory Map Data from Grub2

Post by InfoBroad »

Octocontrabass wrote: ↑Sun Aug 16, 2026 12:06 am
InfoBroad wrote: ↑Sat Aug 15, 2026 7:47 pmExcerpt from multiboot2.h:
Your struct definition doesn't match the layout described in the Multiboot2 specification.
Got it. I was using the functions in Detecting Memory (x86), and that included an updated version of the mmap entry struct that fixed a bug with gcc. Unfortunately, I didn't think to check the current specification to make sure the change made sense.
Octocontrabass wrote: ↑Sun Aug 16, 2026 12:06 am
InfoBroad wrote: ↑Sat Aug 15, 2026 7:47 pmI did split my length and address parameters in my mmap entry struct.
Why?
In the Detecting with GRUB section of Detecting Memory (x86), it said that the current multiboot specification uses a 64-bit integer for the length and address field. This can cause gcc to pack it incorrectly, as shown in this thread. The wiki page supplied an updated entry struct, but I think that was only for Multiboot 1.

Thanks for pointing that out. I'll test it as soon as I can get to my PC.
Octocontrabass
Member
Member
Posts: 6275
Joined: Mon Mar 25, 2013 7:01 pm

Re: Reading Invalid Memory Map Data from Grub2

Post by Octocontrabass »

InfoBroad wrote: ↑Sun Aug 16, 2026 6:13 amIn the Detecting with GRUB section of Detecting Memory (x86), it said that the current multiboot specification uses a 64-bit integer for the length and address field. This can cause gcc to pack it incorrectly, as shown in this thread. The wiki page supplied an updated entry struct, but I think that was only for Multiboot 1.
If it really was a GCC bug and not user error, it probably won't affect you anyway since that thread is ten years old. (Unless your copy of GCC is more than ten years old?)
Post Reply