| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974 |
- #include <time.h>
- #include <stdio.h>
- #include <errno.h>
- #include <ctype.h>
- #include <fcntl.h>
- #include <stdlib.h>
- #include <string.h>
- #include <getopt.h>
- #include <dirent.h>
- #include <unistd.h>
- #include <stdarg.h>
- #ifdef __MINGW32__
- #include <windows.h>
- #else
- #include <signal.h>
- #include <pthread.h>
- #include <termios.h>
- #include <sys/ioctl.h>
- #endif
- #define WM_TOOL_PATH_MAX 256
- #define WM_TOOL_ONCE_READ_LEN 1024
- #define WM_TOOL_RUN_IMG_HEADER_LEN 0x100
- #define WM_TOOL_SECBOOT_IMG_ADDR (0x2100)
- #define WM_TOOL_SECBOOT_HEADER_LEN (0x100)
- #define WM_TOOL_SECBOOT_HEADER_POS (WM_TOOL_SECBOOT_IMG_ADDR - WM_TOOL_SECBOOT_HEADER_LEN)
- //#define WM_TOOL_SECBOOT_IMG_AREA_TOTAL_LEN 9216//(56 * 1024)
- #define WM_TOOL_IMG_HEAD_MAGIC_NO (0xA0FFFF9F)
- #define WM_TOOL_DEFAULT_BAUD_RATE 115200
- #define WM_TOOL_DOWNLOAD_TIMEOUT_SEC (60 * 1)
- #define WM_TOOL_USE_1K_XMODEM 1 /* 1 for use 1k_xmodem 0 for xmodem */
- #define WM_TOOL_IMAGE_VERSION_LEN 16
- /* Xmodem Frame form: <SOH><blk #><255-blk #><--128 data bytes--><CRC hi><CRC lo> */
- #define XMODEM_SOH 0x01
- #define XMODEM_STX 0x02
- #define XMODEM_EOT 0x04
- #define XMODEM_ACK 0x06
- #define XMODEM_NAK 0x15
- #define XMODEM_CAN 0x18
- #define XMODEM_CRC_CHR 'C'
- #define XMODEM_CRC_SIZE 2 /* Crc_High Byte + Crc_Low Byte */
- #define XMODEM_FRAME_ID_SIZE 2 /* Frame_Id + 255-Frame_Id */
- #define XMODEM_DATA_SIZE_SOH 128 /* for Xmodem protocol */
- #define XMODEM_DATA_SIZE_STX 1024 /* for 1K xmodem protocol */
- #if (WM_TOOL_USE_1K_XMODEM)
- #define XMODEM_DATA_SIZE XMODEM_DATA_SIZE_STX
- #define XMODEM_HEAD XMODEM_STX
- #else
- #define XMODEM_DATA_SIZE XMODEM_DATA_SIZE_SOH
- #define XMODEM_HEAD XMODEM_SOH
- #endif
- #ifdef WM_DEBUG
- #define WM_TOOL_DBG_PRINT wm_tool_printf
- #else
- #define WM_TOOL_DBG_PRINT(...)
- #endif
- typedef enum {
- WM_TOOL_DL_ACTION_NONE = 0,
- WM_TOOL_DL_ACTION_AT,
- WM_TOOL_DL_ACTION_RTS
- } wm_tool_dl_action_e;
- typedef enum {
- WM_TOOL_DL_ERASE_NONE = 0,
- WM_TOOL_DL_ERASE_ALL
- } wm_tool_dl_erase_e;
- typedef enum {
- WM_TOOL_DL_TYPE_IMAGE = 0,
- WM_TOOL_DL_TYPE_FLS
- } wm_tool_dl_type_e;
- typedef enum {
- WM_TOOL_LAYOUT_TYPE_1M = 0,
- WM_TOOL_LAYOUT_TYPE_2M = 3
- } wm_tool_layout_type_e;
- typedef enum {
- WM_TOOL_ZIP_TYPE_UNCOMPRESS = 0,
- WM_TOOL_ZIP_TYPE_COMPRESS
- } wm_tool_zip_type_e;
- typedef enum {
- WM_TOOL_CRC32_REFLECT_OUTPUT = 1,
- WM_TOOL_CRC32_REFLECT_INPUT = 2
- } wm_tool_crc32_reflect_e;
- typedef enum {
- WM_TOOL_SHOW_LOG_NONE = 0,
- WM_TOOL_SHOW_LOG_STR,
- WM_TOOL_SHOW_LOG_HEX
- } wm_tool_show_log_e;
- typedef struct {
- unsigned int magic_no;
- unsigned short img_type;
- unsigned short zip_type;
- unsigned int run_img_addr;
- unsigned int run_img_len;
- unsigned int img_header_addr;
- unsigned int upgrade_img_addr;
- unsigned int run_org_checksum;
- unsigned int upd_no;
- unsigned char ver[WM_TOOL_IMAGE_VERSION_LEN];
- unsigned int reserved0;
- unsigned int reserved1;
- unsigned int next_boot;
- unsigned int hd_checksum;
- } wm_tool_firmware_booter_t;
- const static char *wm_tool_version = "1.0.4";
- static int wm_tool_show_usage = 0;
- static int wm_tool_list_com = 0;
- static int wm_tool_show_ver = 0;
- static char wm_tool_serial_path[WM_TOOL_PATH_MAX] = "/dev/ttyS0";
- static unsigned int wm_tool_download_serial_rate = WM_TOOL_DEFAULT_BAUD_RATE;
- static unsigned int wm_tool_normal_serial_rate = WM_TOOL_DEFAULT_BAUD_RATE;
- static wm_tool_dl_action_e wm_tool_dl_action = WM_TOOL_DL_ACTION_NONE;
- static wm_tool_dl_erase_e wm_tool_dl_erase = WM_TOOL_DL_ERASE_NONE;
- static wm_tool_dl_type_e wm_tool_dl_type = WM_TOOL_DL_TYPE_IMAGE;
- static char *wm_tool_download_image = NULL;
- static char *wm_tool_input_binary = NULL;
- static char *wm_tool_output_image = NULL;
- static char *wm_tool_secboot_image = NULL;
- static unsigned int wm_tool_src_binary_len = 0;
- static unsigned int wm_tool_src_binary_crc = 0;
- static int wm_tool_is_debug = 0;
- static char wm_tool_image_version[WM_TOOL_IMAGE_VERSION_LEN];
- static wm_tool_layout_type_e wm_tool_image_type = WM_TOOL_LAYOUT_TYPE_1M;
- static wm_tool_zip_type_e wm_tool_zip_type = WM_TOOL_ZIP_TYPE_COMPRESS;
- static unsigned int wm_tool_upd_addr = 0x8090000;
- static unsigned int wm_tool_run_addr = 0x8002400;
- static unsigned int wm_tool_image_header = 0x8002000;
- static unsigned int wm_tool_next_image_header = 0x0;
- static unsigned int wm_tool_image_upd_no = 0x0;
- static unsigned int wm_tool_file_crc = 0xFFFFFFFF;
- static wm_tool_show_log_e wm_tool_show_log_type = WM_TOOL_SHOW_LOG_NONE;
- #ifdef __MINGW32__
- #ifndef CBR_2000000
- #define CBR_2000000 2000000
- #endif
- #ifndef CBR_1000000
- #define CBR_1000000 1000000
- #endif
- #ifndef CBR_921600
- #define CBR_921600 921600
- #endif
- #ifndef CBR_460800
- #define CBR_460800 460800
- #endif
- static DWORD wm_tool_uart_block = 0;
- static HANDLE wm_tool_uart_handle = NULL;
- const static int wm_tool_uart_speed_array[] = {CBR_2000000, CBR_1000000, CBR_921600, CBR_460800, CBR_115200, CBR_38400,
- CBR_19200, CBR_9600, CBR_4800, CBR_2400, CBR_1200};
- #else /* __MINGW32__ */
- #ifndef B2000000
- #define B2000000 2000000
- #endif
- #ifndef B1000000
- #define B1000000 1000000
- #endif
- #ifndef B921600
- #define B921600 921600
- #endif
- #ifndef B460800
- #define B460800 460800
- #endif
- static int wm_tool_uart_fd = -1;
- static struct termios wm_tool_saved_serial_cfg;
- const static int wm_tool_uart_speed_array[] = {B2000000, B1000000, B921600, B460800, B115200, B38400,
- B19200, B9600, B4800, B2400, B1200};
- #endif /* __MINGW32__ */
- const static int wm_tool_uart_name_array[] = {2000000, 1000000, 921600, 460800, 115200, 38400,
- 19200, 9600, 4800, 2400, 1200};
- const static unsigned char wm_tool_chip_cmd_b115200[] = {0x21, 0x0a, 0x00, 0x97, 0x4b, 0x31, 0x00, 0x00, 0x00, 0x00, 0xc2, 0x01, 0x00};
- const static unsigned char wm_tool_chip_cmd_b460800[] = {0x21, 0x0a, 0x00, 0x07, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x08, 0x07, 0x00};
- const static unsigned char wm_tool_chip_cmd_b921600[] = {0x21, 0x0a, 0x00, 0x5d, 0x50, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00};
- const static unsigned char wm_tool_chip_cmd_b1000000[] = {0x21, 0x0a, 0x00, 0x5e, 0x3d, 0x31, 0x00, 0x00, 0x00, 0x40, 0x42, 0x0f, 0x00};
- const static unsigned char wm_tool_chip_cmd_b2000000[] = {0x21, 0x0a, 0x00, 0xef, 0x2a, 0x31, 0x00, 0x00, 0x00, 0x80, 0x84, 0x1e, 0x00};
- const static unsigned char wm_tool_chip_cmd_get_mac[] = {0x21, 0x06, 0x00, 0xea, 0x2d, 0x38, 0x00, 0x00, 0x00};
- const static unsigned char wm_tool_chip_cmd_reset[] = {0x21, 0x06, 0x00, 0xc7, 0x7c, 0x3f, 0x00, 0x00, 0x00};
- static const unsigned int wm_tool_crc32_tab[] = {0x00000000L, 0x77073096L, 0xee0e612cL,
- 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L,
- 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL,
- 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L,
- 0xf3b97148L, 0x84be41deL, 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L,
- 0x83d385c7L, 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL,
- 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L,
- 0x4c69105eL, 0xd56041e4L, 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L,
- 0xd20d85fdL, 0xa50ab56bL, 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L,
- 0xacbcf940L, 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L,
- 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L,
- 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL, 0x2802b89eL, 0x5f058808L,
- 0xc60cd9b2L, 0xb10be924L, 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL,
- 0xb6662d3dL, 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL,
- 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L,
- 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL,
- 0x91646c97L, 0xe6635c01L, 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L,
- 0xf262004eL, 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L,
- 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL,
- 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL,
- 0xa3bc0074L, 0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL,
- 0xd3d6f4fbL, 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L,
- 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL,
- 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L,
- 0xb966d409L, 0xce61e49fL, 0x5edef90eL, 0x29d9c998L, 0xb0d09822L,
- 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL,
- 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, 0xead54739L,
- 0x9dd277afL, 0x04db2615L, 0x73dc1683L, 0xe3630b12L, 0x94643b84L,
- 0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L,
- 0x7d079eb1L, 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL,
- 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L,
- 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L,
- 0x17b7be43L, 0x60b08ed5L, 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L,
- 0x4fdff252L, 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL,
- 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 0xdf60efc3L,
- 0xa867df55L, 0x316e8eefL, 0x4669be79L, 0xcb61b38cL, 0xbc66831aL,
- 0x256fd2a0L, 0x5268e236L, 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L,
- 0x5505262fL, 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L,
- 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L,
- 0xec63f226L, 0x756aa39cL, 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL,
- 0x72076785L, 0x05005713L, 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL,
- 0x0cb61b38L, 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L,
- 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL,
- 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L, 0x88085ae6L, 0xff0f6a70L,
- 0x66063bcaL, 0x11010b5cL, 0x8f659effL, 0xf862ae69L, 0x616bffd3L,
- 0x166ccf45L, 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L,
- 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL,
- 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L,
- 0x47b2cf7fL, 0x30b5ffe9L, 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L,
- 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL,
- 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L,
- 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL};
- static void wm_tool_signal_proc_entry(void);
- static void wm_tool_stdin_to_uart(void);
- /* ============================ zlib gzip ================================== */
- #define ALLOC(size) zcalloc((voidp)0, 1, size)
- #define TRYFREE(p) {if (p) zcfree((voidp)0, p);}
- #define BINARY 0
- #define ASCII 1
- #define UNKNOWN 2
- #define STORED_BLOCK 0
- #define STATIC_TREES 1
- #define DYN_TREES 2
- #define REP_3_6 16
- #define REPZ_3_10 17
- #define REPZ_11_138 18
- #define MAX_BL_BITS 7
- #define BASE 65521 /* largest prime smaller than 65536 */
- #define NMAX 5552
- #define DO1(buf) {s1 += *buf++; s2 += s1;}
- #define DO2(buf) DO1(buf); DO1(buf);
- #define DO4(buf) DO2(buf); DO2(buf);
- #define DO8(buf) DO4(buf); DO4(buf);
- #define DO16(buf) DO8(buf); DO8(buf);
- #define Z_OK 0
- #define Z_STREAM_END 1
- #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_NULL 0 /* for initializing zalloc, zfree, opaque */
- #define Z_BEST_SPEED 1
- #define Z_BEST_COMPRESSION 9
- #define Z_DEFAULT_COMPRESSION (-1)
- #define DEFLATED 8
- #ifndef WBITS
- # define WBITS 15 /* 32K window */
- #endif
- #ifndef MEM_LEVEL
- # define MEM_LEVEL 8
- #endif
- #define Z_BUFSIZE 4096
- #define GZ_MAGIC_1 0x1f
- #define GZ_MAGIC_2 0x8b
- #ifndef OS_CODE
- # define OS_CODE 0x03 /* assume Unix */
- #endif
- #ifndef TOO_FAR
- # define TOO_FAR 4096
- #endif
- #define Z_NO_FLUSH 0
- #define Z_FINISH 4
- #define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
- #define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
- #define ORIG_NAME 0x08 /* bit 3 set: original file name present */
- #define COMMENT 0x10 /* bit 4 set: file comment present */
- #define RESERVED 0xE0 /* bits 5..7: reserved */
- #define LENGTH_CODES 29/* number of length codes, not counting the special END_BLOCK code */
- #define LITERALS 256/* number of literal bytes 0..255 */
- #define L_CODES (LITERALS+1+LENGTH_CODES)/* number of Literal or Length codes, including the END_BLOCK code */
- #define D_CODES 30/* number of distance codes */
- #define BL_CODES 19/* number of codes used to transfer the bit lengths */
- #define HEAP_SIZE (2*L_CODES+1)/* maximum heap size */
- #define END_BLOCK 256
- #define MAX_BITS 15
- #define MAX_MEM_LEVEL 9
- #define MIN_MATCH 3
- #define MAX_MATCH 258
- #define Z_UNKNOWN 2
- #define INIT_STATE 42
- #define BUSY_STATE 113
- #define FINISH_STATE 666
- #define NIL 0
- #define Z_FILTERED 1
- #define Z_HUFFMAN_ONLY 2
- #define Z_DEFAULT_STRATEGY 0
- #define SMALLEST 1
- #define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
- #define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask)
- #define ERR_RETURN(strm,err) return (strm->msg=z_errmsg[1-err], err)
- #define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
- #define put_short(s, w) { \
- put_byte(s, (uch)((w) & 0xff)); \
- put_byte(s, (uch)((ush)(w) >> 8)); \
- }
- #define INSERT_STRING(s, str, match_head) \
- (UPDATE_HASH(s, s->ins_h, s->window[(str) + MIN_MATCH-1]), \
- s->prev[(str) & s->w_mask] = match_head = s->head[s->ins_h], \
- s->head[s->ins_h] = (str))
- #define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD)
- #define check_match(s, start, match, length)
- #define d_code(dist) \
- ((dist) < 256 ? dist_code[dist] : dist_code[256+((dist)>>7)])
- #define FLUSH_BLOCK_ONLY(s, eof) { \
- ct_flush_block(s, (s->block_start >= 0L ? \
- (char*)&s->window[(unsigned)s->block_start] : \
- (char*)Z_NULL), (long)s->strstart - s->block_start, (eof)); \
- s->block_start = s->strstart; \
- flush_pending(s->strm); \
- }
- #define FLUSH_BLOCK(s, eof) { \
- FLUSH_BLOCK_ONLY(s, eof); \
- if (s->strm->avail_out == 0) return 1; \
- }
- #define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len)
- #define MAX(a,b) (a >= b ? a : b)
- #define Buf_size (8 * 2*sizeof(char))
- #define smaller(tree, n, m, depth) \
- (tree[n].Freq < tree[m].Freq || \
- (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))
- #define pqremove(s, tree, top) \
- {\
- top = s->heap[SMALLEST]; \
- s->heap[SMALLEST] = s->heap[s->heap_len--]; \
- pqdownheap(s, tree, SMALLEST); \
- }
- #ifndef local
- # define local static
- #endif
- #ifndef __P
- #define __P(args) args
- #endif
- #define ZALLOC(strm, items, size) \
- (*((strm)->zalloc))((strm)->opaque, (items), (size))
- #define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidp)(addr))
- #define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
- #define Assert(cond,msg)
- #ifndef Byte
- typedef unsigned char Byte; /* 8 bits */
- #endif
- #ifndef uInt
- typedef unsigned int uInt; /* may be 16 or 32 bits */
- #endif
- #ifndef uLong
- typedef unsigned long uLong; /* 32 bits or more */
- #endif
- typedef Byte *voidp;
- typedef voidp gzFile;
- typedef unsigned char uch;
- typedef unsigned long ulg;
- typedef unsigned short ush;
- typedef ush Pos;
- typedef unsigned IPos;
- typedef voidp (*alloc_func) __P((voidp opaque, uInt items, uInt size));
- typedef void (*free_func) __P((voidp opaque, voidp address));
- typedef uLong (*check_func) __P((uLong check, Byte *buf, uInt len));
- typedef struct z_stream_s {
- Byte *next_in; /* next input byte */
- uInt avail_in; /* number of bytes available at next_in */
- uLong total_in; /* total nb of input bytes read so far */
- Byte *next_out; /* next output byte should be put there */
- uInt avail_out; /* remaining free space at next_out */
- uLong total_out; /* total nb of bytes output so far */
- char *msg; /* last error message, NULL if no error */
- struct internal_state *state; /* not visible by applications */
- alloc_func zalloc; /* used to allocate the internal state */
- free_func zfree; /* used to free the internal state */
- voidp opaque; /* private data object passed to zalloc and zfree */
- Byte data_type; /* best guess about the data type: ascii or binary */
- } z_stream;
- typedef struct gz_stream {
- z_stream stream;
- int z_err; /* error code for last stream operation */
- int z_eof; /* set if end of input file */
- FILE *file; /* .gz file */
- Byte *inbuf; /* input buffer */
- Byte *outbuf; /* output buffer */
- uLong crc; /* crc32 of uncompressed data */
- char *msg; /* error message */
- char *path; /* path name for debugging only */
- int transparent; /* 1 if input file is not a .gz file */
- char mode; /* 'w' or 'r' */
- } gz_stream;
- /* Data structure describing a single value and its code string. */
- typedef struct ct_data_s {
- union {
- ush freq; /* frequency count */
- ush code; /* bit string */
- } fc;
- union {
- ush dad; /* father node in Huffman tree */
- ush len; /* length of bit string */
- } dl;
- } ct_data;
- struct static_tree_desc_s {
- ct_data *static_tree; /* static tree or NULL */
- int *extra_bits; /* extra bits for each code or NULL */
- int extra_base; /* base index for extra_bits */
- int elems; /* max number of elements in the tree */
- int max_length; /* max bit length for the codes */
- };
- typedef struct static_tree_desc_s static_tree_desc;
- typedef struct tree_desc_s {
- ct_data *dyn_tree; /* the dynamic tree */
- int max_code; /* largest code with non zero frequency */
- static_tree_desc *stat_desc; /* the corresponding static tree */
- } tree_desc;
- typedef struct inflate_huft_s inflate_huft;
- struct inflate_huft_s {
- union {
- struct {
- char Exop; /* number of extra bits or operation */
- char Bits; /* number of bits in this code or subcode */
- } what;
- Byte *pad; /* pad structure to a power of 2 (4 bytes for */
- } word; /* 16-bit, 8 bytes for 32-bit machines) */
- union {
- uInt Base; /* literal, length base, or distance base */
- inflate_huft *Next; /* pointer to next level of table */
- } more;
- };
- /* inflate codes private state */
- struct inflate_codes_state {
- /* mode */
- enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
- START, /* x: set up for LEN */
- LEN, /* i: get length/literal/eob next */
- LENEXT, /* i: getting length extra (have base) */
- DIST, /* i: get distance next */
- DISTEXT, /* i: getting distance extra */
- COPY, /* o: copying bytes in window, waiting for space */
- LIT, /* o: got literal, waiting for output space */
- WASH, /* o: got eob, possibly still output waiting */
- END, /* x: got eob and all data flushed */
- BAD} /* x: got error */
- mode; /* current inflate_codes mode */
- /* mode dependent information */
- uInt len;
- union {
- struct {
- inflate_huft *tree; /* pointer into tree */
- uInt need; /* bits needed */
- } code; /* if LEN or DIST, where in tree */
- uInt lit; /* if LIT, literal */
- struct {
- uInt get; /* bits to get for extra */
- uInt dist; /* distance back to copy from */
- } copy; /* if EXT or COPY, where and how much */
- } sub; /* submode */
- /* mode independent information */
- Byte lbits; /* ltree bits decoded per branch */
- Byte dbits; /* dtree bits decoder per branch */
- inflate_huft *ltree; /* literal/length/eob tree */
- inflate_huft *dtree; /* distance tree */
- };
- /* inflate blocks semi-private state */
- struct inflate_blocks_state {
- /* mode */
- enum {
- TYPE, /* get type bits (3, including end bit) */
- LENS, /* get lengths for stored */
- STORED, /* processing stored block */
- TABLE, /* get table lengths */
- BTREE, /* get bit lengths tree for a dynamic block */
- DTREE, /* get length, distance trees for a dynamic block */
- CODES, /* processing fixed or dynamic block */
- DRY, /* output remaining window bytes */
- DONE, /* finished last block, done */
- INF_ERROR}/* got a data error--stuck here */
- mode; /* current inflate_block mode */
- /* mode dependent information */
- union {
- uInt left; /* if STORED, bytes left to copy */
- struct {
- uInt table; /* table lengths (14 bits) */
- uInt index; /* index into blens (or border) */
- uInt *blens; /* bit lengths of codes */
- uInt bb; /* bit length tree depth */
- inflate_huft *tb; /* bit length decoding tree */
- } trees; /* if DTREE, decoding info for trees */
- struct inflate_codes_state
- *codes; /* if CODES, current state */
- } sub; /* submode */
- uInt last; /* true if this block is the last block */
- /* mode independent information */
- uInt bitk; /* bits in bit buffer */
- uLong bitb; /* bit buffer */
- Byte *window; /* sliding window */
- Byte *end; /* one byte after sliding window */
- Byte *read; /* window read pointer */
- Byte *write; /* window write pointer */
- check_func checkfn; /* check function */
- uLong check; /* check on output */
- };
- typedef struct internal_state {
- z_stream *strm; /* pointer back to this zlib stream */
- int status; /* as the name implies */
- Byte *pending_buf; /* output still pending */
- Byte *pending_out; /* next pending byte to output to the stream */
- int pending; /* nb of bytes in the pending buffer */
- uLong adler; /* adler32 of uncompressed data */
- int noheader; /* suppress zlib header and adler32 */
- Byte data_type; /* UNKNOWN, BINARY or ASCII */
- Byte method; /* STORED (for zip only) or DEFLATED */
- /* used by deflate.c: */
- uInt w_size; /* LZ77 window size (32K by default) */
- uInt w_bits; /* log2(w_size) (8..16) */
- uInt w_mask; /* w_size - 1 */
- Byte *window;
- /* Sliding window. Input bytes are read into the second half of the window,
- * and move to the first half later to keep a dictionary of at least wSize
- * bytes. With this organization, matches are limited to a distance of
- * wSize-MAX_MATCH bytes, but this ensures that IO is always
- * performed with a length multiple of the block size. Also, it limits
- * the window size to 64K, which is quite useful on MSDOS.
- * To do: use the user input buffer as sliding window.
- */
- ulg window_size;
- /* Actual size of window: 2*wSize, except when the user input buffer
- * is directly used as sliding window.
- */
- Pos *prev;
- /* Link to older string with same hash index. To limit the size of this
- * array to 64K, this link is maintained only for the last 32K strings.
- * An index in this array is thus a window index modulo 32K.
- */
- Pos *head; /* Heads of the hash chains or NIL. */
- uInt ins_h; /* hash index of string to be inserted */
- uInt hash_size; /* number of elements in hash table */
- uInt hash_bits; /* log2(hash_size) */
- uInt hash_mask; /* hash_size-1 */
- uInt hash_shift;
- /* Number of bits by which ins_h must be shifted at each input
- * step. It must be such that after MIN_MATCH steps, the oldest
- * byte no longer takes part in the hash key, that is:
- * hash_shift * MIN_MATCH >= hash_bits
- */
- long block_start;
- /* Window position at the beginning of the current output block. Gets
- * negative when the window is moved backwards.
- */
- uInt match_length; /* length of best match */
- IPos prev_match; /* previous match */
- int match_available; /* set if previous match exists */
- uInt strstart; /* start of string to insert */
- uInt match_start; /* start of matching string */
- uInt lookahead; /* number of valid bytes ahead in window */
- uInt prev_length;
- /* Length of the best match at previous step. Matches not greater than this
- * are discarded. This is used in the lazy match evaluation.
- */
- uInt max_chain_length;
- /* To speed up deflation, hash chains are never searched beyond this
- * length. A higher limit improves compression ratio but degrades the
- * speed.
- */
- uInt max_lazy_match;
- /* Attempt to find a better match only when the current match is strictly
- * smaller than this value. This mechanism is used only for compression
- * levels >= 4.
- */
- # define max_insert_length max_lazy_match
- /* Insert new strings in the hash table only if the match length is not
- * greater than this length. This saves time but degrades compression.
- * max_insert_length is used only for compression levels <= 3.
- */
- int level; /* compression level (1..9) */
- int strategy; /* favor or force Huffman coding*/
- uInt good_match;
- /* Use a faster search when the previous match is longer than this */
- int nice_match; /* Stop searching when current match exceeds this */
- /* used by trees.c: */
- ct_data dyn_ltree[HEAP_SIZE]; /* literal and length tree */
- ct_data dyn_dtree[2*D_CODES+1]; /* distance tree */
- ct_data bl_tree[2*BL_CODES+1]; /* Huffman tree for the bit lengths */
- tree_desc l_desc; /* descriptor for literal tree */
- tree_desc d_desc; /* descriptor for distance tree */
- tree_desc bl_desc; /* descriptor for bit length tree */
- ush bl_count[MAX_BITS+1];
- /* number of codes at each bit length for an optimal tree */
- int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
- int heap_len; /* number of elements in the heap */
- int heap_max; /* element of largest frequency */
- /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
- * The same heap array is used to build all trees.
- */
- uch depth[2*L_CODES+1];
- /* Depth of each subtree used as tie breaker for trees of equal frequency
- */
- uch *l_buf; /* buffer for literals or lengths */
- uInt lit_bufsize;
- /* Size of match buffer for literals/lengths. There are 4 reasons for
- * limiting lit_bufsize to 64K:
- * - frequencies can be kept in 16 bit counters
- * - if compression is not successful for the first block, all input
- * data is still in the window so we can still emit a stored block even
- * when input comes from standard input. (This can also be done for
- * all blocks if lit_bufsize is not greater than 32K.)
- * - if compression is not successful for a file smaller than 64K, we can
- * even emit a stored file instead of a stored block (saving 5 bytes).
- * This is applicable only for zip (not gzip or zlib).
- * - creating new Huffman trees less frequently may not provide fast
- * adaptation to changes in the input data statistics. (Take for
- * example a binary file with poorly compressible code followed by
- * a highly compressible string table.) Smaller buffer sizes give
- * fast adaptation but have of course the overhead of transmitting
- * trees more frequently.
- * - I can't count above 4
- */
- uInt last_lit; /* running index in l_buf */
- ush *d_buf;
- /* Buffer for distances. To simplify the code, d_buf and l_buf have
- * the same number of elements. To use different lengths, an extra flag
- * array would be necessary.
- */
- ulg opt_len; /* bit length of current block with optimal trees */
- ulg static_len; /* bit length of current block with static trees */
- ulg compressed_len; /* total bit length of compressed file */
- uInt matches; /* number of string matches in current block */
- #ifdef DEBUG
- ulg bits_sent; /* bit length of the compressed data */
- #endif
- ush bi_buf;
- /* Output buffer. bits are inserted starting at the bottom (least
- * significant bits).
- */
- int bi_valid;
- /* Number of valid bits in bi_buf. All bits above the last valid bit
- * are always zero.
- */
- /* mode */
- enum {
- METHOD, /* waiting for method byte */
- FLAG, /* waiting for flag byte */
- //START, /* make new blocks state */
- BLOCKS, /* decompressing blocks */
- CHECK4, /* four check bytes to go */
- CHECK3, /* three check bytes to go */
- CHECK2, /* two check bytes to go */
- CHECK1, /* one check byte to go */
- //DONE, /* finished check, done */
- //INF_ERROR/* got an error--stay here */
- }
- mode; /* current inflate mode */
- /* mode dependent information */
- union {
- uInt method; /* if FLAGS, method byte */
- struct inflate_blocks_state
- *blocks; /* if BLOCKS, current state */
- struct {
- uLong was; /* computed check value */
- uLong need; /* stream check value */
- } check; /* if CHECK, check values to compare */
- } sub; /* submode */
- /* mode independent information */
- int nowrap; /* flag for no wrapper */
- uInt wbits; /* log2(window size) (8..15, defaults to 15) */
- } deflate_state;
- typedef struct config_s {
- ush good_length; /* reduce lazy search above this match length */
- ush max_lazy; /* do not perform lazy search above this match length */
- ush nice_length; /* quit search above this match length */
- ush max_chain;
- } config;
- char *z_errmsg[] = {
- "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) */
- ""};
- local int base_length[LENGTH_CODES];
- local int extra_lbits[LENGTH_CODES] /* extra bits for each length code */
- = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
- local uch length_code[MAX_MATCH-MIN_MATCH+1];
- local int base_dist[D_CODES];
- local int extra_dbits[D_CODES] /* extra bits for each distance code */
- = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
- local ct_data static_ltree[L_CODES+2];
- local uch dist_code[512];
- local int base_dist[D_CODES];
- local ct_data static_dtree[D_CODES];
- local static_tree_desc static_l_desc =
- {static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS};
- local static_tree_desc static_d_desc =
- {static_dtree, extra_dbits, 0, D_CODES, MAX_BITS};
- local int extra_blbits[BL_CODES]/* extra bits for each bit length code */
- = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
- local static_tree_desc static_bl_desc =
- {(ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS};
- local uch bl_order[BL_CODES]
- = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
- local config configuration_table[10] = {
- /* good lazy nice chain */
- /* 0 */ {0, 0, 0, 0}, /* store only */
- /* 1 */ {4, 4, 8, 4}, /* maximum speed, no lazy matches */
- /* 2 */ {4, 5, 16, 8},
- /* 3 */ {4, 6, 32, 32},
- /* 4 */ {4, 4, 16, 16}, /* lazy matches */
- /* 5 */ {8, 16, 32, 32},
- /* 6 */ {8, 16, 128, 128},
- /* 7 */ {8, 32, 128, 256},
- /* 8 */ {32, 128, 258, 1024},
- /* 9 */ {32, 258, 258, 4096}}; /* maximum compression */
- #define FIXEDH 530 /* number of hufts used by fixed tables */
- local inflate_huft fixed_mem[FIXEDH];
- #define next more.Next
- #define Freq fc.freq
- #define Code fc.code
- #define Dad dl.dad
- #define Len dl.len
- local voidp zcalloc (opaque, items, size)
- voidp opaque;
- unsigned items;
- unsigned size;
- {
- return calloc(items, size);
- }
- local void zcfree (opaque, ptr)
- voidp opaque;
- voidp ptr;
- {
- free(ptr);
- }
- local uLong crc32(crc, buf, len)
- uLong crc;
- Byte *buf;
- uInt len;
- {
- if (buf == Z_NULL) return 0L;
- crc = crc ^ 0xffffffffL;
- if (len) do {
- crc = wm_tool_crc32_tab[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
- } while (--len);
- return crc ^ 0xffffffffL;
- }
- local void zmemcpy(dest, source, len)
- Byte* dest;
- Byte* source;
- uInt len;
- {
- if (len == 0) return;
- do {
- *dest++ = *source++; /* ??? to be unrolled */
- } while (--len != 0);
- }
- local void zmemzero(dest, len)
- Byte* dest;
- uInt len;
- {
- if (len == 0) return;
- do {
- *dest++ = 0; /* ??? to be unrolled */
- } while (--len != 0);
- }
- local uLong adler32(adler, buf, len)
- uLong adler;
- Byte *buf;
- uInt len;
- {
- unsigned long s1 = adler & 0xffff;
- unsigned long s2 = (adler >> 16) & 0xffff;
- int k;
- if (buf == Z_NULL) return 1L;
- while (len > 0) {
- k = len < NMAX ? len : NMAX;
- len -= k;
- while (k >= 16) {
- DO16(buf);
- k -= 16;
- }
- if (k != 0) do {
- DO1(buf);
- } while (--k);
- s1 %= BASE;
- s2 %= BASE;
- }
- return (s2 << 16) | s1;
- }
- local int read_buf(strm, buf, size)
- z_stream *strm;
- char *buf;
- unsigned size;
- {
- unsigned len = strm->avail_in;
- if (len > size) len = size;
- if (len == 0) return 0;
- strm->avail_in -= len;
- if (!strm->state->noheader) {
- strm->state->adler = adler32(strm->state->adler, strm->next_in, len);
- }
- zmemcpy((Byte *)buf, strm->next_in, len);
- strm->next_in += len;
- strm->total_in += len;
- return (int)len;
- }
- local int inflate_trees_free(t, z)
- inflate_huft *t; /* table to free */
- z_stream *z; /* for zfree function */
- /* Free the malloc'ed tables built by huft_build(), which makes a linked
- list of the tables it made, with the links in a dummy first entry of
- each table. */
- {
- register inflate_huft *p, *q;
- /* Don't free fixed trees */
- if (t >= fixed_mem && t <= fixed_mem + FIXEDH)
- return Z_OK;
- /* Go through linked list, freeing from the malloced (t[-1]) address. */
- p = t;
- while (p != Z_NULL)
- {
- q = (--p)->next;
- ZFREE(z,p);
- p = q;
- }
- return Z_OK;
- }
- local void inflate_codes_free(c, z)
- struct inflate_codes_state *c;
- z_stream *z;
- {
- inflate_trees_free(c->dtree, z);
- inflate_trees_free(c->ltree, z);
- ZFREE(z, c);
- }
- local int inflate_blocks_free(s, z, c)
- struct inflate_blocks_state *s;
- z_stream *z;
- uLong *c;
- {
- if (s->checkfn != Z_NULL)
- *c = s->check;
- if (s->mode == BTREE || s->mode == DTREE)
- ZFREE(z, s->sub.trees.blens);
- if (s->mode == CODES)
- inflate_codes_free(s->sub.codes, z);
- ZFREE(z, s->window);
- ZFREE(z, s);
- return Z_OK;
- }
- local int deflateEnd (strm)
- z_stream *strm;
- {
- if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
- TRY_FREE(strm, strm->state->window);
- TRY_FREE(strm, strm->state->prev);
- TRY_FREE(strm, strm->state->head);
- TRY_FREE(strm, strm->state->pending_buf);
- ZFREE(strm, strm->state);
- strm->state = Z_NULL;
- return Z_OK;
- }
- local int inflateEnd(z)
- z_stream *z;
- {
- uLong c;
- if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
- return Z_STREAM_ERROR;
- if (z->state->mode == BLOCKS)
- inflate_blocks_free(z->state->sub.blocks, z, &c);
- ZFREE(z, z->state);
- z->state = Z_NULL;
- return Z_OK;
- }
- local int destroy (s)
- gz_stream *s;
- {
- int err = Z_OK;
- if (!s) return Z_STREAM_ERROR;
- TRYFREE(s->inbuf);
- TRYFREE(s->outbuf);
- TRYFREE((voidp)s->path);
- TRYFREE((voidp)s->msg);
- if (s->stream.state != NULL) {
- if (s->mode == 'w') {
- err = deflateEnd(&(s->stream));
- } else if (s->mode == 'r') {
- err = inflateEnd(&(s->stream));
- }
- }
- if (s->file != NULL && fclose(s->file)) {
- err = Z_ERRNO;
- }
- if (s->z_err < 0) err = s->z_err;
- zcfree((voidp)0, (voidp)s);
- return err;
- }
- local void putLong (file, x)
- FILE *file;
- uLong x;
- {
- int n;
- for (n = 0; n < 4; n++) {
- fputc((int)(x & 0xff), file);
- x >>= 8;
- }
- }
- local uLong getLong (buf)
- Byte *buf;
- {
- uLong x = 0;
- Byte *p = buf+4;
- do {
- x <<= 8;
- x |= *--p;
- } while (p != buf);
- return x;
- }
- local unsigned bi_reverse(code, len)
- unsigned code; /* the value to invert */
- int len; /* its bit length */
- {
- register unsigned res = 0;
- do {
- res |= code & 1;
- code >>= 1, res <<= 1;
- } while (--len > 0);
- return res >> 1;
- }
- local void gen_codes (tree, max_code, bl_count)
- ct_data *tree; /* the tree to decorate */
- int max_code; /* largest code with non zero frequency */
- ush bl_count[]; /* number of codes at each bit length */
- {
- ush next_code[MAX_BITS+1]; /* next code value for each bit length */
- ush code = 0; /* running code value */
- int bits; /* bit index */
- int n; /* code index */
- /* The distribution counts are first used to generate the code values
- * without bit reversal.
- */
- for (bits = 1; bits <= MAX_BITS; bits++) {
- next_code[bits] = code = (code + bl_count[bits-1]) << 1;
- }
- /* Check that the bit counts in bl_count are consistent. The last code
- * must be all ones.
- */
- Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
- "inconsistent bit counts");
- for (n = 0; n <= max_code; n++) {
- int len = tree[n].Len;
- if (len == 0) continue;
- /* Now reverse the bits */
- tree[n].Code = bi_reverse(next_code[len]++, len);
- }
- }
- local void ct_static_init()
- {
- int n; /* iterates over tree elements */
- int bits; /* bit counter */
- int length; /* length value */
- int code; /* code value */
- int dist; /* distance index */
- ush bl_count[MAX_BITS+1];
- /* number of codes at each bit length for an optimal tree */
- /* Initialize the mapping length (0..255) -> length code (0..28) */
- length = 0;
- for (code = 0; code < LENGTH_CODES-1; code++) {
- base_length[code] = length;
- for (n = 0; n < (1<<extra_lbits[code]); n++) {
- length_code[length++] = (uch)code;
- }
- }
- Assert (length == 256, "ct_static_init: length != 256");
- /* Note that the length 255 (match length 258) can be represented
- * in two different ways: code 284 + 5 bits or code 285, so we
- * overwrite length_code[255] to use the best encoding:
- */
- length_code[length-1] = (uch)code;
- /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
- dist = 0;
- for (code = 0 ; code < 16; code++) {
- base_dist[code] = dist;
- for (n = 0; n < (1<<extra_dbits[code]); n++) {
- dist_code[dist++] = (uch)code;
- }
- }
- Assert (dist == 256, "ct_static_init: dist != 256");
- dist >>= 7; /* from now on, all distances are divided by 128 */
- for ( ; code < D_CODES; code++) {
- base_dist[code] = dist << 7;
- for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) {
- dist_code[256 + dist++] = (uch)code;
- }
- }
- Assert (dist == 256, "ct_static_init: 256+dist != 512");
- /* Construct the codes of the static literal tree */
- for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
- n = 0;
- while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;
- while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;
- while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;
- while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;
- /* Codes 286 and 287 do not exist, but we must include them in the
- * tree construction to get a canonical Huffman tree (longest code
- * all ones)
- */
- gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count);
- /* The static distance tree is trivial: */
- for (n = 0; n < D_CODES; n++) {
- static_dtree[n].Len = 5;
- static_dtree[n].Code = bi_reverse(n, 5);
- }
- }
- local void init_block(s)
- deflate_state *s;
- {
- int n; /* iterates over tree elements */
- /* Initialize the trees. */
- for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0;
- for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0;
- for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0;
- s->dyn_ltree[END_BLOCK].Freq = 1;
- s->opt_len = s->static_len = 0L;
- s->last_lit = s->matches = 0;
- }
- local void ct_init(s)
- deflate_state *s;
- {
- if (static_dtree[0].Len == 0) {
- ct_static_init(); /* To do: at compile time */
- }
- s->compressed_len = 0L;
- s->l_desc.dyn_tree = s->dyn_ltree;
- s->l_desc.stat_desc = &static_l_desc;
- s->d_desc.dyn_tree = s->dyn_dtree;
- s->d_desc.stat_desc = &static_d_desc;
- s->bl_desc.dyn_tree = s->bl_tree;
- s->bl_desc.stat_desc = &static_bl_desc;
- s->bi_buf = 0;
- s->bi_valid = 0;
- #ifdef DEBUG
- s->bits_sent = 0L;
- #endif
- /* Initialize the first block of the first file: */
- init_block(s);
- }
- local void lm_init (s)
- deflate_state *s;
- {
- register unsigned j;
- s->window_size = (ulg)2L*s->w_size;
- /* Initialize the hash table (avoiding 64K overflow for 16 bit systems).
- * prev[] will be initialized on the fly.
- */
- s->head[s->hash_size-1] = NIL;
- zmemzero((unsigned char*)s->head, (unsigned int)(s->hash_size-1)*sizeof(*s->head));
- /* Set the default configuration parameters:
- */
- s->max_lazy_match = configuration_table[s->level].max_lazy;
- s->good_match = configuration_table[s->level].good_length;
- s->nice_match = configuration_table[s->level].nice_length;
- s->max_chain_length = configuration_table[s->level].max_chain;
- s->strstart = 0;
- s->block_start = 0L;
- s->lookahead = 0;
- s->match_length = MIN_MATCH-1;
- s->match_available = 0;
- #ifdef ASMV
- match_init(); /* initialize the asm code */
- #endif
- s->ins_h = 0;
- for (j=0; j<MIN_MATCH-1; j++) UPDATE_HASH(s, s->ins_h, s->window[j]);
- /* If lookahead < MIN_MATCH, ins_h is garbage, but this is
- * not important since only literal bytes will be emitted.
- */
- }
- local int deflateReset (strm)
- z_stream *strm;
- {
- deflate_state *s;
- if (strm == Z_NULL || strm->state == Z_NULL ||
- strm->zalloc == Z_NULL || strm->zfree == Z_NULL) return Z_STREAM_ERROR;
- strm->total_in = strm->total_out = 0;
- strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */
- strm->data_type = Z_UNKNOWN;
- s = (deflate_state *)strm->state;
- s->pending = 0;
- s->pending_out = s->pending_buf;
- s->status = s->noheader ? BUSY_STATE : INIT_STATE;
- s->adler = 1;
- ct_init(s);
- lm_init(s);
- return Z_OK;
- }
- local int deflateInit2 (strm, level, method, windowBits, memLevel, strategy)
- z_stream *strm;
- int level;
- int method;
- int windowBits;
- int memLevel;
- int strategy;
- {
- deflate_state *s;
- int noheader = 0;
- if (strm == Z_NULL) return Z_STREAM_ERROR;
- strm->msg = Z_NULL;
- if (strm->zalloc == Z_NULL) strm->zalloc = zcalloc;
- if (strm->zfree == Z_NULL) strm->zfree = zcfree;
- if (level == Z_DEFAULT_COMPRESSION) level = 6;
- if (windowBits < 0) { /* undocumented feature: suppress zlib header */
- noheader = 1;
- windowBits = -windowBits;
- }
- if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != DEFLATED ||
- windowBits < 8 || windowBits > 15 || level < 1 || level > 9) {
- return Z_STREAM_ERROR;
- }
- s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state));
- if (s == Z_NULL) return Z_MEM_ERROR;
- strm->state = (struct internal_state *)s;
- s->strm = strm;
- s->noheader = noheader;
- s->w_bits = windowBits;
- s->w_size = 1 << s->w_bits;
- s->w_mask = s->w_size - 1;
- s->hash_bits = memLevel + 7;
- s->hash_size = 1 << s->hash_bits;
- s->hash_mask = s->hash_size - 1;
- s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH);
- s->window = (Byte*) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
- s->prev = (Pos*) ZALLOC(strm, s->w_size, sizeof(Pos));
- s->head = (Pos*) ZALLOC(strm, s->hash_size, sizeof(Pos));
- s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
- s->pending_buf = (uch*) ZALLOC(strm, s->lit_bufsize, 2*sizeof(ush));
- if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
- s->pending_buf == Z_NULL) {
- strm->msg = z_errmsg[1-Z_MEM_ERROR];
- deflateEnd (strm);
- return Z_MEM_ERROR;
- }
- s->d_buf = (ush*) &(s->pending_buf[s->lit_bufsize]);
- s->l_buf = (uch*) &(s->pending_buf[3*s->lit_bufsize]);
- /* We overlay pending_buf and d_buf+l_buf. This works since the average
- * output size for (length,distance) codes is <= 32 bits (worst case
- * is 15+15+13=33).
- */
- s->level = level;
- s->strategy = strategy;
- s->method = (Byte)method;
- return deflateReset(strm);
- }
- local int inflateInit2(z, w)
- z_stream *z;
- int w;
- {
- /* initialize state */
- if (z == Z_NULL)
- return Z_STREAM_ERROR;
- if (z->zalloc == Z_NULL) z->zalloc = zcalloc;
- if (z->zfree == Z_NULL) z->zfree = zcfree;
- z->total_in = z->total_out = 0;
- z->msg = Z_NULL;
- if ((z->state = (struct internal_state *)
- ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
- return Z_MEM_ERROR;
- z->state->mode = METHOD;
- /* handle undocumented nowrap option (no zlib header or check) */
- z->state->nowrap = 0;
- if (w < 0)
- {
- w = - w;
- z->state->nowrap = 1;
- z->state->mode = START;
- }
- /* set window size */
- if (w < 8 || w > 15)
- {
- inflateEnd(z);
- return Z_STREAM_ERROR;
- }
- z->state->wbits = w;
- return Z_OK;
- }
- local void putShortMSB (s, b)
- deflate_state *s;
- uInt b;
- {
- put_byte(s, (Byte)(b >> 8));
- put_byte(s, (Byte)(b & 0xff));
- }
- local void flush_pending(strm)
- z_stream *strm;
- {
- unsigned len = strm->state->pending;
- if (len > strm->avail_out) len = strm->avail_out;
- if (len == 0) return;
- zmemcpy(strm->next_out, strm->state->pending_out, len);
- strm->next_out += len;
- strm->state->pending_out += len;
- strm->total_out += len;
- strm->avail_out -= len;
- strm->state->pending -= len;
- if (strm->state->pending == 0) {
- strm->state->pending_out = strm->state->pending_buf;
- }
- }
- local void fill_window(s)
- deflate_state *s;
- {
- register unsigned n, m;
- unsigned more; /* Amount of free space at the end of the window. */
- do {
- more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);
- /* Deal with !@#$% 64K limit: */
- if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
- more = s->w_size;
- } else if (more == (unsigned)(-1)) {
- /* Very unlikely, but possible on 16 bit machine if strstart == 0
- * and lookahead == 1 (input done one byte at time)
- */
- more--;
- /* If the window is almost full and there is insufficient lookahead,
- * move the upper half to the lower one to make room in the upper half.
- */
- } else if (s->strstart >= s->w_size+MAX_DIST(s)) {
- /* By the IN assertion, the window is not empty so we can't confuse
- * more == 0 with more == 64K on a 16 bit machine.
- */
- memcpy((char*)s->window, (char*)s->window+s->w_size,
- (unsigned)s->w_size);
- s->match_start -= s->w_size;
- s->strstart -= s->w_size; /* we now have strstart >= MAX_DIST */
- s->block_start -= (long) s->w_size;
- for (n = 0; n < s->hash_size; n++) {
- m = s->head[n];
- s->head[n] = (Pos)(m >= s->w_size ? m-s->w_size : NIL);
- }
- for (n = 0; n < s->w_size; n++) {
- m = s->prev[n];
- s->prev[n] = (Pos)(m >= s->w_size ? m-s->w_size : NIL);
- /* If n is not on any hash chain, prev[n] is garbage but
- * its value will never be used.
- */
- }
- more += s->w_size;
- }
- if (s->strm->avail_in == 0) return;
- /* If there was no sliding:
- * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
- * more == window_size - lookahead - strstart
- * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
- * => more >= window_size - 2*WSIZE + 2
- * In the BIG_MEM or MMAP case (not yet supported),
- * window_size == input_size + MIN_LOOKAHEAD &&
- * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
- * Otherwise, window_size == 2*WSIZE so more >= 2.
- * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
- */
- Assert(more >= 2, "more < 2");
- n = read_buf(s->strm, (char*)s->window + s->strstart + s->lookahead,
- more);
- s->lookahead += n;
- } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
- }
- /* For 80x86 and 680x0, an optimized version will be provided in match.asm or
- * match.S. The code will be functionally equivalent.
- */
- local int longest_match(s, cur_match)
- deflate_state *s;
- IPos cur_match; /* current match */
- {
- unsigned chain_length = s->max_chain_length;/* max hash chain length */
- register Byte *scan = s->window + s->strstart; /* current string */
- register Byte *match; /* matched string */
- register int len; /* length of current match */
- int best_len = s->prev_length; /* best match length so far */
- IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
- s->strstart - (IPos)MAX_DIST(s) : NIL;
- /* Stop when cur_match becomes <= limit. To simplify the code,
- * we prevent matches with the string of window index 0.
- */
- #ifdef UNALIGNED_OK
- /* Compare two bytes at a time. Note: this is not always beneficial.
- * Try with and without -DUNALIGNED_OK to check.
- */
- register Byte *strend = s->window + s->strstart + MAX_MATCH - 1;
- register ush scan_start = *(ush*)scan;
- register ush scan_end = *(ush*)(scan+best_len-1);
- #else
- register Byte *strend = s->window + s->strstart + MAX_MATCH;
- register Byte scan_end1 = scan[best_len-1];
- register Byte scan_end = scan[best_len];
- #endif
- /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
- * It is easy to get rid of this optimization if necessary.
- */
- Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
- /* Do not waste too much time if we already have a good match: */
- if (s->prev_length >= s->good_match) {
- chain_length >>= 2;
- }
- Assert(s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
- do {
- Assert(cur_match < s->strstart, "no future");
- match = s->window + cur_match;
- /* Skip to next match if the match length cannot increase
- * or if the match length is less than 2:
- */
- #if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
- /* This code assumes sizeof(unsigned short) == 2. Do not use
- * UNALIGNED_OK if your compiler uses a different size.
- */
- if (*(ush*)(match+best_len-1) != scan_end ||
- *(ush*)match != scan_start) continue;
- /* It is not necessary to compare scan[2] and match[2] since they are
- * always equal when the other bytes match, given that the hash keys
- * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
- * strstart+3, +5, ... up to strstart+257. We check for insufficient
- * lookahead only every 4th comparison; the 128th check will be made
- * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
- * necessary to put more guard bytes at the end of the window, or
- * to check more often for insufficient lookahead.
- */
- scan++, match++;
- do {
- } while (*(ush*)(scan+=2) == *(ush*)(match+=2) &&
- *(ush*)(scan+=2) == *(ush*)(match+=2) &&
- *(ush*)(scan+=2) == *(ush*)(match+=2) &&
- *(ush*)(scan+=2) == *(ush*)(match+=2) &&
- scan < strend);
- /* The funny "do {}" generates better code on most compilers */
- /* Here, scan <= window+strstart+257 */
- Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
- if (*scan == *match) scan++;
- len = (MAX_MATCH - 1) - (int)(strend-scan);
- scan = strend - (MAX_MATCH-1);
- #else /* UNALIGNED_OK */
- if (match[best_len] != scan_end ||
- match[best_len-1] != scan_end1 ||
- *match != *scan ||
- *++match != scan[1]) continue;
- /* The check at best_len-1 can be removed because it will be made
- * again later. (This heuristic is not always a win.)
- * It is not necessary to compare scan[2] and match[2] since they
- * are always equal when the other bytes match, given that
- * the hash keys are equal and that HASH_BITS >= 8.
- */
- scan += 2, match++;
- /* We check for insufficient lookahead only every 8th comparison;
- * the 256th check will be made at strstart+258.
- */
- do {
- } while (*++scan == *++match && *++scan == *++match &&
- *++scan == *++match && *++scan == *++match &&
- *++scan == *++match && *++scan == *++match &&
- *++scan == *++match && *++scan == *++match &&
- scan < strend);
- Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
- len = MAX_MATCH - (int)(strend - scan);
- scan = strend - MAX_MATCH;
- #endif /* UNALIGNED_OK */
- if (len > best_len) {
- s->match_start = cur_match;
- best_len = len;
- if (len >= s->nice_match) break;
- #ifdef UNALIGNED_OK
- scan_end = *(ush*)(scan+best_len-1);
- #else
- scan_end1 = scan[best_len-1];
- scan_end = scan[best_len];
- #endif
- }
- } while ((cur_match = s->prev[cur_match & s->w_mask]) > limit
- && --chain_length != 0);
- return best_len;
- }
- local int ct_tally (s, dist, lc)
- deflate_state *s;
- int dist; /* distance of matched string */
- int lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */
- {
- s->d_buf[s->last_lit] = (ush)dist;
- s->l_buf[s->last_lit++] = (uch)lc;
- if (dist == 0) {
- /* lc is the unmatched char */
- s->dyn_ltree[lc].Freq++;
- } else {
- s->matches++;
- /* Here, lc is the match length - MIN_MATCH */
- dist--; /* dist = match distance - 1 */
- Assert((ush)dist < (ush)MAX_DIST(s) &&
- (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
- (ush)d_code(dist) < (ush)D_CODES, "ct_tally: bad match");
- s->dyn_ltree[length_code[lc]+LITERALS+1].Freq++;
- s->dyn_dtree[d_code(dist)].Freq++;
- }
- /* Try to guess if it is profitable to stop the current block here */
- if (s->level > 2 && (s->last_lit & 0xfff) == 0) {
- /* Compute an upper bound for the compressed length */
- ulg out_length = (ulg)s->last_lit*8L;
- ulg in_length = (ulg)s->strstart - s->block_start;
- int dcode;
- for (dcode = 0; dcode < D_CODES; dcode++) {
- out_length += (ulg)s->dyn_dtree[dcode].Freq *
- (5L+extra_dbits[dcode]);
- }
- out_length >>= 3;
- if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1;
- }
- return (s->last_lit == s->lit_bufsize-1);
- /* We avoid equality with lit_bufsize because of wraparound at 64K
- * on 16 bit machines and because stored blocks are restricted to
- * 64K-1 bytes.
- */
- }
- local void set_data_type(s)
- deflate_state *s;
- {
- int n = 0;
- unsigned ascii_freq = 0;
- unsigned bin_freq = 0;
- while (n < 7) bin_freq += s->dyn_ltree[n++].Freq;
- while (n < 128) ascii_freq += s->dyn_ltree[n++].Freq;
- while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq;
- s->data_type = (Byte)(bin_freq > (ascii_freq >> 2) ? BINARY : ASCII);
- }
- local void pqdownheap(s, tree, k)
- deflate_state *s;
- ct_data *tree; /* the tree to restore */
- int k; /* node to move down */
- {
- int v = s->heap[k];
- int j = k << 1; /* left son of k */
- while (j <= s->heap_len) {
- /* Set j to the smallest of the two sons: */
- if (j < s->heap_len &&
- smaller(tree, s->heap[j+1], s->heap[j], s->depth)) {
- j++;
- }
- /* Exit if v is smaller than both sons */
- if (smaller(tree, v, s->heap[j], s->depth)) break;
- /* Exchange v with the smallest son */
- s->heap[k] = s->heap[j]; k = j;
- /* And continue down the tree, setting j to the left son of k */
- j <<= 1;
- }
- s->heap[k] = v;
- }
- local void gen_bitlen(s, desc)
- deflate_state *s;
- tree_desc *desc; /* the tree descriptor */
- {
- ct_data *tree = desc->dyn_tree;
- int max_code = desc->max_code;
- ct_data *stree = desc->stat_desc->static_tree;
- int *extra = desc->stat_desc->extra_bits;
- int base = desc->stat_desc->extra_base;
- int max_length = desc->stat_desc->max_length;
- int h; /* heap index */
- int n, m; /* iterate over the tree elements */
- int bits; /* bit length */
- int xbits; /* extra bits */
- ush f; /* frequency */
- int overflow = 0; /* number of elements with bit length too large */
- for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0;
- /* In a first pass, compute the optimal bit lengths (which may
- * overflow in the case of the bit length tree).
- */
- tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */
- for (h = s->heap_max+1; h < HEAP_SIZE; h++) {
- n = s->heap[h];
- bits = tree[tree[n].Dad].Len + 1;
- if (bits > max_length) bits = max_length, overflow++;
- tree[n].Len = (ush)bits;
- /* We overwrite tree[n].Dad which is no longer needed */
- if (n > max_code) continue; /* not a leaf node */
- s->bl_count[bits]++;
- xbits = 0;
- if (n >= base) xbits = extra[n-base];
- f = tree[n].Freq;
- s->opt_len += (ulg)f * (bits + xbits);
- if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits);
- }
- if (overflow == 0) return;
- /* This happens for example on obj2 and pic of the Calgary corpus */
- /* Find the first bit length which could increase: */
- do {
- bits = max_length-1;
- while (s->bl_count[bits] == 0) bits--;
- s->bl_count[bits]--; /* move one leaf down the tree */
- s->bl_count[bits+1] += 2; /* move one overflow item as its brother */
- s->bl_count[max_length]--;
- /* The brother of the overflow item also moves one step up,
- * but this does not affect bl_count[max_length]
- */
- overflow -= 2;
- } while (overflow > 0);
- /* Now recompute all bit lengths, scanning in increasing frequency.
- * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
- * lengths instead of fixing only the wrong ones. This idea is taken
- * from 'ar' written by Haruhiko Okumura.)
- */
- for (bits = max_length; bits != 0; bits--) {
- n = s->bl_count[bits];
- while (n != 0) {
- m = s->heap[--h];
- if (m > max_code) continue;
- if (tree[m].Len != (unsigned) bits) {
- s->opt_len += ((long)bits - (long)tree[m].Len)
- *(long)tree[m].Freq;
- tree[m].Len = (ush)bits;
- }
- n--;
- }
- }
- }
- local void build_tree(s, desc)
- deflate_state *s;
- tree_desc *desc; /* the tree descriptor */
- {
- ct_data *tree = desc->dyn_tree;
- ct_data *stree = desc->stat_desc->static_tree;
- int elems = desc->stat_desc->elems;
- int n, m; /* iterate over heap elements */
- int max_code = -1; /* largest code with non zero frequency */
- int node = elems; /* next internal node of the tree */
- int new; /* new node being created */
- /* Construct the initial heap, with least frequent element in
- * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
- * heap[0] is not used.
- */
- s->heap_len = 0, s->heap_max = HEAP_SIZE;
- for (n = 0; n < elems; n++) {
- if (tree[n].Freq != 0) {
- s->heap[++(s->heap_len)] = max_code = n;
- s->depth[n] = 0;
- } else {
- tree[n].Len = 0;
- }
- }
- /* The pkzip format requires that at least one distance code exists,
- * and that at least one bit should be sent even if there is only one
- * possible code. So to avoid special checks later on we force at least
- * two codes of non zero frequency.
- */
- while (s->heap_len < 2) {
- new = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0);
- tree[new].Freq = 1;
- s->depth[new] = 0;
- s->opt_len--; if (stree) s->static_len -= stree[new].Len;
- /* new is 0 or 1 so it does not have extra bits */
- }
- desc->max_code = max_code;
- /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
- * establish sub-heaps of increasing lengths:
- */
- for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n);
- /* Construct the Huffman tree by repeatedly combining the least two
- * frequent nodes.
- */
- do {
- pqremove(s, tree, n); /* n = node of least frequency */
- m = s->heap[SMALLEST]; /* m = node of next least frequency */
- s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */
- s->heap[--(s->heap_max)] = m;
- /* Create a new node father of n and m */
- tree[node].Freq = tree[n].Freq + tree[m].Freq;
- s->depth[node] = (uch) (MAX(s->depth[n], s->depth[m]) + 1);
- tree[n].Dad = tree[m].Dad = (ush)node;
- #ifdef DUMP_BL_TREE
- if (tree == s->bl_tree) {
- fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)",
- node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
- }
- #endif
- /* and insert the new node in the heap */
- s->heap[SMALLEST] = node++;
- pqdownheap(s, tree, SMALLEST);
- } while (s->heap_len >= 2);
- s->heap[--(s->heap_max)] = s->heap[SMALLEST];
- /* At this point, the fields freq and dad are set. We can now
- * generate the bit lengths.
- */
- gen_bitlen(s, (tree_desc *)desc);
- /* The field len is now set, we can generate the bit codes */
- gen_codes ((ct_data *)tree, max_code, s->bl_count);
- }
- local void scan_tree (s, tree, max_code)
- deflate_state *s;
- ct_data *tree; /* the tree to be scanned */
- int max_code; /* and its largest code of non zero frequency */
- {
- int n; /* iterates over all tree elements */
- int prevlen = -1; /* last emitted length */
- int curlen; /* length of current code */
- int nextlen = tree[0].Len; /* length of next code */
- int count = 0; /* repeat count of the current code */
- int max_count = 7; /* max repeat count */
- int min_count = 4; /* min repeat count */
- if (nextlen == 0) max_count = 138, min_count = 3;
- tree[max_code+1].Len = (ush)0xffff; /* guard */
- for (n = 0; n <= max_code; n++) {
- curlen = nextlen; nextlen = tree[n+1].Len;
- if (++count < max_count && curlen == nextlen) {
- continue;
- } else if (count < min_count) {
- s->bl_tree[curlen].Freq += count;
- } else if (curlen != 0) {
- if (curlen != prevlen) s->bl_tree[curlen].Freq++;
- s->bl_tree[REP_3_6].Freq++;
- } else if (count <= 10) {
- s->bl_tree[REPZ_3_10].Freq++;
- } else {
- s->bl_tree[REPZ_11_138].Freq++;
- }
- count = 0; prevlen = curlen;
- if (nextlen == 0) {
- max_count = 138, min_count = 3;
- } else if (curlen == nextlen) {
- max_count = 6, min_count = 3;
- } else {
- max_count = 7, min_count = 4;
- }
- }
- }
- local int build_bl_tree(s)
- deflate_state *s;
- {
- int max_blindex; /* index of last bit length code of non zero freq */
- /* Determine the bit length frequencies for literal and distance trees */
- scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code);
- scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code);
- /* Build the bit length tree: */
- build_tree(s, (tree_desc *)(&(s->bl_desc)));
- /* opt_len now includes the length of the tree representations, except
- * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
- */
- /* Determine the number of bit length codes to send. The pkzip format
- * requires that at least 4 bit length codes be sent. (appnote.txt says
- * 3 but the actual value used is 4.)
- */
- for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {
- if (s->bl_tree[bl_order[max_blindex]].Len != 0) break;
- }
- /* Update opt_len to include the bit length tree and counts */
- s->opt_len += 3*(max_blindex+1) + 5+5+4;
- return max_blindex;
- }
- local void send_bits(s, value, length)
- deflate_state *s;
- int value; /* value to send */
- int length; /* number of bits */
- {
- #ifdef DEBUG
- Assert(length > 0 && length <= 15, "invalid length");
- s->bits_sent += (ulg)length;
- #endif
- /* If not enough room in bi_buf, use (valid) bits from bi_buf and
- * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
- * unused bits in value.
- */
- if (s->bi_valid > (int)Buf_size - length) {
- s->bi_buf |= (value << s->bi_valid);
- put_short(s, s->bi_buf);
- s->bi_buf = (ush)value >> (Buf_size - s->bi_valid);
- s->bi_valid += length - Buf_size;
- } else {
- s->bi_buf |= value << s->bi_valid;
- s->bi_valid += length;
- }
- }
- local void bi_windup(s)
- deflate_state *s;
- {
- if (s->bi_valid > 8) {
- put_short(s, s->bi_buf);
- } else if (s->bi_valid > 0) {
- put_byte(s, (Byte)s->bi_buf);
- }
- s->bi_buf = 0;
- s->bi_valid = 0;
- #ifdef DEBUG
- s->bits_sent = (s->bits_sent+7) & ~7;
- #endif
- }
- local void copy_block(s, buf, len, header)
- deflate_state *s;
- char *buf; /* the input data */
- unsigned len; /* its length */
- int header; /* true if block header must be written */
- {
- bi_windup(s); /* align on byte boundary */
- if (header) {
- put_short(s, (ush)len);
- put_short(s, (ush)~len);
- #ifdef DEBUG
- s->bits_sent += 2*16;
- #endif
- }
- #ifdef DEBUG
- s->bits_sent += (ulg)len<<3;
- #endif
- while (len--) {
- put_byte(s, *buf++);
- }
- }
- local void compress_block(s, ltree, dtree)
- deflate_state *s;
- ct_data *ltree; /* literal tree */
- ct_data *dtree; /* distance tree */
- {
- unsigned dist; /* distance of matched string */
- int lc; /* match length or unmatched char (if dist == 0) */
- unsigned lx = 0; /* running index in l_buf */
- unsigned code; /* the code to send */
- int extra; /* number of extra bits to send */
- if (s->last_lit != 0) do {
- dist = s->d_buf[lx];
- lc = s->l_buf[lx++];
- if (dist == 0) {
- send_code(s, lc, ltree); /* send a literal byte */
- } else {
- /* Here, lc is the match length - MIN_MATCH */
- code = length_code[lc];
- send_code(s, code+LITERALS+1, ltree); /* send the length code */
- extra = extra_lbits[code];
- if (extra != 0) {
- lc -= base_length[code];
- send_bits(s, lc, extra); /* send the extra length bits */
- }
- dist--; /* dist is now the match distance - 1 */
- code = d_code(dist);
- Assert (code < D_CODES, "bad d_code");
- send_code(s, code, dtree); /* send the distance code */
- extra = extra_dbits[code];
- if (extra != 0) {
- dist -= base_dist[code];
- send_bits(s, dist, extra); /* send the extra distance bits */
- }
- } /* literal or match pair ? */
- /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
- Assert(s->pending < s->lit_bufsize + 2*lx, "pendingBuf overflow");
- } while (lx < s->last_lit);
- send_code(s, END_BLOCK, ltree);
- }
- local void send_tree (s, tree, max_code)
- deflate_state *s;
- ct_data *tree; /* the tree to be scanned */
- int max_code; /* and its largest code of non zero frequency */
- {
- int n; /* iterates over all tree elements */
- int prevlen = -1; /* last emitted length */
- int curlen; /* length of current code */
- int nextlen = tree[0].Len; /* length of next code */
- int count = 0; /* repeat count of the current code */
- int max_count = 7; /* max repeat count */
- int min_count = 4; /* min repeat count */
- /* tree[max_code+1].Len = -1; */ /* guard already set */
- if (nextlen == 0) max_count = 138, min_count = 3;
- for (n = 0; n <= max_code; n++) {
- curlen = nextlen; nextlen = tree[n+1].Len;
- if (++count < max_count && curlen == nextlen) {
- continue;
- } else if (count < min_count) {
- do { send_code(s, curlen, s->bl_tree); } while (--count != 0);
- } else if (curlen != 0) {
- if (curlen != prevlen) {
- send_code(s, curlen, s->bl_tree); count--;
- }
- Assert(count >= 3 && count <= 6, " 3_6?");
- send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2);
- } else if (count <= 10) {
- send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3);
- } else {
- send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7);
- }
- count = 0; prevlen = curlen;
- if (nextlen == 0) {
- max_count = 138, min_count = 3;
- } else if (curlen == nextlen) {
- max_count = 6, min_count = 3;
- } else {
- max_count = 7, min_count = 4;
- }
- }
- }
- local void send_all_trees(s, lcodes, dcodes, blcodes)
- deflate_state *s;
- int lcodes, dcodes, blcodes; /* number of codes for each tree */
- {
- int rank; /* index in bl_order */
- Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
- Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
- "too many codes");
- send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */
- send_bits(s, dcodes-1, 5);
- send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */
- for (rank = 0; rank < blcodes; rank++) {
- send_bits(s, s->bl_tree[bl_order[rank]].Len, 3);
- }
- send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */
- send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */
- }
- ulg ct_flush_block(s, buf, stored_len, eof)
- deflate_state *s;
- char *buf; /* input block, or NULL if too old */
- ulg stored_len; /* length of input block */
- int eof; /* true if this is the last block for a file */
- {
- ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
- int max_blindex; /* index of last bit length code of non zero freq */
- /* Check if the file is ascii or binary */
- if (s->data_type == UNKNOWN) set_data_type(s);
- /* Construct the literal and distance trees */
- build_tree(s, (tree_desc *)(&(s->l_desc)));
- build_tree(s, (tree_desc *)(&(s->d_desc)));
- /* At this point, opt_len and static_len are the total bit lengths of
- * the compressed block data, excluding the tree representations.
- */
- /* Build the bit length tree for the above two trees, and get the index
- * in bl_order of the last bit length code to send.
- */
- max_blindex = build_bl_tree(s);
- /* Determine the best encoding. Compute first the block length in bytes */
- opt_lenb = (s->opt_len+3+7)>>3;
- static_lenb = (s->static_len+3+7)>>3;
- if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
- /* If compression failed and this is the first and last block,
- * and if the .zip file can be seeked (to rewrite the local header),
- * the whole file is transformed into a stored file:
- */
- if (stored_len+4 <= opt_lenb && buf != (char*)0) {
- /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
- * Otherwise we can't have processed more than WSIZE input bytes since
- * the last block flush, because compression would have been
- * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
- * transform a block into a stored block.
- */
- send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */
- s->compressed_len = (s->compressed_len + 3 + 7) & ~7L;
- s->compressed_len += (stored_len + 4) << 3;
- copy_block(s, buf, (unsigned)stored_len, 1); /* with header */
- } else if (static_lenb == opt_lenb) {
- send_bits(s, (STATIC_TREES<<1)+eof, 3);
- compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree);
- s->compressed_len += 3 + s->static_len;
- } else {
- send_bits(s, (DYN_TREES<<1)+eof, 3);
- send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1,
- max_blindex+1);
- compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree);
- s->compressed_len += 3 + s->opt_len;
- }
- Assert (s->compressed_len == s->bits_sent, "bad compressed size");
- init_block(s);
- if (eof) {
- bi_windup(s);
- s->compressed_len += 7; /* align on byte boundary */
- }
- return s->compressed_len >> 3;
- }
- local int deflate_fast(s, flush)
- deflate_state *s;
- int flush;
- {
- IPos hash_head; /* head of the hash chain */
- int bflush; /* set if current block must be flushed */
- s->prev_length = MIN_MATCH-1;
- for (;;) {
- /* Make sure that we always have enough lookahead, except
- * at the end of the input file. We need MAX_MATCH bytes
- * for the next match, plus MIN_MATCH bytes to insert the
- * string following the next match.
- */
- if (s->lookahead < MIN_LOOKAHEAD) {
- fill_window(s);
- if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) return 1;
- if (s->lookahead == 0) break; /* flush the current block */
- }
- /* Insert the string window[strstart .. strstart+2] in the
- * dictionary, and set hash_head to the head of the hash chain:
- */
- INSERT_STRING(s, s->strstart, hash_head);
- /* Find the longest match, discarding those <= prev_length.
- * At this point we have always match_length < MIN_MATCH
- */
- if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {
- /* To simplify the code, we prevent matches with the string
- * of window index 0 (in particular we have to avoid a match
- * of the string with itself at the start of the input file).
- */
- if (s->strategy != Z_HUFFMAN_ONLY) {
- s->match_length = longest_match (s, hash_head);
- }
- /* longest_match() sets match_start */
- if (s->match_length > s->lookahead) s->match_length = s->lookahead;
- }
- if (s->match_length >= MIN_MATCH) {
- check_match(s, s->strstart, s->match_start, s->match_length);
- bflush = ct_tally(s, s->strstart - s->match_start,
- s->match_length - MIN_MATCH);
- s->lookahead -= s->match_length;
- /* Insert new strings in the hash table only if the match length
- * is not too large. This saves time but degrades compression.
- */
- if (s->match_length <= s->max_insert_length) {
- s->match_length--; /* string at strstart already in hash table */
- do {
- s->strstart++;
- INSERT_STRING(s, s->strstart, hash_head);
- /* strstart never exceeds WSIZE-MAX_MATCH, so there are
- * always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH
- * these bytes are garbage, but it does not matter since
- * the next lookahead bytes will be emitted as literals.
- */
- } while (--s->match_length != 0);
- s->strstart++;
- } else {
- s->strstart += s->match_length;
- s->match_length = 0;
- s->ins_h = s->window[s->strstart];
- UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
- #if MIN_MATCH != 3
- Call UPDATE_HASH() MIN_MATCH-3 more times
- #endif
- }
- } else {
- /* No match, output a literal byte */
- bflush = ct_tally (s, 0, s->window[s->strstart]);
- s->lookahead--;
- s->strstart++;
- }
- if (bflush) FLUSH_BLOCK(s, 0);
- }
- FLUSH_BLOCK(s, flush == Z_FINISH);
- return 0; /* normal exit */
- }
- local int deflate_slow(s, flush)
- deflate_state *s;
- int flush;
- {
- IPos hash_head; /* head of hash chain */
- int bflush; /* set if current block must be flushed */
- /* Process the input block. */
- for (;;) {
- /* Make sure that we always have enough lookahead, except
- * at the end of the input file. We need MAX_MATCH bytes
- * for the next match, plus MIN_MATCH bytes to insert the
- * string following the next match.
- */
- if (s->lookahead < MIN_LOOKAHEAD) {
- fill_window(s);
- if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) return 1;
- if (s->lookahead == 0) break; /* flush the current block */
- }
- /* Insert the string window[strstart .. strstart+2] in the
- * dictionary, and set hash_head to the head of the hash chain:
- */
- INSERT_STRING(s, s->strstart, hash_head);
- /* Find the longest match, discarding those <= prev_length.
- */
- s->prev_length = s->match_length, s->prev_match = s->match_start;
- s->match_length = MIN_MATCH-1;
- if (hash_head != NIL && s->prev_length < s->max_lazy_match &&
- s->strstart - hash_head <= MAX_DIST(s)) {
- /* To simplify the code, we prevent matches with the string
- * of window index 0 (in particular we have to avoid a match
- * of the string with itself at the start of the input file).
- */
- if (s->strategy != Z_HUFFMAN_ONLY) {
- s->match_length = longest_match (s, hash_head);
- }
- /* longest_match() sets match_start */
- if (s->match_length > s->lookahead) s->match_length = s->lookahead;
- if (s->match_length <= 5 && (s->strategy == Z_FILTERED ||
- (s->match_length == MIN_MATCH &&
- s->strstart - s->match_start > TOO_FAR))) {
- /* If prev_match is also MIN_MATCH, match_start is garbage
- * but we will ignore the current match anyway.
- */
- s->match_length = MIN_MATCH-1;
- }
- }
- /* If there was a match at the previous step and the current
- * match is not better, output the previous match:
- */
- if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {
- check_match(s, s->strstart-1, s->prev_match, s->prev_length);
- bflush = ct_tally(s, s->strstart -1 - s->prev_match,
- s->prev_length - MIN_MATCH);
- /* Insert in hash table all strings up to the end of the match.
- * strstart-1 and strstart are already inserted.
- */
- s->lookahead -= s->prev_length-1;
- s->prev_length -= 2;
- do {
- s->strstart++;
- INSERT_STRING(s, s->strstart, hash_head);
- /* strstart never exceeds WSIZE-MAX_MATCH, so there are
- * always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH
- * these bytes are garbage, but it does not matter since the
- * next lookahead bytes will always be emitted as literals.
- */
- } while (--s->prev_length != 0);
- s->match_available = 0;
- s->match_length = MIN_MATCH-1;
- s->strstart++;
- if (bflush) FLUSH_BLOCK(s, 0);
- } else if (s->match_available) {
- /* If there was no match at the previous position, output a
- * single literal. If there was a match but the current match
- * is longer, truncate the previous match to a single literal.
- */
- if (ct_tally (s, 0, s->window[s->strstart-1])) {
- FLUSH_BLOCK_ONLY(s, 0);
- }
- s->strstart++;
- s->lookahead--;
- if (s->strm->avail_out == 0) return 1;
- } else {
- /* There is no previous match to compare with, wait for
- * the next step to decide.
- */
- s->match_available = 1;
- s->strstart++;
- s->lookahead--;
- }
- }
- if (s->match_available) ct_tally (s, 0, s->window[s->strstart-1]);
- FLUSH_BLOCK(s, flush == Z_FINISH);
- return 0;
- }
- local int deflate (strm, flush)
- z_stream *strm;
- int flush;
- {
- if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
- if (strm->next_out == Z_NULL || strm->next_in == Z_NULL) {
- ERR_RETURN(strm, Z_STREAM_ERROR);
- }
- if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR);
- strm->state->strm = strm; /* just in case */
- /* Write the zlib header */
- if (strm->state->status == INIT_STATE) {
- uInt header = (DEFLATED + ((strm->state->w_bits-8)<<4)) << 8;
- uInt level_flags = (strm->state->level-1) >> 1;
- if (level_flags > 3) level_flags = 3;
- header |= (level_flags << 6);
- header += 31 - (header % 31);
- strm->state->status = BUSY_STATE;
- putShortMSB(strm->state, header);
- }
- /* Flush as much pending output as possible */
- if (strm->state->pending != 0) {
- flush_pending(strm);
- if (strm->avail_out == 0) return Z_OK;
- }
- /* User must not provide more input after the first FINISH: */
- if (strm->state->status == FINISH_STATE && strm->avail_in != 0) {
- ERR_RETURN(strm, Z_BUF_ERROR);
- }
- /* Start a new block or continue the current one.
- */
- if (strm->avail_in != 0 ||
- (flush == Z_FINISH && strm->state->status != FINISH_STATE)) {
- if (flush == Z_FINISH) {
- strm->state->status = FINISH_STATE;
- }
- if (strm->state->level <= 3) {
- if (deflate_fast(strm->state, flush)) return Z_OK;
- } else {
- if (deflate_slow(strm->state, flush)) return Z_OK;
- }
- }
- Assert(strm->avail_out > 0, "bug2");
- if (flush != Z_FINISH) return Z_OK;
- if (strm->state->noheader) return Z_STREAM_END;
- /* Write the zlib trailer (adler32) */
- putShortMSB(strm->state, (uInt)(strm->state->adler >> 16));
- putShortMSB(strm->state, (uInt)(strm->state->adler & 0xffff));
- flush_pending(strm);
- /* If avail_out is zero, the application will call deflate again
- * to flush the rest.
- */
- strm->state->noheader = 1; /* write the trailer only once! */
- return strm->state->pending != 0 ? Z_OK : Z_STREAM_END;
- }
- local int gzflush (file, flush)
- gzFile file;
- int flush;
- {
- uInt len;
- int done = 0;
- gz_stream *s = (gz_stream*)file;
- if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
- s->stream.avail_in = 0; /* should be zero already anyway */
- for (;;) {
- len = Z_BUFSIZE - s->stream.avail_out;
- if (len != 0) {
- if (fwrite(s->outbuf, 1, len, s->file) != len) {
- s->z_err = Z_ERRNO;
- return Z_ERRNO;
- }
- s->stream.next_out = s->outbuf;
- s->stream.avail_out = Z_BUFSIZE;
- }
- if (done) break;
- s->z_err = deflate(&(s->stream), flush);
- /* deflate has finished flushing only when it hasn't used up
- * all the available space in the output buffer:
- */
- done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END);
- if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break;
- }
- return s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
- }
- local gzFile gz_open (path, mode, fd)
- char *path;
- char *mode;
- int fd;
- {
- int err;
- char *p = mode;
- gz_stream *s = (gz_stream *)ALLOC(sizeof(gz_stream));
- if (!s) return Z_NULL;
- s->stream.zalloc = (alloc_func)0;
- s->stream.zfree = (free_func)0;
- s->stream.next_in = s->inbuf = Z_NULL;
- s->stream.next_out = s->outbuf = Z_NULL;
- s->stream.avail_in = s->stream.avail_out = 0;
- s->file = NULL;
- s->z_err = Z_OK;
- s->z_eof = 0;
- s->crc = crc32(0L, Z_NULL, 0);
- s->msg = NULL;
- s->transparent = 0;
- s->path = (char*)ALLOC(strlen(path)+1);
- if (s->path == NULL) {
- return destroy(s), (gzFile)Z_NULL;
- }
- strcpy(s->path, path); /* do this early for debugging */
- s->mode = '\0';
- do {
- if (*p == 'r') s->mode = 'r';
- if (*p == 'w') s->mode = 'w';
- } while (*p++);
- if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL;
- if (s->mode == 'w') {
- err = deflateInit2(&(s->stream), Z_BEST_COMPRESSION,
- DEFLATED, -WBITS, MEM_LEVEL, 0);
- /* windowBits is passed < 0 to suppress zlib header */
- s->stream.next_out = s->outbuf = ALLOC(Z_BUFSIZE);
- if (err != Z_OK || s->outbuf == Z_NULL) {
- return destroy(s), (gzFile)Z_NULL;
- }
- } else {
- err = inflateInit2(&(s->stream), -WBITS);
- s->stream.next_in = s->inbuf = ALLOC(Z_BUFSIZE);
- if (err != Z_OK || s->inbuf == Z_NULL) {
- return destroy(s), (gzFile)Z_NULL;
- }
- }
- s->stream.avail_out = Z_BUFSIZE;
- errno = 0;
- s->file = fd < 0 ? fopen(path, mode) : fdopen(fd, mode);
- if (s->file == NULL) {
- return destroy(s), (gzFile)Z_NULL;
- }
- if (s->mode == 'w') {
- /* Write a very simple .gz header:
- */
- fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", GZ_MAGIC_1, GZ_MAGIC_2,
- DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE);
- } else {
- /* Check and skip the header:
- */
- Byte c1 = 0, c2 = 0;
- Byte method = 0;
- Byte flags = 0;
- Byte xflags = 0;
- Byte time[4];
- Byte osCode;
- int c;
- s->stream.avail_in = fread(s->inbuf, 1, 2, s->file);
- if (s->stream.avail_in != 2 || s->inbuf[0] != GZ_MAGIC_1
- || s->inbuf[1] != GZ_MAGIC_2) {
- s->transparent = 1;
- return (gzFile)s;
- }
- s->stream.avail_in = 0;
- err = fscanf(s->file,"%c%c%4c%c%c", &method, &flags, time, &xflags, &osCode);
- if (method != DEFLATED || feof(s->file) || (flags & RESERVED) != 0) {
- s->z_err = Z_DATA_ERROR;
- return (gzFile)s;
- }
- if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
- long len;
- err = fscanf(s->file, "%c%c", &c1, &c2);
- len = c1 + ((long)c2<<8);
- fseek(s->file, len, SEEK_CUR);
- }
- if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
- while ((c = getc(s->file)) != 0 && c != EOF) ;
- }
- if ((flags & COMMENT) != 0) { /* skip the .gz file comment */
- while ((c = getc(s->file)) != 0 && c != EOF) ;
- }
- if ((flags & HEAD_CRC) != 0) { /* skip the header crc */
- err = fscanf(s->file, "%c%c", &c1, &c2);
- }
- if (feof(s->file)) {
- s->z_err = Z_DATA_ERROR;
- }
- }
- return (gzFile)s;
- }
- local gzFile gzopen (path, mode)
- char *path;
- char *mode;
- {
- return gz_open (path, mode, -1);
- }
- local int gzwrite (file, buf, len)
- gzFile file;
- voidp buf;
- unsigned len;
- {
- gz_stream *s = (gz_stream*)file;
- if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
- s->stream.next_in = buf;
- s->stream.avail_in = len;
- while (s->stream.avail_in != 0) {
- if (s->stream.avail_out == 0) {
- s->stream.next_out = s->outbuf;
- if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
- s->z_err = Z_ERRNO;
- break;
- }
- s->stream.avail_out = Z_BUFSIZE;
- }
- s->z_err = deflate(&(s->stream), Z_NO_FLUSH);
- if (s->z_err != Z_OK) break;
- }
- s->crc = crc32(s->crc, buf, len);
- return len - s->stream.avail_in;
- }
- local int gzclose (file)
- gzFile file;
- {
- uInt n;
- int err;
- gz_stream *s = (gz_stream*)file;
- if (s == NULL) return Z_STREAM_ERROR;
- if (s->mode == 'w') {
- err = gzflush (file, Z_FINISH);
- if (err != Z_OK) return destroy((gz_stream *)file);
- putLong (s->file, s->crc);
- putLong (s->file, s->stream.total_in);
- } else if (s->mode == 'r' && s->z_err == Z_STREAM_END) {
- /* slide CRC and original size if they are at the end of inbuf */
- if ((n = s->stream.avail_in) < 8 && !s->z_eof) {
- Byte *p = s->inbuf;
- Byte *q = s->stream.next_in;
- while (n--) { *p++ = *q++; };
- n = s->stream.avail_in;
- n += fread(p, 1, 8, s->file);
- s->stream.next_in = s->inbuf;
- }
- /* check CRC and original size */
- if (n < 8 ||
- getLong(s->stream.next_in) != s->crc ||
- getLong(s->stream.next_in + 4) != s->stream.total_out) {
- s->z_err = Z_DATA_ERROR;
- }
- }
- return destroy((gz_stream *)file);
- }
- /* ========================================================================= */
- static int wm_tool_printf(const char *format, ...)
- {
- int ret;
- va_list ap;
- va_start(ap, format);
- ret = vprintf(format, ap);
- va_end(ap);
- fflush(stdout);
- return ret;
- }
- static unsigned long long wm_tool_crc32_reflect(unsigned long long ref, unsigned char ch)
- {
- int i;
- unsigned long long value = 0;
- for ( i = 1; i < ( ch + 1 ); i++ )
- {
- if( ref & 1 )
- value |= 1 << ( ch - i );
- ref >>= 1;
- }
- return value;
- }
- static unsigned int wm_tool_crc32(unsigned int crc, unsigned char *buffer, int size, wm_tool_crc32_reflect_e mode)
- {
- int i;
- unsigned char temp;
- for (i = 0; i < size; i++)
- {
- if (mode & WM_TOOL_CRC32_REFLECT_INPUT)
- {
- temp = wm_tool_crc32_reflect(buffer[i], 8);
- }
- else
- {
- temp = buffer[i];
- }
- crc = wm_tool_crc32_tab[(crc ^ temp) & 0xff] ^ (crc >> 8);
- }
- return crc ;
- }
- static unsigned int wm_tool_get_crc32(unsigned char *buffer, int size, wm_tool_crc32_reflect_e mode)
- {
- wm_tool_file_crc = wm_tool_crc32(wm_tool_file_crc, buffer, size, mode);
- if (mode & WM_TOOL_CRC32_REFLECT_OUTPUT)
- {
- wm_tool_file_crc = wm_tool_crc32_reflect(wm_tool_file_crc, 32);
- }
- return wm_tool_file_crc;
- }
- static unsigned short wm_tool_get_crc16(unsigned char *ptr, unsigned short count)
- {
- unsigned short crc, i;
- crc = 0;
- while (count--)
- {
- crc = crc ^ (int) *ptr++ << 8;
- for (i = 0; i < 8; i++)
- {
- if (crc & 0x8000)
- crc = crc << 1 ^ 0x1021;
- else
- crc = crc << 1;
- }
- }
- return (crc & 0xFFFF);
- }
- static int wm_tool_char_to_hex(char ch)
- {
- int hex;
- hex = -1;
- if ((ch >= '0') && (ch <= '9'))
- {
- hex = ch - '0';
- }
- else if ((ch >= 'a') && (ch <= 'f'))
- {
- hex = ch - 'a' + 0xa;
- }
- else if ((ch >= 'A') && (ch <= 'F'))
- {
- hex = ch - 'A' + 0xa;
- }
- return hex;
- }
- static int wm_tool_str_to_hex_array(char *str, int cnt, unsigned char array[])
- {
- int hex;
- unsigned char tmp;
- unsigned char *des;
- des = array;
- while (cnt-- > 0)
- {
- hex = wm_tool_char_to_hex(*str++);
- if (hex < 0)
- {
- return -1;
- }
- else
- {
- tmp = (hex << 4) & 0xf0;
- }
- hex = wm_tool_char_to_hex(*str++);
- if (hex < 0)
- {
- return -1;
- }
- else
- {
- tmp = tmp | (hex & 0x0f);
- }
- *des++ = (unsigned char) tmp;
- }
- return ((*str == 0) ? 0 : -1);
- }
- static char *wm_tool_strcasestr(const char *str1, const char *str2)
- {
- char *cp = (char *) str1;
- char *s1, *s2;
- if (!*str2) return (char *) str1;
- while (*cp) {
- s1 = cp;
- s2 = (char *) str2;
- while (*s1 && *s2 && !(tolower((int)*s1) - tolower((int)*s2))) s1++, s2++;
- if (!*s2) return cp;
- cp++;
- }
- return NULL;
- }
- static int wm_tool_get_file_size(const char* filename)
- {
- FILE *fp = fopen(filename, "r");
- if(!fp) return -1;
- fseek(fp,0L,SEEK_END);
- int size = ftell(fp);
- fclose(fp);
- return size;
- }
- static char *wm_tool_get_name(const char *name)
- {
- static char sz_name[WM_TOOL_PATH_MAX] = {0};
- char *p = (char *)name;
- char *q = (char *)name;
- do
- {
- #ifdef __MINGW32__
- p = strchr(p, '\\');
- #else
- p = strchr(p, '/');
- #endif
- if (p)
- {
- p++;
- q = p;
- }
- } while (p);
- strncpy(sz_name, q, WM_TOOL_PATH_MAX - 1);
- #ifdef __MINGW32__
- p = wm_tool_strcasestr(sz_name, ".exe");
- if (p)
- *p = '\0';
- #endif
- return sz_name;
- }
- static void wm_tool_print_usage(const char *name)
- {
- wm_tool_printf("Usage: %s [-h] [-v] [-b] [-o] [-sb] [-ct] [-it]"
- " [-ua] [-ra] [-ih] [-nh] [-un] [-df] [-vs]"
- " [-l] [-c] [-ws] [-ds] [-rs] [-eo] [-dl] [-sl]"
- "\r\n"
- "\r\n"
- "WinnerMicro firmware packaging "
- "and programming "
- "tool\r\n\r\n"
- "options:\r\n\r\n"
- " -h , show usage\r\n"
- " -v , show version\r\n"
- "\r\n"
- " -b binary , original binary file\r\n"
- " -o output_name , output firmware file\r\n"
- " the default is the same as the original binary file name\r\n"
- " -sb second_boot , second boot file, used to generate fls file\r\n"
- " -fc compress_type , whether the firmware is compressed, default is compressed\r\n"
- " <0 | 1> or <uncompress | compress>\r\n"
- " -it image_type , firmware image layout type, default is 0\r\n"
- " <0 | 1>\r\n"
- " -ua update_address , upgrade storage location (hexadecimal)\r\n"
- " the default is 8090000\r\n"
- " -ra run_address , runtime position (hexadecimal)\r\n"
- " the default is 8002400\r\n"
- " -ih image_header , image header storage location (hexadecimal)\r\n"
- " the default is 8002000\r\n"
- " -nh next_image_header , next image header storage location (hexadecimal)\r\n"
- " the default is 0\r\n"
- " -un upd_no , upd no version number (hexadecimal)\r\n"
- " the default is 0\r\n"
- " -df , generate debug firmware for openocd\r\n"
- " -vs version_string , firmware version string, cannot exceed 16 bytes\r\n"
- "\r\n"
- " -l , list the local serial port\r\n"
- " -c serial_name , connect a serial port\r\n"
- #if defined(__APPLE__) && defined(__MACH__)
- " e.g: tty.usbserial0 tty.usbserial3 tty.usbserial7\r\n"
- #elif defined(__MINGW32__) || defined(__CYGWIN__)
- " e.g: COM0 COM3 COM7\r\n"
- #elif defined(__linux__)
- " e.g: ttyUSB0 ttyUSB3 ttyUSB7\r\n"
- #endif
- " -ws baud_rate , set the serial port speed during normal work, default is 115200\r\n"
- " <1200 - 2000000> or <1M | 2M>\r\n"
- " -ds baud_rate , set the serial port speed when downloading, default is 115200\r\n"
- " <115200 | 460800 | 921600 | 1000000 | 2000000> or <1M | 2M>\r\n"
- " -rs reset_action , set device reset method, default is manual control\r\n"
- " <none | at | rts>\r\n"
- " none - manual control device reset\r\n"
- " at - use the at command to control the device reset\r\n"
- " rts - use the serial port rts pin to control the device reset\r\n"
- " -eo erase_option , firmware area erase option\r\n"
- " <all>\r\n"
- " all - erase all areas\r\n"
- " -dl download_firmware , firmware file to be downloaded, default download compressed image\r\n"
- " -sl display_format , display the log information output from the serial port\r\n"
- " <0 | 1> or <str | hex>\r\n"
- " str - string mode display\r\n"
- " hex - hexadecimal format\r\n"
- , wm_tool_get_name(name));
- return;
- }
- static void wm_tool_print_version(const char *name)
- {
- wm_tool_printf("%s %s for xt804\r\nCopyright (C) 2021 AirM2M, Inc.\r\n", wm_tool_get_name(name), wm_tool_version);
- return;
- }
- static int wm_tool_parse_arv(int argc, char *argv[])
- {
- int opt;
- int option_index = 0;
- char *opt_string = "hvlc:b:o:";
- int cnt = 0;
- opterr = 1;/* show err info */
- struct option long_options[] = {
- {"dl", required_argument, NULL, 'd'},
- {"ws", required_argument, NULL, 'w'},
- {"ds", required_argument, NULL, 's'},
- {"sb", required_argument, NULL, 'S'},
- {"it", required_argument, NULL, 'i'},
- {"fc", required_argument, NULL, 'C'},
- {"ua", required_argument, NULL, 'u'},
- {"ra", required_argument, NULL, 'r'},
- {"ih", required_argument, NULL, 'H'},
- {"nh", required_argument, NULL, 'n'},
- {"un", required_argument, NULL, 'U'},
- {"df", no_argument, NULL, 'D'},
- {"vs", required_argument, NULL, 'V'},
- {"rs", required_argument, NULL, 'a'},
- {"eo", required_argument, NULL, 'e'},
- {"sl", required_argument, NULL, 'g'},
- {0, 0, NULL, 0}
- };
- while ( (opt = getopt_long_only(argc, argv, opt_string, long_options, &option_index)) != -1)
- {
- WM_TOOL_DBG_PRINT("%c-%s\r\n", opt, optarg);
- switch (opt)
- {
- case '?':
- case 'h':
- {
- wm_tool_show_usage = 1;
- break;
- }
- case 'v':
- {
- wm_tool_show_ver = 1;
- break;
- }
- case 'l':
- {
- wm_tool_list_com = 1;
- break;
- }
- case 'c':
- {
- #if defined(__MINGW32__)
- strcpy(wm_tool_serial_path, optarg);
- #elif defined(__CYGWIN__)
- sprintf(wm_tool_serial_path, "/dev/ttyS%d", atoi(optarg + strlen("COM")) - 1);
- #else
- sprintf(wm_tool_serial_path, "/dev/%s", optarg);
- #endif
- break;
- }
- case 'w':
- {
- if ('M' == optarg[1])
- wm_tool_normal_serial_rate = (optarg[0] - 0x30) * 1000000;
- else
- wm_tool_normal_serial_rate = strtol(optarg, NULL, 10);
- break;
- }
- case 's':
- {
- if ('M' == optarg[1])
- wm_tool_download_serial_rate = (optarg[0] - 0x30) * 1000000;
- else
- wm_tool_download_serial_rate = strtol(optarg, NULL, 10);
- break;
- }
- case 'a':
- {
- if (0 == strncmp(optarg, "none", strlen("none")))
- wm_tool_dl_action = WM_TOOL_DL_ACTION_NONE;
- else if (0 == strncmp(optarg, "at", strlen("at")))
- wm_tool_dl_action = WM_TOOL_DL_ACTION_AT;
- else if (0 == strncmp(optarg, "rts", strlen("rts")))
- wm_tool_dl_action = WM_TOOL_DL_ACTION_RTS;
- else
- wm_tool_show_usage = 1;
- break;
- }
- case 'e':
- {
- if (0 == strncmp(optarg, "all", strlen("all")))
- wm_tool_dl_erase = WM_TOOL_DL_ERASE_ALL;
- else
- wm_tool_show_usage = 1;
- break;
- }
- case 'd':
- {
- wm_tool_download_image = strdup(optarg);
- if (wm_tool_strcasestr(wm_tool_download_image, ".fls"))
- wm_tool_dl_type = WM_TOOL_DL_TYPE_FLS;
- break;
- }
- case 'o':
- {
- wm_tool_output_image = strdup(optarg);
- break;
- }
- case 'b':
- {
- wm_tool_input_binary = strdup(optarg);
- break;
- }
- case 'S':
- {
- wm_tool_secboot_image = strdup(optarg);
- break;
- }
- case 'i':
- {
- #if 0
- if ('0' == optarg[0])
- wm_tool_image_type = WM_TOOL_LAYOUT_TYPE_1M;
- else if ('3' == optarg[0])
- wm_tool_image_type = WM_TOOL_LAYOUT_TYPE_2M;
- else if (0 == strncmp(optarg, "1M", strlen("1M")))
- wm_tool_image_type = WM_TOOL_LAYOUT_TYPE_1M;
- else if (0 == strncmp(optarg, "2M", strlen("2M")))
- wm_tool_image_type = WM_TOOL_LAYOUT_TYPE_2M;
- else
- #endif
- {
- if (isdigit((int)optarg[0]))
- wm_tool_image_type = atoi(optarg);//optarg[0] - 0x30;
- else
- wm_tool_show_usage = 1;
- }
- break;
- }
- case 'C':
- {
- if ('0' == optarg[0])
- wm_tool_zip_type = WM_TOOL_ZIP_TYPE_UNCOMPRESS;
- else if ('1' == optarg[0])
- wm_tool_zip_type = WM_TOOL_ZIP_TYPE_COMPRESS;
- else if (0 == strncmp(optarg, "compress", strlen("compress")))
- wm_tool_zip_type = WM_TOOL_ZIP_TYPE_COMPRESS;
- else if (0 == strncmp(optarg, "uncompress", strlen("uncompress")))
- wm_tool_zip_type = WM_TOOL_ZIP_TYPE_UNCOMPRESS;
- else
- wm_tool_show_usage = 1;
- break;
- }
- case 'u':
- {
- wm_tool_upd_addr = strtol(optarg, NULL, 16);
- break;
- }
- case 'r':
- {
- wm_tool_run_addr = strtol(optarg, NULL, 16);
- break;
- }
- case 'D':
- {
- wm_tool_is_debug = 1;
- break;
- }
- case 'V':
- {
- strncpy(wm_tool_image_version, optarg, WM_TOOL_IMAGE_VERSION_LEN);
- wm_tool_image_version[WM_TOOL_IMAGE_VERSION_LEN - 1] = '\0';
- break;
- }
- case 'g':
- {
- if ('0' == optarg[0])
- wm_tool_show_log_type = WM_TOOL_SHOW_LOG_STR;
- else if ('1' == optarg[0])
- wm_tool_show_log_type = WM_TOOL_SHOW_LOG_HEX;
- else if (0 == strncmp(optarg, "str", strlen("str")))
- wm_tool_show_log_type = WM_TOOL_SHOW_LOG_STR;
- else if (0 == strncmp(optarg, "hex", strlen("hex")))
- wm_tool_show_log_type = WM_TOOL_SHOW_LOG_HEX;
- else
- wm_tool_show_usage = 1;
- break;
- break;
- }
- case 'H':
- {
- wm_tool_image_header = strtol(optarg, NULL, 16);
- break;
- }
- case 'n':
- {
- wm_tool_next_image_header = strtol(optarg, NULL, 16);
- break;
- }
- case 'U':
- {
- wm_tool_image_upd_no = strtol(optarg, NULL, 16);
- break;
- }
- default:
- {
- wm_tool_show_usage = 1;
- break;
- }
- }
- cnt++;
- }
- return cnt;
- }
- static int wm_tool_pack_image(const char *outfile)
- {
- FILE *fpbin = NULL;
- FILE *fpimg = NULL;
- int readlen = 0;
- int filelen = 0;
- int patch = 0;
- wm_tool_firmware_booter_t fbooter;
- unsigned char buf[WM_TOOL_ONCE_READ_LEN + 1];
- fpbin = fopen(wm_tool_input_binary, "rb");
- if (NULL == fpbin)
- {
- wm_tool_printf("can not open input file [%s].\r\n", wm_tool_input_binary);
- return -2;
- }
- fpimg = fopen(outfile, "wb+");
- if (NULL == fpimg)
- {
- wm_tool_printf("open img file error: [%s].\r\n", outfile);
- fclose(fpbin);
- return -3;
- }
- /* --------deal with upgrade image's CRC begin---- */
- wm_tool_file_crc = 0xFFFFFFFF;
- while (!feof(fpbin))
- {
- memset(buf, 0, sizeof(buf));
- readlen = fread(buf, 1, WM_TOOL_ONCE_READ_LEN, fpbin);
- if(readlen % WM_TOOL_ONCE_READ_LEN != 0)
- {
- patch = WM_TOOL_ONCE_READ_LEN - readlen % WM_TOOL_ONCE_READ_LEN;
- readlen += patch;
- }
- filelen += readlen;
- wm_tool_get_crc32((unsigned char*)buf, readlen, 0);
- }
- /* --------deal with upgrade image's CRC end---- */
- wm_tool_src_binary_len = filelen;
- wm_tool_src_binary_crc = wm_tool_file_crc;
- memset(&fbooter, 0, sizeof(wm_tool_firmware_booter_t));
- strcpy((char *)fbooter.ver, wm_tool_image_version);
- fbooter.magic_no = WM_TOOL_IMG_HEAD_MAGIC_NO;
- fbooter.run_org_checksum = wm_tool_file_crc;
- fbooter.img_type = wm_tool_image_type;
- fbooter.run_img_len = filelen;
- fbooter.run_img_addr = wm_tool_run_addr;
- fbooter.zip_type = WM_TOOL_ZIP_TYPE_UNCOMPRESS;
- fbooter.img_header_addr = wm_tool_image_header;
- fbooter.upgrade_img_addr = wm_tool_upd_addr;
- fbooter.upd_no = wm_tool_image_upd_no;
- fbooter.next_boot = wm_tool_next_image_header;
- /* calculate image's header's CRC */
- wm_tool_file_crc = 0xFFFFFFFF;
- wm_tool_get_crc32((unsigned char *)&fbooter, sizeof(wm_tool_firmware_booter_t) - 4, 0);
- fbooter.hd_checksum = wm_tool_file_crc;
- /* write image's header to output file */
- fwrite(&fbooter, 1, sizeof(wm_tool_firmware_booter_t), fpimg);
- /* write image to output file */
- fseek(fpbin, 0, SEEK_SET);
- while (!feof(fpbin))
- {
- readlen = fread(buf, 1, WM_TOOL_ONCE_READ_LEN, fpbin);
- fwrite(buf, 1, readlen, fpimg);
- }
- /* write dummy data to pad 4byte-aligned */
- if (patch > 0)
- {
- memset(buf, 0, patch);
- fwrite(buf, 1, patch, fpimg);
- }
- if (fpbin)
- {
- fclose(fpbin);
- }
- if (fpimg)
- {
- fclose(fpimg);
- }
- wm_tool_printf("generate normal image completed.\r\n");
- return 0;
- }
- static int wm_tool_pack_gz_image(const char *gzbin, const char *outfile)
- {
- FILE *fpbin = NULL;
- FILE *fpimg = NULL;
- int readlen = 0;
- int filelen = 0;
- int patch = 0;
- wm_tool_firmware_booter_t fbooter;
- unsigned char buf[WM_TOOL_ONCE_READ_LEN + 1];
- fpbin = fopen(gzbin, "rb");
- if (NULL == fpbin)
- {
- wm_tool_printf("can not open input file [%s].\r\n", gzbin);
- return -2;
- }
- fpimg = fopen(outfile, "wb+");
- if (NULL == fpimg)
- {
- wm_tool_printf("create img file error: [%s].\r\n", outfile);
- fclose(fpbin);
- return -3;
- }
- /* --------deal with upgrade image's CRC begin---- */
- wm_tool_file_crc = 0xFFFFFFFF;
- while (!feof(fpbin))
- {
- memset(buf, 0, sizeof(buf));
- readlen = fread(buf, 1, WM_TOOL_ONCE_READ_LEN, fpbin);
- if(readlen % WM_TOOL_ONCE_READ_LEN != 0)
- {
- patch = WM_TOOL_ONCE_READ_LEN - readlen % WM_TOOL_ONCE_READ_LEN;
- readlen += patch;
- }
- filelen += readlen;
- wm_tool_get_crc32((unsigned char*)buf, readlen, 0);
- }
- /* --------deal with upgrade image's CRC end---- */
- memset(&fbooter, 0, sizeof(wm_tool_firmware_booter_t));
- strcpy((char *)fbooter.ver, wm_tool_image_version);
- fbooter.magic_no = WM_TOOL_IMG_HEAD_MAGIC_NO;
- fbooter.run_org_checksum = wm_tool_file_crc;
- fbooter.img_type = wm_tool_image_type;
- fbooter.run_img_len = filelen;
- fbooter.run_img_addr = wm_tool_run_addr;
- fbooter.zip_type = wm_tool_zip_type;
- fbooter.img_header_addr = wm_tool_image_header;
- fbooter.upgrade_img_addr = wm_tool_upd_addr;
- fbooter.upd_no = wm_tool_image_upd_no;
- fbooter.next_boot = wm_tool_next_image_header;
- /* calculate image's header's CRC */
- wm_tool_file_crc = 0xFFFFFFFF;
- wm_tool_get_crc32((unsigned char *)&fbooter, sizeof(wm_tool_firmware_booter_t) - 4, 0);
- fbooter.hd_checksum = wm_tool_file_crc;
- /* write image's header to output file */
- fwrite(&fbooter, 1, sizeof(wm_tool_firmware_booter_t), fpimg);
- /* write image to output file */
- fseek(fpbin, 0, SEEK_SET);
- while (!feof(fpbin))
- {
- readlen = fread(buf, 1, WM_TOOL_ONCE_READ_LEN, fpbin);
- fwrite(buf, 1, readlen, fpimg);
- }
- /* write dummy data to pad 4byte-aligned */
- if (patch > 0)
- {
- memset(buf, 0, patch);
- fwrite(buf, 1, patch, fpimg);
- }
- if (fpbin)
- {
- fclose(fpbin);
- }
- if (fpimg)
- {
- fclose(fpimg);
- }
- wm_tool_printf("generate compressed image completed.\r\n");
- return 0;
- }
- static int wm_tool_pack_dbg_image(const char *image, const char *outfile)
- {
- FILE *fpimg = NULL;
- FILE *fout = NULL;
- unsigned char buf[WM_TOOL_ONCE_READ_LEN + 1];
- int readlen = 0;
- int i;
- wm_tool_firmware_booter_t fbooter;
- int appimg_len = 0;
- int final_len = 0;
- int magic_word = 0;
- fpimg = fopen(image, "rb");
- if (NULL == fpimg)
- {
- wm_tool_printf("open img file error: [%s].\r\n", image);
- return -4;
- }
- magic_word = 0;
- readlen = fread(&magic_word, 1, 4, fpimg);
- if (magic_word != WM_TOOL_IMG_HEAD_MAGIC_NO)
- {
- wm_tool_printf("input [%s] file magic error.\n", image);
- fclose(fpimg);
- return -5;
- }
- fout = fopen(outfile, "wb+");
- if (NULL == fout)
- {
- wm_tool_printf("create img file error [%s].\r\n", outfile);
- fclose(fpimg);
- return -6;
- }
- appimg_len = wm_tool_get_file_size(image);
- /* write 0xFF to output file */
- final_len = WM_TOOL_RUN_IMG_HEADER_LEN + (appimg_len - sizeof(wm_tool_firmware_booter_t));
- for (i = 0; i < (final_len /WM_TOOL_ONCE_READ_LEN); i++)
- {
- memset(buf, 0xff, WM_TOOL_ONCE_READ_LEN);
- fwrite(buf, 1, WM_TOOL_ONCE_READ_LEN, fout);
- }
- memset(buf, 0xff, final_len % WM_TOOL_ONCE_READ_LEN);
- fwrite(buf, 1, final_len % WM_TOOL_ONCE_READ_LEN, fout);
- memset(&fbooter, 0, sizeof(wm_tool_firmware_booter_t));
- /* write sec img to output file */
- fseek(fpimg, 0, SEEK_SET);
- readlen = fread((unsigned char *)&fbooter, 1, sizeof(wm_tool_firmware_booter_t), fpimg);
- fseek(fout, 0, SEEK_SET);
- fwrite(&fbooter, 1, sizeof(wm_tool_firmware_booter_t), fout);
- fseek(fout, WM_TOOL_RUN_IMG_HEADER_LEN, SEEK_SET);
- while (!feof(fpimg))
- {
- readlen = fread(buf, 1, WM_TOOL_ONCE_READ_LEN, fpimg);
- fwrite(buf, 1, readlen, fout);
- }
- if (fpimg)
- {
- fclose(fpimg);
- }
- if (fout)
- {
- fclose(fout);
- }
- wm_tool_printf("generate debug image completed.\r\n");
- return 0;
- }
- static int wm_tool_pack_fls(const char *image, const char *outfile)
- {
- FILE *fpsec = NULL;
- FILE *fpimg = NULL;
- FILE *fout = NULL;
- unsigned char buf[WM_TOOL_ONCE_READ_LEN + 1];
- int readlen = 0;
- int magic_word = 0;
- fpsec = fopen(wm_tool_secboot_image,"rb");
- if (NULL == fpsec)
- {
- wm_tool_printf("can not open input file [%s].\r\n", wm_tool_secboot_image);
- return -2;
- }
- magic_word = 0;
- readlen = fread(&magic_word, 1, 4, fpsec);
- if (magic_word != WM_TOOL_IMG_HEAD_MAGIC_NO)
- {
- wm_tool_printf("input [%s] file magic error.\r\n", wm_tool_secboot_image);
- fclose(fpsec);
- return -3;
- }
- fpimg = fopen(image, "rb");
- if (NULL == fpimg)
- {
- wm_tool_printf("open img file error [%s].\r\n", image);
- fclose(fpsec);
- return -4;
- }
- magic_word = 0;
- readlen = fread(&magic_word, 1, 4, fpimg);
- if (magic_word != WM_TOOL_IMG_HEAD_MAGIC_NO)
- {
- wm_tool_printf("input [%s] file magic error.\r\n", image);
- fclose(fpsec);
- fclose(fpimg);
- return -5;
- }
- fout = fopen(outfile, "wb+");
- if (NULL == fout)
- {
- wm_tool_printf("create img file error [%s].\r\n", outfile);
- fclose(fpsec);
- fclose(fpimg);
- return -6;
- }
- fseek(fpsec, 0, SEEK_SET);
- while (!feof(fpsec))
- {
- readlen = fread(buf, 1, WM_TOOL_ONCE_READ_LEN, fpsec);
- fwrite(buf, 1, readlen, fout);
- }
- fseek(fpimg, 0, SEEK_SET);
- while (!feof(fpimg))
- {
- readlen = fread(buf, 1, WM_TOOL_ONCE_READ_LEN, fpimg);
- fwrite(buf, 1, readlen, fout);
- }
- if (fpsec)
- {
- fclose(fpsec);
- }
- if (fpimg)
- {
- fclose(fpimg);
- }
- if (fout)
- {
- fclose(fout);
- }
- wm_tool_printf("generate flash file completed.\r\n");
- return 0;
- }
- static int wm_tool_gzip_bin(const char *binary, const char *gzbin)
- {
- FILE *bfp;
- gzFile gzfp;
- int ret;
- char buf[1024];
- bfp = fopen(binary, "rb");
- gzfp = gzopen((char *)gzbin, "wb+");
- if (!bfp || !gzfp)
- {
- wm_tool_printf("can not gzip binary.\r\n");
- return -1;
- }
- do {
- ret = fread(buf, 1, sizeof(buf), bfp);
- if (ret > 0)
- {
- ret = gzwrite(gzfp, (voidp)buf, ret);
- if (ret <= 0)
- {
- wm_tool_printf("can not write gzip binary.\r\n");
- return -2;
- }
- }
- } while (ret > 0);
- gzclose(gzfp);
- fclose(bfp);
- wm_tool_printf("compress binary completed.\r\n");
- return 0;
- }
- static int wm_tool_pack_firmware(void)
- {
- int ret;
- char *path;
- char *name;
- char *image;
- char *gzbin;
- char *gzimg;
- char *dbgimg;
- char *fls;
- if (!wm_tool_input_binary)
- return 1;
- if (!wm_tool_output_image)
- {
- char *r = wm_tool_input_binary;
- char *t = wm_tool_input_binary;
- do
- {
- r = strchr(r, '.');
- if (r)
- {
- t = r;
- r++;
- }
- } while (r);
- wm_tool_output_image = malloc(t - wm_tool_input_binary + 1);
- if (!wm_tool_output_image)
- return -1;
- memcpy(wm_tool_output_image, wm_tool_input_binary, t - wm_tool_input_binary);
- wm_tool_output_image[t - wm_tool_input_binary] = '\0';
- }
- char *p = wm_tool_output_image;
- char *q = wm_tool_output_image;
- do
- {
- p = strchr(p, '/');
- if (p)
- {
- p++;
- q = p;
- }
- } while (p);
- /* output file */
- name = strdup(q);
- *q = '\0';
- path = strdup(wm_tool_output_image);
- image = malloc(strlen(path) + strlen(name) + strlen(".img") + 1);
- if (!image)
- return -1;
- sprintf(image, "%s%s.img", path, name);
- if (WM_TOOL_ZIP_TYPE_UNCOMPRESS == wm_tool_zip_type)
- {
- ret = wm_tool_pack_image(image);
- if (ret)
- return ret;
- }
- if (WM_TOOL_ZIP_TYPE_COMPRESS == wm_tool_zip_type)
- {
- gzbin = malloc(strlen(path) + strlen(name) + strlen("_gz.bin") + 1);
- gzimg = malloc(strlen(path) + strlen(name) + strlen("_gz.img") + 1);
- if (!gzbin || !gzimg)
- return -1;
- sprintf(gzbin, "%s%s.bin.gz", path, name);
- sprintf(gzimg, "%s%s_gz.img", path, name);
- ret = wm_tool_gzip_bin(wm_tool_input_binary, gzbin);
- if (ret)
- return ret;
- ret = wm_tool_pack_gz_image(gzbin, gzimg);
- free(gzbin);
- free(gzimg);
- if (ret)
- return ret;
- }
- if (wm_tool_is_debug)
- {
- dbgimg = malloc(strlen(path) + strlen(name) + strlen("_dbg.img") + 1);
- if (!dbgimg)
- return -1;
- sprintf(dbgimg, "%s%s_dbg.img", path, name);
- ret = wm_tool_pack_dbg_image(image, dbgimg);
- free(dbgimg);
- if (ret)
- return ret;
- }
- if (wm_tool_secboot_image)
- {
- fls = malloc(strlen(path) + strlen(name) + strlen(".fls") + 1);
- if (!fls)
- return -1;
- sprintf(fls, "%s%s.fls", path, name);
- ret = wm_tool_pack_fls(image, fls);
- free(fls);
- }
- free(image);
- return ret;
- }
- #ifdef __MINGW32__
- static BOOL wm_tool_signal_proc(DWORD no)
- {
- switch (no)
- {
- case CTRL_C_EVENT:
- wm_tool_signal_proc_entry();
- return(FALSE);
- default:
- return FALSE;
- }
- }
- static void wm_tool_signal_init(void)
- {
- SetConsoleCtrlHandler((PHANDLER_ROUTINE)wm_tool_signal_proc, TRUE);
- }
- static void wm_tool_delay_ms(int ms)
- {
- Sleep(ms);
- return;
- }
- static int wm_tool_uart_set_rts(int boolflag)
- {
- return EscapeCommFunction(wm_tool_uart_handle,((boolflag) ? SETRTS : CLRRTS)) ? 0 : -1;
- }
- static int wm_tool_uart_set_dtr(int boolflag)
- {
- return EscapeCommFunction(wm_tool_uart_handle,((boolflag) ? SETDTR : CLRDTR)) ? 0 : -1;
- }
- static int wm_tool_uart_set_timeout(void)
- {
- BOOL ret;
- COMMTIMEOUTS timeout;
- timeout.ReadIntervalTimeout = MAXDWORD;
- timeout.ReadTotalTimeoutConstant = 0;
- timeout.ReadTotalTimeoutMultiplier = 0;
- timeout.WriteTotalTimeoutConstant = 0;
- timeout.WriteTotalTimeoutMultiplier = 0;
- ret = SetCommTimeouts(wm_tool_uart_handle, &timeout);
- if (ret)
- ret = SetCommMask(wm_tool_uart_handle, EV_TXEMPTY);
- return ret ? 0 : -1;
- }
- static void wm_tool_uart_set_block(int bolck)
- {
- if (bolck)
- wm_tool_uart_block = INFINITE;
- else
- wm_tool_uart_block = 0;
- return;
- }
- static int wm_tool_uart_set_speed(int speed)
- {
- int i;
- int size;
- DCB cfg;
- size = sizeof(wm_tool_uart_speed_array) / sizeof(int);
- for (i= 0; i < size; i++)
- {
- if (speed == wm_tool_uart_name_array[i])
- {
- if (GetCommState(wm_tool_uart_handle, &cfg))
- {
- cfg.DCBlength = sizeof(DCB);
- cfg.BaudRate = wm_tool_uart_speed_array[i];
- cfg.fBinary = TRUE;
- cfg.fParity = FALSE;
- cfg.fDtrControl = DTR_CONTROL_DISABLE;
- cfg.fDsrSensitivity = FALSE;
- cfg.fRtsControl = RTS_CONTROL_DISABLE;
- cfg.ByteSize = 8;
- cfg.StopBits = ONESTOPBIT;
- cfg.fAbortOnError = FALSE;
- cfg.fOutX = FALSE;
- cfg.fInX = FALSE;
- cfg.fErrorChar = FALSE;
- cfg.fNull = FALSE;
- cfg.fOutxCtsFlow = FALSE;
- cfg.fOutxDsrFlow = FALSE;
- cfg.Parity = NOPARITY;
- cfg.fTXContinueOnXoff = FALSE;
- return SetCommState(wm_tool_uart_handle, &cfg) ? 0 : -1;
- }
- else
- {
- return -3;
- }
- }
- }
- return -2;
- }
- static void wm_tool_uart_clear(void)
- {
- PurgeComm(wm_tool_uart_handle, PURGE_RXCLEAR);
- return;
- }
- static int wm_tool_uart_open(const char *device)
- {
- BOOL ret;
- char name[40];
- sprintf(name,"\\\\.\\%s", device);
- wm_tool_uart_handle = CreateFile(name, GENERIC_WRITE | GENERIC_READ,
- 0, NULL, OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
- NULL);
- if (wm_tool_uart_handle == INVALID_HANDLE_VALUE)
- {
- return -1;
- }
- ret = SetupComm(wm_tool_uart_handle, 4096, 4096);
- if (ret)
- {
- ret = wm_tool_uart_set_speed(WM_TOOL_DEFAULT_BAUD_RATE);
- ret |= wm_tool_uart_set_timeout();
- }
- else
- {
- ret = -1;
- }
- return ret;
- }
- static int wm_tool_uart_read(void *data, unsigned int size)
- {
- BOOL ret;
- DWORD wait;
- unsigned long len = 0;
- COMSTAT state;
- DWORD error;
- OVERLAPPED event;
- do
- {
- memset(&event, 0, sizeof(OVERLAPPED));
- event.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- ClearCommError(wm_tool_uart_handle, &error, &state);
- ret = ReadFile(wm_tool_uart_handle, data, size, &len, &event);
- if (!ret)
- {
- if (ERROR_IO_PENDING == GetLastError())
- {
- wait = WaitForSingleObject(event.hEvent, wm_tool_uart_block);
- if (WAIT_OBJECT_0 == wait)
- ret = TRUE;
- }
- }
- } while (wm_tool_uart_block && !len);
- if (ret)
- {
- if (len > 0)
- return (int)len;
- }
- return -1;
- }
- static int wm_tool_uart_write(const void *data, unsigned int size)
- {
- BOOL ret;
- DWORD wait;
- OVERLAPPED event;
- COMSTAT state;
- DWORD error;
- unsigned int snd = 0;
- unsigned long len = 0;
- memset(&event, 0, sizeof(OVERLAPPED));
- event.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- do
- {
- ClearCommError(wm_tool_uart_handle, &error, &state);
- ret = WriteFile(wm_tool_uart_handle, data + snd, size - snd, &len, &event);
- if (!ret)
- {
- if (ERROR_IO_PENDING == GetLastError())
- {
- wait = WaitForSingleObject(event.hEvent, INFINITE);
- if (WAIT_OBJECT_0 == wait)
- ret = TRUE;
- }
- }
- if (ret)
- {
- if ((len > 0) && (snd != size))
- {
- snd += len;
- }
- else
- {
- return size;
- }
- }
- else
- {
- break;
- }
- } while (1);
- return -1;
- }
- static void wm_tool_uart_close(void)
- {
- FlushFileBuffers(wm_tool_uart_handle);
- CloseHandle(wm_tool_uart_handle);
- wm_tool_uart_handle = NULL;
- return;
- }
- static DWORD WINAPI wm_tool_uart_tx_thread(LPVOID arg)
- {
- wm_tool_stdin_to_uart();
- return 0;
- }
- static int wm_tool_create_thread(void)
- {
- HANDLE thread_handle;
- thread_handle = CreateThread(0, 0, wm_tool_uart_tx_thread, NULL, 0, NULL);
- CloseHandle(thread_handle);
- return 0;
- }
- #else
- static void wm_tool_signal_proc(int no)
- {
- wm_tool_signal_proc_entry();
- }
- static void wm_tool_signal_init(void)
- {
- signal(SIGINT, wm_tool_signal_proc);
- }
- static void wm_tool_delay_ms(int ms)
- {
- usleep(ms * 1000);
- return;
- }
- static int wm_tool_uart_set_rts(int boolflag)
- {
- int ret;
- int controlbits;
- ret = ioctl(wm_tool_uart_fd, TIOCMGET, &controlbits);
- if (ret < 0)
- {
- WM_TOOL_DBG_PRINT("TIOCMGET failed!\r\n");
- return ret;
- }
- if (controlbits & TIOCM_RTS)
- {
- WM_TOOL_DBG_PRINT("TIOCM_RTS!, %d!\r\n", boolflag);
- }
- else
- {
- WM_TOOL_DBG_PRINT("~TIOCM_RTS!, %d!\r\n", boolflag);
- }
- if (boolflag)
- controlbits |= TIOCM_RTS;
- else
- controlbits &= ~TIOCM_RTS;
- ret = ioctl(wm_tool_uart_fd, TIOCMSET, &controlbits);
- if (ret < 0)
- {
- WM_TOOL_DBG_PRINT("TIOCMSET failed!\r\n");
- }
- if (ret >= 0)
- ret = 0;
- return ret;
- }
- static int wm_tool_uart_set_dtr(int boolflag)
- {
- int ret;
- int controlbits;
- ret = ioctl(wm_tool_uart_fd, TIOCMGET, &controlbits);
- if (ret < 0)
- {
- WM_TOOL_DBG_PRINT("TIOCMGET failed!\r\n");
- return ret;
- }
- if (controlbits & TIOCM_DTR)
- {
- WM_TOOL_DBG_PRINT("TIOCM_DTR, %d!\r\n", boolflag);
- }
- else
- {
- WM_TOOL_DBG_PRINT("~TIOCM_DTR, %d!\r\n", boolflag);
- }
- if (boolflag)
- controlbits |= TIOCM_DTR;
- else
- controlbits &= ~TIOCM_DTR;
- ret = ioctl(wm_tool_uart_fd, TIOCMSET, &controlbits);
- if (ret < 0)
- {
- WM_TOOL_DBG_PRINT("TIOCMSET failed!\r\n");
- }
- if (ret >= 0)
- ret = 0;
- return ret;
- }
- static void wm_tool_uart_set_block(int bolck)
- {
- int comopt;
- comopt = fcntl(wm_tool_uart_fd, F_GETFL, 0);
- if (bolck)
- fcntl(wm_tool_uart_fd, F_SETFL, comopt & ~O_NDELAY);
- else
- fcntl(wm_tool_uart_fd, F_SETFL, comopt | O_NDELAY);
- return;
- }
- static int wm_tool_uart_set_speed(int speed)
- {
- int i;
- int size;
- int status = -1;
- struct termios opt;
- tcgetattr(wm_tool_uart_fd, &opt);
- size = sizeof(wm_tool_uart_speed_array) / sizeof(int);
- for (i= 0; i < size; i++)
- {
- if (speed == wm_tool_uart_name_array[i])
- {
- cfsetispeed(&opt, wm_tool_uart_speed_array[i]);
- cfsetospeed(&opt, wm_tool_uart_speed_array[i]);
- status = tcsetattr(wm_tool_uart_fd, TCSANOW, &opt);
- break;
- }
- }
- return status;
- }
- static void wm_tool_uart_clear(void)
- {
- tcflush(wm_tool_uart_fd, TCIFLUSH);
- return;
- }
- static int wm_tool_uart_open(const char *device)
- {
- struct termios tty;
- wm_tool_uart_fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY);
- if (-1 == wm_tool_uart_fd)
- {
- return -1;
- }
- tcgetattr(wm_tool_uart_fd, &wm_tool_saved_serial_cfg);
- wm_tool_uart_set_dtr(0);
- tcgetattr(wm_tool_uart_fd, &tty);
- /* databit 8bit */
- tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;
- /* set into raw, no echo mode */
- tty.c_iflag = IGNBRK;
- tty.c_lflag = 0;
- tty.c_oflag = 0;
- tty.c_cflag |= CLOCAL | CREAD;
- tty.c_cflag &= ~CRTSCTS;
- tty.c_cc[VMIN] = 1;
- tty.c_cc[VTIME] = 5;
- /* have no software flow control */
- tty.c_iflag &= ~(IXON|IXOFF|IXANY);
- /* parity none */
- tty.c_cflag &= ~(PARENB | PARODD);
- /* stopbit 1bit */
- tty.c_cflag &= ~CSTOPB;
- tcsetattr(wm_tool_uart_fd, TCSANOW, &tty);
- return wm_tool_uart_set_speed(WM_TOOL_DEFAULT_BAUD_RATE);
- }
- static int wm_tool_uart_read(void *data, unsigned int size)
- {
- return read(wm_tool_uart_fd, data, size);
- }
- static int wm_tool_uart_write(const void *data, unsigned int size)
- {
- int snd = 0;
- int ret = 0;
- do
- {
- ret = write(wm_tool_uart_fd, data + snd, size - snd);
- if (ret > 0)
- {
- snd += ret;
- if (snd == size)
- {
- return size;
- }
- }
- else
- {
- break;
- }
- } while (1);
- return -1;
- }
- static void wm_tool_uart_close(void)
- {
- tcsetattr(wm_tool_uart_fd, TCSANOW, &wm_tool_saved_serial_cfg);
- tcdrain(wm_tool_uart_fd);
- tcflush(wm_tool_uart_fd, TCIOFLUSH);
- close(wm_tool_uart_fd);
- wm_tool_uart_fd = -1;
- return;
- }
- static void *wm_tool_uart_tx_thread(void *arg)
- {
- wm_tool_stdin_to_uart();
- return NULL;
- }
- static int wm_tool_create_thread(void)
- {
- pthread_t thread_id;
- return pthread_create(&thread_id, NULL, wm_tool_uart_tx_thread, NULL);
- }
- #endif
- static void wm_tool_signal_proc_entry(void)
- {
- WM_TOOL_DBG_PRINT("signal exit.\r\n");
- exit(0);
- }
- static void wm_tool_stdin_to_uart(void)
- {
- int ret;
- char buf[WM_TOOL_ONCE_READ_LEN];
- while (1)
- {
- if (fgets(buf, WM_TOOL_ONCE_READ_LEN, stdin))
- {
- ret = wm_tool_uart_write(buf, strlen(buf));
- if (ret <= 0)
- {
- WM_TOOL_DBG_PRINT("failed to write [%s].\r\n", buf);
- }
- }
- }
- return;
- }
- static int wm_tool_show_log_from_serial(void)
- {
- int i;
- int ret;
- unsigned int j = 0;
- unsigned char buf[WM_TOOL_ONCE_READ_LEN + 1];
- ret = wm_tool_uart_open(wm_tool_serial_path);
- if (ret)
- {
- wm_tool_printf("can not open serial\r\n");
- return ret;
- }
- if (WM_TOOL_DEFAULT_BAUD_RATE != wm_tool_normal_serial_rate)
- {
- ret = wm_tool_uart_set_speed(wm_tool_normal_serial_rate);
- if (ret)
- {
- wm_tool_printf("can not set serial baud rate.\r\n");
- wm_tool_uart_close();
- return ret;
- }
- }
- ret = wm_tool_create_thread();
- if (ret)
- {
- wm_tool_printf("can not create thread.\r\n");
- wm_tool_uart_close();
- return ret;
- }
- wm_tool_uart_set_block(0);
- wm_tool_signal_init();
- while (1)
- {
- ret = wm_tool_uart_read(buf, WM_TOOL_ONCE_READ_LEN);
- if (ret > 0)
- {
- if (WM_TOOL_SHOW_LOG_STR == wm_tool_show_log_type)
- {
- buf[ret] = '\0';
- wm_tool_printf("%s", (char *)buf);
- }
- else if (WM_TOOL_SHOW_LOG_HEX == wm_tool_show_log_type)
- {
- for (i = 0; i < ret; i++, j++)
- {
- wm_tool_printf("%02X ", buf[i]);
- if ((j + 1) % 16 == 0)
- {
- wm_tool_printf("\r\n");
- }
- }
- }
- else
- {
- break;
- }
- }
- else
- {
- wm_tool_delay_ms(1);
- }
- }
- wm_tool_uart_close();
- return ret;
- }
- static int wm_tool_set_wifi_chip_speed(int speed)
- {
- int ret;
- if (2000000 == speed)
- {
- ret = wm_tool_uart_write(wm_tool_chip_cmd_b2000000, sizeof(wm_tool_chip_cmd_b2000000));
- }
- else if (1000000 == speed)
- {
- ret = wm_tool_uart_write(wm_tool_chip_cmd_b1000000, sizeof(wm_tool_chip_cmd_b1000000));
- }
- else if (921600 == speed)
- {
- ret = wm_tool_uart_write(wm_tool_chip_cmd_b921600, sizeof(wm_tool_chip_cmd_b921600));
- }
- else if (460800 == speed)
- {
- ret = wm_tool_uart_write(wm_tool_chip_cmd_b460800, sizeof(wm_tool_chip_cmd_b460800));
- }
- else
- {
- ret = wm_tool_uart_write(wm_tool_chip_cmd_b115200, sizeof(wm_tool_chip_cmd_b115200));
- }
- return ret;
- }
- static int wm_tool_send_esc2uart(int ms)
- {
- int i;
- int err = 0;
- unsigned char esc_key = 27;
- for (i = 0; i < (ms / 10); i++)
- {
- err = wm_tool_uart_write(&esc_key, 1);
- wm_tool_delay_ms(10);/* 10-50ms */
- }
- return err;
- }
- static int wm_tool_erase_image(wm_tool_dl_erase_e type)
- {
- int cnt = 0;
- int ret = -1;
- unsigned char ch;
- unsigned char rom_cmd[] = {0x21, 0x0a, 0x00, 0xc3, 0x35, 0x32, 0x00, 0x00, 0x00, 0x02, 0x00, 0xfe, 0x01}; /*2M-8k*/
- WM_TOOL_DBG_PRINT("start erase.\r\n");
- if (WM_TOOL_DL_ERASE_ALL == type)
- {
- wm_tool_printf("erase flash...\r\n");
- ret = wm_tool_uart_write(rom_cmd, sizeof(rom_cmd));
- }
- if (ret <= 0)
- return -1;
- wm_tool_uart_clear();
- wm_tool_uart_set_block(1);
- do
- {
- ret = wm_tool_uart_read(&ch, 1);
- if (ret > 0)
- {
- if (('C' == ch) || ('P' == ch))
- cnt++;
- else
- cnt = 0;
- }
- else
- {
- wm_tool_printf("erase error, errno = %d.\r\n", errno);
- return -2;
- }
- } while (cnt < 3);
- wm_tool_uart_set_block(0);
- wm_tool_printf("erase finish.\r\n");
- return 0;
- }
- static int wm_tool_query_mac(void)
- {
- int ret = -1;
- int err;
- int offset = 0;
- char macstr[32] = {0};
- int len = strlen("MAC:AABBCCDDEEFF\n");/* resp format, ROM "Mac:AABBCCDDEEFF\n", SECBOOT "MAC:AABBCCDDEEFF\n" */
- unsigned char macaddr[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
- wm_tool_uart_clear();
- wm_tool_uart_set_block(1);
- err = wm_tool_uart_write(wm_tool_chip_cmd_get_mac, sizeof(wm_tool_chip_cmd_get_mac));
- if (err > 0)
- {
- do
- {
- err = wm_tool_uart_read((unsigned char *)(macstr + offset), sizeof(macstr) - 1 - offset);
- if (err > 0)
- {
- offset += err;
- if (offset >= len)
- {
- macstr[len - 1] = '\0';/* \n -> 0 */
- err = wm_tool_str_to_hex_array(macstr + strlen("MAC:"), 6, macaddr);
- if (strstr(macstr, "Mac:"))
- {
- err = wm_tool_str_to_hex_array(macstr + strlen("MAC:"), 6, macaddr);
- }
- else
- {
- err = 0;
- }
- if (!err)
- {
- wm_tool_printf("mac %02X-%02X-%02X-%02X-%02X-%02X.\r\n", macaddr[0],
- macaddr[1], macaddr[2], macaddr[3], macaddr[4], macaddr[5]);
- if (!strncmp(macstr, "Mac:", strlen("Mac:")) &&
- (WM_TOOL_DL_TYPE_FLS != wm_tool_dl_type) &&
- !wm_tool_dl_erase)
- {
- wm_tool_printf("please download the firmware in .fls format.\r\n");
- }
- else
- {
- ret = 0;
- }
- }
- break;
- }
- }
- } while (err > 0);
- }
- wm_tool_uart_set_block(0);
- return ret;
- }
- static int wm_tool_xmodem_download(const char *image)
- {
- FILE *imgfp;
- unsigned char packet_data[XMODEM_DATA_SIZE];
- unsigned char frame_data[XMODEM_DATA_SIZE + XMODEM_CRC_SIZE + XMODEM_FRAME_ID_SIZE + 1];
- int complete, retry_num, pack_counter, read_number, write_number = 0, i;
- unsigned short crc_value;
- unsigned char ack_id;
- int sndlen;
- int ret = -111;
- imgfp = fopen(image, "rb");
- if (!imgfp)
- {
- wm_tool_printf("can not open image to download.\r\n");
- return -1;
- }
- sndlen = 0;
- pack_counter = 0;
- complete = 0;
- retry_num = 0;
- wm_tool_printf("start download.\r\n");
- wm_tool_printf("download 0%%\r\n");
- wm_tool_uart_clear();
- wm_tool_uart_set_block(1);
- ack_id = XMODEM_ACK;
- while (!complete)
- {
- WM_TOOL_DBG_PRINT("switch ack_id = %x\r\n", ack_id);
- switch(ack_id)
- {
- case XMODEM_ACK:
- {
- retry_num = 0;
- pack_counter++;
- read_number = fread(packet_data, sizeof(char), XMODEM_DATA_SIZE, imgfp);
- WM_TOOL_DBG_PRINT("fread = %d\r\n", read_number);
- if (read_number > 0)
- {
- sndlen += read_number;
- if (read_number < XMODEM_DATA_SIZE)
- {
- WM_TOOL_DBG_PRINT("start filling the last frame!\r\n");
- for ( ; read_number < XMODEM_DATA_SIZE; read_number++)
- packet_data[read_number] = 0x0;
- }
- frame_data[0] = XMODEM_HEAD;
- frame_data[1] = (char)pack_counter;
- frame_data[2] = (char)(255 - frame_data[1]);
- for (i = 0; i < XMODEM_DATA_SIZE; i++)
- frame_data[i + 3] = packet_data[i];
- crc_value = wm_tool_get_crc16(packet_data, XMODEM_DATA_SIZE);
- frame_data[XMODEM_DATA_SIZE + 3]=(unsigned char)(crc_value >> 8);
- frame_data[XMODEM_DATA_SIZE + 4]=(unsigned char)(crc_value);
- write_number = wm_tool_uart_write(frame_data, XMODEM_DATA_SIZE + 5);
- if (write_number <= 0)
- wm_tool_printf("write serial error, errno = %d.\r\n", errno);
- WM_TOOL_DBG_PRINT("waiting for ack, %d, %d ...\r\n", pack_counter, write_number);
- while ((wm_tool_uart_read(&ack_id, 1)) <= 0);
- if (ack_id == XMODEM_ACK)
- {
- WM_TOOL_DBG_PRINT("Ok!\r\n");
- if (sndlen % 10240 == 0)
- {
- //wm_tool_printf("#");
- wm_tool_printf("#download %d%%\r\n", sndlen >= 1024*1000 ? 99 : sndlen / (10240));
- }
- }
- else
- {
- WM_TOOL_DBG_PRINT("error = %x!\r\n", ack_id);
- }
- }
- else
- {
- ack_id = XMODEM_EOT;
- complete = 1;
- WM_TOOL_DBG_PRINT("waiting for complete ack ...\r\n");
- while (ack_id != XMODEM_ACK)
- {
- ack_id = XMODEM_EOT;
- write_number = wm_tool_uart_write(&ack_id, 1);
- if (write_number <= 0)
- wm_tool_printf("write serial error, errno = %d.\r\n", errno);
- while ((wm_tool_uart_read(&ack_id, 1)) <= 0);
- }
- WM_TOOL_DBG_PRINT("ok\r\n");
- wm_tool_printf("download 100%%\r\n");
- //wm_tool_printf("download completed.\r\n");
- ret = 0;
- }
- break;
- }
- case XMODEM_NAK:
- {
- if ( retry_num++ > 100)
- {
- WM_TOOL_DBG_PRINT("retry too many times, quit!\r\n");
- wm_tool_printf("download firmware timeout.\r\n");
- complete = 1;
- }
- else
- {
- write_number = wm_tool_uart_write(frame_data, XMODEM_DATA_SIZE + 5);
- if (write_number <= 0)
- wm_tool_printf("write serial error, errno = %d.\r\n", errno);
- WM_TOOL_DBG_PRINT("retry for ack, %d, %d ...\r\n", pack_counter, write_number);
- while ((wm_tool_uart_read(&ack_id, 1)) <= 0);
- if (ack_id == XMODEM_ACK)
- {
- WM_TOOL_DBG_PRINT("ok\r\n");
- }
- else
- {
- WM_TOOL_DBG_PRINT("error!\r\n");
- }
- }
- break;
- }
- default:
- {
- WM_TOOL_DBG_PRINT("fatal error!\r\n");
- WM_TOOL_DBG_PRINT("unknown xmodem protocal [%x].\r\n", ack_id);
- wm_tool_printf("\r\ndownload failed, please reset and try again.\r\n");
- complete = 1;
- break;
- }
- }
- }
- wm_tool_uart_set_block(0);
- fclose(imgfp);
- return ret;
- }
- static int wm_tool_download_firmware(void)
- {
- int ret;
- int cnt = 0;
- int note = 1;
- int timeout = 0;
- float timeuse;
- time_t start, end;
- unsigned char ch;
- wm_tool_printf("connecting serial...\r\n");
- ret = wm_tool_uart_open(wm_tool_serial_path);
- if (ret)
- {
- wm_tool_printf("can not open serial\r\n");
- return ret;
- }
- /* In some cases, setting the serial port initialization setting requires a delay. */
- wm_tool_delay_ms(500);
- wm_tool_printf("serial connected.\r\n");
- if (WM_TOOL_DL_ACTION_AT == wm_tool_dl_action)
- {
- if (WM_TOOL_DEFAULT_BAUD_RATE != wm_tool_normal_serial_rate)
- wm_tool_uart_set_speed(wm_tool_normal_serial_rate);
- #if 0 /* use erase option */
- if (WM_TOOL_DL_TYPE_FLS == wm_tool_dl_type)
- {
- ret = wm_tool_uart_write("AT+&FLSW=8002000,0\r\n", strlen("AT+&FLSW=8002000,0\r\n"));
- if (ret <= 0)
- {
- wm_tool_printf("destroy secboot failed.\r\n");
- wm_tool_uart_close();
- return -3;
- }
- wm_tool_delay_ms(300);
- }
- #endif
- ret = wm_tool_uart_write("AT+Z\r\n", strlen("AT+Z\r\n"));
- if (ret <= 0)
- {
- wm_tool_printf("reset error.\r\n");
- wm_tool_uart_close();
- return -4;
- }
- if (WM_TOOL_DEFAULT_BAUD_RATE != wm_tool_normal_serial_rate)
- wm_tool_uart_set_speed(WM_TOOL_DEFAULT_BAUD_RATE);
- }
- else if (WM_TOOL_DL_ACTION_RTS == wm_tool_dl_action)
- {
- ret = wm_tool_uart_set_dtr(0);
- ret |= wm_tool_uart_set_rts(1);
- wm_tool_delay_ms(50);
- ret |= wm_tool_uart_set_dtr(1);
- ret |= wm_tool_uart_set_rts(0);
- wm_tool_delay_ms(50);
- ret |= wm_tool_uart_set_dtr(0);
- if (ret < 0)
- {
- wm_tool_printf("set rts to reboot error.\r\n");
- wm_tool_uart_close();
- return -5;
- }
- }
- wm_tool_printf("wait serial sync...");
- wm_tool_send_esc2uart(500);/* used for delay */
- start = time(NULL);
- do
- {
- ret = wm_tool_uart_read(&ch, 1);
- WM_TOOL_DBG_PRINT("ret=%d, %x-%c\r\n", ret, ch, ch);
- if (ret > 0)
- {
- if (('C' == ch) || ('P' == ch))
- cnt++;
- else
- cnt = 0;
- }
- else
- {
- wm_tool_send_esc2uart(30);
- }
- end = time(NULL);
- timeuse = difftime(end, start);
- if (timeuse >= 1)
- {
- wm_tool_printf(".");
- if ((((int)timeuse) % 2) == 0) {
- wm_tool_uart_set_rts(0);
- }
- else {
- wm_tool_uart_set_rts(1);
- }
- wm_tool_send_esc2uart(0);
- timeout++;
- if ((timeout >= (WM_TOOL_DOWNLOAD_TIMEOUT_SEC / 10)) && note)
- {
- wm_tool_printf("\r\nplease manually reset the device.\r\n");
- note = 0;
- }
- else if (timeout > WM_TOOL_DOWNLOAD_TIMEOUT_SEC)
- {
- wm_tool_uart_close();
- wm_tool_printf("\r\nserial sync timeout.\r\n");
- return -6;
- }
- start = time(NULL);
- }
- } while (cnt < 3);
- wm_tool_printf("\r\nserial sync sucess.\r\n");
- // ret = wm_tool_query_mac();
- // if (ret)
- // {
- // wm_tool_uart_close();
- // wm_tool_printf("download failed.\r\n");
- // return ret;
- // }
- if (WM_TOOL_DL_ERASE_ALL == wm_tool_dl_erase)
- {
- ret = wm_tool_erase_image(WM_TOOL_DL_ERASE_ALL);
- if (ret)
- {
- wm_tool_uart_close();
- wm_tool_printf("failed to erase.\r\n");
- return ret;
- }
- }
- if (!wm_tool_download_image && wm_tool_dl_erase)
- {
- return 0;
- }
- if (WM_TOOL_DEFAULT_BAUD_RATE != wm_tool_download_serial_rate)
- {
- ret = wm_tool_set_wifi_chip_speed(wm_tool_download_serial_rate);
- if (ret > 0)
- {
- wm_tool_delay_ms(1 * 1000);
- wm_tool_uart_set_speed(wm_tool_download_serial_rate);
- }
- }
- ret = wm_tool_xmodem_download(wm_tool_download_image);
- if (ret == 0) {
- wm_tool_delay_ms(200);
- // 21 06 00 c7 7c 3f 00 00 00
- wm_tool_uart_write(wm_tool_chip_cmd_reset, sizeof(wm_tool_chip_cmd_reset));
- //wm_tool_delay_ms(5);
- wm_tool_printf("download completed.\r\n");
- }
- wm_tool_uart_close();
- return ret;
- }
- static void wm_tool_show_local_com(void)
- {
- #if defined(__APPLE__) && defined(__MACH__)
- char *comstr = "tty.usbserial";
- #elif defined(__CYGWIN__)
- int num;
- char *comstr = "ttyS";
- #elif defined(__linux__)
- char *comstr = "ttyUSB";
- #endif
- #if defined(__APPLE__) || defined(__MACH__) || defined(__CYGWIN__) || defined(__linux__)
- DIR *dir;
- struct dirent *file;
- dir = opendir("/dev");
- if (dir)
- {
- while (NULL != (file = readdir(dir)))
- {
- if ((0 == strncmp(file->d_name, comstr, strlen(comstr))) && (DT_CHR == file->d_type))
- {
- #if defined(__CYGWIN__)
- num = atoi(file->d_name + strlen(comstr));
- wm_tool_printf("COM%d ", num + 1);
- #else
- wm_tool_printf("%s ", file->d_name);
- #endif
- }
- }
- closedir(dir);
- wm_tool_printf("\r\n");
- }
- #elif defined(__MINGW32__)
- LONG ret;
- HKEY key;
- DWORD i = 0;
- DWORD knlen;
- char kname[WM_TOOL_PATH_MAX] = {0};
- DWORD kvlen;
- char kvalue[WM_TOOL_PATH_MAX] = {0};
- REGSAM kmask = KEY_READ;
- #if defined(KEY_WOW64_64KEY)
- BOOL is_64;
- if (IsWow64Process(GetCurrentProcess(), &is_64))
- {
- if (is_64)
- kmask |= KEY_WOW64_64KEY;
- }
- #endif
- ret = RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DEVICEMAP\\SERIALCOMM"), 0, NULL, 0, kmask, NULL, &key, NULL);
- if (ret != ERROR_SUCCESS)
- {
- return;
- }
- do{
- knlen = sizeof(kname);
- kvlen = sizeof(kvalue);
- ret = RegEnumValue(key, i, kname, &knlen, 0, NULL, (LPBYTE)kvalue, &kvlen);
- if (ret == ERROR_SUCCESS)
- {
- if (strcmp(kvalue, "") != 0)
- {
- wm_tool_printf("%s ", kvalue);
- }
- }
- i++;
- } while (ret != ERROR_NO_MORE_ITEMS);
- RegCloseKey(key);
- wm_tool_printf("\r\n");
- #else
- wm_tool_printf("\r\nunsupported system.\r\n");
- #endif
- return;
- }
- static void wm_tool_free_res(void)
- {
- if (wm_tool_download_image)
- free(wm_tool_download_image);
- if (wm_tool_output_image)
- free(wm_tool_output_image);
- if (wm_tool_input_binary)
- free(wm_tool_input_binary);
- if (wm_tool_secboot_image)
- free(wm_tool_secboot_image);
- return;
- }
- int main(int argc, char *argv[])
- {
- int ret = 0;
- if (!wm_tool_parse_arv(argc, argv))
- {
- wm_tool_print_usage(argv[0]);
- wm_tool_free_res();
- return 0;
- }
- if (wm_tool_show_usage)
- {
- wm_tool_print_usage(argv[0]);
- wm_tool_free_res();
- return 0;
- }
- if (wm_tool_show_ver)
- {
- wm_tool_print_version(argv[0]);
- wm_tool_free_res();
- return 0;
- }
- if (wm_tool_list_com)
- {
- wm_tool_show_local_com();
- wm_tool_free_res();
- return 0;
- }
- if (wm_tool_input_binary)
- {
- ret = wm_tool_pack_firmware();
- }
- if (wm_tool_download_image || wm_tool_dl_erase)
- {
- ret = wm_tool_download_firmware();
- }
- if (wm_tool_show_log_type)
- {
- ret = wm_tool_show_log_from_serial();
- }
- if (ret > 0)
- wm_tool_print_usage(argv[0]);
- wm_tool_free_res();
- return ret;
- }
|