blob: 6ade09a6c39c76b01a2219bee2906383133da409 [file] [log] [blame]
#!/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