]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.c
IntelFrameworkModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / IntelFrameworkModulePkg / Library / BaseUefiTianoCustomDecompressLib / BaseUefiTianoCustomDecompressLib.c
CommitLineData
b4b6c8de 1/** @file\r
0a6f4824 2 UEFI and Tiano Custom Decompress Library\r
30f001ca 3 It will do Tiano or UEFI decompress with different verison parameter.\r
0a6f4824
LG
4\r
5Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
c0a00b14 6SPDX-License-Identifier: BSD-2-Clause-Patent\r
54bd896e 7\r
3db51098 8**/\r
54bd896e 9\r
54bd896e 10#include "BaseUefiTianoCustomDecompressLibInternals.h"\r
11\r
ed7752ec 12/**\r
13 Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source.\r
0a6f4824 14\r
ed7752ec 15 @param Sd The global scratch data\r
0a6f4824 16 @param NumOfBits The number of bits to shift and read.\r
ed7752ec 17**/\r
54bd896e 18VOID\r
19FillBuf (\r
20 IN SCRATCH_DATA *Sd,\r
21 IN UINT16 NumOfBits\r
22 )\r
54bd896e 23{\r
b4b6c8de
LG
24 //\r
25 // Left shift NumOfBits of bits in advance\r
26 //\r
9458afa3 27 Sd->mBitBuf = (UINT32) LShiftU64 (((UINT64)Sd->mBitBuf), NumOfBits);\r
54bd896e 28\r
b4b6c8de
LG
29 //\r
30 // Copy data needed in bytes into mSbuBitBuf\r
31 //\r
54bd896e 32 while (NumOfBits > Sd->mBitCount) {\r
9458afa3
AF
33 NumOfBits = (UINT16) (NumOfBits - Sd->mBitCount);\r
34 Sd->mBitBuf |= (UINT32) LShiftU64 (((UINT64)Sd->mSubBitBuf), NumOfBits);\r
54bd896e 35\r
36 if (Sd->mCompSize > 0) {\r
37 //\r
38 // Get 1 byte into SubBitBuf\r
39 //\r
40 Sd->mCompSize--;\r
41 Sd->mSubBitBuf = 0;\r
42 Sd->mSubBitBuf = Sd->mSrcBase[Sd->mInBuf++];\r
43 Sd->mBitCount = 8;\r
44\r
45 } else {\r
46 //\r
47 // No more bits from the source, just pad zero bit.\r
48 //\r
49 Sd->mSubBitBuf = 0;\r
50 Sd->mBitCount = 8;\r
51\r
52 }\r
53 }\r
54\r
b4b6c8de 55 //\r
207f0479 56 // Calculate additional bit count read to update mBitCount\r
b4b6c8de 57 //\r
54bd896e 58 Sd->mBitCount = (UINT16) (Sd->mBitCount - NumOfBits);\r
0a6f4824 59\r
b4b6c8de
LG
60 //\r
61 // Copy NumOfBits of bits from mSubBitBuf into mBitBuf\r
62 //\r
54bd896e 63 Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount;\r
64}\r
65\r
ed7752ec 66/**\r
67 Get NumOfBits of bits out from mBitBuf\r
54bd896e 68\r
0a6f4824
LG
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
54bd896e 71 popped out.\r
72\r
ed7752ec 73 @param Sd The global scratch data.\r
74 @param NumOfBits The number of bits to pop and read.\r
54bd896e 75\r
ed7752ec 76 @return The bits that are popped out.\r
54bd896e 77\r
ed7752ec 78**/\r
79UINT32\r
80GetBits (\r
81 IN SCRATCH_DATA *Sd,\r
82 IN UINT16 NumOfBits\r
83 )\r
54bd896e 84{\r
85 UINT32 OutBits;\r
86\r
b4b6c8de
LG
87 //\r
88 // Pop NumOfBits of Bits from Left\r
0a6f4824 89 //\r
54bd896e 90 OutBits = (UINT32) (Sd->mBitBuf >> (BITBUFSIZ - NumOfBits));\r
91\r
b4b6c8de
LG
92 //\r
93 // Fill up mBitBuf from source\r
94 //\r
54bd896e 95 FillBuf (Sd, NumOfBits);\r
96\r
97 return OutBits;\r
98}\r
99\r
ed7752ec 100/**\r
101 Creates Huffman Code mapping table according to code length array.\r
102\r
0a6f4824 103 Creates Huffman Code mapping table for Extra Set, Char&Len Set\r
ed7752ec 104 and Position Set according to code length array.\r
14531b13 105 If TableBits > 16, then ASSERT ().\r
ed7752ec 106\r
107 @param Sd The global scratch data\r
108 @param NumOfChar 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
b4b6c8de 111 @param Table The table to be created.\r
ed7752ec 112\r
113 @retval 0 OK.\r
114 @retval BAD_TABLE The table is corrupted.\r
115\r
116**/\r
54bd896e 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
54bd896e 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
80267d51 131 UINT16 Index;\r
54bd896e 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
684db6da 140 UINT16 MaxTableLength;\r
54bd896e 141\r
14531b13
LG
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
147\r
aa950314 148 for (Index = 0; Index <= 16; Index++) {\r
54bd896e 149 Count[Index] = 0;\r
150 }\r
151\r
152 for (Index = 0; Index < NumOfChar; Index++) {\r
684db6da
LG
153 if (BitLen[Index] > 16) {\r
154 return (UINT16) BAD_TABLE;\r
155 }\r
54bd896e 156 Count[BitLen[Index]]++;\r
157 }\r
0a6f4824 158\r
aa950314 159 Start[0] = 0;\r
54bd896e 160 Start[1] = 0;\r
161\r
162 for (Index = 1; Index <= 16; Index++) {\r
163 WordOfStart = Start[Index];\r
164 WordOfCount = Count[Index];\r
165 Start[Index + 1] = (UINT16) (WordOfStart + (WordOfCount << (16 - Index)));\r
166 }\r
167\r
168 if (Start[17] != 0) {\r
169 /*(1U << 16)*/\r
170 return (UINT16) BAD_TABLE;\r
171 }\r
172\r
173 JuBits = (UINT16) (16 - TableBits);\r
0a6f4824 174\r
aa950314 175 Weight[0] = 0;\r
54bd896e 176 for (Index = 1; Index <= TableBits; Index++) {\r
177 Start[Index] >>= JuBits;\r
178 Weight[Index] = (UINT16) (1U << (TableBits - Index));\r
179 }\r
180\r
181 while (Index <= 16) {\r
182 Weight[Index] = (UINT16) (1U << (16 - Index));\r
0a6f4824 183 Index++;\r
54bd896e 184 }\r
185\r
186 Index = (UINT16) (Start[TableBits + 1] >> JuBits);\r
187\r
188 if (Index != 0) {\r
189 Index3 = (UINT16) (1U << TableBits);\r
aa950314 190 if (Index < Index3) {\r
191 SetMem16 (Table + Index, (Index3 - Index) * sizeof (*Table), 0);\r
54bd896e 192 }\r
193 }\r
194\r
195 Avail = NumOfChar;\r
196 Mask = (UINT16) (1U << (15 - TableBits));\r
684db6da 197 MaxTableLength = (UINT16) (1U << TableBits);\r
54bd896e 198\r
199 for (Char = 0; Char < NumOfChar; Char++) {\r
200\r
201 Len = BitLen[Char];\r
aa950314 202 if (Len == 0 || Len >= 17) {\r
54bd896e 203 continue;\r
204 }\r
205\r
206 NextCode = (UINT16) (Start[Len] + Weight[Len]);\r
207\r
208 if (Len <= TableBits) {\r
209\r
210 for (Index = Start[Len]; Index < NextCode; Index++) {\r
684db6da
LG
211 if (Index >= MaxTableLength) {\r
212 return (UINT16) BAD_TABLE;\r
213 }\r
54bd896e 214 Table[Index] = Char;\r
215 }\r
216\r
217 } else {\r
218\r
219 Index3 = Start[Len];\r
220 Pointer = &Table[Index3 >> JuBits];\r
221 Index = (UINT16) (Len - TableBits);\r
222\r
223 while (Index != 0) {\r
aa950314 224 if (*Pointer == 0 && Avail < (2 * NC - 1)) {\r
225 Sd->mRight[Avail] = Sd->mLeft[Avail] = 0;\r
54bd896e 226 *Pointer = Avail++;\r
227 }\r
0a6f4824 228\r
aa950314 229 if (*Pointer < (2 * NC - 1)) {\r
230 if ((Index3 & Mask) != 0) {\r
231 Pointer = &Sd->mRight[*Pointer];\r
232 } else {\r
233 Pointer = &Sd->mLeft[*Pointer];\r
234 }\r
54bd896e 235 }\r
236\r
237 Index3 <<= 1;\r
238 Index--;\r
239 }\r
240\r
241 *Pointer = Char;\r
242\r
243 }\r
244\r
245 Start[Len] = NextCode;\r
246 }\r
247 //\r
248 // Succeeds\r
249 //\r
250 return 0;\r
251}\r
252\r
ed7752ec 253/**\r
254 Decodes a position value.\r
0a6f4824 255\r
b4b6c8de
LG
256 Get a position value according to Position Huffman Table.\r
257\r
ed7752ec 258 @param Sd the global scratch data\r
0a6f4824 259\r
ed7752ec 260 @return The position value decoded.\r
261**/\r
54bd896e 262UINT32\r
263DecodeP (\r
264 IN SCRATCH_DATA *Sd\r
265 )\r
54bd896e 266{\r
267 UINT16 Val;\r
268 UINT32 Mask;\r
269 UINT32 Pos;\r
270\r
271 Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];\r
272\r
273 if (Val >= MAXNP) {\r
274 Mask = 1U << (BITBUFSIZ - 1 - 8);\r
275\r
276 do {\r
277\r
b4b6c8de 278 if ((Sd->mBitBuf & Mask) != 0) {\r
54bd896e 279 Val = Sd->mRight[Val];\r
280 } else {\r
281 Val = Sd->mLeft[Val];\r
282 }\r
283\r
284 Mask >>= 1;\r
285 } while (Val >= MAXNP);\r
286 }\r
287 //\r
288 // Advance what we have read\r
289 //\r
290 FillBuf (Sd, Sd->mPTLen[Val]);\r
291\r
292 Pos = Val;\r
293 if (Val > 1) {\r
294 Pos = (UINT32) ((1U << (Val - 1)) + GetBits (Sd, (UINT16) (Val - 1)));\r
295 }\r
296\r
297 return Pos;\r
298}\r
299\r
ed7752ec 300/**\r
301 Reads code lengths for the Extra Set or the Position Set.\r
302\r
70d3fe9d 303 Read in the Extra Set or Position Set Length Array, then\r
ed7752ec 304 generate the Huffman code mapping for them.\r
305\r
306 @param Sd The global scratch data.\r
307 @param nn Number of symbols.\r
308 @param nbit Number of bits needed to represent nn.\r
309 @param Special The special symbol that needs to be taken care of.\r
310\r
311 @retval 0 OK.\r
312 @retval BAD_TABLE Table is corrupted.\r
313\r
314**/\r
54bd896e 315UINT16\r
316ReadPTLen (\r
317 IN SCRATCH_DATA *Sd,\r
318 IN UINT16 nn,\r
319 IN UINT16 nbit,\r
320 IN UINT16 Special\r
321 )\r
54bd896e 322{\r
323 UINT16 Number;\r
324 UINT16 CharC;\r
80267d51 325 UINT16 Index;\r
54bd896e 326 UINT32 Mask;\r
327\r
5a189086 328 ASSERT (nn <= NPT);\r
aa950314 329 //\r
0a6f4824 330 // Read Extra Set Code Length Array size\r
aa950314 331 //\r
54bd896e 332 Number = (UINT16) GetBits (Sd, nbit);\r
333\r
334 if (Number == 0) {\r
aa950314 335 //\r
336 // This represents only Huffman code used\r
337 //\r
54bd896e 338 CharC = (UINT16) GetBits (Sd, nbit);\r
339\r
340 for (Index = 0; Index < 256; Index++) {\r
341 Sd->mPTTable[Index] = CharC;\r
342 }\r
343\r
aa950314 344 SetMem (Sd->mPTLen, nn, 0);\r
54bd896e 345\r
346 return 0;\r
347 }\r
348\r
349 Index = 0;\r
350\r
aa950314 351 while (Index < Number && Index < NPT) {\r
54bd896e 352\r
353 CharC = (UINT16) (Sd->mBitBuf >> (BITBUFSIZ - 3));\r
354\r
aa950314 355 //\r
356 // If a code length is less than 7, then it is encoded as a 3-bit\r
0a6f4824 357 // value. Or it is encoded as a series of "1"s followed by a\r
aa950314 358 // terminating "0". The number of "1"s = Code length - 4.\r
359 //\r
54bd896e 360 if (CharC == 7) {\r
361 Mask = 1U << (BITBUFSIZ - 1 - 3);\r
362 while (Mask & Sd->mBitBuf) {\r
363 Mask >>= 1;\r
364 CharC += 1;\r
365 }\r
366 }\r
0a6f4824 367\r
54bd896e 368 FillBuf (Sd, (UINT16) ((CharC < 7) ? 3 : CharC - 3));\r
369\r
370 Sd->mPTLen[Index++] = (UINT8) CharC;\r
0a6f4824 371\r
aa950314 372 //\r
0a6f4824 373 // For Code&Len Set,\r
aa950314 374 // After the third length of the code length concatenation,\r
0a6f4824 375 // a 2-bit value is used to indicated the number of consecutive\r
aa950314 376 // zero lengths after the third length.\r
377 //\r
54bd896e 378 if (Index == Special) {\r
379 CharC = (UINT16) GetBits (Sd, 2);\r
aa950314 380 while ((INT16) (--CharC) >= 0 && Index < NPT) {\r
54bd896e 381 Sd->mPTLen[Index++] = 0;\r
382 }\r
383 }\r
384 }\r
385\r
aa950314 386 while (Index < nn && Index < NPT) {\r
54bd896e 387 Sd->mPTLen[Index++] = 0;\r
388 }\r
0a6f4824 389\r
54bd896e 390 return MakeTable (Sd, nn, Sd->mPTLen, 8, Sd->mPTTable);\r
391}\r
392\r
ed7752ec 393/**\r
394 Reads code lengths for Char&Len Set.\r
0a6f4824 395\r
ed7752ec 396 Read in and decode the Char&Len Set Code Length Array, then\r
397 generate the Huffman Code mapping table for the Char&Len Set.\r
398\r
399 @param Sd the global scratch data\r
400\r
401**/\r
54bd896e 402VOID\r
403ReadCLen (\r
404 SCRATCH_DATA *Sd\r
405 )\r
54bd896e 406{\r
407 UINT16 Number;\r
408 UINT16 CharC;\r
80267d51 409 UINT16 Index;\r
54bd896e 410 UINT32 Mask;\r
411\r
412 Number = (UINT16) GetBits (Sd, CBIT);\r
413\r
414 if (Number == 0) {\r
aa950314 415 //\r
416 // This represents only Huffman code used\r
417 //\r
54bd896e 418 CharC = (UINT16) GetBits (Sd, CBIT);\r
419\r
aa950314 420 SetMem (Sd->mCLen, NC, 0);\r
54bd896e 421\r
422 for (Index = 0; Index < 4096; Index++) {\r
423 Sd->mCTable[Index] = CharC;\r
424 }\r
425\r
426 return ;\r
427 }\r
428\r
429 Index = 0;\r
aa950314 430 while (Index < Number && Index < NC) {\r
54bd896e 431 CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];\r
432 if (CharC >= NT) {\r
433 Mask = 1U << (BITBUFSIZ - 1 - 8);\r
434\r
435 do {\r
436\r
437 if (Mask & Sd->mBitBuf) {\r
438 CharC = Sd->mRight[CharC];\r
439 } else {\r
440 CharC = Sd->mLeft[CharC];\r
441 }\r
442\r
443 Mask >>= 1;\r
444\r
445 } while (CharC >= NT);\r
446 }\r
447 //\r
448 // Advance what we have read\r
449 //\r
450 FillBuf (Sd, Sd->mPTLen[CharC]);\r
451\r
452 if (CharC <= 2) {\r
453\r
454 if (CharC == 0) {\r
455 CharC = 1;\r
456 } else if (CharC == 1) {\r
457 CharC = (UINT16) (GetBits (Sd, 4) + 3);\r
458 } else if (CharC == 2) {\r
459 CharC = (UINT16) (GetBits (Sd, CBIT) + 20);\r
460 }\r
461\r
aa950314 462 while ((INT16) (--CharC) >= 0 && Index < NC) {\r
54bd896e 463 Sd->mCLen[Index++] = 0;\r
464 }\r
465\r
466 } else {\r
467\r
468 Sd->mCLen[Index++] = (UINT8) (CharC - 2);\r
469\r
470 }\r
471 }\r
472\r
aa950314 473 SetMem (Sd->mCLen + Index, NC - Index, 0);\r
54bd896e 474\r
475 MakeTable (Sd, NC, Sd->mCLen, 12, Sd->mCTable);\r
476\r
477 return ;\r
478}\r
479\r
ed7752ec 480/**\r
54bd896e 481 Decode a character/length value.\r
0a6f4824 482\r
ed7752ec 483 Read one value from mBitBuf, Get one code from mBitBuf. If it is at block boundary, generates\r
484 Huffman code mapping table for Extra Set, Code&Len Set and\r
485 Position Set.\r
54bd896e 486\r
ed7752ec 487 @param Sd The global scratch data.\r
54bd896e 488\r
ed7752ec 489 @return The value decoded.\r
54bd896e 490\r
ed7752ec 491**/\r
492UINT16\r
493DecodeC (\r
494 SCRATCH_DATA *Sd\r
495 )\r
54bd896e 496{\r
497 UINT16 Index2;\r
498 UINT32 Mask;\r
499\r
500 if (Sd->mBlockSize == 0) {\r
501 //\r
502 // Starting a new block\r
b4b6c8de 503 // Read BlockSize from block header\r
0a6f4824 504 //\r
54bd896e 505 Sd->mBlockSize = (UINT16) GetBits (Sd, 16);\r
b4b6c8de
LG
506\r
507 //\r
70d3fe9d 508 // Read in the Extra Set Code Length Array,\r
b4b6c8de
LG
509 // Generate the Huffman code mapping table for Extra Set.\r
510 //\r
54bd896e 511 Sd->mBadTableFlag = ReadPTLen (Sd, NT, TBIT, 3);\r
512 if (Sd->mBadTableFlag != 0) {\r
513 return 0;\r
514 }\r
515\r
b4b6c8de 516 //\r
70d3fe9d 517 // Read in and decode the Char&Len Set Code Length Array,\r
b4b6c8de
LG
518 // Generate the Huffman code mapping table for Char&Len Set.\r
519 //\r
54bd896e 520 ReadCLen (Sd);\r
521\r
b4b6c8de 522 //\r
70d3fe9d 523 // Read in the Position Set Code Length Array,\r
b4b6c8de
LG
524 // Generate the Huffman code mapping table for the Position Set.\r
525 //\r
54bd896e 526 Sd->mBadTableFlag = ReadPTLen (Sd, MAXNP, Sd->mPBit, (UINT16) (-1));\r
527 if (Sd->mBadTableFlag != 0) {\r
528 return 0;\r
529 }\r
530 }\r
531\r
b4b6c8de
LG
532 //\r
533 // Get one code according to Code&Set Huffman Table\r
534 //\r
54bd896e 535 Sd->mBlockSize--;\r
536 Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)];\r
537\r
538 if (Index2 >= NC) {\r
539 Mask = 1U << (BITBUFSIZ - 1 - 12);\r
540\r
541 do {\r
b4b6c8de 542 if ((Sd->mBitBuf & Mask) != 0) {\r
54bd896e 543 Index2 = Sd->mRight[Index2];\r
544 } else {\r
545 Index2 = Sd->mLeft[Index2];\r
546 }\r
547\r
548 Mask >>= 1;\r
549 } while (Index2 >= NC);\r
550 }\r
551 //\r
552 // Advance what we have read\r
553 //\r
554 FillBuf (Sd, Sd->mCLen[Index2]);\r
555\r
556 return Index2;\r
557}\r
558\r
ed7752ec 559/**\r
b4b6c8de 560 Decode the source data and put the resulting data into the destination buffer.\r
0a6f4824 561\r
b4b6c8de 562 @param Sd The global scratch data\r
ed7752ec 563**/\r
54bd896e 564VOID\r
565Decode (\r
566 SCRATCH_DATA *Sd\r
567 )\r
54bd896e 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
b4b6c8de
LG
578 //\r
579 // Get one code from mBitBuf\r
0a6f4824 580 //\r
54bd896e 581 CharC = DecodeC (Sd);\r
582 if (Sd->mBadTableFlag != 0) {\r
b4b6c8de 583 goto Done;\r
54bd896e 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
b4b6c8de 591 goto Done;\r
54bd896e 592 } else {\r
b4b6c8de
LG
593 //\r
594 // Write orignal character into mDstBase\r
595 //\r
54bd896e 596 Sd->mDstBase[Sd->mOutBuf++] = (UINT8) CharC;\r
597 }\r
598\r
599 } else {\r
600 //\r
601 // Process a Pointer\r
602 //\r
15793911 603 CharC = (UINT16) (CharC - (BIT8 - THRESHOLD));\r
0a6f4824 604\r
b4b6c8de
LG
605 //\r
606 // Get string length\r
607 //\r
54bd896e 608 BytesRemain = CharC;\r
609\r
b4b6c8de
LG
610 //\r
611 // Locate string position\r
612 //\r
54bd896e 613 DataIdx = Sd->mOutBuf - DecodeP (Sd) - 1;\r
614\r
b4b6c8de
LG
615 //\r
616 // Write BytesRemain of bytes into mDstBase\r
617 //\r
54bd896e 618 BytesRemain--;\r
619 while ((INT16) (BytesRemain) >= 0) {\r
54bd896e 620 if (Sd->mOutBuf >= Sd->mOrigSize) {\r
621 goto Done ;\r
622 }\r
684db6da
LG
623 if (DataIdx >= Sd->mOrigSize) {\r
624 Sd->mBadTableFlag = (UINT16) BAD_TABLE;\r
625 goto Done ;\r
626 }\r
627 Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++];\r
54bd896e 628\r
629 BytesRemain--;\r
630 }\r
ade71c52
LG
631 //\r
632 // Once mOutBuf is fully filled, directly return\r
633 //\r
634 if (Sd->mOutBuf >= Sd->mOrigSize) {\r
635 goto Done ;\r
636 }\r
54bd896e 637 }\r
638 }\r
639\r
640Done:\r
641 return ;\r
642}\r
643\r
ed7752ec 644/**\r
0a6f4824
LG
645 Given a compressed source buffer, this function retrieves the size of\r
646 the uncompressed buffer and the size of the scratch buffer required\r
b4b6c8de
LG
647 to decompress the compressed source buffer.\r
648\r
0a6f4824 649 Retrieves the size of the uncompressed buffer and the temporary scratch buffer\r
b4b6c8de
LG
650 required to decompress the buffer specified by Source and SourceSize.\r
651 If the size of the uncompressed buffer or the size of the scratch buffer cannot\r
0a6f4824 652 be determined from the compressed data specified by Source and SourceData,\r
b4b6c8de
LG
653 then RETURN_INVALID_PARAMETER is returned. Otherwise, the size of the uncompressed\r
654 buffer is returned in DestinationSize, the size of the scratch buffer is returned\r
655 in ScratchSize, and RETURN_SUCCESS is returned.\r
0a6f4824 656 This function does not have scratch buffer available to perform a thorough\r
b4b6c8de
LG
657 checking of the validity of the source data. It just retrieves the "Original Size"\r
658 field from the beginning bytes of the source data and output it as DestinationSize.\r
659 And ScratchSize is specific to the decompression implementation.\r
660\r
661 If Source is NULL, then ASSERT().\r
662 If DestinationSize is NULL, then ASSERT().\r
663 If ScratchSize is NULL, then ASSERT().\r
664\r
665 @param Source The source buffer containing the compressed data.\r
666 @param SourceSize The size, in bytes, of the source buffer.\r
667 @param DestinationSize A pointer to the size, in bytes, of the uncompressed buffer\r
668 that will be generated when the compressed buffer specified\r
669 by Source and SourceSize is decompressed..\r
670 @param ScratchSize A pointer to the size, in bytes, of the scratch buffer that\r
0a6f4824 671 is required to decompress the compressed buffer specified\r
b4b6c8de
LG
672 by Source and SourceSize.\r
673\r
0a6f4824
LG
674 @retval RETURN_SUCCESS The size of the uncompressed data was returned\r
675 in DestinationSize and the size of the scratch\r
b4b6c8de 676 buffer was returned in ScratchSize.\r
0a6f4824
LG
677 @retval RETURN_INVALID_PARAMETER\r
678 The size of the uncompressed data or the size of\r
679 the scratch buffer cannot be determined from\r
680 the compressed data specified by Source\r
b4b6c8de 681 and SourceSize.\r
ed7752ec 682**/\r
54bd896e 683RETURN_STATUS\r
684EFIAPI\r
685UefiDecompressGetInfo (\r
686 IN CONST VOID *Source,\r
687 IN UINT32 SourceSize,\r
688 OUT UINT32 *DestinationSize,\r
689 OUT UINT32 *ScratchSize\r
690 )\r
54bd896e 691{\r
692 UINT32 CompressedSize;\r
693\r
694 ASSERT (Source != NULL);\r
695 ASSERT (DestinationSize != NULL);\r
696 ASSERT (ScratchSize != NULL);\r
697\r
54bd896e 698 if (SourceSize < 8) {\r
699 return RETURN_INVALID_PARAMETER;\r
700 }\r
701\r
e69a0629 702 CompressedSize = ReadUnaligned32 ((UINT32 *)Source);\r
684db6da 703 if (SourceSize < (CompressedSize + 8) || (CompressedSize + 8) < 8) {\r
54bd896e 704 return RETURN_INVALID_PARAMETER;\r
705 }\r
706\r
18fd8d65 707 *ScratchSize = sizeof (SCRATCH_DATA);\r
e69a0629 708 *DestinationSize = ReadUnaligned32 ((UINT32 *)Source + 1);\r
18fd8d65 709\r
54bd896e 710 return RETURN_SUCCESS;\r
711}\r
712\r
ed7752ec 713/**\r
b4b6c8de
LG
714 Decompresses a compressed source buffer by EFI or Tiano algorithm.\r
715\r
716 Extracts decompressed data to its original form.\r
717 This function is designed so that the decompression algorithm can be implemented\r
718 without using any memory services. As a result, this function is not allowed to\r
0a6f4824 719 call any memory allocation services in its implementation. It is the caller's\r
b4b6c8de 720 responsibility to allocate and free the Destination and Scratch buffers.\r
0a6f4824
LG
721 If the compressed source data specified by Source is successfully decompressed\r
722 into Destination, then RETURN_SUCCESS is returned. If the compressed source data\r
b4b6c8de
LG
723 specified by Source is not in a valid compressed data format,\r
724 then RETURN_INVALID_PARAMETER is returned.\r
725\r
726 If Source is NULL, then ASSERT().\r
727 If Destination is NULL, then ASSERT().\r
728 If the required scratch buffer size > 0 and Scratch is NULL, then ASSERT().\r
729\r
730 @param Source The source buffer containing the compressed data.\r
731 @param Destination The destination buffer to store the decompressed data\r
732 @param Scratch A temporary scratch buffer that is used to perform the decompression.\r
0a6f4824 733 This is an optional parameter that may be NULL if the\r
b4b6c8de
LG
734 required scratch buffer size is 0.\r
735 @param Version 1 for UEFI Decompress algoruthm, 2 for Tiano Decompess algorithm.\r
736\r
0a6f4824 737 @retval RETURN_SUCCESS Decompression completed successfully, and\r
b4b6c8de 738 the uncompressed buffer is returned in Destination.\r
0a6f4824
LG
739 @retval RETURN_INVALID_PARAMETER\r
740 The source buffer specified by Source is corrupted\r
b4b6c8de 741 (not in a valid compressed format).\r
ed7752ec 742**/\r
54bd896e 743RETURN_STATUS\r
744EFIAPI\r
745UefiTianoDecompress (\r
746 IN CONST VOID *Source,\r
747 IN OUT VOID *Destination,\r
748 IN OUT VOID *Scratch,\r
749 IN UINT32 Version\r
750 )\r
54bd896e 751{\r
54bd896e 752 UINT32 CompSize;\r
753 UINT32 OrigSize;\r
754 SCRATCH_DATA *Sd;\r
755 CONST UINT8 *Src;\r
756 UINT8 *Dst;\r
757\r
758 ASSERT (Source != NULL);\r
759 ASSERT (Destination != NULL);\r
760 ASSERT (Scratch != NULL);\r
761\r
762 Src = Source;\r
763 Dst = Destination;\r
764\r
765 Sd = (SCRATCH_DATA *) Scratch;\r
766\r
767 CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24);\r
768 OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);\r
769\r
770 //\r
771 // If compressed file size is 0, return\r
772 //\r
773 if (OrigSize == 0) {\r
774 return RETURN_SUCCESS;\r
775 }\r
776\r
777 Src = Src + 8;\r
778\r
779b8368 779 SetMem (Sd, sizeof (SCRATCH_DATA), 0);\r
780\r
54bd896e 781 //\r
782 // The length of the field 'Position Set Code Length Array Size' in Block Header.\r
8a7d75b0 783 // For UEFI 2.0 de/compression algorithm(Version 1), mPBit = 4\r
54bd896e 784 // For Tiano de/compression algorithm(Version 2), mPBit = 5\r
785 //\r
786 switch (Version) {\r
787 case 1 :\r
788 Sd->mPBit = 4;\r
789 break;\r
790 case 2 :\r
791 Sd->mPBit = 5;\r
792 break;\r
793 default:\r
794 ASSERT (FALSE);\r
795 }\r
796 Sd->mSrcBase = (UINT8 *)Src;\r
797 Sd->mDstBase = Dst;\r
b4b6c8de 798 //\r
207f0479 799 // CompSize and OrigSize are calculated in bytes\r
b4b6c8de 800 //\r
54bd896e 801 Sd->mCompSize = CompSize;\r
802 Sd->mOrigSize = OrigSize;\r
803\r
804 //\r
805 // Fill the first BITBUFSIZ bits\r
806 //\r
807 FillBuf (Sd, BITBUFSIZ);\r
808\r
809 //\r
810 // Decompress it\r
811 //\r
812 Decode (Sd);\r
813\r
814 if (Sd->mBadTableFlag != 0) {\r
815 //\r
816 // Something wrong with the source\r
817 //\r
818 return RETURN_INVALID_PARAMETER;\r
819 }\r
820\r
821 return RETURN_SUCCESS;\r
822}\r
823\r
ed7752ec 824/**\r
b4b6c8de
LG
825 Decompresses a UEFI compressed source buffer.\r
826\r
827 Extracts decompressed data to its original form.\r
828 This function is designed so that the decompression algorithm can be implemented\r
829 without using any memory services. As a result, this function is not allowed to\r
0a6f4824 830 call any memory allocation services in its implementation. It is the caller's\r
b4b6c8de 831 responsibility to allocate and free the Destination and Scratch buffers.\r
0a6f4824
LG
832 If the compressed source data specified by Source is successfully decompressed\r
833 into Destination, then RETURN_SUCCESS is returned. If the compressed source data\r
b4b6c8de
LG
834 specified by Source is not in a valid compressed data format,\r
835 then RETURN_INVALID_PARAMETER is returned.\r
836\r
837 If Source is NULL, then ASSERT().\r
838 If Destination is NULL, then ASSERT().\r
839 If the required scratch buffer size > 0 and Scratch is NULL, then ASSERT().\r
840\r
841 @param Source The source buffer containing the compressed data.\r
842 @param Destination The destination buffer to store the decompressed data\r
843 @param Scratch A temporary scratch buffer that is used to perform the decompression.\r
0a6f4824 844 This is an optional parameter that may be NULL if the\r
b4b6c8de
LG
845 required scratch buffer size is 0.\r
846\r
0a6f4824 847 @retval RETURN_SUCCESS Decompression completed successfully, and\r
b4b6c8de 848 the uncompressed buffer is returned in Destination.\r
0a6f4824
LG
849 @retval RETURN_INVALID_PARAMETER\r
850 The source buffer specified by Source is corrupted\r
b4b6c8de 851 (not in a valid compressed format).\r
ed7752ec 852**/\r
54bd896e 853RETURN_STATUS\r
854EFIAPI\r
855UefiDecompress (\r
856 IN CONST VOID *Source,\r
857 IN OUT VOID *Destination,\r
91c68197 858 IN OUT VOID *Scratch OPTIONAL\r
54bd896e 859 )\r
54bd896e 860{\r
861 return UefiTianoDecompress (Source, Destination, Scratch, 1);\r
862}\r
863\r
ed7752ec 864/**\r
b4b6c8de
LG
865 Examines a GUIDed section and returns the size of the decoded buffer and the\r
866 size of an optional scratch buffer required to actually decode the data in a GUIDed section.\r
867\r
0a6f4824 868 Examines a GUIDed section specified by InputSection.\r
b4b6c8de 869 If GUID for InputSection does not match the GUID that this handler supports,\r
0a6f4824 870 then RETURN_UNSUPPORTED is returned.\r
b4b6c8de
LG
871 If the required information can not be retrieved from InputSection,\r
872 then RETURN_INVALID_PARAMETER is returned.\r
873 If the GUID of InputSection does match the GUID that this handler supports,\r
874 then the size required to hold the decoded buffer is returned in OututBufferSize,\r
875 the size of an optional scratch buffer is returned in ScratchSize, and the Attributes field\r
876 from EFI_GUID_DEFINED_SECTION header of InputSection is returned in SectionAttribute.\r
0a6f4824 877\r
b4b6c8de
LG
878 If InputSection is NULL, then ASSERT().\r
879 If OutputBufferSize is NULL, then ASSERT().\r
880 If ScratchBufferSize is NULL, then ASSERT().\r
881 If SectionAttribute is NULL, then ASSERT().\r
882\r
ed7752ec 883\r
b4b6c8de
LG
884 @param[in] InputSection A pointer to a GUIDed section of an FFS formatted file.\r
885 @param[out] OutputBufferSize A pointer to the size, in bytes, of an output buffer required\r
886 if the buffer specified by InputSection were decoded.\r
887 @param[out] ScratchBufferSize A pointer to the size, in bytes, required as scratch space\r
888 if the buffer specified by InputSection were decoded.\r
889 @param[out] SectionAttribute A pointer to the attributes of the GUIDed section. See the Attributes\r
890 field of EFI_GUID_DEFINED_SECTION in the PI Specification.\r
891\r
892 @retval RETURN_SUCCESS The information about InputSection was returned.\r
893 @retval RETURN_UNSUPPORTED The section specified by InputSection does not match the GUID this handler supports.\r
894 @retval RETURN_INVALID_PARAMETER The information can not be retrieved from the section specified by InputSection.\r
ed7752ec 895\r
ed7752ec 896**/\r
54bd896e 897RETURN_STATUS\r
898EFIAPI\r
18fd8d65
LG
899TianoDecompressGetInfo (\r
900 IN CONST VOID *InputSection,\r
901 OUT UINT32 *OutputBufferSize,\r
902 OUT UINT32 *ScratchBufferSize,\r
903 OUT UINT16 *SectionAttribute\r
54bd896e 904 )\r
54bd896e 905\r
54bd896e 906{\r
18fd8d65
LG
907 ASSERT (SectionAttribute != NULL);\r
908\r
909 if (InputSection == NULL) {\r
910 return RETURN_INVALID_PARAMETER;\r
d8c79a81 911 }\r
e6c560aa 912\r
30f001ca
SZ
913 if (IS_SECTION2 (InputSection)) {\r
914 if (!CompareGuid (\r
915 &gTianoCustomDecompressGuid,\r
916 &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid))) {\r
917 return RETURN_INVALID_PARAMETER;\r
918 }\r
919 //\r
0a6f4824 920 // Get guid attribute of guid section.\r
30f001ca
SZ
921 //\r
922 *SectionAttribute = ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->Attributes;\r
923\r
924 //\r
925 // Call Tiano GetInfo to get the required size info.\r
926 //\r
927 return UefiDecompressGetInfo (\r
928 (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset,\r
929 SECTION2_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset,\r
930 OutputBufferSize,\r
931 ScratchBufferSize\r
932 );\r
933 } else {\r
934 if (!CompareGuid (\r
935 &gTianoCustomDecompressGuid,\r
e6c560aa 936 &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid))) {\r
30f001ca
SZ
937 return RETURN_INVALID_PARAMETER;\r
938 }\r
939 //\r
0a6f4824 940 // Get guid attribute of guid section.\r
30f001ca
SZ
941 //\r
942 *SectionAttribute = ((EFI_GUID_DEFINED_SECTION *) InputSection)->Attributes;\r
18fd8d65 943\r
30f001ca
SZ
944 //\r
945 // Call Tiano GetInfo to get the required size info.\r
946 //\r
947 return UefiDecompressGetInfo (\r
948 (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset,\r
949 SECTION_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset,\r
950 OutputBufferSize,\r
951 ScratchBufferSize\r
952 );\r
953 }\r
54bd896e 954}\r
955\r
ed7752ec 956/**\r
b4b6c8de 957 Decompress a Tiano compressed GUIDed section into a caller allocated output buffer.\r
0a6f4824
LG
958\r
959 Decodes the GUIDed section specified by InputSection.\r
960 If GUID for InputSection does not match the GUID that this handler supports, then RETURN_UNSUPPORTED is returned.\r
b4b6c8de
LG
961 If the data in InputSection can not be decoded, then RETURN_INVALID_PARAMETER is returned.\r
962 If the GUID of InputSection does match the GUID that this handler supports, then InputSection\r
963 is decoded into the buffer specified by OutputBuffer and the authentication status of this\r
964 decode operation is returned in AuthenticationStatus. If the decoded buffer is identical to the\r
965 data in InputSection, then OutputBuffer is set to point at the data in InputSection. Otherwise,\r
966 the decoded data will be placed in caller allocated buffer specified by OutputBuffer.\r
0a6f4824 967\r
b4b6c8de
LG
968 If InputSection is NULL, then ASSERT().\r
969 If OutputBuffer is NULL, then ASSERT().\r
970 If ScratchBuffer is NULL and this decode operation requires a scratch buffer, then ASSERT().\r
971 If AuthenticationStatus is NULL, then ASSERT().\r
972\r
973\r
974 @param[in] InputSection A pointer to a GUIDed section of an FFS formatted file.\r
0a6f4824 975 @param[out] OutputBuffer A pointer to a buffer that contains the result of a decode operation.\r
b4b6c8de 976 @param[in] ScratchBuffer A caller allocated buffer that may be required by this function\r
0a6f4824
LG
977 as a scratch buffer to perform the decode operation.\r
978 @param[out] AuthenticationStatus\r
b4b6c8de
LG
979 A pointer to the authentication status of the decoded output buffer.\r
980 See the definition of authentication status in the EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI\r
981 section of the PI Specification. EFI_AUTH_STATUS_PLATFORM_OVERRIDE must\r
982 never be set by this handler.\r
983\r
984 @retval RETURN_SUCCESS The buffer specified by InputSection was decoded.\r
985 @retval RETURN_UNSUPPORTED The section specified by InputSection does not match the GUID this handler supports.\r
986 @retval RETURN_INVALID_PARAMETER The section specified by InputSection can not be decoded.\r
ed7752ec 987\r
bcd70414 988**/\r
54bd896e 989RETURN_STATUS\r
990EFIAPI\r
18fd8d65
LG
991TianoDecompress (\r
992 IN CONST VOID *InputSection,\r
993 OUT VOID **OutputBuffer,\r
994 IN VOID *ScratchBuffer, OPTIONAL\r
995 OUT UINT32 *AuthenticationStatus\r
54bd896e 996 )\r
54bd896e 997{\r
18fd8d65 998 ASSERT (OutputBuffer != NULL);\r
b4b6c8de 999 ASSERT (InputSection != NULL);\r
e6c560aa 1000\r
30f001ca
SZ
1001 if (IS_SECTION2 (InputSection)) {\r
1002 if (!CompareGuid (\r
1003 &gTianoCustomDecompressGuid,\r
1004 &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid))) {\r
1005 return RETURN_INVALID_PARAMETER;\r
1006 }\r
1007\r
1008 //\r
1009 // Set Authentication to Zero.\r
1010 //\r
1011 *AuthenticationStatus = 0;\r
1012\r
1013 //\r
1014 // Call Tiano Decompress to get the raw data\r
1015 //\r
1016 return UefiTianoDecompress (\r
1017 (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset,\r
1018 *OutputBuffer,\r
1019 ScratchBuffer,\r
1020 2\r
1021 );\r
1022 } else {\r
1023 if (!CompareGuid (\r
1024 &gTianoCustomDecompressGuid,\r
e6c560aa 1025 &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid))) {\r
30f001ca
SZ
1026 return RETURN_INVALID_PARAMETER;\r
1027 }\r
e6c560aa 1028\r
30f001ca
SZ
1029 //\r
1030 // Set Authentication to Zero.\r
1031 //\r
1032 *AuthenticationStatus = 0;\r
1033\r
1034 //\r
1035 // Call Tiano Decompress to get the raw data\r
1036 //\r
1037 return UefiTianoDecompress (\r
1038 (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset,\r
1039 *OutputBuffer,\r
1040 ScratchBuffer,\r
1041 2\r
1042 );\r
1043 }\r
54bd896e 1044}\r
d8c79a81 1045\r
ed7752ec 1046/**\r
b4b6c8de 1047 Registers TianoDecompress and TianoDecompressGetInfo handlers with TianoCustomerDecompressGuid\r
ed7752ec 1048\r
18fd8d65 1049 @retval RETURN_SUCCESS Register successfully.\r
ed7752ec 1050 @retval RETURN_OUT_OF_RESOURCES No enough memory to store this handler.\r
d8c79a81 1051**/\r
8bd22b8a 1052RETURN_STATUS\r
d8c79a81 1053EFIAPI\r
18fd8d65 1054TianoDecompressLibConstructor (\r
2344d341 1055 VOID\r
18fd8d65 1056)\r
d8c79a81 1057{\r
18fd8d65
LG
1058 return ExtractGuidedSectionRegisterHandlers (\r
1059 &gTianoCustomDecompressGuid,\r
1060 TianoDecompressGetInfo,\r
1061 TianoDecompress\r
30f001ca 1062 );\r
6bee1632 1063}\r