From 4e4f8cf4184f1cee61f8b487bd23d749a73fb489 Mon Sep 17 00:00:00 2001 From: James Bunton Date: Fri, 31 Mar 2017 01:24:19 +1100 Subject: [PATCH] multiboot-setup: rewrite, adds awesome * partitions, formats and mounts the device * installs BIOS and EFI bootloader automatically * use rsync to avoid recopying iso files to device * support FreeDOS * use grub instead of refind/syslinux * use grub's loopback feature to read files directly from the iso --- multiboot-setup.sh | 239 ++++++++++++++++++++++++++++----------------- 1 file changed, 152 insertions(+), 87 deletions(-) diff --git a/multiboot-setup.sh b/multiboot-setup.sh index 2eac9e8..5e1ba16 100755 --- a/multiboot-setup.sh +++ b/multiboot-setup.sh @@ -1,134 +1,199 @@ #!/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 //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 <> "$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 <> "$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 <> "$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 <> "$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 <> "$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 <> "$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 <> "$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 -- 2.39.2