summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhpa <hpa>2001-12-11 01:14:19 +0000
committerhpa <hpa>2001-12-11 01:14:19 +0000
commit0d064db972a8bdff2e508a56f07e533348b84017 (patch)
treef7c95efdcc777f145fbd2e9396563c03a92d98da
parent1e15e253ac7f91bc16bf850b28c6e046856e9f77 (diff)
downloadsyslinux-0d064db972a8bdff2e508a56f07e533348b84017.tar.gz
Checkpoint: add printf() for debugging, remove query of E881 (seems
to hang some systems), move E820 table to conventional memory (sized dynamically), use BIOS memory pointer to determine where in DOS memory to put our routine.
-rw-r--r--memdisk/Makefile5
-rw-r--r--memdisk/conio.c310
-rw-r--r--memdisk/conio.h4
-rw-r--r--memdisk/e820test.c5
-rw-r--r--memdisk/init.S1644
-rw-r--r--memdisk/memdisk.asm81
-rw-r--r--memdisk/memdisk.h26
-rw-r--r--memdisk/msetup.c67
-rw-r--r--memdisk/setup.c76
9 files changed, 508 insertions, 110 deletions
diff --git a/memdisk/Makefile b/memdisk/Makefile
index 83b2210f..d5884c0d 100644
--- a/memdisk/Makefile
+++ b/memdisk/Makefile
@@ -12,7 +12,7 @@
## -----------------------------------------------------------------------
CC = gcc
-CFLAGS = -g -O2 -fomit-frame-pointer -march=i386 \
+CFLAGS = -O2 -fomit-frame-pointer -march=i386 \
-malign-functions=0 -malign-jumps=0 -malign-loops=0
LDFLAGS =
AS = as
@@ -33,8 +33,7 @@ clean:
$(AS) -o $@ $<
%.s16: %.s
- echo '.code16' > $@
- sed -e 's/\bcall\b/calll/g' -e 's/\bret\b/retl/g' < $< >> $@
+ echo '.code16gcc' | cat - $< > $@
%.s: %.S
$(CC) -x c $(CFLAGS) -Wp,-traditional -E -o $@ $<
diff --git a/memdisk/conio.c b/memdisk/conio.c
index c2f8616a..8599dddb 100644
--- a/memdisk/conio.c
+++ b/memdisk/conio.c
@@ -52,3 +52,313 @@ int puts(const char *s)
return count;
}
+
+/*
+ * Oh, it's a waste of space, but oh-so-yummy for debugging. It's just
+ * initialization code anyway, so it doesn't take up space when we're
+ * actually running. This version of printf() does not include 64-bit
+ * support. "Live with it."
+ *
+ * Most of this code was shamelessly snarfed from the Linux kernel, then
+ * modified.
+ */
+
+static inline int
+isdigit(int ch)
+{
+ return (ch >= '0') && (ch <= '9');
+}
+
+static int skip_atoi(const char **s)
+{
+ int i=0;
+
+ while (isdigit(**s))
+ i = i*10 + *((*s)++) - '0';
+ return i;
+}
+
+static int strnlen(const char *s, int maxlen)
+{
+ const char *es = s;
+ while ( *es && maxlen ) {
+ es++; maxlen--;
+ }
+
+ return (es-s);
+}
+
+#define ZEROPAD 1 /* pad with zero */
+#define SIGN 2 /* unsigned/signed long */
+#define PLUS 4 /* show plus */
+#define SPACE 8 /* space if plus */
+#define LEFT 16 /* left justified */
+#define SPECIAL 32 /* 0x */
+#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
+
+#define do_div(n,base) ({ \
+int __res; \
+__res = ((unsigned long) n) % (unsigned) base; \
+n = ((unsigned long) n) / (unsigned) base; \
+__res; })
+
+static char * number(char * str, long num, int base, int size, int precision
+ ,int type)
+{
+ char c,sign,tmp[66];
+ const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
+ int i;
+
+ if (type & LARGE)
+ digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ if (type & LEFT)
+ type &= ~ZEROPAD;
+ if (base < 2 || base > 36)
+ return 0;
+ c = (type & ZEROPAD) ? '0' : ' ';
+ sign = 0;
+ if (type & SIGN) {
+ if (num < 0) {
+ sign = '-';
+ num = -num;
+ size--;
+ } else if (type & PLUS) {
+ sign = '+';
+ size--;
+ } else if (type & SPACE) {
+ sign = ' ';
+ size--;
+ }
+ }
+ if (type & SPECIAL) {
+ if (base == 16)
+ size -= 2;
+ else if (base == 8)
+ size--;
+ }
+ i = 0;
+ if (num == 0)
+ tmp[i++]='0';
+ else while (num != 0)
+ tmp[i++] = digits[do_div(num,base)];
+ if (i > precision)
+ precision = i;
+ size -= precision;
+ if (!(type&(ZEROPAD+LEFT)))
+ while(size-->0)
+ *str++ = ' ';
+ if (sign)
+ *str++ = sign;
+ if (type & SPECIAL) {
+ if (base==8)
+ *str++ = '0';
+ else if (base==16) {
+ *str++ = '0';
+ *str++ = digits[33];
+ }
+ }
+ if (!(type & LEFT))
+ while (size-- > 0)
+ *str++ = c;
+ while (i < precision--)
+ *str++ = '0';
+ while (i-- > 0)
+ *str++ = tmp[i];
+ while (size-- > 0)
+ *str++ = ' ';
+ return str;
+}
+
+/* Forward decl. needed for IP address printing stuff... */
+int sprintf(char * buf, const char *fmt, ...);
+
+int vsprintf(char *buf, const char *fmt, va_list args)
+{
+ int len;
+ unsigned long num;
+ int i, base;
+ char * str;
+ const char *s;
+
+ int flags; /* flags to number() */
+
+ int field_width; /* width of output field */
+ int precision; /* min. # of digits for integers; max
+ number of chars for from string */
+ int qualifier; /* 'h', 'l', or 'L' for integer fields */
+
+ for (str=buf ; *fmt ; ++fmt) {
+ if (*fmt != '%') {
+ *str++ = *fmt;
+ continue;
+ }
+
+ /* process flags */
+ flags = 0;
+ repeat:
+ ++fmt; /* this also skips first '%' */
+ switch (*fmt) {
+ case '-': flags |= LEFT; goto repeat;
+ case '+': flags |= PLUS; goto repeat;
+ case ' ': flags |= SPACE; goto repeat;
+ case '#': flags |= SPECIAL; goto repeat;
+ case '0': flags |= ZEROPAD; goto repeat;
+ }
+
+ /* get field width */
+ field_width = -1;
+ if (isdigit(*fmt))
+ field_width = skip_atoi(&fmt);
+ else if (*fmt == '*') {
+ ++fmt;
+ /* it's the next argument */
+ field_width = va_arg(args, int);
+ if (field_width < 0) {
+ field_width = -field_width;
+ flags |= LEFT;
+ }
+ }
+
+ /* get the precision */
+ precision = -1;
+ if (*fmt == '.') {
+ ++fmt;
+ if (isdigit(*fmt))
+ precision = skip_atoi(&fmt);
+ else if (*fmt == '*') {
+ ++fmt;
+ /* it's the next argument */
+ precision = va_arg(args, int);
+ }
+ if (precision < 0)
+ precision = 0;
+ }
+
+ /* get the conversion qualifier */
+ qualifier = -1;
+ if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
+ qualifier = *fmt;
+ ++fmt;
+ }
+
+ /* default base */
+ base = 10;
+
+ switch (*fmt) {
+ case 'c':
+ if (!(flags & LEFT))
+ while (--field_width > 0)
+ *str++ = ' ';
+ *str++ = (unsigned char) va_arg(args, int);
+ while (--field_width > 0)
+ *str++ = ' ';
+ continue;
+
+ case 's':
+ s = va_arg(args, char *);
+ if (!s)
+ s = "(null)";
+
+ len = strnlen(s, precision);
+
+ if (!(flags & LEFT))
+ while (len < field_width--)
+ *str++ = ' ';
+ for (i = 0; i < len; ++i)
+ *str++ = *s++;
+ while (len < field_width--)
+ *str++ = ' ';
+ continue;
+
+ case 'p':
+ if (field_width == -1) {
+ field_width = 2*sizeof(void *);
+ flags |= ZEROPAD;
+ }
+ str = number(str,
+ (unsigned long) va_arg(args, void *), 16,
+ field_width, precision, flags);
+ continue;
+
+
+ case 'n':
+ if (qualifier == 'l') {
+ long * ip = va_arg(args, long *);
+ *ip = (str - buf);
+ } else {
+ int * ip = va_arg(args, int *);
+ *ip = (str - buf);
+ }
+ continue;
+
+ case '%':
+ *str++ = '%';
+ continue;
+
+ /* integer number formats - set up the flags and "break" */
+ case 'o':
+ base = 8;
+ break;
+
+ case 'X':
+ flags |= LARGE;
+ case 'x':
+ base = 16;
+ break;
+
+ case 'd':
+ case 'i':
+ flags |= SIGN;
+ case 'u':
+ break;
+
+ default:
+ *str++ = '%';
+ if (*fmt)
+ *str++ = *fmt;
+ else
+ --fmt;
+ continue;
+ }
+ if (qualifier == 'l')
+ num = va_arg(args, unsigned long);
+ else if (qualifier == 'h') {
+ num = (unsigned short) va_arg(args, int);
+ if (flags & SIGN)
+ num = (short) num;
+ } else if (flags & SIGN)
+ num = va_arg(args, int);
+ else
+ num = va_arg(args, unsigned int);
+ str = number(str, num, base, field_width, precision, flags);
+ }
+ *str = '\0';
+ return str-buf;
+}
+
+int sprintf(char * buf, const char *fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i=vsprintf(buf,fmt,args);
+ va_end(args);
+ return i;
+}
+
+int printf(const char *fmt, ...)
+{
+ char printf_buf[1024];
+ va_list args;
+ int printed;
+
+ va_start(args, fmt);
+ printed = vsprintf(printf_buf, fmt, args);
+ va_end(args);
+
+ puts(printf_buf);
+
+ return printed;
+}
+
diff --git a/memdisk/conio.h b/memdisk/conio.h
index ced7c2cb..7f823aeb 100644
--- a/memdisk/conio.h
+++ b/memdisk/conio.h
@@ -20,7 +20,11 @@
#ifndef CONIO_H
#define CONIO_H
+#include <stdint.h>
+#include <stdarg.h>
+
int putchar(int);
int puts(const char *);
+int printf(const char *, ...);
#endif
diff --git a/memdisk/e820test.c b/memdisk/e820test.c
index 2717fdcd..2d8be07a 100644
--- a/memdisk/e820test.c
+++ b/memdisk/e820test.c
@@ -24,6 +24,11 @@
extern void parse_mem(void);
extern uint32_t dos_mem, low_mem, high_mem;
+void __attribute__((noreturn)) die(void)
+{
+ abort();
+}
+
void printranges(void) {
int i;
diff --git a/memdisk/init.S16 b/memdisk/init.S16
index 1cdff31f..955e8726 100644
--- a/memdisk/init.S16
+++ b/memdisk/init.S16
@@ -19,7 +19,7 @@
* This module *MUST* get linked first into the image
*/
- .section ".text", "ax"
+ .text
.code16
/*
@@ -114,28 +114,38 @@ ramdisk_max: .long 0xffffffff # Load ramdisk as high as
/* ------------------- End of setup header --------------------------- */
-/*
- * Canonicalize CS to match the other segments
- */
-start:
- pushw %ds
- pushw $start2
- lret
+LOWSEG = 0x0800 # 0x8000 physical
-start2:
/*
- * Set up the operating environment expected by the C code.
+ * Move ourselves down in memory to reduce the risk of conflicts;
+ * the canonicalize CS to match the other segments...
+ *
* The C code uses 32-bit registers to make sure the high part of
* %esp is zero.
*
- * The C code expects %cs == %ds == %es, and %fs == 0.
+ * The C code expects %cs == %ds == %es == %ss, and %fs == 0.
+ */
+start:
+ movw $LOWSEG,%ax
+ movw %ax,%es
+ movzbw setup_sects,%cx
+ inc %cx # Add one for the boot sector
+ shlw $7,%cx # Convert to dwords
+ xorw %si,%si
+ xorw %di,%di
+ movw %si,%fs # %fs -> zero segment
+ cld
+ rep ; movsl %ds:(%si),%es:(%di)
+ movw %ax,%ds
+ movw %ax,%ss
+ xorl %esp,%esp # Stack at the top of the segment
+ ljmp $LOWSEG, $startc
+
+startc:
+/*
+ * Set up the operating environment expected by the C code.
*/
- .byte 0x66,0x0f,0xb7,0xe4 # movzwl %sp,%esp
- pushw %ds
- popw %es
- xorw %ax,%ax
- movw %ax,%fs
- sti # We may want to kill this?
+ sti # Maybe not?
calll setup # Call the C code
# The setup function returns the drive number,
# which should be returned in %dl
diff --git a/memdisk/memdisk.asm b/memdisk/memdisk.asm
index 3c9513dd..ddaf100b 100644
--- a/memdisk/memdisk.asm
+++ b/memdisk/memdisk.asm
@@ -239,41 +239,37 @@ setup_regs:
ret
int15_e820:
- cmp edx,534D4150h
+ cmp edx,534D4150h ; "SMAP"
jne near oldint15
cmp ecx,20 ; Need 20 bytes
jb err86
+ push ds
+ push cs
+ pop ds
push edx ; "SMAP"
- push esi
- push edi
and ebx,ebx
jne .renew
- mov ebx,[E820Table]
-.renew: mov esi,ebx
- xor edi,edi
- mov di,cs
- shr di,4
- add edi,E820Buf
- mov ecx,24/2
- call bcopy
- add ebx, byte 12
- pop edi
- pop esi
- mov eax,[cs:E820Buf]
+ mov ebx,E820Table
+.renew:
+ add bx, byte 12 ; Advance to next
+ mov eax,[bx-12] ; Start addr (low)
mov [es:di],eax
- mov eax,[cs:E820Buf+4]
- mov [es:di+4],eax
- mov eax,[cs:E820Buf+12]
- mov [es:di+8],eax
- mov eax,[cs:E820Buf+16]
- mov [es:di+12],eax
- mov eax,[cs:E820Buf+8]
+ mov ecx,[bx-8] ; Start addr (high)
+ mov [es:di+4],ecx
+ mov eax,[bx] ; End addr (low)
+ mov ecx,[bx+4] ; End addr (high)
+ sub eax,[bx-12] ; Derive the length
+ sbb ecx,[bx-8]
+ mov [es:di+8],eax ; Length (low)
+ mov [es:di+12],ecx ; Length (high)
+ mov eax,[bx-4] ; Type
mov [es:di+16],eax
- cmp dword [cs:E820Buf+20], byte -1
+ cmp dword [bx+8], byte -1 ; Type of next = end?
jne .notdone
xor ebx,ebx ; Done with table
.notdone:
pop eax ; "SMAP"
+ pop ds
mov ecx,20 ; Bytes loaded
int15_success:
mov byte [bp+12], 02h ; Clear CF
@@ -412,33 +408,34 @@ Mover_dst2: db 0 ; High 8 bits of source addy
LastStatus db 0 ; Last return status
- section .bss
- alignb 4
+ alignb 4, db 0
PatchArea equ $ ; This gets filled in by the installer
-Cylinders resw 1 ; Cylinder count
-Heads resw 1 ; Head count
-Sectors resd 1 ; Sector count (zero-extended)
-DiskSize resd 1 ; Size of disk in blocks
-DiskBuf resd 1 ; Linear address of high memory disk
+Cylinders dw 0 ; Cylinder count
+Heads dw 0 ; Head count
+Sectors dd 0 ; Sector count (zero-extended)
+DiskSize dd 0 ; Size of disk in blocks
+DiskBuf dd 0 ; Linear address of high memory disk
-E820Table resd 1 ; E820 table in high memory
-Mem1MB resd 1 ; 1MB-16MB memory amount (1K)
-Mem16MB resd 1 ; 16MB-4G memory amount (64K)
-MemInt1588 resd 1 ; 1MB-65MB memory amount (1K)
+Mem1MB dd 0 ; 1MB-16MB memory amount (1K)
+Mem16MB dd 0 ; 16MB-4G memory amount (64K)
+MemInt1588 dd 0 ; 1MB-65MB memory amount (1K)
-OldInt13 resd 1 ; INT 13h in chain
-OldInt15 resd 1 ; INT 15h in chain
+OldInt13 dd 0 ; INT 13h in chain
+OldInt15 dd 0 ; INT 15h in chain
-OldDosMem resw 1 ; Old position of DOS mem end
+OldDosMem dw 0 ; Old position of DOS mem end
-DriveNo resb 1 ; Our drive number
-DriveType resb 1 ; Our drive type (floppies)
+DriveNo db 0 ; Our drive number
+DriveType db 0 ; Our drive type (floppies)
; End patch area
-Stack resd 2 ; Saved SS:ESP on invocation
-E820Buf resd 6 ; E820 fetch buffer
-SavedAX resw 1 ; AX saved on invocation
+Stack dd 0 ; Saved SS:ESP on invocation
+ dw 0
+SavedAX dw 0 ; AX saved on invocation
+
+ alignb 4, db 0 ; We *MUST* end on a dword boundary
+E820Table equ $ ; The installer loads the E820 table here
TotalSize equ $ ; End pointer
diff --git a/memdisk/memdisk.h b/memdisk/memdisk.h
new file mode 100644
index 00000000..b54968dd
--- /dev/null
+++ b/memdisk/memdisk.h
@@ -0,0 +1,26 @@
+#ident "$Id$"
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2001 H. Peter Anvin - All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ * Bostom MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * memdisk.h
+ *
+ * Miscellaneous header definitions
+ */
+
+#ifndef MEMDISK_H
+#define MEMDISK_H
+
+/* What to call when we're dead */
+extern void __attribute__((noreturn)) die(void);
+
+#endif
diff --git a/memdisk/msetup.c b/memdisk/msetup.c
index c37169be..ccb43521 100644
--- a/memdisk/msetup.c
+++ b/memdisk/msetup.c
@@ -18,6 +18,8 @@
*/
#include <stdint.h>
+#include "memdisk.h"
+#include "conio.h"
#include "e820.h"
static inline int get_e820(void)
@@ -26,28 +28,36 @@ static inline int get_e820(void)
uint64_t base;
uint64_t len;
uint32_t type;
- } __attribute__((packed));
+ };
struct e820_info buf;
uint32_t lastptr = 0;
- int copied;
- int range_count;
+ uint32_t copied;
+ int range_count = 0;
do {
+ puts("Calling INT 15 E820...\n");
asm volatile("int $0x15 ; "
"jc 1f ; "
"cmpl $0x534d4150, %%eax ; "
"je 2f\n"
"1:\n\t"
- "xorl %%ecx, %%ecx\n"
+ "xorl %0,%0\n"
"2:"
- : "=c" (copied), "=&b" (lastptr)
+ : "=c" (copied), "+b" (lastptr)
: "a" (0x0000e820), "d" (0x534d4150),
- "c" (20), "D" (&buf)
- : "esi", "ebp");
+ "c" (sizeof(buf)), "D" (&buf)
+ : "eax", "edx", "esi", "edi", "ebp");
if ( copied < 20 )
break;
+ printf("BIOS e820: %08x%08x %08x%08x %u\n",
+ (uint32_t)(buf.base >> 32),
+ (uint32_t)buf.base,
+ (uint32_t)(buf.len >> 32),
+ (uint32_t)buf.len,
+ buf.type);
+
insertrange(buf.base, buf.len, buf.type);
range_count++;
@@ -60,42 +70,22 @@ static inline void get_dos_mem(void)
{
uint16_t dos_kb;
+ puts("Calling INT 12...\n");
asm volatile("int $0x12" : "=a" (dos_kb)
:: "ebx", "ecx", "edx", "esi", "edi", "ebp");
+
+ printf("BIOS 12: %u K DOS memory\n", dos_kb);
insertrange(0, (uint64_t)((uint32_t)dos_kb << 10), 1);
}
-static inline int get_e881(void)
-{
- uint32_t low_mem;
- uint32_t high_mem;
- uint8_t err;
-
- asm volatile("movw $0xe881, %%ax ; "
- "int $0x15 ; "
- "setc %2"
- : "=a" (low_mem), "=b" (high_mem), "=d" (err)
- :: "ecx", "esi", "edi", "ebp");
-
- if ( !err ) {
- if ( low_mem ) {
- insertrange(0x100000, (uint64_t)low_mem << 10, 1);
- }
- if ( high_mem ) {
- insertrange(0x1000000, (uint64_t)high_mem << 16, 1);
- }
- }
-
- return err;
-}
-
static inline int get_e801(void)
{
uint16_t low_mem;
uint16_t high_mem;
uint8_t err;
+ puts("Calling INT 15 E801...\n");
asm volatile("movw $0xe801, %%ax ; "
"int $0x15 ; "
"setc %2"
@@ -103,6 +93,9 @@ static inline int get_e801(void)
:: "ecx", "esi", "edi", "ebp");
if ( !err ) {
+ printf("BIOS e801: %u K low mem, %u K high mem\n",
+ low_mem, high_mem << 6);
+
if ( low_mem ) {
insertrange(0x100000, (uint64_t)((uint32_t)low_mem << 10), 1);
}
@@ -119,6 +112,7 @@ static inline int get_88(void)
uint16_t low_mem;
uint8_t err;
+ puts("Calling INT 15 88...\n");
asm volatile("movb $0x88,%%ah ; "
"int $0x15 ; "
"setc %1"
@@ -126,6 +120,8 @@ static inline int get_88(void)
:: "ebx", "ecx", "esi", "edi", "ebp");
if ( !err ) {
+ printf("BIOS 88: %u K extended memory\n", low_mem);
+
if ( low_mem ) {
insertrange(0x100000, (uint64_t)((uint32_t)low_mem << 10), 1);
}
@@ -142,11 +138,10 @@ void get_mem(void)
{
if ( get_e820() ) {
get_dos_mem();
- if ( get_e881() ) {
- if ( get_e801() ) {
- if ( get_88() ) {
- /* Running out of ideas here... */
- }
+ if ( get_e801() ) {
+ if ( get_88() ) {
+ puts("MEMDISK: Unable to obtain memory map\n");
+ die();
}
}
}
diff --git a/memdisk/setup.c b/memdisk/setup.c
index 64d66ec2..196f33bb 100644
--- a/memdisk/setup.c
+++ b/memdisk/setup.c
@@ -32,7 +32,6 @@ struct patch_area {
uint32_t disksize;
uint32_t diskbuf;
- uint32_t e820table;
uint32_t mem1mb;
uint32_t mem16mb;
uint32_t memint1588;
@@ -88,7 +87,7 @@ wrz_16(uint32_t addr, uint16_t data)
asm volatile("movw %0,%%fs:%1" :: "ri" (data), "m" (*(uint16_t *)addr));
}
static inline void
-wrz_32(uint32_t addr, uint16_t data)
+wrz_32(uint32_t addr, uint32_t data)
{
asm volatile("movl %0,%%fs:%1" :: "ri" (data), "m" (*(uint32_t *)addr));
}
@@ -173,41 +172,70 @@ const struct geometry *get_disk_image_geometry(uint32_t where, uint32_t size)
}
/*
+ * Jump here if all hope is gone...
+ */
+void __attribute__((noreturn)) die(void)
+{
+ asm volatile("sti");
+ for(;;)
+ asm volatile("hlt");
+}
+
+/*
* Actual setup routine
* Returns the drive number (which is then passed in %dl to the
* called routine.)
*/
uint32_t setup(void)
{
- unsigned int size = (int) &_binary_memdisk_bin_size;
+ unsigned int bin_size = (int) &_binary_memdisk_bin_size;
struct memdisk_header *hptr;
struct patch_area *pptr;
uint16_t driverseg;
uint32_t driverptr, driveraddr;
+ uint16_t dosmem_k;
+ uint32_t stddosmem;
uint8_t driveno = 0;
uint8_t status;
uint16_t exitcode;
const struct geometry *geometry;
+ int total_size;
/* Show signs of life */
- puts("Memdisk: hello, world!\n");
+ puts("Memdisk: Hello, World!\n");
+
+ if ( !shdr->ramdisk_image || !shdr->ramdisk_size ) {
+ puts("MEMDISK: No ramdisk image specified!\n");
+ die();
+ }
+
+ printf("Test of simple printf...\n");
+ printf("Ramdisk at 0x%08x, length 0x%08x\n",
+ shdr->ramdisk_image, shdr->ramdisk_size);
- for(;;);
+ /* Reserve the ramdisk memory */
+ insertrange(shdr->ramdisk_image, shdr->ramdisk_size, 2);
geometry = get_disk_image_geometry(shdr->ramdisk_image, shdr->ramdisk_size);
get_mem();
parse_mem();
+ printf("dos_mem = %#10x (%u K)\n"
+ "low_mem = %#10x (%u K)\n"
+ "high_mem = %#10x (%u K)\n",
+ dos_mem, dos_mem >> 10,
+ low_mem, low_mem >> 10,
+ high_mem, high_mem >> 10);
+
/* Figure out where it needs to go */
hptr = (struct memdisk_header *) &_binary_memdisk_bin_start;
pptr = (struct patch_area *)(_binary_memdisk_bin_start + hptr->patch_offs);
- if ( hptr->total_size > dos_mem ) {
- /* Badness... */
- }
+ dosmem_k = rdz_16(BIOS_BASEMEM);
+ pptr->olddosmem = dosmem_k;
+ stddosmem = dosmem_k << 10;
- pptr->olddosmem = rdz_16(BIOS_BASEMEM);
pptr->driveno = geometry->driveno;
pptr->drivetype = geometry->type;
pptr->cylinders = geometry->c;
@@ -216,9 +244,25 @@ uint32_t setup(void)
pptr->disksize = geometry->sectors;
pptr->diskbuf = shdr->ramdisk_image;
- driveraddr = dos_mem - hptr->total_size;
+ /* The size is given by hptr->total_size plus the size of the
+ E820 map -- 12 bytes per range; we may need as many as
+ 2 additional ranges plus the terminating range, over what
+ nranges currently show. */
+
+ total_size = hptr->total_size + (nranges+3)*12;
+ printf("Total size needed = %u bytes\n", total_size);
+
+ if ( total_size > dos_mem ) {
+ puts("MEMDISK: Insufficient low memory\n");
+ die();
+ }
+
+ driveraddr = stddosmem - total_size;
driveraddr &= ~0x3FF;
+ printf("Old dos memory at 0x%05x (map says 0x%05x), loading at 0x%05x\n",
+ stddosmem, dos_mem, driveraddr);
+
/* Reserve this range of memory */
insertrange(driveraddr, dos_mem-driveraddr, 2);
parse_mem();
@@ -238,12 +282,19 @@ uint32_t setup(void)
/* Claim the memory and copy the driver into place */
wrz_16(BIOS_BASEMEM, dos_mem >> 10);
+ /* Copy driver followed by E820 table */
asm volatile("pushw %%es ; "
"movw %0,%%es ; "
+ "cld ; "
+ "rep ; movsl %%ds:(%%si), %%es:(%%di) ; "
+ "movw %2,%%cx ; "
+ "movw %1,%%si ; "
"rep ; movsl %%ds:(%%si), %%es:(%%di) ; "
"popw %%es"
:: "r" (driverseg),
- "c" (size >> 2),
+ "g" ((uint16_t)((nranges+1)*3)), /* 3 dwords/range */
+ "g" ((uint16_t)ranges),
+ "c" (bin_size >> 2),
"S" (&_binary_memdisk_bin_start),
"D" (0));
@@ -266,7 +317,8 @@ uint32_t setup(void)
: "ebx", "ecx", "edx", "esi", "edi", "ebp");
if ( status ) {
- /* Badness... */
+ puts("MEMDISK: Failed to load new boot sector\n");
+ die();
}
/* On return the assembly code will jump to the boot vector */