From 529a2dc5e074b8ac5a99344581c261d3bac4dac7 Mon Sep 17 00:00:00 2001 From: okuji Date: Tue, 25 Jul 2000 12:08:14 +0000 Subject: [PATCH] fix some bugs in the linux boot code. --- ChangeLog | 18 ++++++++++++++++++ grub/asmstub.c | 1 + stage2/asm.S | 14 ++++++++------ stage2/boot.c | 5 ++++- stage2/shared.h | 4 ++-- 5 files changed, 33 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index e1ed66552..f55217fcf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2000-07-25 OKUJI Yoshinori + + * stage2/asm.S [!STAGE1_5] (linux_text_len): New variable. + [!STAGE1_5] (linux_boot): Don't set %eax to LINUX_SETUP + meaninglessly. + Set %ecx to LINUX_TEXT_LEN instead of LINUX_KERNEL_MAXLEN. + [!STAGE1_5] (big_linux_boot): Disable interrupts before changing + the stack pointer. + Change %ss right before %sp. + Reverse the arguments for ljmp. A segment must be after an + offset. *sigh* + * stage2/boot.c (load_image): Set LINUX_TEXT_LEN to TEXT_LEN, + if a Linux kernel is loaded successfully. + * stage2/shared.h (LINUX_VID_MODE_OFFSET): Removed. + [!ASM_FILE] (linux_kernel_header): Change the type of the member + `heap_end_ptr' to unsigned short. + [!ASM_FILE] (linux_text_len): Declared. + 2000-07-24 OKUJI Yoshinori Comply with the Linux/i386 boot protocol version 2.02. diff --git a/grub/asmstub.c b/grub/asmstub.c index fb488c548..1bbb77062 100644 --- a/grub/asmstub.c +++ b/grub/asmstub.c @@ -66,6 +66,7 @@ unsigned long install_partition = 0x20000; unsigned long boot_drive = 0; char version_string[] = VERSION; char config_file[128] = "/boot/grub/menu.lst"; /* FIXME: arbitrary */ +unsigned long linux_text_len = 0; /* Emulation requirements. */ char *grub_scratch_mem = 0; diff --git a/stage2/asm.S b/stage2/asm.S index d7c187394..d0bad03a3 100644 --- a/stage2/asm.S +++ b/stage2/asm.S @@ -1689,14 +1689,15 @@ ENTRY(patch_code_end) * entry point of the Linux setup code. */ +VARIABLE(linux_text_len) + .long 0 + ENTRY(linux_boot) /* don't worry about saving anything, we're committed at this point */ cld /* forward copying */ /* copy kernel */ - movl $LINUX_SETUP, %eax - /* XXX: Too many bytes, but there is no bad effect */ - movl $LINUX_KERNEL_MAXLEN, %ecx + movl EXT_C(linux_text_len), %ecx shll $2, %ecx movl $LINUX_STAGING_AREA, %esi movl $LINUX_KERNEL, %edi @@ -1715,10 +1716,11 @@ ENTRY(big_linux_boot) .code16 /* final setup for linux boot */ - movw $LINUX_SETUP_STACK, %sp - + cli movw $LINUX_INIT_SEG, %ax movw %ax, %ss + movw $LINUX_SETUP_STACK, %sp + movw %ax, %ds movw %ax, %es movw %ax, %fs @@ -1727,8 +1729,8 @@ ENTRY(big_linux_boot) /* jump to start */ /* ljmp */ .byte 0xea - .word LINUX_SETUP_SEG .word 0 + .word LINUX_SETUP_SEG .code32 diff --git a/stage2/boot.c b/stage2/boot.c index 32e0264cf..18ac8d609 100644 --- a/stage2/boot.c +++ b/stage2/boot.c @@ -347,10 +347,13 @@ load_image (char *kernel, char *arg, kernel_t suggested_type, errnum = ERR_EXEC_FORMAT; return KERNEL_TYPE_NONE; } + + /* Ugly hack. */ + linux_text_len = text_len; return big_linux ? KERNEL_TYPE_BIG_LINUX : KERNEL_TYPE_LINUX; } - else if (!errnum) + else if (! errnum) errnum = ERR_EXEC_FORMAT; } else diff --git a/stage2/shared.h b/stage2/shared.h index ef4a4ddb1..3e2ec51cc 100644 --- a/stage2/shared.h +++ b/stage2/shared.h @@ -154,7 +154,6 @@ extern char *grub_scratch_mem; #define LINUX_FLAG_BIG_KERNEL 0x1 /* Linux's video mode selection support. Actually I hate it! */ -#define LINUX_VID_MODE_OFFSET 0x1FA #define LINUX_VID_MODE_NORMAL 0xFFFF #define LINUX_VID_MODE_EXTENDED 0xFFFE #define LINUX_VID_MODE_ASK 0xFFFD @@ -396,7 +395,7 @@ struct linux_kernel_header unsigned long ramdisk_image; /* initrd load address */ unsigned long ramdisk_size; /* initrd size */ unsigned long bootsect_kludge; /* obsolete */ - unsigned long heap_end_ptr; /* Free memory after setup end */ + unsigned short heap_end_ptr; /* Free memory after setup end */ unsigned short pad1; /* Unused */ unsigned long cmd_line_ptr; /* Points to the kernel command line */ } __attribute__ ((packed)); @@ -460,6 +459,7 @@ extern unsigned long boot_part_offset; extern unsigned char force_lba; extern char version_string[]; extern char config_file[]; +extern unsigned long linux_text_len; #ifdef GRUB_UTIL /* If not using config file, this variable is set to zero,