#!/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-elf x86_64-elf armv7a-eabi aarch64-elf mipsel-elf riscv-elf" cleanup_tmpdir() { cd rm -r $TMPDIR } create_results_dirs() { mkdir -p $BASE/coreboot/dbd } call_debbindiff() { local TMPLOG=(mktemp --tmpdir=$TMPDIR) local msg="" 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) msg="$(date -u) - $DBDVERSION had trouble comparing the two builds. Please investigate $1/coreboot.rom" ;; 124) if [ ! -s $TMPDIR/$1.html ] ; then msg="$(date -u) - $DBDVERSION produced no output for $1/coreboot.rom and was killed after running into timeout after ${TIMEOUT}..." else msg="$DBDVERSION was killed after running into timeout after $TIMEOUT, but there is still $TMPDIR/$1.html" fi ;; *) msg="$(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 if [ ! -z $msg ] ; then echo $msg | tee -a $TMPDIR/$1.html fi } # # 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) echo "This is coreboot $COREBOOT_VERSION." echo git log -1 NUM_CPU=$(cat /proc/cpuinfo |grep '^processor'|wc -l) echo "=============================================================================" echo "$(date -u) - Building cross compilers for ${ARCHS} now." GOT_XTOOLCHAIN=false # # build the cross toolchains # set +e for ARCH in ${ARCHS} ; do echo "=============================================================================" echo "$(date -u) - Building cross compiler for ${ARCH}." # taken from util/crossgcc/Makefile: nice ionice -c 3 bash util/crossgcc/buildgcc -j $NUM_CPU -p $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 # # create html about toolchains used # TOOLCHAIN_HTML=$(mktemp) echo "" > $TOOLCHAIN_HTML cd util/crossgcc/tarballs for i in * ; do echo " " >> $TOOLCHAIN_HTML done echo "
cross toolchain sourcesha256sum
$i" >> $TOOLCHAIN_HTML sha256sum $i | cut -d " " -f1 >> $TOOLCHAIN_HTML echo "
" >> $TOOLCHAIN_HTML echo "" >> $TOOLCHAIN_HTML for i in gcc g++ make cmake flex bison iasl ; do echo " " >> $TOOLCHAIN_HTML done echo "
Debian $(cat /etc/debian_version) package on $(dpkg --print-architecture)installed version
$i" >> $TOOLCHAIN_HTML dpkg -s $i|grep '^Version'|cut -d " " -f2 >> $TOOLCHAIN_HTML echo "
" >> $TOOLCHAIN_HTML cd ../../.. 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 --payloads none || true # don't fail the full job just because some targets fail cd coreboot-builds for i in * ; do # abuild and sharedutils are build results but not the results we are looking for... if [ "$i" != "abuild" ] && [ "$i" != "sharedutils" ] ; then mkdir $TMPDIR/b1/$i if [ -f $i/coreboot.rom ] ; then cp -p $i/coreboot.rom $TMPDIR/b1/$i/ fi 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 --payloads none || 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, so 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. The wiki has a lot more information, eg. why this is useful, what common issues exist and which workaround and solutions are known.
" write_page " Reproducible Coreboot is an effort to apply this to coreboot. Thus each coreboot.rom is build twice (without payloads), with a few varitations added and then those two ROMs are compared using debbindiff. Please note that the toolchain is not varied at all as the rebuild happens on exactly the same system. More variations are expected to be seen in the wild.

" write_page "

There is a monthly run jenkins job to test the master branch of coreboot.git. Currently this job is triggered more often though, because this is still under development and brand new. The jenkins job is simply running reproducible_coreboot.sh in a Debian environemnt and this script is solely responsible for creating this page. Feel invited to join #debian-reproducible (on irc.oftc.net) to request job runs whenever sensible. Patches and other feedback are very much appreciated!

" write_page "

"
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) is reproducible.
  • " let GOOD_ROMS+=1 rm -f $BASE/coreboot/dbd/$i.html # cleanup from previous (unreproducible) tests - if needed 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 in our test setup, while $BAD_ROMS ($BAD_PERCENT%) failed to build from source." write_page " These tests were last run on $DATE for version ${COREBOOT_VERSION}.

" cat $TOOLCHAIN_HTML >> $PAGE rm -f $TOOLCHAIN_HTML write_page "
" 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." echo "=============================================================================" # remove coreboot tree, we don't need it anymore... rm coreboot -r cleanup_tmpdir trap - INT TERM EXIT