]>
git.proxmox.com Git - mirror_edk2.git/blob - MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.c
2 UEFI Decompress Library implementation refer to UEFI specification.
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php.
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include <Library/BaseLib.h>
19 #include <Library/DebugLib.h>
20 #include <Library/BaseMemoryLib.h>
21 #include <Library/UefiDecompressLib.h>
23 #include "BaseUefiDecompressLibInternals.h"
26 Read NumOfBit of bits from source into mBitBuf.
28 Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source.
30 @param Sd The global scratch data.
31 @param NumOfBits The number of bits to shift and read.
41 // Left shift NumOfBits of bits in advance
43 Sd
->mBitBuf
= (UINT32
) LShiftU64 (((UINT64
)Sd
->mBitBuf
), NumOfBits
);
46 // Copy data needed in bytes into mSbuBitBuf
48 while (NumOfBits
> Sd
->mBitCount
) {
49 NumOfBits
= (UINT16
) (NumOfBits
- Sd
->mBitCount
);
50 Sd
->mBitBuf
|= (UINT32
) LShiftU64 (((UINT64
)Sd
->mSubBitBuf
), NumOfBits
);
52 if (Sd
->mCompSize
> 0) {
54 // Get 1 byte into SubBitBuf
57 Sd
->mSubBitBuf
= Sd
->mSrcBase
[Sd
->mInBuf
++];
62 // No more bits from the source, just pad zero bit.
71 // Calculate additional bit count read to update mBitCount
73 Sd
->mBitCount
= (UINT16
) (Sd
->mBitCount
- NumOfBits
);
76 // Copy NumOfBits of bits from mSubBitBuf into mBitBuf
78 Sd
->mBitBuf
|= Sd
->mSubBitBuf
>> Sd
->mBitCount
;
82 Get NumOfBits of bits out from mBitBuf.
84 Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent
85 NumOfBits of bits from source. Returns NumOfBits of bits that are
88 @param Sd The global scratch data.
89 @param NumOfBits The number of bits to pop and read.
91 @return The bits that are popped out.
103 // Pop NumOfBits of Bits from Left
105 OutBits
= (UINT32
) (Sd
->mBitBuf
>> (BITBUFSIZ
- NumOfBits
));
108 // Fill up mBitBuf from source
110 FillBuf (Sd
, NumOfBits
);
116 Creates Huffman Code mapping table according to code length array.
118 Creates Huffman Code mapping table for Extra Set, Char&Len Set
119 and Position Set according to code length array.
120 If TableBits > 16, then ASSERT ().
122 @param Sd The global scratch data.
123 @param NumOfChar The number of symbols in the symbol set.
124 @param BitLen Code length array.
125 @param TableBits The width of the mapping table.
126 @param Table The table to be created.
129 @retval BAD_TABLE The table is corrupted.
155 UINT16 MaxTableLength
;
158 // The maximum mapping table width supported by this internal
159 // working function is 16.
161 ASSERT (TableBits
<= 16);
163 for (Index
= 0; Index
<= 16; Index
++) {
167 for (Index
= 0; Index
< NumOfChar
; Index
++) {
168 if (BitLen
[Index
] > 16) {
169 return (UINT16
) BAD_TABLE
;
171 Count
[BitLen
[Index
]]++;
177 for (Index
= 1; Index
<= 16; Index
++) {
178 WordOfStart
= Start
[Index
];
179 WordOfCount
= Count
[Index
];
180 Start
[Index
+ 1] = (UINT16
) (WordOfStart
+ (WordOfCount
<< (16 - Index
)));
183 if (Start
[17] != 0) {
185 return (UINT16
) BAD_TABLE
;
188 JuBits
= (UINT16
) (16 - TableBits
);
191 for (Index
= 1; Index
<= TableBits
; Index
++) {
192 Start
[Index
] >>= JuBits
;
193 Weight
[Index
] = (UINT16
) (1U << (TableBits
- Index
));
196 while (Index
<= 16) {
197 Weight
[Index
] = (UINT16
) (1U << (16 - Index
));
201 Index
= (UINT16
) (Start
[TableBits
+ 1] >> JuBits
);
204 Index3
= (UINT16
) (1U << TableBits
);
205 if (Index
< Index3
) {
206 SetMem16 (Table
+ Index
, (Index3
- Index
) * sizeof (*Table
), 0);
211 Mask
= (UINT16
) (1U << (15 - TableBits
));
212 MaxTableLength
= (UINT16
) (1U << TableBits
);
214 for (Char
= 0; Char
< NumOfChar
; Char
++) {
217 if (Len
== 0 || Len
>= 17) {
221 NextCode
= (UINT16
) (Start
[Len
] + Weight
[Len
]);
223 if (Len
<= TableBits
) {
225 if (Start
[Len
] >= NextCode
|| NextCode
> MaxTableLength
){
226 return (UINT16
) BAD_TABLE
;
229 for (Index
= Start
[Len
]; Index
< NextCode
; Index
++) {
236 Pointer
= &Table
[Index3
>> JuBits
];
237 Index
= (UINT16
) (Len
- TableBits
);
240 if (*Pointer
== 0 && Avail
< (2 * NC
- 1)) {
241 Sd
->mRight
[Avail
] = Sd
->mLeft
[Avail
] = 0;
245 if (*Pointer
< (2 * NC
- 1)) {
246 if ((Index3
& Mask
) != 0) {
247 Pointer
= &Sd
->mRight
[*Pointer
];
249 Pointer
= &Sd
->mLeft
[*Pointer
];
261 Start
[Len
] = NextCode
;
270 Decodes a position value.
272 Get a position value according to Position Huffman Table.
274 @param Sd The global scratch data.
276 @return The position value decoded.
288 Val
= Sd
->mPTTable
[Sd
->mBitBuf
>> (BITBUFSIZ
- 8)];
291 Mask
= 1U << (BITBUFSIZ
- 1 - 8);
295 if ((Sd
->mBitBuf
& Mask
) != 0) {
296 Val
= Sd
->mRight
[Val
];
298 Val
= Sd
->mLeft
[Val
];
302 } while (Val
>= MAXNP
);
305 // Advance what we have read
307 FillBuf (Sd
, Sd
->mPTLen
[Val
]);
311 Pos
= (UINT32
) ((1U << (Val
- 1)) + GetBits (Sd
, (UINT16
) (Val
- 1)));
318 Reads code lengths for the Extra Set or the Position Set.
320 Read in the Extra Set or Position Set Length Array, then
321 generate the Huffman code mapping for them.
323 @param Sd The global scratch data.
324 @param nn The number of symbols.
325 @param nbit The number of bits needed to represent nn.
326 @param Special The special symbol that needs to be taken care of.
329 @retval BAD_TABLE Table is corrupted.
347 // Read Extra Set Code Length Array size
349 Number
= (UINT16
) GetBits (Sd
, nbit
);
353 // This represents only Huffman code used
355 CharC
= (UINT16
) GetBits (Sd
, nbit
);
357 SetMem16 (&Sd
->mPTTable
[0] , sizeof (Sd
->mPTTable
), CharC
);
359 SetMem (Sd
->mPTLen
, nn
, 0);
366 while (Index
< Number
&& Index
< NPT
) {
368 CharC
= (UINT16
) (Sd
->mBitBuf
>> (BITBUFSIZ
- 3));
371 // If a code length is less than 7, then it is encoded as a 3-bit
372 // value. Or it is encoded as a series of "1"s followed by a
373 // terminating "0". The number of "1"s = Code length - 4.
376 Mask
= 1U << (BITBUFSIZ
- 1 - 3);
377 while (Mask
& Sd
->mBitBuf
) {
383 FillBuf (Sd
, (UINT16
) ((CharC
< 7) ? 3 : CharC
- 3));
385 Sd
->mPTLen
[Index
++] = (UINT8
) CharC
;
389 // After the third length of the code length concatenation,
390 // a 2-bit value is used to indicated the number of consecutive
391 // zero lengths after the third length.
393 if (Index
== Special
) {
394 CharC
= (UINT16
) GetBits (Sd
, 2);
395 while ((INT16
) (--CharC
) >= 0 && Index
< NPT
) {
396 Sd
->mPTLen
[Index
++] = 0;
401 while (Index
< nn
&& Index
< NPT
) {
402 Sd
->mPTLen
[Index
++] = 0;
405 return MakeTable (Sd
, nn
, Sd
->mPTLen
, 8, Sd
->mPTTable
);
409 Reads code lengths for Char&Len Set.
411 Read in and decode the Char&Len Set Code Length Array, then
412 generate the Huffman Code mapping table for the Char&Len Set.
414 @param Sd The global scratch data.
427 Number
= (UINT16
) GetBits (Sd
, CBIT
);
431 // This represents only Huffman code used
433 CharC
= (UINT16
) GetBits (Sd
, CBIT
);
435 SetMem (Sd
->mCLen
, NC
, 0);
436 SetMem16 (&Sd
->mCTable
[0], sizeof (Sd
->mCTable
), CharC
);
442 while (Index
< Number
&& Index
< NC
) {
443 CharC
= Sd
->mPTTable
[Sd
->mBitBuf
>> (BITBUFSIZ
- 8)];
445 Mask
= 1U << (BITBUFSIZ
- 1 - 8);
449 if (Mask
& Sd
->mBitBuf
) {
450 CharC
= Sd
->mRight
[CharC
];
452 CharC
= Sd
->mLeft
[CharC
];
457 } while (CharC
>= NT
);
460 // Advance what we have read
462 FillBuf (Sd
, Sd
->mPTLen
[CharC
]);
468 } else if (CharC
== 1) {
469 CharC
= (UINT16
) (GetBits (Sd
, 4) + 3);
470 } else if (CharC
== 2) {
471 CharC
= (UINT16
) (GetBits (Sd
, CBIT
) + 20);
474 while ((INT16
) (--CharC
) >= 0 && Index
< NC
) {
475 Sd
->mCLen
[Index
++] = 0;
480 Sd
->mCLen
[Index
++] = (UINT8
) (CharC
- 2);
485 SetMem (Sd
->mCLen
+ Index
, NC
- Index
, 0);
487 MakeTable (Sd
, NC
, Sd
->mCLen
, 12, Sd
->mCTable
);
493 Decode a character/length value.
495 Read one value from mBitBuf, Get one code from mBitBuf. If it is at block boundary, generates
496 Huffman code mapping table for Extra Set, Code&Len Set and
499 @param Sd The global scratch data.
501 @return The value decoded.
512 if (Sd
->mBlockSize
== 0) {
514 // Starting a new block
515 // Read BlockSize from block header
517 Sd
->mBlockSize
= (UINT16
) GetBits (Sd
, 16);
520 // Read in the Extra Set Code Length Array,
521 // Generate the Huffman code mapping table for Extra Set.
523 Sd
->mBadTableFlag
= ReadPTLen (Sd
, NT
, TBIT
, 3);
524 if (Sd
->mBadTableFlag
!= 0) {
529 // Read in and decode the Char&Len Set Code Length Array,
530 // Generate the Huffman code mapping table for Char&Len Set.
535 // Read in the Position Set Code Length Array,
536 // Generate the Huffman code mapping table for the Position Set.
538 Sd
->mBadTableFlag
= ReadPTLen (Sd
, MAXNP
, Sd
->mPBit
, (UINT16
) (-1));
539 if (Sd
->mBadTableFlag
!= 0) {
545 // Get one code according to Code&Set Huffman Table
548 Index2
= Sd
->mCTable
[Sd
->mBitBuf
>> (BITBUFSIZ
- 12)];
551 Mask
= 1U << (BITBUFSIZ
- 1 - 12);
554 if ((Sd
->mBitBuf
& Mask
) != 0) {
555 Index2
= Sd
->mRight
[Index2
];
557 Index2
= Sd
->mLeft
[Index2
];
561 } while (Index2
>= NC
);
564 // Advance what we have read
566 FillBuf (Sd
, Sd
->mCLen
[Index2
]);
572 Decode the source data and put the resulting data into the destination buffer.
574 @param Sd The global scratch data.
586 BytesRemain
= (UINT16
) (-1);
592 // Get one code from mBitBuf
594 CharC
= DecodeC (Sd
);
595 if (Sd
->mBadTableFlag
!= 0) {
601 // Process an Original character
603 if (Sd
->mOutBuf
>= Sd
->mOrigSize
) {
607 // Write orignal character into mDstBase
609 Sd
->mDstBase
[Sd
->mOutBuf
++] = (UINT8
) CharC
;
616 CharC
= (UINT16
) (CharC
- (BIT8
- THRESHOLD
));
624 // Locate string position
626 DataIdx
= Sd
->mOutBuf
- DecodeP (Sd
) - 1;
629 // Write BytesRemain of bytes into mDstBase
633 while ((INT16
) (BytesRemain
) >= 0) {
634 if (Sd
->mOutBuf
>= Sd
->mOrigSize
) {
637 if (DataIdx
>= Sd
->mOrigSize
) {
638 Sd
->mBadTableFlag
= (UINT16
) BAD_TABLE
;
641 Sd
->mDstBase
[Sd
->mOutBuf
++] = Sd
->mDstBase
[DataIdx
++];
646 // Once mOutBuf is fully filled, directly return
648 if (Sd
->mOutBuf
>= Sd
->mOrigSize
) {
659 Given a compressed source buffer, this function retrieves the size of
660 the uncompressed buffer and the size of the scratch buffer required
661 to decompress the compressed source buffer.
663 Retrieves the size of the uncompressed buffer and the temporary scratch buffer
664 required to decompress the buffer specified by Source and SourceSize.
665 If the size of the uncompressed buffer or the size of the scratch buffer cannot
666 be determined from the compressed data specified by Source and SourceData,
667 then RETURN_INVALID_PARAMETER is returned. Otherwise, the size of the uncompressed
668 buffer is returned in DestinationSize, the size of the scratch buffer is returned
669 in ScratchSize, and RETURN_SUCCESS is returned.
670 This function does not have scratch buffer available to perform a thorough
671 checking of the validity of the source data. It just retrieves the "Original Size"
672 field from the beginning bytes of the source data and output it as DestinationSize.
673 And ScratchSize is specific to the decompression implementation.
675 If Source is NULL, then ASSERT().
676 If DestinationSize is NULL, then ASSERT().
677 If ScratchSize is NULL, then ASSERT().
679 @param Source The source buffer containing the compressed data.
680 @param SourceSize The size, in bytes, of the source buffer.
681 @param DestinationSize A pointer to the size, in bytes, of the uncompressed buffer
682 that will be generated when the compressed buffer specified
683 by Source and SourceSize is decompressed.
684 @param ScratchSize A pointer to the size, in bytes, of the scratch buffer that
685 is required to decompress the compressed buffer specified
686 by Source and SourceSize.
688 @retval RETURN_SUCCESS The size of the uncompressed data was returned
689 in DestinationSize, and the size of the scratch
690 buffer was returned in ScratchSize.
691 @retval RETURN_INVALID_PARAMETER
692 The size of the uncompressed data or the size of
693 the scratch buffer cannot be determined from
694 the compressed data specified by Source
699 UefiDecompressGetInfo (
700 IN CONST VOID
*Source
,
701 IN UINT32 SourceSize
,
702 OUT UINT32
*DestinationSize
,
703 OUT UINT32
*ScratchSize
706 UINT32 CompressedSize
;
708 ASSERT (Source
!= NULL
);
709 ASSERT (DestinationSize
!= NULL
);
710 ASSERT (ScratchSize
!= NULL
);
712 if (SourceSize
< 8) {
713 return RETURN_INVALID_PARAMETER
;
716 CompressedSize
= ReadUnaligned32 ((UINT32
*)Source
);
717 if (SourceSize
< (CompressedSize
+ 8) || (CompressedSize
+ 8) < 8) {
718 return RETURN_INVALID_PARAMETER
;
721 *ScratchSize
= sizeof (SCRATCH_DATA
);
722 *DestinationSize
= ReadUnaligned32 ((UINT32
*)Source
+ 1);
724 return RETURN_SUCCESS
;
728 Decompresses a compressed source buffer.
730 Extracts decompressed data to its original form.
731 This function is designed so that the decompression algorithm can be implemented
732 without using any memory services. As a result, this function is not allowed to
733 call any memory allocation services in its implementation. It is the caller's
734 responsibility to allocate and free the Destination and Scratch buffers.
735 If the compressed source data specified by Source is successfully decompressed
736 into Destination, then RETURN_SUCCESS is returned. If the compressed source data
737 specified by Source is not in a valid compressed data format,
738 then RETURN_INVALID_PARAMETER is returned.
740 If Source is NULL, then ASSERT().
741 If Destination is NULL, then ASSERT().
742 If the required scratch buffer size > 0 and Scratch is NULL, then ASSERT().
744 @param Source The source buffer containing the compressed data.
745 @param Destination The destination buffer to store the decompressed data.
746 @param Scratch A temporary scratch buffer that is used to perform the decompression.
747 This is an optional parameter that may be NULL if the
748 required scratch buffer size is 0.
750 @retval RETURN_SUCCESS Decompression completed successfully, and
751 the uncompressed buffer is returned in Destination.
752 @retval RETURN_INVALID_PARAMETER
753 The source buffer specified by Source is corrupted
754 (not in a valid compressed format).
759 IN CONST VOID
*Source
,
760 IN OUT VOID
*Destination
,
761 IN OUT VOID
*Scratch OPTIONAL
770 ASSERT (Source
!= NULL
);
771 ASSERT (Destination
!= NULL
);
772 ASSERT (Scratch
!= NULL
);
777 Sd
= (SCRATCH_DATA
*) Scratch
;
779 CompSize
= Src
[0] + (Src
[1] << 8) + (Src
[2] << 16) + (Src
[3] << 24);
780 OrigSize
= Src
[4] + (Src
[5] << 8) + (Src
[6] << 16) + (Src
[7] << 24);
783 // If compressed file size is 0, return
786 return RETURN_SUCCESS
;
790 SetMem (Sd
, sizeof (SCRATCH_DATA
), 0);
793 // The length of the field 'Position Set Code Length Array Size' in Block Header.
794 // For UEFI 2.0 de/compression algorithm(Version 1), mPBit = 4
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
;