1 /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 2 * Use of this source code is governed by a BSD-style license that can be 3 * found in the LICENSE file. 4 */ 5 6 /*++ 7 8 Copyright (c) 2004 - 2006, Intel Corporation 9 All rights reserved. This program and the accompanying materials 10 are licensed and made available under the terms and conditions of the BSD License 11 which accompanies this distribution. The full text of the license may be found at 12 http://opensource.org/licenses/bsd-license.php 13 14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 15 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 16 17 Module Name: 18 19 Decompress.c 20 21 Abstract: 22 23 Decompressor. Algorithm Ported from OPSD code (Decomp.asm) 24 25 --*/ 26 27 #include <errno.h> 28 #include <stdint.h> 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <sys/types.h> 33 #include <sys/stat.h> 34 #include <unistd.h> 35 36 #include "eficompress.h" 37 38 39 // 40 // Decompression algorithm begins here 41 // 42 #define BITBUFSIZ 32 43 #define MAXMATCH 256 44 #define THRESHOLD 3 45 #define CODE_BIT 16 46 #define BAD_TABLE - 1 47 48 // 49 // C: Char&Len Set; P: Position Set; T: exTra Set 50 // 51 #define NC (0xff + MAXMATCH + 2 - THRESHOLD) 52 #define CBIT 9 53 #define MAXPBIT 5 54 #define TBIT 5 55 #define MAXNP ((1U << MAXPBIT) - 1) 56 #define NT (CODE_BIT + 3) 57 #if NT > MAXNP 58 #define NPT NT 59 #else 60 #define NPT MAXNP 61 #endif 62 63 typedef struct { 64 UINT8 *mSrcBase; // Starting address of compressed data 65 UINT8 *mDstBase; // Starting address of decompressed data 66 UINT32 mOutBuf; 67 UINT32 mInBuf; 68 69 UINT16 mBitCount; 70 UINT32 mBitBuf; 71 UINT32 mSubBitBuf; 72 UINT16 mBlockSize; 73 UINT32 mCompSize; 74 UINT32 mOrigSize; 75 76 UINT16 mBadTableFlag; 77 78 UINT16 mLeft[2 * NC - 1]; 79 UINT16 mRight[2 * NC - 1]; 80 UINT8 mCLen[NC]; 81 UINT8 mPTLen[NPT]; 82 UINT16 mCTable[4096]; 83 UINT16 mPTTable[256]; 84 85 // 86 // The length of the field 'Position Set Code Length Array Size' in Block Header. 87 // For EFI 1.1 de/compression algorithm, mPBit = 4 88 // For Tiano de/compression algorithm, mPBit = 5 89 // 90 UINT8 mPBit; 91 } SCRATCH_DATA; 92 93 STATIC 94 VOID 95 FillBuf ( 96 IN SCRATCH_DATA *Sd, 97 IN UINT16 NumOfBits 98 ) 99 /*++ 100 101 Routine Description: 102 103 Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source. 104 105 Arguments: 106 107 Sd - The global scratch data 108 NumOfBits - The number of bits to shift and read. 109 110 Returns: (VOID) 111 112 --*/ 113 { 114 Sd->mBitBuf = (UINT32) (Sd->mBitBuf << NumOfBits); 115 116 while (NumOfBits > Sd->mBitCount) { 117 118 Sd->mBitBuf |= (UINT32) (Sd->mSubBitBuf << (NumOfBits = (UINT16) (NumOfBits - Sd->mBitCount))); 119 120 if (Sd->mCompSize > 0) { 121 // 122 // Get 1 byte into SubBitBuf 123 // 124 Sd->mCompSize--; 125 Sd->mSubBitBuf = 0; 126 Sd->mSubBitBuf = Sd->mSrcBase[Sd->mInBuf++]; 127 Sd->mBitCount = 8; 128 129 } else { 130 // 131 // No more bits from the source, just pad zero bit. 132 // 133 Sd->mSubBitBuf = 0; 134 Sd->mBitCount = 8; 135 136 } 137 } 138 139 Sd->mBitCount = (UINT16) (Sd->mBitCount - NumOfBits); 140 Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount; 141 } 142 143 STATIC 144 UINT32 145 GetBits ( 146 IN SCRATCH_DATA *Sd, 147 IN UINT16 NumOfBits 148 ) 149 /*++ 150 151 Routine Description: 152 153 Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent 154 NumOfBits of bits from source. Returns NumOfBits of bits that are 155 popped out. 156 157 Arguments: 158 159 Sd - The global scratch data. 160 NumOfBits - The number of bits to pop and read. 161 162 Returns: 163 164 The bits that are popped out. 165 166 --*/ 167 { 168 UINT32 OutBits; 169 170 OutBits = (UINT32) (Sd->mBitBuf >> (BITBUFSIZ - NumOfBits)); 171 172 FillBuf (Sd, NumOfBits); 173 174 return OutBits; 175 } 176 177 STATIC 178 UINT16 179 MakeTable ( 180 IN SCRATCH_DATA *Sd, 181 IN UINT16 NumOfChar, 182 IN UINT8 *BitLen, 183 IN UINT16 TableBits, 184 OUT UINT16 *Table 185 ) 186 /*++ 187 188 Routine Description: 189 190 Creates Huffman Code mapping table according to code length array. 191 192 Arguments: 193 194 Sd - The global scratch data 195 NumOfChar - Number of symbols in the symbol set 196 BitLen - Code length array 197 TableBits - The width of the mapping table 198 Table - The table 199 200 Returns: 201 202 0 - OK. 203 BAD_TABLE - The table is corrupted. 204 205 --*/ 206 { 207 UINT16 Count[17]; 208 UINT16 Weight[17]; 209 UINT16 Start[18]; 210 UINT16 *Pointer; 211 UINT16 Index3; 212 UINT16 Index; 213 UINT16 Len; 214 UINT16 Char; 215 UINT16 JuBits; 216 UINT16 Avail; 217 UINT16 NextCode; 218 UINT16 Mask; 219 220 for (Index = 1; Index <= 16; Index++) { 221 Count[Index] = 0; 222 } 223 224 for (Index = 0; Index < NumOfChar; Index++) { 225 Count[BitLen[Index]]++; 226 } 227 228 Start[1] = 0; 229 230 for (Index = 1; Index <= 16; Index++) { 231 Start[Index + 1] = (UINT16) (Start[Index] + (Count[Index] << (16 - Index))); 232 } 233 234 if (Start[17] != 0) { 235 /*(1U << 16)*/ 236 return (UINT16) BAD_TABLE; 237 } 238 239 JuBits = (UINT16) (16 - TableBits); 240 241 for (Index = 1; Index <= TableBits; Index++) { 242 Start[Index] >>= JuBits; 243 Weight[Index] = (UINT16) (1U << (TableBits - Index)); 244 } 245 246 while (Index <= 16) { 247 Weight[Index] = (UINT16) (1U << (16 - Index)); 248 Index++; 249 } 250 251 Index = (UINT16) (Start[TableBits + 1] >> JuBits); 252 253 if (Index != 0) { 254 Index3 = (UINT16) (1U << TableBits); 255 while (Index != Index3) { 256 Table[Index++] = 0; 257 } 258 } 259 260 Avail = NumOfChar; 261 Mask = (UINT16) (1U << (15 - TableBits)); 262 263 for (Char = 0; Char < NumOfChar; Char++) { 264 265 Len = BitLen[Char]; 266 if (Len == 0) { 267 continue; 268 } 269 270 NextCode = (UINT16) (Start[Len] + Weight[Len]); 271 272 if (Len <= TableBits) { 273 274 for (Index = Start[Len]; Index < NextCode; Index++) { 275 Table[Index] = Char; 276 } 277 278 } else { 279 280 Index3 = Start[Len]; 281 Pointer = &Table[Index3 >> JuBits]; 282 Index = (UINT16) (Len - TableBits); 283 284 while (Index != 0) { 285 if (*Pointer == 0) { 286 Sd->mRight[Avail] = Sd->mLeft[Avail] = 0; 287 *Pointer = Avail++; 288 } 289 290 if (Index3 & Mask) { 291 Pointer = &Sd->mRight[*Pointer]; 292 } else { 293 Pointer = &Sd->mLeft[*Pointer]; 294 } 295 296 Index3 <<= 1; 297 Index--; 298 } 299 300 *Pointer = Char; 301 302 } 303 304 Start[Len] = NextCode; 305 } 306 // 307 // Succeeds 308 // 309 return 0; 310 } 311 312 STATIC 313 UINT32 314 DecodeP ( 315 IN SCRATCH_DATA *Sd 316 ) 317 /*++ 318 319 Routine Description: 320 321 Decodes a position value. 322 323 Arguments: 324 325 Sd - the global scratch data 326 327 Returns: 328 329 The position value decoded. 330 331 --*/ 332 { 333 UINT16 Val; 334 UINT32 Mask; 335 UINT32 Pos; 336 337 Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)]; 338 339 if (Val >= MAXNP) { 340 Mask = 1U << (BITBUFSIZ - 1 - 8); 341 342 do { 343 344 if (Sd->mBitBuf & Mask) { 345 Val = Sd->mRight[Val]; 346 } else { 347 Val = Sd->mLeft[Val]; 348 } 349 350 Mask >>= 1; 351 } while (Val >= MAXNP); 352 } 353 // 354 // Advance what we have read 355 // 356 FillBuf (Sd, Sd->mPTLen[Val]); 357 358 Pos = Val; 359 if (Val > 1) { 360 Pos = (UINT32) ((1U << (Val - 1)) + GetBits (Sd, (UINT16) (Val - 1))); 361 } 362 363 return Pos; 364 } 365 366 STATIC 367 UINT16 368 ReadPTLen ( 369 IN SCRATCH_DATA *Sd, 370 IN UINT16 nn, 371 IN UINT16 nbit, 372 IN UINT16 Special 373 ) 374 /*++ 375 376 Routine Description: 377 378 Reads code lengths for the Extra Set or the Position Set 379 380 Arguments: 381 382 Sd - The global scratch data 383 nn - Number of symbols 384 nbit - Number of bits needed to represent nn 385 Special - The special symbol that needs to be taken care of 386 387 Returns: 388 389 0 - OK. 390 BAD_TABLE - Table is corrupted. 391 392 --*/ 393 { 394 UINT16 Number; 395 UINT16 CharC; 396 UINT16 Index; 397 UINT32 Mask; 398 399 Number = (UINT16) GetBits (Sd, nbit); 400 401 if (Number == 0) { 402 CharC = (UINT16) GetBits (Sd, nbit); 403 404 for (Index = 0; Index < 256; Index++) { 405 Sd->mPTTable[Index] = CharC; 406 } 407 408 for (Index = 0; Index < nn; Index++) { 409 Sd->mPTLen[Index] = 0; 410 } 411 412 return 0; 413 } 414 415 Index = 0; 416 417 while (Index < Number) { 418 419 CharC = (UINT16) (Sd->mBitBuf >> (BITBUFSIZ - 3)); 420 421 if (CharC == 7) { 422 Mask = 1U << (BITBUFSIZ - 1 - 3); 423 while (Mask & Sd->mBitBuf) { 424 Mask >>= 1; 425 CharC += 1; 426 } 427 } 428 429 FillBuf (Sd, (UINT16) ((CharC < 7) ? 3 : CharC - 3)); 430 431 Sd->mPTLen[Index++] = (UINT8) CharC; 432 433 if (Index == Special) { 434 CharC = (UINT16) GetBits (Sd, 2); 435 while ((INT16) (--CharC) >= 0) { 436 Sd->mPTLen[Index++] = 0; 437 } 438 } 439 } 440 441 while (Index < nn) { 442 Sd->mPTLen[Index++] = 0; 443 } 444 445 return MakeTable (Sd, nn, Sd->mPTLen, 8, Sd->mPTTable); 446 } 447 448 STATIC 449 VOID 450 ReadCLen ( 451 SCRATCH_DATA *Sd 452 ) 453 /*++ 454 455 Routine Description: 456 457 Reads code lengths for Char&Len Set. 458 459 Arguments: 460 461 Sd - the global scratch data 462 463 Returns: (VOID) 464 465 --*/ 466 { 467 UINT16 Number; 468 UINT16 CharC; 469 UINT16 Index; 470 UINT32 Mask; 471 472 Number = (UINT16) GetBits (Sd, CBIT); 473 474 if (Number == 0) { 475 CharC = (UINT16) GetBits (Sd, CBIT); 476 477 for (Index = 0; Index < NC; Index++) { 478 Sd->mCLen[Index] = 0; 479 } 480 481 for (Index = 0; Index < 4096; Index++) { 482 Sd->mCTable[Index] = CharC; 483 } 484 485 return ; 486 } 487 488 Index = 0; 489 while (Index < Number) { 490 491 CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)]; 492 if (CharC >= NT) { 493 Mask = 1U << (BITBUFSIZ - 1 - 8); 494 495 do { 496 497 if (Mask & Sd->mBitBuf) { 498 CharC = Sd->mRight[CharC]; 499 } else { 500 CharC = Sd->mLeft[CharC]; 501 } 502 503 Mask >>= 1; 504 505 } while (CharC >= NT); 506 } 507 // 508 // Advance what we have read 509 // 510 FillBuf (Sd, Sd->mPTLen[CharC]); 511 512 if (CharC <= 2) { 513 514 if (CharC == 0) { 515 CharC = 1; 516 } else if (CharC == 1) { 517 CharC = (UINT16) (GetBits (Sd, 4) + 3); 518 } else if (CharC == 2) { 519 CharC = (UINT16) (GetBits (Sd, CBIT) + 20); 520 } 521 522 while ((INT16) (--CharC) >= 0) { 523 Sd->mCLen[Index++] = 0; 524 } 525 526 } else { 527 528 Sd->mCLen[Index++] = (UINT8) (CharC - 2); 529 530 } 531 } 532 533 while (Index < NC) { 534 Sd->mCLen[Index++] = 0; 535 } 536 537 MakeTable (Sd, NC, Sd->mCLen, 12, Sd->mCTable); 538 539 return ; 540 } 541 542 STATIC 543 UINT16 544 DecodeC ( 545 SCRATCH_DATA *Sd 546 ) 547 /*++ 548 549 Routine Description: 550 551 Decode a character/length value. 552 553 Arguments: 554 555 Sd - The global scratch data. 556 557 Returns: 558 559 The value decoded. 560 561 --*/ 562 { 563 UINT16 Index2; 564 UINT32 Mask; 565 566 if (Sd->mBlockSize == 0) { 567 // 568 // Starting a new block 569 // 570 Sd->mBlockSize = (UINT16) GetBits (Sd, 16); 571 Sd->mBadTableFlag = ReadPTLen (Sd, NT, TBIT, 3); 572 if (Sd->mBadTableFlag != 0) { 573 return 0; 574 } 575 576 ReadCLen (Sd); 577 578 Sd->mBadTableFlag = ReadPTLen (Sd, MAXNP, Sd->mPBit, (UINT16) (-1)); 579 if (Sd->mBadTableFlag != 0) { 580 return 0; 581 } 582 } 583 584 Sd->mBlockSize--; 585 Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)]; 586 587 if (Index2 >= NC) { 588 Mask = 1U << (BITBUFSIZ - 1 - 12); 589 590 do { 591 if (Sd->mBitBuf & Mask) { 592 Index2 = Sd->mRight[Index2]; 593 } else { 594 Index2 = Sd->mLeft[Index2]; 595 } 596 597 Mask >>= 1; 598 } while (Index2 >= NC); 599 } 600 // 601 // Advance what we have read 602 // 603 FillBuf (Sd, Sd->mCLen[Index2]); 604 605 return Index2; 606 } 607 608 STATIC 609 VOID 610 Decode ( 611 SCRATCH_DATA *Sd 612 ) 613 /*++ 614 615 Routine Description: 616 617 Decode the source data and put the resulting data into the destination buffer. 618 619 Arguments: 620 621 Sd - The global scratch data 622 623 Returns: (VOID) 624 625 --*/ 626 { 627 UINT16 BytesRemain; 628 UINT32 DataIdx; 629 UINT16 CharC; 630 631 BytesRemain = (UINT16) (-1); 632 633 DataIdx = 0; 634 635 for (;;) { 636 CharC = DecodeC (Sd); 637 if (Sd->mBadTableFlag != 0) { 638 return ; 639 } 640 641 if (CharC < 256) { 642 // 643 // Process an Original character 644 // 645 if (Sd->mOutBuf >= Sd->mOrigSize) { 646 return ; 647 } else { 648 Sd->mDstBase[Sd->mOutBuf++] = (UINT8) CharC; 649 } 650 651 } else { 652 // 653 // Process a Pointer 654 // 655 CharC = (UINT16) (CharC - (UINT8_MAX + 1 - THRESHOLD)); 656 657 BytesRemain = CharC; 658 659 DataIdx = Sd->mOutBuf - DecodeP (Sd) - 1; 660 661 BytesRemain--; 662 while ((INT16) (BytesRemain) >= 0) { 663 Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++]; 664 if (Sd->mOutBuf >= Sd->mOrigSize) { 665 return ; 666 } 667 668 BytesRemain--; 669 } 670 } 671 } 672 673 return ; 674 } 675 676 EFI_STATUS 677 GetInfo ( 678 IN VOID *Source, 679 IN UINT32 SrcSize, 680 OUT UINT32 *DstSize, 681 OUT UINT32 *ScratchSize 682 ) 683 /*++ 684 685 Routine Description: 686 687 The internal implementation of *_DECOMPRESS_PROTOCOL.GetInfo(). 688 689 Arguments: 690 691 Source - The source buffer containing the compressed data. 692 SrcSize - The size of source buffer 693 DstSize - The size of destination buffer. 694 ScratchSize - The size of scratch buffer. 695 696 Returns: 697 698 EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved. 699 EFI_INVALID_PARAMETER - The source data is corrupted 700 701 --*/ 702 { 703 UINT8 *Src; 704 705 *ScratchSize = sizeof (SCRATCH_DATA); 706 707 Src = Source; 708 if (SrcSize < 8) { 709 return EFI_INVALID_PARAMETER; 710 } 711 712 *DstSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24); 713 return EFI_SUCCESS; 714 } 715 716 EFI_STATUS 717 Decompress ( 718 IN VOID *Source, 719 IN UINT32 SrcSize, 720 IN OUT VOID *Destination, 721 IN UINT32 DstSize, 722 IN OUT VOID *Scratch, 723 IN UINT32 ScratchSize, 724 IN UINT8 Version 725 ) 726 /*++ 727 728 Routine Description: 729 730 The internal implementation of *_DECOMPRESS_PROTOCOL.Decompress(). 731 732 Arguments: 733 734 Source - The source buffer containing the compressed data. 735 SrcSize - The size of source buffer 736 Destination - The destination buffer to store the decompressed data 737 DstSize - The size of destination buffer. 738 Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. 739 ScratchSize - The size of scratch buffer. 740 Version - The version of de/compression algorithm. 741 Version 1 for EFI 1.1 de/compression algorithm. 742 Version 2 for Tiano de/compression algorithm. 743 744 Returns: 745 746 EFI_SUCCESS - Decompression is successfull 747 EFI_INVALID_PARAMETER - The source data is corrupted 748 749 --*/ 750 { 751 UINT32 Index; 752 UINT32 CompSize; 753 UINT32 OrigSize; 754 EFI_STATUS Status; 755 SCRATCH_DATA *Sd; 756 UINT8 *Src; 757 UINT8 *Dst; 758 759 Status = EFI_SUCCESS; 760 Src = Source; 761 Dst = Destination; 762 763 if (ScratchSize < sizeof (SCRATCH_DATA)) { 764 return EFI_INVALID_PARAMETER; 765 } 766 767 Sd = (SCRATCH_DATA *) Scratch; 768 769 if (SrcSize < 8) { 770 return EFI_INVALID_PARAMETER; 771 } 772 773 CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24); 774 OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24); 775 776 // 777 // If compressed file size is 0, return 778 // 779 if (OrigSize == 0) { 780 return Status; 781 } 782 783 if (SrcSize < CompSize + 8) { 784 return EFI_INVALID_PARAMETER; 785 } 786 787 if (DstSize != OrigSize) { 788 return EFI_INVALID_PARAMETER; 789 } 790 791 Src = Src + 8; 792 793 for (Index = 0; Index < sizeof (SCRATCH_DATA); Index++) { 794 ((UINT8 *) Sd)[Index] = 0; 795 } 796 // 797 // The length of the field 'Position Set Code Length Array Size' in Block Header. 798 // For EFI 1.1 de/compression algorithm(Version 1), mPBit = 4 799 // For Tiano de/compression algorithm(Version 2), mPBit = 5 800 // 801 switch (Version) { 802 case 1: 803 Sd->mPBit = 4; 804 break; 805 806 case 2: 807 Sd->mPBit = 5; 808 break; 809 810 default: 811 // 812 // Currently, only have 2 versions 813 // 814 return EFI_INVALID_PARAMETER; 815 } 816 817 Sd->mSrcBase = Src; 818 Sd->mDstBase = Dst; 819 Sd->mCompSize = CompSize; 820 Sd->mOrigSize = OrigSize; 821 822 // 823 // Fill the first BITBUFSIZ bits 824 // 825 FillBuf (Sd, BITBUFSIZ); 826 827 // 828 // Decompress it 829 // 830 Decode (Sd); 831 832 if (Sd->mBadTableFlag != 0) { 833 // 834 // Something wrong with the source 835 // 836 Status = EFI_INVALID_PARAMETER; 837 } 838 839 return Status; 840 } 841 842 EFI_STATUS 843 EFIAPI 844 EfiGetInfo ( 845 IN VOID *Source, 846 IN UINT32 SrcSize, 847 OUT UINT32 *DstSize, 848 OUT UINT32 *ScratchSize 849 ) 850 /*++ 851 852 Routine Description: 853 854 The implementation is same as that of EFI_DECOMPRESS_PROTOCOL.GetInfo(). 855 856 Arguments: 857 858 This - The protocol instance pointer 859 Source - The source buffer containing the compressed data. 860 SrcSize - The size of source buffer 861 DstSize - The size of destination buffer. 862 ScratchSize - The size of scratch buffer. 863 864 Returns: 865 866 EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved. 867 EFI_INVALID_PARAMETER - The source data is corrupted 868 869 --*/ 870 { 871 return GetInfo ( 872 Source, 873 SrcSize, 874 DstSize, 875 ScratchSize 876 ); 877 } 878 879 EFI_STATUS 880 EFIAPI 881 EfiDecompress ( 882 IN VOID *Source, 883 IN UINT32 SrcSize, 884 IN OUT VOID *Destination, 885 IN UINT32 DstSize, 886 IN OUT VOID *Scratch, 887 IN UINT32 ScratchSize 888 ) 889 /*++ 890 891 Routine Description: 892 893 The implementation is same as that of EFI_DECOMPRESS_PROTOCOL.Decompress(). 894 895 Arguments: 896 897 This - The protocol instance pointer 898 Source - The source buffer containing the compressed data. 899 SrcSize - The size of source buffer 900 Destination - The destination buffer to store the decompressed data 901 DstSize - The size of destination buffer. 902 Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. 903 ScratchSize - The size of scratch buffer. 904 905 Returns: 906 907 EFI_SUCCESS - Decompression is successfull 908 EFI_INVALID_PARAMETER - The source data is corrupted 909 910 --*/ 911 { 912 // 913 // For EFI 1.1 de/compression algorithm, the version is 1. 914 // 915 return Decompress ( 916 Source, 917 SrcSize, 918 Destination, 919 DstSize, 920 Scratch, 921 ScratchSize, 922 1 923 ); 924 } 925 926 EFI_STATUS 927 EFIAPI 928 TianoGetInfo ( 929 IN VOID *Source, 930 IN UINT32 SrcSize, 931 OUT UINT32 *DstSize, 932 OUT UINT32 *ScratchSize 933 ) 934 /*++ 935 936 Routine Description: 937 938 The implementation is same as that of EFI_TIANO_DECOMPRESS_PROTOCOL.GetInfo(). 939 940 Arguments: 941 942 This - The protocol instance pointer 943 Source - The source buffer containing the compressed data. 944 SrcSize - The size of source buffer 945 DstSize - The size of destination buffer. 946 ScratchSize - The size of scratch buffer. 947 948 Returns: 949 950 EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved. 951 EFI_INVALID_PARAMETER - The source data is corrupted 952 953 --*/ 954 { 955 return GetInfo ( 956 Source, 957 SrcSize, 958 DstSize, 959 ScratchSize 960 ); 961 } 962 963 EFI_STATUS 964 EFIAPI 965 TianoDecompress ( 966 IN VOID *Source, 967 IN UINT32 SrcSize, 968 IN OUT VOID *Destination, 969 IN UINT32 DstSize, 970 IN OUT VOID *Scratch, 971 IN UINT32 ScratchSize 972 ) 973 /*++ 974 975 Routine Description: 976 977 The implementation is same as that of EFI_TIANO_DECOMPRESS_PROTOCOL.Decompress(). 978 979 Arguments: 980 981 This - The protocol instance pointer 982 Source - The source buffer containing the compressed data. 983 SrcSize - The size of source buffer 984 Destination - The destination buffer to store the decompressed data 985 DstSize - The size of destination buffer. 986 Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. 987 ScratchSize - The size of scratch buffer. 988 989 Returns: 990 991 EFI_SUCCESS - Decompression is successfull 992 EFI_INVALID_PARAMETER - The source data is corrupted 993 994 --*/ 995 { 996 // 997 // For Tiano de/compression algorithm, the version is 2. 998 // 999 return Decompress ( 1000 Source, 1001 SrcSize, 1002 Destination, 1003 DstSize, 1004 Scratch, 1005 ScratchSize, 1006 2 1007 ); 1008 } 1009 1010 1011 #ifndef FOR_LIBRARY 1012 int main(int argc, char *argv[]) 1013 { 1014 char *progname; 1015 int retval = 1; 1016 1017 progname = strrchr(argv[0], '/'); 1018 if (progname) 1019 progname++; 1020 else 1021 progname = argv[0]; 1022 1023 if (argc != 3) 1024 { 1025 fprintf(stderr, "\nUsage: %s INFILE OUTFILE\n\n", progname); 1026 exit(1); 1027 } 1028 1029 char *infile = argv[1]; 1030 char *outfile = argv[2]; 1031 1032 struct stat istat; 1033 if (0 != stat(infile, &istat)) { 1034 fprintf(stderr, "%s: can't stat %s: %s\n", 1035 progname, 1036 infile, 1037 strerror(errno)); 1038 exit(1); 1039 } 1040 uint32_t isize = (uint32_t)istat.st_size; 1041 1042 printf("%s is %d bytes\n", infile, isize); 1043 1044 FILE *ifp = fopen(infile, "rb"); 1045 if (!ifp) 1046 { 1047 fprintf(stderr, "%s: can't read %s: %s\n", 1048 progname, 1049 infile, 1050 strerror(errno)); 1051 exit(1); 1052 } 1053 1054 // read input file into buffer 1055 uint8_t *ibuf = malloc(isize); 1056 if (!ibuf) { 1057 fprintf(stderr, "%s: can't allocate %d bytes: %s\n", 1058 progname, 1059 isize, 1060 strerror(errno)); 1061 goto done1; 1062 } 1063 if (1 != fread(ibuf, isize, 1, ifp)) { 1064 fprintf(stderr, "%s: can't read %d bytes: %s\n", 1065 progname, 1066 isize, 1067 strerror(errno)); 1068 goto done2; 1069 } 1070 1071 1072 // Determine required parameters 1073 uint32_t ssize=0, osize=0; 1074 EFI_STATUS r = GetInfo(ibuf, isize, &osize, &ssize); 1075 if (r != EFI_SUCCESS) { 1076 fprintf(stderr, "%s: GetInfo failed with code %d\n", 1077 progname, 1078 r); 1079 goto done2; 1080 } 1081 printf("need %d bytes of scratch to produce %d bytes of data\n", 1082 ssize, osize); 1083 1084 uint8_t *sbuf = malloc(ssize); 1085 if (!sbuf) { 1086 fprintf(stderr, "%s: can't allocate %d bytes: %s\n", 1087 progname, 1088 ssize, 1089 strerror(errno)); 1090 goto done2; 1091 } 1092 1093 uint8_t *obuf = malloc(osize); 1094 if (!obuf) { 1095 fprintf(stderr, "%s: can't allocate %d bytes: %s\n", 1096 progname, 1097 osize, 1098 strerror(errno)); 1099 goto done3; 1100 } 1101 1102 // Try new version first 1103 r = TianoDecompress(ibuf, isize, obuf, osize, sbuf, ssize); 1104 if (r != EFI_SUCCESS) { 1105 fprintf(stderr, "%s: TianoDecompress failed with code %d\n", 1106 progname, 1107 r); 1108 1109 // Try old version 1110 r = EfiDecompress(ibuf, isize, obuf, osize, sbuf, ssize); 1111 if (r != EFI_SUCCESS) { 1112 fprintf(stderr, "%s: TianoDecompress failed with code %d\n", 1113 progname, 1114 r); 1115 goto done4; 1116 } 1117 } 1118 1119 printf("Uncompressed %d bytes to %d bytes\n", isize, osize); 1120 1121 // Write it out 1122 FILE *ofp = fopen(outfile, "wb"); 1123 if (!ofp) 1124 { 1125 fprintf(stderr, "%s: can't open %s for writing: %s\n", 1126 progname, 1127 outfile, 1128 strerror(errno)); 1129 goto done4; 1130 } 1131 1132 if (1 != fwrite(obuf, osize, 1, ofp)) { 1133 fprintf(stderr, "%s: can't write %d bytes: %s\n", 1134 progname, 1135 osize, 1136 strerror(errno)); 1137 goto done5; 1138 } 1139 1140 printf("wrote %d bytes to %s\n", osize, outfile); 1141 retval = 0; 1142 1143 done5: 1144 fclose(ofp); 1145 1146 done4: 1147 free(obuf); 1148 1149 done3: 1150 free(sbuf); 1151 1152 done2: 1153 free(ibuf); 1154 1155 done1: 1156 fclose(ifp); 1157 1158 return retval; 1159 } 1160 #endif // FOR_LIBRARY 1161