ZFS boot inside on the second partition inside a slice

John Baldwin jhb at freebsd.org
Wed Jun 22 17:33:03 UTC 2011


On Wednesday, June 22, 2011 12:48:43 pm Henri Hennebert wrote:
> No error message but a reboot...
> 
> I add:
> 
>                  loop main.6                     # If not last, read another
> 
>                  mov $msg_debug,%si
>                  call putstr
> 
>                  mov $MEM_BTX,%si                # BTX
> 
> ......
> 
> msg_debug:      .asciz "@\r\n"
> 
> I don't get the @ on the console :-(

Hmm, so it never exits the loop?

> PS - I have to keep a short message otherwise:
> 
> /usr/src/sys/boot/i386/zfsboot/zfsldr.S:322: Error: attempt to move .org 
> backwards

Yeah, it's getting tight.  I've commented the LBA printing bits out (so there
is more room to play with) and made it print out a "." for each disk sector
read:

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
@@ -143,32 +134,35 @@ main.4: 	xor %dx,%dx			# Partition:drive
  * (i.e. after the two vdev labels).  We don't have do anything fancy
  * here to allow for an extra copy of boot1 and a partition table
  * (compare to this section of the UFS bootstrap) so we just load it
- * all at 0x8000. The first part of boot2 is BTX, which wants to run
+ * all at 0x9000. The first part of boot2 is BTX, which wants to run
  * at 0x9000. The boot2.bin binary starts right after the end of BTX,
  * so we have to figure out where the start of it is and then move the
- * binary to 0xc000. After we have moved the client, we relocate BTX
- * 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 zfsboot2, we use an entry point of 0x2000.  That entry point is
- * relative to MEM_USR; thus boot2.bin starts at 0xc000.
+ * binary to 0xc000.  Normally, BTX clients start at MEM_USR, or 0xa000,
+ * but when we use btxld to 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
  * to use a decrementing string move. We also play segment register
  * games with the destination address for the move so that the client
  * can be larger than 16k (which would overflow the zero segment since
- * the client starts at 0xc000). Relocating BTX is easy since the load
- * area and target area do not overlap.
+ * the client starts at 0xc000).
  */
 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_BTX,%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_BTX,%si		# BTX
 		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
-		add $MEM_BUF,%si		#  area
+		add $MEM_BTX,%si		#  area
 		sub %bx,%di			# End of client, 0xc000 rel
 		mov %di,%cx			# Size of
 		inc %cx				#  client
@@ -179,12 +173,6 @@ main.5: 	mov %dx,MEM_ARG			# Save args
 		movsb				#  client
 		mov %ds,%dx			# Back to
 		mov %dx,%es			#  zero segment
-		mov $MEM_BUF,%si		# BTX (before reloc)
-		mov $MEM_BTX,%di		# BTX
-		mov %bx,%cx			# Get BTX length
-		cld				# Increment this time
-		rep				# Relocate
-		movsb				#  BTX
 
 /*
  * Enable A20 so we can access memory above 1 meg.
@@ -214,30 +202,40 @@ 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
+		mov $msg_dot,%si
+		call putstr
+		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 +257,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 +284,43 @@ 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_dot:	.asciz "."
+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