]>
git.proxmox.com Git - mirror_edk2.git/blob - MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.c
15917a1c12b767805e6d21fad185fd50a9a233ef
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 // Include common header file for this module.
20 #include "CommonHeader.h"
22 #include "BaseUefiDecompressLibInternals.h"
25 Read NumOfBit of bits from source into mBitBuf
27 Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source.
29 @param Sd The global scratch data
30 @param NumOfBits The number of bits to shift and read.
40 // Left shift NumOfBits of bits in advance
42 Sd
->mBitBuf
= (UINT32
) (Sd
->mBitBuf
<< NumOfBits
);
45 // Copy data needed in bytes into mSbuBitBuf
47 while (NumOfBits
> Sd
->mBitCount
) {
49 Sd
->mBitBuf
|= (UINT32
) (Sd
->mSubBitBuf
<< (NumOfBits
= (UINT16
) (NumOfBits
- Sd
->mBitCount
)));
51 if (Sd
->mCompSize
> 0) {
53 // Get 1 byte into SubBitBuf
56 Sd
->mSubBitBuf
= Sd
->mSrcBase
[Sd
->mInBuf
++];
61 // No more bits from the source, just pad zero bit.
70 // Caculate additional bit count read to update mBitCount
72 Sd
->mBitCount
= (UINT16
) (Sd
->mBitCount
- NumOfBits
);
75 // Copy NumOfBits of bits from mSubBitBuf into mBitBuf
77 Sd
->mBitBuf
|= Sd
->mSubBitBuf
>> Sd
->mBitCount
;
81 Get NumOfBits of bits out from mBitBuf
83 Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent
84 NumOfBits of bits from source. Returns NumOfBits of bits that are
87 @param Sd The global scratch data.
88 @param NumOfBits The number of bits to pop and read.
90 @return The bits that are popped out.
102 // Pop NumOfBits of Bits from Left
104 OutBits
= (UINT32
) (Sd
->mBitBuf
>> (BITBUFSIZ
- NumOfBits
));
107 // Fill up mBitBuf from source
109 FillBuf (Sd
, NumOfBits
);
115 Creates Huffman Code mapping table according to code length array.
117 Creates Huffman Code mapping table for Extra Set, Char&Len Set
118 and Position Set according to code length array.
120 @param Sd The global scratch data
121 @param NumOfChar Number of symbols in the symbol set
122 @param BitLen Code length array
123 @param TableBits The width of the mapping table
124 @param Table The table
127 @retval BAD_TABLE The table is corrupted.
144 volatile UINT16 Index
;
155 for (Index
= 1; Index
<= 16; Index
++) {
159 for (Index
= 0; Index
< NumOfChar
; Index
++) {
160 Count
[BitLen
[Index
]]++;
165 for (Index
= 1; Index
<= 16; Index
++) {
166 WordOfStart
= Start
[Index
];
167 WordOfCount
= Count
[Index
];
168 Start
[Index
+ 1] = (UINT16
) (WordOfStart
+ (WordOfCount
<< (16 - Index
)));
171 if (Start
[17] != 0) {
173 return (UINT16
) BAD_TABLE
;
176 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 while (Index
!= Index3
) {
198 Mask
= (UINT16
) (1U << (15 - TableBits
));
200 for (Char
= 0; Char
< NumOfChar
; Char
++) {
207 NextCode
= (UINT16
) (Start
[Len
] + Weight
[Len
]);
209 if (Len
<= TableBits
) {
211 for (Index
= Start
[Len
]; Index
< NextCode
; Index
++) {
218 Pointer
= &Table
[Index3
>> JuBits
];
219 Index
= (UINT16
) (Len
- TableBits
);
223 Sd
->mRight
[Avail
] = Sd
->mLeft
[Avail
] = 0;
228 Pointer
= &Sd
->mRight
[*Pointer
];
230 Pointer
= &Sd
->mLeft
[*Pointer
];
241 Start
[Len
] = NextCode
;
250 Decodes a position value.
252 Get a position value according to Position Huffman Table.
254 @param Sd the global scratch data
256 @return The position value decoded.
268 Val
= Sd
->mPTTable
[Sd
->mBitBuf
>> (BITBUFSIZ
- 8)];
271 Mask
= 1U << (BITBUFSIZ
- 1 - 8);
275 if (Sd
->mBitBuf
& Mask
) {
276 Val
= Sd
->mRight
[Val
];
278 Val
= Sd
->mLeft
[Val
];
282 } while (Val
>= MAXNP
);
285 // Advance what we have read
287 FillBuf (Sd
, Sd
->mPTLen
[Val
]);
291 Pos
= (UINT32
) ((1U << (Val
- 1)) + GetBits (Sd
, (UINT16
) (Val
- 1)));
298 Reads code lengths for the Extra Set or the Position Set.
300 Read in the Extra Set or Pointion Set Length Arrary, then
301 generate the Huffman code mapping for them.
303 @param Sd The global scratch data.
304 @param nn Number of symbols.
305 @param nbit Number of bits needed to represent nn.
306 @param Special The special symbol that needs to be taken care of.
309 @retval BAD_TABLE Table is corrupted.
322 volatile UINT16 Index
;
326 // Read Extra Set Code Length Array size
328 Number
= (UINT16
) GetBits (Sd
, nbit
);
332 // This represents only Huffman code used
334 CharC
= (UINT16
) GetBits (Sd
, nbit
);
336 for (Index
= 0; Index
< 256; Index
++) {
337 Sd
->mPTTable
[Index
] = CharC
;
340 for (Index
= 0; Index
< nn
; Index
++) {
341 Sd
->mPTLen
[Index
] = 0;
349 while (Index
< Number
) {
351 CharC
= (UINT16
) (Sd
->mBitBuf
>> (BITBUFSIZ
- 3));
354 // If a code length is less than 7, then it is encoded as a 3-bit
355 // value. Or it is encoded as a series of "1"s followed by a
356 // terminating "0". The number of "1"s = Code length - 4.
359 Mask
= 1U << (BITBUFSIZ
- 1 - 3);
360 while (Mask
& Sd
->mBitBuf
) {
366 FillBuf (Sd
, (UINT16
) ((CharC
< 7) ? 3 : CharC
- 3));
368 Sd
->mPTLen
[Index
++] = (UINT8
) CharC
;
372 // After the third length of the code length concatenation,
373 // a 2-bit value is used to indicated the number of consecutive
374 // zero lengths after the third length.
376 if (Index
== Special
) {
377 CharC
= (UINT16
) GetBits (Sd
, 2);
378 while ((INT16
) (--CharC
) >= 0) {
379 Sd
->mPTLen
[Index
++] = 0;
385 Sd
->mPTLen
[Index
++] = 0;
388 return MakeTable (Sd
, nn
, Sd
->mPTLen
, 8, Sd
->mPTTable
);
392 Reads code lengths for Char&Len Set.
394 Read in and decode the Char&Len Set Code Length Array, then
395 generate the Huffman Code mapping table for the Char&Len Set.
397 @param Sd the global scratch data
407 volatile UINT16 Index
;
410 Number
= (UINT16
) GetBits (Sd
, CBIT
);
414 // This represents only Huffman code used
416 CharC
= (UINT16
) GetBits (Sd
, CBIT
);
418 for (Index
= 0; Index
< NC
; Index
++) {
419 Sd
->mCLen
[Index
] = 0;
422 for (Index
= 0; Index
< 4096; Index
++) {
423 Sd
->mCTable
[Index
] = CharC
;
430 while (Index
< Number
) {
431 CharC
= Sd
->mPTTable
[Sd
->mBitBuf
>> (BITBUFSIZ
- 8)];
433 Mask
= 1U << (BITBUFSIZ
- 1 - 8);
437 if (Mask
& Sd
->mBitBuf
) {
438 CharC
= Sd
->mRight
[CharC
];
440 CharC
= Sd
->mLeft
[CharC
];
445 } while (CharC
>= NT
);
448 // Advance what we have read
450 FillBuf (Sd
, Sd
->mPTLen
[CharC
]);
456 } else if (CharC
== 1) {
457 CharC
= (UINT16
) (GetBits (Sd
, 4) + 3);
458 } else if (CharC
== 2) {
459 CharC
= (UINT16
) (GetBits (Sd
, CBIT
) + 20);
462 while ((INT16
) (--CharC
) >= 0) {
463 Sd
->mCLen
[Index
++] = 0;
468 Sd
->mCLen
[Index
++] = (UINT8
) (CharC
- 2);
474 Sd
->mCLen
[Index
++] = 0;
477 MakeTable (Sd
, NC
, Sd
->mCLen
, 12, Sd
->mCTable
);
483 Decode a character/length value.
485 Read one value from mBitBuf, Get one code from mBitBuf. If it is at block boundary, generates
486 Huffman code mapping table for Extra Set, Code&Len Set and
489 @param Sd The global scratch data.
491 @return The value decoded.
502 if (Sd
->mBlockSize
== 0) {
504 // Starting a new block
505 // Read BlockSize from block header
507 Sd
->mBlockSize
= (UINT16
) GetBits (Sd
, 16);
510 // Read in the Extra Set Code Length Arrary,
511 // Generate the Huffman code mapping table for Extra Set.
513 Sd
->mBadTableFlag
= ReadPTLen (Sd
, NT
, TBIT
, 3);
514 if (Sd
->mBadTableFlag
!= 0) {
519 // Read in and decode the Char&Len Set Code Length Arrary,
520 // Generate the Huffman code mapping table for Char&Len Set.
525 // Read in the Position Set Code Length Arrary,
526 // Generate the Huffman code mapping table for the Position Set.
528 Sd
->mBadTableFlag
= ReadPTLen (Sd
, MAXNP
, Sd
->mPBit
, (UINT16
) (-1));
529 if (Sd
->mBadTableFlag
!= 0) {
535 // Get one code according to Code&Set Huffman Table
538 Index2
= Sd
->mCTable
[Sd
->mBitBuf
>> (BITBUFSIZ
- 12)];
541 Mask
= 1U << (BITBUFSIZ
- 1 - 12);
544 if (Sd
->mBitBuf
& Mask
) {
545 Index2
= Sd
->mRight
[Index2
];
547 Index2
= Sd
->mLeft
[Index2
];
551 } while (Index2
>= NC
);
554 // Advance what we have read
556 FillBuf (Sd
, Sd
->mCLen
[Index2
]);
562 Decode the source data and put the resulting data into the destination buffer.
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 Retrieves the size of the uncompressed buffer and the size of the scratch buffer.
642 Retrieves the size of the uncompressed buffer and the temporary scratch buffer
643 required to decompress the buffer specified by Source and SourceSize.
644 If the size of the uncompressed buffer or the size of the scratch buffer cannot
645 be determined from the compressed data specified by Source and SourceData,
646 then RETURN_INVALID_PARAMETER is returned. Otherwise, the size of the uncompressed
647 buffer is returned in DestinationSize, the size of the scratch buffer is returned
648 in ScratchSize, and RETURN_SUCCESS is returned.
649 This function does not have scratch buffer available to perform a thorough
650 checking of the validity of the source data. It just retrieves the "Original Size"
651 field from the beginning bytes of the source data and output it as DestinationSize.
652 And ScratchSize is specific to the decompression implementation.
654 If Source is NULL, then ASSERT().
655 If DestinationSize is NULL, then ASSERT().
656 If ScratchSize is NULL, then ASSERT().
658 @param Source The source buffer containing the compressed data.
659 @param SourceSize The size, in bytes, of the source buffer.
660 @param DestinationSize A pointer to the size, in bytes, of the uncompressed buffer
661 that will be generated when the compressed buffer specified
662 by Source and SourceSize is decompressed..
663 @param ScratchSize A pointer to the size, in bytes, of the scratch buffer that
664 is required to decompress the compressed buffer specified
665 by Source and SourceSize.
667 @retval RETURN_SUCCESS The size of destination buffer and the size of scratch
668 buffer are successull retrieved.
669 @retval RETURN_INVALID_PARAMETER The source data is corrupted
674 UefiDecompressGetInfo (
675 IN CONST VOID
*Source
,
676 IN UINT32 SourceSize
,
677 OUT UINT32
*DestinationSize
,
678 OUT UINT32
*ScratchSize
681 UINT32 CompressedSize
;
683 ASSERT (Source
!= NULL
);
684 ASSERT (DestinationSize
!= NULL
);
685 ASSERT (ScratchSize
!= NULL
);
687 *ScratchSize
= sizeof (SCRATCH_DATA
);
689 if (SourceSize
< 8) {
690 return RETURN_INVALID_PARAMETER
;
693 CopyMem (&CompressedSize
, Source
, sizeof (UINT32
));
694 CopyMem (DestinationSize
, (VOID
*)((UINT8
*)Source
+ 4), sizeof (UINT32
));
696 if (SourceSize
< (CompressedSize
+ 8)) {
697 return RETURN_INVALID_PARAMETER
;
700 return RETURN_SUCCESS
;
704 Decompresses a compressed source buffer.
706 This function is designed so that the decompression algorithm can be implemented
707 without using any memory services. As a result, this function is not allowed to
708 call any memory allocation services in its implementation. It is the caller's r
709 esponsibility to allocate and free the Destination and Scratch buffers.
710 If the compressed source data specified by Source is sucessfully decompressed
711 into Destination, then RETURN_SUCCESS is returned. If the compressed source data
712 specified by Source is not in a valid compressed data format,
713 then RETURN_INVALID_PARAMETER is returned.
715 If Source is NULL, then ASSERT().
716 If Destination is NULL, then ASSERT().
717 If the required scratch buffer size > 0 and Scratch is NULL, then ASSERT().
719 @param Source The source buffer containing the compressed data.
720 @param Destination The destination buffer to store the decompressed data
721 @param Scratch A temporary scratch buffer that is used to perform the decompression.
722 This is an optional parameter that may be NULL if the
723 required scratch buffer size is 0.
725 @retval RETURN_SUCCESS Decompression is successfull
726 @retval RETURN_INVALID_PARAMETER The source data is corrupted
732 IN CONST VOID
*Source
,
733 IN OUT VOID
*Destination
,
737 volatile UINT32 Index
;
744 ASSERT (Source
!= NULL
);
745 ASSERT (Destination
!= NULL
);
746 ASSERT (Scratch
!= NULL
);
751 Sd
= (SCRATCH_DATA
*) Scratch
;
753 CompSize
= Src
[0] + (Src
[1] << 8) + (Src
[2] << 16) + (Src
[3] << 24);
754 OrigSize
= Src
[4] + (Src
[5] << 8) + (Src
[6] << 16) + (Src
[7] << 24);
757 // If compressed file size is 0, return
760 return RETURN_SUCCESS
;
765 for (Index
= 0; Index
< sizeof (SCRATCH_DATA
); Index
++) {
766 ((UINT8
*) Sd
)[Index
] = 0;
769 // The length of the field 'Position Set Code Length Array Size' in Block Header.
770 // For EFI 1.1 de/compression algorithm(Version 1), mPBit = 4
771 // For Tiano de/compression algorithm(Version 2), mPBit = 5
774 Sd
->mSrcBase
= (UINT8
*)Src
;
777 // CompSize and OrigSize are caculated in bytes
779 Sd
->mCompSize
= CompSize
;
780 Sd
->mOrigSize
= OrigSize
;
783 // Fill the first BITBUFSIZ bits
785 FillBuf (Sd
, BITBUFSIZ
);
792 if (Sd
->mBadTableFlag
!= 0) {
794 // Something wrong with the source
796 return RETURN_INVALID_PARAMETER
;
799 return RETURN_SUCCESS
;