//Every block has the following header: // 0 - compressed size includeing header (word) // 2 - CRC-16 (word) // 4 - block type // 6 - uncompressed size (word) // 8 .. (compressed size + 5) - compressed data (byte array) dword CompressTFD (byte *pSrc, dword SourceBufferSize, byte *pDest, word TFDType, word SysID, void *pPercentFinishedCallback) { word OrigSize, CompSize; dword OutBufferSize, NrBlocks = 0, FullSize = SourceBufferSize; byte *FileHeader; //PercentFinishedCallback is called for every block. PercentFinished contains a number between 0 and 100 void (*PercentFinishedCallback) (dword PercentFinished) = pPercentFinishedCallback; //Build the tfd file header FileHeader = pDest; if (pDest) { STORE_WORD (pDest , 0x0008); STORE_WORD (pDest + 4, SysID); STORE_WORD (pDest + 6, 0x0001); pDest += 10; } OutBufferSize = 10; while (SourceBufferSize) { if (PercentFinishedCallback) PercentFinishedCallback ((FullSize - SourceBufferSize) * 100 / FullSize); NrBlocks++; OrigSize = (SourceBufferSize > 0x7ffa) ? 0x7ffa : SourceBufferSize; if (pDest) { CompSize = CompressBlock (pSrc, OrigSize, pDest + 8); //Build the block header STORE_WORD (pDest , CompSize + 6); STORE_WORD (pDest + 4, TFDType); STORE_WORD (pDest + 6, OrigSize); STORE_WORD (pDest + 2, CRC16 (0, pDest + 4, 4 + CompSize)); pDest += CompSize + 8; } else CompSize = CompressBlock (pSrc, OrigSize, NULL); OutBufferSize += CompSize + 8; SourceBufferSize -= OrigSize; pSrc += OrigSize; } if (FileHeader) { STORE_WORD (FileHeader + 8, NrBlocks); STORE_WORD (FileHeader + 2, CRC16 (0, FileHeader + 4, 6)); } if (PercentFinishedCallback) PercentFinishedCallback (100); return OutBufferSize; }
//Every block has the following header: // 0 - compressed size includeing header (word) // 2 - CRC-16 (word) // 4 - block type // 6 - uncompressed size (word) // 8 .. (compressed size + 5) - compressed data (byte array) dword UncompressTFD (byte *pSrc, byte *pDest, void *pPercentFinishedCallback) { word compSize = 0, uncompSize = 0, NrBlocks = 0; dword outSize = 0, i; //PercentFinishedCallback is called for every block. PercentFinished contains a number between 0 and 100 void (*PercentFinishedCallback) (dword PercentFinished) = pPercentFinishedCallback; if (LOAD_WORD(pSrc) != 8) return 0; //Invalid header? if (CRC16 (0, pSrc + 4, 6) != LOAD_WORD(pSrc + 2)) return 0; //Invalid header CRC? if (LOAD_WORD(pSrc + 6) != 1) return 0; //Invalid file version? NrBlocks = LOAD_WORD(pSrc + 8); pSrc += 10; for (i = 0; i < NrBlocks; i++) { if (PercentFinishedCallback) PercentFinishedCallback (i * 100 / NrBlocks); compSize = LOAD_WORD(pSrc) - 6; uncompSize = LOAD_WORD(pSrc + 6); if (uncompSize > 0x7ffa) return 0; pSrc += 8; if(compSize == uncompSize) { // not compressed data, copy it directly if (pDest) memcpy(pDest, pSrc, uncompSize); } else { // compressed data, uncompress it if (!UncompressBlock (pSrc, compSize, pDest, uncompSize)) return 0; } if (pDest) pDest += uncompSize; pSrc += compSize; outSize += uncompSize; } if (PercentFinishedCallback) PercentFinishedCallback (100); return outSize; }
// UncompressFirmware() is a function wrapper that decodes data blocks // encoded with AR002 algorithm until the uncompressed size field // is set to 0xfefe. This is normaly used for the Loader or the Firmware // inside of the flash memory. // The expected block structure is as follows: // 0 - uncompressed size (word) // 2 - compressed size (incl CRC-16) (word) // 4 - CRC-16 (word) // 6 .. (compressed size + 5) - compressed data (byte array) dword UncompressFirmware(byte *pSrc, byte *pDest, void *pPercentFinishedCallback) { TRACEENTER(); word compSize = 0, uncompSize = 0; dword outSize = 0, NrBlocks = 0, CurrentBlock = 0; byte *OrigpSrc; if(!pSrc || !pDest) { TRACEEXIT(); return 0; } //PercentFinishedCallback is called for every block. PercentFinished contains a number between 0 and 100 void (*PercentFinishedCallback) (dword PercentFinished) = pPercentFinishedCallback; OrigpSrc = pSrc; uncompSize = LOAD_WORD(pSrc + 0); compSize = LOAD_WORD(pSrc + 2); //Count the number of blocks while(uncompSize != 0xfefe) { NrBlocks++; if(uncompSize > 0x8000) { //Uncompressed data block size too large TRACEEXIT(); return 0; } pSrc += 4; pSrc += compSize; uncompSize = LOAD_WORD(pSrc + 0); compSize = LOAD_WORD(pSrc + 2); } pSrc = OrigpSrc; uncompSize = LOAD_WORD(pSrc + 0); compSize = LOAD_WORD(pSrc + 2); while(uncompSize != 0xfefe) { if(PercentFinishedCallback) PercentFinishedCallback(CurrentBlock * 100 / NrBlocks); CurrentBlock++; if(uncompSize > 0x8000) { //Uncompressed data block size too large TRACEEXIT(); return 0; } pSrc += 6; if(compSize == uncompSize) { // data not compressed, copy it directly if(pDest) memcpy(pDest, pSrc, uncompSize); } else { // compressed data, uncompress it if(!UncompressBlock(pSrc, compSize, pDest, uncompSize)) { //Uncompress has failed TRACEEXIT(); return 0; } } if(pDest) pDest += uncompSize; pSrc += compSize; outSize += uncompSize; uncompSize = LOAD_WORD(pSrc + 0); compSize = LOAD_WORD(pSrc + 2); } if(PercentFinishedCallback) PercentFinishedCallback(100); TRACEEXIT(); return outSize; }