3 Copyright (c) 2004 - 2010, 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
) {
971 if (strcmp (Value
, AUTO_STRING
) == 0) {
972 Value64
= (UINT64
) -1;
975 // Update the number of blocks
977 Status
= AsciiStringToUint64 (Value
, FALSE
, &Value64
);
978 if (EFI_ERROR (Status
)) {
979 Error (NULL
, 0, 0, Value
, "invalid value for %s", EFI_NUM_BLOCKS_STRING
);
984 FvInfo
->FvBlocks
[Index
].NumBlocks
= (UINT32
) Value64
;
987 // If there is no number of blocks, but there is a size, then we have a mismatched pair
988 // and should return an error.
990 Status
= FindToken (InfFile
, OPTIONS_SECTION_STRING
, EFI_BLOCK_SIZE_STRING
, Index
, Value
);
991 if (!EFI_ERROR (Status
)) {
992 Error (NULL
, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING
, EFI_BLOCK_SIZE_STRING
);
1002 // Read the size of blocks
1004 Status
= FindToken (InfFile
, OPTIONS_SECTION_STRING
, EFI_BLOCK_SIZE_STRING
, Index
, Value
);
1006 if (Status
== EFI_SUCCESS
) {
1008 // Update the number of blocks
1010 Status
= AsciiStringToUint64 (Value
, FALSE
, &Value64
);
1011 if (EFI_ERROR (Status
)) {
1012 Error (NULL
, 0, 0, Value
, "invalid value specified for %s", EFI_BLOCK_SIZE_STRING
);
1016 FvInfo
->FvBlocks
[Index
].BlockLength
= (UINT32
) Value64
;
1019 // There is a number of blocks, but there is no size, so we have a mismatched pair
1020 // and should return an error.
1022 Error (NULL
, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING
, EFI_BLOCK_SIZE_STRING
);
1029 for (Index
= 0; Index
< MAX_NUMBER_OF_FILES_IN_FV
; Index
++) {
1031 // Read the number of blocks
1033 Status
= FindToken (InfFile
, FILES_SECTION_STRING
, EFI_FILE_NAME_STRING
, Index
, Value
);
1035 if (Status
== EFI_SUCCESS
) {
1039 strcpy (FvInfo
->FvFiles
[Index
], Value
);
1045 if (FindSection (InfFile
, COMPONENT_SECTION_STRING
)) {
1048 Status
= FindTokenInstanceInSection (
1050 COMPONENT_SECTION_STRING
,
1052 FvInfo
->FvComponents
[Index
].ComponentName
,
1055 if (EFI_ERROR (Status
)) {
1058 Status
= AsciiStringToUint64 (Value
, FALSE
, &Value64
);
1059 if (EFI_ERROR (Status
)) {
1060 Error (NULL
, 0, 0, Value
, "not a valid integer");
1064 FvInfo
->FvComponents
[Index
].Size
= (UINTN
) Value64
;
1069 // Compute size for easy access later
1072 for (Index
= 0; FvInfo
->FvBlocks
[Index
].NumBlocks
; Index
++) {
1073 if ((FvInfo
->Size
== (UINTN
) -1 && Index
> 0) ||
1074 (FvInfo
->FvBlocks
[Index
].NumBlocks
== (UINT32
) -1 && Index
> 0)
1077 // Error 1. more pairs after AUTO
1078 // Error 2. AUTO appear in non-first position
1080 Error (NULL
, 0, 0, NULL
, "cannot have more than one pair of %s and %s if %s is set to %s",
1081 EFI_NUM_BLOCKS_STRING
, EFI_BLOCK_SIZE_STRING
,
1082 EFI_NUM_BLOCKS_STRING
, AUTO_STRING
1087 if (FvInfo
->FvBlocks
[Index
].NumBlocks
== (UINT32
) -1) {
1088 FvInfo
->Size
= (UINTN
) -1;
1090 FvInfo
->Size
+= FvInfo
->FvBlocks
[Index
].NumBlocks
* FvInfo
->FvBlocks
[Index
].BlockLength
;
1094 if (FvInfo
->Size
== (UINTN
) -1 && FvInfo
->FvFiles
[0][0] == 0) {
1096 // Non FFS FV cannot set block number to AUTO
1098 Error (NULL
, 0, 0, "non-FFS FV", "cannot set %s to %s", EFI_NUM_BLOCKS_STRING
, AUTO_STRING
);
1106 UpdateFfsFileState (
1107 IN EFI_FFS_FILE_HEADER
*FfsFile
,
1108 IN EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
1112 Routine Description:
1114 This function changes the FFS file attributes based on the erase polarity
1119 FfsFile File header.
1128 if (FvHeader
->Attributes
& EFI_FVB_ERASE_POLARITY
) {
1129 FfsFile
->State
= (UINT8
)~(FfsFile
->State
);
1135 IN EFI_FFS_FILE_HEADER
*FfsFile
,
1136 IN OUT UINT32
*Alignment
1140 Routine Description:
1142 This function determines the alignment of the FFS input file from the file
1147 FfsFile FFS file to parse
1148 Alignment The minimum required alignment of the FFS file, in bytes
1152 EFI_SUCCESS The function completed successfully.
1153 EFI_INVALID_PARAMETER One of the input parameters was invalid.
1154 EFI_ABORTED An error occurred.
1159 // Verify input parameters.
1161 if (FfsFile
== NULL
|| Alignment
== NULL
) {
1162 return EFI_INVALID_PARAMETER
;
1165 switch ((FfsFile
->Attributes
>> 3) & 0x07) {
1171 *Alignment
= (1 << 0);
1176 // 16 byte alignment
1178 *Alignment
= (1 << 4);
1183 // 128 byte alignment
1185 *Alignment
= (1 << 7);
1190 // 512 byte alignment
1192 *Alignment
= (1 << 9);
1197 // 1K byte alignment
1199 *Alignment
= (1 << 10);
1204 // 4K byte alignment
1206 *Alignment
= (1 << 12);
1211 // 32K byte alignment
1213 *Alignment
= (1 << 15);
1218 // 64K byte alignment
1220 *Alignment
= (1 << 16);
1224 Error (NULL
, 0, 0, "nvalid file attribute calculated, this is most likely a utility error", NULL
);
1233 IN OUT MEMORY_FILE
*FvImage
,
1234 IN UINT32 DataAlignment
1238 Routine Description:
1240 This function adds a pad file to the FV image if it required to align the
1241 data of the next file.
1245 FvImage The memory image of the FV to add it to. The current offset
1247 DataAlignment The data alignment of the next FFS file.
1251 EFI_SUCCESS The function completed successfully.
1252 EFI_INVALID_PARAMETER One of the input parameters was invalid.
1253 EFI_OUT_OF_RESOURCES Insufficient resources exist in the FV to complete
1258 EFI_FFS_FILE_HEADER
*PadFile
;
1263 // Verify input parameters.
1265 if (FvImage
== NULL
) {
1266 return EFI_INVALID_PARAMETER
;
1269 // Basic assumption is we start from an 8 byte aligned address
1270 // and our file header is a multiple of 8 bytes
1272 assert ((UINTN
) FvImage
->CurrentFilePointer
% 8 == 0);
1273 assert (sizeof (EFI_FFS_FILE_HEADER
) % 8 == 0);
1276 // Check if a pad file is necessary
1278 if (((UINTN
) FvImage
->CurrentFilePointer
- (UINTN
) FvImage
->FileImage
+ sizeof (EFI_FFS_FILE_HEADER
)) % DataAlignment
== 0) {
1282 // Write pad file header
1284 PadFile
= (EFI_FFS_FILE_HEADER
*) FvImage
->CurrentFilePointer
;
1287 // Verify that we have enough space for the file header
1289 if ((UINTN
) (PadFile
+ sizeof (EFI_FFS_FILE_HEADER
)) >= (UINTN
) FvImage
->Eof
) {
1290 return EFI_OUT_OF_RESOURCES
;
1293 UuidCreate (&PadFileGuid
);
1294 memset (PadFile
, 0, sizeof (EFI_FFS_FILE_HEADER
));
1295 memcpy (&PadFile
->Name
, &PadFileGuid
, sizeof (EFI_GUID
));
1296 PadFile
->Type
= EFI_FV_FILETYPE_FFS_PAD
;
1297 PadFile
->Attributes
= 0;
1300 // Calculate the pad file size
1303 // This is the earliest possible valid offset (current plus pad file header
1304 // plus the next file header)
1306 PadFileSize
= (UINTN
) FvImage
->CurrentFilePointer
- (UINTN
) FvImage
->FileImage
+ (sizeof (EFI_FFS_FILE_HEADER
) * 2);
1309 // Add whatever it takes to get to the next aligned address
1311 while ((PadFileSize
% DataAlignment
) != 0) {
1315 // Subtract the next file header size
1317 PadFileSize
-= sizeof (EFI_FFS_FILE_HEADER
);
1320 // Subtract the starting offset to get size
1322 PadFileSize
-= (UINTN
) FvImage
->CurrentFilePointer
- (UINTN
) FvImage
->FileImage
;
1325 // Write pad file size (calculated size minus next file header size)
1327 PadFile
->Size
[0] = (UINT8
) (PadFileSize
& 0xFF);
1328 PadFile
->Size
[1] = (UINT8
) ((PadFileSize
>> 8) & 0xFF);
1329 PadFile
->Size
[2] = (UINT8
) ((PadFileSize
>> 16) & 0xFF);
1332 // Fill in checksums and state, they must be 0 for checksumming.
1334 PadFile
->IntegrityCheck
.Checksum
.Header
= 0;
1335 PadFile
->IntegrityCheck
.Checksum
.File
= 0;
1337 PadFile
->IntegrityCheck
.Checksum
.Header
= CalculateChecksum8 ((UINT8
*) PadFile
, sizeof (EFI_FFS_FILE_HEADER
));
1338 if (PadFile
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
1339 #if (PI_SPECIFICATION_VERSION < 0x00010000)
1340 PadFile
->IntegrityCheck
.Checksum
.File
= CalculateChecksum8 ((UINT8
*) PadFile
, PadFileSize
);
1342 PadFile
->IntegrityCheck
.Checksum
.File
= CalculateChecksum8 ((UINT8
*) ((UINTN
)PadFile
+ sizeof (EFI_FFS_FILE_HEADER
)), PadFileSize
- sizeof (EFI_FFS_FILE_HEADER
));
1345 PadFile
->IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
1348 PadFile
->State
= EFI_FILE_HEADER_CONSTRUCTION
| EFI_FILE_HEADER_VALID
| EFI_FILE_DATA_VALID
;
1349 UpdateFfsFileState (
1350 (EFI_FFS_FILE_HEADER
*) PadFile
,
1351 (EFI_FIRMWARE_VOLUME_HEADER
*) FvImage
->FileImage
1355 // Verify that we have enough space (including the padding
1357 if ((UINTN
) (PadFile
+ sizeof (EFI_FFS_FILE_HEADER
)) >= (UINTN
) FvImage
->Eof
) {
1358 return EFI_OUT_OF_RESOURCES
;
1361 // Update the current FV pointer
1363 FvImage
->CurrentFilePointer
+= PadFileSize
;
1370 IN EFI_FFS_FILE_HEADER
*FileBuffer
1374 Routine Description:
1376 This function checks the header to validate if it is a VTF file
1380 FileBuffer Buffer in which content of a file has been read.
1384 TRUE If this is a VTF file
1385 FALSE If this is not a VTF file
1389 EFI_GUID VtfGuid
= EFI_FFS_VOLUME_TOP_FILE_GUID
;
1390 if (!memcmp (&FileBuffer
->Name
, &VtfGuid
, sizeof (EFI_GUID
))) {
1398 FfsRebaseImageRead (
1399 IN VOID
*FileHandle
,
1400 IN UINTN FileOffset
,
1401 IN OUT UINT32
*ReadSize
,
1406 Routine Description:
1408 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
1412 FileHandle - The handle to the PE/COFF file
1414 FileOffset - The offset, in bytes, into the file to read
1416 ReadSize - The number of bytes to read from the file starting at FileOffset
1418 Buffer - A pointer to the buffer to read the data into.
1422 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
1426 CHAR8
*Destination8
;
1430 Destination8
= Buffer
;
1431 Source8
= (CHAR8
*) ((UINTN
) FileHandle
+ FileOffset
);
1434 *(Destination8
++) = *(Source8
++);
1442 IN OUT EFI_FFS_FILE_HEADER
*FfsFile
,
1443 IN EFI_PHYSICAL_ADDRESS BaseAddress
1447 Routine Description:
1449 This function determines if a file is XIP and should be rebased. It will
1450 rebase any PE32 sections found in the file using the base address.
1454 FfsFile A pointer to Ffs file image.
1455 BaseAddress The base address to use for rebasing the file image.
1459 EFI_SUCCESS The image was properly rebased.
1460 EFI_INVALID_PARAMETER An input parameter is invalid.
1461 EFI_ABORTED An error occurred while rebasing the input file image.
1462 EFI_OUT_OF_RESOURCES Could not allocate a required resource.
1467 EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1468 UINTN MemoryImagePointer
;
1469 UINTN MemoryImagePointerAligned
;
1471 EFI_PHYSICAL_ADDRESS ImageAddress
;
1473 EFI_PHYSICAL_ADDRESS EntryPoint
;
1475 UINT32 Pe32FileSize
;
1476 UINT32 NewPe32BaseAddress
;
1479 EFI_FILE_SECTION_POINTER CurrentPe32Section
;
1480 UINT8 FileGuidString
[80];
1483 // Verify input parameters
1485 if (FfsFile
== NULL
) {
1486 return EFI_INVALID_PARAMETER
;
1489 // Convert the GUID to a string so we can at least report which file
1490 // if we find an error.
1492 PrintGuidToBuffer (&FfsFile
->Name
, FileGuidString
, sizeof (FileGuidString
), TRUE
);
1495 // Do some nominal checks on the file, then check for XIP.
1497 Status
= VerifyFfsFile (FfsFile
);
1498 if (EFI_ERROR (Status
)) {
1499 Error (NULL
, 0, 0, "invalid FFS file", FileGuidString
);
1500 return EFI_INVALID_PARAMETER
;
1503 if (FfsFile
->Type
!= EFI_FV_FILETYPE_SECURITY_CORE
&&
1504 FfsFile
->Type
!= EFI_FV_FILETYPE_PEI_CORE
&&
1505 FfsFile
->Type
!= EFI_FV_FILETYPE_PEIM
1508 // File is not XIP, so don't rebase
1513 // Rebase each PE32 section
1515 for (Index
= 1;; Index
++) {
1516 Status
= GetSectionByType (FfsFile
, EFI_SECTION_PE32
, Index
, &CurrentPe32Section
);
1517 if (EFI_ERROR (Status
)) {
1521 // Calculate the PE32 base address, the FFS file base plus the offset of the PE32 section
1523 NewPe32BaseAddress
= ((UINT32
) BaseAddress
) + ((UINTN
) CurrentPe32Section
.Pe32Section
- (UINTN
) FfsFile
);
1526 // Initialize context
1528 memset (&ImageContext
, 0, sizeof (ImageContext
));
1529 ImageContext
.Handle
= (VOID
*) ((UINTN
) CurrentPe32Section
.Pe32Section
+ sizeof (EFI_PE32_SECTION
));
1530 ImageContext
.ImageRead
= (EFI_PEI_PE_COFF_LOADER_READ_FILE
) FfsRebaseImageRead
;
1532 Status
= mPeCoffLoader
.GetImageInfo (&mPeCoffLoader
, &ImageContext
);
1534 if (EFI_ERROR (Status
)) {
1535 Error (NULL
, 0, 0, "GetImageInfo() failed", FileGuidString
);
1539 // Allocate a buffer for the image to be loaded into.
1541 Pe32FileSize
= GetLength (CurrentPe32Section
.Pe32Section
->CommonHeader
.Size
);
1542 MemoryImagePointer
= (UINTN
) (malloc (Pe32FileSize
+ 0x1000));
1543 MemoryImagePointerAligned
= (MemoryImagePointer
+ 0x0FFF) & (-1 << 12);
1544 if (MemoryImagePointerAligned
== 0) {
1545 Error (NULL
, 0, 0, "memory allocation failure", NULL
);
1546 return EFI_OUT_OF_RESOURCES
;
1552 ImageContext
.ImageAddress
= MemoryImagePointerAligned
;
1553 Status
= mPeCoffLoader
.LoadImage (&mPeCoffLoader
, &ImageContext
);
1554 if (EFI_ERROR (Status
)) {
1555 Error (NULL
, 0, 0, "LoadImage() failure", FileGuidString
);
1556 free ((VOID
*) MemoryImagePointer
);
1560 Status
= mPeCoffLoader
.RelocateImage (&mPeCoffLoader
, &ImageContext
);
1561 if (EFI_ERROR (Status
)) {
1562 Error (NULL
, 0, 0, "RelocateImage() failure", FileGuidString
);
1563 free ((VOID
*) MemoryImagePointer
);
1567 ImageAddress
= ImageContext
.ImageAddress
;
1568 ImageSize
= ImageContext
.ImageSize
;
1569 EntryPoint
= ImageContext
.EntryPoint
;
1571 if (ImageSize
> Pe32FileSize
) {
1576 "rebased PE32 is larger than original PE32 image",
1577 "0x%X > 0x%X on file %s",
1582 free ((VOID
*) MemoryImagePointer
);
1586 memcpy (CurrentPe32Section
.Pe32Section
, (VOID
*) MemoryImagePointerAligned
, Pe32FileSize
);
1588 free ((VOID
*) MemoryImagePointer
);
1591 // the above for loop will always exit with EFI_NOT_FOUND if it completes
1592 // normally. If Index == 1 at exit, then no PE32 sections were found. If it
1593 // exits with any other error code, then something broke...
1595 if (Status
!= EFI_NOT_FOUND
) {
1596 Error (NULL
, 0, 0, "failed to parse PE32 section", FileGuidString
);
1605 IN UINT64 BaseAddress
,
1606 IN EFI_FFS_FILE_HEADER
*FfsFile
,
1607 IN OUT MEMORY_FILE
*SymImage
,
1608 IN CHAR8
*SourceFileName
1612 Routine Description:
1614 This function adds the SYM tokens in the source file to the destination file.
1615 The SYM tokens are updated to reflect the base address.
1619 BaseAddress The base address for the new SYM tokens.
1620 FfsFile Pointer to the beginning of the FFS file in question.
1621 SymImage The memory file to update with symbol information.
1622 SourceFileName The source file.
1626 EFI_SUCCESS The function completed successfully.
1627 EFI_INVALID_PARAMETER One of the input parameters was invalid.
1628 EFI_ABORTED An error occurred.
1634 CHAR8 Buffer
[_MAX_PATH
];
1635 CHAR8 Type
[_MAX_PATH
];
1636 CHAR8 Address
[_MAX_PATH
];
1637 CHAR8 Section
[_MAX_PATH
];
1638 CHAR8 Token
[_MAX_PATH
];
1639 CHAR8 SymFileName
[_MAX_PATH
];
1640 CHAR8 CodeModuleName
[_MAX_PATH
];
1643 UINT64 TokenAddress
;
1646 EFI_FILE_SECTION_POINTER Pe32Section
;
1652 // Verify input parameters.
1654 if (BaseAddress
== 0 || FfsFile
== NULL
|| SymImage
== NULL
|| SourceFileName
== NULL
) {
1655 Error (NULL
, 0, 0, "invalid parameter passed to AddSymFile()", NULL
);
1656 return EFI_INVALID_PARAMETER
;
1659 // Check if we want to add this file
1662 // Get the file name
1664 strcpy (Buffer
, SourceFileName
);
1667 // Copy the file name for the path of the sym file and truncate the name portion.
1669 strcpy (SymFileName
, Buffer
);
1670 Ptr
= strrchr (SymFileName
, '\\');
1675 // Find the file extension and make it lower case
1677 Ptr
= strrchr (SymFileName
, '.');
1682 // Check if it is PEI file
1684 if (strstr (Buffer
, ".pei") != NULL
) {
1686 // Find the human readable portion
1688 if (!strtok (Buffer
, "-") ||
1689 !strtok (NULL
, "-") ||
1690 !strtok (NULL
, "-") ||
1691 !strtok (NULL
, "-") ||
1692 !strtok (NULL
, "-") ||
1693 !strcpy (Buffer
, strtok (NULL
, "."))
1695 Error (NULL
, 0, 0, "failed to find human readable portion of the file name in AddSymFile()", NULL
);
1699 // Save code module name
1701 strcpy (CodeModuleName
, Buffer
);
1704 // Add the symbol file name and extension to the file path.
1706 strcat (Buffer
, ".sym");
1707 strcat (SymFileName
, "\\");
1708 strcat (SymFileName
, Buffer
);
1711 // Only handle PEIM files.
1716 // Find PE32 section
1718 Status
= GetSectionByType (FfsFile
, EFI_SECTION_PE32
, 1, &Pe32Section
);
1721 // BUGBUG: Assume if no PE32 section it is PIC and hardcode base address
1723 if (Status
== EFI_NOT_FOUND
) {
1724 Status
= GetSectionByType (FfsFile
, EFI_SECTION_TE
, 1, &Pe32Section
);
1727 if (Status
== EFI_SUCCESS
) {
1728 Status
= GetPe32Info (
1729 (VOID
*) ((UINTN
) Pe32Section
.Pe32Section
+ sizeof (EFI_SECTION_PE32
)),
1735 if (Status
== EFI_NOT_FOUND
) {
1737 Status
= EFI_SUCCESS
;
1739 Error (NULL
, 0, 0, "could not parse a PE32 section from the PEI file", NULL
);
1744 if (EFI_ERROR (Status
)) {
1745 Error (NULL
, 0, 0, "GetPe32Info() could not get PE32 entry point for PEI file", NULL
);
1750 // Open the source file
1752 SourceFile
= fopen (SymFileName
, "r");
1753 if (SourceFile
== NULL
) {
1755 // SYM files are not required.
1760 // Read the first line
1762 if (fgets (Buffer
, _MAX_PATH
, SourceFile
) == NULL
) {
1766 // Make sure it matches the expected sym format
1768 if (strcmp (Buffer
, "TEXTSYM format | V1.0\n")) {
1769 fclose (SourceFile
);
1770 Error (NULL
, 0, 0, "AddSymFile() found unexpected sym format in input file", NULL
);
1776 while (feof (SourceFile
) == 0) {
1782 "%s | %s | %s | %s\n",
1789 // If the token starts with "??" ignore it
1791 if (Token
[0] == '?' && Token
[1] == '?') {
1795 // Get the token address
1797 AsciiStringToUint64 (Address
, TRUE
, &TokenAddress
);
1800 // Add the base address
1802 TokenAddress
+= BaseAddress
;
1805 // If PE32 or TE section then find the start of code. For PIC it is hardcoded.
1807 if (Pe32Section
.Pe32Section
) {
1809 // Add the offset of the PE32 section
1811 TokenAddress
+= (UINTN
) Pe32Section
.Pe32Section
- (UINTN
) FfsFile
;
1814 // Add the size of the PE32 section header
1816 TokenAddress
+= sizeof (EFI_PE32_SECTION
);
1819 // BUGBUG: Don't know why this is 0x28 bytes.
1821 TokenAddress
+= 0x28;
1824 // Add the beginning of the code
1826 TokenAddress
+= BaseOfCode
;
1830 "%s | %016I64X | %s | _%s%s\n",
1837 memcpy (SymImage
->CurrentFilePointer
, Buffer
, strlen (Buffer
) + 1);
1838 SymImage
->CurrentFilePointer
= (UINT8
*) (((UINTN
) SymImage
->CurrentFilePointer
) + strlen (Buffer
) + 1);
1842 fclose (SourceFile
);
1848 IN OUT MEMORY_FILE
*FvImage
,
1849 IN OUT FV_INFO
*FvInfo
,
1850 IN OUT EFI_FFS_FILE_HEADER
**VtfFileImage
,
1851 IN OUT UINTN
*FvImageCapacity
1854 Routine Description:
1855 Increase the size of FV image by 1 block. The routine may reallocate memory
1856 depending on the capacity of the FV image.
1859 FvImage The memory image of the FV to add it to. The current offset
1861 FvInfo Pointer to information about the FV.
1862 VtfFileImage A pointer to the VTF file within the FvImage. If this is equal
1863 to the end of the FvImage then no VTF previously found.
1864 FvImageCapacity Capacity of image buffer for FV.
1867 EFI_SUCCESS The function completed successfully.
1868 EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the reallocation.
1875 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
1876 BOOLEAN AllocateNewMemory
;
1877 EFI_FFS_FILE_HEADER
*NewVtfFileImage
;
1878 UINT32 VtfFileLength
;
1881 OldSize
= (UINTN
) FvImage
->Eof
- (UINTN
) FvImage
->FileImage
;
1882 IncreaseSize
= FvInfo
->FvBlocks
[0].BlockLength
;
1883 assert (OldSize
== FvInfo
->FvBlocks
[0].NumBlocks
* FvInfo
->FvBlocks
[0].BlockLength
);
1886 // Assume we have enough capacity
1888 AllocateNewMemory
= FALSE
;
1891 if (OldSize
+ IncreaseSize
> *FvImageCapacity
) {
1892 AllocateNewMemory
= TRUE
;
1894 // Increase capacity by one unit
1896 *FvImageCapacity
= OldSize
+ FV_CAPACITY_INCREASE_UNIT
;
1897 FileImage
= malloc (*FvImageCapacity
);
1899 if (FileImage
== NULL
) {
1900 Error (NULL
, 0, 0, "memory allocation failure", NULL
);
1901 return EFI_OUT_OF_RESOURCES
;
1905 // Initialize the content per FV polarity
1907 if (FvInfo
->FvAttributes
& EFI_FVB_ERASE_POLARITY
) {
1908 memset (FileImage
, -1, *FvImageCapacity
);
1910 memset (FileImage
, 0, *FvImageCapacity
);
1914 // Copy the FV content before VTF
1916 memcpy (FileImage
, FvImage
->FileImage
, (UINTN
) *VtfFileImage
- (UINTN
) FvImage
->FileImage
);
1918 FileImage
= FvImage
->FileImage
;
1922 // Move VTF if it exists
1924 NewVtfFileImage
= (EFI_FFS_FILE_HEADER
*) (FileImage
+ ((UINTN
) *VtfFileImage
- (UINTN
) FvImage
->FileImage
) + IncreaseSize
);
1925 if ((UINTN
) *VtfFileImage
!= (UINTN
) FvImage
->Eof
) {
1927 // Exchange the VTF buffer from end to start for two purpose:
1928 // 1. Exchange: Preserve the default value per FV polarity
1929 // 2. End->Start: Avoid destroying the VTF data during exchanging
1931 VtfFileLength
= GetLength ((*VtfFileImage
)->Size
);
1932 while (VtfFileLength
-- != 0) {
1933 TempByte
= ((UINT8
*) VtfFileImage
)[VtfFileLength
];
1934 ((UINT8
*) VtfFileImage
)[VtfFileLength
] = ((UINT8
*) NewVtfFileImage
)[VtfFileLength
];
1935 ((UINT8
*) NewVtfFileImage
)[VtfFileLength
] = TempByte
;
1940 // Update VTF Pointer
1942 *VtfFileImage
= NewVtfFileImage
;
1947 FvInfo
->FvBlocks
[0].NumBlocks
++;
1952 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) FileImage
;
1953 FvHeader
->FvBlockMap
[0].NumBlocks
= FvInfo
->FvBlocks
[0].NumBlocks
;
1954 FvHeader
->FvLength
= OldSize
+ IncreaseSize
;
1955 FvHeader
->Checksum
= 0;
1956 FvHeader
->Checksum
= CalculateChecksum16 ((UINT16
*) FvHeader
, FvHeader
->HeaderLength
/ sizeof (UINT16
));
1961 if (AllocateNewMemory
) {
1962 free (FvImage
->FileImage
);
1963 FvImage
->CurrentFilePointer
= FileImage
+ (FvImage
->CurrentFilePointer
- FvImage
->FileImage
);
1964 FvImage
->FileImage
= FileImage
;
1966 FvImage
->Eof
= FvImage
->FileImage
+ OldSize
+ IncreaseSize
;
1968 InitializeFvLib (FvImage
->FileImage
, OldSize
+ IncreaseSize
);
1974 IN OUT MEMORY_FILE
*FvImage
,
1977 IN OUT EFI_FFS_FILE_HEADER
**VtfFileImage
,
1978 IN OUT MEMORY_FILE
*SymImage
,
1979 IN OUT UINTN
*FvImageCapacity
1983 Routine Description:
1985 This function adds a file to the FV image. The file will pad to the
1986 appropriate alignment if required.
1990 FvImage The memory image of the FV to add it to. The current offset
1992 FvInfo Pointer to information about the FV.
1993 Index The file in the FvInfo file list to add.
1994 VtfFileImage A pointer to the VTF file within the FvImage. If this is equal
1995 to the end of the FvImage then no VTF previously found.
1996 SymImage The memory image of the Sym file to update if symbols are present.
1997 The current offset must be valid.
1998 FvImageCapacity Capacity of image buffer for FV.
2002 EFI_SUCCESS The function completed successfully.
2003 EFI_INVALID_PARAMETER One of the input parameters was invalid.
2004 EFI_ABORTED An error occurred.
2005 EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the add.
2013 UINT32 CurrentFileAlignment
;
2015 EFI_PHYSICAL_ADDRESS CurrentFileBaseAddress
;
2016 UINT8 VtfHeaderChecksum
;
2017 UINT8 VtfFileChecksum
;
2020 #if (PI_SPECIFICATION_VERSION < 0x00010000)
2021 EFI_FFS_FILE_TAIL TailValue
;
2024 // Verify input parameters.
2026 if (FvImage
== NULL
|| FvInfo
== NULL
|| FvInfo
->FvFiles
[Index
][0] == 0 || VtfFileImage
== NULL
|| SymImage
== NULL
) {
2027 return EFI_INVALID_PARAMETER
;
2030 // Read the file to add
2032 NewFile
= fopen (FvInfo
->FvFiles
[Index
], "rb");
2034 if (NewFile
== NULL
) {
2035 Error (NULL
, 0, 0, FvInfo
->FvFiles
[Index
], "failed to open file for reading");
2039 // Get the file size
2041 FileSize
= _filelength (_fileno (NewFile
));
2044 // Read the file into a buffer
2046 FileBuffer
= malloc (FileSize
);
2047 if (FileBuffer
== NULL
) {
2048 Error (NULL
, 0, 0, "memory allocation failure", NULL
);
2049 return EFI_OUT_OF_RESOURCES
;
2052 NumBytesRead
= fread (FileBuffer
, sizeof (UINT8
), FileSize
, NewFile
);
2055 // Done with the file, from this point on we will just use the buffer read.
2060 // Verify read successful
2062 if (NumBytesRead
!= sizeof (UINT8
) * FileSize
) {
2063 Error (NULL
, 0, 0, FvInfo
->FvFiles
[Index
], "failed to read input file contents");
2064 Status
= EFI_ABORTED
;
2068 // Verify space exists to add the file
2070 while (FileSize
> (UINTN
) ((UINTN
) *VtfFileImage
- (UINTN
) FvImage
->CurrentFilePointer
)) {
2071 if (FvInfo
->Size
!= (UINTN
) -1) {
2072 Error (NULL
, 0, 0, FvInfo
->FvFiles
[Index
], "insufficient space remains to add the file");
2073 Status
= EFI_OUT_OF_RESOURCES
;
2077 // FV Size is AUTO, increase by one block
2079 Status
= ReallocateFvImage (FvImage
, FvInfo
, VtfFileImage
, FvImageCapacity
);
2080 if (EFI_ERROR (Status
)) {
2081 Error (NULL
, 0, 0, FvInfo
->FvFiles
[Index
], "insufficient resources to add the file");
2087 // Update the file state based on polarity of the FV.
2089 UpdateFfsFileState (
2090 (EFI_FFS_FILE_HEADER
*) FileBuffer
,
2091 (EFI_FIRMWARE_VOLUME_HEADER
*) FvImage
->FileImage
2095 // If we have a VTF file, add it at the top.
2097 if (IsVtfFile ((EFI_FFS_FILE_HEADER
*) FileBuffer
)) {
2098 if ((UINTN
) *VtfFileImage
== (UINTN
) FvImage
->Eof
) {
2100 // No previous VTF, add this one.
2102 *VtfFileImage
= (EFI_FFS_FILE_HEADER
*) (UINTN
) ((UINTN
) FvImage
->FileImage
+ FvInfo
->Size
- FileSize
);
2104 // Sanity check. The file MUST align appropriately
2106 if ((((UINTN
) *VtfFileImage
) & 0x07) != 0) {
2107 Error (NULL
, 0, 0, "VTF file does not align on 8-byte boundary", NULL
);
2110 // copy VTF File Header
2112 memcpy (*VtfFileImage
, FileBuffer
, sizeof (EFI_FFS_FILE_HEADER
));
2118 (UINT8
*) *VtfFileImage
+ sizeof (EFI_FFS_FILE_HEADER
),
2119 FileBuffer
+ sizeof (EFI_FFS_FILE_HEADER
),
2120 FileSize
- sizeof (EFI_FFS_FILE_HEADER
)
2124 // re-calculate the VTF File Header
2126 FileState
= (*VtfFileImage
)->State
;
2127 (*VtfFileImage
)->State
= 0;
2128 *(UINT32
*) ((*VtfFileImage
)->Size
) = FileSize
;
2129 (*VtfFileImage
)->IntegrityCheck
.Checksum
.Header
= 0;
2130 (*VtfFileImage
)->IntegrityCheck
.Checksum
.File
= 0;
2132 VtfHeaderChecksum
= CalculateChecksum8 ((UINT8
*) *VtfFileImage
, sizeof (EFI_FFS_FILE_HEADER
));
2133 (*VtfFileImage
)->IntegrityCheck
.Checksum
.Header
= VtfHeaderChecksum
;
2135 // Determine if it has a tail
2137 if ((*VtfFileImage
)->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
2138 TailSize
= sizeof (EFI_FFS_FILE_TAIL
);
2143 if ((*VtfFileImage
)->Attributes
& FFS_ATTRIB_CHECKSUM
) {
2144 #if (PI_SPECIFICATION_VERSION < 0x00010000)
2145 VtfFileChecksum
= CalculateChecksum8 ((UINT8
*) *VtfFileImage
, FileSize
- TailSize
);
2147 VtfFileChecksum
= CalculateChecksum8 ((UINT8
*) ((UINTN
)*VtfFileImage
+ sizeof (EFI_FFS_FILE_HEADER
)), FileSize
- TailSize
- sizeof(EFI_FFS_FILE_HEADER
));
2149 (*VtfFileImage
)->IntegrityCheck
.Checksum
.File
= VtfFileChecksum
;
2151 (*VtfFileImage
)->IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
2153 #if (PI_SPECIFICATION_VERSION < 0x00010000)
2155 // If it has a file tail, update it
2157 if ((*VtfFileImage
)->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
2158 TailValue
= (EFI_FFS_FILE_TAIL
) (~((*VtfFileImage
)->IntegrityCheck
.TailReference
));
2159 *(EFI_FFS_FILE_TAIL
*) (((UINTN
) (*VtfFileImage
) + GetLength ((*VtfFileImage
)->Size
) - sizeof (EFI_FFS_FILE_TAIL
))) = TailValue
;
2162 (*VtfFileImage
)->State
= FileState
;
2163 Status
= EFI_SUCCESS
;
2167 // Already found a VTF file.
2169 Error (NULL
, 0, 0, "multiple VTF files are illegal in a single FV", NULL
);
2170 Status
= EFI_ABORTED
;
2175 // Check if alignment is required
2177 Status
= ReadFfsAlignment ((EFI_FFS_FILE_HEADER
*) FileBuffer
, &CurrentFileAlignment
);
2178 if (EFI_ERROR (Status
)) {
2179 printf ("ERROR: Could not determine alignment of file %s.\n", FvInfo
->FvFiles
[Index
]);
2180 Status
= EFI_ABORTED
;
2184 // Add pad file if necessary
2186 while (EFI_ERROR (AddPadFile (FvImage
, CurrentFileAlignment
))) {
2187 if (FvInfo
->Size
!= (UINTN
) -1) {
2188 printf ("ERROR: Could not align the file data properly.\n");
2189 Status
= EFI_ABORTED
;
2193 // FV Size is AUTO, increase by one block
2195 Status
= ReallocateFvImage (FvImage
, FvInfo
, VtfFileImage
, FvImageCapacity
);
2196 if (EFI_ERROR (Status
)) {
2197 Error (NULL
, 0, 0, FvInfo
->FvFiles
[Index
], "insufficient resources to add the file");
2206 while (FileSize
> (UINTN
) ((UINTN
) *VtfFileImage
- (UINTN
) FvImage
->CurrentFilePointer
)) {
2207 if (FvInfo
->Size
!= (UINTN
) -1) {
2208 printf ("ERROR: The firmware volume is out of space, could not add file %s.\n", FvInfo
->FvFiles
[Index
]);
2209 Status
= EFI_ABORTED
;
2213 // FV Size is AUTO, increase by one one block
2215 Status
= ReallocateFvImage (FvImage
, FvInfo
, VtfFileImage
, FvImageCapacity
);
2216 if (EFI_ERROR (Status
)) {
2217 Error (NULL
, 0, 0, FvInfo
->FvFiles
[Index
], "insufficient resources to add the file");
2226 memcpy (FvImage
->CurrentFilePointer
, FileBuffer
, FileSize
);
2229 // If the file is XIP, rebase
2231 CurrentFileBaseAddress
= FvInfo
->BaseAddress
+ ((UINTN
) FvImage
->CurrentFilePointer
- (UINTN
) FvImage
->FileImage
);
2233 // Status = RebaseFfsFile ((EFI_FFS_FILE_HEADER*) FvImage->CurrentFilePointer, CurrentFileBaseAddress);
2234 // if (EFI_ERROR(Status)) {
2235 // printf ("ERROR: Could not rebase the file %s.\n", FvInfo->FvFiles[Index]);
2236 // return EFI_ABORTED;
2239 // Update Symbol file
2241 Status
= AddSymFile (
2242 CurrentFileBaseAddress
,
2243 (EFI_FFS_FILE_HEADER
*) FvImage
->CurrentFilePointer
,
2245 FvInfo
->FvFiles
[Index
]
2247 assert (!EFI_ERROR (Status
));
2250 // Update the current pointer in the FV image
2252 FvImage
->CurrentFilePointer
+= FileSize
;
2255 // Make next file start at QWord Boundry
2257 while (((UINTN
) FvImage
->CurrentFilePointer
& 0x07) != 0) {
2258 FvImage
->CurrentFilePointer
++;
2263 // Free allocated memory.
2276 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
2277 VARIABLE_STORE_HEADER
*VarStoreHeader
;
2279 // Variable block should exclude FvHeader. Since the length of
2280 // FvHeader depends on the block map, which is variable length,
2281 // we could only decide the actual variable block length here.
2283 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) FvImage
;
2284 FvImage
= FvImage
+ FvHeader
->HeaderLength
;
2286 VarStoreHeader
= (VARIABLE_STORE_HEADER
*) FvImage
;
2288 VarStoreHeader
->Signature
= VARIABLE_STORE_SIGNATURE
;
2289 VarStoreHeader
->Size
= Size
- FvHeader
->HeaderLength
;
2290 VarStoreHeader
->Format
= VARIABLE_STORE_FORMATTED
;
2291 VarStoreHeader
->State
= VARIABLE_STORE_HEALTHY
;
2292 VarStoreHeader
->Reserved
= 0;
2293 VarStoreHeader
->Reserved1
= 0;
2309 AddFTWWorkingBlock (
2315 EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER
*FTWHeader
;
2319 FTWHeader
= (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER
*) FvImage
;
2320 memcpy (&FTWHeader
->Signature
, &(FvInfo
->FvGuid
), sizeof (EFI_GUID
));
2321 FTWHeader
->WriteQueueSize
= Size
- sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER
);
2322 CalculateCrc32 (FvImage
, sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER
), &Crc32
);
2323 FTWHeader
->Crc
= Crc32
;
2324 if (FvInfo
->FvAttributes
& EFI_FVB_ERASE_POLARITY
) {
2325 FTWHeader
->WorkingBlockValid
= 0;
2326 FTWHeader
->WorkingBlockInvalid
= 1;
2328 FTWHeader
->WorkingBlockValid
= 1;
2329 FTWHeader
->WorkingBlockInvalid
= 0;
2352 Routine Description:
2354 This function generate the non FFS FV image, such as the working block
2355 and spare block. How each component of the FV is built is component
2360 FvImage The memory image of the FV to add it to. The current offset
2362 FvInfo Pointer to information about the FV.
2366 EFI_SUCCESS The function completed successfully.
2367 EFI_INVALID_PARAMETER One of the input parameters was invalid.
2368 EFI_ABORTED An error occurred.
2369 EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the add.
2374 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
2377 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) FvImage
;
2380 for (Index
= 0; FvInfo
->FvComponents
[Index
].Size
!= 0; Index
++) {
2381 if (_stricmp (FvInfo
->FvComponents
[Index
].ComponentName
, EFI_NV_VARIABLE_STRING
) == 0) {
2382 AddVariableBlock (FvImage
, FvInfo
->FvComponents
[Index
].Size
, FvInfo
);
2383 } else if (_stricmp (FvInfo
->FvComponents
[Index
].ComponentName
, EFI_NV_EVENT_LOG_STRING
) == 0) {
2384 AddEventLogBlock (FvImage
, FvInfo
->FvComponents
[Index
].Size
, FvInfo
);
2385 } else if (_stricmp (FvInfo
->FvComponents
[Index
].ComponentName
, EFI_NV_FTW_WORKING_STRING
) == 0) {
2386 AddFTWWorkingBlock (FvImage
, FvInfo
->FvComponents
[Index
].Size
, FvInfo
);
2387 } else if (_stricmp (FvInfo
->FvComponents
[Index
].ComponentName
, EFI_NV_FTW_SPARE_STRING
) == 0) {
2388 AddFTWSpareBlock (FvImage
, FvInfo
->FvComponents
[Index
].Size
, FvInfo
);
2390 printf ("Warning: Unknown Non-FFS block %s \n", FvInfo
->FvComponents
[Index
].ComponentName
);
2393 FvImage
= FvImage
+ FvInfo
->FvComponents
[Index
].Size
;
2394 TotalSize
= TotalSize
+ FvInfo
->FvComponents
[Index
].Size
;
2397 // Index and TotalSize is zero mean there's no component, so this is an empty fv
2399 if ((Index
!= 0 || TotalSize
!= 0) && TotalSize
!= FvInfo
->Size
) {
2400 printf ("Error. Component size does not sum up to FV size.\n");
2409 IN MEMORY_FILE
*FvImage
,
2410 IN EFI_FFS_FILE_HEADER
*VtfFileImage
2414 Routine Description:
2416 This function places a pad file between the last file in the FV and the VTF
2417 file if the VTF file exists.
2421 FvImage Memory file for the FV memory image
2422 VtfFileImage The address of the VTF file. If this is the end of the FV
2423 image, no VTF exists and no pad file is needed.
2427 EFI_SUCCESS Completed successfully.
2428 EFI_INVALID_PARAMETER One of the input parameters was NULL.
2432 EFI_FFS_FILE_HEADER
*PadFile
;
2436 // If there is no VTF or the VTF naturally follows the previous file without a
2437 // pad file, then there's nothing to do
2439 if ((UINTN
) VtfFileImage
== (UINTN
) FvImage
->Eof
|| (void *) FvImage
->CurrentFilePointer
== (void *) VtfFileImage
) {
2443 // Pad file starts at beginning of free space
2445 PadFile
= (EFI_FFS_FILE_HEADER
*) FvImage
->CurrentFilePointer
;
2450 memset (PadFile
, 0, sizeof (EFI_FFS_FILE_HEADER
));
2451 memcpy (&PadFile
->Name
, &DefaultFvPadFileNameGuid
, sizeof (EFI_GUID
));
2452 PadFile
->Type
= EFI_FV_FILETYPE_FFS_PAD
;
2453 PadFile
->Attributes
= 0;
2456 // FileSize includes the EFI_FFS_FILE_HEADER
2458 FileSize
= (UINTN
) VtfFileImage
- (UINTN
) FvImage
->CurrentFilePointer
;
2459 PadFile
->Size
[0] = (UINT8
) (FileSize
& 0x000000FF);
2460 PadFile
->Size
[1] = (UINT8
) ((FileSize
& 0x0000FF00) >> 8);
2461 PadFile
->Size
[2] = (UINT8
) ((FileSize
& 0x00FF0000) >> 16);
2464 // Fill in checksums and state, must be zero during checksum calculation.
2466 PadFile
->IntegrityCheck
.Checksum
.Header
= 0;
2467 PadFile
->IntegrityCheck
.Checksum
.File
= 0;
2469 PadFile
->IntegrityCheck
.Checksum
.Header
= CalculateChecksum8 ((UINT8
*) PadFile
, sizeof (EFI_FFS_FILE_HEADER
));
2470 if (PadFile
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
2471 #if (PI_SPECIFICATION_VERSION < 0x00010000)
2472 PadFile
->IntegrityCheck
.Checksum
.File
= CalculateChecksum8 ((UINT8
*) PadFile
, FileSize
);
2474 PadFile
->IntegrityCheck
.Checksum
.File
= CalculateChecksum8 ((UINT8
*) ((UINTN
) PadFile
+ sizeof (EFI_FFS_FILE_HEADER
)), FileSize
- sizeof (EFI_FFS_FILE_HEADER
));
2477 PadFile
->IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
2480 PadFile
->State
= EFI_FILE_HEADER_CONSTRUCTION
| EFI_FILE_HEADER_VALID
| EFI_FILE_DATA_VALID
;
2482 UpdateFfsFileState (
2483 (EFI_FFS_FILE_HEADER
*) PadFile
,
2484 (EFI_FIRMWARE_VOLUME_HEADER
*) FvImage
->FileImage
2487 // Update the current FV pointer
2489 FvImage
->CurrentFilePointer
= FvImage
->Eof
;
2496 IN MEMORY_FILE
*FvImage
,
2498 IN EFI_FFS_FILE_HEADER
*VtfFile
2502 Routine Description:
2504 This parses the FV looking for the PEI core and then plugs the address into
2505 the SALE_ENTRY point of the BSF/VTF for IPF and does BUGBUG TBD action to
2506 complete an IA32 Bootstrap FV.
2510 FvImage Memory file for the FV memory image
2511 FvInfo Information read from INF file.
2512 VtfFile Pointer to the VTF file in the FV image.
2516 EFI_SUCCESS Function Completed successfully.
2517 EFI_ABORTED Error encountered.
2518 EFI_INVALID_PARAMETER A required parameter was NULL.
2519 EFI_NOT_FOUND PEI Core file not found.
2523 EFI_FFS_FILE_HEADER
*PeiCoreFile
;
2524 EFI_FFS_FILE_HEADER
*SecCoreFile
;
2526 EFI_FILE_SECTION_POINTER Pe32Section
;
2530 EFI_PHYSICAL_ADDRESS PeiCorePhysicalAddress
;
2531 EFI_PHYSICAL_ADDRESS SecCorePhysicalAddress
;
2532 EFI_PHYSICAL_ADDRESS
*SecCoreEntryAddressPtr
;
2533 UINT32
*Ia32ResetAddressPtr
;
2535 UINT8
*BytePointer2
;
2536 UINT16
*WordPointer
;
2539 EFI_FFS_FILE_STATE SavedState
;
2542 FIT_TABLE
*FitTablePtr
;
2543 #if (PI_SPECIFICATION_VERSION < 0x00010000)
2544 EFI_FFS_FILE_TAIL TailValue
;
2547 // Verify input parameters
2549 if (FvImage
== NULL
|| FvInfo
== NULL
|| VtfFile
== NULL
) {
2550 return EFI_INVALID_PARAMETER
;
2553 // Initialize FV library
2555 InitializeFvLib (FvImage
->FileImage
, (UINTN
) FvImage
->Eof
- (UINTN
) FvImage
->FileImage
);
2560 Status
= VerifyFfsFile (VtfFile
);
2561 if (EFI_ERROR (Status
)) {
2562 return EFI_INVALID_PARAMETER
;
2565 // Find the PEI Core
2567 Status
= GetFileByType (EFI_FV_FILETYPE_PEI_CORE
, 1, &PeiCoreFile
);
2568 if (EFI_ERROR (Status
) || PeiCoreFile
== NULL
) {
2569 Error (NULL
, 0, 0, "could not find the PEI core in the FV", NULL
);
2573 // PEI Core found, now find PE32 or TE section
2575 Status
= GetSectionByType (PeiCoreFile
, EFI_SECTION_PE32
, 1, &Pe32Section
);
2576 if (Status
== EFI_NOT_FOUND
) {
2577 Status
= GetSectionByType (PeiCoreFile
, EFI_SECTION_TE
, 1, &Pe32Section
);
2580 if (EFI_ERROR (Status
)) {
2581 Error (NULL
, 0, 0, "could not find PE32 or TE section in PEI core file", NULL
);
2585 Status
= GetPe32Info (
2586 (VOID
*) ((UINTN
) Pe32Section
.Pe32Section
+ sizeof (EFI_SECTION_PE32
)),
2592 if (EFI_ERROR (Status
)) {
2593 Error (NULL
, 0, 0, "could not get PE32 entry point for PEI core", NULL
);
2597 // Physical address is FV base + offset of PE32 + offset of the entry point
2599 PeiCorePhysicalAddress
= FvInfo
->BaseAddress
;
2600 PeiCorePhysicalAddress
+= (UINTN
) Pe32Section
.Pe32Section
+ sizeof (EFI_SECTION_PE32
) - (UINTN
) FvImage
->FileImage
;
2601 PeiCorePhysicalAddress
+= EntryPoint
;
2603 if (MachineType
== EFI_IMAGE_MACHINE_IA64
) {
2605 // Update PEI_CORE address
2608 // Set the uncached attribute bit in the physical address
2610 PeiCorePhysicalAddress
|= 0x8000000000000000;
2613 // Check if address is aligned on a 16 byte boundary
2615 if (PeiCorePhysicalAddress
& 0xF) {
2617 "ERROR: PEI_CORE entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n",
2618 PeiCorePhysicalAddress
2623 // First Get the FIT table address
2625 FitAddress
= (*(UINT64
*) (FvImage
->Eof
- IPF_FIT_ADDRESS_OFFSET
)) & 0xFFFFFFFF;
2627 FitTablePtr
= (FIT_TABLE
*) (FvImage
->FileImage
+ (FitAddress
- FvInfo
->BaseAddress
));
2629 Status
= UpdatePeiCoreEntryInFit (FitTablePtr
, PeiCorePhysicalAddress
);
2631 if (!EFI_ERROR (Status
)) {
2632 UpdateFitCheckSum (FitTablePtr
);
2635 // Find the Sec Core
2637 Status
= GetFileByType (EFI_FV_FILETYPE_SECURITY_CORE
, 1, &SecCoreFile
);
2638 if (EFI_ERROR (Status
) || SecCoreFile
== NULL
) {
2639 Error (NULL
, 0, 0, "could not find the Sec core in the FV", NULL
);
2643 // Sec Core found, now find PE32 section
2645 Status
= GetSectionByType (SecCoreFile
, EFI_SECTION_PE32
, 1, &Pe32Section
);
2646 if (EFI_ERROR (Status
)) {
2647 Error (NULL
, 0, 0, "could not find PE32 section in SEC core file", NULL
);
2651 Status
= GetPe32Info (
2652 (VOID
*) ((UINTN
) Pe32Section
.Pe32Section
+ sizeof (EFI_SECTION_PE32
)),
2657 if (EFI_ERROR (Status
)) {
2658 Error (NULL
, 0, 0, "could not get PE32 entry point for SEC core", NULL
);
2662 // Physical address is FV base + offset of PE32 + offset of the entry point
2664 SecCorePhysicalAddress
= FvInfo
->BaseAddress
;
2665 SecCorePhysicalAddress
+= (UINTN
) Pe32Section
.Pe32Section
+ sizeof (EFI_SECTION_PE32
) - (UINTN
) FvImage
->FileImage
;
2666 SecCorePhysicalAddress
+= EntryPoint
;
2669 // Update SEC_CORE address
2672 // Set the uncached attribute bit in the physical address
2674 SecCorePhysicalAddress
|= 0x8000000000000000;
2677 // Update the address
2679 SecCoreEntryAddressPtr
= (EFI_PHYSICAL_ADDRESS
*) ((UINTN
) FvImage
->Eof
- IPF_SALE_ENTRY_ADDRESS_OFFSET
);
2680 *SecCoreEntryAddressPtr
= SecCorePhysicalAddress
;
2683 // Check if address is aligned on a 16 byte boundary
2685 if (SecCorePhysicalAddress
& 0xF) {
2687 "ERROR: SALE_ENTRY entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n",
2688 SecCorePhysicalAddress
2692 } else if ((MachineType
== EFI_IMAGE_MACHINE_IA32
) ||
2693 (MachineType
== EFI_IMAGE_MACHINE_X64
)) {
2695 // Get the location to update
2697 Ia32ResetAddressPtr
= (UINT32
*) ((UINTN
) FvImage
->Eof
- IA32_PEI_CORE_ENTRY_OFFSET
);
2700 // Write lower 32 bits of physical address
2702 *Ia32ResetAddressPtr
= (UINT32
) PeiCorePhysicalAddress
;
2705 // Update the BFV base address
2707 Ia32ResetAddressPtr
= (UINT32
*) ((UINTN
) FvImage
->Eof
- 4);
2708 *Ia32ResetAddressPtr
= (UINT32
) (FvInfo
->BaseAddress
);
2713 // Update the Startup AP in the FVH header block ZeroVector region.
2715 BytePointer
= (UINT8
*) ((UINTN
) FvImage
->FileImage
);
2716 BytePointer2
= (FvInfo
->Size
== 0x10000) ? m64kRecoveryStartupApDataArray
: m128kRecoveryStartupApDataArray
;
2717 for (Index
= 0; Index
< SIZEOF_STARTUP_DATA_ARRAY
; Index
++) {
2718 *BytePointer
++ = *BytePointer2
++;
2721 // Calculate the checksum
2723 WordPointer
= (UINT16
*) ((UINTN
) FvImage
->FileImage
);
2724 for (Index
= 0; Index
< SIZEOF_STARTUP_DATA_ARRAY
/ 2; Index
++) {
2725 CheckSum
= (UINT16
) (CheckSum
+ ((UINT16
) *WordPointer
));
2729 // Update the checksum field
2731 BytePointer
= (UINT8
*) ((UINTN
) FvImage
->FileImage
);
2732 BytePointer
+= (SIZEOF_STARTUP_DATA_ARRAY
- 2);
2733 WordPointer
= (UINT16
*) BytePointer
;
2734 *WordPointer
= (UINT16
) (0x10000 - (UINT32
) CheckSum
);
2736 Error (NULL
, 0, 0, "invalid machine type in PEI core", "machine type=0x%X", (UINT32
) MachineType
);
2740 // Determine if it has an FFS file tail.
2742 if (VtfFile
->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
2743 TailSize
= sizeof (EFI_FFS_FILE_TAIL
);
2748 // Now update file checksum
2750 SavedState
= VtfFile
->State
;
2751 VtfFile
->IntegrityCheck
.Checksum
.File
= 0;
2753 if (VtfFile
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
2754 #if (PI_SPECIFICATION_VERSION < 0x00010000)
2755 VtfFile
->IntegrityCheck
.Checksum
.File
= CalculateChecksum8 (
2757 GetLength (VtfFile
->Size
) - TailSize
2761 VtfFile
->IntegrityCheck
.Checksum
.File
= CalculateChecksum8 (
2762 (UINT8
*) ((UINTN
)VtfFile
+ sizeof (EFI_FFS_FILE_HEADER
)),
2763 GetLength (VtfFile
->Size
) - TailSize
- sizeof (EFI_FFS_FILE_HEADER
)
2767 VtfFile
->IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
2770 VtfFile
->State
= SavedState
;
2772 #if (PI_SPECIFICATION_VERSION < 0x00010000)
2774 // Update tail if present
2776 if (VtfFile
->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
2777 TailValue
= (EFI_FFS_FILE_TAIL
) (~(VtfFile
->IntegrityCheck
.TailReference
));
2778 *(EFI_FFS_FILE_TAIL
*) (((UINTN
) (VtfFile
) + GetLength (VtfFile
->Size
) - sizeof (EFI_FFS_FILE_TAIL
))) = TailValue
;
2787 OUT UINT32
*EntryPoint
,
2788 OUT UINT32
*BaseOfCode
,
2789 OUT UINT16
*MachineType
2793 Routine Description:
2795 Retrieves the PE32 entry point offset and machine type from PE image or TE image.
2796 See EfiImage.h for machine types. The entry point offset is from the beginning
2797 of the PE32 buffer passed in.
2801 Pe32 Beginning of the PE32.
2802 EntryPoint Offset from the beginning of the PE32 to the image entry point.
2803 BaseOfCode Base address of code.
2804 MachineType Magic number for the machine type.
2808 EFI_SUCCESS Function completed successfully.
2809 EFI_ABORTED Error encountered.
2810 EFI_INVALID_PARAMETER A required parameter was NULL.
2811 EFI_UNSUPPORTED The operation is unsupported.
2815 EFI_IMAGE_DOS_HEADER
*DosHeader
;
2816 EFI_IMAGE_NT_HEADERS
*NtHeader
;
2817 EFI_TE_IMAGE_HEADER
*TeHeader
;
2820 // Verify input parameters
2823 return EFI_INVALID_PARAMETER
;
2827 // First check whether it is one TE Image.
2829 TeHeader
= (EFI_TE_IMAGE_HEADER
*) Pe32
;
2830 if (TeHeader
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
2832 // By TeImage Header to get output
2834 *EntryPoint
= TeHeader
->AddressOfEntryPoint
+ sizeof (EFI_TE_IMAGE_HEADER
) - TeHeader
->StrippedSize
;
2835 *BaseOfCode
= TeHeader
->BaseOfCode
+ sizeof (EFI_TE_IMAGE_HEADER
) - TeHeader
->StrippedSize
;
2836 *MachineType
= TeHeader
->Machine
;
2839 // Then check whether
2840 // is the DOS header
2842 DosHeader
= (EFI_IMAGE_DOS_HEADER
*) Pe32
;
2845 // Verify DOS header is expected
2847 if (DosHeader
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2848 printf ("ERROR: Unknown magic number in the DOS header, 0x%04X.\n", DosHeader
->e_magic
);
2849 return EFI_UNSUPPORTED
;
2852 // Immediately following is the NT header.
2854 NtHeader
= (EFI_IMAGE_NT_HEADERS
*) ((UINTN
) Pe32
+ DosHeader
->e_lfanew
);
2857 // Verify NT header is expected
2859 if (NtHeader
->Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2860 printf ("ERROR: Unrecognized image signature 0x%08X.\n", NtHeader
->Signature
);
2861 return EFI_UNSUPPORTED
;
2866 *EntryPoint
= NtHeader
->OptionalHeader
.AddressOfEntryPoint
;
2867 *BaseOfCode
= NtHeader
->OptionalHeader
.BaseOfCode
;
2868 *MachineType
= NtHeader
->FileHeader
.Machine
;
2872 // Verify machine type is supported
2874 if (*MachineType
!= EFI_IMAGE_MACHINE_IA32
&&
2875 *MachineType
!= EFI_IMAGE_MACHINE_IA64
&&
2876 *MachineType
!= EFI_IMAGE_MACHINE_X64
) {
2877 printf ("ERROR: Unrecognized machine type in the PE32 file.\n");
2878 return EFI_UNSUPPORTED
;
2884 // Exposed function implementations (prototypes are defined in GenFvImageLib.h)
2888 IN CHAR8
*InfFileImage
,
2889 IN UINTN InfFileSize
,
2890 OUT UINT8
**FvImage
,
2891 OUT UINTN
*FvImageSize
,
2892 OUT CHAR8
**FvFileName
,
2893 OUT UINT8
**SymImage
,
2894 OUT UINTN
*SymImageSize
,
2895 OUT CHAR8
**SymFileName
2899 Routine Description:
2901 This is the main function which will be called from application.
2905 InfFileImage Buffer containing the INF file contents.
2906 InfFileSize Size of the contents of the InfFileImage buffer.
2907 FvImage Pointer to the FV image created.
2908 FvImageSize Size of the FV image created and pointed to by FvImage.
2909 FvFileName Requested name for the FV file.
2910 SymImage Pointer to the Sym image created.
2911 SymImageSize Size of the Sym image created and pointed to by SymImage.
2912 SymFileName Requested name for the Sym file.
2916 EFI_SUCCESS Function completed successfully.
2917 EFI_OUT_OF_RESOURCES Could not allocate required resources.
2918 EFI_ABORTED Error encountered.
2919 EFI_INVALID_PARAMETER A required parameter was NULL.
2924 MEMORY_FILE InfMemoryFile
;
2925 MEMORY_FILE FvImageMemoryFile
;
2926 MEMORY_FILE SymImageMemoryFile
;
2929 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
2930 EFI_FFS_FILE_HEADER
*VtfFileImage
;
2931 UINTN FvImageCapacity
;
2934 // Check for invalid parameter
2936 if (InfFileImage
== NULL
|| FvImage
== NULL
|| FvImageSize
== NULL
|| FvFileName
== NULL
) {
2937 return EFI_INVALID_PARAMETER
;
2940 // Initialize file structures
2942 InfMemoryFile
.FileImage
= InfFileImage
;
2943 InfMemoryFile
.CurrentFilePointer
= InfFileImage
;
2944 InfMemoryFile
.Eof
= InfFileImage
+ InfFileSize
;
2947 // Parse the FV inf file for header information
2949 Status
= ParseFvInf (&InfMemoryFile
, &FvInfo
);
2950 if (EFI_ERROR (Status
)) {
2951 printf ("ERROR: Could not parse the input INF file.\n");
2955 // Update the file name return values
2957 strcpy (*FvFileName
, FvInfo
.FvName
);
2958 strcpy (*SymFileName
, FvInfo
.SymName
);
2961 // Calculate the FV size
2963 if (FvInfo
.Size
!= (UINTN
) -1) {
2964 *FvImageSize
= FvInfo
.Size
;
2965 FvImageCapacity
= FvInfo
.Size
;
2968 // For auto size, set default as one block
2970 FvInfo
.FvBlocks
[0].NumBlocks
= 1;
2971 *FvImageSize
= FvInfo
.FvBlocks
[0].BlockLength
;
2972 FvImageCapacity
= FV_CAPACITY_INCREASE_UNIT
;
2978 *FvImage
= malloc (FvImageCapacity
);
2979 if (*FvImage
== NULL
) {
2980 return EFI_OUT_OF_RESOURCES
;
2983 // Allocate space for symbol file storage
2985 *SymImage
= malloc (SYMBOL_FILE_SIZE
);
2986 if (*SymImage
== NULL
) {
2987 return EFI_OUT_OF_RESOURCES
;
2990 // Initialize the FV to the erase polarity
2992 if (FvInfo
.FvAttributes
& EFI_FVB_ERASE_POLARITY
) {
2993 memset (*FvImage
, -1, FvImageCapacity
);
2995 memset (*FvImage
, 0, FvImageCapacity
);
2998 // Initialize FV header
3000 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) *FvImage
;
3003 // Initialize the zero vector to all zeros.
3005 memset (FvHeader
->ZeroVector
, 0, 16);
3008 // Copy the FFS GUID
3010 memcpy (&FvHeader
->FileSystemGuid
, &FvInfo
.FvGuid
, sizeof (EFI_GUID
));
3012 FvHeader
->FvLength
= *FvImageSize
;
3013 FvHeader
->Signature
= EFI_FVH_SIGNATURE
;
3014 FvHeader
->Attributes
= FvInfo
.FvAttributes
;
3015 #if (PI_SPECIFICATION_VERSION < 0x00010000)
3016 FvHeader
->Revision
= EFI_FVH_REVISION
;
3017 FvHeader
->Reserved
[0] = 0;
3018 FvHeader
->Reserved
[1] = 0;
3019 FvHeader
->Reserved
[2] = 0;
3021 FvHeader
->Revision
= EFI_FVH_PI_REVISION
;
3022 FvHeader
->ExtHeaderOffset
= 0;
3023 FvHeader
->Reserved
[0] = 0;
3026 // Copy firmware block map
3028 for (Index
= 0; FvInfo
.FvBlocks
[Index
].NumBlocks
!= 0; Index
++) {
3029 FvHeader
->FvBlockMap
[Index
].NumBlocks
= FvInfo
.FvBlocks
[Index
].NumBlocks
;
3030 FvHeader
->FvBlockMap
[Index
].BlockLength
= FvInfo
.FvBlocks
[Index
].BlockLength
;
3033 // Add block map terminator
3035 FvHeader
->FvBlockMap
[Index
].NumBlocks
= 0;
3036 FvHeader
->FvBlockMap
[Index
].BlockLength
= 0;
3039 // Complete the header
3041 FvHeader
->HeaderLength
= (UINT16
) (((UINTN
) &(FvHeader
->FvBlockMap
[Index
+ 1])) - (UINTN
) *FvImage
);
3042 FvHeader
->Checksum
= 0;
3043 FvHeader
->Checksum
= CalculateChecksum16 ((UINT16
*) FvHeader
, FvHeader
->HeaderLength
/ sizeof (UINT16
));
3046 // If there is no FFS file, find and generate each components of the FV
3048 if (FvInfo
.FvFiles
[0][0] == 0) {
3049 Status
= GenNonFFSFv (*FvImage
, &FvInfo
);
3050 if (EFI_ERROR (Status
)) {
3051 printf ("ERROR: Could not generate NonFFS FV.\n");
3059 // Initialize our "file" view of the buffer
3061 FvImageMemoryFile
.FileImage
= *FvImage
;
3062 FvImageMemoryFile
.CurrentFilePointer
= *FvImage
+ FvHeader
->HeaderLength
;
3063 FvImageMemoryFile
.Eof
= *FvImage
+*FvImageSize
;
3066 // Initialize our "file" view of the symbol file.
3068 SymImageMemoryFile
.FileImage
= *SymImage
;
3069 SymImageMemoryFile
.CurrentFilePointer
= *SymImage
;
3070 SymImageMemoryFile
.Eof
= *FvImage
+ SYMBOL_FILE_SIZE
;
3073 // Initialize the FV library.
3075 InitializeFvLib (FvImageMemoryFile
.FileImage
, *FvImageSize
);
3078 // Files start on 8 byte alignments, so move to the next 8 byte aligned
3079 // address. For now, just assert if it isn't. Currently FV header is
3080 // always a multiple of 8 bytes.
3081 // BUGBUG: Handle this better
3083 assert ((((UINTN
) FvImageMemoryFile
.CurrentFilePointer
) % 8) == 0);
3086 // Initialize the VTF file address.
3088 VtfFileImage
= (EFI_FFS_FILE_HEADER
*) FvImageMemoryFile
.Eof
;
3093 for (Index
= 0; FvInfo
.FvFiles
[Index
][0] != 0; Index
++) {
3097 Status
= AddFile (&FvImageMemoryFile
, &FvInfo
, Index
, &VtfFileImage
, &SymImageMemoryFile
, &FvImageCapacity
);
3100 // Update FvImageSize and FvImage as they may be changed in AddFile routine
3102 if (FvInfo
.Size
== (UINTN
) -1) {
3103 *FvImageSize
= FvInfo
.FvBlocks
[0].NumBlocks
* FvInfo
.FvBlocks
[0].BlockLength
;
3104 *FvImage
= FvImageMemoryFile
.FileImage
;
3108 // Exit if error detected while adding the file
3110 if (EFI_ERROR (Status
)) {
3111 printf ("ERROR: Could not add file %s.\n", FvInfo
.FvFiles
[Index
]);
3117 // If there is a VTF file, some special actions need to occur.
3119 if ((UINTN
) VtfFileImage
!= (UINTN
) FvImageMemoryFile
.Eof
) {
3121 // Pad from the end of the last file to the beginning of the VTF file.
3123 Status
= PadFvImage (&FvImageMemoryFile
, VtfFileImage
);
3124 if (EFI_ERROR (Status
)) {
3125 printf ("ERROR: Could not create the pad file between the last file and the VTF file.\n");
3130 // Update reset vector (SALE_ENTRY for IPF)
3131 // Now for IA32 and IA64 platform, the fv which has bsf file must have the
3132 // EndAddress of 0xFFFFFFFF. Thus, only this type fv needs to update the
3133 // reset vector. If the PEI Core is found, the VTF file will probably get
3134 // corrupted by updating the entry point.
3136 if ((FvInfo
.BaseAddress
+ *FvImageSize
) == FV_IMAGES_TOP_ADDRESS
) {
3137 Status
= UpdateResetVector (&FvImageMemoryFile
, &FvInfo
, VtfFileImage
);
3138 if (EFI_ERROR(Status
)) {
3139 printf ("ERROR: Could not update the reset vector.\n");
3146 // Determine final Sym file size
3148 *SymImageSize
= SymImageMemoryFile
.CurrentFilePointer
- SymImageMemoryFile
.FileImage
;
3154 UpdatePeiCoreEntryInFit (
3155 IN FIT_TABLE
*FitTablePtr
,
3156 IN UINT64 PeiCorePhysicalAddress
3160 Routine Description:
3162 This function is used to update the Pei Core address in FIT, this can be used by Sec core to pass control from
3167 FitTablePtr - The pointer of FIT_TABLE.
3168 PeiCorePhysicalAddress - The address of Pei Core entry.
3172 EFI_SUCCESS - The PEI_CORE FIT entry was updated successfully.
3173 EFI_NOT_FOUND - Not found the PEI_CORE FIT entry.
3177 FIT_TABLE
*TmpFitPtr
;
3179 UINTN NumFitComponents
;
3181 TmpFitPtr
= FitTablePtr
;
3182 NumFitComponents
= TmpFitPtr
->CompSize
;
3184 for (Index
= 0; Index
< NumFitComponents
; Index
++) {
3185 if ((TmpFitPtr
->CvAndType
& FIT_TYPE_MASK
) == COMP_TYPE_FIT_PEICORE
) {
3186 TmpFitPtr
->CompAddress
= PeiCorePhysicalAddress
;
3193 return EFI_NOT_FOUND
;
3198 IN FIT_TABLE
*FitTablePtr
3202 Routine Description:
3204 This function is used to update the checksum for FIT.
3209 FitTablePtr - The pointer of FIT_TABLE.
3217 if ((FitTablePtr
->CvAndType
& CHECKSUM_BIT_MASK
) >> 7) {
3218 FitTablePtr
->CheckSum
= 0;
3219 FitTablePtr
->CheckSum
= CalculateChecksum8 ((UINT8
*) FitTablePtr
, FitTablePtr
->CompSize
* 16);