| #!/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 |