Merged mcb30-realmode-redesign back to HEAD

This commit is contained in:
Michael Brown
2005-04-08 15:01:17 +00:00
parent de5d935135
commit 0ff80b477d
100 changed files with 4877 additions and 4263 deletions

View File

@@ -3,11 +3,11 @@
* Body of routines taken from old pcbios.S
*/
#ifdef PCBIOS
#include "etherboot.h"
#include "stdint.h"
#include "realmode.h"
#include "segoff.h"
#include "compiler.h"
#define BIOS_DATA_SEG 0x0040
#define CF ( 1 << 0 )
@@ -23,133 +23,101 @@ timeofday BIOS interrupt.
#define CONFIG_BIOS_CURRTICKS 1
#endif
#if defined(CONFIG_BIOS_CURRTICKS)
unsigned long currticks (void)
{
unsigned long currticks ( void ) {
static uint32_t days = 0;
uint32_t *ticks = VIRTUAL(0x0040,0x006c);
uint8_t *midnight = VIRTUAL(0x0040,0x0070);
uint32_t ticks;
uint8_t midnight;
/* Re-enable interrupts so that the timer interrupt can occur
*/
RM_FRAGMENT(rm_currticks,
"sti\n\t"
"nop\n\t"
"nop\n\t"
"cli\n\t"
);
REAL_EXEC ( rm_currticks,
"sti\n\t"
"nop\n\t"
"nop\n\t"
"cli\n\t",
0,
OUT_CONSTRAINTS (),
IN_CONSTRAINTS (),
CLOBBER ( "eax" ) ); /* can't have an empty clobber list */
real_call ( rm_currticks, NULL, NULL );
get_real ( ticks, BIOS_DATA_SEG, 0x006c );
get_real ( midnight, BIOS_DATA_SEG, 0x0070 );
if ( *midnight ) {
*midnight = 0;
if ( midnight ) {
midnight = 0;
put_real ( midnight, BIOS_DATA_SEG, 0x0070 );
days += 0x1800b0;
}
return ( days + *ticks );
return ( days + ticks );
}
#endif /* CONFIG_BIOS_CURRTICKS */
/**************************************************************************
INT15 - Call Interrupt 0x15
**************************************************************************/
int int15 ( int ax )
{
struct {
reg16_t ax;
} PACKED in_stack;
struct {
reg16_t flags;
} PACKED out_stack;
reg16_t ret_ax;
RM_FRAGMENT(rm_int15,
"sti\n\t"
"popw %ax\n\t"
"stc\n\t"
"int $0x15\n\t"
"pushf\n\t"
"cli\n\t"
);
in_stack.ax.word = ax;
ret_ax.word = real_call ( rm_int15, &in_stack, &out_stack );
/* Carry flag clear indicates function not supported */
if ( ! ( out_stack.flags.word & CF ) ) return 0;
return ret_ax.h;
}
#ifdef POWERSAVE
/**************************************************************************
CPU_NAP - Save power by halting the CPU until the next interrupt
**************************************************************************/
void cpu_nap ( void )
{
RM_FRAGMENT(rm_cpu_nap,
"sti\n\t"
"hlt\n\t"
"cli\n\t"
);
real_call ( rm_cpu_nap, NULL, NULL );
void cpu_nap ( void ) {
REAL_EXEC ( rm_cpu_nap,
"sti\n\t"
"hlt\n\t"
"cli\n\t",
0,
OUT_CONSTRAINTS (),
IN_CONSTRAINTS (),
CLOBBER ( "eax" ) ); /* can't have an empty clobber list */
}
#endif /* POWERSAVE */
#if (TRY_FLOPPY_FIRST > 0)
/**************************************************************************
DISK_INIT - Initialize the disk system
**************************************************************************/
void disk_init ( void )
{
RM_FRAGMENT(rm_disk_init,
"sti\n\t"
"xorw %ax,%ax\n\t"
"movb $0x80,%dl\n\t"
"int $0x13\n\t"
"cli\n\t"
);
real_call ( rm_disk_init, NULL, NULL );
void disk_init ( void ) {
REAL_EXEC ( rm_disk_init,
"sti\n\t"
"xorw %ax,%ax\n\t"
"movb $0x80,%dl\n\t"
"int $0x13\n\t"
"cli\n\t",
0,
OUT_CONSTRAINTS (),
IN_CONSTRAINTS (),
CLOBBER ( "eax", "ebx", "ecx", "edx",
"ebp", "esi", "edi" ) );
}
/**************************************************************************
DISK_READ - Read a sector from disk
**************************************************************************/
unsigned int pcbios_disk_read ( int drive, int cylinder, int head, int sector,
char *buf ) {
struct {
reg16_t ax;
reg16_t cx;
reg16_t dx;
segoff_t buffer;
} PACKED in_stack;
struct {
reg16_t flags;
} PACKED out_stack;
reg16_t ret_ax;
char *fixme_buf ) {
uint16_t ax, flags, discard_c, discard_d;
segoff_t buf = SEGOFF ( fixme_buf );
RM_FRAGMENT(rm_pcbios_disk_read,
"sti\n\t"
"popw %ax\n\t"
"popw %cx\n\t"
"popw %dx\n\t"
"popw %bx\n\t"
"popw %es\n\t"
"int $0x13\n\t"
"pushfw\n\t"
"cli\n\t"
/* FIXME: buf should be passed in as a segoff_t rather than a
* char *
*/
REAL_EXEC ( rm_pcbios_disk_read,
"sti\n\t"
"pushl %%ebx\n\t" /* Convert %ebx to %es:bx */
"popl %%bx\n\t"
"popl %%es\n\t"
"movb $0x02, %%ah\n\t" /* INT 13,2 - Read disk sector */
"movb $0x01, %%al\n\t" /* Read one sector */
"int $0x13\n\t"
"pushfw\n\t"
"popw %%bx\n\t"
"cli\n\t",
4,
OUT_CONSTRAINTS ( "=a" ( ax ), "=b" ( flags ),
"=c" ( discard_c ), "=d" ( discard_d ) ),
IN_CONSTRAINTS ( "c" ( ( ( cylinder & 0xff ) << 8 ) |
( ( cylinder >> 8 ) & 0x3 ) |
sector ),
"d" ( ( head << 8 ) | drive ),
"b" ( buf ) ),
CLOBBER ( "ebp", "esi", "edi" ) );
);
in_stack.ax.h = 2; /* INT 13,2 - Read disk sector */
in_stack.ax.l = 1; /* Read one sector */
in_stack.cx.h = cylinder & 0xff;
in_stack.cx.l = ( ( cylinder >> 8 ) & 0x3 ) | sector;
in_stack.dx.h = head;
in_stack.dx.l = drive;
in_stack.buffer.segment = SEGMENT ( buf );
in_stack.buffer.offset = OFFSET ( buf );
ret_ax.word = real_call ( rm_pcbios_disk_read, &in_stack, &out_stack );
return ( out_stack.flags.word & CF ) ? ret_ax.word : 0;
return ( flags & CF ) ? ax : 0;
}
#endif /* TRY_FLOPPY_FIRST */
#endif /* PCBIOS */

View File

@@ -0,0 +1,76 @@
/* Etherboot routines for PCBIOS firmware.
*
* Body of routines taken from old pcbios.S
*/
#include "compiler.h"
#include "realmode.h"
#include "console.h"
#define ZF ( 1 << 6 )
/**************************************************************************
bios_putchar - Print a character on console
**************************************************************************/
static void bios_putchar ( int character ) {
REAL_EXEC ( rm_console_putc,
"sti\n\t"
"movb $0x0e, %%ah\n\t"
"movl $1, %%ebx\n\t"
"int $0x10\n\t"
"cli\n\t",
1,
OUT_CONSTRAINTS ( "=a" ( character ) ),
IN_CONSTRAINTS ( "a" ( character ) ),
CLOBBER ( "ebx", "ecx", "edx", "ebp", "esi", "edi" ) );
/* NOTE: %eax may be clobbered, so must be specified as an output
* parameter, even though we don't then do anything with it.
*/
}
/**************************************************************************
bios_getchar - Get a character from console
**************************************************************************/
static int bios_getchar ( void ) {
uint16_t character;
REAL_EXEC ( rm_console_getc,
"sti\n\t"
"xorw %%ax, %%ax\n\t"
"int $0x16\n\t"
"cli\n\t",
1,
OUT_CONSTRAINTS ( "=a" ( character ) ),
IN_CONSTRAINTS (),
CLOBBER ( "ebx", "ecx", "edx", "ebp", "esi", "edi" ) );
return ( character & 0xff );
}
/**************************************************************************
bios_iskey - Check for keyboard interrupt
**************************************************************************/
static int bios_iskey ( void ) {
uint16_t flags;
REAL_EXEC ( rm_console_ischar,
"sti\n\t"
"movb $1, %%ah\n\t"
"int $0x16\n\t"
"pushfw\n\t"
"popw %%ax\n\t"
"cli\n\t",
1,
OUT_CONSTRAINTS ( "=a" ( flags ) ),
IN_CONSTRAINTS (),
CLOBBER ( "ebx", "ecx", "edx", "ebp", "esi", "edi" ) );
return ( ( flags & ZF ) == 0 );
}
static struct console_driver bios_console __console_driver = {
.putchar = bios_putchar,
.getchar = bios_getchar,
.iskey = bios_iskey,
};

View File

@@ -1,85 +0,0 @@
/* Etherboot routines for PCBIOS firmware.
*
* Body of routines taken from old pcbios.S
*/
#ifdef PCBIOS
#include "etherboot.h"
#include "realmode.h"
#include "segoff.h"
#define ZF ( 1 << 6 )
/**************************************************************************
CONSOLE_PUTC - Print a character on console
**************************************************************************/
void console_putc ( int character )
{
struct {
reg16_t ax;
} PACKED in_stack;
RM_FRAGMENT(rm_console_putc,
"sti\n\t"
"popw %ax\n\t"
"movb $0x0e, %ah\n\t"
"movl $1, %ebx\n\t"
"int $0x10\n\t"
"cli\n\t"
);
in_stack.ax.l = character;
real_call ( rm_console_putc, &in_stack, NULL );
}
/**************************************************************************
CONSOLE_GETC - Get a character from console
**************************************************************************/
int console_getc ( void )
{
RM_FRAGMENT(rm_console_getc,
"sti\n\t"
"xorw %ax, %ax\n\t"
"int $0x16\n\t"
"xorb %ah, %ah\n\t"
"cli\n\t"
);
return real_call ( rm_console_getc, NULL, NULL );
}
/**************************************************************************
CONSOLE_ISCHAR - Check for keyboard interrupt
**************************************************************************/
int console_ischar ( void )
{
RM_FRAGMENT(rm_console_ischar,
"sti\n\t"
"movb $1, %ah\n\t"
"int $0x16\n\t"
"pushfw\n\t"
"popw %ax\n\t"
"cli\n\t"
);
return ( ( real_call ( rm_console_ischar, NULL, NULL ) & ZF ) == 0 );
}
/**************************************************************************
GETSHIFT - Get keyboard shift state
**************************************************************************/
int getshift ( void )
{
RM_FRAGMENT(rm_getshift,
"sti\n\t"
"movb $2, %ah\n\t"
"int $0x16\n\t"
"andw $0x3, %ax\n\t"
"cli\n\t"
);
return real_call ( rm_getshift, NULL, NULL );
}
#endif /* PCBIOS */

View File

@@ -0,0 +1,90 @@
#include "realmode.h"
#include "timer.h"
#include "latch.h"
#include "bios.h"
#define K_RDWR 0x60 /* keyboard data & cmds (read/write) */
#define K_STATUS 0x64 /* keyboard status */
#define K_CMD 0x64 /* keybd ctlr command (write-only) */
#define K_OBUF_FUL 0x01 /* output buffer full */
#define K_IBUF_FUL 0x02 /* input buffer full */
#define KC_CMD_WIN 0xd0 /* read output port */
#define KC_CMD_WOUT 0xd1 /* write output port */
#define KB_SET_A20 0xdf /* enable A20,
enable output buffer full interrupt
enable data line
disable clock line */
#define KB_UNSET_A20 0xdd /* enable A20,
enable output buffer full interrupt
enable data line
disable clock line */
enum { Disable_A20 = 0x2400, Enable_A20 = 0x2401, Query_A20_Status = 0x2402,
Query_A20_Support = 0x2403 };
#define CF ( 1 << 0 )
#ifndef IBM_L40
static void empty_8042 ( void )
{
unsigned long time;
char st;
time = currticks() + TICKS_PER_SEC; /* max wait of 1 second */
while ((((st = inb(K_CMD)) & K_OBUF_FUL) ||
(st & K_IBUF_FUL)) &&
currticks() < time)
inb(K_RDWR);
}
#endif /* IBM_L40 */
/*
* Gate A20 for high memory
*
* Note that this function gets called as part of the return path from
* librm's real_call, which is used to make the int15 call if librm is
* being used. To avoid an infinite recursion, we make gateA20_set
* return immediately if it is already part of the call stack.
*/
void gateA20_set ( void ) {
static char reentry_guard = 0;
uint16_t flags, status;
if ( reentry_guard )
return;
reentry_guard = 1;
REAL_EXEC ( rm_enableA20,
"sti\n\t"
"stc\n\t"
"int $0x15\n\t"
"pushfw\n\t"
"popw %%bx\n\t"
"cli\n\t",
2,
OUT_CONSTRAINTS ( "=a" ( status ), "=b" ( flags ) ),
IN_CONSTRAINTS ( "a" ( Enable_A20 ) ),
CLOBBER ( "ecx", "edx", "ebp", "esi", "edi" ) );
if ( ( flags & CF ) ||
( ( status >> 8 ) & 0xff ) ) {
/* INT 15 method failed, try alternatives */
#ifdef IBM_L40
outb(0x2, 0x92);
#else /* IBM_L40 */
empty_8042();
outb(KC_CMD_WOUT, K_CMD);
empty_8042();
outb(KB_SET_A20, K_RDWR);
empty_8042();
#endif /* IBM_L40 */
}
reentry_guard = 0;
}
void gateA20_unset ( void ) {
/* Not currently implemented */
}

View File

@@ -1,7 +1,8 @@
#ifdef PCBIOS
#include "etherboot.h"
#include "stdint.h"
#include "stddef.h"
#include "realmode.h"
#include "init.h"
#include "memsizes.h"
#define CF ( 1 << 0 )
@@ -16,109 +17,131 @@ 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 );
static unsigned short basememsize ( void ) {
uint16_t int12_basememsize, fbms_basememsize;
/* There are two methods for retrieving the base memory size:
* INT 12 and the BIOS FBMS counter at 40:13. We read both
* and use the smaller value, to be paranoid.
*/
REAL_EXEC ( rm_basememsize,
"int $0x12\n\t",
1,
OUT_CONSTRAINTS ( "=a" ( int12_basememsize ) ),
IN_CONSTRAINTS (),
CLOBBER ( "ebx", "ecx", "edx", "ebp", "esi", "edi" ) );
get_real ( fbms_basememsize, 0x40, 0x13 );
return ( int12_basememsize < fbms_basememsize ?
int12_basememsize : fbms_basememsize );
}
/**************************************************************************
MEMSIZE - Determine size of extended memory
MEMSIZE - Determine size of extended memory, in kB
**************************************************************************/
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;
static unsigned int memsize ( void ) {
uint16_t extmem_1m_to_16m_k, extmem_16m_plus_64k;
uint16_t confmem_1m_to_16m_k, confmem_16m_plus_64k;
uint16_t flags;
int memsize;
RM_FRAGMENT(rm_memsize,
/* Some buggy BIOSes don't clear/set carry on pass/error of
/* Try INT 15,e801 first
*
* 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"
);
REAL_EXEC ( rm_mem_e801,
"stc\n\t"
"int $0x15\n\t"
"pushfw\n\t" /* flags -> %di */
"popw %%di\n\t",
5,
OUT_CONSTRAINTS ( "=a" ( extmem_1m_to_16m_k ),
"=b" ( extmem_16m_plus_64k ),
"=c" ( confmem_1m_to_16m_k ),
"=d" ( confmem_16m_plus_64k ),
"=D" ( flags ) ),
IN_CONSTRAINTS ( "a" ( 0xe801 ),
"c" ( 0 ),
"d" ( 0 ) ),
CLOBBER ( "ebp", "esi" ) );
/* 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;
if ( ! ( flags & CF ) ) {
/* INT 15,e801 succeeded */
if ( confmem_1m_to_16m_k || confmem_16m_plus_64k ) {
/* Use confmem (cx,dx) values */
memsize = confmem_1m_to_16m_k +
( confmem_16m_plus_64k << 6 );
} else {
/* Use cx,dx */
memsize = ( out_stack.dx.word<<6 ) + out_stack.cx.word;
/* Use extmem (ax,bx) values */
memsize = extmem_1m_to_16m_k +
( extmem_16m_plus_64k << 6 );
}
} else {
/* INT 15,e801 failed; fall back to INT 15,88
*
* CF is apparently unreliable and should be ignored.
*/
REAL_EXEC ( rm_mem_88,
"int $0x15\n\t",
1,
OUT_CONSTRAINTS ( "=a" ( extmem_1m_to_16m_k ) ),
IN_CONSTRAINTS ( "a" ( 0x88 << 8 ) ),
CLOBBER ( "ebx", "ecx", "edx",
"ebp", "esi", "edi" ) );
memsize = extmem_1m_to_16m_k;
}
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;
/**************************************************************************
MEME820 - Retrieve the E820 BIOS memory map
**************************************************************************/
#define SMAP ( 0x534d4150 ) /* "SMAP" */
static int meme820 ( struct e820entry *buf, int count ) {
int index;
uint16_t basemem_entry;
uint32_t smap, next;
uint16_t flags;
uint32_t discard_c, discard_d;
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;
}
index = 0;
next = 0;
do {
basemem_entry = BASEMEM_PARAMETER_INIT ( buf[index] );
REAL_EXEC ( rm_mem_e820,
"int $0x15\n\t"
"pushfw\n\t" /* flags -> %di */
"popw %%di\n\t",
5,
OUT_CONSTRAINTS ( "=a" ( smap ),
"=b" ( next ),
"=c" ( discard_c ),
"=d" ( discard_d ),
"=D" ( flags ) ),
IN_CONSTRAINTS ( "a" ( 0xe820 ),
"b" ( next ),
"c" ( sizeof (struct e820entry) ),
"d" ( SMAP ),
"D" ( basemem_entry ) ),
CLOBBER ( "ebp", "esi" ) );
BASEMEM_PARAMETER_DONE ( buf[index] );
if ( smap != SMAP ) return 0;
if ( flags & CF ) break;
index++;
} while ( ( index < count ) && ( next != 0 ) );
return index;
}
void get_memsizes(void)
{
/**************************************************************************
GET_MEMSIZES - Retrieve the system memory map via any available means
**************************************************************************/
void get_memsizes ( void ) {
/* Ensure we don't stomp bios data structutres.
* the interrupt table: 0x000 - 0x3ff
* the bios data area: 0x400 - 0x502
@@ -127,16 +150,19 @@ void get_memsizes(void)
static const unsigned min_addr = 0x600;
unsigned i;
unsigned basemem;
basemem = get_free_base_memory();
/* Retrieve memory information from the BIOS */
meminfo.basememsize = basememsize();
basemem = meminfo.basememsize << 10;
meminfo.memsize = memsize();
#ifndef IGNORE_E820_MAP
meminfo.map_count = meme820(meminfo.map, E820MAX);
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 */
/* If we don't have an e820 memory map fake it */
if ( meminfo.map_count == 0 ) {
meminfo.map_count = 2;
meminfo.map[0].addr = 0;
meminfo.map[0].size = meminfo.basememsize << 10;
@@ -145,57 +171,56 @@ void get_memsizes(void)
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) {
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) {
if ( meminfo.map[i].addr < min_addr ) {
unsigned long delta;
delta = min_addr - meminfo.map[i].addr;
if (delta > meminfo.map[i].size) {
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
/* 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;
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++) {
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
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 );
}
}
#endif
}
#endif /* PCBIOS */
INIT_FN ( INIT_MEMSIZES, get_memsizes, NULL, NULL );