4 Copyright (c) 2004, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 This file contains functions required to generate a Firmware Volume.
27 #include <uuid/uuid.h>
36 #include <Common/UefiBaseTypes.h>
37 #include <Common/FirmwareVolumeImageFormat.h>
38 #include <Common/Variable.h>
39 #include <Common/WorkingBlockHeader.h>
40 #include <Guid/FirmwareFileSystem.h>
42 #include "GenFvImageLib.h"
43 #include "GenFvImageLibInternal.h"
44 #include "CommonLib.h"
46 #include "EfiUtilityMsgs.h"
48 #include "EfiCompress.h"
49 #include "WinNtInclude.h"
53 // Local function prototypes
58 OUT UINT32
*EntryPoint
,
59 OUT UINT32
*BaseOfCode
,
60 OUT UINT16
*MachineType
64 // Local function implementations.
66 EFI_GUID FfsGuid
= EFI_FIRMWARE_FILE_SYSTEM_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 // Read the alignment capabilities attribute
437 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_CAP_STRING
, 0, Value
);
439 if (Status
== EFI_SUCCESS
) {
443 if (strcmp (Value
, TRUE_STRING
) == 0) {
444 FvInfo
->FvAttributes
|= EFI_FVB_ALIGNMENT_CAP
;
445 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
446 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_CAP_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
450 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_CAP_STRING
, "value not specified");
454 // Read the word alignment capability attribute
456 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_2_STRING
, 0, Value
);
458 if (Status
== EFI_SUCCESS
) {
462 if (strcmp (Value
, TRUE_STRING
) == 0) {
463 FvInfo
->FvAttributes
|= EFI_FVB_ALIGNMENT_2
;
464 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
465 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_2_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
469 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_2_STRING
, "value not specified");
473 // Read the dword alignment capability attribute
475 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_4_STRING
, 0, Value
);
477 if (Status
== EFI_SUCCESS
) {
481 if (strcmp (Value
, TRUE_STRING
) == 0) {
482 FvInfo
->FvAttributes
|= EFI_FVB_ALIGNMENT_4
;
483 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
484 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_4_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
488 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_4_STRING
, "value not specified");
492 // Read the word alignment capability attribute
494 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_8_STRING
, 0, Value
);
496 if (Status
== EFI_SUCCESS
) {
500 if (strcmp (Value
, TRUE_STRING
) == 0) {
501 FvInfo
->FvAttributes
|= EFI_FVB_ALIGNMENT_8
;
502 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
503 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_8_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
507 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_8_STRING
, "value not specified");
511 // Read the qword alignment capability attribute
513 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_16_STRING
, 0, Value
);
515 if (Status
== EFI_SUCCESS
) {
519 if (strcmp (Value
, TRUE_STRING
) == 0) {
520 FvInfo
->FvAttributes
|= EFI_FVB_ALIGNMENT_16
;
521 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
522 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_16_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
526 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_16_STRING
, "value not specified");
530 // Read the 32 byte alignment capability attribute
532 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_32_STRING
, 0, Value
);
534 if (Status
== EFI_SUCCESS
) {
538 if (strcmp (Value
, TRUE_STRING
) == 0) {
539 FvInfo
->FvAttributes
|= EFI_FVB_ALIGNMENT_32
;
540 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
541 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_32_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
545 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_32_STRING
, "value not specified");
549 // Read the 64 byte alignment capability attribute
551 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_64_STRING
, 0, Value
);
553 if (Status
== EFI_SUCCESS
) {
557 if (strcmp (Value
, TRUE_STRING
) == 0) {
558 FvInfo
->FvAttributes
|= EFI_FVB_ALIGNMENT_64
;
559 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
560 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_64_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
564 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_64_STRING
, "value not specified");
568 // Read the 128 byte alignment capability attribute
570 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_128_STRING
, 0, Value
);
572 if (Status
== EFI_SUCCESS
) {
576 if (strcmp (Value
, TRUE_STRING
) == 0) {
577 FvInfo
->FvAttributes
|= EFI_FVB_ALIGNMENT_128
;
578 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
579 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_128_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
583 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_128_STRING
, "value not specified");
587 // Read the 256 byte alignment capability attribute
589 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_256_STRING
, 0, Value
);
591 if (Status
== EFI_SUCCESS
) {
595 if (strcmp (Value
, TRUE_STRING
) == 0) {
596 FvInfo
->FvAttributes
|= EFI_FVB_ALIGNMENT_256
;
597 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
598 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_256_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
602 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_256_STRING
, "value not specified");
606 // Read the 512 byte alignment capability attribute
608 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_512_STRING
, 0, Value
);
610 if (Status
== EFI_SUCCESS
) {
614 if (strcmp (Value
, TRUE_STRING
) == 0) {
615 FvInfo
->FvAttributes
|= EFI_FVB_ALIGNMENT_512
;
616 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
617 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_512_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
621 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_512_STRING
, "value not specified");
625 // Read the 1K byte alignment capability attribute
627 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_1K_STRING
, 0, Value
);
629 if (Status
== EFI_SUCCESS
) {
633 if (strcmp (Value
, TRUE_STRING
) == 0) {
634 FvInfo
->FvAttributes
|= EFI_FVB_ALIGNMENT_1K
;
635 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
636 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_1K_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
640 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_1K_STRING
, "value not specified");
644 // Read the 2K byte alignment capability attribute
646 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_2K_STRING
, 0, Value
);
648 if (Status
== EFI_SUCCESS
) {
652 if (strcmp (Value
, TRUE_STRING
) == 0) {
653 FvInfo
->FvAttributes
|= EFI_FVB_ALIGNMENT_2K
;
654 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
655 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_2K_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
659 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_2K_STRING
, "value not specified");
663 // Read the 4K byte alignment capability attribute
665 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_4K_STRING
, 0, Value
);
667 if (Status
== EFI_SUCCESS
) {
671 if (strcmp (Value
, TRUE_STRING
) == 0) {
672 FvInfo
->FvAttributes
|= EFI_FVB_ALIGNMENT_4K
;
673 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
674 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_4K_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
678 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_4K_STRING
, "value not specified");
682 // Read the 8K byte alignment capability attribute
684 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_8K_STRING
, 0, Value
);
686 if (Status
== EFI_SUCCESS
) {
690 if (strcmp (Value
, TRUE_STRING
) == 0) {
691 FvInfo
->FvAttributes
|= EFI_FVB_ALIGNMENT_8K
;
692 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
693 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_8K_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
697 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_8K_STRING
, "value not specified");
701 // Read the 16K byte alignment capability attribute
703 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_16K_STRING
, 0, Value
);
705 if (Status
== EFI_SUCCESS
) {
709 if (strcmp (Value
, TRUE_STRING
) == 0) {
710 FvInfo
->FvAttributes
|= EFI_FVB_ALIGNMENT_16K
;
711 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
712 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_16K_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
716 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_16K_STRING
, "value not specified");
720 // Read the 32K byte alignment capability attribute
722 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_32K_STRING
, 0, Value
);
724 if (Status
== EFI_SUCCESS
) {
728 if (strcmp (Value
, TRUE_STRING
) == 0) {
729 FvInfo
->FvAttributes
|= EFI_FVB_ALIGNMENT_32K
;
730 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
731 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_32K_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
735 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_32K_STRING
, "value not specified");
739 // Read the 64K byte alignment capability attribute
741 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_64K_STRING
, 0, Value
);
743 if (Status
== EFI_SUCCESS
) {
747 if (strcmp (Value
, TRUE_STRING
) == 0) {
748 FvInfo
->FvAttributes
|= EFI_FVB_ALIGNMENT_64K
;
749 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
750 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_64K_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
754 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_64K_STRING
, "value not specified");
758 if (!(FvInfo
->FvAttributes
& EFI_FVB_ALIGNMENT_CAP
) &&
760 (FvInfo
->FvAttributes
& EFI_FVB_ALIGNMENT_2
) ||
761 (FvInfo
->FvAttributes
& EFI_FVB_ALIGNMENT_4
) ||
762 (FvInfo
->FvAttributes
& EFI_FVB_ALIGNMENT_8
) ||
763 (FvInfo
->FvAttributes
& EFI_FVB_ALIGNMENT_16
) ||
764 (FvInfo
->FvAttributes
& EFI_FVB_ALIGNMENT_32
) ||
765 (FvInfo
->FvAttributes
& EFI_FVB_ALIGNMENT_64
) ||
766 (FvInfo
->FvAttributes
& EFI_FVB_ALIGNMENT_128
) ||
767 (FvInfo
->FvAttributes
& EFI_FVB_ALIGNMENT_256
) ||
768 (FvInfo
->FvAttributes
& EFI_FVB_ALIGNMENT_512
) ||
769 (FvInfo
->FvAttributes
& EFI_FVB_ALIGNMENT_1K
) ||
770 (FvInfo
->FvAttributes
& EFI_FVB_ALIGNMENT_2K
) ||
771 (FvInfo
->FvAttributes
& EFI_FVB_ALIGNMENT_4K
) ||
772 (FvInfo
->FvAttributes
& EFI_FVB_ALIGNMENT_8K
) ||
773 (FvInfo
->FvAttributes
& EFI_FVB_ALIGNMENT_16K
) ||
774 (FvInfo
->FvAttributes
& EFI_FVB_ALIGNMENT_32K
) ||
775 (FvInfo
->FvAttributes
& EFI_FVB_ALIGNMENT_64K
)
782 "illegal combination of alignment attributes",
783 "if %s is not %s, no individual alignments can be %s",
784 EFI_FVB_ALIGNMENT_CAP_STRING
,
793 for (Index
= 0; Index
< MAX_NUMBER_OF_FV_BLOCKS
; Index
++) {
795 // Read the number of blocks
797 Status
= FindToken (InfFile
, OPTIONS_SECTION_STRING
, EFI_NUM_BLOCKS_STRING
, Index
, Value
);
799 if (Status
== EFI_SUCCESS
) {
801 // Update the number of blocks
803 Status
= AsciiStringToUint64 (Value
, FALSE
, &Value64
);
804 if (EFI_ERROR (Status
)) {
805 Error (NULL
, 0, 0, Value
, "invalid value for %s", EFI_NUM_BLOCKS_STRING
);
809 FvInfo
->FvBlocks
[Index
].NumBlocks
= (UINT32
) Value64
;
812 // If there is no number of blocks, but there is a size, then we have a mismatched pair
813 // and should return an error.
815 Status
= FindToken (InfFile
, OPTIONS_SECTION_STRING
, EFI_BLOCK_SIZE_STRING
, Index
, Value
);
816 if (!EFI_ERROR (Status
)) {
817 Error (NULL
, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING
, EFI_BLOCK_SIZE_STRING
);
827 // Read the size of blocks
829 Status
= FindToken (InfFile
, OPTIONS_SECTION_STRING
, EFI_BLOCK_SIZE_STRING
, Index
, Value
);
831 if (Status
== EFI_SUCCESS
) {
833 // Update the number of blocks
835 Status
= AsciiStringToUint64 (Value
, FALSE
, &Value64
);
836 if (EFI_ERROR (Status
)) {
837 Error (NULL
, 0, 0, Value
, "invalid value specified for %s", EFI_BLOCK_SIZE_STRING
);
841 FvInfo
->FvBlocks
[Index
].BlockLength
= (UINT32
) Value64
;
844 // There is a number of blocks, but there is no size, so we have a mismatched pair
845 // and should return an error.
847 Error (NULL
, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING
, EFI_BLOCK_SIZE_STRING
);
854 for (Index
= 0; Index
< MAX_NUMBER_OF_FILES_IN_FV
; Index
++) {
856 // Read the number of blocks
858 Status
= FindToken (InfFile
, FILES_SECTION_STRING
, EFI_FILE_NAME_STRING
, Index
, Value
);
860 if (Status
== EFI_SUCCESS
) {
864 strcpy (FvInfo
->FvFiles
[Index
], Value
);
870 if (FindSection (InfFile
, COMPONENT_SECTION_STRING
)) {
873 // Read component FV_VARIABLE
875 Status
= FindToken (InfFile
, COMPONENT_SECTION_STRING
, EFI_NV_VARIABLE_STRING
, 0, Value
);
877 if (Status
== EFI_SUCCESS
) {
881 strcpy (FvInfo
->FvComponents
[Index
].ComponentName
, EFI_NV_VARIABLE_STRING
);
882 Status
= AsciiStringToUint64 (Value
, FALSE
, &Value64
);
883 if (EFI_ERROR (Status
)) {
884 printf ("ERROR: %s is not a valid integer.\n", EFI_NV_VARIABLE_STRING
);
888 FvInfo
->FvComponents
[Index
].Size
= (UINTN
) Value64
;
890 printf ("WARNING: Could not read %s.\n", EFI_NV_VARIABLE_STRING
);
895 // Read component FV_EVENT_LOG
897 Status
= FindToken (InfFile
, COMPONENT_SECTION_STRING
, EFI_NV_EVENT_LOG_STRING
, 0, Value
);
899 if (Status
== EFI_SUCCESS
) {
903 strcpy (FvInfo
->FvComponents
[Index
].ComponentName
, EFI_NV_EVENT_LOG_STRING
);
904 Status
= AsciiStringToUint64 (Value
, FALSE
, &Value64
);
905 if (EFI_ERROR (Status
)) {
906 printf ("ERROR: %s is not a valid integer.\n", EFI_NV_EVENT_LOG_STRING
);
910 FvInfo
->FvComponents
[Index
].Size
= (UINTN
) Value64
;
912 printf ("WARNING: Could not read %s.\n", EFI_NV_EVENT_LOG_STRING
);
917 // Read component FV_FTW_WORKING
919 Status
= FindToken (InfFile
, COMPONENT_SECTION_STRING
, EFI_NV_FTW_WORKING_STRING
, 0, Value
);
921 if (Status
== EFI_SUCCESS
) {
925 strcpy (FvInfo
->FvComponents
[Index
].ComponentName
, EFI_NV_FTW_WORKING_STRING
);
926 Status
= AsciiStringToUint64 (Value
, FALSE
, &Value64
);
927 if (EFI_ERROR (Status
)) {
928 printf ("ERROR: %s is not a valid integer.\n", EFI_NV_FTW_WORKING_STRING
);
932 FvInfo
->FvComponents
[Index
].Size
= (UINTN
) Value64
;
934 printf ("WARNING: Could not read %s.\n", EFI_NV_FTW_WORKING_STRING
);
939 // Read component FV_FTW_SPARE
941 Status
= FindToken (InfFile
, COMPONENT_SECTION_STRING
, EFI_NV_FTW_SPARE_STRING
, 0, Value
);
943 if (Status
== EFI_SUCCESS
) {
947 strcpy (FvInfo
->FvComponents
[Index
].ComponentName
, EFI_NV_FTW_SPARE_STRING
);
948 Status
= AsciiStringToUint64 (Value
, FALSE
, &Value64
);
949 if (EFI_ERROR (Status
)) {
950 printf ("ERROR: %s is not a valid integer.\n", EFI_NV_FTW_SPARE_STRING
);
954 FvInfo
->FvComponents
[Index
].Size
= (UINTN
) Value64
;
956 printf ("WARNING: Could not read %s.\n", EFI_NV_FTW_SPARE_STRING
);
960 // Compute size for easy access later
963 for (Index
= 0; FvInfo
->FvBlocks
[Index
].NumBlocks
; Index
++) {
964 FvInfo
->Size
+= FvInfo
->FvBlocks
[Index
].NumBlocks
* FvInfo
->FvBlocks
[Index
].BlockLength
;
972 IN EFI_FFS_FILE_HEADER
*FfsFile
,
973 IN EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
979 This function changes the FFS file attributes based on the erase polarity
993 if (FvHeader
->Attributes
& EFI_FVB_ERASE_POLARITY
) {
994 FfsFile
->State
= (UINT8
)~(FfsFile
->State
);
1000 IN EFI_FFS_FILE_HEADER
*FfsFile
,
1001 IN OUT UINT32
*Alignment
1005 Routine Description:
1007 This function determines the alignment of the FFS input file from the file
1012 FfsFile FFS file to parse
1013 Alignment The minimum required alignment of the FFS file, in bytes
1017 EFI_SUCCESS The function completed successfully.
1018 EFI_INVALID_PARAMETER One of the input parameters was invalid.
1019 EFI_ABORTED An error occurred.
1024 // Verify input parameters.
1026 if (FfsFile
== NULL
|| Alignment
== NULL
) {
1027 return EFI_INVALID_PARAMETER
;
1030 switch ((FfsFile
->Attributes
>> 3) & 0x07) {
1036 *Alignment
= (1 << 0);
1041 // 16 byte alignment
1043 *Alignment
= (1 << 4);
1048 // 128 byte alignment
1050 *Alignment
= (1 << 7);
1055 // 512 byte alignment
1057 *Alignment
= (1 << 9);
1062 // 1K byte alignment
1064 *Alignment
= (1 << 10);
1069 // 4K byte alignment
1071 *Alignment
= (1 << 12);
1076 // 32K byte alignment
1078 *Alignment
= (1 << 15);
1083 // 64K byte alignment
1085 *Alignment
= (1 << 16);
1089 Error (NULL
, 0, 0, "nvalid file attribute calculated, this is most likely a utility error", NULL
);
1098 IN OUT MEMORY_FILE
*FvImage
,
1099 IN UINT32 DataAlignment
1103 Routine Description:
1105 This function adds a pad file to the FV image if it required to align the
1106 data of the next file.
1110 FvImage The memory image of the FV to add it to. The current offset
1112 DataAlignment The data alignment of the next FFS file.
1116 EFI_SUCCESS The function completed successfully.
1117 EFI_INVALID_PARAMETER One of the input parameters was invalid.
1118 EFI_OUT_OF_RESOURCES Insufficient resources exist in the FV to complete
1123 EFI_FFS_FILE_HEADER
*PadFile
;
1124 EFI_GUID PadFileGuid
;
1128 // Verify input parameters.
1130 if (FvImage
== NULL
) {
1131 return EFI_INVALID_PARAMETER
;
1134 // Basic assumption is we start from an 8 byte aligned address
1135 // and our file header is a multiple of 8 bytes
1137 assert ((UINTN
) FvImage
->CurrentFilePointer
% 8 == 0);
1138 assert (sizeof (EFI_FFS_FILE_HEADER
) % 8 == 0);
1141 // Check if a pad file is necessary
1143 if (((UINTN
) FvImage
->CurrentFilePointer
- (UINTN
) FvImage
->FileImage
+ sizeof (EFI_FFS_FILE_HEADER
)) % DataAlignment
== 0) {
1147 // Write pad file header
1149 PadFile
= (EFI_FFS_FILE_HEADER
*) FvImage
->CurrentFilePointer
;
1152 // Verify that we have enough space for the file header
1154 if ((UINTN
) (PadFile
+ sizeof (EFI_FFS_FILE_HEADER
)) >= (UINTN
) FvImage
->Eof
) {
1155 return EFI_OUT_OF_RESOURCES
;
1161 uuid_generate (tmp_id
);
1162 memcpy (&PadFileGuid
, tmp_id
, sizeof (EFI_GUID
));
1165 UuidCreate (&PadFileGuid
);
1167 memset (PadFile
, 0, sizeof (EFI_FFS_FILE_HEADER
));
1168 memcpy (&PadFile
->Name
, &PadFileGuid
, sizeof (EFI_GUID
));
1169 PadFile
->Type
= EFI_FV_FILETYPE_FFS_PAD
;
1170 PadFile
->Attributes
= 0;
1173 // Calculate the pad file size
1176 // This is the earliest possible valid offset (current plus pad file header
1177 // plus the next file header)
1179 PadFileSize
= (UINTN
) FvImage
->CurrentFilePointer
- (UINTN
) FvImage
->FileImage
+ (sizeof (EFI_FFS_FILE_HEADER
) * 2);
1182 // Add whatever it takes to get to the next aligned address
1184 while ((PadFileSize
% DataAlignment
) != 0) {
1188 // Subtract the next file header size
1190 PadFileSize
-= sizeof (EFI_FFS_FILE_HEADER
);
1193 // Subtract the starting offset to get size
1195 PadFileSize
-= (UINTN
) FvImage
->CurrentFilePointer
- (UINTN
) FvImage
->FileImage
;
1198 // Write pad file size (calculated size minus next file header size)
1200 PadFile
->Size
[0] = (UINT8
) (PadFileSize
& 0xFF);
1201 PadFile
->Size
[1] = (UINT8
) ((PadFileSize
>> 8) & 0xFF);
1202 PadFile
->Size
[2] = (UINT8
) ((PadFileSize
>> 16) & 0xFF);
1205 // Fill in checksums and state, they must be 0 for checksumming.
1207 PadFile
->IntegrityCheck
.Checksum
.Header
= 0;
1208 PadFile
->IntegrityCheck
.Checksum
.File
= 0;
1210 PadFile
->IntegrityCheck
.Checksum
.Header
= CalculateChecksum8 ((UINT8
*) PadFile
, sizeof (EFI_FFS_FILE_HEADER
));
1211 if (PadFile
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
1212 PadFile
->IntegrityCheck
.Checksum
.File
= CalculateChecksum8 ((UINT8
*) PadFile
, PadFileSize
);
1214 PadFile
->IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
1217 PadFile
->State
= EFI_FILE_HEADER_CONSTRUCTION
| EFI_FILE_HEADER_VALID
| EFI_FILE_DATA_VALID
;
1218 UpdateFfsFileState (
1219 (EFI_FFS_FILE_HEADER
*) PadFile
,
1220 (EFI_FIRMWARE_VOLUME_HEADER
*) FvImage
->FileImage
1224 // Verify that we have enough space (including the padding
1226 if ((UINTN
) (PadFile
+ sizeof (EFI_FFS_FILE_HEADER
)) >= (UINTN
) FvImage
->Eof
) {
1227 return EFI_OUT_OF_RESOURCES
;
1230 // Update the current FV pointer
1232 FvImage
->CurrentFilePointer
+= PadFileSize
;
1239 IN EFI_FFS_FILE_HEADER
*FileBuffer
1243 Routine Description:
1245 This function checks the header to validate if it is a VTF file
1249 FileBuffer Buffer in which content of a file has been read.
1253 TRUE If this is a VTF file
1254 FALSE If this is not a VTF file
1258 EFI_GUID VtfGuid
= EFI_FFS_VOLUME_TOP_FILE_GUID
;
1259 if (!memcmp (&FileBuffer
->Name
, &VtfGuid
, sizeof (EFI_GUID
))) {
1267 FfsRebaseImageRead (
1268 IN VOID
*FileHandle
,
1269 IN UINTN FileOffset
,
1270 IN OUT UINT32
*ReadSize
,
1275 Routine Description:
1277 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
1281 FileHandle - The handle to the PE/COFF file
1283 FileOffset - The offset, in bytes, into the file to read
1285 ReadSize - The number of bytes to read from the file starting at FileOffset
1287 Buffer - A pointer to the buffer to read the data into.
1291 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
1295 CHAR8
*Destination8
;
1299 Destination8
= Buffer
;
1300 Source8
= (CHAR8
*) ((UINTN
) FileHandle
+ FileOffset
);
1303 *(Destination8
++) = *(Source8
++);
1312 IN UINT64 BaseAddress
,
1313 IN EFI_FFS_FILE_HEADER
*FfsFile
,
1314 IN OUT MEMORY_FILE
*SymImage
,
1315 IN CHAR8
*SourceFileName
1319 Routine Description:
1321 This function adds the SYM tokens in the source file to the destination file.
1322 The SYM tokens are updated to reflect the base address.
1326 BaseAddress The base address for the new SYM tokens.
1327 FfsFile Pointer to the beginning of the FFS file in question.
1328 SymImage The memory file to update with symbol information.
1329 SourceFileName The source file.
1333 EFI_SUCCESS The function completed successfully.
1334 EFI_INVALID_PARAMETER One of the input parameters was invalid.
1335 EFI_ABORTED An error occurred.
1341 CHAR8 Buffer
[_MAX_PATH
];
1342 CHAR8 Type
[_MAX_PATH
];
1343 CHAR8 Address
[_MAX_PATH
];
1344 CHAR8 Section
[_MAX_PATH
];
1345 CHAR8 Token
[_MAX_PATH
];
1346 CHAR8 SymFileName
[_MAX_PATH
];
1347 CHAR8 CodeModuleName
[_MAX_PATH
];
1350 UINT64 TokenAddress
;
1353 EFI_FILE_SECTION_POINTER Pe32Section
;
1359 // Verify input parameters.
1361 if (BaseAddress
== 0 || FfsFile
== NULL
|| SymImage
== NULL
|| SourceFileName
== NULL
) {
1362 Error (NULL
, 0, 0, "invalid parameter passed to AddSymFile()", NULL
);
1363 return EFI_INVALID_PARAMETER
;
1366 // Check if we want to add this file
1369 // Get the file name
1371 strcpy (Buffer
, SourceFileName
);
1374 // Copy the file name for the path of the sym file and truncate the name portion.
1376 strcpy (SymFileName
, Buffer
);
1377 Ptr
= strrchr (SymFileName
, '\\');
1382 // Find the file extension and make it lower case
1384 Ptr
= strrchr (SymFileName
, '.');
1389 // Check if it is PEI file
1391 if (strstr (Buffer
, ".pei") != NULL
) {
1393 // Find the human readable portion
1395 if (!strtok (Buffer
, "-") ||
1396 !strtok (NULL
, "-") ||
1397 !strtok (NULL
, "-") ||
1398 !strtok (NULL
, "-") ||
1399 !strtok (NULL
, "-") ||
1400 !strcpy (Buffer
, strtok (NULL
, "."))
1402 Error (NULL
, 0, 0, "failed to find human readable portion of the file name in AddSymFile()", NULL
);
1406 // Save code module name
1408 strcpy (CodeModuleName
, Buffer
);
1411 // Add the symbol file name and extension to the file path.
1413 strcat (Buffer
, ".sym");
1414 strcat (SymFileName
, "\\");
1415 strcat (SymFileName
, Buffer
);
1418 // Only handle PEIM files.
1423 // Find PE32 section
1425 Status
= GetSectionByType (FfsFile
, EFI_SECTION_PE32
, 1, &Pe32Section
);
1428 // BUGBUG: Assume if no PE32 section it is PIC and hardcode base address
1430 if (Status
== EFI_NOT_FOUND
) {
1431 Status
= GetSectionByType (FfsFile
, EFI_SECTION_TE
, 1, &Pe32Section
);
1434 if (Status
== EFI_SUCCESS
) {
1435 Status
= GetPe32Info (
1436 (VOID
*) ((UINTN
) Pe32Section
.Pe32Section
+ sizeof (EFI_SECTION_PE32
)),
1441 } else if (Status
== EFI_NOT_FOUND
) {
1443 // For PIC, hardcode.
1446 Status
= EFI_SUCCESS
;
1448 Error (NULL
, 0, 0, "could not parse a PE32 section from the PEI file", NULL
);
1452 if (EFI_ERROR (Status
)) {
1453 Error (NULL
, 0, 0, "GetPe32Info() could not get PE32 entry point for PEI file", NULL
);
1458 // Open the source file
1460 SourceFile
= fopen (SymFileName
, "r");
1461 if (SourceFile
== NULL
) {
1463 // SYM files are not required.
1468 // Read the first line
1470 if (fgets (Buffer
, _MAX_PATH
, SourceFile
) == NULL
) {
1474 // Make sure it matches the expected sym format
1476 if (strcmp (Buffer
, "TEXTSYM format | V1.0\n")) {
1477 fclose (SourceFile
);
1478 Error (NULL
, 0, 0, "AddSymFile() found unexpected sym format in input file", NULL
);
1484 while (feof (SourceFile
) == 0) {
1490 "%s | %s | %s | %s\n",
1497 // If the token starts with "??" ignore it
1499 if (Token
[0] == '?' && Token
[1] == '?') {
1503 // Get the token address
1505 AsciiStringToUint64 (Address
, TRUE
, &TokenAddress
);
1508 // Add the base address
1510 TokenAddress
+= BaseAddress
;
1513 // If PE32 or TE section then find the start of code. For PIC it is hardcoded.
1515 if (Pe32Section
.Pe32Section
) {
1517 // Add the offset of the PE32 section
1519 TokenAddress
+= (UINTN
) Pe32Section
.Pe32Section
- (UINTN
) FfsFile
;
1522 // Add the size of the PE32 section header
1524 TokenAddress
+= sizeof (EFI_PE32_SECTION
);
1527 // For PIC hardcoded.
1529 TokenAddress
+= 0x28;
1533 // Add the beginning of the code
1535 TokenAddress
+= BaseOfCode
;
1539 "%s | %016I64X | %s | _%s%s\n",
1546 memcpy (SymImage
->CurrentFilePointer
, Buffer
, strlen (Buffer
) + 1);
1547 SymImage
->CurrentFilePointer
= (UINT8
*) (((UINTN
) SymImage
->CurrentFilePointer
) + strlen (Buffer
) + 1);
1551 fclose (SourceFile
);
1557 IN OUT MEMORY_FILE
*FvImage
,
1560 IN OUT EFI_FFS_FILE_HEADER
**VtfFileImage
,
1561 IN OUT MEMORY_FILE
*SymImage
1565 Routine Description:
1567 This function adds a file to the FV image. The file will pad to the
1568 appropriate alignment if required.
1572 FvImage The memory image of the FV to add it to. The current offset
1574 FvInfo Pointer to information about the FV.
1575 Index The file in the FvInfo file list to add.
1576 VtfFileImage A pointer to the VTF file within the FvImage. If this is equal
1577 to the end of the FvImage then no VTF previously found.
1578 SymImage The memory image of the Sym file to update if symbols are present.
1579 The current offset must be valid.
1583 EFI_SUCCESS The function completed successfully.
1584 EFI_INVALID_PARAMETER One of the input parameters was invalid.
1585 EFI_ABORTED An error occurred.
1586 EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the add.
1594 UINT32 CurrentFileAlignment
;
1596 EFI_PHYSICAL_ADDRESS CurrentFileBaseAddress
;
1597 UINT8 VtfHeaderChecksum
;
1598 UINT8 VtfFileChecksum
;
1600 EFI_FFS_FILE_TAIL TailValue
;
1603 // Verify input parameters.
1605 if (FvImage
== NULL
|| FvInfo
== NULL
|| FvInfo
->FvFiles
[Index
][0] == 0 || VtfFileImage
== NULL
|| SymImage
== NULL
) {
1606 return EFI_INVALID_PARAMETER
;
1609 // Read the file to add
1611 NewFile
= fopen (FvInfo
->FvFiles
[Index
], "rb");
1613 if (NewFile
== NULL
) {
1614 Error (NULL
, 0, 0, FvInfo
->FvFiles
[Index
], "failed to open file for reading");
1618 // Get the file size
1622 struct stat stat_buf
;
1623 fstat(fileno(NewFile
), &stat_buf
);
1624 FileSize
= stat_buf
.st_size
;
1627 FileSize
= _filelength (fileno (NewFile
));
1631 // Read the file into a buffer
1633 FileBuffer
= malloc (FileSize
);
1634 if (FileBuffer
== NULL
) {
1635 Error (NULL
, 0, 0, "memory allocation failure", NULL
);
1636 return EFI_OUT_OF_RESOURCES
;
1639 NumBytesRead
= fread (FileBuffer
, sizeof (UINT8
), FileSize
, NewFile
);
1642 // Done with the file, from this point on we will just use the buffer read.
1647 // Verify read successful
1649 if (NumBytesRead
!= sizeof (UINT8
) * FileSize
) {
1651 Error (NULL
, 0, 0, FvInfo
->FvFiles
[Index
], "failed to read input file contents");
1655 // Verify space exists to add the file
1657 if (FileSize
> (UINTN
) ((UINTN
) *VtfFileImage
- (UINTN
) FvImage
->CurrentFilePointer
)) {
1658 Error (NULL
, 0, 0, FvInfo
->FvFiles
[Index
], "insufficient space remains to add the file");
1659 return EFI_OUT_OF_RESOURCES
;
1662 // Update the file state based on polarity of the FV.
1664 UpdateFfsFileState (
1665 (EFI_FFS_FILE_HEADER
*) FileBuffer
,
1666 (EFI_FIRMWARE_VOLUME_HEADER
*) FvImage
->FileImage
1670 // If we have a VTF file, add it at the top.
1672 if (IsVtfFile ((EFI_FFS_FILE_HEADER
*) FileBuffer
)) {
1673 if ((UINTN
) *VtfFileImage
== (UINTN
) FvImage
->Eof
) {
1675 // No previous VTF, add this one.
1677 *VtfFileImage
= (EFI_FFS_FILE_HEADER
*) (UINTN
) ((UINTN
) FvImage
->FileImage
+ FvInfo
->Size
- FileSize
);
1679 // Sanity check. The file MUST align appropriately
1681 if ((((UINTN
) *VtfFileImage
) & 0x07) != 0) {
1682 Error (NULL
, 0, 0, "VTF file does not align on 8-byte boundary", NULL
);
1685 // copy VTF File Header
1687 memcpy (*VtfFileImage
, FileBuffer
, sizeof (EFI_FFS_FILE_HEADER
));
1693 (UINT8
*) *VtfFileImage
+ sizeof (EFI_FFS_FILE_HEADER
),
1694 FileBuffer
+ sizeof (EFI_FFS_FILE_HEADER
),
1695 FileSize
- sizeof (EFI_FFS_FILE_HEADER
)
1699 // re-calculate the VTF File Header
1701 FileState
= (*VtfFileImage
)->State
;
1702 (*VtfFileImage
)->State
= 0;
1703 *(UINT32
*) ((*VtfFileImage
)->Size
) = FileSize
;
1704 (*VtfFileImage
)->IntegrityCheck
.Checksum
.Header
= 0;
1705 (*VtfFileImage
)->IntegrityCheck
.Checksum
.File
= 0;
1707 VtfHeaderChecksum
= CalculateChecksum8 ((UINT8
*) *VtfFileImage
, sizeof (EFI_FFS_FILE_HEADER
));
1708 (*VtfFileImage
)->IntegrityCheck
.Checksum
.Header
= VtfHeaderChecksum
;
1710 // Determine if it has a tail
1712 if ((*VtfFileImage
)->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
1713 TailSize
= sizeof (EFI_FFS_FILE_TAIL
);
1718 if ((*VtfFileImage
)->Attributes
& FFS_ATTRIB_CHECKSUM
) {
1719 VtfFileChecksum
= CalculateChecksum8 ((UINT8
*) *VtfFileImage
, FileSize
- TailSize
);
1720 (*VtfFileImage
)->IntegrityCheck
.Checksum
.File
= VtfFileChecksum
;
1722 (*VtfFileImage
)->IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
1725 // If it has a file tail, update it
1727 if ((*VtfFileImage
)->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
1728 TailValue
= (EFI_FFS_FILE_TAIL
) (~((*VtfFileImage
)->IntegrityCheck
.TailReference
));
1729 *(EFI_FFS_FILE_TAIL
*) (((UINTN
) (*VtfFileImage
) + GetLength ((*VtfFileImage
)->Size
) - sizeof (EFI_FFS_FILE_TAIL
))) = TailValue
;
1731 (*VtfFileImage
)->State
= FileState
;
1736 // Already found a VTF file.
1738 Error (NULL
, 0, 0, "multiple VTF files are illegal in a single FV", NULL
);
1744 // Check if alignment is required
1746 Status
= ReadFfsAlignment ((EFI_FFS_FILE_HEADER
*) FileBuffer
, &CurrentFileAlignment
);
1747 if (EFI_ERROR (Status
)) {
1748 printf ("ERROR: Could not determine alignment of file %s.\n", FvInfo
->FvFiles
[Index
]);
1753 // Add pad file if necessary
1755 Status
= AddPadFile (FvImage
, CurrentFileAlignment
);
1756 if (EFI_ERROR (Status
)) {
1757 printf ("ERROR: Could not align the file data properly.\n");
1764 if ((FvImage
->CurrentFilePointer
+ FileSize
) < FvImage
->Eof
) {
1768 memcpy (FvImage
->CurrentFilePointer
, FileBuffer
, FileSize
);
1771 // If the file is XIP, rebase
1773 CurrentFileBaseAddress
= FvInfo
->BaseAddress
+ ((UINTN
) FvImage
->CurrentFilePointer
- (UINTN
) FvImage
->FileImage
);
1775 // Status = RebaseFfsFile ((EFI_FFS_FILE_HEADER*) FvImage->CurrentFilePointer, CurrentFileBaseAddress);
1776 // if (EFI_ERROR(Status)) {
1777 // printf ("ERROR: Could not rebase the file %s.\n", FvInfo->FvFiles[Index]);
1778 // return EFI_ABORTED;
1781 // Update Symbol file
1783 Status
= AddSymFile (
1784 CurrentFileBaseAddress
,
1785 (EFI_FFS_FILE_HEADER
*) FvImage
->CurrentFilePointer
,
1787 FvInfo
->FvFiles
[Index
]
1789 assert (!EFI_ERROR (Status
));
1792 // Update the current pointer in the FV image
1794 FvImage
->CurrentFilePointer
+= FileSize
;
1796 printf ("ERROR: The firmware volume is out of space, could not add file %s.\n", FvInfo
->FvFiles
[Index
]);
1800 // Make next file start at QWord Boundry
1802 while (((UINTN
) FvImage
->CurrentFilePointer
& 0x07) != 0) {
1803 FvImage
->CurrentFilePointer
++;
1806 // Free allocated memory.
1820 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
1821 VARIABLE_STORE_HEADER
*VarStoreHeader
;
1823 // Variable block should exclude FvHeader. Since the length of
1824 // FvHeader depends on the block map, which is variable length,
1825 // we could only decide the actual variable block length here.
1827 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) FvImage
;
1828 FvImage
= FvImage
+ FvHeader
->HeaderLength
;
1830 VarStoreHeader
= (VARIABLE_STORE_HEADER
*) FvImage
;
1832 VarStoreHeader
->Signature
= VARIABLE_STORE_SIGNATURE
;
1833 VarStoreHeader
->Size
= Size
- FvHeader
->HeaderLength
;
1834 VarStoreHeader
->Format
= VARIABLE_STORE_FORMATTED
;
1835 VarStoreHeader
->State
= VARIABLE_STORE_HEALTHY
;
1836 VarStoreHeader
->Reserved
= 0;
1837 VarStoreHeader
->Reserved1
= 0;
1853 AddFTWWorkingBlock (
1859 EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER
*FTWHeader
;
1863 FTWHeader
= (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER
*) FvImage
;
1864 memcpy (&FTWHeader
->Signature
, &(FvInfo
->FvGuid
), sizeof (EFI_GUID
));
1865 FTWHeader
->WriteQueueSize
= Size
- sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER
);
1866 CalculateCrc32 (FvImage
, sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER
), &Crc32
);
1867 FTWHeader
->Crc
= Crc32
;
1868 if (FvInfo
->FvAttributes
& EFI_FVB_ERASE_POLARITY
) {
1869 FTWHeader
->WorkingBlockValid
= 0;
1870 FTWHeader
->WorkingBlockInvalid
= 1;
1872 FTWHeader
->WorkingBlockValid
= 1;
1873 FTWHeader
->WorkingBlockInvalid
= 0;
1896 Routine Description:
1898 This function generate the non FFS FV image, such as the working block
1899 and spare block. How each component of the FV is built is component
1904 FvImage The memory image of the FV to add it to. The current offset
1906 FvInfo Pointer to information about the FV.
1910 EFI_SUCCESS The function completed successfully.
1911 EFI_INVALID_PARAMETER One of the input parameters was invalid.
1912 EFI_ABORTED An error occurred.
1913 EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the add.
1918 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
1921 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) FvImage
;
1924 for (Index
= 0; FvInfo
->FvComponents
[Index
].Size
!= 0; Index
++) {
1925 if (stricmp (FvInfo
->FvComponents
[Index
].ComponentName
, EFI_NV_VARIABLE_STRING
) == 0) {
1926 AddVariableBlock (FvImage
, FvInfo
->FvComponents
[Index
].Size
, FvInfo
);
1927 } else if (stricmp (FvInfo
->FvComponents
[Index
].ComponentName
, EFI_NV_EVENT_LOG_STRING
) == 0) {
1928 AddEventLogBlock (FvImage
, FvInfo
->FvComponents
[Index
].Size
, FvInfo
);
1929 } else if (stricmp (FvInfo
->FvComponents
[Index
].ComponentName
, EFI_NV_FTW_WORKING_STRING
) == 0) {
1930 AddFTWWorkingBlock (FvImage
, FvInfo
->FvComponents
[Index
].Size
, FvInfo
);
1931 } else if (stricmp (FvInfo
->FvComponents
[Index
].ComponentName
, EFI_NV_FTW_SPARE_STRING
) == 0) {
1932 AddFTWSpareBlock (FvImage
, FvInfo
->FvComponents
[Index
].Size
, FvInfo
);
1934 printf ("Error. Unknown Non-FFS block %s \n", FvInfo
->FvComponents
[Index
].ComponentName
);
1938 FvImage
= FvImage
+ FvInfo
->FvComponents
[Index
].Size
;
1939 TotalSize
= TotalSize
+ FvInfo
->FvComponents
[Index
].Size
;
1942 // Index and TotalSize is zero mean there's no component, so this is an empty fv
1944 if ((Index
!= 0 || TotalSize
!= 0) && TotalSize
!= FvInfo
->Size
) {
1945 printf ("Error. Component size does not sum up to FV size.\n");
1954 IN MEMORY_FILE
*FvImage
,
1955 IN EFI_FFS_FILE_HEADER
*VtfFileImage
1959 Routine Description:
1961 This function places a pad file between the last file in the FV and the VTF
1962 file if the VTF file exists.
1966 FvImage Memory file for the FV memory image
1967 VtfFileImage The address of the VTF file. If this is the end of the FV
1968 image, no VTF exists and no pad file is needed.
1972 EFI_SUCCESS Completed successfully.
1973 EFI_INVALID_PARAMETER One of the input parameters was NULL.
1977 EFI_FFS_FILE_HEADER
*PadFile
;
1981 // If there is no VTF or the VTF naturally follows the previous file without a
1982 // pad file, then there's nothing to do
1984 if ((UINTN
) VtfFileImage
== (UINTN
) FvImage
->Eof
|| (void *) FvImage
->CurrentFilePointer
== (void *) VtfFileImage
) {
1988 // Pad file starts at beginning of free space
1990 PadFile
= (EFI_FFS_FILE_HEADER
*) FvImage
->CurrentFilePointer
;
1995 memset (PadFile
, 0, sizeof (EFI_FFS_FILE_HEADER
));
1996 memcpy (&PadFile
->Name
, &DefaultFvPadFileNameGuid
, sizeof (EFI_GUID
));
1997 PadFile
->Type
= EFI_FV_FILETYPE_FFS_PAD
;
1998 PadFile
->Attributes
= 0;
2001 // FileSize includes the EFI_FFS_FILE_HEADER
2003 FileSize
= (UINTN
) VtfFileImage
- (UINTN
) FvImage
->CurrentFilePointer
;
2004 PadFile
->Size
[0] = (UINT8
) (FileSize
& 0x000000FF);
2005 PadFile
->Size
[1] = (UINT8
) ((FileSize
& 0x0000FF00) >> 8);
2006 PadFile
->Size
[2] = (UINT8
) ((FileSize
& 0x00FF0000) >> 16);
2009 // Fill in checksums and state, must be zero during checksum calculation.
2011 PadFile
->IntegrityCheck
.Checksum
.Header
= 0;
2012 PadFile
->IntegrityCheck
.Checksum
.File
= 0;
2014 PadFile
->IntegrityCheck
.Checksum
.Header
= CalculateChecksum8 ((UINT8
*) PadFile
, sizeof (EFI_FFS_FILE_HEADER
));
2015 if (PadFile
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
2016 PadFile
->IntegrityCheck
.Checksum
.File
= CalculateChecksum8 ((UINT8
*) PadFile
, FileSize
);
2018 PadFile
->IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
2021 PadFile
->State
= EFI_FILE_HEADER_CONSTRUCTION
| EFI_FILE_HEADER_VALID
| EFI_FILE_DATA_VALID
;
2023 UpdateFfsFileState (
2024 (EFI_FFS_FILE_HEADER
*) PadFile
,
2025 (EFI_FIRMWARE_VOLUME_HEADER
*) FvImage
->FileImage
2028 // Update the current FV pointer
2030 FvImage
->CurrentFilePointer
= FvImage
->Eof
;
2037 IN MEMORY_FILE
*FvImage
,
2039 IN EFI_FFS_FILE_HEADER
*VtfFile
2043 Routine Description:
2045 This parses the FV looking for the PEI core and then plugs the address into
2046 the SALE_ENTRY point of the BSF/VTF for IPF and does BUGBUG TBD action to
2047 complete an IA32 Bootstrap FV.
2051 FvImage Memory file for the FV memory image
2052 FvInfo Information read from INF file.
2053 VtfFile Pointer to the VTF file in the FV image.
2057 EFI_SUCCESS Function Completed successfully.
2058 EFI_ABORTED Error encountered.
2059 EFI_INVALID_PARAMETER A required parameter was NULL.
2060 EFI_NOT_FOUND PEI Core file not found.
2064 EFI_FFS_FILE_HEADER
*PeiCoreFile
;
2065 EFI_FFS_FILE_HEADER
*SecCoreFile
;
2067 EFI_FILE_SECTION_POINTER Pe32Section
;
2071 EFI_PHYSICAL_ADDRESS PeiCorePhysicalAddress
;
2072 EFI_PHYSICAL_ADDRESS SecCorePhysicalAddress
;
2073 EFI_PHYSICAL_ADDRESS
*SecCoreEntryAddressPtr
;
2074 UINT32
*Ia32ResetAddressPtr
;
2076 UINT8
*BytePointer2
;
2077 UINT16
*WordPointer
;
2080 EFI_FFS_FILE_STATE SavedState
;
2081 EFI_FFS_FILE_TAIL TailValue
;
2084 FIT_TABLE
*FitTablePtr
;
2087 // Verify input parameters
2089 if (FvImage
== NULL
|| FvInfo
== NULL
|| VtfFile
== NULL
) {
2090 return EFI_INVALID_PARAMETER
;
2093 // Initialize FV library
2095 InitializeFvLib (FvImage
->FileImage
, (UINTN
) FvImage
->Eof
- (UINTN
) FvImage
->FileImage
);
2100 Status
= VerifyFfsFile (VtfFile
);
2101 if (EFI_ERROR (Status
)) {
2102 return EFI_INVALID_PARAMETER
;
2105 // Find the PEI Core
2107 Status
= GetFileByType (EFI_FV_FILETYPE_PEI_CORE
, 1, &PeiCoreFile
);
2108 if (EFI_ERROR (Status
) || PeiCoreFile
== NULL
) {
2109 Error (NULL
, 0, 0, "could not find the PEI core in the FV", NULL
);
2114 // PEI Core found, now find PE32 or TE section
2116 Status
= GetSectionByType (PeiCoreFile
, EFI_SECTION_PE32
, 1, &Pe32Section
);
2117 if (Status
== EFI_NOT_FOUND
) {
2118 Status
= GetSectionByType (PeiCoreFile
, EFI_SECTION_TE
, 1, &Pe32Section
);
2121 if (EFI_ERROR (Status
)) {
2122 Error (NULL
, 0, 0, "could not find PE32 or TE section in PEI core file", NULL
);
2126 Status
= GetPe32Info (
2127 (VOID
*) ((UINTN
) Pe32Section
.Pe32Section
+ sizeof (EFI_SECTION_PE32
)),
2133 if (EFI_ERROR (Status
)) {
2134 Error (NULL
, 0, 0, "could not get PE32 entry point for PEI core", NULL
);
2138 // Physical address is FV base + offset of PE32 + offset of the entry point
2140 PeiCorePhysicalAddress
= FvInfo
->BaseAddress
;
2141 PeiCorePhysicalAddress
+= (UINTN
) Pe32Section
.Pe32Section
+ sizeof (EFI_SECTION_PE32
) - (UINTN
) FvImage
->FileImage
;
2142 PeiCorePhysicalAddress
+= EntryPoint
;
2144 if (MachineType
== EFI_IMAGE_MACHINE_IA64
) {
2146 // Update PEI_CORE address
2149 // Set the uncached attribute bit in the physical address
2151 PeiCorePhysicalAddress
|= 0x8000000000000000ULL
;
2154 // Check if address is aligned on a 16 byte boundary
2156 if (PeiCorePhysicalAddress
& 0xF) {
2158 "ERROR: PEI_CORE entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n",
2159 PeiCorePhysicalAddress
2164 // First Get the FIT table address
2166 FitAddress
= (*(UINT64
*) (FvImage
->Eof
- IPF_FIT_ADDRESS_OFFSET
)) & 0xFFFFFFFF;
2168 FitTablePtr
= (FIT_TABLE
*) (FvImage
->FileImage
+ (FitAddress
- FvInfo
->BaseAddress
));
2170 Status
= UpdatePeiCoreEntryInFit (FitTablePtr
, PeiCorePhysicalAddress
);
2172 if (!EFI_ERROR (Status
)) {
2173 UpdateFitCheckSum (FitTablePtr
);
2176 // Find the Sec Core
2178 Status
= GetFileByType (EFI_FV_FILETYPE_SECURITY_CORE
, 1, &SecCoreFile
);
2179 if (EFI_ERROR (Status
) || SecCoreFile
== NULL
) {
2180 Error (NULL
, 0, 0, "could not find the Sec core in the FV", NULL
);
2184 // Sec Core found, now find PE32 section
2186 Status
= GetSectionByType (SecCoreFile
, EFI_SECTION_PE32
, 1, &Pe32Section
);
2187 if (EFI_ERROR (Status
)) {
2188 Error (NULL
, 0, 0, "could not find PE32 section in SEC core file", NULL
);
2192 Status
= GetPe32Info (
2193 (VOID
*) ((UINTN
) Pe32Section
.Pe32Section
+ sizeof (EFI_SECTION_PE32
)),
2198 if (EFI_ERROR (Status
)) {
2199 Error (NULL
, 0, 0, "could not get PE32 entry point for SEC core", NULL
);
2203 // Physical address is FV base + offset of PE32 + offset of the entry point
2205 SecCorePhysicalAddress
= FvInfo
->BaseAddress
;
2206 SecCorePhysicalAddress
+= (UINTN
) Pe32Section
.Pe32Section
+ sizeof (EFI_SECTION_PE32
) - (UINTN
) FvImage
->FileImage
;
2207 SecCorePhysicalAddress
+= EntryPoint
;
2210 // Update SEC_CORE address
2213 // Set the uncached attribute bit in the physical address
2215 SecCorePhysicalAddress
|= 0x8000000000000000ULL
;
2218 // Update the address
2220 SecCoreEntryAddressPtr
= (EFI_PHYSICAL_ADDRESS
*) ((UINTN
) FvImage
->Eof
- IPF_SALE_ENTRY_ADDRESS_OFFSET
);
2221 *SecCoreEntryAddressPtr
= SecCorePhysicalAddress
;
2224 // Check if address is aligned on a 16 byte boundary
2226 if (SecCorePhysicalAddress
& 0xF) {
2228 "ERROR: SALE_ENTRY entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n",
2229 SecCorePhysicalAddress
2233 } else if (MachineType
== EFI_IMAGE_MACHINE_IA32
) {
2235 // Get the location to update
2237 Ia32ResetAddressPtr
= (UINT32
*) ((UINTN
) FvImage
->Eof
- IA32_PEI_CORE_ENTRY_OFFSET
);
2240 // Write lower 32 bits of physical address
2242 *Ia32ResetAddressPtr
= (UINT32
) PeiCorePhysicalAddress
;
2245 // Update the BFV base address
2247 Ia32ResetAddressPtr
= (UINT32
*) ((UINTN
) FvImage
->Eof
- 4);
2248 *Ia32ResetAddressPtr
= (UINT32
) (FvInfo
->BaseAddress
);
2253 // Update the Startup AP in the FVH header block ZeroVector region.
2255 BytePointer
= (UINT8
*) ((UINTN
) FvImage
->FileImage
);
2256 BytePointer2
= (FvInfo
->Size
== 0x10000) ? m64kRecoveryStartupApDataArray
: m128kRecoveryStartupApDataArray
;
2257 for (Index
= 0; Index
< SIZEOF_STARTUP_DATA_ARRAY
; Index
++) {
2258 *BytePointer
++ = *BytePointer2
++;
2261 // Calculate the checksum
2263 WordPointer
= (UINT16
*) ((UINTN
) FvImage
->FileImage
);
2264 for (Index
= 0; Index
< SIZEOF_STARTUP_DATA_ARRAY
/ 2; Index
++) {
2265 CheckSum
= (UINT16
) (CheckSum
+ ((UINT16
) *WordPointer
));
2269 // Update the checksum field
2271 BytePointer
= (UINT8
*) ((UINTN
) FvImage
->FileImage
);
2272 BytePointer
+= (SIZEOF_STARTUP_DATA_ARRAY
- 2);
2273 WordPointer
= (UINT16
*) BytePointer
;
2274 *WordPointer
= (UINT16
) (0x10000 - (UINT32
) CheckSum
);
2276 Error (NULL
, 0, 0, "invalid machine type in PEI core", "machine type=0x%X", (UINT32
) MachineType
);
2280 // Determine if it has an FFS file tail.
2282 if (VtfFile
->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
2283 TailSize
= sizeof (EFI_FFS_FILE_TAIL
);
2288 // Now update file checksum
2290 SavedState
= VtfFile
->State
;
2291 VtfFile
->IntegrityCheck
.Checksum
.File
= 0;
2293 if (VtfFile
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
2294 VtfFile
->IntegrityCheck
.Checksum
.File
= CalculateChecksum8 (
2296 GetLength (VtfFile
->Size
) - TailSize
2299 VtfFile
->IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
2302 VtfFile
->State
= SavedState
;
2305 // Update tail if present
2307 if (VtfFile
->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
2308 TailValue
= (EFI_FFS_FILE_TAIL
) (~(VtfFile
->IntegrityCheck
.TailReference
));
2309 *(EFI_FFS_FILE_TAIL
*) (((UINTN
) (VtfFile
) + GetLength (VtfFile
->Size
) - sizeof (EFI_FFS_FILE_TAIL
))) = TailValue
;
2318 OUT UINT32
*EntryPoint
,
2319 OUT UINT32
*BaseOfCode
,
2320 OUT UINT16
*MachineType
2324 Routine Description:
2326 Retrieves the PE32 entry point offset and machine type from PE image or TeImage.
2327 See EfiImage.h for machine types. The entry point offset is from the beginning
2328 of the PE32 buffer passed in.
2332 Pe32 Beginning of the PE32.
2333 EntryPoint Offset from the beginning of the PE32 to the image entry point.
2334 BaseOfCode Base address of code.
2335 MachineType Magic number for the machine type.
2339 EFI_SUCCESS Function completed successfully.
2340 EFI_ABORTED Error encountered.
2341 EFI_INVALID_PARAMETER A required parameter was NULL.
2342 EFI_UNSUPPORTED The operation is unsupported.
2346 EFI_IMAGE_DOS_HEADER
*DosHeader
;
2347 EFI_IMAGE_NT_HEADERS
*NtHeader
;
2348 EFI_TE_IMAGE_HEADER
*TeHeader
;
2351 // Verify input parameters
2354 return EFI_INVALID_PARAMETER
;
2358 // First check whether it is one TE Image.
2360 TeHeader
= (EFI_TE_IMAGE_HEADER
*) Pe32
;
2361 if (TeHeader
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
2363 // By TeImage Header to get output
2365 *EntryPoint
= TeHeader
->AddressOfEntryPoint
+ sizeof (EFI_TE_IMAGE_HEADER
) - TeHeader
->StrippedSize
;
2366 *BaseOfCode
= TeHeader
->BaseOfCode
+ sizeof (EFI_TE_IMAGE_HEADER
) - TeHeader
->StrippedSize
;
2367 *MachineType
= TeHeader
->Machine
;
2371 // Then check whether
2372 // First is the DOS header
2374 DosHeader
= (EFI_IMAGE_DOS_HEADER
*) Pe32
;
2377 // Verify DOS header is expected
2379 if (DosHeader
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2380 printf ("ERROR: Unknown magic number in the DOS header, 0x%04X.\n", DosHeader
->e_magic
);
2381 return EFI_UNSUPPORTED
;
2384 // Immediately following is the NT header.
2386 NtHeader
= (EFI_IMAGE_NT_HEADERS
*) ((UINTN
) Pe32
+ DosHeader
->e_lfanew
);
2389 // Verify NT header is expected
2391 if (NtHeader
->Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2392 printf ("ERROR: Unrecognized image signature 0x%08X.\n", NtHeader
->Signature
);
2393 return EFI_UNSUPPORTED
;
2398 *EntryPoint
= NtHeader
->OptionalHeader
.AddressOfEntryPoint
;
2399 *BaseOfCode
= NtHeader
->OptionalHeader
.BaseOfCode
;
2400 *MachineType
= NtHeader
->FileHeader
.Machine
;
2404 // Verify machine type is supported
2406 if (*MachineType
!= EFI_IMAGE_MACHINE_IA32
&& *MachineType
!= EFI_IMAGE_MACHINE_IA64
&& *MachineType
!= EFI_IMAGE_MACHINE_X64
&& *MachineType
!= EFI_IMAGE_MACHINE_EBC
) {
2407 printf ("ERROR: Unrecognized machine type in the PE32 file.\n");
2408 return EFI_UNSUPPORTED
;
2414 // Exposed function implementations (prototypes are defined in GenFvImageLib.h)
2418 IN CHAR8
*InfFileImage
,
2419 IN UINTN InfFileSize
,
2420 OUT UINT8
**FvImage
,
2421 OUT UINTN
*FvImageSize
,
2422 OUT CHAR8
**FvFileName
,
2423 OUT UINT8
**SymImage
,
2424 OUT UINTN
*SymImageSize
,
2425 OUT CHAR8
**SymFileName
2429 Routine Description:
2431 This is the main function which will be called from application.
2435 InfFileImage Buffer containing the INF file contents.
2436 InfFileSize Size of the contents of the InfFileImage buffer.
2437 FvImage Pointer to the FV image created.
2438 FvImageSize Size of the FV image created and pointed to by FvImage.
2439 FvFileName Requested name for the FV file.
2440 SymImage Pointer to the Sym image created.
2441 SymImageSize Size of the Sym image created and pointed to by SymImage.
2442 SymFileName Requested name for the Sym file.
2446 EFI_SUCCESS Function completed successfully.
2447 EFI_OUT_OF_RESOURCES Could not allocate required resources.
2448 EFI_ABORTED Error encountered.
2449 EFI_INVALID_PARAMETER A required parameter was NULL.
2454 MEMORY_FILE InfMemoryFile
;
2455 MEMORY_FILE FvImageMemoryFile
;
2456 MEMORY_FILE SymImageMemoryFile
;
2459 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
2460 EFI_FFS_FILE_HEADER
*VtfFileImage
;
2463 // Check for invalid parameter
2465 if (InfFileImage
== NULL
|| FvImage
== NULL
|| FvImageSize
== NULL
|| FvFileName
== NULL
) {
2466 return EFI_INVALID_PARAMETER
;
2469 // Initialize file structures
2471 InfMemoryFile
.FileImage
= InfFileImage
;
2472 InfMemoryFile
.CurrentFilePointer
= InfFileImage
;
2473 InfMemoryFile
.Eof
= InfFileImage
+ InfFileSize
;
2476 // Parse the FV inf file for header information
2478 Status
= ParseFvInf (&InfMemoryFile
, &FvInfo
);
2479 if (EFI_ERROR (Status
)) {
2480 printf ("ERROR: Could not parse the input INF file.\n");
2484 // Update the file name return values
2486 strcpy (*FvFileName
, FvInfo
.FvName
);
2487 strcpy (*SymFileName
, FvInfo
.SymName
);
2490 // Calculate the FV size
2492 *FvImageSize
= FvInfo
.Size
;
2497 *FvImage
= malloc (*FvImageSize
);
2498 if (*FvImage
== NULL
) {
2499 return EFI_OUT_OF_RESOURCES
;
2502 // Allocate space for symbol file storage
2504 *SymImage
= malloc (SYMBOL_FILE_SIZE
);
2505 if (*SymImage
== NULL
) {
2506 return EFI_OUT_OF_RESOURCES
;
2509 // Initialize the FV to the erase polarity
2511 if (FvInfo
.FvAttributes
& EFI_FVB_ERASE_POLARITY
) {
2512 memset (*FvImage
, -1, *FvImageSize
);
2514 memset (*FvImage
, 0, *FvImageSize
);
2517 // Initialize FV header
2519 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) *FvImage
;
2522 // Initialize the zero vector to all zeros.
2524 memset (FvHeader
->ZeroVector
, 0, 16);
2527 // Copy the FFS GUID
2529 memcpy (&FvHeader
->FileSystemGuid
, &FvInfo
.FvGuid
, sizeof (EFI_GUID
));
2531 FvHeader
->FvLength
= *FvImageSize
;
2532 FvHeader
->Signature
= EFI_FVH_SIGNATURE
;
2533 FvHeader
->Attributes
= FvInfo
.FvAttributes
;
2534 FvHeader
->Revision
= EFI_FVH_REVISION
;
2535 FvHeader
->Reserved
[0] = 0;
2536 FvHeader
->Reserved
[1] = 0;
2537 FvHeader
->Reserved
[2] = 0;
2540 // Copy firmware block map
2542 for (Index
= 0; FvInfo
.FvBlocks
[Index
].NumBlocks
!= 0; Index
++) {
2543 FvHeader
->FvBlockMap
[Index
].NumBlocks
= FvInfo
.FvBlocks
[Index
].NumBlocks
;
2544 FvHeader
->FvBlockMap
[Index
].BlockLength
= FvInfo
.FvBlocks
[Index
].BlockLength
;
2547 // Add block map terminator
2549 FvHeader
->FvBlockMap
[Index
].NumBlocks
= 0;
2550 FvHeader
->FvBlockMap
[Index
].BlockLength
= 0;
2553 // Complete the header
2555 FvHeader
->HeaderLength
= (UINT16
) (((UINTN
) &(FvHeader
->FvBlockMap
[Index
+ 1])) - (UINTN
) *FvImage
);
2556 FvHeader
->Checksum
= 0;
2557 FvHeader
->Checksum
= CalculateChecksum16 ((UINT16
*) FvHeader
, FvHeader
->HeaderLength
/ sizeof (UINT16
));
2560 // If there is no FFS file, find and generate each components of the FV
2562 if (FvInfo
.FvFiles
[0][0] == 0) {
2563 Status
= GenNonFFSFv (*FvImage
, &FvInfo
);
2564 if (EFI_ERROR (Status
)) {
2565 printf ("ERROR: Could not generate NonFFS FV.\n");
2573 // Initialize our "file" view of the buffer
2575 FvImageMemoryFile
.FileImage
= *FvImage
;
2576 FvImageMemoryFile
.CurrentFilePointer
= *FvImage
+ FvHeader
->HeaderLength
;
2577 FvImageMemoryFile
.Eof
= *FvImage
+*FvImageSize
;
2580 // Initialize our "file" view of the symbol file.
2582 SymImageMemoryFile
.FileImage
= *SymImage
;
2583 SymImageMemoryFile
.CurrentFilePointer
= *SymImage
;
2584 SymImageMemoryFile
.Eof
= *FvImage
+ SYMBOL_FILE_SIZE
;
2587 // Initialize the FV library.
2589 InitializeFvLib (FvImageMemoryFile
.FileImage
, FvInfo
.Size
);
2592 // Files start on 8 byte alignments, so move to the next 8 byte aligned
2593 // address. For now, just assert if it isn't. Currently FV header is
2594 // always a multiple of 8 bytes.
2595 // BUGBUG: Handle this better
2597 assert ((((UINTN
) FvImageMemoryFile
.CurrentFilePointer
) % 8) == 0);
2600 // Initialize the VTF file address.
2602 VtfFileImage
= (EFI_FFS_FILE_HEADER
*) FvImageMemoryFile
.Eof
;
2607 for (Index
= 0; FvInfo
.FvFiles
[Index
][0] != 0; Index
++) {
2611 Status
= AddFile (&FvImageMemoryFile
, &FvInfo
, Index
, &VtfFileImage
, &SymImageMemoryFile
);
2614 // Exit if error detected while adding the file
2616 if (EFI_ERROR (Status
)) {
2617 printf ("ERROR: Could not add file %s.\n", FvInfo
.FvFiles
[Index
]);
2623 // If there is a VTF file, some special actions need to occur.
2625 if ((UINTN
) VtfFileImage
!= (UINTN
) FvImageMemoryFile
.Eof
) {
2627 // Pad from the end of the last file to the beginning of the VTF file.
2629 Status
= PadFvImage (&FvImageMemoryFile
, VtfFileImage
);
2630 if (EFI_ERROR (Status
)) {
2631 printf ("ERROR: Could not create the pad file between the last file and the VTF file.\n");
2636 // Update reset vector (SALE_ENTRY for IPF)
2637 // Now for IA32 and IA64 platform, the fv which has bsf file must have the
2638 // EndAddress of 0xFFFFFFFF. Thus, only this type fv needs to update the
2639 // reset vector. If the PEI Core is found, the VTF file will probably get
2640 // corrupted by updating the entry point.
2642 if ((FvInfo
.BaseAddress
+ FvInfo
.Size
) == FV_IMAGES_TOP_ADDRESS
) {
2643 Status
= UpdateResetVector (&FvImageMemoryFile
, &FvInfo
, VtfFileImage
);
2644 if (EFI_ERROR(Status
)) {
2645 printf ("ERROR: Could not update the reset vector.\n");
2652 // Determine final Sym file size
2654 *SymImageSize
= SymImageMemoryFile
.CurrentFilePointer
- SymImageMemoryFile
.FileImage
;
2660 UpdatePeiCoreEntryInFit (
2661 IN FIT_TABLE
*FitTablePtr
,
2662 IN UINT64 PeiCorePhysicalAddress
2666 Routine Description:
2668 This function is used to update the Pei Core address in FIT, this can be used by Sec core to pass control from
2673 FitTablePtr - The pointer of FIT_TABLE.
2674 PeiCorePhysicalAddress - The address of Pei Core entry.
2678 EFI_SUCCESS - The PEI_CORE FIT entry was updated successfully.
2679 EFI_NOT_FOUND - Not found the PEI_CORE FIT entry.
2683 FIT_TABLE
*TmpFitPtr
;
2685 UINTN NumFitComponents
;
2687 TmpFitPtr
= FitTablePtr
;
2688 NumFitComponents
= TmpFitPtr
->CompSize
;
2690 for (Index
= 0; Index
< NumFitComponents
; Index
++) {
2691 if ((TmpFitPtr
->CvAndType
& FIT_TYPE_MASK
) == COMP_TYPE_FIT_PEICORE
) {
2692 TmpFitPtr
->CompAddress
= PeiCorePhysicalAddress
;
2699 return EFI_NOT_FOUND
;
2704 IN FIT_TABLE
*FitTablePtr
2708 Routine Description:
2710 This function is used to update the checksum for FIT.
2715 FitTablePtr - The pointer of FIT_TABLE.
2723 if ((FitTablePtr
->CvAndType
& CHECKSUM_BIT_MASK
) >> 7) {
2724 FitTablePtr
->CheckSum
= 0;
2725 FitTablePtr
->CheckSum
= CalculateChecksum8 ((UINT8
*) FitTablePtr
, FitTablePtr
->CompSize
* 16);