@@ -154,6 +154,28 @@ enable_usb_storage() {
154
154
fi
155
155
}
156
156
157
+ device_has_partitions () {
158
+ local DEVICE=" $1 "
159
+ # fdisk normally says "doesn't contain a valid partition table" for
160
+ # devices that lack a partition table - except for FAT32.
161
+ #
162
+ # FAT32 devices have a volume boot record that looks enough like an MBR
163
+ # to satisfy fdisk. In that case, fdisk prints a partition table header
164
+ # but no partitions.
165
+ #
166
+ # This check covers that: [ $(fdisk -l "$b" | wc -l) -eq 5 ]
167
+ # In both cases the output is 5 lines: 3 about device info, 1 empty line
168
+ # and the 5th will be the table header or the invalid message.
169
+ local DISK_DATA=$( fdisk -l " $DEVICE " )
170
+ if echo " $DISK_DATA " | grep -q " doesn't contain a valid partition table" || \
171
+ [ " $( echo " $DISK_DATA " | wc -l) " -eq 5 ]; then
172
+ # No partition table
173
+ return 1
174
+ fi
175
+ # There is a partition table
176
+ return 0
177
+ }
178
+
157
179
list_usb_storage () {
158
180
TRACE_FUNC
159
181
# List all USB storage devices, including partitions unless we received argument stating we want drives only
@@ -184,16 +206,7 @@ list_usb_storage() {
184
206
# never usable directly, and this allows the "wait for
185
207
# disks" loop in mount-usb to correctly wait for the
186
208
# partitions.
187
- # This check: [ $(fdisk -l "$b" | wc -l) -eq 5 ]
188
- # covers the case of a device without partition table but
189
- # formatted as fat32, which contains a sortof partition table.
190
- # this causes fdisk to not print the invalid partition table
191
- # message and instead it'll print an empty table with header.
192
- # In both cases the output is 5 lines: 3 about device info,
193
- # 1 empty line and the 5th will be the table header or the
194
- # unvalid message.
195
- DISK_DATA=$( fdisk -l " $b " )
196
- if echo " $DISK_DATA " | grep -q " doesn't contain a valid partition table" || [ $( echo " $DISK_DATA " | wc -l) -eq 5 ]; then
209
+ if ! device_has_partitions " $b " ; then
197
210
# No partition table, include this device
198
211
DEBUG " USB storage device without partition table: $b "
199
212
echo " $b "
@@ -520,52 +533,143 @@ verify_checksums() {
520
533
return $?
521
534
}
522
535
536
+ # Check if a device is an LVM2 PV, and if so print the VG name
537
+ find_lvm_vg_name () {
538
+ TRACE_FUNC
539
+ local DEVICE VG
540
+ DEVICE=" $1 "
541
+
542
+ mkdir -p /tmp/root-hashes-gui
543
+ if ! lvm pvs " $DEVICE " > /tmp/root-hashes-gui/lvm_vg 2> /dev/null; then
544
+ # It's not an LVM PV
545
+ return 1
546
+ fi
547
+
548
+ VG=" $( tail -n +2 /tmp/root-hashes-gui/lvm_vg | awk ' {print $2}' ) "
549
+ if [ -z " $VG " ]; then
550
+ DEBUG " Could not find LVM2 VG from lvm pvs output:"
551
+ DEBUG " $( cat /tmp/root-hashes-gui/lvm_vg) "
552
+ return 1
553
+ fi
554
+
555
+ echo " $VG "
556
+ }
557
+
558
+ # If a block device is a partition, check if it is a bios-grub partition on a
559
+ # GPT-partitioned disk.
560
+ is_gpt_bios_grub () {
561
+ TRACE_FUNC
562
+
563
+ local PART_DEV=" $1 " DEVICE NUMBER
564
+
565
+ # Figure out the partitioned device containing this device (if there is
566
+ # one) from /sys/class/block.
567
+ local DEVICE_MATCHES=(" /sys/class/block/" * " /$( basename " $PART_DEV " ) " )
568
+
569
+ DEVICE=" $( echo " ${DEVICE_MATCHES[0]} " | cut -d/ -f5) "
570
+ if [ " ${# DEVICE_MATCHES[@]} " -ne 1 ] || [ " $DEVICE " = " *" ]; then
571
+ return 0
572
+ fi
573
+
574
+ # Extract the partition number
575
+ if ! [[ $( basename " $PART_DEV " ) =~ ([0-9]+)$ ]]; then
576
+ return 0 # Can't figure out the partition number
577
+ fi
578
+
579
+ NUMBER=" ${BASH_REMATCH[1]} "
580
+
581
+ # Now we know the device and partition number, get the type. This is
582
+ # specific to GPT disks, MBR disks are shown differently by fdisk.
583
+ TRACE " $PART_DEV is partition $NUMBER of $DEVICE "
584
+ if [ " $( fdisk -l " /dev/$DEVICE " | awk ' $1 == ' " $NUMBER " ' {print $5}' ) " == grub ]; then
585
+ return 0
586
+ fi
587
+ return 1
588
+ }
589
+
590
+ # Test if a block device could be used as /boot - we can mount it and it
591
+ # contains /boot/grub* files. (Here, the block device could be a partition or
592
+ # an unpartitioned device.)
593
+ #
594
+ # If the device is a partition, its type is also checked. Some common types
595
+ # that we definitely can't mount this way are excluded to silence spurious exFAT
596
+ # errors.
597
+ #
598
+ # Any existing /boot is unmounted. If the device is a reasonable boot device,
599
+ # it's left mounted on /boot.
600
+ mount_possible_boot_device () {
601
+ TRACE_FUNC
602
+
603
+ local BOOT_DEV=" $1 "
604
+ local PARTITION_TYPE
605
+
606
+ # Unmount anything on /boot. Ignore failure since there might not be
607
+ # anything. If there is something mounted and we cannot unmount it for
608
+ # some reason, mount will fail, which is handled.
609
+ umount /boot 2> /dev/null || true
610
+
611
+ # Skip bios-grub partitions on GPT disks, LUKS partitions, and LVM PVs,
612
+ # we can't mount these as /boot.
613
+ if is_gpt_bios_grub " $BOOT_DEV " || cryptsetup isLuks " $BOOT_DEV " ||
614
+ find_lvm_vg_name " $BOOT_DEV " > /dev/null; then
615
+ TRACE " $BOOT_DEV is not a mountable partition for /boot"
616
+ return 1
617
+ fi
618
+
619
+ TRACE " Try mounting $BOOT_DEV as /boot"
620
+ if mount -o ro " $BOOT_DEV " /boot > /dev/null 2>&1 ; then
621
+ if ls -d /boot/grub* > /dev/null 2>&1 ; then
622
+ # This device is a reasonable boot device
623
+ return 0
624
+ fi
625
+ umount /boot || true
626
+ fi
627
+
628
+ return 1
629
+ }
630
+
523
631
# detect and set /boot device
524
632
# mount /boot if successful
525
633
detect_boot_device () {
526
634
TRACE_FUNC
635
+ local devname
527
636
# unmount /boot to be safe
528
637
cd / && umount /boot 2> /dev/null
529
638
530
639
# check $CONFIG_BOOT_DEV if set/valid
531
- if [ -e " $CONFIG_BOOT_DEV " ]; then
532
- if mount -o ro $CONFIG_BOOT_DEV /boot > /dev/null 2>&1 ; then
533
- if ls -d /boot/grub* > /dev/null 2>&1 ; then
534
- # CONFIG_BOOT_DEV is valid device and contains an installed OS
535
- return 0
536
- fi
537
- fi
640
+ if [ -e " $CONFIG_BOOT_DEV " ] && mount_possible_boot_device " $CONFIG_BOOT_DEV " ; then
641
+ # CONFIG_BOOT_DEV is valid device and contains an installed OS
642
+ return 0
538
643
fi
539
644
540
645
# generate list of possible boot devices
541
646
fdisk -l | grep " Disk /dev/" | cut -f2 -d " " | cut -f1 -d " :" > /tmp/disklist
542
647
543
- # filter out extraneous options
544
- > /tmp/boot_device_list
648
+ # Check each possible boot device
545
649
for i in $( cat /tmp/disklist) ; do
546
- # remove block device from list if numeric partitions exist, since not bootable
547
- DEV_NUM_PARTITIONS= $(( $(ls - 1 $i * | wc - l) - 1 ))
548
- if [ ${DEV_NUM_PARTITIONS} -eq 0 ] ; then
549
- echo $i >> /tmp/boot_device_list
650
+ # If the device has partitions, check the partitions instead
651
+ if device_has_partitions " $i " ; then
652
+ devname= " $( basename " $i " ) "
653
+ partitions=( " /sys/class/block/ $devname / $devname " ?* )
550
654
else
551
- ls $i * | tail - ${DEV_NUM_PARTITIONS} >> /tmp/boot_device_list
655
+ partitions=( " $i " ) # Use the device itself
552
656
fi
553
- done
554
-
555
- # iterate thru possible options and check for grub dir
556
- for i in $( cat /tmp/boot_device_list) ; do
557
- umount /boot 2> /dev/null
558
- if mount -o ro $i /boot > /dev/null 2>&1 ; then
559
- if ls -d /boot/grub* > /dev/null 2>&1 ; then
560
- CONFIG_BOOT_DEV=" $i "
657
+ for partition in " ${partitions[@]} " ; do
658
+ partition_dev=/dev/" $( basename " $partition " ) "
659
+ # No sense trying something we already tried above
660
+ if [ " $partition_dev " = " $CONFIG_BOOT_DEV " ]; then
661
+ continue
662
+ fi
663
+ # If this is a reasonable boot device, select it and finish
664
+ if mount_possible_boot_device " $partition_dev " ; then
665
+ CONFIG_BOOT_DEV=" $partition_dev "
561
666
return 0
562
667
fi
563
- fi
668
+ done
564
669
done
565
670
566
671
# no valid boot device found
567
672
echo " Unable to locate /boot files on any mounted disk"
568
- umount /boot 2> /dev/null
569
673
return 1
570
674
}
571
675
0 commit comments