1#!/usr/bin/env bash
2
3# Copyright 2018 The Fuchsia Authors
4#
5# Use of this source code is governed by a MIT-style
6# license that can be found in the LICENSE file or at
7# https://opensource.org/licenses/MIT
8
9set -eo pipefail
10
11SCRIPTS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
12ZIRCON_DIR="${SCRIPTS_DIR}/.."
13
14USE_AVB=
15BOARD=
16BUILD_DIR=
17CMDLINE=
18MKBOOTIMG_CMDLINE=
19MEXEC=
20DTB_PATH=
21DTB_DEST=
22USE_GZIP=
23USE_LZ4=
24KERNEL_OFFSET=0x00080000
25MEMBASE=0x00000000
26BOOT_IMG=
27VBMETA_IMG=
28ZIRCON_BOOTIMAGE=
29MKBOOTIMG_ARGS=
30
31function HELP {
32    echo "help:"
33    echo "-a                                : use AVB to sign image"
34    echo "-b <board>                        : board name"
35    echo "-B <build-dir>                    : path to zircon build directory"
36    echo "-c <cmd line>                     : Extra command line options for the ZBI"
37    echo "-C <cmd line>                     : Extra command line options for mkbootimg"
38    echo "-d <dtb-path>                     : path to device tree binary"
39    echo "-D (append | kdtb | mkbootimg)    : destination for device tree binary"
40    echo "-g                                : gzip compress the image"
41    echo "-l                                : lz4 compress the image"
42    echo "-h                                : print help"
43    echo "-K                                : kernel offset for mkbootimg (default ${KERNEL_OFFSET})"
44    echo "-m                                : Add mexec option to command line"
45    echo "-M                                : membase for mkbootimg (default ${MEMBASE})"
46    echo "-o                                : output boot.img file (defaults to <build-dir>/<board>-boot.img)"
47    echo "-v                                : output vbmeta.img file (defaults to <build-dir>/<board>-vbmeta.img)"
48    echo "-z                                : input zircon ZBI file (defaults to <build-dir>/<board>-boot.img)"
49    exit 1
50}
51
52# These values seem to work with all our boards, so we haven't parameterized them.
53DTB_OFFSET=0x03000000
54BOOT_PARTITION_SIZE=33554432
55
56while getopts "ab:B:c:C::d:D:ghK:lmM:r:o:v:z:" FLAG; do
57    case $FLAG in
58        a) USE_AVB=true;;
59        b) BOARD="${OPTARG}";;
60        B) BUILD_DIR="${OPTARG}";;
61        c) CMDLINE+="${OPTARG}";;
62        C) MKBOOTIMG_CMDLINE+="${OPTARG}";;
63        d) DTB_PATH="${OPTARG}";;
64        D) DTB_DEST="${OPTARG}";;
65        g) USE_GZIP=true;;
66        K) KERNEL_OFFSET="${OPTARG}";;
67        l) USE_LZ4=true;;
68        h) HELP;;
69        m) MEXEC=true;;
70        M) MEMBASE="${OPTARG}";;
71        o) BOOT_IMG="${OPTARG}";;
72        v) VBMETA_IMG="${OPTARG}";;
73        z) ZIRCON_BOOTIMAGE="${OPTARG}";;
74        \?)
75            echo unrecognized option
76            HELP
77            ;;
78    esac
79done
80shift $((OPTIND-1))
81
82if [[ -z "${BOARD}" ]]; then
83    echo must specify a board to flash
84    HELP
85fi
86
87if [[ -z "${BUILD_DIR}" ]]; then
88    echo must specify a Zircon build directory
89    HELP
90fi
91
92if [[ -n "${DTB_PATH}" ]] &&
93   [[ "${DTB_DEST}" != "append" ]] &&
94   [[ "${DTB_DEST}" != "kdtb" ]] &&
95   [[ "${DTB_DEST}" != "mkbootimg" ]]; then
96    echo Invalid dtb destination ${DTB_DEST}
97    HELP
98fi
99
100# Some tools we use
101MKBOOTIMG="${ZIRCON_DIR}/third_party/tools/android/mkbootimg"
102MKKDTB="${BUILD_DIR}/tools/mkkdtb"
103ZBI="${BUILD_DIR}/tools/zbi"
104
105# AVB support
106AVB_DIR="${ZIRCON_DIR}/third_party/tools/android/avb"
107AVBTOOL="${AVB_DIR}/avbtool"
108AVB_KEY="${AVB_DIR}/test/data/testkey_atx_psk.pem"
109AVB_PUBLIC_KEY_METADATA="${AVB_DIR}/test/data/atx_metadata.bin"
110
111# zircon image built by the Zircon build system
112if [[ -z "${ZIRCON_BOOTIMAGE}" ]]; then
113    ZIRCON_BOOTIMAGE="${BUILD_DIR}/zircon.zbi"
114fi
115
116# boot shim for our board
117BOOT_SHIM="${BUILD_DIR}/${BOARD}-boot-shim.bin"
118
119# zircon ZBI image with prepended boot shim
120SHIMMED_ZIRCON_BOOTIMAGE="${BUILD_DIR}/${BOARD}-zircon.shim"
121
122# Final packaged Android style boot.img
123if [[ -z "${BOOT_IMG}" ]]; then
124    BOOT_IMG="${BUILD_DIR}/${BOARD}-boot.img"
125fi
126
127# AVB vbmeta.img
128if [[ -z "${VBMETA_IMG}" ]]; then
129    VBMETA_IMG="${BUILD_DIR}/${BOARD}-vbmeta.img"
130fi
131
132# PACKAGING STEPS BEGIN HERE
133
134if [[ ${MEXEC} == true ]]; then
135    CMDLINE+=" netsvc.netboot=true"
136fi
137
138# Append extra command line items
139if [[ -n "${CMDLINE}" ]]; then
140    CMDLINE_FILE="${BUILD_DIR}/${BOARD}-cmdline.txt"
141    CMDLINE_BOOTIMAGE="${ZIRCON_BOOTIMAGE}.cmdline"
142
143    echo ${CMDLINE} > "${CMDLINE_FILE}"
144    "${ZBI}" -o "${CMDLINE_BOOTIMAGE}" "${ZIRCON_BOOTIMAGE}" -T cmdline "${CMDLINE_FILE}"
145else
146    CMDLINE_BOOTIMAGE="${ZIRCON_BOOTIMAGE}"
147fi
148
149# Prepend boot shim
150cat "${BOOT_SHIM}" "${CMDLINE_BOOTIMAGE}" > "${SHIMMED_ZIRCON_BOOTIMAGE}"
151
152# Optionally compress the shimmed image
153if [[ ${USE_GZIP} == true ]]; then
154    COMPRESSED_BOOTIMAGE="${BUILD_DIR}/${BOARD}-zircon.shim.gz"
155    gzip -c "${SHIMMED_ZIRCON_BOOTIMAGE}" > "${COMPRESSED_BOOTIMAGE}"
156elif [[ ${USE_LZ4} == true ]]; then
157    COMPRESSED_BOOTIMAGE="${BUILD_DIR}/${BOARD}-zircon.shim.lz4"
158    lz4 -c "${SHIMMED_ZIRCON_BOOTIMAGE}" > "${COMPRESSED_BOOTIMAGE}"
159else
160    COMPRESSED_BOOTIMAGE="${SHIMMED_ZIRCON_BOOTIMAGE}"
161fi
162
163# Handle options for packaging dtb
164if [[ -n "${DTB_PATH}" ]] && [[ "${DTB_DEST}" == "append" ]]; then
165    COMPRESSED_BOOTIMAGE_DTB="${COMPRESSED_BOOTIMAGE}.dtb"
166    cat "${COMPRESSED_BOOTIMAGE}" "${DTB_PATH}" > "${COMPRESSED_BOOTIMAGE_DTB}"
167elif [[ -n "${DTB_PATH}" ]] && [[ "${DTB_DEST}" == "kdtb" ]]; then
168    COMPRESSED_BOOTIMAGE_DTB="${COMPRESSED_BOOTIMAGE}.kdtb"
169    "${MKKDTB}" "${COMPRESSED_BOOTIMAGE}" "${DTB_PATH}" "${COMPRESSED_BOOTIMAGE_DTB}"
170elif [[ -n "${DTB_PATH}" ]] && [[ "${DTB_DEST}" == "mkbootimg" ]]; then
171    COMPRESSED_BOOTIMAGE_DTB="${COMPRESSED_BOOTIMAGE}"
172    MKBOOTIMG_ARGS+=" --second ${DTB_PATH} --second_offset ${DTB_OFFSET}"
173else
174    COMPRESSED_BOOTIMAGE_DTB="${COMPRESSED_BOOTIMAGE}"
175fi
176
177# some bootloaders insist on having a ramdisk
178RAMDISK="${BUILD_DIR}/dummy-ramdisk"
179echo "foo" > "${RAMDISK}"
180
181# create our boot.img
182"${MKBOOTIMG}" \
183    --kernel "${COMPRESSED_BOOTIMAGE_DTB}" \
184    --kernel_offset ${KERNEL_OFFSET} \
185    --ramdisk "${RAMDISK}" \
186    --base ${MEMBASE} \
187    --tags_offset 0xE000000 \
188    --cmdline "${MKBOOTIMG_CMDLINE}" \
189    ${MKBOOTIMG_ARGS} \
190    -o "${BOOT_IMG}"
191
192# optionally sign with AVB tools
193if [[ ${USE_AVB} == true ]]; then
194    "${AVBTOOL}" add_hash_footer \
195        --image "${BOOT_IMG}" \
196        --partition_size ${BOOT_PARTITION_SIZE} \
197        --partition_name boot
198
199    "${AVBTOOL}" make_vbmeta_image \
200        --include_descriptors_from_image "${BOOT_IMG}" \
201        --algorithm SHA512_RSA4096 --key "${AVB_KEY}" \
202        --public_key_metadata "${AVB_PUBLIC_KEY_METADATA}" \
203        --padding_size 4096 --output "${VBMETA_IMG}"
204fi
205