ZFS boot inside on the second partition inside a slice

Henri Hennebert hlh at restart.be
Wed Jun 22 11:34:09 UTC 2011


On 06/21/2011 23:27, John Baldwin wrote:
> On Tuesday, June 21, 2011 4:13:20 pm Henri Hennebert wrote:
>> On 06/21/2011 21:25, John Baldwin wrote:
>> and I get:
>>
>> Read error: 04
>
> Hmm, that is the error for an invalid sector.  Try this patch.  It reshuffles
> a few more things and adds code to dump the low 32-bits of the LBA on an
> error:
>
> 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
>   		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
> +		jc nread.1			# If error, fail
> +		ret				# If success, return
> +nread.1:	mov %ah,%al			# Format
> +		mov $read_err,%di		#  error
> +		call hex8			#  code
> +		movl 0x4(%si),%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
>
>

I get

LBA: 00008200
Read error: 04

mfsbsd# gpart show
=>       63  312581745  ad0  MBR  (149G)
          63  167782797    1  ntfs  (80G)
   167782860  144798948    2  freebsd  [active]  (69G)

=>        0  144798948  ad0s2  BSD  (69G)
           0  144798948      1  freebsd-zfs  (69G)




More information about the freebsd-stable mailing list