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