3 # Syslinux Installer / Updater Script (for BIOS only)
4 # Copyright (C) 2011-2013 Matthew Gyurgyik <pyther@pyther.net>
5 # Copyright (C) 2013 Keshav Padram Amburay <(the) (ddoott) (ridikulus) (ddoott) (rat) (aatt) (gemmaeiil) (ddoott) (ccoomm)>
7 # This program is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU General Public License
9 # as published by the Free Software Foundation; either version 2
10 # of the License, or (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 # 2013-10-23 : Keshav Padram Amburay : Updated script to work with Syslinux 6.02 Arch Linux pkg
26 # 1 - get_boot_device or other function failed
27 # 2 - install/update failed
28 # 3 - set_active failed
29 # 4 - install_mbr failed
34 bios_libpath
="/usr/lib/syslinux/bios"
35 bios_bootpath
="/boot/syslinux"
36 EXTLINUX
="/usr/bin/extlinux"
38 bios_autoupdate_file
="/boot/syslinux/SYSLINUX_AUTOUPDATE"
39 pciids_file
="/usr/share/hwdata/pci.ids"
41 ## Helper functions ##
44 # $2 set (array) haystack
46 local needle
="$1" element
49 [[ $element = $needle ]] && return 0
56 if [[ ! -b "${part}" ]]; then
57 echo >&2 "error: '$part' is not a valid block device!"
62 # catch cases like mmcblk0p1 and loop0p3
63 *[[:digit
:]]p
[[:digit
:]]*)
64 local disk
="${part%p[[:digit:]]}" # get everything before p1
67 local disk
="${part%%[[:digit:]]*}"
70 if [[ ! -b "${disk}" ]]; then
71 echo >&2 "error: '$disk' is not a valid block device!"
77 # return true when blockdevice is an md raid, otherwise return a unset value
78 # get all devices that are part of raid device $1
80 [[ $1 && -f /proc
/mdstat
]] ||
return 1
81 local devmajor
=$
(stat
-c %t
"$1")
87 for slave
in /sys
/class
/block
/${1##*/}/slaves
/*; do
88 source "$slave/uevent"
89 slaves
="$slaves/dev/$DEVNAME "
95 # Check /sys/block to see if device is partitioned
96 # If we have a partitioned block device (sda1) /sys/block/sda1/dev will not exist
97 # However, if we have an unpartitioned block device (sda) /sys/block/sda/dev will exist
102 # If block device uevent file should be found
103 # If a partition is passed in path shouldn't exist
104 if [[ $dev = *cciss
* ]]; then
105 [[ -f /sys
/block
/cciss\
!${dev##*/}/dev
]] && return 1
106 elif [[ $dev = *ida
* ]]; then
107 [[ -f /sys
/block
/ida\
!${dev##*/}/dev
]] && return 1
109 [[ -f /sys
/block
/${dev##*/}/dev
]] && return 1
115 # If EFI PART is present in the first 8 bytes then it must be a GPT disk
117 local partsig
=$
(dd if="$1" skip
=64 bs
=8 count
=1 2>/dev
/null
)
118 [[ $partsig = "EFI PART" ]]
122 # $1 - Block Device, no partitions
125 # Special Exception for cciss controllers
126 if [[ $disk = *cciss
* ]]; then
127 for part
in /dev
/cciss
/${disk##*/}*p
*; do
128 local partnum
="${part##*[[:alpha:]]}"
129 sgdisk
"$disk" --attributes="$partnum":clear:2 &>/dev
/null
131 # Smart 2 Controllers
132 elif [[ $disk = *ida
* ]]; then
133 for part
in /dev
/ida
/${disk##*/}*p
*; do
134 local partnum
="${part##*[[:alpha:]]}"
135 sgdisk
"$disk" --attributes="$partnum":clear:2 &>/dev
/null
138 for part
in /sys
/block
/${disk##*/}/${disk##*/}*; do
139 local partnum
="${part##*[[:alpha:]]}"
140 sgdisk
"$disk" --attributes="$partnum":clear:2 &>/dev
/null
150 This script will install or upgrade Syslinux (for BIOS only)
156 -a Set Boot flag on boot partiton
157 -m Install Syslinux MBR
158 -s Updates Syslinux if /boot/syslinux/SYSLINUX_AUTOUPDATE exists
161 -c Chroot install (ex: -c /mnt)
163 Example Usage: $0 -i -a -m # (install, set boot flag, install mbr)
168 # Trys to find the partition that /boot resides on
169 # This will either be on /boot or / (root)
171 if [[ ! -d "$bios_bootpath" ]]; then
172 echo "Could not find $bios_bootpath"
173 echo "Is boot mounted? Is Syslinux installed?"
177 syslinux_fs
=(ext2 ext3 ext4 btrfs vfat xfs
)
179 # Use DATA from findmnt see rc.sysint for more info
180 if [[ -f /proc
/self
/mountinfo
]]; then
181 read rootdev rootfs
< <(findmnt
-run -t noautofs
-o SOURCE
,FSTYPE
"$CHROOT/")
182 read bootdev bootfs
< <(findmnt
-run -t noautofs
-o SOURCE
,FSTYPE
"$CHROOT/boot")
184 echo "Could not find /proc/self/mountinfo"
185 echo "Are you running a kernel greater than 2.6.24?"
189 if [[ $bootfs ]]; then
190 if ! check_is_in
"$bootfs" "${syslinux_fs[@]}"; then
191 echo "/boot file system is not supported by Syslinux"
195 bootpart
="$(readlink -f "$bootdev")"
196 elif [[ $rootfs ]]; then
197 if ! check_is_in
"$rootfs" "${syslinux_fs[@]}"; then
198 echo "/ (root) file system is not supported by Syslinux"
202 bootpart
="$(readlink -f "$rootdev")"
204 echo "Could not find filesystem on / (root) or /boot."
209 # We store the partition table type either gpt or mbr in var ptb
210 # In rare cases a user could have one raid disk using mbr and another using gpt
211 # In such cases we accept that the output may be incomplete
213 # Calls get_ptb() for $bootpart or for all device in RAID
216 if device_is_raid
"$bootpart"; then
217 slaves
=$
(mdraid_all_slaves
"$bootpart")
219 for slave
in ${slaves[@]}; do
220 local disk
=$
(get_disk
"$slave")
221 device_is_gpt
"$disk" && local ptb
="GPT" ||
local ptb
="MBR"
222 bootdevs
[$slave]="$ptb"
225 local disk
=$
(get_disk
"$bootpart")
226 device_is_gpt
"$disk" && local ptb
="GPT" ||
local ptb
="MBR"
227 bootdevs
[$bootpart]="$ptb"
231 # Function Assumes the boot partition should be marked as active
232 # All other partitions should not have the boot flag set
234 # If any bootdev is a block device without partitions bail
235 # we want to set the boot flag on partitioned disk
236 for dev
in "${!bootdevs[@]}"; do
237 dev_is_part
$dev ||
{ echo "$dev does not contain partition table. Aborting set_active!"; return 1; }
240 # Clear BIOS Bootable Legacy Attribute for GPT drives
241 # In rare cases where a RAID device has slaves on the same block device
242 # Attribute 2 will be cleared for each partition multiple times
243 for dev
in "${!bootdevs[@]}"; do
244 local ptb
="${bootdevs[$dev]}"
245 if [[ "$ptb" = GPT
]]; then
246 local disk
=$
(get_disk
"$dev")
247 clear_gpt_attr2
"$disk"
251 # Set the boot flag on bootdevs (generated from get_boot_devices)
252 for part
in "${!bootdevs[@]}"; do
253 local ptb
="${bootdevs[$part]}"
254 local partnum
="${part##*[[:alpha:]]}"
255 local disk
=$
(get_disk
"$part")
257 if [[ "$ptb" = MBR
]]; then
258 if sfdisk
"$disk" --activate "$partnum" &>/dev
/null
; then
259 echo "Boot Flag Set - $part"
261 echo "FAILED to Set the boot flag on $part"
264 elif [[ "$ptb" = GPT
]]; then
265 if [[ ! -e /usr
/bin
/sgdisk
]]; then
266 echo "FAILED to set attribute Legacy BIOS Bootable. sgdisk is not found - please install 'gptfdisk' package."
270 if sgdisk
"$disk" --attributes="$partnum":set:2 &>/dev
/null
; then
271 echo "Attribute Legacy Bios Bootable Set - $part"
273 echo "FAILED to set attribute Legacy BIOS Bootable on $part"
282 # If any bootdev is a block device without partitions bail
283 # we want to install the mbr to a partitioned disk
284 for dev
in "${!bootdevs[@]}"; do
285 dev_is_part
"$dev" ||
{ echo "$dev does not contain partition table. Aborting MBR install."; return 1; }
288 for part
in "${!bootdevs[@]}"; do
289 local partnum
="${part##*[[:alpha:]]}"
290 local disk
=$
(get_disk
"$part")
291 local ptb
="${bootdevs[$part]}"
293 # We want to install to the root of the block device
294 # If the device is a partition - ABORT!
295 dev_is_part
"$disk" && \
296 { echo "ABORT! MBR installation to partition ($disk)!"; exit 4;}
298 if [[ "$ptb" = MBR
]]; then
299 mbrfile
="$bios_libpath/mbr.bin"
300 elif [[ "$ptb" = GPT
]]; then
301 mbrfile
="$bios_libpath/gptmbr.bin"
304 if dd bs
=440 count
=1 conv
=notrunc
if="$mbrfile" of
="$disk" &> /dev
/null
; then
305 echo "Installed MBR ($mbrfile) to $disk"
307 echo "Error Installing MBR ($mbrfile) to $disk"
315 # Copy all syslinux *.c32 modules to /boot
316 rm "$bios_bootpath"/*.c32
&> /dev
/null
317 cp "$bios_libpath"/*.c32
"$bios_bootpath"/ &> /dev
/null
319 # Copy / Symlink pci.ids if pci.ids exists on the FS
320 if [[ -f "$pciids_file" ]]; then
321 rm "$bios_bootpath/pci.ids" &> /dev
/null
322 cp "$pciids_file" "$bios_bootpath/pci.ids" &> /dev
/null
329 if device_is_raid
"$bootpart" ; then
330 echo "Detected RAID on /boot - installing Syslinux with --raid"
331 "$EXTLINUX" --install "$bios_bootpath" --raid &> /dev
/null
333 "$EXTLINUX" --install "$bios_bootpath" &> /dev
/null
337 echo "Syslinux BIOS install failed"
340 echo "Syslinux BIOS install successful"
343 touch "$CHROOT/$bios_autoupdate_file"
349 if device_is_raid
"$bootpart" ; then
350 echo "Detected RAID on /boot - updating Syslinux with --raid"
351 "$EXTLINUX" --update "$bios_bootpath" --raid &> /dev
/null
353 "$EXTLINUX" --update "$bios_bootpath" &> /dev
/null
357 echo "Syslinux BIOS update failed"
360 echo "Syslinux BIOS update successful"
364 if (( $# == 0 )); then
369 while getopts "c:uihmas" opt
; do
372 CHROOT
=$
(readlink
-e "$OPTARG")
373 if [[ -z $CHROOT ]]; then
374 echo "error: chroot path ``$OPTARG does not exist";
394 # If AUTOUPDATE_FILE does not exist exit the script
395 if [[ -f $bios_autoupdate_file ]]; then
408 if [[ $USAGE ]]; then
413 # Display Usage Information if both Install and Update are passed
414 if [[ $INSTALL && $UPDATE ]]; then
419 # Make sure only root can run our script
420 if (( $
(id
-u) != 0 )); then
421 echo "This script must be run as root" 1>&2
425 # If a chroot dir is path set variables to reflect chroot
426 if [[ "$CHROOT" ]]; then
427 bios_libpath
="$CHROOT$bios_libpath"
428 bios_bootpath
="$CHROOT$bios_bootpath"
429 EXTLINUX
="$CHROOT$EXTLINUX"
432 # Exit if no /boot path exists
433 if ( f
=("$bios_bootpath"/*); (( ! ${#f[@]} )) ); then
434 echo "Error: $bios_bootpath is empty!"
435 echo "Is /boot mounted?"
439 # Get the boot device if any of these options are passed
440 if [[ $INSTALL ||
$UPDATE ||
$SET_ACTIVE ||
$MBR ]]; then
445 if [[ $INSTALL ]]; then
447 elif [[ $UPDATE ]]; then
453 if [[ $SET_ACTIVE ]] ||
[[ $MBR ]]; then
456 if [[ $SET_ACTIVE ]]; then