1#!/bin/bash
2
3# Copyright 2017 The Fuchsia Authors
4#
5# Use of this source code is governed by a MIT-style
6# license that can be found in the LICENSE file or at
7# https://opensource.org/licenses/MIT
8
9# Run multiple early-boot entropy collector tests, with different kernel cmdlines.
10#
11# This script listens on stdin for Zircon cmdlines. For each line passed to stdin, a new early boot
12# test is run with that line passed as the kernel cmdline.
13
14# This script requires an output directory, passed as the first (and only) non-option command line
15# argument. There are also a number of options, described in the HELP function below.
16
17set -e -u
18CDPATH=
19ZIRCONDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/../.." && pwd )"
20
21# Print help message and exit
22function HELP {
23    if [[ $HELPFLAG -lt 2 ]]; then
24        echo "Usage: $0 [options] -- <cmdline1> <cmdline2> ..." >&2
25        echo >&2
26        echo "Repeatedly runs boot tests, using each provided cmdline in turn" >&2
27        echo "Mind your shell escapes when calling this script." >&2
28    fi
29    echo "Mandatory options (if omitted, you will be prompted):" >&2
30    echo "    -n <name>   : nodename (only mandatory for non-qemu (netboot) targets)" >&2
31    echo "    -o <dir>    : output directory" >&2
32    echo "    -s <source> : entropy source to test: hw_rng, jitterentropy" >&2
33    echo "    -t <target> : qemu-x86, qemu-arm64, pc, hikey960, odroidc2, or rpi3" >&2
34    echo >&2
35    echo "Optional options (if omitted, default as specified):" >&2
36    echo "    -b <dir>    : build directory [default: autodetected from -t]" >&2
37    echo "    -h          : show help then terminate" >&2
38    if [[ $HELPFLAG -lt 2 ]]; then
39        echo "                : if passed twice, only print options (meant for" >&2
40        echo "                : use by scripts that call $0)" >&2
41    fi
42    echo "    -l <len>    : bytes of data to collect  [default: 1024*1024]" >&2
43    echo "    -r          : Use release build [default: false]" >&2
44    exit 1
45}
46
47# build-related options
48ARCH=
49BUILDDIR=
50BUILD_ARGS=
51BUILD_LEN=$((1024*1024))
52BUILD_PROJECT=
53BUILDDIR_SUFFIX=
54HELPFLAG=0
55METHOD=
56LEN=$((1024*1024))
57NODENAME=
58OUTDIR=
59SOURCE=
60TARGET=
61
62while getopts "b:hl:n:o:rs:t:" FLAG; do
63    case "$FLAG" in
64        b) BUILDDIR="$OPTARG";;
65        h) HELPFLAG=$((HELPFLAG + 1));;
66        l)
67            LEN="$OPTARG"
68            if [[ $LEN -gt $BUILD_LEN ]]; then BUILD_LEN="$LEN"; fi
69            ;;
70        n) NODENAME="$OPTARG";;
71        o) OUTDIR="$OPTARG";;
72        r)
73            BUILDDIR_SUFFIX+="-release"
74            BUILD_ARGS+="DEBUG=0 "
75            ;;
76        s) SOURCE="$OPTARG";;
77        t) TARGET="$OPTARG";;
78        \?)
79            echo "unrecognized option" >&2
80            HELP
81            ;;
82    esac
83done
84
85if (( $HELPFLAG )); then
86    HELP
87fi
88
89
90LASTOPT=$((OPTIND-1))
91if [[ $LASTOPT -lt 1 || ${!LASTOPT} != "--" ]]; then
92    echo "didn't see '--' at end of options" >&2
93    HELP
94else
95    shift $((OPTIND-1))
96fi
97
98if [[ -z $OUTDIR ]]; then
99    echo -n "output directory: " >&2
100    read -r OUTDIR
101fi
102if [[ ! -d $OUTDIR ]]; then
103    echo "missing output directory (tried '$OUTDIR')" >&2
104    HELP
105fi
106
107# prompt for SOURCE if needed
108if [[ -z $SOURCE ]]; then
109    echo "choose entropy source:" >&2
110    select SOURCE in "hw_rng" "jitterentropy"; do
111        if [[ -n $SOURCE ]]; then break; fi
112    done
113fi
114if ! [[ $SOURCE = "hw_rng" || $SOURCE = "jitterentropy" ]]; then
115    echo "unrecognized source '$SOURCE'" >&2
116    HELP
117fi
118# handle the TARGET variable
119if [[ -z $TARGET ]]; then
120    echo "choose target:" >&2
121    select TARGET in "qemu-x86" "qemu-arm64" "pc" "hikey960" "odroidc2" "rpi3"; do
122        if [[ -n $TARGET ]]; then break; fi
123    done
124fi
125case "$TARGET" in
126    qemu-x86)
127        ARCH="x86"
128        BUILD_PROJECT="x86"
129        METHOD=qemu
130        ;;
131    qemu-arm64)
132        ARCH="arm64"
133        BUILD_PROJECT="arm64"
134        METHOD=qemu
135        ;;
136    pc)
137        ARCH="x86"
138        BUILD_PROJECT="x86"
139        METHOD=netboot
140        ;;
141    hikey960 | odroidc2 | rpi3)
142        ARCH="arm64"
143        BUILD_PROJECT="$TARGET"
144        METHOD=netboot
145        ;;
146    *)
147        echo "unrecognized target '$TARGET'" >&2
148        HELP
149        ;;
150esac
151if [[ -z $BUILDDIR ]]; then
152    BUILDDIR="$ZIRCONDIR/build-$BUILD_PROJECT$BUILDDIR_SUFFIX"
153fi
154
155# build Zircon
156(
157    cd "$ZIRCONDIR"
158    scripts/entropy-test/make-parallel -l "$BUILD_LEN" $BUILD_ARGS "$BUILD_PROJECT"
159) || exit 1
160
161# choose nodename (after build, since we need netls)
162if [[ $METHOD = netboot && -z $NODENAME ]]; then
163    readarray -t NODENAMES < <($BUILDDIR/tools/netls --nowait --timeout=1000 |
164        sed 's/^\s*device\s\+//;s/\s\+([a-fA-F0-9:/]\+)\s*$//')
165    echo "choose device to run on:" >&2
166    select NODENAME in "${NODENAMES[@]}"; do
167        if [[ -n $NODENAME ]]; then break; fi
168    done
169fi
170
171# NODENAME is magic: if omitted, we don't pass -n to run-boot-test.
172# So, make NODENAME split into either 0 or 2 words when passed unquoted.
173if [[ -n $NODENAME ]]; then
174    NODENAME="$(printf -- "-n %q" "$NODENAME")"
175fi
176
177# run the tests
178for CMDLINE in "$@"; do
179    STATUS="bad"
180    for ((tries = 0; tries < 5; tries++)); do
181        # $NODENAME is intentionally not quoted. See above.
182        if "$ZIRCONDIR"/scripts/entropy-test/run-boot-test -a "$ARCH" -c "$CMDLINE" -l "$LEN" \
183            -m "$METHOD" $NODENAME  -o "$BUILDDIR" -s "$SOURCE" "$OUTDIR"; then
184            STATUS="good"
185            break
186        fi
187    done
188    if [[ $STATUS != "good" ]]; then
189        echo "Failed too many times. Aborting." >&2
190        echo "Failed cmdline: $CMDLINE" >&2
191        exit 1
192    fi
193done
194