X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fi386%2Fboot%2Fedd.S;h=34321368011ac7b2aadf6111f37d038c274609a8;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=faaa555bbb60a54ccef10887d928a9245ec981de;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/arch/i386/boot/edd.S b/arch/i386/boot/edd.S index faaa555bb..343213680 100644 --- a/arch/i386/boot/edd.S +++ b/arch/i386/boot/edd.S @@ -1,39 +1,144 @@ /* * BIOS Enhanced Disk Drive support + * Copyright (C) 2002, 2003, 2004 Dell, Inc. * by Matt Domsch October 2002 * conformant to T13 Committee www.t13.org * projects 1572D, 1484D, 1386D, 1226DT * disk signature read by Matt Domsch - * and Andrew Wilks September 2003 - * legacy CHS retreival by Patrick J. LoPresti + * and Andrew Wilks September 2003, June 2004 + * legacy CHS retrieval by Patrick J. LoPresti * March 2004 + * Command line option parsing, Matt Domsch, November 2004 */ #include +#include #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) -# Read the first sector of device 80h and store the 4-byte signature + +# 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 $0x80, %dl # from device 80 + movw $EDD_MBR_SIG_BUF, %bx # store buffer ptr in bx +edd_mbr_sig_read: movl $0xFFFFFFFF, %eax - movl %eax, (DISK80_SIG_BUFFER) # assume failure + movl %eax, (%bx) # assume failure + pushw %bx movb $READ_SECTORS, %ah movb $1, %al # read 1 sector - movb $0x80, %dl # from device 80 movb $0, %dh # at head 0 movw $1, %cx # cylinder 0, sector 0 pushw %es pushw %ds popw %es - movw $EDDBUF, %bx - pushw %dx # work around buggy BIOSes + movw $EDDBUF, %bx # disk's data goes into EDDBUF + pushw %dx # work around buggy BIOSes stc # work around buggy BIOSes - int $0x13 + int $0x13 sti # work around buggy BIOSes - popw %dx - jc disk_sig_done - movl (EDDBUF+MBR_SIG_OFFSET), %eax - movl %eax, (DISK80_SIG_BUFFER) # store success -disk_sig_done: + popw %dx 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 + incb %dl # increment to next device + addw $4, %bx # increment sig buffer ptr + cmpb $EDD_MBR_SIG_MAX, (EDD_MBR_SIG_NR_BUF) # Out of space? + jb edd_mbr_sig_read # keep looping +edd_mbr_sig_done: # Do the BIOS Enhanced Disk Drive calls # This consists of two calls: @@ -65,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: