aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCarlo Landmeter <clandmeter@gmail.com>2017-10-19 10:27:08 +0200
committerCarlo Landmeter <clandmeter@gmail.com>2017-10-19 11:03:02 +0200
commit4aeefa0407c2855e9afb1454db1383b3aa24631f (patch)
treed283717f65f514b12c9e92932db55fd53806f4fb
parentc3eeebd0310c79f301636eb6ce271300a8d97ea8 (diff)
downloadalpine-conf-4aeefa0407c2855e9afb1454db1383b3aa24631f.tar.bz2
alpine-conf-4aeefa0407c2855e9afb1454db1383b3aa24631f.tar.xz
setup-disk: add EFI and GPT support
New features: * auto detect EFI boot and install EFI ESP (force with env USE_EFI=1) * allow specifying bootloader by env BOOTLOADER (grub or syslinux) * allow specifying disk label by env DISKLABEL (dos or gpt) TODO: * Make sure MBR is only overwritten on native installs. * Do some more checks to prevent non standard/supported setup like GPT on BIOS installs. TESTS run on ESXi 6.5: Simple native install * syslinux OK * GRUB OK Extended native install * LVM OK * RAID OK * RAID+LVM OK EFI install * Default OK * LVM OK see: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=592834 * RAID NOT SUPPORTED Data install DOS * Default OK * LVM OK Data install GPT * Default OK * LVM OK but: /lib/rc/sh/openrc-run.sh: line 273: can't create /sys/fs/cgroup/openrc/syslog/tasks: nonexistent directory
-rw-r--r--setup-disk.in327
1 files changed, 218 insertions, 109 deletions
diff --git a/setup-disk.in b/setup-disk.in
index 8e0c786..d599efd 100644
--- a/setup-disk.in
+++ b/setup-disk.in
@@ -7,6 +7,8 @@ MBR=${MBR:-"/usr/share/syslinux/mbr.bin"}
ROOTFS=${ROOTFS:-ext4}
BOOTFS=${BOOTFS:-ext4}
VARFS=${VARFS:-ext4}
+BOOTLOADER=${BOOTLOADER:-syslinux}
+DISKLABEL=${DISKLABEL:-dos}
# default location for mounted root
SYSROOT=${SYSROOT:-/mnt}
@@ -67,7 +69,7 @@ enumerate_fstab() {
awk "\$2 ~ /^$escaped_mnt(\/|\$)/ {print \$0}" /proc/mounts | \
sed "s:$mnt:/:g; s: :\t:g" | sed -E 's:/+:/:g' | \
while read fs_spec fs_file fs_vfstype fs_mntops fs_freq fs_passno; do
- if [ "$fs_file" = / ]; then
+ if [ "$fs_file" = / ]; then
fs_passno=1
else
fs_passno=2
@@ -86,19 +88,63 @@ is_lvm() {
lvs "$1" >/dev/null 2>&1
}
+is_efi() {
+ [ -d "/sys/firmware/efi" ] && return 0
+ return 1
+}
+
# Find the disk device from given partition
disk_from_part() {
- # we need convert cciss/c0d0* cciss!c0d0*...
- local i= part=$(echo ${1#/dev/} | sed 's:/:!:g')
- for i in /sys/block/*/$part; do
- i=${i%/*}
- # ...and back from cciss!c0d0 to cciss/c0d0
- if [ -b "/dev/${i##*/}" ]; then
- echo "/dev/${i##*/}" | sed 's:!:/:g'
- return 0
- fi
- done
- return 1
+ local path=${1%/*}
+ local dev=${1##*/}
+ echo $path/$(basename "$(readlink -f "/sys/class/block/$dev/..")")
+}
+
+# $1 partition type (swap,linux,raid,lvm,prep,esp)
+# return partition type id based on table type
+partition_id() {
+ local id
+ if [ "$DISKLABEL" = "gpt" ]; then
+ case "$1" in
+ swap) id=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F ;;
+ linux) id=0FC63DAF-8483-4772-8E79-3D69D8477DE4 ;;
+ raid) id=A19D880F-05FC-4D3B-A006-743F0F84911E ;;
+ lvm) id=E6D6D379-F507-44C2-A23C-238F2A3DF928 ;;
+ prep) id=9E1A2d38-C612-4316-AA26-8B49521E5A8B ;;
+ esp) id=C12A7328-F81F-11D2-BA4B-00A0C93EC93B ;;
+ *) die "Partition id \"$1\" is not supported!" ;;
+ esac
+ elif [ "$DISKLABEL" = "dos" ]; then
+ case "$1" in
+ swap) id=82 ;;
+ linux) id=83 ;;
+ raid) id=fd ;;
+ lvm) id=8e ;;
+ prep) id=41 ;;
+ esp) id=EF ;;
+ *) die "Partition id \"$1\" is not supported!" ;;
+ esac
+ else
+ die "Partition label \"$DISKLABEL\" is not supported!"
+ fi
+ echo $id
+}
+
+# find partitions based on partition type from specified disk
+# type can be any type from partition_id or the literal string "boot"
+find_partitions() {
+ local dev="$1" type="$2" search=
+ case "$type" in
+ boot)
+ search=bootable
+ [ -n "$USE_EFI" ] && search=$(partition_id esp)
+ sfdisk -d "$dev" | awk '/'$search'/ {print $1}'
+ ;;
+ *)
+ search=$(partition_id "$type")
+ sfdisk -d "$dev" | awk '/type='$search'/ {print $1}'
+ ;;
+ esac
}
unpack_apkovl() {
@@ -149,7 +195,7 @@ find_mount_dev() {
}
supported_boot_fs() {
- local supported="ext2 ext3 ext4 btrfs xfs"
+ local supported="ext2 ext3 ext4 btrfs xfs vfat"
local fs=
for fs in $supported; do
[ "$fs" = "$1" ] && return 0
@@ -158,6 +204,13 @@ supported_boot_fs() {
return 1
}
+supported_part_label() {
+ case "$1" in
+ dos|gpt) return 0 ;;
+ *) die "Partition label \"$DISKLABEL\" is not supported!" ;;
+ esac
+}
+
find_volume_group() {
local lv=${1##*/}
lvs --noheadings "$1" | awk '{print $2}'
@@ -202,24 +255,58 @@ has_bootopt() {
return 1
}
-# setup grub bootloader
+# setup GRUB bootloader
setup_grub() {
- local mnt="$1" root="$2" modules="$3" kernel_opts="$4"
- shift 4
- local disks="${@}"
+ local mnt="$1" root="$2" modules="$3" kernel_opts="$4" bootdev="$5"
+ # install GRUB efi mode
+ if [ -n "$USE_EFI" ]; then
+ local target fwa
+ case "$ARCH" in
+ x86_64) target=x86_64-efi ; fwa=x64 ;;
+ x86) target=i386-efi ; fwa=ia32 ;;
+ arm*) target=arm-efi ; fwa=arm ;;
+ aarch64) target=arm64-efi ; fwa=aa64 ;;
+ esac
+ # currently disabling nvram so grub doesnt call efibootmgr
+ # installing to alpine directory so other distros dont overwrite it
+ grub-install --target=$target --efi-directory="$mnt"/boot/efi \
+ --bootloader-id=alpine --boot-directory="$mnt"/boot --no-nvram
+ # fallback mode will use boot/boot${fw arch}.efi
+ install -D "$mnt"/boot/efi/EFI/alpine/grub$fwa.efi \
+ "$mnt"/boot/efi/EFI/boot/boot$fwa.efi
+ # install GRUB for ppc64le
+ elif [ "$ARCH" = "ppc64le" ]; then
+ shift 5
+ local disks="${@}"
+ for disk in $disks; do
+ prep=$(find_partitions "$disk" "prep")
+ echo "Installing grub on $prep"
+ grub-install --boot-directory="$mnt"/boot $prep
+ done
+ # install GRUB in bios mode
+ else
+ local bootdisk=$(disk_from_part $bootdev)
+ case "$ARCH" in
+ x86|x86_64) grub-install --boot-directory="$mnt"/boot \
+ --target=i386-pc $bootdisk ;;
+ *) die "Cannot install GRUB in BIOS mode for $ARCH" ;;
+ esac
+ fi
- for disk in $disks; do
- # install grub
- prep=$(find_prep_partition $disk)
- echo "Installing grub on $prep"
- grub-install --boot-directory="$mnt"/boot/ $prep
- done
- # create grub config
- cat > "$mnt"/boot/grub/grub.cfg <<- EOF
+ # setup GRUB config
+ local kernel
+ case $KERNEL_FLAVOR in
+ vanilla) kernel=vmlinuz ;;
+ *) kernel=vmlinuz-$KERNEL_FLAVOR ;;
+ esac
+
+ # all_video is needed to remove the video error on boot
+ cat > "$mnt"/boot/grub/grub.cfg <<- EOF
set timeout=2
+ insmod all_video
menuentry "Alpine Linux" {
- linux /boot/vmlinuz $modules root=$root $kernel_opts
- initrd /boot/initramfs-$KERNEL_FLAVOR
+ linux /boot/$kernel modules=$modules root=$root $kernel_opts
+ initrd /boot/initramfs-$KERNEL_FLAVOR
}
EOF
}
@@ -251,7 +338,10 @@ install_mounted_root() {
local mnt="$1"
shift 1
local disks="${@}" mnt_boot= boot_fs= root_fs=
- local initfs_features="ata base cdrom ext2 ext3 ext4 keymap kms mmc raid scsi usb virtio nvme"
+ local initfs_features=$(. /etc/mkinitfs/mkinitfs.conf >/dev/null 2>&1 && echo "$features")
+ if [ -z "$initfs_features" ]; then
+ initfs_features="ata base cdrom ext2 ext3 ext4 keymap kms mmc raid scsi usb virtio nvme"
+ fi
local pvs= dev= rootdev= bootdev= extlinux_raidopt= root= modules=
local kernel_opts="quiet"
@@ -361,10 +451,11 @@ install_mounted_root() {
# remove the installed db in case its there so we force re-install
rm -f "$mnt"/var/lib/apk/installed "$mnt"/lib/apk/db/installed
echo "Installing system on $rootdev:"
- case "$ARCH" in
- ppc64le) setup_grub "$mnt" "$root" "$modules" "$kernel_opts" $disks;;
- *) setup_syslinux "$mnt" "$root" "$modules" "$kernel_opts" "$bootdev";;
- esac
+ case "$BOOTLOADER" in
+ grub) setup_grub "$mnt" "$root" "$modules" "$kernel_opts" "$bootdev" $disks ;;
+ syslinux) setup_syslinux "$mnt" "$root" "$modules" "$kernel_opts" "$bootdev" ;;
+ *) die "Bootloader \"$BOOTLOADER\" not supported!" ;;
+ esac
# apk reads config from target root so we need to copy the config
mkdir -p "$mnt"/etc/apk/keys/
@@ -485,9 +576,21 @@ stop_all_raid() {
done
}
+select_bootloader() {
+ local bootloader=syslinux
+ if [ "$ARCH" = "ppc64le" ]; then
+ bootloader=grub-ieee1275
+ elif [ -n "$USE_EFI" ]; then
+ bootloader=grub-efi
+ elif [ "$BOOTLOADER" = "grub" ]; then
+ bootloader=grub-bios
+ fi
+ echo "$bootloader"
+}
+
# install needed programs
init_progs() {
- local raidpkg= lvmpkg= fs= fstools=
+ local raidpkg= lvmpkg= fs= fstools= grub=
[ -n "$USE_RAID" ] && raidpkg="mdadm"
[ -n "$USE_LVM" ] && lvmpkg="lvm2"
for fs in $BOOTFS $ROOTFS $VARFS; do
@@ -538,57 +641,33 @@ confirm_erase() {
# setup partitions on given disk dev in $1.
# usage: setup_partitions <diskdev> size1,type1 [size2,type2 ...]
setup_partitions() {
- local diskdev="$1"
+ local diskdev="$1" start=1M line=
shift
+ supported_part_label "$DISKLABEL" || return 1
- echo "Initializing partitions on $diskdev..."
-
- # new disks does not have an DOS signature in sector 0
- # this makes sfdisk complain. We can workaround this by letting
- # fdisk create that DOS signature, by just do a "w", a write.
- # http://bugs.alpinelinux.org/issues/show/145
- echo "w" | fdisk $diskdev >/dev/null
-
- # fix the MBR while here so extlinux can boot
- if [ -f "$MBR" ]; then
+ # initialize MBR for syslinux only
+ # FIXME: this should only by run by native install
+ if [ "$BOOTLOADER" = "syslinux" ] && [ -f "$MBR" ]; then
cat "$MBR" > $diskdev
fi
- local start=1M
- local line=
# create new partitions
(
for line in "$@"; do
echo "$start,$line"
start=
done
- ) | sfdisk --quiet $diskdev >/dev/null || return 1
+ ) | sfdisk --quiet --label $DISKLABEL $diskdev
# create device nodes if not exist
mdev -s
}
-# find the bootable partition on given disk
-find_boot_partition() {
- sfdisk -d $1 | awk '/bootable/ {print $1}'
-}
-
-# find partition from PReP type on given disk
-find_prep_partition() {
- sfdisk -d $1 | awk '/type=41/ {print $1}'
-}
-
-# find the partition(s) for LVM
-# this is not marked as bootable and is type 8e
-find_lvm_partition() {
- local type=8e
- sfdisk -d $1 | grep -v bootable | awk "/(Id|type)=$type/ {print \$1}"
-}
-
# set up optional raid and create filesystem on boot device.
setup_boot_dev() {
- local disks="$@" disk= bootdev= mkfs_args="-q"
- local part=$(for disk in $disks; do find_boot_partition $disk; done)
+ local disks="$@" disk= bootdev= mkfs_args=
+ [ "$BOOTFS" != "vfat" ] && mkfs_args="-q"
+ local part=$(for disk in $disks; do find_partitions "$disk" "boot"; done)
set -- $part
bootdev=$1
[ -z "$bootdev" ] && return 1
@@ -627,13 +706,12 @@ setup_boot_dev() {
# $2 = partition type
# $3... = disk devices
find_nth_non_boot_parts() {
- local idx=$1
- local id=$2
- local disk=
- shift
- shift
- for disk in $@; do
- sfdisk -d $disk | grep -v bootable \
+ local idx=$1 id=$2 disk= type=bootable
+ shift 2
+ local disks="$@"
+ [ -n "$USE_EFI" ] && type=$(partition_id esp)
+ for disk in $disks; do
+ sfdisk -d $disk | grep -v $type \
| awk "/(Id|type)=$id/ { i++; if (i==$idx) print \$1 }"
done
}
@@ -649,7 +727,8 @@ setup_non_boot_raid_dev() {
shift
local level=1
local missing=
- local raid_parts=$(find_nth_non_boot_parts $idx "fd" $@)
+ local pid=$(partition_id raid)
+ local raid_parts=$(find_nth_non_boot_parts $idx $pid $@)
set -- $raid_parts
# how many disks do we have?
case $# in
@@ -672,7 +751,7 @@ setup_lvm_volume_group() {
setup_non_boot_raid_dev /dev/md1 $@ || return 1
lvmdev=/dev/md1
else
- lvmdev=$(find_lvm_partition $1)
+ lvmdev=$(find_partitions "$1" "lvm")
fi
# be quiet on success
@@ -751,21 +830,19 @@ data_only_disk_install_lvm() {
local diskdev=
local vgname=vg0
local var_dev=/dev/$vgname/lv_var
- local lvm_part_type="8e"
- local part_type=$lvm_part_type
+ local lvm_part_type=$(partition_id lvm)
local size=
init_progs || return 1
confirm_erase $@ || return 1
if [ "$USE_RAID" ]; then
- # the paritition type for raid is "fd"
- part_type="fd"
+ lvm_part_type=$(partition_id raid)
stop_all_raid
fi
for diskdev in "$@"; do
- setup_partitions $diskdev "${size}${size:+M},$part_type" || return 1
+ setup_partitions $diskdev "${size}${size:+M},$lvm_part_type" || return 1
done
setup_lvm_volume_group $vgname $@ || return 1
@@ -779,8 +856,8 @@ data_only_disk_install_lvm() {
data_only_disk_install() {
local diskdev=
local var_dev=
- local var_part_type="83"
- local swap_part_type=82
+ local var_part_type=$(partition_id linux)
+ local swap_part_type=$(partition_id swap)
local size=
local swap_dev= var_dev=
@@ -788,8 +865,8 @@ data_only_disk_install() {
confirm_erase $@ || return 1
if [ "$USE_RAID" ]; then
- var_part_type="fd"
- swap_part_type="fd"
+ var_part_type=$(partition_id raid)
+ swap_part_type=$(partition_id raid)
stop_all_raid
fi
@@ -805,8 +882,8 @@ data_only_disk_install() {
swap_dev=/dev/md1
var_dev=/dev/md2
else
- swap_dev=$(find_nth_non_boot_parts 1 82 $@)
- var_dev=$(find_nth_non_boot_parts 1 83 $@)
+ swap_dev=$(find_nth_non_boot_parts 1 "$swap_part_type" $@)
+ var_dev=$(find_nth_non_boot_parts 1 "$var_part_type" $@)
fi
[ $SWAP_SIZE -gt 0 ] && setup_swap_dev $swap_dev
setup_var $var_dev
@@ -821,10 +898,14 @@ setup_root() {
mkfs.$ROOTFS $MKFS_OPTS_ROOT $mkfs_args "$root_dev"
mkdir -p "$SYSROOT"
mount -t $ROOTFS $root_dev "$SYSROOT" || return 1
- if [ -n "$boot_dev" ]; then
+ if [ -n "$boot_dev" ] && [ -z "$USE_EFI" ]; then
mkdir -p "$SYSROOT"/boot
mount -t $BOOTFS $boot_dev "$SYSROOT"/boot || return 1
fi
+ if [ -n "$boot_dev" ] && [ -n "$USE_EFI" ]; then
+ mkdir -p "$SYSROOT"/boot/efi
+ mount -t $BOOTFS $boot_dev "$SYSROOT"/boot/efi || return 1
+ fi
setup_mdadm_conf
install_mounted_root "$SYSROOT" "$disks" || return 1
@@ -837,20 +918,26 @@ setup_root() {
native_disk_install_lvm() {
local diskdev= vgname=vg0
- local lvm_part_type="8e"
- local boot_part_type="83"
+ local lvm_part_type=$(partition_id lvm)
+ local boot_part_type=$(partition_id linux)
local boot_size=${BOOT_SIZE:-100}
local lvm_size=
local root_dev=/dev/$vgname/lv_root
- init_progs syslinux || return 1
+ init_progs $(select_bootloader) || return 1
confirm_erase $@ || return 1
if [ -n "$USE_RAID" ]; then
- boot_part_type="fd"
- lvm_part_type="fd"
+ boot_part_type=$(partition_id raid)
+ lvm_part_type=$(partition_id raid)
stop_all_raid
fi
+
+ if [ -n "$USE_EFI" ]; then
+ [ -n "$USE_RAID" ] && die "EFI boot is not supported on RAID disks"
+ boot_part_type=$(partition_id esp)
+ fi
+
for diskdev in "$@"; do
setup_partitions $diskdev \
"${boot_size}M,$boot_part_type,*" \
@@ -868,27 +955,30 @@ native_disk_install_lvm() {
}
native_disk_install() {
- local prep_part_type="41" root_part_type="83" swap_part_type="82" boot_part_type="83"
+ local prep_part_type=$(partition_id prep)
+ local root_part_type=$(partition_id linux)
+ local swap_part_type=$(partition_id swap)
+ local boot_part_type=$(partition_id linux)
local prep_size=8
local boot_size=${BOOT_SIZE:-100}
local swap_size=${SWAP_SIZE}
local root_size=
local root_dev= boot_dev= swap_dev=
- local bootloader=
-
- case "$ARCH" in
- ppc64le) bootloader=grub-ieee1275;;
- *) bootloader=syslinux;;
- esac
- init_progs $bootloader || return 1
+ init_progs $(select_bootloader) || return 1
confirm_erase $@ || return 1
if [ -n "$USE_RAID" ]; then
- boot_part_type="fd"
- root_part_type="fd"
- swap_part_type="fd"
+ boot_part_type=$(partition_id raid)
+ root_part_type=$(partition_id raid)
+ swap_part_type=$(partition_id raid)
stop_all_raid
fi
+
+ if [ -n "$USE_EFI" ]; then
+ [ -n "$USE_RAID" ] && die "EFI boot is not supported on RAID disks"
+ boot_part_type=$(partition_id esp)
+ fi
+
for diskdev in "$@"; do
if [ "$ARCH" = "ppc64le" ]; then
setup_partitions $diskdev \
@@ -916,7 +1006,7 @@ native_disk_install() {
swap_dev=/dev/md1
root_dev=/dev/md2
else
- swap_dev=$(find_nth_non_boot_parts 1 82 $@)
+ swap_dev=$(find_nth_non_boot_parts 1 "$swap_part_type" $@)
local index=
case "$ARCH" in
# use the second non botable partition on ppc64le,
@@ -924,7 +1014,7 @@ native_disk_install() {
ppc64le) index=2;;
*) index=1;;
esac
- root_dev=$(find_nth_non_boot_parts $index 83 $@)
+ root_dev=$(find_nth_non_boot_parts $index "$root_part_type" $@)
fi
[ $SWAP_SIZE -gt 0 ] && setup_swap_dev $swap_dev
@@ -1028,10 +1118,20 @@ usage() {
-s Use SWAPSIZE MB instead of autodetecting swap size (Use 0 to disable swap)
-v Be more verbose about what is happening
+ If BOOTLOADER is specified, the specified bootloader will be used.
+ If no bootloader is specified, the default bootloader is syslinux(extlinux)
+ except when EFI is detected or explicitly set by USE_EFI which will select grub.
+ Supported bootloaders are: grub, syslinux
+
+ If DISKLABEL is specified, the specified partition label will be used.
+ if no partition label is specified, the default label will be dos
+ except when EFI is detected or explicitly set by USE_EFI which will select gpt.
+ Supported partition labels are: dos, gpt
+
If BOOTFS, ROOTFS, VARFS are specified, then format a partition with specified
filesystem. If not specified, the default filesystem is ext4.
Supported filesystems for
- boot: ext2, ext3, ext4, btrfs, xfs
+ boot: ext2, ext3, ext4, btrfs, xfs, vfat(EFI)
root: ext2, ext3, ext4, btrfs, xfs
var: ext2, ext3, ext4, btrfs, xfs
__EOF__
@@ -1095,8 +1195,7 @@ if [ $# -gt 0 ]; then
for i in "$@"; do
j=$(readlink -f "$i" | sed 's:^/dev/::; s:/:!:g')
if ! [ -e "/sys/block/$j/device" ]; then
- echo "$i is not a suitable for partitioning"
- exit 1
+ die "$i is not a suitable for partitioning"
fi
diskdevs="$diskdevs /dev/${j//!//}"
done
@@ -1152,6 +1251,16 @@ if [ $# -gt 1 ]; then
USE_RAID=1
fi
+if is_efi || [ -n "$USE_EFI" ]; then
+ USE_EFI=1
+ DISKLABEL=gpt
+ BOOTLOADER=grub
+ BOOT_SIZE=512
+ BOOTFS=vfat
+fi
+
+[ "$ARCH" = "ppc64le" ] && BOOTLOADER=grub
+
dmesg -n1
# native disk install
@@ -1159,7 +1268,7 @@ case "$DISK_MODE" in
sys) native_disk_install$USE_LVM $diskdevs;;
data) data_only_disk_install$USE_LVM $diskdevs;;
none) exit 0;;
-*) echo "Not a valid install mode: $DISK_MODE" >&2; exit 1;;
+*) die "Not a valid install mode: $DISK_MODE" ;;
esac
RC=$?