/* (c) 2009-2010 by Gerhard Wiesinger Source Code released under GNU GPL, v2 only and not any later version. http://www.gnu.org/licenses/gpl-2.0.html Must be compiled with OpenWatcom C for long long support. */ #ifdef __WATCOMC__ #if defined(__386__) && !defined(__WINDOWS_386__) #error Wrong build target, use wcc instead of wcc386! #endif #endif /* end __WATCOMC__ */ #include #include #include typedef unsigned char UCHAR; typedef unsigned int WORD; typedef unsigned long DWORD; typedef unsigned long long QWORD; WORD __cdecl int15_e820h(WORD seg, WORD off); typedef struct { QWORD base_address; QWORD length_in_bytes; DWORD type_of_address_range; } memory_descriptor; int main() { WORD far* pmemory = NULL; WORD far* pebda_word = NULL; UCHAR far* pebda_byte = NULL; union REGS inregs, outregs; union REGPACK regs_pack; int CF = 0; WORD len = 0; memory_descriptor buffer; char* memory_type = "Reserved"; printf("Memory Information V1.0, (c) 2009-2010 by Gerhard Wiesinger\n\n"); ////////////////////////////////////////////////////////////////////// pmemory = (WORD far*)MK_FP(0x40, 0x13); printf("BIOS area 40h:13h=%u, %ukB\n", *pmemory, *pmemory); ////////////////////////////////////////////////////////////////////// int86(0x12, &inregs, &outregs); printf("INT 12h: AX=%u, %ukB\n", outregs.x.ax, outregs.x.ax); ////////////////////////////////////////////////////////////////////// printf("\nINT 15h, AH=88h\n"); regs_pack.h.ah = 0x88; intr(0x15, ®s_pack); CF = regs_pack.w.flags & INTR_CF; if (CF) { printf("Not successful\n"); } else { printf("AX=%u, number of continuous kB starting at absolute address 100000h: %ukB\n", regs_pack.x.ax, regs_pack.x.ax); } ////////////////////////////////////////////////////////////////////// printf("\nINT 15h, AX=E801h\n"); regs_pack.x.ax = 0xE801; intr(0x15, ®s_pack); CF = regs_pack.w.flags & INTR_CF; if (CF) { printf("Not successful\n"); } else { printf("AX=%u, extended memory between 1M and 16M: %ukB\n", regs_pack.x.ax, regs_pack.x.ax); printf("BX=%u, extended memory above 16M, in 64K blocks: %lukB\n", regs_pack.x.bx, ((DWORD)64) * regs_pack.x.bx); printf("CX=%u, configured memory between 1M and 16M: %ukB\n", regs_pack.x.cx, regs_pack.x.cx); printf("DX=%u, configured memory above 16M, in 64K blocks: %lukB\n", regs_pack.x.dx, ((DWORD)64) * regs_pack.x.dx); } ////////////////////////////////////////////////////////////////////// printf("\nINT 15h, AX=E820h\n"); len = int15_e820h(FP_SEG(&buffer), FP_OFF(&buffer)); printf("structure len=%u\n", len); printf("base address %llXh (%llu)\n", buffer.base_address, buffer.base_address); printf("length in bytes %llXh (%llu), %llukB\n", buffer.length_in_bytes, buffer.length_in_bytes, buffer.length_in_bytes/1024); switch(buffer.type_of_address_range) { case 1: memory_type = "memory, available to OS"; break; case 2: memory_type = "reserved, not available (e.g. system ROM, memory-mapped device)"; break; case 3: memory_type = "ACPI reclaim Memory (usable by OS after reading ACPI tables)"; break; case 4: memory_type = "ACPI NVS Memory (OS is required to save this memory between NVS)"; break; default: break; } printf("type of address range: memory type=%lu\n", buffer.type_of_address_range); printf("type of address range: memory type=%s\n", memory_type); printf("\nEBDA - Extended BIOS Data Area information"); pmemory = (WORD far*)MK_FP(0x40, 0x0E); if (*pmemory > 0x3BC) { // BYTE, not WORD, documented wrong pebda_byte = (UCHAR far*)MK_FP(*pmemory, 0x0); printf(", found, segment=%04Xh, memory=%ukB\n", *pmemory, (WORD)(*pebda_byte)); pebda_word = (WORD far*)MK_FP(*pmemory, 0x24); printf("Device driver entry point=%04Xh", *pebda_word); pebda_word = (WORD far*)MK_FP(*pmemory, 0x22); printf(":%04Xh, ", *pebda_word); pebda_byte = (UCHAR far*)MK_FP(*pmemory, 0x26); printf("Device flag 1st byte=%02Xh, ", (WORD)(*pebda_byte)); pebda_byte = (UCHAR far*)MK_FP(*pmemory, 0x27); printf("2nd byte=%02Xh\n", (WORD)(*pebda_byte)); } else { printf("\nNo EBDA found, printer port of LPT4=%03uh\n", *pmemory); } exit(0); return 0; }