| #!/bin/bash |
| |
| # Copyright 2017 The Fuchsia Authors |
| # |
| # Use of this source code is governed by a MIT-style |
| # license that can be found in the LICENSE file or at |
| # https://opensource.org/licenses/MIT |
| |
| # Runs a single instance of the early boot entropy collection test. |
| # |
| # This script assumes that Zircon has already been built to support entropy quality tests (i.e with |
| # the ENABLE_ENTROPY_COLLECTOR_TEST flag set at compile time). It handles starting Zircon either in |
| # qemu or via netboot, then it extracts the entropy file once the boot-time test completes. Usually |
| # you will call a "test driver" script that in turn calls this script, rather than calling this |
| # script directly. |
| # |
| # Where sensible, the option flags agree with scripts/run-zircon. The -a, -m, and -s command line |
| # options are mandatory; the rest are optional. The output directory must also be passed on the |
| # command line, as a positional argument (i.e. without a '-?' type flag). |
| # |
| # This script saves the captured entropy in a file named 'entropy.#########.bin' (to facilitate |
| # running repeated tests with the same output directory). It also saves a metadata file, named |
| # 'entropy.#########.meta', recording certain test parameters. See the source below for more |
| # details. |
| # |
| # BUGS: netboot isn't supported yet, only qemu. |
| |
| set -e -u |
| CDPATH= |
| ZIRCONDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/../.." && pwd )" |
| |
| function HELP { |
| echo "$0 [options] output-dir/" >&2 |
| echo "options:" >&2 |
| echo "-a <arch> : arm64 or x86" >&2 |
| echo "-c <word> : add word to kernel cmdline" >&2 |
| echo "-l <len> : entropy test length (bytes to collect)" >&2 |
| echo "-m <method> : netboot or qemu" >&2 |
| echo "-n <name> : Zircon nodename to use" >&2 |
| echo "-o <dir> : build directory" >&2 |
| echo "-s <source> : hwrng or jitterentropy" >&2 |
| exit 1 |
| } |
| |
| ARCH= |
| BUILDDIR= |
| CMDLINE="" |
| LEN= |
| METHOD= |
| NODENAME= |
| OUTDIR= |
| SRC= |
| |
| while getopts "a:c:hl:m:n:o:s:" FLAG; do |
| case "$FLAG" in |
| a) ARCH="$OPTARG";; |
| c) CMDLINE+="$OPTARG ";; |
| h) HELP;; |
| l) LEN="$OPTARG";; |
| m) METHOD="$OPTARG";; |
| n) NODENAME="$OPTARG";; |
| o) BUILDDIR="$OPTARG";; |
| s) SRC="$OPTARG";; |
| \?) |
| echo "unrecognized option" >&2 |
| HELP |
| ;; |
| esac |
| done |
| shift $((OPTIND-1)) |
| |
| if [[ "$#" -ne "1" ]]; then |
| echo "missing output dir" >&2 |
| HELP |
| fi |
| OUTDIR="$1" |
| shift |
| |
| # check required args |
| if [[ -z $ARCH ]]; then |
| echo "must specify arch" >&2 |
| HELP |
| fi |
| if [[ -z $METHOD ]]; then |
| echo "must specify method" >&2 |
| HELP |
| fi |
| if [[ -z $SRC ]]; then |
| echo "must specify source" >&2 |
| HELP |
| fi |
| if [[ -z $OUTDIR ]]; then |
| echo "must specify outdir" >&2 |
| HELP |
| fi |
| |
| # handle entropy-test specific cmdline args |
| CMDLINE+="kernel.entropy-test.src=$SRC " |
| if [[ -n $LEN ]]; then CMDLINE+="kernel.entropy-test.len=$LEN "; fi |
| |
| # find and read builddir |
| PROJECT="$ARCH" |
| |
| if [[ -z "$BUILDDIR" ]]; then |
| if [[ -n $PROJECT ]]; then |
| BUILDDIR="$ZIRCONDIR/build-$PROJECT" |
| else |
| echo "could not autodetect builddir. use -o." >&2 |
| HELP |
| fi |
| fi |
| |
| if [[ ! -d $BUILDDIR || ! -x $BUILDDIR/tools/netcp ]]; then |
| echo "bad builddir: $BUILDDIR" >&2 |
| HELP |
| fi |
| |
| BUILDID="$(sed -n '/^#define\s\+BUILDID/{s/^[^"]*"//;s/".*$//;p;q}' "$BUILDDIR/config-buildid.h")" |
| |
| # set a few other variables |
| if [[ -z $NODENAME ]]; then |
| if [[ $METHOD = "qemu" ]]; then |
| NODENAME="entropy-test-$(head -c16 /dev/urandom | xxd -p)"; |
| elif [[ $METHOD = "netboot" ]]; then |
| echo "missing nodename - required for netboot" >&2 |
| HELP |
| fi |
| fi |
| CMDLINE+="zircon.nodename=$NODENAME " |
| NUM="$(cd "$OUTDIR"; |
| find . \( -type f -name "entropy.*.bin" -print \) -o \( -type d ! -name . -prune \) | |
| sed 's/^.*entropy\.0*//;s/\.bin$//;s/^$/0/;' | grep '^[0-9]\+$' | |
| sort -nr | head -n 1)" |
| if [[ -z $NUM ]]; then NUM=-1; fi |
| NUM="$(printf "%09d" "$((NUM + 1))")" |
| BINFILE="$OUTDIR/entropy.$NUM.bin" |
| METAFILE="$OUTDIR/entropy.$NUM.meta" |
| |
| # launch zircon |
| case "$METHOD" in |
| qemu) |
| "$ZIRCONDIR/scripts/run-zircon" -a "$ARCH" -c "$CMDLINE" -N -o "$BUILDDIR" </dev/null & |
| ;; |
| netboot) |
| "$BUILDDIR/tools/bootserver" --tftp -n "$NODENAME" \ |
| "$BUILDDIR/zircon.bin" "$BUILDDIR/bootdata.bin" \ |
| -- "$CMDLINE" >/dev/null 2>/dev/null & |
| BOOTSERVER_PID=$! |
| ;; |
| *) |
| echo "unrecognized method: $METHOD" >&2 |
| HELP |
| ;; |
| esac |
| echo "launched zircon with nodename $NODENAME" >&2 |
| |
| # wait for zircon to send us the entropy file |
| while true; do |
| sleep 5; |
| if "$BUILDDIR"/tools/netcp --nowait --timeout=1000 \ |
| "$NODENAME:/boot/kernel/debug/entropy.bin" "$BINFILE" && |
| [[ -z $LEN || $(wc -c <"$BINFILE") -eq $LEN ]] |
| then |
| echo "Finished test on nodename $NODENAME" >&2 |
| break |
| fi |
| done |
| |
| # write the meta file |
| { |
| echo "entropy-test $METHOD" |
| echo "date $(date +"%Y-%m-%d %H:%M:%S %Z")" |
| echo "buildid $BUILDID" |
| echo "arch $ARCH" |
| echo "source $SRC" |
| echo "len $LEN" |
| echo "cmdline $CMDLINE" |
| } >$METAFILE |
| |
| # reset the test device |
| case "$METHOD" in |
| qemu) |
| while "$BUILDDIR"/tools/netaddr --nowait --timeout=1000 \ |
| "$NODENAME" >/dev/null 2>/dev/null; do |
| "$BUILDDIR"/tools/netruncmd --nowait --timeout=1000 "$NODENAME" dm shutdown |
| sleep 2 |
| done |
| ;; |
| netboot) |
| kill "$BOOTSERVER_PID" |
| sleep 1 # make sure bootserver actually has time to shut down |
| while "$BUILDDIR"/tools/netaddr --nowait --timeout=1000 \ |
| "$NODENAME" >/dev/null 2>/dev/null; do |
| "$BUILDDIR"/tools/netruncmd --nowait --timeout=1000 "$NODENAME" dm reboot |
| sleep 2 |
| done |
| ;; |
| esac |