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