[arch-commits] Commit in syslinux/trunk (3 files)

Thomas Bächler thomas at archlinux.org
Sun Feb 27 15:16:15 UTC 2011


    Date: Sunday, February 27, 2011 @ 10:16:15
  Author: thomas
Revision: 111546

syslinux: add syslinux-install_update script

Added:
  syslinux/trunk/syslinux-install_update
  syslinux/trunk/syslinux.install
Modified:
  syslinux/trunk/PKGBUILD

-------------------------+
 PKGBUILD                |   12 -
 syslinux-install_update |  454 ++++++++++++++++++++++++++++++++++++++++++++++
 syslinux.install        |   13 +
 3 files changed, 476 insertions(+), 3 deletions(-)

Modified: PKGBUILD
===================================================================
--- PKGBUILD	2011-02-27 15:09:03 UTC (rev 111545)
+++ PKGBUILD	2011-02-27 15:16:15 UTC (rev 111546)
@@ -4,7 +4,7 @@
 
 pkgname=syslinux
 pkgver=4.03
-pkgrel=2
+pkgrel=3
 arch=('i686' 'x86_64')
 pkgdesc="Collection of boot loaders that boot from FAT, ext2/3/4 and btrfs filesystems, from CDs and via PXE"
 url="http://syslinux.zytor.com/"
@@ -16,12 +16,15 @@
            )
 makedepends=('nasm')
 backup=('boot/syslinux/syslinux.cfg')
+install=syslinux.install
 source=(http://www.kernel.org/pub/linux/utils/boot/syslinux/$pkgname-${pkgver}.tar.bz2
         syslinux-dont-build-dos-windows-targets.patch
-        syslinux.cfg)
+        syslinux.cfg
+        syslinux-install_update)
 sha256sums=('c65567e324f9d1f7f794ae8f9578a0292bbd47d7b8d895a004d2f0152d0bda38'
             '7e9301e37113d8bcddadc3a7d2fd6f3f433ef20ef6fa6df9fe9e256fa8868753'
-            'b4ba8f9daa67ec35da6e05adb610469bc8c4facf488468c1ec3e5860ba75313d')
+            'b4ba8f9daa67ec35da6e05adb610469bc8c4facf488468c1ec3e5860ba75313d'
+            '5586e2f8c27de46629ec2991a56f60dfdbf3e212169e20cf2cf1aa4f10b4d4ba')
 
 build() {
   # Do not try to build syslinux with our default LDFLAGS, it will fail
@@ -40,4 +43,7 @@
 
   # Install the default configuration
   install -D -m644 "$srcdir"/syslinux.cfg "$pkgdir"/boot/syslinux/syslinux.cfg
+  # Install the installation and update script
+  # This script is maintained at git://gist.github.com/772138.git
+  install -D -m755 "$srcdir"/syslinux-install_update "$pkgdir"/usr/sbin/syslinux-install_update
 }

Added: syslinux-install_update
===================================================================
--- syslinux-install_update	                        (rev 0)
+++ syslinux-install_update	2011-02-27 15:16:15 UTC (rev 111546)
@@ -0,0 +1,454 @@
+#!/bin/bash
+#
+# Sylinux Installer / Updater Scripts
+# Copyright (C) 2011  Matthew Gyurgyik <pyther at pyther.net>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+#
+#-----------------
+# Exit Codes:
+#   1 - get_boot_device or other function failed
+#   2 - install/update failed
+#   3 - set_active failed
+#   4 - install_mbr failed
+#
+shopt -s nullglob
+
+libpath="/usr/lib/syslinux"
+bootpath="/boot/syslinux"
+extlinux="/sbin/extlinux"
+
+autoupdate_file=/boot/syslinux/SYSLINUX_AUTOUPDATE
+com32_files=(menu.c32 vesamenu.c32 chain.c32 hdt.c32 reboot.c32 poweroff.com)
+pciids_file=/usr/share/hwdata/pci.ids
+
+## Helper functions ##
+# Taken from libui-sh
+# $1 needle
+# $2 set (array) haystack
+check_is_in() {
+    local needle="$1" element
+    shift
+    for element; do
+        [[ $element = $needle ]] && return 0
+    done
+    return 1
+}
+
+# return true when blockdevice is an md raid, otherwise return a unset value
+# get all devices that are part of raid device $1
+device_is_raid() {
+    [[ $1 && -f /proc/mdstat ]] || return 1
+    local devmajor=$(stat -c %t "$1")
+    (( devmajor == 9 ))
+}
+
+mdraid_all_slaves() {
+    local slave slaves
+    for slave in /sys/class/block/${1##*/}/slaves/*; do
+        source "$slave/uevent"
+        slaves="$slaves/dev/$DEVNAME "
+        unset DEVNAME
+    done
+    echo $slaves
+}
+
+# Check /sys/block to see if device is partitioned
+# If we have a partitioned block device (sda1) /sys/block/sda1/dev will not exist
+# However, if we have an unpartitioned block device (sda) /sys/block/sda/dev will exist
+dev_is_part() {
+    # $1 - blockdevice
+    local dev=$1
+
+    # If block device uevent file should be found
+    # If a partition is passed in path shouldn't exist
+    if [[ $dev = *cciss* ]]; then
+        [[ -f /sys/block/cciss\!${dev##*/}/dev ]] && return 1
+    elif [[ $dev = *ida* ]]; then
+        [[ -f /sys/block/ida\!${dev##*/}/dev ]] && return 1
+    else
+        [[ -f /sys/block/${dev##*/}/dev ]] && return 1
+    fi
+
+    return 0
+}
+
+# If EFI PART is present in the first 8 bytes then it must be a GPT disk
+device_is_gpt() {
+    local partsig=$(dd if="$1" skip=64 bs=8 count=1 2>/dev/null)
+    [[ $partsig = "EFI PART" ]]
+}
+
+clear_gpt_attr2() {
+    # $1 - Block Device, no partitions
+    local disk=$1
+
+    # Special Exception for cciss controllers
+    if [[ $disk = *cciss* ]]; then
+        for part in /dev/cciss/${disk##*/}*p*; do
+            local partnum="${part##*[[:alpha:]]}"
+            sgdisk "$disk" --attributes="$partnum":clear:2 &>/dev/null
+        done
+    # Smart 2 Controllers
+    elif [[ $disk = *ida* ]]; then
+        for part in /dev/ida/${disk##*/}*p*; do
+            local partnum="${part##*[[:alpha:]]}"
+            sgdisk "$disk" --attributes="$partnum":clear:2 &>/dev/null
+        done
+    else
+        for part in  /sys/block/${disk##*/}/${disk##*/}*; do
+            local partnum="${part##*[[:alpha:]]}"
+            sgdisk "$disk" --attributes="$partnum":clear:2 &>/dev/null
+        done
+    fi
+    return 0
+}
+
+usage() {
+cat << EOF
+usage: $0 options
+
+This script will install or upgrade Syslinux
+
+OPTIONS:
+  -h    Show this message
+  -i    Install Syslinux
+  -u    Update Syslinux
+  -a    Set Boot flag on boot partiton
+  -m    Install Syslinux MBR
+  -s    Updates Syslinux if /boot/syslinux/SYSLINUX_AUTOUPDATE exists
+
+ Arguments Required:
+  -c    Chroot install (ex: -c /mnt)
+
+Example Usage: syslinux-install_update.sh -i -a -m (install, set boot flag, install mbr)
+               syslinux-install_update.sh -u (update)
+EOF
+}
+
+# Trys to find the partition that /boot resides on
+# This will either be on /boot or / (root)
+getBoot() {
+    if [[ ! -d "$bootpath" ]]; then
+        echo "Could not find $bootpath"
+        echo "Is boot mounted? Is Syslinux installed?"
+        exit 1
+    fi
+
+    syslinux_fs=(ext2 ext3 ext4 btrfs vfat)
+
+    # Use DATA from findmnt see rc.sysint for more info
+    if [[ -f /proc/self/mountinfo ]]; then
+        read rootdev rootfs < <(findmnt -run -o SOURCE,FSTYPE "$CHROOT/")
+        read bootdev bootfs < <(findmnt -run -o SOURCE,FSTYPE "$CHROOT/boot")
+    else
+        echo "Could not find /proc/self/mountinfo"
+        echo "Are you running a kernel greater than 2.6.24?"
+        exit 1
+    fi
+
+    if [[ $bootfs ]]; then
+        if ! check_is_in "$bootfs" "${syslinux_fs[@]}"; then
+            echo "/boot file system is not supported by Syslinux"
+            exit 1
+        fi
+        boot="boot"
+        bootpart="$bootdev"
+    elif [[ $rootfs ]]; then
+        if ! check_is_in "$rootfs" "${syslinux_fs[@]}"; then
+            echo "/ (root) file system is not supported by Syslinux"
+            exit 1
+        fi
+        boot="root"
+        bootpart="$rootdev"
+    else
+        echo "Could not find filesystem on / (root) or /boot."
+        exit 1
+    fi
+}
+
+# We store the partition table type either gpt or mbr in var ptb
+# In rare cases a user could have one raid disk using mbr and another using gpt
+# In such cases we accept that the output may be incomplete
+
+# Calls get_ptb() for $bootpart or for all device in RAID
+declare -A bootdevs
+get_boot_devices() {
+    if device_is_raid "$bootpart"; then
+        slaves=$(mdraid_all_slaves "$bootpart")
+
+        for slave in ${slaves[@]}; do
+            local disk="${slave%%[[:digit:]]*}"
+            device_is_gpt "$disk" && local ptb="GPT" || local ptb="MBR"
+            bootdevs[$slave]="$ptb"
+        done
+    else
+        local disk="${bootpart%%[[:digit:]]*}"
+        device_is_gpt "$disk" && local ptb="GPT" || local ptb="MBR"
+        bootdevs[$bootpart]="$ptb"
+    fi
+}
+
+# Function Assumes the boot partition should be marked as active
+# All other partitions should not have the boot flag set
+set_active() {
+    # If any bootdev is a block device without partitions bail
+    # we want to set the boot flag on partitioned disk
+    for dev in "${!bootdevs[@]}"; do
+        dev_is_part $dev || { echo "$dev - is a block device. Aborting set_active!"; return 1; }
+    done
+
+    # Clear BIOS Bootable Legacy Attribute for GPT drives
+    # In rare cases where a RAID device has slaves on the same block device
+    # Attribute 2 will be cleared for each partition multiple times
+    for dev in "${!bootdevs[@]}"; do
+        local ptb="${bootdevs[$dev]}"
+        if [[ "$ptb" = GPT ]]; then
+            local disk="${dev%%[[:digit:]]*}" #ex: /dev/sda
+            clear_gpt_attr2 "$disk"
+        fi
+    done
+
+    # Set the boot flag on bootdevs (generated from get_boot_devices)
+    for part in "${!bootdevs[@]}"; do
+        local ptb="${bootdevs[$part]}"
+        local partnum="${part##*[[:alpha:]]}"
+        case "$part" in
+            *[[:digit:]]p[[:digit:]]*)
+                local disk="${part%%p$partnum}" # get everything before p1
+                ;;
+            *)
+                local disk="${part%%[[:digit:]]*}"
+                ;;
+        esac
+
+        if [[ "$ptb" = MBR ]]; then
+            if sfdisk "$disk" -A "$partnum" &>/dev/null; then
+                echo "Boot Flag Set - $part"
+            else
+                echo "FAILED to Set the boot flag on $part"
+                exit 3
+            fi
+        elif [[ "$ptb" = GPT ]]; then
+            if sgdisk "$disk" --attributes="$partnum":set:2 &>/dev/null; then
+                echo "Attribute Legacy Bios Bootable Set - $part"
+            else
+                echo "FAILED to set attribute Legacy BIOS Bootable on $part"
+                exit 3
+            fi
+        fi
+    done
+    return 0
+}
+
+install_mbr() {
+    # If any bootdev is a block device without partitions bail
+    # we want to install the mbr to a partitioned disk
+    for dev in "${!bootdevs[@]}"; do
+        dev_is_part "$dev" || { echo "$dev - is a block device. Aborting MBR install"; return 1; }
+    done
+
+    for part in "${!bootdevs[@]}"; do
+        local partnum="${part##*[[:alpha:]]}"
+        case "$part" in
+            *[[:digit:]]p[[:digit:]]*)
+                local disk="${part%%p$partnum}" # get everything before p1
+                ;;
+            *)
+                local disk="${part%%[[:digit:]]*}"
+                ;;
+        esac
+        local ptb="${bootdevs[$part]}"
+
+        # We want to install to the root of the block device
+        # If the device is a partition - ABORT!
+        dev_is_part "$disk" && \
+        { echo "ABORT! MBR installation to partition ($disk)!"; exit 4;}
+
+        if [[ "$ptb" = MBR ]]; then
+            mbrfile="$libpath/mbr.bin"
+        elif [[ "$ptb" = GPT ]]; then
+            mbrfile="$libpath/gptmbr.bin"
+        fi
+
+        if dd bs=440 count=1 conv=notrunc if="$mbrfile" of="$disk" &> /dev/null; then
+            echo "Installed MBR ($mbrfile) to $disk"
+        else
+            echo "Error Installing MBR ($mbrfile) to $disk"
+            exit 4
+        fi
+    done
+    return 0
+}
+
+_install() {
+    # Find which device contains /boot
+    get_boot_devices
+
+    # Copy files to /boot
+    for file in "${com32_files[@]}"; do
+        # Symlink files even if links exist
+        if [[ "$boot" = root ]]; then
+            ln -s "${libpath#$CHROOT}/$file" "$bootpath/$file" &> /dev/null
+        elif [[ "$boot" = boot ]]; then
+            cp "$libpath/$file" "$bootpath/$file"
+        fi
+    done
+
+    # Copy / Symlink pci.ids if we copy the com32 module and if pci.ids exists in the FS
+    if check_is_in "hdt.c32" "${com32_files[@]}" && [[ -f $pciids_file ]]; then 
+        if [[ "$boot" = root ]]; then
+            ln -s "$pciids_file" "$bootpath/pci.ids" &> /dev/null
+        elif [[ "$boot" = boot ]]; then
+            cp "$pciids_file" "$bootpath/pci.ids" &> /dev/null
+        fi
+    fi
+
+    if device_is_raid "$bootpart"; then
+        echo "Detected RAID on /boot - installing Syslinux with --raid"
+        "$extlinux" --install "$bootpath" -r > /dev/null 2>&1
+    else
+        "$extlinux" --install "$bootpath" > /dev/null 2>&1
+    fi
+
+    if (( $? )); then
+        echo "Syslinux install failed"
+        exit 2
+    else
+        echo "Syslinux install successful"
+    fi
+
+    touch "$CHROOT/$autoupdate_file"
+
+    [[ $SET_ACTIVE ]] && set_active
+
+    [[ $MBR ]] && install_mbr
+}
+
+update() {
+    # Update any com and c32 files in /boot
+    if [[ "$boot" = boot ]]; then
+        for file in "$bootpath"/*.{c32,com}; do
+            file=$(basename "$file")
+            cp "$libpath/$file" "$bootpath/$file" &> /dev/null
+        done
+        if [[ -f "$bootpath/pci.ids" ]]; then
+            cp "$pciids_file" "$bootpath/pci.ids" &> /dev/null
+        fi
+    fi
+
+    if device_is_raid $bootpart; then
+        echo "Detected RAID on /boot - installing Syslinux with --raid"
+        "$extlinux" --update "$bootpath" -r &> /dev/null
+    else
+        "$extlinux" --update "$bootpath" &> /dev/null
+    fi
+
+    if (($?)); then
+        echo "Syslinux update failed"
+        exit 2
+    else
+        echo "Syslinux update successful"
+    fi
+}
+
+# Make sure only root can run our script
+if (( $(id -u) != 0 )); then
+    echo "This script must be run as root" 1>&2
+    exit 1
+fi
+
+if (( $# == 0 )); then
+    usage
+    exit 1
+fi
+
+while getopts "c:uihmas" opt; do
+    case $opt in
+        c)
+            CHROOT=$(readlink -e "$OPTARG")
+            if [[ -z $CHROOT ]]; then
+                echo "error: chroot path ``$OPTARG does not exist";
+                exit 1
+            fi
+            ;;
+        h)
+            usage
+            exit 0
+            ;;
+        i)
+            INSTALL="True"
+            ;;
+        u)
+            UPDATE="True"
+            ;;
+        m)
+            MBR="True"
+            ;;
+        a)
+            SET_ACTIVE="True"
+            ;;
+        s)
+            AUTOUPDATE="True"
+            ;;
+        *)
+            usage
+            exit 1
+            ;;
+    esac
+done
+
+if [[ $INSTALL && $UPDATE ]]; then
+    usage
+    exit 1
+fi
+
+if [[ "$CHROOT" ]]; then
+    libpath="$CHROOT$libpath"
+    bootpath="$CHROOT$bootpath"
+    extlinux="$CHROOT$extlinux"
+fi
+
+[[ "$AUTOUPDATE" && -f $autoupdate_file ]] && UPDATE="True"
+
+if ( f=("$bootpath"/*); (( ! ${#f[@]} )) ); then
+    echo "Error: $bootpath is empty!"
+    echo "Is /boot mounted?"
+    exit 1
+fi
+
+getBoot
+
+#UPDATE is the only function that does not need boot_devices
+[[ $UPDATE ]] && update
+
+# Install will take care of executing get_boot_devices, set_active, and install_mbr
+# Otherwise accept other combonations
+if [[ $INSTALL ]]; then
+    _install
+    exit 0
+elif [[ $SET_ACTIVE ]] || [[ $MBR ]]; then
+    get_boot_devices
+    if [[ $SET_ACTIVE ]]; then
+        set_active || exit $?
+    fi
+    if [[ $MBR ]]; then
+        install_mbr || exit $?
+    fi
+fi
+
+exit 0
+
+# vim: set et sw=4:

Added: syslinux.install
===================================================================
--- syslinux.install	                        (rev 0)
+++ syslinux.install	2011-02-27 15:16:15 UTC (rev 111546)
@@ -0,0 +1,13 @@
+post_install() {
+  echo "==> If you want to use syslinux as your bootloader"
+  echo "==> edit /boot/syslinux/syslinux.cfg and run"
+  echo "==>   # /usr/sbin/syslinux-install_update -i -a -m"
+  echo "==> to install it."
+}
+
+post_upgrade() {
+  # auto-update syslinux if /boot/syslinux/SYSLINUX_AUTOUPDATE exists
+  /usr/sbin/syslinux-install_update -s
+}
+
+# vim:set ts=2 sw=2 et:




More information about the arch-commits mailing list