E280H

Method E820H is come from the accumulated value
in %eax register for bios interrupt with "int 0x15".

This interrupt is issued to check the system memory
and clasifies memory status.
The result is stored in buffer pointed by ex:di.

Before interruption, registers should be set an appropriate values.

AX = 0x820h
EDX = '534D4150H' (SMAP)
EBX = value from which copy the value, at first 0x0.
ECX = size of buffer
ES:DI = pointer to buffer fo result.

If successful, it clear the CF and EAX has 'SMAP'.

Here is a code.
In the code, jae stands for "Jump if Above or Equel",
jne for "Jump Not Equal"

#define SMAP  0x534d4150

meme820: xorl %ebx, %ebx # continuation counter movw $E820MAP, %di # point into the whitelist # so we can have the bios

# directly write into it.

At first, %ebx is cleared and offset of buffer is stored into %di.
The value of offset is defined in e820.h file.

#define E820MAP 0x2d0           /* our map */

Then, next step.

jmpe820:
        movl    $0x0000e820, %eax               # e820, upper word zeroed
        movl    $SMAP, %edx                     # ascii 'SMAP'
        movl    $20, %ecx                       # size of the e820rec
        pushw   %ds                             # data record.
        popw    %es
        int     $0x15                           # make the call
        jc      bail820                         # fall to e801 if it fails

cmpl $SMAP, %eax # check the return is `SMAP' jne bail820 # fall to e801 if it fails

Set %eax to 0xe820h and store 'SMAP' into %edx.
The size of entry of e820 is addr(8byte) + size(8byte) + type(4byte),
so total is 20bytes, which is set to %ecx.

Next, buffer is pointed by es:di, es is equal to ds.
This operation make sure that es:di points to
appropriate area of memory for buffer.

Then, isuue an interrupt with "int 0x15h".
"jc" instruction is "Jump if Carry is set"
and e820 succeeds with carry not set,
"jc" means fail of e820 and jump to bail 820,
next method for memory check, e801.

good820:
        movb    (E820NR), %al                   # up to 128 entries
        cmpb    $E820MAX, %al
        jae     bail820

incb (E820NR) movw %di, %ax addw $20, %ax movw %ax, %di

In e820.h

#define E820MAX 32              /* number of entries in E820MAP */
#define E820NR  0x1e8           /* # entries in E820MAP */

is defined.
Move value of (E820NR) and comparison with 32.
If over the maximun entry, jump to bail820.

Else inclement (E820NR) and adds %di with size of e820 entry.

again820:
        cmpl    $0, %ebx                        # check to see if
        jne     jmpe820                         # %ebx is set to EOF
bail820:

If %ebx is 0, status of memory is filled.
If not, jumps to jmpe820 and continues to retrieve the status the next
memory chunk.

These data is stored into struct e820map defined in include/asm-i386/e820.h
by copy_e820_map() function and printk-ed by print_base_map() function.
Both function is defined in ${linux src}/arch/i386/kernel/setup.c

In my old machine, dmesg has

BIOS-provided physical RAM map:
 BIOS-e820: 0000000000000000 - 00000000000a0000 (usable)
 BIOS-e820: 00000000000f0000 - 0000000000100000 (reserved)
 BIOS-e820: 0000000000100000 - 0000000004000000 (usable)
 BIOS-e820: 00000000ffe00000 - 0000000100000000 (reserved)
64MB LOWMEM available.


inserted by FC2 system