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