xref: /rk3399_ARM-atf/plat/marvell/armada/a8k/a80x0_nbx/verify_build.sh (revision 90b7958b2a6a0010be69b1d8f5ec1aa1cd73d026)
1#!/bin/bash
2# verify_build.sh - Verify a80x0_nbx TF-A build
3#
4# Usage: ./verify_build.sh [build_dir]
5#   build_dir: Path to build output (default: build/a80x0_nbx/debug)
6#              Also accepts BUILD_BASE; a80x0_nbx/{debug,release} is probed.
7#
8# SPDX-License-Identifier: BSD-3-Clause
9# Copyright (C) 2025-2026 Free Mobile / Freebox
10
11set -e
12
13BUILD_DIR="${1:-build/a80x0_nbx/debug}"
14
15# When called with BUILD_BASE (e.g. by CI), artifacts are in the
16# a80x0_nbx/{debug,release} subdirectory.  Probe for it so that both
17#   verify_build.sh build/a80x0_nbx/debug   (local, default)
18#   verify_build.sh $BUILD_BASE              (CI: post_tf_build hook)
19# work transparently.
20if [ ! -f "${BUILD_DIR}/ble.bin" ]; then
21    for _subdir in "${BUILD_DIR}"/a80x0_nbx/debug \
22                   "${BUILD_DIR}"/a80x0_nbx/release; do
23        if [ -d "${_subdir}" ]; then
24            BUILD_DIR="${_subdir}"
25            break
26        fi
27    done
28    unset _subdir
29fi
30
31BLE_ELF="${BUILD_DIR}/ble/ble.elf"
32BL31_ELF="${BUILD_DIR}/bl31/bl31.elf"
33CROSS_PREFIX="${CROSS_COMPILE:-aarch64-linux-gnu-}"
34
35# Colors for output
36RED='\033[0;31m'
37GREEN='\033[0;32m'
38YELLOW='\033[1;33m'
39NC='\033[0m' # No Color
40
41pass() { printf '%b[OK]%b\n' "${GREEN}" "${NC}"; }
42fail() { printf '%b[FAILED]%b\n' "${RED}" "${NC}"; }
43warn() { printf '%b[WARN]%b\n' "${YELLOW}" "${NC}"; }
44missing() { printf '%b[MISSING]%b\n' "${RED}" "${NC}"; }
45
46echo "=============================================="
47echo "  a80x0_nbx TF-A Build Verification"
48echo "=============================================="
49echo ""
50echo "Build directory: ${BUILD_DIR}"
51echo "Cross prefix:    ${CROSS_PREFIX}"
52echo ""
53
54ERRORS=0
55
56# 1. Check build artifacts exist
57echo "1. Checking build artifacts..."
58echo "   ----------------------------------------"
59ARTIFACTS="ble.bin bl1.bin bl2.bin bl31.bin fip.bin flash-image.bin"
60for f in ${ARTIFACTS}; do
61    if [ -f "${BUILD_DIR}/${f}" ]; then
62        SIZE=$(stat -c%s "${BUILD_DIR}/${f}")
63        printf "   %-20s %8d bytes  " "${f}" "${SIZE}"
64        pass
65    else
66        printf "   %-20s %8s        " "${f}" "-"
67        missing
68        ERRORS=$((ERRORS + 1))
69    fi
70done
71echo ""
72
73# 2. Check ramoopsies linker wrapping
74echo "2. Checking ramoopsies --wrap mechanism..."
75echo "   ----------------------------------------"
76if [ -f "${BLE_ELF}" ]; then
77    # Check symbols exist
78    printf "   %-35s " "__wrap_mv_ddr_mem_scrubbing"
79    if "${CROSS_PREFIX}nm" "${BLE_ELF}" 2>/dev/null | grep -q "__wrap_mv_ddr_mem_scrubbing"; then
80        pass
81    else
82        fail
83        ERRORS=$((ERRORS + 1))
84    fi
85
86    printf "   %-35s " "mv_ddr_mem_scrubbing (original)"
87    if "${CROSS_PREFIX}nm" "${BLE_ELF}" 2>/dev/null | grep -q "T mv_ddr_mem_scrubbing$"; then
88        pass
89    else
90        fail
91        ERRORS=$((ERRORS + 1))
92    fi
93
94    printf "   %-35s " "ramoopsies_backup buffer"
95    if "${CROSS_PREFIX}nm" "${BLE_ELF}" 2>/dev/null | grep -q "ramoopsies_backup"; then
96        pass
97    else
98        fail
99        ERRORS=$((ERRORS + 1))
100    fi
101
102    # Verify wrapper calls real function
103    printf "   %-35s " "Wrapper calls original function"
104    CALL_CHAIN=$("${CROSS_PREFIX}objdump" -d "${BLE_ELF}" 2>/dev/null | \
105        grep -A50 "<__wrap_mv_ddr_mem_scrubbing>:" | \
106        grep "bl.*<mv_ddr_mem_scrubbing>" || true)
107    if [ -n "${CALL_CHAIN}" ]; then
108        pass
109    else
110        fail
111        ERRORS=$((ERRORS + 1))
112    fi
113
114    # Check SError vector handling
115    printf "   %-35s " "SError exception vectors"
116    if "${CROSS_PREFIX}nm" "${BLE_ELF}" 2>/dev/null | grep -q "vectors"; then
117        pass
118    else
119        warn
120    fi
121else
122    echo "   BLE ELF not found: ${BLE_ELF}"
123    ERRORS=$((ERRORS + 1))
124fi
125echo ""
126
127# 3. Check DDR driver integration
128echo "3. Checking DDR driver integration..."
129echo "   ----------------------------------------"
130if [ -f "${BLE_ELF}" ]; then
131    DDR_SYMS="ddr3_init mv_ddr_topology_map_get mv_ddr_spd_supported_cls_calc mv_ddr_is_ecc_ena"
132    for sym in ${DDR_SYMS}; do
133        printf "   %-35s " "${sym}"
134        if "${CROSS_PREFIX}nm" "${BLE_ELF}" 2>/dev/null | grep -q "T ${sym}"; then
135            pass
136        else
137            fail
138            ERRORS=$((ERRORS + 1))
139        fi
140    done
141fi
142echo ""
143
144# 4. Check BL31 runtime services
145echo "4. Checking BL31 runtime services..."
146echo "   ----------------------------------------"
147if [ -f "${BL31_ELF}" ]; then
148    BL31_SYMS="mvebu_get_dram_size plat_marvell_get_pm_cfg a8k_pwr_domain_off a8k_system_reset"
149    for sym in ${BL31_SYMS}; do
150        printf "   %-35s " "${sym}"
151        if "${CROSS_PREFIX}nm" "${BL31_ELF}" 2>/dev/null | grep -q " ${sym}"; then
152            pass
153        else
154            echo -n "(inlined?) "
155            warn
156        fi
157    done
158else
159    echo "   BL31 ELF not found: ${BL31_ELF}"
160    ERRORS=$((ERRORS + 1))
161fi
162echo ""
163
164# 5. Check OP-TEE integration (optional)
165echo "5. Checking OP-TEE integration..."
166echo "   ----------------------------------------"
167FIP_BIN="${BUILD_DIR}/fip.bin"
168FIPTOOL="tools/fiptool/fiptool"
169
170# Check if opteed is compiled into BL31
171OPTEE_ENABLED=false
172if [ -f "${BL31_ELF}" ]; then
173    if "${CROSS_PREFIX}nm" "${BL31_ELF}" 2>/dev/null | grep -q "opteed_setup"; then
174        OPTEE_ENABLED=true
175    fi
176fi
177
178if [ "${OPTEE_ENABLED}" = true ]; then
179    printf "   %-35s " "OP-TEE dispatcher (opteed)"
180    pass
181
182    # Check opteed symbols in BL31
183    OPTEE_SYMS="opteed_setup opteed_init optee_vector_table bl32_image_ep_info"
184    for sym in ${OPTEE_SYMS}; do
185        printf "   %-35s " "${sym}"
186        if "${CROSS_PREFIX}nm" "${BL31_ELF}" 2>/dev/null | grep -q "${sym}"; then
187            pass
188        else
189            fail
190            ERRORS=$((ERRORS + 1))
191        fi
192    done
193
194    # Check BL32 (header), BL32_EXTRA1 (pager), BL32_EXTRA2 (pageable) in FIP
195    if [ -f "${FIP_BIN}" ] && [ -x "${FIPTOOL}" ]; then
196        # Check BL32 (v2 header)
197        printf "   %-35s " "BL32 (header) in FIP"
198        BL32_INFO=$(${FIPTOOL} info "${FIP_BIN}" 2>/dev/null | \
199            grep -E "Secure Payload BL32 \(Trusted OS\):" | \
200            head -1 || true)
201        if [ -n "${BL32_INFO}" ]; then
202            BL32_SIZE=$(echo "${BL32_INFO}" | sed -n 's/.*size=\(0x[0-9a-fA-F]*\).*/\1/p')
203            echo -n "(${BL32_SIZE}) "
204            pass
205        else
206            fail
207            echo "   ERROR: BL32 header not found in FIP!"
208            ERRORS=$((ERRORS + 1))
209        fi
210
211        # Check BL32_EXTRA1 (pager)
212        printf "   %-35s " "BL32_EXTRA1 (pager) in FIP"
213        EXTRA1_INFO=$(${FIPTOOL} info "${FIP_BIN}" 2>/dev/null \
214            | grep -E "Trusted OS Extra1" || true)
215        if [ -n "${EXTRA1_INFO}" ]; then
216            EXTRA1_SIZE=$(echo "${EXTRA1_INFO}" | sed -n 's/.*size=\(0x[0-9a-fA-F]*\).*/\1/p')
217            echo -n "(${EXTRA1_SIZE}) "
218            pass
219        else
220            fail
221            echo "   ERROR: BL32_EXTRA1 (pager) not found in FIP - OP-TEE will fail!"
222            ERRORS=$((ERRORS + 1))
223        fi
224
225        # Check BL32_EXTRA2 (pageable) - may be empty/missing for non-paged builds
226        printf "   %-35s " "BL32_EXTRA2 (pageable) in FIP"
227        EXTRA2_INFO=$(${FIPTOOL} info "${FIP_BIN}" 2>/dev/null \
228            | grep -E "Trusted OS Extra2" || true)
229        if [ -n "${EXTRA2_INFO}" ]; then
230            EXTRA2_SIZE=$(echo "${EXTRA2_INFO}" | sed -n 's/.*size=\(0x[0-9a-fA-F]*\).*/\1/p')
231            echo -n "(${EXTRA2_SIZE}) "
232            pass
233        else
234            echo -n "(not present - OK for non-paged) "
235            pass
236        fi
237
238        # Extract and verify OP-TEE header magic and version
239        printf "   %-35s " "OP-TEE header magic"
240        TMPBL32=$(mktemp)
241        if ${FIPTOOL} unpack --tos-fw "${TMPBL32}" --force "${FIP_BIN}" 2>/dev/null; then
242            MAGIC=$(hexdump -n 4 -e '4/1 "%c"' "${TMPBL32}" 2>/dev/null) || MAGIC=""
243            if [ "${MAGIC}" = "OPTE" ]; then
244                echo -n "(\"OPTE\") "
245                pass
246
247                # Check header version (byte 4, should be 2 for v2 format)
248                printf "   %-35s " "OP-TEE header version"
249                VERSION=$(hexdump -s 4 -n 1 -e '1/1 "%d"' "${TMPBL32}" 2>/dev/null) || VERSION="0"
250                if [ "${VERSION}" = "2" ]; then
251                    echo -n "(v${VERSION}) "
252                    pass
253                else
254                    echo -n "(v${VERSION}) "
255                    fail
256                    echo "   ERROR: Expected version 2, got ${VERSION}!"
257                    echo "   Use tee-header_v2.bin as BL32, not tee.bin"
258                    ERRORS=$((ERRORS + 1))
259                fi
260
261                # Check load address (v2 header: load_addr at offset 16)
262                printf "   %-35s " "OP-TEE load address"
263                LOAD_ADDR=$(hexdump -s 16 -n 4 \
264                    -e '1/4 "0x%08x"' "${TMPBL32}" \
265                    2>/dev/null) || LOAD_ADDR=""
266                if [ "${LOAD_ADDR}" = "0x04400000" ]; then
267                    echo -n "(${LOAD_ADDR}) "
268                    pass
269                else
270                    echo -n "(${LOAD_ADDR}) "
271                    warn
272                    echo "   WARNING: Expected 0x04400000"
273                fi
274            else
275                echo -n "(\"${MAGIC}\") "
276                fail
277                echo "   ERROR: Invalid OP-TEE header - expected \"OPTE\" magic!"
278                ERRORS=$((ERRORS + 1))
279            fi
280        else
281            echo -n "(extract failed) "
282            warn
283        fi
284        rm -f "${TMPBL32}"
285    else
286        printf "   %-35s " "BL32 in FIP"
287        echo -n "(fiptool not available) "
288        warn
289    fi
290else
291    printf "   %-35s " "OP-TEE dispatcher (opteed)"
292    echo -n "(not enabled) "
293    warn
294    echo "   INFO: Build without OP-TEE support - this is OK if not using --optee-*"
295fi
296echo ""
297
298# 6. Check platform configuration
299echo "6. Checking platform configuration..."
300echo "   ----------------------------------------"
301if [ -f "${BLE_ELF}" ]; then
302    PLAT_SYMS=""
303    PLAT_SYMS="${PLAT_SYMS} marvell_get_io_win_memory_map"
304    PLAT_SYMS="${PLAT_SYMS} marvell_get_ccu_memory_map"
305    PLAT_SYMS="${PLAT_SYMS} plat_marvell_dram_update_topology"
306    for sym in ${PLAT_SYMS}; do
307        printf "   %-35s " "${sym}"
308        if "${CROSS_PREFIX}nm" "${BLE_ELF}" 2>/dev/null | grep -q " ${sym}"; then
309            pass
310        else
311            echo -n "(inlined?) "
312            warn
313        fi
314    done
315fi
316echo ""
317
318# 7. Check I2C/SPD support
319echo "7. Checking I2C/SPD support..."
320echo "   ----------------------------------------"
321if [ -f "${BLE_ELF}" ]; then
322    I2C_SYMS="i2c_init i2c_read"
323    for sym in ${I2C_SYMS}; do
324        printf "   %-35s " "${sym}"
325        if "${CROSS_PREFIX}nm" "${BLE_ELF}" 2>/dev/null | grep -q "T ${sym}"; then
326            pass
327        else
328            warn
329        fi
330    done
331fi
332echo ""
333
334# 8. Flash image sanity check
335echo "8. Checking flash image format..."
336echo "   ----------------------------------------"
337FLASH_IMAGE="${BUILD_DIR}/flash-image.bin"
338if [ -f "${FLASH_IMAGE}" ]; then
339    # Check magic number (Marvell boot image starts with specific header)
340    MAGIC=$(hexdump -n 4 -e '1/4 "%08x"' "${FLASH_IMAGE}" 2>/dev/null) || \
341    MAGIC=$(od -A n -t x4 -N 4 "${FLASH_IMAGE}" 2>/dev/null | tr -d ' \n') || \
342    MAGIC=""
343    printf "   %-35s " "Flash image header"
344    if [ -n "${MAGIC}" ]; then
345        echo -n "(0x${MAGIC}) "
346        pass
347    else
348        echo -n "(no hex tool) "
349        warn
350    fi
351
352    # Check file size is reasonable
353    SIZE=$(stat -c%s "${FLASH_IMAGE}")
354    printf "   %-35s " "Flash image size"
355    if [ "${SIZE}" -gt 100000 ] && [ "${SIZE}" -lt 2000000 ]; then
356        echo -n "(${SIZE} bytes) "
357        pass
358    else
359        echo -n "(${SIZE} bytes) "
360        warn
361    fi
362else
363    echo "   Flash image not found: ${FLASH_IMAGE}"
364    ERRORS=$((ERRORS + 1))
365fi
366echo ""
367
368# Summary
369echo "=============================================="
370if [ ${ERRORS} -eq 0 ]; then
371    printf '  Result: %bALL CHECKS PASSED%b\n' "${GREEN}" "${NC}"
372else
373    printf '  Result: %b%d CHECK(S) FAILED%b\n' "${RED}" "${ERRORS}" "${NC}"
374fi
375echo "=============================================="
376echo ""
377
378exit ${ERRORS}
379