manjaro-arm-installer 14.6 KB
Newer Older
Dan Johansen's avatar
Dan Johansen committed
1 2 3
#! /bin/bash

# Set globals
4
TMPDIR=/var/tmp/manjaro-arm-installer
5
ARCH='aarch64'
Dan Johansen's avatar
Dan Johansen committed
6
NSPAWN='sudo systemd-nspawn --timezone=off -D'
Dan Johansen's avatar
Dan Johansen committed
7

8 9 10 11 12 13 14
# clearing variables
DEVICE=""
EDITION=""
USER=""
PASSWORD=""
ROOTPASSWORD=""
SDCARD=""
15 16
TIMEZONE=""
LOCALE=""
17

18
# Sanity checks for dependencies
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
if [ ! -f /usr/bin/sudo ]; then
    echo "sudo command is missing! Please install sudo!"
    exit 1
    elif [ ! -f /usr/bin/git ]; then
    echo "git command is missing! Please install git!"
    exit 1
    elif [ ! -f /usr/bin/parted ]; then
    echo "parted command is missing! Please install parted!"
    exit 1
    elif [ ! -f /usr/bin/systemd-nspawn ]; then
    echo "systemd-nspawn command is missing! Please install systemd!"
    exit 1
    elif [ ! -f /usr/bin/wget ]; then
    echo "wget command is missing! Please install wget!"
    exit 1
    elif [ ! -f /usr/bin/dialog ]; then
    echo "dialog command is missing! Please install dialog!"
    exit 1
    elif [ ! -f /usr/bin/bsdtar ]; then
    echo "bsdtar command is missing! Please install libarchive!"
    exit 1
fi
41

Dan Johansen's avatar
Dan Johansen committed
42 43

# Functions
44 45 46 47 48 49 50 51
msg() {
    ALL_OFF="\e[1;0m"
    BOLD="\e[1;1m"
    GREEN="${BOLD}\e[1;32m"
      local mesg=$1; shift
      printf "${GREEN}==>${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
 }

Dan Johansen's avatar
Dan Johansen committed
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73

usage_build_installer() {
    echo "Usage: ${0##*/} [options]"
    echo '    -h                 This help'
    echo ''
    echo ''
    exit $1
}

get_timer(){
    echo $(date +%s)
}

# $1: start timer
elapsed_time(){
    echo $(echo $1 $(get_timer) | awk '{ printf "%0.2f",($2-$1)/60 }')
}

show_elapsed_time(){
    msg "Time %s: %s minutes..." "$1" "$(elapsed_time $2)"
}

74
getarmprofiles () {
75 76 77
    if ls $TMPDIR/arm-profiles/* 1> /dev/null 2>&1; then
        cd $TMPDIR/arm-profiles
        git pull 1> /dev/null 2>&1
78
    else
79 80 81 82
        sudo mkdir -p $TMPDIR
        sudo chmod 777 $TMPDIR
        cd $TMPDIR
        git clone https://gitlab.com/Strit/arm-profiles.git 1> /dev/null 2>&1
83 84 85 86 87 88 89 90 91 92 93 94
    fi

}

create_install() {
 if [[ "$DEVICE" = "oc1" ]] || [[ "$DEVICE" = "rpi2" ]] || [[ "$DEVICE" = "xu4" ]]; then
        ARCH='armv7h'
    else
        ARCH='aarch64'
    fi

    msg "Creating install for $DEVICE..."
95 96 97 98
    
    # fetch and extract rootfs
    msg "Downloading latest $ARCH rootfs..."
    cd $TMPDIR
99
    wget -q --show-progress --progress=bar:force:noscroll https://www.strits.dk/files/Manjaro-ARM-$ARCH-latest.tar.gz
100 101
    
    msg "Extracting $ARCH rootfs..."
Dan Johansen's avatar
Dan Johansen committed
102
    sudo bsdtar -xpf $TMPDIR/Manjaro-ARM-$ARCH-latest.tar.gz -C $TMPDIR/root
Dan Johansen's avatar
Dan Johansen committed
103 104
    
    msg "Setting up keyrings..."
Dan Johansen's avatar
Dan Johansen committed
105 106
    $NSPAWN $TMPDIR/root pacman-key --init 1> /dev/null 2>&1
    $NSPAWN $TMPDIR/root pacman-key --populate archlinuxarm manjaro manjaro-arm 1> /dev/null 2>&1
Dan Johansen's avatar
Dan Johansen committed
107 108 109
    
    msg "Installing packages for $EDITION on $DEVICE..."
    # Install device and editions specific packages
Dan Johansen's avatar
Dan Johansen committed
110
    $NSPAWN $TMPDIR/root pacman -Syy base $PKG_DEVICE $PKG_EDITION --needed --noconfirm
Dan Johansen's avatar
Dan Johansen committed
111 112 113
    
    msg "Enabling services..."
    # Enable services
Dan Johansen's avatar
Dan Johansen committed
114 115
    $NSPAWN $TMPDIR/root systemctl enable systemd-networkd.service getty.target haveged.service dhcpcd.service 1> /dev/null 2>&1
    $NSPAWN $TMPDIR/root systemctl enable $SRV_EDITION 1> /dev/null 2>&1
Dan Johansen's avatar
Dan Johansen committed
116 117

    if [[ "$DEVICE" = "oc1" ]] || [[ "$DEVICE" = "oc2" ]]; then
Dan Johansen's avatar
Dan Johansen committed
118
        $NSPAWN $TMPDIR/root systemctl enable amlogic.service 1> /dev/null 2>&1
Dan Johansen's avatar
Dan Johansen committed
119 120 121
    fi

    msg "Applying overlay for $EDITION..."
122
    sudo cp -ap $TMPDIR/arm-profiles/overlays/$EDITION/* $TMPDIR/root/
Dan Johansen's avatar
Dan Johansen committed
123 124 125
    
    msg "Setting up users..."
    #setup users
126 127 128
    echo "$USER" > $TMPDIR/user
    echo "$PASSWORD" >> $TMPDIR/password
    echo "$PASSWORD" >> $TMPDIR/password
129 130
    echo "$ROOTPASSWORD" >> $TMPDIR/rootpassword
    echo "$ROOTPASSWORD" >> $TMPDIR/rootpassword
Dan Johansen's avatar
Dan Johansen committed
131 132 133
    $NSPAWN $TMPDIR/root passwd root < $TMPDIR/rootpassword 1> /dev/null 2>&1
    $NSPAWN $TMPDIR/root useradd -m -g users -G wheel,storage,network,power -s /bin/bash $(cat $TMPDIR/user) 1> /dev/null 2>&1
    $NSPAWN $TMPDIR/root passwd $(cat $TMPDIR/user) < $TMPDIR/password 1> /dev/null 2>&1
134

Dan Johansen's avatar
Dan Johansen committed
135 136 137 138 139
    
    msg "Enabling user services..."
    if [[ "$EDITION" = "minimal" ]] || [[ "$EDITION" = "server" ]]; then
        echo "No user services for $EDITION edition"
    else
Dan Johansen's avatar
Dan Johansen committed
140
        $NSPAWN $TMPDIR/root --user $(cat $TMPDIR/user) systemctl --user enable pulseaudio.service 1> /dev/null 2>&1
Dan Johansen's avatar
Dan Johansen committed
141 142 143 144
    fi

    msg "Setting up system settings..."
    #system setup
Dan Johansen's avatar
Dan Johansen committed
145 146 147 148 149 150
    $NSPAWN $TMPDIR/root chmod u+s /usr/bin/ping 1> /dev/null 2>&1
    $NSPAWN $TMPDIR/root update-ca-trust 1> /dev/null 2>&1
    $NSPAWN $TMPDIR/root ln -sf /usr/share/zoneinfo/"$TIMEZONE" /etc/localtime 1> /dev/null 2>&1
    $NSPAWN $TMPDIR/root sed -i s/"#$LOCALE"/"$LOCALE"/g /etc/locale.gen 1> /dev/null 2>&1
    $NSPAWN $TMPDIR/root sed -i s/"LANG=en_US.utf8"/"LANG=$LOCALE"/g /etc/locale.conf 1> /dev/null 2>&1
    $NSPAWN $TMPDIR/root locale-gen
Dan Johansen's avatar
Dan Johansen committed
151 152 153
    
    msg "Doing device specific setups for $DEVICE..."
    if [[ "$DEVICE" = "rpi2" ]] || [[ "$DEVICE" = "rpi3" ]]; then
154 155 156 157
        echo "dtparam=audio=on" | sudo tee --append $TMPDIR/root/boot/config.txt
        echo "hdmi_drive=2" | sudo tee --append $TMPDIR/root/boot/config.txt
        echo "audio_pwm_mode=2" | sudo tee --append $TMPDIR/root/boot/config.txt
        echo "/dev/mmcblk0p1  /boot   vfat    defaults        0       0" | sudo tee --append $TMPDIR/root/etc/fstab
Dan Johansen's avatar
Dan Johansen committed
158 159 160 161 162
    elif [[ "$DEVICE" = "oc1" ]] || [[ "$DEVICE" = "oc2" ]]; then
        echo "No device setups for $DEVICE..."
    elif [[ "$DEVICE" = "rock64" ]] || [[ "$DEVICE" = "rockpro64" ]]; then
        echo "No device setups for $DEVICE..."
    elif [[ "$DEVICE" = "pinebook" ]]; then
Dan Johansen's avatar
Dan Johansen committed
163 164
        $NSPAWN $TMPDIR/root systemctl enable pinebook-post-install.service 1> /dev/null 2>&1
        $NSPAWN $TMPDIR/root --user $(cat $TMPDIR/user) systemctl --user enable pinebook-user.service 1> /dev/null 2>&1
Dan Johansen's avatar
Dan Johansen committed
165 166 167 168
    else
        echo ""
    fi
    
169
    msg "Cleaning install for unwanted files..."
Dan Johansen's avatar
Dan Johansen committed
170
       if [[ "$DEVICE" = "oc1" ]] || [[ "$DEVICE" = "rpi2" ]] || [[ "$DEVICE" = "xu4" ]]; then
171
        sudo rm $TMPDIR/root/usr/bin/qemu-arm-static
Dan Johansen's avatar
Dan Johansen committed
172
    else
173
        sudo rm $TMPDIR/root/usr/bin/qemu-aarch64-static
Dan Johansen's avatar
Dan Johansen committed
174
    fi
175 176 177 178
    sudo rm -rf $TMPDIR/root/var/cache/pacman/pkg/*
    sudo rm -rf $TMPDIR/root/var/log/*
    
    # Remove temp files on host
Dan Johansen's avatar
Dan Johansen committed
179
    sudo rm -rf $TMPDIR/user $TMPDIR/password $TMPDIR/rootpassword
180
    sudo rm -rf $TMPDIR/Manjaro-ARM-$ARCH-latest.tar.gz*
Dan Johansen's avatar
Dan Johansen committed
181

182
    msg "$DEVICE $EDITION install complete"
Dan Johansen's avatar
Dan Johansen committed
183 184 185
}

prepare_card () {
186
    msg "Getting $SDCARD ready for $DEVICE..."
Dan Johansen's avatar
Dan Johansen committed
187 188 189
    # For Raspberry Pi devices
    if [[ "$DEVICE" = "rpi2" ]] || [[ "$DEVICE" = "rpi3" ]]; then
        #partition with boot and root
190 191 192
        sudo parted -s $SDCARD mklabel msdos 1> /dev/null 2>&1
        sudo parted -s $SDCARD mkpart primary fat32 0% 100M 1> /dev/null 2>&1
        START=`cat /sys/block/$DEV_NAME/${DEV_NAME}1/start` 
Dan Johansen's avatar
Dan Johansen committed
193
        SIZE=`cat /sys/block/$DEV_NAME/${DEV_NAME}1/size`
194
        END_SECTOR=$(expr $START + $SIZE)
195 196 197 198
        sudo parted -s $SDCARD mkpart primary ext4 "${END_SECTOR}s" 100% 1> /dev/null 2>&1
        sudo partprobe $SDCARD 1> /dev/null 2>&1
        sudo mkfs.vfat "${SDCARD}1" 1> /dev/null 2>&1
        sudo mkfs.ext4 "${SDCARD}2" 1> /dev/null 2>&1
199 200
        
        #Mount SD card
Dan Johansen's avatar
Dan Johansen committed
201 202
        mkdir -p $TMPDIR/root
        mkdir -p $TMPDIR/boot
203 204
        sudo mount ${SDCARD}1 $TMPDIR/boot
        sudo mount ${SDCARD}2 $TMPDIR/root
Dan Johansen's avatar
Dan Johansen committed
205 206 207 208

    # For Odroid devices
    elif [[ "$DEVICE" = "oc1" ]] || [[ "$DEVICE" = "oc2" ]] || [[ "$DEVICE" = "xu4" ]]; then
        #Clear first 8mb
209
        sudo dd if=/dev/zero of=${SDCARD} bs=1M count=8 1> /dev/null 2>&1
Dan Johansen's avatar
Dan Johansen committed
210 211
	
    #partition with a single root partition
212 213 214 215
        sudo parted -s $SDCARD mklabel msdos 1> /dev/null 2>&1
        sudo parted -s $SDCARD mkpart primary ext4 0% 100% 1> /dev/null 2>&1
        sudo partprobe $SDCARD 1> /dev/null 2>&1
        sudo mkfs.ext4 -O ^metadata_csum,^64bit ${SDCARD}1 1> /dev/null 2>&1
216 217
        
        #Mount SD card
Dan Johansen's avatar
Dan Johansen committed
218 219
        mkdir -p $TMPDIR/root
        sudo chmod 777 -R $TMPDIR/root
220
        sudo mount ${SDCARD}1 $TMPDIR/root
Dan Johansen's avatar
Dan Johansen committed
221 222 223 224 225

    # For pinebook device
    elif [[ "$DEVICE" = "pinebook" ]]; then

    #Clear first 8mb
226
        sudo dd if=/dev/zero of=${SDCARD} bs=1M count=8 1> /dev/null 2>&1
Dan Johansen's avatar
Dan Johansen committed
227 228
	
    #partition with a single root partition
229 230 231 232
        sudo parted -s $SDCARD mklabel msdos 1> /dev/null 2>&1
        sudo parted -s $SDCARD mkpart primary ext4 0% 100% 1> /dev/null 2>&1
        sudo partprobe $SDCARD 1> /dev/null 2>&1
        sudo mkfs.ext4 -O ^metadata_csum,^64bit ${SDCARD}1 1> /dev/null 2>&1
233 234
        
        # Mount SD card
Dan Johansen's avatar
Dan Johansen committed
235 236
        mkdir -p $TMPDIR/root
        sudo chmod 777 -R $TMPDIR/root
237
        sudo mount ${SDCARD}1 $TMPDIR/root
238

Dan Johansen's avatar
Dan Johansen committed
239 240 241 242
    # For rockpro64 device
    elif [[ "$DEVICE" = "rockpro64" ]]; then

    #Clear first 8mb
243
        sudo dd if=/dev/zero of=${SDCARD} bs=1M count=8 1> /dev/null 2>&1
Dan Johansen's avatar
Dan Johansen committed
244 245
	
    #partition with a single root partition
246 247 248 249
        sudo parted -s $SDCARD mklabel msdos 1> /dev/null 2>&1
        sudo parted -s $SDCARD mkpart primary ext4 0% 100% 1> /dev/null 2>&1
        sudo partprobe $SDCARD 1> /dev/null 2>&1
        sudo mkfs.ext4 -O ^metadata_csum,^64bit ${SDCARD}1 1> /dev/null 2>&1
250 251
        
        # Mount SD card
Dan Johansen's avatar
Dan Johansen committed
252 253
        mkdir -p $TMPDIR/root
        sudo chmod 777 -R $TMPDIR/root
254
        sudo mount ${SDCARD}1 $TMPDIR/root
255 256 257 258 259 260 261 262 263 264 265 266 267 268
    fi
}

cleanup () {
    msg "Writing bootloader and cleaning up after install..."
   # For Raspberry Pi devices
    if [[ "$DEVICE" = "rpi2" ]] || [[ "$DEVICE" = "rpi3" ]]; then
       #copy rootfs contents over to the FS
        sudo mv $TMPDIR/root/boot/* $TMPDIR/boot
        
        #clean up
        sudo umount $TMPDIR/root
        sudo umount $TMPDIR/boot
        sudo rm -r $TMPDIR/root $TMPDIR/boot
269
        sudo partprobe $SDCARD 1> /dev/null 2>&1
270 271 272 273 274
        
# For Odroid devices
    elif [[ "$DEVICE" = "oc1" ]] || [[ "$DEVICE" = "oc2" ]] || [[ "$DEVICE" = "xu4" ]]; then
    #flash bootloader
        cd $TMPDIR/root/boot/
275
        sudo ./sd_fusing.sh $SDCARD 1> /dev/null 2>&1
276 277 278 279 280
        cd ~

    #clean up
        sudo umount $TMPDIR/root
        sudo rm -r $TMPDIR/root
281
        sudo partprobe $SDCARD 1> /dev/null 2>&1
282 283 284 285
        
    # For pinebook device
    elif [[ "$DEVICE" = "pinebook" ]]; then
    #flash bootloader
286
        sudo dd if=$TMPDIR/root/boot/u-boot-sunxi-with-spl-$DEVICE.bin of=${SDCARD} bs=8k seek=1 1> /dev/null 2>&1
287 288 289 290
        
    #clean up
        sudo umount $TMPDIR/root
        sudo rm -r $TMPDIR/root
291
        sudo partprobe $SDCARD 1> /dev/null 2>&1
Dan Johansen's avatar
Dan Johansen committed
292
        
293 294 295
        
    # For rockpro64 device
    elif [[ "$DEVICE" = "rockpro64" ]]; then
Dan Johansen's avatar
Dan Johansen committed
296
    #flash bootloader
297 298 299
        sudo dd if=$TMPDIR/root/boot/idbloader.img of=${SDCARD} seek=64 conv=notrunc 1> /dev/null 2>&1
        sudo dd if=$TMPDIR/root/boot/uboot.img of=${SDCARD} seek=16384 conv=notrunc 1> /dev/null 2>&1
        sudo dd if=$TMPDIR/root/boot/trust.img of=${SDCARD} seek=24576 conv=notrunc 1> /dev/null 2>&1
Dan Johansen's avatar
Dan Johansen committed
300 301 302 303
        
    #clean up
        sudo umount $TMPDIR/root
        sudo rm -r $TMPDIR/root
304
        sudo partprobe $SDCARD 1> /dev/null 2>&1
305 306
        
fi
Dan Johansen's avatar
Dan Johansen committed
307 308
}

309 310

# Using Dialog to ask for user input for variables
311 312
DEVICE=$(dialog --clear --title "Manjaro ARM Installer" \
        --menu "Choose a device:" 20 51 6 \
313 314
        "rpi3" "Raspberry Pi 3" \
        "oc2" "Odroid C2" \
315
	"pinebook" "Pinebook" \
316 317 318
	"rpi2" "Raspberry Pi 2 (unmaintained)" \
	"oc1" "Odroid C1/C1+ (unmaintained)" \
	"xu4" "Odroid XU4 (unmaintained)" 3>&1 1>&2 2>&3 3>&-)
319 320 321 322 323


#The if statement makes sure that the user has put in something in the previous prompt. If not (left blank or pressed cancel) the script will end
if [ ! -z "$DEVICE" ]
then
324 325
EDITION=$(dialog --clear --title "Manjaro ARM Installer" \
	--menu "Choose an edition:" 20 50 5 \
326 327
	"minimal" "Minimal Edition (Just CLI)" \
	"lxqt" "Full LXQT Desktop and apps (lightweight)" \
328
	"kde" "Full KDE/Plasma Desktop (Heavy)" \
329
	"mate" "Full MATE desktop and apps (lightweight, unmaintained)" \
330
	"i3" "Mininal i3 WM with apps (very light)" 3>&1 1>&2 2>&3 3>&-) 
331 332 333 334 335 336 337 338 339

else 
	clear
	exit 1
fi


if [ ! -z "$EDITION" ]
then
340
USER=$(dialog --clear --title "Manjaro ARM Installer" \
341 342 343 344 345 346 347 348 349 350 351 352
	--inputbox "Enter username:" 8 50 \
        3>&1 1>&2 2>&3 3>&-)
else 
	clear
	exit 1
fi




if [ ! -z "$USER" ]
then
353 354
PASSWORD=$(dialog --clear --title "Manjaro ARM Installer" \
	--passwordbox "Enter Password for $USER:" 8 50 \
355 356 357 358 359 360 361 362 363 364 365
        3>&1 1>&2 2>&3 3>&- \
	)
else 
	clear
	exit 1
fi



if [ ! -z "$PASSWORD" ]
then
366
ROOTPASSWORD=$(dialog --clear --title "Manjaro ARM Installer" \
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386
	--passwordbox "Enter Root Password:" 8 50 \
        3>&1 1>&2 2>&3 3>&- \
	)
else 
	clear
	exit 1
fi




if [ ! -z "$ROOTPASSWORD" ]
then

# simple command to put the results of lsblk (just the names of the devices) into an array and make that array populate the options	
let i=0
W=()
while read -r line; do
    let i=$i+1
    W+=($line "")
387
done < <( lsblk -dn -o NAME )
388
SDCARD=$(dialog --title "Manjaro ARM Installer" \
389
	--menu "Chose your SDCard - Be sure the correct drive is selected!" 20 50 5 \
390 391 392 393 394 395 396 397 398 399
       	"${W[@]}" 3>&2 2>&1 1>&3)

# add /dev/ to the selected option above
SDCARD=/dev/$SDCARD
else 
	clear
	exit 1
fi


400 401 402 403 404 405 406 407 408 409 410 411
if [ ! -z "$SDCARD" ]
then
let i=0
W=()
while read -r line; do
    let i=$i+1
    W+=($line "")
done < <( timedatectl list-timezones )
TIMEZONE=$(dialog --clear --title "Manjaro ARM Installer" \
    --menu "Chose your timezone!" 20 50 15 \
        "${W[@]}" 3>&1 1>&2 2>&3 3>&- \
	)
412
#	--inputbox "Enter timezone (example Europe/London):" 8 50 \
413 414 415 416
else 
	clear
	exit 1
fi
417 418


419 420 421 422 423 424 425 426 427 428 429 430
if [ ! -z "$TIMEZONE" ]
then
let i=0
W=()
while read -r line; do
    let i=$i+1
    W+=($line "")
done < <( cat /etc/locale.gen | grep "UTF-8" | tail -n +2 | awk '{print $1}' | sed -e 's/^#*//' )
LOCALE=$(dialog --clear --title "Manjaro ARM Installer" \
	--menu "Chose your locale!" 20 50 15 \
        "${W[@]}" 3>&1 1>&2 2>&3 3>&- \
	)
431
#	--inputbox "Enter locale (example en_US.UTF-8):" 8 50 \
432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461
else 
	clear
	exit 1
fi

if [ ! -z "$LOCALE" ]
then
dialog --clear --title "Manjaro ARM Installer" \
    --yesno "Is the below information correct:
    Device = $DEVICE
    Edition = $EDITION
    Username = $USER
    Password for $USER = $PASSWORD
    Password for root = $ROOTPASSWORD
    SD/eMMC card = $SDCARD
    Timezone = $TIMEZONE
    Locale = $LOCALE" 20 50 \
    3>&1 1>&2 2>&3 3>&-
else
    clear
    exit 1
fi

response=$?
case $response in
   0) clear; msg "Proceeding....";;
   1) clear; msg "Installation aborted...."; exit 1;;
   255) clear; msg "Installation aborted..."; exit 1;;
esac

462

Dan Johansen's avatar
Dan Johansen committed
463 464 465 466 467 468
if [[ "$DEVICE" = "oc1" ]] || [[ "$DEVICE" = "rpi2" ]] || [[ "$DEVICE" = "xu4" ]]; then
    ARCH='armv7h'
else
    ARCH='aarch64'
fi

469 470
# get the profiles
getarmprofiles
Dan Johansen's avatar
Dan Johansen committed
471 472

#Package lists
473 474 475
PKG_DEVICE=$(grep "^[^#;]" $TMPDIR/arm-profiles/devices/$DEVICE | awk '{print $1}')
PKG_EDITION=$(grep "^[^#;]" $TMPDIR/arm-profiles/editions/$EDITION | awk '{print $1}')
SRV_EDITION=$(grep "^[^#;]" $TMPDIR/arm-profiles/services/$EDITION | awk '{print $1}')
Dan Johansen's avatar
Dan Johansen committed
476

477

Dan Johansen's avatar
Dan Johansen committed
478
# Commands
479
timer_start=$(get_timer)
Dan Johansen's avatar
Dan Johansen committed
480 481

prepare_card
482 483 484 485
create_install
cleanup
show_elapsed_time "${FUNCNAME}" "${timer_start}"
sync