boot - Hack workarounds for chromebook 'SeaBIOS' issues
authorMatthew Dillon <dillon@apollo.backplane.com>
Wed, 1 Jan 2014 17:34:50 +0000 (09:34 -0800)
committerMatthew Dillon <dillon@apollo.backplane.com>
Wed, 1 Jan 2014 17:39:56 +0000 (09:39 -0800)
* The google seabios hack to boot legacy-mode only reports 16MB of extended
  memory.  For now, enforce a minimum of 64MB.

  This was preventing the loader from being able to load the kernel+modules.

* Fix a bug in biosdisk.c to force bounce buffers if the target buffer
  is beyond the segment address limit, in addition to checking for
  64KB boundary crossings.

sys/boot/pc32/libi386/biosdisk.c
sys/boot/pc32/libi386/biosmem.c

index bb639b3..c3b1271 100644 (file)
@@ -1015,24 +1015,32 @@ bd_read(struct open_disk *od, daddr_t dblk, int blks, caddr_t dest)
     resid = blks;
     p = dest;
 
-    /* Decide whether we have to bounce */
+    /*
+     * 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.
+     */
     if ((od->od_unit < 0x80) && 
-       ((VTOP(dest) >> 16) != (VTOP(dest + blks * BIOSDISK_SECSIZE) >> 16))) {
+       (VTOP(dest + blks * BIOSDISK_SECSIZE) >= 16384 * 1024 ||
+        ((VTOP(dest) >> 16) != (VTOP(dest + blks * BIOSDISK_SECSIZE) >> 16)))
+     ) {
 
        /* 
-        * 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.
+        * 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.
         */
        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) & 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;
@@ -1159,10 +1167,10 @@ bd_write(struct open_disk *od, daddr_t dblk, int blks, caddr_t dest)
        ((VTOP(dest) >> 16) != (VTOP(dest + blks * BIOSDISK_SECSIZE) >> 16))) {
 
        /* 
-        * 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.
+        * 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.
         */
 
        x = min(FLOPPY_BOUNCEBUF, (unsigned)blks);
index 42b06d1..034643b 100644 (file)
@@ -49,6 +49,7 @@ static struct smap smap;
 void
 bios_getmem(void)
 {
+    int64_t v;
 
     /* Parse system memory map */
     v86.ebx = 0;
@@ -100,7 +101,11 @@ bios_getmem(void)
        v86.eax = 0xe801;
        v86int();
        if (!(v86.efl & 1)) {
-           bios_extmem = ((v86.ecx & 0xffff) + ((v86.edx & 0xffff) * 64)) * 1024;
+           v = ((v86.ecx & 0xffff) +
+               ((int64_t)(v86.edx & 0xffff) * 64)) * 1024;
+           if (v > 0x40000000)
+               v = 0x40000000;
+           bios_extmem = v;
        }
     }
     if (bios_extmem == 0) {
@@ -111,8 +116,16 @@ bios_getmem(void)
        bios_extmem = (v86.eax & 0xffff) * 1024;
     }
 
-    /* Set memtop to actual top of memory */
-    memtop = 0x100000 + bios_extmem;
-
+    /*
+     * Set memtop to actual top of memory
+     *
+     * This is broken because the boot loader generally needs more than 16MB
+     * now but the extmem usually calculates to ~14-16MB (which is the fully
+     * segmented limit).  Disk I/O will use bounce buffers.
+     *
+     * Hack it for now.
+     */
+    memtop = 0x100000 + bios_extmem;   /* XXX ignored */
+    memtop = 64 * 1024 * 1024;
 }