From fc50ce2dd9f4de675605169495a980426fb97181 Mon Sep 17 00:00:00 2001 From: hpa Date: Sat, 18 Dec 2004 23:28:30 +0000 Subject: [PATCH] Make the DOS-based installer actually work; mark debugging statements as "dprintf" --- dos/argv.c | 10 +++++--- dos/crt0.S | 2 +- dos/syslinux.c | 79 ++++++++++++++++++++++++++++++++++++++++------------------ 3 files changed, 63 insertions(+), 28 deletions(-) diff --git a/dos/argv.c b/dos/argv.c index 62c3b04..5535331 100644 --- a/dos/argv.c +++ b/dos/argv.c @@ -35,6 +35,7 @@ #include #include +#include #define ALIGN_UP(p,t) ((t *)(((uintptr_t)(p) + (sizeof(t)-1)) & ~(sizeof(t)-1))) @@ -67,19 +68,22 @@ int __parse_argv(char ***argv, const char *str) } /* This test is AFTER we have processed the null byte; - we treat it as a whitespace character */ + we treat it as a whitespace character so it terminates + the last argument */ if ( ! *p ) break; } q--; /* Point to final null */ /* Now create argv */ - *argv = arg = ALIGN_UP(q,char *); + arg = ALIGN_UP(q,char *); + *argv = arg; *arg++ = mem; /* argv[0] */ for ( r = mem ; r < q ; r++ ) { - if ( *r == '\0' ) + if ( *r == '\0' ) { *arg++ = r+1; + } } *arg++ = NULL; /* Null pointer at the end */ diff --git a/dos/crt0.S b/dos/crt0.S index 9d0b2f8..af8b8ba 100644 --- a/dos/crt0.S +++ b/dos/crt0.S @@ -33,7 +33,7 @@ _start: # Initialize malloc calll __init_memory_arena - # Now call main... + # Now call main... (NOTE: gcc forces main to be regparm 0) popl %eax # argc popl %edx # argv calll main diff --git a/dos/syslinux.c b/dos/syslinux.c index e42432a..cc611c4 100644 --- a/dos/syslinux.c +++ b/dos/syslinux.c @@ -29,6 +29,12 @@ const char *program = "syslinux"; /* Name of program */ uint16_t dos_version; +#ifdef DEBUG +# define dprintf printf +#else +# define dprintf(...) ((void)0) +#endif + void __attribute__((noreturn)) usage(void) { puts("Usage: syslinux [-sf] drive:\n"); @@ -49,17 +55,21 @@ void __attribute__((noreturn)) die(const char *msg) /* * read/write wrapper functions */ -int open(const char *filename, int mode) +int creat(const char *filename, int mode) { uint16_t rv; uint8_t err; - rv = 0x3D00 | mode; + dprintf("creat(\"%s\", 0x%x)\n", filename, mode); + + rv = 0x3C00; asm volatile("int $0x21 ; setc %0" : "=abcdm" (err), "+a" (rv) - : "d" (filename)); - if ( err ) + : "c" (mode), "d" (filename)); + if ( err ) { + dprintf("rv = %d\n", rv); die("cannot open ldlinux.sys"); + } return rv; } @@ -68,6 +78,8 @@ void close(int fd) { uint16_t rv = 0x3E00; + dprintf("close(%d)\n", fd); + asm volatile("int $0x21" : "+a" (rv) : "b" (fd)); @@ -82,6 +94,8 @@ ssize_t write_file(int fd, const void *buf, size_t count) ssize_t done = 0; uint8_t err; + dprintf("write_file(%d,%p,%u)\n", fd, buf, count); + while ( count ) { rv = 0x4000; asm volatile("int $0x21 ; setc %0" @@ -101,9 +115,11 @@ void write_device(int drive, const void *buf, size_t nsecs, unsigned int sector) { uint8_t err; + dprintf("write_device(%d,%p,%u,%u)\n", drive, buf, nsecs, sector); + asm volatile("int $0x26 ; setc %0 ; popfw" : "=abcdm" (err) - : "a" (drive), "b" (buf), "c" (nsecs), "d" (sector)); + : "a" (drive-1), "b" (buf), "c" (nsecs), "d" (sector)); if ( err ) die("sector write error"); @@ -113,25 +129,26 @@ void read_device(int drive, const void *buf, size_t nsecs, unsigned int sector) { uint8_t err; + dprintf("read_device(%d,%p,%u,%u)\n", drive, buf, nsecs, sector); + asm volatile("int $0x25 ; setc %0 ; popfw" : "=abcdm" (err) - : "a" (drive), "b" (buf), "c" (nsecs), "d" (sector)); + : "a" (drive-1), "b" (buf), "c" (nsecs), "d" (sector)); if ( err ) die("sector write error"); } +/* This call can legitimately fail, and we don't care, so ignore error return */ void set_attributes(const char *file, int attributes) { - uint8_t err; uint16_t rv = 0x4301; - asm volatile("int $0x21 ; setc %0" - : "=abcdm" (err), "+a" (rv) - : "c" (attributes), "d" (file)); + dprintf("set_attributes(\"%s\", 0x%02x)\n", file, attributes); - if ( err ) - die("set attribute error"); + asm volatile("int $0x21" + : "+a" (rv) + : "c" (attributes), "d" (file)); } /* @@ -148,14 +165,15 @@ static inline void get_dos_version(void) uint16_t ver = 0x3001; asm("int $0x21 ; xchgb %%ah,%%al" : "+a" (ver) : : "ebx", "ecx"); dos_version = ver; + dprintf("DOS version %d.%d\n", (dos_version >> 8), dos_version & 0xff); } /* The locking interface relies on static variables. A massive hack :( */ static uint16_t lock_level; -static inline void set_lock_device(int device) +static inline void set_lock_device(uint8_t device) { - lock_level = device << 8; + lock_level = device; } void lock_device(int level) @@ -174,15 +192,23 @@ void lock_device(int level) lock_call = 0x084A; /* MSDN says this is OK for all filesystems */ #endif - while ( (uint8_t)lock_level < level ) { + while ( (lock_level >> 8) < level ) { + uint16_t new_level = lock_level + 0x0100; + dprintf("Trying lock %04x...\n", new_level); rv = 0x444d; asm volatile("int $0x21 ; setc %0" : "=abcdm" (err), "+a" (rv) - : "b" (lock_level+1), "c" (lock_call), "d"(0x0001)); - if ( err ) - die("could not lock device"); + : "b" (new_level), "c" (lock_call), "d"(0x0001)); + if ( err ) { + /* rv == 0x0001 means this call is not supported, if so we + assume locking isn't needed (e.g. Win9x in DOS-only mode) */ + if ( rv == 0x0001 ) + return; + else + die("could not lock device"); + } - lock_level++; + lock_level = new_level; } return; } @@ -203,12 +229,13 @@ void unlock_device(int level) unlock_call = 0x086A; /* MSDN says this is OK for all filesystems */ #endif - while ( (uint8_t)lock_level > level ) { + while ( (lock_level >> 8) > level ) { + uint16_t new_level = lock_level - 0x0100; rv = 0x440d; asm volatile("int $0x21 ; setc %0" : "=abcdm" (err), "+a" (rv) - : "b" (lock_level-1), "c" (unlock_call)); - lock_level--; + : "b" (new_level), "c" (unlock_call)); + lock_level = new_level; } } @@ -225,6 +252,11 @@ int main(int argc, char *argv[]) int nsectors; char *device = NULL; const char *errmsg; + int i; + + dprintf("argv = %p\n", argv); + for ( i = 0 ; i <= argc ; i++ ) + dprintf("argv[%d] = %p = \"%s\"\n", i, argv[i], argv[i]); (void)argc; /* Unused */ @@ -282,10 +314,9 @@ int main(int argc, char *argv[]) ldlinux_name[0] = dev_fd | 0x40; set_attributes(ldlinux_name, 0); - fd = open(ldlinux_name, 2); /* Open for read/write access */ + fd = creat(ldlinux_name, 0x27); /* ARCHIVE SYSTEM HIDDEN READONLY */ write_file(fd, syslinux_ldlinux, syslinux_ldlinux_len); close(fd); - set_attributes(ldlinux_name, 0x27); /* ARCHIVE SYSTEM HIDDEN READONLY */ /* * Now, use libfat to create a block map. This probably -- 2.7.4