]>
Commit | Line | Data |
---|---|---|
b4b6c8de LG |
1 | /** @file\r |
2 | UEFI and Tiano Custom Decompress Library \r | |
3 | Tt will do Tiano or UEFI decompress with different verison parameter.\r | |
3db51098 | 4 | \r |
180a5a35 HT |
5 | Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>\r |
6 | This program and the accompanying materials \r | |
54bd896e | 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 | |
3db51098 | 14 | **/\r |
54bd896e | 15 | \r |
54bd896e | 16 | #include "BaseUefiTianoCustomDecompressLibInternals.h"\r |
17 | \r | |
ed7752ec | 18 | /**\r |
19 | Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source.\r | |
20 | \r | |
21 | @param Sd The global scratch data\r | |
22 | @param NumOfBits The number of bits to shift and read. \r | |
23 | **/\r | |
54bd896e | 24 | VOID\r |
25 | FillBuf (\r | |
26 | IN SCRATCH_DATA *Sd,\r | |
27 | IN UINT16 NumOfBits\r | |
28 | )\r | |
54bd896e | 29 | {\r |
b4b6c8de LG |
30 | //\r |
31 | // Left shift NumOfBits of bits in advance\r | |
32 | //\r | |
54bd896e | 33 | Sd->mBitBuf = (UINT32) (Sd->mBitBuf << NumOfBits);\r |
34 | \r | |
b4b6c8de LG |
35 | //\r |
36 | // Copy data needed in bytes into mSbuBitBuf\r | |
37 | //\r | |
54bd896e | 38 | while (NumOfBits > Sd->mBitCount) {\r |
39 | \r | |
40 | Sd->mBitBuf |= (UINT32) (Sd->mSubBitBuf << (NumOfBits = (UINT16) (NumOfBits - Sd->mBitCount)));\r | |
41 | \r | |
42 | if (Sd->mCompSize > 0) {\r | |
43 | //\r | |
44 | // Get 1 byte into SubBitBuf\r | |
45 | //\r | |
46 | Sd->mCompSize--;\r | |
47 | Sd->mSubBitBuf = 0;\r | |
48 | Sd->mSubBitBuf = Sd->mSrcBase[Sd->mInBuf++];\r | |
49 | Sd->mBitCount = 8;\r | |
50 | \r | |
51 | } else {\r | |
52 | //\r | |
53 | // No more bits from the source, just pad zero bit.\r | |
54 | //\r | |
55 | Sd->mSubBitBuf = 0;\r | |
56 | Sd->mBitCount = 8;\r | |
57 | \r | |
58 | }\r | |
59 | }\r | |
60 | \r | |
b4b6c8de LG |
61 | //\r |
62 | // Caculate additional bit count read to update mBitCount\r | |
63 | //\r | |
54bd896e | 64 | Sd->mBitCount = (UINT16) (Sd->mBitCount - NumOfBits);\r |
b4b6c8de LG |
65 | \r |
66 | //\r | |
67 | // Copy NumOfBits of bits from mSubBitBuf into mBitBuf\r | |
68 | //\r | |
54bd896e | 69 | Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount;\r |
70 | }\r | |
71 | \r | |
ed7752ec | 72 | /**\r |
73 | Get NumOfBits of bits out from mBitBuf\r | |
54bd896e | 74 | \r |
75 | Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent \r | |
76 | NumOfBits of bits from source. Returns NumOfBits of bits that are \r | |
77 | popped out.\r | |
78 | \r | |
ed7752ec | 79 | @param Sd The global scratch data.\r |
80 | @param NumOfBits The number of bits to pop and read.\r | |
54bd896e | 81 | \r |
ed7752ec | 82 | @return The bits that are popped out.\r |
54bd896e | 83 | \r |
ed7752ec | 84 | **/\r |
85 | UINT32\r | |
86 | GetBits (\r | |
87 | IN SCRATCH_DATA *Sd,\r | |
88 | IN UINT16 NumOfBits\r | |
89 | )\r | |
54bd896e | 90 | {\r |
91 | UINT32 OutBits;\r | |
92 | \r | |
b4b6c8de LG |
93 | //\r |
94 | // Pop NumOfBits of Bits from Left\r | |
95 | // \r | |
54bd896e | 96 | OutBits = (UINT32) (Sd->mBitBuf >> (BITBUFSIZ - NumOfBits));\r |
97 | \r | |
b4b6c8de LG |
98 | //\r |
99 | // Fill up mBitBuf from source\r | |
100 | //\r | |
54bd896e | 101 | FillBuf (Sd, NumOfBits);\r |
102 | \r | |
103 | return OutBits;\r | |
104 | }\r | |
105 | \r | |
ed7752ec | 106 | /**\r |
107 | Creates Huffman Code mapping table according to code length array.\r | |
108 | \r | |
109 | Creates Huffman Code mapping table for Extra Set, Char&Len Set \r | |
110 | and Position Set according to code length array.\r | |
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 | |
b4b6c8de | 116 | @param Table The table to be created.\r |
ed7752ec | 117 | \r |
118 | @retval 0 OK.\r | |
119 | @retval BAD_TABLE The table is corrupted.\r | |
120 | \r | |
121 | **/\r | |
54bd896e | 122 | UINT16\r |
123 | MakeTable (\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 | |
54bd896e | 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 | |
80267d51 | 136 | UINT16 Index;\r |
54bd896e | 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 | |
aa950314 | 146 | for (Index = 0; Index <= 16; Index++) {\r |
54bd896e | 147 | Count[Index] = 0;\r |
148 | }\r | |
149 | \r | |
150 | for (Index = 0; Index < NumOfChar; Index++) {\r | |
151 | Count[BitLen[Index]]++;\r | |
152 | }\r | |
aa950314 | 153 | \r |
154 | Start[0] = 0;\r | |
54bd896e | 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 | |
aa950314 | 169 | \r |
170 | Weight[0] = 0;\r | |
54bd896e | 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 | |
aa950314 | 178 | Index++; \r |
54bd896e | 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 | |
aa950314 | 185 | if (Index < Index3) {\r |
186 | SetMem16 (Table + Index, (Index3 - Index) * sizeof (*Table), 0);\r | |
54bd896e | 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 | |
aa950314 | 196 | if (Len == 0 || Len >= 17) {\r |
54bd896e | 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 | |
aa950314 | 215 | if (*Pointer == 0 && Avail < (2 * NC - 1)) {\r |
216 | Sd->mRight[Avail] = Sd->mLeft[Avail] = 0;\r | |
54bd896e | 217 | *Pointer = Avail++;\r |
218 | }\r | |
aa950314 | 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 | |
54bd896e | 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 | |
ed7752ec | 244 | /**\r |
245 | Decodes a position value.\r | |
246 | \r | |
b4b6c8de LG |
247 | Get a position value according to Position Huffman Table.\r |
248 | \r | |
ed7752ec | 249 | @param Sd the global scratch data\r |
250 | \r | |
251 | @return The position value decoded.\r | |
252 | **/\r | |
54bd896e | 253 | UINT32\r |
254 | DecodeP (\r | |
255 | IN SCRATCH_DATA *Sd\r | |
256 | )\r | |
54bd896e | 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 | |
b4b6c8de | 269 | if ((Sd->mBitBuf & Mask) != 0) {\r |
54bd896e | 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 | |
ed7752ec | 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 | |
54bd896e | 306 | UINT16\r |
307 | ReadPTLen (\r | |
308 | IN SCRATCH_DATA *Sd,\r | |
309 | IN UINT16 nn,\r | |
310 | IN UINT16 nbit,\r | |
311 | IN UINT16 Special\r | |
312 | )\r | |
54bd896e | 313 | {\r |
314 | UINT16 Number;\r | |
315 | UINT16 CharC;\r | |
80267d51 | 316 | UINT16 Index;\r |
54bd896e | 317 | UINT32 Mask;\r |
318 | \r | |
aa950314 | 319 | //\r |
320 | // Read Extra Set Code Length Array size \r | |
321 | //\r | |
54bd896e | 322 | Number = (UINT16) GetBits (Sd, nbit);\r |
323 | \r | |
324 | if (Number == 0) {\r | |
aa950314 | 325 | //\r |
326 | // This represents only Huffman code used\r | |
327 | //\r | |
54bd896e | 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 | |
aa950314 | 334 | SetMem (Sd->mPTLen, nn, 0);\r |
54bd896e | 335 | \r |
336 | return 0;\r | |
337 | }\r | |
338 | \r | |
339 | Index = 0;\r | |
340 | \r | |
aa950314 | 341 | while (Index < Number && Index < NPT) {\r |
54bd896e | 342 | \r |
343 | CharC = (UINT16) (Sd->mBitBuf >> (BITBUFSIZ - 3));\r | |
344 | \r | |
aa950314 | 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 | |
54bd896e | 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 | |
aa950314 | 357 | \r |
54bd896e | 358 | FillBuf (Sd, (UINT16) ((CharC < 7) ? 3 : CharC - 3));\r |
359 | \r | |
360 | Sd->mPTLen[Index++] = (UINT8) CharC;\r | |
aa950314 | 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 | |
54bd896e | 368 | if (Index == Special) {\r |
369 | CharC = (UINT16) GetBits (Sd, 2);\r | |
aa950314 | 370 | while ((INT16) (--CharC) >= 0 && Index < NPT) {\r |
54bd896e | 371 | Sd->mPTLen[Index++] = 0;\r |
372 | }\r | |
373 | }\r | |
374 | }\r | |
375 | \r | |
aa950314 | 376 | while (Index < nn && Index < NPT) {\r |
54bd896e | 377 | Sd->mPTLen[Index++] = 0;\r |
378 | }\r | |
aa950314 | 379 | \r |
54bd896e | 380 | return MakeTable (Sd, nn, Sd->mPTLen, 8, Sd->mPTTable);\r |
381 | }\r | |
382 | \r | |
ed7752ec | 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 | |
54bd896e | 392 | VOID\r |
393 | ReadCLen (\r | |
394 | SCRATCH_DATA *Sd\r | |
395 | )\r | |
54bd896e | 396 | {\r |
397 | UINT16 Number;\r | |
398 | UINT16 CharC;\r | |
80267d51 | 399 | UINT16 Index;\r |
54bd896e | 400 | UINT32 Mask;\r |
401 | \r | |
402 | Number = (UINT16) GetBits (Sd, CBIT);\r | |
403 | \r | |
404 | if (Number == 0) {\r | |
aa950314 | 405 | //\r |
406 | // This represents only Huffman code used\r | |
407 | //\r | |
54bd896e | 408 | CharC = (UINT16) GetBits (Sd, CBIT);\r |
409 | \r | |
aa950314 | 410 | SetMem (Sd->mCLen, NC, 0);\r |
54bd896e | 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 | |
aa950314 | 420 | while (Index < Number && Index < NC) {\r |
54bd896e | 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 | |
aa950314 | 452 | while ((INT16) (--CharC) >= 0 && Index < NC) {\r |
54bd896e | 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 | |
aa950314 | 463 | SetMem (Sd->mCLen + Index, NC - Index, 0);\r |
54bd896e | 464 | \r |
465 | MakeTable (Sd, NC, Sd->mCLen, 12, Sd->mCTable);\r | |
466 | \r | |
467 | return ;\r | |
468 | }\r | |
469 | \r | |
ed7752ec | 470 | /**\r |
54bd896e | 471 | Decode a character/length value.\r |
ed7752ec | 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 | |
54bd896e | 476 | \r |
ed7752ec | 477 | @param Sd The global scratch data.\r |
54bd896e | 478 | \r |
ed7752ec | 479 | @return The value decoded.\r |
54bd896e | 480 | \r |
ed7752ec | 481 | **/\r |
482 | UINT16\r | |
483 | DecodeC (\r | |
484 | SCRATCH_DATA *Sd\r | |
485 | )\r | |
54bd896e | 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 | |
b4b6c8de LG |
493 | // Read BlockSize from block header\r |
494 | // \r | |
54bd896e | 495 | Sd->mBlockSize = (UINT16) GetBits (Sd, 16);\r |
b4b6c8de LG |
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 | |
54bd896e | 501 | Sd->mBadTableFlag = ReadPTLen (Sd, NT, TBIT, 3);\r |
502 | if (Sd->mBadTableFlag != 0) {\r | |
503 | return 0;\r | |
504 | }\r | |
505 | \r | |
b4b6c8de LG |
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 | |
54bd896e | 510 | ReadCLen (Sd);\r |
511 | \r | |
b4b6c8de LG |
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 | |
54bd896e | 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 | |
b4b6c8de LG |
522 | //\r |
523 | // Get one code according to Code&Set Huffman Table\r | |
524 | //\r | |
54bd896e | 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 | |
b4b6c8de | 532 | if ((Sd->mBitBuf & Mask) != 0) {\r |
54bd896e | 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 | |
ed7752ec | 549 | /**\r |
b4b6c8de | 550 | Decode the source data and put the resulting data into the destination buffer.\r |
ed7752ec | 551 | \r |
b4b6c8de | 552 | @param Sd The global scratch data\r |
ed7752ec | 553 | **/\r |
54bd896e | 554 | VOID\r |
555 | Decode (\r | |
556 | SCRATCH_DATA *Sd\r | |
557 | )\r | |
54bd896e | 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 | |
b4b6c8de LG |
568 | //\r |
569 | // Get one code from mBitBuf\r | |
570 | // \r | |
54bd896e | 571 | CharC = DecodeC (Sd);\r |
572 | if (Sd->mBadTableFlag != 0) {\r | |
b4b6c8de | 573 | goto Done;\r |
54bd896e | 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 | |
b4b6c8de | 581 | goto Done;\r |
54bd896e | 582 | } else {\r |
b4b6c8de LG |
583 | //\r |
584 | // Write orignal character into mDstBase\r | |
585 | //\r | |
54bd896e | 586 | Sd->mDstBase[Sd->mOutBuf++] = (UINT8) CharC;\r |
587 | }\r | |
588 | \r | |
589 | } else {\r | |
590 | //\r | |
591 | // Process a Pointer\r | |
592 | //\r | |
15793911 | 593 | CharC = (UINT16) (CharC - (BIT8 - THRESHOLD));\r |
b4b6c8de LG |
594 | \r |
595 | //\r | |
596 | // Get string length\r | |
597 | //\r | |
54bd896e | 598 | BytesRemain = CharC;\r |
599 | \r | |
b4b6c8de LG |
600 | //\r |
601 | // Locate string position\r | |
602 | //\r | |
54bd896e | 603 | DataIdx = Sd->mOutBuf - DecodeP (Sd) - 1;\r |
604 | \r | |
b4b6c8de LG |
605 | //\r |
606 | // Write BytesRemain of bytes into mDstBase\r | |
607 | //\r | |
54bd896e | 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 | |
620 | Done:\r | |
621 | return ;\r | |
622 | }\r | |
623 | \r | |
ed7752ec | 624 | /**\r |
b4b6c8de LG |
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 | |
ed7752ec | 662 | **/\r |
54bd896e | 663 | RETURN_STATUS\r |
664 | EFIAPI\r | |
665 | UefiDecompressGetInfo (\r | |
666 | IN CONST VOID *Source,\r | |
667 | IN UINT32 SourceSize,\r | |
668 | OUT UINT32 *DestinationSize,\r | |
669 | OUT UINT32 *ScratchSize\r | |
670 | )\r | |
54bd896e | 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 | |
54bd896e | 678 | if (SourceSize < 8) {\r |
679 | return RETURN_INVALID_PARAMETER;\r | |
680 | }\r | |
681 | \r | |
e69a0629 | 682 | CompressedSize = ReadUnaligned32 ((UINT32 *)Source);\r |
54bd896e | 683 | if (SourceSize < (CompressedSize + 8)) {\r |
684 | return RETURN_INVALID_PARAMETER;\r | |
685 | }\r | |
686 | \r | |
18fd8d65 | 687 | *ScratchSize = sizeof (SCRATCH_DATA);\r |
e69a0629 | 688 | *DestinationSize = ReadUnaligned32 ((UINT32 *)Source + 1);\r |
18fd8d65 | 689 | \r |
54bd896e | 690 | return RETURN_SUCCESS;\r |
691 | }\r | |
692 | \r | |
ed7752ec | 693 | /**\r |
b4b6c8de LG |
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 | |
ed7752ec | 722 | **/\r |
54bd896e | 723 | RETURN_STATUS\r |
724 | EFIAPI\r | |
725 | UefiTianoDecompress (\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 | |
54bd896e | 731 | {\r |
54bd896e | 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 | |
779b8368 | 759 | SetMem (Sd, sizeof (SCRATCH_DATA), 0);\r |
760 | \r | |
54bd896e | 761 | //\r |
762 | // The length of the field 'Position Set Code Length Array Size' in Block Header.\r | |
8a7d75b0 | 763 | // For UEFI 2.0 de/compression algorithm(Version 1), mPBit = 4\r |
54bd896e | 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 | |
b4b6c8de LG |
778 | //\r |
779 | // CompSize and OrigSize are caculated in bytes\r | |
780 | //\r | |
54bd896e | 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 | |
ed7752ec | 804 | /**\r |
b4b6c8de LG |
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 | |
ed7752ec | 832 | **/\r |
54bd896e | 833 | RETURN_STATUS\r |
834 | EFIAPI\r | |
835 | UefiDecompress (\r | |
836 | IN CONST VOID *Source,\r | |
837 | IN OUT VOID *Destination,\r | |
91c68197 | 838 | IN OUT VOID *Scratch OPTIONAL\r |
54bd896e | 839 | )\r |
54bd896e | 840 | {\r |
841 | return UefiTianoDecompress (Source, Destination, Scratch, 1);\r | |
842 | }\r | |
843 | \r | |
ed7752ec | 844 | /**\r |
b4b6c8de LG |
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 | |
ed7752ec | 863 | \r |
b4b6c8de LG |
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 | |
ed7752ec | 875 | \r |
ed7752ec | 876 | **/\r |
54bd896e | 877 | RETURN_STATUS\r |
878 | EFIAPI\r | |
18fd8d65 LG |
879 | TianoDecompressGetInfo (\r |
880 | IN CONST VOID *InputSection,\r | |
881 | OUT UINT32 *OutputBufferSize,\r | |
882 | OUT UINT32 *ScratchBufferSize,\r | |
883 | OUT UINT16 *SectionAttribute\r | |
54bd896e | 884 | )\r |
54bd896e | 885 | \r |
54bd896e | 886 | {\r |
18fd8d65 LG |
887 | ASSERT (SectionAttribute != NULL);\r |
888 | \r | |
889 | if (InputSection == NULL) {\r | |
890 | return RETURN_INVALID_PARAMETER;\r | |
d8c79a81 | 891 | }\r |
e6c560aa LG |
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 | |
18fd8d65 LG |
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 | |
9c294371 | 908 | (*(UINT32 *) (((EFI_COMMON_SECTION_HEADER *) InputSection)->Size) & 0x00ffffff) - ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset,\r |
18fd8d65 LG |
909 | OutputBufferSize,\r |
910 | ScratchBufferSize\r | |
911 | );\r | |
54bd896e | 912 | }\r |
913 | \r | |
ed7752ec | 914 | /**\r |
b4b6c8de LG |
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 | |
ed7752ec | 945 | \r |
bcd70414 | 946 | **/\r |
54bd896e | 947 | RETURN_STATUS\r |
948 | EFIAPI\r | |
18fd8d65 LG |
949 | TianoDecompress (\r |
950 | IN CONST VOID *InputSection,\r | |
951 | OUT VOID **OutputBuffer,\r | |
952 | IN VOID *ScratchBuffer, OPTIONAL\r | |
953 | OUT UINT32 *AuthenticationStatus\r | |
54bd896e | 954 | )\r |
54bd896e | 955 | {\r |
18fd8d65 | 956 | ASSERT (OutputBuffer != NULL);\r |
b4b6c8de | 957 | ASSERT (InputSection != NULL);\r |
e6c560aa LG |
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 | |
18fd8d65 LG |
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 | |
54bd896e | 979 | }\r |
d8c79a81 | 980 | \r |
ed7752ec | 981 | /**\r |
b4b6c8de | 982 | Registers TianoDecompress and TianoDecompressGetInfo handlers with TianoCustomerDecompressGuid\r |
ed7752ec | 983 | \r |
18fd8d65 | 984 | @retval RETURN_SUCCESS Register successfully.\r |
ed7752ec | 985 | @retval RETURN_OUT_OF_RESOURCES No enough memory to store this handler.\r |
d8c79a81 | 986 | **/\r |
8bd22b8a | 987 | RETURN_STATUS\r |
d8c79a81 | 988 | EFIAPI\r |
18fd8d65 LG |
989 | TianoDecompressLibConstructor (\r |
990 | )\r | |
d8c79a81 | 991 | {\r |
18fd8d65 LG |
992 | return ExtractGuidedSectionRegisterHandlers (\r |
993 | &gTianoCustomDecompressGuid,\r | |
994 | TianoDecompressGetInfo,\r | |
995 | TianoDecompress\r | |
996 | ); \r | |
6bee1632 | 997 | }\r |