ZFS boot inside on the second partition inside a slice

Henri Hennebert hlh at restart.be
Wed Jun 22 16:48:47 UTC 2011


On 06/22/2011 17:58, John Baldwin wrote:
> 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,29 +202,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 +253,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 +280,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
>
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 :-(

PS - I have to keep a short message otherwise:

/usr/src/sys/boot/i386/zfsboot/zfsldr.S:322: Error: attempt to move .org 
backwards


Henri
Henri


More information about the freebsd-stable mailing list