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. This sequence is further divided into Blocks 5 and Huffman codings are applied to each Block. 6 7 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR> 8 This program and the accompanying materials 9 are licensed and made available under the terms and conditions of the BSD License 10 which accompanies this distribution. The full text of the license may be found at 11 http://opensource.org/licenses/bsd-license.php 12 13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 15 16 **/ 17 18 #include "Compress.h" 19 20 // 21 // Macro Definitions 22 // 23 #undef UINT8_MAX 24 typedef INT32 NODE; 25 #define UINT8_MAX 0xff 26 #define UINT8_BIT 8 27 #define THRESHOLD 3 28 #define INIT_CRC 0 29 #define WNDBIT 19 30 #define WNDSIZ (1U << WNDBIT) 31 #define MAXMATCH 256 32 #define BLKSIZ (1U << 14) // 16 * 1024U 33 #define PERC_FLAG 0x80000000U 34 #define CODE_BIT 16 35 #define NIL 0 36 #define MAX_HASH_VAL (3 * WNDSIZ + (WNDSIZ / 512 + 1) * UINT8_MAX) 37 #define HASH(p, c) ((p) + ((c) << (WNDBIT - 9)) + WNDSIZ * 2) 38 #define CRCPOLY 0xA001 39 #define UPDATE_CRC(c) mCrc = mCrcTable[(mCrc ^ (c)) & 0xFF] ^ (mCrc >> UINT8_BIT) 40 41 // 42 // C: the Char&Len Set; P: the Position Set; T: the exTra Set 43 // 44 #define NC (UINT8_MAX + MAXMATCH + 2 - THRESHOLD) 45 #define CBIT 9 46 #define NP (WNDBIT + 1) 47 #define PBIT 5 48 #define NT (CODE_BIT + 3) 49 #define TBIT 5 50 #if NT > NP 51 #define NPT NT 52 #else 53 #define NPT NP 54 #endif 55 // 56 // Function Prototypes 57 // 58 59 STATIC 60 VOID 61 PutDword( 62 IN UINT32 Data 63 ); 64 65 STATIC 66 EFI_STATUS 67 AllocateMemory ( 68 VOID 69 ); 70 71 STATIC 72 VOID 73 FreeMemory ( 74 VOID 75 ); 76 77 STATIC 78 VOID 79 InitSlide ( 80 VOID 81 ); 82 83 STATIC 84 NODE 85 Child ( 86 IN NODE NodeQ, 87 IN UINT8 CharC 88 ); 89 90 STATIC 91 VOID 92 MakeChild ( 93 IN NODE NodeQ, 94 IN UINT8 CharC, 95 IN NODE NodeR 96 ); 97 98 STATIC 99 VOID 100 Split ( 101 IN NODE Old 102 ); 103 104 STATIC 105 VOID 106 InsertNode ( 107 VOID 108 ); 109 110 STATIC 111 VOID 112 DeleteNode ( 113 VOID 114 ); 115 116 STATIC 117 VOID 118 GetNextMatch ( 119 VOID 120 ); 121 122 STATIC 123 EFI_STATUS 124 Encode ( 125 VOID 126 ); 127 128 STATIC 129 VOID 130 CountTFreq ( 131 VOID 132 ); 133 134 STATIC 135 VOID 136 WritePTLen ( 137 IN INT32 Number, 138 IN INT32 nbit, 139 IN INT32 Special 140 ); 141 142 STATIC 143 VOID 144 WriteCLen ( 145 VOID 146 ); 147 148 STATIC 149 VOID 150 EncodeC ( 151 IN INT32 Value 152 ); 153 154 STATIC 155 VOID 156 EncodeP ( 157 IN UINT32 Value 158 ); 159 160 STATIC 161 VOID 162 SendBlock ( 163 VOID 164 ); 165 166 STATIC 167 VOID 168 Output ( 169 IN UINT32 c, 170 IN UINT32 p 171 ); 172 173 STATIC 174 VOID 175 HufEncodeStart ( 176 VOID 177 ); 178 179 STATIC 180 VOID 181 HufEncodeEnd ( 182 VOID 183 ); 184 185 STATIC 186 VOID 187 MakeCrcTable ( 188 VOID 189 ); 190 191 STATIC 192 VOID 193 PutBits ( 194 IN INT32 Number, 195 IN UINT32 Value 196 ); 197 198 STATIC 199 INT32 200 FreadCrc ( 201 OUT UINT8 *Pointer, 202 IN INT32 Number 203 ); 204 205 STATIC 206 VOID 207 InitPutBits ( 208 VOID 209 ); 210 211 STATIC 212 VOID 213 CountLen ( 214 IN INT32 Index 215 ); 216 217 STATIC 218 VOID 219 MakeLen ( 220 IN INT32 Root 221 ); 222 223 STATIC 224 VOID 225 DownHeap ( 226 IN INT32 Index 227 ); 228 229 STATIC 230 VOID 231 MakeCode ( 232 IN INT32 Number, 233 IN UINT8 Len[ ], 234 OUT UINT16 Code[] 235 ); 236 237 STATIC 238 INT32 239 MakeTree ( 240 IN INT32 NParm, 241 IN UINT16 FreqParm[], 242 OUT UINT8 LenParm[ ], 243 OUT UINT16 CodeParm[] 244 ); 245 246 // 247 // Global Variables 248 // 249 STATIC UINT8 *mSrc, *mDst, *mSrcUpperLimit, *mDstUpperLimit; 250 251 STATIC UINT8 *mLevel, *mText, *mChildCount, *mBuf, mCLen[NC], mPTLen[NPT], *mLen; 252 STATIC INT16 mHeap[NC + 1]; 253 STATIC INT32 mRemainder, mMatchLen, mBitCount, mHeapSize, mN; 254 STATIC UINT32 mBufSiz = 0, mOutputPos, mOutputMask, mSubBitBuf, mCrc; 255 STATIC UINT32 mCompSize, mOrigSize; 256 257 STATIC UINT16 *mFreq, *mSortPtr, mLenCnt[17], mLeft[2 * NC - 1], mRight[2 * NC - 1], mCrcTable[UINT8_MAX + 1], 258 mCFreq[2 * NC - 1], mCCode[NC], mPFreq[2 * NP - 1], mPTCode[NPT], mTFreq[2 * NT - 1]; 259 260 STATIC NODE mPos, mMatchPos, mAvail, *mPosition, *mParent, *mPrev, *mNext = NULL; 261 262 // 263 // functions 264 // 265 EFI_STATUS 266 TianoCompress ( 267 IN UINT8 *SrcBuffer, 268 IN UINT32 SrcSize, 269 IN UINT8 *DstBuffer, 270 IN OUT UINT32 *DstSize 271 ) 272 /*++ 273 274 Routine Description: 275 276 The internal implementation of [Efi/Tiano]Compress(). 277 278 Arguments: 279 280 SrcBuffer - The buffer storing the source data 281 SrcSize - The size of source data 282 DstBuffer - The buffer to store the compressed data 283 DstSize - On input, the size of DstBuffer; On output, 284 the size of the actual compressed data. 285 Version - The version of de/compression algorithm. 286 Version 1 for UEFI 2.0 de/compression algorithm. 287 Version 2 for Tiano de/compression algorithm. 288 289 Returns: 290 291 EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. In this case, 292 DstSize contains the size needed. 293 EFI_SUCCESS - Compression is successful. 294 EFI_OUT_OF_RESOURCES - No resource to complete function. 295 EFI_INVALID_PARAMETER - Parameter supplied is wrong. 296 297 --*/ 298 { 299 EFI_STATUS Status; 300 301 // 302 // Initializations 303 // 304 mBufSiz = 0; 305 mBuf = NULL; 306 mText = NULL; 307 mLevel = NULL; 308 mChildCount = NULL; 309 mPosition = NULL; 310 mParent = NULL; 311 mPrev = NULL; 312 mNext = NULL; 313 314 mSrc = SrcBuffer; 315 mSrcUpperLimit = mSrc + SrcSize; 316 mDst = DstBuffer; 317 mDstUpperLimit = mDst +*DstSize; 318 319 PutDword (0L); 320 PutDword (0L); 321 322 MakeCrcTable (); 323 324 mOrigSize = mCompSize = 0; 325 mCrc = INIT_CRC; 326 327 // 328 // Compress it 329 // 330 Status = Encode (); 331 if (EFI_ERROR (Status)) { 332 return EFI_OUT_OF_RESOURCES; 333 } 334 // 335 // Null terminate the compressed data 336 // 337 if (mDst < mDstUpperLimit) { 338 *mDst++ = 0; 339 } 340 // 341 // Fill in compressed size and original size 342 // 343 mDst = DstBuffer; 344 PutDword (mCompSize + 1); 345 PutDword (mOrigSize); 346 347 // 348 // Return 349 // 350 if (mCompSize + 1 + 8 > *DstSize) { 351 *DstSize = mCompSize + 1 + 8; 352 return EFI_BUFFER_TOO_SMALL; 353 } else { 354 *DstSize = mCompSize + 1 + 8; 355 return EFI_SUCCESS; 356 } 357 358 } 359 360 STATIC 361 VOID 362 PutDword ( 363 IN UINT32 Data 364 ) 365 /*++ 366 367 Routine Description: 368 369 Put a dword to output stream 370 371 Arguments: 372 373 Data - the dword to put 374 375 Returns: (VOID) 376 377 --*/ 378 { 379 if (mDst < mDstUpperLimit) { 380 *mDst++ = (UINT8) (((UINT8) (Data)) & 0xff); 381 } 382 383 if (mDst < mDstUpperLimit) { 384 *mDst++ = (UINT8) (((UINT8) (Data >> 0x08)) & 0xff); 385 } 386 387 if (mDst < mDstUpperLimit) { 388 *mDst++ = (UINT8) (((UINT8) (Data >> 0x10)) & 0xff); 389 } 390 391 if (mDst < mDstUpperLimit) { 392 *mDst++ = (UINT8) (((UINT8) (Data >> 0x18)) & 0xff); 393 } 394 } 395 396 STATIC 397 EFI_STATUS 398 AllocateMemory ( 399 VOID 400 ) 401 /*++ 402 403 Routine Description: 404 405 Allocate memory spaces for data structures used in compression process 406 407 Argements: 408 VOID 409 410 Returns: 411 412 EFI_SUCCESS - Memory is allocated successfully 413 EFI_OUT_OF_RESOURCES - Allocation fails 414 415 --*/ 416 { 417 UINT32 Index; 418 419 mText = malloc (WNDSIZ * 2 + MAXMATCH); 420 for (Index = 0; Index < WNDSIZ * 2 + MAXMATCH; Index++) { 421 mText[Index] = 0; 422 } 423 424 mLevel = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mLevel)); 425 mChildCount = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mChildCount)); 426 mPosition = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mPosition)); 427 mParent = malloc (WNDSIZ * 2 * sizeof (*mParent)); 428 mPrev = malloc (WNDSIZ * 2 * sizeof (*mPrev)); 429 mNext = malloc ((MAX_HASH_VAL + 1) * sizeof (*mNext)); 430 431 mBufSiz = BLKSIZ; 432 mBuf = malloc (mBufSiz); 433 while (mBuf == NULL) { 434 mBufSiz = (mBufSiz / 10U) * 9U; 435 if (mBufSiz < 4 * 1024U) { 436 return EFI_OUT_OF_RESOURCES; 437 } 438 439 mBuf = malloc (mBufSiz); 440 } 441 442 mBuf[0] = 0; 443 444 return EFI_SUCCESS; 445 } 446 447 VOID 448 FreeMemory ( 449 VOID 450 ) 451 /*++ 452 453 Routine Description: 454 455 Called when compression is completed to free memory previously allocated. 456 457 Arguments: (VOID) 458 459 Returns: (VOID) 460 461 --*/ 462 { 463 if (mText != NULL) { 464 free (mText); 465 } 466 467 if (mLevel != NULL) { 468 free (mLevel); 469 } 470 471 if (mChildCount != NULL) { 472 free (mChildCount); 473 } 474 475 if (mPosition != NULL) { 476 free (mPosition); 477 } 478 479 if (mParent != NULL) { 480 free (mParent); 481 } 482 483 if (mPrev != NULL) { 484 free (mPrev); 485 } 486 487 if (mNext != NULL) { 488 free (mNext); 489 } 490 491 if (mBuf != NULL) { 492 free (mBuf); 493 } 494 495 return ; 496 } 497 498 STATIC 499 VOID 500 InitSlide ( 501 VOID 502 ) 503 /*++ 504 505 Routine Description: 506 507 Initialize String Info Log data structures 508 509 Arguments: (VOID) 510 511 Returns: (VOID) 512 513 --*/ 514 { 515 NODE Index; 516 517 for (Index = WNDSIZ; Index <= WNDSIZ + UINT8_MAX; Index++) { 518 mLevel[Index] = 1; 519 mPosition[Index] = NIL; /* sentinel */ 520 } 521 522 for (Index = WNDSIZ; Index < WNDSIZ * 2; Index++) { 523 mParent[Index] = NIL; 524 } 525 526 mAvail = 1; 527 for (Index = 1; Index < WNDSIZ - 1; Index++) { 528 mNext[Index] = (NODE) (Index + 1); 529 } 530 531 mNext[WNDSIZ - 1] = NIL; 532 for (Index = WNDSIZ * 2; Index <= MAX_HASH_VAL; Index++) { 533 mNext[Index] = NIL; 534 } 535 } 536 537 STATIC 538 NODE 539 Child ( 540 IN NODE NodeQ, 541 IN UINT8 CharC 542 ) 543 /*++ 544 545 Routine Description: 546 547 Find child node given the parent node and the edge character 548 549 Arguments: 550 551 NodeQ - the parent node 552 CharC - the edge character 553 554 Returns: 555 556 The child node (NIL if not found) 557 558 --*/ 559 { 560 NODE NodeR; 561 562 NodeR = mNext[HASH (NodeQ, CharC)]; 563 // 564 // sentinel 565 // 566 mParent[NIL] = NodeQ; 567 while (mParent[NodeR] != NodeQ) { 568 NodeR = mNext[NodeR]; 569 } 570 571 return NodeR; 572 } 573 574 STATIC 575 VOID 576 MakeChild ( 577 IN NODE Parent, 578 IN UINT8 CharC, 579 IN NODE Child 580 ) 581 /*++ 582 583 Routine Description: 584 585 Create a new child for a given parent node. 586 587 Arguments: 588 589 Parent - the parent node 590 CharC - the edge character 591 Child - the child node 592 593 Returns: (VOID) 594 595 --*/ 596 { 597 NODE Node1; 598 NODE Node2; 599 600 Node1 = (NODE) HASH (Parent, CharC); 601 Node2 = mNext[Node1]; 602 mNext[Node1] = Child; 603 mNext[Child] = Node2; 604 mPrev[Node2] = Child; 605 mPrev[Child] = Node1; 606 mParent[Child] = Parent; 607 mChildCount[Parent]++; 608 } 609 610 STATIC 611 VOID 612 Split ( 613 NODE Old 614 ) 615 /*++ 616 617 Routine Description: 618 619 Split a node. 620 621 Arguments: 622 623 Old - the node to split 624 625 Returns: (VOID) 626 627 --*/ 628 { 629 NODE New; 630 NODE TempNode; 631 632 New = mAvail; 633 mAvail = mNext[New]; 634 mChildCount[New] = 0; 635 TempNode = mPrev[Old]; 636 mPrev[New] = TempNode; 637 mNext[TempNode] = New; 638 TempNode = mNext[Old]; 639 mNext[New] = TempNode; 640 mPrev[TempNode] = New; 641 mParent[New] = mParent[Old]; 642 mLevel[New] = (UINT8) mMatchLen; 643 mPosition[New] = mPos; 644 MakeChild (New, mText[mMatchPos + mMatchLen], Old); 645 MakeChild (New, mText[mPos + mMatchLen], mPos); 646 } 647 648 STATIC 649 VOID 650 InsertNode ( 651 VOID 652 ) 653 /*++ 654 655 Routine Description: 656 657 Insert string info for current position into the String Info Log 658 659 Arguments: (VOID) 660 661 Returns: (VOID) 662 663 --*/ 664 { 665 NODE NodeQ; 666 NODE NodeR; 667 NODE Index2; 668 NODE NodeT; 669 UINT8 CharC; 670 UINT8 *t1; 671 UINT8 *t2; 672 673 if (mMatchLen >= 4) { 674 // 675 // We have just got a long match, the target tree 676 // can be located by MatchPos + 1. Travese the tree 677 // from bottom up to get to a proper starting point. 678 // The usage of PERC_FLAG ensures proper node deletion 679 // in DeleteNode() later. 680 // 681 mMatchLen--; 682 NodeR = (NODE) ((mMatchPos + 1) | WNDSIZ); 683 NodeQ = mParent[NodeR]; 684 while (NodeQ == NIL) { 685 NodeR = mNext[NodeR]; 686 NodeQ = mParent[NodeR]; 687 } 688 689 while (mLevel[NodeQ] >= mMatchLen) { 690 NodeR = NodeQ; 691 NodeQ = mParent[NodeQ]; 692 } 693 694 NodeT = NodeQ; 695 while (mPosition[NodeT] < 0) { 696 mPosition[NodeT] = mPos; 697 NodeT = mParent[NodeT]; 698 } 699 700 if (NodeT < WNDSIZ) { 701 mPosition[NodeT] = (NODE) (mPos | (UINT32) PERC_FLAG); 702 } 703 } else { 704 // 705 // Locate the target tree 706 // 707 NodeQ = (NODE) (mText[mPos] + WNDSIZ); 708 CharC = mText[mPos + 1]; 709 NodeR = Child (NodeQ, CharC); 710 if (NodeR == NIL) { 711 MakeChild (NodeQ, CharC, mPos); 712 mMatchLen = 1; 713 return ; 714 } 715 716 mMatchLen = 2; 717 } 718 // 719 // Traverse down the tree to find a match. 720 // Update Position value along the route. 721 // Node split or creation is involved. 722 // 723 for (;;) { 724 if (NodeR >= WNDSIZ) { 725 Index2 = MAXMATCH; 726 mMatchPos = NodeR; 727 } else { 728 Index2 = mLevel[NodeR]; 729 mMatchPos = (NODE) (mPosition[NodeR] & (UINT32)~PERC_FLAG); 730 } 731 732 if (mMatchPos >= mPos) { 733 mMatchPos -= WNDSIZ; 734 } 735 736 t1 = &mText[mPos + mMatchLen]; 737 t2 = &mText[mMatchPos + mMatchLen]; 738 while (mMatchLen < Index2) { 739 if (*t1 != *t2) { 740 Split (NodeR); 741 return ; 742 } 743 744 mMatchLen++; 745 t1++; 746 t2++; 747 } 748 749 if (mMatchLen >= MAXMATCH) { 750 break; 751 } 752 753 mPosition[NodeR] = mPos; 754 NodeQ = NodeR; 755 NodeR = Child (NodeQ, *t1); 756 if (NodeR == NIL) { 757 MakeChild (NodeQ, *t1, mPos); 758 return ; 759 } 760 761 mMatchLen++; 762 } 763 764 NodeT = mPrev[NodeR]; 765 mPrev[mPos] = NodeT; 766 mNext[NodeT] = mPos; 767 NodeT = mNext[NodeR]; 768 mNext[mPos] = NodeT; 769 mPrev[NodeT] = mPos; 770 mParent[mPos] = NodeQ; 771 mParent[NodeR] = NIL; 772 773 // 774 // Special usage of 'next' 775 // 776 mNext[NodeR] = mPos; 777 778 } 779 780 STATIC 781 VOID 782 DeleteNode ( 783 VOID 784 ) 785 /*++ 786 787 Routine Description: 788 789 Delete outdated string info. (The Usage of PERC_FLAG 790 ensures a clean deletion) 791 792 Arguments: (VOID) 793 794 Returns: (VOID) 795 796 --*/ 797 { 798 NODE NodeQ; 799 NODE NodeR; 800 NODE NodeS; 801 NODE NodeT; 802 NODE NodeU; 803 804 if (mParent[mPos] == NIL) { 805 return ; 806 } 807 808 NodeR = mPrev[mPos]; 809 NodeS = mNext[mPos]; 810 mNext[NodeR] = NodeS; 811 mPrev[NodeS] = NodeR; 812 NodeR = mParent[mPos]; 813 mParent[mPos] = NIL; 814 if (NodeR >= WNDSIZ) { 815 return ; 816 } 817 818 mChildCount[NodeR]--; 819 if (mChildCount[NodeR] > 1) { 820 return ; 821 } 822 823 NodeT = (NODE) (mPosition[NodeR] & (UINT32)~PERC_FLAG); 824 if (NodeT >= mPos) { 825 NodeT -= WNDSIZ; 826 } 827 828 NodeS = NodeT; 829 NodeQ = mParent[NodeR]; 830 NodeU = mPosition[NodeQ]; 831 while (NodeU & (UINT32) PERC_FLAG) { 832 NodeU &= (UINT32)~PERC_FLAG; 833 if (NodeU >= mPos) { 834 NodeU -= WNDSIZ; 835 } 836 837 if (NodeU > NodeS) { 838 NodeS = NodeU; 839 } 840 841 mPosition[NodeQ] = (NODE) (NodeS | WNDSIZ); 842 NodeQ = mParent[NodeQ]; 843 NodeU = mPosition[NodeQ]; 844 } 845 846 if (NodeQ < WNDSIZ) { 847 if (NodeU >= mPos) { 848 NodeU -= WNDSIZ; 849 } 850 851 if (NodeU > NodeS) { 852 NodeS = NodeU; 853 } 854 855 mPosition[NodeQ] = (NODE) (NodeS | WNDSIZ | (UINT32) PERC_FLAG); 856 } 857 858 NodeS = Child (NodeR, mText[NodeT + mLevel[NodeR]]); 859 NodeT = mPrev[NodeS]; 860 NodeU = mNext[NodeS]; 861 mNext[NodeT] = NodeU; 862 mPrev[NodeU] = NodeT; 863 NodeT = mPrev[NodeR]; 864 mNext[NodeT] = NodeS; 865 mPrev[NodeS] = NodeT; 866 NodeT = mNext[NodeR]; 867 mPrev[NodeT] = NodeS; 868 mNext[NodeS] = NodeT; 869 mParent[NodeS] = mParent[NodeR]; 870 mParent[NodeR] = NIL; 871 mNext[NodeR] = mAvail; 872 mAvail = NodeR; 873 } 874 875 STATIC 876 VOID 877 GetNextMatch ( 878 VOID 879 ) 880 /*++ 881 882 Routine Description: 883 884 Advance the current position (read in new data if needed). 885 Delete outdated string info. Find a match string for current position. 886 887 Arguments: (VOID) 888 889 Returns: (VOID) 890 891 --*/ 892 { 893 INT32 Number; 894 895 mRemainder--; 896 mPos++; 897 if (mPos == WNDSIZ * 2) { 898 memmove (&mText[0], &mText[WNDSIZ], WNDSIZ + MAXMATCH); 899 Number = FreadCrc (&mText[WNDSIZ + MAXMATCH], WNDSIZ); 900 mRemainder += Number; 901 mPos = WNDSIZ; 902 } 903 904 DeleteNode (); 905 InsertNode (); 906 } 907 908 STATIC 909 EFI_STATUS 910 Encode ( 911 VOID 912 ) 913 /*++ 914 915 Routine Description: 916 917 The main controlling routine for compression process. 918 919 Arguments: (VOID) 920 921 Returns: 922 923 EFI_SUCCESS - The compression is successful 924 EFI_OUT_0F_RESOURCES - Not enough memory for compression process 925 926 --*/ 927 { 928 EFI_STATUS Status; 929 INT32 LastMatchLen; 930 NODE LastMatchPos; 931 932 Status = AllocateMemory (); 933 if (EFI_ERROR (Status)) { 934 FreeMemory (); 935 return Status; 936 } 937 938 InitSlide (); 939 940 HufEncodeStart (); 941 942 mRemainder = FreadCrc (&mText[WNDSIZ], WNDSIZ + MAXMATCH); 943 944 mMatchLen = 0; 945 mPos = WNDSIZ; 946 InsertNode (); 947 if (mMatchLen > mRemainder) { 948 mMatchLen = mRemainder; 949 } 950 951 while (mRemainder > 0) { 952 LastMatchLen = mMatchLen; 953 LastMatchPos = mMatchPos; 954 GetNextMatch (); 955 if (mMatchLen > mRemainder) { 956 mMatchLen = mRemainder; 957 } 958 959 if (mMatchLen > LastMatchLen || LastMatchLen < THRESHOLD) { 960 // 961 // Not enough benefits are gained by outputting a pointer, 962 // so just output the original character 963 // 964 Output (mText[mPos - 1], 0); 965 966 } else { 967 968 if (LastMatchLen == THRESHOLD) { 969 if (((mPos - LastMatchPos - 2) & (WNDSIZ - 1)) > (1U << 11)) { 970 Output (mText[mPos - 1], 0); 971 continue; 972 } 973 } 974 // 975 // Outputting a pointer is beneficial enough, do it. 976 // 977 Output ( 978 LastMatchLen + (UINT8_MAX + 1 - THRESHOLD), 979 (mPos - LastMatchPos - 2) & (WNDSIZ - 1) 980 ); 981 LastMatchLen--; 982 while (LastMatchLen > 0) { 983 GetNextMatch (); 984 LastMatchLen--; 985 } 986 987 if (mMatchLen > mRemainder) { 988 mMatchLen = mRemainder; 989 } 990 } 991 } 992 993 HufEncodeEnd (); 994 FreeMemory (); 995 return EFI_SUCCESS; 996 } 997 998 STATIC 999 VOID 1000 CountTFreq ( 1001 VOID 1002 ) 1003 /*++ 1004 1005 Routine Description: 1006 1007 Count the frequencies for the Extra Set 1008 1009 Arguments: (VOID) 1010 1011 Returns: (VOID) 1012 1013 --*/ 1014 { 1015 INT32 Index; 1016 INT32 Index3; 1017 INT32 Number; 1018 INT32 Count; 1019 1020 for (Index = 0; Index < NT; Index++) { 1021 mTFreq[Index] = 0; 1022 } 1023 1024 Number = NC; 1025 while (Number > 0 && mCLen[Number - 1] == 0) { 1026 Number--; 1027 } 1028 1029 Index = 0; 1030 while (Index < Number) { 1031 Index3 = mCLen[Index++]; 1032 if (Index3 == 0) { 1033 Count = 1; 1034 while (Index < Number && mCLen[Index] == 0) { 1035 Index++; 1036 Count++; 1037 } 1038 1039 if (Count <= 2) { 1040 mTFreq[0] = (UINT16) (mTFreq[0] + Count); 1041 } else if (Count <= 18) { 1042 mTFreq[1]++; 1043 } else if (Count == 19) { 1044 mTFreq[0]++; 1045 mTFreq[1]++; 1046 } else { 1047 mTFreq[2]++; 1048 } 1049 } else { 1050 mTFreq[Index3 + 2]++; 1051 } 1052 } 1053 } 1054 1055 STATIC 1056 VOID 1057 WritePTLen ( 1058 IN INT32 Number, 1059 IN INT32 nbit, 1060 IN INT32 Special 1061 ) 1062 /*++ 1063 1064 Routine Description: 1065 1066 Outputs the code length array for the Extra Set or the Position Set. 1067 1068 Arguments: 1069 1070 Number - the number of symbols 1071 nbit - the number of bits needed to represent 'n' 1072 Special - the special symbol that needs to be take care of 1073 1074 Returns: (VOID) 1075 1076 --*/ 1077 { 1078 INT32 Index; 1079 INT32 Index3; 1080 1081 while (Number > 0 && mPTLen[Number - 1] == 0) { 1082 Number--; 1083 } 1084 1085 PutBits (nbit, Number); 1086 Index = 0; 1087 while (Index < Number) { 1088 Index3 = mPTLen[Index++]; 1089 if (Index3 <= 6) { 1090 PutBits (3, Index3); 1091 } else { 1092 PutBits (Index3 - 3, (1U << (Index3 - 3)) - 2); 1093 } 1094 1095 if (Index == Special) { 1096 while (Index < 6 && mPTLen[Index] == 0) { 1097 Index++; 1098 } 1099 1100 PutBits (2, (Index - 3) & 3); 1101 } 1102 } 1103 } 1104 1105 STATIC 1106 VOID 1107 WriteCLen ( 1108 VOID 1109 ) 1110 /*++ 1111 1112 Routine Description: 1113 1114 Outputs the code length array for Char&Length Set 1115 1116 Arguments: (VOID) 1117 1118 Returns: (VOID) 1119 1120 --*/ 1121 { 1122 INT32 Index; 1123 INT32 Index3; 1124 INT32 Number; 1125 INT32 Count; 1126 1127 Number = NC; 1128 while (Number > 0 && mCLen[Number - 1] == 0) { 1129 Number--; 1130 } 1131 1132 PutBits (CBIT, Number); 1133 Index = 0; 1134 while (Index < Number) { 1135 Index3 = mCLen[Index++]; 1136 if (Index3 == 0) { 1137 Count = 1; 1138 while (Index < Number && mCLen[Index] == 0) { 1139 Index++; 1140 Count++; 1141 } 1142 1143 if (Count <= 2) { 1144 for (Index3 = 0; Index3 < Count; Index3++) { 1145 PutBits (mPTLen[0], mPTCode[0]); 1146 } 1147 } else if (Count <= 18) { 1148 PutBits (mPTLen[1], mPTCode[1]); 1149 PutBits (4, Count - 3); 1150 } else if (Count == 19) { 1151 PutBits (mPTLen[0], mPTCode[0]); 1152 PutBits (mPTLen[1], mPTCode[1]); 1153 PutBits (4, 15); 1154 } else { 1155 PutBits (mPTLen[2], mPTCode[2]); 1156 PutBits (CBIT, Count - 20); 1157 } 1158 } else { 1159 PutBits (mPTLen[Index3 + 2], mPTCode[Index3 + 2]); 1160 } 1161 } 1162 } 1163 1164 STATIC 1165 VOID 1166 EncodeC ( 1167 IN INT32 Value 1168 ) 1169 { 1170 PutBits (mCLen[Value], mCCode[Value]); 1171 } 1172 1173 STATIC 1174 VOID 1175 EncodeP ( 1176 IN UINT32 Value 1177 ) 1178 { 1179 UINT32 Index; 1180 UINT32 NodeQ; 1181 1182 Index = 0; 1183 NodeQ = Value; 1184 while (NodeQ) { 1185 NodeQ >>= 1; 1186 Index++; 1187 } 1188 1189 PutBits (mPTLen[Index], mPTCode[Index]); 1190 if (Index > 1) { 1191 PutBits (Index - 1, Value & (0xFFFFFFFFU >> (32 - Index + 1))); 1192 } 1193 } 1194 1195 STATIC 1196 VOID 1197 SendBlock ( 1198 VOID 1199 ) 1200 /*++ 1201 1202 Routine Description: 1203 1204 Huffman code the block and output it. 1205 1206 Arguments: 1207 (VOID) 1208 1209 Returns: 1210 (VOID) 1211 1212 --*/ 1213 { 1214 UINT32 Index; 1215 UINT32 Index2; 1216 UINT32 Index3; 1217 UINT32 Flags; 1218 UINT32 Root; 1219 UINT32 Pos; 1220 UINT32 Size; 1221 Flags = 0; 1222 1223 Root = MakeTree (NC, mCFreq, mCLen, mCCode); 1224 Size = mCFreq[Root]; 1225 PutBits (16, Size); 1226 if (Root >= NC) { 1227 CountTFreq (); 1228 Root = MakeTree (NT, mTFreq, mPTLen, mPTCode); 1229 if (Root >= NT) { 1230 WritePTLen (NT, TBIT, 3); 1231 } else { 1232 PutBits (TBIT, 0); 1233 PutBits (TBIT, Root); 1234 } 1235 1236 WriteCLen (); 1237 } else { 1238 PutBits (TBIT, 0); 1239 PutBits (TBIT, 0); 1240 PutBits (CBIT, 0); 1241 PutBits (CBIT, Root); 1242 } 1243 1244 Root = MakeTree (NP, mPFreq, mPTLen, mPTCode); 1245 if (Root >= NP) { 1246 WritePTLen (NP, PBIT, -1); 1247 } else { 1248 PutBits (PBIT, 0); 1249 PutBits (PBIT, Root); 1250 } 1251 1252 Pos = 0; 1253 for (Index = 0; Index < Size; Index++) { 1254 if (Index % UINT8_BIT == 0) { 1255 Flags = mBuf[Pos++]; 1256 } else { 1257 Flags <<= 1; 1258 } 1259 1260 if (Flags & (1U << (UINT8_BIT - 1))) { 1261 EncodeC (mBuf[Pos++] + (1U << UINT8_BIT)); 1262 Index3 = mBuf[Pos++]; 1263 for (Index2 = 0; Index2 < 3; Index2++) { 1264 Index3 <<= UINT8_BIT; 1265 Index3 += mBuf[Pos++]; 1266 } 1267 1268 EncodeP (Index3); 1269 } else { 1270 EncodeC (mBuf[Pos++]); 1271 } 1272 } 1273 1274 for (Index = 0; Index < NC; Index++) { 1275 mCFreq[Index] = 0; 1276 } 1277 1278 for (Index = 0; Index < NP; Index++) { 1279 mPFreq[Index] = 0; 1280 } 1281 } 1282 1283 STATIC 1284 VOID 1285 Output ( 1286 IN UINT32 CharC, 1287 IN UINT32 Pos 1288 ) 1289 /*++ 1290 1291 Routine Description: 1292 1293 Outputs an Original Character or a Pointer 1294 1295 Arguments: 1296 1297 CharC - The original character or the 'String Length' element of a Pointer 1298 Pos - The 'Position' field of a Pointer 1299 1300 Returns: (VOID) 1301 1302 --*/ 1303 { 1304 STATIC UINT32 CPos; 1305 1306 if ((mOutputMask >>= 1) == 0) { 1307 mOutputMask = 1U << (UINT8_BIT - 1); 1308 // 1309 // Check the buffer overflow per outputing UINT8_BIT symbols 1310 // which is an Original Character or a Pointer. The biggest 1311 // symbol is a Pointer which occupies 5 bytes. 1312 // 1313 if (mOutputPos >= mBufSiz - 5 * UINT8_BIT) { 1314 SendBlock (); 1315 mOutputPos = 0; 1316 } 1317 1318 CPos = mOutputPos++; 1319 mBuf[CPos] = 0; 1320 } 1321 1322 mBuf[mOutputPos++] = (UINT8) CharC; 1323 mCFreq[CharC]++; 1324 if (CharC >= (1U << UINT8_BIT)) { 1325 mBuf[CPos] |= mOutputMask; 1326 mBuf[mOutputPos++] = (UINT8) (Pos >> 24); 1327 mBuf[mOutputPos++] = (UINT8) (Pos >> 16); 1328 mBuf[mOutputPos++] = (UINT8) (Pos >> (UINT8_BIT)); 1329 mBuf[mOutputPos++] = (UINT8) Pos; 1330 CharC = 0; 1331 while (Pos) { 1332 Pos >>= 1; 1333 CharC++; 1334 } 1335 1336 mPFreq[CharC]++; 1337 } 1338 } 1339 1340 STATIC 1341 VOID 1342 HufEncodeStart ( 1343 VOID 1344 ) 1345 { 1346 INT32 Index; 1347 1348 for (Index = 0; Index < NC; Index++) { 1349 mCFreq[Index] = 0; 1350 } 1351 1352 for (Index = 0; Index < NP; Index++) { 1353 mPFreq[Index] = 0; 1354 } 1355 1356 mOutputPos = mOutputMask = 0; 1357 InitPutBits (); 1358 return ; 1359 } 1360 1361 STATIC 1362 VOID 1363 HufEncodeEnd ( 1364 VOID 1365 ) 1366 { 1367 SendBlock (); 1368 1369 // 1370 // Flush remaining bits 1371 // 1372 PutBits (UINT8_BIT - 1, 0); 1373 1374 return ; 1375 } 1376 1377 STATIC 1378 VOID 1379 MakeCrcTable ( 1380 VOID 1381 ) 1382 { 1383 UINT32 Index; 1384 UINT32 Index2; 1385 UINT32 Temp; 1386 1387 for (Index = 0; Index <= UINT8_MAX; Index++) { 1388 Temp = Index; 1389 for (Index2 = 0; Index2 < UINT8_BIT; Index2++) { 1390 if (Temp & 1) { 1391 Temp = (Temp >> 1) ^ CRCPOLY; 1392 } else { 1393 Temp >>= 1; 1394 } 1395 } 1396 1397 mCrcTable[Index] = (UINT16) Temp; 1398 } 1399 } 1400 1401 STATIC 1402 VOID 1403 PutBits ( 1404 IN INT32 Number, 1405 IN UINT32 Value 1406 ) 1407 /*++ 1408 1409 Routine Description: 1410 1411 Outputs rightmost n bits of x 1412 1413 Arguments: 1414 1415 Number - the rightmost n bits of the data is used 1416 x - the data 1417 1418 Returns: (VOID) 1419 1420 --*/ 1421 { 1422 UINT8 Temp; 1423 1424 while (Number >= mBitCount) { 1425 // 1426 // Number -= mBitCount should never equal to 32 1427 // 1428 Temp = (UINT8) (mSubBitBuf | (Value >> (Number -= mBitCount))); 1429 if (mDst < mDstUpperLimit) { 1430 *mDst++ = Temp; 1431 } 1432 1433 mCompSize++; 1434 mSubBitBuf = 0; 1435 mBitCount = UINT8_BIT; 1436 } 1437 1438 mSubBitBuf |= Value << (mBitCount -= Number); 1439 } 1440 1441 STATIC 1442 INT32 1443 FreadCrc ( 1444 OUT UINT8 *Pointer, 1445 IN INT32 Number 1446 ) 1447 /*++ 1448 1449 Routine Description: 1450 1451 Read in source data 1452 1453 Arguments: 1454 1455 Pointer - the buffer to hold the data 1456 Number - number of bytes to read 1457 1458 Returns: 1459 1460 number of bytes actually read 1461 1462 --*/ 1463 { 1464 INT32 Index; 1465 1466 for (Index = 0; mSrc < mSrcUpperLimit && Index < Number; Index++) { 1467 *Pointer++ = *mSrc++; 1468 } 1469 1470 Number = Index; 1471 1472 Pointer -= Number; 1473 mOrigSize += Number; 1474 Index--; 1475 while (Index >= 0) { 1476 UPDATE_CRC (*Pointer++); 1477 Index--; 1478 } 1479 1480 return Number; 1481 } 1482 1483 STATIC 1484 VOID 1485 InitPutBits ( 1486 VOID 1487 ) 1488 { 1489 mBitCount = UINT8_BIT; 1490 mSubBitBuf = 0; 1491 } 1492 1493 STATIC 1494 VOID 1495 CountLen ( 1496 IN INT32 Index 1497 ) 1498 /*++ 1499 1500 Routine Description: 1501 1502 Count the number of each code length for a Huffman tree. 1503 1504 Arguments: 1505 1506 Index - the top node 1507 1508 Returns: (VOID) 1509 1510 --*/ 1511 { 1512 STATIC INT32 Depth = 0; 1513 1514 if (Index < mN) { 1515 mLenCnt[(Depth < 16) ? Depth : 16]++; 1516 } else { 1517 Depth++; 1518 CountLen (mLeft[Index]); 1519 CountLen (mRight[Index]); 1520 Depth--; 1521 } 1522 } 1523 1524 STATIC 1525 VOID 1526 MakeLen ( 1527 IN INT32 Root 1528 ) 1529 /*++ 1530 1531 Routine Description: 1532 1533 Create code length array for a Huffman tree 1534 1535 Arguments: 1536 1537 Root - the root of the tree 1538 1539 Returns: 1540 1541 VOID 1542 1543 --*/ 1544 { 1545 INT32 Index; 1546 INT32 Index3; 1547 UINT32 Cum; 1548 1549 for (Index = 0; Index <= 16; Index++) { 1550 mLenCnt[Index] = 0; 1551 } 1552 1553 CountLen (Root); 1554 1555 // 1556 // Adjust the length count array so that 1557 // no code will be generated longer than its designated length 1558 // 1559 Cum = 0; 1560 for (Index = 16; Index > 0; Index--) { 1561 Cum += mLenCnt[Index] << (16 - Index); 1562 } 1563 1564 while (Cum != (1U << 16)) { 1565 mLenCnt[16]--; 1566 for (Index = 15; Index > 0; Index--) { 1567 if (mLenCnt[Index] != 0) { 1568 mLenCnt[Index]--; 1569 mLenCnt[Index + 1] += 2; 1570 break; 1571 } 1572 } 1573 1574 Cum--; 1575 } 1576 1577 for (Index = 16; Index > 0; Index--) { 1578 Index3 = mLenCnt[Index]; 1579 Index3--; 1580 while (Index3 >= 0) { 1581 mLen[*mSortPtr++] = (UINT8) Index; 1582 Index3--; 1583 } 1584 } 1585 } 1586 1587 STATIC 1588 VOID 1589 DownHeap ( 1590 IN INT32 Index 1591 ) 1592 { 1593 INT32 Index2; 1594 INT32 Index3; 1595 1596 // 1597 // priority queue: send Index-th entry down heap 1598 // 1599 Index3 = mHeap[Index]; 1600 Index2 = 2 * Index; 1601 while (Index2 <= mHeapSize) { 1602 if (Index2 < mHeapSize && mFreq[mHeap[Index2]] > mFreq[mHeap[Index2 + 1]]) { 1603 Index2++; 1604 } 1605 1606 if (mFreq[Index3] <= mFreq[mHeap[Index2]]) { 1607 break; 1608 } 1609 1610 mHeap[Index] = mHeap[Index2]; 1611 Index = Index2; 1612 Index2 = 2 * Index; 1613 } 1614 1615 mHeap[Index] = (INT16) Index3; 1616 } 1617 1618 STATIC 1619 VOID 1620 MakeCode ( 1621 IN INT32 Number, 1622 IN UINT8 Len[ ], 1623 OUT UINT16 Code[] 1624 ) 1625 /*++ 1626 1627 Routine Description: 1628 1629 Assign code to each symbol based on the code length array 1630 1631 Arguments: 1632 1633 Number - number of symbols 1634 Len - the code length array 1635 Code - stores codes for each symbol 1636 1637 Returns: (VOID) 1638 1639 --*/ 1640 { 1641 INT32 Index; 1642 UINT16 Start[18]; 1643 1644 Start[1] = 0; 1645 for (Index = 1; Index <= 16; Index++) { 1646 Start[Index + 1] = (UINT16) ((Start[Index] + mLenCnt[Index]) << 1); 1647 } 1648 1649 for (Index = 0; Index < Number; Index++) { 1650 Code[Index] = Start[Len[Index]]++; 1651 } 1652 } 1653 1654 STATIC 1655 INT32 1656 MakeTree ( 1657 IN INT32 NParm, 1658 IN UINT16 FreqParm[], 1659 OUT UINT8 LenParm[ ], 1660 OUT UINT16 CodeParm[] 1661 ) 1662 /*++ 1663 1664 Routine Description: 1665 1666 Generates Huffman codes given a frequency distribution of symbols 1667 1668 Arguments: 1669 1670 NParm - number of symbols 1671 FreqParm - frequency of each symbol 1672 LenParm - code length for each symbol 1673 CodeParm - code for each symbol 1674 1675 Returns: 1676 1677 Root of the Huffman tree. 1678 1679 --*/ 1680 { 1681 INT32 Index; 1682 INT32 Index2; 1683 INT32 Index3; 1684 INT32 Avail; 1685 1686 // 1687 // make tree, calculate len[], return root 1688 // 1689 mN = NParm; 1690 mFreq = FreqParm; 1691 mLen = LenParm; 1692 Avail = mN; 1693 mHeapSize = 0; 1694 mHeap[1] = 0; 1695 for (Index = 0; Index < mN; Index++) { 1696 mLen[Index] = 0; 1697 if (mFreq[Index]) { 1698 mHeapSize++; 1699 mHeap[mHeapSize] = (INT16) Index; 1700 } 1701 } 1702 1703 if (mHeapSize < 2) { 1704 CodeParm[mHeap[1]] = 0; 1705 return mHeap[1]; 1706 } 1707 1708 for (Index = mHeapSize / 2; Index >= 1; Index--) { 1709 // 1710 // make priority queue 1711 // 1712 DownHeap (Index); 1713 } 1714 1715 mSortPtr = CodeParm; 1716 do { 1717 Index = mHeap[1]; 1718 if (Index < mN) { 1719 *mSortPtr++ = (UINT16) Index; 1720 } 1721 1722 mHeap[1] = mHeap[mHeapSize--]; 1723 DownHeap (1); 1724 Index2 = mHeap[1]; 1725 if (Index2 < mN) { 1726 *mSortPtr++ = (UINT16) Index2; 1727 } 1728 1729 Index3 = Avail++; 1730 mFreq[Index3] = (UINT16) (mFreq[Index] + mFreq[Index2]); 1731 mHeap[1] = (INT16) Index3; 1732 DownHeap (1); 1733 mLeft[Index3] = (UINT16) Index; 1734 mRight[Index3] = (UINT16) Index2; 1735 } while (mHeapSize > 1); 1736 1737 mSortPtr = CodeParm; 1738 MakeLen (Index3); 1739 MakeCode (NParm, LenParm, CodeParm); 1740 1741 // 1742 // return root 1743 // 1744 return Index3; 1745 } 1746