]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.c
Update the copyright notice format
[mirror_edk2.git] / MdePkg / Library / BaseUefiDecompressLib / BaseUefiDecompressLib.c
CommitLineData
e1f414b6 1/** @file\r
eceb3a4c 2 UEFI Decompress Library implementation refer to UEFI specification.\r
e1f414b6 3\r
6f0dc9ae 4 Copyright (c) 2006 - 2008, Intel Corporation<BR>\r
acbcf042 5 Portions copyright (c) 2008-2009 Apple Inc. All rights reserved.<BR>\r
e1f414b6 6 All rights reserved. This program and the accompanying materials\r
7 are licensed and made available under the terms and conditions of the BSD License\r
8 which accompanies this distribution. The full text of the license may be found at\r
9 http://opensource.org/licenses/bsd-license.php\r
10\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
e1f414b6 14**/\r
15\r
c892d846 16\r
c7d265a9 17#include <Base.h>\r
7fd58cbc 18#include <Library/BaseLib.h>\r
c7d265a9 19#include <Library/DebugLib.h>\r
02313d1e
LG
20#include <Library/BaseMemoryLib.h>\r
21#include <Library/UefiDecompressLib.h>\r
e1f414b6 22\r
23#include "BaseUefiDecompressLibInternals.h"\r
24\r
25/**\r
eceb3a4c 26 Read NumOfBit of bits from source into mBitBuf.\r
e1f414b6 27\r
28 Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source.\r
29\r
30 @param Sd The global scratch data\r
31 @param NumOfBits The number of bits to shift and read.\r
32\r
33**/\r
34VOID\r
35FillBuf (\r
36 IN SCRATCH_DATA *Sd,\r
37 IN UINT16 NumOfBits\r
38 )\r
39{\r
40 //\r
41 // Left shift NumOfBits of bits in advance\r
42 //\r
43 Sd->mBitBuf = (UINT32) (Sd->mBitBuf << NumOfBits);\r
44\r
45 //\r
46 // Copy data needed in bytes into mSbuBitBuf\r
47 //\r
48 while (NumOfBits > Sd->mBitCount) {\r
49\r
50 Sd->mBitBuf |= (UINT32) (Sd->mSubBitBuf << (NumOfBits = (UINT16) (NumOfBits - Sd->mBitCount)));\r
51\r
52 if (Sd->mCompSize > 0) {\r
53 //\r
54 // Get 1 byte into SubBitBuf\r
55 //\r
56 Sd->mCompSize--;\r
57 Sd->mSubBitBuf = Sd->mSrcBase[Sd->mInBuf++];\r
58 Sd->mBitCount = 8;\r
59\r
60 } else {\r
61 //\r
62 // No more bits from the source, just pad zero bit.\r
63 //\r
64 Sd->mSubBitBuf = 0;\r
65 Sd->mBitCount = 8;\r
66\r
67 }\r
68 }\r
69\r
70 //\r
71 // Caculate additional bit count read to update mBitCount\r
72 //\r
73 Sd->mBitCount = (UINT16) (Sd->mBitCount - NumOfBits);\r
74 \r
75 //\r
76 // Copy NumOfBits of bits from mSubBitBuf into mBitBuf\r
77 //\r
78 Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount;\r
79}\r
80\r
81/**\r
eceb3a4c 82 Get NumOfBits of bits out from mBitBuf.\r
e1f414b6 83\r
efb23117 84 Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent\r
85 NumOfBits of bits from source. Returns NumOfBits of bits that are\r
e1f414b6 86 popped out.\r
87\r
88 @param Sd The global scratch data.\r
89 @param NumOfBits The number of bits to pop and read.\r
90\r
91 @return The bits that are popped out.\r
92\r
93**/\r
94UINT32\r
95GetBits (\r
96 IN SCRATCH_DATA *Sd,\r
97 IN UINT16 NumOfBits\r
98 )\r
99{\r
100 UINT32 OutBits;\r
101\r
102 //\r
103 // Pop NumOfBits of Bits from Left\r
104 // \r
105 OutBits = (UINT32) (Sd->mBitBuf >> (BITBUFSIZ - NumOfBits));\r
106\r
107 //\r
108 // Fill up mBitBuf from source\r
109 //\r
110 FillBuf (Sd, NumOfBits);\r
111\r
112 return OutBits;\r
113}\r
114\r
115/**\r
116 Creates Huffman Code mapping table according to code length array.\r
117\r
efb23117 118 Creates Huffman Code mapping table for Extra Set, Char&Len Set\r
e1f414b6 119 and Position Set according to code length array.\r
120\r
121 @param Sd The global scratch data\r
122 @param NumOfChar Number of symbols in the symbol set\r
123 @param BitLen Code length array\r
124 @param TableBits The width of the mapping table\r
efb23117 125 @param Table The table to be created.\r
e1f414b6 126\r
127 @retval 0 OK.\r
128 @retval BAD_TABLE The table is corrupted.\r
129\r
130**/\r
131UINT16\r
132MakeTable (\r
133 IN SCRATCH_DATA *Sd,\r
134 IN UINT16 NumOfChar,\r
135 IN UINT8 *BitLen,\r
136 IN UINT16 TableBits,\r
137 OUT UINT16 *Table\r
138 )\r
139{\r
140 UINT16 Count[17];\r
141 UINT16 Weight[17];\r
142 UINT16 Start[18];\r
143 UINT16 *Pointer;\r
144 UINT16 Index3;\r
02313d1e 145 UINT16 Index;\r
e1f414b6 146 UINT16 Len;\r
147 UINT16 Char;\r
148 UINT16 JuBits;\r
149 UINT16 Avail;\r
150 UINT16 NextCode;\r
151 UINT16 Mask;\r
152 UINT16 WordOfStart;\r
153 UINT16 WordOfCount;\r
154\r
155\r
9872985b 156 for (Index = 0; Index <= 16; Index++) {\r
e1f414b6 157 Count[Index] = 0;\r
158 }\r
159\r
160 for (Index = 0; Index < NumOfChar; Index++) {\r
161 Count[BitLen[Index]]++;\r
162 }\r
9872985b
LG
163 \r
164 Start[0] = 0;\r
e1f414b6 165 Start[1] = 0;\r
166\r
167 for (Index = 1; Index <= 16; Index++) {\r
168 WordOfStart = Start[Index];\r
169 WordOfCount = Count[Index];\r
170 Start[Index + 1] = (UINT16) (WordOfStart + (WordOfCount << (16 - Index)));\r
171 }\r
172\r
173 if (Start[17] != 0) {\r
174 /*(1U << 16)*/\r
175 return (UINT16) BAD_TABLE;\r
176 }\r
177\r
178 JuBits = (UINT16) (16 - TableBits);\r
9872985b
LG
179 \r
180 Weight[0] = 0;\r
e1f414b6 181 for (Index = 1; Index <= TableBits; Index++) {\r
182 Start[Index] >>= JuBits;\r
183 Weight[Index] = (UINT16) (1U << (TableBits - Index));\r
184 }\r
185\r
186 while (Index <= 16) {\r
187 Weight[Index] = (UINT16) (1U << (16 - Index));\r
188 Index++; \r
189 }\r
190\r
191 Index = (UINT16) (Start[TableBits + 1] >> JuBits);\r
192\r
193 if (Index != 0) {\r
194 Index3 = (UINT16) (1U << TableBits);\r
02313d1e
LG
195 if (Index < Index3) {\r
196 SetMem16 (Table + Index, (Index3 - Index) * sizeof (*Table), 0);\r
e1f414b6 197 }\r
198 }\r
199\r
200 Avail = NumOfChar;\r
201 Mask = (UINT16) (1U << (15 - TableBits));\r
202\r
203 for (Char = 0; Char < NumOfChar; Char++) {\r
204\r
205 Len = BitLen[Char];\r
9872985b 206 if (Len == 0 || Len >= 17) {\r
e1f414b6 207 continue;\r
208 }\r
209\r
210 NextCode = (UINT16) (Start[Len] + Weight[Len]);\r
211\r
212 if (Len <= TableBits) {\r
213\r
214 for (Index = Start[Len]; Index < NextCode; Index++) {\r
215 Table[Index] = Char;\r
216 }\r
217\r
218 } else {\r
219\r
220 Index3 = Start[Len];\r
221 Pointer = &Table[Index3 >> JuBits];\r
222 Index = (UINT16) (Len - TableBits);\r
223\r
224 while (Index != 0) {\r
0ba7fffd 225 if (*Pointer == 0 && Avail < (2 * NC - 1)) {\r
9872985b 226 Sd->mRight[Avail] = Sd->mLeft[Avail] = 0;\r
e1f414b6 227 *Pointer = Avail++;\r
228 }\r
29666911
LG
229 \r
230 if (*Pointer < (2 * NC - 1)) {\r
231 if ((Index3 & Mask) != 0) {\r
232 Pointer = &Sd->mRight[*Pointer];\r
233 } else {\r
234 Pointer = &Sd->mLeft[*Pointer];\r
235 }\r
e1f414b6 236 }\r
237\r
238 Index3 <<= 1;\r
239 Index--;\r
240 }\r
241\r
242 *Pointer = Char;\r
243\r
244 }\r
245\r
246 Start[Len] = NextCode;\r
247 }\r
248 //\r
249 // Succeeds\r
250 //\r
251 return 0;\r
252}\r
253\r
254/**\r
255 Decodes a position value.\r
256\r
257 Get a position value according to Position Huffman Table.\r
efb23117 258\r
e1f414b6 259 @param Sd the global scratch data\r
260\r
261 @return The position value decoded.\r
262\r
263**/\r
264UINT32\r
265DecodeP (\r
266 IN SCRATCH_DATA *Sd\r
267 )\r
268{\r
269 UINT16 Val;\r
270 UINT32 Mask;\r
271 UINT32 Pos;\r
272\r
273 Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];\r
274\r
275 if (Val >= MAXNP) {\r
276 Mask = 1U << (BITBUFSIZ - 1 - 8);\r
277\r
278 do {\r
279\r
eceb3a4c 280 if ((Sd->mBitBuf & Mask) != 0) {\r
e1f414b6 281 Val = Sd->mRight[Val];\r
282 } else {\r
283 Val = Sd->mLeft[Val];\r
284 }\r
285\r
286 Mask >>= 1;\r
287 } while (Val >= MAXNP);\r
288 }\r
289 //\r
290 // Advance what we have read\r
291 //\r
292 FillBuf (Sd, Sd->mPTLen[Val]);\r
293\r
294 Pos = Val;\r
295 if (Val > 1) {\r
296 Pos = (UINT32) ((1U << (Val - 1)) + GetBits (Sd, (UINT16) (Val - 1)));\r
297 }\r
298\r
299 return Pos;\r
300}\r
301\r
302/**\r
303 Reads code lengths for the Extra Set or the Position Set.\r
304\r
305 Read in the Extra Set or Pointion Set Length Arrary, then\r
306 generate the Huffman code mapping for them.\r
307\r
308 @param Sd The global scratch data.\r
309 @param nn Number of symbols.\r
310 @param nbit Number of bits needed to represent nn.\r
311 @param Special The special symbol that needs to be taken care of.\r
312\r
313 @retval 0 OK.\r
314 @retval BAD_TABLE Table is corrupted.\r
315\r
316**/\r
317UINT16\r
318ReadPTLen (\r
319 IN SCRATCH_DATA *Sd,\r
320 IN UINT16 nn,\r
321 IN UINT16 nbit,\r
322 IN UINT16 Special\r
323 )\r
324{\r
325 UINT16 Number;\r
326 UINT16 CharC;\r
02313d1e 327 UINT16 Index;\r
e1f414b6 328 UINT32 Mask;\r
329\r
330 //\r
331 // Read Extra Set Code Length Array size \r
332 //\r
333 Number = (UINT16) GetBits (Sd, nbit);\r
334\r
335 if (Number == 0) {\r
336 //\r
337 // This represents only Huffman code used\r
338 //\r
339 CharC = (UINT16) GetBits (Sd, nbit);\r
340\r
ebd04fc2 341 SetMem16 (&Sd->mPTTable[0] , sizeof (Sd->mPTTable), CharC);\r
e1f414b6 342\r
02313d1e 343 SetMem (Sd->mPTLen, nn, 0);\r
e1f414b6 344\r
345 return 0;\r
346 }\r
347\r
348 Index = 0;\r
349\r
9872985b 350 while (Index < Number && Index < NPT) {\r
e1f414b6 351\r
352 CharC = (UINT16) (Sd->mBitBuf >> (BITBUFSIZ - 3));\r
353\r
354 //\r
355 // If a code length is less than 7, then it is encoded as a 3-bit\r
356 // value. Or it is encoded as a series of "1"s followed by a \r
357 // terminating "0". The number of "1"s = Code length - 4.\r
358 //\r
359 if (CharC == 7) {\r
360 Mask = 1U << (BITBUFSIZ - 1 - 3);\r
361 while (Mask & Sd->mBitBuf) {\r
362 Mask >>= 1;\r
363 CharC += 1;\r
364 }\r
365 }\r
366 \r
367 FillBuf (Sd, (UINT16) ((CharC < 7) ? 3 : CharC - 3));\r
368\r
369 Sd->mPTLen[Index++] = (UINT8) CharC;\r
370 \r
371 //\r
372 // For Code&Len Set, \r
373 // After the third length of the code length concatenation,\r
374 // a 2-bit value is used to indicated the number of consecutive \r
375 // zero lengths after the third length.\r
376 //\r
377 if (Index == Special) {\r
378 CharC = (UINT16) GetBits (Sd, 2);\r
0ba7fffd 379 while ((INT16) (--CharC) >= 0 && Index < NPT) {\r
e1f414b6 380 Sd->mPTLen[Index++] = 0;\r
381 }\r
382 }\r
383 }\r
384\r
9872985b 385 while (Index < nn && Index < NPT) {\r
e1f414b6 386 Sd->mPTLen[Index++] = 0;\r
387 }\r
388 \r
389 return MakeTable (Sd, nn, Sd->mPTLen, 8, Sd->mPTTable);\r
390}\r
391\r
392/**\r
393 Reads code lengths for Char&Len Set.\r
efb23117 394\r
e1f414b6 395 Read in and decode the Char&Len Set Code Length Array, then\r
396 generate the Huffman Code mapping table for the Char&Len Set.\r
397\r
398 @param Sd the global scratch data\r
399\r
400**/\r
401VOID\r
402ReadCLen (\r
403 SCRATCH_DATA *Sd\r
404 )\r
405{\r
406 UINT16 Number;\r
407 UINT16 CharC;\r
02313d1e 408 UINT16 Index;\r
e1f414b6 409 UINT32 Mask;\r
410\r
411 Number = (UINT16) GetBits (Sd, CBIT);\r
412\r
413 if (Number == 0) {\r
414 //\r
415 // This represents only Huffman code used\r
416 //\r
417 CharC = (UINT16) GetBits (Sd, CBIT);\r
418\r
02313d1e 419 SetMem (Sd->mCLen, NC, 0);\r
ebd04fc2 420 SetMem16 (&Sd->mCTable[0], sizeof (Sd->mCTable), CharC);\r
e1f414b6 421\r
422 return ;\r
423 }\r
424\r
425 Index = 0;\r
9872985b 426 while (Index < Number && Index < NC) {\r
e1f414b6 427 CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];\r
428 if (CharC >= NT) {\r
429 Mask = 1U << (BITBUFSIZ - 1 - 8);\r
430\r
431 do {\r
432\r
433 if (Mask & Sd->mBitBuf) {\r
434 CharC = Sd->mRight[CharC];\r
435 } else {\r
436 CharC = Sd->mLeft[CharC];\r
437 }\r
438\r
439 Mask >>= 1;\r
440\r
441 } while (CharC >= NT);\r
442 }\r
443 //\r
444 // Advance what we have read\r
445 //\r
446 FillBuf (Sd, Sd->mPTLen[CharC]);\r
447\r
448 if (CharC <= 2) {\r
449\r
450 if (CharC == 0) {\r
451 CharC = 1;\r
452 } else if (CharC == 1) {\r
453 CharC = (UINT16) (GetBits (Sd, 4) + 3);\r
454 } else if (CharC == 2) {\r
455 CharC = (UINT16) (GetBits (Sd, CBIT) + 20);\r
456 }\r
457\r
0ba7fffd 458 while ((INT16) (--CharC) >= 0 && Index < NC) {\r
e1f414b6 459 Sd->mCLen[Index++] = 0;\r
460 }\r
461\r
462 } else {\r
463\r
464 Sd->mCLen[Index++] = (UINT8) (CharC - 2);\r
465\r
466 }\r
467 }\r
468\r
02313d1e 469 SetMem (Sd->mCLen + Index, NC - Index, 0);\r
e1f414b6 470\r
471 MakeTable (Sd, NC, Sd->mCLen, 12, Sd->mCTable);\r
472\r
473 return ;\r
474}\r
475\r
476/**\r
477 Decode a character/length value.\r
efb23117 478\r
e1f414b6 479 Read one value from mBitBuf, Get one code from mBitBuf. If it is at block boundary, generates\r
480 Huffman code mapping table for Extra Set, Code&Len Set and\r
481 Position Set.\r
482\r
483 @param Sd The global scratch data.\r
484\r
485 @return The value decoded.\r
486\r
487**/\r
488UINT16\r
489DecodeC (\r
490 SCRATCH_DATA *Sd\r
491 )\r
492{\r
493 UINT16 Index2;\r
494 UINT32 Mask;\r
495\r
496 if (Sd->mBlockSize == 0) {\r
497 //\r
498 // Starting a new block\r
499 // Read BlockSize from block header\r
500 // \r
501 Sd->mBlockSize = (UINT16) GetBits (Sd, 16);\r
502\r
503 //\r
504 // Read in the Extra Set Code Length Arrary,\r
505 // Generate the Huffman code mapping table for Extra Set.\r
506 //\r
507 Sd->mBadTableFlag = ReadPTLen (Sd, NT, TBIT, 3);\r
508 if (Sd->mBadTableFlag != 0) {\r
509 return 0;\r
510 }\r
511\r
512 //\r
513 // Read in and decode the Char&Len Set Code Length Arrary,\r
514 // Generate the Huffman code mapping table for Char&Len Set.\r
515 //\r
516 ReadCLen (Sd);\r
517\r
518 //\r
519 // Read in the Position Set Code Length Arrary, \r
520 // Generate the Huffman code mapping table for the Position Set.\r
521 //\r
522 Sd->mBadTableFlag = ReadPTLen (Sd, MAXNP, Sd->mPBit, (UINT16) (-1));\r
523 if (Sd->mBadTableFlag != 0) {\r
524 return 0;\r
525 }\r
526 }\r
527\r
528 //\r
529 // Get one code according to Code&Set Huffman Table\r
530 //\r
531 Sd->mBlockSize--;\r
532 Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)];\r
533\r
534 if (Index2 >= NC) {\r
535 Mask = 1U << (BITBUFSIZ - 1 - 12);\r
536\r
537 do {\r
eceb3a4c 538 if ((Sd->mBitBuf & Mask) != 0) {\r
e1f414b6 539 Index2 = Sd->mRight[Index2];\r
540 } else {\r
541 Index2 = Sd->mLeft[Index2];\r
542 }\r
543\r
544 Mask >>= 1;\r
545 } while (Index2 >= NC);\r
546 }\r
547 //\r
548 // Advance what we have read\r
549 //\r
550 FillBuf (Sd, Sd->mCLen[Index2]);\r
551\r
552 return Index2;\r
553}\r
554\r
555/**\r
556 Decode the source data and put the resulting data into the destination buffer.\r
efb23117 557\r
e1f414b6 558 @param Sd The global scratch data\r
559\r
560**/\r
561VOID\r
562Decode (\r
563 SCRATCH_DATA *Sd\r
564 )\r
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
575 //\r
576 // Get one code from mBitBuf\r
577 // \r
578 CharC = DecodeC (Sd);\r
579 if (Sd->mBadTableFlag != 0) {\r
580 goto Done;\r
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
588 goto Done;\r
589 } else {\r
590 //\r
591 // Write orignal character into mDstBase\r
592 //\r
593 Sd->mDstBase[Sd->mOutBuf++] = (UINT8) CharC;\r
594 }\r
595\r
596 } else {\r
597 //\r
598 // Process a Pointer\r
599 //\r
daa6553a 600 CharC = (UINT16) (CharC - (BIT8 - THRESHOLD));\r
e1f414b6 601 \r
602 //\r
603 // Get string length\r
604 //\r
605 BytesRemain = CharC;\r
606\r
607 //\r
608 // Locate string position\r
609 //\r
610 DataIdx = Sd->mOutBuf - DecodeP (Sd) - 1;\r
611\r
612 //\r
613 // Write BytesRemain of bytes into mDstBase\r
614 //\r
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
631/**\r
eceb3a4c
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
e1f414b6 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
eceb3a4c
LG
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
e1f414b6 669**/\r
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
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
e1f414b6 685 if (SourceSize < 8) {\r
686 return RETURN_INVALID_PARAMETER;\r
687 }\r
688\r
7fd58cbc 689 CompressedSize = ReadUnaligned32 ((UINT32 *)Source);\r
e1f414b6 690 if (SourceSize < (CompressedSize + 8)) {\r
691 return RETURN_INVALID_PARAMETER;\r
692 }\r
693\r
7fd58cbc 694 *ScratchSize = sizeof (SCRATCH_DATA);\r
695 *DestinationSize = ReadUnaligned32 ((UINT32 *)Source + 1);\r
696\r
e1f414b6 697 return RETURN_SUCCESS;\r
698}\r
699\r
700/**\r
701 Decompresses a compressed source buffer.\r
702\r
eceb3a4c 703 Extracts decompressed data to its original form.\r
e1f414b6 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
28d3e14f 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
e1f414b6 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 \r
eceb3a4c
LG
723 @retval RETURN_SUCCESS Decompression completed successfully, and \r
724 the uncompressed buffer is returned in Destination.\r
725 @retval RETURN_INVALID_PARAMETER \r
726 The source buffer specified by Source is corrupted \r
727 (not in a valid compressed format).\r
e1f414b6 728**/\r
729RETURN_STATUS\r
730EFIAPI\r
731UefiDecompress (\r
732 IN CONST VOID *Source,\r
733 IN OUT VOID *Destination,\r
6d6a1098 734 IN OUT VOID *Scratch OPTIONAL\r
e1f414b6 735 )\r
736{\r
e1f414b6 737 UINT32 CompSize;\r
738 UINT32 OrigSize;\r
739 SCRATCH_DATA *Sd;\r
740 CONST UINT8 *Src;\r
741 UINT8 *Dst;\r
742\r
743 ASSERT (Source != NULL);\r
744 ASSERT (Destination != NULL);\r
745 ASSERT (Scratch != NULL);\r
746\r
747 Src = Source;\r
748 Dst = Destination;\r
749\r
750 Sd = (SCRATCH_DATA *) Scratch;\r
751\r
752 CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24);\r
753 OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);\r
754\r
755 //\r
756 // If compressed file size is 0, return\r
757 //\r
758 if (OrigSize == 0) {\r
759 return RETURN_SUCCESS;\r
760 }\r
761\r
762 Src = Src + 8;\r
02313d1e 763 SetMem (Sd, sizeof (SCRATCH_DATA), 0);\r
e1f414b6 764\r
e1f414b6 765 //\r
766 // The length of the field 'Position Set Code Length Array Size' in Block Header.\r
8a7d75b0 767 // For UEFI 2.0 de/compression algorithm(Version 1), mPBit = 4\r
e1f414b6 768 //\r
769 Sd->mPBit = 4;\r
770 Sd->mSrcBase = (UINT8 *)Src;\r
771 Sd->mDstBase = Dst;\r
772 //\r
773 // CompSize and OrigSize are caculated in bytes\r
774 //\r
775 Sd->mCompSize = CompSize;\r
776 Sd->mOrigSize = OrigSize;\r
777\r
778 //\r
779 // Fill the first BITBUFSIZ bits\r
780 //\r
781 FillBuf (Sd, BITBUFSIZ);\r
782\r
783 //\r
784 // Decompress it\r
785 //\r
786 Decode (Sd);\r
787\r
788 if (Sd->mBadTableFlag != 0) {\r
789 //\r
790 // Something wrong with the source\r
791 //\r
792 return RETURN_INVALID_PARAMETER;\r
793 }\r
794\r
795 return RETURN_SUCCESS;\r
796}\r