]>
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 - 2008, 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.
19 #include <Library/BaseLib.h>
20 #include <Library/UefiDecompressLib.h>
21 #include <Library/DebugLib.h>
22 #include <Library/BaseMemoryLib.h>
24 #include "BaseUefiDecompressLibInternals.h"
27 Read NumOfBit of bits from source into mBitBuf.
29 Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source.
31 @param Sd The global scratch data
32 @param NumOfBits The number of bits to shift and read.
42 // Left shift NumOfBits of bits in advance
44 Sd
->mBitBuf
= (UINT32
) (Sd
->mBitBuf
<< NumOfBits
);
47 // Copy data needed in bytes into mSbuBitBuf
49 while (NumOfBits
> Sd
->mBitCount
) {
51 Sd
->mBitBuf
|= (UINT32
) (Sd
->mSubBitBuf
<< (NumOfBits
= (UINT16
) (NumOfBits
- Sd
->mBitCount
)));
53 if (Sd
->mCompSize
> 0) {
55 // Get 1 byte into SubBitBuf
58 Sd
->mSubBitBuf
= Sd
->mSrcBase
[Sd
->mInBuf
++];
63 // No more bits from the source, just pad zero bit.
72 // Caculate additional bit count read to update mBitCount
74 Sd
->mBitCount
= (UINT16
) (Sd
->mBitCount
- NumOfBits
);
77 // Copy NumOfBits of bits from mSubBitBuf into mBitBuf
79 Sd
->mBitBuf
|= Sd
->mSubBitBuf
>> Sd
->mBitCount
;
83 Get NumOfBits of bits out from mBitBuf.
85 Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent
86 NumOfBits of bits from source. Returns NumOfBits of bits that are
89 @param Sd The global scratch data.
90 @param NumOfBits The number of bits to pop and read.
92 @return The bits that are popped out.
104 // Pop NumOfBits of Bits from Left
106 OutBits
= (UINT32
) (Sd
->mBitBuf
>> (BITBUFSIZ
- NumOfBits
));
109 // Fill up mBitBuf from source
111 FillBuf (Sd
, NumOfBits
);
117 Creates Huffman Code mapping table according to code length array.
119 Creates Huffman Code mapping table for Extra Set, Char&Len Set
120 and Position Set according to code length array.
122 @param Sd The global scratch data
123 @param NumOfChar 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.
146 volatile UINT16 Index
;
157 for (Index
= 1; Index
<= 16; Index
++) {
161 for (Index
= 0; Index
< NumOfChar
; Index
++) {
162 Count
[BitLen
[Index
]]++;
167 for (Index
= 1; Index
<= 16; Index
++) {
168 WordOfStart
= Start
[Index
];
169 WordOfCount
= Count
[Index
];
170 Start
[Index
+ 1] = (UINT16
) (WordOfStart
+ (WordOfCount
<< (16 - Index
)));
173 if (Start
[17] != 0) {
175 return (UINT16
) BAD_TABLE
;
178 JuBits
= (UINT16
) (16 - TableBits
);
180 for (Index
= 1; Index
<= TableBits
; Index
++) {
181 Start
[Index
] >>= JuBits
;
182 Weight
[Index
] = (UINT16
) (1U << (TableBits
- Index
));
185 while (Index
<= 16) {
186 Weight
[Index
] = (UINT16
) (1U << (16 - Index
));
190 Index
= (UINT16
) (Start
[TableBits
+ 1] >> JuBits
);
193 Index3
= (UINT16
) (1U << TableBits
);
194 while (Index
!= Index3
) {
200 Mask
= (UINT16
) (1U << (15 - TableBits
));
202 for (Char
= 0; Char
< NumOfChar
; Char
++) {
209 NextCode
= (UINT16
) (Start
[Len
] + Weight
[Len
]);
211 if (Len
<= TableBits
) {
213 for (Index
= Start
[Len
]; Index
< NextCode
; Index
++) {
220 Pointer
= &Table
[Index3
>> JuBits
];
221 Index
= (UINT16
) (Len
- TableBits
);
225 Sd
->mRight
[Avail
] = Sd
->mLeft
[Avail
] = 0;
229 if ((Index3
& Mask
) != 0) {
230 Pointer
= &Sd
->mRight
[*Pointer
];
232 Pointer
= &Sd
->mLeft
[*Pointer
];
243 Start
[Len
] = NextCode
;
252 Decodes a position value.
254 Get a position value according to Position Huffman Table.
256 @param Sd the global scratch data
258 @return The position value decoded.
270 Val
= Sd
->mPTTable
[Sd
->mBitBuf
>> (BITBUFSIZ
- 8)];
273 Mask
= 1U << (BITBUFSIZ
- 1 - 8);
277 if ((Sd
->mBitBuf
& Mask
) != 0) {
278 Val
= Sd
->mRight
[Val
];
280 Val
= Sd
->mLeft
[Val
];
284 } while (Val
>= MAXNP
);
287 // Advance what we have read
289 FillBuf (Sd
, Sd
->mPTLen
[Val
]);
293 Pos
= (UINT32
) ((1U << (Val
- 1)) + GetBits (Sd
, (UINT16
) (Val
- 1)));
300 Reads code lengths for the Extra Set or the Position Set.
302 Read in the Extra Set or Pointion Set Length Arrary, then
303 generate the Huffman code mapping for them.
305 @param Sd The global scratch data.
306 @param nn Number of symbols.
307 @param nbit Number of bits needed to represent nn.
308 @param Special The special symbol that needs to be taken care of.
311 @retval BAD_TABLE Table is corrupted.
324 volatile UINT16 Index
;
328 // Read Extra Set Code Length Array size
330 Number
= (UINT16
) GetBits (Sd
, nbit
);
334 // This represents only Huffman code used
336 CharC
= (UINT16
) GetBits (Sd
, nbit
);
338 for (Index
= 0; Index
< 256; Index
++) {
339 Sd
->mPTTable
[Index
] = CharC
;
342 for (Index
= 0; Index
< nn
; Index
++) {
343 Sd
->mPTLen
[Index
] = 0;
351 while (Index
< Number
) {
353 CharC
= (UINT16
) (Sd
->mBitBuf
>> (BITBUFSIZ
- 3));
356 // If a code length is less than 7, then it is encoded as a 3-bit
357 // value. Or it is encoded as a series of "1"s followed by a
358 // terminating "0". The number of "1"s = Code length - 4.
361 Mask
= 1U << (BITBUFSIZ
- 1 - 3);
362 while (Mask
& Sd
->mBitBuf
) {
368 FillBuf (Sd
, (UINT16
) ((CharC
< 7) ? 3 : CharC
- 3));
370 Sd
->mPTLen
[Index
++] = (UINT8
) CharC
;
374 // After the third length of the code length concatenation,
375 // a 2-bit value is used to indicated the number of consecutive
376 // zero lengths after the third length.
378 if (Index
== Special
) {
379 CharC
= (UINT16
) GetBits (Sd
, 2);
380 while ((INT16
) (--CharC
) >= 0) {
381 Sd
->mPTLen
[Index
++] = 0;
387 Sd
->mPTLen
[Index
++] = 0;
390 return MakeTable (Sd
, nn
, Sd
->mPTLen
, 8, Sd
->mPTTable
);
394 Reads code lengths for Char&Len Set.
396 Read in and decode the Char&Len Set Code Length Array, then
397 generate the Huffman Code mapping table for the Char&Len Set.
399 @param Sd the global scratch data
409 volatile UINT16 Index
;
412 Number
= (UINT16
) GetBits (Sd
, CBIT
);
416 // This represents only Huffman code used
418 CharC
= (UINT16
) GetBits (Sd
, CBIT
);
420 for (Index
= 0; Index
< NC
; Index
++) {
421 Sd
->mCLen
[Index
] = 0;
424 for (Index
= 0; Index
< 4096; Index
++) {
425 Sd
->mCTable
[Index
] = CharC
;
432 while (Index
< Number
) {
433 CharC
= Sd
->mPTTable
[Sd
->mBitBuf
>> (BITBUFSIZ
- 8)];
435 Mask
= 1U << (BITBUFSIZ
- 1 - 8);
439 if (Mask
& Sd
->mBitBuf
) {
440 CharC
= Sd
->mRight
[CharC
];
442 CharC
= Sd
->mLeft
[CharC
];
447 } while (CharC
>= NT
);
450 // Advance what we have read
452 FillBuf (Sd
, Sd
->mPTLen
[CharC
]);
458 } else if (CharC
== 1) {
459 CharC
= (UINT16
) (GetBits (Sd
, 4) + 3);
460 } else if (CharC
== 2) {
461 CharC
= (UINT16
) (GetBits (Sd
, CBIT
) + 20);
464 while ((INT16
) (--CharC
) >= 0) {
465 Sd
->mCLen
[Index
++] = 0;
470 Sd
->mCLen
[Index
++] = (UINT8
) (CharC
- 2);
476 Sd
->mCLen
[Index
++] = 0;
479 MakeTable (Sd
, NC
, Sd
->mCLen
, 12, Sd
->mCTable
);
485 Decode a character/length value.
487 Read one value from mBitBuf, Get one code from mBitBuf. If it is at block boundary, generates
488 Huffman code mapping table for Extra Set, Code&Len Set and
491 @param Sd The global scratch data.
493 @return The value decoded.
504 if (Sd
->mBlockSize
== 0) {
506 // Starting a new block
507 // Read BlockSize from block header
509 Sd
->mBlockSize
= (UINT16
) GetBits (Sd
, 16);
512 // Read in the Extra Set Code Length Arrary,
513 // Generate the Huffman code mapping table for Extra Set.
515 Sd
->mBadTableFlag
= ReadPTLen (Sd
, NT
, TBIT
, 3);
516 if (Sd
->mBadTableFlag
!= 0) {
521 // Read in and decode the Char&Len Set Code Length Arrary,
522 // Generate the Huffman code mapping table for Char&Len Set.
527 // Read in the Position Set Code Length Arrary,
528 // Generate the Huffman code mapping table for the Position Set.
530 Sd
->mBadTableFlag
= ReadPTLen (Sd
, MAXNP
, Sd
->mPBit
, (UINT16
) (-1));
531 if (Sd
->mBadTableFlag
!= 0) {
537 // Get one code according to Code&Set Huffman Table
540 Index2
= Sd
->mCTable
[Sd
->mBitBuf
>> (BITBUFSIZ
- 12)];
543 Mask
= 1U << (BITBUFSIZ
- 1 - 12);
546 if ((Sd
->mBitBuf
& Mask
) != 0) {
547 Index2
= Sd
->mRight
[Index2
];
549 Index2
= Sd
->mLeft
[Index2
];
553 } while (Index2
>= NC
);
556 // Advance what we have read
558 FillBuf (Sd
, Sd
->mCLen
[Index2
]);
564 Decode the source data and put the resulting data into the destination buffer.
566 @param Sd The global scratch data
578 BytesRemain
= (UINT16
) (-1);
584 // Get one code from mBitBuf
586 CharC
= DecodeC (Sd
);
587 if (Sd
->mBadTableFlag
!= 0) {
593 // Process an Original character
595 if (Sd
->mOutBuf
>= Sd
->mOrigSize
) {
599 // Write orignal character into mDstBase
601 Sd
->mDstBase
[Sd
->mOutBuf
++] = (UINT8
) CharC
;
608 CharC
= (UINT16
) (CharC
- (UINT8_MAX
+ 1 - THRESHOLD
));
616 // Locate string position
618 DataIdx
= Sd
->mOutBuf
- DecodeP (Sd
) - 1;
621 // Write BytesRemain of bytes into mDstBase
624 while ((INT16
) (BytesRemain
) >= 0) {
625 Sd
->mDstBase
[Sd
->mOutBuf
++] = Sd
->mDstBase
[DataIdx
++];
626 if (Sd
->mOutBuf
>= Sd
->mOrigSize
) {
640 Given a compressed source buffer, this function retrieves the size of
641 the uncompressed buffer and the size of the scratch buffer required
642 to decompress the compressed source buffer.
644 Retrieves the size of the uncompressed buffer and the temporary scratch buffer
645 required to decompress the buffer specified by Source and SourceSize.
646 If the size of the uncompressed buffer or the size of the scratch buffer cannot
647 be determined from the compressed data specified by Source and SourceData,
648 then RETURN_INVALID_PARAMETER is returned. Otherwise, the size of the uncompressed
649 buffer is returned in DestinationSize, the size of the scratch buffer is returned
650 in ScratchSize, and RETURN_SUCCESS is returned.
651 This function does not have scratch buffer available to perform a thorough
652 checking of the validity of the source data. It just retrieves the "Original Size"
653 field from the beginning bytes of the source data and output it as DestinationSize.
654 And ScratchSize is specific to the decompression implementation.
656 If Source is NULL, then ASSERT().
657 If DestinationSize is NULL, then ASSERT().
658 If ScratchSize is NULL, then ASSERT().
660 @param Source The source buffer containing the compressed data.
661 @param SourceSize The size, in bytes, of the source buffer.
662 @param DestinationSize A pointer to the size, in bytes, of the uncompressed buffer
663 that will be generated when the compressed buffer specified
664 by Source and SourceSize is decompressed..
665 @param ScratchSize A pointer to the size, in bytes, of the scratch buffer that
666 is required to decompress the compressed buffer specified
667 by Source and SourceSize.
669 @retval RETURN_SUCCESS The size of the uncompressed data was returned
670 in DestinationSize and the size of the scratch
671 buffer was returned in ScratchSize.
672 @retval RETURN_INVALID_PARAMETER
673 The size of the uncompressed data or the size of
674 the scratch buffer cannot be determined from
675 the compressed data specified by Source
680 UefiDecompressGetInfo (
681 IN CONST VOID
*Source
,
682 IN UINT32 SourceSize
,
683 OUT UINT32
*DestinationSize
,
684 OUT UINT32
*ScratchSize
687 UINT32 CompressedSize
;
689 ASSERT (Source
!= NULL
);
690 ASSERT (DestinationSize
!= NULL
);
691 ASSERT (ScratchSize
!= NULL
);
693 if (SourceSize
< 8) {
694 return RETURN_INVALID_PARAMETER
;
697 CompressedSize
= ReadUnaligned32 ((UINT32
*)Source
);
698 if (SourceSize
< (CompressedSize
+ 8)) {
699 return RETURN_INVALID_PARAMETER
;
702 *ScratchSize
= sizeof (SCRATCH_DATA
);
703 *DestinationSize
= ReadUnaligned32 ((UINT32
*)Source
+ 1);
705 return RETURN_SUCCESS
;
709 Decompresses a compressed source buffer.
711 Extracts decompressed data to its original form.
712 This function is designed so that the decompression algorithm can be implemented
713 without using any memory services. As a result, this function is not allowed to
714 call any memory allocation services in its implementation. It is the caller's r
715 esponsibility to allocate and free the Destination and Scratch buffers.
716 If the compressed source data specified by Source is sucessfully decompressed
717 into Destination, then RETURN_SUCCESS is returned. If the compressed source data
718 specified by Source is not in a valid compressed data format,
719 then RETURN_INVALID_PARAMETER is returned.
721 If Source is NULL, then ASSERT().
722 If Destination is NULL, then ASSERT().
723 If the required scratch buffer size > 0 and Scratch is NULL, then ASSERT().
725 @param Source The source buffer containing the compressed data.
726 @param Destination The destination buffer to store the decompressed data
727 @param Scratch A temporary scratch buffer that is used to perform the decompression.
728 This is an optional parameter that may be NULL if the
729 required scratch buffer size is 0.
731 @retval RETURN_SUCCESS Decompression completed successfully, and
732 the uncompressed buffer is returned in Destination.
733 @retval RETURN_INVALID_PARAMETER
734 The source buffer specified by Source is corrupted
735 (not in a valid compressed format).
740 IN CONST VOID
*Source
,
741 IN OUT VOID
*Destination
,
745 volatile UINT32 Index
;
752 ASSERT (Source
!= NULL
);
753 ASSERT (Destination
!= NULL
);
754 ASSERT (Scratch
!= NULL
);
759 Sd
= (SCRATCH_DATA
*) Scratch
;
761 CompSize
= Src
[0] + (Src
[1] << 8) + (Src
[2] << 16) + (Src
[3] << 24);
762 OrigSize
= Src
[4] + (Src
[5] << 8) + (Src
[6] << 16) + (Src
[7] << 24);
765 // If compressed file size is 0, return
768 return RETURN_SUCCESS
;
773 for (Index
= 0; Index
< sizeof (SCRATCH_DATA
); Index
++) {
774 ((UINT8
*) Sd
)[Index
] = 0;
777 // The length of the field 'Position Set Code Length Array Size' in Block Header.
778 // For UEFI 2.0 de/compression algorithm(Version 1), mPBit = 4
781 Sd
->mSrcBase
= (UINT8
*)Src
;
784 // CompSize and OrigSize are caculated in bytes
786 Sd
->mCompSize
= CompSize
;
787 Sd
->mOrigSize
= OrigSize
;
790 // Fill the first BITBUFSIZ bits
792 FillBuf (Sd
, BITBUFSIZ
);
799 if (Sd
->mBadTableFlag
!= 0) {
801 // Something wrong with the source
803 return RETURN_INVALID_PARAMETER
;
806 return RETURN_SUCCESS
;