]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[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
8028f030
SZ
225 if (Start[Len] >= NextCode || NextCode > MaxTableLength){\r
226 return (UINT16) BAD_TABLE;\r
227 }\r
228\r
e1f414b6 229 for (Index = Start[Len]; Index < NextCode; Index++) {\r
230 Table[Index] = Char;\r
231 }\r
232\r
233 } else {\r
234\r
235 Index3 = Start[Len];\r
236 Pointer = &Table[Index3 >> JuBits];\r
237 Index = (UINT16) (Len - TableBits);\r
238\r
239 while (Index != 0) {\r
0ba7fffd 240 if (*Pointer == 0 && Avail < (2 * NC - 1)) {\r
9872985b 241 Sd->mRight[Avail] = Sd->mLeft[Avail] = 0;\r
e1f414b6 242 *Pointer = Avail++;\r
243 }\r
9095d37b 244\r
29666911
LG
245 if (*Pointer < (2 * NC - 1)) {\r
246 if ((Index3 & Mask) != 0) {\r
247 Pointer = &Sd->mRight[*Pointer];\r
248 } else {\r
249 Pointer = &Sd->mLeft[*Pointer];\r
250 }\r
e1f414b6 251 }\r
252\r
253 Index3 <<= 1;\r
254 Index--;\r
255 }\r
256\r
257 *Pointer = Char;\r
258\r
259 }\r
260\r
261 Start[Len] = NextCode;\r
262 }\r
263 //\r
264 // Succeeds\r
265 //\r
266 return 0;\r
267}\r
268\r
269/**\r
270 Decodes a position value.\r
271\r
272 Get a position value according to Position Huffman Table.\r
efb23117 273\r
58380e9c 274 @param Sd The global scratch data.\r
e1f414b6 275\r
276 @return The position value decoded.\r
277\r
278**/\r
279UINT32\r
280DecodeP (\r
281 IN SCRATCH_DATA *Sd\r
282 )\r
283{\r
284 UINT16 Val;\r
285 UINT32 Mask;\r
286 UINT32 Pos;\r
287\r
288 Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];\r
289\r
290 if (Val >= MAXNP) {\r
291 Mask = 1U << (BITBUFSIZ - 1 - 8);\r
292\r
293 do {\r
294\r
eceb3a4c 295 if ((Sd->mBitBuf & Mask) != 0) {\r
e1f414b6 296 Val = Sd->mRight[Val];\r
297 } else {\r
298 Val = Sd->mLeft[Val];\r
299 }\r
300\r
301 Mask >>= 1;\r
302 } while (Val >= MAXNP);\r
303 }\r
304 //\r
305 // Advance what we have read\r
306 //\r
307 FillBuf (Sd, Sd->mPTLen[Val]);\r
308\r
309 Pos = Val;\r
310 if (Val > 1) {\r
311 Pos = (UINT32) ((1U << (Val - 1)) + GetBits (Sd, (UINT16) (Val - 1)));\r
312 }\r
313\r
314 return Pos;\r
315}\r
316\r
317/**\r
318 Reads code lengths for the Extra Set or the Position Set.\r
319\r
a750b4ae 320 Read in the Extra Set or Position Set Length Array, then\r
e1f414b6 321 generate the Huffman code mapping for them.\r
322\r
323 @param Sd The global scratch data.\r
2fc59a00 324 @param nn The number of symbols.\r
325 @param nbit The number of bits needed to represent nn.\r
e1f414b6 326 @param Special The special symbol that needs to be taken care of.\r
327\r
328 @retval 0 OK.\r
329 @retval BAD_TABLE Table is corrupted.\r
330\r
331**/\r
332UINT16\r
333ReadPTLen (\r
334 IN SCRATCH_DATA *Sd,\r
335 IN UINT16 nn,\r
336 IN UINT16 nbit,\r
337 IN UINT16 Special\r
338 )\r
339{\r
340 UINT16 Number;\r
341 UINT16 CharC;\r
02313d1e 342 UINT16 Index;\r
e1f414b6 343 UINT32 Mask;\r
344\r
6afd9f45 345 ASSERT (nn <= NPT);\r
e1f414b6 346 //\r
9095d37b 347 // Read Extra Set Code Length Array size\r
e1f414b6 348 //\r
349 Number = (UINT16) GetBits (Sd, nbit);\r
350\r
351 if (Number == 0) {\r
352 //\r
353 // This represents only Huffman code used\r
354 //\r
355 CharC = (UINT16) GetBits (Sd, nbit);\r
356\r
ebd04fc2 357 SetMem16 (&Sd->mPTTable[0] , sizeof (Sd->mPTTable), CharC);\r
e1f414b6 358\r
02313d1e 359 SetMem (Sd->mPTLen, nn, 0);\r
e1f414b6 360\r
361 return 0;\r
362 }\r
363\r
364 Index = 0;\r
365\r
9872985b 366 while (Index < Number && Index < NPT) {\r
e1f414b6 367\r
368 CharC = (UINT16) (Sd->mBitBuf >> (BITBUFSIZ - 3));\r
369\r
370 //\r
371 // If a code length is less than 7, then it is encoded as a 3-bit\r
9095d37b 372 // value. Or it is encoded as a series of "1"s followed by a\r
e1f414b6 373 // terminating "0". The number of "1"s = Code length - 4.\r
374 //\r
375 if (CharC == 7) {\r
376 Mask = 1U << (BITBUFSIZ - 1 - 3);\r
377 while (Mask & Sd->mBitBuf) {\r
378 Mask >>= 1;\r
379 CharC += 1;\r
380 }\r
381 }\r
9095d37b 382\r
e1f414b6 383 FillBuf (Sd, (UINT16) ((CharC < 7) ? 3 : CharC - 3));\r
384\r
385 Sd->mPTLen[Index++] = (UINT8) CharC;\r
9095d37b 386\r
e1f414b6 387 //\r
9095d37b 388 // For Code&Len Set,\r
e1f414b6 389 // After the third length of the code length concatenation,\r
9095d37b 390 // a 2-bit value is used to indicated the number of consecutive\r
e1f414b6 391 // zero lengths after the third length.\r
392 //\r
393 if (Index == Special) {\r
394 CharC = (UINT16) GetBits (Sd, 2);\r
0ba7fffd 395 while ((INT16) (--CharC) >= 0 && Index < NPT) {\r
e1f414b6 396 Sd->mPTLen[Index++] = 0;\r
397 }\r
398 }\r
399 }\r
400\r
9872985b 401 while (Index < nn && Index < NPT) {\r
e1f414b6 402 Sd->mPTLen[Index++] = 0;\r
403 }\r
9095d37b 404\r
e1f414b6 405 return MakeTable (Sd, nn, Sd->mPTLen, 8, Sd->mPTTable);\r
406}\r
407\r
408/**\r
409 Reads code lengths for Char&Len Set.\r
efb23117 410\r
e1f414b6 411 Read in and decode the Char&Len Set Code Length Array, then\r
412 generate the Huffman Code mapping table for the Char&Len Set.\r
413\r
58380e9c 414 @param Sd The global scratch data.\r
e1f414b6 415\r
416**/\r
417VOID\r
418ReadCLen (\r
419 SCRATCH_DATA *Sd\r
420 )\r
421{\r
422 UINT16 Number;\r
423 UINT16 CharC;\r
02313d1e 424 UINT16 Index;\r
e1f414b6 425 UINT32 Mask;\r
426\r
427 Number = (UINT16) GetBits (Sd, CBIT);\r
428\r
429 if (Number == 0) {\r
430 //\r
431 // This represents only Huffman code used\r
432 //\r
433 CharC = (UINT16) GetBits (Sd, CBIT);\r
434\r
02313d1e 435 SetMem (Sd->mCLen, NC, 0);\r
ebd04fc2 436 SetMem16 (&Sd->mCTable[0], sizeof (Sd->mCTable), CharC);\r
e1f414b6 437\r
438 return ;\r
439 }\r
440\r
441 Index = 0;\r
9872985b 442 while (Index < Number && Index < NC) {\r
e1f414b6 443 CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];\r
444 if (CharC >= NT) {\r
445 Mask = 1U << (BITBUFSIZ - 1 - 8);\r
446\r
447 do {\r
448\r
449 if (Mask & Sd->mBitBuf) {\r
450 CharC = Sd->mRight[CharC];\r
451 } else {\r
452 CharC = Sd->mLeft[CharC];\r
453 }\r
454\r
455 Mask >>= 1;\r
456\r
457 } while (CharC >= NT);\r
458 }\r
459 //\r
460 // Advance what we have read\r
461 //\r
462 FillBuf (Sd, Sd->mPTLen[CharC]);\r
463\r
464 if (CharC <= 2) {\r
465\r
466 if (CharC == 0) {\r
467 CharC = 1;\r
468 } else if (CharC == 1) {\r
469 CharC = (UINT16) (GetBits (Sd, 4) + 3);\r
470 } else if (CharC == 2) {\r
471 CharC = (UINT16) (GetBits (Sd, CBIT) + 20);\r
472 }\r
473\r
0ba7fffd 474 while ((INT16) (--CharC) >= 0 && Index < NC) {\r
e1f414b6 475 Sd->mCLen[Index++] = 0;\r
476 }\r
477\r
478 } else {\r
479\r
480 Sd->mCLen[Index++] = (UINT8) (CharC - 2);\r
481\r
482 }\r
483 }\r
484\r
02313d1e 485 SetMem (Sd->mCLen + Index, NC - Index, 0);\r
e1f414b6 486\r
487 MakeTable (Sd, NC, Sd->mCLen, 12, Sd->mCTable);\r
488\r
489 return ;\r
490}\r
491\r
492/**\r
493 Decode a character/length value.\r
efb23117 494\r
e1f414b6 495 Read one value from mBitBuf, Get one code from mBitBuf. If it is at block boundary, generates\r
496 Huffman code mapping table for Extra Set, Code&Len Set and\r
497 Position Set.\r
498\r
499 @param Sd The global scratch data.\r
500\r
501 @return The value decoded.\r
502\r
503**/\r
504UINT16\r
505DecodeC (\r
506 SCRATCH_DATA *Sd\r
507 )\r
508{\r
509 UINT16 Index2;\r
510 UINT32 Mask;\r
511\r
512 if (Sd->mBlockSize == 0) {\r
513 //\r
514 // Starting a new block\r
515 // Read BlockSize from block header\r
9095d37b 516 //\r
e1f414b6 517 Sd->mBlockSize = (UINT16) GetBits (Sd, 16);\r
518\r
519 //\r
a750b4ae 520 // Read in the Extra Set Code Length Array,\r
e1f414b6 521 // Generate the Huffman code mapping table for Extra Set.\r
522 //\r
523 Sd->mBadTableFlag = ReadPTLen (Sd, NT, TBIT, 3);\r
524 if (Sd->mBadTableFlag != 0) {\r
525 return 0;\r
526 }\r
527\r
528 //\r
a750b4ae 529 // Read in and decode the Char&Len Set Code Length Array,\r
e1f414b6 530 // Generate the Huffman code mapping table for Char&Len Set.\r
531 //\r
532 ReadCLen (Sd);\r
533\r
534 //\r
a750b4ae 535 // Read in the Position Set Code Length Array,\r
e1f414b6 536 // Generate the Huffman code mapping table for the Position Set.\r
537 //\r
538 Sd->mBadTableFlag = ReadPTLen (Sd, MAXNP, Sd->mPBit, (UINT16) (-1));\r
539 if (Sd->mBadTableFlag != 0) {\r
540 return 0;\r
541 }\r
542 }\r
543\r
544 //\r
545 // Get one code according to Code&Set Huffman Table\r
546 //\r
547 Sd->mBlockSize--;\r
548 Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)];\r
549\r
550 if (Index2 >= NC) {\r
551 Mask = 1U << (BITBUFSIZ - 1 - 12);\r
552\r
553 do {\r
eceb3a4c 554 if ((Sd->mBitBuf & Mask) != 0) {\r
e1f414b6 555 Index2 = Sd->mRight[Index2];\r
556 } else {\r
557 Index2 = Sd->mLeft[Index2];\r
558 }\r
559\r
560 Mask >>= 1;\r
561 } while (Index2 >= NC);\r
562 }\r
563 //\r
564 // Advance what we have read\r
565 //\r
566 FillBuf (Sd, Sd->mCLen[Index2]);\r
567\r
568 return Index2;\r
569}\r
570\r
571/**\r
572 Decode the source data and put the resulting data into the destination buffer.\r
efb23117 573\r
58380e9c 574 @param Sd The global scratch data.\r
e1f414b6 575\r
576**/\r
577VOID\r
578Decode (\r
579 SCRATCH_DATA *Sd\r
580 )\r
581{\r
582 UINT16 BytesRemain;\r
583 UINT32 DataIdx;\r
584 UINT16 CharC;\r
585\r
586 BytesRemain = (UINT16) (-1);\r
587\r
588 DataIdx = 0;\r
589\r
590 for (;;) {\r
591 //\r
592 // Get one code from mBitBuf\r
9095d37b 593 //\r
e1f414b6 594 CharC = DecodeC (Sd);\r
595 if (Sd->mBadTableFlag != 0) {\r
596 goto Done;\r
597 }\r
598\r
599 if (CharC < 256) {\r
600 //\r
601 // Process an Original character\r
602 //\r
603 if (Sd->mOutBuf >= Sd->mOrigSize) {\r
604 goto Done;\r
605 } else {\r
606 //\r
607 // Write orignal character into mDstBase\r
608 //\r
609 Sd->mDstBase[Sd->mOutBuf++] = (UINT8) CharC;\r
610 }\r
611\r
612 } else {\r
613 //\r
614 // Process a Pointer\r
615 //\r
daa6553a 616 CharC = (UINT16) (CharC - (BIT8 - THRESHOLD));\r
9095d37b 617\r
e1f414b6 618 //\r
619 // Get string length\r
620 //\r
621 BytesRemain = CharC;\r
622\r
623 //\r
624 // Locate string position\r
625 //\r
626 DataIdx = Sd->mOutBuf - DecodeP (Sd) - 1;\r
627\r
628 //\r
629 // Write BytesRemain of bytes into mDstBase\r
630 //\r
631 BytesRemain--;\r
2ec7953d 632\r
e1f414b6 633 while ((INT16) (BytesRemain) >= 0) {\r
e1f414b6 634 if (Sd->mOutBuf >= Sd->mOrigSize) {\r
635 goto Done;\r
636 }\r
2ec7953d
LG
637 if (DataIdx >= Sd->mOrigSize) {\r
638 Sd->mBadTableFlag = (UINT16) BAD_TABLE;\r
639 goto Done;\r
640 }\r
641 Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++];\r
e1f414b6 642\r
643 BytesRemain--;\r
644 }\r
1c4cecc9
LG
645 //\r
646 // Once mOutBuf is fully filled, directly return\r
647 //\r
648 if (Sd->mOutBuf >= Sd->mOrigSize) {\r
649 goto Done;\r
650 }\r
e1f414b6 651 }\r
652 }\r
653\r
654Done:\r
655 return ;\r
656}\r
657\r
658/**\r
9095d37b
LG
659 Given a compressed source buffer, this function retrieves the size of\r
660 the uncompressed buffer and the size of the scratch buffer required\r
eceb3a4c 661 to decompress the compressed source buffer.\r
e1f414b6 662\r
9095d37b 663 Retrieves the size of the uncompressed buffer and the temporary scratch buffer\r
e1f414b6 664 required to decompress the buffer specified by Source and SourceSize.\r
665 If the size of the uncompressed buffer or the size of the scratch buffer cannot\r
9095d37b 666 be determined from the compressed data specified by Source and SourceData,\r
e1f414b6 667 then RETURN_INVALID_PARAMETER is returned. Otherwise, the size of the uncompressed\r
668 buffer is returned in DestinationSize, the size of the scratch buffer is returned\r
669 in ScratchSize, and RETURN_SUCCESS is returned.\r
9095d37b 670 This function does not have scratch buffer available to perform a thorough\r
e1f414b6 671 checking of the validity of the source data. It just retrieves the "Original Size"\r
672 field from the beginning bytes of the source data and output it as DestinationSize.\r
673 And ScratchSize is specific to the decompression implementation.\r
674\r
675 If Source is NULL, then ASSERT().\r
676 If DestinationSize is NULL, then ASSERT().\r
677 If ScratchSize is NULL, then ASSERT().\r
678\r
679 @param Source The source buffer containing the compressed data.\r
680 @param SourceSize The size, in bytes, of the source buffer.\r
681 @param DestinationSize A pointer to the size, in bytes, of the uncompressed buffer\r
682 that will be generated when the compressed buffer specified\r
58380e9c 683 by Source and SourceSize is decompressed.\r
e1f414b6 684 @param ScratchSize A pointer to the size, in bytes, of the scratch buffer that\r
9095d37b 685 is required to decompress the compressed buffer specified\r
e1f414b6 686 by Source and SourceSize.\r
687\r
9095d37b
LG
688 @retval RETURN_SUCCESS The size of the uncompressed data was returned\r
689 in DestinationSize, and the size of the scratch\r
eceb3a4c 690 buffer was returned in ScratchSize.\r
9095d37b
LG
691 @retval RETURN_INVALID_PARAMETER\r
692 The size of the uncompressed data or the size of\r
693 the scratch buffer cannot be determined from\r
694 the compressed data specified by Source\r
eceb3a4c 695 and SourceSize.\r
e1f414b6 696**/\r
697RETURN_STATUS\r
698EFIAPI\r
699UefiDecompressGetInfo (\r
700 IN CONST VOID *Source,\r
701 IN UINT32 SourceSize,\r
702 OUT UINT32 *DestinationSize,\r
703 OUT UINT32 *ScratchSize\r
704 )\r
705{\r
706 UINT32 CompressedSize;\r
707\r
708 ASSERT (Source != NULL);\r
709 ASSERT (DestinationSize != NULL);\r
710 ASSERT (ScratchSize != NULL);\r
711\r
e1f414b6 712 if (SourceSize < 8) {\r
713 return RETURN_INVALID_PARAMETER;\r
714 }\r
715\r
7fd58cbc 716 CompressedSize = ReadUnaligned32 ((UINT32 *)Source);\r
2ec7953d 717 if (SourceSize < (CompressedSize + 8) || (CompressedSize + 8) < 8) {\r
e1f414b6 718 return RETURN_INVALID_PARAMETER;\r
719 }\r
720\r
7fd58cbc 721 *ScratchSize = sizeof (SCRATCH_DATA);\r
722 *DestinationSize = ReadUnaligned32 ((UINT32 *)Source + 1);\r
723\r
e1f414b6 724 return RETURN_SUCCESS;\r
725}\r
726\r
727/**\r
728 Decompresses a compressed source buffer.\r
729\r
eceb3a4c 730 Extracts decompressed data to its original form.\r
e1f414b6 731 This function is designed so that the decompression algorithm can be implemented\r
732 without using any memory services. As a result, this function is not allowed to\r
9095d37b 733 call any memory allocation services in its implementation. It is the caller's\r
28d3e14f 734 responsibility to allocate and free the Destination and Scratch buffers.\r
9095d37b
LG
735 If the compressed source data specified by Source is successfully decompressed\r
736 into Destination, then RETURN_SUCCESS is returned. If the compressed source data\r
e1f414b6 737 specified by Source is not in a valid compressed data format,\r
738 then RETURN_INVALID_PARAMETER is returned.\r
739\r
740 If Source is NULL, then ASSERT().\r
741 If Destination is NULL, then ASSERT().\r
742 If the required scratch buffer size > 0 and Scratch is NULL, then ASSERT().\r
743\r
744 @param Source The source buffer containing the compressed data.\r
58380e9c 745 @param Destination The destination buffer to store the decompressed data.\r
e1f414b6 746 @param Scratch A temporary scratch buffer that is used to perform the decompression.\r
9095d37b 747 This is an optional parameter that may be NULL if the\r
e1f414b6 748 required scratch buffer size is 0.\r
9095d37b
LG
749\r
750 @retval RETURN_SUCCESS Decompression completed successfully, and\r
eceb3a4c 751 the uncompressed buffer is returned in Destination.\r
9095d37b
LG
752 @retval RETURN_INVALID_PARAMETER\r
753 The source buffer specified by Source is corrupted\r
eceb3a4c 754 (not in a valid compressed format).\r
e1f414b6 755**/\r
756RETURN_STATUS\r
757EFIAPI\r
758UefiDecompress (\r
759 IN CONST VOID *Source,\r
760 IN OUT VOID *Destination,\r
6d6a1098 761 IN OUT VOID *Scratch OPTIONAL\r
e1f414b6 762 )\r
763{\r
e1f414b6 764 UINT32 CompSize;\r
765 UINT32 OrigSize;\r
766 SCRATCH_DATA *Sd;\r
767 CONST UINT8 *Src;\r
768 UINT8 *Dst;\r
769\r
770 ASSERT (Source != NULL);\r
771 ASSERT (Destination != NULL);\r
772 ASSERT (Scratch != NULL);\r
773\r
774 Src = Source;\r
775 Dst = Destination;\r
776\r
777 Sd = (SCRATCH_DATA *) Scratch;\r
778\r
779 CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24);\r
780 OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);\r
781\r
782 //\r
783 // If compressed file size is 0, return\r
784 //\r
785 if (OrigSize == 0) {\r
786 return RETURN_SUCCESS;\r
787 }\r
788\r
789 Src = Src + 8;\r
02313d1e 790 SetMem (Sd, sizeof (SCRATCH_DATA), 0);\r
e1f414b6 791\r
e1f414b6 792 //\r
793 // The length of the field 'Position Set Code Length Array Size' in Block Header.\r
8a7d75b0 794 // For UEFI 2.0 de/compression algorithm(Version 1), mPBit = 4\r
e1f414b6 795 //\r
796 Sd->mPBit = 4;\r
797 Sd->mSrcBase = (UINT8 *)Src;\r
798 Sd->mDstBase = Dst;\r
799 //\r
4f953ed7 800 // CompSize and OrigSize are calculated in bytes\r
e1f414b6 801 //\r
802 Sd->mCompSize = CompSize;\r
803 Sd->mOrigSize = OrigSize;\r
804\r
805 //\r
806 // Fill the first BITBUFSIZ bits\r
807 //\r
808 FillBuf (Sd, BITBUFSIZ);\r
809\r
810 //\r
811 // Decompress it\r
812 //\r
813 Decode (Sd);\r
814\r
815 if (Sd->mBadTableFlag != 0) {\r
816 //\r
817 // Something wrong with the source\r
818 //\r
819 return RETURN_INVALID_PARAMETER;\r
820 }\r
821\r
822 return RETURN_SUCCESS;\r
823}\r