diff --git a/armsrc/Makefile b/armsrc/Makefile index 23ac247c3..14747c7ed 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -75,13 +75,13 @@ include Standalone/Makefile.inc #the FPGA bitstream files. Note: order matters! FPGA_BITSTREAMS = fpga_lf.bit fpga_hf.bit -#the zlib source files required for decompressing the fpga config at run time -SRC_ZLIB = inflate.c inffast.c inftrees.c adler32.c zutil.c -#additional defines required to compile zlib -ZLIB_CFLAGS = -DZ_SOLO -DZ_PREFIX -DNO_GZIP -DZLIB_PM3_TUNED -APP_CFLAGS += $(ZLIB_CFLAGS) -# zlib includes: -APP_CFLAGS += -I../common/zlib +#the lz4 source files required for decompressing the fpga config at run time +SRC_LZ4 = lz4.c +#additional defines required to compile lz4 +LZ4_CFLAGS = -DNEED_MEMMOVE -DLZ4_MEMORY_USAGE=8 +APP_CFLAGS += $(LZ4_CFLAGS) +# lz4 includes: +APP_CFLAGS += -I../common/lz4 # stdint.h provided locally until GCC 4.5 becomes C99 compliant, # stack-protect , no-pie reduces size on Gentoo Hardened 8.2 gcc @@ -93,7 +93,7 @@ THUMBSRC = start.c \ $(SRC_ISO15693) \ $(SRC_NFCBARCODE) \ $(SRC_LF) \ - $(SRC_ZLIB) \ + $(SRC_LZ4) \ $(SRC_LEGIC) \ $(SRC_FLASH) \ $(SRC_SMARTCARD) \ diff --git a/armsrc/fpgaloader.c b/armsrc/fpgaloader.c index 196364d98..0b7b24cbd 100644 --- a/armsrc/fpgaloader.c +++ b/armsrc/fpgaloader.c @@ -17,10 +17,19 @@ #include "ticks.h" #include "dbprint.h" #include "util.h" -#include "zlib.h" #include "fpga.h" #include "string.h" +#include "lz4.h" // uncompress + +typedef struct lz4_stream_s { + LZ4_streamDecode_t* lz4StreamDecode; + char * next_in; + int avail_in; +} lz4_stream; + +typedef lz4_stream* lz4_streamp; + // remember which version of the bitstream we have already downloaded to the FPGA static int downloaded_bitstream = 0; @@ -30,8 +39,6 @@ extern uint8_t _binary_obj_fpga_all_bit_z_start, _binary_obj_fpga_all_bit_z_end; static uint8_t *fpga_image_ptr = NULL; static uint32_t uncompressed_bytes_cnt; -#define OUTPUT_BUFFER_LEN 80 - //----------------------------------------------------------------------------- // Set up the Serial Peripheral Interface as master // Used to write the FPGA config word @@ -180,18 +187,25 @@ bool FpgaSetupSscDma(uint8_t *buf, int len) { // Uncompress (inflate) the FPGA data. Returns one decompressed byte with // each call. //---------------------------------------------------------------------------- -static int get_from_fpga_combined_stream(z_streamp compressed_fpga_stream, uint8_t *output_buffer) { - if (fpga_image_ptr == compressed_fpga_stream->next_out) { // need more data - compressed_fpga_stream->next_out = output_buffer; - compressed_fpga_stream->avail_out = OUTPUT_BUFFER_LEN; +static int get_from_fpga_combined_stream(lz4_streamp compressed_fpga_stream, uint8_t *output_buffer) { + if (fpga_image_ptr == output_buffer + FPGA_RING_BUFFER_BYTES) { // need more data fpga_image_ptr = output_buffer; - int res = inflate(compressed_fpga_stream, Z_SYNC_FLUSH); - - if (res != Z_OK) - Dbprintf("inflate returned: %d, %s", res, compressed_fpga_stream->msg); - - if (res < 0) + int cmp_bytes = *(compressed_fpga_stream->next_in + 3); + cmp_bytes = (cmp_bytes << 8) + *(compressed_fpga_stream->next_in+2); + cmp_bytes = (cmp_bytes << 8) + *(compressed_fpga_stream->next_in+1); + cmp_bytes = (cmp_bytes << 8) + *(compressed_fpga_stream->next_in+0); + compressed_fpga_stream->next_in += 4; + compressed_fpga_stream->avail_in -= cmp_bytes + 4; + int res = LZ4_decompress_safe_continue(compressed_fpga_stream->lz4StreamDecode, + compressed_fpga_stream->next_in, + (char*)output_buffer, + cmp_bytes, + FPGA_RING_BUFFER_BYTES); + if (res <= 0) { + Dbprintf("inflate returned: %d", res); return res; + } + compressed_fpga_stream->next_in += cmp_bytes; } uncompressed_bytes_cnt++; return *fpga_image_ptr++; @@ -202,7 +216,7 @@ static int get_from_fpga_combined_stream(z_streamp compressed_fpga_stream, uint8 // are combined into one big file: // 288 bytes from FPGA file 1, followed by 288 bytes from FGPA file 2, etc. //---------------------------------------------------------------------------- -static int get_from_fpga_stream(int bitstream_version, z_streamp compressed_fpga_stream, uint8_t *output_buffer) { +static int get_from_fpga_stream(int bitstream_version, lz4_streamp compressed_fpga_stream, uint8_t *output_buffer) { while ((uncompressed_bytes_cnt / FPGA_INTERLEAVE_SIZE) % g_fpga_bitstream_num != (bitstream_version - 1)) { // skip undesired data belonging to other bitstream_versions get_from_fpga_combined_stream(compressed_fpga_stream, output_buffer); @@ -211,37 +225,23 @@ static int get_from_fpga_stream(int bitstream_version, z_streamp compressed_fpga return get_from_fpga_combined_stream(compressed_fpga_stream, output_buffer); } -static voidpf fpga_inflate_malloc(voidpf opaque, uInt items, uInt size) { - return BigBuf_malloc(items * size); -} - -// free eventually allocated BigBuf memory -static void fpga_inflate_free(voidpf opaque, voidpf address) { - BigBuf_free(); - BigBuf_Clear_ext(false); -} - //---------------------------------------------------------------------------- // Initialize decompression of the respective (HF or LF) FPGA stream //---------------------------------------------------------------------------- -static bool reset_fpga_stream(int bitstream_version, z_streamp compressed_fpga_stream, uint8_t *output_buffer) { +static bool reset_fpga_stream(int bitstream_version, lz4_streamp compressed_fpga_stream, uint8_t *output_buffer) { uint8_t header[FPGA_BITSTREAM_FIXED_HEADER_SIZE]; uncompressed_bytes_cnt = 0; // initialize z_stream structure for inflate: - compressed_fpga_stream->next_in = &_binary_obj_fpga_all_bit_z_start; + compressed_fpga_stream->next_in = (char*)&_binary_obj_fpga_all_bit_z_start; compressed_fpga_stream->avail_in = &_binary_obj_fpga_all_bit_z_end - &_binary_obj_fpga_all_bit_z_start; - compressed_fpga_stream->next_out = output_buffer; - compressed_fpga_stream->avail_out = OUTPUT_BUFFER_LEN; - compressed_fpga_stream->zalloc = &fpga_inflate_malloc; - compressed_fpga_stream->zfree = &fpga_inflate_free; - - int res = inflateInit2(compressed_fpga_stream, 0); - if (res < 0) + + int res = LZ4_setStreamDecode(compressed_fpga_stream->lz4StreamDecode, NULL, 0); + if (res == 0) return false; - fpga_image_ptr = output_buffer; + fpga_image_ptr = output_buffer + FPGA_RING_BUFFER_BYTES; for (uint16_t i = 0; i < FPGA_BITSTREAM_FIXED_HEADER_SIZE; i++) header[i] = get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer); @@ -266,7 +266,7 @@ static void DownloadFPGA_byte(uint8_t w) { } // Download the fpga image starting at current stream position with length FpgaImageLen bytes -static void DownloadFPGA(int bitstream_version, int FpgaImageLen, z_streamp compressed_fpga_stream, uint8_t *output_buffer) { +static void DownloadFPGA(int bitstream_version, int FpgaImageLen, lz4_streamp compressed_fpga_stream, uint8_t *output_buffer) { int i = 0; AT91C_BASE_PIOA->PIO_OER = GPIO_FPGA_ON; @@ -348,7 +348,7 @@ static void DownloadFPGA(int bitstream_version, int FpgaImageLen, z_streamp comp * (big endian), bytes content. Except for section 'e' which has 4 bytes * length. */ -static int bitparse_find_section(int bitstream_version, char section_name, uint32_t *section_length, z_streamp compressed_fpga_stream, uint8_t *output_buffer) { +static int bitparse_find_section(int bitstream_version, char section_name, uint32_t *section_length, lz4_streamp compressed_fpga_stream, uint8_t *output_buffer) { int result = 0; #define MAX_FPGA_BIT_STREAM_HEADER_SEARCH 100 // maximum number of bytes to search for the requested section uint16_t numbytes = 0; @@ -407,8 +407,6 @@ void FpgaDownloadAndGo(int bitstream_version) { // Send waiting time extension request as this will take a while send_wtx(1500); - z_stream compressed_fpga_stream; - uint8_t output_buffer[OUTPUT_BUFFER_LEN] = {0x00}; bool verbose = (DBGLEVEL > 3); @@ -416,6 +414,11 @@ void FpgaDownloadAndGo(int bitstream_version) { BigBuf_free(); BigBuf_Clear_ext(verbose); + lz4_stream compressed_fpga_stream; + LZ4_streamDecode_t lz4StreamDecode_body = {{ 0 }}; + compressed_fpga_stream.lz4StreamDecode = &lz4StreamDecode_body; + uint8_t * output_buffer = BigBuf_malloc(FPGA_RING_BUFFER_BYTES); + if (!reset_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer)) return; @@ -425,8 +428,6 @@ void FpgaDownloadAndGo(int bitstream_version) { downloaded_bitstream = bitstream_version; } - inflateEnd(&compressed_fpga_stream); - // turn off antenna FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); diff --git a/armsrc/start.c b/armsrc/start.c index f0f4ea56c..8c769f56a 100644 --- a/armsrc/start.c +++ b/armsrc/start.c @@ -14,49 +14,28 @@ #include "proxmark3_arm.h" #include "appmain.h" -#include "zlib.h" +#include "lz4.h" #include "BigBuf.h" static uint8_t *next_free_memory; extern struct common_area common_area; extern char __data_src_start__, __data_start__, __data_end__, __bss_start__, __bss_end__; -static voidpf inflate_malloc(voidpf opaque, uInt items, uInt size) { - uint8_t *allocated_memory; - - allocated_memory = next_free_memory; - next_free_memory += items * size; - return allocated_memory; -} - -static void inflate_free(voidpf opaque, voidpf address) { - // nothing to do -} - static void uncompress_data_section(void) { - z_stream data_section; - next_free_memory = BigBuf_get_addr(); - // initialize zstream structure - data_section.next_in = (uint8_t *) &__data_src_start__; - data_section.avail_in = &__data_end__ - &__data_start__; // uncompressed size. Wrong but doesn't matter. - data_section.next_out = (uint8_t *) &__data_start__; - data_section.avail_out = &__data_end__ - &__data_start__; // uncompressed size. Correct. - data_section.zalloc = &inflate_malloc; - data_section.zfree = &inflate_free; - data_section.opaque = NULL; + int avail_in = *(&__data_start__ + 3); + avail_in = (avail_in << 8) + *(&__data_start__+2); + avail_in = (avail_in << 8) + *(&__data_start__+1); + avail_in = (avail_in << 8) + *(&__data_start__+0); // compressed size. Correct. + int avail_out = &__data_end__ - &__data_start__; // uncompressed size. Correct. + // uncompress data segment to RAM + int res = LZ4_decompress_safe(&__data_src_start__ + 4, &__data_start__, avail_in, avail_out); - // initialize zlib for inflate - int res = inflateInit2(&data_section, 15); if (res < 0) return; - - // uncompress data segment to RAM - inflate(&data_section, Z_FINISH); - // save the size of the compressed data section - common_area.arg1 = data_section.total_in; + common_area.arg1 = res; } void __attribute__((section(".startos"))) Vector(void); diff --git a/common/lz4/lz4.c b/common/lz4/lz4.c index 9808d70ae..8fb99d913 100644 --- a/common/lz4/lz4.c +++ b/common/lz4/lz4.c @@ -182,6 +182,25 @@ #include /* memset, memcpy */ #define MEM_INIT(p,v,s) memset((p),(v),(s)) +#ifdef NEED_MEMMOVE +void * +memmove (void *dest, const void *src, size_t len) +{ + char *d = dest; + const char *s = src; + if (d < s) + while (len--) + *d++ = *s++; + else + { + char *lasts = (char*)s + (len-1); + char *lastd = d + (len-1); + while (len--) + *lastd-- = *lasts--; + } + return dest; +} +#endif /*-************************************ * Common Constants diff --git a/common_arm/Makefile.common b/common_arm/Makefile.common index c8dceead5..d6415dcda 100644 --- a/common_arm/Makefile.common +++ b/common_arm/Makefile.common @@ -35,7 +35,7 @@ OBJDIR = obj INCLUDE = -I../include -I../common_arm -I../common_fpga -I../common -I. # Also search prerequisites in the common directory (for usb.c), the fpga directory (for fpga.bit), and the zlib directory -VPATH = . ../common_arm ../common ../common/crapto1 ../common/mbedtls ../common/zlib ../fpga ../armsrc/Standalone +VPATH = . ../common_arm ../common ../common/crapto1 ../common/mbedtls ../common/lz4 ../fpga ../armsrc/Standalone INCLUDES = ../include/proxmark3_arm.h ../include/at91sam7s512.h ../include/config_gpio.h ../include/pm3_cmd.h