1#!/bin/bash
2
3##########################################################################
4# Copyright (c) 2009, ETH Zurich.
5# All rights reserved.
6#
7# This file is distributed under the terms in the attached LICENSE file.
8# If you do not find this file, copies can be found by writing to:
9# ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
10##########################################################################
11
12#
13# This script inserts a branch-link instruction as the first word in the
14# kernel ELF file so it can self-load itself. This trickery allows the
15# same kernel to load from ROM or RAM, and makes the RAW blob executable.
16#
17# This script should make you whince. Ultimately it should be replaced by
18# a small program in the blessed scripting language.
19#
20if [ $# -ne 3 ] ; then
21   echo "Usage: <objdump_path> <kernel> <output_file>"
22   exit 1
23fi
24
25OBJDUMP=$1
26KERNEL=$2
27OUTPUT=$3
28
29if [ ! -f ${KERNEL} ]; then
30   echo Failed to find kernel :- \"${KERNEL}\"
31   exit 1
32fi
33
34# check for required tools
35if ! which tr sed dc dd > /dev/null; then
36    echo $0: missing one or more required tools > /dev/stderr
37    exit 1
38fi
39
40#
41# Extract virtual start address, .text virtual address, .text file offset
42# Set as shell variables ENTRY, SIZE, VTEXT, LTEXT, OFFSET
43#
44# The sed expression maps the address info from objdump into shelll variables.
45#
46# The use of tr is primarily to uppercase the hex digits to be presented to dc.
47#
48eval `"${OBJDUMP}" -x "${KERNEL}" | tr "[a-z]" "[A-Z]" | sed -n -e "/^START ADDRESS/ { s@.*0X\([0-9A-F]*\).*@ENTRY=\1;@; p }" -e "/TEXT/ { s@.*TEXT[ \t]*\([0-9A-F]*\)[ \t]*\([0-9A-F]*\)[ \t]*\([0-9A-F]*\)[ \t]*\([0-9A-F]*\).*@SIZE=\1 ; VTEXT=\2; LTEXT=\3; OFFSET=\4@; p; q }"`
49
50if [ "${OFFSET}" = "" ] ; then
51    echo "Failed to extract addresses."
52    exit 1
53fi
54
55if [ "${ENTRY}" != "${VTEXT}" ] ; then
56    # Strictly we should just check entry is in text section.
57    echo "Entry address is not start of text section."
58    exit 1
59fi
60
61#
62# Generate BL instruction (EB + pc_relative_offset / 4).
63#
64BL=`dc -e "16 o 16 i ${ENTRY} ${VTEXT} - ${OFFSET} + 8 - 4 / EB000000 + p"`
65
66
67#
68# 1. In case we compile or a big endian environment:
69# Reverse order of string to get a big endian representation instead of a little endian one. This corresponds to inverting the stack for dc
70#
71# 2. Convert BL instruction from 8 digit hex representation into
72# 32-bit binary word and append rest of kernel.
73
74${OBJDUMP} -f ${KERNEL} | grep -q bigarm # Using return value for if statement
75
76if [ $? -eq 0 ]; then
77    # We compile for big endian - reverse byte order
78    BL=${BL:6:2}${BL:4:2}${BL:2:2}${BL:0:2}
79fi
80
81
82dc -e "16o 16i ${BL} d 100 % P 100 / d 100 % P 100 / d 100 % P 100 / d 100 % P" > ${OUTPUT}
83
84dd if=${KERNEL} of=${OUTPUT} skip=1 seek=1 bs=4 >/dev/null 2>&1 
85exit $?
86