heads/initrd/bin/kexec-parse-boot
MrChromebox a075347351
kexec-parse-boot/bls: Strip boot dir from front of grub entries (#804)
Some grub configs/bls entries contain the full paths to the
kernel/initrd files, which the parsers currently fail to handle,
causing a failed boot without any useful error being presented to the user.

To fix this, strip the bootdir prefix from the menu entries when parsing,
should it exist.

Test: build/boot Librem 13v2 w/F32 and bls entries containing absolute paths.

Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
2020-08-24 16:42:33 -04:00

209 lines
3.6 KiB
Bash
Executable File

#!/bin/sh
set -e -o pipefail
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
}
echo_entry() {
if [ "$kexectype" = "elf" ]; then
if [ -z "$kernel" ]; then return; fi
fix_path $kernel
entry="$name|$kexectype|kernel $path"
if [ -n "$initrd" ]; then
fix_path $initrd
entry="$entry|initrd $path"
fi
if [ -n "$append" ]; then
entry="$entry|append $append"
fi
echo $(eval "echo \"$entry\"")
fi
if [ "$kexectype" = "multiboot" -o "$kexectype" = "xen" ]; then
if [ -z "$kernel" ]; then return; fi
fix_path $kernel
echo $(eval "echo \"$name|$kexectype|kernel $path$modules\"")
fi
}
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*)
kernel=`echo $trimcmd | cut -d\ -f2`
append=`echo $trimcmd | cut -d\ -f3-`
;;
initrd*)
initrd="$val"
;;
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
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