boot - boot loader fixes
authorMatthew Dillon <dillon@apollo.backplane.com>
Wed, 2 Apr 2014 19:22:50 +0000 (12:22 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Wed, 2 Apr 2014 19:22:50 +0000 (12:22 -0700)
* Clarify some issues in comments.

* Don't trust the bios memory boundary, start 1K below it.

* Always bounce, not just for floppies.  This should help with situations
  when loading kernels and modules beyond the 16MB mark.

* Add some debugging memory commands

sys/boot/common/commands.c
sys/boot/pc32/bootasm.h
sys/boot/pc32/btx/btx/btx.S
sys/boot/pc32/btx/btxldr/btxldr.S
sys/boot/pc32/libi386/biosdisk.c
sys/boot/pc32/loader/main.c

index 697b334..def0ad1 100644 (file)
@@ -638,3 +638,34 @@ command_endif(int argc, char *argv[])
                return(-1);
        }
 }
+
+COMMAND_SET(rmem, "rmem", "read memory", command_rmem);
+
+static int
+command_rmem(int argc, char *argv[])
+{
+    int addr;
+
+    if (argc > 1) {
+       addr = strtol(argv[1], NULL, 0);
+       printf("%08x: %08x\n", addr, *(int *)(intptr_t)addr);
+    }
+    return(CMD_OK);
+}
+
+COMMAND_SET(wmem, "wmem", "write memory", command_wmem);
+
+static int
+command_wmem(int argc, char *argv[])
+{
+    int addr;
+    int data;
+
+    if (argc > 2) {
+       addr = strtol(argv[1], NULL, 0);
+       data = strtol(argv[2], NULL, 0);
+       *(int *)(intptr_t)addr = data;
+       printf("%08x: %08x\n", addr, *(int *)(intptr_t)addr);
+    }
+    return(CMD_OK);
+}
index d570717..c538271 100644 (file)
 #define MEM_BTX_USR    0xa000          /* base of BTX client/user memory */
 #define MEM_BTX_USR_ARG        0xa100
 
+/*
+ * By default the user stack is (theoretically) placed at the top of
+ * BIOS memory (typically around the 640K mark).  See btx.S.  BTX loads
+ * the stack from a BIOS memory address (BDA_MEM) rather than figuring it
+ * out from the smap.
+ *
+ * There aren't really any other places we can put it short of intruding on
+ * the kernel/module load space.
+ */
+/*#define MEM_BTX_USR_STK      0x3000000*/
+/*#define MEM_BTX_USR_STK      0x0F0000*/
+
 #elif defined(BOOT_NEWBOOTLOADER) && BOOT_NEWBOOTLOADER == 1
 
 /************************************************************************
index 746eb0f..aae897d 100644 (file)
@@ -245,8 +245,11 @@ init.8:    xorl %ecx,%ecx                  # Zero
 /*
  * XXX We should NOT use BDA_MEM here.  Use a fixed location
  * instead.  (%eax is a physical stack addr)
+ *
+ * (must match stack specified in btxldr)
  */
                movzwl %ss:BDA_MEM,%eax         # Get free memory
+               decl %eax                       # Don't quite trust bios
                shll $0xa,%eax                  # To bytes
 #else
 /*
index a55484e..7c5be34 100644 (file)
@@ -97,6 +97,7 @@ start:                cld                             # String ops inc
                call putstr                     #  ourselves
 #if !defined(MEM_BTX_USR_STK)
                movzwl BDA_MEM,%eax             # Get base memory
+               decl %eax
                shll $0xa,%eax                  # Convert to bytes
 #else
                movl $MEM_BTX_USR_STK,%eax
index c3b1271..d410d70 100644 (file)
@@ -124,6 +124,12 @@ static int bd_open(struct open_file *f, ...);
 static int     bd_close(struct open_file *f);
 static void    bd_print(int verbose);
 
+/*
+ * Max number of sectors to bounce-buffer if the request crosses a 64k boundary
+ */
+#define BOUNCEBUF_SIZE 8192
+#define BOUNCEBUF_SECTS        (BOUNCEBUF_SIZE / BIOSDISK_SECSIZE)
+
 struct devsw biosdisk = {
     "disk", 
     DEVT_DISK, 
@@ -139,7 +145,10 @@ struct devsw biosdisk = {
 static int     bd_opendisk(struct open_disk **odp, struct i386_devdesc *dev);
 static void    bd_closedisk(struct open_disk *od);
 static int     bd_bestslice(struct open_disk *od);
-static void    bd_chainextended(struct open_disk *od, u_int32_t base, u_int32_t offset);
+static void    bd_chainextended(struct open_disk *od, u_int32_t base,
+                                       u_int32_t offset);
+
+static caddr_t bounce_base;
 
 /*
  * Translate between BIOS device numbers and our private unit numbers.
@@ -172,7 +181,10 @@ bd_unit2bios(int unit)
 static int
 bd_init(void) 
 {
-    int                base, unit, nfd = 0;
+    int        base, unit, nfd = 0;
+
+    if (bounce_base == NULL)
+       bounce_base = malloc(BOUNCEBUF_SIZE * 2);
 
     /* sequence 0, 0x80 */
     for (base = 0; base <= 0x80; base += 0x80) {
@@ -998,9 +1010,6 @@ bd_realstrategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf, siz
     return EROFS;
 }
 
-/* Max number of sectors to bounce-buffer if the request crosses a 64k boundary */
-#define FLOPPY_BOUNCEBUF       18
-
 static int
 bd_read(struct open_disk *od, daddr_t dblk, int blks, caddr_t dest)
 {
@@ -1016,15 +1025,9 @@ bd_read(struct open_disk *od, daddr_t dblk, int blks, caddr_t dest)
     p = dest;
 
     /*
-     * Decide whether we have to bounce.
-     *
-     * We have to bounce if the destination buffer is not segment addressable
-     * or if it crosses a 64KB boundary.
+     * Always bounce.  Our buffer is probably not segment-addressable.
      */
-    if ((od->od_unit < 0x80) && 
-       (VTOP(dest + blks * BIOSDISK_SECSIZE) >= 16384 * 1024 ||
-        ((VTOP(dest) >> 16) != (VTOP(dest + blks * BIOSDISK_SECSIZE) >> 16)))
-     ) {
+    if (1) {
 
        /* 
         * There is a 64k physical boundary somewhere in the destination
@@ -1032,10 +1035,11 @@ bd_read(struct open_disk *od, daddr_t dblk, int blks, caddr_t dest)
         * a buffer twice as large as we need to.  Use the bottom half unless
         * there is a break there, in which case we use the top half.
         */
-       x = min(FLOPPY_BOUNCEBUF, (unsigned)blks);
-       bbuf = malloc(x * 2 * BIOSDISK_SECSIZE);
-       if (((u_int32_t)VTOP(bbuf) & 0xffff0000) ==
-           ((u_int32_t)VTOP(bbuf + x * BIOSDISK_SECSIZE) & 0xffff0000)) {
+       bbuf = bounce_base;
+       x = min(BOUNCEBUF_SECTS, (unsigned)blks);
+
+       if (((u_int32_t)VTOP(bbuf) & 0xffff8000) ==
+           ((u_int32_t)VTOP(bbuf + x * BIOSDISK_SECSIZE - 1) & 0xffff8000)) {
            breg = bbuf;
        } else {
            breg = bbuf + x * BIOSDISK_SECSIZE;
@@ -1059,7 +1063,7 @@ bd_read(struct open_disk *od, daddr_t dblk, int blks, caddr_t dest)
            x = min(x, maxfer);         /* fit bounce buffer */
 
        /* where do we transfer to? */
-       xp = bbuf == NULL ? p : breg;
+       xp = (bbuf == NULL ? p : breg);
 
        /* correct sector number for 1-based BIOS numbering */
        sec++;
@@ -1125,15 +1129,16 @@ bd_read(struct open_disk *od, daddr_t dblk, int blks, caddr_t dest)
            }
        }
        
-       DEBUG("%u sectors from %u/%u/%d to %p (0x%x) %s", x, cyl, hd, sec - 1, p, VTOP(p), result ? "failed" : "ok");
+       DEBUG("%u sectors from %u/%u/%d to %p (0x%x) %s",
+             x, cyl, hd, sec - 1, p, VTOP(p), result ? "failed" : "ok");
        /* BUG here, cannot use v86 in printf because putchar uses it too */
        DEBUG("ax = 0x%04x cx = 0x%04x dx = 0x%04x status 0x%x", 
-             0x200 | x, ((cyl & 0xff) << 8) | ((cyl & 0x300) >> 2) | sec, (hd << 8) | od->od_unit, (v86.eax >> 8) & 0xff);
-       if (result) {
-           if (bbuf != NULL)
-               free(bbuf);
+             0x200 | x,
+             ((cyl & 0xff) << 8) | ((cyl & 0x300) >> 2) | sec,
+             (hd << 8) | od->od_unit,
+             (v86.eax >> 8) & 0xff);
+       if (result)
            return(-1);
-       }
        if (bbuf != NULL)
            bcopy(breg, p, x * BIOSDISK_SECSIZE);
        p += (x * BIOSDISK_SECSIZE);
@@ -1142,8 +1147,6 @@ bd_read(struct open_disk *od, daddr_t dblk, int blks, caddr_t dest)
     }
        
 /*    hexdump(dest, (blks * BIOSDISK_SECSIZE)); */
-    if (bbuf != NULL)
-       free(bbuf);
     return(0);
 }
 
@@ -1162,25 +1165,26 @@ bd_write(struct open_disk *od, daddr_t dblk, int blks, caddr_t dest)
     resid = blks;
     p = dest;
 
-    /* Decide whether we have to bounce */
-    if ((od->od_unit < 0x80) && 
-       ((VTOP(dest) >> 16) != (VTOP(dest + blks * BIOSDISK_SECSIZE) >> 16))) {
-
+    /*
+     * Always bounce.  Our buffer is probably not segment-addressable.
+     */
+    if (1) {
        /* 
         * There is a 64k physical boundary somewhere in the destination
         * buffer, so we have to arrange a suitable bounce buffer.  Allocate
         * a buffer twice as large as we need to.  Use the bottom half
         * unless there is a break there, in which case we use the top half.
         */
+       bbuf = bounce_base;
+       x = min(BOUNCEBUF_SECTS, (unsigned)blks);
 
-       x = min(FLOPPY_BOUNCEBUF, (unsigned)blks);
-       bbuf = malloc(x * 2 * BIOSDISK_SECSIZE);
-       if (((u_int32_t)VTOP(bbuf) & 0xffff0000) == ((u_int32_t)VTOP(bbuf + x * BIOSDISK_SECSIZE) & 0xffff0000)) {
+       if (((u_int32_t)VTOP(bbuf) & 0xffff0000) ==
+           ((u_int32_t)VTOP(bbuf + x * BIOSDISK_SECSIZE - 1) & 0xffff0000)) {
            breg = bbuf;
        } else {
            breg = bbuf + x * BIOSDISK_SECSIZE;
        }
-       maxfer = x;                     /* limit transfers to bounce region size */
+       maxfer = x;             /* limit transfers to bounce region size */
     } else {
        breg = bbuf = NULL;
        maxfer = 0;
@@ -1199,7 +1203,7 @@ bd_write(struct open_disk *od, daddr_t dblk, int blks, caddr_t dest)
            x = szmin(x, maxfer);               /* fit bounce buffer */
 
        /* where do we transfer to? */
-       xp = bbuf == NULL ? p : breg;
+       xp = (bbuf == NULL ? p : breg);
 
        /* correct sector number for 1-based BIOS numbering */
        sec++;
@@ -1280,16 +1284,11 @@ bd_write(struct open_disk *od, daddr_t dblk, int blks, caddr_t dest)
        /* BUG here, cannot use v86 in printf because putchar uses it too */
        DEBUG("ax = 0x%04x cx = 0x%04x dx = 0x%04x status 0x%x", 
              0x200 | x, ((cyl & 0xff) << 8) | ((cyl & 0x300) >> 2) | sec, (hd << 8) | od->od_unit, (v86.eax >> 8) & 0xff);
-       if (result) {
-           if (bbuf != NULL)
-               free(bbuf);
+       if (result)
            return(-1);
-       }
     }
        
-/*    hexdump(dest, (blks * BIOSDISK_SECSIZE)); */
-    if (bbuf != NULL)
-       free(bbuf);
+    /* hexdump(dest, (blks * BIOSDISK_SECSIZE)); */
     return(0);
 }
 static int
index 3faef6e..41cccbc 100644 (file)
@@ -171,7 +171,7 @@ main(void)
      * data.
      */
     bios_getmem();
-    memend = (char *)&memend - 0x8000; /* space for stack */
+    memend = (char *)&memend - 0x8000; /* space for stack (16K) */
     memend = (char *)((uintptr_t)memend & ~(uintptr_t)(0x1000 - 1));
     if (memend < (char *)_end) {
        setheap((void *)_end, PTOV(bios_basemem));
@@ -365,8 +365,13 @@ COMMAND_SET(heap, "heap", "show heap usage", command_heap);
 static int
 command_heap(int argc, char *argv[])
 {
+    char *base;
+    size_t bytes;
+
     mallocstats();
-    printf("heap base at %p, top at %p\n", _end, sbrk(0));
+    base = getheap(&bytes);
+    printf("heap %p-%p (%d)\n", base, base + bytes, (int)bytes);
+    printf("stack at %p\n", &argc);
     return(CMD_OK);
 }