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