1 /** @file 2 Compression routine. The compression algorithm is a mixture of LZ77 and Huffman 3 coding. LZ77 transforms the source data into a sequence of Original Characters 4 and Pointers to repeated strings. 5 This sequence is further divided into Blocks and Huffman codings are applied to 6 each Block. 7 8 Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR> 9 This program and the accompanying materials 10 are licensed and made available under the terms and conditions of the BSD License 11 which accompanies this distribution. The full text of the license may be found at 12 http://opensource.org/licenses/bsd-license.php 13 14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 15 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 16 17 **/ 18 19 #include "Compress.h" 20 #include "TianoCompress.h" 21 #include "EfiUtilityMsgs.h" 22 #include "ParseInf.h" 23 #include <stdio.h> 24 #include "assert.h" 25 26 // 27 // Macro Definitions 28 // 29 static BOOLEAN VerboseMode = FALSE; 30 static BOOLEAN QuietMode = FALSE; 31 #undef UINT8_MAX 32 #define UINT8_MAX 0xff 33 #define UINT8_BIT 8 34 #define THRESHOLD 3 35 #define INIT_CRC 0 36 #define WNDBIT 19 37 #define WNDSIZ (1U << WNDBIT) 38 #define MAXMATCH 256 39 #define BLKSIZ (1U << 14) // 16 * 1024U 40 #define PERC_FLAG 0x80000000U 41 #define CODE_BIT 16 42 #define NIL 0 43 #define MAX_HASH_VAL (3 * WNDSIZ + (WNDSIZ / 512 + 1) * UINT8_MAX) 44 #define HASH(p, c) ((p) + ((c) << (WNDBIT - 9)) + WNDSIZ * 2) 45 #define CRCPOLY 0xA001 46 #define UPDATE_CRC(c) mCrc = mCrcTable[(mCrc ^ (c)) & 0xFF] ^ (mCrc >> UINT8_BIT) 47 48 // 49 // C: the Char&Len Set; P: the Position Set; T: the exTra Set 50 // 51 //#define NC (UINT8_MAX + MAXMATCH + 2 - THRESHOLD) 52 #define CBIT 9 53 #define NP (WNDBIT + 1) 54 #define PBIT 5 55 //#define NT (CODE_BIT + 3) 56 //#define TBIT 5 57 //#if NT > NP 58 //#define NPT NT 59 //#else 60 //#define NPT NP 61 //#endif 62 63 // 64 // Global Variables 65 // 66 STATIC BOOLEAN ENCODE = FALSE; 67 STATIC BOOLEAN DECODE = FALSE; 68 STATIC UINT8 *mSrc, *mDst, *mSrcUpperLimit, *mDstUpperLimit; 69 STATIC UINT8 *mLevel, *mText, *mChildCount, *mBuf, mCLen[NC], mPTLen[NPT], *mLen; 70 STATIC INT16 mHeap[NC + 1]; 71 STATIC INT32 mRemainder, mMatchLen, mBitCount, mHeapSize, mN; 72 STATIC UINT32 mBufSiz = 0, mOutputPos, mOutputMask, mSubBitBuf, mCrc; 73 STATIC UINT32 mCompSize, mOrigSize; 74 75 STATIC UINT16 *mFreq, *mSortPtr, mLenCnt[17], mLeft[2 * NC - 1], mRight[2 * NC - 1], mCrcTable[UINT8_MAX + 1], 76 mCFreq[2 * NC - 1], mCCode[NC], mPFreq[2 * NP - 1], mPTCode[NPT], mTFreq[2 * NT - 1]; 77 78 STATIC NODE mPos, mMatchPos, mAvail, *mPosition, *mParent, *mPrev, *mNext = NULL; 79 80 static UINT64 DebugLevel; 81 static BOOLEAN DebugMode; 82 // 83 // functions 84 // 85 EFI_STATUS 86 TianoCompress ( 87 IN UINT8 *SrcBuffer, 88 IN UINT32 SrcSize, 89 IN UINT8 *DstBuffer, 90 IN OUT UINT32 *DstSize 91 ) 92 /*++ 93 94 Routine Description: 95 96 The internal implementation of [Efi/Tiano]Compress(). 97 98 Arguments: 99 100 SrcBuffer - The buffer storing the source data 101 SrcSize - The size of source data 102 DstBuffer - The buffer to store the compressed data 103 104 Version - The version of de/compression algorithm. 105 Version 1 for EFI 1.1 de/compression algorithm. 106 Version 2 for Tiano de/compression algorithm. 107 108 Returns: 109 110 EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. In this case, 111 DstSize contains the size needed. 112 EFI_SUCCESS - Compression is successful. 113 EFI_OUT_OF_RESOURCES - No resource to complete function. 114 EFI_INVALID_PARAMETER - Parameter supplied is wrong. 115 116 --*/ 117 { 118 EFI_STATUS Status; 119 120 // 121 // Initializations 122 // 123 mBufSiz = 0; 124 mBuf = NULL; 125 mText = NULL; 126 mLevel = NULL; 127 mChildCount = NULL; 128 mPosition = NULL; 129 mParent = NULL; 130 mPrev = NULL; 131 mNext = NULL; 132 133 134 mSrc = SrcBuffer; 135 mSrcUpperLimit = mSrc + SrcSize; 136 mDst = DstBuffer; 137 mDstUpperLimit = mDst +*DstSize; 138 139 PutDword (0L); 140 PutDword (0L); 141 142 MakeCrcTable (); 143 144 mOrigSize = mCompSize = 0; 145 mCrc = INIT_CRC; 146 147 // 148 // Compress it 149 // 150 Status = Encode (); 151 if (EFI_ERROR (Status)) { 152 return EFI_OUT_OF_RESOURCES; 153 } 154 155 // 156 // Null terminate the compressed data 157 // 158 159 if (mDst < mDstUpperLimit) { 160 *mDst++ = 0; 161 } 162 163 // 164 // Fill in compressed size and original size 165 // 166 mDst = DstBuffer; 167 168 PutDword (mCompSize + 1); 169 PutDword (mOrigSize); 170 // 171 // Return 172 // 173 174 if (mCompSize + 1 + 8 > *DstSize) { 175 *DstSize = mCompSize + 1 + 8; 176 return EFI_BUFFER_TOO_SMALL; 177 } else { 178 *DstSize = mCompSize + 1 + 8; 179 return EFI_SUCCESS; 180 } 181 } 182 183 STATIC 184 VOID 185 PutDword ( 186 IN UINT32 Data 187 ) 188 /*++ 189 190 Routine Description: 191 192 Put a dword to output stream 193 194 Arguments: 195 196 Data - the dword to put 197 198 Returns: (VOID) 199 200 --*/ 201 { 202 if (mDst < mDstUpperLimit) { 203 *mDst++ = (UINT8) (((UINT8) (Data)) & 0xff); 204 } 205 206 if (mDst < mDstUpperLimit) { 207 *mDst++ = (UINT8) (((UINT8) (Data >> 0x08)) & 0xff); 208 } 209 210 if (mDst < mDstUpperLimit) { 211 *mDst++ = (UINT8) (((UINT8) (Data >> 0x10)) & 0xff); 212 } 213 214 if (mDst < mDstUpperLimit) { 215 *mDst++ = (UINT8) (((UINT8) (Data >> 0x18)) & 0xff); 216 } 217 } 218 219 STATIC 220 EFI_STATUS 221 AllocateMemory ( 222 VOID 223 ) 224 /*++ 225 226 Routine Description: 227 228 Allocate memory spaces for data structures used in compression process 229 230 Argements: 231 VOID 232 233 Returns: 234 235 EFI_SUCCESS - Memory is allocated successfully 236 EFI_OUT_OF_RESOURCES - Allocation fails 237 238 --*/ 239 { 240 UINT32 Index; 241 242 mText = malloc (WNDSIZ * 2 + MAXMATCH); 243 for (Index = 0; Index < WNDSIZ * 2 + MAXMATCH; Index++) { 244 mText[Index] = 0; 245 } 246 247 mLevel = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mLevel)); 248 mChildCount = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mChildCount)); 249 mPosition = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mPosition)); 250 mParent = malloc (WNDSIZ * 2 * sizeof (*mParent)); 251 mPrev = malloc (WNDSIZ * 2 * sizeof (*mPrev)); 252 mNext = malloc ((MAX_HASH_VAL + 1) * sizeof (*mNext)); 253 254 mBufSiz = BLKSIZ; 255 mBuf = malloc (mBufSiz); 256 while (mBuf == NULL) { 257 mBufSiz = (mBufSiz / 10U) * 9U; 258 if (mBufSiz < 4 * 1024U) { 259 return EFI_OUT_OF_RESOURCES; 260 } 261 262 mBuf = malloc (mBufSiz); 263 } 264 265 mBuf[0] = 0; 266 267 return EFI_SUCCESS; 268 } 269 270 VOID 271 FreeMemory ( 272 VOID 273 ) 274 /*++ 275 276 Routine Description: 277 278 Called when compression is completed to free memory previously allocated. 279 280 Arguments: (VOID) 281 282 Returns: (VOID) 283 284 --*/ 285 { 286 if (mText != NULL) { 287 free (mText); 288 } 289 290 if (mLevel != NULL) { 291 free (mLevel); 292 } 293 294 if (mChildCount != NULL) { 295 free (mChildCount); 296 } 297 298 if (mPosition != NULL) { 299 free (mPosition); 300 } 301 302 if (mParent != NULL) { 303 free (mParent); 304 } 305 306 if (mPrev != NULL) { 307 free (mPrev); 308 } 309 310 if (mNext != NULL) { 311 free (mNext); 312 } 313 314 if (mBuf != NULL) { 315 free (mBuf); 316 } 317 318 return ; 319 } 320 321 STATIC 322 VOID 323 InitSlide ( 324 VOID 325 ) 326 /*++ 327 328 Routine Description: 329 330 Initialize String Info Log data structures 331 332 Arguments: (VOID) 333 334 Returns: (VOID) 335 336 --*/ 337 { 338 NODE Index; 339 340 for (Index = WNDSIZ; Index <= WNDSIZ + UINT8_MAX; Index++) { 341 mLevel[Index] = 1; 342 mPosition[Index] = NIL; // sentinel 343 } 344 345 for (Index = WNDSIZ; Index < WNDSIZ * 2; Index++) { 346 mParent[Index] = NIL; 347 } 348 349 mAvail = 1; 350 for (Index = 1; Index < WNDSIZ - 1; Index++) { 351 mNext[Index] = (NODE) (Index + 1); 352 } 353 354 mNext[WNDSIZ - 1] = NIL; 355 for (Index = WNDSIZ * 2; Index <= MAX_HASH_VAL; Index++) { 356 mNext[Index] = NIL; 357 } 358 } 359 360 STATIC 361 NODE 362 Child ( 363 IN NODE NodeQ, 364 IN UINT8 CharC 365 ) 366 /*++ 367 368 Routine Description: 369 370 Find child node given the parent node and the edge character 371 372 Arguments: 373 374 NodeQ - the parent node 375 CharC - the edge character 376 377 Returns: 378 379 The child node (NIL if not found) 380 381 --*/ 382 { 383 NODE NodeR; 384 385 NodeR = mNext[HASH (NodeQ, CharC)]; 386 // 387 // sentinel 388 // 389 mParent[NIL] = NodeQ; 390 while (mParent[NodeR] != NodeQ) { 391 NodeR = mNext[NodeR]; 392 } 393 394 return NodeR; 395 } 396 397 STATIC 398 VOID 399 MakeChild ( 400 IN NODE Parent, 401 IN UINT8 CharC, 402 IN NODE Child 403 ) 404 /*++ 405 406 Routine Description: 407 408 Create a new child for a given parent node. 409 410 Arguments: 411 412 Parent - the parent node 413 CharC - the edge character 414 Child - the child node 415 416 Returns: (VOID) 417 418 --*/ 419 { 420 NODE Node1; 421 NODE Node2; 422 423 Node1 = (NODE) HASH (Parent, CharC); 424 Node2 = mNext[Node1]; 425 mNext[Node1] = Child; 426 mNext[Child] = Node2; 427 mPrev[Node2] = Child; 428 mPrev[Child] = Node1; 429 mParent[Child] = Parent; 430 mChildCount[Parent]++; 431 } 432 433 STATIC 434 VOID 435 Split ( 436 NODE Old 437 ) 438 /*++ 439 440 Routine Description: 441 442 Split a node. 443 444 Arguments: 445 446 Old - the node to split 447 448 Returns: (VOID) 449 450 --*/ 451 { 452 NODE New; 453 NODE TempNode; 454 455 New = mAvail; 456 mAvail = mNext[New]; 457 mChildCount[New] = 0; 458 TempNode = mPrev[Old]; 459 mPrev[New] = TempNode; 460 mNext[TempNode] = New; 461 TempNode = mNext[Old]; 462 mNext[New] = TempNode; 463 mPrev[TempNode] = New; 464 mParent[New] = mParent[Old]; 465 mLevel[New] = (UINT8) mMatchLen; 466 mPosition[New] = mPos; 467 MakeChild (New, mText[mMatchPos + mMatchLen], Old); 468 MakeChild (New, mText[mPos + mMatchLen], mPos); 469 } 470 471 STATIC 472 VOID 473 InsertNode ( 474 VOID 475 ) 476 /*++ 477 478 Routine Description: 479 480 Insert string info for current position into the String Info Log 481 482 Arguments: (VOID) 483 484 Returns: (VOID) 485 486 --*/ 487 { 488 NODE NodeQ; 489 NODE NodeR; 490 NODE Index2; 491 NODE NodeT; 492 UINT8 CharC; 493 UINT8 *t1; 494 UINT8 *t2; 495 496 if (mMatchLen >= 4) { 497 // 498 // We have just got a long match, the target tree 499 // can be located by MatchPos + 1. Travese the tree 500 // from bottom up to get to a proper starting point. 501 // The usage of PERC_FLAG ensures proper node deletion 502 // in DeleteNode() later. 503 // 504 mMatchLen--; 505 NodeR = (NODE) ((mMatchPos + 1) | WNDSIZ); 506 NodeQ = mParent[NodeR]; 507 while (NodeQ == NIL) { 508 NodeR = mNext[NodeR]; 509 NodeQ = mParent[NodeR]; 510 } 511 512 while (mLevel[NodeQ] >= mMatchLen) { 513 NodeR = NodeQ; 514 NodeQ = mParent[NodeQ]; 515 } 516 517 NodeT = NodeQ; 518 while (mPosition[NodeT] < 0) { 519 mPosition[NodeT] = mPos; 520 NodeT = mParent[NodeT]; 521 } 522 523 if (NodeT < WNDSIZ) { 524 mPosition[NodeT] = (NODE) (mPos | (UINT32) PERC_FLAG); 525 } 526 } else { 527 // 528 // Locate the target tree 529 // 530 NodeQ = (NODE) (mText[mPos] + WNDSIZ); 531 CharC = mText[mPos + 1]; 532 NodeR = Child (NodeQ, CharC); 533 if (NodeR == NIL) { 534 MakeChild (NodeQ, CharC, mPos); 535 mMatchLen = 1; 536 return ; 537 } 538 539 mMatchLen = 2; 540 } 541 // 542 // Traverse down the tree to find a match. 543 // Update Position value along the route. 544 // Node split or creation is involved. 545 // 546 for (;;) { 547 if (NodeR >= WNDSIZ) { 548 Index2 = MAXMATCH; 549 mMatchPos = NodeR; 550 } else { 551 Index2 = mLevel[NodeR]; 552 mMatchPos = (NODE) (mPosition[NodeR] & (UINT32)~PERC_FLAG); 553 } 554 555 if (mMatchPos >= mPos) { 556 mMatchPos -= WNDSIZ; 557 } 558 559 t1 = &mText[mPos + mMatchLen]; 560 t2 = &mText[mMatchPos + mMatchLen]; 561 while (mMatchLen < Index2) { 562 if (*t1 != *t2) { 563 Split (NodeR); 564 return ; 565 } 566 567 mMatchLen++; 568 t1++; 569 t2++; 570 } 571 572 if (mMatchLen >= MAXMATCH) { 573 break; 574 } 575 576 mPosition[NodeR] = mPos; 577 NodeQ = NodeR; 578 NodeR = Child (NodeQ, *t1); 579 if (NodeR == NIL) { 580 MakeChild (NodeQ, *t1, mPos); 581 return ; 582 } 583 584 mMatchLen++; 585 } 586 587 NodeT = mPrev[NodeR]; 588 mPrev[mPos] = NodeT; 589 mNext[NodeT] = mPos; 590 NodeT = mNext[NodeR]; 591 mNext[mPos] = NodeT; 592 mPrev[NodeT] = mPos; 593 mParent[mPos] = NodeQ; 594 mParent[NodeR] = NIL; 595 596 // 597 // Special usage of 'next' 598 // 599 mNext[NodeR] = mPos; 600 601 } 602 603 STATIC 604 VOID 605 DeleteNode ( 606 VOID 607 ) 608 /*++ 609 610 Routine Description: 611 612 Delete outdated string info. (The Usage of PERC_FLAG 613 ensures a clean deletion) 614 615 Arguments: (VOID) 616 617 Returns: (VOID) 618 619 --*/ 620 { 621 NODE NodeQ; 622 NODE NodeR; 623 NODE NodeS; 624 NODE NodeT; 625 NODE NodeU; 626 627 if (mParent[mPos] == NIL) { 628 return ; 629 } 630 631 NodeR = mPrev[mPos]; 632 NodeS = mNext[mPos]; 633 mNext[NodeR] = NodeS; 634 mPrev[NodeS] = NodeR; 635 NodeR = mParent[mPos]; 636 mParent[mPos] = NIL; 637 if (NodeR >= WNDSIZ) { 638 return ; 639 } 640 641 mChildCount[NodeR]--; 642 if (mChildCount[NodeR] > 1) { 643 return ; 644 } 645 646 NodeT = (NODE) (mPosition[NodeR] & (UINT32)~PERC_FLAG); 647 if (NodeT >= mPos) { 648 NodeT -= WNDSIZ; 649 } 650 651 NodeS = NodeT; 652 NodeQ = mParent[NodeR]; 653 NodeU = mPosition[NodeQ]; 654 while (NodeU & (UINT32) PERC_FLAG) { 655 NodeU &= (UINT32)~PERC_FLAG; 656 if (NodeU >= mPos) { 657 NodeU -= WNDSIZ; 658 } 659 660 if (NodeU > NodeS) { 661 NodeS = NodeU; 662 } 663 664 mPosition[NodeQ] = (NODE) (NodeS | WNDSIZ); 665 NodeQ = mParent[NodeQ]; 666 NodeU = mPosition[NodeQ]; 667 } 668 669 if (NodeQ < WNDSIZ) { 670 if (NodeU >= mPos) { 671 NodeU -= WNDSIZ; 672 } 673 674 if (NodeU > NodeS) { 675 NodeS = NodeU; 676 } 677 678 mPosition[NodeQ] = (NODE) (NodeS | WNDSIZ | (UINT32) PERC_FLAG); 679 } 680 681 NodeS = Child (NodeR, mText[NodeT + mLevel[NodeR]]); 682 NodeT = mPrev[NodeS]; 683 NodeU = mNext[NodeS]; 684 mNext[NodeT] = NodeU; 685 mPrev[NodeU] = NodeT; 686 NodeT = mPrev[NodeR]; 687 mNext[NodeT] = NodeS; 688 mPrev[NodeS] = NodeT; 689 NodeT = mNext[NodeR]; 690 mPrev[NodeT] = NodeS; 691 mNext[NodeS] = NodeT; 692 mParent[NodeS] = mParent[NodeR]; 693 mParent[NodeR] = NIL; 694 mNext[NodeR] = mAvail; 695 mAvail = NodeR; 696 } 697 698 STATIC 699 VOID 700 GetNextMatch ( 701 VOID 702 ) 703 /*++ 704 705 Routine Description: 706 707 Advance the current position (read in new data if needed). 708 Delete outdated string info. Find a match string for current position. 709 710 Arguments: (VOID) 711 712 Returns: (VOID) 713 714 --*/ 715 { 716 INT32 Number; 717 718 mRemainder--; 719 mPos++; 720 if (mPos == WNDSIZ * 2) { 721 memmove (&mText[0], &mText[WNDSIZ], WNDSIZ + MAXMATCH); 722 Number = FreadCrc (&mText[WNDSIZ + MAXMATCH], WNDSIZ); 723 mRemainder += Number; 724 mPos = WNDSIZ; 725 } 726 727 DeleteNode (); 728 InsertNode (); 729 } 730 731 STATIC 732 EFI_STATUS 733 Encode ( 734 VOID 735 ) 736 /*++ 737 738 Routine Description: 739 740 The main controlling routine for compression process. 741 742 Arguments: (VOID) 743 744 Returns: 745 746 EFI_SUCCESS - The compression is successful 747 EFI_OUT_0F_RESOURCES - Not enough memory for compression process 748 749 --*/ 750 { 751 EFI_STATUS Status; 752 INT32 LastMatchLen; 753 NODE LastMatchPos; 754 755 Status = AllocateMemory (); 756 if (EFI_ERROR (Status)) { 757 FreeMemory (); 758 return Status; 759 } 760 761 InitSlide (); 762 763 HufEncodeStart (); 764 765 mRemainder = FreadCrc (&mText[WNDSIZ], WNDSIZ + MAXMATCH); 766 767 mMatchLen = 0; 768 mPos = WNDSIZ; 769 InsertNode (); 770 if (mMatchLen > mRemainder) { 771 mMatchLen = mRemainder; 772 } 773 774 while (mRemainder > 0) { 775 LastMatchLen = mMatchLen; 776 LastMatchPos = mMatchPos; 777 GetNextMatch (); 778 if (mMatchLen > mRemainder) { 779 mMatchLen = mRemainder; 780 } 781 782 if (mMatchLen > LastMatchLen || LastMatchLen < THRESHOLD) { 783 // 784 // Not enough benefits are gained by outputting a pointer, 785 // so just output the original character 786 // 787 Output (mText[mPos - 1], 0); 788 789 } else { 790 791 if (LastMatchLen == THRESHOLD) { 792 if (((mPos - LastMatchPos - 2) & (WNDSIZ - 1)) > (1U << 11)) { 793 Output (mText[mPos - 1], 0); 794 continue; 795 } 796 } 797 // 798 // Outputting a pointer is beneficial enough, do it. 799 // 800 Output ( 801 LastMatchLen + (UINT8_MAX + 1 - THRESHOLD), 802 (mPos - LastMatchPos - 2) & (WNDSIZ - 1) 803 ); 804 LastMatchLen--; 805 while (LastMatchLen > 0) { 806 GetNextMatch (); 807 LastMatchLen--; 808 } 809 810 if (mMatchLen > mRemainder) { 811 mMatchLen = mRemainder; 812 } 813 } 814 } 815 816 HufEncodeEnd (); 817 FreeMemory (); 818 return EFI_SUCCESS; 819 } 820 821 STATIC 822 VOID 823 CountTFreq ( 824 VOID 825 ) 826 /*++ 827 828 Routine Description: 829 830 Count the frequencies for the Extra Set 831 832 Arguments: (VOID) 833 834 Returns: (VOID) 835 836 --*/ 837 { 838 INT32 Index; 839 INT32 Index3; 840 INT32 Number; 841 INT32 Count; 842 843 for (Index = 0; Index < NT; Index++) { 844 mTFreq[Index] = 0; 845 } 846 847 Number = NC; 848 while (Number > 0 && mCLen[Number - 1] == 0) { 849 Number--; 850 } 851 852 Index = 0; 853 while (Index < Number) { 854 Index3 = mCLen[Index++]; 855 if (Index3 == 0) { 856 Count = 1; 857 while (Index < Number && mCLen[Index] == 0) { 858 Index++; 859 Count++; 860 } 861 862 if (Count <= 2) { 863 mTFreq[0] = (UINT16) (mTFreq[0] + Count); 864 } else if (Count <= 18) { 865 mTFreq[1]++; 866 } else if (Count == 19) { 867 mTFreq[0]++; 868 mTFreq[1]++; 869 } else { 870 mTFreq[2]++; 871 } 872 } else { 873 mTFreq[Index3 + 2]++; 874 } 875 } 876 } 877 878 STATIC 879 VOID 880 WritePTLen ( 881 IN INT32 Number, 882 IN INT32 nbit, 883 IN INT32 Special 884 ) 885 /*++ 886 887 Routine Description: 888 889 Outputs the code length array for the Extra Set or the Position Set. 890 891 Arguments: 892 893 Number - the number of symbols 894 nbit - the number of bits needed to represent 'n' 895 Special - the special symbol that needs to be take care of 896 897 Returns: (VOID) 898 899 --*/ 900 { 901 INT32 Index; 902 INT32 Index3; 903 904 while (Number > 0 && mPTLen[Number - 1] == 0) { 905 Number--; 906 } 907 908 PutBits (nbit, Number); 909 Index = 0; 910 while (Index < Number) { 911 Index3 = mPTLen[Index++]; 912 if (Index3 <= 6) { 913 PutBits (3, Index3); 914 } else { 915 PutBits (Index3 - 3, (1U << (Index3 - 3)) - 2); 916 } 917 918 if (Index == Special) { 919 while (Index < 6 && mPTLen[Index] == 0) { 920 Index++; 921 } 922 923 PutBits (2, (Index - 3) & 3); 924 } 925 } 926 } 927 928 STATIC 929 VOID 930 WriteCLen ( 931 VOID 932 ) 933 /*++ 934 935 Routine Description: 936 937 Outputs the code length array for Char&Length Set 938 939 Arguments: (VOID) 940 941 Returns: (VOID) 942 943 --*/ 944 { 945 INT32 Index; 946 INT32 Index3; 947 INT32 Number; 948 INT32 Count; 949 950 Number = NC; 951 while (Number > 0 && mCLen[Number - 1] == 0) { 952 Number--; 953 } 954 955 PutBits (CBIT, Number); 956 Index = 0; 957 while (Index < Number) { 958 Index3 = mCLen[Index++]; 959 if (Index3 == 0) { 960 Count = 1; 961 while (Index < Number && mCLen[Index] == 0) { 962 Index++; 963 Count++; 964 } 965 966 if (Count <= 2) { 967 for (Index3 = 0; Index3 < Count; Index3++) { 968 PutBits (mPTLen[0], mPTCode[0]); 969 } 970 } else if (Count <= 18) { 971 PutBits (mPTLen[1], mPTCode[1]); 972 PutBits (4, Count - 3); 973 } else if (Count == 19) { 974 PutBits (mPTLen[0], mPTCode[0]); 975 PutBits (mPTLen[1], mPTCode[1]); 976 PutBits (4, 15); 977 } else { 978 PutBits (mPTLen[2], mPTCode[2]); 979 PutBits (CBIT, Count - 20); 980 } 981 } else { 982 PutBits (mPTLen[Index3 + 2], mPTCode[Index3 + 2]); 983 } 984 } 985 } 986 987 STATIC 988 VOID 989 EncodeC ( 990 IN INT32 Value 991 ) 992 { 993 PutBits (mCLen[Value], mCCode[Value]); 994 } 995 996 STATIC 997 VOID 998 EncodeP ( 999 IN UINT32 Value 1000 ) 1001 { 1002 UINT32 Index; 1003 UINT32 NodeQ; 1004 1005 Index = 0; 1006 NodeQ = Value; 1007 while (NodeQ) { 1008 NodeQ >>= 1; 1009 Index++; 1010 } 1011 1012 PutBits (mPTLen[Index], mPTCode[Index]); 1013 if (Index > 1) { 1014 PutBits (Index - 1, Value & (0xFFFFFFFFU >> (32 - Index + 1))); 1015 } 1016 } 1017 1018 STATIC 1019 VOID 1020 SendBlock ( 1021 VOID 1022 ) 1023 /*++ 1024 1025 Routine Description: 1026 1027 Huffman code the block and output it. 1028 1029 Arguments: 1030 (VOID) 1031 1032 Returns: 1033 (VOID) 1034 1035 --*/ 1036 { 1037 UINT32 Index; 1038 UINT32 Index2; 1039 UINT32 Index3; 1040 UINT32 Flags; 1041 UINT32 Root; 1042 UINT32 Pos; 1043 UINT32 Size; 1044 Flags = 0; 1045 1046 Root = MakeTree (NC, mCFreq, mCLen, mCCode); 1047 Size = mCFreq[Root]; 1048 1049 PutBits (16, Size); 1050 if (Root >= NC) { 1051 CountTFreq (); 1052 Root = MakeTree (NT, mTFreq, mPTLen, mPTCode); 1053 if (Root >= NT) { 1054 WritePTLen (NT, TBIT, 3); 1055 } else { 1056 PutBits (TBIT, 0); 1057 PutBits (TBIT, Root); 1058 } 1059 1060 WriteCLen (); 1061 } else { 1062 PutBits (TBIT, 0); 1063 PutBits (TBIT, 0); 1064 PutBits (CBIT, 0); 1065 PutBits (CBIT, Root); 1066 } 1067 1068 Root = MakeTree (NP, mPFreq, mPTLen, mPTCode); 1069 if (Root >= NP) { 1070 WritePTLen (NP, PBIT, -1); 1071 } else { 1072 PutBits (PBIT, 0); 1073 PutBits (PBIT, Root); 1074 } 1075 1076 Pos = 0; 1077 for (Index = 0; Index < Size; Index++) { 1078 if (Index % UINT8_BIT == 0) { 1079 Flags = mBuf[Pos++]; 1080 } else { 1081 Flags <<= 1; 1082 } 1083 1084 if (Flags & (1U << (UINT8_BIT - 1))) { 1085 EncodeC (mBuf[Pos++] + (1U << UINT8_BIT)); 1086 Index3 = mBuf[Pos++]; 1087 for (Index2 = 0; Index2 < 3; Index2++) { 1088 Index3 <<= UINT8_BIT; 1089 Index3 += mBuf[Pos++]; 1090 } 1091 1092 EncodeP (Index3); 1093 } else { 1094 EncodeC (mBuf[Pos++]); 1095 } 1096 } 1097 1098 for (Index = 0; Index < NC; Index++) { 1099 mCFreq[Index] = 0; 1100 } 1101 1102 for (Index = 0; Index < NP; Index++) { 1103 mPFreq[Index] = 0; 1104 } 1105 } 1106 1107 STATIC 1108 VOID 1109 Output ( 1110 IN UINT32 CharC, 1111 IN UINT32 Pos 1112 ) 1113 /*++ 1114 1115 Routine Description: 1116 1117 Outputs an Original Character or a Pointer 1118 1119 Arguments: 1120 1121 CharC - The original character or the 'String Length' element of a Pointer 1122 Pos - The 'Position' field of a Pointer 1123 1124 Returns: (VOID) 1125 1126 --*/ 1127 { 1128 STATIC UINT32 CPos; 1129 1130 if ((mOutputMask >>= 1) == 0) { 1131 mOutputMask = 1U << (UINT8_BIT - 1); 1132 // 1133 // Check the buffer overflow per outputing UINT8_BIT symbols 1134 // which is an Original Character or a Pointer. The biggest 1135 // symbol is a Pointer which occupies 5 bytes. 1136 // 1137 if (mOutputPos >= mBufSiz - 5 * UINT8_BIT) { 1138 SendBlock (); 1139 mOutputPos = 0; 1140 } 1141 1142 CPos = mOutputPos++; 1143 mBuf[CPos] = 0; 1144 } 1145 1146 mBuf[mOutputPos++] = (UINT8) CharC; 1147 mCFreq[CharC]++; 1148 if (CharC >= (1U << UINT8_BIT)) { 1149 mBuf[CPos] |= mOutputMask; 1150 mBuf[mOutputPos++] = (UINT8) (Pos >> 24); 1151 mBuf[mOutputPos++] = (UINT8) (Pos >> 16); 1152 mBuf[mOutputPos++] = (UINT8) (Pos >> (UINT8_BIT)); 1153 mBuf[mOutputPos++] = (UINT8) Pos; 1154 CharC = 0; 1155 while (Pos) { 1156 Pos >>= 1; 1157 CharC++; 1158 } 1159 1160 mPFreq[CharC]++; 1161 } 1162 } 1163 1164 STATIC 1165 VOID 1166 HufEncodeStart ( 1167 VOID 1168 ) 1169 { 1170 INT32 Index; 1171 1172 for (Index = 0; Index < NC; Index++) { 1173 mCFreq[Index] = 0; 1174 } 1175 1176 for (Index = 0; Index < NP; Index++) { 1177 mPFreq[Index] = 0; 1178 } 1179 1180 mOutputPos = mOutputMask = 0; 1181 InitPutBits (); 1182 return ; 1183 } 1184 1185 STATIC 1186 VOID 1187 HufEncodeEnd ( 1188 VOID 1189 ) 1190 { 1191 SendBlock (); 1192 1193 // 1194 // Flush remaining bits 1195 // 1196 PutBits (UINT8_BIT - 1, 0); 1197 1198 return ; 1199 } 1200 1201 STATIC 1202 VOID 1203 MakeCrcTable ( 1204 VOID 1205 ) 1206 { 1207 UINT32 Index; 1208 UINT32 Index2; 1209 UINT32 Temp; 1210 1211 for (Index = 0; Index <= UINT8_MAX; Index++) { 1212 Temp = Index; 1213 for (Index2 = 0; Index2 < UINT8_BIT; Index2++) { 1214 if (Temp & 1) { 1215 Temp = (Temp >> 1) ^ CRCPOLY; 1216 } else { 1217 Temp >>= 1; 1218 } 1219 } 1220 1221 mCrcTable[Index] = (UINT16) Temp; 1222 } 1223 } 1224 1225 STATIC 1226 VOID 1227 PutBits ( 1228 IN INT32 Number, 1229 IN UINT32 Value 1230 ) 1231 /*++ 1232 1233 Routine Description: 1234 1235 Outputs rightmost n bits of x 1236 1237 Arguments: 1238 1239 Number - the rightmost n bits of the data is used 1240 x - the data 1241 1242 Returns: (VOID) 1243 1244 --*/ 1245 { 1246 UINT8 Temp; 1247 1248 while (Number >= mBitCount) { 1249 // 1250 // Number -= mBitCount should never equal to 32 1251 // 1252 Temp = (UINT8) (mSubBitBuf | (Value >> (Number -= mBitCount))); 1253 1254 if (mDst < mDstUpperLimit) { 1255 *mDst++ = Temp; 1256 } 1257 1258 mCompSize++; 1259 mSubBitBuf = 0; 1260 mBitCount = UINT8_BIT; 1261 } 1262 1263 mSubBitBuf |= Value << (mBitCount -= Number); 1264 } 1265 1266 STATIC 1267 INT32 1268 FreadCrc ( 1269 OUT UINT8 *Pointer, 1270 IN INT32 Number 1271 ) 1272 /*++ 1273 1274 Routine Description: 1275 1276 Read in source data 1277 1278 Arguments: 1279 1280 Pointer - the buffer to hold the data 1281 Number - number of bytes to read 1282 1283 Returns: 1284 1285 number of bytes actually read 1286 1287 --*/ 1288 { 1289 INT32 Index; 1290 1291 for (Index = 0; mSrc < mSrcUpperLimit && Index < Number; Index++) { 1292 *Pointer++ = *mSrc++; 1293 } 1294 1295 Number = Index; 1296 1297 Pointer -= Number; 1298 mOrigSize += Number; 1299 1300 Index--; 1301 while (Index >= 0) { 1302 UPDATE_CRC (*Pointer++); 1303 Index--; 1304 } 1305 1306 return Number; 1307 } 1308 1309 STATIC 1310 VOID 1311 InitPutBits ( 1312 VOID 1313 ) 1314 { 1315 mBitCount = UINT8_BIT; 1316 mSubBitBuf = 0; 1317 } 1318 1319 STATIC 1320 VOID 1321 CountLen ( 1322 IN INT32 Index 1323 ) 1324 /*++ 1325 1326 Routine Description: 1327 1328 Count the number of each code length for a Huffman tree. 1329 1330 Arguments: 1331 1332 Index - the top node 1333 1334 Returns: (VOID) 1335 1336 --*/ 1337 { 1338 STATIC INT32 Depth = 0; 1339 1340 if (Index < mN) { 1341 mLenCnt[(Depth < 16) ? Depth : 16]++; 1342 } else { 1343 Depth++; 1344 CountLen (mLeft[Index]); 1345 CountLen (mRight[Index]); 1346 Depth--; 1347 } 1348 } 1349 1350 STATIC 1351 VOID 1352 MakeLen ( 1353 IN INT32 Root 1354 ) 1355 /*++ 1356 1357 Routine Description: 1358 1359 Create code length array for a Huffman tree 1360 1361 Arguments: 1362 1363 Root - the root of the tree 1364 1365 Returns: 1366 1367 VOID 1368 1369 --*/ 1370 { 1371 INT32 Index; 1372 INT32 Index3; 1373 UINT32 Cum; 1374 1375 for (Index = 0; Index <= 16; Index++) { 1376 mLenCnt[Index] = 0; 1377 } 1378 1379 CountLen (Root); 1380 1381 // 1382 // Adjust the length count array so that 1383 // no code will be generated longer than its designated length 1384 // 1385 Cum = 0; 1386 for (Index = 16; Index > 0; Index--) { 1387 Cum += mLenCnt[Index] << (16 - Index); 1388 } 1389 1390 while (Cum != (1U << 16)) { 1391 mLenCnt[16]--; 1392 for (Index = 15; Index > 0; Index--) { 1393 if (mLenCnt[Index] != 0) { 1394 mLenCnt[Index]--; 1395 mLenCnt[Index + 1] += 2; 1396 break; 1397 } 1398 } 1399 1400 Cum--; 1401 } 1402 1403 for (Index = 16; Index > 0; Index--) { 1404 Index3 = mLenCnt[Index]; 1405 Index3--; 1406 while (Index3 >= 0) { 1407 mLen[*mSortPtr++] = (UINT8) Index; 1408 Index3--; 1409 } 1410 } 1411 } 1412 1413 STATIC 1414 VOID 1415 DownHeap ( 1416 IN INT32 Index 1417 ) 1418 { 1419 INT32 Index2; 1420 INT32 Index3; 1421 1422 // 1423 // priority queue: send Index-th entry down heap 1424 // 1425 Index3 = mHeap[Index]; 1426 Index2 = 2 * Index; 1427 while (Index2 <= mHeapSize) { 1428 if (Index2 < mHeapSize && mFreq[mHeap[Index2]] > mFreq[mHeap[Index2 + 1]]) { 1429 Index2++; 1430 } 1431 1432 if (mFreq[Index3] <= mFreq[mHeap[Index2]]) { 1433 break; 1434 } 1435 1436 mHeap[Index] = mHeap[Index2]; 1437 Index = Index2; 1438 Index2 = 2 * Index; 1439 } 1440 1441 mHeap[Index] = (INT16) Index3; 1442 } 1443 1444 STATIC 1445 VOID 1446 MakeCode ( 1447 IN INT32 Number, 1448 IN UINT8 Len[ ], 1449 OUT UINT16 Code[] 1450 ) 1451 /*++ 1452 1453 Routine Description: 1454 1455 Assign code to each symbol based on the code length array 1456 1457 Arguments: 1458 1459 Number - number of symbols 1460 Len - the code length array 1461 Code - stores codes for each symbol 1462 1463 Returns: (VOID) 1464 1465 --*/ 1466 { 1467 INT32 Index; 1468 UINT16 Start[18]; 1469 1470 Start[1] = 0; 1471 for (Index = 1; Index <= 16; Index++) { 1472 Start[Index + 1] = (UINT16) ((Start[Index] + mLenCnt[Index]) << 1); 1473 } 1474 1475 for (Index = 0; Index < Number; Index++) { 1476 Code[Index] = Start[Len[Index]]++; 1477 } 1478 } 1479 1480 STATIC 1481 INT32 1482 MakeTree ( 1483 IN INT32 NParm, 1484 IN UINT16 FreqParm[], 1485 OUT UINT8 LenParm[ ], 1486 OUT UINT16 CodeParm[] 1487 ) 1488 /*++ 1489 1490 Routine Description: 1491 1492 Generates Huffman codes given a frequency distribution of symbols 1493 1494 Arguments: 1495 1496 NParm - number of symbols 1497 FreqParm - frequency of each symbol 1498 LenParm - code length for each symbol 1499 CodeParm - code for each symbol 1500 1501 Returns: 1502 1503 Root of the Huffman tree. 1504 1505 --*/ 1506 { 1507 INT32 Index; 1508 INT32 Index2; 1509 INT32 Index3; 1510 INT32 Avail; 1511 1512 // 1513 // make tree, calculate len[], return root 1514 // 1515 mN = NParm; 1516 mFreq = FreqParm; 1517 mLen = LenParm; 1518 Avail = mN; 1519 mHeapSize = 0; 1520 mHeap[1] = 0; 1521 for (Index = 0; Index < mN; Index++) { 1522 mLen[Index] = 0; 1523 if (mFreq[Index]) { 1524 mHeapSize++; 1525 mHeap[mHeapSize] = (INT16) Index; 1526 } 1527 } 1528 1529 if (mHeapSize < 2) { 1530 CodeParm[mHeap[1]] = 0; 1531 return mHeap[1]; 1532 } 1533 1534 for (Index = mHeapSize / 2; Index >= 1; Index--) { 1535 // 1536 // make priority queue 1537 // 1538 DownHeap (Index); 1539 } 1540 1541 mSortPtr = CodeParm; 1542 do { 1543 Index = mHeap[1]; 1544 if (Index < mN) { 1545 *mSortPtr++ = (UINT16) Index; 1546 } 1547 1548 mHeap[1] = mHeap[mHeapSize--]; 1549 DownHeap (1); 1550 Index2 = mHeap[1]; 1551 if (Index2 < mN) { 1552 *mSortPtr++ = (UINT16) Index2; 1553 } 1554 1555 Index3 = Avail++; 1556 mFreq[Index3] = (UINT16) (mFreq[Index] + mFreq[Index2]); 1557 mHeap[1] = (INT16) Index3; 1558 DownHeap (1); 1559 mLeft[Index3] = (UINT16) Index; 1560 mRight[Index3] = (UINT16) Index2; 1561 } while (mHeapSize > 1); 1562 1563 mSortPtr = CodeParm; 1564 MakeLen (Index3); 1565 MakeCode (NParm, LenParm, CodeParm); 1566 1567 // 1568 // return root 1569 // 1570 return Index3; 1571 } 1572 1573 EFI_STATUS 1574 GetFileContents ( 1575 IN char *InputFileName, 1576 OUT UINT8 *FileBuffer, 1577 OUT UINT32 *BufferLength 1578 ) 1579 /*++ 1580 1581 Routine Description: 1582 1583 Get the contents of file specified in InputFileName 1584 into FileBuffer. 1585 1586 Arguments: 1587 1588 InputFileName - Name of the input file. 1589 1590 FileBuffer - Output buffer to contain data 1591 1592 BufferLength - Actual length of the data 1593 1594 Returns: 1595 1596 EFI_SUCCESS on successful return 1597 EFI_ABORTED if unable to open input file. 1598 1599 --*/ 1600 { 1601 UINTN Size; 1602 UINTN FileSize; 1603 FILE *InputFile; 1604 1605 Size = 0; 1606 // 1607 // Copy the file contents to the output buffer. 1608 // 1609 InputFile = fopen (LongFilePath (InputFileName), "rb"); 1610 if (InputFile == NULL) { 1611 Error (NULL, 0, 0001, "Error opening file: %s", InputFileName); 1612 return EFI_ABORTED; 1613 } 1614 1615 fseek (InputFile, 0, SEEK_END); 1616 FileSize = ftell (InputFile); 1617 fseek (InputFile, 0, SEEK_SET); 1618 // 1619 // Now read the contents of the file into the buffer 1620 // 1621 if (FileSize > 0 && FileBuffer != NULL) { 1622 if (fread (FileBuffer, FileSize, 1, InputFile) != 1) { 1623 Error (NULL, 0, 0004, "Error reading contents of input file: %s", InputFileName); 1624 fclose (InputFile); 1625 return EFI_ABORTED; 1626 } 1627 } 1628 1629 fclose (InputFile); 1630 Size += (UINTN) FileSize; 1631 *BufferLength = Size; 1632 1633 if (FileBuffer != NULL) { 1634 return EFI_SUCCESS; 1635 } else { 1636 return EFI_BUFFER_TOO_SMALL; 1637 } 1638 } 1639 1640 VOID 1641 Version ( 1642 VOID 1643 ) 1644 /*++ 1645 1646 Routine Description: 1647 1648 Displays the standard utility information to SDTOUT 1649 1650 Arguments: 1651 1652 None 1653 1654 Returns: 1655 1656 None 1657 1658 --*/ 1659 { 1660 fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION); 1661 } 1662 1663 VOID 1664 Usage ( 1665 VOID 1666 ) 1667 /*++ 1668 1669 Routine Description: 1670 1671 Displays the utility usage syntax to STDOUT 1672 1673 Arguments: 1674 1675 None 1676 1677 Returns: 1678 1679 None 1680 1681 --*/ 1682 { 1683 // 1684 // Summary usage 1685 // 1686 fprintf (stdout, "Usage: %s -e|-d [options] <input_file>\n\n", UTILITY_NAME); 1687 1688 // 1689 // Copyright declaration 1690 // 1691 fprintf (stdout, "Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.\n\n"); 1692 1693 // 1694 // Details Option 1695 // 1696 fprintf (stdout, "Options:\n"); 1697 fprintf (stdout, " -o FileName, --output FileName\n\ 1698 File will be created to store the ouput content.\n"); 1699 fprintf (stdout, " -v, --verbose\n\ 1700 Turn on verbose output with informational messages.\n"); 1701 fprintf (stdout, " -q, --quiet\n\ 1702 Disable all messages except key message and fatal error\n"); 1703 fprintf (stdout, " --debug [0-9]\n\ 1704 Enable debug messages, at input debug level.\n"); 1705 fprintf (stdout, " --version\n\ 1706 Show program's version number and exit.\n"); 1707 fprintf (stdout, " -h, --help\n\ 1708 Show this help message and exit.\n"); 1709 } 1710 1711 1712 int 1713 main ( 1714 int argc, 1715 char *argv[] 1716 ) 1717 /*++ 1718 1719 Routine Description: 1720 1721 Main 1722 1723 Arguments: 1724 1725 command line parameters 1726 1727 Returns: 1728 1729 EFI_SUCCESS Section header successfully generated and section concatenated. 1730 EFI_ABORTED Could not generate the section 1731 EFI_OUT_OF_RESOURCES No resource to complete the operation. 1732 1733 --*/ 1734 { 1735 FILE *OutputFile; 1736 char *OutputFileName; 1737 char *InputFileName; 1738 FILE *InputFile; 1739 EFI_STATUS Status; 1740 UINT8 *FileBuffer; 1741 UINT8 *OutBuffer; 1742 UINT32 InputLength; 1743 UINT32 DstSize; 1744 SCRATCH_DATA *Scratch; 1745 UINT8 *Src; 1746 UINT32 OrigSize; 1747 1748 SetUtilityName(UTILITY_NAME); 1749 1750 FileBuffer = NULL; 1751 Src = NULL; 1752 OutBuffer = NULL; 1753 Scratch = NULL; 1754 OrigSize = 0; 1755 InputLength = 0; 1756 InputFileName = NULL; 1757 OutputFileName = NULL; 1758 DstSize=0; 1759 DebugLevel = 0; 1760 DebugMode = FALSE; 1761 1762 // 1763 // Verify the correct number of arguments 1764 // 1765 if (argc == 1) { 1766 Error (NULL, 0, 1001, "Missing options", "No input options specified."); 1767 Usage(); 1768 return 0; 1769 } 1770 1771 if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0)) { 1772 Usage(); 1773 return 0; 1774 } 1775 1776 if ((strcmp(argv[1], "--version") == 0)) { 1777 Version(); 1778 return 0; 1779 } 1780 1781 argc--; 1782 argv++; 1783 if (strcmp(argv[0],"-e") == 0) { 1784 // 1785 // encode the input file 1786 // 1787 ENCODE = TRUE; 1788 argc--; 1789 argv++; 1790 } else if (strcmp(argv[0], "-d") == 0) { 1791 // 1792 // decode the input file 1793 // 1794 DECODE = TRUE; 1795 argc--; 1796 argv++; 1797 } else { 1798 // 1799 // Error command line 1800 // 1801 Error (NULL, 0, 1003, "Invalid option value", "the options specified are not recognized."); 1802 Usage(); 1803 return 1; 1804 } 1805 1806 while (argc > 0) { 1807 if ((strcmp(argv[0], "-v") == 0) || (stricmp(argv[0], "--verbose") == 0)) { 1808 VerboseMode = TRUE; 1809 argc--; 1810 argv++; 1811 continue; 1812 } 1813 1814 if (stricmp (argv[0], "--debug") == 0) { 1815 argc-=2; 1816 argv++; 1817 Status = AsciiStringToUint64(argv[0], FALSE, &DebugLevel); 1818 if (DebugLevel > 9) { 1819 Error (NULL, 0 ,2000, "Invalid parameter", "Unrecognized argument %s", argv[0]); 1820 goto ERROR; 1821 } 1822 if (DebugLevel>=5 && DebugLevel <=9){ 1823 DebugMode = TRUE; 1824 } else { 1825 DebugMode = FALSE; 1826 } 1827 argv++; 1828 continue; 1829 } 1830 1831 if ((strcmp(argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) { 1832 QuietMode = TRUE; 1833 argc--; 1834 argv++; 1835 continue; 1836 } 1837 1838 if ((strcmp(argv[0], "-o") == 0) || (stricmp (argv[0], "--output") == 0)) { 1839 if (argv[1] == NULL || argv[1][0] == '-') { 1840 Error (NULL, 0, 1003, "Invalid option value", "Output File name is missing for -o option"); 1841 goto ERROR; 1842 } 1843 OutputFileName = argv[1]; 1844 argc -=2; 1845 argv +=2; 1846 continue; 1847 } 1848 1849 if (argv[0][0]!='-') { 1850 InputFileName = argv[0]; 1851 argc--; 1852 argv++; 1853 continue; 1854 } 1855 1856 Error (NULL, 0, 1000, "Unknown option", argv[0]); 1857 goto ERROR; 1858 } 1859 1860 if (InputFileName == NULL) { 1861 Error (NULL, 0, 1001, "Missing options", "No input files specified."); 1862 goto ERROR; 1863 } 1864 1865 // 1866 // All Parameters has been parsed, now set the message print level 1867 // 1868 if (QuietMode) { 1869 SetPrintLevel(40); 1870 } else if (VerboseMode) { 1871 SetPrintLevel(15); 1872 } else if (DebugMode) { 1873 SetPrintLevel(DebugLevel); 1874 } 1875 1876 if (VerboseMode) { 1877 VerboseMsg("%s tool start.\n", UTILITY_NAME); 1878 } 1879 Scratch = (SCRATCH_DATA *)malloc(sizeof(SCRATCH_DATA)); 1880 if (Scratch == NULL) { 1881 Error (NULL, 0, 4001, "Resource:", "Memory cannot be allocated!"); 1882 goto ERROR; 1883 } 1884 1885 InputFile = fopen (LongFilePath (InputFileName), "rb"); 1886 if (InputFile == NULL) { 1887 Error (NULL, 0, 0001, "Error opening input file", InputFileName); 1888 goto ERROR; 1889 } 1890 1891 Status = GetFileContents( 1892 InputFileName, 1893 FileBuffer, 1894 &InputLength); 1895 1896 if (Status == EFI_BUFFER_TOO_SMALL) { 1897 FileBuffer = (UINT8 *) malloc (InputLength); 1898 if (FileBuffer == NULL) { 1899 Error (NULL, 0, 4001, "Resource:", "Memory cannot be allocated!"); 1900 return 1; 1901 } 1902 1903 Status = GetFileContents ( 1904 InputFileName, 1905 FileBuffer, 1906 &InputLength 1907 ); 1908 } 1909 1910 if (EFI_ERROR(Status)) { 1911 free(FileBuffer); 1912 return 1; 1913 } 1914 1915 if (OutputFileName != NULL) { 1916 OutputFile = fopen (LongFilePath (OutputFileName), "wb"); 1917 if (OutputFile == NULL) { 1918 Error (NULL, 0, 0001, "Error opening output file for writing", OutputFileName); 1919 if (InputFile != NULL) { 1920 fclose (InputFile); 1921 } 1922 goto ERROR; 1923 } 1924 } else { 1925 OutputFileName = DEFAULT_OUTPUT_FILE; 1926 OutputFile = fopen (LongFilePath (OutputFileName), "wb"); 1927 } 1928 1929 if (ENCODE) { 1930 // 1931 // First call TianoCompress to get DstSize 1932 // 1933 if (DebugMode) { 1934 DebugMsg(UTILITY_NAME, 0, DebugLevel, "Encoding", NULL); 1935 } 1936 Status = TianoCompress ((UINT8 *)FileBuffer, InputLength, OutBuffer, &DstSize); 1937 1938 if (Status == EFI_BUFFER_TOO_SMALL) { 1939 OutBuffer = (UINT8 *) malloc (DstSize); 1940 if (OutBuffer == NULL) { 1941 Error (NULL, 0, 4001, "Resource:", "Memory cannot be allocated!"); 1942 goto ERROR; 1943 } 1944 } 1945 Status = TianoCompress ((UINT8 *)FileBuffer, InputLength, OutBuffer, &DstSize); 1946 if (Status != EFI_SUCCESS) { 1947 Error (NULL, 0, 0007, "Error compressing file", NULL); 1948 goto ERROR; 1949 } 1950 1951 fwrite(OutBuffer,(size_t)DstSize, 1, OutputFile); 1952 free(Scratch); 1953 free(FileBuffer); 1954 free(OutBuffer); 1955 1956 if (DebugMode) { 1957 DebugMsg(UTILITY_NAME, 0, DebugLevel, "Encoding Successful!\n", NULL); 1958 } 1959 if (VerboseMode) { 1960 VerboseMsg("Encoding successful\n"); 1961 } 1962 return 0; 1963 } 1964 else if (DECODE) { 1965 if (DebugMode) { 1966 DebugMsg(UTILITY_NAME, 0, DebugLevel, "Decoding\n", NULL); 1967 } 1968 // 1969 // Get Compressed file original size 1970 // 1971 Src = (UINT8 *)FileBuffer; 1972 OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24); 1973 1974 // 1975 // Allocate OutputBuffer 1976 // 1977 OutBuffer = (UINT8 *)malloc(OrigSize); 1978 if (OutBuffer == NULL) { 1979 Error (NULL, 0, 4001, "Resource:", "Memory cannot be allocated!"); 1980 goto ERROR; 1981 } 1982 1983 Status = Decompress((VOID *)FileBuffer, (VOID *)OutBuffer, (VOID *)Scratch, 2); 1984 if (Status != EFI_SUCCESS) { 1985 goto ERROR; 1986 } 1987 1988 fwrite(OutBuffer, (size_t)(Scratch->mOrigSize), 1, OutputFile); 1989 free(Scratch); 1990 free(FileBuffer); 1991 free(OutBuffer); 1992 1993 if (DebugMode) { 1994 DebugMsg(UTILITY_NAME, 0, DebugLevel, "Encoding successful!\n", NULL); 1995 } 1996 1997 if (VerboseMode) { 1998 VerboseMsg("Decoding successful\n"); 1999 } 2000 return 0; 2001 } 2002 2003 ERROR: 2004 if (DebugMode) { 2005 if (ENCODE) { 2006 DebugMsg(UTILITY_NAME, 0, DebugLevel, "Encoding Error\n", NULL); 2007 } else if (DECODE) { 2008 DebugMsg(UTILITY_NAME, 0, DebugLevel, "Decoding Error\n", NULL); 2009 } 2010 } 2011 if (Scratch != NULL) { 2012 free(Scratch); 2013 } 2014 if (FileBuffer != NULL) { 2015 free(FileBuffer); 2016 } 2017 if (OutBuffer != NULL) { 2018 free(OutBuffer); 2019 } 2020 2021 if (VerboseMode) { 2022 VerboseMsg("%s tool done with return code is 0x%x.\n", UTILITY_NAME, GetUtilityStatus ()); 2023 } 2024 return GetUtilityStatus (); 2025 } 2026 2027 VOID 2028 FillBuf ( 2029 IN SCRATCH_DATA *Sd, 2030 IN UINT16 NumOfBits 2031 ) 2032 /*++ 2033 2034 Routine Description: 2035 2036 Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source. 2037 2038 Arguments: 2039 2040 Sd - The global scratch data 2041 NumOfBits - The number of bits to shift and read. 2042 2043 Returns: (VOID) 2044 2045 --*/ 2046 { 2047 Sd->mBitBuf = (UINT32) (Sd->mBitBuf << NumOfBits); 2048 2049 while (NumOfBits > Sd->mBitCount) { 2050 2051 Sd->mBitBuf |= (UINT32) (Sd->mSubBitBuf << (NumOfBits = (UINT16) (NumOfBits - Sd->mBitCount))); 2052 2053 if (Sd->mCompSize > 0) { 2054 // 2055 // Get 1 byte into SubBitBuf 2056 // 2057 Sd->mCompSize--; 2058 Sd->mSubBitBuf = 0; 2059 Sd->mSubBitBuf = Sd->mSrcBase[Sd->mInBuf++]; 2060 Sd->mBitCount = 8; 2061 2062 } else { 2063 // 2064 // No more bits from the source, just pad zero bit. 2065 // 2066 Sd->mSubBitBuf = 0; 2067 Sd->mBitCount = 8; 2068 2069 } 2070 } 2071 2072 Sd->mBitCount = (UINT16) (Sd->mBitCount - NumOfBits); 2073 Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount; 2074 } 2075 2076 UINT32 2077 GetBits ( 2078 IN SCRATCH_DATA *Sd, 2079 IN UINT16 NumOfBits 2080 ) 2081 /*++ 2082 2083 Routine Description: 2084 2085 Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent 2086 NumOfBits of bits from source. Returns NumOfBits of bits that are 2087 popped out. 2088 2089 Arguments: 2090 2091 Sd - The global scratch data. 2092 NumOfBits - The number of bits to pop and read. 2093 2094 Returns: 2095 2096 The bits that are popped out. 2097 2098 --*/ 2099 { 2100 UINT32 OutBits; 2101 2102 OutBits = (UINT32) (Sd->mBitBuf >> (BITBUFSIZ - NumOfBits)); 2103 2104 FillBuf (Sd, NumOfBits); 2105 2106 return OutBits; 2107 } 2108 2109 UINT16 2110 MakeTable ( 2111 IN SCRATCH_DATA *Sd, 2112 IN UINT16 NumOfChar, 2113 IN UINT8 *BitLen, 2114 IN UINT16 TableBits, 2115 OUT UINT16 *Table 2116 ) 2117 /*++ 2118 2119 Routine Description: 2120 2121 Creates Huffman Code mapping table according to code length array. 2122 2123 Arguments: 2124 2125 Sd - The global scratch data 2126 NumOfChar - Number of symbols in the symbol set 2127 BitLen - Code length array 2128 TableBits - The width of the mapping table 2129 Table - The table 2130 2131 Returns: 2132 2133 0 - OK. 2134 BAD_TABLE - The table is corrupted. 2135 2136 --*/ 2137 { 2138 UINT16 Count[17]; 2139 UINT16 Weight[17]; 2140 UINT16 Start[18]; 2141 UINT16 *Pointer; 2142 UINT16 Index3; 2143 volatile UINT16 Index; 2144 UINT16 Len; 2145 UINT16 Char; 2146 UINT16 JuBits; 2147 UINT16 Avail; 2148 UINT16 NextCode; 2149 UINT16 Mask; 2150 UINT16 WordOfStart; 2151 UINT16 WordOfCount; 2152 2153 for (Index = 1; Index <= 16; Index++) { 2154 Count[Index] = 0; 2155 } 2156 2157 for (Index = 0; Index < NumOfChar; Index++) { 2158 Count[BitLen[Index]]++; 2159 } 2160 2161 Start[1] = 0; 2162 2163 for (Index = 1; Index <= 16; Index++) { 2164 WordOfStart = Start[Index]; 2165 WordOfCount = Count[Index]; 2166 Start[Index + 1] = (UINT16) (WordOfStart + (WordOfCount << (16 - Index))); 2167 } 2168 2169 if (Start[17] != 0) { 2170 // 2171 //(1U << 16) 2172 // 2173 return (UINT16) BAD_TABLE; 2174 } 2175 2176 JuBits = (UINT16) (16 - TableBits); 2177 2178 for (Index = 1; Index <= TableBits; Index++) { 2179 Start[Index] >>= JuBits; 2180 Weight[Index] = (UINT16) (1U << (TableBits - Index)); 2181 } 2182 2183 while (Index <= 16) { 2184 Weight[Index] = (UINT16) (1U << (16 - Index)); 2185 Index++; 2186 } 2187 2188 Index = (UINT16) (Start[TableBits + 1] >> JuBits); 2189 2190 if (Index != 0) { 2191 Index3 = (UINT16) (1U << TableBits); 2192 while (Index != Index3) { 2193 Table[Index++] = 0; 2194 } 2195 } 2196 2197 Avail = NumOfChar; 2198 Mask = (UINT16) (1U << (15 - TableBits)); 2199 2200 for (Char = 0; Char < NumOfChar; Char++) { 2201 2202 Len = BitLen[Char]; 2203 if (Len == 0) { 2204 continue; 2205 } 2206 2207 NextCode = (UINT16) (Start[Len] + Weight[Len]); 2208 2209 if (Len <= TableBits) { 2210 2211 for (Index = Start[Len]; Index < NextCode; Index++) { 2212 Table[Index] = Char; 2213 } 2214 2215 } else { 2216 2217 Index3 = Start[Len]; 2218 Pointer = &Table[Index3 >> JuBits]; 2219 Index = (UINT16) (Len - TableBits); 2220 2221 while (Index != 0) { 2222 if (*Pointer == 0) { 2223 Sd->mRight[Avail] = Sd->mLeft[Avail] = 0; 2224 *Pointer = Avail++; 2225 } 2226 2227 if (Index3 & Mask) { 2228 Pointer = &Sd->mRight[*Pointer]; 2229 } else { 2230 Pointer = &Sd->mLeft[*Pointer]; 2231 } 2232 2233 Index3 <<= 1; 2234 Index--; 2235 } 2236 2237 *Pointer = Char; 2238 2239 } 2240 2241 Start[Len] = NextCode; 2242 } 2243 // 2244 // Succeeds 2245 // 2246 return 0; 2247 } 2248 2249 UINT32 2250 DecodeP ( 2251 IN SCRATCH_DATA *Sd 2252 ) 2253 /*++ 2254 2255 Routine Description: 2256 2257 Decodes a position value. 2258 2259 Arguments: 2260 2261 Sd - the global scratch data 2262 2263 Returns: 2264 2265 The position value decoded. 2266 2267 --*/ 2268 { 2269 UINT16 Val; 2270 UINT32 Mask; 2271 UINT32 Pos; 2272 2273 Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)]; 2274 2275 if (Val >= MAXNP) { 2276 Mask = 1U << (BITBUFSIZ - 1 - 8); 2277 2278 do { 2279 2280 if (Sd->mBitBuf & Mask) { 2281 Val = Sd->mRight[Val]; 2282 } else { 2283 Val = Sd->mLeft[Val]; 2284 } 2285 2286 Mask >>= 1; 2287 } while (Val >= MAXNP); 2288 } 2289 // 2290 // Advance what we have read 2291 // 2292 FillBuf (Sd, Sd->mPTLen[Val]); 2293 2294 Pos = Val; 2295 if (Val > 1) { 2296 Pos = (UINT32) ((1U << (Val - 1)) + GetBits (Sd, (UINT16) (Val - 1))); 2297 } 2298 2299 return Pos; 2300 } 2301 2302 UINT16 2303 ReadPTLen ( 2304 IN SCRATCH_DATA *Sd, 2305 IN UINT16 nn, 2306 IN UINT16 nbit, 2307 IN UINT16 Special 2308 ) 2309 /*++ 2310 2311 Routine Description: 2312 2313 Reads code lengths for the Extra Set or the Position Set 2314 2315 Arguments: 2316 2317 Sd - The global scratch data 2318 nn - Number of symbols 2319 nbit - Number of bits needed to represent nn 2320 Special - The special symbol that needs to be taken care of 2321 2322 Returns: 2323 2324 0 - OK. 2325 BAD_TABLE - Table is corrupted. 2326 2327 --*/ 2328 { 2329 UINT16 Number; 2330 UINT16 CharC; 2331 volatile UINT16 Index; 2332 UINT32 Mask; 2333 2334 Number = (UINT16) GetBits (Sd, nbit); 2335 2336 if (Number == 0) { 2337 CharC = (UINT16) GetBits (Sd, nbit); 2338 2339 for (Index = 0; Index < 256; Index++) { 2340 Sd->mPTTable[Index] = CharC; 2341 } 2342 2343 for (Index = 0; Index < nn; Index++) { 2344 Sd->mPTLen[Index] = 0; 2345 } 2346 2347 return 0; 2348 } 2349 2350 Index = 0; 2351 2352 while (Index < Number) { 2353 2354 CharC = (UINT16) (Sd->mBitBuf >> (BITBUFSIZ - 3)); 2355 2356 if (CharC == 7) { 2357 Mask = 1U << (BITBUFSIZ - 1 - 3); 2358 while (Mask & Sd->mBitBuf) { 2359 Mask >>= 1; 2360 CharC += 1; 2361 } 2362 } 2363 2364 FillBuf (Sd, (UINT16) ((CharC < 7) ? 3 : CharC - 3)); 2365 2366 Sd->mPTLen[Index++] = (UINT8) CharC; 2367 2368 if (Index == Special) { 2369 CharC = (UINT16) GetBits (Sd, 2); 2370 while ((INT16) (--CharC) >= 0) { 2371 Sd->mPTLen[Index++] = 0; 2372 } 2373 } 2374 } 2375 2376 while (Index < nn) { 2377 Sd->mPTLen[Index++] = 0; 2378 } 2379 2380 return MakeTable (Sd, nn, Sd->mPTLen, 8, Sd->mPTTable); 2381 } 2382 2383 VOID 2384 ReadCLen ( 2385 SCRATCH_DATA *Sd 2386 ) 2387 /*++ 2388 2389 Routine Description: 2390 2391 Reads code lengths for Char&Len Set. 2392 2393 Arguments: 2394 2395 Sd - the global scratch data 2396 2397 Returns: (VOID) 2398 2399 --*/ 2400 { 2401 UINT16 Number; 2402 UINT16 CharC; 2403 volatile UINT16 Index; 2404 UINT32 Mask; 2405 2406 Number = (UINT16) GetBits (Sd, CBIT); 2407 2408 if (Number == 0) { 2409 CharC = (UINT16) GetBits (Sd, CBIT); 2410 2411 for (Index = 0; Index < NC; Index++) { 2412 Sd->mCLen[Index] = 0; 2413 } 2414 2415 for (Index = 0; Index < 4096; Index++) { 2416 Sd->mCTable[Index] = CharC; 2417 } 2418 2419 return ; 2420 } 2421 2422 Index = 0; 2423 while (Index < Number) { 2424 2425 CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)]; 2426 if (CharC >= NT) { 2427 Mask = 1U << (BITBUFSIZ - 1 - 8); 2428 2429 do { 2430 2431 if (Mask & Sd->mBitBuf) { 2432 CharC = Sd->mRight[CharC]; 2433 } else { 2434 CharC = Sd->mLeft[CharC]; 2435 } 2436 2437 Mask >>= 1; 2438 2439 } while (CharC >= NT); 2440 } 2441 // 2442 // Advance what we have read 2443 // 2444 FillBuf (Sd, Sd->mPTLen[CharC]); 2445 2446 if (CharC <= 2) { 2447 2448 if (CharC == 0) { 2449 CharC = 1; 2450 } else if (CharC == 1) { 2451 CharC = (UINT16) (GetBits (Sd, 4) + 3); 2452 } else if (CharC == 2) { 2453 CharC = (UINT16) (GetBits (Sd, CBIT) + 20); 2454 } 2455 2456 while ((INT16) (--CharC) >= 0) { 2457 Sd->mCLen[Index++] = 0; 2458 } 2459 2460 } else { 2461 2462 Sd->mCLen[Index++] = (UINT8) (CharC - 2); 2463 2464 } 2465 } 2466 2467 while (Index < NC) { 2468 Sd->mCLen[Index++] = 0; 2469 } 2470 2471 MakeTable (Sd, NC, Sd->mCLen, 12, Sd->mCTable); 2472 2473 return ; 2474 } 2475 2476 UINT16 2477 DecodeC ( 2478 SCRATCH_DATA *Sd 2479 ) 2480 /*++ 2481 2482 Routine Description: 2483 2484 Decode a character/length value. 2485 2486 Arguments: 2487 2488 Sd - The global scratch data. 2489 2490 Returns: 2491 2492 The value decoded. 2493 2494 --*/ 2495 { 2496 UINT16 Index2; 2497 UINT32 Mask; 2498 2499 if (Sd->mBlockSize == 0) { 2500 // 2501 // Starting a new block 2502 // 2503 Sd->mBlockSize = (UINT16) GetBits (Sd, 16); 2504 Sd->mBadTableFlag = ReadPTLen (Sd, NT, TBIT, 3); 2505 if (Sd->mBadTableFlag != 0) { 2506 return 0; 2507 } 2508 2509 ReadCLen (Sd); 2510 2511 Sd->mBadTableFlag = ReadPTLen (Sd, MAXNP, Sd->mPBit, (UINT16) (-1)); 2512 if (Sd->mBadTableFlag != 0) { 2513 return 0; 2514 } 2515 } 2516 2517 Sd->mBlockSize--; 2518 Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)]; 2519 2520 if (Index2 >= NC) { 2521 Mask = 1U << (BITBUFSIZ - 1 - 12); 2522 2523 do { 2524 if (Sd->mBitBuf & Mask) { 2525 Index2 = Sd->mRight[Index2]; 2526 } else { 2527 Index2 = Sd->mLeft[Index2]; 2528 } 2529 2530 Mask >>= 1; 2531 } while (Index2 >= NC); 2532 } 2533 // 2534 // Advance what we have read 2535 // 2536 FillBuf (Sd, Sd->mCLen[Index2]); 2537 2538 return Index2; 2539 } 2540 2541 VOID 2542 Decode ( 2543 SCRATCH_DATA *Sd 2544 ) 2545 /*++ 2546 2547 Routine Description: 2548 2549 Decode the source data and put the resulting data into the destination buffer. 2550 2551 Arguments: 2552 2553 Sd - The global scratch data 2554 2555 Returns: (VOID) 2556 2557 --*/ 2558 { 2559 UINT16 BytesRemain; 2560 UINT32 DataIdx; 2561 UINT16 CharC; 2562 2563 BytesRemain = (UINT16) (-1); 2564 2565 DataIdx = 0; 2566 2567 for (;;) { 2568 CharC = DecodeC (Sd); 2569 if (Sd->mBadTableFlag != 0) { 2570 goto Done ; 2571 } 2572 2573 if (CharC < 256) { 2574 // 2575 // Process an Original character 2576 // 2577 if (Sd->mOutBuf >= Sd->mOrigSize) { 2578 goto Done ; 2579 } else { 2580 Sd->mDstBase[Sd->mOutBuf++] = (UINT8) CharC; 2581 } 2582 2583 } else { 2584 // 2585 // Process a Pointer 2586 // 2587 CharC = (UINT16) (CharC - (UINT8_MAX + 1 - THRESHOLD)); 2588 2589 BytesRemain = CharC; 2590 2591 DataIdx = Sd->mOutBuf - DecodeP (Sd) - 1; 2592 2593 BytesRemain--; 2594 while ((INT16) (BytesRemain) >= 0) { 2595 Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++]; 2596 if (Sd->mOutBuf >= Sd->mOrigSize) { 2597 goto Done ; 2598 } 2599 2600 BytesRemain--; 2601 } 2602 } 2603 } 2604 2605 Done: 2606 return ; 2607 } 2608 2609 RETURN_STATUS 2610 EFIAPI 2611 Decompress ( 2612 IN VOID *Source, 2613 IN OUT VOID *Destination, 2614 IN OUT VOID *Scratch, 2615 IN UINT32 Version 2616 ) 2617 /*++ 2618 2619 Routine Description: 2620 2621 The internal implementation of Decompress(). 2622 2623 Arguments: 2624 2625 Source - The source buffer containing the compressed data. 2626 Destination - The destination buffer to store the decompressed data 2627 Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. 2628 Version - 1 for EFI1.1 Decompress algoruthm, 2 for Tiano Decompress algorithm 2629 2630 Returns: 2631 2632 RETURN_SUCCESS - Decompression is successfull 2633 RETURN_INVALID_PARAMETER - The source data is corrupted 2634 2635 --*/ 2636 { 2637 volatile UINT32 Index; 2638 UINT32 CompSize; 2639 UINT32 OrigSize; 2640 SCRATCH_DATA *Sd; 2641 CONST UINT8 *Src; 2642 UINT8 *Dst; 2643 2644 // 2645 // Verify input is not NULL 2646 // 2647 assert(Source); 2648 // assert(Destination); 2649 assert(Scratch); 2650 2651 Src = (UINT8 *)Source; 2652 Dst = (UINT8 *)Destination; 2653 2654 Sd = (SCRATCH_DATA *) Scratch; 2655 CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24); 2656 OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24); 2657 2658 // 2659 // If compressed file size is 0, return 2660 // 2661 if (OrigSize == 0) { 2662 return RETURN_SUCCESS; 2663 } 2664 2665 Src = Src + 8; 2666 2667 for (Index = 0; Index < sizeof (SCRATCH_DATA); Index++) { 2668 ((UINT8 *) Sd)[Index] = 0; 2669 } 2670 // 2671 // The length of the field 'Position Set Code Length Array Size' in Block Header. 2672 // For EFI 1.1 de/compression algorithm(Version 1), mPBit = 4 2673 // For Tiano de/compression algorithm(Version 2), mPBit = 5 2674 // 2675 switch (Version) { 2676 case 1 : 2677 Sd->mPBit = 4; 2678 break; 2679 case 2 : 2680 Sd->mPBit = 5; 2681 break; 2682 default: 2683 assert(FALSE); 2684 } 2685 Sd->mSrcBase = (UINT8 *)Src; 2686 Sd->mDstBase = Dst; 2687 Sd->mCompSize = CompSize; 2688 Sd->mOrigSize = OrigSize; 2689 2690 // 2691 // Fill the first BITBUFSIZ bits 2692 // 2693 FillBuf (Sd, BITBUFSIZ); 2694 2695 // 2696 // Decompress it 2697 // 2698 2699 Decode (Sd); 2700 2701 if (Sd->mBadTableFlag != 0) { 2702 // 2703 // Something wrong with the source 2704 // 2705 return RETURN_INVALID_PARAMETER; 2706 } 2707 2708 return RETURN_SUCCESS; 2709 } 2710 2711 2712