comply with the linux/i386 boot protocol version 2.02.
This commit is contained in:
parent
a4a19300f1
commit
c786d8603e
5 changed files with 166 additions and 54 deletions
40
ChangeLog
40
ChangeLog
|
@ -1,3 +1,43 @@
|
|||
2000-07-24 OKUJI Yoshinori <okuji@gnu.org>
|
||||
|
||||
Comply with the Linux/i386 boot protocol version 2.02.
|
||||
|
||||
* stage2/asm.S [!STAGE1_5] (linux_boot): Set the length of moved
|
||||
bytes to LINUX_KERNEL_MAXLEN instead of
|
||||
LINUX_KERNEL_LEN_OFFSET(%eax), since the field is obsolete.
|
||||
[!STAGE1_5] (big_linux_boot): Don't use SEGMENT or OFFSET.
|
||||
Instead, embed the segment and the offset in the code itself.
|
||||
Set %ds, %es, %fs and %gs to %ax (LINUX_INIT_SEG).
|
||||
* stage2/boot.c (load_image): Rewrite the Linux support code
|
||||
heavily. Use a structure instead of a batch of macros, to access
|
||||
a Linux kernel header.
|
||||
(load_initrd): If MOVETO plus LEN is greater than or equal to
|
||||
LINUX_INITRD_MAX_ADDRESS, set MOVETO to LINUX_INITRD_MAX_ADDRESS
|
||||
minus LEN with page aligned.
|
||||
* stage2/shared.h (LINUX_MAGIC_SIGNATURE): New macro.
|
||||
(LINUX_DEFAULT_SETUP_SECTS): Likewise.
|
||||
(LINUX_FLAG_CAN_USE_HEAP): Likewise.
|
||||
(LINUX_INITRD_MAX_ADDRESS): Likewise.
|
||||
(LINUX_MAX_SETUP_SECTS): Likewise.
|
||||
(LINUX_BOOT_LOADER_TYPE): Likewise.
|
||||
(LINUX_HEAP_END_OFFSET): Likewise.
|
||||
(LINUX_SETUP_MAXLEN): Removed.
|
||||
(LINUX_KERNEL_LEN_OFFSET): Likewise.
|
||||
(LINUX_SETUP_LEN_OFFSET): Likewise.
|
||||
(LINUX_SETUP_STACK): Set to 0x7F00 instead of 0x3FF4 (why was it
|
||||
this value?).
|
||||
(LINUX_SETUP_LOADER): Removed.
|
||||
(LINUX_SETUP_LOAD_FLAGS): Likewise.
|
||||
(LINUX_SETUP_CODE_START): Likewise.
|
||||
(LINUX_SETUP_INITRD): Likewise.
|
||||
(CL_MY_LOCATION): Set to RAW_ADDR(0x97F00) instead of
|
||||
RAW_ADDR(0x92000).
|
||||
(CL_MY_END_ADDR): Set to RAW_addr(0x97FFF) instead of
|
||||
RAW_ADDR(0x920FF).
|
||||
(CL_MAGIC_ADDR): Removed.
|
||||
(CL_OFFSET): Likewise.
|
||||
[!ASM_FILE] (struct linux_kernel_header): New structure tag.
|
||||
|
||||
2000-07-23 OKUJI Yoshinori <okuji@gnu.org>
|
||||
|
||||
* docs/tutorial.texi: Fix some syntax errors and ambiguous
|
||||
|
|
1
NEWS
1
NEWS
|
@ -6,6 +6,7 @@ New in 0.5.96 - XXXX-XX-XX:
|
|||
with this command.
|
||||
* You can specify `--no-mem-option' to the command "kernel", if you want
|
||||
GRUB not to pass a Linux's mem option automatically.
|
||||
* Now GRUB is compliant with the Linux/i386 boot protocol version 2.02.
|
||||
|
||||
New in 0.5.95 - 2000-06-27:
|
||||
* NetBSD ELF kernel support is added. You have to specify the new option
|
||||
|
|
22
stage2/asm.S
22
stage2/asm.S
|
@ -1695,7 +1695,8 @@ ENTRY(linux_boot)
|
|||
|
||||
/* copy kernel */
|
||||
movl $LINUX_SETUP, %eax
|
||||
movl LINUX_KERNEL_LEN_OFFSET(%eax), %ecx
|
||||
/* XXX: Too many bytes, but there is no bad effect */
|
||||
movl $LINUX_KERNEL_MAXLEN, %ecx
|
||||
shll $2, %ecx
|
||||
movl $LINUX_STAGING_AREA, %esi
|
||||
movl $LINUX_KERNEL, %edi
|
||||
|
@ -1710,12 +1711,6 @@ ENTRY(big_linux_boot)
|
|||
|
||||
/* final setup for linux boot */
|
||||
|
||||
movw $LINUX_SETUP_SEG, %ax
|
||||
movw %ax, segment
|
||||
|
||||
xorl %eax, %eax
|
||||
movl %eax, offset
|
||||
|
||||
call EXT_C(prot_to_real)
|
||||
.code16
|
||||
|
||||
|
@ -1724,13 +1719,16 @@ ENTRY(big_linux_boot)
|
|||
|
||||
movw $LINUX_INIT_SEG, %ax
|
||||
movw %ax, %ss
|
||||
movw %ax, %ds
|
||||
movw %ax, %es
|
||||
movw %ax, %fs
|
||||
movw %ax, %gs
|
||||
|
||||
/* jump to start */
|
||||
#ifdef ABSOLUTE_WITHOUT_ASTERISK
|
||||
DATA32 ADDR32 ljmp (offset)
|
||||
#else
|
||||
DATA32 ADDR32 ljmp *(offset)
|
||||
#endif
|
||||
/* ljmp */
|
||||
.byte 0xea
|
||||
.word LINUX_SETUP_SEG
|
||||
.word 0
|
||||
.code32
|
||||
|
||||
|
||||
|
|
102
stage2/boot.c
102
stage2/boot.c
|
@ -45,6 +45,7 @@ load_image (char *kernel, char *arg, kernel_t suggested_type,
|
|||
kernel_t type = KERNEL_TYPE_NONE;
|
||||
unsigned long flags = 0, text_len = 0, data_len = 0, bss_len = 0;
|
||||
char *str = 0, *str2 = 0;
|
||||
struct linux_kernel_header *lh;
|
||||
union
|
||||
{
|
||||
struct multiboot_header *mb;
|
||||
|
@ -90,6 +91,10 @@ load_image (char *kernel, char *arg, kernel_t suggested_type,
|
|||
}
|
||||
}
|
||||
|
||||
/* Use BUFFER as a linux kernel header, if the image is Linux zImage
|
||||
or bzImage. */
|
||||
lh = (struct linux_kernel_header *) buffer;
|
||||
|
||||
/* ELF loading supported if multiboot, FreeBSD and NetBSD. */
|
||||
if ((type == KERNEL_TYPE_MULTIBOOT
|
||||
|| grub_strcmp (pu.elf->e_ident + EI_BRAND, "FreeBSD") == 0
|
||||
|
@ -200,31 +205,63 @@ load_image (char *kernel, char *arg, kernel_t suggested_type,
|
|||
exec_type = 1;
|
||||
str = "a.out";
|
||||
}
|
||||
else if ((*((unsigned short *) (buffer + BOOTSEC_SIG_OFFSET))
|
||||
== BOOTSEC_SIGNATURE)
|
||||
&& ((data_len
|
||||
= (((long) *((unsigned char *)
|
||||
(buffer + LINUX_SETUP_LEN_OFFSET))) << 9))
|
||||
<= LINUX_SETUP_MAXLEN)
|
||||
&& ((text_len
|
||||
= (((long) *((unsigned long *)
|
||||
(buffer + LINUX_KERNEL_LEN_OFFSET))) << 4)),
|
||||
(data_len + text_len + SECTOR_SIZE) <= ((filemax + 15) & 0xFFFFFFF0)))
|
||||
else if (lh->boot_flag == BOOTSEC_SIGNATURE
|
||||
&& lh->setup_sects <= LINUX_MAX_SETUP_SECTS)
|
||||
{
|
||||
int big_linux = buffer[LINUX_SETUP_LOAD_FLAGS] & LINUX_FLAG_BIG_KERNEL;
|
||||
buffer[LINUX_SETUP_LOADER] = 0x70;
|
||||
int big_linux = 0;
|
||||
int setup_sects = lh->setup_sects;
|
||||
|
||||
if (lh->header == LINUX_MAGIC_SIGNATURE && lh->version >= 0x0200)
|
||||
{
|
||||
big_linux = (lh->loadflags & LINUX_FLAG_BIG_KERNEL);
|
||||
lh->type_of_loader = LINUX_BOOT_LOADER_TYPE;
|
||||
|
||||
if (lh->version >= 0x0201)
|
||||
{
|
||||
lh->heap_end_ptr = LINUX_HEAP_END_OFFSET;
|
||||
lh->loadflags |= LINUX_FLAG_CAN_USE_HEAP;
|
||||
}
|
||||
|
||||
if (lh->version >= 0x0202)
|
||||
lh->cmd_line_ptr = CL_MY_LOCATION;
|
||||
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);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Your kernel is quite old... */
|
||||
lh->cl_magic = CL_MAGIC;
|
||||
lh->cl_offset = CL_MY_LOCATION - CL_BASE_ADDR;
|
||||
|
||||
setup_sects = LINUX_DEFAULT_SETUP_SECTS;
|
||||
}
|
||||
|
||||
/* If SETUP_SECTS is not set, set it to the default (4). */
|
||||
if (! setup_sects)
|
||||
setup_sects = LINUX_DEFAULT_SETUP_SECTS;
|
||||
|
||||
data_len = setup_sects << 9;
|
||||
text_len = filemax - data_len - SECTOR_SIZE;
|
||||
|
||||
if (! big_linux && text_len > LINUX_KERNEL_MAXLEN)
|
||||
{
|
||||
printf (" linux 'zImage' kernel too big, try 'make bzImage'\n");
|
||||
grub_printf (" linux 'zImage' kernel too big, try 'make bzImage'\n");
|
||||
grub_close ();
|
||||
errnum = ERR_WONT_FIT;
|
||||
return KERNEL_TYPE_NONE;
|
||||
}
|
||||
|
||||
printf (" [Linux-%s, setup=0x%x, size=0x%x]\n",
|
||||
(big_linux ? "bzImage" : "zImage"), data_len, text_len);
|
||||
grub_printf (" [Linux-%s, setup=0x%x, size=0x%x]\n",
|
||||
(big_linux ? "bzImage" : "zImage"), data_len, text_len);
|
||||
|
||||
if (mbi.mem_lower >= 608)
|
||||
/* 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 shit! */
|
||||
{
|
||||
|
@ -254,24 +291,24 @@ load_image (char *kernel, char *arg, kernel_t suggested_type,
|
|||
return KERNEL_TYPE_NONE;
|
||||
}
|
||||
|
||||
/* Set the vid mode to VID_MODE. Note that this can work
|
||||
because i386 architecture is little-endian. */
|
||||
grub_memmove (buffer + LINUX_VID_MODE_OFFSET,
|
||||
(char *) &vid_mode,
|
||||
sizeof (unsigned short));
|
||||
lh->vid_mode = vid_mode;
|
||||
}
|
||||
}
|
||||
|
||||
memmove ((char *) LINUX_SETUP, buffer, data_len + SECTOR_SIZE);
|
||||
|
||||
if (lh->header != LINUX_MAGIC_SIGNATURE ||
|
||||
lh->version < 0x0200)
|
||||
/* Clear the heap space. */
|
||||
grub_memset ((char *) LINUX_SETUP + ((setup_sects - 1) << 9),
|
||||
0,
|
||||
(64 - setup_sects - 1) << 9);
|
||||
|
||||
/* copy command-line plus memory hack to staging area */
|
||||
{
|
||||
char *src = arg;
|
||||
char *dest = (char *) CL_MY_LOCATION;
|
||||
|
||||
*((unsigned short *) CL_OFFSET) = CL_MY_LOCATION - CL_BASE_ADDR;
|
||||
*((unsigned short *) CL_MAGIC_ADDR) = CL_MAGIC;
|
||||
|
||||
/* Add a mem option automatically only if the user doesn't
|
||||
specify it explicitly. */
|
||||
if (! grub_strstr (src, "mem=")
|
||||
|
@ -563,8 +600,9 @@ int
|
|||
load_initrd (char *initrd)
|
||||
{
|
||||
int len;
|
||||
unsigned long *ramdisk, moveto;
|
||||
|
||||
unsigned long moveto;
|
||||
struct linux_kernel_header *lh;
|
||||
|
||||
if (! grub_open (initrd))
|
||||
return 0;
|
||||
|
||||
|
@ -575,7 +613,10 @@ load_initrd (char *initrd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
moveto = ((mbi.mem_upper + 0x400) * 0x400 - len) & 0x3ffff000;
|
||||
moveto = ((mbi.mem_upper + 0x400) * 0x400 - len) & 0xfffff000;
|
||||
if (moveto + len >= LINUX_INITRD_MAX_ADDRESS)
|
||||
moveto = (LINUX_INITRD_MAX_ADDRESS - len) & 0xfffff000;
|
||||
|
||||
/* XXX: Linux 2.3.xx has a bug in the memory range check, so avoid
|
||||
the last page. */
|
||||
moveto -= 0x1000;
|
||||
|
@ -583,9 +624,10 @@ load_initrd (char *initrd)
|
|||
|
||||
printf (" [Linux-initrd @ 0x%x, 0x%x bytes]\n", moveto, len);
|
||||
|
||||
ramdisk = (unsigned long *) (LINUX_SETUP + LINUX_SETUP_INITRD);
|
||||
ramdisk[0] = RAW_ADDR (moveto);
|
||||
ramdisk[1] = 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;
|
||||
|
||||
grub_close ();
|
||||
return 1;
|
||||
|
|
|
@ -135,22 +135,23 @@ extern char *grub_scratch_mem;
|
|||
* Linux setup parameters
|
||||
*/
|
||||
|
||||
#define LINUX_MAGIC_SIGNATURE 0x53726448 /* "HdrS" */
|
||||
#define LINUX_DEFAULT_SETUP_SECTS 4
|
||||
#define LINUX_FLAG_CAN_USE_HEAP 0x80
|
||||
#define LINUX_INITRD_MAX_ADDRESS 0x3C000000
|
||||
#define LINUX_MAX_SETUP_SECTS 63
|
||||
#define LINUX_BOOT_LOADER_TYPE 0x71
|
||||
#define LINUX_HEAP_END_OFFSET (0x7F00 - 0x200)
|
||||
|
||||
#define LINUX_STAGING_AREA RAW_ADDR (0x100000)
|
||||
#define LINUX_SETUP RAW_ADDR (0x90000)
|
||||
#define LINUX_SETUP_MAXLEN 0x1E00
|
||||
#define LINUX_KERNEL RAW_ADDR (0x10000)
|
||||
#define LINUX_KERNEL_MAXLEN 0x7F000
|
||||
#define LINUX_SETUP_SEG 0x9020
|
||||
#define LINUX_INIT_SEG 0x9000
|
||||
#define LINUX_KERNEL_LEN_OFFSET 0x1F4
|
||||
#define LINUX_SETUP_LEN_OFFSET 0x1F1
|
||||
#define LINUX_SETUP_STACK 0x3FF4
|
||||
#define LINUX_SETUP_STACK 0x7F00
|
||||
|
||||
#define LINUX_SETUP_LOADER 0x210
|
||||
#define LINUX_SETUP_LOAD_FLAGS 0x211
|
||||
#define LINUX_FLAG_BIG_KERNEL 0x1
|
||||
#define LINUX_SETUP_CODE_START 0x214
|
||||
#define LINUX_SETUP_INITRD 0x218
|
||||
|
||||
/* Linux's video mode selection support. Actually I hate it! */
|
||||
#define LINUX_VID_MODE_OFFSET 0x1FA
|
||||
|
@ -158,12 +159,10 @@ extern char *grub_scratch_mem;
|
|||
#define LINUX_VID_MODE_EXTENDED 0xFFFE
|
||||
#define LINUX_VID_MODE_ASK 0xFFFD
|
||||
|
||||
#define CL_MY_LOCATION RAW_ADDR (0x92000)
|
||||
#define CL_MY_END_ADDR RAW_ADDR (0x920FF)
|
||||
#define CL_MAGIC_ADDR RAW_ADDR (0x90020)
|
||||
#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 CL_OFFSET RAW_ADDR (0x90022)
|
||||
|
||||
/*
|
||||
* General disk stuff
|
||||
|
@ -370,6 +369,38 @@ extern char *grub_scratch_mem;
|
|||
#include "mb_header.h"
|
||||
#include "mb_info.h"
|
||||
|
||||
/* For the Linux/i386 boot protocol version 2.02. */
|
||||
struct linux_kernel_header
|
||||
{
|
||||
char code1[0x0020];
|
||||
unsigned short cl_magic; /* Magic number 0xA33F */
|
||||
unsigned short cl_offset; /* The offset of command line */
|
||||
char code2[0x01F1 - 0x0020 - 2 - 2];
|
||||
unsigned char setup_sects; /* The size of the setup in sectors */
|
||||
unsigned short root_flags; /* If the root is mounted readonly */
|
||||
unsigned short syssize; /* obsolete */
|
||||
unsigned short swap_dev; /* obsolete */
|
||||
unsigned short ram_size; /* obsolete */
|
||||
unsigned short vid_mode; /* Video mode control */
|
||||
unsigned short root_dev; /* Default root device number */
|
||||
unsigned short boot_flag; /* 0xAA55 magic number */
|
||||
unsigned short jump; /* Jump instruction */
|
||||
unsigned long header; /* Magic signature "HdrS" */
|
||||
unsigned short version; /* Boot protocol version supported */
|
||||
unsigned long realmode_swtch; /* Boot loader hook */
|
||||
unsigned long start_sys; /* Points to kernel version string */
|
||||
unsigned char type_of_loader; /* Boot loader identifier */
|
||||
unsigned char loadflags; /* Boot protocol option flags */
|
||||
unsigned short setup_move_size; /* Move to high memory size */
|
||||
unsigned long code32_start; /* Boot loader hook */
|
||||
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 pad1; /* Unused */
|
||||
unsigned long cmd_line_ptr; /* Points to the kernel command line */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Memory map address range descriptor used by GET_MMAP_ENTRY. */
|
||||
struct mmar_desc
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue