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