]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.c
Checked in part of MDE library instances following PI and UEFI. It includes:
[mirror_edk2.git] / MdePkg / Library / BaseUefiDecompressLib / BaseUefiDecompressLib.c
CommitLineData
e1f414b6 1/** @file\r
2 UEFI Decompress Library.\r
3\r
4 Copyright (c) 2006, Intel Corporation\r
5 All rights reserved. This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13 Module Name: UefiDecompressLib.c\r
14\r
15**/\r
16\r
17//\r
c7d265a9 18// The package level header files this module uses\r
e1f414b6 19//\r
c7d265a9 20#include <Base.h>\r
21//\r
22// The protocols, PPI and GUID defintions for this module\r
23//\r
24//\r
25// The Library classes this module consumes\r
26//\r
27#include <Library/UefiDecompressLib.h>\r
28#include <Library/DebugLib.h>\r
29#include <Library/BaseMemoryLib.h>\r
e1f414b6 30\r
31#include "BaseUefiDecompressLibInternals.h"\r
32\r
33/**\r
34 Read NumOfBit of bits from source into mBitBuf\r
35\r
36 Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source.\r
37\r
38 @param Sd The global scratch data\r
39 @param NumOfBits The number of bits to shift and read.\r
40\r
41**/\r
42VOID\r
43FillBuf (\r
44 IN SCRATCH_DATA *Sd,\r
45 IN UINT16 NumOfBits\r
46 )\r
47{\r
48 //\r
49 // Left shift NumOfBits of bits in advance\r
50 //\r
51 Sd->mBitBuf = (UINT32) (Sd->mBitBuf << NumOfBits);\r
52\r
53 //\r
54 // Copy data needed in bytes into mSbuBitBuf\r
55 //\r
56 while (NumOfBits > Sd->mBitCount) {\r
57\r
58 Sd->mBitBuf |= (UINT32) (Sd->mSubBitBuf << (NumOfBits = (UINT16) (NumOfBits - Sd->mBitCount)));\r
59\r
60 if (Sd->mCompSize > 0) {\r
61 //\r
62 // Get 1 byte into SubBitBuf\r
63 //\r
64 Sd->mCompSize--;\r
65 Sd->mSubBitBuf = Sd->mSrcBase[Sd->mInBuf++];\r
66 Sd->mBitCount = 8;\r
67\r
68 } else {\r
69 //\r
70 // No more bits from the source, just pad zero bit.\r
71 //\r
72 Sd->mSubBitBuf = 0;\r
73 Sd->mBitCount = 8;\r
74\r
75 }\r
76 }\r
77\r
78 //\r
79 // Caculate additional bit count read to update mBitCount\r
80 //\r
81 Sd->mBitCount = (UINT16) (Sd->mBitCount - NumOfBits);\r
82 \r
83 //\r
84 // Copy NumOfBits of bits from mSubBitBuf into mBitBuf\r
85 //\r
86 Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount;\r
87}\r
88\r
89/**\r
90 Get NumOfBits of bits out from mBitBuf\r
91\r
92 Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent \r
93 NumOfBits of bits from source. Returns NumOfBits of bits that are \r
94 popped out.\r
95\r
96 @param Sd The global scratch data.\r
97 @param NumOfBits The number of bits to pop and read.\r
98\r
99 @return The bits that are popped out.\r
100\r
101**/\r
102UINT32\r
103GetBits (\r
104 IN SCRATCH_DATA *Sd,\r
105 IN UINT16 NumOfBits\r
106 )\r
107{\r
108 UINT32 OutBits;\r
109\r
110 //\r
111 // Pop NumOfBits of Bits from Left\r
112 // \r
113 OutBits = (UINT32) (Sd->mBitBuf >> (BITBUFSIZ - NumOfBits));\r
114\r
115 //\r
116 // Fill up mBitBuf from source\r
117 //\r
118 FillBuf (Sd, NumOfBits);\r
119\r
120 return OutBits;\r
121}\r
122\r
123/**\r
124 Creates Huffman Code mapping table according to code length array.\r
125\r
126 Creates Huffman Code mapping table for Extra Set, Char&Len Set \r
127 and Position Set according to code length array.\r
128\r
129 @param Sd The global scratch data\r
130 @param NumOfChar Number of symbols in the symbol set\r
131 @param BitLen Code length array\r
132 @param TableBits The width of the mapping table\r
133 @param Table The table\r
134\r
135 @retval 0 OK.\r
136 @retval BAD_TABLE The table is corrupted.\r
137\r
138**/\r
139UINT16\r
140MakeTable (\r
141 IN SCRATCH_DATA *Sd,\r
142 IN UINT16 NumOfChar,\r
143 IN UINT8 *BitLen,\r
144 IN UINT16 TableBits,\r
145 OUT UINT16 *Table\r
146 )\r
147{\r
148 UINT16 Count[17];\r
149 UINT16 Weight[17];\r
150 UINT16 Start[18];\r
151 UINT16 *Pointer;\r
152 UINT16 Index3;\r
153 volatile UINT16 Index;\r
154 UINT16 Len;\r
155 UINT16 Char;\r
156 UINT16 JuBits;\r
157 UINT16 Avail;\r
158 UINT16 NextCode;\r
159 UINT16 Mask;\r
160 UINT16 WordOfStart;\r
161 UINT16 WordOfCount;\r
162\r
163\r
164 for (Index = 1; Index <= 16; Index++) {\r
165 Count[Index] = 0;\r
166 }\r
167\r
168 for (Index = 0; Index < NumOfChar; Index++) {\r
169 Count[BitLen[Index]]++;\r
170 }\r
171\r
172 Start[1] = 0;\r
173\r
174 for (Index = 1; Index <= 16; Index++) {\r
175 WordOfStart = Start[Index];\r
176 WordOfCount = Count[Index];\r
177 Start[Index + 1] = (UINT16) (WordOfStart + (WordOfCount << (16 - Index)));\r
178 }\r
179\r
180 if (Start[17] != 0) {\r
181 /*(1U << 16)*/\r
182 return (UINT16) BAD_TABLE;\r
183 }\r
184\r
185 JuBits = (UINT16) (16 - TableBits);\r
186\r
187 for (Index = 1; Index <= TableBits; Index++) {\r
188 Start[Index] >>= JuBits;\r
189 Weight[Index] = (UINT16) (1U << (TableBits - Index));\r
190 }\r
191\r
192 while (Index <= 16) {\r
193 Weight[Index] = (UINT16) (1U << (16 - Index));\r
194 Index++; \r
195 }\r
196\r
197 Index = (UINT16) (Start[TableBits + 1] >> JuBits);\r
198\r
199 if (Index != 0) {\r
200 Index3 = (UINT16) (1U << TableBits);\r
201 while (Index != Index3) {\r
202 Table[Index++] = 0;\r
203 }\r
204 }\r
205\r
206 Avail = NumOfChar;\r
207 Mask = (UINT16) (1U << (15 - TableBits));\r
208\r
209 for (Char = 0; Char < NumOfChar; Char++) {\r
210\r
211 Len = BitLen[Char];\r
212 if (Len == 0) {\r
213 continue;\r
214 }\r
215\r
216 NextCode = (UINT16) (Start[Len] + Weight[Len]);\r
217\r
218 if (Len <= TableBits) {\r
219\r
220 for (Index = Start[Len]; Index < NextCode; Index++) {\r
221 Table[Index] = Char;\r
222 }\r
223\r
224 } else {\r
225\r
226 Index3 = Start[Len];\r
227 Pointer = &Table[Index3 >> JuBits];\r
228 Index = (UINT16) (Len - TableBits);\r
229\r
230 while (Index != 0) {\r
231 if (*Pointer == 0) {\r
232 Sd->mRight[Avail] = Sd->mLeft[Avail] = 0;\r
233 *Pointer = Avail++;\r
234 }\r
235\r
236 if (Index3 & Mask) {\r
237 Pointer = &Sd->mRight[*Pointer];\r
238 } else {\r
239 Pointer = &Sd->mLeft[*Pointer];\r
240 }\r
241\r
242 Index3 <<= 1;\r
243 Index--;\r
244 }\r
245\r
246 *Pointer = Char;\r
247\r
248 }\r
249\r
250 Start[Len] = NextCode;\r
251 }\r
252 //\r
253 // Succeeds\r
254 //\r
255 return 0;\r
256}\r
257\r
258/**\r
259 Decodes a position value.\r
260\r
261 Get a position value according to Position Huffman Table.\r
262 \r
263 @param Sd the global scratch data\r
264\r
265 @return The position value decoded.\r
266\r
267**/\r
268UINT32\r
269DecodeP (\r
270 IN SCRATCH_DATA *Sd\r
271 )\r
272{\r
273 UINT16 Val;\r
274 UINT32 Mask;\r
275 UINT32 Pos;\r
276\r
277 Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];\r
278\r
279 if (Val >= MAXNP) {\r
280 Mask = 1U << (BITBUFSIZ - 1 - 8);\r
281\r
282 do {\r
283\r
284 if (Sd->mBitBuf & Mask) {\r
285 Val = Sd->mRight[Val];\r
286 } else {\r
287 Val = Sd->mLeft[Val];\r
288 }\r
289\r
290 Mask >>= 1;\r
291 } while (Val >= MAXNP);\r
292 }\r
293 //\r
294 // Advance what we have read\r
295 //\r
296 FillBuf (Sd, Sd->mPTLen[Val]);\r
297\r
298 Pos = Val;\r
299 if (Val > 1) {\r
300 Pos = (UINT32) ((1U << (Val - 1)) + GetBits (Sd, (UINT16) (Val - 1)));\r
301 }\r
302\r
303 return Pos;\r
304}\r
305\r
306/**\r
307 Reads code lengths for the Extra Set or the Position Set.\r
308\r
309 Read in the Extra Set or Pointion Set Length Arrary, then\r
310 generate the Huffman code mapping for them.\r
311\r
312 @param Sd The global scratch data.\r
313 @param nn Number of symbols.\r
314 @param nbit Number of bits needed to represent nn.\r
315 @param Special The special symbol that needs to be taken care of.\r
316\r
317 @retval 0 OK.\r
318 @retval BAD_TABLE Table is corrupted.\r
319\r
320**/\r
321UINT16\r
322ReadPTLen (\r
323 IN SCRATCH_DATA *Sd,\r
324 IN UINT16 nn,\r
325 IN UINT16 nbit,\r
326 IN UINT16 Special\r
327 )\r
328{\r
329 UINT16 Number;\r
330 UINT16 CharC;\r
331 volatile UINT16 Index;\r
332 UINT32 Mask;\r
333\r
334 //\r
335 // Read Extra Set Code Length Array size \r
336 //\r
337 Number = (UINT16) GetBits (Sd, nbit);\r
338\r
339 if (Number == 0) {\r
340 //\r
341 // This represents only Huffman code used\r
342 //\r
343 CharC = (UINT16) GetBits (Sd, nbit);\r
344\r
345 for (Index = 0; Index < 256; Index++) {\r
346 Sd->mPTTable[Index] = CharC;\r
347 }\r
348\r
349 for (Index = 0; Index < nn; Index++) {\r
350 Sd->mPTLen[Index] = 0;\r
351 }\r
352\r
353 return 0;\r
354 }\r
355\r
356 Index = 0;\r
357\r
358 while (Index < Number) {\r
359\r
360 CharC = (UINT16) (Sd->mBitBuf >> (BITBUFSIZ - 3));\r
361\r
362 //\r
363 // If a code length is less than 7, then it is encoded as a 3-bit\r
364 // value. Or it is encoded as a series of "1"s followed by a \r
365 // terminating "0". The number of "1"s = Code length - 4.\r
366 //\r
367 if (CharC == 7) {\r
368 Mask = 1U << (BITBUFSIZ - 1 - 3);\r
369 while (Mask & Sd->mBitBuf) {\r
370 Mask >>= 1;\r
371 CharC += 1;\r
372 }\r
373 }\r
374 \r
375 FillBuf (Sd, (UINT16) ((CharC < 7) ? 3 : CharC - 3));\r
376\r
377 Sd->mPTLen[Index++] = (UINT8) CharC;\r
378 \r
379 //\r
380 // For Code&Len Set, \r
381 // After the third length of the code length concatenation,\r
382 // a 2-bit value is used to indicated the number of consecutive \r
383 // zero lengths after the third length.\r
384 //\r
385 if (Index == Special) {\r
386 CharC = (UINT16) GetBits (Sd, 2);\r
387 while ((INT16) (--CharC) >= 0) {\r
388 Sd->mPTLen[Index++] = 0;\r
389 }\r
390 }\r
391 }\r
392\r
393 while (Index < nn) {\r
394 Sd->mPTLen[Index++] = 0;\r
395 }\r
396 \r
397 return MakeTable (Sd, nn, Sd->mPTLen, 8, Sd->mPTTable);\r
398}\r
399\r
400/**\r
401 Reads code lengths for Char&Len Set.\r
402 \r
403 Read in and decode the Char&Len Set Code Length Array, then\r
404 generate the Huffman Code mapping table for the Char&Len Set.\r
405\r
406 @param Sd the global scratch data\r
407\r
408**/\r
409VOID\r
410ReadCLen (\r
411 SCRATCH_DATA *Sd\r
412 )\r
413{\r
414 UINT16 Number;\r
415 UINT16 CharC;\r
416 volatile UINT16 Index;\r
417 UINT32 Mask;\r
418\r
419 Number = (UINT16) GetBits (Sd, CBIT);\r
420\r
421 if (Number == 0) {\r
422 //\r
423 // This represents only Huffman code used\r
424 //\r
425 CharC = (UINT16) GetBits (Sd, CBIT);\r
426\r
427 for (Index = 0; Index < NC; Index++) {\r
428 Sd->mCLen[Index] = 0;\r
429 }\r
430\r
431 for (Index = 0; Index < 4096; Index++) {\r
432 Sd->mCTable[Index] = CharC;\r
433 }\r
434\r
435 return ;\r
436 }\r
437\r
438 Index = 0;\r
439 while (Index < Number) {\r
440 CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];\r
441 if (CharC >= NT) {\r
442 Mask = 1U << (BITBUFSIZ - 1 - 8);\r
443\r
444 do {\r
445\r
446 if (Mask & Sd->mBitBuf) {\r
447 CharC = Sd->mRight[CharC];\r
448 } else {\r
449 CharC = Sd->mLeft[CharC];\r
450 }\r
451\r
452 Mask >>= 1;\r
453\r
454 } while (CharC >= NT);\r
455 }\r
456 //\r
457 // Advance what we have read\r
458 //\r
459 FillBuf (Sd, Sd->mPTLen[CharC]);\r
460\r
461 if (CharC <= 2) {\r
462\r
463 if (CharC == 0) {\r
464 CharC = 1;\r
465 } else if (CharC == 1) {\r
466 CharC = (UINT16) (GetBits (Sd, 4) + 3);\r
467 } else if (CharC == 2) {\r
468 CharC = (UINT16) (GetBits (Sd, CBIT) + 20);\r
469 }\r
470\r
471 while ((INT16) (--CharC) >= 0) {\r
472 Sd->mCLen[Index++] = 0;\r
473 }\r
474\r
475 } else {\r
476\r
477 Sd->mCLen[Index++] = (UINT8) (CharC - 2);\r
478\r
479 }\r
480 }\r
481\r
482 while (Index < NC) {\r
483 Sd->mCLen[Index++] = 0;\r
484 }\r
485\r
486 MakeTable (Sd, NC, Sd->mCLen, 12, Sd->mCTable);\r
487\r
488 return ;\r
489}\r
490\r
491/**\r
492 Decode a character/length value.\r
493 \r
494 Read one value from mBitBuf, Get one code from mBitBuf. If it is at block boundary, generates\r
495 Huffman code mapping table for Extra Set, Code&Len Set and\r
496 Position Set.\r
497\r
498 @param Sd The global scratch data.\r
499\r
500 @return The value decoded.\r
501\r
502**/\r
503UINT16\r
504DecodeC (\r
505 SCRATCH_DATA *Sd\r
506 )\r
507{\r
508 UINT16 Index2;\r
509 UINT32 Mask;\r
510\r
511 if (Sd->mBlockSize == 0) {\r
512 //\r
513 // Starting a new block\r
514 // Read BlockSize from block header\r
515 // \r
516 Sd->mBlockSize = (UINT16) GetBits (Sd, 16);\r
517\r
518 //\r
519 // Read in the Extra Set Code Length Arrary,\r
520 // Generate the Huffman code mapping table for Extra Set.\r
521 //\r
522 Sd->mBadTableFlag = ReadPTLen (Sd, NT, TBIT, 3);\r
523 if (Sd->mBadTableFlag != 0) {\r
524 return 0;\r
525 }\r
526\r
527 //\r
528 // Read in and decode the Char&Len Set Code Length Arrary,\r
529 // Generate the Huffman code mapping table for Char&Len Set.\r
530 //\r
531 ReadCLen (Sd);\r
532\r
533 //\r
534 // Read in the Position Set Code Length Arrary, \r
535 // Generate the Huffman code mapping table for the Position Set.\r
536 //\r
537 Sd->mBadTableFlag = ReadPTLen (Sd, MAXNP, Sd->mPBit, (UINT16) (-1));\r
538 if (Sd->mBadTableFlag != 0) {\r
539 return 0;\r
540 }\r
541 }\r
542\r
543 //\r
544 // Get one code according to Code&Set Huffman Table\r
545 //\r
546 Sd->mBlockSize--;\r
547 Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)];\r
548\r
549 if (Index2 >= NC) {\r
550 Mask = 1U << (BITBUFSIZ - 1 - 12);\r
551\r
552 do {\r
553 if (Sd->mBitBuf & Mask) {\r
554 Index2 = Sd->mRight[Index2];\r
555 } else {\r
556 Index2 = Sd->mLeft[Index2];\r
557 }\r
558\r
559 Mask >>= 1;\r
560 } while (Index2 >= NC);\r
561 }\r
562 //\r
563 // Advance what we have read\r
564 //\r
565 FillBuf (Sd, Sd->mCLen[Index2]);\r
566\r
567 return Index2;\r
568}\r
569\r
570/**\r
571 Decode the source data and put the resulting data into the destination buffer.\r
572\r
573 Decode the source data and put the resulting data into the destination buffer.\r
574 \r
575 @param Sd The global scratch data\r
576\r
577**/\r
578VOID\r
579Decode (\r
580 SCRATCH_DATA *Sd\r
581 )\r
582{\r
583 UINT16 BytesRemain;\r
584 UINT32 DataIdx;\r
585 UINT16 CharC;\r
586\r
587 BytesRemain = (UINT16) (-1);\r
588\r
589 DataIdx = 0;\r
590\r
591 for (;;) {\r
592 //\r
593 // Get one code from mBitBuf\r
594 // \r
595 CharC = DecodeC (Sd);\r
596 if (Sd->mBadTableFlag != 0) {\r
597 goto Done;\r
598 }\r
599\r
600 if (CharC < 256) {\r
601 //\r
602 // Process an Original character\r
603 //\r
604 if (Sd->mOutBuf >= Sd->mOrigSize) {\r
605 goto Done;\r
606 } else {\r
607 //\r
608 // Write orignal character into mDstBase\r
609 //\r
610 Sd->mDstBase[Sd->mOutBuf++] = (UINT8) CharC;\r
611 }\r
612\r
613 } else {\r
614 //\r
615 // Process a Pointer\r
616 //\r
617 CharC = (UINT16) (CharC - (UINT8_MAX + 1 - THRESHOLD));\r
618 \r
619 //\r
620 // Get string length\r
621 //\r
622 BytesRemain = CharC;\r
623\r
624 //\r
625 // Locate string position\r
626 //\r
627 DataIdx = Sd->mOutBuf - DecodeP (Sd) - 1;\r
628\r
629 //\r
630 // Write BytesRemain of bytes into mDstBase\r
631 //\r
632 BytesRemain--;\r
633 while ((INT16) (BytesRemain) >= 0) {\r
634 Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++];\r
635 if (Sd->mOutBuf >= Sd->mOrigSize) {\r
636 goto Done;\r
637 }\r
638\r
639 BytesRemain--;\r
640 }\r
641 }\r
642 }\r
643\r
644Done:\r
645 return ;\r
646}\r
647\r
648/**\r
649 Retrieves the size of the uncompressed buffer and the size of the scratch buffer.\r
650\r
651 Retrieves the size of the uncompressed buffer and the temporary scratch buffer \r
652 required to decompress the buffer specified by Source and SourceSize.\r
653 If the size of the uncompressed buffer or the size of the scratch buffer cannot\r
654 be determined from the compressed data specified by Source and SourceData, \r
655 then RETURN_INVALID_PARAMETER is returned. Otherwise, the size of the uncompressed\r
656 buffer is returned in DestinationSize, the size of the scratch buffer is returned\r
657 in ScratchSize, and RETURN_SUCCESS is returned.\r
658 This function does not have scratch buffer available to perform a thorough \r
659 checking of the validity of the source data. It just retrieves the "Original Size"\r
660 field from the beginning bytes of the source data and output it as DestinationSize.\r
661 And ScratchSize is specific to the decompression implementation.\r
662\r
663 If Source is NULL, then ASSERT().\r
664 If DestinationSize is NULL, then ASSERT().\r
665 If ScratchSize is NULL, then ASSERT().\r
666\r
667 @param Source The source buffer containing the compressed data.\r
668 @param SourceSize The size, in bytes, of the source buffer.\r
669 @param DestinationSize A pointer to the size, in bytes, of the uncompressed buffer\r
670 that will be generated when the compressed buffer specified\r
671 by Source and SourceSize is decompressed..\r
672 @param ScratchSize A pointer to the size, in bytes, of the scratch buffer that\r
673 is required to decompress the compressed buffer specified \r
674 by Source and SourceSize.\r
675\r
676 @retval RETURN_SUCCESS The size of destination buffer and the size of scratch \r
677 buffer are successull retrieved.\r
678 @retval RETURN_INVALID_PARAMETER The source data is corrupted\r
679\r
680**/\r
681RETURN_STATUS\r
682EFIAPI\r
683UefiDecompressGetInfo (\r
684 IN CONST VOID *Source,\r
685 IN UINT32 SourceSize,\r
686 OUT UINT32 *DestinationSize,\r
687 OUT UINT32 *ScratchSize\r
688 )\r
689{\r
690 UINT32 CompressedSize;\r
691\r
692 ASSERT (Source != NULL);\r
693 ASSERT (DestinationSize != NULL);\r
694 ASSERT (ScratchSize != NULL);\r
695\r
696 *ScratchSize = sizeof (SCRATCH_DATA);\r
697\r
698 if (SourceSize < 8) {\r
699 return RETURN_INVALID_PARAMETER;\r
700 }\r
701\r
702 CopyMem (&CompressedSize, Source, sizeof (UINT32));\r
703 CopyMem (DestinationSize, (VOID *)((UINT8 *)Source + 4), sizeof (UINT32));\r
704\r
705 if (SourceSize < (CompressedSize + 8)) {\r
706 return RETURN_INVALID_PARAMETER;\r
707 }\r
708\r
709 return RETURN_SUCCESS;\r
710}\r
711\r
712/**\r
713 Decompresses a compressed source buffer.\r
714\r
715 This function is designed so that the decompression algorithm can be implemented\r
716 without using any memory services. As a result, this function is not allowed to\r
717 call any memory allocation services in its implementation. It is the caller's r\r
718 esponsibility to allocate and free the Destination and Scratch buffers.\r
719 If the compressed source data specified by Source is sucessfully decompressed \r
720 into Destination, then RETURN_SUCCESS is returned. If the compressed source data \r
721 specified by Source is not in a valid compressed data format,\r
722 then RETURN_INVALID_PARAMETER is returned.\r
723\r
724 If Source is NULL, then ASSERT().\r
725 If Destination is NULL, then ASSERT().\r
726 If the required scratch buffer size > 0 and Scratch is NULL, then ASSERT().\r
727\r
728 @param Source The source buffer containing the compressed data.\r
729 @param Destination The destination buffer to store the decompressed data\r
730 @param Scratch A temporary scratch buffer that is used to perform the decompression.\r
731 This is an optional parameter that may be NULL if the \r
732 required scratch buffer size is 0.\r
733 \r
734 @retval RETURN_SUCCESS Decompression is successfull\r
735 @retval RETURN_INVALID_PARAMETER The source data is corrupted\r
736\r
737**/\r
738RETURN_STATUS\r
739EFIAPI\r
740UefiDecompress (\r
741 IN CONST VOID *Source,\r
742 IN OUT VOID *Destination,\r
743 IN OUT VOID *Scratch\r
744 )\r
745{\r
746 volatile UINT32 Index;\r
747 UINT32 CompSize;\r
748 UINT32 OrigSize;\r
749 SCRATCH_DATA *Sd;\r
750 CONST UINT8 *Src;\r
751 UINT8 *Dst;\r
752\r
753 ASSERT (Source != NULL);\r
754 ASSERT (Destination != NULL);\r
755 ASSERT (Scratch != NULL);\r
756\r
757 Src = Source;\r
758 Dst = Destination;\r
759\r
760 Sd = (SCRATCH_DATA *) Scratch;\r
761\r
762 CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24);\r
763 OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);\r
764\r
765 //\r
766 // If compressed file size is 0, return\r
767 //\r
768 if (OrigSize == 0) {\r
769 return RETURN_SUCCESS;\r
770 }\r
771\r
772 Src = Src + 8;\r
773\r
774 for (Index = 0; Index < sizeof (SCRATCH_DATA); Index++) {\r
775 ((UINT8 *) Sd)[Index] = 0;\r
776 }\r
777 //\r
778 // The length of the field 'Position Set Code Length Array Size' in Block Header.\r
779 // For EFI 1.1 de/compression algorithm(Version 1), mPBit = 4\r
780 // For Tiano de/compression algorithm(Version 2), mPBit = 5\r
781 //\r
782 Sd->mPBit = 4;\r
783 Sd->mSrcBase = (UINT8 *)Src;\r
784 Sd->mDstBase = Dst;\r
785 //\r
786 // CompSize and OrigSize are caculated in bytes\r
787 //\r
788 Sd->mCompSize = CompSize;\r
789 Sd->mOrigSize = OrigSize;\r
790\r
791 //\r
792 // Fill the first BITBUFSIZ bits\r
793 //\r
794 FillBuf (Sd, BITBUFSIZ);\r
795\r
796 //\r
797 // Decompress it\r
798 //\r
799 Decode (Sd);\r
800\r
801 if (Sd->mBadTableFlag != 0) {\r
802 //\r
803 // Something wrong with the source\r
804 //\r
805 return RETURN_INVALID_PARAMETER;\r
806 }\r
807\r
808 return RETURN_SUCCESS;\r
809}\r