boot - Fix CD booting
authorMatthew Dillon <dillon@apollo.backplane.com>
Wed, 19 Aug 2015 19:23:26 +0000 (12:23 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Wed, 19 Aug 2015 19:23:26 +0000 (12:23 -0700)
* Recent changes to move the loader's heap to high-memory broke the
  CD I/O code due to being beyond the BIOS'es segmentation range.  The
  HDD code was already using bounce buffers, but the CD code was not.

* Adjust the CD I/O code to use bounce buffers too.

Reported-by: numerous.
Testing-by: swildner
sys/boot/pc32/libi386/bioscd.c
sys/boot/pc32/libi386/biosdisk.c
sys/boot/pc32/libi386/libi386.h

index 8b992ce..afe47ef 100644 (file)
@@ -217,6 +217,7 @@ bc_strategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf,
        int unit;
        int blks;
 #ifdef BD_SUPPORT_FRAGS
+#error "xxx broken code xxx"
        char fragbuf[BIOSCD_SECSIZE];
        size_t fragsize;
 
@@ -262,6 +263,7 @@ bc_read(int unit, daddr_t dblk, int blks, caddr_t dest)
        u_int result, retry;
        static unsigned short packet[8];
        int biosdev;
+       int n;
 #ifdef DISK_DEBUG
        int error;
 #endif
@@ -288,11 +290,15 @@ bc_read(int unit, daddr_t dblk, int blks, caddr_t dest)
                        v86.edx = biosdev;
                        v86int();
                }
+
+               n = BOUNCEBUF_SIZE / BIOSCD_SECSIZE;
+               if (n > blks)
+                       n = blks;
            
                packet[0] = 0x10;
-               packet[1] = blks;
-               packet[2] = VTOPOFF(dest);
-               packet[3] = VTOPSEG(dest);
+               packet[1] = n;
+               packet[2] = VTOPOFF(bounce_base);
+               packet[3] = VTOPSEG(bounce_base);
                packet[4] = dblk & 0xffff;
                packet[5] = dblk >> 16;
                packet[6] = 0;
@@ -305,8 +311,14 @@ bc_read(int unit, daddr_t dblk, int blks, caddr_t dest)
                v86.esi = VTOPOFF(packet);
                v86int();
                result = (v86.efl & PSL_C);
-               if (result == 0)
-                       break;
+               if (result == 0) {
+                       bcopy(bounce_base, dest, n * BIOSCD_SECSIZE);
+                       blks -= n;
+                       dest += n * BIOSCD_SECSIZE;
+                       if (blks == 0)
+                               break;
+                       retry = 0;
+               }
        }
        
 #ifdef DISK_DEBUG
index 48bd510..2cf9407 100644 (file)
@@ -124,12 +124,6 @@ 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, 
@@ -148,11 +142,8 @@ static int bd_bestslice(struct open_disk *od);
 static void    bd_chainextended(struct open_disk *od, u_int32_t base,
                                        u_int32_t offset);
 
-/*
- * Bounce buffers can no longer be malloc()'d because the malloc pool
- * now uses high memory.  Declare statically.
- */
-static char    bounce_base[BOUNCEBUF_SIZE];
+char   bounce_base[BOUNCEBUF_SIZE];    /* also used by CD code */
+
 
 /*
  * Translate between BIOS device numbers and our private unit numbers.
index 228cd50..78f77ed 100644 (file)
@@ -72,6 +72,17 @@ write_eflags(u_int ef)
        __asm __volatile("pushl %0; popfl" : : "r" (ef));
 }
 
+/*
+ * Max number of sectors to bounce-buffer if the request crosses a 64k boundary
+ *
+ * Bounce buffers can no longer be malloc()'d because the malloc pool
+ * now uses high memory.  Declare statically.
+ */
+#define BOUNCEBUF_SIZE  8192
+#define BOUNCEBUF_SECTS (BOUNCEBUF_SIZE / BIOSDISK_SECSIZE)
+
+extern char    bounce_base[BOUNCEBUF_SIZE];
+
 int    i386_getdev(void **vdev, const char *devspec, const char **path);
 char   *i386_fmtdev(void *vdev);
 int    i386_setcurrdev(struct env_var *ev, int flags, const void *value);