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