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