diff --git a/ChangeLog b/ChangeLog index 1f6606e98..c62675dae 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,39 @@ +2000-04-03 OKUJI Yoshinori + + Add a dirty hack into the kernel loader so that the user can + force GRUB to load NetBSD ELF kernels. The support code is + mostly stolen from a patch by Pavel Roskin. + + * stage2/boot.c (load_image): Added an optional argument + SUGGESTED_TYPE. + If BUFFER is a bootable ELF image and SUGGESTED_TYPE is + KERNEL_TYPE_NETBSD, then load it as an ELF image and set STR2 to + "NetBSD" and TYPE to SUGGESTED_TYPE. + If the image is a Linux kernel and SUGGESTED_TYPE is not + KERNEL_TYPE_NONE, make sure that SUGGESTED_TYPE matches up to + the Linux kernel type. + If TYPE is KERNEL_TYPE_NETBSD, set MEMADDR to + RAW_ADDR (phdr->paddr & 0xFFFFFF) like FreeBSD. + If SUGGESTED_TYPE is not KERNEL_TYPE_NONE, make sure that + SUGGESTED_TYPE is equal to TYPE. + (bsd_boot): If TYPE is not KERNEL_TYPE_FREEBSD (i.e. NetBSD or + OpenBSD) and the bit MB_INFO_AOUT_SYMS is set, set END_MARK to + MBI.SYMS.A.ADDR + 4 + MBI.SYMS.A.TABSIZE + MBI.SYMS.A.STRSIZE. + If the bit is clear, set END_MARK to 0. + Pass END_MARK to *ENTRY_ADDR instead of directly calculating the + end of symbols. + * stage2/shared.h (load_image): Added the argument + SUGGESTED_TYPE to the prototype. + * stage2/builtins.c (kernel_func): Added a new option, + `--type=TYPE'. Check if ARG is started with "--type=". + If so, set SUGGESTED_TYPE to KERNEL_TYPE_NETBSD, + KERNEL_TYPE_FREEBSD, KERNEL_TYPE_NETBSD, KERNEL_TYPE_LINUX, + KERNEL_TYPE_BIG_LINUX, KERNEL_TYPE_MULTIBOOT if ARG is "netbsd", + "freebsd", "openbsd", "linux", "biglinux", "multiboot", + respectively. Otherwise, set ERRNUM to ERR_BAD_ARGUMENT and + return 1. Set KERNEL_ARG to a string after the option. + (builtin_kernel): Added a description about the new option. + 2000-04-03 OKUJI Yoshinori * stage2/stage2.c (run_menu) [GRUB_UTIL]: Removed a nested diff --git a/NEWS b/NEWS index 24015241a..c6d3a2796 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,15 @@ NEWS - list of user-visible changes between releases of GRUB +New in 0.5.95 - XXXX-XX-XX: +* NetBSD ELF kernel support is added. You have to specify the new option + to the command "kernel". See below. +* Added a new option `--type=TYPE' into the command "kernel". This + option suggests what type of kernel you want to load. TYPE must be + either of "netbsd", "freebsd", "openbsd", "linux", "biglinux" and + "multiboot". Actually, this option will be necessary only if you want + to load a NetBSD ELF kernel, because GRUB can automatically determine + a kernel type in the other cases. + New in 0.5.94 - 2000-03-06: * Stage 1 supports both the LBA mode and the CHS mode. * The NetBSD and OpenBSD boot bug is fixed. diff --git a/stage2/boot.c b/stage2/boot.c index 97147bf7e..6b5dba1ae 100644 --- a/stage2/boot.c +++ b/stage2/boot.c @@ -38,7 +38,7 @@ static struct mod_list mll[99]; */ kernel_t -load_image (char *kernel, char *arg) +load_image (char *kernel, char *arg, kernel_t suggested_type) { int len, i, exec_type = 0, align_4k = 1; kernel_t type = KERNEL_TYPE_NONE; @@ -89,9 +89,10 @@ load_image (char *kernel, char *arg) } } - /* ELF loading supported if multiboot and FreeBSD. */ + /* ELF loading supported if multiboot, FreeBSD and NetBSD. */ if ((type == KERNEL_TYPE_MULTIBOOT - || grub_strcmp (pu.elf->e_ident + EI_BRAND, "FreeBSD") == 0) + || grub_strcmp (pu.elf->e_ident + EI_BRAND, "FreeBSD") == 0 + || suggested_type == KERNEL_TYPE_NETBSD) && len > sizeof (Elf32_Ehdr) && BOOTABLE_I386_ELF ((*((Elf32_Ehdr *) buffer)))) { @@ -113,8 +114,18 @@ load_image (char *kernel, char *arg) if (type == KERNEL_TYPE_NONE) { - str2 = "FreeBSD"; - type = KERNEL_TYPE_FREEBSD; + /* At the moment, there is no way to identify a NetBSD ELF + kernel, so rely on the suggested type by the user. */ + if (suggested_type == KERNEL_TYPE_NETBSD) + { + str2 = "NetBSD"; + type = suggested_type; + } + else + { + str2 = "FreeBSD"; + type = KERNEL_TYPE_FREEBSD; + } } } else if (flags & MULTIBOOT_AOUT_KLUDGE) @@ -287,6 +298,16 @@ load_image (char *kernel, char *arg) >= (text_len - 16)) { grub_close (); + + /* Sanity check. */ + if (suggested_type != KERNEL_TYPE_NONE + && ((big_linux && suggested_type != KERNEL_TYPE_BIG_LINUX) + || (! big_linux && suggested_type != KERNEL_TYPE_LINUX))) + { + errnum = ERR_EXEC_FORMAT; + return KERNEL_TYPE_NONE; + } + return big_linux ? KERNEL_TYPE_BIG_LINUX : KERNEL_TYPE_LINUX; } else if (!errnum) @@ -436,7 +457,7 @@ load_image (char *kernel, char *arg) grub_seek (phdr->p_offset); filesiz = phdr->p_filesz; - if (type == KERNEL_TYPE_FREEBSD) + if (type == KERNEL_TYPE_FREEBSD || type == KERNEL_TYPE_NETBSD) memaddr = RAW_ADDR (phdr->p_paddr & 0xFFFFFF); else memaddr = RAW_ADDR (phdr->p_paddr); @@ -487,6 +508,14 @@ load_image (char *kernel, char *arg) } grub_close (); + + /* Sanity check. */ + if (suggested_type != KERNEL_TYPE_NONE && suggested_type != type) + { + errnum = ERR_EXEC_FORMAT; + return KERNEL_TYPE_NONE; + } + return type; } @@ -702,9 +731,16 @@ bsd_boot (kernel_t type, int bootdev, char *arg) */ /* call entry point */ - (*entry_addr) (clval, bootdev, 0, - (mbi.syms.a.addr + 4 - + mbi.syms.a.tabsize + mbi.syms.a.strsize), + unsigned long end_mark; + + if (mbi.flags & MB_INFO_AOUT_SYMS) + end_mark = (mbi.syms.a.addr + 4 + + mbi.syms.a.tabsize + mbi.syms.a.strsize); + else + /* FIXME: it should be mbi.syms.e.size. */ + end_mark = 0; + + (*entry_addr) (clval, bootdev, 0, end_mark, mbi.mem_upper, mbi.mem_lower); } } diff --git a/stage2/builtins.c b/stage2/builtins.c index 9d2ed9fc6..0bd3b758e 100644 --- a/stage2/builtins.c +++ b/stage2/builtins.c @@ -1826,7 +1826,40 @@ static struct builtin builtin_ioprobe = static int kernel_func (char *arg, int flags) { - int len = grub_strlen (arg); + int len; + char *kernel_arg = arg; + kernel_t suggested_type = KERNEL_TYPE_NONE; + + /* If the option `--type=TYPE' is specified, convert the string to + a kernel type. */ + if (grub_memcmp (arg, "--type=") == 0) + { + arg += 7; + + if (grub_memcmp (arg, "netbsd") == 0) + suggested_type = KERNEL_TYPE_NETBSD; + else if (grub_memcmp (arg, "freebsd") == 0) + suggested_type = KERNEL_TYPE_FREEBSD; + else if (grub_memcmp (arg, "openbsd") == 0) + /* XXX: For now, OpenBSD is identical to NetBSD, from GRUB's + point of view. */ + suggested_type = KERNEL_TYPE_NETBSD; + else if (grub_memcmp (arg, "linux") == 0) + suggested_type = KERNEL_TYPE_LINUX; + else if (grub_memcmp (arg, "biglinux") == 0) + suggested_type = KERNEL_TYPE_BIG_LINUX; + else if (grub_memcmp (arg, "multiboot") == 0) + suggested_type = KERNEL_TYPE_MULTIBOOT; + else + { + errnum = ERR_BAD_ARGUMENT; + return 1; + } + + kernel_arg = skip_to (0, arg); + } + + len = grub_strlen (kernel_arg); /* Reset MB_CMDLINE. */ mb_cmdline = (char *) MB_CMDLINE_BUF; @@ -1837,8 +1870,8 @@ kernel_func (char *arg, int flags) } /* Copy the command-line to MB_CMDLINE. */ - grub_memmove (mb_cmdline, arg, len + 1); - kernel_type = load_image (arg, mb_cmdline); + grub_memmove (mb_cmdline, kernel_arg, len + 1); + kernel_type = load_image (kernel_arg, mb_cmdline, suggested_type); if (kernel_type == KERNEL_TYPE_NONE) return 1; @@ -1851,11 +1884,13 @@ static struct builtin builtin_kernel = "kernel", kernel_func, BUILTIN_CMDLINE, - "kernel FILE [ARG ...]", - "Attempt to load the primary boot image from" - " FILE. The rest of the line is passed verbatim as the" - " \"kernel command line\". Any modules must be reloaded after" - " using this command." + "kernel [--type=TYPE] FILE [ARG ...]", + "Attempt to load the primary boot image from FILE. The rest of the" + "line is passed verbatim as the \"kernel command line\". Any modules" + " must be reloaded after using this command. The option --type is used" + " to suggest what type of kernel to be loaded. TYPE must be either of" + " \"netbsd\", \"freebsd\", \"openbsd\", \"linux\", \"biglinux\" and" + " \"multiboot\"." }; diff --git a/stage2/shared.h b/stage2/shared.h index f93d3ac5d..e5b3dcaaa 100644 --- a/stage2/shared.h +++ b/stage2/shared.h @@ -781,7 +781,7 @@ void copy_current_part_entry (char *buf); #ifndef STAGE1_5 void bsd_boot (kernel_t type, int bootdev, char *arg) __attribute__ ((noreturn)); -kernel_t load_image (char *kernel, char *arg); +kernel_t load_image (char *kernel, char *arg, kernel_t suggested_type); int load_module (char *module, char *arg); int load_initrd (char *initrd); #endif