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