]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Library/UefiShellDebug1CommandsLib/Compress.c
ShellPkg: Parse new SMBIOS 3.0 fields.
[mirror_edk2.git] / ShellPkg / Library / UefiShellDebug1CommandsLib / Compress.c
CommitLineData
5d73d92f 1/** @file\r
2 Main file for compression routine.\r
3\r
4 Compression routine. The compression algorithm is a mixture of\r
5 LZ77 and Huffman coding. LZ77 transforms the source data into a\r
6 sequence of Original Characters and Pointers to repeated strings.\r
7 This sequence is further divided into Blocks and Huffman codings\r
8 are applied to each Block.\r
9\r
e8c737ae 10 Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>\r
5d73d92f 11 This program and the accompanying materials\r
12 are licensed and made available under the terms and conditions of the BSD License\r
13 which accompanies this distribution. The full text of the license may be found at\r
14 http://opensource.org/licenses/bsd-license.php\r
15\r
16 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
17 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
18\r
19**/\r
20\r
21#include <Library/MemoryAllocationLib.h>\r
22#include <Library/BaseMemoryLib.h>\r
23#include <Library/DebugLib.h>\r
24#include <ShellBase.h>\r
e8c737ae 25#include <Uefi.h>\r
5d73d92f 26\r
27//\r
28// Macro Definitions\r
29//\r
30typedef INT16 NODE;\r
31#define UINT8_MAX 0xff\r
32#define UINT8_BIT 8\r
33#define THRESHOLD 3\r
34#define INIT_CRC 0\r
35#define WNDBIT 13\r
36#define WNDSIZ (1U << WNDBIT)\r
37#define MAXMATCH 256\r
38#define BLKSIZ (1U << 14) // 16 * 1024U\r
39#define PERC_FLAG 0x8000U\r
40#define CODE_BIT 16\r
41#define NIL 0\r
42#define MAX_HASH_VAL (3 * WNDSIZ + (WNDSIZ / 512 + 1) * UINT8_MAX)\r
3737ac2b 43#define HASH(LoopVar7, LoopVar5) ((LoopVar7) + ((LoopVar5) << (WNDBIT - 9)) + WNDSIZ * 2)\r
5d73d92f 44#define CRCPOLY 0xA001\r
3737ac2b 45#define UPDATE_CRC(LoopVar5) mCrc = mCrcTable[(mCrc ^ (LoopVar5)) & 0xFF] ^ (mCrc >> UINT8_BIT)\r
5d73d92f 46\r
47//\r
48// C: the Char&Len Set; P: the Position Set; T: the exTra Set\r
49//\r
50#define NC (UINT8_MAX + MAXMATCH + 2 - THRESHOLD)\r
51#define CBIT 9\r
52#define NP (WNDBIT + 1)\r
53#define PBIT 4\r
54#define NT (CODE_BIT + 3)\r
55#define TBIT 5\r
56#if NT > NP\r
57 #define NPT NT\r
58#else\r
59 #define NPT NP\r
60#endif\r
61//\r
62// Function Prototypes\r
63//\r
64\r
65/**\r
66 Put a dword to output stream\r
67\r
68 @param[in] Data The dword to put.\r
69**/\r
70VOID\r
71EFIAPI\r
72PutDword(\r
73 IN UINT32 Data\r
74 );\r
75\r
5d73d92f 76//\r
77// Global Variables\r
78//\r
3737ac2b 79STATIC UINT8 *mSrc;\r
80STATIC UINT8 *mDst;\r
81STATIC UINT8 *mSrcUpperLimit;\r
82STATIC UINT8 *mDstUpperLimit;\r
83\r
84STATIC UINT8 *mLevel;\r
85STATIC UINT8 *mText;\r
86STATIC UINT8 *mChildCount;\r
87STATIC UINT8 *mBuf;\r
88STATIC UINT8 mCLen[NC];\r
89STATIC UINT8 mPTLen[NPT];\r
90STATIC UINT8 *mLen;\r
5d73d92f 91STATIC INT16 mHeap[NC + 1];\r
3737ac2b 92STATIC INT32 mRemainder;\r
93STATIC INT32 mMatchLen;\r
94STATIC INT32 mBitCount;\r
95STATIC INT32 mHeapSize;\r
96STATIC INT32 mTempInt32;\r
97STATIC UINT32 mBufSiz = 0;\r
98STATIC UINT32 mOutputPos;\r
99STATIC UINT32 mOutputMask;\r
100STATIC UINT32 mSubBitBuf;\r
101STATIC UINT32 mCrc;\r
102STATIC UINT32 mCompSize;\r
103STATIC UINT32 mOrigSize;\r
104\r
105STATIC UINT16 *mFreq;\r
106STATIC UINT16 *mSortPtr;\r
107STATIC UINT16 mLenCnt[17];\r
108STATIC UINT16 mLeft[2 * NC - 1];\r
109STATIC UINT16 mRight[2 * NC - 1];\r
110STATIC UINT16 mCrcTable[UINT8_MAX + 1];\r
111STATIC UINT16 mCFreq[2 * NC - 1];\r
3737ac2b 112STATIC UINT16 mCCode[NC];\r
113STATIC UINT16 mPFreq[2 * NP - 1];\r
114STATIC UINT16 mPTCode[NPT];\r
115STATIC UINT16 mTFreq[2 * NT - 1];\r
116\r
117STATIC NODE mPos;\r
118STATIC NODE mMatchPos;\r
119STATIC NODE mAvail;\r
120STATIC NODE *mPosition;\r
121STATIC NODE *mParent;\r
122STATIC NODE *mPrev;\r
123STATIC NODE *mNext = NULL;\r
124INT32 mHuffmanDepth = 0;\r
5d73d92f 125\r
5d73d92f 126/**\r
3737ac2b 127 Make a CRC table.\r
5d73d92f 128\r
5d73d92f 129**/\r
3737ac2b 130VOID\r
5d73d92f 131EFIAPI\r
3737ac2b 132MakeCrcTable (\r
133 VOID\r
5d73d92f 134 )\r
135{\r
3737ac2b 136 UINT32 LoopVar1;\r
5d73d92f 137\r
3737ac2b 138 UINT32 LoopVar2;\r
5d73d92f 139\r
3737ac2b 140 UINT32 LoopVar4;\r
5d73d92f 141\r
3737ac2b 142 for (LoopVar1 = 0; LoopVar1 <= UINT8_MAX; LoopVar1++) {\r
143 LoopVar4 = LoopVar1;\r
144 for (LoopVar2 = 0; LoopVar2 < UINT8_BIT; LoopVar2++) {\r
145 if ((LoopVar4 & 1) != 0) {\r
146 LoopVar4 = (LoopVar4 >> 1) ^ CRCPOLY;\r
147 } else {\r
148 LoopVar4 >>= 1;\r
149 }\r
150 }\r
5d73d92f 151\r
3737ac2b 152 mCrcTable[LoopVar1] = (UINT16) LoopVar4;\r
5d73d92f 153 }\r
5d73d92f 154}\r
155\r
156/**\r
157 Put a dword to output stream\r
158\r
159 @param[in] Data The dword to put.\r
160**/\r
161VOID\r
162EFIAPI\r
163PutDword (\r
164 IN UINT32 Data\r
165 )\r
166{\r
167 if (mDst < mDstUpperLimit) {\r
168 *mDst++ = (UINT8) (((UINT8) (Data)) & 0xff);\r
169 }\r
170\r
171 if (mDst < mDstUpperLimit) {\r
172 *mDst++ = (UINT8) (((UINT8) (Data >> 0x08)) & 0xff);\r
173 }\r
174\r
175 if (mDst < mDstUpperLimit) {\r
176 *mDst++ = (UINT8) (((UINT8) (Data >> 0x10)) & 0xff);\r
177 }\r
178\r
179 if (mDst < mDstUpperLimit) {\r
180 *mDst++ = (UINT8) (((UINT8) (Data >> 0x18)) & 0xff);\r
181 }\r
182}\r
183\r
3737ac2b 184/**\r
185 Allocate memory spaces for data structures used in compression process.\r
186 \r
187 @retval EFI_SUCCESS Memory was allocated successfully.\r
188 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
189**/\r
5d73d92f 190EFI_STATUS\r
191EFIAPI\r
192AllocateMemory (\r
193 VOID\r
194 )\r
5d73d92f 195{\r
196 mText = AllocateZeroPool (WNDSIZ * 2 + MAXMATCH);\r
3737ac2b 197 mLevel = AllocateZeroPool ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mLevel));\r
198 mChildCount = AllocateZeroPool ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mChildCount));\r
199 mPosition = AllocateZeroPool ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mPosition));\r
200 mParent = AllocateZeroPool (WNDSIZ * 2 * sizeof (*mParent));\r
201 mPrev = AllocateZeroPool (WNDSIZ * 2 * sizeof (*mPrev));\r
202 mNext = AllocateZeroPool ((MAX_HASH_VAL + 1) * sizeof (*mNext));\r
5d73d92f 203\r
204 mBufSiz = BLKSIZ;\r
3737ac2b 205 mBuf = AllocateZeroPool (mBufSiz);\r
5d73d92f 206 while (mBuf == NULL) {\r
207 mBufSiz = (mBufSiz / 10U) * 9U;\r
208 if (mBufSiz < 4 * 1024U) {\r
209 return EFI_OUT_OF_RESOURCES;\r
210 }\r
211\r
3737ac2b 212 mBuf = AllocateZeroPool (mBufSiz);\r
5d73d92f 213 }\r
214\r
215 mBuf[0] = 0;\r
216\r
217 return EFI_SUCCESS;\r
218}\r
219\r
3737ac2b 220/**\r
221 Called when compression is completed to free memory previously allocated.\r
222\r
223**/\r
224VOID\r
5d73d92f 225EFIAPI\r
226FreeMemory (\r
227 VOID\r
228 )\r
5d73d92f 229{\r
230 SHELL_FREE_NON_NULL (mText);\r
231 SHELL_FREE_NON_NULL (mLevel);\r
232 SHELL_FREE_NON_NULL (mChildCount);\r
233 SHELL_FREE_NON_NULL (mPosition);\r
234 SHELL_FREE_NON_NULL (mParent);\r
235 SHELL_FREE_NON_NULL (mPrev);\r
236 SHELL_FREE_NON_NULL (mNext);\r
237 SHELL_FREE_NON_NULL (mBuf);\r
238}\r
239\r
3737ac2b 240/**\r
ae724571 241 Initialize String Info Log data structures.\r
3737ac2b 242**/\r
5d73d92f 243VOID\r
244EFIAPI\r
245InitSlide (\r
246 VOID\r
247 )\r
5d73d92f 248{\r
3737ac2b 249 NODE LoopVar1;\r
5d73d92f 250\r
251 SetMem (mLevel + WNDSIZ, (UINT8_MAX + 1) * sizeof (UINT8), 1);\r
252 SetMem (mPosition + WNDSIZ, (UINT8_MAX + 1) * sizeof (NODE), 0);\r
253\r
254 SetMem (mParent + WNDSIZ, WNDSIZ * sizeof (NODE), 0);\r
255\r
256 mAvail = 1;\r
3737ac2b 257 for (LoopVar1 = 1; LoopVar1 < WNDSIZ - 1; LoopVar1++) {\r
258 mNext[LoopVar1] = (NODE) (LoopVar1 + 1);\r
5d73d92f 259 }\r
260\r
261 mNext[WNDSIZ - 1] = NIL;\r
262 SetMem (mNext + WNDSIZ * 2, (MAX_HASH_VAL - WNDSIZ * 2 + 1) * sizeof (NODE), 0);\r
263}\r
264\r
3737ac2b 265/**\r
5d73d92f 266 Find child node given the parent node and the edge character\r
267\r
3737ac2b 268 @param[in] LoopVar6 The parent node.\r
269 @param[in] LoopVar5 The edge character.\r
5d73d92f 270\r
3737ac2b 271 @return The child node.\r
272 @retval NIL(Zero) No child could be found.\r
5d73d92f 273\r
274**/\r
3737ac2b 275NODE\r
276EFIAPI\r
277Child (\r
278 IN NODE LoopVar6,\r
279 IN UINT8 LoopVar5\r
280 )\r
5d73d92f 281{\r
3737ac2b 282 NODE LoopVar4;\r
5d73d92f 283\r
3737ac2b 284 LoopVar4 = mNext[HASH (LoopVar6, LoopVar5)];\r
285 mParent[NIL] = LoopVar6; /* sentinel */\r
286 while (mParent[LoopVar4] != LoopVar6) {\r
287 LoopVar4 = mNext[LoopVar4];\r
5d73d92f 288 }\r
289\r
3737ac2b 290 return LoopVar4;\r
5d73d92f 291}\r
292\r
3737ac2b 293/**\r
294 Create a new child for a given parent node.\r
295\r
296 @param[in] LoopVar6 The parent node.\r
297 @param[in] LoopVar5 The edge character.\r
298 @param[in] LoopVar4 The child node.\r
299**/\r
5d73d92f 300VOID\r
301EFIAPI\r
302MakeChild (\r
3737ac2b 303 IN NODE LoopVar6,\r
304 IN UINT8 LoopVar5,\r
305 IN NODE LoopVar4\r
5d73d92f 306 )\r
5d73d92f 307{\r
3737ac2b 308 NODE LoopVar12;\r
309\r
310 NODE LoopVar10;\r
311\r
312 LoopVar12 = (NODE) HASH (LoopVar6, LoopVar5);\r
313 LoopVar10 = mNext[LoopVar12];\r
314 mNext[LoopVar12] = LoopVar4;\r
315 mNext[LoopVar4] = LoopVar10;\r
316 mPrev[LoopVar10] = LoopVar4;\r
317 mPrev[LoopVar4] = LoopVar12;\r
318 mParent[LoopVar4] = LoopVar6;\r
319 mChildCount[LoopVar6]++;\r
5d73d92f 320}\r
321\r
3737ac2b 322/**\r
323 Split a node.\r
324\r
325 @param[in] Old The node to split.\r
326**/\r
5d73d92f 327VOID\r
328EFIAPI\r
329Split (\r
3737ac2b 330 IN NODE Old\r
5d73d92f 331 )\r
5d73d92f 332{\r
333 NODE New;\r
334\r
3737ac2b 335 NODE LoopVar10;\r
5d73d92f 336\r
337 New = mAvail;\r
338 mAvail = mNext[New];\r
339 mChildCount[New] = 0;\r
3737ac2b 340 LoopVar10 = mPrev[Old];\r
341 mPrev[New] = LoopVar10;\r
342 mNext[LoopVar10] = New;\r
343 LoopVar10 = mNext[Old];\r
344 mNext[New] = LoopVar10;\r
345 mPrev[LoopVar10] = New;\r
5d73d92f 346 mParent[New] = mParent[Old];\r
347 mLevel[New] = (UINT8) mMatchLen;\r
348 mPosition[New] = mPos;\r
349 MakeChild (New, mText[mMatchPos + mMatchLen], Old);\r
350 MakeChild (New, mText[mPos + mMatchLen], mPos);\r
351}\r
352\r
3737ac2b 353/**\r
354 Insert string info for current position into the String Info Log.\r
355\r
356**/\r
5d73d92f 357VOID\r
358EFIAPI\r
359InsertNode (\r
360 VOID\r
361 )\r
5d73d92f 362{\r
3737ac2b 363 NODE LoopVar6;\r
5d73d92f 364\r
3737ac2b 365 NODE LoopVar4;\r
5d73d92f 366\r
3737ac2b 367 NODE LoopVar2;\r
5d73d92f 368\r
3737ac2b 369 NODE LoopVar10;\r
370 UINT8 LoopVar5;\r
371 UINT8 *TempString3;\r
372 UINT8 *TempString2;\r
5d73d92f 373\r
374 if (mMatchLen >= 4) {\r
375 //\r
376 // We have just got a long match, the target tree\r
377 // can be located by MatchPos + 1. Travese the tree\r
378 // from bottom up to get to a proper starting point.\r
379 // The usage of PERC_FLAG ensures proper node deletion\r
380 // in DeleteNode() later.\r
381 //\r
382 mMatchLen--;\r
3737ac2b 383 LoopVar4 = (NODE) ((mMatchPos + 1) | WNDSIZ);\r
384 LoopVar6 = mParent[LoopVar4];\r
385 while (LoopVar6 == NIL) {\r
386 LoopVar4 = mNext[LoopVar4];\r
387 LoopVar6 = mParent[LoopVar4];\r
5d73d92f 388 }\r
389\r
3737ac2b 390 while (mLevel[LoopVar6] >= mMatchLen) {\r
391 LoopVar4 = LoopVar6;\r
392 LoopVar6 = mParent[LoopVar6];\r
5d73d92f 393 }\r
394\r
3737ac2b 395 LoopVar10 = LoopVar6;\r
396 while (mPosition[LoopVar10] < 0) {\r
397 mPosition[LoopVar10] = mPos;\r
398 LoopVar10 = mParent[LoopVar10];\r
5d73d92f 399 }\r
400\r
3737ac2b 401 if (LoopVar10 < WNDSIZ) {\r
402 mPosition[LoopVar10] = (NODE) (mPos | PERC_FLAG);\r
5d73d92f 403 }\r
404 } else {\r
405 //\r
406 // Locate the target tree\r
407 //\r
3737ac2b 408 LoopVar6 = (NODE) (mText[mPos] + WNDSIZ);\r
409 LoopVar5 = mText[mPos + 1];\r
410 LoopVar4 = Child (LoopVar6, LoopVar5);\r
411 if (LoopVar4 == NIL) {\r
412 MakeChild (LoopVar6, LoopVar5, mPos);\r
5d73d92f 413 mMatchLen = 1;\r
414 return ;\r
415 }\r
416\r
417 mMatchLen = 2;\r
418 }\r
419 //\r
420 // Traverse down the tree to find a match.\r
421 // Update Position value along the route.\r
422 // Node split or creation is involved.\r
423 //\r
424 for (;;) {\r
3737ac2b 425 if (LoopVar4 >= WNDSIZ) {\r
426 LoopVar2 = MAXMATCH;\r
427 mMatchPos = LoopVar4;\r
5d73d92f 428 } else {\r
3737ac2b 429 LoopVar2 = mLevel[LoopVar4];\r
430 mMatchPos = (NODE) (mPosition[LoopVar4] & ~PERC_FLAG);\r
5d73d92f 431 }\r
432\r
433 if (mMatchPos >= mPos) {\r
434 mMatchPos -= WNDSIZ;\r
435 }\r
436\r
3737ac2b 437 TempString3 = &mText[mPos + mMatchLen];\r
438 TempString2 = &mText[mMatchPos + mMatchLen];\r
439 while (mMatchLen < LoopVar2) {\r
440 if (*TempString3 != *TempString2) {\r
441 Split (LoopVar4);\r
5d73d92f 442 return ;\r
443 }\r
444\r
445 mMatchLen++;\r
3737ac2b 446 TempString3++;\r
447 TempString2++;\r
5d73d92f 448 }\r
449\r
450 if (mMatchLen >= MAXMATCH) {\r
451 break;\r
452 }\r
453\r
3737ac2b 454 mPosition[LoopVar4] = mPos;\r
455 LoopVar6 = LoopVar4;\r
456 LoopVar4 = Child (LoopVar6, *TempString3);\r
457 if (LoopVar4 == NIL) {\r
458 MakeChild (LoopVar6, *TempString3, mPos);\r
5d73d92f 459 return ;\r
460 }\r
461\r
462 mMatchLen++;\r
463 }\r
464\r
3737ac2b 465 LoopVar10 = mPrev[LoopVar4];\r
466 mPrev[mPos] = LoopVar10;\r
467 mNext[LoopVar10] = mPos;\r
468 LoopVar10 = mNext[LoopVar4];\r
469 mNext[mPos] = LoopVar10;\r
470 mPrev[LoopVar10] = mPos;\r
471 mParent[mPos] = LoopVar6;\r
472 mParent[LoopVar4] = NIL;\r
5d73d92f 473\r
474 //\r
475 // Special usage of 'next'\r
476 //\r
3737ac2b 477 mNext[LoopVar4] = mPos;\r
5d73d92f 478\r
479}\r
480\r
3737ac2b 481/**\r
482 Delete outdated string info. (The Usage of PERC_FLAG\r
483 ensures a clean deletion).\r
484\r
485**/\r
5d73d92f 486VOID\r
487EFIAPI\r
488DeleteNode (\r
489 VOID\r
490 )\r
5d73d92f 491{\r
3737ac2b 492 NODE LoopVar6;\r
5d73d92f 493\r
3737ac2b 494 NODE LoopVar4;\r
5d73d92f 495\r
3737ac2b 496 NODE LoopVar11;\r
5d73d92f 497\r
3737ac2b 498 NODE LoopVar10;\r
5d73d92f 499\r
3737ac2b 500 NODE LoopVar9;\r
5d73d92f 501\r
502 if (mParent[mPos] == NIL) {\r
503 return ;\r
504 }\r
505\r
3737ac2b 506 LoopVar4 = mPrev[mPos];\r
507 LoopVar11 = mNext[mPos];\r
508 mNext[LoopVar4] = LoopVar11;\r
509 mPrev[LoopVar11] = LoopVar4;\r
510 LoopVar4 = mParent[mPos];\r
5d73d92f 511 mParent[mPos] = NIL;\r
3737ac2b 512 if (LoopVar4 >= WNDSIZ) {\r
5d73d92f 513 return ;\r
514 }\r
515\r
3737ac2b 516 mChildCount[LoopVar4]--;\r
517 if (mChildCount[LoopVar4] > 1) {\r
5d73d92f 518 return ;\r
519 }\r
520\r
3737ac2b 521 LoopVar10 = (NODE) (mPosition[LoopVar4] & ~PERC_FLAG);\r
522 if (LoopVar10 >= mPos) {\r
523 LoopVar10 -= WNDSIZ;\r
5d73d92f 524 }\r
525\r
3737ac2b 526 LoopVar11 = LoopVar10;\r
527 LoopVar6 = mParent[LoopVar4];\r
528 LoopVar9 = mPosition[LoopVar6];\r
529 while ((LoopVar9 & PERC_FLAG) != 0){\r
530 LoopVar9 &= ~PERC_FLAG;\r
531 if (LoopVar9 >= mPos) {\r
532 LoopVar9 -= WNDSIZ;\r
5d73d92f 533 }\r
534\r
3737ac2b 535 if (LoopVar9 > LoopVar11) {\r
536 LoopVar11 = LoopVar9;\r
5d73d92f 537 }\r
538\r
3737ac2b 539 mPosition[LoopVar6] = (NODE) (LoopVar11 | WNDSIZ);\r
540 LoopVar6 = mParent[LoopVar6];\r
541 LoopVar9 = mPosition[LoopVar6];\r
5d73d92f 542 }\r
543\r
3737ac2b 544 if (LoopVar6 < WNDSIZ) {\r
545 if (LoopVar9 >= mPos) {\r
546 LoopVar9 -= WNDSIZ;\r
5d73d92f 547 }\r
548\r
3737ac2b 549 if (LoopVar9 > LoopVar11) {\r
550 LoopVar11 = LoopVar9;\r
5d73d92f 551 }\r
552\r
3737ac2b 553 mPosition[LoopVar6] = (NODE) (LoopVar11 | WNDSIZ | PERC_FLAG);\r
5d73d92f 554 }\r
555\r
3737ac2b 556 LoopVar11 = Child (LoopVar4, mText[LoopVar10 + mLevel[LoopVar4]]);\r
557 LoopVar10 = mPrev[LoopVar11];\r
558 LoopVar9 = mNext[LoopVar11];\r
559 mNext[LoopVar10] = LoopVar9;\r
560 mPrev[LoopVar9] = LoopVar10;\r
561 LoopVar10 = mPrev[LoopVar4];\r
562 mNext[LoopVar10] = LoopVar11;\r
563 mPrev[LoopVar11] = LoopVar10;\r
564 LoopVar10 = mNext[LoopVar4];\r
565 mPrev[LoopVar10] = LoopVar11;\r
566 mNext[LoopVar11] = LoopVar10;\r
567 mParent[LoopVar11] = mParent[LoopVar4];\r
568 mParent[LoopVar4] = NIL;\r
569 mNext[LoopVar4] = mAvail;\r
570 mAvail = LoopVar4;\r
5d73d92f 571}\r
572\r
3737ac2b 573/**\r
574 Read in source data\r
575\r
576 @param[out] LoopVar7 The buffer to hold the data.\r
577 @param[in] LoopVar8 The number of bytes to read.\r
578\r
579 @return The number of bytes actually read.\r
580**/\r
581INT32\r
5d73d92f 582EFIAPI\r
3737ac2b 583FreadCrc (\r
584 OUT UINT8 *LoopVar7,\r
585 IN INT32 LoopVar8\r
5d73d92f 586 )\r
3737ac2b 587{\r
588 INT32 LoopVar1;\r
5d73d92f 589\r
3737ac2b 590 for (LoopVar1 = 0; mSrc < mSrcUpperLimit && LoopVar1 < LoopVar8; LoopVar1++) {\r
591 *LoopVar7++ = *mSrc++;\r
592 }\r
5d73d92f 593\r
3737ac2b 594 LoopVar8 = LoopVar1;\r
595\r
596 LoopVar7 -= LoopVar8;\r
597 mOrigSize += LoopVar8;\r
598 LoopVar1--;\r
599 while (LoopVar1 >= 0) {\r
600 UPDATE_CRC (*LoopVar7++);\r
601 LoopVar1--;\r
602 }\r
5d73d92f 603\r
3737ac2b 604 return LoopVar8;\r
605}\r
5d73d92f 606\r
3737ac2b 607/**\r
608 Advance the current position (read in new data if needed).\r
609 Delete outdated string info. Find a match string for current position.\r
5d73d92f 610\r
ecae5117 611 @retval TRUE The operation was successful.\r
612 @retval FALSE The operation failed due to insufficient memory.\r
5d73d92f 613**/\r
ecae5117 614BOOLEAN\r
3737ac2b 615EFIAPI\r
616GetNextMatch (\r
617 VOID\r
618 )\r
5d73d92f 619{\r
3737ac2b 620 INT32 LoopVar8;\r
5d73d92f 621 VOID *Temp;\r
622\r
623 mRemainder--;\r
624 mPos++;\r
625 if (mPos == WNDSIZ * 2) {\r
3737ac2b 626 Temp = AllocateZeroPool (WNDSIZ + MAXMATCH);\r
ecae5117 627 if (Temp == NULL) {\r
628 return (FALSE);\r
629 }\r
5d73d92f 630 CopyMem (Temp, &mText[WNDSIZ], WNDSIZ + MAXMATCH);\r
631 CopyMem (&mText[0], Temp, WNDSIZ + MAXMATCH);\r
632 FreePool (Temp);\r
3737ac2b 633 LoopVar8 = FreadCrc (&mText[WNDSIZ + MAXMATCH], WNDSIZ);\r
634 mRemainder += LoopVar8;\r
5d73d92f 635 mPos = WNDSIZ;\r
636 }\r
637\r
638 DeleteNode ();\r
639 InsertNode ();\r
ecae5117 640\r
641 return (TRUE);\r
5d73d92f 642}\r
643\r
3737ac2b 644/**\r
645 Send entry LoopVar1 down the queue.\r
646\r
647 @param[in] LoopVar1 The index of the item to move.\r
648**/\r
649VOID\r
5d73d92f 650EFIAPI\r
3737ac2b 651DownHeap (\r
652 IN INT32 i\r
5d73d92f 653 )\r
3737ac2b 654{\r
655 INT32 LoopVar1;\r
5d73d92f 656\r
3737ac2b 657 INT32 LoopVar2;\r
5d73d92f 658\r
3737ac2b 659 //\r
660 // priority queue: send i-th entry down heap\r
661 //\r
662 LoopVar2 = mHeap[i];\r
663 LoopVar1 = 2 * i;\r
664 while (LoopVar1 <= mHeapSize) {\r
665 if (LoopVar1 < mHeapSize && mFreq[mHeap[LoopVar1]] > mFreq[mHeap[LoopVar1 + 1]]) {\r
666 LoopVar1++;\r
667 }\r
668\r
669 if (mFreq[LoopVar2] <= mFreq[mHeap[LoopVar1]]) {\r
670 break;\r
671 }\r
5d73d92f 672\r
3737ac2b 673 mHeap[i] = mHeap[LoopVar1];\r
674 i = LoopVar1;\r
675 LoopVar1 = 2 * i;\r
676 }\r
5d73d92f 677\r
3737ac2b 678 mHeap[i] = (INT16) LoopVar2;\r
679}\r
5d73d92f 680\r
3737ac2b 681/**\r
682 Count the number of each code length for a Huffman tree.\r
5d73d92f 683\r
3737ac2b 684 @param[in] LoopVar1 The top node.\r
5d73d92f 685**/\r
3737ac2b 686VOID\r
687EFIAPI\r
688CountLen (\r
689 IN INT32 LoopVar1\r
690 )\r
5d73d92f 691{\r
3737ac2b 692 if (LoopVar1 < mTempInt32) {\r
693 mLenCnt[(mHuffmanDepth < 16) ? mHuffmanDepth : 16]++;\r
694 } else {\r
695 mHuffmanDepth++;\r
696 CountLen (mLeft[LoopVar1]);\r
697 CountLen (mRight[LoopVar1]);\r
698 mHuffmanDepth--;\r
5d73d92f 699 }\r
3737ac2b 700}\r
5d73d92f 701\r
3737ac2b 702/**\r
703 Create code length array for a Huffman tree.\r
5d73d92f 704\r
3737ac2b 705 @param[in] Root The root of the tree.\r
706**/\r
707VOID\r
708EFIAPI\r
709MakeLen (\r
710 IN INT32 Root\r
711 )\r
712{\r
713 INT32 LoopVar1;\r
5d73d92f 714\r
3737ac2b 715 INT32 LoopVar2;\r
716 UINT32 Cum;\r
5d73d92f 717\r
3737ac2b 718 for (LoopVar1 = 0; LoopVar1 <= 16; LoopVar1++) {\r
719 mLenCnt[LoopVar1] = 0;\r
5d73d92f 720 }\r
721\r
3737ac2b 722 CountLen (Root);\r
5d73d92f 723\r
3737ac2b 724 //\r
725 // Adjust the length count array so that\r
726 // no code will be generated longer than its designated length\r
727 //\r
728 Cum = 0;\r
729 for (LoopVar1 = 16; LoopVar1 > 0; LoopVar1--) {\r
730 Cum += mLenCnt[LoopVar1] << (16 - LoopVar1);\r
731 }\r
5d73d92f 732\r
3737ac2b 733 while (Cum != (1U << 16)) {\r
734 mLenCnt[16]--;\r
735 for (LoopVar1 = 15; LoopVar1 > 0; LoopVar1--) {\r
736 if (mLenCnt[LoopVar1] != 0) {\r
737 mLenCnt[LoopVar1]--;\r
738 mLenCnt[LoopVar1 + 1] += 2;\r
739 break;\r
5d73d92f 740 }\r
741 }\r
3737ac2b 742\r
743 Cum--;\r
5d73d92f 744 }\r
745\r
3737ac2b 746 for (LoopVar1 = 16; LoopVar1 > 0; LoopVar1--) {\r
747 LoopVar2 = mLenCnt[LoopVar1];\r
748 LoopVar2--;\r
749 while (LoopVar2 >= 0) {\r
750 mLen[*mSortPtr++] = (UINT8) LoopVar1;\r
751 LoopVar2--;\r
752 }\r
753 }\r
5d73d92f 754}\r
755\r
3737ac2b 756/**\r
757 Assign code to each symbol based on the code length array.\r
758 \r
759 @param[in] LoopVar8 The number of symbols.\r
760 @param[in] Len The code length array.\r
761 @param[out] Code The stores codes for each symbol.\r
762**/\r
5d73d92f 763VOID\r
764EFIAPI\r
3737ac2b 765MakeCode (\r
766 IN INT32 LoopVar8,\r
767 IN UINT8 Len[ ],\r
768 OUT UINT16 Code[ ]\r
5d73d92f 769 )\r
3737ac2b 770{\r
771 INT32 LoopVar1;\r
772 UINT16 Start[18];\r
5d73d92f 773\r
3737ac2b 774 Start[1] = 0;\r
775 for (LoopVar1 = 1; LoopVar1 <= 16; LoopVar1++) {\r
776 Start[LoopVar1 + 1] = (UINT16) ((Start[LoopVar1] + mLenCnt[LoopVar1]) << 1);\r
777 }\r
5d73d92f 778\r
3737ac2b 779 for (LoopVar1 = 0; LoopVar1 < LoopVar8; LoopVar1++) {\r
780 Code[LoopVar1] = Start[Len[LoopVar1]]++;\r
781 }\r
782}\r
783 \r
784/**\r
785 Generates Huffman codes given a frequency distribution of symbols.\r
5d73d92f 786\r
3737ac2b 787 @param[in] NParm The number of symbols.\r
788 @param[in] FreqParm The frequency of each symbol.\r
789 @param[out] LenParm The code length for each symbol.\r
790 @param[out] CodeParm The code for each symbol.\r
5d73d92f 791\r
3737ac2b 792 @return The root of the Huffman tree.\r
5d73d92f 793**/\r
3737ac2b 794INT32\r
795EFIAPI\r
796MakeTree (\r
797 IN INT32 NParm,\r
798 IN UINT16 FreqParm[ ],\r
799 OUT UINT8 LenParm[ ],\r
800 OUT UINT16 CodeParm[ ]\r
801 )\r
5d73d92f 802{\r
3737ac2b 803 INT32 LoopVar1;\r
5d73d92f 804\r
3737ac2b 805 INT32 LoopVar2;\r
5d73d92f 806\r
3737ac2b 807 INT32 LoopVar3;\r
5d73d92f 808\r
3737ac2b 809 INT32 Avail;\r
5d73d92f 810\r
3737ac2b 811 //\r
812 // make tree, calculate len[], return root\r
813 //\r
814 mTempInt32 = NParm;\r
815 mFreq = FreqParm;\r
816 mLen = LenParm;\r
817 Avail = mTempInt32;\r
818 mHeapSize = 0;\r
819 mHeap[1] = 0;\r
820 for (LoopVar1 = 0; LoopVar1 < mTempInt32; LoopVar1++) {\r
821 mLen[LoopVar1] = 0;\r
822 if ((mFreq[LoopVar1]) != 0) {\r
823 mHeapSize++;\r
824 mHeap[mHeapSize] = (INT16) LoopVar1;\r
825 }\r
5d73d92f 826 }\r
827\r
3737ac2b 828 if (mHeapSize < 2) {\r
829 CodeParm[mHeap[1]] = 0;\r
830 return mHeap[1];\r
5d73d92f 831 }\r
832\r
3737ac2b 833 for (LoopVar1 = mHeapSize / 2; LoopVar1 >= 1; LoopVar1--) {\r
834 //\r
835 // make priority queue\r
836 //\r
837 DownHeap (LoopVar1);\r
838 }\r
5d73d92f 839\r
3737ac2b 840 mSortPtr = CodeParm;\r
841 do {\r
842 LoopVar1 = mHeap[1];\r
843 if (LoopVar1 < mTempInt32) {\r
844 *mSortPtr++ = (UINT16) LoopVar1;\r
5d73d92f 845 }\r
5d73d92f 846\r
3737ac2b 847 mHeap[1] = mHeap[mHeapSize--];\r
848 DownHeap (1);\r
849 LoopVar2 = mHeap[1];\r
850 if (LoopVar2 < mTempInt32) {\r
851 *mSortPtr++ = (UINT16) LoopVar2;\r
852 }\r
5d73d92f 853\r
3737ac2b 854 LoopVar3 = Avail++;\r
855 mFreq[LoopVar3] = (UINT16) (mFreq[LoopVar1] + mFreq[LoopVar2]);\r
856 mHeap[1] = (INT16) LoopVar3;\r
857 DownHeap (1);\r
858 mLeft[LoopVar3] = (UINT16) LoopVar1;\r
859 mRight[LoopVar3] = (UINT16) LoopVar2;\r
860 } while (mHeapSize > 1);\r
5d73d92f 861\r
3737ac2b 862 mSortPtr = CodeParm;\r
863 MakeLen (LoopVar3);\r
864 MakeCode (NParm, LenParm, CodeParm);\r
5d73d92f 865\r
3737ac2b 866 //\r
867 // return root\r
868 //\r
869 return LoopVar3;\r
870}\r
5d73d92f 871\r
3737ac2b 872/**\r
873 Outputs rightmost LoopVar8 bits of x\r
5d73d92f 874\r
3737ac2b 875 @param[in] LoopVar8 The rightmost LoopVar8 bits of the data is used.\r
876 @param[in] x The data.\r
5d73d92f 877**/\r
3737ac2b 878VOID\r
879EFIAPI\r
880PutBits (\r
881 IN INT32 LoopVar8,\r
882 IN UINT32 x\r
883 )\r
5d73d92f 884{\r
3737ac2b 885 UINT8 Temp;\r
5d73d92f 886\r
3737ac2b 887 if (LoopVar8 < mBitCount) {\r
888 mSubBitBuf |= x << (mBitCount -= LoopVar8);\r
889 } else {\r
5d73d92f 890\r
3737ac2b 891 Temp = (UINT8)(mSubBitBuf | (x >> (LoopVar8 -= mBitCount)));\r
892 if (mDst < mDstUpperLimit) {\r
893 *mDst++ = Temp;\r
894 }\r
895 mCompSize++;\r
5d73d92f 896\r
3737ac2b 897 if (LoopVar8 < UINT8_BIT) {\r
898 mSubBitBuf = x << (mBitCount = UINT8_BIT - LoopVar8);\r
5d73d92f 899 } else {\r
5d73d92f 900\r
3737ac2b 901 Temp = (UINT8)(x >> (LoopVar8 - UINT8_BIT));\r
902 if (mDst < mDstUpperLimit) {\r
903 *mDst++ = Temp;\r
5d73d92f 904 }\r
3737ac2b 905 mCompSize++;\r
5d73d92f 906\r
3737ac2b 907 mSubBitBuf = x << (mBitCount = 2 * UINT8_BIT - LoopVar8);\r
5d73d92f 908 }\r
909 }\r
910}\r
911\r
3737ac2b 912/**\r
913 Encode a signed 32 bit number.\r
914\r
915 @param[in] LoopVar5 The number to encode.\r
916**/\r
5d73d92f 917VOID\r
918EFIAPI\r
3737ac2b 919EncodeC (\r
920 IN INT32 LoopVar5\r
5d73d92f 921 )\r
3737ac2b 922{\r
923 PutBits (mCLen[LoopVar5], mCCode[LoopVar5]);\r
924}\r
5d73d92f 925\r
3737ac2b 926/**\r
927 Encode a unsigned 32 bit number.\r
5d73d92f 928\r
3737ac2b 929 @param[in] LoopVar7 The number to encode.\r
930**/\r
931VOID\r
932EFIAPI\r
933EncodeP (\r
934 IN UINT32 LoopVar7\r
935 )\r
936{\r
937 UINT32 LoopVar5;\r
5d73d92f 938\r
3737ac2b 939 UINT32 LoopVar6;\r
5d73d92f 940\r
3737ac2b 941 LoopVar5 = 0;\r
942 LoopVar6 = LoopVar7;\r
943 while (LoopVar6 != 0) {\r
944 LoopVar6 >>= 1;\r
945 LoopVar5++;\r
946 }\r
947\r
948 PutBits (mPTLen[LoopVar5], mPTCode[LoopVar5]);\r
949 if (LoopVar5 > 1) {\r
950 PutBits(LoopVar5 - 1, LoopVar7 & (0xFFFFU >> (17 - LoopVar5)));\r
951 }\r
952}\r
953\r
954/**\r
955 Count the frequencies for the Extra Set.\r
5d73d92f 956\r
957**/\r
3737ac2b 958VOID\r
959EFIAPI\r
960CountTFreq (\r
961 VOID\r
962 )\r
5d73d92f 963{\r
3737ac2b 964 INT32 LoopVar1;\r
5d73d92f 965\r
3737ac2b 966 INT32 LoopVar3;\r
5d73d92f 967\r
3737ac2b 968 INT32 LoopVar8;\r
5d73d92f 969\r
970 INT32 Count;\r
971\r
3737ac2b 972 for (LoopVar1 = 0; LoopVar1 < NT; LoopVar1++) {\r
973 mTFreq[LoopVar1] = 0;\r
5d73d92f 974 }\r
975\r
3737ac2b 976 LoopVar8 = NC;\r
977 while (LoopVar8 > 0 && mCLen[LoopVar8 - 1] == 0) {\r
978 LoopVar8--;\r
979 }\r
980\r
981 LoopVar1 = 0;\r
982 while (LoopVar1 < LoopVar8) {\r
983 LoopVar3 = mCLen[LoopVar1++];\r
984 if (LoopVar3 == 0) {\r
5d73d92f 985 Count = 1;\r
3737ac2b 986 while (LoopVar1 < LoopVar8 && mCLen[LoopVar1] == 0) {\r
987 LoopVar1++;\r
5d73d92f 988 Count++;\r
989 }\r
990\r
991 if (Count <= 2) {\r
3737ac2b 992 mTFreq[0] = (UINT16) (mTFreq[0] + Count);\r
5d73d92f 993 } else if (Count <= 18) {\r
3737ac2b 994 mTFreq[1]++;\r
5d73d92f 995 } else if (Count == 19) {\r
3737ac2b 996 mTFreq[0]++;\r
997 mTFreq[1]++;\r
5d73d92f 998 } else {\r
3737ac2b 999 mTFreq[2]++;\r
5d73d92f 1000 }\r
1001 } else {\r
3737ac2b 1002 ASSERT((LoopVar3+2)<(2 * NT - 1));\r
1003 mTFreq[LoopVar3 + 2]++;\r
5d73d92f 1004 }\r
1005 }\r
1006}\r
1007\r
3737ac2b 1008/**\r
1009 Outputs the code length array for the Extra Set or the Position Set.\r
5d73d92f 1010\r
3737ac2b 1011 @param[in] LoopVar8 The number of symbols.\r
1012 @param[in] nbit The number of bits needed to represent 'LoopVar8'.\r
1013 @param[in] Special The special symbol that needs to be take care of.\r
1014\r
1015**/\r
5d73d92f 1016VOID\r
1017EFIAPI\r
3737ac2b 1018WritePTLen (\r
1019 IN INT32 LoopVar8,\r
1020 IN INT32 nbit,\r
1021 IN INT32 Special\r
5d73d92f 1022 )\r
1023{\r
3737ac2b 1024 INT32 LoopVar1;\r
5d73d92f 1025\r
3737ac2b 1026 INT32 LoopVar3;\r
5d73d92f 1027\r
3737ac2b 1028 while (LoopVar8 > 0 && mPTLen[LoopVar8 - 1] == 0) {\r
1029 LoopVar8--;\r
5d73d92f 1030 }\r
1031\r
3737ac2b 1032 PutBits (nbit, LoopVar8);\r
1033 LoopVar1 = 0;\r
1034 while (LoopVar1 < LoopVar8) {\r
1035 LoopVar3 = mPTLen[LoopVar1++];\r
1036 if (LoopVar3 <= 6) {\r
1037 PutBits (3, LoopVar3);\r
1038 } else {\r
1039 PutBits (LoopVar3 - 3, (1U << (LoopVar3 - 3)) - 2);\r
1040 }\r
1041\r
1042 if (LoopVar1 == Special) {\r
1043 while (LoopVar1 < 6 && mPTLen[LoopVar1] == 0) {\r
1044 LoopVar1++;\r
1045 }\r
1046\r
1047 PutBits (2, (LoopVar1 - 3) & 3);\r
1048 }\r
5d73d92f 1049 }\r
1050}\r
1051\r
3737ac2b 1052/**\r
ae724571 1053 Outputs the code length array for Char&Length Set.\r
3737ac2b 1054**/\r
5d73d92f 1055VOID\r
1056EFIAPI\r
3737ac2b 1057WriteCLen (\r
5d73d92f 1058 VOID\r
1059 )\r
3737ac2b 1060{\r
1061 INT32 LoopVar1;\r
5d73d92f 1062\r
3737ac2b 1063 INT32 LoopVar3;\r
5d73d92f 1064\r
3737ac2b 1065 INT32 LoopVar8;\r
5d73d92f 1066\r
3737ac2b 1067 INT32 Count;\r
5d73d92f 1068\r
3737ac2b 1069 LoopVar8 = NC;\r
1070 while (LoopVar8 > 0 && mCLen[LoopVar8 - 1] == 0) {\r
1071 LoopVar8--;\r
1072 }\r
5d73d92f 1073\r
3737ac2b 1074 PutBits (CBIT, LoopVar8);\r
1075 LoopVar1 = 0;\r
1076 while (LoopVar1 < LoopVar8) {\r
1077 LoopVar3 = mCLen[LoopVar1++];\r
1078 if (LoopVar3 == 0) {\r
1079 Count = 1;\r
1080 while (LoopVar1 < LoopVar8 && mCLen[LoopVar1] == 0) {\r
1081 LoopVar1++;\r
1082 Count++;\r
1083 }\r
1084\r
1085 if (Count <= 2) {\r
1086 for (LoopVar3 = 0; LoopVar3 < Count; LoopVar3++) {\r
1087 PutBits (mPTLen[0], mPTCode[0]);\r
1088 }\r
1089 } else if (Count <= 18) {\r
1090 PutBits (mPTLen[1], mPTCode[1]);\r
1091 PutBits (4, Count - 3);\r
1092 } else if (Count == 19) {\r
1093 PutBits (mPTLen[0], mPTCode[0]);\r
1094 PutBits (mPTLen[1], mPTCode[1]);\r
1095 PutBits (4, 15);\r
1096 } else {\r
1097 PutBits (mPTLen[2], mPTCode[2]);\r
1098 PutBits (CBIT, Count - 20);\r
1099 }\r
1100 } else {\r
1101 ASSERT((LoopVar3+2)<NPT);\r
1102 PutBits (mPTLen[LoopVar3 + 2], mPTCode[LoopVar3 + 2]);\r
1103 }\r
1104 }\r
1105}\r
5d73d92f 1106\r
3737ac2b 1107/**\r
1108 Huffman code the block and output it.\r
5d73d92f 1109\r
1110**/\r
3737ac2b 1111VOID\r
1112EFIAPI\r
1113SendBlock (\r
1114 VOID\r
1115 )\r
5d73d92f 1116{\r
3737ac2b 1117 UINT32 LoopVar1;\r
5d73d92f 1118\r
3737ac2b 1119 UINT32 LoopVar3;\r
5d73d92f 1120\r
1121 UINT32 Flags;\r
1122\r
1123 UINT32 Root;\r
1124\r
1125 UINT32 Pos;\r
1126\r
1127 UINT32 Size;\r
1128 Flags = 0;\r
1129\r
1130 Root = MakeTree (NC, mCFreq, mCLen, mCCode);\r
1131 Size = mCFreq[Root];\r
1132 PutBits (16, Size);\r
1133 if (Root >= NC) {\r
1134 CountTFreq ();\r
1135 Root = MakeTree (NT, mTFreq, mPTLen, mPTCode);\r
1136 if (Root >= NT) {\r
1137 WritePTLen (NT, TBIT, 3);\r
1138 } else {\r
1139 PutBits (TBIT, 0);\r
1140 PutBits (TBIT, Root);\r
1141 }\r
1142\r
1143 WriteCLen ();\r
1144 } else {\r
1145 PutBits (TBIT, 0);\r
1146 PutBits (TBIT, 0);\r
1147 PutBits (CBIT, 0);\r
1148 PutBits (CBIT, Root);\r
1149 }\r
1150\r
1151 Root = MakeTree (NP, mPFreq, mPTLen, mPTCode);\r
1152 if (Root >= NP) {\r
1153 WritePTLen (NP, PBIT, -1);\r
1154 } else {\r
1155 PutBits (PBIT, 0);\r
1156 PutBits (PBIT, Root);\r
1157 }\r
1158\r
1159 Pos = 0;\r
3737ac2b 1160 for (LoopVar1 = 0; LoopVar1 < Size; LoopVar1++) {\r
1161 if (LoopVar1 % UINT8_BIT == 0) {\r
5d73d92f 1162 Flags = mBuf[Pos++];\r
1163 } else {\r
1164 Flags <<= 1;\r
1165 }\r
1166 if ((Flags & (1U << (UINT8_BIT - 1))) != 0){\r
1167 EncodeC(mBuf[Pos++] + (1U << UINT8_BIT));\r
3737ac2b 1168 LoopVar3 = mBuf[Pos++] << UINT8_BIT;\r
1169 LoopVar3 += mBuf[Pos++];\r
5d73d92f 1170\r
3737ac2b 1171 EncodeP (LoopVar3);\r
5d73d92f 1172 } else {\r
1173 EncodeC (mBuf[Pos++]);\r
1174 }\r
1175 }\r
1176\r
1177 SetMem (mCFreq, NC * sizeof (UINT16), 0);\r
1178 SetMem (mPFreq, NP * sizeof (UINT16), 0);\r
1179}\r
1180\r
3737ac2b 1181/**\r
1182 Start the huffman encoding.\r
1183\r
1184**/\r
5d73d92f 1185VOID\r
1186EFIAPI\r
3737ac2b 1187HufEncodeStart (\r
1188 VOID\r
5d73d92f 1189 )\r
3737ac2b 1190{\r
1191 SetMem (mCFreq, NC * sizeof (UINT16), 0);\r
1192 SetMem (mPFreq, NP * sizeof (UINT16), 0);\r
5d73d92f 1193\r
3737ac2b 1194 mOutputPos = mOutputMask = 0;\r
5d73d92f 1195\r
3737ac2b 1196 mBitCount = UINT8_BIT;\r
1197 mSubBitBuf = 0;\r
1198}\r
5d73d92f 1199\r
3737ac2b 1200/**\r
1201 Outputs an Original Character or a Pointer.\r
5d73d92f 1202\r
3737ac2b 1203 @param[in] LoopVar5 The original character or the 'String Length' element of \r
1204 a Pointer.\r
1205 @param[in] LoopVar7 The 'Position' field of a Pointer.\r
5d73d92f 1206**/\r
3737ac2b 1207VOID\r
1208EFIAPI\r
1209CompressOutput (\r
1210 IN UINT32 LoopVar5,\r
1211 IN UINT32 LoopVar7\r
1212 )\r
5d73d92f 1213{\r
1214 STATIC UINT32 CPos;\r
1215\r
1216 if ((mOutputMask >>= 1) == 0) {\r
1217 mOutputMask = 1U << (UINT8_BIT - 1);\r
1218 if (mOutputPos >= mBufSiz - 3 * UINT8_BIT) {\r
1219 SendBlock ();\r
1220 mOutputPos = 0;\r
1221 }\r
1222\r
1223 CPos = mOutputPos++;\r
1224 mBuf[CPos] = 0;\r
1225 }\r
3737ac2b 1226 mBuf[mOutputPos++] = (UINT8) LoopVar5;\r
1227 mCFreq[LoopVar5]++;\r
1228 if (LoopVar5 >= (1U << UINT8_BIT)) {\r
5d73d92f 1229 mBuf[CPos] = (UINT8)(mBuf[CPos]|mOutputMask);\r
3737ac2b 1230 mBuf[mOutputPos++] = (UINT8)(LoopVar7 >> UINT8_BIT);\r
1231 mBuf[mOutputPos++] = (UINT8) LoopVar7;\r
1232 LoopVar5 = 0;\r
1233 while (LoopVar7!=0) {\r
1234 LoopVar7 >>= 1;\r
1235 LoopVar5++;\r
5d73d92f 1236 }\r
3737ac2b 1237 mPFreq[LoopVar5]++;\r
5d73d92f 1238 }\r
1239}\r
1240\r
3737ac2b 1241/**\r
1242 End the huffman encoding.\r
5d73d92f 1243\r
3737ac2b 1244**/\r
5d73d92f 1245VOID\r
1246EFIAPI\r
1247HufEncodeEnd (\r
1248 VOID\r
1249 )\r
1250{\r
1251 SendBlock ();\r
1252\r
1253 //\r
1254 // Flush remaining bits\r
1255 //\r
1256 PutBits (UINT8_BIT - 1, 0);\r
5d73d92f 1257}\r
1258\r
3737ac2b 1259/**\r
1260 The main controlling routine for compression process.\r
1261\r
1262 @retval EFI_SUCCESS The compression is successful.\r
1263 @retval EFI_OUT_0F_RESOURCES Not enough memory for compression process.\r
1264**/\r
1265EFI_STATUS\r
5d73d92f 1266EFIAPI\r
3737ac2b 1267Encode (\r
5d73d92f 1268 VOID\r
1269 )\r
1270{\r
3737ac2b 1271 EFI_STATUS Status;\r
1272 INT32 LastMatchLen;\r
1273 NODE LastMatchPos;\r
5d73d92f 1274\r
3737ac2b 1275 Status = AllocateMemory ();\r
1276 if (EFI_ERROR (Status)) {\r
1277 FreeMemory ();\r
1278 return Status;\r
5d73d92f 1279 }\r
5d73d92f 1280\r
3737ac2b 1281 InitSlide ();\r
5d73d92f 1282\r
3737ac2b 1283 HufEncodeStart ();\r
5d73d92f 1284\r
3737ac2b 1285 mRemainder = FreadCrc (&mText[WNDSIZ], WNDSIZ + MAXMATCH);\r
5d73d92f 1286\r
3737ac2b 1287 mMatchLen = 0;\r
1288 mPos = WNDSIZ;\r
1289 InsertNode ();\r
1290 if (mMatchLen > mRemainder) {\r
1291 mMatchLen = mRemainder;\r
1292 }\r
5d73d92f 1293\r
3737ac2b 1294 while (mRemainder > 0) {\r
1295 LastMatchLen = mMatchLen;\r
1296 LastMatchPos = mMatchPos;\r
ecae5117 1297 if (!GetNextMatch ()) {\r
1298 Status = EFI_OUT_OF_RESOURCES;\r
1299 }\r
3737ac2b 1300 if (mMatchLen > mRemainder) {\r
1301 mMatchLen = mRemainder;\r
5d73d92f 1302 }\r
5d73d92f 1303\r
3737ac2b 1304 if (mMatchLen > LastMatchLen || LastMatchLen < THRESHOLD) {\r
1305 //\r
1306 // Not enough benefits are gained by outputting a pointer,\r
1307 // so just output the original character\r
1308 //\r
1309 CompressOutput(mText[mPos - 1], 0);\r
5d73d92f 1310 } else {\r
3737ac2b 1311 //\r
1312 // Outputting a pointer is beneficial enough, do it.\r
1313 //\r
5d73d92f 1314\r
3737ac2b 1315 CompressOutput(LastMatchLen + (UINT8_MAX + 1 - THRESHOLD),\r
1316 (mPos - LastMatchPos - 2) & (WNDSIZ - 1));\r
1317 LastMatchLen--;\r
1318 while (LastMatchLen > 0) {\r
ecae5117 1319 if (!GetNextMatch ()) {\r
1320 Status = EFI_OUT_OF_RESOURCES;\r
1321 }\r
3737ac2b 1322 LastMatchLen--;\r
5d73d92f 1323 }\r
5d73d92f 1324\r
3737ac2b 1325 if (mMatchLen > mRemainder) {\r
1326 mMatchLen = mRemainder;\r
1327 }\r
5d73d92f 1328 }\r
1329 }\r
5d73d92f 1330\r
3737ac2b 1331 HufEncodeEnd ();\r
1332 FreeMemory ();\r
ecae5117 1333 return (Status);\r
5d73d92f 1334}\r
1335\r
3737ac2b 1336/**\r
1337 The compression routine.\r
5d73d92f 1338\r
4ff7e37b
ED
1339 @param[in] SrcBuffer The buffer containing the source data.\r
1340 @param[in] SrcSize The number of bytes in SrcBuffer.\r
1341 @param[in] DstBuffer The buffer to put the compressed image in.\r
1342 @param[in, out] DstSize On input the size (in bytes) of DstBuffer, on\r
3737ac2b 1343 return the number of bytes placed in DstBuffer.\r
5d73d92f 1344\r
3737ac2b 1345 @retval EFI_SUCCESS The compression was sucessful.\r
1346 @retval EFI_BUFFER_TOO_SMALL The buffer was too small. DstSize is required.\r
5d73d92f 1347**/\r
3737ac2b 1348EFI_STATUS\r
5d73d92f 1349EFIAPI\r
3737ac2b 1350Compress (\r
1351 IN VOID *SrcBuffer,\r
1352 IN UINT64 SrcSize,\r
1353 IN VOID *DstBuffer,\r
1354 IN OUT UINT64 *DstSize\r
5d73d92f 1355 )\r
5d73d92f 1356{\r
3737ac2b 1357 EFI_STATUS Status;\r
5d73d92f 1358\r
1359 //\r
3737ac2b 1360 // Initializations\r
5d73d92f 1361 //\r
3737ac2b 1362 mBufSiz = 0;\r
1363 mBuf = NULL;\r
1364 mText = NULL;\r
1365 mLevel = NULL;\r
1366 mChildCount = NULL;\r
1367 mPosition = NULL;\r
1368 mParent = NULL;\r
1369 mPrev = NULL;\r
1370 mNext = NULL;\r
5d73d92f 1371\r
3737ac2b 1372 mSrc = SrcBuffer;\r
1373 mSrcUpperLimit = mSrc + SrcSize;\r
1374 mDst = DstBuffer;\r
1375 mDstUpperLimit = mDst +*DstSize;\r
5d73d92f 1376\r
3737ac2b 1377 PutDword (0L);\r
1378 PutDword (0L);\r
5d73d92f 1379\r
3737ac2b 1380 MakeCrcTable ();\r
5d73d92f 1381\r
3737ac2b 1382 mOrigSize = mCompSize = 0;\r
1383 mCrc = INIT_CRC;\r
5d73d92f 1384\r
1385 //\r
3737ac2b 1386 // Compress it\r
5d73d92f 1387 //\r
3737ac2b 1388 Status = Encode ();\r
1389 if (EFI_ERROR (Status)) {\r
1390 return EFI_OUT_OF_RESOURCES;\r
5d73d92f 1391 }\r
5d73d92f 1392 //\r
3737ac2b 1393 // Null terminate the compressed data\r
5d73d92f 1394 //\r
3737ac2b 1395 if (mDst < mDstUpperLimit) {\r
1396 *mDst++ = 0;\r
5d73d92f 1397 }\r
3737ac2b 1398 //\r
1399 // Fill in compressed size and original size\r
1400 //\r
1401 mDst = DstBuffer;\r
1402 PutDword (mCompSize + 1);\r
1403 PutDword (mOrigSize);\r
5d73d92f 1404\r
1405 //\r
3737ac2b 1406 // Return\r
5d73d92f 1407 //\r
3737ac2b 1408 if (mCompSize + 1 + 8 > *DstSize) {\r
1409 *DstSize = mCompSize + 1 + 8;\r
1410 return EFI_BUFFER_TOO_SMALL;\r
1411 } else {\r
1412 *DstSize = mCompSize + 1 + 8;\r
1413 return EFI_SUCCESS;\r
1414 }\r
1415\r
5d73d92f 1416}\r
3737ac2b 1417\r