]>
git.proxmox.com Git - mirror_edk2.git/blob - MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.c
2952e98b03a837a6a87441f3a8675f313ac7d2c2
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.
16 // The package level header files this module uses
20 // The protocols, PPI and GUID defintions for this module
23 // The Library classes this module consumes
25 #include <Library/UefiDecompressLib.h>
26 #include <Library/DebugLib.h>
27 #include <Library/BaseMemoryLib.h>
29 #include "BaseUefiDecompressLibInternals.h"
32 Read NumOfBit of bits from source into mBitBuf
34 Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source.
36 @param Sd The global scratch data
37 @param NumOfBits The number of bits to shift and read.
47 // Left shift NumOfBits of bits in advance
49 Sd
->mBitBuf
= (UINT32
) (Sd
->mBitBuf
<< NumOfBits
);
52 // Copy data needed in bytes into mSbuBitBuf
54 while (NumOfBits
> Sd
->mBitCount
) {
56 Sd
->mBitBuf
|= (UINT32
) (Sd
->mSubBitBuf
<< (NumOfBits
= (UINT16
) (NumOfBits
- Sd
->mBitCount
)));
58 if (Sd
->mCompSize
> 0) {
60 // Get 1 byte into SubBitBuf
63 Sd
->mSubBitBuf
= Sd
->mSrcBase
[Sd
->mInBuf
++];
68 // No more bits from the source, just pad zero bit.
77 // Caculate additional bit count read to update mBitCount
79 Sd
->mBitCount
= (UINT16
) (Sd
->mBitCount
- NumOfBits
);
82 // Copy NumOfBits of bits from mSubBitBuf into mBitBuf
84 Sd
->mBitBuf
|= Sd
->mSubBitBuf
>> Sd
->mBitCount
;
88 Get NumOfBits of bits out from mBitBuf
90 Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent
91 NumOfBits of bits from source. Returns NumOfBits of bits that are
94 @param Sd The global scratch data.
95 @param NumOfBits The number of bits to pop and read.
97 @return The bits that are popped out.
109 // Pop NumOfBits of Bits from Left
111 OutBits
= (UINT32
) (Sd
->mBitBuf
>> (BITBUFSIZ
- NumOfBits
));
114 // Fill up mBitBuf from source
116 FillBuf (Sd
, NumOfBits
);
122 Creates Huffman Code mapping table according to code length array.
124 Creates Huffman Code mapping table for Extra Set, Char&Len Set
125 and Position Set according to code length array.
127 @param Sd The global scratch data
128 @param NumOfChar Number of symbols in the symbol set
129 @param BitLen Code length array
130 @param TableBits The width of the mapping table
131 @param Table The table
134 @retval BAD_TABLE The table is corrupted.
151 volatile UINT16 Index
;
162 for (Index
= 1; Index
<= 16; Index
++) {
166 for (Index
= 0; Index
< NumOfChar
; Index
++) {
167 Count
[BitLen
[Index
]]++;
172 for (Index
= 1; Index
<= 16; Index
++) {
173 WordOfStart
= Start
[Index
];
174 WordOfCount
= Count
[Index
];
175 Start
[Index
+ 1] = (UINT16
) (WordOfStart
+ (WordOfCount
<< (16 - Index
)));
178 if (Start
[17] != 0) {
180 return (UINT16
) BAD_TABLE
;
183 JuBits
= (UINT16
) (16 - TableBits
);
185 for (Index
= 1; Index
<= TableBits
; Index
++) {
186 Start
[Index
] >>= JuBits
;
187 Weight
[Index
] = (UINT16
) (1U << (TableBits
- Index
));
190 while (Index
<= 16) {
191 Weight
[Index
] = (UINT16
) (1U << (16 - Index
));
195 Index
= (UINT16
) (Start
[TableBits
+ 1] >> JuBits
);
198 Index3
= (UINT16
) (1U << TableBits
);
199 while (Index
!= Index3
) {
205 Mask
= (UINT16
) (1U << (15 - TableBits
));
207 for (Char
= 0; Char
< NumOfChar
; Char
++) {
214 NextCode
= (UINT16
) (Start
[Len
] + Weight
[Len
]);
216 if (Len
<= TableBits
) {
218 for (Index
= Start
[Len
]; Index
< NextCode
; Index
++) {
225 Pointer
= &Table
[Index3
>> JuBits
];
226 Index
= (UINT16
) (Len
- TableBits
);
230 Sd
->mRight
[Avail
] = Sd
->mLeft
[Avail
] = 0;
235 Pointer
= &Sd
->mRight
[*Pointer
];
237 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
) {
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 Pointion Set Length Arrary, then
308 generate the Huffman code mapping for them.
310 @param Sd The global scratch data.
311 @param nn Number of symbols.
312 @param nbit 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.
329 volatile UINT16 Index
;
333 // Read Extra Set Code Length Array size
335 Number
= (UINT16
) GetBits (Sd
, nbit
);
339 // This represents only Huffman code used
341 CharC
= (UINT16
) GetBits (Sd
, nbit
);
343 for (Index
= 0; Index
< 256; Index
++) {
344 Sd
->mPTTable
[Index
] = CharC
;
347 for (Index
= 0; Index
< nn
; Index
++) {
348 Sd
->mPTLen
[Index
] = 0;
356 while (Index
< Number
) {
358 CharC
= (UINT16
) (Sd
->mBitBuf
>> (BITBUFSIZ
- 3));
361 // If a code length is less than 7, then it is encoded as a 3-bit
362 // value. Or it is encoded as a series of "1"s followed by a
363 // terminating "0". The number of "1"s = Code length - 4.
366 Mask
= 1U << (BITBUFSIZ
- 1 - 3);
367 while (Mask
& Sd
->mBitBuf
) {
373 FillBuf (Sd
, (UINT16
) ((CharC
< 7) ? 3 : CharC
- 3));
375 Sd
->mPTLen
[Index
++] = (UINT8
) CharC
;
379 // After the third length of the code length concatenation,
380 // a 2-bit value is used to indicated the number of consecutive
381 // zero lengths after the third length.
383 if (Index
== Special
) {
384 CharC
= (UINT16
) GetBits (Sd
, 2);
385 while ((INT16
) (--CharC
) >= 0) {
386 Sd
->mPTLen
[Index
++] = 0;
392 Sd
->mPTLen
[Index
++] = 0;
395 return MakeTable (Sd
, nn
, Sd
->mPTLen
, 8, Sd
->mPTTable
);
399 Reads code lengths for Char&Len Set.
401 Read in and decode the Char&Len Set Code Length Array, then
402 generate the Huffman Code mapping table for the Char&Len Set.
404 @param Sd the global scratch data
414 volatile UINT16 Index
;
417 Number
= (UINT16
) GetBits (Sd
, CBIT
);
421 // This represents only Huffman code used
423 CharC
= (UINT16
) GetBits (Sd
, CBIT
);
425 for (Index
= 0; Index
< NC
; Index
++) {
426 Sd
->mCLen
[Index
] = 0;
429 for (Index
= 0; Index
< 4096; Index
++) {
430 Sd
->mCTable
[Index
] = CharC
;
437 while (Index
< Number
) {
438 CharC
= Sd
->mPTTable
[Sd
->mBitBuf
>> (BITBUFSIZ
- 8)];
440 Mask
= 1U << (BITBUFSIZ
- 1 - 8);
444 if (Mask
& Sd
->mBitBuf
) {
445 CharC
= Sd
->mRight
[CharC
];
447 CharC
= Sd
->mLeft
[CharC
];
452 } while (CharC
>= NT
);
455 // Advance what we have read
457 FillBuf (Sd
, Sd
->mPTLen
[CharC
]);
463 } else if (CharC
== 1) {
464 CharC
= (UINT16
) (GetBits (Sd
, 4) + 3);
465 } else if (CharC
== 2) {
466 CharC
= (UINT16
) (GetBits (Sd
, CBIT
) + 20);
469 while ((INT16
) (--CharC
) >= 0) {
470 Sd
->mCLen
[Index
++] = 0;
475 Sd
->mCLen
[Index
++] = (UINT8
) (CharC
- 2);
481 Sd
->mCLen
[Index
++] = 0;
484 MakeTable (Sd
, NC
, Sd
->mCLen
, 12, Sd
->mCTable
);
490 Decode a character/length value.
492 Read one value from mBitBuf, Get one code from mBitBuf. If it is at block boundary, generates
493 Huffman code mapping table for Extra Set, Code&Len Set and
496 @param Sd The global scratch data.
498 @return The value decoded.
509 if (Sd
->mBlockSize
== 0) {
511 // Starting a new block
512 // Read BlockSize from block header
514 Sd
->mBlockSize
= (UINT16
) GetBits (Sd
, 16);
517 // Read in the Extra Set Code Length Arrary,
518 // Generate the Huffman code mapping table for Extra Set.
520 Sd
->mBadTableFlag
= ReadPTLen (Sd
, NT
, TBIT
, 3);
521 if (Sd
->mBadTableFlag
!= 0) {
526 // Read in and decode the Char&Len Set Code Length Arrary,
527 // Generate the Huffman code mapping table for Char&Len Set.
532 // Read in the Position Set Code Length Arrary,
533 // Generate the Huffman code mapping table for the Position Set.
535 Sd
->mBadTableFlag
= ReadPTLen (Sd
, MAXNP
, Sd
->mPBit
, (UINT16
) (-1));
536 if (Sd
->mBadTableFlag
!= 0) {
542 // Get one code according to Code&Set Huffman Table
545 Index2
= Sd
->mCTable
[Sd
->mBitBuf
>> (BITBUFSIZ
- 12)];
548 Mask
= 1U << (BITBUFSIZ
- 1 - 12);
551 if (Sd
->mBitBuf
& Mask
) {
552 Index2
= Sd
->mRight
[Index2
];
554 Index2
= Sd
->mLeft
[Index2
];
558 } while (Index2
>= NC
);
561 // Advance what we have read
563 FillBuf (Sd
, Sd
->mCLen
[Index2
]);
569 Decode the source data and put the resulting data into the destination buffer.
571 Decode the source data and put the resulting data into the destination buffer.
573 @param Sd The global scratch data
585 BytesRemain
= (UINT16
) (-1);
591 // Get one code from mBitBuf
593 CharC
= DecodeC (Sd
);
594 if (Sd
->mBadTableFlag
!= 0) {
600 // Process an Original character
602 if (Sd
->mOutBuf
>= Sd
->mOrigSize
) {
606 // Write orignal character into mDstBase
608 Sd
->mDstBase
[Sd
->mOutBuf
++] = (UINT8
) CharC
;
615 CharC
= (UINT16
) (CharC
- (UINT8_MAX
+ 1 - THRESHOLD
));
623 // Locate string position
625 DataIdx
= Sd
->mOutBuf
- DecodeP (Sd
) - 1;
628 // Write BytesRemain of bytes into mDstBase
631 while ((INT16
) (BytesRemain
) >= 0) {
632 Sd
->mDstBase
[Sd
->mOutBuf
++] = Sd
->mDstBase
[DataIdx
++];
633 if (Sd
->mOutBuf
>= Sd
->mOrigSize
) {
647 Retrieves the size of the uncompressed buffer and the size of the scratch buffer.
649 Retrieves the size of the uncompressed buffer and the temporary scratch buffer
650 required to decompress the buffer specified by Source and SourceSize.
651 If the size of the uncompressed buffer or the size of the scratch buffer cannot
652 be determined from the compressed data specified by Source and SourceData,
653 then RETURN_INVALID_PARAMETER is returned. Otherwise, the size of the uncompressed
654 buffer is returned in DestinationSize, the size of the scratch buffer is returned
655 in ScratchSize, and RETURN_SUCCESS is returned.
656 This function does not have scratch buffer available to perform a thorough
657 checking of the validity of the source data. It just retrieves the "Original Size"
658 field from the beginning bytes of the source data and output it as DestinationSize.
659 And ScratchSize is specific to the decompression implementation.
661 If Source is NULL, then ASSERT().
662 If DestinationSize is NULL, then ASSERT().
663 If ScratchSize is NULL, then ASSERT().
665 @param Source The source buffer containing the compressed data.
666 @param SourceSize The size, in bytes, of the source buffer.
667 @param DestinationSize A pointer to the size, in bytes, of the uncompressed buffer
668 that will be generated when the compressed buffer specified
669 by Source and SourceSize is decompressed..
670 @param ScratchSize A pointer to the size, in bytes, of the scratch buffer that
671 is required to decompress the compressed buffer specified
672 by Source and SourceSize.
674 @retval RETURN_SUCCESS The size of destination buffer and the size of scratch
675 buffer are successull retrieved.
676 @retval RETURN_INVALID_PARAMETER The source data is corrupted
681 UefiDecompressGetInfo (
682 IN CONST VOID
*Source
,
683 IN UINT32 SourceSize
,
684 OUT UINT32
*DestinationSize
,
685 OUT UINT32
*ScratchSize
688 UINT32 CompressedSize
;
690 ASSERT (Source
!= NULL
);
691 ASSERT (DestinationSize
!= NULL
);
692 ASSERT (ScratchSize
!= NULL
);
694 *ScratchSize
= sizeof (SCRATCH_DATA
);
696 if (SourceSize
< 8) {
697 return RETURN_INVALID_PARAMETER
;
700 CopyMem (&CompressedSize
, Source
, sizeof (UINT32
));
701 CopyMem (DestinationSize
, (VOID
*)((UINT8
*)Source
+ 4), sizeof (UINT32
));
703 if (SourceSize
< (CompressedSize
+ 8)) {
704 return RETURN_INVALID_PARAMETER
;
707 return RETURN_SUCCESS
;
711 Decompresses a compressed source buffer.
713 This function is designed so that the decompression algorithm can be implemented
714 without using any memory services. As a result, this function is not allowed to
715 call any memory allocation services in its implementation. It is the caller's r
716 esponsibility to allocate and free the Destination and Scratch buffers.
717 If the compressed source data specified by Source is sucessfully decompressed
718 into Destination, then RETURN_SUCCESS is returned. If the compressed source data
719 specified by Source is not in a valid compressed data format,
720 then RETURN_INVALID_PARAMETER is returned.
722 If Source is NULL, then ASSERT().
723 If Destination is NULL, then ASSERT().
724 If the required scratch buffer size > 0 and Scratch is NULL, then ASSERT().
726 @param Source The source buffer containing the compressed data.
727 @param Destination The destination buffer to store the decompressed data
728 @param Scratch A temporary scratch buffer that is used to perform the decompression.
729 This is an optional parameter that may be NULL if the
730 required scratch buffer size is 0.
732 @retval RETURN_SUCCESS Decompression is successfull
733 @retval RETURN_INVALID_PARAMETER The source data is corrupted
739 IN CONST VOID
*Source
,
740 IN OUT VOID
*Destination
,
744 volatile UINT32 Index
;
751 ASSERT (Source
!= NULL
);
752 ASSERT (Destination
!= NULL
);
753 ASSERT (Scratch
!= NULL
);
758 Sd
= (SCRATCH_DATA
*) Scratch
;
760 CompSize
= Src
[0] + (Src
[1] << 8) + (Src
[2] << 16) + (Src
[3] << 24);
761 OrigSize
= Src
[4] + (Src
[5] << 8) + (Src
[6] << 16) + (Src
[7] << 24);
764 // If compressed file size is 0, return
767 return RETURN_SUCCESS
;
772 for (Index
= 0; Index
< sizeof (SCRATCH_DATA
); Index
++) {
773 ((UINT8
*) Sd
)[Index
] = 0;
776 // The length of the field 'Position Set Code Length Array Size' in Block Header.
777 // For EFI 1.1 de/compression algorithm(Version 1), mPBit = 4
778 // For Tiano de/compression algorithm(Version 2), mPBit = 5
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
;