aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2006-09-26 04:52:38 -0400
committerAndi Kleen <andi@basil.nowhere.org>2006-09-26 04:52:38 -0400
commit575400d1b483fbe9e03c68758059bfaf4e4768d1 (patch)
tree9839d343d235dabfdb27e8ad2e48511ae542b015
parent53ee11ae0d73f28029a5f0d991bc4dcd7c817e7a (diff)
[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>
-rw-r--r--arch/i386/boot/edd.S97
-rw-r--r--include/linux/edd.h1
2 files changed, 76 insertions, 22 deletions
diff --git a/arch/i386/boot/edd.S b/arch/i386/boot/edd.S
index 4b84ea216f2b..34321368011a 100644
--- a/arch/i386/boot/edd.S
+++ b/arch/i386/boot/edd.S
@@ -15,42 +15,95 @@
15#include <asm/setup.h> 15#include <asm/setup.h>
16 16
17#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) 17#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
18
19# It is assumed that %ds == INITSEG here
20
18 movb $0, (EDD_MBR_SIG_NR_BUF) 21 movb $0, (EDD_MBR_SIG_NR_BUF)
19 movb $0, (EDDNR) 22 movb $0, (EDDNR)
20 23
21# Check the command line for two options: 24# Check the command line for options:
22# edd=of disables EDD completely (edd=off) 25# edd=of disables EDD completely (edd=off)
23# edd=sk skips the MBR test (edd=skipmbr) 26# edd=sk skips the MBR test (edd=skipmbr)
27# edd=on re-enables EDD (edd=on)
28
24 pushl %esi 29 pushl %esi
25 cmpl $0, %cs:cmd_line_ptr 30 movw $edd_mbr_sig_start, %di # Default to edd=on
26 jz done_cl 31
27 movl %cs:(cmd_line_ptr), %esi 32 movl %cs:(cmd_line_ptr), %esi
28# ds:esi has the pointer to the command line now 33 andl %esi, %esi
29 movl $(COMMAND_LINE_SIZE-7), %ecx 34 jz old_cl # Old boot protocol?
30# loop through kernel command line one byte at a time 35
31cl_loop: 36# Convert to a real-mode pointer in fs:si
32 cmpl $EDD_CL_EQUALS, (%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?
44old_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
53have_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"...
59cl_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 jz found_edd_equals 66 jz found_edd_equals
34 incl %esi 67 cmpb $0x20, %al # <= space consider whitespace
35 loop cl_loop 68 ja cl_skipword
36 jmp done_cl 69 incw %si
70 jmp cl_atspace
71
72cl_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
37found_edd_equals: 83found_edd_equals:
38# only looking at first two characters after equals 84# only looking at first two characters after equals
39 addl $4, %esi 85# late overrides early on the command line, so keep going after finding something
40 cmpw $EDD_CL_OFF, (%si) # edd=of 86 movw %fs:4(%si), %ax
41 jz do_edd_off 87 cmpw $EDD_CL_OFF, %ax # edd=of
42 cmpw $EDD_CL_SKIP, (%si) # edd=sk 88 je do_edd_off
43 jz do_edd_skipmbr 89 cmpw $EDD_CL_SKIP, %ax # edd=sk
44 jmp done_cl 90 je do_edd_skipmbr
91 cmpw $EDD_CL_ON, %ax # edd=on
92 je do_edd_on
93 jmp cl_skipword
45do_edd_skipmbr: 94do_edd_skipmbr:
46 popl %esi 95 movw $edd_start, %di
47 jmp edd_start 96 jmp cl_skipword
48do_edd_off: 97do_edd_off:
49 popl %esi 98 movw $edd_done, %di
50 jmp edd_done 99 jmp cl_skipword
100do_edd_on:
101 movw $edd_mbr_sig_start, %di
102 jmp cl_skipword
103
51done_cl: 104done_cl:
52 popl %esi 105 popl %esi
53 106 jmpw *%di
54 107
55# Read the first sector of each BIOS disk device and store the 4-byte signature 108# Read the first sector of each BIOS disk device and store the 4-byte signature
56edd_mbr_sig_start: 109edd_mbr_sig_start:
diff --git a/include/linux/edd.h b/include/linux/edd.h
index 162512b886f7..b2b3e68aa512 100644
--- a/include/linux/edd.h
+++ b/include/linux/edd.h
@@ -52,6 +52,7 @@
52#define EDD_CL_EQUALS 0x3d646465 /* "edd=" */ 52#define EDD_CL_EQUALS 0x3d646465 /* "edd=" */
53#define EDD_CL_OFF 0x666f /* "of" for off */ 53#define EDD_CL_OFF 0x666f /* "of" for off */
54#define EDD_CL_SKIP 0x6b73 /* "sk" for skipmbr */ 54#define EDD_CL_SKIP 0x6b73 /* "sk" for skipmbr */
55#define EDD_CL_ON 0x6e6f /* "on" for on */
55 56
56#ifndef __ASSEMBLY__ 57#ifndef __ASSEMBLY__
57 58