mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-07-05 13:51:52 +00:00
[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>
This commit is contained in:
parent
53ee11ae0d
commit
575400d1b4
2 changed files with 76 additions and 22 deletions
|
@ -15,42 +15,95 @@
|
||||||
#include <asm/setup.h>
|
#include <asm/setup.h>
|
||||||
|
|
||||||
#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
|
#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
|
||||||
|
|
||||||
|
# It is assumed that %ds == INITSEG here
|
||||||
|
|
||||||
movb $0, (EDD_MBR_SIG_NR_BUF)
|
movb $0, (EDD_MBR_SIG_NR_BUF)
|
||||||
movb $0, (EDDNR)
|
movb $0, (EDDNR)
|
||||||
|
|
||||||
# Check the command line for two options:
|
# Check the command line for options:
|
||||||
# edd=of disables EDD completely (edd=off)
|
# edd=of disables EDD completely (edd=off)
|
||||||
# edd=sk skips the MBR test (edd=skipmbr)
|
# edd=sk skips the MBR test (edd=skipmbr)
|
||||||
|
# edd=on re-enables EDD (edd=on)
|
||||||
|
|
||||||
pushl %esi
|
pushl %esi
|
||||||
cmpl $0, %cs:cmd_line_ptr
|
movw $edd_mbr_sig_start, %di # Default to edd=on
|
||||||
jz done_cl
|
|
||||||
movl %cs:(cmd_line_ptr), %esi
|
movl %cs:(cmd_line_ptr), %esi
|
||||||
# ds:esi has the pointer to the command line now
|
andl %esi, %esi
|
||||||
movl $(COMMAND_LINE_SIZE-7), %ecx
|
jz old_cl # Old boot protocol?
|
||||||
# loop through kernel command line one byte at a time
|
|
||||||
cl_loop:
|
# Convert to a real-mode pointer in fs:si
|
||||||
cmpl $EDD_CL_EQUALS, (%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
|
jz found_edd_equals
|
||||||
incl %esi
|
cmpb $0x20, %al # <= space consider whitespace
|
||||||
loop cl_loop
|
ja cl_skipword
|
||||||
jmp done_cl
|
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:
|
found_edd_equals:
|
||||||
# only looking at first two characters after equals
|
# only looking at first two characters after equals
|
||||||
addl $4, %esi
|
# late overrides early on the command line, so keep going after finding something
|
||||||
cmpw $EDD_CL_OFF, (%si) # edd=of
|
movw %fs:4(%si), %ax
|
||||||
jz do_edd_off
|
cmpw $EDD_CL_OFF, %ax # edd=of
|
||||||
cmpw $EDD_CL_SKIP, (%si) # edd=sk
|
je do_edd_off
|
||||||
jz do_edd_skipmbr
|
cmpw $EDD_CL_SKIP, %ax # edd=sk
|
||||||
jmp done_cl
|
je do_edd_skipmbr
|
||||||
|
cmpw $EDD_CL_ON, %ax # edd=on
|
||||||
|
je do_edd_on
|
||||||
|
jmp cl_skipword
|
||||||
do_edd_skipmbr:
|
do_edd_skipmbr:
|
||||||
popl %esi
|
movw $edd_start, %di
|
||||||
jmp edd_start
|
jmp cl_skipword
|
||||||
do_edd_off:
|
do_edd_off:
|
||||||
popl %esi
|
movw $edd_done, %di
|
||||||
jmp edd_done
|
jmp cl_skipword
|
||||||
|
do_edd_on:
|
||||||
|
movw $edd_mbr_sig_start, %di
|
||||||
|
jmp cl_skipword
|
||||||
|
|
||||||
done_cl:
|
done_cl:
|
||||||
popl %esi
|
popl %esi
|
||||||
|
jmpw *%di
|
||||||
|
|
||||||
# Read the first sector of each BIOS disk device and store the 4-byte signature
|
# Read the first sector of each BIOS disk device and store the 4-byte signature
|
||||||
edd_mbr_sig_start:
|
edd_mbr_sig_start:
|
||||||
|
|
|
@ -52,6 +52,7 @@
|
||||||
#define EDD_CL_EQUALS 0x3d646465 /* "edd=" */
|
#define EDD_CL_EQUALS 0x3d646465 /* "edd=" */
|
||||||
#define EDD_CL_OFF 0x666f /* "of" for off */
|
#define EDD_CL_OFF 0x666f /* "of" for off */
|
||||||
#define EDD_CL_SKIP 0x6b73 /* "sk" for skipmbr */
|
#define EDD_CL_SKIP 0x6b73 /* "sk" for skipmbr */
|
||||||
|
#define EDD_CL_ON 0x6e6f /* "on" for on */
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue