2002-07-12 Yoshinori K. Okuji <okuji@enbug.org>
* stage2/boot.c (load_image): Rewrite the Linux booting support radically. Now it should work even on a machine having, say, only 128KB, theoretically. Of course, GRUB itself doesn't work on such a system, though. (load_initrd): Initialize LH based on CUR_ADDR, because the location becomes dynamic. * stage2/shared.h (LINUX_MAX_SETUP_SECTS): Set to 64. (LINUX_HEAP_END_OFFSET): Set to (0x9000 - 0x200). (LINUX_STAGING_AREA): Removed. (LINUX_SETUP): Likewise. (LINUX_KERNEL): Likewise. (LINUX_KERNEL_MAXLEN): Likewise. (LINUX_SETUP_SEG): Likewise. (LINUX_INIT_SEG): Likewise. (LINUX_SETUP_STACK): Set to 0x9000. (LINUX_BZIMAGE_ADDR): New macro. (LINUX_ZIMAGE_ADDR): Likewise. (LINUX_OLD_REAL_MODE_ADDR): Likewise. (CL_MY_LOCATION): Removed. (CL_MY_END_ADDR): Likewise. (CL_BASE_ADDR): Likewise. (CL_MAGIC): Renamed to ... (LINUX_CL_MAGIC): ... this. (LINUX_CL_OFFSET): New macro. (LINUX_CL_END_OFFSET): Likewise. (LINUX_SETUP_MOVE_SIZE): Likewise. (struct linux_kernel_header): Change the type of the member "cmd_line_ptr" to char *. (linux_data_tmp_addr): Declared. (linux_data_real_addr): Likewise. * stage2/asm.S [!STAGE1_5] (linux_data_tmp_addr): New variable. [!STAGE1_5] (linux_data_real_addr): Likewise. [!STAGE1_5] (big_linux_boot): Copy the real mode part from LINUX_DATA_TMP_ADDR to LINUX_DATA_REAL_ADDR. * grub/asmstub.c (linux_data_tmp_addr): New variable. (linux_data_real_addr): Likewise.
This commit is contained in:
parent
f8b4503f1b
commit
51955d52d8
6 changed files with 158 additions and 88 deletions
39
ChangeLog
39
ChangeLog
|
@ -1,3 +1,42 @@
|
|||
2002-07-12 Yoshinori K. Okuji <okuji@enbug.org>
|
||||
|
||||
* stage2/boot.c (load_image): Rewrite the Linux booting support
|
||||
radically. Now it should work even on a machine having, say,
|
||||
only 128KB, theoretically. Of course, GRUB itself doesn't work
|
||||
on such a system, though.
|
||||
(load_initrd): Initialize LH based on CUR_ADDR, because the
|
||||
location becomes dynamic.
|
||||
* stage2/shared.h (LINUX_MAX_SETUP_SECTS): Set to 64.
|
||||
(LINUX_HEAP_END_OFFSET): Set to (0x9000 - 0x200).
|
||||
(LINUX_STAGING_AREA): Removed.
|
||||
(LINUX_SETUP): Likewise.
|
||||
(LINUX_KERNEL): Likewise.
|
||||
(LINUX_KERNEL_MAXLEN): Likewise.
|
||||
(LINUX_SETUP_SEG): Likewise.
|
||||
(LINUX_INIT_SEG): Likewise.
|
||||
(LINUX_SETUP_STACK): Set to 0x9000.
|
||||
(LINUX_BZIMAGE_ADDR): New macro.
|
||||
(LINUX_ZIMAGE_ADDR): Likewise.
|
||||
(LINUX_OLD_REAL_MODE_ADDR): Likewise.
|
||||
(CL_MY_LOCATION): Removed.
|
||||
(CL_MY_END_ADDR): Likewise.
|
||||
(CL_BASE_ADDR): Likewise.
|
||||
(CL_MAGIC): Renamed to ...
|
||||
(LINUX_CL_MAGIC): ... this.
|
||||
(LINUX_CL_OFFSET): New macro.
|
||||
(LINUX_CL_END_OFFSET): Likewise.
|
||||
(LINUX_SETUP_MOVE_SIZE): Likewise.
|
||||
(struct linux_kernel_header): Change the type of the member
|
||||
"cmd_line_ptr" to char *.
|
||||
(linux_data_tmp_addr): Declared.
|
||||
(linux_data_real_addr): Likewise.
|
||||
* stage2/asm.S [!STAGE1_5] (linux_data_tmp_addr): New variable.
|
||||
[!STAGE1_5] (linux_data_real_addr): Likewise.
|
||||
[!STAGE1_5] (big_linux_boot): Copy the real mode part from
|
||||
LINUX_DATA_TMP_ADDR to LINUX_DATA_REAL_ADDR.
|
||||
* grub/asmstub.c (linux_data_tmp_addr): New variable.
|
||||
(linux_data_real_addr): Likewise.
|
||||
|
||||
2002-07-09 Yoshinori K. Okuji <okuji@enbug.org>
|
||||
|
||||
From Mark Kettenis <kettenis@chello.nl>:
|
||||
|
|
2
NEWS
2
NEWS
|
@ -20,6 +20,8 @@ New in 0.93:
|
|||
intelligent terminal (such as the comint mode in GNU Emacs).
|
||||
* The utility ``grub-md5-crypt'' prompts to retype a password and checks
|
||||
if the passwords match.
|
||||
* Support for booting Linux is rewritten, so GRUB now supports
|
||||
large-EBDA systems.
|
||||
|
||||
New in 0.92 - 2002-04-30:
|
||||
* The command "displaymem" uses only hex digits for consistency.
|
||||
|
|
|
@ -73,6 +73,8 @@ int saved_entryno = 0;
|
|||
char version_string[] = VERSION;
|
||||
char config_file[128] = "/boot/grub/menu.lst"; /* FIXME: arbitrary */
|
||||
unsigned long linux_text_len = 0;
|
||||
char *linux_data_tmp_addr = 0;
|
||||
char *linux_data_real_addr = 0;
|
||||
unsigned short io_map[IO_MAP_SIZE];
|
||||
struct apm_info apm_bios_info;
|
||||
|
||||
|
|
40
stage2/asm.S
40
stage2/asm.S
|
@ -1728,6 +1728,12 @@ ENTRY(patch_code_end)
|
|||
VARIABLE(linux_text_len)
|
||||
.long 0
|
||||
|
||||
VARIABLE(linux_data_tmp_addr)
|
||||
.long 0
|
||||
|
||||
VARIABLE(linux_data_real_addr)
|
||||
.long 0
|
||||
|
||||
ENTRY(linux_boot)
|
||||
/* don't worry about saving anything, we're committed at this point */
|
||||
cld /* forward copying */
|
||||
|
@ -1736,13 +1742,29 @@ ENTRY(linux_boot)
|
|||
movl EXT_C(linux_text_len), %ecx
|
||||
addl $3, %ecx
|
||||
shrl $2, %ecx
|
||||
movl $LINUX_STAGING_AREA, %esi
|
||||
movl $LINUX_KERNEL, %edi
|
||||
movl $LINUX_BZIMAGE_ADDR, %esi
|
||||
movl $LINUX_ZIMAGE_ADDR, %edi
|
||||
|
||||
rep
|
||||
movsl
|
||||
|
||||
ENTRY(big_linux_boot)
|
||||
movl EXT_C(linux_data_real_addr), %ebx
|
||||
|
||||
/* copy the real mode part */
|
||||
movl EXT_C(linux_data_tmp_addr), %esi
|
||||
movl %ebx, %edi
|
||||
movl $LINUX_SETUP_MOVE_SIZE, %ecx
|
||||
cld
|
||||
rep
|
||||
movsb
|
||||
|
||||
/* change %ebx to the segment address */
|
||||
shrl $4, %ebx
|
||||
movl %ebx, %eax
|
||||
addl $0x20, %eax
|
||||
movl %eax, linux_setup_seg
|
||||
|
||||
/* XXX new stack pointer in safe area for calling functions */
|
||||
movl $0x4000, %esp
|
||||
call EXT_C(stop_floppy)
|
||||
|
@ -1754,20 +1776,20 @@ ENTRY(big_linux_boot)
|
|||
|
||||
/* final setup for linux boot */
|
||||
cli
|
||||
movw $LINUX_INIT_SEG, %ax
|
||||
movw %ax, %ss
|
||||
movw %bx, %ss
|
||||
movw $LINUX_SETUP_STACK, %sp
|
||||
|
||||
movw %ax, %ds
|
||||
movw %ax, %es
|
||||
movw %ax, %fs
|
||||
movw %ax, %gs
|
||||
movw %bx, %ds
|
||||
movw %bx, %es
|
||||
movw %bx, %fs
|
||||
movw %bx, %gs
|
||||
|
||||
/* jump to start */
|
||||
/* ljmp */
|
||||
.byte 0xea
|
||||
.word 0
|
||||
.word LINUX_SETUP_SEG
|
||||
linux_setup_seg:
|
||||
.word 0
|
||||
.code32
|
||||
|
||||
|
||||
|
|
|
@ -227,6 +227,13 @@ load_image (char *kernel, char *arg, kernel_t suggested_type,
|
|||
big_linux = (lh->loadflags & LINUX_FLAG_BIG_KERNEL);
|
||||
lh->type_of_loader = LINUX_BOOT_LOADER_TYPE;
|
||||
|
||||
/* Put the real mode part at as a high location as possible. */
|
||||
linux_data_real_addr
|
||||
= (char *) ((mbi.mem_lower << 10) - LINUX_SETUP_MOVE_SIZE);
|
||||
/* But it must not exceed the traditional area. */
|
||||
if (linux_data_real_addr > (char *) LINUX_OLD_REAL_MODE_ADDR)
|
||||
linux_data_real_addr = (char *) LINUX_OLD_REAL_MODE_ADDR;
|
||||
|
||||
if (lh->version >= 0x0201)
|
||||
{
|
||||
lh->heap_end_ptr = LINUX_HEAP_END_OFFSET;
|
||||
|
@ -234,22 +241,23 @@ load_image (char *kernel, char *arg, kernel_t suggested_type,
|
|||
}
|
||||
|
||||
if (lh->version >= 0x0202)
|
||||
lh->cmd_line_ptr = CL_MY_LOCATION;
|
||||
lh->cmd_line_ptr = linux_data_real_addr + LINUX_CL_OFFSET;
|
||||
else
|
||||
{
|
||||
lh->cl_magic = CL_MAGIC;
|
||||
lh->cl_offset = CL_MY_LOCATION - CL_BASE_ADDR;
|
||||
lh->setup_move_size
|
||||
= (unsigned short) (CL_MY_END_ADDR - CL_BASE_ADDR + 1);
|
||||
lh->cl_magic = LINUX_CL_MAGIC;
|
||||
lh->cl_offset = LINUX_CL_OFFSET;
|
||||
lh->setup_move_size = LINUX_SETUP_MOVE_SIZE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Your kernel is quite old... */
|
||||
lh->cl_magic = CL_MAGIC;
|
||||
lh->cl_offset = CL_MY_LOCATION - CL_BASE_ADDR;
|
||||
lh->cl_magic = LINUX_CL_MAGIC;
|
||||
lh->cl_offset = LINUX_CL_OFFSET;
|
||||
|
||||
setup_sects = LINUX_DEFAULT_SETUP_SECTS;
|
||||
|
||||
linux_data_real_addr = (char *) LINUX_OLD_REAL_MODE_ADDR;
|
||||
}
|
||||
|
||||
/* If SETUP_SECTS is not set, set it to the default (4). */
|
||||
|
@ -259,21 +267,22 @@ load_image (char *kernel, char *arg, kernel_t suggested_type,
|
|||
data_len = setup_sects << 9;
|
||||
text_len = filemax - data_len - SECTOR_SIZE;
|
||||
|
||||
if (! big_linux && text_len > LINUX_KERNEL_MAXLEN)
|
||||
linux_data_tmp_addr = (char *) LINUX_BZIMAGE_ADDR + text_len;
|
||||
|
||||
if (! big_linux
|
||||
&& text_len > linux_data_real_addr - (char *) LINUX_ZIMAGE_ADDR)
|
||||
{
|
||||
grub_printf (" linux 'zImage' kernel too big, try 'make bzImage'\n");
|
||||
grub_close ();
|
||||
errnum = ERR_WONT_FIT;
|
||||
return KERNEL_TYPE_NONE;
|
||||
}
|
||||
|
||||
else if (linux_data_real_addr + LINUX_SETUP_MOVE_SIZE
|
||||
> RAW_ADDR ((char *) (mbi.mem_lower << 10)))
|
||||
errnum = ERR_WONT_FIT;
|
||||
else
|
||||
{
|
||||
grub_printf (" [Linux-%s, setup=0x%x, size=0x%x]\n",
|
||||
(big_linux ? "bzImage" : "zImage"), data_len, text_len);
|
||||
|
||||
/* FIXME: SETUP_SECTS should be supported up to 63.
|
||||
But do you know there are >640KB conventional memory machines? */
|
||||
if (mbi.mem_lower >= 608 && setup_sects < 60)
|
||||
{
|
||||
/* Video mode selection support. What a mess! */
|
||||
/* NOTE: Even the word "mess" is not still enough to
|
||||
represent how wrong and bad the Linux video support is,
|
||||
|
@ -367,19 +376,19 @@ load_image (char *kernel, char *arg, kernel_t suggested_type,
|
|||
/* It is possible that DATA_LEN is greater than MULTIBOOT_SEARCH,
|
||||
so the data may have been read partially. */
|
||||
if (data_len <= MULTIBOOT_SEARCH)
|
||||
grub_memmove ((char *) LINUX_SETUP, buffer,
|
||||
grub_memmove (linux_data_tmp_addr, buffer,
|
||||
data_len + SECTOR_SIZE);
|
||||
else
|
||||
{
|
||||
grub_memmove ((char *) LINUX_SETUP, buffer, MULTIBOOT_SEARCH);
|
||||
grub_read ((char *) LINUX_SETUP + MULTIBOOT_SEARCH,
|
||||
grub_memmove (linux_data_tmp_addr, buffer, MULTIBOOT_SEARCH);
|
||||
grub_read (linux_data_tmp_addr + MULTIBOOT_SEARCH,
|
||||
data_len + SECTOR_SIZE - MULTIBOOT_SEARCH);
|
||||
}
|
||||
|
||||
if (lh->header != LINUX_MAGIC_SIGNATURE ||
|
||||
lh->version < 0x0200)
|
||||
/* Clear the heap space. */
|
||||
grub_memset ((char *) LINUX_SETUP + ((setup_sects - 1) << 9),
|
||||
grub_memset (linux_data_tmp_addr + ((setup_sects + 1) << 9),
|
||||
0,
|
||||
(64 - setup_sects - 1) << 9);
|
||||
|
||||
|
@ -393,24 +402,25 @@ load_image (char *kernel, char *arg, kernel_t suggested_type,
|
|||
avoid to copy spaces unnecessarily. Hell. */
|
||||
{
|
||||
char *src = skip_to (0, arg);
|
||||
char *dest = (char *) CL_MY_LOCATION;
|
||||
char *dest = linux_data_tmp_addr + LINUX_CL_OFFSET;
|
||||
|
||||
while (((int) dest) < CL_MY_END_ADDR && *src)
|
||||
while (dest < linux_data_tmp_addr + LINUX_CL_END_OFFSET && *src)
|
||||
*(dest++) = *(src++);
|
||||
|
||||
/* Add a mem option automatically only if the user doesn't
|
||||
specify it explicitly. */
|
||||
if (! grub_strstr (arg, "mem=")
|
||||
&& ! (load_flags & KERNEL_LOAD_NO_MEM_OPTION))
|
||||
&& ! (load_flags & KERNEL_LOAD_NO_MEM_OPTION)
|
||||
&& dest + 15 < linux_data_tmp_addr + LINUX_CL_END_OFFSET)
|
||||
{
|
||||
if (dest != (char *) CL_MY_LOCATION)
|
||||
*(dest++) = ' ';
|
||||
|
||||
grub_memmove (dest, "mem=", 4);
|
||||
dest += 4;
|
||||
*dest++ = ' ';
|
||||
*dest++ = 'm';
|
||||
*dest++ = 'e';
|
||||
*dest++ = 'm';
|
||||
*dest++ = '=';
|
||||
|
||||
dest = convert_to_ascii (dest, 'u', (extended_memory + 0x400));
|
||||
*(dest++) = 'K';
|
||||
*dest++ = 'K';
|
||||
}
|
||||
|
||||
*dest = 0;
|
||||
|
@ -419,8 +429,8 @@ load_image (char *kernel, char *arg, kernel_t suggested_type,
|
|||
/* offset into file */
|
||||
grub_seek (data_len + SECTOR_SIZE);
|
||||
|
||||
cur_addr = LINUX_STAGING_AREA + text_len;
|
||||
grub_read ((char *) LINUX_STAGING_AREA, text_len);
|
||||
cur_addr = (int) linux_data_tmp_addr + LINUX_SETUP_MOVE_SIZE;
|
||||
grub_read ((char *) LINUX_BZIMAGE_ADDR, text_len);
|
||||
|
||||
if (errnum == ERR_NONE)
|
||||
{
|
||||
|
@ -440,11 +450,7 @@ load_image (char *kernel, char *arg, kernel_t suggested_type,
|
|||
|
||||
return big_linux ? KERNEL_TYPE_BIG_LINUX : KERNEL_TYPE_LINUX;
|
||||
}
|
||||
|
||||
grub_close ();
|
||||
}
|
||||
else
|
||||
errnum = ERR_WONT_FIT;
|
||||
}
|
||||
else /* no recognizable format */
|
||||
errnum = ERR_EXEC_FORMAT;
|
||||
|
@ -780,7 +786,8 @@ load_initrd (char *initrd)
|
|||
{
|
||||
int len;
|
||||
unsigned long moveto;
|
||||
struct linux_kernel_header *lh;
|
||||
struct linux_kernel_header *lh
|
||||
= (struct linux_kernel_header *) (cur_addr - LINUX_SETUP_MOVE_SIZE);
|
||||
|
||||
#ifndef NO_DECOMPRESSION
|
||||
no_decompression = 1;
|
||||
|
@ -815,7 +822,6 @@ load_initrd (char *initrd)
|
|||
printf (" [Linux-initrd @ 0x%x, 0x%x bytes]\n", moveto, len);
|
||||
|
||||
/* FIXME: Should check if the kernel supports INITRD. */
|
||||
lh = (struct linux_kernel_header *) LINUX_SETUP;
|
||||
lh->ramdisk_image = RAW_ADDR (moveto);
|
||||
lh->ramdisk_size = len;
|
||||
|
||||
|
|
|
@ -138,17 +138,14 @@ extern char *grub_scratch_mem;
|
|||
#define LINUX_DEFAULT_SETUP_SECTS 4
|
||||
#define LINUX_FLAG_CAN_USE_HEAP 0x80
|
||||
#define LINUX_INITRD_MAX_ADDRESS 0x38000000
|
||||
#define LINUX_MAX_SETUP_SECTS 63
|
||||
#define LINUX_MAX_SETUP_SECTS 64
|
||||
#define LINUX_BOOT_LOADER_TYPE 0x71
|
||||
#define LINUX_HEAP_END_OFFSET (0x7F00 - 0x200)
|
||||
#define LINUX_HEAP_END_OFFSET (0x9000 - 0x200)
|
||||
|
||||
#define LINUX_STAGING_AREA RAW_ADDR (0x100000)
|
||||
#define LINUX_SETUP RAW_ADDR (0x90000)
|
||||
#define LINUX_KERNEL RAW_ADDR (0x10000)
|
||||
#define LINUX_KERNEL_MAXLEN 0x7F000
|
||||
#define LINUX_SETUP_SEG 0x9020
|
||||
#define LINUX_INIT_SEG 0x9000
|
||||
#define LINUX_SETUP_STACK 0x7F00
|
||||
#define LINUX_BZIMAGE_ADDR RAW_ADDR (0x100000)
|
||||
#define LINUX_ZIMAGE_ADDR RAW_ADDR (0x10000)
|
||||
#define LINUX_OLD_REAL_MODE_ADDR RAW_ADDR (0x90000)
|
||||
#define LINUX_SETUP_STACK 0x9000
|
||||
|
||||
#define LINUX_FLAG_BIG_KERNEL 0x1
|
||||
|
||||
|
@ -157,10 +154,10 @@ extern char *grub_scratch_mem;
|
|||
#define LINUX_VID_MODE_EXTENDED 0xFFFE
|
||||
#define LINUX_VID_MODE_ASK 0xFFFD
|
||||
|
||||
#define CL_MY_LOCATION RAW_ADDR (0x97F00)
|
||||
#define CL_MY_END_ADDR RAW_ADDR (0x97FFF)
|
||||
#define CL_MAGIC 0xA33F
|
||||
#define CL_BASE_ADDR RAW_ADDR (0x90000)
|
||||
#define LINUX_CL_OFFSET 0x9000
|
||||
#define LINUX_CL_END_OFFSET 0x90FF
|
||||
#define LINUX_SETUP_MOVE_SIZE 0x9100
|
||||
#define LINUX_CL_MAGIC 0xA33F
|
||||
|
||||
/*
|
||||
* General disk stuff
|
||||
|
@ -376,7 +373,7 @@ extern char *grub_scratch_mem;
|
|||
#include "mb_header.h"
|
||||
#include "mb_info.h"
|
||||
|
||||
/* For the Linux/i386 boot protocol version 2.02. */
|
||||
/* For the Linux/i386 boot protocol version 2.03. */
|
||||
struct linux_kernel_header
|
||||
{
|
||||
char code1[0x0020];
|
||||
|
@ -405,7 +402,7 @@ struct linux_kernel_header
|
|||
unsigned long bootsect_kludge; /* obsolete */
|
||||
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 */
|
||||
char *cmd_line_ptr; /* Points to the kernel command line */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Memory map address range descriptor used by GET_MMAP_ENTRY. */
|
||||
|
@ -550,6 +547,8 @@ extern unsigned char force_lba;
|
|||
extern char version_string[];
|
||||
extern char config_file[];
|
||||
extern unsigned long linux_text_len;
|
||||
extern char *linux_data_tmp_addr;
|
||||
extern char *linux_data_real_addr;
|
||||
|
||||
#ifdef GRUB_UTIL
|
||||
/* If not using config file, this variable is set to zero,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue