Date: Sat, 17 May 2014 11:58:26 -0400 From: Allan Jude <freebsd@allanjude.com> To: roberto@freebsd.org, freebsd-sysinstall@freebsd.org Subject: patch to bsdinstall to support BSD partitions Message-ID: <53778722.9000608@allanjude.com>
next in thread | raw e-mail | index | archive | help
[-- Attachment #1 --]
On some Lenovo machines, booting ZFS off MBR partitions does not work
On the Lenovo X61s that we were able to test on at the BSDCan Hackers
Lounge, we were able to get them to boot properly using a BSD
partitioning scheme instead.
The attached patch makes the following changes:
Add support for BSD partition type
Moved the write of the MBR boot sector to the end of the process to
avoid it being nuked by the pedantic zpool labelclear commands
Change the MBR code to not always create 2 zpools when using MBR. The
user only wants 2 pools (1 unencrypted to boot, and one encrypted for
data) in the case where they enable encryption. Due to the simplicity of
the code in previous versions of bsdinstall, two pools were used to
avoid a problem with the order of the creation of the partitions to
ensure that there was a partition at the front of the drive for the boot
code, and that the swap partition was the 2nd partition (BSD partition 'b')
Some style cleanup to make the flow of the MBR section more
fix an syntax error introduced in the previous patch where a newline was
not escaped
Write the zfsboot code to the two different places require for MBR and
BSD. Write the larger section first because writing the first sector
first seems to make the BSD partition disappear and appear as an empty
MBR (No idea why this was happening, reproduced on two Lenovo laptops)
Resolve variable reuse by renaming 'disksize' in second card to
'usablesize' to avoid disksize being disksize less swap+boot size
Sponsored By: ScaleEngine Inc.
[-- Attachment #2 --]
Index: usr.sbin/bsdinstall/scripts/zfsboot
===================================================================
--- usr.sbin/bsdinstall/scripts/zfsboot (revision 266146)
+++ usr.sbin/bsdinstall/scripts/zfsboot (working copy)
@@ -77,17 +77,17 @@
#
# Create a separate boot pool?
-# NB: Automatically set when using geli(8) or MBR
+# NB: Automatically set when using geli(8)
#
: ${ZFSBOOT_BOOT_POOL=}
#
-# Default name for boot pool when enabled (e.g., geli(8) or MBR)
+# Default name for boot pool when enabled (e.g., geli(8))
#
: ${ZFSBOOT_BOOT_POOL_NAME:=bootpool}
#
-# Default size for boot pool when enabled (e.g., geli(8) or MBR)
+# Default size for boot pool when enabled (e.g., geli(8))
#
: ${ZFSBOOT_BOOT_POOL_SIZE:=2g}
@@ -253,7 +253,7 @@
msg_null_poolname="NULL poolname"
msg_ok="OK"
msg_partition_scheme="Partition Scheme"
-msg_partition_scheme_help="Toggle between GPT and MBR partitioning schemes"
+msg_partition_scheme_help="Toggle between GPT, MBR, and BSD partitioning schemes"
msg_please_enter_a_name_for_your_zpool="Please enter a name for your zpool:"
msg_please_enter_amount_of_swap_space="Please enter amount of swap space (SI-Unit suffixes\nrecommended; e.g., \`2g' for 2 Gigabytes):"
msg_please_select_one_or_more_disks="Please select one or more disks to create a zpool:"
@@ -721,7 +721,7 @@
# Check for unknown partition scheme before proceeding further
case "$ZFSBOOT_PARTITION_SCHEME" in
- ""|MBR|GPT) : known good ;;
+ ""|MBR|GPT|BSD) : known good ;;
*)
f_dprintf "$funcname: %s is an unsupported partition scheme" \
"$ZFSBOOT_PARTITION_SCHEME"
@@ -777,7 +777,7 @@
[ ${swapsize:-0} -gt 0 ] && targetpart=p3
#
- # Prepare boot pool if enabled (e.g., for geli(8))
+ # 3. Prepare boot pool if enabled (e.g., for geli(8))
#
if [ "$ZFSBOOT_BOOT_POOL" ]; then
bootpart=p2 swappart=p3 targetpart=p3
@@ -798,7 +798,7 @@
fi
#
- # 3. Add freebsd-swap partition labeled `swap#'
+ # 4. Add freebsd-swap partition labeled `swap#'
#
if [ ${swapsize:-0} -gt 0 ]; then
f_eval_catch $funcname gpart \
@@ -811,7 +811,7 @@
fi
#
- # 4. Add freebsd-zfs partition labeled `zfs#' for zroot
+ # 5. Add freebsd-zfs partition labeled `zfs#' for zroot
#
f_eval_catch $funcname gpart "$GPART_ADD_LABEL" \
zfs$index freebsd-zfs $disk || return $FAILURE
@@ -819,6 +819,87 @@
/dev/$disk$targetpart
;;
+ BSD) f_dprintf "$funcname: Creating BSD layout..."
+ #
+ # 1. Create BSD layout and write boot sector
+ #
+ f_eval_catch $funcname gpart "$GPART_CREATE" bsd $disk ||
+ return $FAILURE
+
+ bootpart=a swappart=b targetpart=a mbrindex=1
+ #
+ # 2. Prepare boot pool if enabled (e.g., for geli(8))
+ #
+ if [ "$ZFSBOOT_BOOT_POOL" ]; then
+ bootpart=a swappart=b targetpart=d mbrindex=4
+ #
+ # 3. Create an unencrypted boot pool
+ #
+ f_eval_catch $funcname gpart \
+ "$GPART_ADD_INDEX_WITH_SIZE" 1 \
+ freebsd-zfs ${bootsize}b $disk ||
+ return $FAILURE
+ # Pedantically detach bootpart
+ f_eval_catch -d $funcname geli \
+ "$GELI_DETACH_F" \
+ /dev/$disk$bootpart
+ # Pedantically nuke any old labels
+ f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \
+ /dev/$disk$bootpart
+ #
+ # 4. Add freebsd-swap partition
+ #
+ if [ ${swapsize:-0} -gt 0 ]; then
+ f_eval_catch $funcname gpart \
+ "$GPART_ADD_INDEX_WITH_SIZE" 2 \
+ freebsd-swap ${swapsize}b $disk ||
+ return $FAILURE
+ # Pedantically nuke any old labels on the swap
+ f_eval_catch -d $funcname zpool \
+ "$ZPOOL_LABELCLEAR_F" \
+ /dev/$disk$swappart
+ fi
+ #
+ # 5. Add second freebsd-zfs partition for main pool
+ #
+ f_eval_catch $funcname gpart "$GPART_ADD_INDEX" \
+ $mbrindex freebsd-zfs $disk ||
+ return $FAILURE
+ # Pedantically detach targetpart
+ f_eval_catch -d $funcname geli \
+ "$GELI_DETACH_F" \
+ /dev/$disk$targetpart
+ f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \
+ /dev/$disk$targetpart
+ else
+ #
+ # 6. Create and boot off of the main pool
+ #
+ local partsize=$(( $disksize - $swapsize ))
+ f_eval_catch $funcname gpart \
+ "$GPART_ADD_INDEX_WITH_SIZE" $mbrindex \
+ freebsd-zfs ${partsize}b $disk ||
+ return $FAILURE
+ # Pedantically nuke any old labels
+ f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \
+ /dev/$disk$bootpart
+ #
+ # 7. There is no partition after this, so autosize swap
+ #
+ if [ ${swapsize:-0} -gt 0 ]; then
+ f_eval_catch $funcname gpart \
+ "$GPART_ADD_INDEX" 2 \
+ freebsd-swap $disk ||
+ return $FAILURE
+ # Pedantically nuke any old labels on the swap
+ f_eval_catch -d $funcname zpool \
+ "$ZPOOL_LABELCLEAR_F" \
+ /dev/$disk$swappart
+ fi
+ fi
+
+ ;;
+
MBR) f_dprintf "$funcname: Creating MBR layout..."
#
# 1. Create MBR layout (no labels)
@@ -825,8 +906,6 @@
#
f_eval_catch $funcname gpart "$GPART_CREATE" mbr $disk ||
return $FAILURE
- f_eval_catch $funcname gpart "$GPART_BOOTCODE" /boot/mbr \
- $disk || return $FAILURE
#
# 2. Add freebsd slice with all available space
@@ -847,50 +926,86 @@
f_eval_catch $funcname gpart "$GPART_CREATE" BSD ${disk}s1 ||
return $FAILURE
- # NB: zpool will use s1a (no labels)
- bootpart=s1a swappart=s1b targetpart=s1d mbrindex=4
+ bootpart=s1a swappart=s1b targetpart=s1a mbrindex=1
#
- # Always prepare a boot pool on MBR
+ # 4. Prepare boot pool if enabled (e.g., for geli(8))
#
- ZFSBOOT_BOOT_POOL=1
- f_eval_catch $funcname gpart \
- "$GPART_ADD_INDEX_WITH_SIZE" \
- 1 freebsd-zfs ${bootsize}b ${disk}s1 ||
- return $FAILURE
- # Pedantically nuke any old labels
- f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \
- /dev/$disk$bootpart
- if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then
+ if [ "$ZFSBOOT_BOOT_POOL" ]; then
+ bootpart=s1a swappart=s1b targetpart=s1d mbrindex=4
+ #
+ # 5. Create an unencrypted boot pool
+ #
+ f_eval_catch $funcname gpart \
+ "$GPART_ADD_INDEX_WITH_SIZE" 1 \
+ freebsd-zfs ${bootsize}b $disk ||
+ return $FAILURE
+ # Pedantically nuke any old labels
+ f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \
+ /dev/$disk$bootpart
# Pedantically detach targetpart for later
f_eval_catch -d $funcname geli \
- "$GELI_DETACH_F" \
- /dev/$disk$targetpart
- fi
+ "$GELI_DETACH_F" \
+ /dev/$disk$bootpart
+ #
+ # 6. Add freebsd-swap partition
+ #
+ if [ ${swapsize:-0} -gt 0 ]; then
+ f_eval_catch $funcname gpart \
+ "$GPART_ADD_INDEX_WITH_SIZE" 2 \
+ freebsd-swap ${swapsize}b \
+ ${disk}s1 || return $FAILURE
+ # Pedantically nuke any old labels on the swap
+ f_eval_catch -d $funcname zpool \
+ "$ZPOOL_LABELCLEAR_F" \
+ /dev/$disk$swappart
+ fi
+ #
+ # 7. Add second freebsd-zfs partition for main pool
+ #
+ f_eval_catch $funcname gpart "$GPART_ADD_INDEX" \
+ $mbrindex freebsd-zfs ${disk}s1 ||
+ return $FAILURE
+ # Pedantically detach targetpart
+ f_eval_catch -d $funcname geli \
+ "$GELI_DETACH_F" \
+ /dev/$disk$targetpart
+ f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \
+ /dev/$disk$targetpart # Pedantic
- #
- # 4. Add freebsd-swap partition
- #
- if [ ${swapsize:-0} -gt 0 ]; then
+ else
+ #
+ # 8. Create and boot off of the main pool
+ #
+ local partsize=$(( $disksize - $swapsize ))
f_eval_catch $funcname gpart \
- "$GPART_ADD_INDEX_WITH_SIZE" 2 \
- freebsd-swap ${swapsize}b ${disk}s1 ||
- return $FAILURE
- # Pedantically nuke any old labels on the swap
+ "$GPART_ADD_INDEX_WITH_SIZE" $mbrindex \
+ freebsd-zfs ${partsize}b ${disk}s1 ||
+ return $FAILURE
+ # Pedantically nuke any old labels
f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \
- /dev/${disk}s1b
+ /dev/$disk$bootpart
+ #
+ # 9. There is no partition after this, so autosize swap
+ #
+ if [ ${swapsize:-0} -gt 0 ]; then
+ f_eval_catch $funcname gpart \
+ "$GPART_ADD_INDEX" 2 \
+ freebsd-swap ${disk}s1 ||
+ return $FAILURE
+ # Pedantically nuke any old labels on the swap
+ f_eval_catch -d $funcname zpool \
+ "$ZPOOL_LABELCLEAR_F" \
+ /dev/$disk$swappart
+ fi
fi
#
- # 5. Add freebsd-zfs partition for zroot
+ # 10. Install bootcode
#
- f_eval_catch $funcname gpart "$GPART_ADD_INDEX" \
- $mbrindex freebsd-zfs ${disk}s1 || return $FAILURE
- f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \
- /dev/$disk$targetpart # Pedantic
- f_eval_catch $funcname dd "$DD_WITH_OPTIONS" \
- /boot/zfsboot /dev/${disk}s1 count=1 ||
- return $FAILURE
+ f_eval_catch $funcname gpart "$GPART_BOOTCODE" /boot/mbr \
+ $disk || return $FAILURE
+
;;
esac # $ZFSBOOT_PARTITION_SCHEME
@@ -898,6 +1013,7 @@
# Update fstab(5)
if [ "$isswapmirror" ]; then
# This is not the first disk in the mirror, do nothing
+ true
elif [ "$ZFSBOOT_SWAP_ENCRYPTION" -a "$ZFSBOOT_SWAP_MIRROR" ]; then
f_eval_catch $funcname printf "$PRINTF_FSTAB" \
/dev/mirror/swap.eli none swap sw 0 0 \
@@ -1149,7 +1265,7 @@
#
f_dprintf "$funcname: Creating root pool..."
f_eval_catch $funcname zpool "$ZPOOL_CREATE_WITH_OPTIONS" \
- "-o altroot=$BSDINSTALL_CHROOT -O compress=lz4
+ "-o altroot=$BSDINSTALL_CHROOT -O compress=lz4 \
-m none -f" \
"$zroot_name" "$zroot_vdevtype" "$zroot_vdevs" ||
return $FAILURE
@@ -1230,7 +1346,7 @@
fi
done
- # MBR boot loader touch-up
+ # write remainder of boot loader for MBR and BSD
if [ "$ZFSBOOT_PARTITION_SCHEME" = "MBR" ]; then
f_dprintf "$funcname: Updating MBR boot loader on disks..."
# Stick the ZFS boot loader in the "convienient hole" after
@@ -1239,7 +1355,23 @@
f_eval_catch $funcname dd "$DD_WITH_OPTIONS" \
/boot/zfsboot /dev/$disk$bootpart \
"skip=1 seek=1024" || return $FAILURE
+ f_eval_catch $funcname dd "$DD_WITH_OPTIONS" \
+ /boot/zfsboot /dev/${disk}s1 count=1 ||
+ return $FAILURE
done
+ elif [ "$ZFSBOOT_PARTITION_SCHEME" = "BSD" ]; then
+ f_dprintf "$funcname: Updating BSD boot loader on disks..."
+ # Stick the ZFS boot loader in the "convienient hole" after
+ # the ZFS internal metadata
+ # Install the first bit last, else odd things happen
+ for disk in $disks; do
+ f_eval_catch $funcname dd "$DD_WITH_OPTIONS" \
+ /boot/zfsboot /dev/$disk$bootpart \
+ "skip=1 seek=1024" || return $FAILURE
+ f_eval_catch $funcname dd "$DD_WITH_OPTIONS" \
+ /boot/zfsboot /dev/${disk} count=1 ||
+ return $FAILURE
+ done
fi
# Re-import the ZFS pool(s)
@@ -1426,8 +1558,8 @@
$disk $DEVICE_TYPE_DISK device
$device get capacity disksize || continue
[ ${disksize:-0} -ge 0 ] || disksize=0
- disksize=$(( $disksize - $minsize ))
- [ $disksize -lt $minsize ] &&
+ usablesize=$(( $disksize - $minsize ))
+ [ $usablesize -lt $minsize ] &&
teeny_disks="$teeny_disks $disk"
done
if [ "$teeny_disks" ]; then
@@ -1499,9 +1631,11 @@
fi
;;
?" $msg_partition_scheme")
- # Toggle between GPT and MBR
+ # Toggle between GPT, MBR, and BSD
if [ "$ZFSBOOT_PARTITION_SCHEME" = GPT ]; then
ZFSBOOT_PARTITION_SCHEME=MBR
+ elif [ "$ZFSBOOT_PARTITION_SCHEME" = MBR ]; then
+ ZFSBOOT_PARTITION_SCHEME=BSD
else
ZFSBOOT_PARTITION_SCHEME=GPT
fi
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?53778722.9000608>
