diff options
author | Carlo Landmeter <clandmeter@gmail.com> | 2017-10-19 10:27:08 +0200 |
---|---|---|
committer | Carlo Landmeter <clandmeter@gmail.com> | 2017-10-19 11:03:02 +0200 |
commit | 4aeefa0407c2855e9afb1454db1383b3aa24631f (patch) | |
tree | d283717f65f514b12c9e92932db55fd53806f4fb /setup-disk.in | |
parent | c3eeebd0310c79f301636eb6ce271300a8d97ea8 (diff) | |
download | alpine-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
Diffstat (limited to 'setup-disk.in')
-rw-r--r-- | setup-disk.in | 327 |
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=$? |