sortix-mirror/build-aux/iso-grub-cfg.sh

671 lines
13 KiB
Bash
Executable File

#!/bin/sh
# Copyright (c) 2018, 2022 Jonas 'Sortie' Termansen.
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# iso-grub-cfg.sh
# Generate GRUB bootloader configuration for release .iso filesystems.
# Note: This file has detailed documentation in release-iso-bootconfig(7).
set -e
this=$(which -- "$0")
thisdir=$(dirname -- "$this")
directory=
mount=false
platform=
version=
dashdash=
previous_option=
for argument do
if test -n "$previous_option"; then
eval $previous_option=\$argument
previous_option=
continue
fi
case $argument in
*=?*) parameter=$(expr "X$argument" : '[^=]*=\(.*\)' || true) ;;
*=) parameter= ;;
*) parameter=yes ;;
esac
case $dashdash$argument in
--) dashdash=yes ;;
--platform) previous_option=platform ;;
--platform=*) platform=$parameter ;;
--mount) mount=true ;;
--version=*) version=$parameter ;;
--version) previous_option=version ;;
-*) echo "$0: unrecognized option $argument" >&2
exit 1 ;;
*) directory="$argument" ;;
esac
done
if test -n "$previous_option"; then
echo "$0: option '$argument' requires an argument" >&2
exit 1
fi
if test -z "$platform"; then
echo "$0: platform wasn't set with --platform" >&2
exit 1
fi
if test -z "$version"; then
echo "$0: version wasn't set with --version" >&2
exit 1
fi
if test -z "$directory"; then
echo "$0: no directory operand supplied" >&2
exit 1
fi
machine=$(expr x"$platform" : 'x\([^-]*\).*')
maybe_compressed() {
if [ -e "$1.xz" ]; then
echo "$1.xz"
elif [ -e "$1.gz" ]; then
echo "$1.gz"
elif [ -e "$1" ]; then
echo "$1"
fi
}
human_size() {
(export LC_ALL=C; du -bh "$1" 2>/dev/null || du -h "$1") |
sed -E 's/^([^[:space:]]+).*/\1/'
}
portvar() {
echo "$1" | sed -e 's/-/_/g' -e 's/+/x/g'
}
isinset() {
(for port in $2; do
if [ x"$1" = x"$port" ]; then
echo true
exit 0
fi
done
echo false
exit 0)
}
. "$thisdir/ports.conf"
cd "$directory"
kernel=$(maybe_compressed boot/sortix.bin)
if $mount; then
initrd=$(maybe_compressed boot/sortix.initrd)
initrds=$initrd
else
live_initrd=$(maybe_compressed boot/live.initrd)
overlay_initrd=$(maybe_compressed boot/overlay.initrd)
src_initrd=$(maybe_compressed boot/src.initrd)
system_initrd=$(maybe_compressed boot/system.initrd)
initrds="$system_initrd $src_initrd $live_initrd $overlay_initrd"
fi
if $mount; then
ports=
else
ports=$(ls repository |
grep -E '\.tix\.tar\.xz$' |
sed -E 's/\.tix\.tar\.xz$//')
fi
mkdir -p boot/grub
mkdir -p boot/grub/init
echo "furthermore" > boot/grub/init/furthermore
# TODO: Possibly use a 'try' feature to not warn in case it was already unset.
echo "unset require dhclient" > boot/grub/init/network-no-dhclient
echo "require ntpd optional" > boot/grub/init/local-ntpd
echo "require sshd optional" > boot/grub/init/local-sshd
exec > boot/grub/grub.cfg
for hook in \
advanced_menu_post \
advanced_menu_pre \
initrd_post \
kernel_post \
kernel_pre \
menu_post \
menu_pre \
ports_menu \
ports_menu_post \
ports_menu_pre \
ports_menu_sets \
ports_post \
ports_pre \
tix_menu \
tix_menu_post \
tix_menu_pre \
tix_menu_sets \
; do
cat << EOF
function hook_$hook {
true
}
EOF
done
for set in all $sets no; do
cat << EOF
function hook_ports_set_$set {
true
}
function hook_tix_set_$set {
true
}
EOF
done
echo
cat << EOF
insmod part_msdos
insmod ext2
EOF
find . | grep -Eq '\.gz$' && echo "insmod gzio"
find . | grep -Eq '\.xz$' && echo "insmod xzio"
cat << EOF
insmod all_video
if loadfont unicode; then
insmod gfxterm
terminal_output gfxterm
fi
set version="$version"
set machine="$machine"
set mount=$mount
if \$mount; then
chain='-- /sbin/init --target=chain'
else
chain=
fi
set base_menu_title="Sortix \$version for \$machine"
set menu_title="\$base_menu_title"
set timeout=10
set default="0"
if [ -e /boot/random.seed ]; then
no_random_seed=
else
no_random_seed=--no-random-seed
fi
set enable_src=true
set enable_network_drivers=
set enable_dhclient=true
set enable_gui=true
set enable_ntpd=false
set enable_sshd=false
export version
export machine
export mount
export chain
export base_menu_title
export menu_title
export timeout
export default
export no_random_seed
export enable_src
export enable_network_drivers
export enable_dhclient
export enable_gui
export enable_ntpd
export enable_sshd
EOF
if [ -n "$ports" ]; then
echo
for port in $ports; do
printf 'port_%s=true\n' "$(portvar "$port")"
done
for port in $ports; do
printf 'tix_%s=false\n' "$(portvar "$port")"
done
echo
for port in $ports; do
printf 'export port_%s\n' "$(portvar "$port")"
done
for port in $ports; do
printf 'export tix_%s\n' "$(portvar "$port")"
done
fi
echo
echo 'function select_ports_set_no {'
for port in $ports; do
printf " port_%s=false\n" "$(portvar "$port")"
done
printf " hook_port_set_no\n"
echo "}"
for set in $sets; do
echo
set_content=$(eval echo \$set_$set)
echo "function select_ports_set_$set {"
for port in $ports; do
printf " port_%s=%s\n" "$(portvar "$port")" "$(isinset "$port" "$set_content")"
done
printf " hook_port_set_%s\n" "$set"
echo "}"
done
echo
echo 'function select_ports_set_all {'
for port in $ports; do
printf " port_%s=true\n" "$(portvar "$port")"
done
printf " hook_port_set_all\n"
echo "}"
echo
echo 'function select_tix_set_no {'
for port in $ports; do
printf " tix_%s=false\n" "$(portvar "$port")"
done
printf " hook_tix_set_no\n"
echo "}"
for set in $sets; do
echo
set_content=$(eval echo \$set_$set)
echo "function select_tix_set_$set {"
for port in $ports; do
printf " tix_%s=%s\n" "$(portvar "$port")" "$(isinset "$port" "$set_content")"
done
printf " hook_tix_set_%s\n" "$set"
echo "}"
done
echo
echo 'function select_tix_set_all {'
for port in $ports; do
printf " tix_%s=true\n" "$(portvar "$port")"
done
printf " hook_tix_set_all\n"
echo "}"
echo
printf "function load_base {\n"
case $platform in
x86_64-*)
cat << EOF
if ! cpuid -l; then
echo "Error: You cannot run this 64-bit operating system because this" \
"computer has no 64-bit mode."
read
exit
fi
EOF
;;
esac
cat << EOF
hook_kernel_pre
echo -n "Loading /$kernel ($(human_size $kernel)) ... "
multiboot /$kernel \$no_random_seed \$enable_network_drivers \$chain "\$@"
echo done
hook_kernel_post
# TODO: Injecting configuration doesn't work for mounted cdroms.
if ! \$enable_dhclient; then
echo -n "Disabling dhclient ... "
module /boot/grub/init/furthermore --create-to /etc/init/network
module /boot/grub/init/network-no-dhclient --append-to /etc/init/network
echo done
fi
if \$enable_ntpd; then
echo -n "Enabling ntpd ... "
module /boot/grub/init/local-ntpd --append-to /etc/init/local
module /boot/grub/init/furthermore --create-to /etc/init/time
module /boot/grub/init/local-ntpd --append-to /etc/init/time
echo done
fi
if \$enable_sshd; then
echo -n "Enabling sshd ... "
module /boot/grub/init/local-sshd --append-to /etc/init/local
echo done
fi
if [ \$no_random_seed != --no-random-seed ]; then
echo -n "Loading /boot/random.seed (256) ... "
module /boot/random.seed --random-seed
echo done
fi
EOF
for initrd in $initrds; do
if [ "$initrd" = "$src_initrd" ]; then
cat << EOF
if \$enable_src; then
echo -n "Loading /$initrd ($(human_size $initrd)) ... "
module /$initrd
echo done
fi
EOF
else
cat << EOF
echo -n "Loading /$initrd ($(human_size $initrd)) ... "
module /$initrd
echo done
EOF
fi
done
cat << EOF
hook_initrd_post
}
EOF
echo
cat << EOF
function load_ports {
hook_ports_pre
EOF
if [ -z "$ports" ]; then
printf " true\n"
fi
for port in $ports; do
tix=repository/$port.tix.tar.xz
cat << EOF
if \$tix_$(portvar "$port"); then
echo -n "Loading /$tix ($(human_size $tix)) ... "
module --nounzip /$tix --to /$tix
echo done
fi
if \$port_$(portvar "$port"); then
echo -n "Loading /$tix ($(human_size $tix)) ... "
module /$tix --tix
echo done
fi
EOF
done
cat << EOF
hook_ports_post
}
EOF
echo
cat << EOF
function load_sortix {
load_base "\$@"
load_ports
}
EOF
cat << EOF
if [ -e /boot/grub/hooks.cfg ]; then
. /boot/grub/hooks.cfg
fi
. /boot/grub/main.cfg
EOF
exec > boot/grub/main.cfg
menuentry() {
echo
printf "menuentry \"Sortix (%s)\" {\n" "$1"
if [ -n "$2" ]; then
printf " if \$enable_gui; then\n"
printf " load_sortix %s-gui\n" "$2"
printf " else\n"
printf " load_sortix %s\n" "$2"
printf " fi\n"
else
printf " load_sortix\n"
fi
printf "}\n"
}
cat << EOF
menu_title="\$base_menu_title"
hook_menu_pre
EOF
menuentry "live environment" '-- /sbin/init --target=single-user'
menuentry "new installation" '-- /sbin/init --target=sysinstall'
menuentry "upgrade existing installation" '-- /sbin/init --target=sysupgrade'
cat << EOF
if ! $mount; then
menuentry "Select ports..." {
configfile /boot/grub/ports.cfg
}
fi
menuentry "Advanced..." {
configfile /boot/grub/advanced.cfg
}
hook_menu_post
EOF
exec > boot/grub/advanced.cfg
cat << EOF
menuentry "Back..." {
configfile /boot/grub/main.cfg
}
menu_title="\$base_menu_title - Advanced Options"
hook_advanced_menu_pre
if "\$enable_gui"; then
menuentry "Disable GUI" {
enable_gui=false
configfile /boot/grub/advanced.cfg
}
else
menuentry "Enable GUI" {
enable_gui=true
configfile /boot/grub/advanced.cfg
}
fi
if ! $mount; then
if "\$enable_src"; then
menuentry "Disable loading source code" {
enable_src=false
configfile /boot/grub/advanced.cfg
}
else
menuentry "Enable loading source code" {
enable_src=true
configfile /boot/grub/advanced.cfg
}
fi
fi
if [ "\$enable_network_drivers" = --disable-network-drivers ]; then
menuentry "Enable networking drivers" {
enable_network_drivers=
configfile /boot/grub/advanced.cfg
}
else
menuentry "Disable networking drivers" {
enable_network_drivers=--disable-network-drivers
configfile /boot/grub/advanced.cfg
}
fi
if ! $mount; then
if \$enable_dhclient; then
menuentry "Disable DHCP client" {
enable_dhclient=false
configfile /boot/grub/advanced.cfg
}
else
menuentry "Enable DHCP client" {
enable_dhclient=true
configfile /boot/grub/advanced.cfg
}
fi
if \$enable_ntpd; then
menuentry "Disable NTP client" {
enable_ntpd=false
configfile /boot/grub/advanced.cfg
}
else
menuentry "Enable NTP client" {
enable_ntpd=true
configfile /boot/grub/advanced.cfg
}
fi
if \$enable_sshd; then
menuentry "Disable SSH server" {
enable_sshd=false
configfile /boot/grub/advanced.cfg
}
else
menuentry "Enable SSH server" {
enable_sshd=true
configfile /boot/grub/advanced.cfg
}
fi
menuentry "Select binary packages..." {
configfile /boot/grub/tix.cfg
}
fi
hook_advanced_menu_post
EOF
exec > boot/grub/ports.cfg
cat << EOF
menuentry "Back..." {
configfile /boot/grub/main.cfg
}
menu_title="\$base_menu_title - Ports"
hook_ports_menu_pre
menuentry "Load all ports" {
select_ports_set_all
configfile /boot/grub/ports.cfg
}
hook_ports_menu_sets
EOF
for set in $sets; do
echo
set_content=$(eval echo \$set_$set)
printf 'menuentry "Load only '"$set"' ports" {\n'
printf " select_ports_set_%s\n" "$set"
printf ' configfile /boot/grub/ports.cfg\n'
printf '}\n'
done
cat << EOF
menuentry "Load no ports" {
select_ports_set_no
configfile /boot/grub/ports.cfg
}
hook_ports_menu
EOF
for port in $ports; do
cat << EOF
if \$port_$(portvar "$port"); then
menuentry "$port = true" {
port_$(portvar "$port")=false
configfile /boot/grub/ports.cfg
}
else
menuentry "$port = false" {
port_$(portvar "$port")=true
configfile /boot/grub/ports.cfg
}
fi
EOF
done
cat << EOF
hook_ports_menu_post
EOF
exec > boot/grub/tix.cfg
cat << EOF
menuentry "Back..." {
configfile /boot/grub/advanced.cfg
}
menu_title="\$base_menu_title - Binary Packages"
hook_tix_menu_pre
menuentry "Load all binary packages" {
select_tix_set_all
configfile /boot/grub/tix.cfg
}
hook_tix_menu_sets
EOF
for set in $sets; do
echo
set_content=$(eval echo \$set_$set)
printf 'menuentry "Load only '"$set"' binary packages" {\n'
printf " select_tix_set_%s\n" "$set"
printf ' configfile /boot/grub/tix.cfg\n'
printf '}\n'
done
cat << EOF
menuentry "Load no binary packages" {
select_tix_set_no
configfile /boot/grub/tix.cfg
}
hook_tix_menu
EOF
for port in $ports; do
cat << EOF
if \$tix_$(portvar "$port"); then
menuentry "$port = true" {
tix_$(portvar "$port")=false
configfile /boot/grub/tix.cfg
}
else
menuentry "$port = false" {
tix_$(portvar "$port")=true
configfile /boot/grub/tix.cfg
}
fi
EOF
done
cat << EOF
hook_tix_menu_post
EOF