binman: fit: Compress generated fdt images and use it on Rockchip
Subsystems (2)
v2 cover binman: fit: Compress generated fdt images and use it on Rockchip
Entry_fit's @fdt-SEQ generator always embeds the raw .dtb. Add a 'fit,compress' property so binman can compress it with any algorithm FIT defines (xz is rejected) and set 'compression' to match.
Add a generic SPL_FIT_FDT_COMP choice (none, LZMA, gzip: what the SPL FIT loader can currently decompress) and use it on Rockchip.
The default is none so no in-tree board changes.
---
Changes in v2:
- Use a binman-level 'fit,compress' property instead of acting on 'compression'
- Support all algorithms binman knows via a shared bintool-name helper
- Register the bintool in AddBintools() and handle a missing tool, reject 'xz'
- Split the test device trees and tests into their own patches
- Document the property in the Entry_fit docstring
- Expand the Rockchip commit message
- Add a generic SPL_FIT_FDT_COMP choice in boot/Kconfig used by Rockchip
- Link to v1: https://patch.msgid.link/20261010-b4-binman-fit-fdt-compression-v1-0-4465558758cc@protonmail.com
---
Petr Hodina (6):
binman: Factor out the compression bintool lookup
binman: fit: Add fit,compress for generated fdt images
binman: test: Add fit,compress device trees
binman: test: Add tests for fit,compress
boot: Add a choice for the compression of the FDT in the FIT
rockchip: Allow compression of the FDT in the FIT
arch/arm/dts/rockchip-u-boot.dtsi | 15 ++++++- boot/Kconfig | 32 ++++++++++++++ tools/binman/entry.py | 27 +++++++++--- tools/binman/etype/fit.py | 67 ++++++++++++++++++++++++++++++ tools/binman/ftest.py | 44 ++++++++++++++++++++ tools/binman/test/fit/fdt_compress.dts | 24 +++++++++++ tools/binman/test/fit/fdt_compress_bad.dts | 24 +++++++++++ tools/binman/test/fit/fdt_compress_xz.dts | 24 +++++++++++ 8 files changed, 250 insertions(+), 7 deletions(-)
---
base-commit: 8d534cec0cc0109a37c0ded8854da03f1526dc0e
change-id: 20261010-b4-binman-fit-fdt-compression-3166bcbd15b5
Best regards,
Signature · 1 line
Petr Hodina <[email protected]>
PATCH v2 1/6 binman: Factor out the compression bintool lookup
Move the compression-algorithm-to-bintool mapping out of Entry.AddBintools() into get_comp_bintool_name() so that it can be shared with other etypes.
--- tools/binman/entry.py | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-)
tools/binman/entry.py +21 -6
@@ -1297,12 +1297,27 @@ features to produce new behaviours. """ algo = self.compress if algo != 'none': - algos = ['bzip2', 'gzip', 'lz4', 'lzma', 'lzo', 'xz', 'zstd'] - if algo not in algos: - raise ValueError("Unknown algorithm '%s'" % algo) - names = {'lzma': 'lzma_alone', 'lzo': 'lzop'} - name = names.get(self.compress, self.compress) - self.comp_bintool = self.AddBintool(btools, name) + self.comp_bintool = self.AddBintool( + btools, self.get_comp_bintool_name(algo)) + + @staticmethod + def get_comp_bintool_name(algo): + """Get the name of the bintool which handles a compression algorithm + + Args: + algo (str): Compression algorithm, e.g. 'gzip' + + Returns: + str: Name of bintool + + Raises: + ValueError: if the algorithm is not supported + """ + algos = ['bzip2', 'gzip', 'lz4', 'lzma', 'lzo', 'xz', 'zstd'] + if algo not in algos: + raise ValueError("Unknown algorithm '%s'" % algo) + names = {'lzma': 'lzma_alone', 'lzo': 'lzop'} + return names.get(algo, algo) @classmethod def AddBintool(self, tools, name):
Signature · 1 line
2.55.0
Re: [PATCH v2 1/6] binman: Factor out the compression bintool lookup
Quoted 10 lines · On 2026-10-17T07:38:59, Petr Hodina via B4 Relay…
binman: Factor out the compression bintool lookup
Move the compression-algorithm-to-bintool mapping out of
Entry.AddBintools()intoget_comp_bintool_name()so that it can be shared with other etypes.Signed-off-by Petr Hodina <[email protected]>
tools/binman/entry.py| 27 +++++++++++++++++++++------1 file changed, 21 insertions(+), 6 deletions(-)
Re: [PATCH v2 1/6] binman: Factor out the compression bintool lookup
In reply to Petr HodinaHi Petr,
Quoted 36 lines · On 10/17/26 9:39 AM, Petr Hodina via B4 Relay wrote:
From: Petr Hodina <[email protected]>
Move the compression-algorithm-to-bintool mapping out of
Entry.AddBintools()intoget_comp_bintool_name()so that it can be shared with other etypes.Signed-off-by Petr Hodina <[email protected]>--- tools/binman/entry.py | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-)tools/binman/entry.py +11
-6@@ -1297,12 +1297,27 @@ features to produce new behaviours. """ algo = self.compress if algo != 'none': - algos = ['bzip2', 'gzip', 'lz4', 'lzma', 'lzo', 'xz', 'zstd'] - if algo not in algos: - raise ValueError("Unknown algorithm '%s'" % algo) - names = {'lzma': 'lzma_alone', 'lzo': 'lzop'} - name = names.get(self.compress, self.compress) - self.comp_bintool = self.AddBintool(btools, name) + self.comp_bintool = self.AddBintool( + btools, self.get_comp_bintool_name(algo)) + + @staticmethod + def get_comp_bintool_name(algo): + """Get the name of the bintool which handles a compression algorithm + + Args: + algo (str): Compression algorithm, e.g. 'gzip' + + Returns:
tools/binman/entry.py features to produce new behaviours. · line 1320
Quoted 10 lines
tools/binman/entry.py +10
-0+ str: Name of bintool + + Raises: + ValueError: if the algorithm is not supported + """ + algos = ['bzip2', 'gzip', 'lz4', 'lzma', 'lzo', 'xz', 'zstd'] + if algo not in algos: + raise ValueError("Unknown algorithm '%s'" % algo) + names = {'lzma': 'lzma_alone', 'lzo': 'lzop'} + return names.get(algo, algo)
I can't help but think this is the wrong way to handle that. Why should Entry deal with Bintool stuff?
I'm thinking this is best handled by at the very least a static method in Bintool instead.
In a future patch, I think it would also make sense to not have this hardcoded in Bintool class at all and have every BintoolPacker report which algorithms they handle so we don't have to keep a list of supported algorithms outside of the one class it matters, the one supporting the algorithm.
Cheers,
Quentin
PATCH v2 2/6 binman: fit: Add fit,compress for generated fdt images
In reply to Petr HodinaThe 'compression' property of a FIT image is only metadata.
Add a 'fit,compress' property for generator nodes. It names the algorithm so binman compresses each .dtb with it and writes the algorithm to 'compression' in the generated node.
Any algorithm known to Entry.AddBintools() is accepted.
Register the needed bintools in Entry_fit.AddBintools() and report a missing one in the usual way instead of failing.
Document the property.
--- tools/binman/etype/fit.py | 67 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+)
tools/binman/etype/fit.py +67 -0
@@ -274,6 +274,29 @@ class Entry_fit(Entry_section): string from the root node of the devicetree, so that things work correctly with FIT's configuration-matching algortihm. + Compressing the FDT images + ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + The 'compression' property of an image node is copied into the FIT as + metadata only. It tells the loader how the data is stored, but binman does + not touch the data. + For generated FDT nodes, the 'fit,compress' property can be used to ask + binman to compress the .dtb as well. The algorithm is written to + the 'compression' property of each generated node, so it should + not also be given there:: + + images { + @fdt-SEQ { + description = "fdt-NAME"; + type = "flat_dt"; + fit,compress = "lzma"; + }; + }; + + Any algorithm supported by binman can be used (see the 'compress' property + of entries) except "xz" which FIT does not define or "none". The matching + compression tool must be installed. + Dealing with phases ~~~~~~~~~~~~~~~~~~~
@@ -746,6 +769,26 @@ class Entry_fit(Entry_section): return tools.read_file(output_fname) + def _compress_fdt(self, algo, data): + """Compress the data of a generated fdt node + + Args: + algo (str): Compression algorithm + data (bytes): Data to compress + + Returns: + bytes: Compressed data + + Raises: + ValueError: if the compression tool is not available + """ + btool = self.fdt_comp_bintools[algo] + if not btool.is_present(): + raise ValueError( + f"Cannot compress fdt with '{algo}': tool '{btool.name}' is " + f"missing") + return btool.compress(data) + def _raise_subnode(self, node, msg): """Raise an error with a paticular FIT subnode
@@ -883,6 +926,7 @@ class Entry_fit(Entry_section): else: fname = tools.get_input_filename(fdt_fname + '.dtb') fdt_phase = None + compress = 'none' with fsw.add_node(node_name): for pname, prop in node.props.items(): if pname == 'fit,firmware':
@@ -902,6 +946,9 @@ class Entry_fit(Entry_section): fsw.property('compatible', prop.bytes) elif pname == 'fit,fdt-phase': fdt_phase = fdt_util.GetString(node, pname) + elif pname == 'fit,compress': + compress = fdt_util.GetString(node, pname) + fsw.property_string('compression', compress) elif pname.startswith('fit,'): self._raise_subnode( node, f"Unknown directive '{pname}'")
@@ -922,6 +969,8 @@ class Entry_fit(Entry_section): data = tools.read_file(phase_fname) else: data = tools.read_file(fname) + if compress != 'none': + data = self._compress_fdt(compress, data) fsw.property('data', data) for subnode in node.subnodes:
@@ -1148,10 +1197,28 @@ class Entry_fit(Entry_section): entry.SetImagePos(image_pos + self.offset) def AddBintools(self, btools): + # Add the tool for each algorithm requested by a generator node super().AddBintools(btools) self.mkimage = self.AddBintool(btools, 'mkimage') self.fdtgrep = self.AddBintool(btools, 'fdtgrep') + self.fdt_comp_bintools = {} + def _add_comp_bintools(node): + for prop in node.props.values(): + if prop.name == 'fit,compress' and prop.value != 'none': + if prop.value == 'xz': + self._raise_subnode( + node, "fit,compress 'xz' is not a FIT compression") + try: + name = self.get_comp_bintool_name(prop.value) + except ValueError as exc: + self._raise_subnode(node, str(exc)) + self.fdt_comp_bintools[prop.value] = self.AddBintool( + btools, name) + for subnode in node.subnodes: + _add_comp_bintools(subnode) + _add_comp_bintools(self._node) + def CheckMissing(self, missing_list): # We must use our private entry list for this since generator nodes # which are removed from self._entries will otherwise not show up as
Signature · 1 line
2.55.0
Re: [PATCH v2 2/6] binman: fit: Add fit, compress for generated fdt images
Hi Petr,
Quoted 4 lines · On 2026-10-17T07:38:59, Petr Hodina via B4 Relay…
binman: fit: Add fit,compress for generated fdt images
The 'compression' property of a FIT image is only metadata.
Quoted 8 lines
Add a 'fit,compress' property for generator nodes. It names the algorithm so binman compresses each .dtb with it and writes the algorithm to 'compression' in the generated node.
Any algorithm known to
Entry.AddBintools()is accepted.Register the needed bintools in
Entry_fit.AddBintools()and report a missing one in the usual way instead of failing.
The code does not match this. _compress_fdt() raises ValueError when the tool is missing, and testFitFdtCompressMissing asserts that behaviour even with allow_missing=True. The usual pattern in binman (see Entry.CompressData() and the mkimage path above in this same file) is to call record_missing_bintool() and emit placeholder data so the build completes and the user gets a single consolidated missing-tools report. Please either make _compress_fdt() follow that pattern, or reword the commit message to say that a missing compressor is a hard error.
tools/binman/etype/fit.py class Entry_fit(Entry_section): · line 275
Quoted 12 lines
Document the property.
Signed-off-by Petr Hodina <[email protected]>
tools/binman/etype/fit.py| 67 +++++++++++++++++++++++++++++++++++++++++++++++1 file changed, 67 insertions(+)tools/binman/etype/fit.py +2
-0@@ -274,6 +274,29 @@ class Entry_fit(Entry_section): + Any algorithm supported by binman can be used (see the 'compress' property + of entries) except "xz" which FIT does not define or "none".
The "or 'none'" tail reads as if 'none' were also excluded, which it isn't — it's the default. Please reword, e.g. "any algorithm supported by binman (see the 'compress' property of entries) except 'xz', which FIT does not define".
tools/binman/etype/fit.py class Entry_fit(Entry_section): · line 1201
Quoted 7 lines
tools/binman/etype/fit.py +1
-0@@ -1148,10 +1197,28 @@ class Entry_fit(Entry_section): def AddBintools(self, btools): + # Add the tool for each algorithm requested by a generator node super().AddBintools(btools) self.mkimage = self.AddBintool(btools, 'mkimage') self.fdtgrep = self.AddBintool(btools, 'fdtgrep')
The comment belongs on the fdt_comp_bintools block below, not up here — as it stands it reads as if it applies to mkimage/fdtgrep.
Quoted 8 lines
tools/binman/etype/fit.py +6
-0@@ -1148,10 +1197,28 @@ class Entry_fit(Entry_section): + self.fdt_comp_bintools = {} + def _add_comp_bintools(node): + for prop in node.props.values(): + if prop.name == 'fit,compress' and prop.value != 'none': + if prop.value == 'xz': + self._raise_subnode(
tools/binman/etype/fit.py class Entry_fit(Entry_section): · line 1212
Quoted 10 lines
tools/binman/etype/fit.py +10
-0+ node, "fit,compress 'xz' is not a FIT compression") + try: + name = self.get_comp_bintool_name(prop.value) + except ValueError as exc: + self._raise_subnode(node, str(exc)) + self.fdt_comp_bintools[prop.value] = self.AddBintool( + btools, name) + for subnode in node.subnodes: + _add_comp_bintools(subnode) + _add_comp_bintools(self._node)
Just to check — this walks every subnode and acts on any 'fit,compress' prop, including on a plain (non-generator) image node, which the _build_input() path never honours. Worth restricting to generator nodes (name starting with '@') so the two sides stay in sync? Otherwise someone will set fit,compress on an ordinary image and silently get no compression.
Regards,
Simon
Re: [PATCH v2 2/6] binman: fit: Add fit,compress for generated fdt images
In reply to Petr HodinaHi Petr,
Quoted 28 lines · On 10/17/26 9:39 AM, Petr Hodina via B4 Relay wrote:
From: Petr Hodina <[email protected]>
The 'compression' property of a FIT image is only metadata.
Add a 'fit,compress' property for generator nodes. It names the algorithm so binman compresses each .dtb with it and writes the algorithm to 'compression' in the generated node.
Any algorithm known to
Entry.AddBintools()is accepted.Register the needed bintools in
Entry_fit.AddBintools()and report a missing one in the usual way instead of failing.Document the property.
Signed-off-by Petr Hodina <[email protected]>--- tools/binman/etype/fit.py | 67 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+)tools/binman/etype/fit.py +0
-0@@ -274,6 +274,29 @@ class Entry_fit(Entry_section): string from the root node of the devicetree, so that things work correctly with FIT's configuration-matching algortihm.
tools/binman/etype/fit.py class Entry_fit(Entry_section): · line 286
Quoted 10 lines
tools/binman/etype/fit.py +10
-0+ Compressing the FDT images + ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + The 'compression' property of an image node is copied into the FIT as + metadata only. It tells the loader how the data is stored, but binman does + not touch the data. + For generated FDT nodes, the 'fit,compress' property can be used to ask + binman to compress the .dtb as well. The algorithm is written to + the 'compression' property of each generated node, so it should + not also be given there::
I'm wondering if we shouldn't have a different logic. Keep compression as the property, and the user must set it when they want to use compression. Then, set fit,compress in the node if you want U-Boot to actually act on it, otherwise it's left in the default format. This allows us to simply trust what the user puts in the compression property, which is ruled by the FIT spec, so if they put something wrong there, their fault.
In either case, I'm wondering if there could be a need for having a compression = "none" but still have U-Boot compress it. According to the spec:
"""
If the data is compressed but it should not be uncompressed by the loader (e.g. compressed ramdisk <pair: ramdisk; compressed), this should also be set to “none”. """
Then we need to decorrelate both and they mean different things.
Cheers,
Quentin
PATCH v2 3/6 binman: test: Add fit,compress device trees
In reply to Petr HodinaAdd two minimal device trees with a FIT containing an @fdt-SEQ template which uses 'fit,compress': one with "lzma", another on with "xz" which is currently not supported in SPL and one with an unknown algorithm.
They are used by the tests in the next patch.
--- tools/binman/test/fit/fdt_compress.dts | 24 ++++++++++++++++++++++++ tools/binman/test/fit/fdt_compress_bad.dts | 24 ++++++++++++++++++++++++ tools/binman/test/fit/fdt_compress_xz.dts | 24 ++++++++++++++++++++++++ 3 files changed, 72 insertions(+)
tools/binman/test/fit/fdt_compress.dts new file +24 -0
@@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + fit { + description = "test-desc"; + #address-cells = <1>; + fit,fdt-list = "of-list"; + + images { + @fdt-SEQ { + description = "fdt-NAME.dtb"; + type = "flat_dt"; + fit,compress = "lzma"; + }; + }; + }; + }; +};
tools/binman/test/fit/fdt_compress_bad.dts new file +24 -0
@@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + fit { + description = "test-desc"; + #address-cells = <1>; + fit,fdt-list = "of-list"; + + images { + @fdt-SEQ { + description = "fdt-NAME.dtb"; + type = "flat_dt"; + fit,compress = "bad"; + }; + }; + }; + }; +};
tools/binman/test/fit/fdt_compress_xz.dts new file +24 -0
@@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + fit { + description = "test-desc"; + #address-cells = <1>; + fit,fdt-list = "of-list"; + + images { + @fdt-SEQ { + description = "fdt-NAME.dtb"; + type = "flat_dt"; + fit,compress = "xz"; + }; + }; + }; + }; +};
Signature · 1 line
2.55.0
Re: [PATCH v2 3/6] binman: test: Add fit,compress device trees
Quoted 6 lines · On 2026-10-17T07:38:59, Petr Hodina via B4 Relay…
binman: test: Add fit,compress device trees
Add two minimal device trees with a FIT containing an @fdt-SEQ template which uses 'fit,compress': one with "lzma", another on with "xz" which is currently not supported in SPL and one with an unknown algorithm.
Quoted 8 lines
They are used by the tests in the next patch.
Signed-off-by Petr Hodina <[email protected]>
tools/binman/test/fit/fdt_compress.dts| 24 ++++++++++++++++++++++++tools/binman/test/fit/fdt_compress_bad.dts | 24 ++++++++++++++++++++++++ tools/binman/test/fit/fdt_compress_xz.dts | 24 ++++++++++++++++++++++++ 3 files changed, 72 insertions(+)
PATCH v2 4/6 binman: test: Add tests for fit,compress
In reply to Petr HodinaCheck that generated fdt images are compressed and that 'compression' is set from 'fit,compress', that an unknown algorithm is rejected and that a missing compression tool is reported.
--- tools/binman/ftest.py | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+)
tools/binman/ftest.py +44 -0
@@ -4357,6 +4357,50 @@ class TestFunctional(unittest.TestCase): """Test an image with an FIT with multiple FDT images""" self.CheckFitFdt() + def _FitFdtCompress(self, fname): + entry_args = {'of-list': 'test-fdt1 test-fdt2'} + extra_indirs = [os.path.join(self._indir, TEST_FDT_SUBDIR)] + return self._DoReadFileDtb(fname, entry_args=entry_args, + extra_indirs=extra_indirs)[0] + + def testFitFdtCompress(self): + """Test that fit,compress compresses generated fdt images""" + bintool = self.comp_bintools['lzma_alone'] + self._CheckBintool(bintool) + data = self._FitFdtCompress('fit/fdt_compress.dts') + dtb = fdt.Fdt.FromData(data) + dtb.Scan() + for seq, expected in ((1, TEST_FDT1_DATA), (2, TEST_FDT2_DATA)): + fnode = dtb.GetNode('/images/fdt-%d' % seq) + self.assertEqual('lzma', fnode.props['compression'].value) + self.assertNotIn('fit,compress', fnode.props) + comp = fnode.props['data'].bytes + self.assertNotEqual(expected, comp) + self.assertEqual(expected, bintool.decompress(comp)) + + def testFitFdtCompressBad(self): + """Test an unsupported fdt compression algorithm""" + with self.assertRaises(ValueError) as e: + self._FitFdtCompress('fit/fdt_compress_bad.dts') + self.assertIn("Unknown algorithm 'bad'", str(e.exception)) + + def testFitFdtCompressXz(self): + """Test that xz is rejected as it is not a FIT compression""" + with self.assertRaises(ValueError) as e: + self._FitFdtCompress('fit/fdt_compress_xz.dts') + self.assertIn("fit,compress 'xz' is not a FIT compression", + str(e.exception)) + + def testFitFdtCompressMissing(self): + """Test that a missing compression tool is an error""" + with self.assertRaises(ValueError) as e: + self._DoTestFile('fit/fdt_compress.dts', allow_missing=True, + force_missing_bintools='lzma_alone', + entry_args={'of-list': 'test-fdt1 test-fdt2'}, + extra_indirs=[os.path.join(self._indir, + TEST_FDT_SUBDIR)]) + self.assertIn("tool 'lzma_alone' is missing", str(e.exception)) + def testFitFdtMissingList(self): """Test handling of a missing 'of-list' entry arg""" with self.assertRaises(ValueError) as e:
Signature · 1 line
2.55.0
Re: [PATCH v2 4/6] binman: test: Add tests for fit,compress
Hi Petr,
Quoted 15 lines · On 2026-10-17T07:38:59, Petr Hodina via B4 Relay…
binman: test: Add tests for fit,compress
Check that generated fdt images are compressed and that 'compression' is set from 'fit,compress', that an unknown algorithm is rejected and that a missing compression tool is reported.
Signed-off-by Petr Hodina <[email protected]>
tools/binman/ftest.py| 44 ++++++++++++++++++++++++++++++++++++++++++++1 file changed, 44 insertions(+)tools/binman/ftest.py +4
-0+ def testFitFdtCompress(self): + """Test that fit,compress compresses generated fdt images""" + bintool = self.comp_bintools['lzma_alone'] + self._CheckBintool(bintool)
tools/binman/ftest.py class TestFunctional(unittest.TestCase): · line 4379
Quoted 10 lines
tools/binman/ftest.py +10
-0+ data = self._FitFdtCompress('fit/fdt_compress.dts') + dtb = fdt.Fdt.FromData(data) + dtb.Scan() + for seq, expected in ((1, TEST_FDT1_DATA), (2, TEST_FDT2_DATA)): + fnode = dtb.GetNode('/images/fdt-%d' % seq) + self.assertEqual('lzma', fnode.props['compression'].value) + self.assertNotIn('fit,compress', fnode.props) + comp = fnode.props['data'].bytes + self.assertNotEqual(expected, comp) + self.assertEqual(expected, bintool.decompress(comp))
Only lzma is exercised on the happy path. It would be worth adding a second dts (say gzip) and a parallel test, so the shared bintool lookup from patch 1 is covered against regressions where a specific algorithm name is not handled. What do you think?
Regards,
Simon
Re: [PATCH v2 4/6] binman: test: Add tests for fit,compress
In reply to Petr HodinaHi Petr,
Squash with patch 3 please.
Quoted 67 lines · On 10/17/26 9:39 AM, Petr Hodina via B4 Relay wrote:
From: Petr Hodina <[email protected]>
Check that generated fdt images are compressed and that 'compression' is set from 'fit,compress', that an unknown algorithm is rejected and that a missing compression tool is reported.
Signed-off-by Petr Hodina <[email protected]>--- tools/binman/ftest.py | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+)tools/binman/ftest.py +44
-0@@ -4357,6 +4357,50 @@ class TestFunctional(unittest.TestCase): """Test an image with an FIT with multiple FDT images""" self.CheckFitFdt() + def _FitFdtCompress(self, fname): + entry_args = {'of-list': 'test-fdt1 test-fdt2'} + extra_indirs = [os.path.join(self._indir, TEST_FDT_SUBDIR)] + return self._DoReadFileDtb(fname, entry_args=entry_args, + extra_indirs=extra_indirs)[0] + + def testFitFdtCompress(self): + """Test that fit,compress compresses generated fdt images""" + bintool = self.comp_bintools['lzma_alone'] + self._CheckBintool(bintool) + data = self._FitFdtCompress('fit/fdt_compress.dts') + dtb = fdt.Fdt.FromData(data) + dtb.Scan() + for seq, expected in ((1, TEST_FDT1_DATA), (2, TEST_FDT2_DATA)): + fnode = dtb.GetNode('/images/fdt-%d' % seq) + self.assertEqual('lzma', fnode.props['compression'].value) + self.assertNotIn('fit,compress', fnode.props) + comp = fnode.props['data'].bytes + self.assertNotEqual(expected, comp) + self.assertEqual(expected, bintool.decompress(comp)) + + def testFitFdtCompressBad(self): + """Test an unsupported fdt compression algorithm""" + with self.assertRaises(ValueError) as e: + self._FitFdtCompress('fit/fdt_compress_bad.dts') + self.assertIn("Unknown algorithm 'bad'", str(e.exception)) + + def testFitFdtCompressXz(self): + """Test that xz is rejected as it is not a FIT compression""" + with self.assertRaises(ValueError) as e: + self._FitFdtCompress('fit/fdt_compress_xz.dts') + self.assertIn("fit,compress 'xz' is not a FIT compression", + str(e.exception)) + + def testFitFdtCompressMissing(self): + """Test that a missing compression tool is an error""" + with self.assertRaises(ValueError) as e: + self._DoTestFile('fit/fdt_compress.dts', allow_missing=True, + force_missing_bintools='lzma_alone', + entry_args={'of-list': 'test-fdt1 test-fdt2'}, + extra_indirs=[os.path.join(self._indir, + TEST_FDT_SUBDIR)]) + self.assertIn("tool 'lzma_alone' is missing", str(e.exception)) + def testFitFdtMissingList(self): """Test handling of a missing 'of-list' entry arg""" with self.assertRaises(ValueError) as e:
PATCH v2 5/6 boot: Add a choice for the compression of the FDT in the FIT
In reply to Petr HodinaAdd SPL_FIT_FDT_COMP so a board can select how binman compresses the devicetrees in its FIT (none, LZMA or gzip). LZMA and gzip are the only algorithms the SPL FIT loader can decompress. The default is none.
--- boot/Kconfig | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+)
boot/Kconfig +32 -0
@@ -236,6 +236,38 @@ config SPL_FIT_FULL_CHECK advantage of bugs or omissions in the code. This includes a bad structure, multiple root nodes and the like. +choice + prompt "Compression of the FDT in the FIT" + depends on SPL_FIT + default SPL_FIT_FDT_COMP_NONE + help + Select how binman compresses the devicetrees in the FIT. This is + independent of the compression of U-Boot itself. SPL must be able to + decompress the chosen algorithm. Only boards whose binman description + uses the fit,compress property are affected. + +config SPL_FIT_FDT_COMP_NONE + bool "None" + help + Do not compress the devicetrees. This needs no decompression support + in SPL but makes the FIT larger. + +config SPL_FIT_FDT_COMP_LZMA + bool "LZMA" + depends on SPL_LZMA + help + Compress the devicetrees with LZMA. This gives the smallest FIT but + needs the most time and memory to decompress in SPL. + +config SPL_FIT_FDT_COMP_GZIP + bool "gzip" + depends on SPL_GZIP + help + Compress the devicetrees with gzip. This decompresses faster than + LZMA in SPL but the FIT is larger. + +endchoice + config SPL_FIT_SIGNATURE bool "Enable signature verification of FIT firmware within SPL" depends on SPL_DM
Signature · 1 line
2.55.0
Re: [PATCH v2 5/6] boot: Add a choice for the compression of the FDT in the FIT
Hi Petr,
Quoted 5 lines · On 2026-10-17T07:38:59, Petr Hodina via B4 Relay…
boot: Add a choice for the compression of the FDT in the FIT
Add
SPL_FIT_FDT_COMPso a board can select how binman compresses the devicetrees in its FIT (none, LZMA or gzip). LZMA and gzip are the only algorithms the SPL FIT loader can decompress. The default is none.
Just to check — do we need a user-facing choice for this? The existing FIT_UBOOT_COMP in rockchip-u-boot.dtsi picks the algorithm from whichever of SPL_GZIP / SPL_LZMA is enabled, with no extra Kconfig. The same pattern would work here and would avoid adding a choice that every SPL_FIT board sees in menuconfig, when only Rockchip uses fit,compress today. What do you think?
Quoted 8 lines
Signed-off-by Petr Hodina <[email protected]>boot/Kconfig | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
boot/Kconfig config SPL_FIT_FULL_CHECK · line 244
Quoted 9 lines
boot/Kconfig +9
-0@@ -236,6 +236,38 @@ config SPL_FIT_FULL_CHECK +choice + prompt "Compression of the FDT in the FIT" + depends on SPL_FIT + default SPL_FIT_FDT_COMP_NONE + help + Select how binman compresses the devicetrees in the FIT. This is + independent of the compression of U-Boot itself. SPL must be able to + decompress the chosen algorithm. Only boards whose binman description + uses the fit,compress property are affected.
If the choice is kept, please tighten the dependency to 'depends on SPL_FIT && (SPL_LZMA || SPL_GZIP)'. Otherwise every SPL_FIT board gets a one-option choice offering only None, which is just menuconfig noise.
boot/Kconfig config SPL_FIT_FULL_CHECK · line 236
Quoted 3 lines
boot/Kconfig +1
-0@@ -236,6 +236,38 @@ config SPL_FIT_FULL_CHECK + prompt "Compression of the FDT in the FIT"
The symbols are SPL_FIT_FDT_COMP_* but the prompt doesn't mention SPL. Something like "SPL FIT: FDT compression" would make it clearer in menuconfig that this is SPL-only.
Regards,
Simon
PATCH v2 6/6 rockchip: Allow compression of the FDT in the FIT
In reply to Petr HodinaCompressing the FDT shrinks the FIT at the cost of decompression time in SPL.
Define FIT_FDT_COMP from the SPL_FIT_FDT_COMP choice and use it in the @fdt-SEQ template via 'fit,compress'.
This has no effect on any current board as no in-tree Rockchip defconfig selects a compression.
--- arch/arm/dts/rockchip-u-boot.dtsi | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-)
arch/arm/dts/rockchip-u-boot.dtsi +14 -1
@@ -19,6 +19,19 @@ #define FIT_UBOOT_COMP "none" #endif +/* + * The compression of the FDT is chosen by the SPL_FIT_FDT_COMP choice. It + * is independent of FIT_UBOOT_COMP so U-Boot may be gzip-compressed while the + * FDT is LZMA-compressed. + */ +#if defined(CONFIG_SPL_FIT_FDT_COMP_LZMA) +#define FIT_FDT_COMP "lzma" +#elif defined(CONFIG_SPL_FIT_FDT_COMP_GZIP) +#define FIT_FDT_COMP "gzip" +#else +#define FIT_FDT_COMP "none" +#endif + /* * SHA256 should be enabled in SPL when signature validation is involved, * CRC32 should only be used for basic checksum validation of FIT images.
@@ -136,7 +149,7 @@ @fdt-SEQ { description = "fdt-NAME"; - compression = "none"; + fit,compress = FIT_FDT_COMP; type = "flat_dt"; #ifdef FIT_HASH_ALGO hash {
Signature · 1 line
2.55.0
Re: [PATCH v2 6/6] rockchip: Allow compression of the FDT in the FIT
Quoted 8 lines · On 2026-10-17T07:38:59, Petr Hodina via B4 Relay…
rockchip: Allow compression of the FDT in the FIT
Compressing the FDT shrinks the FIT at the cost of decompression time in SPL.
Define
FIT_FDT_COMPfrom theSPL_FIT_FDT_COMPchoice and use it in the @fdt-SEQ template via 'fit,compress'.
Quoted 7 lines
This has no effect on any current board as no in-tree Rockchip defconfig selects a compression.
Signed-off-by Petr Hodina <[email protected]>
arch/arm/dts/rockchip-u-boot.dtsi| 15 ++++++++++++++-1 file changed, 14 insertions(+), 1 deletion(-)
Re: [PATCH v2 6/6] rockchip: Allow compression of the FDT in the FIT
In reply to Petr HodinaHi Petr,
Quoted 26 lines · On 10/17/26 9:39 AM, Petr Hodina via B4 Relay wrote:
From: Petr Hodina <[email protected]>
Compressing the FDT shrinks the FIT at the cost of decompression time in SPL.
Define
FIT_FDT_COMPfrom theSPL_FIT_FDT_COMPchoice and use it in the @fdt-SEQ template via 'fit,compress'.This has no effect on any current board as no in-tree Rockchip defconfig selects a compression.
Signed-off-by Petr Hodina <[email protected]>--- arch/arm/dts/rockchip-u-boot.dtsi | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-)arch/arm/dts/rockchip-u-boot.dtsi +2
-0@@ -19,6 +19,19 @@ #define FIT_UBOOT_COMP "none" #endif +/* + * The compression of the FDT is chosen by the SPL_FIT_FDT_COMP choice. It
arch/arm/dts/rockchip-u-boot.dtsi line 33
Quoted 10 lines
arch/arm/dts/rockchip-u-boot.dtsi +10
-0+ * is independent of FIT_UBOOT_COMP so U-Boot may be gzip-compressed while the + * FDT is LZMA-compressed. + */ +#if defined(CONFIG_SPL_FIT_FDT_COMP_LZMA) +#define FIT_FDT_COMP "lzma" +#elif defined(CONFIG_SPL_FIT_FDT_COMP_GZIP) +#define FIT_FDT_COMP "gzip" +#else +#define FIT_FDT_COMP "none" +#endif
issue: wrong place for this
We would then need everybody to reimplement that if they want to use it.
Instead, create an invisible string Kconfig symbol which defaults to the string value related to the selected CONFIG_SPL_FIT_FDT_COMP_* in the Kconfig choice menu.
Otherwise, I generally have the same question as Alexey, is there actual size and/or speed improvements you saw on Rockchip for this series?
Cheers,
Quentin
Hi Petr,
Quoted 4 lines · On Sat, Oct 17, 2026 at 11:39 AM Petr Hodina via B4 Relay…
Entry_fit's @fdt-SEQ generator always embeds the raw .dtb. Add a 'fit,compress' property so binman can compress it with any algorithm FIT defines (xz is rejected) and set 'compression' to match.
We currently use 'compress' (without the "fit," prefix) for the U-Boot binary. Having multiple spellings for a semantically similar property sounds confusing.
Quoted 2 lines
Add a generic
SPL_FIT_FDT_COMPchoice (none, LZMA, gzip: what the SPL FIT loader can currently decompress) and use it on Rockchip.
Do you happen to have any numbers regarding the size savings and the real-world cost in loading time? DTBs are not that large, so I'm wondering if it's really worth the added complexity.
Best regards,
Alexey
Hi Alexey,
Quoted 3 lines · Alexey Charkov
We currently use 'compress' (without the "fit," prefix) for the U-Boot binary. Having multiple spellings for a semantically similar property sounds confusing.
The 'fit,' prefix is the established convention in Entry_fit for properties that control FIT generation (fit,fdt-list, fit,operation, fit,align, fit,sign, fit,encrypt, fit,engine, ...). The plain 'compress' property acts on an entry's own data at the binman level and pairs with uncomp-size tracking, whereas here we are telling the FIT generator to compress the embedded fdt subimage and emit a matching 'compression' property in the FIT itself. So the two really are different operations and keeping the 'fit,' prefix fits the surrounding code. I think that is the right call.
Regards,
Simon