From e61530408c4b3605390748fc544b5afcfda996a3 Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Sun, 5 Apr 2015 19:15:02 +0200 Subject: [PATCH 1/1] add: hw ver: show FPGA versions for both HF and LF FPGA configs add: hw ver: show used and free flash memory chg: prepare fpgaloader for compressed FPGA configs --- armsrc/Makefile | 3 +- armsrc/appmain.c | 11 +- armsrc/apps.h | 2 +- armsrc/fpga_hf.bit.gz | Bin 0 -> 19160 bytes armsrc/fpga_lf.bit.gz | Bin 0 -> 18299 bytes armsrc/fpgaloader.c | 246 +++--- armsrc/inffast.h | 11 + armsrc/inffixed.h | 94 +++ armsrc/inflate.c | 1512 ++++++++++++++++++++++++++++++++++ armsrc/inflate.h | 122 +++ armsrc/inftrees.h | 62 ++ armsrc/ldscript | 1 + armsrc/zconf.h | 511 ++++++++++++ armsrc/zlib.h | 1768 ++++++++++++++++++++++++++++++++++++++++ armsrc/zutil.h | 253 ++++++ client/Makefile | 12 +- client/cmdhftopaz.c | 408 ++++++++++ client/cmdhw.c | 34 +- client/fpga_compress.c | 221 +++++ 19 files changed, 5137 insertions(+), 134 deletions(-) create mode 100644 armsrc/fpga_hf.bit.gz create mode 100644 armsrc/fpga_lf.bit.gz create mode 100644 armsrc/inffast.h create mode 100644 armsrc/inffixed.h create mode 100644 armsrc/inflate.c create mode 100644 armsrc/inflate.h create mode 100644 armsrc/inftrees.h create mode 100644 armsrc/zconf.h create mode 100644 armsrc/zlib.h create mode 100644 armsrc/zutil.h create mode 100644 client/cmdhftopaz.c create mode 100644 client/fpga_compress.c diff --git a/armsrc/Makefile b/armsrc/Makefile index 899b0307..3fd93ac3 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -30,7 +30,8 @@ THUMBSRC = start.c \ util.c \ string.c \ usb_cdc.c \ - cmd.c + cmd.c \ + inflate.c # These are to be compiled in ARM mode ARMSRC = fpgaloader.c \ diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 96644b9a..80ae4bc2 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -310,7 +310,7 @@ void ReadMem(int addr) /* osimage version information is linked in */ extern struct version_information version_information; /* bootrom version information is pointed to from _bootphase1_version_pointer */ -extern char *_bootphase1_version_pointer, _flash_start, _flash_end; +extern char *_bootphase1_version_pointer, _flash_start, _flash_end, _bootrom_start, _bootrom_end, __os_size__; void SendVersion(void) { char temp[512]; /* Limited data payload in USB packets */ @@ -331,10 +331,13 @@ void SendVersion(void) FormatVersionInformation(temp, sizeof(temp), "os: ", &version_information); DbpString(temp); - FpgaGatherVersion(temp, sizeof(temp)); + FpgaGatherVersion(FPGA_BITSTREAM_LF, temp, sizeof(temp)); DbpString(temp); - // Send Chip ID - cmd_send(CMD_ACK,*(AT91C_DBGU_CIDR),0,0,NULL,0); + FpgaGatherVersion(FPGA_BITSTREAM_HF, temp, sizeof(temp)); + DbpString(temp); + + // Send Chip ID and used flash memory + cmd_send(CMD_ACK, *(AT91C_DBGU_CIDR), (uint32_t)&_bootrom_end - (uint32_t)&_bootrom_start + (uint32_t)&__os_size__, 0, NULL, 0); } #ifdef WITH_LF diff --git a/armsrc/apps.h b/armsrc/apps.h index 57fb55fd..fa081d21 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -55,7 +55,7 @@ void FpgaSendCommand(uint16_t cmd, uint16_t v); void FpgaWriteConfWord(uint8_t v); void FpgaDownloadAndGo(int bitstream_version); int FpgaGatherBitstreamVersion(); -void FpgaGatherVersion(char *dst, int len); +void FpgaGatherVersion(int bitstream_version, char *dst, int len); void FpgaSetupSsc(void); void SetupSpi(int mode); bool FpgaSetupSscDma(uint8_t *buf, int len); diff --git a/armsrc/fpga_hf.bit.gz b/armsrc/fpga_hf.bit.gz new file mode 100644 index 0000000000000000000000000000000000000000..0cbb214d2cd73816870d583a0890aa3f64142f8d GIT binary patch literal 19160 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 literal 0 HcmV?d00001 diff --git a/armsrc/fpga_lf.bit.gz b/armsrc/fpga_lf.bit.gz new file mode 100644 index 0000000000000000000000000000000000000000..d736beed49b3f8d06886758910df578f539042f7 GIT binary patch literal 18299 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 - DownloadFPGA_byte(FpgaImage[(i++)^0x3]); - /* Explanation of the magic in the above line: - * i^0x3 inverts the lower two bits of the integer i, counting backwards - * for each 4 byte increment. The generated sequence of (i++)^3 is - * 3 2 1 0 7 6 5 4 11 10 9 8 15 14 13 12 etc. pp. - */ - } - } else { - while(FpgaImageLen-->0) - DownloadFPGA_byte(*FpgaImage++); + while(FpgaImageLen-->0) { + DownloadFPGA_byte(get_from_fpga_stream()); } // continue to clock FPGA until ready signal goes high @@ -250,39 +262,21 @@ static void DownloadFPGA(const char *FpgaImage, int FpgaImageLen, int byterevers LED_D_OFF(); } -static char *bitparse_headers_start; -static char *bitparse_bitstream_end; -static int bitparse_initialized = 0; + /* Simple Xilinx .bit parser. The file starts with the fixed opaque byte sequence * 00 09 0f f0 0f f0 0f f0 0f f0 00 00 01 * After that the format is 1 byte section type (ASCII character), 2 byte length * (big endian), bytes content. Except for section 'e' which has 4 bytes * length. */ -static const char _bitparse_fixed_header[] = {0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x01}; -static int bitparse_init(void * start_address, void *end_address) -{ - bitparse_initialized = 0; - - if(memcmp(_bitparse_fixed_header, start_address, sizeof(_bitparse_fixed_header)) != 0) { - return 0; /* Not matched */ - } else { - bitparse_headers_start= ((char*)start_address) + sizeof(_bitparse_fixed_header); - bitparse_bitstream_end= (char*)end_address; - bitparse_initialized = 1; - return 1; - } -} - -int bitparse_find_section(char section_name, char **section_start, unsigned int *section_length) +int bitparse_find_section(char section_name, unsigned int *section_length) { - char *pos = bitparse_headers_start; int result = 0; - - if(!bitparse_initialized) return 0; - - while(pos < bitparse_bitstream_end) { - char current_name = *pos++; + #define MAX_FPGA_BIT_STREAM_HEADER_SEARCH 100 // maximum number of bytes to search for the requested section + uint16_t numbytes = 0; + while(numbytes < MAX_FPGA_BIT_STREAM_HEADER_SEARCH) { + char current_name = get_from_fpga_stream(); + numbytes++; unsigned int current_length = 0; if(current_name < 'a' || current_name > 'e') { /* Strange section name, abort */ @@ -292,11 +286,13 @@ int bitparse_find_section(char section_name, char **section_start, unsigned int switch(current_name) { case 'e': /* Four byte length field */ - current_length += (*pos++) << 24; - current_length += (*pos++) << 16; + current_length += get_from_fpga_stream() << 24; + current_length += get_from_fpga_stream() << 16; + numbytes += 2; default: /* Fall through, two byte length field */ - current_length += (*pos++) << 8; - current_length += (*pos++) << 0; + current_length += get_from_fpga_stream() << 8; + current_length += get_from_fpga_stream() << 0; + numbytes += 2; } if(current_name != 'e' && current_length > 255) { @@ -306,108 +302,136 @@ int bitparse_find_section(char section_name, char **section_start, unsigned int if(current_name == section_name) { /* Found it */ - *section_start = pos; *section_length = current_length; result = 1; break; } - pos += current_length; /* Skip section */ + for (uint16_t i = 0; i < current_length && numbytes < MAX_FPGA_BIT_STREAM_HEADER_SEARCH; i++) { + get_from_fpga_stream(); + numbytes++; + } } return result; } +void init_fpga_inflate(void) +{ + // initialize zlib for inflate +} + + //----------------------------------------------------------------------------- // Find out which FPGA image format is stored in flash, then call DownloadFPGA // with the right parameters to download the image //----------------------------------------------------------------------------- -extern char _binary_fpga_lf_bit_start, _binary_fpga_lf_bit_end; -extern char _binary_fpga_hf_bit_start, _binary_fpga_hf_bit_end; void FpgaDownloadAndGo(int bitstream_version) { - void *bit_start; - void *bit_end; - + uint8_t header[FPGA_BITSTREAM_FIXED_HEADER_SIZE]; + // check whether or not the bitstream is already loaded - if (FpgaGatherBitstreamVersion() == bitstream_version) + if (downloaded_bitstream == bitstream_version) return; if (bitstream_version == FPGA_BITSTREAM_LF) { - bit_start = &_binary_fpga_lf_bit_start; - bit_end = &_binary_fpga_lf_bit_end; + reset_fpga_stream(&_binary_fpga_lf_bit_start); } else if (bitstream_version == FPGA_BITSTREAM_HF) { - bit_start = &_binary_fpga_hf_bit_start; - bit_end = &_binary_fpga_hf_bit_end; + reset_fpga_stream(&_binary_fpga_hf_bit_start); } else return; - /* Check for the new flash image format: Should have the .bit file at &_binary_fpga_bit_start - */ - if(bitparse_init(bit_start, bit_end)) { - /* Successfully initialized the .bit parser. Find the 'e' section and - * send its contents to the FPGA. - */ - char *bitstream_start; - unsigned int bitstream_length; - if(bitparse_find_section('e', &bitstream_start, &bitstream_length)) { - DownloadFPGA(bitstream_start, bitstream_length, 0); + uint16_t i = 0; + for (; i < GZIP_HEADER_SIZE; i++) { + header[i] = get_from_fpga_stream(); + } + + // Check for compressed new flash image format (starts with gzip header) + if(memcmp(_gzip_header, header, GZIP_HEADER_SIZE) == 0) { + init_fpga_inflate(); + } + + for (; i < FPGA_BITSTREAM_FIXED_HEADER_SIZE; i++) { + header[i] = get_from_fpga_stream(); + } + + // Check for the new flash image format: Should have the .bit file at &_binary_fpga_bit_start + if(memcmp(_bitparse_fixed_header, header, FPGA_BITSTREAM_FIXED_HEADER_SIZE) == 0) { + unsigned int bitstream_length; + if(bitparse_find_section('e', &bitstream_length)) { + DownloadFPGA(bitstream_length); + downloaded_bitstream = bitstream_version; return; /* All done */ } } - - /* Fallback for the old flash image format: Check for the magic marker 0xFFFFFFFF - * 0xAA995566 at address 0x102000. This is raw bitstream with a size of 336,768 bits - * = 10,524 uint32_t, stored as uint32_t e.g. little-endian in memory, but each DWORD - * is still to be transmitted in MSBit first order. Set the invert flag to indicate - * that the DownloadFPGA function should invert every 4 byte sequence when doing - * the bytewise download. - */ - if( *(uint32_t*)0x102000 == 0xFFFFFFFF && *(uint32_t*)0x102004 == 0xAA995566 ) - DownloadFPGA((char*)0x102000, 10524*4, 1); -} +} int FpgaGatherBitstreamVersion() { - char temp[256]; - FpgaGatherVersion(temp, sizeof (temp)); - if (!memcmp("LF", temp, 2)) - return FPGA_BITSTREAM_LF; - else if (!memcmp("HF", temp, 2)) - return FPGA_BITSTREAM_HF; - return FPGA_BITSTREAM_ERR; + return downloaded_bitstream; } -void FpgaGatherVersion(char *dst, int len) +void FpgaGatherVersion(int bitstream_version, char *dst, int len) { - char *fpga_info; unsigned int fpga_info_len; - dst[0] = 0; - if(!bitparse_find_section('e', &fpga_info, &fpga_info_len)) { - strncat(dst, "FPGA image: legacy image without version information", len-1); - } else { - /* USB packets only have 48 bytes data payload, so be terse */ - if(bitparse_find_section('a', &fpga_info, &fpga_info_len) && fpga_info[fpga_info_len-1] == 0 ) { - if (!memcmp("fpga_lf", fpga_info, 7)) - strncat(dst, "LF ", len-1); - else if (!memcmp("fpga_hf", fpga_info, 7)) - strncat(dst, "HF ", len-1); + char tempstr[40]; + + dst[0] = '\0'; + + if (bitstream_version == FPGA_BITSTREAM_LF) { + reset_fpga_stream(&_binary_fpga_lf_bit_start); + } else if (bitstream_version == FPGA_BITSTREAM_HF) { + reset_fpga_stream(&_binary_fpga_hf_bit_start); + } else + return; + + + for (uint16_t i = 0; i < FPGA_BITSTREAM_FIXED_HEADER_SIZE; i++) { + get_from_fpga_stream(); + } + + if(bitparse_find_section('a', &fpga_info_len)) { + for (uint16_t i = 0; i < fpga_info_len; i++) { + char c = (char)get_from_fpga_stream(); + if (i < sizeof(tempstr)) { + tempstr[i] = c; + } } - strncat(dst, "FPGA image built", len-1); -#if 0 - if(bitparse_find_section('b', &fpga_info, &fpga_info_len) && fpga_info[fpga_info_len-1] == 0 ) { - strncat(dst, " for ", len-1); - strncat(dst, fpga_info, len-1); + if (!memcmp("fpga_lf", tempstr, 7)) + strncat(dst, "LF ", len-1); + else if (!memcmp("fpga_hf", tempstr, 7)) + strncat(dst, "HF ", len-1); + } + strncat(dst, "FPGA image built", len-1); + if(bitparse_find_section('b', &fpga_info_len)) { + strncat(dst, " for ", len-1); + for (uint16_t i = 0; i < fpga_info_len; i++) { + char c = (char)get_from_fpga_stream(); + if (i < sizeof(tempstr)) { + tempstr[i] = c; + } } -#endif - if(bitparse_find_section('c', &fpga_info, &fpga_info_len) && fpga_info[fpga_info_len-1] == 0 ) { - strncat(dst, " on ", len-1); - strncat(dst, fpga_info, len-1); + strncat(dst, tempstr, len-1); + } + if(bitparse_find_section('c', &fpga_info_len)) { + strncat(dst, " on ", len-1); + for (uint16_t i = 0; i < fpga_info_len; i++) { + char c = (char)get_from_fpga_stream(); + if (i < sizeof(tempstr)) { + tempstr[i] = c; + } } - if(bitparse_find_section('d', &fpga_info, &fpga_info_len) && fpga_info[fpga_info_len-1] == 0 ) { - strncat(dst, " at ", len-1); - strncat(dst, fpga_info, len-1); + strncat(dst, tempstr, len-1); + } + if(bitparse_find_section('d', &fpga_info_len)) { + strncat(dst, " at ", len-1); + for (uint16_t i = 0; i < fpga_info_len; i++) { + char c = (char)get_from_fpga_stream(); + if (i < sizeof(tempstr)) { + tempstr[i] = c; + } } + strncat(dst, tempstr, len-1); } } diff --git a/armsrc/inffast.h b/armsrc/inffast.h new file mode 100644 index 00000000..e5c1aa4c --- /dev/null +++ b/armsrc/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/armsrc/inffixed.h b/armsrc/inffixed.h new file mode 100644 index 00000000..d6283277 --- /dev/null +++ b/armsrc/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. + It is part of the implementation of this library and is + subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/armsrc/inflate.c b/armsrc/inflate.c new file mode 100644 index 00000000..870f89bb --- /dev/null +++ b/armsrc/inflate.c @@ -0,0 +1,1512 @@ +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2012 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * Change history: + * + * 1.2.beta0 24 Nov 2002 + * - First version -- complete rewrite of inflate to simplify code, avoid + * creation of window when not needed, minimize use of window when it is + * needed, make inffast.c even faster, implement gzip decoding, and to + * improve code readability and style over the previous zlib inflate code + * + * 1.2.beta1 25 Nov 2002 + * - Use pointers for available input and output checking in inffast.c + * - Remove input and output counters in inffast.c + * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 + * - Remove unnecessary second byte pull from length extra in inffast.c + * - Unroll direct copy to three copies per loop in inffast.c + * + * 1.2.beta2 4 Dec 2002 + * - Change external routine names to reduce potential conflicts + * - Correct filename to inffixed.h for fixed tables in inflate.c + * - Make hbuf[] unsigned char to match parameter type in inflate.c + * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) + * to avoid negation problem on Alphas (64 bit) in inflate.c + * + * 1.2.beta3 22 Dec 2002 + * - Add comments on state->bits assertion in inffast.c + * - Add comments on op field in inftrees.h + * - Fix bug in reuse of allocated window after inflateReset() + * - Remove bit fields--back to byte structure for speed + * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths + * - Change post-increments to pre-increments in inflate_fast(), PPC biased? + * - Add compile time option, POSTINC, to use post-increments instead (Intel?) + * - Make MATCH copy in inflate() much faster for when inflate_fast() not used + * - Use local copies of stream next and avail values, as well as local bit + * buffer and bit count in inflate()--for speed when inflate_fast() not used + * + * 1.2.beta4 1 Jan 2003 + * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings + * - Move a comment on output buffer sizes from inffast.c to inflate.c + * - Add comments in inffast.c to introduce the inflate_fast() routine + * - Rearrange window copies in inflate_fast() for speed and simplification + * - Unroll last copy for window match in inflate_fast() + * - Use local copies of window variables in inflate_fast() for speed + * - Pull out common wnext == 0 case for speed in inflate_fast() + * - Make op and len in inflate_fast() unsigned for consistency + * - Add FAR to lcode and dcode declarations in inflate_fast() + * - Simplified bad distance check in inflate_fast() + * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new + * source file infback.c to provide a call-back interface to inflate for + * programs like gzip and unzip -- uses window as output buffer to avoid + * window copying + * + * 1.2.beta5 1 Jan 2003 + * - Improved inflateBack() interface to allow the caller to provide initial + * input in strm. + * - Fixed stored blocks bug in inflateBack() + * + * 1.2.beta6 4 Jan 2003 + * - Added comments in inffast.c on effectiveness of POSTINC + * - Typecasting all around to reduce compiler warnings + * - Changed loops from while (1) or do {} while (1) to for (;;), again to + * make compilers happy + * - Changed type of window in inflateBackInit() to unsigned char * + * + * 1.2.beta7 27 Jan 2003 + * - Changed many types to unsigned or unsigned short to avoid warnings + * - Added inflateCopy() function + * + * 1.2.0 9 Mar 2003 + * - Changed inflateBack() interface to provide separate opaque descriptors + * for the in() and out() functions + * - Changed inflateBack() argument and in_func typedef to swap the length + * and buffer address return values for the input function + * - Check next_in and next_out for Z_NULL on entry to inflate() + * + * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); +local int updatewindow OF((z_streamp strm, const unsigned char FAR *end, + unsigned copy)); +#ifdef BUILDFIXED + void makefixed OF((void)); +#endif +local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf, + unsigned len)); + +int ZEXPORT inflateResetKeep(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + if (state->wrap) /* to support ill-conceived Java test suite */ + strm->adler = state->wrap & 1; + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->dmax = 32768U; + state->head = Z_NULL; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + state->sane = 1; + state->back = -1; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +int ZEXPORT inflateReset(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + state->wsize = 0; + state->whave = 0; + state->wnext = 0; + return inflateResetKeep(strm); +} + +int ZEXPORT inflateReset2(strm, windowBits) +z_streamp strm; +int windowBits; +{ + int wrap; + struct inflate_state FAR *state; + + /* get the state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* extract wrap request from windowBits parameter */ + if (windowBits < 0) { + wrap = 0; + windowBits = -windowBits; + } + else { + wrap = (windowBits >> 4) + 1; +#ifdef GUNZIP + if (windowBits < 48) + windowBits &= 15; +#endif + } + + /* set number of window bits, free window if different */ + if (windowBits && (windowBits < 8 || windowBits > 15)) + return Z_STREAM_ERROR; + if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) { + ZFREE(strm, state->window); + state->window = Z_NULL; + } + + /* update state and reset the rest of it */ + state->wrap = wrap; + state->wbits = (unsigned)windowBits; + return inflateReset(strm); +} + +int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) +z_streamp strm; +int windowBits; +const char *version; +int stream_size; +{ + int ret; + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; +#endif + } + if (strm->zfree == (free_func)0) +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zfree = zcfree; +#endif + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + state->window = Z_NULL; + ret = inflateReset2(strm, windowBits); + if (ret != Z_OK) { + ZFREE(strm, state); + strm->state = Z_NULL; + } + return ret; +} + +int ZEXPORT inflateInit_(strm, version, stream_size) +z_streamp strm; +const char *version; +int stream_size; +{ + return inflateInit2_(strm, DEF_WBITS, version, stream_size); +} + +int ZEXPORT inflatePrime(strm, bits, value) +z_streamp strm; +int bits; +int value; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (bits < 0) { + state->hold = 0; + state->bits = 0; + return Z_OK; + } + if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; + value &= (1L << bits) - 1; + state->hold += value << state->bits; + state->bits += bits; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +#ifdef MAKEFIXED +#include + +/* + Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also + defines BUILDFIXED, so the tables are built on the fly. makefixed() writes + those tables to stdout, which would be piped to inffixed.h. A small program + can simply call makefixed to do this: + + void makefixed(void); + + int main(void) + { + makefixed(); + return 0; + } + + Then that can be linked with zlib built with MAKEFIXED defined and run: + + a.out > inffixed.h + */ +void makefixed() +{ + unsigned low, size; + struct inflate_state state; + + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op, + state.lencode[low].bits, state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +local int updatewindow(strm, end, copy) +z_streamp strm; +const Bytef *end; +unsigned copy; +{ + struct inflate_state FAR *state; + unsigned dist; + + state = (struct inflate_state FAR *)strm->state; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { + state->window = (unsigned char FAR *) + ZALLOC(strm, 1U << state->wbits, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->wnext = 0; + state->whave = 0; + } + + /* copy state->wsize or less output bytes into the circular window */ + if (copy >= state->wsize) { + zmemcpy(state->window, end - state->wsize, state->wsize); + state->wnext = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->wnext; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->wnext, end - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, end - copy, copy); + state->wnext = copy; + state->whave = state->wsize; + } + else { + state->wnext += dist; + if (state->wnext == state->wsize) state->wnext = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE(check, buf, len) \ + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) +#else +# define UPDATE(check, buf, len) adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int ZEXPORT inflate(strm, flush) +z_streamp strm; +int flush; +{ + struct inflate_state FAR *state; + z_const unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code here; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ +#endif + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + state->flags = 0; /* expect zlib header */ + if (state->head != Z_NULL) + state->head->done = -1; + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + len = BITS(4) + 8; + if (state->wbits == 0) + state->wbits = len; + else if (len > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + state->dmax = 1U << len; + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->head != Z_NULL) + state->head->text = (int)((hold >> 8) & 1); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + case TIME: + NEEDBITS(32); + if (state->head != Z_NULL) + state->head->time = hold; + if (state->flags & 0x0200) CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + case OS: + NEEDBITS(16); + if (state->head != Z_NULL) { + state->head->xflags = (int)(hold & 0xff); + state->head->os = (int)(hold >> 8); + } + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->head != Z_NULL) + state->head->extra_len = (unsigned)hold; + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + } + else if (state->head != Z_NULL) + state->head->extra = Z_NULL; + state->mode = EXTRA; + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->head != Z_NULL && + state->head->extra != Z_NULL) { + len = state->head->extra_len - state->length; + zmemcpy(state->head->extra + len, next, + len + copy > state->head->extra_max ? + state->head->extra_max - len : copy); + } + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->length = 0; + state->mode = NAME; + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->name != Z_NULL && + state->length < state->head->name_max) + state->head->name[state->length++] = len; + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->name = Z_NULL; + state->length = 0; + state->mode = COMMENT; + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->comment != Z_NULL && + state->length < state->head->comm_max) + state->head->comment[state->length++] = len; + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->comment = Z_NULL; + state->mode = HCRC; + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if (hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + if (state->head != Z_NULL) { + state->head->hcrc = (int)((state->flags >> 9) & 1); + state->head->done = 1; + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = ZSWAP32(hold); + INITBITS(); + state->mode = DICT; + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + case TYPE: + if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN_; /* decode codes */ + if (flush == Z_TREES) { + DROPBITS(2); + goto inf_leave; + } + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY_; + if (flush == Z_TREES) goto inf_leave; + case COPY_: + state->mode = COPY; + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (const code FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.val < 16) { + DROPBITS(here.bits); + state->lens[state->have++] = here.val; + } + else { + if (here.val == 16) { + NEEDBITS(here.bits + 2); + DROPBITS(here.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (here.val == 17) { + NEEDBITS(here.bits + 3); + DROPBITS(here.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(here.bits + 7); + DROPBITS(here.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* check for end-of-block code (better have one) */ + if (state->lens[256] == 0) { + strm->msg = (char *)"invalid code -- missing end-of-block"; + state->mode = BAD; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state->next = state->codes; + state->lencode = (const code FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (const code FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN_; + if (flush == Z_TREES) goto inf_leave; + case LEN_: + state->mode = LEN; + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + if (state->mode == TYPE) + state->back = -1; + break; + } + state->back = 0; + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.op && (here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + state->length = (unsigned)here.val; + if ((int)(here.op) == 0) { + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + state->mode = LIT; + break; + } + if (here.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->back = -1; + state->mode = TYPE; + break; + } + if (here.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(here.op) & 15; + state->mode = LENEXT; + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->was = state->length; + state->mode = DIST; + case DIST: + for (;;) { + here = state->distcode[BITS(state->distbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if ((here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + if (here.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)here.val; + state->extra = (unsigned)(here.op) & 15; + state->mode = DISTEXT; + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } +#ifdef INFLATE_STRICT + if (state->offset > state->dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->whave) { + if (state->sane) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + Trace((stderr, "inflate.c too far\n")); + copy -= state->whave; + if (copy > state->length) copy = state->length; + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = 0; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; +#endif + } + if (copy > state->wnext) { + copy -= state->wnext; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->wnext - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if (out) + strm->adler = state->check = + UPDATE(state->check, put - out, out); + out = left; + if (( +#ifdef GUNZIP + state->flags ? hold : +#endif + ZSWAP32(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if (hold != (state->total & 0xffffffffUL)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + RESTORE(); + if (state->wsize || (out != strm->avail_out && state->mode < BAD && + (state->mode < CHECK || flush != Z_FINISH))) + if (updatewindow(strm, strm->next_out, out - strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if (state->wrap && out) + strm->adler = state->check = + UPDATE(state->check, strm->next_out - out, out); + strm->data_type = state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0) + + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; +} + +int ZEXPORT inflateEnd(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +int ZEXPORT inflateGetDictionary(strm, dictionary, dictLength) +z_streamp strm; +Bytef *dictionary; +uInt *dictLength; +{ + struct inflate_state FAR *state; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* copy dictionary */ + if (state->whave && dictionary != Z_NULL) { + zmemcpy(dictionary, state->window + state->wnext, + state->whave - state->wnext); + zmemcpy(dictionary + state->whave - state->wnext, + state->window, state->wnext); + } + if (dictLength != Z_NULL) + *dictLength = state->whave; + return Z_OK; +} + +int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) +z_streamp strm; +const Bytef *dictionary; +uInt dictLength; +{ + struct inflate_state FAR *state; + unsigned long dictid; + int ret; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->wrap != 0 && state->mode != DICT) + return Z_STREAM_ERROR; + + /* check for correct dictionary identifier */ + if (state->mode == DICT) { + dictid = adler32(0L, Z_NULL, 0); + dictid = adler32(dictid, dictionary, dictLength); + if (dictid != state->check) + return Z_DATA_ERROR; + } + + /* copy dictionary to window using updatewindow(), which will amend the + existing dictionary if appropriate */ + ret = updatewindow(strm, dictionary + dictLength, dictLength); + if (ret) { + state->mode = MEM; + return Z_MEM_ERROR; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +int ZEXPORT inflateGetHeader(strm, head) +z_streamp strm; +gz_headerp head; +{ + struct inflate_state FAR *state; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; + + /* save header structure */ + state->head = head; + head->done = 0; + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +local unsigned syncsearch(have, buf, len) +unsigned FAR *have; +const unsigned char FAR *buf; +unsigned len; +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int ZEXPORT inflateSync(strm) +z_streamp strm; +{ + unsigned len; /* number of bytes to look at or looked at */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; + + /* check parameters */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->mode = TYPE; + return Z_OK; +} + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +int ZEXPORT inflateCopy(dest, source) +z_streamp dest; +z_streamp source; +{ + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + unsigned wsize; + + /* check input */ + if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || + source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; + + /* allocate space */ + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } + + /* copy state */ + zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); + zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state)); + if (state->lencode >= state->codes && + state->lencode <= state->codes + ENOUGH - 1) { + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + } + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) { + wsize = 1U << state->wbits; + zmemcpy(window, state->window, wsize); + } + copy->window = window; + dest->state = (struct internal_state FAR *)copy; + return Z_OK; +} + +int ZEXPORT inflateUndermine(strm, subvert) +z_streamp strm; +int subvert; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + state->sane = !subvert; +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + return Z_OK; +#else + state->sane = 1; + return Z_DATA_ERROR; +#endif +} + +long ZEXPORT inflateMark(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return -1L << 16; + state = (struct inflate_state FAR *)strm->state; + return ((long)(state->back) << 16) + + (state->mode == COPY ? state->length : + (state->mode == MATCH ? state->was - state->length : 0)); +} diff --git a/armsrc/inflate.h b/armsrc/inflate.h new file mode 100644 index 00000000..95f4986d --- /dev/null +++ b/armsrc/inflate.h @@ -0,0 +1,122 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2009 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD, /* i: waiting for magic header */ + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY_, /* i/o: same as COPY below, but only first time in */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN_, /* i: same as LEN below, but only first time in */ + LEN, /* i: waiting for length/lit/eob code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ + LENGTH, /* i: waiting for 32-bit length (gzip) */ + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to BAD or MEM on error -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) or (raw) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT -> + HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + (raw) -> TYPEDO + Read deflate blocks: + TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK + STORED -> COPY_ -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN_ + LEN_ -> LEN + Read deflate codes in fixed or dynamic block: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* state maintained between inflate() calls. Approximately 10K bytes. */ +struct inflate_state { + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + gz_headerp head; /* where to save gzip header information */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ + int sane; /* if false, allow invalid distance too far */ + int back; /* bits back of last unprocessed length/lit */ + unsigned was; /* initial length of match */ +}; diff --git a/armsrc/inftrees.h b/armsrc/inftrees.h new file mode 100644 index 00000000..baa53a0b --- /dev/null +++ b/armsrc/inftrees.h @@ -0,0 +1,62 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2005, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of the dynamic table. The maximum number of code structures is + 1444, which is the sum of 852 for literal/length codes and 592 for distance + codes. These values were found by exhaustive searches using the program + examples/enough.c found in the zlib distribtution. The arguments to that + program are the number of symbols, the initial root table size, and the + maximum bit length of a code. "enough 286 9 15" for literal/length codes + returns returns 852, and "enough 30 6 15" for distance codes returns 592. + The initial root table size (9 or 6) is found in the fifth argument of the + inflate_table() calls in inflate.c and infback.c. If the root table size is + changed, then these maximum sizes would be need to be recalculated and + updated. */ +#define ENOUGH_LENS 852 +#define ENOUGH_DISTS 592 +#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) + +/* Type of code to build for inflate_table() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/armsrc/ldscript b/armsrc/ldscript index 840b8196..ce7a330e 100644 --- a/armsrc/ldscript +++ b/armsrc/ldscript @@ -51,6 +51,7 @@ SECTIONS __data_src_start__ = LOADADDR(.data); __data_start__ = ADDR(.data); __data_end__ = __data_start__ + SIZEOF(.data); + __os_size__ = SIZEOF(.text) + SIZEOF(.data) + SIZEOF(.rodata); .bss : { __bss_start__ = .; diff --git a/armsrc/zconf.h b/armsrc/zconf.h new file mode 100644 index 00000000..9987a775 --- /dev/null +++ b/armsrc/zconf.h @@ -0,0 +1,511 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2013 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET + +/* all linked symbols */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_bits z__tr_flush_bits +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# endif +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePending z_deflatePending +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# ifdef _WIN32 +# define gzopen_w z_gzopen_w +# endif +# define gzprintf z_gzprintf +# define gzvprintf z_gzvprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzwrite z_gzwrite +# endif +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetHeader z_inflateGetHeader +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateSetDictionary z_inflateSetDictionary +# define inflateGetDictionary z_inflateGetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflateResetKeep z_inflateResetKeep +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# ifndef Z_SOLO +# define uncompress z_uncompress +# endif +# define zError z_zError +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# ifndef Z_SOLO +# define gzFile z_gzFile +# endif +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +#if defined(ZLIB_CONST) && !defined(z_const) +# define z_const const +#else +# define z_const +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +#ifndef Z_ARG /* function prototypes for stdarg */ +# if defined(STDC) || defined(Z_HAVE_STDARG_H) +# define Z_ARG(args) args +# else +# define Z_ARG(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +# include +# if (UINT_MAX == 0xffffffffUL) +# define Z_U4 unsigned +# elif (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# elif (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short +# endif +#endif + +#ifdef Z_U4 + typedef Z_U4 z_crc_t; +#else + typedef unsigned long z_crc_t; +#endif + +#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + +#ifdef STDC +# ifndef Z_SOLO +# include /* for off_t */ +# endif +#endif + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +# include /* for va_list */ +# endif +#endif + +#ifdef _WIN32 +# ifndef Z_SOLO +# include /* for wchar_t */ +# endif +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) +# define Z_HAVE_UNISTD_H +#endif +#ifndef Z_SOLO +# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +# endif +#endif + +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if !defined(_WIN32) && defined(Z_LARGE64) +# define z_off64_t off64_t +#else +# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# define z_off64_t __int64 +# else +# define z_off64_t z_off_t +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/armsrc/zlib.h b/armsrc/zlib.h new file mode 100644 index 00000000..3e0c7672 --- /dev/null +++ b/armsrc/zlib.h @@ -0,0 +1,1768 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.8, April 28th, 2013 + + Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 + (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.8" +#define ZLIB_VERNUM 0x1280 +#define ZLIB_VER_MAJOR 1 +#define ZLIB_VER_MINOR 2 +#define ZLIB_VER_REVISION 8 +#define ZLIB_VER_SUBREVISION 0 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed data. + This version of the library supports only one compression method (deflation) + but other algorithms will be added later and will have the same stream + interface. + + Compression can be done in a single step if the buffers are large enough, + or can be done by repeated calls of the compression function. In the latter + case, the application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip streams in memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never crash + even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + z_const Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total number of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total number of bytes output so far */ + + z_const char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has dropped + to zero. It must update next_out and avail_out when avail_out has dropped + to zero. The application must initialize zalloc, zfree and opaque before + calling the init function. All other fields are set by the compression + library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this if + the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers + returned by zalloc for objects of exactly 65536 bytes *must* have their + offset normalized to zero. The default allocation function provided by this + library ensures this (see zutil.c). To reduce memory requirements and avoid + any allocation of 64K objects, at the expense of compression ratio, compile + the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or progress + reports. After compression, total_in holds the total size of the + uncompressed data and may be saved for use in the decompressor (particularly + if the decompressor wants to decompress everything in a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +#define Z_TREES 6 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is not + compatible with the zlib.h header file used by the application. This check + is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. If + zalloc and zfree are set to Z_NULL, deflateInit updates them to use default + allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at all + (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION + requests a default compromise between speed and compression (currently + equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if level is not a valid compression level, or + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). msg is set to null + if there is no error message. deflateInit does not perform any compression: + this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). Some + output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating avail_in or avail_out accordingly; avail_out should + never be zero before the call. The application can consume the compressed + output when it wants, for example when the output buffer is full (avail_out + == 0), or after each call of deflate(). If deflate returns Z_OK and with + zero avail_out, it must be called again after making room in the output + buffer because there might be more output pending. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumulate before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In + particular avail_in is zero after the call if enough output space has been + provided before the call.) Flushing may degrade compression for some + compression algorithms and so it should be used only when necessary. This + completes the current deflate block and follows it with an empty stored block + that is three bits plus filler bits to the next byte, followed by four bytes + (00 00 ff ff). + + If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the + output buffer, but the output is not aligned to a byte boundary. All of the + input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. + This completes the current deflate block and follows it with an empty fixed + codes block that is 10 bits long. This assures that enough bytes are output + in order for the decompressor to finish the block before the empty fixed code + block. + + If flush is set to Z_BLOCK, a deflate block is completed and emitted, as + for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to + seven bits of the current block are held to be written as the next byte after + the next deflate block is completed. In this case, the decompressor may not + be provided enough bits at this point in order to complete decompression of + the data provided so far to the compressor. It may need to wait for the next + block to be emitted. This is for advanced applications that need to control + the emission of deflate blocks. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there was + enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the stream + are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least the + value returned by deflateBound (see below). Then deflate is guaranteed to + return Z_STREAM_END. If not enough output space is provided, deflate will + not return Z_STREAM_END, and it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered + binary. This field is only for information purposes and does not affect the + compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, msg + may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the + exact value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit() does not process any header information -- that is deferred + until inflate() is called. +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing will + resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there is + no more input data or no more space in the output buffer (see below about + the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating the next_* and avail_* values accordingly. The + application can consume the uncompressed output when it wants, for example + when the output buffer is full (avail_out == 0), or after each call of + inflate(). If inflate returns Z_OK and with zero avail_out, it must be + called again after making room in the output buffer because there might be + more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, + Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() + stop if and when it gets to the next deflate block boundary. When decoding + the zlib or gzip format, this will cause inflate() to return immediately + after the header and before the first block. When doing a raw inflate, + inflate() will go ahead and process the first block, and will return when it + gets to the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 if + inflate() is currently decoding the last block in the deflate stream, plus + 128 if inflate() returned immediately after decoding an end-of-block code or + decoding the complete header up to just before the first byte of the deflate + stream. The end-of-block will not be indicated until all of the uncompressed + data from that block has been written to strm->next_out. The number of + unused bits may in general be greater than seven, except when bit 7 of + data_type is set, in which case the number of unused bits will be less than + eight. data_type is set as noted here every time inflate() returns for all + flush options, and so can be used to determine the amount of currently + consumed input in bits. + + The Z_TREES option behaves as Z_BLOCK does, but it also returns when the + end of each deflate block header is reached, before any actual data in that + block is decoded. This allows the caller to determine the length of the + deflate block header for later use in random access within a deflate block. + 256 is added to the value of strm->data_type when inflate() returns + immediately after reaching the end of the deflate block header. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step (a + single call of inflate), the parameter flush should be set to Z_FINISH. In + this case all pending input is processed and all pending output is flushed; + avail_out must be large enough to hold all of the uncompressed data for the + operation to complete. (The size of the uncompressed data may have been + saved by the compressor for this purpose.) The use of Z_FINISH is not + required to perform an inflation in one step. However it may be used to + inform inflate that a faster approach can be used for the single inflate() + call. Z_FINISH also informs inflate to not maintain a sliding window if the + stream completes, which reduces inflate's memory footprint. If the stream + does not complete, either because not all of the stream is provided or not + enough output space is provided, then a sliding window will be allocated and + inflate() can be called again to continue the operation as if Z_NO_FLUSH had + been used. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the effects of the flush parameter in this implementation are + on the return value of inflate() as noted below, when inflate() returns early + when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of + memory for a sliding window when Z_FINISH is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the Adler-32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the Adler-32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() can decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically, if requested when + initializing with inflateInit2(). Any information contained in the gzip + header is not retained, so applications that need that information should + instead use raw inflate, see inflateInit2() below, or inflateBack() and + perform their own processing of the gzip header and trailer. When processing + gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output + producted so far. The CRC-32 is checked against the gzip trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may + then call inflateSync() to look for a good compression block if a partial + recovery of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by the + caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), no + header crc, and the operating system will be set to 255 (unknown). If a + gzip stream is being written, strm->adler is a crc32 instead of an adler32. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but is + slow and reduces compression ratio; memLevel=9 uses maximum memory for + optimal speed. The default value is 8. See zconf.h for total memory usage + as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as + fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The + strategy parameter only affects the compression ratio but not the + correctness of the compressed output even if it is not set appropriately. + Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler + decoder for special applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid + method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is + incompatible with the version assumed by the caller (ZLIB_VERSION). msg is + set to null if there is no error message. deflateInit2 does not perform any + compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. When using the zlib format, this + function must be called immediately after deflateInit, deflateInit2 or + deflateReset, and before any call of deflate. When doing raw deflate, this + function must be called either before any call of deflate, or immediately + after the completion of a deflate block, i.e. after all input has been + consumed and all output has been delivered when using any of the flush + options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The + compressor and decompressor must use exactly the same dictionary (see + inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size + provided in deflateInit or deflateInit2. Thus the strings most likely to be + useful should be put at the end of the dictionary, not at the front. In + addition, the current implementation of deflate will use at most the window + size minus 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if not at a block boundary for raw deflate). deflateSetDictionary does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and can + consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. The + stream will keep the same compression level and any other attributes that + may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different strategy. + If the compression level is changed, the input available so far is + compressed with the old level (and may be flushed); the new level will take + effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to be + compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if + strm->avail_out was zero. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() or + deflateInit2(), and after deflateSetHeader(), if used. This would be used + to allocate an output buffer for deflation in a single pass, and so would be + called before deflate(). If that first deflate() call is provided the + sourceLen input bytes, an output buffer allocated to the size returned by + deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed + to return Z_STREAM_END. Note that it is possible for the compressed size to + be larger than the value returned by deflateBound() if flush options other + than Z_FINISH or Z_NO_FLUSH are used. +*/ + +ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, + unsigned *pending, + int *bits)); +/* + deflatePending() returns the number of bytes and bits of output that have + been generated, but not yet provided in the available output. The bytes not + provided would be due to the available output space having being consumed. + The number of bits of output not provided are between 0 and 7, where they + await more bits to join them in order to fill out a full byte. If pending + or bits are Z_NULL, then those values are not set. + + deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. + */ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the bits + leftover from a previous deflate stream when appending to it. As such, this + function can only be used for raw deflate, and must be used before the first + deflate() call after a deflateInit2() or deflateReset(). bits must be less + than or equal to 16, and that many of the least significant bits of value + will be inserted in the output. + + deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough + room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be zero to request that inflate use the window size in + the zlib header of the compressed stream. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a + crc32 instead of an adler32. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit2 does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit2() does not process any header information -- that is + deferred until inflate() is called. +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called at any + time to set the dictionary. If the provided dictionary is smaller than the + window and there is already data in the window, then the provided dictionary + will amend what's there. The application must insure that the dictionary + that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by inflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If inflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a possible full flush point (see above + for the description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync searches for a 00 00 FF FF pattern in the compressed data. + All full flush points have this pattern, but not all occurrences of this + pattern are full flush points. + + inflateSync returns Z_OK if a possible full flush point has been found, + Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point + has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. + In the success case, the application may save the current current value of + total_in which indicates where valid compressed data was found. In the + error case, the application may repeatedly call inflateSync, providing more + input each time, until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. The + stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, + int windowBits)); +/* + This function is the same as inflateReset, but it also permits changing + the wrap and window size requests. The windowBits parameter is interpreted + the same as it is for inflateInit2. + + inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL), or if + the windowBits parameter is invalid. +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + If bits is negative, then the input stream bit buffer is emptied. Then + inflatePrime() can be called again to put bits in the buffer. This is used + to clear out bits leftover after feeding inflate a block description prior + to feeding inflate codes. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); +/* + This function returns two values, one in the lower 16 bits of the return + value, and the other in the remaining upper bits, obtained by shifting the + return value down 16 bits. If the upper value is -1 and the lower value is + zero, then inflate() is currently decoding information outside of a block. + If the upper value is -1 and the lower value is non-zero, then inflate is in + the middle of a stored block, with the lower value equaling the number of + bytes from the input remaining to copy. If the upper value is not -1, then + it is the number of bits back from the current bit position in the input of + the code (literal or length/distance pair) currently being processed. In + that case the lower value is the number of bytes already emitted for that + code. + + A code is being processed if inflate is waiting for more input to complete + decoding of the code, or if it has completed decoding but is waiting for + more output space to write the literal or match data. + + inflateMark() is used to mark locations in the input data for random + access, which may be at bit positions, and to note those cases where the + output of a code may span boundaries of random access blocks. The current + location in the input stream can be determined from avail_in and data_type + as noted in the description for the Z_BLOCK flush parameter for inflate. + + inflateMark returns the value noted above or -1 << 16 if the provided + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be + used to force inflate() to return immediately after header processing is + complete and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When any + of extra, name, or comment are not Z_NULL and the respective field is not + present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the parameters are invalid, Z_MEM_ERROR if the internal state could not be + allocated, or Z_VERSION_ERROR if the version of the library does not match + the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, + z_const unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is potentially more efficient than + inflate() for file i/o applications, in that it avoids copying between the + output and the sliding window by simply making the window itself the output + buffer. inflate() can be faster on modern CPUs when used with large + buffers. inflateBack() trusts the application to not change the output + buffer passed by the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free the + allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects only + the raw deflate stream to decompress. This is different from the normal + behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format error + in the deflate stream (in which case strm->msg is set to indicate the nature + of the error), or Z_STREAM_ERROR if the stream was not properly initialized. + In the case of Z_BUF_ERROR, an input or output error can be distinguished + using strm->next_in which will be Z_NULL only if in() returned an error. If + strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning + non-zero. (in() will always be called before out(), so strm->next_in is + assured to be defined if out() returns non-zero.) Note that inflateBack() + cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + +#ifndef Z_SOLO + + /* utility functions */ + +/* + The following utility functions are implemented on top of the basic + stream-oriented functions. To simplify the interface, some default options + are assumed (compression level and memory usage, standard memory allocation + functions). The source code of these utility functions can be modified if + you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before a + compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, destLen + is the actual size of the uncompressed buffer. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In + the case where there is not enough room, uncompress() will fill the output + buffer with the uncompressed data up to that point. +*/ + + /* gzip file access functions */ + +/* + This library supports reading and writing files in gzip (.gz) format with + an interface similar to that of stdio, using the functions that start with + "gz". The gzip format is different from the zlib format. gzip is a gzip + wrapper, documented in RFC 1952, wrapped around a deflate stream. +*/ + +typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ + +/* +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); + + Opens a gzip (.gz) file for reading or writing. The mode parameter is as + in fopen ("rb" or "wb") but can also include a compression level ("wb9") or + a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only + compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' + for fixed code compression as in "wb9F". (See the description of + deflateInit2 for more information about the strategy parameter.) 'T' will + request transparent writing or appending with no compression and not using + the gzip format. + + "a" can be used instead of "w" to request that the gzip stream that will + be written be appended to the file. "+" will result in an error, since + reading and writing to the same gzip file is not supported. The addition of + "x" when writing will create the file exclusively, which fails if the file + already exists. On systems that support it, the addition of "e" when + reading or writing will set the flag to close the file on an execve() call. + + These functions, as well as gzip, will read and decode a sequence of gzip + streams in a file. The append function of gzopen() can be used to create + such a file. (Also see gzflush() for another way to do this.) When + appending, gzopen does not test whether the file begins with a gzip stream, + nor does it look for the end of the gzip streams to begin appending. gzopen + will simply append a gzip stream to the existing file. + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. When + reading, this will be detected automatically by looking for the magic two- + byte gzip header. + + gzopen returns NULL if the file could not be opened, if there was + insufficient memory to allocate the gzFile state, or if an invalid mode was + specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). + errno can be checked to determine if the reason gzopen failed was that the + file could not be opened. +*/ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen associates a gzFile with the file descriptor fd. File descriptors + are obtained from calls like open, dup, creat, pipe or fileno (if the file + has been previously opened with fopen). The mode parameter is as in gzopen. + + The next call of gzclose on the returned gzFile will also close the file + descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor + fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, + mode);. The duplicated descriptor should be saved to avoid a leak, since + gzdopen does not close fd if it fails. If you are using fileno() to get the + file descriptor from a FILE *, then you will have to use dup() to avoid + double-close()ing the file descriptor. Both gzclose() and fclose() will + close the associated file descriptor, so they need to have different file + descriptors. + + gzdopen returns NULL if there was insufficient memory to allocate the + gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not + provided, or '+' was provided), or if fd is -1. The file descriptor is not + used until the next gz* read, write, seek, or close operation, so gzdopen + will not detect if fd is invalid (unless fd is -1). +*/ + +ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); +/* + Set the internal buffer size used by this library's functions. The + default buffer size is 8192 bytes. This function must be called after + gzopen() or gzdopen(), and before any other calls that read or write the + file. The buffer memory allocation is always deferred to the first read or + write. Two buffers are allocated, either both of the specified size when + writing, or one of the specified size and the other twice that size when + reading. A larger buffer size of, for example, 64K or 128K bytes will + noticeably increase the speed of decompression (reading). + + The new buffer size also affects the maximum length for gzprintf(). + + gzbuffer() returns 0 on success, or -1 on failure, such as being called + too late. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. If + the input file is not in gzip format, gzread copies the given number of + bytes into the buffer directly from the file. + + After reaching the end of a gzip stream in the input, gzread will continue + to read, looking for another gzip stream. Any number of gzip streams may be + concatenated in the input file, and will all be decompressed by gzread(). + If something other than a gzip stream is encountered after a gzip stream, + that remaining trailing garbage is ignored (and no error is returned). + + gzread can be used to read a gzip file that is being concurrently written. + Upon reaching the end of the input, gzread will return with the available + data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then + gzclearerr can be used to clear the end of file indicator in order to permit + gzread to be tried again. Z_OK indicates that a gzip stream was completed + on the last gzread. Z_BUF_ERROR indicates that the input file ended in the + middle of a gzip stream. Note that gzread does not return -1 in the event + of an incomplete gzip stream. This error is deferred until gzclose(), which + will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip + stream. Alternatively, gzerror can be used before gzclose to detect this + case. + + gzread returns the number of uncompressed bytes actually read, less than + len for end of file, or -1 for error. +*/ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes written or 0 in case of + error. +*/ + +ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the arguments to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or 0 in case of error. The number of + uncompressed bytes written is limited to 8191, or one less than the buffer + size given to gzbuffer(). The caller should assure that this limit is not + exceeded. If it is exceeded, then gzprintf() will return an error (0) with + nothing written. In this case, there may also be a buffer overflow with + unpredictable consequences, which is possible only if zlib was compiled with + the insecure functions sprintf() or vsprintf() because the secure snprintf() + or vsnprintf() functions were not available. This can be determined using + zlibCompileFlags(). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or a + newline character is read and transferred to buf, or an end-of-file + condition is encountered. If any characters are read or if len == 1, the + string is terminated with a null character. If no characters are read due + to an end-of-file or len < 1, then the buffer is left untouched. + + gzgets returns buf which is a null-terminated string, or it returns NULL + for end-of-file or in case of error. If there was an error, the contents at + buf are indeterminate. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. gzputc + returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte or -1 + in case of end of file or error. This is implemented as a macro for speed. + As such, it does not do all of the checking the other functions do. I.e. + it does not check to see if file is NULL, nor whether the structure file + points to has been clobbered or not. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read as the first character + on the next read. At least one character of push-back is allowed. + gzungetc() returns the character pushed, or -1 on failure. gzungetc() will + fail if c is -1, and may fail if a character has been pushed but not read + yet. If gzungetc is used immediately after gzopen or gzdopen, at least the + output buffer size of pushed characters is allowed. (See gzbuffer above.) + The pushed character will be discarded if the stream is repositioned with + gzseek() or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter flush + is as in the deflate() function. The return value is the zlib error number + (see function gzerror below). gzflush is only permitted when writing. + + If the flush parameter is Z_FINISH, the remaining data is written and the + gzip stream is completed in the output. If gzwrite() is called again, a new + gzip stream will be started in the output. gzread() is able to read such + concatented gzip streams. + + gzflush should be called only when strictly necessary because it will + degrade compression if called too often. +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); + + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); + + Returns the starting position for the next gzread or gzwrite on the given + compressed file. This position represents a number of bytes in the + uncompressed data stream, and is zero when starting, even if appending or + reading a gzip stream from the middle of a file using gzdopen(). + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); + + Returns the current offset in the file being read or written. This offset + includes the count of bytes that precede the gzip stream, for example when + appending or when using gzdopen() for reading. When reading, the offset + does not include as yet unused buffered input. This information can be used + for a progress indicator. On error, gzoffset() returns -1. +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns true (1) if the end-of-file indicator has been set while reading, + false (0) otherwise. Note that the end-of-file indicator is set only if the + read tried to go past the end of the input, but came up short. Therefore, + just like feof(), gzeof() may return false even if there is no more data to + read, in the event that the last read request was for the exact number of + bytes remaining in the input file. This will happen if the input file size + is an exact multiple of the buffer size. + + If gzeof() returns true, then the read functions will return no more data, + unless the end-of-file indicator is reset by gzclearerr() and the input file + has grown since the previous end of file was detected. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. + + If the input file is empty, gzdirect() will return true, since the input + does not contain a gzip stream. + + If gzdirect() is used immediately after gzopen() or gzdopen() it will + cause buffers to be allocated to allow reading the file to determine if it + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). + + When writing, gzdirect() returns true (1) if transparent writing was + requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: + gzdirect() is not needed when writing. Transparent writing must be + explicitly requested, so the application already knows the answer. When + linking statically, using gzdirect() will include all of the zlib code for + gzip file reading and decompression, which may not be desired.) +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file and + deallocates the (de)compression state. Note that once file is closed, you + cannot call gzerror with file, since its structures have been deallocated. + gzclose must not be called more than once on the same file, just as free + must not be called more than once on the same allocation. + + gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a + file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the + last read ended in the middle of a gzip stream, or Z_OK on success. +*/ + +ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); +/* + Same as gzclose(), but gzclose_r() is only for use when reading, and + gzclose_w() is only for use when writing or appending. The advantage to + using these instead of gzclose() is that they avoid linking in zlib + compression or decompression code that is not used when only reading or only + writing respectively. If gzclose() is used, then both compression and + decompression code will be included the application when linking to a static + zlib library. +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the given + compressed file. errnum is set to zlib error number. If an error occurred + in the file system and not in the compression library, errnum is set to + Z_ERRNO and the application may consult errno to get the exact error code. + + The application must not modify the returned string. Future calls to + this function may invalidate the previously returned string. If file is + closed, then the string previously returned by gzerror will no longer be + available. + + gzerror() should be used to distinguish errors from end-of-file for those + functions above that do not distinguish those cases in their return values. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + +#endif /* !Z_SOLO */ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the compression + library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is Z_NULL, this function returns the + required initial value for the checksum. + + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. + + Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +/* +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); + + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note + that the z_off_t type (like off_t) is a signed integer. If len2 is + negative, the result has no meaning or utility. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is Z_NULL, this function returns the required + initial value for the crc. Pre- and post-conditioning (one's complement) is + performed within this function so it shouldn't be done by the application. + + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) + +#ifndef Z_SOLO + +/* gzgetc() macro and its supporting function and exposed data structure. Note + * that the real internal state is much larger than the exposed structure. + * This abbreviated structure exposes just enough for the gzgetc() macro. The + * user should not mess with these exposed elements, since their names or + * behavior could change in the future, perhaps even capriciously. They can + * only be used by the gzgetc() macro. You have been warned. + */ +struct gzFile_s { + unsigned have; + unsigned char *next; + z_off64_t pos; +}; +ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ +#ifdef Z_PREFIX_SET +# undef z_gzgetc +# define z_gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g)) +#else +# define gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g)) +#endif + +/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or + * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if + * both are true, the application gets the *64 functions, and the regular + * functions are changed to 64 bits) -- in case these are set on systems + * without large file support, _LFS64_LARGEFILE must also be true + */ +#ifdef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); +#endif + +#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) +# ifdef Z_PREFIX_SET +# define z_gzopen z_gzopen64 +# define z_gzseek z_gzseek64 +# define z_gztell z_gztell64 +# define z_gzoffset z_gzoffset64 +# define z_adler32_combine z_adler32_combine64 +# define z_crc32_combine z_crc32_combine64 +# else +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# endif +# ifndef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +# endif +#else + ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); +#endif + +#else /* Z_SOLO */ + + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); + +#endif /* !Z_SOLO */ + +/* hack for buggy compilers */ +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; +#endif + +/* undocumented functions */ +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); +ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); +ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); +ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); +ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); +#if defined(_WIN32) && !defined(Z_SOLO) +ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, + const char *mode)); +#endif +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file, + const char *format, + va_list va)); +# endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/armsrc/zutil.h b/armsrc/zutil.h new file mode 100644 index 00000000..24ab06b1 --- /dev/null +++ b/armsrc/zutil.h @@ -0,0 +1,253 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2013 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#ifdef HAVE_HIDDEN +# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) +#else +# define ZLIB_INTERNAL +#endif + +#include "zlib.h" + +#if defined(STDC) && !defined(Z_SOLO) +# if !(defined(_WIN32_WCE) && defined(_MSC_VER)) +# include +# endif +# include +# include +#endif + +#ifdef Z_SOLO + typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */ +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# ifndef Z_SOLO +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +# if defined(M_I86) && !defined(Z_SOLO) +# include +# endif +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# ifndef Z_SOLO +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +# endif +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#ifdef WIN32 +# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ +# define OS_CODE 0x0b +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0f +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + +#if defined(__BORLANDC__) && !defined(MSDOS) + #pragma warn -8004 + #pragma warn -8008 + #pragma warn -8066 +#endif + +/* provide prototypes for these when building zlib without LFS */ +#if !defined(_WIN32) && \ + (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(pyr) || defined(Z_SOLO) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include + extern int ZLIB_INTERNAL z_verbose; + extern void ZLIB_INTERNAL z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + +#ifndef Z_SOLO + voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, + unsigned size)); + void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); +#endif + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +/* Reverse the bytes in a 32-bit value */ +#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +#endif /* ZUTIL_H */ diff --git a/client/Makefile b/client/Makefile index 7954d1ea..44ca8a96 100644 --- a/client/Makefile +++ b/client/Makefile @@ -12,7 +12,8 @@ CXX=g++ VPATH = ../common OBJDIR = obj -LDLIBS = -L/opt/local/lib -L/usr/local/lib ../liblua/liblua.a -lreadline -lpthread -lm +LDLIBS = -L/opt/local/lib -L/usr/local/lib -lreadline -lpthread -lm +LUALIB = ../liblua/liblua.a LDFLAGS = $(COMMON_FLAGS) CFLAGS = -std=c99 -I. -I../include -I../common -I/opt/local/include -I../liblua -Wall $(COMMON_FLAGS) -g -O4 LUAPLATFORM = generic @@ -108,15 +109,15 @@ COREOBJS = $(CORESRCS:%.c=$(OBJDIR)/%.o) CMDOBJS = $(CMDSRCS:%.c=$(OBJDIR)/%.o) RM = rm -f -BINS = proxmark3 flasher #snooper cli +BINS = proxmark3 flasher fpga_compress #snooper cli CLEAN = cli cli.exe flasher flasher.exe proxmark3 proxmark3.exe snooper snooper.exe $(CMDOBJS) $(OBJDIR)/*.o *.o *.moc.cpp all: lua_build $(BINS) all-static: LDLIBS:=-static $(LDLIBS) -all-static: snooper cli flasher +all-static: snooper cli flasher fpga_compress -proxmark3: LDLIBS+=$(QTLDLIBS) +proxmark3: LDLIBS+=$(QTLDLIBS) $(LUALIB) proxmark3: $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(QTGUI) $(CXX) $(CXXFLAGS) $^ $(LDLIBS) -o $@ @@ -129,6 +130,9 @@ cli: $(OBJDIR)/cli.o $(COREOBJS) $(CMDOBJS) $(OBJDIR)/guidummy.o flasher: $(OBJDIR)/flash.o $(OBJDIR)/flasher.o $(COREOBJS) $(CXX) $(CXXFLAGS) $^ $(LDLIBS) -o $@ +fpga_compress: $(OBJDIR)/fpga_compress.o + $(CXX) $(CXXFLAGS) $^ $(LDLIBS) -o $@ + $(OBJDIR)/%.o: %.c $(CC) $(CFLAGS) -c -o $@ $< diff --git a/client/cmdhftopaz.c b/client/cmdhftopaz.c new file mode 100644 index 00000000..e76b3fb5 --- /dev/null +++ b/client/cmdhftopaz.c @@ -0,0 +1,408 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2015 Piwi +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// High frequency Topaz (NFC Type 1) commands +//----------------------------------------------------------------------------- + +#include +#include +#include +#include +#include "cmdmain.h" +#include "cmdparser.h" +#include "cmdhftopaz.h" +#include "cmdhf14a.h" +#include "ui.h" +#include "mifare.h" +#include "proxmark3.h" +#include "iso14443crc.h" +#include "protocols.h" + +#define TOPAZ_MAX_MEMORY 2048 + +static struct { + uint8_t HR01[2]; + uint8_t uid[7]; + uint8_t size; + uint8_t data_blocks[TOPAZ_MAX_MEMORY/8][8]; + uint8_t *dynamic_lock_areas; + uint8_t *dynamic_reserved_areas; +} topaz_tag; + + +static void topaz_switch_on_field(void) +{ + UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_SELECT | ISO14A_NO_DISCONNECT | ISO14A_TOPAZMODE, 0, 0}}; + SendCommand(&c); +} + + +static void topaz_switch_off_field(void) +{ + UsbCommand c = {CMD_READER_ISO_14443a, {0, 0, 0}}; + SendCommand(&c); +} + + +static int topaz_send_cmd_raw(uint8_t *cmd, uint8_t len, uint8_t *response) +{ + UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_NO_DISCONNECT | ISO14A_TOPAZMODE, len, 0}}; + memcpy(c.d.asBytes, cmd, len); + SendCommand(&c); + + UsbCommand resp; + WaitForResponse(CMD_ACK, &resp); + + if (resp.arg[0] > 0) { + memcpy(response, resp.d.asBytes, resp.arg[0]); + } + + return resp.arg[0]; +} + + +static int topaz_send_cmd(uint8_t *cmd, uint8_t len, uint8_t *response) +{ + if (len > 1) { + uint8_t first, second; + ComputeCrc14443(CRC_14443_B, cmd, len-2, &first, &second); + cmd[len-2] = first; + cmd[len-1] = second; + } + + return topaz_send_cmd_raw(cmd, len, response); +} + + +static int topaz_select(uint8_t *atqa, uint8_t *rid_response) +{ + // ToDo: implement anticollision + + uint8_t wupa_cmd[] = {TOPAZ_WUPA}; + uint8_t rid_cmd[] = {TOPAZ_RID, 0, 0, 0, 0, 0, 0, 0, 0}; + + topaz_switch_on_field(); + + if (!topaz_send_cmd(wupa_cmd, sizeof(wupa_cmd), atqa)) { + topaz_switch_off_field(); + return -1; // WUPA failed + } + + if (!topaz_send_cmd(rid_cmd, sizeof(rid_cmd), rid_response)) { + topaz_switch_off_field(); + return -2; // RID failed + } + + return 0; // OK +} + + +static int topaz_rall(uint8_t *uid, uint8_t *response) +{ + uint8_t rall_cmd[] = {TOPAZ_RALL, 0, 0, 0, 0, 0, 0, 0, 0}; + + memcpy(&rall_cmd[3], uid, 4); + if (!topaz_send_cmd(rall_cmd, sizeof(rall_cmd), response)) { + topaz_switch_off_field(); + return -1; // RALL failed + } + + return 0; +} + + +static bool topaz_block_is_locked(uint8_t blockno, uint8_t *lockbits) +{ + if(lockbits[blockno/8] >> (blockno % 8) & 0x01) { + return true; + } else { + return false; + } +} + + +static int topaz_print_CC(uint8_t *data) +{ + if(data[0] != 0xe1) { + return -1; // no NDEF message + } + + PrintAndLog("Capability Container: %02x %02x %02x %02x", data[0], data[1], data[2], data[3]); + PrintAndLog(" %02x: NDEF Magic Number", data[0]); + PrintAndLog(" %02x: version %d.%d supported by tag", data[1], (data[1] & 0xF0) >> 4, data[1] & 0x0f); + PrintAndLog(" %02x: Physical Memory Size of this tag: %d bytes", data[2], (data[2] + 1) * 8); + PrintAndLog(" %02x: %s / %s", data[3], + (data[3] & 0xF0) ? "(RFU)" : "Read access granted without any security", + (data[3] & 0x0F)==0 ? "Write access granted without any security" : (data[3] & 0x0F)==0x0F ? "No write access granted at all" : "(RFU)"); + return 0; +} + + +static void get_TLV(uint8_t **TLV_ptr, uint8_t *tag, uint16_t *length, uint8_t **value) +{ + *length = 0; + *value = NULL; + + *tag = **TLV_ptr; + *TLV_ptr += 1; + switch (*tag) { + case 0x00: // NULL TLV. + case 0xFE: // Terminator TLV. + break; + case 0x01: // Lock Control TLV + case 0x02: // Reserved Memory TLV + case 0x03: // NDEF message TLV + case 0xFD: // proprietary TLV + *length = **TLV_ptr; + *TLV_ptr += 1; + if (*length == 0xff) { + *length = **TLV_ptr << 8; + *TLV_ptr += 1; + *length |= **TLV_ptr; + *TLV_ptr += 1; + } + *value = *TLV_ptr; + *TLV_ptr += *length; + break; + default: // RFU + break; + } +} + + +static bool topaz_print_lock_control_TLVs(uint8_t *memory) +{ + uint8_t *TLV_ptr = memory; + uint8_t tag = 0; + uint16_t length; + uint8_t *value; + bool lock_TLV_present = false; + + while(*TLV_ptr != 0x03 && *TLV_ptr != 0xFD && *TLV_ptr != 0xFE) { + // all Lock Control TLVs shall be present before the NDEF message TLV, the proprietary TLV (and the Terminator TLV) + get_TLV(&TLV_ptr, &tag, &length, &value); + if (tag == 0x01) { // the Lock Control TLV + uint8_t pages_addr = value[0] >> 4; + uint8_t byte_offset = value[0] & 0x0f; + uint8_t size_in_bits = value[1] ? value[1] : 256; + uint8_t bytes_per_page = 1 << (value[2] & 0x0f); + uint8_t bytes_locked_per_bit = 1 << (value[2] >> 4); + PrintAndLog("Lock Area of %d bits at byte offset 0x%02x. Each Lock Bit locks %d bytes.", + size_in_bits, + pages_addr * bytes_per_page + byte_offset, + bytes_locked_per_bit); + lock_TLV_present = true; + } + } + + if (!lock_TLV_present) { + PrintAndLog("(No Lock Control TLV present)"); + return -1; + } else { + return 0; + } +} + + +static int topaz_print_reserved_memory_control_TLVs(uint8_t *memory) +{ + uint8_t *TLV_ptr = memory; + uint8_t tag = 0; + uint16_t length; + uint8_t *value; + bool reserved_memory_control_TLV_present = false; + + while(*TLV_ptr != 0x03 && *TLV_ptr != 0xFD && *TLV_ptr != 0xFE) { + // all Reserved Memory Control TLVs shall be present before the NDEF message TLV, the proprietary TLV (and the Terminator TLV) + get_TLV(&TLV_ptr, &tag, &length, &value); + if (tag == 0x02) { // the Reserved Memory Control TLV + uint8_t pages_addr = value[0] >> 4; + uint8_t byte_offset = value[0] & 0x0f; + uint8_t size_in_bytes = value[1] ? value[1] : 256; + uint8_t bytes_per_page = 1 << (value[2] & 0x0f); + PrintAndLog("Reserved Memory of %d bytes at byte offset 0x%02x.", + size_in_bytes, + pages_addr * bytes_per_page + byte_offset); + reserved_memory_control_TLV_present = true; + } + } + + if (!reserved_memory_control_TLV_present) { + PrintAndLog("(No Reserved Memory Control TLV present)"); + return -1; + } else { + return 0; + } +} + + +static void topaz_print_lifecycle_state(uint8_t *data) +{ + +} + + +static void topaz_print_NDEF(uint8_t *data) +{ + +} + + +int CmdHFTopazReader(const char *Cmd) +{ + int status; + uint8_t atqa[2]; + uint8_t rid_response[8]; + uint8_t *uid_echo = &rid_response[2]; + uint8_t rall_response[124]; + + status = topaz_select(atqa, rid_response); + + if (status == -1) { + PrintAndLog("Error: couldn't receive ATQA"); + return -1; + } + + PrintAndLog("ATQA : %02x %02x", atqa[1], atqa[0]); + if (atqa[1] != 0x0c && atqa[0] != 0x00) { + PrintAndLog("Tag doesn't support the Topaz protocol."); + topaz_switch_off_field(); + return -1; + } + + if (status == -2) { + PrintAndLog("Error: tag didn't answer to RID"); + topaz_switch_off_field(); + return -1; + } + + topaz_tag.HR01[0] = rid_response[0]; + topaz_tag.HR01[1] = rid_response[1]; + + // ToDo: CRC check + PrintAndLog("HR0 : %02x (%sa Topaz tag (%scapable of carrying a NDEF message), %s memory map)", rid_response[0], + (rid_response[0] & 0xF0) == 0x10 ? "" : "not ", + (rid_response[0] & 0xF0) == 0x10 ? "" : "not ", + (rid_response[0] & 0x0F) == 0x10 ? "static" : "dynamic"); + PrintAndLog("HR1 : %02x", rid_response[1]); + + status = topaz_rall(uid_echo, rall_response); + + if(status == -1) { + PrintAndLog("Error: tag didn't answer to RALL"); + topaz_switch_off_field(); + return -1; + } + + memcpy(topaz_tag.uid, rall_response+2, 7); + PrintAndLog("UID : %02x %02x %02x %02x %02x %02x %02x", + topaz_tag.uid[6], + topaz_tag.uid[5], + topaz_tag.uid[4], + topaz_tag.uid[3], + topaz_tag.uid[2], + topaz_tag.uid[1], + topaz_tag.uid[0]); + PrintAndLog(" UID[6] (Manufacturer Byte) = %02x, Manufacturer: %s", + topaz_tag.uid[6], + getTagInfo(topaz_tag.uid[6])); + + memcpy(topaz_tag.data_blocks, rall_response+2, 0x10*8); + PrintAndLog(""); + PrintAndLog("Static Data blocks 00 to 0c:"); + PrintAndLog("block# | offset | Data | Locked?"); + char line[80]; + for (uint16_t i = 0; i <= 0x0c; i++) { + for (uint16_t j = 0; j < 8; j++) { + sprintf(&line[3*j], "%02x ", topaz_tag.data_blocks[i][j] /*rall_response[2 + 8*i + j]*/); + } + PrintAndLog(" 0x%02x | 0x%02x | %s| %-3s", i, i*8, line, topaz_block_is_locked(i, &topaz_tag.data_blocks[0x0d][0]) ? "yes" : "no"); + } + + PrintAndLog(""); + PrintAndLog("Static Reserved block 0d:"); + for (uint16_t j = 0; j < 8; j++) { + sprintf(&line[3*j], "%02x ", topaz_tag.data_blocks[0x0d][j]); + } + PrintAndLog(" 0x%02x | 0x%02x | %s| %-3s", 0x0d, 0x0d*8, line, "n/a"); + + PrintAndLog(""); + PrintAndLog("Static Lockbits and OTP Bytes:"); + for (uint16_t j = 0; j < 8; j++) { + sprintf(&line[3*j], "%02x ", topaz_tag.data_blocks[0x0e][j]); + } + PrintAndLog(" 0x%02x | 0x%02x | %s| %-3s", 0x0e, 0x0e*8, line, "n/a"); + + PrintAndLog(""); + + status = topaz_print_CC(&topaz_tag.data_blocks[1][0]); + + if (status == -1) { + PrintAndLog("No NDEF message present"); + topaz_switch_off_field(); + return 0; + } + + PrintAndLog(""); + bool lock_TLV_present = topaz_print_lock_control_TLVs(&topaz_tag.data_blocks[1][4]); + + PrintAndLog(""); + bool reserved_mem_present = topaz_print_reserved_memory_control_TLVs(&topaz_tag.data_blocks[1][4]); + + topaz_print_lifecycle_state(&topaz_tag.data_blocks[1][0]); + + topaz_print_NDEF(&topaz_tag.data_blocks[1][0]); + + topaz_switch_off_field(); + return 0; +} + + +int CmdHFTopazSim(const char *Cmd) +{ + PrintAndLog("not yet implemented"); + return 0; +} + + +int CmdHFTopazCmdRaw(const char *Cmd) +{ + PrintAndLog("not yet implemented"); + return 0; +} + + +static int CmdHelp(const char *Cmd); + + +static command_t CommandTable[] = +{ + {"help", CmdHelp, 1, "This help"}, + {"reader", CmdHFTopazReader, 0, "Act like a Topaz reader"}, + {"sim", CmdHFTopazSim, 0, " -- Simulate Topaz tag"}, + {"snoop", CmdHF14ASnoop, 0, "Eavesdrop a Topaz reader-tag communication"}, + {"raw", CmdHFTopazCmdRaw, 0, "Send raw hex data to tag"}, + {NULL, NULL, 0, NULL} +}; + + +int CmdHFTopaz(const char *Cmd) { + // flush + WaitForResponseTimeout(CMD_ACK,NULL,100); + + // parse + CmdsParse(CommandTable, Cmd); + return 0; +} + +static int CmdHelp(const char *Cmd) +{ + CmdsHelp(CommandTable); + return 0; +} + + diff --git a/client/cmdhw.c b/client/cmdhw.c index 5ec0aa60..78695346 100644 --- a/client/cmdhw.c +++ b/client/cmdhw.c @@ -23,9 +23,11 @@ static int CmdHelp(const char *Cmd); -static void lookupChipID(uint32_t iChipID) +static void lookupChipID(uint32_t iChipID, uint32_t mem_used) { char asBuff[100]; + uint32_t mem_avail = 0; + switch(iChipID) { case 0x270B0A40: @@ -103,37 +105,43 @@ static void lookupChipID(uint32_t iChipID) switch((iChipID&0xF00)>>8) { case 0: - sprintf(asBuff,"None"); + mem_avail = 0; break; case 1: - sprintf(asBuff,"8K bytes"); + mem_avail = 8; break; case 2: - sprintf(asBuff,"16K bytes"); + mem_avail = 16; break; case 3: - sprintf(asBuff,"32K bytes"); + mem_avail = 32; break; case 5: - sprintf(asBuff,"64K bytes"); + mem_avail = 64; break; case 7: - sprintf(asBuff,"128K bytes"); + mem_avail = 128; break; case 9: - sprintf(asBuff,"256K bytes"); + mem_avail = 256; break; case 10: - sprintf(asBuff,"512K bytes"); + mem_avail = 512; break; case 12: - sprintf(asBuff,"1024K bytes"); + mem_avail = 1024; break; case 14: - sprintf(asBuff,"2048K bytes"); + mem_avail = 2048; break; } - PrintAndLog("Nonvolatile Program Memory Size: %s",asBuff); + PrintAndLog("Nonvolatile Program Memory Size: %dK bytes. Used: %d bytes (%2.0f\%). Free: %d bytes (%2.0f\%).", + mem_avail, + mem_used, + mem_avail == 0 ? 0 : (float)mem_used/(mem_avail*1024)*100, + mem_avail*1024 - mem_used, + mem_avail == 0 ? 0 : (float)(mem_avail*1024-mem_used)/(mem_avail*1024)*100 + ); switch((iChipID&0xF000)>>12) { case 0: @@ -400,7 +408,7 @@ int CmdVersion(const char *Cmd) UsbCommand resp; SendCommand(&c); if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) { - lookupChipID(resp.arg[0]); + lookupChipID(resp.arg[0], resp.arg[1]); } return 0; } diff --git a/client/fpga_compress.c b/client/fpga_compress.c new file mode 100644 index 00000000..9e0946b2 --- /dev/null +++ b/client/fpga_compress.c @@ -0,0 +1,221 @@ +//----------------------------------------------------------------------------- +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Flasher frontend tool +//----------------------------------------------------------------------------- + +#include +#include +#include +#include "sleep.h" +#include "proxmark3.h" +#include "flash.h" +#include "uart.h" +#include "usb_cmd.h" + +#define MAX(a,b) ((a)>(b)?(a):(b)) + +struct huffman_record { + int16_t symbol; + uint16_t count; + uint8_t code_size; + uint8_t code; + struct huffman_record *left; + struct huffman_record *right; + struct huffman_record *next; + }; + +typedef struct huffman_record huffman_record_t; + +#define FPGA_CONFIG_SIZE 42175 +static uint8_t fpga_config[FPGA_CONFIG_SIZE]; +static huffman_record_t leaf_nodes[256]; +static uint8_t start_code[256]; + +static void usage(char *argv0) +{ + fprintf(stderr, "Usage: %s [-d] \n\n", argv0); + fprintf(stderr, "\t-d\tdecompress\n\n"); +} + + +void add_to_heap(huffman_record_t **heap, huffman_record_t *new_record) +{ + huffman_record_t *succ = *heap; + huffman_record_t *pred = NULL; + +// fprintf(stderr, "Adding symbol %d, count %d\n", new_record->symbol, new_record->count); + + while (succ != NULL && new_record->count > succ->count) { + pred = succ; + succ = succ->next; + } + + // insert new record + new_record->next = succ; + if (pred == NULL) { // first record in heap + *heap = new_record; + } else { + pred->next = new_record; + } +} + + +uint16_t set_codesize(huffman_record_t *tree_ptr, uint8_t depth) +{ + uint16_t max_size = depth; + tree_ptr->code_size = depth; + if (tree_ptr->left != NULL) { + max_size = MAX(set_codesize(tree_ptr->left, depth+1), max_size); + } + if (tree_ptr->right != NULL) { + max_size = MAX(set_codesize(tree_ptr->right, depth+1), max_size); + } + return max_size; +} + +int huffman_encode(FILE *infile, FILE *outfile) +{ + int i; + + // init leaf_nodes: + for (i = 0; i < 256; i++) { + leaf_nodes[i].count = 0; + leaf_nodes[i].symbol = i; + leaf_nodes[i].left = NULL; + leaf_nodes[i].right = NULL; + leaf_nodes[i].next = NULL; + } + + // read the input file into fpga_config[] and count occurrences of each symbol: + i = 0; + while(!feof(infile)) { + uint8_t c; + c = fgetc(infile); + fpga_config[i++] = c; + leaf_nodes[c].count++; + if (i > FPGA_CONFIG_SIZE+1) { + fprintf(stderr, "Input file too big (> %d bytes). This is probably not a PM3 FPGA config file.", FPGA_CONFIG_SIZE); + fclose(infile); + fclose(outfile); + return -1; + } + } + + fprintf(stderr, "\nStatistics: (symbol: count)\n"); + for (i = 0; i < 256; i++) { + fprintf(stderr, "%3d: %5d\n", i, leaf_nodes[i].count); + } + + // build the Huffman tree: + huffman_record_t *heap_ptr = NULL; + + for (i = 0; i < 256; i++) { + add_to_heap(&heap_ptr, &leaf_nodes[i]); + } + + fprintf(stderr, "\nSorted statistics: (symbol: count)\n"); + for (huffman_record_t *p = heap_ptr; p != NULL; p = p->next) { + fprintf(stderr, "%3d: %5d\n", p->symbol, p->count); + } + + for (i = 0; i < 255; i++) { + // remove and combine the first two nodes + huffman_record_t *p1, *p2; + p1 = heap_ptr; + p2 = heap_ptr->next; + heap_ptr = p2->next; + huffman_record_t *new_node = malloc(sizeof(huffman_record_t)); + new_node->left = p1; + new_node->right = p2; + new_node->count = p1->count + p2->count; + add_to_heap(&heap_ptr, new_node); + } + + uint16_t max_codesize = set_codesize(heap_ptr, 0); + + fprintf(stderr, "\nStatistics: (symbol: count, codesize)\n"); + uint32_t compressed_size = 0; + for (i = 0; i < 256; i++) { + fprintf(stderr, "%3d: %5d, %d\n", leaf_nodes[i].symbol, leaf_nodes[i].count, leaf_nodes[i].code_size); + compressed_size += leaf_nodes[i].count * leaf_nodes[i].code_size; + } + fprintf(stderr, "Compressed size = %ld (%f% of original size)", (compressed_size+7)/8, (float)(compressed_size)/(FPGA_CONFIG_SIZE * 8) * 100); + fprintf(stderr, "Max Codesize = %d bits", max_codesize); + + uint8_t code = 0; + for (i = max_codesize; i > 0; i--) { + code = (code + 1) >> 1; + start_code[i] = code; + for (uint16_t j = 0; j < 256; j++) { + if (leaf_nodes[j].code_size == i) { + leaf_nodes[j].code = code; + code++; + } + } + } + + + fprintf(stderr, "\nStatistics: (symbol: count, codesize, code)\n"); + for (i = 0; i < 256; i++) { + fprintf(stderr, "%3d: %5d, %d, %02x\n", leaf_nodes[i].symbol, leaf_nodes[i].count, leaf_nodes[i].code_size, leaf_nodes[i].code); + } + + fclose(infile); + fclose(outfile); + + return 0; +} + +int huffman_decode(FILE *infile, FILE *outfile) +{ + return 0; +} + + +int main(int argc, char **argv) +{ + bool decode = false; + char *infilename; + char *outfilename; + + if (argc < 3) { + usage(argv[0]); + return -1; + } + + if (argc > 3) { + if (!strcmp(argv[1], "-d")) { + decode = true; + infilename = argv[2]; + outfilename = argv[3]; + } else { + usage(argv[0]); + return -1; + } + } else { + infilename = argv[1]; + outfilename = argv[2]; + } + + FILE *infile = fopen(infilename, "rb"); + if (infile == NULL) { + fprintf(stderr, "Error. Cannot open input file %s", infilename); + return -1; + } + + FILE *outfile = fopen(outfilename, "wb"); + if (outfile == NULL) { + fprintf(stderr, "Error. Cannot open output file %s", outfilename); + fclose(infile); + return -1; + } + + if (decode) { + return huffman_decode(infile, outfile); + } else { + return huffman_encode(infile, outfile); + } +} -- 2.39.5