Experimental boot code patch (was Re: lost with booting)
This patch causes the boot1/boot2 code to always try packet mode first
(if the BIOS supports it), and fall back to CHS mode if it doesn't.
Previously CHS mode would always be used for requests with cylinder
numbers below 1024 and packet mode would only be tried for cylinder
numbers >= 1024. Packet mode for boot0 is still controlled by boot0cfg.
This is basically an end-run around CHS. For any BIOS supporting packet
mode, packet mode is used no matter what the BIOS setting for the disk
is.
The real question here is whether this boot code works with very old
machines whos BIOS'es do not have any clue about packet mode.
-Matt
Index: i386/boot2/boot1.S
===================================================================
RCS file: /cvs/src/sys/boot/i386/boot2/boot1.S,v
retrieving revision 1.8
diff -u -r1.8 boot1.S
--- i386/boot2/boot1.S 27 Jul 2004 19:37:17 -0000 1.8
+++ i386/boot2/boot1.S 9 Sep 2004 23:09:38 -0000
@@ -314,8 +314,43 @@
//
// %dl - byte - drive number
// stack - 10 bytes - EDD Packet
-//
-read: push %dx // Save
+
+read:
+ /*
+ * Try EDD mode first. If not enabled or no BIOS support
+ * exists, fall back to CHS mode.
+ */
+ testb $FL_PACKET,%cs:BOOT1_ORIGIN+flags-start
+ jz read.1
+
+ /*
+ * BIOS: check extensions present
+ */
+ mov $0x55aa,%bx
+ push %dx
+ movb $0x41,%ah
+ int $0x13
+ pop %dx
+ jc read.1 /* BIOS error return */
+ cmp $0xaa55,%bx /* check for proper magic */
+ jne read.1
+ testb $0x1,%cl /* packet interface support? */
+ jz read.1
+
+ /*
+ * Issue packet command.
+ * BIOS: Extended read command
+ */
+ mov %bp,%si
+ movb $0x42,%ah
+ int $0x13
+ retw
+
+ /*
+ * Fallback to CHS mode
+ */
+read.1:
+ push %dx // Save
movb $0x8,%ah // BIOS: Get drive
int $0x13 // parameters
movb %dh,%ch // Max head number
@@ -338,7 +373,7 @@
pop %dx // Restore
cmpl $0x3ff,%eax // Cylinder number supportable?
sti // Enable interrupts
- ja read.7 // No, try EDD
+ ja ereturn // No, failed
xchgb %al,%ah // Set up cylinder
rorb $0x2,%al // number
orb %ch,%al // Merge
@@ -374,24 +409,8 @@
read.5: shlb %bl // buffer
add %bl,0x5(%bp) // pointer,
sub %al,0x2(%bp) // block count
- ja read // If not done
+ ja read.1 // If not done
read.6: retw // To caller
-read.7: testb $FL_PACKET,%cs:BOOT1_ORIGIN+flags-start // LBA support enabled?
- jz ereturn // No, so return an error
- mov $0x55aa,%bx // Magic
- push %dx // Save
- movb $0x41,%ah // BIOS: Check
- int $0x13 // extensions present
- pop %dx // Restore
- jc return // If error, return an error
- cmp $0xaa55,%bx // Magic?
- jne ereturn // No, so return an error
- testb $0x1,%cl // Packet interface?
- jz ereturn // No, so return an error
- mov %bp,%si // Disk packet
- movb $0x42,%ah // BIOS: Extended
- int $0x13 // read
- retw // To caller
// Messages
Index: i386/libi386/biosdisk.c
===================================================================
RCS file: /cvs/src/sys/boot/i386/libi386/biosdisk.c,v
retrieving revision 1.6
diff -u -r1.6 biosdisk.c
--- i386/libi386/biosdisk.c 21 Jun 2004 03:38:52 -0000 1.6
+++ i386/libi386/biosdisk.c 9 Sep 2004 23:34:58 -0000
@@ -891,9 +891,14 @@
/* correct sector number for 1-based BIOS numbering */
sec++;
- /* Loop retrying the operation a couple of times. The BIOS may also retry. */
+ /*
+ * Loop retrying the operation a couple of times. The BIOS may also
+ * retry.
+ */
for (retry = 0; retry < 3; retry++) {
- /* if retrying, reset the drive */
+ /*
+ * If retrying, reset the drive.
+ */
if (retry > 0) {
v86.ctl = V86_FLAGS;
v86.addr = 0x13;
@@ -902,34 +907,33 @@
v86int();
}
- if(cyl > 1023) {
- /* use EDD if the disk supports it, otherwise, return error */
- if(od->od_flags & BD_MODEEDD1) {
- static unsigned short packet[8];
-
- packet[0] = 0x10;
- packet[1] = x;
- packet[2] = VTOPOFF(xp);
- packet[3] = VTOPSEG(xp);
- packet[4] = dblk & 0xffff;
- packet[5] = dblk >> 16;
- packet[6] = 0;
- packet[7] = 0;
- v86.ctl = V86_FLAGS;
- v86.addr = 0x13;
- v86.eax = 0x4200;
- v86.edx = od->od_unit;
- v86.ds = VTOPSEG(packet);
- v86.esi = VTOPOFF(packet);
- v86int();
- result = (v86.efl & 0x1);
- if(result == 0)
- break;
- } else {
- result = 1;
+ /*
+ * Always use EDD if the disk supports it, otherwise fall back
+ * to CHS mode (returning an error if the cylinder number is
+ * too large).
+ */
+ if (od->od_flags & BD_MODEEDD1) {
+ static unsigned short packet[8];
+
+ packet[0] = 0x10;
+ packet[1] = x;
+ packet[2] = VTOPOFF(xp);
+ packet[3] = VTOPSEG(xp);
+ packet[4] = dblk & 0xffff;
+ packet[5] = dblk >> 16;
+ packet[6] = 0;
+ packet[7] = 0;
+ v86.ctl = V86_FLAGS;
+ v86.addr = 0x13;
+ v86.eax = 0x4200;
+ v86.edx = od->od_unit;
+ v86.ds = VTOPSEG(packet);
+ v86.esi = VTOPOFF(packet);
+ v86int();
+ result = (v86.efl & 0x1);
+ if (result == 0)
break;
- }
- } else {
+ } else if (cyl < 1024) {
/* Use normal CHS addressing */
v86.ctl = V86_FLAGS;
v86.addr = 0x13;
@@ -941,7 +945,10 @@
v86int();
result = (v86.efl & 0x1);
if (result == 0)
- break;
+ break;
+ } else {
+ result = 1;
+ break;
}
}
@@ -1034,9 +1041,14 @@
dblk += x;
resid -= x;
- /* Loop retrying the operation a couple of times. The BIOS may also retry. */
+ /*
+ * Loop retrying the operation a couple of times. The BIOS may also
+ * retry.
+ */
for (retry = 0; retry < 3; retry++) {
- /* if retrying, reset the drive */
+ /*
+ * If retrying, reset the drive.
+ */
if (retry > 0) {
v86.ctl = V86_FLAGS;
v86.addr = 0x13;
@@ -1044,36 +1056,35 @@
v86.edx = od->od_unit;
v86int();
}
-
- if(cyl > 1023) {
- /* use EDD if the disk supports it, otherwise, return error */
- if(od->od_flags & BD_MODEEDD1) {
- static unsigned short packet[8];
-
- packet[0] = 0x10;
- packet[1] = x;
- packet[2] = VTOPOFF(xp);
- packet[3] = VTOPSEG(xp);
- packet[4] = dblk & 0xffff;
- packet[5] = dblk >> 16;
- packet[6] = 0;
- packet[7] = 0;
- v86.ctl = V86_FLAGS;
- v86.addr = 0x13;
- /* Should we Write with verify ?? 0x4302 ? */
- v86.eax = 0x4300;
- v86.edx = od->od_unit;
- v86.ds = VTOPSEG(packet);
- v86.esi = VTOPOFF(packet);
- v86int();
- result = (v86.efl & 0x1);
- if(result == 0)
- break;
- } else {
- result = 1;
+
+ /*
+ * Always use EDD if the disk supports it, otherwise fall back
+ * to CHS mode (returning an error if the cylinder number is
+ * too large).
+ */
+ if (od->od_flags & BD_MODEEDD1) {
+ static unsigned short packet[8];
+
+ packet[0] = 0x10;
+ packet[1] = x;
+ packet[2] = VTOPOFF(xp);
+ packet[3] = VTOPSEG(xp);
+ packet[4] = dblk & 0xffff;
+ packet[5] = dblk >> 16;
+ packet[6] = 0;
+ packet[7] = 0;
+ v86.ctl = V86_FLAGS;
+ v86.addr = 0x13;
+ /* Should we Write with verify ?? 0x4302 ? */
+ v86.eax = 0x4300;
+ v86.edx = od->od_unit;
+ v86.ds = VTOPSEG(packet);
+ v86.esi = VTOPOFF(packet);
+ v86int();
+ result = (v86.efl & 0x1);
+ if (result == 0)
break;
- }
- } else {
+ } else if (cyl < 1024) {
/* Use normal CHS addressing */
v86.ctl = V86_FLAGS;
v86.addr = 0x13;
@@ -1085,7 +1096,10 @@
v86int();
result = (v86.efl & 0x1);
if (result == 0)
- break;
+ break;
+ } else {
+ result = 1;
+ break;
}
}
討論串 (同標題文章)
完整討論串 (本文為第 1 之 4 篇):