Tuesday 26 October 2010

Int 0x15 e820 and libx86

One of the more obscure libraries I've looked at recently is libx86 which provides some x86 real mode functionality to do tricks such as BIOS calls from user space. The library provides routines to do real mode malloc/free and also a structure to pass/return CPU register to/from an Interrupt call. One uses:

sudo apt-get install libx86-dev

..to install the libx86 devel library.

I experimented with libx86 by using the Int 0x15 AX=0xe820 call to query the system address map. One loads EAX with 0xe820, EBX initially with zero (for the first address map structure), ES:DI with a pointer a 20 byte real mode buffer, ECX with 20 (size of the buffer) and EDX with the signature 'SMAP'. If the carry is set or EBX is zero after the call, then either an error occurred or one has reached the end of the table. After the call, EBX contains a continuation value that is passed back in EBX on the next call. The 20 byte real mode buffer is populated as follows:

 uint32     BaseAddrLo   Lo 32 Bits of Base Address
 uint32     BaseAddrHi   Hi 32 Bits of Base Address
 uint32     LengthLo     Lo 32 Bits of Length in Bytes
 uint32     LengthHi     Hi 32 Bits of Length in Bytes
 uint32     Type         Address type 
 
My implementation to dump out the entire system address map can be found here. Compile and link with libx86 and then run the executable using sudo:

sudo ./e820
Base Address Length Type
0000000000000000 000000000009fc00 RAM
000000000009fc00 0000000000000400 Reserved
00000000000e0000 0000000000020000 Reserved
0000000000100000 000000003f6b0000 RAM
000000003f7b0000 000000000000e000 ACPI Reclaim
000000003f7be000 0000000000032000 ACPI NVS memory
000000003f7f0000 0000000000010000 Reserved
00000000fee00000 0000000000001000 Reserved
00000000fff00000 0000000000100000 Reserved

Anyhow, I hope this example shows how to do BIOS interrupts using libx86 from userspace in Linux.