From: hpa Date: Tue, 11 Dec 2001 01:14:19 +0000 (+0000) Subject: Checkpoint: add printf() for debugging, remove query of E881 (seems X-Git-Tag: syslinux-3.11~789 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0d064db972a8bdff2e508a56f07e533348b84017;p=profile%2Fivi%2Fsyslinux.git 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. --- diff --git a/memdisk/Makefile b/memdisk/Makefile index 83b2210..d5884c0 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 c2f8616..8599ddd 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 ced7c2c..7f823ae 100644 --- a/memdisk/conio.h +++ b/memdisk/conio.h @@ -20,7 +20,11 @@ #ifndef CONIO_H #define CONIO_H +#include +#include + int putchar(int); int puts(const char *); +int printf(const char *, ...); #endif diff --git a/memdisk/e820test.c b/memdisk/e820test.c index 2717fdc..2d8be07 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 1cdff31..955e872 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 3c9513d..ddaf100 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 0000000..b54968d --- /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 c37169b..ccb4352 100644 --- a/memdisk/msetup.c +++ b/memdisk/msetup.c @@ -18,6 +18,8 @@ */ #include +#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 64d66ec..196f33b 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 */