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