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 <Guid/CustomDecompress.h>
19 #include "BaseUefiTianoCustomDecompressLibInternals.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.
120 volatile UINT16 Index
;
130 for (Index
= 1; Index
<= 16; Index
++) {
134 for (Index
= 0; Index
< NumOfChar
; Index
++) {
135 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
);
153 for (Index
= 1; Index
<= TableBits
; Index
++) {
154 Start
[Index
] >>= JuBits
;
155 Weight
[Index
] = (UINT16
) (1U << (TableBits
- Index
));
158 while (Index
<= 16) {
159 Weight
[Index
] = (UINT16
) (1U << (16 - Index
));
163 Index
= (UINT16
) (Start
[TableBits
+ 1] >> JuBits
);
166 Index3
= (UINT16
) (1U << TableBits
);
167 while (Index
!= Index3
) {
173 Mask
= (UINT16
) (1U << (15 - TableBits
));
175 for (Char
= 0; Char
< NumOfChar
; Char
++) {
182 NextCode
= (UINT16
) (Start
[Len
] + Weight
[Len
]);
184 if (Len
<= TableBits
) {
186 for (Index
= Start
[Len
]; Index
< NextCode
; Index
++) {
193 Pointer
= &Table
[Index3
>> JuBits
];
194 Index
= (UINT16
) (Len
- TableBits
);
198 Sd
->mRight
[Avail
] = Sd
->mLeft
[Avail
] = 0;
203 Pointer
= &Sd
->mRight
[*Pointer
];
205 Pointer
= &Sd
->mLeft
[*Pointer
];
216 Start
[Len
] = NextCode
;
225 Decodes a position value.
227 @param Sd the global scratch data
229 @return The position value decoded.
240 Val
= Sd
->mPTTable
[Sd
->mBitBuf
>> (BITBUFSIZ
- 8)];
243 Mask
= 1U << (BITBUFSIZ
- 1 - 8);
247 if (Sd
->mBitBuf
& Mask
) {
248 Val
= Sd
->mRight
[Val
];
250 Val
= Sd
->mLeft
[Val
];
254 } while (Val
>= MAXNP
);
257 // Advance what we have read
259 FillBuf (Sd
, Sd
->mPTLen
[Val
]);
263 Pos
= (UINT32
) ((1U << (Val
- 1)) + GetBits (Sd
, (UINT16
) (Val
- 1)));
270 Reads code lengths for the Extra Set or the Position Set.
272 Read in the Extra Set or Pointion Set Length Arrary, then
273 generate the Huffman code mapping for them.
275 @param Sd The global scratch data.
276 @param nn Number of symbols.
277 @param nbit Number of bits needed to represent nn.
278 @param Special The special symbol that needs to be taken care of.
281 @retval BAD_TABLE Table is corrupted.
294 volatile UINT16 Index
;
297 Number
= (UINT16
) GetBits (Sd
, nbit
);
300 CharC
= (UINT16
) GetBits (Sd
, nbit
);
302 for (Index
= 0; Index
< 256; Index
++) {
303 Sd
->mPTTable
[Index
] = CharC
;
306 for (Index
= 0; Index
< nn
; Index
++) {
307 Sd
->mPTLen
[Index
] = 0;
315 while (Index
< Number
) {
317 CharC
= (UINT16
) (Sd
->mBitBuf
>> (BITBUFSIZ
- 3));
320 Mask
= 1U << (BITBUFSIZ
- 1 - 3);
321 while (Mask
& Sd
->mBitBuf
) {
327 FillBuf (Sd
, (UINT16
) ((CharC
< 7) ? 3 : CharC
- 3));
329 Sd
->mPTLen
[Index
++] = (UINT8
) CharC
;
331 if (Index
== Special
) {
332 CharC
= (UINT16
) GetBits (Sd
, 2);
333 while ((INT16
) (--CharC
) >= 0) {
334 Sd
->mPTLen
[Index
++] = 0;
340 Sd
->mPTLen
[Index
++] = 0;
343 return MakeTable (Sd
, nn
, Sd
->mPTLen
, 8, Sd
->mPTTable
);
347 Reads code lengths for Char&Len Set.
349 Read in and decode the Char&Len Set Code Length Array, then
350 generate the Huffman Code mapping table for the Char&Len Set.
352 @param Sd the global scratch data
362 volatile UINT16 Index
;
365 Number
= (UINT16
) GetBits (Sd
, CBIT
);
368 CharC
= (UINT16
) GetBits (Sd
, CBIT
);
370 for (Index
= 0; Index
< NC
; Index
++) {
371 Sd
->mCLen
[Index
] = 0;
374 for (Index
= 0; Index
< 4096; Index
++) {
375 Sd
->mCTable
[Index
] = CharC
;
382 while (Index
< Number
) {
384 CharC
= Sd
->mPTTable
[Sd
->mBitBuf
>> (BITBUFSIZ
- 8)];
386 Mask
= 1U << (BITBUFSIZ
- 1 - 8);
390 if (Mask
& Sd
->mBitBuf
) {
391 CharC
= Sd
->mRight
[CharC
];
393 CharC
= Sd
->mLeft
[CharC
];
398 } while (CharC
>= NT
);
401 // Advance what we have read
403 FillBuf (Sd
, Sd
->mPTLen
[CharC
]);
409 } else if (CharC
== 1) {
410 CharC
= (UINT16
) (GetBits (Sd
, 4) + 3);
411 } else if (CharC
== 2) {
412 CharC
= (UINT16
) (GetBits (Sd
, CBIT
) + 20);
415 while ((INT16
) (--CharC
) >= 0) {
416 Sd
->mCLen
[Index
++] = 0;
421 Sd
->mCLen
[Index
++] = (UINT8
) (CharC
- 2);
427 Sd
->mCLen
[Index
++] = 0;
430 MakeTable (Sd
, NC
, Sd
->mCLen
, 12, Sd
->mCTable
);
436 Decode a character/length value.
438 Read one value from mBitBuf, Get one code from mBitBuf. If it is at block boundary, generates
439 Huffman code mapping table for Extra Set, Code&Len Set and
442 @param Sd The global scratch data.
444 @return The value decoded.
455 if (Sd
->mBlockSize
== 0) {
457 // Starting a new block
459 Sd
->mBlockSize
= (UINT16
) GetBits (Sd
, 16);
460 Sd
->mBadTableFlag
= ReadPTLen (Sd
, NT
, TBIT
, 3);
461 if (Sd
->mBadTableFlag
!= 0) {
467 Sd
->mBadTableFlag
= ReadPTLen (Sd
, MAXNP
, Sd
->mPBit
, (UINT16
) (-1));
468 if (Sd
->mBadTableFlag
!= 0) {
474 Index2
= Sd
->mCTable
[Sd
->mBitBuf
>> (BITBUFSIZ
- 12)];
477 Mask
= 1U << (BITBUFSIZ
- 1 - 12);
480 if (Sd
->mBitBuf
& Mask
) {
481 Index2
= Sd
->mRight
[Index2
];
483 Index2
= Sd
->mLeft
[Index2
];
487 } while (Index2
>= NC
);
490 // Advance what we have read
492 FillBuf (Sd
, Sd
->mCLen
[Index2
]);
498 Decode the source data ad put the resulting data into the destination buffer.
500 @param Sd - The global scratch data
511 BytesRemain
= (UINT16
) (-1);
516 CharC
= DecodeC (Sd
);
517 if (Sd
->mBadTableFlag
!= 0) {
523 // Process an Original character
525 if (Sd
->mOutBuf
>= Sd
->mOrigSize
) {
528 Sd
->mDstBase
[Sd
->mOutBuf
++] = (UINT8
) CharC
;
535 CharC
= (UINT16
) (CharC
- (UINT8_MAX
+ 1 - THRESHOLD
));
539 DataIdx
= Sd
->mOutBuf
- DecodeP (Sd
) - 1;
542 while ((INT16
) (BytesRemain
) >= 0) {
543 Sd
->mDstBase
[Sd
->mOutBuf
++] = Sd
->mDstBase
[DataIdx
++];
544 if (Sd
->mOutBuf
>= Sd
->mOrigSize
) {
558 The internal implementation of *_DECOMPRESS_PROTOCOL.GetInfo().
560 @param Source The source buffer containing the compressed data.
561 @param SourceSize The size of source buffer
562 @param DestinationSize The size of destination buffer.
563 @param ScratchSize The size of scratch buffer.
565 @retval RETURN_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved.
566 @retval RETURN_INVALID_PARAMETER - The source data is corrupted
570 UefiDecompressGetInfo (
571 IN CONST VOID
*Source
,
572 IN UINT32 SourceSize
,
573 OUT UINT32
*DestinationSize
,
574 OUT UINT32
*ScratchSize
577 UINT32 CompressedSize
;
579 ASSERT (Source
!= NULL
);
580 ASSERT (DestinationSize
!= NULL
);
581 ASSERT (ScratchSize
!= NULL
);
583 if (SourceSize
< 8) {
584 return RETURN_INVALID_PARAMETER
;
587 CompressedSize
= ReadUnaligned32 ((UINT32
*)Source
);
588 if (SourceSize
< (CompressedSize
+ 8)) {
589 return RETURN_INVALID_PARAMETER
;
592 *ScratchSize
= sizeof (SCRATCH_DATA
);
593 *DestinationSize
= ReadUnaligned32 ((UINT32
*)Source
+ 1);
595 return RETURN_SUCCESS
;
599 The internal implementation of *_DECOMPRESS_PROTOCOL.Decompress().
601 @param Source The source buffer containing the compressed data.
602 @param Destination The destination buffer to store the decompressed data
603 @param Scratch The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.
604 @param Version 1 for UEFI Decompress algoruthm, 2 for Tiano Decompess algorithm
606 @retval RETURN_SUCCESS Decompression is successfull
607 @retval RETURN_INVALID_PARAMETER The source data is corrupted
611 UefiTianoDecompress (
612 IN CONST VOID
*Source
,
613 IN OUT VOID
*Destination
,
614 IN OUT VOID
*Scratch
,
618 volatile UINT32 Index
;
625 ASSERT (Source
!= NULL
);
626 ASSERT (Destination
!= NULL
);
627 ASSERT (Scratch
!= NULL
);
632 Sd
= (SCRATCH_DATA
*) Scratch
;
634 CompSize
= Src
[0] + (Src
[1] << 8) + (Src
[2] << 16) + (Src
[3] << 24);
635 OrigSize
= Src
[4] + (Src
[5] << 8) + (Src
[6] << 16) + (Src
[7] << 24);
638 // If compressed file size is 0, return
641 return RETURN_SUCCESS
;
646 for (Index
= 0; Index
< sizeof (SCRATCH_DATA
); Index
++) {
647 ((UINT8
*) Sd
)[Index
] = 0;
650 // The length of the field 'Position Set Code Length Array Size' in Block Header.
651 // For UEFI 2.0 de/compression algorithm(Version 1), mPBit = 4
652 // For Tiano de/compression algorithm(Version 2), mPBit = 5
664 Sd
->mSrcBase
= (UINT8
*)Src
;
666 Sd
->mCompSize
= CompSize
;
667 Sd
->mOrigSize
= OrigSize
;
670 // Fill the first BITBUFSIZ bits
672 FillBuf (Sd
, BITBUFSIZ
);
679 if (Sd
->mBadTableFlag
!= 0) {
681 // Something wrong with the source
683 return RETURN_INVALID_PARAMETER
;
686 return RETURN_SUCCESS
;
690 The internal implementation of *_DECOMPRESS_PROTOCOL.Decompress().
692 @param Source - The source buffer containing the compressed data.
693 @param Destination - The destination buffer to store the decompressed data
694 @param Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.
696 @retval RETURN_SUCCESS - Decompression is successfull
697 @retval RETURN_INVALID_PARAMETER - The source data is corrupted
702 IN CONST VOID
*Source
,
703 IN OUT VOID
*Destination
,
707 return UefiTianoDecompress (Source
, Destination
, Scratch
, 1);
711 The internal implementation of Tiano decompress GetInfo.
713 @param InputSection Buffer containing the input GUIDed section to be processed.
714 @param OutputBufferSize The size of OutputBuffer.
715 @param ScratchBufferSize The size of ScratchBuffer.
716 @param SectionAttribute The attribute of the input guided section.
718 @retval RETURN_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved.
719 @retval RETURN_INVALID_PARAMETER - The source data is corrupted
720 The GUID in InputSection does not match this instance guid.
724 TianoDecompressGetInfo (
725 IN CONST VOID
*InputSection
,
726 OUT UINT32
*OutputBufferSize
,
727 OUT UINT32
*ScratchBufferSize
,
728 OUT UINT16
*SectionAttribute
732 ASSERT (SectionAttribute
!= NULL
);
734 if (InputSection
== NULL
) {
735 return RETURN_INVALID_PARAMETER
;
739 &gTianoCustomDecompressGuid
,
740 &(((EFI_GUID_DEFINED_SECTION
*) InputSection
)->SectionDefinitionGuid
))) {
741 return RETURN_INVALID_PARAMETER
;
744 // Get guid attribute of guid section.
746 *SectionAttribute
= ((EFI_GUID_DEFINED_SECTION
*) InputSection
)->Attributes
;
749 // Call Tiano GetInfo to get the required size info.
751 return UefiDecompressGetInfo (
752 (UINT8
*) InputSection
+ ((EFI_GUID_DEFINED_SECTION
*) InputSection
)->DataOffset
,
753 (*(UINT32
*) (((EFI_COMMON_SECTION_HEADER
*) InputSection
)->Size
) & 0x00ffffff) - ((EFI_GUID_DEFINED_SECTION
*) InputSection
)->DataOffset
,
760 The implementation of Tiano Decompress().
762 @param InputSection Buffer containing the input GUIDed section to be processed.
763 @param OutputBuffer OutputBuffer to point to the start of the section's contents.
764 if guided data is not prcessed. Otherwise,
765 OutputBuffer to contain the output data, which is allocated by the caller.
766 @param ScratchBuffer A pointer to a caller-allocated buffer for function internal use.
767 @param AuthenticationStatus A pointer to a caller-allocated UINT32 that indicates the
768 authentication status of the output buffer.
770 @retval RETURN_SUCCESS Decompression is successfull
771 @retval RETURN_INVALID_PARAMETER The source data is corrupted, or
772 The GUID in InputSection does not match this instance guid.
778 IN CONST VOID
*InputSection
,
779 OUT VOID
**OutputBuffer
,
780 IN VOID
*ScratchBuffer
, OPTIONAL
781 OUT UINT32
*AuthenticationStatus
784 ASSERT (OutputBuffer
!= NULL
);
786 if (InputSection
== NULL
) {
787 return RETURN_INVALID_PARAMETER
;
791 &gTianoCustomDecompressGuid
,
792 &(((EFI_GUID_DEFINED_SECTION
*) InputSection
)->SectionDefinitionGuid
))) {
793 return RETURN_INVALID_PARAMETER
;
797 // Set Authentication to Zero.
799 *AuthenticationStatus
= 0;
802 // Call Tiano Decompress to get the raw data
804 return UefiTianoDecompress (
805 (UINT8
*) InputSection
+ ((EFI_GUID_DEFINED_SECTION
*) InputSection
)->DataOffset
,
813 Register TianoDecompress handler.
815 @retval RETURN_SUCCESS Register successfully.
816 @retval RETURN_OUT_OF_RESOURCES No enough memory to store this handler.
820 TianoDecompressLibConstructor (
823 return ExtractGuidedSectionRegisterHandlers (
824 &gTianoCustomDecompressGuid
,
825 TianoDecompressGetInfo
,