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