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
FillBuf(IN SCRATCH_DATA * Sd,IN UINT16 NumOfBits)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
GetBits(IN SCRATCH_DATA * Sd,IN UINT16 NumOfBits)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
MakeTable(IN SCRATCH_DATA * Sd,IN UINT16 NumOfChar,IN UINT8 * BitLen,IN UINT16 TableBits,OUT UINT16 * Table)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
DecodeP(IN SCRATCH_DATA * Sd)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
ReadPTLen(IN SCRATCH_DATA * Sd,IN UINT16 nn,IN UINT16 nbit,IN UINT16 Special)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
ReadCLen(SCRATCH_DATA * Sd)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
DecodeC(SCRATCH_DATA * Sd)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
Decode(SCRATCH_DATA * Sd)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
GetInfo(IN VOID * Source,IN UINT32 SrcSize,OUT UINT32 * DstSize,OUT UINT32 * ScratchSize)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
Decompress(IN VOID * Source,IN UINT32 SrcSize,IN OUT VOID * Destination,IN UINT32 DstSize,IN OUT VOID * Scratch,IN UINT32 ScratchSize,IN UINT8 Version)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
EfiGetInfo(IN VOID * Source,IN UINT32 SrcSize,OUT UINT32 * DstSize,OUT UINT32 * ScratchSize)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
EfiDecompress(IN VOID * Source,IN UINT32 SrcSize,IN OUT VOID * Destination,IN UINT32 DstSize,IN OUT VOID * Scratch,IN UINT32 ScratchSize)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
TianoGetInfo(IN VOID * Source,IN UINT32 SrcSize,OUT UINT32 * DstSize,OUT UINT32 * ScratchSize)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
TianoDecompress(IN VOID * Source,IN UINT32 SrcSize,IN OUT VOID * Destination,IN UINT32 DstSize,IN OUT VOID * Scratch,IN UINT32 ScratchSize)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
main(int argc,char * argv[])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