2 UEFI and Custom Decompress Library
3 The function of UefiTianoDecompress() is interface for this module,
4 it will do tiano or uefi decompress with different verison parameter.
5 See EFI specification 1.1 Chapter 17 to get LZ77 compress/decompress.
7 Copyright (c) 2006, Intel Corporation
8 All rights reserved. This program and the accompanying materials
9 are licensed and made available under the terms and conditions of the BSD License
10 which accompanies this distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include "BaseUefiTianoCustomDecompressLibInternals.h"
21 Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source.
23 @param Sd The global scratch data
24 @param NumOfBits The number of bits to shift and read.
32 Sd
->mBitBuf
= (UINT32
) (Sd
->mBitBuf
<< NumOfBits
);
34 while (NumOfBits
> Sd
->mBitCount
) {
36 Sd
->mBitBuf
|= (UINT32
) (Sd
->mSubBitBuf
<< (NumOfBits
= (UINT16
) (NumOfBits
- Sd
->mBitCount
)));
38 if (Sd
->mCompSize
> 0) {
40 // Get 1 byte into SubBitBuf
44 Sd
->mSubBitBuf
= Sd
->mSrcBase
[Sd
->mInBuf
++];
49 // No more bits from the source, just pad zero bit.
57 Sd
->mBitCount
= (UINT16
) (Sd
->mBitCount
- NumOfBits
);
58 Sd
->mBitBuf
|= Sd
->mSubBitBuf
>> Sd
->mBitCount
;
62 Get NumOfBits of bits out from mBitBuf
64 Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent
65 NumOfBits of bits from source. Returns NumOfBits of bits that are
68 @param Sd The global scratch data.
69 @param NumOfBits The number of bits to pop and read.
71 @return The bits that are popped out.
82 OutBits
= (UINT32
) (Sd
->mBitBuf
>> (BITBUFSIZ
- NumOfBits
));
84 FillBuf (Sd
, NumOfBits
);
90 Creates Huffman Code mapping table according to code length array.
92 Creates Huffman Code mapping table for Extra Set, Char&Len Set
93 and Position Set according to code length array.
95 @param Sd The global scratch data
96 @param NumOfChar Number of symbols in the symbol set
97 @param BitLen Code length array
98 @param TableBits The width of the mapping table
99 @param Table The table
102 @retval BAD_TABLE The table is corrupted.
129 for (Index
= 0; Index
<= 16; Index
++) {
133 for (Index
= 0; Index
< NumOfChar
; Index
++) {
134 Count
[BitLen
[Index
]]++;
140 for (Index
= 1; Index
<= 16; Index
++) {
141 WordOfStart
= Start
[Index
];
142 WordOfCount
= Count
[Index
];
143 Start
[Index
+ 1] = (UINT16
) (WordOfStart
+ (WordOfCount
<< (16 - Index
)));
146 if (Start
[17] != 0) {
148 return (UINT16
) BAD_TABLE
;
151 JuBits
= (UINT16
) (16 - TableBits
);
154 for (Index
= 1; Index
<= TableBits
; Index
++) {
155 Start
[Index
] >>= JuBits
;
156 Weight
[Index
] = (UINT16
) (1U << (TableBits
- Index
));
159 while (Index
<= 16) {
160 Weight
[Index
] = (UINT16
) (1U << (16 - Index
));
164 Index
= (UINT16
) (Start
[TableBits
+ 1] >> JuBits
);
167 Index3
= (UINT16
) (1U << TableBits
);
168 if (Index
< Index3
) {
169 SetMem16 (Table
+ Index
, (Index3
- Index
) * sizeof (*Table
), 0);
174 Mask
= (UINT16
) (1U << (15 - TableBits
));
176 for (Char
= 0; Char
< NumOfChar
; Char
++) {
179 if (Len
== 0 || Len
>= 17) {
183 NextCode
= (UINT16
) (Start
[Len
] + Weight
[Len
]);
185 if (Len
<= TableBits
) {
187 for (Index
= Start
[Len
]; Index
< NextCode
; Index
++) {
194 Pointer
= &Table
[Index3
>> JuBits
];
195 Index
= (UINT16
) (Len
- TableBits
);
198 if (*Pointer
== 0 && Avail
< (2 * NC
- 1)) {
199 Sd
->mRight
[Avail
] = Sd
->mLeft
[Avail
] = 0;
203 if (*Pointer
< (2 * NC
- 1)) {
204 if ((Index3
& Mask
) != 0) {
205 Pointer
= &Sd
->mRight
[*Pointer
];
207 Pointer
= &Sd
->mLeft
[*Pointer
];
219 Start
[Len
] = NextCode
;
228 Decodes a position value.
230 @param Sd the global scratch data
232 @return The position value decoded.
243 Val
= Sd
->mPTTable
[Sd
->mBitBuf
>> (BITBUFSIZ
- 8)];
246 Mask
= 1U << (BITBUFSIZ
- 1 - 8);
250 if (Sd
->mBitBuf
& Mask
) {
251 Val
= Sd
->mRight
[Val
];
253 Val
= Sd
->mLeft
[Val
];
257 } while (Val
>= MAXNP
);
260 // Advance what we have read
262 FillBuf (Sd
, Sd
->mPTLen
[Val
]);
266 Pos
= (UINT32
) ((1U << (Val
- 1)) + GetBits (Sd
, (UINT16
) (Val
- 1)));
273 Reads code lengths for the Extra Set or the Position Set.
275 Read in the Extra Set or Pointion Set Length Arrary, then
276 generate the Huffman code mapping for them.
278 @param Sd The global scratch data.
279 @param nn Number of symbols.
280 @param nbit Number of bits needed to represent nn.
281 @param Special The special symbol that needs to be taken care of.
284 @retval BAD_TABLE Table is corrupted.
301 // Read Extra Set Code Length Array size
303 Number
= (UINT16
) GetBits (Sd
, nbit
);
307 // This represents only Huffman code used
309 CharC
= (UINT16
) GetBits (Sd
, nbit
);
311 for (Index
= 0; Index
< 256; Index
++) {
312 Sd
->mPTTable
[Index
] = CharC
;
315 SetMem (Sd
->mPTLen
, nn
, 0);
322 while (Index
< Number
&& Index
< NPT
) {
324 CharC
= (UINT16
) (Sd
->mBitBuf
>> (BITBUFSIZ
- 3));
327 // If a code length is less than 7, then it is encoded as a 3-bit
328 // value. Or it is encoded as a series of "1"s followed by a
329 // terminating "0". The number of "1"s = Code length - 4.
332 Mask
= 1U << (BITBUFSIZ
- 1 - 3);
333 while (Mask
& Sd
->mBitBuf
) {
339 FillBuf (Sd
, (UINT16
) ((CharC
< 7) ? 3 : CharC
- 3));
341 Sd
->mPTLen
[Index
++] = (UINT8
) CharC
;
345 // After the third length of the code length concatenation,
346 // a 2-bit value is used to indicated the number of consecutive
347 // zero lengths after the third length.
349 if (Index
== Special
) {
350 CharC
= (UINT16
) GetBits (Sd
, 2);
351 while ((INT16
) (--CharC
) >= 0 && Index
< NPT
) {
352 Sd
->mPTLen
[Index
++] = 0;
357 while (Index
< nn
&& Index
< NPT
) {
358 Sd
->mPTLen
[Index
++] = 0;
361 return MakeTable (Sd
, nn
, Sd
->mPTLen
, 8, Sd
->mPTTable
);
365 Reads code lengths for Char&Len Set.
367 Read in and decode the Char&Len Set Code Length Array, then
368 generate the Huffman Code mapping table for the Char&Len Set.
370 @param Sd the global scratch data
383 Number
= (UINT16
) GetBits (Sd
, CBIT
);
387 // This represents only Huffman code used
389 CharC
= (UINT16
) GetBits (Sd
, CBIT
);
391 SetMem (Sd
->mCLen
, NC
, 0);
393 for (Index
= 0; Index
< 4096; Index
++) {
394 Sd
->mCTable
[Index
] = CharC
;
401 while (Index
< Number
&& Index
< NC
) {
402 CharC
= Sd
->mPTTable
[Sd
->mBitBuf
>> (BITBUFSIZ
- 8)];
404 Mask
= 1U << (BITBUFSIZ
- 1 - 8);
408 if (Mask
& Sd
->mBitBuf
) {
409 CharC
= Sd
->mRight
[CharC
];
411 CharC
= Sd
->mLeft
[CharC
];
416 } while (CharC
>= NT
);
419 // Advance what we have read
421 FillBuf (Sd
, Sd
->mPTLen
[CharC
]);
427 } else if (CharC
== 1) {
428 CharC
= (UINT16
) (GetBits (Sd
, 4) + 3);
429 } else if (CharC
== 2) {
430 CharC
= (UINT16
) (GetBits (Sd
, CBIT
) + 20);
433 while ((INT16
) (--CharC
) >= 0 && Index
< NC
) {
434 Sd
->mCLen
[Index
++] = 0;
439 Sd
->mCLen
[Index
++] = (UINT8
) (CharC
- 2);
444 SetMem (Sd
->mCLen
+ Index
, NC
- Index
, 0);
446 MakeTable (Sd
, NC
, Sd
->mCLen
, 12, Sd
->mCTable
);
452 Decode a character/length value.
454 Read one value from mBitBuf, Get one code from mBitBuf. If it is at block boundary, generates
455 Huffman code mapping table for Extra Set, Code&Len Set and
458 @param Sd The global scratch data.
460 @return The value decoded.
471 if (Sd
->mBlockSize
== 0) {
473 // Starting a new block
475 Sd
->mBlockSize
= (UINT16
) GetBits (Sd
, 16);
476 Sd
->mBadTableFlag
= ReadPTLen (Sd
, NT
, TBIT
, 3);
477 if (Sd
->mBadTableFlag
!= 0) {
483 Sd
->mBadTableFlag
= ReadPTLen (Sd
, MAXNP
, Sd
->mPBit
, (UINT16
) (-1));
484 if (Sd
->mBadTableFlag
!= 0) {
490 Index2
= Sd
->mCTable
[Sd
->mBitBuf
>> (BITBUFSIZ
- 12)];
493 Mask
= 1U << (BITBUFSIZ
- 1 - 12);
496 if (Sd
->mBitBuf
& Mask
) {
497 Index2
= Sd
->mRight
[Index2
];
499 Index2
= Sd
->mLeft
[Index2
];
503 } while (Index2
>= NC
);
506 // Advance what we have read
508 FillBuf (Sd
, Sd
->mCLen
[Index2
]);
514 Decode the source data ad put the resulting data into the destination buffer.
516 @param Sd - The global scratch data
527 BytesRemain
= (UINT16
) (-1);
532 CharC
= DecodeC (Sd
);
533 if (Sd
->mBadTableFlag
!= 0) {
539 // Process an Original character
541 if (Sd
->mOutBuf
>= Sd
->mOrigSize
) {
544 Sd
->mDstBase
[Sd
->mOutBuf
++] = (UINT8
) CharC
;
551 CharC
= (UINT16
) (CharC
- (BIT8
- THRESHOLD
));
555 DataIdx
= Sd
->mOutBuf
- DecodeP (Sd
) - 1;
558 while ((INT16
) (BytesRemain
) >= 0) {
559 Sd
->mDstBase
[Sd
->mOutBuf
++] = Sd
->mDstBase
[DataIdx
++];
560 if (Sd
->mOutBuf
>= Sd
->mOrigSize
) {
574 The internal implementation of *_DECOMPRESS_PROTOCOL.GetInfo().
576 @param Source The source buffer containing the compressed data.
577 @param SourceSize The size of source buffer
578 @param DestinationSize The size of destination buffer.
579 @param ScratchSize The size of scratch buffer.
581 @retval RETURN_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved.
582 @retval RETURN_INVALID_PARAMETER - The source data is corrupted
586 UefiDecompressGetInfo (
587 IN CONST VOID
*Source
,
588 IN UINT32 SourceSize
,
589 OUT UINT32
*DestinationSize
,
590 OUT UINT32
*ScratchSize
593 UINT32 CompressedSize
;
595 ASSERT (Source
!= NULL
);
596 ASSERT (DestinationSize
!= NULL
);
597 ASSERT (ScratchSize
!= NULL
);
599 if (SourceSize
< 8) {
600 return RETURN_INVALID_PARAMETER
;
603 CompressedSize
= ReadUnaligned32 ((UINT32
*)Source
);
604 if (SourceSize
< (CompressedSize
+ 8)) {
605 return RETURN_INVALID_PARAMETER
;
608 *ScratchSize
= sizeof (SCRATCH_DATA
);
609 *DestinationSize
= ReadUnaligned32 ((UINT32
*)Source
+ 1);
611 return RETURN_SUCCESS
;
615 The internal implementation of *_DECOMPRESS_PROTOCOL.Decompress().
617 @param Source The source buffer containing the compressed data.
618 @param Destination The destination buffer to store the decompressed data
619 @param Scratch The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.
620 @param Version 1 for UEFI Decompress algoruthm, 2 for Tiano Decompess algorithm
622 @retval RETURN_SUCCESS Decompression is successfull
623 @retval RETURN_INVALID_PARAMETER The source data is corrupted
627 UefiTianoDecompress (
628 IN CONST VOID
*Source
,
629 IN OUT VOID
*Destination
,
630 IN OUT VOID
*Scratch
,
640 ASSERT (Source
!= NULL
);
641 ASSERT (Destination
!= NULL
);
642 ASSERT (Scratch
!= NULL
);
647 Sd
= (SCRATCH_DATA
*) Scratch
;
649 CompSize
= Src
[0] + (Src
[1] << 8) + (Src
[2] << 16) + (Src
[3] << 24);
650 OrigSize
= Src
[4] + (Src
[5] << 8) + (Src
[6] << 16) + (Src
[7] << 24);
653 // If compressed file size is 0, return
656 return RETURN_SUCCESS
;
661 SetMem (Sd
, sizeof (SCRATCH_DATA
), 0);
664 // The length of the field 'Position Set Code Length Array Size' in Block Header.
665 // For UEFI 2.0 de/compression algorithm(Version 1), mPBit = 4
666 // For Tiano de/compression algorithm(Version 2), mPBit = 5
678 Sd
->mSrcBase
= (UINT8
*)Src
;
680 Sd
->mCompSize
= CompSize
;
681 Sd
->mOrigSize
= OrigSize
;
684 // Fill the first BITBUFSIZ bits
686 FillBuf (Sd
, BITBUFSIZ
);
693 if (Sd
->mBadTableFlag
!= 0) {
695 // Something wrong with the source
697 return RETURN_INVALID_PARAMETER
;
700 return RETURN_SUCCESS
;
704 The internal implementation of *_DECOMPRESS_PROTOCOL.Decompress().
706 @param Source - The source buffer containing the compressed data.
707 @param Destination - The destination buffer to store the decompressed data
708 @param Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.
710 @retval RETURN_SUCCESS - Decompression is successfull
711 @retval RETURN_INVALID_PARAMETER - The source data is corrupted
716 IN CONST VOID
*Source
,
717 IN OUT VOID
*Destination
,
721 return UefiTianoDecompress (Source
, Destination
, Scratch
, 1);
725 The internal implementation of Tiano decompress GetInfo.
727 @param InputSection Buffer containing the input GUIDed section to be processed.
728 @param OutputBufferSize The size of OutputBuffer.
729 @param ScratchBufferSize The size of ScratchBuffer.
730 @param SectionAttribute The attribute of the input guided section.
732 @retval RETURN_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved.
733 @retval RETURN_INVALID_PARAMETER - The source data is corrupted
734 The GUID in InputSection does not match this instance guid.
738 TianoDecompressGetInfo (
739 IN CONST VOID
*InputSection
,
740 OUT UINT32
*OutputBufferSize
,
741 OUT UINT32
*ScratchBufferSize
,
742 OUT UINT16
*SectionAttribute
746 ASSERT (SectionAttribute
!= NULL
);
748 if (InputSection
== NULL
) {
749 return RETURN_INVALID_PARAMETER
;
753 &gTianoCustomDecompressGuid
,
754 &(((EFI_GUID_DEFINED_SECTION
*) InputSection
)->SectionDefinitionGuid
))) {
755 return RETURN_INVALID_PARAMETER
;
758 // Get guid attribute of guid section.
760 *SectionAttribute
= ((EFI_GUID_DEFINED_SECTION
*) InputSection
)->Attributes
;
763 // Call Tiano GetInfo to get the required size info.
765 return UefiDecompressGetInfo (
766 (UINT8
*) InputSection
+ ((EFI_GUID_DEFINED_SECTION
*) InputSection
)->DataOffset
,
767 (*(UINT32
*) (((EFI_COMMON_SECTION_HEADER
*) InputSection
)->Size
) & 0x00ffffff) - ((EFI_GUID_DEFINED_SECTION
*) InputSection
)->DataOffset
,
774 The implementation of Tiano Decompress().
776 @param InputSection Buffer containing the input GUIDed section to be processed.
777 @param OutputBuffer OutputBuffer to point to the start of the section's contents.
778 if guided data is not prcessed. Otherwise,
779 OutputBuffer to contain the output data, which is allocated by the caller.
780 @param ScratchBuffer A pointer to a caller-allocated buffer for function internal use.
781 @param AuthenticationStatus A pointer to a caller-allocated UINT32 that indicates the
782 authentication status of the output buffer.
784 @retval RETURN_SUCCESS Decompression is successfull
785 @retval RETURN_INVALID_PARAMETER The source data is corrupted, or
786 The GUID in InputSection does not match this instance guid.
792 IN CONST VOID
*InputSection
,
793 OUT VOID
**OutputBuffer
,
794 IN VOID
*ScratchBuffer
, OPTIONAL
795 OUT UINT32
*AuthenticationStatus
798 ASSERT (OutputBuffer
!= NULL
);
800 if (InputSection
== NULL
) {
801 return RETURN_INVALID_PARAMETER
;
805 &gTianoCustomDecompressGuid
,
806 &(((EFI_GUID_DEFINED_SECTION
*) InputSection
)->SectionDefinitionGuid
))) {
807 return RETURN_INVALID_PARAMETER
;
811 // Set Authentication to Zero.
813 *AuthenticationStatus
= 0;
816 // Call Tiano Decompress to get the raw data
818 return UefiTianoDecompress (
819 (UINT8
*) InputSection
+ ((EFI_GUID_DEFINED_SECTION
*) InputSection
)->DataOffset
,
827 Register TianoDecompress handler.
829 @retval RETURN_SUCCESS Register successfully.
830 @retval RETURN_OUT_OF_RESOURCES No enough memory to store this handler.
834 TianoDecompressLibConstructor (
837 return ExtractGuidedSectionRegisterHandlers (
838 &gTianoCustomDecompressGuid
,
839 TianoDecompressGetInfo
,