Page 1 of 1

A Question about ARDS (Address Range Descriptor Struct)

Posted: Sat Dec 31, 2016 7:50 am
by Js2xxx
Well, does anybody know the types of ARDS?
I've only known 01h and 02h.

If anybody knows a lot about any other knowledge of it, please teach me as well.

Thanks a lot.

Re: A Question about ARDS (Address Range Descriptor Struct)

Posted: Sat Dec 31, 2016 7:55 am
by Brendan
Hi,
XuQihang wrote:Well, does anybody know the types of ARDS?
I've only known 01h and 02h.

If anybody knows a lot about any other knowledge of it, please teach me as well.
Could you be a little more specific?

The nice thing about languages like C is that anyone can define a structure called ARDS and put anything they feel like in it. :roll:


Cheers,

Brendan

Re: A Question about ARDS (Address Range Descriptor Struct)

Posted: Sat Dec 31, 2016 8:00 am
by alexfru
INT 15h, AX=E820h: ES:DI Pointer to an Address Range Descriptor structure which the BIOS is to fill in.

Re: A Question about ARDS (Address Range Descriptor Struct)

Posted: Sat Dec 31, 2016 8:45 am
by Js2xxx
Brendan wrote:Hi,
XuQihang wrote:Well, does anybody know the types of ARDS?
I've only known 01h and 02h.

If anybody knows a lot about any other knowledge of it, please teach me as well.
Could you be a little more specific?

The nice thing about languages like C is that anyone can define a structure called ARDS and put anything they feel like in it. :roll:


Cheers,

Brendan
I means, I want to get memory information by calling BIOS (16 Bits Assembler). I've heard the way is 'mov ax, 0E820h' and 'int 15h'. Some book wrote after calling the pointer of ARDS is stored in 'es:di'. Now I can get ARDS, but I don't know the detailed structure of ARDS.
Can you help me? If you don't mind, I'll be very grateful.

Re: A Question about ARDS (Address Range Descriptor Struct)

Posted: Sat Dec 31, 2016 8:48 am
by Js2xxx
alexfru wrote:INT 15h, AX=E820h: ES:DI Pointer to an Address Range Descriptor structure which the BIOS is to fill in.
And after I got it, how to catch the information in it?
Thanks if you don't mind telling me about it.

Re: A Question about ARDS (Address Range Descriptor Struct)

Posted: Sat Dec 31, 2016 9:29 am
by BrightLight

Code: Select all

struct e820_entry
{
	uint64_t base;
	uint64_t length;
	uint32_t type;
	uint32_t acpi3;
}__attribute__((packed))
base is the 64-bit physical address of the physical memory range.
length is the 64-bit length of the physical memory located at base.
type can be one of several values. 1 means "available" or usable RAM. 2 means hardware-reserved. 3 means hardware-reserved until you've saved the ACPI tables. 4 means ACPI memory that must be preserved during sleep states. 5 means the memory contains errors. All other values should be treated as type 2. You shouldn't allow your physical memory manager to allocate memory except those that are marked 1 or "free for use."
acpi3 may or may not be present. If the function returned 20 bytes, then this field is not present. If it returned 24 bytes, then it is present. It is a bitfield, but I'm not sure what exactly it contains. You can find out from the ACPI spec.

Re: A Question about ARDS (Address Range Descriptor Struct)

Posted: Sat Dec 31, 2016 11:16 am
by Brendan
Hi,
XuQihang wrote:
Brendan wrote:Could you be a little more specific?
I means, I want to get memory information by calling BIOS (16 Bits Assembler). I've heard the way is 'mov ax, 0E820h' and 'int 15h'. Some book wrote after calling the pointer of ARDS is stored in 'es:di'. Now I can get ARDS, but I don't know the detailed structure of ARDS.
Can you help me? If you don't mind, I'll be very grateful.
This is part of the ACPI specification now (since the first version of the ACPI specification); and the ACPI specification/s gives complete details (including the extension that increased the structure's size to 24 bytes and the flags that were added, and all the new types, etc). I'd recommend downloading at least the most recent version of the ACPI specification (and every version of the ACPI specification if you can, so you can figure out what was added when).

For old information (including information for computers that existed before the first version of ACPI) see the corresponding entry in Ralph Brown's Interrupt List.

Note that:
  • The raw data from "int 0x15, eax=0xE820" should be sanitised; including merging adjacent areas of the same type and attributes, handling areas that are misreported as overlapping, and possibly sorting it in a sane order.
  • The memory map you get from UEFI is quite different (different types, additional "cacheability" information, etc).
  • If you support very old computers (that don't support "int 0x15, eax=0xE820") it's possible to fabricate equivelent information from older BIOS functions (but takes some care).
  • None of the memory maps from firmware (from UEFI, from BIOS "int 0x15, eax=0xE820", or fabricated from older BIOS functions) include:
    • information about NUMA domains (can be obtained from ACPI's tables)
    • "hot-plug RAM" areas (can be obtained from ACPI's tables)
    • the physical address space size (can be obtained from CPUID)
    • which areas are/aren't usable for memory mapped PCI devices (can be derived from other information and "guesswork")
    • which areas are currently being used by memory mapped PCI devices (can be derived from PCI configuration space)
    • how physical memory areas relate to "motherboard RAM slots" and what type of RAM is involved and if it's ECC or not (can only be partially obtained from SMBIOS tables - you need a motherboard chipset to figure it out properly).
  • The memory maps from BIOS (from BIOS "int 0x15, eax=0xE820", or fabricated from older BIOS functions) don't include cacheability information (but the memory map from UEFI does). You could obtain this information on BIOS systems by extracting it directly from the CPU's MTRRs.
For these reasons I recommend inventing your own "memory map entry structure", and converting whatever the firmware gives you into your own format, and then merging all the other information (from other places) into that structure. If you do this right, you can end up with a "standard for your OS" memory map (regardless of what the firmware was) that contains all relevant information in one place.


Cheers,

Brendan

Re: A Question about ARDS (Address Range Descriptor Struct)

Posted: Sun Jan 01, 2017 12:23 am
by Js2xxx
Now I can successfully get the data in ARDS.
Then would you mind telling me how to calculate the memory size?

Re: A Question about ARDS (Address Range Descriptor Struct)

Posted: Sun Jan 01, 2017 12:29 am
by alexfru
XuQihang wrote:Now I can successfully get the data in ARDS.
Then would you mind telling me how to calculate the memory size?
Don't you have it now? It's in your picture.

Re: A Question about ARDS (Address Range Descriptor Struct)

Posted: Sun Jan 01, 2017 12:39 am
by Js2xxx
alexfru wrote: Don't you have it now? It's in your picture.
Well, I means, the total memory size.
I use VMware and I allocate 5 GB Memory for the vm, but the calculation result is greater than 5 GB.
I don't know what goes wrong.

Re: A Question about ARDS (Address Range Descriptor Struct)

Posted: Sun Jan 01, 2017 12:56 am
by alexfru
XuQihang wrote: I use VMware and I allocate 5 GB Memory for the vm, but the calculation result is greater than 5 GB.
I don't know what goes wrong.
I think you shouldn't be adding sizes of areas other than type 1. And also 1 GB probably means 1,073,741,824 and not 1,000,000,000.

Re: A Question about ARDS (Address Range Descriptor Struct)

Posted: Sun Jan 01, 2017 1:13 am
by Js2xxx
alexfru wrote:
I think you shouldn't be adding sizes of areas other than type 1. And also 1 GB probably means 1,073,741,824 and not 1,000,000,000.
Well, I've done what you say. However, the result isn't 5 GB again.
5 GB is 1_4000_0000h, but the result is 1_3FF8_F800h. It's 7_0800h lower.

Re: A Question about ARDS (Address Range Descriptor Struct)

Posted: Sun Jan 01, 2017 2:01 am
by mikegonta
omarrx024 wrote:

Code: Select all

struct e820_entry
{
	uint64_t base;
	uint64_t length;
	uint32_t type;
	uint32_t acpi3;
}__attribute__((packed))
For best performance on x86 (and others) don't pack already "packed" structs.
Why you shouldn’t use __attribute__((packed))

Re: A Question about ARDS (Address Range Descriptor Struct)

Posted: Sun Jan 01, 2017 2:18 am
by Brendan
Hi,
XuQihang wrote:Then would you mind telling me how to calculate the memory size?
That depends on which memory size you want:
  • For "amount of currently usable RAM", add up the lengths for each area reported as "type = 1"
  • For "amount of currently free and usable RAM", get the "amount of currently usable RAM" and subtract whatever your OS is already using and subtract the estimated size of the BIOS Data Area (e.g. "about 1.5 Kib" or maybe 4 KiB).
  • For "amount of total usable RAM", add up the lengths for each area reported as "type = 1" or "type = 3" (the ACPI reclaimable areas that become usable after you reclaim them).
  • For "amount of RAM installed", it's impossible to figure this out reliably from the memory map because the chipset and BIOS can steal RAM for various purposes (integrated video, memory for SMM, etc) and can also relocate areas (e.g. to make space for the "PCI hole" below 4 GiB). Instead, you need to get this information from the firmware's SMBIOS tables.
Note: Most of the above assumes that there are no overlapping areas. E.g. If the firmware is a little buggy and says there's three areas of RAM that are 1 GiB in size and that all start at the same address, then that counts as 1 GiB of RAM and not 3 GiB of RAM.


Cheers,

Brendan