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