mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-10-06 01:17:56 +00:00
zlib_decompress() walks its output in whole FPGA_INTERLEAVE_SIZE chunks:
for (long k = 0; k < *outsize / (FPGA_INTERLEAVE_SIZE * num_outfiles); k++)
so a stream that is not a whole number of chunks loses its trailing partial one.
With two or more inputs the read loop zero-pads each stream past EOF and the
total lands on a boundary, but the padding was guarded by 'num_infiles > 1', so
the single input case was left ragged. 42172 bytes of fpga_pm3_hf.bit is 146.43
chunks, and -d handed back 39788 - a clean looking prefix, short by 2384 bytes,
22 of them real bitstream data.
Gate the padding on single_block instead. It must not be 'always pad': -s is the
.data section, and start.c's uncompress_data_section() sizes the decompression
with __data_end__ - __data_start__. Rounding .data from 14944 up to 14976 makes
LZ4_decompress_safe() return an error, and that path is the LED panic loop, so
the firmware would never reach AppMain().
1 bitstream 42172 in -> 42336 packed, -d round trip byte identical,
archive 28730 -> 28731
4 bitstreams archive byte identical to 43fe6c3eb, round trip exact
-s .data byte identical to 43fe6c3eb on the same input, unpadded
The 164 padding bytes never reach the FPGA: DownloadFPGA() shifts out only
bitstream_length bytes, taken from the .bit 'e' section header.
Also simulated the ARM decoder over the new archive - LZ4_decompress_safe_continue()
block by block into a FPGA_RING_BUFFER_BYTES buffer - 3 blocks of 16384/16384/9568,
none over the ring buffer.
Co-Authored-By: Claude Opus 5 (1M context)