#!/bin/bash # Copyright 2014-2015 Holger Levsen # © 2015 Mattia Rizzolo # released under the GPLv=2 DEBUG=false . /srv/jenkins/bin/common-functions.sh common_init "$@" # common code defining db access . /srv/jenkins/bin/reproducible_common.sh set -e # build for different architectures ARCHS="i386 mips arm arm64 riscv" cleanup_tmpdir() { cd rm -r $TMPDIR } create_results_dirs() { mkdir -p $BASE/coreboot/dbd } call_debbindiff() { local TMPLOG=(mktemp --tmpdir=$TMPDIR) set +e ( timeout $TIMEOUT schroot \ --directory $TMPDIR \ -c source:jenkins-reproducible-${DBDSUITE}-debbindiff \ debbindiff -- \ --html $TMPDIR/$1.html \ $TMPDIR/b1/$1/coreboot.rom \ $TMPDIR/b2/$1/coreboot.rom 2>&1 \ ) 2>&1 >> $TMPLOG RESULT=$? if ! "$DEBUG" ; then set +x ; fi set -e cat $TMPLOG # print dbd output rm -f $TMPLOG case $RESULT in 0) echo "$(date -u) - $1/coreboot.rom is reproducible, yay!" ;; 1) echo "$(date -u) - $DBDVERSION found issues, please investigate $1/coreboot.rom" ;; 2) echo "$(date -u) - $DBDVERSION had trouble comparing the two builds. Please investigate $1/coreboot.rom" ;; 124) if [ ! -s $TMPDIR/$1.html ] ; then echo "$(date -u) - $DBDVERSION produced no output for $1/coreboot.rom and was killed after running into timeout after ${TIMEOUT}..." else local msg="$DBDVERSION was killed after running into timeout after $TIMEOUT" msg="$msg, but there is still $TMPDIR/$1.html" fi echo $msg ;; *) echo "$(date -u) - Something weird happened when running $DBDVERSION on $1/coreboot.rom (which exited with $RESULT) and I don't know how to handle it" ;; esac } # # main # TMPDIR=$(mktemp --tmpdir=/srv/reproducible-results -d) # where everything actually happens trap cleanup_tmpdir INT TERM EXIT cd $TMPDIR DATE=$(date -u +'%Y-%m-%d') START=$(date +'%s') mkdir b1 b2 echo "=============================================================================" echo "$(date -u) - Cloning the coreboot git repository with submodules now." echo "=============================================================================" git clone --recursive http://review.coreboot.org/p/coreboot.git cd coreboot # still required because coreboot moved submodules and to take care of old git versions git submodule update --init --checkout 3rdparty/blobs COREBOOT="$(git log -1)" COREBOOT_VERSION=$(git describe) NUM_CPU=$(cat /proc/cpuinfo |grep '^processor'|wc -l) echo "=============================================================================" echo "$(date -u) - Building cross compilers for ${ARCHS} now." echo "=============================================================================" GOT_XTOOLCHAIN=false set +e for ARCH in ${ARCHS} ; do echo "$(date -u) - Building cross compiler for ${ARCH}." nice ionice -c 3 make -j $NUM_CPU crossgcc-$ARCH RESULT=$? if [ $RESULT -eq 0 ] ; then GOT_XTOOLCHAIN=true fi done set -e if ! $GOT_XTOOLCHAIN ; then echo "Need at least one cross toolchain, aborting." fi echo "=============================================================================" echo "$(date -u) - Building coreboot ${COREBOOT_VERSION} images now - first build run." echo "=============================================================================" export TZ="/usr/share/zoneinfo/Etc/GMT+12" # prevent failing using more than one CPU sed -i 's#MAKE=$i#MAKE=make#' util/abuild/abuild # use all cores for first build sed -i "s#cpus=1#cpus=$NUM_CPU#" util/abuild/abuild sed -i 's#USE_XARGS=1#USE_XARGS=0#g' util/abuild/abuild # actually build everything nice ionice -c 3 \ bash util/abuild/abuild || true # don't fail the full job just because some targets fail cd coreboot-builds for i in * ; do mkdir $TMPDIR/b1/$i if [ -f $i/coreboot.rom ] ; then cp -p $i/coreboot.rom $TMPDIR/b1/$i/ fi done cd .. rm coreboot-builds -rf echo "=============================================================================" echo "$(date -u) - Building coreboot images now - second build run." echo "=============================================================================" export TZ="/usr/share/zoneinfo/Etc/GMT-14" export LANG="fr_CH.UTF-8" export LC_ALL="fr_CH.UTF-8" export PATH="/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/i/capture/the/path" export CAPTURE_ENVIRONMENT="I capture the environment" umask 0002 # use allmost all cores for second build NEW_NUM_CPU=$(echo $NUM_CPU-1|bc) sed -i "s#cpus=$NUM_CPU#cpus=$NEW_NUM_CPU#" util/abuild/abuild nice ionice -c 3 \ linux64 --uname-2.6 \ bash util/abuild/abuild || true # don't fail the full job just because some targets fail # reset environment to default values again export LANG="en_GB.UTF-8" unset LC_ALL export TZ="/usr/share/zoneinfo/UTC" export PATH="/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:" umask 0022 cd coreboot-builds for i in * ; do if [ -f $i/coreboot.rom ] ; then mkdir $TMPDIR/b2/$i cp -p $i/coreboot.rom $TMPDIR/b2/$i/ fi done cd .. rm coreboot-builds -r cd .. TIMEOUT="30m" DBDSUITE="unstable" DBDVERSION="$(schroot --directory /tmp -c source:jenkins-reproducible-${DBDSUITE}-debbindiff debbindiff -- --version 2>&1)" echo "=============================================================================" echo "$(date -u) - Running $DBDVERSION on coreboot images now" echo "=============================================================================" # and creating the webpage while we're at it PAGE=$PWD/coreboot/coreboot.html cat > $PAGE <<- EOF coreboot

 

coreboot

coreboot™: fast, flexible and reproducible Open Source firmware?

EOF write_page "

Reproducible Coreboot

" write_page "

Reproducible builds enable anyone to reproduce bit by bit identical binary packages from a given source, si that anyone can verify that a given binary derived from the source it was said to be derived. There is a lot more information about reproducible builds on the Debian wiki and on https://reproducible.debian.net.
" write_page " Reproducible Coreboot is an effort to apply this to coreboot. Thus each coreboot.rom is build twice, with a few varitations added and then those two ROMs are compared using debbindiff. Please note that more variations are to be expected in the wild.

" write_page "

This set up to test the master branch of coreboot.git monthly, but as this is brand new, currently updates are triggered more often. Patches are very much welcome, the coreboot pages are solely generated by reproducible_coreboot.sh.

" write_page "

These tests were last run on $DATE for version ${COREBOOT_VERSION}.

"
echo -n "$COREBOOT" >> $PAGE
write_page "       

" write_explaination_table coreboot write_page "
    " BAD_ROMS=0 GOOD_ROMS=0 ALL_ROMS=0 create_results_dirs cd b1 for i in * ; do let ALL_ROMS+=1 if [ -f $i/coreboot.rom ] ; then call_debbindiff $i SIZE="$(du -h -b $i/coreboot.rom | cut -f1)" SIZE="$(echo $SIZE/1024|bc)" if [ -f $TMPDIR/$i.html ] ; then mv $TMPDIR/$i.html $BASE/coreboot/dbd/$i.html write_page "
  • \"unreproducible $i (${SIZE}K) is unreproducible.
  • " else SHASUM=$(sha256sum $i/coreboot.rom|cut -d " " -f1) write_page "
  • \"reproducible $i ($SHASUM, ${SIZE}K) had no debbindiff output so it's probably reproducible :)
  • " let GOOD_ROMS+=1 fi else write_page "
  • \"FTBFS $i failed to build from source.
  • " let BAD_ROMS+=1 fi done GOOD_PERCENT=$(echo "scale=1 ; ($GOOD_ROMS*100/$ALL_ROMS)" | bc) BAD_PERCENT=$(echo "scale=1 ; ($BAD_ROMS*100/$ALL_ROMS)" | bc) write_page "

$GOOD_ROMS ($GOOD_PERCENT%) out of $ALL_ROMS built coreboot images were reproducible, while $BAD_ROMS ($BAD_PERCENT%) failed to built from source.

" cat >> $PAGE <<- EOF
EOF write_page_footer coreboot cd .. PAGE=coreboot/coreboot.html publish_page # the end calculate_build_duration print_out_duration irc_message "$REPRODUCIBLE_URL/coreboot/ has been updated." # remove coreboot tree, we don't need it anymore... rm coreboot -r cleanup_tmpdir trap - INT TERM EXIT