summaryrefslogtreecommitdiff
path: root/sys/arch/i386/stand/libsa
diff options
context:
space:
mode:
authorTobias Weingartner <weingart@cvs.openbsd.org>1997-10-17 15:03:29 +0000
committerTobias Weingartner <weingart@cvs.openbsd.org>1997-10-17 15:03:29 +0000
commit41093f286d691912ac4dbf211375b21dbff49e4e (patch)
tree2921090c2b4c87b93ba68120400a50ef8a5cfec7 /sys/arch/i386/stand/libsa
parent82b80c5d2e1dea90de4bcb7b3dda8c4854d6564a (diff)
Use BIOS to probe for memory map.
Probe for BIOS supported disks. Use BIOS to get geometry for supported disks. All in preparation to passing the whole thing to the kernel.
Diffstat (limited to 'sys/arch/i386/stand/libsa')
-rw-r--r--sys/arch/i386/stand/libsa/Makefile5
-rw-r--r--sys/arch/i386/stand/libsa/biosdev.c75
-rw-r--r--sys/arch/i386/stand/libsa/biosdev.h6
-rw-r--r--sys/arch/i386/stand/libsa/cmd_i386.c105
-rw-r--r--sys/arch/i386/stand/libsa/gidt.S10
-rw-r--r--sys/arch/i386/stand/libsa/libsa.h5
-rw-r--r--sys/arch/i386/stand/libsa/machdep.c3
-rw-r--r--sys/arch/i386/stand/libsa/memprobe.c326
8 files changed, 486 insertions, 49 deletions
diff --git a/sys/arch/i386/stand/libsa/Makefile b/sys/arch/i386/stand/libsa/Makefile
index a1d5a8c9dd1..dd0e818b045 100644
--- a/sys/arch/i386/stand/libsa/Makefile
+++ b/sys/arch/i386/stand/libsa/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.26 1997/09/21 10:02:08 mickey Exp $
+# $OpenBSD: Makefile,v 1.27 1997/10/17 15:03:20 weingart Exp $
LIB= sa
@@ -15,7 +15,8 @@ DIR_KERN=$S/lib/libkern
# i386 stuff (so, it will possibly load in the same 64k)
SRCS= gidt.S debug_i386.S alloca.S \
machdep.c dev_i386.c exec_i386.c cmd_i386.c \
- biosdev.c bioscons.c gateA20.c memprobe.c time.c
+ biosdev.c bioscons.c gateA20.c smpprobe.c \
+ memprobe.c diskprobe.c time.c
# stand routines
SRCS+= alloc.c exit.c exec.c getfile.c gets.c globals.c strcmp.c strlen.c \
diff --git a/sys/arch/i386/stand/libsa/biosdev.c b/sys/arch/i386/stand/libsa/biosdev.c
index 193a4755780..8ba83e43fa9 100644
--- a/sys/arch/i386/stand/libsa/biosdev.c
+++ b/sys/arch/i386/stand/libsa/biosdev.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: biosdev.c,v 1.36 1997/10/07 08:56:19 mickey Exp $ */
+/* $OpenBSD: biosdev.c,v 1.37 1997/10/17 15:03:21 weingart Exp $ */
/*
* Copyright (c) 1996 Michael Shalayeff
@@ -52,13 +52,13 @@ struct biosdisk {
};
/*
- *
* return a word that represents the max number
* of sectors and heads for this device
*
*/
u_int32_t
-biosdinfo(int dev)
+biosdinfo(dev)
+ int dev;
{
u_int f, rv;
__asm __volatile (DOINT(0x13) "; setc %b0\n\t"
@@ -71,10 +71,37 @@ biosdinfo(int dev)
}
/*
+ * Probe if given bios disk exists.
+ *
+ * NOTE: This seems to hang on certain machines. Use biosdinfo()
+ * first, and verify with biosdprobe() IFF biosdinfo() succeeds
+ * first.
+ *
+ * XXX - biosdinfo() and biosdprobe() should be integrated into 1 fcn.
+ */
+u_int32_t
+biosdprobe(dev)
+ int dev;
+{
+ u_int32_t val = 0;
+
+ __asm __volatile (
+ DOINT(0x13) "\n\t"
+ "setc %b0 \n\t"
+ : "=a" (val)
+ : "0" (0x1500),
+ "d" (dev)
+ : "%ecx", "%edx", "cc");
+
+ return(val & 0xffff);
+}
+
+/*
* reset disk system
*/
static __inline int
-biosdreset(int dev)
+biosdreset(dev)
+ int dev;
{
int rv;
__asm __volatile (DOINT(0x13) "; setc %b0" : "=a" (rv)
@@ -82,8 +109,11 @@ biosdreset(int dev)
return (rv & 0xff)? rv >> 8 : 0;
}
-static __inline int
-biosd_rw(int rw, int dev, int cyl, int head, int sect, int nsect, void* buf)
+__inline int
+biosd_rw(rw, dev, cyl, head, sect, nsect, buf)
+ int rw, dev, cyl, head;
+ int sect, nsect;
+ void* buf;
{
int rv;
BIOS_regs.biosr_es = (u_int32_t)buf >> 4;
@@ -110,7 +140,8 @@ biosd_rw(int rw, int dev, int cyl, int head, int sect, int nsect, void* buf)
* check the features supported by the bios for the drive
*/
static __inline int
-EDDcheck (int dev)
+EDDcheck (dev)
+ int dev;
{
int rv, bm, sgn;
__asm __volatile(DOINT(0x13) "; setc %b0"
@@ -120,7 +151,11 @@ EDDcheck (int dev)
}
int
-EDD_rw(int rw, int dev, u_int64_t daddr, u_int32_t nblk, void *buf)
+EDD_rw(rw, dev, daddr, nblk, buf)
+ int rw, dev;
+ u_int64_t daddr;
+ u_int32_t nblk;
+ void *buf;
{
int rv;
struct EDD_CB cb;
@@ -332,8 +367,10 @@ biosopen(struct open_file *f, ...)
return 0;
}
+
static __inline const char *
-biosdisk_err(u_int error)
+biosdisk_err(error)
+ u_int error;
{
static const u_char errs[] =
/* ignored "\x00" "successful completion\0" */
@@ -379,7 +416,8 @@ biosdisk_err(u_int error)
}
static __inline int
-biosdisk_errno(u_int error)
+biosdisk_errno(error)
+ u_int error;
{
static const struct biosdisk_errors {
u_char error;
@@ -410,8 +448,13 @@ biosdisk_errno(u_int error)
}
int
-biosstrategy(void *devdata, int rw,
- daddr_t blk, size_t size, void *buf, size_t *rsize)
+biosstrategy(devdata, rw, blk, size, buf, rsize)
+ void *devdata;
+ int rw;
+ daddr_t blk;
+ size_t size;
+ void *buf;
+ size_t *rsize;
{
u_int8_t error = 0;
register struct biosdisk *bd = (struct biosdisk *)devdata;
@@ -498,14 +541,18 @@ biosstrategy(void *devdata, int rw,
}
int
-biosclose(struct open_file *f)
+biosclose(f)
+ struct open_file *f;
{
free(f->f_devdata, 0);
return 0;
}
int
-biosioctl(struct open_file *f, u_long cmd, void *data)
+biosioctl(f, cmd, data)
+ struct open_file *f;
+ u_long cmd;
+ void *data;
{
return 0;
}
diff --git a/sys/arch/i386/stand/libsa/biosdev.h b/sys/arch/i386/stand/libsa/biosdev.h
index e54a352ba41..b3aff102afa 100644
--- a/sys/arch/i386/stand/libsa/biosdev.h
+++ b/sys/arch/i386/stand/libsa/biosdev.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: biosdev.h,v 1.21 1997/09/20 22:40:44 flipk Exp $ */
+/* $OpenBSD: biosdev.h,v 1.22 1997/10/17 15:03:22 weingart Exp $ */
/*
* Copyright (c) 1996 Michael Shalayeff
@@ -41,7 +41,9 @@ int biosstrategy __P((void *, int, daddr_t, size_t, void *, size_t *));
int biosopen __P((struct open_file *, ...));
int biosclose __P((struct open_file *));
int biosioctl __P((struct open_file *, u_long, void *));
-u_int32_t biosdinfo(int);
+u_int32_t biosdinfo __P((int));
+u_int32_t biosdprobe __P((int));
+int biosd_rw __P((int, int, int, int, int, int, void*));
/* bioscons.c */
diff --git a/sys/arch/i386/stand/libsa/cmd_i386.c b/sys/arch/i386/stand/libsa/cmd_i386.c
index 4d8db5efb49..1934e21dff8 100644
--- a/sys/arch/i386/stand/libsa/cmd_i386.c
+++ b/sys/arch/i386/stand/libsa/cmd_i386.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd_i386.c,v 1.9 1997/10/09 22:23:00 deraadt Exp $ */
+/* $OpenBSD: cmd_i386.c,v 1.10 1997/10/17 15:03:23 weingart Exp $ */
/*
* Copyright (c) 1997 Michael Shalayeff, Tobias Weingartner
@@ -33,6 +33,7 @@
*/
#include <sys/param.h>
+#include <sys/disklabel.h>
#include <machine/biosvar.h>
#include "debug.h"
#include "biosdev.h"
@@ -41,24 +42,39 @@
static int Xdiskinfo __P((void));
static int Xregs __P((void));
+static int Xboot __P((void));
+static int Xmemory __P((void));
+
+/* From gidt.S */
+int bootbuf __P((int, int));
+
+/* From probedisk.c */
+extern bios_diskinfo_t bios_diskinfo[];
+
const struct cmd_table cmd_machine[] = {
{ "diskinfo", CMDT_CMD, Xdiskinfo },
{ "regs", CMDT_CMD, Xregs },
+ { "boot", CMDT_CMD, Xboot },
+ { "memory", CMDT_CMD, Xmemory },
{ NULL, 0 }
};
static int
Xdiskinfo()
{
- u_int32_t di;
int i;
- printf("Disk\tCylinders\tHeads\tSectors\n");
- for(i = 0x80; i < 0x84; i++){
- if ((di = biosdinfo(i)))
- printf("0x%x\t %d \t%d\t%d\n", i,
- BIOSNTRACKS(di), BIOSNHEADS(di), BIOSNSECTS(di));
+ printf("Disk\tBIOS#\tCylinders\tHeads\tSectors\n");
+ for(i = 0; bios_diskinfo[i].bios_number != -1 && i < 10; i++){
+ int d = bios_diskinfo[i].bios_number;
+
+ printf("%cd%d\t 0x%x\t %s%d \t%d\t%d\n",
+ (d & 0x80)?'h':'f', (d & 0x80)?d - 128:d, d,
+ (bios_diskinfo[i].bios_cylinders < 100)?" ":" ",
+ bios_diskinfo[i].bios_cylinders,
+ bios_diskinfo[i].bios_heads,
+ bios_diskinfo[i].bios_sectors);
}
return 0;
@@ -70,3 +86,78 @@ Xregs()
DUMP_REGS;
return 0;
}
+
+static int
+Xboot()
+{
+ int dev, part, st;
+ char *buf = (void *)0x7c00;
+
+ if(cmd.argc != 2) {
+ printf("machine boot {fd,hd}[0123][abcd]\n");
+ return 0;
+ }
+
+ /* Check arg */
+ if(cmd.argv[1][0] != 'f' && cmd.argv[1][0] != 'h')
+ goto bad;
+ if(cmd.argv[1][1] != 'd')
+ goto bad;
+ if(cmd.argv[1][2] < '0' || cmd.argv[1][2] > '3')
+ goto bad;
+ if(cmd.argv[1][3] < 'a' || cmd.argv[1][3] > 'd')
+ goto bad;
+
+ printf("Booting from %s ", cmd.argv[1]);
+
+ dev = (cmd.argv[1][0] == 'h')?0x80:0;
+ dev += (cmd.argv[1][2] - '0');
+ part = (cmd.argv[1][3] - 'a');
+
+ printf("[%x,%d]\n", dev, part);
+
+ /* Read boot sector from device */
+ st = biosd_rw(F_READ, dev, 0, 0, 1, 1, buf);
+ if(st) goto bad;
+
+ /* Frob boot flag in buffer from HD */
+ if(dev & 0x80){
+ int i, j;
+
+ for(i = 0, j = DOSPARTOFF; i < 4; i++, j += 16)
+ if(part == i)
+ buf[j] = 0x80;
+ else
+ buf[j] = 0x00;
+ }
+
+ printf("%x %x %x %x %x\n", buf[0], buf[1], buf[2], buf[3], buf[4]);
+
+ /* Load %dl, ljmp */
+ bootbuf(dev, part);
+
+bad:
+ printf("Invalid device!\n");
+ return 0;
+}
+
+int
+Xmemory()
+{
+ struct BIOS_MAP *tm = memory_map;
+ int count, total = 0;
+
+ for(count = 0; tm[count].type != BIOS_MAP_END; count++){
+ printf("Region %d: type %u at 0x%x for %uKB\n", count,
+ tm[count].type, tm[count].addr, tm[count].size/1024);
+
+ if(tm[count].type == BIOS_MAP_FREE)
+ total += tm[count].size;
+ }
+
+ printf("Low ram: %dKB High ram: %dKB\n", cnvmem, extmem);
+ printf("Total free memory: %dKB\n", total/1024);
+
+ return 0;
+}
+
diff --git a/sys/arch/i386/stand/libsa/gidt.S b/sys/arch/i386/stand/libsa/gidt.S
index dcba77861a4..db4d7da3295 100644
--- a/sys/arch/i386/stand/libsa/gidt.S
+++ b/sys/arch/i386/stand/libsa/gidt.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: gidt.S,v 1.15 1997/09/02 17:05:12 mickey Exp $ */
+/* $OpenBSD: gidt.S,v 1.16 1997/10/17 15:03:24 weingart Exp $ */
/*
* Copyright (c) 1997 Michael Shalayeff
@@ -416,3 +416,11 @@ intno = . - 1
popal
iret
+/* Call buffer at 07c0:0000 in real mode to simulate a BIOS boot */
+ENTRY(bootbuf)
+ popl %eax /* Don't need return address */
+ popl %edx /* Device */
+ popl %eax /* Partition - Not used, overwritten */
+ prot2real /* Switch */
+ ljmp $0x7c0, $0x000
+
diff --git a/sys/arch/i386/stand/libsa/libsa.h b/sys/arch/i386/stand/libsa/libsa.h
index 911a59e9cb8..15ac5f6d5ca 100644
--- a/sys/arch/i386/stand/libsa/libsa.h
+++ b/sys/arch/i386/stand/libsa/libsa.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: libsa.h,v 1.17 1997/09/17 17:56:10 mickey Exp $ */
+/* $OpenBSD: libsa.h,v 1.18 1997/10/17 15:03:26 weingart Exp $ */
/*
* Copyright (c) 1996 Michael Shalayeff
@@ -35,7 +35,9 @@
#include <lib/libsa/stand.h>
void gateA20 __P((int));
+void smpprobe __P((void));
void memprobe __P((void));
+void diskprobe __P((void));
void devboot __P((dev_t, char *));
void *alloca __P((size_t));
void machdep __P((void));
@@ -43,6 +45,7 @@ void time_print __P((void));
extern const char bdevs[][4];
extern const int nbdevs;
+extern struct BIOS_MAP *memory_map;
extern int bootdev; /* XXX pass through the global to exec_i386 */
extern u_int cnvmem, extmem; /* XXX global pass memprobe()->machdep_start() */
diff --git a/sys/arch/i386/stand/libsa/machdep.c b/sys/arch/i386/stand/libsa/machdep.c
index c5b5bed28be..14ee4567561 100644
--- a/sys/arch/i386/stand/libsa/machdep.c
+++ b/sys/arch/i386/stand/libsa/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.17 1997/10/12 21:14:23 mickey Exp $ */
+/* $OpenBSD: machdep.c,v 1.18 1997/10/17 15:03:27 weingart Exp $ */
/*
* Copyright (c) 1997 Michael Shalayeff
@@ -143,6 +143,7 @@ machdep()
cninit(); CKPT('3');
#ifndef _TEST
memprobe(); CKPT('4');
+ diskprobe(); CKPT('6');
#endif
if ((BIOS_vars.bios_apm_detail = apm_check())) {
diff --git a/sys/arch/i386/stand/libsa/memprobe.c b/sys/arch/i386/stand/libsa/memprobe.c
index 180d742f4dc..64e25790cee 100644
--- a/sys/arch/i386/stand/libsa/memprobe.c
+++ b/sys/arch/i386/stand/libsa/memprobe.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: memprobe.c,v 1.14 1997/10/12 21:01:01 mickey Exp $ */
+/* $OpenBSD: memprobe.c,v 1.15 1997/10/17 15:03:28 weingart Exp $ */
/*
* Copyright (c) 1997 Tobias Weingartner
@@ -37,36 +37,194 @@
#include "libsa.h"
static int addrprobe __P((u_int));
-u_int cnvmem, extmem;
+u_int cnvmem, extmem; /* XXX - remove */
+struct BIOS_MAP *memory_map;
-void
-memprobe()
+struct E820_desc_t {
+ u_int32_t addr_lo;
+ u_int32_t addr_hi;
+ u_int32_t size_lo;
+ u_int32_t size_hi;
+ u_int32_t type;
+} __attribute__ ((packed));
+static struct E820_desc_t Desc;
+
+
+#define E820_MAX_MAPENT 10
+
+/* BIOS int 15, AX=E820
+ *
+ * This is the "prefered" method.
+ */
+struct BIOS_MAP *
+bios_E820()
{
- int ram;
+ static struct BIOS_MAP bm[E820_MAX_MAPENT]; /* This is easier */
+ int E820Present = 0;
+ int eax = 0, count = 0;
+ volatile int ebx = 0;
- __asm __volatile(DOINT(0x12) : "=a" (cnvmem)
- :: "%ecx", "%edx", "cc");
- cnvmem &= 0xffff;
+ do {
+ BIOS_regs.biosr_es = ((unsigned)(&Desc) >> 4);
+ __asm __volatile(
+ "movl %2, %%ebx\n\t"
+ "movl $0x534D4150, %%edx\n\t"
+ DOINT(0x15) "\n\t"
+ "movl %%eax, %%edx\n\t"
+ "setc %b0\n\t"
+ "movzbl %b0, %0\n\t"
+ "cmpl $0x534D4150, %%edx\n\t"
+ "je 1f\n\t"
+ "incl %%eax\n\t"
+ "1:\n\t"
+ : "=a" (eax)
+ : "0" (0xE820),
+ "1" (ebx),
+ "c" (sizeof(Desc)),
+ "D" ((unsigned)(&Desc) & 0xF)
+ : "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "cc", "memory");
+ ebx = BIOS_regs.biosr_bx;
- printf("%d Kb conventional memory.\n", cnvmem);
+ if(eax) break; /* Not present, or done */
- /* probe extended memory
- *
- * There is no need to do this in assembly language. This is
- * much easier to debug in C anyways.
- */
- for(ram = 1024; ram < 512*1024; ram += 4){
+ /* We are ignoring the upper 32 bits in the 64 bit
+ * integer returned. If anyone has a PC where the
+ * upper 32 bits are not zeros, *please* tell me! ;)
+ *
+ * NOTE: the BIOS_MAP_* numbers are the same, save for
+ * the "zero" case, which we remap to reserved.
+ */
+ bm[count].addr = Desc.addr_lo;
+ bm[count].size = Desc.size_lo;
+ bm[count].type = (Desc.type)?Desc.type:BIOS_MAP_RES;
- if(!(ram % 64))
- printf("Probing memory: %d KB\r", ram-1024);
- if(addrprobe(ram))
- break;
+ E820Present = 1;
+ } while((++count < E820_MAX_MAPENT) && (ebx != 0)); /* Do not re-oder! */
+
+ if(E820Present){
+ printf("int 0x15 [E820]\n");
+ bm[count].type = BIOS_MAP_END;
+ return(bm);
}
- printf("%d Kb extended memory.\n", ram-1024);
- extmem = ram - 1024;
+ return(NULL);
+}
+
+
+/* BIOS int 15, AX=E801
+ *
+ * Only used if int 15, AX=E820 does not work.
+ * This should work for more than 64MB.
+ */
+struct BIOS_MAP *
+bios_E801()
+{
+ static struct BIOS_MAP bm[3];
+ int eax, edx = 0;
+
+ /* Test for 0xE801 */
+ __asm __volatile(
+ DOINT(0x15) "\n\t"
+ "setc %b0\n\t"
+ "movzbl %b0, %0\n\t"
+ : "=a" (eax)
+ : "a" (0xE801)
+ );
+
+ /* Make a memory map from info */
+ if(!eax){
+ printf("int 0x15 [E801], ");
+
+ __asm __volatile(
+ DOINT(0x15) "\n\t"
+ : "=a" (eax), "=d" (edx)
+ : "a" (0xE801)
+ );
+
+ /* Make sure only valid bits */
+ eax &= 0xFFFF;
+ edx &= 0xFFFF;
+
+ /* Fill out BIOS map */
+ bm[0].addr = (1024 * 1024); /* 1MB */
+ bm[0].size = eax * 1024;
+ bm[0].type = BIOS_MAP_FREE;
+
+ bm[1].addr = (1024 * 1024) * 16; /* 16MB */
+ bm[1].size = (edx * 1024) * 64;
+ bm[1].type = BIOS_MAP_FREE;
+
+ bm[2].type = BIOS_MAP_END;
+
+ return(bm);
+ }
+
+ return(NULL);
+}
+
+
+/* BIOS int 15, AX=8800
+ *
+ * Only used if int 15, AX=E801 does not work.
+ * Machines with this are restricted to 64MB.
+ */
+struct BIOS_MAP *
+bios_8800()
+{
+ static struct BIOS_MAP bm[2];
+ int eax, mem;
+
+ __asm __volatile(
+ DOINT(0x15) "\n\t"
+ "movl %%eax, %%ecx\n\t"
+ "setc %b0\n\t"
+ "movzbl %b0, %0\n\t"
+ : "=a" (eax), "=c" (mem)
+ : "a" (0x8800)
+ );
+
+ if(eax) return(NULL);
+
+ printf("int 0x15 [8800], ");
+
+ /* Fill out a BIOS_MAP */
+ bm[0].addr = 1024*1024; /* 1MB */
+ bm[0].size = (mem & 0xFFFF) * 1024;
+ bm[0].type = BIOS_MAP_FREE;
+
+ bm[1].type = BIOS_MAP_END;
+
+ return(bm);
+}
+
+
+/* BIOS int 0x12 Get Conventional Memory
+ *
+ * Only used if int 15, AX=E820 does not work.
+ */
+struct BIOS_MAP *
+bios_int12()
+{
+ static struct BIOS_MAP bm[2];
+ int mem;
+
+ printf("int 0x12\n");
+
+ __asm __volatile(DOINT(0x12) : "=a" (mem)
+ :: "%ecx", "%edx", "cc");
+ mem &= 0xffff;
+
+ /* Fill out a BIOS_MAP */
+ bm[0].addr = 0;
+ bm[0].size = mem * 1024;
+ bm[0].type = BIOS_MAP_FREE;
+
+ bm[1].type = BIOS_MAP_END;
+
+ return(bm);
}
+
/* addrprobe(kloc): Probe memory at address kloc * 1024.
*
* This is a hack, but it seems to work ok. Maybe this is
@@ -77,6 +235,8 @@ memprobe()
* return values just written on non-existent memory...
*
* BTW: These machines are pretty broken IMHO.
+ *
+ * XXX - Does not detect aliased memory.
*/
static int
addrprobe(kloc)
@@ -122,3 +282,127 @@ addrprobe(kloc)
}
+/* Probe for all extended memory.
+ *
+ * This is only used as a last resort. If we resort to this
+ * routine, we are getting pretty desparate. Hopefully nobody
+ * has to rely on this after all the work above.
+ *
+ * XXX - Does not detect aliases memory.
+ * XXX - Could be destructive, as it does write.
+ */
+struct BIOS_MAP *
+badprobe()
+{
+ static struct BIOS_MAP bm[2];
+ int ram;
+
+ printf("Physical, ");
+ /* probe extended memory
+ *
+ * There is no need to do this in assembly language. This is
+ * much easier to debug in C anyways.
+ */
+ for(ram = 1024; ram < 512*1024; ram += 4)
+ if(addrprobe(ram))
+ break;
+
+ bm[0].addr = 1024 * 1024;
+ bm[0].size = (ram - 1024) * 1024;
+ bm[0].type = BIOS_MAP_FREE;
+
+ bm[1].type = BIOS_MAP_END;
+
+ return(bm);
+}
+
+
+int
+count(map)
+ struct BIOS_MAP *map;
+{
+ int i;
+
+ for(i = 0; map[i].type != BIOS_MAP_END; i++) ;
+
+ return(i);
+}
+
+
+struct BIOS_MAP *
+combine(a, b)
+ struct BIOS_MAP *a, *b;
+{
+ struct BIOS_MAP *res;
+ int size, i;
+
+ /* Sanity checks */
+ if(!b) return(a);
+ if(!a) return(b);
+
+ size = (count(a) + count(b) + 1) * sizeof(struct BIOS_MAP);
+ res = alloc(size);
+
+ /* Again */
+ if(!res) return(NULL); /* We are in deep doggie-doo */
+
+ for(i = 0; a[i].type != BIOS_MAP_END; i++)
+ res[i] = a[i];
+ size = count(a);
+ for(; b[i - size].type != BIOS_MAP_END; i++)
+ res[i] = b[i - size];
+
+ res[i].type = BIOS_MAP_END;
+ return(res);
+}
+
+
+void
+memprobe()
+{
+ struct BIOS_MAP *tm, *em, *bm; /* total, extended, base */
+ int count, total = 0;
+
+ printf("Probing memory: ");
+ tm = em = bm = NULL;
+
+ tm = bios_E820();
+ if(!tm){
+ em = bios_E801();
+ if(!em) em = bios_8800();
+ if(!em) em = badprobe();
+ bm = bios_int12();
+
+ tm = combine(bm, em);
+ }
+
+ /* Register in global var */
+ memory_map = tm;
+ printf("mem0:");
+
+ /* Get total free memory */
+ for(count = 0; tm[count].type != BIOS_MAP_END; count++) {
+ if(tm[count].type == BIOS_MAP_FREE) {
+ total += tm[count].size;
+
+ printf(" %dKB", tm[count].size/1024);
+ }
+ }
+ printf("\n");
+
+ /* XXX - Compatibility, remove later */
+ cnvmem = extmem = 0;
+ for(count = 0; tm[count].type != BIOS_MAP_END; count++) {
+ if((tm[count].addr < 0xFFFFF) && (tm[count].type == BIOS_MAP_FREE)){
+
+ cnvmem += tm[count].size;
+ }
+ if((tm[count].addr > 0xFFFFF) && (tm[count].type == BIOS_MAP_FREE)){
+
+ extmem += tm[count].size;
+ }
+ }
+ cnvmem /= 1024;
+ extmem /= 1024;
+}
+