]>
git.proxmox.com Git - mirror_edk2.git/blob - MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.c
2 UEFI 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.
13 Module Name: UefiDecompressLib.c
18 // The package level header files this module uses
22 // The protocols, PPI and GUID defintions for this module
25 // The Library classes this module consumes
27 #include <Library/UefiDecompressLib.h>
28 #include <Library/DebugLib.h>
29 #include <Library/BaseMemoryLib.h>
31 #include "BaseUefiDecompressLibInternals.h"
34 Read NumOfBit of bits from source into mBitBuf
36 Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source.
38 @param Sd The global scratch data
39 @param NumOfBits The number of bits to shift and read.
49 // Left shift NumOfBits of bits in advance
51 Sd
->mBitBuf
= (UINT32
) (Sd
->mBitBuf
<< NumOfBits
);
54 // Copy data needed in bytes into mSbuBitBuf
56 while (NumOfBits
> Sd
->mBitCount
) {
58 Sd
->mBitBuf
|= (UINT32
) (Sd
->mSubBitBuf
<< (NumOfBits
= (UINT16
) (NumOfBits
- Sd
->mBitCount
)));
60 if (Sd
->mCompSize
> 0) {
62 // Get 1 byte into SubBitBuf
65 Sd
->mSubBitBuf
= Sd
->mSrcBase
[Sd
->mInBuf
++];
70 // No more bits from the source, just pad zero bit.
79 // Caculate additional bit count read to update mBitCount
81 Sd
->mBitCount
= (UINT16
) (Sd
->mBitCount
- NumOfBits
);
84 // Copy NumOfBits of bits from mSubBitBuf into mBitBuf
86 Sd
->mBitBuf
|= Sd
->mSubBitBuf
>> Sd
->mBitCount
;
90 Get NumOfBits of bits out from mBitBuf
92 Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent
93 NumOfBits of bits from source. Returns NumOfBits of bits that are
96 @param Sd The global scratch data.
97 @param NumOfBits The number of bits to pop and read.
99 @return The bits that are popped out.
111 // Pop NumOfBits of Bits from Left
113 OutBits
= (UINT32
) (Sd
->mBitBuf
>> (BITBUFSIZ
- NumOfBits
));
116 // Fill up mBitBuf from source
118 FillBuf (Sd
, NumOfBits
);
124 Creates Huffman Code mapping table according to code length array.
126 Creates Huffman Code mapping table for Extra Set, Char&Len Set
127 and Position Set according to code length array.
129 @param Sd The global scratch data
130 @param NumOfChar Number of symbols in the symbol set
131 @param BitLen Code length array
132 @param TableBits The width of the mapping table
133 @param Table The table
136 @retval BAD_TABLE The table is corrupted.
153 volatile UINT16 Index
;
164 for (Index
= 1; Index
<= 16; Index
++) {
168 for (Index
= 0; Index
< NumOfChar
; Index
++) {
169 Count
[BitLen
[Index
]]++;
174 for (Index
= 1; Index
<= 16; Index
++) {
175 WordOfStart
= Start
[Index
];
176 WordOfCount
= Count
[Index
];
177 Start
[Index
+ 1] = (UINT16
) (WordOfStart
+ (WordOfCount
<< (16 - Index
)));
180 if (Start
[17] != 0) {
182 return (UINT16
) BAD_TABLE
;
185 JuBits
= (UINT16
) (16 - TableBits
);
187 for (Index
= 1; Index
<= TableBits
; Index
++) {
188 Start
[Index
] >>= JuBits
;
189 Weight
[Index
] = (UINT16
) (1U << (TableBits
- Index
));
192 while (Index
<= 16) {
193 Weight
[Index
] = (UINT16
) (1U << (16 - Index
));
197 Index
= (UINT16
) (Start
[TableBits
+ 1] >> JuBits
);
200 Index3
= (UINT16
) (1U << TableBits
);
201 while (Index
!= Index3
) {
207 Mask
= (UINT16
) (1U << (15 - TableBits
));
209 for (Char
= 0; Char
< NumOfChar
; Char
++) {
216 NextCode
= (UINT16
) (Start
[Len
] + Weight
[Len
]);
218 if (Len
<= TableBits
) {
220 for (Index
= Start
[Len
]; Index
< NextCode
; Index
++) {
227 Pointer
= &Table
[Index3
>> JuBits
];
228 Index
= (UINT16
) (Len
- TableBits
);
232 Sd
->mRight
[Avail
] = Sd
->mLeft
[Avail
] = 0;
237 Pointer
= &Sd
->mRight
[*Pointer
];
239 Pointer
= &Sd
->mLeft
[*Pointer
];
250 Start
[Len
] = NextCode
;
259 Decodes a position value.
261 Get a position value according to Position Huffman Table.
263 @param Sd the global scratch data
265 @return The position value decoded.
277 Val
= Sd
->mPTTable
[Sd
->mBitBuf
>> (BITBUFSIZ
- 8)];
280 Mask
= 1U << (BITBUFSIZ
- 1 - 8);
284 if (Sd
->mBitBuf
& Mask
) {
285 Val
= Sd
->mRight
[Val
];
287 Val
= Sd
->mLeft
[Val
];
291 } while (Val
>= MAXNP
);
294 // Advance what we have read
296 FillBuf (Sd
, Sd
->mPTLen
[Val
]);
300 Pos
= (UINT32
) ((1U << (Val
- 1)) + GetBits (Sd
, (UINT16
) (Val
- 1)));
307 Reads code lengths for the Extra Set or the Position Set.
309 Read in the Extra Set or Pointion Set Length Arrary, then
310 generate the Huffman code mapping for them.
312 @param Sd The global scratch data.
313 @param nn Number of symbols.
314 @param nbit Number of bits needed to represent nn.
315 @param Special The special symbol that needs to be taken care of.
318 @retval BAD_TABLE Table is corrupted.
331 volatile UINT16 Index
;
335 // Read Extra Set Code Length Array size
337 Number
= (UINT16
) GetBits (Sd
, nbit
);
341 // This represents only Huffman code used
343 CharC
= (UINT16
) GetBits (Sd
, nbit
);
345 for (Index
= 0; Index
< 256; Index
++) {
346 Sd
->mPTTable
[Index
] = CharC
;
349 for (Index
= 0; Index
< nn
; Index
++) {
350 Sd
->mPTLen
[Index
] = 0;
358 while (Index
< Number
) {
360 CharC
= (UINT16
) (Sd
->mBitBuf
>> (BITBUFSIZ
- 3));
363 // If a code length is less than 7, then it is encoded as a 3-bit
364 // value. Or it is encoded as a series of "1"s followed by a
365 // terminating "0". The number of "1"s = Code length - 4.
368 Mask
= 1U << (BITBUFSIZ
- 1 - 3);
369 while (Mask
& Sd
->mBitBuf
) {
375 FillBuf (Sd
, (UINT16
) ((CharC
< 7) ? 3 : CharC
- 3));
377 Sd
->mPTLen
[Index
++] = (UINT8
) CharC
;
381 // After the third length of the code length concatenation,
382 // a 2-bit value is used to indicated the number of consecutive
383 // zero lengths after the third length.
385 if (Index
== Special
) {
386 CharC
= (UINT16
) GetBits (Sd
, 2);
387 while ((INT16
) (--CharC
) >= 0) {
388 Sd
->mPTLen
[Index
++] = 0;
394 Sd
->mPTLen
[Index
++] = 0;
397 return MakeTable (Sd
, nn
, Sd
->mPTLen
, 8, Sd
->mPTTable
);
401 Reads code lengths for Char&Len Set.
403 Read in and decode the Char&Len Set Code Length Array, then
404 generate the Huffman Code mapping table for the Char&Len Set.
406 @param Sd the global scratch data
416 volatile UINT16 Index
;
419 Number
= (UINT16
) GetBits (Sd
, CBIT
);
423 // This represents only Huffman code used
425 CharC
= (UINT16
) GetBits (Sd
, CBIT
);
427 for (Index
= 0; Index
< NC
; Index
++) {
428 Sd
->mCLen
[Index
] = 0;
431 for (Index
= 0; Index
< 4096; Index
++) {
432 Sd
->mCTable
[Index
] = CharC
;
439 while (Index
< Number
) {
440 CharC
= Sd
->mPTTable
[Sd
->mBitBuf
>> (BITBUFSIZ
- 8)];
442 Mask
= 1U << (BITBUFSIZ
- 1 - 8);
446 if (Mask
& Sd
->mBitBuf
) {
447 CharC
= Sd
->mRight
[CharC
];
449 CharC
= Sd
->mLeft
[CharC
];
454 } while (CharC
>= NT
);
457 // Advance what we have read
459 FillBuf (Sd
, Sd
->mPTLen
[CharC
]);
465 } else if (CharC
== 1) {
466 CharC
= (UINT16
) (GetBits (Sd
, 4) + 3);
467 } else if (CharC
== 2) {
468 CharC
= (UINT16
) (GetBits (Sd
, CBIT
) + 20);
471 while ((INT16
) (--CharC
) >= 0) {
472 Sd
->mCLen
[Index
++] = 0;
477 Sd
->mCLen
[Index
++] = (UINT8
) (CharC
- 2);
483 Sd
->mCLen
[Index
++] = 0;
486 MakeTable (Sd
, NC
, Sd
->mCLen
, 12, Sd
->mCTable
);
492 Decode a character/length value.
494 Read one value from mBitBuf, Get one code from mBitBuf. If it is at block boundary, generates
495 Huffman code mapping table for Extra Set, Code&Len Set and
498 @param Sd The global scratch data.
500 @return The value decoded.
511 if (Sd
->mBlockSize
== 0) {
513 // Starting a new block
514 // Read BlockSize from block header
516 Sd
->mBlockSize
= (UINT16
) GetBits (Sd
, 16);
519 // Read in the Extra Set Code Length Arrary,
520 // Generate the Huffman code mapping table for Extra Set.
522 Sd
->mBadTableFlag
= ReadPTLen (Sd
, NT
, TBIT
, 3);
523 if (Sd
->mBadTableFlag
!= 0) {
528 // Read in and decode the Char&Len Set Code Length Arrary,
529 // Generate the Huffman code mapping table for Char&Len Set.
534 // Read in the Position Set Code Length Arrary,
535 // Generate the Huffman code mapping table for the Position Set.
537 Sd
->mBadTableFlag
= ReadPTLen (Sd
, MAXNP
, Sd
->mPBit
, (UINT16
) (-1));
538 if (Sd
->mBadTableFlag
!= 0) {
544 // Get one code according to Code&Set Huffman Table
547 Index2
= Sd
->mCTable
[Sd
->mBitBuf
>> (BITBUFSIZ
- 12)];
550 Mask
= 1U << (BITBUFSIZ
- 1 - 12);
553 if (Sd
->mBitBuf
& Mask
) {
554 Index2
= Sd
->mRight
[Index2
];
556 Index2
= Sd
->mLeft
[Index2
];
560 } while (Index2
>= NC
);
563 // Advance what we have read
565 FillBuf (Sd
, Sd
->mCLen
[Index2
]);
571 Decode the source data and put the resulting data into the destination buffer.
573 Decode the source data and put the resulting data into the destination buffer.
575 @param Sd The global scratch data
587 BytesRemain
= (UINT16
) (-1);
593 // Get one code from mBitBuf
595 CharC
= DecodeC (Sd
);
596 if (Sd
->mBadTableFlag
!= 0) {
602 // Process an Original character
604 if (Sd
->mOutBuf
>= Sd
->mOrigSize
) {
608 // Write orignal character into mDstBase
610 Sd
->mDstBase
[Sd
->mOutBuf
++] = (UINT8
) CharC
;
617 CharC
= (UINT16
) (CharC
- (UINT8_MAX
+ 1 - THRESHOLD
));
625 // Locate string position
627 DataIdx
= Sd
->mOutBuf
- DecodeP (Sd
) - 1;
630 // Write BytesRemain of bytes into mDstBase
633 while ((INT16
) (BytesRemain
) >= 0) {
634 Sd
->mDstBase
[Sd
->mOutBuf
++] = Sd
->mDstBase
[DataIdx
++];
635 if (Sd
->mOutBuf
>= Sd
->mOrigSize
) {
649 Retrieves the size of the uncompressed buffer and the size of the scratch buffer.
651 Retrieves the size of the uncompressed buffer and the temporary scratch buffer
652 required to decompress the buffer specified by Source and SourceSize.
653 If the size of the uncompressed buffer or the size of the scratch buffer cannot
654 be determined from the compressed data specified by Source and SourceData,
655 then RETURN_INVALID_PARAMETER is returned. Otherwise, the size of the uncompressed
656 buffer is returned in DestinationSize, the size of the scratch buffer is returned
657 in ScratchSize, and RETURN_SUCCESS is returned.
658 This function does not have scratch buffer available to perform a thorough
659 checking of the validity of the source data. It just retrieves the "Original Size"
660 field from the beginning bytes of the source data and output it as DestinationSize.
661 And ScratchSize is specific to the decompression implementation.
663 If Source is NULL, then ASSERT().
664 If DestinationSize is NULL, then ASSERT().
665 If ScratchSize is NULL, then ASSERT().
667 @param Source The source buffer containing the compressed data.
668 @param SourceSize The size, in bytes, of the source buffer.
669 @param DestinationSize A pointer to the size, in bytes, of the uncompressed buffer
670 that will be generated when the compressed buffer specified
671 by Source and SourceSize is decompressed..
672 @param ScratchSize A pointer to the size, in bytes, of the scratch buffer that
673 is required to decompress the compressed buffer specified
674 by Source and SourceSize.
676 @retval RETURN_SUCCESS The size of destination buffer and the size of scratch
677 buffer are successull retrieved.
678 @retval RETURN_INVALID_PARAMETER The source data is corrupted
683 UefiDecompressGetInfo (
684 IN CONST VOID
*Source
,
685 IN UINT32 SourceSize
,
686 OUT UINT32
*DestinationSize
,
687 OUT UINT32
*ScratchSize
690 UINT32 CompressedSize
;
692 ASSERT (Source
!= NULL
);
693 ASSERT (DestinationSize
!= NULL
);
694 ASSERT (ScratchSize
!= NULL
);
696 *ScratchSize
= sizeof (SCRATCH_DATA
);
698 if (SourceSize
< 8) {
699 return RETURN_INVALID_PARAMETER
;
702 CopyMem (&CompressedSize
, Source
, sizeof (UINT32
));
703 CopyMem (DestinationSize
, (VOID
*)((UINT8
*)Source
+ 4), sizeof (UINT32
));
705 if (SourceSize
< (CompressedSize
+ 8)) {
706 return RETURN_INVALID_PARAMETER
;
709 return RETURN_SUCCESS
;
713 Decompresses a compressed source buffer.
715 This function is designed so that the decompression algorithm can be implemented
716 without using any memory services. As a result, this function is not allowed to
717 call any memory allocation services in its implementation. It is the caller's r
718 esponsibility to allocate and free the Destination and Scratch buffers.
719 If the compressed source data specified by Source is sucessfully decompressed
720 into Destination, then RETURN_SUCCESS is returned. If the compressed source data
721 specified by Source is not in a valid compressed data format,
722 then RETURN_INVALID_PARAMETER is returned.
724 If Source is NULL, then ASSERT().
725 If Destination is NULL, then ASSERT().
726 If the required scratch buffer size > 0 and Scratch is NULL, then ASSERT().
728 @param Source The source buffer containing the compressed data.
729 @param Destination The destination buffer to store the decompressed data
730 @param Scratch A temporary scratch buffer that is used to perform the decompression.
731 This is an optional parameter that may be NULL if the
732 required scratch buffer size is 0.
734 @retval RETURN_SUCCESS Decompression is successfull
735 @retval RETURN_INVALID_PARAMETER The source data is corrupted
741 IN CONST VOID
*Source
,
742 IN OUT VOID
*Destination
,
746 volatile UINT32 Index
;
753 ASSERT (Source
!= NULL
);
754 ASSERT (Destination
!= NULL
);
755 ASSERT (Scratch
!= NULL
);
760 Sd
= (SCRATCH_DATA
*) Scratch
;
762 CompSize
= Src
[0] + (Src
[1] << 8) + (Src
[2] << 16) + (Src
[3] << 24);
763 OrigSize
= Src
[4] + (Src
[5] << 8) + (Src
[6] << 16) + (Src
[7] << 24);
766 // If compressed file size is 0, return
769 return RETURN_SUCCESS
;
774 for (Index
= 0; Index
< sizeof (SCRATCH_DATA
); Index
++) {
775 ((UINT8
*) Sd
)[Index
] = 0;
778 // The length of the field 'Position Set Code Length Array Size' in Block Header.
779 // For EFI 1.1 de/compression algorithm(Version 1), mPBit = 4
780 // For Tiano de/compression algorithm(Version 2), mPBit = 5
783 Sd
->mSrcBase
= (UINT8
*)Src
;
786 // CompSize and OrigSize are caculated in bytes
788 Sd
->mCompSize
= CompSize
;
789 Sd
->mOrigSize
= OrigSize
;
792 // Fill the first BITBUFSIZ bits
794 FillBuf (Sd
, BITBUFSIZ
);
801 if (Sd
->mBadTableFlag
!= 0) {
803 // Something wrong with the source
805 return RETURN_INVALID_PARAMETER
;
808 return RETURN_SUCCESS
;