Skip to content

Commit 37579ca

Browse files
committed
fdt: boot a FIT with no kernel load/entry and no device tree
1 parent eb710fe commit 37579ca

16 files changed

Lines changed: 1071 additions & 40 deletions

‎.github/workflows/test-configs.yml‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,6 +1123,12 @@ jobs:
11231123
arch: aarch64
11241124
config-file: ./config/examples/versal_vmk180.config
11251125

1126+
versal_vmk180_highddr_test:
1127+
uses: ./.github/workflows/test-build-aarch64.yml
1128+
with:
1129+
arch: aarch64
1130+
config-file: ./config/examples/versal_vmk180_highddr.config
1131+
11261132
versal_vmk180_sdcard_test:
11271133
uses: ./.github/workflows/test-build-aarch64.yml
11281134
with:

‎config/examples/versal_vmk180.config‎

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,16 @@ GZIP?=1
6767
# "bootm" loads; without this wolfBoot ignores it.
6868
FIT_RAMDISK?=1
6969

70+
# Load address for the FIT kernel sub-image, overriding the FIT's own
71+
# `load`/`entry`. Needed when the ITS omits them (Yocto leaves them out
72+
# unless UBOOT_LOADADDRESS/UBOOT_ENTRYPOINT are set), since a gzip kernel
73+
# has nowhere to decompress to and an uncompressed one would be entered in
74+
# place at whatever alignment the FIT happens to give it. 0 honors the FIT.
75+
#WOLFBOOT_LOAD_KERNEL_ADDRESS?=0x200000
76+
77+
# Likewise for the ramdisk: 0 honors the FIT's own `load`.
78+
#WOLFBOOT_LOAD_RAMDISK_ADDRESS?=0x40000000
79+
7080
# Toolchain
7181
USE_GCC=1
7282
CROSS_COMPILE=aarch64-none-elf-
@@ -107,14 +117,29 @@ WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x6000000
107117
WOLFBOOT_LOAD_DTS_ADDRESS?=0x1000
108118

109119
# High DDR aperture: for designs whose DDR lives above the default address map
110-
# (e.g. DDR at 0x400_0000_0000). These must stay BELOW the defaults above and
120+
# (e.g. DDR at 0x400_0000_0000). config/examples/versal_vmk180_highddr.config
121+
# is this recipe already applied, with a worked DDR layout.
122+
# These must stay BELOW the defaults above and
111123
# use '=' so they override them. Base and size are 512 GB aligned with no
112124
# UL/ULL suffix (the assembler consumes them); the FIT ITS must then use
113125
# #address-cells = <2> with two-cell load/entry values, and the bootgen BIF
114126
# and BL31 BL33 entry must match WOLFBOOT_ORIGIN.
127+
#
128+
# Note the digit count: 0x40000800000 is 0x400_0080_0000 (8 MB into the
129+
# window), not 0x400_0800_0000 (128 MB in).
130+
#
131+
# Every address below is a distinct, non-overlapping region. The kernel and
132+
# ramdisk destinations must clear the FIT staging buffer at
133+
# WOLFBOOT_LOAD_ADDRESS, because the sub-images are read out of it while
134+
# they are being written - a large image whose destination overlaps the
135+
# staging buffer (or wolfBoot itself) hangs partway through the copy.
136+
# Size WOLFBOOT_PARTITION_SIZE for the whole signed FIT: a kernel plus a
137+
# large initramfs easily exceeds the 44 MB default set above.
115138
#WOLFBOOT_ORIGIN=0x40000800000
116139
#WOLFBOOT_LOAD_ADDRESS=0x40010000000
117140
#WOLFBOOT_LOAD_DTS_ADDRESS=0x40000001000
141+
#WOLFBOOT_LOAD_KERNEL_ADDRESS=0x40002000000
142+
#WOLFBOOT_LOAD_RAMDISK_ADDRESS=0x40030000000
118143
#CFLAGS_EXTRA+=-DVERSAL_DDR_HIGH_BASE=0x40000000000
119144
#CFLAGS_EXTRA+=-DVERSAL_DDR_HIGH_SIZE=0x10000000000
120145
#CFLAGS_EXTRA+=-DVERSAL_NO_DDR_LOW
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
# wolfBoot configuration for AMD Versal - DDR Boot with a high DDR aperture
2+
# Versal with DDR mapped at 0x400_0000_0000 instead of the default map.
3+
#
4+
# This configuration replaces U-Boot in the Versal boot flow:
5+
# PLM -> PSM -> BL31 (EL3) -> wolfBoot (EL2) -> Linux (EL1)
6+
#
7+
# Derived from versal_vmk180.config; see that file for the knobs this one
8+
# does not change. Every address here lives inside the aperture declared by
9+
# VERSAL_DDR_HIGH_BASE/SIZE, which is what generates the translation-table
10+
# entries covering it. All clock, MIO and DDR initialization is done by
11+
# PLM/PSM before wolfBoot starts.
12+
#
13+
# Three things outside this file have to agree with it:
14+
# - the bootgen BIF: wolfboot.elf at WOLFBOOT_ORIGIN, and the raw DTB
15+
# partition at WOLFBOOT_LOAD_DTS_ADDRESS
16+
# - BL31's BL33 entry (PRELOADED_BL33_BASE) = WOLFBOOT_ORIGIN
17+
# - the FIT ITS: #address-cells = <2>, because a single cell cannot hold
18+
# an address above 4 GB
19+
20+
ARCH?=AARCH64
21+
TARGET?=versal
22+
23+
WOLFBOOT_VERSION?=1
24+
25+
# ECC-384 with SHA-384 (good balance of security and performance)
26+
SIGN?=ECC384
27+
HASH?=SHA384
28+
IMAGE_HEADER_SIZE?=512
29+
30+
# RSA 4096-bit with SHA3-384 (alternative)
31+
#SIGN?=RSA4096
32+
#HASH?=SHA3
33+
#IMAGE_HEADER_SIZE?=1024
34+
35+
# Debug options
36+
DEBUG?=1
37+
DEBUG_SYMBOLS=1
38+
DEBUG_UART=1
39+
40+
# Boot Benchmarking (optional):
41+
# Enables timing of boot operations (flash read, integrity, signature).
42+
BOOT_BENCHMARK?=1
43+
44+
VTOR?=1
45+
CORTEX_M0?=0
46+
NO_ASM?=0
47+
ALLOW_DOWNGRADE?=0
48+
NVM_FLASH_WRITEONCE?=0
49+
V?=0
50+
SPMATH?=1
51+
RAM_CODE?=0
52+
DUALBANK_SWAP?=0
53+
PKA?=0
54+
WOLFTPM?=0
55+
56+
# Flash configuration
57+
EXT_FLASH?=1
58+
NO_XIP=1
59+
60+
# Boot Exception Level
61+
# Choose the exception level for booting applications (mutually exclusive):
62+
# BOOT_EL1: Transition applications to EL1 (default - for Linux, most bare-metal)
63+
# BOOT_EL2: Boot applications at EL2 (for hypervisors, RTOSes that expect EL2)
64+
# Default is BOOT_EL1 if neither is specified.
65+
# Uncomment one of the following to override:
66+
#BOOT_EL1=1
67+
#BOOT_EL2=1
68+
69+
# ELF loading support
70+
ELF?=1
71+
72+
# Native gzip decompression for FIT subimages (set GZIP=0 to disable)
73+
GZIP?=1
74+
75+
# FIT ramdisk (initramfs) extraction plus the /chosen/linux,initrd-{start,end}
76+
# fixup. A stock PetaLinux image.ub carries a ramdisk sub-image that a U-Boot
77+
# "bootm" loads; without this wolfBoot ignores it.
78+
FIT_RAMDISK?=1
79+
80+
# WOLFBOOT_LOAD_KERNEL_ADDRESS / WOLFBOOT_LOAD_RAMDISK_ADDRESS override the
81+
# FIT's own `load`/`entry`, which is what lets a FIT built without them boot
82+
# at all (Yocto omits both unless UBOOT_LOADADDRESS/UBOOT_ENTRYPOINT are
83+
# set). Both are set in the DDR layout below.
84+
85+
# Toolchain
86+
USE_GCC=1
87+
CROSS_COMPILE=aarch64-none-elf-
88+
89+
# ============================================================================
90+
# Boot Memory Layout
91+
# ============================================================================
92+
# wolfBoot runs from DDR inside the high aperture, at EL2 non-secure.
93+
# WOLFBOOT_ORIGIN is set with the rest of the layout further down - the
94+
# bootgen BIF partition header and BL31's PRELOADED_BL33_BASE must both
95+
# name that same address, not the 0x8000000 the default-map configs use.
96+
97+
# Optional debugging with OCRAM
98+
# Versal Gen 1 (VMK180): OCM is 256KB at 0xFFFC0000 - 0xFFFFFFFF
99+
# Versal Gen 2: OCM is 2MB at 0xFFE00000 - 0xFFFFFFFF
100+
#WOLFBOOT_ORIGIN=0xFFFC0000
101+
102+
# Flash Sector Size (QSPI)
103+
WOLFBOOT_SECTOR_SIZE=0x20000
104+
105+
# Application Partition Size (44MB)
106+
WOLFBOOT_PARTITION_SIZE=0x2C00000
107+
108+
# Location in Flash for Primary Boot Partition
109+
WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x800000
110+
111+
# Load Partition to RAM Address (Linux kernel loads here)
112+
WOLFBOOT_LOAD_ADDRESS?=0x10000000
113+
114+
# Location in Flash for Secondary Partition (update image)
115+
WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x3400000
116+
117+
# Location to store wolfBoot state/swap
118+
WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x6000000
119+
120+
# DTS (Device Tree) - matches addresses from BOOT.BIN analysis
121+
WOLFBOOT_LOAD_DTS_ADDRESS?=0x1000
122+
123+
# The aperture itself. Base and size are 512 GB aligned with no UL/ULL
124+
# suffix, because the assembler consumes them when it builds the
125+
# translation tables. VERSAL_NO_DDR_LOW drops the default low-DDR mapping
126+
# for parts that have none.
127+
CFLAGS_EXTRA+=-DVERSAL_DDR_HIGH_BASE=0x40000000000
128+
CFLAGS_EXTRA+=-DVERSAL_DDR_HIGH_SIZE=0x10000000000
129+
CFLAGS_EXTRA+=-DVERSAL_NO_DDR_LOW
130+
131+
# DDR layout inside the aperture. These use '=' so they override the '?='
132+
# defaults above. Each region is distinct: the kernel and ramdisk
133+
# destinations clear the FIT staging buffer at WOLFBOOT_LOAD_ADDRESS,
134+
# because the sub-images are read out of it while they are being written,
135+
# and a destination that overlaps the staging buffer or wolfBoot itself
136+
# hangs partway through the copy.
137+
#
138+
# 0x400_0000_1000 DTB (WOLFBOOT_LOAD_DTS_ADDRESS)
139+
# 0x400_0080_0000 wolfBoot (WOLFBOOT_ORIGIN)
140+
# 0x400_0200_0000 kernel (WOLFBOOT_LOAD_KERNEL_ADDRESS)
141+
# 0x400_1000_0000 FIT staging (WOLFBOOT_LOAD_ADDRESS)
142+
# 0x400_3000_0000 ramdisk (WOLFBOOT_LOAD_RAMDISK_ADDRESS)
143+
WOLFBOOT_ORIGIN=0x40000800000
144+
WOLFBOOT_LOAD_DTS_ADDRESS=0x40000001000
145+
WOLFBOOT_LOAD_KERNEL_ADDRESS=0x40002000000
146+
WOLFBOOT_LOAD_ADDRESS=0x40010000000
147+
WOLFBOOT_LOAD_RAMDISK_ADDRESS=0x40030000000
148+
WOLFBOOT_DTS_BOOT_ADDRESS?=0x7B0000
149+
WOLFBOOT_DTS_UPDATE_ADDRESS?=0x39B0000
150+
151+
# Speed up reads by using larger blocks
152+
CFLAGS_EXTRA+=-DWOLFBOOT_SHA_BLOCK_SIZE=4096
153+
154+
# UART Configuration - UART0 for APU console
155+
CFLAGS_EXTRA+=-DDEBUG_UART_NUM=0
156+
157+
# QSPI Reference Clock: Ref (300MHz default for Versal)
158+
#CFLAGS_EXTRA+=-DGQSPI_CLK_REF=300000000
159+
160+
# QSPI Bus Divisor: (2 << div) = BUS (0=div2, 1=div4, 2=div8)
161+
# MT25QU01G max: 133MHz Quad Read (0x6C) with 8 dummy cycles
162+
# div=0: 300MHz/2 = 150MHz (above spec but tested working)
163+
# div=1: 300MHz/4 = 75MHz (within spec, default)
164+
# div=2: 300MHz/8 = 37.5MHz (conservative)
165+
#CFLAGS_EXTRA+=-DGQSPI_CLK_DIV=1
166+
167+
# QSPI flash options (uncomment to enable)
168+
#CFLAGS_EXTRA+=-DDEBUG_QSPI # Enable QSPI debug logging
169+
#CFLAGS_EXTRA+=-DGQSPI_MODE_IO # Use polling instead of DMA (slower)
170+
#CFLAGS_EXTRA+=-DTEST_EXT_FLASH # Run flash erase/write/read test

‎docs/Targets.md‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5146,6 +5146,41 @@ A stock PetaLinux `image.ub` carries a `ramdisk` sub-image that `bootm` passes t
51465146

51475147
`WOLFBOOT_LOAD_RAMDISK_ADDRESS` defaults to 0, which uses the ramdisk in place inside the staged FIT. Set it to a DDR address clear of the kernel, DTB and staging area if the payload needs a fixed location.
51485148

5149+
##### FIT images built without `load`/`entry`
5150+
5151+
Some producers emit a FIT whose kernel node declares neither `load` nor `entry` - Yocto's `kernel-fitimage` class omits both unless `UBOOT_LOADADDRESS` and `UBOOT_ENTRYPOINT` are set - and leave it to U-Boot to place the image. wolfBoot needs a destination: a `compression = "gzip"` kernel has nowhere to decompress to, and an uncompressed one would be entered in place inside the staged FIT at whatever alignment the FIT happens to give it, which does not satisfy the arm64 boot protocol's 2 MB-aligned base.
5152+
5153+
Either add the properties to the ITS, or set `WOLFBOOT_LOAD_KERNEL_ADDRESS` in the config to the address the kernel should be staged at. A nonzero value overrides the FIT's `load`/`entry` for the kernel node and is returned as the entry point; 0 (the default) honors whatever the FIT declares. `WOLFBOOT_LOAD_RAMDISK_ADDRESS` does the same for the `ramdisk` node.
5154+
5155+
For a DDR aperture above 4 GB the ITS must use `#address-cells = <2>` and two-cell values, since a single cell cannot hold the address:
5156+
5157+
```dts
5158+
/ {
5159+
#address-cells = <2>;
5160+
images {
5161+
kernel-1 {
5162+
data = /incbin/("Image.gz");
5163+
compression = "gzip";
5164+
load = <0x00000400 0x08000000>;
5165+
entry = <0x00000400 0x08000000>;
5166+
hash-1 { algo = "sha256"; };
5167+
};
5168+
};
5169+
};
5170+
```
5171+
5172+
##### FIT images with no device tree
5173+
5174+
A kernel-only FIT - no `fdt` sub-image, and no `fdt` property on the configuration node - takes its device tree from the boot firmware instead, which is the arrangement U-Boot describes with `fdtcontroladdr`. Point `WOLFBOOT_LOAD_DTS_ADDRESS` at wherever the earlier stage left the blob; for a bootgen raw partition that is the `load` address in the BIF:
5175+
5176+
```
5177+
{ type=raw, load=0x40000001000, file=system-top.dtb }
5178+
```
5179+
5180+
wolfBoot then relocates and validates that DTB exactly as it does for a non-FIT payload, and hands it to the kernel in `x0`.
5181+
5182+
Because such a DTB is outside the FIT, the wolfBoot signature does not cover it, so it is not treated as authenticated: `/chosen/bootargs` from the blob is **not** trusted and `LINUX_BOOTARGS` replaces it (see below). Bind a digest with `sign --dts` to have the DTB authenticated and its own bootargs honored, and set `WOLFBOOT_REQUIRE_SIGNED_DTB=1` to make a missing digest fatal rather than a warning.
5183+
51495184
**Kernel Command Line (bootargs)**
51505185

51515186
If the FIT's DTB carries `/chosen/bootargs`, wolfBoot keeps them by default - an image boots with the arguments its kernel was validated with. Setting `LINUX_BOOTARGS` or `LINUX_BOOTARGS_ROOT` in the config replaces the DTB's value (the replaced value is logged); `CFLAGS_EXTRA+=-DLINUX_BOOTARGS_OVERRIDE=0` demotes an explicit `LINUX_BOOTARGS` to a fallback used only when the DTB has none.

‎include/fdt.h‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,12 @@ void* fit_load_image_ex(fdt_ctx* ctx, const char* image, int* lenp,
404404
void* fit_load_image_to(fdt_ctx* ctx, const char* image, void* dst,
405405
uint32_t dst_max, int* lenp);
406406

407+
/* Load the FIT kernel sub-image, relocated to
408+
* WOLFBOOT_LOAD_KERNEL_ADDRESS when that is nonzero (which overrides
409+
* the FIT's `load`/`entry`, so a FIT built without them still boots).
410+
* Returns the kernel entry address, or NULL on failure. */
411+
void* fit_load_kernel(fdt_ctx* ctx, const char* kernel_node, int* lenp);
412+
407413
#ifdef WOLFBOOT_FIT_RAMDISK
408414
/* Load a FIT ramdisk sub-image (optionally relocated to
409415
* WOLFBOOT_LOAD_RAMDISK_ADDRESS) and patch /chosen/linux,initrd-* in

‎options.mk‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,6 +1096,24 @@ ifeq ($(FIT_RAMDISK),1)
10961096
CFLAGS+=-DWOLFBOOT_FIT_RAMDISK
10971097
endif
10981098

1099+
# Load address for the FIT kernel sub-image. 0 (the default) means "honor
1100+
# the FIT's own `load` property instead". Set this when the FIT was built
1101+
# without `load`/`entry` on the kernel node: a producer that omits them
1102+
# leaves U-Boot to pick the address, and a gzip kernel cannot be
1103+
# decompressed at all without a destination. Pick a region clear of the
1104+
# FIT staging area (WOLFBOOT_LOAD_ADDRESS) and of the DTB/ramdisk
1105+
# addresses.
1106+
#
1107+
# Passed as a CFLAG rather than through include/target.h.in because
1108+
# src/fdt.c reads it unconditionally, and target.h is generated by three
1109+
# different paths (this Makefile, CMakeLists.txt and stage1/Makefile) that
1110+
# do not all substitute the optional load addresses. src/fdt.c defaults it
1111+
# to 0 when it is not defined.
1112+
WOLFBOOT_LOAD_KERNEL_ADDRESS ?= 0
1113+
ifneq ($(WOLFBOOT_LOAD_KERNEL_ADDRESS),0)
1114+
CFLAGS+=-DWOLFBOOT_LOAD_KERNEL_ADDRESS=$(WOLFBOOT_LOAD_KERNEL_ADDRESS)
1115+
endif
1116+
10991117
# FPGA_BITSTREAM=1 enables loading an "fpga" sub-image from a FIT and
11001118
# programming the PL before booting (Xilinx ZynqMP/Zynq-7000; Versal is
11011119
# stubbed pending a PLM Load-PDI path). Off by default.

‎src/boot_aarch64.c‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,10 +155,10 @@ void RAMFUNCTION do_boot(const uint32_t *app_offset, const uint32_t* dts_offset)
155155
void RAMFUNCTION do_boot(const uint32_t *app_offset)
156156
#endif
157157
{
158-
wolfBoot_printf("do_boot: entry=0x%08x, EL=%d\n",
159-
(uint32_t)(uintptr_t)app_offset, current_el());
158+
wolfBoot_printf("do_boot: entry=%p, EL=%d\n", (void*)app_offset,
159+
current_el());
160160
#ifdef MMU
161-
wolfBoot_printf("do_boot: dts=0x%08x\n", (uint32_t)(uintptr_t)dts_offset);
161+
wolfBoot_printf("do_boot: dts=%p\n", (void*)dts_offset);
162162
/* WOLFBOOT_DTS_MAX_SIZE is this target's DTS staging-window size
163163
* (see include/fdt.h); it bounds the fixups below. */
164164
hal_dts_fixup((uint32_t*)dts_offset, WOLFBOOT_DTS_MAX_SIZE);

‎src/fdt.c‎

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -804,7 +804,17 @@ void* fdt_getprop_address(const fdt_ctx* ctx, int nodeoffset, const char* name)
804804
return NULL;
805805
}
806806
if (len == 8) {
807-
return (void*)(uintptr_t)fdt_rd64u(val);
807+
uint64_t addr64 = fdt_rd64u(val);
808+
/* A two-cell value wider than the target's pointer must be
809+
* rejected, not truncated: silently dropping the high cell turns
810+
* an out-of-range address into an unrelated low one that the
811+
* caller would then copy to or branch to. */
812+
#if UINTPTR_MAX < UINT64_MAX
813+
if (addr64 > (uint64_t)UINTPTR_MAX) {
814+
return NULL;
815+
}
816+
#endif
817+
return (void*)(uintptr_t)addr64;
808818
}
809819
if (len == 4) {
810820
return (void*)(uintptr_t)fdt_rd32(val);
@@ -1649,6 +1659,35 @@ const char* fit_get_compatible(fdt_ctx* ctx, const char* image)
16491659
return NULL;
16501660
}
16511661

1662+
/* Defensive fallback: targets that never set a kernel relocation
1663+
* address leave WOLFBOOT_LOAD_KERNEL_ADDRESS at 0, in which case the
1664+
* FIT's own `load` property is honored. */
1665+
#ifndef WOLFBOOT_LOAD_KERNEL_ADDRESS
1666+
#define WOLFBOOT_LOAD_KERNEL_ADDRESS 0
1667+
#endif
1668+
1669+
/* Upper bound on the (decompressed) kernel size. Defaults to the
1670+
* generic FIT decompression cap. */
1671+
#ifndef WOLFBOOT_FIT_MAX_KERNEL
1672+
#define WOLFBOOT_FIT_MAX_KERNEL WOLFBOOT_FIT_MAX_DECOMP
1673+
#endif
1674+
1675+
/* Load the FIT kernel sub-image. If WOLFBOOT_LOAD_KERNEL_ADDRESS is
1676+
* nonzero the kernel is staged there and the FIT's `load`/`entry` are
1677+
* bypassed, which is what lets a FIT whose kernel node declares neither
1678+
* one boot at all: without a destination a gzip kernel cannot be
1679+
* decompressed, and an uncompressed one would be entered in place at
1680+
* whatever alignment the FIT happens to give it. */
1681+
void* fit_load_kernel(fdt_ctx* ctx, const char* kernel_node, int* lenp)
1682+
{
1683+
if (WOLFBOOT_LOAD_KERNEL_ADDRESS != 0) {
1684+
return fit_load_image_to(ctx, kernel_node,
1685+
(void*)WOLFBOOT_LOAD_KERNEL_ADDRESS,
1686+
(uint32_t)WOLFBOOT_FIT_MAX_KERNEL, lenp);
1687+
}
1688+
return fit_load_image(ctx, kernel_node, lenp);
1689+
}
1690+
16521691
#ifdef WOLFBOOT_FIT_RAMDISK
16531692
/* Defensive fallback: targets without a fixed relocation address
16541693
* leave WOLFBOOT_LOAD_RAMDISK_ADDRESS at 0, in which case the
@@ -1916,7 +1955,10 @@ static void* fit_load_image_inner(fdt_ctx* ctx, const char* image, int* lenp,
19161955
wolfBoot_printf("FIT: subimage '%s' declares "
19171956
"compression=\"%s\" but has no distinct load "
19181957
"destination (load=%p, data=%p); refusing to pass "
1919-
"compressed bytes through as raw\n",
1958+
"compressed bytes through as raw. Add `load` to the "
1959+
"FIT node; the kernel, ramdisk and fpga loaders can "
1960+
"take WOLFBOOT_LOAD_{KERNEL,RAMDISK,FPGA}_ADDRESS "
1961+
"instead\n",
19201962
image, compstr, load, data);
19211963
return NULL;
19221964
}

0 commit comments

Comments
 (0)