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