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