2 UEFI and Custom Decompress Library
4 Copyright (c) 2006, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include <Guid/CustomDecompress.h>
16 #include "BaseUefiTianoCustomDecompressLibInternals.h"
27 Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source.
31 Sd - The global scratch data
32 NumOfBits - The number of bits to shift and read.
38 Sd
->mBitBuf
= (UINT32
) (Sd
->mBitBuf
<< NumOfBits
);
40 while (NumOfBits
> Sd
->mBitCount
) {
42 Sd
->mBitBuf
|= (UINT32
) (Sd
->mSubBitBuf
<< (NumOfBits
= (UINT16
) (NumOfBits
- Sd
->mBitCount
)));
44 if (Sd
->mCompSize
> 0) {
46 // Get 1 byte into SubBitBuf
50 Sd
->mSubBitBuf
= Sd
->mSrcBase
[Sd
->mInBuf
++];
55 // No more bits from the source, just pad zero bit.
63 Sd
->mBitCount
= (UINT16
) (Sd
->mBitCount
- NumOfBits
);
64 Sd
->mBitBuf
|= Sd
->mSubBitBuf
>> Sd
->mBitCount
;
76 Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent
77 NumOfBits of bits from source. Returns NumOfBits of bits that are
82 Sd - The global scratch data.
83 NumOfBits - The number of bits to pop and read.
87 The bits that are popped out.
93 OutBits
= (UINT32
) (Sd
->mBitBuf
>> (BITBUFSIZ
- NumOfBits
));
95 FillBuf (Sd
, NumOfBits
);
112 Creates Huffman Code mapping table according to code length array.
116 Sd - The global scratch data
117 NumOfChar - Number of symbols in the symbol set
118 BitLen - Code length array
119 TableBits - The width of the mapping table
125 BAD_TABLE - The table is corrupted.
134 volatile UINT16 Index
;
144 for (Index
= 1; Index
<= 16; Index
++) {
148 for (Index
= 0; Index
< NumOfChar
; Index
++) {
149 Count
[BitLen
[Index
]]++;
154 for (Index
= 1; Index
<= 16; Index
++) {
155 WordOfStart
= Start
[Index
];
156 WordOfCount
= Count
[Index
];
157 Start
[Index
+ 1] = (UINT16
) (WordOfStart
+ (WordOfCount
<< (16 - Index
)));
160 if (Start
[17] != 0) {
162 return (UINT16
) BAD_TABLE
;
165 JuBits
= (UINT16
) (16 - TableBits
);
167 for (Index
= 1; Index
<= TableBits
; Index
++) {
168 Start
[Index
] >>= JuBits
;
169 Weight
[Index
] = (UINT16
) (1U << (TableBits
- Index
));
172 while (Index
<= 16) {
173 Weight
[Index
] = (UINT16
) (1U << (16 - Index
));
177 Index
= (UINT16
) (Start
[TableBits
+ 1] >> JuBits
);
180 Index3
= (UINT16
) (1U << TableBits
);
181 while (Index
!= Index3
) {
187 Mask
= (UINT16
) (1U << (15 - TableBits
));
189 for (Char
= 0; Char
< NumOfChar
; Char
++) {
196 NextCode
= (UINT16
) (Start
[Len
] + Weight
[Len
]);
198 if (Len
<= TableBits
) {
200 for (Index
= Start
[Len
]; Index
< NextCode
; Index
++) {
207 Pointer
= &Table
[Index3
>> JuBits
];
208 Index
= (UINT16
) (Len
- TableBits
);
212 Sd
->mRight
[Avail
] = Sd
->mLeft
[Avail
] = 0;
217 Pointer
= &Sd
->mRight
[*Pointer
];
219 Pointer
= &Sd
->mLeft
[*Pointer
];
230 Start
[Len
] = NextCode
;
246 Decodes a position value.
250 Sd - the global scratch data
254 The position value decoded.
262 Val
= Sd
->mPTTable
[Sd
->mBitBuf
>> (BITBUFSIZ
- 8)];
265 Mask
= 1U << (BITBUFSIZ
- 1 - 8);
269 if (Sd
->mBitBuf
& Mask
) {
270 Val
= Sd
->mRight
[Val
];
272 Val
= Sd
->mLeft
[Val
];
276 } while (Val
>= MAXNP
);
279 // Advance what we have read
281 FillBuf (Sd
, Sd
->mPTLen
[Val
]);
285 Pos
= (UINT32
) ((1U << (Val
- 1)) + GetBits (Sd
, (UINT16
) (Val
- 1)));
302 Reads code lengths for the Extra Set or the Position Set
306 Sd - The global scratch data
307 nn - Number of symbols
308 nbit - Number of bits needed to represent nn
309 Special - The special symbol that needs to be taken care of
314 BAD_TABLE - Table is corrupted.
320 volatile UINT16 Index
;
323 Number
= (UINT16
) GetBits (Sd
, nbit
);
326 CharC
= (UINT16
) GetBits (Sd
, nbit
);
328 for (Index
= 0; Index
< 256; Index
++) {
329 Sd
->mPTTable
[Index
] = CharC
;
332 for (Index
= 0; Index
< nn
; Index
++) {
333 Sd
->mPTLen
[Index
] = 0;
341 while (Index
< Number
) {
343 CharC
= (UINT16
) (Sd
->mBitBuf
>> (BITBUFSIZ
- 3));
346 Mask
= 1U << (BITBUFSIZ
- 1 - 3);
347 while (Mask
& Sd
->mBitBuf
) {
353 FillBuf (Sd
, (UINT16
) ((CharC
< 7) ? 3 : CharC
- 3));
355 Sd
->mPTLen
[Index
++] = (UINT8
) CharC
;
357 if (Index
== Special
) {
358 CharC
= (UINT16
) GetBits (Sd
, 2);
359 while ((INT16
) (--CharC
) >= 0) {
360 Sd
->mPTLen
[Index
++] = 0;
366 Sd
->mPTLen
[Index
++] = 0;
369 return MakeTable (Sd
, nn
, Sd
->mPTLen
, 8, Sd
->mPTTable
);
380 Reads code lengths for Char&Len Set.
384 Sd - the global scratch data
392 volatile UINT16 Index
;
395 Number
= (UINT16
) GetBits (Sd
, CBIT
);
398 CharC
= (UINT16
) GetBits (Sd
, CBIT
);
400 for (Index
= 0; Index
< NC
; Index
++) {
401 Sd
->mCLen
[Index
] = 0;
404 for (Index
= 0; Index
< 4096; Index
++) {
405 Sd
->mCTable
[Index
] = CharC
;
412 while (Index
< Number
) {
414 CharC
= Sd
->mPTTable
[Sd
->mBitBuf
>> (BITBUFSIZ
- 8)];
416 Mask
= 1U << (BITBUFSIZ
- 1 - 8);
420 if (Mask
& Sd
->mBitBuf
) {
421 CharC
= Sd
->mRight
[CharC
];
423 CharC
= Sd
->mLeft
[CharC
];
428 } while (CharC
>= NT
);
431 // Advance what we have read
433 FillBuf (Sd
, Sd
->mPTLen
[CharC
]);
439 } else if (CharC
== 1) {
440 CharC
= (UINT16
) (GetBits (Sd
, 4) + 3);
441 } else if (CharC
== 2) {
442 CharC
= (UINT16
) (GetBits (Sd
, CBIT
) + 20);
445 while ((INT16
) (--CharC
) >= 0) {
446 Sd
->mCLen
[Index
++] = 0;
451 Sd
->mCLen
[Index
++] = (UINT8
) (CharC
- 2);
457 Sd
->mCLen
[Index
++] = 0;
460 MakeTable (Sd
, NC
, Sd
->mCLen
, 12, Sd
->mCTable
);
473 Decode a character/length value.
477 Sd - The global scratch data.
488 if (Sd
->mBlockSize
== 0) {
490 // Starting a new block
492 Sd
->mBlockSize
= (UINT16
) GetBits (Sd
, 16);
493 Sd
->mBadTableFlag
= ReadPTLen (Sd
, NT
, TBIT
, 3);
494 if (Sd
->mBadTableFlag
!= 0) {
500 Sd
->mBadTableFlag
= ReadPTLen (Sd
, MAXNP
, Sd
->mPBit
, (UINT16
) (-1));
501 if (Sd
->mBadTableFlag
!= 0) {
507 Index2
= Sd
->mCTable
[Sd
->mBitBuf
>> (BITBUFSIZ
- 12)];
510 Mask
= 1U << (BITBUFSIZ
- 1 - 12);
513 if (Sd
->mBitBuf
& Mask
) {
514 Index2
= Sd
->mRight
[Index2
];
516 Index2
= Sd
->mLeft
[Index2
];
520 } while (Index2
>= NC
);
523 // Advance what we have read
525 FillBuf (Sd
, Sd
->mCLen
[Index2
]);
538 Decode the source data and put the resulting data into the destination buffer.
542 Sd - The global scratch data
552 BytesRemain
= (UINT16
) (-1);
557 CharC
= DecodeC (Sd
);
558 if (Sd
->mBadTableFlag
!= 0) {
564 // Process an Original character
566 if (Sd
->mOutBuf
>= Sd
->mOrigSize
) {
569 Sd
->mDstBase
[Sd
->mOutBuf
++] = (UINT8
) CharC
;
576 CharC
= (UINT16
) (CharC
- (UINT8_MAX
+ 1 - THRESHOLD
));
580 DataIdx
= Sd
->mOutBuf
- DecodeP (Sd
) - 1;
583 while ((INT16
) (BytesRemain
) >= 0) {
584 Sd
->mDstBase
[Sd
->mOutBuf
++] = Sd
->mDstBase
[DataIdx
++];
585 if (Sd
->mOutBuf
>= Sd
->mOrigSize
) {
600 UefiDecompressGetInfo (
601 IN CONST VOID
*Source
,
602 IN UINT32 SourceSize
,
603 OUT UINT32
*DestinationSize
,
604 OUT UINT32
*ScratchSize
610 The internal implementation of *_DECOMPRESS_PROTOCOL.GetInfo().
614 Source - The source buffer containing the compressed data.
615 SourceSize - The size of source buffer
616 DestinationSize - The size of destination buffer.
617 ScratchSize - The size of scratch buffer.
621 RETURN_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved.
622 RETURN_INVALID_PARAMETER - The source data is corrupted
626 UINT32 CompressedSize
;
628 ASSERT (Source
!= NULL
);
629 ASSERT (DestinationSize
!= NULL
);
630 ASSERT (ScratchSize
!= NULL
);
632 if (SourceSize
< 8) {
633 return RETURN_INVALID_PARAMETER
;
636 CompressedSize
= *(UINT32
*) Source
;
637 if (SourceSize
< (CompressedSize
+ 8)) {
638 return RETURN_INVALID_PARAMETER
;
641 *ScratchSize
= sizeof (SCRATCH_DATA
);
642 *DestinationSize
= *((UINT32
*) Source
+ 1);
644 return RETURN_SUCCESS
;
649 UefiTianoDecompress (
650 IN CONST VOID
*Source
,
651 IN OUT VOID
*Destination
,
652 IN OUT VOID
*Scratch
,
659 The internal implementation of *_DECOMPRESS_PROTOCOL.Decompress().
663 Source - The source buffer containing the compressed data.
664 Destination - The destination buffer to store the decompressed data
665 Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.
666 Version - 1 for UEFI Decompress algoruthm, 2 for Tiano Decompess algorithm
670 RETURN_SUCCESS - Decompression is successfull
671 RETURN_INVALID_PARAMETER - The source data is corrupted
675 volatile UINT32 Index
;
682 ASSERT (Source
!= NULL
);
683 ASSERT (Destination
!= NULL
);
684 ASSERT (Scratch
!= NULL
);
689 Sd
= (SCRATCH_DATA
*) Scratch
;
691 CompSize
= Src
[0] + (Src
[1] << 8) + (Src
[2] << 16) + (Src
[3] << 24);
692 OrigSize
= Src
[4] + (Src
[5] << 8) + (Src
[6] << 16) + (Src
[7] << 24);
695 // If compressed file size is 0, return
698 return RETURN_SUCCESS
;
703 for (Index
= 0; Index
< sizeof (SCRATCH_DATA
); Index
++) {
704 ((UINT8
*) Sd
)[Index
] = 0;
707 // The length of the field 'Position Set Code Length Array Size' in Block Header.
708 // For UEFI 2.0 de/compression algorithm(Version 1), mPBit = 4
709 // For Tiano de/compression algorithm(Version 2), mPBit = 5
721 Sd
->mSrcBase
= (UINT8
*)Src
;
723 Sd
->mCompSize
= CompSize
;
724 Sd
->mOrigSize
= OrigSize
;
727 // Fill the first BITBUFSIZ bits
729 FillBuf (Sd
, BITBUFSIZ
);
736 if (Sd
->mBadTableFlag
!= 0) {
738 // Something wrong with the source
740 return RETURN_INVALID_PARAMETER
;
743 return RETURN_SUCCESS
;
749 IN CONST VOID
*Source
,
750 IN OUT VOID
*Destination
,
757 The internal implementation of *_DECOMPRESS_PROTOCOL.Decompress().
761 Source - The source buffer containing the compressed data.
762 Destination - The destination buffer to store the decompressed data
763 Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.
767 RETURN_SUCCESS - Decompression is successfull
768 RETURN_INVALID_PARAMETER - The source data is corrupted
772 return UefiTianoDecompress (Source
, Destination
, Scratch
, 1);
777 TianoDecompressGetInfo (
778 IN CONST VOID
*InputSection
,
779 OUT UINT32
*OutputBufferSize
,
780 OUT UINT32
*ScratchBufferSize
,
781 OUT UINT16
*SectionAttribute
787 The internal implementation of Tiano decompress GetInfo.
790 InputSection Buffer containing the input GUIDed section to be processed.
791 OutputBufferSize The size of OutputBuffer.
792 ScratchBufferSize The size of ScratchBuffer.
793 SectionAttribute The attribute of the input guided section.
797 RETURN_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved.
798 RETURN_INVALID_PARAMETER - The source data is corrupted
799 The GUID in InputSection does not match this instance guid.
803 ASSERT (SectionAttribute
!= NULL
);
805 if (InputSection
== NULL
) {
806 return RETURN_INVALID_PARAMETER
;
810 &gTianoCustomDecompressGuid
,
811 &(((EFI_GUID_DEFINED_SECTION
*) InputSection
)->SectionDefinitionGuid
))) {
812 return RETURN_INVALID_PARAMETER
;
815 // Get guid attribute of guid section.
817 *SectionAttribute
= ((EFI_GUID_DEFINED_SECTION
*) InputSection
)->Attributes
;
820 // Call Tiano GetInfo to get the required size info.
822 return UefiDecompressGetInfo (
823 (UINT8
*) InputSection
+ ((EFI_GUID_DEFINED_SECTION
*) InputSection
)->DataOffset
,
824 *(UINT32
*) (((EFI_COMMON_SECTION_HEADER
*) InputSection
)->Size
) & 0x00ffffff - ((EFI_GUID_DEFINED_SECTION
*) InputSection
)->DataOffset
,
833 IN CONST VOID
*InputSection
,
834 OUT VOID
**OutputBuffer
,
835 IN VOID
*ScratchBuffer
, OPTIONAL
836 OUT UINT32
*AuthenticationStatus
842 The implementation of Tiano Decompress().
845 InputSection Buffer containing the input GUIDed section to be processed.
846 OutputBuffer OutputBuffer to point to the start of the section's contents.
847 if guided data is not prcessed. Otherwise,
848 OutputBuffer to contain the output data, which is allocated by the caller.
849 ScratchBuffer A pointer to a caller-allocated buffer for function internal use.
850 AuthenticationStatus A pointer to a caller-allocated UINT32 that indicates the
851 authentication status of the output buffer.
855 RETURN_SUCCESS - Decompression is successfull
856 RETURN_INVALID_PARAMETER - The source data is corrupted, or
857 The GUID in InputSection does not match this instance guid.
861 ASSERT (OutputBuffer
!= NULL
);
863 if (InputSection
== NULL
) {
864 return RETURN_INVALID_PARAMETER
;
868 &gTianoCustomDecompressGuid
,
869 &(((EFI_GUID_DEFINED_SECTION
*) InputSection
)->SectionDefinitionGuid
))) {
870 return RETURN_INVALID_PARAMETER
;
874 // Set Authentication to Zero.
876 *AuthenticationStatus
= 0;
879 // Call Tiano Decompress to get the raw data
881 return UefiTianoDecompress (
882 (UINT8
*) InputSection
+ ((EFI_GUID_DEFINED_SECTION
*) InputSection
)->DataOffset
,
890 Register TianoDecompress handler.
892 @retval RETURN_SUCCESS Register successfully.
893 @retval RETURN_OUT_OF_RESOURCES No enough memory to store this handler.
897 TianoDecompressLibConstructor (
900 return ExtractGuidedSectionRegisterHandlers (
901 &gTianoCustomDecompressGuid
,
902 TianoDecompressGetInfo
,