summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/binman/entries.rst10
-rw-r--r--tools/binman/etype/nxp_header_ddrfw.py29
-rw-r--r--tools/binman/ftest.py11
-rw-r--r--tools/binman/test/346_nxp_ddrfw_imx95.dts24
-rw-r--r--tools/imx8image.c147
-rwxr-xr-xtools/imx9_image.sh8
6 files changed, 213 insertions, 16 deletions
diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst
index 780e9817fb6..4f05aa0a323 100644
--- a/tools/binman/entries.rst
+++ b/tools/binman/entries.rst
@@ -1663,6 +1663,16 @@ Properties / Entry arguments:
+.. _etype_nxp_header_ddrfw:
+
+Entry: nxp-header-ddrfw: add a header to DDR PHY firmware images
+----------------------------------------------------------------
+
+This entry is used to combine DDR PHY firmware images and their byte counts
+together. See imx95_evk.rst for how to get DDR PHY Firmware Images.
+
+
+
.. _etype_opensbi:
Entry: opensbi: RISC-V OpenSBI fw_dynamic blob
diff --git a/tools/binman/etype/nxp_header_ddrfw.py b/tools/binman/etype/nxp_header_ddrfw.py
new file mode 100644
index 00000000000..655699e6ffa
--- /dev/null
+++ b/tools/binman/etype/nxp_header_ddrfw.py
@@ -0,0 +1,29 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright 2025 NXP
+
+from binman.etype.section import Entry_section
+
+class Entry_nxp_header_ddrfw(Entry_section):
+ """Add a header to DDR PHY firmware images
+
+ This entry is used for i.MX95 to combine DDR PHY firmware images and their
+ byte counts together.
+
+ See imx95_evk.rst for how to get DDR PHY Firmware Images.
+ """
+
+ def __init__(self, section, etype, node):
+ super().__init__(section, etype, node)
+
+ def BuildSectionData(self, required):
+ section_data = bytearray()
+ header_data = bytearray()
+
+ for entry in self._entries.values():
+ entry_data = entry.GetData(required)
+
+ section_data += entry_data
+ header_data += entry.contents_size.to_bytes(4, 'little')
+
+ return header_data + section_data
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index 92df2a03650..fa174900014 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -104,6 +104,8 @@ PRE_LOAD_VERSION = 0x11223344.to_bytes(4, 'big')
PRE_LOAD_HDR_SIZE = 0x00001000.to_bytes(4, 'big')
TI_BOARD_CONFIG_DATA = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
TI_UNSECURE_DATA = b'unsecuredata'
+IMX_LPDDR_IMEM_DATA = b'qwertyuiop1234567890'
+IMX_LPDDR_DMEM_DATA = b'asdfghjklzxcvbnm'
# Subdirectory of the input dir to use to put test FDTs
TEST_FDT_SUBDIR = 'fdts'
@@ -202,6 +204,8 @@ class TestFunctional(unittest.TestCase):
TestFunctional._MakeInputFile('fsp_m.bin', FSP_M_DATA)
TestFunctional._MakeInputFile('fsp_s.bin', FSP_S_DATA)
TestFunctional._MakeInputFile('fsp_t.bin', FSP_T_DATA)
+ TestFunctional._MakeInputFile('lpddr5_imem.bin', IMX_LPDDR_IMEM_DATA)
+ TestFunctional._MakeInputFile('lpddr5_dmem.bin', IMX_LPDDR_DMEM_DATA)
cls._elf_testdir = os.path.join(cls._indir, 'elftest')
elf_test.BuildElfTestFiles(cls._elf_testdir)
@@ -7848,6 +7852,13 @@ fdt fdtmap Extract the devicetree blob from the fdtmap
"""Test that binman can produce an iMX8 image"""
self._DoTestFile('339_nxp_imx8.dts')
+ def testNxpHeaderDdrfw(self):
+ """Test that binman can add a header to DDR PHY firmware images"""
+ data = self._DoReadFile('346_nxp_ddrfw_imx95.dts')
+ self.assertEqual(len(IMX_LPDDR_IMEM_DATA).to_bytes(4, 'little') +
+ len(IMX_LPDDR_DMEM_DATA).to_bytes(4, 'little') +
+ IMX_LPDDR_IMEM_DATA + IMX_LPDDR_DMEM_DATA, data)
+
def testFitSignSimple(self):
"""Test that image with FIT and signature nodes can be signed"""
if not elf.ELF_TOOLS:
diff --git a/tools/binman/test/346_nxp_ddrfw_imx95.dts b/tools/binman/test/346_nxp_ddrfw_imx95.dts
new file mode 100644
index 00000000000..889f6f29860
--- /dev/null
+++ b/tools/binman/test/346_nxp_ddrfw_imx95.dts
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ imx-lpddr {
+ type = "nxp-header-ddrfw";
+
+ imx-lpddr-imem {
+ filename = "lpddr5_imem.bin";
+ type = "blob-ext";
+ };
+
+ imx-lpddr-dmem {
+ filename = "lpddr5_dmem.bin";
+ type = "blob-ext";
+ };
+ };
+ };
+};
diff --git a/tools/imx8image.c b/tools/imx8image.c
index 0135b190951..a333ded46e2 100644
--- a/tools/imx8image.c
+++ b/tools/imx8image.c
@@ -7,6 +7,7 @@
#include "imx8image.h"
#include <image.h>
+#include <linux/sizes.h>
static int p_idx;
static int sector_size;
@@ -54,7 +55,9 @@ static table_entry_t imx8image_cmds[] = {
{CMD_CONTAINER, "CONTAINER", "new container", },
{CMD_IMAGE, "IMAGE", "new image", },
{CMD_DATA, "DATA", "new data", },
- {-1, "", "", },
+ {CMD_DUMMY_V2X, "DUMMY_V2X", "v2x", },
+ {CMD_HOLD, "HOLD", "hold", },
+ {-1, "", "", }
};
static table_entry_t imx8image_core_entries[] = {
@@ -66,7 +69,9 @@ static table_entry_t imx8image_core_entries[] = {
{CFG_A55, "A55", "A55 core", },
{CFG_A53, "A53", "A53 core", },
{CFG_A72, "A72", "A72 core", },
- {-1, "", "", },
+ {CFG_OEI, "OEI", "OEI", },
+ {CFG_M33, "M33", "M33 core", },
+ {-1, "", "", }
};
static table_entry_t imx8image_sector_size[] = {
@@ -144,6 +149,14 @@ static void parse_cfg_cmd(image_t *param_stack, int32_t cmd, char *token,
exit(EXIT_FAILURE);
}
break;
+ case CMD_DUMMY_V2X:
+ param_stack[p_idx].option = DUMMY_V2X;
+ param_stack[p_idx++].entry = (uint32_t)strtoll(token, NULL, 0);
+ break;
+ case CMD_HOLD:
+ param_stack[p_idx].option = HOLD;
+ param_stack[p_idx].entry = (uint32_t)strtoll(token, NULL, 0);
+ param_stack[p_idx++].filename = NULL;
default:
break;
}
@@ -221,6 +234,16 @@ static void parse_cfg_fld(image_t *param_stack, int32_t *cmd, char *token,
(*cmd == CMD_DATA) ? DATA : AP;
param_stack[p_idx].filename = token;
break;
+ case CFG_OEI:
+ param_stack[p_idx].option = OEI;
+ param_stack[p_idx].filename = token;
+ param_stack[p_idx].ext = CORE_CM4_0;
+ break;
+ case CFG_M33:
+ param_stack[p_idx].option = M40;
+ param_stack[p_idx].ext = 0;
+ param_stack[p_idx].filename = token;
+ break;
}
break;
case CFG_LOAD_ADDR:
@@ -238,9 +261,15 @@ static void parse_cfg_fld(image_t *param_stack, int32_t *cmd, char *token,
case CFG_A53:
case CFG_A55:
case CFG_A72:
+ case CFG_M33:
param_stack[p_idx++].entry =
(uint32_t)strtoll(token, NULL, 0);
break;
+ case CFG_OEI:
+ param_stack[p_idx].dst = (uint32_t)strtoll(token, NULL, 0);
+ param_stack[p_idx].entry = param_stack[p_idx].dst + 1;
+ p_idx++;
+ break;
}
default:
break;
@@ -549,6 +578,7 @@ static void set_image_array_entry(flash_header_v3_t *container,
char *tmp_filename, bool dcd_skip)
{
uint64_t entry = image_stack->entry;
+ uint64_t dst = image_stack->dst;
uint64_t core = image_stack->ext;
uint32_t meta;
char *tmp_name = "";
@@ -558,7 +588,9 @@ static void set_image_array_entry(flash_header_v3_t *container,
img->offset = offset; /* Is re-adjusted later */
img->size = size;
- set_image_hash(img, tmp_filename, IMAGE_HASH_ALGO_DEFAULT);
+ if (type != DUMMY_V2X) {
+ set_image_hash(img, tmp_filename, IMAGE_HASH_ALGO_DEFAULT);
+ }
switch (type) {
case SECO:
@@ -580,6 +612,27 @@ static void set_image_array_entry(flash_header_v3_t *container,
img->dst = 0xe4000000; /* S400 IRAM base */
img->entry = 0xe4000000;
break;
+ case OEI:
+ if (soc != IMX9) {
+ fprintf(stderr, "Error: invalid core id: %" PRIi64 "\n", core);
+ exit(EXIT_FAILURE);
+ }
+
+ img->hab_flags |= IMG_TYPE_OEI;
+ if (core == CORE_CM4_0) {
+ img->hab_flags |= CORE_ULP_CM33 << BOOT_IMG_FLAGS_CORE_SHIFT;
+ meta = CORE_IMX95_M33P;
+
+ } else {
+ img->hab_flags |= CORE_ULP_CA35 << BOOT_IMG_FLAGS_CORE_SHIFT;
+ meta = CORE_IMX95_A55C0;
+ }
+ tmp_name = "OEI";
+ img->dst = (dst ? dst : entry);
+ img->entry = entry;
+ img->meta = meta;
+ custom_partition = 0;
+ break;
case AP:
if (soc == QX && core == CORE_CA35) {
meta = IMAGE_A35_DEFAULT_META(custom_partition);
@@ -587,8 +640,10 @@ static void set_image_array_entry(flash_header_v3_t *container,
meta = IMAGE_A53_DEFAULT_META(custom_partition);
} else if (soc == QM && core == CORE_CA72) {
meta = IMAGE_A72_DEFAULT_META(custom_partition);
- } else if (((soc == ULP) || (soc == IMX9)) && core == CORE_CA35) {
+ } else if ((soc == ULP) && core == CORE_CA35) {
meta = 0;
+ } else if ((soc == IMX9) && core == CORE_CA35) {
+ meta = CORE_IMX95_A55C0;
} else {
fprintf(stderr,
"Error: invalid AP core id: %" PRIu64 "\n",
@@ -687,6 +742,15 @@ static void set_image_array_entry(flash_header_v3_t *container,
img->entry = 0x28300200;
}
break;
+ case DUMMY_V2X:
+ img->hab_flags |= IMG_TYPE_V2X_DUMMY;
+ img->hab_flags |= CORE_SC << BOOT_IMG_FLAGS_CORE_SHIFT;
+ tmp_name = "V2X Dummy";
+ set_image_hash(img, "/dev/null", IMAGE_HASH_ALGO_DEFAULT);
+ img->dst = entry;
+ img->entry = entry;
+ img->size = 0; /* dummy image has no size */
+ break;
default:
fprintf(stderr, "unrecognized image type (%d)\n", type);
exit(EXIT_FAILURE);
@@ -709,15 +773,26 @@ void set_container(flash_header_v3_t *container, uint16_t sw_version,
fprintf(stdout, "container flags: 0x%x\n", container->flags);
}
-static int get_container_image_start_pos(image_t *image_stack, uint32_t align)
+static int get_container_image_start_pos(image_t *image_stack, uint32_t align, uint32_t *v2x)
{
image_t *img_sp = image_stack;
/*8K total container header*/
int file_off = CONTAINER_IMAGE_ARRAY_START_OFFSET;
FILE *fd = NULL;
- flash_header_v3_t header;
+ flash_header_v3_t *header;
+ flash_header_v3_t *header2;
+ void *p;
int ret;
+ p = calloc(1, SZ_4K);
+ if (!p) {
+ fprintf(stderr, "Fail to alloc 4K memory\n");
+ exit(EXIT_FAILURE);
+ }
+
+ header = p;
+ header2 = p + FIRST_CONTAINER_HEADER_LENGTH;
+
while (img_sp->option != NO_IMG) {
if (img_sp->option == APPEND) {
fd = fopen(img_sp->filename, "r");
@@ -726,7 +801,7 @@ static int get_container_image_start_pos(image_t *image_stack, uint32_t align)
exit(EXIT_FAILURE);
}
- ret = fread(&header, sizeof(header), 1, fd);
+ ret = fread(header, SZ_4K, 1, fd);
if (ret != 1) {
printf("Failure Read header %d\n", ret);
exit(EXIT_FAILURE);
@@ -734,19 +809,27 @@ static int get_container_image_start_pos(image_t *image_stack, uint32_t align)
fclose(fd);
- if (header.tag != IVT_HEADER_TAG_B0) {
- fprintf(stderr, "header tag mismatched file %s\n", img_sp->filename);
+ if (header->tag != IVT_HEADER_TAG_B0) {
+ fprintf(stderr, "header tag mismatched \n");
exit(EXIT_FAILURE);
} else {
- file_off +=
- header.img[header.num_images - 1].size;
- file_off = ALIGN(file_off, align);
+ if (header2->tag != IVT_HEADER_TAG_B0) {
+ file_off += header->img[header->num_images - 1].size;
+ file_off = ALIGN(file_off, align);
+ } else {
+ file_off = header2->img[header2->num_images - 1].offset + FIRST_CONTAINER_HEADER_LENGTH;
+ file_off += header2->img[header2->num_images - 1].size;
+ file_off = ALIGN(file_off, align);
+ fprintf(stderr, "Has 2nd container %x\n", file_off);
+ *v2x = true;
+ }
}
}
img_sp++;
}
+ free(p);
return file_off;
}
@@ -838,6 +921,7 @@ static int build_container(soc_type_t soc, uint32_t sector_size,
char *tmp_filename = NULL;
uint32_t size = 0;
uint32_t file_padding = 0;
+ uint32_t v2x = false;
int ret;
int container = -1;
@@ -861,7 +945,7 @@ static int build_container(soc_type_t soc, uint32_t sector_size,
set_imx_hdr_v3(&imx_header, 0);
set_imx_hdr_v3(&imx_header, 1);
- file_off = get_container_image_start_pos(image_stack, sector_size);
+ file_off = get_container_image_start_pos(image_stack, sector_size, &v2x);
fprintf(stdout, "container image offset (aligned):%x\n", file_off);
/* step through image stack and generate the header */
@@ -870,6 +954,7 @@ static int build_container(soc_type_t soc, uint32_t sector_size,
/* stop once we reach null terminator */
while (img_sp->option != NO_IMG) {
switch (img_sp->option) {
+ case OEI:
case AP:
case M40:
case M41:
@@ -892,6 +977,30 @@ static int build_container(soc_type_t soc, uint32_t sector_size,
file_off += ALIGN(sbuf.st_size, sector_size);
break;
+ case DUMMY_V2X:
+ if (container < 0) {
+ fprintf(stderr, "No container found\n");
+ exit(EXIT_FAILURE);
+ }
+ tmp_filename = "dummy";
+ set_image_array_entry(&imx_header.fhdr[container],
+ soc,
+ img_sp,
+ file_off,
+ 0,
+ tmp_filename,
+ dcd_skip);
+ img_sp->src = file_off;
+ break;
+
+ case HOLD:
+ if (container < 0) {
+ fprintf(stderr, "No container found\n");
+ exit(EXIT_FAILURE);
+ }
+ file_off += ALIGN(img_sp->entry, sector_size);
+ break;
+
case SECO:
case SENTINEL:
if (container < 0) {
@@ -963,11 +1072,15 @@ static int build_container(soc_type_t soc, uint32_t sector_size,
do {
if (img_sp->option == APPEND) {
copy_file(ofd, img_sp->filename, 0, 0);
- file_padding += FIRST_CONTAINER_HEADER_LENGTH;
+ if (v2x)
+ file_padding += FIRST_CONTAINER_HEADER_LENGTH * 2;
+ else
+ file_padding += FIRST_CONTAINER_HEADER_LENGTH;
}
img_sp++;
} while (img_sp->option != NO_IMG);
+ fprintf(stderr, "%s: %x %d\n", __func__, file_padding, v2x);
/* Add padding or skip appended container */
ret = lseek(ofd, file_padding, SEEK_SET);
if (ret < 0) {
@@ -980,6 +1093,7 @@ static int build_container(soc_type_t soc, uint32_t sector_size,
/* Note: Image offset are not contained in the image */
tmp = flatten_container_header(&imx_header, container + 1,
&size, file_padding);
+ fprintf(stderr, "error writing image hdr %x\n", size);
/* Write image header */
if (write(ofd, tmp, size) != size) {
fprintf(stderr, "error writing image hdr\n");
@@ -1000,7 +1114,8 @@ static int build_container(soc_type_t soc, uint32_t sector_size,
img_sp->option == AP || img_sp->option == DATA ||
img_sp->option == SCD || img_sp->option == SCFW ||
img_sp->option == SECO || img_sp->option == MSG_BLOCK ||
- img_sp->option == UPOWER || img_sp->option == SENTINEL) {
+ img_sp->option == UPOWER || img_sp->option == SENTINEL ||
+ img_sp->option == OEI) {
copy_file_aligned(ofd, img_sp->filename, img_sp->src,
sector_size);
}
@@ -1031,7 +1146,7 @@ int imx8image_copy_image(int outfd, struct image_tool_params *mparams)
fprintf(stdout, "CONTAINER SW VERSION:\t0x%04x\n", sw_version);
build_container(soc, sector_size, emmc_fastboot,
- img_sp, dcd_skip, fuse_version, sw_version, outfd);
+ img_sp, false, fuse_version, sw_version, outfd);
return 0;
}
diff --git a/tools/imx9_image.sh b/tools/imx9_image.sh
index ca78a57a19a..6523d1a0ad1 100755
--- a/tools/imx9_image.sh
+++ b/tools/imx9_image.sh
@@ -18,6 +18,14 @@ for f in $blobs; do
continue
fi
+ if [ $f = "m33-oei-ddrfw.bin" ]; then
+ continue
+ fi
+
+ if [ $f = "u-boot.bin" ]; then
+ continue
+ fi
+
if [ ! -f $tmp ]; then
echo "WARNING '$tmp' not found, resulting binary may be not-functional" >&2