]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageLib.c
Sync all bug fixes between EDK1.04 and EDK1.06 into EdkCompatibilityPkg.
[mirror_edk2.git] / EdkCompatibilityPkg / Sample / Tools / Source / GenFvImage / GenFvImageLib.c
... / ...
CommitLineData
1/*++\r
2\r
3Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>\r
4This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 GenFvImageLib.c\r
15\r
16Abstract:\r
17\r
18 This file contains functions required to generate a Firmware Volume.\r
19\r
20--*/\r
21\r
22//\r
23// Include files\r
24//\r
25#include "GenFvImageLib.h"\r
26#include "GenFvImageLibInternal.h"\r
27#include <string.h>\r
28#include EFI_GUID_DEFINITION (PeiPeCoffLoader)\r
29#include "EfiFirmwareFileSystem.h"\r
30#include "EfiWorkingBlockHeader.h"\r
31#include "EfiVariable.h"\r
32#include <io.h>\r
33#include <assert.h>\r
34#include "CommonLib.h"\r
35#include "FvLib.h"\r
36#include "EfiImage.h"\r
37#include "crc32.h"\r
38#include "EfiUtilityMsgs.h"\r
39#include EFI_GUID_DEFINITION (FirmwareFileSystem)\r
40#include EFI_GUID_DEFINITION (FirmwareFileSystem2)\r
41\r
42//\r
43// Define the PE/COFF loader\r
44//\r
45extern EFI_PEI_PE_COFF_LOADER_PROTOCOL mPeCoffLoader;\r
46\r
47//\r
48// Local function prototypes\r
49//\r
50EFI_STATUS\r
51GetPe32Info (\r
52 IN UINT8 *Pe32,\r
53 OUT UINT32 *EntryPoint,\r
54 OUT UINT32 *BaseOfCode,\r
55 OUT UINT16 *MachineType\r
56 );\r
57\r
58//\r
59// Local function implementations.\r
60//\r
61#if (PI_SPECIFICATION_VERSION < 0x00010000)\r
62EFI_GUID FfsGuid = EFI_FIRMWARE_FILE_SYSTEM_GUID;\r
63#else\r
64EFI_GUID FfsGuid = EFI_FIRMWARE_FILE_SYSTEM2_GUID;\r
65#endif\r
66\r
67EFI_GUID DefaultFvPadFileNameGuid = { 0x78f54d4, 0xcc22, 0x4048, 0x9e, 0x94, 0x87, 0x9c, 0x21, 0x4d, 0x56, 0x2f };\r
68\r
69//\r
70// This data array will be located at the base of the Firmware Volume Header (FVH)\r
71// in the boot block. It must not exceed 14 bytes of code. The last 2 bytes\r
72// will be used to keep the FVH checksum consistent.\r
73// This code will be run in response to a starutp IPI for HT-enabled systems.\r
74//\r
75#define SIZEOF_STARTUP_DATA_ARRAY 0x10\r
76\r
77UINT8 m128kRecoveryStartupApDataArray[SIZEOF_STARTUP_DATA_ARRAY] = {\r
78 //\r
79 // EA D0 FF 00 F0 ; far jmp F000:FFD0\r
80 // 0, 0, 0, 0, 0, 0, 0, 0, 0, ; Reserved bytes\r
81 // 0, 0 ; Checksum Padding\r
82 //\r
83 0xEA,\r
84 0xD0,\r
85 0xFF,\r
86 0x0,\r
87 0xF0,\r
88 0x00,\r
89 0x00,\r
90 0x00,\r
91 0x00,\r
92 0x00,\r
93 0x00,\r
94 0x00,\r
95 0x00,\r
96 0x00,\r
97 0x00,\r
98 0x00\r
99};\r
100\r
101UINT8 m64kRecoveryStartupApDataArray[SIZEOF_STARTUP_DATA_ARRAY] = {\r
102 //\r
103 // EB CE ; jmp short ($-0x30)\r
104 // ; (from offset 0x0 to offset 0xFFD0)\r
105 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ; Reserved bytes\r
106 // 0, 0 ; Checksum Padding\r
107 //\r
108 0xEB,\r
109 0xCE,\r
110 0x00,\r
111 0x00,\r
112 0x00,\r
113 0x00,\r
114 0x00,\r
115 0x00,\r
116 0x00,\r
117 0x00,\r
118 0x00,\r
119 0x00,\r
120 0x00,\r
121 0x00,\r
122 0x00,\r
123 0x00\r
124};\r
125\r
126EFI_STATUS\r
127ParseFvInf (\r
128 IN MEMORY_FILE *InfFile,\r
129 IN FV_INFO *FvInfo\r
130 )\r
131/*++\r
132\r
133Routine Description:\r
134\r
135 This function parses a FV.INF file and copies info into a FV_INFO structure.\r
136\r
137Arguments:\r
138\r
139 InfFile Memory file image.\r
140 FvInfo Information read from INF file.\r
141\r
142Returns:\r
143\r
144 EFI_SUCCESS INF file information successfully retrieved.\r
145 EFI_ABORTED INF file has an invalid format.\r
146 EFI_NOT_FOUND A required string was not found in the INF file.\r
147--*/\r
148{\r
149 CHAR8 Value[_MAX_PATH];\r
150 UINT64 Value64;\r
151 UINTN Index;\r
152 EFI_STATUS Status;\r
153\r
154 //\r
155 // Initialize FV info\r
156 //\r
157 memset (FvInfo, 0, sizeof (FV_INFO));\r
158\r
159 //\r
160 // Read the FV base address\r
161 //\r
162 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_BASE_ADDRESS_STRING, 0, Value);\r
163\r
164 if (Status == EFI_SUCCESS) {\r
165 //\r
166 // Get the base address\r
167 //\r
168 Status = AsciiStringToUint64 (Value, FALSE, &Value64);\r
169 if (EFI_ERROR (Status)) {\r
170 Error (NULL, 0, 0, EFI_FV_BASE_ADDRESS_STRING, "invalid value");\r
171 return EFI_ABORTED;\r
172 }\r
173\r
174 FvInfo->BaseAddress = Value64;\r
175 } else {\r
176 Error (NULL, 0, 0, EFI_FV_BASE_ADDRESS_STRING, "could not find value");\r
177 return EFI_ABORTED;\r
178 }\r
179 //\r
180 // Read the FV Guid\r
181 //\r
182 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_GUID_STRING, 0, Value);\r
183\r
184 if (Status == EFI_SUCCESS) {\r
185 //\r
186 // Get the guid value\r
187 //\r
188 Status = StringToGuid (Value, &FvInfo->FvGuid);\r
189 if (EFI_ERROR (Status)) {\r
190 memcpy (&FvInfo->FvGuid, &FfsGuid, sizeof (EFI_GUID));\r
191 }\r
192 } else {\r
193 memcpy (&FvInfo->FvGuid, &FfsGuid, sizeof (EFI_GUID));\r
194 }\r
195 //\r
196 // Read the FV file name\r
197 //\r
198 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_FILE_NAME_STRING, 0, Value);\r
199\r
200 if (Status == EFI_SUCCESS) {\r
201 //\r
202 // copy the file name\r
203 //\r
204 strcpy (FvInfo->FvName, Value);\r
205 } else {\r
206 Error (NULL, 0, 0, EFI_FV_FILE_NAME_STRING, "value not specified");\r
207 return EFI_ABORTED;\r
208 }\r
209 //\r
210 // Read the Sym file name\r
211 //\r
212 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_SYM_FILE_NAME_STRING, 0, Value);\r
213\r
214 if (Status == EFI_SUCCESS) {\r
215 //\r
216 // copy the file name\r
217 //\r
218 strcpy (FvInfo->SymName, Value);\r
219 } else {\r
220 //\r
221 // Symbols not required, so init to NULL.\r
222 //\r
223 strcpy (FvInfo->SymName, "");\r
224 }\r
225 //\r
226 // Read the read disabled capability attribute\r
227 //\r
228 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_DISABLED_CAP_STRING, 0, Value);\r
229\r
230 if (Status == EFI_SUCCESS) {\r
231 //\r
232 // Update the read disabled flag\r
233 //\r
234 if (strcmp (Value, TRUE_STRING) == 0) {\r
235 FvInfo->FvAttributes |= EFI_FVB_READ_DISABLED_CAP;\r
236 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
237 Error (NULL, 0, 0, EFI_FVB_READ_DISABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
238 return EFI_ABORTED;\r
239 }\r
240 } else {\r
241 Error (NULL, 0, 0, EFI_FVB_READ_DISABLED_CAP_STRING, "value not specified");\r
242 return Status;\r
243 }\r
244 //\r
245 // Read the read enabled capability attribute\r
246 //\r
247 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_ENABLED_CAP_STRING, 0, Value);\r
248\r
249 if (Status == EFI_SUCCESS) {\r
250 //\r
251 // Update the read disabled flag\r
252 //\r
253 if (strcmp (Value, TRUE_STRING) == 0) {\r
254 FvInfo->FvAttributes |= EFI_FVB_READ_ENABLED_CAP;\r
255 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
256 Error (NULL, 0, 0, EFI_FVB_READ_ENABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
257 return EFI_ABORTED;\r
258 }\r
259 } else {\r
260 Error (NULL, 0, 0, EFI_FVB_READ_ENABLED_CAP_STRING, "value not specified");\r
261 return Status;\r
262 }\r
263 //\r
264 // Read the read status attribute\r
265 //\r
266 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_STATUS_STRING, 0, Value);\r
267\r
268 if (Status == EFI_SUCCESS) {\r
269 //\r
270 // Update the read disabled flag\r
271 //\r
272 if (strcmp (Value, TRUE_STRING) == 0) {\r
273 FvInfo->FvAttributes |= EFI_FVB_READ_STATUS;\r
274 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
275 Error (NULL, 0, 0, EFI_FVB_READ_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
276 return EFI_ABORTED;\r
277 }\r
278 } else {\r
279 Error (NULL, 0, 0, EFI_FVB_READ_STATUS_STRING, "value not specified");\r
280 return Status;\r
281 }\r
282 //\r
283 // Read the write disabled capability attribute\r
284 //\r
285 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_DISABLED_CAP_STRING, 0, Value);\r
286\r
287 if (Status == EFI_SUCCESS) {\r
288 //\r
289 // Update the write disabled flag\r
290 //\r
291 if (strcmp (Value, TRUE_STRING) == 0) {\r
292 FvInfo->FvAttributes |= EFI_FVB_WRITE_DISABLED_CAP;\r
293 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
294 Error (NULL, 0, 0, EFI_FVB_WRITE_DISABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
295 return EFI_ABORTED;\r
296 }\r
297 } else {\r
298 Error (NULL, 0, 0, EFI_FVB_WRITE_DISABLED_CAP_STRING, "value not specified");\r
299 return Status;\r
300 }\r
301 //\r
302 // Read the write enabled capability attribute\r
303 //\r
304 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_ENABLED_CAP_STRING, 0, Value);\r
305\r
306 if (Status == EFI_SUCCESS) {\r
307 //\r
308 // Update the write disabled flag\r
309 //\r
310 if (strcmp (Value, TRUE_STRING) == 0) {\r
311 FvInfo->FvAttributes |= EFI_FVB_WRITE_ENABLED_CAP;\r
312 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
313 Error (NULL, 0, 0, EFI_FVB_WRITE_ENABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
314 return EFI_ABORTED;\r
315 }\r
316 } else {\r
317 Error (NULL, 0, 0, EFI_FVB_WRITE_ENABLED_CAP_STRING, "value not specified");\r
318 return Status;\r
319 }\r
320 //\r
321 // Read the write status attribute\r
322 //\r
323 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_STATUS_STRING, 0, Value);\r
324\r
325 if (Status == EFI_SUCCESS) {\r
326 //\r
327 // Update the write disabled flag\r
328 //\r
329 if (strcmp (Value, TRUE_STRING) == 0) {\r
330 FvInfo->FvAttributes |= EFI_FVB_WRITE_STATUS;\r
331 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
332 Error (NULL, 0, 0, EFI_FVB_WRITE_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
333 return EFI_ABORTED;\r
334 }\r
335 } else {\r
336 Error (NULL, 0, 0, EFI_FVB_WRITE_STATUS_STRING, "value not specified");\r
337 return Status;\r
338 }\r
339 //\r
340 // Read the lock capability attribute\r
341 //\r
342 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_LOCK_CAP_STRING, 0, Value);\r
343\r
344 if (Status == EFI_SUCCESS) {\r
345 //\r
346 // Update the attribute flag\r
347 //\r
348 if (strcmp (Value, TRUE_STRING) == 0) {\r
349 FvInfo->FvAttributes |= EFI_FVB_LOCK_CAP;\r
350 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
351 Error (NULL, 0, 0, EFI_FVB_LOCK_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
352 return EFI_ABORTED;\r
353 }\r
354 } else {\r
355 Error (NULL, 0, 0, EFI_FVB_LOCK_CAP_STRING, "value not specified");\r
356 return Status;\r
357 }\r
358 //\r
359 // Read the lock status attribute\r
360 //\r
361 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_LOCK_STATUS_STRING, 0, Value);\r
362\r
363 if (Status == EFI_SUCCESS) {\r
364 //\r
365 // Update the attribute flag\r
366 //\r
367 if (strcmp (Value, TRUE_STRING) == 0) {\r
368 FvInfo->FvAttributes |= EFI_FVB_LOCK_STATUS;\r
369 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
370 Error (NULL, 0, 0, EFI_FVB_LOCK_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
371 return EFI_ABORTED;\r
372 }\r
373 } else {\r
374 Error (NULL, 0, 0, EFI_FVB_LOCK_STATUS_STRING, "value not specified");\r
375 return Status;\r
376 }\r
377 //\r
378 // Read the sticky write attribute\r
379 //\r
380 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_STICKY_WRITE_STRING, 0, Value);\r
381\r
382 if (Status == EFI_SUCCESS) {\r
383 //\r
384 // Update the attribute flag\r
385 //\r
386 if (strcmp (Value, TRUE_STRING) == 0) {\r
387 FvInfo->FvAttributes |= EFI_FVB_STICKY_WRITE;\r
388 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
389 Error (NULL, 0, 0, EFI_FVB_STICKY_WRITE_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
390 return EFI_ABORTED;\r
391 }\r
392 } else {\r
393 Error (NULL, 0, 0, EFI_FVB_STICKY_WRITE_STRING, "value not specified");\r
394 return Status;\r
395 }\r
396 //\r
397 // Read the memory mapped attribute\r
398 //\r
399 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_MEMORY_MAPPED_STRING, 0, Value);\r
400\r
401 if (Status == EFI_SUCCESS) {\r
402 //\r
403 // Update the attribute flag\r
404 //\r
405 if (strcmp (Value, TRUE_STRING) == 0) {\r
406 FvInfo->FvAttributes |= EFI_FVB_MEMORY_MAPPED;\r
407 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
408 Error (NULL, 0, 0, EFI_FVB_MEMORY_MAPPED_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
409 return EFI_ABORTED;\r
410 }\r
411 } else {\r
412 Error (NULL, 0, 0, EFI_FVB_MEMORY_MAPPED_STRING, "value not specified");\r
413 return Status;\r
414 }\r
415 //\r
416 // Read the erase polarity attribute\r
417 //\r
418 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ERASE_POLARITY_STRING, 0, Value);\r
419\r
420 if (Status == EFI_SUCCESS) {\r
421 //\r
422 // Update the attribute flag\r
423 //\r
424 if (strcmp (Value, ONE_STRING) == 0) {\r
425 FvInfo->FvAttributes |= EFI_FVB_ERASE_POLARITY;\r
426 } else if (strcmp (Value, ZERO_STRING) != 0) {\r
427 Error (NULL, 0, 0, EFI_FVB_ERASE_POLARITY_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
428 return EFI_ABORTED;\r
429 }\r
430 } else {\r
431 Error (NULL, 0, 0, EFI_FVB_ERASE_POLARITY_STRING, "value not specified");\r
432 return Status;\r
433 }\r
434\r
435#if (PI_SPECIFICATION_VERSION >= 0x00010000) \r
436 //\r
437 // Read the read lock capability attribute\r
438 //\r
439 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_LOCK_CAP_STRING, 0, Value);\r
440\r
441 if (Status == EFI_SUCCESS) {\r
442 //\r
443 // Update attribute\r
444 //\r
445 if (strcmp (Value, TRUE_STRING) == 0) {\r
446 FvInfo->FvAttributes |= EFI_FVB2_READ_LOCK_CAP;\r
447 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
448 Error (NULL, 0, 0, EFI_FVB_READ_LOCK_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
449 return EFI_ABORTED;\r
450 }\r
451 } else {\r
452 Error (NULL, 0, 0, EFI_FVB_READ_LOCK_CAP_STRING, "value not specified");\r
453 return Status;\r
454 }\r
455\r
456 //\r
457 // Read the read lock status attribute\r
458 //\r
459 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_LOCK_STATUS_STRING, 0, Value);\r
460\r
461 if (Status == EFI_SUCCESS) {\r
462 //\r
463 // Update attribute\r
464 //\r
465 if (strcmp (Value, TRUE_STRING) == 0) {\r
466 FvInfo->FvAttributes |= EFI_FVB2_READ_LOCK_STATUS;\r
467 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
468 Error (NULL, 0, 0, EFI_FVB_READ_LOCK_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
469 return EFI_ABORTED;\r
470 }\r
471 } else {\r
472 Error (NULL, 0, 0, EFI_FVB_READ_LOCK_STATUS_STRING, "value not specified");\r
473 return Status;\r
474 }\r
475\r
476 //\r
477 // Read the write lock capability attribute\r
478 //\r
479 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_LOCK_CAP_STRING, 0, Value);\r
480\r
481 if (Status == EFI_SUCCESS) {\r
482 //\r
483 // Update attribute\r
484 //\r
485 if (strcmp (Value, TRUE_STRING) == 0) {\r
486 FvInfo->FvAttributes |= EFI_FVB2_WRITE_LOCK_CAP;\r
487 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
488 Error (NULL, 0, 0, EFI_FVB_WRITE_LOCK_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
489 return EFI_ABORTED;\r
490 }\r
491 } else {\r
492 Error (NULL, 0, 0, EFI_FVB_WRITE_LOCK_CAP_STRING, "value not specified");\r
493 return Status;\r
494 }\r
495\r
496 //\r
497 // Read the write lock status attribute\r
498 //\r
499 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_LOCK_STATUS_STRING, 0, Value);\r
500\r
501 if (Status == EFI_SUCCESS) {\r
502 //\r
503 // Update attribute\r
504 //\r
505 if (strcmp (Value, TRUE_STRING) == 0) {\r
506 FvInfo->FvAttributes |= EFI_FVB2_WRITE_LOCK_STATUS;\r
507 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
508 Error (NULL, 0, 0, EFI_FVB_WRITE_LOCK_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
509 return EFI_ABORTED;\r
510 }\r
511 } else {\r
512 Error (NULL, 0, 0, EFI_FVB_WRITE_LOCK_STATUS_STRING, "value not specified");\r
513 return Status;\r
514 }\r
515#endif\r
516\r
517#if (PI_SPECIFICATION_VERSION < 0x00010000) \r
518 //\r
519 // Read the alignment capabilities attribute\r
520 //\r
521 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_CAP_STRING, 0, Value);\r
522\r
523 if (Status == EFI_SUCCESS) {\r
524 //\r
525 // Update attribute\r
526 //\r
527 if (strcmp (Value, TRUE_STRING) == 0) {\r
528 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_CAP;\r
529 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
530 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
531 return EFI_ABORTED;\r
532 }\r
533 } else {\r
534 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_CAP_STRING, "value not specified");\r
535 return Status;\r
536 }\r
537\r
538 //\r
539 // Read the word alignment capability attribute\r
540 //\r
541 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_2_STRING, 0, Value);\r
542\r
543 if (Status == EFI_SUCCESS) {\r
544 //\r
545 // Update attribute\r
546 //\r
547 if (strcmp (Value, TRUE_STRING) == 0) {\r
548 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_2;\r
549 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
550 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
551 return EFI_ABORTED;\r
552 }\r
553 } else {\r
554 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2_STRING, "value not specified");\r
555 return Status;\r
556 }\r
557\r
558 \r
559 //\r
560 // Read the dword alignment capability attribute\r
561 //\r
562 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_4_STRING, 0, Value);\r
563\r
564 if (Status == EFI_SUCCESS) {\r
565 //\r
566 // Update attribute\r
567 //\r
568 if (strcmp (Value, TRUE_STRING) == 0) {\r
569 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_4;\r
570 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
571 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
572 return EFI_ABORTED;\r
573 }\r
574 } else {\r
575 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4_STRING, "value not specified");\r
576 return Status;\r
577 }\r
578 //\r
579 // Read the word alignment capability attribute\r
580 //\r
581 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_8_STRING, 0, Value);\r
582\r
583 if (Status == EFI_SUCCESS) {\r
584 //\r
585 // Update attribute\r
586 //\r
587 if (strcmp (Value, TRUE_STRING) == 0) {\r
588 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_8;\r
589 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
590 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
591 return EFI_ABORTED;\r
592 }\r
593 } else {\r
594 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8_STRING, "value not specified");\r
595 return Status;\r
596 }\r
597 //\r
598 // Read the qword alignment capability attribute\r
599 //\r
600 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_16_STRING, 0, Value);\r
601\r
602 if (Status == EFI_SUCCESS) {\r
603 //\r
604 // Update attribute\r
605 //\r
606 if (strcmp (Value, TRUE_STRING) == 0) {\r
607 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_16;\r
608 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
609 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
610 return EFI_ABORTED;\r
611 }\r
612 } else {\r
613 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16_STRING, "value not specified");\r
614 return Status;\r
615 }\r
616 //\r
617 // Read the 32 byte alignment capability attribute\r
618 //\r
619 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_32_STRING, 0, Value);\r
620\r
621 if (Status == EFI_SUCCESS) {\r
622 //\r
623 // Update attribute\r
624 //\r
625 if (strcmp (Value, TRUE_STRING) == 0) {\r
626 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_32;\r
627 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
628 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
629 return EFI_ABORTED;\r
630 }\r
631 } else {\r
632 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32_STRING, "value not specified");\r
633 return Status;\r
634 }\r
635 //\r
636 // Read the 64 byte alignment capability attribute\r
637 //\r
638 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_64_STRING, 0, Value);\r
639\r
640 if (Status == EFI_SUCCESS) {\r
641 //\r
642 // Update attribute\r
643 //\r
644 if (strcmp (Value, TRUE_STRING) == 0) {\r
645 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_64;\r
646 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
647 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
648 return EFI_ABORTED;\r
649 }\r
650 } else {\r
651 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64_STRING, "value not specified");\r
652 return Status;\r
653 }\r
654 //\r
655 // Read the 128 byte alignment capability attribute\r
656 //\r
657 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_128_STRING, 0, Value);\r
658\r
659 if (Status == EFI_SUCCESS) {\r
660 //\r
661 // Update attribute\r
662 //\r
663 if (strcmp (Value, TRUE_STRING) == 0) {\r
664 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_128;\r
665 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
666 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_128_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
667 return EFI_ABORTED;\r
668 }\r
669 } else {\r
670 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_128_STRING, "value not specified");\r
671 return Status;\r
672 }\r
673 //\r
674 // Read the 256 byte alignment capability attribute\r
675 //\r
676 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_256_STRING, 0, Value);\r
677\r
678 if (Status == EFI_SUCCESS) {\r
679 //\r
680 // Update attribute\r
681 //\r
682 if (strcmp (Value, TRUE_STRING) == 0) {\r
683 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_256;\r
684 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
685 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_256_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
686 return EFI_ABORTED;\r
687 }\r
688 } else {\r
689 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_256_STRING, "value not specified");\r
690 return Status;\r
691 }\r
692 //\r
693 // Read the 512 byte alignment capability attribute\r
694 //\r
695 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_512_STRING, 0, Value);\r
696\r
697 if (Status == EFI_SUCCESS) {\r
698 //\r
699 // Update attribute\r
700 //\r
701 if (strcmp (Value, TRUE_STRING) == 0) {\r
702 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_512;\r
703 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
704 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_512_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
705 return EFI_ABORTED;\r
706 }\r
707 } else {\r
708 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_512_STRING, "value not specified");\r
709 return Status;\r
710 }\r
711 //\r
712 // Read the 1K byte alignment capability attribute\r
713 //\r
714 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_1K_STRING, 0, Value);\r
715\r
716 if (Status == EFI_SUCCESS) {\r
717 //\r
718 // Update attribute\r
719 //\r
720 if (strcmp (Value, TRUE_STRING) == 0) {\r
721 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_1K;\r
722 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
723 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_1K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
724 return EFI_ABORTED;\r
725 }\r
726 } else {\r
727 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_1K_STRING, "value not specified");\r
728 return Status;\r
729 }\r
730 //\r
731 // Read the 2K byte alignment capability attribute\r
732 //\r
733 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_2K_STRING, 0, Value);\r
734\r
735 if (Status == EFI_SUCCESS) {\r
736 //\r
737 // Update attribute\r
738 //\r
739 if (strcmp (Value, TRUE_STRING) == 0) {\r
740 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_2K;\r
741 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
742 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
743 return EFI_ABORTED;\r
744 }\r
745 } else {\r
746 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2K_STRING, "value not specified");\r
747 return Status;\r
748 }\r
749 //\r
750 // Read the 4K byte alignment capability attribute\r
751 //\r
752 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_4K_STRING, 0, Value);\r
753\r
754 if (Status == EFI_SUCCESS) {\r
755 //\r
756 // Update attribute\r
757 //\r
758 if (strcmp (Value, TRUE_STRING) == 0) {\r
759 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_4K;\r
760 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
761 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
762 return EFI_ABORTED;\r
763 }\r
764 } else {\r
765 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4K_STRING, "value not specified");\r
766 return Status;\r
767 }\r
768 //\r
769 // Read the 8K byte alignment capability attribute\r
770 //\r
771 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_8K_STRING, 0, Value);\r
772\r
773 if (Status == EFI_SUCCESS) {\r
774 //\r
775 // Update attribute\r
776 //\r
777 if (strcmp (Value, TRUE_STRING) == 0) {\r
778 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_8K;\r
779 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
780 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
781 return EFI_ABORTED;\r
782 }\r
783 } else {\r
784 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8K_STRING, "value not specified");\r
785 return Status;\r
786 }\r
787 //\r
788 // Read the 16K byte alignment capability attribute\r
789 //\r
790 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_16K_STRING, 0, Value);\r
791\r
792 if (Status == EFI_SUCCESS) {\r
793 //\r
794 // Update attribute\r
795 //\r
796 if (strcmp (Value, TRUE_STRING) == 0) {\r
797 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_16K;\r
798 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
799 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
800 return EFI_ABORTED;\r
801 }\r
802 } else {\r
803 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16K_STRING, "value not specified");\r
804 return Status;\r
805 }\r
806 //\r
807 // Read the 32K byte alignment capability attribute\r
808 //\r
809 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_32K_STRING, 0, Value);\r
810\r
811 if (Status == EFI_SUCCESS) {\r
812 //\r
813 // Update attribute\r
814 //\r
815 if (strcmp (Value, TRUE_STRING) == 0) {\r
816 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_32K;\r
817 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
818 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
819 return EFI_ABORTED;\r
820 }\r
821 } else {\r
822 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32K_STRING, "value not specified");\r
823 return Status;\r
824 }\r
825 //\r
826 // Read the 64K byte alignment capability attribute\r
827 //\r
828 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_64K_STRING, 0, Value);\r
829\r
830 if (Status == EFI_SUCCESS) {\r
831 //\r
832 // Update attribute\r
833 //\r
834 if (strcmp (Value, TRUE_STRING) == 0) {\r
835 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_64K;\r
836 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
837 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
838 return EFI_ABORTED;\r
839 }\r
840 } else {\r
841 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64K_STRING, "value not specified");\r
842 return Status;\r
843 }\r
844\r
845 if (!(FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_CAP) &&\r
846 (\r
847 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_2) ||\r
848 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_4) ||\r
849 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_8) ||\r
850 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_16) ||\r
851 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_32) ||\r
852 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_64) ||\r
853 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_128) ||\r
854 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_256) ||\r
855 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_512) ||\r
856 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_1K) ||\r
857 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_2K) ||\r
858 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_4K) ||\r
859 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_8K) ||\r
860 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_16K) ||\r
861 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_32K) ||\r
862 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_64K)\r
863 )\r
864 ){\r
865 Error (\r
866 NULL,\r
867 0,\r
868 0,\r
869 "illegal combination of alignment attributes",\r
870 "if %s is not %s, no individual alignments can be %s",\r
871 EFI_FVB_ALIGNMENT_CAP_STRING,\r
872 TRUE_STRING,\r
873 TRUE_STRING\r
874 );\r
875 return EFI_ABORTED;\r
876 }\r
877#else\r
878 //\r
879 // Read the PI1.0 FVB2 Alignment Capabilities Attribute\r
880 //\r
881 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB2_ALIGNMENT_STRING, 0, Value);\r
882\r
883 if (Status == EFI_SUCCESS) {\r
884 //\r
885 // Update attribute\r
886 //\r
887 if (strcmp (Value, EFI_FVB2_ALIGNMENT_1_STRING) == 0) {\r
888 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_1;\r
889 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_2_STRING) == 0) {\r
890 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_2;\r
891 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_4_STRING) == 0) {\r
892 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_4;\r
893 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_8_STRING) == 0) {\r
894 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_8;\r
895 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_16_STRING) == 0) {\r
896 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_16;\r
897 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_32_STRING) == 0) {\r
898 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_32;\r
899 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_64_STRING) == 0) {\r
900 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_64;\r
901 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_128_STRING) == 0) {\r
902 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_128;\r
903 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_256_STRING) == 0) {\r
904 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_256;\r
905 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_512_STRING) == 0) {\r
906 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_512;\r
907 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_1K_STRING) == 0) {\r
908 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_1K;\r
909 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_2K_STRING) == 0) {\r
910 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_2K;\r
911 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_4K_STRING) == 0) {\r
912 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_4K;\r
913 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_8K_STRING) == 0) {\r
914 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_8K;\r
915 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_16K_STRING) == 0) {\r
916 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_16K;\r
917 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_32K_STRING) == 0) {\r
918 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_32K;\r
919 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_64K_STRING) == 0) {\r
920 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_64K;\r
921 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_128K_STRING) == 0) {\r
922 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_128K;\r
923 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_256K_STRING) == 0) {\r
924 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_256K;\r
925 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_512K_STRING) == 0) {\r
926 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMNET_512K;\r
927 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_1M_STRING) == 0) {\r
928 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_1M;\r
929 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_2M_STRING) == 0) {\r
930 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_2M;\r
931 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_4M_STRING) == 0) {\r
932 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_4M;\r
933 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_8M_STRING) == 0) {\r
934 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_8M;\r
935 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_16M_STRING) == 0) {\r
936 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_16M;\r
937 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_32M_STRING) == 0) {\r
938 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_32M;\r
939 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_64M_STRING) == 0) {\r
940 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_64M;\r
941 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_128M_STRING) == 0) {\r
942 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_128M;\r
943 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_256M_STRING) == 0) {\r
944 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_256M;\r
945 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_512M_STRING) == 0) {\r
946 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_512M;\r
947 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_1G_STRING) == 0) {\r
948 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_1G;\r
949 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_2G_STRING) == 0) {\r
950 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_2G;\r
951 } else {\r
952 Error (NULL, 0, 0, EFI_FVB2_ALIGNMENT_STRING, "value not correct!");\r
953 return EFI_ABORTED;\r
954 }\r
955 } else {\r
956 Error (NULL, 0, 0, EFI_FVB2_ALIGNMENT_STRING, "value not specified");\r
957 return Status;\r
958 }\r
959\r
960#endif \r
961 //\r
962 // Read block maps\r
963 //\r
964 for (Index = 0; Index < MAX_NUMBER_OF_FV_BLOCKS; Index++) {\r
965 //\r
966 // Read the number of blocks\r
967 //\r
968 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_NUM_BLOCKS_STRING, Index, Value);\r
969\r
970 if (Status == EFI_SUCCESS) {\r
971 if (strcmp (Value, AUTO_STRING) == 0) {\r
972 Value64 = (UINT64) -1;\r
973 } else {\r
974 //\r
975 // Update the number of blocks\r
976 //\r
977 Status = AsciiStringToUint64 (Value, FALSE, &Value64);\r
978 if (EFI_ERROR (Status)) {\r
979 Error (NULL, 0, 0, Value, "invalid value for %s", EFI_NUM_BLOCKS_STRING);\r
980 return EFI_ABORTED;\r
981 }\r
982 }\r
983\r
984 FvInfo->FvBlocks[Index].NumBlocks = (UINT32) Value64;\r
985 } else {\r
986 //\r
987 // If there is no number of blocks, but there is a size, then we have a mismatched pair\r
988 // and should return an error.\r
989 //\r
990 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_BLOCK_SIZE_STRING, Index, Value);\r
991 if (!EFI_ERROR (Status)) {\r
992 Error (NULL, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING);\r
993 return EFI_ABORTED;\r
994 } else {\r
995 //\r
996 // We are done\r
997 //\r
998 break;\r
999 }\r
1000 }\r
1001 //\r
1002 // Read the size of blocks\r
1003 //\r
1004 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_BLOCK_SIZE_STRING, Index, Value);\r
1005\r
1006 if (Status == EFI_SUCCESS) {\r
1007 //\r
1008 // Update the number of blocks\r
1009 //\r
1010 Status = AsciiStringToUint64 (Value, FALSE, &Value64);\r
1011 if (EFI_ERROR (Status)) {\r
1012 Error (NULL, 0, 0, Value, "invalid value specified for %s", EFI_BLOCK_SIZE_STRING);\r
1013 return EFI_ABORTED;\r
1014 }\r
1015\r
1016 FvInfo->FvBlocks[Index].BlockLength = (UINT32) Value64;\r
1017 } else {\r
1018 //\r
1019 // There is a number of blocks, but there is no size, so we have a mismatched pair\r
1020 // and should return an error.\r
1021 //\r
1022 Error (NULL, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING);\r
1023 return EFI_ABORTED;\r
1024 }\r
1025 }\r
1026 //\r
1027 // Read files\r
1028 //\r
1029 for (Index = 0; Index < MAX_NUMBER_OF_FILES_IN_FV; Index++) {\r
1030 //\r
1031 // Read the number of blocks\r
1032 //\r
1033 Status = FindToken (InfFile, FILES_SECTION_STRING, EFI_FILE_NAME_STRING, Index, Value);\r
1034\r
1035 if (Status == EFI_SUCCESS) {\r
1036 //\r
1037 // Add the file\r
1038 //\r
1039 strcpy (FvInfo->FvFiles[Index], Value);\r
1040 } else {\r
1041 break;\r
1042 }\r
1043 }\r
1044\r
1045 if (FindSection (InfFile, COMPONENT_SECTION_STRING)) {\r
1046 Index = 0;\r
1047 while (TRUE) {\r
1048 Status = FindTokenInstanceInSection (\r
1049 InfFile,\r
1050 COMPONENT_SECTION_STRING,\r
1051 Index,\r
1052 FvInfo->FvComponents[Index].ComponentName,\r
1053 Value\r
1054 );\r
1055 if (EFI_ERROR (Status)) {\r
1056 break;\r
1057 }\r
1058 Status = AsciiStringToUint64 (Value, FALSE, &Value64);\r
1059 if (EFI_ERROR (Status)) {\r
1060 Error (NULL, 0, 0, Value, "not a valid integer");\r
1061 return EFI_ABORTED;\r
1062 }\r
1063\r
1064 FvInfo->FvComponents[Index].Size = (UINTN) Value64;\r
1065 Index++;\r
1066 }\r
1067 }\r
1068 //\r
1069 // Compute size for easy access later\r
1070 //\r
1071 FvInfo->Size = 0;\r
1072 for (Index = 0; FvInfo->FvBlocks[Index].NumBlocks; Index++) {\r
1073 if ((FvInfo->Size == (UINTN) -1 && Index > 0) ||\r
1074 (FvInfo->FvBlocks[Index].NumBlocks == (UINT32) -1 && Index > 0)\r
1075 ) {\r
1076 //\r
1077 // Error 1. more pairs after AUTO\r
1078 // Error 2. AUTO appear in non-first position\r
1079 //\r
1080 Error (NULL, 0, 0, NULL, "cannot have more than one pair of %s and %s if %s is set to %s", \r
1081 EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING,\r
1082 EFI_NUM_BLOCKS_STRING, AUTO_STRING\r
1083 );\r
1084 return EFI_ABORTED;\r
1085 }\r
1086\r
1087 if (FvInfo->FvBlocks[Index].NumBlocks == (UINT32) -1) {\r
1088 FvInfo->Size = (UINTN) -1;\r
1089 } else {\r
1090 FvInfo->Size += FvInfo->FvBlocks[Index].NumBlocks * FvInfo->FvBlocks[Index].BlockLength;\r
1091 }\r
1092 }\r
1093\r
1094 if (FvInfo->Size == (UINTN) -1 && FvInfo->FvFiles[0][0] == 0) {\r
1095 //\r
1096 // Non FFS FV cannot set block number to AUTO\r
1097 //\r
1098 Error (NULL, 0, 0, "non-FFS FV", "cannot set %s to %s", EFI_NUM_BLOCKS_STRING, AUTO_STRING);\r
1099 return EFI_ABORTED;\r
1100 }\r
1101\r
1102 return EFI_SUCCESS;\r
1103}\r
1104\r
1105VOID\r
1106UpdateFfsFileState (\r
1107 IN EFI_FFS_FILE_HEADER *FfsFile,\r
1108 IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader\r
1109 )\r
1110/*++\r
1111\r
1112Routine Description:\r
1113\r
1114 This function changes the FFS file attributes based on the erase polarity\r
1115 of the FV.\r
1116\r
1117Arguments:\r
1118\r
1119 FfsFile File header.\r
1120 FvHeader FV header.\r
1121\r
1122Returns:\r
1123\r
1124 None\r
1125\r
1126--*/\r
1127{\r
1128 if (FvHeader->Attributes & EFI_FVB_ERASE_POLARITY) {\r
1129 FfsFile->State = (UINT8)~(FfsFile->State);\r
1130 }\r
1131}\r
1132\r
1133EFI_STATUS\r
1134ReadFfsAlignment (\r
1135 IN EFI_FFS_FILE_HEADER *FfsFile,\r
1136 IN OUT UINT32 *Alignment\r
1137 )\r
1138/*++\r
1139\r
1140Routine Description:\r
1141\r
1142 This function determines the alignment of the FFS input file from the file\r
1143 attributes.\r
1144\r
1145Arguments:\r
1146\r
1147 FfsFile FFS file to parse\r
1148 Alignment The minimum required alignment of the FFS file, in bytes\r
1149\r
1150Returns:\r
1151\r
1152 EFI_SUCCESS The function completed successfully.\r
1153 EFI_INVALID_PARAMETER One of the input parameters was invalid.\r
1154 EFI_ABORTED An error occurred.\r
1155\r
1156--*/\r
1157{\r
1158 //\r
1159 // Verify input parameters.\r
1160 //\r
1161 if (FfsFile == NULL || Alignment == NULL) {\r
1162 return EFI_INVALID_PARAMETER;\r
1163 }\r
1164\r
1165 switch ((FfsFile->Attributes >> 3) & 0x07) {\r
1166\r
1167 case 0:\r
1168 //\r
1169 // 1 byte alignment\r
1170 //\r
1171 *Alignment = (1 << 0);\r
1172 break;\r
1173\r
1174 case 1:\r
1175 //\r
1176 // 16 byte alignment\r
1177 //\r
1178 *Alignment = (1 << 4);\r
1179 break;\r
1180\r
1181 case 2:\r
1182 //\r
1183 // 128 byte alignment\r
1184 //\r
1185 *Alignment = (1 << 7);\r
1186 break;\r
1187\r
1188 case 3:\r
1189 //\r
1190 // 512 byte alignment\r
1191 //\r
1192 *Alignment = (1 << 9);\r
1193 break;\r
1194\r
1195 case 4:\r
1196 //\r
1197 // 1K byte alignment\r
1198 //\r
1199 *Alignment = (1 << 10);\r
1200 break;\r
1201\r
1202 case 5:\r
1203 //\r
1204 // 4K byte alignment\r
1205 //\r
1206 *Alignment = (1 << 12);\r
1207 break;\r
1208\r
1209 case 6:\r
1210 //\r
1211 // 32K byte alignment\r
1212 //\r
1213 *Alignment = (1 << 15);\r
1214 break;\r
1215\r
1216 case 7:\r
1217 //\r
1218 // 64K byte alignment\r
1219 //\r
1220 *Alignment = (1 << 16);\r
1221 break;\r
1222\r
1223 default:\r
1224 Error (NULL, 0, 0, "nvalid file attribute calculated, this is most likely a utility error", NULL);\r
1225 return EFI_ABORTED;\r
1226 }\r
1227\r
1228 return EFI_SUCCESS;\r
1229}\r
1230\r
1231EFI_STATUS\r
1232AddPadFile (\r
1233 IN OUT MEMORY_FILE *FvImage,\r
1234 IN UINT32 DataAlignment\r
1235 )\r
1236/*++\r
1237\r
1238Routine Description:\r
1239\r
1240 This function adds a pad file to the FV image if it required to align the\r
1241 data of the next file.\r
1242\r
1243Arguments:\r
1244\r
1245 FvImage The memory image of the FV to add it to. The current offset\r
1246 must be valid.\r
1247 DataAlignment The data alignment of the next FFS file.\r
1248\r
1249Returns:\r
1250\r
1251 EFI_SUCCESS The function completed successfully.\r
1252 EFI_INVALID_PARAMETER One of the input parameters was invalid.\r
1253 EFI_OUT_OF_RESOURCES Insufficient resources exist in the FV to complete\r
1254 the pad file add.\r
1255\r
1256--*/\r
1257{\r
1258 EFI_FFS_FILE_HEADER *PadFile;\r
1259 UUID PadFileGuid;\r
1260 UINTN PadFileSize;\r
1261\r
1262 //\r
1263 // Verify input parameters.\r
1264 //\r
1265 if (FvImage == NULL) {\r
1266 return EFI_INVALID_PARAMETER;\r
1267 }\r
1268 //\r
1269 // Basic assumption is we start from an 8 byte aligned address\r
1270 // and our file header is a multiple of 8 bytes\r
1271 //\r
1272 assert ((UINTN) FvImage->CurrentFilePointer % 8 == 0);\r
1273 assert (sizeof (EFI_FFS_FILE_HEADER) % 8 == 0);\r
1274\r
1275 //\r
1276 // Check if a pad file is necessary\r
1277 //\r
1278 if (((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + sizeof (EFI_FFS_FILE_HEADER)) % DataAlignment == 0) {\r
1279 return EFI_SUCCESS;\r
1280 }\r
1281 //\r
1282 // Write pad file header\r
1283 //\r
1284 PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer;\r
1285\r
1286 //\r
1287 // Verify that we have enough space for the file header\r
1288 //\r
1289 if ((UINTN) (PadFile + sizeof (EFI_FFS_FILE_HEADER)) >= (UINTN) FvImage->Eof) {\r
1290 return EFI_OUT_OF_RESOURCES;\r
1291 }\r
1292\r
1293 UuidCreate (&PadFileGuid);\r
1294 memset (PadFile, 0, sizeof (EFI_FFS_FILE_HEADER));\r
1295 memcpy (&PadFile->Name, &PadFileGuid, sizeof (EFI_GUID));\r
1296 PadFile->Type = EFI_FV_FILETYPE_FFS_PAD;\r
1297 PadFile->Attributes = 0;\r
1298\r
1299 //\r
1300 // Calculate the pad file size\r
1301 //\r
1302 //\r
1303 // This is the earliest possible valid offset (current plus pad file header\r
1304 // plus the next file header)\r
1305 //\r
1306 PadFileSize = (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + (sizeof (EFI_FFS_FILE_HEADER) * 2);\r
1307\r
1308 //\r
1309 // Add whatever it takes to get to the next aligned address\r
1310 //\r
1311 while ((PadFileSize % DataAlignment) != 0) {\r
1312 PadFileSize++;\r
1313 }\r
1314 //\r
1315 // Subtract the next file header size\r
1316 //\r
1317 PadFileSize -= sizeof (EFI_FFS_FILE_HEADER);\r
1318\r
1319 //\r
1320 // Subtract the starting offset to get size\r
1321 //\r
1322 PadFileSize -= (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage;\r
1323\r
1324 //\r
1325 // Write pad file size (calculated size minus next file header size)\r
1326 //\r
1327 PadFile->Size[0] = (UINT8) (PadFileSize & 0xFF);\r
1328 PadFile->Size[1] = (UINT8) ((PadFileSize >> 8) & 0xFF);\r
1329 PadFile->Size[2] = (UINT8) ((PadFileSize >> 16) & 0xFF);\r
1330\r
1331 //\r
1332 // Fill in checksums and state, they must be 0 for checksumming.\r
1333 //\r
1334 PadFile->IntegrityCheck.Checksum.Header = 0;\r
1335 PadFile->IntegrityCheck.Checksum.File = 0;\r
1336 PadFile->State = 0;\r
1337 PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER));\r
1338 if (PadFile->Attributes & FFS_ATTRIB_CHECKSUM) {\r
1339#if (PI_SPECIFICATION_VERSION < 0x00010000) \r
1340 PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) PadFile, PadFileSize);\r
1341#else\r
1342 PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) ((UINTN)PadFile + sizeof (EFI_FFS_FILE_HEADER)), PadFileSize - sizeof (EFI_FFS_FILE_HEADER));\r
1343#endif\r
1344 } else {\r
1345 PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
1346 }\r
1347\r
1348 PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;\r
1349 UpdateFfsFileState (\r
1350 (EFI_FFS_FILE_HEADER *) PadFile,\r
1351 (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage\r
1352 );\r
1353\r
1354 //\r
1355 // Verify that we have enough space (including the padding\r
1356 //\r
1357 if ((UINTN) (PadFile + sizeof (EFI_FFS_FILE_HEADER)) >= (UINTN) FvImage->Eof) {\r
1358 return EFI_OUT_OF_RESOURCES;\r
1359 }\r
1360 //\r
1361 // Update the current FV pointer\r
1362 //\r
1363 FvImage->CurrentFilePointer += PadFileSize;\r
1364\r
1365 return EFI_SUCCESS;\r
1366}\r
1367\r
1368BOOLEAN\r
1369IsVtfFile (\r
1370 IN EFI_FFS_FILE_HEADER *FileBuffer\r
1371 )\r
1372/*++\r
1373\r
1374Routine Description:\r
1375\r
1376 This function checks the header to validate if it is a VTF file\r
1377\r
1378Arguments:\r
1379\r
1380 FileBuffer Buffer in which content of a file has been read.\r
1381\r
1382Returns:\r
1383\r
1384 TRUE If this is a VTF file\r
1385 FALSE If this is not a VTF file\r
1386\r
1387--*/\r
1388{\r
1389 EFI_GUID VtfGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;\r
1390 if (!memcmp (&FileBuffer->Name, &VtfGuid, sizeof (EFI_GUID))) {\r
1391 return TRUE;\r
1392 } else {\r
1393 return FALSE;\r
1394 }\r
1395}\r
1396\r
1397EFI_STATUS\r
1398FfsRebaseImageRead (\r
1399 IN VOID *FileHandle,\r
1400 IN UINTN FileOffset,\r
1401 IN OUT UINT32 *ReadSize,\r
1402 OUT VOID *Buffer\r
1403 )\r
1404/*++\r
1405\r
1406Routine Description:\r
1407\r
1408 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file\r
1409\r
1410Arguments:\r
1411\r
1412 FileHandle - The handle to the PE/COFF file\r
1413\r
1414 FileOffset - The offset, in bytes, into the file to read\r
1415\r
1416 ReadSize - The number of bytes to read from the file starting at FileOffset\r
1417\r
1418 Buffer - A pointer to the buffer to read the data into.\r
1419\r
1420Returns:\r
1421\r
1422 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset\r
1423\r
1424--*/\r
1425{\r
1426 CHAR8 *Destination8;\r
1427 CHAR8 *Source8;\r
1428 UINT32 Length;\r
1429\r
1430 Destination8 = Buffer;\r
1431 Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);\r
1432 Length = *ReadSize;\r
1433 while (Length--) {\r
1434 *(Destination8++) = *(Source8++);\r
1435 }\r
1436\r
1437 return EFI_SUCCESS;\r
1438}\r
1439\r
1440EFI_STATUS\r
1441RebaseFfsFile (\r
1442 IN OUT EFI_FFS_FILE_HEADER *FfsFile,\r
1443 IN EFI_PHYSICAL_ADDRESS BaseAddress\r
1444 )\r
1445/*++\r
1446\r
1447Routine Description:\r
1448\r
1449 This function determines if a file is XIP and should be rebased. It will\r
1450 rebase any PE32 sections found in the file using the base address.\r
1451\r
1452Arguments:\r
1453\r
1454 FfsFile A pointer to Ffs file image.\r
1455 BaseAddress The base address to use for rebasing the file image.\r
1456\r
1457Returns:\r
1458\r
1459 EFI_SUCCESS The image was properly rebased.\r
1460 EFI_INVALID_PARAMETER An input parameter is invalid.\r
1461 EFI_ABORTED An error occurred while rebasing the input file image.\r
1462 EFI_OUT_OF_RESOURCES Could not allocate a required resource.\r
1463\r
1464--*/\r
1465{\r
1466 EFI_STATUS Status;\r
1467 EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
1468 UINTN MemoryImagePointer;\r
1469 UINTN MemoryImagePointerAligned;\r
1470\r
1471 EFI_PHYSICAL_ADDRESS ImageAddress;\r
1472 UINT64 ImageSize;\r
1473 EFI_PHYSICAL_ADDRESS EntryPoint;\r
1474\r
1475 UINT32 Pe32FileSize;\r
1476 UINT32 NewPe32BaseAddress;\r
1477\r
1478 UINTN Index;\r
1479 EFI_FILE_SECTION_POINTER CurrentPe32Section;\r
1480 UINT8 FileGuidString[80];\r
1481\r
1482 //\r
1483 // Verify input parameters\r
1484 //\r
1485 if (FfsFile == NULL) {\r
1486 return EFI_INVALID_PARAMETER;\r
1487 }\r
1488 //\r
1489 // Convert the GUID to a string so we can at least report which file\r
1490 // if we find an error.\r
1491 //\r
1492 PrintGuidToBuffer (&FfsFile->Name, FileGuidString, sizeof (FileGuidString), TRUE);\r
1493\r
1494 //\r
1495 // Do some nominal checks on the file, then check for XIP.\r
1496 //\r
1497 Status = VerifyFfsFile (FfsFile);\r
1498 if (EFI_ERROR (Status)) {\r
1499 Error (NULL, 0, 0, "invalid FFS file", FileGuidString);\r
1500 return EFI_INVALID_PARAMETER;\r
1501 }\r
1502\r
1503 if (FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE &&\r
1504 FfsFile->Type != EFI_FV_FILETYPE_PEI_CORE &&\r
1505 FfsFile->Type != EFI_FV_FILETYPE_PEIM\r
1506 ) {\r
1507 //\r
1508 // File is not XIP, so don't rebase\r
1509 //\r
1510 return EFI_SUCCESS;\r
1511 }\r
1512 //\r
1513 // Rebase each PE32 section\r
1514 //\r
1515 for (Index = 1;; Index++) {\r
1516 Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, Index, &CurrentPe32Section);\r
1517 if (EFI_ERROR (Status)) {\r
1518 break;\r
1519 }\r
1520 //\r
1521 // Calculate the PE32 base address, the FFS file base plus the offset of the PE32 section\r
1522 //\r
1523 NewPe32BaseAddress = ((UINT32) BaseAddress) + ((UINTN) CurrentPe32Section.Pe32Section - (UINTN) FfsFile);\r
1524\r
1525 //\r
1526 // Initialize context\r
1527 //\r
1528 memset (&ImageContext, 0, sizeof (ImageContext));\r
1529 ImageContext.Handle = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION));\r
1530 ImageContext.ImageRead = (EFI_PEI_PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;\r
1531\r
1532 Status = mPeCoffLoader.GetImageInfo (&mPeCoffLoader, &ImageContext);\r
1533\r
1534 if (EFI_ERROR (Status)) {\r
1535 Error (NULL, 0, 0, "GetImageInfo() failed", FileGuidString);\r
1536 return Status;\r
1537 }\r
1538 //\r
1539 // Allocate a buffer for the image to be loaded into.\r
1540 //\r
1541 Pe32FileSize = GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size);\r
1542 MemoryImagePointer = (UINTN) (malloc (Pe32FileSize + 0x1000));\r
1543 MemoryImagePointerAligned = (MemoryImagePointer + 0x0FFF) & (-1 << 12);\r
1544 if (MemoryImagePointerAligned == 0) {\r
1545 Error (NULL, 0, 0, "memory allocation failure", NULL);\r
1546 return EFI_OUT_OF_RESOURCES;\r
1547 }\r
1548\r
1549 //\r
1550 // bugbug\r
1551 //\r
1552 ImageContext.ImageAddress = MemoryImagePointerAligned;\r
1553 Status = mPeCoffLoader.LoadImage (&mPeCoffLoader, &ImageContext);\r
1554 if (EFI_ERROR (Status)) {\r
1555 Error (NULL, 0, 0, "LoadImage() failure", FileGuidString);\r
1556 free ((VOID *) MemoryImagePointer);\r
1557 return Status;\r
1558 }\r
1559\r
1560 Status = mPeCoffLoader.RelocateImage (&mPeCoffLoader, &ImageContext);\r
1561 if (EFI_ERROR (Status)) {\r
1562 Error (NULL, 0, 0, "RelocateImage() failure", FileGuidString);\r
1563 free ((VOID *) MemoryImagePointer);\r
1564 return Status;\r
1565 }\r
1566\r
1567 ImageAddress = ImageContext.ImageAddress;\r
1568 ImageSize = ImageContext.ImageSize;\r
1569 EntryPoint = ImageContext.EntryPoint;\r
1570\r
1571 if (ImageSize > Pe32FileSize) {\r
1572 Error (\r
1573 NULL,\r
1574 0,\r
1575 0,\r
1576 "rebased PE32 is larger than original PE32 image",\r
1577 "0x%X > 0x%X on file %s",\r
1578 ImageSize,\r
1579 Pe32FileSize,\r
1580 FileGuidString\r
1581 );\r
1582 free ((VOID *) MemoryImagePointer);\r
1583 return EFI_ABORTED;\r
1584 }\r
1585\r
1586 memcpy (CurrentPe32Section.Pe32Section, (VOID *) MemoryImagePointerAligned, Pe32FileSize);\r
1587\r
1588 free ((VOID *) MemoryImagePointer);\r
1589 }\r
1590 //\r
1591 // the above for loop will always exit with EFI_NOT_FOUND if it completes\r
1592 // normally. If Index == 1 at exit, then no PE32 sections were found. If it\r
1593 // exits with any other error code, then something broke...\r
1594 //\r
1595 if (Status != EFI_NOT_FOUND) {\r
1596 Error (NULL, 0, 0, "failed to parse PE32 section", FileGuidString);\r
1597 return Status;\r
1598 }\r
1599\r
1600 return EFI_SUCCESS;\r
1601}\r
1602\r
1603EFI_STATUS\r
1604AddSymFile (\r
1605 IN UINT64 BaseAddress,\r
1606 IN EFI_FFS_FILE_HEADER *FfsFile,\r
1607 IN OUT MEMORY_FILE *SymImage,\r
1608 IN CHAR8 *SourceFileName\r
1609 )\r
1610/*++\r
1611\r
1612Routine Description:\r
1613\r
1614 This function adds the SYM tokens in the source file to the destination file.\r
1615 The SYM tokens are updated to reflect the base address.\r
1616\r
1617Arguments:\r
1618\r
1619 BaseAddress The base address for the new SYM tokens.\r
1620 FfsFile Pointer to the beginning of the FFS file in question.\r
1621 SymImage The memory file to update with symbol information.\r
1622 SourceFileName The source file.\r
1623\r
1624Returns:\r
1625\r
1626 EFI_SUCCESS The function completed successfully.\r
1627 EFI_INVALID_PARAMETER One of the input parameters was invalid.\r
1628 EFI_ABORTED An error occurred.\r
1629\r
1630--*/\r
1631{\r
1632 FILE *SourceFile;\r
1633\r
1634 CHAR8 Buffer[_MAX_PATH];\r
1635 CHAR8 Type[_MAX_PATH];\r
1636 CHAR8 Address[_MAX_PATH];\r
1637 CHAR8 Section[_MAX_PATH];\r
1638 CHAR8 Token[_MAX_PATH];\r
1639 CHAR8 SymFileName[_MAX_PATH];\r
1640 CHAR8 CodeModuleName[_MAX_PATH];\r
1641 CHAR8 *Ptr;\r
1642\r
1643 UINT64 TokenAddress;\r
1644\r
1645 EFI_STATUS Status;\r
1646 EFI_FILE_SECTION_POINTER Pe32Section;\r
1647 UINT32 EntryPoint;\r
1648 UINT32 BaseOfCode;\r
1649 UINT16 MachineType;\r
1650\r
1651 //\r
1652 // Verify input parameters.\r
1653 //\r
1654 if (BaseAddress == 0 || FfsFile == NULL || SymImage == NULL || SourceFileName == NULL) {\r
1655 Error (NULL, 0, 0, "invalid parameter passed to AddSymFile()", NULL);\r
1656 return EFI_INVALID_PARAMETER;\r
1657 }\r
1658 //\r
1659 // Check if we want to add this file\r
1660 //\r
1661 //\r
1662 // Get the file name\r
1663 //\r
1664 strcpy (Buffer, SourceFileName);\r
1665\r
1666 //\r
1667 // Copy the file name for the path of the sym file and truncate the name portion.\r
1668 //\r
1669 strcpy (SymFileName, Buffer);\r
1670 Ptr = strrchr (SymFileName, '\\');\r
1671 assert (Ptr);\r
1672 Ptr[0] = 0;\r
1673\r
1674 //\r
1675 // Find the file extension and make it lower case\r
1676 //\r
1677 Ptr = strrchr (SymFileName, '.');\r
1678 if (Ptr != NULL) {\r
1679 _strlwr (Ptr);\r
1680 }\r
1681 //\r
1682 // Check if it is PEI file\r
1683 //\r
1684 if (strstr (Buffer, ".pei") != NULL) {\r
1685 //\r
1686 // Find the human readable portion\r
1687 //\r
1688 if (!strtok (Buffer, "-") ||\r
1689 !strtok (NULL, "-") ||\r
1690 !strtok (NULL, "-") ||\r
1691 !strtok (NULL, "-") ||\r
1692 !strtok (NULL, "-") ||\r
1693 !strcpy (Buffer, strtok (NULL, "."))\r
1694 ) {\r
1695 Error (NULL, 0, 0, "failed to find human readable portion of the file name in AddSymFile()", NULL);\r
1696 return EFI_ABORTED;\r
1697 }\r
1698 //\r
1699 // Save code module name\r
1700 //\r
1701 strcpy (CodeModuleName, Buffer);\r
1702\r
1703 //\r
1704 // Add the symbol file name and extension to the file path.\r
1705 //\r
1706 strcat (Buffer, ".sym");\r
1707 strcat (SymFileName, "\\");\r
1708 strcat (SymFileName, Buffer);\r
1709 } else {\r
1710 //\r
1711 // Only handle PEIM files.\r
1712 //\r
1713 return EFI_SUCCESS;\r
1714 }\r
1715 //\r
1716 // Find PE32 section\r
1717 //\r
1718 Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, 1, &Pe32Section);\r
1719\r
1720 //\r
1721 // BUGBUG: Assume if no PE32 section it is PIC and hardcode base address\r
1722 //\r
1723 if (Status == EFI_NOT_FOUND) {\r
1724 Status = GetSectionByType (FfsFile, EFI_SECTION_TE, 1, &Pe32Section);\r
1725 }\r
1726\r
1727 if (Status == EFI_SUCCESS) {\r
1728 Status = GetPe32Info (\r
1729 (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),\r
1730 &EntryPoint,\r
1731 &BaseOfCode,\r
1732 &MachineType\r
1733 );\r
1734 } else {\r
1735 if (Status == EFI_NOT_FOUND) {\r
1736 BaseOfCode = 0x60;\r
1737 Status = EFI_SUCCESS;\r
1738 } else {\r
1739 Error (NULL, 0, 0, "could not parse a PE32 section from the PEI file", NULL);\r
1740 return Status;\r
1741 }\r
1742 }\r
1743\r
1744 if (EFI_ERROR (Status)) {\r
1745 Error (NULL, 0, 0, "GetPe32Info() could not get PE32 entry point for PEI file", NULL);\r
1746 return Status;\r
1747 }\r
1748\r
1749 //\r
1750 // Open the source file\r
1751 //\r
1752 SourceFile = fopen (SymFileName, "r");\r
1753 if (SourceFile == NULL) {\r
1754 //\r
1755 // SYM files are not required.\r
1756 //\r
1757 return EFI_SUCCESS;\r
1758 }\r
1759 //\r
1760 // Read the first line\r
1761 //\r
1762 if (fgets (Buffer, _MAX_PATH, SourceFile) == NULL) {\r
1763 Buffer[0] = 0;\r
1764 }\r
1765 //\r
1766 // Make sure it matches the expected sym format\r
1767 //\r
1768 if (strcmp (Buffer, "TEXTSYM format | V1.0\n")) {\r
1769 fclose (SourceFile);\r
1770 Error (NULL, 0, 0, "AddSymFile() found unexpected sym format in input file", NULL);\r
1771 return EFI_ABORTED;\r
1772 }\r
1773 //\r
1774 // Read in the file\r
1775 //\r
1776 while (feof (SourceFile) == 0) {\r
1777 //\r
1778 // Read a line\r
1779 //\r
1780 if (fscanf (\r
1781 SourceFile,\r
1782 "%s | %s | %s | %s\n",\r
1783 Type,\r
1784 Address,\r
1785 Section,\r
1786 Token\r
1787 ) == 4) {\r
1788 //\r
1789 // If the token starts with "??" ignore it\r
1790 //\r
1791 if (Token[0] == '?' && Token[1] == '?') {\r
1792 continue;\r
1793 }\r
1794 //\r
1795 // Get the token address\r
1796 //\r
1797 AsciiStringToUint64 (Address, TRUE, &TokenAddress);\r
1798\r
1799 //\r
1800 // Add the base address\r
1801 //\r
1802 TokenAddress += BaseAddress;\r
1803\r
1804 //\r
1805 // If PE32 or TE section then find the start of code. For PIC it is hardcoded.\r
1806 //\r
1807 if (Pe32Section.Pe32Section) {\r
1808 //\r
1809 // Add the offset of the PE32 section\r
1810 //\r
1811 TokenAddress += (UINTN) Pe32Section.Pe32Section - (UINTN) FfsFile;\r
1812\r
1813 //\r
1814 // Add the size of the PE32 section header\r
1815 //\r
1816 TokenAddress += sizeof (EFI_PE32_SECTION);\r
1817 } else {\r
1818 //\r
1819 // BUGBUG: Don't know why this is 0x28 bytes.\r
1820 //\r
1821 TokenAddress += 0x28;\r
1822 }\r
1823 //\r
1824 // Add the beginning of the code\r
1825 //\r
1826 TokenAddress += BaseOfCode;\r
1827\r
1828 sprintf (\r
1829 Buffer,\r
1830 "%s | %016I64X | %s | _%s%s\n",\r
1831 Type,\r
1832 TokenAddress,\r
1833 Section,\r
1834 CodeModuleName,\r
1835 Token\r
1836 );\r
1837 memcpy (SymImage->CurrentFilePointer, Buffer, strlen (Buffer) + 1);\r
1838 SymImage->CurrentFilePointer = (UINT8 *) (((UINTN) SymImage->CurrentFilePointer) + strlen (Buffer) + 1);\r
1839 }\r
1840 }\r
1841\r
1842 fclose (SourceFile);\r
1843 return EFI_SUCCESS;\r
1844}\r
1845\r
1846EFI_STATUS\r
1847ReallocateFvImage (\r
1848 IN OUT MEMORY_FILE *FvImage,\r
1849 IN OUT FV_INFO *FvInfo,\r
1850 IN OUT EFI_FFS_FILE_HEADER **VtfFileImage,\r
1851 IN OUT UINTN *FvImageCapacity\r
1852 )\r
1853/*++\r
1854Routine Description:\r
1855 Increase the size of FV image by 1 block. The routine may reallocate memory\r
1856 depending on the capacity of the FV image.\r
1857\r
1858Arguments:\r
1859 FvImage The memory image of the FV to add it to. The current offset\r
1860 must be valid.\r
1861 FvInfo Pointer to information about the FV.\r
1862 VtfFileImage A pointer to the VTF file within the FvImage. If this is equal\r
1863 to the end of the FvImage then no VTF previously found.\r
1864 FvImageCapacity Capacity of image buffer for FV.\r
1865\r
1866Returns:\r
1867 EFI_SUCCESS The function completed successfully.\r
1868 EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the reallocation.\r
1869\r
1870--*/\r
1871{\r
1872 CHAR8 *FileImage;\r
1873 UINTN OldSize;\r
1874 UINTN IncreaseSize;\r
1875 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;\r
1876 BOOLEAN AllocateNewMemory;\r
1877 EFI_FFS_FILE_HEADER *NewVtfFileImage;\r
1878 UINT32 VtfFileLength;\r
1879 UINT8 TempByte;\r
1880\r
1881 OldSize = (UINTN) FvImage->Eof - (UINTN) FvImage->FileImage;\r
1882 IncreaseSize = FvInfo->FvBlocks[0].BlockLength;\r
1883 assert (OldSize == FvInfo->FvBlocks[0].NumBlocks * FvInfo->FvBlocks[0].BlockLength);\r
1884\r
1885 //\r
1886 // Assume we have enough capacity\r
1887 //\r
1888 AllocateNewMemory = FALSE;\r
1889 \r
1890\r
1891 if (OldSize + IncreaseSize > *FvImageCapacity) {\r
1892 AllocateNewMemory = TRUE;\r
1893 //\r
1894 // Increase capacity by one unit\r
1895 //\r
1896 *FvImageCapacity = OldSize + FV_CAPACITY_INCREASE_UNIT;\r
1897 FileImage = malloc (*FvImageCapacity);\r
1898\r
1899 if (FileImage == NULL) {\r
1900 Error (NULL, 0, 0, "memory allocation failure", NULL);\r
1901 return EFI_OUT_OF_RESOURCES;\r
1902 }\r
1903\r
1904 //\r
1905 // Initialize the content per FV polarity\r
1906 //\r
1907 if (FvInfo->FvAttributes & EFI_FVB_ERASE_POLARITY) {\r
1908 memset (FileImage, -1, *FvImageCapacity);\r
1909 } else {\r
1910 memset (FileImage, 0, *FvImageCapacity);\r
1911 }\r
1912\r
1913 //\r
1914 // Copy the FV content before VTF\r
1915 //\r
1916 memcpy (FileImage, FvImage->FileImage, (UINTN) *VtfFileImage - (UINTN) FvImage->FileImage);\r
1917 } else {\r
1918 FileImage = FvImage->FileImage;\r
1919 }\r
1920\r
1921 //\r
1922 // Move VTF if it exists\r
1923 //\r
1924 NewVtfFileImage = (EFI_FFS_FILE_HEADER *) (FileImage + ((UINTN) *VtfFileImage - (UINTN) FvImage->FileImage) + IncreaseSize);\r
1925 if ((UINTN) *VtfFileImage != (UINTN) FvImage->Eof) {\r
1926 //\r
1927 // Exchange the VTF buffer from end to start for two purpose:\r
1928 // 1. Exchange: Preserve the default value per FV polarity\r
1929 // 2. End->Start: Avoid destroying the VTF data during exchanging\r
1930 //\r
1931 VtfFileLength = GetLength ((*VtfFileImage)->Size);\r
1932 while (VtfFileLength-- != 0) {\r
1933 TempByte = ((UINT8 *) VtfFileImage)[VtfFileLength];\r
1934 ((UINT8 *) VtfFileImage)[VtfFileLength] = ((UINT8 *) NewVtfFileImage)[VtfFileLength];\r
1935 ((UINT8 *) NewVtfFileImage)[VtfFileLength] = TempByte;\r
1936 }\r
1937 }\r
1938\r
1939 //\r
1940 // Update VTF Pointer\r
1941 //\r
1942 *VtfFileImage = NewVtfFileImage;\r
1943\r
1944 //\r
1945 // Update FvInfo\r
1946 //\r
1947 FvInfo->FvBlocks[0].NumBlocks ++;\r
1948\r
1949 //\r
1950 // Update FV Header\r
1951 //\r
1952 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FileImage;\r
1953 FvHeader->FvBlockMap[0].NumBlocks = FvInfo->FvBlocks[0].NumBlocks;\r
1954 FvHeader->FvLength = OldSize + IncreaseSize;\r
1955 FvHeader->Checksum = 0;\r
1956 FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));\r
1957 \r
1958 //\r
1959 // Update FvImage\r
1960 //\r
1961 if (AllocateNewMemory) {\r
1962 free (FvImage->FileImage);\r
1963 FvImage->CurrentFilePointer = FileImage + (FvImage->CurrentFilePointer - FvImage->FileImage); \r
1964 FvImage->FileImage = FileImage;\r
1965 }\r
1966 FvImage->Eof = FvImage->FileImage + OldSize + IncreaseSize;\r
1967\r
1968 InitializeFvLib (FvImage->FileImage, OldSize + IncreaseSize);\r
1969 return EFI_SUCCESS;\r
1970}\r
1971\r
1972EFI_STATUS\r
1973AddFile (\r
1974 IN OUT MEMORY_FILE *FvImage,\r
1975 IN FV_INFO *FvInfo,\r
1976 IN UINTN Index,\r
1977 IN OUT EFI_FFS_FILE_HEADER **VtfFileImage,\r
1978 IN OUT MEMORY_FILE *SymImage,\r
1979 IN OUT UINTN *FvImageCapacity\r
1980 )\r
1981/*++\r
1982\r
1983Routine Description:\r
1984\r
1985 This function adds a file to the FV image. The file will pad to the\r
1986 appropriate alignment if required.\r
1987\r
1988Arguments:\r
1989\r
1990 FvImage The memory image of the FV to add it to. The current offset\r
1991 must be valid.\r
1992 FvInfo Pointer to information about the FV.\r
1993 Index The file in the FvInfo file list to add.\r
1994 VtfFileImage A pointer to the VTF file within the FvImage. If this is equal\r
1995 to the end of the FvImage then no VTF previously found.\r
1996 SymImage The memory image of the Sym file to update if symbols are present.\r
1997 The current offset must be valid.\r
1998 FvImageCapacity Capacity of image buffer for FV.\r
1999\r
2000Returns:\r
2001\r
2002 EFI_SUCCESS The function completed successfully.\r
2003 EFI_INVALID_PARAMETER One of the input parameters was invalid.\r
2004 EFI_ABORTED An error occurred.\r
2005 EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the add.\r
2006\r
2007--*/\r
2008{\r
2009 FILE *NewFile;\r
2010 UINTN FileSize;\r
2011 UINT8 *FileBuffer;\r
2012 UINTN NumBytesRead;\r
2013 UINT32 CurrentFileAlignment;\r
2014 EFI_STATUS Status;\r
2015 EFI_PHYSICAL_ADDRESS CurrentFileBaseAddress;\r
2016 UINT8 VtfHeaderChecksum;\r
2017 UINT8 VtfFileChecksum;\r
2018 UINT8 FileState;\r
2019 UINT32 TailSize;\r
2020#if (PI_SPECIFICATION_VERSION < 0x00010000)\r
2021 EFI_FFS_FILE_TAIL TailValue;\r
2022#endif\r
2023 //\r
2024 // Verify input parameters.\r
2025 //\r
2026 if (FvImage == NULL || FvInfo == NULL || FvInfo->FvFiles[Index][0] == 0 || VtfFileImage == NULL || SymImage == NULL) {\r
2027 return EFI_INVALID_PARAMETER;\r
2028 }\r
2029 //\r
2030 // Read the file to add\r
2031 //\r
2032 NewFile = fopen (FvInfo->FvFiles[Index], "rb");\r
2033\r
2034 if (NewFile == NULL) {\r
2035 Error (NULL, 0, 0, FvInfo->FvFiles[Index], "failed to open file for reading");\r
2036 return EFI_ABORTED;\r
2037 }\r
2038 //\r
2039 // Get the file size\r
2040 //\r
2041 FileSize = _filelength (_fileno (NewFile));\r
2042\r
2043 //\r
2044 // Read the file into a buffer\r
2045 //\r
2046 FileBuffer = malloc (FileSize);\r
2047 if (FileBuffer == NULL) {\r
2048 Error (NULL, 0, 0, "memory allocation failure", NULL);\r
2049 return EFI_OUT_OF_RESOURCES;\r
2050 }\r
2051\r
2052 NumBytesRead = fread (FileBuffer, sizeof (UINT8), FileSize, NewFile);\r
2053\r
2054 //\r
2055 // Done with the file, from this point on we will just use the buffer read.\r
2056 //\r
2057 fclose (NewFile);\r
2058\r
2059 //\r
2060 // Verify read successful\r
2061 //\r
2062 if (NumBytesRead != sizeof (UINT8) * FileSize) {\r
2063 Error (NULL, 0, 0, FvInfo->FvFiles[Index], "failed to read input file contents");\r
2064 Status = EFI_ABORTED;\r
2065 goto Exit;\r
2066 }\r
2067 //\r
2068 // Verify space exists to add the file\r
2069 //\r
2070 while (FileSize > (UINTN) ((UINTN) *VtfFileImage - (UINTN) FvImage->CurrentFilePointer)) {\r
2071 if (FvInfo->Size != (UINTN) -1) {\r
2072 Error (NULL, 0, 0, FvInfo->FvFiles[Index], "insufficient space remains to add the file");\r
2073 Status = EFI_OUT_OF_RESOURCES;\r
2074 goto Exit;\r
2075 } else {\r
2076 //\r
2077 // FV Size is AUTO, increase by one block\r
2078 //\r
2079 Status = ReallocateFvImage (FvImage, FvInfo, VtfFileImage, FvImageCapacity);\r
2080 if (EFI_ERROR (Status)) {\r
2081 Error (NULL, 0, 0, FvInfo->FvFiles[Index], "insufficient resources to add the file");\r
2082 goto Exit;\r
2083 }\r
2084 }\r
2085 }\r
2086 //\r
2087 // Update the file state based on polarity of the FV.\r
2088 //\r
2089 UpdateFfsFileState (\r
2090 (EFI_FFS_FILE_HEADER *) FileBuffer,\r
2091 (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage\r
2092 );\r
2093\r
2094 //\r
2095 // If we have a VTF file, add it at the top.\r
2096 //\r
2097 if (IsVtfFile ((EFI_FFS_FILE_HEADER *) FileBuffer)) {\r
2098 if ((UINTN) *VtfFileImage == (UINTN) FvImage->Eof) {\r
2099 //\r
2100 // No previous VTF, add this one.\r
2101 //\r
2102 *VtfFileImage = (EFI_FFS_FILE_HEADER *) (UINTN) ((UINTN) FvImage->FileImage + FvInfo->Size - FileSize);\r
2103 //\r
2104 // Sanity check. The file MUST align appropriately\r
2105 //\r
2106 if ((((UINTN) *VtfFileImage) & 0x07) != 0) {\r
2107 Error (NULL, 0, 0, "VTF file does not align on 8-byte boundary", NULL);\r
2108 }\r
2109 //\r
2110 // copy VTF File Header\r
2111 //\r
2112 memcpy (*VtfFileImage, FileBuffer, sizeof (EFI_FFS_FILE_HEADER));\r
2113\r
2114 //\r
2115 // Copy VTF body\r
2116 //\r
2117 memcpy (\r
2118 (UINT8 *) *VtfFileImage + sizeof (EFI_FFS_FILE_HEADER),\r
2119 FileBuffer + sizeof (EFI_FFS_FILE_HEADER),\r
2120 FileSize - sizeof (EFI_FFS_FILE_HEADER)\r
2121 );\r
2122\r
2123 //\r
2124 // re-calculate the VTF File Header\r
2125 //\r
2126 FileState = (*VtfFileImage)->State;\r
2127 (*VtfFileImage)->State = 0;\r
2128 *(UINT32 *) ((*VtfFileImage)->Size) = FileSize;\r
2129 (*VtfFileImage)->IntegrityCheck.Checksum.Header = 0;\r
2130 (*VtfFileImage)->IntegrityCheck.Checksum.File = 0;\r
2131\r
2132 VtfHeaderChecksum = CalculateChecksum8 ((UINT8 *) *VtfFileImage, sizeof (EFI_FFS_FILE_HEADER));\r
2133 (*VtfFileImage)->IntegrityCheck.Checksum.Header = VtfHeaderChecksum;\r
2134 //\r
2135 // Determine if it has a tail\r
2136 //\r
2137 if ((*VtfFileImage)->Attributes & FFS_ATTRIB_TAIL_PRESENT) {\r
2138 TailSize = sizeof (EFI_FFS_FILE_TAIL);\r
2139 } else {\r
2140 TailSize = 0;\r
2141 }\r
2142\r
2143 if ((*VtfFileImage)->Attributes & FFS_ATTRIB_CHECKSUM) {\r
2144 #if (PI_SPECIFICATION_VERSION < 0x00010000)\r
2145 VtfFileChecksum = CalculateChecksum8 ((UINT8 *) *VtfFileImage, FileSize - TailSize);\r
2146 #else\r
2147 VtfFileChecksum = CalculateChecksum8 ((UINT8 *) ((UINTN)*VtfFileImage + sizeof (EFI_FFS_FILE_HEADER)), FileSize - TailSize - sizeof(EFI_FFS_FILE_HEADER));\r
2148 #endif\r
2149 (*VtfFileImage)->IntegrityCheck.Checksum.File = VtfFileChecksum;\r
2150 } else {\r
2151 (*VtfFileImage)->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
2152 }\r
2153 #if (PI_SPECIFICATION_VERSION < 0x00010000)\r
2154 //\r
2155 // If it has a file tail, update it\r
2156 //\r
2157 if ((*VtfFileImage)->Attributes & FFS_ATTRIB_TAIL_PRESENT) {\r
2158 TailValue = (EFI_FFS_FILE_TAIL) (~((*VtfFileImage)->IntegrityCheck.TailReference));\r
2159 *(EFI_FFS_FILE_TAIL *) (((UINTN) (*VtfFileImage) + GetLength ((*VtfFileImage)->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;\r
2160 }\r
2161 #endif \r
2162 (*VtfFileImage)->State = FileState;\r
2163 Status = EFI_SUCCESS;\r
2164 goto Exit;\r
2165 } else {\r
2166 //\r
2167 // Already found a VTF file.\r
2168 //\r
2169 Error (NULL, 0, 0, "multiple VTF files are illegal in a single FV", NULL);\r
2170 Status = EFI_ABORTED;\r
2171 goto Exit;\r
2172 }\r
2173 }\r
2174 //\r
2175 // Check if alignment is required\r
2176 //\r
2177 Status = ReadFfsAlignment ((EFI_FFS_FILE_HEADER *) FileBuffer, &CurrentFileAlignment);\r
2178 if (EFI_ERROR (Status)) {\r
2179 printf ("ERROR: Could not determine alignment of file %s.\n", FvInfo->FvFiles[Index]);\r
2180 Status = EFI_ABORTED;\r
2181 goto Exit;\r
2182 }\r
2183 //\r
2184 // Add pad file if necessary\r
2185 //\r
2186 while (EFI_ERROR (AddPadFile (FvImage, CurrentFileAlignment))) {\r
2187 if (FvInfo->Size != (UINTN) -1) {\r
2188 printf ("ERROR: Could not align the file data properly.\n");\r
2189 Status = EFI_ABORTED;\r
2190 goto Exit;\r
2191 } else { \r
2192 //\r
2193 // FV Size is AUTO, increase by one block\r
2194 //\r
2195 Status = ReallocateFvImage (FvImage, FvInfo, VtfFileImage, FvImageCapacity);\r
2196 if (EFI_ERROR (Status)) {\r
2197 Error (NULL, 0, 0, FvInfo->FvFiles[Index], "insufficient resources to add the file");\r
2198 goto Exit;\r
2199 } \r
2200 }\r
2201 }\r
2202\r
2203 //\r
2204 // Add file\r
2205 //\r
2206 while (FileSize > (UINTN) ((UINTN) *VtfFileImage - (UINTN) FvImage->CurrentFilePointer)) {\r
2207 if (FvInfo->Size != (UINTN) -1) {\r
2208 printf ("ERROR: The firmware volume is out of space, could not add file %s.\n", FvInfo->FvFiles[Index]);\r
2209 Status = EFI_ABORTED;\r
2210 goto Exit;\r
2211 } else { \r
2212 //\r
2213 // FV Size is AUTO, increase by one one block\r
2214 //\r
2215 Status = ReallocateFvImage (FvImage, FvInfo, VtfFileImage, FvImageCapacity);\r
2216 if (EFI_ERROR (Status)) {\r
2217 Error (NULL, 0, 0, FvInfo->FvFiles[Index], "insufficient resources to add the file");\r
2218 goto Exit;\r
2219 }\r
2220 }\r
2221 }\r
2222\r
2223 //\r
2224 // Copy the file\r
2225 //\r
2226 memcpy (FvImage->CurrentFilePointer, FileBuffer, FileSize);\r
2227\r
2228 //\r
2229 // If the file is XIP, rebase\r
2230 //\r
2231 CurrentFileBaseAddress = FvInfo->BaseAddress + ((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage);\r
2232 //\r
2233 // Status = RebaseFfsFile ((EFI_FFS_FILE_HEADER*) FvImage->CurrentFilePointer, CurrentFileBaseAddress);\r
2234 // if (EFI_ERROR(Status)) {\r
2235 // printf ("ERROR: Could not rebase the file %s.\n", FvInfo->FvFiles[Index]);\r
2236 // return EFI_ABORTED;\r
2237 // }\r
2238 //\r
2239 // Update Symbol file\r
2240 //\r
2241 Status = AddSymFile (\r
2242 CurrentFileBaseAddress,\r
2243 (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer,\r
2244 SymImage,\r
2245 FvInfo->FvFiles[Index]\r
2246 );\r
2247 assert (!EFI_ERROR (Status));\r
2248\r
2249 //\r
2250 // Update the current pointer in the FV image\r
2251 //\r
2252 FvImage->CurrentFilePointer += FileSize;\r
2253\r
2254 //\r
2255 // Make next file start at QWord Boundry\r
2256 //\r
2257 while (((UINTN) FvImage->CurrentFilePointer & 0x07) != 0) {\r
2258 FvImage->CurrentFilePointer++;\r
2259 }\r
2260\r
2261Exit:\r
2262 //\r
2263 // Free allocated memory.\r
2264 //\r
2265 free (FileBuffer);\r
2266 return Status;\r
2267}\r
2268\r
2269EFI_STATUS\r
2270AddVariableBlock (\r
2271 IN UINT8 *FvImage,\r
2272 IN UINTN Size,\r
2273 IN FV_INFO *FvInfo\r
2274 )\r
2275{\r
2276 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;\r
2277 VARIABLE_STORE_HEADER *VarStoreHeader;\r
2278 //\r
2279 // Variable block should exclude FvHeader. Since the length of\r
2280 // FvHeader depends on the block map, which is variable length,\r
2281 // we could only decide the actual variable block length here.\r
2282 //\r
2283 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage;\r
2284 FvImage = FvImage + FvHeader->HeaderLength;\r
2285\r
2286 VarStoreHeader = (VARIABLE_STORE_HEADER *) FvImage;\r
2287\r
2288 VarStoreHeader->Signature = VARIABLE_STORE_SIGNATURE;\r
2289 VarStoreHeader->Size = Size - FvHeader->HeaderLength;\r
2290 VarStoreHeader->Format = VARIABLE_STORE_FORMATTED;\r
2291 VarStoreHeader->State = VARIABLE_STORE_HEALTHY;\r
2292 VarStoreHeader->Reserved = 0;\r
2293 VarStoreHeader->Reserved1 = 0;\r
2294\r
2295 return EFI_SUCCESS;\r
2296}\r
2297\r
2298EFI_STATUS\r
2299AddEventLogBlock (\r
2300 IN UINT8 *FvImage,\r
2301 IN UINTN Size,\r
2302 IN FV_INFO *FvInfo\r
2303 )\r
2304{\r
2305 return EFI_SUCCESS;\r
2306}\r
2307\r
2308EFI_STATUS\r
2309AddFTWWorkingBlock (\r
2310 IN UINT8 *FvImage,\r
2311 IN UINTN Size,\r
2312 IN FV_INFO *FvInfo\r
2313 )\r
2314{\r
2315 EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *FTWHeader;\r
2316 UINT32 Crc32;\r
2317\r
2318 Crc32 = 0;\r
2319 FTWHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) FvImage;\r
2320 memcpy (&FTWHeader->Signature, &(FvInfo->FvGuid), sizeof (EFI_GUID));\r
2321 FTWHeader->WriteQueueSize = Size - sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER);\r
2322 CalculateCrc32 (FvImage, sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER), &Crc32);\r
2323 FTWHeader->Crc = Crc32;\r
2324 if (FvInfo->FvAttributes & EFI_FVB_ERASE_POLARITY) {\r
2325 FTWHeader->WorkingBlockValid = 0;\r
2326 FTWHeader->WorkingBlockInvalid = 1;\r
2327 } else {\r
2328 FTWHeader->WorkingBlockValid = 1;\r
2329 FTWHeader->WorkingBlockInvalid = 0;\r
2330 }\r
2331\r
2332 return EFI_SUCCESS;\r
2333}\r
2334\r
2335EFI_STATUS\r
2336AddFTWSpareBlock (\r
2337 IN UINT8 *FvImage,\r
2338 IN UINTN Size,\r
2339 IN FV_INFO *FvInfo\r
2340 )\r
2341{\r
2342 return EFI_SUCCESS;\r
2343}\r
2344\r
2345EFI_STATUS\r
2346GenNonFFSFv (\r
2347 IN UINT8 *FvImage,\r
2348 IN FV_INFO *FvInfo\r
2349 )\r
2350/*++\r
2351\r
2352Routine Description:\r
2353\r
2354 This function generate the non FFS FV image, such as the working block\r
2355 and spare block. How each component of the FV is built is component\r
2356 specific.\r
2357\r
2358Arguments:\r
2359\r
2360 FvImage The memory image of the FV to add it to. The current offset\r
2361 must be valid.\r
2362 FvInfo Pointer to information about the FV.\r
2363\r
2364Returns:\r
2365\r
2366 EFI_SUCCESS The function completed successfully.\r
2367 EFI_INVALID_PARAMETER One of the input parameters was invalid.\r
2368 EFI_ABORTED An error occurred.\r
2369 EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the add.\r
2370\r
2371--*/\r
2372{\r
2373 UINTN Index;\r
2374 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;\r
2375 UINT64 TotalSize;\r
2376\r
2377 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage;\r
2378 TotalSize = 0;\r
2379\r
2380 for (Index = 0; FvInfo->FvComponents[Index].Size != 0; Index++) {\r
2381 if (_stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_VARIABLE_STRING) == 0) {\r
2382 AddVariableBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);\r
2383 } else if (_stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_EVENT_LOG_STRING) == 0) {\r
2384 AddEventLogBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);\r
2385 } else if (_stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_WORKING_STRING) == 0) {\r
2386 AddFTWWorkingBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);\r
2387 } else if (_stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_SPARE_STRING) == 0) {\r
2388 AddFTWSpareBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);\r
2389 } else {\r
2390 printf ("Warning: Unknown Non-FFS block %s \n", FvInfo->FvComponents[Index].ComponentName);\r
2391 }\r
2392\r
2393 FvImage = FvImage + FvInfo->FvComponents[Index].Size;\r
2394 TotalSize = TotalSize + FvInfo->FvComponents[Index].Size;\r
2395 }\r
2396 //\r
2397 // Index and TotalSize is zero mean there's no component, so this is an empty fv\r
2398 //\r
2399 if ((Index != 0 || TotalSize != 0) && TotalSize != FvInfo->Size) {\r
2400 printf ("Error. Component size does not sum up to FV size.\n");\r
2401 return EFI_ABORTED;\r
2402 }\r
2403\r
2404 return EFI_SUCCESS;\r
2405}\r
2406\r
2407EFI_STATUS\r
2408PadFvImage (\r
2409 IN MEMORY_FILE *FvImage,\r
2410 IN EFI_FFS_FILE_HEADER *VtfFileImage\r
2411 )\r
2412/*++\r
2413\r
2414Routine Description:\r
2415\r
2416 This function places a pad file between the last file in the FV and the VTF\r
2417 file if the VTF file exists.\r
2418\r
2419Arguments:\r
2420\r
2421 FvImage Memory file for the FV memory image\r
2422 VtfFileImage The address of the VTF file. If this is the end of the FV\r
2423 image, no VTF exists and no pad file is needed.\r
2424\r
2425Returns:\r
2426\r
2427 EFI_SUCCESS Completed successfully.\r
2428 EFI_INVALID_PARAMETER One of the input parameters was NULL.\r
2429\r
2430--*/\r
2431{\r
2432 EFI_FFS_FILE_HEADER *PadFile;\r
2433 UINTN FileSize;\r
2434\r
2435 //\r
2436 // If there is no VTF or the VTF naturally follows the previous file without a\r
2437 // pad file, then there's nothing to do\r
2438 //\r
2439 if ((UINTN) VtfFileImage == (UINTN) FvImage->Eof || (void *) FvImage->CurrentFilePointer == (void *) VtfFileImage) {\r
2440 return EFI_SUCCESS;\r
2441 }\r
2442 //\r
2443 // Pad file starts at beginning of free space\r
2444 //\r
2445 PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer;\r
2446\r
2447 //\r
2448 // write header\r
2449 //\r
2450 memset (PadFile, 0, sizeof (EFI_FFS_FILE_HEADER));\r
2451 memcpy (&PadFile->Name, &DefaultFvPadFileNameGuid, sizeof (EFI_GUID));\r
2452 PadFile->Type = EFI_FV_FILETYPE_FFS_PAD;\r
2453 PadFile->Attributes = 0;\r
2454\r
2455 //\r
2456 // FileSize includes the EFI_FFS_FILE_HEADER\r
2457 //\r
2458 FileSize = (UINTN) VtfFileImage - (UINTN) FvImage->CurrentFilePointer;\r
2459 PadFile->Size[0] = (UINT8) (FileSize & 0x000000FF);\r
2460 PadFile->Size[1] = (UINT8) ((FileSize & 0x0000FF00) >> 8);\r
2461 PadFile->Size[2] = (UINT8) ((FileSize & 0x00FF0000) >> 16);\r
2462\r
2463 //\r
2464 // Fill in checksums and state, must be zero during checksum calculation.\r
2465 //\r
2466 PadFile->IntegrityCheck.Checksum.Header = 0;\r
2467 PadFile->IntegrityCheck.Checksum.File = 0;\r
2468 PadFile->State = 0;\r
2469 PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER));\r
2470 if (PadFile->Attributes & FFS_ATTRIB_CHECKSUM) {\r
2471#if (PI_SPECIFICATION_VERSION < 0x00010000)\r
2472 PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) PadFile, FileSize);\r
2473#else\r
2474 PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) ((UINTN) PadFile + sizeof (EFI_FFS_FILE_HEADER)), FileSize - sizeof (EFI_FFS_FILE_HEADER));\r
2475#endif\r
2476 } else {\r
2477 PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
2478 }\r
2479\r
2480 PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;\r
2481\r
2482 UpdateFfsFileState (\r
2483 (EFI_FFS_FILE_HEADER *) PadFile,\r
2484 (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage\r
2485 );\r
2486 //\r
2487 // Update the current FV pointer\r
2488 //\r
2489 FvImage->CurrentFilePointer = FvImage->Eof;\r
2490\r
2491 return EFI_SUCCESS;\r
2492}\r
2493\r
2494EFI_STATUS\r
2495UpdateResetVector (\r
2496 IN MEMORY_FILE *FvImage,\r
2497 IN FV_INFO *FvInfo,\r
2498 IN EFI_FFS_FILE_HEADER *VtfFile\r
2499 )\r
2500/*++\r
2501\r
2502Routine Description:\r
2503\r
2504 This parses the FV looking for the PEI core and then plugs the address into\r
2505 the SALE_ENTRY point of the BSF/VTF for IPF and does BUGBUG TBD action to\r
2506 complete an IA32 Bootstrap FV.\r
2507\r
2508Arguments:\r
2509\r
2510 FvImage Memory file for the FV memory image\r
2511 FvInfo Information read from INF file.\r
2512 VtfFile Pointer to the VTF file in the FV image.\r
2513\r
2514Returns:\r
2515\r
2516 EFI_SUCCESS Function Completed successfully.\r
2517 EFI_ABORTED Error encountered.\r
2518 EFI_INVALID_PARAMETER A required parameter was NULL.\r
2519 EFI_NOT_FOUND PEI Core file not found.\r
2520\r
2521--*/\r
2522{\r
2523 EFI_FFS_FILE_HEADER *PeiCoreFile;\r
2524 EFI_FFS_FILE_HEADER *SecCoreFile;\r
2525 EFI_STATUS Status;\r
2526 EFI_FILE_SECTION_POINTER Pe32Section;\r
2527 UINT32 EntryPoint;\r
2528 UINT32 BaseOfCode;\r
2529 UINT16 MachineType;\r
2530 EFI_PHYSICAL_ADDRESS PeiCorePhysicalAddress;\r
2531 EFI_PHYSICAL_ADDRESS SecCorePhysicalAddress;\r
2532 EFI_PHYSICAL_ADDRESS *SecCoreEntryAddressPtr;\r
2533 UINT32 *Ia32ResetAddressPtr;\r
2534 UINT8 *BytePointer;\r
2535 UINT8 *BytePointer2;\r
2536 UINT16 *WordPointer;\r
2537 UINT16 CheckSum;\r
2538 UINTN Index;\r
2539 EFI_FFS_FILE_STATE SavedState;\r
2540 UINT32 TailSize;\r
2541 UINT64 FitAddress;\r
2542 FIT_TABLE *FitTablePtr;\r
2543#if (PI_SPECIFICATION_VERSION < 0x00010000)\r
2544 EFI_FFS_FILE_TAIL TailValue;\r
2545#endif\r
2546 //\r
2547 // Verify input parameters\r
2548 //\r
2549 if (FvImage == NULL || FvInfo == NULL || VtfFile == NULL) {\r
2550 return EFI_INVALID_PARAMETER;\r
2551 }\r
2552 //\r
2553 // Initialize FV library\r
2554 //\r
2555 InitializeFvLib (FvImage->FileImage, (UINTN) FvImage->Eof - (UINTN) FvImage->FileImage);\r
2556\r
2557 //\r
2558 // Verify VTF file\r
2559 //\r
2560 Status = VerifyFfsFile (VtfFile);\r
2561 if (EFI_ERROR (Status)) {\r
2562 return EFI_INVALID_PARAMETER;\r
2563 }\r
2564 //\r
2565 // Find the PEI Core\r
2566 //\r
2567 Status = GetFileByType (EFI_FV_FILETYPE_PEI_CORE, 1, &PeiCoreFile);\r
2568 if (EFI_ERROR (Status) || PeiCoreFile == NULL) {\r
2569 Error (NULL, 0, 0, "could not find the PEI core in the FV", NULL);\r
2570 return EFI_ABORTED;\r
2571 }\r
2572 //\r
2573 // PEI Core found, now find PE32 or TE section\r
2574 //\r
2575 Status = GetSectionByType (PeiCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);\r
2576 if (Status == EFI_NOT_FOUND) {\r
2577 Status = GetSectionByType (PeiCoreFile, EFI_SECTION_TE, 1, &Pe32Section);\r
2578 }\r
2579\r
2580 if (EFI_ERROR (Status)) {\r
2581 Error (NULL, 0, 0, "could not find PE32 or TE section in PEI core file", NULL);\r
2582 return EFI_ABORTED;\r
2583 }\r
2584\r
2585 Status = GetPe32Info (\r
2586 (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),\r
2587 &EntryPoint,\r
2588 &BaseOfCode,\r
2589 &MachineType\r
2590 );\r
2591\r
2592 if (EFI_ERROR (Status)) {\r
2593 Error (NULL, 0, 0, "could not get PE32 entry point for PEI core", NULL);\r
2594 return EFI_ABORTED;\r
2595 }\r
2596 //\r
2597 // Physical address is FV base + offset of PE32 + offset of the entry point\r
2598 //\r
2599 PeiCorePhysicalAddress = FvInfo->BaseAddress;\r
2600 PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;\r
2601 PeiCorePhysicalAddress += EntryPoint;\r
2602\r
2603 if (MachineType == EFI_IMAGE_MACHINE_IA64) {\r
2604 //\r
2605 // Update PEI_CORE address\r
2606 //\r
2607 //\r
2608 // Set the uncached attribute bit in the physical address\r
2609 //\r
2610 PeiCorePhysicalAddress |= 0x8000000000000000;\r
2611\r
2612 //\r
2613 // Check if address is aligned on a 16 byte boundary\r
2614 //\r
2615 if (PeiCorePhysicalAddress & 0xF) {\r
2616 printf (\r
2617 "ERROR: PEI_CORE entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n",\r
2618 PeiCorePhysicalAddress\r
2619 );\r
2620 return EFI_ABORTED;\r
2621 }\r
2622 //\r
2623 // First Get the FIT table address\r
2624 //\r
2625 FitAddress = (*(UINT64 *) (FvImage->Eof - IPF_FIT_ADDRESS_OFFSET)) & 0xFFFFFFFF;\r
2626\r
2627 FitTablePtr = (FIT_TABLE *) (FvImage->FileImage + (FitAddress - FvInfo->BaseAddress));\r
2628\r
2629 Status = UpdatePeiCoreEntryInFit (FitTablePtr, PeiCorePhysicalAddress);\r
2630\r
2631 if (!EFI_ERROR (Status)) {\r
2632 UpdateFitCheckSum (FitTablePtr);\r
2633 }\r
2634 //\r
2635 // Find the Sec Core\r
2636 //\r
2637 Status = GetFileByType (EFI_FV_FILETYPE_SECURITY_CORE, 1, &SecCoreFile);\r
2638 if (EFI_ERROR (Status) || SecCoreFile == NULL) {\r
2639 Error (NULL, 0, 0, "could not find the Sec core in the FV", NULL);\r
2640 return EFI_ABORTED;\r
2641 }\r
2642 //\r
2643 // Sec Core found, now find PE32 section\r
2644 //\r
2645 Status = GetSectionByType (SecCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);\r
2646 if (EFI_ERROR (Status)) {\r
2647 Error (NULL, 0, 0, "could not find PE32 section in SEC core file", NULL);\r
2648 return EFI_ABORTED;\r
2649 }\r
2650\r
2651 Status = GetPe32Info (\r
2652 (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),\r
2653 &EntryPoint,\r
2654 &BaseOfCode,\r
2655 &MachineType\r
2656 );\r
2657 if (EFI_ERROR (Status)) {\r
2658 Error (NULL, 0, 0, "could not get PE32 entry point for SEC core", NULL);\r
2659 return EFI_ABORTED;\r
2660 }\r
2661 //\r
2662 // Physical address is FV base + offset of PE32 + offset of the entry point\r
2663 //\r
2664 SecCorePhysicalAddress = FvInfo->BaseAddress;\r
2665 SecCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;\r
2666 SecCorePhysicalAddress += EntryPoint;\r
2667\r
2668 //\r
2669 // Update SEC_CORE address\r
2670 //\r
2671 //\r
2672 // Set the uncached attribute bit in the physical address\r
2673 //\r
2674 SecCorePhysicalAddress |= 0x8000000000000000;\r
2675\r
2676 //\r
2677 // Update the address\r
2678 //\r
2679 SecCoreEntryAddressPtr = (EFI_PHYSICAL_ADDRESS *) ((UINTN) FvImage->Eof - IPF_SALE_ENTRY_ADDRESS_OFFSET);\r
2680 *SecCoreEntryAddressPtr = SecCorePhysicalAddress;\r
2681\r
2682 //\r
2683 // Check if address is aligned on a 16 byte boundary\r
2684 //\r
2685 if (SecCorePhysicalAddress & 0xF) {\r
2686 printf (\r
2687 "ERROR: SALE_ENTRY entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n",\r
2688 SecCorePhysicalAddress\r
2689 );\r
2690 return EFI_ABORTED;\r
2691 }\r
2692 } else if ((MachineType == EFI_IMAGE_MACHINE_IA32) || \r
2693 (MachineType == EFI_IMAGE_MACHINE_X64)) {\r
2694 //\r
2695 // Get the location to update\r
2696 //\r
2697 Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - IA32_PEI_CORE_ENTRY_OFFSET);\r
2698\r
2699 //\r
2700 // Write lower 32 bits of physical address\r
2701 //\r
2702 *Ia32ResetAddressPtr = (UINT32) PeiCorePhysicalAddress;\r
2703\r
2704 //\r
2705 // Update the BFV base address\r
2706 //\r
2707 Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - 4);\r
2708 *Ia32ResetAddressPtr = (UINT32) (FvInfo->BaseAddress);\r
2709\r
2710 CheckSum = 0x0000;\r
2711\r
2712 //\r
2713 // Update the Startup AP in the FVH header block ZeroVector region.\r
2714 //\r
2715 BytePointer = (UINT8 *) ((UINTN) FvImage->FileImage);\r
2716 BytePointer2 = (FvInfo->Size == 0x10000) ? m64kRecoveryStartupApDataArray : m128kRecoveryStartupApDataArray;\r
2717 for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY; Index++) {\r
2718 *BytePointer++ = *BytePointer2++;\r
2719 }\r
2720 //\r
2721 // Calculate the checksum\r
2722 //\r
2723 WordPointer = (UINT16 *) ((UINTN) FvImage->FileImage);\r
2724 for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY / 2; Index++) {\r
2725 CheckSum = (UINT16) (CheckSum + ((UINT16) *WordPointer));\r
2726 WordPointer++;\r
2727 }\r
2728 //\r
2729 // Update the checksum field\r
2730 //\r
2731 BytePointer = (UINT8 *) ((UINTN) FvImage->FileImage);\r
2732 BytePointer += (SIZEOF_STARTUP_DATA_ARRAY - 2);\r
2733 WordPointer = (UINT16 *) BytePointer;\r
2734 *WordPointer = (UINT16) (0x10000 - (UINT32) CheckSum);\r
2735 } else {\r
2736 Error (NULL, 0, 0, "invalid machine type in PEI core", "machine type=0x%X", (UINT32) MachineType);\r
2737 return EFI_ABORTED;\r
2738 }\r
2739 //\r
2740 // Determine if it has an FFS file tail.\r
2741 //\r
2742 if (VtfFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {\r
2743 TailSize = sizeof (EFI_FFS_FILE_TAIL);\r
2744 } else {\r
2745 TailSize = 0;\r
2746 }\r
2747 //\r
2748 // Now update file checksum\r
2749 //\r
2750 SavedState = VtfFile->State;\r
2751 VtfFile->IntegrityCheck.Checksum.File = 0;\r
2752 VtfFile->State = 0;\r
2753 if (VtfFile->Attributes & FFS_ATTRIB_CHECKSUM) {\r
2754#if (PI_SPECIFICATION_VERSION < 0x00010000)\r
2755 VtfFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (\r
2756 (UINT8 *) VtfFile,\r
2757 GetLength (VtfFile->Size) - TailSize\r
2758 );\r
2759\r
2760#else\r
2761 VtfFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (\r
2762 (UINT8 *) ((UINTN)VtfFile + sizeof (EFI_FFS_FILE_HEADER)),\r
2763 GetLength (VtfFile->Size) - TailSize - sizeof (EFI_FFS_FILE_HEADER)\r
2764 );\r
2765#endif\r
2766 } else {\r
2767 VtfFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
2768 }\r
2769\r
2770 VtfFile->State = SavedState;\r
2771\r
2772#if (PI_SPECIFICATION_VERSION < 0x00010000)\r
2773 //\r
2774 // Update tail if present\r
2775 //\r
2776 if (VtfFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {\r
2777 TailValue = (EFI_FFS_FILE_TAIL) (~(VtfFile->IntegrityCheck.TailReference));\r
2778 *(EFI_FFS_FILE_TAIL *) (((UINTN) (VtfFile) + GetLength (VtfFile->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;\r
2779 }\r
2780#endif\r
2781 return EFI_SUCCESS;\r
2782}\r
2783\r
2784EFI_STATUS\r
2785GetPe32Info (\r
2786 IN UINT8 *Pe32,\r
2787 OUT UINT32 *EntryPoint,\r
2788 OUT UINT32 *BaseOfCode,\r
2789 OUT UINT16 *MachineType\r
2790 )\r
2791/*++\r
2792\r
2793Routine Description:\r
2794\r
2795 Retrieves the PE32 entry point offset and machine type from PE image or TE image.\r
2796 See EfiImage.h for machine types. The entry point offset is from the beginning\r
2797 of the PE32 buffer passed in.\r
2798\r
2799Arguments:\r
2800\r
2801 Pe32 Beginning of the PE32.\r
2802 EntryPoint Offset from the beginning of the PE32 to the image entry point.\r
2803 BaseOfCode Base address of code.\r
2804 MachineType Magic number for the machine type.\r
2805\r
2806Returns:\r
2807\r
2808 EFI_SUCCESS Function completed successfully.\r
2809 EFI_ABORTED Error encountered.\r
2810 EFI_INVALID_PARAMETER A required parameter was NULL.\r
2811 EFI_UNSUPPORTED The operation is unsupported.\r
2812\r
2813--*/\r
2814{\r
2815 EFI_IMAGE_DOS_HEADER *DosHeader;\r
2816 EFI_IMAGE_NT_HEADERS *NtHeader;\r
2817 EFI_TE_IMAGE_HEADER *TeHeader;\r
2818\r
2819 //\r
2820 // Verify input parameters\r
2821 //\r
2822 if (Pe32 == NULL) {\r
2823 return EFI_INVALID_PARAMETER;\r
2824 }\r
2825\r
2826 //\r
2827 // First check whether it is one TE Image.\r
2828 //\r
2829 TeHeader = (EFI_TE_IMAGE_HEADER *) Pe32;\r
2830 if (TeHeader->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
2831 //\r
2832 // By TeImage Header to get output\r
2833 //\r
2834 *EntryPoint = TeHeader->AddressOfEntryPoint + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader->StrippedSize;\r
2835 *BaseOfCode = TeHeader->BaseOfCode + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader->StrippedSize;\r
2836 *MachineType = TeHeader->Machine;\r
2837 } else {\r
2838 //\r
2839 // Then check whether\r
2840 // is the DOS header\r
2841 //\r
2842 DosHeader = (EFI_IMAGE_DOS_HEADER *) Pe32;\r
2843\r
2844 //\r
2845 // Verify DOS header is expected\r
2846 //\r
2847 if (DosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
2848 printf ("ERROR: Unknown magic number in the DOS header, 0x%04X.\n", DosHeader->e_magic);\r
2849 return EFI_UNSUPPORTED;\r
2850 }\r
2851 //\r
2852 // Immediately following is the NT header.\r
2853 //\r
2854 NtHeader = (EFI_IMAGE_NT_HEADERS *) ((UINTN) Pe32 + DosHeader->e_lfanew);\r
2855 \r
2856 //\r
2857 // Verify NT header is expected\r
2858 //\r
2859 if (NtHeader->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
2860 printf ("ERROR: Unrecognized image signature 0x%08X.\n", NtHeader->Signature);\r
2861 return EFI_UNSUPPORTED;\r
2862 }\r
2863 //\r
2864 // Get output\r
2865 //\r
2866 *EntryPoint = NtHeader->OptionalHeader.AddressOfEntryPoint;\r
2867 *BaseOfCode = NtHeader->OptionalHeader.BaseOfCode;\r
2868 *MachineType = NtHeader->FileHeader.Machine;\r
2869 }\r
2870\r
2871 //\r
2872 // Verify machine type is supported\r
2873 //\r
2874 if (*MachineType != EFI_IMAGE_MACHINE_IA32 && \r
2875 *MachineType != EFI_IMAGE_MACHINE_IA64 &&\r
2876 *MachineType != EFI_IMAGE_MACHINE_X64) {\r
2877 printf ("ERROR: Unrecognized machine type in the PE32 file.\n");\r
2878 return EFI_UNSUPPORTED;\r
2879 }\r
2880\r
2881 return EFI_SUCCESS;\r
2882}\r
2883//\r
2884// Exposed function implementations (prototypes are defined in GenFvImageLib.h)\r
2885//\r
2886EFI_STATUS\r
2887GenerateFvImage (\r
2888 IN CHAR8 *InfFileImage,\r
2889 IN UINTN InfFileSize,\r
2890 OUT UINT8 **FvImage,\r
2891 OUT UINTN *FvImageSize,\r
2892 OUT CHAR8 **FvFileName,\r
2893 OUT UINT8 **SymImage,\r
2894 OUT UINTN *SymImageSize,\r
2895 OUT CHAR8 **SymFileName\r
2896 )\r
2897/*++\r
2898\r
2899Routine Description:\r
2900\r
2901 This is the main function which will be called from application.\r
2902\r
2903Arguments:\r
2904\r
2905 InfFileImage Buffer containing the INF file contents.\r
2906 InfFileSize Size of the contents of the InfFileImage buffer.\r
2907 FvImage Pointer to the FV image created.\r
2908 FvImageSize Size of the FV image created and pointed to by FvImage.\r
2909 FvFileName Requested name for the FV file.\r
2910 SymImage Pointer to the Sym image created.\r
2911 SymImageSize Size of the Sym image created and pointed to by SymImage.\r
2912 SymFileName Requested name for the Sym file.\r
2913\r
2914Returns:\r
2915\r
2916 EFI_SUCCESS Function completed successfully.\r
2917 EFI_OUT_OF_RESOURCES Could not allocate required resources.\r
2918 EFI_ABORTED Error encountered.\r
2919 EFI_INVALID_PARAMETER A required parameter was NULL.\r
2920\r
2921--*/\r
2922{\r
2923 EFI_STATUS Status;\r
2924 MEMORY_FILE InfMemoryFile;\r
2925 MEMORY_FILE FvImageMemoryFile;\r
2926 MEMORY_FILE SymImageMemoryFile;\r
2927 FV_INFO FvInfo;\r
2928 UINTN Index;\r
2929 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;\r
2930 EFI_FFS_FILE_HEADER *VtfFileImage;\r
2931 UINTN FvImageCapacity;\r
2932\r
2933 //\r
2934 // Check for invalid parameter\r
2935 //\r
2936 if (InfFileImage == NULL || FvImage == NULL || FvImageSize == NULL || FvFileName == NULL) {\r
2937 return EFI_INVALID_PARAMETER;\r
2938 }\r
2939 //\r
2940 // Initialize file structures\r
2941 //\r
2942 InfMemoryFile.FileImage = InfFileImage;\r
2943 InfMemoryFile.CurrentFilePointer = InfFileImage;\r
2944 InfMemoryFile.Eof = InfFileImage + InfFileSize;\r
2945\r
2946 //\r
2947 // Parse the FV inf file for header information\r
2948 //\r
2949 Status = ParseFvInf (&InfMemoryFile, &FvInfo);\r
2950 if (EFI_ERROR (Status)) {\r
2951 printf ("ERROR: Could not parse the input INF file.\n");\r
2952 return EFI_ABORTED;\r
2953 }\r
2954 //\r
2955 // Update the file name return values\r
2956 //\r
2957 strcpy (*FvFileName, FvInfo.FvName);\r
2958 strcpy (*SymFileName, FvInfo.SymName);\r
2959\r
2960 //\r
2961 // Calculate the FV size\r
2962 //\r
2963 if (FvInfo.Size != (UINTN) -1) {\r
2964 *FvImageSize = FvInfo.Size;\r
2965 FvImageCapacity = FvInfo.Size;\r
2966 } else {\r
2967 //\r
2968 // For auto size, set default as one block\r
2969 //\r
2970 FvInfo.FvBlocks[0].NumBlocks = 1;\r
2971 *FvImageSize = FvInfo.FvBlocks[0].BlockLength;\r
2972 FvImageCapacity = FV_CAPACITY_INCREASE_UNIT;\r
2973 }\r
2974\r
2975 //\r
2976 // Allocate the FV\r
2977 //\r
2978 *FvImage = malloc (FvImageCapacity);\r
2979 if (*FvImage == NULL) {\r
2980 return EFI_OUT_OF_RESOURCES;\r
2981 }\r
2982 //\r
2983 // Allocate space for symbol file storage\r
2984 //\r
2985 *SymImage = malloc (SYMBOL_FILE_SIZE);\r
2986 if (*SymImage == NULL) {\r
2987 return EFI_OUT_OF_RESOURCES;\r
2988 }\r
2989 //\r
2990 // Initialize the FV to the erase polarity\r
2991 //\r
2992 if (FvInfo.FvAttributes & EFI_FVB_ERASE_POLARITY) {\r
2993 memset (*FvImage, -1, FvImageCapacity);\r
2994 } else {\r
2995 memset (*FvImage, 0, FvImageCapacity);\r
2996 }\r
2997 //\r
2998 // Initialize FV header\r
2999 //\r
3000 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) *FvImage;\r
3001\r
3002 //\r
3003 // Initialize the zero vector to all zeros.\r
3004 //\r
3005 memset (FvHeader->ZeroVector, 0, 16);\r
3006\r
3007 //\r
3008 // Copy the FFS GUID\r
3009 //\r
3010 memcpy (&FvHeader->FileSystemGuid, &FvInfo.FvGuid, sizeof (EFI_GUID));\r
3011\r
3012 FvHeader->FvLength = *FvImageSize;\r
3013 FvHeader->Signature = EFI_FVH_SIGNATURE;\r
3014 FvHeader->Attributes = FvInfo.FvAttributes;\r
3015#if (PI_SPECIFICATION_VERSION < 0x00010000)\r
3016 FvHeader->Revision = EFI_FVH_REVISION;\r
3017 FvHeader->Reserved[0] = 0;\r
3018 FvHeader->Reserved[1] = 0;\r
3019 FvHeader->Reserved[2] = 0;\r
3020#else\r
3021 FvHeader->Revision = EFI_FVH_PI_REVISION;\r
3022 FvHeader->ExtHeaderOffset = 0;\r
3023 FvHeader->Reserved[0] = 0;\r
3024#endif\r
3025 //\r
3026 // Copy firmware block map\r
3027 //\r
3028 for (Index = 0; FvInfo.FvBlocks[Index].NumBlocks != 0; Index++) {\r
3029 FvHeader->FvBlockMap[Index].NumBlocks = FvInfo.FvBlocks[Index].NumBlocks;\r
3030 FvHeader->FvBlockMap[Index].BlockLength = FvInfo.FvBlocks[Index].BlockLength;\r
3031 }\r
3032 //\r
3033 // Add block map terminator\r
3034 //\r
3035 FvHeader->FvBlockMap[Index].NumBlocks = 0;\r
3036 FvHeader->FvBlockMap[Index].BlockLength = 0;\r
3037\r
3038 //\r
3039 // Complete the header\r
3040 //\r
3041 FvHeader->HeaderLength = (UINT16) (((UINTN) &(FvHeader->FvBlockMap[Index + 1])) - (UINTN) *FvImage);\r
3042 FvHeader->Checksum = 0;\r
3043 FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));\r
3044\r
3045 //\r
3046 // If there is no FFS file, find and generate each components of the FV\r
3047 //\r
3048 if (FvInfo.FvFiles[0][0] == 0) {\r
3049 Status = GenNonFFSFv (*FvImage, &FvInfo);\r
3050 if (EFI_ERROR (Status)) {\r
3051 printf ("ERROR: Could not generate NonFFS FV.\n");\r
3052 free (*FvImage);\r
3053 return EFI_ABORTED;\r
3054 }\r
3055\r
3056 return EFI_SUCCESS;\r
3057 }\r
3058 //\r
3059 // Initialize our "file" view of the buffer\r
3060 //\r
3061 FvImageMemoryFile.FileImage = *FvImage;\r
3062 FvImageMemoryFile.CurrentFilePointer = *FvImage + FvHeader->HeaderLength;\r
3063 FvImageMemoryFile.Eof = *FvImage +*FvImageSize;\r
3064\r
3065 //\r
3066 // Initialize our "file" view of the symbol file.\r
3067 //\r
3068 SymImageMemoryFile.FileImage = *SymImage;\r
3069 SymImageMemoryFile.CurrentFilePointer = *SymImage;\r
3070 SymImageMemoryFile.Eof = *FvImage + SYMBOL_FILE_SIZE;\r
3071\r
3072 //\r
3073 // Initialize the FV library.\r
3074 //\r
3075 InitializeFvLib (FvImageMemoryFile.FileImage, *FvImageSize);\r
3076\r
3077 //\r
3078 // Files start on 8 byte alignments, so move to the next 8 byte aligned\r
3079 // address. For now, just assert if it isn't. Currently FV header is\r
3080 // always a multiple of 8 bytes.\r
3081 // BUGBUG: Handle this better\r
3082 //\r
3083 assert ((((UINTN) FvImageMemoryFile.CurrentFilePointer) % 8) == 0);\r
3084\r
3085 //\r
3086 // Initialize the VTF file address.\r
3087 //\r
3088 VtfFileImage = (EFI_FFS_FILE_HEADER *) FvImageMemoryFile.Eof;\r
3089\r
3090 //\r
3091 // Add files to FV\r
3092 //\r
3093 for (Index = 0; FvInfo.FvFiles[Index][0] != 0; Index++) {\r
3094 //\r
3095 // Add the file\r
3096 //\r
3097 Status = AddFile (&FvImageMemoryFile, &FvInfo, Index, &VtfFileImage, &SymImageMemoryFile, &FvImageCapacity);\r
3098\r
3099 //\r
3100 // Update FvImageSize and FvImage as they may be changed in AddFile routine\r
3101 //\r
3102 if (FvInfo.Size == (UINTN) -1) {\r
3103 *FvImageSize = FvInfo.FvBlocks[0].NumBlocks * FvInfo.FvBlocks[0].BlockLength;\r
3104 *FvImage = FvImageMemoryFile.FileImage;\r
3105 }\r
3106\r
3107 //\r
3108 // Exit if error detected while adding the file\r
3109 //\r
3110 if (EFI_ERROR (Status)) {\r
3111 printf ("ERROR: Could not add file %s.\n", FvInfo.FvFiles[Index]);\r
3112 free (*FvImage);\r
3113 return EFI_ABORTED;\r
3114 }\r
3115 }\r
3116 //\r
3117 // If there is a VTF file, some special actions need to occur.\r
3118 //\r
3119 if ((UINTN) VtfFileImage != (UINTN) FvImageMemoryFile.Eof) {\r
3120 //\r
3121 // Pad from the end of the last file to the beginning of the VTF file.\r
3122 //\r
3123 Status = PadFvImage (&FvImageMemoryFile, VtfFileImage);\r
3124 if (EFI_ERROR (Status)) {\r
3125 printf ("ERROR: Could not create the pad file between the last file and the VTF file.\n");\r
3126 free (*FvImage);\r
3127 return EFI_ABORTED;\r
3128 }\r
3129 //\r
3130 // Update reset vector (SALE_ENTRY for IPF)\r
3131 // Now for IA32 and IA64 platform, the fv which has bsf file must have the \r
3132 // EndAddress of 0xFFFFFFFF. Thus, only this type fv needs to update the \r
3133 // reset vector. If the PEI Core is found, the VTF file will probably get \r
3134 // corrupted by updating the entry point. \r
3135 //\r
3136 if ((FvInfo.BaseAddress + *FvImageSize) == FV_IMAGES_TOP_ADDRESS) { \r
3137 Status = UpdateResetVector (&FvImageMemoryFile, &FvInfo, VtfFileImage);\r
3138 if (EFI_ERROR(Status)) { \r
3139 printf ("ERROR: Could not update the reset vector.\n"); \r
3140 free (*FvImage); \r
3141 return EFI_ABORTED; \r
3142 } \r
3143 }\r
3144 }\r
3145 //\r
3146 // Determine final Sym file size\r
3147 //\r
3148 *SymImageSize = SymImageMemoryFile.CurrentFilePointer - SymImageMemoryFile.FileImage;\r
3149\r
3150 return EFI_SUCCESS;\r
3151}\r
3152\r
3153EFI_STATUS\r
3154UpdatePeiCoreEntryInFit (\r
3155 IN FIT_TABLE *FitTablePtr,\r
3156 IN UINT64 PeiCorePhysicalAddress\r
3157 )\r
3158/*++\r
3159\r
3160Routine Description:\r
3161\r
3162 This function is used to update the Pei Core address in FIT, this can be used by Sec core to pass control from\r
3163 Sec to Pei Core\r
3164\r
3165Arguments:\r
3166\r
3167 FitTablePtr - The pointer of FIT_TABLE.\r
3168 PeiCorePhysicalAddress - The address of Pei Core entry.\r
3169\r
3170Returns:\r
3171\r
3172 EFI_SUCCESS - The PEI_CORE FIT entry was updated successfully.\r
3173 EFI_NOT_FOUND - Not found the PEI_CORE FIT entry.\r
3174\r
3175--*/\r
3176{\r
3177 FIT_TABLE *TmpFitPtr;\r
3178 UINTN Index;\r
3179 UINTN NumFitComponents;\r
3180\r
3181 TmpFitPtr = FitTablePtr;\r
3182 NumFitComponents = TmpFitPtr->CompSize;\r
3183\r
3184 for (Index = 0; Index < NumFitComponents; Index++) {\r
3185 if ((TmpFitPtr->CvAndType & FIT_TYPE_MASK) == COMP_TYPE_FIT_PEICORE) {\r
3186 TmpFitPtr->CompAddress = PeiCorePhysicalAddress;\r
3187 return EFI_SUCCESS;\r
3188 }\r
3189\r
3190 TmpFitPtr++;\r
3191 }\r
3192\r
3193 return EFI_NOT_FOUND;\r
3194}\r
3195\r
3196VOID\r
3197UpdateFitCheckSum (\r
3198 IN FIT_TABLE *FitTablePtr\r
3199 )\r
3200/*++\r
3201\r
3202Routine Description:\r
3203\r
3204 This function is used to update the checksum for FIT.\r
3205\r
3206\r
3207Arguments:\r
3208\r
3209 FitTablePtr - The pointer of FIT_TABLE.\r
3210\r
3211Returns:\r
3212\r
3213 None.\r
3214\r
3215--*/\r
3216{\r
3217 if ((FitTablePtr->CvAndType & CHECKSUM_BIT_MASK) >> 7) {\r
3218 FitTablePtr->CheckSum = 0;\r
3219 FitTablePtr->CheckSum = CalculateChecksum8 ((UINT8 *) FitTablePtr, FitTablePtr->CompSize * 16);\r
3220 }\r
3221}\r