|
@@ -0,0 +1,668 @@
|
|
|
+#!/bin/bash
|
|
|
+# use TERM to exit on error
|
|
|
+trap "exit 1" TERM
|
|
|
+export TOP_PID=$$
|
|
|
+
|
|
|
+# coreboot repo
|
|
|
+COREBOOT_REPO_PURISM="https://source.puri.sm/coreboot/coreboot.git"
|
|
|
+COREBOOT_REPO_TAG="4.14-Purism-1"
|
|
|
+
|
|
|
+# dependencies
|
|
|
+DEPS_BASE=(dmidecode wget sha256sum gzip)
|
|
|
+DEPS_FLASH=(git build-essential libpci-dev libudev-dev zlib1g-dev)
|
|
|
+DEPS_FLASH_FEDORA=(git gcc g++ make xz bzip2 pciutils-devel)
|
|
|
+DEPS_COREBOOT=(gnat m4 bison flex libncurses5-dev python python2)
|
|
|
+DEPS_COREBOOT_FEDORA=(gcc-gnat bison flex ncurses-devel zlib-devel python python2 patch)
|
|
|
+DEPS_GRUB2=(autoconf automake autopoint libfreetype-dev fonts-unifont)
|
|
|
+DEPS_GRUB2_FEDORA=(autoconf automake gettext-devel freetype-devel unifont-fonts)
|
|
|
+
|
|
|
+#local dirs
|
|
|
+LOCAL_TOOLS_PATH="./tools"
|
|
|
+LOCAL_FIRMWARE_PATH="./firmware"
|
|
|
+LOCAL_TEMP_DIR="$(mktemp -d)"
|
|
|
+
|
|
|
+# locally compiled coreboot utils
|
|
|
+CBFSTOOL_CB="./coreboot/util/cbfstool/cbfstool"
|
|
|
+IFDTOOL_CB="./coreboot/util/ifdtool/ifdtool"
|
|
|
+
|
|
|
+# functions, functions, functions
|
|
|
+
|
|
|
+check_root() {
|
|
|
+ if [[ "$EUID" != 0 ]]; then
|
|
|
+ die "This script must be run as root; re-run prefixed with sudo"
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+print_info () {
|
|
|
+
|
|
|
+ clear
|
|
|
+ echo "################################################"
|
|
|
+ echo "## Purism Librem coreboot Utility "
|
|
|
+ echo "################################################"
|
|
|
+ if [[ "${LIBREM_MODEL^^}" != "UNKNOWN" ]]; then
|
|
|
+ model=${LIBREM_MODEL^}
|
|
|
+ echo "# Device: Librem ${model//_/ }"
|
|
|
+ echo "# Serial: ${DMIDECODE_SERIAL_NUMBER}"
|
|
|
+ echo "# Firmware: ${FW_TYPE_STRING}"
|
|
|
+ echo "# Version: ${CURRENT_FW_VER} ${CURRENT_FW_DATE}"
|
|
|
+ echo "################################################"
|
|
|
+ fi
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+initial_setup () {
|
|
|
+
|
|
|
+ # get model, firmware version, serial # via dmidecode
|
|
|
+ vendor=$(dmidecode -s bios-vendor)
|
|
|
+ model=$(dmidecode -s system-product-name | grep -i Librem)
|
|
|
+ CURRENT_FW_VER=$(dmidecode -s bios-version)
|
|
|
+ CURRENT_FW_DATE=$(dmidecode -s bios-release-date)
|
|
|
+ DMIDECODE_SERIAL_NUMBER=$(dmidecode -t 1 | grep "Serial Number" | cut -d' ' -f 3-)
|
|
|
+ # set CURRENT_FW_TYPE type
|
|
|
+ if [ "$vendor" = "coreboot" ]; then
|
|
|
+ case ${CURRENT_FW_VER^^} in
|
|
|
+ *"PUREBOOT"* )
|
|
|
+ CURRENT_FW_TYPE="HEADS";;
|
|
|
+ *"HEADS"* )
|
|
|
+ CURRENT_FW_TYPE="HEADS";;
|
|
|
+ *"GRUB2"* )
|
|
|
+ CURRENT_FW_TYPE="GRUB2";;
|
|
|
+ * )
|
|
|
+ CURRENT_FW_TYPE="STANDARD";;
|
|
|
+ esac
|
|
|
+ else
|
|
|
+ CURRENT_FW_TYPE="UNKNOWN"
|
|
|
+ fi
|
|
|
+ FW_UPDATE=""
|
|
|
+ case $CURRENT_FW_TYPE in
|
|
|
+ "HEADS" )
|
|
|
+ FW_TYPE_STRING="PureBoot (coreboot+Heads)"
|
|
|
+ CURR_FW_NUM=`echo ${CURRENT_FW_VER} | sed -e "s/^PureBoot-beta-//" -e "s/^PureBoot-Release-//"`
|
|
|
+ UPD_FW_NUM=`echo ${COREBOOT_HEADS_VERSION} | sed -e "s/^PureBoot-beta-//" -e "s/^PureBoot-Release-//"`
|
|
|
+ [[ "$UPD_FW_NUM" > "$CURR_FW_NUM" ]] \
|
|
|
+ && FW_UPDATE=`echo ${COREBOOT_HEADS_VERSION} | tr '-' ' '`
|
|
|
+ CURRENT_FW_VER=`echo ${CURRENT_FW_VER#PureBoot-} | tr '-' ' '`
|
|
|
+ CURRENT_FW_DATE=""
|
|
|
+ ;;
|
|
|
+ "STANDARD" )
|
|
|
+ FW_TYPE_STRING="Standard (coreboot+SeaBIOS)"
|
|
|
+ [[ "$COREBOOT_SEABIOS_VERSION" > "$CURRENT_FW_VER" ]] \
|
|
|
+ && FW_UPDATE="$COREBOOT_SEABIOS_VERSION";
|
|
|
+ CURRENT_FW_DATE="(${CURRENT_FW_DATE})"
|
|
|
+ ;;
|
|
|
+ "GRUB2" )
|
|
|
+ FW_TYPE_STRING="Grub2 (coreboot+Grub2)"
|
|
|
+ [[ "$COREBOOT_GRUB2_VERSION" > "$CURRENT_FW_VER" ]] \
|
|
|
+ && FW_UPDATE="$COREBOOT_GRUB2_VERSION";
|
|
|
+ CURRENT_FW_DATE="(${CURRENT_FW_DATE})"
|
|
|
+ ;;
|
|
|
+
|
|
|
+
|
|
|
+ * )
|
|
|
+ FW_TYPE_STRING="Unknown" ;;
|
|
|
+ esac
|
|
|
+
|
|
|
+ # set LIBREM_MODEL, MODEL_INDEX
|
|
|
+ # strip leading 'librem' + space/underscore
|
|
|
+ model=`echo ${model,,} | sed -e "s/^librem//" -e "s/^ //" -e "s/^_//"`
|
|
|
+ case ${model} in
|
|
|
+ "14")
|
|
|
+ LIBREM_MODEL="14";
|
|
|
+ PLATFORM="CML";
|
|
|
+ MODEL_INDEX="9";;
|
|
|
+ *)
|
|
|
+ LIBREM_MODEL="unknown";
|
|
|
+ PLATFORM="UNK";
|
|
|
+ MODEL_INDEX="0";;
|
|
|
+ esac
|
|
|
+}
|
|
|
+
|
|
|
+cleanup() {
|
|
|
+ # ensure all files owned by calling/non-root user
|
|
|
+ chown -R -f $(logname). .
|
|
|
+}
|
|
|
+
|
|
|
+die () {
|
|
|
+ local msg=$1
|
|
|
+
|
|
|
+ if [ ! -z "$msg" ]; then
|
|
|
+ echo ""
|
|
|
+ echo -e "$msg"
|
|
|
+ echo ""
|
|
|
+ fi
|
|
|
+ kill -s TERM $TOP_PID
|
|
|
+ cleanup
|
|
|
+ exit 1
|
|
|
+}
|
|
|
+
|
|
|
+get_flashrom () {
|
|
|
+ # check if flashrom exists on system
|
|
|
+ echo ""
|
|
|
+ echo "Checking for usable version of flashrom"
|
|
|
+ FLASHROM_CMD=$(which flashrom)
|
|
|
+ if [[ ! -z "$FLASHROM_CMD" && "$PLATFORM" != "CML" ]]; then
|
|
|
+ #check version
|
|
|
+ version=$($FLASHROM_CMD -R | awk -F" " '{print $2;exit}' | grep "1.")
|
|
|
+ if [[ "$version" > "v1.1" ]]; then
|
|
|
+ # verify build supports logging (some PureOS/Debian versions broken)
|
|
|
+ if $FLASHROM_CMD -L -o /tmp/flashrom.log >/dev/null 2>&1 ; then
|
|
|
+ #use system flashrom
|
|
|
+ echo "Found built-in flashrom version $version"
|
|
|
+ return
|
|
|
+ fi
|
|
|
+ fi
|
|
|
+ fi
|
|
|
+
|
|
|
+ # no system flashrom, not version 1.2+, or PLATFORM == CML:
|
|
|
+ # build from upstream flashrom source
|
|
|
+
|
|
|
+ # check deps first
|
|
|
+ check_dependencies "flashrom"
|
|
|
+ if [ ! -d ${LOCAL_TOOLS_PATH}/flashrom ]; then
|
|
|
+ (
|
|
|
+ mkdir -p ${LOCAL_TOOLS_PATH}
|
|
|
+ cd ${LOCAL_TOOLS_PATH}
|
|
|
+ echo -n "Cloning flashrom git repo..."
|
|
|
+ git clone --single-branch --branch master https://review.coreboot.org/flashrom.git >/dev/null
|
|
|
+ [ $? -ne 0 ] && die "Error cloning flashrom repo from git"
|
|
|
+ echo "done"
|
|
|
+ )
|
|
|
+ fi
|
|
|
+ (
|
|
|
+ echo -n "Building flashrom from source..."
|
|
|
+ cd ${LOCAL_TOOLS_PATH}/flashrom
|
|
|
+ git fetch origin >/dev/null 2>&1
|
|
|
+ if ! git show c64486b >/dev/null 2>&1; then
|
|
|
+ cd ..
|
|
|
+ rm -rf ./flashrom
|
|
|
+ git clone --single-branch --branch master https://review.coreboot.org/flashrom.git >/dev/null
|
|
|
+ [ $? -ne 0 ] && die "Error cloning flashrom repo from git"
|
|
|
+ cd flashrom
|
|
|
+ fi
|
|
|
+ git reset --hard c64486b >/dev/null 2>&1
|
|
|
+ [ $? -ne 0 ] && die "Error checking out flashrom via git"
|
|
|
+ make CONFIG_NOTHING=yes CONFIG_DUMMY=yes CONFIG_INTERNAL=yes WARNERROR=no
|
|
|
+ [ $? -ne 0 ] && die "Error building flashrom (missing build dependency libpci-dev?)"
|
|
|
+ echo "done"
|
|
|
+ )
|
|
|
+ FLASHROM_CMD="${LOCAL_TOOLS_PATH}/flashrom/flashrom"
|
|
|
+}
|
|
|
+
|
|
|
+get_serial () {
|
|
|
+ if [ "$PLATFORM" = "BDW" ]; then
|
|
|
+ #no serial to set, clear file if exists
|
|
|
+ rm -f ${LOCAL_TEMP_DIR}/serial_number.txt >/dev/null
|
|
|
+ return;
|
|
|
+ fi
|
|
|
+ #prompt user for serial # selection/entry
|
|
|
+ echo ""
|
|
|
+ echo "Set the device serial number:"
|
|
|
+ echo ""
|
|
|
+ if [ "$DMIDECODE_SERIAL_NUMBER" != "" ]; then
|
|
|
+ DMIDECODE_SERIAL_OPT=1
|
|
|
+ MANUAL_SERIAL_OPT=2
|
|
|
+ NO_SERIAL_OPT=3
|
|
|
+ echo "${DMIDECODE_SERIAL_OPT} - Extracted from your local system (${DMIDECODE_SERIAL_NUMBER})"
|
|
|
+ else
|
|
|
+ DMIDECODE_SERIAL_OPT=0
|
|
|
+ MANUAL_SERIAL_OPT=1
|
|
|
+ NO_SERIAL_OPT=2
|
|
|
+ fi
|
|
|
+ echo "${MANUAL_SERIAL_OPT} - Enter serial number manually"
|
|
|
+ echo "${NO_SERIAL_OPT} - Do not set a serial number"
|
|
|
+ echo ""
|
|
|
+
|
|
|
+ serial=0
|
|
|
+ [ ${MODEL_INDEX} = 0 ] && default=2 || default=1
|
|
|
+ while [ "$serial" == "0" ]; do
|
|
|
+ read -r -p "Enter your choice (default: $default): " serial
|
|
|
+ [ "$serial" = "" ] && serial=$default
|
|
|
+ case $serial in
|
|
|
+ ${DMIDECODE_SERIAL_OPT} )
|
|
|
+ if [ "$DMIDECODE_SERIAL_OPT" = 1 ]; then
|
|
|
+ echo -n "$DMIDECODE_SERIAL_NUMBER" > ${LOCAL_TEMP_DIR}/serial_number.txt
|
|
|
+ else
|
|
|
+ echo "Invalid option"
|
|
|
+ serial=0
|
|
|
+ fi
|
|
|
+ ;;
|
|
|
+ ${MANUAL_SERIAL_OPT} )
|
|
|
+ read -r -p "Enter the machine's serial number : " serial_number
|
|
|
+ echo -n "$serial_number" > ${LOCAL_TEMP_DIR}/serial_number.txt
|
|
|
+ ;;
|
|
|
+ ${NO_SERIAL_OPT} )
|
|
|
+ echo -n "" > ${LOCAL_TEMP_DIR}/serial_number.txt
|
|
|
+ ;;
|
|
|
+ * )
|
|
|
+ echo "Invalid option"
|
|
|
+ serial=0
|
|
|
+ ;;
|
|
|
+ esac
|
|
|
+ done
|
|
|
+ echo ""
|
|
|
+}
|
|
|
+
|
|
|
+flashrom_progress() {
|
|
|
+ local current=0
|
|
|
+ local total_bytes=0
|
|
|
+ local percent=0
|
|
|
+ local IN=''
|
|
|
+ local spin='-\|/'
|
|
|
+ local spin_idx=0
|
|
|
+ local progressbar=''
|
|
|
+ local progressbar2=''
|
|
|
+ local status='init'
|
|
|
+ local prev_word=''
|
|
|
+ local prev_prev_word=''
|
|
|
+
|
|
|
+ progressbar2=$(for ((i=0; i < 49; i++)) do echo -ne ' ' ; done)
|
|
|
+ echo "Initializing internal Flash Programmer"
|
|
|
+ while true ; do
|
|
|
+ prev_prev_word=$prev_word
|
|
|
+ prev_word=$IN
|
|
|
+ read -r -d' ' IN || break
|
|
|
+ if [ "$total_bytes" != "0" ]; then
|
|
|
+ current=$(echo "$IN" | grep -E -o '0x[0-9a-f]+-0x[0-9a-f]+:.*' | grep -E -o "0x[0-9a-f]+" | tail -n 1)
|
|
|
+ if [ "${current}" != "" ]; then
|
|
|
+ percent=$((100 * (current + 1) / total_bytes))
|
|
|
+ progressbar=$(for ((i=0; i < $((percent / 2)); i++)) do echo -ne '#' ; done)
|
|
|
+ progressbar2=$(for ((i=0; i < $((49 - percent / 2)); i++)) do echo -ne ' ' ; done)
|
|
|
+ fi
|
|
|
+ else
|
|
|
+ if [ "$prev_prev_word" == "Reading" ] && [ "$IN" == "bytes" ]; then
|
|
|
+ total_bytes=$prev_word
|
|
|
+ echo "Total flash size : $total_bytes bytes"
|
|
|
+ fi
|
|
|
+ fi
|
|
|
+ if [ "$percent" -eq 100 ]; then
|
|
|
+ spin_idx=4
|
|
|
+ else
|
|
|
+ spin_idx=$(( (spin_idx+1) %4 ))
|
|
|
+ fi
|
|
|
+ if [ "$status" == "init" ]; then
|
|
|
+ if [ "$IN" == "contents..." ]; then
|
|
|
+ status="reading"
|
|
|
+ echo "Reading old flash contents. Please wait..."
|
|
|
+ fi
|
|
|
+ fi
|
|
|
+ if [ "$status" == "reading" ]; then
|
|
|
+ if echo "${IN}" | grep "done." > /dev/null ; then
|
|
|
+ status="writing"
|
|
|
+ fi
|
|
|
+ fi
|
|
|
+ if [ "$status" == "writing" ]; then
|
|
|
+ echo -ne "Flashing: [${progressbar}${spin:$spin_idx:1}${progressbar2}] (${percent}%)\\r"
|
|
|
+ if echo "$IN" | grep "Verifying" > /dev/null ; then
|
|
|
+ status="verifying"
|
|
|
+ echo ""
|
|
|
+ echo "Verifying flash contents. Please wait..."
|
|
|
+ fi
|
|
|
+ if echo "$IN" | grep "identical" > /dev/null ; then
|
|
|
+ status="done"
|
|
|
+ echo ""
|
|
|
+ echo "The flash contents are identical to the image being flashed."
|
|
|
+ fi
|
|
|
+ fi
|
|
|
+ if [ "$status" == "verifying" ]; then
|
|
|
+ if echo "${IN}" | grep "VERIFIED." > /dev/null ; then
|
|
|
+ status="done"
|
|
|
+ echo "The flash contents were verified and the image was flashed correctly."
|
|
|
+ fi
|
|
|
+ fi
|
|
|
+ done
|
|
|
+ echo ""
|
|
|
+ if [ "$status" == "done" ]; then
|
|
|
+ return 0
|
|
|
+ else
|
|
|
+ echo 'Error flashing coreboot -- see timestampped flashrom log in current directory for more info'
|
|
|
+ echo ""
|
|
|
+ return 1
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+set_serial_number () {
|
|
|
+ # pass in full path of file in which to inject serial
|
|
|
+ [[ -z "$1" || ! -f "$1" ]] && die "Error: a valid firmware filename is required"
|
|
|
+
|
|
|
+ # check if we have a serial # to add to cbfs
|
|
|
+ if [ -f ${LOCAL_TEMP_DIR}/serial_number.txt ]; then
|
|
|
+ # get cbfstool if needed
|
|
|
+ get_cbfstool
|
|
|
+ # inject serial into coreboot image
|
|
|
+ echo "Injecting serial number into firmware image"
|
|
|
+ $CBFSTOOL_BIN "$1" remove -n serial_number -r COREBOOT >/dev/null 2>&1
|
|
|
+ $CBFSTOOL_BIN "$1" add -n serial_number -t raw -f ${LOCAL_TEMP_DIR}/serial_number.txt -r COREBOOT >/dev/null 2>&1
|
|
|
+ [ $? -ne 0 ] && die "Error adding serial number to file ${1}"
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+backup_firmware () {
|
|
|
+
|
|
|
+ # assume FLASHROM_CMD exists/is set already, LOCAL_TEMP_DIR set up
|
|
|
+ mkdir -p ${BACKUP_DIR}
|
|
|
+ DATE_FIX=$(date '+%Y%m%d-%H%M%S')
|
|
|
+ $FLASHROM_CMD -p internal:ich_spi_mode=hwseq -r ${BACKUP_DIR}/backup-${DATE_FIX}.bin -o ${BACKUP_DIR}/backup-$(date '+%Y%m%d-%H%M%S').log >/dev/null 2>&1
|
|
|
+ if [ $? -ne 0 ]; then
|
|
|
+ die "Error reading current firmware; see flashrom log for more info."
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+flash_firmware_internal () {
|
|
|
+ # assume FLASHROM_CMD exists/is set already
|
|
|
+ # pass in full path of file to be flashed
|
|
|
+ [[ -z "$1" || ! -f "$1" ]] && die "Error: a valid filename to be flashed is required"
|
|
|
+ $FLASHROM_CMD -p internal:ich_spi_mode=hwseq -w "$1" -V -o "./flashrom-$(date '+%Y%m%d-%H%M%S').log" 2>&1 | flashrom_progress
|
|
|
+ return $?
|
|
|
+}
|
|
|
+
|
|
|
+update_serial_number () {
|
|
|
+
|
|
|
+ # ensure using SeaBIOS
|
|
|
+ if [[ "${CURRENT_FW_TYPE}" != "STANDARD" ]]; then
|
|
|
+ echo "This feature is only valid for use with the standard/SeaBIOS firmware"
|
|
|
+ echo ""
|
|
|
+ return
|
|
|
+ fi
|
|
|
+
|
|
|
+ # show serial menu / create serial.txt
|
|
|
+ get_serial
|
|
|
+
|
|
|
+ # check for / get flashrom
|
|
|
+ get_flashrom
|
|
|
+
|
|
|
+ # read current firmware
|
|
|
+ echo ""
|
|
|
+ if [ ! -f ${LOCAL_TEMP_DIR}/${CURRENT_FW_BIN} ]; then
|
|
|
+ echo "Reading current firmware..."
|
|
|
+ read_current_firmware
|
|
|
+ else
|
|
|
+ echo "Current firmware already read from flash"
|
|
|
+ fi
|
|
|
+
|
|
|
+ # inject into current firmware
|
|
|
+ set_serial_number "${LOCAL_TEMP_DIR}/${CURRENT_FW_BIN}"
|
|
|
+
|
|
|
+ # prompt to update
|
|
|
+ echo ""
|
|
|
+ flash=0
|
|
|
+ while [ "$flash" != "y" ] && [ "$flash" != "n" ]; do
|
|
|
+ read -r -p "Do you want to update the serial number now (Y/n) ? " flash
|
|
|
+ [[ "$flash" == "N" ]] && flash="n"
|
|
|
+ [[ "$flash" = "" || "$flash" == "Y" ]] && flash="y"
|
|
|
+ done
|
|
|
+ if [ "$flash" == "y" ]; then
|
|
|
+ echo ""
|
|
|
+ echo "coreboot flashing in progress. Do NOT interrupt this process."
|
|
|
+ echo ""
|
|
|
+ flash_firmware_internal "${LOCAL_TEMP_DIR}/${CURRENT_FW_BIN}"
|
|
|
+ if [ $? -eq 0 ]; then
|
|
|
+ echo "Serial number successfully updated; change will take effect on next boot"
|
|
|
+ echo ""
|
|
|
+ fi
|
|
|
+ fi
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+update_crossgcc_toolchain() {
|
|
|
+ # assume called from coreboot root dir
|
|
|
+
|
|
|
+ local CURRENT_TOOLCHAIN_VERSION=0
|
|
|
+ local GCC_FILE='util/crossgcc/xgcc/bin/i386-elf-gcc'
|
|
|
+ local TARGET_TOOLCHAIN_VERSION="$(git log -n 1 --pretty=%h util/crossgcc)"
|
|
|
+
|
|
|
+ if [ -f "${GCC_FILE}" ]; then
|
|
|
+ CURRENT_TOOLCHAIN_VERSION=$(${GCC_FILE} --version | grep -m 1 'coreboot toolchain' \
|
|
|
+ | cut -f2 -d'v' | cut -f2 -d'_' | cut -f1 -d')')
|
|
|
+ fi
|
|
|
+ if [ "${CURRENT_TOOLCHAIN_VERSION}" != "${TARGET_TOOLCHAIN_VERSION}" ]; then
|
|
|
+ echo "coreboot toolchain version changed from ${CURRENT_TOOLCHAIN_VERSION} to ${TARGET_TOOLCHAIN_VERSION}"
|
|
|
+ echo "Cleaning crossgcc compiler before rebuilding it"
|
|
|
+ make crossgcc-clean
|
|
|
+ retries=0
|
|
|
+ until [ "$retries" -ge 5 ]
|
|
|
+ do
|
|
|
+ make crossgcc-i386 CPUS=$(nproc) && break
|
|
|
+ retries=$((retries+1))
|
|
|
+ done
|
|
|
+ [ $? -ne 0 ] && die "Error building coreboot toolchain" || true
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+build_coreboot() {
|
|
|
+
|
|
|
+ # extract / set device serial # to be injected later
|
|
|
+ get_serial
|
|
|
+
|
|
|
+ echo ""
|
|
|
+ echo "Checking out/updating coreboot repo..."
|
|
|
+ echo ""
|
|
|
+
|
|
|
+ # check dir, clone if needed
|
|
|
+ if [ ! -d coreboot ]; then
|
|
|
+ echo ""
|
|
|
+ git clone --branch ${COREBOOT_REPO_TAG} ${COREBOOT_REPO_PURISM} coreboot
|
|
|
+ [ $? -ne 0 ] && die "Error cloning coreboot git repo"
|
|
|
+ (
|
|
|
+ cd coreboot
|
|
|
+ # It can fail if you don't have a git global user.name/user.email setup
|
|
|
+ make gitconfig 2>/dev/null || true
|
|
|
+ # init/update submodules
|
|
|
+ git submodule update --init --force --checkout >/dev/null 2>&1
|
|
|
+ [ $? -ne 0 ] && die "Error checking out/updating coreboot submodules"
|
|
|
+ )
|
|
|
+ fi
|
|
|
+
|
|
|
+ # check out correct branch
|
|
|
+ (
|
|
|
+ cd coreboot
|
|
|
+ git fetch 2>/dev/null
|
|
|
+ [ $? -ne 0 ] && die "Error fetching coreboot git repo"
|
|
|
+ git fetch --tags 2>/dev/null
|
|
|
+ [ $? -ne 0 ] && die "Error fetching coreboot git repo"
|
|
|
+ git checkout --detach ${COREBOOT_REPO_TAG} 2>/dev/null
|
|
|
+ [ $? -ne 0 ] && die "Error checking out coreboot git repo"
|
|
|
+
|
|
|
+ # ensure submodules sane
|
|
|
+ if [[ "`git diff 3rdparty`" != "" ]]; then
|
|
|
+ git submodule update --force --checkout >/dev/null 2>&1
|
|
|
+ [[ "`git diff 3rdparty`" != "" ]] && \
|
|
|
+ die "submodules have been modified; build would not be reproducible"
|
|
|
+ fi
|
|
|
+
|
|
|
+ #build cbfstool and ifdtool
|
|
|
+ (
|
|
|
+ cd util/cbfstool
|
|
|
+ make
|
|
|
+ [ $? -ne 0 ] && die "Error building cbfstool"
|
|
|
+ )
|
|
|
+ (
|
|
|
+ cd util/ifdtool
|
|
|
+ make
|
|
|
+ [ $? -ne 0 ] && die "Error building ifdtool"
|
|
|
+ )
|
|
|
+ )
|
|
|
+
|
|
|
+ # build coreboot
|
|
|
+ (
|
|
|
+ # set pwd
|
|
|
+ cd coreboot
|
|
|
+
|
|
|
+ # let user know this will take a few
|
|
|
+ echo -e "\n\n"
|
|
|
+ echo "Ready to build coreboot - this will take some time depending on your connection"
|
|
|
+ echo "speed and CPU/RAM, esp if the toolchain needs to be built."
|
|
|
+ echo ""
|
|
|
+
|
|
|
+ # check/build toolchain
|
|
|
+ update_crossgcc_toolchain || die
|
|
|
+
|
|
|
+ # get git version
|
|
|
+ GIT_VERSION=$(git describe --tags --dirty)
|
|
|
+
|
|
|
+ # do a clean build
|
|
|
+ make distclean
|
|
|
+ # copy config
|
|
|
+ cp ../resources/config .config
|
|
|
+ # copt grub config
|
|
|
+ cp ../resources/grub.cfg grub.cfg
|
|
|
+ echo "CONFIG_LOCALVERSION=\"${GIT_VERSION}\"" >> .config
|
|
|
+ make olddefconfig >/dev/null
|
|
|
+ # build coreboot and payload(s)
|
|
|
+ make
|
|
|
+ [ $? -ne 0 ] && die "Error building coreboot"
|
|
|
+ # copy to root dir
|
|
|
+ #cp build/coreboot.rom ../${COREBOOT_IMAGE}
|
|
|
+ )
|
|
|
+
|
|
|
+ # calculate hash of BIOS region before injecting bootorder/serial
|
|
|
+ ${IFDTOOL_CB} -x ${COREBOOT_IMAGE}
|
|
|
+ bios_sha=$(sha256sum flashregion_1_bios.bin | awk '{print $1}')
|
|
|
+ rm -f flashregion*.bin
|
|
|
+
|
|
|
+ # set serial
|
|
|
+ set_serial_number ${COREBOOT_IMAGE}
|
|
|
+
|
|
|
+ #set boot delay
|
|
|
+ # add an 8s boot delay for the Librem Mini so splash screen
|
|
|
+ # actually shown on displays with sluggish init
|
|
|
+ if [[ ${LIBREM_MODEL^^} == "MINI"* ]]; then
|
|
|
+ ${CBFSTOOL_CB} ${COREBOOT_IMAGE} add-int -i 8000 -n etc/boot-menu-wait >/dev/null
|
|
|
+ fi
|
|
|
+ # print CBFS contents
|
|
|
+ ${CBFSTOOL_CB} ${COREBOOT_IMAGE} print
|
|
|
+
|
|
|
+ echo ""
|
|
|
+ echo ""
|
|
|
+ echo "Finished building coreboot for Librem ${LIBREM_MODEL^}"
|
|
|
+ echo ""
|
|
|
+ COREBOOT_BIOS_SHA="COREBOOT_BIOS_SHA_${LIBREM_MODEL^^}"
|
|
|
+ COREBOOT_BIOS_SHA=${!COREBOOT_BIOS_SHA}
|
|
|
+ if [ "${bios_sha}" != "${COREBOOT_BIOS_SHA}" ]; then
|
|
|
+ echo "WARNING: Built coreboot image hash does not match expected reproducible build hash"
|
|
|
+ echo "Built: ${bios_sha}"
|
|
|
+ echo "Expected: ${COREBOOT_BIOS_SHA}"
|
|
|
+ else
|
|
|
+ echo "Built coreboot image hash matches expected reproducible build hash"
|
|
|
+ fi
|
|
|
+
|
|
|
+ # prompt to flash
|
|
|
+ echo ""
|
|
|
+ if [ ${CURRENT_FW_TYPE} != "HEADS" ]; then
|
|
|
+ flash=0
|
|
|
+ while [ "$flash" != "y" ] && [ "$flash" != "n" ]; do
|
|
|
+ read -r -p "Do you want to flash the coreboot update now (y/N) ? " flash
|
|
|
+ if [ "$flash" = "" ] || [ "$flash" == "N" ]; then
|
|
|
+ flash="n"
|
|
|
+ fi
|
|
|
+ if [ "$flash" == "Y" ]; then
|
|
|
+ flash="y"
|
|
|
+ fi
|
|
|
+ done
|
|
|
+ if [ "$flash" == "y" ]; then
|
|
|
+ # check for / get flashrom
|
|
|
+ get_flashrom
|
|
|
+ echo ""
|
|
|
+ echo "coreboot flashing in progress. Do NOT interrupt this process."
|
|
|
+ echo ""
|
|
|
+ flash_firmware_internal ${COREBOOT_IMAGE}
|
|
|
+ if [ $? -eq 0 ]; then
|
|
|
+ echo ""
|
|
|
+ echo "You must reboot for the coreboot update to take effect."
|
|
|
+ echo ""
|
|
|
+ read -r -p "Reboot now? (y/N) ? " rb
|
|
|
+ if [ "$rb" = "Y" ] || [ "$rb" == "y" ]; then
|
|
|
+ cleanup
|
|
|
+ reboot
|
|
|
+ fi
|
|
|
+ fi
|
|
|
+ else
|
|
|
+ echo ""
|
|
|
+ fi
|
|
|
+ else
|
|
|
+ echo "You may now copy the coreboot update file ($COREBOOT_IMAGE) to USB for updating via Heads."
|
|
|
+ echo ""
|
|
|
+ read -ep "Press [Enter] to exit."
|
|
|
+ cleanup
|
|
|
+ exit 0
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+check_dependencies() {
|
|
|
+
|
|
|
+ local dep_type=$1
|
|
|
+ local DEPS
|
|
|
+ local use_dnf=false
|
|
|
+ [[ `which dnf 2>/dev/null` ]] && use_dnf=true
|
|
|
+
|
|
|
+ case $dep_type in
|
|
|
+ "base")
|
|
|
+ DEPS=${DEPS_BASE[@]} ;;
|
|
|
+ "flashrom")
|
|
|
+ if [ $use_dnf = true ]; then
|
|
|
+ DEPS=(${DEPS_BASE[@]} ${DEPS_FLASH_FEDORA[@]}) ;
|
|
|
+ else
|
|
|
+ DEPS=(${DEPS_BASE[@]} ${DEPS_FLASH[@]}) ;
|
|
|
+ fi
|
|
|
+ ;;
|
|
|
+ "coreboot")
|
|
|
+ if [ $use_dnf = true ]; then
|
|
|
+ DEPS=(${DEPS_BASE[@]} ${DEPS_FLASH_FEDORA[@]} ${DEPS_GRUB2_FEDORA[@]}) ;
|
|
|
+ else
|
|
|
+ DEPS=(${DEPS_BASE[@]} ${DEPS_FLASH[@]} ${DEPS_COREBOOT[@]} ${DEPS_GRUB2[@]}) ;
|
|
|
+ fi
|
|
|
+ ;;
|
|
|
+ *)
|
|
|
+ ;;
|
|
|
+ esac
|
|
|
+
|
|
|
+ local pkg needed=()
|
|
|
+ for pkg in "${DEPS[@]}"; do
|
|
|
+ if [[ ! `which ${pkg} 2>/dev/null` \
|
|
|
+ && ! `dnf list installed 2>/dev/null | grep "^${pkg}"` \
|
|
|
+ && ! `apt list --installed 2>/dev/null | grep "^${pkg}"` \
|
|
|
+ && ! -f "/usr/share/doc/${pkg}/copyright" ]]; then
|
|
|
+ needed+=("${pkg}")
|
|
|
+ fi
|
|
|
+ done
|
|
|
+ if [[ "${#needed[@]}" -gt 0 ]]; then
|
|
|
+ echo ""
|
|
|
+ echo "One or more required dependencies are missing: ${needed[@]}"
|
|
|
+ echo "The script will now attempt to install them for you"
|
|
|
+ echo ""
|
|
|
+ read -rp "Press [Enter] to continue " discard
|
|
|
+ echo ""
|
|
|
+ if [ $use_dnf = true ]; then
|
|
|
+ if ! sudo dnf -y install "${needed[@]}" ; then
|
|
|
+ die "Some required dependencies could not be installed automatically"
|
|
|
+ fi
|
|
|
+ elif which apt >/dev/null ; then
|
|
|
+ sudo apt-get update >/dev/null 2>&1
|
|
|
+ if ! sudo apt-get -y install "${needed[@]}" ; then
|
|
|
+ die "Some required dependencies could not be installed automatically"
|
|
|
+ fi
|
|
|
+ else
|
|
|
+ echo "The script was unable to install the required dependencies automatically"
|
|
|
+ echo ""
|
|
|
+ die "Please ensure all required dependencies are installed and re-run this script"
|
|
|
+ fi
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+# Start of main script
|
|
|
+# let's do stuff
|
|
|
+
|
|
|
+check_root
|
|
|
+
|
|
|
+check_dependencies "base"
|
|
|
+
|
|
|
+check_dependencies "flashrom"
|
|
|
+
|
|
|
+check_dependencies "coreboot"
|
|
|
+
|
|
|
+initial_setup
|
|
|
+
|
|
|
+print_info
|
|
|
+
|
|
|
+get_flashrom
|
|
|
+
|
|
|
+build_coreboot
|