From add4d470469b74bb2495431a7963e39eb80d17ab Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Wed, 15 Apr 2015 19:16:00 +0200 Subject: [PATCH] add: compress fpga images during compile, uncompress at run time --- .gitignore | 1 + Makefile | 1 - armsrc/Makefile | 20 ++- armsrc/adler32.c | 179 ++++++++++++++++++++++ armsrc/apps.h | 55 +------ armsrc/fpga_hf.bit.gz | Bin 19160 -> 0 bytes armsrc/fpga_lf.bit.gz | Bin 18299 -> 0 bytes armsrc/fpgaloader.c | 186 +++++++++++++--------- armsrc/fpgaloader.h | 64 ++++++++ armsrc/inffast.c | 340 +++++++++++++++++++++++++++++++++++++++++ armsrc/inftrees.c | 302 ++++++++++++++++++++++++++++++++++++ armsrc/zutil.c | 324 +++++++++++++++++++++++++++++++++++++++ common/Makefile.common | 1 + 13 files changed, 1343 insertions(+), 130 deletions(-) create mode 100644 armsrc/adler32.c delete mode 100644 armsrc/fpga_hf.bit.gz delete mode 100644 armsrc/fpga_lf.bit.gz create mode 100644 armsrc/fpgaloader.h create mode 100644 armsrc/inffast.c create mode 100644 armsrc/inftrees.c create mode 100644 armsrc/zutil.c diff --git a/.gitignore b/.gitignore index 07669e14..51dcefc5 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ *.bin *.dll *.moc.cpp +*.gz *.exe proxmark proxmark3 diff --git a/Makefile b/Makefile index b558da2d..dfcbaecf 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,5 @@ include common/Makefile.common -GZIP=gzip FLASH_PORT=/dev/ttyACM0 all clean: %: bootrom/% armsrc/% client/% recovery/% diff --git a/armsrc/Makefile b/armsrc/Makefile index 3fd93ac3..c7d85f1a 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -10,7 +10,7 @@ APP_INCLUDES = apps.h #remove one of the following defines and comment out the relevant line #in the next section to remove that particular feature from compilation -APP_CFLAGS = -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DWITH_ICLASS -DWITH_LEGICRF -DWITH_HITAG -DWITH_CRC -DON_DEVICE -fno-strict-aliasing -ffunction-sections -fdata-sections +APP_CFLAGS = -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DWITH_ICLASS -DWITH_LEGICRF -DWITH_HITAG -DWITH_CRC -DON_DEVICE -DZ_SOLO -fno-strict-aliasing -ffunction-sections -fdata-sections #-DWITH_LCD #SRC_LCD = fonts.c LCD.c @@ -31,7 +31,11 @@ THUMBSRC = start.c \ string.c \ usb_cdc.c \ cmd.c \ - inflate.c + inflate.c \ + zutil.c \ + adler32.c \ + inftrees.c \ + inffast.c # These are to be compiled in ARM mode ARMSRC = fpgaloader.c \ @@ -57,11 +61,14 @@ OBJS = $(OBJDIR)/osimage.s19 all: $(OBJS) -$(OBJDIR)/fpga_lf.o: fpga_lf.bit - $(OBJCOPY) -O elf32-littlearm -I binary -B arm --redefine-sym _binary____fpga_fpga_lf_bit_start=_binary_fpga_lf_bit_start --redefine-sym _binary____fpga_fpga_lf_bit_end=_binary_fpga_lf_bit_end --prefix-sections=fpga_lf_bit $^ $@ +$(OBJDIR)/fpga_lf.o: $(OBJDIR)/fpga_lf.bit.gz + $(OBJCOPY) -O elf32-littlearm -I binary -B arm --redefine-sym _binary_obj_fpga_lf_bit_gz_start=_binary_fpga_lf_bit_start --redefine-sym _binary_obj_fpga_lf_bit_gz_end=_binary_fpga_lf_bit_end --prefix-sections=fpga_lf_bit $^ $@ -$(OBJDIR)/fpga_hf.o: fpga_hf.bit - $(OBJCOPY) -O elf32-littlearm -I binary -B arm --redefine-sym _binary____fpga_fpga_hf_bit_start=_binary_fpga_hf_bit_start --redefine-sym _binary____fpga_fpga_hf_bit_end=_binary_fpga_hf_bit_end --prefix-sections=fpga_hf_bit $^ $@ +$(OBJDIR)/fpga_hf.o: $(OBJDIR)/fpga_hf.bit.gz + $(OBJCOPY) -O elf32-littlearm -I binary -B arm --redefine-sym _binary_obj_fpga_hf_bit_gz_start=_binary_fpga_hf_bit_start --redefine-sym _binary_obj_fpga_hf_bit_gz_end=_binary_fpga_hf_bit_end --prefix-sections=fpga_hf_bit $^ $@ + +$(OBJDIR)/%.bit.gz: %.bit + $(GZIP) --best -c $^ >$@ $(OBJDIR)/fullimage.elf: $(VERSIONOBJ) $(OBJDIR)/fpga_lf.o $(OBJDIR)/fpga_hf.o $(THUMBOBJ) $(ARMOBJ) $(CC) $(LDFLAGS) -Wl,-T,ldscript,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^ $(LIBS) @@ -82,6 +89,7 @@ clean: $(DELETE) $(OBJDIR)$(PATHSEP)*.s19 $(DELETE) $(OBJDIR)$(PATHSEP)*.map $(DELETE) $(OBJDIR)$(PATHSEP)*.d + $(DELETE) $(OBJDIR)$(PATHSEP)*.gz $(DELETE) version.c .PHONY: all clean help diff --git a/armsrc/adler32.c b/armsrc/adler32.c new file mode 100644 index 00000000..a868f073 --- /dev/null +++ b/armsrc/adler32.c @@ -0,0 +1,179 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2011 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" + +#define local static + +local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2)); + +#define BASE 65521 /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +/* use NO_DIVIDE if your processor does not do division in hardware -- + try it both ways to see which is faster */ +#ifdef NO_DIVIDE +/* note that this assumes BASE is 65521, where 65536 % 65521 == 15 + (thank you to John Reiser for pointing this out) */ +# define CHOP(a) \ + do { \ + unsigned long tmp = a >> 16; \ + a &= 0xffffUL; \ + a += (tmp << 4) - tmp; \ + } while (0) +# define MOD28(a) \ + do { \ + CHOP(a); \ + if (a >= BASE) a -= BASE; \ + } while (0) +# define MOD(a) \ + do { \ + CHOP(a); \ + MOD28(a); \ + } while (0) +# define MOD63(a) \ + do { /* this assumes a is not negative */ \ + z_off64_t tmp = a >> 32; \ + a &= 0xffffffffL; \ + a += (tmp << 8) - (tmp << 5) + tmp; \ + tmp = a >> 16; \ + a &= 0xffffL; \ + a += (tmp << 4) - tmp; \ + tmp = a >> 16; \ + a &= 0xffffL; \ + a += (tmp << 4) - tmp; \ + if (a >= BASE) a -= BASE; \ + } while (0) +#else +# define MOD(a) a %= BASE +# define MOD28(a) a %= BASE +# define MOD63(a) a %= BASE +#endif + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + unsigned long sum2; + unsigned n; + + /* split Adler-32 into component sums */ + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + + /* in case user likes doing a byte at a time, keep it fast */ + if (len == 1) { + adler += buf[0]; + if (adler >= BASE) + adler -= BASE; + sum2 += adler; + if (sum2 >= BASE) + sum2 -= BASE; + return adler | (sum2 << 16); + } + + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (buf == Z_NULL) + return 1L; + + /* in case short lengths are provided, keep it somewhat fast */ + if (len < 16) { + while (len--) { + adler += *buf++; + sum2 += adler; + } + if (adler >= BASE) + adler -= BASE; + MOD28(sum2); /* only added so many BASE's */ + return adler | (sum2 << 16); + } + + /* do length NMAX blocks -- requires just one modulo operation */ + while (len >= NMAX) { + len -= NMAX; + n = NMAX / 16; /* NMAX is divisible by 16 */ + do { + DO16(buf); /* 16 sums unrolled */ + buf += 16; + } while (--n); + MOD(adler); + MOD(sum2); + } + + /* do remaining bytes (less than NMAX, still just one modulo) */ + if (len) { /* avoid modulos if none remaining */ + while (len >= 16) { + len -= 16; + DO16(buf); + buf += 16; + } + while (len--) { + adler += *buf++; + sum2 += adler; + } + MOD(adler); + MOD(sum2); + } + + /* return recombined sums */ + return adler | (sum2 << 16); +} + +/* ========================================================================= */ +local uLong adler32_combine_(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off64_t len2; +{ + unsigned long sum1; + unsigned long sum2; + unsigned rem; + + /* for negative len, return invalid adler32 as a clue for debugging */ + if (len2 < 0) + return 0xffffffffUL; + + /* the derivation of this formula is left as an exercise for the reader */ + MOD63(len2); /* assumes len2 >= 0 */ + rem = (unsigned)len2; + sum1 = adler1 & 0xffff; + sum2 = rem * sum1; + MOD(sum2); + sum1 += (adler2 & 0xffff) + BASE - 1; + sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; + if (sum1 >= BASE) sum1 -= BASE; + if (sum1 >= BASE) sum1 -= BASE; + if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1); + if (sum2 >= BASE) sum2 -= BASE; + return sum1 | (sum2 << 16); +} + +/* ========================================================================= */ +uLong ZEXPORT adler32_combine(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off_t len2; +{ + return adler32_combine_(adler1, adler2, len2); +} + +uLong ZEXPORT adler32_combine64(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off64_t len2; +{ + return adler32_combine_(adler1, adler2, len2); +} diff --git a/armsrc/apps.h b/armsrc/apps.h index fa081d21..98be05a3 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -19,6 +19,7 @@ #include "mifare.h" #include "../common/crc32.h" #include "BigBuf.h" +#include "fpgaloader.h" extern const uint8_t OddByteParity[256]; extern int rsamples; // = 0; @@ -50,60 +51,6 @@ void ListenReaderField(int limit); extern int ToSendMax; extern uint8_t ToSend[]; -/// fpga.h -void FpgaSendCommand(uint16_t cmd, uint16_t v); -void FpgaWriteConfWord(uint8_t v); -void FpgaDownloadAndGo(int bitstream_version); -int FpgaGatherBitstreamVersion(); -void FpgaGatherVersion(int bitstream_version, char *dst, int len); -void FpgaSetupSsc(void); -void SetupSpi(int mode); -bool FpgaSetupSscDma(uint8_t *buf, int len); -#define FpgaDisableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS; -#define FpgaEnableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN; -void SetAdcMuxFor(uint32_t whichGpio); - -// Definitions for the FPGA commands. -#define FPGA_CMD_SET_CONFREG (1<<12) -#define FPGA_CMD_SET_DIVISOR (2<<12) -#define FPGA_CMD_SET_USER_BYTE1 (3<<12) -// Definitions for the FPGA configuration word. -// LF -#define FPGA_MAJOR_MODE_LF_ADC (0<<5) -#define FPGA_MAJOR_MODE_LF_EDGE_DETECT (1<<5) -#define FPGA_MAJOR_MODE_LF_PASSTHRU (2<<5) -// HF -#define FPGA_MAJOR_MODE_HF_READER_TX (0<<5) -#define FPGA_MAJOR_MODE_HF_READER_RX_XCORR (1<<5) -#define FPGA_MAJOR_MODE_HF_SIMULATOR (2<<5) -#define FPGA_MAJOR_MODE_HF_ISO14443A (3<<5) -// BOTH -#define FPGA_MAJOR_MODE_OFF (7<<5) -// Options for LF_ADC -#define FPGA_LF_ADC_READER_FIELD (1<<0) -// Options for LF_EDGE_DETECT -#define FPGA_CMD_SET_EDGE_DETECT_THRESHOLD FPGA_CMD_SET_USER_BYTE1 -#define FPGA_LF_EDGE_DETECT_READER_FIELD (1<<0) -#define FPGA_LF_EDGE_DETECT_TOGGLE_MODE (1<<1) -// Options for the HF reader, tx to tag -#define FPGA_HF_READER_TX_SHALLOW_MOD (1<<0) -// Options for the HF reader, correlating against rx from tag -#define FPGA_HF_READER_RX_XCORR_848_KHZ (1<<0) -#define FPGA_HF_READER_RX_XCORR_SNOOP (1<<1) -#define FPGA_HF_READER_RX_XCORR_QUARTER_FREQ (1<<2) -// Options for the HF simulated tag, how to modulate -#define FPGA_HF_SIMULATOR_NO_MODULATION (0<<0) -#define FPGA_HF_SIMULATOR_MODULATE_BPSK (1<<0) -#define FPGA_HF_SIMULATOR_MODULATE_212K (2<<0) -#define FPGA_HF_SIMULATOR_MODULATE_424K (4<<0) -#define FPGA_HF_SIMULATOR_MODULATE_424K_8BIT 0x5//101 - -// Options for ISO14443A -#define FPGA_HF_ISO14443A_SNIFFER (0<<0) -#define FPGA_HF_ISO14443A_TAGSIM_LISTEN (1<<0) -#define FPGA_HF_ISO14443A_TAGSIM_MOD (2<<0) -#define FPGA_HF_ISO14443A_READER_LISTEN (3<<0) -#define FPGA_HF_ISO14443A_READER_MOD (4<<0) /// lfops.h extern uint8_t decimation; diff --git a/armsrc/fpga_hf.bit.gz b/armsrc/fpga_hf.bit.gz deleted file mode 100644 index 0cbb214d2cd73816870d583a0890aa3f64142f8d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19160 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 diff --git a/armsrc/fpga_lf.bit.gz b/armsrc/fpga_lf.bit.gz deleted file mode 100644 index d736beed49b3f8d06886758910df578f539042f7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18299 zcmWh!1w)iw6IGG!Zg@dO5$Tp#X(c3-j+O52+Li9^2BoByMsjHoq`{@TyIGcvkM9TE z`^+@)PDq$KQaWjix_e0}|v1ap$cR7}Of9SyyJ|-Nkc7GK0#2T4j%XuNK z7*xGJZvGJhJB*49zG7Q?X7N)@73X#Aj927OF)?zwA&TMJz2!p$j3R46)c0Y`zd(3R zRGO2z#Q$j3AGGH^ezqDMJ^UL5elmT+x0fJ+nK{9@Ua|6?E(bg?gFURb3YJ}82aw3B zffsY(&feT=FV{&Xvnf=ZjgoCllJ!WuWfe9{)5f@TIMRDqpB^7{1OwL4gJl@8r$*1d z>*I5(VYDfe*`7KZ=01r*i&BAsNl*GP(30nwiNWC#g$5Com^VhqviCO=YkiFq2LGFg9{hUUJ~{f+qonZVe*S7bx!4m|6%{^MWFVT(ULG66d3zhAuE1^%<^}j6 z?@%hs^g;ZSFwxluLbSW@^Df?4eN!=76=YvWC^A~g^)G40?a`^9P;4_>hrozD^fo=M ztDvu8(}gK}dIRK39(k9Ni^7w{kKwLP$@7X;`o=YzW%s(Wd948(Z0vBA4RhGC5@Bt= zY+E^`36J?CS!RXEbh2LQYyDCuU%tq4SJ&#l!QOcJ@iU7%5w%G;qAEK@cM;5mkDd8l zC(>oXdB4|ZAfK@Ugu_uZ7c2RWHV$`+E;0M>M;(^0{p`CVdFNC@*^8gO21V+RiI#9Q zg%%0_JN?CN?*hhN`#z|BR6l2(>Zm+>JX%kCT&F>eeJis(>mg#nIG4q?A5Cw6F;eLA zViI^@f5@3hnnc9Vr%@*sD}kY?e`Q>L@qSW^upk~Nu+GafXU;J8;EQ->r*HO8z*+*CuG|ZEIDARTm3t_ zXya1Oy{lHM=q!2X&66q@wwf1&=O@NW)i&NSHo$a=tbXHmSvPV_iCIA)nfW;)rTFF} z4*8UI+vc~3Xik0~28PyjbMtue8C@q;7e`VFs|1C=`oK2PpV#ND>!HYk)?z8vjEYK3NB4Haw0h5Eaq}Z0@n-UP5e{C^o__dAG7VfAcbOYWO z=f*{E&0e-0vx^5vB*Ylu_;=j49jSDUiD<#|TY7oEpu8P4rxJqNaZUz-OMgCpV)C+_ zRonRnfi$*s8NC*KzEWDJFqdVQ@UYrCAY#4qduu5CLwIP^9TkQq;y~Ix_8%?xU~p&G z%fO2MmfVz#KKv$eW|p)fx#gJ>hueEO{5TLzpYQLSq1$kx8Iusp0ss1ZQck)Atw#OloqYP~&xyVP}Bjhqyl>!0dk-*_7* z7LG;-AUwwpPxa(^55bevZLdue!VcDTApttHs6z-QOJ*>>Blm3&#Pk^U>UY%OW{iiW z0}gUiXj+pgiu3XwLKlceZsC#?jgNUhz?3H>Le@|Wh2Xf^<9kn%s zB*iZYnvxT4W<(vKTF2X-R(IRE22R-#Xv>j7lV^9AZ{}wWq0bEkV`dgTkXm(T6YJMA zx9KyIv9vDh6^^Q|7e{qYy^tMAt^L*B1ev2%yp0U{ZpcFbd>~qp6SNaHK~+2VB!#}C z{>%8h``-abgrIe5S#fzQ&nQ{7m~l^&ATuPgY5Xxe|E1-)8U;_9BK^_TP)T*~35 zz#t83)jnP!zIU^ubz=^K#-@*sNyyW@|3o;G+N&|ThVy9}b&WebwEN|746ZG+Fn!PBa_lyJUtx|#$0SOFVx_6G} z3AH}8ZUGFSINA#pMp1*<>SGL()=X6-FgyZi>XRC4d3-0IX!LaE{OD}^H=2n)#Q}e? zvO3Jgglhm2G7s@K(%_pC6T|{F6}mP&!QN8FHOWe>CXxCM9Ig1HsTA`e{RL?jrx<)^ z5NYx55*tIham-!Aiwmu2kuZP%gLbNjj#aiK2I#s&AgOlJBO6&pg%B4o^ifpF|mNA!)Z2ziVgtLh#woHu=#ABXg;+{5#y-PYi3pPaqvTTR_D` zu;qqHtS9}_Exc&Vy*UywD4_WY-~TkUjV2#~p!m?o=Yh*y@7 zVyT%h@e)qEWF?QftF=6TGMlqlUI6wSFr(_Bkugo3TYp%vtWohra;Z5GZc2kp`3RYB zNRGCo(ZbYRW<6gN&}r=!z()hH={6j#EdOl*xzEk{gBt>ngw}Zl;IU8U%Um^ZxGt^8 zjrWPjP&qLAx-hPl1tTlMunqJM4lF@nlS1Ro1fx&%Z56xXU3)8kT<~CIk=etD`wX4} z&DUT`P!j>jE>~G}iaG+EHYW?Vib??InbK}FwY@QRz1O86vAE!FuR|zJ{n4me&Ge@^Iz;U{U`CU9T!- z#{}2MxCD#tbp*`Pc*Fv`T3TzdP#qya2~)1hhNUaPr&X7VAUZrfL1%Gz6Q$ROJjj@L z-BR(8DO=Nm+qpd*;&)G&v+t}4kYn5b&O{H^8_tYeBpmX;dsxg(0gzH9LZsh7ch+Ha z?b~M=%MA#_gFmy+4l`nal=FExKJ!=H1r9;L!!e~vUjq`%VyF|}p!O1LO=DxYs`xdD z0&b#3E1WvSIu?6esy7REl#tyU(*`fmDxc7e~d!prz83NyfQ(T z&7dj4!rNmOtUhMhHTv+MNa@MMZ{$&x9x$?2PDGoij%7YBh+Rbba2@9LyP))o<8fkp!T#k$f>1IG1Hp;HcF*ru9>xV_ToxhJU3xVM9q*pYfS*l8`a-?06Xl}|4q z#8%QPPvE;VlX(JzUpwCubJe?!45wd0wyPmBqM`(cinvtIkVm=GW=?vGQmF^w$Zt$K zq&@d-yxGu#%Ex;+N;EW@9hRa7b@KRkHJ^9q`kYG%g*;*pz~4JOeK_T01LcO^cTRnH&fg#&+Dl-*I(+ zrgNxmEJS*t-2Zk5sJ$;Jr{oRkXm|?*yu5VKP6b@UVT*%?O%dJ&Q!N+!#&*ppq5%6n zH(4$q`dnWxIB^#A^zC1TlcIO+ALbpyk?=IivxsSFEPMPmKSE7zoxiycy+r3g(quZ-YR zC9Do!ZlE^(Fzan^!FMYKLW&aNIU~={WOc=)(9gZFV-d>4k}-nq*lFp1AHrjRxa7Zn zo%u|N7=#Q<#RW#ooDB^?L^tLM2^hh9g17{W-<Qz^R8>O#tPfpw2;beISgFfd{1B*Dlqv3|djV9~zVh z&}Zu?c@V(xEADE8PbXNlBDK>}*7hP6#&+YeF7>Y*ZKPVaKaoPm`z%+}8?H1v?p5cc zhVeh2BfR_0{NZ6oD!^r#6MohR#+FL&I$vhMcLaG;N-I3AM1<7t*I(PMPod3CTRXtN zrd!q9D=eV65BXb&=)Td~XEYxa@*N{@3JmyGbI#9?`1Sag@dDSPO>{VGotZMARVMY> zYd*(6B7oT4!vSOwwj;l7n&WgdYYv=^cv{h$Qs@Tz?)i+DP+4n@AV^GDtNIR)S2GxSj8-Eo%3E&06Aci*tB{%RP;cp zFkL5x^DUSHDsVM@m5=SRQ?$%={Z=AUXB$YfsS6mFs}^M_v9z@Dr|+7|S7gO7@GzF1 z<3F%G8~&2d-LlI+g5|Q!DUA+`FEk!Ki+A=5H|aeU#u>;eZC=^}np2Hil6xPfMNOqy zdj}|tAAB;9@03QDbWM;|bJ)g{e;^$#8x7;%*q}vdHwaUMWI>F-u1Bb(C#^Qq^vlqm z(eRAb%$TQKml=V(lJ%*o65kbBvX7)sOKFASx1=U`+#E z@F(@>zPF%>nx}h^Q&@*7?q2dzk5_WbZIoO_`f|2D<11wj@=i@xwfuxSqIo6o9mJ9+ z_ja0dZ;X@K|NZ&~jL%HHm*8&n$8m{LMOzZ*lA03uKaRFEbs$2f6pH6y&>3oNKAZl8q zb=5Dsd_%dLgj=^w?^T)NB-j^DpI~|qU@u@jp{=>+qj8_&eee7FPHyy1RNsVer1Y4F z>*8I(pkK{>R+MSNv8+N$C`QMycD#e(VGj0^A>jtjzYg|oe?{8xfHcuAzl?9&dY#{e zif+szgrTo!7q*8W_y(N#M3%1|dEEc~DQ$z_Fmw!){)hZief(VdwKNBBL`HeO+eiZN zPG+Ut&)S2_#uZcMznDzooygLY56PowYM zGh<0FWyf!wI?XTgC*MjT{hq{=zUEo?g9N{r{Q3d+lANx_F;=ln68YXff?j+?|6m?6 z&Slsbu zCn?~*PidWI-p;mcqjd>gV!?dakKXAaPqFN+Bx_Ds77`sUyz1oq~^# zE*t}D3URI(A(u3iod`c4+z0A$7;Es^R(IOX=p!8U)8YFnqkiW_(`Tq>2U8VXpWC-f zDUgym{9J&V_uJ9i#Qw0YkI|3Uu_6XaF`MwYKH<3kK$(BqQXPm&YB%r6@SbdO#x6)q33 z&D%u=jB=GAh;Jioi~yz87FT)Md8E+ElyZa2tlgitl1Pc4jMM&&i%&4hO;$~3HE7;l z1xxX%ngp}drDe(m!x1QZh#QMnba9HYD9n{O{hXH(>Tn0b3P?B+eL<=WLWeOyMY-S# z=E|etP9My@%S7V917y(5K+<*-6i%`*x1mWd^lJ|^6>d-+o+gvQMqv61sq)*>$mZ=1 z>D(8uBI`DgIo>J7Cgq9o4vHaZ==O>?31S#nhNxhFKR*IY-c8gz9pbH9B@Wcnf5y*J z(Fdg-aEa3Py_XxI(J3Ztj*R@}XG255Ka!gMa0r~=Aqj1^d{#f_(D<~gNM2$#&k0p& zMcRxD%ZMKhirnzp4mo~vtRCShuG7z~3$4pu|E*9g_r>QG^B?=6<5u#S);tlWRLX#U zn{d8i&6VIZ2dRS6wfVlc>mZr-ZEhF9?9JdUyGRfOJs^zN!$cx3r&j2`KR#Gx!Ok%2 z>{1jqKSD0n)qSe?8C725^&auY5Lzcj`)Op3ub=V&9x7STIe#lXue4uhg{!p=hkEI)BuQyx3bP$OMd84lCT1xTv*v3dJphiw>V^KIZ~n}@2&86MY?8lM1foVAP6p;0qcCLY zlXO-niC6WE&VK|%NuYk31IQpBQjj%2Od{N^#F!|Y;U?xFFYTX2ycC;Zy3c& zcW5plzoWkT3BKA&I>;PUr0BLX;*QePdY z#i^?1rBe_LrM|zXKr+CZEsnR#+APOj?eDfLKeG96$lPW#zTEe<(jaBWR;zv=553r5 zq)?tcr$36P7OcUeR)!+z^Zb+J;t*(R7Wuk<%(^!PEBF~yTn?qu z|FZ8=g0Dn`F^SxR78~y$lnkn8uCufv{qL%gYOFd&A;PvZ=`s z_iqPyC}YWQW930bax;5ifIFUFeH(Cl0Rg5wC~wBLb>AgjU|m@U0He?@T0ii>@zw70 zi5a*|Jt3n|o);K{#afV_lYmmaO5Baor!s4<=aT4>+pjRML#OOIy}2Uc zlM~Rt#_4`79|Ql}T{V^>ZJRTeL5IyuL{_{_5r^+L}bR?RL=Ow2dv0aeeTt1NiJTvF*O|_O_i&d`)rJb`H8Ss5P%{@iW zOOVdm6|^he(z2tgfRhIk%x@nhopNYpR1lB&WRpLjY@`1v6) z$MxNt6C=m&T0V;q3gz?ya9(LeVwjC*Hq+0hpI@Z$b?NT=^kq<{41KY@Jqh<}VI%nW z_2OFYl%%+az=><2(k2s{SMvgiUZ~`?g31YVqenQ-HsEQbM-!l*zja|T+oH9YGk~C9 zT{C_%QcD#vl1JLhuP6rTdu5|FGSuh>Cd-ov0$zMQsGPa}j^<;o+wm18=TZNa(J*nL zg~E|8GaTP|u18|(Hy-l~#bjPxh@PA!sT;Haiufr~y?XF5hBUk1&^|-RX?;A^XycZy z;rJ$h_@kn-w>fnd8m=#Veg0l8O{5FqqoN_@$iHH!XSe&R$ktJ+Jy z7k+ouuMmByk_5EtKdsAwyAM$!@)6=PXzlWmkw=rAqChAuWl5S<%1P%pG2FtPk(Z1V z*IFCv(yj58dB-{c5I1LNbAzF&1m=Zz4TKpK=-3YH-5rzT}?z0aB3tRp??r{cFH$`1A%^R=uA#b4Im z!;ZC3rjJ^o6@?p7rcMRENa{Jn@QtAul{D_CJX*sSJhzcb3Vq3{^uXe!g!fwUmW2TT~38vH6jsoSo@8E3qLyX2F-U==xYIk1Ij4q4+6em34jOS4 z0^Zqh)dd<$hz98a13QVa3}RTJwPVimEcxbMM0#ACzgNrFY5VYHxd0%331&N!Q2Wr| zD%4Ve0oiC5s!qg`SV36g)^i~!3(MK%74JWrYWr`l*!KeWdkxC0uSQr*ALGnZKS{13 zP|UTl*v}>#J&Bi8AZnvJ<-G207G;a*tD=bje&nk5F=>pTaGJS}z}_HrekxI0Hj)HE zd-lMog-F9DM!zt%yAwS$z4K=Ga{mrSJ@*4fjjIqK52H9{9jE-}O@(O?0Z4nYJ$(i< zQ<3@chVbGF`^t~@QtNv_f4q9aKLMUb2Q%IYL$?a%b_JbL-8(?%?##L87bf?_mYHX; zDZH|H!ly{P3^4Pc57vWchL@~w1i+qKpABkh6vT@Q*Cj>v8;LWl!n}1*3QiasALzgJ z_4ZMyS?rHxg-*7gov>JeSkXfP31xW3AGdSIZn^`!?e}hj?5`F_+fLwi;9K;jkO13v`a=k4G?Dh%i2|y%(Me&sl7SZwt?e%iZcj2zlXJ~(*Zg}k&cct<=W4hzAx2-Y25WX}=L3XPMPin{Mik^xL2>6K~p3&Xh;_F8@P+(EhqSjeMi+V%ek9DWot9bC(% z%)ntPc!n`bM}~AYyn?FFcEQ01H;^~eHC|W_sBpaVU_>A7lb@wRy*lF9C$`u4(Zg?W z?rH0*ixDoKxy}uf^ZH$dy$9_;a3tS*b;IuXY&BbDAoWdzG>5Bht zyr42CX7e{Fd%gYTXtATKX@F*Y;_47o;N3_Hb~C#l>#XIR#6r`^ObIfEd`qv<%rVoG zbcauoAh1{Ln>!fu)uNyoT z(U88fbQi~1qN}s3OY_IL&q&H2J{vsKUoi-g+_^d5K1_?3UFw6}RyVaPz6CH=d@87_ z_BXv?CY=+Jw6!OE6qV!q8twVA7MZO+j{VNItLnikrh>M~Di+Bq9FK1{g=v(Wmzbr* zM*zX3L->lMf3$7n2_H-6Z0wPF&aUV7{S*dGE0;%87apU7k!;Y@b7fNK{MDpG*vuk9 zFn%OpS+t;Uvg*I>O|K}i_+4=9(D6%25YfSHJ zFSPARMEx-IIr+~|hP}}EUM-c$8q*T|f9|bMA;&GjH;_AgDBr09k{w)bTnmYPxVicg z@GHon5}(-rg&=KkC;nsgVC>di^Tf_WL;!d&Z#tK-DSrvim?91S#QBx49(!+P4rgU+ z3+OuyII~+LWTmdv2BqKdKfQjedGzo_9}U>Juz#hBUW#8V1H7b;4$Hl8vJUCSV~D68 z_8l97PRgAwqrai_kJx`td?E_RLRPYF+6sp|qdC9W$do14&O(FgLY*qv}~Xg zN|da~{Ftl9C0had{6Ap5;V?--ZS;@p>h!M~XBS7LLq(QCx!u3-nDNb_{kh~jA05ra za?j5&6xS9{G<_<5U&w&eDKt|6;9=UVMH6u=T6irGNvmS0bdGv=34E1 zk%CI86K?eRc#;~3JR$??O>$K1aSh1Mk0PDjV}_)!6)WDZJliZPguUp@@J@J36Gf2@D@0Hs+n+Ra&B{W?I-tYt?$`nMKy zRAo-o@H`>p);I%vBBf+U9LlW|`dx6hcp&5W#s@vteXYHkicx$3!GQ3{mWr+&TJ|sQpa2z$}w> zq+S?}0&>lykxuxUh-Y)URsI-vXTa3oFpBs}Mvy=+*#H;@%@clYn;so%(UCfrZy4Qh zILzdh=JD}Zl121c1*X#`8n)i|z2i-1B+2AYW{xk!vVHR|U~vn0br1B4Trny8BxFxW z?yQA*W9TXxBMzU-7GH2zF&$F8$35r4*c6S>Os}QZFwGdDZ;Y>Kg;IqSCZ<;Zbj;>#CM)AvWrprDHYu{Eg~ z^iI^*N@1=9^m(%H7ZJCf38-SBBcH%x;M3CC&C-gDB5r0-p6^4(jdT)jx9Q>Dt>Wu{ z*4#mpio2)4c)>H4%HQ-A2}2Qc5&V2Bt^rbuC% zcK$C>jh*~xEAGJaK5=88ROv5Ivcjv(_Bn$hkuRD8BgDASPzUKX7G8!a?CU|lMDVNQ zCOHJL>w6g!63XRuzOhz0sn34R{dO*oVmo8=> zuYq_W>Xl#?3MD-sp`^(J^d#BE5&)=2KYGs2KdF>Vl<_ z_$#W-U)fD8gDarYxF~00IC7=W;0Ah3@sPn?fUX^V18<&)sCak$P`eHc4*?Dp+B&~% z;VGp!A=qo=K9{puqAv&6;iLE*_AhS1)WnaRYB7WA-ww`@uL$4tr2@L0X&yr@Iu{{# z%CW=Z51x?&p%rv#tUCP})(vOiv@#zQJQZEX*XHF4YnwyCbvotC+%{qJYZl#^+}rS- zccNf8Ph%FasBz=vC4^c3{-sFQSghnMD!jAHE1i6e+(T>l<=@{tTtCVpT}d##cOf>f z@KHtUKrhtj1T@*QjQ-@A#uuT|55gIfl8nPH?&c}!w z1kPLBFZs7Pi{#A;=e$450mU;8eCda^g_wutHN5cOYUDS!-9h?AmIYa z%A6)Jk3jv43@fqmaUrJ%nb&dnN(@GvMSmy{I6bZQYOamse18eSm2FoQ9<$>Ne`&i(W6Q;PsJ1Hs z#tPhhyYbe0f&UM~Wmbq-X%h)(XPwS@WZ=q84$hf0YU%ys%7Gc?wy5L)&cu!}ZuI0F zkjf12&?U#$dJpa!6bodUIvho|b#xG|mU3n*gaoL-_bxv~*r=0=Fe{a*jD{`upUL)* zC@w~Bz*wykd$;9+;{N)OQe$h8fTGBadgwki5vv)0i;iWdsO#A@{Td34MYp=wM4D^J zJl>~%-rM{wl9nR4p z{awvl6!E(1cZ?kDQyP+@uOoq8?>&@lAFM3gZm0$|zmn%{^+A4C*;>novNvAafC(H6 z@%FYE62L13#^}UbA&Hpnx+KV`Zh>~ei*GAim%N<#z^2&H^x+PNZCm0+MsD|iy(y??E3b=z3cIT0y@qj-84+!E3czA*E%nK?^ud<03N8JvMCu=YNwg;!DEw$` z$~lw$yii<6d(sFUCUs)_45QC)v;PAaboDdZ|264!ujs-X$*lH26{-y!-WXcRp(8h# z(?xSdr^v$}rrmLe8KYWtnSWRwCY4#n$99vaFFU`07@yC8#TqEUN+i4`ugi>;1acu zym`dqLcIyQJ8dMf<*gj9DfuaRcFjNEN^Du#%I~ z#jew0S4bV-uhr~dx99d;z5kki?$9y~vjkU<^e*{-VZk7NMO~O?H-@#rSje!IGQcZC zMm)z7Ra^KK*Qm*|wQpmoTy!^)73E<4o-0xL=JP#{`#x!c#WP)+DKsxD<_EWIwlZ>b ze5oTAghgQYR~NH6v5+OYsPgLksGzotP-#v=3N2h4skHv<#End_Lj1 zdFOalBN8FkznqF83et29|K3JERWS@TVJ|*q)8%CT=*Ti_Fkg7_-*_lNUMr#x8nngH zoM>|PYV|#h_Lg9 z!UBtCDvr6n5@~U}<4`Y8$hwgfI^7n14mubX3%Da<8;#FqM_eB44Nx_Gy)$~ZNEnNZ z8S94fi2oWlO@ERbF-U|Q-QnCEDF=YXdbON5U^^ z>!8#Hp5qok*;Ne&hKUmcKP{JpD} zP7=7Jgw-uA1m0|JScFzV@xXsyGhV{>``oL9PVZ znPHU{)c~x<)RsuXxNfVAL*yMyYvjQ;3}JfDn0wGBebc*jJh4?~eUH+>yPDu&$v?a~ zW0LjyUARi;Sq@R?M2m=l28P*>u-st&r-Y?jx(wE5>ZSsVjkf;H?M3Dk**Xfr4;gIe ztoav@UABSWYtyPt3eQ4p-s@r5)#4EvIQ*ZZnqPYh6n#|1fzzTZ6}6;^Hpbf3Jgp-m z_0ExU65z-)U)8+Cei^24fu|31h3G`Mu7$@9cE7Tamiy07eL`lG;^l~OTM_jTwG^DR`?cXTaYQ-X?0q@nSPR0XbJgj{p~@q@{AaP)j0NuJfH zr|gx51~`*uPZgc|F`XVXFFj%R^AG}_O8acrz@O#8xR#t-3aE-F@+`Q@{rg;La75St zh8Jb~i@!{2a8;|IdGn!B@0xpy?<@8#FC+qsaqA~tC6owPELd&SDLQludk%=1<|i`G z&Z3WFCc@vM>WtIGpe>8mT&^Q};XxNX&Ybd4NCEUbQ7o|h zQ~woXI60JuFf0dxo(sCz*l%mE1XMW)(!Yl1IR4Xw_Q|-WrQvO@i*pfOJHsMhe#*(J#luHhfcmal>bwi!b!?R zc7{$Bd^-cfTy zZ70Bcc?fEwNc?4SGGNe#$;3O6yO`PZ&j*zKEhwTF@ADXJuqY?SNX9jg9Ft9yUm!m8 zZRkWY8G;UTWSO7R$3!aE_c1qvqzl&)d6pWFQkSDC3(H%2NV-^NC+^st4O(c|Orevk z%}_R~8v_Us04z4{+|=O61u+dh3-NNsTpkZO1WYtYv2XBRgVdu!a*R;OV{*E2Gj9(^ z(pxSzj}Syjl?E*K@rF1O^!}q+B>BdDu~8324;aRMgfKPr$uf+@D00PkJZ88kjwak+ zN93Aj=FWXz?6$Z*@}c0C{jAe=@G}J{fqzvP9c$@b)`jaB7zFX)djPt_oZgmocHa~O z0)$w$Yl19;crJom-o*uQaB`b-9qaAE0K z8wFnx{(`H^QNC`_5?F%Dh9bK*XbE9@|Pu8YIc@;e&^&i z-U^7a2Z)NWVHQaedaaU%6pzRC(O3TdNsinn33QjJsg^-Q5`460Z0g<`(Jb_D9~phc zZjxs|}ihmq=J2z4Jb53|#gwyU{ z>9R-*?#dwyP26s633nFGk82w*Cr_9`L* z>v_Xhfckx(si6qC#)myZ9a=x!^G4&`6WfwEg43Ey#2zw)*U*;6 z`?lCLNa7&b#TUZpD^a{=krCKF#>Uygi!|Bof=lT@*j~%bJaYd2iBsg}KYAX+;X*^6g*GhD5cOR#6rmpy5i!!Gq`3rD*_ z9C0dbC(UU?Ivq&s%QkRpdu|Oc!EQ8`vS_#GWb0B=%#@N}7n&3f`c})Ns6u!)Z29e|S*PjsIimQk>FO1_qTr=8k_7>Ykat-OH zG)Vzjz3KGVk#QmwUU3av=T#FEhBBzZf*-KAgN&w&-RR9eTu|Fqz+=8n+M8Zo;QSK( zYMd#&>k|NUL#fV2!zlvX(_4n?7$4hw!_ZzIwVP6s4&V=eJT~oanNz5;z+{lm^(l)A zMkM8vghv~2vKRVQ0FtDd{ zVvtkoIK?&2?X)OWJsT^RlIM5exnGmx9;@a^eFud%u>tzI2D<>v;57d_9e=7;8s7BqMjfVy0`}jI#^S^jR zC}QvNth?zd)fyx2gJ8s5jX&Cy53sPzx4c*}eyx@Fh8q~kG99P`8-J|lkU%K#;v1?m z#EWaD*)s3DD$AZ3i|nJ*H%dL=GOaz5cETl_{a@mhdyu9P+?}KKjD;~ToDuKs->l(? zd(5)+d83OcnBy&RA+Rt~R!4|yg{%ph?1kb5gh8)BEb@i?Bf@FsUF5Avyb~s$5T?4G z2;GV*o6jFBa^RhB|*zV0&)qphItB7DQDye#nY$(cu62x65n+b$I9eXGF=5^Jt zXc1cp*uKKa>%zN3AamoAiZGx2n)6_5wv#TsaTNAr3s=0L9d>0fma(gf@mqrZoyRI) z(=@+;X46jtU6SmWsTrlc3uYHoEyE;h*ZOu+B3NN6q3IRy?}`}9?Gfqd>jhK$C}WJ> zLZr%><9n6!h@LA_$aUkKLbz^$I`PGBqgT?nCX*9M?piw~2}6v!t+#@DrD4(Mk}En+ zD1YdQ{&pVNXHwb=?SYMs#?0-Vvn+<_PaPbHhHrG+7`4&NCo!xhF;1qgSjU~c1c>S- zofoY6Pf_9d7nfx;r&QU1SwYxiVIv(G0H(To+Hl0NR)uy{0P&wG@T6e`2(STj&ed2N ze6hF9xfSa7J%TWaW_lv!^+g_FO$Axmg76Gs3@^ErXD$jZTZ`0;QymuZDTpWJ?h}de zx4SYy^Xbfl!J9riw!EQLdXPDOhEP01-jAqJmAthL`kC3hgZ~i?wJW=@%dZ&C!1wIFx)6?4neSB35zNgol4VzyvoT+{eXd@Sc zdf&a?4`AFU1brMx0PgP*EFvnt)s&trhfLO0>w zFSt0>8r$Gana$iOhpJis^8W)>Yu$J$fE$Z}(#ZGytSiin?ci4rhNl23(eJ=BvXLh> z!37$&!faD)Pp+zlRoB#8i2ywJF5hE-FW|$d+l%8N)7E)bT^ST2;oc93uEllQ_NXfF zgD(5bB>+3(>C7lg-p4qOCz2DdXUu#4Ud1n1?!ui&s0ZY@sT!!dBMSNEDxrdxpQi zSMXiAa`F3@9@1a%ae&2-v7bfZ^oz#_qSK<2FfE4u7V~F;cSn1=PDC(|jEkSI97)b0 zX?TY2<8MUBbCSSu#W`%q;PtW|e$NY)fsfAm6F-b>c-x`da&JjMpEwt9OPqsmYwvCT zFu7k;;&|0M8x)NnhRp0XoFPp#(ep2XSbzpwnEknR78LJrZ$Vs4-gI!Xku?4{{Dz<- z)%J6Q`W&yW6nOq-NAQs%u!gg)BPu$K(Nw&S>g&i=KNaS?__+GB1H%2ihFV;j^aheQ z#=yt?j3`P^>}AH)R?(g`z7dw zQPzsalcO`W#b%@F-RZM3)o90EM|>i|)doO--~j-mQK(J%CAKSHF)cnW7(@-z#c>^) zVqN6!_pg`D&-f;X{7w$2sJ7TsnJ6H|?5KOqqO_;Z>Zx0zkbo%$y>{rW}PwCSGiE2egl~c%P+QiT*CJ^Q9jdkkR@-q@vKZE zr~Sa;J%Z-Dh5^I)eJADW9khnLu+ZsoR)VWTy3FbNn$Zk%>GHBD3_B=Vbd25j(XdS|vQckI8B%)+*!ah93#`Bg}{Q*Rm=K)w6vBb}aki%R|c&umkOrSyKeK@P&GGx2c4$ZjYmbMV3gNSBE5 z*&kR9G(W=dR(oJBDOa3_Ch6(}t=euxOP>wdkG1`V(naKAhzPOOs^kbkjt(`bW zW1+WrYfpRW3Gnn$IjXL5dcz_8yp)IK`ZB`SIZ#ti#ec2hh0C}9q-(0bl__@>$S&a| zaNTSVEynJN3HqdHWdb@1v3j>k8|J>$5yDPD&8GiY%xbrskbmF!e^$18Dye+=XR00yF$ z{2{@>=3|XwU+Z1qgat!f7kZy}Zaw0i3KVD?eKvX0V%aHp1sN0?-+RU_1foWVp$zKS zBAh)1;B{EyaFlXntiaoIZhjPsARn4UVCSZMuX}-vt3LLuT(hZaCBVF2|HnS|+wF0o z-sF0j@#9`JS8WRoip5u{_VuKu_F3aloEolxfZX-p){5v?ex{+H=>18upPlVhci(Z1 zjZjG#-#*7V(cJ*5U%ons<{lRv4RE|Y64eVxy%n0y`s+fC_DuRbj1ift`8snt9E%)H zchvig@KZ!nBYEa-=?@?K(eh-hyZ%;PU&Pq%Im>_gqRIMybh>ARm5y+7dUpn<4|t&G z&P<&eAn2V7$Xe6HTBi1onVbV;Ik7ZqF!qKw$1w?Hj!!z)4_&?zJ+9AqFNo>Q_p*CU zUSBYmk;zteb`*>tp0<)S!jy^`z6hX3Te7xaaPXe!9^5m^-8|08;>8{unm>*ZiZ61N&fnH?p}9_ z^|O)0nxqWEw*Wwt50$AmG3KVG$GIRp7G%`M3;~rV*2+&RBLz|nFJ@zrDvjbnke2w( zQ0|}`mTq2iCG=DSe<-)~3ru!>U@7Me&cEhc`umJ--u)Mn3doW1VQA>YbK0$EchApb zteh|2^<=?eR{rlU4VY@iq4GK2nKxU9R9pn(A#m&oNV3G(3_?wL=ezw!g+2p2O!c0` z$Z4{ZAfR%B`I7!WBKu#c3%l``A+O`?wEw6I9-jbbX*r1*HyGY*)o7*5{*Kd zxht=sy7afW-397`+OuPcEv<^GBOjP`bz4zyRa7u6(pdis=>``0bGdDpbNQ@0rKGsx zwAqx?a0-?~B^L(1x?ah-;@s1&B)Y=JYE>Wf8C)3dc!876v^=A!XgK|1Qi88H=BUb` zV;m`KvV>vPIe)7x-L=v9j5;?{G-h{~rL81g;ZDEWOZqL0E@AlEobIYM)~K^Hp0TW} z!dR1>?cS3v+bDeoKF#Mk#_Y7TQEI0vrqi!-X%$bUm0F1mJzY~U4P8}i zgEGjH!aq@`Cl%+O=hw*pj-O25SX=2gx`g5Ut>@R2-PLtl`m?ojUvQ0CMZ;M;A6p~e z#ZRYis;zv%H6$|rtoFm!Z0DZR=Y0AFWhq~u{v;a788I@tdg+Suw?0Pe zYol0A!vByl%egXp=JiDeh6lsK@IG*#kixJUbjvf+*h(_oduUmu{p)KK8t@)*rT9}O zEj8Dt=F}+9JI2S#W<%1Pqbu$`^<|p|{-EHT2`8-^6P4?QQI}BBkcQ}r_qR&1 zVD9j&qT#)t+T;uR(w^^HbKH_R^G=ul^~X$Cm`k|AZ)B+A0l>S>1Q^ec$VXv}u6xZ@SXWrI#gcdj^pOZrXg z%jwr|SYK|x(#i^{3RZKyFwH2w!xXxJgrlY{H7u#vuQFI_hEsA4JU`7CbpFB?*pu99#|<-ugl~#@GPic)HSLI zN%Q3Bjms*h8_wU7lK%oMAULjea5-SC`hNwNgK+E^e-Xsx=9zH${h4t&Xt?*V9@s@E z8tP=IF|$I?I9I#|c}Sy53K^z*#l^uM64aYfUF|XI)Lyer@9klA(2G}QdQQ9)!`vT! z^-1PL&w*c>hFG`7EABnM(~ASgI#Scv#YLU{}TRn|8*_@^FIkNBqsjb{t5Wt=YyXQem?m5 z;OB#%4}L!Q`QT^fc!`O4$@E{B!Lq`tuaxuu><1qsLl_d_f8}$SWM+7c{@Z8|J?CHD zo_}laN35w8In +#include +#include +#include "fpgaloader.h" #include "proxmark3.h" -#include "apps.h" #include "util.h" #include "string.h" +#include "BigBuf.h" +#include "zlib.h" + +extern void Dbprintf(const char *fmt, ...); // remember which version of the bitstream we have already downloaded to the FPGA static int downloaded_bitstream = FPGA_BITSTREAM_ERR; @@ -23,9 +31,8 @@ extern uint8_t _binary_fpga_hf_bit_start, _binary_fpga_hf_bit_end; static uint8_t *fpga_image_ptr = NULL; static const uint8_t _bitparse_fixed_header[] = {0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x01}; -static const uint8_t _gzip_header[] = {0x1f, 0x8b, 0x08}; // including compression method 0x08 (deflate) -#define GZIP_HEADER_SIZE sizeof(_gzip_header) #define FPGA_BITSTREAM_FIXED_HEADER_SIZE sizeof(_bitparse_fixed_header) +#define OUTPUT_BUFFER_LEN 80 //----------------------------------------------------------------------------- // Set up the Serial Peripheral Interface as master @@ -164,15 +171,86 @@ bool FpgaSetupSscDma(uint8_t *buf, int len) } -void reset_fpga_stream(uint8_t *image_start) +uint8_t get_from_fpga_stream(z_streamp compressed_fpga_stream, uint8_t *output_buffer) { - fpga_image_ptr = image_start; + if (fpga_image_ptr == compressed_fpga_stream->next_out) { // need more data + compressed_fpga_stream->next_out = output_buffer; + compressed_fpga_stream->avail_out = OUTPUT_BUFFER_LEN; + fpga_image_ptr = output_buffer; + int res = inflate(compressed_fpga_stream, Z_SYNC_FLUSH); + // if (res != Z_OK && res != Z_STREAM_END) { + Dbprintf("inflate returned: %d, %s", res, compressed_fpga_stream->msg); + // } + } + + Dbprintf("get_from_fpga_stream() returns %02x", *fpga_image_ptr); + return *fpga_image_ptr++; } -uint8_t get_from_fpga_stream(void) +static voidpf fpga_inflate_malloc(voidpf opaque, uInt items, uInt size) { - return *fpga_image_ptr++; + Dbprintf("zlib requested %d bytes", items*size); + return BigBuf_malloc(items*size); +} + + +static void fpga_inflate_free(voidpf opaque, voidpf address) +{ + Dbprintf("zlib wants to free memory"); + BigBuf_free_keep_EM(); +} + + +void init_fpga_inflate(z_streamp compressed_fpga_stream, uint8_t *fpga_image_start, uint32_t fpga_image_size, uint8_t *output_buffer) +{ + // initialize z_stream structure for inflate: + compressed_fpga_stream->next_in = fpga_image_start; + compressed_fpga_stream->avail_in = fpga_image_size; + compressed_fpga_stream->next_out = output_buffer; + compressed_fpga_stream->avail_out = OUTPUT_BUFFER_LEN; + compressed_fpga_stream->zalloc = &fpga_inflate_malloc; + compressed_fpga_stream->zfree = &fpga_inflate_free; + + // initialize inflate to automatically detect header: + int res = inflateInit2(compressed_fpga_stream, 15+32); + + fpga_image_ptr = output_buffer; + + Dbprintf("InflateInit returned %d", res); + Dbprintf("fpga_image_ptr pointing at %02x %02x %02x %02x", fpga_image_ptr[0], fpga_image_ptr[1], fpga_image_ptr[2], fpga_image_ptr[3]); + Dbprintf("zstream->next_in pointing at %02x %02x %02x %02x", compressed_fpga_stream->next_in[0], compressed_fpga_stream->next_in[1], compressed_fpga_stream->next_in[2], compressed_fpga_stream->next_in[3]); +} + + +bool reset_fpga_stream(int bitstream_version, z_streamp compressed_fpga_stream, uint8_t *output_buffer) +{ + uint8_t header[FPGA_BITSTREAM_FIXED_HEADER_SIZE]; + uint8_t *fpga_image_start; + uint32_t fpga_image_size; + + if (bitstream_version == FPGA_BITSTREAM_LF) { + fpga_image_start = &_binary_fpga_lf_bit_start; + fpga_image_size = (uint32_t)&_binary_fpga_lf_bit_end - (uint32_t)&_binary_fpga_lf_bit_start; + } else if (bitstream_version == FPGA_BITSTREAM_HF) { + fpga_image_start = &_binary_fpga_hf_bit_start; + fpga_image_size = (uint32_t)&_binary_fpga_hf_bit_end - (uint32_t)&_binary_fpga_hf_bit_start; + } else { + return false; + } + + init_fpga_inflate(compressed_fpga_stream, fpga_image_start, fpga_image_size, output_buffer); + + for (uint16_t i = 0; i < FPGA_BITSTREAM_FIXED_HEADER_SIZE; i++) { + header[i] = get_from_fpga_stream(compressed_fpga_stream, output_buffer); + } + + // Check for a valid .bit file (starts with _bitparse_fixed_header) + if(memcmp(_bitparse_fixed_header, header, FPGA_BITSTREAM_FIXED_HEADER_SIZE) == 0) { + return true; + } else { + return false; + } } @@ -190,8 +268,11 @@ static void DownloadFPGA_byte(unsigned char w) } // Download the fpga image starting at current stream position with length FpgaImageLen bytes -static void DownloadFPGA(int FpgaImageLen) +static void DownloadFPGA(int FpgaImageLen, z_streamp compressed_fpga_stream, uint8_t *output_buffer) { + Dbprintf("Would have loaded FPGA"); + return; + int i=0; AT91C_BASE_PIOA->PIO_OER = GPIO_FPGA_ON; @@ -244,7 +325,7 @@ static void DownloadFPGA(int FpgaImageLen) } while(FpgaImageLen-->0) { - DownloadFPGA_byte(get_from_fpga_stream()); + DownloadFPGA_byte(get_from_fpga_stream(compressed_fpga_stream, output_buffer)); } // continue to clock FPGA until ready signal goes high @@ -269,13 +350,13 @@ static void DownloadFPGA(int FpgaImageLen) * (big endian), bytes content. Except for section 'e' which has 4 bytes * length. */ -int bitparse_find_section(char section_name, unsigned int *section_length) +int bitparse_find_section(char section_name, unsigned int *section_length, z_streamp compressed_fpga_stream, uint8_t *output_buffer) { int result = 0; #define MAX_FPGA_BIT_STREAM_HEADER_SEARCH 100 // maximum number of bytes to search for the requested section uint16_t numbytes = 0; while(numbytes < MAX_FPGA_BIT_STREAM_HEADER_SEARCH) { - char current_name = get_from_fpga_stream(); + char current_name = get_from_fpga_stream(compressed_fpga_stream, output_buffer); numbytes++; unsigned int current_length = 0; if(current_name < 'a' || current_name > 'e') { @@ -286,12 +367,12 @@ int bitparse_find_section(char section_name, unsigned int *section_length) switch(current_name) { case 'e': /* Four byte length field */ - current_length += get_from_fpga_stream() << 24; - current_length += get_from_fpga_stream() << 16; + current_length += get_from_fpga_stream(compressed_fpga_stream, output_buffer) << 24; + current_length += get_from_fpga_stream(compressed_fpga_stream, output_buffer) << 16; numbytes += 2; default: /* Fall through, two byte length field */ - current_length += get_from_fpga_stream() << 8; - current_length += get_from_fpga_stream() << 0; + current_length += get_from_fpga_stream(compressed_fpga_stream, output_buffer) << 8; + current_length += get_from_fpga_stream(compressed_fpga_stream, output_buffer) << 0; numbytes += 2; } @@ -308,7 +389,7 @@ int bitparse_find_section(char section_name, unsigned int *section_length) } for (uint16_t i = 0; i < current_length && numbytes < MAX_FPGA_BIT_STREAM_HEADER_SEARCH; i++) { - get_from_fpga_stream(); + get_from_fpga_stream(compressed_fpga_stream, output_buffer); numbytes++; } } @@ -316,11 +397,6 @@ int bitparse_find_section(char section_name, unsigned int *section_length) return result; } -void init_fpga_inflate(void) -{ - // initialize zlib for inflate -} - //----------------------------------------------------------------------------- // Find out which FPGA image format is stored in flash, then call DownloadFPGA @@ -328,71 +404,42 @@ void init_fpga_inflate(void) //----------------------------------------------------------------------------- void FpgaDownloadAndGo(int bitstream_version) { - uint8_t header[FPGA_BITSTREAM_FIXED_HEADER_SIZE]; + z_stream compressed_fpga_stream; + uint8_t output_buffer[OUTPUT_BUFFER_LEN]; // check whether or not the bitstream is already loaded if (downloaded_bitstream == bitstream_version) return; - 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 + if (!reset_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer)) { return; - - 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 */ - } + unsigned int bitstream_length; + if(bitparse_find_section('e', &bitstream_length, &compressed_fpga_stream, output_buffer)) { + DownloadFPGA(bitstream_length, &compressed_fpga_stream, output_buffer); + downloaded_bitstream = bitstream_version; + return; /* All done */ } } -int FpgaGatherBitstreamVersion() -{ - return downloaded_bitstream; -} void FpgaGatherVersion(int bitstream_version, char *dst, int len) { unsigned int fpga_info_len; char tempstr[40]; + z_stream compressed_fpga_stream; + uint8_t output_buffer[OUTPUT_BUFFER_LEN]; 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 + if (!reset_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer)) { 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)) { + if(bitparse_find_section('a', &fpga_info_len, &compressed_fpga_stream, output_buffer)) { for (uint16_t i = 0; i < fpga_info_len; i++) { - char c = (char)get_from_fpga_stream(); + char c = (char)get_from_fpga_stream(&compressed_fpga_stream, output_buffer); if (i < sizeof(tempstr)) { tempstr[i] = c; } @@ -403,30 +450,30 @@ void FpgaGatherVersion(int bitstream_version, char *dst, int len) strncat(dst, "HF ", len-1); } strncat(dst, "FPGA image built", len-1); - if(bitparse_find_section('b', &fpga_info_len)) { + if(bitparse_find_section('b', &fpga_info_len, &compressed_fpga_stream, output_buffer)) { strncat(dst, " for ", len-1); for (uint16_t i = 0; i < fpga_info_len; i++) { - char c = (char)get_from_fpga_stream(); + char c = (char)get_from_fpga_stream(&compressed_fpga_stream, output_buffer); if (i < sizeof(tempstr)) { tempstr[i] = c; } } strncat(dst, tempstr, len-1); } - if(bitparse_find_section('c', &fpga_info_len)) { + if(bitparse_find_section('c', &fpga_info_len, &compressed_fpga_stream, output_buffer)) { strncat(dst, " on ", len-1); for (uint16_t i = 0; i < fpga_info_len; i++) { - char c = (char)get_from_fpga_stream(); + char c = (char)get_from_fpga_stream(&compressed_fpga_stream, output_buffer); if (i < sizeof(tempstr)) { tempstr[i] = c; } } strncat(dst, tempstr, len-1); } - if(bitparse_find_section('d', &fpga_info_len)) { + if(bitparse_find_section('d', &fpga_info_len, &compressed_fpga_stream, output_buffer)) { strncat(dst, " at ", len-1); for (uint16_t i = 0; i < fpga_info_len; i++) { - char c = (char)get_from_fpga_stream(); + char c = (char)get_from_fpga_stream(&compressed_fpga_stream, output_buffer); if (i < sizeof(tempstr)) { tempstr[i] = c; } @@ -435,6 +482,7 @@ void FpgaGatherVersion(int bitstream_version, char *dst, int len) } } + //----------------------------------------------------------------------------- // Send a 16 bit command/data pair to the FPGA. // The bit format is: C3 C2 C1 C0 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 diff --git a/armsrc/fpgaloader.h b/armsrc/fpgaloader.h new file mode 100644 index 00000000..6981b216 --- /dev/null +++ b/armsrc/fpgaloader.h @@ -0,0 +1,64 @@ +//----------------------------------------------------------------------------- +// Jonathan Westhues, April 2006 +// iZsh , 2014 +// +// 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. +//----------------------------------------------------------------------------- +// Routines to load the FPGA image, and then to configure the FPGA's major +// mode once it is configured. +//----------------------------------------------------------------------------- + +void FpgaSendCommand(uint16_t cmd, uint16_t v); +void FpgaWriteConfWord(uint8_t v); +void FpgaDownloadAndGo(int bitstream_version); +void FpgaGatherVersion(int bitstream_version, char *dst, int len); +void FpgaSetupSsc(void); +void SetupSpi(int mode); +bool FpgaSetupSscDma(uint8_t *buf, int len); +#define FpgaDisableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS; +#define FpgaEnableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN; +void SetAdcMuxFor(uint32_t whichGpio); + +// Definitions for the FPGA commands. +#define FPGA_CMD_SET_CONFREG (1<<12) +#define FPGA_CMD_SET_DIVISOR (2<<12) +#define FPGA_CMD_SET_USER_BYTE1 (3<<12) +// Definitions for the FPGA configuration word. +// LF +#define FPGA_MAJOR_MODE_LF_ADC (0<<5) +#define FPGA_MAJOR_MODE_LF_EDGE_DETECT (1<<5) +#define FPGA_MAJOR_MODE_LF_PASSTHRU (2<<5) +// HF +#define FPGA_MAJOR_MODE_HF_READER_TX (0<<5) +#define FPGA_MAJOR_MODE_HF_READER_RX_XCORR (1<<5) +#define FPGA_MAJOR_MODE_HF_SIMULATOR (2<<5) +#define FPGA_MAJOR_MODE_HF_ISO14443A (3<<5) +// BOTH +#define FPGA_MAJOR_MODE_OFF (7<<5) +// Options for LF_ADC +#define FPGA_LF_ADC_READER_FIELD (1<<0) +// Options for LF_EDGE_DETECT +#define FPGA_CMD_SET_EDGE_DETECT_THRESHOLD FPGA_CMD_SET_USER_BYTE1 +#define FPGA_LF_EDGE_DETECT_READER_FIELD (1<<0) +#define FPGA_LF_EDGE_DETECT_TOGGLE_MODE (1<<1) +// Options for the HF reader, tx to tag +#define FPGA_HF_READER_TX_SHALLOW_MOD (1<<0) +// Options for the HF reader, correlating against rx from tag +#define FPGA_HF_READER_RX_XCORR_848_KHZ (1<<0) +#define FPGA_HF_READER_RX_XCORR_SNOOP (1<<1) +#define FPGA_HF_READER_RX_XCORR_QUARTER_FREQ (1<<2) +// Options for the HF simulated tag, how to modulate +#define FPGA_HF_SIMULATOR_NO_MODULATION (0<<0) +#define FPGA_HF_SIMULATOR_MODULATE_BPSK (1<<0) +#define FPGA_HF_SIMULATOR_MODULATE_212K (2<<0) +#define FPGA_HF_SIMULATOR_MODULATE_424K (4<<0) +#define FPGA_HF_SIMULATOR_MODULATE_424K_8BIT 0x5//101 + +// Options for ISO14443A +#define FPGA_HF_ISO14443A_SNIFFER (0<<0) +#define FPGA_HF_ISO14443A_TAGSIM_LISTEN (1<<0) +#define FPGA_HF_ISO14443A_TAGSIM_MOD (2<<0) +#define FPGA_HF_ISO14443A_READER_LISTEN (3<<0) +#define FPGA_HF_ISO14443A_READER_MOD (4<<0) diff --git a/armsrc/inffast.c b/armsrc/inffast.c new file mode 100644 index 00000000..bda59ceb --- /dev/null +++ b/armsrc/inffast.c @@ -0,0 +1,340 @@ +/* inffast.c -- fast decoding + * Copyright (C) 1995-2008, 2010, 2013 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifndef ASMINF + +/* Allow machine dependent optimization for post-increment or pre-increment. + Based on testing to date, + Pre-increment preferred for: + - PowerPC G3 (Adler) + - MIPS R5000 (Randers-Pehrson) + Post-increment preferred for: + - none + No measurable difference: + - Pentium III (Anderson) + - M68060 (Nikl) + */ +#ifdef POSTINC +# define OFF 0 +# define PUP(a) *(a)++ +#else +# define OFF 1 +# define PUP(a) *++(a) +#endif + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void ZLIB_INTERNAL inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + z_const unsigned char FAR *in; /* local strm->next_in */ + z_const unsigned char FAR *last; /* have enough input while in < last */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ +#ifdef INFLATE_STRICT + unsigned dmax; /* maximum distance from zlib header */ +#endif + 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 wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code here; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in - OFF; + last = in + (strm->avail_in - 5); + out = strm->next_out - OFF; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); +#ifdef INFLATE_STRICT + dmax = state->dmax; +#endif + wsize = state->wsize; + whave = state->whave; + wnext = state->wnext; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + here = lcode[hold & lmask]; + dolen: + op = (unsigned)(here.bits); + hold >>= op; + bits -= op; + op = (unsigned)(here.op); + if (op == 0) { /* literal */ + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + PUP(out) = (unsigned char)(here.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(here.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + here = dcode[hold & dmask]; + dodist: + op = (unsigned)(here.bits); + hold >>= op; + bits -= op; + op = (unsigned)(here.op); + if (op & 16) { /* distance base */ + dist = (unsigned)(here.val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); +#ifdef INFLATE_STRICT + if (dist > dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + if (state->sane) { + strm->msg = + (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + if (len <= op - whave) { + do { + PUP(out) = 0; + } while (--len); + continue; + } + len -= op - whave; + do { + PUP(out) = 0; + } while (--op > whave); + if (op == 0) { + from = out - dist; + do { + PUP(out) = PUP(from); + } while (--len); + continue; + } +#endif + } + from = window - OFF; + if (wnext == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (wnext < op) { /* wrap around window */ + from += wsize + wnext - op; + op -= wnext; + if (op < len) { /* some from end of window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = window - OFF; + if (wnext < len) { /* some from start of window */ + op = wnext; + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += wnext - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + else { + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } while (len > 2); + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + here = dcode[here.val + (hold & ((1U << op) - 1))]; + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + here = lcode[here.val + (hold & ((1U << op) - 1))]; + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in + OFF; + strm->next_out = out + OFF; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and wnext == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ diff --git a/armsrc/inftrees.c b/armsrc/inftrees.c new file mode 100644 index 00000000..d8c53250 --- /dev/null +++ b/armsrc/inftrees.c @@ -0,0 +1,302 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2013 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#define MAXBITS 15 + +const char inflate_copyright[] = + " inflate 1.2.8 Copyright 1995-2013 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work) +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code here; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + int end; /* use base and extra for symbol > end */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) { /* no symbols to code at all */ + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)1; + here.val = (unsigned short)0; + *(*table)++ = here; /* make a table to force an error */ + *(*table)++ = here; + *bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min < max; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || max != 1)) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked for LENS and DIST tables against + the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in + the initial root table size constants. See the comments in inftrees.h + for more information. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + end = 19; + break; + case LENS: + base = lbase; + base -= 257; + extra = lext; + extra -= 257; + end = 256; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if ((type == LENS && used > ENOUGH_LENS) || + (type == DISTS && used > ENOUGH_DISTS)) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + here.bits = (unsigned char)(len - drop); + if ((int)(work[sym]) < end) { + here.op = (unsigned char)0; + here.val = work[sym]; + } + else if ((int)(work[sym]) > end) { + here.op = (unsigned char)(extra[work[sym]]); + here.val = base[work[sym]]; + } + else { + here.op = (unsigned char)(32 + 64); /* end of block */ + here.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + next[(huff >> drop) + fill] = here; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if ((type == LENS && used > ENOUGH_LENS) || + (type == DISTS && used > ENOUGH_DISTS)) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } + + /* fill in remaining table entry if code is incomplete (guaranteed to have + at most one remaining entry, since if the code is incomplete, the + maximum code length that was allowed to get this far is one bit) */ + if (huff != 0) { + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)(len - drop); + here.val = (unsigned short)0; + next[huff] = here; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} diff --git a/armsrc/zutil.c b/armsrc/zutil.c new file mode 100644 index 00000000..23d2ebef --- /dev/null +++ b/armsrc/zutil.c @@ -0,0 +1,324 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2005, 2010, 2011, 2012 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" +#ifndef Z_SOLO +# include "gzguts.h" +#endif + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +z_const char * const z_errmsg[10] = { +"need dictionary", /* Z_NEED_DICT 2 */ +"stream end", /* Z_STREAM_END 1 */ +"", /* Z_OK 0 */ +"file error", /* Z_ERRNO (-1) */ +"stream error", /* Z_STREAM_ERROR (-2) */ +"data error", /* Z_DATA_ERROR (-3) */ +"insufficient memory", /* Z_MEM_ERROR (-4) */ +"buffer error", /* Z_BUF_ERROR (-5) */ +"incompatible version",/* Z_VERSION_ERROR (-6) */ +""}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +uLong ZEXPORT zlibCompileFlags() +{ + uLong flags; + + flags = 0; + switch ((int)(sizeof(uInt))) { + case 2: break; + case 4: flags += 1; break; + case 8: flags += 2; break; + default: flags += 3; + } + switch ((int)(sizeof(uLong))) { + case 2: break; + case 4: flags += 1 << 2; break; + case 8: flags += 2 << 2; break; + default: flags += 3 << 2; + } + switch ((int)(sizeof(voidpf))) { + case 2: break; + case 4: flags += 1 << 4; break; + case 8: flags += 2 << 4; break; + default: flags += 3 << 4; + } + switch ((int)(sizeof(z_off_t))) { + case 2: break; + case 4: flags += 1 << 6; break; + case 8: flags += 2 << 6; break; + default: flags += 3 << 6; + } +#ifdef DEBUG + flags += 1 << 8; +#endif +#if defined(ASMV) || defined(ASMINF) + flags += 1 << 9; +#endif +#ifdef ZLIB_WINAPI + flags += 1 << 10; +#endif +#ifdef BUILDFIXED + flags += 1 << 12; +#endif +#ifdef DYNAMIC_CRC_TABLE + flags += 1 << 13; +#endif +#ifdef NO_GZCOMPRESS + flags += 1L << 16; +#endif +#ifdef NO_GZIP + flags += 1L << 17; +#endif +#ifdef PKZIP_BUG_WORKAROUND + flags += 1L << 20; +#endif +#ifdef FASTEST + flags += 1L << 21; +#endif +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifdef NO_vsnprintf + flags += 1L << 25; +# ifdef HAS_vsprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_vsnprintf_void + flags += 1L << 26; +# endif +# endif +#else + flags += 1L << 24; +# ifdef NO_snprintf + flags += 1L << 25; +# ifdef HAS_sprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_snprintf_void + flags += 1L << 26; +# endif +# endif +#endif + return flags; +} + +#ifdef DEBUG + +# ifndef verbose +# define verbose 0 +# endif +int ZLIB_INTERNAL z_verbose = verbose; + +void ZLIB_INTERNAL z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + +#if defined(_WIN32_WCE) + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. + */ + int errno = 0; +#endif + +#ifndef HAVE_MEMCPY + +void ZLIB_INTERNAL zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int ZLIB_INTERNAL zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void ZLIB_INTERNAL zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + +#ifndef Z_SOLO + +#ifdef SYS16BIT + +#ifdef __TURBOC__ +/* Turbo C in 16-bit mode */ + +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf = opaque; /* just to make some compilers happy */ + ulg bsize = (ulg)items*size; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) +{ + int n; + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + ptr = opaque; /* just to make some compilers happy */ + Assert(0, "zcfree: ptr not found"); +} + +#endif /* __TURBOC__ */ + + +#ifdef M_I86 +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + return _halloc((long)items, size); +} + +void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + _hfree(ptr); +} + +#endif /* M_I86 */ + +#endif /* SYS16BIT */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf ZLIB_INTERNAL zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + if (opaque) items += size - size; /* make compiler happy */ + return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : + (voidpf)calloc(items, size); +} + +void ZLIB_INTERNAL zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + free(ptr); + if (opaque) return; /* make compiler happy */ +} + +#endif /* MY_ZCALLOC */ + +#endif /* !Z_SOLO */ diff --git a/common/Makefile.common b/common/Makefile.common index 2b2bb2fb..d7e3457f 100644 --- a/common/Makefile.common +++ b/common/Makefile.common @@ -25,6 +25,7 @@ CC = $(CROSS)gcc AS = $(CROSS)as LD = $(CROSS)ld OBJCOPY = $(CROSS)objcopy +GZIP=gzip OBJDIR = obj -- 2.39.2