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
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.
18 This file contains functions required to generate a Firmware Volume.
25 #include "GenFvImageLib.h"
26 #include "GenFvImageLibInternal.h"
28 #include EFI_GUID_DEFINITION (PeiPeCoffLoader)
29 #include "EfiFirmwareFileSystem.h"
30 #include "EfiWorkingBlockHeader.h"
31 #include "EfiVariable.h"
34 #include "CommonLib.h"
38 #include "EfiUtilityMsgs.h"
39 #include EFI_GUID_DEFINITION (FirmwareFileSystem)
40 #include EFI_GUID_DEFINITION (FirmwareFileSystem2)
43 // Define the PE/COFF loader
45 extern EFI_PEI_PE_COFF_LOADER_PROTOCOL mPeCoffLoader
;
48 // Local function prototypes
53 OUT UINT32
*EntryPoint
,
54 OUT UINT32
*BaseOfCode
,
55 OUT UINT16
*MachineType
59 // Local function implementations.
61 #if (PI_SPECIFICATION_VERSION < 0x00010000)
62 EFI_GUID FfsGuid
= EFI_FIRMWARE_FILE_SYSTEM_GUID
;
64 EFI_GUID FfsGuid
= EFI_FIRMWARE_FILE_SYSTEM2_GUID
;
67 EFI_GUID DefaultFvPadFileNameGuid
= { 0x78f54d4, 0xcc22, 0x4048, 0x9e, 0x94, 0x87, 0x9c, 0x21, 0x4d, 0x56, 0x2f };
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.
75 #define SIZEOF_STARTUP_DATA_ARRAY 0x10
77 UINT8 m128kRecoveryStartupApDataArray
[SIZEOF_STARTUP_DATA_ARRAY
] = {
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
101 UINT8 m64kRecoveryStartupApDataArray
[SIZEOF_STARTUP_DATA_ARRAY
] = {
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
128 IN MEMORY_FILE
*InfFile
,
135 This function parses a FV.INF file and copies info into a FV_INFO structure.
139 InfFile Memory file image.
140 FvInfo Information read from INF file.
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.
149 CHAR8 Value
[_MAX_PATH
];
155 // Initialize FV info
157 memset (FvInfo
, 0, sizeof (FV_INFO
));
160 // Read the FV base address
162 Status
= FindToken (InfFile
, OPTIONS_SECTION_STRING
, EFI_FV_BASE_ADDRESS_STRING
, 0, Value
);
164 if (Status
== EFI_SUCCESS
) {
166 // Get the base address
168 Status
= AsciiStringToUint64 (Value
, FALSE
, &Value64
);
169 if (EFI_ERROR (Status
)) {
170 Error (NULL
, 0, 0, EFI_FV_BASE_ADDRESS_STRING
, "invalid value");
174 FvInfo
->BaseAddress
= Value64
;
176 Error (NULL
, 0, 0, EFI_FV_BASE_ADDRESS_STRING
, "could not find value");
182 Status
= FindToken (InfFile
, OPTIONS_SECTION_STRING
, EFI_FV_GUID_STRING
, 0, Value
);
184 if (Status
== EFI_SUCCESS
) {
186 // Get the guid value
188 Status
= StringToGuid (Value
, &FvInfo
->FvGuid
);
189 if (EFI_ERROR (Status
)) {
190 memcpy (&FvInfo
->FvGuid
, &FfsGuid
, sizeof (EFI_GUID
));
193 memcpy (&FvInfo
->FvGuid
, &FfsGuid
, sizeof (EFI_GUID
));
196 // Read the FV file name
198 Status
= FindToken (InfFile
, OPTIONS_SECTION_STRING
, EFI_FV_FILE_NAME_STRING
, 0, Value
);
200 if (Status
== EFI_SUCCESS
) {
202 // copy the file name
204 strcpy (FvInfo
->FvName
, Value
);
206 Error (NULL
, 0, 0, EFI_FV_FILE_NAME_STRING
, "value not specified");
210 // Read the Sym file name
212 Status
= FindToken (InfFile
, OPTIONS_SECTION_STRING
, EFI_SYM_FILE_NAME_STRING
, 0, Value
);
214 if (Status
== EFI_SUCCESS
) {
216 // copy the file name
218 strcpy (FvInfo
->SymName
, Value
);
221 // Symbols not required, so init to NULL.
223 strcpy (FvInfo
->SymName
, "");
226 // Read the read disabled capability attribute
228 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_READ_DISABLED_CAP_STRING
, 0, Value
);
230 if (Status
== EFI_SUCCESS
) {
232 // Update the read disabled flag
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
);
241 Error (NULL
, 0, 0, EFI_FVB_READ_DISABLED_CAP_STRING
, "value not specified");
245 // Read the read enabled capability attribute
247 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_READ_ENABLED_CAP_STRING
, 0, Value
);
249 if (Status
== EFI_SUCCESS
) {
251 // Update the read disabled flag
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
);
260 Error (NULL
, 0, 0, EFI_FVB_READ_ENABLED_CAP_STRING
, "value not specified");
264 // Read the read status attribute
266 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_READ_STATUS_STRING
, 0, Value
);
268 if (Status
== EFI_SUCCESS
) {
270 // Update the read disabled flag
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
);
279 Error (NULL
, 0, 0, EFI_FVB_READ_STATUS_STRING
, "value not specified");
283 // Read the write disabled capability attribute
285 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_WRITE_DISABLED_CAP_STRING
, 0, Value
);
287 if (Status
== EFI_SUCCESS
) {
289 // Update the write disabled flag
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
);
298 Error (NULL
, 0, 0, EFI_FVB_WRITE_DISABLED_CAP_STRING
, "value not specified");
302 // Read the write enabled capability attribute
304 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_WRITE_ENABLED_CAP_STRING
, 0, Value
);
306 if (Status
== EFI_SUCCESS
) {
308 // Update the write disabled flag
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
);
317 Error (NULL
, 0, 0, EFI_FVB_WRITE_ENABLED_CAP_STRING
, "value not specified");
321 // Read the write status attribute
323 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_WRITE_STATUS_STRING
, 0, Value
);
325 if (Status
== EFI_SUCCESS
) {
327 // Update the write disabled flag
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
);
336 Error (NULL
, 0, 0, EFI_FVB_WRITE_STATUS_STRING
, "value not specified");
340 // Read the lock capability attribute
342 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_LOCK_CAP_STRING
, 0, Value
);
344 if (Status
== EFI_SUCCESS
) {
346 // Update the attribute flag
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
);
355 Error (NULL
, 0, 0, EFI_FVB_LOCK_CAP_STRING
, "value not specified");
359 // Read the lock status attribute
361 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_LOCK_STATUS_STRING
, 0, Value
);
363 if (Status
== EFI_SUCCESS
) {
365 // Update the attribute flag
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
);
374 Error (NULL
, 0, 0, EFI_FVB_LOCK_STATUS_STRING
, "value not specified");
378 // Read the sticky write attribute
380 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_STICKY_WRITE_STRING
, 0, Value
);
382 if (Status
== EFI_SUCCESS
) {
384 // Update the attribute flag
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
);
393 Error (NULL
, 0, 0, EFI_FVB_STICKY_WRITE_STRING
, "value not specified");
397 // Read the memory mapped attribute
399 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_MEMORY_MAPPED_STRING
, 0, Value
);
401 if (Status
== EFI_SUCCESS
) {
403 // Update the attribute flag
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
);
412 Error (NULL
, 0, 0, EFI_FVB_MEMORY_MAPPED_STRING
, "value not specified");
416 // Read the erase polarity attribute
418 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ERASE_POLARITY_STRING
, 0, Value
);
420 if (Status
== EFI_SUCCESS
) {
422 // Update the attribute flag
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
);
431 Error (NULL
, 0, 0, EFI_FVB_ERASE_POLARITY_STRING
, "value not specified");
435 #if (PI_SPECIFICATION_VERSION >= 0x00010000)
437 // Read the read lock capability attribute
439 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_READ_LOCK_CAP_STRING
, 0, Value
);
441 if (Status
== EFI_SUCCESS
) {
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
);
452 Error (NULL
, 0, 0, EFI_FVB_READ_LOCK_CAP_STRING
, "value not specified");
457 // Read the read lock status attribute
459 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_READ_LOCK_STATUS_STRING
, 0, Value
);
461 if (Status
== EFI_SUCCESS
) {
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
);
472 Error (NULL
, 0, 0, EFI_FVB_READ_LOCK_STATUS_STRING
, "value not specified");
477 // Read the write lock capability attribute
479 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_WRITE_LOCK_CAP_STRING
, 0, Value
);
481 if (Status
== EFI_SUCCESS
) {
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
);
492 Error (NULL
, 0, 0, EFI_FVB_WRITE_LOCK_CAP_STRING
, "value not specified");
497 // Read the write lock status attribute
499 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_WRITE_LOCK_STATUS_STRING
, 0, Value
);
501 if (Status
== EFI_SUCCESS
) {
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
);
512 Error (NULL
, 0, 0, EFI_FVB_WRITE_LOCK_STATUS_STRING
, "value not specified");
517 #if (PI_SPECIFICATION_VERSION < 0x00010000)
519 // Read the alignment capabilities attribute
521 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_CAP_STRING
, 0, Value
);
523 if (Status
== EFI_SUCCESS
) {
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
);
534 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_CAP_STRING
, "value not specified");
539 // Read the word alignment capability attribute
541 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_2_STRING
, 0, Value
);
543 if (Status
== EFI_SUCCESS
) {
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
);
554 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_2_STRING
, "value not specified");
560 // Read the dword alignment capability attribute
562 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_4_STRING
, 0, Value
);
564 if (Status
== EFI_SUCCESS
) {
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
);
575 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_4_STRING
, "value not specified");
579 // Read the word alignment capability attribute
581 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_8_STRING
, 0, Value
);
583 if (Status
== EFI_SUCCESS
) {
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
);
594 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_8_STRING
, "value not specified");
598 // Read the qword alignment capability attribute
600 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_16_STRING
, 0, Value
);
602 if (Status
== EFI_SUCCESS
) {
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
);
613 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_16_STRING
, "value not specified");
617 // Read the 32 byte alignment capability attribute
619 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_32_STRING
, 0, Value
);
621 if (Status
== EFI_SUCCESS
) {
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
);
632 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_32_STRING
, "value not specified");
636 // Read the 64 byte alignment capability attribute
638 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_64_STRING
, 0, Value
);
640 if (Status
== EFI_SUCCESS
) {
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
);
651 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_64_STRING
, "value not specified");
655 // Read the 128 byte alignment capability attribute
657 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_128_STRING
, 0, Value
);
659 if (Status
== EFI_SUCCESS
) {
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
);
670 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_128_STRING
, "value not specified");
674 // Read the 256 byte alignment capability attribute
676 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_256_STRING
, 0, Value
);
678 if (Status
== EFI_SUCCESS
) {
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
);
689 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_256_STRING
, "value not specified");
693 // Read the 512 byte alignment capability attribute
695 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_512_STRING
, 0, Value
);
697 if (Status
== EFI_SUCCESS
) {
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
);
708 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_512_STRING
, "value not specified");
712 // Read the 1K byte alignment capability attribute
714 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_1K_STRING
, 0, Value
);
716 if (Status
== EFI_SUCCESS
) {
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
);
727 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_1K_STRING
, "value not specified");
731 // Read the 2K byte alignment capability attribute
733 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_2K_STRING
, 0, Value
);
735 if (Status
== EFI_SUCCESS
) {
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
);
746 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_2K_STRING
, "value not specified");
750 // Read the 4K byte alignment capability attribute
752 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_4K_STRING
, 0, Value
);
754 if (Status
== EFI_SUCCESS
) {
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
);
765 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_4K_STRING
, "value not specified");
769 // Read the 8K byte alignment capability attribute
771 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_8K_STRING
, 0, Value
);
773 if (Status
== EFI_SUCCESS
) {
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
);
784 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_8K_STRING
, "value not specified");
788 // Read the 16K byte alignment capability attribute
790 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_16K_STRING
, 0, Value
);
792 if (Status
== EFI_SUCCESS
) {
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
);
803 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_16K_STRING
, "value not specified");
807 // Read the 32K byte alignment capability attribute
809 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_32K_STRING
, 0, Value
);
811 if (Status
== EFI_SUCCESS
) {
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
);
822 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_32K_STRING
, "value not specified");
826 // Read the 64K byte alignment capability attribute
828 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_64K_STRING
, 0, Value
);
830 if (Status
== EFI_SUCCESS
) {
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
);
841 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_64K_STRING
, "value not specified");
845 if (!(FvInfo
->FvAttributes
& EFI_FVB_ALIGNMENT_CAP
) &&
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
)
869 "illegal combination of alignment attributes",
870 "if %s is not %s, no individual alignments can be %s",
871 EFI_FVB_ALIGNMENT_CAP_STRING
,
879 // Read the PI1.0 FVB2 Alignment Capabilities Attribute
881 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB2_ALIGNMENT_STRING
, 0, Value
);
883 if (Status
== EFI_SUCCESS
) {
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
;
952 Error (NULL
, 0, 0, EFI_FVB2_ALIGNMENT_STRING
, "value not correct!");
956 Error (NULL
, 0, 0, EFI_FVB2_ALIGNMENT_STRING
, "value not specified");
964 for (Index
= 0; Index
< MAX_NUMBER_OF_FV_BLOCKS
; Index
++) {
966 // Read the number of blocks
968 Status
= FindToken (InfFile
, OPTIONS_SECTION_STRING
, EFI_NUM_BLOCKS_STRING
, Index
, Value
);
970 if (Status
== EFI_SUCCESS
) {
972 // Update the number of blocks
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
);
980 FvInfo
->FvBlocks
[Index
].NumBlocks
= (UINT32
) Value64
;
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.
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
);
998 // Read the size of blocks
1000 Status
= FindToken (InfFile
, OPTIONS_SECTION_STRING
, EFI_BLOCK_SIZE_STRING
, Index
, Value
);
1002 if (Status
== EFI_SUCCESS
) {
1004 // Update the number of blocks
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
);
1012 FvInfo
->FvBlocks
[Index
].BlockLength
= (UINT32
) Value64
;
1015 // There is a number of blocks, but there is no size, so we have a mismatched pair
1016 // and should return an error.
1018 Error (NULL
, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING
, EFI_BLOCK_SIZE_STRING
);
1025 for (Index
= 0; Index
< MAX_NUMBER_OF_FILES_IN_FV
; Index
++) {
1027 // Read the number of blocks
1029 Status
= FindToken (InfFile
, FILES_SECTION_STRING
, EFI_FILE_NAME_STRING
, Index
, Value
);
1031 if (Status
== EFI_SUCCESS
) {
1035 strcpy (FvInfo
->FvFiles
[Index
], Value
);
1041 if (FindSection (InfFile
, COMPONENT_SECTION_STRING
)) {
1044 // Read component FV_VARIABLE
1046 Status
= FindToken (InfFile
, COMPONENT_SECTION_STRING
, EFI_NV_VARIABLE_STRING
, 0, Value
);
1048 if (Status
== EFI_SUCCESS
) {
1050 // Add the component
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
);
1059 FvInfo
->FvComponents
[Index
].Size
= (UINTN
) Value64
;
1061 printf ("WARNING: Could not read %s.\n", EFI_NV_VARIABLE_STRING
);
1066 // Read component FV_EVENT_LOG
1068 Status
= FindToken (InfFile
, COMPONENT_SECTION_STRING
, EFI_NV_EVENT_LOG_STRING
, 0, Value
);
1070 if (Status
== EFI_SUCCESS
) {
1072 // Add the component
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
);
1081 FvInfo
->FvComponents
[Index
].Size
= (UINTN
) Value64
;
1083 printf ("WARNING: Could not read %s.\n", EFI_NV_EVENT_LOG_STRING
);
1088 // Read component FV_FTW_WORKING
1090 Status
= FindToken (InfFile
, COMPONENT_SECTION_STRING
, EFI_NV_FTW_WORKING_STRING
, 0, Value
);
1092 if (Status
== EFI_SUCCESS
) {
1094 // Add the component
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
);
1103 FvInfo
->FvComponents
[Index
].Size
= (UINTN
) Value64
;
1105 printf ("WARNING: Could not read %s.\n", EFI_NV_FTW_WORKING_STRING
);
1110 // Read component FV_FTW_SPARE
1112 Status
= FindToken (InfFile
, COMPONENT_SECTION_STRING
, EFI_NV_FTW_SPARE_STRING
, 0, Value
);
1114 if (Status
== EFI_SUCCESS
) {
1116 // Add the component
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
);
1125 FvInfo
->FvComponents
[Index
].Size
= (UINTN
) Value64
;
1127 printf ("WARNING: Could not read %s.\n", EFI_NV_FTW_SPARE_STRING
);
1131 // Compute size for easy access later
1134 for (Index
= 0; FvInfo
->FvBlocks
[Index
].NumBlocks
; Index
++) {
1135 FvInfo
->Size
+= FvInfo
->FvBlocks
[Index
].NumBlocks
* FvInfo
->FvBlocks
[Index
].BlockLength
;
1142 UpdateFfsFileState (
1143 IN EFI_FFS_FILE_HEADER
*FfsFile
,
1144 IN EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
1148 Routine Description:
1150 This function changes the FFS file attributes based on the erase polarity
1155 FfsFile File header.
1164 if (FvHeader
->Attributes
& EFI_FVB_ERASE_POLARITY
) {
1165 FfsFile
->State
= (UINT8
)~(FfsFile
->State
);
1171 IN EFI_FFS_FILE_HEADER
*FfsFile
,
1172 IN OUT UINT32
*Alignment
1176 Routine Description:
1178 This function determines the alignment of the FFS input file from the file
1183 FfsFile FFS file to parse
1184 Alignment The minimum required alignment of the FFS file, in bytes
1188 EFI_SUCCESS The function completed successfully.
1189 EFI_INVALID_PARAMETER One of the input parameters was invalid.
1190 EFI_ABORTED An error occurred.
1195 // Verify input parameters.
1197 if (FfsFile
== NULL
|| Alignment
== NULL
) {
1198 return EFI_INVALID_PARAMETER
;
1201 switch ((FfsFile
->Attributes
>> 3) & 0x07) {
1207 *Alignment
= (1 << 0);
1212 // 16 byte alignment
1214 *Alignment
= (1 << 4);
1219 // 128 byte alignment
1221 *Alignment
= (1 << 7);
1226 // 512 byte alignment
1228 *Alignment
= (1 << 9);
1233 // 1K byte alignment
1235 *Alignment
= (1 << 10);
1240 // 4K byte alignment
1242 *Alignment
= (1 << 12);
1247 // 32K byte alignment
1249 *Alignment
= (1 << 15);
1254 // 64K byte alignment
1256 *Alignment
= (1 << 16);
1260 Error (NULL
, 0, 0, "nvalid file attribute calculated, this is most likely a utility error", NULL
);
1269 IN OUT MEMORY_FILE
*FvImage
,
1270 IN UINT32 DataAlignment
1274 Routine Description:
1276 This function adds a pad file to the FV image if it required to align the
1277 data of the next file.
1281 FvImage The memory image of the FV to add it to. The current offset
1283 DataAlignment The data alignment of the next FFS file.
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
1294 EFI_FFS_FILE_HEADER
*PadFile
;
1299 // Verify input parameters.
1301 if (FvImage
== NULL
) {
1302 return EFI_INVALID_PARAMETER
;
1305 // Basic assumption is we start from an 8 byte aligned address
1306 // and our file header is a multiple of 8 bytes
1308 assert ((UINTN
) FvImage
->CurrentFilePointer
% 8 == 0);
1309 assert (sizeof (EFI_FFS_FILE_HEADER
) % 8 == 0);
1312 // Check if a pad file is necessary
1314 if (((UINTN
) FvImage
->CurrentFilePointer
- (UINTN
) FvImage
->FileImage
+ sizeof (EFI_FFS_FILE_HEADER
)) % DataAlignment
== 0) {
1318 // Write pad file header
1320 PadFile
= (EFI_FFS_FILE_HEADER
*) FvImage
->CurrentFilePointer
;
1323 // Verify that we have enough space for the file header
1325 if ((UINTN
) (PadFile
+ sizeof (EFI_FFS_FILE_HEADER
)) >= (UINTN
) FvImage
->Eof
) {
1326 return EFI_OUT_OF_RESOURCES
;
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;
1336 // Calculate the pad file size
1339 // This is the earliest possible valid offset (current plus pad file header
1340 // plus the next file header)
1342 PadFileSize
= (UINTN
) FvImage
->CurrentFilePointer
- (UINTN
) FvImage
->FileImage
+ (sizeof (EFI_FFS_FILE_HEADER
) * 2);
1345 // Add whatever it takes to get to the next aligned address
1347 while ((PadFileSize
% DataAlignment
) != 0) {
1351 // Subtract the next file header size
1353 PadFileSize
-= sizeof (EFI_FFS_FILE_HEADER
);
1356 // Subtract the starting offset to get size
1358 PadFileSize
-= (UINTN
) FvImage
->CurrentFilePointer
- (UINTN
) FvImage
->FileImage
;
1361 // Write pad file size (calculated size minus next file header size)
1363 PadFile
->Size
[0] = (UINT8
) (PadFileSize
& 0xFF);
1364 PadFile
->Size
[1] = (UINT8
) ((PadFileSize
>> 8) & 0xFF);
1365 PadFile
->Size
[2] = (UINT8
) ((PadFileSize
>> 16) & 0xFF);
1368 // Fill in checksums and state, they must be 0 for checksumming.
1370 PadFile
->IntegrityCheck
.Checksum
.Header
= 0;
1371 PadFile
->IntegrityCheck
.Checksum
.File
= 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
);
1377 PadFile
->IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
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
1387 // Verify that we have enough space (including the padding
1389 if ((UINTN
) (PadFile
+ sizeof (EFI_FFS_FILE_HEADER
)) >= (UINTN
) FvImage
->Eof
) {
1390 return EFI_OUT_OF_RESOURCES
;
1393 // Update the current FV pointer
1395 FvImage
->CurrentFilePointer
+= PadFileSize
;
1402 IN EFI_FFS_FILE_HEADER
*FileBuffer
1406 Routine Description:
1408 This function checks the header to validate if it is a VTF file
1412 FileBuffer Buffer in which content of a file has been read.
1416 TRUE If this is a VTF file
1417 FALSE If this is not a VTF file
1421 EFI_GUID VtfGuid
= EFI_FFS_VOLUME_TOP_FILE_GUID
;
1422 if (!memcmp (&FileBuffer
->Name
, &VtfGuid
, sizeof (EFI_GUID
))) {
1430 FfsRebaseImageRead (
1431 IN VOID
*FileHandle
,
1432 IN UINTN FileOffset
,
1433 IN OUT UINT32
*ReadSize
,
1438 Routine Description:
1440 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
1444 FileHandle - The handle to the PE/COFF file
1446 FileOffset - The offset, in bytes, into the file to read
1448 ReadSize - The number of bytes to read from the file starting at FileOffset
1450 Buffer - A pointer to the buffer to read the data into.
1454 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
1458 CHAR8
*Destination8
;
1462 Destination8
= Buffer
;
1463 Source8
= (CHAR8
*) ((UINTN
) FileHandle
+ FileOffset
);
1466 *(Destination8
++) = *(Source8
++);
1474 IN OUT EFI_FFS_FILE_HEADER
*FfsFile
,
1475 IN EFI_PHYSICAL_ADDRESS BaseAddress
1479 Routine Description:
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.
1486 FfsFile A pointer to Ffs file image.
1487 BaseAddress The base address to use for rebasing the file image.
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.
1499 EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1500 UINTN MemoryImagePointer
;
1501 UINTN MemoryImagePointerAligned
;
1503 EFI_PHYSICAL_ADDRESS ImageAddress
;
1505 EFI_PHYSICAL_ADDRESS EntryPoint
;
1507 UINT32 Pe32FileSize
;
1508 UINT32 NewPe32BaseAddress
;
1511 EFI_FILE_SECTION_POINTER CurrentPe32Section
;
1512 UINT8 FileGuidString
[80];
1515 // Verify input parameters
1517 if (FfsFile
== NULL
) {
1518 return EFI_INVALID_PARAMETER
;
1521 // Convert the GUID to a string so we can at least report which file
1522 // if we find an error.
1524 PrintGuidToBuffer (&FfsFile
->Name
, FileGuidString
, sizeof (FileGuidString
), TRUE
);
1527 // Do some nominal checks on the file, then check for XIP.
1529 Status
= VerifyFfsFile (FfsFile
);
1530 if (EFI_ERROR (Status
)) {
1531 Error (NULL
, 0, 0, "invalid FFS file", FileGuidString
);
1532 return EFI_INVALID_PARAMETER
;
1535 if (FfsFile
->Type
!= EFI_FV_FILETYPE_SECURITY_CORE
&&
1536 FfsFile
->Type
!= EFI_FV_FILETYPE_PEI_CORE
&&
1537 FfsFile
->Type
!= EFI_FV_FILETYPE_PEIM
1540 // File is not XIP, so don't rebase
1545 // Rebase each PE32 section
1547 for (Index
= 1;; Index
++) {
1548 Status
= GetSectionByType (FfsFile
, EFI_SECTION_PE32
, Index
, &CurrentPe32Section
);
1549 if (EFI_ERROR (Status
)) {
1553 // Calculate the PE32 base address, the FFS file base plus the offset of the PE32 section
1555 NewPe32BaseAddress
= ((UINT32
) BaseAddress
) + ((UINTN
) CurrentPe32Section
.Pe32Section
- (UINTN
) FfsFile
);
1558 // Initialize context
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
;
1564 Status
= mPeCoffLoader
.GetImageInfo (&mPeCoffLoader
, &ImageContext
);
1566 if (EFI_ERROR (Status
)) {
1567 Error (NULL
, 0, 0, "GetImageInfo() failed", FileGuidString
);
1571 // Allocate a buffer for the image to be loaded into.
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
;
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
);
1592 Status
= mPeCoffLoader
.RelocateImage (&mPeCoffLoader
, &ImageContext
);
1593 if (EFI_ERROR (Status
)) {
1594 Error (NULL
, 0, 0, "RelocateImage() failure", FileGuidString
);
1595 free ((VOID
*) MemoryImagePointer
);
1599 ImageAddress
= ImageContext
.ImageAddress
;
1600 ImageSize
= ImageContext
.ImageSize
;
1601 EntryPoint
= ImageContext
.EntryPoint
;
1603 if (ImageSize
> Pe32FileSize
) {
1608 "rebased PE32 is larger than original PE32 image",
1609 "0x%X > 0x%X on file %s",
1614 free ((VOID
*) MemoryImagePointer
);
1618 memcpy (CurrentPe32Section
.Pe32Section
, (VOID
*) MemoryImagePointerAligned
, Pe32FileSize
);
1620 free ((VOID
*) MemoryImagePointer
);
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...
1627 if (Status
!= EFI_NOT_FOUND
) {
1628 Error (NULL
, 0, 0, "failed to parse PE32 section", FileGuidString
);
1637 IN UINT64 BaseAddress
,
1638 IN EFI_FFS_FILE_HEADER
*FfsFile
,
1639 IN OUT MEMORY_FILE
*SymImage
,
1640 IN CHAR8
*SourceFileName
1644 Routine Description:
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.
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.
1658 EFI_SUCCESS The function completed successfully.
1659 EFI_INVALID_PARAMETER One of the input parameters was invalid.
1660 EFI_ABORTED An error occurred.
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
];
1675 UINT64 TokenAddress
;
1678 EFI_FILE_SECTION_POINTER Pe32Section
;
1684 // Verify input parameters.
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
;
1691 // Check if we want to add this file
1694 // Get the file name
1696 strcpy (Buffer
, SourceFileName
);
1699 // Copy the file name for the path of the sym file and truncate the name portion.
1701 strcpy (SymFileName
, Buffer
);
1702 Ptr
= strrchr (SymFileName
, '\\');
1707 // Find the file extension and make it lower case
1709 Ptr
= strrchr (SymFileName
, '.');
1714 // Check if it is PEI file
1716 if (strstr (Buffer
, ".pei") != NULL
) {
1718 // Find the human readable portion
1720 if (!strtok (Buffer
, "-") ||
1721 !strtok (NULL
, "-") ||
1722 !strtok (NULL
, "-") ||
1723 !strtok (NULL
, "-") ||
1724 !strtok (NULL
, "-") ||
1725 !strcpy (Buffer
, strtok (NULL
, "."))
1727 Error (NULL
, 0, 0, "failed to find human readable portion of the file name in AddSymFile()", NULL
);
1731 // Save code module name
1733 strcpy (CodeModuleName
, Buffer
);
1736 // Add the symbol file name and extension to the file path.
1738 strcat (Buffer
, ".sym");
1739 strcat (SymFileName
, "\\");
1740 strcat (SymFileName
, Buffer
);
1743 // Only handle PEIM files.
1748 // Find PE32 section
1750 Status
= GetSectionByType (FfsFile
, EFI_SECTION_PE32
, 1, &Pe32Section
);
1753 // BUGBUG: Assume if no PE32 section it is PIC and hardcode base address
1755 if (Status
== EFI_NOT_FOUND
) {
1756 Status
= GetSectionByType (FfsFile
, EFI_SECTION_TE
, 1, &Pe32Section
);
1759 if (Status
== EFI_SUCCESS
) {
1760 Status
= GetPe32Info (
1761 (VOID
*) ((UINTN
) Pe32Section
.Pe32Section
+ sizeof (EFI_SECTION_PE32
)),
1767 if (Status
== EFI_NOT_FOUND
) {
1769 Status
= EFI_SUCCESS
;
1771 Error (NULL
, 0, 0, "could not parse a PE32 section from the PEI file", NULL
);
1776 if (EFI_ERROR (Status
)) {
1777 Error (NULL
, 0, 0, "GetPe32Info() could not get PE32 entry point for PEI file", NULL
);
1782 // Open the source file
1784 SourceFile
= fopen (SymFileName
, "r");
1785 if (SourceFile
== NULL
) {
1787 // SYM files are not required.
1792 // Read the first line
1794 if (fgets (Buffer
, _MAX_PATH
, SourceFile
) == NULL
) {
1798 // Make sure it matches the expected sym format
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
);
1808 while (feof (SourceFile
) == 0) {
1814 "%s | %s | %s | %s\n",
1821 // If the token starts with "??" ignore it
1823 if (Token
[0] == '?' && Token
[1] == '?') {
1827 // Get the token address
1829 AsciiStringToUint64 (Address
, TRUE
, &TokenAddress
);
1832 // Add the base address
1834 TokenAddress
+= BaseAddress
;
1837 // If PE32 or TE section then find the start of code. For PIC it is hardcoded.
1839 if (Pe32Section
.Pe32Section
) {
1841 // Add the offset of the PE32 section
1843 TokenAddress
+= (UINTN
) Pe32Section
.Pe32Section
- (UINTN
) FfsFile
;
1846 // Add the size of the PE32 section header
1848 TokenAddress
+= sizeof (EFI_PE32_SECTION
);
1851 // BUGBUG: Don't know why this is 0x28 bytes.
1853 TokenAddress
+= 0x28;
1856 // Add the beginning of the code
1858 TokenAddress
+= BaseOfCode
;
1862 "%s | %016I64X | %s | _%s%s\n",
1869 memcpy (SymImage
->CurrentFilePointer
, Buffer
, strlen (Buffer
) + 1);
1870 SymImage
->CurrentFilePointer
= (UINT8
*) (((UINTN
) SymImage
->CurrentFilePointer
) + strlen (Buffer
) + 1);
1874 fclose (SourceFile
);
1880 IN OUT MEMORY_FILE
*FvImage
,
1883 IN OUT EFI_FFS_FILE_HEADER
**VtfFileImage
,
1884 IN OUT MEMORY_FILE
*SymImage
1888 Routine Description:
1890 This function adds a file to the FV image. The file will pad to the
1891 appropriate alignment if required.
1895 FvImage The memory image of the FV to add it to. The current offset
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.
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.
1917 UINT32 CurrentFileAlignment
;
1919 EFI_PHYSICAL_ADDRESS CurrentFileBaseAddress
;
1920 UINT8 VtfHeaderChecksum
;
1921 UINT8 VtfFileChecksum
;
1924 #if (PI_SPECIFICATION_VERSION < 0x00010000)
1925 EFI_FFS_FILE_TAIL TailValue
;
1928 // Verify input parameters.
1930 if (FvImage
== NULL
|| FvInfo
== NULL
|| FvInfo
->FvFiles
[Index
][0] == 0 || VtfFileImage
== NULL
|| SymImage
== NULL
) {
1931 return EFI_INVALID_PARAMETER
;
1934 // Read the file to add
1936 NewFile
= fopen (FvInfo
->FvFiles
[Index
], "rb");
1938 if (NewFile
== NULL
) {
1939 Error (NULL
, 0, 0, FvInfo
->FvFiles
[Index
], "failed to open file for reading");
1943 // Get the file size
1945 FileSize
= _filelength (_fileno (NewFile
));
1948 // Read the file into a buffer
1950 FileBuffer
= malloc (FileSize
);
1951 if (FileBuffer
== NULL
) {
1952 Error (NULL
, 0, 0, "memory allocation failure", NULL
);
1953 return EFI_OUT_OF_RESOURCES
;
1956 NumBytesRead
= fread (FileBuffer
, sizeof (UINT8
), FileSize
, NewFile
);
1959 // Done with the file, from this point on we will just use the buffer read.
1964 // Verify read successful
1966 if (NumBytesRead
!= sizeof (UINT8
) * FileSize
) {
1968 Error (NULL
, 0, 0, FvInfo
->FvFiles
[Index
], "failed to read input file contents");
1972 // Verify space exists to add the file
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
;
1979 // Update the file state based on polarity of the FV.
1981 UpdateFfsFileState (
1982 (EFI_FFS_FILE_HEADER
*) FileBuffer
,
1983 (EFI_FIRMWARE_VOLUME_HEADER
*) FvImage
->FileImage
1987 // If we have a VTF file, add it at the top.
1989 if (IsVtfFile ((EFI_FFS_FILE_HEADER
*) FileBuffer
)) {
1990 if ((UINTN
) *VtfFileImage
== (UINTN
) FvImage
->Eof
) {
1992 // No previous VTF, add this one.
1994 *VtfFileImage
= (EFI_FFS_FILE_HEADER
*) (UINTN
) ((UINTN
) FvImage
->FileImage
+ FvInfo
->Size
- FileSize
);
1996 // Sanity check. The file MUST align appropriately
1998 if ((((UINTN
) *VtfFileImage
) & 0x07) != 0) {
1999 Error (NULL
, 0, 0, "VTF file does not align on 8-byte boundary", NULL
);
2002 // copy VTF File Header
2004 memcpy (*VtfFileImage
, FileBuffer
, sizeof (EFI_FFS_FILE_HEADER
));
2010 (UINT8
*) *VtfFileImage
+ sizeof (EFI_FFS_FILE_HEADER
),
2011 FileBuffer
+ sizeof (EFI_FFS_FILE_HEADER
),
2012 FileSize
- sizeof (EFI_FFS_FILE_HEADER
)
2016 // re-calculate the VTF File Header
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;
2024 VtfHeaderChecksum
= CalculateChecksum8 ((UINT8
*) *VtfFileImage
, sizeof (EFI_FFS_FILE_HEADER
));
2025 (*VtfFileImage
)->IntegrityCheck
.Checksum
.Header
= VtfHeaderChecksum
;
2027 // Determine if it has a tail
2029 if ((*VtfFileImage
)->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
2030 TailSize
= sizeof (EFI_FFS_FILE_TAIL
);
2035 if ((*VtfFileImage
)->Attributes
& FFS_ATTRIB_CHECKSUM
) {
2036 VtfFileChecksum
= CalculateChecksum8 ((UINT8
*) *VtfFileImage
, FileSize
- TailSize
);
2037 (*VtfFileImage
)->IntegrityCheck
.Checksum
.File
= VtfFileChecksum
;
2039 (*VtfFileImage
)->IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
2041 #if (PI_SPECIFICATION_VERSION < 0x00010000)
2043 // If it has a file tail, update it
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
;
2050 (*VtfFileImage
)->State
= FileState
;
2055 // Already found a VTF file.
2057 Error (NULL
, 0, 0, "multiple VTF files are illegal in a single FV", NULL
);
2063 // Check if alignment is required
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
]);
2072 // Add pad file if necessary
2074 Status
= AddPadFile (FvImage
, CurrentFileAlignment
);
2075 if (EFI_ERROR (Status
)) {
2076 printf ("ERROR: Could not align the file data properly.\n");
2083 if ((FvImage
->CurrentFilePointer
+ FileSize
) < FvImage
->Eof
) {
2087 memcpy (FvImage
->CurrentFilePointer
, FileBuffer
, FileSize
);
2090 // If the file is XIP, rebase
2092 CurrentFileBaseAddress
= FvInfo
->BaseAddress
+ ((UINTN
) FvImage
->CurrentFilePointer
- (UINTN
) FvImage
->FileImage
);
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;
2100 // Update Symbol file
2102 Status
= AddSymFile (
2103 CurrentFileBaseAddress
,
2104 (EFI_FFS_FILE_HEADER
*) FvImage
->CurrentFilePointer
,
2106 FvInfo
->FvFiles
[Index
]
2108 assert (!EFI_ERROR (Status
));
2111 // Update the current pointer in the FV image
2113 FvImage
->CurrentFilePointer
+= FileSize
;
2115 printf ("ERROR: The firmware volume is out of space, could not add file %s.\n", FvInfo
->FvFiles
[Index
]);
2119 // Make next file start at QWord Boundry
2121 while (((UINTN
) FvImage
->CurrentFilePointer
& 0x07) != 0) {
2122 FvImage
->CurrentFilePointer
++;
2125 // Free allocated memory.
2139 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
2140 VARIABLE_STORE_HEADER
*VarStoreHeader
;
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.
2146 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) FvImage
;
2147 FvImage
= FvImage
+ FvHeader
->HeaderLength
;
2149 VarStoreHeader
= (VARIABLE_STORE_HEADER
*) FvImage
;
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;
2172 AddFTWWorkingBlock (
2178 EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER
*FTWHeader
;
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;
2191 FTWHeader
->WorkingBlockValid
= 1;
2192 FTWHeader
->WorkingBlockInvalid
= 0;
2215 Routine Description:
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
2223 FvImage The memory image of the FV to add it to. The current offset
2225 FvInfo Pointer to information about the FV.
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.
2237 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
2240 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) FvImage
;
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
);
2253 printf ("Error. Unknown Non-FFS block %s \n", FvInfo
->FvComponents
[Index
].ComponentName
);
2257 FvImage
= FvImage
+ FvInfo
->FvComponents
[Index
].Size
;
2258 TotalSize
= TotalSize
+ FvInfo
->FvComponents
[Index
].Size
;
2261 // Index and TotalSize is zero mean there's no component, so this is an empty fv
2263 if ((Index
!= 0 || TotalSize
!= 0) && TotalSize
!= FvInfo
->Size
) {
2264 printf ("Error. Component size does not sum up to FV size.\n");
2273 IN MEMORY_FILE
*FvImage
,
2274 IN EFI_FFS_FILE_HEADER
*VtfFileImage
2278 Routine Description:
2280 This function places a pad file between the last file in the FV and the VTF
2281 file if the VTF file exists.
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.
2291 EFI_SUCCESS Completed successfully.
2292 EFI_INVALID_PARAMETER One of the input parameters was NULL.
2296 EFI_FFS_FILE_HEADER
*PadFile
;
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
2303 if ((UINTN
) VtfFileImage
== (UINTN
) FvImage
->Eof
|| (void *) FvImage
->CurrentFilePointer
== (void *) VtfFileImage
) {
2307 // Pad file starts at beginning of free space
2309 PadFile
= (EFI_FFS_FILE_HEADER
*) FvImage
->CurrentFilePointer
;
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;
2320 // FileSize includes the EFI_FFS_FILE_HEADER
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);
2328 // Fill in checksums and state, must be zero during checksum calculation.
2330 PadFile
->IntegrityCheck
.Checksum
.Header
= 0;
2331 PadFile
->IntegrityCheck
.Checksum
.File
= 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
);
2337 PadFile
->IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
2340 PadFile
->State
= EFI_FILE_HEADER_CONSTRUCTION
| EFI_FILE_HEADER_VALID
| EFI_FILE_DATA_VALID
;
2342 UpdateFfsFileState (
2343 (EFI_FFS_FILE_HEADER
*) PadFile
,
2344 (EFI_FIRMWARE_VOLUME_HEADER
*) FvImage
->FileImage
2347 // Update the current FV pointer
2349 FvImage
->CurrentFilePointer
= FvImage
->Eof
;
2356 IN MEMORY_FILE
*FvImage
,
2358 IN EFI_FFS_FILE_HEADER
*VtfFile
2362 Routine Description:
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.
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.
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.
2383 EFI_FFS_FILE_HEADER
*PeiCoreFile
;
2384 EFI_FFS_FILE_HEADER
*SecCoreFile
;
2386 EFI_FILE_SECTION_POINTER Pe32Section
;
2390 EFI_PHYSICAL_ADDRESS PeiCorePhysicalAddress
;
2391 EFI_PHYSICAL_ADDRESS SecCorePhysicalAddress
;
2392 EFI_PHYSICAL_ADDRESS
*SecCoreEntryAddressPtr
;
2393 UINT32
*Ia32ResetAddressPtr
;
2395 UINT8
*BytePointer2
;
2396 UINT16
*WordPointer
;
2399 EFI_FFS_FILE_STATE SavedState
;
2402 FIT_TABLE
*FitTablePtr
;
2403 #if (PI_SPECIFICATION_VERSION < 0x00010000)
2404 EFI_FFS_FILE_TAIL TailValue
;
2407 // Verify input parameters
2409 if (FvImage
== NULL
|| FvInfo
== NULL
|| VtfFile
== NULL
) {
2410 return EFI_INVALID_PARAMETER
;
2413 // Initialize FV library
2415 InitializeFvLib (FvImage
->FileImage
, (UINTN
) FvImage
->Eof
- (UINTN
) FvImage
->FileImage
);
2420 Status
= VerifyFfsFile (VtfFile
);
2421 if (EFI_ERROR (Status
)) {
2422 return EFI_INVALID_PARAMETER
;
2425 // Find the PEI Core
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
);
2433 // PEI Core found, now find PE32 or TE section
2435 Status
= GetSectionByType (PeiCoreFile
, EFI_SECTION_PE32
, 1, &Pe32Section
);
2436 if (Status
== EFI_NOT_FOUND
) {
2437 Status
= GetSectionByType (PeiCoreFile
, EFI_SECTION_TE
, 1, &Pe32Section
);
2440 if (EFI_ERROR (Status
)) {
2441 Error (NULL
, 0, 0, "could not find PE32 or TE section in PEI core file", NULL
);
2445 Status
= GetPe32Info (
2446 (VOID
*) ((UINTN
) Pe32Section
.Pe32Section
+ sizeof (EFI_SECTION_PE32
)),
2452 if (EFI_ERROR (Status
)) {
2453 Error (NULL
, 0, 0, "could not get PE32 entry point for PEI core", NULL
);
2457 // Physical address is FV base + offset of PE32 + offset of the entry point
2459 PeiCorePhysicalAddress
= FvInfo
->BaseAddress
;
2460 PeiCorePhysicalAddress
+= (UINTN
) Pe32Section
.Pe32Section
+ sizeof (EFI_SECTION_PE32
) - (UINTN
) FvImage
->FileImage
;
2461 PeiCorePhysicalAddress
+= EntryPoint
;
2463 if (MachineType
== EFI_IMAGE_MACHINE_IA64
) {
2465 // Update PEI_CORE address
2468 // Set the uncached attribute bit in the physical address
2470 PeiCorePhysicalAddress
|= 0x8000000000000000;
2473 // Check if address is aligned on a 16 byte boundary
2475 if (PeiCorePhysicalAddress
& 0xF) {
2477 "ERROR: PEI_CORE entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n",
2478 PeiCorePhysicalAddress
2483 // First Get the FIT table address
2485 FitAddress
= (*(UINT64
*) (FvImage
->Eof
- IPF_FIT_ADDRESS_OFFSET
)) & 0xFFFFFFFF;
2487 FitTablePtr
= (FIT_TABLE
*) (FvImage
->FileImage
+ (FitAddress
- FvInfo
->BaseAddress
));
2489 Status
= UpdatePeiCoreEntryInFit (FitTablePtr
, PeiCorePhysicalAddress
);
2491 if (!EFI_ERROR (Status
)) {
2492 UpdateFitCheckSum (FitTablePtr
);
2495 // Find the Sec Core
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
);
2503 // Sec Core found, now find PE32 section
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
);
2511 Status
= GetPe32Info (
2512 (VOID
*) ((UINTN
) Pe32Section
.Pe32Section
+ sizeof (EFI_SECTION_PE32
)),
2517 if (EFI_ERROR (Status
)) {
2518 Error (NULL
, 0, 0, "could not get PE32 entry point for SEC core", NULL
);
2522 // Physical address is FV base + offset of PE32 + offset of the entry point
2524 SecCorePhysicalAddress
= FvInfo
->BaseAddress
;
2525 SecCorePhysicalAddress
+= (UINTN
) Pe32Section
.Pe32Section
+ sizeof (EFI_SECTION_PE32
) - (UINTN
) FvImage
->FileImage
;
2526 SecCorePhysicalAddress
+= EntryPoint
;
2529 // Update SEC_CORE address
2532 // Set the uncached attribute bit in the physical address
2534 SecCorePhysicalAddress
|= 0x8000000000000000;
2537 // Update the address
2539 SecCoreEntryAddressPtr
= (EFI_PHYSICAL_ADDRESS
*) ((UINTN
) FvImage
->Eof
- IPF_SALE_ENTRY_ADDRESS_OFFSET
);
2540 *SecCoreEntryAddressPtr
= SecCorePhysicalAddress
;
2543 // Check if address is aligned on a 16 byte boundary
2545 if (SecCorePhysicalAddress
& 0xF) {
2547 "ERROR: SALE_ENTRY entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n",
2548 SecCorePhysicalAddress
2552 } else if ((MachineType
== EFI_IMAGE_MACHINE_IA32
) ||
2553 (MachineType
== EFI_IMAGE_MACHINE_X64
)) {
2555 // Get the location to update
2557 Ia32ResetAddressPtr
= (UINT32
*) ((UINTN
) FvImage
->Eof
- IA32_PEI_CORE_ENTRY_OFFSET
);
2560 // Write lower 32 bits of physical address
2562 *Ia32ResetAddressPtr
= (UINT32
) PeiCorePhysicalAddress
;
2565 // Update the BFV base address
2567 Ia32ResetAddressPtr
= (UINT32
*) ((UINTN
) FvImage
->Eof
- 4);
2568 *Ia32ResetAddressPtr
= (UINT32
) (FvInfo
->BaseAddress
);
2573 // Update the Startup AP in the FVH header block ZeroVector region.
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
++;
2581 // Calculate the checksum
2583 WordPointer
= (UINT16
*) ((UINTN
) FvImage
->FileImage
);
2584 for (Index
= 0; Index
< SIZEOF_STARTUP_DATA_ARRAY
/ 2; Index
++) {
2585 CheckSum
= (UINT16
) (CheckSum
+ ((UINT16
) *WordPointer
));
2589 // Update the checksum field
2591 BytePointer
= (UINT8
*) ((UINTN
) FvImage
->FileImage
);
2592 BytePointer
+= (SIZEOF_STARTUP_DATA_ARRAY
- 2);
2593 WordPointer
= (UINT16
*) BytePointer
;
2594 *WordPointer
= (UINT16
) (0x10000 - (UINT32
) CheckSum
);
2596 Error (NULL
, 0, 0, "invalid machine type in PEI core", "machine type=0x%X", (UINT32
) MachineType
);
2600 // Determine if it has an FFS file tail.
2602 if (VtfFile
->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
2603 TailSize
= sizeof (EFI_FFS_FILE_TAIL
);
2608 // Now update file checksum
2610 SavedState
= VtfFile
->State
;
2611 VtfFile
->IntegrityCheck
.Checksum
.File
= 0;
2613 if (VtfFile
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
2614 VtfFile
->IntegrityCheck
.Checksum
.File
= CalculateChecksum8 (
2616 GetLength (VtfFile
->Size
) - TailSize
2619 VtfFile
->IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
2622 VtfFile
->State
= SavedState
;
2624 #if (PI_SPECIFICATION_VERSION < 0x00010000)
2626 // Update tail if present
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
;
2639 OUT UINT32
*EntryPoint
,
2640 OUT UINT32
*BaseOfCode
,
2641 OUT UINT16
*MachineType
2645 Routine Description:
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.
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.
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.
2667 EFI_IMAGE_DOS_HEADER
*DosHeader
;
2668 EFI_IMAGE_NT_HEADERS
*NtHeader
;
2669 EFI_TE_IMAGE_HEADER
*TeHeader
;
2672 // Verify input parameters
2675 return EFI_INVALID_PARAMETER
;
2679 // First check whether it is one TE Image.
2681 TeHeader
= (EFI_TE_IMAGE_HEADER
*) Pe32
;
2682 if (TeHeader
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
2684 // By TeImage Header to get output
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
;
2691 // Then check whether
2692 // is the DOS header
2694 DosHeader
= (EFI_IMAGE_DOS_HEADER
*) Pe32
;
2697 // Verify DOS header is expected
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
;
2704 // Immediately following is the NT header.
2706 NtHeader
= (EFI_IMAGE_NT_HEADERS
*) ((UINTN
) Pe32
+ DosHeader
->e_lfanew
);
2709 // Verify NT header is expected
2711 if (NtHeader
->Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2712 printf ("ERROR: Unrecognized image signature 0x%08X.\n", NtHeader
->Signature
);
2713 return EFI_UNSUPPORTED
;
2718 *EntryPoint
= NtHeader
->OptionalHeader
.AddressOfEntryPoint
;
2719 *BaseOfCode
= NtHeader
->OptionalHeader
.BaseOfCode
;
2720 *MachineType
= NtHeader
->FileHeader
.Machine
;
2724 // Verify machine type is supported
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
;
2736 // Exposed function implementations (prototypes are defined in GenFvImageLib.h)
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
2751 Routine Description:
2753 This is the main function which will be called from application.
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.
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.
2776 MEMORY_FILE InfMemoryFile
;
2777 MEMORY_FILE FvImageMemoryFile
;
2778 MEMORY_FILE SymImageMemoryFile
;
2781 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
2782 EFI_FFS_FILE_HEADER
*VtfFileImage
;
2785 // Check for invalid parameter
2787 if (InfFileImage
== NULL
|| FvImage
== NULL
|| FvImageSize
== NULL
|| FvFileName
== NULL
) {
2788 return EFI_INVALID_PARAMETER
;
2791 // Initialize file structures
2793 InfMemoryFile
.FileImage
= InfFileImage
;
2794 InfMemoryFile
.CurrentFilePointer
= InfFileImage
;
2795 InfMemoryFile
.Eof
= InfFileImage
+ InfFileSize
;
2798 // Parse the FV inf file for header information
2800 Status
= ParseFvInf (&InfMemoryFile
, &FvInfo
);
2801 if (EFI_ERROR (Status
)) {
2802 printf ("ERROR: Could not parse the input INF file.\n");
2806 // Update the file name return values
2808 strcpy (*FvFileName
, FvInfo
.FvName
);
2809 strcpy (*SymFileName
, FvInfo
.SymName
);
2812 // Calculate the FV size
2814 *FvImageSize
= FvInfo
.Size
;
2819 *FvImage
= malloc (*FvImageSize
);
2820 if (*FvImage
== NULL
) {
2821 return EFI_OUT_OF_RESOURCES
;
2824 // Allocate space for symbol file storage
2826 *SymImage
= malloc (SYMBOL_FILE_SIZE
);
2827 if (*SymImage
== NULL
) {
2828 return EFI_OUT_OF_RESOURCES
;
2831 // Initialize the FV to the erase polarity
2833 if (FvInfo
.FvAttributes
& EFI_FVB_ERASE_POLARITY
) {
2834 memset (*FvImage
, -1, *FvImageSize
);
2836 memset (*FvImage
, 0, *FvImageSize
);
2839 // Initialize FV header
2841 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) *FvImage
;
2844 // Initialize the zero vector to all zeros.
2846 memset (FvHeader
->ZeroVector
, 0, 16);
2849 // Copy the FFS GUID
2851 memcpy (&FvHeader
->FileSystemGuid
, &FvInfo
.FvGuid
, sizeof (EFI_GUID
));
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;
2862 FvHeader
->Revision
= EFI_FVH_PI_REVISION
;
2863 FvHeader
->ExtHeaderOffset
= 0;
2864 FvHeader
->Reserved
[0] = 0;
2867 // Copy firmware block map
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
;
2874 // Add block map terminator
2876 FvHeader
->FvBlockMap
[Index
].NumBlocks
= 0;
2877 FvHeader
->FvBlockMap
[Index
].BlockLength
= 0;
2880 // Complete the header
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
));
2887 // If there is no FFS file, find and generate each components of the FV
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");
2900 // Initialize our "file" view of the buffer
2902 FvImageMemoryFile
.FileImage
= *FvImage
;
2903 FvImageMemoryFile
.CurrentFilePointer
= *FvImage
+ FvHeader
->HeaderLength
;
2904 FvImageMemoryFile
.Eof
= *FvImage
+*FvImageSize
;
2907 // Initialize our "file" view of the symbol file.
2909 SymImageMemoryFile
.FileImage
= *SymImage
;
2910 SymImageMemoryFile
.CurrentFilePointer
= *SymImage
;
2911 SymImageMemoryFile
.Eof
= *FvImage
+ SYMBOL_FILE_SIZE
;
2914 // Initialize the FV library.
2916 InitializeFvLib (FvImageMemoryFile
.FileImage
, FvInfo
.Size
);
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
2924 assert ((((UINTN
) FvImageMemoryFile
.CurrentFilePointer
) % 8) == 0);
2927 // Initialize the VTF file address.
2929 VtfFileImage
= (EFI_FFS_FILE_HEADER
*) FvImageMemoryFile
.Eof
;
2934 for (Index
= 0; FvInfo
.FvFiles
[Index
][0] != 0; Index
++) {
2938 Status
= AddFile (&FvImageMemoryFile
, &FvInfo
, Index
, &VtfFileImage
, &SymImageMemoryFile
);
2941 // Exit if error detected while adding the file
2943 if (EFI_ERROR (Status
)) {
2944 printf ("ERROR: Could not add file %s.\n", FvInfo
.FvFiles
[Index
]);
2950 // If there is a VTF file, some special actions need to occur.
2952 if ((UINTN
) VtfFileImage
!= (UINTN
) FvImageMemoryFile
.Eof
) {
2954 // Pad from the end of the last file to the beginning of the VTF file.
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");
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.
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");
2979 // Determine final Sym file size
2981 *SymImageSize
= SymImageMemoryFile
.CurrentFilePointer
- SymImageMemoryFile
.FileImage
;
2987 UpdatePeiCoreEntryInFit (
2988 IN FIT_TABLE
*FitTablePtr
,
2989 IN UINT64 PeiCorePhysicalAddress
2993 Routine Description:
2995 This function is used to update the Pei Core address in FIT, this can be used by Sec core to pass control from
3000 FitTablePtr - The pointer of FIT_TABLE.
3001 PeiCorePhysicalAddress - The address of Pei Core entry.
3005 EFI_SUCCESS - The PEI_CORE FIT entry was updated successfully.
3006 EFI_NOT_FOUND - Not found the PEI_CORE FIT entry.
3010 FIT_TABLE
*TmpFitPtr
;
3012 UINTN NumFitComponents
;
3014 TmpFitPtr
= FitTablePtr
;
3015 NumFitComponents
= TmpFitPtr
->CompSize
;
3017 for (Index
= 0; Index
< NumFitComponents
; Index
++) {
3018 if ((TmpFitPtr
->CvAndType
& FIT_TYPE_MASK
) == COMP_TYPE_FIT_PEICORE
) {
3019 TmpFitPtr
->CompAddress
= PeiCorePhysicalAddress
;
3026 return EFI_NOT_FOUND
;
3031 IN FIT_TABLE
*FitTablePtr
3035 Routine Description:
3037 This function is used to update the checksum for FIT.
3042 FitTablePtr - The pointer of FIT_TABLE.
3050 if ((FitTablePtr
->CvAndType
& CHECKSUM_BIT_MASK
) >> 7) {
3051 FitTablePtr
->CheckSum
= 0;
3052 FitTablePtr
->CheckSum
= CalculateChecksum8 ((UINT8
*) FitTablePtr
, FitTablePtr
->CompSize
* 16);