archboot/usr/bin/archboot-setup.sh
2021-10-18 10:14:21 +02:00

5013 lines
202 KiB
Bash
Executable file

#!/usr/bin/env bash
# we rely on some output which is parsed in english!
unset LANG
ANSWER="/tmp/.setup"
TITLE="Arch Linux Installation"
# use the first VT not dedicated to a running console
LOG="/dev/tty7"
# don't use /mnt because it's intended to mount other things there!
DESTDIR="/install"
EDITOR=""
_BLKID="blkid -c /dev/null"
_LSBLK="lsblk -rpno"
# name of kernel package
KERNELPKG="linux"
# name of the kernel image
VMLINUZ="vmlinuz-${KERNELPKG}"
# name of the initramfs filesystem
INITRAMFS="initramfs-${KERNELPKG}"
# name of intel ucode initramfs image
INTEL_UCODE="intel-ucode.img"
# name of amd ucode initramfs image
AMD_UCODE="amd-ucode.img"
# abstract the common pacman args
PACMAN="pacman --root "${DESTDIR}" --cachedir="${DESTDIR}"/var/cache/pacman/pkg --noconfirm --noprogressbar"
# downloader
DLPROG="wget"
# sources
SYNC_URL=""
MIRRORLIST="/etc/pacman.d/mirrorlist"
unset PACKAGES
# partitions
PART_ROOT=""
ROOTFS=""
# install stages
S_SRC=0 # choose mirror
S_NET=0 # network configuration
S_PART=0 # partitioning
S_MKFS=0 # formatting
S_MKFSAUTO=0 # auto fs part/formatting
S_INSTALL=0 # package installation
S_CONFIG=0 # configuration editing
# menu item tracker- autoselect the next item
NEXTITEM=""
# DIALOG()
# an el-cheapo dialog wrapper
#
# parameters: see dialog(1)
# returns: whatever dialog did
DIALOG() {
dialog --backtitle "${TITLE}" --aspect 15 "$@"
return $?
}
# chroot_mount()
# prepares target system as a chroot
#
chroot_mount()
{
[[ -e "${DESTDIR}/proc" ]] || mkdir -m 555 "${DESTDIR}/proc"
[[ -e "${DESTDIR}/sys" ]] || mkdir -m 555 "${DESTDIR}/sys"
[[ -e "${DESTDIR}/dev" ]] || mkdir -m 755 "${DESTDIR}/dev"
mount proc "${DESTDIR}/proc" -t proc -o nosuid,noexec,nodev
mount sys "${DESTDIR}/sys" -t sysfs -o nosuid,noexec,nodev,ro
mount udev "${DESTDIR}/dev" -t devtmpfs -o mode=0755,nosuid
mount devpts "${DESTDIR}/dev/pts" -t devpts -o mode=0620,gid=5,nosuid,noexec
mount shm "${DESTDIR}/dev/shm" -t tmpfs -o mode=1777,nosuid,nodev
}
# chroot_umount()
# tears down chroot in target system
#
chroot_umount()
{
umount -R "${DESTDIR}/proc"
umount -R "${DESTDIR}/sys"
umount -R "${DESTDIR}/dev"
}
getfstype()
{
echo "$(${_LSBLK} FSTYPE ${1})"
}
# getfsuuid()
# converts /dev devices to FSUUIDs
#
# parameters: device file
# outputs: FSUUID on success
# nothing on failure
# returns: nothing
getfsuuid()
{
echo "$(${_LSBLK} UUID ${1})"
}
# parameters: device file
# outputs: LABEL on success
# nothing on failure
# returns: nothing
getfslabel()
{
echo "$(${_LSBLK} LABEL ${1})"
}
getpartuuid()
{
echo "$(${_LSBLK} PARTUUID ${1})"
}
getpartlabel()
{
echo "$(${_LSBLK} PARTLABEL ${1})"
}
# list all net devices with mac adress
net_interfaces() {
for i in $(ls /sys/class/net); do
echo "$i $(cat /sys/class/net/$i/address)"
done
}
# activate_dmraid()
# activate dmraid devices
activate_dmraid()
{
if [[ -e /usr/bin/dmraid ]]; then
DIALOG --infobox "Activating dmraid arrays..." 0 0
dmraid -ay -I -Z >/dev/null 2>&1
fi
}
# activate_lvm2
# activate lvm2 devices
activate_lvm2()
{
ACTIVATE_LVM2=""
if [[ -e /usr/bin/lvm ]]; then
OLD_LVM2_GROUPS=${LVM2_GROUPS}
OLD_LVM2_VOLUMES=${LVM2_VOLUMES}
DIALOG --infobox "Scanning logical volumes..." 0 0
lvm vgscan --ignorelockingfailure >/dev/null 2>&1
DIALOG --infobox "Activating logical volumes..." 0 0
lvm vgchange --ignorelockingfailure --ignoremonitoring -ay >/dev/null 2>&1
LVM2_GROUPS="$(vgs -o vg_name --noheading 2>/dev/null)"
LVM2_VOLUMES="$(lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null)"
[[ "${OLD_LVM2_GROUPS}" = "${LVM2_GROUPS}" && "${OLD_LVM2_GROUPS}" = "${LVM2_GROUPS}" ]] && ACTIVATE_LVM2="no"
fi
}
# activate_raid
# activate md devices
activate_raid()
{
ACTIVATE_RAID=""
if [[ -e /usr/bin/mdadm ]]; then
DIALOG --infobox "Activating RAID arrays..." 0 0
mdadm --assemble --scan >/dev/null 2>&1 || ACTIVATE_RAID="no"
fi
}
# activate_luks
# activate luks devices
activate_luks()
{
ACTIVATE_LUKS=""
if [[ -e /usr/bin/cryptsetup ]]; then
DIALOG --infobox "Scanning for luks encrypted devices..." 0 0
if [[ "$(${_LSBLK} FSTYPE | grep "crypto_LUKS")" ]]; then
for PART in $(${_LSBLK} NAME,FSTYPE | grep " crypto_LUKS$" | cut -d' ' -f 1); do
# skip already encrypted devices, device mapper!
if ! [[ "$(${_LSBLK} TYPE ${PART} | grep "crypt$")" ]]; then
RUN_LUKS=""
DIALOG --yesno "Setup detected luks encrypted device, do you want to activate ${PART} ?" 0 0 && RUN_LUKS="1"
[[ "${RUN_LUKS}" = "1" ]] && _enter_luks_name && _enter_luks_passphrase && _opening_luks
[[ "${RUN_LUKS}" = "" ]] && ACTIVATE_LUKS="no"
else
ACTIVATE_LUKS="no"
fi
done
else
ACTIVATE_LUKS="no"
fi
fi
}
# activate_special_devices()
# activate special devices:
# activate dmraid, lvm2 and raid devices, if not already activated during bootup!
# run it more times if needed, it can be hidden by each other!
activate_special_devices()
{
ACTIVATE_RAID=""
ACTIVATE_LUKS=""
ACTIVATE_LVM2=""
activate_dmraid
while ! [[ "${ACTIVATE_LVM2}" = "no" && "${ACTIVATE_RAID}" = "no" && "${ACTIVATE_LUKS}" = "no" ]]; do
activate_raid
activate_lvm2
activate_luks
done
}
# destdir_mounts()
# check if PART_ROOT is set and if something is mounted on ${DESTDIR}
destdir_mounts(){
# Don't ask for filesystem and create new filesystems
ASK_MOUNTPOINTS=""
PART_ROOT=""
# check if something is mounted on ${DESTDIR}
PART_ROOT="$(mount | grep "${DESTDIR} " | cut -d' ' -f 1)"
# Run mountpoints, if nothing is mounted on ${DESTDIR}
if [[ "${PART_ROOT}" = "" ]]; then
DIALOG --msgbox "Setup couldn't detect mounted partition(s) in ${DESTDIR}, please set mountpoints first." 0 0
detect_uefi_boot
mountpoints || return 1
fi
}
# lists linux blockdevices
blockdevices() {
# all available block disk devices
for dev in $(${_LSBLK} NAME,TYPE | grep "disk$" | cut -d' ' -f1); do
# exclude checks:
#- dmraid_devices
# $(${_LSBLK} TYPE ${dev} | grep dmraid
#- iso9660 devices
# "$(${_LSBLK} FSTYPE ${dev} | grep "iso9660")
#- fakeraid isw devices
# $(${_LSBLK} FSTYPE ${dev} | grep "isw_raid_member")
#- fakeraid ddf devices
# $(${_LSBLK} FSTYPE ${dev} | grep "ddf_raid_member")
if ! [[ "$(${_LSBLK} TYPE ${dev} | grep "dmraid")" || "$(${_LSBLK} FSTYPE ${dev} | grep "iso9660")" || "$(${_LSBLK} FSTYPE ${dev} | grep "isw_raid_member")" || "$(${_LSBLK} FSTYPE ${dev} | grep "ddf_raid_member")" ]]; then
echo "${dev}"
[[ "${1}" ]] && echo ${1}
fi
done
}
# lists linux blockdevice partitions
blockdevices_partitions() {
# all available block devices partitions
# printk off needed cause of parted usage
printk off
for part in $(${_LSBLK} NAME,TYPE | grep "part$"| cut -d' ' -f1); do
# exclude checks:
#- part of raid device
# $(${_LSBLK} FSTYPE ${part} | grep "linux_raid_member")
#- part of lvm2 device
# $(${_LSBLK} FSTYPE /dev/${part} | grep "LVM2_member")
#- part of luks device
# $(${_LSBLK} FSTYPE /dev/${part} | grep "crypto_LUKS")
#- extended partition
# $(sfdisk -l 2>/dev/null | grep "${part}" | grep "Extended$")
# - extended partition (LBA)
# $(sfdisk -l 2>/dev/null | grep "${part}" | grep "(LBA)$")
#- bios_grub partitions
# "$(echo ${part} | grep "[a-z]$(parted -s $(${_LSBLK} PKNAME ${part}) print 2>/dev/null | grep bios_grub | cut -d " " -f 2)$")"
#- iso9660 devices
# "$(${_LSBLK} FSTYPE -s ${part} | grep "iso9660")"
if ! [[ "$(${_LSBLK} FSTYPE ${part} | grep "linux_raid_member")" || "$(${_LSBLK} FSTYPE ${part} | grep "LVM2_member")" || "$(${_LSBLK} FSTYPE ${part} | grep "crypto_LUKS")" || "$(sfdisk -l 2>/dev/null | grep "${part}" | grep "Extended$")" || "$(sfdisk -l 2>/dev/null | grep "${part}" | grep "(LBA)$")" || "$(echo ${part} | grep "[a-z]$(parted -s $(${_LSBLK} PKNAME ${part}) print 2>/dev/null | grep bios_grub | cut -d " " -f 2)$")" || "$(${_LSBLK} FSTYPE -s ${part} | grep "iso9660")" ]]; then
echo "${part}"
[[ "${1}" ]] && echo ${1}
fi
done
printk on
}
# list none partitionable raid md devices
raid_devices() {
for dev in $(${_LSBLK} NAME,TYPE | grep " raid.*$" | cut -d' ' -f 1 | grep -v "_d.*$" | sort -u); do
# exclude checks:
# - part of lvm2 device_found
# ${_LSBLK} FSTYPE ${dev} | grep "LVM2_member")
# - part of luks device
# $(${_LSBLK} FSTYPE ${dev} | grep "crypto_LUKS")
# - part of isw fakeraid
# $(${_LSBLK} FSTYPE ${dev} -s | grep "isw_raid_member")
# - part of ddf fakeraid
# $(${_LSBLK} FSTYPE ${dev} -s | grep "ddf_raid_member")
if ! [[ "$(${_LSBLK} FSTYPE ${dev} | grep "LVM2_member")" || "$(${_LSBLK} FSTYPE ${dev} | grep "crypto_LUKS")" || "$(${_LSBLK} FSTYPE ${dev} -s | grep "isw_raid_member")" || "$(${_LSBLK} FSTYPE ${dev} -s | grep "ddf_raid_member")" ]]; then
echo "${dev}"
[[ "${1}" ]] && echo ${1}
fi
done
}
# lists default linux partitionable raid devices
partitionable_raid_devices() {
for dev in $(${_LSBLK} NAME,TYPE | grep " raid.*$" | cut -d' ' -f 1 | grep "_d.*$" | sort -u); do
echo "${dev}"
[[ "${1}" ]] && echo ${1}
done
}
# lists linux partitionable raid devices partitions
partitionable_raid_devices_partitions() {
for part in $(${_LSBLK} NAME,TYPE | grep "md$" | cut -d' ' -f 1 | sort -u) ; do
# exclude checks:
# - part of lvm2 device_found
# ${_LSBLK} FSTYPE ${part} | grep "LVM2_member")
# - part of luks device
# $(${_LSBLK} FSTYPE ${part} | grep "crypto_LUKS")
# - extended partition
# $(sfdisk -l 2>/dev/null | grep "${part}" | grep "Extended$")
# - extended partition (LBA)
# $(sfdisk -l 2>/dev/null | grep "${part}" | grep "(LBA)$")")
# - part of isw fakeraid
# $(${_LSBLK} FSTYPE ${dev} -s | grep "isw_raid_member")
# - part of ddf fakeraid
# $(${_LSBLK} FSTYPE ${dev} -s | grep "ddf_raid_member")
if ! [[ "$(${_LSBLK} FSTYPE ${part} | grep "LVM2_member")" || "$(${_LSBLK} FSTYPE ${part} | grep "crypto_LUKS")" || "$(sfdisk -l 2>/dev/null | grep "${part}" | grep "Extended$")" || "$(sfdisk -l 2>/dev/null | grep "${part}" | grep "(LBA)$")" || $(${_LSBLK} FSTYPE ${dev} -s | grep "isw_raid_member") || "$(${_LSBLK} FSTYPE ${dev} -s | grep "ddf_raid_member")" ]]; then
echo "${part}"
[[ "${1}" ]] && echo ${1}
fi
done
}
# lists dmraid devices
dmraid_devices() {
for dev in $(${_LSBLK} NAME,TYPE | grep "dmraid$" | cut -d' ' -f 1 | grep -v "_.*p.*$" | sort -u); do
echo "${dev}"
[[ "${1}" ]] && echo ${1}
done
# isw_raid_member, managed by mdadm
for dev in $(${_LSBLK} NAME,TYPE ${i} | grep " raid.*$" | cut -d' ' -f 1 | sort -u); do
if [[ "$(${_LSBLK} NAME,FSTYPE -s | grep "isw_raid_member$" | cut -d' ' -f 1)" ]]; then
echo "${dev}"
[[ "${1}" ]] && echo ${1}
fi
done
# ddf_raid_member, managed by mdadm
for dev in $(${_LSBLK} NAME,TYPE ${i} | grep " raid.*$" | cut -d' ' -f 1 | sort -u); do
if [[ "$(${_LSBLK} NAME,FSTYPE -s | grep "ddf_raid_member$" | cut -d' ' -f 1)" ]]; then
echo "${dev}"
[[ "${1}" ]] && echo ${1}
fi
done
}
# dmraid_partitions
# - show dmraid partitions
dmraid_partitions() {
for part in $(${_LSBLK} NAME,TYPE | grep "dmraid$" | cut -d' ' -f 1 | grep "_.*p.*$" | sort -u); do
# exclude checks:
# - part of lvm2 device
# ${_LSBLK} FSTYPE ${dev} | grep "LVM2_member")
# - part of luks device
# $(${_LSBLK} FSTYPE ${dev} | grep "crypto_LUKS")
# - part of raid device
# $(${_LSBLK} FSTYPE ${dev} | grep "linux_raid_member$")
# - extended partition
# $(sfdisk -l 2>/dev/null | grep "${part}" | grep "Extended$")
# - extended partition (LBA)
# $(sfdisk -l 2>/dev/null | grep "${part}" | grep "(LBA)$")
if ! [[ "$(${_LSBLK} FSTYPE ${part} | grep "crypto_LUKS$")" || "$(${_LSBLK} FSTYPE ${part} | grep "LVM2_member$")" || "$(${_LSBLK} FSTYPE ${part} | grep "linux_raid_member$")" || "$(sfdisk -l 2>/dev/null | grep "${part}" | grep "Extended$")"|| "$(sfdisk -l 2>/dev/null | grep "${part}" | grep "(LBA)$")" ]]; then
echo "${part}"
[[ "${1}" ]] && echo ${1}
fi
done
# isw_raid_member, managed by mdadm
for dev in $(${_LSBLK} NAME,TYPE ${i} | grep " md$" | cut -d' ' -f 1 | sort -u); do
if [[ "$(${_LSBLK} NAME,FSTYPE -s | grep "isw_raid_member$" | cut -d' ' -f 1)" ]]; then
echo "${dev}"
[[ "${1}" ]] && echo ${1}
fi
done
# ddf_raid_member, managed by mdadm
for dev in $(${_LSBLK} NAME,TYPE ${i} | grep " md$" | cut -d' ' -f 1 | sort -u); do
if [[ "$(${_LSBLK} NAME,FSTYPE -s | grep "ddf_raid_member$" | cut -d' ' -f 1)" ]]; then
echo "${dev}"
[[ "${1}" ]] && echo ${1}
fi
done
}
# dm_devices
# - show device mapper devices:
# lvm2 and cryptdevices
dm_devices() {
for dev in $(${_LSBLK} NAME,TYPE | grep -e "lvm$" -e "crypt$" | cut -d' ' -f1 | sort -u); do
# exclude checks:
# - part of lvm2 device
# ${_LSBLK} FSTYPE ${dev} | grep "LVM2_member")
# - part of luks device
# $(${_LSBLK} FSTYPE ${dev} | grep "crypto_LUKS")
# - part of raid device
# $(${_LSBLK} FSTYPE ${dev} | grep "linux_raid_member$")
# - part of running raid on encrypted device
# $(${_LSBLK} TYPE ${dev} | grep "raid.*$
if ! [[ "$(${_LSBLK} FSTYPE ${dev} | grep "crypto_LUKS$")" || "$(${_LSBLK} FSTYPE ${dev} | grep "LVM2_member$")" || "$(${_LSBLK} FSTYPE ${dev} | grep "linux_raid_member$")" || "$(${_LSBLK} TYPE ${dev} | grep "raid.*$")" ]]; then
echo "${dev}"
[[ "${1}" ]] && echo ${1}
fi
done
}
finddisks() {
blockdevices ${1}
dmraid_devices ${1}
partitionable_raid_devices ${1}
}
findpartitions() {
blockdevices_partitions ${1}
dm_devices ${1}
dmraid_partitions ${1}
raid_devices ${1}
partitionable_raid_devices_partitions ${1}
}
# don't check on raid devices!
findbootloaderdisks() {
if ! [[ "${USE_DMRAID}" = "1" ]]; then
blockdevices ${1}
else
dmraid_devices ${1}
fi
}
# don't list raid devices, lvm2 and devicemapper!
findbootloaderpartitions() {
if ! [[ "${USE_DMRAID}" = "1" ]]; then
blockdevices_partitions ${1}
else
dmraid_partitions ${1}
fi
}
# find any gpt/guid formatted disks
find_gpt() {
GUID_DETECTED=""
for i in $(finddisks); do
[[ "$(${_BLKID} -p -i -o value -s PTTYPE ${i})" == "gpt" ]] && GUID_DETECTED="1"
done
}
# freeze and unfreeze xfs, as hack for grub(2) installing
freeze_xfs() {
sync
if [[ -x /usr/bin/xfs_freeze ]]; then
if [[ "$(cat /proc/mounts | grep "${DESTDIR}/boot " | grep " xfs ")" ]]; then
xfs_freeze -f ${DESTDIR}/boot >/dev/null 2>&1
xfs_freeze -u ${DESTDIR}/boot >/dev/null 2>&1
fi
if [[ "$(cat /proc/mounts | grep "${DESTDIR} " | grep " xfs ")" ]]; then
xfs_freeze -f ${DESTDIR} >/dev/null 2>&1
xfs_freeze -u ${DESTDIR} >/dev/null 2>&1
fi
fi
}
mapdev() {
partition_flag=0
device_found=0
# check if we use sd or vd device
if ! [[ "$(echo ${1} | grep /dev/sd)" || "$(echo ${1} | grep /dev/vd)" ]]; then
linuxdevice=$(echo ${1} | sed -e 's#p[0-9].*$##')
else
linuxdevice=$(echo ${1} | sed -e 's#[0-9].*$##g')
fi
if ! [[ "$(echo ${1} | grep /dev/sd)" || "$(echo ${1} | grep /dev/vd)" ]]; then
if [[ "$(echo ${1} | egrep 'p[0-9].*$')" ]]; then
pnum=$(echo ${1} | sed -e 's#.*p##g')
partition_flag=1
fi
else
if [[ "$(echo ${1} | egrep '[0-9]$')" ]]; then
# /dev/sdX and /dev/vdX
pnum=$(echo ${1} | cut -b9-)
partition_flag=1
fi
fi
for dev in ${devs}; do
if [[ "(" = $(echo ${dev} | cut -b1) ]]; then
grubdevice="${dev}"
else
if [[ "${dev}" = "${linuxdevice}" ]]; then
device_found=1
break
fi
fi
done
if [[ "${device_found}" = "1" ]]; then
if [[ "${partition_flag}" = "0" ]]; then
echo "${grubdevice}"
else
grubdevice_stringlen=${#grubdevice}
grubdevice_stringlen=$((${grubdevice_stringlen} - 1))
grubdevice=$(echo ${grubdevice} | cut -b1-${grubdevice_stringlen})
echo "${grubdevice},${pnum})"
fi
else
echo "DEVICE NOT FOUND"
fi
}
printk()
{
case ${1} in
"on") echo 4 >/proc/sys/kernel/printk ;;
"off") echo 0 >/proc/sys/kernel/printk ;;
esac
}
getdest() {
[[ "${DESTDIR}" ]] && return 0
DIALOG --inputbox "Enter the destination directory where your target system is mounted" 8 65 "${DESTDIR}" 2>${ANSWER} || return 1
DESTDIR=$(cat ${ANSWER})
}
# geteditor()
# prompts the user to choose an editor
# sets EDITOR global variable
#
geteditor() {
if ! [[ "${EDITOR}" ]]; then
DIALOG --menu "Select a Text Editor to Use" 10 35 3 \
"1" "nano (easier)" \
"2" "vi" 2>${ANSWER} || return 1
case $(cat ${ANSWER}) in
"1") EDITOR="nano" ;;
"2") EDITOR="vi" ;;
esac
fi
}
# set device name scheme
set_device_name_scheme() {
NAME_SCHEME_PARAMETER=""
NAME_SCHEME_LEVELS=""
MENU_DESC_TEXT=""
# check if gpt/guid formatted disks are there
find_gpt
## util-linux root=PARTUUID=/root=PARTLABEL= support - https://git.kernel.org/?p=utils/util-linux/util-linux.git;a=commitdiff;h=fc387ee14c6b8672761ae5e67ff639b5cae8f27c;hp=21d1fa53f16560dacba33fffb14ffc05d275c926
## mkinitcpio's init root=PARTUUID= support - https://projects.archlinux.org/mkinitcpio.git/tree/init_functions#n185
if [[ "${GUID_DETECTED}" == "1" ]]; then
NAME_SCHEME_LEVELS="${NAME_SCHEME_LEVELS} PARTUUID PARTUUID=<partuuid> PARTLABEL PARTLABEL=<partlabel>"
MENU_DESC_TEXT="\nPARTUUID and PARTLABEL are specific to GPT disks.\nIn GPT disks, PARTUUID is recommended.\nIn MBR/msdos disks,"
fi
NAME_SCHEME_LEVELS="${NAME_SCHEME_LEVELS} FSUUID UUID=<uuid> FSLABEL LABEL=<label> KERNEL /dev/<kernelname>"
DIALOG --menu "Select the device name scheme you want to use in config files. ${MENU_DESC_TEXT} FSUUID is recommended." 15 70 9 ${NAME_SCHEME_LEVELS} 2>${ANSWER} || return 1
NAME_SCHEME_PARAMETER=$(cat ${ANSWER})
NAME_SCHEME_PARAMETER_RUN="1"
}
# set GUID (gpt) usage
set_guid() {
## Lenovo BIOS-GPT issues - Arch Forum - https://bbs.archlinux.org/viewtopic.php?id=131149 , https://bbs.archlinux.org/viewtopic.php?id=133330 , https://bbs.archlinux.org/viewtopic.php?id=138958
## Lenovo BIOS-GPT issues - in Fedora - https://bugzilla.redhat.com/show_bug.cgi?id=735733, https://bugzilla.redhat.com/show_bug.cgi?id=749325 , http://git.fedorahosted.org/git/?p=anaconda.git;a=commit;h=ae74cebff312327ce2d9b5ac3be5dbe22e791f09
GUIDPARAMETER=""
DIALOG --yesno "Do you want to use GUID Partition Table (GPT)?\n\nIt is a standard for the layout of the partition table on a physical storage disk. Although it forms a part of the Unified Extensible Firmware Interface (UEFI) standard, it is also used on some BIOS systems because of the limitations of MBR aka msdos partition tables, which restrict maximum disk size to 2 TiB.\n\nWindows 10 and later versions include the capability to use GPT for non-boot aka data disks (only UEFI systems can boot Windows 10 and later from GPT disks).\n\nAttention:\n- Please check if your other operating systems have GPT support!\n- Use this option for a GRUB(2) setup, which should support LVM, RAID\n etc., which doesn't fit into the usual 30k MS-DOS post-MBR gap.\n- BIOS-GPT boot may not work in some Lenovo systems (irrespective of the\n
bootloader used). " 0 0 && GUIDPARAMETER="yes"
}
# Get a list of available disks for use in the "Available disks" dialogs.
# This will print the mountpoints as follows, getting size info from lsblk:
# /dev/sda 64G
_getavaildisks()
{
for i in $(finddisks); do
${_LSBLK} NAME,SIZE -d ${i}
done
}
# Get a list of available partitions for use in the "Available Mountpoints" dialogs.
# This will print the mountpoints as follows, getting size info from lsblk:
# /dev/sda1 640M
_getavailpartitions()
{
for i in $(findpartitions); do
${_LSBLK} NAME,SIZE -d ${i}
done
}
# Disable swap and all mounted partitions for the destination system. Unmount
# the destination root partition last!
_umountall()
{
DIALOG --infobox "Disabling swapspace, unmounting already mounted disk devices..." 0 0
swapoff -a >/dev/null 2>&1
for i in $(findmnt --list --submounts ${DESTDIR} -o TARGET -n | tac); do
umount $i
done
}
# Disable all software raid devices
_stopmd()
{
if [[ "$(cat /proc/mdstat 2>/dev/null | grep ^md)" ]]; then
DISABLEMD=""
DIALOG --defaultno --yesno "Setup detected already running raid devices, do you want to disable them completely?" 0 0 && DISABLEMD="1"
if [[ "${DISABLEMD}" = "1" ]]; then
DIALOG --infobox "Disabling all software raid devices..." 0 0
for i in $(cat /proc/mdstat 2>/dev/null | grep ^md | sed -e 's# :.*##g'); do
mdadm --manage --stop /dev/${i} > ${LOG}
done
DIALOG --infobox "Cleaning superblocks of all software raid devices..." 0 0
for i in $(${_LSBLK} NAME,FSTYPE | grep "linux_raid_member$" | cut -d' ' -f 1); do
mdadm --zero-superblock ${i} > ${LOG}
done
fi
fi
DISABLEMDSB=""
if [[ "$(${_LSBLK} FSTYPE | grep "linux_raid_member")" ]]; then
DIALOG --defaultno --yesno "Setup detected superblock of raid devices, do you want to clean the superblock of them?" 0 0 && DISABLEMDSB="1"
if [[ "${DISABLEMDSB}" = "1" ]]; then
DIALOG --infobox "Cleaning superblocks of all software raid devices..." 0 0
for i in $(${_LSBLK} NAME,FSTYPE | grep "linux_raid_member$" | cut -d' ' -f 1); do
mdadm --zero-superblock ${i} > ${LOG}
done
fi
fi
}
# Disable all lvm devices
_stoplvm()
{
DISABLELVM=""
DETECTED_LVM=""
LV_VOLUMES="$(lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null)"
LV_GROUPS="$(vgs -o vg_name --noheading 2>/dev/null)"
LV_PHYSICAL="$(pvs -o pv_name --noheading 2>/dev/null)"
! [[ "${LV_VOLUMES}" = "" ]] && DETECTED_LVM=1
! [[ "${LV_GROUPS}" = "" ]] && DETECTED_LVM=1
! [[ "${LV_PHYSICAL}" = "" ]] && DETECTED_LVM=1
if [[ "${DETECTED_LVM}" = "1" ]]; then
DIALOG --defaultno --yesno "Setup detected lvm volumes, volume groups or physical devices, do you want to remove them completely?" 0 0 && DISABLELVM="1"
fi
if [[ "${DISABLELVM}" = "1" ]]; then
DIALOG --infobox "Removing logical volumes ..." 0 0
for i in ${LV_VOLUMES}; do
lvremove -f /dev/mapper/${i} 2>/dev/null> ${LOG}
done
DIALOG --infobox "Removing logical groups ..." 0 0
for i in ${LV_GROUPS}; do
vgremove -f ${i} 2>/dev/null > ${LOG}
done
DIALOG --infobox "Removing physical volumes ..." 0 0
for i in ${LV_PHYSICAL}; do
pvremove -f ${i} 2>/dev/null > ${LOG}
done
fi
}
# Disable all luks encrypted devices
_stopluks()
{
DISABLELUKS=""
DETECTED_LUKS=""
LUKSDEVICE=""
# detect already running luks devices
LUKSDEVICE="$(${_LSBLK} NAME,TYPE | grep " crypt$" | cut -d' ' -f1)"
! [[ "${LUKSDEVICE}" = "" ]] && DETECTED_LUKS=1
if [[ "${DETECTED_LUKS}" = "1" ]]; then
DIALOG --defaultno --yesno "Setup detected running luks encrypted devices, do you want to remove them completely?" 0 0 && DISABLELUKS="1"
fi
if [[ "${DISABLELUKS}" = "1" ]]; then
DIALOG --infobox "Removing luks encrypted devices ..." 0 0
for i in ${LUKSDEVICE}; do
LUKS_REAL_DEVICE="$(${_LSBLK} NAME,FSTYPE -s "${LUKSDEVICE}" | grep " crypto_LUKS$" | cut -d' ' -f1)"
cryptsetup remove ${i} > ${LOG}
# delete header from device
wipefs -a ${LUKS_REAL_DEVICE} >/dev/null 2>&1
done
fi
DISABLELUKS=""
DETECTED_LUKS=""
# detect not running luks devices
[[ "$(${_LSBLK} FSTYPE | grep "crypto_LUKS")" ]] && DETECTED_LUKS=1
if [[ "${DETECTED_LUKS}" = "1" ]]; then
DIALOG --defaultno --yesno "Setup detected not running luks encrypted devices, do you want to remove them completely?" 0 0 && DISABLELUKS="1"
fi
if [[ "${DISABLELUKS}" = "1" ]]; then
DIALOG --infobox "Removing not running luks encrypted devices ..." 0 0
for i in $(${_LSBLK} NAME,FSTYPE | grep "crypto_LUKS$" | cut -d' ' -f1); do
# delete header from device
wipefs -a ${i} >/dev/null 2>&1
done
fi
[[ -e /tmp/.crypttab ]] && rm /tmp/.crypttab
}
#_dmraid_update
_dmraid_update()
{
printk off
DIALOG --infobox "Deactivating dmraid devices ..." 0 0
dmraid -an >/dev/null 2>&1
if [[ "${DETECTED_LVM}" = "1" || "${DETECTED_LUKS}" = "1" ]]; then
DIALOG --defaultno --yesno "Setup detected running dmraid devices and/or running lvm2, luks encrypted devices. If you reduced/deleted partitions on your dmraid device a complete reset of devicemapper devices is needed. This will reset also your created lvm2 or encrypted devices. Are you sure you want to do this?" 0 0 && RESETDM="1"
if [[ "${RESETDM}" = "1" ]]; then
DIALOG --infobox "Resetting devicemapper devices ..." 0 0
dmsetup remove_all >/dev/null 2>&1
fi
else
DIALOG --infobox "Resetting devicemapper devices ..." 0 0
dmsetup remove_all >/dev/null 2>&1
fi
DIALOG --infobox "Reactivating dmraid devices ..." 0 0
dmraid -ay -I -Z >/dev/null 2>&1
printk on
}
#helpbox for raid
_helpraid()
{
DIALOG --msgbox "LINUX SOFTWARE RAID SUMMARY:\n
-----------------------------\n\n
Linear mode:\n
You have two or more partitions which are not necessarily the same size\n
(but of course can be), which you want to append to each other.\n
Spare-disks are not supported here. If a disk dies, the array dies with\n
it.\n\n
RAID-0:\n
You have two or more devices, of approximately the same size, and you want\n
to combine their storage capacity and also combine their performance by\n
accessing them in parallel. Like in Linear mode, spare disks are not\n
supported here either. RAID-0 has no redundancy, so when a disk dies, the\n
array goes with it.\n\n
RAID-1:\n
You have two devices of approximately same size, and you want the two to\n
be mirrors of each other. Eventually you have more devices, which you\n
want to keep as stand-by spare-disks, that will automatically become a\n
part of the mirror if one of the active devices break.\n\n
RAID-4:\n
You have three or more devices of roughly the same size and you want\n
a way that protects data against loss of any one disk.\n
Fault tolerance is achieved by adding an extra disk to the array, which\n
is dedicated to storing parity information. The overall capacity of the\n
array is reduced by one disk.\n
The storage efficiency is 66 percent. With six drives, the storage\n
efficiency is 87 percent. The main disadvantage is poor performance for\n
multiple,\ simultaneous, and independent read/write operations.\n
Thus, if any disk fails, all data stay intact. But if two disks fail,\n
all data is lost.\n\n
RAID-5:\n
You have three or more devices of roughly the same size, you want to\n
combine them into a larger device, but still to maintain a degree of\n
redundancy fordata safety. Eventually you have a number of devices to use\n
as spare-disks, that will not take part in the array before another device\n
fails. If you use N devices where the smallest has size S, the size of the\n
entire array will be (N-1)*S. This \"missing\" space is used for parity\n
(redundancy) information. Thus, if any disk fails, all data stay intact.\n
But if two disks fail, all data is lost.\n\n
RAID-6:\n
You have four or more devices of roughly the same size and you want\n
a way that protects data against loss of any two disks.\n
Fault tolerance is achieved by adding an two extra disk to the array,\n
which is dedicated to storing parity information. The overall capacity\n
of the array is reduced by 2 disks.\n
Thus, if any two disks fail, all data stay intact. But if 3 disks fail,\n
all data is lost.\n\n
RAID-10:\n
Shorthand for RAID1+0, a mirrored striped array and needs a minimum of\n
two disks. It provides superior data security and can survive multiple\n
disk failures. The main disadvantage is cost, because 50% of your\n
storage is duplication." 0 0
}
# Create raid or raid_partition
_raid()
{
MDFINISH=""
while [[ "${MDFINISH}" != "DONE" ]]; do
activate_special_devices
: >/tmp/.raid
: >/tmp/.raid-spare
# check for devices
# Remove all raid devices with children
RAID_BLACKLIST="$(for i in $(${_LSBLK} NAME,TYPE | grep " raid.*$" | cut -d' ' -f1 | sort -u); do
echo $(${_LSBLK} NAME ${i}) _
done)"
PARTS="$(for i in $(findpartitions); do
! [[ "$(echo "${RAID_BLACKLIST}" | egrep "${i} _")" ]] && echo $i _
done)"
# break if all devices are in use
if [[ "${PARTS}" = "" ]]; then
DIALOG --msgbox "All devices in use. No more devices left for new creation." 0 0
return 1
fi
# enter raid device name
RAIDDEVICE=""
while [[ "${RAIDDEVICE}" = "" ]]; do
if [[ "${RAID_PARTITION}" = "" ]]; then
DIALOG --inputbox "Enter the node name for the raiddevice:\n/dev/md[number]\n/dev/md0\n/dev/md1\n\n" 15 65 "/dev/md0" 2>${ANSWER} || return 1
fi
if [[ "${RAID_PARTITION}" = "1" ]]; then
DIALOG --inputbox "Enter the node name for partitionable raiddevice:\n/dev/md_d[number]\n/dev/md_d0\n/dev/md_d1" 15 65 "/dev/md_d0" 2>${ANSWER} || return 1
fi
RAIDDEVICE=$(cat ${ANSWER})
if [[ "$(cat /proc/mdstat 2>/dev/null | grep "^$(echo ${RAIDDEVICE} | sed -e 's#/dev/##g')")" ]]; then
DIALOG --msgbox "ERROR: You have defined 2 identical node names! Please enter another name." 8 65
RAIDDEVICE=""
fi
done
RAIDLEVELS="linear - raid0 - raid1 - raid4 - raid5 - raid6 - raid10 -"
DIALOG --menu "Select the raid level you want to use" 21 50 11 ${RAIDLEVELS} 2>${ANSWER} || return 1
LEVEL=$(cat ${ANSWER})
# raid5 and raid10 support parity parameter
PARITY=""
if [[ "${LEVEL}" = "raid5" || "${LEVEL}" = "raid6" || "${LEVEL}" = "raid10" ]]; then
PARITYLEVELS="left-asymmetric - left-symmetric - right-asymmetric - right-symmetric -"
DIALOG --menu "Select the parity layout you want to use (default is left-symmetric)" 21 50 13 ${PARITYLEVELS} 2>${ANSWER} || return 1
PARTIY=$(cat ${ANSWER})
fi
# show all devices with sizes
DIALOG --cr-wrap --msgbox "DISKS:\n$(_getavaildisks)\n\nPARTITIONS:\n$(_getavailpartitions)" 0 0
# select the first device to use, no missing option available!
RAIDNUMBER=1
DIALOG --menu "Select device ${RAIDNUMBER}" 21 50 13 ${PARTS} 2>${ANSWER} || return 1
PART=$(cat ${ANSWER})
echo "${PART}" >>/tmp/.raid
while [[ "${PART}" != "DONE" ]]; do
RAIDNUMBER=$((${RAIDNUMBER} + 1))
# clean loop from used partition and options
PARTS="$(echo ${PARTS} | sed -e "s#${PART}\ _##g" -e 's#MISSING\ _##g' -e 's#SPARE\ _##g')"
# raid0 doesn't support missing devices
! [[ "${LEVEL}" = "raid0" || "${LEVEL}" = "linear" ]] && MDEXTRA="MISSING _"
# add more devices
DIALOG --menu "Select additional device ${RAIDNUMBER}" 21 50 13 ${PARTS} ${MDEXTRA} DONE _ 2>${ANSWER} || return 1
PART=$(cat ${ANSWER})
SPARE=""
! [[ "${LEVEL}" = "raid0" || "${LEVEL}" = "linear" ]] && DIALOG --yesno --defaultno "Would you like to use ${PART} as spare device?" 0 0 && SPARE="1"
[[ "${PART}" = "DONE" ]] && break
if [[ "${PART}" = "MISSING" ]]; then
DIALOG --yesno "Would you like to create a degraded raid on ${RAIDDEVICE}?" 0 0 && DEGRADED="missing"
echo "${DEGRADED}" >>/tmp/.raid
else
if [[ "${SPARE}" = "1" ]]; then
echo "${PART}" >>/tmp/.raid-spare
else
echo "${PART}" >>/tmp/.raid
fi
fi
done
# final step ask if everything is ok?
DIALOG --yesno "Would you like to create ${RAIDDEVICE} like this?\n\nLEVEL:\n${LEVEL}\n\nDEVICES:\n$(for i in $(cat /tmp/.raid); do echo "${i}\n";done)\nSPARES:\n$(for i in $(cat /tmp/.raid-spare); do echo "${i}\n";done)" 0 0 && MDFINISH="DONE"
done
_createraid
}
# create raid device
_createraid()
{
DEVICES="$(echo -n $(cat /tmp/.raid))"
SPARES="$(echo -n $(cat /tmp/.raid-spare))"
# combine both if spares are available, spares at the end!
[[ -n ${SPARES} ]] && DEVICES="${DEVICES} ${SPARES}"
# get number of devices
RAID_DEVICES="$(cat /tmp/.raid | wc -l)"
SPARE_DEVICES="$(cat /tmp/.raid-spare | wc -l)"
# generate options for mdadm
RAIDOPTIONS="--force --run --level=${LEVEL}"
[[ "$(echo ${RAIDDEVICE} | grep /md_d[0-9])" ]] && RAIDOPTIONS="${RAIDOPTIONS} -a mdp"
! [[ "${RAID_DEVICES}" = "0" ]] && RAIDOPTIONS="${RAIDOPTIONS} --raid-devices=${RAID_DEVICES}"
! [[ "${SPARE_DEVICES}" = "0" ]] && RAIDOPTIONS="${RAIDOPTIONS} --spare-devices=${SPARE_DEVICES}"
! [[ "${PARITY}" = "" ]] && RAIDOPTIONS="${RAIDOPTIONS} --layout=${PARITY}"
DIALOG --infobox "Creating ${RAIDDEVICE}..." 0 0
mdadm --create ${RAIDDEVICE} ${RAIDOPTIONS} ${DEVICES} >${LOG} 2>&1
if [[ $? -gt 0 ]]; then
DIALOG --msgbox "Error creating ${RAIDDEVICE} (see ${LOG} for details)." 0 0
return 1
fi
if [[ "$(echo ${RAIDDEVICE} | grep /md_d[0-9])" ]]; then
# switch for mbr usage
set_guid
if [[ "${GUIDPARAMETER}" = "" ]]; then
DIALOG --msgbox "Now you'll be put into the parted program where you can partition your raiddevice to your needs." 18 70
parted -a optimal -s ${RAIDDEVICE} mktable msdos
clear
parted ${RAIDDEVICE} print
parted ${RAIDDEVICE}
else
DISC=${RAIDDEVICE}
RUN_CFDISK="1"
CHECK_BIOS_BOOT_GRUB=""
CHECK_UEFISYS_PART=""
check_gpt
fi
fi
}
# help for lvm
_helplvm()
{
DIALOG --msgbox "LOGICAL VOLUME SUMMARY:\n
-----------------------------\n\n
LVM is a Logical Volume Manager for the Linux kernel. With LVM you can\n
abstract your storage space and have \"virtual partitions\" which are easier\n
to modify.\n\nThe basic building block of LVM are:\n
- Physical volume (PV):\n
Partition on storage disk (or even storage disk itself or loopback file) on\n
which you can have virtual groups. It has a special header and is\n
divided into physical extents. Think of physical volumes as big building\n
blocks which can be used to build your storage drive.\n
- Volume group (VG):\n
Group of physical volumes that are used as storage volume (as one disk).\n
They contain logical volumes. Think of volume groups as storage drives.\n
- Logical volume(LV):\n
A \"virtual/logical partition\" that resides in a volume group and is\n
composed of physical extents. Think of logical volumes as normal\n
partitions." 0 0
}
# Creates physical volume
_createpv()
{
PVFINISH=""
while [[ "${PVFINISH}" != "DONE" ]]; do
activate_special_devices
: >/tmp/.pvs-create
# Remove all lvm devices with children
LVM_BLACKLIST="$(for i in $(${_LSBLK} NAME,TYPE | grep " lvm$" | cut -d' ' -f1 | sort -u); do
echo $(${_LSBLK} NAME ${i}) _
done)"
PARTS="$(for i in $(findpartitions); do
! [[ "$(echo "${LVM_BLACKLIST}" | egrep "${i} _")" ]] && echo $i _
done)"
# break if all devices are in use
if [[ "${PARTS}" = "" ]]; then
DIALOG --msgbox "No devices left for physical volume creation." 0 0
return 1
fi
# show all devices with sizes
DIALOG --cr-wrap --msgbox "DISKS:\n$(_getavaildisks)\n\nPARTITIONS:\n$(_getavailpartitions)\n\n" 0 0
# select the first device to use
DEVNUMBER=1
DIALOG --menu "Select device number ${DEVNUMBER} for physical volume" 21 50 13 ${PARTS} 2>${ANSWER} || return 1
PART=$(cat ${ANSWER})
echo "${PART}" >>/tmp/.pvs-create
while [[ "${PART}" != "DONE" ]]; do
DEVNUMBER=$((${DEVNUMBER} + 1))
# clean loop from used partition and options
PARTS="$(echo ${PARTS} | sed -e "s#${PART}\ _##g")"
# add more devices
DIALOG --menu "Select additional device number ${DEVNUMBER} for physical volume" 21 50 13 ${PARTS} DONE _ 2>${ANSWER} || return 1
PART=$(cat ${ANSWER})
[[ "${PART}" = "DONE" ]] && break
echo "${PART}" >>/tmp/.pvs-create
done
# final step ask if everything is ok?
DIALOG --yesno "Would you like to create physical volume on devices below?\n$(cat /tmp/.pvs-create | sed -e 's#$#\\n#g')" 0 0 && PVFINISH="DONE"
done
DIALOG --infobox "Creating physical volume on ${PART}..." 0 0
PART="$(echo -n $(cat /tmp/.pvs-create))"
pvcreate ${PART} >${LOG} 2>&1
if [[ $? -gt 0 ]]; then
DIALOG --msgbox "Error creating physical volume on ${PART} (see ${LOG} for details)." 0 0
return 1
fi
# run udevadm to get values exported
udevadm trigger
udevadm settle
}
#find physical volumes that are not in use
findpv()
{
for i in $(${_LSBLK} NAME,FSTYPE | grep " LVM2_member$" | cut -d' ' -f1 | sort -u); do
# exclude checks:
#- not part of running lvm2
# ! "$(${_LSBLK} TYPE ${i} | grep "lvm")"
#- not part of volume group
# $(pvs -o vg_name --noheading ${i} | grep " $")
if [[ ! "$(${_LSBLK} TYPE ${i} | grep "lvm")" && $(pvs -o vg_name --noheading ${i} | grep " $") ]]; then
echo "${i}"
[[ "${1}" ]] && echo ${1}
fi
done
}
getavailablepv()
{
for i in $(${_LSBLK} NAME,FSTYPE | grep " LVM2_member$" | cut -d' ' -f1 | sort -u); do
# exclude checks:
#- not part of running lvm2
# ! "$(${_LSBLK} TYPE ${i} | grep "lvm")"
#- not part of volume group
# $(pvs -o vg_name --noheading ${i} | grep " $")
if [[ ! "$(${_LSBLK} TYPE ${i} | grep "lvm")" && $(pvs -o vg_name --noheading ${i} | grep " $") ]]; then
echo "$(${_LSBLK} NAME,SIZE ${i})"
fi
done
}
#find volume groups that are not already full in use
findvg()
{
for dev in $(vgs -o vg_name --noheading);do
if ! [[ "$(vgs -o vg_free --noheading --units m ${dev} | grep " 0m$")" ]]; then
echo "${dev}"
[[ "${1}" ]] && echo ${1}
fi
done
}
getavailablevg()
{
for i in "$(vgs -o vg_name,vg_free --noheading --units m)"; do
if ! [[ "$(echo ${i} | grep " 0m$")" ]]; then
echo "${i}\n"
fi
done
}
# Creates volume group
_createvg()
{
VGFINISH=""
while [[ "${VGFINISH}" != "DONE" ]]; do
: >/tmp/.pvs
VGDEVICE=""
PVS=$(findpv _)
# break if all devices are in use
if [[ "${PVS}" = "" ]]; then
DIALOG --msgbox "No devices left for Volume Group creation." 0 0
return 1
fi
# enter volume group name
VGDEVICE=""
while [[ "${VGDEVICE}" = "" ]]; do
DIALOG --inputbox "Enter the Volume Group name:\nfoogroup\n<yourvolumegroupname>\n\n" 15 65 "foogroup" 2>${ANSWER} || return 1
VGDEVICE=$(cat ${ANSWER})
if [[ "$(vgs -o vg_name --noheading 2>/dev/null | grep "^ $(echo ${VGDEVICE})")" ]]; then
DIALOG --msgbox "ERROR: You have defined 2 identical Volume Group names! Please enter another name." 8 65
VGDEVICE=""
fi
done
# show all devices with sizes, which are not in use
DIALOG --cr-wrap --msgbox "Physical Volumes:\n$(getavailablepv)" 0 0
# select the first device to use, no missing option available!
PVNUMBER=1
DIALOG --menu "Select Physical Volume ${PVNUMBER} for ${VGDEVICE}" 21 50 13 ${PVS} 2>${ANSWER} || return 1
PV=$(cat ${ANSWER})
echo "${PV}" >>/tmp/.pvs
while [[ "${PVS}" != "DONE" ]]; do
PVNUMBER=$((${PVNUMBER} + 1))
# clean loop from used partition and options
PVS="$(echo ${PVS} | sed -e "s#${PV}\ _##g")"
# add more devices
DIALOG --menu "Select additional Physical Volume ${PVNUMBER} for ${VGDEVICE}" 21 50 13 ${PVS} DONE _ 2>${ANSWER} || return 1
PV=$(cat ${ANSWER})
[[ "${PV}" = "DONE" ]] && break
echo "${PV}" >>/tmp/.pvs
done
# final step ask if everything is ok?
DIALOG --yesno "Would you like to create Volume Group like this?\n\n${VGDEVICE}\n\nPhysical Volumes:\n$(cat /tmp/.pvs | sed -e 's#$#\\n#g')" 0 0 && VGFINISH="DONE"
done
DIALOG --infobox "Creating Volume Group ${VGDEVICE}..." 0 0
PV="$(echo -n $(cat /tmp/.pvs))"
vgcreate ${VGDEVICE} ${PV} >${LOG} 2>&1
if [[ $? -gt 0 ]]; then
DIALOG --msgbox "Error creating Volume Group ${VGDEVICE} (see ${LOG} for details)." 0 0
return 1
fi
}
# Creates logical volume
_createlv()
{
LVFINISH=""
while [[ "${LVFINISH}" != "DONE" ]]; do
LVDEVICE=""
LV_SIZE_SET=""
LVS=$(findvg _)
# break if all devices are in use
if [[ "${LVS}" = "" ]]; then
DIALOG --msgbox "No Volume Groups with free space available for Logical Volume creation." 0 0
return 1
fi
# show all devices with sizes, which are not 100% in use!
DIALOG --cr-wrap --msgbox "Volume Groups:\n$(getavailablevg)" 0 0
DIALOG --menu "Select Volume Group" 21 50 13 ${LVS} 2>${ANSWER} || return 1
LV=$(cat ${ANSWER})
# enter logical volume name
LVDEVICE=""
while [[ "${LVDEVICE}" = "" ]]; do
DIALOG --inputbox "Enter the Logical Volume name:\nfooname\n<yourvolumename>\n\n" 15 65 "fooname" 2>${ANSWER} || return 1
LVDEVICE=$(cat ${ANSWER})
if [[ "$(lvs -o lv_name,vg_name --noheading 2>/dev/null | grep " $(echo ${LVDEVICE}) $(echo ${LV})"$)" ]]; then
DIALOG --msgbox "ERROR: You have defined 2 identical Logical Volume names! Please enter another name." 8 65
LVDEVICE=""
fi
done
while [[ "${LV_SIZE_SET}" = "" ]]; do
LV_ALL=""
DIALOG --inputbox "Enter the size (MB) of your Logical Volume,\nMinimum value is > 0.\n\nVolume space left: $(vgs -o vg_free --noheading --units m ${LV})B\n\nIf you enter no value, all free space left will be used." 10 65 "" 2>${ANSWER} || return 1
LV_SIZE=$(cat ${ANSWER})
if [[ "${LV_SIZE}" = "" ]]; then
DIALOG --yesno "Would you like to create Logical Volume with no free space left?" 0 0 && LV_ALL="1"
if ! [[ "${LV_ALL}" = "1" ]]; then
LV_SIZE=0
fi
fi
if [[ "${LV_SIZE}" = "0" ]]; then
DIALOG --msgbox "ERROR: You have entered a invalid size, please enter again." 0 0
else
if [[ "${LV_SIZE}" -ge "$(vgs -o vg_free --noheading --units m | sed -e 's#m##g')" ]]; then
DIALOG --msgbox "ERROR: You have entered a too large size, please enter again." 0 0
else
LV_SIZE_SET=1
fi
fi
done
#Contiguous doesn't work with +100%FREE
LV_CONTIGUOUS=""
[[ "${LV_ALL}" = "" ]] && DIALOG --defaultno --yesno "Would you like to create Logical Volume as a contiguous partition, that means that your space doesn't get partitioned over one or more disks nor over non-contiguous physical extents.\n(usefull for swap space etc.)?" 0 0 && LV_CONTIGUOUS="1"
if [[ "${LV_CONTIGUOUS}" = "1" ]]; then
CONTIGUOUS=yes
LV_EXTRA="-C y"
else
CONTIGUOUS=no
LV_EXTRA=""
fi
[[ "${LV_SIZE}" = "" ]] && LV_SIZE="All free space left"
# final step ask if everything is ok?
DIALOG --yesno "Would you like to create Logical Volume ${LVDEVICE} like this?\nVolume Group:\n${LV}\nVolume Size:\n${LV_SIZE}\nContiguous Volume:\n${CONTIGUOUS}" 0 0 && LVFINISH="DONE"
done
DIALOG --infobox "Creating Logical Volume ${LVDEVICE}..." 0 0
if [[ "${LV_ALL}" = "1" ]]; then
lvcreate ${LV_EXTRA} -l +100%FREE ${LV} -n ${LVDEVICE} >${LOG} 2>&1
else
lvcreate ${LV_EXTRA} -L ${LV_SIZE} ${LV} -n ${LVDEVICE} >${LOG} 2>&1
fi
if [[ $? -gt 0 ]]; then
DIALOG --msgbox "Error creating Logical Volume ${LVDEVICE} (see ${LOG} for details)." 0 0
return 1
fi
}
# enter luks name
_enter_luks_name() {
LUKSDEVICE=""
while [[ "${LUKSDEVICE}" = "" ]]; do
DIALOG --inputbox "Enter the name for luks encrypted device ${PART}:\nfooname\n<yourname>\n\n" 15 65 "fooname" 2>${ANSWER} || return 1
LUKSDEVICE=$(cat ${ANSWER})
if ! [[ "$(cryptsetup status ${LUKSDEVICE} | grep inactive)" ]]; then
DIALOG --msgbox "ERROR: You have defined 2 identical luks encryption device names! Please enter another name." 8 65
LUKSDEVICE=""
fi
done
}
# enter luks passphrase
_enter_luks_passphrase () {
LUKSPASSPHRASE=""
while [[ "${LUKSPASSPHRASE}" = "" ]]; do
DIALOG --insecure --passwordbox "Enter passphrase for luks encrypted device ${PART}:" 0 0 2>${ANSWER} || return 1
LUKSPASS=$(cat ${ANSWER})
DIALOG --insecure --passwordbox "Retype passphrase for luks encrypted device ${PART}:" 0 0 2>${ANSWER} || return 1
LUKSPASS2=$(cat ${ANSWER})
if [[ -n "${LUKSPASS}" && -n "${LUKSPASS2}" && "${LUKSPASS}" = "${LUKSPASS2}" ]]; then
LUKSPASSPHRASE=${LUKSPASS}
echo ${LUKSPASSPHRASE} > /tmp/passphrase-${LUKSDEVICE}
LUKSPASSPHRASE=/tmp/passphrase-${LUKSDEVICE}
else
DIALOG --msgbox "Passphrases didn't match or was empty, please enter again." 0 0
fi
done
}
# opening luks
_opening_luks() {
DIALOG --infobox "Opening encrypted ${PART}..." 0 0
luksOpen_success="0"
while [[ "${luksOpen_success}" = "0" ]]; do
cryptsetup luksOpen ${PART} ${LUKSDEVICE} >${LOG} <${LUKSPASSPHRASE} && luksOpen_success=1
if [[ "${luksOpen_success}" = "0" ]]; then
DIALOG --msgbox "Error: Passphrases didn't match, please enter again." 0 0
_enter_luks_passphrase || return 1
fi
done
DIALOG --yesno "Would you like to save the passphrase of luks device in /etc/$(basename ${LUKSPASSPHRASE})?\nName:${LUKSDEVICE}" 0 0 || LUKSPASSPHRASE="ASK"
echo ${LUKSDEVICE} ${PART} /etc/$(basename ${LUKSPASSPHRASE}) >> /tmp/.crypttab
}
# help for luks
_helpluks()
{
DIALOG --msgbox "LUKS ENCRYPTION SUMMARY:\n
-----------------------------\n\n
Encryption is useful for two (related) reasons.\n
Firstly, it prevents anyone with physical access to your computer,\n
and your storage drive in particular, from getting the data from it\n
(unless they have your passphrase/key).\n
Secondly, it allows you to wipe the data on your storage drive with\n
far more confidence in the event of you selling or discarding\n
your drive.\n
Basically, it supplements the access control mechanisms of the operating\n
system (like file permissions) by making it harder to bypass the operating\n
system by inserting a boot CD, for example. Encrypting the root partition\n
prevents anyone from using this method to insert viruses or trojans onto\n
your computer.\n\n
ATTENTION:\n
Having encrypted partitions does not protect you from all possible\n
attacks. The encryption is only as good as your key management, and there\n
are other ways to break into computers, while they are running." 0 0
}
# create luks device
_luks()
{
NAME_SCHEME_PARAMETER_RUN=""
LUKSFINISH=""
while [[ "${LUKSFINISH}" != "DONE" ]]; do
activate_special_devices
# Remove all crypt devices with children
CRYPT_BLACKLIST="$(for i in $(${_LSBLK} NAME,TYPE | grep " crypt$" | cut -d' ' -f1 | sort -u); do
echo $(${_LSBLK} NAME ${i}) _
done)"
PARTS="$(for i in $(findpartitions); do
! [[ "$(echo "${CRYPT_BLACKLIST}" | egrep "${i} _")" ]] && echo $i _
done)"
# break if all devices are in use
if [[ "${PARTS}" = "" ]]; then
DIALOG --msgbox "No devices left for luks encryption." 0 0
return 1
fi
# show all devices with sizes
DIALOG --cr-wrap --msgbox "DISKS:\n$(_getavaildisks)\n\nPARTITIONS:\n$(_getavailpartitions)\n\n" 0 0
DIALOG --menu "Select device for luks encryption" 21 50 13 ${PARTS} 2>${ANSWER} || return 1
PART=$(cat ${ANSWER})
# enter luks name
_enter_luks_name
### TODO: offer more options for encrypt!
### defaults are used only
# final step ask if everything is ok?
DIALOG --yesno "Would you like to encrypt luks device below?\nName:${LUKSDEVICE}\nDevice:${PART}\n" 0 0 && LUKSFINISH="DONE"
done
_enter_luks_passphrase || return 1
DIALOG --infobox "Encrypting ${PART}..." 0 0
cryptsetup luksFormat ${PART} >${LOG} <${LUKSPASSPHRASE}
_opening_luks
}
autoprepare() {
# check on encrypted devices, else weird things can happen!
_stopluks
# check on raid devices, else weird things can happen during partitioning!
_stopmd
# check on lvm devices, else weird things can happen during partitioning!
_stoplvm
NAME_SCHEME_PARAMETER_RUN=""
# switch for mbr usage
set_guid
: >/tmp/.device-names
DISCS=$(blockdevices)
if [[ "$(echo ${DISCS} | wc -w)" -gt 1 ]]; then
DIALOG --cr-wrap --msgbox "Available Disks:\n\n$(_getavaildisks)\n" 0 0
DIALOG --menu "Select the storage drive to use" 14 55 7 $(blockdevices _) 2>"${ANSWER}" || return 1
DISC=$(cat ${ANSWER})
else
DISC="${DISCS}"
if [[ "${DISC}" = "" ]]; then
DIALOG --msgbox "ERROR: Setup cannot find available disk device, please use normal installation routine for partitioning and mounting devices." 0 0
return 1
fi
fi
BOOT_PART_SIZE=""
GUID_PART_SIZE=""
UEFISYS_PART_SIZE=""
DEFAULTFS=""
_UEFISYS_BOOTPART=""
UEFISYS_MOUNTPOINT=""
UEFISYS_PART_SET=""
BOOT_PART_SET=""
SWAP_PART_SET=""
ROOT_PART_SET=""
CHOSEN_FS=""
# get just the disk size in 1000*1000 MB
DISC_SIZE="$(($(${_LSBLK} SIZE -d -b ${DISC})/1000000))"
if [[ "${DISC_SIZE}" = "" ]]; then
DIALOG --msgbox "ERROR: Setup cannot detect size of your device, please use normal installation routine for partitioning and mounting devices." 0 0
return 1
fi
if [[ "${GUIDPARAMETER}" = "yes" ]]; then
DIALOG --inputbox "Enter the mountpoint of your UEFI SYSTEM PARTITION (Default is /boot) : " 0 0 "/boot" 2>"${ANSWER}" || return 1
UEFISYS_MOUNTPOINT="$(cat ${ANSWER})"
fi
if [[ "${UEFISYS_MOUNTPOINT}" == "/boot" ]]; then
DIALOG --msgbox "You have chosen to use /boot as the UEFISYS Mountpoint. The minimum partition size is 260 MiB and only FAT32 FS is supported" 0 0
_UEFISYS_BOOTPART="1"
fi
while [[ "${DEFAULTFS}" = "" ]]; do
FSOPTS=""
[[ "$(which mkfs.ext2 2>/dev/null)" ]] && FSOPTS="${FSOPTS} ext2 Ext2"
[[ "$(which mkfs.ext3 2>/dev/null)" ]] && FSOPTS="${FSOPTS} ext3 Ext3"
[[ "$(which mkfs.ext4 2>/dev/null)" ]] && FSOPTS="${FSOPTS} ext4 Ext4"
[[ "$(which mkfs.btrfs 2>/dev/null)" ]] && FSOPTS="${FSOPTS} btrfs Btrfs"
[[ "$(which mkfs.nilfs2 2>/dev/null)" ]] && FSOPTS="${FSOPTS} nilfs2 Nilfs2"
[[ "$(which mkfs.f2fs 2>/dev/null)" ]] && FSOPTS="${FSOPTS} f2fs F2FS"
[[ "$(which mkreiserfs 2>/dev/null)" ]] && FSOPTS="${FSOPTS} reiserfs Reiser3"
[[ "$(which mkfs.xfs 2>/dev/null)" ]] && FSOPTS="${FSOPTS} xfs XFS"
[[ "$(which mkfs.jfs 2>/dev/null)" ]] && FSOPTS="${FSOPTS} jfs JFS"
# create 1 MB bios_grub partition for grub BIOS GPT support
if [[ "${GUIDPARAMETER}" = "yes" ]]; then
GUID_PART_SIZE="2"
GPT_BIOS_GRUB_PART_SIZE="${GUID_PART_SIZE}"
_PART_NUM="1"
_GPT_BIOS_GRUB_PART_NUM="${_PART_NUM}"
DISC_SIZE="$((${DISC_SIZE}-${GUID_PART_SIZE}))"
fi
if [[ "${GUIDPARAMETER}" = "yes" ]]; then
if [[ "${_UEFISYS_BOOTPART}" == "1" ]]; then
while [[ "${UEFISYS_PART_SET}" = "" ]]; do
DIALOG --inputbox "Enter the size (MB) of your /boot partition,\nMinimum value is 260.\n\nDisk space left: ${DISC_SIZE} MB" 10 65 "1024" 2>${ANSWER} || return 1
UEFISYS_PART_SIZE="$(cat ${ANSWER})"
if [[ "${UEFISYS_PART_SIZE}" = "" ]]; then
DIALOG --msgbox "ERROR: You have entered a invalid size, please enter again." 0 0
else
if [[ "${UEFISYS_PART_SIZE}" -ge "${DISC_SIZE}" || "${UEFISYS_PART_SIZE}" -lt "260" || "${UEFISYS_PART_SIZE}" = "${DISC_SIZE}" ]]; then
DIALOG --msgbox "ERROR: You have entered an invalid size, please enter again." 0 0
else
BOOT_PART_SET=1
UEFISYS_PART_SET=1
_PART_NUM="$((${_PART_NUM}+1))"
_UEFISYS_PART_NUM="${_PART_NUM}"
fi
fi
done
else
while [[ "${UEFISYS_PART_SET}" = "" ]]; do
DIALOG --inputbox "Enter the size (MB) of your UEFI SYSTEM PARTITION,\nMinimum value is 260.\n\nDisk space left: ${DISC_SIZE} MB" 10 65 "1024" 2>${ANSWER} || return 1
UEFISYS_PART_SIZE="$(cat ${ANSWER})"
if [[ "${UEFISYS_PART_SIZE}" = "" ]]; then
DIALOG --msgbox "ERROR: You have entered a invalid size, please enter again." 0 0
else
if [[ "${UEFISYS_PART_SIZE}" -ge "${DISC_SIZE}" || "${UEFISYS_PART_SIZE}" -lt "260" || "${UEFISYS_PART_SIZE}" = "${DISC_SIZE}" ]]; then
DIALOG --msgbox "ERROR: You have entered an invalid size, please enter again." 0 0
else
UEFISYS_PART_SET=1
_PART_NUM="$((${_PART_NUM}+1))"
_UEFISYS_PART_NUM="${_PART_NUM}"
fi
fi
done
fi
DISC_SIZE="$((${DISC_SIZE}-${UEFISYS_PART_SIZE}))"
while [[ "${BOOT_PART_SET}" = "" ]]; do
DIALOG --inputbox "Enter the size (MB) of your /boot partition,\nMinimum value is 16.\n\nDisk space left: ${DISC_SIZE} MB" 10 65 "512" 2>${ANSWER} || return 1
BOOT_PART_SIZE="$(cat ${ANSWER})"
if [[ "${BOOT_PART_SIZE}" = "" ]]; then
DIALOG --msgbox "ERROR: You have entered a invalid size, please enter again." 0 0
else
if [[ "${BOOT_PART_SIZE}" -ge "${DISC_SIZE}" || "${BOOT_PART_SIZE}" -lt "16" || "${SBOOT_PART_SIZE}" = "${DISC_SIZE}" ]]; then
DIALOG --msgbox "ERROR: You have entered an invalid size, please enter again." 0 0
else
BOOT_PART_SET=1
_PART_NUM="$((${_UEFISYS_PART_NUM}+1))"
_BOOT_PART_NUM="${_PART_NUM}"
DISC_SIZE="$((${DISC_SIZE}-${BOOT_PART_SIZE}))"
fi
fi
done
else
while [[ "${BOOT_PART_SET}" = "" ]]; do
DIALOG --inputbox "Enter the size (MB) of your /boot partition,\nMinimum value is 16.\n\nDisk space left: ${DISC_SIZE} MB" 10 65 "512" 2>${ANSWER} || return 1
BOOT_PART_SIZE="$(cat ${ANSWER})"
if [[ "${BOOT_PART_SIZE}" = "" ]]; then
DIALOG --msgbox "ERROR: You have entered a invalid size, please enter again." 0 0
else
if [[ "${BOOT_PART_SIZE}" -ge "${DISC_SIZE}" || "${BOOT_PART_SIZE}" -lt "16" || "${SBOOT_PART_SIZE}" = "${DISC_SIZE}" ]]; then
DIALOG --msgbox "ERROR: You have entered an invalid size, please enter again." 0 0
else
BOOT_PART_SET=1
_PART_NUM="1"
_BOOT_PART_NUM="${_PART_NUM}"
DISC_SIZE="$((${DISC_SIZE}-${BOOT_PART_SIZE}))"
fi
fi
done
fi
SWAP_SIZE="256"
[[ "${DISC_SIZE}" -lt "256" ]] && SWAP_SIZE="${DISC_SIZE}"
while [[ "${SWAP_PART_SET}" = "" ]]; do
DIALOG --inputbox "Enter the size (MB) of your swap partition,\nMinimum value is > 0.\n\nDisk space left: ${DISC_SIZE} MB" 10 65 "${SWAP_SIZE}" 2>"${ANSWER}" || return 1
SWAP_PART_SIZE=$(cat ${ANSWER})
if [[ "${SWAP_PART_SIZE}" = "" || "${SWAP_PART_SIZE}" = "0" ]]; then
DIALOG --msgbox "ERROR: You have entered an invalid size, please enter again." 0 0
else
if [[ "${SWAP_PART_SIZE}" -ge "${DISC_SIZE}" ]]; then
DIALOG --msgbox "ERROR: You have entered a too large size, please enter again." 0 0
else
SWAP_PART_SET=1
_PART_NUM="$((${_PART_NUM}+1))"
_SWAP_PART_NUM="${_PART_NUM}"
fi
fi
done
while [[ "${CHOSEN_FS}" = "" ]]; do
DIALOG --menu "Select a filesystem for / and /home:" 16 45 9 ${FSOPTS} 2>${ANSWER} || return 1
FSTYPE=$(cat ${ANSWER})
DIALOG --yesno "${FSTYPE} will be used for / and /home. Is this OK?" 0 0 && CHOSEN_FS=1
done
# / and /home are subvolumes on btrfs
if ! [[ "${FSTYPE}" = "btrfs" ]]; then
DISC_SIZE="$((${DISC_SIZE}-${SWAP_PART_SIZE}))"
ROOT_SIZE="7500"
[[ "${DISC_SIZE}" -lt "7500" ]] && ROOT_SIZE="${DISC_SIZE}"
while [[ "${ROOT_PART_SET}" = "" ]]; do
DIALOG --inputbox "Enter the size (MB) of your / partition\nMinimum value is 2500,\nthe /home partition will use the remaining space.\n\nDisk space left: ${DISC_SIZE} MB" 10 65 "${ROOT_SIZE}" 2>"${ANSWER}" || return 1
ROOT_PART_SIZE=$(cat ${ANSWER})
if [[ "${ROOT_PART_SIZE}" = "" || "${ROOT_PART_SIZE}" = "0" || "${ROOT_PART_SIZE}" -lt "2500" ]]; then
DIALOG --msgbox "ERROR: You have entered an invalid size, please enter again." 0 0
else
if [[ "${ROOT_PART_SIZE}" -ge "${DISC_SIZE}" ]]; then
DIALOG --msgbox "ERROR: You have entered a too large size, please enter again." 0 0
else
DIALOG --yesno "$((${DISC_SIZE}-${ROOT_PART_SIZE})) MB will be used for your /home partition. Is this OK?" 0 0 && ROOT_PART_SET=1
fi
fi
done
fi
_PART_NUM="$((${_PART_NUM}+1))"
_ROOT_PART_NUM="${_PART_NUM}"
if ! [[ "${FSTYPE}" = "btrfs" ]]; then
_PART_NUM="$((${_PART_NUM}+1))"
fi
_HOME_PART_NUM="${_PART_NUM}"
DEFAULTFS=1
done
DIALOG --defaultno --yesno "${DISC} will be COMPLETELY ERASED! Are you absolutely sure?" 0 0 \
|| return 1
DEVICE=${DISC}
# validate DEVICE
if [[ ! -b "${DEVICE}" ]]; then
DIALOG --msgbox "Device '${DEVICE}' is not valid" 0 0
return 1
fi
# validate DEST
if [[ ! -d "${DESTDIR}" ]]; then
DIALOG --msgbox "Destination directory '${DESTDIR}' is not valid" 0 0
return 1
fi
[[ -e /tmp/.fstab ]] && rm -f /tmp/.fstab
# disable swap and all mounted partitions, umount / last!
_umountall
# we assume a /dev/sdX,/dev/vdX or /dev/nvmeXnY format
if [[ "${GUIDPARAMETER}" == "yes" ]]; then
# GPT (GUID) is supported only by 'parted' or 'sgdisk'
printk off
DIALOG --infobox "Partitioning ${DEVICE}" 0 0
# clean partition table to avoid issues!
sgdisk --zap ${DEVICE} &>/dev/null
# clear all magic strings/signatures - mdadm, lvm, partition tables etc.
dd if=/dev/zero of=${DEVICE} bs=512 count=2048 &>/dev/null
wipefs -a ${DEVICE} &>/dev/null
# create fresh GPT
sgdisk --clear ${DEVICE} &>/dev/null
# create actual partitions
sgdisk --set-alignment="2048" --new=${_GPT_BIOS_GRUB_PART_NUM}:0:+${GPT_BIOS_GRUB_PART_SIZE}M --typecode=${_GPT_BIOS_GRUB_PART_NUM}:EF02 --change-name=${_GPT_BIOS_GRUB_PART_NUM}:BIOS_GRUB ${DEVICE} > ${LOG}
sgdisk --set-alignment="2048" --new=${_UEFISYS_PART_NUM}:0:+${UEFISYS_PART_SIZE}M --typecode=${_UEFISYS_PART_NUM}:EF00 --change-name=${_UEFISYS_PART_NUM}:UEFI_SYSTEM ${DEVICE} > ${LOG}
if [[ "${_UEFISYS_BOOTPART}" == "1" ]]; then
sgdisk --attributes=${_UEFISYS_PART_NUM}:set:2 ${DEVICE} > ${LOG}
else
sgdisk --set-alignment="2048" --new=${_BOOT_PART_NUM}:0:+${BOOT_PART_SIZE}M --typecode=${_BOOT_PART_NUM}:8300 --attributes=${_BOOT_PART_NUM}:set:2 --change-name=${_BOOT_PART_NUM}:ARCHLINUX_BOOT ${DEVICE} > ${LOG}
fi
sgdisk --set-alignment="2048" --new=${_SWAP_PART_NUM}:0:+${SWAP_PART_SIZE}M --typecode=${_SWAP_PART_NUM}:8200 --change-name=${_SWAP_PART_NUM}:ARCHLINUX_SWAP ${DEVICE} > ${LOG}
if [[ "${FSTYPE}" = "btrfs" ]]; then
sgdisk --set-alignment="2048" --new=${_ROOT_PART_NUM}:0:0 --typecode=${_ROOT_PART_NUM}:8300 --change-name=${_ROOT_PART_NUM}:ARCHLINUX_ROOT ${DEVICE} > ${LOG}
else
sgdisk --set-alignment="2048" --new=${_ROOT_PART_NUM}:0:+${ROOT_PART_SIZE}M --typecode=${_ROOT_PART_NUM}:8300 --change-name=${_ROOT_PART_NUM}:ARCHLINUX_ROOT ${DEVICE} > ${LOG}
sgdisk --set-alignment="2048" --new=${_HOME_PART_NUM}:0:0 --typecode=${_HOME_PART_NUM}:8302 --change-name=${_HOME_PART_NUM}:ARCHLINUX_HOME ${DEVICE} > ${LOG}
fi
sgdisk --print ${DEVICE} > ${LOG}
else
# start at sector 1 for 4k drive compatibility and correct alignment
printk off
DIALOG --infobox "Partitioning ${DEVICE}" 0 0
# clean partitiontable to avoid issues!
dd if=/dev/zero of=${DEVICE} bs=512 count=2048 >/dev/null 2>&1
wipefs -a ${DEVICE} &>/dev/null
# create DOS MBR with parted
parted -a optimal -s ${DEVICE} unit MiB mktable msdos >/dev/null 2>&1
parted -a optimal -s ${DEVICE} unit MiB mkpart primary 1 $((${GUID_PART_SIZE}+${BOOT_PART_SIZE})) >${LOG}
parted -a optimal -s ${DEVICE} unit MiB set 1 boot on >${LOG}
parted -a optimal -s ${DEVICE} unit MiB mkpart primary $((${GUID_PART_SIZE}+${BOOT_PART_SIZE})) $((${GUID_PART_SIZE}+${BOOT_PART_SIZE}+${SWAP_PART_SIZE})) >${LOG}
# $(sgdisk -E ${DEVICE}) | grep ^[0-9] as end of last partition to keep the possibilty to convert to GPT later, instead of 100%
if [[ "${FSTYPE}" = "btrfs" ]]; then
parted -a optimal -s ${DEVICE} unit MiB mkpart primary $((${GUID_PART_SIZE}+${BOOT_PART_SIZE}+${SWAP_PART_SIZE})) $(sgdisk -E ${DEVICE} | grep ^[0-9])S >${LOG}
else
parted -a optimal -s ${DEVICE} unit MiB mkpart primary $((${GUID_PART_SIZE}+${BOOT_PART_SIZE}+${SWAP_PART_SIZE})) $((${GUID_PART_SIZE}+${BOOT_PART_SIZE}+${SWAP_PART_SIZE}+${ROOT_PART_SIZE})) >${LOG}
parted -a optimal -s ${DEVICE} unit MiB mkpart primary $((${GUID_PART_SIZE}+${BOOT_PART_SIZE}+${SWAP_PART_SIZE}+${ROOT_PART_SIZE})) $(sgdisk -E ${DEVICE} | grep ^[0-9])S >${LOG}
fi
fi
if [[ $? -gt 0 ]]; then
DIALOG --msgbox "Error partitioning ${DEVICE} (see ${LOG} for details)" 0 0
printk on
return 1
fi
# reread partitiontable for kernel
partprobe ${DEVICE}
printk on
## wait until /dev initialized correct devices
udevadm settle
if [[ "${NAME_SCHEME_PARAMETER_RUN}" == "" ]]; then
set_device_name_scheme || return 1
fi
## FSSPECS - default filesystem specs (the + is bootable flag)
## <partnum>:<mountpoint>:<partsize>:<fstype>[:<fsoptions>][:+]:labelname
## The partitions in FSSPECS list should be listed in the "mountpoint" order.
## Make sure the "root" partition is defined first in the FSSPECS list
_FSSPEC_ROOT_PART="${_ROOT_PART_NUM}:/:${FSTYPE}::ROOT_ARCH"
_FSSPEC_HOME_PART="${_HOME_PART_NUM}:/home:${FSTYPE}::HOME_ARCH"
_FSSPEC_SWAP_PART="${_SWAP_PART_NUM}:swap:swap::SWAP_ARCH"
_FSSPEC_BOOT_PART="${_BOOT_PART_NUM}:/boot:ext2::BOOT_ARCH"
_FSSPEC_UEFISYS_PART="${_UEFISYS_PART_NUM}:${UEFISYS_MOUNTPOINT}:vfat:-F32:EFISYS"
if [[ "${GUIDPARAMETER}" == "yes" ]]; then
if [[ "${_UEFISYS_BOOTPART}" == "1" ]]; then
FSSPECS="${_FSSPEC_ROOT_PART} ${_FSSPEC_UEFISYS_PART} ${_FSSPEC_HOME_PART} ${_FSSPEC_SWAP_PART}"
else
FSSPECS="${_FSSPEC_ROOT_PART} ${_FSSPEC_BOOT_PART} ${_FSSPEC_UEFISYS_PART} ${_FSSPEC_HOME_PART} ${_FSSPEC_SWAP_PART}"
fi
else
FSSPECS="${_FSSPEC_ROOT_PART} ${_FSSPEC_BOOT_PART} ${_FSSPEC_HOME_PART} ${_FSSPEC_SWAP_PART}"
fi
## make and mount filesystems
for fsspec in ${FSSPECS}; do
DOMKFS="yes"
PART="${DEVICE}$(echo ${fsspec} | tr -d ' ' | cut -f1 -d:)"
# Add check on nvme controller: Uses /dev/nvme0n1pX name scheme
[[ $(echo "${DEVICE}" | grep "nvme") ]] && PART="${DEVICE}p$(echo ${fsspec} | tr -d ' ' | cut -f1 -d:)"
MP="$(echo ${fsspec} | tr -d ' ' | cut -f2 -d:)"
FSTYPE="$(echo ${fsspec} | tr -d ' ' | cut -f3 -d:)"
FS_OPTIONS="$(echo ${fsspec} | tr -d ' ' | cut -f4 -d:)"
[[ "${FS_OPTIONS}" == "" ]] && FS_OPTIONS="NONE"
LABEL_NAME="$(echo ${fsspec} | tr -d ' ' | cut -f5 -d:)"
BTRFS_DEVICES="${PART}"
if [[ "${FSTYPE}" = "btrfs" ]]; then
BTRFS_COMPRESS="compress=lzo"
[[ "${MP}" = "/" ]] && BTRFS_SUBVOLUME="root"
[[ "${MP}" = "/home" ]] && BTRFS_SUBVOLUME="home" && DOMKFS="no"
DOSUBVOLUME="yes"
else
BTRFS_COMPRESS="NONE"
BTRFS_SUBVOLUME="NONE"
DOSUBVOLUME="no"
fi
BTRFS_LEVEL="NONE"
if ! [[ "${FSTYPE}" = "swap" ]]; then
DIALOG --infobox "Creating ${FSTYPE} on ${PART}\nwith FSLABEL ${LABEL_NAME} ,\nmounting to ${DESTDIR}${MP}" 0 0
else
DIALOG --infobox "Creating and activating swapspace on ${PART}" 0 0
fi
_mkfs ${DOMKFS} ${PART} ${FSTYPE} ${DESTDIR} ${MP} ${LABEL_NAME} ${FS_OPTIONS} ${BTRFS_DEVICES} ${BTRFS_LEVEL} ${BTRFS_SUBVOLUME} ${DOSUBVOLUME} ${BTRFS_COMPRESS} || return 1
sleep 1
done
DIALOG --msgbox "Auto-prepare was successful" 0 0
S_MKFSAUTO=1
}
detect_DISC() {
if [[ "${DISC}" == "" ]] || [[ ! "$(echo ${DISC} | grep '/dev/')" ]]; then
DISC="$(${_LSBLK} PKNAME "$(findmnt -vno SOURCE "${DESTDIR}/boot")")"
fi
if [[ "${DISC}" == "" ]]; then
DISC="$(${_LSBLK} PKNAME "$(findmnt -vno SOURCE "${DESTDIR}/")")"
fi
}
check_gpt() {
GUID_DETECTED=""
[[ "$(${_BLKID} -p -i -o value -s PTTYPE ${DISC})" == "gpt" ]] && GUID_DETECTED="1"
if [[ "${GUID_DETECTED}" == "" ]]; then
DIALOG --defaultno --yesno "Setup detected no GUID (gpt) partition table on ${DISC}.\n\nDo you want to convert the existing MBR table in ${DISC} to a GUID (gpt) partition table?" 0 0 || return 1
sgdisk --mbrtogpt ${DISC} > ${LOG} && GUID_DETECTED="1"
# reread partitiontable for kernel
partprobe ${DISC} > ${LOG}
if [[ "${GUID_DETECTED}" == "" ]]; then
DIALOG --defaultno --yesno "Conversion failed on ${DISC}.\nSetup detected no GUID (gpt) partition table on ${DISC}.\n\nDo you want to create a new GUID (gpt) table now on ${DISC}?\n\n${DISC} will be COMPLETELY ERASED! Are you absolutely sure?" 0 0 || return 1
# clean partition table to avoid issues!
sgdisk --zap ${DISC} &>/dev/null
# clear all magic strings/signatures - mdadm, lvm, partition tables etc.
dd if=/dev/zero of=${DISC} bs=512 count=2048 &>/dev/null
wipefs -a ${DISC} &>/dev/null
# create fresh GPT
sgdisk --clear ${DISC} &>/dev/null
GUID_DETECTED="1"
fi
fi
if [[ "${GUID_DETECTED}" == "1" ]]; then
### This check is not enabled in any function yet!
if [[ "${CHECK_UEFISYS_PART}" == "1" ]]; then
check_efisys_part
fi
if [[ "${CHECK_BIOS_BOOT_GRUB}" == "1" ]]; then
if ! [[ "$(sgdisk -p ${DISC} | grep 'EF02')" ]]; then
DIALOG --msgbox "Setup detected no BIOS BOOT PARTITION in ${DISC}. Please create a >=1 MB BIOS Boot partition for grub BIOS GPT support." 0 0
RUN_CFDISK="1"
fi
fi
fi
if [[ "${RUN_CFDISK}" == "1" ]]; then
DIALOG --msgbox "Now you'll be put into cfdisk where you can partition your storage drive.\nYou should make a swap partition and as many data partitions as you will need." 18 70
clear && cfdisk ${DISC}
# reread partitiontable for kernel
partprobe ${DEVICE}
fi
}
## check and mount EFISYS partition at ${UEFISYS_MOUNTPOINT}
check_efisys_part() {
detect_DISC
if [[ "$(${_BLKID} -p -i -o value -s PTTYPE ${DISC})" != "gpt" ]]; then
GUID_DETECTED=""
DIALOG --defaultno --yesno "Setup detected no GUID (gpt) partition table on ${DISC}.\nUEFI boot requires ${DISC} to be partitioned as GPT.\n\nDo you want to convert the existing MBR table in ${DISC} to a GUID (gpt) partition table?" 0 0 || return 1
DIALOG --msgbox "Setup will now try to non-destructively convert ${DISC} to GPT using sgdisk." 0 0
sgdisk --mbrtogpt ${DISC} > ${LOG} && GUID_DETECTED="1"
partprobe ${DISC} > ${LOG}
if [[ "${GUID_DETECTED}" == "" ]]; then
DIALOG --msgbox "Conversion failed on ${DISC}.\nSetup detected no GUID (gpt) partition table on ${DISC}.\n\n You need to fix your partition table first, before setup can proceed." 0 0
return 1
fi
fi
if [[ ! "$(sgdisk -p ${DISC} | grep 'EF00')" ]]; then
# Windows 10 recommends a minimum of 260MB Efi Systen Partition
DIALOG --msgbox "Setup detected no EFI System partition in ${DISC}. You will now be put into cfdisk. Please create a >= 260 MB partition with cfdisk type EFI System .\nWhen prompted (later) to format as FAT32, say YES.\nIf you already have a >=260 MB FAT32 EFI System partition, check whether that partition has EFI System cfdisk type code." 0 0
clear && cfdisk "${DISC}"
RUN_CFDISK=""
fi
if [[ "$(sgdisk -p ${DISC} | grep 'EF00')" ]]; then
# check on unique PARTTYPE c12a7328-f81f-11d2-ba4b-00a0c93ec93b for EFI System Partition type UUID
UEFISYS_PART="$(${_LSBLK} NAME,PARTTYPE ${DISC} | grep 'c12a7328-f81f-11d2-ba4b-00a0c93ec93b' | cut -d " " -f1)"
if [[ "$(${_LSBLK} FSTYPE ${UEFISYS_PART})" != "vfat" ]]; then
## Check whether EFISYS is FAT, otherwise inform the user and offer to format the partition as FAT32.
DIALOG --defaultno --yesno "Detected EFI System partition ${UEFISYS_PART} does not appear to be FAT formatted. UEFI Specification requires EFI System partition to be FAT32 formatted. Do you want to format ${UEFISYS_PART} as FAT32?\nNote: Setup will proceed even if you select NO. Some systems like Apple Macs may work with Non-FAT EFI System partition. However the installed system is not in conformance with UEFI Spec., and MAY NOT boot properly." 0 0 && _FORMAT_UEFISYS_FAT32="1"
fi
if [[ "$(${_LSBLK} FSTYPE ${UEFISYS_PART})" == "vfat" ]] && [[ "$(${_BLKID} -p -i -o value -s VERSION ${UEFISYS_PART})" != "FAT32" ]]; then
## Check whether EFISYS is FAT32 (specifically), otherwise warn the user about compatibility issues with UEFI Spec.
DIALOG --defaultno --yesno "Detected EFI System partition ${UEFISYS_PART} does not appear to be FAT32 formatted. Do you want to format ${UEFISYS_PART} as FAT32?\nNote: Setup will proceed even if you select NO. Most systems will boot fine even with FAT16 or FAT12 EFI System partition, however some firmwares may refuse to boot with a non-FAT32 EFI System partition. It is recommended to use FAT32 for maximum compatibility with UEFI Spec." 0 0 && _FORMAT_UEFISYS_FAT32="1"
fi
#autodetect efisys mountpoint, on fail ask for mountpoint
UEFISYS_MOUNTPOINT="/$(basename $(mount | grep "${UEFISYS_PART}" | cut -d " " -f 3))"
if [[ "${UEFISYS_MOUNTPOINT}" == "/" ]]; then
DIALOG --inputbox "Enter the mountpoint of your EFI System partition (Default is /boot): " 0 0 "/boot" 2>${ANSWER} || return 1
UEFISYS_MOUNTPOINT="$(cat ${ANSWER})"
fi
umount "${DESTDIR}/${UEFISYS_MOUNTPOINT}" &> /dev/null
umount "${UEFISYS_PART}" &> /dev/null
if [[ "${_FORMAT_UEFISYS_FAT32}" == "1" ]]; then
mkfs.vfat -F32 -n "EFISYS" "${UEFISYS_PART}"
fi
mkdir -p "${DESTDIR}/${UEFISYS_MOUNTPOINT}"
if [[ "$(${_LSBLK} FSTYPE ${UEFISYS_PART})" == "vfat" ]]; then
mount -o rw,flush -t vfat "${UEFISYS_PART}" "${DESTDIR}/${UEFISYS_MOUNTPOINT}"
else
DIALOG --msgbox "${UEFISYS_PART} is not formatted using FAT filesystem. Setup will go ahead but there might be issues using non-FAT FS for EFI System partition." 0 0
mount -o rw "${UEFISYS_PART}" "${DESTDIR}/${UEFISYS_MOUNTPOINT}"
fi
mkdir -p "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI" || true
else
DIALOG --msgbox "Setup did not find any EFI System partition in ${DISC}. Please create >= 260 MB FAT32 partition with cfdisk type EFI System code and try again." 0 0
return 1
fi
}
partition() {
# disable swap and all mounted partitions, umount / last!
_umountall
# activate dmraid
activate_dmraid
# check on encrypted devices, else weird things can happen!
_stopluks
# check on raid devices, else weird things can happen during partitioning!
_stopmd
# check on lvm devices, else weird things can happen during partitioning!
_stoplvm
# update dmraid
! [[ "$(dmraid_devices)" = "" ]] && _dmraid_update
# switch for mbr usage
set_guid
# Select disk to partition
DISCS=$(finddisks _)
DISCS="${DISCS} OTHER _ DONE +"
DIALOG --cr-wrap --msgbox "Available Disks:\n\n$(_getavaildisks)\n" 0 0
DISC=""
while true; do
# Prompt the user with a list of known disks
DIALOG --menu "Select the disk you want to partition\n(select DONE when finished)" 14 55 7 ${DISCS} 2>${ANSWER} || return 1
DISC=$(cat ${ANSWER})
if [[ "${DISC}" == "OTHER" ]]; then
DIALOG --inputbox "Enter the full path to the device you wish to partition" 8 65 "/dev/sda" 2>${ANSWER} || DISC=""
DISC=$(cat ${ANSWER})
fi
# Leave our loop if the user is done partitioning
[[ "${DISC}" == "DONE" ]] && break
MSDOS_DETECTED=""
if ! [[ "${DISC}" == "" ]]; then
if [[ "${GUIDPARAMETER}" == "yes" ]]; then
CHECK_BIOS_BOOT_GRUB=""
CHECK_UEFISYS_PART=""
RUN_CFDISK="1"
check_gpt
else
[[ "$(${_BLKID} -p -i -o value -s PTTYPE ${DISC})" == "dos" ]] && MSDOS_DETECTED="1"
if [[ "${MSDOS_DETECTED}" == "" ]]; then
DIALOG --defaultno --yesno "Setup detected no MS-DOS partition table on ${DISC}.\nDo you want to create a MS-DOS partition table now on ${DISC}?\n\n${DISC} will be COMPLETELY ERASED! Are you absolutely sure?" 0 0 || return 1
# clean partitiontable to avoid issues!
dd if=/dev/zero of=${DEVICE} bs=512 count=2048 >/dev/null 2>&1
wipefs -a ${DEVICE} /dev/null 2>&1
parted -a optimal -s ${DISC} mktable msdos >${LOG}
fi
# Partition disc
DIALOG --msgbox "Now you'll be put into cfdisk where you can partition your storage drive. You should make a swap partition and as many data partitions as you will need." 18 70
clear
cfdisk ${DISC}
# reread partitiontable for kernel
partprobe ${DISC}
fi
fi
done
# update dmraid
_dmraid_update
NEXTITEM="4"
S_PART=1
}
# scan and update btrfs devices
btrfs_scan() {
btrfs device scan >/dev/null 2>&1
}
# mount btrfs for checks
mount_btrfs() {
btrfs_scan
BTRFSMP="$(mktemp -d /tmp/brtfsmp.XXXX)"
mount ${PART} ${BTRFSMP}
}
# unmount btrfs after checks done
umount_btrfs() {
umount ${BTRFSMP}
rm -r ${BTRFSMP}
}
# Set BTRFS_DEVICES on detected btrfs devices
find_btrfs_raid_devices() {
btrfs_scan
if [[ "${DETECT_CREATE_FILESYSTEM}" = "no" && "${FSTYPE}" = "btrfs" ]]; then
for i in $(btrfs filesystem show ${PART} | cut -d " " -f 11); do
BTRFS_DEVICES="${BTRFS_DEVICES}#${i}"
done
fi
}
find_btrfs_raid_bootloader_devices() {
btrfs_scan
BTRFS_COUNT=1
if [[ "$(${_LSBLK} FSTYPE ${bootdev})" = "btrfs" ]]; then
BTRFS_DEVICES=""
for i in $(btrfs filesystem show ${bootdev} | cut -d " " -f 11); do
BTRFS_DEVICES="${BTRFS_DEVICES}#${i}"
BTRFS_COUNT=$((${BTRFS_COUNT}+1))
done
fi
}
# find btrfs subvolume
find_btrfs_subvolume() {
if [[ "${DETECT_CREATE_FILESYSTEM}" = "no" ]]; then
# existing btrfs subvolumes
mount_btrfs
for i in $(btrfs subvolume list ${BTRFSMP} | cut -d " " -f 9); do
echo ${i}
[[ "${1}" ]] && echo ${1}
done
umount_btrfs
fi
}
find_btrfs_bootloader_subvolume() {
BTRFS_SUBVOLUME_COUNT=1
if [[ "$(${_LSBLK} FSTYPE ${bootdev})" = "btrfs" ]]; then
BTRFS_SUBVOLUMES=""
PART="${bootdev}"
mount_btrfs
for i in $(btrfs subvolume list ${BTRFSMP} | cut -d " " -f 7); do
BTRFS_SUBVOLUMES="${BTRFS_SUBVOLUMES}#${i}"
BTRFS_SUBVOLUME_COUNT=$((${BTRFS_COUNT}+1))
done
umount_btrfs
fi
}
# subvolumes already in use
subvolumes_in_use() {
SUBVOLUME_IN_USE=""
for i in $(grep ${PART}[:#] /tmp/.parts); do
if [[ "$(echo ${i} | grep ":btrfs:")" ]]; then
SUBVOLUME_IN_USE="${SUBVOLUME_IN_USE} $(echo ${i} | cut -d: -f 9)"
fi
done
}
# ask for btrfs compress option
btrfs_compress() {
BTRFS_COMPRESS="NONE"
BTRFS_COMPRESSLEVELS="lzo - zlib - zstd -"
if [[ "${BTRFS_SUBVOLUME}" = "NONE" ]]; then
DIALOG --yesno "Would you like to compress the data on ${PART}?" 0 0 && BTRFS_COMPRESS="compress"
else
DIALOG --yesno "Would you like to compress the data on ${PART} subvolume=${BTRFS_SUBVOLUME}?" 0 0 && BTRFS_COMPRESS="compress"
fi
if [[ "${BTRFS_COMPRESS}" = "compress" ]]; then
DIALOG --menu "Select the compression method you want to use" 21 50 9 ${BTRFS_COMPRESSLEVELS} 2>${ANSWER} || return 1
BTRFS_COMPRESS="compress=$(cat ${ANSWER})"
fi
}
# values that are needed for fs creation
clear_fs_values() {
: >/tmp/.btrfs-devices
DOMKFS="no"
LABEL_NAME=""
FS_OPTIONS=""
BTRFS_DEVICES=""
BTRFS_LEVEL=""
BTRFS_SUBVOLUME=""
DOSUBVOLUME=""
BTRFS_COMPRESS=""
}
# do not ask for btrfs filesystem creation, if already prepared for creation!
check_btrfs_filesystem_creation() {
DETECT_CREATE_FILESYSTEM="no"
SKIP_FILESYSTEM="no"
SKIP_ASK_SUBVOLUME="no"
for i in $(grep ${PART}[:#] /tmp/.parts); do
if [[ "$(echo ${i} | grep ":btrfs:")" ]]; then
FSTYPE="btrfs"
SKIP_FILESYSTEM="yes"
# check on filesystem creation, skip subvolume asking then!
[[ "$(echo ${i} | cut -d: -f 4 | grep yes)" ]] && DETECT_CREATE_FILESYSTEM="yes"
[[ "${DETECT_CREATE_FILESYSTEM}" = "yes" ]] && SKIP_ASK_SUBVOLUME="yes"
fi
done
}
# remove devices with no subvolume from list and generate raid device list
btrfs_parts() {
if [[ -s /tmp/.btrfs-devices ]]; then
BTRFS_DEVICES=""
for i in $(cat /tmp/.btrfs-devices); do
BTRFS_DEVICES="${BTRFS_DEVICES}#${i}"
# remove device if no subvolume is used!
[[ "${BTRFS_SUBVOLUME}" = "NONE" ]] && PARTS="$(echo ${PARTS} | sed -e "s#${i}\ _##g")"
done
else
[[ "${BTRFS_SUBVOLUME}" = "NONE" ]] && PARTS="$(echo ${PARTS} | sed -e "s#${PART}\ _##g")"
fi
}
# choose raid level to use on btrfs device
btrfs_raid_level() {
BTRFS_RAIDLEVELS="NONE - raid0 - raid1 - raid5 - raid6 - raid10 - single -"
BTRFS_RAID_FINISH=""
BTRFS_LEVEL=""
BTRFS_DEVICE="${PART}"
: >/tmp/.btrfs-devices
DIALOG --msgbox "BTRFS DATA RAID OPTIONS:\n\nRAID5/6 are for testing purpose. Use with extreme care!\n\nIf you don't need this feature select NONE." 0 0
while [[ "${BTRFS_RAID_FINISH}" != "DONE" ]]; do
DIALOG --menu "Select the raid data level you want to use" 21 50 9 ${BTRFS_RAIDLEVELS} 2>${ANSWER} || return 1
BTRFS_LEVEL=$(cat ${ANSWER})
if [[ "${BTRFS_LEVEL}" = "NONE" ]]; then
echo "${BTRFS_DEVICE}" >>/tmp/.btrfs-devices
break
else
# take selected device as 1st device, add additional devices in part below.
select_btrfs_raid_devices
fi
done
}
# select btrfs raid devices
select_btrfs_raid_devices () {
# show all devices with sizes
# DIALOG --msgbox "DISKS:\n$(_getavaildisks)\n\nPARTITIONS:\n$(_getavailpartitions)" 0 0
# select the second device to use, no missing option available!
: >/tmp/.btrfs-devices
BTRFS_PART="${BTRFS_DEVICE}"
BTRFS_PARTS="${PARTS}"
echo "${BTRFS_PART}" >>/tmp/.btrfs-devices
BTRFS_PARTS="$(echo ${BTRFS_PARTS} | sed -e "s#${BTRFS_PART}\ _##g")"
RAIDNUMBER=2
DIALOG --menu "Select device ${RAIDNUMBER}" 21 50 13 ${BTRFS_PARTS} 2>${ANSWER} || return 1
BTRFS_PART=$(cat ${ANSWER})
echo "${BTRFS_PART}" >>/tmp/.btrfs-devices
while [[ "${BTRFS_PART}" != "DONE" ]]; do
BTRFS_DONE=""
RAIDNUMBER=$((${RAIDNUMBER} + 1))
# RAID5 needs 3 devices
# RAID6, RAID10 need 4 devices!
[[ "${RAIDNUMBER}" -ge 3 && ! "${BTRFS_LEVEL}" = "raid10" && ! "${BTRFS_LEVEL}" = "raid6" && ! "${BTRFS_LEVEL}" = "raid5" ]] && BTRFS_DONE="DONE _"
[[ "${RAIDNUMBER}" -ge 4 && "${BTRFS_LEVEL}" = "raid5" ]] && BTRFS_DONE="DONE _"
[[ "${RAIDNUMBER}" -ge 5 && "${BTRFS_LEVEL}" = "raid10" || "${BTRFS_LEVEL}" = "raid6" ]] && BTRFS_DONE="DONE _"
# clean loop from used partition and options
BTRFS_PARTS="$(echo ${BTRFS_PARTS} | sed -e "s#${BTRFS_PART}\ _##g")"
# add more devices
DIALOG --menu "Select device ${RAIDNUMBER}" 21 50 13 ${BTRFS_PARTS} ${BTRFS_DONE} 2>${ANSWER} || return 1
BTRFS_PART=$(cat ${ANSWER})
[[ "${BTRFS_PART}" = "DONE" ]] && break
echo "${BTRFS_PART}" >>/tmp/.btrfs-devices
done
# final step ask if everything is ok?
DIALOG --yesno "Would you like to create btrfs raid data like this?\n\nLEVEL:\n${BTRFS_LEVEL}\n\nDEVICES:\n$(for i in $(cat /tmp/.btrfs-devices); do echo "${i}\n"; done)" 0 0 && BTRFS_RAID_FINISH="DONE"
}
# prepare new btrfs device
prepare_btrfs() {
btrfs_raid_level || return 1
prepare_btrfs_subvolume || return 1
}
# prepare btrfs subvolume
prepare_btrfs_subvolume() {
DOSUBVOLUME="no"
BTRFS_SUBVOLUME="NONE"
if [[ "${SKIP_ASK_SUBVOLUME}" = "no" ]]; then
DIALOG --defaultno --yesno "Would you like to create a new subvolume on ${PART}?" 0 0 && DOSUBVOLUME="yes"
else
DOSUBVOLUME="yes"
fi
if [[ "${DOSUBVOLUME}" = "yes" ]]; then
BTRFS_SUBVOLUME="NONE"
while [[ "${BTRFS_SUBVOLUME}" = "NONE" ]]; do
DIALOG --inputbox "Enter the SUBVOLUME name for the device, keep it short\nand use no spaces or special\ncharacters." 10 65 2>${ANSWER} || return 1
BTRFS_SUBVOLUME=$(cat ${ANSWER})
check_btrfs_subvolume
done
else
BTRFS_SUBVOLUME="NONE"
fi
}
# check btrfs subvolume
check_btrfs_subvolume(){
[[ "${DOMKFS}" = "yes" && "${FSTYPE}" = "btrfs" ]] && DETECT_CREATE_FILESYSTEM="yes"
if [[ "${DETECT_CREATE_FILESYSTEM}" = "no" ]]; then
mount_btrfs
for i in $(btrfs subvolume list ${BTRFSMP} | cut -d " " -f 7); do
if [[ "$(echo ${i} | grep "${BTRFS_SUBVOLUME}"$)" ]]; then
DIALOG --msgbox "ERROR: You have defined 2 identical SUBVOLUME names or an empty name! Please enter another name." 8 65
BTRFS_SUBVOLUME="NONE"
fi
done
umount_btrfs
else
subvolumes_in_use
if [[ "$(echo ${SUBVOLUME_IN_USE} | egrep "${BTRFS_SUBVOLUME}")" ]]; then
DIALOG --msgbox "ERROR: You have defined 2 identical SUBVOLUME names or an empty name! Please enter another name." 8 65
BTRFS_SUBVOLUME="NONE"
fi
fi
}
# create btrfs subvolume
create_btrfs_subvolume() {
mount_btrfs
btrfs subvolume create ${BTRFSMP}/${_btrfssubvolume} >${LOG}
# change permission from 700 to 755
# to avoid warnings during package installation
chmod 755 ${BTRFSMP}/${_btrfssubvolume}
umount_btrfs
}
# choose btrfs subvolume from list
choose_btrfs_subvolume () {
BTRFS_SUBVOLUME="NONE"
SUBVOLUMES_DETECTED="no"
SUBVOLUMES=$(find_btrfs_subvolume _)
# check if subvolumes are present
[[ -n "${SUBVOLUMES}" ]] && SUBVOLUMES_DETECTED="yes"
subvolumes_in_use
for i in ${SUBVOLUME_IN_USE}; do
SUBVOLUMES=$(echo ${SUBVOLUMES} | sed -e "s#${i}\ _##g")
done
if [[ -n "${SUBVOLUMES}" ]]; then
DIALOG --menu "Select the subvolume to mount" 21 50 13 ${SUBVOLUMES} 2>${ANSWER} || return 1
BTRFS_SUBVOLUME=$(cat ${ANSWER})
else
if [[ "${SUBVOLUMES_DETECTED}" = "yes" ]]; then
DIALOG --msgbox "ERROR: All subvolumes of the device are already in use. Switching to create a new one now." 8 65
SKIP_ASK_SUBVOLUME=yes
prepare_btrfs_subvolume || return 1
fi
fi
}
# btrfs subvolume menu
btrfs_subvolume() {
FILESYSTEM_FINISH=""
if [[ "${FSTYPE}" = "btrfs" && "${DOMKFS}" = "no" ]]; then
if [[ "${ASK_MOUNTPOINTS}" = "1" ]]; then
# create subvolume if requested
# choose btrfs subvolume if present
prepare_btrfs_subvolume || return 1
if [[ "${BTRFS_SUBVOLUME}" = "NONE" ]]; then
choose_btrfs_subvolume || return 1
fi
else
# use device if no subvolume is present
choose_btrfs_subvolume || return 1
fi
btrfs_compress
fi
FILESYSTEM_FINISH="yes"
}
# add ssd mount options
ssd_optimization() {
# ext4, jfs, xfs, btrfs, nilfs2, f2fs have ssd mount option support
ssd_mount_options=""
if [[ "$(echo ${_fstype} | egrep 'ext4|jfs|btrfs|xfs|nilfs2|f2fs')" ]]; then
# check all underlying devices on ssd
for i in $(${_LSBLK} NAME,TYPE ${device} -s | grep "disk$" | cut -d' ' -f 1); do
# check for ssd
if [[ "$(cat /sys/block/$(basename ${i})/queue/rotational)" == "0" ]]; then
ssd_mount_options="noatime"
fi
done
fi
}
select_filesystem() {
FILESYSTEM_FINISH=""
# don't allow vfat as / filesystem, it will not work!
# don't allow ntfs as / filesystem, this is stupid!
FSOPTS=""
[[ "$(which mkfs.ext2 2>/dev/null)" ]] && FSOPTS="${FSOPTS} ext2 Ext2"
[[ "$(which mkfs.ext3 2>/dev/null)" ]] && FSOPTS="${FSOPTS} ext3 Ext3"
[[ "$(which mkfs.ext4 2>/dev/null)" ]] && FSOPTS="${FSOPTS} ext4 Ext4"
[[ "$(which mkfs.btrfs 2>/dev/null)" ]] && FSOPTS="${FSOPTS} btrfs Btrfs"
[[ "$(which mkfs.nilfs2 2>/dev/null)" ]] && FSOPTS="${FSOPTS} nilfs2 Nilfs2"
[[ "$(which mkfs.f2fs 2>/dev/null)" ]] && FSOPTS="${FSOPTS} f2fs F2FS"
[[ "$(which mkreiserfs 2>/dev/null)" ]] && FSOPTS="${FSOPTS} reiserfs Reiser3"
[[ "$(which mkfs.xfs 2>/dev/null)" ]] && FSOPTS="${FSOPTS} xfs XFS"
[[ "$(which mkfs.jfs 2>/dev/null)" ]] && FSOPTS="${FSOPTS} jfs JFS"
[[ "$(which mkfs.ntfs 2>/dev/null)" && "${DO_ROOT}" = "DONE" ]] && FSOPTS="${FSOPTS} ntfs-3g NTFS"
[[ "$(which mkfs.vfat 2>/dev/null)" && "${DO_ROOT}" = "DONE" ]] && FSOPTS="${FSOPTS} vfat FAT32"
DIALOG --menu "Select a filesystem for ${PART}" 21 50 13 ${FSOPTS} 2>${ANSWER} || return 1
FSTYPE=$(cat ${ANSWER})
}
enter_mountpoint() {
FILESYSTEM_FINISH=""
MP=""
while [[ "${MP}" = "" ]]; do
DIALOG --inputbox "Enter the mountpoint for ${PART}" 8 65 "/boot" 2>${ANSWER} || return 1
MP=$(cat ${ANSWER})
if grep ":${MP}:" /tmp/.parts; then
DIALOG --msgbox "ERROR: You have defined 2 identical mountpoints! Please select another mountpoint." 8 65
MP=""
fi
done
}
# set sane values for paramaters, if not already set
check_mkfs_values() {
# Set values, to not confuse mkfs call!
[[ "${FS_OPTIONS}" = "" ]] && FS_OPTIONS="NONE"
[[ "${BTRFS_DEVICES}" = "" ]] && BTRFS_DEVICES="NONE"
[[ "${BTRFS_LEVEL}" = "" ]] && BTRFS_LEVEL="NONE"
[[ "${BTRFS_SUBVOLUME}" = "" ]] && BTRFS_SUBVOLUME="NONE"
[[ "${DOSUBVOLUME}" = "" ]] && DOSUBVOLUME="no"
[[ "${LABEL_NAME}" = "" && -n "$(${_LSBLK} LABEL ${PART})" ]] && LABEL_NAME="$(${_LSBLK} LABEL ${PART})"
[[ "${LABEL_NAME}" = "" ]] && LABEL_NAME="NONE"
}
create_filesystem() {
FILESYSTEM_FINISH=""
LABEL_NAME=""
FS_OPTIONS=""
BTRFS_DEVICES=""
BTRFS_LEVEL=""
DIALOG --yesno "Would you like to create a filesystem on ${PART}?\n\n(This will overwrite existing data!)" 0 0 && DOMKFS="yes"
if [[ "${DOMKFS}" = "yes" ]]; then
while [[ "${LABEL_NAME}" = "" ]]; do
DIALOG --inputbox "Enter the LABEL name for the device, keep it short\n(not more than 12 characters) and use no spaces or special\ncharacters." 10 65 \
"$(${_LSBLK} LABEL ${PART})" 2>${ANSWER} || return 1
LABEL_NAME=$(cat ${ANSWER})
if grep ":${LABEL_NAME}$" /tmp/.parts; then
DIALOG --msgbox "ERROR: You have defined 2 identical LABEL names! Please enter another name." 8 65
LABEL_NAME=""
fi
done
if [[ "${FSTYPE}" = "btrfs" ]]; then
prepare_btrfs || return 1
btrfs_compress
fi
DIALOG --inputbox "Enter additional options to the filesystem creation utility.\nUse this field only, if the defaults are not matching your needs,\nelse just leave it empty." 10 70 2>${ANSWER} || return 1
FS_OPTIONS=$(cat ${ANSWER})
fi
FILESYSTEM_FINISH="yes"
}
mountpoints() {
NAME_SCHEME_PARAMETER_RUN=""
while [[ "${PARTFINISH}" != "DONE" ]]; do
activate_special_devices
: >/tmp/.device-names
: >/tmp/.fstab
: >/tmp/.parts
#
# Select mountpoints
#
DIALOG --cr-wrap --msgbox "Available partitions:\n\n$(_getavailpartitions)\n" 0 0
PARTS=$(findpartitions _)
DO_SWAP=""
while [[ "${DO_SWAP}" != "DONE" ]]; do
FSTYPE="swap"
DIALOG --menu "Select the partition to use as swap" 21 50 13 NONE - ${PARTS} 2>${ANSWER} || return 1
PART=$(cat ${ANSWER})
if [[ "${PART}" != "NONE" ]]; then
clear_fs_values
if [[ "${ASK_MOUNTPOINTS}" = "1" ]]; then
create_filesystem
else
FILESYSTEM_FINISH="yes"
fi
else
FILESYSTEM_FINISH="yes"
fi
[[ "${FILESYSTEM_FINISH}" = "yes" ]] && DO_SWAP=DONE
done
check_mkfs_values
if [[ "${PART}" != "NONE" ]]; then
PARTS="$(echo ${PARTS} | sed -e "s#${PART}\ _##g")"
echo "${PART}:swap:swap:${DOMKFS}:${LABEL_NAME}:${FS_OPTIONS}:${BTRFS_DEVICES}:${BTRFS_LEVEL}:${BTRFS_SUBVOLUME}:${DOSUBVOLUME}:${BTRFS_COMPRESS}" >>/tmp/.parts
fi
DO_ROOT=""
while [[ "${DO_ROOT}" != "DONE" ]]; do
DIALOG --menu "Select the partition to mount as /" 21 50 13 ${PARTS} 2>${ANSWER} || return 1
PART=$(cat ${ANSWER})
PART_ROOT=${PART}
# Select root filesystem type
FSTYPE="$(${_LSBLK} FSTYPE ${PART})"
# clear values first!
clear_fs_values
check_btrfs_filesystem_creation
if [[ "${ASK_MOUNTPOINTS}" = "1" && "${SKIP_FILESYSTEM}" = "no" ]]; then
select_filesystem && create_filesystem && btrfs_subvolume
else
btrfs_subvolume
fi
[[ "${FILESYSTEM_FINISH}" = "yes" ]] && DO_ROOT=DONE
done
find_btrfs_raid_devices
btrfs_parts
check_mkfs_values
echo "${PART}:${FSTYPE}:/:${DOMKFS}:${LABEL_NAME}:${FS_OPTIONS}:${BTRFS_DEVICES}:${BTRFS_LEVEL}:${BTRFS_SUBVOLUME}:${DOSUBVOLUME}:${BTRFS_COMPRESS}" >>/tmp/.parts
! [[ "${FSTYPE}" = "btrfs" ]] && PARTS="$(echo ${PARTS} | sed -e "s#${PART}\ _##g")"
#
# Additional partitions
#
while [[ "${PART}" != "DONE" ]]; do
DO_ADDITIONAL=""
while [[ "${DO_ADDITIONAL}" != "DONE" ]]; do
DIALOG --menu "Select any additional partitions to mount under your new root (select DONE when finished)" 21 52 13 ${PARTS} DONE _ 2>${ANSWER} || return 1
PART=$(cat ${ANSWER})
if [[ "${PART}" != "DONE" ]]; then
FSTYPE="$(${_LSBLK} FSTYPE ${PART})"
# clear values first!
clear_fs_values
check_btrfs_filesystem_creation
# Select a filesystem type
if [[ "${ASK_MOUNTPOINTS}" = "1" && "${SKIP_FILESYSTEM}" = "no" ]]; then
enter_mountpoint && select_filesystem && create_filesystem && btrfs_subvolume
else
enter_mountpoint
btrfs_subvolume
fi
else
FILESYSTEM_FINISH="yes"
fi
[[ "${FILESYSTEM_FINISH}" = "yes" ]] && DO_ADDITIONAL="DONE"
done
if [[ "${PART}" != "DONE" ]]; then
find_btrfs_raid_devices
btrfs_parts
check_mkfs_values
echo "${PART}:${FSTYPE}:${MP}:${DOMKFS}:${LABEL_NAME}:${FS_OPTIONS}:${BTRFS_DEVICES}:${BTRFS_LEVEL}:${BTRFS_SUBVOLUME}:${DOSUBVOLUME}:${BTRFS_COMPRESS}" >>/tmp/.parts
! [[ "${FSTYPE}" = "btrfs" ]] && PARTS="$(echo ${PARTS} | sed -e "s#${PART}\ _##g")"
fi
done
DIALOG --yesno "Would you like to create and mount the filesytems like this?\n\nSyntax\n------\nDEVICE:TYPE:MOUNTPOINT:FORMAT:LABEL:FSOPTIONS:BTRFS_DETAILS\n\n$(for i in $(cat /tmp/.parts | sed -e 's, ,#,g'); do echo "${i}\n";done)" 0 0 && PARTFINISH="DONE"
done
# disable swap and all mounted partitions
_umountall
if [[ "${NAME_SCHEME_PARAMETER_RUN}" = "" ]]; then
set_device_name_scheme || return 1
fi
printk off
for line in $(cat /tmp/.parts); do
PART=$(echo ${line} | cut -d: -f 1)
FSTYPE=$(echo ${line} | cut -d: -f 2)
MP=$(echo ${line} | cut -d: -f 3)
DOMKFS=$(echo ${line} | cut -d: -f 4)
LABEL_NAME=$(echo ${line} | cut -d: -f 5)
FS_OPTIONS=$(echo ${line} | cut -d: -f 6)
BTRFS_DEVICES=$(echo ${line} | cut -d: -f 7)
BTRFS_LEVEL=$(echo ${line} | cut -d: -f 8)
BTRFS_SUBVOLUME=$(echo ${line} | cut -d: -f 9)
DOSUBVOLUME=$(echo ${line} | cut -d: -f 10)
BTRFS_COMPRESS=$(echo ${line} | cut -d: -f 11)
if [[ "${DOMKFS}" = "yes" ]]; then
if [[ "${FSTYPE}" = "swap" ]]; then
DIALOG --infobox "Creating and activating swapspace on ${PART}" 0 0
else
DIALOG --infobox "Creating ${FSTYPE} on ${PART},\nmounting to ${DESTDIR}${MP}" 0 0
fi
_mkfs yes ${PART} ${FSTYPE} ${DESTDIR} ${MP} ${LABEL_NAME} ${FS_OPTIONS} ${BTRFS_DEVICES} ${BTRFS_LEVEL} ${BTRFS_SUBVOLUME} ${DOSUBVOLUME} ${BTRFS_COMPRESS} || return 1
else
if [[ "${FSTYPE}" = "swap" ]]; then
DIALOG --infobox "Activating swapspace on ${PART}" 0 0
else
DIALOG --infobox "Mounting ${FSTYPE} on ${PART} to ${DESTDIR}${MP}" 0 0
fi
_mkfs no ${PART} ${FSTYPE} ${DESTDIR} ${MP} ${LABEL_NAME} ${FS_OPTIONS} ${BTRFS_DEVICES} ${BTRFS_LEVEL} ${BTRFS_SUBVOLUME} ${DOSUBVOLUME} ${BTRFS_COMPRESS} || return 1
fi
sleep 1
done
printk on
DIALOG --msgbox "Partitions were successfully mounted." 0 0
NEXTITEM="5"
S_MKFS=1
}
# _mkfs()
# Create and mount filesystems in our destination system directory.
#
# args:
# domk: Whether to make the filesystem or use what is already there
# device: Device filesystem is on
# fstype: type of filesystem located at the device (or what to create)
# dest: Mounting location for the destination system
# mountpoint: Mount point inside the destination system, e.g. '/boot'
# returns: 1 on failure
_mkfs() {
local _domk=${1}
local _device=${2}
local _fstype=${3}
local _dest=${4}
local _mountpoint=${5}
local _labelname=${6}
local _fsoptions=${7}
local _btrfsdevices="$(echo ${8} | sed -e 's|#| |g')"
local _btrfslevel=${9}
local _btrfssubvolume=${10}
local _dosubvolume=${11}
local _btrfscompress=${12}
# correct empty entries
[[ "${_fsoptions}" = "NONE" ]] && _fsoptions=""
[[ "${_btrfscompress}" = "NONE" ]] && _btrfscompress=""
[[ "${_btrfssubvolume}" = "NONE" ]] && _btrfssubvolume=""
# add btrfs raid level, if needed
[[ ! "${_btrfslevel}" = "NONE" && "${_fstype}" = "btrfs" ]] && _fsoptions="${_fsoptions} -m ${_btrfslevel} -d ${_btrfslevel}"
# add btrfs options, minimum requirement linux 3.14 -O no-holes
[[ "${_fstype}" = "btrfs" ]] && _fsoptions="${_fsoptions} -O no-holes"
# we have two main cases: "swap" and everything else.
if [[ "${_fstype}" = "swap" ]]; then
swapoff ${_device} >/dev/null 2>&1
if [[ "${_domk}" = "yes" ]]; then
mkswap -L ${_labelname} ${_device} >${LOG} 2>&1
if [[ $? != 0 ]]; then
DIALOG --msgbox "Error creating swap: mkswap ${_device}" 0 0
return 1
fi
fi
swapon ${_device} >${LOG} 2>&1
if [[ $? != 0 ]]; then
DIALOG --msgbox "Error activating swap: swapon ${_device}" 0 0
return 1
fi
else
# make sure the fstype is one we can handle
local knownfs=0
for fs in xfs jfs reiserfs ext2 ext3 ext4 f2fs btrfs nilfs2 ntfs-3g vfat; do
[[ "${_fstype}" = "${fs}" ]] && knownfs=1 && break
done
if [[ ${knownfs} -eq 0 ]]; then
DIALOG --msgbox "unknown fstype ${_fstype} for ${_device}" 0 0
return 1
fi
# if we were tasked to create the filesystem, do so
if [[ "${_domk}" = "yes" ]]; then
local ret
case ${_fstype} in
xfs) mkfs.xfs ${_fsoptions} -L ${_labelname} -f ${_device} >${LOG} 2>&1; ret=$? ;;
jfs) yes | mkfs.jfs ${_fsoptions} -L ${_labelname} ${_device} >${LOG} 2>&1; ret=$? ;;
reiserfs) yes | mkreiserfs ${_fsoptions} -l ${_labelname} ${_device} >${LOG} 2>&1; ret=$? ;;
ext2) mkfs.ext2 -F -L ${_fsoptions} ${_labelname} ${_device} >${LOG} 2>&1; ret=$? ;;
ext3) mke2fs -F ${_fsoptions} -L ${_labelname} -t ext3 ${_device} >${LOG} 2>&1; ret=$? ;;
ext4) mke2fs -F ${_fsoptions} -L ${_labelname} -t ext4 ${_device} >${LOG} 2>&1; ret=$? ;;
f2fs) mkfs.f2fs ${_fsoptions} -l ${_labelname} ${_device} >${LOG} 2>&1; ret=$? ;;
btrfs) mkfs.btrfs -f ${_fsoptions} -L ${_labelname} ${_btrfsdevices} >${LOG} 2>&1; ret=$? ;;
nilfs2) mkfs.nilfs2 -f ${_fsoptions} -L ${_labelname} ${_device} >${LOG} 2>&1; ret=$? ;;
ntfs-3g) mkfs.ntfs ${_fsoptions} -L ${_labelname} ${_device} >${LOG} 2>&1; ret=$? ;;
vfat) mkfs.vfat -F32 ${_fsoptions} -n ${_labelname} ${_device} >${LOG} 2>&1; ret=$? ;;
# don't handle anything else here, we will error later
esac
if [[ ${ret} != 0 ]]; then
DIALOG --msgbox "Error creating filesystem ${_fstype} on ${_device}" 0 0
return 1
fi
sleep 2
fi
if [[ "${_fstype}" = "btrfs" && -n "${_btrfssubvolume}" && "${_dosubvolume}" = "yes" ]]; then
create_btrfs_subvolume
fi
btrfs_scan
sleep 2
# create our mount directory
mkdir -p ${_dest}${_mountpoint}
# add ssd optimization before mounting
ssd_optimization
_mountoptions=""
# prepare btrfs mount options
[[ -n "${_btrfssubvolume}" ]] && _mountoptions="${_mountoptions} subvol=${_btrfssubvolume}"
[[ -n "${_btrfscompress}" ]] && _mountoptions="${_mountoptions} ${_btrfscompress}"
_mountoptions="${_mountoptions} ${ssd_mount_options}"
# eleminate spaces at beginning and end, replace other spaces with ,
_mountoptions="$(echo ${_mountoptions} | sed -e 's#^ *##g' -e 's# *$##g' | sed -e 's# #,#g')"
# mount the bad boy
mount -t ${_fstype} -o "${_mountoptions}" ${_device} ${_dest}${_mountpoint} >${LOG} 2>&1
if [[ $? != 0 ]]; then
DIALOG --msgbox "Error mounting ${_dest}${_mountpoint}" 0 0
return 1
fi
# btrfs needs balancing, else weird things could happen
[[ "${_fstype}" = "btrfs" ]] && btrfs balance start --full-balance ${_dest}${_mountpoint} >${LOG} 2>&1
# change permission of base directories to correct permission
# to avoid btrfs issues
if [[ "${_mountpoint}" = "/tmp" ]]; then
chmod 1777 ${_dest}${_mountpoint}
elif [[ "${_mountpoint}" = "/root" ]]; then
chmod 750 ${_dest}${_mountpoint}
else
chmod 755 ${_dest}${_mountpoint}
fi
fi
# add to .device-names for config files
local _fsuuid="$(getfsuuid ${_device})"
local _fslabel="$(getfslabel ${_device})"
if [[ "${GUID_DETECTED}" == "1" ]]; then
local _partuuid="$(getpartuuid ${_device})"
local _partlabel="$(getpartlabel ${_device})"
echo "# DEVICE DETAILS: ${_device} PARTUUID=${_partuuid} PARTLABEL=${_partlabel} UUID=${_fsuuid} LABEL=${_fslabel}" >> /tmp/.device-names
else
echo "# DEVICE DETAILS: ${_device} UUID=${_fsuuid} LABEL=${_fslabel}" >> /tmp/.device-names
fi
# add to temp fstab
if [[ "${NAME_SCHEME_PARAMETER}" == "FSUUID" ]]; then
if [[ -n "${_fsuuid}" ]]; then
_device="UUID=${_fsuuid}"
fi
elif [[ "${NAME_SCHEME_PARAMETER}" == "FSLABEL" ]]; then
if [[ -n "${_fslabel}" ]]; then
_device="LABEL=${_fslabel}"
fi
else
if [[ "${GUID_DETECTED}" == "1" ]]; then
if [[ "${NAME_SCHEME_PARAMETER}" == "PARTUUID" ]]; then
if [[ -n "${_partuuid}" ]]; then
_device="PARTUUID=${_partuuid}"
fi
elif [[ "${NAME_SCHEME_PARAMETER}" == "PARTLABEL" ]]; then
if [[ -n "${_partlabel}" ]]; then
_device="PARTLABEL=${_partlabel}"
fi
fi
fi
fi
# / root is not needed in fstab, it's mounted automatically
# systemd supports detection on GPT disks:
# /boot as ESP: c12a7328-f81f-11d2-ba4b-00a0c93ec93b
# swap: 0657fd6d-a4ab-43c4-84e5-0933c84b4f4f
# /home: 933ac7e1-2eb4-4f13-b844-0e14e2aef915
# Complex devices, like mdadm, encrypt or lvm are not supported
# _GUID_VALUE:
# get real device name from lsblk first to get GUID_VALUE from blkid
_GUID_VALUE="$(${_BLKID} -p -i -s PART_ENTRY_TYPE -o value $(${_LSBLK} NAME,UUID,LABEL,PARTLABEL,PARTUUID | grep $(echo ${_device} | cut -d"=" -f2) | cut -d" " -f 1))"
if ! [[ "${_GUID_VALUE}" == "933ac7e1-2eb4-4f13-b844-0e14e2aef915" && "${_mountpoint}" == "/home" || "${_GUID_VALUE}" == "0657fd6d-a4ab-43c4-84e5-0933c84b4f4f" && "${_mountpoint}" == "swap" || "${_GUID_VALUE}" == "c12a7328-f81f-11d2-ba4b-00a0c93ec93b" && "${_mountpoint}" == "/boot" && "${_DETECTED_UEFI_BOOT}" == "1" || "${_mountpoint}" == "/" ]]; then
if [[ "${_mountoptions}" == "" ]]; then
echo -n "${_device} ${_mountpoint} ${_fstype} defaults 0 " >>/tmp/.fstab
else
echo -n "${_device} ${_mountpoint} ${_fstype} defaults,${_mountoptions} 0 " >>/tmp/.fstab
fi
if [[ "${_fstype}" = "swap" || "${_fstype}" = "btrfs" ]]; then
echo "0" >>/tmp/.fstab
else
echo "1" >>/tmp/.fstab
fi
fi
unset _mountoptions
unset _btrfssubvolume
unset _btrfscompress
}
getsource() {
S_SRC=0
if [[ "${MODE}" = "network" ]]; then
select_mirror || return 1
fi
S_SRC=1
}
# select_mirror()
# Prompt user for preferred mirror and set ${SYNC_URL}
#
# args: none
# returns: nothing
select_mirror() {
NEXTITEM="4"
## Download updated mirrorlist, if possible
dialog --infobox "Downloading latest mirrorlist ..." 0 0
${DLPROG} -q "https://www.archlinux.org/mirrorlist/?country=all&protocol=http&protocol=https&ip_version=4&ip_version=6&use_mirror_status=on" -O /tmp/pacman_mirrorlist.txt -o ${LOG} 2>/dev/null
if [[ "$(grep '#Server = http:' /tmp/pacman_mirrorlist.txt)" ]]; then
mv "${MIRRORLIST}" "${MIRRORLIST}.bak"
cp /tmp/pacman_mirrorlist.txt "${MIRRORLIST}"
fi
# FIXME: this regex doesn't honor commenting
MIRRORS=$(egrep -o '((http)|(https))://[^/]*' "${MIRRORLIST}" | sed 's|$| _|g')
DIALOG --menu "Select a mirror" 14 55 7 \
${MIRRORS} \
"Custom" "_" 2>${ANSWER} || return 1
local _server=$(cat ${ANSWER})
if [[ "${_server}" = "Custom" ]]; then
DIALOG --inputbox "Enter the full URL to repositories." 8 65 \
"" 2>${ANSWER} || return 1
SYNC_URL=$(cat ${ANSWER})
else
# Form the full URL for our mirror by grepping for the server name in
# our mirrorlist and pulling the full URL out. Substitute 'core' in
# for the repository name, and ensure that if it was listed twice we
# only return one line for the mirror.
SYNC_URL=$(egrep -o "${_server}.*" "${MIRRORLIST}" | head -n1)
fi
echo "Using mirror: ${SYNC_URL}" >${LOG}
echo "Server = "${SYNC_URL}"" >> /etc/pacman.d/mirrorlist
if [[ "${DOTESTING}" == "yes" ]]; then
echo "[testing]" >> /etc/pacman.conf
echo "Include = /etc/pacman.d/mirrorlist" >> /etc/pacman.conf
echo "[community-testing]" >> /etc/pacman.conf
echo "Include = /etc/pacman.d/mirrorlist" >> /etc/pacman.conf
fi
}
# dotesting()
# enable testing repository on network install
dotesting() {
DOTESTING=""
DIALOG --defaultno --yesno "Do you want to enable [testing] repository?\n\nOnly enable this if you need latest available packages for testing purposes!" 8 60 && DOTESTING="yes"
}
# configures pacman and syncs db on destination system
# params: none
# returns: 1 on error
prepare_pacman() {
# Set up the necessary directories for pacman use
[[ ! -d "${DESTDIR}/var/cache/pacman/pkg" ]] && mkdir -m 755 -p "${DESTDIR}/var/cache/pacman/pkg"
[[ ! -d "${DESTDIR}/var/lib/pacman" ]] && mkdir -m 755 -p "${DESTDIR}/var/lib/pacman"
DIALOG --infobox "Refreshing package database..." 6 45
${PACMAN} -Sy >${LOG} 2>&1 || return 1
if [[ $? -ne 0 ]]; then
DIALOG --msgbox "Pacman preparation failed! Check ${LOG} for errors." 6 60
return 1
fi
return 0
}
# Set PACKAGES parameter before running to install wanted packages
run_pacman(){
# create chroot environment on target system
# code straight from mkarchroot
chroot_mount
# execute pacman in a subshell so we can follow its progress
# pacman output goes /tmp/pacman.log
# /tmp/setup-pacman-running acts as a lockfile
( \
echo "Installing Packages..." >/tmp/pacman.log ; \
echo >>/tmp/pacman.log ; \
touch /tmp/setup-pacman-running ; \
${PACMAN} -S ${PACKAGES} 2>&1 >> /tmp/pacman.log ; \
echo $? > /tmp/.pacman-retcode ; \
if [[ $(cat /tmp/.pacman-retcode) -ne 0 ]]; then
echo -e "\nPackage Installation FAILED." >>/tmp/pacman.log
else
echo -e "\nPackage Installation Complete." >>/tmp/pacman.log
fi
rm /tmp/setup-pacman-running
) &
# display pacman output while it's running
sleep 2
dialog --backtitle "${TITLE}" --title " Installing... Please Wait " \
--no-kill --tailboxbg "/tmp/pacman.log" 18 70 2>${ANSWER}
while [[ -f /tmp/setup-pacman-running ]]; do
/usr/bin/true
done
kill $(cat ${ANSWER})
# pacman finished, display scrollable output
local _result=''
if [[ $(cat /tmp/.pacman-retcode) -ne 0 ]]; then
_result="Installation Failed (see errors below)"
else
_result="Installation Complete"
fi
rm /tmp/.pacman-retcode
DIALOG --title "${_result}" --exit-label "Continue" \
--textbox "/tmp/pacman.log" 18 70 || return 1
# ensure the disk is synced
sync
chroot_umount
}
# install_packages()
# performs package installation to the target system
#
install_packages() {
destdir_mounts || return 1
if [[ "${S_MKFS}" != "1" && "${S_MKFSAUTO}" != "1" ]]; then
getdest
fi
prepare_pacman
PACKAGES=""
DIALOG --yesno "Next step will install base, linux, linux-firmware, netctl and filesystem tools for a minimal system.\n\nDo you wish to continue?" 10 50 || return 1
PACKAGES="base linux linux-firmware"
# Add packages which are not in core repository
if [[ -n "$(pgrep dhclient)" ]]; then
! [[ "$(echo ${PACKAGES} | grep -w dhclient)" ]] && PACKAGES="${PACKAGES} dhclient"
fi
# Add filesystem packages
if [[ "$(${_LSBLK} FSTYPE | grep ntfs)" ]]; then
! [[ "$(echo ${PACKAGES} | grep -w ntfs-3g)" ]] && PACKAGES="${PACKAGES} ntfs-3g"
fi
if [[ "$(${_LSBLK} FSTYPE | grep btrfs)" ]]; then
! [[ "$(echo ${PACKAGES} | grep -w btrfs-progs)" ]] && PACKAGES="${PACKAGES} btrfs-progs"
fi
if [[ "$(${_LSBLK} FSTYPE | grep nilfs2)" ]]; then
! [[ "$(echo ${PACKAGES} | grep -w nilfs-utils)" ]] && PACKAGES="${PACKAGES} nilfs-utils"
fi
if [[ "$(${_LSBLK} FSTYPE | grep ext)" ]]; then
! [[ "$(echo ${PACKAGES} | grep -w e2fsprogs)" ]] && PACKAGES="${PACKAGES} e2fsprogs"
fi
if [[ "$(${_LSBLK} FSTYPE | grep reiserfs)" ]]; then
! [[ "$(echo ${PACKAGES} | grep -w reiserfsprogs)" ]] && PACKAGES="${PACKAGES} reiserfsprogs"
fi
if [[ "$(${_LSBLK} FSTYPE | grep xfs)" ]]; then
! [[ "$(echo ${PACKAGES} | grep -w xfsprogs)" ]] && PACKAGES="${PACKAGES} xfsprogs"
fi
if [[ "$(${_LSBLK} FSTYPE | grep jfs)" ]]; then
! [[ "$(echo ${PACKAGES} | grep -w jfsutils)" ]] && PACKAGES="${PACKAGES} jfsutils"
fi
if [[ "$(${_LSBLK} FSTYPE | grep f2fs)" ]]; then
! [[ "$(echo ${PACKAGES} | grep -w f2fs-tools)" ]] && PACKAGES="${PACKAGES} f2fs-tools"
fi
if [[ "$(${_LSBLK} FSTYPE | grep vfat)" ]]; then
! [[ "$(echo ${PACKAGES} | grep -w dosfstools)" ]] && PACKAGES="${PACKAGES} dosfstools"
fi
if ! [[ "$(dmraid_devices)" = "" ]]; then
! [[ "$(echo ${PACKAGES} | grep -w dmraid)" ]] && PACKAGES="${PACKAGES} dmraid"
fi
### HACK:
# always add systemd-sysvcompat components
PACKAGES="$(echo ${PACKAGES} | sed -e "s#\ systemd-sysvcompat\ # #g")"
PACKAGES="${PACKAGES} systemd-sysvcompat"
### HACK:
# always add intel-ucode
PACKAGES="$(echo ${PACKAGES} | sed -e "s#\ intel-ucode\ # #g")"
PACKAGES="${PACKAGES} intel-ucode"
# always add amd-ucode
PACKAGES="$(echo ${PACKAGES} | sed -e "s#\ amd-ucode\ # #g")"
PACKAGES="${PACKAGES} amd-ucode"
### HACK:
# always add netctl with optdepends
PACKAGES="$(echo ${PACKAGES} | sed -e "s#\ netctl\ # #g")"
PACKAGES="${PACKAGES} netctl"
PACKAGES="$(echo ${PACKAGES} | sed -e "s#\ dhcpd\ # #g")"
PACKAGES="${PACKAGES} dhcpcd"
PACKAGES="$(echo ${PACKAGES} | sed -e "s#\ wpa_supplicant\ # #g")"
PACKAGES="${PACKAGES} wpa_supplicant"
### HACK:
# always add lvm2, cryptsetup and mdadm
PACKAGES="$(echo ${PACKAGES} | sed -e "s#\ lvm2\ # #g")"
PACKAGES="${PACKAGES} lvm2"
PACKAGES="$(echo ${PACKAGES} | sed -e "s#\ cryptsetup\ # #g")"
PACKAGES="${PACKAGES} cryptsetup"
PACKAGES="$(echo ${PACKAGES} | sed -e "s#\ mdadm\ # #g")"
PACKAGES="${PACKAGES} mdadm"
### HACK: circular depends are possible in base, install filesystem first!
PACKAGES="$(echo ${PACKAGES} | sed -e "s#\ filesystem\ # #g")"
PACKAGES="filesystem ${PACKAGES}"
DIALOG --infobox "Package installation will begin in 3 seconds. You can watch the output in the progress window. Please be patient." 0 0
sleep 3
run_pacman
S_INSTALL=1
NEXTITEM="6"
chroot_mount
# automagic time!
# any automatic configuration should go here
DIALOG --infobox "Writing base configuration..." 6 40
auto_fstab
auto_ssd
auto_mdadm
auto_luks
auto_pacman
auto_testing
# tear down the chroot environment
chroot_umount
}
# auto_fstab()
# preprocess fstab file
# comments out old fields and inserts new ones
# according to partitioning/formatting stage
#
auto_fstab(){
# Modify fstab
if [[ "${S_MKFS}" = "1" || "${S_MKFSAUTO}" = "1" ]]; then
if [[ -f /tmp/.device-names ]]; then
sort /tmp/.device-names >>${DESTDIR}/etc/fstab
fi
if [[ -f /tmp/.fstab ]]; then
# clean fstab first from entries
sed -i -e '/^\#/!d' ${DESTDIR}/etc/fstab
sort /tmp/.fstab >>${DESTDIR}/etc/fstab
fi
fi
}
# auto_ssd()
# add udev rule for ssd disks using the deadline scheduler by default
# add sysctl file for swaps
auto_ssd () {
[[ ! -f ${DESTDIR}/etc/udev/rules.d/60-ioschedulers.rules ]] && cp /etc/udev/rules.d/60-ioschedulers.rules ${DESTDIR}/etc/udev/rules.d/60-ioschedulers.rules
[[ ! -f ${DESTDIR}/etc/sysctl.d/99-sysctl.conf ]] && cp /etc/sysctl.d/99-sysctl.conf ${DESTDIR}/etc/sysctl.d/99-sysctl.conf
}
# auto_mdadm()
# add mdadm setup to existing /etc/mdadm.conf
auto_mdadm()
{
if [[ -e ${DESTDIR}/etc/mdadm.conf ]]; then
if [[ "$(cat /proc/mdstat | grep ^md)" ]]; then
DIALOG --infobox "Adding raid setup to ${DESTDIR}/etc/mdadm.conf ..." 4 40
mdadm -Ds >> ${DESTDIR}/etc/mdadm.conf
fi
fi
}
# auto_network()
# configures network on host system according to installer
# settings if user wishes to do so
#
auto_network()
{
# exit if network wasn't configured in installer
if [[ ${S_NET} -eq 0 ]]; then
return 1
fi
# copy netctl profiles
[[ -d ${DESTDIR}/etc/netctl ]] && cp /etc/netctl/* ${DESTDIR}/etc/netctl/ 2>/dev/null
# enable netctl profiles
for i in $(echo /etc/netctl/*); do
[[ -f $i ]] && chroot ${DESTDIR} /usr/bin/netctl enable $(basename $i)
done
# copy proxy settings
if [[ "${PROXY_HTTP}" != "" ]]; then
echo "export http_proxy=${PROXY_HTTP}" >> ${DESTDIR}/etc/profile.d/proxy.sh;
chmod a+x ${DESTDIR}/etc/profile.d/proxy.sh
fi
if [[ "${PROXY_FTP}" != "" ]]; then
echo "export ftp_proxy=${PROXY_FTP}" >> ${DESTDIR}/etc/profile.d/proxy.sh;
chmod a+x ${DESTDIR}/etc/profile.d/proxy.sh
fi
}
# Pacman signature check is enabled by default
# add gnupg pacman files to installed system
# in order to have a working pacman on installed system
auto_pacman()
{
if ! [[ -d ${DESTDIR}/etc/pacman.d/gnupg ]]; then
DO_PACMAN_GPG=""
DIALOG --yesno "Would you like to copy pacman's GPG files to installed system?\nDuring boot pacman GPG entropy was generated by haveged,\nif you need your own entropy answer NO." 0 0 && DO_PACMAN_GPG="yes"
if [[ "${DO_PACMAN_GPG}" = "yes" ]]; then
DIALOG --infobox "Copy /etc/pacman.d/gnupg directory to ${DESTDIR}/etc/pacman.d/gnupg ..." 0 0
cp -ar /etc/pacman.d/gnupg ${DESTDIR}/etc/pacman.d 2>&1
fi
fi
}
# If [testing] repository was enabled during installation,
# enable it on installed system too!
auto_testing()
{
if [[ "${DOTESTING}" == "yes" ]]; then
sed -i -e '/^#\[testing\]/ { n ; s/^#// }' ${DESTDIR}/etc/pacman.conf
sed -i -e '/^#\[community-testing\]/ { n ; s/^#// }' ${DESTDIR}/etc/pacman.conf
sed -i -e 's:^#\[testing\]:\[testing\]:g' -e 's:^#\[community-testing\]:\[community-testing\]:g' ${DESTDIR}/etc/pacman.conf
fi
}
# donetwork()
# Hand-hold through setting up networking
#
# args: none
# returns: 1 on failure
donetwork() {
NETPARAMETERS=""
while [[ "${NETPARAMETERS}" = "" ]]; do
# select network interface
INTERFACE=
S_DHCP=
ifaces=$(net_interfaces)
while [[ "${INTERFACE}" = "" ]]; do
DIALOG --ok-label "Select" --menu "Select a network interface" 14 55 7 ${ifaces} 2>${ANSWER}
case $? in
1) return 1 ;;
0) INTERFACE=$(cat ${ANSWER}) ;;
esac
done
# wireless switch
CONNECTION=""
WLAN_HIDDEN=""
WLAN_ESSID=""
WLAN_SECURITY=""
WLAN_KEY=""
DIALOG --defaultno --yesno "Is your network device wireless?" 5 40
if [[ $? -eq 0 ]]; then
CONNECTION="wireless"
DIALOG --inputbox "Enter your ESSID" 7 40 "MyNetwork" 2>${ANSWER} || return 1
WLAN_ESSID=$(cat ${ANSWER})
DIALOG --defaultno --yesno "Is your wireless network hidden?" 5 40
[[ $? -eq 0 ]] && WLAN_HIDDEN="yes"
DIALOG --yesno "Is your wireless network encrypted?" 5 40
if [[ $? -eq 0 ]]; then
while [[ "${WLAN_SECURITY}" = "" ]]; do
DIALOG --ok-label "Select" --menu "Select encryption type" 9 40 7 \
"wep" "WEP encryption" \
"wpa" "WPA encryption" 2>${ANSWER}
case $? in
1) return 1 ;;
0) WLAN_SECURITY=$(cat ${ANSWER}) ;;
esac
done
DIALOG --inputbox "Enter your KEY" 5 40 "WirelessKey" 2>${ANSWER} || return 1
WLAN_KEY=$(cat ${ANSWER})
else
WLAN_SECURITY="none"
fi
else
CONNECTION="ethernet"
fi
# dhcp switch
IP=""
DHCLIENT=""
DIALOG --yesno "Do you want to use DHCP?" 5 40
if [[ $? -eq 0 ]]; then
IP="dhcp"
DIALOG --defaultno --yesno "Do you want to use dhclient instead of dhcpcd?" 5 55
[[ $? -eq 0 ]] && DHCLIENT="yes"
S_DHCP=1
else
IP="static"
DIALOG --inputbox "Enter your IP address and netmask" 7 40 "192.168.1.23/24" 2>${ANSWER} || return 1
IPADDR=$(cat ${ANSWER})
DIALOG --inputbox "Enter your gateway" 7 40 "192.168.1.1" 2>${ANSWER} || return 1
GW=$(cat ${ANSWER})
DIALOG --inputbox "Enter your DNS server IP" 7 40 "192.168.1.1" 2>${ANSWER} || return 1
DNS=$(cat ${ANSWER})
fi
DIALOG --yesno "Are these settings correct?\n\nInterface: ${INTERFACE}\nConnection: ${CONNECTION}\nESSID: ${WLAN_ESSID}\nHidden: ${WLAN_HIDDEN}\nEncryption: ${WLAN_SECURITY}\nKey: ${WLAN_KEY}\ndhcp or static: ${IP}\nUse dhclient: ${DHCLIENT}\nIP address: ${IPADDR}\nGateway: ${GW}\nDNS server: ${DNS}" 0 0
case $? in
1) ;;
0) NETPARAMETERS="1" ;;
esac
done
# profile name
NETWORK_PROFILE=""
DIALOG --inputbox "Enter your network profile name" 7 40 "${INTERFACE}-${CONNECTION}" 2>${ANSWER} || return 1
NETWORK_PROFILE=/etc/netctl/$(cat ${ANSWER})
# write profile
echo "Connection=${CONNECTION}" >${NETWORK_PROFILE}
echo "Description='$NETWORK_PROFILE generated by archboot setup'" >>${NETWORK_PROFILE}
echo "Interface=${INTERFACE}" >>${NETWORK_PROFILE}
if [[ "${CONNECTION}" = "wireless" ]]; then
echo "Security=${WLAN_SECURITY}" >>${NETWORK_PROFILE}
echo "ESSID='${WLAN_ESSID}'" >>${NETWORK_PROFILE}
echo "Key='${WLAN_KEY}'" >>${NETWORK_PROFILE}
[[ "${WLAN_HIDDEN}" = "yes" ]] && echo "Hidden=yes" >>${NETWORK_PROFILE}
fi
echo "IP=${IP}" >>${NETWORK_PROFILE}
if [[ "${IP}" = "dhcp" ]]; then
[[ "${DHCLIENT}" = "yes" ]] && echo "DHCPClient=dhclient" >>${NETWORK_PROFILE}
else
echo "Address='${IPADDR}'" >>${NETWORK_PROFILE}
echo "Gateway='${GW}'" >>${NETWORK_PROFILE}
echo "DNS=('${DNS}')" >>${NETWORK_PROFILE}
fi
# bring down interface first
systemctl stop dhcpcd@${INTERFACE}.service
ip link set dev ${INTERFACE} down
# run netctl
netctl restart $(basename ${NETWORK_PROFILE}) >${LOG}
if [[ $? -gt 0 ]]; then
DIALOG --msgbox "Error occured while running netctl. (see 'journalctl -xn' for output)" 0 0
return 1
fi
# http/ftp proxy settings
DIALOG --inputbox "Enter your HTTP proxy server, for example:\nhttp://name:port\nhttp://ip:port\nhttp://username:password@ip:port\n\n Leave the field empty if no proxy is needed to install." 13 65 "" 2>${ANSWER} || return 1
PROXY_HTTP=$(cat ${ANSWER})
DIALOG --inputbox "Enter your FTP proxy server, for example:\nhttp://name:port\nhttp://ip:port\nhttp://username:password@ip:port\n\n Leave the field empty if no proxy is needed to install." 13 65 "" 2>${ANSWER} || return 1
PROXY_FTP=$(cat ${ANSWER})
if [[ "${PROXY_HTTP}" = "" ]]; then
unset http_proxy
else
export http_proxy=${PROXY_HTTP}
fi
if [[ "${PROXY_FTP}" = "" ]]; then
unset ftp_proxy
else
export ftp_proxy=${PROXY_FTP}
fi
# add sleep here dhcp can need some time to get link
DIALOG --infobox "Please wait 5 seconds for network link to come up ..." 0 0
sleep 5
NEXTITEM="2"
S_NET=1
}
getrootfstype() {
ROOTFS="$(getfstype ${PART_ROOT})"
}
getrootflags() {
ROOTFLAGS=""
ROOTFLAGS="$(findmnt -m -n -o options -T ${DESTDIR})"
# add subvolume for btrfs
if [[ "${ROOTFS}" == "btrfs" ]]; then
[[ "$(findmnt -m -n -o SOURCE -T ${DESTDIR} | grep "\[")" ]] && ROOTFLAGS="${ROOTFLAGS},subvol=$(basename "$(findmnt -m -n -o SOURCE -T ${DESTDIR} | cut -d "]" -f1)")"
fi
[[ -n "${ROOTFLAGS}" ]] && ROOTFLAGS="rootflags=${ROOTFLAGS}"
}
getraidarrays() {
RAIDARRAYS=""
if ! [[ "$(grep ^ARRAY ${DESTDIR}/etc/mdadm.conf)" ]]; then
RAIDARRAYS="$(echo -n $(cat /proc/mdstat 2>/dev/null | grep ^md | sed -e 's#\[[0-9]\]##g' -e 's# :.* raid[0-9]##g' -e 's#md#md=#g' -e 's# #,/dev/#g' -e 's#_##g'))"
fi
}
getcryptsetup() {
CRYPTSETUP=""
if ! [[ "$(cryptsetup status $(basename ${PART_ROOT}) | grep inactive)" ]]; then
#avoid clash with dmraid here
if [[ "$(cryptsetup status $(basename ${PART_ROOT}))" ]]; then
if [[ "${NAME_SCHEME_PARAMETER}" == "FSUUID" ]]; then
CRYPTDEVICE="UUID=$(echo $(${_LSBLK} UUID $(cryptsetup status $(basename ${PART_ROOT}) | grep device: | sed -e 's#device:##g')))"
elif [[ "${NAME_SCHEME_PARAMETER}" == "FSLABEL" ]]; then
CRYPTDEVICE="LABEL=$(echo $(${_LSBLK} LABEL $(cryptsetup status $(basename ${PART_ROOT}) | grep device: | sed -e 's#device:##g')))"
else
CRYPTDEVICE="$(echo $(cryptsetup status $(basename ${PART_ROOT}) | grep device: | sed -e 's#device:##g'))"
fi
CRYPTNAME="$(basename ${PART_ROOT})"
CRYPTSETUP="cryptdevice=${CRYPTDEVICE}:${CRYPTNAME}"
fi
fi
}
getrootpartuuid() {
_rootpart="${PART_ROOT}"
_partuuid="$(getpartuuid ${PART_ROOT})"
if [[ -n "${_partuuid}" ]]; then
_rootpart="PARTUUID=${_partuuid}"
fi
}
getrootpartlabel() {
_rootpart="${PART_ROOT}"
_partlabel="$(getpartlabel ${PART_ROOT})"
if [[ -n "${_partlabel}" ]]; then
_rootpart="PARTLABEL=${_partlabel}"
fi
}
getrootfsuuid() {
_rootpart="${PART_ROOT}"
_fsuuid="$(getfsuuid ${PART_ROOT})"
if [[ -n "${_fsuuid}" ]]; then
_rootpart="UUID=${_fsuuid}"
fi
}
getrootfslabel() {
_rootpart="${PART_ROOT}"
_fslabel="$(getfslabel ${PART_ROOT})"
if [[ -n "${_fslabel}" ]]; then
_rootpart="LABEL=${_fslabel}"
fi
}
## Setup kernel cmdline parameters to be added to bootloader configs
bootloader_kernel_parameters() {
if [[ "${GUID_DETECTED}" == "1" ]]; then
[[ "${NAME_SCHEME_PARAMETER}" == "PARTUUID" ]] && getrootpartuuid
[[ "${NAME_SCHEME_PARAMETER}" == "PARTLABEL" ]] && getrootpartlabel
fi
[[ "${NAME_SCHEME_PARAMETER}" == "FSUUID" ]] && getrootfsuuid
[[ "${NAME_SCHEME_PARAMETER}" == "FSLABEL" ]] && getrootfslabel
[[ "${_rootpart}" == "" ]] && _rootpart="${PART_ROOT}"
_KERNEL_PARAMS_COMMON_UNMOD="root=${_rootpart} rootfstype=${ROOTFS} rw ${ROOTFLAGS} ${RAIDARRAYS} ${CRYPTSETUP} cgroup_disable=memory"
_KERNEL_PARAMS_BIOS_UNMOD="${_KERNEL_PARAMS_COMMON_UNMOD}"
_KERNEL_PARAMS_UEFI_UNMOD="${_KERNEL_PARAMS_COMMON_UNMOD} add_efi_memmap"
_KERNEL_PARAMS_BIOS_MOD="$(echo "${_KERNEL_PARAMS_BIOS_UNMOD}" | sed -e 's# # #g' | sed -e 's# # #g')"
_KERNEL_PARAMS_UEFI_MOD="$(echo "${_KERNEL_PARAMS_UEFI_UNMOD}" | sed -e 's# # #g' | sed -e 's# # #g')"
}
# basic checks needed for all bootloaders
common_bootloader_checks() {
activate_special_devices
getrootfstype
getraidarrays
getcryptsetup
getrootflags
bootloader_kernel_parameters
}
# look for a separately-mounted /boot partition
check_bootpart() {
subdir=""
bootdev="$(mount | grep "${DESTDIR}/boot " | cut -d' ' -f 1)"
if [[ "${bootdev}" == "" ]]; then
subdir="/boot"
bootdev="${PART_ROOT}"
fi
}
# extlinux cannot boot from compressed btrfs
# extlinux cannot boot from btrfs raid, compressed btrfs
# FS60996:
# btrfs subvolume support of /boot or / is broken as of 14.09.2021
abort_syslinux_btrfs() {
FSTYPE="$(${_LSBLK} FSTYPE ${bootdev})"
if [[ "${FSTYPE}" = "btrfs" ]]; then
# abort on compress or subvolume on /boot
if [[ "$(mount | grep ${DESTDIR}/boot | grep subvol)" ]]; then
DIALOG --msgbox "Error:\nYour selected bootloader cannot boot from btrfs partition with /boot on subvolume." 0 0
return 1
fi
if [[ "$(mount | grep ${DESTDIR}/boot | grep compress)" ]]; then
DIALOG --msgbox "Error:\nYour selected bootloader cannot boot from btrfs partition with /boot and enabled compress option." 0 0
return 1
fi
# abort on compress or subvolume on / with /boot on it.
if [[ ! "$(mount | grep ${DESTDIR}/boot)" ]]; then
if [[ "$(mount | grep "${DESTDIR} " | grep subvol)" ]]; then
DIALOG --msgbox "Error:\nYour selected bootloader cannot boot from btrfs with /boot on / subvolume." 0 0
return 1
fi
if [[ "$(mount | grep "${DESTDIR} " | grep compress)" ]]; then
DIALOG --msgbox "Error:\nYour selected bootloader cannot boot from btrfs with /boot on / and enabled compress option." 0 0
return 1
fi
fi
CHECK is not perfect
find_btrfs_raid_bootloader_devices
if [[ ${BTRFS_COUNT} -ge 3 ]]; then
DIALOG --msgbox "Error:\n${SYSLINUX} cannot boot from any btrfs raid." 0 0
return 1
fi
fi
}
# check for nilfs2 bootpart and abort if detected
abort_nilfs_bootpart() {
FSTYPE="$(${_LSBLK} FSTYPE ${bootdev})"
if [[ "${FSTYPE}" = "nilfs2" ]]; then
DIALOG --msgbox "Error:\nYour selected bootloader cannot boot from nilfs2 partition with /boot on it." 0 0
return 1
fi
}
# check for f2fs bootpart and abort if detected
abort_f2fs_bootpart() {
FSTYPE="$(${_LSBLK} FSTYPE ${bootdev})"
if [[ "${FSTYPE}" = "f2fs" ]]; then
DIALOG --msgbox "Error:\nYour selected bootloader cannot boot from f2fs partition with /boot on it." 0 0
return 1
fi
}
uefi_mount_efivarfs() {
## Mount efivarfs if it is not already mounted
if [[ ! "$(mount | grep /sys/firmware/efi/efivars)" ]]; then
modprobe -q efivarfs
mount -t efivarfs efivarfs /sys/firmware/efi/efivars
fi
}
detect_uefi_secure_boot() {
export _DETECTED_UEFI_SECURE_BOOT="0"
if [[ "${_DETECTED_UEFI_BOOT}" == "1" ]]; then
uefi_mount_efivarfs
_SECUREBOOT_VAR_VALUE="$(efivar -n 8be4df61-93ca-11d2-aa0d-00e098032b8c-SecureBoot | tail -n -1 | awk '{print $2}')"
_SETUPMODE_VAR_VALUE="$(efivar -n 8be4df61-93ca-11d2-aa0d-00e098032b8c-SetupMode | tail -n -1 | awk '{print $2}')"
if [[ "${_SECUREBOOT_VAR_VALUE}" == "01" ]] && [[ "${_SETUPMODE_VAR_VALUE}" == "00" ]]; then
export _DETECTED_UEFI_SECURE_BOOT="1"
fi
fi
}
detect_uefi_boot() {
export _DETECTED_UEFI_BOOT="0"
[[ -e "/sys/firmware/efi" ]] && _DETECTED_UEFI_BOOT="1"
detect_uefi_secure_boot
}
do_uefi_setup_env_vars() {
if [[ "$(uname -m)" == "x86_64" ]]; then
if [[ "$(grep '_IA32_UEFI=1' /proc/cmdline 1>/dev/null)" ]]; then
export _EFI_MIXED="1"
export _UEFI_ARCH="IA32"
export _SPEC_UEFI_ARCH="ia32"
else
export _EFI_MIXED="0"
export _UEFI_ARCH="X64"
export _SPEC_UEFI_ARCH="x64"
fi
fi
}
do_uefi_common() {
do_uefi_setup_env_vars
PACKAGES=""
[[ ! -f "${DESTDIR}/usr/bin/mkfs.vfat" ]] && PACKAGES="${PACKAGES} dosfstools"
[[ ! -f "${DESTDIR}/usr/bin/efivar" ]] && PACKAGES="${PACKAGES} efivar"
[[ ! -f "${DESTDIR}/usr/bin/efibootmgr" ]] && PACKAGES="${PACKAGES} efibootmgr"
if [[ "${_DETECTED_UEFI_SECURE_BOOT}" == "1" ]]; then
[[ ! -f "${DESTDIR}/usr/bin/mokutil" ]] && PACKAGES="${PACKAGES} mokutil"
[[ ! -f "${DESTDIR}/usr/bin/efi-readvar" ]] && PACKAGES="${PACKAGES} efitools"
fi
! [[ "${PACKAGES}" == "" ]] && run_pacman
unset PACKAGES
check_efisys_part
}
do_uefi_efibootmgr() {
uefi_mount_efivarfs
if [[ "$(/usr/bin/efivar -l)" ]]; then
cat << EFIBEOF > "/tmp/efibootmgr_run.sh"
#!/usr/bin/env bash
_EFIBOOTMGR_LOADER_PARAMETERS="${_EFIBOOTMGR_LOADER_PARAMETERS}"
for _bootnum in \$(efibootmgr | grep '^Boot[0-9]' | fgrep -i "${_EFIBOOTMGR_LABEL}" | cut -b5-8) ; do
efibootmgr --quiet --bootnum "\${_bootnum}" --delete-bootnum
done
if [[ "\${_EFIBOOTMGR_LOADER_PARAMETERS}" != "" ]]; then
efibootmgr --quiet --create --disk "${_EFIBOOTMGR_DISC}" --part "${_EFIBOOTMGR_PART_NUM}" --loader "${_EFIBOOTMGR_LOADER_PATH}" --label "${_EFIBOOTMGR_LABEL}" --unicode "\${_EFIBOOTMGR_LOADER_PARAMETERS}" -e "3"
else
efibootmgr --quiet --create --disk "${_EFIBOOTMGR_DISC}" --part "${_EFIBOOTMGR_PART_NUM}" --loader "${_EFIBOOTMGR_LOADER_PATH}" --label "${_EFIBOOTMGR_LABEL}" -e "3"
fi
EFIBEOF
chmod a+x "/tmp/efibootmgr_run.sh"
/tmp/efibootmgr_run.sh &>"/tmp/efibootmgr_run.log"
else
DIALOG --msgbox "Boot entry could not be created. Check whether you have booted in UEFI boot mode and create a boot entry for ${UEFISYS_MOUNTPOINT}/${_EFIBOOTMGR_LOADER_PATH} using efibootmgr." 0 0
fi
unset _EFIBOOTMGR_LABEL
unset _EFIBOOTMGR_DISC
unset _EFIBOOTMGR_PART_NUM
unset _EFIBOOTMGR_LOADER_PATH
unset _EFIBOOTMGR_LOADER_PARAMETERS
}
do_apple_efi_hfs_bless() {
## Grub upstream bzr mactel branch => http://bzr.savannah.gnu.org/lh/grub/branches/mactel/changes
## Fedora's mactel-boot => https://bugzilla.redhat.com/show_bug.cgi?id=755093
DIALOG --msgbox "TODO: Apple Mac EFI Bootloader Setup" 0 0
}
do_uefi_bootmgr_setup() {
_uefisysdev="$(findmnt -vno SOURCE "${DESTDIR}/${UEFISYS_MOUNTPOINT}")"
_DISC="$(${_LSBLK} KNAME "${_uefisysdev}")"
UEFISYS_PART_NUM="$(${_BLKID} -p -i -s PART_ENTRY_NUMBER -o value "${_uefisysdev}")"
_BOOTMGR_DISC="${_DISC}"
_BOOTMGR_PART_NUM="${UEFISYS_PART_NUM}"
if [[ "$(cat "/sys/class/dmi/id/sys_vendor")" == 'Apple Inc.' ]] || [[ "$(cat "/sys/class/dmi/id/sys_vendor")" == 'Apple Computer, Inc.' ]]; then
do_apple_efi_hfs_bless
else
## For all the non-Mac UEFI systems
_EFIBOOTMGR_LABEL="${_BOOTMGR_LABEL}"
_EFIBOOTMGR_DISC="${_BOOTMGR_DISC}"
_EFIBOOTMGR_PART_NUM="${_BOOTMGR_PART_NUM}"
_EFIBOOTMGR_LOADER_PATH="${_BOOTMGR_LOADER_PATH}"
_EFIBOOTMGR_LOADER_PARAMETERS="${_BOOTMGR_LOADER_PARAMETERS}"
do_uefi_efibootmgr
fi
unset _BOOTMGR_LABEL
unset _BOOTMGR_DISC
unset _BOOTMGR_PART_NUM
unset _BOOTMGR_LOADER_PATH
unset _BOOTMGR_LOADER_PARAMETERS
}
do_uefi_secure_boot_efitools() {
do_uefi_common
# install helper tools and create entries in UEFI boot manager, if not present
if [[ "${_DETECTED_UEFI_SECURE_BOOT}" == "1" ]]; then
chroot_mount
if [[ ! -f "${UEFISYS_MOUNTPOINT}/EFI/BOOT/HashTool.efi" ]]; then
chroot "${DESTDIR}" cp "/usr/share/efitools/efi/HashTool.efi" "${UEFISYS_MOUNTPOINT}/EFI/BOOT/HashTool.efi"
_BOOTMGR_LABEL="HashTool (Secure Boot)"
_BOOTMGR_LOADER_DIR="/EFI/BOOT/HashTool.efi"
do_uefi_bootmgr_setup
fi
if [[ ! -f "${UEFISYS_MOUNTPOINT}/EFI/BOOT/KeyTool.efi" ]]; then
chroot "${DESTDIR}" cp "/usr/share/efitools/efi/KeyTool.efi" "${UEFISYS_MOUNTPOINT}/EFI/BOOT/KeyTool.efi"
_BOOTMGR_LABEL="KeyTool (Secure Boot)"
_BOOTMGR_LOADER_DIR="/EFI/BOOT/KeyTool.efi"
do_uefi_bootmgr_setup
fi
chroot_umount
fi
}
do_secureboot_keys() {
CN=""
MOK_PW=""
KEYDIR=""
while [[ "${KEYDIR}" = "" ]]; do
DIALOG --inputbox "Setup keys:\nEnter the directory to store the keys on ${DESTDIR}.\nPlease leave the leading slash \"/\"." 8 65 "etc/secureboot/keys" 2>${ANSWER} || KEYDIR=""
KEYDIR=$(cat ${ANSWER})
done
if [[ ! -d "${DESTDIR}/${KEYDIR}" ]]; then
while [[ "${CN}" = "" ]]; do
DIALOG --inputbox "Setup keys:\nEnter a common name(CN) for your keys, eg. Your Name" 8 65 "" 2>${ANSWER} || CN=""
CN=$(cat ${ANSWER})
done
secureboot-keys.sh -name="${CN}" "${DESTDIR}/${KEYDIR}" > ${LOG} 2>&1 || return 1
DIALOG --inputbox "Setup keys:\nEnter a common name(CN) for your keys, eg. Your Name" 8 65 "" 2>${ANSWER} || CN=""
else
DIALOG --msgbox "Setup keys:\n-Directory ${DESTDIR}/${KEYDIR} exists\n-assuming keys are already created\n-trying to use existing keys now" 8 65 ""
fi
}
do_mok_sign () {
UEFI_BOOTLOADER_DIR="${UEFISYS_MOUNTPOINT}/EFI/BOOT"
INSTALL_MOK=""
MOK_PW=""
DIALOG --yesno "Do you want to install the MOK certificate to the UEFI keys?" 0 0 && INSTALL_MOK="1"
if [[ "${INSTALL_MOK}" == "1" ]]; then
while [[ "${MOK_PW}" = "" ]]; do
DIALOG --insecure --passwordbox "Enter a one time MOK password for SHIM on reboot:" 8 65 2>${ANSWER} || return 1
PASS=$(cat ${ANSWER})
DIALOG --insecure --passwordbox "Retype one time MOK password:" 8 65 2>${ANSWER} || return 1
PASS2=$(cat ${ANSWER})
if [[ "${PASS}" = "${PASS2}" ]]; then
MOK_PW=${PASS}
echo ${MOK_PW} > /tmp/.password
echo ${MOK_PW} >> /tmp/.password
MOK_PW=/tmp/.password
else
DIALOG --msgbox "Password didn't match, please enter again." 8 65
fi
done
mokutil -i ${DESTDIR}/${KEYDIR}/MOK/MOK.cer < ${MOK_PW} > ${LOG}
rm /tmp/.password
DIALOG --msgbox "MOK keys have been installed successfully." 8 65
fi
SIGN_MOK=""
DIALOG --yesno "Do you want to sign /boot/${VMLINUZ} and ${UEFI_BOOTLOADER_DIR}/grub${_SPEC_UEFI_ARCH}.efi with the MOK certificate?" 0 0 && SIGN_MOK="1"
if [[ "${SIGN_MOK}" == "1" ]]; then
chroot_mount
chroot "${DESTDIR}" sbsign --key /${KEYDIR}/MOK/MOK.key --cert /${KEYDIR}/MOK/MOK.crt --output /boot/${VMLINUZ} /boot/${VMLINUZ} > ${LOG}
chroot "${DESTDIR}" sbsign --key /${KEYDIR}/MOK/MOK.key --cert /${KEYDIR}/MOK/MOK.crt --output ${UEFI_BOOTLOADER_DIR}/grub${_SPEC_UEFI_ARCH}.efi ${UEFI_BOOTLOADER_DIR}/grub${_SPEC_UEFI_ARCH}.efi > ${LOG}
chroot_umount
DIALOG --msgbox "/boot/${VMLINUZ} and ${UEFI_BOOTLOADER_DIR}/grub${_SPEC_UEFI_ARCH}.efi\nbeen signed successfully." 8 65
fi
}
do_pacman_sign() {
SIGN_KERNEL=""
DIALOG --yesno "Do you want to install a pacman hook for automatic signing /boot/${VMLINUZ} on updates?" 0 0 && SIGN_KERNEL="1"
if [[ "${SIGN_KERNEL}" == "1" ]]; then
[[ ! -d "${DESTDIR}/etc/pacman.d/hooks" ]] && mkdir -p ${DESTDIR}/etc/pacman.d/hooks/
HOOKNAME="${DESTDIR}/etc/pacman.d/hooks/999-sign_kernel_for_secureboot.hook"
cat << EOF > ${HOOKNAME}
[Trigger]
Operation = Install
Operation = Upgrade
Type = Package
Target = linux
[Action]
Description = Signing kernel with Machine Owner Key for Secure Boot
When = PostTransaction
Exec = /usr/bin/find /boot/ -maxdepth 1 -name 'vmlinuz-*' -exec /usr/bin/sh -c 'if ! /usr/bin/sbverify --list {} 2>/dev/null | /usr/bin/grep -q "signature certificates"; then /usr/bin/sbsign --key /${KEYDIR}/MOK.key --cert /${KEYDIR}/MOK.crt --output {} {}; fi' ;
Depends = sbsigntools
Depends = findutils
Depends = grep
EOF
DIALOG --msgbox "Pacman hook for automatic signing has been installed successfully:\n${HOOKNAME}" 8 75
fi
}
do_efistub_copy_to_efisys() {
if [[ "${UEFISYS_MOUNTPOINT}" != "/boot" ]]; then
_EFISTUB_KERNEL="${VMLINUZ/linux/arch}.efi"
_EFISTUB_INITRAMFS="${INITRAMFS/linux/arch}"
! [[ -d "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/arch" ]] && mkdir -p "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/arch/"
rm -f "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/arch/${_EFISTUB_KERNEL}"
rm -f "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/arch/${_EFISTUB_INITRAMFS}.img"
rm -f "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/arch/${_EFISTUB_INITRAMFS}-fallback.img"
cp -f "${DESTDIR}/boot/${VMLINUZ}" "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/arch/${_EFISTUB_KERNEL}"
cp -f "${DESTDIR}/boot/${INITRAMFS}.img" "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/arch/${_EFISTUB_INITRAMFS}.img"
cp -f "${DESTDIR}/boot/${INITRAMFS}-fallback.img" "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/arch/${_EFISTUB_INITRAMFS}-fallback.img"
#######################
cat << CONFEOF > "${DESTDIR}/etc/systemd/system/efistub_copy.path"
[Unit]
Description=Copy EFISTUB Kernel and Initramfs files to EFI SYSTEM PARTITION
[Path]
PathChanged=/boot/${VMLINUZ}
PathChanged=/boot/${INTEL_UCODE}
PathChanged=/boot/${AMD_UCODE}
PathChanged=/boot/${INITRAMFS}.img
PathChanged=/boot/${INITRAMFS}-fallback.img
Unit=efistub_copy.service
[Install]
WantedBy=multi-user.target
CONFEOF
cat << CONFEOF > "${DESTDIR}/etc/systemd/system/efistub_copy.service"
[Unit]
Description=Copy EFISTUB Kernel and Initramfs files to EFI SYSTEM PARTITION
[Service]
Type=oneshot
ExecStart=/usr/bin/cp -f /boot/${VMLINUZ} ${UEFISYS_MOUNTPOINT}/EFI/arch/${_EFISTUB_KERNEL}
ExecStart=/usr/bin/cp -f /boot/${INTEL_UCODE} ${UEFISYS_MOUNTPOINT}/EFI/arch/${INTEL_UCODE}
ExecStart=/usr/bin/cp -f /boot/${AMD_UCODE} ${UEFISYS_MOUNTPOINT}/EFI/arch/${AMD_UCODE}
ExecStart=/usr/bin/cp -f /boot/${INITRAMFS}.img ${UEFISYS_MOUNTPOINT}/EFI/arch/${_EFISTUB_INITRAMFS}.img
ExecStart=/usr/bin/cp -f /boot/${INITRAMFS}-fallback.img ${UEFISYS_MOUNTPOINT}/EFI/arch/${_EFISTUB_INITRAMFS}-fallback.img
CONFEOF
chroot "${DESTDIR}" /usr/bin/systemctl enable efistub_copy.path
fi
###########################
_bootdev="$(findmnt -vno SOURCE "${DESTDIR}/boot")"
_uefisysdev="$(findmnt -vno SOURCE "${DESTDIR}/${UEFISYS_MOUNTPOINT}")"
UEFISYS_PART_FS_UUID="$(getfsuuid "${_uefisysdev}")"
UEFISYS_PART_FS_LABEL="$(getfslabel "${_uefisysdev}")"
UEFISYS_PART_GPT_GUID="$(getpartuuid "${_uefisysdev}")"
UEFISYS_PART_GPT_LABEL="$(getpartlabel "${_uefisysdev}")"
if [[ "${UEFISYS_MOUNTPOINT}" == "/boot" ]]; then
_KERNEL_NORMAL="/${VMLINUZ}"
_INITRD_INTEL_UCODE="/${INTEL_UCODE}"
_INITRD_AMD_UCODE="/${AMD_UCODE}"
_INITRD_NORMAL="/${INITRAMFS}.img"
_INITRD_FALLBACK_NORMAL="/${INITRAMFS}-fallback.img"
else
_KERNEL_NORMAL="/EFI/arch/${_EFISTUB_KERNEL}"
_INITRD_INTEL_UCODE="/EFI/arch/${INTEL_UCODE}"
_INITRD_AMD_UCODE="/EFI/arch/${AMD_UCODE}"
_INITRD_NORMAL="/EFI/arch/${_EFISTUB_INITRAMFS}.img"
_INITRD_FALLBACK_NORMAL="/EFI/arch/${_EFISTUB_INITRAMFS}-fallback.img"
fi
}
do_efistub_uefi() {
do_uefi_common
bootdev=""
grubdev=""
complexuuid=""
FAIL_COMPLEX=""
USE_DMRAID=""
RAID_ON_LVM=""
common_bootloader_checks
do_efistub_copy_to_efisys
###################################
if [[ "${UEFISYS_MOUNTPOINT}" == "/boot" ]]; then
_CONTINUE="1"
else
if [[ -e "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/arch/${_EFISTUB_KERNEL}" ]] && [[ -e "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/arch/${_EFISTUB_INITRAMFS}.img" ]]; then
DIALOG --msgbox "The EFISTUB Kernel and initramfs have been copied to ${UEFISYS_MOUNTPOINT}/EFI/arch/${_EFISTUB_KERNEL} and ${UEFISYS_MOUNTPOINT}/EFI/arch/${_EFISTUB_INITRAMFS}.img respectively." 0 0
_CONTINUE="1"
else
DIALOG --msgbox "Error setting up EFISTUB kernel and initramfs in ${UEFISYS_MOUNTPOINT}." 0 0
_CONTINUE="0"
fi
fi
if [[ "${_CONTINUE}" == "1" ]]; then
DIALOG --menu "Select which UEFI Boot Manager to install, to provide a menu for the EFISTUB kernels?" 11 55 3 \
"Systemd-boot" "Systemd-boot for ${UEFI_ARCH} UEFI" \
"rEFInd" "rEFInd for ${UEFI_ARCH} UEFI" \
"NONE" "No Boot Manager" 2>${ANSWER} || CANCEL=1
case $(cat ${ANSWER}) in
"Systemd-boot") do_systemd_boot_uefi ;;
"rEFInd") do_refind_uefi;;
"NONE") return 0 ;;
esac
fi
}
do_systemd_boot_uefi() {
DIALOG --msgbox "Setting up Systemd-boot now ..." 0 0
# create directory structure, if it doesn't exist
! [[ -d "${DESTDIR}/${UEFISYS_MOUNTPOINT}/loader/entries" ]] && mkdir -p "${DESTDIR}/${UEFISYS_MOUNTPOINT}/loader/entries"
cat << GUMEOF > "${DESTDIR}/${UEFISYS_MOUNTPOINT}/loader/entries/archlinux-core-main.conf"
title Arch Linux
linux ${_KERNEL_NORMAL}
initrd ${_INITRD_INTEL_UCODE}
initrd ${_INITRD_AMD_UCODE}
initrd ${_INITRD_NORMAL}
options ${_KERNEL_PARAMS_UEFI_MOD}
GUMEOF
cat << GUMEOF > "${DESTDIR}/${UEFISYS_MOUNTPOINT}/loader/entries/archlinux-core-fallback.conf"
title Arch Linux Fallback
linux ${_KERNEL_NORMAL}
initrd ${_INITRD_INTEL_UCODE}
initrd ${_INITRD_AMD_UCODE}
initrd ${_INITRD_FALLBACK_NORMAL}
options ${_KERNEL_PARAMS_UEFI_MOD}
GUMEOF
cat << GUMEOF > "${DESTDIR}/${UEFISYS_MOUNTPOINT}/loader/loader.conf"
timeout 5
default archlinux-core-main
GUMEOF
uefi_mount_efivarfs
chroot_mount
chroot "${DESTDIR}" "/usr/bin/bootctl" --path="${UEFISYS_MOUNTPOINT}" install
chroot "${DESTDIR}" "/usr/bin/bootctl" --path="${UEFISYS_MOUNTPOINT}" update
chroot_umount
if [[ -e "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/systemd/systemd-boot${_SPEC_UEFI_ARCH}.efi" ]]; then
DIALOG --msgbox "You will now be put into the editor to edit loader.conf and Systemd-boot menu entry files . After you save your changes, exit the editor." 0 0
geteditor || return 1
"${EDITOR}" "${DESTDIR}/${UEFISYS_MOUNTPOINT}/loader/entries/archlinux-core-main.conf"
"${EDITOR}" "${DESTDIR}/${UEFISYS_MOUNTPOINT}/loader/entries/archlinux-core-fallback.conf"
"${EDITOR}" "${DESTDIR}/${UEFISYS_MOUNTPOINT}/loader/loader.conf"
DIALOG --defaultno --yesno "Do you want to copy ${UEFISYS_MOUNTPOINT}/EFI/systemd/systemd-boot${_SPEC_UEFI_ARCH}.efi to ${UEFISYS_MOUNTPOINT}/EFI/BOOT/boot${_SPEC_UEFI_ARCH}.efi ?\n\nThis might be needed in some systems where efibootmgr may not work due to firmware issues." 0 0 && _UEFISYS_EFI_BOOT_DIR="1"
if [[ "${_UEFISYS_EFI_BOOT_DIR}" == "1" ]]; then
mkdir -p "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/BOOT"
rm -f "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/BOOT/boot${_SPEC_UEFI_ARCH}.efi" || true
cp -f "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/systemd/systemd-boot${_SPEC_UEFI_ARCH}.efi" "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/BOOT/boot${_SPEC_UEFI_ARCH}.efi"
fi
else
DIALOG --msgbox "Error installing Systemd-boot..." 0 0
fi
}
do_refind_uefi() {
DIALOG --msgbox "Setting up rEFInd now ..." 0 0
if [[ ! -f "${DESTDIR}/usr/bin/refind-install" ]]; then
DIALOG --infobox "Couldn't find ${DESTDIR}/usr/bin/refind-install, installing refind pkg in 3 seconds ..." 0 0
sleep 3
PACKAGES="refind"
run_pacman
unset PACKAGES
fi
! [[ -d "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/refind" ]] && mkdir -p "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/refind/"
cp -f "${DESTDIR}/usr/share/refind/refind_${_SPEC_UEFI_ARCH}.efi" "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/refind/refind_${_SPEC_UEFI_ARCH}.efi"
cp -r "${DESTDIR}/usr/share/refind/icons" "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/refind/icons"
cp -r "${DESTDIR}/usr/share/refind/fonts" "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/refind/fonts"
! [[ -d "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/tools" ]] && mkdir -p "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/tools/"
cp -rf "${DESTDIR}/usr/share/refind/drivers_${_SPEC_UEFI_ARCH}" "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/tools/drivers_${_SPEC_UEFI_ARCH}"
mv "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/tools/drivers_${_SPEC_UEFI_ARCH}"/ext2_x64.{,_}efi
_REFIND_CONFIG="${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/refind/refind.conf"
cp -f "${DESTDIR}/usr/share/refind/refind.conf-sample" "${_REFIND_CONFIG}"
sed 's|^#resolution 1024 768|resolution 1024 768|g' -i "${_REFIND_CONFIG}"
sed 's|^#scan_driver_dirs EFI/tools/drivers,drivers|scan_driver_dirs EFI/tools/drivers_${_SPEC_UEFI_ARCH}|g' -i "${_REFIND_CONFIG}"
sed 's|^#scanfor internal,external,optical,manual|scanfor manual,internal,external,optical|g' -i "${_REFIND_CONFIG}"
sed 's|^#also_scan_dirs boot,ESP2:EFI/linux/kernels|also_scan_dirs boot|g' -i "${_REFIND_CONFIG}"
sed 's|^#scan_all_linux_kernels|scan_all_linux_kernels|g' -i "${_REFIND_CONFIG}"
if [[ "${UEFISYS_MOUNTPOINT}" == "/boot" ]]; then
_REFIND_LINUX_CONF="${DESTDIR}/${UEFISYS_MOUNTPOINT}/refind_linux.conf"
else
_REFIND_LINUX_CONF="${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/arch/refind_linux.conf"
fi
cat << REFINDEOF > "${_REFIND_LINUX_CONF}"
"Boot with Defaults" "${_KERNEL_PARAMS_UEFI_MOD} initrd=${_INITRD_INTEL_UCODE} initrd=${_INITRD_AMD_UCODE} initrd=${_INITRD_NORMAL}"
"Boot with fallback initramfs" "${_KERNEL_PARAMS_UEFI_MOD} initrd=${_INITRD_INTEL_UCODE} initrd=${_INITRD_AMD_UCODE} initrd=${_INITRD_FALLBACK_NORMAL}"
REFINDEOF
if [[ -e "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/refind/refind_${_SPEC_UEFI_ARCH}.efi" ]]; then
_BOOTMGR_LABEL="rEFInd"
_BOOTMGR_LOADER_DIR="/EFI/refind/refind_${_SPEC_UEFI_ARCH}.efi"
do_uefi_bootmgr_setup
DIALOG --msgbox "refind has been setup successfully." 0 0
DIALOG --msgbox "You will now be put into the editor to edit refind.conf and refind_linux.conf . After you save your changes, exit the editor." 0 0
geteditor || return 1
"${EDITOR}" "${_REFIND_CONFIG}"
DIALOG --defaultno --yesno "Do you want to copy ${UEFISYS_MOUNTPOINT}/EFI/refind/refind_${_SPEC_UEFI_ARCH}.efi to ${UEFISYS_MOUNTPOINT}/EFI/BOOT/boot${_SPEC_UEFI_ARCH}.efi ?\n\nThis might be needed in some systems where efibootmgr may not work due to firmware issues." 0 0 && _UEFISYS_EFI_BOOT_DIR="1"
if [[ "${_UEFISYS_EFI_BOOT_DIR}" == "1" ]]; then
mkdir -p "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/BOOT"
rm -f "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/BOOT/boot${_SPEC_UEFI_ARCH}.efi" || true
rm -f "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/BOOT/refind.conf" || true
rm -rf "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/BOOT/icons" || true
cp -f "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/refind/refind_${_SPEC_UEFI_ARCH}.efi" "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/BOOT/boot${_SPEC_UEFI_ARCH}.efi"
cp -f "${_REFIND_CONFIG}" "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/BOOT/refind.conf"
cp -rf "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/refind/icons" "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/BOOT/icons"
fi
else
DIALOG --msgbox "Error setting up refind." 0 0
fi
}
do_syslinux_common_before() {
bootdev=""
complexuuid=""
FAIL_COMPLEX=""
USE_DMRAID=""
RAID_ON_LVM=""
common_bootloader_checks
if [[ ! -f "${DESTDIR}/usr/lib/syslinux/bios/ldlinux.c32" ]]; then
DIALOG --infobox "Couldn't find syslinux files, installing syslinux and mtools in 3 seconds ..." 0 0
sleep 3
PACKAGES="syslinux mtools"
run_pacman
# reset PACKAGES after installing
unset PACKAGES
fi
}
do_syslinux_config() {
if [[ "${_SYSLINUX_UEFI}" == "1" ]]; then
_SYSLINUX_UEFI_CONFIG_PATH="${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/syslinux/syslinux.cfg"
cat << EOF > "${_SYSLINUX_UEFI_CONFIG_PATH}"
PATH /EFI/syslinux
UI menu.c32
DEFAULT arch
PROMPT 1
TIMEOUT 100
ONTIMEOUT arch
LABEL arch
MENU LABEL Arch Linux
LINUX ${_KERNEL_NORMAL}
APPEND ${_KERNEL_PARAMS_UEFI_MOD}
INITRD ${_INITRD_INTEL_UCODE},${_INITRD_AMD_UCODE},${_INITRD_NORMAL}
LABEL arch-fallback
MENU LABEL Arch Linux Fallback
LINUX ${_KERNEL_NORMAL}
APPEND ${_KERNEL_PARAMS_UEFI_MOD}
INITRD ${_INITRD_INTEL_UCODE},${_INITRD_AMD_UCODE},${_INITRD_FALLBACK_NORMAL}
EOF
DIALOG --msgbox "You will now be put into the editor to edit syslinux.cfg . After you save your changes, exit the editor." 0 0
geteditor || return 1
"${EDITOR}" "${_SYSLINUX_UEFI_CONFIG_PATH}"
fi
if [[ "${_SYSLINUX_BIOS}" == "1" ]]; then
_SYSLINUX_BIOS_CONFIG_PATH="${DESTDIR}/boot/${SYSLINUX_DIR}/syslinux.cfg"
cat << EOF > "${_SYSLINUX_BIOS_CONFIG_PATH}"
PATH ${subdir}/${SYSLINUX_DIR}
UI vesamenu.c32
PROMPT 1
TIMEOUT 100
ONTIMEOUT arch
MENU TITLE Arch Linux
MENU BACKGROUND ${subdir}/${SYSLINUX_DIR}/splash.png
MENU WIDTH 78
MENU MARGIN 4
MENU ROWS 10
MENU VSHIFT 10
MENU TIMEOUTROW 15
MENU TABMSGROW 13
MENU CMDLINEROW 11
MENU HELPMSGROW 17
MENU HELPMSGENDROW 29
# Refer to http://syslinux.zytor.com/wiki/index.php/Doc/menu
MENU COLOR border 30;44 #40ffffff #a0000000 std
MENU COLOR title 1;36;44 #9033ccff #a0000000 std
MENU COLOR sel 7;37;40 #e0ffffff #20ffffff all
MENU COLOR unsel 37;44 #50ffffff #a0000000 std
MENU COLOR help 37;40 #c0ffffff #a0000000 std
MENU COLOR timeout_msg 37;40 #80ffffff #00000000 std
MENU COLOR timeout 1;37;40 #c0ffffff #00000000 std
MENU COLOR msg07 37;40 #90ffffff #a0000000 std
MENU COLOR tabmsg 31;40 #30ffffff #00000000 std
LABEL arch
TEXT HELP
Boot Arch Linux
ENDTEXT
MENU LABEL Arch Linux
LINUX ${subdir}/${VMLINUZ}
APPEND ${_KERNEL_PARAMS_BIOS_MOD}
INITRD ${subdir}/${INTEL_UCODE},${subdir}/${AMD_UCODE},${subdir}/${INITRAMFS}.img
LABEL arch-fallback
TEXT HELP
Boot Arch Linux Fallback
ENDTEXT
MENU LABEL Arch Linux Fallback
LINUX ${subdir}/${VMLINUZ}
APPEND ${_KERNEL_PARAMS_BIOS_MOD}
INITRD ${subdir}/${INTEL_UCODE},${subdir}/${AMD_UCODE},${subdir}/${INITRAMFS}-fallback.img
EOF
DIALOG --msgbox "You will now be put into the editor to edit syslinux.cfg . After you save your changes, exit the editor." 0 0
geteditor || return 1
"${EDITOR}" "${_SYSLINUX_BIOS_CONFIG_PATH}"
fi
}
do_syslinux_uefi() {
do_uefi_common
[[ "${_UEFI_ARCH}" == "X64" ]] && _SYSLINUX_BUILD="efi64"
[[ "${_UEFI_ARCH}" == "IA32" ]] && _SYSLINUX_BUILD="efi32"
DIALOG --msgbox "Setting up Syslinux EFI now ..." 0 0
do_syslinux_common_before
! [[ -d "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI" ]] && mkdir -p "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/"
cp -r "${DESTDIR}/usr/lib/syslinux/${_SYSLINUX_BUILD}" "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/syslinux"
do_efistub_copy_to_efisys
if [[ -e "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/syslinux/syslinux.efi" ]]; then
_BOOTMGR_LABEL="Syslinux"
_BOOTMGR_LOADER_DIR="/EFI/syslinux/syslinux.efi"
do_uefi_bootmgr_setup
_SYSLINUX_BIOS="0"
_SYSLINUX_UEFI="1"
do_syslinux_config
_SYSLINUX_UEFI=""
_SYSLINUX_BIOS=""
DIALOG --msgbox "Syslinux EFI has been setup successfully." 0 0
DIALOG --defaultno --yesno "Do you want to copy ${UEFISYS_MOUNTPOINT}/EFI/syslinux/syslinux.efi to ${UEFISYS_MOUNTPOINT}/EFI/BOOT/boot${_SPEC_UEFI_ARCH}.efi ?\n\nThis might be needed in some systems where efibootmgr may not work due to firmware issues." 0 0 && _UEFISYS_EFI_BOOT_DIR="1"
if [[ "${_UEFISYS_EFI_BOOT_DIR}" == "1" ]]; then
! [[ -d "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/BOOT" ]] && mkdir -p "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/BOOT"
rm -f "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/BOOT/boot${_SPEC_UEFI_ARCH}.efi"
rm -f "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/BOOT"/*.c32
rm -f "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/BOOT/syslinux.cfg"
cp -f "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/syslinux/syslinux.efi" "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/BOOT/boot${_SPEC_UEFI_ARCH}.efi"
cp -f "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/syslinux/syslinux.cfg" "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/BOOT/syslinux.cfg"
cp -f "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/syslinux"/*.c32 "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/BOOT/"
fi
else
DIALOG --msgbox "Error setting up Syslinux EFI." 0 0
fi
}
## install syslinux/extlinux bios bootloader
do_syslinux_bios() {
SYSLINUX="EXTLINUX"
SYSLINUX_PROGRAM="extlinux"
SYSLINUX_DIR="syslinux"
SYSLINUX_CONF="syslinux.cfg"
SYSLINUX_OPTS=""
do_syslinux_common_before
check_bootpart
abort_syslinux_btrfs || return 1
abort_nilfs_bootpart || return 1
abort_f2fs_bootpart || return 1
# extlinux only can boot from ext2/3/4, xfs and btrfs partitions!
FSTYPE="$(${_LSBLK} FSTYPE ${bootdev})"
if ! [[ "${FSTYPE}" == "ext2" || "${FSTYPE}" == "ext3" || "${FSTYPE}" == "ext4" || "${FSTYPE}" == "btrfs" || "${FSTYPE}" == "vfat" || "${FSTYPE}" == "xfs" ]]; then
DIALOG --msgbox "Error:\nCouldn't find ext2/3/4, btrfs, vfat or xfs partition with /boot on it." 0 0
return 1
fi
# extlinux cannot boot from any raid partition, encrypted and dmraid device
if [[ "$(echo ${bootdev} | grep /dev/md*p)" || "$(echo ${bootdev} | grep /dev/mapper)" ]]; then
DIALOG --msgbox "Error:\n${SYSLINUX} cannot boot from any raid partition, encrypted or dmraid device." 0 0
return 1
fi
# check if raid1 device is used, else fail.
if [[ "$(echo ${bootdev} | grep /dev/md)" ]]; then
if ! [[ "$(mdadm --detail ${bootdev} | grep Level | sed -e 's#.*:\ ##g')" = "raid1" ]]; then
DIALOG --msgbox "Error:\n${SYSLINUX} cannot boot from none raid1 devices." 0 0
return 1
else
SYSLINUX_OPTS="--raid"
fi
fi
DEVS="$(findbootloaderdisks _)"
DEVS="${DEVS} $(findbootloaderpartitions _)"
if [[ "${DEVS}" == "" ]]; then
DIALOG --msgbox "No storage drives were found" 0 0
return 1
fi
DIALOG --menu "Select the boot device where the ${SYSLINUX} BIOS bootloader will be installed (usually the MBR)" 14 55 7 ${DEVS} 2>${ANSWER} || return 1
ROOTDEV=$(cat ${ANSWER})
# check if GPT/GUID is used
GUID_DETECTED=""
[[ "$(${_BLKID} -p -i -o value -s PTTYPE ${ROOTDEV})" == "gpt" ]] && GUID_DETECTED="1"
PARTITION_NUMBER=$(echo ${bootdev} | sed -e 's#.*[a-z]##g')
if [[ "${GUID_DETECTED}" == '1' ]]; then
# Set Legacy BIOS Bootable GPT Partition Attribute using sgdisk
if ! [[ "$(sgdisk -i ${PARTITION_NUMBER} ${ROOTDEV} | grep '^Attribute' | grep '4$')" ]]; then
sgdisk ${ROOTDEV} --attributes=${PARTITION_NUMBER}:set:2
fi
else
printk off
# mark the partition with /boot as active in MBR
parted -s ${ROOTDEV} set ${PARTITION_NUMBER} boot on >${LOG}
printk on
fi
## install syslinux/extlinux bios
DIALOG --infobox "Installing the ${SYSLINUX} BIOS bootloader..." 0 0
mkdir -p "${DESTDIR}/boot/${SYSLINUX_DIR}" || true
cp -f "${DESTDIR}/usr/lib/syslinux/bios"/*.c32 "${DESTDIR}/boot/${SYSLINUX_DIR}"
chroot_mount
chroot "${DESTDIR}" "${SYSLINUX_PROGRAM}" ${SYSLINUX_OPTS} --install "/boot/${SYSLINUX_DIR}" &>"${LOG}"
chroot_umount
MBR="${DESTDIR}/usr/lib/syslinux/bios/mbr.bin"
GPTMBR="${DESTDIR}/usr/lib/syslinux/bios/gptmbr.bin"
## Install MBR boot code only if the selected ROOTDEV is a DISC and not a partition
if [[ "$(${_LSBLK} TYPE -d ${ROOTDEV} | grep "disk")" ]]; then
## check if GPT/GUID is used
GUID_DETECTED=""
[[ "$(${_BLKID} -p -i -o value -s PTTYPE ${ROOTDEV})" == "gpt" ]] && GUID_DETECTED="1"
if [[ "${GUID_DETECTED}" == '1' ]]; then
cat "${GPTMBR}" > "${ROOTDEV}"
else
cat "${MBR}" > "${ROOTDEV}"
fi
fi
# btrfs does not have ldlinux.sys in filesystem!
if [[ -e "${DESTDIR}/boot/${SYSLINUX_DIR}/ldlinux.sys" || "${FSTYPE}" == "btrfs" ]]; then
_SYSLINUX_UEFI="0"
_SYSLINUX_BIOS="1"
do_syslinux_config
_SYSLINUX_BIOS=""
_SYSLINUX_UEFI=""
DIALOG --msgbox "${SYSLINUX} was successfully installed." 0 0
else
DIALOG --msgbox "Error installing ${SYSLINUX}. (see ${LOG} for output)" 0 0
return 1
fi
}
do_grub_common_before() {
##### Check whether the below limitations still continue with ver 2.00~beta4
### Grub(2) restrictions:
## - Encryption is not recommended for grub(2) /boot!
bootdev=""
grubdev=""
complexuuid=""
FAIL_COMPLEX=""
USE_DMRAID=""
RAID_ON_LVM=""
common_bootloader_checks
abort_f2fs_bootpart || return 1
if ! [[ "$(dmraid -r | grep ^no )" ]]; then
DIALOG --yesno "Setup detected dmraid device.\nDo you want to install grub on this device?" 0 0 && USE_DMRAID="1"
fi
if [[ ! -f "${DESTDIR}/usr/lib/grub/i386-pc/kernel.img" ]]; then
DIALOG --infobox "Couldn't find ${DESTDIR}/usr/lib/grub/i386-pc/kernel.img , installing grub pkg in 3 secons ..." 0 0
sleep 3
PACKAGES="grub"
run_pacman
# reset PACKAGES after installing
unset PACKAGES
fi
}
do_grub_config() {
chroot_mount
########
BOOT_PART_FS_UUID="$(chroot "${DESTDIR}" /usr/bin/grub-probe --target="fs_uuid" "/boot" 2>/dev/null)"
BOOT_PART_FS_LABEL="$(chroot "${DESTDIR}" /usr/bin/grub-probe --target="fs_label" "/boot" 2>/dev/null)"
BOOT_PART_HINTS_STRING="$(chroot "${DESTDIR}" /usr/bin/grub-probe --target="hints_string" "/boot" 2>/dev/null)"
BOOT_PART_FS="$(chroot "${DESTDIR}" /usr/bin/grub-probe --target="fs" "/boot" 2>/dev/null)"
BOOT_PART_DRIVE="$(chroot "${DESTDIR}" /usr/bin/grub-probe --target="drive" "/boot" 2>/dev/null)"
########
ROOT_PART_FS_UUID="$(chroot "${DESTDIR}" /usr/bin/grub-probe --target="fs_uuid" "/" 2>/dev/null)"
ROOT_PART_FS_LABEL="$(chroot "${DESTDIR}" /usr/bin/grub-probe --target="fs_label" "/" 2>/dev/null)"
ROOT_PART_HINTS_STRING="$(chroot "${DESTDIR}" /usr/bin/grub-probe --target="hints_string" "/" 2>/dev/null)"
ROOT_PART_FS="$(chroot "${DESTDIR}" /usr/bin/grub-probe --target="fs" "/" 2>/dev/null)"
ROOT_PART_DEVICE="$(chroot "${DESTDIR}" /usr/bin/grub-probe --target="device" "/" 2>/dev/null)"
########
USR_PART_FS_UUID="$(chroot "${DESTDIR}" /usr/bin/grub-probe --target="fs_uuid" "/usr" 2>/dev/null)"
USR_PART_HINTS_STRING="$(chroot "${DESTDIR}" /usr/bin/grub-probe --target="hints_string" "/usr" 2>/dev/null)"
USR_PART_FS="$(chroot "${DESTDIR}" /usr/bin/grub-probe --target="fs" "/usr" 2>/dev/null)"
########
if [[ "${GRUB_UEFI}" == "1" ]]; then
UEFISYS_PART_FS_UUID="$(chroot "${DESTDIR}" /usr/bin/grub-probe --target="fs_uuid" "/${UEFISYS_MOUNTPOINT}" 2>/dev/null)"
UEFISYS_PART_HINTS_STRING="$(chroot "${DESTDIR}" /usr/bin/grub-probe --target="hints_string" "/${UEFISYS_MOUNTPOINT}" 2>/dev/null)"
fi
########
if [[ "$(${_BLKID} -p -i -o value -s PART_ENTRY_SCHEME ${ROOT_PART_DEVICE})" == 'gpt' ]]; then
ROOT_PART_GPT_GUID="$(${_LSBLK} PARTUUID ${ROOT_PART_DEVICE})"
ROOT_PART_GPT_LABEL="$(${_LSBLK} PARTLABEL ${ROOT_PART_DEVICE})"
fi
########
if [[ "${ROOT_PART_FS_UUID}" == "${BOOT_PART_FS_UUID}" ]]; then
subdir="/boot"
# on btrfs we need to check on subvol
if [[ $(mount | grep "${DESTDIR} " | grep btrfs | grep subvol) ]]; then
subdir="/$(echo $(btrfs subvolume show "${DESTDIR}/" | grep Name | cut -d ":" -f2))"/boot
fi
else
subdir=""
# on btrfs we need to check on subvol
if [[ $(mount | grep "${DESTDIR}/boot " | grep btrfs | grep subvol) ]]; then
subdir="/$(echo $(btrfs subvolume show "${DESTDIR}/boot" | grep Name | cut -d ":" -f2))"
fi
fi
########
## Move old config file, if any
if [[ "${_DETECTED_UEFI_SECURE_BOOT}" == "1" ]]; then
GRUB_CFG="grub${_SPEC_UEFI_ARCH}.cfg"
else
GRUB_CFG="grub.cfg"
fi
mv "${DESTDIR}/${GRUB_PREFIX_DIR}/${GRUB_CFG}" "${DESTDIR}/${GRUB_PREFIX_DIR}/${GRUB_CFG}.bak" || true
## Ignore if the insmod entries are repeated - there are possibilities of having /boot in one disk and root-fs in altogether different disk
## with totally different configuration.
cat << EOF > "${DESTDIR}/${GRUB_PREFIX_DIR}/${GRUB_CFG}"
if [ "\${grub_platform}" == "efi" ]; then
set _UEFI_ARCH="\${grub_cpu}"
if [ "\${grub_cpu}" == "x86_64" ]; then
set _SPEC_UEFI_ARCH="x64"
fi
if [ "\${grub_cpu}" == "i386" ]; then
set _SPEC_UEFI_ARCH="ia32"
fi
fi
EOF
cat << EOF >> "${DESTDIR}/${GRUB_PREFIX_DIR}/${GRUB_CFG}"
insmod part_gpt
insmod part_msdos
# Include fat fs module - required for uefi systems.
insmod fat
insmod ${BOOT_PART_FS}
insmod ${ROOT_PART_FS}
insmod ${USR_PART_FS}
insmod search_fs_file
insmod search_fs_uuid
insmod search_label
insmod linux
insmod chain
set pager="1"
# set debug="all"
set locale_dir="\${prefix}/locale"
EOF
[[ "${USE_RAID}" == "1" ]] && echo "insmod raid" >> "${DESTDIR}/${GRUB_PREFIX_DIR}/${GRUB_CFG}"
! [[ "${RAID_ON_LVM}" == "" ]] && echo "insmod lvm" >> "${DESTDIR}/${GRUB_PREFIX_DIR}/${GRUB_CFG}"
cat << EOF >> "${DESTDIR}/${GRUB_PREFIX_DIR}/${GRUB_CFG}"
if [ -e "\${prefix}/\${grub_cpu}-\${grub_platform}/all_video.mod" ]; then
insmod all_video
else
if [ "\${grub_platform}" == "efi" ]; then
insmod efi_gop
insmod efi_uga
fi
if [ "\${grub_platform}" == "pc" ]; then
insmod vbe
insmod vga
fi
insmod video_bochs
insmod video_cirrus
fi
insmod font
search --fs-uuid --no-floppy --set=usr_part ${USR_PART_HINTS_STRING} ${USR_PART_FS_UUID}
search --fs-uuid --no-floppy --set=root_part ${ROOT_PART_HINTS_STRING} ${ROOT_PART_FS_UUID}
if [ -e "\${prefix}/fonts/unicode.pf2" ]; then
set _fontfile="\${prefix}/fonts/unicode.pf2"
else
if [ -e "(\${root_part})/usr/share/grub/unicode.pf2" ]; then
set _fontfile="(\${root_part})/usr/share/grub/unicode.pf2"
else
if [ -e "(\${usr_part})/share/grub/unicode.pf2" ]; then
set _fontfile="(\${usr_part})/share/grub/unicode.pf2"
fi
fi
fi
if loadfont "\${_fontfile}" ; then
insmod gfxterm
set gfxmode="auto"
terminal_input console
terminal_output gfxterm
fi
EOF
echo "" >> "${DESTDIR}/${GRUB_PREFIX_DIR}/${GRUB_CFG}"
sort "/tmp/.device-names" >> "${DESTDIR}/${GRUB_PREFIX_DIR}/${GRUB_CFG}"
echo "" >> "${DESTDIR}/${GRUB_PREFIX_DIR}/${GRUB_CFG}"
if [[ "${NAME_SCHEME_PARAMETER}" == "PARTUUID" ]] || [[ "${NAME_SCHEME_PARAMETER}" == "FSUUID" ]] ; then
GRUB_ROOT_DRIVE="search --fs-uuid --no-floppy --set=root ${BOOT_PART_HINTS_STRING} ${BOOT_PART_FS_UUID}"
else
if [[ "${NAME_SCHEME_PARAMETER}" == "PARTLABEL" ]] || [[ "${NAME_SCHEME_PARAMETER}" == "FSLABEL" ]] ; then
GRUB_ROOT_DRIVE="search --label --no-floppy --set=root ${BOOT_PART_HINTS_STRING} ${BOOT_PART_FS_LABEL}"
else
GRUB_ROOT_DRIVE="set root="${BOOT_PART_DRIVE}""
fi
fi
if [[ "${GRUB_UEFI}" == "1" ]]; then
LINUX_UNMOD_COMMAND="linux ${subdir}/${VMLINUZ} ${_KERNEL_PARAMS_UEFI_MOD}"
else
LINUX_UNMOD_COMMAND="linux ${subdir}/${VMLINUZ} ${_KERNEL_PARAMS_BIOS_MOD}"
fi
LINUX_MOD_COMMAND=$(echo "${LINUX_UNMOD_COMMAND}" | sed -e 's# # #g' | sed -e 's# # #g')
## create default kernel entry
NUMBER="0"
cat << EOF >> "${DESTDIR}/${GRUB_PREFIX_DIR}/${GRUB_CFG}"
# (${NUMBER}) Arch Linux
menuentry "Arch Linux" {
set gfxpayload="keep"
${GRUB_ROOT_DRIVE}
${LINUX_MOD_COMMAND}
initrd ${subdir}/${INTEL_UCODE} ${subdir}/${AMD_UCODE} ${subdir}/${INITRAMFS}.img
}
EOF
NUMBER=$((${NUMBER}+1))
## create kernel fallback entry
cat << EOF >> "${DESTDIR}/${GRUB_PREFIX_DIR}/${GRUB_CFG}"
# (${NUMBER}) Arch Linux Fallback
menuentry "Arch Linux Fallback" {
set gfxpayload="keep"
${GRUB_ROOT_DRIVE}
${LINUX_MOD_COMMAND}
initrd ${subdir}/${INTEL_UCODE} ${subdir}/${AMD_UCODE} ${subdir}/${INITRAMFS}-fallback.img
}
EOF
NUMBER=$((${NUMBER}+1))
cat << EOF >> "${DESTDIR}/${GRUB_PREFIX_DIR}/${GRUB_CFG}"
if [ "\${grub_platform}" == "efi" ]; then
## UEFI Shell 2.0
#menuentry "UEFI Shell \${_UEFI_ARCH} v2" {
# search --fs-uuid --no-floppy --set=root ${UEFISYS_PART_HINTS_STRING} ${UEFISYS_PART_FS_UUID}
# chainloader /EFI/tools/shell\${_SPEC_UEFI_ARCH}_v2.efi
#}
## UEFI Shell 1.0
#menuentry "UEFI Shell \${_UEFI_ARCH} v1" {
# search --fs-uuid --no-floppy --set=root ${UEFISYS_PART_HINTS_STRING} ${UEFISYS_PART_FS_UUID}
# chainloader /EFI/tools/shell\${_SPEC_UEFI_ARCH}_v1.efi
#}
fi
EOF
NUMBER=$((${NUMBER}+1))
cat << EOF >> "${DESTDIR}/${GRUB_PREFIX_DIR}/${GRUB_CFG}"
if [ "\${grub_platform}" == "efi" ]; then
if [ "\${grub_cpu}" == "x86_64" ]; then
## Microsoft Windows 10/11 via x86_64 UEFI
#menuentry \"Microsoft Windows 10/11 x86_64 UEFI-GPT\" {
# insmod part_gpt
# insmod fat
# insmod search_fs_uuid
# insmod chain
# search --fs-uuid --no-floppy --set=root ${UEFISYS_PART_HINTS_STRING} ${UEFISYS_PART_FS_UUID}
# chainloader /EFI/Microsoft/Boot/bootmgfw.efi
#}
fi
fi
EOF
NUMBER=$((${NUMBER}+1))
## TODO: Detect actual Windows installation if any
## create example file for windows
cat << EOF >> "${DESTDIR}/${GRUB_PREFIX_DIR}/${GRUB_CFG}"
if [ "\${grub_platform}" == "pc" ]; then
## Microsoft Windows 10/11 BIOS
#menuentry \"Microsoft Windows 10/11 BIOS-MBR\" {
# insmod part_msdos
# insmod ntfs
# insmod search_fs_uuid
# insmod ntldr
# search --fs-uuid --no-floppy --set=root <FS_UUID of Windows SYSTEM Partition>
# ntldr /bootmgr
#}
fi
EOF
## copy unicode.pf2 font file
cp -f "${DESTDIR}/usr/share/grub/unicode.pf2" "${DESTDIR}/${GRUB_PREFIX_DIR}/fonts/unicode.pf2"
chroot_umount
## Edit grub.cfg config file
DIALOG --msgbox "You must now review the grub(2) configuration file.\n\nYou will now be put into the editor. After you save your changes, exit the editor." 0 0
geteditor || return 1
"${EDITOR}" "${DESTDIR}/${GRUB_PREFIX_DIR}/${GRUB_CFG}"
unset BOOT_PART_FS_UUID
unset BOOT_PART_FS
unset BOOT_PART_FS_LABEL
unset BOOT_PART_DRIVE
unset ROOT_PART_FS_UUID
unset ROOT_PART_FS
unset ROOT_PART_FS_LABEL
unset ROOT_PART_DEVICE
unset GRUB_ROOT_DRIVE
unset LINUX_UNMOD_COMMAND
unset LINUX_MOD_COMMAND
}
do_grub_bios() {
do_grub_common_before
# try to auto-configure GRUB(2)...
if [[ "${PART_ROOT}" != "" ]]; then
check_bootpart
# check if raid, raid partition, dmraid or device devicemapper is used
if [[ "$(echo ${bootdev} | grep /dev/md)" ]] || [[ "$(echo ${bootdev} | grep /dev/mapper)" ]]; then
# boot from lvm, raid, partitioned raid and dmraid devices is supported
FAIL_COMPLEX="0"
if [[ "$(cryptsetup status ${bootdev})" ]]; then
# encryption devices are not supported
FAIL_COMPLEX="1"
fi
fi
if [[ "${FAIL_COMPLEX}" == "0" ]]; then
grubdev=$(basename ${bootdev})
complexuuid=$(getfsuuid ${bootdev})
# check if mapper is used
if [[ "$(echo ${bootdev} | grep /dev/mapper)" ]]; then
RAID_ON_LVM="0"
#check if mapper contains a md device!
for devpath in $(pvs -o pv_name --noheading); do
if [[ "$(echo ${devpath} | grep -v /dev/md*p | grep /dev/md)" ]]; then
detectedvolumegroup="$(echo $(pvs -o vg_name --noheading ${devpath}))"
if [[ "$(echo /dev/mapper/${detectedvolumegroup}-* | grep ${bootdev})" ]]; then
# change bootdev to md device!
bootdev=$(pvs -o pv_name --noheading ${devpath})
RAID_ON_LVM="1"
break
fi
fi
done
fi
#check if raid is used
USE_RAID=""
if [[ "$(echo ${bootdev} | grep /dev/md)" ]]; then
USE_RAID="1"
fi
else
# use normal device
grubdev=$(mapdev ${bootdev})
fi
fi
# A switch is needed if complex ${bootdev} is used!
# - LVM and RAID ${bootdev} needs the MBR of a device and cannot be used itself as ${bootdev}
if [[ "${FAIL_COMPLEX}" == "0" ]]; then
DEVS="$(findbootloaderdisks _)"
if [[ "${DEVS}" == "" ]]; then
DIALOG --msgbox "No storage drives were found" 0 0
return 1
fi
DIALOG --menu "Select the boot device where the GRUB(2) bootloader will be installed." 14 55 7 ${DEVS} 2>${ANSWER} || return 1
bootdev=$(cat ${ANSWER})
else
DEVS="$(findbootloaderdisks _)"
## grub BIOS install to partition is not supported
# DEVS="${DEVS} $(findbootloaderpartitions _)"
if [[ "${DEVS}" == "" ]]; then
DIALOG --msgbox "No storage drives were found" 0 0
return 1
fi
DIALOG --menu "Select the boot device where the GRUB(2) bootloader will be installed." 14 55 7 ${DEVS} 2>${ANSWER} || return 1
bootdev=$(cat ${ANSWER})
fi
if [[ "$(${_BLKID} -p -i -o value -s PTTYPE ${bootdev})" == "gpt" ]]; then
CHECK_BIOS_BOOT_GRUB="1"
CHECK_UEFISYS_PART=""
RUN_CFDISK=""
DISC="${bootdev}"
check_gpt
else
if [[ "${FAIL_COMPLEX}" == "0" ]]; then
DIALOG --defaultno --yesno "Warning:\nSetup detected no GUID (gpt) partition table.\n\nGrub(2) has only space for approx. 30k core.img file. Depending on your setup, it might not fit into this gap and fail.\n\nDo you really want to install grub(2) to a msdos partition table?" 0 0 || return 1
fi
fi
if [[ "${FAIL_COMPLEX}" == "1" ]]; then
DIALOG --msgbox "Error:\nGrub(2) cannot boot from ${bootdev}, which contains /boot!\n\nPossible error sources:\n- encrypted devices are not supported" 0 0
return 1
fi
DIALOG --infobox "Installing the GRUB(2) BIOS bootloader..." 0 0
# freeze and unfreeze xfs filesystems to enable grub(2) installation on xfs filesystems
freeze_xfs
chroot_mount
chroot "${DESTDIR}" "/usr/bin/grub-install" \
--directory="/usr/lib/grub/i386-pc" \
--target="i386-pc" \
--boot-directory="/boot" \
--recheck \
--debug \
"${bootdev}" &>"/tmp/grub_bios_install.log"
chroot_umount
mkdir -p "${DESTDIR}/boot/grub/locale"
cp -f "${DESTDIR}/usr/share/locale/en@quot/LC_MESSAGES/grub.mo" "${DESTDIR}/boot/grub/locale/en.mo"
if [[ -e "${DESTDIR}/boot/grub/i386-pc/core.img" ]]; then
DIALOG --msgbox "GRUB(2) BIOS has been successfully installed." 0 0
GRUB_PREFIX_DIR="/boot/grub/"
GRUB_BIOS="1"
do_grub_config
GRUB_BIOS=""
else
DIALOG --msgbox "Error installing GRUB(2) BIOS.\nCheck /tmp/grub_bios_install.log for more info.\n\nYou probably need to install it manually by chrooting into ${DESTDIR}.\nDon't forget to bind mount /dev and /proc into ${DESTDIR} before chrooting." 0 0
return 1
fi
}
do_grub_uefi() {
do_uefi_common
[[ "${_UEFI_ARCH}" == "X64" ]] && _GRUB_ARCH="x86_64"
[[ "${_UEFI_ARCH}" == "IA32" ]] && _GRUB_ARCH="i386"
do_grub_common_before
chroot_mount
if [[ "${_DETECTED_UEFI_SECURE_BOOT}" == "1" ]]; then
# install fedora shim
[[ ! -d ${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/BOOT ]] && mkdir -p ${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/BOOT/
cp -f /usr/share/archboot/fedora-shim/shim${_SPEC_UEFI_ARCH}.efi ${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/BOOT/BOOT${_UEFI_ARCH}.efi
cp -f /usr/share/archboot/fedora-shim/mm${_SPEC_UEFI_ARCH}.efi ${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/BOOT/
GRUB_PREFIX_DIR="${UEFISYS_MOUNTPOINT}/EFI/BOOT/"
else
## Create GRUB Standalone EFI image - https://wiki.archlinux.org/index.php/GRUB#GRUB_Standalone
echo 'configfile ${cmdpath}/grub.cfg' > /tmp/grub.cfg
chroot "${DESTDIR}" "/usr/bin/grub-mkstandalone" \
--directory="/usr/lib/grub/${_GRUB_ARCH}-efi" \
--format="${_GRUB_ARCH}-efi" \
--modules="part_gpt part_msdos" \
--install-modules="all" \
--fonts="unicode" \
--locales="en@quot" \
--themes="" \
--verbose \
--output="${UEFISYS_MOUNTPOINT}/EFI/grub/grub${_SPEC_UEFI_ARCH}_standalone.efi" \
"/boot/grub/grub.cfg=/tmp/grub.cfg" &> "/tmp/grub_uefi_${_UEFI_ARCH}_mkstandalone.log"
## Install GRUB normally
chroot "${DESTDIR}" "/usr/bin/grub-install" \
--directory="/usr/lib/grub/${_GRUB_ARCH}-efi" \
--target="${_GRUB_ARCH}-efi" \
--efi-directory="${UEFISYS_MOUNTPOINT}" \
--bootloader-id="grub" \
--boot-directory="/boot" \
--no-nvram \
--recheck \
--debug &> "/tmp/grub_uefi_${_UEFI_ARCH}_install.log"
cat "/tmp/grub_uefi_${_UEFI_ARCH}_mkstandalone.log" >> "${LOG}"
cat "/tmp/grub_uefi_${_UEFI_ARCH}_install.log" >> "${LOG}"
GRUB_PREFIX_DIR="/boot/grub/"
fi
chroot_umount
GRUB_UEFI="1"
do_grub_config
GRUB_UEFI=""
if [[ "${_DETECTED_UEFI_SECURE_BOOT}" == "1" ]]; then
# generate GRUB with config embeded
chroot_mount
# create Arch Linux sbat file
# add sbat file: https://bugs.archlinux.org/task/72415
echo "sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md" > ${DESTDIR}/tmp/sbat.csv
echo "grub,1,Free Software Foundation,grub,2.06,https//www.gnu.org/software/grub/" >> ${DESTDIR}/tmp/sbat.csv
echo "arch,1,Arch Linux,\$pkgname,\$pkgver,https://archlinux.org/packages/core/x86_64/grub/" >> ${DESTDIR}/tmp/sbat.csv
### Hint: https://src.fedoraproject.org/rpms/grub2/blob/rawhide/f/grub.macros#_407
_GRUB_MODULES="all_video boot btrfs cat configfile cryptodisk echo efi_gop efi_uga efifwsetup efinet ext2 f2fs fat \
font gcry_rijndael gcry_rsa gcry_serpent gcry_sha256 gcry_twofish gcry_whirlpool gfxmenu gfxterm gzio \
halt hfsplus http iso9660 loadenv loopback linux lvm lsefi lsefimmap luks luks2 mdraid09 mdraid1x minicmd \
net normal part_apple part_msdos part_gpt password_pbkdf2 pgp png reboot regexp search search_fs_uuid \
search_fs_file search_label serial sleep syslinuxcfg test tftp video xfs zstd backtrace chain tpm usb \
usbserial_common usbserial_pl2303 usbserial_ftdi usbserial_usbdebug keylayouts at_keyboard"
# add -v for verbose
_COMMON_GRUB_OPTIONS="--sbat /tmp/sbat.csv --modules="${_GRUB_MODULES}" --fonts="unicode" --locales="en@quot" --themes="""
chroot "${DESTDIR}" grub-mkstandalone -d /usr/lib/grub/${_GRUB_ARCH}-efi -O ${_GRUB_ARCH}-efi ${_COMMON_GRUB_OPTIONS} -o "${GRUB_PREFIX_DIR}/grub${_SPEC_UEFI_ARCH}.efi" "boot/grub/grub.cfg=/${GRUB_PREFIX_DIR}/${GRUB_CFG}"
cp /${GRUB_PREFIX_DIR}/${GRUB_CFG} ${UEFISYS_MOUNTPOINT}/EFI/BOOT/grub${_SPEC_UEFI_ARCH}.cfg
chroot_umount
fi
if [[ -e "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/grub/grub${_SPEC_UEFI_ARCH}_standalone.efi" ]]; then
cp -f "${DESTDIR}/${UEFISYS_MOUNTPOINT}/${GRUB_PREFIX_DIR}/grub.cfg" "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/grub/grub.cfg"
_BOOTMGR_LABEL="GRUB_Standalone"
_BOOTMGR_LOADER_DIR="/EFI/grub/grub${_SPEC_UEFI_ARCH}_standalone.efi"
do_uefi_bootmgr_setup
DIALOG --msgbox "GRUB(2) Standalone for ${_UEFI_ARCH} UEFI has been installed successfully." 8 65
elif [[ -e "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/grub/grub${_SPEC_UEFI_ARCH}.efi" ]] && [[ -e "${DESTDIR}/boot/grub/${_GRUB_ARCH}-efi/core.efi" ]]; then
_BOOTMGR_LABEL="GRUB_Normal"
_BOOTMGR_LOADER_DIR="/EFI/grub/grub${_SPEC_UEFI_ARCH}.efi"
do_uefi_bootmgr_setup
DIALOG --msgbox "GRUB(2) for ${_UEFI_ARCH} UEFI has been installed successfully." 8 65
DIALOG --defaultno --yesno "Do you want to copy ${UEFISYS_MOUNTPOINT}/EFI/grub/grub${_SPEC_UEFI_ARCH}.efi to ${UEFISYS_MOUNTPOINT}/EFI/BOOT/boot${_SPEC_UEFI_ARCH}.efi ?\n\nThis might be needed in some systems where efibootmgr may not work due to firmware issues." 0 0 && _UEFISYS_EFI_BOOT_DIR="1"
if [[ "${_UEFISYS_EFI_BOOT_DIR}" == "1" ]]; then
mkdir -p "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/BOOT"
rm -f "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/BOOT/boot${_SPEC_UEFI_ARCH}.efi" || true
cp -f "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/grub/grub${_SPEC_UEFI_ARCH}.efi" "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/BOOT/boot${_SPEC_UEFI_ARCH}.efi"
fi
elif [[ -e "${DESTDIR}/${UEFISYS_MOUNTPOINT}/EFI/BOOT/grub${_SPEC_UEFI_ARCH}.efi" ]]; then
do_secureboot_keys
do_mok_sign
do_pacman_sign
do_uefi_secure_boot_efitools
_BOOTMGR_LABEL="SHIM with GRUB Secure Boot"
_BOOTMGR_LOADER_DIR="/EFI/BOOT/BOOT${_UEFI_ARCH}.efi"
do_uefi_bootmgr_setup
DIALOG --msgbox "SHIM and GRUB Secure Boot for ${_UEFI_ARCH} UEFI has been installed successfully." 8 75
else
DIALOG --msgbox "Error installing GRUB(2) for ${_UEFI_ARCH} UEFI.\nCheck /tmp/grub_uefi_${_UEFI_ARCH}_install.log for more info.\n\nYou probably need to install it manually by chrooting into ${DESTDIR}.\nDon't forget to bind mount /dev, /sys and /proc into ${DESTDIR} before chrooting." 0 0
return 1
fi
}
select_source() {
NEXTITEM="2"
MODE="network"
if [[ ${S_NET} -eq 0 ]]; then
donetwork || return 1
fi
if [[ ${S_TESTING} -eq 0 ]]; then
dotesting
fi
TITLE="Arch Linux Installation"
getsource || return 1
# check for updating complete environment with packages
if [[ -d "/var/cache/pacman/pkg" ]] && [[ -n "$(ls -A "/var/cache/pacman/pkg")" ]]; then
echo "Packages are already in pacman cache... > ${LOG}"
else
detect_uefi_boot
UPDATE_ENVIRONMENT=""
if [[ -e "/usr/bin/update-installer.sh" && "${_DETECTED_UEFI_SECURE_BOOT}" == "0" ]];then
DIALOG --defaultno --yesno "${_DETECTED_UEFI_SECURE_BOOT} Do you want to update the archboot environment to latest packages with caching packages for installation?\n\nATTENTION:\nRequires at least 4GB RAM and will reboot the system using kexec!" 0 0 && UPDATE_ENVIRONMENT="1"
if [[ "${UPDATE_ENVIRONMENT}" == "1" ]]; then
DIALOG --infobox "Now setting up new archboot environment and dowloading latest packages.\n\nRunning at the moment: update-installer.sh -latest-install\nCheck "${LOG}" for progress...\n\nGet a cup of coffee ...\nThis needs approx. 5 minutes on a fast internet connection (100Mbit)." 0 0
/usr/bin/update-installer.sh -latest-install > "${LOG}" 2>&1
fi
fi
fi
NEXTITEM="3"
}
set_clock() {
if [[ -e /usr/bin/tz ]]; then
tz --setup && NEXTITEM="4"
else
DIALOG --msgbox "Error:\ntz script not found, aborting clock setting" 0 0
fi
}
set_keyboard() {
if [[ -e /usr/bin/km ]]; then
km --setup && NEXTITEM="1"
else
DIALOG --msgbox "Error:\nkm script not found, aborting keyboard and console setting" 0 0
fi
}
# run_mkinitcpio()
# runs mkinitcpio on the target system, displays output
#
run_mkinitcpio() {
chroot_mount
# all mkinitcpio output goes to /tmp/mkinitcpio.log, which we tail into a dialog
( \
touch /tmp/setup-mkinitcpio-running
echo "Initramfs progress ..." > /tmp/initramfs.log; echo >> /tmp/mkinitcpio.log
chroot ${DESTDIR} /usr/bin/mkinitcpio -p ${KERNELPKG} >>/tmp/mkinitcpio.log 2>&1
echo >> /tmp/mkinitcpio.log
rm -f /tmp/setup-mkinitcpio-running
) &
sleep 2
dialog --backtitle "${TITLE}" --title "Rebuilding initramfs images ..." --no-kill --tailboxbg "/tmp/mkinitcpio.log" 18 70
while [[ -f /tmp/setup-mkinitcpio-running ]]; do
/usr/bin/true
done
chroot_umount
}
prepare_storagedrive() {
S_MKFSAUTO=0
S_MKFS=0
DONE=0
NEXTITEM=""
detect_
while [[ "${DONE}" = "0" ]]; do
if [[ -n "${NEXTITEM}" ]]; then
DEFAULT="--default-item ${NEXTITEM}"
else
DEFAULT=""
fi
CANCEL=""
dialog ${DEFAULT} --backtitle "${TITLE}" --menu "Prepare Storage Drive" 12 60 5 \
"1" "Auto-Prepare (erases the ENTIRE storage drive)" \
"2" "Partition Storage Drives" \
"3" "Create Software Raid, Lvm2 and Luks encryption" \
"4" "Set Filesystem Mountpoints" \
"5" "Return to Main Menu" 2>${ANSWER} || CANCEL="1"
NEXTITEM="$(cat ${ANSWER})"
[[ "${S_MKFSAUTO}" = "1" ]] && DONE=1
case $(cat ${ANSWER}) in
"1")
autoprepare
[[ "${S_MKFSAUTO}" = "1" ]] && DONE=1
;;
"2")
partition ;;
"3")
create_special ;;
"4")
PARTFINISH=""
ASK_MOUNTPOINTS="1"
mountpoints ;;
*)
DONE=1 ;;
esac
done
if [[ "${CANCEL}" = "1" ]]; then
NEXTITEM="4"
else
NEXTITEM="5"
fi
}
# menu for raid, lvm and encrypt
create_special() {
NEXTITEM=""
SPECIALDONE=0
while [[ "${SPECIALDONE}" = "0" ]]; do
if [[ -n "${NEXTITEM}" ]]; then
DEFAULT="--default-item ${NEXTITEM}"
else
DEFAULT=""
fi
CANCEL=""
dialog ${DEFAULT} --backtitle "${TITLE}" --menu "Create Software Raid, LVM2 and Luks encryption" 14 60 5 \
"1" "Create Software Raid" \
"2" "Create LVM2" \
"3" "Create Luks encryption" \
"4" "Return to Previous Menu" 2>${ANSWER} || CANCEL="1"
NEXTITEM="$(cat ${ANSWER})"
case $(cat ${ANSWER}) in
"1")
_createmd ;;
"2")
_createlvm ;;
"3")
_createluks ;;
*)
SPECIALDONE=1 ;;
esac
done
if [[ "${CANCEL}" = "1" ]]; then
NEXTITEM="3"
else
NEXTITEM="4"
fi
}
# menu for md creation
_createmd() {
NEXTITEM=""
MDDONE=0
while [[ "${MDDONE}" = "0" ]]; do
if [[ -n "${NEXTITEM}" ]]; then
DEFAULT="--default-item ${NEXTITEM}"
else
DEFAULT=""
fi
CANCEL=""
dialog ${DEFAULT} --backtitle "${TITLE}" --menu "Create Software Raid" 12 60 5 \
"1" "Raid Help" \
"2" "Reset Software Raid completely" \
"3" "Create Software Raid" \
"4" "Create Partitionable Software Raid" \
"5" "Return to Previous Menu" 2>${ANSWER} || CANCEL="1"
NEXTITEM="$(cat ${ANSWER})"
case $(cat ${ANSWER}) in
"1")
_helpraid ;;
"2")
_stopmd ;;
"3")
RAID_PARTITION=""
_raid ;;
"4")
RAID_PARTITION="1"
_raid ;;
*)
MDDONE=1 ;;
esac
done
if [[ "${CANCEL}" = "1" ]]; then
NEXTITEM="1"
else
NEXTITEM="4"
fi
}
# menu for lvm creation
_createlvm() {
NEXTITEM=""
LVMDONE=0
while [[ "${LVMDONE}" = "0" ]]; do
if [[ -n "${NEXTITEM}" ]]; then
DEFAULT="--default-item ${NEXTITEM}"
else
DEFAULT=""
fi
CANCEL=""
dialog ${DEFAULT} --backtitle "${TITLE}" --menu "Create physical volume, volume group or logical volume" 13 60 7 \
"1" "LVM Help" \
"2" "Reset Logical Volume completely" \
"3" "Create Physical Volume" \
"4" "Create Volume Group" \
"5" "Create Logical Volume" \
"6" "Return to Previous Menu" 2>${ANSWER} || CANCEL="1"
NEXTITEM="$(cat ${ANSWER})"
case $(cat ${ANSWER}) in
"1")
_helplvm ;;
"2")
_stoplvm ;;
"3")
_createpv ;;
"4")
_createvg ;;
"5")
_createlv ;;
*)
LVMDONE=1 ;;
esac
done
if [[ "${CANCEL}" = "1" ]]; then
NEXTITEM="2"
else
NEXTITEM="4"
fi
}
# menu for luks creation
_createluks() {
NEXTITEM=""
LUKSDONE=0
while [[ "${LUKSDONE}" = "0" ]]; do
if [[ -n "${NEXTITEM}" ]]; then
DEFAULT="--default-item ${NEXTITEM}"
else
DEFAULT=""
fi
CANCEL=""
dialog ${DEFAULT} --backtitle "${TITLE}" --menu "Create Luks Encryption" 12 60 5 \
"1" "Luks Help" \
"2" "Reset Luks Encryption completely" \
"3" "Create Luks" \
"4" "Return to Previous Menu" 2>${ANSWER} || CANCEL="1"
NEXTITEM="$(cat ${ANSWER})"
case $(cat ${ANSWER}) in
"1")
_helpluks ;;
"2")
_stopluks ;;
"3")
_luks ;;
*)
LUKSDONE=1 ;;
esac
done
if [[ "${CANCEL}" = "1" ]]; then
NEXTITEM="3"
else
NEXTITEM="4"
fi
}
auto_hwdetect() {
HWDETECT=""
FBPARAMETER=""
HWPARAMETER=""
HWDETECTMODULES=""
HWDETECTHOOKS=""
HWKVER==
DIALOG --yesno "PRECONFIGURATION?\n-----------------\n\nDo you want to use 'hwdetect' for:\n'/etc/mkinitcpio.conf'?\n\nThis ensures consistent ordering of your storage disk / usb controllers.\n\nIt is recommended to say 'YES' here." 18 70 && HWDETECT="yes"
if [[ "${HWDETECT}" = "yes" ]]; then
# check on used keymap
! [[ "$(grep '^KEYMAP="us"' ${DESTDIR}/etc/vconsole.conf)" ]] && HWPARAMETER="${HWPARAMETER} --keymap"
# check on framebuffer modules and kms
[[ "$(grep "^radeon" /proc/modules)" ]] && FBPARAMETER="--ati-kms"
[[ "$(grep "^amdgpu" /proc/modules)" ]] && FBPARAMETER="--amd-kms"
[[ "$(grep "^i915" /proc/modules )" ]] && FBPARAMETER="--intel-kms"
[[ "$(grep "^nouveau" /proc/modules)" ]] && FBPARAMETER="--nvidia-kms"
if [[ "$(lsmod | grep ^nfs)" ]]; then
DIALOG --defaultno --yesno "Setup detected nfs driver...\nDo you need support for booting from nfs shares?" 0 0 && HWPARAMETER="${HWPARAMETER} --nfs"
fi
if [[ -e ${DESTDIR}/lib/initcpio/hooks/dmraid ]]; then
if ! [[ "$(dmraid -r | grep ^no )" ]]; then
HWPARAMETER="${HWPARAMETER} --dmraid"
fi
fi
offset=$(hexdump -s 526 -n 2 -e '"%0d"' "${DESTDIR}/boot/${VMLINUZ}")
read HWKER _ < <(dd if="${DESTDIR}/boot/${VMLINUZ}" bs=1 count=127 skip=$(( offset + 0x200 )) 2>/dev/null)
HWDETECTMODULES="$(echo $(hwdetect --kernel_directory=${DESTDIR} --kernel_version=${HWKVER} ${FBPARAMETER} --hostcontroller --filesystem ${HWPARAMETER}) | sed -e 's#.*\" ##g')"
HWDETECTHOOKS="$(hwdetect --kernel_directory=${DESTDIR} --kernel_version=${HWKVER} --rootdevice=${PART_ROOT} --hooks-dir=${DESTDIR}/usr/lib/initcpio/install ${FBPARAMETER} ${HWPARAMETER} --hooks)"
[[ -n "${HWDETECTMODULES}" ]] && sed -i -e "s/^MODULES=.*/${HWDETECTMODULES}/g" ${DESTDIR}/etc/mkinitcpio.conf
[[ -n "${HWDETECTHOOKS}" ]] && sed -i -e "s/^HOOKS=.*/${HWDETECTHOOKS}/g" ${DESTDIR}/etc/mkinitcpio.conf
fi
}
auto_parameters() {
if [[ ! -f ${DESTDIR}/etc/vconsole.conf ]]; then
: >${DESTDIR}/etc/vconsole.conf
if [[ -s /tmp/.keymap ]]; then
DIALOG --infobox "Setting the keymap: $(cat /tmp/.keymap | sed -e 's/\..*//g') in vconsole.conf ..." 0 0
echo KEYMAP=$(cat /tmp/.keymap | sed -e 's/\..*//g') >> ${DESTDIR}/etc/vconsole.conf
fi
if [[ -s /tmp/.font ]]; then
DIALOG --infobox "Setting the consolefont: $(cat /tmp/.font | sed -e 's/\..*//g') in vconsole.conf ..." 0 0
echo FONT=$(cat /tmp/.font | sed -e 's/\..*//g') >> ${DESTDIR}/etc/vconsole.conf
fi
fi
}
auto_luks() {
# remove root device from crypttab
if [[ -e /tmp/.crypttab && "$(grep -v '^#' ${DESTDIR}/etc/crypttab)" = "" ]]; then
# add to temp crypttab
sed -i -e "/^$(basename ${PART_ROOT}) /d" /tmp/.crypttab
cat /tmp/.crypttab >> ${DESTDIR}/etc/crypttab
chmod 600 /tmp/passphrase-* 2>/dev/null
cp /tmp/passphrase-* ${DESTDIR}/etc/ 2>/dev/null
fi
}
auto_timesetting() {
if [[ -e /etc/localtime && ! -e ${DESTDIR}/etc/localtime ]]; then
cp -a /etc/localtime ${DESTDIR}/etc/localtime
fi
if [[ ! -f ${DESTDIR}/etc/adjtime ]]; then
echo "0.0 0 0.0" > ${DESTDIR}/etc/adjtime
echo "0" >> ${DESTDIR}/etc/adjtime
[[ -s /tmp/.hardwareclock ]] && cat /tmp/.hardwareclock >>${DESTDIR}/etc/adjtime
fi
}
auto_pacman_mirror() {
# /etc/pacman.d/mirrorlist
# add installer-selected mirror to the top of the mirrorlist
if [[ "${MODE}" = "network" && "${SYNC_URL}" != "" ]]; then
SYNC_URL="${SYNC_URL}"
awk "BEGIN { printf(\"# Mirror used during installation\nServer = "${SYNC_URL}"\n\n\") } 1 " "${DESTDIR}/etc/pacman.d/mirrorlist" > /tmp/inst-mirrorlist
mv /tmp/inst-mirrorlist "${DESTDIR}/etc/pacman.d/mirrorlist"
fi
}
auto_system_files () {
if [[ ! -f ${DESTDIR}/etc/hostname ]]; then
echo "myhostname" > ${DESTDIR}/etc/hostname
fi
if [[ ! -f ${DESTDIR}/etc/locale.conf ]]; then
echo "LANG=en_US.UTF-8" > ${DESTDIR}/etc/locale.conf
echo "LC_COLLATE=C" >> ${DESTDIR}/etc/locale.conf
fi
}
configure_system() {
destdir_mounts || return 1
## PREPROCESSING ##
# only done on first invocation of configure_system and redone on canceled configure system
if [[ ${S_CONFIG} -eq 0 ]]; then
auto_pacman_mirror
auto_network
auto_parameters
auto_system_files
auto_hwdetect
fi
## END PREPROCESS ##
geteditor || return 1
FILE=""
# main menu loop
while true; do
S_CONFIG=0
if [[ -n "${FILE}" ]]; then
DEFAULT="--default-item ${FILE}"
else
DEFAULT=""
fi
DIALOG ${DEFAULT} --menu "Configuration" 21 80 16 \
"/etc/hostname" "System Hostname" \
"/etc/vconsole.conf" "Virtual Console" \
"/etc/locale.conf" "Locale Setting" \
"/etc/fstab" "Filesystem Mountpoints" \
"/etc/mkinitcpio.conf" "Initramfs Config" \
"/etc/modprobe.d/modprobe.conf" "Kernel Modules" \
"/etc/resolv.conf" "DNS Servers" \
"/etc/hosts" "Network Hosts" \
"/etc/locale.gen" "Glibc Locales" \
"/etc/pacman.d/mirrorlist" "Pacman Mirror List" \
"/etc/pacman.conf" "Pacman Config File" \
"Root-Password" "Set the root password" \
"Return" "Return to Main Menu" 2>${ANSWER} || break
FILE="$(cat ${ANSWER})"
if [[ "${FILE}" = "Return" || -z "${FILE}" ]]; then # exit
S_CONFIG=1
break
elif [[ "${FILE}" = "/etc/mkinitcpio.conf" ]]; then # non-file
DIALOG --msgbox "The mkinitcpio.conf file controls which modules will be placed into the initramfs for your system's kernel.\n\n- Non US keymap users should add 'keymap' to HOOKS= array\n- If you install under VMWARE add 'BusLogic' to MODULES= array\n- raid, lvm2, encrypt are not enabled by default\n- 2 or more disk controllers, please specify the correct module\n loading order in MODULES= array \n\nMost of you will not need to change anything in this file." 18 70
HOOK_ERROR=""
${EDITOR} ${DESTDIR}${FILE}
for i in $(cat ${DESTDIR}/etc/mkinitcpio.conf | grep ^HOOKS | sed -e 's/"//g' -e 's/HOOKS=//g'); do
[[ -e ${DESTDIR}/usr/lib/initcpio/install/${i} ]] || HOOK_ERROR=1
done
if [[ "${HOOK_ERROR}" = "1" ]]; then
DIALOG --msgbox "ERROR: Detected error in 'HOOKS=' line, please correct HOOKS= in /etc/mkinitcpio.conf!" 18 70
fi
elif [[ "${FILE}" = "/etc/locale.gen" ]]; then # non-file
# enable glibc locales from locale.conf
for i in $(grep "^LANG" ${DESTDIR}/etc/locale.conf | sed -e 's/.*=//g' -e's/\..*//g'); do
sed -i -e "s/^#${i}/${i}/g" ${DESTDIR}/etc/locale.gen
done
${EDITOR} ${DESTDIR}${FILE}
elif [[ "${FILE}" = "Root-Password" ]]; then # non-file
PASSWORD=""
while [[ "${PASSWORD}" = "" ]]; do
DIALOG --insecure --passwordbox "Enter root password:" 0 0 2>${ANSWER} || return 1
PASS=$(cat ${ANSWER})
DIALOG --insecure --passwordbox "Retype root password:" 0 0 2>${ANSWER} || return 1
PASS2=$(cat ${ANSWER})
if [[ "${PASS}" = "${PASS2}" ]]; then
PASSWORD=${PASS}
echo ${PASSWORD} > /tmp/.password
echo ${PASSWORD} >> /tmp/.password
PASSWORD=/tmp/.password
else
DIALOG --msgbox "Password didn't match, please enter again." 0 0
fi
done
chroot ${DESTDIR} passwd root < /tmp/.password
rm /tmp/.password
else #regular file
${EDITOR} ${DESTDIR}${FILE}
fi
done
if [[ ${S_CONFIG} -eq 1 ]]; then
# only done on normal exit of configure menu
## POSTPROCESSING ##
# adjust time
auto_timesetting
# /etc/initcpio.conf
run_mkinitcpio
# /etc/locale.gen
# enable at least en_US.UTF8 if nothing was changed, else weird things happen on reboot!
! [[ $(grep -q ^[a-z] ${DESTDIR}/etc/locale.gen) ]] && sed -i -e 's:^#en_US.UTF-8:en_US.UTF-8:g' ${DESTDIR}/etc/locale.gen
chroot ${DESTDIR} locale-gen >/dev/null 2>&1
## END POSTPROCESSING ##
NEXTITEM="7"
fi
}
install_bootloader_uefi() {
do_uefi_setup_env_vars
if [[ "${_EFI_MIXED}" == "1" ]]; then
_EFISTUB_MENU_LABEL=""
_EFISTUB_MENU_TEXT=""
else
_EFISTUB_MENU_LABEL="EFISTUB"
_EFISTUB_MENU_TEXT="EFISTUB for ${_UEFI_ARCH} UEFI"
fi
if [[ "${_DETECTED_UEFI_SECURE_BOOT}" == "1" ]]; then
do_grub_uefi
else
DIALOG --menu "Which ${_UEFI_ARCH} UEFI bootloader would you like to use?" 12 55 5 \
"${_EFISTUB_MENU_LABEL}" "${_EFISTUB_MENU_TEXT}" \
"GRUB_UEFI" "GRUB(2) for ${_UEFI_ARCH} UEFI" \
"SYSLINUX_UEFI" "SYSLINUX for ${_UEFI_ARCH} UEFI" 2>${ANSWER} || CANCEL=1
case $(cat ${ANSWER}) in
"EFISTUB") do_efistub_uefi ;;
"GRUB_UEFI") do_grub_uefi ;;
"SYSLINUX_UEFI") do_syslinux_uefi ;;
esac
fi
}
install_bootloader_bios() {
DIALOG --menu "Which BIOS bootloader would you like to use?" 11 50 4 \
"GRUB_BIOS" "GRUB(2) BIOS" \
"SYSLINUX_BIOS" "SYSLINUX BIOS" 2>${ANSWER} || CANCEL=1
case $(cat ${ANSWER}) in
"GRUB_BIOS") do_grub_bios ;;
"SYSLINUX_BIOS") do_syslinux_bios ;;
esac
}
install_bootloader() {
destdir_mounts || return 1
if [[ "${NAME_SCHEME_PARAMETER_RUN}" == "" ]]; then
set_device_name_scheme || return 1
fi
if [[ "${S_SRC}" = "0" ]]; then
select_source || return 1
fi
prepare_pacman
CANCEL=""
detect_uefi_boot
_ANOTHER="1"
NEXTITEM="7"
if [[ "${_DETECTED_UEFI_BOOT}" == "1" ]]; then
do_uefi_setup_env_vars
_ANOTHER="0"
if [[ "${_DETECTED_UEFI_SECURE_BOOT}" == "1" ]]; then
DIALOG --yesno "Setup has detected that you are using Secure Boot ...\nDo you like to install SHIM and GRUB ${_UEFI_ARCH} UEFI bootloader?" 0 0 || CANCEL="1"
if [[ "${CANCEL}" == "" ]]; then
install_bootloader_uefi
NEXTITEM="8"
else
NEXTITEM="7"
fi
else
DIALOG --yesno "Setup has detected that you are using ${_UEFI_ARCH} UEFI ...\nDo you like to install a ${_UEFI_ARCH} UEFI bootloader?" 0 0 && install_bootloader_uefi
DIALOG --defaultno --yesno "Do you want to install another bootloader?" 0 0 && _ANOTHER="1"
NEXTITEM="8"
fi
fi
while [[ "${_ANOTHER}" == "1" ]]; do
install_bootloader_menu
_ANOTHER="0"
DIALOG --defaultno --yesno "Do you want to install another bootloader?" 0 0 && _ANOTHER="1"
done
}
install_bootloader_menu() {
DIALOG --menu "What is your boot system type?" 10 40 2 \
"UEFI" "UEFI" \
"BIOS" "BIOS" 2>${ANSWER} || CANCEL=1
case $(cat ${ANSWER}) in
"UEFI") install_bootloader_uefi ;;
"BIOS") install_bootloader_bios ;;
esac
if [[ "${CANCEL}" = "1" ]]; then
NEXTITEM="7"
else
NEXTITEM="8"
fi
}
mainmenu() {
if [[ -n "${NEXTITEM}" ]]; then
DEFAULT="--default-item ${NEXTITEM}"
else
DEFAULT=""
fi
dialog ${DEFAULT} --backtitle "${TITLE}" --title " MAIN MENU " \
--menu "Use the UP and DOWN arrows to navigate menus.\nUse TAB to switch between buttons and ENTER to select." 18 58 14 \
"0" "Set Keyboard And Console Font" \
"1" "Set up Network" \
"2" "Select Source" \
"3" "Set Time And Date" \
"4" "Prepare Storage Drive" \
"5" "Install Packages" \
"6" "Configure System" \
"7" "Install Bootloader" \
"8" "Exit Install" 2>${ANSWER}
NEXTITEM="$(cat ${ANSWER})"
case $(cat ${ANSWER}) in
"0")
set_keyboard ;;
"1")
donetwork ;;
"2")
select_source ;;
"3")
set_clock ;;
"4")
prepare_storagedrive ;;
"5")
install_packages ;;
"6")
configure_system ;;
"7")
install_bootloader ;;
"8")
[[ -e /tmp/.setup-running ]] && rm /tmp/.setup-running
clear
echo ""
echo "If the install finished successfully, you can now type 'reboot'"
echo "to restart the system."
echo ""
exit 0 ;;
*)
DIALOG --yesno "Abort Installation?" 6 40 && [[ -e /tmp/.setup-running ]] && rm /tmp/.setup-running && clear && exit 0
;;
esac
}
#####################
## begin execution ##
if [[ -e /tmp/.setup-running ]]; then
echo "HINT:"
echo "setup already runs on a different console!"
echo "Please remove /tmp/.setup-running first to launch setup!"
exit 1
fi
: >/tmp/.setup-running
: >/tmp/.setup
DIALOG --msgbox "Welcome to the Arch Linux Installation program.\n\nThe install process is fairly straightforward, and you should run through the options in the order they are presented.\n\nIf you are unfamiliar with partitioning/making filesystems, you may want to consult some documentation before continuing.\n\nYou can view all output from commands by viewing your VC7 console (ALT-F7). ALT-F1 will bring you back here." 14 65
while true; do
mainmenu
done
clear
exit 0
# vim: set ts=4 sw=4 et: