Physical Memory Map

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
Caleb1994
Member
Member
Posts: 83
Joined: Sun Feb 13, 2011 4:55 pm

Physical Memory Map

Post by Caleb1994 »

Hey guys, here's the story: I set up a basic Physical Memory Manager, and proceeded to retrieve the memory map, and mark blocks as reserved where needed. I ran into a snag. GRUB is telling me that the memory map is unsupported in qemu(my main emulator) ("Error 10: Unsupported Multiboot feature requested" or something to that extent, I know it's error 10 lol). I also tried it on my physical machine and in virtual box. Is there any other way to retrieve the memory map (not using the BIOS, since if grub doesn't support it, that means the BIOS doesn't since grub uses the bios).

I know the BIOS must get the information somewhere. I thought maybe the CMOS, but according to the OSDev wiki ("Detecting Memory") the CMOS "also has no information about any other reserved regions." which means it doesn't know what memory is where :/

Anybody know of a way that will work reliably from machine to machine? I thought if there was a way, GRUB would have it, but I guess not. lol

Oh! Also, here is my multiboot header:

Code: Select all

    MULTIBOOT_PAGE_ALIGN	equ 1<<0
    MULTIBOOT_MEMORY_INFO	equ 1<<1
    MULTIBOOT_AOUT_KLUDGE	equ 1<<16
    MULTIBOOT_MEMORY_MAP	equ 1<<6
    MULTIBOOT_HEADER_MAGIC	equ 0x1BADB002
    MULTIBOOT_HEADER_FLAGS	equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO | MULTIBOOT_AOUT_KLUDGE | MULTIBOOT_MEMORY_MAP
    MULTIBOOT_CHECKSUM	equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: Physical Memory Map

Post by gerryg400 »

You're getting confused between the flags that you should pass to grub in the multiboot header and the flags that grub returns to you in the multiboot information structure.

Specifically

Code: Select all

MULTIBOOT_MEMORY_MAP   equ 1<<6
is a flag that grub returns to you if it finds memory and fills in memory in the mmap* fields of the multiboot information structure.

You are already requesting the memory map by passing

Code: Select all

MULTIBOOT_MEMORY_INFO   equ 1<<1
Just remove the MULTIBOOT_MEMORY_MAP from your MULTIBOOT_HEADER_FLAGS and you should be okay.
If a trainstation is where trains stop, what is a workstation ?
Caleb1994
Member
Member
Posts: 83
Joined: Sun Feb 13, 2011 4:55 pm

Re: Physical Memory Map

Post by Caleb1994 »

Thank you! I misread the Multiboot Specs! I looked back at it and then felt stupid #-o

And a quick reply! [-o< =D>

because of this I actually wrote macros to test for the validity of fields in the multiboot structure (which I should've done before :P) lol

Now, after I wrote those macros, It seems that GRUB is telling me the information is good, but the mmap_length parameter is NULL. Here is the multiboot_info structure i have:

Code: Select all

/* Defines all possible information structures passed to the kernel
	by the multiboot compliant bootloader.
*/
typedef volatile struct
{
	u32 flags;			// Flags, specifying which fields below are valid
	u32 memlo;			// The amount of physical memory flags[0]
	u32 memhi;
	u32 boot_device;		// Boot Device, flags[1]
	u32 cmdline;			// flags[2]
	u32 mods_count;			// modules loaded with kernel, flags[3]
	u32 mods_address;
	u32 syms0, syms1, syms2;	// symbol table. flags[4] or flags[5]
	u32 mmap_length;		// memory map. flags[6]
	u32 mmap_addr;
	u32 drives_length;		// first drive structure. flags[7]
	u32 drives_addr;
	u32 config_table;		// ROM config table. flags[8]
	u32 bootloader_name;		// flags[9]
	u32 apm_table;			// Advanced Power Managment table. flags[10]
	u32 vbe_control_info;		// Video BIOS extensions. flags[11]
	u32 vbe_mode_info;
	u16 vbe_mode;
	u16 vbe_interface_seg,
		vbe_interface_off,
		vbe_interface_len;
} multiboot_info;
and here is my macros to check the field validity ( I don't see a reason these would be the problem, but whatever lol)

Code: Select all

/*! multiboot_info flags bits */
#define MULTIBOOT_MEMSZ	(1<<0)		// Memory size feilds (memlo, memhi)
#define MULTIBOOT_BOOTDEV (1<<1)	// Boot Device field
#define MULTIBOOT_CMDLINE (1<<2)	// Command line field
#define MULTIBOOT_BOOTMODS (1<<3)	// Boot modules loaded
#define MULTIBOOT_AOUTSYMS (1<<4)	// AOUT style symbol table
#define MULTIBOOT_ELFSYMS (1<<5)	// ELF Style symbol table
#define MULTIBOOT_MEMMAP (1<<6)		// Memory map fields
#define MULTIBOOT_DRIVESTRUCT (1<<7)	// Drive Structure fields
#define MULTIBOOT_ROMCFG (1<<8)		// Location of the rom config table
#define MULTIBOOT_BOOTNAME (1<<9)	// Name of the bootloader
#define MULTIBOOT_APMTABLE (1<<10)	// APM table
#define MULTIBOOT_VBEINFO (1<<11)	// VideoBiosExtensions
/*! Check if a field is valid */
#define MULTIBOOT_VALID(mboot, field)	(mboot->flags & field)
In the GRUB command line, I can type "displaymem" and I get the memory map just fine, so there is no reason why it shouldn't be passing the map to me! :/ but when I do this:

k_printf("info->mmap_addr=0x%X\ninfo->mmap_length=%u\n", info->mmap_addr, info->mmap_length);

I get:

0x90
0

any ideas? I have googled for "GRUB memory map length zero" and the like, but haven't found anything useful yet.
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: Physical Memory Map

Post by gerryg400 »

Your multiboot info structure is defined incorrectly. The mmap_length field is supposed to be 44 bytes from the beginning. Yours is 40. Also make sure you 'pack' the structure.
If a trainstation is where trains stop, what is a workstation ?
Caleb1994
Member
Member
Posts: 83
Joined: Sun Feb 13, 2011 4:55 pm

Re: Physical Memory Map

Post by Caleb1994 »

You are correct! I was missing one 'sym' value! And thanks for the tip on the packing! my new structure looks like this:

Code: Select all

/* Defines all possible information structures passed to the kernel
	by the multiboot compliant bootloader.
*/
typedef volatile struct
{
	u32 flags;			// Flags, specifying which fields below are valid
	u32 memlo;			// The amount of physical memory flags[0]
	u32 memhi;
	u32 boot_device;		// Boot Device, flags[1]
	u32 cmdline;			// flags[2]
	u32 mods_count;			// modules loaded with kernel, flags[3]
	u32 mods_address;
	u32 syms0, syms1, syms2, syms3;	// symbol table. flags[4] or flags[5]
	u32 mmap_length;		// memory map. flags[6]
	u32 mmap_addr;
	u32 drives_length;		// first drive structure. flags[7]
	u32 drives_addr;
	u32 config_table;		// ROM config table. flags[8]
	u32 bootloader_name;		// flags[9]
	u32 apm_table;			// Advanced Power Managment table. flags[10]
	u32 vbe_control_info;		// Video BIOS extensions. flags[11]
	u32 vbe_mode_info;
	u16 vbe_mode;
	u16 vbe_interface_seg,
		vbe_interface_off,
		vbe_interface_len;
} __attribute__( (packed) ) multiboot_info;
Okay, I'm now getting a base address of 0x2BF74 and a length of 144. Sounds reasonable. I just have to go read the multiboot specs to figure out exactly how these entries are stored. xD

Thanks a lot! (P.S. I love your signature. lol)
Caleb1994
Member
Member
Posts: 83
Joined: Sun Feb 13, 2011 4:55 pm

Re: Physical Memory Map

Post by Caleb1994 »

Okay, I don't understand this. Everything seems to be correct. According to the Multiboot Specs (http://www.gnu.org/software/grub/manual ... iboot.html) This is the structure for the memory map descriptors:

Code: Select all

/*! Defines a memory region descriptor from the memory map */
struct memory_region {
	u32	size;
	u32	startLo;	//base address
	u32	startHi;
	u32	sizeLo;		//length (in bytes)
	u32	sizeHi;
	u32	type;
} __attribute__( (packed) );
and this seems to work for the first descriptor. According to the manual, size is the size of the structure without the size member (it's wierd i know lol), and does not necessaraly equal 20 (as you would expect). This value is 20 in the first descriptor, and After the first descriptor, all the other descriptors are NULL. every value in the structure is zero. When I use the "displaymem" command in grub I get 6 entry with valid values, but I'm not getting all of those values in my kernel. The first one lines up with grub, though. Here is my printing loop:

Code: Select all

	struct memory_region* region = (struct memory_region*)(info->mmap_addr);
	u32 i = 0, length = info->mmap_length / sizeof(struct memory_region);
	for(i; i < length; ++i)
	{
		k_printf("\t\t%s: Base Address: 0x%X%X,\n\t\t\tLength: 0x%X%X\n", region->type == 1 ? "Usable RAM" : "Reserved",
									region->startHi, region->startLo,
									region->sizeHi, region->sizeLo);
		pmm_init_region (region->startLo, region->sizeLo);
		region += region->size + 4;
	}
k_printf: exactly what you would expect. printf style console output
pmm_init_region: Physical Memory Manager function used to free up a region of memory for use
info: pointer to the multiboot info structure that grub passed to me.

I have a screenshot of my output attached to the post. I have been staring at this all morning and most of yesterday, and just can't see anything wrong! Lol I can't move on with out a memory manager :(

By the way, I just realized that the way I'm calculating "length" isn't going to work if "size" isn't always 20. But that isn't going to affect my output. I will fix it, though. xD
Attachments
Image of my booted kernel
Image of my booted kernel
Caleb1994
Member
Member
Posts: 83
Joined: Sun Feb 13, 2011 4:55 pm

Re: Physical Memory Map

Post by Caleb1994 »

1. I mentioned that at the end of my post.
2. You are definetly correct. lol Sorry! I was just trying to see my values, and didn't completely think it through. It's odd though, that the value matched up anyway. I guess this is a sign that I need to add the "padding" feature into my printf function so I can tell it to pad with '0' characters xD
3. THIS is probably the culprit. I feel REALLY dumb. lol

Just changed that to: region = (struct memory_region*)((u8*)region + region->size + 4);

Fixed #1 and #3, and am in the process of fixing #2! Although, without fixing #2, it works! Thanks tons man!
Caleb1994
Member
Member
Posts: 83
Joined: Sun Feb 13, 2011 4:55 pm

Re: Physical Memory Map

Post by Caleb1994 »

True. I had never looked this deep into the printf function. It more lengthy then i assumed :O lol

I was out most of the day yesterday, and today I just finished implementing some more std. headers that would be very useful when writing printf (ctype.h, string.h mostly).

Thanks for the tips, I'm on to finishing printf/writing my paging initialization functions! Once I got passed the initial "Holy crap where do I start!?" feeling, this is getting to be a whole lot of fun! :)
Post Reply