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