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 // Decompression algorithm begins here
27 // C: Char&Len Set; P: Position Set; T: exTra Set
29 #define NC (0xff + MAXMATCH + 2 - THRESHOLD)
33 #define MAXNP ((1U << MAXPBIT) - 1)
34 #define NT (CODE_BIT + 3)
42 UINT8
*mSrcBase
; ///< Starting address of compressed data
43 UINT8
*mDstBase
; ///< Starting address of decompressed data
56 UINT16 mLeft
[2 * NC
- 1];
57 UINT16 mRight
[2 * NC
- 1];
64 /// The length of the field 'Position Set Code Length Array Size' in Block Header.
65 /// For EFI 1.1 de/compression algorithm, mPBit = 4
66 /// For Tiano de/compression algorithm, mPBit = 5
72 Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source.
74 @param Sd The global scratch data
75 @param NumOfBits The number of bits to shift and read.
84 Sd
->mBitBuf
= (UINT32
) (Sd
->mBitBuf
<< NumOfBits
);
86 while (NumOfBits
> Sd
->mBitCount
) {
88 Sd
->mBitBuf
|= (UINT32
) (Sd
->mSubBitBuf
<< (NumOfBits
= (UINT16
) (NumOfBits
- Sd
->mBitCount
)));
90 if (Sd
->mCompSize
> 0) {
92 // Get 1 byte into SubBitBuf
96 Sd
->mSubBitBuf
= Sd
->mSrcBase
[Sd
->mInBuf
++];
101 // No more bits from the source, just pad zero bit.
109 Sd
->mBitCount
= (UINT16
) (Sd
->mBitCount
- NumOfBits
);
110 Sd
->mBitBuf
|= Sd
->mSubBitBuf
>> Sd
->mBitCount
;
114 Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent
115 NumOfBits of bits from source. Returns NumOfBits of bits that are
118 @param Sd The global scratch data.
119 @param NumOfBits The number of bits to pop and read.
121 @return The bits that are popped out.
132 OutBits
= (UINT32
) (Sd
->mBitBuf
>> (BITBUFSIZ
- NumOfBits
));
134 FillBuf (Sd
, NumOfBits
);
140 Creates Huffman Code mapping table according to code length array.
142 @param Sd The global scratch data
143 @param NumOfChar Number of symbols in the symbol set
144 @param BitLen Code length array
145 @param TableBits The width of the mapping table
146 @param Table The table
149 @retval BAD_TABLE The table is corrupted.
166 volatile UINT16 Index
;
174 for (Index
= 1; Index
<= 16; Index
++) {
178 for (Index
= 0; Index
< NumOfChar
; Index
++) {
179 Count
[BitLen
[Index
]]++;
184 for (Index
= 1; Index
<= 16; Index
++) {
185 Start
[Index
+ 1] = (UINT16
) (Start
[Index
] + (Count
[Index
] << (16 - Index
)));
188 if (Start
[17] != 0) {
190 return (UINT16
) BAD_TABLE
;
193 JuBits
= (UINT16
) (16 - TableBits
);
195 for (Index
= 1; Index
<= TableBits
; Index
++) {
196 Start
[Index
] >>= JuBits
;
197 Weight
[Index
] = (UINT16
) (1U << (TableBits
- Index
));
200 while (Index
<= 16) {
201 Weight
[Index
] = (UINT16
) (1U << (16 - Index
));
205 Index
= (UINT16
) (Start
[TableBits
+ 1] >> JuBits
);
208 Index3
= (UINT16
) (1U << TableBits
);
209 while (Index
!= Index3
) {
215 Mask
= (UINT16
) (1U << (15 - TableBits
));
217 for (Char
= 0; Char
< NumOfChar
; Char
++) {
224 NextCode
= (UINT16
) (Start
[Len
] + Weight
[Len
]);
226 if (Len
<= TableBits
) {
228 for (Index
= Start
[Len
]; Index
< NextCode
; Index
++) {
235 Pointer
= &Table
[Index3
>> JuBits
];
236 Index
= (UINT16
) (Len
- TableBits
);
240 Sd
->mRight
[Avail
] = Sd
->mLeft
[Avail
] = 0;
245 Pointer
= &Sd
->mRight
[*Pointer
];
247 Pointer
= &Sd
->mLeft
[*Pointer
];
258 Start
[Len
] = NextCode
;
267 Decodes a position value.
269 @param Sd the global scratch data
271 @return The position value decoded.
283 Val
= Sd
->mPTTable
[Sd
->mBitBuf
>> (BITBUFSIZ
- 8)];
286 Mask
= 1U << (BITBUFSIZ
- 1 - 8);
290 if (Sd
->mBitBuf
& Mask
) {
291 Val
= Sd
->mRight
[Val
];
293 Val
= Sd
->mLeft
[Val
];
297 } while (Val
>= MAXNP
);
300 // Advance what we have read
302 FillBuf (Sd
, Sd
->mPTLen
[Val
]);
306 Pos
= (UINT32
) ((1U << (Val
- 1)) + GetBits (Sd
, (UINT16
) (Val
- 1)));
313 Reads code lengths for the Extra Set or the Position Set.
315 @param Sd The global scratch data.
316 @param nn Number of symbols.
317 @param nbit Number of bits needed to represent nn.
318 @param Special The special symbol that needs to be taken care of.
321 @retval BAD_TABLE Table is corrupted.
334 volatile UINT16 Index
;
337 Number
= (UINT16
) GetBits (Sd
, nbit
);
340 CharC
= (UINT16
) GetBits (Sd
, nbit
);
342 for (Index
= 0; Index
< 256; Index
++) {
343 Sd
->mPTTable
[Index
] = CharC
;
346 for (Index
= 0; Index
< nn
; Index
++) {
347 Sd
->mPTLen
[Index
] = 0;
355 while (Index
< Number
) {
357 CharC
= (UINT16
) (Sd
->mBitBuf
>> (BITBUFSIZ
- 3));
360 Mask
= 1U << (BITBUFSIZ
- 1 - 3);
361 while (Mask
& Sd
->mBitBuf
) {
367 FillBuf (Sd
, (UINT16
) ((CharC
< 7) ? 3 : CharC
- 3));
369 Sd
->mPTLen
[Index
++] = (UINT8
) CharC
;
371 if (Index
== Special
) {
372 CharC
= (UINT16
) GetBits (Sd
, 2);
373 while ((INT16
) (--CharC
) >= 0) {
374 Sd
->mPTLen
[Index
++] = 0;
380 Sd
->mPTLen
[Index
++] = 0;
383 return MakeTable (Sd
, nn
, Sd
->mPTLen
, 8, Sd
->mPTTable
);
387 Reads code lengths for Char&Len Set.
389 @param Sd the global scratch data
399 volatile UINT16 Index
;
402 Number
= (UINT16
) GetBits (Sd
, CBIT
);
405 CharC
= (UINT16
) GetBits (Sd
, CBIT
);
407 for (Index
= 0; Index
< NC
; Index
++) {
408 Sd
->mCLen
[Index
] = 0;
411 for (Index
= 0; Index
< 4096; Index
++) {
412 Sd
->mCTable
[Index
] = CharC
;
419 while (Index
< Number
) {
421 CharC
= Sd
->mPTTable
[Sd
->mBitBuf
>> (BITBUFSIZ
- 8)];
423 Mask
= 1U << (BITBUFSIZ
- 1 - 8);
427 if (Mask
& Sd
->mBitBuf
) {
428 CharC
= Sd
->mRight
[CharC
];
430 CharC
= Sd
->mLeft
[CharC
];
435 } while (CharC
>= NT
);
438 // Advance what we have read
440 FillBuf (Sd
, Sd
->mPTLen
[CharC
]);
446 } else if (CharC
== 1) {
447 CharC
= (UINT16
) (GetBits (Sd
, 4) + 3);
448 } else if (CharC
== 2) {
449 CharC
= (UINT16
) (GetBits (Sd
, CBIT
) + 20);
452 while ((INT16
) (--CharC
) >= 0) {
453 Sd
->mCLen
[Index
++] = 0;
458 Sd
->mCLen
[Index
++] = (UINT8
) (CharC
- 2);
464 Sd
->mCLen
[Index
++] = 0;
467 MakeTable (Sd
, NC
, Sd
->mCLen
, 12, Sd
->mCTable
);
473 Decode a character/length value.
475 @param Sd The global scratch data.
477 @return The value decoded.
488 if (Sd
->mBlockSize
== 0) {
490 // Starting a new block
492 Sd
->mBlockSize
= (UINT16
) GetBits (Sd
, 16);
493 Sd
->mBadTableFlag
= ReadPTLen (Sd
, NT
, TBIT
, 3);
494 if (Sd
->mBadTableFlag
!= 0) {
500 Sd
->mBadTableFlag
= ReadPTLen (Sd
, MAXNP
, Sd
->mPBit
, (UINT16
) (-1));
501 if (Sd
->mBadTableFlag
!= 0) {
507 Index2
= Sd
->mCTable
[Sd
->mBitBuf
>> (BITBUFSIZ
- 12)];
510 Mask
= 1U << (BITBUFSIZ
- 1 - 12);
513 if (Sd
->mBitBuf
& Mask
) {
514 Index2
= Sd
->mRight
[Index2
];
516 Index2
= Sd
->mLeft
[Index2
];
520 } while (Index2
>= NC
);
523 // Advance what we have read
525 FillBuf (Sd
, Sd
->mCLen
[Index2
]);
531 Decode the source data and put the resulting data into the destination buffer.
533 @param Sd The global scratch data
545 BytesRemain
= (UINT16
) (-1);
550 CharC
= DecodeC (Sd
);
551 if (Sd
->mBadTableFlag
!= 0) {
557 // Process an Original character
559 if (Sd
->mOutBuf
>= Sd
->mOrigSize
) {
562 Sd
->mDstBase
[Sd
->mOutBuf
++] = (UINT8
) CharC
;
569 CharC
= (UINT16
) (CharC
- (UINT8_MAX
+ 1 - THRESHOLD
));
573 DataIdx
= Sd
->mOutBuf
- DecodeP (Sd
) - 1;
576 while ((INT16
) (BytesRemain
) >= 0) {
577 Sd
->mDstBase
[Sd
->mOutBuf
++] = Sd
->mDstBase
[DataIdx
++];
578 if (Sd
->mOutBuf
>= Sd
->mOrigSize
) {
591 The internal implementation of *_DECOMPRESS_PROTOCOL.GetInfo().
593 @param Source The source buffer containing the compressed data.
594 @param SourceSize The size of source buffer
595 @param DestinationSize The size of destination buffer.
596 @param ScratchSize The size of scratch buffer.
598 @retval RETURN_SUCCESS The size of destination buffer and the size of scratch buffer are successull retrieved.
599 @retval RETURN_INVALID_PARAMETER The source data is corrupted
604 UefiDecompressGetInfo (
605 IN CONST VOID
*Source
,
606 IN UINT32 SourceSize
,
607 OUT UINT32
*DestinationSize
,
608 OUT UINT32
*ScratchSize
611 UINT32 CompressedSize
;
613 ASSERT (Source
!= NULL
);
614 ASSERT (DestinationSize
!= NULL
);
615 ASSERT (ScratchSize
!= NULL
);
617 *ScratchSize
= sizeof (SCRATCH_DATA
);
619 if (SourceSize
< 8) {
620 return RETURN_INVALID_PARAMETER
;
623 CopyMem (&CompressedSize
, Source
, sizeof (UINT32
));
624 CopyMem (DestinationSize
, (VOID
*)((UINT8
*)Source
+ 4), sizeof (UINT32
));
626 if (SourceSize
< (CompressedSize
+ 8)) {
627 return RETURN_INVALID_PARAMETER
;
630 return RETURN_SUCCESS
;
634 The internal implementation of *_DECOMPRESS_PROTOCOL.Decompress().
636 @param Source The source buffer containing the compressed data.
637 @param Destination The destination buffer to store the decompressed data
638 @param Scratch The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.
640 @retval RETURN_SUCCESS Decompression is successfull
641 @retval RETURN_INVALID_PARAMETER The source data is corrupted
647 IN CONST VOID
*Source
,
648 IN OUT VOID
*Destination
,
652 volatile UINT32 Index
;
659 ASSERT (Source
!= NULL
);
660 ASSERT (Destination
!= NULL
);
661 ASSERT (Scratch
!= NULL
);
666 Sd
= (SCRATCH_DATA
*) Scratch
;
668 CompSize
= Src
[0] + (Src
[1] << 8) + (Src
[2] << 16) + (Src
[3] << 24);
669 OrigSize
= Src
[4] + (Src
[5] << 8) + (Src
[6] << 16) + (Src
[7] << 24);
672 // If compressed file size is 0, return
675 return RETURN_SUCCESS
;
680 for (Index
= 0; Index
< sizeof (SCRATCH_DATA
); Index
++) {
681 ((UINT8
*) Sd
)[Index
] = 0;
684 // The length of the field 'Position Set Code Length Array Size' in Block Header.
685 // For EFI 1.1 de/compression algorithm(Version 1), mPBit = 4
686 // For Tiano de/compression algorithm(Version 2), mPBit = 5
689 Sd
->mSrcBase
= (UINT8
*)Src
;
691 Sd
->mCompSize
= CompSize
;
692 Sd
->mOrigSize
= OrigSize
;
695 // Fill the first BITBUFSIZ bits
697 FillBuf (Sd
, BITBUFSIZ
);
704 if (Sd
->mBadTableFlag
!= 0) {
706 // Something wrong with the source
708 return RETURN_INVALID_PARAMETER
;
711 return RETURN_SUCCESS
;