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