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"
52 // Different file separater for Linux and Windows
55 #define FILE_SEP_CHAR '/'
56 #define FILE_SEP_STRING "/"
58 #define FILE_SEP_CHAR '\\'
59 #define FILE_SEP_STRING "\\"
62 static UINT32 MaxFfsAlignment
= 0;
64 // Local function prototypes
69 OUT UINT32
*EntryPoint
,
70 OUT UINT32
*BaseOfCode
,
71 OUT UINT16
*MachineType
75 // Local function implementations.
77 EFI_GUID FfsGuid
= EFI_FIRMWARE_FILE_SYSTEM_GUID
;
78 EFI_GUID DefaultFvPadFileNameGuid
= { 0x78f54d4, 0xcc22, 0x4048, 0x9e, 0x94, 0x87, 0x9c, 0x21, 0x4d, 0x56, 0x2f };
81 // This data array will be located at the base of the Firmware Volume Header (FVH)
82 // in the boot block. It must not exceed 14 bytes of code. The last 2 bytes
83 // will be used to keep the FVH checksum consistent.
84 // This code will be run in response to a starutp IPI for HT-enabled systems.
86 #define SIZEOF_STARTUP_DATA_ARRAY 0x10
88 UINT8 m128kRecoveryStartupApDataArray
[SIZEOF_STARTUP_DATA_ARRAY
] = {
90 // EA D0 FF 00 F0 ; far jmp F000:FFD0
91 // 0, 0, 0, 0, 0, 0, 0, 0, 0, ; Reserved bytes
92 // 0, 0 ; Checksum Padding
112 UINT8 m64kRecoveryStartupApDataArray
[SIZEOF_STARTUP_DATA_ARRAY
] = {
114 // EB CE ; jmp short ($-0x30)
115 // ; (from offset 0x0 to offset 0xFFD0)
116 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ; Reserved bytes
117 // 0, 0 ; Checksum Padding
139 IN MEMORY_FILE
*InfFile
,
146 This function parses a FV.INF file and copies info into a FV_INFO structure.
150 InfFile Memory file image.
151 FvInfo Information read from INF file.
155 EFI_SUCCESS INF file information successfully retrieved.
156 EFI_ABORTED INF file has an invalid format.
157 EFI_NOT_FOUND A required string was not found in the INF file.
160 CHAR8 Value
[_MAX_PATH
];
166 // Initialize FV info
168 memset (FvInfo
, 0, sizeof (FV_INFO
));
171 // Read the FV base address
173 Status
= FindToken (InfFile
, OPTIONS_SECTION_STRING
, EFI_FV_BASE_ADDRESS_STRING
, 0, Value
);
175 if (Status
== EFI_SUCCESS
) {
177 // Get the base address
179 Status
= AsciiStringToUint64 (Value
, FALSE
, &Value64
);
180 if (EFI_ERROR (Status
)) {
181 Error (NULL
, 0, 0, EFI_FV_BASE_ADDRESS_STRING
, "invalid value");
185 FvInfo
->BaseAddress
= Value64
;
187 Error (NULL
, 0, 0, EFI_FV_BASE_ADDRESS_STRING
, "could not find value");
193 Status
= FindToken (InfFile
, OPTIONS_SECTION_STRING
, EFI_FV_GUID_STRING
, 0, Value
);
195 if (Status
== EFI_SUCCESS
) {
197 // Get the guid value
199 Status
= StringToGuid (Value
, &FvInfo
->FvGuid
);
200 if (EFI_ERROR (Status
)) {
201 memcpy (&FvInfo
->FvGuid
, &FfsGuid
, sizeof (EFI_GUID
));
204 memcpy (&FvInfo
->FvGuid
, &FfsGuid
, sizeof (EFI_GUID
));
207 // Read the FV file name
209 Status
= FindToken (InfFile
, OPTIONS_SECTION_STRING
, EFI_FV_FILE_NAME_STRING
, 0, Value
);
211 if (Status
== EFI_SUCCESS
) {
213 // copy the file name
215 strcpy (FvInfo
->FvName
, Value
);
217 Error (NULL
, 0, 0, EFI_FV_FILE_NAME_STRING
, "value not specified");
221 // Read the Sym file name
223 Status
= FindToken (InfFile
, OPTIONS_SECTION_STRING
, EFI_SYM_FILE_NAME_STRING
, 0, Value
);
225 if (Status
== EFI_SUCCESS
) {
227 // copy the file name
229 strcpy (FvInfo
->SymName
, Value
);
232 // Symbols not required, so init to NULL.
234 strcpy (FvInfo
->SymName
, "");
237 // Read the read disabled capability attribute
239 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_READ_DISABLED_CAP_STRING
, 0, Value
);
241 if (Status
== EFI_SUCCESS
) {
243 // Update the read disabled flag
245 if (strcmp (Value
, TRUE_STRING
) == 0) {
246 FvInfo
->FvAttributes
|= EFI_FVB_READ_DISABLED_CAP
;
247 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
248 Error (NULL
, 0, 0, EFI_FVB_READ_DISABLED_CAP_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
252 Error (NULL
, 0, 0, EFI_FVB_READ_DISABLED_CAP_STRING
, "value not specified");
256 // Read the read enabled capability attribute
258 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_READ_ENABLED_CAP_STRING
, 0, Value
);
260 if (Status
== EFI_SUCCESS
) {
262 // Update the read disabled flag
264 if (strcmp (Value
, TRUE_STRING
) == 0) {
265 FvInfo
->FvAttributes
|= EFI_FVB_READ_ENABLED_CAP
;
266 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
267 Error (NULL
, 0, 0, EFI_FVB_READ_ENABLED_CAP_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
271 Error (NULL
, 0, 0, EFI_FVB_READ_ENABLED_CAP_STRING
, "value not specified");
275 // Read the read status attribute
277 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_READ_STATUS_STRING
, 0, Value
);
279 if (Status
== EFI_SUCCESS
) {
281 // Update the read disabled flag
283 if (strcmp (Value
, TRUE_STRING
) == 0) {
284 FvInfo
->FvAttributes
|= EFI_FVB_READ_STATUS
;
285 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
286 Error (NULL
, 0, 0, EFI_FVB_READ_STATUS_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
290 Error (NULL
, 0, 0, EFI_FVB_READ_STATUS_STRING
, "value not specified");
294 // Read the write disabled capability attribute
296 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_WRITE_DISABLED_CAP_STRING
, 0, Value
);
298 if (Status
== EFI_SUCCESS
) {
300 // Update the write disabled flag
302 if (strcmp (Value
, TRUE_STRING
) == 0) {
303 FvInfo
->FvAttributes
|= EFI_FVB_WRITE_DISABLED_CAP
;
304 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
305 Error (NULL
, 0, 0, EFI_FVB_WRITE_DISABLED_CAP_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
309 Error (NULL
, 0, 0, EFI_FVB_WRITE_DISABLED_CAP_STRING
, "value not specified");
313 // Read the write enabled capability attribute
315 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_WRITE_ENABLED_CAP_STRING
, 0, Value
);
317 if (Status
== EFI_SUCCESS
) {
319 // Update the write disabled flag
321 if (strcmp (Value
, TRUE_STRING
) == 0) {
322 FvInfo
->FvAttributes
|= EFI_FVB_WRITE_ENABLED_CAP
;
323 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
324 Error (NULL
, 0, 0, EFI_FVB_WRITE_ENABLED_CAP_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
328 Error (NULL
, 0, 0, EFI_FVB_WRITE_ENABLED_CAP_STRING
, "value not specified");
332 // Read the write status attribute
334 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_WRITE_STATUS_STRING
, 0, Value
);
336 if (Status
== EFI_SUCCESS
) {
338 // Update the write disabled flag
340 if (strcmp (Value
, TRUE_STRING
) == 0) {
341 FvInfo
->FvAttributes
|= EFI_FVB_WRITE_STATUS
;
342 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
343 Error (NULL
, 0, 0, EFI_FVB_WRITE_STATUS_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
347 Error (NULL
, 0, 0, EFI_FVB_WRITE_STATUS_STRING
, "value not specified");
351 // Read the lock capability attribute
353 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_LOCK_CAP_STRING
, 0, Value
);
355 if (Status
== EFI_SUCCESS
) {
357 // Update the attribute flag
359 if (strcmp (Value
, TRUE_STRING
) == 0) {
360 FvInfo
->FvAttributes
|= EFI_FVB_LOCK_CAP
;
361 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
362 Error (NULL
, 0, 0, EFI_FVB_LOCK_CAP_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
366 Error (NULL
, 0, 0, EFI_FVB_LOCK_CAP_STRING
, "value not specified");
370 // Read the lock status attribute
372 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_LOCK_STATUS_STRING
, 0, Value
);
374 if (Status
== EFI_SUCCESS
) {
376 // Update the attribute flag
378 if (strcmp (Value
, TRUE_STRING
) == 0) {
379 FvInfo
->FvAttributes
|= EFI_FVB_LOCK_STATUS
;
380 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
381 Error (NULL
, 0, 0, EFI_FVB_LOCK_STATUS_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
385 Error (NULL
, 0, 0, EFI_FVB_LOCK_STATUS_STRING
, "value not specified");
389 // Read the sticky write attribute
391 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_STICKY_WRITE_STRING
, 0, Value
);
393 if (Status
== EFI_SUCCESS
) {
395 // Update the attribute flag
397 if (strcmp (Value
, TRUE_STRING
) == 0) {
398 FvInfo
->FvAttributes
|= EFI_FVB_STICKY_WRITE
;
399 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
400 Error (NULL
, 0, 0, EFI_FVB_STICKY_WRITE_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
404 Error (NULL
, 0, 0, EFI_FVB_STICKY_WRITE_STRING
, "value not specified");
408 // Read the memory mapped attribute
410 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_MEMORY_MAPPED_STRING
, 0, Value
);
412 if (Status
== EFI_SUCCESS
) {
414 // Update the attribute flag
416 if (strcmp (Value
, TRUE_STRING
) == 0) {
417 FvInfo
->FvAttributes
|= EFI_FVB_MEMORY_MAPPED
;
418 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
419 Error (NULL
, 0, 0, EFI_FVB_MEMORY_MAPPED_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
423 Error (NULL
, 0, 0, EFI_FVB_MEMORY_MAPPED_STRING
, "value not specified");
427 // Read the erase polarity attribute
429 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ERASE_POLARITY_STRING
, 0, Value
);
431 if (Status
== EFI_SUCCESS
) {
433 // Update the attribute flag
435 if (strcmp (Value
, ONE_STRING
) == 0) {
436 FvInfo
->FvAttributes
|= EFI_FVB_ERASE_POLARITY
;
437 } else if (strcmp (Value
, ZERO_STRING
) != 0) {
438 Error (NULL
, 0, 0, EFI_FVB_ERASE_POLARITY_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
442 Error (NULL
, 0, 0, EFI_FVB_ERASE_POLARITY_STRING
, "value not specified");
446 // Read the alignment capabilities attribute
448 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_CAP_STRING
, 0, Value
);
450 if (Status
== EFI_SUCCESS
) {
454 if (strcmp (Value
, TRUE_STRING
) == 0) {
455 FvInfo
->FvAttributes
|= EFI_FVB_ALIGNMENT_CAP
;
456 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
457 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_CAP_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
461 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_CAP_STRING
, "value not specified");
465 // Read the word alignment capability attribute
467 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_2_STRING
, 0, Value
);
469 if (Status
== EFI_SUCCESS
) {
473 if (strcmp (Value
, TRUE_STRING
) == 0) {
474 FvInfo
->FvAttributes
|= EFI_FVB_ALIGNMENT_2
;
475 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
476 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_2_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
480 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_2_STRING
, "value not specified");
484 // Read the dword alignment capability attribute
486 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_4_STRING
, 0, Value
);
488 if (Status
== EFI_SUCCESS
) {
492 if (strcmp (Value
, TRUE_STRING
) == 0) {
493 FvInfo
->FvAttributes
|= EFI_FVB_ALIGNMENT_4
;
494 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
495 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_4_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
499 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_4_STRING
, "value not specified");
503 // Read the word alignment capability attribute
505 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_8_STRING
, 0, Value
);
507 if (Status
== EFI_SUCCESS
) {
511 if (strcmp (Value
, TRUE_STRING
) == 0) {
512 FvInfo
->FvAttributes
|= EFI_FVB_ALIGNMENT_8
;
513 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
514 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_8_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
518 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_8_STRING
, "value not specified");
522 // Read the qword alignment capability attribute
524 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_16_STRING
, 0, Value
);
526 if (Status
== EFI_SUCCESS
) {
530 if (strcmp (Value
, TRUE_STRING
) == 0) {
531 FvInfo
->FvAttributes
|= EFI_FVB_ALIGNMENT_16
;
532 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
533 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_16_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
537 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_16_STRING
, "value not specified");
541 // Read the 32 byte alignment capability attribute
543 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_32_STRING
, 0, Value
);
545 if (Status
== EFI_SUCCESS
) {
549 if (strcmp (Value
, TRUE_STRING
) == 0) {
550 FvInfo
->FvAttributes
|= EFI_FVB_ALIGNMENT_32
;
551 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
552 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_32_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
556 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_32_STRING
, "value not specified");
560 // Read the 64 byte alignment capability attribute
562 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_64_STRING
, 0, Value
);
564 if (Status
== EFI_SUCCESS
) {
568 if (strcmp (Value
, TRUE_STRING
) == 0) {
569 FvInfo
->FvAttributes
|= EFI_FVB_ALIGNMENT_64
;
570 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
571 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_64_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
575 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_64_STRING
, "value not specified");
579 // Read the 128 byte alignment capability attribute
581 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_128_STRING
, 0, Value
);
583 if (Status
== EFI_SUCCESS
) {
587 if (strcmp (Value
, TRUE_STRING
) == 0) {
588 FvInfo
->FvAttributes
|= EFI_FVB_ALIGNMENT_128
;
589 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
590 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_128_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
594 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_128_STRING
, "value not specified");
598 // Read the 256 byte alignment capability attribute
600 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_256_STRING
, 0, Value
);
602 if (Status
== EFI_SUCCESS
) {
606 if (strcmp (Value
, TRUE_STRING
) == 0) {
607 FvInfo
->FvAttributes
|= EFI_FVB_ALIGNMENT_256
;
608 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
609 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_256_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
613 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_256_STRING
, "value not specified");
617 // Read the 512 byte alignment capability attribute
619 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_512_STRING
, 0, Value
);
621 if (Status
== EFI_SUCCESS
) {
625 if (strcmp (Value
, TRUE_STRING
) == 0) {
626 FvInfo
->FvAttributes
|= EFI_FVB_ALIGNMENT_512
;
627 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
628 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_512_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
632 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_512_STRING
, "value not specified");
636 // Read the 1K byte alignment capability attribute
638 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_1K_STRING
, 0, Value
);
640 if (Status
== EFI_SUCCESS
) {
644 if (strcmp (Value
, TRUE_STRING
) == 0) {
645 FvInfo
->FvAttributes
|= EFI_FVB_ALIGNMENT_1K
;
646 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
647 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_1K_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
651 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_1K_STRING
, "value not specified");
655 // Read the 2K byte alignment capability attribute
657 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_2K_STRING
, 0, Value
);
659 if (Status
== EFI_SUCCESS
) {
663 if (strcmp (Value
, TRUE_STRING
) == 0) {
664 FvInfo
->FvAttributes
|= EFI_FVB_ALIGNMENT_2K
;
665 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
666 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_2K_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
670 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_2K_STRING
, "value not specified");
674 // Read the 4K byte alignment capability attribute
676 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_4K_STRING
, 0, Value
);
678 if (Status
== EFI_SUCCESS
) {
682 if (strcmp (Value
, TRUE_STRING
) == 0) {
683 FvInfo
->FvAttributes
|= EFI_FVB_ALIGNMENT_4K
;
684 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
685 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_4K_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
689 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_4K_STRING
, "value not specified");
693 // Read the 8K byte alignment capability attribute
695 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_8K_STRING
, 0, Value
);
697 if (Status
== EFI_SUCCESS
) {
701 if (strcmp (Value
, TRUE_STRING
) == 0) {
702 FvInfo
->FvAttributes
|= EFI_FVB_ALIGNMENT_8K
;
703 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
704 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_8K_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
708 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_8K_STRING
, "value not specified");
712 // Read the 16K byte alignment capability attribute
714 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_16K_STRING
, 0, Value
);
716 if (Status
== EFI_SUCCESS
) {
720 if (strcmp (Value
, TRUE_STRING
) == 0) {
721 FvInfo
->FvAttributes
|= EFI_FVB_ALIGNMENT_16K
;
722 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
723 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_16K_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
727 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_16K_STRING
, "value not specified");
731 // Read the 32K byte alignment capability attribute
733 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_32K_STRING
, 0, Value
);
735 if (Status
== EFI_SUCCESS
) {
739 if (strcmp (Value
, TRUE_STRING
) == 0) {
740 FvInfo
->FvAttributes
|= EFI_FVB_ALIGNMENT_32K
;
741 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
742 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_32K_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
746 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_32K_STRING
, "value not specified");
750 // Read the 64K byte alignment capability attribute
752 Status
= FindToken (InfFile
, ATTRIBUTES_SECTION_STRING
, EFI_FVB_ALIGNMENT_64K_STRING
, 0, Value
);
754 if (Status
== EFI_SUCCESS
) {
758 if (strcmp (Value
, TRUE_STRING
) == 0) {
759 FvInfo
->FvAttributes
|= EFI_FVB_ALIGNMENT_64K
;
760 } else if (strcmp (Value
, FALSE_STRING
) != 0) {
761 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_64K_STRING
, "expected %s | %s", TRUE_STRING
, FALSE_STRING
);
765 Error (NULL
, 0, 0, EFI_FVB_ALIGNMENT_64K_STRING
, "value not specified");
769 if (!(FvInfo
->FvAttributes
& EFI_FVB_ALIGNMENT_CAP
) &&
771 (FvInfo
->FvAttributes
& EFI_FVB_ALIGNMENT_2
) ||
772 (FvInfo
->FvAttributes
& EFI_FVB_ALIGNMENT_4
) ||
773 (FvInfo
->FvAttributes
& EFI_FVB_ALIGNMENT_8
) ||
774 (FvInfo
->FvAttributes
& EFI_FVB_ALIGNMENT_16
) ||
775 (FvInfo
->FvAttributes
& EFI_FVB_ALIGNMENT_32
) ||
776 (FvInfo
->FvAttributes
& EFI_FVB_ALIGNMENT_64
) ||
777 (FvInfo
->FvAttributes
& EFI_FVB_ALIGNMENT_128
) ||
778 (FvInfo
->FvAttributes
& EFI_FVB_ALIGNMENT_256
) ||
779 (FvInfo
->FvAttributes
& EFI_FVB_ALIGNMENT_512
) ||
780 (FvInfo
->FvAttributes
& EFI_FVB_ALIGNMENT_1K
) ||
781 (FvInfo
->FvAttributes
& EFI_FVB_ALIGNMENT_2K
) ||
782 (FvInfo
->FvAttributes
& EFI_FVB_ALIGNMENT_4K
) ||
783 (FvInfo
->FvAttributes
& EFI_FVB_ALIGNMENT_8K
) ||
784 (FvInfo
->FvAttributes
& EFI_FVB_ALIGNMENT_16K
) ||
785 (FvInfo
->FvAttributes
& EFI_FVB_ALIGNMENT_32K
) ||
786 (FvInfo
->FvAttributes
& EFI_FVB_ALIGNMENT_64K
)
793 "illegal combination of alignment attributes",
794 "if %s is not %s, no individual alignments can be %s",
795 EFI_FVB_ALIGNMENT_CAP_STRING
,
804 for (Index
= 0; Index
< MAX_NUMBER_OF_FV_BLOCKS
; Index
++) {
806 // Read the number of blocks
808 Status
= FindToken (InfFile
, OPTIONS_SECTION_STRING
, EFI_NUM_BLOCKS_STRING
, Index
, Value
);
810 if (Status
== EFI_SUCCESS
) {
812 // Update the number of blocks
814 Status
= AsciiStringToUint64 (Value
, FALSE
, &Value64
);
815 if (EFI_ERROR (Status
)) {
816 Error (NULL
, 0, 0, Value
, "invalid value for %s", EFI_NUM_BLOCKS_STRING
);
820 FvInfo
->FvBlocks
[Index
].NumBlocks
= (UINT32
) Value64
;
823 // If there is no number of blocks, but there is a size, then we have a mismatched pair
824 // and should return an error.
826 Status
= FindToken (InfFile
, OPTIONS_SECTION_STRING
, EFI_BLOCK_SIZE_STRING
, Index
, Value
);
827 if (!EFI_ERROR (Status
)) {
828 Error (NULL
, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING
, EFI_BLOCK_SIZE_STRING
);
838 // Read the size of blocks
840 Status
= FindToken (InfFile
, OPTIONS_SECTION_STRING
, EFI_BLOCK_SIZE_STRING
, Index
, Value
);
842 if (Status
== EFI_SUCCESS
) {
844 // Update the number of blocks
846 Status
= AsciiStringToUint64 (Value
, FALSE
, &Value64
);
847 if (EFI_ERROR (Status
)) {
848 Error (NULL
, 0, 0, Value
, "invalid value specified for %s", EFI_BLOCK_SIZE_STRING
);
852 FvInfo
->FvBlocks
[Index
].BlockLength
= (UINT32
) Value64
;
855 // There is a number of blocks, but there is no size, so we have a mismatched pair
856 // and should return an error.
858 Error (NULL
, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING
, EFI_BLOCK_SIZE_STRING
);
865 for (Index
= 0; Index
< MAX_NUMBER_OF_FILES_IN_FV
; Index
++) {
867 // Read the number of blocks
869 Status
= FindToken (InfFile
, FILES_SECTION_STRING
, EFI_FILE_NAME_STRING
, Index
, Value
);
871 if (Status
== EFI_SUCCESS
) {
875 strcpy (FvInfo
->FvFiles
[Index
], Value
);
881 if (FindSection (InfFile
, COMPONENT_SECTION_STRING
)) {
884 // Read component FV_VARIABLE
886 Status
= FindToken (InfFile
, COMPONENT_SECTION_STRING
, EFI_NV_VARIABLE_STRING
, 0, Value
);
888 if (Status
== EFI_SUCCESS
) {
892 strcpy (FvInfo
->FvComponents
[Index
].ComponentName
, EFI_NV_VARIABLE_STRING
);
893 Status
= AsciiStringToUint64 (Value
, FALSE
, &Value64
);
894 if (EFI_ERROR (Status
)) {
895 printf ("ERROR: %s is not a valid integer.\n", EFI_NV_VARIABLE_STRING
);
899 FvInfo
->FvComponents
[Index
].Size
= (UINTN
) Value64
;
901 printf ("WARNING: Could not read %s.\n", EFI_NV_VARIABLE_STRING
);
906 // Read component FV_EVENT_LOG
908 Status
= FindToken (InfFile
, COMPONENT_SECTION_STRING
, EFI_NV_EVENT_LOG_STRING
, 0, Value
);
910 if (Status
== EFI_SUCCESS
) {
914 strcpy (FvInfo
->FvComponents
[Index
].ComponentName
, EFI_NV_EVENT_LOG_STRING
);
915 Status
= AsciiStringToUint64 (Value
, FALSE
, &Value64
);
916 if (EFI_ERROR (Status
)) {
917 printf ("ERROR: %s is not a valid integer.\n", EFI_NV_EVENT_LOG_STRING
);
921 FvInfo
->FvComponents
[Index
].Size
= (UINTN
) Value64
;
923 printf ("WARNING: Could not read %s.\n", EFI_NV_EVENT_LOG_STRING
);
928 // Read component FV_FTW_WORKING
930 Status
= FindToken (InfFile
, COMPONENT_SECTION_STRING
, EFI_NV_FTW_WORKING_STRING
, 0, Value
);
932 if (Status
== EFI_SUCCESS
) {
936 strcpy (FvInfo
->FvComponents
[Index
].ComponentName
, EFI_NV_FTW_WORKING_STRING
);
937 Status
= AsciiStringToUint64 (Value
, FALSE
, &Value64
);
938 if (EFI_ERROR (Status
)) {
939 printf ("ERROR: %s is not a valid integer.\n", EFI_NV_FTW_WORKING_STRING
);
943 FvInfo
->FvComponents
[Index
].Size
= (UINTN
) Value64
;
945 printf ("WARNING: Could not read %s.\n", EFI_NV_FTW_WORKING_STRING
);
950 // Read component FV_FTW_SPARE
952 Status
= FindToken (InfFile
, COMPONENT_SECTION_STRING
, EFI_NV_FTW_SPARE_STRING
, 0, Value
);
954 if (Status
== EFI_SUCCESS
) {
958 strcpy (FvInfo
->FvComponents
[Index
].ComponentName
, EFI_NV_FTW_SPARE_STRING
);
959 Status
= AsciiStringToUint64 (Value
, FALSE
, &Value64
);
960 if (EFI_ERROR (Status
)) {
961 printf ("ERROR: %s is not a valid integer.\n", EFI_NV_FTW_SPARE_STRING
);
965 FvInfo
->FvComponents
[Index
].Size
= (UINTN
) Value64
;
967 printf ("WARNING: Could not read %s.\n", EFI_NV_FTW_SPARE_STRING
);
971 // Compute size for easy access later
974 for (Index
= 0; FvInfo
->FvBlocks
[Index
].NumBlocks
; Index
++) {
975 FvInfo
->Size
+= FvInfo
->FvBlocks
[Index
].NumBlocks
* FvInfo
->FvBlocks
[Index
].BlockLength
;
983 IN EFI_FFS_FILE_HEADER
*FfsFile
,
984 IN EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
990 This function changes the FFS file attributes based on the erase polarity
1004 if (FvHeader
->Attributes
& EFI_FVB_ERASE_POLARITY
) {
1005 FfsFile
->State
= (UINT8
)~(FfsFile
->State
);
1011 IN EFI_FFS_FILE_HEADER
*FfsFile
,
1012 IN OUT UINT32
*Alignment
1016 Routine Description:
1018 This function determines the alignment of the FFS input file from the file
1023 FfsFile FFS file to parse
1024 Alignment The minimum required alignment of the FFS file, in bytes
1028 EFI_SUCCESS The function completed successfully.
1029 EFI_INVALID_PARAMETER One of the input parameters was invalid.
1030 EFI_ABORTED An error occurred.
1035 // Verify input parameters.
1037 if (FfsFile
== NULL
|| Alignment
== NULL
) {
1038 return EFI_INVALID_PARAMETER
;
1041 switch ((FfsFile
->Attributes
>> 3) & 0x07) {
1045 // 8 byte alignment, mini alignment requirement for FFS file.
1047 *Alignment
= (1 << 3);
1052 // 16 byte alignment
1054 *Alignment
= (1 << 4);
1059 // 128 byte alignment
1061 *Alignment
= (1 << 7);
1066 // 512 byte alignment
1068 *Alignment
= (1 << 9);
1073 // 1K byte alignment
1075 *Alignment
= (1 << 10);
1080 // 4K byte alignment
1082 *Alignment
= (1 << 12);
1087 // 32K byte alignment
1089 *Alignment
= (1 << 15);
1094 // 64K byte alignment
1096 *Alignment
= (1 << 16);
1100 Error (NULL
, 0, 0, "nvalid file attribute calculated, this is most likely a utility error", NULL
);
1109 IN OUT MEMORY_FILE
*FvImage
,
1110 IN UINT32 DataAlignment
1114 Routine Description:
1116 This function adds a pad file to the FV image if it required to align the
1117 data of the next file.
1121 FvImage The memory image of the FV to add it to. The current offset
1123 DataAlignment The data alignment of the next FFS file.
1127 EFI_SUCCESS The function completed successfully.
1128 EFI_INVALID_PARAMETER One of the input parameters was invalid.
1129 EFI_OUT_OF_RESOURCES Insufficient resources exist in the FV to complete
1134 EFI_FFS_FILE_HEADER
*PadFile
;
1135 EFI_GUID PadFileGuid
;
1139 // Verify input parameters.
1141 if (FvImage
== NULL
) {
1142 return EFI_INVALID_PARAMETER
;
1145 // Basic assumption is we start from an 8 byte aligned address
1146 // and our file header is a multiple of 8 bytes
1148 assert ((UINTN
) FvImage
->CurrentFilePointer
% 8 == 0);
1149 assert (sizeof (EFI_FFS_FILE_HEADER
) % 8 == 0);
1152 // Check if a pad file is necessary
1154 if (((UINTN
) FvImage
->CurrentFilePointer
- (UINTN
) FvImage
->FileImage
+ sizeof (EFI_FFS_FILE_HEADER
)) % DataAlignment
== 0) {
1158 // Write pad file header
1160 PadFile
= (EFI_FFS_FILE_HEADER
*) FvImage
->CurrentFilePointer
;
1163 // Verify that we have enough space for the file header
1165 if ((UINTN
) (PadFile
+ sizeof (EFI_FFS_FILE_HEADER
)) >= (UINTN
) FvImage
->Eof
) {
1166 return EFI_OUT_OF_RESOURCES
;
1172 uuid_generate (tmp_id
);
1173 memcpy (&PadFileGuid
, tmp_id
, sizeof (EFI_GUID
));
1176 UuidCreate (&PadFileGuid
);
1178 memset (PadFile
, 0, sizeof (EFI_FFS_FILE_HEADER
));
1179 memcpy (&PadFile
->Name
, &PadFileGuid
, sizeof (EFI_GUID
));
1180 PadFile
->Type
= EFI_FV_FILETYPE_FFS_PAD
;
1181 PadFile
->Attributes
= 0;
1184 // Calculate the pad file size
1187 // This is the earliest possible valid offset (current plus pad file header
1188 // plus the next file header)
1190 PadFileSize
= (UINTN
) FvImage
->CurrentFilePointer
- (UINTN
) FvImage
->FileImage
+ (sizeof (EFI_FFS_FILE_HEADER
) * 2);
1193 // Add whatever it takes to get to the next aligned address
1195 while ((PadFileSize
% DataAlignment
) != 0) {
1199 // Subtract the next file header size
1201 PadFileSize
-= sizeof (EFI_FFS_FILE_HEADER
);
1204 // Subtract the starting offset to get size
1206 PadFileSize
-= (UINTN
) FvImage
->CurrentFilePointer
- (UINTN
) FvImage
->FileImage
;
1209 // Write pad file size (calculated size minus next file header size)
1211 PadFile
->Size
[0] = (UINT8
) (PadFileSize
& 0xFF);
1212 PadFile
->Size
[1] = (UINT8
) ((PadFileSize
>> 8) & 0xFF);
1213 PadFile
->Size
[2] = (UINT8
) ((PadFileSize
>> 16) & 0xFF);
1216 // Fill in checksums and state, they must be 0 for checksumming.
1218 PadFile
->IntegrityCheck
.Checksum
.Header
= 0;
1219 PadFile
->IntegrityCheck
.Checksum
.File
= 0;
1221 PadFile
->IntegrityCheck
.Checksum
.Header
= CalculateChecksum8 ((UINT8
*) PadFile
, sizeof (EFI_FFS_FILE_HEADER
));
1222 if (PadFile
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
1223 PadFile
->IntegrityCheck
.Checksum
.File
= CalculateChecksum8 ((UINT8
*) PadFile
, PadFileSize
);
1225 PadFile
->IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
1228 PadFile
->State
= EFI_FILE_HEADER_CONSTRUCTION
| EFI_FILE_HEADER_VALID
| EFI_FILE_DATA_VALID
;
1229 UpdateFfsFileState (
1230 (EFI_FFS_FILE_HEADER
*) PadFile
,
1231 (EFI_FIRMWARE_VOLUME_HEADER
*) FvImage
->FileImage
1235 // Verify that we have enough space (including the padding
1237 if ((UINTN
) (PadFile
+ sizeof (EFI_FFS_FILE_HEADER
)) >= (UINTN
) FvImage
->Eof
) {
1238 return EFI_OUT_OF_RESOURCES
;
1241 // Update the current FV pointer
1243 FvImage
->CurrentFilePointer
+= PadFileSize
;
1250 IN EFI_FFS_FILE_HEADER
*FileBuffer
1254 Routine Description:
1256 This function checks the header to validate if it is a VTF file
1260 FileBuffer Buffer in which content of a file has been read.
1264 TRUE If this is a VTF file
1265 FALSE If this is not a VTF file
1269 EFI_GUID VtfGuid
= EFI_FFS_VOLUME_TOP_FILE_GUID
;
1270 if (!memcmp (&FileBuffer
->Name
, &VtfGuid
, sizeof (EFI_GUID
))) {
1278 FfsRebaseImageRead (
1279 IN VOID
*FileHandle
,
1280 IN UINTN FileOffset
,
1281 IN OUT UINT32
*ReadSize
,
1286 Routine Description:
1288 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
1292 FileHandle - The handle to the PE/COFF file
1294 FileOffset - The offset, in bytes, into the file to read
1296 ReadSize - The number of bytes to read from the file starting at FileOffset
1298 Buffer - A pointer to the buffer to read the data into.
1302 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
1306 CHAR8
*Destination8
;
1310 Destination8
= Buffer
;
1311 Source8
= (CHAR8
*) ((UINTN
) FileHandle
+ FileOffset
);
1314 *(Destination8
++) = *(Source8
++);
1323 IN UINT64 BaseAddress
,
1324 IN EFI_FFS_FILE_HEADER
*FfsFile
,
1325 IN OUT MEMORY_FILE
*SymImage
,
1326 IN CHAR8
*SourceFileName
1330 Routine Description:
1332 This function adds the SYM tokens in the source file to the destination file.
1333 The SYM tokens are updated to reflect the base address.
1337 BaseAddress The base address for the new SYM tokens.
1338 FfsFile Pointer to the beginning of the FFS file in question.
1339 SymImage The memory file to update with symbol information.
1340 SourceFileName The source file.
1344 EFI_SUCCESS The function completed successfully.
1345 EFI_INVALID_PARAMETER One of the input parameters was invalid.
1346 EFI_ABORTED An error occurred.
1352 CHAR8 Buffer
[_MAX_PATH
];
1353 CHAR8 Type
[_MAX_PATH
];
1354 CHAR8 Address
[_MAX_PATH
];
1355 CHAR8 Section
[_MAX_PATH
];
1356 CHAR8 Token
[_MAX_PATH
];
1357 CHAR8 SymFileName
[_MAX_PATH
];
1358 CHAR8 CodeModuleName
[_MAX_PATH
];
1361 UINT64 TokenAddress
;
1364 EFI_FILE_SECTION_POINTER Pe32Section
;
1370 // Verify input parameters.
1372 if (BaseAddress
== 0 || FfsFile
== NULL
|| SymImage
== NULL
|| SourceFileName
== NULL
) {
1373 Error (NULL
, 0, 0, "invalid parameter passed to AddSymFile()", NULL
);
1374 return EFI_INVALID_PARAMETER
;
1377 // Check if we want to add this file
1380 // Get the file name
1382 strcpy (Buffer
, SourceFileName
);
1385 // Copy the file name for the path of the sym file and truncate the name portion.
1387 strcpy (SymFileName
, Buffer
);
1388 Ptr
= strrchr (SymFileName
, FILE_SEP_CHAR
);
1393 // Find the file extension and make it lower case
1395 Ptr
= strrchr (SymFileName
, '.');
1400 // Check if it is PEI file
1402 if (strstr (Buffer
, ".pei") != NULL
) {
1404 // Find the human readable portion
1406 if (!strtok (Buffer
, "-") ||
1407 !strtok (NULL
, "-") ||
1408 !strtok (NULL
, "-") ||
1409 !strtok (NULL
, "-") ||
1410 !strtok (NULL
, "-") ||
1411 !strcpy (Buffer
, strtok (NULL
, "."))
1413 Error (NULL
, 0, 0, "failed to find human readable portion of the file name in AddSymFile()", NULL
);
1417 // Save code module name
1419 strcpy (CodeModuleName
, Buffer
);
1422 // Add the symbol file name and extension to the file path.
1424 strcat (Buffer
, ".sym");
1425 strcat (SymFileName
, FILE_SEP_CHAR
);
1426 strcat (SymFileName
, Buffer
);
1429 // Only handle PEIM files.
1434 // Find PE32 section
1436 Status
= GetSectionByType (FfsFile
, EFI_SECTION_PE32
, 1, &Pe32Section
);
1439 // BUGBUG: Assume if no PE32 section it is PIC and hardcode base address
1441 if (Status
== EFI_NOT_FOUND
) {
1442 Status
= GetSectionByType (FfsFile
, EFI_SECTION_TE
, 1, &Pe32Section
);
1445 if (Status
== EFI_SUCCESS
) {
1446 Status
= GetPe32Info (
1447 (VOID
*) ((UINTN
) Pe32Section
.Pe32Section
+ sizeof (EFI_SECTION_PE32
)),
1452 } else if (Status
== EFI_NOT_FOUND
) {
1454 // For PIC, hardcode.
1457 Status
= EFI_SUCCESS
;
1459 Error (NULL
, 0, 0, "could not parse a PE32 section from the PEI file", NULL
);
1463 if (EFI_ERROR (Status
)) {
1464 Error (NULL
, 0, 0, "GetPe32Info() could not get PE32 entry point for PEI file", NULL
);
1469 // Open the source file
1471 SourceFile
= fopen (SymFileName
, "r");
1472 if (SourceFile
== NULL
) {
1474 // SYM files are not required.
1479 // Read the first line
1481 if (fgets (Buffer
, _MAX_PATH
, SourceFile
) == NULL
) {
1485 // Make sure it matches the expected sym format
1487 if (strcmp (Buffer
, "TEXTSYM format | V1.0\n")) {
1488 fclose (SourceFile
);
1489 Error (NULL
, 0, 0, "AddSymFile() found unexpected sym format in input file", NULL
);
1495 while (feof (SourceFile
) == 0) {
1501 "%s | %s | %s | %s\n",
1508 // If the token starts with "??" ignore it
1510 if (Token
[0] == '?' && Token
[1] == '?') {
1514 // Get the token address
1516 AsciiStringToUint64 (Address
, TRUE
, &TokenAddress
);
1519 // Add the base address
1521 TokenAddress
+= BaseAddress
;
1524 // If PE32 or TE section then find the start of code. For PIC it is hardcoded.
1526 if (Pe32Section
.Pe32Section
) {
1528 // Add the offset of the PE32 section
1530 TokenAddress
+= (UINTN
) Pe32Section
.Pe32Section
- (UINTN
) FfsFile
;
1533 // Add the size of the PE32 section header
1535 TokenAddress
+= sizeof (EFI_PE32_SECTION
);
1538 // For PIC hardcoded.
1540 TokenAddress
+= 0x28;
1544 // Add the beginning of the code
1546 TokenAddress
+= BaseOfCode
;
1550 "%s | %016I64X | %s | _%s%s\n",
1557 memcpy (SymImage
->CurrentFilePointer
, Buffer
, strlen (Buffer
) + 1);
1558 SymImage
->CurrentFilePointer
= (UINT8
*) (((UINTN
) SymImage
->CurrentFilePointer
) + strlen (Buffer
) + 1);
1562 fclose (SourceFile
);
1568 IN OUT MEMORY_FILE
*FvImage
,
1571 IN OUT EFI_FFS_FILE_HEADER
**VtfFileImage
,
1572 IN OUT MEMORY_FILE
*SymImage
1576 Routine Description:
1578 This function adds a file to the FV image. The file will pad to the
1579 appropriate alignment if required.
1583 FvImage The memory image of the FV to add it to. The current offset
1585 FvInfo Pointer to information about the FV.
1586 Index The file in the FvInfo file list to add.
1587 VtfFileImage A pointer to the VTF file within the FvImage. If this is equal
1588 to the end of the FvImage then no VTF previously found.
1589 SymImage The memory image of the Sym file to update if symbols are present.
1590 The current offset must be valid.
1594 EFI_SUCCESS The function completed successfully.
1595 EFI_INVALID_PARAMETER One of the input parameters was invalid.
1596 EFI_ABORTED An error occurred.
1597 EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the add.
1605 UINT32 CurrentFileAlignment
;
1607 EFI_PHYSICAL_ADDRESS CurrentFileBaseAddress
;
1608 UINT8 VtfHeaderChecksum
;
1609 UINT8 VtfFileChecksum
;
1611 EFI_FFS_FILE_TAIL TailValue
;
1614 // Verify input parameters.
1616 if (FvImage
== NULL
|| FvInfo
== NULL
|| FvInfo
->FvFiles
[Index
][0] == 0 || VtfFileImage
== NULL
|| SymImage
== NULL
) {
1617 return EFI_INVALID_PARAMETER
;
1620 // Read the file to add
1622 NewFile
= fopen (FvInfo
->FvFiles
[Index
], "rb");
1624 if (NewFile
== NULL
) {
1625 Error (NULL
, 0, 0, FvInfo
->FvFiles
[Index
], "failed to open file for reading");
1629 // Get the file size
1631 FileSize
= _filelength (fileno (NewFile
));
1634 // Read the file into a buffer
1636 FileBuffer
= malloc (FileSize
);
1637 if (FileBuffer
== NULL
) {
1638 Error (NULL
, 0, 0, "memory allocation failure", NULL
);
1639 return EFI_OUT_OF_RESOURCES
;
1642 NumBytesRead
= fread (FileBuffer
, sizeof (UINT8
), FileSize
, NewFile
);
1645 // Done with the file, from this point on we will just use the buffer read.
1650 // Verify read successful
1652 if (NumBytesRead
!= sizeof (UINT8
) * FileSize
) {
1654 Error (NULL
, 0, 0, FvInfo
->FvFiles
[Index
], "failed to read input file contents");
1658 // Verify space exists to add the file
1660 if (FileSize
> (UINTN
) ((UINTN
) *VtfFileImage
- (UINTN
) FvImage
->CurrentFilePointer
)) {
1661 Error (NULL
, 0, 0, FvInfo
->FvFiles
[Index
], "insufficient space remains to add the file");
1662 return EFI_OUT_OF_RESOURCES
;
1665 // Update the file state based on polarity of the FV.
1667 UpdateFfsFileState (
1668 (EFI_FFS_FILE_HEADER
*) FileBuffer
,
1669 (EFI_FIRMWARE_VOLUME_HEADER
*) FvImage
->FileImage
1673 // If we have a VTF file, add it at the top.
1675 if (IsVtfFile ((EFI_FFS_FILE_HEADER
*) FileBuffer
)) {
1676 if ((UINTN
) *VtfFileImage
== (UINTN
) FvImage
->Eof
) {
1678 // No previous VTF, add this one.
1680 *VtfFileImage
= (EFI_FFS_FILE_HEADER
*) (UINTN
) ((UINTN
) FvImage
->FileImage
+ FvInfo
->Size
- FileSize
);
1682 // Sanity check. The file MUST align appropriately
1684 if ((((UINTN
) *VtfFileImage
) & 0x07) != 0) {
1685 Error (NULL
, 0, 0, "VTF file does not align on 8-byte boundary", NULL
);
1688 // copy VTF File Header
1690 memcpy (*VtfFileImage
, FileBuffer
, sizeof (EFI_FFS_FILE_HEADER
));
1696 (UINT8
*) *VtfFileImage
+ sizeof (EFI_FFS_FILE_HEADER
),
1697 FileBuffer
+ sizeof (EFI_FFS_FILE_HEADER
),
1698 FileSize
- sizeof (EFI_FFS_FILE_HEADER
)
1702 // re-calculate the VTF File Header
1704 FileState
= (*VtfFileImage
)->State
;
1705 (*VtfFileImage
)->State
= 0;
1706 *(UINT32
*) ((*VtfFileImage
)->Size
) = FileSize
;
1707 (*VtfFileImage
)->IntegrityCheck
.Checksum
.Header
= 0;
1708 (*VtfFileImage
)->IntegrityCheck
.Checksum
.File
= 0;
1710 VtfHeaderChecksum
= CalculateChecksum8 ((UINT8
*) *VtfFileImage
, sizeof (EFI_FFS_FILE_HEADER
));
1711 (*VtfFileImage
)->IntegrityCheck
.Checksum
.Header
= VtfHeaderChecksum
;
1713 // Determine if it has a tail
1715 if ((*VtfFileImage
)->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
1716 TailSize
= sizeof (EFI_FFS_FILE_TAIL
);
1721 if ((*VtfFileImage
)->Attributes
& FFS_ATTRIB_CHECKSUM
) {
1722 VtfFileChecksum
= CalculateChecksum8 ((UINT8
*) *VtfFileImage
, FileSize
- TailSize
);
1723 (*VtfFileImage
)->IntegrityCheck
.Checksum
.File
= VtfFileChecksum
;
1725 (*VtfFileImage
)->IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
1728 // If it has a file tail, update it
1730 if ((*VtfFileImage
)->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
1731 TailValue
= (EFI_FFS_FILE_TAIL
) (~((*VtfFileImage
)->IntegrityCheck
.TailReference
));
1732 *(EFI_FFS_FILE_TAIL
*) (((UINTN
) (*VtfFileImage
) + GetLength ((*VtfFileImage
)->Size
) - sizeof (EFI_FFS_FILE_TAIL
))) = TailValue
;
1734 (*VtfFileImage
)->State
= FileState
;
1739 // Already found a VTF file.
1741 Error (NULL
, 0, 0, "multiple VTF files are illegal in a single FV", NULL
);
1747 // Check if alignment is required
1749 Status
= ReadFfsAlignment ((EFI_FFS_FILE_HEADER
*) FileBuffer
, &CurrentFileAlignment
);
1750 if (EFI_ERROR (Status
)) {
1751 printf ("ERROR: Could not determine alignment of file %s.\n", FvInfo
->FvFiles
[Index
]);
1757 // Find the largest alignment of all the FFS files in the FV
1759 if (CurrentFileAlignment
> MaxFfsAlignment
) {
1760 MaxFfsAlignment
= CurrentFileAlignment
;
1763 // Add pad file if necessary
1765 Status
= AddPadFile (FvImage
, CurrentFileAlignment
);
1766 if (EFI_ERROR (Status
)) {
1767 printf ("ERROR: Could not align the file data properly.\n");
1774 if ((FvImage
->CurrentFilePointer
+ FileSize
) < FvImage
->Eof
) {
1778 memcpy (FvImage
->CurrentFilePointer
, FileBuffer
, FileSize
);
1781 // If the file is XIP, rebase
1783 CurrentFileBaseAddress
= FvInfo
->BaseAddress
+ ((UINTN
) FvImage
->CurrentFilePointer
- (UINTN
) FvImage
->FileImage
);
1785 // Status = RebaseFfsFile ((EFI_FFS_FILE_HEADER*) FvImage->CurrentFilePointer, CurrentFileBaseAddress);
1786 // if (EFI_ERROR(Status)) {
1787 // printf ("ERROR: Could not rebase the file %s.\n", FvInfo->FvFiles[Index]);
1788 // return EFI_ABORTED;
1791 // Update Symbol file
1793 Status
= AddSymFile (
1794 CurrentFileBaseAddress
,
1795 (EFI_FFS_FILE_HEADER
*) FvImage
->CurrentFilePointer
,
1797 FvInfo
->FvFiles
[Index
]
1799 assert (!EFI_ERROR (Status
));
1802 // Update the current pointer in the FV image
1804 FvImage
->CurrentFilePointer
+= FileSize
;
1806 printf ("ERROR: The firmware volume is out of space, could not add file %s.\n", FvInfo
->FvFiles
[Index
]);
1810 // Make next file start at QWord Boundry
1812 while (((UINTN
) FvImage
->CurrentFilePointer
& 0x07) != 0) {
1813 FvImage
->CurrentFilePointer
++;
1816 // Free allocated memory.
1830 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
1831 VARIABLE_STORE_HEADER
*VarStoreHeader
;
1833 // Variable block should exclude FvHeader. Since the length of
1834 // FvHeader depends on the block map, which is variable length,
1835 // we could only decide the actual variable block length here.
1837 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) FvImage
;
1838 FvImage
= FvImage
+ FvHeader
->HeaderLength
;
1840 VarStoreHeader
= (VARIABLE_STORE_HEADER
*) FvImage
;
1842 VarStoreHeader
->Signature
= VARIABLE_STORE_SIGNATURE
;
1843 VarStoreHeader
->Size
= Size
- FvHeader
->HeaderLength
;
1844 VarStoreHeader
->Format
= VARIABLE_STORE_FORMATTED
;
1845 VarStoreHeader
->State
= VARIABLE_STORE_HEALTHY
;
1846 VarStoreHeader
->Reserved
= 0;
1847 VarStoreHeader
->Reserved1
= 0;
1863 AddFTWWorkingBlock (
1869 EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER
*FTWHeader
;
1873 FTWHeader
= (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER
*) FvImage
;
1874 memcpy (&FTWHeader
->Signature
, &(FvInfo
->FvGuid
), sizeof (EFI_GUID
));
1875 FTWHeader
->WriteQueueSize
= Size
- sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER
);
1876 CalculateCrc32 (FvImage
, sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER
), &Crc32
);
1877 FTWHeader
->Crc
= Crc32
;
1878 if (FvInfo
->FvAttributes
& EFI_FVB_ERASE_POLARITY
) {
1879 FTWHeader
->WorkingBlockValid
= 0;
1880 FTWHeader
->WorkingBlockInvalid
= 1;
1882 FTWHeader
->WorkingBlockValid
= 1;
1883 FTWHeader
->WorkingBlockInvalid
= 0;
1906 Routine Description:
1908 This function generate the non FFS FV image, such as the working block
1909 and spare block. How each component of the FV is built is component
1914 FvImage The memory image of the FV to add it to. The current offset
1916 FvInfo Pointer to information about the FV.
1920 EFI_SUCCESS The function completed successfully.
1921 EFI_INVALID_PARAMETER One of the input parameters was invalid.
1922 EFI_ABORTED An error occurred.
1923 EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the add.
1928 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
1931 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) FvImage
;
1934 for (Index
= 0; FvInfo
->FvComponents
[Index
].Size
!= 0; Index
++) {
1935 if (stricmp (FvInfo
->FvComponents
[Index
].ComponentName
, EFI_NV_VARIABLE_STRING
) == 0) {
1936 AddVariableBlock (FvImage
, FvInfo
->FvComponents
[Index
].Size
, FvInfo
);
1937 } else if (stricmp (FvInfo
->FvComponents
[Index
].ComponentName
, EFI_NV_EVENT_LOG_STRING
) == 0) {
1938 AddEventLogBlock (FvImage
, FvInfo
->FvComponents
[Index
].Size
, FvInfo
);
1939 } else if (stricmp (FvInfo
->FvComponents
[Index
].ComponentName
, EFI_NV_FTW_WORKING_STRING
) == 0) {
1940 AddFTWWorkingBlock (FvImage
, FvInfo
->FvComponents
[Index
].Size
, FvInfo
);
1941 } else if (stricmp (FvInfo
->FvComponents
[Index
].ComponentName
, EFI_NV_FTW_SPARE_STRING
) == 0) {
1942 AddFTWSpareBlock (FvImage
, FvInfo
->FvComponents
[Index
].Size
, FvInfo
);
1944 printf ("Error. Unknown Non-FFS block %s \n", FvInfo
->FvComponents
[Index
].ComponentName
);
1948 FvImage
= FvImage
+ FvInfo
->FvComponents
[Index
].Size
;
1949 TotalSize
= TotalSize
+ FvInfo
->FvComponents
[Index
].Size
;
1952 // Index and TotalSize is zero mean there's no component, so this is an empty fv
1954 if ((Index
!= 0 || TotalSize
!= 0) && TotalSize
!= FvInfo
->Size
) {
1955 printf ("Error. Component size does not sum up to FV size.\n");
1964 IN MEMORY_FILE
*FvImage
,
1965 IN EFI_FFS_FILE_HEADER
*VtfFileImage
1969 Routine Description:
1971 This function places a pad file between the last file in the FV and the VTF
1972 file if the VTF file exists.
1976 FvImage Memory file for the FV memory image
1977 VtfFileImage The address of the VTF file. If this is the end of the FV
1978 image, no VTF exists and no pad file is needed.
1982 EFI_SUCCESS Completed successfully.
1983 EFI_INVALID_PARAMETER One of the input parameters was NULL.
1987 EFI_FFS_FILE_HEADER
*PadFile
;
1991 // If there is no VTF or the VTF naturally follows the previous file without a
1992 // pad file, then there's nothing to do
1994 if ((UINTN
) VtfFileImage
== (UINTN
) FvImage
->Eof
|| (void *) FvImage
->CurrentFilePointer
== (void *) VtfFileImage
) {
1998 // Pad file starts at beginning of free space
2000 PadFile
= (EFI_FFS_FILE_HEADER
*) FvImage
->CurrentFilePointer
;
2005 memset (PadFile
, 0, sizeof (EFI_FFS_FILE_HEADER
));
2006 memcpy (&PadFile
->Name
, &DefaultFvPadFileNameGuid
, sizeof (EFI_GUID
));
2007 PadFile
->Type
= EFI_FV_FILETYPE_FFS_PAD
;
2008 PadFile
->Attributes
= 0;
2011 // FileSize includes the EFI_FFS_FILE_HEADER
2013 FileSize
= (UINTN
) VtfFileImage
- (UINTN
) FvImage
->CurrentFilePointer
;
2014 PadFile
->Size
[0] = (UINT8
) (FileSize
& 0x000000FF);
2015 PadFile
->Size
[1] = (UINT8
) ((FileSize
& 0x0000FF00) >> 8);
2016 PadFile
->Size
[2] = (UINT8
) ((FileSize
& 0x00FF0000) >> 16);
2019 // Fill in checksums and state, must be zero during checksum calculation.
2021 PadFile
->IntegrityCheck
.Checksum
.Header
= 0;
2022 PadFile
->IntegrityCheck
.Checksum
.File
= 0;
2024 PadFile
->IntegrityCheck
.Checksum
.Header
= CalculateChecksum8 ((UINT8
*) PadFile
, sizeof (EFI_FFS_FILE_HEADER
));
2025 if (PadFile
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
2026 PadFile
->IntegrityCheck
.Checksum
.File
= CalculateChecksum8 ((UINT8
*) PadFile
, FileSize
);
2028 PadFile
->IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
2031 PadFile
->State
= EFI_FILE_HEADER_CONSTRUCTION
| EFI_FILE_HEADER_VALID
| EFI_FILE_DATA_VALID
;
2033 UpdateFfsFileState (
2034 (EFI_FFS_FILE_HEADER
*) PadFile
,
2035 (EFI_FIRMWARE_VOLUME_HEADER
*) FvImage
->FileImage
2038 // Update the current FV pointer
2040 FvImage
->CurrentFilePointer
= FvImage
->Eof
;
2047 IN MEMORY_FILE
*FvImage
,
2049 IN EFI_FFS_FILE_HEADER
*VtfFile
2053 Routine Description:
2055 This parses the FV looking for the PEI core and then plugs the address into
2056 the SALE_ENTRY point of the BSF/VTF for IPF and does BUGBUG TBD action to
2057 complete an IA32 Bootstrap FV.
2061 FvImage Memory file for the FV memory image
2062 FvInfo Information read from INF file.
2063 VtfFile Pointer to the VTF file in the FV image.
2067 EFI_SUCCESS Function Completed successfully.
2068 EFI_ABORTED Error encountered.
2069 EFI_INVALID_PARAMETER A required parameter was NULL.
2070 EFI_NOT_FOUND PEI Core file not found.
2074 EFI_FFS_FILE_HEADER
*PeiCoreFile
;
2075 EFI_FFS_FILE_HEADER
*SecCoreFile
;
2077 EFI_FILE_SECTION_POINTER Pe32Section
;
2081 EFI_PHYSICAL_ADDRESS PeiCorePhysicalAddress
;
2082 EFI_PHYSICAL_ADDRESS SecCorePhysicalAddress
;
2083 EFI_PHYSICAL_ADDRESS
*SecCoreEntryAddressPtr
;
2084 UINT32
*Ia32ResetAddressPtr
;
2086 UINT8
*BytePointer2
;
2087 UINT16
*WordPointer
;
2090 EFI_FFS_FILE_STATE SavedState
;
2091 EFI_FFS_FILE_TAIL TailValue
;
2094 FIT_TABLE
*FitTablePtr
;
2097 // Verify input parameters
2099 if (FvImage
== NULL
|| FvInfo
== NULL
|| VtfFile
== NULL
) {
2100 return EFI_INVALID_PARAMETER
;
2103 // Initialize FV library
2105 InitializeFvLib (FvImage
->FileImage
, (UINTN
) FvImage
->Eof
- (UINTN
) FvImage
->FileImage
);
2110 Status
= VerifyFfsFile (VtfFile
);
2111 if (EFI_ERROR (Status
)) {
2112 return EFI_INVALID_PARAMETER
;
2115 // Find the PEI Core
2117 Status
= GetFileByType (EFI_FV_FILETYPE_PEI_CORE
, 1, &PeiCoreFile
);
2118 if (EFI_ERROR (Status
) || PeiCoreFile
== NULL
) {
2119 Error (NULL
, 0, 0, "could not find the PEI core in the FV", NULL
);
2124 // PEI Core found, now find PE32 or TE section
2126 Status
= GetSectionByType (PeiCoreFile
, EFI_SECTION_PE32
, 1, &Pe32Section
);
2127 if (Status
== EFI_NOT_FOUND
) {
2128 Status
= GetSectionByType (PeiCoreFile
, EFI_SECTION_TE
, 1, &Pe32Section
);
2131 if (EFI_ERROR (Status
)) {
2132 Error (NULL
, 0, 0, "could not find PE32 or TE section in PEI core file", NULL
);
2136 Status
= GetPe32Info (
2137 (VOID
*) ((UINTN
) Pe32Section
.Pe32Section
+ sizeof (EFI_SECTION_PE32
)),
2143 if (EFI_ERROR (Status
)) {
2144 Error (NULL
, 0, 0, "could not get PE32 entry point for PEI core", NULL
);
2148 // Physical address is FV base + offset of PE32 + offset of the entry point
2150 PeiCorePhysicalAddress
= FvInfo
->BaseAddress
;
2151 PeiCorePhysicalAddress
+= (UINTN
) Pe32Section
.Pe32Section
+ sizeof (EFI_SECTION_PE32
) - (UINTN
) FvImage
->FileImage
;
2152 PeiCorePhysicalAddress
+= EntryPoint
;
2154 if (MachineType
== EFI_IMAGE_MACHINE_IA64
) {
2156 // Update PEI_CORE address
2159 // Set the uncached attribute bit in the physical address
2161 PeiCorePhysicalAddress
|= 0x8000000000000000ULL
;
2164 // Check if address is aligned on a 16 byte boundary
2166 if (PeiCorePhysicalAddress
& 0xF) {
2168 "ERROR: PEI_CORE entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n",
2169 PeiCorePhysicalAddress
2174 // First Get the FIT table address
2176 FitAddress
= (*(UINT64
*) (FvImage
->Eof
- IPF_FIT_ADDRESS_OFFSET
)) & 0xFFFFFFFF;
2178 FitTablePtr
= (FIT_TABLE
*) (FvImage
->FileImage
+ (FitAddress
- FvInfo
->BaseAddress
));
2180 Status
= UpdatePeiCoreEntryInFit (FitTablePtr
, PeiCorePhysicalAddress
);
2182 if (!EFI_ERROR (Status
)) {
2183 UpdateFitCheckSum (FitTablePtr
);
2186 // Find the Sec Core
2188 Status
= GetFileByType (EFI_FV_FILETYPE_SECURITY_CORE
, 1, &SecCoreFile
);
2189 if (EFI_ERROR (Status
) || SecCoreFile
== NULL
) {
2190 Error (NULL
, 0, 0, "could not find the Sec core in the FV", NULL
);
2194 // Sec Core found, now find PE32 section
2196 Status
= GetSectionByType (SecCoreFile
, EFI_SECTION_PE32
, 1, &Pe32Section
);
2197 if (EFI_ERROR (Status
)) {
2198 Error (NULL
, 0, 0, "could not find PE32 section in SEC core file", NULL
);
2202 Status
= GetPe32Info (
2203 (VOID
*) ((UINTN
) Pe32Section
.Pe32Section
+ sizeof (EFI_SECTION_PE32
)),
2208 if (EFI_ERROR (Status
)) {
2209 Error (NULL
, 0, 0, "could not get PE32 entry point for SEC core", NULL
);
2213 // Physical address is FV base + offset of PE32 + offset of the entry point
2215 SecCorePhysicalAddress
= FvInfo
->BaseAddress
;
2216 SecCorePhysicalAddress
+= (UINTN
) Pe32Section
.Pe32Section
+ sizeof (EFI_SECTION_PE32
) - (UINTN
) FvImage
->FileImage
;
2217 SecCorePhysicalAddress
+= EntryPoint
;
2220 // Update SEC_CORE address
2223 // Set the uncached attribute bit in the physical address
2225 SecCorePhysicalAddress
|= 0x8000000000000000ULL
;
2228 // Update the address
2230 SecCoreEntryAddressPtr
= (EFI_PHYSICAL_ADDRESS
*) ((UINTN
) FvImage
->Eof
- IPF_SALE_ENTRY_ADDRESS_OFFSET
);
2231 *SecCoreEntryAddressPtr
= SecCorePhysicalAddress
;
2234 // Check if address is aligned on a 16 byte boundary
2236 if (SecCorePhysicalAddress
& 0xF) {
2238 "ERROR: SALE_ENTRY entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n",
2239 SecCorePhysicalAddress
2243 } else if (MachineType
== EFI_IMAGE_MACHINE_IA32
) {
2245 // Get the location to update
2247 Ia32ResetAddressPtr
= (UINT32
*) ((UINTN
) FvImage
->Eof
- IA32_PEI_CORE_ENTRY_OFFSET
);
2250 // Write lower 32 bits of physical address
2252 *Ia32ResetAddressPtr
= (UINT32
) PeiCorePhysicalAddress
;
2255 // Update the BFV base address
2257 Ia32ResetAddressPtr
= (UINT32
*) ((UINTN
) FvImage
->Eof
- 4);
2258 *Ia32ResetAddressPtr
= (UINT32
) (FvInfo
->BaseAddress
);
2263 // Update the Startup AP in the FVH header block ZeroVector region.
2265 BytePointer
= (UINT8
*) ((UINTN
) FvImage
->FileImage
);
2266 BytePointer2
= (FvInfo
->Size
== 0x10000) ? m64kRecoveryStartupApDataArray
: m128kRecoveryStartupApDataArray
;
2267 for (Index
= 0; Index
< SIZEOF_STARTUP_DATA_ARRAY
; Index
++) {
2268 *BytePointer
++ = *BytePointer2
++;
2271 // Calculate the checksum
2273 WordPointer
= (UINT16
*) ((UINTN
) FvImage
->FileImage
);
2274 for (Index
= 0; Index
< SIZEOF_STARTUP_DATA_ARRAY
/ 2; Index
++) {
2275 CheckSum
= (UINT16
) (CheckSum
+ ((UINT16
) *WordPointer
));
2279 // Update the checksum field
2281 BytePointer
= (UINT8
*) ((UINTN
) FvImage
->FileImage
);
2282 BytePointer
+= (SIZEOF_STARTUP_DATA_ARRAY
- 2);
2283 WordPointer
= (UINT16
*) BytePointer
;
2284 *WordPointer
= (UINT16
) (0x10000 - (UINT32
) CheckSum
);
2286 Error (NULL
, 0, 0, "invalid machine type in PEI core", "machine type=0x%X", (UINT32
) MachineType
);
2290 // Determine if it has an FFS file tail.
2292 if (VtfFile
->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
2293 TailSize
= sizeof (EFI_FFS_FILE_TAIL
);
2298 // Now update file checksum
2300 SavedState
= VtfFile
->State
;
2301 VtfFile
->IntegrityCheck
.Checksum
.File
= 0;
2303 if (VtfFile
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
2304 VtfFile
->IntegrityCheck
.Checksum
.File
= CalculateChecksum8 (
2306 GetLength (VtfFile
->Size
) - TailSize
2309 VtfFile
->IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
2312 VtfFile
->State
= SavedState
;
2315 // Update tail if present
2317 if (VtfFile
->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
2318 TailValue
= (EFI_FFS_FILE_TAIL
) (~(VtfFile
->IntegrityCheck
.TailReference
));
2319 *(EFI_FFS_FILE_TAIL
*) (((UINTN
) (VtfFile
) + GetLength (VtfFile
->Size
) - sizeof (EFI_FFS_FILE_TAIL
))) = TailValue
;
2328 OUT UINT32
*EntryPoint
,
2329 OUT UINT32
*BaseOfCode
,
2330 OUT UINT16
*MachineType
2334 Routine Description:
2336 Retrieves the PE32 entry point offset and machine type from PE image or TeImage.
2337 See EfiImage.h for machine types. The entry point offset is from the beginning
2338 of the PE32 buffer passed in.
2342 Pe32 Beginning of the PE32.
2343 EntryPoint Offset from the beginning of the PE32 to the image entry point.
2344 BaseOfCode Base address of code.
2345 MachineType Magic number for the machine type.
2349 EFI_SUCCESS Function completed successfully.
2350 EFI_ABORTED Error encountered.
2351 EFI_INVALID_PARAMETER A required parameter was NULL.
2352 EFI_UNSUPPORTED The operation is unsupported.
2356 EFI_IMAGE_DOS_HEADER
*DosHeader
;
2357 EFI_IMAGE_NT_HEADERS
*NtHeader
;
2358 EFI_TE_IMAGE_HEADER
*TeHeader
;
2361 // Verify input parameters
2364 return EFI_INVALID_PARAMETER
;
2368 // First check whether it is one TE Image.
2370 TeHeader
= (EFI_TE_IMAGE_HEADER
*) Pe32
;
2371 if (TeHeader
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
2373 // By TeImage Header to get output
2375 *EntryPoint
= TeHeader
->AddressOfEntryPoint
+ sizeof (EFI_TE_IMAGE_HEADER
) - TeHeader
->StrippedSize
;
2376 *BaseOfCode
= TeHeader
->BaseOfCode
+ sizeof (EFI_TE_IMAGE_HEADER
) - TeHeader
->StrippedSize
;
2377 *MachineType
= TeHeader
->Machine
;
2381 // Then check whether
2382 // First is the DOS header
2384 DosHeader
= (EFI_IMAGE_DOS_HEADER
*) Pe32
;
2387 // Verify DOS header is expected
2389 if (DosHeader
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2390 printf ("ERROR: Unknown magic number in the DOS header, 0x%04X.\n", DosHeader
->e_magic
);
2391 return EFI_UNSUPPORTED
;
2394 // Immediately following is the NT header.
2396 NtHeader
= (EFI_IMAGE_NT_HEADERS
*) ((UINTN
) Pe32
+ DosHeader
->e_lfanew
);
2399 // Verify NT header is expected
2401 if (NtHeader
->Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2402 printf ("ERROR: Unrecognized image signature 0x%08X.\n", NtHeader
->Signature
);
2403 return EFI_UNSUPPORTED
;
2408 *EntryPoint
= NtHeader
->OptionalHeader
.AddressOfEntryPoint
;
2409 *BaseOfCode
= NtHeader
->OptionalHeader
.BaseOfCode
;
2410 *MachineType
= NtHeader
->FileHeader
.Machine
;
2414 // Verify machine type is supported
2416 if (*MachineType
!= EFI_IMAGE_MACHINE_IA32
&& *MachineType
!= EFI_IMAGE_MACHINE_IA64
&& *MachineType
!= EFI_IMAGE_MACHINE_X64
&& *MachineType
!= EFI_IMAGE_MACHINE_EBC
) {
2417 printf ("ERROR: Unrecognized machine type in the PE32 file.\n");
2418 return EFI_UNSUPPORTED
;
2424 // Exposed function implementations (prototypes are defined in GenFvImageLib.h)
2428 IN CHAR8
*InfFileImage
,
2429 IN UINTN InfFileSize
,
2430 OUT UINT8
**FvImage
,
2431 OUT UINTN
*FvImageSize
,
2432 OUT CHAR8
**FvFileName
,
2433 OUT UINT8
**SymImage
,
2434 OUT UINTN
*SymImageSize
,
2435 OUT CHAR8
**SymFileName
2439 Routine Description:
2441 This is the main function which will be called from application.
2445 InfFileImage Buffer containing the INF file contents.
2446 InfFileSize Size of the contents of the InfFileImage buffer.
2447 FvImage Pointer to the FV image created.
2448 FvImageSize Size of the FV image created and pointed to by FvImage.
2449 FvFileName Requested name for the FV file.
2450 SymImage Pointer to the Sym image created.
2451 SymImageSize Size of the Sym image created and pointed to by SymImage.
2452 SymFileName Requested name for the Sym file.
2456 EFI_SUCCESS Function completed successfully.
2457 EFI_OUT_OF_RESOURCES Could not allocate required resources.
2458 EFI_ABORTED Error encountered.
2459 EFI_INVALID_PARAMETER A required parameter was NULL.
2464 MEMORY_FILE InfMemoryFile
;
2465 MEMORY_FILE FvImageMemoryFile
;
2466 MEMORY_FILE SymImageMemoryFile
;
2469 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
2470 EFI_FFS_FILE_HEADER
*VtfFileImage
;
2473 // Check for invalid parameter
2475 if (InfFileImage
== NULL
|| FvImage
== NULL
|| FvImageSize
== NULL
|| FvFileName
== NULL
) {
2476 return EFI_INVALID_PARAMETER
;
2479 // Initialize file structures
2481 InfMemoryFile
.FileImage
= InfFileImage
;
2482 InfMemoryFile
.CurrentFilePointer
= InfFileImage
;
2483 InfMemoryFile
.Eof
= InfFileImage
+ InfFileSize
;
2486 // Parse the FV inf file for header information
2488 Status
= ParseFvInf (&InfMemoryFile
, &FvInfo
);
2489 if (EFI_ERROR (Status
)) {
2490 printf ("ERROR: Could not parse the input INF file.\n");
2494 // Update the file name return values
2496 strcpy (*FvFileName
, FvInfo
.FvName
);
2497 strcpy (*SymFileName
, FvInfo
.SymName
);
2500 // Calculate the FV size
2502 *FvImageSize
= FvInfo
.Size
;
2507 *FvImage
= malloc (*FvImageSize
);
2508 if (*FvImage
== NULL
) {
2509 return EFI_OUT_OF_RESOURCES
;
2512 // Allocate space for symbol file storage
2514 *SymImage
= malloc (SYMBOL_FILE_SIZE
);
2515 if (*SymImage
== NULL
) {
2516 return EFI_OUT_OF_RESOURCES
;
2519 // Initialize the FV to the erase polarity
2521 if (FvInfo
.FvAttributes
& EFI_FVB_ERASE_POLARITY
) {
2522 memset (*FvImage
, -1, *FvImageSize
);
2524 memset (*FvImage
, 0, *FvImageSize
);
2527 // Initialize FV header
2529 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) *FvImage
;
2532 // Initialize the zero vector to all zeros.
2534 memset (FvHeader
->ZeroVector
, 0, 16);
2537 // Copy the FFS GUID
2539 memcpy (&FvHeader
->FileSystemGuid
, &FvInfo
.FvGuid
, sizeof (EFI_GUID
));
2541 FvHeader
->FvLength
= *FvImageSize
;
2542 FvHeader
->Signature
= EFI_FVH_SIGNATURE
;
2543 FvHeader
->Attributes
= FvInfo
.FvAttributes
;
2544 FvHeader
->Revision
= EFI_FVH_REVISION
;
2545 FvHeader
->Reserved
[0] = 0;
2546 FvHeader
->Reserved
[1] = 0;
2547 FvHeader
->Reserved
[2] = 0;
2550 // Copy firmware block map
2552 for (Index
= 0; FvInfo
.FvBlocks
[Index
].NumBlocks
!= 0; Index
++) {
2553 FvHeader
->FvBlockMap
[Index
].NumBlocks
= FvInfo
.FvBlocks
[Index
].NumBlocks
;
2554 FvHeader
->FvBlockMap
[Index
].BlockLength
= FvInfo
.FvBlocks
[Index
].BlockLength
;
2557 // Add block map terminator
2559 FvHeader
->FvBlockMap
[Index
].NumBlocks
= 0;
2560 FvHeader
->FvBlockMap
[Index
].BlockLength
= 0;
2563 // Complete the header
2565 FvHeader
->HeaderLength
= (UINT16
) (((UINTN
) &(FvHeader
->FvBlockMap
[Index
+ 1])) - (UINTN
) *FvImage
);
2566 FvHeader
->Checksum
= 0;
2567 FvHeader
->Checksum
= CalculateChecksum16 ((UINT16
*) FvHeader
, FvHeader
->HeaderLength
/ sizeof (UINT16
));
2570 // If there is no FFS file, find and generate each components of the FV
2572 if (FvInfo
.FvFiles
[0][0] == 0) {
2573 Status
= GenNonFFSFv (*FvImage
, &FvInfo
);
2574 if (EFI_ERROR (Status
)) {
2575 printf ("ERROR: Could not generate NonFFS FV.\n");
2583 // Initialize our "file" view of the buffer
2585 FvImageMemoryFile
.FileImage
= *FvImage
;
2586 FvImageMemoryFile
.CurrentFilePointer
= *FvImage
+ FvHeader
->HeaderLength
;
2587 FvImageMemoryFile
.Eof
= *FvImage
+*FvImageSize
;
2590 // Initialize our "file" view of the symbol file.
2592 SymImageMemoryFile
.FileImage
= *SymImage
;
2593 SymImageMemoryFile
.CurrentFilePointer
= *SymImage
;
2594 SymImageMemoryFile
.Eof
= *FvImage
+ SYMBOL_FILE_SIZE
;
2597 // Initialize the FV library.
2599 InitializeFvLib (FvImageMemoryFile
.FileImage
, FvInfo
.Size
);
2602 // Files start on 8 byte alignments, so move to the next 8 byte aligned
2603 // address. For now, just assert if it isn't. Currently FV header is
2604 // always a multiple of 8 bytes.
2605 // BUGBUG: Handle this better
2607 assert ((((UINTN
) FvImageMemoryFile
.CurrentFilePointer
) % 8) == 0);
2610 // Initialize the VTF file address.
2612 VtfFileImage
= (EFI_FFS_FILE_HEADER
*) FvImageMemoryFile
.Eof
;
2617 for (Index
= 0; FvInfo
.FvFiles
[Index
][0] != 0; Index
++) {
2621 Status
= AddFile (&FvImageMemoryFile
, &FvInfo
, Index
, &VtfFileImage
, &SymImageMemoryFile
);
2624 // Exit if error detected while adding the file
2626 if (EFI_ERROR (Status
)) {
2627 printf ("ERROR: Could not add file %s.\n", FvInfo
.FvFiles
[Index
]);
2633 // If there is a VTF file, some special actions need to occur.
2635 if ((UINTN
) VtfFileImage
!= (UINTN
) FvImageMemoryFile
.Eof
) {
2637 // Pad from the end of the last file to the beginning of the VTF file.
2639 Status
= PadFvImage (&FvImageMemoryFile
, VtfFileImage
);
2640 if (EFI_ERROR (Status
)) {
2641 printf ("ERROR: Could not create the pad file between the last file and the VTF file.\n");
2646 // Update reset vector (SALE_ENTRY for IPF)
2647 // Now for IA32 and IA64 platform, the fv which has bsf file must have the
2648 // EndAddress of 0xFFFFFFFF. Thus, only this type fv needs to update the
2649 // reset vector. If the PEI Core is found, the VTF file will probably get
2650 // corrupted by updating the entry point.
2652 if ((FvInfo
.BaseAddress
+ FvInfo
.Size
) == FV_IMAGES_TOP_ADDRESS
) {
2653 Status
= UpdateResetVector (&FvImageMemoryFile
, &FvInfo
, VtfFileImage
);
2654 if (EFI_ERROR(Status
)) {
2655 printf ("ERROR: Could not update the reset vector.\n");
2662 // Determine final Sym file size
2664 *SymImageSize
= SymImageMemoryFile
.CurrentFilePointer
- SymImageMemoryFile
.FileImage
;
2667 // Update FV Alignment attribute to the largest alignment of all the FFS files in the FV
2669 if (FvHeader
->Attributes
| EFI_FVB_ALIGNMENT_CAP
) {
2670 for (Index
= 1; Index
<= 16; Index
++) {
2671 if ((1 << Index
) < MaxFfsAlignment
) {
2673 // Unset the unsupported alignment attribute.
2675 FvHeader
->Attributes
= FvHeader
->Attributes
& ~((1 << Index
) * EFI_FVB_ALIGNMENT_CAP
);
2678 // Set the supported alignment attribute.
2680 FvHeader
->Attributes
= FvHeader
->Attributes
| ((1 << Index
) * EFI_FVB_ALIGNMENT_CAP
);
2685 // Update Checksum for FvHeader
2687 FvHeader
->Checksum
= 0;
2688 FvHeader
->Checksum
= CalculateChecksum16 ((UINT16
*) FvHeader
, FvHeader
->HeaderLength
/ sizeof (UINT16
));
2695 UpdatePeiCoreEntryInFit (
2696 IN FIT_TABLE
*FitTablePtr
,
2697 IN UINT64 PeiCorePhysicalAddress
2701 Routine Description:
2703 This function is used to update the Pei Core address in FIT, this can be used by Sec core to pass control from
2708 FitTablePtr - The pointer of FIT_TABLE.
2709 PeiCorePhysicalAddress - The address of Pei Core entry.
2713 EFI_SUCCESS - The PEI_CORE FIT entry was updated successfully.
2714 EFI_NOT_FOUND - Not found the PEI_CORE FIT entry.
2718 FIT_TABLE
*TmpFitPtr
;
2720 UINTN NumFitComponents
;
2722 TmpFitPtr
= FitTablePtr
;
2723 NumFitComponents
= TmpFitPtr
->CompSize
;
2725 for (Index
= 0; Index
< NumFitComponents
; Index
++) {
2726 if ((TmpFitPtr
->CvAndType
& FIT_TYPE_MASK
) == COMP_TYPE_FIT_PEICORE
) {
2727 TmpFitPtr
->CompAddress
= PeiCorePhysicalAddress
;
2734 return EFI_NOT_FOUND
;
2739 IN FIT_TABLE
*FitTablePtr
2743 Routine Description:
2745 This function is used to update the checksum for FIT.
2750 FitTablePtr - The pointer of FIT_TABLE.
2758 if ((FitTablePtr
->CvAndType
& CHECKSUM_BIT_MASK
) >> 7) {
2759 FitTablePtr
->CheckSum
= 0;
2760 FitTablePtr
->CheckSum
= CalculateChecksum8 ((UINT8
*) FitTablePtr
, FitTablePtr
->CompSize
* 16);