#!/bin/bash
-set -e
+set -eu
-SYSLINUX_CFG="syslinux/syslinux.cfg"
-REFIND_CFG="System/Library/CoreServices/refind.conf"
+ISO_MNT="/mnt/iso"
+PARTITION_LABEL="multiboot"
+MULTIBOOT_MNT="/mnt/multiboot"
+GRUB_CFG="${MULTIBOOT_MNT}/grub/grub.cfg"
-function setup_bootloader {
- install_syslinux
- install_refind
- rm -rf distros
+function cmd_format {
+ if [ -z "${1:-}" ]; then
+ echo "Usage: $0 format /dev/sdX"
+ exit 1
+ fi
+ set -x
+
+ sudo -k
+ DISK_DEVICE="$1"
+ PARTITION_DEVICE="${DISK_DEVICE}1"
+ echo -ne 'label: dos\ntype=83, bootable\n' | sudo sfdisk "$DISK_DEVICE"
+ sudo mkfs.vfat -n "$PARTITION_LABEL" "$PARTITION_DEVICE"
}
-function install_syslinux {
- rm -rf syslinux
- mkdir syslinux
- cp -R /usr/lib/syslinux/bios/*.c32 syslinux/
+function cmd_bootloader {
+ DISK_DEVICE="$(mount|grep /mnt/multiboot|cut -d' ' -f1|sed 's/[0-9]*$//')"
+ set -x
- echo "UI menu.c32" >> "$SYSLINUX_CFG"
+ sudo -k
+ install_grub_bios
+ install_grub_efi
+ install_grub_cfg
+}
+
+function install_grub_bios {
+ sudo grub-install \
+ --target=i386-pc \
+ --boot-directory="$MULTIBOOT_MNT" \
+ "$DISK_DEVICE"
+}
- echo "Run these commands to configure set up your bootable device:"
- echo " # dosfslabel /dev/sdX1 multiboot"
- echo " # dd bs=440 count=1 if=/usr/lib/syslinux/bios/mbr.bin of=/dev/sdX"
- echo " # extlinux -i -d /<mountpoint>/syslinux"
+function install_grub_efi {
+ sudo grub-install \
+ --target=x86_64-efi \
+ --no-nvram \
+ --removable \
+ --efi-directory="$MULTIBOOT_MNT" \
+ --boot-directory="$MULTIBOOT_MNT" \
+ "$DISK_DEVICE"
}
-function install_refind {
- rm -rf System
- mkdir -p System/Library/CoreServices
- cp /usr/share/refind/refind_x64.efi System/Library/CoreServices/boot.efi
+function install_grub_cfg {
+ mkdir -p "$(dirname "$GRUB_CFG")"
+ cat <<EOT >> "$GRUB_CFG"
+insmod all_video
+insmod part_msdos
+search --set=root --label $PARTITION_LABEL
- echo "timeout 0" >> "$REFIND_CFG"
- echo "textonly true" >> "$REFIND_CFG"
- echo "textmode 1024" >> "$REFIND_CFG"
- echo "scanfor manual" >> "$REFIND_CFG"
+EOT
}
-function setup_iso {
+function cmd_mount {
+ if [ -z "${1:-}" ]; then
+ echo "Usage: $0 mount /dev/sdX1"
+ exit 1
+ fi
+ set -x
+
+ PARTITION_DEVICE="$1"
+ sudo mkdir -p "$MULTIBOOT_MNT"
+ while sudo umount "$PARTITION_DEVICE"; do true; done
+ sudo mount "$PARTITION_DEVICE" "$MULTIBOOT_MNT" -o "uid=$(whoami)"
+}
+
+function cmd_umount {
+ set -x
+
+ sudo umount "$MULTIBOOT_MNT"
+ sudo rmdir "$MULTIBOOT_MNT"
+}
+
+function cmd_add_iso {
+ if [ -z "${1:-}" ]; then
+ echo "Usage: $0 add_iso /path/to/ubuntu.iso"
+ exit 1
+ fi
+ set -x
+
+ ISO_FILE="$1"
mount_iso
- set_boot_vars
- copy_boot_files
- configure_syslinux
- configure_refind
+ setup_iso
umount_iso
}
function mount_iso {
umount_iso
- sudo mount "$ISOFILE" /mnt
+ sudo mkdir -p "$ISO_MNT"
+ sudo mount "$ISO_FILE" "$ISO_MNT"
}
function umount_iso {
- sudo umount /mnt || true
+ sudo umount "$ISO_MNT" || true
+ sudo rmdir "$ISO_MNT" || true
}
-function set_boot_vars {
- if [[ "$ISOFILE" == *ubuntu*.iso ]]; then
- set_ubuntu_boot_vars
- elif [[ "$ISOFILE" == *Fedora*.iso ]]; then
- set_fedora_boot_vars
- elif [[ "$ISOFILE" == *archlinux*.iso ]]; then
- set_archlinux_boot_vars
+function setup_iso {
+ if [[ "$ISO_FILE" == *ubuntu*.iso ]]; then
+ setup_ubuntu
+ elif [[ "$ISO_FILE" == *Fedora*.iso ]]; then
+ setup_fedora
+ elif [[ "$ISO_FILE" == *archlinux*.iso ]]; then
+ setup_archlinux
+ elif [[ "$ISO_FILE" == *FD12CD.iso ]]; then
+ setup_freedos
else
- echo "Unsupported ISO! $ISOFILE"
+ echo "Unsupported ISO! $ISO_FILE"
fi
}
-function set_ubuntu_boot_vars {
- version="$(basename "$ISOFILE" | cut -d- -f2)"
- menulabel="Ubuntu $version"
- unpackdir="distros/ubuntu_$(generate_safe_filename "$version")"
- kernel="/mnt/casper/vmlinuz.efi"
- initrd="/mnt/casper/initrd.lz"
- bootparams="boot=casper iso-scan/filename=/${unpackdir}/$(basename "$ISOFILE")"
-}
+function setup_ubuntu {
+ local version="$(basename "$ISO_FILE" | cut -d- -f2)"
+
+ copy_iso_data "$ISO_FILE" "${MULTIBOOT_MNT}/"
-function set_fedora_boot_vars {
- version="$(basename "$ISOFILE" .iso | sed 's/.*x86_64-//')"
- menulabel="Fedora $version"
- unpackdir="distros/fedora_$(generate_safe_filename "$version")"
- kernel="/mnt/isolinux/vmlinuz"
- initrd="/mnt/isolinux/initrd.img"
- bootparams="root=live:CDLABEL=$(basename "$ISOFILE" .iso) rootfstype=auto iso-scan/filename=/${unpackdir}/$(basename "$ISOFILE")"
+ cat <<EOT >> "$GRUB_CFG"
+menuentry 'Ubuntu $version' {
+ loopback loop /$(basename "$ISO_FILE")
+ linux (loop)/casper/vmlinuz.efi boot=casper quiet iso-scan/filename=/$(basename "$ISO_FILE")
+ initrd (loop)/casper/initrd.lz
}
-function set_archlinux_boot_vars {
- version="$(basename "$ISOFILE" .iso | sed -e 's/archlinux-//' -e 's/-dual//')"
- menulabel="ArchLinux $version"
- unpackdir="distros/archlinux_$(generate_safe_filename "$version")"
- kernel="/mnt/arch/boot/x86_64/vmlinuz"
- initrd="/mnt/arch/boot/x86_64/archiso.img"
- bootparams="img_label=multiboot img_loop=${unpackdir}/$(basename "$ISOFILE") archisobasedir=arch earlymodules=loop"
+EOT
}
-function generate_safe_filename {
- echo -n "$1" | tr -c '[:alnum:]\n' '_'
+function setup_fedora {
+ local version="$(basename "$ISO_FILE" .iso | sed 's/.*x86_64-\([0-9\.]*\)-.*/\1/')"
+
+ copy_iso_data "$ISO_FILE" "${MULTIBOOT_MNT}/"
+
+ cat <<EOT >> "$GRUB_CFG"
+menuentry 'Fedora $version' {
+ loopback loop /$(basename "$ISO_FILE")
+ linux (loop)/isolinux/vmlinuz root=live:CDLABEL=$(blkid -s LABEL -o value "$ISO_FILE") rd.live.image quiet iso-scan/filename=/$(basename "$ISO_FILE")
+ initrd (loop)/isolinux/initrd.img
}
-function copy_boot_files {
- mkdir -p "${unpackdir}"
- ln "$ISOFILE" "${unpackdir}/"
- cp "$kernel" "$initrd" "${unpackdir}/"
+EOT
}
-function configure_syslinux {
- cat <<EOT >> "$SYSLINUX_CFG"
+function setup_archlinux {
+ local version="$(basename "$ISO_FILE" .iso | sed -e 's/archlinux-//' -e 's/-dual//')"
-LABEL $(basename $unpackdir)
-MENU LABEL ${menulabel}
-LINUX /${unpackdir}/$(basename ${kernel})
-INITRD /${unpackdir}/$(basename ${initrd})
-APPEND ${bootparams}
-EOT
+ copy_iso_data "$ISO_FILE" "${MULTIBOOT_MNT}/"
+
+ cat <<EOT >> "$GRUB_CFG"
+menuentry 'Arch Linux $version' {
+ loopback loop /$(basename "$ISO_FILE")
+ linux (loop)/arch/boot/x86_64/vmlinuz img_label=${PARTITION_LABEL} img_loop=$(basename "$ISO_FILE") archisobasedir=arch earlymodules=loop
+ initrd (loop)/arch/boot/x86_64/archiso.img
}
-function configure_refind {
- cat <<EOT >> "$REFIND_CFG"
+EOT
+}
-menuentry "${menulabel}"
- loader /${unpackdir}/$(basename ${kernel})
- initrd /${unpackdir}/$(basename ${initrd})
- options "${bootparams}"
+function setup_freedos {
+ local freedos_dir="${MULTIBOOT_MNT}/freedos/"
+
+ mkdir -p "$freedos_dir"
+ copy_iso_data "${ISO_MNT}/" "$freedos_dir"
+
+ cat <<EOT >> "$GRUB_CFG"
+menuentry 'FreeDOS' {
+ if [ \${grub_platform} = pc ]; then
+ linux16 /freedos/ISOLINUX/MEMDISK
+ initrd16 /freedos/ISOLINUX/FDBOOT.img
+ else
+ echo "FreeDOS only works with BIOS boot."
+ sleep 3
+ fi
}
+
EOT
}
-if [ "$1" = "reset" ]; then
- setup_bootloader
-elif [[ "$1" == *.iso ]]; then
- ISOFILE="$1"
- setup_iso
+function copy_iso_data {
+ local distro_data="$1"
+ local dest="$2"
+
+ rsync --recursive --size-only --progress "$distro_data" "$dest"
+}
+
+CMD="cmd_${1:-}"
+shift || true
+
+if [ "$(type -t -- "$CMD")" = "function" ]; then
+ "${CMD}" "$@"
else
- echo "Usage: $0 [reset|/path/to/ubuntu.iso]"
+ echo "Usage: $0 [format|mount|bootloader|add_iso|umount]"
+ exit 1
fi