Files
proxmark3/common_fpga/fpga.h
T
iceman1001andClaude Opus 5 (1M context) 43fe6c3eb8 fpga_compress: pick the LZ4 block size by consumer, not by file count
The 1 MB block branch exists for the ARM .data section: start.c's
uncompress_data_section() reads one 4-byte length and does one
LZ4_decompress_safe(), so .data has to arrive as a single block. It was
selected by 'num_infiles == 1', which is not what tells the two callers apart.

A build that skips LF, FeliCa and ISO15693 leaves FPGA_BITSTREAMS holding just
fpga_pm3_hf.bit, so the bitstream took that same branch and was packed as one
42 kB block. get_from_fpga_combined_stream() decompresses into a
FPGA_RING_BUFFER_BYTES buffer, 16 kB since 83c3f81b1:

  [#] inflate returned: -13247
  [#] reset_fpga_stream failed

Before 83c3f81b1 the copy was clamped with MIN(FPGA_RING_BUFFER_BYTES, ...)
whatever buffer_size said, so the blocks came out at 30 kB and the 30 kB ring
buffer still took them. That is why the commit looks like the cause - it only
removed the clamp that was covering for the wrong branch.

Add -s for the single block case and let the FPGA path always chop at
FPGA_RING_BUFFER_BYTES, however many bitstreams went in:

  4 bitstreams   169344 in -> 106933 out, byte identical to before
  1 bitstream     42172 in ->  28718 out, 3 blocks 13265/13206/2247,
                                          was 1 block of 27627
  .data  (-s)     14944 in ->   8786 out, byte identical to the
                                          obj/fullimage.data.bin.z in tree

Also hand the ring buffer back when reset_fpga_stream() fails. The early
return left it allocated for the rest of the session, which is the reporter's

  [#]   BigBuf_size............. 48116
  [#]   Available memory........ 31732

48116 - 31732 is 16384, exactly FPGA_RING_BUFFER_BYTES.

No CAPABILITIES_VERSION bump: fpga_all.bit.z is objcopy'd into the same
fullimage as the decompressor that reads it, so nothing here is client facing.

Reported and correctly diagnosed by @ewangsoft.

Fixes #3599

Co-Authored-By: Claude Opus 5 (1M context)
2026-09-13 08:14:43 +02:00

72 lines
3.0 KiB
C

//-----------------------------------------------------------------------------
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// See LICENSE.txt for the text of the license.
//-----------------------------------------------------------------------------
#ifndef __FPGA_H
#define __FPGA_H
#include <stdbool.h>
#include <inttypes.h>
#define FPGA_BITSTREAM_FIXED_HEADER_SIZE sizeof(bitparse_fixed_header)
#define FPGA_INTERLEAVE_SIZE 288
#if defined XC3
#define FPGA_TYPE "3s100evq100"
#define FPGA_CONFIG_SIZE 72864L // FPGA .bit file rounded up to next multiple of FPGA_INTERLEAVE_SIZE
#elif defined XC2S50
#define FPGA_TYPE "2s50vq144"
#define FPGA_CONFIG_SIZE 69984L // FPGA .bit file rounded up to next multiple of FPGA_INTERLEAVE_SIZE
#else
#define FPGA_TYPE "2s30vq100"
#define FPGA_CONFIG_SIZE 42336L // FPGA .bit file rounded up to next multiple of FPGA_INTERLEAVE_SIZE
#endif
// LZ4 sliding-window / staging size for ONE compressed block, not the image:
// fpga_compress chops the interleaved bitstreams into blocks of at most this
// size, and the ARM decompresses them one at a time while DownloadFPGA() shifts
// the bytes out to the FPGA. It is allocated out of BigBuf, which on AT91 is
// only ~31-33 kB, so 30 kB left nothing for the caller.
// Smaller window = slightly worse compression
// Measured on flash:
// 30 kB -> 102555 bytes
// 16 kB -> 107121 bytes
// This does NOT bound the firmware's .data section
// fpga_compress -s gives the .data section its own 1 MB block, because start.c only decompresses one.
// Every FPGA bitstream, even a lone one in a HF only build, is chopped at this size.
#define FPGA_RING_BUFFER_BYTES (1024 * 16)
#define FPGA_TRACE_SIZE 3072
// definitions for multiple FPGA config files support
typedef enum {
FPGA_BITSTREAM_UNKNOWN = 0,
FPGA_BITSTREAM_LF = 1,
FPGA_BITSTREAM_MIN = FPGA_BITSTREAM_LF,
FPGA_BITSTREAM_HF,
FPGA_BITSTREAM_HF_FELICA,
FPGA_BITSTREAM_HF_15,
FPGA_BITSTREAM_MAX = FPGA_BITSTREAM_HF_15,
FPGA_CONFIG_COUNT
} FPGA_config;
typedef struct {
const char *const versionString;
const FPGA_config target_config;
} FPGA_VERSION_INFORMATION;
static const uint8_t bitparse_fixed_header[] = {0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x01};
extern const int g_fpga_bitstream_num;
extern const FPGA_VERSION_INFORMATION g_fpga_version_information[];
#endif