]> code.delx.au - monosys/blob - multiboot-setup
check-pacman-updates: don't fail to exit if up to date
[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 for arch in i386-efi x86_64-efi; do
46 sudo grub-install \
47 --target="$arch" \
48 --no-nvram \
49 --removable \
50 --efi-directory="$MULTIBOOT_MNT" \
51 --boot-directory="$MULTIBOOT_MNT" \
52 "$DISK_DEVICE"
53 done
54 }
55
56 function cmd_mount {
57 set -x
58
59 PARTITION_DEVICE="$(readlink -f /dev/disk/by-label/multiboot)"
60 sudo mkdir -p "$MULTIBOOT_MNT"
61 while sudo umount "$PARTITION_DEVICE" &> /dev/null; do true; done
62 sudo mount "$PARTITION_DEVICE" "$MULTIBOOT_MNT" -o "uid=$(whoami)"
63 }
64
65 function cmd_umount {
66 set -x
67
68 sudo umount "$MULTIBOOT_MNT"
69 sudo rmdir "$MULTIBOOT_MNT"
70 }
71
72 function cmd_add_iso {
73 if [ ! -f "${MULTIBOOT_MNT}/$(basename "${1:-}")" ]; then
74 echo "Usage: $0 add_iso ${MULTIBOOT_MNT}/ubuntu.iso"
75 exit 1
76 fi
77 set -x
78
79 ISO_BASENAME="$(basename "$1")"
80 GRUB_PART_CFG="${MULTIBOOT_MNT}/grub/parts/${ISO_BASENAME}"
81
82 mkdir -p "$(dirname "$GRUB_PART_CFG")"
83
84 if [[ "$ISO_BASENAME" == ubuntu-*-desktop-*.iso ]]; then
85 setup_ubuntu
86 elif [[ "$ISO_BASENAME" == debian-live-*.iso ]]; then
87 setup_debian
88 elif [[ "$ISO_BASENAME" == Fedora-Workstation-Live-*.iso ]]; then
89 setup_fedora
90 elif [[ "$ISO_BASENAME" == archlinux-*.iso ]]; then
91 setup_archlinux
92 elif [[ "$ISO_BASENAME" == FD12*.zip ]]; then
93 setup_freedos
94 else
95 echo "Unsupported ISO! $ISO_BASENAME"
96 fi
97
98 delete_stray_grub_parts
99 print_grub_cfg > "${MULTIBOOT_MNT}/grub/grub.cfg"
100 }
101
102 function setup_ubuntu {
103 cat <<EOT > "$GRUB_PART_CFG"
104 menuentry '$ISO_BASENAME' {
105 loopback loop /$ISO_BASENAME
106 linux (loop)/casper/vmlinuz.efi boot=casper quiet iso-scan/filename=/$ISO_BASENAME
107 initrd (loop)/casper/initrd.lz
108 }
109
110 EOT
111 }
112
113 function setup_debian {
114 cat <<EOT > "$GRUB_PART_CFG"
115 menuentry '$ISO_BASENAME' {
116 loopback loop /$ISO_BASENAME
117 linux (loop)/live/vmlinuz boot=live components findiso=/$ISO_BASENAME
118 initrd (loop)/live/initrd.img
119 }
120
121 EOT
122 }
123
124 function setup_fedora {
125 cat <<EOT > "$GRUB_PART_CFG"
126 menuentry '$ISO_BASENAME' {
127 loopback loop /$ISO_BASENAME
128 linux (loop)/isolinux/vmlinuz root=live:CDLABEL=$(blkid -s LABEL -o value "${MULTIBOOT_MNT}/$ISO_BASENAME") rd.live.image quiet iso-scan/filename=/$ISO_BASENAME
129 initrd (loop)/isolinux/initrd.img
130 }
131
132 EOT
133 }
134
135 function setup_archlinux {
136 cat <<EOT > "$GRUB_PART_CFG"
137 menuentry '$ISO_BASENAME' {
138 loopback loop /$ISO_BASENAME
139 linux (loop)/arch/boot/x86_64/vmlinuz img_label=${PARTITION_LABEL} img_loop=$ISO_BASENAME archisobasedir=arch earlymodules=loop
140 initrd (loop)/arch/boot/x86_64/archiso.img
141 }
142
143 EOT
144 }
145
146 function setup_freedos {
147 install_memdisk
148
149 cat <<EOT > "$GRUB_PART_CFG"
150 menuentry '$ISO_BASENAME' {
151 if [ \${grub_platform} = pc ]; then
152 linux16 /memdisk raw
153 initrd16 /$ISO_BASENAME
154 else
155 echo "FreeDOS only works with BIOS boot."
156 sleep 3
157 fi
158 }
159
160 EOT
161 }
162
163 function install_memdisk {
164 local dest="${MULTIBOOT_MNT}/memdisk"
165
166 if [ -f "$dest" ]; then
167 return
168 fi
169
170 for maybe in /usr/lib/syslinux/bios/memdisk /usr/lib/syslinux/memdisk; do
171 if [ -f "$maybe" ]; then
172 cp "$maybe" "$dest"
173 return
174 fi
175 done
176
177 curl --fail "$SYSLINUX_URL" | \
178 tar xz --strip-components=3 -C "$MULTIBOOT_MNT" \
179 "syslinux-${SYSLINUX_VERSION}/bios/memdisk/memdisk"
180 }
181
182 function delete_stray_grub_parts {
183 pushd "${MULTIBOOT_MNT}/grub/parts" &> /dev/null
184 comm -13 \
185 <(find "${MULTIBOOT_MNT}/" -maxdepth 1 -type f -printf '%f\n'|sort) \
186 <(find "${MULTIBOOT_MNT}/grub/parts/" -type f -printf '%f\n'|sort) \
187 | xargs -d '\n' -r rm
188 popd &> /dev/null
189 }
190
191 function print_grub_cfg {
192 cat <<EOT
193 insmod all_video
194 insmod part_msdos
195 insmod progress
196 search --set=root --label $PARTITION_LABEL
197
198 EOT
199
200 cat "${MULTIBOOT_MNT}/grub/parts/"*
201 }
202
203 CMD="cmd_${1:-}"
204 shift || true
205
206 if [ "$(type -t -- "$CMD")" = "function" ]; then
207 "${CMD}" "$@"
208 else
209 echo "Usage: $0 [format|mount|bootloader|add_iso|umount]"
210 exit 1
211 fi