summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPali Rohár <pali@kernel.org>2023-01-08 13:46:14 +0100
committerStefan Roese <sr@denx.de>2023-03-01 06:39:17 +0100
commita190667b111bd2731a8cef173c0e84e14fb14218 (patch)
treea4442394a0b359fe58d2c0459faefeea54fc7b9c
parent53ee6ec82744666719f2c9954a013c4397b77be9 (diff)
downloadu-boot-a190667b111bd2731a8cef173c0e84e14fb14218.tar.gz
u-boot-a190667b111bd2731a8cef173c0e84e14fb14218.tar.bz2
u-boot-a190667b111bd2731a8cef173c0e84e14fb14218.zip
tools: kwboot: Add check that kwbimage contains DDR init code
Some NOR images may be execute-in-place and do not contain DDR init code in its kwbimage header. Such images cannot be booted over UART as BootROM loads them to RAM. Add check that kwbimage contains DDR init code in its header (either as binary code header or as the simple register-value set). In some cases it is possible to load very small image into L2SRAM and when DDR init code is not required. So check for L2SRAM load address and skip DDR init code check in this case. Signed-off-by: Pali Rohár <pali@kernel.org>
-rw-r--r--tools/kwboot.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/tools/kwboot.c b/tools/kwboot.c
index c8c7a8d246..f624edc779 100644
--- a/tools/kwboot.c
+++ b/tools/kwboot.c
@@ -1780,6 +1780,47 @@ kwboot_img_is_secure(void *img)
return 0;
}
+static int
+kwboot_img_has_ddr_init(void *img)
+{
+ const struct register_set_hdr_v1 *rhdr;
+ const struct main_hdr_v0 *hdr0;
+ struct opt_hdr_v1 *ohdr;
+ u32 ohdrsz;
+ int last;
+
+ /*
+ * kwbimage v0 image headers contain DDR init code either in
+ * extension header or in binary code header.
+ */
+ if (kwbimage_version(img) == 0) {
+ hdr0 = img;
+ return hdr0->ext || hdr0->bin;
+ }
+
+ /*
+ * kwbimage v1 image headers contain DDR init code either in binary
+ * code header or in a register set list header with SDRAM_SETUP.
+ */
+ for_each_opt_hdr_v1 (ohdr, img) {
+ if (ohdr->headertype == OPT_HDR_V1_BINARY_TYPE)
+ return 1;
+ if (ohdr->headertype == OPT_HDR_V1_REGISTER_TYPE) {
+ rhdr = (const struct register_set_hdr_v1 *)ohdr;
+ ohdrsz = opt_hdr_v1_size(ohdr);
+ if (ohdrsz >= sizeof(*ohdr) + sizeof(rhdr->data[0].last_entry)) {
+ ohdrsz -= sizeof(*ohdr) + sizeof(rhdr->data[0].last_entry);
+ last = ohdrsz / sizeof(rhdr->data[0].entry);
+ if (rhdr->data[last].last_entry.delay ==
+ REGISTER_SET_HDR_OPT_DELAY_SDRAM_SETUP)
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
static void *
kwboot_img_grow_data_right(void *img, size_t *size, size_t grow)
{
@@ -2011,6 +2052,13 @@ kwboot_img_patch(void *img, size_t *size, int baudrate)
kwboot_img_grow_data_right(img, size, sizeof(uint32_t));
}
+ if (!kwboot_img_has_ddr_init(img) &&
+ (le32_to_cpu(hdr->destaddr) < 0x40000000 ||
+ le32_to_cpu(hdr->destaddr) + le32_to_cpu(hdr->blocksize) > 0x40034000)) {
+ fprintf(stderr, "Image does not contain DDR init code needed for UART booting\n");
+ goto err;
+ }
+
is_secure = kwboot_img_is_secure(img);
if (hdr->blockid != IBR_HDR_UART_ID) {