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