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"
19 #include <Guid/CustomDecompress.h>
22 Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source.
24 @param Sd The global scratch data
25 @param NumOfBits The number of bits to shift and read.
33 Sd
->mBitBuf
= (UINT32
) (Sd
->mBitBuf
<< NumOfBits
);
35 while (NumOfBits
> Sd
->mBitCount
) {
37 Sd
->mBitBuf
|= (UINT32
) (Sd
->mSubBitBuf
<< (NumOfBits
= (UINT16
) (NumOfBits
- Sd
->mBitCount
)));
39 if (Sd
->mCompSize
> 0) {
41 // Get 1 byte into SubBitBuf
45 Sd
->mSubBitBuf
= Sd
->mSrcBase
[Sd
->mInBuf
++];
50 // No more bits from the source, just pad zero bit.
58 Sd
->mBitCount
= (UINT16
) (Sd
->mBitCount
- NumOfBits
);
59 Sd
->mBitBuf
|= Sd
->mSubBitBuf
>> Sd
->mBitCount
;
63 Get NumOfBits of bits out from mBitBuf
65 Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent
66 NumOfBits of bits from source. Returns NumOfBits of bits that are
69 @param Sd The global scratch data.
70 @param NumOfBits The number of bits to pop and read.
72 @return The bits that are popped out.
83 OutBits
= (UINT32
) (Sd
->mBitBuf
>> (BITBUFSIZ
- NumOfBits
));
85 FillBuf (Sd
, NumOfBits
);
91 Creates Huffman Code mapping table according to code length array.
93 Creates Huffman Code mapping table for Extra Set, Char&Len Set
94 and Position Set according to code length array.
96 @param Sd The global scratch data
97 @param NumOfChar Number of symbols in the symbol set
98 @param BitLen Code length array
99 @param TableBits The width of the mapping table
100 @param Table The table
103 @retval BAD_TABLE The table is corrupted.
130 for (Index
= 0; Index
<= 16; Index
++) {
134 for (Index
= 0; Index
< NumOfChar
; Index
++) {
135 Count
[BitLen
[Index
]]++;
141 for (Index
= 1; Index
<= 16; Index
++) {
142 WordOfStart
= Start
[Index
];
143 WordOfCount
= Count
[Index
];
144 Start
[Index
+ 1] = (UINT16
) (WordOfStart
+ (WordOfCount
<< (16 - Index
)));
147 if (Start
[17] != 0) {
149 return (UINT16
) BAD_TABLE
;
152 JuBits
= (UINT16
) (16 - TableBits
);
155 for (Index
= 1; Index
<= TableBits
; Index
++) {
156 Start
[Index
] >>= JuBits
;
157 Weight
[Index
] = (UINT16
) (1U << (TableBits
- Index
));
160 while (Index
<= 16) {
161 Weight
[Index
] = (UINT16
) (1U << (16 - Index
));
165 Index
= (UINT16
) (Start
[TableBits
+ 1] >> JuBits
);
168 Index3
= (UINT16
) (1U << TableBits
);
169 if (Index
< Index3
) {
170 SetMem16 (Table
+ Index
, (Index3
- Index
) * sizeof (*Table
), 0);
175 Mask
= (UINT16
) (1U << (15 - TableBits
));
177 for (Char
= 0; Char
< NumOfChar
; Char
++) {
180 if (Len
== 0 || Len
>= 17) {
184 NextCode
= (UINT16
) (Start
[Len
] + Weight
[Len
]);
186 if (Len
<= TableBits
) {
188 for (Index
= Start
[Len
]; Index
< NextCode
; Index
++) {
195 Pointer
= &Table
[Index3
>> JuBits
];
196 Index
= (UINT16
) (Len
- TableBits
);
199 if (*Pointer
== 0 && Avail
< (2 * NC
- 1)) {
200 Sd
->mRight
[Avail
] = Sd
->mLeft
[Avail
] = 0;
204 if (*Pointer
< (2 * NC
- 1)) {
205 if ((Index3
& Mask
) != 0) {
206 Pointer
= &Sd
->mRight
[*Pointer
];
208 Pointer
= &Sd
->mLeft
[*Pointer
];
220 Start
[Len
] = NextCode
;
229 Decodes a position value.
231 @param Sd the global scratch data
233 @return The position value decoded.
244 Val
= Sd
->mPTTable
[Sd
->mBitBuf
>> (BITBUFSIZ
- 8)];
247 Mask
= 1U << (BITBUFSIZ
- 1 - 8);
251 if (Sd
->mBitBuf
& Mask
) {
252 Val
= Sd
->mRight
[Val
];
254 Val
= Sd
->mLeft
[Val
];
258 } while (Val
>= MAXNP
);
261 // Advance what we have read
263 FillBuf (Sd
, Sd
->mPTLen
[Val
]);
267 Pos
= (UINT32
) ((1U << (Val
- 1)) + GetBits (Sd
, (UINT16
) (Val
- 1)));
274 Reads code lengths for the Extra Set or the Position Set.
276 Read in the Extra Set or Pointion Set Length Arrary, then
277 generate the Huffman code mapping for them.
279 @param Sd The global scratch data.
280 @param nn Number of symbols.
281 @param nbit Number of bits needed to represent nn.
282 @param Special The special symbol that needs to be taken care of.
285 @retval BAD_TABLE Table is corrupted.
302 // Read Extra Set Code Length Array size
304 Number
= (UINT16
) GetBits (Sd
, nbit
);
308 // This represents only Huffman code used
310 CharC
= (UINT16
) GetBits (Sd
, nbit
);
312 for (Index
= 0; Index
< 256; Index
++) {
313 Sd
->mPTTable
[Index
] = CharC
;
316 SetMem (Sd
->mPTLen
, nn
, 0);
323 while (Index
< Number
&& Index
< NPT
) {
325 CharC
= (UINT16
) (Sd
->mBitBuf
>> (BITBUFSIZ
- 3));
328 // If a code length is less than 7, then it is encoded as a 3-bit
329 // value. Or it is encoded as a series of "1"s followed by a
330 // terminating "0". The number of "1"s = Code length - 4.
333 Mask
= 1U << (BITBUFSIZ
- 1 - 3);
334 while (Mask
& Sd
->mBitBuf
) {
340 FillBuf (Sd
, (UINT16
) ((CharC
< 7) ? 3 : CharC
- 3));
342 Sd
->mPTLen
[Index
++] = (UINT8
) CharC
;
346 // After the third length of the code length concatenation,
347 // a 2-bit value is used to indicated the number of consecutive
348 // zero lengths after the third length.
350 if (Index
== Special
) {
351 CharC
= (UINT16
) GetBits (Sd
, 2);
352 while ((INT16
) (--CharC
) >= 0 && Index
< NPT
) {
353 Sd
->mPTLen
[Index
++] = 0;
358 while (Index
< nn
&& Index
< NPT
) {
359 Sd
->mPTLen
[Index
++] = 0;
362 return MakeTable (Sd
, nn
, Sd
->mPTLen
, 8, Sd
->mPTTable
);
366 Reads code lengths for Char&Len Set.
368 Read in and decode the Char&Len Set Code Length Array, then
369 generate the Huffman Code mapping table for the Char&Len Set.
371 @param Sd the global scratch data
384 Number
= (UINT16
) GetBits (Sd
, CBIT
);
388 // This represents only Huffman code used
390 CharC
= (UINT16
) GetBits (Sd
, CBIT
);
392 SetMem (Sd
->mCLen
, NC
, 0);
394 for (Index
= 0; Index
< 4096; Index
++) {
395 Sd
->mCTable
[Index
] = CharC
;
402 while (Index
< Number
&& Index
< NC
) {
403 CharC
= Sd
->mPTTable
[Sd
->mBitBuf
>> (BITBUFSIZ
- 8)];
405 Mask
= 1U << (BITBUFSIZ
- 1 - 8);
409 if (Mask
& Sd
->mBitBuf
) {
410 CharC
= Sd
->mRight
[CharC
];
412 CharC
= Sd
->mLeft
[CharC
];
417 } while (CharC
>= NT
);
420 // Advance what we have read
422 FillBuf (Sd
, Sd
->mPTLen
[CharC
]);
428 } else if (CharC
== 1) {
429 CharC
= (UINT16
) (GetBits (Sd
, 4) + 3);
430 } else if (CharC
== 2) {
431 CharC
= (UINT16
) (GetBits (Sd
, CBIT
) + 20);
434 while ((INT16
) (--CharC
) >= 0 && Index
< NC
) {
435 Sd
->mCLen
[Index
++] = 0;
440 Sd
->mCLen
[Index
++] = (UINT8
) (CharC
- 2);
445 SetMem (Sd
->mCLen
+ Index
, NC
- Index
, 0);
447 MakeTable (Sd
, NC
, Sd
->mCLen
, 12, Sd
->mCTable
);
453 Decode a character/length value.
455 Read one value from mBitBuf, Get one code from mBitBuf. If it is at block boundary, generates
456 Huffman code mapping table for Extra Set, Code&Len Set and
459 @param Sd The global scratch data.
461 @return The value decoded.
472 if (Sd
->mBlockSize
== 0) {
474 // Starting a new block
476 Sd
->mBlockSize
= (UINT16
) GetBits (Sd
, 16);
477 Sd
->mBadTableFlag
= ReadPTLen (Sd
, NT
, TBIT
, 3);
478 if (Sd
->mBadTableFlag
!= 0) {
484 Sd
->mBadTableFlag
= ReadPTLen (Sd
, MAXNP
, Sd
->mPBit
, (UINT16
) (-1));
485 if (Sd
->mBadTableFlag
!= 0) {
491 Index2
= Sd
->mCTable
[Sd
->mBitBuf
>> (BITBUFSIZ
- 12)];
494 Mask
= 1U << (BITBUFSIZ
- 1 - 12);
497 if (Sd
->mBitBuf
& Mask
) {
498 Index2
= Sd
->mRight
[Index2
];
500 Index2
= Sd
->mLeft
[Index2
];
504 } while (Index2
>= NC
);
507 // Advance what we have read
509 FillBuf (Sd
, Sd
->mCLen
[Index2
]);
515 Decode the source data ad put the resulting data into the destination buffer.
517 @param Sd - The global scratch data
528 BytesRemain
= (UINT16
) (-1);
533 CharC
= DecodeC (Sd
);
534 if (Sd
->mBadTableFlag
!= 0) {
540 // Process an Original character
542 if (Sd
->mOutBuf
>= Sd
->mOrigSize
) {
545 Sd
->mDstBase
[Sd
->mOutBuf
++] = (UINT8
) CharC
;
552 CharC
= (UINT16
) (CharC
- (BIT8
- THRESHOLD
));
556 DataIdx
= Sd
->mOutBuf
- DecodeP (Sd
) - 1;
559 while ((INT16
) (BytesRemain
) >= 0) {
560 Sd
->mDstBase
[Sd
->mOutBuf
++] = Sd
->mDstBase
[DataIdx
++];
561 if (Sd
->mOutBuf
>= Sd
->mOrigSize
) {
575 The internal implementation of *_DECOMPRESS_PROTOCOL.GetInfo().
577 @param Source The source buffer containing the compressed data.
578 @param SourceSize The size of source buffer
579 @param DestinationSize The size of destination buffer.
580 @param ScratchSize The size of scratch buffer.
582 @retval RETURN_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved.
583 @retval RETURN_INVALID_PARAMETER - The source data is corrupted
587 UefiDecompressGetInfo (
588 IN CONST VOID
*Source
,
589 IN UINT32 SourceSize
,
590 OUT UINT32
*DestinationSize
,
591 OUT UINT32
*ScratchSize
594 UINT32 CompressedSize
;
596 ASSERT (Source
!= NULL
);
597 ASSERT (DestinationSize
!= NULL
);
598 ASSERT (ScratchSize
!= NULL
);
600 if (SourceSize
< 8) {
601 return RETURN_INVALID_PARAMETER
;
604 CompressedSize
= ReadUnaligned32 ((UINT32
*)Source
);
605 if (SourceSize
< (CompressedSize
+ 8)) {
606 return RETURN_INVALID_PARAMETER
;
609 *ScratchSize
= sizeof (SCRATCH_DATA
);
610 *DestinationSize
= ReadUnaligned32 ((UINT32
*)Source
+ 1);
612 return RETURN_SUCCESS
;
616 The internal implementation of *_DECOMPRESS_PROTOCOL.Decompress().
618 @param Source The source buffer containing the compressed data.
619 @param Destination The destination buffer to store the decompressed data
620 @param Scratch The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.
621 @param Version 1 for UEFI Decompress algoruthm, 2 for Tiano Decompess algorithm
623 @retval RETURN_SUCCESS Decompression is successfull
624 @retval RETURN_INVALID_PARAMETER The source data is corrupted
628 UefiTianoDecompress (
629 IN CONST VOID
*Source
,
630 IN OUT VOID
*Destination
,
631 IN OUT VOID
*Scratch
,
641 ASSERT (Source
!= NULL
);
642 ASSERT (Destination
!= NULL
);
643 ASSERT (Scratch
!= NULL
);
648 Sd
= (SCRATCH_DATA
*) Scratch
;
650 CompSize
= Src
[0] + (Src
[1] << 8) + (Src
[2] << 16) + (Src
[3] << 24);
651 OrigSize
= Src
[4] + (Src
[5] << 8) + (Src
[6] << 16) + (Src
[7] << 24);
654 // If compressed file size is 0, return
657 return RETURN_SUCCESS
;
662 SetMem (Sd
, sizeof (SCRATCH_DATA
), 0);
665 // The length of the field 'Position Set Code Length Array Size' in Block Header.
666 // For UEFI 2.0 de/compression algorithm(Version 1), mPBit = 4
667 // For Tiano de/compression algorithm(Version 2), mPBit = 5
679 Sd
->mSrcBase
= (UINT8
*)Src
;
681 Sd
->mCompSize
= CompSize
;
682 Sd
->mOrigSize
= OrigSize
;
685 // Fill the first BITBUFSIZ bits
687 FillBuf (Sd
, BITBUFSIZ
);
694 if (Sd
->mBadTableFlag
!= 0) {
696 // Something wrong with the source
698 return RETURN_INVALID_PARAMETER
;
701 return RETURN_SUCCESS
;
705 The internal implementation of *_DECOMPRESS_PROTOCOL.Decompress().
707 @param Source - The source buffer containing the compressed data.
708 @param Destination - The destination buffer to store the decompressed data
709 @param Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.
711 @retval RETURN_SUCCESS - Decompression is successfull
712 @retval RETURN_INVALID_PARAMETER - The source data is corrupted
717 IN CONST VOID
*Source
,
718 IN OUT VOID
*Destination
,
722 return UefiTianoDecompress (Source
, Destination
, Scratch
, 1);
726 The internal implementation of Tiano decompress GetInfo.
728 @param InputSection Buffer containing the input GUIDed section to be processed.
729 @param OutputBufferSize The size of OutputBuffer.
730 @param ScratchBufferSize The size of ScratchBuffer.
731 @param SectionAttribute The attribute of the input guided section.
733 @retval RETURN_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved.
734 @retval RETURN_INVALID_PARAMETER - The source data is corrupted
735 The GUID in InputSection does not match this instance guid.
739 TianoDecompressGetInfo (
740 IN CONST VOID
*InputSection
,
741 OUT UINT32
*OutputBufferSize
,
742 OUT UINT32
*ScratchBufferSize
,
743 OUT UINT16
*SectionAttribute
747 ASSERT (SectionAttribute
!= NULL
);
749 if (InputSection
== NULL
) {
750 return RETURN_INVALID_PARAMETER
;
754 &gTianoCustomDecompressGuid
,
755 &(((EFI_GUID_DEFINED_SECTION
*) InputSection
)->SectionDefinitionGuid
))) {
756 return RETURN_INVALID_PARAMETER
;
759 // Get guid attribute of guid section.
761 *SectionAttribute
= ((EFI_GUID_DEFINED_SECTION
*) InputSection
)->Attributes
;
764 // Call Tiano GetInfo to get the required size info.
766 return UefiDecompressGetInfo (
767 (UINT8
*) InputSection
+ ((EFI_GUID_DEFINED_SECTION
*) InputSection
)->DataOffset
,
768 (*(UINT32
*) (((EFI_COMMON_SECTION_HEADER
*) InputSection
)->Size
) & 0x00ffffff) - ((EFI_GUID_DEFINED_SECTION
*) InputSection
)->DataOffset
,
775 The implementation of Tiano Decompress().
777 @param InputSection Buffer containing the input GUIDed section to be processed.
778 @param OutputBuffer OutputBuffer to point to the start of the section's contents.
779 if guided data is not prcessed. Otherwise,
780 OutputBuffer to contain the output data, which is allocated by the caller.
781 @param ScratchBuffer A pointer to a caller-allocated buffer for function internal use.
782 @param AuthenticationStatus A pointer to a caller-allocated UINT32 that indicates the
783 authentication status of the output buffer.
785 @retval RETURN_SUCCESS Decompression is successfull
786 @retval RETURN_INVALID_PARAMETER The source data is corrupted, or
787 The GUID in InputSection does not match this instance guid.
793 IN CONST VOID
*InputSection
,
794 OUT VOID
**OutputBuffer
,
795 IN VOID
*ScratchBuffer
, OPTIONAL
796 OUT UINT32
*AuthenticationStatus
799 ASSERT (OutputBuffer
!= NULL
);
801 if (InputSection
== NULL
) {
802 return RETURN_INVALID_PARAMETER
;
806 &gTianoCustomDecompressGuid
,
807 &(((EFI_GUID_DEFINED_SECTION
*) InputSection
)->SectionDefinitionGuid
))) {
808 return RETURN_INVALID_PARAMETER
;
812 // Set Authentication to Zero.
814 *AuthenticationStatus
= 0;
817 // Call Tiano Decompress to get the raw data
819 return UefiTianoDecompress (
820 (UINT8
*) InputSection
+ ((EFI_GUID_DEFINED_SECTION
*) InputSection
)->DataOffset
,
828 Register TianoDecompress handler.
830 @retval RETURN_SUCCESS Register successfully.
831 @retval RETURN_OUT_OF_RESOURCES No enough memory to store this handler.
835 TianoDecompressLibConstructor (
838 return ExtractGuidedSectionRegisterHandlers (
839 &gTianoCustomDecompressGuid
,
840 TianoDecompressGetInfo
,