#!/usr/bin/env bash # helper script: download coreboot # # Copyright (C) 2014, 2015, 2016, 2020, 2021 Leah Rowe # Copyright (C) 2022 Alper Nebi Yasak # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # [ "x${DEBUG+set}" = 'xset' ] && set -v set -u -e list_supported_boards() { for board in resources/coreboot/*; do echo $board | sed 's#resources/coreboot/##' done } usage() { progname="./download coreboot" printf "Usage:\n" printf "\t%s # %s\n" \ "${progname}" \ "Download and deblob Coreboot for all the boards" printf "\t%s [board [board] ...] # %s\n" \ "${progname}" \ "Download and deblob Coreboot for the given boards" printf "\t%s --list-boards # %s\n" \ "${progname}" \ "Prints this help" printf "\t%s --help # %s\n" \ "${progname}" \ "List supported boards" printf "\t%s --help # %s\n" \ "${progname}" \ "Prints this help" } # In this script, set -u is used to check for undefined variables, and # the test command doesn't do any lazy evaluation, so we can't use # a syntax like that: [ $# -eq 1 -a "$1" == "--help" ]. if [ $# -eq 1 ] && [ "$1" == "--help" ] ; then usage exit 0 elif [ $# -eq 1 ] && [ "$1" == "--list-boards" ] ; then list_supported_boards exit 0 fi # set this when you want to modify each coreboot tree # for example, you want to test custom patches # NODELETE= ./download coreboot deletegit="true" deleteblobs="true" if [ "x${NODELETE+set}" = 'xset' ]; then [ "x${NODELETE:-all}" = "xgit" ] && deletegit="false" [ "x${NODELETE:-all}" = "xall" ] && deleteblobs="false" && deletegit="false" fi # Error handling is extreme in this script. # This script handles the internet, and Git. Both are inherently unreliable. [[ -f build_error ]] && rm -f build_error rm -f resources/coreboot/*/seen downloadfor() { board="${1}" cbtree="undefined" cbrevision="undefined" # The loop will always exit, but this while loop is crafted # such that a tree referencing a tree that references another tree is possible # (and so on) while true; do cbrevision="undefined" cbtree="undefined" if [ ! -f "resources/coreboot/${board}/board.cfg" ]; then printf "ERROR: download/coreboot: board.cfg does not exist for '%s'\n" "${board}" return 1 fi if [ -f "resources/coreboot/${board}/seen" ]; then printf "ERROR: download/coreboot: logical loop; '%s' board.cfg refers to another tree, which ultimately refers back to '%s'.\n" "${board}" "${board}" return 1 fi # This is to override $cbrevision and $cbtree source "resources/coreboot/${board}/board.cfg" || touch ../build_error if [ -f build_error ]; then printf "ERROR: download/coreboot: problem sourcing %s/board.cfg\n" "${board}" return 1 fi touch "resources/coreboot/${board}/seen" if [ "${board}" != "${cbtree}" ]; then board="${cbtree}" else if [ "${cbtree}" = "undefined" ]; then printf "ERROR: download/coreboot: tree name undefined for '%s\n'" "${board}" return 1 fi if [ "${cbrevision}" = "undefined" ]; then printf "ERROR: download/coreboot: commit ID undefined for '%s'\n" "${board}" return 1 fi break fi done rm -f resources/coreboot/*/seen if [ -d "coreboot/${cbtree}" ]; then printf "REMARK: download/coreboot: directory for '%s' already exists. Skipping setup.\n" "${cbtree}" if [ "${cbtree}" != "${1}" ]; then printf "(for board: '${1}')\n" fi return 0 fi if [ ! -d coreboot ]; then mkdir "coreboot/" fi if [ ! -d coreboot ]; then printf "ERROR: download/coreboot: directory not created. Check file system permissions\n" return 1 fi cd "coreboot/" if [ ! -d coreboot/.git ] && [ -d coreboot ]; then rm -Rf coreboot/ fi if [ ! -d coreboot ]; then printf "Download coreboot from upstream:\n" git clone --depth=1 https://review.coreboot.org/coreboot || rm -Rf coreboot if [ ! -d coreboot ]; then printf "WARNING: Upstream failed. Trying backup github repository:\n" git clone --depth=1 https://github.com/coreboot/coreboot.git || rm -Rf coreboot fi if [ ! -d coreboot ]; then printf "ERROR: download/coreboot: Problem with git-clone. Network issue?\n" cd ../; return 1 fi fi ( cd coreboot/; git fetch --depth=1 origin "${cbrevision}" || touch ../build_error ) if [ -f ../build_error ]; then printf "ERROR: download/coreboot: Problem with git-fetch. Network issue?\n" cd ../; return 1 fi cp -R coreboot "${cbtree}" || touch ../build_error if [ -f ../build_error ]; then printf "ERROR: download/coreboot: Unable to copy directory. Check file system permissions or free space.\n" rm -Rf "${cbtree}/" cd ../; return 1 fi cd ${cbtree}/ git reset --hard ${cbrevision} || touch ../../build_error if [ -f ../../build_error ]; then printf "ERROR: download/coreboot: Unable to reset to commit ID/tag '%s' for board '%s' on tree '%s'\n" "${cbrevision}" "${1}" "${cbtree}" cd ../../; return 1 fi git submodule update --init --depth=1 || touch ../../build_error if [ -f ../../build_error ]; then printf "ERROR: download/coreboot: Unable to update submodules for tree '%s'\n" "${cbtree}" cd ../../; return 1 fi for patch in ../../resources/coreboot/${cbtree}/patches/*.patch; do if [ ! -f "${patch}" ]; then continue fi git am "${patch}" || touch ../../build_error if [ -f ../../build_error ]; then printf "ERROR: download/coreboot: Unable to apply patch '%s' for board '%s' on tree '%s'" "${patch}" "${1}" "${cbtree}" git am --abort cd ../../; return 1 fi done # extra.sh could be used to patch submodules, if you wanted to # It's impossible to predict what submodules will be available, and # it's rare that you'd want to patch them, so this is handled by # extra.sh on a per-board basis # In fact, extra.sh can be used for anything you want. if [ -f "../../resources/coreboot/${board}/extra.sh" ]; then "../../resources/coreboot/${board}/extra.sh" || touch ../../build_error if [ -f ../../build_error ]; then cd ../../; return 1 fi return 0 else cd ../../ return 0 fi } printf "Downloading coreboot and (if exist in build system) applying patches\n" if [ $# -gt 0 ]; then for board in "${@}"; do rm -f resources/coreboot/*/seen downloadfor "${board}" if [ -f build_error ]; then break; fi done else for board in resources/coreboot/*; do rm -f resources/coreboot/*/seen if [ ! -d "${board}/" ]; then continue fi downloadfor "${board##*/}" if [ -f build_error ]; then break; fi done fi rm -f resources/coreboot/*/seen rm -f "build_error" printf "\n\n" if [ "${deleteblobs}" = "true" ]; then if [ "${deletegit}" = "true" ]; then rm -Rf coreboot/coreboot/ rm -Rf coreboot/.git* coreboot/*/.git* coreboot/*/3rdparty/*/.git* rm -Rf coreboot/*/util/nvidia/cbootimage/.git* fi for cbdir in coreboot/*; do if [ ! -d "${cbdir}" ]; then continue; fi cbtree="${cbdir##coreboot/}" cbtree="${cbtree%/}" if [ ! -d "coreboot/${cbtree}" ]; then continue; fi bloblist="resources/coreboot/${cbtree}/blobs.list" if [ -f "${bloblist}" ]; then for blobfile in $(cat "${bloblist}"); do printf "Deleting blob: 'coreboot/%s/%s'\n" "${cbtree}" "${blobfile}" rm -f "coreboot/${cbtree}/${blobfile}" done fi rmlist="resources/coreboot/${cbtree}/rm.list" if [ -f "${rmlist}" ]; then for rmentry in $(cat "${rmlist}"); do printf "Deleting directory to save space: 'coreboot/%s/%s'\n" "${cbtree}" "${rmentry}" rm -Rf "coreboot/${cbtree}/${rmentry}" done fi done fi exit 0