| #!/bin/sh | |
| # | |
| # Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) | |
| # | |
| # SPDX-License-Identifier: GPL-2.0-only | |
| # | |
| set -eu | |
| PROGNAME=${0##*/} | |
| # We use the following exit status conventions: | |
| # 0: normal operation, successful, "true" | |
| # 1: expected failure, "false" | |
| # 2: usage error | |
| # 3: other error | |
| EXIT_STATUS=3 | |
| # Emit diagnostic message. | |
| # @params: a set of strings comprising a human-intelligible message | |
| _print () { | |
| echo "${PROGNAME:-(unknown program)}: $*" | |
| } | |
| # Emit error message to standard error. | |
| # @params: a set of strings comprising a human-intelligible message | |
| fail () { | |
| _print "error: $*" >&2 | |
| } | |
| # Report unrecoverable error and terminate script. | |
| # @params: a set of strings comprising a human-intelligible message | |
| # | |
| # Note: $EXIT_STATUS, if set in the invoking scope, determines the exit status | |
| # used by this function. | |
| die () { | |
| _print "fatal error: $*" >&2 | |
| exit ${EXIT_STATUS:-3} | |
| } | |
| # Display a usage message. | |
| show_usage () { | |
| cat <<EOF | |
| $PROGNAME: generate U-Boot payload for ARM platform | |
| Usage: | |
| $PROGNAME OBJCOPY-TOOL ELF-FILE ARCHITECTURE OUTPUT-FILE | |
| $PROGNAME uses objcopy, readelf (both from GNU binutils), and mkimage | |
| (from the U-Boot tools) to extract the entry point (start symbol) of an | |
| ELF executable and wrap the object in a chain-loadable payload for use | |
| by the U-Boot boot loader. | |
| OBJCOPY-TOOL should be the path to a version of GNU objcopy appropriate | |
| for the (cross-)built ELF-FILE. ELF-FILE should be an ELF executable | |
| object. ARCHITECTURE must be either "arm" or "arm64". The image is | |
| written to OUTPUT-FILE. | |
| EOF | |
| } | |
| # Clean up temporary file. $TEMPFILE is defined before this function is called. | |
| cleanup () { | |
| rm -f $TEMPFILE | |
| } | |
| # Output the start symbol from given ELF object. | |
| # | |
| # Note: This function is sensitive to the output format of "readelf". | |
| get_start_symbol() { | |
| ELF_FILE=$1 | |
| if ! $READELF -h "$ELF_FILE" > /dev/null | |
| then | |
| die "\"$ELF_FILE\" does not appear to be an ELF file" | |
| fi | |
| set -- $($READELF -s $ELF_FILE | grep -w _start) | |
| echo $2 | |
| } | |
| if [ $# -ne 5 ] | |
| then | |
| fail "expected 5 arguments, got $#: \"$*\"" | |
| show_usage >&2 | |
| exit 2 | |
| fi | |
| OBJCOPY=$1 | |
| READELF=$2 | |
| ELF_FILE=$3 | |
| ARCHITECTURE=$4 | |
| OUTPUT=$5 | |
| # Validate arguments. $ELF_FILE is validated by get_start_symbol(). We'll let | |
| # mkimage fail if $OUTPUT is not writable. | |
| if ! [ -x "$OBJCOPY" ] | |
| then | |
| die "\"$OBJCOPY\" does not exist or is not executable" | |
| fi | |
| case "$ARCHITECTURE" in | |
| (arm|arm64) | |
| ;; | |
| (*) | |
| EXIT_STATUS=2 | |
| die "unrecognized (ARM) architecture \"$ARCHITECTURE\"" | |
| ;; | |
| esac | |
| # $ARCHITECTURE is now known to be a safe string and no longer requires | |
| # quotation. | |
| TEMPFILE=$(mktemp) | |
| trap cleanup HUP INT QUIT TERM EXIT | |
| # Note: Because we are using a temporary file, the appending redirection is | |
| # important! Do not degenerate it to ">", which will unlink the destination | |
| # first and reintroduce the race that mktemp avoids. | |
| "$OBJCOPY" -O binary "$ELF_FILE" /dev/stdout >> $TEMPFILE | |
| START=$(get_start_symbol "$ELF_FILE") | |
| mkimage -A $ARCHITECTURE -O linux -T kernel -C none \ | |
| -a $START -e $START -d $TEMPFILE "$OUTPUT" | |
| exit 0 |