12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346 |
- #!/bin/bash
- PATH="$PATH:/usr/sbin:/sbin"
- RED="\e[31;1m" GREEN="\e[32;1m" YELLOW="\e[33;1m" BLUE="\e[34;1m" PURPLE="\e[35;1m" RESET="\e[0m"
- PROGNAME=$(basename $0)
- TITLE='Armbian Encrypted Root Filesystem Setup'
- CONFIG_VARS='
- ARMBIAN_IMAGE
- BOOTPART_LABEL
- ROOTFS_NAME
- DISK_PASSWD
- UNLOCKING_USERHOST
- SERIAL_CONSOLE
- IP_ADDRESS
- NETMASK
- ADD_ALL_MODS
- ADD_MODS
- USE_LOCAL_AUTHORIZED_KEYS
- USB_GADGET
- '
- STATES='
- card_partitioned
- bootpart_copied
- bootpart_label_created
- rootpart_copied
- target_configured
- '
- USER_OPTS_INFO="
- NO_CLEANUP - no cleanup of mounts after program run
- FORCE_REBUILD - force full rebuild
- FORCE_RECONFIGURE - force reconfiguration
- FORCE_REFORMAT_ROOT - force reformat of encrypted root partition
- ADD_ALL_MODS - add all currently loaded modules to initramfs
- ADD_MODS y add specified modules to initramfs
- USE_LOCAL_AUTHORIZED_KEYS - use local 'authorized_keys' file
- PARTITION_ONLY - partition and create filesystems only
- ERASE - zero boot sector, boot partition and beginning of root partition
- ROOTENC_REUSE_FS - reuse existing filesystems (for development only)
- ROOTENC_TESTING - developer tweaks
- ROOTENC_PAUSE - pause along the way
- ROOTENC_IGNORE_APT_ERRORS - continue even if apt update fails
- SERIAL_CONSOLE - enable disk unlocking via serial console
- USB_GADGET - enable disk unlocking via SSH over USB (g_ether)
- VERBOSE - produce verbose output
- "
- RSYNC_VERBOSITY='--info=progress2'
- print_help() {
- echo " ${PROGNAME^^}: Create an Armbian image with encrypted root filesystem
- USAGE: $PROGNAME [options] <SD card device name>
- OPTIONS: '-h' Print this help message
- '-C' Don't perform unmounts or clean up build directory at exit
- '-d' Produce tons of debugging output
- '-f' Force reconfiguration of target system
- '-F' Force a complete rebuild of target system
- '-m' Add all currently loaded modules to the initramfs (may help
- fix blank screen on bootup issues)
- '-o' Add specified modules to the initramfs (comma-separated list)
- '-M' Mount source and target systems and exit
- '-U' Unmount source and target systems and exit
- '-p' Partition and create filesystems only. Do not copy data
- '-R' Force reformat of encrypted root partition
- '-s' Use 'authorized_keys' file from working directory, if available
- (see below)
- '-v' Be more verbose
- '-u' Perform an 'apt upgrade' after each 'apt update'
- '-z' Erase boot sector and first partition of SD card before partitioning
- (an extra paranoia step, but it can’t hurt)
- For non-interactive operation, set the following variables in your environment
- or on the command line:
- ROOTFS_NAME - device mapper name of target root filesystem
- IP_ADDRESS - IP address of target (set to 'dhcp' for dynamic IP
- or 'none' to disable remote SSH unlocking support)
- BOOTPART_LABEL - Boot partition label of target
- DISK_PASSWD - Disk password of target root filesystem
- UNLOCKING_USERHOST - USER@HOST of remote unlocking host
- SERIAL_CONSOLE - Set this to 'y' to enable disk unlocking from the
- serial console
- INSTRUCTIONS FOR USE
- This script must be invoked as superuser on a running Armbian system.
- Packages will be installed using APT, so the system must be Internet-
- connected and its clock correctly set.
- If remote unlocking via SSH is desired, the unlocking host must be reachable.
- Alternatively, SSH public keys for the unlocking host or hosts may be
- provided in the file 'authorized_keys' in the current directory. This file
- has the same format as a standard SSH 'authorized_keys' file.
- Architecture of host and target (e.g. 64-bit or 32-bit ARM) must be the same.
- For best results, the host and target hardware should also be identical or
- similar. Building on a host with more memory than the target, for example,
- may lead to disk unlocking failure on the target. For most users, who’ll be
- building for the currently-running board, this point is a non-issue.
- 1. Place an Armbian boot image file for the target system in the current
- directory. For best results, the image file should match the Debian
- or Ubuntu release of the host system.
- 2. Insert a USB card reader with a blank micro-SD card for the target
- system into the host’s USB port.
- 3. Determine the SD card’s device name using 'dmesg' or 'lsblk'.
- 4. Invoke the script with the device name as argument. If any options
- are desired, they must precede the device name.
- If the board has an eMMC, it may be used as the target device instead of
- an SD card." | less
- }
- pause() {
- echo -ne $GREEN'(Press any key to continue)'$RESET >&$stderr_dup
- read
- no_fmsg=1
- }
- _debug_pause() { [ "$ROOTENC_PAUSE" ] && pause; true; }
- imsg() { echo -e "$1" >&$stdout_dup; no_fmsg=1; }
- imsg_nonl() { echo -ne "$1" >&$stdout_dup; no_fmsg=1; }
- tmsg() {
- no_fmsg=1
- [ "$ROOTENC_TESTING" ] || return 0
- echo -e "$1" >&$stdout_dup
- }
- warn() { echo -e "$YELLOW$1$RESET" >&$stdout_dup; no_fmsg=1; }
- warn_nonl() { echo -ne "$YELLOW$1$RESET" >&$stdout_dup; no_fmsg=1; }
- rmsg() { echo -e "$RED$1$RESET" >&$stdout_dup; no_fmsg=1; }
- gmsg() { echo -e "$GREEN$1$RESET" >&$stdout_dup; no_fmsg=1; }
- pu_msg() { echo -e "$PURPLE$1$RESET" >&$stdout_dup; no_fmsg=1; }
- do_partprobe() {
- if [ "$VERBOSE" ]; then partprobe; else partprobe 2>/dev/null; fi
- no_fmsg=1
- }
- _show_output() { [ "$VERBOSE" ] || exec 1>&$stdout_dup 2>&$stderr_dup; }
- _hide_output() { [ "$VERBOSE" ] || exec &>'/dev/null'; }
- bail() { exit; }
- die() {
- echo -e "$RED$1$RESET" >&$stdout_dup
- no_fmsg=1
- exit 1
- }
- _return_handler() {
- local funcname=${FUNCNAME[1]} exitval=$? res
- if [ "${funcname:0:1}" == '_' -o "$no_fmsg" ]; then
- no_fmsg=
- return 0
- fi
- if [ "$exitval" -eq 0 ]; then res='OK'; else res="False ($exitval)"; fi
- printf "$BLUE%-32s $res$RESET\n" "$funcname" >&$stdout_dup
- }
- _sigint_handler() {
- warn "\nExiting at user request"
- exit 1
- }
- _error_handler() {
- local exitval=$?
- warn "$(basename ${BASH_SOURCE[1]}):${BASH_LINENO[0]}: ${FUNCNAME[1]}() failed at command '$BASH_COMMAND'"
- rmsg "$SCRIPT_DESC exiting with error ($exitval)"
- }
- _do_header() {
- echo
- local reply
- if banner=$(toilet --filter border --filter gay --width 51 -s -f smbraille "$TITLE" 2>/dev/null); then
- while read reply; do
- echo -e " $reply"
- done <<-EOF
- $banner
- EOF
- else
- echo -n ' '
- echo $TITLE
- echo
- fi
- echo " For detailed usage information,"
- echo " invoke with the '-h' switch"
- echo
- }
- _warn_user_opts() {
- local out opt have_optarg text
- while read opt have_optarg text; do
- [ "$opt" ] || continue
- if [ "${!opt}" ]; then
- if [ $have_optarg == 'y' ]; then
- out+=" + $text (${!opt})\n"
- else
- out+=" + $text\n"
- fi
- fi
- done <<<$USER_OPTS_INFO
- if [ "$out" ]; then
- warn "\n The following user options are in effect:"
- warn_nonl "${out}"
- fi
- }
- _set_host_vars() {
- BUILD_DIR='armbian_rootenc_build'
- SRC_ROOT="$BUILD_DIR/src"
- BOOT_ROOT="$BUILD_DIR/boot"
- TARGET_ROOT="$BUILD_DIR/target"
- CONFIG_VARS_FILE="$BOOT_ROOT/.rootenc_config_vars"
- host_distro=$(lsb_release --short --codename)
- host_kernel=$(ls '/boot' | egrep '^vmlinu[xz]') # allow 'vmlinux' or 'vmlinuz'
- }
- check_sdcard_name_and_params() {
- local dev chk
- dev=$1
- [ "$dev" ] || die "You must supply a device name"
- [ "${dev:0:5}" == '/dev/' ] || dev="/dev/$dev"
- [ -e "$dev" ] || die "$dev does not exist"
- chk="$(lsblk --noheadings --nodeps --list --output=TYPE $dev 2>/dev/null)"
- [ "$chk" != 'disk' -a "$chk" != 'loop' ] && {
- [ "$chk" == 'part' ] && die "$dev is a partition, not a block device!"
- die "$dev is not a block device!"
- }
- local pttype size nodos oversize removable non_removable part_sep
- pttype=$(blkid --output=udev $dev | grep TYPE | cut -d '=' -f2)
- size="$(lsblk --noheadings --nodeps --list --output=SIZE --bytes $dev 2>/dev/null)"
- removable="$(lsblk --noheadings --nodeps --list --output=RM $dev 2>/dev/null)"
- nodos=$([ "$pttype" -a "$pttype" != 'dos' ] && echo "Partition type is ${pttype^^}") || true
- oversize=$([ $size -gt 137438953472 ] && echo 'Size is > 128GiB') || true
- non_removable=$([ $removable -ne 0 ] || echo 'Device is non-removable')
- SD_INFO="$(lsblk --noheadings --nodeps --list --output=VENDOR,MODEL,SIZE $dev 2>/dev/null)"
- SD_INFO=${SD_INFO// / }
- if [ "$nodos" -o "$oversize" -o "$non_removable" ]; then
- warn " $dev ($SD_INFO) doesn’t appear to be an SD card"
- warn " for the following reasons:"
- if [ "$non_removable" ]; then warn " $non_removable"; fi
- if [ "$nodos" ]; then warn " $nodos"; fi
- if [ "$oversize" ]; then warn " $oversize"; fi
- _user_confirm ' Are you sure this is the correct device of your blank SD card?' 'no'
- fi
- SDCARD_DEVNAME=${dev:5}
- [ "${SDCARD_DEVNAME%[0-9]}" == $SDCARD_DEVNAME ] || part_sep='p'
- BOOT_DEVNAME=$SDCARD_DEVNAME${part_sep}1
- ROOT_DEVNAME=$SDCARD_DEVNAME${part_sep}2
- [ "$SDCARD_DEVNAME" ] || die 'You must supply a device name for the SD card!'
- pu_msg "Will write to target $dev ($SD_INFO)"
- }
- _get_user_var() {
- local var desc dfl prompt pat pat_errmsg vtest cprompt seen_prompt reply redo
- var=$1 desc=$2 dfl=$3 prompt=$4 pat=$5 pat_errmsg=$6 vtest=$7
- [ "$MOUNT_TARGET_ONLY" ] && [[ ! $var =~ ^(DISK_PASSWD|ROOTFS_NAME)$ ]] && {
- eval "$var=$dfl"
- return 0
- }
- if [ "$pat" == 'bool' ]; then READOPTS='-n1' READNL="\n"; else READOPTS='' READNL=''; fi
- while true; do
- if [ -z "${!var}" -o "$seen_prompt" -o "$redo" ]; then
- if [ "$seen_prompt" ]; then
- echo -n " Enter $desc: "
- else
- cprompt=
- while read reply; do
- cprompt+=" ${reply## }\n"
- done <<-EOF
- $prompt
- EOF
- echo
- if [ "$dfl" ]; then
- printf "${cprompt:0:-2} " "$dfl"
- else
- echo -ne "${cprompt:0:-2} "
- fi
- seen_prompt=1
- fi
- eval "read $READOPTS $var"; echo -ne "$READNL"
- fi
- redo=1
- if [ -z "${!var}" -a "$dfl" ]; then eval "$var=$dfl"; fi
- [ "${!var}" ] || {
- rmsg " $desc must not be empty"
- continue
- }
- if [ "$pat" ]; then
- local rpat=$pat
- if [ "$pat" == 'bool' ]; then
- rpat='^[ynYN]*$'
- pat_errmsg="You must type 'y' or 'n'"
- fi
- echo "${!var}" | egrep -qi "$rpat" || {
- rmsg " ${!var}: $pat_errmsg"
- continue
- }
- if [ "$pat" == 'bool' ]; then
- if [[ ${!var} =~ ^[Yy]$ ]]; then eval "$var=yes"; else eval "$var="; fi
- fi
- fi
- if [ "$vtest" ]; then
- $vtest || continue
- fi
- break
- done
- }
- _get_user_vars() {
- local dq='[0-9]{1,3}'
- _get_user_var 'IP_ADDRESS' 'IP address' '' \
- "Enter the IP address of the target machine.
- Enter 'dhcp' for a dynamic IP or 'none' for no remote SSH unlocking support
- IP address:" \
- "^(dhcp|none|$dq\.$dq\.$dq\.$dq)$" \
- 'malformed IP address'
- IP_ADDRESS=${IP_ADDRESS,,}
- [[ $IP_ADDRESS =~ ^(dhcp|none)$ ]] || {
- _get_user_var 'NETMASK' 'netmask' '255.255.255.0' \
- "Enter the netmask of the target machine,
- or hit ENTER for the default (%s): " \
- "^($dq\.$dq\.$dq\.$dq)$" \
- 'malformed netmask'
- }
- _get_user_var 'BOOTPART_LABEL' 'boot partition label' 'ARMBIAN_BOOT' \
- "Enter a boot partition label for the target machine,
- or hit ENTER for the default (%s): " \
- '^[A-Za-z0-9_]{1,16}$' \
- "Label must contain no more than 16 characters in the set 'A-Za-z0-9_'"
- _get_user_var 'ROOTFS_NAME' 'root filesystem device name' 'rootfs' \
- "Enter a device name for the encrypted root filesystem,
- or hit ENTER for the default (%s):" \
- '^[a-z0-9_]{1,48}$' \
- "Name must contain no more than 48 characters in the set 'a-z0-9_'" \
- '_test_rootfs_mounted'
- if [ "$MOUNT_TARGET_ONLY" ]; then
- local pw_prompt="Enter disk password:"
- else
- local pw_prompt="Choose a simple disk password for the installation process.
- Once your encrypted system is up and running, you can change
- the password using the 'cryptsetup' command.
- Enter password:"
- fi
- _get_user_var 'DISK_PASSWD' 'disk password' '' "$pw_prompt" \
- '^[A-Za-z0-9_ ]{1,10}$' \
- "Temporary disk password must contain no more than 10 characters in the set 'A-Za-z0-9_ '"
- if [ "$IP_ADDRESS" == 'none' ]; then
- UNLOCKING_USERHOST=
- elif [ -e 'authorized_keys' -a "$USE_LOCAL_AUTHORIZED_KEYS" ]; then
- UNLOCKING_USERHOST=
- else
- _get_user_var 'UNLOCKING_USERHOST' 'USER@HOST' '' \
- "Enter the user@host of the machine you'll be unlocking from:" \
- '\S+@\S+' \
- 'malformed USER@HOST' \
- '_test_unlocking_host_available'
- fi
- _get_user_var 'SERIAL_CONSOLE' 'serial console unlocking' '' \
- "Unlock the disk from the serial console. WARNING: enabling this will
- make it impossible to unlock the disk using the keyboard and monitor,
- though unlocking via SSH will still work.
- Enable unlocking via serial console? (y/n):" \
- 'bool'
- _get_user_var 'USB_GADGET' 'disk unlocking via SSH over USB (g_ether)' '' \
- "Unlock the disk via SSH over USB (g_ether). Enable this only if your board
- supports USB gadget mode, i.e. if it has a USB OTG port. WARNING: enabling this
- will make it impossible to unlock the disk over the Ethernet interface (eth0).
- Enable unlocking via SSH over USB? (y/n):" \
- 'bool'
- true
- }
- _test_rootfs_mounted() {
- [ -e "/dev/mapper/$ROOTFS_NAME" ] && {
- local mnt=$(lsblk --list --noheadings --output=MOUNTPOINT /dev/mapper/$ROOTFS_NAME)
- [ "$mnt" ] && {
- rmsg " Device '$ROOTFS_NAME' is in use and mounted on $mnt"
- return 1
- }
- }
- return 0
- }
- _test_unlocking_host_available() {
- local ul_host=${UNLOCKING_USERHOST#*@}
- ping -c1 $ul_host &>/dev/null || {
- rmsg " Unable to ping host '$ul_host'"
- return 1
- }
- }
- _test_sdcard_mounted() {
- local chk="$(lsblk --noheadings --list --output=MOUNTPOINT /dev/$SDCARD_DEVNAME)"
- [ -z "$chk" ] || {
- lsblk --output=NAME,SIZE,TYPE,FSTYPE,MOUNTPOINT /dev/$SDCARD_DEVNAME
- die "Device /dev/$SDCARD_DEVNAME has mounted partitions!"
- }
- }
- get_authorized_keys() {
- [ -e 'authorized_keys' -a "$USE_LOCAL_AUTHORIZED_KEYS" ] || {
- rsync "$UNLOCKING_USERHOST:.ssh/id_*.pub" 'authorized_keys'
- }
- }
- _apt_update() {
- [ "$ROOTENC_IGNORE_APT_ERRORS" ] && set +e
- apt --yes update
- [ "$APT_UPGRADE" ] && apt --yes upgrade
- [ "$ROOTENC_IGNORE_APT_ERRORS" ] && set -e
- true
- }
- _print_pkgs_to_install() {
- local pkgs pkgs_ssh
- case $1 in
- 'host')
- case "$host_distro" in
- bionic|buster|focal|bullseye|jammy)
- pkgs='cryptsetup-bin ed' ;;
- *)
- pkgs='cryptsetup-bin ed'
- warn "Warning: unrecognized host distribution '$host_distro'" ;;
- esac ;;
- 'target')
- case "$target_distro" in
- buster|focal|bullseye|jammy)
- pkgs='cryptsetup-initramfs' pkgs_ssh='dropbear-initramfs' ;;
- bionic)
- pkgs='cryptsetup' pkgs_ssh='dropbear-initramfs' ;;
- *)
- pkgs='cryptsetup-initramfs' pkgs_ssh='dropbear-initramfs'
- warn "Warning: unrecognized target distribution '$target_distro'" ;;
- esac
- [ "$IP_ADDRESS" != 'none' ] && pkgs+=" $pkgs_ssh" ;;
- esac
- for i in $pkgs; do
- dpkg -l $i 2>/dev/null | grep -q ^ii || echo $i
- done
- }
- apt_install_host() {
- local pkgs=$(_print_pkgs_to_install 'host')
- [ "$pkgs" ] && {
- _apt_update
- apt --yes install $pkgs
- }
- true
- }
- create_build_dir() {
- mkdir -p $BUILD_DIR
- mkdir -p $SRC_ROOT
- mkdir -p $BOOT_ROOT
- mkdir -p $TARGET_ROOT
- }
- umount_target() {
- for i in $BOOT_ROOT $TARGET_ROOT; do
- while mountpoint -q $i; do
- umount -Rl $i
- done
- done
- }
- remove_build_dir() {
- [ -d $TARGET_ROOT ] && rmdir $TARGET_ROOT
- [ -d $BOOT_ROOT ] && rmdir $BOOT_ROOT
- [ -d $SRC_ROOT ] && rmdir $SRC_ROOT
- [ -d $BUILD_DIR ] && rmdir $BUILD_DIR
- true
- }
- _get_device_maps() {
- local dm_type=$1 varname="device_maps_$1" dm_name ls mp
- eval "$varname="
- while read dm_name; do
- [ "$dm_name" == 'No devices found' ] && break
- fstype="$(lsblk --noheadings --nodeps -o fstype "/dev/mapper/$dm_name")"
- [ "$fstype" == 'ext4' ] || continue
- ls=$(findmnt -n --source "/dev/mapper/$dm_name" | cut -f 1 -d ' ')
- if [ "$ls" -a "$dm_type" == 'mounted_on_target' ]; then
- while read mp; do
- if [ "${mp: -${#TARGET_ROOT}}" == "$TARGET_ROOT" ]; then
- eval "$varname+='$dm_name '"
- fi
- done <<<"$ls"
- elif [ -z "$ls" -a "$dm_type" == 'unmounted' ]; then
- eval "$varname+='$dm_name '"
- fi
- done <<<$(dmsetup ls | cut -f 1)
- tmsg "$varname=[${!varname}]"
- }
- _close_device_maps() {
- local dm_type=$1
- local varname="device_maps_${dm_type}"
- for i in ${!varname}; do
- tmsg "closing $i"
- cryptsetup status $i > '/dev/null' && cryptsetup luksClose $i
- done
- true
- }
- _preclean() {
- close_loopmount
- _get_device_maps 'unmounted'
- _close_device_maps 'unmounted'
- _get_device_maps 'mounted_on_target'
- umount_target
- _close_device_maps 'mounted_on_target'
- remove_build_dir
- }
- _clean() {
- pu_msg "Cleaning up, please wait..."
- _show_output
- close_loopmount
- _get_device_maps 'mounted_on_target'
- umount_target
- update_config_vars_file
- _close_device_maps 'mounted_on_target'
- [ -e 'authorized_keys' -a -z "$USE_LOCAL_AUTHORIZED_KEYS" ] && shred -u 'authorized_keys'
- remove_build_dir
- }
- get_armbian_image() {
- ARMBIAN_IMAGE="$(ls *.img)"
- [ "$ARMBIAN_IMAGE" ] || die 'You must place an Armbian image in the current directory!'
- local count=$(echo "$ARMBIAN_IMAGE" | wc -l)
- [ "$count" == 1 ] || die "More than one image file present!:\n$ARMBIAN_IMAGE"
- }
- _confirm_user_vars() {
- echo
- echo " Armbian image: $ARMBIAN_IMAGE"
- echo " Target device: /dev/$SDCARD_DEVNAME ($SD_INFO)"
- echo " Root filesystem device name: /dev/mapper/$ROOTFS_NAME"
- echo " Target IP address: $IP_ADDRESS"
- [ "$NETMASK" ] && echo " Target netmask: $NETMASK"
- echo " Boot partition label: $BOOTPART_LABEL"
- echo " Disk password: $DISK_PASSWD"
- [ "$UNLOCKING_USERHOST" ] && echo " user@host of unlocking host: $UNLOCKING_USERHOST"
- echo " Serial console unlocking: ${SERIAL_CONSOLE:-no}"
- echo " SSH over USB unlocking: ${USB_GADGET:-no}"
- echo
- _user_confirm ' Are these settings correct?' 'yes'
- }
- setup_loopmount() {
- LOOP_DEV=$(losetup -f)
- losetup -P $LOOP_DEV $ARMBIAN_IMAGE
- mount ${LOOP_DEV}p1 $SRC_ROOT
- START_SECTOR=$(fdisk -l $LOOP_DEV -o Start | tail -n1 | tr -d ' ') # usually 32768
- BOOT_SECTORS=409600 # 200MB
- }
- _umount_with_check() {
- mountpoint -q $1 && umount $1
- }
- update_config_vars_file() {
- mount "/dev/$BOOT_DEVNAME" $BOOT_ROOT
- _print_config_vars $CONFIG_VARS_FILE
- umount $BOOT_ROOT
- }
- _print_states() {
- for i in $STATES; do
- echo $i: ${!i}
- done
- }
- _update_state_from_config_vars() {
- [ -e $CONFIG_VARS_FILE ] || return 0
- local reply
- while read reply; do
- eval "c$reply"
- done <<<$(cat $CONFIG_VARS_FILE)
- local saved_states cfgvar_changed
- saved_states="$(_print_states)"
- cfgvar_changed=
- [ $cARMBIAN_IMAGE != $ARMBIAN_IMAGE ] && cfgvar_changed+=' ARMBIAN_IMAGE' card_partitioned='n'
- [ $cBOOTPART_LABEL != $BOOTPART_LABEL ] && cfgvar_changed+=' BOOTPART_LABEL' bootpart_label_created='n'
- [ $cROOTFS_NAME != $ROOTFS_NAME ] && cfgvar_changed+=' ROOTFS_NAME' target_configured='n'
- [ $cDISK_PASSWD != $DISK_PASSWD ] && cfgvar_changed+=' DISK_PASSWD' rootpart_copied='n'
- [ "$UNLOCKING_USERHOST" -a "$cUNLOCKING_USERHOST" != "$UNLOCKING_USERHOST" ] && {
- cfgvar_changed+=' UNLOCKING_USERHOST' target_configured='n'
- }
- [ "$cSERIAL_CONSOLE" != "$SERIAL_CONSOLE" ] && {
- cfgvar_changed+=' SERIAL_CONSOLE' target_configured='n'
- }
- [ $cIP_ADDRESS != $IP_ADDRESS ] && cfgvar_changed+=' IP_ADDRESS' target_configured='n'
- [ "$cNETMASK" != "$NETMASK" ] && cfgvar_changed+=' NETMASK' target_configured='n'
- [ "$cADD_ALL_MODS" != "$ADD_ALL_MODS" ] && cfgvar_changed+=' ADD_ALL_MODS' target_configured='n'
- [ "$cADD_MODS" != "$ADD_MODS" ] && cfgvar_changed+=' ADD_MODS' target_configured='n'
- [ "$cUSB_GADGET" != "$USB_GADGET" ] && cfgvar_changed+=' USB_GADGET' target_configured='n'
- [ "$IP_ADDRESS" -a "$cUSE_LOCAL_AUTHORIZED_KEYS" != "$USE_LOCAL_AUTHORIZED_KEYS" ] && {
- cfgvar_changed+=' USE_LOCAL_AUTHORIZED_KEYS' target_configured='n'
- }
- [ $card_partitioned == 'n' ] && {
- bootpart_copied='n'
- bootpart_label_created='n'
- rootpart_copied='n'
- target_configured='n'
- }
- [ $bootpart_copied == 'n' ] && bootpart_label_created='n'
- [ $rootpart_copied == 'n' ] && target_configured='n'
- [ "$saved_states" != "$(_print_states)" ] && {
- warn "Install state altered due to changed config vars:$cfgvar_changed"
- for i in $STATES; do
- if [ "${!i}" == 'n' ]; then
- imsg " $i: ${RED}no$RESET"
- else
- imsg " $i: ${GREEN}yes$RESET"
- fi
- done
- _delete_state_files
- }
- true
- }
- _add_state_file() {
- local state=$1 cmd=$2
- if [ "$cmd" == 'target' ]; then
- touch "$TARGET_ROOT/boot/.rootenc_install_state/$state"
- else
- [ "$cmd" == 'mount' ] && mount "/dev/$BOOT_DEVNAME" $BOOT_ROOT
- mkdir -p "$BOOT_ROOT/.rootenc_install_state"
- touch "$BOOT_ROOT/.rootenc_install_state/$state"
- [ "$cmd" == 'mount' ] && umount $BOOT_ROOT
- fi
- eval "$state='y'"
- tmsg "added state file '$state'"
- }
- _delete_state_files() {
- for i in $STATES; do
- local fn="$BOOT_ROOT/.rootenc_install_state/$i"
- [ ${!i} == 'n' -a -e $fn ] && /bin/rm $fn
- done
- true
- }
- _get_state_from_state_files() {
- for i in $STATES; do
- if [ -e "$BOOT_ROOT/.rootenc_install_state/$i" ]; then
- eval "$i=y"
- else
- eval "$i=n"
- fi
- done
- }
- _print_state_from_state_files() {
- imsg 'Install state:'
- for i in $STATES; do
- if [ -e "$BOOT_ROOT/.rootenc_install_state/$i" ]; then
- imsg " $i: ${GREEN}yes$RESET"
- else
- imsg " $i: ${RED}no$RESET"
- fi
- done
- }
- check_install_state() {
- for i in $STATES; do eval "$i=n"; done
- if [ "$FORCE_REBUILD" ]; then
- return
- else
- do_partprobe
- lsblk --noheadings --list /dev/$SDCARD_DEVNAME -o 'NAME' | grep -q $BOOT_DEVNAME || return 0
- lsblk --noheadings --list /dev/$BOOT_DEVNAME -o 'FSTYPE' | grep -q 'ext4' || return 0
- mount "/dev/$BOOT_DEVNAME" $BOOT_ROOT
- _get_state_from_state_files
- if [ "$target_configured" == 'y' -a "$FORCE_RECONFIGURE" ]; then
- target_configured='n'
- _delete_state_files
- fi
- _print_state_from_state_files
- _update_state_from_config_vars
- _umount_with_check $BOOT_ROOT
- fi
- }
- close_loopmount() {
- while mountpoint -q $SRC_ROOT; do
- umount $SRC_ROOT
- done
- for i in $(losetup --noheadings --raw --list -j $ARMBIAN_IMAGE | awk '{print $1}'); do
- losetup -d $i
- done
- }
- _user_confirm() {
- local prompt1 prompt2 dfl_action reply
- prompt1=$1 dfl_action=$2
- if [ "$dfl_action" == 'yes' ]; then
- prompt2='(Y/n)'
- else
- prompt2='(y/N)'
- fi
- imsg_nonl "$prompt1 $prompt2 "
- read -n1 reply
- [ "$reply" ] && imsg ''
- [ "$dfl_action" == 'yes' -a -z "$reply" ] && return
- [ "$reply" == 'y' -o "$reply" == 'Y' ] && return
- warn "Exiting at user request"
- exit 1
- }
- erase_boot_sector_and_first_partition() {
- local sectors count
- sectors=$((START_SECTOR+BOOT_SECTORS+100))
- count=$(((sectors/8192)+1))
- pu_msg "Erasing up to beginning of second partition ($sectors sectors, ${count}M):"
- _show_output
- dd if=/dev/zero \
- of=/dev/$SDCARD_DEVNAME \
- status=progress \
- bs=$((512*8192)) \
- count=$count
- _hide_output
- }
- create_partition_label() {
- pu_msg "Creating new partition label on /dev/$SDCARD_DEVNAME"
- local fdisk_cmds="o\nw\n"
- set +e
- echo -e "$fdisk_cmds" | fdisk "/dev/$SDCARD_DEVNAME"
- set -e
- do_partprobe
- }
- copy_boot_loader() {
- local count
- count=$((START_SECTOR/2048))
- pu_msg "Copying boot loader ($START_SECTOR sectors, ${count}M):"
- _show_output
- dd if=$ARMBIAN_IMAGE \
- of=/dev/$SDCARD_DEVNAME \
- status=progress \
- bs=$((512*2048)) \
- count=$count
- _hide_output
- do_partprobe
- }
- _print_config_vars() {
- local outfile=$1
- local data="$(for i in $CONFIG_VARS; do echo "$i='${!i}'"; done)"
- if [ "$outfile" ]; then echo "$data" > $outfile; else echo "$data"; fi
- }
- partition_sd_card() {
- local p1_end p2_start fdisk_cmds bname rname fstype
- p1_end=$((START_SECTOR+BOOT_SECTORS-1))
- p2_start=$((p1_end+1))
- fdisk_cmds="o\nn\np\n1\n$START_SECTOR\n$p1_end\nn\np\n2\n$p2_start\n\nw\n"
- set +e; trap - ERR # fdisk exits with error if partition table cannot be re-read
- echo -e "$fdisk_cmds" | fdisk "/dev/$SDCARD_DEVNAME"
- set -e; trap '_error_handler' ERR
- do_partprobe
- bname="$(lsblk --noheadings --list --output=NAME /dev/$BOOT_DEVNAME)"
- [ "$bname" == $BOOT_DEVNAME ] || die 'Partitioning failed!'
- rname="$(lsblk --noheadings --list --output=NAME /dev/$ROOT_DEVNAME)"
- [ "$rname" == $ROOT_DEVNAME ] || die 'Partitioning failed!'
- # filesystem is required by call to _add_state_file(), so we must create it here
- fstype=$(lsblk --noheadings --list --output=FSTYPE "/dev/$BOOT_DEVNAME")
- [ "$fstype" == 'ext4' -a "$ROOTENC_REUSE_FS" ] || mkfs.ext4 -F "/dev/$BOOT_DEVNAME"
- do_partprobe
- _add_state_file 'card_partitioned' 'mount'
- }
- _do_partition() {
- imsg "All data on /dev/$SDCARD_DEVNAME ($SD_INFO) will be destroyed!!!"
- _user_confirm 'Are you sure you want to continue?' 'no'
- if [ "$ERASE" ]; then
- erase_boot_sector_and_first_partition
- else
- create_partition_label
- fi
- copy_boot_loader
- partition_sd_card
- }
- copy_system_boot() {
- [ "$PARTITION_ONLY" ] && {
- _add_state_file 'bootpart_copied' 'mount'
- return
- }
- mount "/dev/$BOOT_DEVNAME" $BOOT_ROOT
- pu_msg "Copying files to boot partition:"
- _show_output
- rsync $RSYNC_VERBOSITY --archive $SRC_ROOT/boot/* $BOOT_ROOT
- _hide_output
- [ -e "$BOOT_ROOT/boot" ] || (cd $BOOT_ROOT && ln -s . 'boot')
- _add_state_file 'bootpart_copied'
- umount $BOOT_ROOT
- }
- create_bootpart_label() {
- e2label "/dev/$BOOT_DEVNAME" "$BOOTPART_LABEL"
- do_partprobe
- _add_state_file 'bootpart_label_created' 'mount'
- }
- copy_system_root() {
- if [ "$FORCE_REFORMAT_ROOT" ] || ! cryptsetup isLuks "/dev/$ROOT_DEVNAME"; then
- pu_msg "Formatting encrypted root partition:"
- echo -n $DISK_PASSWD | cryptsetup luksFormat "/dev/$ROOT_DEVNAME" '-'
- fi
- echo $DISK_PASSWD | cryptsetup luksOpen "/dev/$ROOT_DEVNAME" $ROOTFS_NAME
- local fstype=$(lsblk --noheadings --list --output=FSTYPE "/dev/mapper/$ROOTFS_NAME")
- [ "$fstype" == 'ext4' -a "$ROOTENC_REUSE_FS" ] || mkfs.ext4 -F "/dev/mapper/$ROOTFS_NAME"
- [ "$PARTITION_ONLY" ] || {
- mount "/dev/mapper/$ROOTFS_NAME" $TARGET_ROOT
- pu_msg "Copying system to encrypted root partition:"
- _show_output
- rsync $RSYNC_VERBOSITY --archive --exclude=boot $SRC_ROOT/* $TARGET_ROOT
- _hide_output
- sync
- mkdir -p "$TARGET_ROOT/boot"
- touch "$TARGET_ROOT/root/.no_rootfs_resize"
- umount $TARGET_ROOT
- }
- cryptsetup luksClose $ROOTFS_NAME
- do_partprobe
- _add_state_file 'rootpart_copied' 'mount'
- }
- mount_target() {
- echo $DISK_PASSWD | cryptsetup luksOpen "/dev/$ROOT_DEVNAME" $ROOTFS_NAME
- mount "/dev/mapper/$ROOTFS_NAME" $TARGET_ROOT
- mount "/dev/$BOOT_DEVNAME" "$TARGET_ROOT/boot"
- local src dest args
- while read src dest args; do
- mount $args $src $TARGET_ROOT/$dest
- done <<-EOF
- udev dev -t devtmpfs -o rw,relatime,nosuid,mode=0755
- devpts dev/pts -t devpts
- tmpfs dev/shm -t tmpfs -o rw,nosuid,nodev,relatime
- proc proc -t proc
- sys sys -t sysfs
- EOF
- }
- _copy_to_target() {
- local fn=$1
- if [ -e $fn ]; then
- echo "Copying '$fn'"
- cat $fn > $TARGET_ROOT/$fn
- else
- imsg "Unable to copy '$fn' to target (file does not exist)"
- false
- fi
- }
- create_etc_crypttab() {
- local root_uuid="$(lsblk --noheadings --list --nodeps --output=UUID /dev/$ROOT_DEVNAME)"
- echo "$ROOTFS_NAME UUID=$root_uuid none initramfs,luks" > "$TARGET_ROOT/etc/crypttab"
- _display_file "$TARGET_ROOT/etc/crypttab"
- }
- copy_etc_files() {
- _copy_to_target '/etc/resolv.conf'
- _copy_to_target '/etc/hosts'
- set +e
- _copy_to_target /etc/apt/apt.conf.d/*proxy
- set -e
- }
- _set_target_vars() {
- target_distro=$(chroot $TARGET_ROOT 'lsb_release' '--short' '--codename')
- target_kernel=$(chroot $TARGET_ROOT 'ls' '/boot' | egrep '^vmlinu[xz]')
- imsg "$(printf '%-8s %-28s %s' '' 'Host' 'Target')"
- imsg "$(printf '%-8s %-28s %s' '' '----' '------')"
- imsg "$(printf '%-8s %-28s %s' 'distro:' $host_distro $target_distro)"
- imsg "$(printf '%-8s %-28s %s' 'kernel:' $host_kernel $target_kernel)"
- }
- _distros_match() {
- [ $host_distro == $target_distro ]
- }
- _kernels_match() {
- [ ${host_kernel%.*} == ${target_kernel%.*} ] || return 1
- [ ${host_kernel##*-} == ${target_kernel##*-} ]
- }
- copy_etc_files_distro_specific() {
- local files='/etc/apt/sources.list /etc/apt/sources.list.d/armbian.list'
- if _distros_match; then
- for i in $files; do _copy_to_target $i; done
- else
- warn 'Warning: host and target distros do not match:'
- for i in $files; do imsg " not copying $i"; done
- fi
- }
- _display_file() {
- local name text reply
- if [ "$2" ]; then
- name="$1"
- text="$2"
- else
- name=${1#$TARGET_ROOT}
- text="$(cat $1)"
- fi
- hl='────────────────────────────────────────'
- hl="$hl$hl$hl"
- hls=${hl:0:${#name}+1}
- echo "┌─$hls─┐"
- echo "│ $name: │"
- echo "├─$hls─┘"
- echo "$text" | sed 's/^/│ /'
- }
- edit_armbianEnv() {
- local file text console_arg
- file="$TARGET_ROOT/boot/armbianEnv.txt"
- ed $file <<-'EOF'
- g/^\s*rootdev=/d
- g/^\s*console=/d
- g/^\s*bootlogo=/d
- wq
- EOF
- case $SERIAL_CONSOLE in
- 'yes') console_arg='serial' ;;
- *) console_arg='display' ;;
- esac
- text="rootdev=/dev/mapper/$ROOTFS_NAME
- console=$console_arg
- bootlogo=false"
- echo "$text" >> $file
- _display_file $file
- }
- # Add the following lines to '/etc/initramfs-tools/initramfs.conf'. If
- # your board’s IP address will be statically configured, substitute the
- # correct static IP address after 'IP='. If it will be configured via
- # DHCP, omit the IP line entirely:
- edit_initramfs_conf() {
- local file="$TARGET_ROOT/etc/initramfs-tools/initramfs.conf" dev='eth0'
- [ "$USB_GADGET" ] && dev='usb0'
- ed $file <<-'EOF'
- g/^\s*IP=/s/^/# /
- g/^\s*DEVICE=/d
- wq
- EOF
- [ "$IP_ADDRESS" == 'dhcp' -o "$IP_ADDRESS" == 'none' ] || {
- echo "IP=$IP_ADDRESS:::$NETMASK::$dev:off" >> $file
- }
- [ "$IP_ADDRESS" == 'none' ] || echo "DEVICE=$dev" >> $file
- _display_file $file
- }
- edit_initramfs_modules() {
- local modlist file hdr
- [ "$ADD_ALL_MODS" -o "$ADD_MODS" -o "$USB_GADGET" ] && {
- if ! _kernels_match; then
- warn 'Host and target kernels do not match. Not adding modules to initramfs'
- elif ! _distros_match; then
- warn 'Host and target distros do not match. Not adding modules to initramfs'
- else
- local g_mods='libcomposite u_ether usb_f_rndis g_ether usb_f_eem'
- [ "$ADD_ALL_MODS" ] && modlist=$(lsmod | cut -d ' ' -f1 | tail -n+2)
- [ "$ADD_MODS" ] && modlist+=$(echo; for m in ${ADD_MODS//,/ }; do echo $m; done)
- [ "$USB_GADGET" ] && modlist+=$(echo; for m in $g_mods; do echo $m; done)
- fi
- }
- file="$TARGET_ROOT/etc/initramfs-tools/modules"
- hdr="# List of modules that you want to include in your initramfs.
- # They will be loaded at boot time in the order below.
- #
- # Syntax: module_name [args ...]
- #
- # You must run update-initramfs(8) to effect this change.
- #
- "
- echo "$hdr$modlist" > $file
- _display_file $file
- }
- copy_authorized_keys() {
- local dest="$TARGET_ROOT/etc/dropbear-initramfs"
- mkdir -p $dest
- /bin/cp 'authorized_keys' $dest
- _display_file "$dest/authorized_keys"
- }
- create_fstab() {
- local boot_uuid file text
- boot_uuid="$(lsblk --noheadings --list --output=UUID /dev/$BOOT_DEVNAME)"
- file="$TARGET_ROOT/etc/fstab"
- text="/dev/mapper/$ROOTFS_NAME / ext4 defaults,noatime,nodiratime,commit=600,errors=remount-ro 0 1
- UUID=$boot_uuid /boot ext4 defaults,noatime,nodiratime,commit=600,errors=remount-ro 0 2
- tmpfs /tmp tmpfs defaults,nosuid 0 0"
- echo "$text" > $file
- _display_file $file
- }
- edit_dropbear_cfg() {
- local dest file text
- dest="$TARGET_ROOT/etc/dropbear-initramfs"
- file="$dest/config"
- text='DROPBEAR_OPTIONS="-p 2222"
- DROPBEAR=y'
- if [ "$IP_ADDRESS" == 'none' ]; then
- [ -e $file ] && rm -v $file
- true
- else
- mkdir -p $dest
- [ -e $file ] && grep -q '^DROPBEAR_OPTIONS="-p 2222"' $file || echo "$text" >> $file
- _display_file $file
- fi
- }
- netman_manage_usb0() {
- local file bu_file text
- file="$TARGET_ROOT/etc/NetworkManager/NetworkManager.conf"
- bu_file="$file.rootenc.orig"
- text='
- [device]
- match-device=interface-name:eth0
- managed=0
- match-device=interface-name:usb0
- managed=1'
- if [ -e $file ]; then
- if [ "$USB_GADGET" ]; then
- grep -q '^match-device=interface-name:usb0' $file || {
- /bin/cp $file $bu_file
- echo "$text" >> $file
- }
- else
- [ -e $bu_file ] && /bin/mv $bu_file $file
- fi
- _display_file $file
- else
- warn "$file does not exist, not enabling managed usb0"
- fi
- }
- ifupdown_config_usb0() {
- local file bu_file text
- file="$TARGET_ROOT/etc/network/interfaces"
- bu_file="$file.rootenc.orig"
- text="
- auto usb0
- iface usb0 inet static
- address $IP_ADDRESS
- netmask $NETMASK
- "
- if [ -e $file ]; then
- if [ "$USB_GADGET" -a "$IP_ADDRESS" != 'dhcp' ]; then
- grep -q '^auto usb0' $file || {
- /bin/cp $file $bu_file
- echo "$text" >> $file
- }
- systemctl mask network-manager
- else
- [ -e $bu_file ] && /bin/mv $bu_file $file
- systemctl unmask network-manager
- fi
- _display_file $file
- else
- warn "$file does not exist, not configuring static usb0"
- fi
- }
- create_cryptroot_unlock_sh() {
- local dest file text
- dest="$TARGET_ROOT/etc/initramfs-tools/hooks"
- file="$dest/cryptroot-unlock.sh"
- text='#!/bin/sh
- if [ "$1" = "prereqs" ]; then echo "dropbear-initramfs"; exit 0; fi
- . /usr/share/initramfs-tools/hook-functions
- source="/tmp/cryptroot-unlock-profile"
- root_home=$(echo $DESTDIR/root-*)
- root_home=${root_home#$DESTDIR}
- echo "if [ \"\$SSH_CLIENT\" ]; then /usr/bin/cryptroot-unlock; fi" > $source
- copy_file ssh_login_profile $source $root_home/.profile
- exit 0'
- mkdir -p $dest
- echo "$text" > $file
- chmod 755 $file
- _display_file $file
- }
- # begin chroot functions:
- apt_install_target() {
- local pkgs=$(_print_pkgs_to_install 'target')
- [ "$pkgs" ] && {
- echo "target packages to install: $pkgs"
- local ls1 ls2
- _show_output
- ls1=$(ls -l /boot/initrd.img-*)
- # DEBUG:
- # dpkg-reconfigure $pkgs # doesn't work in chroot
- # apt --yes purge $pkgs
- # apt-get --yes --purge autoremove
- dpkg --configure --pending --force-confdef
- set +e
- apt --yes purge 'bash-completion'
- apt --yes purge 'command-not-found'
- set -e
- _apt_update
- echo 'force-confdef' > /root/.dpkg.cfg
- apt --yes install $pkgs
- rm /root/.dpkg.cfg
- apt --yes autoremove
- ls2=$(ls -l /boot/initrd.img-*)
- [ "$ls1" != "$ls2" ] && initramfs_updated='y'
- _hide_output
- }
- true
- }
- update_initramfs() {
- [ "$ROOTENC_TESTING" ] && return 0
- _show_output
- local ver=$(echo /boot/vmlinu?-* | sed 's/.boot.vmlinu.-//')
- update-initramfs -k $ver -u
- _hide_output
- }
- check_initramfs() {
- local text chk count
- text="$(lsinitramfs /boot/initrd.img*)"
- set +e
- chk=$(echo "$text" | grep 'cryptsetup')
- count=$(echo "$chk" | wc -l)
- [ "$count" -gt 5 ] || { echo "$text"; die 'Cryptsetup scripts missing in initramfs image'; }
- _display_file "lsinitramfs /boot/initrd.img* | grep 'cryptsetup'" "$chk"
- [ "$IP_ADDRESS" == 'none' ] || {
- chk=$(echo "$text" | grep 'dropbear')
- count=$(echo "$chk" | wc -l)
- [ "$count" -gt 5 ] || { echo "$text"; die 'Dropbear scripts missing in initramfs image'; }
- _display_file "lsinitramfs /boot/initrd.img* | grep 'dropbear'" "$chk"
- chk=$(echo "$text" | grep 'authorized_keys')
- count=$(echo "$chk" | wc -l)
- [ "$count" -eq 1 ] || { echo "$text"; die 'authorized_keys missing in initramfs image'; }
- _display_file "lsinitramfs /boot/initrd.img* | grep 'authorized_keys'" "$chk"
- }
- set -e
- }
- configure_target() {
- [ "$PARTITION_ONLY" ] && return
- mount_target
- _set_target_vars
- copy_etc_files
- copy_etc_files_distro_specific
- edit_initramfs_conf
- edit_initramfs_modules
- [ "$IP_ADDRESS" == 'none' ] || copy_authorized_keys
- create_etc_crypttab
- create_fstab
- edit_dropbear_cfg
- netman_manage_usb0
- ifupdown_config_usb0
- [ "$IP_ADDRESS" == 'none' ] || create_cryptroot_unlock_sh
- edit_armbianEnv
- _debug_pause
- _show_output # this must be done before entering chroot
- /bin/cp $0 $TARGET_ROOT
- export 'ROOTFS_NAME' 'IP_ADDRESS' 'target_distro' 'ROOTENC_TESTING' 'ROOTENC_PAUSE' 'ROOTENC_IGNORE_APT_ERRORS' 'APT_UPGRADE'
- chroot $TARGET_ROOT "./$PROGNAME" $ORIG_OPTS 'in_target'
- /bin/cp -a '/etc/resolv.conf' "$TARGET_ROOT/etc" # this could be a symlink
- /bin/rm "$TARGET_ROOT/$PROGNAME"
- _add_state_file 'target_configured' 'target'
- }
- _set_env_vars() {
- shopt -s extglob
- local name val
- while [ $# -gt 0 ]; do
- name=${1%=?*} val=${1#+([A-Z_])=}
- [ "$name" == "$1" -o "$val" == "$1" ] && die "$1: illegal argument (must be in format 'NAME=value')"
- eval "$name=$val"
- shift
- done
- shopt -u extglob
- }
- _mount_target_and_exit() {
- setup_loopmount
- mount_target
- _set_target_vars
- rmdir $BOOT_ROOT
- exit
- }
- # begin execution
- set -e
- while getopts hCfFmo:MUpRsudvz OPT
- do
- case "$OPT" in
- h) print_help; exit ;;
- C) NO_CLEANUP='y' ;;
- f) FORCE_RECONFIGURE='y' ;;
- F) FORCE_REBUILD='y' ;;
- m) ADD_ALL_MODS='y' ;;
- o) ADD_MODS=$OPTARG ;;
- M) MOUNT_TARGET_ONLY='y' ;;
- U) UMOUNT_TARGET_ONLY='y' ;;
- p) PARTITION_ONLY='y' ;;
- R) FORCE_REFORMAT_ROOT='y' ;;
- s) USE_LOCAL_AUTHORIZED_KEYS='y' ;;
- u) APT_UPGRADE='y' ;;
- d) DEBUG='y' ;&
- v) VERBOSE='y' RSYNC_VERBOSITY='--verbose' ;;
- z) ERASE='y' ;;
- *) exit ;;
- esac
- ORIG_OPTS+="-$OPT $OPTARG "
- done
- shift $((OPTIND-1))
- trap '_return_handler' RETURN
- trap '_sigint_handler' INT
- trap '_error_handler' ERR
- set -o functrace
- set -o errtrace
- exec {stdout_dup}>&1
- exec {stderr_dup}>&2
- [ $UID == 0 -o $EUID == 0 ] || die 'This program must be run as root!'
- export HOME='/root'
- [ "$DEBUG" ] && set -x
- ARG1=$1; shift
- _set_env_vars $@
- if [ "$ARG1" == 'in_target' ]; then
- SCRIPT_DESC='Target script'
- _hide_output
- [ "$target_distro" == 'bionic' ] && {
- echo 'export CRYPTSETUP=y' > '/etc/initramfs-tools/conf.d/cryptsetup'
- }
- apt_install_target
- [ "$initramfs_updated" ] || update_initramfs
- check_initramfs
- else
- SCRIPT_DESC='Host script'
- _do_header
- _set_host_vars
- get_armbian_image
- apt_install_host # _preclean requires cryptsetup
- _preclean
- [ "$UMOUNT_TARGET_ONLY" ] && exit
- check_sdcard_name_and_params $ARG1
- create_build_dir
- [ "$MOUNT_TARGET_ONLY" ] && warn 'Mounting source and target and exiting at user request'
- _get_user_vars
- _test_sdcard_mounted
- [ "$MOUNT_TARGET_ONLY" ] && _mount_target_and_exit
- _warn_user_opts
- _confirm_user_vars
- [ "$IP_ADDRESS" == 'none' ] || get_authorized_keys
- [ "$NO_CLEANUP" ] || trap '_clean' EXIT
- setup_loopmount
- _debug_pause
- check_install_state
- _hide_output
- [ "$card_partitioned" == 'n' ] && _do_partition
- _debug_pause
- [ "$bootpart_copied" == 'n' ] && copy_system_boot
- [ "$bootpart_label_created" == 'n' ] && create_bootpart_label
- [ "$rootpart_copied" == 'n' ] && copy_system_root
- [ "$target_configured" == 'n' ] && configure_target
- sync
- gmsg 'All done!'
- if [ "$IP_ADDRESS" != 'none' ]; then
- imsg "To unlock the target disk, execute the following from the unlocking host:"
- imsg " ssh -p 2222 root@${IP_ADDRESS/dhcp/TARGET_IP}"
- fi
- fi
|