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
_______________________________________________
freebsd-stable@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-stable
To unsubscribe, send any mail to "freebsd-stable-unsubscr...@freebsd.org"

Reply via email to