]> git.proxmox.com Git - mirror_edk2.git/blame - EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageLib.c
Add in the 1st version of ECP.
[mirror_edk2.git] / EdkCompatibilityPkg / Sample / Tools / Source / GenFvImage / GenFvImageLib.c
CommitLineData
3eb9473e 1/*++\r
2\r
3Copyright (c) 2004 - 2007, Intel Corporation \r
4All rights reserved. This 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 //\r
972 // Update the number of blocks\r
973 //\r
974 Status = AsciiStringToUint64 (Value, FALSE, &Value64);\r
975 if (EFI_ERROR (Status)) {\r
976 Error (NULL, 0, 0, Value, "invalid value for %s", EFI_NUM_BLOCKS_STRING);\r
977 return EFI_ABORTED;\r
978 }\r
979\r
980 FvInfo->FvBlocks[Index].NumBlocks = (UINT32) Value64;\r
981 } else {\r
982 //\r
983 // If there is no number of blocks, but there is a size, then we have a mismatched pair\r
984 // and should return an error.\r
985 //\r
986 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_BLOCK_SIZE_STRING, Index, Value);\r
987 if (!EFI_ERROR (Status)) {\r
988 Error (NULL, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING);\r
989 return EFI_ABORTED;\r
990 } else {\r
991 //\r
992 // We are done\r
993 //\r
994 break;\r
995 }\r
996 }\r
997 //\r
998 // Read the size of blocks\r
999 //\r
1000 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_BLOCK_SIZE_STRING, Index, Value);\r
1001\r
1002 if (Status == EFI_SUCCESS) {\r
1003 //\r
1004 // Update the number of blocks\r
1005 //\r
1006 Status = AsciiStringToUint64 (Value, FALSE, &Value64);\r
1007 if (EFI_ERROR (Status)) {\r
1008 Error (NULL, 0, 0, Value, "invalid value specified for %s", EFI_BLOCK_SIZE_STRING);\r
1009 return EFI_ABORTED;\r
1010 }\r
1011\r
1012 FvInfo->FvBlocks[Index].BlockLength = (UINT32) Value64;\r
1013 } else {\r
1014 //\r
1015 // There is a number of blocks, but there is no size, so we have a mismatched pair\r
1016 // and should return an error.\r
1017 //\r
1018 Error (NULL, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING);\r
1019 return EFI_ABORTED;\r
1020 }\r
1021 }\r
1022 //\r
1023 // Read files\r
1024 //\r
1025 for (Index = 0; Index < MAX_NUMBER_OF_FILES_IN_FV; Index++) {\r
1026 //\r
1027 // Read the number of blocks\r
1028 //\r
1029 Status = FindToken (InfFile, FILES_SECTION_STRING, EFI_FILE_NAME_STRING, Index, Value);\r
1030\r
1031 if (Status == EFI_SUCCESS) {\r
1032 //\r
1033 // Add the file\r
1034 //\r
1035 strcpy (FvInfo->FvFiles[Index], Value);\r
1036 } else {\r
1037 break;\r
1038 }\r
1039 }\r
1040\r
1041 if (FindSection (InfFile, COMPONENT_SECTION_STRING)) {\r
1042 Index = 0;\r
1043 //\r
1044 // Read component FV_VARIABLE\r
1045 //\r
1046 Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_VARIABLE_STRING, 0, Value);\r
1047\r
1048 if (Status == EFI_SUCCESS) {\r
1049 //\r
1050 // Add the component\r
1051 //\r
1052 strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_VARIABLE_STRING);\r
1053 Status = AsciiStringToUint64 (Value, FALSE, &Value64);\r
1054 if (EFI_ERROR (Status)) {\r
1055 printf ("ERROR: %s is not a valid integer.\n", EFI_NV_VARIABLE_STRING);\r
1056 return EFI_ABORTED;\r
1057 }\r
1058\r
1059 FvInfo->FvComponents[Index].Size = (UINTN) Value64;\r
1060 } else {\r
1061 printf ("WARNING: Could not read %s.\n", EFI_NV_VARIABLE_STRING);\r
1062 }\r
1063\r
1064 Index++;\r
1065 //\r
1066 // Read component FV_EVENT_LOG\r
1067 //\r
1068 Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_EVENT_LOG_STRING, 0, Value);\r
1069\r
1070 if (Status == EFI_SUCCESS) {\r
1071 //\r
1072 // Add the component\r
1073 //\r
1074 strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_EVENT_LOG_STRING);\r
1075 Status = AsciiStringToUint64 (Value, FALSE, &Value64);\r
1076 if (EFI_ERROR (Status)) {\r
1077 printf ("ERROR: %s is not a valid integer.\n", EFI_NV_EVENT_LOG_STRING);\r
1078 return EFI_ABORTED;\r
1079 }\r
1080\r
1081 FvInfo->FvComponents[Index].Size = (UINTN) Value64;\r
1082 } else {\r
1083 printf ("WARNING: Could not read %s.\n", EFI_NV_EVENT_LOG_STRING);\r
1084 }\r
1085\r
1086 Index++;\r
1087 //\r
1088 // Read component FV_FTW_WORKING\r
1089 //\r
1090 Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_FTW_WORKING_STRING, 0, Value);\r
1091\r
1092 if (Status == EFI_SUCCESS) {\r
1093 //\r
1094 // Add the component\r
1095 //\r
1096 strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_WORKING_STRING);\r
1097 Status = AsciiStringToUint64 (Value, FALSE, &Value64);\r
1098 if (EFI_ERROR (Status)) {\r
1099 printf ("ERROR: %s is not a valid integer.\n", EFI_NV_FTW_WORKING_STRING);\r
1100 return EFI_ABORTED;\r
1101 }\r
1102\r
1103 FvInfo->FvComponents[Index].Size = (UINTN) Value64;\r
1104 } else {\r
1105 printf ("WARNING: Could not read %s.\n", EFI_NV_FTW_WORKING_STRING);\r
1106 }\r
1107\r
1108 Index++;\r
1109 //\r
1110 // Read component FV_FTW_SPARE\r
1111 //\r
1112 Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_FTW_SPARE_STRING, 0, Value);\r
1113\r
1114 if (Status == EFI_SUCCESS) {\r
1115 //\r
1116 // Add the component\r
1117 //\r
1118 strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_SPARE_STRING);\r
1119 Status = AsciiStringToUint64 (Value, FALSE, &Value64);\r
1120 if (EFI_ERROR (Status)) {\r
1121 printf ("ERROR: %s is not a valid integer.\n", EFI_NV_FTW_SPARE_STRING);\r
1122 return EFI_ABORTED;\r
1123 }\r
1124\r
1125 FvInfo->FvComponents[Index].Size = (UINTN) Value64;\r
1126 } else {\r
1127 printf ("WARNING: Could not read %s.\n", EFI_NV_FTW_SPARE_STRING);\r
1128 }\r
1129 }\r
1130 //\r
1131 // Compute size for easy access later\r
1132 //\r
1133 FvInfo->Size = 0;\r
1134 for (Index = 0; FvInfo->FvBlocks[Index].NumBlocks; Index++) {\r
1135 FvInfo->Size += FvInfo->FvBlocks[Index].NumBlocks * FvInfo->FvBlocks[Index].BlockLength;\r
1136 }\r
1137\r
1138 return EFI_SUCCESS;\r
1139}\r
1140\r
1141VOID\r
1142UpdateFfsFileState (\r
1143 IN EFI_FFS_FILE_HEADER *FfsFile,\r
1144 IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader\r
1145 )\r
1146/*++\r
1147\r
1148Routine Description:\r
1149\r
1150 This function changes the FFS file attributes based on the erase polarity\r
1151 of the FV.\r
1152\r
1153Arguments:\r
1154\r
1155 FfsFile File header.\r
1156 FvHeader FV header.\r
1157\r
1158Returns:\r
1159\r
1160 None\r
1161\r
1162--*/\r
1163{\r
1164 if (FvHeader->Attributes & EFI_FVB_ERASE_POLARITY) {\r
1165 FfsFile->State = (UINT8)~(FfsFile->State);\r
1166 }\r
1167}\r
1168\r
1169EFI_STATUS\r
1170ReadFfsAlignment (\r
1171 IN EFI_FFS_FILE_HEADER *FfsFile,\r
1172 IN OUT UINT32 *Alignment\r
1173 )\r
1174/*++\r
1175\r
1176Routine Description:\r
1177\r
1178 This function determines the alignment of the FFS input file from the file\r
1179 attributes.\r
1180\r
1181Arguments:\r
1182\r
1183 FfsFile FFS file to parse\r
1184 Alignment The minimum required alignment of the FFS file, in bytes\r
1185\r
1186Returns:\r
1187\r
1188 EFI_SUCCESS The function completed successfully.\r
1189 EFI_INVALID_PARAMETER One of the input parameters was invalid.\r
1190 EFI_ABORTED An error occurred.\r
1191\r
1192--*/\r
1193{\r
1194 //\r
1195 // Verify input parameters.\r
1196 //\r
1197 if (FfsFile == NULL || Alignment == NULL) {\r
1198 return EFI_INVALID_PARAMETER;\r
1199 }\r
1200\r
1201 switch ((FfsFile->Attributes >> 3) & 0x07) {\r
1202\r
1203 case 0:\r
1204 //\r
1205 // 1 byte alignment\r
1206 //\r
1207 *Alignment = (1 << 0);\r
1208 break;\r
1209\r
1210 case 1:\r
1211 //\r
1212 // 16 byte alignment\r
1213 //\r
1214 *Alignment = (1 << 4);\r
1215 break;\r
1216\r
1217 case 2:\r
1218 //\r
1219 // 128 byte alignment\r
1220 //\r
1221 *Alignment = (1 << 7);\r
1222 break;\r
1223\r
1224 case 3:\r
1225 //\r
1226 // 512 byte alignment\r
1227 //\r
1228 *Alignment = (1 << 9);\r
1229 break;\r
1230\r
1231 case 4:\r
1232 //\r
1233 // 1K byte alignment\r
1234 //\r
1235 *Alignment = (1 << 10);\r
1236 break;\r
1237\r
1238 case 5:\r
1239 //\r
1240 // 4K byte alignment\r
1241 //\r
1242 *Alignment = (1 << 12);\r
1243 break;\r
1244\r
1245 case 6:\r
1246 //\r
1247 // 32K byte alignment\r
1248 //\r
1249 *Alignment = (1 << 15);\r
1250 break;\r
1251\r
1252 case 7:\r
1253 //\r
1254 // 64K byte alignment\r
1255 //\r
1256 *Alignment = (1 << 16);\r
1257 break;\r
1258\r
1259 default:\r
1260 Error (NULL, 0, 0, "nvalid file attribute calculated, this is most likely a utility error", NULL);\r
1261 return EFI_ABORTED;\r
1262 }\r
1263\r
1264 return EFI_SUCCESS;\r
1265}\r
1266\r
1267EFI_STATUS\r
1268AddPadFile (\r
1269 IN OUT MEMORY_FILE *FvImage,\r
1270 IN UINT32 DataAlignment\r
1271 )\r
1272/*++\r
1273\r
1274Routine Description:\r
1275\r
1276 This function adds a pad file to the FV image if it required to align the\r
1277 data of the next file.\r
1278\r
1279Arguments:\r
1280\r
1281 FvImage The memory image of the FV to add it to. The current offset\r
1282 must be valid.\r
1283 DataAlignment The data alignment of the next FFS file.\r
1284\r
1285Returns:\r
1286\r
1287 EFI_SUCCESS The function completed successfully.\r
1288 EFI_INVALID_PARAMETER One of the input parameters was invalid.\r
1289 EFI_OUT_OF_RESOURCES Insufficient resources exist in the FV to complete\r
1290 the pad file add.\r
1291\r
1292--*/\r
1293{\r
1294 EFI_FFS_FILE_HEADER *PadFile;\r
1295 UUID PadFileGuid;\r
1296 UINTN PadFileSize;\r
1297\r
1298 //\r
1299 // Verify input parameters.\r
1300 //\r
1301 if (FvImage == NULL) {\r
1302 return EFI_INVALID_PARAMETER;\r
1303 }\r
1304 //\r
1305 // Basic assumption is we start from an 8 byte aligned address\r
1306 // and our file header is a multiple of 8 bytes\r
1307 //\r
1308 assert ((UINTN) FvImage->CurrentFilePointer % 8 == 0);\r
1309 assert (sizeof (EFI_FFS_FILE_HEADER) % 8 == 0);\r
1310\r
1311 //\r
1312 // Check if a pad file is necessary\r
1313 //\r
1314 if (((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + sizeof (EFI_FFS_FILE_HEADER)) % DataAlignment == 0) {\r
1315 return EFI_SUCCESS;\r
1316 }\r
1317 //\r
1318 // Write pad file header\r
1319 //\r
1320 PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer;\r
1321\r
1322 //\r
1323 // Verify that we have enough space for the file header\r
1324 //\r
1325 if ((UINTN) (PadFile + sizeof (EFI_FFS_FILE_HEADER)) >= (UINTN) FvImage->Eof) {\r
1326 return EFI_OUT_OF_RESOURCES;\r
1327 }\r
1328\r
1329 UuidCreate (&PadFileGuid);\r
1330 memset (PadFile, 0, sizeof (EFI_FFS_FILE_HEADER));\r
1331 memcpy (&PadFile->Name, &PadFileGuid, sizeof (EFI_GUID));\r
1332 PadFile->Type = EFI_FV_FILETYPE_FFS_PAD;\r
1333 PadFile->Attributes = 0;\r
1334\r
1335 //\r
1336 // Calculate the pad file size\r
1337 //\r
1338 //\r
1339 // This is the earliest possible valid offset (current plus pad file header\r
1340 // plus the next file header)\r
1341 //\r
1342 PadFileSize = (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + (sizeof (EFI_FFS_FILE_HEADER) * 2);\r
1343\r
1344 //\r
1345 // Add whatever it takes to get to the next aligned address\r
1346 //\r
1347 while ((PadFileSize % DataAlignment) != 0) {\r
1348 PadFileSize++;\r
1349 }\r
1350 //\r
1351 // Subtract the next file header size\r
1352 //\r
1353 PadFileSize -= sizeof (EFI_FFS_FILE_HEADER);\r
1354\r
1355 //\r
1356 // Subtract the starting offset to get size\r
1357 //\r
1358 PadFileSize -= (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage;\r
1359\r
1360 //\r
1361 // Write pad file size (calculated size minus next file header size)\r
1362 //\r
1363 PadFile->Size[0] = (UINT8) (PadFileSize & 0xFF);\r
1364 PadFile->Size[1] = (UINT8) ((PadFileSize >> 8) & 0xFF);\r
1365 PadFile->Size[2] = (UINT8) ((PadFileSize >> 16) & 0xFF);\r
1366\r
1367 //\r
1368 // Fill in checksums and state, they must be 0 for checksumming.\r
1369 //\r
1370 PadFile->IntegrityCheck.Checksum.Header = 0;\r
1371 PadFile->IntegrityCheck.Checksum.File = 0;\r
1372 PadFile->State = 0;\r
1373 PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER));\r
1374 if (PadFile->Attributes & FFS_ATTRIB_CHECKSUM) {\r
1375 PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) PadFile, PadFileSize);\r
1376 } else {\r
1377 PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
1378 }\r
1379\r
1380 PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;\r
1381 UpdateFfsFileState (\r
1382 (EFI_FFS_FILE_HEADER *) PadFile,\r
1383 (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage\r
1384 );\r
1385\r
1386 //\r
1387 // Verify that we have enough space (including the padding\r
1388 //\r
1389 if ((UINTN) (PadFile + sizeof (EFI_FFS_FILE_HEADER)) >= (UINTN) FvImage->Eof) {\r
1390 return EFI_OUT_OF_RESOURCES;\r
1391 }\r
1392 //\r
1393 // Update the current FV pointer\r
1394 //\r
1395 FvImage->CurrentFilePointer += PadFileSize;\r
1396\r
1397 return EFI_SUCCESS;\r
1398}\r
1399\r
1400BOOLEAN\r
1401IsVtfFile (\r
1402 IN EFI_FFS_FILE_HEADER *FileBuffer\r
1403 )\r
1404/*++\r
1405\r
1406Routine Description:\r
1407\r
1408 This function checks the header to validate if it is a VTF file\r
1409\r
1410Arguments:\r
1411\r
1412 FileBuffer Buffer in which content of a file has been read.\r
1413\r
1414Returns:\r
1415\r
1416 TRUE If this is a VTF file\r
1417 FALSE If this is not a VTF file\r
1418\r
1419--*/\r
1420{\r
1421 EFI_GUID VtfGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;\r
1422 if (!memcmp (&FileBuffer->Name, &VtfGuid, sizeof (EFI_GUID))) {\r
1423 return TRUE;\r
1424 } else {\r
1425 return FALSE;\r
1426 }\r
1427}\r
1428\r
1429EFI_STATUS\r
1430FfsRebaseImageRead (\r
1431 IN VOID *FileHandle,\r
1432 IN UINTN FileOffset,\r
1433 IN OUT UINT32 *ReadSize,\r
1434 OUT VOID *Buffer\r
1435 )\r
1436/*++\r
1437\r
1438Routine Description:\r
1439\r
1440 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file\r
1441\r
1442Arguments:\r
1443\r
1444 FileHandle - The handle to the PE/COFF file\r
1445\r
1446 FileOffset - The offset, in bytes, into the file to read\r
1447\r
1448 ReadSize - The number of bytes to read from the file starting at FileOffset\r
1449\r
1450 Buffer - A pointer to the buffer to read the data into.\r
1451\r
1452Returns:\r
1453\r
1454 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset\r
1455\r
1456--*/\r
1457{\r
1458 CHAR8 *Destination8;\r
1459 CHAR8 *Source8;\r
1460 UINT32 Length;\r
1461\r
1462 Destination8 = Buffer;\r
1463 Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);\r
1464 Length = *ReadSize;\r
1465 while (Length--) {\r
1466 *(Destination8++) = *(Source8++);\r
1467 }\r
1468\r
1469 return EFI_SUCCESS;\r
1470}\r
1471\r
1472EFI_STATUS\r
1473RebaseFfsFile (\r
1474 IN OUT EFI_FFS_FILE_HEADER *FfsFile,\r
1475 IN EFI_PHYSICAL_ADDRESS BaseAddress\r
1476 )\r
1477/*++\r
1478\r
1479Routine Description:\r
1480\r
1481 This function determines if a file is XIP and should be rebased. It will\r
1482 rebase any PE32 sections found in the file using the base address.\r
1483\r
1484Arguments:\r
1485\r
1486 FfsFile A pointer to Ffs file image.\r
1487 BaseAddress The base address to use for rebasing the file image.\r
1488\r
1489Returns:\r
1490\r
1491 EFI_SUCCESS The image was properly rebased.\r
1492 EFI_INVALID_PARAMETER An input parameter is invalid.\r
1493 EFI_ABORTED An error occurred while rebasing the input file image.\r
1494 EFI_OUT_OF_RESOURCES Could not allocate a required resource.\r
1495\r
1496--*/\r
1497{\r
1498 EFI_STATUS Status;\r
1499 EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
1500 UINTN MemoryImagePointer;\r
1501 UINTN MemoryImagePointerAligned;\r
1502\r
1503 EFI_PHYSICAL_ADDRESS ImageAddress;\r
1504 UINT64 ImageSize;\r
1505 EFI_PHYSICAL_ADDRESS EntryPoint;\r
1506\r
1507 UINT32 Pe32FileSize;\r
1508 UINT32 NewPe32BaseAddress;\r
1509\r
1510 UINTN Index;\r
1511 EFI_FILE_SECTION_POINTER CurrentPe32Section;\r
1512 UINT8 FileGuidString[80];\r
1513\r
1514 //\r
1515 // Verify input parameters\r
1516 //\r
1517 if (FfsFile == NULL) {\r
1518 return EFI_INVALID_PARAMETER;\r
1519 }\r
1520 //\r
1521 // Convert the GUID to a string so we can at least report which file\r
1522 // if we find an error.\r
1523 //\r
1524 PrintGuidToBuffer (&FfsFile->Name, FileGuidString, sizeof (FileGuidString), TRUE);\r
1525\r
1526 //\r
1527 // Do some nominal checks on the file, then check for XIP.\r
1528 //\r
1529 Status = VerifyFfsFile (FfsFile);\r
1530 if (EFI_ERROR (Status)) {\r
1531 Error (NULL, 0, 0, "invalid FFS file", FileGuidString);\r
1532 return EFI_INVALID_PARAMETER;\r
1533 }\r
1534\r
1535 if (FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE &&\r
1536 FfsFile->Type != EFI_FV_FILETYPE_PEI_CORE &&\r
1537 FfsFile->Type != EFI_FV_FILETYPE_PEIM\r
1538 ) {\r
1539 //\r
1540 // File is not XIP, so don't rebase\r
1541 //\r
1542 return EFI_SUCCESS;\r
1543 }\r
1544 //\r
1545 // Rebase each PE32 section\r
1546 //\r
1547 for (Index = 1;; Index++) {\r
1548 Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, Index, &CurrentPe32Section);\r
1549 if (EFI_ERROR (Status)) {\r
1550 break;\r
1551 }\r
1552 //\r
1553 // Calculate the PE32 base address, the FFS file base plus the offset of the PE32 section\r
1554 //\r
1555 NewPe32BaseAddress = ((UINT32) BaseAddress) + ((UINTN) CurrentPe32Section.Pe32Section - (UINTN) FfsFile);\r
1556\r
1557 //\r
1558 // Initialize context\r
1559 //\r
1560 memset (&ImageContext, 0, sizeof (ImageContext));\r
1561 ImageContext.Handle = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION));\r
1562 ImageContext.ImageRead = (EFI_PEI_PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;\r
1563\r
1564 Status = mPeCoffLoader.GetImageInfo (&mPeCoffLoader, &ImageContext);\r
1565\r
1566 if (EFI_ERROR (Status)) {\r
1567 Error (NULL, 0, 0, "GetImageInfo() failed", FileGuidString);\r
1568 return Status;\r
1569 }\r
1570 //\r
1571 // Allocate a buffer for the image to be loaded into.\r
1572 //\r
1573 Pe32FileSize = GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size);\r
1574 MemoryImagePointer = (UINTN) (malloc (Pe32FileSize + 0x1000));\r
1575 MemoryImagePointerAligned = (MemoryImagePointer + 0x0FFF) & (-1 << 12);\r
1576 if (MemoryImagePointerAligned == 0) {\r
1577 Error (NULL, 0, 0, "memory allocation failure", NULL);\r
1578 return EFI_OUT_OF_RESOURCES;\r
1579 }\r
1580\r
1581 //\r
1582 // bugbug\r
1583 //\r
1584 ImageContext.ImageAddress = MemoryImagePointerAligned;\r
1585 Status = mPeCoffLoader.LoadImage (&mPeCoffLoader, &ImageContext);\r
1586 if (EFI_ERROR (Status)) {\r
1587 Error (NULL, 0, 0, "LoadImage() failure", FileGuidString);\r
1588 free ((VOID *) MemoryImagePointer);\r
1589 return Status;\r
1590 }\r
1591\r
1592 Status = mPeCoffLoader.RelocateImage (&mPeCoffLoader, &ImageContext);\r
1593 if (EFI_ERROR (Status)) {\r
1594 Error (NULL, 0, 0, "RelocateImage() failure", FileGuidString);\r
1595 free ((VOID *) MemoryImagePointer);\r
1596 return Status;\r
1597 }\r
1598\r
1599 ImageAddress = ImageContext.ImageAddress;\r
1600 ImageSize = ImageContext.ImageSize;\r
1601 EntryPoint = ImageContext.EntryPoint;\r
1602\r
1603 if (ImageSize > Pe32FileSize) {\r
1604 Error (\r
1605 NULL,\r
1606 0,\r
1607 0,\r
1608 "rebased PE32 is larger than original PE32 image",\r
1609 "0x%X > 0x%X on file %s",\r
1610 ImageSize,\r
1611 Pe32FileSize,\r
1612 FileGuidString\r
1613 );\r
1614 free ((VOID *) MemoryImagePointer);\r
1615 return EFI_ABORTED;\r
1616 }\r
1617\r
1618 memcpy (CurrentPe32Section.Pe32Section, (VOID *) MemoryImagePointerAligned, Pe32FileSize);\r
1619\r
1620 free ((VOID *) MemoryImagePointer);\r
1621 }\r
1622 //\r
1623 // the above for loop will always exit with EFI_NOT_FOUND if it completes\r
1624 // normally. If Index == 1 at exit, then no PE32 sections were found. If it\r
1625 // exits with any other error code, then something broke...\r
1626 //\r
1627 if (Status != EFI_NOT_FOUND) {\r
1628 Error (NULL, 0, 0, "failed to parse PE32 section", FileGuidString);\r
1629 return Status;\r
1630 }\r
1631\r
1632 return EFI_SUCCESS;\r
1633}\r
1634\r
1635EFI_STATUS\r
1636AddSymFile (\r
1637 IN UINT64 BaseAddress,\r
1638 IN EFI_FFS_FILE_HEADER *FfsFile,\r
1639 IN OUT MEMORY_FILE *SymImage,\r
1640 IN CHAR8 *SourceFileName\r
1641 )\r
1642/*++\r
1643\r
1644Routine Description:\r
1645\r
1646 This function adds the SYM tokens in the source file to the destination file.\r
1647 The SYM tokens are updated to reflect the base address.\r
1648\r
1649Arguments:\r
1650\r
1651 BaseAddress The base address for the new SYM tokens.\r
1652 FfsFile Pointer to the beginning of the FFS file in question.\r
1653 SymImage The memory file to update with symbol information.\r
1654 SourceFileName The source file.\r
1655\r
1656Returns:\r
1657\r
1658 EFI_SUCCESS The function completed successfully.\r
1659 EFI_INVALID_PARAMETER One of the input parameters was invalid.\r
1660 EFI_ABORTED An error occurred.\r
1661\r
1662--*/\r
1663{\r
1664 FILE *SourceFile;\r
1665\r
1666 CHAR8 Buffer[_MAX_PATH];\r
1667 CHAR8 Type[_MAX_PATH];\r
1668 CHAR8 Address[_MAX_PATH];\r
1669 CHAR8 Section[_MAX_PATH];\r
1670 CHAR8 Token[_MAX_PATH];\r
1671 CHAR8 SymFileName[_MAX_PATH];\r
1672 CHAR8 CodeModuleName[_MAX_PATH];\r
1673 CHAR8 *Ptr;\r
1674\r
1675 UINT64 TokenAddress;\r
1676\r
1677 EFI_STATUS Status;\r
1678 EFI_FILE_SECTION_POINTER Pe32Section;\r
1679 UINT32 EntryPoint;\r
1680 UINT32 BaseOfCode;\r
1681 UINT16 MachineType;\r
1682\r
1683 //\r
1684 // Verify input parameters.\r
1685 //\r
1686 if (BaseAddress == 0 || FfsFile == NULL || SymImage == NULL || SourceFileName == NULL) {\r
1687 Error (NULL, 0, 0, "invalid parameter passed to AddSymFile()", NULL);\r
1688 return EFI_INVALID_PARAMETER;\r
1689 }\r
1690 //\r
1691 // Check if we want to add this file\r
1692 //\r
1693 //\r
1694 // Get the file name\r
1695 //\r
1696 strcpy (Buffer, SourceFileName);\r
1697\r
1698 //\r
1699 // Copy the file name for the path of the sym file and truncate the name portion.\r
1700 //\r
1701 strcpy (SymFileName, Buffer);\r
1702 Ptr = strrchr (SymFileName, '\\');\r
1703 assert (Ptr);\r
1704 Ptr[0] = 0;\r
1705\r
1706 //\r
1707 // Find the file extension and make it lower case\r
1708 //\r
1709 Ptr = strrchr (SymFileName, '.');\r
1710 if (Ptr != NULL) {\r
1711 _strlwr (Ptr);\r
1712 }\r
1713 //\r
1714 // Check if it is PEI file\r
1715 //\r
1716 if (strstr (Buffer, ".pei") != NULL) {\r
1717 //\r
1718 // Find the human readable portion\r
1719 //\r
1720 if (!strtok (Buffer, "-") ||\r
1721 !strtok (NULL, "-") ||\r
1722 !strtok (NULL, "-") ||\r
1723 !strtok (NULL, "-") ||\r
1724 !strtok (NULL, "-") ||\r
1725 !strcpy (Buffer, strtok (NULL, "."))\r
1726 ) {\r
1727 Error (NULL, 0, 0, "failed to find human readable portion of the file name in AddSymFile()", NULL);\r
1728 return EFI_ABORTED;\r
1729 }\r
1730 //\r
1731 // Save code module name\r
1732 //\r
1733 strcpy (CodeModuleName, Buffer);\r
1734\r
1735 //\r
1736 // Add the symbol file name and extension to the file path.\r
1737 //\r
1738 strcat (Buffer, ".sym");\r
1739 strcat (SymFileName, "\\");\r
1740 strcat (SymFileName, Buffer);\r
1741 } else {\r
1742 //\r
1743 // Only handle PEIM files.\r
1744 //\r
1745 return EFI_SUCCESS;\r
1746 }\r
1747 //\r
1748 // Find PE32 section\r
1749 //\r
1750 Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, 1, &Pe32Section);\r
1751\r
1752 //\r
1753 // BUGBUG: Assume if no PE32 section it is PIC and hardcode base address\r
1754 //\r
1755 if (Status == EFI_NOT_FOUND) {\r
1756 Status = GetSectionByType (FfsFile, EFI_SECTION_TE, 1, &Pe32Section);\r
1757 }\r
1758\r
1759 if (Status == EFI_SUCCESS) {\r
1760 Status = GetPe32Info (\r
1761 (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),\r
1762 &EntryPoint,\r
1763 &BaseOfCode,\r
1764 &MachineType\r
1765 );\r
1766 } else {\r
1767 if (Status == EFI_NOT_FOUND) {\r
1768 BaseOfCode = 0x60;\r
1769 Status = EFI_SUCCESS;\r
1770 } else {\r
1771 Error (NULL, 0, 0, "could not parse a PE32 section from the PEI file", NULL);\r
1772 return Status;\r
1773 }\r
1774 }\r
1775\r
1776 if (EFI_ERROR (Status)) {\r
1777 Error (NULL, 0, 0, "GetPe32Info() could not get PE32 entry point for PEI file", NULL);\r
1778 return Status;\r
1779 }\r
1780\r
1781 //\r
1782 // Open the source file\r
1783 //\r
1784 SourceFile = fopen (SymFileName, "r");\r
1785 if (SourceFile == NULL) {\r
1786 //\r
1787 // SYM files are not required.\r
1788 //\r
1789 return EFI_SUCCESS;\r
1790 }\r
1791 //\r
1792 // Read the first line\r
1793 //\r
1794 if (fgets (Buffer, _MAX_PATH, SourceFile) == NULL) {\r
1795 Buffer[0] = 0;\r
1796 }\r
1797 //\r
1798 // Make sure it matches the expected sym format\r
1799 //\r
1800 if (strcmp (Buffer, "TEXTSYM format | V1.0\n")) {\r
1801 fclose (SourceFile);\r
1802 Error (NULL, 0, 0, "AddSymFile() found unexpected sym format in input file", NULL);\r
1803 return EFI_ABORTED;\r
1804 }\r
1805 //\r
1806 // Read in the file\r
1807 //\r
1808 while (feof (SourceFile) == 0) {\r
1809 //\r
1810 // Read a line\r
1811 //\r
1812 if (fscanf (\r
1813 SourceFile,\r
1814 "%s | %s | %s | %s\n",\r
1815 Type,\r
1816 Address,\r
1817 Section,\r
1818 Token\r
1819 ) == 4) {\r
1820 //\r
1821 // If the token starts with "??" ignore it\r
1822 //\r
1823 if (Token[0] == '?' && Token[1] == '?') {\r
1824 continue;\r
1825 }\r
1826 //\r
1827 // Get the token address\r
1828 //\r
1829 AsciiStringToUint64 (Address, TRUE, &TokenAddress);\r
1830\r
1831 //\r
1832 // Add the base address\r
1833 //\r
1834 TokenAddress += BaseAddress;\r
1835\r
1836 //\r
1837 // If PE32 or TE section then find the start of code. For PIC it is hardcoded.\r
1838 //\r
1839 if (Pe32Section.Pe32Section) {\r
1840 //\r
1841 // Add the offset of the PE32 section\r
1842 //\r
1843 TokenAddress += (UINTN) Pe32Section.Pe32Section - (UINTN) FfsFile;\r
1844\r
1845 //\r
1846 // Add the size of the PE32 section header\r
1847 //\r
1848 TokenAddress += sizeof (EFI_PE32_SECTION);\r
1849 } else {\r
1850 //\r
1851 // BUGBUG: Don't know why this is 0x28 bytes.\r
1852 //\r
1853 TokenAddress += 0x28;\r
1854 }\r
1855 //\r
1856 // Add the beginning of the code\r
1857 //\r
1858 TokenAddress += BaseOfCode;\r
1859\r
1860 sprintf (\r
1861 Buffer,\r
1862 "%s | %016I64X | %s | _%s%s\n",\r
1863 Type,\r
1864 TokenAddress,\r
1865 Section,\r
1866 CodeModuleName,\r
1867 Token\r
1868 );\r
1869 memcpy (SymImage->CurrentFilePointer, Buffer, strlen (Buffer) + 1);\r
1870 SymImage->CurrentFilePointer = (UINT8 *) (((UINTN) SymImage->CurrentFilePointer) + strlen (Buffer) + 1);\r
1871 }\r
1872 }\r
1873\r
1874 fclose (SourceFile);\r
1875 return EFI_SUCCESS;\r
1876}\r
1877\r
1878EFI_STATUS\r
1879AddFile (\r
1880 IN OUT MEMORY_FILE *FvImage,\r
1881 IN FV_INFO *FvInfo,\r
1882 IN UINTN Index,\r
1883 IN OUT EFI_FFS_FILE_HEADER **VtfFileImage,\r
1884 IN OUT MEMORY_FILE *SymImage\r
1885 )\r
1886/*++\r
1887\r
1888Routine Description:\r
1889\r
1890 This function adds a file to the FV image. The file will pad to the\r
1891 appropriate alignment if required.\r
1892\r
1893Arguments:\r
1894\r
1895 FvImage The memory image of the FV to add it to. The current offset\r
1896 must be valid.\r
1897 FvInfo Pointer to information about the FV.\r
1898 Index The file in the FvInfo file list to add.\r
1899 VtfFileImage A pointer to the VTF file within the FvImage. If this is equal\r
1900 to the end of the FvImage then no VTF previously found.\r
1901 SymImage The memory image of the Sym file to update if symbols are present.\r
1902 The current offset must be valid.\r
1903\r
1904Returns:\r
1905\r
1906 EFI_SUCCESS The function completed successfully.\r
1907 EFI_INVALID_PARAMETER One of the input parameters was invalid.\r
1908 EFI_ABORTED An error occurred.\r
1909 EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the add.\r
1910\r
1911--*/\r
1912{\r
1913 FILE *NewFile;\r
1914 UINTN FileSize;\r
1915 UINT8 *FileBuffer;\r
1916 UINTN NumBytesRead;\r
1917 UINT32 CurrentFileAlignment;\r
1918 EFI_STATUS Status;\r
1919 EFI_PHYSICAL_ADDRESS CurrentFileBaseAddress;\r
1920 UINT8 VtfHeaderChecksum;\r
1921 UINT8 VtfFileChecksum;\r
1922 UINT8 FileState;\r
1923 UINT32 TailSize;\r
1924#if (PI_SPECIFICATION_VERSION < 0x00010000)\r
1925 EFI_FFS_FILE_TAIL TailValue;\r
1926#endif\r
1927 //\r
1928 // Verify input parameters.\r
1929 //\r
1930 if (FvImage == NULL || FvInfo == NULL || FvInfo->FvFiles[Index][0] == 0 || VtfFileImage == NULL || SymImage == NULL) {\r
1931 return EFI_INVALID_PARAMETER;\r
1932 }\r
1933 //\r
1934 // Read the file to add\r
1935 //\r
1936 NewFile = fopen (FvInfo->FvFiles[Index], "rb");\r
1937\r
1938 if (NewFile == NULL) {\r
1939 Error (NULL, 0, 0, FvInfo->FvFiles[Index], "failed to open file for reading");\r
1940 return EFI_ABORTED;\r
1941 }\r
1942 //\r
1943 // Get the file size\r
1944 //\r
1945 FileSize = _filelength (_fileno (NewFile));\r
1946\r
1947 //\r
1948 // Read the file into a buffer\r
1949 //\r
1950 FileBuffer = malloc (FileSize);\r
1951 if (FileBuffer == NULL) {\r
1952 Error (NULL, 0, 0, "memory allocation failure", NULL);\r
1953 return EFI_OUT_OF_RESOURCES;\r
1954 }\r
1955\r
1956 NumBytesRead = fread (FileBuffer, sizeof (UINT8), FileSize, NewFile);\r
1957\r
1958 //\r
1959 // Done with the file, from this point on we will just use the buffer read.\r
1960 //\r
1961 fclose (NewFile);\r
1962\r
1963 //\r
1964 // Verify read successful\r
1965 //\r
1966 if (NumBytesRead != sizeof (UINT8) * FileSize) {\r
1967 free (FileBuffer);\r
1968 Error (NULL, 0, 0, FvInfo->FvFiles[Index], "failed to read input file contents");\r
1969 return EFI_ABORTED;\r
1970 }\r
1971 //\r
1972 // Verify space exists to add the file\r
1973 //\r
1974 if (FileSize > (UINTN) ((UINTN) *VtfFileImage - (UINTN) FvImage->CurrentFilePointer)) {\r
1975 Error (NULL, 0, 0, FvInfo->FvFiles[Index], "insufficient space remains to add the file");\r
1976 return EFI_OUT_OF_RESOURCES;\r
1977 }\r
1978 //\r
1979 // Update the file state based on polarity of the FV.\r
1980 //\r
1981 UpdateFfsFileState (\r
1982 (EFI_FFS_FILE_HEADER *) FileBuffer,\r
1983 (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage\r
1984 );\r
1985\r
1986 //\r
1987 // If we have a VTF file, add it at the top.\r
1988 //\r
1989 if (IsVtfFile ((EFI_FFS_FILE_HEADER *) FileBuffer)) {\r
1990 if ((UINTN) *VtfFileImage == (UINTN) FvImage->Eof) {\r
1991 //\r
1992 // No previous VTF, add this one.\r
1993 //\r
1994 *VtfFileImage = (EFI_FFS_FILE_HEADER *) (UINTN) ((UINTN) FvImage->FileImage + FvInfo->Size - FileSize);\r
1995 //\r
1996 // Sanity check. The file MUST align appropriately\r
1997 //\r
1998 if ((((UINTN) *VtfFileImage) & 0x07) != 0) {\r
1999 Error (NULL, 0, 0, "VTF file does not align on 8-byte boundary", NULL);\r
2000 }\r
2001 //\r
2002 // copy VTF File Header\r
2003 //\r
2004 memcpy (*VtfFileImage, FileBuffer, sizeof (EFI_FFS_FILE_HEADER));\r
2005\r
2006 //\r
2007 // Copy VTF body\r
2008 //\r
2009 memcpy (\r
2010 (UINT8 *) *VtfFileImage + sizeof (EFI_FFS_FILE_HEADER),\r
2011 FileBuffer + sizeof (EFI_FFS_FILE_HEADER),\r
2012 FileSize - sizeof (EFI_FFS_FILE_HEADER)\r
2013 );\r
2014\r
2015 //\r
2016 // re-calculate the VTF File Header\r
2017 //\r
2018 FileState = (*VtfFileImage)->State;\r
2019 (*VtfFileImage)->State = 0;\r
2020 *(UINT32 *) ((*VtfFileImage)->Size) = FileSize;\r
2021 (*VtfFileImage)->IntegrityCheck.Checksum.Header = 0;\r
2022 (*VtfFileImage)->IntegrityCheck.Checksum.File = 0;\r
2023\r
2024 VtfHeaderChecksum = CalculateChecksum8 ((UINT8 *) *VtfFileImage, sizeof (EFI_FFS_FILE_HEADER));\r
2025 (*VtfFileImage)->IntegrityCheck.Checksum.Header = VtfHeaderChecksum;\r
2026 //\r
2027 // Determine if it has a tail\r
2028 //\r
2029 if ((*VtfFileImage)->Attributes & FFS_ATTRIB_TAIL_PRESENT) {\r
2030 TailSize = sizeof (EFI_FFS_FILE_TAIL);\r
2031 } else {\r
2032 TailSize = 0;\r
2033 }\r
2034\r
2035 if ((*VtfFileImage)->Attributes & FFS_ATTRIB_CHECKSUM) {\r
2036 VtfFileChecksum = CalculateChecksum8 ((UINT8 *) *VtfFileImage, FileSize - TailSize);\r
2037 (*VtfFileImage)->IntegrityCheck.Checksum.File = VtfFileChecksum;\r
2038 } else {\r
2039 (*VtfFileImage)->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
2040 }\r
2041 #if (PI_SPECIFICATION_VERSION < 0x00010000)\r
2042 //\r
2043 // If it has a file tail, update it\r
2044 //\r
2045 if ((*VtfFileImage)->Attributes & FFS_ATTRIB_TAIL_PRESENT) {\r
2046 TailValue = (EFI_FFS_FILE_TAIL) (~((*VtfFileImage)->IntegrityCheck.TailReference));\r
2047 *(EFI_FFS_FILE_TAIL *) (((UINTN) (*VtfFileImage) + GetLength ((*VtfFileImage)->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;\r
2048 }\r
2049 #endif \r
2050 (*VtfFileImage)->State = FileState;\r
2051 free (FileBuffer);\r
2052 return EFI_SUCCESS;\r
2053 } else {\r
2054 //\r
2055 // Already found a VTF file.\r
2056 //\r
2057 Error (NULL, 0, 0, "multiple VTF files are illegal in a single FV", NULL);\r
2058 free (FileBuffer);\r
2059 return EFI_ABORTED;\r
2060 }\r
2061 }\r
2062 //\r
2063 // Check if alignment is required\r
2064 //\r
2065 Status = ReadFfsAlignment ((EFI_FFS_FILE_HEADER *) FileBuffer, &CurrentFileAlignment);\r
2066 if (EFI_ERROR (Status)) {\r
2067 printf ("ERROR: Could not determine alignment of file %s.\n", FvInfo->FvFiles[Index]);\r
2068 free (FileBuffer);\r
2069 return EFI_ABORTED;\r
2070 }\r
2071 //\r
2072 // Add pad file if necessary\r
2073 //\r
2074 Status = AddPadFile (FvImage, CurrentFileAlignment);\r
2075 if (EFI_ERROR (Status)) {\r
2076 printf ("ERROR: Could not align the file data properly.\n");\r
2077 free (FileBuffer);\r
2078 return EFI_ABORTED;\r
2079 }\r
2080 //\r
2081 // Add file\r
2082 //\r
2083 if ((FvImage->CurrentFilePointer + FileSize) < FvImage->Eof) {\r
2084 //\r
2085 // Copy the file\r
2086 //\r
2087 memcpy (FvImage->CurrentFilePointer, FileBuffer, FileSize);\r
2088\r
2089 //\r
2090 // If the file is XIP, rebase\r
2091 //\r
2092 CurrentFileBaseAddress = FvInfo->BaseAddress + ((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage);\r
2093 //\r
2094 // Status = RebaseFfsFile ((EFI_FFS_FILE_HEADER*) FvImage->CurrentFilePointer, CurrentFileBaseAddress);\r
2095 // if (EFI_ERROR(Status)) {\r
2096 // printf ("ERROR: Could not rebase the file %s.\n", FvInfo->FvFiles[Index]);\r
2097 // return EFI_ABORTED;\r
2098 // }\r
2099 //\r
2100 // Update Symbol file\r
2101 //\r
2102 Status = AddSymFile (\r
2103 CurrentFileBaseAddress,\r
2104 (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer,\r
2105 SymImage,\r
2106 FvInfo->FvFiles[Index]\r
2107 );\r
2108 assert (!EFI_ERROR (Status));\r
2109\r
2110 //\r
2111 // Update the current pointer in the FV image\r
2112 //\r
2113 FvImage->CurrentFilePointer += FileSize;\r
2114 } else {\r
2115 printf ("ERROR: The firmware volume is out of space, could not add file %s.\n", FvInfo->FvFiles[Index]);\r
2116 return EFI_ABORTED;\r
2117 }\r
2118 //\r
2119 // Make next file start at QWord Boundry\r
2120 //\r
2121 while (((UINTN) FvImage->CurrentFilePointer & 0x07) != 0) {\r
2122 FvImage->CurrentFilePointer++;\r
2123 }\r
2124 //\r
2125 // Free allocated memory.\r
2126 //\r
2127 free (FileBuffer);\r
2128\r
2129 return EFI_SUCCESS;\r
2130}\r
2131\r
2132EFI_STATUS\r
2133AddVariableBlock (\r
2134 IN UINT8 *FvImage,\r
2135 IN UINTN Size,\r
2136 IN FV_INFO *FvInfo\r
2137 )\r
2138{\r
2139 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;\r
2140 VARIABLE_STORE_HEADER *VarStoreHeader;\r
2141 //\r
2142 // Variable block should exclude FvHeader. Since the length of\r
2143 // FvHeader depends on the block map, which is variable length,\r
2144 // we could only decide the actual variable block length here.\r
2145 //\r
2146 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage;\r
2147 FvImage = FvImage + FvHeader->HeaderLength;\r
2148\r
2149 VarStoreHeader = (VARIABLE_STORE_HEADER *) FvImage;\r
2150\r
2151 VarStoreHeader->Signature = VARIABLE_STORE_SIGNATURE;\r
2152 VarStoreHeader->Size = Size - FvHeader->HeaderLength;\r
2153 VarStoreHeader->Format = VARIABLE_STORE_FORMATTED;\r
2154 VarStoreHeader->State = VARIABLE_STORE_HEALTHY;\r
2155 VarStoreHeader->Reserved = 0;\r
2156 VarStoreHeader->Reserved1 = 0;\r
2157\r
2158 return EFI_SUCCESS;\r
2159}\r
2160\r
2161EFI_STATUS\r
2162AddEventLogBlock (\r
2163 IN UINT8 *FvImage,\r
2164 IN UINTN Size,\r
2165 IN FV_INFO *FvInfo\r
2166 )\r
2167{\r
2168 return EFI_SUCCESS;\r
2169}\r
2170\r
2171EFI_STATUS\r
2172AddFTWWorkingBlock (\r
2173 IN UINT8 *FvImage,\r
2174 IN UINTN Size,\r
2175 IN FV_INFO *FvInfo\r
2176 )\r
2177{\r
2178 EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *FTWHeader;\r
2179 UINT32 Crc32;\r
2180\r
2181 Crc32 = 0;\r
2182 FTWHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) FvImage;\r
2183 memcpy (&FTWHeader->Signature, &(FvInfo->FvGuid), sizeof (EFI_GUID));\r
2184 FTWHeader->WriteQueueSize = Size - sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER);\r
2185 CalculateCrc32 (FvImage, sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER), &Crc32);\r
2186 FTWHeader->Crc = Crc32;\r
2187 if (FvInfo->FvAttributes & EFI_FVB_ERASE_POLARITY) {\r
2188 FTWHeader->WorkingBlockValid = 0;\r
2189 FTWHeader->WorkingBlockInvalid = 1;\r
2190 } else {\r
2191 FTWHeader->WorkingBlockValid = 1;\r
2192 FTWHeader->WorkingBlockInvalid = 0;\r
2193 }\r
2194\r
2195 return EFI_SUCCESS;\r
2196}\r
2197\r
2198EFI_STATUS\r
2199AddFTWSpareBlock (\r
2200 IN UINT8 *FvImage,\r
2201 IN UINTN Size,\r
2202 IN FV_INFO *FvInfo\r
2203 )\r
2204{\r
2205 return EFI_SUCCESS;\r
2206}\r
2207\r
2208EFI_STATUS\r
2209GenNonFFSFv (\r
2210 IN UINT8 *FvImage,\r
2211 IN FV_INFO *FvInfo\r
2212 )\r
2213/*++\r
2214\r
2215Routine Description:\r
2216\r
2217 This function generate the non FFS FV image, such as the working block\r
2218 and spare block. How each component of the FV is built is component\r
2219 specific.\r
2220\r
2221Arguments:\r
2222\r
2223 FvImage The memory image of the FV to add it to. The current offset\r
2224 must be valid.\r
2225 FvInfo Pointer to information about the FV.\r
2226\r
2227Returns:\r
2228\r
2229 EFI_SUCCESS The function completed successfully.\r
2230 EFI_INVALID_PARAMETER One of the input parameters was invalid.\r
2231 EFI_ABORTED An error occurred.\r
2232 EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the add.\r
2233\r
2234--*/\r
2235{\r
2236 UINTN Index;\r
2237 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;\r
2238 UINT64 TotalSize;\r
2239\r
2240 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage;\r
2241 TotalSize = 0;\r
2242\r
2243 for (Index = 0; FvInfo->FvComponents[Index].Size != 0; Index++) {\r
2244 if (_stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_VARIABLE_STRING) == 0) {\r
2245 AddVariableBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);\r
2246 } else if (_stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_EVENT_LOG_STRING) == 0) {\r
2247 AddEventLogBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);\r
2248 } else if (_stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_WORKING_STRING) == 0) {\r
2249 AddFTWWorkingBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);\r
2250 } else if (_stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_SPARE_STRING) == 0) {\r
2251 AddFTWSpareBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);\r
2252 } else {\r
2253 printf ("Error. Unknown Non-FFS block %s \n", FvInfo->FvComponents[Index].ComponentName);\r
2254 return EFI_ABORTED;\r
2255 }\r
2256\r
2257 FvImage = FvImage + FvInfo->FvComponents[Index].Size;\r
2258 TotalSize = TotalSize + FvInfo->FvComponents[Index].Size;\r
2259 }\r
2260 //\r
2261 // Index and TotalSize is zero mean there's no component, so this is an empty fv\r
2262 //\r
2263 if ((Index != 0 || TotalSize != 0) && TotalSize != FvInfo->Size) {\r
2264 printf ("Error. Component size does not sum up to FV size.\n");\r
2265 return EFI_ABORTED;\r
2266 }\r
2267\r
2268 return EFI_SUCCESS;\r
2269}\r
2270\r
2271EFI_STATUS\r
2272PadFvImage (\r
2273 IN MEMORY_FILE *FvImage,\r
2274 IN EFI_FFS_FILE_HEADER *VtfFileImage\r
2275 )\r
2276/*++\r
2277\r
2278Routine Description:\r
2279\r
2280 This function places a pad file between the last file in the FV and the VTF\r
2281 file if the VTF file exists.\r
2282\r
2283Arguments:\r
2284\r
2285 FvImage Memory file for the FV memory image\r
2286 VtfFileImage The address of the VTF file. If this is the end of the FV\r
2287 image, no VTF exists and no pad file is needed.\r
2288\r
2289Returns:\r
2290\r
2291 EFI_SUCCESS Completed successfully.\r
2292 EFI_INVALID_PARAMETER One of the input parameters was NULL.\r
2293\r
2294--*/\r
2295{\r
2296 EFI_FFS_FILE_HEADER *PadFile;\r
2297 UINTN FileSize;\r
2298\r
2299 //\r
2300 // If there is no VTF or the VTF naturally follows the previous file without a\r
2301 // pad file, then there's nothing to do\r
2302 //\r
2303 if ((UINTN) VtfFileImage == (UINTN) FvImage->Eof || (void *) FvImage->CurrentFilePointer == (void *) VtfFileImage) {\r
2304 return EFI_SUCCESS;\r
2305 }\r
2306 //\r
2307 // Pad file starts at beginning of free space\r
2308 //\r
2309 PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer;\r
2310\r
2311 //\r
2312 // write header\r
2313 //\r
2314 memset (PadFile, 0, sizeof (EFI_FFS_FILE_HEADER));\r
2315 memcpy (&PadFile->Name, &DefaultFvPadFileNameGuid, sizeof (EFI_GUID));\r
2316 PadFile->Type = EFI_FV_FILETYPE_FFS_PAD;\r
2317 PadFile->Attributes = 0;\r
2318\r
2319 //\r
2320 // FileSize includes the EFI_FFS_FILE_HEADER\r
2321 //\r
2322 FileSize = (UINTN) VtfFileImage - (UINTN) FvImage->CurrentFilePointer;\r
2323 PadFile->Size[0] = (UINT8) (FileSize & 0x000000FF);\r
2324 PadFile->Size[1] = (UINT8) ((FileSize & 0x0000FF00) >> 8);\r
2325 PadFile->Size[2] = (UINT8) ((FileSize & 0x00FF0000) >> 16);\r
2326\r
2327 //\r
2328 // Fill in checksums and state, must be zero during checksum calculation.\r
2329 //\r
2330 PadFile->IntegrityCheck.Checksum.Header = 0;\r
2331 PadFile->IntegrityCheck.Checksum.File = 0;\r
2332 PadFile->State = 0;\r
2333 PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER));\r
2334 if (PadFile->Attributes & FFS_ATTRIB_CHECKSUM) {\r
2335 PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) PadFile, FileSize);\r
2336 } else {\r
2337 PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
2338 }\r
2339\r
2340 PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;\r
2341\r
2342 UpdateFfsFileState (\r
2343 (EFI_FFS_FILE_HEADER *) PadFile,\r
2344 (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage\r
2345 );\r
2346 //\r
2347 // Update the current FV pointer\r
2348 //\r
2349 FvImage->CurrentFilePointer = FvImage->Eof;\r
2350\r
2351 return EFI_SUCCESS;\r
2352}\r
2353\r
2354EFI_STATUS\r
2355UpdateResetVector (\r
2356 IN MEMORY_FILE *FvImage,\r
2357 IN FV_INFO *FvInfo,\r
2358 IN EFI_FFS_FILE_HEADER *VtfFile\r
2359 )\r
2360/*++\r
2361\r
2362Routine Description:\r
2363\r
2364 This parses the FV looking for the PEI core and then plugs the address into\r
2365 the SALE_ENTRY point of the BSF/VTF for IPF and does BUGBUG TBD action to\r
2366 complete an IA32 Bootstrap FV.\r
2367\r
2368Arguments:\r
2369\r
2370 FvImage Memory file for the FV memory image\r
2371 FvInfo Information read from INF file.\r
2372 VtfFile Pointer to the VTF file in the FV image.\r
2373\r
2374Returns:\r
2375\r
2376 EFI_SUCCESS Function Completed successfully.\r
2377 EFI_ABORTED Error encountered.\r
2378 EFI_INVALID_PARAMETER A required parameter was NULL.\r
2379 EFI_NOT_FOUND PEI Core file not found.\r
2380\r
2381--*/\r
2382{\r
2383 EFI_FFS_FILE_HEADER *PeiCoreFile;\r
2384 EFI_FFS_FILE_HEADER *SecCoreFile;\r
2385 EFI_STATUS Status;\r
2386 EFI_FILE_SECTION_POINTER Pe32Section;\r
2387 UINT32 EntryPoint;\r
2388 UINT32 BaseOfCode;\r
2389 UINT16 MachineType;\r
2390 EFI_PHYSICAL_ADDRESS PeiCorePhysicalAddress;\r
2391 EFI_PHYSICAL_ADDRESS SecCorePhysicalAddress;\r
2392 EFI_PHYSICAL_ADDRESS *SecCoreEntryAddressPtr;\r
2393 UINT32 *Ia32ResetAddressPtr;\r
2394 UINT8 *BytePointer;\r
2395 UINT8 *BytePointer2;\r
2396 UINT16 *WordPointer;\r
2397 UINT16 CheckSum;\r
2398 UINTN Index;\r
2399 EFI_FFS_FILE_STATE SavedState;\r
2400 UINT32 TailSize;\r
2401 UINT64 FitAddress;\r
2402 FIT_TABLE *FitTablePtr;\r
2403#if (PI_SPECIFICATION_VERSION < 0x00010000)\r
2404 EFI_FFS_FILE_TAIL TailValue;\r
2405#endif\r
2406 //\r
2407 // Verify input parameters\r
2408 //\r
2409 if (FvImage == NULL || FvInfo == NULL || VtfFile == NULL) {\r
2410 return EFI_INVALID_PARAMETER;\r
2411 }\r
2412 //\r
2413 // Initialize FV library\r
2414 //\r
2415 InitializeFvLib (FvImage->FileImage, (UINTN) FvImage->Eof - (UINTN) FvImage->FileImage);\r
2416\r
2417 //\r
2418 // Verify VTF file\r
2419 //\r
2420 Status = VerifyFfsFile (VtfFile);\r
2421 if (EFI_ERROR (Status)) {\r
2422 return EFI_INVALID_PARAMETER;\r
2423 }\r
2424 //\r
2425 // Find the PEI Core\r
2426 //\r
2427 Status = GetFileByType (EFI_FV_FILETYPE_PEI_CORE, 1, &PeiCoreFile);\r
2428 if (EFI_ERROR (Status) || PeiCoreFile == NULL) {\r
2429 Error (NULL, 0, 0, "could not find the PEI core in the FV", NULL);\r
2430 return EFI_ABORTED;\r
2431 }\r
2432 //\r
2433 // PEI Core found, now find PE32 or TE section\r
2434 //\r
2435 Status = GetSectionByType (PeiCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);\r
2436 if (Status == EFI_NOT_FOUND) {\r
2437 Status = GetSectionByType (PeiCoreFile, EFI_SECTION_TE, 1, &Pe32Section);\r
2438 }\r
2439\r
2440 if (EFI_ERROR (Status)) {\r
2441 Error (NULL, 0, 0, "could not find PE32 or TE section in PEI core file", NULL);\r
2442 return EFI_ABORTED;\r
2443 }\r
2444\r
2445 Status = GetPe32Info (\r
2446 (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),\r
2447 &EntryPoint,\r
2448 &BaseOfCode,\r
2449 &MachineType\r
2450 );\r
2451\r
2452 if (EFI_ERROR (Status)) {\r
2453 Error (NULL, 0, 0, "could not get PE32 entry point for PEI core", NULL);\r
2454 return EFI_ABORTED;\r
2455 }\r
2456 //\r
2457 // Physical address is FV base + offset of PE32 + offset of the entry point\r
2458 //\r
2459 PeiCorePhysicalAddress = FvInfo->BaseAddress;\r
2460 PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;\r
2461 PeiCorePhysicalAddress += EntryPoint;\r
2462\r
2463 if (MachineType == EFI_IMAGE_MACHINE_IA64) {\r
2464 //\r
2465 // Update PEI_CORE address\r
2466 //\r
2467 //\r
2468 // Set the uncached attribute bit in the physical address\r
2469 //\r
2470 PeiCorePhysicalAddress |= 0x8000000000000000;\r
2471\r
2472 //\r
2473 // Check if address is aligned on a 16 byte boundary\r
2474 //\r
2475 if (PeiCorePhysicalAddress & 0xF) {\r
2476 printf (\r
2477 "ERROR: PEI_CORE entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n",\r
2478 PeiCorePhysicalAddress\r
2479 );\r
2480 return EFI_ABORTED;\r
2481 }\r
2482 //\r
2483 // First Get the FIT table address\r
2484 //\r
2485 FitAddress = (*(UINT64 *) (FvImage->Eof - IPF_FIT_ADDRESS_OFFSET)) & 0xFFFFFFFF;\r
2486\r
2487 FitTablePtr = (FIT_TABLE *) (FvImage->FileImage + (FitAddress - FvInfo->BaseAddress));\r
2488\r
2489 Status = UpdatePeiCoreEntryInFit (FitTablePtr, PeiCorePhysicalAddress);\r
2490\r
2491 if (!EFI_ERROR (Status)) {\r
2492 UpdateFitCheckSum (FitTablePtr);\r
2493 }\r
2494 //\r
2495 // Find the Sec Core\r
2496 //\r
2497 Status = GetFileByType (EFI_FV_FILETYPE_SECURITY_CORE, 1, &SecCoreFile);\r
2498 if (EFI_ERROR (Status) || SecCoreFile == NULL) {\r
2499 Error (NULL, 0, 0, "could not find the Sec core in the FV", NULL);\r
2500 return EFI_ABORTED;\r
2501 }\r
2502 //\r
2503 // Sec Core found, now find PE32 section\r
2504 //\r
2505 Status = GetSectionByType (SecCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);\r
2506 if (EFI_ERROR (Status)) {\r
2507 Error (NULL, 0, 0, "could not find PE32 section in SEC core file", NULL);\r
2508 return EFI_ABORTED;\r
2509 }\r
2510\r
2511 Status = GetPe32Info (\r
2512 (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),\r
2513 &EntryPoint,\r
2514 &BaseOfCode,\r
2515 &MachineType\r
2516 );\r
2517 if (EFI_ERROR (Status)) {\r
2518 Error (NULL, 0, 0, "could not get PE32 entry point for SEC core", NULL);\r
2519 return EFI_ABORTED;\r
2520 }\r
2521 //\r
2522 // Physical address is FV base + offset of PE32 + offset of the entry point\r
2523 //\r
2524 SecCorePhysicalAddress = FvInfo->BaseAddress;\r
2525 SecCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;\r
2526 SecCorePhysicalAddress += EntryPoint;\r
2527\r
2528 //\r
2529 // Update SEC_CORE address\r
2530 //\r
2531 //\r
2532 // Set the uncached attribute bit in the physical address\r
2533 //\r
2534 SecCorePhysicalAddress |= 0x8000000000000000;\r
2535\r
2536 //\r
2537 // Update the address\r
2538 //\r
2539 SecCoreEntryAddressPtr = (EFI_PHYSICAL_ADDRESS *) ((UINTN) FvImage->Eof - IPF_SALE_ENTRY_ADDRESS_OFFSET);\r
2540 *SecCoreEntryAddressPtr = SecCorePhysicalAddress;\r
2541\r
2542 //\r
2543 // Check if address is aligned on a 16 byte boundary\r
2544 //\r
2545 if (SecCorePhysicalAddress & 0xF) {\r
2546 printf (\r
2547 "ERROR: SALE_ENTRY entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n",\r
2548 SecCorePhysicalAddress\r
2549 );\r
2550 return EFI_ABORTED;\r
2551 }\r
2552 } else if ((MachineType == EFI_IMAGE_MACHINE_IA32) || \r
2553 (MachineType == EFI_IMAGE_MACHINE_X64)) {\r
2554 //\r
2555 // Get the location to update\r
2556 //\r
2557 Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - IA32_PEI_CORE_ENTRY_OFFSET);\r
2558\r
2559 //\r
2560 // Write lower 32 bits of physical address\r
2561 //\r
2562 *Ia32ResetAddressPtr = (UINT32) PeiCorePhysicalAddress;\r
2563\r
2564 //\r
2565 // Update the BFV base address\r
2566 //\r
2567 Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - 4);\r
2568 *Ia32ResetAddressPtr = (UINT32) (FvInfo->BaseAddress);\r
2569\r
2570 CheckSum = 0x0000;\r
2571\r
2572 //\r
2573 // Update the Startup AP in the FVH header block ZeroVector region.\r
2574 //\r
2575 BytePointer = (UINT8 *) ((UINTN) FvImage->FileImage);\r
2576 BytePointer2 = (FvInfo->Size == 0x10000) ? m64kRecoveryStartupApDataArray : m128kRecoveryStartupApDataArray;\r
2577 for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY; Index++) {\r
2578 *BytePointer++ = *BytePointer2++;\r
2579 }\r
2580 //\r
2581 // Calculate the checksum\r
2582 //\r
2583 WordPointer = (UINT16 *) ((UINTN) FvImage->FileImage);\r
2584 for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY / 2; Index++) {\r
2585 CheckSum = (UINT16) (CheckSum + ((UINT16) *WordPointer));\r
2586 WordPointer++;\r
2587 }\r
2588 //\r
2589 // Update the checksum field\r
2590 //\r
2591 BytePointer = (UINT8 *) ((UINTN) FvImage->FileImage);\r
2592 BytePointer += (SIZEOF_STARTUP_DATA_ARRAY - 2);\r
2593 WordPointer = (UINT16 *) BytePointer;\r
2594 *WordPointer = (UINT16) (0x10000 - (UINT32) CheckSum);\r
2595 } else {\r
2596 Error (NULL, 0, 0, "invalid machine type in PEI core", "machine type=0x%X", (UINT32) MachineType);\r
2597 return EFI_ABORTED;\r
2598 }\r
2599 //\r
2600 // Determine if it has an FFS file tail.\r
2601 //\r
2602 if (VtfFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {\r
2603 TailSize = sizeof (EFI_FFS_FILE_TAIL);\r
2604 } else {\r
2605 TailSize = 0;\r
2606 }\r
2607 //\r
2608 // Now update file checksum\r
2609 //\r
2610 SavedState = VtfFile->State;\r
2611 VtfFile->IntegrityCheck.Checksum.File = 0;\r
2612 VtfFile->State = 0;\r
2613 if (VtfFile->Attributes & FFS_ATTRIB_CHECKSUM) {\r
2614 VtfFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (\r
2615 (UINT8 *) VtfFile,\r
2616 GetLength (VtfFile->Size) - TailSize\r
2617 );\r
2618 } else {\r
2619 VtfFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
2620 }\r
2621\r
2622 VtfFile->State = SavedState;\r
2623\r
2624#if (PI_SPECIFICATION_VERSION < 0x00010000)\r
2625 //\r
2626 // Update tail if present\r
2627 //\r
2628 if (VtfFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {\r
2629 TailValue = (EFI_FFS_FILE_TAIL) (~(VtfFile->IntegrityCheck.TailReference));\r
2630 *(EFI_FFS_FILE_TAIL *) (((UINTN) (VtfFile) + GetLength (VtfFile->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;\r
2631 }\r
2632#endif\r
2633 return EFI_SUCCESS;\r
2634}\r
2635\r
2636EFI_STATUS\r
2637GetPe32Info (\r
2638 IN UINT8 *Pe32,\r
2639 OUT UINT32 *EntryPoint,\r
2640 OUT UINT32 *BaseOfCode,\r
2641 OUT UINT16 *MachineType\r
2642 )\r
2643/*++\r
2644\r
2645Routine Description:\r
2646\r
2647 Retrieves the PE32 entry point offset and machine type from PE image or TE image.\r
2648 See EfiImage.h for machine types. The entry point offset is from the beginning\r
2649 of the PE32 buffer passed in.\r
2650\r
2651Arguments:\r
2652\r
2653 Pe32 Beginning of the PE32.\r
2654 EntryPoint Offset from the beginning of the PE32 to the image entry point.\r
2655 BaseOfCode Base address of code.\r
2656 MachineType Magic number for the machine type.\r
2657\r
2658Returns:\r
2659\r
2660 EFI_SUCCESS Function completed successfully.\r
2661 EFI_ABORTED Error encountered.\r
2662 EFI_INVALID_PARAMETER A required parameter was NULL.\r
2663 EFI_UNSUPPORTED The operation is unsupported.\r
2664\r
2665--*/\r
2666{\r
2667 EFI_IMAGE_DOS_HEADER *DosHeader;\r
2668 EFI_IMAGE_NT_HEADERS *NtHeader;\r
2669 EFI_TE_IMAGE_HEADER *TeHeader;\r
2670\r
2671 //\r
2672 // Verify input parameters\r
2673 //\r
2674 if (Pe32 == NULL) {\r
2675 return EFI_INVALID_PARAMETER;\r
2676 }\r
2677\r
2678 //\r
2679 // First check whether it is one TE Image.\r
2680 //\r
2681 TeHeader = (EFI_TE_IMAGE_HEADER *) Pe32;\r
2682 if (TeHeader->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
2683 //\r
2684 // By TeImage Header to get output\r
2685 //\r
2686 *EntryPoint = TeHeader->AddressOfEntryPoint + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader->StrippedSize;\r
2687 *BaseOfCode = TeHeader->BaseOfCode + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader->StrippedSize;\r
2688 *MachineType = TeHeader->Machine;\r
2689 } else {\r
2690 //\r
2691 // Then check whether\r
2692 // is the DOS header\r
2693 //\r
2694 DosHeader = (EFI_IMAGE_DOS_HEADER *) Pe32;\r
2695\r
2696 //\r
2697 // Verify DOS header is expected\r
2698 //\r
2699 if (DosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
2700 printf ("ERROR: Unknown magic number in the DOS header, 0x%04X.\n", DosHeader->e_magic);\r
2701 return EFI_UNSUPPORTED;\r
2702 }\r
2703 //\r
2704 // Immediately following is the NT header.\r
2705 //\r
2706 NtHeader = (EFI_IMAGE_NT_HEADERS *) ((UINTN) Pe32 + DosHeader->e_lfanew);\r
2707 \r
2708 //\r
2709 // Verify NT header is expected\r
2710 //\r
2711 if (NtHeader->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
2712 printf ("ERROR: Unrecognized image signature 0x%08X.\n", NtHeader->Signature);\r
2713 return EFI_UNSUPPORTED;\r
2714 }\r
2715 //\r
2716 // Get output\r
2717 //\r
2718 *EntryPoint = NtHeader->OptionalHeader.AddressOfEntryPoint;\r
2719 *BaseOfCode = NtHeader->OptionalHeader.BaseOfCode;\r
2720 *MachineType = NtHeader->FileHeader.Machine;\r
2721 }\r
2722\r
2723 //\r
2724 // Verify machine type is supported\r
2725 //\r
2726 if (*MachineType != EFI_IMAGE_MACHINE_IA32 && \r
2727 *MachineType != EFI_IMAGE_MACHINE_IA64 &&\r
2728 *MachineType != EFI_IMAGE_MACHINE_X64) {\r
2729 printf ("ERROR: Unrecognized machine type in the PE32 file.\n");\r
2730 return EFI_UNSUPPORTED;\r
2731 }\r
2732\r
2733 return EFI_SUCCESS;\r
2734}\r
2735//\r
2736// Exposed function implementations (prototypes are defined in GenFvImageLib.h)\r
2737//\r
2738EFI_STATUS\r
2739GenerateFvImage (\r
2740 IN CHAR8 *InfFileImage,\r
2741 IN UINTN InfFileSize,\r
2742 OUT UINT8 **FvImage,\r
2743 OUT UINTN *FvImageSize,\r
2744 OUT CHAR8 **FvFileName,\r
2745 OUT UINT8 **SymImage,\r
2746 OUT UINTN *SymImageSize,\r
2747 OUT CHAR8 **SymFileName\r
2748 )\r
2749/*++\r
2750\r
2751Routine Description:\r
2752\r
2753 This is the main function which will be called from application.\r
2754\r
2755Arguments:\r
2756\r
2757 InfFileImage Buffer containing the INF file contents.\r
2758 InfFileSize Size of the contents of the InfFileImage buffer.\r
2759 FvImage Pointer to the FV image created.\r
2760 FvImageSize Size of the FV image created and pointed to by FvImage.\r
2761 FvFileName Requested name for the FV file.\r
2762 SymImage Pointer to the Sym image created.\r
2763 SymImageSize Size of the Sym image created and pointed to by SymImage.\r
2764 SymFileName Requested name for the Sym file.\r
2765\r
2766Returns:\r
2767\r
2768 EFI_SUCCESS Function completed successfully.\r
2769 EFI_OUT_OF_RESOURCES Could not allocate required resources.\r
2770 EFI_ABORTED Error encountered.\r
2771 EFI_INVALID_PARAMETER A required parameter was NULL.\r
2772\r
2773--*/\r
2774{\r
2775 EFI_STATUS Status;\r
2776 MEMORY_FILE InfMemoryFile;\r
2777 MEMORY_FILE FvImageMemoryFile;\r
2778 MEMORY_FILE SymImageMemoryFile;\r
2779 FV_INFO FvInfo;\r
2780 UINTN Index;\r
2781 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;\r
2782 EFI_FFS_FILE_HEADER *VtfFileImage;\r
2783\r
2784 //\r
2785 // Check for invalid parameter\r
2786 //\r
2787 if (InfFileImage == NULL || FvImage == NULL || FvImageSize == NULL || FvFileName == NULL) {\r
2788 return EFI_INVALID_PARAMETER;\r
2789 }\r
2790 //\r
2791 // Initialize file structures\r
2792 //\r
2793 InfMemoryFile.FileImage = InfFileImage;\r
2794 InfMemoryFile.CurrentFilePointer = InfFileImage;\r
2795 InfMemoryFile.Eof = InfFileImage + InfFileSize;\r
2796\r
2797 //\r
2798 // Parse the FV inf file for header information\r
2799 //\r
2800 Status = ParseFvInf (&InfMemoryFile, &FvInfo);\r
2801 if (EFI_ERROR (Status)) {\r
2802 printf ("ERROR: Could not parse the input INF file.\n");\r
2803 return EFI_ABORTED;\r
2804 }\r
2805 //\r
2806 // Update the file name return values\r
2807 //\r
2808 strcpy (*FvFileName, FvInfo.FvName);\r
2809 strcpy (*SymFileName, FvInfo.SymName);\r
2810\r
2811 //\r
2812 // Calculate the FV size\r
2813 //\r
2814 *FvImageSize = FvInfo.Size;\r
2815\r
2816 //\r
2817 // Allocate the FV\r
2818 //\r
2819 *FvImage = malloc (*FvImageSize);\r
2820 if (*FvImage == NULL) {\r
2821 return EFI_OUT_OF_RESOURCES;\r
2822 }\r
2823 //\r
2824 // Allocate space for symbol file storage\r
2825 //\r
2826 *SymImage = malloc (SYMBOL_FILE_SIZE);\r
2827 if (*SymImage == NULL) {\r
2828 return EFI_OUT_OF_RESOURCES;\r
2829 }\r
2830 //\r
2831 // Initialize the FV to the erase polarity\r
2832 //\r
2833 if (FvInfo.FvAttributes & EFI_FVB_ERASE_POLARITY) {\r
2834 memset (*FvImage, -1, *FvImageSize);\r
2835 } else {\r
2836 memset (*FvImage, 0, *FvImageSize);\r
2837 }\r
2838 //\r
2839 // Initialize FV header\r
2840 //\r
2841 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) *FvImage;\r
2842\r
2843 //\r
2844 // Initialize the zero vector to all zeros.\r
2845 //\r
2846 memset (FvHeader->ZeroVector, 0, 16);\r
2847\r
2848 //\r
2849 // Copy the FFS GUID\r
2850 //\r
2851 memcpy (&FvHeader->FileSystemGuid, &FvInfo.FvGuid, sizeof (EFI_GUID));\r
2852\r
2853 FvHeader->FvLength = *FvImageSize;\r
2854 FvHeader->Signature = EFI_FVH_SIGNATURE;\r
2855 FvHeader->Attributes = FvInfo.FvAttributes;\r
2856#if (PI_SPECIFICATION_VERSION < 0x00010000)\r
2857 FvHeader->Revision = EFI_FVH_REVISION;\r
2858 FvHeader->Reserved[0] = 0;\r
2859 FvHeader->Reserved[1] = 0;\r
2860 FvHeader->Reserved[2] = 0;\r
2861#else\r
2862 FvHeader->Revision = EFI_FVH_PI_REVISION;\r
2863 FvHeader->ExtHeaderOffset = 0;\r
2864 FvHeader->Reserved[0] = 0;\r
2865#endif\r
2866 //\r
2867 // Copy firmware block map\r
2868 //\r
2869 for (Index = 0; FvInfo.FvBlocks[Index].NumBlocks != 0; Index++) {\r
2870 FvHeader->FvBlockMap[Index].NumBlocks = FvInfo.FvBlocks[Index].NumBlocks;\r
2871 FvHeader->FvBlockMap[Index].BlockLength = FvInfo.FvBlocks[Index].BlockLength;\r
2872 }\r
2873 //\r
2874 // Add block map terminator\r
2875 //\r
2876 FvHeader->FvBlockMap[Index].NumBlocks = 0;\r
2877 FvHeader->FvBlockMap[Index].BlockLength = 0;\r
2878\r
2879 //\r
2880 // Complete the header\r
2881 //\r
2882 FvHeader->HeaderLength = (UINT16) (((UINTN) &(FvHeader->FvBlockMap[Index + 1])) - (UINTN) *FvImage);\r
2883 FvHeader->Checksum = 0;\r
2884 FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));\r
2885\r
2886 //\r
2887 // If there is no FFS file, find and generate each components of the FV\r
2888 //\r
2889 if (FvInfo.FvFiles[0][0] == 0) {\r
2890 Status = GenNonFFSFv (*FvImage, &FvInfo);\r
2891 if (EFI_ERROR (Status)) {\r
2892 printf ("ERROR: Could not generate NonFFS FV.\n");\r
2893 free (*FvImage);\r
2894 return EFI_ABORTED;\r
2895 }\r
2896\r
2897 return EFI_SUCCESS;\r
2898 }\r
2899 //\r
2900 // Initialize our "file" view of the buffer\r
2901 //\r
2902 FvImageMemoryFile.FileImage = *FvImage;\r
2903 FvImageMemoryFile.CurrentFilePointer = *FvImage + FvHeader->HeaderLength;\r
2904 FvImageMemoryFile.Eof = *FvImage +*FvImageSize;\r
2905\r
2906 //\r
2907 // Initialize our "file" view of the symbol file.\r
2908 //\r
2909 SymImageMemoryFile.FileImage = *SymImage;\r
2910 SymImageMemoryFile.CurrentFilePointer = *SymImage;\r
2911 SymImageMemoryFile.Eof = *FvImage + SYMBOL_FILE_SIZE;\r
2912\r
2913 //\r
2914 // Initialize the FV library.\r
2915 //\r
2916 InitializeFvLib (FvImageMemoryFile.FileImage, FvInfo.Size);\r
2917\r
2918 //\r
2919 // Files start on 8 byte alignments, so move to the next 8 byte aligned\r
2920 // address. For now, just assert if it isn't. Currently FV header is\r
2921 // always a multiple of 8 bytes.\r
2922 // BUGBUG: Handle this better\r
2923 //\r
2924 assert ((((UINTN) FvImageMemoryFile.CurrentFilePointer) % 8) == 0);\r
2925\r
2926 //\r
2927 // Initialize the VTF file address.\r
2928 //\r
2929 VtfFileImage = (EFI_FFS_FILE_HEADER *) FvImageMemoryFile.Eof;\r
2930\r
2931 //\r
2932 // Add files to FV\r
2933 //\r
2934 for (Index = 0; FvInfo.FvFiles[Index][0] != 0; Index++) {\r
2935 //\r
2936 // Add the file\r
2937 //\r
2938 Status = AddFile (&FvImageMemoryFile, &FvInfo, Index, &VtfFileImage, &SymImageMemoryFile);\r
2939\r
2940 //\r
2941 // Exit if error detected while adding the file\r
2942 //\r
2943 if (EFI_ERROR (Status)) {\r
2944 printf ("ERROR: Could not add file %s.\n", FvInfo.FvFiles[Index]);\r
2945 free (*FvImage);\r
2946 return EFI_ABORTED;\r
2947 }\r
2948 }\r
2949 //\r
2950 // If there is a VTF file, some special actions need to occur.\r
2951 //\r
2952 if ((UINTN) VtfFileImage != (UINTN) FvImageMemoryFile.Eof) {\r
2953 //\r
2954 // Pad from the end of the last file to the beginning of the VTF file.\r
2955 //\r
2956 Status = PadFvImage (&FvImageMemoryFile, VtfFileImage);\r
2957 if (EFI_ERROR (Status)) {\r
2958 printf ("ERROR: Could not create the pad file between the last file and the VTF file.\n");\r
2959 free (*FvImage);\r
2960 return EFI_ABORTED;\r
2961 }\r
2962 //\r
2963 // Update reset vector (SALE_ENTRY for IPF)\r
2964 // Now for IA32 and IA64 platform, the fv which has bsf file must have the \r
2965 // EndAddress of 0xFFFFFFFF. Thus, only this type fv needs to update the \r
2966 // reset vector. If the PEI Core is found, the VTF file will probably get \r
2967 // corrupted by updating the entry point. \r
2968 //\r
2969 if ((FvInfo.BaseAddress + FvInfo.Size) == FV_IMAGES_TOP_ADDRESS) { \r
2970 Status = UpdateResetVector (&FvImageMemoryFile, &FvInfo, VtfFileImage);\r
2971 if (EFI_ERROR(Status)) { \r
2972 printf ("ERROR: Could not update the reset vector.\n"); \r
2973 free (*FvImage); \r
2974 return EFI_ABORTED; \r
2975 } \r
2976 }\r
2977 } \r
2978 //\r
2979 // Determine final Sym file size\r
2980 //\r
2981 *SymImageSize = SymImageMemoryFile.CurrentFilePointer - SymImageMemoryFile.FileImage;\r
2982\r
2983 return EFI_SUCCESS;\r
2984}\r
2985\r
2986EFI_STATUS\r
2987UpdatePeiCoreEntryInFit (\r
2988 IN FIT_TABLE *FitTablePtr,\r
2989 IN UINT64 PeiCorePhysicalAddress\r
2990 )\r
2991/*++\r
2992\r
2993Routine Description:\r
2994\r
2995 This function is used to update the Pei Core address in FIT, this can be used by Sec core to pass control from\r
2996 Sec to Pei Core\r
2997\r
2998Arguments:\r
2999\r
3000 FitTablePtr - The pointer of FIT_TABLE.\r
3001 PeiCorePhysicalAddress - The address of Pei Core entry.\r
3002\r
3003Returns:\r
3004\r
3005 EFI_SUCCESS - The PEI_CORE FIT entry was updated successfully.\r
3006 EFI_NOT_FOUND - Not found the PEI_CORE FIT entry.\r
3007\r
3008--*/\r
3009{\r
3010 FIT_TABLE *TmpFitPtr;\r
3011 UINTN Index;\r
3012 UINTN NumFitComponents;\r
3013\r
3014 TmpFitPtr = FitTablePtr;\r
3015 NumFitComponents = TmpFitPtr->CompSize;\r
3016\r
3017 for (Index = 0; Index < NumFitComponents; Index++) {\r
3018 if ((TmpFitPtr->CvAndType & FIT_TYPE_MASK) == COMP_TYPE_FIT_PEICORE) {\r
3019 TmpFitPtr->CompAddress = PeiCorePhysicalAddress;\r
3020 return EFI_SUCCESS;\r
3021 }\r
3022\r
3023 TmpFitPtr++;\r
3024 }\r
3025\r
3026 return EFI_NOT_FOUND;\r
3027}\r
3028\r
3029VOID\r
3030UpdateFitCheckSum (\r
3031 IN FIT_TABLE *FitTablePtr\r
3032 )\r
3033/*++\r
3034\r
3035Routine Description:\r
3036\r
3037 This function is used to update the checksum for FIT.\r
3038\r
3039\r
3040Arguments:\r
3041\r
3042 FitTablePtr - The pointer of FIT_TABLE.\r
3043\r
3044Returns:\r
3045\r
3046 None.\r
3047\r
3048--*/\r
3049{\r
3050 if ((FitTablePtr->CvAndType & CHECKSUM_BIT_MASK) >> 7) {\r
3051 FitTablePtr->CheckSum = 0;\r
3052 FitTablePtr->CheckSum = CalculateChecksum8 ((UINT8 *) FitTablePtr, FitTablePtr->CompSize * 16);\r
3053 }\r
3054}\r