2022-07-16 17:18:03 +02:00
|
|
|
#
|
|
|
|
# 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
|
2023-03-21 14:11:10 +01:00
|
|
|
#
|
|
|
|
# lsblk --tree=PATH -o PATH,TYPE,PARTUUID
|
2022-07-16 17:18:03 +02:00
|
|
|
|
|
|
|
function get_uuid() {
|
2023-03-16 17:30:32 +01:00
|
|
|
# arg $1: Partition
|
|
|
|
# arg $2: Variable name to store UUID
|
2023-03-21 14:11:10 +01:00
|
|
|
validate_args 2 "$@" || return $?
|
|
|
|
local partition="${1}"
|
|
|
|
local -n uuid_ptr=$2
|
2022-07-16 17:18:03 +02:00
|
|
|
|
2023-03-16 17:30:32 +01:00
|
|
|
# shellcheck disable=SC2034
|
2023-03-21 14:11:10 +01:00
|
|
|
uuid_ptr="$(blkid -o value -s UUID "${partition}")" || return $?
|
2022-07-16 17:18:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function get_partitions(){
|
2023-03-21 14:11:10 +01:00
|
|
|
# arg $1: block device
|
|
|
|
# arg $2: name of variable to store partitions
|
|
|
|
validate_args 2 "$@" || return $?
|
|
|
|
local block_device="$1"
|
|
|
|
local -n partitions_ptr=$2
|
|
|
|
|
|
|
|
# Remove first line of output (which is just the block device itself)
|
|
|
|
# with sed: `sed 1d`
|
|
|
|
# shellcheck disable=SC2034
|
|
|
|
partitions_ptr="$(lsblk -pln -o name "${block_device}" | sed 1d)" || return $?
|
2022-07-16 17:18:03 +02:00
|
|
|
|
2023-03-21 14:11:10 +01:00
|
|
|
newline_separated_to_array partitions_ptr partitions_ptr || return $?
|
2022-07-16 17:18:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function get_block_devices() {
|
2023-03-21 14:11:10 +01:00
|
|
|
# arg $1: name of variable to store block devices
|
|
|
|
validate_args 1 "$@" || return $?
|
|
|
|
local -n block_devices_ptr=$1
|
2022-07-16 17:18:03 +02:00
|
|
|
|
|
|
|
# Get list of devices, one per line
|
2023-03-21 14:11:10 +01:00
|
|
|
# shellcheck disable=SC2034
|
|
|
|
block_devices_ptr="$(lsblk -dplnx size -o name | grep -Ev 'boot|rpmb|loop' | tac)" || return $?
|
2022-07-16 17:18:03 +02:00
|
|
|
|
2023-03-21 14:11:10 +01:00
|
|
|
newline_separated_to_array block_devices_ptr block_devices_ptr || return $?
|
2022-07-16 17:18:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function get_block_devices_with_size() {
|
2023-03-21 14:11:10 +01:00
|
|
|
# Example: variable with name $1 has content ('/dev/nvme0n1' '1,9T')
|
|
|
|
#
|
|
|
|
# arg $1: name of variable to store block device paths and their sizes
|
|
|
|
validate_args 1 "$@" || return $?
|
|
|
|
local -n block_device_sizes_ptr=$1
|
2022-07-16 17:18:03 +02:00
|
|
|
|
2023-03-16 17:30:32 +01:00
|
|
|
# Get list of devices and their sizes, one pair per line.
|
2022-07-16 17:18:03 +02:00
|
|
|
# Use sed to remove multiple white spaces: sed 's|\s\s*| |'
|
2023-03-21 14:11:10 +01:00
|
|
|
# shellcheck disable=SC2034
|
|
|
|
block_device_sizes_ptr="$(lsblk -dplnx size -o name,size | grep -Ev 'boot|rpmb|loop' | sed 's|\s\s*| |' | tac)" || return $?
|
2022-07-16 17:18:03 +02:00
|
|
|
|
2023-03-21 14:11:10 +01:00
|
|
|
newline_to_space block_device_sizes_ptr || return $?
|
|
|
|
space_separated_to_array block_device_sizes_ptr block_device_sizes_ptr || return $?
|
2022-07-16 17:18:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function partition() {
|
|
|
|
# Creates two partitions:
|
2023-03-21 14:11:10 +01:00
|
|
|
# - boot partition, by default 260MiB
|
|
|
|
# - luks partition, rest of the device for (encrypted) data
|
2022-07-16 17:18:03 +02:00
|
|
|
#
|
2023-03-21 14:11:10 +01:00
|
|
|
# arg $1: target block device
|
|
|
|
# arg $2: boot firmware: 'uefi' | 'bios'
|
|
|
|
# arg $3: boot partition size in MiB: >=260 | 'none'
|
|
|
|
# arg $4: name of variable to store boot partition
|
|
|
|
# arg $5: name of variable to store luks partition
|
|
|
|
validate_args 5 "$@" || return $?
|
|
|
|
local target_block_device="${1}"
|
|
|
|
local boot_firmware="${2}"
|
|
|
|
local boot_part_size="${3}"
|
|
|
|
local -n boot_part=$4
|
|
|
|
local -n luks_part=$5
|
|
|
|
|
|
|
|
local minimum=260
|
|
|
|
# Check if too small
|
|
|
|
if [ "${boot_part_size}" -lt "${minimum}" ]; then
|
|
|
|
printf '%s\n' "boot_part_size should be >= ${minimum}"
|
|
|
|
return 1
|
2022-07-16 17:18:03 +02:00
|
|
|
fi
|
|
|
|
|
|
|
|
# As our data partition is encrypted,
|
|
|
|
# we need a separate boot partition!
|
2023-03-21 14:11:10 +01:00
|
|
|
case "${boot_firmware}" in
|
2022-07-16 17:18:03 +02:00
|
|
|
uefi)
|
|
|
|
# EFI boot partition
|
|
|
|
#
|
|
|
|
# Create a partition with fat32 as the file system type and set the
|
|
|
|
# esp flag on it.
|
2023-03-21 14:11:10 +01:00
|
|
|
sudo parted --script "${target_block_device}" -- mklabel gpt \
|
|
|
|
mkpart ESP fat32 2Mib "${boot_part_size}MiB" \
|
2022-07-16 17:18:03 +02:00
|
|
|
set 1 esp on \
|
2023-03-21 14:11:10 +01:00
|
|
|
mkpart primary "${boot_part_size}MiB" 100% || return $?
|
2022-07-16 17:18:03 +02:00
|
|
|
|
2023-03-21 14:11:10 +01:00
|
|
|
get_partitions "${target_block_device}" PARTITIONS || return $?
|
|
|
|
boot_part="${PARTITIONS[0]}"
|
|
|
|
luks_part="${PARTITIONS[1]}"
|
2022-07-16 17:18:03 +02:00
|
|
|
;;
|
|
|
|
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
|
2023-03-21 14:11:10 +01:00
|
|
|
sudo parted --script "${target_block_device}" -- mklabel gpt \
|
2022-07-16 17:18:03 +02:00
|
|
|
mkpart primary 1MiB 2MiB \
|
|
|
|
set 1 bios_grub on \
|
2023-03-21 14:11:10 +01:00
|
|
|
mkpart primary 2MiB "${boot_part_size}MiB" \
|
|
|
|
mkpart primary "${boot_part_size}MiB" 100% || return $?
|
2022-07-16 17:18:03 +02:00
|
|
|
|
2023-03-21 14:11:10 +01:00
|
|
|
get_partitions "${target_block_device}" PARTITIONS || return $?
|
|
|
|
boot_part="${PARTITIONS[2]}"
|
|
|
|
luks_part="${PARTITIONS[3]}"
|
2022-07-16 17:18:03 +02:00
|
|
|
;;
|
|
|
|
*)
|
2023-03-21 14:11:10 +01:00
|
|
|
printf '%s\n' "Expected uefi or bios but got ${boot_firmware} instead!"
|
2022-07-16 17:18:03 +02:00
|
|
|
return 1
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
|
2023-03-21 14:11:10 +01:00
|
|
|
printf '%s\n' "boot partition: ${boot_part}"
|
|
|
|
printf '%s\n' "luks partition: ${luks_part}"
|
2022-07-16 17:18:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function format() {
|
2023-03-21 14:11:10 +01:00
|
|
|
# Formats the `boot` and `luks` partitions.
|
|
|
|
#
|
|
|
|
# If FDE is enabled ('true'),
|
|
|
|
# then $2 will be encrypted with password $3 and opened at $7.
|
|
|
|
#
|
|
|
|
# If FDE is disabled,
|
|
|
|
# then $7 is identical with $2.
|
|
|
|
#
|
|
|
|
# arg $1: boot partition
|
|
|
|
# arg $2: (encrypted) luks partition
|
|
|
|
# arg $3: password of luks partition
|
|
|
|
# arg $4: full-disk-encryption (FDE): 'true' | 'false'
|
|
|
|
# arg $5: filesystem: 'BTRFS' | 'EXT4' | 'F2FS'
|
|
|
|
# arg $6: name of variable to store partition of encrypted luks partition (if FDE='true').
|
|
|
|
# Set to /dev/mapper/$(basename $LUKS_PART)
|
|
|
|
# arg $7: name of variable to store data partition
|
2022-07-16 17:18:03 +02:00
|
|
|
#
|
|
|
|
# @post
|
|
|
|
# boot partition formatted
|
2023-03-21 14:11:10 +01:00
|
|
|
# luks partition formatted and accessible under $7
|
|
|
|
validate_args 7 "$@" || return $?
|
|
|
|
local boot_part="${1}"
|
|
|
|
local luks_part="${2}"
|
|
|
|
local luks_pwd="${3}"
|
|
|
|
local fde="${4}"
|
|
|
|
local fs="${5}"
|
|
|
|
# shellcheck disable=SC2034
|
|
|
|
local -n luks_part_uuid=$6
|
|
|
|
local -n data_part=$7
|
2022-07-16 17:18:03 +02:00
|
|
|
|
2023-03-21 14:11:10 +01:00
|
|
|
printf '%s\n' 'Wiping old signatures from partitions ...'
|
|
|
|
sudo wipefs --all "${boot_part}" || return $?
|
|
|
|
sudo wipefs --all "${luks_part}" || return $?
|
2022-07-16 17:18:03 +02:00
|
|
|
|
2023-03-21 14:11:10 +01:00
|
|
|
printf '%s\n' "Formatting boot partition ${boot_part} ..."
|
|
|
|
sudo mkfs.fat -F32 "${boot_part}" || return $?
|
2022-07-16 17:18:03 +02:00
|
|
|
|
2023-03-21 14:11:10 +01:00
|
|
|
case "${fde}" in
|
2022-07-16 17:18:03 +02:00
|
|
|
true)
|
2023-03-21 14:11:10 +01:00
|
|
|
# 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.
|
|
|
|
printf '%s\n' "Creating encrypted luks partition ${luks_part} ..."
|
|
|
|
printf '%s' "${luks_pwd}" | sudo cryptsetup luksFormat \
|
2022-07-16 17:18:03 +02:00
|
|
|
--cipher aes-xts-plain64 --key-size 512 --hash sha512 \
|
2023-03-21 14:11:10 +01:00
|
|
|
--iter-time 10000 --use-random "${luks_part}" || return $?
|
2022-07-16 17:18:03 +02:00
|
|
|
|
2023-03-21 14:11:10 +01:00
|
|
|
get_uuid "${luks_part}" luks_part_uuid || return $?
|
2022-07-16 17:18:03 +02:00
|
|
|
|
|
|
|
local luks_name
|
2023-03-21 14:11:10 +01:00
|
|
|
luks_name="$(basename "${luks_part}")"
|
|
|
|
data_part="/dev/mapper/${luks_name}"
|
2022-07-16 17:18:03 +02:00
|
|
|
|
2023-03-16 17:30:32 +01:00
|
|
|
# Open luks partition
|
2023-03-21 14:11:10 +01:00
|
|
|
printf '%s' "${luks_pwd}" | sudo cryptsetup luksOpen "${luks_part}" "${luks_name}" || return $?
|
2022-07-16 17:18:03 +02:00
|
|
|
;;
|
|
|
|
false)
|
2023-03-21 14:11:10 +01:00
|
|
|
data_part="${luks_part}"
|
2022-07-16 17:18:03 +02:00
|
|
|
;;
|
|
|
|
*)
|
2023-03-21 14:11:10 +01:00
|
|
|
printf '%s\n' "Invalid option: ${fde}"
|
2022-07-16 17:18:03 +02:00
|
|
|
return 1
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
|
2023-03-21 14:11:10 +01:00
|
|
|
printf '%s\n' "Formatting the data partition ${data_part} ..."
|
|
|
|
case "${fs}" in
|
2022-07-16 17:18:03 +02:00
|
|
|
BTRFS)
|
2023-03-21 14:11:10 +01:00
|
|
|
sudo mkfs.btrfs "${data_part}" || return $?
|
2022-07-16 17:18:03 +02:00
|
|
|
;;
|
|
|
|
EXT4)
|
2023-03-21 14:11:10 +01:00
|
|
|
# https://wiki.archlinux.org/index.php/Ext4
|
|
|
|
# If the CPU supports SSE 4.2, make sure the crc32c_intel kernel module is loaded
|
|
|
|
sudo mkfs.ext4 -O metadata_csum "${data_part}" || return $?
|
2022-07-16 17:18:03 +02:00
|
|
|
;;
|
|
|
|
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)
|
2023-03-21 14:11:10 +01:00
|
|
|
sudo mkfs.f2fs -O extra_attr,inode_checksum,sb_checksum,compression "${data_part}" || return $?
|
2022-07-16 17:18:03 +02:00
|
|
|
;;
|
|
|
|
*)
|
2023-03-21 14:11:10 +01:00
|
|
|
printf '%s\n' "Filesystem ${fs} is not yet supported!"
|
2022-07-16 17:18:03 +02:00
|
|
|
return 1
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
}
|