#!/usr/bin/env bash # helper script: download u-boot # # Copyright (C) 2014, 2015, 2016, 2020, 2021 Leah Rowe # Copyright (C) 2021 Denis 'GNUtoo' Carikli # 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 # set this when you want to modify each u-boot tree # for example, you want to test custom patches # NODELETE= ./download u-boot 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 list_supported_boards() { for board in resources/u-boot/*; do if [ -d ${board} ]; then echo "${board#resources/u-boot/}" fi done } downloadfor() { board="${1}" # 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 ubrevision="undefined" ubtree="undefined" if [ ! -f "resources/u-boot/${board}/board.cfg" ]; then printf "ERROR: %s: board.cfg does not exist for '%s'\n" \ "download/u-boot" "${board}" return 1 fi if [ -f "resources/u-boot/${board}/seen" ]; then printf "ERROR: %s: logical loop; '%s' board.cfg refers to another tree, which ultimately refers back to '%s'.\n" \ "download/u-boot" "${board}" "${board}" return 1 fi # This is to override $ubrevision and $ubtree source "resources/u-boot/${board}/board.cfg" || touch build_error if [ -f build_error ]; then printf "ERROR: %s: problem sourcing %s/board.cfg\n" \ "download/u-boot" "${board}" return 1 fi touch "resources/u-boot/${board}/seen" if [ "${board}" != "${ubtree}" ]; then board="${ubtree}" else if [ "${ubtree}" = "undefined" ]; then printf "ERROR: %s: tree name undefined for '%s\n'" \ "download/u-boot" "${board}" return 1 fi if [ "${ubrevision}" = "undefined" ]; then printf "ERROR: %s: commit ID undefined for '%s'\n" \ "download/u-boot" "${board}" return 1 fi break fi done rm -f resources/u-boot/*/seen ubtree="u-boot/${ubtree}" if [ -d "${ubtree}" ]; then printf \ "REMARK: '%s' directory already exists. Skipping setup.\n" \ "${ubtree}" if [ "${ubtree}" != "u-boot/${board}" ]; then printf "(for board: '${board}')\n" fi return 0 fi if [ ! -d "u-boot" ]; then mkdir -p "u-boot" fi if [ ! -d "u-boot" ]; then printf \ "ERROR: '%s' directory not created. Check file system permissions\n" \ "u-boot" return 1 fi uboot_dir="u-boot/u-boot" if [ ! -d "${uboot_dir}/.git" ] && [ -d "${uboot_dir}" ]; then rm -Rf "${uboot_dir}" fi if [ ! -d "${uboot_dir}" ]; then printf "Download u-boot from upstream:\n" git clone --depth=1 https://source.denx.de/u-boot/u-boot.git \ "${uboot_dir}" || \ rm -Rf "${uboot_dir}" if [ ! -d "${uboot_dir}" ]; then printf "WARNING: Upstream failed. Trying backup github repository:\n" git clone --depth=1 https://github.com/u-boot/u-boot.git \ "${uboot_dir}" || \ rm -Rf coreboot fi if [ ! -d "${uboot_dir}" ]; then printf \ "ERROR: %s: Problem with git-clone. Network issue?\n" \ "download/u-boot" return 1 fi fi git -C "${uboot_dir}" fetch --depth=1 origin "${ubrevision}" || touch build_error if [ -f build_error ]; then printf \ "ERROR: %s: Problem with git-fetch. Network issue?\n" \ "download/u-boot" return 1 fi cp -R "${uboot_dir}" "${ubtree}" || touch build_error if [ -f build_error ]; then printf "ERROR: %s: Unable to copy directory. Check file system permissions or free space.\n" \ "download/u-boot" rm -Rf "${ubtree}/" return 1 fi git -C "${ubtree}" reset --hard ${ubrevision} || \ touch build_error if [ -f build_error ]; then printf \ "ERROR: %s: Unable to reset to commit ID/tag '%s' for board '%s' on tree '%s'\n" \ "download/u-boot" "${ubrevision}" "${board}" "${ubtree}" return 1 fi git -C "${ubtree}" submodule update --init --depth=1 || touch build_error if [ -f build_error ]; then printf "ERROR: %s: Unable to update submodules for tree '%s'\n" \ "${ubtree}" return 1 fi for patch in resources/u-boot/${board}/patches/*.patch; do if [ ! -f "${patch}" ]; then continue fi git -C "${ubtree}" am "$(pwd)/${patch}" || touch build_error if [ -f build_error ]; then printf "ERROR: %s: Unable to apply patch '%s' for board '%s' on tree '%s'" \ "download/u-boot" "${patch}" "${board}" "${ubtree}" git -C "${ubtree}" am --abort 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/u-boot/${board}/extra.sh" ]; then "resources/u-boot/${board}/extra.sh" || touch build_error if [ -f build_error ]; then return 1 fi return 0 else return 0 fi } strip_comments() { file="$1" # Remove comments sed 's/#.*//' "${file}" | \ # Remove lines composed of whitespaces only sed '/^\W\+$/d' | \ # Remove empty lines sed '/^$/d' } generate_deblob_script() { blob_list_file="$1" output="$2" # Add sheebang and copyright headers from this file awk '{ if ($0 !~ /^#/ && NF > 0) { stop=1; } if (stop !=1) { printf("%s\n", $0); } }' $0 >> ${output} # Add rm -rf before directories and rm -f before files awk \ '{ }{ if (NF == 0) { printf("\n"); } else { if ($0 !~ /#/ && $NF ~ /\/$/) { printf("rm -rf %s\n", $0); } else if ($0 !~ /#/) { printf("rm -f %s\n", $0); } else { # We have comments, try to see if they are # still valid paths before the comments comments_found=0 last_field=0 for(i=1; i<=NF; i++) { if($i ~ /#/) { comments_found=1; } else if(comments_found != 1) { last_field=i; } } if (last_field == 0) { printf("%s\n", $0); } else if ($last_field ~ /\/$/) { printf("rm -rf %s\n", $0); } else { printf("rm -f %s\n", $0); } } } }' "${blob_list_file}" >> "${output}" } usage() { progname="./download u-boot" printf "Usage:\n" printf "\t%s # %s\n" \ "${progname}" \ "Download and deblob u-boot for all boards" printf "\t%s [board] # %s\n" \ "${progname}" \ "Download and deblob u-boot for the given board" printf "\t%s --blobs-list # %s\n" \ "${progname}" \ "Print the path of the generic blobs.list file" printf "\t%s --blobs-list [board] # %s\n" \ "${progname}" \ "Print the path of the blobs.list file for the given board" printf "\t%s --gen-deblob-script # %s\n" \ "${progname}" \ "Print the path of a generated generic deblob script" printf "\t%s --gen-deblob-script [board] # %s\n" \ "${progname}" \ "Print the path of a generated deblob script for the given board" printf "\t%s --list-boards # %s\n" \ "${progname}" \ "List supported boards" printf "\t%s --help # %s\n" \ "${progname}" \ "Prints this help" } download_uboot_board() { board="${1}" ubtree="u-boot/${board}" printf "Downloading u-boot " printf "and (if exist in build system) applying patches\n" downloadfor "${board}" rm -f "build_error" printf "\n\n" if [ "${deleteblobs}" = "true" ]; then if [ "${deletegit}" = "true" ]; then rm -rf "${ubtree}"/.git* "${ubtree}"/*/.git* fi blobslist="$(print_blobs_list_path "${board}")" for blob_path in $(strip_comments "${blobslist}"); do if echo "${blob_path}" | \ grep '/$' 2>&1 >/dev/null ; then printf "Deleting blob directory: '%s/%s'\n" \ "${ubtree}" "${blob_path}" rm -rf "${ubtree}/${blob_path}" else printf "Deleting blob file: '%s/%s'\n" \ "${ubtree}" "${blob_path}" rm -f "${ubtree}/${blob_path}" fi done fi } print_blobs_list_path() { board="$1" if [ -f "resources/u-boot/${board}/blobs.list" ]; then printf "resources/u-boot/${board}/blobs.list\n" else printf "resources/u-boot/default/blobs.list\n" fi } print_deblob_script_path() { board="$1" path="$(mktemp)" generate_deblob_script "$(print_blobs_list_path ${board})" "${path}" printf "%s\n" ${path} } if [ $# -eq 0 ] ; then for board in $(list_supported_boards); do download_uboot_board "${board}" done if [ "${deletegit}" = "true" ]; then rm -rf u-boot/u-boot/ u-boot/.git* fi exit 0 elif [ $# -eq 1 -a "$1" == "--help" ] ; then usage exit 0 elif [ $# -eq 1 -a "$1" == "--list-boards" ] ; then list_supported_boards exit 0 elif [ $# -eq 1 -a "$1" == "--blobs-list" ] ; then print_blobs_list_path "default" exit 0 elif [ $# -eq 2 -a "$1" == "--blobs-list" ] ; then found=0 for board in $(list_supported_boards) ; do if [ "${board}" = "$2" ] ; then print_blobs_list_path "$2" exit 0 fi done printf "Error: Board '${2}' is not supported\n" exit 1 elif [ $# -eq 1 -a "$1" == "--gen-deblob-script" ] ; then print_deblob_script_path "default" exit 0 elif [ $# -eq 2 -a "$1" == "--gen-deblob-script" ] ; then found=0 for board in $(list_supported_boards) ; do if [ "$board" = "$2" ] ; then print_deblob_script_path "$2" exit 0 fi done printf "Error: Board '${2}' is not supported\n" exit 1 elif [ $# -eq 1 ] ; then for board in $(list_supported_boards) ; do if [ "$board" = "$1" ] ; then download_uboot_board "$1" exit 0 fi done if [ "${deletegit}" = "true" ]; then rm -rf u-boot/u-boot/ u-boot/.git* fi printf "Error: Board '${1}' is not supported\n" exit 1 fi exit 0