zfsboot cleanup patch to remove use of xread
John Baldwin
jhb at freebsd.org
Wed Apr 6 17:29:54 UTC 2011
boot2 has a gross hack where it calls back into boot1 to do disk I/O due to
size constraints. zfsboot copied this code, but zfsboot does not suffer from
the same size restrictions, so I'd like to remove it. I have a patch that
should do this, but I don't currently have a test system setup to test this.
If someone has an easy way to test a modified zfsboot (including a way to
recover easily in case it fails to boot), please test this patch:
Index: boot/i386/boot2/Makefile
===================================================================
--- boot/i386/boot2/Makefile (revision 220383)
+++ boot/i386/boot2/Makefile (working copy)
@@ -32,6 +32,7 @@
-mno-align-long-strings \
-mrtd \
-mregparm=3 \
+ -DUSE_XREAD \
-D${BOOT2_UFS} \
-DFLAGS=${BOOT_BOOT1_FLAGS} \
-DSIOPRT=${BOOT_COMCONSOLE_PORT} \
Index: boot/i386/zfsboot/zfsldr.S
===================================================================
--- boot/i386/zfsboot/zfsldr.S (revision 220383)
+++ boot/i386/zfsboot/zfsldr.S (working copy)
@@ -30,16 +30,12 @@
.set PRT_NUM,0x4 # Partitions
.set PRT_BSD,0xa5 # Partition type
-/* Flag Bits */
- .set FL_PACKET,0x80 # Packet mode
-
/* Misc. Constants */
.set SIZ_PAG,0x1000 # Page size
.set SIZ_SEC,0x200 # Sector size
.set NSECT,0x80
.globl start
- .globl xread
.code16
start: jmp main # Start recognizably
@@ -49,7 +45,7 @@
* FAT disks have this at the start of their MBR. While normal BIOS's will
* work fine without this section, IBM's El Torito emulation "fixes" up the
* BPB by writing into the memory copy of the MBR. Rather than have data
- * written into our xread routine, we'll define a BPB to work around it.
+ * written into our code, we'll define a BPB to work around it.
* The data marked with (T) indicates a field required for a ThinkPad to
* recognize the disk and (W) indicates fields written from IBM BIOS code.
* The use of the BPB is based on what OpenBSD and NetBSD implemented in
@@ -80,34 +76,7 @@
.org 0x25,0x90
/*
- * Trampoline used by boot2 to call read to read data from the disk via
- * the BIOS. Call with:
- *
- * %ecx:%eax - long - LBA to read in
- * %es:(%bx) - caddr_t - buffer to read data into
- * %dl - byte - drive to read from
- * %dh - byte - num sectors to read
- */
-
-xread: push %ss # Address
- pop %ds # data
-/*
- * Setup an EDD disk packet and pass it to read
- */
-xread.1: pushl %ecx # Starting absolute block
- pushl %eax # block number
- push %es # Address of
- push %bx # transfer buffer
- xor %ax,%ax # Number of
- movb %dh,%al # blocks to
- push %ax # transfer
- push $0x10 # Size of packet
- mov %sp,%bp # Packet pointer
- callw read # Read from disk
- lea 0x10(%bp),%sp # Clear stack
- lret # To far caller
-/*
- * Load the rest of boot2 and BTX up, copy the parts to the right locations,
+ * Load the rest of zfsboot2 and BTX up, copy the parts to the right
locations,
* and start it all up.
*/
@@ -181,7 +150,7 @@
* itself to 0x9000 - doing it in this order means that none of the
* memcpy regions overlap which would corrupt the copy. Normally, BTX
* clients start at MEM_USR, or 0xa000, but when we use btxld to
- * create boot2, we use an entry point of 0x2000. That entry point is
+ * create zfsboot2, we use an entry point of 0x2000. That entry point is
* relative to MEM_USR; thus boot2.bin starts at 0xc000.
*
* The load area and the target area for the client overlap so we have
@@ -241,15 +210,29 @@
/*
- * Trampoline used to call read from within boot1.
+ * Trampoline used to call read from within zfsldr. Sets up an EDD
+ * packet on the stack and passes it to read.
+ *
+ * %eax - int - LBA to read in relative to partition start
+ * %dl - byte - drive to read from
+ * %dh - byte - num sectors to read
+ * %si - ptr - MBR partition entry
*/
nread: xor %eax,%eax # Sector offset in partition
-nread.1: mov $MEM_BUF,%bx # Transfer buffer
- xor %ecx,%ecx # Get
+nread.1: xor %ecx,%ecx # Get
addl 0x8(%si),%eax # LBA
adc $0,%ecx
- push %cs # Read from
- callw xread.1 # disk
+ pushl %ecx # Starting absolute block
+ pushl %eax # block number
+ push %es # Address of
+ push $MEM_BUF # transfer buffer
+ xor %ax,%ax # Number of
+ movb %dh,%al # blocks to
+ push %ax # transfer
+ push $0x10 # Size of packet
+ mov %sp,%bp # Packet pointer
+ callw read # Read from disk
+ lea 0x10(%bp),%sp # Clear stack
jnc return # If success, return
mov $msg_read,%si # Otherwise, set the error
# message and fall through to
@@ -293,9 +276,7 @@
* %dl - byte - drive number
* stack - 10 bytes - EDD Packet
*/
-read: testb $FL_PACKET,%cs:MEM_REL+flags-start # LBA support enabled?
- jz read.1 # No, use CHS
- cmpb $0x80,%dl # Hard drive?
+read: cmpb $0x80,%dl # Hard drive?
jb read.1 # No, use CHS
mov $0x55aa,%bx # Magic
push %dx # Save
@@ -311,73 +292,9 @@
movb $0x42,%ah # BIOS: Extended
int $0x13 # read
retw # To caller
-#if 0
-read.1: push %dx # Save
- movb $0x8,%ah # BIOS: Get drive
- int $0x13 # parameters
- movb %dh,%ch # Max head number
- pop %dx # Restore
- jc return # If error
- andb $0x3f,%cl # Sectors per track
- jz ereturn # If zero
- cli # Disable interrupts
- mov 0x8(%bp),%eax # Get LBA
- push %dx # Save
- movzbl %cl,%ebx # Divide by
- xor %edx,%edx # sectors
- div %ebx # per track
- movb %ch,%bl # Max head number
- movb %dl,%ch # Sector number
- inc %bx # Divide by
- xorb %dl,%dl # number
- div %ebx # of heads
- movb %dl,%bh # Head number
- pop %dx # Restore
- cmpl $0x3ff,%eax # Cylinder number supportable?
- sti # Enable interrupts
- ja ereturn # No, return an error
- xchgb %al,%ah # Set up cylinder
- rorb $0x2,%al # number
- orb %ch,%al # Merge
- inc %ax # sector
- xchg %ax,%cx # number
- movb %bh,%dh # Head number
- subb %ah,%al # Sectors this track
- mov 0x2(%bp),%ah # Blocks to read
- cmpb %ah,%al # To read
- jb read.2 # this
-#ifdef TRACK_AT_A_TIME
- movb %ah,%al # track
-#else
- movb $1,%al # one sector
-#endif
-read.2: mov $0x5,%di # Try count
-read.3: les 0x4(%bp),%bx # Transfer buffer
- push %ax # Save
- movb $0x2,%ah # BIOS: Read
- int $0x13 # from disk
- pop %bx # Restore
- jnc read.4 # If success
- dec %di # Retry?
- jz read.6 # No
- xorb %ah,%ah # BIOS: Reset
- int $0x13 # disk system
- xchg %bx,%ax # Block count
- jmp read.3 # Continue
-read.4: movzbw %bl,%ax # Sectors read
- add %ax,0x8(%bp) # Adjust
- jnc read.5 # LBA,
- incw 0xa(%bp) # transfer
-read.5: shlb %bl # buffer
- add %bl,0x5(%bp) # pointer,
- sub %al,0x2(%bp) # block count
- ja read.1 # If not done
-read.6: retw # To caller
-#else
read.1: mov $msg_chs,%si
jmp error
msg_chs: .asciz "CHS not supported"
-#endif
/* Messages */
@@ -386,8 +303,6 @@
prompt: .asciz " error\r\n"
-flags: .byte FLAGS # Flags
-
.org PRT_OFF,0x90
/* Partition table */
Index: boot/i386/zfsboot/Makefile
===================================================================
--- boot/i386/zfsboot/Makefile (revision 220383)
+++ boot/i386/zfsboot/Makefile (working copy)
@@ -6,9 +6,6 @@
NM?= nm
-# A value of 0x80 enables LBA support.
-BOOT_BOOT1_FLAGS?= 0x80
-
BOOT_COMCONSOLE_PORT?= 0x3f8
BOOT_COMCONSOLE_SPEED?= 9600
B2SIOFMT?= 0x3
@@ -25,7 +22,6 @@
-mno-align-long-strings \
-mrtd \
-DBOOT2 \
- -DFLAGS=${BOOT_BOOT1_FLAGS} \
-DSIOPRT=${BOOT_COMCONSOLE_PORT} \
-DSIOFMT=${B2SIOFMT} \
-DSIOSPD=${BOOT_COMCONSOLE_SPEED} \
@@ -64,7 +60,7 @@
${LD} ${LDFLAGS} -e start -Ttext ${ORG1} -o ${.TARGET} zfsldr.o
CLEANFILES+= zfsboot2 zfsboot.ld zfsboot.ldr zfsboot.bin zfsboot.out \
- zfsboot.o zfsboot.s zfsboot.s.tmp xreadorg.h sio.o
+ zfsboot.o zfsboot.s zfsboot.s.tmp sio.o
# We currently allow 65536 bytes for zfsboot - in practice it could be
# any size up to 3.5Mb but keeping it fixed size simplifies zfsldr.
@@ -91,20 +87,13 @@
zfsboot.o: zfsboot.s
-SRCS= zfsboot.c xreadorg.h
+SRCS= zfsboot.c
-zfsboot.s: zfsboot.c xreadorg.h ${.CURDIR}/../../zfs/zfsimpl.c
+zfsboot.s: zfsboot.c ${.CURDIR}/../../zfs/zfsimpl.c
${CC} ${CFLAGS} -S -o zfsboot.s.tmp ${.CURDIR}/zfsboot.c
sed -e '/align/d' -e '/nop/d' < zfsboot.s.tmp > zfsboot.s
rm -f zfsboot.s.tmp
-xreadorg.h: zfsldr.out
- ${NM} -t d ${.ALLSRC} | awk '/([0-9])+ T xread/ \
- { x = $$1 - ORG1; \
- printf("#define XREADORG %#x\n", REL1 + x) }' \
- ORG1=`printf "%d" ${ORG1}` \
- REL1=`printf "%d" ${REL1}` > ${.TARGET}
-
.if ${MACHINE_CPUARCH} == "amd64"
beforedepend zfsboot.s: machine
CLEANFILES+= machine
Index: boot/i386/common/drv.c
===================================================================
--- boot/i386/common/drv.c (revision 220383)
+++ boot/i386/common/drv.c (working copy)
@@ -26,7 +26,7 @@
#include "rbx.h"
#include "util.h"
#include "drv.h"
-#ifndef GPT
+#ifdef USE_XREAD
#include "xreadorg.h"
#endif
@@ -58,7 +58,7 @@
}
#endif /* GPT */
-#ifdef GPT
+#ifndef USE_XREAD
static struct {
uint16_t len;
uint16_t count;
@@ -66,7 +66,7 @@
uint16_t seg;
uint64_t lba;
} packet;
-#endif /* GPT */
+#endif
int
drvread(struct dsk *dskp, void *buf, daddr_t lba, unsigned nblk)
@@ -75,7 +75,7 @@
if (!OPT_CHECK(RBX_QUIET))
printf("%c\b", c = c << 8 | c >> 24);
-#ifdef GPT
+#ifndef USE_XREAD
packet.len = 0x10;
packet.count = nblk;
packet.off = VTOPOFF(buf);
@@ -87,7 +87,7 @@
v86.edx = dskp->drive;
v86.ds = VTOPSEG(&packet);
v86.esi = VTOPOFF(&packet);
-#else /* !GPT */
+#else /* USE_XREAD */
v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS;
v86.addr = XREADORG; /* call to xread in boot1 */
v86.es = VTOPSEG(buf);
@@ -95,7 +95,7 @@
v86.ebx = VTOPOFF(buf);
v86.ecx = lba >> 32;
v86.edx = nblk << 8 | dskp->drive;
-#endif /* !GPT */
+#endif /* USE_XREAD */
v86int();
if (V86_CY(v86.efl)) {
printf("%s: error %u lba %u\n",
--
John Baldwin
More information about the freebsd-fs
mailing list