/** * @file hv_boot_Lzss.c * @brief Lzss source code. * @details This file provides the following functions: \n * (1) Initialization and de-initialization functions \n * (2) Start and stop functions \n * (3) Feed functions \n * * @author HiView SoC Software Team * @version 1.0.0 * @date 2022-08-18 * @copyright Copyright(c),2022-8, Hiview Software. All rights reserved. * @par History: * *
Author Date Change Description *
HiView SoC Software Team 2022-08-23 init *
*/ #include "hv_chip_Config.h" #include "hv_boot_Common.h" #define N 4096 /* size of ring buffer */ #define F 18 /* upper limit for match_length */ #define THRESHOLD 4 /* encode string into position and length if match_length is greater than this */ #define NIL N /* index for root of binary search trees */ static unsigned long int textsize = 0; /* text size counter */ static unsigned long int codesize = 0; /* code size counter */ static unsigned long int printcount = 0; /* counter for reporting progress every 1K bytes */ static unsigned char text_buf[N + F - 1] = {0}; /* ring buffer of size N,with extra F-1 bytes to facilitate string comparison */ static int match_position = 0; static int match_length = 0; /* of longest match. These are set by the InsertNode() procedure. */ static int lson[N + 1] = {0}; static int rson[N + 257] = {0}; static int dad[N + 1] = {0}; /* left & right children &parents -- These constitute binary search trees. */ /* input & output files */ static unsigned char *infile = 0; static unsigned char *fileoff = 0; static unsigned char *outfile = 0; void InitTree(void) /* initialize trees */ { int i; /* For i = 0 to N - 1, rson[i] and lson[i] will be the right and left children of node i. These nodes need not be initialized. Also, dad[i] is the parent of node i. These are initialized to NIL (= N), which stands for 'not used.' For i = 0 to 255, rson[N + i + 1] is the root of the tree for strings that begin with character i. These are initialized to NIL. Note there are 256 trees. */ for (i = N + 1; i <= N + 256; i++) rson[i] = NIL; for (i = 0; i < N; i++) dad[i] = NIL; } void InsertNode(int r) /* Inserts string of length F, text_buf[r..r+F-1], into one of the trees (text_buf[r]'th tree) and returns the longest-match position and length via the global variables match_position and match_length. If match_length = F, then removes the old node in favor of the new one, because the old one will be deleted sooner. Note r plays double role, as tree node and position in buffer. */ { int i, p, cmp; unsigned char *key; cmp = 1; key = &text_buf[r]; p = N + 1 + key[0]; rson[r] = lson[r] = NIL; match_length = 0; for ( ; ; ) { if (cmp >= 0) { if (rson[p] != NIL) p = rson[p]; else { rson[p] = r; dad[r] = p; return; } } else { if (lson[p] != NIL) p = lson[p]; else { lson[p] = r; dad[r] = p; return; } } for (i = 1; i < F; i++) if ((cmp = key[i] - text_buf[p + i]) != 0) break; if (i > match_length) { match_position = p; if ((match_length = i) >= F) break; } } dad[r] = dad[p]; lson[r] = lson[p]; rson[r] = rson[p]; dad[lson[p]] = r; dad[rson[p]] = r; if (rson[dad[p]] == p) rson[dad[p]] = r; else lson[dad[p]] = r; dad[p] = NIL; /* remove p */ } void DeleteNode(int p) /* deletes node p from tree */ { int q; if (dad[p] == NIL) return; /* not in tree */ if (rson[p] == NIL) q = lson[p]; else if (lson[p] == NIL) q = rson[p]; else { q = lson[p]; if (rson[q] != NIL) { do { q = rson[q]; } while (rson[q] != NIL); rson[dad[q]] = lson[q]; dad[lson[q]] = dad[q]; lson[q] = lson[p]; dad[lson[p]] = q; } rson[q] = rson[p]; dad[rson[p]] = q; } dad[q] = dad[p]; if (rson[dad[p]] == p) rson[dad[p]] = q; else lson[dad[p]] = q; dad[p] = NIL; } void Decode(void) /* Just the reverse of Encode(). */ { int i, j, k, r, c; unsigned int flags; for (i = 0; i < N - F; i++) text_buf[i] = ' '; r = N - F; flags = 0; for ( ; ; ) { if (((flags >>= 1) & 256) == 0) { if (infile==fileoff) { break; } c = *infile++; flags = c | 0xff00; /* uses higher byte cleverly */ } /* to count eight */ if (flags & 1) { if (infile==fileoff) { break; } c = *infile++; *outfile++=c; text_buf[r++] = c; r &= (N - 1); } else { if (infile==fileoff) { break; } i = *infile++; if (infile==fileoff) { break; } j = *infile++; i |= ((j & 0xf0) << 4); j = (j & 0x0f) + THRESHOLD; for (k = 0; k <= j; k++) { c = text_buf[(i + k) & (N - 1)]; *outfile++=c; text_buf[r++] = c; r &= (N - 1); } } } } int Hv_Boot_GetFileSize(void) { char *pcPoint = infile; int uiSize = 0; int iCount = 0; unsigned int uiMaigic = 0; Hv_Boot_Print_String(BOOT_DEBUG_LEVEL_INFO, ">>> check size in\n"); Hv_Boot_PrintHex(BOOT_DEBUG_LEVEL_INFO, (unsigned int)infile); /* check magic "HIVIEW!" */ for (pcPoint = infile, iCount = 0; iCount < 4; iCount++, pcPoint++) { uiMaigic = (uiMaigic << 8) + (*pcPoint); } if (uiMaigic != 0x48495649) { Hv_Boot_Print_String(BOOT_DEBUG_LEVEL_WAR, ">>> no hivi\n"); return -1; } for (pcPoint = infile + 4, iCount = 0; iCount < 4; iCount++, pcPoint++) { uiMaigic = (uiMaigic << 8) + (*pcPoint); } if (uiMaigic != 0x4557210A) { Hv_Boot_Print_String(BOOT_DEBUG_LEVEL_WAR, ">>> no iew!\n"); return -2; } /* check size */ for (pcPoint = infile + 8, iCount = 0; (*pcPoint != 0xa) && (*pcPoint < 0x3a) && (*pcPoint > 0x2f) && (iCount < 8); pcPoint++,iCount++) { uiSize = uiSize * 10 + (*pcPoint - 0x30); } if ((uiSize > 512) && (uiSize < 1458716)) { infile += 32; fileoff = infile + uiSize; Hv_Boot_PrintHex(BOOT_DEBUG_LEVEL_INFO, uiSize); return 0; } Hv_Boot_Print_String(BOOT_DEBUG_LEVEL_WAR, ">>> size wrong!\n"); return -3; } int Hv_Boot_LzssDecompress(char *pcSrc, char *pcDst, int iChanegeEndian, int iSize) { int iLoop = 0; unsigned char ucTemp = 0; if (pcSrc != 0) { infile = pcSrc; } if (infile == 0) { return -1; } if (pcDst == 0) { return -1; } outfile = pcDst; if (Hv_Boot_GetFileSize()) { if (iSize == 0) { return -1; } else { fileoff = infile + iSize; Hv_Boot_Print_String(BOOT_DEBUG_LEVEL_INFO, ">>> valid size\n"); Hv_Boot_PrintHex(BOOT_DEBUG_LEVEL_INFO, (unsigned int)iSize); } } Hv_Boot_Print_String(BOOT_DEBUG_LEVEL_INFO, ">>> decompress bin\n"); Hv_Boot_PrintHex(BOOT_DEBUG_LEVEL_INFO, (unsigned int)infile); Hv_Boot_PrintHex(BOOT_DEBUG_LEVEL_INFO, (unsigned int)fileoff); Decode(); Hv_Boot_Print_String(BOOT_DEBUG_LEVEL_INFO, ">>> decompress bin over\n"); Hv_Boot_PrintHex(BOOT_DEBUG_LEVEL_INFO, (unsigned int)pcDst); Hv_Boot_PrintHex(BOOT_DEBUG_LEVEL_INFO, (unsigned int)outfile); if (iChanegeEndian == 0) { return 0; } for (iLoop = 0; iLoop < (fileoff - infile); iLoop += 4) { ucTemp = *(infile+iLoop+3); *(infile+iLoop+3) = *(infile+iLoop+0); *(infile+iLoop+0) = ucTemp; ucTemp = *(infile+iLoop+2); *(infile+iLoop+2) = *(infile+iLoop+1); *(infile+iLoop+1) = ucTemp; } return 0; }