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