diff options
author | Pav Lucistnik <pav@FreeBSD.org> | 2004-06-06 13:31:35 +0000 |
---|---|---|
committer | Pav Lucistnik <pav@FreeBSD.org> | 2004-06-06 13:31:35 +0000 |
commit | bf04ac81d5fc4704ddf6a5080032b91512160e77 (patch) | |
tree | 9adae1ce75f20bcbeacbc750056864b5885e8d5d /sysutils/grub | |
parent | Update to 2.6 (diff) |
- Fix a few non-critical bugs in ufs2 patch
PR: ports/65933
Submitted by: Sergey Matveychuk <sem@ciam.ru> (maintainer)
Obtained from: grub CVS
Notes
Notes:
svn path=/head/; revision=110945
Diffstat (limited to 'sysutils/grub')
-rw-r--r-- | sysutils/grub/Makefile | 2 | ||||
-rw-r--r-- | sysutils/grub/files/patch-lib_device.c | 4 | ||||
-rw-r--r-- | sysutils/grub/files/patch-ufs2 | 8817 |
3 files changed, 134 insertions, 8689 deletions
diff --git a/sysutils/grub/Makefile b/sysutils/grub/Makefile index facc3cd1ec6e..1e0895041f18 100644 --- a/sysutils/grub/Makefile +++ b/sysutils/grub/Makefile @@ -7,7 +7,7 @@ PORTNAME= grub PORTVERSION= 0.94 -PORTREVISION= 3 +PORTREVISION= 4 CATEGORIES= sysutils MASTER_SITES= ftp://alpha.gnu.org/gnu/grub/ diff --git a/sysutils/grub/files/patch-lib_device.c b/sysutils/grub/files/patch-lib_device.c index ac44ee3ea91f..d0b3dd951c3e 100644 --- a/sysutils/grub/files/patch-lib_device.c +++ b/sysutils/grub/files/patch-lib_device.c @@ -1,5 +1,5 @@ --- lib/device.c.orig Sat Jan 17 18:57:57 2004 -+++ lib/device.c Sat Jan 31 06:32:24 2004 ++++ lib/device.c Mon Mar 1 06:36:39 2004 @@ -78,6 +78,12 @@ # include <sys/ioctl.h> /* ioctl */ # include <sys/disklabel.h> @@ -36,7 +36,7 @@ /* FreeBSD, NetBSD or OpenBSD */ { struct disklabel hdg; -+#if __FreeBSD_version < 500040 ++#if !defined(__FreeBSD__) || __FreeBSD_version < 500040 if (ioctl (fd, DIOCGDINFO, &hdg)) goto fail; diff --git a/sysutils/grub/files/patch-ufs2 b/sysutils/grub/files/patch-ufs2 index fcf637cabeef..cb1f18aa1b9c 100644 --- a/sysutils/grub/files/patch-ufs2 +++ b/sysutils/grub/files/patch-ufs2 @@ -1,6 +1,6 @@ -diff -ruN grub-0.94.orig/configure.ac configure.ac ---- grub-0.94.orig/configure.ac Wed Feb 11 00:22:12 2004 -+++ configure.ac Wed Feb 11 00:22:29 2004 +diff -ruN configure.ac.orig configure.ac +--- configure.ac.orig Sat Apr 24 20:49:07 2004 ++++ configure.ac Sat Apr 24 20:49:16 2004 @@ -227,6 +227,13 @@ FSYS_CFLAGS="$FSYS_CFLAGS -DFSYS_FFS=1" fi @@ -15,653 +15,9 @@ diff -ruN grub-0.94.orig/configure.ac configure.ac AC_ARG_ENABLE(minix, [ --disable-minix disable Minix fs support in Stage 2]) -diff -ruN grub-0.94.orig/configure.ac.orig configure.ac.orig ---- grub-0.94.orig/configure.ac.orig Thu Jan 1 03:00:00 1970 -+++ configure.ac.orig Sun Oct 19 21:25:30 2003 -@@ -0,0 +1,640 @@ -+dnl Configure script for GRUB. -+dnl Copyright 1999,2000,2001,2002,2003 Free Software Foundation, Inc. -+ -+dnl Permission to use, copy, modify and distribute this software and its -+dnl documentation is hereby granted, provided that both the copyright -+dnl notice and this permission notice appear in all copies of the -+dnl software, derivative works or modified versions, and any portions -+dnl thereof, and that both notices appear in supporting documentation. -+dnl -+dnl THE FREE SOFTWARE FOUNDATION ALLOWS FREE USE OF THIS SOFTWARE IN ITS -+dnl "AS IS" CONDITION. THE FREE SOFTWARE FOUNDATION DISCLAIMS ANY -+dnl LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE -+dnl USE OF THIS SOFTWARE. -+ -+AC_PREREQ(2.57) -+AC_INIT([GRUB], [0.94], [bug-grub@gnu.org]) -+AC_CONFIG_SRCDIR([stage2/stage2.c]) -+AC_CONFIG_HEADER([config.h]) -+AM_INIT_AUTOMAKE -+ -+AC_CANONICAL_HOST -+ -+case "$host_cpu" in -+i[[3456]]86) host_cpu=i386 ;; -+x86_64) host_cpu=x86_64 ;; -+*) AC_MSG_ERROR([unsupported CPU type]) ;; -+esac -+ -+AC_SUBST(host_cpu) -+AC_SUBST(host_vendor) -+ -+# -+# Options -+# -+ -+AM_MAINTAINER_MODE -+if test "x$enable_maintainer_mode" = xyes; then -+ AC_PATH_PROG(PERL,perl) -+ if test -z "$PERL"; then -+ AC_MSG_ERROR([perl not found]) -+ fi -+fi -+ -+# This should be checked before AC_PROG_CC -+if test "x$CFLAGS" = x; then -+ default_CFLAGS=yes -+fi -+ -+if test "x$host_cpu" = xx86_64; then -+ CFLAGS="-m32 $CFLAGS" -+fi -+ -+# -+# Programs -+# -+ -+AC_CHECK_TOOL(CC, gcc) -+AC_PROG_CC -+# We need this for older versions of Autoconf. -+_AM_DEPENDENCIES(CC) -+ -+dnl Because recent automake complains about AS, set it here. -+CCAS="$CC" -+AC_SUBST(CCAS) -+ -+AC_ARG_WITH(binutils, -+ [ --with-binutils=DIR search the directory DIR to find binutils]) -+ -+if test "x$with_binutils" != x; then -+dnl AC_PATH_TOOL is not seen in autoconf 2.13, so use AC_PATH_PROG -+dnl instead for now. It is preferable when you cross-compile GRUB. -+dnl AC_PATH_TOOL(RANLIB, ranlib, :, "$with_binutils:$PATH") -+ AC_PATH_PROG(RANLIB, ranlib, :, "$with_binutils:$PATH") -+else -+ AC_PROG_RANLIB -+fi -+ -+# optimization flags -+if test "x$ac_cv_prog_gcc" = xyes; then -+ if test "x$default_CFLAGS" = xyes; then -+ # Autoconf may set CFLAGS to -O2 and/or -g. So eliminate them. -+ CFLAGS="`echo $CFLAGS | sed -e 's/-g//g' -e 's/-O[[0-9]]//g'` -g" -+ # If the user specify the directory for binutils, add the option `-B'. -+ if test "x$with_binutils" != x; then -+ CFLAGS="-B$with_binutils/ $CFLAGS" -+ fi -+ STAGE1_CFLAGS="-O2" -+ GRUB_CFLAGS="-O2" -+ AC_CACHE_CHECK([whether optimization for size works], size_flag, [ -+ saved_CFLAGS=$CFLAGS -+ CFLAGS="-Os -g" -+ AC_TRY_COMPILE(, , size_flag=yes, size_flag=no) -+ CFLAGS=$saved_CFLAGS -+ ]) -+ if test "x$size_flag" = xyes; then -+ STAGE2_CFLAGS="-Os" -+ else -+ STAGE2_CFLAGS="-O2 -fno-strength-reduce -fno-unroll-loops" -+ fi -+ fi -+fi -+ -+AC_SUBST(STAGE1_CFLAGS) -+AC_SUBST(STAGE2_CFLAGS) -+AC_SUBST(GRUB_CFLAGS) -+ -+# Enforce coding standards. -+CPPFLAGS="$CPPFLAGS -Wall -Wmissing-prototypes -Wunused -Wshadow" -+CPPFLAGS="$CPPFLAGS -Wpointer-arith" -+ -+AC_CACHE_CHECK([whether -Wundef works], undef_flag, [ -+ saved_CPPFLAGS="$CPPFLAGS" -+ CPPFLAGS="-Wundef" -+ AC_TRY_COMPILE(, , undef_flag=yes, undef_flag=no) -+ CPPFLAGS="$saved_CPPFLAGS" -+]) -+ -+# The options `-falign-*' are supported by gcc 3.0 or later. -+# Probably it is sufficient to only check for -falign-loops. -+AC_CACHE_CHECK([whether -falign-loops works], [falign_loop_flag], [ -+ saved_CPPFLAGS="$CPPFLAGS" -+ CPPFLAGS="-falign-loops=1" -+ AC_TRY_COMPILE(, , [falign_loop_flag=yes], [falign_loop_flag=no]) -+ CPPFLAGS="$saved_CPPFLAGS" -+]) -+ -+# Force no alignment to save space. -+if test "x$falign_loop_flag" = xyes; then -+ CPPFLAGS="$CPPFLAGS -falign-jumps=1 -falign-loops=1 -falign-functions=1" -+else -+ CPPFLAGS="$CPPFLAGS -malign-jumps=1 -malign-loops=1 -malign-functions=1" -+fi -+ -+if test "x$undef_flag" = xyes; then -+ CPPFLAGS="$CPPFLAGS -Wundef" -+fi -+ -+if test "x$with_binutils" != x; then -+dnl AC_PATH_TOOL(OBJCOPY, objcopy, , "$with_binutils:$PATH") -+ AC_PATH_PROG(OBJCOPY, objcopy, , "$with_binutils:$PATH") -+else -+ AC_CHECK_TOOL(OBJCOPY, objcopy) -+fi -+ -+# Defined in acinclude.m4. -+grub_ASM_USCORE -+grub_PROG_OBJCOPY_ABSOLUTE -+if test "x$grub_cv_prog_objcopy_absolute" != xyes; then -+ AC_MSG_ERROR([GRUB requires a working absolute objcopy; upgrade your binutils]) -+fi -+ -+grub_ASM_PREFIX_REQUIREMENT -+ -+grub_ASM_ADDR32 -+if test "x$grub_cv_asm_addr32" != xyes; then -+ AC_MSG_ERROR([GRUB requires GAS .code16 addr32 support; upgrade your binutils]) -+fi -+ -+grub_ASM_ABSOLUTE_WITHOUT_ASTERISK -+ -+grub_CHECK_START_SYMBOL -+grub_CHECK_USCORE_START_SYMBOL -+if test "x$grub_cv_check_start_symbol" != "xyes" \ -+ -a "x$grub_cv_check_uscore_start_symbol" != "xyes"; then -+ AC_MSG_ERROR([Neither start nor _start is defined]) -+fi -+ -+grub_CHECK_USCORE_USCORE_BSS_START_SYMBOL -+grub_CHECK_USCORE_EDATA_SYMBOL -+grub_CHECK_EDATA_SYMBOL -+if test "x$grub_cv_check_uscore_uscore_bss_start_symbol" != "xyes" \ -+ -a "x$grub_cv_check_uscore_edata_symbol" != "xyes" \ -+ -a "x$grub_cv_check_edata_symbol" != "xyes"; then -+ AC_MSG_ERROR([None of __bss_start, _edata, edata defined]) -+fi -+ -+grub_CHECK_END_SYMBOL -+grub_CHECK_USCORE_END_SYMBOL -+if test "x$grub_cv_check_end_symbol" != "xyes" \ -+ -a "x$grub_cv_check_uscore_end_symbol" != "xyes"; then -+ AC_MSG_ERROR([Neither end nor _end is defined]) -+fi -+ -+# Check for curses libraries. -+AC_ARG_WITH(curses, -+ [ --without-curses do not use curses]) -+ -+# Get the filename or the whole disk and open it. -+# Known to work on NetBSD. -+AC_CHECK_LIB(util, opendisk, [GRUB_LIBS="$GRUB_LIBS -lutil" -+ AC_DEFINE(HAVE_OPENDISK, 1, [Define if opendisk() in -lutil can be used])]) -+ -+# Unless the user specify --without-curses, check for curses. -+if test "x$with_curses" != "xno"; then -+ AC_CHECK_LIB(ncurses, wgetch, [GRUB_LIBS="$GRUB_LIBS -lncurses" -+ AC_DEFINE(HAVE_LIBCURSES)], -+ [AC_CHECK_LIB(curses, wgetch, [GRUB_LIBS="$GRUB_LIBS -lcurses" -+ AC_DEFINE(HAVE_LIBCURSES)])]) -+fi -+ -+AC_SUBST(GRUB_LIBS) -+ -+# Check for headers. -+AC_CHECK_HEADERS(string.h strings.h ncurses/curses.h ncurses.h curses.h) -+ -+# Check for user options. -+ -+# filesystems support. -+AC_ARG_ENABLE(ext2fs, -+ [ --disable-ext2fs disable ext2fs support in Stage 2]) -+ -+if test x"$enable_ext2fs" != xno; then -+ FSYS_CFLAGS="$FSYS_CFLAGS -DFSYS_EXT2FS=1" -+fi -+ -+AC_ARG_ENABLE(fat, -+ [ --disable-fat disable FAT support in Stage 2]) -+ -+if test x"$enable_fat" != xno; then -+ FSYS_CFLAGS="$FSYS_CFLAGS -DFSYS_FAT=1" -+fi -+ -+AC_ARG_ENABLE(ffs, -+ [ --disable-ffs disable FFS support in Stage 2]) -+ -+if test x"$enable_ffs" != xno; then -+ FSYS_CFLAGS="$FSYS_CFLAGS -DFSYS_FFS=1" -+fi -+ -+AC_ARG_ENABLE(minix, -+ [ --disable-minix disable Minix fs support in Stage 2]) -+ -+if test x"$enable_minix" != xno; then -+ FSYS_CFLAGS="$FSYS_CFLAGS -DFSYS_MINIX=1" -+fi -+ -+AC_ARG_ENABLE(reiserfs, -+ [ --disable-reiserfs disable ReiserFS support in Stage 2]) -+ -+if test x"$enable_reiserfs" != xno; then -+ FSYS_CFLAGS="$FSYS_CFLAGS -DFSYS_REISERFS=1" -+fi -+ -+AC_ARG_ENABLE(vstafs, -+ [ --disable-vstafs disable VSTa FS support in Stage 2]) -+ -+if test x"$enable_vstafs" != xno; then -+ FSYS_CFLAGS="$FSYS_CFLAGS -DFSYS_VSTAFS=1" -+fi -+ -+AC_ARG_ENABLE(jfs, -+ [ --disable-jfs disable IBM JFS support in Stage 2]) -+ -+if test x"$enable_jfs" != xno; then -+ FSYS_CFLAGS="$FSYS_CFLAGS -DFSYS_JFS=1" -+fi -+ -+AC_ARG_ENABLE(xfs, -+ [ --disable-xfs disable SGI XFS support in Stage 2]) -+ -+if test x"$enable_xfs" != xno; then -+ FSYS_CFLAGS="$FSYS_CFLAGS -DFSYS_XFS=1" -+fi -+ -+dnl AC_ARG_ENABLE(tftp, -+dnl [ --enable-tftp enable TFTP support in Stage 2]) -+dnl -+dnl #if test x"$enable_tftp" = xyes; then -+dnl FSYS_CFLAGS="$FSYS_CFLAGS -DFSYS_TFTP=1" -+dnl fi -+ -+AC_ARG_ENABLE(gunzip, -+ [ --disable-gunzip disable decompression in Stage 2]) -+ -+if test x"$enable_gunzip" = xno; then -+ FSYS_CFLAGS="$FSYS_CFLAGS -DNO_DECOMPRESSION=1" -+fi -+ -+AC_ARG_ENABLE(md5-password, -+ [ --disable-md5-password disable MD5 password support in Stage 2]) -+if test "x$enable_md5_password" != xno; then -+ FSYS_CFLAGS="$FSYS_CFLAGS -DUSE_MD5_PASSWORDS=1" -+fi -+ -+dnl The netboot support. -+dnl General options. -+AC_ARG_ENABLE(packet-retransmission, -+ [ --disable-packet-retransmission -+ turn off packet retransmission]) -+if test "x$enable_packet_retransmission" != xno; then -+ NET_EXTRAFLAGS="$NET_EXTRAFLAGS -DCONGESTED=1" -+fi -+ -+AC_ARG_ENABLE(pci-direct, -+ [ --enable-pci-direct access PCI directly instead of using BIOS]) -+if test "x$enable_pci_direct" = xyes; then -+ NET_EXTRAFLAGS="$NET_EXTRAFLAGS -DCONFIG_PCI_DIRECT=1" -+fi -+ -+dnl Device drivers. -+AC_ARG_ENABLE(3c509, -+ [ --enable-3c509 enable 3Com509 driver]) -+if test "x$enable_3c509" = xyes; then -+ NET_CFLAGS="$NET_CFLAGS -DINCLUDE_3C509" -+ NETBOOT_DRIVERS="$NETBOOT_DRIVERS 3c509.o" -+fi -+ -+AC_ARG_ENABLE(3c529, -+ [ --enable-3c529 enable 3Com529 driver]) -+if test "x$enable_3c529" = xyes; then -+ NET_CFLAGS="$NET_CFLAGS -DINCLUDE_3C529=1" -+ NETBOOT_DRIVERS="$NETBOOT_DRIVERS 3c529.o" -+fi -+ -+AC_ARG_ENABLE(3c595, -+ [ --enable-3c595 enable 3Com595 driver]) -+if test "x$enable_3c595" = xyes; then -+ NET_CFLAGS="$NET_CFLAGS -DINCLUDE_3C595=1" -+ NETBOOT_DRIVERS="$NETBOOT_DRIVERS 3c595.o" -+fi -+ -+AC_ARG_ENABLE(3c90x, -+ [ --enable-3c90x enable 3Com90x driver]) -+if test "x$enable_3c90x" = xyes; then -+ NET_CFLAGS="$NET_CFLAGS -DINCLUDE_3C90X=1" -+ NETBOOT_DRIVERS="$NETBOOT_DRIVERS 3c90x.o" -+fi -+ -+AC_ARG_ENABLE(cs89x0, -+ [ --enable-cs89x0 enable CS89x0 driver]) -+if test "x$enable_cs89x0" = xyes; then -+ NET_CFLAGS="$NET_CFLAGS -DINCLUDE_CS89X0=1" -+ NETBOOT_DRIVERS="$NETBOOT_DRIVERS cs89x0.o" -+fi -+ -+AC_ARG_ENABLE(davicom, -+ [ --enable-davicom enable Davicom driver]) -+if test "x$enable_davicom" = xyes; then -+ NET_CFLAGS="$NET_CFLAGS -DINCLUDE_DAVICOM=1" -+ NETBOOT_DRIVERS="$NETBOOT_DRIVERS davicom.o" -+fi -+ -+AC_ARG_ENABLE(depca, -+ [ --enable-depca enable DEPCA and EtherWORKS driver]) -+if test "x$enable_depca" = xyes; then -+ NET_CFLAGS="$NET_CFLAGS -DINCLUDE_DEPCA=1" -+ NETBOOT_DRIVERS="$NETBOOT_DRIVERS depca.o" -+fi -+ -+AC_ARG_ENABLE(eepro, -+ [ --enable-eepro enable Etherexpress Pro/10 driver]) -+if test "x$enable_eepro" = xyes; then -+ NET_CFLAGS="$NET_CFLAGS -DINCLUDE_EEPRO=1" -+ NETBOOT_DRIVERS="$NETBOOT_DRIVERS eepro.o" -+fi -+ -+AC_ARG_ENABLE(eepro100, -+ [ --enable-eepro100 enable Etherexpress Pro/100 driver]) -+if test "x$enable_eepro100" = xyes; then -+ NET_CFLAGS="$NET_CFLAGS -DINCLUDE_EEPRO100=1" -+ NETBOOT_DRIVERS="$NETBOOT_DRIVERS eepro100.o" -+fi -+ -+AC_ARG_ENABLE(epic100, -+ [ --enable-epic100 enable SMC 83c170 EPIC/100 driver]) -+if test "x$enable_epic100" = xyes; then -+ NET_CFLAGS="$NET_CFLAGS -DINCLUDE_EPIC100=1" -+ NETBOOT_DRIVERS="$NETBOOT_DRIVERS epic100.o" -+fi -+ -+AC_ARG_ENABLE(3c507, -+ [ --enable-3c507 enable 3Com507 driver]) -+if test "x$enable_3c507" = xyes; then -+ NET_CFLAGS="$NET_CFLAGS -DINCLUDE_3C507=1" -+ NETBOOT_DRIVERS="$NETBOOT_DRIVERS 3c507.o" -+fi -+ -+AC_ARG_ENABLE(exos205, -+ [ --enable-exos205 enable EXOS205 driver]) -+if test "x$enable_exos205" = xyes; then -+ NET_CFLAGS="$NET_CFLAGS -DINCLUDE_EXOS205=1" -+ NETBOOT_DRIVERS="$NETBOOT_DRIVERS exos205.o" -+fi -+ -+AC_ARG_ENABLE(ni5210, -+ [ --enable-ni5210 enable Racal-Interlan NI5210 driver]) -+if test "x$enable_ni5210" = xyes; then -+ NET_CFLAGS="$NET_CFLAGS -DINCLUDE_NI5210=1" -+ NETBOOT_DRIVERS="$NETBOOT_DRIVERS ni5210.o" -+fi -+ -+AC_ARG_ENABLE(lance, -+ [ --enable-lance enable Lance PCI PCNet/32 driver]) -+if test "x$enable_lance" = xyes; then -+ NET_CFLAGS="$NET_CFLAGS -DINCLUDE_LANCE=1" -+ NETBOOT_DRIVERS="$NETBOOT_DRIVERS lance.o" -+fi -+ -+AC_ARG_ENABLE(ne2100, -+ [ --enable-ne2100 enable Novell NE2100 driver]) -+if test "x$enable_ne2100" = xyes; then -+ NET_CFLAGS="$NET_CFLAGS -DINCLUDE_NE2100=1" -+ NETBOOT_DRIVERS="$NETBOOT_DRIVERS ne2100.o" -+fi -+ -+AC_ARG_ENABLE(ni6510, -+ [ --enable-ni6510 enable Racal-Interlan NI6510 driver]) -+if test "x$enable_ni6510" = xyes; then -+ NET_CFLAGS="$NET_CFLAGS -DINCLUDE_NI6510=1" -+ NETBOOT_DRIVERS="$NETBOOT_DRIVERS ni6510.o" -+fi -+ -+AC_ARG_ENABLE(natsemi, -+ [ --enable-natsemi enable NatSemi DP8381x driver]) -+if test "x$enable_natsemi" = xyes; then -+ NET_CFLAGS="$NET_CFLAGS -DINCLUDE_NATSEMI=1" -+ NETBOOT_DRIVERS="$NETBOOT_DRIVERS natsemi.o" -+fi -+ -+AC_ARG_ENABLE(ni5010, -+ [ --enable-ni5010 enable Racal-Interlan NI5010 driver]) -+if test "x$enable_ni5010" = xyes; then -+ NET_CFLAGS="$NET_CFLAGS -DINCLUDE_NI5010=1" -+ NETBOOT_DRIVERS="$NETBOOT_DRIVERS ni5010.o" -+fi -+ -+AC_ARG_ENABLE(3c503, -+ [ --enable-3c503 enable 3Com503 driver]) -+if test "x$enable_3c503" = xyes; then -+ NET_CFLAGS="$NET_CFLAGS -DINCLUDE_3C503=1" -+ NETBOOT_DRIVERS="$NETBOOT_DRIVERS 3c503.o" -+fi -+ -+AC_ARG_ENABLE(ne, -+ [ --enable-ne enable NE1000/2000 ISA driver]) -+if test "x$enable_ne" = xyes; then -+ NET_CFLAGS="$NET_CFLAGS -DINCLUDE_NE=1" -+ NETBOOT_DRIVERS="$NETBOOT_DRIVERS ne.o" -+fi -+ -+AC_ARG_ENABLE(ns8390, -+ [ --enable-ns8390 enable NE2000 PCI driver]) -+if test "x$enable_ns8390" = xyes; then -+ NET_CFLAGS="$NET_CFLAGS -DINCLUDE_NS8390=1" -+ NETBOOT_DRIVERS="$NETBOOT_DRIVERS ns8390.o" -+fi -+ -+AC_ARG_ENABLE(wd, -+ [ --enable-wd enable WD8003/8013, SMC8216/8416 driver]) -+if test "x$enable_wd" = xyes; then -+ NET_CFLAGS="$NET_CFLAGS -DINCLUDE_WD=1" -+ NETBOOT_DRIVERS="$NETBOOT_DRIVERS wd.o" -+fi -+ -+AC_ARG_ENABLE(otulip, -+ [ --enable-otulip enable old Tulip driver]) -+if test "x$enable_otulip" = xyes; then -+ NET_CFLAGS="$NET_CFLAGS -DINCLUDE_OTULIP=1" -+ NETBOOT_DRIVERS="$NETBOOT_DRIVERS otulip.o" -+fi -+ -+AC_ARG_ENABLE(rtl8139, -+ [ --enable-rtl8139 enable Realtek 8139 driver]) -+if test "x$enable_rtl8139" = xyes; then -+ NET_CFLAGS="$NET_CFLAGS -DINCLUDE_RTL8139=1" -+ NETBOOT_DRIVERS="$NETBOOT_DRIVERS rtl8139.o" -+fi -+ -+AC_ARG_ENABLE(sis900, -+ [ --enable-sis900 enable SIS 900 and SIS 7016 driver]) -+if test "x$enable_sis900" = xyes; then -+ NET_CFLAGS="$NET_CFLAGS -DINCLUDE_SIS900=1" -+ NETBOOT_DRIVERS="$NETBOOT_DRIVERS sis900.o" -+fi -+ -+AC_ARG_ENABLE(sk-g16, -+ [ --enable-sk-g16 enable Schneider and Koch G16 driver]) -+if test "x$enable_sk_g16" = xyes; then -+ NET_CFLAGS="$NET_CFLAGS -DINCLUDE_SK_G16=1" -+ NETBOOT_DRIVERS="$NETBOOT_DRIVERS sk_g16.o" -+fi -+ -+AC_ARG_ENABLE(smc9000, -+ [ --enable-smc9000 enable SMC9000 driver]) -+if test "x$enable_smc9000" = xyes; then -+ NET_CFLAGS="$NET_CFLAGS -DINCLUDE_SMC9000=1" -+ NETBOOT_DRIVERS="$NETBOOT_DRIVERS smc9000.o" -+fi -+ -+AC_ARG_ENABLE(tiara, -+ [ --enable-tiara enable Tiara driver]) -+if test "x$enable_tiara" = xyes; then -+ NET_CFLAGS="$NET_CFLAGS -DINCLUDE_TIARA=1" -+ NETBOOT_DRIVERS="$NETBOOT_DRIVERS tiara.o" -+fi -+ -+AC_ARG_ENABLE(tulip, -+ [ --enable-tulip enable Tulip driver]) -+if test "x$enable_tulip" = xyes; then -+ NET_CFLAGS="$NET_CFLAGS -DINCLUDE_TULIP=1" -+ NETBOOT_DRIVERS="$NETBOOT_DRIVERS tulip.o" -+fi -+ -+AC_ARG_ENABLE(via-rhine, -+ [ --enable-via-rhine enable Rhine-I/II driver]) -+if test "x$enable_via_rhine" = xyes; then -+ NET_CFLAGS="$NET_CFLAGS -DINCLUDE_VIA_RHINE=1" -+ NETBOOT_DRIVERS="$NETBOOT_DRIVERS via_rhine.o" -+fi -+ -+AC_ARG_ENABLE(w89c840, -+ [ --enable-w89c840 enable Winbond W89c840, Compex RL100-ATX driver]) -+if test "x$enable_w89c840" = xyes; then -+ NET_CFLAGS="$NET_CFLAGS -DINCLUDE_W89C840=1" -+ NETBOOT_DRIVERS="$NETBOOT_DRIVERS w89c840.o" -+fi -+ -+dnl Check if the netboot support is turned on. -+AM_CONDITIONAL(NETBOOT_SUPPORT, test "x$NET_CFLAGS" != x) -+if test "x$NET_CFLAGS" != x; then -+ FSYS_CFLAGS="$FSYS_CFLAGS -DFSYS_TFTP=1" -+fi -+ -+dnl Extra options. -+AC_ARG_ENABLE(3c503-shmem, -+ [ --enable-3c503-shmem use 3c503 shared memory mode]) -+if test "x$enable_3c503_shmem" = xyes; then -+ NET_EXTRAFLAGS="$NET_EXTRAFLAGS -DT503_SHMEM=1" -+fi -+ -+AC_ARG_ENABLE(3c503-aui, -+ [ --enable-3c503-aui use AUI by default on 3c503 cards]) -+if test "x$enable_3c503_aui" = xyes; then -+ NET_EXTRAFLAGS="$NET_EXTRAFLAGS -DT503_AUI=1" -+fi -+ -+AC_ARG_ENABLE(compex-rl2000-fix, -+ [ --enable-compex-rl2000-fix -+ specify this if you have a Compex RL2000 PCI]) -+if test "x$enable_compex_rl2000_fix" = xyes; then -+ NET_EXTRAFLAGS="$NET_EXTRAFLAGS -DCOMPEX_RL2000_FIX=1" -+fi -+ -+AC_ARG_ENABLE(smc9000-scan, -+ [ --enable-smc9000-scan=LIST -+ probe for SMC9000 I/O addresses using LIST], -+ [NET_EXTRAFLAGS="$NET_EXTRAFLAGS -DSMC9000_SCAN=$enable_smc9000_scan"]) -+ -+AC_ARG_ENABLE(ne-scan, -+ [ --enable-ne-scan=LIST probe for NE base address using LIST], -+ [NET_EXTRAFLAGS="$NET_EXTRAFLAGS -DNE_SCAN=$enable_ne_scan"], -+ [NET_EXTRAFLAGS="$NET_EXTRAFLAGS -DNE_SCAN=0x280,0x300,0x320,0x340"]) -+ -+AC_ARG_ENABLE(wd-default-mem, -+ [ --enable-wd-default-mem=MEM -+ set the default memory location for WD/SMC], -+ [NET_EXTRAFLAGS="$NET_EXTRAFLAGS -DWD_DEFAULT_MEM=$enable_wd_default_mem"], -+ [NET_EXTRAFLAGS="$NET_EXTRAFLAGS -DWD_DEFAULT_MEM=0xCC000"]) -+ -+AC_ARG_ENABLE(cs-scan, -+ [ --enable-cs-scan=LIST probe for CS89x0 base address using LIST], -+ [NET_EXTRAFLAGS="$NET_EXTRAFLAGS -DCS_SCAN=$enable_cs_scan"]) -+ -+dnl Diskless -+AC_ARG_ENABLE(diskless, -+ [ --enable-diskless enable diskless support]) -+AM_CONDITIONAL(DISKLESS_SUPPORT, test "x$enable_diskless" = xyes) -+ -+dnl Hercules terminal -+AC_ARG_ENABLE(hercules, -+ [ --disable-hercules disable hercules terminal support]) -+AM_CONDITIONAL(HERCULES_SUPPORT, test "x$enable_hercules" != xno) -+ -+dnl Serial terminal -+AC_ARG_ENABLE(serial, -+ [ --disable-serial disable serial terminal support]) -+AM_CONDITIONAL(SERIAL_SUPPORT, test "x$enable_serial" != xno) -+ -+dnl Simulation of the slowness of a serial device. -+AC_ARG_ENABLE(serial-speed-simulation, -+ [ --enable-serial-speed-simulation -+ simulate the slowness of a serial device]) -+AM_CONDITIONAL(SERIAL_SPEED_SIMULATION, -+ test "x$enable_serial_speed_simulation" = xyes) -+ -+# Sanity check. -+if test "x$enable_diskless" = xyes; then -+ if test "x$NET_CFLAGS" = x; then -+ AC_MSG_ERROR([You must enable at least one network driver]) -+ fi -+fi -+ -+dnl Embed a menu string in GRUB itself. -+AC_ARG_ENABLE(preset-menu, -+ [ --enable-preset-menu=FILE -+ preset a menu file FILE in Stage 2]) -+if test "x$enable_preset_menu" = x; then -+ : -+else -+ if test -r $enable_preset_menu; then -+ grub_DEFINE_FILE(PRESET_MENU_STRING, [$enable_preset_menu]) -+ else -+ AC_MSG_ERROR([Cannot read the preset menu file $enable_preset_menu]) -+ fi -+fi -+ -+dnl Build the example Multiboot kernel. -+AC_ARG_ENABLE(example-kernel, -+ [ --enable-example-kernel -+ build the example Multiboot kernel]) -+AM_CONDITIONAL(BUILD_EXAMPLE_KERNEL, test "x$enable_example_kernel" = xyes) -+ -+dnl Automatic Linux mem= option. -+AC_ARG_ENABLE(auto-linux-mem-opt, -+ [ --disable-auto-linux-mem-opt -+ don't pass Linux mem= option automatically]) -+if test "x$enable_auto_linux_mem_opt" = xno; then -+ : -+else -+ AC_DEFINE(AUTO_LINUX_MEM_OPT) -+fi -+ -+dnl Now substitute the variables. -+AC_SUBST(FSYS_CFLAGS) -+AC_SUBST(NET_CFLAGS) -+AC_SUBST(NET_EXTRAFLAGS) -+AC_SUBST(NETBOOT_DRIVERS) -+ -+dnl Because recent automake complains about CCASFLAGS, set it here. -+CCASFLAGS='$(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)' -+AC_SUBST(CCASFLAGS) -+ -+ -+dnl Output. -+AC_CONFIG_FILES([Makefile stage1/Makefile stage2/Makefile \ -+ docs/Makefile lib/Makefile util/Makefile \ -+ grub/Makefile netboot/Makefile util/grub-image \ -+ util/grub-install util/grub-md5-crypt \ -+ util/grub-terminfo]) -+AC_OUTPUT -diff -ruN grub-0.94.orig/grub/Makefile.am grub/Makefile.am ---- grub-0.94.orig/grub/Makefile.am Wed Feb 11 00:22:12 2004 -+++ grub/Makefile.am Wed Feb 11 00:22:29 2004 +diff -ruN grub/Makefile.am.orig grub/Makefile.am +--- grub/Makefile.am.orig Sat Apr 24 20:49:07 2004 ++++ grub/Makefile.am Sat Apr 24 20:49:16 2004 @@ -7,6 +7,7 @@ endif @@ -670,30 +26,9 @@ diff -ruN grub-0.94.orig/grub/Makefile.am grub/Makefile.am -DFSYS_FFS=1 -DFSYS_MINIX=1 -DSUPPORT_HERCULES=1 \ $(SERIAL_FLAGS) -I$(top_srcdir)/stage2 \ -I$(top_srcdir)/stage1 -I$(top_srcdir)/lib -diff -ruN grub-0.94.orig/grub/Makefile.am.orig grub/Makefile.am.orig ---- grub-0.94.orig/grub/Makefile.am.orig Thu Jan 1 03:00:00 1970 -+++ grub/Makefile.am.orig Sun Jan 18 22:34:24 2004 -@@ -0,0 +1,17 @@ -+sbin_PROGRAMS = grub -+ -+if SERIAL_SPEED_SIMULATION -+SERIAL_FLAGS = -DSUPPORT_SERIAL=1 -DSIMULATE_SLOWNESS_OF_SERIAL=1 -+else -+SERIAL_FLAGS = -DSUPPORT_SERIAL=1 -+endif -+ -+AM_CPPFLAGS = -DGRUB_UTIL=1 -DFSYS_EXT2FS=1 -DFSYS_FAT=1 \ -+ -DFSYS_FFS=1 -DFSYS_MINIX=1 -DSUPPORT_HERCULES=1 \ -+ $(SERIAL_FLAGS) -I$(top_srcdir)/stage2 \ -+ -I$(top_srcdir)/stage1 -I$(top_srcdir)/lib -+ -+AM_CFLAGS = $(GRUB_CFLAGS) -fwritable-strings -+ -+grub_SOURCES = main.c asmstub.c -+grub_LDADD = ../stage2/libgrub.a ../lib/libcommon.a $(GRUB_LIBS) -diff -ruN grub-0.94.orig/stage2/Makefile.am stage2/Makefile.am ---- grub-0.94.orig/stage2/Makefile.am Wed Feb 11 00:22:12 2004 -+++ stage2/Makefile.am Wed Feb 11 00:22:29 2004 +diff -ruN stage2/Makefile.am.orig stage2/Makefile.am +--- stage2/Makefile.am.orig Sat Apr 24 20:49:07 2004 ++++ stage2/Makefile.am Sat Apr 24 20:49:16 2004 @@ -17,10 +17,12 @@ noinst_LIBRARIES = libgrub.a libgrub_a_SOURCES = boot.c builtins.c char_io.c cmdline.c common.c \ @@ -757,252 +92,9 @@ diff -ruN grub-0.94.orig/stage2/Makefile.am stage2/Makefile.am # For minix_stage1_5 target. minix_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c disk_io.c \ -diff -ruN grub-0.94.orig/stage2/Makefile.am.orig stage2/Makefile.am.orig ---- grub-0.94.orig/stage2/Makefile.am.orig Thu Jan 1 03:00:00 1970 -+++ stage2/Makefile.am.orig Sun Oct 19 20:45:18 2003 -@@ -0,0 +1,239 @@ -+# For test target. -+TESTS = size_test -+noinst_SCRIPTS = $(TESTS) -+ -+# For dist target. -+noinst_HEADERS = apic.h defs.h dir.h disk_inode.h disk_inode_ffs.h \ -+ fat.h filesys.h freebsd.h fs.h hercules.h i386-elf.h \ -+ imgact_aout.h jfs.h mb_header.h mb_info.h md5.h nbi.h \ -+ pc_slice.h serial.h shared.h smp-imps.h term.h terminfo.h \ -+ tparm.h nbi.h vstafs.h xfs.h -+EXTRA_DIST = setjmp.S apm.S $(noinst_SCRIPTS) -+ -+# For <stage1.h>. -+INCLUDES = -I$(top_srcdir)/stage1 -+ -+# The library for /sbin/grub. -+noinst_LIBRARIES = libgrub.a -+libgrub_a_SOURCES = boot.c builtins.c char_io.c cmdline.c common.c \ -+ disk_io.c fsys_ext2fs.c fsys_fat.c fsys_ffs.c fsys_jfs.c \ -+ fsys_minix.c fsys_reiserfs.c fsys_vstafs.c fsys_xfs.c gunzip.c \ -+ md5.c serial.c stage2.c terminfo.c tparm.c -+libgrub_a_CFLAGS = $(GRUB_CFLAGS) -I$(top_srcdir)/lib \ -+ -DGRUB_UTIL=1 -DFSYS_EXT2FS=1 -DFSYS_FAT=1 -DFSYS_FFS=1 \ -+ -DFSYS_JFS=1 -DFSYS_MINIX=1 -DFSYS_REISERFS=1 -DFSYS_VSTAFS=1 \ -+ -DFSYS_XFS=1 -DUSE_MD5_PASSWORDS=1 \ -+ -DSUPPORT_SERIAL=1 -DSUPPORT_HERCULES=1 -fwritable-strings -+ -+# Stage 2 and Stage 1.5's. -+pkgdatadir = $(datadir)/$(PACKAGE)/$(host_cpu)-$(host_vendor) -+ -+EXTRA_PROGRAMS = nbloader.exec pxeloader.exec diskless.exec -+ -+if DISKLESS_SUPPORT -+pkgdata_DATA = stage2 e2fs_stage1_5 fat_stage1_5 ffs_stage1_5 \ -+ jfs_stage1_5 minix_stage1_5 reiserfs_stage1_5 vstafs_stage1_5 \ -+ xfs_stage1_5 nbgrub pxegrub -+noinst_DATA = pre_stage2 start nbloader pxeloader diskless -+noinst_PROGRAMS = pre_stage2.exec start.exec e2fs_stage1_5.exec \ -+ fat_stage1_5.exec ffs_stage1_5.exec jfs_stage1_5.exec \ -+ minix_stage1_5.exec reiserfs_stage1_5.exec \ -+ vstafs_stage1_5.exec xfs_stage1_5.exec nbloader.exec \ -+ pxeloader.exec diskless.exec -+else -+pkgdata_DATA = stage2 e2fs_stage1_5 fat_stage1_5 ffs_stage1_5 \ -+ jfs_stage1_5 minix_stage1_5 reiserfs_stage1_5 vstafs_stage1_5 \ -+ xfs_stage1_5 -+noinst_DATA = pre_stage2 start -+noinst_PROGRAMS = pre_stage2.exec start.exec e2fs_stage1_5.exec \ -+ fat_stage1_5.exec ffs_stage1_5.exec jfs_stage1_5.exec \ -+ minix_stage1_5.exec reiserfs_stage1_5.exec \ -+ vstafs_stage1_5.exec xfs_stage1_5.exec -+endif -+MOSTLYCLEANFILES = $(noinst_PROGRAMS) -+ -+PRE_STAGE2_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,8200 -+START_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,8000 -+NBLOADER_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,0 -+PXELOADER_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,7C00 -+ -+if NETBOOT_SUPPORT -+NETBOOT_FLAGS = -I$(top_srcdir)/netboot -DSUPPORT_NETBOOT=1 -+else -+NETBOOT_FLAGS = -+endif -+ -+if SERIAL_SUPPORT -+SERIAL_FLAGS = -DSUPPORT_SERIAL=1 -+else -+SERIAL_FLAGS = -+endif -+ -+if HERCULES_SUPPORT -+HERCULES_FLAGS = -DSUPPORT_HERCULES=1 -+else -+HERCULES_FLAGS = -+endif -+ -+STAGE2_COMPILE = $(STAGE2_CFLAGS) -fno-builtin -nostdinc \ -+ $(NETBOOT_FLAGS) $(SERIAL_FLAGS) $(HERCULES_FLAGS) -+ -+STAGE1_5_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,2000 -+STAGE1_5_COMPILE = $(STAGE2_COMPILE) -DNO_DECOMPRESSION=1 -DSTAGE1_5=1 -+ -+# For stage2 target. -+pre_stage2_exec_SOURCES = asm.S bios.c boot.c builtins.c char_io.c \ -+ cmdline.c common.c console.c disk_io.c fsys_ext2fs.c \ -+ fsys_fat.c fsys_ffs.c fsys_jfs.c fsys_minix.c fsys_reiserfs.c \ -+ fsys_vstafs.c fsys_xfs.c gunzip.c hercules.c md5.c serial.c \ -+ smp-imps.c stage2.c terminfo.c tparm.c -+pre_stage2_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS) -+pre_stage2_exec_CCASFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS) -+pre_stage2_exec_LDFLAGS = $(PRE_STAGE2_LINK) -+ -+if NETBOOT_SUPPORT -+pre_stage2_exec_LDADD = ../netboot/libdrivers.a -+endif -+ -+if DISKLESS_SUPPORT -+BUILT_SOURCES = stage2_size.h diskless_size.h -+else -+BUILT_SOURCES = stage2_size.h -+endif -+ -+CLEANFILES = $(pkgdata_DATA) $(noinst_DATA) $(BUILT_SOURCES) -+ -+stage2_size.h: pre_stage2 -+ -rm -f stage2_size.h -+ set dummy `ls -l pre_stage2`; \ -+ echo "#define STAGE2_SIZE $$6" > stage2_size.h -+ -+start_exec_SOURCES = start.S -+start_exec_CCASFLAGS = $(STAGE2_COMPILE) -+start_exec_LDFLAGS = $(START_LINK) -+ -+# XXX: automake doesn't provide a way to specify dependencies for object -+# files explicitly, so we must write this by a general Makefile scheme. -+# If automake change the naming scheme for per-executable objects, this -+# will be broken. -+start_exec-start.$(OBJEXT): stage2_size.h -+ -+stage2: pre_stage2 start -+ -rm -f stage2 -+ cat start pre_stage2 > stage2 -+ -+# For e2fs_stage1_5 target. -+e2fs_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c disk_io.c \ -+ stage1_5.c fsys_ext2fs.c bios.c -+e2fs_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_EXT2FS=1 \ -+ -DNO_BLOCK_FILES=1 -+e2fs_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_EXT2FS=1 \ -+ -DNO_BLOCK_FILES=1 -+e2fs_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK) -+ -+# For fat_stage1_5 target. -+fat_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c disk_io.c \ -+ stage1_5.c fsys_fat.c bios.c -+fat_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_FAT=1 \ -+ -DNO_BLOCK_FILES=1 -+fat_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_FAT=1 \ -+ -DNO_BLOCK_FILES=1 -+fat_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK) -+ -+# For ffs_stage1_5 target. -+ffs_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c disk_io.c \ -+ stage1_5.c fsys_ffs.c bios.c -+ffs_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_FFS=1 \ -+ -DNO_BLOCK_FILES=1 -+ffs_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_FFS=1 \ -+ -DNO_BLOCK_FILES=1 -+ffs_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK) -+ -+# For minix_stage1_5 target. -+minix_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c disk_io.c \ -+ stage1_5.c fsys_minix.c bios.c -+minix_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_MINIX=1 \ -+ -DNO_BLOCK_FILES=1 -+minix_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_MINIX=1 \ -+ -DNO_BLOCK_FILES=1 -+minix_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK) -+ -+# For reiserfs_stage1_5 target. -+reiserfs_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c \ -+ disk_io.c stage1_5.c fsys_reiserfs.c bios.c -+reiserfs_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_REISERFS=1 \ -+ -DNO_BLOCK_FILES=1 -+reiserfs_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_REISERFS=1 \ -+ -DNO_BLOCK_FILES=1 -+reiserfs_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK) -+ -+# For vstafs_stage1_5 target. -+vstafs_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c \ -+ disk_io.c stage1_5.c fsys_vstafs.c bios.c -+vstafs_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_VSTAFS=1 \ -+ -DNO_BLOCK_FILES=1 -+vstafs_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_VSTAFS=1 \ -+ -DNO_BLOCK_FILES=1 -+vstafs_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK) -+ -+# For jfs_stage1_5 target. -+jfs_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c \ -+ disk_io.c stage1_5.c fsys_jfs.c bios.c -+jfs_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_JFS=1 \ -+ -DNO_BLOCK_FILES=1 -+jfs_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_JFS=1 \ -+ -DNO_BLOCK_FILES=1 -+jfs_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK) -+ -+# For xfs_stage1_5 target. -+xfs_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c \ -+ disk_io.c stage1_5.c fsys_xfs.c bios.c -+xfs_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_XFS=1 \ -+ -DNO_BLOCK_FILES=1 -+xfs_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_XFS=1 \ -+ -DNO_BLOCK_FILES=1 -+xfs_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK) -+ -+# For diskless target. -+diskless_exec_SOURCES = $(pre_stage2_exec_SOURCES) -+diskless_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS) \ -+ -DSUPPORT_DISKLESS=1 -+diskless_exec_CCASFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS) \ -+ -DSUPPORT_DISKLESS=1 -+diskless_exec_LDFLAGS = $(PRE_STAGE2_LINK) -+diskless_exec_LDADD = ../netboot/libdrivers.a -+ -+diskless_size.h: diskless -+ -rm -f $@ -+ set dummy `ls -l $^`; \ -+ echo "#define DISKLESS_SIZE $$6" > $@ -+ -+# For nbloader target. -+nbloader_exec_SOURCES = nbloader.S -+nbloader_exec_CCASFLAGS = $(STAGE2_COMPILE) -+nbloader_exec_LDFLAGS = $(NBLOADER_LINK) -+ -+# XXX: See the comment for start_exec-start.o. -+nbloader_exec-nbloader.$(OBJEXT): diskless_size.h -+ -+# For nbgrub target. -+nbgrub: nbloader diskless -+ -rm -f $@ -+ cat $^ > $@ -+ -+# For pxeloader target. -+pxeloader_exec_SOURCES = pxeloader.S -+pxeloader_exec_CCASFLAGS = $(STAGE2_COMPILE) -+pxeloader_exec_LDFLAGS = $(PXELOADER_LINK) -+ -+# XXX: See the comment for start_exec-start.o. -+pxeloader_exec-pxeloader.$(OBJEXT): diskless_size.h -+ -+# For pxegrub target. -+pxegrub: pxeloader diskless -+ -rm -f $@ -+ cat $^ > $@ -+ -+# General rule for making a raw binary. -+%: %.exec -+ $(OBJCOPY) -O binary $< $@ -diff -ruN grub-0.94.orig/stage2/builtins.c stage2/builtins.c ---- grub-0.94.orig/stage2/builtins.c Wed Feb 11 00:22:12 2004 -+++ stage2/builtins.c Wed Feb 11 00:22:29 2004 +diff -ruN stage2/builtins.c.orig stage2/builtins.c +--- stage2/builtins.c.orig Sat Apr 24 20:49:07 2004 ++++ stage2/builtins.c Sat Apr 24 20:49:16 2004 @@ -3747,6 +3747,7 @@ { {"ext2fs", "/e2fs_stage1_5"}, @@ -1011,4768 +103,9 @@ diff -ruN grub-0.94.orig/stage2/builtins.c stage2/builtins.c {"ffs", "/ffs_stage1_5"}, {"jfs", "/jfs_stage1_5"}, {"minix", "/minix_stage1_5"}, -diff -ruN grub-0.94.orig/stage2/builtins.c.orig stage2/builtins.c.orig ---- grub-0.94.orig/stage2/builtins.c.orig Thu Jan 1 03:00:00 1970 -+++ stage2/builtins.c.orig Sun Jan 11 12:39:22 2004 -@@ -0,0 +1,4755 @@ -+/* builtins.c - the GRUB builtin commands */ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+/* Include stdio.h before shared.h, because we can't define -+ WITHOUT_LIBC_STUBS here. */ -+#ifdef GRUB_UTIL -+# include <stdio.h> -+#endif -+ -+#include <shared.h> -+#include <filesys.h> -+#include <term.h> -+ -+#ifdef SUPPORT_NETBOOT -+# define GRUB 1 -+# include <etherboot.h> -+#endif -+ -+#ifdef SUPPORT_SERIAL -+# include <serial.h> -+# include <terminfo.h> -+#endif -+ -+#ifdef GRUB_UTIL -+# include <device.h> -+#else /* ! GRUB_UTIL */ -+# include <apic.h> -+# include <smp-imps.h> -+#endif /* ! GRUB_UTIL */ -+ -+#ifdef USE_MD5_PASSWORDS -+# include <md5.h> -+#endif -+ -+/* The type of kernel loaded. */ -+kernel_t kernel_type; -+/* The boot device. */ -+static int bootdev; -+/* True when the debug mode is turned on, and false -+ when it is turned off. */ -+int debug = 0; -+/* The default entry. */ -+int default_entry = 0; -+/* The fallback entry. */ -+int fallback_entry = -1; -+/* The number of current entry. */ -+int current_entryno; -+/* The address for Multiboot command-line buffer. */ -+static char *mb_cmdline; -+/* The password. */ -+char *password; -+/* The password type. */ -+password_t password_type; -+/* The flag for indicating that the user is authoritative. */ -+int auth = 0; -+/* The timeout. */ -+int grub_timeout = -1; -+/* Whether to show the menu or not. */ -+int show_menu = 1; -+/* The BIOS drive map. */ -+static unsigned short bios_drive_map[DRIVE_MAP_SIZE + 1]; -+ -+/* Prototypes for allowing straightfoward calling of builtins functions -+ inside other functions. */ -+static int configfile_func (char *arg, int flags); -+ -+/* Initialize the data for builtins. */ -+void -+init_builtins (void) -+{ -+ kernel_type = KERNEL_TYPE_NONE; -+ /* BSD and chainloading evil hacks! */ -+ bootdev = set_bootdev (0); -+ mb_cmdline = (char *) MB_CMDLINE_BUF; -+} -+ -+/* Initialize the data for the configuration file. */ -+void -+init_config (void) -+{ -+ default_entry = 0; -+ password = 0; -+ fallback_entry = -1; -+ grub_timeout = -1; -+} -+ -+/* Check a password for correctness. Returns 0 if password was -+ correct, and a value != 0 for error, similarly to strcmp. */ -+int -+check_password (char *entered, char* expected, password_t type) -+{ -+ switch (type) -+ { -+ case PASSWORD_PLAIN: -+ return strcmp (entered, expected); -+ -+#ifdef USE_MD5_PASSWORDS -+ case PASSWORD_MD5: -+ return check_md5_password (entered, expected); -+#endif -+ default: -+ /* unsupported password type: be secure */ -+ return 1; -+ } -+} -+ -+/* Print which sector is read when loading a file. */ -+static void -+disk_read_print_func (int sector, int offset, int length) -+{ -+ grub_printf ("[%d,%d,%d]", sector, offset, length); -+} -+ -+ -+/* blocklist */ -+static int -+blocklist_func (char *arg, int flags) -+{ -+ char *dummy = (char *) RAW_ADDR (0x100000); -+ int start_sector; -+ int num_sectors = 0; -+ int num_entries = 0; -+ int last_length = 0; -+ -+ /* Collect contiguous blocks into one entry as many as possible, -+ and print the blocklist notation on the screen. */ -+ static void disk_read_blocklist_func (int sector, int offset, int length) -+ { -+ if (num_sectors > 0) -+ { -+ if (start_sector + num_sectors == sector -+ && offset == 0 && last_length == SECTOR_SIZE) -+ { -+ num_sectors++; -+ last_length = length; -+ return; -+ } -+ else -+ { -+ if (last_length == SECTOR_SIZE) -+ grub_printf ("%s%d+%d", num_entries ? "," : "", -+ start_sector - part_start, num_sectors); -+ else if (num_sectors > 1) -+ grub_printf ("%s%d+%d,%d[0-%d]", num_entries ? "," : "", -+ start_sector - part_start, num_sectors-1, -+ start_sector + num_sectors-1 - part_start, -+ last_length); -+ else -+ grub_printf ("%s%d[0-%d]", num_entries ? "," : "", -+ start_sector - part_start, last_length); -+ num_entries++; -+ num_sectors = 0; -+ } -+ } -+ -+ if (offset > 0) -+ { -+ grub_printf("%s%d[%d-%d]", num_entries ? "," : "", -+ sector-part_start, offset, offset+length); -+ num_entries++; -+ } -+ else -+ { -+ start_sector = sector; -+ num_sectors = 1; -+ last_length = length; -+ } -+ } -+ -+ /* Open the file. */ -+ if (! grub_open (arg)) -+ return 1; -+ -+ /* Print the device name. */ -+ grub_printf ("(%cd%d", -+ (current_drive & 0x80) ? 'h' : 'f', -+ current_drive & ~0x80); -+ -+ if ((current_partition & 0xFF0000) != 0xFF0000) -+ grub_printf (",%d", (current_partition >> 16) & 0xFF); -+ -+ if ((current_partition & 0x00FF00) != 0x00FF00) -+ grub_printf (",%c", 'a' + ((current_partition >> 8) & 0xFF)); -+ -+ grub_printf (")"); -+ -+ /* Read in the whole file to DUMMY. */ -+ disk_read_hook = disk_read_blocklist_func; -+ if (! grub_read (dummy, -1)) -+ goto fail; -+ -+ /* The last entry may not be printed yet. Don't check if it is a -+ * full sector, since it doesn't matter if we read too much. */ -+ if (num_sectors > 0) -+ grub_printf ("%s%d+%d", num_entries ? "," : "", -+ start_sector - part_start, num_sectors); -+ -+ grub_printf ("\n"); -+ -+ fail: -+ disk_read_hook = 0; -+ grub_close (); -+ return errnum; -+} -+ -+static struct builtin builtin_blocklist = -+{ -+ "blocklist", -+ blocklist_func, -+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST, -+ "blocklist FILE", -+ "Print the blocklist notation of the file FILE." -+}; -+ -+/* boot */ -+static int -+boot_func (char *arg, int flags) -+{ -+ /* Clear the int15 handler if we can boot the kernel successfully. -+ This assumes that the boot code never fails only if KERNEL_TYPE is -+ not KERNEL_TYPE_NONE. Is this assumption is bad? */ -+ if (kernel_type != KERNEL_TYPE_NONE) -+ unset_int15_handler (); -+ -+#ifdef SUPPORT_NETBOOT -+ /* Shut down the networking. */ -+ cleanup_net (); -+#endif -+ -+ switch (kernel_type) -+ { -+ case KERNEL_TYPE_FREEBSD: -+ case KERNEL_TYPE_NETBSD: -+ /* *BSD */ -+ bsd_boot (kernel_type, bootdev, (char *) mbi.cmdline); -+ break; -+ -+ case KERNEL_TYPE_LINUX: -+ /* Linux */ -+ linux_boot (); -+ break; -+ -+ case KERNEL_TYPE_BIG_LINUX: -+ /* Big Linux */ -+ big_linux_boot (); -+ break; -+ -+ case KERNEL_TYPE_CHAINLOADER: -+ /* Chainloader */ -+ -+ /* Check if we should set the int13 handler. */ -+ if (bios_drive_map[0] != 0) -+ { -+ int i; -+ -+ /* Search for SAVED_DRIVE. */ -+ for (i = 0; i < DRIVE_MAP_SIZE; i++) -+ { -+ if (! bios_drive_map[i]) -+ break; -+ else if ((bios_drive_map[i] & 0xFF) == saved_drive) -+ { -+ /* Exchage SAVED_DRIVE with the mapped drive. */ -+ saved_drive = (bios_drive_map[i] >> 8) & 0xFF; -+ break; -+ } -+ } -+ -+ /* Set the handler. This is somewhat dangerous. */ -+ set_int13_handler (bios_drive_map); -+ } -+ -+ gateA20 (0); -+ boot_drive = saved_drive; -+ chain_stage1 (0, BOOTSEC_LOCATION, boot_part_addr); -+ break; -+ -+ case KERNEL_TYPE_MULTIBOOT: -+ /* Multiboot */ -+ multi_boot ((int) entry_addr, (int) &mbi); -+ break; -+ -+ default: -+ errnum = ERR_BOOT_COMMAND; -+ return 1; -+ } -+ -+ return 0; -+} -+ -+static struct builtin builtin_boot = -+{ -+ "boot", -+ boot_func, -+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST, -+ "boot", -+ "Boot the OS/chain-loader which has been loaded." -+}; -+ -+ -+#ifdef SUPPORT_NETBOOT -+/* bootp */ -+static int -+bootp_func (char *arg, int flags) -+{ -+ int with_configfile = 0; -+ -+ if (grub_memcmp (arg, "--with-configfile", sizeof ("--with-configfile") - 1) -+ == 0) -+ { -+ with_configfile = 1; -+ arg = skip_to (0, arg); -+ } -+ -+ if (! bootp ()) -+ { -+ if (errnum == ERR_NONE) -+ errnum = ERR_DEV_VALUES; -+ -+ return 1; -+ } -+ -+ /* Notify the configuration. */ -+ print_network_configuration (); -+ -+ /* XXX: this can cause an endless loop, but there is no easy way to -+ detect such a loop unfortunately. */ -+ if (with_configfile) -+ configfile_func (config_file, flags); -+ -+ return 0; -+} -+ -+static struct builtin builtin_bootp = -+{ -+ "bootp", -+ bootp_func, -+ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, -+ "bootp [--with-configfile]", -+ "Initialize a network device via BOOTP. If the option `--with-configfile'" -+ " is given, try to load a configuration file specified by the 150 vendor" -+ " tag." -+}; -+#endif /* SUPPORT_NETBOOT */ -+ -+ -+/* cat */ -+static int -+cat_func (char *arg, int flags) -+{ -+ char c; -+ -+ if (! grub_open (arg)) -+ return 1; -+ -+ while (grub_read (&c, 1)) -+ { -+ /* Because running "cat" with a binary file can confuse the terminal, -+ print only some characters as they are. */ -+ if (grub_isspace (c) || (c >= ' ' && c <= '~')) -+ grub_putchar (c); -+ else -+ grub_putchar ('?'); -+ } -+ -+ grub_close (); -+ return 0; -+} -+ -+static struct builtin builtin_cat = -+{ -+ "cat", -+ cat_func, -+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST, -+ "cat FILE", -+ "Print the contents of the file FILE." -+}; -+ -+ -+/* chainloader */ -+static int -+chainloader_func (char *arg, int flags) -+{ -+ int force = 0; -+ char *file = arg; -+ -+ /* If the option `--force' is specified? */ -+ if (substring ("--force", arg) <= 0) -+ { -+ force = 1; -+ file = skip_to (0, arg); -+ } -+ -+ /* Open the file. */ -+ if (! grub_open (file)) -+ { -+ kernel_type = KERNEL_TYPE_NONE; -+ return 1; -+ } -+ -+ /* Read the first block. */ -+ if (grub_read ((char *) BOOTSEC_LOCATION, SECTOR_SIZE) != SECTOR_SIZE) -+ { -+ grub_close (); -+ kernel_type = KERNEL_TYPE_NONE; -+ -+ /* This below happens, if a file whose size is less than 512 bytes -+ is loaded. */ -+ if (errnum == ERR_NONE) -+ errnum = ERR_EXEC_FORMAT; -+ -+ return 1; -+ } -+ -+ /* If not loading it forcibly, check for the signature. */ -+ if (! force -+ && (*((unsigned short *) (BOOTSEC_LOCATION + BOOTSEC_SIG_OFFSET)) -+ != BOOTSEC_SIGNATURE)) -+ { -+ grub_close (); -+ errnum = ERR_EXEC_FORMAT; -+ kernel_type = KERNEL_TYPE_NONE; -+ return 1; -+ } -+ -+ grub_close (); -+ kernel_type = KERNEL_TYPE_CHAINLOADER; -+ -+ /* XXX: Windows evil hack. For now, only the first five letters are -+ checked. */ -+ if (IS_PC_SLICE_TYPE_FAT (current_slice) -+ && ! grub_memcmp ((char *) BOOTSEC_LOCATION + BOOTSEC_BPB_SYSTEM_ID, -+ "MSWIN", 5)) -+ *((unsigned long *) (BOOTSEC_LOCATION + BOOTSEC_BPB_HIDDEN_SECTORS)) -+ = part_start; -+ -+ errnum = ERR_NONE; -+ -+ return 0; -+} -+ -+static struct builtin builtin_chainloader = -+{ -+ "chainloader", -+ chainloader_func, -+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST, -+ "chainloader [--force] FILE", -+ "Load the chain-loader FILE. If --force is specified, then load it" -+ " forcibly, whether the boot loader signature is present or not." -+}; -+ -+ -+/* This function could be used to debug new filesystem code. Put a file -+ in the new filesystem and the same file in a well-tested filesystem. -+ Then, run "cmp" with the files. If no output is obtained, probably -+ the code is good, otherwise investigate what's wrong... */ -+/* cmp FILE1 FILE2 */ -+static int -+cmp_func (char *arg, int flags) -+{ -+ /* The filenames. */ -+ char *file1, *file2; -+ /* The addresses. */ -+ char *addr1, *addr2; -+ int i; -+ /* The size of the file. */ -+ int size; -+ -+ /* Get the filenames from ARG. */ -+ file1 = arg; -+ file2 = skip_to (0, arg); -+ if (! *file1 || ! *file2) -+ { -+ errnum = ERR_BAD_ARGUMENT; -+ return 1; -+ } -+ -+ /* Terminate the filenames for convenience. */ -+ nul_terminate (file1); -+ nul_terminate (file2); -+ -+ /* Read the whole data from FILE1. */ -+ addr1 = (char *) RAW_ADDR (0x100000); -+ if (! grub_open (file1)) -+ return 1; -+ -+ /* Get the size. */ -+ size = filemax; -+ if (grub_read (addr1, -1) != size) -+ { -+ grub_close (); -+ return 1; -+ } -+ -+ grub_close (); -+ -+ /* Read the whole data from FILE2. */ -+ addr2 = addr1 + size; -+ if (! grub_open (file2)) -+ return 1; -+ -+ /* Check if the size of FILE2 is equal to the one of FILE2. */ -+ if (size != filemax) -+ { -+ grub_printf ("Differ in size: 0x%x [%s], 0x%x [%s]\n", -+ size, file1, filemax, file2); -+ grub_close (); -+ return 0; -+ } -+ -+ if (! grub_read (addr2, -1)) -+ { -+ grub_close (); -+ return 1; -+ } -+ -+ grub_close (); -+ -+ /* Now compare ADDR1 with ADDR2. */ -+ for (i = 0; i < size; i++) -+ { -+ if (addr1[i] != addr2[i]) -+ grub_printf ("Differ at the offset %d: 0x%x [%s], 0x%x [%s]\n", -+ i, (unsigned) addr1[i], file1, -+ (unsigned) addr2[i], file2); -+ } -+ -+ return 0; -+} -+ -+static struct builtin builtin_cmp = -+{ -+ "cmp", -+ cmp_func, -+ BUILTIN_CMDLINE, -+ "cmp FILE1 FILE2", -+ "Compare the file FILE1 with the FILE2 and inform the different values" -+ " if any." -+}; -+ -+ -+/* color */ -+/* Set new colors used for the menu interface. Support two methods to -+ specify a color name: a direct integer representation and a symbolic -+ color name. An example of the latter is "blink-light-gray/blue". */ -+static int -+color_func (char *arg, int flags) -+{ -+ char *normal; -+ char *highlight; -+ int new_normal_color; -+ int new_highlight_color; -+ static char *color_list[16] = -+ { -+ "black", -+ "blue", -+ "green", -+ "cyan", -+ "red", -+ "magenta", -+ "brown", -+ "light-gray", -+ "dark-gray", -+ "light-blue", -+ "light-green", -+ "light-cyan", -+ "light-red", -+ "light-magenta", -+ "yellow", -+ "white" -+ }; -+ -+ /* Convert the color name STR into the magical number. */ -+ static int color_number (char *str) -+ { -+ char *ptr; -+ int i; -+ int color = 0; -+ -+ /* Find the separator. */ -+ for (ptr = str; *ptr && *ptr != '/'; ptr++) -+ ; -+ -+ /* If not found, return -1. */ -+ if (! *ptr) -+ return -1; -+ -+ /* Terminate the string STR. */ -+ *ptr++ = 0; -+ -+ /* If STR contains the prefix "blink-", then set the `blink' bit -+ in COLOR. */ -+ if (substring ("blink-", str) <= 0) -+ { -+ color = 0x80; -+ str += 6; -+ } -+ -+ /* Search for the color name. */ -+ for (i = 0; i < 16; i++) -+ if (grub_strcmp (color_list[i], str) == 0) -+ { -+ color |= i; -+ break; -+ } -+ -+ if (i == 16) -+ return -1; -+ -+ str = ptr; -+ nul_terminate (str); -+ -+ /* Search for the color name. */ -+ for (i = 0; i < 8; i++) -+ if (grub_strcmp (color_list[i], str) == 0) -+ { -+ color |= i << 4; -+ break; -+ } -+ -+ if (i == 8) -+ return -1; -+ -+ return color; -+ } -+ -+ normal = arg; -+ highlight = skip_to (0, arg); -+ -+ new_normal_color = color_number (normal); -+ if (new_normal_color < 0 && ! safe_parse_maxint (&normal, &new_normal_color)) -+ return 1; -+ -+ /* The second argument is optional, so set highlight_color -+ to inverted NORMAL_COLOR. */ -+ if (! *highlight) -+ new_highlight_color = ((new_normal_color >> 4) -+ | ((new_normal_color & 0xf) << 4)); -+ else -+ { -+ new_highlight_color = color_number (highlight); -+ if (new_highlight_color < 0 -+ && ! safe_parse_maxint (&highlight, &new_highlight_color)) -+ return 1; -+ } -+ -+ if (current_term->setcolor) -+ current_term->setcolor (new_normal_color, new_highlight_color); -+ -+ return 0; -+} -+ -+static struct builtin builtin_color = -+{ -+ "color", -+ color_func, -+ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, -+ "color NORMAL [HIGHLIGHT]", -+ "Change the menu colors. The color NORMAL is used for most" -+ " lines in the menu, and the color HIGHLIGHT is used to highlight the" -+ " line where the cursor points. If you omit HIGHLIGHT, then the" -+ " inverted color of NORMAL is used for the highlighted line." -+ " The format of a color is \"FG/BG\". FG and BG are symbolic color names." -+ " A symbolic color name must be one of these: black, blue, green," -+ " cyan, red, magenta, brown, light-gray, dark-gray, light-blue," -+ " light-green, light-cyan, light-red, light-magenta, yellow and white." -+ " But only the first eight names can be used for BG. You can prefix" -+ " \"blink-\" to FG if you want a blinking foreground color." -+}; -+ -+ -+/* configfile */ -+static int -+configfile_func (char *arg, int flags) -+{ -+ char *new_config = config_file; -+ -+ /* Check if the file ARG is present. */ -+ if (! grub_open (arg)) -+ return 1; -+ -+ grub_close (); -+ -+ /* Copy ARG to CONFIG_FILE. */ -+ while ((*new_config++ = *arg++) != 0) -+ ; -+ -+#ifdef GRUB_UTIL -+ /* Force to load the configuration file. */ -+ use_config_file = 1; -+#endif -+ -+ /* Make sure that the user will not be authoritative. */ -+ auth = 0; -+ -+ /* Restart cmain. */ -+ grub_longjmp (restart_env, 0); -+ -+ /* Never reach here. */ -+ return 0; -+} -+ -+static struct builtin builtin_configfile = -+{ -+ "configfile", -+ configfile_func, -+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST, -+ "configfile FILE", -+ "Load FILE as the configuration file." -+}; -+ -+ -+/* debug */ -+static int -+debug_func (char *arg, int flags) -+{ -+ if (debug) -+ { -+ debug = 0; -+ grub_printf (" Debug mode is turned off\n"); -+ } -+ else -+ { -+ debug = 1; -+ grub_printf (" Debug mode is turned on\n"); -+ } -+ -+ return 0; -+} -+ -+static struct builtin builtin_debug = -+{ -+ "debug", -+ debug_func, -+ BUILTIN_CMDLINE, -+ "debug", -+ "Turn on/off the debug mode." -+}; -+ -+ -+/* default */ -+static int -+default_func (char *arg, int flags) -+{ -+#ifndef SUPPORT_DISKLESS -+ if (grub_strcmp (arg, "saved") == 0) -+ { -+ default_entry = saved_entryno; -+ return 0; -+ } -+#endif /* SUPPORT_DISKLESS */ -+ -+ if (! safe_parse_maxint (&arg, &default_entry)) -+ return 1; -+ -+ return 0; -+} -+ -+static struct builtin builtin_default = -+{ -+ "default", -+ default_func, -+ BUILTIN_MENU, -+#if 0 -+ "default [NUM | `saved']", -+ "Set the default entry to entry number NUM (if not specified, it is" -+ " 0, the first entry) or the entry number saved by savedefault." -+#endif -+}; -+ -+ -+#ifdef GRUB_UTIL -+/* device */ -+static int -+device_func (char *arg, int flags) -+{ -+ char *drive = arg; -+ char *device; -+ -+ /* Get the drive number from DRIVE. */ -+ if (! set_device (drive)) -+ return 1; -+ -+ /* Get the device argument. */ -+ device = skip_to (0, drive); -+ -+ /* Terminate DEVICE. */ -+ nul_terminate (device); -+ -+ if (! *device || ! check_device (device)) -+ { -+ errnum = ERR_FILE_NOT_FOUND; -+ return 1; -+ } -+ -+ assign_device_name (current_drive, device); -+ -+ return 0; -+} -+ -+static struct builtin builtin_device = -+{ -+ "device", -+ device_func, -+ BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST, -+ "device DRIVE DEVICE", -+ "Specify DEVICE as the actual drive for a BIOS drive DRIVE. This command" -+ " can be used only in the grub shell." -+}; -+#endif /* GRUB_UTIL */ -+ -+ -+#ifdef SUPPORT_NETBOOT -+/* dhcp */ -+static int -+dhcp_func (char *arg, int flags) -+{ -+ /* For now, this is an alias for bootp. */ -+ return bootp_func (arg, flags); -+} -+ -+static struct builtin builtin_dhcp = -+{ -+ "dhcp", -+ dhcp_func, -+ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, -+ "dhcp", -+ "Initialize a network device via DHCP." -+}; -+#endif /* SUPPORT_NETBOOT */ -+ -+ -+/* displayapm */ -+static int -+displayapm_func (char *arg, int flags) -+{ -+ if (mbi.flags & MB_INFO_APM_TABLE) -+ { -+ grub_printf ("APM BIOS information:\n" -+ " Version: 0x%x\n" -+ " 32-bit CS: 0x%x\n" -+ " Offset: 0x%x\n" -+ " 16-bit CS: 0x%x\n" -+ " 16-bit DS: 0x%x\n" -+ " 32-bit CS length: 0x%x\n" -+ " 16-bit CS length: 0x%x\n" -+ " 16-bit DS length: 0x%x\n", -+ (unsigned) apm_bios_info.version, -+ (unsigned) apm_bios_info.cseg, -+ apm_bios_info.offset, -+ (unsigned) apm_bios_info.cseg_16, -+ (unsigned) apm_bios_info.dseg_16, -+ (unsigned) apm_bios_info.cseg_len, -+ (unsigned) apm_bios_info.cseg_16_len, -+ (unsigned) apm_bios_info.dseg_16_len); -+ } -+ else -+ { -+ grub_printf ("No APM BIOS found or probe failed\n"); -+ } -+ -+ return 0; -+} -+ -+static struct builtin builtin_displayapm = -+{ -+ "displayapm", -+ displayapm_func, -+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST, -+ "displayapm", -+ "Display APM BIOS information." -+}; -+ -+ -+/* displaymem */ -+static int -+displaymem_func (char *arg, int flags) -+{ -+ if (get_eisamemsize () != -1) -+ grub_printf (" EISA Memory BIOS Interface is present\n"); -+ if (get_mmap_entry ((void *) SCRATCHADDR, 0) != 0 -+ || *((int *) SCRATCHADDR) != 0) -+ grub_printf (" Address Map BIOS Interface is present\n"); -+ -+ grub_printf (" Lower memory: %uK, " -+ "Upper memory (to first chipset hole): %uK\n", -+ mbi.mem_lower, mbi.mem_upper); -+ -+ if (mbi.flags & MB_INFO_MEM_MAP) -+ { -+ struct AddrRangeDesc *map = (struct AddrRangeDesc *) mbi.mmap_addr; -+ int end_addr = mbi.mmap_addr + mbi.mmap_length; -+ -+ grub_printf (" [Address Range Descriptor entries " -+ "immediately follow (values are 64-bit)]\n"); -+ while (end_addr > (int) map) -+ { -+ char *str; -+ -+ if (map->Type == MB_ARD_MEMORY) -+ str = "Usable RAM"; -+ else -+ str = "Reserved"; -+ grub_printf (" %s: Base Address: 0x%x X 4GB + 0x%x,\n" -+ " Length: 0x%x X 4GB + 0x%x bytes\n", -+ str, -+ (unsigned long) (map->BaseAddr >> 32), -+ (unsigned long) (map->BaseAddr & 0xFFFFFFFF), -+ (unsigned long) (map->Length >> 32), -+ (unsigned long) (map->Length & 0xFFFFFFFF)); -+ -+ map = ((struct AddrRangeDesc *) (((int) map) + 4 + map->size)); -+ } -+ } -+ -+ return 0; -+} -+ -+static struct builtin builtin_displaymem = -+{ -+ "displaymem", -+ displaymem_func, -+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST, -+ "displaymem", -+ "Display what GRUB thinks the system address space map of the" -+ " machine is, including all regions of physical RAM installed." -+}; -+ -+ -+/* dump FROM TO */ -+#ifdef GRUB_UTIL -+static int -+dump_func (char *arg, int flags) -+{ -+ char *from, *to; -+ FILE *fp; -+ char c; -+ -+ from = arg; -+ to = skip_to (0, arg); -+ if (! *from || ! *to) -+ { -+ errnum = ERR_BAD_ARGUMENT; -+ return 1; -+ } -+ -+ nul_terminate (from); -+ nul_terminate (to); -+ -+ if (! grub_open (from)) -+ return 1; -+ -+ fp = fopen (to, "w"); -+ if (! fp) -+ { -+ errnum = ERR_WRITE; -+ return 1; -+ } -+ -+ while (grub_read (&c, 1)) -+ if (fputc (c, fp) == EOF) -+ { -+ errnum = ERR_WRITE; -+ fclose (fp); -+ return 1; -+ } -+ -+ if (fclose (fp) == EOF) -+ { -+ errnum = ERR_WRITE; -+ return 1; -+ } -+ -+ grub_close (); -+ return 0; -+} -+ -+static struct builtin builtin_dump = -+ { -+ "dump", -+ dump_func, -+ BUILTIN_CMDLINE, -+ "dump FROM TO", -+ "Dump the contents of the file FROM to the file TO. FROM must be" -+ " a GRUB file and TO must be an OS file." -+ }; -+#endif /* GRUB_UTIL */ -+ -+ -+static char embed_info[32]; -+/* embed */ -+/* Embed a Stage 1.5 in the first cylinder after MBR or in the -+ bootloader block in a FFS. */ -+static int -+embed_func (char *arg, int flags) -+{ -+ char *stage1_5; -+ char *device; -+ char *stage1_5_buffer = (char *) RAW_ADDR (0x100000); -+ int len, size; -+ int sector; -+ -+ stage1_5 = arg; -+ device = skip_to (0, stage1_5); -+ -+ /* Open a Stage 1.5. */ -+ if (! grub_open (stage1_5)) -+ return 1; -+ -+ /* Read the whole of the Stage 1.5. */ -+ len = grub_read (stage1_5_buffer, -1); -+ grub_close (); -+ -+ if (errnum) -+ return 1; -+ -+ size = (len + SECTOR_SIZE - 1) / SECTOR_SIZE; -+ -+ /* Get the device where the Stage 1.5 will be embedded. */ -+ set_device (device); -+ if (errnum) -+ return 1; -+ -+ if (current_partition == 0xFFFFFF) -+ { -+ /* Embed it after the MBR. */ -+ -+ char mbr[SECTOR_SIZE]; -+ char ezbios_check[2*SECTOR_SIZE]; -+ int i; -+ -+ /* Open the partition. */ -+ if (! open_partition ()) -+ return 1; -+ -+ /* No floppy has MBR. */ -+ if (! (current_drive & 0x80)) -+ { -+ errnum = ERR_DEV_VALUES; -+ return 1; -+ } -+ -+ /* Read the MBR of CURRENT_DRIVE. */ -+ if (! rawread (current_drive, PC_MBR_SECTOR, 0, SECTOR_SIZE, mbr)) -+ return 1; -+ -+ /* Sanity check. */ -+ if (! PC_MBR_CHECK_SIG (mbr)) -+ { -+ errnum = ERR_BAD_PART_TABLE; -+ return 1; -+ } -+ -+ /* Check if the disk can store the Stage 1.5. */ -+ for (i = 0; i < 4; i++) -+ if (PC_SLICE_TYPE (mbr, i) && PC_SLICE_START (mbr, i) - 1 < size) -+ { -+ errnum = ERR_NO_DISK_SPACE; -+ return 1; -+ } -+ -+ /* Check for EZ-BIOS signature. It should be in the third -+ * sector, but due to remapping it can appear in the second, so -+ * load and check both. -+ */ -+ if (! rawread (current_drive, 1, 0, 2 * SECTOR_SIZE, ezbios_check)) -+ return 1; -+ -+ if (! memcmp (ezbios_check + 3, "AERMH", 5) -+ || ! memcmp (ezbios_check + 512 + 3, "AERMH", 5)) -+ { -+ /* The space after the MBR is used by EZ-BIOS which we must -+ * not overwrite. -+ */ -+ errnum = ERR_NO_DISK_SPACE; -+ return 1; -+ } -+ -+ sector = 1; -+ } -+ else -+ { -+ /* Embed it in the bootloader block in the filesystem. */ -+ int start_sector; -+ -+ /* Open the partition. */ -+ if (! open_device ()) -+ return 1; -+ -+ /* Check if the current slice supports embedding. */ -+ if (fsys_table[fsys_type].embed_func == 0 -+ || ! fsys_table[fsys_type].embed_func (&start_sector, size)) -+ { -+ errnum = ERR_DEV_VALUES; -+ return 1; -+ } -+ -+ sector = part_start + start_sector; -+ } -+ -+ /* Clear the cache. */ -+ buf_track = -1; -+ -+ /* Now perform the embedding. */ -+ if (! devwrite (sector - part_start, size, stage1_5_buffer)) -+ return 1; -+ -+ grub_printf (" %d sectors are embedded.\n", size); -+ grub_sprintf (embed_info, "%d+%d", sector - part_start, size); -+ return 0; -+} -+ -+static struct builtin builtin_embed = -+{ -+ "embed", -+ embed_func, -+ BUILTIN_CMDLINE, -+ "embed STAGE1_5 DEVICE", -+ "Embed the Stage 1.5 STAGE1_5 in the sectors after MBR if DEVICE" -+ " is a drive, or in the \"bootloader\" area if DEVICE is a FFS partition." -+ " Print the number of sectors which STAGE1_5 occupies if successful." -+}; -+ -+ -+/* fallback */ -+static int -+fallback_func (char *arg, int flags) -+{ -+ if (! safe_parse_maxint (&arg, &fallback_entry)) -+ return 1; -+ -+ return 0; -+} -+ -+static struct builtin builtin_fallback = -+{ -+ "fallback", -+ fallback_func, -+ BUILTIN_MENU, -+#if 0 -+ "fallback NUM", -+ "Go into unattended boot mode: if the default boot entry has any" -+ " errors, instead of waiting for the user to do anything, it" -+ " immediately starts over using the NUM entry (same numbering as the" -+ " `default' command). This obviously won't help if the machine" -+ " was rebooted by a kernel that GRUB loaded." -+#endif -+}; -+ -+ -+/* find */ -+/* Search for the filename ARG in all of partitions. */ -+static int -+find_func (char *arg, int flags) -+{ -+ char *filename = arg; -+ unsigned long drive; -+ unsigned long tmp_drive = saved_drive; -+ unsigned long tmp_partition = saved_partition; -+ int got_file = 0; -+ -+ /* Floppies. */ -+ for (drive = 0; drive < 8; drive++) -+ { -+ current_drive = drive; -+ current_partition = 0xFFFFFF; -+ -+ if (open_device ()) -+ { -+ saved_drive = current_drive; -+ saved_partition = current_partition; -+ if (grub_open (filename)) -+ { -+ grub_close (); -+ grub_printf (" (fd%d)\n", drive); -+ got_file = 1; -+ } -+ } -+ -+ errnum = ERR_NONE; -+ } -+ -+ /* Hard disks. */ -+ for (drive = 0x80; drive < 0x88; drive++) -+ { -+ unsigned long part = 0xFFFFFF; -+ unsigned long start, len, offset, ext_offset; -+ int type, entry; -+ char buf[SECTOR_SIZE]; -+ -+ current_drive = drive; -+ while (next_partition (drive, 0xFFFFFF, &part, &type, -+ &start, &len, &offset, &entry, -+ &ext_offset, buf)) -+ { -+ if (type != PC_SLICE_TYPE_NONE -+ && ! IS_PC_SLICE_TYPE_BSD (type) -+ && ! IS_PC_SLICE_TYPE_EXTENDED (type)) -+ { -+ current_partition = part; -+ if (open_device ()) -+ { -+ saved_drive = current_drive; -+ saved_partition = current_partition; -+ if (grub_open (filename)) -+ { -+ int bsd_part = (part >> 8) & 0xFF; -+ int pc_slice = part >> 16; -+ -+ grub_close (); -+ -+ if (bsd_part == 0xFF) -+ grub_printf (" (hd%d,%d)\n", -+ drive - 0x80, pc_slice); -+ else -+ grub_printf (" (hd%d,%d,%c)\n", -+ drive - 0x80, pc_slice, bsd_part + 'a'); -+ -+ got_file = 1; -+ } -+ } -+ } -+ -+ /* We want to ignore any error here. */ -+ errnum = ERR_NONE; -+ } -+ -+ /* next_partition always sets ERRNUM in the last call, so clear -+ it. */ -+ errnum = ERR_NONE; -+ } -+ -+ saved_drive = tmp_drive; -+ saved_partition = tmp_partition; -+ -+ if (got_file) -+ { -+ errnum = ERR_NONE; -+ return 0; -+ } -+ -+ errnum = ERR_FILE_NOT_FOUND; -+ return 1; -+} -+ -+static struct builtin builtin_find = -+{ -+ "find", -+ find_func, -+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST, -+ "find FILENAME", -+ "Search for the filename FILENAME in all of partitions and print the list of" -+ " the devices which contain the file." -+}; -+ -+ -+/* fstest */ -+static int -+fstest_func (char *arg, int flags) -+{ -+ if (disk_read_hook) -+ { -+ disk_read_hook = NULL; -+ printf (" Filesystem tracing is now off\n"); -+ } -+ else -+ { -+ disk_read_hook = disk_read_print_func; -+ printf (" Filesystem tracing is now on\n"); -+ } -+ -+ return 0; -+} -+ -+static struct builtin builtin_fstest = -+{ -+ "fstest", -+ fstest_func, -+ BUILTIN_CMDLINE, -+ "fstest", -+ "Toggle filesystem test mode." -+}; -+ -+ -+/* geometry */ -+static int -+geometry_func (char *arg, int flags) -+{ -+ struct geometry geom; -+ char *msg; -+ char *device = arg; -+#ifdef GRUB_UTIL -+ char *ptr; -+#endif -+ -+ /* Get the device number. */ -+ set_device (device); -+ if (errnum) -+ return 1; -+ -+ /* Check for the geometry. */ -+ if (get_diskinfo (current_drive, &geom)) -+ { -+ errnum = ERR_NO_DISK; -+ return 1; -+ } -+ -+ /* Attempt to read the first sector, because some BIOSes turns out not -+ to support LBA even though they set the bit 0 in the support -+ bitmap, only after reading something actually. */ -+ if (biosdisk (BIOSDISK_READ, current_drive, &geom, 0, 1, SCRATCHSEG)) -+ { -+ errnum = ERR_READ; -+ return 1; -+ } -+ -+#ifdef GRUB_UTIL -+ ptr = skip_to (0, device); -+ if (*ptr) -+ { -+ char *cylinder, *head, *sector, *total_sector; -+ int num_cylinder, num_head, num_sector, num_total_sector; -+ -+ cylinder = ptr; -+ head = skip_to (0, cylinder); -+ sector = skip_to (0, head); -+ total_sector = skip_to (0, sector); -+ if (! safe_parse_maxint (&cylinder, &num_cylinder) -+ || ! safe_parse_maxint (&head, &num_head) -+ || ! safe_parse_maxint (§or, &num_sector)) -+ return 1; -+ -+ disks[current_drive].cylinders = num_cylinder; -+ disks[current_drive].heads = num_head; -+ disks[current_drive].sectors = num_sector; -+ -+ if (safe_parse_maxint (&total_sector, &num_total_sector)) -+ disks[current_drive].total_sectors = num_total_sector; -+ else -+ disks[current_drive].total_sectors -+ = num_cylinder * num_head * num_sector; -+ errnum = 0; -+ -+ geom = disks[current_drive]; -+ buf_drive = -1; -+ } -+#endif /* GRUB_UTIL */ -+ -+#ifdef GRUB_UTIL -+ msg = device_map[current_drive]; -+#else -+ if (geom.flags & BIOSDISK_FLAG_LBA_EXTENSION) -+ msg = "LBA"; -+ else -+ msg = "CHS"; -+#endif -+ -+ grub_printf ("drive 0x%x: C/H/S = %d/%d/%d, " -+ "The number of sectors = %d, %s\n", -+ current_drive, -+ geom.cylinders, geom.heads, geom.sectors, -+ geom.total_sectors, msg); -+ real_open_partition (1); -+ -+ return 0; -+} -+ -+static struct builtin builtin_geometry = -+{ -+ "geometry", -+ geometry_func, -+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST, -+ "geometry DRIVE [CYLINDER HEAD SECTOR [TOTAL_SECTOR]]", -+ "Print the information for a drive DRIVE. In the grub shell, you can" -+ " set the geometry of the drive arbitrarily. The number of the cylinders," -+ " the one of the heads, the one of the sectors and the one of the total" -+ " sectors are set to CYLINDER, HEAD, SECTOR and TOTAL_SECTOR," -+ " respectively. If you omit TOTAL_SECTOR, then it will be calculated based" -+ " on the C/H/S values automatically." -+}; -+ -+ -+/* halt */ -+static int -+halt_func (char *arg, int flags) -+{ -+ int no_apm; -+ -+ no_apm = (grub_memcmp (arg, "--no-apm", 8) == 0); -+ grub_halt (no_apm); -+ -+ /* Never reach here. */ -+ return 1; -+} -+ -+static struct builtin builtin_halt = -+{ -+ "halt", -+ halt_func, -+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST, -+ "halt [--no-apm]", -+ "Halt your system. If APM is avaiable on it, turn off the power using" -+ " the APM BIOS, unless you specify the option `--no-apm'." -+}; -+ -+ -+/* help */ -+#define MAX_SHORT_DOC_LEN 39 -+#define MAX_LONG_DOC_LEN 66 -+ -+static int -+help_func (char *arg, int flags) -+{ -+ int all = 0; -+ -+ if (grub_memcmp (arg, "--all", sizeof ("--all") - 1) == 0) -+ { -+ all = 1; -+ arg = skip_to (0, arg); -+ } -+ -+ if (! *arg) -+ { -+ /* Invoked with no argument. Print the list of the short docs. */ -+ struct builtin **builtin; -+ int left = 1; -+ -+ for (builtin = builtin_table; *builtin != 0; builtin++) -+ { -+ int len; -+ int i; -+ -+ /* If this cannot be used in the command-line interface, -+ skip this. */ -+ if (! ((*builtin)->flags & BUILTIN_CMDLINE)) -+ continue; -+ -+ /* If this doesn't need to be listed automatically and "--all" -+ is not specified, skip this. */ -+ if (! all && ! ((*builtin)->flags & BUILTIN_HELP_LIST)) -+ continue; -+ -+ len = grub_strlen ((*builtin)->short_doc); -+ /* If the length of SHORT_DOC is too long, truncate it. */ -+ if (len > MAX_SHORT_DOC_LEN - 1) -+ len = MAX_SHORT_DOC_LEN - 1; -+ -+ for (i = 0; i < len; i++) -+ grub_putchar ((*builtin)->short_doc[i]); -+ -+ for (; i < MAX_SHORT_DOC_LEN; i++) -+ grub_putchar (' '); -+ -+ if (! left) -+ grub_putchar ('\n'); -+ -+ left = ! left; -+ } -+ -+ /* If the last entry was at the left column, no newline was printed -+ at the end. */ -+ if (! left) -+ grub_putchar ('\n'); -+ } -+ else -+ { -+ /* Invoked with one or more patterns. */ -+ do -+ { -+ struct builtin **builtin; -+ char *next_arg; -+ -+ /* Get the next argument. */ -+ next_arg = skip_to (0, arg); -+ -+ /* Terminate ARG. */ -+ nul_terminate (arg); -+ -+ for (builtin = builtin_table; *builtin; builtin++) -+ { -+ /* Skip this if this is only for the configuration file. */ -+ if (! ((*builtin)->flags & BUILTIN_CMDLINE)) -+ continue; -+ -+ if (substring (arg, (*builtin)->name) < 1) -+ { -+ char *doc = (*builtin)->long_doc; -+ -+ /* At first, print the name and the short doc. */ -+ grub_printf ("%s: %s\n", -+ (*builtin)->name, (*builtin)->short_doc); -+ -+ /* Print the long doc. */ -+ while (*doc) -+ { -+ int len = grub_strlen (doc); -+ int i; -+ -+ /* If LEN is too long, fold DOC. */ -+ if (len > MAX_LONG_DOC_LEN) -+ { -+ /* Fold this line at the position of a space. */ -+ for (len = MAX_LONG_DOC_LEN; len > 0; len--) -+ if (doc[len - 1] == ' ') -+ break; -+ } -+ -+ grub_printf (" "); -+ for (i = 0; i < len; i++) -+ grub_putchar (*doc++); -+ grub_putchar ('\n'); -+ } -+ } -+ } -+ -+ arg = next_arg; -+ } -+ while (*arg); -+ } -+ -+ return 0; -+} -+ -+static struct builtin builtin_help = -+{ -+ "help", -+ help_func, -+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST, -+ "help [--all] [PATTERN ...]", -+ "Display helpful information about builtin commands. Not all commands" -+ " aren't shown without the option `--all'." -+}; -+ -+ -+/* hiddenmenu */ -+static int -+hiddenmenu_func (char *arg, int flags) -+{ -+ show_menu = 0; -+ return 0; -+} -+ -+static struct builtin builtin_hiddenmenu = -+{ -+ "hiddenmenu", -+ hiddenmenu_func, -+ BUILTIN_MENU, -+#if 0 -+ "hiddenmenu", -+ "Hide the menu." -+#endif -+}; -+ -+ -+/* hide */ -+static int -+hide_func (char *arg, int flags) -+{ -+ if (! set_device (arg)) -+ return 1; -+ -+ if (! set_partition_hidden_flag (1)) -+ return 1; -+ -+ return 0; -+} -+ -+static struct builtin builtin_hide = -+{ -+ "hide", -+ hide_func, -+ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, -+ "hide PARTITION", -+ "Hide PARTITION by setting the \"hidden\" bit in" -+ " its partition type code." -+}; -+ -+ -+#ifdef SUPPORT_NETBOOT -+/* ifconfig */ -+static int -+ifconfig_func (char *arg, int flags) -+{ -+ char *svr = 0, *ip = 0, *gw = 0, *sm = 0; -+ -+ if (! eth_probe ()) -+ { -+ grub_printf ("No ethernet card found.\n"); -+ errnum = ERR_DEV_VALUES; -+ return 1; -+ } -+ -+ while (*arg) -+ { -+ if (! grub_memcmp ("--server=", arg, sizeof ("--server=") - 1)) -+ svr = arg + sizeof("--server=") - 1; -+ else if (! grub_memcmp ("--address=", arg, sizeof ("--address=") - 1)) -+ ip = arg + sizeof ("--address=") - 1; -+ else if (! grub_memcmp ("--gateway=", arg, sizeof ("--gateway=") - 1)) -+ gw = arg + sizeof ("--gateway=") - 1; -+ else if (! grub_memcmp ("--mask=", arg, sizeof("--mask=") - 1)) -+ sm = arg + sizeof ("--mask=") - 1; -+ else -+ { -+ errnum = ERR_BAD_ARGUMENT; -+ return 1; -+ } -+ -+ arg = skip_to (0, arg); -+ } -+ -+ if (! ifconfig (ip, sm, gw, svr)) -+ { -+ errnum = ERR_BAD_ARGUMENT; -+ return 1; -+ } -+ -+ print_network_configuration (); -+ return 0; -+} -+ -+static struct builtin builtin_ifconfig = -+{ -+ "ifconfig", -+ ifconfig_func, -+ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, -+ "ifconfig [--address=IP] [--gateway=IP] [--mask=MASK] [--server=IP]", -+ "Configure the IP address, the netmask, the gateway and the server" -+ " address or print current network configuration." -+}; -+#endif /* SUPPORT_NETBOOT */ -+ -+ -+/* impsprobe */ -+static int -+impsprobe_func (char *arg, int flags) -+{ -+#ifdef GRUB_UTIL -+ /* In the grub shell, we cannot probe IMPS. */ -+ errnum = ERR_UNRECOGNIZED; -+ return 1; -+#else /* ! GRUB_UTIL */ -+ if (!imps_probe ()) -+ printf (" No MPS information found or probe failed\n"); -+ -+ return 0; -+#endif /* ! GRUB_UTIL */ -+} -+ -+static struct builtin builtin_impsprobe = -+{ -+ "impsprobe", -+ impsprobe_func, -+ BUILTIN_CMDLINE, -+ "impsprobe", -+ "Probe the Intel Multiprocessor Specification 1.1 or 1.4" -+ " configuration table and boot the various CPUs which are found into" -+ " a tight loop." -+}; -+ -+ -+/* initrd */ -+static int -+initrd_func (char *arg, int flags) -+{ -+ switch (kernel_type) -+ { -+ case KERNEL_TYPE_LINUX: -+ case KERNEL_TYPE_BIG_LINUX: -+ if (! load_initrd (arg)) -+ return 1; -+ break; -+ -+ default: -+ errnum = ERR_NEED_LX_KERNEL; -+ return 1; -+ } -+ -+ return 0; -+} -+ -+static struct builtin builtin_initrd = -+{ -+ "initrd", -+ initrd_func, -+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST, -+ "initrd FILE [ARG ...]", -+ "Load an initial ramdisk FILE for a Linux format boot image and set the" -+ " appropriate parameters in the Linux setup area in memory." -+}; -+ -+ -+/* install */ -+static int -+install_func (char *arg, int flags) -+{ -+ char *stage1_file, *dest_dev, *file, *addr; -+ char *stage1_buffer = (char *) RAW_ADDR (0x100000); -+ char *stage2_buffer = stage1_buffer + SECTOR_SIZE; -+ char *old_sect = stage2_buffer + SECTOR_SIZE; -+ char *stage2_first_buffer = old_sect + SECTOR_SIZE; -+ char *stage2_second_buffer = stage2_first_buffer + SECTOR_SIZE; -+ /* XXX: Probably SECTOR_SIZE is reasonable. */ -+ char *config_filename = stage2_second_buffer + SECTOR_SIZE; -+ char *dummy = config_filename + SECTOR_SIZE; -+ int new_drive = 0xFF; -+ int dest_drive, dest_partition, dest_sector; -+ int src_drive, src_partition, src_part_start; -+ int i; -+ struct geometry dest_geom, src_geom; -+ int saved_sector; -+ int stage2_first_sector, stage2_second_sector; -+ char *ptr; -+ int installaddr, installlist; -+ /* Point to the location of the name of a configuration file in Stage 2. */ -+ char *config_file_location; -+ /* If FILE is a Stage 1.5? */ -+ int is_stage1_5 = 0; -+ /* Must call grub_close? */ -+ int is_open = 0; -+ /* If LBA is forced? */ -+ int is_force_lba = 0; -+ /* Was the last sector full? */ -+ int last_length = SECTOR_SIZE; -+ -+#ifdef GRUB_UTIL -+ /* If the Stage 2 is in a partition mounted by an OS, this will store -+ the filename under the OS. */ -+ char *stage2_os_file = 0; -+#endif /* GRUB_UTIL */ -+ -+ /* Save the first sector of Stage2 in STAGE2_SECT. */ -+ static void disk_read_savesect_func (int sector, int offset, int length) -+ { -+ if (debug) -+ printf ("[%d]", sector); -+ -+ /* ReiserFS has files which sometimes contain data not aligned -+ on sector boundaries. Returning an error is better than -+ silently failing. */ -+ if (offset != 0 || length != SECTOR_SIZE) -+ errnum = ERR_UNALIGNED; -+ -+ saved_sector = sector; -+ } -+ -+ /* Write SECTOR to INSTALLLIST, and update INSTALLADDR and -+ INSTALLSECT. */ -+ static void disk_read_blocklist_func (int sector, int offset, int length) -+ { -+ if (debug) -+ printf("[%d]", sector); -+ -+ if (offset != 0 || last_length != SECTOR_SIZE) -+ { -+ /* We found a non-sector-aligned data block. */ -+ errnum = ERR_UNALIGNED; -+ return; -+ } -+ -+ last_length = length; -+ -+ if (*((unsigned long *) (installlist - 4)) -+ + *((unsigned short *) installlist) != sector -+ || installlist == (int) stage2_first_buffer + SECTOR_SIZE + 4) -+ { -+ installlist -= 8; -+ -+ if (*((unsigned long *) (installlist - 8))) -+ errnum = ERR_WONT_FIT; -+ else -+ { -+ *((unsigned short *) (installlist + 2)) = (installaddr >> 4); -+ *((unsigned long *) (installlist - 4)) = sector; -+ } -+ } -+ -+ *((unsigned short *) installlist) += 1; -+ installaddr += 512; -+ } -+ -+ /* First, check the GNU-style long option. */ -+ while (1) -+ { -+ if (grub_memcmp ("--force-lba", arg, sizeof ("--force-lba") - 1) == 0) -+ { -+ is_force_lba = 1; -+ arg = skip_to (0, arg); -+ } -+#ifdef GRUB_UTIL -+ else if (grub_memcmp ("--stage2=", arg, sizeof ("--stage2=") - 1) == 0) -+ { -+ stage2_os_file = arg + sizeof ("--stage2=") - 1; -+ arg = skip_to (0, arg); -+ nul_terminate (stage2_os_file); -+ } -+#endif /* GRUB_UTIL */ -+ else -+ break; -+ } -+ -+ stage1_file = arg; -+ dest_dev = skip_to (0, stage1_file); -+ if (*dest_dev == 'd') -+ { -+ new_drive = 0; -+ dest_dev = skip_to (0, dest_dev); -+ } -+ file = skip_to (0, dest_dev); -+ addr = skip_to (0, file); -+ -+ /* Get the installation address. */ -+ if (! safe_parse_maxint (&addr, &installaddr)) -+ { -+ /* ADDR is not specified. */ -+ installaddr = 0; -+ ptr = addr; -+ errnum = 0; -+ } -+ else -+ ptr = skip_to (0, addr); -+ -+#ifndef NO_DECOMPRESSION -+ /* Do not decompress Stage 1 or Stage 2. */ -+ no_decompression = 1; -+#endif -+ -+ /* Read Stage 1. */ -+ is_open = grub_open (stage1_file); -+ if (! is_open -+ || ! grub_read (stage1_buffer, SECTOR_SIZE) == SECTOR_SIZE) -+ goto fail; -+ -+ /* Read the old sector from DEST_DEV. */ -+ if (! set_device (dest_dev) -+ || ! open_partition () -+ || ! devread (0, 0, SECTOR_SIZE, old_sect)) -+ goto fail; -+ -+ /* Store the information for the destination device. */ -+ dest_drive = current_drive; -+ dest_partition = current_partition; -+ dest_geom = buf_geom; -+ dest_sector = part_start; -+ -+ /* Copy the possible DOS BPB, 59 bytes at byte offset 3. */ -+ grub_memmove (stage1_buffer + BOOTSEC_BPB_OFFSET, -+ old_sect + BOOTSEC_BPB_OFFSET, -+ BOOTSEC_BPB_LENGTH); -+ -+ /* If for a hard disk, copy the possible MBR/extended part table. */ -+ if (dest_drive & 0x80) -+ grub_memmove (stage1_buffer + STAGE1_WINDOWS_NT_MAGIC, -+ old_sect + STAGE1_WINDOWS_NT_MAGIC, -+ STAGE1_PARTEND - STAGE1_WINDOWS_NT_MAGIC); -+ -+ /* Check for the version and the signature of Stage 1. */ -+ if (*((short *)(stage1_buffer + STAGE1_VER_MAJ_OFFS)) != COMPAT_VERSION -+ || (*((unsigned short *) (stage1_buffer + BOOTSEC_SIG_OFFSET)) -+ != BOOTSEC_SIGNATURE)) -+ { -+ errnum = ERR_BAD_VERSION; -+ goto fail; -+ } -+ -+ /* This below is not true any longer. But should we leave this alone? */ -+ -+ /* If DEST_DRIVE is a floppy, Stage 2 must have the iteration probe -+ routine. */ -+ if (! (dest_drive & 0x80) -+ && (*((unsigned char *) (stage1_buffer + BOOTSEC_PART_OFFSET)) == 0x80 -+ || stage1_buffer[BOOTSEC_PART_OFFSET] == 0)) -+ { -+ errnum = ERR_BAD_VERSION; -+ goto fail; -+ } -+ -+ grub_close (); -+ -+ /* Open Stage 2. */ -+ is_open = grub_open (file); -+ if (! is_open) -+ goto fail; -+ -+ src_drive = current_drive; -+ src_partition = current_partition; -+ src_part_start = part_start; -+ src_geom = buf_geom; -+ -+ if (! new_drive) -+ new_drive = src_drive; -+ else if (src_drive != dest_drive) -+ grub_printf ("Warning: the option `d' was not used, but the Stage 1 will" -+ " be installed on a\ndifferent drive than the drive where" -+ " the Stage 2 resides.\n"); -+ -+ /* Set the boot drive. */ -+ *((unsigned char *) (stage1_buffer + STAGE1_BOOT_DRIVE)) = new_drive; -+ -+ /* Set the "force LBA" flag. */ -+ *((unsigned char *) (stage1_buffer + STAGE1_FORCE_LBA)) = is_force_lba; -+ -+ /* Set the boot drive mask. This is a workaround for buggy BIOSes which -+ don't pass boot drive correctly. Instead, they pass 0x00 even when -+ booted from 0x80. */ -+ *((unsigned char *) (stage1_buffer + STAGE1_BOOT_DRIVE_MASK)) -+ = (dest_drive & BIOS_FLAG_FIXED_DISK); -+ -+ /* Read the first sector of Stage 2. */ -+ disk_read_hook = disk_read_savesect_func; -+ if (grub_read (stage2_first_buffer, SECTOR_SIZE) != SECTOR_SIZE) -+ goto fail; -+ -+ stage2_first_sector = saved_sector; -+ -+ /* Read the second sector of Stage 2. */ -+ if (grub_read (stage2_second_buffer, SECTOR_SIZE) != SECTOR_SIZE) -+ goto fail; -+ -+ stage2_second_sector = saved_sector; -+ -+ /* Check for the version of Stage 2. */ -+ if (*((short *) (stage2_second_buffer + STAGE2_VER_MAJ_OFFS)) -+ != COMPAT_VERSION) -+ { -+ errnum = ERR_BAD_VERSION; -+ goto fail; -+ } -+ -+ /* Check for the Stage 2 id. */ -+ if (stage2_second_buffer[STAGE2_STAGE2_ID] != STAGE2_ID_STAGE2) -+ is_stage1_5 = 1; -+ -+ /* If INSTALLADDR is not specified explicitly in the command-line, -+ determine it by the Stage 2 id. */ -+ if (! installaddr) -+ { -+ if (! is_stage1_5) -+ /* Stage 2. */ -+ installaddr = 0x8000; -+ else -+ /* Stage 1.5. */ -+ installaddr = 0x2000; -+ } -+ -+ *((unsigned long *) (stage1_buffer + STAGE1_STAGE2_SECTOR)) -+ = stage2_first_sector; -+ *((unsigned short *) (stage1_buffer + STAGE1_STAGE2_ADDRESS)) -+ = installaddr; -+ *((unsigned short *) (stage1_buffer + STAGE1_STAGE2_SEGMENT)) -+ = installaddr >> 4; -+ -+ i = (int) stage2_first_buffer + SECTOR_SIZE - 4; -+ while (*((unsigned long *) i)) -+ { -+ if (i < (int) stage2_first_buffer -+ || (*((int *) (i - 4)) & 0x80000000) -+ || *((unsigned short *) i) >= 0xA00 -+ || *((short *) (i + 2)) == 0) -+ { -+ errnum = ERR_BAD_VERSION; -+ goto fail; -+ } -+ -+ *((int *) i) = 0; -+ *((int *) (i - 4)) = 0; -+ i -= 8; -+ } -+ -+ installlist = (int) stage2_first_buffer + SECTOR_SIZE + 4; -+ installaddr += SECTOR_SIZE; -+ -+ /* Read the whole of Stage2 except for the first sector. */ -+ grub_seek (SECTOR_SIZE); -+ -+ disk_read_hook = disk_read_blocklist_func; -+ if (! grub_read (dummy, -1)) -+ goto fail; -+ -+ disk_read_hook = 0; -+ -+ /* Find a string for the configuration filename. */ -+ config_file_location = stage2_second_buffer + STAGE2_VER_STR_OFFS; -+ while (*(config_file_location++)) -+ ; -+ -+ /* Set the "force LBA" flag for Stage2. */ -+ *((unsigned char *) (stage2_second_buffer + STAGE2_FORCE_LBA)) -+ = is_force_lba; -+ -+ if (*ptr == 'p') -+ { -+ *((long *) (stage2_second_buffer + STAGE2_INSTALLPART)) -+ = src_partition; -+ if (is_stage1_5) -+ { -+ /* Reset the device information in FILE if it is a Stage 1.5. */ -+ unsigned long device = 0xFFFFFFFF; -+ -+ grub_memmove (config_file_location, (char *) &device, -+ sizeof (device)); -+ } -+ -+ ptr = skip_to (0, ptr); -+ } -+ -+ if (*ptr) -+ { -+ grub_strcpy (config_filename, ptr); -+ nul_terminate (config_filename); -+ -+ if (! is_stage1_5) -+ /* If it is a Stage 2, just copy PTR to CONFIG_FILE_LOCATION. */ -+ grub_strcpy (config_file_location, ptr); -+ else -+ { -+ char *real_config; -+ unsigned long device; -+ -+ /* Translate the external device syntax to the internal device -+ syntax. */ -+ if (! (real_config = set_device (ptr))) -+ { -+ /* The Stage 2 PTR does not contain the device name, so -+ use the root device instead. */ -+ errnum = ERR_NONE; -+ current_drive = saved_drive; -+ current_partition = saved_partition; -+ real_config = ptr; -+ } -+ -+ if (current_drive == src_drive) -+ { -+ /* If the drive where the Stage 2 resides is the same as -+ the one where the Stage 1.5 resides, do not embed the -+ drive number. */ -+ current_drive = 0xFF; -+ } -+ -+ device = (current_drive << 24) | current_partition; -+ grub_memmove (config_file_location, (char *) &device, -+ sizeof (device)); -+ grub_strcpy (config_file_location + sizeof (device), -+ real_config); -+ } -+ -+ /* If a Stage 1.5 is used, then we need to modify the Stage2. */ -+ if (is_stage1_5) -+ { -+ char *real_config_filename = skip_to (0, ptr); -+ -+ is_open = grub_open (config_filename); -+ if (! is_open) -+ goto fail; -+ -+ /* Skip the first sector. */ -+ grub_seek (SECTOR_SIZE); -+ -+ disk_read_hook = disk_read_savesect_func; -+ if (grub_read (stage2_buffer, SECTOR_SIZE) != SECTOR_SIZE) -+ goto fail; -+ -+ disk_read_hook = 0; -+ grub_close (); -+ is_open = 0; -+ -+ /* Sanity check. */ -+ if (*(stage2_buffer + STAGE2_STAGE2_ID) != STAGE2_ID_STAGE2) -+ { -+ errnum = ERR_BAD_VERSION; -+ goto fail; -+ } -+ -+ /* Set the "force LBA" flag for Stage2. */ -+ *(stage2_buffer + STAGE2_FORCE_LBA) = is_force_lba; -+ -+ /* If REAL_CONFIG_FILENAME is specified, copy it to the Stage2. */ -+ if (*real_config_filename) -+ { -+ /* Specified */ -+ char *location; -+ -+ /* Find a string for the configuration filename. */ -+ location = stage2_buffer + STAGE2_VER_STR_OFFS; -+ while (*(location++)) -+ ; -+ -+ /* Copy the name. */ -+ grub_strcpy (location, real_config_filename); -+ } -+ -+ /* Write it to the disk. */ -+ buf_track = -1; -+ -+#ifdef GRUB_UTIL -+ /* In the grub shell, access the Stage 2 via the OS filesystem -+ service, if possible. */ -+ if (stage2_os_file) -+ { -+ FILE *fp; -+ -+ fp = fopen (stage2_os_file, "r+"); -+ if (! fp) -+ { -+ errnum = ERR_FILE_NOT_FOUND; -+ goto fail; -+ } -+ -+ if (fseek (fp, SECTOR_SIZE, SEEK_SET) != 0) -+ { -+ fclose (fp); -+ errnum = ERR_BAD_VERSION; -+ goto fail; -+ } -+ -+ if (fwrite (stage2_buffer, 1, SECTOR_SIZE, fp) -+ != SECTOR_SIZE) -+ { -+ fclose (fp); -+ errnum = ERR_WRITE; -+ goto fail; -+ } -+ -+ fclose (fp); -+ } -+ else -+#endif /* GRUB_UTIL */ -+ { -+ if (! devwrite (saved_sector - part_start, 1, stage2_buffer)) -+ goto fail; -+ } -+ } -+ } -+ -+ /* Clear the cache. */ -+ buf_track = -1; -+ -+ /* Write the modified sectors of Stage2 to the disk. */ -+#ifdef GRUB_UTIL -+ if (! is_stage1_5 && stage2_os_file) -+ { -+ FILE *fp; -+ -+ fp = fopen (stage2_os_file, "r+"); -+ if (! fp) -+ { -+ errnum = ERR_FILE_NOT_FOUND; -+ goto fail; -+ } -+ -+ if (fwrite (stage2_first_buffer, 1, SECTOR_SIZE, fp) != SECTOR_SIZE) -+ { -+ fclose (fp); -+ errnum = ERR_WRITE; -+ goto fail; -+ } -+ -+ if (fwrite (stage2_second_buffer, 1, SECTOR_SIZE, fp) != SECTOR_SIZE) -+ { -+ fclose (fp); -+ errnum = ERR_WRITE; -+ goto fail; -+ } -+ -+ fclose (fp); -+ } -+ else -+#endif /* GRUB_UTIL */ -+ { -+ /* The first. */ -+ current_drive = src_drive; -+ current_partition = src_partition; -+ -+ if (! open_partition ()) -+ goto fail; -+ -+ if (! devwrite (stage2_first_sector - src_part_start, 1, -+ stage2_first_buffer)) -+ goto fail; -+ -+ if (! devwrite (stage2_second_sector - src_part_start, 1, -+ stage2_second_buffer)) -+ goto fail; -+ } -+ -+ /* Write the modified sector of Stage 1 to the disk. */ -+ current_drive = dest_drive; -+ current_partition = dest_partition; -+ if (! open_partition ()) -+ goto fail; -+ -+ devwrite (0, 1, stage1_buffer); -+ -+ fail: -+ if (is_open) -+ grub_close (); -+ -+ disk_read_hook = 0; -+ -+#ifndef NO_DECOMPRESSION -+ no_decompression = 0; -+#endif -+ -+ return errnum; -+} -+ -+static struct builtin builtin_install = -+{ -+ "install", -+ install_func, -+ BUILTIN_CMDLINE, -+ "install [--stage2=STAGE2_FILE] [--force-lba] STAGE1 [d] DEVICE STAGE2 [ADDR] [p] [CONFIG_FILE] [REAL_CONFIG_FILE]", -+ "Install STAGE1 on DEVICE, and install a blocklist for loading STAGE2" -+ " as a Stage 2. If the option `d' is present, the Stage 1 will always" -+ " look for the disk where STAGE2 was installed, rather than using" -+ " the booting drive. The Stage 2 will be loaded at address ADDR, which" -+ " will be determined automatically if you don't specify it. If" -+ " the option `p' or CONFIG_FILE is present, then the first block" -+ " of Stage 2 is patched with new values of the partition and name" -+ " of the configuration file used by the true Stage 2 (for a Stage 1.5," -+ " this is the name of the true Stage 2) at boot time. If STAGE2 is a Stage" -+ " 1.5 and REAL_CONFIG_FILE is present, then the Stage 2 CONFIG_FILE is" -+ " patched with the configuration filename REAL_CONFIG_FILE." -+ " If the option `--force-lba' is specified, disable some sanity checks" -+ " for LBA mode. If the option `--stage2' is specified, rewrite the Stage" -+ " 2 via your OS's filesystem instead of the raw device." -+}; -+ -+ -+/* ioprobe */ -+static int -+ioprobe_func (char *arg, int flags) -+{ -+#ifdef GRUB_UTIL -+ -+ errnum = ERR_UNRECOGNIZED; -+ return 1; -+ -+#else /* ! GRUB_UTIL */ -+ -+ unsigned short *port; -+ -+ /* Get the drive number. */ -+ set_device (arg); -+ if (errnum) -+ return 1; -+ -+ /* Clean out IO_MAP. */ -+ grub_memset ((char *) io_map, 0, IO_MAP_SIZE * sizeof (unsigned short)); -+ -+ /* Track the int13 handler. */ -+ track_int13 (current_drive); -+ -+ /* Print out the result. */ -+ for (port = io_map; *port != 0; port++) -+ grub_printf (" 0x%x", (unsigned int) *port); -+ -+ return 0; -+ -+#endif /* ! GRUB_UTIL */ -+} -+ -+static struct builtin builtin_ioprobe = -+{ -+ "ioprobe", -+ ioprobe_func, -+ BUILTIN_CMDLINE, -+ "ioprobe DRIVE", -+ "Probe I/O ports used for the drive DRIVE." -+}; -+ -+ -+/* kernel */ -+static int -+kernel_func (char *arg, int flags) -+{ -+ int len; -+ kernel_t suggested_type = KERNEL_TYPE_NONE; -+ unsigned long load_flags = 0; -+ -+#ifndef AUTO_LINUX_MEM_OPT -+ load_flags |= KERNEL_LOAD_NO_MEM_OPTION; -+#endif -+ -+ /* Deal with GNU-style long options. */ -+ while (1) -+ { -+ /* If the option `--type=TYPE' is specified, convert the string to -+ a kernel type. */ -+ if (grub_memcmp (arg, "--type=", 7) == 0) -+ { -+ arg += 7; -+ -+ if (grub_memcmp (arg, "netbsd", 6) == 0) -+ suggested_type = KERNEL_TYPE_NETBSD; -+ else if (grub_memcmp (arg, "freebsd", 7) == 0) -+ suggested_type = KERNEL_TYPE_FREEBSD; -+ else if (grub_memcmp (arg, "openbsd", 7) == 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", 5) == 0) -+ suggested_type = KERNEL_TYPE_LINUX; -+ else if (grub_memcmp (arg, "biglinux", 8) == 0) -+ suggested_type = KERNEL_TYPE_BIG_LINUX; -+ else if (grub_memcmp (arg, "multiboot", 9) == 0) -+ suggested_type = KERNEL_TYPE_MULTIBOOT; -+ else -+ { -+ errnum = ERR_BAD_ARGUMENT; -+ return 1; -+ } -+ } -+ /* If the `--no-mem-option' is specified, don't pass a Linux's mem -+ option automatically. If the kernel is another type, this flag -+ has no effect. */ -+ else if (grub_memcmp (arg, "--no-mem-option", 15) == 0) -+ load_flags |= KERNEL_LOAD_NO_MEM_OPTION; -+ else -+ break; -+ -+ /* Try the next. */ -+ arg = skip_to (0, arg); -+ } -+ -+ len = grub_strlen (arg); -+ -+ /* Reset MB_CMDLINE. */ -+ mb_cmdline = (char *) MB_CMDLINE_BUF; -+ if (len + 1 > MB_CMDLINE_BUFLEN) -+ { -+ errnum = ERR_WONT_FIT; -+ return 1; -+ } -+ -+ /* Copy the command-line to MB_CMDLINE. */ -+ grub_memmove (mb_cmdline, arg, len + 1); -+ kernel_type = load_image (arg, mb_cmdline, suggested_type, load_flags); -+ if (kernel_type == KERNEL_TYPE_NONE) -+ return 1; -+ -+ mb_cmdline += len + 1; -+ return 0; -+} -+ -+static struct builtin builtin_kernel = -+{ -+ "kernel", -+ kernel_func, -+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST, -+ "kernel [--no-mem-option] [--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\". The option --no-mem-option tells GRUB not to pass a" -+ " Linux's mem option automatically." -+}; -+ -+ -+/* lock */ -+static int -+lock_func (char *arg, int flags) -+{ -+ if (! auth && password) -+ { -+ errnum = ERR_PRIVILEGED; -+ return 1; -+ } -+ -+ return 0; -+} -+ -+static struct builtin builtin_lock = -+{ -+ "lock", -+ lock_func, -+ BUILTIN_CMDLINE, -+ "lock", -+ "Break a command execution unless the user is authenticated." -+}; -+ -+ -+/* makeactive */ -+static int -+makeactive_func (char *arg, int flags) -+{ -+ if (! make_saved_active ()) -+ return 1; -+ -+ return 0; -+} -+ -+static struct builtin builtin_makeactive = -+{ -+ "makeactive", -+ makeactive_func, -+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST, -+ "makeactive", -+ "Set the active partition on the root disk to GRUB's root device." -+ " This command is limited to _primary_ PC partitions on a hard disk." -+}; -+ -+ -+/* map */ -+/* Map FROM_DRIVE to TO_DRIVE. */ -+static int -+map_func (char *arg, int flags) -+{ -+ char *to_drive; -+ char *from_drive; -+ unsigned long to, from; -+ int i; -+ -+ to_drive = arg; -+ from_drive = skip_to (0, arg); -+ -+ /* Get the drive number for TO_DRIVE. */ -+ set_device (to_drive); -+ if (errnum) -+ return 1; -+ to = current_drive; -+ -+ /* Get the drive number for FROM_DRIVE. */ -+ set_device (from_drive); -+ if (errnum) -+ return 1; -+ from = current_drive; -+ -+ /* Search for an empty slot in BIOS_DRIVE_MAP. */ -+ for (i = 0; i < DRIVE_MAP_SIZE; i++) -+ { -+ /* Perhaps the user wants to override the map. */ -+ if ((bios_drive_map[i] & 0xff) == from) -+ break; -+ -+ if (! bios_drive_map[i]) -+ break; -+ } -+ -+ if (i == DRIVE_MAP_SIZE) -+ { -+ errnum = ERR_WONT_FIT; -+ return 1; -+ } -+ -+ if (to == from) -+ /* If TO is equal to FROM, delete the entry. */ -+ grub_memmove ((char *) &bios_drive_map[i], (char *) &bios_drive_map[i + 1], -+ sizeof (unsigned short) * (DRIVE_MAP_SIZE - i)); -+ else -+ bios_drive_map[i] = from | (to << 8); -+ -+ return 0; -+} -+ -+static struct builtin builtin_map = -+{ -+ "map", -+ map_func, -+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST, -+ "map TO_DRIVE FROM_DRIVE", -+ "Map the drive FROM_DRIVE to the drive TO_DRIVE. This is necessary" -+ " when you chain-load some operating systems, such as DOS, if such an" -+ " OS resides at a non-first drive." -+}; -+ -+ -+#ifdef USE_MD5_PASSWORDS -+/* md5crypt */ -+static int -+md5crypt_func (char *arg, int flags) -+{ -+ char crypted[36]; -+ char key[32]; -+ unsigned int seed; -+ int i; -+ const char *const seedchars = -+ "./0123456789ABCDEFGHIJKLMNOPQRST" -+ "UVWXYZabcdefghijklmnopqrstuvwxyz"; -+ -+ /* First create a salt. */ -+ -+ /* The magical prefix. */ -+ grub_memset (crypted, 0, sizeof (crypted)); -+ grub_memmove (crypted, "$1$", 3); -+ -+ /* Create the length of a salt. */ -+ seed = currticks (); -+ -+ /* Generate a salt. */ -+ for (i = 0; i < 8 && seed; i++) -+ { -+ /* FIXME: This should be more random. */ -+ crypted[3 + i] = seedchars[seed & 0x3f]; -+ seed >>= 6; -+ } -+ -+ /* A salt must be terminated with `$', if it is less than 8 chars. */ -+ crypted[3 + i] = '$'; -+ -+#ifdef DEBUG_MD5CRYPT -+ grub_printf ("salt = %s\n", crypted); -+#endif -+ -+ /* Get a password. */ -+ grub_memset (key, 0, sizeof (key)); -+ get_cmdline ("Password: ", key, sizeof (key) - 1, '*', 0); -+ -+ /* Crypt the key. */ -+ make_md5_password (key, crypted); -+ -+ grub_printf ("Encrypted: %s\n", crypted); -+ return 0; -+} -+ -+static struct builtin builtin_md5crypt = -+{ -+ "md5crypt", -+ md5crypt_func, -+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST, -+ "md5crypt", -+ "Generate a password in MD5 format." -+}; -+#endif /* USE_MD5_PASSWORDS */ -+ -+ -+/* module */ -+static int -+module_func (char *arg, int flags) -+{ -+ int len = grub_strlen (arg); -+ -+ switch (kernel_type) -+ { -+ case KERNEL_TYPE_MULTIBOOT: -+ if (mb_cmdline + len + 1 > (char *) MB_CMDLINE_BUF + MB_CMDLINE_BUFLEN) -+ { -+ errnum = ERR_WONT_FIT; -+ return 1; -+ } -+ grub_memmove (mb_cmdline, arg, len + 1); -+ if (! load_module (arg, mb_cmdline)) -+ return 1; -+ mb_cmdline += len + 1; -+ break; -+ -+ case KERNEL_TYPE_LINUX: -+ case KERNEL_TYPE_BIG_LINUX: -+ if (! load_initrd (arg)) -+ return 1; -+ break; -+ -+ default: -+ errnum = ERR_NEED_MB_KERNEL; -+ return 1; -+ } -+ -+ return 0; -+} -+ -+static struct builtin builtin_module = -+{ -+ "module", -+ module_func, -+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST, -+ "module FILE [ARG ...]", -+ "Load a boot module FILE for a Multiboot format boot image (no" -+ " interpretation of the file contents is made, so users of this" -+ " command must know what the kernel in question expects). The" -+ " rest of the line is passed as the \"module command line\", like" -+ " the `kernel' command." -+}; -+ -+ -+/* modulenounzip */ -+static int -+modulenounzip_func (char *arg, int flags) -+{ -+ int ret; -+ -+#ifndef NO_DECOMPRESSION -+ no_decompression = 1; -+#endif -+ -+ ret = module_func (arg, flags); -+ -+#ifndef NO_DECOMPRESSION -+ no_decompression = 0; -+#endif -+ -+ return ret; -+} -+ -+static struct builtin builtin_modulenounzip = -+{ -+ "modulenounzip", -+ modulenounzip_func, -+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST, -+ "modulenounzip FILE [ARG ...]", -+ "The same as `module', except that automatic decompression is" -+ " disabled." -+}; -+ -+ -+/* pager [on|off] */ -+static int -+pager_func (char *arg, int flags) -+{ -+ /* If ARG is empty, toggle the flag. */ -+ if (! *arg) -+ use_pager = ! use_pager; -+ else if (grub_memcmp (arg, "on", 2) == 0) -+ use_pager = 1; -+ else if (grub_memcmp (arg, "off", 3) == 0) -+ use_pager = 0; -+ else -+ { -+ errnum = ERR_BAD_ARGUMENT; -+ return 1; -+ } -+ -+ grub_printf (" Internal pager is now %s\n", use_pager ? "on" : "off"); -+ return 0; -+} -+ -+static struct builtin builtin_pager = -+{ -+ "pager", -+ pager_func, -+ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, -+ "pager [FLAG]", -+ "Toggle pager mode with no argument. If FLAG is given and its value" -+ " is `on', turn on the mode. If FLAG is `off', turn off the mode." -+}; -+ -+ -+/* partnew PART TYPE START LEN */ -+static int -+partnew_func (char *arg, int flags) -+{ -+ int new_type, new_start, new_len; -+ int start_cl, start_ch, start_dh; -+ int end_cl, end_ch, end_dh; -+ int entry; -+ char mbr[512]; -+ -+ /* Convert a LBA address to a CHS address in the INT 13 format. */ -+ auto void lba_to_chs (int lba, int *cl, int *ch, int *dh); -+ void lba_to_chs (int lba, int *cl, int *ch, int *dh) -+ { -+ int cylinder, head, sector; -+ -+ sector = lba % buf_geom.sectors + 1; -+ head = (lba / buf_geom.sectors) % buf_geom.heads; -+ cylinder = lba / (buf_geom.sectors * buf_geom.heads); -+ -+ if (cylinder >= buf_geom.cylinders) -+ cylinder = buf_geom.cylinders - 1; -+ -+ *cl = sector | ((cylinder & 0x300) >> 2); -+ *ch = cylinder & 0xFF; -+ *dh = head; -+ } -+ -+ /* Get the drive and the partition. */ -+ if (! set_device (arg)) -+ return 1; -+ -+ /* The drive must be a hard disk. */ -+ if (! (current_drive & 0x80)) -+ { -+ errnum = ERR_BAD_ARGUMENT; -+ return 1; -+ } -+ -+ /* The partition must a primary partition. */ -+ if ((current_partition >> 16) > 3 -+ || (current_partition & 0xFFFF) != 0xFFFF) -+ { -+ errnum = ERR_BAD_ARGUMENT; -+ return 1; -+ } -+ -+ entry = current_partition >> 16; -+ -+ /* Get the new partition type. */ -+ arg = skip_to (0, arg); -+ if (! safe_parse_maxint (&arg, &new_type)) -+ return 1; -+ -+ /* The partition type is unsigned char. */ -+ if (new_type > 0xFF) -+ { -+ errnum = ERR_BAD_ARGUMENT; -+ return 1; -+ } -+ -+ /* Get the new partition start. */ -+ arg = skip_to (0, arg); -+ if (! safe_parse_maxint (&arg, &new_start)) -+ return 1; -+ -+ /* Get the new partition length. */ -+ arg = skip_to (0, arg); -+ if (! safe_parse_maxint (&arg, &new_len)) -+ return 1; -+ -+ /* Read the MBR. */ -+ if (! rawread (current_drive, 0, 0, SECTOR_SIZE, mbr)) -+ return 1; -+ -+ /* Check if the new partition will fit in the disk. */ -+ if (new_start + new_len > buf_geom.total_sectors) -+ { -+ errnum = ERR_GEOM; -+ return 1; -+ } -+ -+ /* Store the partition information in the MBR. */ -+ lba_to_chs (new_start, &start_cl, &start_ch, &start_dh); -+ lba_to_chs (new_start + new_len - 1, &end_cl, &end_ch, &end_dh); -+ -+ PC_SLICE_FLAG (mbr, entry) = 0; -+ PC_SLICE_HEAD (mbr, entry) = start_dh; -+ PC_SLICE_SEC (mbr, entry) = start_cl; -+ PC_SLICE_CYL (mbr, entry) = start_ch; -+ PC_SLICE_TYPE (mbr, entry) = new_type; -+ PC_SLICE_EHEAD (mbr, entry) = end_dh; -+ PC_SLICE_ESEC (mbr, entry) = end_cl; -+ PC_SLICE_ECYL (mbr, entry) = end_ch; -+ PC_SLICE_START (mbr, entry) = new_start; -+ PC_SLICE_LENGTH (mbr, entry) = new_len; -+ -+ /* Make sure that the MBR has a valid signature. */ -+ PC_MBR_SIG (mbr) = PC_MBR_SIGNATURE; -+ -+ /* Write back the MBR to the disk. */ -+ buf_track = -1; -+ if (! rawwrite (current_drive, 0, mbr)) -+ return 1; -+ -+ return 0; -+} -+ -+static struct builtin builtin_partnew = -+{ -+ "partnew", -+ partnew_func, -+ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, -+ "partnew PART TYPE START LEN", -+ "Create a primary partition at the starting address START with the" -+ " length LEN, with the type TYPE. START and LEN are in sector units." -+}; -+ -+ -+/* parttype PART TYPE */ -+static int -+parttype_func (char *arg, int flags) -+{ -+ int new_type; -+ unsigned long part = 0xFFFFFF; -+ unsigned long start, len, offset, ext_offset; -+ int entry, type; -+ char mbr[512]; -+ -+ /* Get the drive and the partition. */ -+ if (! set_device (arg)) -+ return 1; -+ -+ /* The drive must be a hard disk. */ -+ if (! (current_drive & 0x80)) -+ { -+ errnum = ERR_BAD_ARGUMENT; -+ return 1; -+ } -+ -+ /* The partition must be a PC slice. */ -+ if ((current_partition >> 16) == 0xFF -+ || (current_partition & 0xFFFF) != 0xFFFF) -+ { -+ errnum = ERR_BAD_ARGUMENT; -+ return 1; -+ } -+ -+ /* Get the new partition type. */ -+ arg = skip_to (0, arg); -+ if (! safe_parse_maxint (&arg, &new_type)) -+ return 1; -+ -+ /* The partition type is unsigned char. */ -+ if (new_type > 0xFF) -+ { -+ errnum = ERR_BAD_ARGUMENT; -+ return 1; -+ } -+ -+ /* Look for the partition. */ -+ while (next_partition (current_drive, 0xFFFFFF, &part, &type, -+ &start, &len, &offset, &entry, -+ &ext_offset, mbr)) -+ { -+ if (part == current_partition) -+ { -+ /* Found. */ -+ -+ /* Set the type to NEW_TYPE. */ -+ PC_SLICE_TYPE (mbr, entry) = new_type; -+ -+ /* Write back the MBR to the disk. */ -+ buf_track = -1; -+ if (! rawwrite (current_drive, offset, mbr)) -+ return 1; -+ -+ /* Succeed. */ -+ return 0; -+ } -+ } -+ -+ /* The partition was not found. ERRNUM was set by next_partition. */ -+ return 1; -+} -+ -+static struct builtin builtin_parttype = -+{ -+ "parttype", -+ parttype_func, -+ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, -+ "parttype PART TYPE", -+ "Change the type of the partition PART to TYPE." -+}; -+ -+ -+/* password */ -+static int -+password_func (char *arg, int flags) -+{ -+ int len; -+ password_t type = PASSWORD_PLAIN; -+ -+#ifdef USE_MD5_PASSWORDS -+ if (grub_memcmp (arg, "--md5", 5) == 0) -+ { -+ type = PASSWORD_MD5; -+ arg = skip_to (0, arg); -+ } -+#endif -+ if (grub_memcmp (arg, "--", 2) == 0) -+ { -+ type = PASSWORD_UNSUPPORTED; -+ arg = skip_to (0, arg); -+ } -+ -+ if ((flags & (BUILTIN_CMDLINE | BUILTIN_SCRIPT)) != 0) -+ { -+ /* Do password check! */ -+ char entered[32]; -+ -+ /* Wipe out any previously entered password */ -+ entered[0] = 0; -+ get_cmdline ("Password: ", entered, 31, '*', 0); -+ -+ nul_terminate (arg); -+ if (check_password (entered, arg, type) != 0) -+ { -+ errnum = ERR_PRIVILEGED; -+ return 1; -+ } -+ } -+ else -+ { -+ len = grub_strlen (arg); -+ -+ /* PASSWORD NUL NUL ... */ -+ if (len + 2 > PASSWORD_BUFLEN) -+ { -+ errnum = ERR_WONT_FIT; -+ return 1; -+ } -+ -+ /* Copy the password and clear the rest of the buffer. */ -+ password = (char *) PASSWORD_BUF; -+ grub_memmove (password, arg, len); -+ grub_memset (password + len, 0, PASSWORD_BUFLEN - len); -+ password_type = type; -+ } -+ return 0; -+} -+ -+static struct builtin builtin_password = -+{ -+ "password", -+ password_func, -+ BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_NO_ECHO, -+ "password [--md5] PASSWD [FILE]", -+ "If used in the first section of a menu file, disable all" -+ " interactive editing control (menu entry editor and" -+ " command line). If the password PASSWD is entered, it loads the" -+ " FILE as a new config file and restarts the GRUB Stage 2. If you" -+ " omit the argument FILE, then GRUB just unlocks privileged" -+ " instructions. You can also use it in the script section, in" -+ " which case it will ask for the password, before continueing." -+ " The option --md5 tells GRUB that PASSWD is encrypted with" -+ " md5crypt." -+}; -+ -+ -+/* pause */ -+static int -+pause_func (char *arg, int flags) -+{ -+ printf("%s\n", arg); -+ -+ /* If ESC is returned, then abort this entry. */ -+ if (ASCII_CHAR (getkey ()) == 27) -+ return 1; -+ -+ return 0; -+} -+ -+static struct builtin builtin_pause = -+{ -+ "pause", -+ pause_func, -+ BUILTIN_CMDLINE | BUILTIN_NO_ECHO, -+ "pause [MESSAGE ...]", -+ "Print MESSAGE, then wait until a key is pressed." -+}; -+ -+ -+#ifdef GRUB_UTIL -+/* quit */ -+static int -+quit_func (char *arg, int flags) -+{ -+ stop (); -+ -+ /* Never reach here. */ -+ return 0; -+} -+ -+static struct builtin builtin_quit = -+{ -+ "quit", -+ quit_func, -+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST, -+ "quit", -+ "Exit from the GRUB shell." -+}; -+#endif /* GRUB_UTIL */ -+ -+ -+#ifdef SUPPORT_NETBOOT -+/* rarp */ -+static int -+rarp_func (char *arg, int flags) -+{ -+ if (! rarp ()) -+ { -+ if (errnum == ERR_NONE) -+ errnum = ERR_DEV_VALUES; -+ -+ return 1; -+ } -+ -+ /* Notify the configuration. */ -+ print_network_configuration (); -+ return 0; -+} -+ -+static struct builtin builtin_rarp = -+{ -+ "rarp", -+ rarp_func, -+ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, -+ "rarp", -+ "Initialize a network device via RARP." -+}; -+#endif /* SUPPORT_NETBOOT */ -+ -+ -+static int -+read_func (char *arg, int flags) -+{ -+ int addr; -+ -+ if (! safe_parse_maxint (&arg, &addr)) -+ return 1; -+ -+ grub_printf ("Address 0x%x: Value 0x%x\n", -+ addr, *((unsigned *) RAW_ADDR (addr))); -+ return 0; -+} -+ -+static struct builtin builtin_read = -+{ -+ "read", -+ read_func, -+ BUILTIN_CMDLINE, -+ "read ADDR", -+ "Read a 32-bit value from memory at address ADDR and" -+ " display it in hex format." -+}; -+ -+ -+/* reboot */ -+static int -+reboot_func (char *arg, int flags) -+{ -+ grub_reboot (); -+ -+ /* Never reach here. */ -+ return 1; -+} -+ -+static struct builtin builtin_reboot = -+{ -+ "reboot", -+ reboot_func, -+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST, -+ "reboot", -+ "Reboot your system." -+}; -+ -+ -+/* Print the root device information. */ -+static void -+print_root_device (void) -+{ -+ if (saved_drive == NETWORK_DRIVE) -+ { -+ /* Network drive. */ -+ grub_printf (" (nd):"); -+ } -+ else if (saved_drive & 0x80) -+ { -+ /* Hard disk drive. */ -+ grub_printf (" (hd%d", saved_drive - 0x80); -+ -+ if ((saved_partition & 0xFF0000) != 0xFF0000) -+ grub_printf (",%d", saved_partition >> 16); -+ -+ if ((saved_partition & 0x00FF00) != 0x00FF00) -+ grub_printf (",%c", ((saved_partition >> 8) & 0xFF) + 'a'); -+ -+ grub_printf ("):"); -+ } -+ else -+ { -+ /* Floppy disk drive. */ -+ grub_printf (" (fd%d):", saved_drive); -+ } -+ -+ /* Print the filesystem information. */ -+ current_partition = saved_partition; -+ current_drive = saved_drive; -+ print_fsys_type (); -+} -+ -+static int -+real_root_func (char *arg, int attempt_mount) -+{ -+ int hdbias = 0; -+ char *biasptr; -+ char *next; -+ -+ /* If ARG is empty, just print the current root device. */ -+ if (! *arg) -+ { -+ print_root_device (); -+ return 0; -+ } -+ -+ /* Call set_device to get the drive and the partition in ARG. */ -+ next = set_device (arg); -+ if (! next) -+ return 1; -+ -+ /* Ignore ERR_FSYS_MOUNT. */ -+ if (attempt_mount) -+ { -+ if (! open_device () && errnum != ERR_FSYS_MOUNT) -+ return 1; -+ } -+ else -+ { -+ /* This is necessary, because the location of a partition table -+ must be set appropriately. */ -+ if (open_partition ()) -+ { -+ set_bootdev (0); -+ if (errnum) -+ return 1; -+ } -+ } -+ -+ /* Clear ERRNUM. */ -+ errnum = 0; -+ saved_partition = current_partition; -+ saved_drive = current_drive; -+ -+ if (attempt_mount) -+ { -+ /* BSD and chainloading evil hacks !! */ -+ biasptr = skip_to (0, next); -+ safe_parse_maxint (&biasptr, &hdbias); -+ errnum = 0; -+ bootdev = set_bootdev (hdbias); -+ if (errnum) -+ return 1; -+ -+ /* Print the type of the filesystem. */ -+ print_fsys_type (); -+ } -+ -+ return 0; -+} -+ -+static int -+root_func (char *arg, int flags) -+{ -+ return real_root_func (arg, 1); -+} -+ -+static struct builtin builtin_root = -+{ -+ "root", -+ root_func, -+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST, -+ "root [DEVICE [HDBIAS]]", -+ "Set the current \"root device\" to the device DEVICE, then" -+ " attempt to mount it to get the partition size (for passing the" -+ " partition descriptor in `ES:ESI', used by some chain-loaded" -+ " bootloaders), the BSD drive-type (for booting BSD kernels using" -+ " their native boot format), and correctly determine " -+ " the PC partition where a BSD sub-partition is located. The" -+ " optional HDBIAS parameter is a number to tell a BSD kernel" -+ " how many BIOS drive numbers are on controllers before the current" -+ " one. For example, if there is an IDE disk and a SCSI disk, and your" -+ " FreeBSD root partition is on the SCSI disk, then use a `1' for HDBIAS." -+}; -+ -+ -+/* rootnoverify */ -+static int -+rootnoverify_func (char *arg, int flags) -+{ -+ return real_root_func (arg, 0); -+} -+ -+static struct builtin builtin_rootnoverify = -+{ -+ "rootnoverify", -+ rootnoverify_func, -+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST, -+ "rootnoverify [DEVICE [HDBIAS]]", -+ "Similar to `root', but don't attempt to mount the partition. This" -+ " is useful for when an OS is outside of the area of the disk that" -+ " GRUB can read, but setting the correct root device is still" -+ " desired. Note that the items mentioned in `root' which" -+ " derived from attempting the mount will NOT work correctly." -+}; -+ -+ -+/* savedefault */ -+static int -+savedefault_func (char *arg, int flags) -+{ -+#if !defined(SUPPORT_DISKLESS) && !defined(GRUB_UTIL) -+ char buffer[512]; -+ int *entryno_ptr; -+ -+ /* This command is only useful when you boot an entry from the menu -+ interface. */ -+ if (! (flags & BUILTIN_SCRIPT)) -+ { -+ errnum = ERR_UNRECOGNIZED; -+ return 1; -+ } -+ -+ /* Get the geometry of the boot drive (i.e. the disk which contains -+ this stage2). */ -+ if (get_diskinfo (boot_drive, &buf_geom)) -+ { -+ errnum = ERR_NO_DISK; -+ return 1; -+ } -+ -+ /* Load the second sector of this stage2. */ -+ if (! rawread (boot_drive, install_second_sector, 0, SECTOR_SIZE, buffer)) -+ { -+ return 1; -+ } -+ -+ /* Sanity check. */ -+ if (buffer[STAGE2_STAGE2_ID] != STAGE2_ID_STAGE2 -+ || *((short *) (buffer + STAGE2_VER_MAJ_OFFS)) != COMPAT_VERSION) -+ { -+ errnum = ERR_BAD_VERSION; -+ return 1; -+ } -+ -+ entryno_ptr = (int *) (buffer + STAGE2_SAVED_ENTRYNO); -+ -+ /* Check if the saved entry number differs from current entry number. */ -+ if (*entryno_ptr != current_entryno) -+ { -+ /* Overwrite the saved entry number. */ -+ *entryno_ptr = current_entryno; -+ -+ /* Save the image in the disk. */ -+ if (! rawwrite (boot_drive, install_second_sector, buffer)) -+ return 1; -+ -+ /* Clear the cache. */ -+ buf_track = -1; -+ } -+ -+ return 0; -+#else /* ! SUPPORT_DISKLESS && ! GRUB_UTIL */ -+ errnum = ERR_UNRECOGNIZED; -+ return 1; -+#endif /* ! SUPPORT_DISKLESS && ! GRUB_UTIL */ -+} -+ -+static struct builtin builtin_savedefault = -+{ -+ "savedefault", -+ savedefault_func, -+ BUILTIN_CMDLINE, -+ "savedefault", -+ "Save the current entry as the default boot entry." -+}; -+ -+ -+#ifdef SUPPORT_SERIAL -+/* serial */ -+static int -+serial_func (char *arg, int flags) -+{ -+ unsigned short port = serial_hw_get_port (0); -+ unsigned int speed = 9600; -+ int word_len = UART_8BITS_WORD; -+ int parity = UART_NO_PARITY; -+ int stop_bit_len = UART_1_STOP_BIT; -+ -+ /* Process GNU-style long options. -+ FIXME: We should implement a getopt-like function, to avoid -+ duplications. */ -+ while (1) -+ { -+ if (grub_memcmp (arg, "--unit=", sizeof ("--unit=") - 1) == 0) -+ { -+ char *p = arg + sizeof ("--unit=") - 1; -+ int unit; -+ -+ if (! safe_parse_maxint (&p, &unit)) -+ return 1; -+ -+ if (unit < 0 || unit > 3) -+ { -+ errnum = ERR_DEV_VALUES; -+ return 1; -+ } -+ -+ port = serial_hw_get_port (unit); -+ } -+ else if (grub_memcmp (arg, "--speed=", sizeof ("--speed=") - 1) == 0) -+ { -+ char *p = arg + sizeof ("--speed=") - 1; -+ int num; -+ -+ if (! safe_parse_maxint (&p, &num)) -+ return 1; -+ -+ speed = (unsigned int) num; -+ } -+ else if (grub_memcmp (arg, "--port=", sizeof ("--port=") - 1) == 0) -+ { -+ char *p = arg + sizeof ("--port=") - 1; -+ int num; -+ -+ if (! safe_parse_maxint (&p, &num)) -+ return 1; -+ -+ port = (unsigned short) num; -+ } -+ else if (grub_memcmp (arg, "--word=", sizeof ("--word=") - 1) == 0) -+ { -+ char *p = arg + sizeof ("--word=") - 1; -+ int len; -+ -+ if (! safe_parse_maxint (&p, &len)) -+ return 1; -+ -+ switch (len) -+ { -+ case 5: word_len = UART_5BITS_WORD; break; -+ case 6: word_len = UART_6BITS_WORD; break; -+ case 7: word_len = UART_7BITS_WORD; break; -+ case 8: word_len = UART_8BITS_WORD; break; -+ default: -+ errnum = ERR_BAD_ARGUMENT; -+ return 1; -+ } -+ } -+ else if (grub_memcmp (arg, "--stop=", sizeof ("--stop=") - 1) == 0) -+ { -+ char *p = arg + sizeof ("--stop=") - 1; -+ int len; -+ -+ if (! safe_parse_maxint (&p, &len)) -+ return 1; -+ -+ switch (len) -+ { -+ case 1: stop_bit_len = UART_1_STOP_BIT; break; -+ case 2: stop_bit_len = UART_2_STOP_BITS; break; -+ default: -+ errnum = ERR_BAD_ARGUMENT; -+ return 1; -+ } -+ } -+ else if (grub_memcmp (arg, "--parity=", sizeof ("--parity=") - 1) == 0) -+ { -+ char *p = arg + sizeof ("--parity=") - 1; -+ -+ if (grub_memcmp (p, "no", sizeof ("no") - 1) == 0) -+ parity = UART_NO_PARITY; -+ else if (grub_memcmp (p, "odd", sizeof ("odd") - 1) == 0) -+ parity = UART_ODD_PARITY; -+ else if (grub_memcmp (p, "even", sizeof ("even") - 1) == 0) -+ parity = UART_EVEN_PARITY; -+ else -+ { -+ errnum = ERR_BAD_ARGUMENT; -+ return 1; -+ } -+ } -+# ifdef GRUB_UTIL -+ /* In the grub shell, don't use any port number but open a tty -+ device instead. */ -+ else if (grub_memcmp (arg, "--device=", sizeof ("--device=") - 1) == 0) -+ { -+ char *p = arg + sizeof ("--device=") - 1; -+ char dev[256]; /* XXX */ -+ char *q = dev; -+ -+ while (*p && ! grub_isspace (*p)) -+ *q++ = *p++; -+ -+ *q = 0; -+ serial_set_device (dev); -+ } -+# endif /* GRUB_UTIL */ -+ else -+ break; -+ -+ arg = skip_to (0, arg); -+ } -+ -+ /* Initialize the serial unit. */ -+ if (! serial_hw_init (port, speed, word_len, parity, stop_bit_len)) -+ { -+ errnum = ERR_BAD_ARGUMENT; -+ return 1; -+ } -+ -+ return 0; -+} -+ -+static struct builtin builtin_serial = -+{ -+ "serial", -+ serial_func, -+ BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST, -+ "serial [--unit=UNIT] [--port=PORT] [--speed=SPEED] [--word=WORD] [--parity=PARITY] [--stop=STOP] [--device=DEV]", -+ "Initialize a serial device. UNIT is a digit that specifies which serial" -+ " device is used (e.g. 0 == COM1). If you need to specify the port number," -+ " set it by --port. SPEED is the DTE-DTE speed. WORD is the word length," -+ " PARITY is the type of parity, which is one of `no', `odd' and `even'." -+ " STOP is the length of stop bit(s). The option --device can be used only" -+ " in the grub shell, which specifies the file name of a tty device. The" -+ " default values are COM1, 9600, 8N1." -+}; -+#endif /* SUPPORT_SERIAL */ -+ -+ -+/* setkey */ -+struct keysym -+{ -+ char *unshifted_name; /* the name in unshifted state */ -+ char *shifted_name; /* the name in shifted state */ -+ unsigned char unshifted_ascii; /* the ascii code in unshifted state */ -+ unsigned char shifted_ascii; /* the ascii code in shifted state */ -+ unsigned char keycode; /* keyboard scancode */ -+}; -+ -+/* The table for key symbols. If the "shifted" member of an entry is -+ NULL, the entry does not have shifted state. */ -+static struct keysym keysym_table[] = -+{ -+ {"escape", 0, 0x1b, 0, 0x01}, -+ {"1", "exclam", '1', '!', 0x02}, -+ {"2", "at", '2', '@', 0x03}, -+ {"3", "numbersign", '3', '#', 0x04}, -+ {"4", "dollar", '4', '$', 0x05}, -+ {"5", "percent", '5', '%', 0x06}, -+ {"6", "caret", '6', '^', 0x07}, -+ {"7", "ampersand", '7', '&', 0x08}, -+ {"8", "asterisk", '8', '*', 0x09}, -+ {"9", "parenleft", '9', '(', 0x0a}, -+ {"0", "parenright", '0', ')', 0x0b}, -+ {"minus", "underscore", '-', '_', 0x0c}, -+ {"equal", "plus", '=', '+', 0x0d}, -+ {"backspace", 0, '\b', 0, 0x0e}, -+ {"tab", 0, '\t', 0, 0x0f}, -+ {"q", "Q", 'q', 'Q', 0x10}, -+ {"w", "W", 'w', 'W', 0x11}, -+ {"e", "E", 'e', 'E', 0x12}, -+ {"r", "R", 'r', 'R', 0x13}, -+ {"t", "T", 't', 'T', 0x14}, -+ {"y", "Y", 'y', 'Y', 0x15}, -+ {"u", "U", 'u', 'U', 0x16}, -+ {"i", "I", 'i', 'I', 0x17}, -+ {"o", "O", 'o', 'O', 0x18}, -+ {"p", "P", 'p', 'P', 0x19}, -+ {"bracketleft", "braceleft", '[', '{', 0x1a}, -+ {"bracketright", "braceright", ']', '}', 0x1b}, -+ {"enter", 0, '\n', 0, 0x1c}, -+ {"control", 0, 0, 0, 0x1d}, -+ {"a", "A", 'a', 'A', 0x1e}, -+ {"s", "S", 's', 'S', 0x1f}, -+ {"d", "D", 'd', 'D', 0x20}, -+ {"f", "F", 'f', 'F', 0x21}, -+ {"g", "G", 'g', 'G', 0x22}, -+ {"h", "H", 'h', 'H', 0x23}, -+ {"j", "J", 'j', 'J', 0x24}, -+ {"k", "K", 'k', 'K', 0x25}, -+ {"l", "L", 'l', 'L', 0x26}, -+ {"semicolon", "colon", ';', ':', 0x27}, -+ {"quote", "doublequote", '\'', '"', 0x28}, -+ {"backquote", "tilde", '`', '~', 0x29}, -+ {"shift", 0, 0, 0, 0x2a}, -+ {"backslash", "bar", '\\', '|', 0x2b}, -+ {"z", "Z", 'z', 'Z', 0x2c}, -+ {"x", "X", 'x', 'X', 0x2d}, -+ {"c", "C", 'c', 'C', 0x2e}, -+ {"v", "V", 'v', 'V', 0x2f}, -+ {"b", "B", 'b', 'B', 0x30}, -+ {"n", "N", 'n', 'N', 0x31}, -+ {"m", "M", 'm', 'M', 0x32}, -+ {"comma", "less", ',', '<', 0x33}, -+ {"period", "greater", '.', '>', 0x34}, -+ {"slash", "question", '/', '?', 0x35}, -+ {"alt", 0, 0, 0, 0x38}, -+ {"space", 0, ' ', 0, 0x39}, -+ {"capslock", 0, 0, 0, 0x3a}, -+ {"F1", 0, 0, 0, 0x3b}, -+ {"F2", 0, 0, 0, 0x3c}, -+ {"F3", 0, 0, 0, 0x3d}, -+ {"F4", 0, 0, 0, 0x3e}, -+ {"F5", 0, 0, 0, 0x3f}, -+ {"F6", 0, 0, 0, 0x40}, -+ {"F7", 0, 0, 0, 0x41}, -+ {"F8", 0, 0, 0, 0x42}, -+ {"F9", 0, 0, 0, 0x43}, -+ {"F10", 0, 0, 0, 0x44}, -+ /* Caution: do not add NumLock here! we cannot deal with it properly. */ -+ {"delete", 0, 0x7f, 0, 0x53} -+}; -+ -+static int -+setkey_func (char *arg, int flags) -+{ -+ char *to_key, *from_key; -+ int to_code, from_code; -+ int map_in_interrupt = 0; -+ -+ static int find_key_code (char *key) -+ { -+ int i; -+ -+ for (i = 0; i < sizeof (keysym_table) / sizeof (keysym_table[0]); i++) -+ { -+ if (keysym_table[i].unshifted_name && -+ grub_strcmp (key, keysym_table[i].unshifted_name) == 0) -+ return keysym_table[i].keycode; -+ else if (keysym_table[i].shifted_name && -+ grub_strcmp (key, keysym_table[i].shifted_name) == 0) -+ return keysym_table[i].keycode; -+ } -+ -+ return 0; -+ } -+ -+ static int find_ascii_code (char *key) -+ { -+ int i; -+ -+ for (i = 0; i < sizeof (keysym_table) / sizeof (keysym_table[0]); i++) -+ { -+ if (keysym_table[i].unshifted_name && -+ grub_strcmp (key, keysym_table[i].unshifted_name) == 0) -+ return keysym_table[i].unshifted_ascii; -+ else if (keysym_table[i].shifted_name && -+ grub_strcmp (key, keysym_table[i].shifted_name) == 0) -+ return keysym_table[i].shifted_ascii; -+ } -+ -+ return 0; -+ } -+ -+ to_key = arg; -+ from_key = skip_to (0, to_key); -+ -+ if (! *to_key) -+ { -+ /* If the user specifies no argument, reset the key mappings. */ -+ grub_memset (bios_key_map, 0, KEY_MAP_SIZE * sizeof (unsigned short)); -+ grub_memset (ascii_key_map, 0, KEY_MAP_SIZE * sizeof (unsigned short)); -+ -+ return 0; -+ } -+ else if (! *from_key) -+ { -+ /* The user must specify two arguments or zero argument. */ -+ errnum = ERR_BAD_ARGUMENT; -+ return 1; -+ } -+ -+ nul_terminate (to_key); -+ nul_terminate (from_key); -+ -+ to_code = find_ascii_code (to_key); -+ from_code = find_ascii_code (from_key); -+ if (! to_code || ! from_code) -+ { -+ map_in_interrupt = 1; -+ to_code = find_key_code (to_key); -+ from_code = find_key_code (from_key); -+ if (! to_code || ! from_code) -+ { -+ errnum = ERR_BAD_ARGUMENT; -+ return 1; -+ } -+ } -+ -+ if (map_in_interrupt) -+ { -+ int i; -+ -+ /* Find an empty slot. */ -+ for (i = 0; i < KEY_MAP_SIZE; i++) -+ { -+ if ((bios_key_map[i] & 0xff) == from_code) -+ /* Perhaps the user wants to overwrite the map. */ -+ break; -+ -+ if (! bios_key_map[i]) -+ break; -+ } -+ -+ if (i == KEY_MAP_SIZE) -+ { -+ errnum = ERR_WONT_FIT; -+ return 1; -+ } -+ -+ if (to_code == from_code) -+ /* If TO is equal to FROM, delete the entry. */ -+ grub_memmove ((char *) &bios_key_map[i], -+ (char *) &bios_key_map[i + 1], -+ sizeof (unsigned short) * (KEY_MAP_SIZE - i)); -+ else -+ bios_key_map[i] = (to_code << 8) | from_code; -+ -+ /* Ugly but should work. */ -+ unset_int15_handler (); -+ set_int15_handler (); -+ } -+ else -+ { -+ int i; -+ -+ /* Find an empty slot. */ -+ for (i = 0; i < KEY_MAP_SIZE; i++) -+ { -+ if ((ascii_key_map[i] & 0xff) == from_code) -+ /* Perhaps the user wants to overwrite the map. */ -+ break; -+ -+ if (! ascii_key_map[i]) -+ break; -+ } -+ -+ if (i == KEY_MAP_SIZE) -+ { -+ errnum = ERR_WONT_FIT; -+ return 1; -+ } -+ -+ if (to_code == from_code) -+ /* If TO is equal to FROM, delete the entry. */ -+ grub_memmove ((char *) &ascii_key_map[i], -+ (char *) &ascii_key_map[i + 1], -+ sizeof (unsigned short) * (KEY_MAP_SIZE - i)); -+ else -+ ascii_key_map[i] = (to_code << 8) | from_code; -+ } -+ -+ return 0; -+} -+ -+static struct builtin builtin_setkey = -+{ -+ "setkey", -+ setkey_func, -+ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, -+ "setkey [TO_KEY FROM_KEY]", -+ "Change the keyboard map. The key FROM_KEY is mapped to the key TO_KEY." -+ " A key must be an alphabet, a digit, or one of these: escape, exclam," -+ " at, numbersign, dollar, percent, caret, ampersand, asterisk, parenleft," -+ " parenright, minus, underscore, equal, plus, backspace, tab, bracketleft," -+ " braceleft, bracketright, braceright, enter, control, semicolon, colon," -+ " quote, doublequote, backquote, tilde, shift, backslash, bar, comma," -+ " less, period, greater, slash, question, alt, space, capslock, FX (X" -+ " is a digit), and delete. If no argument is specified, reset key" -+ " mappings." -+}; -+ -+ -+/* setup */ -+static int -+setup_func (char *arg, int flags) -+{ -+ /* Point to the string of the installed drive/partition. */ -+ char *install_ptr; -+ /* Point to the string of the drive/parition where the GRUB images -+ reside. */ -+ char *image_ptr; -+ unsigned long installed_drive, installed_partition; -+ unsigned long image_drive, image_partition; -+ unsigned long tmp_drive, tmp_partition; -+ char stage1[64]; -+ char stage2[64]; -+ char config_filename[64]; -+ char real_config_filename[64]; -+ char cmd_arg[256]; -+ char device[16]; -+ char *buffer = (char *) RAW_ADDR (0x100000); -+ int is_force_lba = 0; -+ char *stage2_arg = 0; -+ char *prefix = 0; -+ -+ auto int check_file (char *file); -+ auto void sprint_device (int drive, int partition); -+ auto int embed_stage1_5 (char * stage1_5, int drive, int partition); -+ -+ /* Check if the file FILE exists like Autoconf. */ -+ int check_file (char *file) -+ { -+ int ret; -+ -+ grub_printf (" Checking if \"%s\" exists... ", file); -+ ret = grub_open (file); -+ if (ret) -+ { -+ grub_close (); -+ grub_printf ("yes\n"); -+ } -+ else -+ grub_printf ("no\n"); -+ -+ return ret; -+ } -+ -+ /* Construct a device name in DEVICE. */ -+ void sprint_device (int drive, int partition) -+ { -+ grub_sprintf (device, "(%cd%d", -+ (drive & 0x80) ? 'h' : 'f', -+ drive & ~0x80); -+ if ((partition & 0xFF0000) != 0xFF0000) -+ { -+ char tmp[16]; -+ grub_sprintf (tmp, ",%d", (partition >> 16) & 0xFF); -+ grub_strncat (device, tmp, 256); -+ } -+ if ((partition & 0x00FF00) != 0x00FF00) -+ { -+ char tmp[16]; -+ grub_sprintf (tmp, ",%c", 'a' + ((partition >> 8) & 0xFF)); -+ grub_strncat (device, tmp, 256); -+ } -+ grub_strncat (device, ")", 256); -+ } -+ -+ int embed_stage1_5 (char *stage1_5, int drive, int partition) -+ { -+ /* We install GRUB into the MBR, so try to embed the -+ Stage 1.5 in the sectors right after the MBR. */ -+ sprint_device (drive, partition); -+ grub_sprintf (cmd_arg, "%s %s", stage1_5, device); -+ -+ /* Notify what will be run. */ -+ grub_printf (" Running \"embed %s\"... ", cmd_arg); -+ -+ embed_func (cmd_arg, flags); -+ if (! errnum) -+ { -+ /* Construct the blocklist representation. */ -+ grub_sprintf (buffer, "%s%s", device, embed_info); -+ grub_printf ("succeeded\n"); -+ return 1; -+ } -+ else -+ { -+ grub_printf ("failed (this is not fatal)\n"); -+ return 0; -+ } -+ } -+ -+ struct stage1_5_map { -+ char *fsys; -+ char *name; -+ }; -+ struct stage1_5_map stage1_5_map[] = -+ { -+ {"ext2fs", "/e2fs_stage1_5"}, -+ {"fat", "/fat_stage1_5"}, -+ {"ffs", "/ffs_stage1_5"}, -+ {"jfs", "/jfs_stage1_5"}, -+ {"minix", "/minix_stage1_5"}, -+ {"reiserfs", "/reiserfs_stage1_5"}, -+ {"vstafs", "/vstafs_stage1_5"}, -+ {"xfs", "/xfs_stage1_5"} -+ }; -+ -+ tmp_drive = saved_drive; -+ tmp_partition = saved_partition; -+ -+ /* Check if the user specifies --force-lba. */ -+ while (1) -+ { -+ if (grub_memcmp ("--force-lba", arg, sizeof ("--force-lba") - 1) == 0) -+ { -+ is_force_lba = 1; -+ arg = skip_to (0, arg); -+ } -+ else if (grub_memcmp ("--prefix=", arg, sizeof ("--prefix=") - 1) == 0) -+ { -+ prefix = arg + sizeof ("--prefix=") - 1; -+ arg = skip_to (0, arg); -+ nul_terminate (prefix); -+ } -+#ifdef GRUB_UTIL -+ else if (grub_memcmp ("--stage2=", arg, sizeof ("--stage2=") - 1) == 0) -+ { -+ stage2_arg = arg; -+ arg = skip_to (0, arg); -+ nul_terminate (stage2_arg); -+ } -+#endif /* GRUB_UTIL */ -+ else -+ break; -+ } -+ -+ install_ptr = arg; -+ image_ptr = skip_to (0, install_ptr); -+ -+ /* Make sure that INSTALL_PTR is valid. */ -+ set_device (install_ptr); -+ if (errnum) -+ return 1; -+ -+ installed_drive = current_drive; -+ installed_partition = current_partition; -+ -+ /* Mount the drive pointed by IMAGE_PTR. */ -+ if (*image_ptr) -+ { -+ /* If the drive/partition where the images reside is specified, -+ get the drive and the partition. */ -+ set_device (image_ptr); -+ if (errnum) -+ return 1; -+ } -+ else -+ { -+ /* If omitted, use SAVED_PARTITION and SAVED_DRIVE. */ -+ current_drive = saved_drive; -+ current_partition = saved_partition; -+ } -+ -+ image_drive = saved_drive = current_drive; -+ image_partition = saved_partition = current_partition; -+ -+ /* Open it. */ -+ if (! open_device ()) -+ goto fail; -+ -+ /* Check if stage1 exists. If the user doesn't specify the option -+ `--prefix', attempt /boot/grub and /grub. */ -+ /* NOTE: It is dangerous to run this command without `--prefix' in the -+ grub shell, since that affects `--stage2'. */ -+ if (! prefix) -+ { -+ prefix = "/boot/grub"; -+ grub_sprintf (stage1, "%s%s", prefix, "/stage1"); -+ if (! check_file (stage1)) -+ { -+ errnum = ERR_NONE; -+ prefix = "/grub"; -+ grub_sprintf (stage1, "%s%s", prefix, "/stage1"); -+ if (! check_file (stage1)) -+ goto fail; -+ } -+ } -+ else -+ { -+ grub_sprintf (stage1, "%s%s", prefix, "/stage1"); -+ if (! check_file (stage1)) -+ goto fail; -+ } -+ -+ /* The prefix was determined. */ -+ grub_sprintf (stage2, "%s%s", prefix, "/stage2"); -+ grub_sprintf (config_filename, "%s%s", prefix, "/menu.lst"); -+ *real_config_filename = 0; -+ -+ /* Check if stage2 exists. */ -+ if (! check_file (stage2)) -+ goto fail; -+ -+ { -+ char *fsys = fsys_table[fsys_type].name; -+ int i; -+ int size = sizeof (stage1_5_map) / sizeof (stage1_5_map[0]); -+ -+ /* Iterate finding the same filesystem name as FSYS. */ -+ for (i = 0; i < size; i++) -+ if (grub_strcmp (fsys, stage1_5_map[i].fsys) == 0) -+ { -+ /* OK, check if the Stage 1.5 exists. */ -+ char stage1_5[64]; -+ -+ grub_sprintf (stage1_5, "%s%s", prefix, stage1_5_map[i].name); -+ if (check_file (stage1_5)) -+ { -+ if (embed_stage1_5 (stage1_5, -+ installed_drive, installed_partition) -+ || embed_stage1_5 (stage1_5, -+ image_drive, image_partition)) -+ { -+ grub_strcpy (real_config_filename, config_filename); -+ sprint_device (image_drive, image_partition); -+ grub_sprintf (config_filename, "%s%s", device, stage2); -+ grub_strcpy (stage2, buffer); -+ } -+ } -+ errnum = 0; -+ break; -+ } -+ } -+ -+ /* Construct a string that is used by the command "install" as its -+ arguments. */ -+ sprint_device (installed_drive, installed_partition); -+ -+#if 1 -+ /* Don't embed a drive number unnecessarily. */ -+ grub_sprintf (cmd_arg, "%s%s%s%s %s%s %s p %s %s", -+ is_force_lba? "--force-lba " : "", -+ stage2_arg? stage2_arg : "", -+ stage2_arg? " " : "", -+ stage1, -+ (installed_drive != image_drive) ? "d " : "", -+ device, -+ stage2, -+ config_filename, -+ real_config_filename); -+#else /* NOT USED */ -+ /* This code was used, because we belived some BIOSes had a problem -+ that they didn't pass a booting drive correctly. It turned out, -+ however, stage1 could trash a booting drive when checking LBA support, -+ because some BIOSes modified the register %dx in INT 13H, AH=48H. -+ So it becamed unclear whether GRUB should use a pre-defined booting -+ drive or not. If the problem still exists, it would be necessary to -+ switch back to this code. */ -+ grub_sprintf (cmd_arg, "%s%s%s%s d %s %s p %s %s", -+ is_force_lba? "--force-lba " : "", -+ stage2_arg? stage2_arg : "", -+ stage2_arg? " " : "", -+ stage1, -+ device, -+ stage2, -+ config_filename, -+ real_config_filename); -+#endif /* NOT USED */ -+ -+ /* Notify what will be run. */ -+ grub_printf (" Running \"install %s\"... ", cmd_arg); -+ -+ /* Make sure that SAVED_DRIVE and SAVED_PARTITION are identical -+ with IMAGE_DRIVE and IMAGE_PARTITION, respectively. */ -+ saved_drive = image_drive; -+ saved_partition = image_partition; -+ -+ /* Run the command. */ -+ if (! install_func (cmd_arg, flags)) -+ grub_printf ("succeeded\nDone.\n"); -+ else -+ grub_printf ("failed\n"); -+ -+ fail: -+ saved_drive = tmp_drive; -+ saved_partition = tmp_partition; -+ return errnum; -+} -+ -+static struct builtin builtin_setup = -+{ -+ "setup", -+ setup_func, -+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST, -+ "setup [--prefix=DIR] [--stage2=STAGE2_FILE] [--force-lba] INSTALL_DEVICE [IMAGE_DEVICE]", -+ "Set up the installation of GRUB automatically. This command uses" -+ " the more flexible command \"install\" in the backend and installs" -+ " GRUB into the device INSTALL_DEVICE. If IMAGE_DEVICE is specified," -+ " then find the GRUB images in the device IMAGE_DEVICE, otherwise" -+ " use the current \"root device\", which can be set by the command" -+ " \"root\". If you know that your BIOS should support LBA but GRUB" -+ " doesn't work in LBA mode, specify the option `--force-lba'." -+ " If you install GRUB under the grub shell and you cannot unmount the" -+ " partition where GRUB images reside, specify the option `--stage2'" -+ " to tell GRUB the file name under your OS." -+}; -+ -+ -+#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) -+/* terminal */ -+static int -+terminal_func (char *arg, int flags) -+{ -+ /* The index of the default terminal in TERM_TABLE. */ -+ int default_term = -1; -+ struct term_entry *prev_term = current_term; -+ int to = -1; -+ int lines = 0; -+ int no_message = 0; -+ unsigned long term_flags = 0; -+ /* XXX: Assume less than 32 terminals. */ -+ unsigned long term_bitmap = 0; -+ -+ /* Get GNU-style long options. */ -+ while (1) -+ { -+ if (grub_memcmp (arg, "--dumb", sizeof ("--dumb") - 1) == 0) -+ term_flags |= TERM_DUMB; -+ else if (grub_memcmp (arg, "--no-echo", sizeof ("--no-echo") - 1) == 0) -+ /* ``--no-echo'' implies ``--no-edit''. */ -+ term_flags |= (TERM_NO_ECHO | TERM_NO_EDIT); -+ else if (grub_memcmp (arg, "--no-edit", sizeof ("--no-edit") - 1) == 0) -+ term_flags |= TERM_NO_EDIT; -+ else if (grub_memcmp (arg, "--timeout=", sizeof ("--timeout=") - 1) == 0) -+ { -+ char *val = arg + sizeof ("--timeout=") - 1; -+ -+ if (! safe_parse_maxint (&val, &to)) -+ return 1; -+ } -+ else if (grub_memcmp (arg, "--lines=", sizeof ("--lines=") - 1) == 0) -+ { -+ char *val = arg + sizeof ("--lines=") - 1; -+ -+ if (! safe_parse_maxint (&val, &lines)) -+ return 1; -+ -+ /* Probably less than four is meaningless.... */ -+ if (lines < 4) -+ { -+ errnum = ERR_BAD_ARGUMENT; -+ return 1; -+ } -+ } -+ else if (grub_memcmp (arg, "--silent", sizeof ("--silent") - 1) == 0) -+ no_message = 1; -+ else -+ break; -+ -+ arg = skip_to (0, arg); -+ } -+ -+ /* If no argument is specified, show current setting. */ -+ if (! *arg) -+ { -+ grub_printf ("%s%s%s%s\n", -+ current_term->name, -+ current_term->flags & TERM_DUMB ? " (dumb)" : "", -+ current_term->flags & TERM_NO_EDIT ? " (no edit)" : "", -+ current_term->flags & TERM_NO_ECHO ? " (no echo)" : ""); -+ return 0; -+ } -+ -+ while (*arg) -+ { -+ int i; -+ char *next = skip_to (0, arg); -+ -+ nul_terminate (arg); -+ -+ for (i = 0; term_table[i].name; i++) -+ { -+ if (grub_strcmp (arg, term_table[i].name) == 0) -+ { -+ if (term_table[i].flags & TERM_NEED_INIT) -+ { -+ errnum = ERR_DEV_NEED_INIT; -+ return 1; -+ } -+ -+ if (default_term < 0) -+ default_term = i; -+ -+ term_bitmap |= (1 << i); -+ break; -+ } -+ } -+ -+ if (! term_table[i].name) -+ { -+ errnum = ERR_BAD_ARGUMENT; -+ return 1; -+ } -+ -+ arg = next; -+ } -+ -+ /* If multiple terminals are specified, wait until the user pushes any -+ key on one of the terminals. */ -+ if (term_bitmap & ~(1 << default_term)) -+ { -+ int time1, time2 = -1; -+ -+ /* XXX: Disable the pager. */ -+ count_lines = -1; -+ -+ /* Get current time. */ -+ while ((time1 = getrtsecs ()) == 0xFF) -+ ; -+ -+ /* Wait for a key input. */ -+ while (to) -+ { -+ int i; -+ -+ for (i = 0; term_table[i].name; i++) -+ { -+ if (term_bitmap & (1 << i)) -+ { -+ if (term_table[i].checkkey () >= 0) -+ { -+ (void) term_table[i].getkey (); -+ default_term = i; -+ -+ goto end; -+ } -+ } -+ } -+ -+ /* Prompt the user, once per sec. */ -+ if ((time1 = getrtsecs ()) != time2 && time1 != 0xFF) -+ { -+ if (! no_message) -+ { -+ /* Need to set CURRENT_TERM to each of selected -+ terminals. */ -+ for (i = 0; term_table[i].name; i++) -+ if (term_bitmap & (1 << i)) -+ { -+ current_term = term_table + i; -+ grub_printf ("\rPress any key to continue.\n"); -+ } -+ -+ /* Restore CURRENT_TERM. */ -+ current_term = prev_term; -+ } -+ -+ time2 = time1; -+ if (to > 0) -+ to--; -+ } -+ } -+ } -+ -+ end: -+ current_term = term_table + default_term; -+ current_term->flags = term_flags; -+ -+ if (lines) -+ max_lines = lines; -+ else -+ /* 24 would be a good default value. */ -+ max_lines = 24; -+ -+ /* If the interface is currently the command-line, -+ restart it to repaint the screen. */ -+ if (current_term != prev_term && (flags & BUILTIN_CMDLINE)) -+ grub_longjmp (restart_cmdline_env, 0); -+ -+ return 0; -+} -+ -+static struct builtin builtin_terminal = -+{ -+ "terminal", -+ terminal_func, -+ BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST, -+ "terminal [--dumb] [--no-echo] [--no-edit] [--timeout=SECS] [--lines=LINES] [--silent] [console] [serial] [hercules]", -+ "Select a terminal. When multiple terminals are specified, wait until" -+ " you push any key to continue. If both console and serial are specified," -+ " the terminal to which you input a key first will be selected. If no" -+ " argument is specified, print current setting. The option --dumb" -+ " specifies that your terminal is dumb, otherwise, vt100-compatibility" -+ " is assumed. If you specify --no-echo, input characters won't be echoed." -+ " If you specify --no-edit, the BASH-like editing feature will be disabled." -+ " If --timeout is present, this command will wait at most for SECS" -+ " seconds. The option --lines specifies the maximum number of lines." -+ " The option --silent is used to suppress messages." -+}; -+#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES */ -+ -+ -+#ifdef SUPPORT_SERIAL -+static int -+terminfo_func (char *arg, int flags) -+{ -+ struct terminfo term; -+ -+ if (*arg) -+ { -+ struct -+ { -+ const char *name; -+ char *var; -+ } -+ options[] = -+ { -+ {"--name=", term.name}, -+ {"--cursor-address=", term.cursor_address}, -+ {"--clear-screen=", term.clear_screen}, -+ {"--enter-standout-mode=", term.enter_standout_mode}, -+ {"--exit-standout-mode=", term.exit_standout_mode} -+ }; -+ -+ grub_memset (&term, 0, sizeof (term)); -+ -+ while (*arg) -+ { -+ int i; -+ char *next = skip_to (0, arg); -+ -+ nul_terminate (arg); -+ -+ for (i = 0; i < sizeof (options) / sizeof (options[0]); i++) -+ { -+ const char *name = options[i].name; -+ int len = grub_strlen (name); -+ -+ if (! grub_memcmp (arg, name, len)) -+ { -+ grub_strcpy (options[i].var, ti_unescape_string (arg + len)); -+ break; -+ } -+ } -+ -+ if (i == sizeof (options) / sizeof (options[0])) -+ { -+ errnum = ERR_BAD_ARGUMENT; -+ return errnum; -+ } -+ -+ arg = next; -+ } -+ -+ if (term.name[0] == 0 || term.cursor_address[0] == 0) -+ { -+ errnum = ERR_BAD_ARGUMENT; -+ return errnum; -+ } -+ -+ ti_set_term (&term); -+ } -+ else -+ { -+ /* No option specifies printing out current settings. */ -+ ti_get_term (&term); -+ -+ grub_printf ("name=%s\n", -+ ti_escape_string (term.name)); -+ grub_printf ("cursor_address=%s\n", -+ ti_escape_string (term.cursor_address)); -+ grub_printf ("clear_screen=%s\n", -+ ti_escape_string (term.clear_screen)); -+ grub_printf ("enter_standout_mode=%s\n", -+ ti_escape_string (term.enter_standout_mode)); -+ grub_printf ("exit_standout_mode=%s\n", -+ ti_escape_string (term.exit_standout_mode)); -+ } -+ -+ return 0; -+} -+ -+static struct builtin builtin_terminfo = -+{ -+ "terminfo", -+ terminfo_func, -+ BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST, -+ "terminfo [--name=NAME --cursor-address=SEQ [--clear-screen=SEQ]" -+ " [--enter-standout-mode=SEQ] [--exit-standout-mode=SEQ]]", -+ -+ "Define the capabilities of your terminal. Use this command to" -+ " define escape sequences, if it is not vt100-compatible." -+ " You may use \\e for ESC and ^X for a control character." -+ " If no option is specified, the current settings are printed." -+}; -+#endif /* SUPPORT_SERIAL */ -+ -+ -+/* testload */ -+static int -+testload_func (char *arg, int flags) -+{ -+ int i; -+ -+ kernel_type = KERNEL_TYPE_NONE; -+ -+ if (! grub_open (arg)) -+ return 1; -+ -+ disk_read_hook = disk_read_print_func; -+ -+ /* Perform filesystem test on the specified file. */ -+ /* Read whole file first. */ -+ grub_printf ("Whole file: "); -+ -+ grub_read ((char *) RAW_ADDR (0x100000), -1); -+ -+ /* Now compare two sections of the file read differently. */ -+ -+ for (i = 0; i < 0x10ac0; i++) -+ { -+ *((unsigned char *) RAW_ADDR (0x200000 + i)) = 0; -+ *((unsigned char *) RAW_ADDR (0x300000 + i)) = 1; -+ } -+ -+ /* First partial read. */ -+ grub_printf ("\nPartial read 1: "); -+ -+ grub_seek (0); -+ grub_read ((char *) RAW_ADDR (0x200000), 0x7); -+ grub_read ((char *) RAW_ADDR (0x200007), 0x100); -+ grub_read ((char *) RAW_ADDR (0x200107), 0x10); -+ grub_read ((char *) RAW_ADDR (0x200117), 0x999); -+ grub_read ((char *) RAW_ADDR (0x200ab0), 0x10); -+ grub_read ((char *) RAW_ADDR (0x200ac0), 0x10000); -+ -+ /* Second partial read. */ -+ grub_printf ("\nPartial read 2: "); -+ -+ grub_seek (0); -+ grub_read ((char *) RAW_ADDR (0x300000), 0x10000); -+ grub_read ((char *) RAW_ADDR (0x310000), 0x10); -+ grub_read ((char *) RAW_ADDR (0x310010), 0x7); -+ grub_read ((char *) RAW_ADDR (0x310017), 0x10); -+ grub_read ((char *) RAW_ADDR (0x310027), 0x999); -+ grub_read ((char *) RAW_ADDR (0x3109c0), 0x100); -+ -+ grub_printf ("\nHeader1 = 0x%x, next = 0x%x, next = 0x%x, next = 0x%x\n", -+ *((int *) RAW_ADDR (0x200000)), -+ *((int *) RAW_ADDR (0x200004)), -+ *((int *) RAW_ADDR (0x200008)), -+ *((int *) RAW_ADDR (0x20000c))); -+ -+ grub_printf ("Header2 = 0x%x, next = 0x%x, next = 0x%x, next = 0x%x\n", -+ *((int *) RAW_ADDR (0x300000)), -+ *((int *) RAW_ADDR (0x300004)), -+ *((int *) RAW_ADDR (0x300008)), -+ *((int *) RAW_ADDR (0x30000c))); -+ -+ for (i = 0; i < 0x10ac0; i++) -+ if (*((unsigned char *) RAW_ADDR (0x200000 + i)) -+ != *((unsigned char *) RAW_ADDR (0x300000 + i))) -+ break; -+ -+ grub_printf ("Max is 0x10ac0: i=0x%x, filepos=0x%x\n", i, filepos); -+ disk_read_hook = 0; -+ grub_close (); -+ return 0; -+} -+ -+static struct builtin builtin_testload = -+{ -+ "testload", -+ testload_func, -+ BUILTIN_CMDLINE, -+ "testload FILE", -+ "Read the entire contents of FILE in several different ways and" -+ " compares them, to test the filesystem code. The output is somewhat" -+ " cryptic, but if no errors are reported and the final `i=X," -+ " filepos=Y' reading has X and Y equal, then it is definitely" -+ " consistent, and very likely works correctly subject to a" -+ " consistent offset error. If this test succeeds, then a good next" -+ " step is to try loading a kernel." -+}; -+ -+ -+/* testvbe MODE */ -+static int -+testvbe_func (char *arg, int flags) -+{ -+ int mode_number; -+ struct vbe_controller controller; -+ struct vbe_mode mode; -+ -+ if (! *arg) -+ { -+ errnum = ERR_BAD_ARGUMENT; -+ return 1; -+ } -+ -+ if (! safe_parse_maxint (&arg, &mode_number)) -+ return 1; -+ -+ /* Preset `VBE2'. */ -+ grub_memmove (controller.signature, "VBE2", 4); -+ -+ /* Detect VBE BIOS. */ -+ if (get_vbe_controller_info (&controller) != 0x004F) -+ { -+ grub_printf (" VBE BIOS is not present.\n"); -+ return 0; -+ } -+ -+ if (controller.version < 0x0200) -+ { -+ grub_printf (" VBE version %d.%d is not supported.\n", -+ (int) (controller.version >> 8), -+ (int) (controller.version & 0xFF)); -+ return 0; -+ } -+ -+ if (get_vbe_mode_info (mode_number, &mode) != 0x004F -+ || (mode.mode_attributes & 0x0091) != 0x0091) -+ { -+ grub_printf (" Mode 0x%x is not supported.\n", mode_number); -+ return 0; -+ } -+ -+ /* Now trip to the graphics mode. */ -+ if (set_vbe_mode (mode_number | (1 << 14)) != 0x004F) -+ { -+ grub_printf (" Switching to Mode 0x%x failed.\n", mode_number); -+ return 0; -+ } -+ -+ /* Draw something on the screen... */ -+ { -+ unsigned char *base_buf = (unsigned char *) mode.phys_base; -+ int scanline = controller.version >= 0x0300 -+ ? mode.linear_bytes_per_scanline : mode.bytes_per_scanline; -+ /* FIXME: this assumes that any depth is a modulo of 8. */ -+ int bpp = mode.bits_per_pixel / 8; -+ int width = mode.x_resolution; -+ int height = mode.y_resolution; -+ int x, y; -+ unsigned color = 0; -+ -+ /* Iterate drawing on the screen, until the user hits any key. */ -+ while (checkkey () == -1) -+ { -+ for (y = 0; y < height; y++) -+ { -+ unsigned char *line_buf = base_buf + scanline * y; -+ -+ for (x = 0; x < width; x++) -+ { -+ unsigned char *buf = line_buf + bpp * x; -+ int i; -+ -+ for (i = 0; i < bpp; i++, buf++) -+ *buf = (color >> (i * 8)) & 0xff; -+ } -+ -+ color++; -+ } -+ } -+ -+ /* Discard the input. */ -+ getkey (); -+ } -+ -+ /* Back to the default text mode. */ -+ if (set_vbe_mode (0x03) != 0x004F) -+ { -+ /* Why?! */ -+ grub_reboot (); -+ } -+ -+ return 0; -+} -+ -+static struct builtin builtin_testvbe = -+{ -+ "testvbe", -+ testvbe_func, -+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST, -+ "testvbe MODE", -+ "Test the VBE mode MODE. Hit any key to return." -+}; -+ -+ -+#ifdef SUPPORT_NETBOOT -+/* tftpserver */ -+static int -+tftpserver_func (char *arg, int flags) -+{ -+ if (! *arg || ! ifconfig (0, 0, 0, arg)) -+ { -+ errnum = ERR_BAD_ARGUMENT; -+ return 1; -+ } -+ -+ print_network_configuration (); -+ return 0; -+} -+ -+static struct builtin builtin_tftpserver = -+{ -+ "tftpserver", -+ tftpserver_func, -+ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, -+ "tftpserver IPADDR", -+ "Override the TFTP server address." -+}; -+#endif /* SUPPORT_NETBOOT */ -+ -+ -+/* timeout */ -+static int -+timeout_func (char *arg, int flags) -+{ -+ if (! safe_parse_maxint (&arg, &grub_timeout)) -+ return 1; -+ -+ return 0; -+} -+ -+static struct builtin builtin_timeout = -+{ -+ "timeout", -+ timeout_func, -+ BUILTIN_MENU, -+#if 0 -+ "timeout SEC", -+ "Set a timeout, in SEC seconds, before automatically booting the" -+ " default entry (normally the first entry defined)." -+#endif -+}; -+ -+ -+/* title */ -+static int -+title_func (char *arg, int flags) -+{ -+ /* This function is not actually used at least currently. */ -+ return 0; -+} -+ -+static struct builtin builtin_title = -+{ -+ "title", -+ title_func, -+ BUILTIN_TITLE, -+#if 0 -+ "title [NAME ...]", -+ "Start a new boot entry, and set its name to the contents of the" -+ " rest of the line, starting with the first non-space character." -+#endif -+}; -+ -+ -+/* unhide */ -+static int -+unhide_func (char *arg, int flags) -+{ -+ if (! set_device (arg)) -+ return 1; -+ -+ if (! set_partition_hidden_flag (0)) -+ return 1; -+ -+ return 0; -+} -+ -+static struct builtin builtin_unhide = -+{ -+ "unhide", -+ unhide_func, -+ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, -+ "unhide PARTITION", -+ "Unhide PARTITION by clearing the \"hidden\" bit in its" -+ " partition type code." -+}; -+ -+ -+/* uppermem */ -+static int -+uppermem_func (char *arg, int flags) -+{ -+ if (! safe_parse_maxint (&arg, (int *) &mbi.mem_upper)) -+ return 1; -+ -+ mbi.flags &= ~MB_INFO_MEM_MAP; -+ return 0; -+} -+ -+static struct builtin builtin_uppermem = -+{ -+ "uppermem", -+ uppermem_func, -+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST, -+ "uppermem KBYTES", -+ "Force GRUB to assume that only KBYTES kilobytes of upper memory are" -+ " installed. Any system address range maps are discarded." -+}; -+ -+ -+/* vbeprobe */ -+static int -+vbeprobe_func (char *arg, int flags) -+{ -+ struct vbe_controller controller; -+ unsigned short *mode_list; -+ int mode_number = -1; -+ -+ auto unsigned long vbe_far_ptr_to_linear (unsigned long); -+ -+ unsigned long vbe_far_ptr_to_linear (unsigned long ptr) -+ { -+ unsigned short seg = (ptr >> 16); -+ unsigned short off = (ptr & 0xFFFF); -+ -+ return (seg << 4) + off; -+ } -+ -+ if (*arg) -+ { -+ if (! safe_parse_maxint (&arg, &mode_number)) -+ return 1; -+ } -+ -+ /* Set the signature to `VBE2', to obtain VBE 3.0 information. */ -+ grub_memmove (controller.signature, "VBE2", 4); -+ -+ if (get_vbe_controller_info (&controller) != 0x004F) -+ { -+ grub_printf (" VBE BIOS is not present.\n"); -+ return 0; -+ } -+ -+ /* Check the version. */ -+ if (controller.version < 0x0200) -+ { -+ grub_printf (" VBE version %d.%d is not supported.\n", -+ (int) (controller.version >> 8), -+ (int) (controller.version & 0xFF)); -+ return 0; -+ } -+ -+ /* Print some information. */ -+ grub_printf (" VBE version %d.%d\n", -+ (int) (controller.version >> 8), -+ (int) (controller.version & 0xFF)); -+ -+ /* Iterate probing modes. */ -+ for (mode_list -+ = (unsigned short *) vbe_far_ptr_to_linear (controller.video_mode); -+ *mode_list != 0xFFFF; -+ mode_list++) -+ { -+ struct vbe_mode mode; -+ -+ if (get_vbe_mode_info (*mode_list, &mode) != 0x004F) -+ continue; -+ -+ /* Skip this, if this is not supported or linear frame buffer -+ mode is not support. */ -+ if ((mode.mode_attributes & 0x0081) != 0x0081) -+ continue; -+ -+ if (mode_number == -1 || mode_number == *mode_list) -+ { -+ char *model; -+ switch (mode.memory_model) -+ { -+ case 0x00: model = "Text"; break; -+ case 0x01: model = "CGA graphics"; break; -+ case 0x02: model = "Hercules graphics"; break; -+ case 0x03: model = "Planar"; break; -+ case 0x04: model = "Packed pixel"; break; -+ case 0x05: model = "Non-chain 4, 256 color"; break; -+ case 0x06: model = "Direct Color"; break; -+ case 0x07: model = "YUV"; break; -+ default: model = "Unknown"; break; -+ } -+ -+ grub_printf (" 0x%x: %s, %ux%ux%u\n", -+ (unsigned) *mode_list, -+ model, -+ (unsigned) mode.x_resolution, -+ (unsigned) mode.y_resolution, -+ (unsigned) mode.bits_per_pixel); -+ -+ if (mode_number != -1) -+ break; -+ } -+ } -+ -+ if (mode_number != -1 && mode_number != *mode_list) -+ grub_printf (" Mode 0x%x is not found or supported.\n", mode_number); -+ -+ return 0; -+} -+ -+static struct builtin builtin_vbeprobe = -+{ -+ "vbeprobe", -+ vbeprobe_func, -+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST, -+ "vbeprobe [MODE]", -+ "Probe VBE information. If the mode number MODE is specified, show only" -+ " the information about only the mode." -+}; -+ -+ -+/* The table of builtin commands. Sorted in dictionary order. */ -+struct builtin *builtin_table[] = -+{ -+ &builtin_blocklist, -+ &builtin_boot, -+#ifdef SUPPORT_NETBOOT -+ &builtin_bootp, -+#endif /* SUPPORT_NETBOOT */ -+ &builtin_cat, -+ &builtin_chainloader, -+ &builtin_cmp, -+ &builtin_color, -+ &builtin_configfile, -+ &builtin_debug, -+ &builtin_default, -+#ifdef GRUB_UTIL -+ &builtin_device, -+#endif /* GRUB_UTIL */ -+#ifdef SUPPORT_NETBOOT -+ &builtin_dhcp, -+#endif /* SUPPORT_NETBOOT */ -+ &builtin_displayapm, -+ &builtin_displaymem, -+#ifdef GRUB_UTIL -+ &builtin_dump, -+#endif /* GRUB_UTIL */ -+ &builtin_embed, -+ &builtin_fallback, -+ &builtin_find, -+ &builtin_fstest, -+ &builtin_geometry, -+ &builtin_halt, -+ &builtin_help, -+ &builtin_hiddenmenu, -+ &builtin_hide, -+#ifdef SUPPORT_NETBOOT -+ &builtin_ifconfig, -+#endif /* SUPPORT_NETBOOT */ -+ &builtin_impsprobe, -+ &builtin_initrd, -+ &builtin_install, -+ &builtin_ioprobe, -+ &builtin_kernel, -+ &builtin_lock, -+ &builtin_makeactive, -+ &builtin_map, -+#ifdef USE_MD5_PASSWORDS -+ &builtin_md5crypt, -+#endif /* USE_MD5_PASSWORDS */ -+ &builtin_module, -+ &builtin_modulenounzip, -+ &builtin_pager, -+ &builtin_partnew, -+ &builtin_parttype, -+ &builtin_password, -+ &builtin_pause, -+#ifdef GRUB_UTIL -+ &builtin_quit, -+#endif /* GRUB_UTIL */ -+#ifdef SUPPORT_NETBOOT -+ &builtin_rarp, -+#endif /* SUPPORT_NETBOOT */ -+ &builtin_read, -+ &builtin_reboot, -+ &builtin_root, -+ &builtin_rootnoverify, -+ &builtin_savedefault, -+#ifdef SUPPORT_SERIAL -+ &builtin_serial, -+#endif /* SUPPORT_SERIAL */ -+ &builtin_setkey, -+ &builtin_setup, -+#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) -+ &builtin_terminal, -+#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES */ -+#ifdef SUPPORT_SERIAL -+ &builtin_terminfo, -+#endif /* SUPPORT_SERIAL */ -+ &builtin_testload, -+ &builtin_testvbe, -+#ifdef SUPPORT_NETBOOT -+ &builtin_tftpserver, -+#endif /* SUPPORT_NETBOOT */ -+ &builtin_timeout, -+ &builtin_title, -+ &builtin_unhide, -+ &builtin_uppermem, -+ &builtin_vbeprobe, -+ 0 -+}; -diff -ruN grub-0.94.orig/stage2/disk_io.c stage2/disk_io.c ---- grub-0.94.orig/stage2/disk_io.c Wed Feb 11 00:22:12 2004 -+++ stage2/disk_io.c Wed Feb 11 00:22:29 2004 +diff -ruN stage2/disk_io.c.orig stage2/disk_io.c +--- stage2/disk_io.c.orig Sat Apr 24 20:49:07 2004 ++++ stage2/disk_io.c Sat Apr 24 20:49:16 2004 @@ -72,6 +72,9 @@ # ifdef FSYS_XFS {"xfs", xfs_mount, xfs_read, xfs_dir, 0, 0}, @@ -5783,1754 +116,9 @@ diff -ruN grub-0.94.orig/stage2/disk_io.c stage2/disk_io.c /* XX FFS should come last as it's superblock is commonly crossing tracks on floppies from track 1 to 2, while others only use 1. */ # ifdef FSYS_FFS -diff -ruN grub-0.94.orig/stage2/disk_io.c.orig stage2/disk_io.c.orig ---- grub-0.94.orig/stage2/disk_io.c.orig Thu Jan 1 03:00:00 1970 -+++ stage2/disk_io.c.orig Sun Oct 19 19:58:03 2003 -@@ -0,0 +1,1741 @@ -+/* disk_io.c - implement abstract BIOS disk input and output */ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 1999,2000,2001,2002,2003 Free Software Foundation, Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+ -+#include <shared.h> -+#include <filesys.h> -+ -+#ifdef SUPPORT_NETBOOT -+# define GRUB 1 -+# include <etherboot.h> -+#endif -+ -+#ifdef GRUB_UTIL -+# include <device.h> -+#endif -+ -+/* instrumentation variables */ -+void (*disk_read_hook) (int, int, int) = NULL; -+void (*disk_read_func) (int, int, int) = NULL; -+ -+#ifndef STAGE1_5 -+int print_possibilities; -+ -+static int do_completion; -+static int unique; -+static char *unique_string; -+ -+#endif -+ -+int fsmax; -+struct fsys_entry fsys_table[NUM_FSYS + 1] = -+{ -+ /* TFTP should come first because others don't handle net device. */ -+# ifdef FSYS_TFTP -+ {"tftp", tftp_mount, tftp_read, tftp_dir, tftp_close, 0}, -+# endif -+# ifdef FSYS_FAT -+ {"fat", fat_mount, fat_read, fat_dir, 0, 0}, -+# endif -+# ifdef FSYS_EXT2FS -+ {"ext2fs", ext2fs_mount, ext2fs_read, ext2fs_dir, 0, 0}, -+# endif -+# ifdef FSYS_MINIX -+ {"minix", minix_mount, minix_read, minix_dir, 0, 0}, -+# endif -+# ifdef FSYS_REISERFS -+ {"reiserfs", reiserfs_mount, reiserfs_read, reiserfs_dir, 0, reiserfs_embed}, -+# endif -+# ifdef FSYS_VSTAFS -+ {"vstafs", vstafs_mount, vstafs_read, vstafs_dir, 0, 0}, -+# endif -+# ifdef FSYS_JFS -+ {"jfs", jfs_mount, jfs_read, jfs_dir, 0, jfs_embed}, -+# endif -+# ifdef FSYS_XFS -+ {"xfs", xfs_mount, xfs_read, xfs_dir, 0, 0}, -+# endif -+ /* XX FFS should come last as it's superblock is commonly crossing tracks -+ on floppies from track 1 to 2, while others only use 1. */ -+# ifdef FSYS_FFS -+ {"ffs", ffs_mount, ffs_read, ffs_dir, 0, ffs_embed}, -+# endif -+ {0, 0, 0, 0, 0, 0} -+}; -+ -+ -+/* These have the same format as "boot_drive" and "install_partition", but -+ are meant to be working values. */ -+unsigned long current_drive = 0xFF; -+unsigned long current_partition; -+ -+#ifndef STAGE1_5 -+/* The register ESI should contain the address of the partition to be -+ used for loading a chain-loader when chain-loading the loader. */ -+unsigned long boot_part_addr = 0; -+#endif -+ -+/* -+ * Global variables describing details of the filesystem -+ */ -+ -+/* FIXME: BSD evil hack */ -+#include "freebsd.h" -+int bsd_evil_hack; -+ -+/* filesystem type */ -+int fsys_type = NUM_FSYS; -+#ifndef NO_BLOCK_FILES -+static int block_file = 0; -+#endif /* NO_BLOCK_FILES */ -+ -+/* these are the translated numbers for the open partition */ -+unsigned long part_start; -+unsigned long part_length; -+ -+int current_slice; -+ -+/* disk buffer parameters */ -+int buf_drive = -1; -+int buf_track; -+struct geometry buf_geom; -+ -+/* filesystem common variables */ -+int filepos; -+int filemax; -+ -+int -+rawread (int drive, int sector, int byte_offset, int byte_len, char *buf) -+{ -+ int slen = (byte_offset + byte_len + SECTOR_SIZE - 1) >> SECTOR_BITS; -+ -+ if (byte_len <= 0) -+ return 1; -+ -+ while (byte_len > 0 && !errnum) -+ { -+ int soff, num_sect, bufaddr, track, size = byte_len; -+ -+ /* -+ * Check track buffer. If it isn't valid or it is from the -+ * wrong disk, then reset the disk geometry. -+ */ -+ if (buf_drive != drive) -+ { -+ if (get_diskinfo (drive, &buf_geom)) -+ { -+ errnum = ERR_NO_DISK; -+ return 0; -+ } -+ buf_drive = drive; -+ buf_track = -1; -+ } -+ -+ /* Make sure that SECTOR is valid. */ -+ if (sector < 0 || sector >= buf_geom.total_sectors) -+ { -+ errnum = ERR_GEOM; -+ return 0; -+ } -+ -+ /* Get first sector of track */ -+ soff = sector % buf_geom.sectors; -+ track = sector - soff; -+ num_sect = buf_geom.sectors - soff; -+ bufaddr = BUFFERADDR + (soff * SECTOR_SIZE) + byte_offset; -+ -+ if (track != buf_track) -+ { -+ int bios_err, read_start = track, read_len = buf_geom.sectors; -+ -+ /* -+ * If there's more than one read in this entire loop, then -+ * only make the earlier reads for the portion needed. This -+ * saves filling the buffer with data that won't be used! -+ */ -+ if (slen > num_sect) -+ { -+ read_start = sector; -+ read_len = num_sect; -+ bufaddr = BUFFERADDR + byte_offset; -+ } -+ -+ bios_err = biosdisk (BIOSDISK_READ, drive, &buf_geom, -+ read_start, read_len, BUFFERSEG); -+ if (bios_err) -+ { -+ buf_track = -1; -+ -+ if (bios_err == BIOSDISK_ERROR_GEOMETRY) -+ errnum = ERR_GEOM; -+ else -+ { -+ /* -+ * If there was an error, try to load only the -+ * required sector(s) rather than failing completely. -+ */ -+ if (slen > num_sect -+ || biosdisk (BIOSDISK_READ, drive, &buf_geom, -+ sector, slen, BUFFERSEG)) -+ errnum = ERR_READ; -+ -+ bufaddr = BUFFERADDR + byte_offset; -+ } -+ } -+ else -+ buf_track = track; -+ -+ if ((buf_track == 0 || sector == 0) -+ && (PC_SLICE_TYPE (BUFFERADDR, 0) == PC_SLICE_TYPE_EZD -+ || PC_SLICE_TYPE (BUFFERADDR, 1) == PC_SLICE_TYPE_EZD -+ || PC_SLICE_TYPE (BUFFERADDR, 2) == PC_SLICE_TYPE_EZD -+ || PC_SLICE_TYPE (BUFFERADDR, 3) == PC_SLICE_TYPE_EZD)) -+ { -+ /* This is a EZD disk map sector 0 to sector 1 */ -+ if (buf_track == 0 || slen >= 2) -+ { -+ /* We already read the sector 1, copy it to sector 0 */ -+ memmove ((char *) BUFFERADDR, -+ (char *) BUFFERADDR + SECTOR_SIZE, SECTOR_SIZE); -+ } -+ else -+ { -+ if (biosdisk (BIOSDISK_READ, drive, &buf_geom, -+ 1, 1, BUFFERSEG)) -+ errnum = ERR_READ; -+ } -+ } -+ } -+ -+ if (size > ((num_sect * SECTOR_SIZE) - byte_offset)) -+ size = (num_sect * SECTOR_SIZE) - byte_offset; -+ -+ /* -+ * Instrumentation to tell which sectors were read and used. -+ */ -+ if (disk_read_func) -+ { -+ int sector_num = sector; -+ int length = SECTOR_SIZE - byte_offset; -+ if (length > size) -+ length = size; -+ (*disk_read_func) (sector_num++, byte_offset, length); -+ length = size - length; -+ if (length > 0) -+ { -+ while (length > SECTOR_SIZE) -+ { -+ (*disk_read_func) (sector_num++, 0, SECTOR_SIZE); -+ length -= SECTOR_SIZE; -+ } -+ (*disk_read_func) (sector_num, 0, length); -+ } -+ } -+ -+ memmove (buf, (char *) bufaddr, size); -+ -+ buf += size; -+ byte_len -= size; -+ sector += num_sect; -+ slen -= num_sect; -+ byte_offset = 0; -+ } -+ -+ return (!errnum); -+} -+ -+ -+int -+devread (int sector, int byte_offset, int byte_len, char *buf) -+{ -+ /* -+ * Check partition boundaries -+ */ -+ if (sector < 0 -+ || ((sector + ((byte_offset + byte_len - 1) >> SECTOR_BITS)) -+ >= part_length)) -+ { -+ errnum = ERR_OUTSIDE_PART; -+ return 0; -+ } -+ -+ /* -+ * Get the read to the beginning of a partition. -+ */ -+ sector += byte_offset >> SECTOR_BITS; -+ byte_offset &= SECTOR_SIZE - 1; -+ -+#if !defined(STAGE1_5) -+ if (disk_read_hook && debug) -+ printf ("<%d, %d, %d>", sector, byte_offset, byte_len); -+#endif /* !STAGE1_5 */ -+ -+ /* -+ * Call RAWREAD, which is very similar, but: -+ * -+ * -- It takes an extra parameter, the drive number. -+ * -- It requires that "sector" is relative to the beginning -+ * of the disk. -+ * -- It doesn't handle offsets of more than 511 bytes into the -+ * sector. -+ */ -+ return rawread (current_drive, part_start + sector, byte_offset, -+ byte_len, buf); -+} -+ -+#ifndef STAGE1_5 -+int -+rawwrite (int drive, int sector, char *buf) -+{ -+ if (sector == 0) -+ { -+ if (biosdisk (BIOSDISK_READ, drive, &buf_geom, 0, 1, SCRATCHSEG)) -+ { -+ errnum = ERR_WRITE; -+ return 0; -+ } -+ -+ if (PC_SLICE_TYPE (SCRATCHADDR, 0) == PC_SLICE_TYPE_EZD -+ || PC_SLICE_TYPE (SCRATCHADDR, 1) == PC_SLICE_TYPE_EZD -+ || PC_SLICE_TYPE (SCRATCHADDR, 2) == PC_SLICE_TYPE_EZD -+ || PC_SLICE_TYPE (SCRATCHADDR, 3) == PC_SLICE_TYPE_EZD) -+ sector = 1; -+ } -+ -+ memmove ((char *) SCRATCHADDR, buf, SECTOR_SIZE); -+ if (biosdisk (BIOSDISK_WRITE, drive, &buf_geom, -+ sector, 1, SCRATCHSEG)) -+ { -+ errnum = ERR_WRITE; -+ return 0; -+ } -+ -+ if (sector - sector % buf_geom.sectors == buf_track) -+ /* Clear the cache. */ -+ buf_track = -1; -+ -+ return 1; -+} -+ -+int -+devwrite (int sector, int sector_count, char *buf) -+{ -+#if defined(GRUB_UTIL) && defined(__linux__) -+ if (current_partition != 0xFFFFFF) -+ { -+ /* If the grub shell is running under Linux and the user wants to -+ embed a Stage 1.5 into a partition instead of a MBR, use system -+ calls directly instead of biosdisk, because of the bug in -+ Linux. *sigh* */ -+ return write_to_partition (device_map, current_drive, current_partition, -+ sector, sector_count, buf); -+ } -+ else -+#endif /* GRUB_UTIL && __linux__ */ -+ { -+ int i; -+ -+ for (i = 0; i < sector_count; i++) -+ { -+ if (! rawwrite (current_drive, part_start + sector + i, -+ buf + (i << SECTOR_BITS))) -+ return 0; -+ -+ } -+ return 1; -+ } -+} -+ -+static int -+sane_partition (void) -+{ -+ /* network drive */ -+ if (current_drive == NETWORK_DRIVE) -+ return 1; -+ -+ if (!(current_partition & 0xFF000000uL) -+ && (current_drive & 0xFFFFFF7F) < 8 -+ && (current_partition & 0xFF) == 0xFF -+ && ((current_partition & 0xFF00) == 0xFF00 -+ || (current_partition & 0xFF00) < 0x800) -+ && ((current_partition >> 16) == 0xFF -+ || (current_drive & 0x80))) -+ return 1; -+ -+ errnum = ERR_DEV_VALUES; -+ return 0; -+} -+#endif /* ! STAGE1_5 */ -+ -+static void -+attempt_mount (void) -+{ -+#ifndef STAGE1_5 -+ for (fsys_type = 0; fsys_type < NUM_FSYS; fsys_type++) -+ if ((fsys_table[fsys_type].mount_func) ()) -+ break; -+ -+ if (fsys_type == NUM_FSYS && errnum == ERR_NONE) -+ errnum = ERR_FSYS_MOUNT; -+#else -+ fsys_type = 0; -+ if ((*(fsys_table[fsys_type].mount_func)) () != 1) -+ { -+ fsys_type = NUM_FSYS; -+ errnum = ERR_FSYS_MOUNT; -+ } -+#endif -+} -+ -+ -+#ifndef STAGE1_5 -+/* Turn on the active flag for the partition SAVED_PARTITION in the -+ drive SAVED_DRIVE. If an error occurs, return zero, otherwise return -+ non-zero. */ -+int -+make_saved_active (void) -+{ -+ char mbr[512]; -+ -+ if (saved_drive & 0x80) -+ { -+ /* Hard disk */ -+ int part = saved_partition >> 16; -+ -+ /* If the partition is not a primary partition, the active flag is -+ meaningless. (XXX: Really?) */ -+ if (part > 3) -+ { -+ errnum = ERR_DEV_VALUES; -+ return 0; -+ } -+ -+ /* Read the MBR in the scratch space. */ -+ if (! rawread (saved_drive, 0, 0, SECTOR_SIZE, mbr)) -+ return 0; -+ -+ /* If the partition is an extended partition, setting the active -+ flag violates the specification by IBM. */ -+ if (IS_PC_SLICE_TYPE_EXTENDED (PC_SLICE_TYPE (mbr, part))) -+ { -+ errnum = ERR_DEV_VALUES; -+ return 0; -+ } -+ -+ /* Check if the active flag is disabled. */ -+ if (PC_SLICE_FLAG (mbr, part) != PC_SLICE_FLAG_BOOTABLE) -+ { -+ int i; -+ -+ /* Clear all the active flags in this table. */ -+ for (i = 0; i < 4; i++) -+ PC_SLICE_FLAG (mbr, i) = 0; -+ -+ /* Set the flag. */ -+ PC_SLICE_FLAG (mbr, part) = PC_SLICE_FLAG_BOOTABLE; -+ -+ /* Write back the MBR. */ -+ if (! rawwrite (saved_drive, 0, mbr)) -+ return 0; -+ } -+ } -+ else -+ { -+ /* If the drive is not a hard disk drive, you shouldn't call this -+ function. (XXX: Should I just ignore this error?) */ -+ errnum = ERR_DEV_VALUES; -+ return 0; -+ } -+ -+ return 1; -+} -+ -+/* Hide/Unhide CURRENT_PARTITION. */ -+int -+set_partition_hidden_flag (int hidden) -+{ -+ unsigned long part = 0xFFFFFF; -+ unsigned long start, len, offset, ext_offset; -+ int entry, type; -+ char mbr[512]; -+ -+ /* The drive must be a hard disk. */ -+ if (! (current_drive & 0x80)) -+ { -+ errnum = ERR_BAD_ARGUMENT; -+ return 1; -+ } -+ -+ /* The partition must be a PC slice. */ -+ if ((current_partition >> 16) == 0xFF -+ || (current_partition & 0xFFFF) != 0xFFFF) -+ { -+ errnum = ERR_BAD_ARGUMENT; -+ return 1; -+ } -+ -+ /* Look for the partition. */ -+ while (next_partition (current_drive, 0xFFFFFF, &part, &type, -+ &start, &len, &offset, &entry, -+ &ext_offset, mbr)) -+ { -+ if (part == current_partition) -+ { -+ /* Found. */ -+ if (hidden) -+ PC_SLICE_TYPE (mbr, entry) |= PC_SLICE_TYPE_HIDDEN_FLAG; -+ else -+ PC_SLICE_TYPE (mbr, entry) &= ~PC_SLICE_TYPE_HIDDEN_FLAG; -+ -+ /* Write back the MBR to the disk. */ -+ buf_track = -1; -+ if (! rawwrite (current_drive, offset, mbr)) -+ return 1; -+ -+ /* Succeed. */ -+ return 0; -+ } -+ } -+ -+ return 1; -+} -+ -+ -+static void -+check_and_print_mount (void) -+{ -+ attempt_mount (); -+ if (errnum == ERR_FSYS_MOUNT) -+ errnum = ERR_NONE; -+ if (!errnum) -+ print_fsys_type (); -+ print_error (); -+} -+#endif /* STAGE1_5 */ -+ -+ -+/* Get the information on next partition on the drive DRIVE. -+ The caller must not modify the contents of the arguments when -+ iterating this function. The partition representation in GRUB will -+ be stored in *PARTITION. Likewise, the partition type in *TYPE, the -+ start sector in *START, the length in *LEN, the offset of the -+ partition table in *OFFSET, the entry number in the table in *ENTRY, -+ the offset of the extended partition in *EXT_OFFSET. -+ BUF is used to store a MBR, the boot sector of a partition, or -+ a BSD label sector, and it must be at least 512 bytes length. -+ When calling this function first, *PARTITION must be initialized to -+ 0xFFFFFF. The return value is zero if fails, otherwise non-zero. */ -+int -+next_partition (unsigned long drive, unsigned long dest, -+ unsigned long *partition, int *type, -+ unsigned long *start, unsigned long *len, -+ unsigned long *offset, int *entry, -+ unsigned long *ext_offset, char *buf) -+{ -+ /* Forward declarations. */ -+ auto int next_bsd_partition (void); -+ auto int next_pc_slice (void); -+ -+ /* Get next BSD partition in current PC slice. */ -+ int next_bsd_partition (void) -+ { -+ int i; -+ int bsd_part_no = (*partition & 0xFF00) >> 8; -+ -+ /* If this is the first time... */ -+ if (bsd_part_no == 0xFF) -+ { -+ /* Check if the BSD label is within current PC slice. */ -+ if (*len < BSD_LABEL_SECTOR + 1) -+ { -+ errnum = ERR_BAD_PART_TABLE; -+ return 0; -+ } -+ -+ /* Read the BSD label. */ -+ if (! rawread (drive, *start + BSD_LABEL_SECTOR, -+ 0, SECTOR_SIZE, buf)) -+ return 0; -+ -+ /* Check if it is valid. */ -+ if (! BSD_LABEL_CHECK_MAG (buf)) -+ { -+ errnum = ERR_BAD_PART_TABLE; -+ return 0; -+ } -+ -+ bsd_part_no = -1; -+ } -+ -+ /* Search next valid BSD partition. */ -+ for (i = bsd_part_no + 1; i < BSD_LABEL_NPARTS (buf); i++) -+ { -+ if (BSD_PART_TYPE (buf, i)) -+ { -+ /* Note that *TYPE and *PARTITION were set -+ for current PC slice. */ -+ *type = (BSD_PART_TYPE (buf, i) << 8) | (*type & 0xFF); -+ *start = BSD_PART_START (buf, i); -+ *len = BSD_PART_LENGTH (buf, i); -+ *partition = (*partition & 0xFF00FF) | (i << 8); -+ -+#ifndef STAGE1_5 -+ /* XXX */ -+ if ((drive & 0x80) && BSD_LABEL_DTYPE (buf) == DTYPE_SCSI) -+ bsd_evil_hack = 4; -+#endif /* ! STAGE1_5 */ -+ -+ return 1; -+ } -+ } -+ -+ errnum = ERR_NO_PART; -+ return 0; -+ } -+ -+ /* Get next PC slice. Be careful of that this function may return -+ an empty PC slice (i.e. a partition whose type is zero) as well. */ -+ int next_pc_slice (void) -+ { -+ int pc_slice_no = (*partition & 0xFF0000) >> 16; -+ -+ /* If this is the first time... */ -+ if (pc_slice_no == 0xFF) -+ { -+ *offset = 0; -+ *ext_offset = 0; -+ *entry = -1; -+ pc_slice_no = -1; -+ } -+ -+ /* Read the MBR or the boot sector of the extended partition. */ -+ if (! rawread (drive, *offset, 0, SECTOR_SIZE, buf)) -+ return 0; -+ -+ /* Check if it is valid. */ -+ if (! PC_MBR_CHECK_SIG (buf)) -+ { -+ errnum = ERR_BAD_PART_TABLE; -+ return 0; -+ } -+ -+ /* Increase the entry number. */ -+ (*entry)++; -+ -+ /* If this is out of current partition table... */ -+ if (*entry == PC_SLICE_MAX) -+ { -+ int i; -+ -+ /* Search the first extended partition in current table. */ -+ for (i = 0; i < PC_SLICE_MAX; i++) -+ { -+ if (IS_PC_SLICE_TYPE_EXTENDED (PC_SLICE_TYPE (buf, i))) -+ { -+ /* Found. Set the new offset and the entry number, -+ and restart this function. */ -+ *offset = *ext_offset + PC_SLICE_START (buf, i); -+ if (! *ext_offset) -+ *ext_offset = *offset; -+ *entry = -1; -+ return next_pc_slice (); -+ } -+ } -+ -+ errnum = ERR_NO_PART; -+ return 0; -+ } -+ -+ *type = PC_SLICE_TYPE (buf, *entry); -+ *start = *offset + PC_SLICE_START (buf, *entry); -+ *len = PC_SLICE_LENGTH (buf, *entry); -+ -+ /* The calculation of a PC slice number is complicated, because of -+ the rather odd definition of extended partitions. Even worse, -+ there is no guarantee that this is consistent with every -+ operating systems. Uggh. */ -+ if (pc_slice_no < PC_SLICE_MAX -+ || (! IS_PC_SLICE_TYPE_EXTENDED (*type) -+ && *type != PC_SLICE_TYPE_NONE)) -+ pc_slice_no++; -+ -+ *partition = (pc_slice_no << 16) | 0xFFFF; -+ return 1; -+ } -+ -+ /* Start the body of this function. */ -+ -+#ifndef STAGE1_5 -+ if (current_drive == NETWORK_DRIVE) -+ return 0; -+#endif -+ -+ /* If previous partition is a BSD partition or a PC slice which -+ contains BSD partitions... */ -+ if ((*partition != 0xFFFFFF && IS_PC_SLICE_TYPE_BSD (*type & 0xff)) -+ || ! (drive & 0x80)) -+ { -+ if (*type == PC_SLICE_TYPE_NONE) -+ *type = PC_SLICE_TYPE_FREEBSD; -+ -+ /* Get next BSD partition, if any. */ -+ if (next_bsd_partition ()) -+ return 1; -+ -+ /* If the destination partition is a BSD partition and current -+ BSD partition has any error, abort the operation. */ -+ if ((dest & 0xFF00) != 0xFF00 -+ && ((dest & 0xFF0000) == 0xFF0000 -+ || (dest & 0xFF0000) == (*partition & 0xFF0000))) -+ return 0; -+ -+ /* Ignore the error. */ -+ errnum = ERR_NONE; -+ } -+ -+ return next_pc_slice (); -+} -+ -+#ifndef STAGE1_5 -+static unsigned long cur_part_offset; -+static unsigned long cur_part_addr; -+#endif -+ -+/* Open a partition. */ -+int -+real_open_partition (int flags) -+{ -+ unsigned long dest_partition = current_partition; -+ unsigned long part_offset; -+ unsigned long ext_offset; -+ int entry; -+ char buf[SECTOR_SIZE]; -+ int bsd_part, pc_slice; -+ -+ /* For simplicity. */ -+ auto int next (void); -+ int next (void) -+ { -+ int ret = next_partition (current_drive, dest_partition, -+ ¤t_partition, ¤t_slice, -+ &part_start, &part_length, -+ &part_offset, &entry, &ext_offset, buf); -+ bsd_part = (current_partition >> 8) & 0xFF; -+ pc_slice = current_partition >> 16; -+ return ret; -+ } -+ -+#ifndef STAGE1_5 -+ /* network drive */ -+ if (current_drive == NETWORK_DRIVE) -+ return 1; -+ -+ if (! sane_partition ()) -+ return 0; -+#endif -+ -+ bsd_evil_hack = 0; -+ current_slice = 0; -+ part_start = 0; -+ -+ /* Make sure that buf_geom is valid. */ -+ if (buf_drive != current_drive) -+ { -+ if (get_diskinfo (current_drive, &buf_geom)) -+ { -+ errnum = ERR_NO_DISK; -+ return 0; -+ } -+ buf_drive = current_drive; -+ buf_track = -1; -+ } -+ part_length = buf_geom.total_sectors; -+ -+ /* If this is the whole disk, return here. */ -+ if (! flags && current_partition == 0xFFFFFF) -+ return 1; -+ -+ if (flags) -+ dest_partition = 0xFFFFFF; -+ -+ /* Initialize CURRENT_PARTITION for next_partition. */ -+ current_partition = 0xFFFFFF; -+ -+ while (next ()) -+ { -+#ifndef STAGE1_5 -+ loop_start: -+ -+ cur_part_offset = part_offset; -+ cur_part_addr = BOOT_PART_TABLE + (entry << 4); -+#endif /* ! STAGE1_5 */ -+ -+ /* If this is a valid partition... */ -+ if (current_slice) -+ { -+#ifndef STAGE1_5 -+ /* Display partition information. */ -+ if (flags && ! IS_PC_SLICE_TYPE_EXTENDED (current_slice)) -+ { -+ if (! do_completion) -+ { -+ if (current_drive & 0x80) -+ grub_printf (" Partition num: %d, ", -+ current_partition >> 16); -+ -+ if (! IS_PC_SLICE_TYPE_BSD (current_slice)) -+ check_and_print_mount (); -+ else -+ { -+ int got_part = 0; -+ int saved_slice = current_slice; -+ -+ while (next ()) -+ { -+ if (bsd_part == 0xFF) -+ break; -+ -+ if (! got_part) -+ { -+ grub_printf ("[BSD sub-partitions immediately follow]\n"); -+ got_part = 1; -+ } -+ -+ grub_printf (" BSD Partition num: \'%c\', ", -+ bsd_part + 'a'); -+ check_and_print_mount (); -+ } -+ -+ if (! got_part) -+ grub_printf (" No BSD sub-partition found, partition type 0x%x\n", -+ saved_slice); -+ -+ if (errnum) -+ { -+ errnum = ERR_NONE; -+ break; -+ } -+ -+ goto loop_start; -+ } -+ } -+ else -+ { -+ if (bsd_part != 0xFF) -+ { -+ char str[16]; -+ -+ if (! (current_drive & 0x80) -+ || (dest_partition >> 16) == pc_slice) -+ grub_sprintf (str, "%c)", bsd_part + 'a'); -+ else -+ grub_sprintf (str, "%d,%c)", -+ pc_slice, bsd_part + 'a'); -+ print_a_completion (str); -+ } -+ else if (! IS_PC_SLICE_TYPE_BSD (current_slice)) -+ { -+ char str[8]; -+ -+ grub_sprintf (str, "%d)", pc_slice); -+ print_a_completion (str); -+ } -+ } -+ } -+ -+ errnum = ERR_NONE; -+#endif /* ! STAGE1_5 */ -+ -+ /* Check if this is the destination partition. */ -+ if (! flags -+ && (dest_partition == current_partition -+ || ((dest_partition >> 16) == 0xFF -+ && ((dest_partition >> 8) & 0xFF) == bsd_part))) -+ return 1; -+ } -+ } -+ -+#ifndef STAGE1_5 -+ if (flags) -+ { -+ if (! (current_drive & 0x80)) -+ { -+ current_partition = 0xFFFFFF; -+ check_and_print_mount (); -+ } -+ -+ errnum = ERR_NONE; -+ return 1; -+ } -+#endif /* ! STAGE1_5 */ -+ -+ return 0; -+} -+ -+ -+int -+open_partition (void) -+{ -+ return real_open_partition (0); -+} -+ -+ -+#ifndef STAGE1_5 -+/* XX used for device completion in 'set_device' and 'print_completions' */ -+static int incomplete, disk_choice; -+static enum -+{ -+ PART_UNSPECIFIED = 0, -+ PART_DISK, -+ PART_CHOSEN, -+} -+part_choice; -+#endif /* ! STAGE1_5 */ -+ -+char * -+set_device (char *device) -+{ -+#ifdef STAGE1_5 -+ /* In Stage 1.5, the first 4 bytes of FILENAME has a device number. */ -+ unsigned long dev = *((unsigned long *) device); -+ int drive = (dev >> 24) & 0xFF; -+ int partition = dev & 0xFFFFFF; -+ -+ /* If DRIVE is disabled (0xFF), use SAVED_DRIVE instead. */ -+ if (drive == 0xFF) -+ current_drive = saved_drive; -+ else -+ current_drive = drive; -+ -+ /* The `partition' part must always have a valid number. */ -+ current_partition = partition; -+ -+ return device + sizeof (unsigned long); -+ -+#else /* ! STAGE1_5 */ -+ -+ int result = 0; -+ -+ incomplete = 0; -+ disk_choice = 1; -+ part_choice = PART_UNSPECIFIED; -+ current_drive = saved_drive; -+ current_partition = 0xFFFFFF; -+ -+ if (*device == '(' && !*(device + 1)) -+ /* user has given '(' only, let disk_choice handle what disks we have */ -+ return device + 1; -+ -+ if (*device == '(' && *(++device)) -+ { -+ if (*device != ',' && *device != ')') -+ { -+ char ch = *device; -+#ifdef SUPPORT_NETBOOT -+ if (*device == 'f' || *device == 'h' || -+ (*device == 'n' && network_ready)) -+#else -+ if (*device == 'f' || *device == 'h') -+#endif /* SUPPORT_NETBOOT */ -+ { -+ /* user has given '([fhn]', check for resp. add 'd' and -+ let disk_choice handle what disks we have */ -+ if (!*(device + 1)) -+ { -+ device++; -+ *device++ = 'd'; -+ *device = '\0'; -+ return device; -+ } -+ else if (*(device + 1) == 'd' && !*(device + 2)) -+ return device + 2; -+ } -+ -+#ifdef SUPPORT_NETBOOT -+ if ((*device == 'f' || *device == 'h' || -+ (*device == 'n' && network_ready)) -+#else -+ if ((*device == 'f' || *device == 'h') -+#endif /* SUPPORT_NETBOOT */ -+ && (device += 2, (*(device - 1) != 'd'))) -+ errnum = ERR_NUMBER_PARSING; -+ -+#ifdef SUPPORT_NETBOOT -+ if (ch == 'n' && network_ready) -+ current_drive = NETWORK_DRIVE; -+ else -+#endif /* SUPPORT_NETBOOT */ -+ { -+ safe_parse_maxint (&device, (int *) ¤t_drive); -+ -+ disk_choice = 0; -+ if (ch == 'h') -+ current_drive += 0x80; -+ } -+ } -+ -+ if (errnum) -+ return 0; -+ -+ if (*device == ')') -+ { -+ part_choice = PART_CHOSEN; -+ result = 1; -+ } -+ else if (*device == ',') -+ { -+ /* Either an absolute PC or BSD partition. */ -+ disk_choice = 0; -+ part_choice ++; -+ device++; -+ -+ if (*device >= '0' && *device <= '9') -+ { -+ part_choice ++; -+ current_partition = 0; -+ -+ if (!(current_drive & 0x80) -+ || !safe_parse_maxint (&device, (int *) ¤t_partition) -+ || current_partition > 254) -+ { -+ errnum = ERR_DEV_FORMAT; -+ return 0; -+ } -+ -+ current_partition = (current_partition << 16) + 0xFFFF; -+ -+ if (*device == ',') -+ device++; -+ -+ if (*device >= 'a' && *device <= 'h') -+ { -+ current_partition = (((*(device++) - 'a') << 8) -+ | (current_partition & 0xFF00FF)); -+ } -+ } -+ else if (*device >= 'a' && *device <= 'h') -+ { -+ part_choice ++; -+ current_partition = ((*(device++) - 'a') << 8) | 0xFF00FF; -+ } -+ -+ if (*device == ')') -+ { -+ if (part_choice == PART_DISK) -+ { -+ current_partition = saved_partition; -+ part_choice ++; -+ } -+ -+ result = 1; -+ } -+ } -+ } -+ -+ if (! sane_partition ()) -+ return 0; -+ -+ if (result) -+ return device + 1; -+ else -+ { -+ if (!*device) -+ incomplete = 1; -+ errnum = ERR_DEV_FORMAT; -+ } -+ -+ return 0; -+ -+#endif /* ! STAGE1_5 */ -+} -+ -+/* -+ * This performs a "mount" on the current device, both drive and partition -+ * number. -+ */ -+ -+int -+open_device (void) -+{ -+ if (open_partition ()) -+ attempt_mount (); -+ -+ if (errnum != ERR_NONE) -+ return 0; -+ -+ return 1; -+} -+ -+ -+#ifndef STAGE1_5 -+int -+set_bootdev (int hdbias) -+{ -+ int i, j; -+ -+ /* Copy the boot partition information to 0x7be-0x7fd for chain-loading. */ -+ if ((saved_drive & 0x80) && cur_part_addr) -+ { -+ if (rawread (saved_drive, cur_part_offset, -+ 0, SECTOR_SIZE, (char *) SCRATCHADDR)) -+ { -+ char *dst, *src; -+ -+ /* Need only the partition table. -+ XXX: We cannot use grub_memmove because BOOT_PART_TABLE -+ (0x07be) is less than 0x1000. */ -+ dst = (char *) BOOT_PART_TABLE; -+ src = (char *) SCRATCHADDR + BOOTSEC_PART_OFFSET; -+ while (dst < (char *) BOOT_PART_TABLE + BOOTSEC_PART_LENGTH) -+ *dst++ = *src++; -+ -+ /* Set the active flag of the booted partition. */ -+ for (i = 0; i < 4; i++) -+ PC_SLICE_FLAG (BOOT_PART_TABLE, i) = 0; -+ -+ *((unsigned char *) cur_part_addr) = PC_SLICE_FLAG_BOOTABLE; -+ boot_part_addr = cur_part_addr; -+ } -+ else -+ return 0; -+ } -+ -+ /* -+ * Set BSD boot device. -+ */ -+ i = (saved_partition >> 16) + 2; -+ if (saved_partition == 0xFFFFFF) -+ i = 1; -+ else if ((saved_partition >> 16) == 0xFF) -+ i = 0; -+ -+ /* FIXME: extremely evil hack!!! */ -+ j = 2; -+ if (saved_drive & 0x80) -+ j = bsd_evil_hack; -+ -+ return MAKEBOOTDEV (j, (i >> 4), (i & 0xF), -+ ((saved_drive - hdbias) & 0x7F), -+ ((saved_partition >> 8) & 0xFF)); -+} -+#endif /* STAGE1_5 */ -+ -+ -+static char * -+setup_part (char *filename) -+{ -+#ifdef STAGE1_5 -+ -+ if (! (filename = set_device (filename))) -+ { -+ current_drive = 0xFF; -+ return 0; -+ } -+ -+# ifndef NO_BLOCK_FILES -+ if (*filename != '/') -+ open_partition (); -+ else -+# endif /* ! NO_BLOCK_FILES */ -+ open_device (); -+ -+#else /* ! STAGE1_5 */ -+ -+ if (*filename == '(') -+ { -+ if ((filename = set_device (filename)) == 0) -+ { -+ current_drive = 0xFF; -+ return 0; -+ } -+# ifndef NO_BLOCK_FILES -+ if (*filename != '/') -+ open_partition (); -+ else -+# endif /* ! NO_BLOCK_FILES */ -+ open_device (); -+ } -+ else if (saved_drive != current_drive -+ || saved_partition != current_partition -+ || (*filename == '/' && fsys_type == NUM_FSYS) -+ || buf_drive == -1) -+ { -+ current_drive = saved_drive; -+ current_partition = saved_partition; -+ /* allow for the error case of "no filesystem" after the partition -+ is found. This makes block files work fine on no filesystem */ -+# ifndef NO_BLOCK_FILES -+ if (*filename != '/') -+ open_partition (); -+ else -+# endif /* ! NO_BLOCK_FILES */ -+ open_device (); -+ } -+ -+#endif /* ! STAGE1_5 */ -+ -+ if (errnum && (*filename == '/' || errnum != ERR_FSYS_MOUNT)) -+ return 0; -+ else -+ errnum = 0; -+ -+#ifndef STAGE1_5 -+ if (!sane_partition ()) -+ return 0; -+#endif -+ -+ return filename; -+} -+ -+ -+#ifndef STAGE1_5 -+/* -+ * This prints the filesystem type or gives relevant information. -+ */ -+ -+void -+print_fsys_type (void) -+{ -+ if (! do_completion) -+ { -+ printf (" Filesystem type "); -+ -+ if (fsys_type != NUM_FSYS) -+ printf ("is %s, ", fsys_table[fsys_type].name); -+ else -+ printf ("unknown, "); -+ -+ if (current_partition == 0xFFFFFF) -+ printf ("using whole disk\n"); -+ else -+ printf ("partition type 0x%x\n", current_slice & 0xFF); -+ } -+} -+#endif /* STAGE1_5 */ -+ -+#ifndef STAGE1_5 -+/* If DO_COMPLETION is true, just print NAME. Otherwise save the unique -+ part into UNIQUE_STRING. */ -+void -+print_a_completion (char *name) -+{ -+ /* If NAME is "." or "..", do not count it. */ -+ if (grub_strcmp (name, ".") == 0 || grub_strcmp (name, "..") == 0) -+ return; -+ -+ if (do_completion) -+ { -+ char *buf = unique_string; -+ -+ if (! unique) -+ while ((*buf++ = *name++)) -+ ; -+ else -+ { -+ while (*buf && (*buf == *name)) -+ { -+ buf++; -+ name++; -+ } -+ /* mismatch, strip it. */ -+ *buf = '\0'; -+ } -+ } -+ else -+ grub_printf (" %s", name); -+ -+ unique++; -+} -+ -+/* -+ * This lists the possible completions of a device string, filename, or -+ * any sane combination of the two. -+ */ -+ -+int -+print_completions (int is_filename, int is_completion) -+{ -+ char *buf = (char *) COMPLETION_BUF; -+ char *ptr = buf; -+ -+ unique_string = (char *) UNIQUE_BUF; -+ *unique_string = 0; -+ unique = 0; -+ do_completion = is_completion; -+ -+ if (! is_filename) -+ { -+ /* Print the completions of builtin commands. */ -+ struct builtin **builtin; -+ -+ if (! is_completion) -+ grub_printf (" Possible commands are:"); -+ -+ for (builtin = builtin_table; (*builtin); builtin++) -+ { -+ /* If *BUILTIN cannot be run in the command-line, skip it. */ -+ if (! ((*builtin)->flags & BUILTIN_CMDLINE)) -+ continue; -+ -+ if (substring (buf, (*builtin)->name) <= 0) -+ print_a_completion ((*builtin)->name); -+ } -+ -+ if (is_completion && *unique_string) -+ { -+ if (unique == 1) -+ { -+ char *u = unique_string + grub_strlen (unique_string); -+ -+ *u++ = ' '; -+ *u = 0; -+ } -+ -+ grub_strcpy (buf, unique_string); -+ } -+ -+ if (! is_completion) -+ grub_putchar ('\n'); -+ -+ print_error (); -+ do_completion = 0; -+ if (errnum) -+ return -1; -+ else -+ return unique - 1; -+ } -+ -+ if (*buf == '/' || (ptr = set_device (buf)) || incomplete) -+ { -+ errnum = 0; -+ -+ if (*buf == '(' && (incomplete || ! *ptr)) -+ { -+ if (! part_choice) -+ { -+ /* disk completions */ -+ int disk_no, i, j; -+ struct geometry geom; -+ -+ if (! is_completion) -+ grub_printf (" Possible disks are: "); -+ -+#ifdef SUPPORT_NETBOOT -+ if (!ptr || *(ptr-1) != 'd' || *(ptr-2) != 'n') -+#endif /* SUPPORT_NETBOOT */ -+ { -+ for (i = (ptr && (*(ptr-1) == 'd' && *(ptr-2) == 'h') ? 1:0); -+ i < (ptr && (*(ptr-1) == 'd' && *(ptr-2) == 'f') ? 1:2); -+ i++) -+ { -+ for (j = 0; j < 8; j++) -+ { -+ disk_no = (i * 0x80) + j; -+ if ((disk_choice || disk_no == current_drive) -+ && ! get_diskinfo (disk_no, &geom)) -+ { -+ char dev_name[8]; -+ -+ grub_sprintf (dev_name, "%cd%d", i ? 'h':'f', j); -+ print_a_completion (dev_name); -+ } -+ } -+ } -+ } -+# ifdef SUPPORT_NETBOOT -+ if (network_ready && -+ (disk_choice || NETWORK_DRIVE == current_drive) && -+ (!ptr || *(ptr-1) == '(' || -+ (*(ptr-1) == 'd' && *(ptr-2) == 'n'))) -+ print_a_completion ("nd"); -+# endif /* SUPPORT_NETBOOT */ -+ -+ if (is_completion && *unique_string) -+ { -+ ptr = buf; -+ while (*ptr != '(') -+ ptr--; -+ ptr++; -+ grub_strcpy (ptr, unique_string); -+ if (unique == 1) -+ { -+ ptr += grub_strlen (ptr); -+ if (*unique_string == 'h') -+ { -+ *ptr++ = ','; -+ *ptr = 0; -+ } -+ else -+ { -+ *ptr++ = ')'; -+ *ptr = 0; -+ } -+ } -+ } -+ -+ if (! is_completion) -+ grub_putchar ('\n'); -+ } -+ else -+ { -+ /* partition completions */ -+ if (part_choice == PART_CHOSEN -+ && open_partition () -+ && ! IS_PC_SLICE_TYPE_BSD (current_slice)) -+ { -+ unique = 1; -+ ptr = buf + grub_strlen (buf); -+ if (*(ptr - 1) != ')') -+ { -+ *ptr++ = ')'; -+ *ptr = 0; -+ } -+ } -+ else -+ { -+ if (! is_completion) -+ grub_printf (" Possible partitions are:\n"); -+ real_open_partition (1); -+ -+ if (is_completion && *unique_string) -+ { -+ ptr = buf; -+ while (*ptr++ != ',') -+ ; -+ grub_strcpy (ptr, unique_string); -+ } -+ } -+ } -+ } -+ else if (ptr && *ptr == '/') -+ { -+ /* filename completions */ -+ if (! is_completion) -+ grub_printf (" Possible files are:"); -+ -+ dir (buf); -+ -+ if (is_completion && *unique_string) -+ { -+ ptr += grub_strlen (ptr); -+ while (*ptr != '/') -+ ptr--; -+ ptr++; -+ -+ grub_strcpy (ptr, unique_string); -+ -+ if (unique == 1) -+ { -+ ptr += grub_strlen (unique_string); -+ -+ /* Check if the file UNIQUE_STRING is a directory. */ -+ *ptr = '/'; -+ *(ptr + 1) = 0; -+ -+ dir (buf); -+ -+ /* Restore the original unique value. */ -+ unique = 1; -+ -+ if (errnum) -+ { -+ /* Regular file */ -+ errnum = 0; -+ *ptr = ' '; -+ *(ptr + 1) = 0; -+ } -+ } -+ } -+ -+ if (! is_completion) -+ grub_putchar ('\n'); -+ } -+ else -+ errnum = ERR_BAD_FILENAME; -+ } -+ -+ print_error (); -+ do_completion = 0; -+ if (errnum) -+ return -1; -+ else -+ return unique - 1; -+} -+#endif /* STAGE1_5 */ -+ -+ -+/* -+ * This is the generic file open function. -+ */ -+ -+int -+grub_open (char *filename) -+{ -+#ifndef NO_DECOMPRESSION -+ compressed_file = 0; -+#endif /* NO_DECOMPRESSION */ -+ -+ /* if any "dir" function uses/sets filepos, it must -+ set it to zero before returning if opening a file! */ -+ filepos = 0; -+ -+ if (!(filename = setup_part (filename))) -+ return 0; -+ -+#ifndef NO_BLOCK_FILES -+ block_file = 0; -+#endif /* NO_BLOCK_FILES */ -+ -+ /* This accounts for partial filesystem implementations. */ -+ fsmax = MAXINT; -+ -+ if (*filename != '/') -+ { -+#ifndef NO_BLOCK_FILES -+ char *ptr = filename; -+ int tmp, list_addr = BLK_BLKLIST_START; -+ filemax = 0; -+ -+ while (list_addr < BLK_MAX_ADDR) -+ { -+ tmp = 0; -+ safe_parse_maxint (&ptr, &tmp); -+ errnum = 0; -+ -+ if (*ptr != '+') -+ { -+ if ((*ptr && *ptr != '/' && !isspace (*ptr)) -+ || tmp == 0 || tmp > filemax) -+ errnum = ERR_BAD_FILENAME; -+ else -+ filemax = tmp; -+ -+ break; -+ } -+ -+ /* since we use the same filesystem buffer, mark it to -+ be remounted */ -+ fsys_type = NUM_FSYS; -+ -+ BLK_BLKSTART (list_addr) = tmp; -+ ptr++; -+ -+ if (!safe_parse_maxint (&ptr, &tmp) -+ || tmp == 0 -+ || (*ptr && *ptr != ',' && *ptr != '/' && !isspace (*ptr))) -+ { -+ errnum = ERR_BAD_FILENAME; -+ break; -+ } -+ -+ BLK_BLKLENGTH (list_addr) = tmp; -+ -+ filemax += (tmp * SECTOR_SIZE); -+ list_addr += BLK_BLKLIST_INC_VAL; -+ -+ if (*ptr != ',') -+ break; -+ -+ ptr++; -+ } -+ -+ if (list_addr < BLK_MAX_ADDR && ptr != filename && !errnum) -+ { -+ block_file = 1; -+ BLK_CUR_FILEPOS = 0; -+ BLK_CUR_BLKLIST = BLK_BLKLIST_START; -+ BLK_CUR_BLKNUM = 0; -+ -+#ifndef NO_DECOMPRESSION -+ return gunzip_test_header (); -+#else /* NO_DECOMPRESSION */ -+ return 1; -+#endif /* NO_DECOMPRESSION */ -+ } -+#else /* NO_BLOCK_FILES */ -+ errnum = ERR_BAD_FILENAME; -+#endif /* NO_BLOCK_FILES */ -+ } -+ -+ if (!errnum && fsys_type == NUM_FSYS) -+ errnum = ERR_FSYS_MOUNT; -+ -+# ifndef STAGE1_5 -+ /* set "dir" function to open a file */ -+ print_possibilities = 0; -+# endif -+ -+ if (!errnum && (*(fsys_table[fsys_type].dir_func)) (filename)) -+ { -+#ifndef NO_DECOMPRESSION -+ return gunzip_test_header (); -+#else /* NO_DECOMPRESSION */ -+ return 1; -+#endif /* NO_DECOMPRESSION */ -+ } -+ -+ return 0; -+} -+ -+ -+int -+grub_read (char *buf, int len) -+{ -+ /* Make sure "filepos" is a sane value */ -+ if ((filepos < 0) || (filepos > filemax)) -+ filepos = filemax; -+ -+ /* Make sure "len" is a sane value */ -+ if ((len < 0) || (len > (filemax - filepos))) -+ len = filemax - filepos; -+ -+ /* if target file position is past the end of -+ the supported/configured filesize, then -+ there is an error */ -+ if (filepos + len > fsmax) -+ { -+ errnum = ERR_FILELENGTH; -+ return 0; -+ } -+ -+#ifndef NO_DECOMPRESSION -+ if (compressed_file) -+ return gunzip_read (buf, len); -+#endif /* NO_DECOMPRESSION */ -+ -+#ifndef NO_BLOCK_FILES -+ if (block_file) -+ { -+ int size, off, ret = 0; -+ -+ while (len && !errnum) -+ { -+ /* we may need to look for the right block in the list(s) */ -+ if (filepos < BLK_CUR_FILEPOS) -+ { -+ BLK_CUR_FILEPOS = 0; -+ BLK_CUR_BLKLIST = BLK_BLKLIST_START; -+ BLK_CUR_BLKNUM = 0; -+ } -+ -+ /* run BLK_CUR_FILEPOS up to filepos */ -+ while (filepos > BLK_CUR_FILEPOS) -+ { -+ if ((filepos - (BLK_CUR_FILEPOS & ~(SECTOR_SIZE - 1))) -+ >= SECTOR_SIZE) -+ { -+ BLK_CUR_FILEPOS += SECTOR_SIZE; -+ BLK_CUR_BLKNUM++; -+ -+ if (BLK_CUR_BLKNUM >= BLK_BLKLENGTH (BLK_CUR_BLKLIST)) -+ { -+ BLK_CUR_BLKLIST += BLK_BLKLIST_INC_VAL; -+ BLK_CUR_BLKNUM = 0; -+ } -+ } -+ else -+ BLK_CUR_FILEPOS = filepos; -+ } -+ -+ off = filepos & (SECTOR_SIZE - 1); -+ size = ((BLK_BLKLENGTH (BLK_CUR_BLKLIST) - BLK_CUR_BLKNUM) -+ * SECTOR_SIZE) - off; -+ if (size > len) -+ size = len; -+ -+ disk_read_func = disk_read_hook; -+ -+ /* read current block and put it in the right place in memory */ -+ devread (BLK_BLKSTART (BLK_CUR_BLKLIST) + BLK_CUR_BLKNUM, -+ off, size, buf); -+ -+ disk_read_func = NULL; -+ -+ len -= size; -+ filepos += size; -+ ret += size; -+ buf += size; -+ } -+ -+ if (errnum) -+ ret = 0; -+ -+ return ret; -+ } -+#endif /* NO_BLOCK_FILES */ -+ -+ if (fsys_type == NUM_FSYS) -+ { -+ errnum = ERR_FSYS_MOUNT; -+ return 0; -+ } -+ -+ return (*(fsys_table[fsys_type].read_func)) (buf, len); -+} -+ -+#ifndef STAGE1_5 -+/* Reposition a file offset. */ -+int -+grub_seek (int offset) -+{ -+ if (offset > filemax || offset < 0) -+ return -1; -+ -+ filepos = offset; -+ return offset; -+} -+ -+int -+dir (char *dirname) -+{ -+#ifndef NO_DECOMPRESSION -+ compressed_file = 0; -+#endif /* NO_DECOMPRESSION */ -+ -+ if (!(dirname = setup_part (dirname))) -+ return 0; -+ -+ if (*dirname != '/') -+ errnum = ERR_BAD_FILENAME; -+ -+ if (fsys_type == NUM_FSYS) -+ errnum = ERR_FSYS_MOUNT; -+ -+ if (errnum) -+ return 0; -+ -+ /* set "dir" function to list completions */ -+ print_possibilities = 1; -+ -+ return (*(fsys_table[fsys_type].dir_func)) (dirname); -+} -+#endif /* STAGE1_5 */ -+ -+void -+grub_close (void) -+{ -+#ifndef NO_BLOCK_FILES -+ if (block_file) -+ return; -+#endif /* NO_BLOCK_FILES */ -+ -+ if (fsys_table[fsys_type].close_func != 0) -+ (*(fsys_table[fsys_type].close_func)) (); -+} -diff -ruN grub-0.94.orig/stage2/filesys.h stage2/filesys.h ---- grub-0.94.orig/stage2/filesys.h Wed Feb 11 00:22:12 2004 -+++ stage2/filesys.h Wed Feb 11 00:22:29 2004 +diff -ruN stage2/filesys.h.orig stage2/filesys.h +--- stage2/filesys.h.orig Sat Apr 24 20:49:07 2004 ++++ stage2/filesys.h Sat Apr 24 20:49:16 2004 @@ -30,6 +30,16 @@ #define FSYS_FFS_NUM 0 #endif @@ -7556,160 +144,10 @@ diff -ruN grub-0.94.orig/stage2/filesys.h stage2/filesys.h + FSYS_TFTP_NUM) #endif -diff -ruN grub-0.94.orig/stage2/filesys.h.orig stage2/filesys.h.orig ---- grub-0.94.orig/stage2/filesys.h.orig Thu Jan 1 03:00:00 1970 -+++ stage2/filesys.h.orig Wed Jul 9 15:45:52 2003 -@@ -0,0 +1,146 @@ -+/* filesys.h - abstract filesystem interface */ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#include "pc_slice.h" -+ -+#ifdef FSYS_FFS -+#define FSYS_FFS_NUM 1 -+int ffs_mount (void); -+int ffs_read (char *buf, int len); -+int ffs_dir (char *dirname); -+int ffs_embed (int *start_sector, int needed_sectors); -+#else -+#define FSYS_FFS_NUM 0 -+#endif -+ -+#ifdef FSYS_FAT -+#define FSYS_FAT_NUM 1 -+int fat_mount (void); -+int fat_read (char *buf, int len); -+int fat_dir (char *dirname); -+#else -+#define FSYS_FAT_NUM 0 -+#endif -+ -+#ifdef FSYS_EXT2FS -+#define FSYS_EXT2FS_NUM 1 -+int ext2fs_mount (void); -+int ext2fs_read (char *buf, int len); -+int ext2fs_dir (char *dirname); -+#else -+#define FSYS_EXT2FS_NUM 0 -+#endif -+ -+#ifdef FSYS_MINIX -+#define FSYS_MINIX_NUM 1 -+int minix_mount (void); -+int minix_read (char *buf, int len); -+int minix_dir (char *dirname); -+#else -+#define FSYS_MINIX_NUM 0 -+#endif -+ -+#ifdef FSYS_REISERFS -+#define FSYS_REISERFS_NUM 1 -+int reiserfs_mount (void); -+int reiserfs_read (char *buf, int len); -+int reiserfs_dir (char *dirname); -+int reiserfs_embed (int *start_sector, int needed_sectors); -+#else -+#define FSYS_REISERFS_NUM 0 -+#endif -+ -+#ifdef FSYS_VSTAFS -+#define FSYS_VSTAFS_NUM 1 -+int vstafs_mount (void); -+int vstafs_read (char *buf, int len); -+int vstafs_dir (char *dirname); -+#else -+#define FSYS_VSTAFS_NUM 0 -+#endif -+ -+#ifdef FSYS_JFS -+#define FSYS_JFS_NUM 1 -+int jfs_mount (void); -+int jfs_read (char *buf, int len); -+int jfs_dir (char *dirname); -+int jfs_embed (int *start_sector, int needed_sectors); -+#else -+#define FSYS_JFS_NUM 0 -+#endif -+ -+#ifdef FSYS_XFS -+#define FSYS_XFS_NUM 1 -+int xfs_mount (void); -+int xfs_read (char *buf, int len); -+int xfs_dir (char *dirname); -+#else -+#define FSYS_XFS_NUM 0 -+#endif -+ -+#ifdef FSYS_TFTP -+#define FSYS_TFTP_NUM 1 -+int tftp_mount (void); -+int tftp_read (char *buf, int len); -+int tftp_dir (char *dirname); -+void tftp_close (void); -+#else -+#define FSYS_TFTP_NUM 0 -+#endif -+ -+#ifndef NUM_FSYS -+#define NUM_FSYS \ -+ (FSYS_FFS_NUM + FSYS_FAT_NUM + FSYS_EXT2FS_NUM + FSYS_MINIX_NUM \ -+ + FSYS_REISERFS_NUM + FSYS_VSTAFS_NUM + FSYS_JFS_NUM + FSYS_XFS_NUM \ -+ + FSYS_TFTP_NUM) -+#endif -+ -+/* defines for the block filesystem info area */ -+#ifndef NO_BLOCK_FILES -+#define BLK_CUR_FILEPOS (*((int*)FSYS_BUF)) -+#define BLK_CUR_BLKLIST (*((int*)(FSYS_BUF+4))) -+#define BLK_CUR_BLKNUM (*((int*)(FSYS_BUF+8))) -+#define BLK_MAX_ADDR (FSYS_BUF+0x7FF9) -+#define BLK_BLKSTART(l) (*((int*)l)) -+#define BLK_BLKLENGTH(l) (*((int*)(l+4))) -+#define BLK_BLKLIST_START (FSYS_BUF+12) -+#define BLK_BLKLIST_INC_VAL 8 -+#endif /* NO_BLOCK_FILES */ -+ -+/* this next part is pretty ugly, but it keeps it in one place! */ -+ -+struct fsys_entry -+{ -+ char *name; -+ int (*mount_func) (void); -+ int (*read_func) (char *buf, int len); -+ int (*dir_func) (char *dirname); -+ void (*close_func) (void); -+ int (*embed_func) (int *start_sector, int needed_sectors); -+}; -+ -+#ifdef STAGE1_5 -+# define print_possibilities 0 -+#else -+extern int print_possibilities; -+#endif -+ -+extern int fsmax; -+extern struct fsys_entry fsys_table[NUM_FSYS + 1]; -diff -ruN grub-0.94.orig/stage2/fsys_ufs2.c stage2/fsys_ufs2.c ---- grub-0.94.orig/stage2/fsys_ufs2.c Thu Jan 1 03:00:00 1970 -+++ stage2/fsys_ufs2.c Wed Feb 11 00:22:29 2004 -@@ -0,0 +1,305 @@ +diff -ruN stage2/fsys_ufs2.c.orig stage2/fsys_ufs2.c +--- stage2/fsys_ufs2.c.orig Thu Jan 1 03:00:00 1970 ++++ stage2/fsys_ufs2.c Sat Apr 24 21:05:20 2004 +@@ -0,0 +1,333 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2000, 2001 Free Software Foundation, Inc. @@ -7762,6 +200,14 @@ diff -ruN grub-0.94.orig/stage2/fsys_ufs2.c stage2/fsys_ufs2.c + * the rights to redistribute these changes. + * + * from: Mach, Revision 2.2 92/04/04 11:35:49 rpd ++ * $Id: fsys_ufs2.c,v 1.10 2001/11/12 06:57:29 okuji Exp $ ++ */ ++ ++/* ++ * Copyright (c) 2004 Valery Hromov ++ * ++ * Permission to use, copy, modify and distribute this software granted ++ * to the Free Software Foundation. + * + */ + @@ -7777,24 +223,47 @@ diff -ruN grub-0.94.orig/stage2/fsys_ufs2.c stage2/fsys_ufs2.c +static int mapblock_offset; +static int mapblock_bsize; + ++static int sblock_try[] = SBLOCKSEARCH; ++static ufs2_daddr_t sblockloc; ++static int type; ++ +/* pointer to superblock */ +#define SUPERBLOCK ((struct fs *) ( FSYS_BUF + 8192 )) -+#define INODE ((struct ufs2_dinode *) ( FSYS_BUF + 16384 )) ++ ++#define INODE_UFS2 ((struct ufs2_dinode *) ( FSYS_BUF + 16384 )) ++ +#define MAPBUF ( FSYS_BUF + 24576 ) +#define MAPBUF_LEN 8192 + -+ +int +ufs2_mount (void) +{ -+ int retval = 1; ++ int retval = 0; ++ int i; + -+ if ((((current_drive & 0x80) || (current_slice != 0)) -+ && ! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_BSDFFS)) -+ || part_length < (SBLOCK_UFS2 + (SBLOCKSIZE / DEV_BSIZE)) -+ || !devread (0, SBLOCK_UFS2, SBLOCKSIZE, (char *) SUPERBLOCK) -+ || SUPERBLOCK->fs_magic != FS_UFS2_MAGIC) -+ retval = 0; ++ sblockloc = -1; ++ type = 0; ++ ++ if ( ! (((current_drive & 0x80) || (current_slice != 0)) ++ && ! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_BSDFFS))) { ++ ++ for (i = 0; sblock_try[i] != -1; ++i) { ++ if (! (part_length < (sblock_try[i] + (SBLOCKSIZE / DEV_BSIZE)) ++ || !devread (0, sblock_try[i], SBLOCKSIZE, (char *) SUPERBLOCK))) { ++ if (SUPERBLOCK->fs_magic == FS_UFS2_MAGIC /* && ++ (SUPERBLOCK->fs_sblockloc == sblockloc || ++ (SUPERBLOCK->fs_old_flags & FS_FLAGS_UPDATED) == 0)*/) { ++ type = 2; ++ } else { ++ continue; ++ } ++ ++ retval = 1; ++ sblockloc = sblock_try[i]; ++ break; ++ } ++ } ++ } + + mapblock = -1; + mapblock_offset = -1; @@ -7808,11 +277,12 @@ diff -ruN grub-0.94.orig/stage2/fsys_ufs2.c stage2/fsys_ufs2.c + int bnum, offset, bsize; + + if (file_block < NDADDR) -+ return (INODE->di_db[file_block]); ++ return (INODE_UFS2->di_db[file_block]); + + /* If the blockmap loaded does not include FILE_BLOCK, + load a new blockmap. */ -+ if ((bnum = fsbtodb (SUPERBLOCK, INODE->di_ib[0])) != mapblock ++ ++ if ((bnum = fsbtodb (SUPERBLOCK, INODE_UFS2->di_ib[0])) != mapblock + || (mapblock_offset <= bnum && bnum <= mapblock_offset + mapblock_bsize)) + { + if (MAPBUF_LEN < SUPERBLOCK->fs_bsize) @@ -7857,7 +327,7 @@ diff -ruN grub-0.94.orig/stage2/fsys_ufs2.c stage2/fsys_ufs2.c + { + off = blkoff (SUPERBLOCK, filepos); + logno = lblkno (SUPERBLOCK, filepos); -+ size = blksize (SUPERBLOCK, INODE, logno); ++ size = blksize (SUPERBLOCK, INODE_UFS2, logno); + + if ((map = block_map (logno)) < 0) + break; @@ -7898,23 +368,23 @@ diff -ruN grub-0.94.orig/stage2/fsys_ufs2.c stage2/fsys_ufs2.c + + /* load current inode (defaults to the root inode) */ + -+ if (!devread (fsbtodb (SUPERBLOCK, ino_to_fsba (SUPERBLOCK, ino)), -+ ino % (SUPERBLOCK->fs_inopb) * sizeof (struct ufs2_dinode), -+ sizeof (struct ufs2_dinode), (char *) INODE)) -+ return 0; /* XXX what return value? */ ++ if (!devread (fsbtodb (SUPERBLOCK, ino_to_fsba (SUPERBLOCK, ino)), ++ ino % (SUPERBLOCK->fs_inopb) * sizeof (struct ufs2_dinode), ++ sizeof (struct ufs2_dinode), (char *) INODE_UFS2)) ++ return 0; /* XXX what return value? */ + + /* if we have a real file (and we're not just printing possibilities), + then this is where we want to exit */ + + if (!*dirname || isspace (*dirname)) + { -+ if ((INODE->di_mode & IFMT) != IFREG) ++ if ((INODE_UFS2->di_mode & IFMT) != IFREG) + { + errnum = ERR_BAD_FILETYPE; + return 0; + } + -+ filemax = INODE->di_size; ++ filemax = INODE_UFS2->di_size; + + /* incomplete implementation requires this! */ + fsmax = (NDADDR + NINDIR (SUPERBLOCK)) * SUPERBLOCK->fs_bsize; @@ -7926,7 +396,7 @@ diff -ruN grub-0.94.orig/stage2/fsys_ufs2.c stage2/fsys_ufs2.c + while (*dirname == '/') + dirname++; + -+ if (!(INODE->di_size) || ((INODE->di_mode & IFMT) != IFDIR)) ++ if (!(INODE_UFS2->di_size) || ((INODE_UFS2->di_mode & IFMT) != IFDIR)) + { + errnum = ERR_BAD_FILETYPE; + return 0; @@ -7941,12 +411,8 @@ diff -ruN grub-0.94.orig/stage2/fsys_ufs2.c stage2/fsys_ufs2.c + + do + { -+ if (loc >= INODE->di_size) ++ if (loc >= INODE_UFS2->di_size) + { -+#if 0 -+ putchar ('\n'); -+#endif -+ + if (print_possibilities < 0) + return 1; + @@ -7961,7 +427,7 @@ diff -ruN grub-0.94.orig/stage2/fsys_ufs2.c stage2/fsys_ufs2.c + + if ((map = block_map (block)) < 0 + || !devread (fsbtodb (SUPERBLOCK, map), 0, -+ blksize (SUPERBLOCK, INODE, block), ++ blksize (SUPERBLOCK, INODE_UFS2, block), + (char *) FSYS_BUF)) + { + errnum = ERR_FSYS_CORRUPT; @@ -8015,9 +481,9 @@ diff -ruN grub-0.94.orig/stage2/fsys_ufs2.c stage2/fsys_ufs2.c +} + +#endif /* FSYS_UFS2 */ -diff -ruN grub-0.94.orig/stage2/shared.h stage2/shared.h ---- grub-0.94.orig/stage2/shared.h Wed Feb 11 00:22:12 2004 -+++ stage2/shared.h Wed Feb 11 00:22:29 2004 +diff -ruN stage2/shared.h.orig stage2/shared.h +--- stage2/shared.h.orig Sat Apr 24 20:49:07 2004 ++++ stage2/shared.h Sat Apr 24 20:49:16 2004 @@ -205,6 +205,7 @@ #define STAGE2_ID_VSTAFS_STAGE1_5 6 #define STAGE2_ID_JFS_STAGE1_5 7 @@ -8035,993 +501,9 @@ diff -ruN grub-0.94.orig/stage2/shared.h stage2/shared.h # else # error "unknown Stage 2" # endif -diff -ruN grub-0.94.orig/stage2/shared.h.orig stage2/shared.h.orig ---- grub-0.94.orig/stage2/shared.h.orig Thu Jan 1 03:00:00 1970 -+++ stage2/shared.h.orig Sun Jan 11 12:39:22 2004 -@@ -0,0 +1,980 @@ -+/* shared.h - definitions used in all GRUB-specific code */ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+/* -+ * Generic defines to use anywhere -+ */ -+ -+#ifndef GRUB_SHARED_HEADER -+#define GRUB_SHARED_HEADER 1 -+ -+#include <config.h> -+ -+/* Add an underscore to a C symbol in assembler code if needed. */ -+#ifdef HAVE_ASM_USCORE -+# define EXT_C(sym) _ ## sym -+#else -+# define EXT_C(sym) sym -+#endif -+ -+/* Maybe redirect memory requests through grub_scratch_mem. */ -+#ifdef GRUB_UTIL -+extern char *grub_scratch_mem; -+# define RAW_ADDR(x) ((x) + (int) grub_scratch_mem) -+# define RAW_SEG(x) (RAW_ADDR ((x) << 4) >> 4) -+#else -+# define RAW_ADDR(x) (x) -+# define RAW_SEG(x) (x) -+#endif -+ -+/* -+ * Integer sizes -+ */ -+ -+#define MAXINT 0x7FFFFFFF -+ -+/* Maximum command line size. Before you blindly increase this value, -+ see the comment in char_io.c (get_cmdline). */ -+#define MAX_CMDLINE 1600 -+#define NEW_HEAPSIZE 1500 -+ -+/* 512-byte scratch area */ -+#define SCRATCHADDR RAW_ADDR (0x77e00) -+#define SCRATCHSEG RAW_SEG (0x77e0) -+ -+/* -+ * This is the location of the raw device buffer. It is 31.5K -+ * in size. -+ */ -+ -+#define BUFFERLEN 0x7e00 -+#define BUFFERADDR RAW_ADDR (0x70000) -+#define BUFFERSEG RAW_SEG (0x7000) -+ -+#define BOOT_PART_TABLE RAW_ADDR (0x07be) -+ -+/* -+ * BIOS disk defines -+ */ -+#define BIOSDISK_READ 0x0 -+#define BIOSDISK_WRITE 0x1 -+#define BIOSDISK_ERROR_GEOMETRY 0x100 -+#define BIOSDISK_FLAG_LBA_EXTENSION 0x1 -+ -+/* -+ * This is the filesystem (not raw device) buffer. -+ * It is 32K in size, do not overrun! -+ */ -+ -+#define FSYS_BUFLEN 0x8000 -+#define FSYS_BUF RAW_ADDR (0x68000) -+ -+/* Command-line buffer for Multiboot kernels and modules. This area -+ includes the area into which Stage 1.5 and Stage 1 are loaded, but -+ that's no problem. */ -+#define MB_CMDLINE_BUF RAW_ADDR (0x2000) -+#define MB_CMDLINE_BUFLEN 0x6000 -+ -+/* The buffer for the password. */ -+#define PASSWORD_BUF RAW_ADDR (0x78000) -+#define PASSWORD_BUFLEN 0x200 -+ -+/* The buffer for the command-line. */ -+#define CMDLINE_BUF (PASSWORD_BUF + PASSWORD_BUFLEN) -+#define CMDLINE_BUFLEN MAX_CMDLINE -+ -+/* The kill buffer for the command-line. */ -+#define KILL_BUF (CMDLINE_BUF + CMDLINE_BUFLEN) -+#define KILL_BUFLEN MAX_CMDLINE -+ -+/* The history buffer for the command-line. */ -+#define HISTORY_BUF (KILL_BUF + KILL_BUFLEN) -+#define HISTORY_SIZE 5 -+#define HISTORY_BUFLEN (MAX_CMDLINE * HISTORY_SIZE) -+ -+/* The buffer for the completion. */ -+#define COMPLETION_BUF (HISTORY_BUF + HISTORY_BUFLEN) -+#define COMPLETION_BUFLEN MAX_CMDLINE -+ -+/* The buffer for the unique string. */ -+#define UNIQUE_BUF (COMPLETION_BUF + COMPLETION_BUFLEN) -+#define UNIQUE_BUFLEN MAX_CMDLINE -+ -+/* The buffer for the menu entries. */ -+#define MENU_BUF (UNIQUE_BUF + UNIQUE_BUFLEN) -+#define MENU_BUFLEN (0x8000 + PASSWORD_BUF - UNIQUE_BUF) -+ -+/* The size of the drive map. */ -+#define DRIVE_MAP_SIZE 8 -+ -+/* The size of the key map. */ -+#define KEY_MAP_SIZE 128 -+ -+/* The size of the io map. */ -+#define IO_MAP_SIZE 128 -+ -+/* -+ * 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 0x38000000 -+#define LINUX_MAX_SETUP_SECTS 64 -+#define LINUX_BOOT_LOADER_TYPE 0x71 -+#define LINUX_HEAP_END_OFFSET (0x9000 - 0x200) -+ -+#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 -+ -+/* Linux's video mode selection support. Actually I hate it! */ -+#define LINUX_VID_MODE_NORMAL 0xFFFF -+#define LINUX_VID_MODE_EXTENDED 0xFFFE -+#define LINUX_VID_MODE_ASK 0xFFFD -+ -+#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 -+ */ -+ -+#define SECTOR_SIZE 0x200 -+#define SECTOR_BITS 9 -+#define BIOS_FLAG_FIXED_DISK 0x80 -+ -+#define BOOTSEC_LOCATION RAW_ADDR (0x7C00) -+#define BOOTSEC_SIGNATURE 0xAA55 -+#define BOOTSEC_BPB_OFFSET 0x3 -+#define BOOTSEC_BPB_LENGTH 0x3B -+#define BOOTSEC_BPB_SYSTEM_ID 0x3 -+#define BOOTSEC_BPB_HIDDEN_SECTORS 0x1C -+#define BOOTSEC_PART_OFFSET 0x1BE -+#define BOOTSEC_PART_LENGTH 0x40 -+#define BOOTSEC_SIG_OFFSET 0x1FE -+#define BOOTSEC_LISTSIZE 8 -+ -+/* Not bad, perhaps. */ -+#define NETWORK_DRIVE 0x20 -+ -+/* -+ * GRUB specific information -+ * (in LSB order) -+ */ -+ -+#include <stage1.h> -+ -+#define STAGE2_VER_MAJ_OFFS 0x6 -+#define STAGE2_INSTALLPART 0x8 -+#define STAGE2_SAVED_ENTRYNO 0xc -+#define STAGE2_STAGE2_ID 0x10 -+#define STAGE2_FORCE_LBA 0x11 -+#define STAGE2_VER_STR_OFFS 0x12 -+ -+/* Stage 2 identifiers */ -+#define STAGE2_ID_STAGE2 0 -+#define STAGE2_ID_FFS_STAGE1_5 1 -+#define STAGE2_ID_E2FS_STAGE1_5 2 -+#define STAGE2_ID_FAT_STAGE1_5 3 -+#define STAGE2_ID_MINIX_STAGE1_5 4 -+#define STAGE2_ID_REISERFS_STAGE1_5 5 -+#define STAGE2_ID_VSTAFS_STAGE1_5 6 -+#define STAGE2_ID_JFS_STAGE1_5 7 -+#define STAGE2_ID_XFS_STAGE1_5 8 -+ -+#ifndef STAGE1_5 -+# define STAGE2_ID STAGE2_ID_STAGE2 -+#else -+# if defined(FSYS_FFS) -+# define STAGE2_ID STAGE2_ID_FFS_STAGE1_5 -+# elif defined(FSYS_EXT2FS) -+# define STAGE2_ID STAGE2_ID_E2FS_STAGE1_5 -+# elif defined(FSYS_FAT) -+# define STAGE2_ID STAGE2_ID_FAT_STAGE1_5 -+# elif defined(FSYS_MINIX) -+# define STAGE2_ID STAGE2_ID_MINIX_STAGE1_5 -+# elif defined(FSYS_REISERFS) -+# define STAGE2_ID STAGE2_ID_REISERFS_STAGE1_5 -+# elif defined(FSYS_VSTAFS) -+# define STAGE2_ID STAGE2_ID_VSTAFS_STAGE1_5 -+# elif defined(FSYS_JFS) -+# define STAGE2_ID STAGE2_ID_JFS_STAGE1_5 -+# elif defined(FSYS_XFS) -+# define STAGE2_ID STAGE2_ID_XFS_STAGE1_5 -+# else -+# error "unknown Stage 2" -+# endif -+#endif -+ -+/* -+ * defines for use when switching between real and protected mode -+ */ -+ -+#define CR0_PE_ON 0x1 -+#define CR0_PE_OFF 0xfffffffe -+#define PROT_MODE_CSEG 0x8 -+#define PROT_MODE_DSEG 0x10 -+#define PSEUDO_RM_CSEG 0x18 -+#define PSEUDO_RM_DSEG 0x20 -+#define STACKOFF (0x2000 - 0x10) -+#define PROTSTACKINIT (FSYS_BUF - 0x10) -+ -+ -+/* -+ * Assembly code defines -+ * -+ * "EXT_C" is assumed to be defined in the Makefile by the configure -+ * command. -+ */ -+ -+#define ENTRY(x) .globl EXT_C(x) ; EXT_C(x): -+#define VARIABLE(x) ENTRY(x) -+ -+ -+#define K_RDWR 0x60 /* keyboard data & cmds (read/write) */ -+#define K_STATUS 0x64 /* keyboard status */ -+#define K_CMD 0x64 /* keybd ctlr command (write-only) */ -+ -+#define K_OBUF_FUL 0x01 /* output buffer full */ -+#define K_IBUF_FUL 0x02 /* input buffer full */ -+ -+#define KC_CMD_WIN 0xd0 /* read output port */ -+#define KC_CMD_WOUT 0xd1 /* write output port */ -+#define KB_OUTPUT_MASK 0xdd /* enable output buffer full interrupt -+ enable data line -+ enable clock line */ -+#define KB_A20_ENABLE 0x02 -+ -+/* Codes for getchar. */ -+#define ASCII_CHAR(x) ((x) & 0xFF) -+#if !defined(GRUB_UTIL) || !defined(HAVE_LIBCURSES) -+# define KEY_LEFT 0x4B00 -+# define KEY_RIGHT 0x4D00 -+# define KEY_UP 0x4800 -+# define KEY_DOWN 0x5000 -+# define KEY_IC 0x5200 /* insert char */ -+# define KEY_DC 0x5300 /* delete char */ -+# define KEY_BACKSPACE 0x0008 -+# define KEY_HOME 0x4700 -+# define KEY_END 0x4F00 -+# define KEY_NPAGE 0x5100 -+# define KEY_PPAGE 0x4900 -+# define A_NORMAL 0x7 -+# define A_REVERSE 0x70 -+#elif defined(HAVE_NCURSES_CURSES_H) -+# include <ncurses/curses.h> -+#elif defined(HAVE_NCURSES_H) -+# include <ncurses.h> -+#elif defined(HAVE_CURSES_H) -+# include <curses.h> -+#endif -+ -+/* In old BSD curses, A_NORMAL and A_REVERSE are not defined, so we -+ define them here if they are undefined. */ -+#ifndef A_NORMAL -+# define A_NORMAL 0 -+#endif /* ! A_NORMAL */ -+#ifndef A_REVERSE -+# ifdef A_STANDOUT -+# define A_REVERSE A_STANDOUT -+# else /* ! A_STANDOUT */ -+# define A_REVERSE 0 -+# endif /* ! A_STANDOUT */ -+#endif /* ! A_REVERSE */ -+ -+/* Define ACS_* ourselves, since the definitions are not consistent among -+ various curses implementations. */ -+#undef ACS_ULCORNER -+#undef ACS_URCORNER -+#undef ACS_LLCORNER -+#undef ACS_LRCORNER -+#undef ACS_HLINE -+#undef ACS_VLINE -+#undef ACS_LARROW -+#undef ACS_RARROW -+#undef ACS_UARROW -+#undef ACS_DARROW -+ -+#define ACS_ULCORNER '+' -+#define ACS_URCORNER '+' -+#define ACS_LLCORNER '+' -+#define ACS_LRCORNER '+' -+#define ACS_HLINE '-' -+#define ACS_VLINE '|' -+#define ACS_LARROW '<' -+#define ACS_RARROW '>' -+#define ACS_UARROW '^' -+#define ACS_DARROW 'v' -+ -+/* Special graphics characters for IBM displays. */ -+#define DISP_UL 218 -+#define DISP_UR 191 -+#define DISP_LL 192 -+#define DISP_LR 217 -+#define DISP_HORIZ 196 -+#define DISP_VERT 179 -+#define DISP_LEFT 0x1b -+#define DISP_RIGHT 0x1a -+#define DISP_UP 0x18 -+#define DISP_DOWN 0x19 -+ -+/* Remap some libc-API-compatible function names so that we prevent -+ circularararity. */ -+#ifndef WITHOUT_LIBC_STUBS -+#define memmove grub_memmove -+#define memcpy grub_memmove /* we don't need a separate memcpy */ -+#define memset grub_memset -+#define isspace grub_isspace -+#define printf grub_printf -+#define sprintf grub_sprintf -+#undef putchar -+#define putchar grub_putchar -+#define strncat grub_strncat -+#define strstr grub_strstr -+#define memcmp grub_memcmp -+#define strcmp grub_strcmp -+#define tolower grub_tolower -+#define strlen grub_strlen -+#define strcpy grub_strcpy -+#endif /* WITHOUT_LIBC_STUBS */ -+ -+ -+#ifndef ASM_FILE -+/* -+ * Below this should be ONLY defines and other constructs for C code. -+ */ -+ -+/* multiboot stuff */ -+ -+#include "mb_header.h" -+#include "mb_info.h" -+ -+/* For the Linux/i386 boot protocol version 2.03. */ -+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 short heap_end_ptr; /* Free memory after setup end */ -+ unsigned short pad1; /* Unused */ -+ char *cmd_line_ptr; /* Points to the kernel command line */ -+ unsigned long initrd_addr_max; /* The highest address of initrd */ -+} __attribute__ ((packed)); -+ -+/* Memory map address range descriptor used by GET_MMAP_ENTRY. */ -+struct mmar_desc -+{ -+ unsigned long desc_len; /* Size of this descriptor. */ -+ unsigned long long addr; /* Base address. */ -+ unsigned long long length; /* Length in bytes. */ -+ unsigned long type; /* Type of address range. */ -+} __attribute__ ((packed)); -+ -+/* VBE controller information. */ -+struct vbe_controller -+{ -+ unsigned char signature[4]; -+ unsigned short version; -+ unsigned long oem_string; -+ unsigned long capabilities; -+ unsigned long video_mode; -+ unsigned short total_memory; -+ unsigned short oem_software_rev; -+ unsigned long oem_vendor_name; -+ unsigned long oem_product_name; -+ unsigned long oem_product_rev; -+ unsigned char reserved[222]; -+ unsigned char oem_data[256]; -+} __attribute__ ((packed)); -+ -+/* VBE mode information. */ -+struct vbe_mode -+{ -+ unsigned short mode_attributes; -+ unsigned char win_a_attributes; -+ unsigned char win_b_attributes; -+ unsigned short win_granularity; -+ unsigned short win_size; -+ unsigned short win_a_segment; -+ unsigned short win_b_segment; -+ unsigned long win_func; -+ unsigned short bytes_per_scanline; -+ -+ /* >=1.2 */ -+ unsigned short x_resolution; -+ unsigned short y_resolution; -+ unsigned char x_char_size; -+ unsigned char y_char_size; -+ unsigned char number_of_planes; -+ unsigned char bits_per_pixel; -+ unsigned char number_of_banks; -+ unsigned char memory_model; -+ unsigned char bank_size; -+ unsigned char number_of_image_pages; -+ unsigned char reserved0; -+ -+ /* direct color */ -+ unsigned char red_mask_size; -+ unsigned char red_field_position; -+ unsigned char green_mask_size; -+ unsigned char green_field_position; -+ unsigned char blue_mask_size; -+ unsigned char blue_field_position; -+ unsigned char reserved_mask_size; -+ unsigned char reserved_field_position; -+ unsigned char direct_color_mode_info; -+ -+ /* >=2.0 */ -+ unsigned long phys_base; -+ unsigned long reserved1; -+ unsigned short reversed2; -+ -+ /* >=3.0 */ -+ unsigned short linear_bytes_per_scanline; -+ unsigned char banked_number_of_image_pages; -+ unsigned char linear_number_of_image_pages; -+ unsigned char linear_red_mask_size; -+ unsigned char linear_red_field_position; -+ unsigned char linear_green_mask_size; -+ unsigned char linear_green_field_position; -+ unsigned char linear_blue_mask_size; -+ unsigned char linear_blue_field_position; -+ unsigned char linear_reserved_mask_size; -+ unsigned char linear_reserved_field_position; -+ unsigned long max_pixel_clock; -+ -+ unsigned char reserved3[189]; -+} __attribute__ ((packed)); -+ -+ -+#undef NULL -+#define NULL ((void *) 0) -+ -+/* Error codes (descriptions are in common.c) */ -+typedef enum -+{ -+ ERR_NONE = 0, -+ ERR_BAD_FILENAME, -+ ERR_BAD_FILETYPE, -+ ERR_BAD_GZIP_DATA, -+ ERR_BAD_GZIP_HEADER, -+ ERR_BAD_PART_TABLE, -+ ERR_BAD_VERSION, -+ ERR_BELOW_1MB, -+ ERR_BOOT_COMMAND, -+ ERR_BOOT_FAILURE, -+ ERR_BOOT_FEATURES, -+ ERR_DEV_FORMAT, -+ ERR_DEV_VALUES, -+ ERR_EXEC_FORMAT, -+ ERR_FILELENGTH, -+ ERR_FILE_NOT_FOUND, -+ ERR_FSYS_CORRUPT, -+ ERR_FSYS_MOUNT, -+ ERR_GEOM, -+ ERR_NEED_LX_KERNEL, -+ ERR_NEED_MB_KERNEL, -+ ERR_NO_DISK, -+ ERR_NO_PART, -+ ERR_NUMBER_PARSING, -+ ERR_OUTSIDE_PART, -+ ERR_READ, -+ ERR_SYMLINK_LOOP, -+ ERR_UNRECOGNIZED, -+ ERR_WONT_FIT, -+ ERR_WRITE, -+ ERR_BAD_ARGUMENT, -+ ERR_UNALIGNED, -+ ERR_PRIVILEGED, -+ ERR_DEV_NEED_INIT, -+ ERR_NO_DISK_SPACE, -+ ERR_NUMBER_OVERFLOW, -+ -+ MAX_ERR_NUM -+} grub_error_t; -+ -+extern unsigned long install_partition; -+extern unsigned long boot_drive; -+extern unsigned long install_second_sector; -+extern struct apm_info apm_bios_info; -+extern unsigned long boot_part_addr; -+extern int saved_entryno; -+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, -+ otherwise non-zero. */ -+extern int use_config_file; -+/* If using the preset menu, this variable is set to non-zero, -+ otherwise zero. */ -+extern int use_preset_menu; -+/* If not using curses, this variable is set to zero, otherwise non-zero. */ -+extern int use_curses; -+/* The flag for verbose messages. */ -+extern int verbose; -+/* The flag for read-only. */ -+extern int read_only; -+/* The number of floppies to be probed. */ -+extern int floppy_disks; -+/* The map between BIOS drives and UNIX device file names. */ -+extern char **device_map; -+/* The filename which stores the information about a device map. */ -+extern char *device_map_file; -+/* The array of geometries. */ -+extern struct geometry *disks; -+/* Assign DRIVE to a device name DEVICE. */ -+extern void assign_device_name (int drive, const char *device); -+#endif -+ -+#ifndef STAGE1_5 -+/* GUI interface variables. */ -+extern int fallback_entry; -+extern int default_entry; -+extern int current_entryno; -+ -+/* The constants for password types. */ -+typedef enum -+{ -+ PASSWORD_PLAIN, -+ PASSWORD_MD5, -+ PASSWORD_UNSUPPORTED -+} -+password_t; -+ -+extern char *password; -+extern password_t password_type; -+extern int auth; -+extern char commands[]; -+ -+/* For `more'-like feature. */ -+extern int max_lines; -+extern int count_lines; -+extern int use_pager; -+#endif -+ -+#ifndef NO_DECOMPRESSION -+extern int no_decompression; -+extern int compressed_file; -+#endif -+ -+/* instrumentation variables */ -+extern void (*disk_read_hook) (int, int, int); -+extern void (*disk_read_func) (int, int, int); -+ -+#ifndef STAGE1_5 -+/* The flag for debug mode. */ -+extern int debug; -+#endif /* STAGE1_5 */ -+ -+extern unsigned long current_drive; -+extern unsigned long current_partition; -+ -+extern int fsys_type; -+ -+/* The information for a disk geometry. The CHS information is only for -+ DOS/Partition table compatibility, and the real number of sectors is -+ stored in TOTAL_SECTORS. */ -+struct geometry -+{ -+ /* The number of cylinders */ -+ unsigned long cylinders; -+ /* The number of heads */ -+ unsigned long heads; -+ /* The number of sectors */ -+ unsigned long sectors; -+ /* The total number of sectors */ -+ unsigned long total_sectors; -+ /* Flags */ -+ unsigned long flags; -+}; -+ -+extern unsigned long part_start; -+extern unsigned long part_length; -+ -+extern int current_slice; -+ -+extern int buf_drive; -+extern int buf_track; -+extern struct geometry buf_geom; -+ -+/* these are the current file position and maximum file position */ -+extern int filepos; -+extern int filemax; -+ -+/* -+ * Common BIOS/boot data. -+ */ -+ -+extern struct multiboot_info mbi; -+extern unsigned long saved_drive; -+extern unsigned long saved_partition; -+#ifndef STAGE1_5 -+extern unsigned long saved_mem_upper; -+extern unsigned long extended_memory; -+#endif -+ -+/* -+ * Error variables. -+ */ -+ -+extern grub_error_t errnum; -+extern char *err_list[]; -+ -+/* Simplify declaration of entry_addr. */ -+typedef void (*entry_func) (int, int, int, int, int, int) -+ __attribute__ ((noreturn)); -+ -+extern entry_func entry_addr; -+ -+/* Enter the stage1.5/stage2 C code after the stack is set up. */ -+void cmain (void); -+ -+/* Halt the processor (called after an unrecoverable error). */ -+void stop (void) __attribute__ ((noreturn)); -+ -+/* Reboot the system. */ -+void grub_reboot (void) __attribute__ ((noreturn)); -+ -+/* Halt the system, using APM if possible. If NO_APM is true, don't use -+ APM even if it is available. */ -+void grub_halt (int no_apm) __attribute__ ((noreturn)); -+ -+/* Copy MAP to the drive map and set up int13_handler. */ -+void set_int13_handler (unsigned short *map); -+ -+/* Set up int15_handler. */ -+void set_int15_handler (void); -+ -+/* Restore the original int15 handler. */ -+void unset_int15_handler (void); -+ -+/* Track the int13 handler to probe I/O address space. */ -+void track_int13 (int drive); -+ -+/* The key map. */ -+extern unsigned short bios_key_map[]; -+extern unsigned short ascii_key_map[]; -+extern unsigned short io_map[]; -+ -+/* calls for direct boot-loader chaining */ -+void chain_stage1 (unsigned long segment, unsigned long offset, -+ unsigned long part_table_addr) -+ __attribute__ ((noreturn)); -+void chain_stage2 (unsigned long segment, unsigned long offset, -+ int second_sector) -+ __attribute__ ((noreturn)); -+ -+/* do some funky stuff, then boot linux */ -+void linux_boot (void) __attribute__ ((noreturn)); -+ -+/* do some funky stuff, then boot bzImage linux */ -+void big_linux_boot (void) __attribute__ ((noreturn)); -+ -+/* booting a multiboot executable */ -+void multi_boot (int start, int mb_info) __attribute__ ((noreturn)); -+ -+/* If LINEAR is nonzero, then set the Intel processor to linear mode. -+ Otherwise, bit 20 of all memory accesses is always forced to zero, -+ causing a wraparound effect for bugwards compatibility with the -+ 8086 CPU. */ -+void gateA20 (int linear); -+ -+/* memory probe routines */ -+int get_memsize (int type); -+int get_eisamemsize (void); -+ -+/* Fetch the next entry in the memory map and return the continuation -+ value. DESC is a pointer to the descriptor buffer, and CONT is the -+ previous continuation value (0 to get the first entry in the -+ map). */ -+int get_mmap_entry (struct mmar_desc *desc, int cont); -+ -+/* Get the linear address of a ROM configuration table. Return zero, -+ if fails. */ -+unsigned long get_rom_config_table (void); -+ -+/* Get APM BIOS information. */ -+void get_apm_info (void); -+ -+/* Get VBE controller information. */ -+int get_vbe_controller_info (struct vbe_controller *controller); -+ -+/* Get VBE mode information. */ -+int get_vbe_mode_info (int mode_number, struct vbe_mode *mode); -+ -+/* Set VBE mode. */ -+int set_vbe_mode (int mode_number); -+ -+/* Return the data area immediately following our code. */ -+int get_code_end (void); -+ -+/* low-level timing info */ -+int getrtsecs (void); -+int currticks (void); -+ -+/* Clear the screen. */ -+void cls (void); -+ -+/* Turn on/off cursor. */ -+int setcursor (int on); -+ -+/* Get the current cursor position (where 0,0 is the top left hand -+ corner of the screen). Returns packed values, (RET >> 8) is x, -+ (RET & 0xff) is y. */ -+int getxy (void); -+ -+/* Set the cursor position. */ -+void gotoxy (int x, int y); -+ -+/* Displays an ASCII character. IBM displays will translate some -+ characters to special graphical ones (see the DISP_* constants). */ -+void grub_putchar (int c); -+ -+/* Wait for a keypress, and return its packed BIOS/ASCII key code. -+ Use ASCII_CHAR(ret) to extract the ASCII code. */ -+int getkey (void); -+ -+/* Like GETKEY, but doesn't block, and returns -1 if no keystroke is -+ available. */ -+int checkkey (void); -+ -+/* Low-level disk I/O */ -+int get_diskinfo (int drive, struct geometry *geometry); -+int biosdisk (int subfunc, int drive, struct geometry *geometry, -+ int sector, int nsec, int segment); -+void stop_floppy (void); -+ -+/* Command-line interface functions. */ -+#ifndef STAGE1_5 -+ -+/* The flags for the builtins. */ -+#define BUILTIN_CMDLINE 0x1 /* Run in the command-line. */ -+#define BUILTIN_MENU 0x2 /* Run in the menu. */ -+#define BUILTIN_TITLE 0x4 /* Only for the command title. */ -+#define BUILTIN_SCRIPT 0x8 /* Run in the script. */ -+#define BUILTIN_NO_ECHO 0x10 /* Don't print command on booting. */ -+#define BUILTIN_HELP_LIST 0x20 /* Show help in listing. */ -+ -+/* The table for a builtin. */ -+struct builtin -+{ -+ /* The command name. */ -+ char *name; -+ /* The callback function. */ -+ int (*func) (char *, int); -+ /* The combination of the flags defined above. */ -+ int flags; -+ /* The short version of the documentation. */ -+ char *short_doc; -+ /* The long version of the documentation. */ -+ char *long_doc; -+}; -+ -+/* All the builtins are registered in this. */ -+extern struct builtin *builtin_table[]; -+ -+/* The constants for kernel types. */ -+typedef enum -+{ -+ KERNEL_TYPE_NONE, /* None is loaded. */ -+ KERNEL_TYPE_MULTIBOOT, /* Multiboot. */ -+ KERNEL_TYPE_LINUX, /* Linux. */ -+ KERNEL_TYPE_BIG_LINUX, /* Big Linux. */ -+ KERNEL_TYPE_FREEBSD, /* FreeBSD. */ -+ KERNEL_TYPE_NETBSD, /* NetBSD. */ -+ KERNEL_TYPE_CHAINLOADER /* Chainloader. */ -+} -+kernel_t; -+ -+extern kernel_t kernel_type; -+extern int show_menu; -+extern int grub_timeout; -+ -+void init_builtins (void); -+void init_config (void); -+char *skip_to (int after_equal, char *cmdline); -+struct builtin *find_command (char *command); -+void print_cmdline_message (int forever); -+void enter_cmdline (char *heap, int forever); -+int run_script (char *script, char *heap); -+#endif -+ -+/* C library replacement functions with identical semantics. */ -+void grub_printf (const char *format,...); -+int grub_sprintf (char *buffer, const char *format, ...); -+int grub_tolower (int c); -+int grub_isspace (int c); -+int grub_strncat (char *s1, const char *s2, int n); -+void *grub_memmove (void *to, const void *from, int len); -+void *grub_memset (void *start, int c, int len); -+int grub_strncat (char *s1, const char *s2, int n); -+char *grub_strstr (const char *s1, const char *s2); -+int grub_memcmp (const char *s1, const char *s2, int n); -+int grub_strcmp (const char *s1, const char *s2); -+int grub_strlen (const char *str); -+char *grub_strcpy (char *dest, const char *src); -+ -+#ifndef GRUB_UTIL -+typedef unsigned long grub_jmp_buf[6]; -+#else -+/* In the grub shell, use the libc jmp_buf instead. */ -+# include <setjmp.h> -+# define grub_jmp_buf jmp_buf -+#endif -+ -+#ifdef GRUB_UTIL -+# define grub_setjmp setjmp -+# define grub_longjmp longjmp -+#else /* ! GRUB_UTIL */ -+int grub_setjmp (grub_jmp_buf env); -+void grub_longjmp (grub_jmp_buf env, int val); -+#endif /* ! GRUB_UTIL */ -+ -+/* The environment for restarting Stage 2. */ -+extern grub_jmp_buf restart_env; -+/* The environment for restarting the command-line interface. */ -+extern grub_jmp_buf restart_cmdline_env; -+ -+/* misc */ -+void init_page (void); -+void print_error (void); -+char *convert_to_ascii (char *buf, int c, ...); -+int get_cmdline (char *prompt, char *cmdline, int maxlen, -+ int echo_char, int history); -+int substring (const char *s1, const char *s2); -+int nul_terminate (char *str); -+int get_based_digit (int c, int base); -+int safe_parse_maxint (char **str_ptr, int *myint_ptr); -+int memcheck (int start, int len); -+void grub_putstr (const char *str); -+ -+#ifndef NO_DECOMPRESSION -+/* Compression support. */ -+int gunzip_test_header (void); -+int gunzip_read (char *buf, int len); -+#endif /* NO_DECOMPRESSION */ -+ -+int rawread (int drive, int sector, int byte_offset, int byte_len, char *buf); -+int devread (int sector, int byte_offset, int byte_len, char *buf); -+int rawwrite (int drive, int sector, char *buf); -+int devwrite (int sector, int sector_len, char *buf); -+ -+/* Parse a device string and initialize the global parameters. */ -+char *set_device (char *device); -+int open_device (void); -+int real_open_partition (int flags); -+int open_partition (void); -+int next_partition (unsigned long drive, unsigned long dest, -+ unsigned long *partition, int *type, -+ unsigned long *start, unsigned long *len, -+ unsigned long *offset, int *entry, -+ unsigned long *ext_offset, char *buf); -+ -+/* Sets device to the one represented by the SAVED_* parameters. */ -+int make_saved_active (void); -+ -+/* Set or clear the current root partition's hidden flag. */ -+int set_partition_hidden_flag (int hidden); -+ -+/* Open a file or directory on the active device, using GRUB's -+ internal filesystem support. */ -+int grub_open (char *filename); -+ -+/* Read LEN bytes into BUF from the file that was opened with -+ GRUB_OPEN. If LEN is -1, read all the remaining data in the file. */ -+int grub_read (char *buf, int len); -+ -+/* Reposition a file offset. */ -+int grub_seek (int offset); -+ -+/* Close a file. */ -+void grub_close (void); -+ -+/* List the contents of the directory that was opened with GRUB_OPEN, -+ printing all completions. */ -+int dir (char *dirname); -+ -+int set_bootdev (int hdbias); -+ -+/* Display statistics on the current active device. */ -+void print_fsys_type (void); -+ -+/* Display device and filename completions. */ -+void print_a_completion (char *filename); -+int print_completions (int is_filename, int is_completion); -+ -+/* Copies the current partition data to the desired address. */ -+void copy_current_part_entry (char *buf); -+ -+#ifndef STAGE1_5 -+void bsd_boot (kernel_t type, int bootdev, char *arg) -+ __attribute__ ((noreturn)); -+ -+/* Define flags for load_image here. */ -+/* Don't pass a Linux's mem option automatically. */ -+#define KERNEL_LOAD_NO_MEM_OPTION (1 << 0) -+ -+kernel_t load_image (char *kernel, char *arg, kernel_t suggested_type, -+ unsigned long load_flags); -+ -+int load_module (char *module, char *arg); -+int load_initrd (char *initrd); -+ -+int check_password(char *entered, char* expected, password_t type); -+#endif -+ -+void init_bios_info (void); -+ -+#endif /* ASM_FILE */ -+ -+#endif /* ! GRUB_SHARED_HEADER */ -diff -ruN grub-0.94.orig/stage2/size_test stage2/size_test ---- grub-0.94.orig/stage2/size_test Wed Feb 11 00:22:12 2004 -+++ stage2/size_test Wed Feb 11 00:22:29 2004 +diff -ruN stage2/size_test.orig stage2/size_test +--- stage2/size_test.orig Sat Apr 24 20:49:07 2004 ++++ stage2/size_test Sat Apr 24 20:49:16 2004 @@ -40,6 +40,8 @@ # The bootloader area of a FFS partition is 14 sectors. check ffs_stage1_5 7168 @@ -9031,68 +513,10 @@ diff -ruN grub-0.94.orig/stage2/size_test stage2/size_test # Stage 1.5 can be installed in the sectors immediately after MBR in the # first cylinder, so the size is (63 - 1) sectors. check fat_stage1_5 31744 -diff -ruN grub-0.94.orig/stage2/size_test.orig stage2/size_test.orig ---- grub-0.94.orig/stage2/size_test.orig Thu Jan 1 03:00:00 1970 -+++ stage2/size_test.orig Wed Jul 9 15:45:53 2003 -@@ -0,0 +1,54 @@ -+#!/bin/sh -+ -+# Check the sizes of Stage 2 and Stage 1.5's. -+# Copyright (C) 1999 Free Software Foundation, Inc. -+ -+# This program is free software; you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation; either version 2, or (at your option) -+# any later version. -+ -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+ -+# You should have received a copy of the GNU General Public License -+# along with this program; if not, write to the Free Software Foundation, -+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ -+# Written by OKUJI Yoshinori <okuji@kuicr.kyoto-u.ac.jp> -+ -+ -+# This function checks if the size of the first argument (filename) is -+# greater than the second argument (limit). If so, then exit with the -+# status 1, otherwise do nothing. -+check () -+{ -+ local file size limit -+ -+ file=$1 -+ limit=$2 -+ set dummy `ls -l $file` -+ size=$6 -+ if test $size -gt $limit; then -+ echo "$file is too big ($size > $limit)." -+ exit 1 -+ fi -+} -+ -+# The bootloader area of a FFS partition is 14 sectors. -+check ffs_stage1_5 7168 -+ -+# Stage 1.5 can be installed in the sectors immediately after MBR in the -+# first cylinder, so the size is (63 - 1) sectors. -+check fat_stage1_5 31744 -+ -+# Likewise. -+check e2fs_stage1_5 31744 -+ -+# Likewise. -+check minix_stage1_5 31744 -+ -+# Success. -+exit 0 -diff -ruN grub-0.94.orig/stage2/ufs2.h stage2/ufs2.h ---- grub-0.94.orig/stage2/ufs2.h Thu Jan 1 03:00:00 1970 -+++ stage2/ufs2.h Wed Feb 11 00:23:16 2004 -@@ -0,0 +1,410 @@ +diff -ruN stage2/ufs2.h.orig stage2/ufs2.h +--- stage2/ufs2.h.orig Thu Jan 1 03:00:00 1970 ++++ stage2/ufs2.h Sat Apr 24 20:49:31 2004 +@@ -0,0 +1,449 @@ +/* + * Copyright (c) 2002 Networks Associates Technology, Inc. + * All rights reserved. @@ -9136,7 +560,7 @@ diff -ruN grub-0.94.orig/stage2/ufs2.h stage2/ufs2.h + * SUCH DAMAGE. + * + * @(#)dinode.h 8.3 (Berkeley) 1/21/94 -+ * $FreeBSD: /tmp/pcvs/ports/sysutils/grub/files/Attic/patch-ufs2,v 1.1 2004-02-10 22:00:02 krion Exp $ ++ * $FreeBSD: /tmp/pcvs/ports/sysutils/grub/files/Attic/patch-ufs2,v 1.2 2004-06-06 13:31:35 pav Exp $ + */ + +#ifndef _GRUB_UFS2_H_ @@ -9161,16 +585,14 @@ diff -ruN grub-0.94.orig/stage2/ufs2.h stage2/ufs2.h + +/* + * __uint* constants already defined in -+ * FreeBSD 5.x /usr/include/machine/_types.h -+ * or -+ * FreeBSD 4.x /usr/include/machine/ansi.h ++ * FreeBSD's /usr/include/machine/_types.h + */ +#if !defined(_MACHINE__TYPES_H_) && !defined(_MACHINE_ANSI_H_) +typedef uint8_t __uint8_t; +typedef uint16_t __uint16_t; +typedef uint32_t __uint32_t; +typedef uint64_t __uint64_t; -+#endif /* _MACHINE__TYPES_H_ */ ++#endif /* !_MACHINE__TYPES_H_ && !_MACHINE_ANSI_H_ */ + +#define i_size di_size + @@ -9188,6 +610,7 @@ diff -ruN grub-0.94.orig/stage2/ufs2.h stage2/ufs2.h +/* + * The size of physical and logical block numbers and time fields in UFS. + */ ++typedef int32_t ufs1_daddr_t; +typedef int64_t ufs2_daddr_t; +typedef int64_t ufs_lbn_t; +typedef int64_t ufs_time_t; @@ -9225,6 +648,29 @@ diff -ruN grub-0.94.orig/stage2/ufs2.h stage2/ufs2.h +#define NDADDR 12 /* Direct addresses in inode. */ +#define NIADDR 3 /* Indirect addresses in inode. */ + ++struct ufs1_dinode { ++ u_int16_t di_mode; /* 0: IFMT, permissions; see below. */ ++ int16_t di_nlink; /* 2: File link count. */ ++ union { ++ u_int16_t oldids[2]; /* 4: Ffs: old user and group ids. */ ++ } di_u; ++ u_int64_t di_size; /* 8: File byte count. */ ++ int32_t di_atime; /* 16: Last access time. */ ++ int32_t di_atimensec; /* 20: Last access time. */ ++ int32_t di_mtime; /* 24: Last modified time. */ ++ int32_t di_mtimensec; /* 28: Last modified time. */ ++ int32_t di_ctime; /* 32: Last inode change time. */ ++ int32_t di_ctimensec; /* 36: Last inode change time. */ ++ ufs1_daddr_t di_db[NDADDR]; /* 40: Direct disk blocks. */ ++ ufs1_daddr_t di_ib[NIADDR]; /* 88: Indirect disk blocks. */ ++ u_int32_t di_flags; /* 100: Status flags (chflags). */ ++ int32_t di_blocks; /* 104: Blocks actually held. */ ++ int32_t di_gen; /* 108: Generation number. */ ++ u_int32_t di_uid; /* 112: File owner. */ ++ u_int32_t di_gid; /* 116: File group. */ ++ int32_t di_spare[2]; /* 120: Reserved; currently unused */ ++}; ++ +struct ufs2_dinode { + u_int16_t di_mode; /* 0: IFMT, permissions; see below. */ + int16_t di_nlink; /* 2: File link count. */ @@ -9274,8 +720,16 @@ diff -ruN grub-0.94.orig/stage2/ufs2.h stage2/ufs2.h +#define DT_SOCK 12 +#define DT_WHT 14 + -+#define SBLOCK_UFS2 65536 -+#define SBLOCKSIZE 8192 ++/* ++ * Superblock offsets ++ */ ++#define SBLOCK_FLOPPY 0 ++#define SBLOCK_UFS1 8192 ++#define SBLOCK_UFS2 65536 ++#define SBLOCK_PIGGY 262144 ++#define SBLOCKSIZE 8192 ++#define SBLOCKSEARCH \ ++ { SBLOCK_UFS2, SBLOCK_UFS1, SBLOCK_FLOPPY, SBLOCK_PIGGY, -1 } + +#define MAXMNTLEN 512 + @@ -9419,6 +873,7 @@ diff -ruN grub-0.94.orig/stage2/ufs2.h stage2/ufs2.h +/* + * Filesystem identification + */ ++#define FS_UFS1_MAGIC 0x011954 /* UFS1 fast filesystem magic number */ +#define FS_UFS2_MAGIC 0x19540119 /* UFS2 fast filesystem magic number */ + +/* @@ -9502,22 +957,12 @@ diff -ruN grub-0.94.orig/stage2/ufs2.h stage2/ufs2.h + */ +#define NINDIR(fs) ((fs)->fs_nindir) + ++#define FS_UNCLEAN 0x01 /* filesystem not clean at mount */ ++#define FS_DOSOFTDEP 0x02 /* filesystem using soft dependencies */ ++#define FS_NEEDSFSCK 0x04 /* filesystem needs sync fsck before mount */ ++#define FS_INDEXDIRS 0x08 /* kernel supports indexed directories */ ++#define FS_ACLS 0x10 /* file system has ACLs enabled */ ++#define FS_MULTILABEL 0x20 /* file system is MAC multi-label */ ++#define FS_FLAGS_UPDATED 0x80 /* flags have been moved to new location */ ++ +#endif /* _GRUB_UFS2_H_ */ ---- util/grub-install.in.orig Wed Feb 11 00:31:26 2004 -+++ util/grub-install.in Wed Feb 11 00:31:58 2004 -@@ -105,11 +105,11 @@ - tmp_disk=`echo "$1" | sed 's%\([sh]d[0-9]*\).*%\1%'` - tmp_part=`echo "$1" | sed "s%$tmp_disk%%"` ;; - freebsd*) -- tmp_disk=`echo "$1" | sed 's%r\{0,1\}\([saw]d[0-9]*\).*$%r\1%' \ -- | sed 's%r\{0,1\}\(da[0-9]*\).*$%r\1%'` -+ tmp_disk=`echo "$1" | sed 's%\([saw]d[0-9]*\).*$%\1%' \ -+ | sed 's%\(da[0-9]*\).*$%\1%'` - tmp_part=`echo "$1" \ -- | sed "s%.*/r\{0,1\}[saw]d[0-9]\(s[0-9]*[a-h]\)%\1%" \ -- | sed "s%.*/r\{0,1\}da[0-9]\(s[0-9]*[a-h]\)%\1%"` -+ | sed "s%.*/[saw]d[0-9]\(s[0-9]*[a-h]\)%\1%" \ -+ | sed "s%.*/da[0-9]\(s[0-9]*[a-h]\)%\1%"` - ;; - netbsd*) - tmp_disk=`echo "$1" | sed 's%r\{0,1\}\([sw]d[0-9]*\).*$%r\1d%' \ |