[SOLVED] Using memory map to calculate size of system RAM

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
User avatar
austanss
Member
Member
Posts: 377
Joined: Sun Oct 11, 2020 9:46 pm
Location: United States

[SOLVED] Using memory map to calculate size of system RAM

Post by austanss »

I wrote a function to parse my memory map, namely to print to serial output the contents, and return the size of system RAM in bytes.

Code: Select all

// @brief Parses the memory map and returns the amount of RAM in the system.
uint64_t mem_map_parse(Memory_Map_Descriptor* memmap, uint64_t map_size, uint64_t desc_size)
{
	uint8_t *startOfMemoryMap = (uint8_t *)memmap;
	uint8_t *endOfMemoryMap = startOfMemoryMap + map_size;

	uint8_t *offset = startOfMemoryMap;

	uint32_t counter = 0;
 	serial_msg("\n\nMEMORY MAP:\n-=-=-=-=-=-\n");

	while (offset < endOfMemoryMap)
	{
		Memory_Map_Descriptor *desc = (Memory_Map_Descriptor *)offset;

		hex_str_serial(desc->physical_start);
		serial_msg(": ");
		serial_msg(memory_types[desc->type]);
		serial_msg(" (");
		dec_str_serial(desc->count);
		serial_msg(")");
		serial_msg("\n");

		offset += desc_size;

		counter++;
	}

	offset -= desc_size;

	Memory_Map_Descriptor *desc = (Memory_Map_Descriptor *)offset;

	hex_str_serial(desc->physical_start);
	serial_msg(": ");
	serial_msg(memory_types[desc->type]);
	serial_msg(" (");
	dec_str_serial(desc->count);
	serial_msg(")");
	serial_msg("\n");

	return (((uint64_t)desc->physical_start) + ((desc->count * 0x1000)));
}
Aight so I have a function calling that function:

Code: Select all

void malloc_init(Memory_Map_Descriptor* memmap, uint64_t map_size, uint64_t desc_size)
{
	serial_msg("\n");
	dec_str_serial(((mem_map_parse(memmap, map_size, desc_size)) / 1024) / 1024);
	serial_msg("MiB of RAM\n");
}
And it prints:

Code: Select all

5120MiB of RAM
However, it should state that i have 4096MiB, as I am allocating 4GiB to QEMU.
I try allocating 6GiB:

Code: Select all

7168MiB of RAM
I know it has to be a mathematical error, as my memory map is correct...

Forgive me if I am overlooking something, I am taking 8th grade pre-algebra at the moment...

...though this shouldn't be too complicated.
Last edited by austanss on Thu Dec 03, 2020 5:17 pm, edited 1 time in total.
Skylight: https://github.com/austanss/skylight

I make stupid mistakes and my vision is terrible. Not a good combination.

NOTE: Never respond to my posts with "it's too hard".
feryno
Member
Member
Posts: 73
Joined: Thu Feb 09, 2012 6:53 am
Location: Czechoslovakia
Contact:

Re: Using memory map to calculate size of system RAM

Post by feryno »

there is a "hole" below 4 GB for firmware, APIC, video frame buffer etc so the RAM is not contiguous, part of RAM somewhere like 0-3GB, then the hole for hardware like 3-4 GB, then the rest of RAM starts from 4 GB
hypervisor-based solutions developer (Intel, AMD)
Octocontrabass
Member
Member
Posts: 5568
Joined: Mon Mar 25, 2013 7:01 pm

Re: Using memory map to calculate size of system RAM

Post by Octocontrabass »

Memory is not guaranteed to be one contiguous block. Memory is not guaranteed to start from physical address 0 (although it usually does on x86 systems). The memory map is not guaranteed to be sorted in any particular order.

If you want to know how much memory there is, you have to add up all of the memory map entries that indicate memory.
User avatar
austanss
Member
Member
Posts: 377
Joined: Sun Oct 11, 2020 9:46 pm
Location: United States

Re: Using memory map to calculate size of system RAM

Post by austanss »

so do I count
"EfiUnusableMemory"
"EfiACPIReclaimMemory"
"EfiACPIMemoryNVS"
towards the total memory count or no?
Skylight: https://github.com/austanss/skylight

I make stupid mistakes and my vision is terrible. Not a good combination.

NOTE: Never respond to my posts with "it's too hard".
User avatar
zaval
Member
Member
Posts: 656
Joined: Fri Feb 17, 2017 4:01 pm
Location: Ukraine, Bachmut
Contact:

Re: Using memory map to calculate size of system RAM

Post by zaval »

here is an example of counting number of usable RAM size in UEFI pages (4KB)

Code: Select all

UINTN GetUsableRamSizeInPages(EFI_MEMORY_DESCRIPTOR *MemoryMap, UINTN NumberOfElements, UINTN ReportedDescriptorSize){
	UINTN	Nop;
	INTN	i, Type;
	EFI_MEMORY_DESCRIPTOR *Desc;

	Nop = 0;
	for(i = 0, Desc = MemoryMap; i < NumberOfElements; i++){
		Type = Desc->Type;
		if(Type == EfiConventionalMemory
			|| Type == EfiLoaderCode || Type == EfiLoaderData
			|| Type == EfiBootServicesCode || Type == BootServicesData
		){
			Nop += Desc->NumberOfPages;
		}
		Desc = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)Desc + ReportedDescriptorSize);
	}

	return Nop;
}
Depending on when you want to call this calculation, you also might want to add memory of the type EfiACPIReclaimMemory, in case, you've dealt with ACPI as per the spec. Also, if you use your own private OSL types, you need to add them too.

Edit: I totally forgot about the moronic tendency for the reported by FW descriptor size often be larger, than than the descriptor structure (with paddings incl), for example, it's often reported to be 48 bytes instead of 40 - yet some 8 bytes got added behind the descriptor in every entry. fixed the example.
Last edited by zaval on Fri Dec 18, 2020 8:03 pm, edited 2 times in total.
ANT - NT-like OS for x64 and arm64.
efify - UEFI for a couple of boards (mips and arm). suspended due to lost of all the target park boards (russians destroyed our town).
User avatar
austanss
Member
Member
Posts: 377
Joined: Sun Oct 11, 2020 9:46 pm
Location: United States

Re: Using memory map to calculate size of system RAM

Post by austanss »

I haven't dealt with ACPI.

This is my code:

Code: Select all

uint64_t mem_map_parse(Memory_Map_Descriptor* memmap, uint64_t map_size, uint64_t desc_size)
{
	uint8_t *startOfMemoryMap = (uint8_t *)memmap;
	uint8_t *endOfMemoryMap = startOfMemoryMap + map_size;

	uint8_t *offset = startOfMemoryMap;

	uint64_t pages;

	uint32_t counter = 0;
 	serial_msg("\n\nMEMORY MAP:\n-=-=-=-=-=-\n");

	while (offset < endOfMemoryMap)
	{
		Memory_Map_Descriptor *desc = (Memory_Map_Descriptor *)offset;

		if   (desc->type == 0x07
		   || desc->type == 0x01 || desc->type == 0x02
		   || desc->type == 0x04 || desc->type == 0x05)
			pages += desc->count;

		hex_str_serial(desc->physical_start);
		serial_msg(": ");
		serial_msg(memory_types[desc->type]);
		serial_msg(" (");
		dec_str_serial(desc->count);
		serial_msg(")");
		serial_msg("\n");

		offset += desc_size;

		counter++;
	}

	offset -= desc_size;

	Memory_Map_Descriptor *desc = (Memory_Map_Descriptor *)offset;

	hex_str_serial(desc->physical_start);
	serial_msg(": ");
	serial_msg(memory_types[desc->type]);
	serial_msg(" (");
	dec_str_serial(desc->count);
	serial_msg(")");
	serial_msg("\n");

	return pages * 0x1000;
}
And it states that I have 12504056MiB of RAM... I allocated 6GB...
Skylight: https://github.com/austanss/skylight

I make stupid mistakes and my vision is terrible. Not a good combination.

NOTE: Never respond to my posts with "it's too hard".
User avatar
zaval
Member
Member
Posts: 656
Joined: Fri Feb 17, 2017 4:01 pm
Location: Ukraine, Bachmut
Contact:

Re: Using memory map to calculate size of system RAM

Post by zaval »

your pages variable isn't initialized before the loop. also, you forgot to add pages in that block after the loop. why you have that at all?
ANT - NT-like OS for x64 and arm64.
efify - UEFI for a couple of boards (mips and arm). suspended due to lost of all the target park boards (russians destroyed our town).
Octocontrabass
Member
Member
Posts: 5568
Joined: Mon Mar 25, 2013 7:01 pm

Re: Using memory map to calculate size of system RAM

Post by Octocontrabass »

rizxt wrote:so do I count
"EfiUnusableMemory"
"EfiACPIReclaimMemory"
"EfiACPIMemoryNVS"
towards the total memory count or no?
Memory that is not usable to your OS may not be memory at all, so I'd only count usable memory. The UEFI specification should tell you which of those are usable.
User avatar
austanss
Member
Member
Posts: 377
Joined: Sun Oct 11, 2020 9:46 pm
Location: United States

Re: Using memory map to calculate size of system RAM

Post by austanss »

zaval wrote:your pages variable isn't initialized before the loop. also, you forgot to add pages in that block after the loop. why you have that at all?
that was debug.
Skylight: https://github.com/austanss/skylight

I make stupid mistakes and my vision is terrible. Not a good combination.

NOTE: Never respond to my posts with "it's too hard".
User avatar
austanss
Member
Member
Posts: 377
Joined: Sun Oct 11, 2020 9:46 pm
Location: United States

Re: Using memory map to calculate size of system RAM

Post by austanss »

thanks for that it's printing out values with operable accuracy. solved.
Skylight: https://github.com/austanss/skylight

I make stupid mistakes and my vision is terrible. Not a good combination.

NOTE: Never respond to my posts with "it's too hard".
Post Reply