ZFS boot inside on the second partition inside a slice

John Baldwin jhb at freebsd.org
Wed Jun 22 13:57:14 UTC 2011


On Wednesday, June 22, 2011 7:34:05 am Henri Hennebert wrote:
> I get
> 
> LBA: 00008200
> Read error: 04

Odd.  Oh, I fubar'd and read the wrong thing for the sector.  Also, we
should leave the EDD packet on the stack so it doesn't get trashed by
calling hex8, etc.  Please try this:

Index: zfsldr.S
===================================================================
--- zfsldr.S	(revision 223365)
+++ zfsldr.S	(working copy)
@@ -16,7 +16,6 @@
  */
 
 /* Memory Locations */
-		.set MEM_REL,0x700		# Relocation address
 		.set MEM_ARG,0x900		# Arguments
 		.set MEM_ORG,0x7c00		# Origin
 		.set MEM_BUF,0x8000		# Load area
@@ -91,26 +90,18 @@ main:		cld				# String ops inc
 		mov %cx,%ss			# Set up
 		mov $start,%sp			#  stack
 /*
- * Relocate ourself to MEM_REL.  Since %cx == 0, the inc %ch sets
- * %cx == 0x100.
- */
-		mov %sp,%si			# Source
-		mov $MEM_REL,%di		# Destination
-		incb %ch			# Word count
-		rep				# Copy
-		movsw				#  code
-/*
  * If we are on a hard drive, then load the MBR and look for the first
  * FreeBSD slice.  We use the fake partition entry below that points to
  * the MBR when we call nread.  The first pass looks for the first active
  * FreeBSD slice.  The second pass looks for the first non-active FreeBSD
  * slice if the first one fails.
  */
-		mov $part4,%si			# Partition
+		mov $part4,%si			# Dummy partition
 		cmpb $0x80,%dl			# Hard drive?
 		jb main.4			# No
-		movb $0x1,%dh			# Block count
-		callw nread			# Read MBR
+		xor %eax,%eax			# Read MBR
+		movw $MEM_BUF,%bx		#  from first
+		callw nread			#  sector
 		mov $0x1,%cx	 		# Two passes
 main.1: 	mov $MEM_BUF+PRT_OFF,%si	# Partition table
 		movb $0x1,%dh			# Partition
@@ -161,10 +152,16 @@ main.4: 	xor %dx,%dx			# Partition:drive
  * area and target area do not overlap.
  */
 main.5: 	mov %dx,MEM_ARG			# Save args
-		movb $NSECT,%dh			# Sector count
+		mov $NSECT,%cx			# Sector count
 		movl $1024,%eax			# Offset to boot2
-		callw nread.1			# Read disk
-main.6:		mov $MEM_BUF,%si		# BTX (before reloc)
+		mov $MEM_BUF,%bx		# Destination buffer
+main.6:		pushal				# Save params
+		callw nread			# Read disk
+		popal				# Restore
+		incl %eax			# Update for
+		add $SIZ_SEC,%bx		#  next sector
+		loop main.6			# If not last, read another
+		mov $MEM_BUF,%si		# BTX (before reloc)
 		mov 0xa(%si),%bx		# Get BTX length and set
 		mov $NSECT*SIZ_SEC-1,%di	# Size of load area (less one)
 		mov %di,%si			# End of load
@@ -214,29 +211,35 @@ seta20.3:	sti				# Enable interrupts
  * packet on the stack and passes it to read.
  *
  * %eax		- int     - LBA to read in relative to partition start
+ * %es:%bx	- ptr	  - destination address
  * %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:	xor %ecx,%ecx			# Get
+nread:		xor %ecx,%ecx			# Get
 		addl 0x8(%si),%eax		#  LBA
 		adc $0,%ecx
 		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 %bx			#  transfer buffer
+		push $0x1			# Read 1 sector
 		push $0x10			# Size of packet
 		mov %sp,%bp			# Packet pointer
 		callw read			# Read from disk
+		jc nread.1			# If error, fail
 		lea 0x10(%bp),%sp		# Clear stack
-		jnc return			# If success, return
-		mov $msg_read,%si		# Otherwise, set the error
-						#  message and fall through to
-						#  the error routine
+		ret				# If success, return
+nread.1:	mov %ah,%al			# Format
+		mov $read_err,%di		#  error
+		call hex8			#  code
+		movl 0x8(%bp),%eax		# Format
+		mov $lba,%di			#  LBA
+		call hex32
+		mov $msg_lba,%si		# Display
+		call putstr			#  LBA
+		mov $msg_read,%si		# Set the error message and
+						#  fall through to the error
+						#  routine
 /*
  * Print out the error message pointed to by %ds:(%si) followed
  * by a prompt, wait for a keypress, and then reboot the machine.
@@ -259,14 +262,6 @@ putstr: 	lodsb				# Get char
 		jne putstr.0			# No
 
 /*
- * Overused return code.  ereturn is used to return an error from the
- * read function.  Since we assume putstr succeeds, we (ab)use the
- * same code when we return from putstr.
- */
-ereturn:	movb $0x1,%ah			# Invalid
-		stc				#  argument
-return: 	retw				# To caller
-/*
  * Reads sectors from the disk.  If EDD is enabled, then check if it is
  * installed and use it if it is.  If it is not installed or not enabled, then
  * fall back to using CHS.  Since we use a LBA, if we are using CHS, we have to
@@ -294,14 +289,38 @@ read:		cmpb $0x80,%dl			# Hard drive?
 		retw				# To caller
 read.1:		mov $msg_chs,%si
 		jmp error
-msg_chs:	.asciz "CHS not supported"
 
+/*
+ * Convert EAX, AX, or AL to hex, saving the result to [EDI].
+ */
+hex32:		pushl %eax			# Save
+		shrl $0x10,%eax 		# Do upper
+		call hex16			#  16
+		popl %eax			# Restore
+hex16:		call hex16.1			# Do upper 8
+hex16.1:	xchgb %ah,%al			# Save/restore
+hex8:		push %ax			# Save
+		shrb $0x4,%al			# Do upper
+		call hex8.1			#  4
+		pop %ax				# Restore
+hex8.1: 	andb $0xf,%al			# Get lower 4
+		cmpb $0xa,%al			# Convert
+		sbbb $0x69,%al			#  to hex
+		das				#  digit
+		orb $0x20,%al			# To lower case
+		stosb				# Save char
+		ret				# (Recursive)
+
 /* Messages */
 
-msg_read:	.asciz "Read"
-msg_part:	.asciz "Boot"
+msg_chs:	.asciz "CHS not supported"
+msg_read:	.ascii "Read error: "
+read_err:	.asciz "XX"
+msg_lba:	.ascii "LBA: "
+lba:		.asciz "XXXXXXXX\r\n"
+msg_part:	.asciz "Boot error"
 
-prompt: 	.asciz " error\r\n"
+prompt: 	.asciz "\r\n"
 
 		.org PRT_OFF,0x90
 


-- 
John Baldwin


More information about the freebsd-stable mailing list