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