fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / arch / i386 / boot / edd.S
index 8897906..3432136 100644 (file)
 /*
  * BIOS Enhanced Disk Drive support
+ * Copyright (C) 2002, 2003, 2004 Dell, Inc.
  * by Matt Domsch <Matt_Domsch@dell.com> October 2002
  * conformant to T13 Committee www.t13.org
  *   projects 1572D, 1484D, 1386D, 1226DT
  * disk signature read by Matt Domsch <Matt_Domsch@dell.com>
  *     and Andrew Wilks <Andrew_Wilks@dell.com> September 2003, June 2004
- * legacy CHS retreival by Patrick J. LoPresti <patl@users.sourceforge.net>
+ * legacy CHS retrieval by Patrick J. LoPresti <patl@users.sourceforge.net>
  *      March 2004
+ * Command line option parsing, Matt Domsch, November 2004
  */
 
 #include <linux/edd.h>
+#include <asm/setup.h>
 
 #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
+
+# It is assumed that %ds == INITSEG here
+
+       movb    $0, (EDD_MBR_SIG_NR_BUF)
+       movb    $0, (EDDNR)
+
+# Check the command line for options:
+# edd=of  disables EDD completely  (edd=off)
+# edd=sk  skips the MBR test    (edd=skipmbr)
+# edd=on  re-enables EDD (edd=on)
+
+       pushl   %esi
+       movw    $edd_mbr_sig_start, %di # Default to edd=on
+
+       movl    %cs:(cmd_line_ptr), %esi
+       andl    %esi, %esi
+       jz      old_cl                  # Old boot protocol?
+
+# Convert to a real-mode pointer in fs:si
+       movl    %esi, %eax
+       shrl    $4, %eax
+       movw    %ax, %fs
+       andw    $0xf, %si
+       jmp     have_cl_pointer
+
+# Old-style boot protocol?
+old_cl:
+       push    %ds                     # aka INITSEG
+       pop     %fs
+
+       cmpw    $0xa33f, (0x20)
+       jne     done_cl                 # No command line at all?
+       movw    (0x22), %si             # Pointer relative to INITSEG
+
+# fs:si has the pointer to the command line now
+have_cl_pointer:
+
+# Loop through kernel command line one byte at a time.  Just in
+# case the loader is buggy and failed to null-terminate the command line
+# terminate if we get close enough to the end of the segment that we
+# cannot fit "edd=XX"...
+cl_atspace:
+       cmpw    $-5, %si                # Watch for segment wraparound
+       jae     done_cl
+       movl    %fs:(%si), %eax
+       andb    %al, %al                # End of line?
+       jz      done_cl
+       cmpl    $EDD_CL_EQUALS, %eax
+       jz      found_edd_equals
+       cmpb    $0x20, %al              # <= space consider whitespace
+       ja      cl_skipword
+       incw    %si
+       jmp     cl_atspace
+
+cl_skipword:
+       cmpw    $-5, %si                # Watch for segment wraparound
+       jae     done_cl
+       movb    %fs:(%si), %al          # End of string?
+       andb    %al, %al
+       jz      done_cl
+       cmpb    $0x20, %al
+       jbe     cl_atspace
+       incw    %si
+       jmp     cl_skipword
+
+found_edd_equals:
+# only looking at first two characters after equals
+# late overrides early on the command line, so keep going after finding something
+       movw    %fs:4(%si), %ax
+       cmpw    $EDD_CL_OFF, %ax        # edd=of
+       je      do_edd_off
+       cmpw    $EDD_CL_SKIP, %ax       # edd=sk
+       je      do_edd_skipmbr
+       cmpw    $EDD_CL_ON, %ax         # edd=on
+       je      do_edd_on
+       jmp     cl_skipword
+do_edd_skipmbr:
+       movw    $edd_start, %di
+       jmp     cl_skipword
+do_edd_off:
+       movw    $edd_done, %di
+       jmp     cl_skipword
+do_edd_on:
+       movw    $edd_mbr_sig_start, %di
+       jmp     cl_skipword
+
+done_cl:
+       popl    %esi
+       jmpw    *%di
+
 # Read the first sector of each BIOS disk device and store the 4-byte signature
 edd_mbr_sig_start:
-       movb    $0, (EDD_MBR_SIG_NR_BUF)        # zero value at EDD_MBR_SIG_NR_BUF
        movb    $0x80, %dl                      # from device 80
        movw    $EDD_MBR_SIG_BUF, %bx           # store buffer ptr in bx
 edd_mbr_sig_read:
@@ -37,6 +129,8 @@ edd_mbr_sig_read:
        popw    %es
        popw    %bx
        jc      edd_mbr_sig_done                # on failure, we're done.
+       cmpb    $0, %ah         # some BIOSes do not set CF
+       jne     edd_mbr_sig_done                # on failure, we're done.
        movl    (EDDBUF+EDD_MBR_SIG_OFFSET), %eax # read sig out of the MBR
        movl    %eax, (%bx)                     # store success
        incb    (EDD_MBR_SIG_NR_BUF)            # note that we stored something
@@ -76,7 +170,6 @@ edd_start:
                                                        # result buffer for fn48
        movw    $EDDBUF+EDDEXTSIZE, %si         # in ds:si, fn41 results
                                                # kept just before that
-       movb    $0, (EDDNR)                     # zero value at EDDNR
        movb    $0x80, %dl                      # BIOS device 0x80
 
 edd_check_ext: