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