]> code.delx.au - monosys/commitdiff
multiboot-setup: rewrite, adds awesome
authorJames Bunton <jamesbunton@delx.net.au>
Thu, 30 Mar 2017 14:24:19 +0000 (01:24 +1100)
committerJames Bunton <jamesbunton@delx.net.au>
Thu, 30 Mar 2017 15:39:14 +0000 (02:39 +1100)
* 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

index 2eac9e880c33a0c15764ae00fcacd6a98034a4e1..5e1ba16ffbc7cc0847f43fed430cd9ae613e59fb 100755 (executable)
 #!/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