]> code.delx.au - monosys/blob - multiboot-setup
reboot-no-passphrase supports multiple devices
[monosys] / multiboot-setup
1 #!/bin/bash
2
3 set -eu
4
5 PARTITION_LABEL="multiboot"
6 MULTIBOOT_MNT="/mnt/multiboot"
7 SYSLINUX_VERSION="6.03"
8 SYSLINUX_URL="https://www.kernel.org/pub/linux/utils/boot/syslinux/syslinux-${SYSLINUX_VERSION}.tar.gz"
9
10 function cmd_format {
11 if [ ! -b "${1:-}" ]; then
12 echo "Usage: $0 format /dev/sdX"
13 exit 1
14 fi
15 set -x
16
17 sudo -k
18 DISK_DEVICE="$1"
19 PARTITION_DEVICE="${DISK_DEVICE}1"
20 echo -ne 'label: dos\ntype=c, bootable\n' | sudo sfdisk "$DISK_DEVICE"
21 sudo mkfs.vfat -n "$PARTITION_LABEL" "$PARTITION_DEVICE"
22 }
23
24 function cmd_bootloader {
25 DISK_DEVICE="$(mount|grep /mnt/multiboot|cut -d' ' -f1|sed 's/[0-9]*$//')"
26 if [ ! -b "$DISK_DEVICE" ]; then
27 echo "ERROR! Could not find disk to install bootloader. Try using mount."
28 exit 1
29 fi
30 set -x
31
32 sudo -k
33 install_grub_bios
34 install_grub_efi
35 }
36
37 function install_grub_bios {
38 sudo grub-install \
39 --target=i386-pc \
40 --boot-directory="$MULTIBOOT_MNT" \
41 "$DISK_DEVICE"
42 }
43
44 function install_grub_efi {
45 sudo grub-install \
46 --target=x86_64-efi \
47 --no-nvram \
48 --removable \
49 --efi-directory="$MULTIBOOT_MNT" \
50 --boot-directory="$MULTIBOOT_MNT" \
51 "$DISK_DEVICE"
52 }
53
54 function cmd_mount {
55 set -x
56
57 PARTITION_DEVICE="$(readlink -f /dev/disk/by-label/multiboot)"
58 sudo mkdir -p "$MULTIBOOT_MNT"
59 while sudo umount "$PARTITION_DEVICE" &> /dev/null; do true; done
60 sudo mount "$PARTITION_DEVICE" "$MULTIBOOT_MNT" -o "uid=$(whoami)"
61 }
62
63 function cmd_umount {
64 set -x
65
66 sudo umount "$MULTIBOOT_MNT"
67 sudo rmdir "$MULTIBOOT_MNT"
68 }
69
70 function cmd_add_iso {
71 if [ ! -f "${1:-}" ]; then
72 echo "Usage: $0 add_iso /path/to/ubuntu.iso"
73 exit 1
74 fi
75 set -x
76
77 ISO_FILENAME="$1"
78 ISO_BASENAME="$(basename "$ISO_FILENAME")"
79 GRUB_PART_CFG="${MULTIBOOT_MNT}/grub/parts/${ISO_BASENAME}"
80
81 mkdir -p "$(dirname "$GRUB_PART_CFG")"
82
83 if [[ "$ISO_BASENAME" == ubuntu-*-desktop-*.iso ]]; then
84 setup_ubuntu
85 elif [[ "$ISO_BASENAME" == debian-live-*.iso ]]; then
86 setup_debian
87 elif [[ "$ISO_BASENAME" == Fedora-Workstation-Live-*.iso ]]; then
88 setup_fedora
89 elif [[ "$ISO_BASENAME" == archlinux-*.iso ]]; then
90 setup_archlinux
91 elif [[ "$ISO_BASENAME" == FD12*.zip ]]; then
92 setup_freedos
93 else
94 echo "Unsupported ISO! $ISO_BASENAME"
95 fi
96
97 delete_stray_grub_parts
98 print_grub_cfg > "${MULTIBOOT_MNT}/grub/grub.cfg"
99 }
100
101 function setup_ubuntu {
102 copy_iso_data
103
104 cat <<EOT > "$GRUB_PART_CFG"
105 menuentry '$ISO_BASENAME' {
106 loopback loop /$ISO_BASENAME
107 linux (loop)/casper/vmlinuz.efi boot=casper quiet iso-scan/filename=/$ISO_BASENAME
108 initrd (loop)/casper/initrd.lz
109 }
110
111 EOT
112 }
113
114 function setup_debian {
115 copy_iso_data
116
117 cat <<EOT > "$GRUB_PART_CFG"
118 menuentry '$ISO_BASENAME' {
119 loopback loop /$ISO_BASENAME
120 linux (loop)/live/vmlinuz boot=live components findiso=/$ISO_BASENAME
121 initrd (loop)/live/initrd.img
122 }
123
124 EOT
125 }
126
127 function setup_fedora {
128 copy_iso_data
129
130 cat <<EOT > "$GRUB_PART_CFG"
131 menuentry '$ISO_BASENAME' {
132 loopback loop /$ISO_BASENAME
133 linux (loop)/isolinux/vmlinuz root=live:CDLABEL=$(blkid -s LABEL -o value "$ISO_FILENAME") rd.live.image quiet iso-scan/filename=/$ISO_BASENAME
134 initrd (loop)/isolinux/initrd.img
135 }
136
137 EOT
138 }
139
140 function setup_archlinux {
141 copy_iso_data
142
143 cat <<EOT > "$GRUB_PART_CFG"
144 menuentry '$ISO_BASENAME' {
145 loopback loop /$ISO_BASENAME
146 linux (loop)/arch/boot/x86_64/vmlinuz img_label=${PARTITION_LABEL} img_loop=$ISO_BASENAME archisobasedir=arch earlymodules=loop
147 initrd (loop)/arch/boot/x86_64/archiso.img
148 }
149
150 EOT
151 }
152
153 function setup_freedos {
154 install_memdisk
155 copy_iso_data
156
157 cat <<EOT > "$GRUB_PART_CFG"
158 menuentry '$ISO_BASENAME' {
159 if [ \${grub_platform} = pc ]; then
160 linux16 /memdisk raw
161 initrd16 /$ISO_BASENAME
162 else
163 echo "FreeDOS only works with BIOS boot."
164 sleep 3
165 fi
166 }
167
168 EOT
169 }
170
171 function copy_iso_data {
172 rsync --size-only --progress "$ISO_FILENAME" "${MULTIBOOT_MNT}/"
173 }
174
175 function install_memdisk {
176 local dest="${MULTIBOOT_MNT}/memdisk"
177
178 if [ -f "$dest" ]; then
179 return
180 fi
181
182 for maybe in /usr/lib/syslinux/bios/memdisk /usr/lib/syslinux/memdisk; do
183 if [ -f "$maybe" ]; then
184 cp "$maybe" "$dest"
185 return
186 fi
187 done
188
189 curl --fail "$SYSLINUX_URL" | \
190 tar xz --strip-components=3 -C "$MULTIBOOT_MNT" \
191 "syslinux-${SYSLINUX_VERSION}/bios/memdisk/memdisk"
192 }
193
194 function delete_stray_grub_parts {
195 pushd "${MULTIBOOT_MNT}/grub/parts" &> /dev/null
196 comm -13 \
197 <(find "${MULTIBOOT_MNT}/" -maxdepth 1 -type f -printf '%f\n'|sort) \
198 <(find "${MULTIBOOT_MNT}/grub/parts/" -type f -printf '%f\n'|sort) \
199 | xargs -d '\n' -r rm
200 popd &> /dev/null
201 }
202
203 function print_grub_cfg {
204 cat <<EOT
205 insmod all_video
206 insmod part_msdos
207 insmod progress
208 search --set=root --label $PARTITION_LABEL
209
210 EOT
211
212 cat "${MULTIBOOT_MNT}/grub/parts/"*
213 }
214
215 CMD="cmd_${1:-}"
216 shift || true
217
218 if [ "$(type -t -- "$CMD")" = "function" ]; then
219 "${CMD}" "$@"
220 else
221 echo "Usage: $0 [format|mount|bootloader|add_iso|umount]"
222 exit 1
223 fi