1 /** @file 2 UEFI and Tiano Custom Decompress Library 3 It will do Tiano or UEFI decompress with different verison parameter. 4 5 Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR> 6 This program and the accompanying materials 7 are licensed and made available under the terms and conditions of the BSD License 8 which accompanies this distribution. The full text of the license may be found at 9 http://opensource.org/licenses/bsd-license.php 10 11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13 14 **/ 15 16 #include "BaseUefiTianoCustomDecompressLibInternals.h" 17 18 /** 19 Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source. 20 21 @param Sd The global scratch data 22 @param NumOfBits The number of bits to shift and read. 23 **/ 24 VOID 25 FillBuf ( 26 IN SCRATCH_DATA *Sd, 27 IN UINT16 NumOfBits 28 ) 29 { 30 // 31 // Left shift NumOfBits of bits in advance 32 // 33 Sd->mBitBuf = (UINT32) (Sd->mBitBuf << NumOfBits); 34 35 // 36 // Copy data needed in bytes into mSbuBitBuf 37 // 38 while (NumOfBits > Sd->mBitCount) { 39 40 Sd->mBitBuf |= (UINT32) (Sd->mSubBitBuf << (NumOfBits = (UINT16) (NumOfBits - Sd->mBitCount))); 41 42 if (Sd->mCompSize > 0) { 43 // 44 // Get 1 byte into SubBitBuf 45 // 46 Sd->mCompSize--; 47 Sd->mSubBitBuf = 0; 48 Sd->mSubBitBuf = Sd->mSrcBase[Sd->mInBuf++]; 49 Sd->mBitCount = 8; 50 51 } else { 52 // 53 // No more bits from the source, just pad zero bit. 54 // 55 Sd->mSubBitBuf = 0; 56 Sd->mBitCount = 8; 57 58 } 59 } 60 61 // 62 // Calculate additional bit count read to update mBitCount 63 // 64 Sd->mBitCount = (UINT16) (Sd->mBitCount - NumOfBits); 65 66 // 67 // Copy NumOfBits of bits from mSubBitBuf into mBitBuf 68 // 69 Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount; 70 } 71 72 /** 73 Get NumOfBits of bits out from mBitBuf 74 75 Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent 76 NumOfBits of bits from source. Returns NumOfBits of bits that are 77 popped out. 78 79 @param Sd The global scratch data. 80 @param NumOfBits The number of bits to pop and read. 81 82 @return The bits that are popped out. 83 84 **/ 85 UINT32 86 GetBits ( 87 IN SCRATCH_DATA *Sd, 88 IN UINT16 NumOfBits 89 ) 90 { 91 UINT32 OutBits; 92 93 // 94 // Pop NumOfBits of Bits from Left 95 // 96 OutBits = (UINT32) (Sd->mBitBuf >> (BITBUFSIZ - NumOfBits)); 97 98 // 99 // Fill up mBitBuf from source 100 // 101 FillBuf (Sd, NumOfBits); 102 103 return OutBits; 104 } 105 106 /** 107 Creates Huffman Code mapping table according to code length array. 108 109 Creates Huffman Code mapping table for Extra Set, Char&Len Set 110 and Position Set according to code length array. 111 If TableBits > 16, then ASSERT (). 112 113 @param Sd The global scratch data 114 @param NumOfChar Number of symbols in the symbol set 115 @param BitLen Code length array 116 @param TableBits The width of the mapping table 117 @param Table The table to be created. 118 119 @retval 0 OK. 120 @retval BAD_TABLE The table is corrupted. 121 122 **/ 123 UINT16 124 MakeTable ( 125 IN SCRATCH_DATA *Sd, 126 IN UINT16 NumOfChar, 127 IN UINT8 *BitLen, 128 IN UINT16 TableBits, 129 OUT UINT16 *Table 130 ) 131 { 132 UINT16 Count[17]; 133 UINT16 Weight[17]; 134 UINT16 Start[18]; 135 UINT16 *Pointer; 136 UINT16 Index3; 137 UINT16 Index; 138 UINT16 Len; 139 UINT16 Char; 140 UINT16 JuBits; 141 UINT16 Avail; 142 UINT16 NextCode; 143 UINT16 Mask; 144 UINT16 WordOfStart; 145 UINT16 WordOfCount; 146 147 // 148 // The maximum mapping table width supported by this internal 149 // working function is 16. 150 // 151 ASSERT (TableBits <= 16); 152 153 for (Index = 0; Index <= 16; Index++) { 154 Count[Index] = 0; 155 } 156 157 for (Index = 0; Index < NumOfChar; Index++) { 158 Count[BitLen[Index]]++; 159 } 160 161 Start[0] = 0; 162 Start[1] = 0; 163 164 for (Index = 1; Index <= 16; Index++) { 165 WordOfStart = Start[Index]; 166 WordOfCount = Count[Index]; 167 Start[Index + 1] = (UINT16) (WordOfStart + (WordOfCount << (16 - Index))); 168 } 169 170 if (Start[17] != 0) { 171 /*(1U << 16)*/ 172 return (UINT16) BAD_TABLE; 173 } 174 175 JuBits = (UINT16) (16 - TableBits); 176 177 Weight[0] = 0; 178 for (Index = 1; Index <= TableBits; Index++) { 179 Start[Index] >>= JuBits; 180 Weight[Index] = (UINT16) (1U << (TableBits - Index)); 181 } 182 183 while (Index <= 16) { 184 Weight[Index] = (UINT16) (1U << (16 - Index)); 185 Index++; 186 } 187 188 Index = (UINT16) (Start[TableBits + 1] >> JuBits); 189 190 if (Index != 0) { 191 Index3 = (UINT16) (1U << TableBits); 192 if (Index < Index3) { 193 SetMem16 (Table + Index, (Index3 - Index) * sizeof (*Table), 0); 194 } 195 } 196 197 Avail = NumOfChar; 198 Mask = (UINT16) (1U << (15 - TableBits)); 199 200 for (Char = 0; Char < NumOfChar; Char++) { 201 202 Len = BitLen[Char]; 203 if (Len == 0 || Len >= 17) { 204 continue; 205 } 206 207 NextCode = (UINT16) (Start[Len] + Weight[Len]); 208 209 if (Len <= TableBits) { 210 211 for (Index = Start[Len]; Index < NextCode; Index++) { 212 Table[Index] = Char; 213 } 214 215 } else { 216 217 Index3 = Start[Len]; 218 Pointer = &Table[Index3 >> JuBits]; 219 Index = (UINT16) (Len - TableBits); 220 221 while (Index != 0) { 222 if (*Pointer == 0 && Avail < (2 * NC - 1)) { 223 Sd->mRight[Avail] = Sd->mLeft[Avail] = 0; 224 *Pointer = Avail++; 225 } 226 227 if (*Pointer < (2 * NC - 1)) { 228 if ((Index3 & Mask) != 0) { 229 Pointer = &Sd->mRight[*Pointer]; 230 } else { 231 Pointer = &Sd->mLeft[*Pointer]; 232 } 233 } 234 235 Index3 <<= 1; 236 Index--; 237 } 238 239 *Pointer = Char; 240 241 } 242 243 Start[Len] = NextCode; 244 } 245 // 246 // Succeeds 247 // 248 return 0; 249 } 250 251 /** 252 Decodes a position value. 253 254 Get a position value according to Position Huffman Table. 255 256 @param Sd the global scratch data 257 258 @return The position value decoded. 259 **/ 260 UINT32 261 DecodeP ( 262 IN SCRATCH_DATA *Sd 263 ) 264 { 265 UINT16 Val; 266 UINT32 Mask; 267 UINT32 Pos; 268 269 Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)]; 270 271 if (Val >= MAXNP) { 272 Mask = 1U << (BITBUFSIZ - 1 - 8); 273 274 do { 275 276 if ((Sd->mBitBuf & Mask) != 0) { 277 Val = Sd->mRight[Val]; 278 } else { 279 Val = Sd->mLeft[Val]; 280 } 281 282 Mask >>= 1; 283 } while (Val >= MAXNP); 284 } 285 // 286 // Advance what we have read 287 // 288 FillBuf (Sd, Sd->mPTLen[Val]); 289 290 Pos = Val; 291 if (Val > 1) { 292 Pos = (UINT32) ((1U << (Val - 1)) + GetBits (Sd, (UINT16) (Val - 1))); 293 } 294 295 return Pos; 296 } 297 298 /** 299 Reads code lengths for the Extra Set or the Position Set. 300 301 Read in the Extra Set or Pointion Set Length Arrary, then 302 generate the Huffman code mapping for them. 303 304 @param Sd The global scratch data. 305 @param nn Number of symbols. 306 @param nbit Number of bits needed to represent nn. 307 @param Special The special symbol that needs to be taken care of. 308 309 @retval 0 OK. 310 @retval BAD_TABLE Table is corrupted. 311 312 **/ 313 UINT16 314 ReadPTLen ( 315 IN SCRATCH_DATA *Sd, 316 IN UINT16 nn, 317 IN UINT16 nbit, 318 IN UINT16 Special 319 ) 320 { 321 UINT16 Number; 322 UINT16 CharC; 323 UINT16 Index; 324 UINT32 Mask; 325 326 ASSERT (nn <= NPT); 327 // 328 // Read Extra Set Code Length Array size 329 // 330 Number = (UINT16) GetBits (Sd, nbit); 331 332 if (Number == 0) { 333 // 334 // This represents only Huffman code used 335 // 336 CharC = (UINT16) GetBits (Sd, nbit); 337 338 for (Index = 0; Index < 256; Index++) { 339 Sd->mPTTable[Index] = CharC; 340 } 341 342 SetMem (Sd->mPTLen, nn, 0); 343 344 return 0; 345 } 346 347 Index = 0; 348 349 while (Index < Number && Index < NPT) { 350 351 CharC = (UINT16) (Sd->mBitBuf >> (BITBUFSIZ - 3)); 352 353 // 354 // If a code length is less than 7, then it is encoded as a 3-bit 355 // value. Or it is encoded as a series of "1"s followed by a 356 // terminating "0". The number of "1"s = Code length - 4. 357 // 358 if (CharC == 7) { 359 Mask = 1U << (BITBUFSIZ - 1 - 3); 360 while (Mask & Sd->mBitBuf) { 361 Mask >>= 1; 362 CharC += 1; 363 } 364 } 365 366 FillBuf (Sd, (UINT16) ((CharC < 7) ? 3 : CharC - 3)); 367 368 Sd->mPTLen[Index++] = (UINT8) CharC; 369 370 // 371 // For Code&Len Set, 372 // After the third length of the code length concatenation, 373 // a 2-bit value is used to indicated the number of consecutive 374 // zero lengths after the third length. 375 // 376 if (Index == Special) { 377 CharC = (UINT16) GetBits (Sd, 2); 378 while ((INT16) (--CharC) >= 0 && Index < NPT) { 379 Sd->mPTLen[Index++] = 0; 380 } 381 } 382 } 383 384 while (Index < nn && Index < NPT) { 385 Sd->mPTLen[Index++] = 0; 386 } 387 388 return MakeTable (Sd, nn, Sd->mPTLen, 8, Sd->mPTTable); 389 } 390 391 /** 392 Reads code lengths for Char&Len Set. 393 394 Read in and decode the Char&Len Set Code Length Array, then 395 generate the Huffman Code mapping table for the Char&Len Set. 396 397 @param Sd the global scratch data 398 399 **/ 400 VOID 401 ReadCLen ( 402 SCRATCH_DATA *Sd 403 ) 404 { 405 UINT16 Number; 406 UINT16 CharC; 407 UINT16 Index; 408 UINT32 Mask; 409 410 Number = (UINT16) GetBits (Sd, CBIT); 411 412 if (Number == 0) { 413 // 414 // This represents only Huffman code used 415 // 416 CharC = (UINT16) GetBits (Sd, CBIT); 417 418 SetMem (Sd->mCLen, NC, 0); 419 420 for (Index = 0; Index < 4096; Index++) { 421 Sd->mCTable[Index] = CharC; 422 } 423 424 return ; 425 } 426 427 Index = 0; 428 while (Index < Number && Index < NC) { 429 CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)]; 430 if (CharC >= NT) { 431 Mask = 1U << (BITBUFSIZ - 1 - 8); 432 433 do { 434 435 if (Mask & Sd->mBitBuf) { 436 CharC = Sd->mRight[CharC]; 437 } else { 438 CharC = Sd->mLeft[CharC]; 439 } 440 441 Mask >>= 1; 442 443 } while (CharC >= NT); 444 } 445 // 446 // Advance what we have read 447 // 448 FillBuf (Sd, Sd->mPTLen[CharC]); 449 450 if (CharC <= 2) { 451 452 if (CharC == 0) { 453 CharC = 1; 454 } else if (CharC == 1) { 455 CharC = (UINT16) (GetBits (Sd, 4) + 3); 456 } else if (CharC == 2) { 457 CharC = (UINT16) (GetBits (Sd, CBIT) + 20); 458 } 459 460 while ((INT16) (--CharC) >= 0 && Index < NC) { 461 Sd->mCLen[Index++] = 0; 462 } 463 464 } else { 465 466 Sd->mCLen[Index++] = (UINT8) (CharC - 2); 467 468 } 469 } 470 471 SetMem (Sd->mCLen + Index, NC - Index, 0); 472 473 MakeTable (Sd, NC, Sd->mCLen, 12, Sd->mCTable); 474 475 return ; 476 } 477 478 /** 479 Decode a character/length value. 480 481 Read one value from mBitBuf, Get one code from mBitBuf. If it is at block boundary, generates 482 Huffman code mapping table for Extra Set, Code&Len Set and 483 Position Set. 484 485 @param Sd The global scratch data. 486 487 @return The value decoded. 488 489 **/ 490 UINT16 491 DecodeC ( 492 SCRATCH_DATA *Sd 493 ) 494 { 495 UINT16 Index2; 496 UINT32 Mask; 497 498 if (Sd->mBlockSize == 0) { 499 // 500 // Starting a new block 501 // Read BlockSize from block header 502 // 503 Sd->mBlockSize = (UINT16) GetBits (Sd, 16); 504 505 // 506 // Read in the Extra Set Code Length Arrary, 507 // Generate the Huffman code mapping table for Extra Set. 508 // 509 Sd->mBadTableFlag = ReadPTLen (Sd, NT, TBIT, 3); 510 if (Sd->mBadTableFlag != 0) { 511 return 0; 512 } 513 514 // 515 // Read in and decode the Char&Len Set Code Length Arrary, 516 // Generate the Huffman code mapping table for Char&Len Set. 517 // 518 ReadCLen (Sd); 519 520 // 521 // Read in the Position Set Code Length Arrary, 522 // Generate the Huffman code mapping table for the Position Set. 523 // 524 Sd->mBadTableFlag = ReadPTLen (Sd, MAXNP, Sd->mPBit, (UINT16) (-1)); 525 if (Sd->mBadTableFlag != 0) { 526 return 0; 527 } 528 } 529 530 // 531 // Get one code according to Code&Set Huffman Table 532 // 533 Sd->mBlockSize--; 534 Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)]; 535 536 if (Index2 >= NC) { 537 Mask = 1U << (BITBUFSIZ - 1 - 12); 538 539 do { 540 if ((Sd->mBitBuf & Mask) != 0) { 541 Index2 = Sd->mRight[Index2]; 542 } else { 543 Index2 = Sd->mLeft[Index2]; 544 } 545 546 Mask >>= 1; 547 } while (Index2 >= NC); 548 } 549 // 550 // Advance what we have read 551 // 552 FillBuf (Sd, Sd->mCLen[Index2]); 553 554 return Index2; 555 } 556 557 /** 558 Decode the source data and put the resulting data into the destination buffer. 559 560 @param Sd The global scratch data 561 **/ 562 VOID 563 Decode ( 564 SCRATCH_DATA *Sd 565 ) 566 { 567 UINT16 BytesRemain; 568 UINT32 DataIdx; 569 UINT16 CharC; 570 571 BytesRemain = (UINT16) (-1); 572 573 DataIdx = 0; 574 575 for (;;) { 576 // 577 // Get one code from mBitBuf 578 // 579 CharC = DecodeC (Sd); 580 if (Sd->mBadTableFlag != 0) { 581 goto Done; 582 } 583 584 if (CharC < 256) { 585 // 586 // Process an Original character 587 // 588 if (Sd->mOutBuf >= Sd->mOrigSize) { 589 goto Done; 590 } else { 591 // 592 // Write orignal character into mDstBase 593 // 594 Sd->mDstBase[Sd->mOutBuf++] = (UINT8) CharC; 595 } 596 597 } else { 598 // 599 // Process a Pointer 600 // 601 CharC = (UINT16) (CharC - (BIT8 - THRESHOLD)); 602 603 // 604 // Get string length 605 // 606 BytesRemain = CharC; 607 608 // 609 // Locate string position 610 // 611 DataIdx = Sd->mOutBuf - DecodeP (Sd) - 1; 612 613 // 614 // Write BytesRemain of bytes into mDstBase 615 // 616 BytesRemain--; 617 while ((INT16) (BytesRemain) >= 0) { 618 Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++]; 619 if (Sd->mOutBuf >= Sd->mOrigSize) { 620 goto Done ; 621 } 622 623 BytesRemain--; 624 } 625 } 626 } 627 628 Done: 629 return ; 630 } 631 632 /** 633 Given a compressed source buffer, this function retrieves the size of 634 the uncompressed buffer and the size of the scratch buffer required 635 to decompress the compressed source buffer. 636 637 Retrieves the size of the uncompressed buffer and the temporary scratch buffer 638 required to decompress the buffer specified by Source and SourceSize. 639 If the size of the uncompressed buffer or the size of the scratch buffer cannot 640 be determined from the compressed data specified by Source and SourceData, 641 then RETURN_INVALID_PARAMETER is returned. Otherwise, the size of the uncompressed 642 buffer is returned in DestinationSize, the size of the scratch buffer is returned 643 in ScratchSize, and RETURN_SUCCESS is returned. 644 This function does not have scratch buffer available to perform a thorough 645 checking of the validity of the source data. It just retrieves the "Original Size" 646 field from the beginning bytes of the source data and output it as DestinationSize. 647 And ScratchSize is specific to the decompression implementation. 648 649 If Source is NULL, then ASSERT(). 650 If DestinationSize is NULL, then ASSERT(). 651 If ScratchSize is NULL, then ASSERT(). 652 653 @param Source The source buffer containing the compressed data. 654 @param SourceSize The size, in bytes, of the source buffer. 655 @param DestinationSize A pointer to the size, in bytes, of the uncompressed buffer 656 that will be generated when the compressed buffer specified 657 by Source and SourceSize is decompressed.. 658 @param ScratchSize A pointer to the size, in bytes, of the scratch buffer that 659 is required to decompress the compressed buffer specified 660 by Source and SourceSize. 661 662 @retval RETURN_SUCCESS The size of the uncompressed data was returned 663 in DestinationSize and the size of the scratch 664 buffer was returned in ScratchSize. 665 @retval RETURN_INVALID_PARAMETER 666 The size of the uncompressed data or the size of 667 the scratch buffer cannot be determined from 668 the compressed data specified by Source 669 and SourceSize. 670 **/ 671 RETURN_STATUS 672 EFIAPI 673 UefiDecompressGetInfo ( 674 IN CONST VOID *Source, 675 IN UINT32 SourceSize, 676 OUT UINT32 *DestinationSize, 677 OUT UINT32 *ScratchSize 678 ) 679 { 680 UINT32 CompressedSize; 681 682 ASSERT (Source != NULL); 683 ASSERT (DestinationSize != NULL); 684 ASSERT (ScratchSize != NULL); 685 686 if (SourceSize < 8) { 687 return RETURN_INVALID_PARAMETER; 688 } 689 690 CompressedSize = ReadUnaligned32 ((UINT32 *)Source); 691 if (SourceSize < (CompressedSize + 8)) { 692 return RETURN_INVALID_PARAMETER; 693 } 694 695 *ScratchSize = sizeof (SCRATCH_DATA); 696 *DestinationSize = ReadUnaligned32 ((UINT32 *)Source + 1); 697 698 return RETURN_SUCCESS; 699 } 700 701 /** 702 Decompresses a compressed source buffer by EFI or Tiano algorithm. 703 704 Extracts decompressed data to its original form. 705 This function is designed so that the decompression algorithm can be implemented 706 without using any memory services. As a result, this function is not allowed to 707 call any memory allocation services in its implementation. It is the caller's 708 responsibility to allocate and free the Destination and Scratch buffers. 709 If the compressed source data specified by Source is successfully decompressed 710 into Destination, then RETURN_SUCCESS is returned. If the compressed source data 711 specified by Source is not in a valid compressed data format, 712 then RETURN_INVALID_PARAMETER is returned. 713 714 If Source is NULL, then ASSERT(). 715 If Destination is NULL, then ASSERT(). 716 If the required scratch buffer size > 0 and Scratch is NULL, then ASSERT(). 717 718 @param Source The source buffer containing the compressed data. 719 @param Destination The destination buffer to store the decompressed data 720 @param Scratch A temporary scratch buffer that is used to perform the decompression. 721 This is an optional parameter that may be NULL if the 722 required scratch buffer size is 0. 723 @param Version 1 for UEFI Decompress algoruthm, 2 for Tiano Decompess algorithm. 724 725 @retval RETURN_SUCCESS Decompression completed successfully, and 726 the uncompressed buffer is returned in Destination. 727 @retval RETURN_INVALID_PARAMETER 728 The source buffer specified by Source is corrupted 729 (not in a valid compressed format). 730 **/ 731 RETURN_STATUS 732 EFIAPI 733 UefiTianoDecompress ( 734 IN CONST VOID *Source, 735 IN OUT VOID *Destination, 736 IN OUT VOID *Scratch, 737 IN UINT32 Version 738 ) 739 { 740 UINT32 CompSize; 741 UINT32 OrigSize; 742 SCRATCH_DATA *Sd; 743 CONST UINT8 *Src; 744 UINT8 *Dst; 745 746 ASSERT (Source != NULL); 747 ASSERT (Destination != NULL); 748 ASSERT (Scratch != NULL); 749 750 Src = Source; 751 Dst = Destination; 752 753 Sd = (SCRATCH_DATA *) Scratch; 754 755 CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24); 756 OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24); 757 758 // 759 // If compressed file size is 0, return 760 // 761 if (OrigSize == 0) { 762 return RETURN_SUCCESS; 763 } 764 765 Src = Src + 8; 766 767 SetMem (Sd, sizeof (SCRATCH_DATA), 0); 768 769 // 770 // The length of the field 'Position Set Code Length Array Size' in Block Header. 771 // For UEFI 2.0 de/compression algorithm(Version 1), mPBit = 4 772 // For Tiano de/compression algorithm(Version 2), mPBit = 5 773 // 774 switch (Version) { 775 case 1 : 776 Sd->mPBit = 4; 777 break; 778 case 2 : 779 Sd->mPBit = 5; 780 break; 781 default: 782 ASSERT (FALSE); 783 } 784 Sd->mSrcBase = (UINT8 *)Src; 785 Sd->mDstBase = Dst; 786 // 787 // CompSize and OrigSize are calculated in bytes 788 // 789 Sd->mCompSize = CompSize; 790 Sd->mOrigSize = OrigSize; 791 792 // 793 // Fill the first BITBUFSIZ bits 794 // 795 FillBuf (Sd, BITBUFSIZ); 796 797 // 798 // Decompress it 799 // 800 Decode (Sd); 801 802 if (Sd->mBadTableFlag != 0) { 803 // 804 // Something wrong with the source 805 // 806 return RETURN_INVALID_PARAMETER; 807 } 808 809 return RETURN_SUCCESS; 810 } 811 812 /** 813 Decompresses a UEFI compressed source buffer. 814 815 Extracts decompressed data to its original form. 816 This function is designed so that the decompression algorithm can be implemented 817 without using any memory services. As a result, this function is not allowed to 818 call any memory allocation services in its implementation. It is the caller's 819 responsibility to allocate and free the Destination and Scratch buffers. 820 If the compressed source data specified by Source is successfully decompressed 821 into Destination, then RETURN_SUCCESS is returned. If the compressed source data 822 specified by Source is not in a valid compressed data format, 823 then RETURN_INVALID_PARAMETER is returned. 824 825 If Source is NULL, then ASSERT(). 826 If Destination is NULL, then ASSERT(). 827 If the required scratch buffer size > 0 and Scratch is NULL, then ASSERT(). 828 829 @param Source The source buffer containing the compressed data. 830 @param Destination The destination buffer to store the decompressed data 831 @param Scratch A temporary scratch buffer that is used to perform the decompression. 832 This is an optional parameter that may be NULL if the 833 required scratch buffer size is 0. 834 835 @retval RETURN_SUCCESS Decompression completed successfully, and 836 the uncompressed buffer is returned in Destination. 837 @retval RETURN_INVALID_PARAMETER 838 The source buffer specified by Source is corrupted 839 (not in a valid compressed format). 840 **/ 841 RETURN_STATUS 842 EFIAPI 843 UefiDecompress ( 844 IN CONST VOID *Source, 845 IN OUT VOID *Destination, 846 IN OUT VOID *Scratch OPTIONAL 847 ) 848 { 849 return UefiTianoDecompress (Source, Destination, Scratch, 1); 850 } 851 852 /** 853 Examines a GUIDed section and returns the size of the decoded buffer and the 854 size of an optional scratch buffer required to actually decode the data in a GUIDed section. 855 856 Examines a GUIDed section specified by InputSection. 857 If GUID for InputSection does not match the GUID that this handler supports, 858 then RETURN_UNSUPPORTED is returned. 859 If the required information can not be retrieved from InputSection, 860 then RETURN_INVALID_PARAMETER is returned. 861 If the GUID of InputSection does match the GUID that this handler supports, 862 then the size required to hold the decoded buffer is returned in OututBufferSize, 863 the size of an optional scratch buffer is returned in ScratchSize, and the Attributes field 864 from EFI_GUID_DEFINED_SECTION header of InputSection is returned in SectionAttribute. 865 866 If InputSection is NULL, then ASSERT(). 867 If OutputBufferSize is NULL, then ASSERT(). 868 If ScratchBufferSize is NULL, then ASSERT(). 869 If SectionAttribute is NULL, then ASSERT(). 870 871 872 @param[in] InputSection A pointer to a GUIDed section of an FFS formatted file. 873 @param[out] OutputBufferSize A pointer to the size, in bytes, of an output buffer required 874 if the buffer specified by InputSection were decoded. 875 @param[out] ScratchBufferSize A pointer to the size, in bytes, required as scratch space 876 if the buffer specified by InputSection were decoded. 877 @param[out] SectionAttribute A pointer to the attributes of the GUIDed section. See the Attributes 878 field of EFI_GUID_DEFINED_SECTION in the PI Specification. 879 880 @retval RETURN_SUCCESS The information about InputSection was returned. 881 @retval RETURN_UNSUPPORTED The section specified by InputSection does not match the GUID this handler supports. 882 @retval RETURN_INVALID_PARAMETER The information can not be retrieved from the section specified by InputSection. 883 884 **/ 885 RETURN_STATUS 886 EFIAPI 887 TianoDecompressGetInfo ( 888 IN CONST VOID *InputSection, 889 OUT UINT32 *OutputBufferSize, 890 OUT UINT32 *ScratchBufferSize, 891 OUT UINT16 *SectionAttribute 892 ) 893 894 { 895 ASSERT (SectionAttribute != NULL); 896 897 if (InputSection == NULL) { 898 return RETURN_INVALID_PARAMETER; 899 } 900 901 if (IS_SECTION2 (InputSection)) { 902 if (!CompareGuid ( 903 &gTianoCustomDecompressGuid, 904 &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid))) { 905 return RETURN_INVALID_PARAMETER; 906 } 907 // 908 // Get guid attribute of guid section. 909 // 910 *SectionAttribute = ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->Attributes; 911 912 // 913 // Call Tiano GetInfo to get the required size info. 914 // 915 return UefiDecompressGetInfo ( 916 (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset, 917 SECTION2_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset, 918 OutputBufferSize, 919 ScratchBufferSize 920 ); 921 } else { 922 if (!CompareGuid ( 923 &gTianoCustomDecompressGuid, 924 &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid))) { 925 return RETURN_INVALID_PARAMETER; 926 } 927 // 928 // Get guid attribute of guid section. 929 // 930 *SectionAttribute = ((EFI_GUID_DEFINED_SECTION *) InputSection)->Attributes; 931 932 // 933 // Call Tiano GetInfo to get the required size info. 934 // 935 return UefiDecompressGetInfo ( 936 (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset, 937 SECTION_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset, 938 OutputBufferSize, 939 ScratchBufferSize 940 ); 941 } 942 } 943 944 /** 945 Decompress a Tiano compressed GUIDed section into a caller allocated output buffer. 946 947 Decodes the GUIDed section specified by InputSection. 948 If GUID for InputSection does not match the GUID that this handler supports, then RETURN_UNSUPPORTED is returned. 949 If the data in InputSection can not be decoded, then RETURN_INVALID_PARAMETER is returned. 950 If the GUID of InputSection does match the GUID that this handler supports, then InputSection 951 is decoded into the buffer specified by OutputBuffer and the authentication status of this 952 decode operation is returned in AuthenticationStatus. If the decoded buffer is identical to the 953 data in InputSection, then OutputBuffer is set to point at the data in InputSection. Otherwise, 954 the decoded data will be placed in caller allocated buffer specified by OutputBuffer. 955 956 If InputSection is NULL, then ASSERT(). 957 If OutputBuffer is NULL, then ASSERT(). 958 If ScratchBuffer is NULL and this decode operation requires a scratch buffer, then ASSERT(). 959 If AuthenticationStatus is NULL, then ASSERT(). 960 961 962 @param[in] InputSection A pointer to a GUIDed section of an FFS formatted file. 963 @param[out] OutputBuffer A pointer to a buffer that contains the result of a decode operation. 964 @param[in] ScratchBuffer A caller allocated buffer that may be required by this function 965 as a scratch buffer to perform the decode operation. 966 @param[out] AuthenticationStatus 967 A pointer to the authentication status of the decoded output buffer. 968 See the definition of authentication status in the EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI 969 section of the PI Specification. EFI_AUTH_STATUS_PLATFORM_OVERRIDE must 970 never be set by this handler. 971 972 @retval RETURN_SUCCESS The buffer specified by InputSection was decoded. 973 @retval RETURN_UNSUPPORTED The section specified by InputSection does not match the GUID this handler supports. 974 @retval RETURN_INVALID_PARAMETER The section specified by InputSection can not be decoded. 975 976 **/ 977 RETURN_STATUS 978 EFIAPI 979 TianoDecompress ( 980 IN CONST VOID *InputSection, 981 OUT VOID **OutputBuffer, 982 IN VOID *ScratchBuffer, OPTIONAL 983 OUT UINT32 *AuthenticationStatus 984 ) 985 { 986 ASSERT (OutputBuffer != NULL); 987 ASSERT (InputSection != NULL); 988 989 if (IS_SECTION2 (InputSection)) { 990 if (!CompareGuid ( 991 &gTianoCustomDecompressGuid, 992 &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid))) { 993 return RETURN_INVALID_PARAMETER; 994 } 995 996 // 997 // Set Authentication to Zero. 998 // 999 *AuthenticationStatus = 0; 1000 1001 // 1002 // Call Tiano Decompress to get the raw data 1003 // 1004 return UefiTianoDecompress ( 1005 (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset, 1006 *OutputBuffer, 1007 ScratchBuffer, 1008 2 1009 ); 1010 } else { 1011 if (!CompareGuid ( 1012 &gTianoCustomDecompressGuid, 1013 &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid))) { 1014 return RETURN_INVALID_PARAMETER; 1015 } 1016 1017 // 1018 // Set Authentication to Zero. 1019 // 1020 *AuthenticationStatus = 0; 1021 1022 // 1023 // Call Tiano Decompress to get the raw data 1024 // 1025 return UefiTianoDecompress ( 1026 (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset, 1027 *OutputBuffer, 1028 ScratchBuffer, 1029 2 1030 ); 1031 } 1032 } 1033 1034 /** 1035 Registers TianoDecompress and TianoDecompressGetInfo handlers with TianoCustomerDecompressGuid 1036 1037 @retval RETURN_SUCCESS Register successfully. 1038 @retval RETURN_OUT_OF_RESOURCES No enough memory to store this handler. 1039 **/ 1040 RETURN_STATUS 1041 EFIAPI 1042 TianoDecompressLibConstructor ( 1043 ) 1044 { 1045 return ExtractGuidedSectionRegisterHandlers ( 1046 &gTianoCustomDecompressGuid, 1047 TianoDecompressGetInfo, 1048 TianoDecompress 1049 ); 1050 } 1051