get memory map from grub 2

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.
jayt
Posts: 17
Joined: Mon Aug 26, 2013 1:40 am

Re: get memory map from grub 2

Post by jayt »

I'm using Linux.
I found a 0.9.7 GRUB but the problem stays the same.

The kernel doesn't get the memory map right.
I know it should be simple but it seams it isn't.

As seen on my screenshot in the last posting, the magic number from GRUB is right, so
the address of the memory info structure should be right too.

I'm still searching the error.
User avatar
dozniak
Member
Member
Posts: 723
Joined: Thu Jul 12, 2012 7:29 am
Location: Tallinn, Estonia

Re: get memory map from grub 2

Post by dozniak »

I didn't see you printing this magic in your kernel_main though. Are you sure it's passed in correctly?
Learn to read.
jayt
Posts: 17
Joined: Mon Aug 26, 2013 1:40 am

Re: get memory map from grub 2

Post by jayt »

I think the two arguments passed from the kernel loader to the C kernel are in right order.
Here is my kernel start:

Code: Select all

typedef struct memory_map_t_kernel
{
   u32int size;
   //unsigned long base_addr_low;
   //unsigned long base_addr_high;
   u64int addr;
   // unsigned long length_low;
   // unsigned long length_high;
   u64int len; //holds both halves.
   u32int type;
} memory_map_t_kernel;


struct memory_map_kernel memory_map_kernel[MAX_MEMORY_MAP];
s32int memory_map_index = -1;

int kernel_main (multiboot_info_t* mbt, unsigned int magic)
{
	u8int *first_frame, *second_frame;
	u32int size;
	u8int buf[256];
	u8int color;
	
	u64int mmap_address = mbt->mmap_addr;
	u64int mmap_length = mbt->mmap_length;
	
	u64int memory_kb;
	
	/* memory_kb = get_memory_size_64mb (); */
	
	/* get memory map from grub */
	
	terminal_initialize ();
	
	
	terminal_writestring ("sizeof u32int: ");
	ltoa (sizeof (u32int), buf, 10);
	terminal_writestring (buf);
	terminal_writestring ("\n");
	
	terminal_writestring ("sizeof u64int: ");
	ltoa (sizeof (u64int), buf, 10);
	terminal_writestring (buf);
	terminal_writestring ("\n");
	
	terminal_writestring ("mbt: ");
	ltoa (mbt, buf, 16);
	terminal_writestring (buf);
	terminal_writestring ("\n");
	
	terminal_writestring ("magic: ");
	ltoa (magic, buf, 16);
	terminal_writestring (buf);
	terminal_writestring ("\n");
	
	terminal_writestring ("memory map address: ");
	
	memory_map_t_kernel *mmap;
	mmap = (memory_map_t_kernel *) mbt->mmap_addr;
	
	ltoa (mbt->mmap_addr, buf, 16);
	terminal_writestring (buf);
	terminal_writestring ("\n");
	
	terminal_writestring ("mmap_addr + mmap_length: ");
	ltoa (mbt->mmap_addr + mbt->mmap_length, buf, 16);
	terminal_writestring (buf);
	terminal_writestring ("\n");
	
	if ((u64int) mmap >= (u64int) (mmap_address + mmap_length))
	{
		terminal_writestring ("ERROR mmap greater or equal mmap_addr + mmap_length!\n");
	}

	while ((u64int) mmap < (u64int) (mmap_address + mmap_length))
	{
		terminal_writestring ("memory map: ");
		
		/* mmap = (multiboot_memory_map_t*) ( (unsigned int)mmap + mmap->size + sizeof(unsigned int) ); */
		
		mmap = (memory_map_t_kernel*) ( (u32int)mmap + mmap->size + sizeof(u32int));
		
		ltoa (mmap->addr, buf, 16);
		terminal_writestring (buf);
		terminal_writestring (" ");
		ltoa (mmap->len, buf, 16);
		terminal_writestring (buf);
		terminal_writestring ("  ");
		ltoa (mmap->type, buf, 10);
		terminal_writestring (buf);
		terminal_writestring ("\n");
	}
I don't know what is wrong here. It just looks to me like the code in the tutorial here.
But it wont work right.
User avatar
darkinsanity
Member
Member
Posts: 45
Joined: Wed Sep 17, 2008 3:59 am
Location: Germany

Re: get memory map from grub 2

Post by darkinsanity »

I also use GRUB 2 and I recommend using this header just to be sure that you don't have any errors in your structs (I translated it to FreeBASIC to use it).
Looking at your code this caught my eye:

Code: Select all

mmap = (memory_map_t_kernel*) ( (u32int)mmap + mmap->size + sizeof(u32int));
Where does that sizeof(u32int) come from? Replacing that line with this should work:

Code: Select all

mmap++;
Also, this should happen AFTER the debug output, otherwise you're skipping the first entry of the map! To me it seems that you're destroying your mmap-Pointer with that sizeof(u32int) before the output.

edit: To minimize the chance that this is the fault of GRUB, try copying your kernel into this image. It's an outdated test-image of my kernel but the memory-map stuff worked 100%, so if it fails with this image, the problem is most likely hidden in your code.
jayt
Posts: 17
Joined: Mon Aug 26, 2013 1:40 am

Re: get memory map from grub 2

Post by jayt »

I tried it with your ISO grub image, but I got still no memory map.
Thanks for your tipp with the ++mmap;.

I tried a different loader + loader linker and got a different output of the kernel.

I think my kernel loader + link table are not right:

Code: Select all

[BITS 32]
global loader           ; making entry point visible to linker

; setting up the Multiboot header - see GRUB docs for details
MODULEALIGN equ  1<<0                   ; align loaded modules on page boundaries
MEMINFO     equ  1<<1                   ; provide memory map
FLAGS       equ  MODULEALIGN | MEMINFO  ; this is the Multiboot 'flag' field
MAGIC       equ    0x1BADB002           ; 'magic number' lets bootloader find the header
CHECKSUM    equ -(MAGIC + FLAGS)        ; checksum required

section .text
align 4
MultiBootHeader:
   dd MAGIC
   dd FLAGS
   dd CHECKSUM

; reserve initial kernel stack space
STACKSIZE equ 0x4000                  ; that's 16k.

global _loader
_loader:
   ;hlt								  ; debug
   
   mov esp, stack+STACKSIZE           ; set up the stack
   push dword eax                           ; pass Multiboot magic number
   push dword ebx                           ; ebx pass Multiboot info structure
 
	;hlt
 
   extern kernel_main
   call  kernel_main                  ; call kernel proper
   hlt                                ; halt machine should kernel return

section .bss
align 32
stack:
   resb STACKSIZE                     ; reserve 16k stack on a quadword boundary



; linker table =======================================================================

/* The bootloader will look at this image and start execution at the symbol
   designated as the entry point. */
ENTRY(_loader)

/* Tell where the various sections of the object files will be put in the final
   kernel image. */
SECTIONS
{
	/* Begin putting sections at 1 MiB, a conventional place for kernels to be
	   loaded at by the bootloader. */
	. = 1M;

	/* First put the multiboot header, as it is required to be put very early
	   early in the image or the bootloader won't recognize the file format.
	   Next we'll put the .text section. */
	.text BLOCK(4K) : ALIGN(4K)
	{
		*(.MultiBootHeader)
		*(.text)
	}

	/* Read-only data. */
	.rodata BLOCK(4K) : ALIGN(4K)
	{
		*(.rodata)
	}

	/* Read-write data (initialized) */
	.data BLOCK(4K) : ALIGN(4K)
	{
		*(.data)
	}

	/* Read-write data (uninitialized) and stack */
	.bss BLOCK(4K) : ALIGN(4K)
	{
		*(COMMON)
		*(.bss)
		*(.bootstrap_stack)
	}

	/* The compiler may produce other sections, by default it will put them in
	   a segment with the same name. Simply add stuff here as needed. */
}
So the error is here I think.
If someone could look at it, this would help me.
jayt
Posts: 17
Joined: Mon Aug 26, 2013 1:40 am

Re: get memory map from grub 2

Post by jayt »

I putted the following lines in my kernel C file:

Code: Select all

#define CHECK_FLAG(flags,bit)   ((flags) & (1 << (bit))) /* Check if the bit BIT in FLAGS is set. */
        
         if (CHECK_FLAG (mbt->flags, 0))
	{
		ltoa ((u32int) mbt->mem_lower + (u32int) mbt->mem_upper, buf, 10);
		terminal_writestring ("memory in KB: ");
		terminal_writestring (buf);
		terminal_writestring ("\n");
	}
The if statement executes and prints out 8 KB of RAM!!!

I think my mbt pointer got from GRUB contains nothing but trash.
This _is_ the problem.

How can I fix this?
jayt
Posts: 17
Joined: Mon Aug 26, 2013 1:40 am

Re: get memory map from grub 2

Post by jayt »

Stop! this was the wrong output.
It shows 523836 KB RAM. I setted 512 MB RAM in Bochs.

But the memory map is still not valid.
jayt
Posts: 17
Joined: Mon Aug 26, 2013 1:40 am

Re: get memory map from grub 2

Post by jayt »

I found a correct i64toa () function and now the right memory map values are shown!
This is solved now.

I checked the output of my kernel with the GRUB memory map printed with:
lsmmap.

They are the same.
Post Reply