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