mirror of
https://github.com/linuxboot/heads.git
synced 2024-12-20 21:43:11 +00:00
8da5d5d723
- modify bash to have it configured with -Os
244 lines
4.7 KiB
Bash
Executable File
244 lines
4.7 KiB
Bash
Executable File
#!/bin/bash
|
|
set -e -o pipefail
|
|
. /etc/functions
|
|
|
|
TRACE "Under /bin/kexec-parse-boot"
|
|
|
|
bootdir="$1"
|
|
file="$2"
|
|
|
|
if [ -z "$bootdir" -o -z "$file" ]; then
|
|
die "Usage: $0 /boot /boot/grub/grub.cfg"
|
|
fi
|
|
|
|
reset_entry() {
|
|
name=""
|
|
kexectype="elf"
|
|
kernel=""
|
|
initrd=""
|
|
modules=""
|
|
append=""
|
|
}
|
|
|
|
filedir=`dirname $file`
|
|
bootdir="${bootdir%%/}"
|
|
bootlen="${#bootdir}"
|
|
appenddir="${filedir:$bootlen}"
|
|
|
|
fix_path() {
|
|
path="$@"
|
|
if [ "${path:0:1}" != "/" ]; then
|
|
path="$appenddir/$path"
|
|
fi
|
|
}
|
|
|
|
# GRUB kernel lines (linux/multiboot) can include a command line. Check whether
|
|
# the file path exists in $bootdir.
|
|
check_path() {
|
|
local checkpath firstval
|
|
checkpath="$1"
|
|
firstval="$(echo "$checkpath" | cut -d\ -f1)"
|
|
if ! [ -r "$bootdir$firstval" ]; then return 1; fi
|
|
return 0
|
|
}
|
|
|
|
echo_entry() {
|
|
if [ -z "$kernel" ]; then return; fi
|
|
|
|
fix_path $kernel
|
|
# The kernel must exist - if it doesn't, ignore this entry, it
|
|
# wouldn't work anyway. This could happen if there was a
|
|
# GRUB variable in the kernel path, etc.
|
|
if ! check_path "$path"; then return; fi
|
|
entry="$name|$kexectype|kernel $path"
|
|
|
|
case "$kexectype" in
|
|
elf)
|
|
if [ -n "$initrd" ]; then
|
|
for init in $(echo $initrd | tr ',' ' '); do
|
|
fix_path $init
|
|
# The initrd must also exist
|
|
if ! check_path "$path"; then return; fi
|
|
entry="$entry|initrd $path"
|
|
done
|
|
fi
|
|
if [ -n "$append" ]; then
|
|
entry="$entry|append $append"
|
|
fi
|
|
;;
|
|
multiboot|xen)
|
|
entry="$entry$modules"
|
|
;;
|
|
*)
|
|
return
|
|
;;
|
|
esac
|
|
|
|
# Double-expand here in case there are variables in the kernel
|
|
# parameters - some configs do this and can boot with empty
|
|
# expansions (Debian Live ISOs use this for loopback boots)
|
|
echo $(eval "echo \"$entry\"")
|
|
}
|
|
|
|
search_entry() {
|
|
case $line in
|
|
menuentry* | MENUENTRY* )
|
|
state="grub"
|
|
reset_entry
|
|
name=`echo $line | tr "'" "\"" | cut -d\" -f 2`
|
|
;;
|
|
|
|
label* | LABEL* )
|
|
state="syslinux"
|
|
reset_entry
|
|
name=`echo $line | cut -c6- `
|
|
esac
|
|
}
|
|
|
|
grub_entry() {
|
|
if [ "$line" = "}" ]; then
|
|
echo_entry
|
|
state="search"
|
|
return
|
|
fi
|
|
|
|
# add info to menuentry
|
|
trimcmd=`echo $line | tr '\t ' ' ' | tr -s ' '`
|
|
cmd=`echo $trimcmd | cut -d\ -f1`
|
|
val=`echo $trimcmd | cut -d\ -f2-`
|
|
case $cmd in
|
|
multiboot*)
|
|
# TODO: differentiate between Xen and other multiboot kernels
|
|
kexectype="xen"
|
|
kernel="$val"
|
|
;;
|
|
module*)
|
|
case $val in
|
|
--nounzip*) val=`echo $val | cut -d\ -f2-` ;;
|
|
esac
|
|
fix_path $val
|
|
modules="$modules|module $path"
|
|
;;
|
|
linux*)
|
|
# Some configs have a device specification in the kernel
|
|
# or initrd path. Assume this would be /boot and remove
|
|
# it. Keep the '/' following the device, since this
|
|
# path is relative to the device root, not the config
|
|
# location.
|
|
kernel=`echo $trimcmd | sed "s/([^)]*)//g" | cut -d\ -f2`
|
|
append=`echo $trimcmd | cut -d\ -f3-`
|
|
;;
|
|
initrd*)
|
|
# Trim off device specification as above
|
|
initrd="$(echo "$val" | sed "s/([^)]*)//g")"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
syslinux_end() {
|
|
# finish menuentry
|
|
|
|
# attempt to parse out of append if missing initrd
|
|
if [ -z "$initrd" ]; then
|
|
newappend=""
|
|
for param in $append; do
|
|
case $param in
|
|
initrd=*)
|
|
initrd=`echo $param | cut -d\= -f2`
|
|
;;
|
|
*) newappend="$newappend $param" ;;
|
|
esac
|
|
done
|
|
append="${newappend##' '}"
|
|
fi
|
|
|
|
appenddir="$(echo $appenddir | cut -d\/ -f -2)"
|
|
echo_entry
|
|
state="search"
|
|
}
|
|
|
|
syslinux_multiboot_append() {
|
|
splitval=`echo "${val// --- /|}" | tr '|' '\n'`
|
|
while read line
|
|
do
|
|
if [ -z "$kernel" ]; then
|
|
kernel="$line"
|
|
else
|
|
fix_path $line
|
|
modules="$modules|module $path"
|
|
fi
|
|
done << EOF
|
|
$splitval
|
|
EOF
|
|
}
|
|
|
|
syslinux_entry() {
|
|
case $line in
|
|
"")
|
|
syslinux_end
|
|
return
|
|
;;
|
|
label* | LABEL* )
|
|
syslinux_end
|
|
search_entry
|
|
return
|
|
;;
|
|
esac
|
|
|
|
# add info to menuentry
|
|
trimcmd=`echo $line | tr '\t ' ' ' | tr -s ' '`
|
|
cmd=`echo $trimcmd | cut -d\ -f1`
|
|
val=`echo $trimcmd | cut -d\ -f2-`
|
|
case $trimcmd in
|
|
menu* | MENU* )
|
|
cmd2=`echo $trimcmd | cut -d \ -f2`
|
|
if [ "$cmd2" = "label" -o "$cmd2" = "LABEL" ]; then
|
|
name=`echo $trimcmd | cut -c11- | tr -d '^'`
|
|
fi
|
|
;;
|
|
linux* | LINUX* | kernel* | KERNEL* )
|
|
case $val in
|
|
# TODO: differentiate between Xen and other multiboot kernels
|
|
*mboot.c32) kexectype="xen" ;;
|
|
*.c32)
|
|
# skip this entry
|
|
state="search"
|
|
;;
|
|
*)
|
|
kernel="${val#"$bootdir"}"
|
|
esac
|
|
;;
|
|
initrd* | INITRD* )
|
|
initrd="${val#"$bootdir"}"
|
|
;;
|
|
append* | APPEND* )
|
|
if [ "$kexectype" = "multiboot" -o "$kexectype" = "xen" ]; then
|
|
syslinux_multiboot_append
|
|
else
|
|
append="$val"
|
|
fi
|
|
;;
|
|
esac
|
|
}
|
|
|
|
state="search"
|
|
while read line
|
|
do
|
|
case $state in
|
|
search)
|
|
search_entry
|
|
;;
|
|
grub)
|
|
grub_entry
|
|
;;
|
|
syslinux)
|
|
syslinux_entry
|
|
;;
|
|
esac
|
|
done < "$file"
|
|
|
|
# handle EOF case
|
|
if [ "$state" = "syslinux" ]; then
|
|
syslinux_end
|
|
fi
|