]> git.proxmox.com Git - mirror_edk2.git/blame - Tools/Source/TianoTools/GenFvImage/GenFvImageLib.c
Initial import.
[mirror_edk2.git] / Tools / Source / TianoTools / GenFvImage / GenFvImageLib.c
CommitLineData
878ddf1f 1/*++\r
2i\r
3\r
4Copyright (c) 2004, Intel Corporation \r
5All rights reserved. This program and the accompanying materials \r
6are licensed and made available under the terms and conditions of the BSD License \r
7which accompanies this distribution. The full text of the license may be found at \r
8http://opensource.org/licenses/bsd-license.php \r
9 \r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
12\r
13Module Name:\r
14\r
15 GenFvImageLib.c\r
16\r
17Abstract:\r
18\r
19 This file contains functions required to generate a Firmware Volume.\r
20\r
21--*/\r
22\r
23//\r
24// Include files\r
25//\r
26#define EFI_SPECIFICATION_VERSION 0x00020000\r
27#define EDK_RELEASE_VERSION 0x00020000\r
28#ifdef __GNUC__\r
29#include <uuid/uuid.h>\r
30#include <sys/stat.h>\r
31#endif\r
32#include <string.h>\r
33#ifndef __GNUC__\r
34#include <io.h>\r
35#endif\r
36#include <assert.h>\r
37#include <Dxe.h>\r
38#include <Library/PeCoffLib.h>\r
39#include "GenFvImageLib.h"\r
40#include "GenFvImageLibInternal.h"\r
41#include <CommonLib.h>\r
42#include <FirmwareVolumeImageFormat.h>\r
43#include <Crc32.h>\r
44#include <EfiUtilityMsgs.h>\r
45#include <FvLib.h>\r
46#include <EfiCompress.h>\r
47#include <Variable.h>\r
48#include <WinNtInclude.h>\r
49#include <WorkingBlockHeader.h>\r
50\r
51\r
52//\r
53// Local function prototypes\r
54//\r
55EFI_STATUS\r
56GetPe32Info (\r
57 IN UINT8 *Pe32,\r
58 OUT UINT32 *EntryPoint,\r
59 OUT UINT32 *BaseOfCode,\r
60 OUT UINT16 *MachineType\r
61 );\r
62\r
63//\r
64// Local function implementations.\r
65//\r
66EFI_GUID FfsGuid = EFI_FIRMWARE_FILE_SYSTEM_GUID;\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 // Read the alignment capabilities attribute\r
436 //\r
437 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_CAP_STRING, 0, Value);\r
438\r
439 if (Status == EFI_SUCCESS) {\r
440 //\r
441 // Update attribute\r
442 //\r
443 if (strcmp (Value, TRUE_STRING) == 0) {\r
444 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_CAP;\r
445 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
446 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
447 return EFI_ABORTED;\r
448 }\r
449 } else {\r
450 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_CAP_STRING, "value not specified");\r
451 return Status;\r
452 }\r
453 //\r
454 // Read the word alignment capability attribute\r
455 //\r
456 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_2_STRING, 0, Value);\r
457\r
458 if (Status == EFI_SUCCESS) {\r
459 //\r
460 // Update attribute\r
461 //\r
462 if (strcmp (Value, TRUE_STRING) == 0) {\r
463 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_2;\r
464 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
465 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
466 return EFI_ABORTED;\r
467 }\r
468 } else {\r
469 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2_STRING, "value not specified");\r
470 return Status;\r
471 }\r
472 //\r
473 // Read the dword alignment capability attribute\r
474 //\r
475 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_4_STRING, 0, Value);\r
476\r
477 if (Status == EFI_SUCCESS) {\r
478 //\r
479 // Update attribute\r
480 //\r
481 if (strcmp (Value, TRUE_STRING) == 0) {\r
482 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_4;\r
483 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
484 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
485 return EFI_ABORTED;\r
486 }\r
487 } else {\r
488 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4_STRING, "value not specified");\r
489 return Status;\r
490 }\r
491 //\r
492 // Read the word alignment capability attribute\r
493 //\r
494 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_8_STRING, 0, Value);\r
495\r
496 if (Status == EFI_SUCCESS) {\r
497 //\r
498 // Update attribute\r
499 //\r
500 if (strcmp (Value, TRUE_STRING) == 0) {\r
501 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_8;\r
502 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
503 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
504 return EFI_ABORTED;\r
505 }\r
506 } else {\r
507 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8_STRING, "value not specified");\r
508 return Status;\r
509 }\r
510 //\r
511 // Read the qword alignment capability attribute\r
512 //\r
513 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_16_STRING, 0, Value);\r
514\r
515 if (Status == EFI_SUCCESS) {\r
516 //\r
517 // Update attribute\r
518 //\r
519 if (strcmp (Value, TRUE_STRING) == 0) {\r
520 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_16;\r
521 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
522 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
523 return EFI_ABORTED;\r
524 }\r
525 } else {\r
526 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16_STRING, "value not specified");\r
527 return Status;\r
528 }\r
529 //\r
530 // Read the 32 byte alignment capability attribute\r
531 //\r
532 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_32_STRING, 0, Value);\r
533\r
534 if (Status == EFI_SUCCESS) {\r
535 //\r
536 // Update attribute\r
537 //\r
538 if (strcmp (Value, TRUE_STRING) == 0) {\r
539 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_32;\r
540 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
541 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
542 return EFI_ABORTED;\r
543 }\r
544 } else {\r
545 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32_STRING, "value not specified");\r
546 return Status;\r
547 }\r
548 //\r
549 // Read the 64 byte alignment capability attribute\r
550 //\r
551 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_64_STRING, 0, Value);\r
552\r
553 if (Status == EFI_SUCCESS) {\r
554 //\r
555 // Update attribute\r
556 //\r
557 if (strcmp (Value, TRUE_STRING) == 0) {\r
558 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_64;\r
559 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
560 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
561 return EFI_ABORTED;\r
562 }\r
563 } else {\r
564 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64_STRING, "value not specified");\r
565 return Status;\r
566 }\r
567 //\r
568 // Read the 128 byte alignment capability attribute\r
569 //\r
570 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_128_STRING, 0, Value);\r
571\r
572 if (Status == EFI_SUCCESS) {\r
573 //\r
574 // Update attribute\r
575 //\r
576 if (strcmp (Value, TRUE_STRING) == 0) {\r
577 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_128;\r
578 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
579 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_128_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
580 return EFI_ABORTED;\r
581 }\r
582 } else {\r
583 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_128_STRING, "value not specified");\r
584 return Status;\r
585 }\r
586 //\r
587 // Read the 256 byte alignment capability attribute\r
588 //\r
589 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_256_STRING, 0, Value);\r
590\r
591 if (Status == EFI_SUCCESS) {\r
592 //\r
593 // Update attribute\r
594 //\r
595 if (strcmp (Value, TRUE_STRING) == 0) {\r
596 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_256;\r
597 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
598 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_256_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
599 return EFI_ABORTED;\r
600 }\r
601 } else {\r
602 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_256_STRING, "value not specified");\r
603 return Status;\r
604 }\r
605 //\r
606 // Read the 512 byte alignment capability attribute\r
607 //\r
608 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_512_STRING, 0, Value);\r
609\r
610 if (Status == EFI_SUCCESS) {\r
611 //\r
612 // Update attribute\r
613 //\r
614 if (strcmp (Value, TRUE_STRING) == 0) {\r
615 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_512;\r
616 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
617 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_512_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
618 return EFI_ABORTED;\r
619 }\r
620 } else {\r
621 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_512_STRING, "value not specified");\r
622 return Status;\r
623 }\r
624 //\r
625 // Read the 1K byte alignment capability attribute\r
626 //\r
627 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_1K_STRING, 0, Value);\r
628\r
629 if (Status == EFI_SUCCESS) {\r
630 //\r
631 // Update attribute\r
632 //\r
633 if (strcmp (Value, TRUE_STRING) == 0) {\r
634 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_1K;\r
635 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
636 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_1K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
637 return EFI_ABORTED;\r
638 }\r
639 } else {\r
640 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_1K_STRING, "value not specified");\r
641 return Status;\r
642 }\r
643 //\r
644 // Read the 2K byte alignment capability attribute\r
645 //\r
646 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_2K_STRING, 0, Value);\r
647\r
648 if (Status == EFI_SUCCESS) {\r
649 //\r
650 // Update attribute\r
651 //\r
652 if (strcmp (Value, TRUE_STRING) == 0) {\r
653 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_2K;\r
654 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
655 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
656 return EFI_ABORTED;\r
657 }\r
658 } else {\r
659 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2K_STRING, "value not specified");\r
660 return Status;\r
661 }\r
662 //\r
663 // Read the 4K byte alignment capability attribute\r
664 //\r
665 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_4K_STRING, 0, Value);\r
666\r
667 if (Status == EFI_SUCCESS) {\r
668 //\r
669 // Update attribute\r
670 //\r
671 if (strcmp (Value, TRUE_STRING) == 0) {\r
672 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_4K;\r
673 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
674 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
675 return EFI_ABORTED;\r
676 }\r
677 } else {\r
678 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4K_STRING, "value not specified");\r
679 return Status;\r
680 }\r
681 //\r
682 // Read the 8K byte alignment capability attribute\r
683 //\r
684 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_8K_STRING, 0, Value);\r
685\r
686 if (Status == EFI_SUCCESS) {\r
687 //\r
688 // Update attribute\r
689 //\r
690 if (strcmp (Value, TRUE_STRING) == 0) {\r
691 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_8K;\r
692 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
693 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
694 return EFI_ABORTED;\r
695 }\r
696 } else {\r
697 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8K_STRING, "value not specified");\r
698 return Status;\r
699 }\r
700 //\r
701 // Read the 16K byte alignment capability attribute\r
702 //\r
703 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_16K_STRING, 0, Value);\r
704\r
705 if (Status == EFI_SUCCESS) {\r
706 //\r
707 // Update attribute\r
708 //\r
709 if (strcmp (Value, TRUE_STRING) == 0) {\r
710 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_16K;\r
711 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
712 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
713 return EFI_ABORTED;\r
714 }\r
715 } else {\r
716 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16K_STRING, "value not specified");\r
717 return Status;\r
718 }\r
719 //\r
720 // Read the 32K byte alignment capability attribute\r
721 //\r
722 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_32K_STRING, 0, Value);\r
723\r
724 if (Status == EFI_SUCCESS) {\r
725 //\r
726 // Update attribute\r
727 //\r
728 if (strcmp (Value, TRUE_STRING) == 0) {\r
729 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_32K;\r
730 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
731 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
732 return EFI_ABORTED;\r
733 }\r
734 } else {\r
735 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32K_STRING, "value not specified");\r
736 return Status;\r
737 }\r
738 //\r
739 // Read the 64K byte alignment capability attribute\r
740 //\r
741 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_64K_STRING, 0, Value);\r
742\r
743 if (Status == EFI_SUCCESS) {\r
744 //\r
745 // Update attribute\r
746 //\r
747 if (strcmp (Value, TRUE_STRING) == 0) {\r
748 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_64K;\r
749 } else if (strcmp (Value, FALSE_STRING) != 0) {\r
750 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
751 return EFI_ABORTED;\r
752 }\r
753 } else {\r
754 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64K_STRING, "value not specified");\r
755 return Status;\r
756 }\r
757\r
758 if (!(FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_CAP) &&\r
759 (\r
760 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_2) ||\r
761 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_4) ||\r
762 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_8) ||\r
763 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_16) ||\r
764 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_32) ||\r
765 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_64) ||\r
766 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_128) ||\r
767 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_256) ||\r
768 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_512) ||\r
769 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_1K) ||\r
770 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_2K) ||\r
771 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_4K) ||\r
772 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_8K) ||\r
773 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_16K) ||\r
774 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_32K) ||\r
775 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_64K)\r
776 )\r
777 ) {\r
778 Error (\r
779 NULL,\r
780 0,\r
781 0,\r
782 "illegal combination of alignment attributes",\r
783 "if %s is not %s, no individual alignments can be %s",\r
784 EFI_FVB_ALIGNMENT_CAP_STRING,\r
785 TRUE_STRING,\r
786 TRUE_STRING\r
787 );\r
788 return EFI_ABORTED;\r
789 }\r
790 //\r
791 // Read block maps\r
792 //\r
793 for (Index = 0; Index < MAX_NUMBER_OF_FV_BLOCKS; Index++) {\r
794 //\r
795 // Read the number of blocks\r
796 //\r
797 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_NUM_BLOCKS_STRING, Index, Value);\r
798\r
799 if (Status == EFI_SUCCESS) {\r
800 //\r
801 // Update the number of blocks\r
802 //\r
803 Status = AsciiStringToUint64 (Value, FALSE, &Value64);\r
804 if (EFI_ERROR (Status)) {\r
805 Error (NULL, 0, 0, Value, "invalid value for %s", EFI_NUM_BLOCKS_STRING);\r
806 return EFI_ABORTED;\r
807 }\r
808\r
809 FvInfo->FvBlocks[Index].NumBlocks = (UINT32) Value64;\r
810 } else {\r
811 //\r
812 // If there is no number of blocks, but there is a size, then we have a mismatched pair\r
813 // and should return an error.\r
814 //\r
815 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_BLOCK_SIZE_STRING, Index, Value);\r
816 if (!EFI_ERROR (Status)) {\r
817 Error (NULL, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING);\r
818 return EFI_ABORTED;\r
819 } else {\r
820 //\r
821 // We are done\r
822 //\r
823 break;\r
824 }\r
825 }\r
826 //\r
827 // Read the size of blocks\r
828 //\r
829 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_BLOCK_SIZE_STRING, Index, Value);\r
830\r
831 if (Status == EFI_SUCCESS) {\r
832 //\r
833 // Update the number of blocks\r
834 //\r
835 Status = AsciiStringToUint64 (Value, FALSE, &Value64);\r
836 if (EFI_ERROR (Status)) {\r
837 Error (NULL, 0, 0, Value, "invalid value specified for %s", EFI_BLOCK_SIZE_STRING);\r
838 return EFI_ABORTED;\r
839 }\r
840\r
841 FvInfo->FvBlocks[Index].BlockLength = (UINT32) Value64;\r
842 } else {\r
843 //\r
844 // There is a number of blocks, but there is no size, so we have a mismatched pair\r
845 // and should return an error.\r
846 //\r
847 Error (NULL, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING);\r
848 return EFI_ABORTED;\r
849 }\r
850 }\r
851 //\r
852 // Read files\r
853 //\r
854 for (Index = 0; Index < MAX_NUMBER_OF_FILES_IN_FV; Index++) {\r
855 //\r
856 // Read the number of blocks\r
857 //\r
858 Status = FindToken (InfFile, FILES_SECTION_STRING, EFI_FILE_NAME_STRING, Index, Value);\r
859\r
860 if (Status == EFI_SUCCESS) {\r
861 //\r
862 // Add the file\r
863 //\r
864 strcpy (FvInfo->FvFiles[Index], Value);\r
865 } else {\r
866 break;\r
867 }\r
868 }\r
869\r
870 if (FindSection (InfFile, COMPONENT_SECTION_STRING)) {\r
871 Index = 0;\r
872 //\r
873 // Read component FV_VARIABLE\r
874 //\r
875 Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_VARIABLE_STRING, 0, Value);\r
876\r
877 if (Status == EFI_SUCCESS) {\r
878 //\r
879 // Add the component\r
880 //\r
881 strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_VARIABLE_STRING);\r
882 Status = AsciiStringToUint64 (Value, FALSE, &Value64);\r
883 if (EFI_ERROR (Status)) {\r
884 printf ("ERROR: %s is not a valid integer.\n", EFI_NV_VARIABLE_STRING);\r
885 return EFI_ABORTED;\r
886 }\r
887\r
888 FvInfo->FvComponents[Index].Size = (UINTN) Value64;\r
889 } else {\r
890 printf ("WARNING: Could not read %s.\n", EFI_NV_VARIABLE_STRING);\r
891 }\r
892\r
893 Index++;\r
894 //\r
895 // Read component FV_EVENT_LOG\r
896 //\r
897 Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_EVENT_LOG_STRING, 0, Value);\r
898\r
899 if (Status == EFI_SUCCESS) {\r
900 //\r
901 // Add the component\r
902 //\r
903 strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_EVENT_LOG_STRING);\r
904 Status = AsciiStringToUint64 (Value, FALSE, &Value64);\r
905 if (EFI_ERROR (Status)) {\r
906 printf ("ERROR: %s is not a valid integer.\n", EFI_NV_EVENT_LOG_STRING);\r
907 return EFI_ABORTED;\r
908 }\r
909\r
910 FvInfo->FvComponents[Index].Size = (UINTN) Value64;\r
911 } else {\r
912 printf ("WARNING: Could not read %s.\n", EFI_NV_EVENT_LOG_STRING);\r
913 }\r
914\r
915 Index++;\r
916 //\r
917 // Read component FV_FTW_WORKING\r
918 //\r
919 Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_FTW_WORKING_STRING, 0, Value);\r
920\r
921 if (Status == EFI_SUCCESS) {\r
922 //\r
923 // Add the component\r
924 //\r
925 strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_WORKING_STRING);\r
926 Status = AsciiStringToUint64 (Value, FALSE, &Value64);\r
927 if (EFI_ERROR (Status)) {\r
928 printf ("ERROR: %s is not a valid integer.\n", EFI_NV_FTW_WORKING_STRING);\r
929 return EFI_ABORTED;\r
930 }\r
931\r
932 FvInfo->FvComponents[Index].Size = (UINTN) Value64;\r
933 } else {\r
934 printf ("WARNING: Could not read %s.\n", EFI_NV_FTW_WORKING_STRING);\r
935 }\r
936\r
937 Index++;\r
938 //\r
939 // Read component FV_FTW_SPARE\r
940 //\r
941 Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_FTW_SPARE_STRING, 0, Value);\r
942\r
943 if (Status == EFI_SUCCESS) {\r
944 //\r
945 // Add the component\r
946 //\r
947 strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_SPARE_STRING);\r
948 Status = AsciiStringToUint64 (Value, FALSE, &Value64);\r
949 if (EFI_ERROR (Status)) {\r
950 printf ("ERROR: %s is not a valid integer.\n", EFI_NV_FTW_SPARE_STRING);\r
951 return EFI_ABORTED;\r
952 }\r
953\r
954 FvInfo->FvComponents[Index].Size = (UINTN) Value64;\r
955 } else {\r
956 printf ("WARNING: Could not read %s.\n", EFI_NV_FTW_SPARE_STRING);\r
957 }\r
958 }\r
959 //\r
960 // Compute size for easy access later\r
961 //\r
962 FvInfo->Size = 0;\r
963 for (Index = 0; FvInfo->FvBlocks[Index].NumBlocks; Index++) {\r
964 FvInfo->Size += FvInfo->FvBlocks[Index].NumBlocks * FvInfo->FvBlocks[Index].BlockLength;\r
965 }\r
966\r
967 return EFI_SUCCESS;\r
968}\r
969\r
970VOID\r
971UpdateFfsFileState (\r
972 IN EFI_FFS_FILE_HEADER *FfsFile,\r
973 IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader\r
974 )\r
975/*++\r
976\r
977Routine Description:\r
978\r
979 This function changes the FFS file attributes based on the erase polarity\r
980 of the FV.\r
981\r
982Arguments:\r
983\r
984 FfsFile File header.\r
985 FvHeader FV header.\r
986\r
987Returns:\r
988\r
989 None\r
990\r
991--*/\r
992{\r
993 if (FvHeader->Attributes & EFI_FVB_ERASE_POLARITY) {\r
994 FfsFile->State = (UINT8)~(FfsFile->State);\r
995 }\r
996}\r
997\r
998EFI_STATUS\r
999ReadFfsAlignment (\r
1000 IN EFI_FFS_FILE_HEADER *FfsFile,\r
1001 IN OUT UINT32 *Alignment\r
1002 )\r
1003/*++\r
1004\r
1005Routine Description:\r
1006\r
1007 This function determines the alignment of the FFS input file from the file\r
1008 attributes.\r
1009\r
1010Arguments:\r
1011\r
1012 FfsFile FFS file to parse\r
1013 Alignment The minimum required alignment of the FFS file, in bytes\r
1014\r
1015Returns:\r
1016\r
1017 EFI_SUCCESS The function completed successfully.\r
1018 EFI_INVALID_PARAMETER One of the input parameters was invalid.\r
1019 EFI_ABORTED An error occurred.\r
1020\r
1021--*/\r
1022{\r
1023 //\r
1024 // Verify input parameters.\r
1025 //\r
1026 if (FfsFile == NULL || Alignment == NULL) {\r
1027 return EFI_INVALID_PARAMETER;\r
1028 }\r
1029\r
1030 switch ((FfsFile->Attributes >> 3) & 0x07) {\r
1031\r
1032 case 0:\r
1033 //\r
1034 // 1 byte alignment\r
1035 //\r
1036 *Alignment = (1 << 0);\r
1037 break;\r
1038\r
1039 case 1:\r
1040 //\r
1041 // 16 byte alignment\r
1042 //\r
1043 *Alignment = (1 << 4);\r
1044 break;\r
1045\r
1046 case 2:\r
1047 //\r
1048 // 128 byte alignment\r
1049 //\r
1050 *Alignment = (1 << 7);\r
1051 break;\r
1052\r
1053 case 3:\r
1054 //\r
1055 // 512 byte alignment\r
1056 //\r
1057 *Alignment = (1 << 9);\r
1058 break;\r
1059\r
1060 case 4:\r
1061 //\r
1062 // 1K byte alignment\r
1063 //\r
1064 *Alignment = (1 << 10);\r
1065 break;\r
1066\r
1067 case 5:\r
1068 //\r
1069 // 4K byte alignment\r
1070 //\r
1071 *Alignment = (1 << 12);\r
1072 break;\r
1073\r
1074 case 6:\r
1075 //\r
1076 // 32K byte alignment\r
1077 //\r
1078 *Alignment = (1 << 15);\r
1079 break;\r
1080\r
1081 case 7:\r
1082 //\r
1083 // 64K byte alignment\r
1084 //\r
1085 *Alignment = (1 << 16);\r
1086 break;\r
1087\r
1088 default:\r
1089 Error (NULL, 0, 0, "nvalid file attribute calculated, this is most likely a utility error", NULL);\r
1090 return EFI_ABORTED;\r
1091 }\r
1092\r
1093 return EFI_SUCCESS;\r
1094}\r
1095\r
1096EFI_STATUS\r
1097AddPadFile (\r
1098 IN OUT MEMORY_FILE *FvImage,\r
1099 IN UINT32 DataAlignment\r
1100 )\r
1101/*++\r
1102\r
1103Routine Description:\r
1104\r
1105 This function adds a pad file to the FV image if it required to align the\r
1106 data of the next file.\r
1107\r
1108Arguments:\r
1109\r
1110 FvImage The memory image of the FV to add it to. The current offset\r
1111 must be valid.\r
1112 DataAlignment The data alignment of the next FFS file.\r
1113\r
1114Returns:\r
1115\r
1116 EFI_SUCCESS The function completed successfully.\r
1117 EFI_INVALID_PARAMETER One of the input parameters was invalid.\r
1118 EFI_OUT_OF_RESOURCES Insufficient resources exist in the FV to complete\r
1119 the pad file add.\r
1120\r
1121--*/\r
1122{\r
1123 EFI_FFS_FILE_HEADER *PadFile;\r
1124 EFI_GUID PadFileGuid;\r
1125 UINTN PadFileSize;\r
1126\r
1127 //\r
1128 // Verify input parameters.\r
1129 //\r
1130 if (FvImage == NULL) {\r
1131 return EFI_INVALID_PARAMETER;\r
1132 }\r
1133 //\r
1134 // Basic assumption is we start from an 8 byte aligned address\r
1135 // and our file header is a multiple of 8 bytes\r
1136 //\r
1137 assert ((UINTN) FvImage->CurrentFilePointer % 8 == 0);\r
1138 assert (sizeof (EFI_FFS_FILE_HEADER) % 8 == 0);\r
1139\r
1140 //\r
1141 // Check if a pad file is necessary\r
1142 //\r
1143 if (((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + sizeof (EFI_FFS_FILE_HEADER)) % DataAlignment == 0) {\r
1144 return EFI_SUCCESS;\r
1145 }\r
1146 //\r
1147 // Write pad file header\r
1148 //\r
1149 PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer;\r
1150\r
1151 //\r
1152 // Verify that we have enough space for the file header\r
1153 //\r
1154 if ((UINTN) (PadFile + sizeof (EFI_FFS_FILE_HEADER)) >= (UINTN) FvImage->Eof) {\r
1155 return EFI_OUT_OF_RESOURCES;\r
1156 }\r
1157\r
1158#ifdef __GNUC__\r
1159 {\r
1160 uuid_t tmp_id;\r
1161 uuid_generate (tmp_id);\r
1162 memcpy (&PadFileGuid, tmp_id, sizeof (EFI_GUID));\r
1163 }\r
1164#else\r
1165 UuidCreate (&PadFileGuid);\r
1166#endif\r
1167 memset (PadFile, 0, sizeof (EFI_FFS_FILE_HEADER));\r
1168 memcpy (&PadFile->Name, &PadFileGuid, sizeof (EFI_GUID));\r
1169 PadFile->Type = EFI_FV_FILETYPE_FFS_PAD;\r
1170 PadFile->Attributes = 0;\r
1171\r
1172 //\r
1173 // Calculate the pad file size\r
1174 //\r
1175 //\r
1176 // This is the earliest possible valid offset (current plus pad file header\r
1177 // plus the next file header)\r
1178 //\r
1179 PadFileSize = (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + (sizeof (EFI_FFS_FILE_HEADER) * 2);\r
1180\r
1181 //\r
1182 // Add whatever it takes to get to the next aligned address\r
1183 //\r
1184 while ((PadFileSize % DataAlignment) != 0) {\r
1185 PadFileSize++;\r
1186 }\r
1187 //\r
1188 // Subtract the next file header size\r
1189 //\r
1190 PadFileSize -= sizeof (EFI_FFS_FILE_HEADER);\r
1191\r
1192 //\r
1193 // Subtract the starting offset to get size\r
1194 //\r
1195 PadFileSize -= (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage;\r
1196\r
1197 //\r
1198 // Write pad file size (calculated size minus next file header size)\r
1199 //\r
1200 PadFile->Size[0] = (UINT8) (PadFileSize & 0xFF);\r
1201 PadFile->Size[1] = (UINT8) ((PadFileSize >> 8) & 0xFF);\r
1202 PadFile->Size[2] = (UINT8) ((PadFileSize >> 16) & 0xFF);\r
1203\r
1204 //\r
1205 // Fill in checksums and state, they must be 0 for checksumming.\r
1206 //\r
1207 PadFile->IntegrityCheck.Checksum.Header = 0;\r
1208 PadFile->IntegrityCheck.Checksum.File = 0;\r
1209 PadFile->State = 0;\r
1210 PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER));\r
1211 if (PadFile->Attributes & FFS_ATTRIB_CHECKSUM) {\r
1212 PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) PadFile, PadFileSize);\r
1213 } else {\r
1214 PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
1215 }\r
1216\r
1217 PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;\r
1218 UpdateFfsFileState (\r
1219 (EFI_FFS_FILE_HEADER *) PadFile,\r
1220 (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage\r
1221 );\r
1222\r
1223 //\r
1224 // Verify that we have enough space (including the padding\r
1225 //\r
1226 if ((UINTN) (PadFile + sizeof (EFI_FFS_FILE_HEADER)) >= (UINTN) FvImage->Eof) {\r
1227 return EFI_OUT_OF_RESOURCES;\r
1228 }\r
1229 //\r
1230 // Update the current FV pointer\r
1231 //\r
1232 FvImage->CurrentFilePointer += PadFileSize;\r
1233\r
1234 return EFI_SUCCESS;\r
1235}\r
1236\r
1237BOOLEAN\r
1238IsVtfFile (\r
1239 IN EFI_FFS_FILE_HEADER *FileBuffer\r
1240 )\r
1241/*++\r
1242\r
1243Routine Description:\r
1244\r
1245 This function checks the header to validate if it is a VTF file\r
1246\r
1247Arguments:\r
1248\r
1249 FileBuffer Buffer in which content of a file has been read.\r
1250\r
1251Returns:\r
1252\r
1253 TRUE If this is a VTF file\r
1254 FALSE If this is not a VTF file\r
1255\r
1256--*/\r
1257{\r
1258 EFI_GUID VtfGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;\r
1259 if (!memcmp (&FileBuffer->Name, &VtfGuid, sizeof (EFI_GUID))) {\r
1260 return TRUE;\r
1261 } else {\r
1262 return FALSE;\r
1263 }\r
1264}\r
1265\r
1266EFI_STATUS\r
1267FfsRebaseImageRead (\r
1268 IN VOID *FileHandle,\r
1269 IN UINTN FileOffset,\r
1270 IN OUT UINT32 *ReadSize,\r
1271 OUT VOID *Buffer\r
1272 )\r
1273/*++\r
1274\r
1275Routine Description:\r
1276\r
1277 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file\r
1278\r
1279Arguments:\r
1280\r
1281 FileHandle - The handle to the PE/COFF file\r
1282\r
1283 FileOffset - The offset, in bytes, into the file to read\r
1284\r
1285 ReadSize - The number of bytes to read from the file starting at FileOffset\r
1286\r
1287 Buffer - A pointer to the buffer to read the data into.\r
1288\r
1289Returns:\r
1290\r
1291 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset\r
1292\r
1293--*/\r
1294{\r
1295 CHAR8 *Destination8;\r
1296 CHAR8 *Source8;\r
1297 UINT32 Length;\r
1298\r
1299 Destination8 = Buffer;\r
1300 Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);\r
1301 Length = *ReadSize;\r
1302 while (Length--) {\r
1303 *(Destination8++) = *(Source8++);\r
1304 }\r
1305\r
1306 return EFI_SUCCESS;\r
1307}\r
1308\r
1309EFI_STATUS\r
1310RebaseFfsFile (\r
1311 IN OUT EFI_FFS_FILE_HEADER *FfsFile,\r
1312 IN EFI_PHYSICAL_ADDRESS BaseAddress\r
1313 )\r
1314/*++\r
1315\r
1316Routine Description:\r
1317\r
1318 This function determines if a file is XIP and should be rebased. It will\r
1319 rebase any PE32 sections found in the file using the base address.\r
1320\r
1321Arguments:\r
1322\r
1323 FfsFile A pointer to Ffs file image.\r
1324 BaseAddress The base address to use for rebasing the file image.\r
1325\r
1326Returns:\r
1327\r
1328 EFI_SUCCESS The image was properly rebased.\r
1329 EFI_INVALID_PARAMETER An input parameter is invalid.\r
1330 EFI_ABORTED An error occurred while rebasing the input file image.\r
1331 EFI_OUT_OF_RESOURCES Could not allocate a required resource.\r
1332\r
1333--*/\r
1334{\r
1335 EFI_STATUS Status;\r
1336 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
1337 UINTN MemoryImagePointer;\r
1338 UINTN MemoryImagePointerAligned;\r
1339\r
1340 EFI_PHYSICAL_ADDRESS ImageAddress;\r
1341 UINT64 ImageSize;\r
1342 EFI_PHYSICAL_ADDRESS EntryPoint;\r
1343\r
1344 UINT32 Pe32FileSize;\r
1345 UINT32 NewPe32BaseAddress;\r
1346\r
1347 UINTN Index;\r
1348 EFI_FILE_SECTION_POINTER CurrentPe32Section;\r
1349 UINT8 FileGuidString[80];\r
1350\r
1351 //\r
1352 // Verify input parameters\r
1353 //\r
1354 if (FfsFile == NULL) {\r
1355 return EFI_INVALID_PARAMETER;\r
1356 }\r
1357 //\r
1358 // Convert the GUID to a string so we can at least report which file\r
1359 // if we find an error.\r
1360 //\r
1361 PrintGuidToBuffer (&FfsFile->Name, FileGuidString, sizeof (FileGuidString), TRUE);\r
1362\r
1363 //\r
1364 // Do some nominal checks on the file, then check for XIP.\r
1365 //\r
1366 Status = VerifyFfsFile (FfsFile);\r
1367 if (EFI_ERROR (Status)) {\r
1368 Error (NULL, 0, 0, "invalid FFS file", FileGuidString);\r
1369 return EFI_INVALID_PARAMETER;\r
1370 }\r
1371\r
1372 if (FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE &&\r
1373 FfsFile->Type != EFI_FV_FILETYPE_PEI_CORE &&\r
1374 FfsFile->Type != EFI_FV_FILETYPE_PEIM\r
1375 ) {\r
1376 //\r
1377 // File is not XIP, so don't rebase\r
1378 //\r
1379 return EFI_SUCCESS;\r
1380 }\r
1381 //\r
1382 // Rebase each PE32 section\r
1383 //\r
1384 for (Index = 1;; Index++) {\r
1385 Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, Index, &CurrentPe32Section);\r
1386 if (EFI_ERROR (Status)) {\r
1387 break;\r
1388 }\r
1389 //\r
1390 // Calculate the PE32 base address, the FFS file base plus the offset of the PE32 section\r
1391 //\r
1392 NewPe32BaseAddress = ((UINT32) BaseAddress) + ((UINTN) CurrentPe32Section.Pe32Section - (UINTN) FfsFile);\r
1393\r
1394 //\r
1395 // Initialize context\r
1396 //\r
1397 memset (&ImageContext, 0, sizeof (ImageContext));\r
1398 ImageContext.Handle = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION));\r
1399 ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;\r
1400\r
1401 Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
1402\r
1403 if (EFI_ERROR (Status)) {\r
1404 Error (NULL, 0, 0, "GetImageInfo() failed", FileGuidString);\r
1405 return Status;\r
1406 }\r
1407 //\r
1408 // Allocate a buffer for the image to be loaded into.\r
1409 //\r
1410 Pe32FileSize = GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size);\r
1411 MemoryImagePointer = (UINTN) (malloc (Pe32FileSize + 0x1000));\r
1412 MemoryImagePointerAligned = (MemoryImagePointer + 0x0FFF) & (-1 << 12);\r
1413 if (MemoryImagePointerAligned == 0) {\r
1414 Error (NULL, 0, 0, "memory allocation failure", NULL);\r
1415 return EFI_OUT_OF_RESOURCES;\r
1416 }\r
1417\r
1418 //\r
1419 // bugbug\r
1420 //\r
1421 ImageContext.ImageAddress = MemoryImagePointerAligned;\r
1422 Status = PeCoffLoaderLoadImage (&ImageContext);\r
1423 if (EFI_ERROR (Status)) {\r
1424 Error (NULL, 0, 0, "LoadImage() failure", FileGuidString);\r
1425 free ((VOID *) MemoryImagePointer);\r
1426 return Status;\r
1427 }\r
1428\r
1429 Status = PeCoffLoaderRelocateImage (&ImageContext);\r
1430 if (EFI_ERROR (Status)) {\r
1431 Error (NULL, 0, 0, "RelocateImage() failure", FileGuidString);\r
1432 free ((VOID *) MemoryImagePointer);\r
1433 return Status;\r
1434 }\r
1435\r
1436 ImageAddress = ImageContext.ImageAddress;\r
1437 ImageSize = ImageContext.ImageSize;\r
1438 EntryPoint = ImageContext.EntryPoint;\r
1439\r
1440 if (ImageSize > Pe32FileSize) {\r
1441 Error (\r
1442 NULL,\r
1443 0,\r
1444 0,\r
1445 "rebased PE32 is larger than original PE32 image",\r
1446 "0x%X > 0x%X on file %s",\r
1447 ImageSize,\r
1448 Pe32FileSize,\r
1449 FileGuidString\r
1450 );\r
1451 free ((VOID *) MemoryImagePointer);\r
1452 return EFI_ABORTED;\r
1453 }\r
1454\r
1455 memcpy (CurrentPe32Section.Pe32Section, (VOID *) MemoryImagePointerAligned, Pe32FileSize);\r
1456\r
1457 free ((VOID *) MemoryImagePointer);\r
1458 }\r
1459 //\r
1460 // the above for loop will always exit with EFI_NOT_FOUND if it completes\r
1461 // normally. If Index == 1 at exit, then no PE32 sections were found. If it\r
1462 // exits with any other error code, then something broke...\r
1463 //\r
1464 if (Status != EFI_NOT_FOUND) {\r
1465 Error (NULL, 0, 0, "failed to parse PE32 section", FileGuidString);\r
1466 return Status;\r
1467 }\r
1468\r
1469 return EFI_SUCCESS;\r
1470}\r
1471\r
1472EFI_STATUS\r
1473AddSymFile (\r
1474 IN UINT64 BaseAddress,\r
1475 IN EFI_FFS_FILE_HEADER *FfsFile,\r
1476 IN OUT MEMORY_FILE *SymImage,\r
1477 IN CHAR8 *SourceFileName\r
1478 )\r
1479/*++\r
1480\r
1481Routine Description:\r
1482\r
1483 This function adds the SYM tokens in the source file to the destination file.\r
1484 The SYM tokens are updated to reflect the base address.\r
1485\r
1486Arguments:\r
1487\r
1488 BaseAddress The base address for the new SYM tokens.\r
1489 FfsFile Pointer to the beginning of the FFS file in question.\r
1490 SymImage The memory file to update with symbol information.\r
1491 SourceFileName The source file.\r
1492\r
1493Returns:\r
1494\r
1495 EFI_SUCCESS The function completed successfully.\r
1496 EFI_INVALID_PARAMETER One of the input parameters was invalid.\r
1497 EFI_ABORTED An error occurred.\r
1498\r
1499--*/\r
1500{\r
1501 FILE *SourceFile;\r
1502\r
1503 CHAR8 Buffer[_MAX_PATH];\r
1504 CHAR8 Type[_MAX_PATH];\r
1505 CHAR8 Address[_MAX_PATH];\r
1506 CHAR8 Section[_MAX_PATH];\r
1507 CHAR8 Token[_MAX_PATH];\r
1508 CHAR8 SymFileName[_MAX_PATH];\r
1509 CHAR8 CodeModuleName[_MAX_PATH];\r
1510 CHAR8 *Ptr;\r
1511\r
1512 UINT64 TokenAddress;\r
1513\r
1514 EFI_STATUS Status;\r
1515 EFI_FILE_SECTION_POINTER Pe32Section;\r
1516 UINT32 EntryPoint;\r
1517 UINT32 BaseOfCode;\r
1518 UINT16 MachineType;\r
1519 EFI_TE_IMAGE_HEADER *TeHdr;\r
1520\r
1521 TeHdr = NULL;\r
1522 //\r
1523 // Verify input parameters.\r
1524 //\r
1525 if (BaseAddress == 0 || FfsFile == NULL || SymImage == NULL || SourceFileName == NULL) {\r
1526 Error (NULL, 0, 0, "invalid parameter passed to AddSymFile()", NULL);\r
1527 return EFI_INVALID_PARAMETER;\r
1528 }\r
1529 //\r
1530 // Check if we want to add this file\r
1531 //\r
1532 //\r
1533 // Get the file name\r
1534 //\r
1535 strcpy (Buffer, SourceFileName);\r
1536\r
1537 //\r
1538 // Copy the file name for the path of the sym file and truncate the name portion.\r
1539 //\r
1540 strcpy (SymFileName, Buffer);\r
1541 Ptr = strrchr (SymFileName, '\\');\r
1542 assert (Ptr);\r
1543 Ptr[0] = 0;\r
1544\r
1545 //\r
1546 // Find the file extension and make it lower case\r
1547 //\r
1548 Ptr = strrchr (SymFileName, '.');\r
1549 if (Ptr != NULL) {\r
1550 strlwr (Ptr);\r
1551 }\r
1552 //\r
1553 // Check if it is PEI file\r
1554 //\r
1555 if (strstr (Buffer, ".pei") != NULL) {\r
1556 //\r
1557 // Find the human readable portion\r
1558 //\r
1559 if (!strtok (Buffer, "-") ||\r
1560 !strtok (NULL, "-") ||\r
1561 !strtok (NULL, "-") ||\r
1562 !strtok (NULL, "-") ||\r
1563 !strtok (NULL, "-") ||\r
1564 !strcpy (Buffer, strtok (NULL, "."))\r
1565 ) {\r
1566 Error (NULL, 0, 0, "failed to find human readable portion of the file name in AddSymFile()", NULL);\r
1567 return EFI_ABORTED;\r
1568 }\r
1569 //\r
1570 // Save code module name\r
1571 //\r
1572 strcpy (CodeModuleName, Buffer);\r
1573\r
1574 //\r
1575 // Add the symbol file name and extension to the file path.\r
1576 //\r
1577 strcat (Buffer, ".sym");\r
1578 strcat (SymFileName, "\\");\r
1579 strcat (SymFileName, Buffer);\r
1580 } else {\r
1581 //\r
1582 // Only handle PEIM files.\r
1583 //\r
1584 return EFI_SUCCESS;\r
1585 }\r
1586 //\r
1587 // Find PE32 section\r
1588 //\r
1589 Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, 1, &Pe32Section);\r
1590\r
1591 //\r
1592 // BUGBUG: Assume if no PE32 section it is PIC and hardcode base address\r
1593 //\r
1594 if (Status == EFI_NOT_FOUND) {\r
1595 Status = GetSectionByType (FfsFile, EFI_SECTION_TE, 1, &Pe32Section);\r
1596 if (Status == EFI_NOT_FOUND) {\r
1597 BaseOfCode = 0x60;\r
1598 } else {\r
1599 TeHdr = (EFI_TE_IMAGE_HEADER *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_COMMON_SECTION_HEADER));\r
1600 BaseOfCode = TeHdr->BaseOfCode - TeHdr->StrippedSize;\r
1601 }\r
1602 } else if (EFI_ERROR (Status)) {\r
1603 Error (NULL, 0, 0, "could not parse a PE32 section from the PEI file", NULL);\r
1604 return Status;\r
1605 } else {\r
1606 Status = GetPe32Info (\r
1607 (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),\r
1608 &EntryPoint,\r
1609 &BaseOfCode,\r
1610 &MachineType\r
1611 );\r
1612 if (EFI_ERROR (Status)) {\r
1613 Error (NULL, 0, 0, "GetPe32Info() could not get PE32 entry point for PEI file", NULL);\r
1614 return Status;\r
1615 }\r
1616 }\r
1617 //\r
1618 // Open the source file\r
1619 //\r
1620 SourceFile = fopen (SymFileName, "r");\r
1621 if (SourceFile == NULL) {\r
1622 //\r
1623 // SYM files are not required.\r
1624 //\r
1625 return EFI_SUCCESS;\r
1626 }\r
1627 //\r
1628 // Read the first line\r
1629 //\r
1630 if (fgets (Buffer, _MAX_PATH, SourceFile) == NULL) {\r
1631 Buffer[0] = 0;\r
1632 }\r
1633 //\r
1634 // Make sure it matches the expected sym format\r
1635 //\r
1636 if (strcmp (Buffer, "TEXTSYM format | V1.0\n")) {\r
1637 fclose (SourceFile);\r
1638 Error (NULL, 0, 0, "AddSymFile() found unexpected sym format in input file", NULL);\r
1639 return EFI_ABORTED;\r
1640 }\r
1641 //\r
1642 // Read in the file\r
1643 //\r
1644 while (feof (SourceFile) == 0) {\r
1645 //\r
1646 // Read a line\r
1647 //\r
1648 if (fscanf (\r
1649 SourceFile,\r
1650 "%s | %s | %s | %s\n",\r
1651 Type,\r
1652 Address,\r
1653 Section,\r
1654 Token\r
1655 ) == 4) {\r
1656 //\r
1657 // If the token starts with "??" ignore it\r
1658 //\r
1659 if (Token[0] == '?' && Token[1] == '?') {\r
1660 continue;\r
1661 }\r
1662 //\r
1663 // Get the token address\r
1664 //\r
1665 AsciiStringToUint64 (Address, TRUE, &TokenAddress);\r
1666\r
1667 //\r
1668 // Add the base address\r
1669 //\r
1670 TokenAddress += BaseAddress;\r
1671\r
1672 //\r
1673 // If PE32 then find the start of code. For PIC it is hardcoded.\r
1674 //\r
1675 if (TeHdr == NULL && Pe32Section.Pe32Section) {\r
1676 //\r
1677 // Add the offset of the PE32 section\r
1678 //\r
1679 TokenAddress += (UINTN) Pe32Section.Pe32Section - (UINTN) FfsFile;\r
1680\r
1681 //\r
1682 // Add the size of the PE32 section header\r
1683 //\r
1684 TokenAddress += sizeof (EFI_PE32_SECTION);\r
1685 } else if (TeHdr != NULL) {\r
1686 //\r
1687 // Add the Te section and FfsHeader\r
1688 //\r
1689 //\r
1690 // BUGBUG: Don't know why this is 0x28 bytes.\r
1691 //\r
1692 TokenAddress += (UINTN) TeHdr - (UINTN) FfsFile + 0x28;\r
1693 } else {\r
1694 //\r
1695 // BUGBUG: Don't know why this is 0x28 bytes.\r
1696 //\r
1697 TokenAddress += 0x28;\r
1698 }\r
1699 //\r
1700 // Add the beginning of the code\r
1701 //\r
1702 TokenAddress += BaseOfCode;\r
1703\r
1704 sprintf (\r
1705 Buffer,\r
1706 "%s | %016I64X | %s | _%s%s\n",\r
1707 Type,\r
1708 TokenAddress,\r
1709 Section,\r
1710 CodeModuleName,\r
1711 Token\r
1712 );\r
1713 memcpy (SymImage->CurrentFilePointer, Buffer, strlen (Buffer) + 1);\r
1714 SymImage->CurrentFilePointer = (UINT8 *) (((UINTN) SymImage->CurrentFilePointer) + strlen (Buffer) + 1);\r
1715 }\r
1716 }\r
1717\r
1718 fclose (SourceFile);\r
1719 return EFI_SUCCESS;\r
1720}\r
1721\r
1722EFI_STATUS\r
1723AddFile (\r
1724 IN OUT MEMORY_FILE *FvImage,\r
1725 IN FV_INFO *FvInfo,\r
1726 IN UINTN Index,\r
1727 IN OUT EFI_FFS_FILE_HEADER **VtfFileImage,\r
1728 IN OUT MEMORY_FILE *SymImage\r
1729 )\r
1730/*++\r
1731\r
1732Routine Description:\r
1733\r
1734 This function adds a file to the FV image. The file will pad to the\r
1735 appropriate alignment if required.\r
1736\r
1737Arguments:\r
1738\r
1739 FvImage The memory image of the FV to add it to. The current offset\r
1740 must be valid.\r
1741 FvInfo Pointer to information about the FV.\r
1742 Index The file in the FvInfo file list to add.\r
1743 VtfFileImage A pointer to the VTF file within the FvImage. If this is equal\r
1744 to the end of the FvImage then no VTF previously found.\r
1745 SymImage The memory image of the Sym file to update if symbols are present.\r
1746 The current offset must be valid.\r
1747\r
1748Returns:\r
1749\r
1750 EFI_SUCCESS The function completed successfully.\r
1751 EFI_INVALID_PARAMETER One of the input parameters was invalid.\r
1752 EFI_ABORTED An error occurred.\r
1753 EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the add.\r
1754\r
1755--*/\r
1756{\r
1757 FILE *NewFile;\r
1758 UINTN FileSize;\r
1759 UINT8 *FileBuffer;\r
1760 UINTN NumBytesRead;\r
1761 UINT32 CurrentFileAlignment;\r
1762 EFI_STATUS Status;\r
1763 EFI_PHYSICAL_ADDRESS CurrentFileBaseAddress;\r
1764 UINT8 VtfHeaderChecksum;\r
1765 UINT8 VtfFileChecksum;\r
1766 UINT8 FileState;\r
1767 EFI_FFS_FILE_TAIL TailValue;\r
1768 UINT32 TailSize;\r
1769 //\r
1770 // Verify input parameters.\r
1771 //\r
1772 if (FvImage == NULL || FvInfo == NULL || FvInfo->FvFiles[Index][0] == 0 || VtfFileImage == NULL || SymImage == NULL) {\r
1773 return EFI_INVALID_PARAMETER;\r
1774 }\r
1775 //\r
1776 // Read the file to add\r
1777 //\r
1778 NewFile = fopen (FvInfo->FvFiles[Index], "rb");\r
1779\r
1780 if (NewFile == NULL) {\r
1781 Error (NULL, 0, 0, FvInfo->FvFiles[Index], "failed to open file for reading");\r
1782 return EFI_ABORTED;\r
1783 }\r
1784 //\r
1785 // Get the file size\r
1786 //\r
1787#ifdef __GNUC__\r
1788 {\r
1789 struct stat stat_buf;\r
1790 fstat(fileno(NewFile), &stat_buf);\r
1791 FileSize = stat_buf.st_size;\r
1792 }\r
1793#else\r
1794 FileSize = _filelength (fileno (NewFile));\r
1795#endif\r
1796\r
1797 //\r
1798 // Read the file into a buffer\r
1799 //\r
1800 FileBuffer = malloc (FileSize);\r
1801 if (FileBuffer == NULL) {\r
1802 Error (NULL, 0, 0, "memory allocation failure", NULL);\r
1803 return EFI_OUT_OF_RESOURCES;\r
1804 }\r
1805\r
1806 NumBytesRead = fread (FileBuffer, sizeof (UINT8), FileSize, NewFile);\r
1807\r
1808 //\r
1809 // Done with the file, from this point on we will just use the buffer read.\r
1810 //\r
1811 fclose (NewFile);\r
1812\r
1813 //\r
1814 // Verify read successful\r
1815 //\r
1816 if (NumBytesRead != sizeof (UINT8) * FileSize) {\r
1817 free (FileBuffer);\r
1818 Error (NULL, 0, 0, FvInfo->FvFiles[Index], "failed to read input file contents");\r
1819 return EFI_ABORTED;\r
1820 }\r
1821 //\r
1822 // Verify space exists to add the file\r
1823 //\r
1824 if (FileSize > (UINTN) ((UINTN) *VtfFileImage - (UINTN) FvImage->CurrentFilePointer)) {\r
1825 Error (NULL, 0, 0, FvInfo->FvFiles[Index], "insufficient space remains to add the file");\r
1826 return EFI_OUT_OF_RESOURCES;\r
1827 }\r
1828 //\r
1829 // Update the file state based on polarity of the FV.\r
1830 //\r
1831 UpdateFfsFileState (\r
1832 (EFI_FFS_FILE_HEADER *) FileBuffer,\r
1833 (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage\r
1834 );\r
1835\r
1836 //\r
1837 // If we have a VTF file, add it at the top.\r
1838 //\r
1839 if (IsVtfFile ((EFI_FFS_FILE_HEADER *) FileBuffer)) {\r
1840 if ((UINTN) *VtfFileImage == (UINTN) FvImage->Eof) {\r
1841 //\r
1842 // No previous VTF, add this one.\r
1843 //\r
1844 *VtfFileImage = (EFI_FFS_FILE_HEADER *) (UINTN) ((UINTN) FvImage->FileImage + FvInfo->Size - FileSize);\r
1845 //\r
1846 // Sanity check. The file MUST align appropriately\r
1847 //\r
1848 if ((((UINTN) *VtfFileImage) & 0x07) != 0) {\r
1849 Error (NULL, 0, 0, "VTF file does not align on 8-byte boundary", NULL);\r
1850 }\r
1851 //\r
1852 // copy VTF File Header\r
1853 //\r
1854 memcpy (*VtfFileImage, FileBuffer, sizeof (EFI_FFS_FILE_HEADER));\r
1855\r
1856 //\r
1857 // Copy VTF body\r
1858 //\r
1859 memcpy (\r
1860 (UINT8 *) *VtfFileImage + sizeof (EFI_FFS_FILE_HEADER),\r
1861 FileBuffer + sizeof (EFI_FFS_FILE_HEADER),\r
1862 FileSize - sizeof (EFI_FFS_FILE_HEADER)\r
1863 );\r
1864\r
1865 //\r
1866 // re-calculate the VTF File Header\r
1867 //\r
1868 FileState = (*VtfFileImage)->State;\r
1869 (*VtfFileImage)->State = 0;\r
1870 *(UINT32 *) ((*VtfFileImage)->Size) = FileSize;\r
1871 (*VtfFileImage)->IntegrityCheck.Checksum.Header = 0;\r
1872 (*VtfFileImage)->IntegrityCheck.Checksum.File = 0;\r
1873\r
1874 VtfHeaderChecksum = CalculateChecksum8 ((UINT8 *) *VtfFileImage, sizeof (EFI_FFS_FILE_HEADER));\r
1875 (*VtfFileImage)->IntegrityCheck.Checksum.Header = VtfHeaderChecksum;\r
1876 //\r
1877 // Determine if it has a tail\r
1878 //\r
1879 if ((*VtfFileImage)->Attributes & FFS_ATTRIB_TAIL_PRESENT) {\r
1880 TailSize = sizeof (EFI_FFS_FILE_TAIL);\r
1881 } else {\r
1882 TailSize = 0;\r
1883 }\r
1884\r
1885 if ((*VtfFileImage)->Attributes & FFS_ATTRIB_CHECKSUM) {\r
1886 VtfFileChecksum = CalculateChecksum8 ((UINT8 *) *VtfFileImage, FileSize - TailSize);\r
1887 (*VtfFileImage)->IntegrityCheck.Checksum.File = VtfFileChecksum;\r
1888 } else {\r
1889 (*VtfFileImage)->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
1890 }\r
1891 //\r
1892 // If it has a file tail, update it\r
1893 //\r
1894 if ((*VtfFileImage)->Attributes & FFS_ATTRIB_TAIL_PRESENT) {\r
1895 TailValue = (EFI_FFS_FILE_TAIL) (~((*VtfFileImage)->IntegrityCheck.TailReference));\r
1896 *(EFI_FFS_FILE_TAIL *) (((UINTN) (*VtfFileImage) + GetLength ((*VtfFileImage)->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;\r
1897 }\r
1898 (*VtfFileImage)->State = FileState;\r
1899 free (FileBuffer);\r
1900 return EFI_SUCCESS;\r
1901 } else {\r
1902 //\r
1903 // Already found a VTF file.\r
1904 //\r
1905 Error (NULL, 0, 0, "multiple VTF files are illegal in a single FV", NULL);\r
1906 free (FileBuffer);\r
1907 return EFI_ABORTED;\r
1908 }\r
1909 }\r
1910 //\r
1911 // Check if alignment is required\r
1912 //\r
1913 Status = ReadFfsAlignment ((EFI_FFS_FILE_HEADER *) FileBuffer, &CurrentFileAlignment);\r
1914 if (EFI_ERROR (Status)) {\r
1915 printf ("ERROR: Could not determine alignment of file %s.\n", FvInfo->FvFiles[Index]);\r
1916 free (FileBuffer);\r
1917 return EFI_ABORTED;\r
1918 }\r
1919 //\r
1920 // Add pad file if necessary\r
1921 //\r
1922 Status = AddPadFile (FvImage, CurrentFileAlignment);\r
1923 if (EFI_ERROR (Status)) {\r
1924 printf ("ERROR: Could not align the file data properly.\n");\r
1925 free (FileBuffer);\r
1926 return EFI_ABORTED;\r
1927 }\r
1928 //\r
1929 // Add file\r
1930 //\r
1931 if ((FvImage->CurrentFilePointer + FileSize) < FvImage->Eof) {\r
1932 //\r
1933 // Copy the file\r
1934 //\r
1935 memcpy (FvImage->CurrentFilePointer, FileBuffer, FileSize);\r
1936\r
1937 //\r
1938 // If the file is XIP, rebase\r
1939 //\r
1940 CurrentFileBaseAddress = FvInfo->BaseAddress + ((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage);\r
1941 //\r
1942 // Status = RebaseFfsFile ((EFI_FFS_FILE_HEADER*) FvImage->CurrentFilePointer, CurrentFileBaseAddress);\r
1943 // if (EFI_ERROR(Status)) {\r
1944 // printf ("ERROR: Could not rebase the file %s.\n", FvInfo->FvFiles[Index]);\r
1945 // return EFI_ABORTED;\r
1946 // }\r
1947 //\r
1948 // Update Symbol file\r
1949 //\r
1950 Status = AddSymFile (\r
1951 CurrentFileBaseAddress,\r
1952 (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer,\r
1953 SymImage,\r
1954 FvInfo->FvFiles[Index]\r
1955 );\r
1956 assert (!EFI_ERROR (Status));\r
1957\r
1958 //\r
1959 // Update the current pointer in the FV image\r
1960 //\r
1961 FvImage->CurrentFilePointer += FileSize;\r
1962 } else {\r
1963 printf ("ERROR: The firmware volume is out of space, could not add file %s.\n", FvInfo->FvFiles[Index]);\r
1964 return EFI_ABORTED;\r
1965 }\r
1966 //\r
1967 // Make next file start at QWord Boundry\r
1968 //\r
1969 while (((UINTN) FvImage->CurrentFilePointer & 0x07) != 0) {\r
1970 FvImage->CurrentFilePointer++;\r
1971 }\r
1972 //\r
1973 // Free allocated memory.\r
1974 //\r
1975 free (FileBuffer);\r
1976\r
1977 return EFI_SUCCESS;\r
1978}\r
1979\r
1980EFI_STATUS\r
1981AddVariableBlock (\r
1982 IN UINT8 *FvImage,\r
1983 IN UINTN Size,\r
1984 IN FV_INFO *FvInfo\r
1985 )\r
1986{\r
1987 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;\r
1988 VARIABLE_STORE_HEADER *VarStoreHeader;\r
1989 //\r
1990 // Variable block should exclude FvHeader. Since the length of\r
1991 // FvHeader depends on the block map, which is variable length,\r
1992 // we could only decide the actual variable block length here.\r
1993 //\r
1994 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage;\r
1995 FvImage = FvImage + FvHeader->HeaderLength;\r
1996\r
1997 VarStoreHeader = (VARIABLE_STORE_HEADER *) FvImage;\r
1998\r
1999 VarStoreHeader->Signature = VARIABLE_STORE_SIGNATURE;\r
2000 VarStoreHeader->Size = Size - FvHeader->HeaderLength;\r
2001 VarStoreHeader->Format = VARIABLE_STORE_FORMATTED;\r
2002 VarStoreHeader->State = VARIABLE_STORE_HEALTHY;\r
2003 VarStoreHeader->Reserved = 0;\r
2004 VarStoreHeader->Reserved1 = 0;\r
2005\r
2006 return EFI_SUCCESS;\r
2007}\r
2008\r
2009EFI_STATUS\r
2010AddEventLogBlock (\r
2011 IN UINT8 *FvImage,\r
2012 IN UINTN Size,\r
2013 IN FV_INFO *FvInfo\r
2014 )\r
2015{\r
2016 return EFI_SUCCESS;\r
2017}\r
2018\r
2019EFI_STATUS\r
2020AddFTWWorkingBlock (\r
2021 IN UINT8 *FvImage,\r
2022 IN UINTN Size,\r
2023 IN FV_INFO *FvInfo\r
2024 )\r
2025{\r
2026 EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *FTWHeader;\r
2027 UINT32 Crc32;\r
2028\r
2029 Crc32 = 0;\r
2030 FTWHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) FvImage;\r
2031 memcpy (&FTWHeader->Signature, &(FvInfo->FvGuid), sizeof (EFI_GUID));\r
2032 FTWHeader->WriteQueueSize = Size - sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER);\r
2033 CalculateCrc32 (FvImage, sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER), &Crc32);\r
2034 FTWHeader->Crc = Crc32;\r
2035 if (FvInfo->FvAttributes & EFI_FVB_ERASE_POLARITY) {\r
2036 FTWHeader->WorkingBlockValid = 0;\r
2037 FTWHeader->WorkingBlockInvalid = 1;\r
2038 } else {\r
2039 FTWHeader->WorkingBlockValid = 1;\r
2040 FTWHeader->WorkingBlockInvalid = 0;\r
2041 }\r
2042\r
2043 return EFI_SUCCESS;\r
2044}\r
2045\r
2046EFI_STATUS\r
2047AddFTWSpareBlock (\r
2048 IN UINT8 *FvImage,\r
2049 IN UINTN Size,\r
2050 IN FV_INFO *FvInfo\r
2051 )\r
2052{\r
2053 return EFI_SUCCESS;\r
2054}\r
2055\r
2056EFI_STATUS\r
2057GenNonFFSFv (\r
2058 IN UINT8 *FvImage,\r
2059 IN FV_INFO *FvInfo\r
2060 )\r
2061/*++\r
2062\r
2063Routine Description:\r
2064\r
2065 This function generate the non FFS FV image, such as the working block\r
2066 and spare block. How each component of the FV is built is component\r
2067 specific.\r
2068\r
2069Arguments:\r
2070\r
2071 FvImage The memory image of the FV to add it to. The current offset\r
2072 must be valid.\r
2073 FvInfo Pointer to information about the FV.\r
2074\r
2075Returns:\r
2076\r
2077 EFI_SUCCESS The function completed successfully.\r
2078 EFI_INVALID_PARAMETER One of the input parameters was invalid.\r
2079 EFI_ABORTED An error occurred.\r
2080 EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the add.\r
2081\r
2082--*/\r
2083{\r
2084 UINTN Index;\r
2085 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;\r
2086 UINT64 TotalSize;\r
2087\r
2088 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage;\r
2089 TotalSize = 0;\r
2090\r
2091 for (Index = 0; FvInfo->FvComponents[Index].Size != 0; Index++) {\r
2092 if (stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_VARIABLE_STRING) == 0) {\r
2093 AddVariableBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);\r
2094 } else if (stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_EVENT_LOG_STRING) == 0) {\r
2095 AddEventLogBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);\r
2096 } else if (stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_WORKING_STRING) == 0) {\r
2097 AddFTWWorkingBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);\r
2098 } else if (stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_SPARE_STRING) == 0) {\r
2099 AddFTWSpareBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);\r
2100 } else {\r
2101 printf ("Error. Unknown Non-FFS block %s \n", FvInfo->FvComponents[Index].ComponentName);\r
2102 return EFI_ABORTED;\r
2103 }\r
2104\r
2105 FvImage = FvImage + FvInfo->FvComponents[Index].Size;\r
2106 TotalSize = TotalSize + FvInfo->FvComponents[Index].Size;\r
2107 }\r
2108 //\r
2109 // Index and TotalSize is zero mean there's no component, so this is an empty fv\r
2110 //\r
2111 if ((Index != 0 || TotalSize != 0) && TotalSize != FvInfo->Size) {\r
2112 printf ("Error. Component size does not sum up to FV size.\n");\r
2113 return EFI_ABORTED;\r
2114 }\r
2115\r
2116 return EFI_SUCCESS;\r
2117}\r
2118\r
2119EFI_STATUS\r
2120PadFvImage (\r
2121 IN MEMORY_FILE *FvImage,\r
2122 IN EFI_FFS_FILE_HEADER *VtfFileImage\r
2123 )\r
2124/*++\r
2125\r
2126Routine Description:\r
2127\r
2128 This function places a pad file between the last file in the FV and the VTF\r
2129 file if the VTF file exists.\r
2130\r
2131Arguments:\r
2132\r
2133 FvImage Memory file for the FV memory image\r
2134 VtfFileImage The address of the VTF file. If this is the end of the FV\r
2135 image, no VTF exists and no pad file is needed.\r
2136\r
2137Returns:\r
2138\r
2139 EFI_SUCCESS Completed successfully.\r
2140 EFI_INVALID_PARAMETER One of the input parameters was NULL.\r
2141\r
2142--*/\r
2143{\r
2144 EFI_FFS_FILE_HEADER *PadFile;\r
2145 UINTN FileSize;\r
2146\r
2147 //\r
2148 // If there is no VTF or the VTF naturally follows the previous file without a\r
2149 // pad file, then there's nothing to do\r
2150 //\r
2151 if ((UINTN) VtfFileImage == (UINTN) FvImage->Eof || (void *) FvImage->CurrentFilePointer == (void *) VtfFileImage) {\r
2152 return EFI_SUCCESS;\r
2153 }\r
2154 //\r
2155 // Pad file starts at beginning of free space\r
2156 //\r
2157 PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer;\r
2158\r
2159 //\r
2160 // write header\r
2161 //\r
2162 memset (PadFile, 0, sizeof (EFI_FFS_FILE_HEADER));\r
2163 memcpy (&PadFile->Name, &DefaultFvPadFileNameGuid, sizeof (EFI_GUID));\r
2164 PadFile->Type = EFI_FV_FILETYPE_FFS_PAD;\r
2165 PadFile->Attributes = 0;\r
2166\r
2167 //\r
2168 // FileSize includes the EFI_FFS_FILE_HEADER\r
2169 //\r
2170 FileSize = (UINTN) VtfFileImage - (UINTN) FvImage->CurrentFilePointer;\r
2171 PadFile->Size[0] = (UINT8) (FileSize & 0x000000FF);\r
2172 PadFile->Size[1] = (UINT8) ((FileSize & 0x0000FF00) >> 8);\r
2173 PadFile->Size[2] = (UINT8) ((FileSize & 0x00FF0000) >> 16);\r
2174\r
2175 //\r
2176 // Fill in checksums and state, must be zero during checksum calculation.\r
2177 //\r
2178 PadFile->IntegrityCheck.Checksum.Header = 0;\r
2179 PadFile->IntegrityCheck.Checksum.File = 0;\r
2180 PadFile->State = 0;\r
2181 PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER));\r
2182 if (PadFile->Attributes & FFS_ATTRIB_CHECKSUM) {\r
2183 PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) PadFile, FileSize);\r
2184 } else {\r
2185 PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
2186 }\r
2187\r
2188 PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;\r
2189\r
2190 UpdateFfsFileState (\r
2191 (EFI_FFS_FILE_HEADER *) PadFile,\r
2192 (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage\r
2193 );\r
2194 //\r
2195 // Update the current FV pointer\r
2196 //\r
2197 FvImage->CurrentFilePointer = FvImage->Eof;\r
2198\r
2199 return EFI_SUCCESS;\r
2200}\r
2201\r
2202EFI_STATUS\r
2203UpdateResetVector (\r
2204 IN MEMORY_FILE *FvImage,\r
2205 IN FV_INFO *FvInfo,\r
2206 IN EFI_FFS_FILE_HEADER *VtfFile\r
2207 )\r
2208/*++\r
2209\r
2210Routine Description:\r
2211\r
2212 This parses the FV looking for the PEI core and then plugs the address into\r
2213 the SALE_ENTRY point of the BSF/VTF for IPF and does BUGBUG TBD action to\r
2214 complete an IA32 Bootstrap FV.\r
2215\r
2216Arguments:\r
2217\r
2218 FvImage Memory file for the FV memory image\r
2219 FvInfo Information read from INF file.\r
2220 VtfFile Pointer to the VTF file in the FV image.\r
2221\r
2222Returns:\r
2223\r
2224 EFI_SUCCESS Function Completed successfully.\r
2225 EFI_ABORTED Error encountered.\r
2226 EFI_INVALID_PARAMETER A required parameter was NULL.\r
2227 EFI_NOT_FOUND PEI Core file not found.\r
2228\r
2229--*/\r
2230{\r
2231 EFI_FFS_FILE_HEADER *PeiCoreFile;\r
2232 EFI_FFS_FILE_HEADER *SecCoreFile;\r
2233 EFI_STATUS Status;\r
2234 EFI_FILE_SECTION_POINTER Pe32Section;\r
2235 UINT32 EntryPoint;\r
2236 UINT32 BaseOfCode;\r
2237 UINT16 MachineType;\r
2238 EFI_PHYSICAL_ADDRESS PeiCorePhysicalAddress;\r
2239 EFI_PHYSICAL_ADDRESS SecCorePhysicalAddress;\r
2240 EFI_PHYSICAL_ADDRESS *SecCoreEntryAddressPtr;\r
2241 UINT32 *Ia32ResetAddressPtr;\r
2242 UINT8 *BytePointer;\r
2243 UINT8 *BytePointer2;\r
2244 UINT16 *WordPointer;\r
2245 UINT16 CheckSum;\r
2246 UINTN Index;\r
2247 EFI_FFS_FILE_STATE SavedState;\r
2248 EFI_FFS_FILE_TAIL TailValue;\r
2249 UINT32 TailSize;\r
2250 UINT64 FitAddress;\r
2251 FIT_TABLE *FitTablePtr;\r
2252\r
2253 //\r
2254 // Verify input parameters\r
2255 //\r
2256 if (FvImage == NULL || FvInfo == NULL || VtfFile == NULL) {\r
2257 return EFI_INVALID_PARAMETER;\r
2258 }\r
2259 //\r
2260 // Initialize FV library\r
2261 //\r
2262 InitializeFvLib (FvImage->FileImage, (UINTN) FvImage->Eof - (UINTN) FvImage->FileImage);\r
2263\r
2264 //\r
2265 // Verify VTF file\r
2266 //\r
2267 Status = VerifyFfsFile (VtfFile);\r
2268 if (EFI_ERROR (Status)) {\r
2269 return EFI_INVALID_PARAMETER;\r
2270 }\r
2271 //\r
2272 // Find the PEI Core\r
2273 //\r
2274 Status = GetFileByType (EFI_FV_FILETYPE_PEI_CORE, 1, &PeiCoreFile);\r
2275 if (EFI_ERROR (Status) || PeiCoreFile == NULL) {\r
2276 Error (NULL, 0, 0, "could not find the PEI core in the FV", NULL);\r
2277 return EFI_ABORTED;\r
2278 }\r
2279 //\r
2280 // PEI Core found, now find PE32 section\r
2281 //\r
2282 Status = GetSectionByType (PeiCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);\r
2283 if (EFI_ERROR (Status)) {\r
2284 Error (NULL, 0, 0, "could not find PE32 section in PEI core file", NULL);\r
2285 return EFI_ABORTED;\r
2286 }\r
2287\r
2288 Status = GetPe32Info (\r
2289 (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),\r
2290 &EntryPoint,\r
2291 &BaseOfCode,\r
2292 &MachineType\r
2293 );\r
2294 if (EFI_ERROR (Status)) {\r
2295 Error (NULL, 0, 0, "could not get PE32 entry point for PEI core", NULL);\r
2296 return EFI_ABORTED;\r
2297 }\r
2298 //\r
2299 // Physical address is FV base + offset of PE32 + offset of the entry point\r
2300 //\r
2301 PeiCorePhysicalAddress = FvInfo->BaseAddress;\r
2302 PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;\r
2303 PeiCorePhysicalAddress += EntryPoint;\r
2304\r
2305 if (MachineType == EFI_IMAGE_MACHINE_IA64) {\r
2306 //\r
2307 // Update PEI_CORE address\r
2308 //\r
2309 //\r
2310 // Set the uncached attribute bit in the physical address\r
2311 //\r
2312 PeiCorePhysicalAddress |= 0x8000000000000000ULL;\r
2313\r
2314 //\r
2315 // Check if address is aligned on a 16 byte boundary\r
2316 //\r
2317 if (PeiCorePhysicalAddress & 0xF) {\r
2318 printf (\r
2319 "ERROR: PEI_CORE entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n",\r
2320 PeiCorePhysicalAddress\r
2321 );\r
2322 return EFI_ABORTED;\r
2323 }\r
2324 //\r
2325 // First Get the FIT table address\r
2326 //\r
2327 FitAddress = (*(UINT64 *) (FvImage->Eof - IPF_FIT_ADDRESS_OFFSET)) & 0xFFFFFFFF;\r
2328\r
2329 FitTablePtr = (FIT_TABLE *) (FvImage->FileImage + (FitAddress - FvInfo->BaseAddress));\r
2330\r
2331 Status = UpdatePeiCoreEntryInFit (FitTablePtr, PeiCorePhysicalAddress);\r
2332\r
2333 if (!EFI_ERROR (Status)) {\r
2334 UpdateFitCheckSum (FitTablePtr);\r
2335 }\r
2336 //\r
2337 // Find the Sec Core\r
2338 //\r
2339 Status = GetFileByType (EFI_FV_FILETYPE_SECURITY_CORE, 1, &SecCoreFile);\r
2340 if (EFI_ERROR (Status) || SecCoreFile == NULL) {\r
2341 Error (NULL, 0, 0, "could not find the Sec core in the FV", NULL);\r
2342 return EFI_ABORTED;\r
2343 }\r
2344 //\r
2345 // Sec Core found, now find PE32 section\r
2346 //\r
2347 Status = GetSectionByType (SecCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);\r
2348 if (EFI_ERROR (Status)) {\r
2349 Error (NULL, 0, 0, "could not find PE32 section in SEC core file", NULL);\r
2350 return EFI_ABORTED;\r
2351 }\r
2352\r
2353 Status = GetPe32Info (\r
2354 (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),\r
2355 &EntryPoint,\r
2356 &BaseOfCode,\r
2357 &MachineType\r
2358 );\r
2359 if (EFI_ERROR (Status)) {\r
2360 Error (NULL, 0, 0, "could not get PE32 entry point for SEC core", NULL);\r
2361 return EFI_ABORTED;\r
2362 }\r
2363 //\r
2364 // Physical address is FV base + offset of PE32 + offset of the entry point\r
2365 //\r
2366 SecCorePhysicalAddress = FvInfo->BaseAddress;\r
2367 SecCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;\r
2368 SecCorePhysicalAddress += EntryPoint;\r
2369\r
2370 //\r
2371 // Update SEC_CORE address\r
2372 //\r
2373 //\r
2374 // Set the uncached attribute bit in the physical address\r
2375 //\r
2376 SecCorePhysicalAddress |= 0x8000000000000000ULL;\r
2377\r
2378 //\r
2379 // Update the address\r
2380 //\r
2381 SecCoreEntryAddressPtr = (EFI_PHYSICAL_ADDRESS *) ((UINTN) FvImage->Eof - IPF_SALE_ENTRY_ADDRESS_OFFSET);\r
2382 *SecCoreEntryAddressPtr = SecCorePhysicalAddress;\r
2383\r
2384 //\r
2385 // Check if address is aligned on a 16 byte boundary\r
2386 //\r
2387 if (SecCorePhysicalAddress & 0xF) {\r
2388 printf (\r
2389 "ERROR: SALE_ENTRY entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n",\r
2390 SecCorePhysicalAddress\r
2391 );\r
2392 return EFI_ABORTED;\r
2393 }\r
2394 } else if (MachineType == EFI_IMAGE_MACHINE_IA32) {\r
2395 //\r
2396 // Get the location to update\r
2397 //\r
2398 Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - IA32_PEI_CORE_ENTRY_OFFSET);\r
2399\r
2400 //\r
2401 // Write lower 32 bits of physical address\r
2402 //\r
2403 *Ia32ResetAddressPtr = (UINT32) PeiCorePhysicalAddress;\r
2404\r
2405 //\r
2406 // Update the BFV base address\r
2407 //\r
2408 Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - 4);\r
2409 *Ia32ResetAddressPtr = (UINT32) (FvInfo->BaseAddress);\r
2410\r
2411 CheckSum = 0x0000;\r
2412\r
2413 //\r
2414 // Update the Startup AP in the FVH header block ZeroVector region.\r
2415 //\r
2416 BytePointer = (UINT8 *) ((UINTN) FvImage->FileImage);\r
2417 BytePointer2 = (FvInfo->Size == 0x10000) ? m64kRecoveryStartupApDataArray : m128kRecoveryStartupApDataArray;\r
2418 for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY; Index++) {\r
2419 *BytePointer++ = *BytePointer2++;\r
2420 }\r
2421 //\r
2422 // Calculate the checksum\r
2423 //\r
2424 WordPointer = (UINT16 *) ((UINTN) FvImage->FileImage);\r
2425 for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY / 2; Index++) {\r
2426 CheckSum = (UINT16) (CheckSum + ((UINT16) *WordPointer));\r
2427 WordPointer++;\r
2428 }\r
2429 //\r
2430 // Update the checksum field\r
2431 //\r
2432 BytePointer = (UINT8 *) ((UINTN) FvImage->FileImage);\r
2433 BytePointer += (SIZEOF_STARTUP_DATA_ARRAY - 2);\r
2434 WordPointer = (UINT16 *) BytePointer;\r
2435 *WordPointer = (UINT16) (0x10000 - (UINT32) CheckSum);\r
2436 } else {\r
2437 Error (NULL, 0, 0, "invalid machine type in PEI core", "machine type=0x%X", (UINT32) MachineType);\r
2438 return EFI_ABORTED;\r
2439 }\r
2440 //\r
2441 // Determine if it has an FFS file tail.\r
2442 //\r
2443 if (VtfFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {\r
2444 TailSize = sizeof (EFI_FFS_FILE_TAIL);\r
2445 } else {\r
2446 TailSize = 0;\r
2447 }\r
2448 //\r
2449 // Now update file checksum\r
2450 //\r
2451 SavedState = VtfFile->State;\r
2452 VtfFile->IntegrityCheck.Checksum.File = 0;\r
2453 VtfFile->State = 0;\r
2454 if (VtfFile->Attributes & FFS_ATTRIB_CHECKSUM) {\r
2455 VtfFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (\r
2456 (UINT8 *) VtfFile,\r
2457 GetLength (VtfFile->Size) - TailSize\r
2458 );\r
2459 } else {\r
2460 VtfFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
2461 }\r
2462\r
2463 VtfFile->State = SavedState;\r
2464\r
2465 //\r
2466 // Update tail if present\r
2467 //\r
2468 if (VtfFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {\r
2469 TailValue = (EFI_FFS_FILE_TAIL) (~(VtfFile->IntegrityCheck.TailReference));\r
2470 *(EFI_FFS_FILE_TAIL *) (((UINTN) (VtfFile) + GetLength (VtfFile->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;\r
2471 }\r
2472\r
2473 return EFI_SUCCESS;\r
2474}\r
2475\r
2476EFI_STATUS\r
2477GetPe32Info (\r
2478 IN UINT8 *Pe32,\r
2479 OUT UINT32 *EntryPoint,\r
2480 OUT UINT32 *BaseOfCode,\r
2481 OUT UINT16 *MachineType\r
2482 )\r
2483/*++\r
2484\r
2485Routine Description:\r
2486\r
2487 Retrieves the PE32 entry point offset and machine type. See EfiImage.h for\r
2488 machine types. The entry point offset is from the beginning of the PE32\r
2489 buffer passed in.\r
2490\r
2491Arguments:\r
2492\r
2493 Pe32 Beginning of the PE32.\r
2494 EntryPoint Offset from the beginning of the PE32 to the image entry point.\r
2495 BaseOfCode Base address of code.\r
2496 MachineType Magic number for the machine type.\r
2497\r
2498Returns:\r
2499\r
2500 EFI_SUCCESS Function completed successfully.\r
2501 EFI_ABORTED Error encountered.\r
2502 EFI_INVALID_PARAMETER A required parameter was NULL.\r
2503 EFI_UNSUPPORTED The operation is unsupported.\r
2504\r
2505--*/\r
2506{\r
2507 EFI_IMAGE_DOS_HEADER *DosHeader;\r
2508 EFI_IMAGE_NT_HEADERS *NtHeader;\r
2509\r
2510 //\r
2511 // Verify input parameters\r
2512 //\r
2513 if (Pe32 == NULL) {\r
2514 return EFI_INVALID_PARAMETER;\r
2515 }\r
2516 //\r
2517 // First is the DOS header\r
2518 //\r
2519 DosHeader = (EFI_IMAGE_DOS_HEADER *) Pe32;\r
2520\r
2521 //\r
2522 // Verify DOS header is expected\r
2523 //\r
2524 if (DosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
2525 printf ("ERROR: Unknown magic number in the DOS header, 0x%04X.\n", DosHeader->e_magic);\r
2526 return EFI_UNSUPPORTED;\r
2527 }\r
2528 //\r
2529 // Immediately following is the NT header.\r
2530 //\r
2531 NtHeader = (EFI_IMAGE_NT_HEADERS *) ((UINTN) Pe32 + DosHeader->e_lfanew);\r
2532\r
2533 //\r
2534 // Verify NT header is expected\r
2535 //\r
2536 if (NtHeader->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
2537 printf ("ERROR: Unrecognized image signature 0x%08X.\n", NtHeader->Signature);\r
2538 return EFI_UNSUPPORTED;\r
2539 }\r
2540 //\r
2541 // Get output\r
2542 //\r
2543 *EntryPoint = NtHeader->OptionalHeader.AddressOfEntryPoint;\r
2544 *BaseOfCode = NtHeader->OptionalHeader.BaseOfCode;\r
2545 *MachineType = NtHeader->FileHeader.Machine;\r
2546\r
2547 //\r
2548 // Verify machine type is supported\r
2549 //\r
2550 if (*MachineType != EFI_IMAGE_MACHINE_IA32 && *MachineType != EFI_IMAGE_MACHINE_IA64 && *MachineType != EFI_IMAGE_MACHINE_X64 && *MachineType != EFI_IMAGE_MACHINE_EBC) {\r
2551 printf ("ERROR: Unrecognized machine type in the PE32 file.\n");\r
2552 return EFI_UNSUPPORTED;\r
2553 }\r
2554\r
2555 return EFI_SUCCESS;\r
2556}\r
2557//\r
2558// Exposed function implementations (prototypes are defined in GenFvImageLib.h)\r
2559//\r
2560EFI_STATUS\r
2561GenerateFvImage (\r
2562 IN CHAR8 *InfFileImage,\r
2563 IN UINTN InfFileSize,\r
2564 OUT UINT8 **FvImage,\r
2565 OUT UINTN *FvImageSize,\r
2566 OUT CHAR8 **FvFileName,\r
2567 OUT UINT8 **SymImage,\r
2568 OUT UINTN *SymImageSize,\r
2569 OUT CHAR8 **SymFileName\r
2570 )\r
2571/*++\r
2572\r
2573Routine Description:\r
2574\r
2575 This is the main function which will be called from application.\r
2576\r
2577Arguments:\r
2578\r
2579 InfFileImage Buffer containing the INF file contents.\r
2580 InfFileSize Size of the contents of the InfFileImage buffer.\r
2581 FvImage Pointer to the FV image created.\r
2582 FvImageSize Size of the FV image created and pointed to by FvImage.\r
2583 FvFileName Requested name for the FV file.\r
2584 SymImage Pointer to the Sym image created.\r
2585 SymImageSize Size of the Sym image created and pointed to by SymImage.\r
2586 SymFileName Requested name for the Sym file.\r
2587\r
2588Returns:\r
2589\r
2590 EFI_SUCCESS Function completed successfully.\r
2591 EFI_OUT_OF_RESOURCES Could not allocate required resources.\r
2592 EFI_ABORTED Error encountered.\r
2593 EFI_INVALID_PARAMETER A required parameter was NULL.\r
2594\r
2595--*/\r
2596{\r
2597 EFI_STATUS Status;\r
2598 MEMORY_FILE InfMemoryFile;\r
2599 MEMORY_FILE FvImageMemoryFile;\r
2600 MEMORY_FILE SymImageMemoryFile;\r
2601 FV_INFO FvInfo;\r
2602 UINTN Index;\r
2603 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;\r
2604 EFI_FFS_FILE_HEADER *VtfFileImage;\r
2605\r
2606 //\r
2607 // Check for invalid parameter\r
2608 //\r
2609 if (InfFileImage == NULL || FvImage == NULL || FvImageSize == NULL || FvFileName == NULL) {\r
2610 return EFI_INVALID_PARAMETER;\r
2611 }\r
2612 //\r
2613 // Initialize file structures\r
2614 //\r
2615 InfMemoryFile.FileImage = InfFileImage;\r
2616 InfMemoryFile.CurrentFilePointer = InfFileImage;\r
2617 InfMemoryFile.Eof = InfFileImage + InfFileSize;\r
2618\r
2619 //\r
2620 // Parse the FV inf file for header information\r
2621 //\r
2622 Status = ParseFvInf (&InfMemoryFile, &FvInfo);\r
2623 if (EFI_ERROR (Status)) {\r
2624 printf ("ERROR: Could not parse the input INF file.\n");\r
2625 return EFI_ABORTED;\r
2626 }\r
2627 //\r
2628 // Update the file name return values\r
2629 //\r
2630 strcpy (*FvFileName, FvInfo.FvName);\r
2631 strcpy (*SymFileName, FvInfo.SymName);\r
2632\r
2633 //\r
2634 // Calculate the FV size\r
2635 //\r
2636 *FvImageSize = FvInfo.Size;\r
2637\r
2638 //\r
2639 // Allocate the FV\r
2640 //\r
2641 *FvImage = malloc (*FvImageSize);\r
2642 if (*FvImage == NULL) {\r
2643 return EFI_OUT_OF_RESOURCES;\r
2644 }\r
2645 //\r
2646 // Allocate space for symbol file storage\r
2647 //\r
2648 *SymImage = malloc (SYMBOL_FILE_SIZE);\r
2649 if (*SymImage == NULL) {\r
2650 return EFI_OUT_OF_RESOURCES;\r
2651 }\r
2652 //\r
2653 // Initialize the FV to the erase polarity\r
2654 //\r
2655 if (FvInfo.FvAttributes & EFI_FVB_ERASE_POLARITY) {\r
2656 memset (*FvImage, -1, *FvImageSize);\r
2657 } else {\r
2658 memset (*FvImage, 0, *FvImageSize);\r
2659 }\r
2660 //\r
2661 // Initialize FV header\r
2662 //\r
2663 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) *FvImage;\r
2664\r
2665 //\r
2666 // Initialize the zero vector to all zeros.\r
2667 //\r
2668 memset (FvHeader->ZeroVector, 0, 16);\r
2669\r
2670 //\r
2671 // Copy the FFS GUID\r
2672 //\r
2673 memcpy (&FvHeader->FileSystemGuid, &FvInfo.FvGuid, sizeof (EFI_GUID));\r
2674\r
2675 FvHeader->FvLength = *FvImageSize;\r
2676 FvHeader->Signature = EFI_FVH_SIGNATURE;\r
2677 FvHeader->Attributes = FvInfo.FvAttributes;\r
2678 FvHeader->Revision = EFI_FVH_REVISION;\r
2679 FvHeader->Reserved[0] = 0;\r
2680 FvHeader->Reserved[1] = 0;\r
2681 FvHeader->Reserved[2] = 0;\r
2682\r
2683 //\r
2684 // Copy firmware block map\r
2685 //\r
2686 for (Index = 0; FvInfo.FvBlocks[Index].NumBlocks != 0; Index++) {\r
2687 FvHeader->FvBlockMap[Index].NumBlocks = FvInfo.FvBlocks[Index].NumBlocks;\r
2688 FvHeader->FvBlockMap[Index].BlockLength = FvInfo.FvBlocks[Index].BlockLength;\r
2689 }\r
2690 //\r
2691 // Add block map terminator\r
2692 //\r
2693 FvHeader->FvBlockMap[Index].NumBlocks = 0;\r
2694 FvHeader->FvBlockMap[Index].BlockLength = 0;\r
2695\r
2696 //\r
2697 // Complete the header\r
2698 //\r
2699 FvHeader->HeaderLength = (UINT16) (((UINTN) &(FvHeader->FvBlockMap[Index + 1])) - (UINTN) *FvImage);\r
2700 FvHeader->Checksum = 0;\r
2701 FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));\r
2702\r
2703 //\r
2704 // If there is no FFS file, find and generate each components of the FV\r
2705 //\r
2706 if (FvInfo.FvFiles[0][0] == 0) {\r
2707 Status = GenNonFFSFv (*FvImage, &FvInfo);\r
2708 if (EFI_ERROR (Status)) {\r
2709 printf ("ERROR: Could not generate NonFFS FV.\n");\r
2710 free (*FvImage);\r
2711 return EFI_ABORTED;\r
2712 }\r
2713\r
2714 return EFI_SUCCESS;\r
2715 }\r
2716 //\r
2717 // Initialize our "file" view of the buffer\r
2718 //\r
2719 FvImageMemoryFile.FileImage = *FvImage;\r
2720 FvImageMemoryFile.CurrentFilePointer = *FvImage + FvHeader->HeaderLength;\r
2721 FvImageMemoryFile.Eof = *FvImage +*FvImageSize;\r
2722\r
2723 //\r
2724 // Initialize our "file" view of the symbol file.\r
2725 //\r
2726 SymImageMemoryFile.FileImage = *SymImage;\r
2727 SymImageMemoryFile.CurrentFilePointer = *SymImage;\r
2728 SymImageMemoryFile.Eof = *FvImage + SYMBOL_FILE_SIZE;\r
2729\r
2730 //\r
2731 // Initialize the FV library.\r
2732 //\r
2733 InitializeFvLib (FvImageMemoryFile.FileImage, FvInfo.Size);\r
2734\r
2735 //\r
2736 // Files start on 8 byte alignments, so move to the next 8 byte aligned\r
2737 // address. For now, just assert if it isn't. Currently FV header is\r
2738 // always a multiple of 8 bytes.\r
2739 // BUGBUG: Handle this better\r
2740 //\r
2741 assert ((((UINTN) FvImageMemoryFile.CurrentFilePointer) % 8) == 0);\r
2742\r
2743 //\r
2744 // Initialize the VTF file address.\r
2745 //\r
2746 VtfFileImage = (EFI_FFS_FILE_HEADER *) FvImageMemoryFile.Eof;\r
2747\r
2748 //\r
2749 // Add files to FV\r
2750 //\r
2751 for (Index = 0; FvInfo.FvFiles[Index][0] != 0; Index++) {\r
2752 //\r
2753 // Add the file\r
2754 //\r
2755 Status = AddFile (&FvImageMemoryFile, &FvInfo, Index, &VtfFileImage, &SymImageMemoryFile);\r
2756\r
2757 //\r
2758 // Exit if error detected while adding the file\r
2759 //\r
2760 if (EFI_ERROR (Status)) {\r
2761 printf ("ERROR: Could not add file %s.\n", FvInfo.FvFiles[Index]);\r
2762 free (*FvImage);\r
2763 return EFI_ABORTED;\r
2764 }\r
2765 }\r
2766 //\r
2767 // If there is a VTF file, some special actions need to occur.\r
2768 //\r
2769 if ((UINTN) VtfFileImage != (UINTN) FvImageMemoryFile.Eof) {\r
2770 //\r
2771 // Pad from the end of the last file to the beginning of the VTF file.\r
2772 //\r
2773 Status = PadFvImage (&FvImageMemoryFile, VtfFileImage);\r
2774 if (EFI_ERROR (Status)) {\r
2775 printf ("ERROR: Could not create the pad file between the last file and the VTF file.\n");\r
2776 free (*FvImage);\r
2777 return EFI_ABORTED;\r
2778 }\r
2779 //\r
2780 // Update reset vector (SALE_ENTRY for IPF)\r
2781 // Now for IA32 and IA64 platform, the fv which has bsf file must have the \r
2782 // EndAddress of 0xFFFFFFFF. Thus, only this type fv needs to update the \r
2783 // reset vector. If the PEI Core is found, the VTF file will probably get \r
2784 // corrupted by updating the entry point. \r
2785 //\r
2786 if ((FvInfo.BaseAddress + FvInfo.Size) == FV_IMAGES_TOP_ADDRESS) { \r
2787 Status = UpdateResetVector (&FvImageMemoryFile, &FvInfo, VtfFileImage);\r
2788 if (EFI_ERROR(Status)) { \r
2789 printf ("ERROR: Could not update the reset vector.\n"); \r
2790 free (*FvImage); \r
2791 return EFI_ABORTED; \r
2792 } \r
2793 }\r
2794 } \r
2795 //\r
2796 // Determine final Sym file size\r
2797 //\r
2798 *SymImageSize = SymImageMemoryFile.CurrentFilePointer - SymImageMemoryFile.FileImage;\r
2799\r
2800 return EFI_SUCCESS;\r
2801}\r
2802\r
2803EFI_STATUS\r
2804UpdatePeiCoreEntryInFit (\r
2805 IN FIT_TABLE *FitTablePtr,\r
2806 IN UINT64 PeiCorePhysicalAddress\r
2807 )\r
2808/*++\r
2809\r
2810Routine Description:\r
2811\r
2812 This function is used to update the Pei Core address in FIT, this can be used by Sec core to pass control from\r
2813 Sec to Pei Core\r
2814\r
2815Arguments:\r
2816\r
2817 FitTablePtr - The pointer of FIT_TABLE.\r
2818 PeiCorePhysicalAddress - The address of Pei Core entry.\r
2819\r
2820Returns:\r
2821\r
2822 EFI_SUCCESS - The PEI_CORE FIT entry was updated successfully.\r
2823 EFI_NOT_FOUND - Not found the PEI_CORE FIT entry.\r
2824\r
2825--*/\r
2826{\r
2827 FIT_TABLE *TmpFitPtr;\r
2828 UINTN Index;\r
2829 UINTN NumFitComponents;\r
2830\r
2831 TmpFitPtr = FitTablePtr;\r
2832 NumFitComponents = TmpFitPtr->CompSize;\r
2833\r
2834 for (Index = 0; Index < NumFitComponents; Index++) {\r
2835 if ((TmpFitPtr->CvAndType & FIT_TYPE_MASK) == COMP_TYPE_FIT_PEICORE) {\r
2836 TmpFitPtr->CompAddress = PeiCorePhysicalAddress;\r
2837 return EFI_SUCCESS;\r
2838 }\r
2839\r
2840 TmpFitPtr++;\r
2841 }\r
2842\r
2843 return EFI_NOT_FOUND;\r
2844}\r
2845\r
2846VOID\r
2847UpdateFitCheckSum (\r
2848 IN FIT_TABLE *FitTablePtr\r
2849 )\r
2850/*++\r
2851\r
2852Routine Description:\r
2853\r
2854 This function is used to update the checksum for FIT.\r
2855\r
2856\r
2857Arguments:\r
2858\r
2859 FitTablePtr - The pointer of FIT_TABLE.\r
2860\r
2861Returns:\r
2862\r
2863 None.\r
2864\r
2865--*/\r
2866{\r
2867 if ((FitTablePtr->CvAndType & CHECKSUM_BIT_MASK) >> 7) {\r
2868 FitTablePtr->CheckSum = 0;\r
2869 FitTablePtr->CheckSum = CalculateChecksum8 ((UINT8 *) FitTablePtr, FitTablePtr->CompSize * 16);\r
2870 }\r
2871}\r