From 69318c29dba0cd4c58424190e0336a58548b63aa Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Wed, 19 Aug 2015 12:23:26 -0700 Subject: [PATCH] boot - Fix CD booting * 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 | 22 +++++++++++++++++----- sys/boot/pc32/libi386/biosdisk.c | 13 ++----------- sys/boot/pc32/libi386/libi386.h | 11 +++++++++++ 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/sys/boot/pc32/libi386/bioscd.c b/sys/boot/pc32/libi386/bioscd.c index 8b992ceb39..afe47ef671 100644 --- a/sys/boot/pc32/libi386/bioscd.c +++ b/sys/boot/pc32/libi386/bioscd.c @@ -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 diff --git a/sys/boot/pc32/libi386/biosdisk.c b/sys/boot/pc32/libi386/biosdisk.c index 48bd510df0..2cf9407bab 100644 --- a/sys/boot/pc32/libi386/biosdisk.c +++ b/sys/boot/pc32/libi386/biosdisk.c @@ -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. diff --git a/sys/boot/pc32/libi386/libi386.h b/sys/boot/pc32/libi386/libi386.h index 228cd50ef2..78f77edead 100644 --- a/sys/boot/pc32/libi386/libi386.h +++ b/sys/boot/pc32/libi386/libi386.h @@ -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); -- 2.41.0