manjaro-arm-installer 14.8 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

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

17
# Sanity checks for dependencies
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
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
40

Dan Johansen's avatar
Dan Johansen committed
41 42

# Functions
43 44 45 46 47 48 49 50
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
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72

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)"
}

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

}

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

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

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

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

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

    msg "Setting up system settings..."
    #system setup
144 145
    sudo systemd-nspawn -D $TMPDIR/root chmod u+s /usr/bin/ping 1> /dev/null 2>&1
    sudo systemd-nspawn -D $TMPDIR/root update-ca-trust 1> /dev/null 2>&1
146 147 148 149
    sudo systemd-nspawn -D $TMPDIR/root ln -sf /usr/share/zoneinfo/"$TIMEZONE" /etc/localtime 1> /dev/null 2>&1
    sudo systemd-nspawn -D $TMPDIR/root sed -i s/"#$LOCALE"/"$LOCALE"/g /etc/locale.gen 1> /dev/null 2>&1
    sudo systemd-nspawn -D $TMPDIR/root sed -i s/"LANG=en_US.utf8"/"LANG=$LOCALE"/g /etc/locale.conf 1> /dev/null 2>&1
    sudo systemd-nspawn -D $TMPDIR/root locale-gen
Dan Johansen's avatar
Dan Johansen committed
150 151 152
    
    msg "Doing device specific setups for $DEVICE..."
    if [[ "$DEVICE" = "rpi2" ]] || [[ "$DEVICE" = "rpi3" ]]; then
153 154 155 156
        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
157 158 159 160 161
    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
162 163
        sudo systemd-nspawn -D $TMPDIR/root systemctl enable pinebook-post-install.service 1> /dev/null 2>&1
        sudo systemd-nspawn -D $TMPDIR/root --user $(cat $TMPDIR/user) systemctl --user enable pinebook-user.service 1> /dev/null 2>&1
Dan Johansen's avatar
Dan Johansen committed
164 165 166 167
    else
        echo ""
    fi
    
168
    msg "Cleaning install for unwanted files..."
Dan Johansen's avatar
Dan Johansen committed
169
       if [[ "$DEVICE" = "oc1" ]] || [[ "$DEVICE" = "rpi2" ]] || [[ "$DEVICE" = "xu4" ]]; then
170
        sudo rm $TMPDIR/root/usr/bin/qemu-arm-static
Dan Johansen's avatar
Dan Johansen committed
171
    else
172
        sudo rm $TMPDIR/root/usr/bin/qemu-aarch64-static
Dan Johansen's avatar
Dan Johansen committed
173
    fi
174 175 176 177
    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
178
    sudo rm -rf $TMPDIR/user $TMPDIR/password $TMPDIR/rootpassword
179
    sudo rm -rf $TMPDIR/Manjaro-ARM-$ARCH-latest.tar.gz*
Dan Johansen's avatar
Dan Johansen committed
180

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

prepare_card () {
185
    msg "Getting $SDCARD ready for $DEVICE..."
Dan Johansen's avatar
Dan Johansen committed
186 187 188
    # For Raspberry Pi devices
    if [[ "$DEVICE" = "rpi2" ]] || [[ "$DEVICE" = "rpi3" ]]; then
        #partition with boot and root
189 190 191
        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
192
        SIZE=`cat /sys/block/$DEV_NAME/${DEV_NAME}1/size`
193
        END_SECTOR=$(expr $START + $SIZE)
194 195 196 197
        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
198 199
        
        #Mount SD card
Dan Johansen's avatar
Dan Johansen committed
200 201
        mkdir -p $TMPDIR/root
        mkdir -p $TMPDIR/boot
202 203
        sudo mount ${SDCARD}1 $TMPDIR/boot
        sudo mount ${SDCARD}2 $TMPDIR/root
Dan Johansen's avatar
Dan Johansen committed
204 205 206 207

    # For Odroid devices
    elif [[ "$DEVICE" = "oc1" ]] || [[ "$DEVICE" = "oc2" ]] || [[ "$DEVICE" = "xu4" ]]; then
        #Clear first 8mb
208
        sudo dd if=/dev/zero of=${SDCARD} bs=1M count=8 1> /dev/null 2>&1
Dan Johansen's avatar
Dan Johansen committed
209 210
	
    #partition with a single root partition
211 212 213 214
        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
215 216
        
        #Mount SD card
Dan Johansen's avatar
Dan Johansen committed
217 218
        mkdir -p $TMPDIR/root
        sudo chmod 777 -R $TMPDIR/root
219
        sudo mount ${SDCARD}1 $TMPDIR/root
Dan Johansen's avatar
Dan Johansen committed
220 221 222 223 224

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

    #Clear first 8mb
225
        sudo dd if=/dev/zero of=${SDCARD} bs=1M count=8 1> /dev/null 2>&1
Dan Johansen's avatar
Dan Johansen committed
226 227
	
    #partition with a single root partition
228 229 230 231
        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
232 233
        
        # Mount SD card
Dan Johansen's avatar
Dan Johansen committed
234 235
        mkdir -p $TMPDIR/root
        sudo chmod 777 -R $TMPDIR/root
236
        sudo mount ${SDCARD}1 $TMPDIR/root
237

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

    #Clear first 8mb
242
        sudo dd if=/dev/zero of=${SDCARD} bs=1M count=8 1> /dev/null 2>&1
Dan Johansen's avatar
Dan Johansen committed
243 244
	
    #partition with a single root partition
245 246 247 248
        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
249 250
        
        # Mount SD card
Dan Johansen's avatar
Dan Johansen committed
251 252
        mkdir -p $TMPDIR/root
        sudo chmod 777 -R $TMPDIR/root
253
        sudo mount ${SDCARD}1 $TMPDIR/root
254 255 256 257 258 259 260 261 262 263 264 265 266 267
    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
268
        sudo partprobe $SDCARD 1> /dev/null 2>&1
269 270 271 272 273
        
# For Odroid devices
    elif [[ "$DEVICE" = "oc1" ]] || [[ "$DEVICE" = "oc2" ]] || [[ "$DEVICE" = "xu4" ]]; then
    #flash bootloader
        cd $TMPDIR/root/boot/
274
        sudo ./sd_fusing.sh $SDCARD 1> /dev/null 2>&1
275 276 277 278 279
        cd ~

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

308 309

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


#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
323 324
EDITION=$(dialog --clear --title "Manjaro ARM Installer" \
	--menu "Choose an edition:" 20 50 5 \
325 326
	"minimal" "Minimal Edition (Just CLI)" \
	"lxqt" "Full LXQT Desktop and apps (lightweight)" \
327
	"kde" "Full KDE/Plasma Desktop (Heavy)" \
328
	"mate" "Full MATE desktop and apps (lightweight, unmaintained)" \
329
	"i3" "Mininal i3 WM with apps (very light)" 3>&1 1>&2 2>&3 3>&-) 
330 331 332 333 334 335 336 337 338

else 
	clear
	exit 1
fi


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




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



if [ ! -z "$PASSWORD" ]
then
365
ROOTPASSWORD=$(dialog --clear --title "Manjaro ARM Installer" \
366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385
	--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 "")
386
done < <( lsblk -dn -o NAME )
387
SDCARD=$(dialog --title "Manjaro ARM Installer" \
388
	--menu "Chose your SDCard - Be sure the correct drive is selected!" 20 50 5 \
389 390 391 392 393 394 395 396 397 398
       	"${W[@]}" 3>&2 2>&1 1>&3)

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


399 400 401 402 403 404 405 406 407 408 409 410
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>&- \
	)
411
#	--inputbox "Enter timezone (example Europe/London):" 8 50 \
412 413 414 415
else 
	clear
	exit 1
fi
416 417


418 419 420 421 422 423 424 425 426 427 428 429
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>&- \
	)
430
#	--inputbox "Enter locale (example en_US.UTF-8):" 8 50 \
431 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
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

461

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

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

#Package lists
472 473 474
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
475

476

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

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