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 - 2016, 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 if (mText == NULL) { 421 return EFI_OUT_OF_RESOURCES; 422 } 423 for (Index = 0; Index < WNDSIZ * 2 + MAXMATCH; Index++) { 424 mText[Index] = 0; 425 } 426 427 mLevel = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mLevel)); 428 mChildCount = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mChildCount)); 429 mPosition = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mPosition)); 430 mParent = malloc (WNDSIZ * 2 * sizeof (*mParent)); 431 mPrev = malloc (WNDSIZ * 2 * sizeof (*mPrev)); 432 mNext = malloc ((MAX_HASH_VAL + 1) * sizeof (*mNext)); 433 if (mLevel == NULL || mChildCount == NULL || mPosition == NULL || 434 mParent == NULL || mPrev == NULL || mNext == NULL) { 435 return EFI_OUT_OF_RESOURCES; 436 } 437 438 mBufSiz = BLKSIZ; 439 mBuf = malloc (mBufSiz); 440 while (mBuf == NULL) { 441 mBufSiz = (mBufSiz / 10U) * 9U; 442 if (mBufSiz < 4 * 1024U) { 443 return EFI_OUT_OF_RESOURCES; 444 } 445 446 mBuf = malloc (mBufSiz); 447 } 448 449 mBuf[0] = 0; 450 451 return EFI_SUCCESS; 452 } 453 454 VOID 455 FreeMemory ( 456 VOID 457 ) 458 /*++ 459 460 Routine Description: 461 462 Called when compression is completed to free memory previously allocated. 463 464 Arguments: (VOID) 465 466 Returns: (VOID) 467 468 --*/ 469 { 470 if (mText != NULL) { 471 free (mText); 472 } 473 474 if (mLevel != NULL) { 475 free (mLevel); 476 } 477 478 if (mChildCount != NULL) { 479 free (mChildCount); 480 } 481 482 if (mPosition != NULL) { 483 free (mPosition); 484 } 485 486 if (mParent != NULL) { 487 free (mParent); 488 } 489 490 if (mPrev != NULL) { 491 free (mPrev); 492 } 493 494 if (mNext != NULL) { 495 free (mNext); 496 } 497 498 if (mBuf != NULL) { 499 free (mBuf); 500 } 501 502 return ; 503 } 504 505 STATIC 506 VOID 507 InitSlide ( 508 VOID 509 ) 510 /*++ 511 512 Routine Description: 513 514 Initialize String Info Log data structures 515 516 Arguments: (VOID) 517 518 Returns: (VOID) 519 520 --*/ 521 { 522 NODE Index; 523 524 for (Index = WNDSIZ; Index <= WNDSIZ + UINT8_MAX; Index++) { 525 mLevel[Index] = 1; 526 mPosition[Index] = NIL; /* sentinel */ 527 } 528 529 for (Index = WNDSIZ; Index < WNDSIZ * 2; Index++) { 530 mParent[Index] = NIL; 531 } 532 533 mAvail = 1; 534 for (Index = 1; Index < WNDSIZ - 1; Index++) { 535 mNext[Index] = (NODE) (Index + 1); 536 } 537 538 mNext[WNDSIZ - 1] = NIL; 539 for (Index = WNDSIZ * 2; Index <= MAX_HASH_VAL; Index++) { 540 mNext[Index] = NIL; 541 } 542 } 543 544 STATIC 545 NODE 546 Child ( 547 IN NODE NodeQ, 548 IN UINT8 CharC 549 ) 550 /*++ 551 552 Routine Description: 553 554 Find child node given the parent node and the edge character 555 556 Arguments: 557 558 NodeQ - the parent node 559 CharC - the edge character 560 561 Returns: 562 563 The child node (NIL if not found) 564 565 --*/ 566 { 567 NODE NodeR; 568 569 NodeR = mNext[HASH (NodeQ, CharC)]; 570 // 571 // sentinel 572 // 573 mParent[NIL] = NodeQ; 574 while (mParent[NodeR] != NodeQ) { 575 NodeR = mNext[NodeR]; 576 } 577 578 return NodeR; 579 } 580 581 STATIC 582 VOID 583 MakeChild ( 584 IN NODE Parent, 585 IN UINT8 CharC, 586 IN NODE Child 587 ) 588 /*++ 589 590 Routine Description: 591 592 Create a new child for a given parent node. 593 594 Arguments: 595 596 Parent - the parent node 597 CharC - the edge character 598 Child - the child node 599 600 Returns: (VOID) 601 602 --*/ 603 { 604 NODE Node1; 605 NODE Node2; 606 607 Node1 = (NODE) HASH (Parent, CharC); 608 Node2 = mNext[Node1]; 609 mNext[Node1] = Child; 610 mNext[Child] = Node2; 611 mPrev[Node2] = Child; 612 mPrev[Child] = Node1; 613 mParent[Child] = Parent; 614 mChildCount[Parent]++; 615 } 616 617 STATIC 618 VOID 619 Split ( 620 NODE Old 621 ) 622 /*++ 623 624 Routine Description: 625 626 Split a node. 627 628 Arguments: 629 630 Old - the node to split 631 632 Returns: (VOID) 633 634 --*/ 635 { 636 NODE New; 637 NODE TempNode; 638 639 New = mAvail; 640 mAvail = mNext[New]; 641 mChildCount[New] = 0; 642 TempNode = mPrev[Old]; 643 mPrev[New] = TempNode; 644 mNext[TempNode] = New; 645 TempNode = mNext[Old]; 646 mNext[New] = TempNode; 647 mPrev[TempNode] = New; 648 mParent[New] = mParent[Old]; 649 mLevel[New] = (UINT8) mMatchLen; 650 mPosition[New] = mPos; 651 MakeChild (New, mText[mMatchPos + mMatchLen], Old); 652 MakeChild (New, mText[mPos + mMatchLen], mPos); 653 } 654 655 STATIC 656 VOID 657 InsertNode ( 658 VOID 659 ) 660 /*++ 661 662 Routine Description: 663 664 Insert string info for current position into the String Info Log 665 666 Arguments: (VOID) 667 668 Returns: (VOID) 669 670 --*/ 671 { 672 NODE NodeQ; 673 NODE NodeR; 674 NODE Index2; 675 NODE NodeT; 676 UINT8 CharC; 677 UINT8 *t1; 678 UINT8 *t2; 679 680 if (mMatchLen >= 4) { 681 // 682 // We have just got a long match, the target tree 683 // can be located by MatchPos + 1. Travese the tree 684 // from bottom up to get to a proper starting point. 685 // The usage of PERC_FLAG ensures proper node deletion 686 // in DeleteNode() later. 687 // 688 mMatchLen--; 689 NodeR = (NODE) ((mMatchPos + 1) | WNDSIZ); 690 NodeQ = mParent[NodeR]; 691 while (NodeQ == NIL) { 692 NodeR = mNext[NodeR]; 693 NodeQ = mParent[NodeR]; 694 } 695 696 while (mLevel[NodeQ] >= mMatchLen) { 697 NodeR = NodeQ; 698 NodeQ = mParent[NodeQ]; 699 } 700 701 NodeT = NodeQ; 702 while (mPosition[NodeT] < 0) { 703 mPosition[NodeT] = mPos; 704 NodeT = mParent[NodeT]; 705 } 706 707 if (NodeT < WNDSIZ) { 708 mPosition[NodeT] = (NODE) (mPos | (UINT32) PERC_FLAG); 709 } 710 } else { 711 // 712 // Locate the target tree 713 // 714 NodeQ = (NODE) (mText[mPos] + WNDSIZ); 715 CharC = mText[mPos + 1]; 716 NodeR = Child (NodeQ, CharC); 717 if (NodeR == NIL) { 718 MakeChild (NodeQ, CharC, mPos); 719 mMatchLen = 1; 720 return ; 721 } 722 723 mMatchLen = 2; 724 } 725 // 726 // Traverse down the tree to find a match. 727 // Update Position value along the route. 728 // Node split or creation is involved. 729 // 730 for (;;) { 731 if (NodeR >= WNDSIZ) { 732 Index2 = MAXMATCH; 733 mMatchPos = NodeR; 734 } else { 735 Index2 = mLevel[NodeR]; 736 mMatchPos = (NODE) (mPosition[NodeR] & (UINT32)~PERC_FLAG); 737 } 738 739 if (mMatchPos >= mPos) { 740 mMatchPos -= WNDSIZ; 741 } 742 743 t1 = &mText[mPos + mMatchLen]; 744 t2 = &mText[mMatchPos + mMatchLen]; 745 while (mMatchLen < Index2) { 746 if (*t1 != *t2) { 747 Split (NodeR); 748 return ; 749 } 750 751 mMatchLen++; 752 t1++; 753 t2++; 754 } 755 756 if (mMatchLen >= MAXMATCH) { 757 break; 758 } 759 760 mPosition[NodeR] = mPos; 761 NodeQ = NodeR; 762 NodeR = Child (NodeQ, *t1); 763 if (NodeR == NIL) { 764 MakeChild (NodeQ, *t1, mPos); 765 return ; 766 } 767 768 mMatchLen++; 769 } 770 771 NodeT = mPrev[NodeR]; 772 mPrev[mPos] = NodeT; 773 mNext[NodeT] = mPos; 774 NodeT = mNext[NodeR]; 775 mNext[mPos] = NodeT; 776 mPrev[NodeT] = mPos; 777 mParent[mPos] = NodeQ; 778 mParent[NodeR] = NIL; 779 780 // 781 // Special usage of 'next' 782 // 783 mNext[NodeR] = mPos; 784 785 } 786 787 STATIC 788 VOID 789 DeleteNode ( 790 VOID 791 ) 792 /*++ 793 794 Routine Description: 795 796 Delete outdated string info. (The Usage of PERC_FLAG 797 ensures a clean deletion) 798 799 Arguments: (VOID) 800 801 Returns: (VOID) 802 803 --*/ 804 { 805 NODE NodeQ; 806 NODE NodeR; 807 NODE NodeS; 808 NODE NodeT; 809 NODE NodeU; 810 811 if (mParent[mPos] == NIL) { 812 return ; 813 } 814 815 NodeR = mPrev[mPos]; 816 NodeS = mNext[mPos]; 817 mNext[NodeR] = NodeS; 818 mPrev[NodeS] = NodeR; 819 NodeR = mParent[mPos]; 820 mParent[mPos] = NIL; 821 if (NodeR >= WNDSIZ) { 822 return ; 823 } 824 825 mChildCount[NodeR]--; 826 if (mChildCount[NodeR] > 1) { 827 return ; 828 } 829 830 NodeT = (NODE) (mPosition[NodeR] & (UINT32)~PERC_FLAG); 831 if (NodeT >= mPos) { 832 NodeT -= WNDSIZ; 833 } 834 835 NodeS = NodeT; 836 NodeQ = mParent[NodeR]; 837 NodeU = mPosition[NodeQ]; 838 while (NodeU & (UINT32) PERC_FLAG) { 839 NodeU &= (UINT32)~PERC_FLAG; 840 if (NodeU >= mPos) { 841 NodeU -= WNDSIZ; 842 } 843 844 if (NodeU > NodeS) { 845 NodeS = NodeU; 846 } 847 848 mPosition[NodeQ] = (NODE) (NodeS | WNDSIZ); 849 NodeQ = mParent[NodeQ]; 850 NodeU = mPosition[NodeQ]; 851 } 852 853 if (NodeQ < WNDSIZ) { 854 if (NodeU >= mPos) { 855 NodeU -= WNDSIZ; 856 } 857 858 if (NodeU > NodeS) { 859 NodeS = NodeU; 860 } 861 862 mPosition[NodeQ] = (NODE) (NodeS | WNDSIZ | (UINT32) PERC_FLAG); 863 } 864 865 NodeS = Child (NodeR, mText[NodeT + mLevel[NodeR]]); 866 NodeT = mPrev[NodeS]; 867 NodeU = mNext[NodeS]; 868 mNext[NodeT] = NodeU; 869 mPrev[NodeU] = NodeT; 870 NodeT = mPrev[NodeR]; 871 mNext[NodeT] = NodeS; 872 mPrev[NodeS] = NodeT; 873 NodeT = mNext[NodeR]; 874 mPrev[NodeT] = NodeS; 875 mNext[NodeS] = NodeT; 876 mParent[NodeS] = mParent[NodeR]; 877 mParent[NodeR] = NIL; 878 mNext[NodeR] = mAvail; 879 mAvail = NodeR; 880 } 881 882 STATIC 883 VOID 884 GetNextMatch ( 885 VOID 886 ) 887 /*++ 888 889 Routine Description: 890 891 Advance the current position (read in new data if needed). 892 Delete outdated string info. Find a match string for current position. 893 894 Arguments: (VOID) 895 896 Returns: (VOID) 897 898 --*/ 899 { 900 INT32 Number; 901 902 mRemainder--; 903 mPos++; 904 if (mPos == WNDSIZ * 2) { 905 memmove (&mText[0], &mText[WNDSIZ], WNDSIZ + MAXMATCH); 906 Number = FreadCrc (&mText[WNDSIZ + MAXMATCH], WNDSIZ); 907 mRemainder += Number; 908 mPos = WNDSIZ; 909 } 910 911 DeleteNode (); 912 InsertNode (); 913 } 914 915 STATIC 916 EFI_STATUS 917 Encode ( 918 VOID 919 ) 920 /*++ 921 922 Routine Description: 923 924 The main controlling routine for compression process. 925 926 Arguments: (VOID) 927 928 Returns: 929 930 EFI_SUCCESS - The compression is successful 931 EFI_OUT_0F_RESOURCES - Not enough memory for compression process 932 933 --*/ 934 { 935 EFI_STATUS Status; 936 INT32 LastMatchLen; 937 NODE LastMatchPos; 938 939 Status = AllocateMemory (); 940 if (EFI_ERROR (Status)) { 941 FreeMemory (); 942 return Status; 943 } 944 945 InitSlide (); 946 947 HufEncodeStart (); 948 949 mRemainder = FreadCrc (&mText[WNDSIZ], WNDSIZ + MAXMATCH); 950 951 mMatchLen = 0; 952 mPos = WNDSIZ; 953 InsertNode (); 954 if (mMatchLen > mRemainder) { 955 mMatchLen = mRemainder; 956 } 957 958 while (mRemainder > 0) { 959 LastMatchLen = mMatchLen; 960 LastMatchPos = mMatchPos; 961 GetNextMatch (); 962 if (mMatchLen > mRemainder) { 963 mMatchLen = mRemainder; 964 } 965 966 if (mMatchLen > LastMatchLen || LastMatchLen < THRESHOLD) { 967 // 968 // Not enough benefits are gained by outputting a pointer, 969 // so just output the original character 970 // 971 Output (mText[mPos - 1], 0); 972 973 } else { 974 975 if (LastMatchLen == THRESHOLD) { 976 if (((mPos - LastMatchPos - 2) & (WNDSIZ - 1)) > (1U << 11)) { 977 Output (mText[mPos - 1], 0); 978 continue; 979 } 980 } 981 // 982 // Outputting a pointer is beneficial enough, do it. 983 // 984 Output ( 985 LastMatchLen + (UINT8_MAX + 1 - THRESHOLD), 986 (mPos - LastMatchPos - 2) & (WNDSIZ - 1) 987 ); 988 LastMatchLen--; 989 while (LastMatchLen > 0) { 990 GetNextMatch (); 991 LastMatchLen--; 992 } 993 994 if (mMatchLen > mRemainder) { 995 mMatchLen = mRemainder; 996 } 997 } 998 } 999 1000 HufEncodeEnd (); 1001 FreeMemory (); 1002 return EFI_SUCCESS; 1003 } 1004 1005 STATIC 1006 VOID 1007 CountTFreq ( 1008 VOID 1009 ) 1010 /*++ 1011 1012 Routine Description: 1013 1014 Count the frequencies for the Extra Set 1015 1016 Arguments: (VOID) 1017 1018 Returns: (VOID) 1019 1020 --*/ 1021 { 1022 INT32 Index; 1023 INT32 Index3; 1024 INT32 Number; 1025 INT32 Count; 1026 1027 for (Index = 0; Index < NT; Index++) { 1028 mTFreq[Index] = 0; 1029 } 1030 1031 Number = NC; 1032 while (Number > 0 && mCLen[Number - 1] == 0) { 1033 Number--; 1034 } 1035 1036 Index = 0; 1037 while (Index < Number) { 1038 Index3 = mCLen[Index++]; 1039 if (Index3 == 0) { 1040 Count = 1; 1041 while (Index < Number && mCLen[Index] == 0) { 1042 Index++; 1043 Count++; 1044 } 1045 1046 if (Count <= 2) { 1047 mTFreq[0] = (UINT16) (mTFreq[0] + Count); 1048 } else if (Count <= 18) { 1049 mTFreq[1]++; 1050 } else if (Count == 19) { 1051 mTFreq[0]++; 1052 mTFreq[1]++; 1053 } else { 1054 mTFreq[2]++; 1055 } 1056 } else { 1057 mTFreq[Index3 + 2]++; 1058 } 1059 } 1060 } 1061 1062 STATIC 1063 VOID 1064 WritePTLen ( 1065 IN INT32 Number, 1066 IN INT32 nbit, 1067 IN INT32 Special 1068 ) 1069 /*++ 1070 1071 Routine Description: 1072 1073 Outputs the code length array for the Extra Set or the Position Set. 1074 1075 Arguments: 1076 1077 Number - the number of symbols 1078 nbit - the number of bits needed to represent 'n' 1079 Special - the special symbol that needs to be take care of 1080 1081 Returns: (VOID) 1082 1083 --*/ 1084 { 1085 INT32 Index; 1086 INT32 Index3; 1087 1088 while (Number > 0 && mPTLen[Number - 1] == 0) { 1089 Number--; 1090 } 1091 1092 PutBits (nbit, Number); 1093 Index = 0; 1094 while (Index < Number) { 1095 Index3 = mPTLen[Index++]; 1096 if (Index3 <= 6) { 1097 PutBits (3, Index3); 1098 } else { 1099 PutBits (Index3 - 3, (1U << (Index3 - 3)) - 2); 1100 } 1101 1102 if (Index == Special) { 1103 while (Index < 6 && mPTLen[Index] == 0) { 1104 Index++; 1105 } 1106 1107 PutBits (2, (Index - 3) & 3); 1108 } 1109 } 1110 } 1111 1112 STATIC 1113 VOID 1114 WriteCLen ( 1115 VOID 1116 ) 1117 /*++ 1118 1119 Routine Description: 1120 1121 Outputs the code length array for Char&Length Set 1122 1123 Arguments: (VOID) 1124 1125 Returns: (VOID) 1126 1127 --*/ 1128 { 1129 INT32 Index; 1130 INT32 Index3; 1131 INT32 Number; 1132 INT32 Count; 1133 1134 Number = NC; 1135 while (Number > 0 && mCLen[Number - 1] == 0) { 1136 Number--; 1137 } 1138 1139 PutBits (CBIT, Number); 1140 Index = 0; 1141 while (Index < Number) { 1142 Index3 = mCLen[Index++]; 1143 if (Index3 == 0) { 1144 Count = 1; 1145 while (Index < Number && mCLen[Index] == 0) { 1146 Index++; 1147 Count++; 1148 } 1149 1150 if (Count <= 2) { 1151 for (Index3 = 0; Index3 < Count; Index3++) { 1152 PutBits (mPTLen[0], mPTCode[0]); 1153 } 1154 } else if (Count <= 18) { 1155 PutBits (mPTLen[1], mPTCode[1]); 1156 PutBits (4, Count - 3); 1157 } else if (Count == 19) { 1158 PutBits (mPTLen[0], mPTCode[0]); 1159 PutBits (mPTLen[1], mPTCode[1]); 1160 PutBits (4, 15); 1161 } else { 1162 PutBits (mPTLen[2], mPTCode[2]); 1163 PutBits (CBIT, Count - 20); 1164 } 1165 } else { 1166 PutBits (mPTLen[Index3 + 2], mPTCode[Index3 + 2]); 1167 } 1168 } 1169 } 1170 1171 STATIC 1172 VOID 1173 EncodeC ( 1174 IN INT32 Value 1175 ) 1176 { 1177 PutBits (mCLen[Value], mCCode[Value]); 1178 } 1179 1180 STATIC 1181 VOID 1182 EncodeP ( 1183 IN UINT32 Value 1184 ) 1185 { 1186 UINT32 Index; 1187 UINT32 NodeQ; 1188 1189 Index = 0; 1190 NodeQ = Value; 1191 while (NodeQ) { 1192 NodeQ >>= 1; 1193 Index++; 1194 } 1195 1196 PutBits (mPTLen[Index], mPTCode[Index]); 1197 if (Index > 1) { 1198 PutBits (Index - 1, Value & (0xFFFFFFFFU >> (32 - Index + 1))); 1199 } 1200 } 1201 1202 STATIC 1203 VOID 1204 SendBlock ( 1205 VOID 1206 ) 1207 /*++ 1208 1209 Routine Description: 1210 1211 Huffman code the block and output it. 1212 1213 Arguments: 1214 (VOID) 1215 1216 Returns: 1217 (VOID) 1218 1219 --*/ 1220 { 1221 UINT32 Index; 1222 UINT32 Index2; 1223 UINT32 Index3; 1224 UINT32 Flags; 1225 UINT32 Root; 1226 UINT32 Pos; 1227 UINT32 Size; 1228 Flags = 0; 1229 1230 Root = MakeTree (NC, mCFreq, mCLen, mCCode); 1231 Size = mCFreq[Root]; 1232 PutBits (16, Size); 1233 if (Root >= NC) { 1234 CountTFreq (); 1235 Root = MakeTree (NT, mTFreq, mPTLen, mPTCode); 1236 if (Root >= NT) { 1237 WritePTLen (NT, TBIT, 3); 1238 } else { 1239 PutBits (TBIT, 0); 1240 PutBits (TBIT, Root); 1241 } 1242 1243 WriteCLen (); 1244 } else { 1245 PutBits (TBIT, 0); 1246 PutBits (TBIT, 0); 1247 PutBits (CBIT, 0); 1248 PutBits (CBIT, Root); 1249 } 1250 1251 Root = MakeTree (NP, mPFreq, mPTLen, mPTCode); 1252 if (Root >= NP) { 1253 WritePTLen (NP, PBIT, -1); 1254 } else { 1255 PutBits (PBIT, 0); 1256 PutBits (PBIT, Root); 1257 } 1258 1259 Pos = 0; 1260 for (Index = 0; Index < Size; Index++) { 1261 if (Index % UINT8_BIT == 0) { 1262 Flags = mBuf[Pos++]; 1263 } else { 1264 Flags <<= 1; 1265 } 1266 1267 if (Flags & (1U << (UINT8_BIT - 1))) { 1268 EncodeC (mBuf[Pos++] + (1U << UINT8_BIT)); 1269 Index3 = mBuf[Pos++]; 1270 for (Index2 = 0; Index2 < 3; Index2++) { 1271 Index3 <<= UINT8_BIT; 1272 Index3 += mBuf[Pos++]; 1273 } 1274 1275 EncodeP (Index3); 1276 } else { 1277 EncodeC (mBuf[Pos++]); 1278 } 1279 } 1280 1281 for (Index = 0; Index < NC; Index++) { 1282 mCFreq[Index] = 0; 1283 } 1284 1285 for (Index = 0; Index < NP; Index++) { 1286 mPFreq[Index] = 0; 1287 } 1288 } 1289 1290 STATIC 1291 VOID 1292 Output ( 1293 IN UINT32 CharC, 1294 IN UINT32 Pos 1295 ) 1296 /*++ 1297 1298 Routine Description: 1299 1300 Outputs an Original Character or a Pointer 1301 1302 Arguments: 1303 1304 CharC - The original character or the 'String Length' element of a Pointer 1305 Pos - The 'Position' field of a Pointer 1306 1307 Returns: (VOID) 1308 1309 --*/ 1310 { 1311 STATIC UINT32 CPos; 1312 1313 if ((mOutputMask >>= 1) == 0) { 1314 mOutputMask = 1U << (UINT8_BIT - 1); 1315 // 1316 // Check the buffer overflow per outputing UINT8_BIT symbols 1317 // which is an Original Character or a Pointer. The biggest 1318 // symbol is a Pointer which occupies 5 bytes. 1319 // 1320 if (mOutputPos >= mBufSiz - 5 * UINT8_BIT) { 1321 SendBlock (); 1322 mOutputPos = 0; 1323 } 1324 1325 CPos = mOutputPos++; 1326 mBuf[CPos] = 0; 1327 } 1328 1329 mBuf[mOutputPos++] = (UINT8) CharC; 1330 mCFreq[CharC]++; 1331 if (CharC >= (1U << UINT8_BIT)) { 1332 mBuf[CPos] |= mOutputMask; 1333 mBuf[mOutputPos++] = (UINT8) (Pos >> 24); 1334 mBuf[mOutputPos++] = (UINT8) (Pos >> 16); 1335 mBuf[mOutputPos++] = (UINT8) (Pos >> (UINT8_BIT)); 1336 mBuf[mOutputPos++] = (UINT8) Pos; 1337 CharC = 0; 1338 while (Pos) { 1339 Pos >>= 1; 1340 CharC++; 1341 } 1342 1343 mPFreq[CharC]++; 1344 } 1345 } 1346 1347 STATIC 1348 VOID 1349 HufEncodeStart ( 1350 VOID 1351 ) 1352 { 1353 INT32 Index; 1354 1355 for (Index = 0; Index < NC; Index++) { 1356 mCFreq[Index] = 0; 1357 } 1358 1359 for (Index = 0; Index < NP; Index++) { 1360 mPFreq[Index] = 0; 1361 } 1362 1363 mOutputPos = mOutputMask = 0; 1364 InitPutBits (); 1365 return ; 1366 } 1367 1368 STATIC 1369 VOID 1370 HufEncodeEnd ( 1371 VOID 1372 ) 1373 { 1374 SendBlock (); 1375 1376 // 1377 // Flush remaining bits 1378 // 1379 PutBits (UINT8_BIT - 1, 0); 1380 1381 return ; 1382 } 1383 1384 STATIC 1385 VOID 1386 MakeCrcTable ( 1387 VOID 1388 ) 1389 { 1390 UINT32 Index; 1391 UINT32 Index2; 1392 UINT32 Temp; 1393 1394 for (Index = 0; Index <= UINT8_MAX; Index++) { 1395 Temp = Index; 1396 for (Index2 = 0; Index2 < UINT8_BIT; Index2++) { 1397 if (Temp & 1) { 1398 Temp = (Temp >> 1) ^ CRCPOLY; 1399 } else { 1400 Temp >>= 1; 1401 } 1402 } 1403 1404 mCrcTable[Index] = (UINT16) Temp; 1405 } 1406 } 1407 1408 STATIC 1409 VOID 1410 PutBits ( 1411 IN INT32 Number, 1412 IN UINT32 Value 1413 ) 1414 /*++ 1415 1416 Routine Description: 1417 1418 Outputs rightmost n bits of x 1419 1420 Arguments: 1421 1422 Number - the rightmost n bits of the data is used 1423 x - the data 1424 1425 Returns: (VOID) 1426 1427 --*/ 1428 { 1429 UINT8 Temp; 1430 1431 while (Number >= mBitCount) { 1432 // 1433 // Number -= mBitCount should never equal to 32 1434 // 1435 Temp = (UINT8) (mSubBitBuf | (Value >> (Number -= mBitCount))); 1436 if (mDst < mDstUpperLimit) { 1437 *mDst++ = Temp; 1438 } 1439 1440 mCompSize++; 1441 mSubBitBuf = 0; 1442 mBitCount = UINT8_BIT; 1443 } 1444 1445 mSubBitBuf |= Value << (mBitCount -= Number); 1446 } 1447 1448 STATIC 1449 INT32 1450 FreadCrc ( 1451 OUT UINT8 *Pointer, 1452 IN INT32 Number 1453 ) 1454 /*++ 1455 1456 Routine Description: 1457 1458 Read in source data 1459 1460 Arguments: 1461 1462 Pointer - the buffer to hold the data 1463 Number - number of bytes to read 1464 1465 Returns: 1466 1467 number of bytes actually read 1468 1469 --*/ 1470 { 1471 INT32 Index; 1472 1473 for (Index = 0; mSrc < mSrcUpperLimit && Index < Number; Index++) { 1474 *Pointer++ = *mSrc++; 1475 } 1476 1477 Number = Index; 1478 1479 Pointer -= Number; 1480 mOrigSize += Number; 1481 Index--; 1482 while (Index >= 0) { 1483 UPDATE_CRC (*Pointer++); 1484 Index--; 1485 } 1486 1487 return Number; 1488 } 1489 1490 STATIC 1491 VOID 1492 InitPutBits ( 1493 VOID 1494 ) 1495 { 1496 mBitCount = UINT8_BIT; 1497 mSubBitBuf = 0; 1498 } 1499 1500 STATIC 1501 VOID 1502 CountLen ( 1503 IN INT32 Index 1504 ) 1505 /*++ 1506 1507 Routine Description: 1508 1509 Count the number of each code length for a Huffman tree. 1510 1511 Arguments: 1512 1513 Index - the top node 1514 1515 Returns: (VOID) 1516 1517 --*/ 1518 { 1519 STATIC INT32 Depth = 0; 1520 1521 if (Index < mN) { 1522 mLenCnt[(Depth < 16) ? Depth : 16]++; 1523 } else { 1524 Depth++; 1525 CountLen (mLeft[Index]); 1526 CountLen (mRight[Index]); 1527 Depth--; 1528 } 1529 } 1530 1531 STATIC 1532 VOID 1533 MakeLen ( 1534 IN INT32 Root 1535 ) 1536 /*++ 1537 1538 Routine Description: 1539 1540 Create code length array for a Huffman tree 1541 1542 Arguments: 1543 1544 Root - the root of the tree 1545 1546 Returns: 1547 1548 VOID 1549 1550 --*/ 1551 { 1552 INT32 Index; 1553 INT32 Index3; 1554 UINT32 Cum; 1555 1556 for (Index = 0; Index <= 16; Index++) { 1557 mLenCnt[Index] = 0; 1558 } 1559 1560 CountLen (Root); 1561 1562 // 1563 // Adjust the length count array so that 1564 // no code will be generated longer than its designated length 1565 // 1566 Cum = 0; 1567 for (Index = 16; Index > 0; Index--) { 1568 Cum += mLenCnt[Index] << (16 - Index); 1569 } 1570 1571 while (Cum != (1U << 16)) { 1572 mLenCnt[16]--; 1573 for (Index = 15; Index > 0; Index--) { 1574 if (mLenCnt[Index] != 0) { 1575 mLenCnt[Index]--; 1576 mLenCnt[Index + 1] += 2; 1577 break; 1578 } 1579 } 1580 1581 Cum--; 1582 } 1583 1584 for (Index = 16; Index > 0; Index--) { 1585 Index3 = mLenCnt[Index]; 1586 Index3--; 1587 while (Index3 >= 0) { 1588 mLen[*mSortPtr++] = (UINT8) Index; 1589 Index3--; 1590 } 1591 } 1592 } 1593 1594 STATIC 1595 VOID 1596 DownHeap ( 1597 IN INT32 Index 1598 ) 1599 { 1600 INT32 Index2; 1601 INT32 Index3; 1602 1603 // 1604 // priority queue: send Index-th entry down heap 1605 // 1606 Index3 = mHeap[Index]; 1607 Index2 = 2 * Index; 1608 while (Index2 <= mHeapSize) { 1609 if (Index2 < mHeapSize && mFreq[mHeap[Index2]] > mFreq[mHeap[Index2 + 1]]) { 1610 Index2++; 1611 } 1612 1613 if (mFreq[Index3] <= mFreq[mHeap[Index2]]) { 1614 break; 1615 } 1616 1617 mHeap[Index] = mHeap[Index2]; 1618 Index = Index2; 1619 Index2 = 2 * Index; 1620 } 1621 1622 mHeap[Index] = (INT16) Index3; 1623 } 1624 1625 STATIC 1626 VOID 1627 MakeCode ( 1628 IN INT32 Number, 1629 IN UINT8 Len[ ], 1630 OUT UINT16 Code[] 1631 ) 1632 /*++ 1633 1634 Routine Description: 1635 1636 Assign code to each symbol based on the code length array 1637 1638 Arguments: 1639 1640 Number - number of symbols 1641 Len - the code length array 1642 Code - stores codes for each symbol 1643 1644 Returns: (VOID) 1645 1646 --*/ 1647 { 1648 INT32 Index; 1649 UINT16 Start[18]; 1650 1651 Start[1] = 0; 1652 for (Index = 1; Index <= 16; Index++) { 1653 Start[Index + 1] = (UINT16) ((Start[Index] + mLenCnt[Index]) << 1); 1654 } 1655 1656 for (Index = 0; Index < Number; Index++) { 1657 Code[Index] = Start[Len[Index]]++; 1658 } 1659 } 1660 1661 STATIC 1662 INT32 1663 MakeTree ( 1664 IN INT32 NParm, 1665 IN UINT16 FreqParm[], 1666 OUT UINT8 LenParm[ ], 1667 OUT UINT16 CodeParm[] 1668 ) 1669 /*++ 1670 1671 Routine Description: 1672 1673 Generates Huffman codes given a frequency distribution of symbols 1674 1675 Arguments: 1676 1677 NParm - number of symbols 1678 FreqParm - frequency of each symbol 1679 LenParm - code length for each symbol 1680 CodeParm - code for each symbol 1681 1682 Returns: 1683 1684 Root of the Huffman tree. 1685 1686 --*/ 1687 { 1688 INT32 Index; 1689 INT32 Index2; 1690 INT32 Index3; 1691 INT32 Avail; 1692 1693 // 1694 // make tree, calculate len[], return root 1695 // 1696 mN = NParm; 1697 mFreq = FreqParm; 1698 mLen = LenParm; 1699 Avail = mN; 1700 mHeapSize = 0; 1701 mHeap[1] = 0; 1702 for (Index = 0; Index < mN; Index++) { 1703 mLen[Index] = 0; 1704 if (mFreq[Index]) { 1705 mHeapSize++; 1706 mHeap[mHeapSize] = (INT16) Index; 1707 } 1708 } 1709 1710 if (mHeapSize < 2) { 1711 CodeParm[mHeap[1]] = 0; 1712 return mHeap[1]; 1713 } 1714 1715 for (Index = mHeapSize / 2; Index >= 1; Index--) { 1716 // 1717 // make priority queue 1718 // 1719 DownHeap (Index); 1720 } 1721 1722 mSortPtr = CodeParm; 1723 do { 1724 Index = mHeap[1]; 1725 if (Index < mN) { 1726 *mSortPtr++ = (UINT16) Index; 1727 } 1728 1729 mHeap[1] = mHeap[mHeapSize--]; 1730 DownHeap (1); 1731 Index2 = mHeap[1]; 1732 if (Index2 < mN) { 1733 *mSortPtr++ = (UINT16) Index2; 1734 } 1735 1736 Index3 = Avail++; 1737 mFreq[Index3] = (UINT16) (mFreq[Index] + mFreq[Index2]); 1738 mHeap[1] = (INT16) Index3; 1739 DownHeap (1); 1740 mLeft[Index3] = (UINT16) Index; 1741 mRight[Index3] = (UINT16) Index2; 1742 } while (mHeapSize > 1); 1743 1744 mSortPtr = CodeParm; 1745 MakeLen (Index3); 1746 MakeCode (NParm, LenParm, CodeParm); 1747 1748 // 1749 // return root 1750 // 1751 return Index3; 1752 } 1753