Make the DOS-based installer actually work; mark debugging statements
authorhpa <hpa>
Sat, 18 Dec 2004 23:28:30 +0000 (23:28 +0000)
committerhpa <hpa>
Sat, 18 Dec 2004 23:28:30 +0000 (23:28 +0000)
as "dprintf"

dos/argv.c
dos/crt0.S
dos/syslinux.c

index 62c3b04..5535331 100644 (file)
@@ -35,6 +35,7 @@
 
 #include <inttypes.h>
 #include <stddef.h>
+#include <stdio.h>
 
 #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 */
index 9d0b2f8..af8b8ba 100644 (file)
@@ -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
index e42432a..cc611c4 100644 (file)
 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