]>
git.proxmox.com Git - mirror_edk2.git/blob - MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.c
28b4bf9d8bcf4a36bc2779b2766bcde65368ff22
2 UEFI Decompress Library implementation refer to UEFI specification.
4 Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
5 Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "BaseUefiDecompressLibInternals.h"
13 Read NumOfBit of bits from source into mBitBuf.
15 Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source.
17 @param Sd The global scratch data.
18 @param NumOfBits The number of bits to shift and read.
28 // Left shift NumOfBits of bits in advance
30 Sd
->mBitBuf
= (UINT32
) LShiftU64 (((UINT64
)Sd
->mBitBuf
), NumOfBits
);
33 // Copy data needed in bytes into mSbuBitBuf
35 while (NumOfBits
> Sd
->mBitCount
) {
36 NumOfBits
= (UINT16
) (NumOfBits
- Sd
->mBitCount
);
37 Sd
->mBitBuf
|= (UINT32
) LShiftU64 (((UINT64
)Sd
->mSubBitBuf
), NumOfBits
);
39 if (Sd
->mCompSize
> 0) {
41 // Get 1 byte into SubBitBuf
44 Sd
->mSubBitBuf
= Sd
->mSrcBase
[Sd
->mInBuf
++];
49 // No more bits from the source, just pad zero bit.
58 // Calculate additional bit count read to update mBitCount
60 Sd
->mBitCount
= (UINT16
) (Sd
->mBitCount
- NumOfBits
);
63 // Copy NumOfBits of bits from mSubBitBuf into mBitBuf
65 Sd
->mBitBuf
|= Sd
->mSubBitBuf
>> Sd
->mBitCount
;
69 Get NumOfBits of bits out from mBitBuf.
71 Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent
72 NumOfBits of bits from source. Returns NumOfBits of bits that are
75 @param Sd The global scratch data.
76 @param NumOfBits The number of bits to pop and read.
78 @return The bits that are popped out.
90 // Pop NumOfBits of Bits from Left
92 OutBits
= (UINT32
) (Sd
->mBitBuf
>> (BITBUFSIZ
- NumOfBits
));
95 // Fill up mBitBuf from source
97 FillBuf (Sd
, NumOfBits
);
103 Creates Huffman Code mapping table according to code length array.
105 Creates Huffman Code mapping table for Extra Set, Char&Len Set
106 and Position Set according to code length array.
107 If TableBits > 16, then ASSERT ().
109 @param Sd The global scratch data.
110 @param NumOfChar The number of symbols in the symbol set.
111 @param BitLen Code length array.
112 @param TableBits The width of the mapping table.
113 @param Table The table to be created.
116 @retval BAD_TABLE The table is corrupted.
142 UINT16 MaxTableLength
;
145 // The maximum mapping table width supported by this internal
146 // working function is 16.
148 ASSERT (TableBits
<= 16);
150 for (Index
= 0; Index
<= 16; Index
++) {
154 for (Index
= 0; Index
< NumOfChar
; Index
++) {
155 if (BitLen
[Index
] > 16) {
156 return (UINT16
) BAD_TABLE
;
158 Count
[BitLen
[Index
]]++;
164 for (Index
= 1; Index
<= 16; Index
++) {
165 WordOfStart
= Start
[Index
];
166 WordOfCount
= Count
[Index
];
167 Start
[Index
+ 1] = (UINT16
) (WordOfStart
+ (WordOfCount
<< (16 - Index
)));
170 if (Start
[17] != 0) {
172 return (UINT16
) BAD_TABLE
;
175 JuBits
= (UINT16
) (16 - TableBits
);
178 for (Index
= 1; Index
<= TableBits
; Index
++) {
179 Start
[Index
] >>= JuBits
;
180 Weight
[Index
] = (UINT16
) (1U << (TableBits
- Index
));
183 while (Index
<= 16) {
184 Weight
[Index
] = (UINT16
) (1U << (16 - Index
));
188 Index
= (UINT16
) (Start
[TableBits
+ 1] >> JuBits
);
191 Index3
= (UINT16
) (1U << TableBits
);
192 if (Index
< Index3
) {
193 SetMem16 (Table
+ Index
, (Index3
- Index
) * sizeof (*Table
), 0);
198 Mask
= (UINT16
) (1U << (15 - TableBits
));
199 MaxTableLength
= (UINT16
) (1U << TableBits
);
201 for (Char
= 0; Char
< NumOfChar
; Char
++) {
204 if (Len
== 0 || Len
>= 17) {
208 NextCode
= (UINT16
) (Start
[Len
] + Weight
[Len
]);
210 if (Len
<= TableBits
) {
212 if (Start
[Len
] >= NextCode
|| NextCode
> MaxTableLength
){
213 return (UINT16
) BAD_TABLE
;
216 for (Index
= Start
[Len
]; Index
< NextCode
; Index
++) {
223 Pointer
= &Table
[Index3
>> JuBits
];
224 Index
= (UINT16
) (Len
- TableBits
);
227 if (*Pointer
== 0 && Avail
< (2 * NC
- 1)) {
228 Sd
->mRight
[Avail
] = Sd
->mLeft
[Avail
] = 0;
232 if (*Pointer
< (2 * NC
- 1)) {
233 if ((Index3
& Mask
) != 0) {
234 Pointer
= &Sd
->mRight
[*Pointer
];
236 Pointer
= &Sd
->mLeft
[*Pointer
];
248 Start
[Len
] = NextCode
;
257 Decodes a position value.
259 Get a position value according to Position Huffman Table.
261 @param Sd The global scratch data.
263 @return The position value decoded.
275 Val
= Sd
->mPTTable
[Sd
->mBitBuf
>> (BITBUFSIZ
- 8)];
278 Mask
= 1U << (BITBUFSIZ
- 1 - 8);
282 if ((Sd
->mBitBuf
& Mask
) != 0) {
283 Val
= Sd
->mRight
[Val
];
285 Val
= Sd
->mLeft
[Val
];
289 } while (Val
>= MAXNP
);
292 // Advance what we have read
294 FillBuf (Sd
, Sd
->mPTLen
[Val
]);
298 Pos
= (UINT32
) ((1U << (Val
- 1)) + GetBits (Sd
, (UINT16
) (Val
- 1)));
305 Reads code lengths for the Extra Set or the Position Set.
307 Read in the Extra Set or Position Set Length Array, then
308 generate the Huffman code mapping for them.
310 @param Sd The global scratch data.
311 @param nn The number of symbols.
312 @param nbit The number of bits needed to represent nn.
313 @param Special The special symbol that needs to be taken care of.
316 @retval BAD_TABLE Table is corrupted.
334 // Read Extra Set Code Length Array size
336 Number
= (UINT16
) GetBits (Sd
, nbit
);
340 // This represents only Huffman code used
342 CharC
= (UINT16
) GetBits (Sd
, nbit
);
344 SetMem16 (&Sd
->mPTTable
[0] , sizeof (Sd
->mPTTable
), CharC
);
346 SetMem (Sd
->mPTLen
, nn
, 0);
353 while (Index
< Number
&& Index
< NPT
) {
355 CharC
= (UINT16
) (Sd
->mBitBuf
>> (BITBUFSIZ
- 3));
358 // If a code length is less than 7, then it is encoded as a 3-bit
359 // value. Or it is encoded as a series of "1"s followed by a
360 // terminating "0". The number of "1"s = Code length - 4.
363 Mask
= 1U << (BITBUFSIZ
- 1 - 3);
364 while (Mask
& Sd
->mBitBuf
) {
370 FillBuf (Sd
, (UINT16
) ((CharC
< 7) ? 3 : CharC
- 3));
372 Sd
->mPTLen
[Index
++] = (UINT8
) CharC
;
376 // After the third length of the code length concatenation,
377 // a 2-bit value is used to indicated the number of consecutive
378 // zero lengths after the third length.
380 if (Index
== Special
) {
381 CharC
= (UINT16
) GetBits (Sd
, 2);
382 while ((INT16
) (--CharC
) >= 0 && Index
< NPT
) {
383 Sd
->mPTLen
[Index
++] = 0;
388 while (Index
< nn
&& Index
< NPT
) {
389 Sd
->mPTLen
[Index
++] = 0;
392 return MakeTable (Sd
, nn
, Sd
->mPTLen
, 8, Sd
->mPTTable
);
396 Reads code lengths for Char&Len Set.
398 Read in and decode the Char&Len Set Code Length Array, then
399 generate the Huffman Code mapping table for the Char&Len Set.
401 @param Sd The global scratch data.
414 Number
= (UINT16
) GetBits (Sd
, CBIT
);
418 // This represents only Huffman code used
420 CharC
= (UINT16
) GetBits (Sd
, CBIT
);
422 SetMem (Sd
->mCLen
, NC
, 0);
423 SetMem16 (&Sd
->mCTable
[0], sizeof (Sd
->mCTable
), CharC
);
429 while (Index
< Number
&& Index
< NC
) {
430 CharC
= Sd
->mPTTable
[Sd
->mBitBuf
>> (BITBUFSIZ
- 8)];
432 Mask
= 1U << (BITBUFSIZ
- 1 - 8);
436 if (Mask
& Sd
->mBitBuf
) {
437 CharC
= Sd
->mRight
[CharC
];
439 CharC
= Sd
->mLeft
[CharC
];
444 } while (CharC
>= NT
);
447 // Advance what we have read
449 FillBuf (Sd
, Sd
->mPTLen
[CharC
]);
455 } else if (CharC
== 1) {
456 CharC
= (UINT16
) (GetBits (Sd
, 4) + 3);
457 } else if (CharC
== 2) {
458 CharC
= (UINT16
) (GetBits (Sd
, CBIT
) + 20);
461 while ((INT16
) (--CharC
) >= 0 && Index
< NC
) {
462 Sd
->mCLen
[Index
++] = 0;
467 Sd
->mCLen
[Index
++] = (UINT8
) (CharC
- 2);
472 SetMem (Sd
->mCLen
+ Index
, NC
- Index
, 0);
474 MakeTable (Sd
, NC
, Sd
->mCLen
, 12, Sd
->mCTable
);
480 Decode a character/length value.
482 Read one value from mBitBuf, Get one code from mBitBuf. If it is at block boundary, generates
483 Huffman code mapping table for Extra Set, Code&Len Set and
486 @param Sd The global scratch data.
488 @return The value decoded.
499 if (Sd
->mBlockSize
== 0) {
501 // Starting a new block
502 // Read BlockSize from block header
504 Sd
->mBlockSize
= (UINT16
) GetBits (Sd
, 16);
507 // Read in the Extra Set Code Length Array,
508 // Generate the Huffman code mapping table for Extra Set.
510 Sd
->mBadTableFlag
= ReadPTLen (Sd
, NT
, TBIT
, 3);
511 if (Sd
->mBadTableFlag
!= 0) {
516 // Read in and decode the Char&Len Set Code Length Array,
517 // Generate the Huffman code mapping table for Char&Len Set.
522 // Read in the Position Set Code Length Array,
523 // Generate the Huffman code mapping table for the Position Set.
525 Sd
->mBadTableFlag
= ReadPTLen (Sd
, MAXNP
, Sd
->mPBit
, (UINT16
) (-1));
526 if (Sd
->mBadTableFlag
!= 0) {
532 // Get one code according to Code&Set Huffman Table
535 Index2
= Sd
->mCTable
[Sd
->mBitBuf
>> (BITBUFSIZ
- 12)];
538 Mask
= 1U << (BITBUFSIZ
- 1 - 12);
541 if ((Sd
->mBitBuf
& Mask
) != 0) {
542 Index2
= Sd
->mRight
[Index2
];
544 Index2
= Sd
->mLeft
[Index2
];
548 } while (Index2
>= NC
);
551 // Advance what we have read
553 FillBuf (Sd
, Sd
->mCLen
[Index2
]);
559 Decode the source data and put the resulting data into the destination buffer.
561 @param Sd The global scratch data.
573 BytesRemain
= (UINT16
) (-1);
579 // Get one code from mBitBuf
581 CharC
= DecodeC (Sd
);
582 if (Sd
->mBadTableFlag
!= 0) {
588 // Process an Original character
590 if (Sd
->mOutBuf
>= Sd
->mOrigSize
) {
594 // Write orignal character into mDstBase
596 Sd
->mDstBase
[Sd
->mOutBuf
++] = (UINT8
) CharC
;
603 CharC
= (UINT16
) (CharC
- (BIT8
- THRESHOLD
));
611 // Locate string position
613 DataIdx
= Sd
->mOutBuf
- DecodeP (Sd
) - 1;
616 // Write BytesRemain of bytes into mDstBase
620 while ((INT16
) (BytesRemain
) >= 0) {
621 if (Sd
->mOutBuf
>= Sd
->mOrigSize
) {
624 if (DataIdx
>= Sd
->mOrigSize
) {
625 Sd
->mBadTableFlag
= (UINT16
) BAD_TABLE
;
628 Sd
->mDstBase
[Sd
->mOutBuf
++] = Sd
->mDstBase
[DataIdx
++];
633 // Once mOutBuf is fully filled, directly return
635 if (Sd
->mOutBuf
>= Sd
->mOrigSize
) {
646 Given a compressed source buffer, this function retrieves the size of
647 the uncompressed buffer and the size of the scratch buffer required
648 to decompress the compressed source buffer.
650 Retrieves the size of the uncompressed buffer and the temporary scratch buffer
651 required to decompress the buffer specified by Source and SourceSize.
652 If the size of the uncompressed buffer or the size of the scratch buffer cannot
653 be determined from the compressed data specified by Source and SourceData,
654 then RETURN_INVALID_PARAMETER is returned. Otherwise, the size of the uncompressed
655 buffer is returned in DestinationSize, the size of the scratch buffer is returned
656 in ScratchSize, and RETURN_SUCCESS is returned.
657 This function does not have scratch buffer available to perform a thorough
658 checking of the validity of the source data. It just retrieves the "Original Size"
659 field from the beginning bytes of the source data and output it as DestinationSize.
660 And ScratchSize is specific to the decompression implementation.
662 If Source is NULL, then ASSERT().
663 If DestinationSize is NULL, then ASSERT().
664 If ScratchSize is NULL, then ASSERT().
666 @param Source The source buffer containing the compressed data.
667 @param SourceSize The size, in bytes, of the source buffer.
668 @param DestinationSize A pointer to the size, in bytes, of the uncompressed buffer
669 that will be generated when the compressed buffer specified
670 by Source and SourceSize is decompressed.
671 @param ScratchSize A pointer to the size, in bytes, of the scratch buffer that
672 is required to decompress the compressed buffer specified
673 by Source and SourceSize.
675 @retval RETURN_SUCCESS The size of the uncompressed data was returned
676 in DestinationSize, and the size of the scratch
677 buffer was returned in ScratchSize.
678 @retval RETURN_INVALID_PARAMETER
679 The size of the uncompressed data or the size of
680 the scratch buffer cannot be determined from
681 the compressed data specified by Source
686 UefiDecompressGetInfo (
687 IN CONST VOID
*Source
,
688 IN UINT32 SourceSize
,
689 OUT UINT32
*DestinationSize
,
690 OUT UINT32
*ScratchSize
693 UINT32 CompressedSize
;
695 ASSERT (Source
!= NULL
);
696 ASSERT (DestinationSize
!= NULL
);
697 ASSERT (ScratchSize
!= NULL
);
699 if (SourceSize
< 8) {
700 return RETURN_INVALID_PARAMETER
;
703 CompressedSize
= ReadUnaligned32 ((UINT32
*)Source
);
704 if (SourceSize
< (CompressedSize
+ 8) || (CompressedSize
+ 8) < 8) {
705 return RETURN_INVALID_PARAMETER
;
708 *ScratchSize
= sizeof (SCRATCH_DATA
);
709 *DestinationSize
= ReadUnaligned32 ((UINT32
*)Source
+ 1);
711 return RETURN_SUCCESS
;
715 Decompresses a compressed source buffer.
717 Extracts decompressed data to its original form.
718 This function is designed so that the decompression algorithm can be implemented
719 without using any memory services. As a result, this function is not allowed to
720 call any memory allocation services in its implementation. It is the caller's
721 responsibility to allocate and free the Destination and Scratch buffers.
722 If the compressed source data specified by Source is successfully decompressed
723 into Destination, then RETURN_SUCCESS is returned. If the compressed source data
724 specified by Source is not in a valid compressed data format,
725 then RETURN_INVALID_PARAMETER is returned.
727 If Source is NULL, then ASSERT().
728 If Destination is NULL, then ASSERT().
729 If the required scratch buffer size > 0 and Scratch is NULL, then ASSERT().
730 If the Version is not 1 or 2, then ASSERT().
732 @param Source The source buffer containing the compressed data.
733 @param Destination The destination buffer to store the decompressed data.
734 @param Scratch A temporary scratch buffer that is used to perform the decompression.
735 This is an optional parameter that may be NULL if the
736 required scratch buffer size is 0.
737 @param Version 1 for UEFI Decompress algoruthm, 2 for Tiano Decompess algorithm.
739 @retval RETURN_SUCCESS Decompression completed successfully, and
740 the uncompressed buffer is returned in Destination.
741 @retval RETURN_INVALID_PARAMETER
742 The source buffer specified by Source is corrupted
743 (not in a valid compressed format).
746 UefiTianoDecompress (
747 IN CONST VOID
*Source
,
748 IN OUT VOID
*Destination
,
749 IN OUT VOID
*Scratch
,
759 ASSERT (Source
!= NULL
);
760 ASSERT (Destination
!= NULL
);
761 ASSERT (Scratch
!= NULL
);
762 ASSERT (Version
== 1 || Version
== 2);
767 Sd
= (SCRATCH_DATA
*) Scratch
;
769 CompSize
= Src
[0] + (Src
[1] << 8) + (Src
[2] << 16) + (Src
[3] << 24);
770 OrigSize
= Src
[4] + (Src
[5] << 8) + (Src
[6] << 16) + (Src
[7] << 24);
773 // If compressed file size is 0, return
776 return RETURN_SUCCESS
;
780 SetMem (Sd
, sizeof (SCRATCH_DATA
), 0);
783 // The length of the field 'Position Set Code Length Array Size' in Block Header.
784 // For UEFI 2.0 de/compression algorithm(Version 1), mPBit = 4
785 // For Tiano de/compression algorithm(Version 2), mPBit = 5
797 Sd
->mSrcBase
= (UINT8
*)Src
;
800 // CompSize and OrigSize are calculated in bytes
802 Sd
->mCompSize
= CompSize
;
803 Sd
->mOrigSize
= OrigSize
;
806 // Fill the first BITBUFSIZ bits
808 FillBuf (Sd
, BITBUFSIZ
);
815 if (Sd
->mBadTableFlag
!= 0) {
817 // Something wrong with the source
819 return RETURN_INVALID_PARAMETER
;
822 return RETURN_SUCCESS
;
826 Decompresses a UEFI compressed source buffer.
828 Extracts decompressed data to its original form.
829 This function is designed so that the decompression algorithm can be implemented
830 without using any memory services. As a result, this function is not allowed to
831 call any memory allocation services in its implementation. It is the caller's
832 responsibility to allocate and free the Destination and Scratch buffers.
833 If the compressed source data specified by Source is successfully decompressed
834 into Destination, then RETURN_SUCCESS is returned. If the compressed source data
835 specified by Source is not in a valid compressed data format,
836 then RETURN_INVALID_PARAMETER is returned.
838 If Source is NULL, then ASSERT().
839 If Destination is NULL, then ASSERT().
840 If the required scratch buffer size > 0 and Scratch is NULL, then ASSERT().
842 @param Source The source buffer containing the compressed data.
843 @param Destination The destination buffer to store the decompressed data
844 @param Scratch A temporary scratch buffer that is used to perform the decompression.
845 This is an optional parameter that may be NULL if the
846 required scratch buffer size is 0.
848 @retval RETURN_SUCCESS Decompression completed successfully, and
849 the uncompressed buffer is returned in Destination.
850 @retval RETURN_INVALID_PARAMETER
851 The source buffer specified by Source is corrupted
852 (not in a valid compressed format).
857 IN CONST VOID
*Source
,
858 IN OUT VOID
*Destination
,
859 IN OUT VOID
*Scratch OPTIONAL
862 return UefiTianoDecompress (Source
, Destination
, Scratch
, 1);