1#!/bin/bash 2# shellcheck disable=SC1091 3# shellcheck disable=SC2034 4# shellcheck disable=SC2059 5# shellcheck disable=SC2086 # we want word splitting 6 7. "$SCRIPTS_DIR"/setup-test-env.sh 8 9# Boot script for devices attached to a PoE switch, using NFS for the root 10# filesystem. 11 12# We're run from the root of the repo, make a helper var for our paths 13BM=$CI_PROJECT_DIR/install/bare-metal 14CI_COMMON=$CI_PROJECT_DIR/install/common 15CI_INSTALL=$CI_PROJECT_DIR/install 16 17# Runner config checks 18if [ -z "$BM_SERIAL" ]; then 19 echo "Must set BM_SERIAL in your gitlab-runner config.toml [[runners]] environment" 20 echo "This is the serial port to listen the device." 21 exit 1 22fi 23 24if [ -z "$BM_POE_ADDRESS" ]; then 25 echo "Must set BM_POE_ADDRESS in your gitlab-runner config.toml [[runners]] environment" 26 echo "This is the PoE switch address to connect for powering up/down devices." 27 exit 1 28fi 29 30if [ -z "$BM_POE_INTERFACE" ]; then 31 echo "Must set BM_POE_INTERFACE in your gitlab-runner config.toml [[runners]] environment" 32 echo "This is the PoE switch interface where the device is connected." 33 exit 1 34fi 35 36if [ -z "$BM_POWERUP" ]; then 37 echo "Must set BM_POWERUP in your gitlab-runner config.toml [[runners]] environment" 38 echo "This is a shell script that should power up the device and begin its boot sequence." 39 exit 1 40fi 41 42if [ -z "$BM_POWERDOWN" ]; then 43 echo "Must set BM_POWERDOWN in your gitlab-runner config.toml [[runners]] environment" 44 echo "This is a shell script that should power off the device." 45 exit 1 46fi 47 48if [ ! -d /nfs ]; then 49 echo "NFS rootfs directory needs to be mounted at /nfs by the gitlab runner" 50 exit 1 51fi 52 53if [ ! -d /tftp ]; then 54 echo "TFTP directory for this board needs to be mounted at /tftp by the gitlab runner" 55 exit 1 56fi 57 58# job config checks 59if [ -z "$BM_ROOTFS" ]; then 60 echo "Must set BM_ROOTFS to your board's rootfs directory in the job's variables" 61 exit 1 62fi 63 64if [ -z "$BM_BOOTFS" ] && { [ -z "$BM_KERNEL" ] || [ -z "$BM_DTB" ]; } ; then 65 echo "Must set /boot files for the TFTP boot in the job's variables or set kernel and dtb" 66 exit 1 67fi 68 69if [ -z "$BM_CMDLINE" ]; then 70 echo "Must set BM_CMDLINE to your board's kernel command line arguments" 71 exit 1 72fi 73 74section_start prepare_rootfs "Preparing rootfs components" 75 76set -ex 77 78date +'%F %T' 79 80# Clear out any previous run's artifacts. 81rm -rf results/ 82mkdir -p results 83 84# Create the rootfs in the NFS directory. rm to make sure it's in a pristine 85# state, since it's volume-mounted on the host. 86rsync -a --delete $BM_ROOTFS/ /nfs/ 87 88date +'%F %T' 89 90# If BM_BOOTFS is an URL, download it 91if echo $BM_BOOTFS | grep -q http; then 92 curl -L --retry 4 -f --retry-all-errors --retry-delay 60 \ 93 "${FDO_HTTP_CACHE_URI:-}$BM_BOOTFS" -o /tmp/bootfs.tar 94 BM_BOOTFS=/tmp/bootfs.tar 95fi 96 97date +'%F %T' 98 99# If BM_BOOTFS is a file, assume it is a tarball and uncompress it 100if [ -f "${BM_BOOTFS}" ]; then 101 mkdir -p /tmp/bootfs 102 tar xf $BM_BOOTFS -C /tmp/bootfs 103 BM_BOOTFS=/tmp/bootfs 104fi 105 106# If BM_KERNEL and BM_DTS is present 107if [ -n "${EXTERNAL_KERNEL_TAG}" ]; then 108 if [ -z "${BM_KERNEL}" ] || [ -z "${BM_DTB}" ]; then 109 echo "This machine cannot be tested with external kernel since BM_KERNEL or BM_DTB missing!" 110 exit 1 111 fi 112 113 curl -L --retry 4 -f --retry-all-errors --retry-delay 60 \ 114 "${FDO_HTTP_CACHE_URI:-}${KERNEL_IMAGE_BASE}/${DEBIAN_ARCH}/${BM_KERNEL}" -o "${BM_KERNEL}" 115 curl -L --retry 4 -f --retry-all-errors --retry-delay 60 \ 116 "${FDO_HTTP_CACHE_URI:-}${KERNEL_IMAGE_BASE}/${DEBIAN_ARCH}/${BM_DTB}.dtb" -o "${BM_DTB}.dtb" 117 curl -L --retry 4 -f --retry-all-errors --retry-delay 60 \ 118 "${FDO_HTTP_CACHE_URI:-}${KERNEL_IMAGE_BASE}/${DEBIAN_ARCH}/modules.tar.zst" -o modules.tar.zst 119fi 120 121date +'%F %T' 122 123# Install kernel modules (it could be either in /lib/modules or 124# /usr/lib/modules, but we want to install in the latter) 125if [ -n "${EXTERNAL_KERNEL_TAG}" ]; then 126 tar --keep-directory-symlink --zstd -xf modules.tar.zst -C /nfs/ 127 rm modules.tar.zst & 128elif [ -n "${BM_BOOTFS}" ]; then 129 [ -d $BM_BOOTFS/usr/lib/modules ] && rsync -a $BM_BOOTFS/usr/lib/modules/ /nfs/usr/lib/modules/ 130 [ -d $BM_BOOTFS/lib/modules ] && rsync -a $BM_BOOTFS/lib/modules/ /nfs/lib/modules/ 131else 132 echo "No modules!" 133fi 134 135 136date +'%F %T' 137 138# Install kernel image + bootloader files 139if [ -n "${EXTERNAL_KERNEL_TAG}" ] || [ -z "$BM_BOOTFS" ]; then 140 mv "${BM_KERNEL}" "${BM_DTB}.dtb" /tftp/ 141else # BM_BOOTFS 142 rsync -aL --delete $BM_BOOTFS/boot/ /tftp/ 143fi 144 145date +'%F %T' 146 147# Set up the pxelinux config for Jetson Nano 148mkdir -p /tftp/pxelinux.cfg 149cat <<EOF >/tftp/pxelinux.cfg/default-arm-tegra210-p3450-0000 150PROMPT 0 151TIMEOUT 30 152DEFAULT primary 153MENU TITLE jetson nano boot options 154LABEL primary 155 MENU LABEL CI kernel on TFTP 156 LINUX Image 157 FDT tegra210-p3450-0000.dtb 158 APPEND \${cbootargs} $BM_CMDLINE 159EOF 160 161# Set up the pxelinux config for Jetson TK1 162cat <<EOF >/tftp/pxelinux.cfg/default-arm-tegra124-jetson-tk1 163PROMPT 0 164TIMEOUT 30 165DEFAULT primary 166MENU TITLE jetson TK1 boot options 167LABEL primary 168 MENU LABEL CI kernel on TFTP 169 LINUX zImage 170 FDT tegra124-jetson-tk1.dtb 171 APPEND \${cbootargs} $BM_CMDLINE 172EOF 173 174# Create the rootfs in the NFS directory 175. $BM/rootfs-setup.sh /nfs 176 177date +'%F %T' 178 179echo "$BM_CMDLINE" > /tftp/cmdline.txt 180 181# Add some options in config.txt, if defined 182if [ -n "$BM_BOOTCONFIG" ]; then 183 printf "$BM_BOOTCONFIG" >> /tftp/config.txt 184fi 185 186section_end prepare_rootfs 187 188set +e 189STRUCTURED_LOG_FILE=results/job_detail.json 190python3 $CI_INSTALL/custom_logger.py ${STRUCTURED_LOG_FILE} --update dut_job_type "${DEVICE_TYPE}" 191python3 $CI_INSTALL/custom_logger.py ${STRUCTURED_LOG_FILE} --update farm "${FARM}" 192ATTEMPTS=3 193first_attempt=True 194while [ $((ATTEMPTS--)) -gt 0 ]; do 195 section_start dut_boot "Booting hardware device ..." 196 python3 $CI_INSTALL/custom_logger.py ${STRUCTURED_LOG_FILE} --create-dut-job dut_name "${CI_RUNNER_DESCRIPTION}" 197 # Update subtime time to CI_JOB_STARTED_AT only for the first run 198 if [ "$first_attempt" = "True" ]; then 199 python3 $CI_INSTALL/custom_logger.py ${STRUCTURED_LOG_FILE} --update-dut-time submit "${CI_JOB_STARTED_AT}" 200 else 201 python3 $CI_INSTALL/custom_logger.py ${STRUCTURED_LOG_FILE} --update-dut-time submit 202 fi 203 python3 $BM/poe_run.py \ 204 --dev="$BM_SERIAL" \ 205 --powerup="$BM_POWERUP" \ 206 --powerdown="$BM_POWERDOWN" \ 207 --boot-timeout-seconds ${BOOT_PHASE_TIMEOUT_SECONDS:-300} \ 208 --test-timeout-minutes ${TEST_PHASE_TIMEOUT_MINUTES:-$((CI_JOB_TIMEOUT/60 - ${TEST_SETUP_AND_UPLOAD_MARGIN_MINUTES:-5}))} 209 ret=$? 210 211 if [ $ret -eq 2 ]; then 212 python3 $CI_INSTALL/custom_logger.py ${STRUCTURED_LOG_FILE} --close-dut-job 213 first_attempt=False 214 error "Device failed to boot; will retry" 215 else 216 # We're no longer in dut_boot by this point 217 unset CURRENT_SECTION 218 ATTEMPTS=0 219 fi 220done 221 222section_start dut_cleanup "Cleaning up after job" 223python3 $CI_INSTALL/custom_logger.py ${STRUCTURED_LOG_FILE} --close-dut-job 224python3 $CI_INSTALL/custom_logger.py ${STRUCTURED_LOG_FILE} --close 225set -e 226 227date +'%F %T' 228 229# Bring artifacts back from the NFS dir to the build dir where gitlab-runner 230# will look for them. 231cp -Rp /nfs/results/. results/ 232 233date +'%F %T' 234section_end dut_cleanup 235 236exit $ret 237