diff options
| author | blogic <blogic@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2012-10-05 10:12:53 +0000 | 
|---|---|---|
| committer | blogic <blogic@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2012-10-05 10:12:53 +0000 | 
| commit | 5c105d9f3fd086aff195d3849dcf847d6b0bd927 (patch) | |
| tree | 1229a11f725bfa58aa7c57a76898553bb5f6654a /package/grub/patches | |
| download | openwrt-5c105d9f3fd086aff195d3849dcf847d6b0bd927.tar.gz openwrt-5c105d9f3fd086aff195d3849dcf847d6b0bd927.zip | |
branch Attitude Adjustment
git-svn-id: svn://svn.openwrt.org/openwrt/branches/attitude_adjustment@33625 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'package/grub/patches')
| -rw-r--r-- | package/grub/patches/002-strip_note_gnu_build_id.patch | 22 | ||||
| -rw-r--r-- | package/grub/patches/010-fixes-1.patch | 4466 | ||||
| -rw-r--r-- | package/grub/patches/020-ext4_support.patch | 267 | ||||
| -rw-r--r-- | package/grub/patches/030-add-stage2-ldscripts.patch | 77 | ||||
| -rw-r--r-- | package/grub/patches/040-automake-compat.patch | 41 | ||||
| -rw-r--r-- | package/grub/patches/100-add_configure_macros.patch | 11 | ||||
| -rw-r--r-- | package/grub/patches/110-remove_configure_errors.patch | 38 | ||||
| -rw-r--r-- | package/grub/patches/200-darwin_fixes.patch | 48 | ||||
| -rw-r--r-- | package/grub/patches/210-remove_inline_asm.patch | 14 | 
9 files changed, 4984 insertions, 0 deletions
| diff --git a/package/grub/patches/002-strip_note_gnu_build_id.patch b/package/grub/patches/002-strip_note_gnu_build_id.patch new file mode 100644 index 000000000..40aa74dc7 --- /dev/null +++ b/package/grub/patches/002-strip_note_gnu_build_id.patch @@ -0,0 +1,22 @@ +--- a/stage1/Makefile.in ++++ b/stage1/Makefile.in +@@ -427,7 +427,7 @@ uninstall-am: uninstall-info-am uninstal + 	uninstall-nodist_pkglibDATA +  + .exec: +-	$(OBJCOPY) -O binary $< $@ ++	$(OBJCOPY) -O binary -R .comment -R .note -R .note.gnu.build-id $< $@ + # Tell versions [3.59,3.63) of GNU make to not export all variables. + # Otherwise a system limit (for SysV at least) may be exceeded. + .NOEXPORT: +--- a/stage2/Makefile.in ++++ b/stage2/Makefile.in +@@ -3244,7 +3244,7 @@ pxegrub: pxeloader diskless + 	-rm -f $@ + 	cat $^ > $@ + .exec: +-	$(OBJCOPY) -O binary $< $@ ++	$(OBJCOPY) -O binary -R .comment -R .note -R .note.gnu.build-id $< $@ + # Tell versions [3.59,3.63) of GNU make to not export all variables. + # Otherwise a system limit (for SysV at least) may be exceeded. + .NOEXPORT: diff --git a/package/grub/patches/010-fixes-1.patch b/package/grub/patches/010-fixes-1.patch new file mode 100644 index 000000000..91a9e2190 --- /dev/null +++ b/package/grub/patches/010-fixes-1.patch @@ -0,0 +1,4466 @@ +Submitted By: Jim Gifford (jim at linuxfromscratch dot org) +Date: 2006-07-04 +Initial Package Version: 0.97 +Origin: Debian +Upstream Status: Unknown +Description: Contains various fixes and enhancements +	Graphics mode support +	Fixes for Raid Support +	XFS Filesystem Boot Freeze Fixes +	Removed 2GB Memory Limitation +	Freebsd support +	Fixes for initrd support +	Grub installation Fixes +	Linux 2.6 geometry Fixes +	Intel Mac Support +	Autoconf and aclocal updates + +http://trac.cross-lfs.org/browser/trunk/patches/grub-0.97-fixes-1.patch + +--- a/aclocal.m4 ++++ b/aclocal.m4 +@@ -1,7 +1,7 @@ +-# generated automatically by aclocal 1.9.4 -*- Autoconf -*- ++# generated automatically by aclocal 1.9.6 -*- Autoconf -*- +  +-# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 +-# Free Software Foundation, Inc. ++# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, ++# 2005  Free Software Foundation, Inc. + # This file is free software; the Free Software Foundation + # gives unlimited permission to copy and/or distribute it, + # with or without modifications, as long as this notice is preserved. +@@ -11,23 +11,11 @@ + # even the implied warranty of MERCHANTABILITY or FITNESS FOR A + # PARTICULAR PURPOSE. +  +-#                                                        -*- Autoconf -*- +-# Copyright (C) 2002, 2003  Free Software Foundation, Inc. +-# Generated from amversion.in; do not edit by hand. +- +-# 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 ++# Copyright (C) 2002, 2003, 2005  Free Software Foundation, Inc. ++# ++# This file is free software; the Free Software Foundation ++# gives unlimited permission to copy and/or distribute it, ++# with or without modifications, as long as this notice is preserved. +  + # AM_AUTOMAKE_VERSION(VERSION) + # ---------------------------- +@@ -40,26 +28,15 @@ AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api + # Call AM_AUTOMAKE_VERSION so it can be traced. + # This function is AC_REQUIREd by AC_INIT_AUTOMAKE. + AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +-	 [AM_AUTOMAKE_VERSION([1.9.4])]) +- +-# AM_AUX_DIR_EXPAND +- +-# Copyright (C) 2001, 2003 Free Software Foundation, Inc. ++	 [AM_AUTOMAKE_VERSION([1.9.6])]) +  +-# 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. ++# AM_AUX_DIR_EXPAND                                         -*- Autoconf -*- +  +-# 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. ++# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc. ++# ++# This file is free software; the Free Software Foundation ++# gives unlimited permission to copy and/or distribute it, ++# with or without modifications, as long as this notice is preserved. +  + # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets + # $ac_aux_dir to `$srcdir/foo'.  In other projects, it is set to +@@ -106,26 +83,16 @@ AC_PREREQ([2.50])dnl + am_aux_dir=`cd $ac_aux_dir && pwd` + ]) +  +-# AM_CONDITIONAL                                              -*- Autoconf -*- ++# AM_CONDITIONAL                                            -*- Autoconf -*- +  +-# Copyright (C) 1997, 2000, 2001, 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, 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. ++# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005 ++# Free Software Foundation, Inc. ++# ++# This file is free software; the Free Software Foundation ++# gives unlimited permission to copy and/or distribute it, ++# with or without modifications, as long as this notice is preserved. +  +-# serial 6 ++# serial 7 +  + # AM_CONDITIONAL(NAME, SHELL-CONDITION) + # ------------------------------------- +@@ -149,26 +116,15 @@ AC_CONFIG_COMMANDS_PRE( + Usually this means the macro was only invoked conditionally.]]) + fi])]) +  +-# serial 7						-*- Autoconf -*- +  +-# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 ++# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 + # Free Software Foundation, Inc. ++# ++# This file is free software; the Free Software Foundation ++# gives unlimited permission to copy and/or distribute it, ++# with or without modifications, as long as this notice is preserved. +  +-# 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. +- ++# serial 8 +  + # There are a few dirty hacks below to avoid letting `AC_PROG_CC' be + # written in clear, in which case automake, when reading aclocal.m4, +@@ -177,7 +133,6 @@ fi])]) + # CC etc. in the Makefile, will ask for an AC_PROG_CC use... +  +  +- + # _AM_DEPENDENCIES(NAME) + # ---------------------- + # See how the compiler implements dependency checking. +@@ -317,27 +272,16 @@ AM_CONDITIONAL([AMDEP], [test "x$enable_ + AC_SUBST([AMDEPBACKSLASH]) + ]) +  +-# Generate code to set up dependency tracking.   -*- Autoconf -*- +- +-# 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, or (at your option) +-# any later version. ++# Generate code to set up dependency tracking.              -*- Autoconf -*- +  +-# 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. ++# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 ++# Free Software Foundation, Inc. ++# ++# This file is free software; the Free Software Foundation ++# gives unlimited permission to copy and/or distribute it, ++# with or without modifications, as long as this notice is preserved. +  +-#serial 2 ++#serial 3 +  + # _AM_OUTPUT_DEPENDENCY_COMMANDS + # ------------------------------ +@@ -396,30 +340,19 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS] +      [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) + ]) +  +-# Do all the work for Automake.                            -*- Autoconf -*- ++# Do all the work for Automake.                             -*- Autoconf -*- +  +-# This macro actually does too much some checks are only needed if +-# your package does certain things.  But this isn't really a big deal. +- +-# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 ++# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 + # Free Software Foundation, Inc. ++# ++# This file is free software; the Free Software Foundation ++# gives unlimited permission to copy and/or distribute it, ++# with or without modifications, as long as this notice is preserved. +  +-# 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. ++# serial 12 +  +-# serial 11 ++# This macro actually does too much.  Some checks are only needed if ++# your package does certain things.  But this isn't really a big deal. +  + # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) + # AM_INIT_AUTOMAKE([OPTIONS]) +@@ -521,51 +454,27 @@ for _am_header in $config_headers :; do + done + echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count]) +  ++# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc. ++# ++# This file is free software; the Free Software Foundation ++# gives unlimited permission to copy and/or distribute it, ++# with or without modifications, as long as this notice is preserved. ++ + # AM_PROG_INSTALL_SH + # ------------------ + # Define $install_sh. +- +-# Copyright (C) 2001, 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, 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. +- + AC_DEFUN([AM_PROG_INSTALL_SH], + [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl + install_sh=${install_sh-"$am_aux_dir/install-sh"} + AC_SUBST(install_sh)]) +  +-#                                                          -*- Autoconf -*- +-# Copyright (C) 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, 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. ++# Copyright (C) 2003, 2005  Free Software Foundation, Inc. ++# ++# This file is free software; the Free Software Foundation ++# gives unlimited permission to copy and/or distribute it, ++# with or without modifications, as long as this notice is preserved. +  +-# serial 1 ++# serial 2 +  + # Check whether the underlying file-system supports filenames + # with a leading dot.  For instance MS-DOS doesn't. +@@ -580,28 +489,17 @@ fi + rmdir .tst 2>/dev/null + AC_SUBST([am__leading_dot])]) +  +-# Add --enable-maintainer-mode option to configure. ++# Add --enable-maintainer-mode option to configure.         -*- Autoconf -*- + # From Jim Meyering +  +-# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004 ++# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005 + # Free Software Foundation, Inc. ++# ++# This file is free software; the Free Software Foundation ++# gives unlimited permission to copy and/or distribute it, ++# with or without modifications, as long as this notice is preserved. +  +-# 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. +- +-# serial 3 ++# serial 4 +  + AC_DEFUN([AM_MAINTAINER_MODE], + [AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) +@@ -620,26 +518,15 @@ AC_DEFUN([AM_MAINTAINER_MODE], +  + AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE]) +  +-# Check to see how 'make' treats includes.	-*- Autoconf -*- +- +-# Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. ++# Check to see how 'make' treats includes.	            -*- Autoconf -*- +  +-# 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. ++# Copyright (C) 2001, 2002, 2003, 2005  Free Software Foundation, Inc. ++# ++# This file is free software; the Free Software Foundation ++# gives unlimited permission to copy and/or distribute it, ++# with or without modifications, as long as this notice is preserved. +  +-# serial 2 ++# serial 3 +  + # AM_MAKE_INCLUDE() + # ----------------- +@@ -683,27 +570,16 @@ AC_MSG_RESULT([$_am_result]) + rm -f confinc confmf + ]) +  +-#  -*- Autoconf -*- +- +- +-# Copyright (C) 1997, 1999, 2000, 2001, 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, or (at your option) +-# any later version. ++# Fake the existence of programs that GNU maintainers use.  -*- Autoconf -*- +  +-# 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. ++# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2005 ++# Free Software Foundation, Inc. ++# ++# This file is free software; the Free Software Foundation ++# gives unlimited permission to copy and/or distribute it, ++# with or without modifications, as long as this notice is preserved. +  +-# serial 3 ++# serial 4 +  + # AM_MISSING_PROG(NAME, PROGRAM) + # ------------------------------ +@@ -729,27 +605,16 @@ else + fi + ]) +  ++# Copyright (C) 2003, 2004, 2005  Free Software Foundation, Inc. ++# ++# This file is free software; the Free Software Foundation ++# gives unlimited permission to copy and/or distribute it, ++# with or without modifications, as long as this notice is preserved. ++ + # AM_PROG_MKDIR_P + # --------------- + # Check whether `mkdir -p' is supported, fallback to mkinstalldirs otherwise. +- +-# Copyright (C) 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, 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. +- ++# + # Automake 1.8 used `mkdir -m 0755 -p --' to ensure that directories + # created by `make install' are always world readable, even if the + # installer happens to have an overly restrictive umask (e.g. 077). +@@ -803,26 +668,15 @@ else + fi + AC_SUBST([mkdir_p])]) +  +-# Helper functions for option handling.                    -*- Autoconf -*- ++# Helper functions for option handling.                     -*- Autoconf -*- +  +-# Copyright (C) 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, 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. ++# Copyright (C) 2001, 2002, 2003, 2005  Free Software Foundation, Inc. ++# ++# This file is free software; the Free Software Foundation ++# gives unlimited permission to copy and/or distribute it, ++# with or without modifications, as long as this notice is preserved. +  +-# serial 2 ++# serial 3 +  + # _AM_MANGLE_OPTION(NAME) + # ----------------------- +@@ -847,28 +701,16 @@ AC_DEFUN([_AM_SET_OPTIONS], + AC_DEFUN([_AM_IF_OPTION], + [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) +  +-# +-# Check to make sure that the build environment is sane. +-# +- +-# Copyright (C) 1996, 1997, 2000, 2001, 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, or (at your option) +-# any later version. ++# Check to make sure that the build environment is sane.    -*- Autoconf -*- +  +-# 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. ++# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005 ++# Free Software Foundation, Inc. ++# ++# This file is free software; the Free Software Foundation ++# gives unlimited permission to copy and/or distribute it, ++# with or without modifications, as long as this notice is preserved. +  +-# serial 3 ++# serial 4 +  + # AM_SANITY_CHECK + # --------------- +@@ -911,25 +753,14 @@ Check your system clock]) + fi + AC_MSG_RESULT(yes)]) +  +-# AM_PROG_INSTALL_STRIP +- +-# Copyright (C) 2001, 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, 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. ++# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc. ++# ++# This file is free software; the Free Software Foundation ++# gives unlimited permission to copy and/or distribute it, ++# with or without modifications, as long as this notice is preserved. +  ++# AM_PROG_INSTALL_STRIP ++# --------------------- + # One issue with vendor `install' (even GNU) is that you can't + # specify the program used to strip binaries.  This is especially + # annoying in cross-compiling environments, where the build's strip +@@ -952,25 +783,13 @@ AC_SUBST([INSTALL_STRIP_PROGRAM])]) +  + # Check how to create a tarball.                            -*- Autoconf -*- +  +-# Copyright (C) 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, 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. +- +-# serial 1 ++# Copyright (C) 2004, 2005  Free Software Foundation, Inc. ++# ++# This file is free software; the Free Software Foundation ++# gives unlimited permission to copy and/or distribute it, ++# with or without modifications, as long as this notice is preserved. +  ++# serial 2 +  + # _AM_PROG_TAR(FORMAT) + # -------------------- +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,51 @@ ++2006-05-02  Pavel Roskin  <proski@gnu.org> ++ ++	* stage2/stage2.c (run_menu): Fix "savedefault" to save only top ++	level menu positions.  Remember current position when calling a ++	submenu.  Don't recalculate it when booting from a submenu. ++ ++	* grub/main.c (main): Make sure the boot drive number doesn't ++	exceed 255. ++ ++2006-05-02  Vesa Jaaskelainen  <chaac@nic.fi> ++ ++	* stage2/shared.h (vbe_mode): Back ported aligment fix from GRUB 2 ++	to GRUB Legacy.  Problem reported by Gerardo Richarte. ++ ++2006-04-23  Robert Millan  <robertmh@gnu.org> ++ ++	* grub/asmstub.c (get_diskinfo): Optimize sysctl routine. ++ ++2006-04-20  Robert Millan  <robertmh@gnu.org> ++ ++	Fixes for kernel of FreeBSD: ++	* grub/asmstub.c (get_diskinfo): Toggle "kern.geom.debugflags" sysctl ++	before opening a device for writing. ++	* util/grub-install.in: Devices don't have this "r" prefix anymore. ++ ++2006-04-16  Yoshinori K. Okuji  <okuji@enbug.org> ++ ++	* docs/multiboot.texi: Correct the offset of address ++	fields. Reported by Jeroen Dekkers. ++ ++2006-03-21  Yoshinori K. Okuji  <okuji@enbug.org> ++ ++	* stage2/builtins.c (setup_func): Specify the size of DEVICE to ++	grub_strncat instead of a strange number 256. Reported by Vitaly ++	Fertman <vitaly@namesys.com>. ++ ++2005-09-29  Yoshinori K. Okuji  <okuji@enbug.org> ++ ++	* docs/multiboot.texi: Fix a bug in the byte order of ++	boot_device. I hope this won't affect any OS image. ++	Increased the version number to 0.6.94. ++ ++2005-09-28  Yoshinori K. Okuji  <okuji@enbug.org> ++ ++	* stage2/boot.c (load_image): Even if an OS image is an ELF ++	object, use the a.out kludge if MULTIBOOT_AOUT_KLUDGE is ++	specified. ++ + 2005-05-08  Yoshinori K. Okuji  <okuji@enbug.org> +  + 	* configure.ac (AC_INIT): Upgraded to 0.97. +--- a/configure ++++ b/configure +@@ -311,7 +311,7 @@ ac_includes_default="\ + # include <unistd.h> + #endif" +  +-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar build build_cpu build_vendor build_os host host_cpu host_vendor host_os MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT PERL CC ac_ct_CC CFLAGS LDFLAGS CPPFLAGS EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CCAS RANLIB ac_ct_RANLIB STAGE1_CFLAGS STAGE2_CFLAGS GRUB_CFLAGS OBJCOPY ac_ct_OBJCOPY GRUB_LIBS CPP EGREP NETBOOT_SUPPORT_TRUE NETBOOT_SUPPORT_FALSE DISKLESS_SUPPORT_TRUE DISKLESS_SUPPORT_FALSE HERCULES_SUPPORT_TRUE HERCULES_SUPPORT_FALSE SERIAL_SUPPORT_TRUE SERIAL_SUPPORT_FALSE SERIAL_SPEED_SIMULATION_TRUE SERIAL_SPEED_SIMULATION_FALSE BUILD_EXAMPLE_KERNEL_TRUE BUILD_EXAMPLE_KERNEL_FALSE FSYS_CFLAGS NET_CFLAGS NET_EXTRAFLAGS NETBOOT_DRIVERS CCASFLAGS LIBOBJS LTLIBOBJS' ++ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar build build_cpu build_vendor build_os host host_cpu host_vendor host_os MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT PERL CC ac_ct_CC CFLAGS LDFLAGS CPPFLAGS EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CCAS RANLIB ac_ct_RANLIB STAGE1_CFLAGS STAGE2_CFLAGS GRUB_CFLAGS OBJCOPY ac_ct_OBJCOPY GRUB_LIBS CPP EGREP NETBOOT_SUPPORT_TRUE NETBOOT_SUPPORT_FALSE DISKLESS_SUPPORT_TRUE DISKLESS_SUPPORT_FALSE GRAPHICS_SUPPORT_TRUE GRAPHICS_SUPPORT_FALSE HERCULES_SUPPORT_TRUE HERCULES_SUPPORT_FALSE SERIAL_SUPPORT_TRUE SERIAL_SUPPORT_FALSE SERIAL_SPEED_SIMULATION_TRUE SERIAL_SPEED_SIMULATION_FALSE BUILD_EXAMPLE_KERNEL_TRUE BUILD_EXAMPLE_KERNEL_FALSE FSYS_CFLAGS NET_CFLAGS NET_EXTRAFLAGS NETBOOT_DRIVERS CCASFLAGS LIBOBJS LTLIBOBJS' + ac_subst_files='' +  + # Initialize some variables set by options. +@@ -914,6 +914,7 @@ Optional Features: +                           set the default memory location for WD/SMC +   --enable-cs-scan=LIST   probe for CS89x0 base address using LIST +   --enable-diskless       enable diskless support ++  --disable-graphics      disable graphics terminal support +   --disable-hercules      disable hercules terminal support +   --disable-serial        disable serial terminal support +   --enable-serial-speed-simulation +@@ -5966,6 +5967,22 @@ else + fi +  +  ++# Check whether --enable-graphics or --disable-graphics was given. ++if test "${enable_graphics+set}" = set; then ++  enableval="$enable_graphics" ++ ++fi; ++ ++ ++if test "x$enable_graphics" != xno; then ++  GRAPHICS_SUPPORT_TRUE= ++  GRAPHICS_SUPPORT_FALSE='#' ++else ++  GRAPHICS_SUPPORT_TRUE='#' ++  GRAPHICS_SUPPORT_FALSE= ++fi ++ ++ + # Check whether --enable-hercules or --disable-hercules was given. + if test "${enable_hercules+set}" = set; then +   enableval="$enable_hercules" +@@ -6270,6 +6287,13 @@ echo "$as_me: error: conditional \"DISKL + Usually this means the macro was only invoked conditionally." >&2;} +    { (exit 1); exit 1; }; } + fi ++if test -z "${GRAPHICS_SUPPORT_TRUE}" && test -z "${GRAPHICS_SUPPORT_FALSE}"; then ++  { { echo "$as_me:$LINENO: error: conditional \"GRAPHICS_SUPPORT\" was never defined. ++Usually this means the macro was only invoked conditionally." >&5 ++echo "$as_me: error: conditional \"GRAPHICS_SUPPORT\" was never defined. ++Usually this means the macro was only invoked conditionally." >&2;} ++   { (exit 1); exit 1; }; } ++fi + if test -z "${HERCULES_SUPPORT_TRUE}" && test -z "${HERCULES_SUPPORT_FALSE}"; then +   { { echo "$as_me:$LINENO: error: conditional \"HERCULES_SUPPORT\" was never defined. + Usually this means the macro was only invoked conditionally." >&5 +@@ -6907,6 +6931,8 @@ s,@NETBOOT_SUPPORT_TRUE@,$NETBOOT_SUPPOR + s,@NETBOOT_SUPPORT_FALSE@,$NETBOOT_SUPPORT_FALSE,;t t + s,@DISKLESS_SUPPORT_TRUE@,$DISKLESS_SUPPORT_TRUE,;t t + s,@DISKLESS_SUPPORT_FALSE@,$DISKLESS_SUPPORT_FALSE,;t t ++s,@GRAPHICS_SUPPORT_TRUE@,$GRAPHICS_SUPPORT_TRUE,;t t ++s,@GRAPHICS_SUPPORT_FALSE@,$GRAPHICS_SUPPORT_FALSE,;t t + s,@HERCULES_SUPPORT_TRUE@,$HERCULES_SUPPORT_TRUE,;t t + s,@HERCULES_SUPPORT_FALSE@,$HERCULES_SUPPORT_FALSE,;t t + s,@SERIAL_SUPPORT_TRUE@,$SERIAL_SUPPORT_TRUE,;t t +--- a/configure.ac ++++ b/configure.ac +@@ -595,6 +595,11 @@ AC_ARG_ENABLE(diskless, +   [  --enable-diskless       enable diskless support]) + AM_CONDITIONAL(DISKLESS_SUPPORT, test "x$enable_diskless" = xyes) +  ++dnl Graphical splashscreen support ++AC_ARG_ENABLE(graphics, ++  [  --disable-graphics      disable graphics terminal support]) ++AM_CONDITIONAL(GRAPHICS_SUPPORT, test "x$enable_graphics" != xno) ++ + dnl Hercules terminal + AC_ARG_ENABLE(hercules, +   [  --disable-hercules      disable hercules terminal support]) +--- a/docs/grub.8 ++++ b/docs/grub.8 +@@ -1,5 +1,5 @@ + .\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.23. +-.TH GRUB "8" "May 2005" "grub (GNU GRUB 0.97)" FSF ++.TH GRUB "8" "September 2005" "grub (GNU GRUB 0.97)" FSF + .SH NAME + grub \- the grub shell + .SH SYNOPSIS +--- a/docs/grub.texi ++++ b/docs/grub.texi +@@ -2199,6 +2199,7 @@ Commands usable anywhere in the menu and + * rarp::                        Initialize a network device via RARP + * serial::                      Set up a serial device + * setkey::                      Configure the key map ++* splashimage::                 Use a splash image + * terminal::                    Choose a terminal + * terminfo::                    Define escape sequences for a terminal + * tftpserver::                  Specify a TFTP server +@@ -2578,6 +2579,16 @@ character each of the symbols correspond + @end deffn +  +  ++@node splashimage ++@subsection splashimage ++ ++@deffn Command splashimage file ++Select an image to use as the background image.  This should be ++specified using normal GRUB device naming syntax.  The format of the ++file is a gzipped xpm which is 640x480 with a 14 color palette. ++@end deffn ++ ++ + @node terminal + @subsection terminal +  +@@ -2685,6 +2696,7 @@ you forget a command, you can run the co + * module::                      Load a module + * modulenounzip::               Load a module without decompression + * pause::                       Wait for a key press ++* print::                       Print a message + * quit::                        Exit from the grub shell + * reboot::                      Reboot your computer + * read::                        Read data from memory +@@ -3091,6 +3103,16 @@ change floppies. + @end deffn +  +  ++@node print ++@subsection print ++ ++@deffn Command print message @dots{} ++Print the @var{message}. Note that placing @key{^G} (ASCII code 7) in the ++message will cause the speaker to emit the standard beep sound, which is ++useful for visually impaired people. ++@end deffn ++ ++ + @node quit + @subsection quit +  +--- a/docs/multiboot.texi ++++ b/docs/multiboot.texi +@@ -25,7 +25,7 @@ + @ifinfo + Copyright @copyright{} 1995, 96 Bryan Ford <baford@@cs.utah.edu> + Copyright @copyright{} 1995, 96 Erich Stefan Boleyn <erich@@uruk.org> +-Copyright @copyright{} 1999, 2000, 2001, 2002 Free Software Foundation, Inc. ++Copyright @copyright{} 1999, 2000, 2001, 2002, 2005, 2006 Free Software Foundation, Inc. +  + Permission is granted to make and distribute verbatim copies of + this manual provided the copyright notice and this permission notice +@@ -57,7 +57,7 @@ into another language, under the above c + @vskip 0pt plus 1filll + Copyright @copyright{} 1995, 96 Bryan Ford <baford@@cs.utah.edu> + Copyright @copyright{} 1995, 96 Erich Stefan Boleyn <erich@@uruk.org> +-Copyright @copyright{} 1999, 2000, 2001, 2002 Free Software Foundation, Inc. ++Copyright @copyright{} 1999, 2000, 2001, 2002, 2005, 2006 Free Software Foundation, Inc. +  + Permission is granted to make and distribute verbatim copies of + this manual provided the copyright notice and this permission notice +@@ -80,7 +80,7 @@ into another language, under the above c + @top Multiboot Specification +  + This file documents Multiboot Specification, the proposal for the boot +-sequence standard. This edition documents version 0.6.93. ++sequence standard. This edition documents version 0.6.94. + @end ifnottex +  + @menu +@@ -426,7 +426,7 @@ mode table (@pxref{Boot information form + kernel. +  + If bit 16 in the @samp{flags} word is set, then the fields at offsets +-8-24 in the Multiboot header are valid, and the boot loader should use ++12-28 in the Multiboot header are valid, and the boot loader should use + them instead of the fields in the actual executable header to calculate + where to load the OS image. This information does not need to be + provided if the kernel image is in @sc{elf} format, but it @emph{must} +@@ -677,7 +677,7 @@ follows: + @example + @group + +-------+-------+-------+-------+ +-| drive | part1 | part2 | part3 | ++| part3 | part2 | part1 | drive | + +-------+-------+-------+-------+ + @end group + @end example +@@ -1199,6 +1199,13 @@ The maintainer changes to the GNU GRUB m + @email{bug-grub@@gnu.org}, from Bryan Ford and Erich Stefan Boleyn. + @end itemize +  ++@item ++The byte order of the @samp{boot_device} in Multiboot information is ++reversed. This was a mistake. ++ ++@item ++The offset of the address fields were wrong. ++ + @item 0.6 + @itemize @bullet + @item +--- a/grub/asmstub.c ++++ b/grub/asmstub.c +@@ -42,6 +42,12 @@ int grub_stage2 (void); + #include <sys/time.h> + #include <termios.h> + #include <signal.h> ++#include <sys/mman.h> ++ ++#include <limits.h> ++#ifndef PAGESIZE ++#define PAGESIZE 4096 ++#endif +  + #ifdef __linux__ + # include <sys/ioctl.h>		/* ioctl */ +@@ -55,6 +61,10 @@ int grub_stage2 (void); + # endif /* ! BLKFLSBUF */ + #endif /* __linux__ */ +  ++#if defined(__FreeBSD_kernel__) || defined(__FreeBSD__) ++# include <sys/sysctl.h> ++#endif ++ + /* We want to prevent any circularararity in our stubs, as well as +    libc name clashes. */ + #define WITHOUT_LIBC_STUBS 1 +@@ -144,6 +154,22 @@ grub_stage2 (void) +   assert (grub_scratch_mem == 0); +   scratch = malloc (0x100000 + EXTENDED_MEMSIZE + 15); +   assert (scratch); ++ ++  { ++    char *p; ++    int ret; ++ ++    /* Align to a multiple of PAGESIZE, assumed to be a power of two. */ ++    p = (char *) (((long) scratch) & ~(PAGESIZE - 1)); ++ ++    /* The simulated stack needs to be executable, since GCC uses stack ++     * trampolines to implement nested functions. ++     */ ++    ret = mprotect (p, 0x100000 + EXTENDED_MEMSIZE + 15, ++		    PROT_READ | PROT_WRITE | PROT_EXEC); ++    assert (ret == 0); ++  } ++ +   grub_scratch_mem = (char *) ((((int) scratch) >> 4) << 4); +  +   /* FIXME: simulate the memory holes using mprot, if available. */ +@@ -777,7 +803,39 @@ get_diskinfo (int drive, struct geometry +  +       /* Open read/write, or read-only if that failed. */ +       if (! read_only) +-	disks[drive].flags = open (devname, O_RDWR); ++	{ ++/* By default, kernel of FreeBSD does not allow overwriting MBR */ ++#if defined(__FreeBSD_kernel__) || defined(__FreeBSD__) ++#define GEOM_SYSCTL	"kern.geom.debugflags" ++	  int old_flags, flags; ++	  size_t sizeof_int = sizeof (int); ++ ++	  if (sysctlbyname (GEOM_SYSCTL, &old_flags, &sizeof_int, NULL, 0) != 0) ++	    grub_printf ("failed to get " GEOM_SYSCTL "sysctl: %s\n", strerror (errno)); ++ ++	  if ((old_flags & 0x10) == 0) ++	    { ++	      /* "allow foot shooting", see geom(4) */ ++	      flags = old_flags | 0x10; ++ ++	      if (sysctlbyname (GEOM_SYSCTL, NULL, NULL, &flags, sizeof (int)) != 0) ++		{ ++		  flags = old_flags; ++		  grub_printf ("failed to set " GEOM_SYSCTL "sysctl: %s\n", strerror (errno)); ++		} ++	    } ++	  else ++	    flags = old_flags; ++#endif ++	  disks[drive].flags = open (devname, O_RDWR); ++#if defined(__FreeBSD_kernel__) || defined(__FreeBSD__) ++	  if (flags != old_flags) ++	    { ++	      if (sysctlbyname (GEOM_SYSCTL, NULL, NULL, &old_flags, sizeof (int)) != 0) ++	        grub_printf ("failed to set " GEOM_SYSCTL "sysctl: %s\n", strerror (errno)); ++	    } ++#endif ++	} +  +       if (disks[drive].flags == -1) + 	{ +--- a/grub/main.c ++++ b/grub/main.c +@@ -32,6 +32,7 @@ int grub_stage2 (void); + #define WITHOUT_LIBC_STUBS 1 + #include <shared.h> + #include <term.h> ++#include <device.h> +  + char *program_name = 0; + int use_config_file = 1; +@@ -192,6 +193,12 @@ main (int argc, char **argv) + 	      perror ("strtoul"); + 	      exit (1); + 	    } ++	  if (boot_drive >= NUM_DISKS) ++	    { ++	      fprintf (stderr, "boot_drive should be from 0 to %d\n", ++		       NUM_DISKS - 1); ++	      exit (1); ++	    } + 	  break; +  + 	case OPT_NO_CONFIG_FILE: +--- a/lib/device.c ++++ b/lib/device.c +@@ -131,6 +131,152 @@ get_kfreebsd_version () + #include <shared.h> + #include <device.h> +  ++#if defined(__linux__) ++/* The 2.6 kernel has removed all of the geometry handling for IDE drives ++ * that did fixups for LBA, etc.  This means that the geometry we get ++ * with the ioctl has a good chance of being wrong.  So, we get to  ++ * also know about partition tables and try to read what the geometry ++ * is there. *grumble*   Very closely based on code from cfdisk ++ */ ++static void get_kernel_geometry(int fd, long long *cyl, int *heads, int *sectors) { ++    struct hd_geometry hdg; ++     ++    if (ioctl (fd, HDIO_GETGEO, &hdg)) ++        return; ++ ++    *cyl = hdg.cylinders; ++    *heads = hdg.heads; ++    *sectors = hdg.sectors; ++} ++ ++struct partition { ++        unsigned char boot_ind;         /* 0x80 - active */ ++        unsigned char head;             /* starting head */ ++        unsigned char sector;           /* starting sector */ ++        unsigned char cyl;              /* starting cylinder */ ++        unsigned char sys_ind;          /* What partition type */ ++        unsigned char end_head;         /* end head */ ++        unsigned char end_sector;       /* end sector */ ++        unsigned char end_cyl;          /* end cylinder */ ++        unsigned char start4[4];        /* starting sector counting from 0 */ ++        unsigned char size4[4];         /* nr of sectors in partition */ ++}; ++ ++#define ALIGNMENT 2 ++typedef union { ++    struct { ++	unsigned char align[ALIGNMENT]; ++	unsigned char b[SECTOR_SIZE]; ++    } c; ++    struct { ++	unsigned char align[ALIGNMENT]; ++	unsigned char buffer[0x1BE]; ++	struct partition part[4]; ++	unsigned char magicflag[2]; ++    } p; ++} partition_table; ++ ++#define PART_TABLE_FLAG0 0x55 ++#define PART_TABLE_FLAG1 0xAA ++ ++static void ++get_partition_table_geometry(partition_table *bufp, long long *cyl, int *heads,  ++                             int *sectors) { ++    struct partition *p; ++    int i,h,s,hh,ss; ++    int first = 1; ++    int bad = 0; ++ ++    if (bufp->p.magicflag[0] != PART_TABLE_FLAG0 || ++	bufp->p.magicflag[1] != PART_TABLE_FLAG1) { ++	    /* Matthew Wilcox: slightly friendlier version of ++	       fatal(_("Bad signature on partition table"), 3); ++	    */ ++            fprintf(stderr, "Unknown partition table signature\n"); ++	    return; ++    } ++ ++    hh = ss = 0; ++    for (i=0; i<4; i++) { ++	p = &(bufp->p.part[i]); ++	if (p->sys_ind != 0) { ++	    h = p->end_head + 1; ++	    s = (p->end_sector & 077); ++	    if (first) { ++		hh = h; ++		ss = s; ++		first = 0; ++	    } else if (hh != h || ss != s) ++		bad = 1; ++	} ++    } ++ ++    if (!first && !bad) { ++	*heads = hh; ++	*sectors = ss; ++    } ++} ++ ++static long long my_lseek (unsigned int fd, long long offset,  ++                           unsigned int origin) ++{ ++#if defined(__linux__) && (!defined(__GLIBC__) || \ ++        ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1)))) ++  /* Maybe libc doesn't have large file support.  */ ++  loff_t offset, result; ++  static int _llseek (uint filedes, ulong hi, ulong lo, ++                      loff_t *res, uint wh); ++  _syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo, ++             loff_t *, res, uint, wh); ++   ++  if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET) < 0) ++    return (long long) -1; ++  return result; ++#else ++  return lseek(fd, offset, SEEK_SET); ++#endif ++} ++ ++static void get_linux_geometry (int fd, struct geometry *geom) { ++    long long kern_cyl = 0; int kern_head = 0, kern_sectors = 0; ++    long long pt_cyl = 0; int pt_head = 0, pt_sectors = 0; ++    partition_table bufp; ++    char *buff, *buf_unaligned; ++ ++    buf_unaligned = malloc(sizeof(partition_table) + 4095); ++    buff = (char *) (((unsigned long)buf_unaligned + 4096 - 1) & ++                     (~(4096-1))); ++ ++    get_kernel_geometry(fd, &kern_cyl, &kern_head, &kern_sectors); ++ ++    if (my_lseek (fd, 0*SECTOR_SIZE, SEEK_SET) < 0) { ++        fprintf(stderr, "Unable to seek"); ++    } ++ ++    if (read(fd, buff, SECTOR_SIZE) == SECTOR_SIZE) { ++        memcpy(bufp.c.b, buff, SECTOR_SIZE); ++        get_partition_table_geometry(&bufp, &pt_cyl, &pt_head, &pt_sectors); ++    } else { ++        fprintf(stderr, "Unable to read partition table: %s\n", strerror(errno)); ++    } ++ ++    if (pt_head && pt_sectors) { ++        int cyl_size; ++ ++        geom->heads = pt_head; ++        geom->sectors = pt_sectors; ++        cyl_size = pt_head * pt_sectors; ++        geom->cylinders = geom->total_sectors/cyl_size; ++    } else { ++        geom->heads = kern_head; ++        geom->sectors = kern_sectors; ++        geom->cylinders = kern_cyl; ++    } ++ ++    return; ++} ++#endif ++ + /* Get the geometry of a drive DRIVE.  */ + void + get_drive_geometry (struct geometry *geom, char **map, int drive) +@@ -151,21 +297,16 @@ get_drive_geometry (struct geometry *geo + #if defined(__linux__) +   /* Linux */ +   { +-    struct hd_geometry hdg; +     unsigned long nr; +-     +-    if (ioctl (fd, HDIO_GETGEO, &hdg)) +-      goto fail; +  +     if (ioctl (fd, BLKGETSIZE, &nr)) +       goto fail; +      +     /* Got the geometry, so save it. */ +-    geom->cylinders = hdg.cylinders; +-    geom->heads = hdg.heads; +-    geom->sectors = hdg.sectors; +     geom->total_sectors = nr; +-     ++    get_linux_geometry(fd, geom); ++    if (!geom->heads && !geom->cylinders && !geom->sectors) ++        goto fail; +     goto success; +   } +  +@@ -403,6 +544,18 @@ get_dac960_disk_name (char *name, int co + } +  + static void ++get_cciss_disk_name (char *name, int controller, int drive) ++{ ++  sprintf (name, "/dev/cciss/c%dd%d", controller, drive); ++} ++ ++static void ++get_ida_disk_name (char *name, int controller, int drive) ++{ ++  sprintf (name, "/dev/ida/c%dd%d", controller, drive); ++} ++ ++static void + get_ataraid_disk_name (char *name, int unit) + { +   sprintf (name, "/dev/ataraid/d%c", unit + '0'); +@@ -801,6 +954,74 @@ init_device_map (char ***map, const char + 	  } +       } +   } ++ ++  /* This is for CCISS, its like the DAC960  - we have ++     /dev/cciss/<controller>d<logical drive>p<partition>  ++ ++     It currently supports up to 3 controllers, 10 logical volumes ++     and 10 partitions ++ ++     Code gratuitously copied from DAC960 above. ++     Horms <horms@verge.net.au> 23rd July 2004 ++  */ ++  { ++    int controller, drive; ++     ++    for (controller = 0; controller < 2; controller++) ++      { ++	for (drive = 0; drive < 9; drive++) ++	  { ++	    char name[24]; ++	     ++	    get_cciss_disk_name (name, controller, drive); ++	    if (check_device (name)) ++	      { ++		(*map)[num_hd + 0x80] = strdup (name); ++		assert ((*map)[num_hd + 0x80]); ++		 ++		/* If the device map file is opened, write the map.  */ ++		if (fp) ++		  fprintf (fp, "(hd%d)\t%s\n", num_hd, name); ++		 ++		num_hd++; ++	      } ++	  } ++      } ++  } ++ ++  /* This is for Compaq Smart Array, its like the DAC960  - we have ++     /dev/ida/<controller>d<logical drive>p<partition>  ++ ++     It currently supports up to 3 controllers, 10 logical volumes ++     and 15 partitions ++ ++     Code gratuitously copied from DAC960 above. ++     Piotr Roszatycki <dexter@debian.org> ++  */ ++  { ++    int controller, drive; ++     ++    for (controller = 0; controller < 2; controller++) ++      { ++	for (drive = 0; drive < 9; drive++) ++	  { ++	    char name[24]; ++	     ++	    get_ida_disk_name (name, controller, drive); ++	    if (check_device (name)) ++	      { ++		(*map)[num_hd + 0x80] = strdup (name); ++		assert ((*map)[num_hd + 0x80]); ++		 ++		/* If the device map file is opened, write the map.  */ ++		if (fp) ++		  fprintf (fp, "(hd%d)\t%s\n", num_hd, name); ++		 ++		num_hd++; ++	      } ++	  } ++      } ++  } + #endif /* __linux__ */ +    +   /* OK, close the device map file if opened.  */ +@@ -844,6 +1065,7 @@ write_to_partition (char **map, int driv + { +   char dev[PATH_MAX];	/* XXX */ +   int fd; ++  off_t offset = (off_t) sector * (off_t) SECTOR_SIZE; +    +   if ((partition & 0x00FF00) != 0x00FF00) +     { +@@ -861,8 +1083,14 @@ write_to_partition (char **map, int driv +       if (strcmp (dev + strlen(dev) - 5, "/disc") == 0) + 	strcpy (dev + strlen(dev) - 5, "/part"); +     } +-  sprintf (dev + strlen(dev), "%d", ((partition >> 16) & 0xFF) + 1); +-   ++  sprintf (dev + strlen(dev), "%s%d",  ++   /* Compaq smart and others */ ++   (strncmp(dev, "/dev/ida/", 9) == 0 || ++   strncmp(dev, "/dev/ataraid/", 13) == 0 || ++   strncmp(dev, "/dev/cciss/", 11) == 0 || ++   strncmp(dev, "/dev/rd/", 8) == 0) ? "p" : "", ++   ((partition >> 16) & 0xFF) + 1); ++ +   /* Open the partition.  */ +   fd = open (dev, O_RDWR); +   if (fd < 0) +@@ -870,35 +1098,13 @@ write_to_partition (char **map, int driv +       errnum = ERR_NO_PART; +       return 0; +     } +-   +-#if defined(__linux__) && (!defined(__GLIBC__) || \ +-        ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1)))) +-  /* Maybe libc doesn't have large file support.  */ +-  { +-    loff_t offset, result; +-    static int _llseek (uint filedes, ulong hi, ulong lo, +-                        loff_t *res, uint wh); +-    _syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo, +-               loff_t *, res, uint, wh); +  +-    offset = (loff_t) sector * (loff_t) SECTOR_SIZE; +-    if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET)) +-      { +-	errnum = ERR_DEV_VALUES; +-	return 0; +-      } +-  } +-#else +-  { +-    off_t offset = (off_t) sector * (off_t) SECTOR_SIZE; +  +-    if (lseek (fd, offset, SEEK_SET) != offset) +-      { +-	errnum = ERR_DEV_VALUES; +-	return 0; +-      } +-  } +-#endif ++  if (my_lseek(fd, offset, SEEK_SET) != offset) ++    { ++      errnum = ERR_DEV_VALUES; ++      return 0; ++    } +    +   if (write (fd, buf, size * SECTOR_SIZE) != (size * SECTOR_SIZE)) +     { +--- a/stage2/asm.S ++++ b/stage2/asm.S +@@ -1651,7 +1651,29 @@ ENTRY(gateA20) + 	jnz	3f + 	ret +  +-3:	/* use keyboard controller */ ++3:	/* ++	 * try to switch gateA20 using PORT92, the "Fast A20 and Init" ++	 * register ++	*/ ++	mov $0x92, %dx ++	inb %dx, %al ++	/* skip the port92 code if it's unimplemented (read returns 0xff) */ ++	cmpb $0xff, %al ++	jz 6f ++	 ++	/* set or clear bit1, the ALT_A20_GATE bit */ ++	movb 4(%esp), %ah ++	testb %ah, %ah ++	jz 4f ++	orb $2, %al ++	jmp 5f ++4:	and $0xfd, %al ++	 ++	/* clear the INIT_NOW bit don't accidently reset the machine */ ++5:	and $0xfe, %al ++	outb %al, %dx ++	 ++6:	/* use keyboard controller */ + 	pushl	%eax +  + 	call    gloop1 +@@ -1661,9 +1683,12 @@ ENTRY(gateA20) +  + gloopint1: + 	inb	$K_STATUS ++	cmpb	$0xff, %al ++	jz	gloopint1_done + 	andb	$K_IBUF_FUL, %al + 	jnz	gloopint1 +  ++gloopint1_done:	 + 	movb	$KB_OUTPUT_MASK, %al + 	cmpb	$0, 0x8(%esp) + 	jz	gdoit +@@ -1684,6 +1709,8 @@ gdoit: +  + gloop1: + 	inb	$K_STATUS ++	cmpb	$0xff, %al ++	jz	gloop2ret + 	andb	$K_IBUF_FUL, %al + 	jnz	gloop1 +  +@@ -1991,6 +2018,11 @@ ENTRY(ascii_key_map) + ENTRY(console_getkey) + 	push	%ebp +  ++wait_for_key: ++	call	EXT_C(console_checkkey) ++	incl	%eax ++	jz	wait_for_key ++	 + 	call	EXT_C(prot_to_real) + 	.code16 +  +@@ -2216,7 +2248,304 @@ ENTRY(console_setcursor) + 	pop	%ebx + 	pop	%ebp + 	ret +-		 ++ ++ ++/* graphics mode functions */ ++#ifdef SUPPORT_GRAPHICS ++VARIABLE(cursorX) ++.word	0 ++VARIABLE(cursorY) ++.word	0 ++VARIABLE(cursorCount) ++.word 0 ++VARIABLE(cursorBuf) ++.byte	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ++ ++ ++/* ++ * set_int1c_handler(void) ++ */ ++ENTRY(set_int1c_handler) ++	pushl   %edi ++ ++	/* save the original int1c handler */ ++	movl    $0x70, %edi ++	movw    (%edi), %ax ++	movw    %ax, ABS(int1c_offset) ++	movw    2(%edi), %ax ++	movw    %ax, ABS(int1c_segment) ++ ++	/* save the new int1c handler */ ++	movw    $ABS(int1c_handler), %ax ++	movw    %ax, (%edi) ++	xorw    %ax, %ax ++	movw    %ax, 2(%edi) ++ ++	popl    %edi ++	ret ++ ++ ++/* ++ * unset_int1c_handler(void) ++ */ ++ENTRY(unset_int1c_handler) ++	pushl   %edi ++ ++	/* check if int1c_handler is set */ ++	movl    $0x70, %edi ++	movw    $ABS(int1c_handler), %ax ++	cmpw    %ax, (%edi) ++	jne     int1c_1 ++	xorw    %ax, %ax ++	cmpw    %ax, 2(%edi) ++	jne     int1c_1 ++ ++	/* restore the original */ ++	movw    ABS(int1c_offset), %ax ++	movw    %ax, (%edi) ++	movw    ABS(int1c_segment), %ax ++	movw    %ax, 2(%edi) ++ ++int1c_1: ++	popl    %edi ++	ret ++ ++ ++/* ++ * blinks graphics cursor ++ */ ++	.code16 ++write_data: ++	movw    $0, %ax ++	movw    %ax, %ds ++ ++	mov     $0xA000, %ax            /* video in es:di */ ++	mov     %ax, %es ++	mov     $80, %ax ++	movw    $ABS(cursorY), %si ++	mov     %ds:(%si), %bx ++	mul     %bx ++	movw    $ABS(cursorX), %si ++	mov     %ds:(%si), %bx ++	shr     $3, %bx                 /* %bx /= 8 */ ++	add     %bx, %ax ++	mov     %ax, %di ++ ++	movw    $ABS(cursorBuf), %si    /* fontBuf in ds:si */ ++ ++	/* prepare for data moving */ ++	mov     $16, %dx                /* altura da fonte */ ++	mov     $80, %bx                /* bytes por linha */ ++ ++write_loop: ++	movb    %ds:(%si), %al ++	xorb    $0xff, %al ++	movb    %al, %ds:(%si)          /* invert cursorBuf */ ++	movb    %al, %es:(%di)          /* write to video */ ++	add     %bx, %di ++	inc     %si ++	dec     %dx ++	jg      write_loop ++	ret ++ ++int1c_handler: ++	pusha ++	mov     $0, %ax ++	mov     %ax, %ds ++	mov     $ABS(cursorCount), %si ++	mov     %ds:(%si), %ax ++	inc     %ax ++	mov     %ax, %ds:(%si) ++	cmp     $9, %ax ++	jne     int1c_done ++ ++	mov     $0, %ax ++	mov     %ax, %ds:(%si) ++	call    write_data ++ ++int1c_done: ++	popa ++	iret ++	/* call previous int1c handler */ ++	/* ljmp */ ++	.byte   0xea ++int1c_offset:  .word   0 ++int1c_segment: .word   0 ++	.code32 ++ ++ ++/* ++ * unsigned char set_videomode(unsigned char mode) ++ * BIOS call "INT 10H Function 0h" to set video mode ++ *	Call with	%ah = 0x0 ++ *			%al = video mode ++ *  Returns old videomode. ++ */ ++ENTRY(set_videomode) ++	pushl	%ebp ++	movl	%esp,%ebp ++	pushl	%ebx ++	pushl	%ecx ++ ++	movb	8(%ebp), %cl ++ ++	call	EXT_C(prot_to_real) ++	.code16 ++ ++	xorb	%al, %al ++	movb	$0xf, %ah ++	int	$0x10			/* Get Current Video mode */ ++	movb	%al, %ch ++	xorb	%ah, %ah ++	movb	%cl, %al ++	int	$0x10			/* Set Video mode */ ++ ++	DATA32	call	EXT_C(real_to_prot) ++	.code32 ++ ++	xorl	%eax, %eax ++	movb	%ch, %al ++ ++	popl	%ecx ++	popl	%ebx ++	popl	%ebp ++	ret ++ ++ ++/* ++ * int get_videomode() ++ * BIOS call "INT 10H Function 0Fh" to get current video mode ++ *	Call with	%al = 0x0 ++ *			%ah = 0xF ++ *	Returns current videomode. ++ */ ++ENTRY(get_videomode) ++	pushl	%ebp ++	movl	%esp,%ebp ++	pushl	%ebx ++	pushl	%ecx ++ ++	call	EXT_C(prot_to_real) ++	.code16 ++ ++	xorb	%al, %al ++	movb	$0xF, %ah ++	int	$0x10			/* Get Current Video mode */ ++	movb	%al, %cl	/* For now we only want display mode */ ++ ++	DATA32	call	EXT_C(real_to_prot) ++	.code32 ++ ++	xorl	%eax, %eax ++	movb	%cl, %al ++ ++	popl	%ecx ++	popl	%ebx ++	popl	%ebp ++	ret ++ ++ ++/* ++ * unsigned char * graphics_get_font() ++ * BIOS call "INT 10H Function 11h" to set font ++ *      Call with       %ah = 0x11 ++ */ ++ENTRY(graphics_get_font) ++	push	%ebp ++	push	%ebx ++	push	%ecx ++	push	%edx ++ ++	call	EXT_C(prot_to_real) ++	.code16 ++ ++	movw	$0x1130, %ax ++	movb	$6, %bh		/* font 8x16 */ ++	int	$0x10 ++	movw	%bp, %dx ++	movw	%es, %cx ++ ++	DATA32	call	EXT_C(real_to_prot) ++	.code32 ++ ++	xorl	%eax, %eax ++	movw	%cx, %ax ++	shll	$4, %eax ++	movw	%dx, %ax ++ ++	pop	%edx ++	pop	%ecx ++	pop	%ebx ++	pop	%ebp ++	ret ++ ++ ++/* ++ * graphics_set_palette(index, red, green, blue) ++ * BIOS call "INT 10H Function 10h" to set individual dac register ++ *	Call with	%ah = 0x10 ++ *			%bx = register number ++ *			%ch = new value for green (0-63) ++ *			%cl = new value for blue (0-63) ++ *			%dh = new value for red (0-63) ++ */ ++ ++ENTRY(graphics_set_palette) ++	push	%ebp ++	push	%eax ++	push	%ebx ++	push	%ecx ++	push	%edx ++ ++	movw	$0x3c8, %bx		/* address write mode register */ ++ ++	/* wait vertical retrace */ ++	movw	$0x3da, %dx ++l1b: ++	inb	%dx, %al	/* wait vertical active display */ ++	test	$8, %al ++	jnz	l1b ++ ++l2b: ++	inb	%dx, %al	/* wait vertical retrace */ ++	test	$8, %al ++	jnz	l2b ++ ++	mov	%bx, %dx ++	movb	0x18(%esp), %al		/* index */ ++	outb	%al, %dx ++	inc	%dx ++ ++	movb	0x1c(%esp), %al		/* red */ ++	outb	%al, %dx ++ ++	movb	0x20(%esp), %al		/* green */ ++	outb	%al, %dx ++ ++	movb	0x24(%esp), %al		/* blue */ ++	outb	%al, %dx ++ ++	movw	0x18(%esp), %bx ++ ++	call	EXT_C(prot_to_real) ++	.code16 ++ ++	movb	%bl, %bh ++	movw	$0x1000, %ax ++	int	$0x10 ++ ++	DATA32	call	EXT_C(real_to_prot) ++	.code32 ++ ++	pop	%edx ++	pop	%ecx ++	pop	%ebx ++	pop	%eax ++	pop	%ebp ++	ret ++#endif /* SUPPORT_GRAPHICS */ ++ ++ + /* +  * getrtsecs() +  *	if a seconds value can be read, read it and return it (BCD), +--- a/stage2/boot.c ++++ b/stage2/boot.c +@@ -1,7 +1,7 @@ + /* boot.c - load and bootstrap a kernel */ + /* +  *  GRUB  --  GRand Unified Bootloader +- *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc. ++ *  Copyright (C) 1999,2000,2001,2002,2003,2004,2005  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 +@@ -29,6 +29,8 @@ static int cur_addr; + entry_func entry_addr; + static struct mod_list mll[99]; + static int linux_mem_size; ++static int elf_kernel_addr; ++static int elf_kernel_size; +  + /* +  *  The next two functions, 'load_image' and 'load_module', are the building +@@ -96,7 +98,7 @@ load_image (char *kernel, char *arg, ker +   lh = (struct linux_kernel_header *) buffer; +    +   /* ELF loading supported if multiboot, FreeBSD and NetBSD.  */ +-  if ((type == KERNEL_TYPE_MULTIBOOT ++  if (((type == KERNEL_TYPE_MULTIBOOT && ! (flags & MULTIBOOT_AOUT_KLUDGE)) +        || pu.elf->e_ident[EI_OSABI] == ELFOSABI_FREEBSD +        || grub_strcmp (pu.elf->e_ident + EI_BRAND, "FreeBSD") == 0 +        || suggested_type == KERNEL_TYPE_NETBSD) +@@ -594,6 +596,7 @@ load_image (char *kernel, char *arg, ker +  +       /* reset this to zero for now */ +       cur_addr = 0; ++      elf_kernel_addr = ~0; +  +       /* scan for program segments */ +       for (i = 0; i < pu.elf->e_phnum; i++) +@@ -630,6 +633,8 @@ load_image (char *kernel, char *arg, ker + 	      /* mark memory as used */ + 	      if (cur_addr < memaddr + memsiz) + 		cur_addr = memaddr + memsiz; ++	      if (elf_kernel_addr > cur_addr) ++		elf_kernel_addr = cur_addr; + 	      printf (", <0x%x:0x%x:0x%x>", memaddr, filesiz, + 		      memsiz - filesiz); + 	      /* increment number of segments */ +@@ -647,6 +652,8 @@ load_image (char *kernel, char *arg, ker + 	    } + 	} +  ++      elf_kernel_size = cur_addr - elf_kernel_addr; ++ +       if (! errnum) + 	{ + 	  if (! loaded) +@@ -824,8 +831,11 @@ load_initrd (char *initrd) +     moveto = (mbi.mem_upper + 0x400) << 10; +    +   moveto = (moveto - len) & 0xfffff000; +-  max_addr = (lh->header == LINUX_MAGIC_SIGNATURE && lh->version >= 0x0203 +-	      ? lh->initrd_addr_max : LINUX_INITRD_MAX_ADDRESS); ++  max_addr = LINUX_INITRD_MAX_ADDRESS; ++  if (lh->header == LINUX_MAGIC_SIGNATURE && ++      lh->version >= 0x0203 && ++      lh->initrd_addr_max < max_addr) ++    max_addr = lh->initrd_addr_max; +   if (moveto + len >= max_addr) +     moveto = (max_addr - len) & 0xfffff000; +    +@@ -864,6 +874,129 @@ bsd_boot_entry (int flags, int bootdev,  + } + #endif +  ++#define mem_align4k(p)	((p) + 0xFFF) & 0xFFFFF000 ++ ++static void ++kfreebsd_setenv (char *env, const char *var, const char *value) ++{ ++  while (1) ++    { ++      if (env[0] == '\0' && env[1] == '\0') ++	{ ++	  env++; ++	  break; ++	} ++      else ++        env++; ++    } ++ ++  grub_sprintf (env, "%s=%s", var, value); ++  env[grub_strlen (env) + 1] = '\0'; ++} ++ ++static char * ++kfreebsd_read_hints (char *buf) ++{ ++  char *buf_end = buf; ++ ++  if (grub_open ("/boot/device.hints")) ++    { ++      char *line_start; ++      int line_len = 0; ++      char *envp; ++      int env_len; ++ ++      env_len = grub_read (buf, -1); ++      if (env_len) ++	{ ++	  buf_end += env_len; ++	  *(buf_end++) = '\0'; ++	} ++      else ++	return buf_end; ++ ++      grub_close (); ++ ++      envp = line_start = buf; ++      while (*envp) ++	{ ++	  char *envp_current = envp; ++	 ++	  switch (*envp) ++	    { ++	      case ' ': ++		while (*envp == ' ') ++		  { ++		    envp++; ++		    env_len--; ++		  } ++		grub_memmove (envp_current, envp, env_len + 1); ++		envp = envp_current; ++		break; ++	      case '#': ++		while (*envp != '\n') ++		  { ++		    envp++; ++		    env_len--; ++		  } ++		if (!line_len) ++		  envp++; ++		grub_memmove (envp_current, envp, env_len + 1); ++		envp = envp_current; ++		break; ++	      case '\n': ++		if (!line_len) ++		  { ++		    env_len--; ++		    grub_memmove (line_start, envp, env_len + 1); ++		  } ++		*(envp++) = '\0'; ++		line_len = 0; ++		line_start = envp; ++	      default: ++		envp++; ++		line_len++; ++		break; ++	    } ++	} ++ ++      buf_end = buf + env_len; ++      *(buf_end++) = '\0'; ++    } ++ ++  return buf_end; ++} ++ ++static u32_t * ++kfreebsd_set_module_string (u32_t type, u32_t *dst, char *src) ++{ ++  int size; ++ ++  *(dst++) = type; ++  *(dst++) = size = grub_strlen (src) + 1; ++  grub_strcpy ((void *) dst, src); ++ ++  return dst + (size + sizeof(u32_t) - 1) / sizeof(u32_t); ++} ++ ++static u32_t * ++kfreebsd_set_module_var (u32_t type, u32_t *dst, u32_t src) ++{ ++  *(dst++) = type; ++  *(dst++) = sizeof(u32_t); ++  *(dst++) = src; ++ ++  return dst; ++} ++ ++static u32_t * ++kfreebsd_set_modules (u32_t *modulep) ++{ ++  /* XXX: Need to copy the whole module structure.  */ ++  /* XXX: How to pass the module name ?  */ ++ ++  return modulep; ++} +  + /* +  *  All "*_boot" commands depend on the images being loaded into memory +@@ -877,7 +1010,10 @@ void + bsd_boot (kernel_t type, int bootdev, char *arg) + { +   char *str; +-  int clval = 0, i; ++  char *kernelname; ++  char *bsd_root; ++  int clval = 0; ++  int i; +   struct bootinfo bi; +  + #ifdef GRUB_UTIL +@@ -886,8 +1022,21 @@ bsd_boot (kernel_t type, int bootdev, ch +   stop_floppy (); + #endif +  ++  while (*arg != '/') ++    arg++; ++  kernelname = arg; ++ +   while (*(++arg) && *arg != ' '); ++  *(arg++) = 0; +   str = arg; ++ ++  bsd_root = grub_strstr (str, "root="); ++  if (bsd_root) ++    { ++      bsd_root += 5; ++      /* XXX: should copy the str or terminate it.  */ ++    } ++ +   while (*str) +     { +       if (*str == '-') +@@ -910,6 +1059,8 @@ bsd_boot (kernel_t type, int bootdev, ch + 		clval |= RB_GDB; + 	      if (*str == 'h') + 		clval |= RB_SERIAL; ++	      if (*str == 'p') ++		clval |= RB_PAUSE; + 	      if (*str == 'm') + 		clval |= RB_MUTE; + 	      if (*str == 'r') +@@ -927,14 +1078,17 @@ bsd_boot (kernel_t type, int bootdev, ch +  +   if (type == KERNEL_TYPE_FREEBSD) +     { ++      char *envp; ++      u32_t *modp; ++ +       clval |= RB_BOOTINFO; +  +       bi.bi_version = BOOTINFO_VERSION; +  +-      *arg = 0; +-      while ((--arg) > (char *) MB_CMDLINE_BUF && *arg != '/'); +-      if (*arg == '/') +-	bi.bi_kernelname = arg + 1; ++      bi.bi_pad[0] = bi.bi_pad[1] = 0; ++ ++      if (*kernelname == '/') ++	bi.bi_kernelname = kernelname; +       else + 	bi.bi_kernelname = 0; +  +@@ -961,6 +1115,30 @@ bsd_boot (kernel_t type, int bootdev, ch +       bi.bi_basemem = mbi.mem_lower; +       bi.bi_extmem = extended_memory; +  ++      /* Setup the environment.  */ ++      bi.bi_envp = cur_addr = mem_align4k (cur_addr); ++      grub_memset ((void *) cur_addr, 0, 2); ++      cur_addr = (int) kfreebsd_read_hints ((void *) cur_addr); ++ ++      envp = (char *) bi.bi_envp; ++      kfreebsd_setenv (envp, "kernelname", kernelname); ++      kfreebsd_setenv (envp, "vfs.root.mountfrom", bsd_root); ++ ++      /* Setup the modules list.  */ ++      bi.bi_modulep = cur_addr = mem_align4k (cur_addr); ++      modp = (u32_t *) bi.bi_modulep; ++      /* The first module is the kernel.  */ ++      modp = kfreebsd_set_module_string (MODINFO_NAME, modp, kernelname); ++      modp = kfreebsd_set_module_string (MODINFO_TYPE, modp, "elf kernel"); ++      modp = kfreebsd_set_module_string (MODINFO_ARGS, modp, arg); ++      modp = kfreebsd_set_module_var (MODINFO_ADDR, modp, elf_kernel_addr); ++      modp = kfreebsd_set_module_var (MODINFO_SIZE, modp, elf_kernel_size); ++      /* Now the real modules.  */ ++      modp = kfreebsd_set_modules(modp); ++ ++      /* Set the kernel end.  */ ++      bi.bi_kernend = cur_addr = mem_align4k (((int) modp) + 1); ++ +       if (mbi.flags & MB_INFO_AOUT_SYMS) + 	{ + 	  bi.bi_symtab = mbi.syms.a.addr; +@@ -970,8 +1148,9 @@ bsd_boot (kernel_t type, int bootdev, ch + #if 0 +       else if (mbi.flags & MB_INFO_ELF_SHDR) + 	{ +-	  /* FIXME: Should check if a symbol table exists and, if exists, +-	     pass the table to BI.  */ ++	  bi.bi_symtab = mbi.syms.e.addr; ++	  bi.bi_esymtab = mbi.syms.e.addr ++	    + mbi.syms.e.size * mbi.syms.e.num * mbi.syms.e.shndx; + 	} + #endif +       else +--- a/stage2/builtins.c ++++ b/stage2/builtins.c +@@ -28,6 +28,10 @@ + #include <filesys.h> + #include <term.h> +  ++#ifdef SUPPORT_GRAPHICS ++# include <graphics.h> ++#endif ++ + #ifdef SUPPORT_NETBOOT + # define GRUB	1 + # include <etherboot.h> +@@ -82,6 +86,10 @@ static unsigned short bios_drive_map[DRI +    inside other functions.  */ + static int configfile_func (char *arg, int flags); +  ++static int savedefault_helper (char *arg, int flags); ++ ++static int savedefault_shell (char *arg, int flags); ++ + /* Initialize the data for builtins.  */ + void + init_builtins (void) +@@ -237,12 +245,22 @@ static struct builtin builtin_blocklist  + static int + boot_func (char *arg, int flags) + { ++  struct term_entry *prev_term = current_term; +   /* 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 (); +  ++  /* if our terminal needed initialization, we should shut it down ++   * before booting the kernel, but we want to save what it was so ++   * we can come back if needed */ ++  if (current_term->shutdown)  ++    { ++      current_term->shutdown(); ++      current_term = term_table; /* assumption: console is first */ ++    } ++ + #ifdef SUPPORT_NETBOOT +   /* Shut down the networking.  */ +   cleanup_net (); +@@ -306,6 +324,13 @@ boot_func (char *arg, int flags) +       return 1; +     } +  ++  /* if we get back here, we should go back to what our term was before */ ++  current_term = prev_term; ++  if (current_term->startup) ++      /* if our terminal fails to initialize, fall back to console since ++       * it should always work */ ++      if (current_term->startup() == 0) ++          current_term = term_table; /* we know that console is first */ +   return 0; + } +  +@@ -852,6 +877,251 @@ static struct builtin builtin_dhcp = + }; + #endif /* SUPPORT_NETBOOT */ +  ++#ifdef SUPPORT_GRAPHICS ++ ++static int splashimage_func(char *arg, int flags) { ++  int i; ++     ++  /* filename can only be 256 characters due to our buffer size */ ++  if (grub_strlen(arg) > 256) { ++    grub_printf("Splash image filename too large\n"); ++    grub_printf("Press any key to continue..."); ++    getkey(); ++    return 1; ++  } ++ ++  /* get rid of TERM_NEED_INIT from the graphics terminal. */ ++  for (i = 0; term_table[i].name; i++) { ++    if (grub_strcmp (term_table[i].name, "graphics") == 0) { ++      term_table[i].flags &= ~TERM_NEED_INIT; ++      break; ++    } ++  } ++ ++  graphics_set_splash(arg); ++ ++  if (flags == BUILTIN_CMDLINE && graphics_inited) { ++    graphics_end(); ++    if (graphics_init() == 0) { ++      /* Fallback to default term */ ++      current_term = term_table; ++      max_lines = current_term->max_lines; ++      if (current_term->cls) ++        current_term->cls(); ++      grub_printf("Failed to set splash image and/or graphics mode\n"); ++      return 1; ++    } ++    graphics_cls(); ++  } ++ ++  if (flags == BUILTIN_MENU) ++    current_term = term_table + i; ++ ++  return 0; ++} ++ ++static struct builtin builtin_splashimage = ++{ ++  "splashimage", ++  splashimage_func, ++  BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, ++  "splashimage FILE", ++  "Load FILE as the background image when in graphics mode." ++}; ++ ++ ++/* shade */ ++static int ++shade_func(char *arg, int flags) ++{ ++    int new_shade; ++ ++    if (!arg || safe_parse_maxint(&arg, &new_shade) == 0) ++       return (1); ++ ++    if (shade != new_shade) { ++       shade = new_shade; ++       if (flags == BUILTIN_CMDLINE && graphics_inited) { ++           graphics_end(); ++           graphics_init(); ++           graphics_cls(); ++       } ++    } ++ ++    return 0; ++} ++ ++static struct builtin builtin_shade = ++{ ++  "shade", ++  shade_func, ++  BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, ++  "shade INTEGER", ++  "If set to 0, disables the use of shaded text, else enables it." ++}; ++ ++ ++/* foreground */ ++static int ++foreground_func(char *arg, int flags) ++{ ++    if (grub_strlen(arg) == 6) { ++	int r = ((hex(arg[0]) << 4) | hex(arg[1])) >> 2; ++	int g = ((hex(arg[2]) << 4) | hex(arg[3])) >> 2; ++	int b = ((hex(arg[4]) << 4) | hex(arg[5])) >> 2; ++ ++	foreground = (r << 16) | (g << 8) | b; ++	if (graphics_inited) ++	    graphics_set_palette(15, r, g, b); ++ ++	return 0; ++    } ++ ++    return 1; ++} ++ ++static struct builtin builtin_foreground = ++{ ++  "foreground", ++  foreground_func, ++  BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, ++  "foreground RRGGBB", ++  "Sets the foreground color when in graphics mode." ++  "RR is red, GG is green, and BB blue. Numbers must be in hexadecimal." ++}; ++ ++ ++/* background */ ++static int ++background_func(char *arg, int flags) ++{ ++    if (grub_strlen(arg) == 6) { ++	int r = ((hex(arg[0]) << 4) | hex(arg[1])) >> 2; ++	int g = ((hex(arg[2]) << 4) | hex(arg[3])) >> 2; ++	int b = ((hex(arg[4]) << 4) | hex(arg[5])) >> 2; ++ ++	background = (r << 16) | (g << 8) | b; ++	if (graphics_inited) ++	    graphics_set_palette(0, r, g, b); ++	return 0; ++    } ++ ++    return 1; ++} ++ ++static struct builtin builtin_background = ++{ ++  "background", ++  background_func, ++  BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, ++  "background RRGGBB", ++  "Sets the background color when in graphics mode." ++  "RR is red, GG is green, and BB blue. Numbers must be in hexadecimal." ++}; ++ ++ ++/* border */ ++static int ++border_func(char *arg, int flags) ++{ ++    if (grub_strlen(arg) == 6) { ++       int r = ((hex(arg[0]) << 4) | hex(arg[1])) >> 2; ++       int g = ((hex(arg[2]) << 4) | hex(arg[3])) >> 2; ++       int b = ((hex(arg[4]) << 4) | hex(arg[5])) >> 2; ++ ++       window_border = (r << 16) | (g << 8) | b; ++       if (graphics_inited) ++           graphics_set_palette(0x11, r, g, b); ++ ++       return 0; ++    } ++ ++    return 1; ++} ++ ++static struct builtin builtin_border = ++{ ++  "border", ++  border_func, ++  BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, ++  "border RRGGBB", ++  "Sets the border video color when in graphics mode." ++  "RR is red, GG is green, and BB blue. Numbers must be in hexadecimal." ++}; ++ ++ ++/* viewport */ ++static int ++viewport_func (char *arg, int flags) ++{ ++    int i; ++    int x0 = 0, y0 = 0, x1 = 80, y1 = 30; ++    int *pos[4] = { &x0, &y0, &x1, &y1 }; ++ ++    if (!arg) ++       return (1); ++    for (i = 0; i < 4; i++) { ++       if (!*arg) ++           return (1); ++    while (*arg && (*arg == ' ' || *arg == '\t')) ++           ++arg; ++       if (!safe_parse_maxint(&arg, pos[i])) ++           return (1); ++       while (*arg && (*arg != ' ' && *arg != '\t')) ++           ++arg; ++    } ++ ++    /* minimum size is 65 colums and 16 rows */ ++    if (x0 > x1 - 66 || y0 > y1 - 16 || x0 < 0 || y0 < 0 || x1 > 80 || y1 > 30) ++       return 1; ++ ++    view_x0 = x0; ++    view_y0 = y0; ++    view_x1 = x1; ++    view_y1 = y1; ++ ++    if (flags == BUILTIN_CMDLINE && graphics_inited) { ++       graphics_end(); ++       graphics_init(); ++       graphics_cls(); ++    } ++ ++    return 0; ++} ++ ++static struct builtin builtin_viewport = ++{ ++  "viewport", ++  viewport_func, ++  BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, ++  "viewport x0 y0 x1 y1", ++  "Changes grub internals to output text in the window defined by" ++  " four parameters. The x and y parameters are 0 based. This option" ++  " only works with the graphics interface." ++}; ++ ++#endif /* SUPPORT_GRAPHICS */ ++ ++ ++/* clear */ ++static int  ++clear_func()  ++{ ++  if (current_term->cls) ++    current_term->cls(); ++ ++  return 0; ++} ++ ++static struct builtin builtin_clear = ++{ ++  "clear", ++  clear_func, ++  BUILTIN_CMDLINE | BUILTIN_HELP_LIST, ++  "clear", ++  "Clear the screen" ++}; ++ +  + /* displayapm */ + static int +@@ -1454,14 +1724,20 @@ static struct builtin builtin_halt = +  +  + /* help */ +-#define MAX_SHORT_DOC_LEN	39 +-#define MAX_LONG_DOC_LEN	66 +- + static int + help_func (char *arg, int flags) + { +-  int all = 0; +-   ++  int all = 0, max_short_doc_len, max_long_doc_len; ++  max_short_doc_len = 39; ++  max_long_doc_len = 66; ++#ifdef SUPPORT_GRAPHICS ++  if (grub_memcmp (current_term->name, "graphics", sizeof ("graphics") - 1) == 0) ++    { ++      max_short_doc_len = (view_x1 - view_x0 + 1) / 2 - 1; ++      max_long_doc_len = (view_x1 - view_x0) - 14; ++    } ++#endif ++ +   if (grub_memcmp (arg, "--all", sizeof ("--all") - 1) == 0) +     { +       all = 1; +@@ -1491,13 +1767,13 @@ help_func (char *arg, int flags) +  + 	  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; ++	  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++) ++	  for (; i < max_short_doc_len; i++) + 	    grub_putchar (' '); +  + 	  if (! left) +@@ -1546,10 +1822,10 @@ help_func (char *arg, int flags) + 		      int i; +  + 		      /* If LEN is too long, fold DOC.  */ +-		      if (len > MAX_LONG_DOC_LEN) ++		      if (len > max_long_doc_len) + 			{ + 			  /* Fold this line at the position of a space.  */ +-			  for (len = MAX_LONG_DOC_LEN; len > 0; len--) ++			  for (len = max_long_doc_len; len > 0; len--) + 			    if (doc[len - 1] == ' ') + 			      break; + 			} +@@ -2323,6 +2599,25 @@ static struct builtin builtin_ioprobe = +   "Probe I/O ports used for the drive DRIVE." + }; +  ++/* print */ ++static int ++print_func (char *arg, int flags) ++{ ++  printf("%s\n", arg); ++ ++  return 0; ++} ++ ++static struct builtin builtin_print = ++{ ++  "print", ++  print_func, ++  BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_NO_ECHO, ++  "print [MESSAGE ...]", ++  "Print MESSAGE." ++}; ++ ++ +  + /* kernel */ + static int +@@ -3221,7 +3516,102 @@ static struct builtin builtin_rootnoveri + static int + savedefault_func (char *arg, int flags) + { +-#if !defined(SUPPORT_DISKLESS) && !defined(GRUB_UTIL) ++#if !defined(SUPPORT_DISKLESS) ++  #if !defined(GRUB_UTIL) ++	savedefault_helper(arg, flags); ++  #else ++	savedefault_shell(arg, flags); ++  #endif ++#else /* !SUPPORT_DISKLESS */  ++  errnum = ERR_UNRECOGNIZED; ++  return 1; ++#endif /* !SUPPORT_DISKLESS */ ++} ++ ++#if !defined(SUPPORT_DISKLESS) && defined(GRUB_UTIL) ++/* savedefault_shell */ ++static int ++savedefault_shell(char *arg, int flags) ++ { ++  int once_only = 0; ++  int new_default; ++  int curr_default = -1; ++  int curr_prev_default = -1; ++  int new_prev_default = -1; ++  FILE *fp; ++  size_t bytes = 10; ++  char line[bytes]; ++  char *default_file = (char *) DEFAULT_FILE_BUF; ++  char buf[bytes]; ++  int i; ++   ++  while (1) ++    { ++      if (grub_memcmp ("--default=", arg, sizeof ("--default=") - 1) == 0) ++        { ++          char *p = arg + sizeof ("--default=") - 1; ++          if (! safe_parse_maxint (&p, &new_default)) ++            return 1; ++          arg = skip_to (0, arg); ++        } ++      else if (grub_memcmp ("--once", arg, sizeof ("--once") - 1) == 0) ++        { ++         once_only = 1; ++         arg = skip_to (0, arg); ++	} ++      else ++        break; ++    } ++ ++  *default_file = 0; ++  grub_strncat (default_file, config_file, DEFAULT_FILE_BUFLEN); ++  for (i = grub_strlen(default_file); i >= 0; i--) ++    if (default_file[i] == '/') ++    { ++      i++; ++      break; ++    } ++  default_file[i] = 0; ++  grub_strncat (default_file + i, "default", DEFAULT_FILE_BUFLEN - i); ++ ++  if(!(fp = fopen(default_file,"w"))) ++    { ++      errnum = ERR_READ; ++      goto fail; ++    } ++   ++  read(&line, -1); ++     ++  sscanf(line, "%d:%d", &curr_prev_default, &curr_default); ++      ++  if(curr_default != -1) ++    new_prev_default = curr_default; ++  else ++    { ++      if(curr_prev_default != -1) ++        new_prev_default = curr_prev_default; ++      else ++        new_prev_default = 0; ++    } ++      ++  if(once_only) ++    sprintf(buf, "%d:%d\n", new_prev_default, new_default); ++  else ++    sprintf(buf, "%d\n", new_default); ++      ++  fprintf(fp, buf);    ++      ++fail: ++  fclose(fp); ++  return errnum; ++} ++#endif ++ ++/* savedefault_helper */ ++static int ++savedefault_helper (char *arg, int flags) ++{ ++#if !defined(SUPPORT_DISKLESS) +   unsigned long tmp_drive = saved_drive; +   unsigned long tmp_partition = saved_partition; +   char *default_file = (char *) DEFAULT_FILE_BUF; +@@ -3300,19 +3690,23 @@ savedefault_func (char *arg, int flags) +       disk_read_hook = 0; +       grub_close (); +        +-      if (len != sizeof (buf)) +-	{ +-	  /* This is too small. Do not modify the file manually, please!  */ +-	  errnum = ERR_READ; +-	  goto fail; +-	} +- +       if (sector_count > 2) + 	{ + 	  /* Is this possible?! Too fragmented!  */ + 	  errnum = ERR_FSYS_CORRUPT; + 	  goto fail; + 	} ++ ++      char *tmp; ++      if((tmp = grub_strstr(buf, ":")) != NULL) ++      { ++       int f_len = grub_strlen(buf) - grub_strlen(tmp); ++       char *def; ++       int a; ++       for(a = 0; a < f_len; a++) ++         grub_memcpy(&def[a], &buf[a], sizeof(char)); ++       safe_parse_maxint (&def, &entryno); ++      } +        +       /* Set up a string to be written.  */ +       grub_memset (buf, '\n', sizeof (buf)); +@@ -3830,15 +4224,15 @@ setup_func (char *arg, int flags) + 	{ + 	  char tmp[16]; + 	  grub_sprintf (tmp, ",%d", (partition >> 16) & 0xFF); +-	  grub_strncat (device, tmp, 256); ++	  grub_strncat (device, tmp, sizeof (device)); + 	} +       if ((partition & 0x00FF00) != 0x00FF00) + 	{ + 	  char tmp[16]; + 	  grub_sprintf (tmp, ",%c", 'a' + ((partition >> 8) & 0xFF)); +-	  grub_strncat (device, tmp, 256); ++	  grub_strncat (device, tmp, sizeof (device)); + 	} +-      grub_strncat (device, ")", 256); ++      grub_strncat (device, ")", sizeof (device)); +     } +    +   int embed_stage1_5 (char *stage1_5, int drive, int partition) +@@ -4085,7 +4479,7 @@ static struct builtin builtin_setup = + }; +  +  +-#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) ++#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) || defined(SUPPORT_GRAPHICS) + /* terminal */ + static int + terminal_func (char *arg, int flags) +@@ -4244,17 +4638,29 @@ terminal_func (char *arg, int flags) +  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; +-   ++    max_lines = current_term->max_lines; ++ +   /* If the interface is currently the command-line, +      restart it to repaint the screen.  */ +-  if (current_term != prev_term && (flags & BUILTIN_CMDLINE)) ++  if ((current_term != prev_term) && (flags & BUILTIN_CMDLINE)){ ++    if (prev_term->shutdown) ++      prev_term->shutdown(); ++    if (current_term->startup) { ++      /* If startup fails, return to previous term */ ++      if (current_term->startup() == 0) { ++        current_term = prev_term; ++        max_lines = current_term->max_lines; ++        if (current_term->cls) { ++          current_term->cls(); ++        } ++      } ++    } +     grub_longjmp (restart_cmdline_env, 0); ++  } +    +   return 0; + } +@@ -4264,7 +4670,7 @@ 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]", ++  "terminal [--dumb] [--no-echo] [--no-edit] [--timeout=SECS] [--lines=LINES] [--silent] [console] [serial] [hercules] [graphics]", +   "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" +@@ -4276,7 +4682,7 @@ static struct builtin builtin_terminal = +   " seconds. The option --lines specifies the maximum number of lines." +   " The option --silent is used to suppress messages." + }; +-#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES */ ++#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES || SUPPORT_GRAPHICS */ +  +  + #ifdef SUPPORT_SERIAL +@@ -4795,13 +5201,20 @@ static struct builtin builtin_vbeprobe = + /* The table of builtin commands. Sorted in dictionary order.  */ + struct builtin *builtin_table[] = + { ++#ifdef SUPPORT_GRAPHICS ++  &builtin_background, ++#endif +   &builtin_blocklist, +   &builtin_boot, + #ifdef SUPPORT_NETBOOT +   &builtin_bootp, + #endif /* SUPPORT_NETBOOT */ ++#ifdef SUPPORT_GRAPHICS ++  &builtin_border, ++#endif +   &builtin_cat, +   &builtin_chainloader, ++  &builtin_clear, +   &builtin_cmp, +   &builtin_color, +   &builtin_configfile, +@@ -4821,6 +5234,9 @@ struct builtin *builtin_table[] = +   &builtin_embed, +   &builtin_fallback, +   &builtin_find, ++#ifdef SUPPORT_GRAPHICS ++  &builtin_foreground, ++#endif +   &builtin_fstest, +   &builtin_geometry, +   &builtin_halt, +@@ -4848,6 +5264,7 @@ struct builtin *builtin_table[] = +   &builtin_parttype, +   &builtin_password, +   &builtin_pause, ++  &builtin_print, + #ifdef GRUB_UTIL +   &builtin_quit, + #endif /* GRUB_UTIL */ +@@ -4864,9 +5281,13 @@ struct builtin *builtin_table[] = + #endif /* SUPPORT_SERIAL */ +   &builtin_setkey, +   &builtin_setup, +-#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) ++#ifdef SUPPORT_GRAPHICS ++  &builtin_shade, ++  &builtin_splashimage, ++#endif /* SUPPORT_GRAPHICS */ ++#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) || defined(SUPPORT_GRAPHICS) +   &builtin_terminal, +-#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES */ ++#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES || SUPPORT_GRAPHICS */ + #ifdef SUPPORT_SERIAL +   &builtin_terminfo, + #endif /* SUPPORT_SERIAL */ +@@ -4880,5 +5301,8 @@ struct builtin *builtin_table[] = +   &builtin_unhide, +   &builtin_uppermem, +   &builtin_vbeprobe, ++#ifdef SUPPORT_GRAPHICS ++  &builtin_viewport, ++#endif +   0 + }; +--- a/stage2/char_io.c ++++ b/stage2/char_io.c +@@ -29,12 +29,17 @@ + # include <serial.h> + #endif +  ++#ifdef SUPPORT_GRAPHICS ++# include <graphics.h> ++#endif ++ + #ifndef STAGE1_5 + struct term_entry term_table[] = +   { +     { +       "console", +       0, ++      24, +       console_putchar, +       console_checkkey, +       console_getkey, +@@ -43,13 +48,16 @@ struct term_entry term_table[] = +       console_cls, +       console_setcolorstate, +       console_setcolor, +-      console_setcursor ++      console_setcursor, ++      0,  ++      0 +     }, + #ifdef SUPPORT_SERIAL +     { +       "serial", +       /* A serial device must be initialized.  */ +       TERM_NEED_INIT, ++      24, +       serial_putchar, +       serial_checkkey, +       serial_getkey, +@@ -58,6 +66,8 @@ struct term_entry term_table[] = +       serial_cls, +       serial_setcolorstate, +       0, ++      0, ++      0,  +       0 +     }, + #endif /* SUPPORT_SERIAL */ +@@ -65,6 +75,7 @@ struct term_entry term_table[] = +     { +       "hercules", +       0, ++      24, +       hercules_putchar, +       console_checkkey, +       console_getkey, +@@ -73,11 +84,30 @@ struct term_entry term_table[] = +       hercules_cls, +       hercules_setcolorstate, +       hercules_setcolor, +-      hercules_setcursor ++      hercules_setcursor, ++      0, ++      0 +     },       + #endif /* SUPPORT_HERCULES */ ++#ifdef SUPPORT_GRAPHICS ++    { "graphics", ++      TERM_NEED_INIT, /* flags */ ++      30, /* number of lines */ ++      graphics_putchar, /* putchar */ ++      console_checkkey, /* checkkey */ ++      console_getkey, /* getkey */ ++      graphics_getxy, /* getxy */ ++      graphics_gotoxy, /* gotoxy */ ++      graphics_cls, /* cls */ ++      graphics_setcolorstate, /* setcolorstate */ ++      graphics_setcolor, /* setcolor */ ++      graphics_setcursor, /* nocursor */ ++      graphics_init, /* initialize */ ++      graphics_end /* shutdown */ ++    }, ++#endif /* SUPPORT_GRAPHICS */ +     /* This must be the last entry.  */ +-    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } ++    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } +   }; +  + /* This must be console.  */ +@@ -305,9 +335,10 @@ real_get_cmdline (char *prompt, char *cm +  +   /* XXX: These should be defined in shared.h, but I leave these here, +      until this code is freezed.  */ +-#define CMDLINE_WIDTH	78 + #define CMDLINE_MARGIN	10 +-   ++ ++  /* command-line limits */ ++  int cmdline_width = 78, col_start = 0; +   int xpos, lpos, c, section; +   /* The length of PROMPT.  */ +   int plen; +@@ -338,7 +369,7 @@ real_get_cmdline (char *prompt, char *cm +        +       /* If the cursor is in the first section, display the first section + 	 instead of the second.  */ +-      if (section == 1 && plen + lpos < CMDLINE_WIDTH) ++      if (section == 1 && plen + lpos < cmdline_width) + 	cl_refresh (1, 0); +       else if (xpos - count < 1) + 	cl_refresh (1, 0); +@@ -354,7 +385,7 @@ real_get_cmdline (char *prompt, char *cm + 		grub_putchar ('\b'); + 	    } + 	  else +-	    gotoxy (xpos, getxy () & 0xFF); ++	    gotoxy (xpos + col_start, getxy () & 0xFF); + 	} +     } +  +@@ -364,7 +395,7 @@ real_get_cmdline (char *prompt, char *cm +       lpos += count; +  +       /* If the cursor goes outside, scroll the screen to the right.  */ +-      if (xpos + count >= CMDLINE_WIDTH) ++      if (xpos + count >= cmdline_width) + 	cl_refresh (1, 0); +       else + 	{ +@@ -383,7 +414,7 @@ real_get_cmdline (char *prompt, char *cm + 		} + 	    } + 	  else +-	    gotoxy (xpos, getxy () & 0xFF); ++	    gotoxy (xpos + col_start, getxy () & 0xFF); + 	} +     } +  +@@ -398,14 +429,14 @@ real_get_cmdline (char *prompt, char *cm +       if (full) + 	{ + 	  /* Recompute the section number.  */ +-	  if (lpos + plen < CMDLINE_WIDTH) ++	  if (lpos + plen < cmdline_width) + 	    section = 0; + 	  else +-	    section = ((lpos + plen - CMDLINE_WIDTH) +-		       / (CMDLINE_WIDTH - 1 - CMDLINE_MARGIN) + 1); ++	    section = ((lpos + plen - cmdline_width) ++		       / (cmdline_width - 1 - CMDLINE_MARGIN) + 1); +  + 	  /* From the start to the end.  */ +-	  len = CMDLINE_WIDTH; ++	  len = cmdline_width; + 	  pos = 0; + 	  grub_putchar ('\r'); +  +@@ -445,8 +476,8 @@ real_get_cmdline (char *prompt, char *cm + 	  if (! full) + 	    offset = xpos - 1; + 	   +-	  start = ((section - 1) * (CMDLINE_WIDTH - 1 - CMDLINE_MARGIN) +-		   + CMDLINE_WIDTH - plen - CMDLINE_MARGIN); ++	  start = ((section - 1) * (cmdline_width - 1 - CMDLINE_MARGIN) ++		   + cmdline_width - plen - CMDLINE_MARGIN); + 	  xpos = lpos + 1 - start; + 	  start += offset; + 	} +@@ -471,7 +502,7 @@ real_get_cmdline (char *prompt, char *cm +        +       /* If the cursor is at the last position, put `>' or a space, + 	 depending on if there are more characters in BUF.  */ +-      if (pos == CMDLINE_WIDTH) ++      if (pos == cmdline_width) + 	{ + 	  if (start + len < llen) + 	    grub_putchar ('>'); +@@ -488,7 +519,7 @@ real_get_cmdline (char *prompt, char *cm + 	    grub_putchar ('\b'); + 	} +       else +-	gotoxy (xpos, getxy () & 0xFF); ++	gotoxy (xpos + col_start, getxy () & 0xFF); +     } +  +   /* Initialize the command-line.  */ +@@ -518,10 +549,10 @@ real_get_cmdline (char *prompt, char *cm + 	   + 	  llen += l; + 	  lpos += l; +-	  if (xpos + l >= CMDLINE_WIDTH) ++	  if (xpos + l >= cmdline_width) + 	    cl_refresh (1, 0); +-	  else if (xpos + l + llen - lpos > CMDLINE_WIDTH) +-	    cl_refresh (0, CMDLINE_WIDTH - xpos); ++	  else if (xpos + l + llen - lpos > cmdline_width) ++	    cl_refresh (0, cmdline_width - xpos); + 	  else + 	    cl_refresh (0, l + llen - lpos); + 	} +@@ -533,12 +564,22 @@ real_get_cmdline (char *prompt, char *cm +       grub_memmove (buf + lpos, buf + lpos + count, llen - count + 1); +       llen -= count; +        +-      if (xpos + llen + count - lpos > CMDLINE_WIDTH) +-	cl_refresh (0, CMDLINE_WIDTH - xpos); ++      if (xpos + llen + count - lpos > cmdline_width) ++	cl_refresh (0, cmdline_width - xpos); +       else + 	cl_refresh (0, llen + count - lpos); +     } +  ++  max_lines = current_term->max_lines; ++#ifdef SUPPORT_GRAPHICS ++  if (grub_memcmp (current_term->name, "graphics", sizeof ("graphics") - 1) == 0) ++    { ++      cmdline_width = (view_x1 - view_x0) - 2; ++      col_start = view_x0; ++      max_lines = view_y1 - view_y0; ++    } ++#endif ++ +   plen = grub_strlen (prompt); +   llen = grub_strlen (cmdline); +  +@@ -1006,6 +1047,48 @@ checkkey (void) + } + #endif /* ! STAGE1_5 */ +  ++#ifndef STAGE1_5 ++/* Internal pager.  */ ++int ++do_more (void) ++{ ++  if (count_lines >= 0) ++    { ++      count_lines++; ++      if (count_lines >= max_lines - 2) ++        { ++          int tmp; ++ ++          /* It's important to disable the feature temporarily, because ++             the following grub_printf call will print newlines.  */ ++          count_lines = -1; ++ ++          grub_printf("\n"); ++          if (current_term->setcolorstate) ++            current_term->setcolorstate (COLOR_STATE_HIGHLIGHT); ++ ++          grub_printf ("[Hit return to continue]"); ++ ++          if (current_term->setcolorstate) ++            current_term->setcolorstate (COLOR_STATE_NORMAL); ++ ++ ++          do ++            { ++              tmp = ASCII_CHAR (getkey ()); ++            } ++          while (tmp != '\n' && tmp != '\r'); ++          grub_printf ("\r                        \r"); ++ ++          /* Restart to count lines.  */ ++          count_lines = 0; ++          return 1; ++        } ++    } ++  return 0; ++} ++#endif ++ + /* Display an ASCII character.  */ + void + grub_putchar (int c) +@@ -1034,38 +1117,11 @@ grub_putchar (int c) +  +   if (c == '\n') +     { ++      int flag; +       /* Internal `more'-like feature.  */ +-      if (count_lines >= 0) +-	{ +-	  count_lines++; +-	  if (count_lines >= max_lines - 2) +-	    { +-	      int tmp; +-	       +-	      /* It's important to disable the feature temporarily, because +-		 the following grub_printf call will print newlines.  */ +-	      count_lines = -1; +- +-	      if (current_term->setcolorstate) +-		current_term->setcolorstate (COLOR_STATE_HIGHLIGHT); +-	       +-	      grub_printf ("\n[Hit return to continue]"); +- +-	      if (current_term->setcolorstate) +-		current_term->setcolorstate (COLOR_STATE_NORMAL); +-	       +-	      do +-		{ +-		  tmp = ASCII_CHAR (getkey ()); +-		} +-	      while (tmp != '\n' && tmp != '\r'); +-	      grub_printf ("\r                        \r"); +-	       +-	      /* Restart to count lines.  */ +-	      count_lines = 0; +-	      return; +-	    } +-	} ++      flag = do_more (); ++      if (flag) ++        return; +     } +  +   current_term->putchar (c); +@@ -1090,7 +1146,7 @@ void + cls (void) + { +   /* If the terminal is dumb, there is no way to clean the terminal.  */ +-  if (current_term->flags & TERM_DUMB) ++  if (current_term->flags & TERM_DUMB)  +     grub_putchar ('\n'); +   else +     current_term->cls (); +@@ -1175,13 +1231,13 @@ grub_strlen (const char *str) + #endif /* ! STAGE1_5 */ +  + int +-memcheck (int addr, int len) ++memcheck (unsigned long int addr, unsigned long int len) + { + #ifdef GRUB_UTIL +-  auto int start_addr (void); +-  auto int end_addr (void); ++  auto unsigned long int start_addr (void); ++  auto int unsigned long end_addr (void); +    +-  auto int start_addr (void) ++  auto unsigned long int start_addr (void) +     { +       int ret; + # if defined(HAVE_START_SYMBOL) +@@ -1192,7 +1248,7 @@ memcheck (int addr, int len) +       return ret; +     } +  +-  auto int end_addr (void) ++  auto unsigned long int end_addr (void) +     { +       int ret; + # if defined(HAVE_END_SYMBOL) +@@ -1217,6 +1273,16 @@ memcheck (int addr, int len) +   return ! errnum; + } +  ++void ++grub_memcpy(void *dest, const void *src, int len) ++{ ++  int i; ++  register char *d = (char*)dest, *s = (char*)src; ++ ++  for (i = 0; i < len; i++) ++    d[i] = s[i]; ++} ++ + void * + grub_memmove (void *to, const void *from, int len) + { +--- a/stage2/cmdline.c ++++ b/stage2/cmdline.c +@@ -50,10 +50,11 @@ skip_to (int after_equal, char *cmdline) + void + print_cmdline_message (int forever) + { +-  printf (" [ Minimal BASH-like line editing is supported.  For the first word, TAB\n" +-	  "   lists possible command completions.  Anywhere else TAB lists the possible\n" +-	  "   completions of a device/filename.%s ]\n", +-	  (forever ? "" : "  ESC at any time exits.")); ++  grub_printf("       [ Minimal BASH-like line editing is supported.   For\n" ++              "         the   first   word,  TAB  lists  possible  command\n" ++              "         completions.  Anywhere else TAB lists the possible\n" ++              "         completions of a device/filename.%s ]\n", ++              (forever ? "" : "  ESC at any time\n         exits.")); + } +  + /* Find the builtin whose command name is COMMAND and return the +--- a/stage2/freebsd.h ++++ b/stage2/freebsd.h +@@ -1,7 +1,7 @@ +  + /* +  *  GRUB  --  GRand Unified Bootloader +- *  Copyright (C) 2001  Free Software Foundation, Inc. ++ *  Copyright (C) 2001, 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 +@@ -35,6 +35,10 @@ + #define RB_CDROM        0x2000	/* use cdrom as root */ + #define RB_GDB		0x8000	/* use GDB remote debugger instead of DDB */ + #define RB_MUTE		0x10000	/* Come up with the console muted */ ++#define RB_SELFTEST	0x20000 /* don't complete the boot; do selftest */ ++#define RB_RESERVED1	0x40000 /* reserved for internal use of boot blocks */ ++#define RB_RESERVED2	0x80000 /* reserved for internal use of boot blocks */ ++#define RB_PAUSE	0x100000 /* pause after each output line during probe */ + #define RB_MULTIPLE	0x20000000	/* Use multiple consoles */ +  + #define RB_BOOTINFO     0x80000000	/* have `struct bootinfo *' arg */ +@@ -70,6 +74,9 @@ +  + #define N_BIOS_GEOM             8 +  ++typedef unsigned char u8_t; ++typedef unsigned int u32_t; ++ + /* +  * A zero bootinfo field often means that there is no info available. +  * Flags are used to indicate the validity of fields where zero is a +@@ -77,19 +84,33 @@ +  */ + struct bootinfo +   { +-    unsigned int bi_version; +-    unsigned char *bi_kernelname; +-    struct nfs_diskless *bi_nfs_diskless; ++    u32_t bi_version; ++    u8_t *bi_kernelname; ++    u32_t bi_nfs_diskless; +     /* End of fields that are always present. */ + #define bi_endcommon            bi_n_bios_used +-    unsigned int bi_n_bios_used; +-    unsigned long bi_bios_geom[N_BIOS_GEOM]; +-    unsigned int bi_size; +-    unsigned char bi_memsizes_valid; +-    unsigned char bi_bios_dev; +-    unsigned char bi_pad[2]; +-    unsigned long bi_basemem; +-    unsigned long bi_extmem; +-    unsigned long bi_symtab; +-    unsigned long bi_esymtab; ++    u32_t bi_n_bios_used; ++    u32_t bi_bios_geom[N_BIOS_GEOM]; ++    u32_t bi_size; ++    u8_t bi_memsizes_valid; ++    u8_t bi_bios_dev; ++    u8_t bi_pad[2]; ++    u32_t bi_basemem; ++    u32_t bi_extmem; ++    u32_t bi_symtab; ++    u32_t bi_esymtab; ++    /* Items below only from advanced bootloader */ ++    u32_t bi_kernend; ++    u32_t bi_envp; ++    u32_t bi_modulep; +   }; ++ ++#define MODINFO_END		0x0000		/* End of list */ ++#define MODINFO_NAME		0x0001		/* Name of module (string) */ ++#define MODINFO_TYPE		0x0002		/* Type of module (string) */ ++#define MODINFO_ADDR		0x0003		/* Loaded address */ ++#define MODINFO_SIZE		0x0004		/* Size of module */ ++#define MODINFO_EMPTY		0x0005		/* Has been deleted */ ++#define MODINFO_ARGS		0x0006		/* Parameters string */ ++#define MODINFO_METADATA	0x8000		/* Module-specfic */ ++ +--- /dev/null ++++ b/stage2/graphics.c +@@ -0,0 +1,585 @@ ++/* ++ * graphics.c - graphics mode support for GRUB ++ * Implemented as a terminal type by Jeremy Katz <katzj@redhat.com> based ++ * on a patch by Paulo César Pereira de Andrade <pcpa@conectiva.com.br> ++ * Options and enhancements made by Herton Ronaldo Krzesinski ++ * <herton@mandriva.com> ++ * ++ *  GRUB  --  GRand Unified Bootloader ++ *  Copyright (C) 2001,2002  Red Hat, Inc. ++ *  Portions copyright (C) 2000  Conectiva, 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. ++ */ ++ ++#ifdef SUPPORT_GRAPHICS ++ ++#include <term.h> ++#include <shared.h> ++#include <graphics.h> ++ ++int saved_videomode; ++unsigned char *font8x16; ++ ++int graphics_inited = 0; ++static char splashimage[256]; ++ ++int shade = 1, no_cursor = 0; ++ ++#define VSHADOW VSHADOW1 ++unsigned char VSHADOW1[38400]; ++unsigned char VSHADOW2[38400]; ++unsigned char VSHADOW4[38400]; ++unsigned char VSHADOW8[38400]; ++ ++/* define the default viewable area */ ++int view_x0 = 0; ++int view_y0 = 0; ++int view_x1 = 80; ++int view_y1 = 30; ++ ++/* text buffer has to be kept around so that we can write things as we ++ * scroll and the like */ ++unsigned short text[80 * 30]; ++ ++/* graphics options */ ++int foreground = (63 << 16) | (63 << 8) | (63), background = 0, window_border = 0; ++ ++/* current position */ ++static int fontx = 0; ++static int fonty = 0; ++ ++/* global state so that we don't try to recursively scroll or cursor */ ++static int no_scroll = 0; ++ ++/* color state */ ++static int graphics_standard_color = A_NORMAL; ++static int graphics_normal_color = A_NORMAL; ++static int graphics_highlight_color = A_REVERSE; ++static int graphics_current_color = A_NORMAL; ++static color_state graphics_color_state = COLOR_STATE_STANDARD; ++ ++static inline void outb(unsigned short port, unsigned char val) ++{ ++    __asm __volatile ("outb %0,%1"::"a" (val), "d" (port)); ++} ++ ++static void MapMask(int value) { ++    outb(0x3c4, 2); ++    outb(0x3c5, value); ++} ++ ++/* bit mask register */ ++static void BitMask(int value) { ++    outb(0x3ce, 8); ++    outb(0x3cf, value); ++} ++ ++/* move the graphics cursor location to col, row */ ++static void graphics_setxy(int col, int row) { ++    if (col >= view_x0 && col < view_x1) { ++        fontx = col; ++        cursorX = col << 3; ++    } ++    if (row >= view_y0 && row < view_y1) { ++        fonty = row; ++        cursorY = row << 4; ++    } ++} ++ ++/* scroll the screen */ ++static void graphics_scroll() { ++    int i, j, k; ++ ++    /* we don't want to scroll recursively... that would be bad */ ++    if (no_scroll) ++        return; ++    no_scroll = 1; ++ ++    /* disable pager temporarily */ ++    k = count_lines; ++    count_lines = -1; ++     ++    /* move everything up a line */ ++    for (j = view_y0 + 1; j < view_y1; j++) { ++        graphics_gotoxy(view_x0, j - 1); ++        for (i = view_x0; i < view_x1; i++) { ++            graphics_putchar(text[j * 80 + i]); ++        } ++    } ++ ++    /* last line should be blank */ ++    graphics_gotoxy(view_x0, view_y1 - 1); ++    for (i = view_x0; i < view_x1; i++) ++        graphics_putchar(' '); ++    graphics_setxy(view_x0, view_y1 - 1); ++ ++    count_lines = k; ++ ++    no_scroll = 0; ++} ++ ++/* Set the splash image */ ++void graphics_set_splash(char *splashfile) { ++    grub_strcpy(splashimage, splashfile); ++} ++ ++/* Get the current splash image */ ++char *graphics_get_splash(void) { ++    return splashimage; ++} ++ ++/*  ++ * Initialize a vga16 graphics display with the palette based off of ++ * the image in splashimage.  If the image doesn't exist, leave graphics ++ * mode. The mode initiated is 12h. From "Ralf Brown's Interrupt List": ++ *      text/ text pixel   pixel   colors disply scrn  system ++ *      grph resol  box  resolution       pages  addr ++ * 12h   G   80x30  8x16  640x480  16/256K  .    A000  VGA,ATI VIP ++ *       G   80x30  8x16  640x480  16/64    .    A000  ATI EGA Wonder ++ *       G     .     .    640x480  16       .      .   UltraVision+256K EGA ++ */ ++int graphics_init() ++{ ++    if (!graphics_inited) { ++        saved_videomode = set_videomode(0x12); ++        if (get_videomode() != 0x12) { ++            set_videomode(saved_videomode); ++            return 0; ++        } ++        graphics_inited = 1; ++    } ++    else ++        return 1; ++ ++    font8x16 = (unsigned char*)graphics_get_font(); ++ ++    /* make sure that the highlight color is set correctly */ ++    graphics_highlight_color = ((graphics_normal_color >> 4) |  ++                                ((graphics_normal_color & 0xf) << 4)); ++ ++    graphics_cls(); ++ ++    if (!read_image(splashimage)) { ++        grub_printf("Failed to read splash image (%s)\n", splashimage); ++        grub_printf("Press any key to continue..."); ++        getkey(); ++        set_videomode(saved_videomode); ++        graphics_inited = 0; ++        return 0; ++    } ++ ++    set_int1c_handler(); ++ ++    return 1; ++} ++ ++/* Leave graphics mode */ ++void graphics_end(void) ++{ ++    if (graphics_inited) { ++        unset_int1c_handler(); ++        set_videomode(saved_videomode); ++        graphics_inited = 0; ++        no_cursor = 0; ++    } ++} ++ ++/* Print ch on the screen.  Handle any needed scrolling or the like */ ++void graphics_putchar(int ch) { ++    ch &= 0xff; ++ ++    graphics_cursor(0); ++ ++    if (ch == '\n') { ++        if (fonty + 1 < view_y1) ++            graphics_setxy(fontx, fonty + 1); ++        else ++            graphics_scroll(); ++        graphics_cursor(1); ++        return; ++    } else if (ch == '\r') { ++        graphics_setxy(view_x0, fonty); ++        graphics_cursor(1); ++        return; ++    } ++ ++    graphics_cursor(0); ++ ++    text[fonty * 80 + fontx] = ch; ++    text[fonty * 80 + fontx] &= 0x00ff; ++    if (graphics_current_color & 0xf0) ++        text[fonty * 80 + fontx] |= 0x100; ++ ++    graphics_cursor(0); ++ ++    if ((fontx + 1) >= view_x1) { ++        graphics_setxy(view_x0, fonty); ++        if (fonty + 1 < view_y1) ++            graphics_setxy(view_x0, fonty + 1); ++        else ++            graphics_scroll(); ++        graphics_cursor(1); ++        do_more (); ++        graphics_cursor(0); ++    } else { ++        graphics_setxy(fontx + 1, fonty); ++    } ++ ++    graphics_cursor(1); ++} ++ ++/* get the current location of the cursor */ ++int graphics_getxy(void) { ++    return (fontx << 8) | fonty; ++} ++ ++void graphics_gotoxy(int x, int y) { ++    graphics_cursor(0); ++ ++    graphics_setxy(x, y); ++ ++    graphics_cursor(1); ++} ++ ++void graphics_cls(void) { ++    int i; ++    unsigned char *mem, *s1, *s2, *s4, *s8; ++ ++    graphics_cursor(0); ++    graphics_gotoxy(view_x0, view_y0); ++ ++    mem = (unsigned char*)VIDEOMEM; ++    s1 = (unsigned char*)VSHADOW1; ++    s2 = (unsigned char*)VSHADOW2; ++    s4 = (unsigned char*)VSHADOW4; ++    s8 = (unsigned char*)VSHADOW8; ++ ++    for (i = 0; i < 80 * 30; i++) ++        text[i] = ' '; ++    graphics_cursor(1); ++ ++    BitMask(0xff); ++ ++    /* plane 1 */ ++    MapMask(1); ++    grub_memcpy(mem, s1, 38400); ++ ++    /* plane 2 */ ++    MapMask(2); ++    grub_memcpy(mem, s2, 38400); ++ ++    /* plane 3 */ ++    MapMask(4); ++    grub_memcpy(mem, s4, 38400); ++ ++    /* plane 4 */ ++    MapMask(8); ++    grub_memcpy(mem, s8, 38400); ++ ++    MapMask(15); ++ ++    if (no_cursor) { ++        no_cursor = 0; ++        set_int1c_handler(); ++    } ++} ++ ++void graphics_setcolorstate (color_state state) { ++    switch (state) { ++    case COLOR_STATE_STANDARD: ++        graphics_current_color = graphics_standard_color; ++        break; ++    case COLOR_STATE_NORMAL: ++        graphics_current_color = graphics_normal_color; ++        break; ++    case COLOR_STATE_HIGHLIGHT: ++        graphics_current_color = graphics_highlight_color; ++        break; ++    default: ++        graphics_current_color = graphics_standard_color; ++        break; ++    } ++ ++    graphics_color_state = state; ++} ++ ++void graphics_setcolor (int normal_color, int highlight_color) { ++    graphics_normal_color = normal_color; ++    graphics_highlight_color = highlight_color; ++ ++    graphics_setcolorstate (graphics_color_state); ++} ++ ++int graphics_setcursor (int on) { ++    if (!no_cursor && !on) { ++        no_cursor = 1; ++        unset_int1c_handler(); ++        graphics_cursor(0); ++    } ++    else if(no_cursor && on) { ++        no_cursor = 0; ++        set_int1c_handler(); ++        graphics_cursor(1); ++    } ++    return 0; ++} ++ ++/* Read in the splashscreen image and set the palette up appropriately. ++ * Format of splashscreen is an xpm (can be gzipped) with 16 colors and ++ * 640x480. */ ++int read_image(char *s) ++{ ++    char buf[32], pal[16], c; ++    unsigned char base, mask, *s1, *s2, *s4, *s8; ++    unsigned i, len, idx, colors, x, y, width, height; ++ ++    if (!grub_open(s)) ++        return 0; ++ ++    /* read header */ ++    if (!grub_read((char*)&buf, 10) || grub_memcmp(buf, "/* XPM */\n", 10)) { ++        grub_close(); ++        return 0; ++    } ++     ++    /* parse info */ ++    while (grub_read(&c, 1)) { ++        if (c == '"') ++            break; ++    } ++ ++    while (grub_read(&c, 1) && (c == ' ' || c == '\t')) ++        ; ++ ++    i = 0; ++    width = c - '0'; ++    while (grub_read(&c, 1)) { ++        if (c >= '0' && c <= '9') ++            width = width * 10 + c - '0'; ++        else ++            break; ++    } ++    while (grub_read(&c, 1) && (c == ' ' || c == '\t')) ++        ; ++ ++    height = c - '0'; ++    while (grub_read(&c, 1)) { ++        if (c >= '0' && c <= '9') ++            height = height * 10 + c - '0'; ++        else ++            break; ++    } ++    while (grub_read(&c, 1) && (c == ' ' || c == '\t')) ++        ; ++ ++    colors = c - '0'; ++    while (grub_read(&c, 1)) { ++        if (c >= '0' && c <= '9') ++            colors = colors * 10 + c - '0'; ++        else ++            break; ++    } ++ ++    base = 0; ++    while (grub_read(&c, 1) && c != '"') ++        ; ++ ++    /* palette */ ++    for (i = 0, idx = 1; i < colors; i++) { ++        len = 0; ++ ++        while (grub_read(&c, 1) && c != '"') ++            ; ++        grub_read(&c, 1);       /* char */ ++        base = c; ++        grub_read(buf, 4);      /* \t c # */ ++ ++        while (grub_read(&c, 1) && c != '"') { ++            if (len < sizeof(buf)) ++                buf[len++] = c; ++        } ++ ++        if (len == 6 && idx < 15) { ++            int r = ((hex(buf[0]) << 4) | hex(buf[1])) >> 2; ++            int g = ((hex(buf[2]) << 4) | hex(buf[3])) >> 2; ++            int b = ((hex(buf[4]) << 4) | hex(buf[5])) >> 2; ++ ++            pal[idx] = base; ++            graphics_set_palette(idx, r, g, b); ++            ++idx; ++        } ++    } ++ ++    x = y = len = 0; ++ ++    s1 = (unsigned char*)VSHADOW1; ++    s2 = (unsigned char*)VSHADOW2; ++    s4 = (unsigned char*)VSHADOW4; ++    s8 = (unsigned char*)VSHADOW8; ++ ++    for (i = 0; i < 38400; i++) ++        s1[i] = s2[i] = s4[i] = s8[i] = 0; ++ ++    /* parse xpm data */ ++    while (y < height) { ++        while (1) { ++            if (!grub_read(&c, 1)) { ++                grub_close(); ++                return 0; ++            } ++            if (c == '"') ++                break; ++        } ++ ++        while (grub_read(&c, 1) && c != '"') { ++            for (i = 1; i < 15; i++) ++                if (pal[i] == c) { ++                    c = i; ++                    break; ++                } ++ ++            mask = 0x80 >> (x & 7); ++            if (c & 1) ++                s1[len + (x >> 3)] |= mask; ++            if (c & 2) ++                s2[len + (x >> 3)] |= mask; ++            if (c & 4) ++                s4[len + (x >> 3)] |= mask; ++            if (c & 8) ++                s8[len + (x >> 3)] |= mask; ++ ++            if (++x >= 640) { ++                x = 0; ++ ++                if (y < 480) ++                    len += 80; ++                ++y; ++            } ++        } ++    } ++ ++    grub_close(); ++ ++    graphics_set_palette(0, (background >> 16), (background >> 8) & 63,  ++                background & 63); ++    graphics_set_palette(15, (foreground >> 16), (foreground >> 8) & 63,  ++                foreground & 63); ++    graphics_set_palette(0x11, (window_border >> 16), (window_border >> 8) & 63,  ++                         window_border & 63); ++ ++    return 1; ++} ++ ++/* Convert a character which is a hex digit to the appropriate integer */ ++int hex(int v) ++{ ++    if (v >= 'A' && v <= 'F') ++        return (v - 'A' + 10); ++    if (v >= 'a' && v <= 'f') ++        return (v - 'a' + 10); ++    return (v - '0'); ++} ++ ++void graphics_cursor(int set) { ++    unsigned char *pat, *mem, *ptr, chr[16 << 2]; ++    int i, ch, invert, offset; ++ ++    if (set && (no_cursor || no_scroll)) ++        return; ++ ++    offset = cursorY * 80 + fontx; ++    ch = text[fonty * 80 + fontx] & 0xff; ++    invert = (text[fonty * 80 + fontx] & 0xff00) != 0; ++    pat = font8x16 + (ch << 4); ++ ++    mem = (unsigned char*)VIDEOMEM + offset; ++ ++    if (!set) { ++        for (i = 0; i < 16; i++) { ++            unsigned char mask = pat[i]; ++ ++            if (!invert) { ++                chr[i     ] = ((unsigned char*)VSHADOW1)[offset]; ++                chr[16 + i] = ((unsigned char*)VSHADOW2)[offset]; ++                chr[32 + i] = ((unsigned char*)VSHADOW4)[offset]; ++                chr[48 + i] = ((unsigned char*)VSHADOW8)[offset]; ++ ++                if (shade) { ++                    if (ch == DISP_VERT || ch == DISP_LL || ++                        ch == DISP_UR || ch == DISP_LR) { ++                        unsigned char pmask = ~(pat[i] >> 1); ++ ++                        chr[i     ] &= pmask; ++                        chr[16 + i] &= pmask; ++                        chr[32 + i] &= pmask; ++                        chr[48 + i] &= pmask; ++                    } ++                    if (i > 0 && ch != DISP_VERT) { ++                        unsigned char pmask = ~(pat[i - 1] >> 1); ++ ++                        chr[i     ] &= pmask; ++                        chr[16 + i] &= pmask; ++                        chr[32 + i] &= pmask; ++                        chr[48 + i] &= pmask; ++                        if (ch == DISP_HORIZ || ch == DISP_UR || ch == DISP_LR) { ++                            pmask = ~pat[i - 1]; ++ ++                            chr[i     ] &= pmask; ++                            chr[16 + i] &= pmask; ++                            chr[32 + i] &= pmask; ++                            chr[48 + i] &= pmask; ++                        } ++                    } ++                } ++                chr[i     ] |= mask; ++                chr[16 + i] |= mask; ++                chr[32 + i] |= mask; ++                chr[48 + i] |= mask; ++ ++                offset += 80; ++            } ++            else { ++                chr[i     ] = mask; ++                chr[16 + i] = mask; ++                chr[32 + i] = mask; ++                chr[48 + i] = mask; ++            } ++        } ++    } ++    else { ++        MapMask(15); ++        ptr = mem; ++        for (i = 0; i < 16; i++, ptr += 80) { ++            cursorBuf[i] = pat[i]; ++            *ptr = ~pat[i]; ++        } ++        return; ++    } ++ ++    offset = 0; ++    for (i = 1; i < 16; i <<= 1, offset += 16) { ++        int j; ++ ++        MapMask(i); ++        ptr = mem; ++        for (j = 0; j < 16; j++, ptr += 80) ++            *ptr = chr[j + offset]; ++    } ++ ++    MapMask(15); ++} ++ ++#endif /* SUPPORT_GRAPHICS */ +--- /dev/null ++++ b/stage2/graphics.h +@@ -0,0 +1,44 @@ ++/* graphics.h - graphics console interface */ ++/* ++ *  GRUB  --  GRand Unified Bootloader ++ *  Copyright (C) 2002  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. ++ */ ++ ++#ifndef GRAPHICS_H ++#define GRAPHICS_H ++ ++/* magic constant */ ++#define VIDEOMEM 0xA0000 ++ ++/* function prototypes */ ++char *graphics_get_splash(void); ++ ++int read_image(char *s); ++void graphics_cursor(int set); ++ ++/* function prototypes for asm functions */ ++void * graphics_get_font(); ++void graphics_set_palette(int idx, int red, int green, int blue); ++void set_int1c_handler(); ++void unset_int1c_handler(); ++ ++extern short cursorX, cursorY; ++extern char cursorBuf[16]; ++extern int shade; ++extern int view_x0, view_y0, view_x1, view_y1; ++ ++#endif /* GRAPHICS_H */ +--- a/stage2/Makefile.am ++++ b/stage2/Makefile.am +@@ -7,7 +7,7 @@ noinst_HEADERS = apic.h defs.h dir.h dis +         fat.h filesys.h freebsd.h fs.h hercules.h i386-elf.h \ + 	imgact_aout.h iso9660.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 ufs2.h vstafs.h xfs.h ++	terminfo.h tparm.h nbi.h ufs2.h vstafs.h xfs.h graphics.h + EXTRA_DIST = setjmp.S apm.S $(noinst_SCRIPTS) +  + # For <stage1.h>. +@@ -19,7 +19,7 @@ libgrub_a_SOURCES = boot.c builtins.c ch + 	disk_io.c fsys_ext2fs.c fsys_fat.c fsys_ffs.c fsys_iso9660.c \ + 	fsys_jfs.c fsys_minix.c fsys_reiserfs.c fsys_ufs2.c \ + 	fsys_vstafs.c fsys_xfs.c gunzip.c md5.c serial.c stage2.c \ +-	terminfo.c tparm.c ++	terminfo.c tparm.c graphics.c + libgrub_a_CFLAGS = $(GRUB_CFLAGS) -I$(top_srcdir)/lib \ + 	-DGRUB_UTIL=1 -DFSYS_EXT2FS=1 -DFSYS_FAT=1 -DFSYS_FFS=1 \ + 	-DFSYS_ISO9660=1 -DFSYS_JFS=1 -DFSYS_MINIX=1 -DFSYS_REISERFS=1 \ +@@ -79,8 +79,14 @@ else + HERCULES_FLAGS = + endif +  ++if GRAPHICS_SUPPORT ++GRAPHICS_FLAGS = -DSUPPORT_GRAPHICS=1 ++else ++GRAPHICS_FLAGS = ++endif ++ + STAGE2_COMPILE = $(STAGE2_CFLAGS) -fno-builtin -nostdinc \ +-	$(NETBOOT_FLAGS) $(SERIAL_FLAGS) $(HERCULES_FLAGS) ++	$(NETBOOT_FLAGS) $(SERIAL_FLAGS) $(HERCULES_FLAGS) $(GRAPHICS_FLAGS) +  + STAGE1_5_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,2000 + STAGE1_5_COMPILE = $(STAGE2_COMPILE) -DNO_DECOMPRESSION=1 -DSTAGE1_5=1 +@@ -90,7 +96,8 @@ pre_stage2_exec_SOURCES = asm.S bios.c b + 	cmdline.c common.c console.c disk_io.c fsys_ext2fs.c \ + 	fsys_fat.c fsys_ffs.c fsys_iso9660.c fsys_jfs.c fsys_minix.c \ + 	fsys_reiserfs.c fsys_ufs2.c fsys_vstafs.c fsys_xfs.c gunzip.c \ +-	hercules.c md5.c serial.c smp-imps.c stage2.c terminfo.c tparm.c ++	hercules.c md5.c serial.c smp-imps.c stage2.c terminfo.c tparm.c \ ++	graphics.c + pre_stage2_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS) + pre_stage2_exec_CCASFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS) + pre_stage2_exec_LDFLAGS = $(PRE_STAGE2_LINK) +--- a/stage2/shared.h ++++ b/stage2/shared.h +@@ -499,7 +499,11 @@ struct vbe_mode +   unsigned char linear_reserved_field_position; +   unsigned long max_pixel_clock; +  +-  unsigned char reserved3[189]; ++  /* Reserved field to make structure to be 256 bytes long, VESA BIOS  ++     Extension 3.0 Specification says to reserve 189 bytes here but  ++     that doesn't make structure to be 256 bytes.  So additional one is  ++     added here.  */ ++  unsigned char reserved3[189 + 1]; + } __attribute__ ((packed)); +  +  +@@ -792,6 +796,11 @@ int getxy (void); + /* Set the cursor position. */ + void gotoxy (int x, int y); +  ++/* Internal pager ++   Returns 1 = if pager was used ++           0 = if pager wasn't used  */ ++int do_more (void); ++ + /* Displays an ASCII character.  IBM displays will translate some +    characters to special graphical ones (see the DISP_* constants). */ + void grub_putchar (int c); +@@ -871,6 +880,7 @@ int grub_sprintf (char *buffer, const ch + int grub_tolower (int c); + int grub_isspace (int c); + int grub_strncat (char *s1, const char *s2, int n); ++void grub_memcpy(void *dest, const void *src, int len); + 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); +@@ -911,7 +921,7 @@ int substring (const char *s1, const cha + 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); ++int memcheck (unsigned long int start, unsigned long int len); + void grub_putstr (const char *str); +  + #ifndef NO_DECOMPRESSION +--- a/stage2/stage2.c ++++ b/stage2/stage2.c +@@ -20,6 +20,12 @@ + #include <shared.h> + #include <term.h> +  ++#ifdef SUPPORT_GRAPHICS ++# include <graphics.h> ++#endif ++ ++int col_start, col_end, row_start, box_size; ++ + grub_jmp_buf restart_env; +  + #if defined(PRESET_MENU_STRING) || defined(SUPPORT_DISKLESS) +@@ -105,13 +111,13 @@ print_entry (int y, int highlight, char  +   if (highlight && current_term->setcolorstate) +     current_term->setcolorstate (COLOR_STATE_HIGHLIGHT); +  +-  gotoxy (2, y); ++  gotoxy (2 + col_start, y); +   grub_putchar (' '); +-  for (x = 3; x < 75; x++) ++  for (x = 3 + col_start; x < (col_end - 5); x++) +     { +-      if (*entry && x <= 72) ++      if (*entry && x <= (col_end - 8)) + 	{ +-	  if (x == 72) ++	  if (x == (col_end - 8)) + 	    grub_putchar (DISP_RIGHT); + 	  else + 	    grub_putchar (*entry++); +@@ -119,7 +125,7 @@ print_entry (int y, int highlight, char  +       else + 	grub_putchar (' '); +     } +-  gotoxy (74, y); ++  gotoxy ((col_end - 6), y); +  +   if (current_term->setcolorstate) +     current_term->setcolorstate (COLOR_STATE_STANDARD); +@@ -131,7 +137,7 @@ print_entries (int y, int size, int firs + { +   int i; +    +-  gotoxy (77, y + 1); ++  gotoxy ((col_end - 3), y + 1); +  +   if (first) +     grub_putchar (DISP_UP); +@@ -151,14 +157,14 @@ print_entries (int y, int size, int firs + 	menu_entries++; +     } +  +-  gotoxy (77, y + size); ++  gotoxy ((col_end - 3), y + size); +  +   if (*menu_entries) +     grub_putchar (DISP_DOWN); +   else +     grub_putchar (' '); +  +-  gotoxy (74, y + entryno + 1); ++  gotoxy ((col_end - 6), y + entryno + 1); + } +  + static void +@@ -196,30 +202,30 @@ print_border (int y, int size) +   if (current_term->setcolorstate) +     current_term->setcolorstate (COLOR_STATE_NORMAL); +    +-  gotoxy (1, y); ++  gotoxy (1 + col_start, y); +  +   grub_putchar (DISP_UL); +-  for (i = 0; i < 73; i++) ++  for (i = col_start; i < (col_end - 7); i++) +     grub_putchar (DISP_HORIZ); +   grub_putchar (DISP_UR); +  +   i = 1; +   while (1) +     { +-      gotoxy (1, y + i); ++      gotoxy (1 + col_start, y + i); +  +       if (i > size) + 	break; +        +       grub_putchar (DISP_VERT); +-      gotoxy (75, y + i); ++      gotoxy ((col_end - 5), y + i); +       grub_putchar (DISP_VERT); +  +       i++; +     } +  +   grub_putchar (DISP_LL); +-  for (i = 0; i < 73; i++) ++  for (i = col_start; i < (col_end - 7); i++) +     grub_putchar (DISP_HORIZ); +   grub_putchar (DISP_LR); +  +@@ -233,6 +239,7 @@ run_menu (char *menu_entries, char *conf + { +   int c, time1, time2 = -1, first_entry = 0; +   char *cur_entry = 0; ++  struct term_entry *prev_term = NULL; +  +   /* +    *  Main loop for menu UI. +@@ -250,6 +257,22 @@ restart: + 	} +     } +  ++  col_start = 0; ++  col_end = 80; ++  row_start = 0; ++  box_size = 12; ++  /* if we're using viewport we need to make sure to setup ++     coordinates correctly.  */ ++#ifdef SUPPORT_GRAPHICS ++  if (grub_memcmp (current_term->name, "graphics", sizeof ("graphics") - 1) == 0) ++    { ++      col_start = view_x0; ++      col_end = view_x1; ++      row_start = view_y0; ++      box_size = (view_y1 - view_y0) - 13; ++    } ++#endif ++ +   /* If the timeout was expired or wasn't set, force to show the menu +      interface. */ +   if (grub_timeout < 0) +@@ -302,36 +325,36 @@ restart: +       if (current_term->flags & TERM_DUMB) + 	print_entries_raw (num_entries, first_entry, menu_entries); +       else +-	print_border (3, 12); ++	print_border (3 + row_start, box_size); +  +       grub_printf ("\n\ +-      Use the %c and %c keys to select which entry is highlighted.\n", ++    Use the %c and %c keys to select which entry is highlighted.\n", + 		   DISP_UP, DISP_DOWN); +        +       if (! auth && password) + 	{ + 	  printf ("\ +-      Press enter to boot the selected OS or \'p\' to enter a\n\ +-      password to unlock the next set of features."); ++    Press enter to boot the selected OS or \'p\' to enter a\n\ ++    password to unlock the next set of features."); + 	} +       else + 	{ + 	  if (config_entries) + 	    printf ("\ +-      Press enter to boot the selected OS, \'e\' to edit the\n\ +-      commands before booting, or \'c\' for a command-line."); ++    Press enter to boot the selected OS, \'e\' to edit the\n\ ++    commands before booting, or \'c\' for a command-line."); + 	  else + 	    printf ("\ +-      Press \'b\' to boot, \'e\' to edit the selected command in the\n\ +-      boot sequence, \'c\' for a command-line, \'o\' to open a new line\n\ +-      after (\'O\' for before) the selected line, \'d\' to remove the\n\ +-      selected line, or escape to go back to the main menu."); ++    Press \'b\' to boot, \'e\' to edit the selected command in the\n\ ++    boot sequence, \'c\' for a command-line, \'o\' to open a new line\n\ ++    after (\'O\' for before) the selected line, \'d\' to remove the\n\ ++    selected line, or escape to go back to the main menu."); + 	} +  +       if (current_term->flags & TERM_DUMB) + 	grub_printf ("\n\nThe selected entry is %d ", entryno); +       else +-	print_entries (3, 12, first_entry, entryno, menu_entries); ++	print_entries (3 + row_start, box_size, first_entry, entryno, menu_entries); +     } +  +   /* XX using RT clock now, need to initialize value */ +@@ -358,10 +381,10 @@ restart: + 			   entryno, grub_timeout); + 	  else + 	    { +-	      gotoxy (3, 22); +-	      grub_printf ("The highlighted entry will be booted automatically in %d seconds.    ", ++	      gotoxy (3 + col_start, 10 + box_size + row_start); ++	      grub_printf (" The highlighted entry will be booted automatically in %d seconds.   ", + 			   grub_timeout); +-	      gotoxy (74, 4 + entryno); ++	      gotoxy ((col_end - 6), 4 + entryno + row_start); + 	  } + 	   + 	  grub_timeout--; +@@ -387,12 +410,12 @@ restart: + 	      if (current_term->flags & TERM_DUMB) + 		grub_putchar ('\r'); + 	      else +-		gotoxy (3, 22); ++		gotoxy (3 + col_start, 10 + box_size + row_start); + 	      printf ("                                                                    "); + 	      grub_timeout = -1; + 	      fallback_entryno = -1; + 	      if (! (current_term->flags & TERM_DUMB)) +-		gotoxy (74, 4 + entryno); ++		gotoxy ((col_end - 6), 4 + entryno + row_start); + 	    } +  + 	  /* We told them above (at least in SUPPORT_SERIAL) to use +@@ -408,12 +431,12 @@ restart: + 		{ + 		  if (entryno > 0) + 		    { +-		      print_entry (4 + entryno, 0, ++		      print_entry (4 + entryno + row_start, 0, + 				   get_entry (menu_entries, + 					      first_entry + entryno, + 					      0)); + 		      entryno--; +-		      print_entry (4 + entryno, 1, ++		      print_entry (4 + entryno + row_start, 1, + 				   get_entry (menu_entries, + 					      first_entry + entryno, + 					      0)); +@@ -421,7 +444,7 @@ restart: + 		  else if (first_entry > 0) + 		    { + 		      first_entry--; +-		      print_entries (3, 12, first_entry, entryno, ++		      print_entries (3 + row_start, box_size, first_entry, entryno, + 				     menu_entries); + 		    } + 		} +@@ -433,29 +456,29 @@ restart: + 		entryno++; + 	      else + 		{ +-		  if (entryno < 11) ++		  if (entryno < (box_size - 1)) + 		    { +-		      print_entry (4 + entryno, 0, ++		      print_entry (4 + entryno + row_start, 0, + 				   get_entry (menu_entries, + 					      first_entry + entryno, + 					      0)); + 		      entryno++; +-		      print_entry (4 + entryno, 1, ++		      print_entry (4 + entryno + row_start, 1, + 				   get_entry (menu_entries, + 					      first_entry + entryno, + 					      0)); + 		  } +-		else if (num_entries > 12 + first_entry) ++		else if (num_entries > box_size + first_entry) + 		  { + 		    first_entry++; +-		    print_entries (3, 12, first_entry, entryno, menu_entries); ++		    print_entries (3 + row_start, box_size, first_entry, entryno, menu_entries); + 		  } + 		} + 	    } + 	  else if (c == 7) + 	    { + 	      /* Page Up */ +-	      first_entry -= 12; ++	      first_entry -= box_size; + 	      if (first_entry < 0) + 		{ + 		  entryno += first_entry; +@@ -463,20 +486,20 @@ restart: + 		  if (entryno < 0) + 		    entryno = 0; + 		} +-	      print_entries (3, 12, first_entry, entryno, menu_entries); ++	      print_entries (3 + row_start, box_size, first_entry, entryno, menu_entries); + 	    } + 	  else if (c == 3) + 	    { + 	      /* Page Down */ +-	      first_entry += 12; ++	      first_entry += box_size; + 	      if (first_entry + entryno + 1 >= num_entries) + 		{ +-		  first_entry = num_entries - 12; ++		  first_entry = num_entries - box_size; + 		  if (first_entry < 0) + 		    first_entry = 0; + 		  entryno = num_entries - first_entry - 1; + 		} +-	      print_entries (3, 12, first_entry, entryno, menu_entries); ++	      print_entries (3 + row_start, box_size, first_entry, entryno, menu_entries); + 	    } +  + 	  if (config_entries) +@@ -489,7 +512,7 @@ restart: + 	      if ((c == 'd') || (c == 'o') || (c == 'O')) + 		{ + 		  if (! (current_term->flags & TERM_DUMB)) +-		    print_entry (4 + entryno, 0, ++		    print_entry (4 + entryno + row_start, 0, + 				 get_entry (menu_entries, + 					    first_entry + entryno, + 					    0)); +@@ -537,7 +560,7 @@ restart: +  + 		      if (entryno >= num_entries) + 			entryno--; +-		      if (first_entry && num_entries < 12 + first_entry) ++		      if (first_entry && num_entries < box_size + first_entry) + 			first_entry--; + 		    } +  +@@ -549,7 +572,7 @@ restart: + 		      grub_printf ("\n"); + 		    } + 		  else +-		    print_entries (3, 12, first_entry, entryno, menu_entries); ++		    print_entries (3 + row_start, box_size, first_entry, entryno, menu_entries); + 		} +  + 	      cur_entry = menu_entries; +@@ -570,7 +593,7 @@ restart: + 		  if (current_term->flags & TERM_DUMB) + 		    grub_printf ("\r                                    "); + 		  else +-		    gotoxy (1, 21); ++		    gotoxy (1 + col_start, 9 + box_size + row_start); +  + 		  /* Wipe out the previously entered password */ + 		  grub_memset (entered, 0, sizeof (entered)); +@@ -651,7 +674,10 @@ restart: + 		  *(new_heap++) = 0; +  + 		  if (config_entries) +-		    run_menu (heap, NULL, new_num_entries, new_heap, 0); ++		    { ++		      current_entryno = first_entry + entryno; ++		      run_menu (heap, NULL, new_num_entries, new_heap, 0); ++		    } + 		  else + 		    { + 		      cls (); +@@ -714,6 +740,15 @@ restart: +    +   cls (); +   setcursor (1); ++  /* if our terminal needed initialization, we should shut it down ++   * before booting the kernel, but we want to save what it was so ++   * we can come back if needed */ ++  prev_term = current_term; ++  if (current_term->shutdown)  ++    { ++      current_term->shutdown(); ++      current_term = term_table; /* assumption: console is first */ ++    } +    +   while (1) +     { +@@ -727,7 +762,8 @@ restart: + 	cur_entry = get_entry (config_entries, first_entry + entryno, 1); +  +       /* Set CURRENT_ENTRYNO for the command "savedefault".  */ +-      current_entryno = first_entry + entryno; ++      if (config_entries) ++	current_entryno = first_entry + entryno; +        +       if (run_script (cur_entry, heap)) + 	{ +@@ -748,6 +784,13 @@ restart: + 	break; +     } +  ++  /* if we get back here, we should go back to what our term was before */ ++  current_term = prev_term; ++  if (current_term->startup) ++      /* if our terminal fails to initialize, fall back to console since ++       * it should always work */ ++      if (current_term->startup() == 0) ++          current_term = term_table; /* we know that console is first */ +   show_menu = 1; +   goto restart; + } +@@ -891,8 +934,18 @@ cmain (void) + 	      len = grub_read (buf, sizeof (buf)); + 	      if (len > 0) + 		{ ++		  char *tmp; ++		  char *def; + 		  buf[sizeof (buf) - 1] = 0; +-		  safe_parse_maxint (&p, &saved_entryno); ++ ++		  if((tmp = grub_strstr(p, ":")) != NULL) ++		  { ++		    *tmp++; ++		    grub_memcpy(&def, &tmp, sizeof(p)); ++		  }else ++		    grub_memcpy(&def, &p, sizeof(p)); ++		   ++		  safe_parse_maxint (&def, &saved_entryno); + 		} +  + 	      grub_close (); +@@ -1050,6 +1103,16 @@ cmain (void) + 	  while (is_preset); + 	} +  ++      /* go ahead and make sure the terminal is setup */ ++      if (current_term->startup) ++	{ ++	  /* If initialization fails, go back to default terminal */ ++	  if (current_term->startup() == 0) ++		  { ++		      current_term = term_table; ++		  } ++	} ++ +       if (! num_entries) + 	{ + 	  /* If no acceptable config file, goto command-line, starting +--- a/stage2/term.h ++++ b/stage2/term.h +@@ -60,6 +60,8 @@ struct term_entry +   const char *name; +   /* The feature flags defined above.  */ +   unsigned long flags; ++  /* Default for maximum number of lines if not specified */ ++  unsigned short max_lines; +   /* Put a character.  */ +   void (*putchar) (int c); +   /* Check if any input character is available.  */ +@@ -79,6 +81,10 @@ struct term_entry +   void (*setcolor) (int normal_color, int highlight_color); +   /* Turn on/off the cursor.  */ +   int (*setcursor) (int on); ++  /* function to start a terminal */ ++  int (*startup) (void); ++  /* function to use to shutdown a terminal */ ++  void (*shutdown) (void); + }; +  + /* This lists up available terminals.  */ +@@ -124,4 +130,24 @@ void hercules_setcolor (int normal_color + int hercules_setcursor (int on); + #endif +  ++#ifdef SUPPORT_GRAPHICS ++extern int foreground, background, window_border, graphics_inited, saved_videomode; ++ ++void graphics_set_splash(char *splashfile); ++int set_videomode(int mode); ++int get_videomode(void); ++void graphics_putchar (int c); ++int graphics_getxy(void); ++void graphics_gotoxy(int x, int y); ++void graphics_cls(void); ++void graphics_setcolorstate (color_state state); ++void graphics_setcolor (int normal_color, int highlight_color); ++int graphics_setcursor (int on); ++int graphics_init(void); ++void graphics_end(void); ++ ++int hex(int v); ++void graphics_set_palette(int idx, int red, int green, int blue); ++#endif /* SUPPORT_GRAPHICS */ ++ + #endif /* ! GRUB_TERM_HEADER */ +--- a/THANKS ++++ b/THANKS +@@ -121,3 +121,4 @@ Vesa Jaaskelainen <jaaskela@tietomyrsky. + Yedidyah Bar-David <didi@post.tau.ac.il> + Yury V. Umanets <umka@namesys.com> + Yuri Zaporogets <yuriz@ukr.net> ++Vitaly Fertman <vitaly@namesys.com> +--- a/util/grub-install.in ++++ b/util/grub-install.in +@@ -81,6 +81,50 @@ Report bugs to <bug-grub@gnu.org>. + EOF + } +  ++# Usage: getraid_mdadm mddevice ++# Routine to find a physical device from an md device ++# If found, the first grub BIOS device (from device.map) is returned  ++# If no BIOS drives match the RAID devices, the first device returned ++# from mdadm -D is returned ++getraid_mdadm() { ++	device=$1 ++	mdadm=$(mdadm -D "$device") || { ++		echo "$PROG: mdadm -D $device failed" >&2 ++		exit 1 ++	} ++	eval "$( ++		echo "$mdadm" | awk ' ++			$1 == "Number" && $2 == "Major" { start = 1; next } ++			$1 == "UUID" { print "uuid=" $3; start = 0; next } ++			!start { next } ++			$2 == 0 && $3 == 0 { next } ++			{ devices = devices "\n" $NF } ++			END { print "devices='\''" devices "'\''" } ++		' ++	)" ++ ++	# Convert RAID devices list into a list of disks ++	tmp_disks=`echo "$devices" | sed -e 's%\([sh]d[a-z]\)[0-9]*$%\1%' \ ++					 -e 's%\(d[0-9]*\)p[0-9]*$%\1%' \ ++					 -e 's%\(fd[0-9]*\)$%\1%' \ ++					 -e 's%/part[0-9]*$%/disc%' \ ++					 -e 's%\(c[0-7]d[0-9]*\).*$%\1%' \ ++					 -e '/^$/d' | ++				     sed -n '1h;2,$H;${g;s/\n/|/g;p}'` ++ ++	# Find first BIOS disk that's a member of the RAID array ++	# Default to first RAID member if no tmp_disks are BIOS devices ++	set -- `egrep $tmp_disks $device_map | \ ++		sort | \ ++		sed -n 1p ` ++	device=${2:-${tmp_disks%%|*}} ++ ++	# Return first partition on BIOS disk that's part of the RAID ++	echo "$devices" | \ ++		sed -n "\:${device}:p" | \ ++		sed -n 1p ++} ++ + # Usage: convert os_device + # Convert an OS device to the corresponding GRUB drive. + # This part is OS-specific. +@@ -96,6 +140,10 @@ convert () { +     # Break the device name into the disk part and the partition part. +     case "$host_os" in +     linux*) ++	# Find an actual physical device if we're passed a RAID device ++	case $1 in ++		/dev/md*)  set -- `getraid_mdadm $1` ++	esac + 	tmp_disk=`echo "$1" | sed -e 's%\([sh]d[a-z]\)[0-9]*$%\1%' \ + 				  -e 's%\(d[0-9]*\)p[0-9]*$%\1%' \ + 				  -e 's%\(fd[0-9]*\)$%\1%' \ +@@ -112,8 +160,8 @@ convert () { + 	tmp_disk=`echo "$1" | sed 's%\([sh]d[0-9]*\).*%\1%'` + 	tmp_part=`echo "$1" | sed "s%$tmp_disk%%"` ;; +     freebsd* | kfreebsd*-gnu) +-	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%r\{0,1\}\([saw]d[0-9]*\).*$%\1%' \ ++			    | sed 's%r\{0,1\}\(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%"` +@@ -131,7 +179,7 @@ convert () { +  +     # Get the drive name. +     tmp_drive=`grep -v '^#' $device_map | grep "$tmp_disk *$" \ +-	| sed 's%.*\(([hf]d[0-9][a-g0-9,]*)\).*%\1%'` ++	| sed 's%.*\(([hf]d[0-9][a-z0-9,]*)\).*%\1%'` +  +     # If not found, print an error message and exit. +     if test "x$tmp_drive" = x; then +@@ -148,13 +196,13 @@ convert () { + 	gnu*) + 	    if echo $tmp_part | grep "^s" >/dev/null; then + 		tmp_pc_slice=`echo $tmp_part \ +-		    | sed "s%s\([0-9]*\)[a-g]*$%\1%"` ++		    | sed "s%s\([0-9]*\)[a-z]*$%\1%"` + 		tmp_drive=`echo "$tmp_drive" \ + 		    | sed "s%)%,\`expr "$tmp_pc_slice" - 1\`)%"` + 	    fi +-	    if echo $tmp_part | grep "[a-g]$" >/dev/null; then ++	    if echo $tmp_part | grep "[a-z]$" >/dev/null; then + 		tmp_bsd_partition=`echo "$tmp_part" \ +-		    | sed "s%[^a-g]*\([a-g]\)$%\1%"` ++		    | sed "s%[^a-z]*\([a-z]\)$%\1%"` + 		tmp_drive=`echo "$tmp_drive" \ + 		    | sed "s%)%,$tmp_bsd_partition)%"` + 	    fi +@@ -336,6 +384,10 @@ else +     # Create a safe temporary file. +     test -n "$mklog" && log_file=`$mklog` +  ++    # Before all invocations of the grub shell, call sync to make sure ++    # the raw device is in sync with any bufferring in filesystems. ++    sync ++  +     $grub_shell --batch $no_floppy --device-map=$device_map <<EOF >$log_file + quit + EOF +@@ -450,6 +502,24 @@ rm -f $log_file + # Create a safe temporary file. + test -n "$mklog" && log_file=`$mklog` +  ++# Sync to prevent GRUB from not finding stage files (notably, on XFS) ++sync ++ ++# XFS needs special magic ++xfs_frozen=false ++if which xfs_freeze > /dev/null ; then ++  cat << EOF ++Due to a bug in xfs_freeze, the following command might produce a segmentation ++fault when ${grubdir} is not in an XFS filesystem. This error is harmless and ++can be ignored. ++EOF ++  if xfs_freeze -f ${grubdir} ; then xfs_frozen=true ; fi ++fi ++ ++# Before all invocations of the grub shell, call sync to make sure ++# the raw device is in sync with any bufferring in filesystems. ++sync ++ + # Now perform the installation. + $grub_shell --batch $no_floppy --device-map=$device_map <<EOF >$log_file + root $root_drive +@@ -457,6 +527,10 @@ setup $force_lba --stage2=$grubdir/stage + quit + EOF +  ++if ${xfs_frozen} ; then ++  xfs_freeze -u ${grubdir} ++fi ++ + if grep "Error [0-9]*: " $log_file >/dev/null || test $debug = yes; then +     cat $log_file 1>&2 +     exit 1 diff --git a/package/grub/patches/020-ext4_support.patch b/package/grub/patches/020-ext4_support.patch new file mode 100644 index 000000000..06cd2c261 --- /dev/null +++ b/package/grub/patches/020-ext4_support.patch @@ -0,0 +1,267 @@ +--- a/stage2/fsys_ext2fs.c ++++ b/stage2/fsys_ext2fs.c +@@ -51,6 +51,9 @@ typedef unsigned int __u32; + #define EXT2_TIND_BLOCK                 (EXT2_DIND_BLOCK + 1) + #define EXT2_N_BLOCKS                   (EXT2_TIND_BLOCK + 1) +  ++/* Inode flags */ ++#define EXT4_EXTENTS_FL                 0x00080000 /* Inode uses extents */ ++ + /* include/linux/ext2_fs.h */ + struct ext2_super_block +   { +@@ -191,6 +194,42 @@ struct ext2_dir_entry + #define EXT2_DIR_REC_LEN(name_len)      (((name_len) + 8 + EXT2_DIR_ROUND) & \ +                                          ~EXT2_DIR_ROUND) +  ++/* linux/ext4_fs_extents.h */ ++/* ++ * This is the extent on-disk structure. ++ * It's used at the bottom of the tree. ++ */ ++struct ext4_extent { ++    __u32 ee_block;       /* first logical block extent covers */ ++    __u16 ee_len;         /* number of blocks covered by extent */ ++    __u16 ee_start_hi;    /* high 16 bits of physical block */ ++    __u32 ee_start;       /* low 32 bits of physical block */ ++}; ++ ++/* ++ * This is index on-disk structure. ++ * It's used at all the levels except the bottom. ++ */ ++struct ext4_extent_idx { ++    __u32 ei_block;       /* index covers logical blocks from 'block' */ ++    __u32 ei_leaf;        /* pointer to the physical block of the next * ++                                 * level. leaf or next index could be there */ ++    __u16 ei_leaf_hi;     /* high 16 bits of physical block */ ++    __u16 ei_unused; ++}; ++ ++/* ++ * Each block (leaves and indexes), even inode-stored has header. ++ */ ++struct ext4_extent_header { ++    __u16  eh_magic;       /* probably will support different formats */ ++    __u16  eh_entries;     /* number of valid entries */ ++    __u16  eh_max;         /* capacity of store in entries */ ++    __u16  eh_depth;       /* has tree real underlying blocks? */ ++    __u32  eh_generation;  /* generation of the tree */ ++}; ++ ++#define EXT4_EXT_MAGIC          0xf30a +  + /* ext2/super.c */ + #define log2(n) ffz(~(n)) +@@ -279,6 +318,27 @@ ext2_rdfsb (int fsblock, int buffer) + 		  EXT2_BLOCK_SIZE (SUPERBLOCK), (char *) buffer); + } +  ++/* Walk through extents index tree to find the good leaf */ ++static struct ext4_extent_header * ++ext4_recurse_extent_index(struct ext4_extent_header *extent_block, int logical_block) ++{ ++  int i; ++  struct ext4_extent_idx *index = (struct ext4_extent_idx *) (extent_block + 1); ++  if (extent_block->eh_magic != EXT4_EXT_MAGIC) ++    return NULL; ++  if (extent_block->eh_depth == 0) ++    return extent_block; ++  for (i = 0; i < extent_block->eh_entries; i++) ++    { ++      if (logical_block < index[i].ei_block) ++        break; ++    } ++  if (i == 0 || !ext2_rdfsb(index[i-1].ei_leaf, DATABLOCK1)) ++    return NULL; ++  return (ext4_recurse_extent_index((struct ext4_extent_header *) DATABLOCK1, logical_block)); ++} ++ ++ + /* from +   ext2/inode.c:ext2_bmap() + */ +@@ -287,7 +347,6 @@ ext2_rdfsb (int fsblock, int buffer) + static int + ext2fs_block_map (int logical_block) + { +- + #ifdef E2DEBUG +   unsigned char *i; +   for (i = (unsigned char *) INODE; +@@ -308,82 +367,106 @@ ext2fs_block_map (int logical_block) +   printf ("logical block %d\n", logical_block); + #endif /* E2DEBUG */ +  +-  /* if it is directly pointed to by the inode, return that physical addr */ +-  if (logical_block < EXT2_NDIR_BLOCKS) ++  if (!(INODE->i_flags & EXT4_EXTENTS_FL)) +     { +-#ifdef E2DEBUG +-      printf ("returning %d\n", (unsigned char *) (INODE->i_block[logical_block])); +-      printf ("returning %d\n", INODE->i_block[logical_block]); +-#endif /* E2DEBUG */ +-      return INODE->i_block[logical_block]; +-    } +-  /* else */ +-  logical_block -= EXT2_NDIR_BLOCKS; +-  /* try the indirect block */ +-  if (logical_block < EXT2_ADDR_PER_BLOCK (SUPERBLOCK)) +-    { +-      if (mapblock1 != 1 +-	  && !ext2_rdfsb (INODE->i_block[EXT2_IND_BLOCK], DATABLOCK1)) +-	{ +-	  errnum = ERR_FSYS_CORRUPT; +-	  return -1; +-	} +-      mapblock1 = 1; +-      return ((__u32 *) DATABLOCK1)[logical_block]; +-    } +-  /* else */ +-  logical_block -= EXT2_ADDR_PER_BLOCK (SUPERBLOCK); +-  /* now try the double indirect block */ +-  if (logical_block < (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2))) +-    { +-      int bnum; +-      if (mapblock1 != 2 +-	  && !ext2_rdfsb (INODE->i_block[EXT2_DIND_BLOCK], DATABLOCK1)) +-	{ +-	  errnum = ERR_FSYS_CORRUPT; +-	  return -1; +-	} +-      mapblock1 = 2; +-      if ((bnum = (((__u32 *) DATABLOCK1) +-		   [logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)])) +-	  != mapblock2 +-	  && !ext2_rdfsb (bnum, DATABLOCK2)) +-	{ +-	  errnum = ERR_FSYS_CORRUPT; +-	  return -1; +-	} +-      mapblock2 = bnum; ++      /* if it is directly pointed to by the inode, return that physical addr */ ++      if (logical_block < EXT2_NDIR_BLOCKS) ++        { ++#ifdef E2DEBUG ++          printf ("returning %d\n", (unsigned char *) (INODE->i_block[logical_block])); ++          printf ("returning %d\n", INODE->i_block[logical_block]); ++#endif /* E2DEBUG */ ++          return INODE->i_block[logical_block]; ++        } ++      /* else */ ++      logical_block -= EXT2_NDIR_BLOCKS; ++      /* try the indirect block */ ++      if (logical_block < EXT2_ADDR_PER_BLOCK (SUPERBLOCK)) ++        { ++          if (mapblock1 != 1 && !ext2_rdfsb (INODE->i_block[EXT2_IND_BLOCK], DATABLOCK1)) ++            { ++              errnum = ERR_FSYS_CORRUPT; ++              return -1; ++            } ++          mapblock1 = 1; ++          return ((__u32 *) DATABLOCK1)[logical_block]; ++        } ++      /* else */ ++      logical_block -= EXT2_ADDR_PER_BLOCK (SUPERBLOCK); ++      /* now try the double indirect block */ ++      if (logical_block < (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2))) ++        { ++          int bnum; ++          if (mapblock1 != 2 && !ext2_rdfsb (INODE->i_block[EXT2_DIND_BLOCK], DATABLOCK1)) ++            { ++              errnum = ERR_FSYS_CORRUPT; ++              return -1; ++            } ++          mapblock1 = 2; ++          if ((bnum = (((__u32 *) DATABLOCK1) ++                  [logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)])) ++         != mapblock2 ++         && !ext2_rdfsb (bnum, DATABLOCK2)) ++           { ++             errnum = ERR_FSYS_CORRUPT; ++             return -1; ++           } ++          mapblock2 = bnum; ++          return ((__u32 *) DATABLOCK2) ++            [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)]; ++        } ++      /* else */ ++      mapblock2 = -1; ++      logical_block -= (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2)); ++      if (mapblock1 != 3 ++          && !ext2_rdfsb (INODE->i_block[EXT2_TIND_BLOCK], DATABLOCK1)) ++        { ++          errnum = ERR_FSYS_CORRUPT; ++          return -1; ++        } ++      mapblock1 = 3; ++      if (!ext2_rdfsb (((__u32 *) DATABLOCK1) ++                  [logical_block >> (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) ++                                     * 2)], ++                  DATABLOCK2)) ++        { ++          errnum = ERR_FSYS_CORRUPT; ++          return -1; ++        } ++      if (!ext2_rdfsb (((__u32 *) DATABLOCK2) ++                  [(logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)) ++                   & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)], ++                  DATABLOCK2)) ++        { ++          errnum = ERR_FSYS_CORRUPT; ++          return -1; ++        } ++ +       return ((__u32 *) DATABLOCK2) +-	[logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)]; ++       [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)]; +     } +-  /* else */ +-  mapblock2 = -1; +-  logical_block -= (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2)); +-  if (mapblock1 != 3 +-      && !ext2_rdfsb (INODE->i_block[EXT2_TIND_BLOCK], DATABLOCK1)) +-    { +-      errnum = ERR_FSYS_CORRUPT; +-      return -1; +-    } +-  mapblock1 = 3; +-  if (!ext2_rdfsb (((__u32 *) DATABLOCK1) +-		   [logical_block >> (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) +-				      * 2)], +-		   DATABLOCK2)) +-    { +-      errnum = ERR_FSYS_CORRUPT; +-      return -1; +-    } +-  if (!ext2_rdfsb (((__u32 *) DATABLOCK2) +-		   [(logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)) +-		    & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)], +-		   DATABLOCK2)) ++    /* inode is in extents format */ ++    else +     { ++      int i; ++      struct ext4_extent_header *extent_hdr = ++         ext4_recurse_extent_index((struct ext4_extent_header *) INODE->i_block, logical_block); ++      struct ext4_extent *extent = (struct ext4_extent *) (extent_hdr + 1); ++      if ( extent_hdr == NULL || extent_hdr->eh_magic != EXT4_EXT_MAGIC) ++        { ++          errnum = ERR_FSYS_CORRUPT; ++          return -1; ++        } ++      for (i = 0; i<extent_hdr->eh_entries; i++) ++        { ++          if (extent[i].ee_block <= logical_block && logical_block < extent[i].ee_block + extent[i].ee_len && !(extent[i].ee_len>>15)) ++            return (logical_block - extent[i].ee_block + extent[i].ee_start); ++        } ++      /* We should not arrive here */ ++ +       errnum = ERR_FSYS_CORRUPT; +       return -1; +     } +-  return ((__u32 *) DATABLOCK2) +-    [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)]; + } +  + /* preconditions: all preconds of ext2fs_block_map */ diff --git a/package/grub/patches/030-add-stage2-ldscripts.patch b/package/grub/patches/030-add-stage2-ldscripts.patch new file mode 100644 index 000000000..aff7ed466 --- /dev/null +++ b/package/grub/patches/030-add-stage2-ldscripts.patch @@ -0,0 +1,77 @@ +From 8858927ddc6797489cad322fc2d2134aeae543cd Mon Sep 17 00:00:00 2001 +From: Arnaud Lacombe <lacombar@gmail.com> +Date: Sun, 11 Dec 2011 16:44:02 -0500 +Subject: [PATCH] add-stage2-ldscripts  + +--- + stage2/Makefile.am      |    2 +- + stage2/Makefile.in      |    2 +- + stage2/stage2.ldscripts |   30 ++++++++++++++++++++++++++++++ + 3 files changed, 32 insertions(+), 2 deletions(-) + create mode 100644 stage2/stage2.ldscripts + +diff --git a/stage2/Makefile.am b/stage2/Makefile.am +index f8e6d42..ea28a4d 100644 +--- a/stage2/Makefile.am ++++ b/stage2/Makefile.am +@@ -55,7 +55,7 @@ noinst_PROGRAMS = pre_stage2.exec start.exec start_eltorito.exec \ + endif + MOSTLYCLEANFILES = $(noinst_PROGRAMS) +  +-PRE_STAGE2_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,8200 ++PRE_STAGE2_LINK = -nostdlib -Wl,-N -Wl,-Tstage2.ldscripts + 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 +diff --git a/stage2/Makefile.in b/stage2/Makefile.in +index d0062bd..7bee2d5 100644 +--- a/stage2/Makefile.in ++++ b/stage2/Makefile.in +@@ -468,7 +468,7 @@ libgrub_a_CFLAGS = $(GRUB_CFLAGS) -I$(top_srcdir)/lib \ + @DISKLESS_SUPPORT_FALSE@noinst_DATA = pre_stage2 start start_eltorito + @DISKLESS_SUPPORT_TRUE@noinst_DATA = pre_stage2 start start_eltorito nbloader pxeloader diskless + MOSTLYCLEANFILES = $(noinst_PROGRAMS) +-PRE_STAGE2_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,8200 ++PRE_STAGE2_LINK = -nostdlib -Wl,-N -Wl,-Tstage2.ldscripts + 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 +diff --git a/stage2/stage2.ldscripts b/stage2/stage2.ldscripts +new file mode 100644 +index 0000000..2c8b8e1 +--- /dev/null ++++ b/stage2/stage2.ldscripts +@@ -0,0 +1,30 @@ ++/* Script for -N: mix text and data on same page; don't align data */ ++OUTPUT_FORMAT("elf32-i386", "elf32-i386", ++	      "elf32-i386") ++OUTPUT_ARCH(i386) ++ENTRY(_start) ++SECTIONS ++{ ++  . = 0x8200; ++  .text           : ++  { ++    _start = .; ++    *(.text .text.* ) ++  } ++  .rodata         : { *(.rodata .rodata.* ) } ++  /* Adjust the address for the data segment.  We want to adjust up to ++     the same address within the page on the next page up.  */ ++  . = .; ++  .data           : { *(.data .data.* ) } ++  __bss_start = .; ++  .bss            : ++  { ++   *(.bss .bss.* ) ++   *(COMMON) ++   . = ALIGN(. != 0 ? 32 / 8 : 1); ++  } ++  . = ALIGN(32 / 8); ++  . = ALIGN(32 / 8); ++  _end = .; PROVIDE (end = .); ++  .comment       0 : { *(.comment) } ++} +--  +1.7.6.153.g78432 + diff --git a/package/grub/patches/040-automake-compat.patch b/package/grub/patches/040-automake-compat.patch new file mode 100644 index 000000000..da13cea7e --- /dev/null +++ b/package/grub/patches/040-automake-compat.patch @@ -0,0 +1,41 @@ +--- a/stage1/Makefile.am ++++ b/stage1/Makefile.am +@@ -1,7 +1,7 @@ + pkglibdir = $(libdir)/$(PACKAGE)/$(host_cpu)-$(host_vendor) +-nodist_pkglib_DATA = stage1 ++nodist_pkgdata_DATA = stage1 +  +-CLEANFILES = $(nodist_pkglib_DATA) ++CLEANFILES = $(nodist_pkgdata_DATA) +  + # We can't use builtins or standard includes. + AM_CCASFLAGS = $(STAGE1_CFLAGS) -fno-builtin -nostdinc +--- a/stage2/Makefile.am ++++ b/stage2/Makefile.am +@@ -32,7 +32,7 @@ pkglibdir = $(libdir)/$(PACKAGE)/$(host_ + EXTRA_PROGRAMS = nbloader.exec pxeloader.exec diskless.exec +  + if DISKLESS_SUPPORT +-pkglib_DATA = stage2 stage2_eltorito e2fs_stage1_5 fat_stage1_5 \ ++pkgdata_DATA = stage2 stage2_eltorito e2fs_stage1_5 fat_stage1_5 \ + 	ffs_stage1_5 iso9660_stage1_5 jfs_stage1_5 minix_stage1_5 \ + 	reiserfs_stage1_5 ufs2_stage1_5 vstafs_stage1_5 xfs_stage1_5 \ + 	nbgrub pxegrub +@@ -43,7 +43,7 @@ noinst_PROGRAMS = pre_stage2.exec start. + 	reiserfs_stage1_5.exec ufs2_stage1_5.exec vstafs_stage1_5.exec \ + 	xfs_stage1_5.exec nbloader.exec pxeloader.exec diskless.exec + else +-pkglib_DATA = stage2 stage2_eltorito e2fs_stage1_5 fat_stage1_5 \ ++pkgdata_DATA = stage2 stage2_eltorito e2fs_stage1_5 fat_stage1_5 \ + 	ffs_stage1_5 iso9660_stage1_5 jfs_stage1_5 minix_stage1_5 \ + 	reiserfs_stage1_5 ufs2_stage1_5 vstafs_stage1_5 xfs_stage1_5 + noinst_DATA = pre_stage2 start start_eltorito +@@ -112,7 +112,7 @@ else + BUILT_SOURCES = stage2_size.h + endif +  +-CLEANFILES = $(pkglib_DATA) $(noinst_DATA) $(BUILT_SOURCES) ++CLEANFILES = $(pkgdata_DATA) $(noinst_DATA) $(BUILT_SOURCES) +  + stage2_size.h: pre_stage2 + 	-rm -f stage2_size.h diff --git a/package/grub/patches/100-add_configure_macros.patch b/package/grub/patches/100-add_configure_macros.patch new file mode 100644 index 000000000..476f778bc --- /dev/null +++ b/package/grub/patches/100-add_configure_macros.patch @@ -0,0 +1,11 @@ +--- a/configure.ac ++++ b/configure.ac +@@ -56,6 +56,8 @@ fi +  + AC_CHECK_TOOL(CC, gcc) + AC_PROG_CC ++AM_PROG_CC_C_O ++AM_PROG_AS + # We need this for older versions of Autoconf. + _AM_DEPENDENCIES(CC) +  diff --git a/package/grub/patches/110-remove_configure_errors.patch b/package/grub/patches/110-remove_configure_errors.patch new file mode 100644 index 000000000..f090aa975 --- /dev/null +++ b/package/grub/patches/110-remove_configure_errors.patch @@ -0,0 +1,38 @@ +--- a/configure.ac ++++ b/configure.ac +@@ -177,26 +177,22 @@ 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 ++# 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 ++#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, diff --git a/package/grub/patches/200-darwin_fixes.patch b/package/grub/patches/200-darwin_fixes.patch new file mode 100644 index 000000000..c5c55a918 --- /dev/null +++ b/package/grub/patches/200-darwin_fixes.patch @@ -0,0 +1,48 @@ +--- a/stage2/asm.S ++++ b/stage2/asm.S +@@ -95,14 +95,16 @@ VARIABLE(stage2_id) + VARIABLE(force_lba) + 	.byte	0 + VARIABLE(version_string) +-	.string VERSION ++	.ascii VERSION ++	.byte	0 + VARIABLE(config_file) + #ifndef STAGE1_5 +-	.string "/boot/grub/menu.lst" ++	.ascii "/boot/grub/menu.lst" + #else   /* STAGE1_5 */ + 	.long	0xffffffff +-	.string "/boot/grub/stage2" ++	.ascii "/boot/grub/stage2" + #endif  /* STAGE1_5 */ ++	.byte	0 +  + 	/* + 	 *  Leave some breathing room for the config file name. +@@ -762,7 +764,9 @@ ENTRY(chain_stage1) + 	call	EXT_C(prot_to_real) + 	.code16 +  +-#ifdef ABSOLUTE_WITHOUT_ASTERISK ++#ifdef __APPLE__ ++	DATA32	ADDR32	ljmp	offset ++#elif defined(ABSOLUTE_WITHOUT_ASTERISK) + 	DATA32	ADDR32	ljmp	(offset) + #else + 	DATA32	ADDR32	ljmp	*(offset) +--- a/stage2/char_io.c ++++ b/stage2/char_io.c +@@ -1345,5 +1345,12 @@ grub_strcpy (char *dest, const char *src + #ifndef GRUB_UTIL + # undef memcpy + /* GCC emits references to memcpy() for struct copies etc.  */ ++#ifdef __APPLE__ ++void *memcpy (void *dest, const void *src, int n) ++{ ++	return grub_memmove(dest, src, n); ++} ++#else + void *memcpy (void *dest, const void *src, int n)  __attribute__ ((alias ("grub_memmove"))); + #endif ++#endif diff --git a/package/grub/patches/210-remove_inline_asm.patch b/package/grub/patches/210-remove_inline_asm.patch new file mode 100644 index 000000000..8eb9fc2c9 --- /dev/null +++ b/package/grub/patches/210-remove_inline_asm.patch @@ -0,0 +1,14 @@ +--- a/stage2/fsys_iso9660.c ++++ b/stage2/fsys_iso9660.c +@@ -83,10 +83,7 @@ iso9660_devread (int sector, int byte_of +  +   sector += (byte_offset >> sector_size_lg2); +   byte_offset &= (buf_geom.sector_size - 1); +-  asm volatile ("shl%L0 %1,%0" +-		: "=r"(sector) +-		: "Ic"((int8_t)(ISO_SECTOR_BITS - sector_size_lg2)), +-		"0"(sector)); ++  sector <<= ISO_SECTOR_BITS - sector_size_lg2; +  + #if !defined(STAGE1_5) +   if (disk_read_hook && debug) | 
