[PATCH v2 8/8] test: fit: cover the kernel_noload lzma header-size and unknown-size paths
Aristo Chen <[email protected]>
| Newsgroups | org.u-boot-project.lists.u-boot |
|---|---|
| Message-ID | <[email protected]> |
Exercise bootm_lzma_uncompressed_size() end-to-end on sandbox: - test_fit_kernel_noload_decomp_lzma_hdr_sized boots a 6 MiB kernel_noload payload that lzma compresses far past the 8x fallback heuristic, so the boot only succeeds when bootm sizes the buffer from the header's uncompressed-size field. Streaming encoders write the "unknown" marker into that field, so the test compresses with Python's lzma module and patches the real size into the fixed 8-byte field, matching what LZMA SDK style encoders record. - test_fit_kernel_noload_decomp_lzma_unknown_size leaves the marker in place and checks that bootm falls back to the 8x heuristic buffer and still boots the image. No external tool is required: Python's lzma module is part of the standard library. Signed-off-by: Aristo Chen <[email protected]> --- test/py/tests/test_fit.py | 98 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/test/py/tests/test_fit.py b/test/py/tests/test_fit.py index 42edddb0600..0edf875a9e1 100755 --- a/test/py/tests/test_fit.py +++ b/test/py/tests/test_fit.py @@ -704,6 +704,104 @@ class TestFitImage: 'bootm rejected a well-compressed zstd kernel_noload image whose ' 'frame header records the real content size: %s' % text) + @pytest.mark.buildconfigspec('lzma') + def test_fit_kernel_noload_decomp_lzma_hdr_sized(self, ubman, fsetup): + """A well-compressed lzma kernel_noload image fits when the header + records the real uncompressed size. + + Same as test_fit_kernel_noload_decomp_gzip_hdr_sized but for lzma. + Streaming encoders write the "unknown" marker into the .lzma-alone + size field, so compress with Python's lzma module and patch the + real size into the fixed 8-byte header field, the way LZMA SDK + style encoders record it. + """ + lzma = pytest.importorskip('lzma') + sz_1m = 1 << 20 + bootm_len = int(ubman.config.buildconfig['config_sys_bootm_len'], 0) + + decomp_size = 6 * sz_1m + assert decomp_size <= bootm_len, ( + 'Test setup error: decomp_size (%#x) must be <= ' + 'CONFIG_SYS_BOOTM_LEN (%#x)' % (decomp_size, bootm_len)) + kernel = fit_util.make_fname(ubman, 'test-noload-kernel-lzma.bin') + with open(kernel, 'wb') as fd: + fd.write(b'\0' * decomp_size) + filters = [{'id': lzma.FILTER_LZMA1, 'preset': 6, + 'dict_size': 1 << 20}] + blob = lzma.compress(self.read_file(kernel), + format=lzma.FORMAT_ALONE, filters=filters) + assert blob[5:13] == b'\xff' * 8, ( + 'Test setup error: expected the streaming encoder to write the ' + '"unknown" size marker') + blob = blob[:5] + decomp_size.to_bytes(8, 'little') + blob[13:] + kernel_lzma = kernel + '.lzma' + with open(kernel_lzma, 'wb') as fd: + fd.write(blob) + + image_len = self.filesize(kernel_lzma) + heuristic_bound = (image_len * 8 + sz_1m - 1) // sz_1m * sz_1m + assert heuristic_bound < decomp_size, ( + 'Test setup error: 8x heuristic bound (%#x) must be < uncompressed ' + 'size (%#x); if this fires, lzma got less effective and the test ' + 'needs a bigger payload' % (heuristic_bound, decomp_size)) + + fit = fit_util.make_fit(ubman, fsetup['mkimage'], NOLOAD_ITS, + {'kernel': kernel_lzma, 'compression': 'lzma'}, + basename='test-noload-lzma-hdrsized.fit') + fit_addr = fsetup['fit_addr'] + + output = ubman.run_command_list([ + 'host load hostfs 0 %x %s' % (fit_addr, fit), + 'bootm start %x' % fit_addr, + 'bootm loados', + ]) + text = '\n'.join(output) + assert 'Image too large' not in text, ( + 'bootm rejected a well-compressed lzma kernel_noload image whose ' + 'header records the real uncompressed size: %s' % text) + + @pytest.mark.buildconfigspec('lzma') + def test_fit_kernel_noload_decomp_lzma_unknown_size(self, ubman, fsetup): + """An lzma stream with the "unknown" size marker falls back cleanly + + Streaming encoders write 0xff..ff into the .lzma-alone size field. + bootm must fall back to the 8x heuristic buffer and still boot the + image. + """ + lzma = pytest.importorskip('lzma') + sz_1m = 1 << 20 + + # Incompressible data keeps the real size well inside the 8x + # fallback buffer. + payload = os.urandom(sz_1m) + kernel = fit_util.make_fname(ubman, 'test-noload-kernel-lzma-unk.bin') + filters = [{'id': lzma.FILTER_LZMA1, 'preset': 6, + 'dict_size': 1 << 20}] + blob = lzma.compress(payload, format=lzma.FORMAT_ALONE, + filters=filters) + assert blob[5:13] == b'\xff' * 8, ( + 'Test setup error: expected the streaming encoder to write the ' + '"unknown" size marker') + kernel_lzma = kernel + '.lzma' + with open(kernel_lzma, 'wb') as fd: + fd.write(blob) + + fit = fit_util.make_fit(ubman, fsetup['mkimage'], NOLOAD_ITS, + {'kernel': kernel_lzma, 'compression': 'lzma'}, + basename='test-noload-lzma-unk.fit') + fit_addr = fsetup['fit_addr'] + + output = ubman.run_command_list([ + 'host load hostfs 0 %x %s' % (fit_addr, fit), + 'bootm start %x' % fit_addr, + 'bootm loados', + ]) + text = '\n'.join(output) + assert 'Image too large' not in text, ( + 'bootm rejected an lzma kernel_noload image carrying the ' + '"unknown" size marker; the 8x fallback should have covered ' + 'it: %s' % text) + @pytest.mark.buildconfigspec('gzip') def test_fit_kernel_noload_decomp_gzip_boundary(self, ubman, fsetup): """Test that decompression succeeds exactly at the buffer limit -- 2.43.0