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