grub giving garbage values for size of main memory

Programming, for all ages and all languages.
Post Reply
681anki
Posts: 7
Joined: Sun Aug 12, 2012 1:46 am

grub giving garbage values for size of main memory

Post by 681anki »

Code: Select all

#include "multiboot.h"
#include "lib/print.h"
void kmain(multiboot_info_t* mbd, unsigned int magic)
	{
	  unsigned long total_memory_size = ((unsigned long)mbd->mem_lower + (unsigned long)mbd->mem_upper);

          printunlong(total_memory_size);  // <- this statement *** 
         }

this is my kernel code to get size of main memory..but i'm getting value of

"this statement" as "4294967294179488" ....Does that value has some meaning or its meaningless...
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: grub giving garbage values for size of main memory

Post by Brendan »

Hi,
681anki wrote:

Code: Select all

	  unsigned long total_memory_size = ((unsigned long)mbd->mem_lower + (unsigned long)mbd->mem_upper);
These fields are both 32-bit unsigned integers. For GCC, "unsigned long" is probably a 64 bit integer. This means that you're loading the highest 32-bits with trash.

These fields are only valid of bit 0 of flags (first field of the Multiboot information structure) is set. You don't test if this bit is set, so you don't know if the "mem_lower" and "mem_upper" fields are supposed to be valid anyway.

If the "mem_upper" field is valid, it only tells you how much RAM exists from 1 MiB to the first hole. It ignores any RAM above the first hole. For example, if the computer has 123 GiB of RAM then it might report 3 GiB, or 14 MiB, and ignore the rest.

I'd strongly recommend using the memory map (e.g. the "mmap_length" and "mmap_addr" fields) if it's possible/present instead. If the memory map isn't present and you have no other option, refuse to boot (because I've seen GRUB's code and wouldn't trust the "mem_lower" and "mem_upper" fields even if GRUB does say they're valid).


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
NickJohnson
Member
Member
Posts: 1249
Joined: Tue Mar 24, 2009 8:11 pm
Location: Sunnyvale, California

Re: grub giving garbage values for size of main memory

Post by NickJohnson »

Brendan wrote:These fields are both 32-bit unsigned integers. For GCC, "unsigned long" is probably a 64 bit integer. This means that you're loading the highest 32-bits with trash.
Wait, what? I'm pretty sure unsigned long on 32-bit GCC is a 32-bit integer (unsigned long long is 64-bit), and casting any integer to an integer of a larger width should never change its numerical value. I suspect the problem is more with the fields not being filled in correctly by GRUB, or the OP's print function having issues.

Also, the calculation for how much memory you have is mem_upper - mem_lower, not mem_lower + mem_upper... (not that that sort of error would give you this problem.)
User avatar
thepowersgang
Member
Member
Posts: 734
Joined: Tue Dec 25, 2007 6:03 am
Libera.chat IRC: thePowersGang
Location: Perth, Western Australia
Contact:

Re: grub giving garbage values for size of main memory

Post by thepowersgang »

May I just quickly note, the forum rules say to avoid colours for a reason (See attachment)

That said, make sure you actually have a valid multiboot structure (check the magic and check the flag bits to ensure the data is valid)
Attachments
Using a black background theme
Using a black background theme
osdev-crap_font.png (6.98 KiB) Viewed 3039 times
Kernel Development, It's the brain surgery of programming.
Acess2 OS (c) | Tifflin OS (rust) | mrustc - Rust compiler
Currently Working on: mrustc
Nable
Member
Member
Posts: 453
Joined: Tue Nov 08, 2011 11:35 am

Re: grub giving garbage values for size of main memory

Post by Nable »

printunlong - what is it it and how it could print more digits then uint32 can hold?
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: grub giving garbage values for size of main memory

Post by Brendan »

Hi,
NickJohnson wrote:
Brendan wrote:These fields are both 32-bit unsigned integers. For GCC, "unsigned long" is probably a 64 bit integer. This means that you're loading the highest 32-bits with trash.
Wait, what? I'm pretty sure unsigned long on 32-bit GCC is a 32-bit integer (unsigned long long is 64-bit), and casting any integer to an integer of a larger width should never change its numerical value. I suspect the problem is more with the fields not being filled in correctly by GRUB, or the OP's print function having issues.
For some reason I assumed a 64-bit GCC was being used due to the "4294967294179488" value being displayed, and didn't look at the code closely enough. :oops:
NickJohnson wrote:Also, the calculation for how much memory you have is mem_upper - mem_lower, not mem_lower + mem_upper... (not that that sort of error would give you this problem.)
From a version of the multiboot specification:
"If bit 0 in the ‘flags’ word is set, then the ‘mem_*’ fields are valid. ‘mem_lower’ and ‘mem_upper’ indicate the amount of lower and upper memory, respectively, in kilobytes. Lower memory starts at address 0, and upper memory starts at address 1 megabyte. The maximum possible value for lower memory is 640 kilobytes. The value returned for upper memory is maximally the address of the first upper memory hole minus 1 megabyte. It is not guaranteed to be this value."

The correct calculation to determine "the number of KiB of RAM below the first hole, or less" would be "mbd->mem_lower + mbd->mem_upper" (which is literally the number of KiB below 0x00100000 plus the number of KiB between 0x00100000 and *somewhere*). Because both fields are KiB and not bytes, and because there's at least one hole below 0xFFFFFFFF, you shouldn't need to worry about overflows for this calculation if you use 32-bit (signed or unsigned) arithmetic.

The main point is that if GRUB says that the "mem_upper" and "mem_lower" fields fields are valid, and if these fields actually are valid; then "the number of KiB of RAM below the first hole, or less" is virtually useless anyway. There's no point bothering to fix "virtually useless" code.

There are only 3 values that might be useful:
  • The amount of RAM that is physically installed. To get this value you need to use SMBIOS, chipset specific knowledge, or guesswork/estimation.
  • The amount of RAM that is actually usable. To get this value you need parse the memory map that GRUB got from the BIOS (e.g. from "int 0x15, eax=0xE820") and find the sum of areas marked as either "usable RAM" or "ACPI reclaimable".
  • The amount of RAM that is currently free. To get this value early during boot you'd need parse the memory map that GRUB got from the BIOS (e.g. from "int 0x15, eax=0xE820") and find the sum of areas marked as "usable RAM" (but not "ACPI reclaimable"); then subtract the amount of RAM used by your own code (including stack, modules, etc), and subtract the amount of RAM GRUB left "in use" for its boot information table. Later (after boot and/or after you've setup your own physical memory manager to track free pages) you should have better ways of doing this.
Finally, in my opinion (for a "production quality" OS), GRUB's code is relatively dodgy anyway. The code that sets the "mem_upper" and "mem_lower" fields doesn't use many of the possible BIOS functions and has too few sanity checks. In a similar way, the code that gets the memory map from the BIOS "int 0x15, eax=0xE820" function doesn't do many sanity checks and doesn't do *any* post-processing (e.g. doesn't sort the list, doesn't remove redundant entries, doesn't merge "similar but adjacent" entries, doesn't check for or handle overlapping areas, etc). In addition to these problems (or possibly because of these problems) GRUB also allows the user to screw it all up (or possibly allows the user to override it when GRUB screws it up) via. an "uppermem" command.

Note: Despite my comments above; GRUB's memory detection code should work fine on almost all modern computers, and is adequate for a hobby OS; especially if you refuse to use the "mem_upper" and "mem_lower" fields, and especially if you sanitize the memory map yourself.


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
681anki
Posts: 7
Joined: Sun Aug 12, 2012 1:46 am

Re: grub giving garbage values for size of main memory

Post by 681anki »

Nable wrote:printunlong - what is it it and how it could print more digits then uint32 can hold?
now i get it correctly...there was wrong code in my function so..thanks to u ..and all experts...
Tosi
Member
Member
Posts: 255
Joined: Tue Jun 15, 2010 9:27 am
Location: Flyover State, United States
Contact:

Re: grub giving garbage values for size of main memory

Post by Tosi »

Use the memory map from GRUB rather than the memory size fields; somebody else on this forum mentioned that they only give the amount of memory below the first hole above 1 MB, which there might not be any on an emulator, giving correct values, while real hardware gives you too small of a value.
Post Reply