On systems which support multiple boot platforms such as BIOS and EFI, it makes no sense to show menu entries which are not supported by the current boot platform. Menu entries generated from os-prober "chain" boot type use boot sector chainloading which is supported on PC BIOS platform only. Show "chain" menu entries only if boot platform is PC BIOS. Show "efi" menu entries only if boot platform is EFI. This is aimed to allow os-prober to report both EFI and PC BIOS boot loaders regardless of the current boot mode on x86 systems which support both EFI and legacy BIOS boot, in order to generate a config file which can be used with either BIOS or EFI boot. Signed-off-by: Pascal Hambourg <pascal@plouf.fr.eu.org> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
364 lines
12 KiB
Bash
364 lines
12 KiB
Bash
#! /bin/sh
|
|
set -e
|
|
|
|
# grub-mkconfig helper script.
|
|
# Copyright (C) 2006,2007,2008,2009 Free Software Foundation, Inc.
|
|
#
|
|
# GRUB 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 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
prefix="@prefix@"
|
|
exec_prefix="@exec_prefix@"
|
|
datarootdir="@datarootdir@"
|
|
|
|
export TEXTDOMAIN=@PACKAGE@
|
|
export TEXTDOMAINDIR="@localedir@"
|
|
|
|
. "$pkgdatadir/grub-mkconfig_lib"
|
|
|
|
if [ "x${GRUB_DISABLE_OS_PROBER}" = "xtrue" ]; then
|
|
grub_warn "$(gettext_printf "os-prober will not be executed to detect other bootable partitions.\nSystems on them will not be added to the GRUB boot configuration.\nCheck GRUB_DISABLE_OS_PROBER documentation entry.")"
|
|
exit 0
|
|
fi
|
|
|
|
if ! command -v os-prober > /dev/null || ! command -v linux-boot-prober > /dev/null ; then
|
|
# missing os-prober and/or linux-boot-prober
|
|
exit 0
|
|
fi
|
|
|
|
grub_warn "$(gettext_printf "os-prober will be executed to detect other bootable partitions.\nIts output will be used to detect bootable binaries on them and create new boot entries.")"
|
|
|
|
OSPROBED="`os-prober | tr ' ' '^' | paste -s -d ' '`"
|
|
if [ -z "${OSPROBED}" ] ; then
|
|
# empty os-prober output, nothing doing
|
|
exit 0
|
|
fi
|
|
|
|
osx_entry() {
|
|
if [ x$2 = x32 ]; then
|
|
# TRANSLATORS: it refers to kernel architecture (32-bit)
|
|
bitstr="$(gettext "(32-bit)")"
|
|
else
|
|
# TRANSLATORS: it refers to kernel architecture (64-bit)
|
|
bitstr="$(gettext "(64-bit)")"
|
|
fi
|
|
# TRANSLATORS: it refers on the OS residing on device %s
|
|
onstr="$(gettext_printf "(on %s)" "${DEVICE}")"
|
|
cat << EOF
|
|
menuentry '$(echo "${LONGNAME} $bitstr $onstr" | grub_quote)' --class osx --class darwin --class os \$menuentry_id_option 'osprober-xnu-$2-$(grub_get_device_id "${DEVICE}")' {
|
|
EOF
|
|
save_default_entry | grub_add_tab
|
|
prepare_grub_to_access_device ${DEVICE} | grub_add_tab
|
|
cat << EOF
|
|
load_video
|
|
set do_resume=0
|
|
if [ /var/vm/sleepimage -nt10 / ]; then
|
|
if xnu_resume /var/vm/sleepimage; then
|
|
set do_resume=1
|
|
fi
|
|
fi
|
|
if [ \$do_resume = 0 ]; then
|
|
xnu_uuid ${OSXUUID} uuid
|
|
if [ -f /Extra/DSDT.aml ]; then
|
|
acpi -e /Extra/DSDT.aml
|
|
fi
|
|
if [ /kernelcache -nt /System/Library/Extensions ]; then
|
|
$1 /kernelcache boot-uuid=\${uuid} rd=*uuid
|
|
elif [ -f /System/Library/Kernels/kernel ]; then
|
|
$1 /System/Library/Kernels/kernel boot-uuid=\${uuid} rd=*uuid
|
|
xnu_kextdir /System/Library/Extensions
|
|
else
|
|
$1 /mach_kernel boot-uuid=\${uuid} rd=*uuid
|
|
if [ /System/Library/Extensions.mkext -nt /System/Library/Extensions ]; then
|
|
xnu_mkext /System/Library/Extensions.mkext
|
|
else
|
|
xnu_kextdir /System/Library/Extensions
|
|
fi
|
|
fi
|
|
if [ -f /Extra/Extensions.mkext ]; then
|
|
xnu_mkext /Extra/Extensions.mkext
|
|
fi
|
|
if [ -d /Extra/Extensions ]; then
|
|
xnu_kextdir /Extra/Extensions
|
|
fi
|
|
if [ -f /Extra/devprop.bin ]; then
|
|
xnu_devprop_load /Extra/devprop.bin
|
|
fi
|
|
if [ -f /Extra/splash.jpg ]; then
|
|
insmod jpeg
|
|
xnu_splash /Extra/splash.jpg
|
|
fi
|
|
if [ -f /Extra/splash.png ]; then
|
|
insmod png
|
|
xnu_splash /Extra/splash.png
|
|
fi
|
|
if [ -f /Extra/splash.tga ]; then
|
|
insmod tga
|
|
xnu_splash /Extra/splash.tga
|
|
fi
|
|
fi
|
|
}
|
|
EOF
|
|
}
|
|
|
|
used_osprober_linux_ids=
|
|
|
|
if [ "x$GRUB_TOP_LEVEL_OS_PROBER" != x ]; then
|
|
OSPROBED=$(grub_move_to_front "$GRUB_TOP_LEVEL_OS_PROBER" ${OSPROBED})
|
|
fi
|
|
|
|
case "$GRUB_OS_PROBER_SKIP_LIST" in *@/[dD][eE][vV]/*)
|
|
grub_warn "$(gettext_printf "GRUB_OS_PROBER_SKIP_LIST contains deprecated <UUID>@/dev/* notation. The @/dev/* suffix is ignored.")"
|
|
esac
|
|
|
|
for OS in ${OSPROBED} ; do
|
|
DEVICE="`echo ${OS} | cut -d ':' -f 1`"
|
|
LONGNAME="`echo ${OS} | cut -d ':' -f 2 | tr '^' ' '`"
|
|
LABEL="`echo ${OS} | cut -d ':' -f 3 | tr '^' ' '`"
|
|
BOOT="`echo ${OS} | cut -d ':' -f 4`"
|
|
unset UUID
|
|
if [ -n "${GRUB_OS_PROBER_SKIP_LIST}" ] && UUID="`${grub_probe} --target=fs_uuid --device ${DEVICE%@*}`"; then
|
|
SPACE='[[:space:],;]' # regex matching spaces and common separators
|
|
|
|
if [ x"${DEVICE##*@*}" = x ] ; then
|
|
EXPUUID="$UUID@${DEVICE#*@}"
|
|
else
|
|
EXPUUID="$UUID(@/dev/.*)?"
|
|
fi
|
|
|
|
if printf %s " ${GRUB_OS_PROBER_SKIP_LIST} " | grep -Eqie "${SPACE}${EXPUUID}${SPACE}" ; then
|
|
echo "Skipped ${LONGNAME} on ${DEVICE} by user request." >&2
|
|
continue
|
|
fi
|
|
fi
|
|
|
|
BTRFS="`echo ${OS} | cut -d ':' -f 5`"
|
|
if [ "x$BTRFS" = "xbtrfs" ]; then
|
|
BTRFSuuid="`echo ${OS} | cut -d ':' -f 6`"
|
|
BTRFSsubvol="`echo ${OS} | cut -d ':' -f 7`"
|
|
fi
|
|
|
|
if [ -z "${LONGNAME}" ] ; then
|
|
LONGNAME="${LABEL}"
|
|
fi
|
|
|
|
# os-prober returns text string followed by optional counter
|
|
CLASS="--class $(echo "${LABEL}" | LC_ALL=C sed 's,[[:digit:]]*$,,' | cut -d' ' -f1 | tr 'A-Z' 'a-z' | LC_ALL=C sed 's,[^[:alnum:]_],_,g')"
|
|
|
|
gettext_printf "Found %s on %s\n" "${LONGNAME}" "${DEVICE}" >&2
|
|
|
|
case ${BOOT} in
|
|
chain)
|
|
|
|
onstr="$(gettext_printf "(on %s)" "${DEVICE}")"
|
|
cat << EOF
|
|
# This menu entry is supported only on PC BIOS platforms.
|
|
if [ "\$grub_platform" = "pc" ]; then
|
|
menuentry '$(echo "${LONGNAME} $onstr" | grub_quote)' $CLASS --class os \$menuentry_id_option 'osprober-chain-$(grub_get_device_id "${DEVICE}")' {
|
|
EOF
|
|
save_default_entry | grub_add_tab
|
|
prepare_grub_to_access_device ${DEVICE} | grub_add_tab
|
|
|
|
if [ x"`${grub_probe} --device ${DEVICE} --target=partmap`" = xmsdos ]; then
|
|
cat << EOF
|
|
parttool \${root} hidden-
|
|
EOF
|
|
fi
|
|
|
|
case ${LONGNAME} in
|
|
Windows\ Vista*|Windows\ 7*|Windows\ Server\ 2008*)
|
|
;;
|
|
*)
|
|
cat << EOF
|
|
drivemap -s (hd0) \${root}
|
|
EOF
|
|
;;
|
|
esac
|
|
|
|
cat <<EOF
|
|
chainloader +1
|
|
}
|
|
fi
|
|
EOF
|
|
;;
|
|
efi)
|
|
|
|
EFIPATH=${DEVICE#*@}
|
|
DEVICE=${DEVICE%@*}
|
|
onstr="$(gettext_printf "(on %s)" "${DEVICE}")"
|
|
cat << EOF
|
|
# This menu entry is supported only on EFI platforms.
|
|
if [ "\$grub_platform" = "efi" ]; then
|
|
menuentry '$(echo "${LONGNAME} $onstr" | grub_quote)' $CLASS --class os \$menuentry_id_option 'osprober-efi-$(grub_get_device_id "${DEVICE}")' {
|
|
EOF
|
|
save_default_entry | sed -e "s/^/\t/"
|
|
prepare_grub_to_access_device ${DEVICE} | sed -e "s/^/\t/"
|
|
|
|
cat <<EOF
|
|
chainloader ${EFIPATH}
|
|
}
|
|
fi
|
|
EOF
|
|
;;
|
|
linux)
|
|
if [ "x$BTRFS" = "xbtrfs" ]; then
|
|
LINUXPROBED="`linux-boot-prober btrfs ${BTRFSuuid} ${BTRFSsubvol} 2> /dev/null | tr ' ' '^' | paste -s -d ' '`"
|
|
else
|
|
LINUXPROBED="`linux-boot-prober ${DEVICE} 2> /dev/null | tr ' ' '^' | paste -s -d ' '`"
|
|
fi
|
|
prepare_boot_cache=
|
|
boot_device_id=
|
|
is_top_level=true
|
|
title_correction_code=
|
|
OS="${LONGNAME}"
|
|
|
|
for LINUX in ${LINUXPROBED} ; do
|
|
LROOT="`echo ${LINUX} | cut -d ':' -f 1`"
|
|
LBOOT="`echo ${LINUX} | cut -d ':' -f 2`"
|
|
LLABEL="`echo ${LINUX} | cut -d ':' -f 3 | tr '^' ' '`"
|
|
LKERNEL="`echo ${LINUX} | cut -d ':' -f 4`"
|
|
LINITRD="`echo ${LINUX} | cut -d ':' -f 5 | tr '^' ' '`"
|
|
LPARAMS="`echo ${LINUX} | cut -d ':' -f 6- | tr '^' ' '`"
|
|
|
|
if [ -z "${LLABEL}" ] ; then
|
|
LLABEL="${LONGNAME}"
|
|
fi
|
|
|
|
if [ "${LROOT}" != "${LBOOT}" ]; then
|
|
LKERNEL="${LKERNEL#/boot}"
|
|
LINITRD="${LINITRD#/boot}"
|
|
fi
|
|
|
|
onstr="$(gettext_printf "(on %s)" "${DEVICE}")"
|
|
recovery_params="$(echo "${LPARAMS}" | grep single)" || true
|
|
counter=1
|
|
while echo "$used_osprober_linux_ids" | grep 'osprober-gnulinux-$LKERNEL-${recovery_params}-$counter-$boot_device_id' > /dev/null; do
|
|
counter=$((counter+1));
|
|
done
|
|
if [ -z "$boot_device_id" ]; then
|
|
boot_device_id="$(grub_get_device_id "${DEVICE}")"
|
|
fi
|
|
used_osprober_linux_ids="$used_osprober_linux_ids 'osprober-gnulinux-$LKERNEL-${recovery_params}-$counter-$boot_device_id'"
|
|
|
|
if [ -z "${prepare_boot_cache}" ]; then
|
|
prepare_boot_cache="$(prepare_grub_to_access_device ${LBOOT} | grub_add_tab)"
|
|
fi
|
|
|
|
# The GRUB_DISABLE_SUBMENU option used to be different than others since it was
|
|
# mentioned in the documentation that has to be set to 'y' instead of 'true' to
|
|
# enable it. This caused a lot of confusion to users that set the option to 'y',
|
|
# 'yes' or 'true'. This was fixed but all of these values must be supported now.
|
|
if [ "x${GRUB_DISABLE_SUBMENU}" = xyes ] || [ "x${GRUB_DISABLE_SUBMENU}" = xy ]; then
|
|
GRUB_DISABLE_SUBMENU="true"
|
|
fi
|
|
|
|
if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xtrue ]; then
|
|
cat << EOF
|
|
menuentry '$(echo "$OS $onstr" | grub_quote)' $CLASS --class gnu-linux --class gnu --class os \$menuentry_id_option 'osprober-gnulinux-simple-$boot_device_id' {
|
|
EOF
|
|
save_default_entry | grub_add_tab
|
|
printf '%s\n' "${prepare_boot_cache}"
|
|
cat << EOF
|
|
linux ${LKERNEL} ${LPARAMS}
|
|
EOF
|
|
if [ -n "${LINITRD}" ] ; then
|
|
cat << EOF
|
|
initrd ${LINITRD}
|
|
EOF
|
|
fi
|
|
cat << EOF
|
|
}
|
|
EOF
|
|
echo "submenu '$(gettext_printf "Advanced options for %s" "${OS} $onstr" | grub_quote)' \$menuentry_id_option 'osprober-gnulinux-advanced-$boot_device_id' {"
|
|
is_top_level=false
|
|
fi
|
|
title="${LLABEL} $onstr"
|
|
cat << EOF
|
|
menuentry '$(echo "$title" | grub_quote)' --class gnu-linux --class gnu --class os \$menuentry_id_option 'osprober-gnulinux-$LKERNEL-${recovery_params}-$boot_device_id' {
|
|
EOF
|
|
save_default_entry | sed -e "s/^/$grub_tab$grub_tab/"
|
|
printf '%s\n' "${prepare_boot_cache}" | grub_add_tab
|
|
cat << EOF
|
|
linux ${LKERNEL} ${LPARAMS}
|
|
EOF
|
|
if [ -n "${LINITRD}" ] ; then
|
|
cat << EOF
|
|
initrd ${LINITRD}
|
|
EOF
|
|
fi
|
|
cat << EOF
|
|
}
|
|
EOF
|
|
if [ x"$title" = x"$GRUB_ACTUAL_DEFAULT" ] || [ x"Previous Linux versions>$title" = x"$GRUB_ACTUAL_DEFAULT" ]; then
|
|
replacement_title="$(echo "Advanced options for ${OS} $onstr" | sed 's,>,>>,g')>$(echo "$title" | sed 's,>,>>,g')"
|
|
quoted="$(echo "$GRUB_ACTUAL_DEFAULT" | grub_quote)"
|
|
title_correction_code="${title_correction_code}if [ \"x\$default\" = '$quoted' ]; then default='$(echo "$replacement_title" | grub_quote)'; fi;"
|
|
grub_warn "$(gettext_printf "Please don't use old title \`%s' for GRUB_DEFAULT, use \`%s' (for versions before 2.00) or \`%s' (for 2.00 or later)" "$GRUB_ACTUAL_DEFAULT" "$replacement_title" "gnulinux-advanced-$boot_device_id>gnulinux-$version-$type-$boot_device_id")"
|
|
fi
|
|
done
|
|
if [ x"$is_top_level" != xtrue ]; then
|
|
echo '}'
|
|
fi
|
|
echo "$title_correction_code"
|
|
;;
|
|
macosx)
|
|
if [ "${UUID=`${grub_probe} --target=fs_uuid --device ${DEVICE}`}" ]; then
|
|
OSXUUID="${UUID}"
|
|
osx_entry xnu_kernel 32
|
|
osx_entry xnu_kernel64 64
|
|
fi
|
|
;;
|
|
hurd)
|
|
onstr="$(gettext_printf "(on %s)" "${DEVICE}")"
|
|
cat << EOF
|
|
menuentry '$(echo "${LONGNAME} $onstr" | grub_quote)' --class hurd --class gnu --class os \$menuentry_id_option 'osprober-gnuhurd-/boot/gnumach.gz-false-$(grub_get_device_id "${DEVICE}")' {
|
|
EOF
|
|
save_default_entry | grub_add_tab
|
|
prepare_grub_to_access_device ${DEVICE} | grub_add_tab
|
|
grub_device="`${grub_probe} --device ${DEVICE} --target=drive`"
|
|
mach_device="`echo "${grub_device}" | sed -e 's/(\(hd.*\),msdos\(.*\))/\1s\2/'`"
|
|
grub_fs="`${grub_probe} --device ${DEVICE} --target=fs`"
|
|
case "${grub_fs}" in
|
|
*fs) hurd_fs="${grub_fs}" ;;
|
|
*) hurd_fs="${grub_fs}fs" ;;
|
|
esac
|
|
cat << EOF
|
|
multiboot /boot/gnumach.gz root=device:${mach_device}
|
|
module /hurd/${hurd_fs}.static ${hurd_fs} --readonly \\
|
|
--multiboot-command-line='\${kernel-command-line}' \\
|
|
--host-priv-port='\${host-port}' \\
|
|
--device-master-port='\${device-port}' \\
|
|
--exec-server-task='\${exec-task}' -T typed '\${root}' \\
|
|
'\$(task-create)' '\$(task-resume)'
|
|
module /lib/ld.so.1 exec /hurd/exec '\$(exec-task=task-create)'
|
|
}
|
|
EOF
|
|
;;
|
|
minix)
|
|
cat << EOF
|
|
menuentry "${LONGNAME} (on ${DEVICE}, Multiboot)" {
|
|
EOF
|
|
save_default_entry | sed -e "s/^/\t/"
|
|
prepare_grub_to_access_device ${DEVICE} | sed -e "s/^/\t/"
|
|
cat << EOF
|
|
multiboot /boot/image_latest
|
|
}
|
|
EOF
|
|
;;
|
|
*)
|
|
# TRANSLATORS: %s is replaced by OS name.
|
|
gettext_printf "%s is not yet supported by grub-mkconfig.\n" " ${LONGNAME}" >&2
|
|
;;
|
|
esac
|
|
done
|