123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- #ifdef PCBIOS
-
- #include "etherboot.h"
- #include "realmode.h"
-
- #define CF ( 1 << 0 )
-
- #ifndef MEMSIZES_DEBUG
- #define MEMSIZES_DEBUG 0
- #endif
-
- /* by Eric Biederman */
-
- struct meminfo meminfo;
-
- /**************************************************************************
- BASEMEMSIZE - Get size of the conventional (base) memory
- **************************************************************************/
- unsigned short basememsize ( void )
- {
- RM_FRAGMENT(rm_basememsize,
- "int $0x12\n\t"
- );
- return real_call ( rm_basememsize, NULL, NULL );
- }
-
- /**************************************************************************
- MEMSIZE - Determine size of extended memory
- **************************************************************************/
- unsigned int memsize ( void )
- {
- struct {
- reg16_t ax;
- } PACKED in_stack;
- struct {
- reg16_t ax;
- reg16_t bx;
- reg16_t cx;
- reg16_t dx;
- reg16_t flags;
- } PACKED out_stack;
- int memsize;
-
- RM_FRAGMENT(rm_memsize,
- /* Some buggy BIOSes don't clear/set carry on pass/error of
- * e801h memory size call or merely pass cx,dx through without
- * changing them, so we set carry and zero cx,dx before call.
- */
- "stc\n\t"
- "xorw %cx,%cx\n\t"
- "xorw %dx,%dx\n\t"
- "popw %ax\n\t"
- "int $0x15\n\t"
- "pushfw\n\t"
- "pushw %dx\n\t"
- "pushw %cx\n\t"
- "pushw %bx\n\t"
- "pushw %ax\n\t"
- );
-
- /* Try INT 15,e801 first */
- in_stack.ax.word = 0xe801;
- real_call ( rm_memsize, &in_stack, &out_stack );
- if ( out_stack.flags.word & CF ) {
- /* INT 15,e801 not supported: try INT 15,88 */
- in_stack.ax.word = 0x8800;
- memsize = real_call ( rm_memsize, &in_stack, &out_stack );
- } else {
- /* Some BIOSes report extended memory via ax,bx rather
- * than cx,dx
- */
- if ( (out_stack.cx.word==0) && (out_stack.dx.word==0) ) {
- /* Use ax,bx */
- memsize = ( out_stack.bx.word<<6 ) + out_stack.ax.word;
- } else {
- /* Use cx,dx */
- memsize = ( out_stack.dx.word<<6 ) + out_stack.cx.word;
- }
- }
- return memsize;
- }
-
- #define SMAP ( 0x534d4150 )
- int meme820 ( struct e820entry *buf, int count )
- {
- struct {
- reg16_t flags;
- reg32_t eax;
- reg32_t ebx;
- struct e820entry entry;
- } PACKED stack;
- int index = 0;
-
- RM_FRAGMENT(rm_meme820,
- "addw $6, %sp\n\t" /* skip flags, eax */
- "popl %ebx\n\t"
- "pushw %ss\n\t" /* es:di = ss:sp */
- "popw %es\n\t"
- "movw %sp, %di\n\t"
- "movl $0xe820, %eax\n\t"
- "movl $" RM_STR(SMAP) ", %edx\n\t"
- "movl $" RM_STR(E820ENTRY_SIZE) ", %ecx\n\t"
- "int $0x15\n\t"
- "pushl %ebx\n\t"
- "pushl %eax\n\t"
- "pushfw\n\t"
- );
-
- stack.ebx.dword = 0; /* 'EOF' marker */
- while ( ( index < count ) &&
- ( ( index == 0 ) || ( stack.ebx.dword != 0 ) ) ) {
- real_call ( rm_meme820, &stack, &stack );
- if ( stack.eax.dword != SMAP ) return 0;
- if ( stack.flags.word & CF ) return 0;
- buf[index++] = stack.entry;
- }
- return index;
- }
-
- void get_memsizes(void)
- {
- /* Ensure we don't stomp bios data structutres.
- * the interrupt table: 0x000 - 0x3ff
- * the bios data area: 0x400 - 0x502
- * Dos variables: 0x502 - 0x5ff
- */
- static const unsigned min_addr = 0x600;
- unsigned i;
- unsigned basemem;
- basemem = get_free_base_memory();
- meminfo.basememsize = basememsize();
- meminfo.memsize = memsize();
- #ifndef IGNORE_E820_MAP
- meminfo.map_count = meme820(meminfo.map, E820MAX);
- #else
- meminfo.map_count = 0;
- #endif
- if (meminfo.map_count == 0) {
- /* If we don't have an e820 memory map fake it */
- meminfo.map_count = 2;
- meminfo.map[0].addr = 0;
- meminfo.map[0].size = meminfo.basememsize << 10;
- meminfo.map[0].type = E820_RAM;
- meminfo.map[1].addr = 1024*1024;
- meminfo.map[1].size = meminfo.memsize << 10;
- meminfo.map[1].type = E820_RAM;
- }
- /* Scrub the e820 map */
- for(i = 0; i < meminfo.map_count; i++) {
- if (meminfo.map[i].type != E820_RAM) {
- continue;
- }
- /* Reserve the bios data structures */
- if (meminfo.map[i].addr < min_addr) {
- unsigned long delta;
- delta = min_addr - meminfo.map[i].addr;
- if (delta > meminfo.map[i].size) {
- delta = meminfo.map[i].size;
- }
- meminfo.map[i].addr = min_addr;
- meminfo.map[i].size -= delta;
- }
- /* Ensure the returned e820 map is in sync
- * with the actual memory state
- */
- if ((meminfo.map[i].addr < 0xa0000) &&
- ((meminfo.map[i].addr + meminfo.map[i].size) > basemem))
- {
- if (meminfo.map[i].addr <= basemem) {
- meminfo.map[i].size = basemem - meminfo.map[i].addr;
- } else {
- meminfo.map[i].addr = basemem;
- meminfo.map[i].size = 0;
- }
- }
- }
- #if MEMSIZES_DEBUG
- {
- int i;
- printf("basememsize %d\n", meminfo.basememsize);
- printf("memsize %d\n", meminfo.memsize);
- printf("Memory regions(%d):\n", meminfo.map_count);
- for(i = 0; i < meminfo.map_count; i++) {
- unsigned long long r_start, r_end;
- r_start = meminfo.map[i].addr;
- r_end = r_start + meminfo.map[i].size;
- printf("[%X%X, %X%X) type %d\n",
- (unsigned long)(r_start >> 32),
- (unsigned long)r_start,
- (unsigned long)(r_end >> 32),
- (unsigned long)r_end,
- meminfo.map[i].type);
- #if defined(CONSOLE_FIRMWARE)
- sleep(1); /* No way to see 32 entries on a standard 80x25 screen... */
- #endif
- }
- }
- #endif
- }
-
- #endif /* PCBIOS */
|