Commit 575400d1b483fbe9e03c68758059bfaf4e4768d1

Authored by H. Peter Anvin
Committed by Andi Kleen
1 parent 53ee11ae0d

[PATCH] i386: Fix the EDD code misparsing the command line

The EDD code would scan the command line as a fixed array, without
taking account of either whitespace, null-termination, the old
command-line protocol, late overrides early, or the fact that the
command line may not be reachable from INITSEG.

This should fix those problems, and enable us to use a longer command
line.

Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Signed-off-by: Andi Kleen <ak@suse.de>

Showing 2 changed files with 76 additions and 22 deletions Side-by-side Diff

arch/i386/boot/edd.S
... ... @@ -15,42 +15,95 @@
15 15 #include <asm/setup.h>
16 16  
17 17 #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
  18 +
  19 +# It is assumed that %ds == INITSEG here
  20 +
18 21 movb $0, (EDD_MBR_SIG_NR_BUF)
19 22 movb $0, (EDDNR)
20 23  
21   -# Check the command line for two options:
  24 +# Check the command line for options:
22 25 # edd=of disables EDD completely (edd=off)
23 26 # edd=sk skips the MBR test (edd=skipmbr)
  27 +# edd=on re-enables EDD (edd=on)
  28 +
24 29 pushl %esi
25   - cmpl $0, %cs:cmd_line_ptr
26   - jz done_cl
  30 + movw $edd_mbr_sig_start, %di # Default to edd=on
  31 +
27 32 movl %cs:(cmd_line_ptr), %esi
28   -# ds:esi has the pointer to the command line now
29   - movl $(COMMAND_LINE_SIZE-7), %ecx
30   -# loop through kernel command line one byte at a time
31   -cl_loop:
32   - cmpl $EDD_CL_EQUALS, (%si)
  33 + andl %esi, %esi
  34 + jz old_cl # Old boot protocol?
  35 +
  36 +# Convert to a real-mode pointer in fs:si
  37 + movl %esi, %eax
  38 + shrl $4, %eax
  39 + movw %ax, %fs
  40 + andw $0xf, %si
  41 + jmp have_cl_pointer
  42 +
  43 +# Old-style boot protocol?
  44 +old_cl:
  45 + push %ds # aka INITSEG
  46 + pop %fs
  47 +
  48 + cmpw $0xa33f, (0x20)
  49 + jne done_cl # No command line at all?
  50 + movw (0x22), %si # Pointer relative to INITSEG
  51 +
  52 +# fs:si has the pointer to the command line now
  53 +have_cl_pointer:
  54 +
  55 +# Loop through kernel command line one byte at a time. Just in
  56 +# case the loader is buggy and failed to null-terminate the command line
  57 +# terminate if we get close enough to the end of the segment that we
  58 +# cannot fit "edd=XX"...
  59 +cl_atspace:
  60 + cmpw $-5, %si # Watch for segment wraparound
  61 + jae done_cl
  62 + movl %fs:(%si), %eax
  63 + andb %al, %al # End of line?
  64 + jz done_cl
  65 + cmpl $EDD_CL_EQUALS, %eax
33 66 jz found_edd_equals
34   - incl %esi
35   - loop cl_loop
36   - jmp done_cl
  67 + cmpb $0x20, %al # <= space consider whitespace
  68 + ja cl_skipword
  69 + incw %si
  70 + jmp cl_atspace
  71 +
  72 +cl_skipword:
  73 + cmpw $-5, %si # Watch for segment wraparound
  74 + jae done_cl
  75 + movb %fs:(%si), %al # End of string?
  76 + andb %al, %al
  77 + jz done_cl
  78 + cmpb $0x20, %al
  79 + jbe cl_atspace
  80 + incw %si
  81 + jmp cl_skipword
  82 +
37 83 found_edd_equals:
38 84 # only looking at first two characters after equals
39   - addl $4, %esi
40   - cmpw $EDD_CL_OFF, (%si) # edd=of
41   - jz do_edd_off
42   - cmpw $EDD_CL_SKIP, (%si) # edd=sk
43   - jz do_edd_skipmbr
44   - jmp done_cl
  85 +# late overrides early on the command line, so keep going after finding something
  86 + movw %fs:4(%si), %ax
  87 + cmpw $EDD_CL_OFF, %ax # edd=of
  88 + je do_edd_off
  89 + cmpw $EDD_CL_SKIP, %ax # edd=sk
  90 + je do_edd_skipmbr
  91 + cmpw $EDD_CL_ON, %ax # edd=on
  92 + je do_edd_on
  93 + jmp cl_skipword
45 94 do_edd_skipmbr:
46   - popl %esi
47   - jmp edd_start
  95 + movw $edd_start, %di
  96 + jmp cl_skipword
48 97 do_edd_off:
49   - popl %esi
50   - jmp edd_done
  98 + movw $edd_done, %di
  99 + jmp cl_skipword
  100 +do_edd_on:
  101 + movw $edd_mbr_sig_start, %di
  102 + jmp cl_skipword
  103 +
51 104 done_cl:
52 105 popl %esi
53   -
  106 + jmpw *%di
54 107  
55 108 # Read the first sector of each BIOS disk device and store the 4-byte signature
56 109 edd_mbr_sig_start:
... ... @@ -52,6 +52,7 @@
52 52 #define EDD_CL_EQUALS 0x3d646465 /* "edd=" */
53 53 #define EDD_CL_OFF 0x666f /* "of" for off */
54 54 #define EDD_CL_SKIP 0x6b73 /* "sk" for skipmbr */
  55 +#define EDD_CL_ON 0x6e6f /* "on" for on */
55 56  
56 57 #ifndef __ASSEMBLY__
57 58