From owner-freebsd-stable@FreeBSD.ORG Wed Jun 22 15:58:18 2011 Return-Path: Delivered-To: freebsd-stable@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 28B14106566B for ; Wed, 22 Jun 2011 15:58:18 +0000 (UTC) (envelope-from jhb@freebsd.org) Received: from cyrus.watson.org (cyrus.watson.org [65.122.17.42]) by mx1.freebsd.org (Postfix) with ESMTP id C9BB68FC15 for ; Wed, 22 Jun 2011 15:58:17 +0000 (UTC) Received: from bigwig.baldwin.cx (66.111.2.69.static.nyinternet.net [66.111.2.69]) by cyrus.watson.org (Postfix) with ESMTPSA id 5E59546B06; Wed, 22 Jun 2011 11:58:17 -0400 (EDT) Received: from jhbbsd.localnet (unknown [209.249.190.124]) by bigwig.baldwin.cx (Postfix) with ESMTPSA id EABB28A01F; Wed, 22 Jun 2011 11:58:16 -0400 (EDT) From: John Baldwin To: Henri Hennebert Date: Wed, 22 Jun 2011 11:58:16 -0400 User-Agent: KMail/1.13.5 (FreeBSD/8.2-CBSD-20110617; KDE/4.5.5; amd64; ; ) References: <4E01FA03.9070805@restart.be> <4E01FADA.2070104@restart.be> In-Reply-To: <4E01FADA.2070104@restart.be> MIME-Version: 1.0 Content-Type: Text/Plain; charset="iso-8859-15" Content-Transfer-Encoding: 7bit Message-Id: <201106221158.16485.jhb@freebsd.org> X-Greylist: Sender succeeded SMTP AUTH, not delayed by milter-greylist-4.2.6 (bigwig.baldwin.cx); Wed, 22 Jun 2011 11:58:17 -0400 (EDT) Cc: freebsd-stable@freebsd.org Subject: Re: ZFS boot inside on the second partition inside a slice X-BeenThere: freebsd-stable@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Production branch of FreeBSD source code List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 22 Jun 2011 15:58:18 -0000 On Wednesday, June 22, 2011 10:23:22 am Henri Hennebert wrote: > On 06/22/2011 16:19, Henri Hennebert wrote: > > This time: > > > > LBA: 3c802308 > > Read error: 04 > > > > This morning I was reading the code (I'm in Belgium) and find that the > > previous LBA output was DAP+4 and so was the addr of the buffer. 0x8200 > > = $MEM_BUF+512, and so we must be in the second read. > > > > OK I think I see, the first read mangle the partition table previously > read at $MEM_BUF and so the next one is wrong. Ahh, very true. I was planning to simplify the code to just load at MEM_BTX directly and avoid copying BTX. I went ahead and did that below: 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 -- John Baldwin