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