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# Runs a single instance of the early boot entropy collection test. 10# 11# This script assumes that Zircon has already been built to support entropy quality tests (i.e with 12# the ENABLE_ENTROPY_COLLECTOR_TEST flag set at compile time). It handles starting Zircon either in 13# qemu or via netboot, then it extracts the entropy file once the boot-time test completes. Usually 14# you will call a "test driver" script that in turn calls this script, rather than calling this 15# script directly. 16# 17# Where sensible, the option flags agree with scripts/run-zircon. The -a, -m, and -s command line 18# options are mandatory; the rest are optional. The output directory must also be passed on the 19# command line, as a positional argument (i.e. without a '-?' type flag). 20# 21# This script saves the captured entropy in a file named 'entropy.#########.bin' (to facilitate 22# running repeated tests with the same output directory). It also saves a metadata file, named 23# 'entropy.#########.meta', recording certain test parameters. See the source below for more 24# details. 25# 26# BUGS: netboot isn't supported yet, only qemu. 27 28set -e -u 29CDPATH= 30ZIRCONDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/../.." && pwd )" 31 32function HELP { 33 echo "$0 [options] output-dir/" >&2 34 echo "options:" >&2 35 echo "-a <arch> : arm64 or x86" >&2 36 echo "-c <word> : add word to kernel cmdline" >&2 37 echo "-l <len> : entropy test length (bytes to collect)" >&2 38 echo "-m <method> : netboot or qemu" >&2 39 echo "-n <name> : Zircon nodename to use" >&2 40 echo "-o <dir> : build directory" >&2 41 echo "-s <source> : hwrng or jitterentropy" >&2 42 exit 1 43} 44 45ARCH= 46BUILDDIR= 47CMDLINE="" 48LEN= 49METHOD= 50NODENAME= 51OUTDIR= 52SRC= 53 54while getopts "a:c:hl:m:n:o:s:" FLAG; do 55 case "$FLAG" in 56 a) ARCH="$OPTARG";; 57 c) CMDLINE+="$OPTARG ";; 58 h) HELP;; 59 l) LEN="$OPTARG";; 60 m) METHOD="$OPTARG";; 61 n) NODENAME="$OPTARG";; 62 o) BUILDDIR="$OPTARG";; 63 s) SRC="$OPTARG";; 64 \?) 65 echo "unrecognized option" >&2 66 HELP 67 ;; 68 esac 69done 70shift $((OPTIND-1)) 71 72if [[ "$#" -ne "1" ]]; then 73 echo "missing output dir" >&2 74 HELP 75fi 76OUTDIR="$1" 77shift 78 79# check required args 80if [[ -z $ARCH ]]; then 81 echo "must specify arch" >&2 82 HELP 83fi 84if [[ -z $METHOD ]]; then 85 echo "must specify method" >&2 86 HELP 87fi 88if [[ -z $SRC ]]; then 89 echo "must specify source" >&2 90 HELP 91fi 92if [[ -z $OUTDIR ]]; then 93 echo "must specify outdir" >&2 94 HELP 95fi 96 97# handle entropy-test specific cmdline args 98CMDLINE+="kernel.entropy-test.src=$SRC " 99if [[ -n $LEN ]]; then CMDLINE+="kernel.entropy-test.len=$LEN "; fi 100 101# find and read builddir 102PROJECT="$ARCH" 103 104if [[ -z "$BUILDDIR" ]]; then 105 if [[ -n $PROJECT ]]; then 106 BUILDDIR="$ZIRCONDIR/build-$PROJECT" 107 else 108 echo "could not autodetect builddir. use -o." >&2 109 HELP 110 fi 111fi 112 113if [[ ! -d $BUILDDIR || ! -x $BUILDDIR/tools/netcp ]]; then 114 echo "bad builddir: $BUILDDIR" >&2 115 HELP 116fi 117 118BUILDID="$(sed -n '/^#define\s\+BUILDID/{s/^[^"]*"//;s/".*$//;p;q}' "$BUILDDIR/config-buildid.h")" 119 120# set a few other variables 121if [[ -z $NODENAME ]]; then 122 if [[ $METHOD = "qemu" ]]; then 123 NODENAME="entropy-test-$(head -c16 /dev/urandom | xxd -p)"; 124 elif [[ $METHOD = "netboot" ]]; then 125 echo "missing nodename - required for netboot" >&2 126 HELP 127 fi 128fi 129CMDLINE+="zircon.nodename=$NODENAME " 130NUM="$(cd "$OUTDIR"; 131 find . \( -type f -name "entropy.*.bin" -print \) -o \( -type d ! -name . -prune \) | 132 sed 's/^.*entropy\.0*//;s/\.bin$//;s/^$/0/;' | grep '^[0-9]\+$' | 133 sort -nr | head -n 1)" 134if [[ -z $NUM ]]; then NUM=-1; fi 135NUM="$(printf "%09d" "$((NUM + 1))")" 136BINFILE="$OUTDIR/entropy.$NUM.bin" 137METAFILE="$OUTDIR/entropy.$NUM.meta" 138 139# launch zircon 140case "$METHOD" in 141 qemu) 142 "$ZIRCONDIR/scripts/run-zircon" -a "$ARCH" -c "$CMDLINE" -N -o "$BUILDDIR" </dev/null & 143 ;; 144 netboot) 145 "$BUILDDIR/tools/bootserver" --tftp -n "$NODENAME" \ 146 "$BUILDDIR/zircon.bin" "$BUILDDIR/bootdata.bin" \ 147 -- "$CMDLINE" >/dev/null 2>/dev/null & 148 BOOTSERVER_PID=$! 149 ;; 150 *) 151 echo "unrecognized method: $METHOD" >&2 152 HELP 153 ;; 154esac 155echo "launched zircon with nodename $NODENAME" >&2 156 157# wait for zircon to send us the entropy file 158while true; do 159 sleep 5; 160 if "$BUILDDIR"/tools/netcp --nowait --timeout=1000 \ 161 "$NODENAME:/boot/kernel/debug/entropy.bin" "$BINFILE" && 162 [[ -z $LEN || $(wc -c <"$BINFILE") -eq $LEN ]] 163 then 164 echo "Finished test on nodename $NODENAME" >&2 165 break 166 fi 167done 168 169# write the meta file 170{ 171 echo "entropy-test $METHOD" 172 echo "date $(date +"%Y-%m-%d %H:%M:%S %Z")" 173 echo "buildid $BUILDID" 174 echo "arch $ARCH" 175 echo "source $SRC" 176 echo "len $LEN" 177 echo "cmdline $CMDLINE" 178} >$METAFILE 179 180# reset the test device 181case "$METHOD" in 182 qemu) 183 while "$BUILDDIR"/tools/netaddr --nowait --timeout=1000 \ 184 "$NODENAME" >/dev/null 2>/dev/null; do 185 "$BUILDDIR"/tools/netruncmd --nowait --timeout=1000 "$NODENAME" dm shutdown 186 sleep 2 187 done 188 ;; 189 netboot) 190 kill "$BOOTSERVER_PID" 191 sleep 1 # make sure bootserver actually has time to shut down 192 while "$BUILDDIR"/tools/netaddr --nowait --timeout=1000 \ 193 "$NODENAME" >/dev/null 2>/dev/null; do 194 "$BUILDDIR"/tools/netruncmd --nowait --timeout=1000 "$NODENAME" dm reboot 195 sleep 2 196 done 197 ;; 198esac 199