# # lsblk # # -d, --nodeps Do not print holder devices or slaves. # -p, --paths Print full device paths. # -l, --list Produce output in the form of a list. # -n, --noheadings # -x, --sort column function get_uuid() { # arg $1: partition # arg $2: variable name to store UUID local -n ptr=$2 || return $? ptr="$(blkid -o value -s UUID "${1}")" || return $? } function get_partitions(){ # arg $1: block-device # @post # PARTITIONS (array with one partition per entry) # Remove first line of output (which is just the block device $1 itself) # with sed: sed 1d PARTITIONS="$(lsblk -pln -o name "${1}" | sed 1d)" || return $? newline_separated_to_array PARTITIONS PARTITIONS || return $? } function get_block_devices() { # @post # BLOCK_DEVICES (array with one entry for each block device) # Get list of devices, one per line BLOCK_DEVICES="$(lsblk -dplnx size -o name | grep -Ev 'boot|rpmb|loop' | tac)" || return $? newline_separated_to_array BLOCK_DEVICES BLOCK_DEVICES || return $? } function get_block_devices_with_size() { # @post # BLOCK_DEVICE_SIZES (array with two entries for each block device: device path and device size) # Get list of devices and their sizes, one pair per line # Use sed to remove multiple white spaces: sed 's|\s\s*| |' BLOCK_DEVICE_SIZES="$(lsblk -dplnx size -o name,size | grep -Ev 'boot|rpmb|loop' | sed 's|\s\s*| |' | tac)" || return $? newline_to_space BLOCK_DEVICE_SIZES || return $? space_separated_to_array BLOCK_DEVICE_SIZES BLOCK_DEVICE_SIZES || return $? } function partition() { # Creates two partitions: # - BOOT_PART by default 261mb # - LUKS_PART rest of the device for (encrypted) data # # @pre # TARGET_BLOCK_DEVICE # BOOT_FIRMWARE # @post # BOOT_PART # LUKS_PART # if BOOT_PART_SIZE not given, set to default value BOOT_PART_SIZE="${BOOT_PART_SIZE:='261'}" # if too small, print warning and exit if [ "${BOOT_PART_SIZE}" -lt '261' ]; then echo 'BOOT_PART_SIZE should be larger than 260!'; return 1; fi # As our data partition is encrypted, # we need a separate boot partition! case "${BOOT_FIRMWARE}" in uefi) # EFI boot partition # # Create a partition with fat32 as the file system type and set the # esp flag on it. sudo parted --script "${TARGET_BLOCK_DEVICE}" -- mklabel gpt \ mkpart ESP fat32 2Mib "${BOOT_PART_SIZE}MiB" \ set 1 esp on \ mkpart primary "${BOOT_PART_SIZE}MiB" 100% || return $? get_partitions "${TARGET_BLOCK_DEVICE}" || return $? BOOT_PART="${PARTITIONS[0]}" LUKS_PART="${PARTITIONS[1]}" ;; bios) # > On a BIOS/GPT configuration, a BIOS boot partition is required. GRUB embeds its `core.img` # > into this partition. # > For parted set/activate the flag bios_grub on the partition. # # archwiki -> GRUB#GUID_Partition_Table_(GPT)_specific_instructions # https://www.gnu.org/software/grub/manual/grub/html_node/BIOS-installation.html#BIOS-installation sudo parted --script "${TARGET_BLOCK_DEVICE}" -- mklabel gpt \ mkpart primary 1MiB 2MiB \ set 1 bios_grub on \ mkpart primary 2MiB "${BOOT_PART_SIZE}MiB" \ mkpart primary "${BOOT_PART_SIZE}MiB" 100% || return $? get_partitions "${TARGET_BLOCK_DEVICE}" || return $? BOOT_PART="${PARTITIONS[2]}" LUKS_PART="${PARTITIONS[3]}" ;; *) echo 'Expected uefi or bios but got '"${BOOT_FIRMWARE}"' instead!' return 1 ;; esac echo 'boot partition: '"${BOOT_PART}" echo 'luks partition: '"${LUKS_PART}" } function format() { # Formats BOOT_PART and LUKS_PART. # If encryption is enabled (FDE='true'), then an encrypted partition will be created at LUKS_PART # which can be accessed under DATA_PART. # If encryption is disabled, then DATA_PART is identical to LUKS_PART. # # @pre # BOOT_FIRMWARE # BOOT_PART # LUKS_PART # LUKS_PWD # FDE: 'true' | 'false' # FS # @post # LUKS_PART_UUID: only set if FDE='true' # DATA_PART: if FDE='true', then set to /dev/mapper/$(basename "${LUKS_PART}") # boot partition formatted # luks partition formatted and accessible under DATA_PART echo 'Wiping old signatures from partitions ...' sudo wipefs "${BOOT_PART}" || return $? sudo wipefs "${LUKS_PART}" || return $? echo 'Formatting boot partition '"${BOOT_PART}"' ...' sudo mkfs.fat -F32 "${BOOT_PART}" || return $? case "${FDE}" in true) # Note: # FDE: GRUB does support LUKS2 since this commit: https://git.savannah.gnu.org/cgit/grub.git/commit/?id=365e0cc3e7e44151c14dd29514c2f870b49f9755 # -> Using "--type luks1" is no longer required. echo 'Creating encrypted luks partition '"${LUKS_PART}"' ...' printf '%s' "${LUKS_PWD}" | sudo cryptsetup luksFormat \ --cipher aes-xts-plain64 --key-size 512 --hash sha512 \ --iter-time 10000 --use-random "${LUKS_PART}" || return $? get_uuid "${LUKS_PART}" LUKS_PART_UUID || return $? local luks_name luks_name=$(basename "${LUKS_PART}") DATA_PART="/dev/mapper/${luks_name}" # open luks partition printf '%s' "${LUKS_PWD}" | sudo cryptsetup luksOpen "${LUKS_PART}" "${luks_name}" || return $? ;; false) DATA_PART="${LUKS_PART}" ;; *) echo 'Invalid option: '"${FDE}" return 1 ;; esac echo 'Formatting the data partition '"${DATA_PART}"' ...' case "${FS}" in BTRFS) sudo mkfs.btrfs "${DATA_PART}" || return $? ;; EXT4) # archwiki -> Ext4#Enabling_metadata_checksums sudo mkfs.ext4 -O metadata_csum "${DATA_PART}" || return $? ;; F2FS) # archwiki -> F2FS#Creating_a_F2FS_file_system # - requires f2fs-tools # - compression: "-O compression" and when mounting the filesystem, specify compress_algorithm=(lzo|lz4|zstd|lzo-rle) sudo mkfs.f2fs -O extra_attr,inode_checksum,sb_checksum,compression "${DATA_PART}" || return $? ;; *) echo 'Filesystem '"${FS}"' is not yet supported!' return 1 ;; esac }