diff options
author | qwang12 <qwang12@6f19259b-4bc3-4df7-8a09-765794883524> | 2007-06-28 07:00:39 +0000 |
---|---|---|
committer | qwang12 <qwang12@6f19259b-4bc3-4df7-8a09-765794883524> | 2007-06-28 07:00:39 +0000 |
commit | 3eb9473ea9a949badfe06ae61d2d3fcfa53651c7 (patch) | |
tree | e9d8c368dbb1e58794b2c00acefe4bbad270f8c4 /EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageLib.c | |
parent | 30d4a0c7ec19938196b1308006b990e0945150da (diff) | |
download | edk2-3eb9473ea9a949badfe06ae61d2d3fcfa53651c7.tar.gz edk2-3eb9473ea9a949badfe06ae61d2d3fcfa53651c7.tar.bz2 edk2-3eb9473ea9a949badfe06ae61d2d3fcfa53651c7.zip |
Add in the 1st version of ECP.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2832 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageLib.c')
-rw-r--r-- | EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageLib.c | 3054 |
1 files changed, 3054 insertions, 0 deletions
diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageLib.c b/EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageLib.c new file mode 100644 index 0000000000..3c591841ed --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageLib.c @@ -0,0 +1,3054 @@ +/*++
+
+Copyright (c) 2004 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ GenFvImageLib.c
+
+Abstract:
+
+ This file contains functions required to generate a Firmware Volume.
+
+--*/
+
+//
+// Include files
+//
+#include "GenFvImageLib.h"
+#include "GenFvImageLibInternal.h"
+#include <string.h>
+#include EFI_GUID_DEFINITION (PeiPeCoffLoader)
+#include "EfiFirmwareFileSystem.h"
+#include "EfiWorkingBlockHeader.h"
+#include "EfiVariable.h"
+#include <io.h>
+#include <assert.h>
+#include "CommonLib.h"
+#include "FvLib.h"
+#include "EfiImage.h"
+#include "crc32.h"
+#include "EfiUtilityMsgs.h"
+#include EFI_GUID_DEFINITION (FirmwareFileSystem)
+#include EFI_GUID_DEFINITION (FirmwareFileSystem2)
+
+//
+// Define the PE/COFF loader
+//
+extern EFI_PEI_PE_COFF_LOADER_PROTOCOL mPeCoffLoader;
+
+//
+// Local function prototypes
+//
+EFI_STATUS
+GetPe32Info (
+ IN UINT8 *Pe32,
+ OUT UINT32 *EntryPoint,
+ OUT UINT32 *BaseOfCode,
+ OUT UINT16 *MachineType
+ );
+
+//
+// Local function implementations.
+//
+#if (PI_SPECIFICATION_VERSION < 0x00010000)
+EFI_GUID FfsGuid = EFI_FIRMWARE_FILE_SYSTEM_GUID;
+#else
+EFI_GUID FfsGuid = EFI_FIRMWARE_FILE_SYSTEM2_GUID;
+#endif
+
+EFI_GUID DefaultFvPadFileNameGuid = { 0x78f54d4, 0xcc22, 0x4048, 0x9e, 0x94, 0x87, 0x9c, 0x21, 0x4d, 0x56, 0x2f };
+
+//
+// This data array will be located at the base of the Firmware Volume Header (FVH)
+// in the boot block. It must not exceed 14 bytes of code. The last 2 bytes
+// will be used to keep the FVH checksum consistent.
+// This code will be run in response to a starutp IPI for HT-enabled systems.
+//
+#define SIZEOF_STARTUP_DATA_ARRAY 0x10
+
+UINT8 m128kRecoveryStartupApDataArray[SIZEOF_STARTUP_DATA_ARRAY] = {
+ //
+ // EA D0 FF 00 F0 ; far jmp F000:FFD0
+ // 0, 0, 0, 0, 0, 0, 0, 0, 0, ; Reserved bytes
+ // 0, 0 ; Checksum Padding
+ //
+ 0xEA,
+ 0xD0,
+ 0xFF,
+ 0x0,
+ 0xF0,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00
+};
+
+UINT8 m64kRecoveryStartupApDataArray[SIZEOF_STARTUP_DATA_ARRAY] = {
+ //
+ // EB CE ; jmp short ($-0x30)
+ // ; (from offset 0x0 to offset 0xFFD0)
+ // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ; Reserved bytes
+ // 0, 0 ; Checksum Padding
+ //
+ 0xEB,
+ 0xCE,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00
+};
+
+EFI_STATUS
+ParseFvInf (
+ IN MEMORY_FILE *InfFile,
+ IN FV_INFO *FvInfo
+ )
+/*++
+
+Routine Description:
+
+ This function parses a FV.INF file and copies info into a FV_INFO structure.
+
+Arguments:
+
+ InfFile Memory file image.
+ FvInfo Information read from INF file.
+
+Returns:
+
+ EFI_SUCCESS INF file information successfully retrieved.
+ EFI_ABORTED INF file has an invalid format.
+ EFI_NOT_FOUND A required string was not found in the INF file.
+--*/
+{
+ CHAR8 Value[_MAX_PATH];
+ UINT64 Value64;
+ UINTN Index;
+ EFI_STATUS Status;
+
+ //
+ // Initialize FV info
+ //
+ memset (FvInfo, 0, sizeof (FV_INFO));
+
+ //
+ // Read the FV base address
+ //
+ Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_BASE_ADDRESS_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Get the base address
+ //
+ Status = AsciiStringToUint64 (Value, FALSE, &Value64);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, EFI_FV_BASE_ADDRESS_STRING, "invalid value");
+ return EFI_ABORTED;
+ }
+
+ FvInfo->BaseAddress = Value64;
+ } else {
+ Error (NULL, 0, 0, EFI_FV_BASE_ADDRESS_STRING, "could not find value");
+ return EFI_ABORTED;
+ }
+ //
+ // Read the FV Guid
+ //
+ Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_GUID_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Get the guid value
+ //
+ Status = StringToGuid (Value, &FvInfo->FvGuid);
+ if (EFI_ERROR (Status)) {
+ memcpy (&FvInfo->FvGuid, &FfsGuid, sizeof (EFI_GUID));
+ }
+ } else {
+ memcpy (&FvInfo->FvGuid, &FfsGuid, sizeof (EFI_GUID));
+ }
+ //
+ // Read the FV file name
+ //
+ Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_FILE_NAME_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // copy the file name
+ //
+ strcpy (FvInfo->FvName, Value);
+ } else {
+ Error (NULL, 0, 0, EFI_FV_FILE_NAME_STRING, "value not specified");
+ return EFI_ABORTED;
+ }
+ //
+ // Read the Sym file name
+ //
+ Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_SYM_FILE_NAME_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // copy the file name
+ //
+ strcpy (FvInfo->SymName, Value);
+ } else {
+ //
+ // Symbols not required, so init to NULL.
+ //
+ strcpy (FvInfo->SymName, "");
+ }
+ //
+ // Read the read disabled capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_DISABLED_CAP_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update the read disabled flag
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_READ_DISABLED_CAP;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_READ_DISABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_READ_DISABLED_CAP_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the read enabled capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_ENABLED_CAP_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update the read disabled flag
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_READ_ENABLED_CAP;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_READ_ENABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_READ_ENABLED_CAP_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the read status attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_STATUS_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update the read disabled flag
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_READ_STATUS;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_READ_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_READ_STATUS_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the write disabled capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_DISABLED_CAP_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update the write disabled flag
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_WRITE_DISABLED_CAP;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_WRITE_DISABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_WRITE_DISABLED_CAP_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the write enabled capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_ENABLED_CAP_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update the write disabled flag
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_WRITE_ENABLED_CAP;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_WRITE_ENABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_WRITE_ENABLED_CAP_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the write status attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_STATUS_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update the write disabled flag
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_WRITE_STATUS;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_WRITE_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_WRITE_STATUS_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the lock capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_LOCK_CAP_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update the attribute flag
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_LOCK_CAP;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_LOCK_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_LOCK_CAP_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the lock status attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_LOCK_STATUS_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update the attribute flag
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_LOCK_STATUS;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_LOCK_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_LOCK_STATUS_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the sticky write attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_STICKY_WRITE_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update the attribute flag
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_STICKY_WRITE;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_STICKY_WRITE_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_STICKY_WRITE_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the memory mapped attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_MEMORY_MAPPED_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update the attribute flag
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_MEMORY_MAPPED;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_MEMORY_MAPPED_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_MEMORY_MAPPED_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the erase polarity attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ERASE_POLARITY_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update the attribute flag
+ //
+ if (strcmp (Value, ONE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_ERASE_POLARITY;
+ } else if (strcmp (Value, ZERO_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_ERASE_POLARITY_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_ERASE_POLARITY_STRING, "value not specified");
+ return Status;
+ }
+
+#if (PI_SPECIFICATION_VERSION >= 0x00010000)
+ //
+ // Read the read lock capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_LOCK_CAP_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB2_READ_LOCK_CAP;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_READ_LOCK_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_READ_LOCK_CAP_STRING, "value not specified");
+ return Status;
+ }
+
+ //
+ // Read the read lock status attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_LOCK_STATUS_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB2_READ_LOCK_STATUS;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_READ_LOCK_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_READ_LOCK_STATUS_STRING, "value not specified");
+ return Status;
+ }
+
+ //
+ // Read the write lock capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_LOCK_CAP_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB2_WRITE_LOCK_CAP;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_WRITE_LOCK_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_WRITE_LOCK_CAP_STRING, "value not specified");
+ return Status;
+ }
+
+ //
+ // Read the write lock status attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_LOCK_STATUS_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB2_WRITE_LOCK_STATUS;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_WRITE_LOCK_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_WRITE_LOCK_STATUS_STRING, "value not specified");
+ return Status;
+ }
+#endif
+
+#if (PI_SPECIFICATION_VERSION < 0x00010000)
+ //
+ // Read the alignment capabilities attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_CAP_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_CAP;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_CAP_STRING, "value not specified");
+ return Status;
+ }
+
+ //
+ // Read the word alignment capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_2_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_2;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2_STRING, "value not specified");
+ return Status;
+ }
+
+
+ //
+ // Read the dword alignment capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_4_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_4;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the word alignment capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_8_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_8;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the qword alignment capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_16_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_16;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the 32 byte alignment capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_32_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_32;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the 64 byte alignment capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_64_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_64;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the 128 byte alignment capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_128_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_128;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_128_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_128_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the 256 byte alignment capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_256_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_256;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_256_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_256_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the 512 byte alignment capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_512_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_512;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_512_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_512_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the 1K byte alignment capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_1K_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_1K;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_1K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_1K_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the 2K byte alignment capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_2K_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_2K;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2K_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the 4K byte alignment capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_4K_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_4K;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4K_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the 8K byte alignment capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_8K_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_8K;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8K_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the 16K byte alignment capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_16K_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_16K;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16K_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the 32K byte alignment capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_32K_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_32K;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32K_STRING, "value not specified");
+ return Status;
+ }
+ //
+ // Read the 64K byte alignment capability attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_64K_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, TRUE_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_64K;
+ } else if (strcmp (Value, FALSE_STRING) != 0) {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64K_STRING, "value not specified");
+ return Status;
+ }
+
+ if (!(FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_CAP) &&
+ (
+ (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_2) ||
+ (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_4) ||
+ (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_8) ||
+ (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_16) ||
+ (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_32) ||
+ (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_64) ||
+ (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_128) ||
+ (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_256) ||
+ (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_512) ||
+ (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_1K) ||
+ (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_2K) ||
+ (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_4K) ||
+ (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_8K) ||
+ (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_16K) ||
+ (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_32K) ||
+ (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_64K)
+ )
+ ){
+ Error (
+ NULL,
+ 0,
+ 0,
+ "illegal combination of alignment attributes",
+ "if %s is not %s, no individual alignments can be %s",
+ EFI_FVB_ALIGNMENT_CAP_STRING,
+ TRUE_STRING,
+ TRUE_STRING
+ );
+ return EFI_ABORTED;
+ }
+#else
+ //
+ // Read the PI1.0 FVB2 Alignment Capabilities Attribute
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB2_ALIGNMENT_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update attribute
+ //
+ if (strcmp (Value, EFI_FVB2_ALIGNMENT_1_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_1;
+ } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_2_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_2;
+ } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_4_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_4;
+ } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_8_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_8;
+ } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_16_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_16;
+ } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_32_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_32;
+ } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_64_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_64;
+ } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_128_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_128;
+ } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_256_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_256;
+ } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_512_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_512;
+ } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_1K_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_1K;
+ } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_2K_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_2K;
+ } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_4K_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_4K;
+ } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_8K_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_8K;
+ } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_16K_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_16K;
+ } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_32K_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_32K;
+ } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_64K_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_64K;
+ } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_128K_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_128K;
+ } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_256K_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_256K;
+ } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_512K_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB2_ALIGNMNET_512K;
+ } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_1M_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_1M;
+ } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_2M_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_2M;
+ } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_4M_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_4M;
+ } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_8M_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_8M;
+ } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_16M_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_16M;
+ } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_32M_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_32M;
+ } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_64M_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_64M;
+ } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_128M_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_128M;
+ } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_256M_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_256M;
+ } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_512M_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_512M;
+ } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_1G_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_1G;
+ } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_2G_STRING) == 0) {
+ FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_2G;
+ } else {
+ Error (NULL, 0, 0, EFI_FVB2_ALIGNMENT_STRING, "value not correct!");
+ return EFI_ABORTED;
+ }
+ } else {
+ Error (NULL, 0, 0, EFI_FVB2_ALIGNMENT_STRING, "value not specified");
+ return Status;
+ }
+
+#endif
+ //
+ // Read block maps
+ //
+ for (Index = 0; Index < MAX_NUMBER_OF_FV_BLOCKS; Index++) {
+ //
+ // Read the number of blocks
+ //
+ Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_NUM_BLOCKS_STRING, Index, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update the number of blocks
+ //
+ Status = AsciiStringToUint64 (Value, FALSE, &Value64);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, Value, "invalid value for %s", EFI_NUM_BLOCKS_STRING);
+ return EFI_ABORTED;
+ }
+
+ FvInfo->FvBlocks[Index].NumBlocks = (UINT32) Value64;
+ } else {
+ //
+ // If there is no number of blocks, but there is a size, then we have a mismatched pair
+ // and should return an error.
+ //
+ Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_BLOCK_SIZE_STRING, Index, Value);
+ if (!EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING);
+ return EFI_ABORTED;
+ } else {
+ //
+ // We are done
+ //
+ break;
+ }
+ }
+ //
+ // Read the size of blocks
+ //
+ Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_BLOCK_SIZE_STRING, Index, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Update the number of blocks
+ //
+ Status = AsciiStringToUint64 (Value, FALSE, &Value64);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, Value, "invalid value specified for %s", EFI_BLOCK_SIZE_STRING);
+ return EFI_ABORTED;
+ }
+
+ FvInfo->FvBlocks[Index].BlockLength = (UINT32) Value64;
+ } else {
+ //
+ // There is a number of blocks, but there is no size, so we have a mismatched pair
+ // and should return an error.
+ //
+ Error (NULL, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING);
+ return EFI_ABORTED;
+ }
+ }
+ //
+ // Read files
+ //
+ for (Index = 0; Index < MAX_NUMBER_OF_FILES_IN_FV; Index++) {
+ //
+ // Read the number of blocks
+ //
+ Status = FindToken (InfFile, FILES_SECTION_STRING, EFI_FILE_NAME_STRING, Index, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Add the file
+ //
+ strcpy (FvInfo->FvFiles[Index], Value);
+ } else {
+ break;
+ }
+ }
+
+ if (FindSection (InfFile, COMPONENT_SECTION_STRING)) {
+ Index = 0;
+ //
+ // Read component FV_VARIABLE
+ //
+ Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_VARIABLE_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Add the component
+ //
+ strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_VARIABLE_STRING);
+ Status = AsciiStringToUint64 (Value, FALSE, &Value64);
+ if (EFI_ERROR (Status)) {
+ printf ("ERROR: %s is not a valid integer.\n", EFI_NV_VARIABLE_STRING);
+ return EFI_ABORTED;
+ }
+
+ FvInfo->FvComponents[Index].Size = (UINTN) Value64;
+ } else {
+ printf ("WARNING: Could not read %s.\n", EFI_NV_VARIABLE_STRING);
+ }
+
+ Index++;
+ //
+ // Read component FV_EVENT_LOG
+ //
+ Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_EVENT_LOG_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Add the component
+ //
+ strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_EVENT_LOG_STRING);
+ Status = AsciiStringToUint64 (Value, FALSE, &Value64);
+ if (EFI_ERROR (Status)) {
+ printf ("ERROR: %s is not a valid integer.\n", EFI_NV_EVENT_LOG_STRING);
+ return EFI_ABORTED;
+ }
+
+ FvInfo->FvComponents[Index].Size = (UINTN) Value64;
+ } else {
+ printf ("WARNING: Could not read %s.\n", EFI_NV_EVENT_LOG_STRING);
+ }
+
+ Index++;
+ //
+ // Read component FV_FTW_WORKING
+ //
+ Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_FTW_WORKING_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Add the component
+ //
+ strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_WORKING_STRING);
+ Status = AsciiStringToUint64 (Value, FALSE, &Value64);
+ if (EFI_ERROR (Status)) {
+ printf ("ERROR: %s is not a valid integer.\n", EFI_NV_FTW_WORKING_STRING);
+ return EFI_ABORTED;
+ }
+
+ FvInfo->FvComponents[Index].Size = (UINTN) Value64;
+ } else {
+ printf ("WARNING: Could not read %s.\n", EFI_NV_FTW_WORKING_STRING);
+ }
+
+ Index++;
+ //
+ // Read component FV_FTW_SPARE
+ //
+ Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_FTW_SPARE_STRING, 0, Value);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Add the component
+ //
+ strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_SPARE_STRING);
+ Status = AsciiStringToUint64 (Value, FALSE, &Value64);
+ if (EFI_ERROR (Status)) {
+ printf ("ERROR: %s is not a valid integer.\n", EFI_NV_FTW_SPARE_STRING);
+ return EFI_ABORTED;
+ }
+
+ FvInfo->FvComponents[Index].Size = (UINTN) Value64;
+ } else {
+ printf ("WARNING: Could not read %s.\n", EFI_NV_FTW_SPARE_STRING);
+ }
+ }
+ //
+ // Compute size for easy access later
+ //
+ FvInfo->Size = 0;
+ for (Index = 0; FvInfo->FvBlocks[Index].NumBlocks; Index++) {
+ FvInfo->Size += FvInfo->FvBlocks[Index].NumBlocks * FvInfo->FvBlocks[Index].BlockLength;
+ }
+
+ return EFI_SUCCESS;
+}
+
+VOID
+UpdateFfsFileState (
+ IN EFI_FFS_FILE_HEADER *FfsFile,
+ IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader
+ )
+/*++
+
+Routine Description:
+
+ This function changes the FFS file attributes based on the erase polarity
+ of the FV.
+
+Arguments:
+
+ FfsFile File header.
+ FvHeader FV header.
+
+Returns:
+
+ None
+
+--*/
+{
+ if (FvHeader->Attributes & EFI_FVB_ERASE_POLARITY) {
+ FfsFile->State = (UINT8)~(FfsFile->State);
+ }
+}
+
+EFI_STATUS
+ReadFfsAlignment (
+ IN EFI_FFS_FILE_HEADER *FfsFile,
+ IN OUT UINT32 *Alignment
+ )
+/*++
+
+Routine Description:
+
+ This function determines the alignment of the FFS input file from the file
+ attributes.
+
+Arguments:
+
+ FfsFile FFS file to parse
+ Alignment The minimum required alignment of the FFS file, in bytes
+
+Returns:
+
+ EFI_SUCCESS The function completed successfully.
+ EFI_INVALID_PARAMETER One of the input parameters was invalid.
+ EFI_ABORTED An error occurred.
+
+--*/
+{
+ //
+ // Verify input parameters.
+ //
+ if (FfsFile == NULL || Alignment == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ switch ((FfsFile->Attributes >> 3) & 0x07) {
+
+ case 0:
+ //
+ // 1 byte alignment
+ //
+ *Alignment = (1 << 0);
+ break;
+
+ case 1:
+ //
+ // 16 byte alignment
+ //
+ *Alignment = (1 << 4);
+ break;
+
+ case 2:
+ //
+ // 128 byte alignment
+ //
+ *Alignment = (1 << 7);
+ break;
+
+ case 3:
+ //
+ // 512 byte alignment
+ //
+ *Alignment = (1 << 9);
+ break;
+
+ case 4:
+ //
+ // 1K byte alignment
+ //
+ *Alignment = (1 << 10);
+ break;
+
+ case 5:
+ //
+ // 4K byte alignment
+ //
+ *Alignment = (1 << 12);
+ break;
+
+ case 6:
+ //
+ // 32K byte alignment
+ //
+ *Alignment = (1 << 15);
+ break;
+
+ case 7:
+ //
+ // 64K byte alignment
+ //
+ *Alignment = (1 << 16);
+ break;
+
+ default:
+ Error (NULL, 0, 0, "nvalid file attribute calculated, this is most likely a utility error", NULL);
+ return EFI_ABORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AddPadFile (
+ IN OUT MEMORY_FILE *FvImage,
+ IN UINT32 DataAlignment
+ )
+/*++
+
+Routine Description:
+
+ This function adds a pad file to the FV image if it required to align the
+ data of the next file.
+
+Arguments:
+
+ FvImage The memory image of the FV to add it to. The current offset
+ must be valid.
+ DataAlignment The data alignment of the next FFS file.
+
+Returns:
+
+ EFI_SUCCESS The function completed successfully.
+ EFI_INVALID_PARAMETER One of the input parameters was invalid.
+ EFI_OUT_OF_RESOURCES Insufficient resources exist in the FV to complete
+ the pad file add.
+
+--*/
+{
+ EFI_FFS_FILE_HEADER *PadFile;
+ UUID PadFileGuid;
+ UINTN PadFileSize;
+
+ //
+ // Verify input parameters.
+ //
+ if (FvImage == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Basic assumption is we start from an 8 byte aligned address
+ // and our file header is a multiple of 8 bytes
+ //
+ assert ((UINTN) FvImage->CurrentFilePointer % 8 == 0);
+ assert (sizeof (EFI_FFS_FILE_HEADER) % 8 == 0);
+
+ //
+ // Check if a pad file is necessary
+ //
+ if (((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + sizeof (EFI_FFS_FILE_HEADER)) % DataAlignment == 0) {
+ return EFI_SUCCESS;
+ }
+ //
+ // Write pad file header
+ //
+ PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer;
+
+ //
+ // Verify that we have enough space for the file header
+ //
+ if ((UINTN) (PadFile + sizeof (EFI_FFS_FILE_HEADER)) >= (UINTN) FvImage->Eof) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ UuidCreate (&PadFileGuid);
+ memset (PadFile, 0, sizeof (EFI_FFS_FILE_HEADER));
+ memcpy (&PadFile->Name, &PadFileGuid, sizeof (EFI_GUID));
+ PadFile->Type = EFI_FV_FILETYPE_FFS_PAD;
+ PadFile->Attributes = 0;
+
+ //
+ // Calculate the pad file size
+ //
+ //
+ // This is the earliest possible valid offset (current plus pad file header
+ // plus the next file header)
+ //
+ PadFileSize = (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + (sizeof (EFI_FFS_FILE_HEADER) * 2);
+
+ //
+ // Add whatever it takes to get to the next aligned address
+ //
+ while ((PadFileSize % DataAlignment) != 0) {
+ PadFileSize++;
+ }
+ //
+ // Subtract the next file header size
+ //
+ PadFileSize -= sizeof (EFI_FFS_FILE_HEADER);
+
+ //
+ // Subtract the starting offset to get size
+ //
+ PadFileSize -= (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage;
+
+ //
+ // Write pad file size (calculated size minus next file header size)
+ //
+ PadFile->Size[0] = (UINT8) (PadFileSize & 0xFF);
+ PadFile->Size[1] = (UINT8) ((PadFileSize >> 8) & 0xFF);
+ PadFile->Size[2] = (UINT8) ((PadFileSize >> 16) & 0xFF);
+
+ //
+ // Fill in checksums and state, they must be 0 for checksumming.
+ //
+ PadFile->IntegrityCheck.Checksum.Header = 0;
+ PadFile->IntegrityCheck.Checksum.File = 0;
+ PadFile->State = 0;
+ PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER));
+ if (PadFile->Attributes & FFS_ATTRIB_CHECKSUM) {
+ PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) PadFile, PadFileSize);
+ } else {
+ PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
+ }
+
+ PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
+ UpdateFfsFileState (
+ (EFI_FFS_FILE_HEADER *) PadFile,
+ (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage
+ );
+
+ //
+ // Verify that we have enough space (including the padding
+ //
+ if ((UINTN) (PadFile + sizeof (EFI_FFS_FILE_HEADER)) >= (UINTN) FvImage->Eof) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Update the current FV pointer
+ //
+ FvImage->CurrentFilePointer += PadFileSize;
+
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+IsVtfFile (
+ IN EFI_FFS_FILE_HEADER *FileBuffer
+ )
+/*++
+
+Routine Description:
+
+ This function checks the header to validate if it is a VTF file
+
+Arguments:
+
+ FileBuffer Buffer in which content of a file has been read.
+
+Returns:
+
+ TRUE If this is a VTF file
+ FALSE If this is not a VTF file
+
+--*/
+{
+ EFI_GUID VtfGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;
+ if (!memcmp (&FileBuffer->Name, &VtfGuid, sizeof (EFI_GUID))) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+EFI_STATUS
+FfsRebaseImageRead (
+ IN VOID *FileHandle,
+ IN UINTN FileOffset,
+ IN OUT UINT32 *ReadSize,
+ OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
+
+Arguments:
+
+ FileHandle - The handle to the PE/COFF file
+
+ FileOffset - The offset, in bytes, into the file to read
+
+ ReadSize - The number of bytes to read from the file starting at FileOffset
+
+ Buffer - A pointer to the buffer to read the data into.
+
+Returns:
+
+ EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
+
+--*/
+{
+ CHAR8 *Destination8;
+ CHAR8 *Source8;
+ UINT32 Length;
+
+ Destination8 = Buffer;
+ Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);
+ Length = *ReadSize;
+ while (Length--) {
+ *(Destination8++) = *(Source8++);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+RebaseFfsFile (
+ IN OUT EFI_FFS_FILE_HEADER *FfsFile,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress
+ )
+/*++
+
+Routine Description:
+
+ This function determines if a file is XIP and should be rebased. It will
+ rebase any PE32 sections found in the file using the base address.
+
+Arguments:
+
+ FfsFile A pointer to Ffs file image.
+ BaseAddress The base address to use for rebasing the file image.
+
+Returns:
+
+ EFI_SUCCESS The image was properly rebased.
+ EFI_INVALID_PARAMETER An input parameter is invalid.
+ EFI_ABORTED An error occurred while rebasing the input file image.
+ EFI_OUT_OF_RESOURCES Could not allocate a required resource.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
+ UINTN MemoryImagePointer;
+ UINTN MemoryImagePointerAligned;
+
+ EFI_PHYSICAL_ADDRESS ImageAddress;
+ UINT64 ImageSize;
+ EFI_PHYSICAL_ADDRESS EntryPoint;
+
+ UINT32 Pe32FileSize;
+ UINT32 NewPe32BaseAddress;
+
+ UINTN Index;
+ EFI_FILE_SECTION_POINTER CurrentPe32Section;
+ UINT8 FileGuidString[80];
+
+ //
+ // Verify input parameters
+ //
+ if (FfsFile == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Convert the GUID to a string so we can at least report which file
+ // if we find an error.
+ //
+ PrintGuidToBuffer (&FfsFile->Name, FileGuidString, sizeof (FileGuidString), TRUE);
+
+ //
+ // Do some nominal checks on the file, then check for XIP.
+ //
+ Status = VerifyFfsFile (FfsFile);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "invalid FFS file", FileGuidString);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE &&
+ FfsFile->Type != EFI_FV_FILETYPE_PEI_CORE &&
+ FfsFile->Type != EFI_FV_FILETYPE_PEIM
+ ) {
+ //
+ // File is not XIP, so don't rebase
+ //
+ return EFI_SUCCESS;
+ }
+ //
+ // Rebase each PE32 section
+ //
+ for (Index = 1;; Index++) {
+ Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, Index, &CurrentPe32Section);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ //
+ // Calculate the PE32 base address, the FFS file base plus the offset of the PE32 section
+ //
+ NewPe32BaseAddress = ((UINT32) BaseAddress) + ((UINTN) CurrentPe32Section.Pe32Section - (UINTN) FfsFile);
+
+ //
+ // Initialize context
+ //
+ memset (&ImageContext, 0, sizeof (ImageContext));
+ ImageContext.Handle = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION));
+ ImageContext.ImageRead = (EFI_PEI_PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;
+
+ Status = mPeCoffLoader.GetImageInfo (&mPeCoffLoader, &ImageContext);
+
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "GetImageInfo() failed", FileGuidString);
+ return Status;
+ }
+ //
+ // Allocate a buffer for the image to be loaded into.
+ //
+ Pe32FileSize = GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size);
+ MemoryImagePointer = (UINTN) (malloc (Pe32FileSize + 0x1000));
+ MemoryImagePointerAligned = (MemoryImagePointer + 0x0FFF) & (-1 << 12);
+ if (MemoryImagePointerAligned == 0) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // bugbug
+ //
+ ImageContext.ImageAddress = MemoryImagePointerAligned;
+ Status = mPeCoffLoader.LoadImage (&mPeCoffLoader, &ImageContext);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "LoadImage() failure", FileGuidString);
+ free ((VOID *) MemoryImagePointer);
+ return Status;
+ }
+
+ Status = mPeCoffLoader.RelocateImage (&mPeCoffLoader, &ImageContext);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "RelocateImage() failure", FileGuidString);
+ free ((VOID *) MemoryImagePointer);
+ return Status;
+ }
+
+ ImageAddress = ImageContext.ImageAddress;
+ ImageSize = ImageContext.ImageSize;
+ EntryPoint = ImageContext.EntryPoint;
+
+ if (ImageSize > Pe32FileSize) {
+ Error (
+ NULL,
+ 0,
+ 0,
+ "rebased PE32 is larger than original PE32 image",
+ "0x%X > 0x%X on file %s",
+ ImageSize,
+ Pe32FileSize,
+ FileGuidString
+ );
+ free ((VOID *) MemoryImagePointer);
+ return EFI_ABORTED;
+ }
+
+ memcpy (CurrentPe32Section.Pe32Section, (VOID *) MemoryImagePointerAligned, Pe32FileSize);
+
+ free ((VOID *) MemoryImagePointer);
+ }
+ //
+ // the above for loop will always exit with EFI_NOT_FOUND if it completes
+ // normally. If Index == 1 at exit, then no PE32 sections were found. If it
+ // exits with any other error code, then something broke...
+ //
+ if (Status != EFI_NOT_FOUND) {
+ Error (NULL, 0, 0, "failed to parse PE32 section", FileGuidString);
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AddSymFile (
+ IN UINT64 BaseAddress,
+ IN EFI_FFS_FILE_HEADER *FfsFile,
+ IN OUT MEMORY_FILE *SymImage,
+ IN CHAR8 *SourceFileName
+ )
+/*++
+
+Routine Description:
+
+ This function adds the SYM tokens in the source file to the destination file.
+ The SYM tokens are updated to reflect the base address.
+
+Arguments:
+
+ BaseAddress The base address for the new SYM tokens.
+ FfsFile Pointer to the beginning of the FFS file in question.
+ SymImage The memory file to update with symbol information.
+ SourceFileName The source file.
+
+Returns:
+
+ EFI_SUCCESS The function completed successfully.
+ EFI_INVALID_PARAMETER One of the input parameters was invalid.
+ EFI_ABORTED An error occurred.
+
+--*/
+{
+ FILE *SourceFile;
+
+ CHAR8 Buffer[_MAX_PATH];
+ CHAR8 Type[_MAX_PATH];
+ CHAR8 Address[_MAX_PATH];
+ CHAR8 Section[_MAX_PATH];
+ CHAR8 Token[_MAX_PATH];
+ CHAR8 SymFileName[_MAX_PATH];
+ CHAR8 CodeModuleName[_MAX_PATH];
+ CHAR8 *Ptr;
+
+ UINT64 TokenAddress;
+
+ EFI_STATUS Status;
+ EFI_FILE_SECTION_POINTER Pe32Section;
+ UINT32 EntryPoint;
+ UINT32 BaseOfCode;
+ UINT16 MachineType;
+
+ //
+ // Verify input parameters.
+ //
+ if (BaseAddress == 0 || FfsFile == NULL || SymImage == NULL || SourceFileName == NULL) {
+ Error (NULL, 0, 0, "invalid parameter passed to AddSymFile()", NULL);
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Check if we want to add this file
+ //
+ //
+ // Get the file name
+ //
+ strcpy (Buffer, SourceFileName);
+
+ //
+ // Copy the file name for the path of the sym file and truncate the name portion.
+ //
+ strcpy (SymFileName, Buffer);
+ Ptr = strrchr (SymFileName, '\\');
+ assert (Ptr);
+ Ptr[0] = 0;
+
+ //
+ // Find the file extension and make it lower case
+ //
+ Ptr = strrchr (SymFileName, '.');
+ if (Ptr != NULL) {
+ _strlwr (Ptr);
+ }
+ //
+ // Check if it is PEI file
+ //
+ if (strstr (Buffer, ".pei") != NULL) {
+ //
+ // Find the human readable portion
+ //
+ if (!strtok (Buffer, "-") ||
+ !strtok (NULL, "-") ||
+ !strtok (NULL, "-") ||
+ !strtok (NULL, "-") ||
+ !strtok (NULL, "-") ||
+ !strcpy (Buffer, strtok (NULL, "."))
+ ) {
+ Error (NULL, 0, 0, "failed to find human readable portion of the file name in AddSymFile()", NULL);
+ return EFI_ABORTED;
+ }
+ //
+ // Save code module name
+ //
+ strcpy (CodeModuleName, Buffer);
+
+ //
+ // Add the symbol file name and extension to the file path.
+ //
+ strcat (Buffer, ".sym");
+ strcat (SymFileName, "\\");
+ strcat (SymFileName, Buffer);
+ } else {
+ //
+ // Only handle PEIM files.
+ //
+ return EFI_SUCCESS;
+ }
+ //
+ // Find PE32 section
+ //
+ Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, 1, &Pe32Section);
+
+ //
+ // BUGBUG: Assume if no PE32 section it is PIC and hardcode base address
+ //
+ if (Status == EFI_NOT_FOUND) {
+ Status = GetSectionByType (FfsFile, EFI_SECTION_TE, 1, &Pe32Section);
+ }
+
+ if (Status == EFI_SUCCESS) {
+ Status = GetPe32Info (
+ (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),
+ &EntryPoint,
+ &BaseOfCode,
+ &MachineType
+ );
+ } else {
+ if (Status == EFI_NOT_FOUND) {
+ BaseOfCode = 0x60;
+ Status = EFI_SUCCESS;
+ } else {
+ Error (NULL, 0, 0, "could not parse a PE32 section from the PEI file", NULL);
+ return Status;
+ }
+ }
+
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "GetPe32Info() could not get PE32 entry point for PEI file", NULL);
+ return Status;
+ }
+
+ //
+ // Open the source file
+ //
+ SourceFile = fopen (SymFileName, "r");
+ if (SourceFile == NULL) {
+ //
+ // SYM files are not required.
+ //
+ return EFI_SUCCESS;
+ }
+ //
+ // Read the first line
+ //
+ if (fgets (Buffer, _MAX_PATH, SourceFile) == NULL) {
+ Buffer[0] = 0;
+ }
+ //
+ // Make sure it matches the expected sym format
+ //
+ if (strcmp (Buffer, "TEXTSYM format | V1.0\n")) {
+ fclose (SourceFile);
+ Error (NULL, 0, 0, "AddSymFile() found unexpected sym format in input file", NULL);
+ return EFI_ABORTED;
+ }
+ //
+ // Read in the file
+ //
+ while (feof (SourceFile) == 0) {
+ //
+ // Read a line
+ //
+ if (fscanf (
+ SourceFile,
+ "%s | %s | %s | %s\n",
+ Type,
+ Address,
+ Section,
+ Token
+ ) == 4) {
+ //
+ // If the token starts with "??" ignore it
+ //
+ if (Token[0] == '?' && Token[1] == '?') {
+ continue;
+ }
+ //
+ // Get the token address
+ //
+ AsciiStringToUint64 (Address, TRUE, &TokenAddress);
+
+ //
+ // Add the base address
+ //
+ TokenAddress += BaseAddress;
+
+ //
+ // If PE32 or TE section then find the start of code. For PIC it is hardcoded.
+ //
+ if (Pe32Section.Pe32Section) {
+ //
+ // Add the offset of the PE32 section
+ //
+ TokenAddress += (UINTN) Pe32Section.Pe32Section - (UINTN) FfsFile;
+
+ //
+ // Add the size of the PE32 section header
+ //
+ TokenAddress += sizeof (EFI_PE32_SECTION);
+ } else {
+ //
+ // BUGBUG: Don't know why this is 0x28 bytes.
+ //
+ TokenAddress += 0x28;
+ }
+ //
+ // Add the beginning of the code
+ //
+ TokenAddress += BaseOfCode;
+
+ sprintf (
+ Buffer,
+ "%s | %016I64X | %s | _%s%s\n",
+ Type,
+ TokenAddress,
+ Section,
+ CodeModuleName,
+ Token
+ );
+ memcpy (SymImage->CurrentFilePointer, Buffer, strlen (Buffer) + 1);
+ SymImage->CurrentFilePointer = (UINT8 *) (((UINTN) SymImage->CurrentFilePointer) + strlen (Buffer) + 1);
+ }
+ }
+
+ fclose (SourceFile);
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AddFile (
+ IN OUT MEMORY_FILE *FvImage,
+ IN FV_INFO *FvInfo,
+ IN UINTN Index,
+ IN OUT EFI_FFS_FILE_HEADER **VtfFileImage,
+ IN OUT MEMORY_FILE *SymImage
+ )
+/*++
+
+Routine Description:
+
+ This function adds a file to the FV image. The file will pad to the
+ appropriate alignment if required.
+
+Arguments:
+
+ FvImage The memory image of the FV to add it to. The current offset
+ must be valid.
+ FvInfo Pointer to information about the FV.
+ Index The file in the FvInfo file list to add.
+ VtfFileImage A pointer to the VTF file within the FvImage. If this is equal
+ to the end of the FvImage then no VTF previously found.
+ SymImage The memory image of the Sym file to update if symbols are present.
+ The current offset must be valid.
+
+Returns:
+
+ EFI_SUCCESS The function completed successfully.
+ EFI_INVALID_PARAMETER One of the input parameters was invalid.
+ EFI_ABORTED An error occurred.
+ EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the add.
+
+--*/
+{
+ FILE *NewFile;
+ UINTN FileSize;
+ UINT8 *FileBuffer;
+ UINTN NumBytesRead;
+ UINT32 CurrentFileAlignment;
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS CurrentFileBaseAddress;
+ UINT8 VtfHeaderChecksum;
+ UINT8 VtfFileChecksum;
+ UINT8 FileState;
+ UINT32 TailSize;
+#if (PI_SPECIFICATION_VERSION < 0x00010000)
+ EFI_FFS_FILE_TAIL TailValue;
+#endif
+ //
+ // Verify input parameters.
+ //
+ if (FvImage == NULL || FvInfo == NULL || FvInfo->FvFiles[Index][0] == 0 || VtfFileImage == NULL || SymImage == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Read the file to add
+ //
+ NewFile = fopen (FvInfo->FvFiles[Index], "rb");
+
+ if (NewFile == NULL) {
+ Error (NULL, 0, 0, FvInfo->FvFiles[Index], "failed to open file for reading");
+ return EFI_ABORTED;
+ }
+ //
+ // Get the file size
+ //
+ FileSize = _filelength (_fileno (NewFile));
+
+ //
+ // Read the file into a buffer
+ //
+ FileBuffer = malloc (FileSize);
+ if (FileBuffer == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NumBytesRead = fread (FileBuffer, sizeof (UINT8), FileSize, NewFile);
+
+ //
+ // Done with the file, from this point on we will just use the buffer read.
+ //
+ fclose (NewFile);
+
+ //
+ // Verify read successful
+ //
+ if (NumBytesRead != sizeof (UINT8) * FileSize) {
+ free (FileBuffer);
+ Error (NULL, 0, 0, FvInfo->FvFiles[Index], "failed to read input file contents");
+ return EFI_ABORTED;
+ }
+ //
+ // Verify space exists to add the file
+ //
+ if (FileSize > (UINTN) ((UINTN) *VtfFileImage - (UINTN) FvImage->CurrentFilePointer)) {
+ Error (NULL, 0, 0, FvInfo->FvFiles[Index], "insufficient space remains to add the file");
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Update the file state based on polarity of the FV.
+ //
+ UpdateFfsFileState (
+ (EFI_FFS_FILE_HEADER *) FileBuffer,
+ (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage
+ );
+
+ //
+ // If we have a VTF file, add it at the top.
+ //
+ if (IsVtfFile ((EFI_FFS_FILE_HEADER *) FileBuffer)) {
+ if ((UINTN) *VtfFileImage == (UINTN) FvImage->Eof) {
+ //
+ // No previous VTF, add this one.
+ //
+ *VtfFileImage = (EFI_FFS_FILE_HEADER *) (UINTN) ((UINTN) FvImage->FileImage + FvInfo->Size - FileSize);
+ //
+ // Sanity check. The file MUST align appropriately
+ //
+ if ((((UINTN) *VtfFileImage) & 0x07) != 0) {
+ Error (NULL, 0, 0, "VTF file does not align on 8-byte boundary", NULL);
+ }
+ //
+ // copy VTF File Header
+ //
+ memcpy (*VtfFileImage, FileBuffer, sizeof (EFI_FFS_FILE_HEADER));
+
+ //
+ // Copy VTF body
+ //
+ memcpy (
+ (UINT8 *) *VtfFileImage + sizeof (EFI_FFS_FILE_HEADER),
+ FileBuffer + sizeof (EFI_FFS_FILE_HEADER),
+ FileSize - sizeof (EFI_FFS_FILE_HEADER)
+ );
+
+ //
+ // re-calculate the VTF File Header
+ //
+ FileState = (*VtfFileImage)->State;
+ (*VtfFileImage)->State = 0;
+ *(UINT32 *) ((*VtfFileImage)->Size) = FileSize;
+ (*VtfFileImage)->IntegrityCheck.Checksum.Header = 0;
+ (*VtfFileImage)->IntegrityCheck.Checksum.File = 0;
+
+ VtfHeaderChecksum = CalculateChecksum8 ((UINT8 *) *VtfFileImage, sizeof (EFI_FFS_FILE_HEADER));
+ (*VtfFileImage)->IntegrityCheck.Checksum.Header = VtfHeaderChecksum;
+ //
+ // Determine if it has a tail
+ //
+ if ((*VtfFileImage)->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
+ TailSize = sizeof (EFI_FFS_FILE_TAIL);
+ } else {
+ TailSize = 0;
+ }
+
+ if ((*VtfFileImage)->Attributes & FFS_ATTRIB_CHECKSUM) {
+ VtfFileChecksum = CalculateChecksum8 ((UINT8 *) *VtfFileImage, FileSize - TailSize);
+ (*VtfFileImage)->IntegrityCheck.Checksum.File = VtfFileChecksum;
+ } else {
+ (*VtfFileImage)->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
+ }
+ #if (PI_SPECIFICATION_VERSION < 0x00010000)
+ //
+ // If it has a file tail, update it
+ //
+ if ((*VtfFileImage)->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
+ TailValue = (EFI_FFS_FILE_TAIL) (~((*VtfFileImage)->IntegrityCheck.TailReference));
+ *(EFI_FFS_FILE_TAIL *) (((UINTN) (*VtfFileImage) + GetLength ((*VtfFileImage)->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;
+ }
+ #endif
+ (*VtfFileImage)->State = FileState;
+ free (FileBuffer);
+ return EFI_SUCCESS;
+ } else {
+ //
+ // Already found a VTF file.
+ //
+ Error (NULL, 0, 0, "multiple VTF files are illegal in a single FV", NULL);
+ free (FileBuffer);
+ return EFI_ABORTED;
+ }
+ }
+ //
+ // Check if alignment is required
+ //
+ Status = ReadFfsAlignment ((EFI_FFS_FILE_HEADER *) FileBuffer, &CurrentFileAlignment);
+ if (EFI_ERROR (Status)) {
+ printf ("ERROR: Could not determine alignment of file %s.\n", FvInfo->FvFiles[Index]);
+ free (FileBuffer);
+ return EFI_ABORTED;
+ }
+ //
+ // Add pad file if necessary
+ //
+ Status = AddPadFile (FvImage, CurrentFileAlignment);
+ if (EFI_ERROR (Status)) {
+ printf ("ERROR: Could not align the file data properly.\n");
+ free (FileBuffer);
+ return EFI_ABORTED;
+ }
+ //
+ // Add file
+ //
+ if ((FvImage->CurrentFilePointer + FileSize) < FvImage->Eof) {
+ //
+ // Copy the file
+ //
+ memcpy (FvImage->CurrentFilePointer, FileBuffer, FileSize);
+
+ //
+ // If the file is XIP, rebase
+ //
+ CurrentFileBaseAddress = FvInfo->BaseAddress + ((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage);
+ //
+ // Status = RebaseFfsFile ((EFI_FFS_FILE_HEADER*) FvImage->CurrentFilePointer, CurrentFileBaseAddress);
+ // if (EFI_ERROR(Status)) {
+ // printf ("ERROR: Could not rebase the file %s.\n", FvInfo->FvFiles[Index]);
+ // return EFI_ABORTED;
+ // }
+ //
+ // Update Symbol file
+ //
+ Status = AddSymFile (
+ CurrentFileBaseAddress,
+ (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer,
+ SymImage,
+ FvInfo->FvFiles[Index]
+ );
+ assert (!EFI_ERROR (Status));
+
+ //
+ // Update the current pointer in the FV image
+ //
+ FvImage->CurrentFilePointer += FileSize;
+ } else {
+ printf ("ERROR: The firmware volume is out of space, could not add file %s.\n", FvInfo->FvFiles[Index]);
+ return EFI_ABORTED;
+ }
+ //
+ // Make next file start at QWord Boundry
+ //
+ while (((UINTN) FvImage->CurrentFilePointer & 0x07) != 0) {
+ FvImage->CurrentFilePointer++;
+ }
+ //
+ // Free allocated memory.
+ //
+ free (FileBuffer);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AddVariableBlock (
+ IN UINT8 *FvImage,
+ IN UINTN Size,
+ IN FV_INFO *FvInfo
+ )
+{
+ EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
+ VARIABLE_STORE_HEADER *VarStoreHeader;
+ //
+ // Variable block should exclude FvHeader. Since the length of
+ // FvHeader depends on the block map, which is variable length,
+ // we could only decide the actual variable block length here.
+ //
+ FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage;
+ FvImage = FvImage + FvHeader->HeaderLength;
+
+ VarStoreHeader = (VARIABLE_STORE_HEADER *) FvImage;
+
+ VarStoreHeader->Signature = VARIABLE_STORE_SIGNATURE;
+ VarStoreHeader->Size = Size - FvHeader->HeaderLength;
+ VarStoreHeader->Format = VARIABLE_STORE_FORMATTED;
+ VarStoreHeader->State = VARIABLE_STORE_HEALTHY;
+ VarStoreHeader->Reserved = 0;
+ VarStoreHeader->Reserved1 = 0;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AddEventLogBlock (
+ IN UINT8 *FvImage,
+ IN UINTN Size,
+ IN FV_INFO *FvInfo
+ )
+{
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AddFTWWorkingBlock (
+ IN UINT8 *FvImage,
+ IN UINTN Size,
+ IN FV_INFO *FvInfo
+ )
+{
+ EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *FTWHeader;
+ UINT32 Crc32;
+
+ Crc32 = 0;
+ FTWHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) FvImage;
+ memcpy (&FTWHeader->Signature, &(FvInfo->FvGuid), sizeof (EFI_GUID));
+ FTWHeader->WriteQueueSize = Size - sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER);
+ CalculateCrc32 (FvImage, sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER), &Crc32);
+ FTWHeader->Crc = Crc32;
+ if (FvInfo->FvAttributes & EFI_FVB_ERASE_POLARITY) {
+ FTWHeader->WorkingBlockValid = 0;
+ FTWHeader->WorkingBlockInvalid = 1;
+ } else {
+ FTWHeader->WorkingBlockValid = 1;
+ FTWHeader->WorkingBlockInvalid = 0;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AddFTWSpareBlock (
+ IN UINT8 *FvImage,
+ IN UINTN Size,
+ IN FV_INFO *FvInfo
+ )
+{
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GenNonFFSFv (
+ IN UINT8 *FvImage,
+ IN FV_INFO *FvInfo
+ )
+/*++
+
+Routine Description:
+
+ This function generate the non FFS FV image, such as the working block
+ and spare block. How each component of the FV is built is component
+ specific.
+
+Arguments:
+
+ FvImage The memory image of the FV to add it to. The current offset
+ must be valid.
+ FvInfo Pointer to information about the FV.
+
+Returns:
+
+ EFI_SUCCESS The function completed successfully.
+ EFI_INVALID_PARAMETER One of the input parameters was invalid.
+ EFI_ABORTED An error occurred.
+ EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the add.
+
+--*/
+{
+ UINTN Index;
+ EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
+ UINT64 TotalSize;
+
+ FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage;
+ TotalSize = 0;
+
+ for (Index = 0; FvInfo->FvComponents[Index].Size != 0; Index++) {
+ if (_stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_VARIABLE_STRING) == 0) {
+ AddVariableBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);
+ } else if (_stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_EVENT_LOG_STRING) == 0) {
+ AddEventLogBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);
+ } else if (_stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_WORKING_STRING) == 0) {
+ AddFTWWorkingBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);
+ } else if (_stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_SPARE_STRING) == 0) {
+ AddFTWSpareBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);
+ } else {
+ printf ("Error. Unknown Non-FFS block %s \n", FvInfo->FvComponents[Index].ComponentName);
+ return EFI_ABORTED;
+ }
+
+ FvImage = FvImage + FvInfo->FvComponents[Index].Size;
+ TotalSize = TotalSize + FvInfo->FvComponents[Index].Size;
+ }
+ //
+ // Index and TotalSize is zero mean there's no component, so this is an empty fv
+ //
+ if ((Index != 0 || TotalSize != 0) && TotalSize != FvInfo->Size) {
+ printf ("Error. Component size does not sum up to FV size.\n");
+ return EFI_ABORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PadFvImage (
+ IN MEMORY_FILE *FvImage,
+ IN EFI_FFS_FILE_HEADER *VtfFileImage
+ )
+/*++
+
+Routine Description:
+
+ This function places a pad file between the last file in the FV and the VTF
+ file if the VTF file exists.
+
+Arguments:
+
+ FvImage Memory file for the FV memory image
+ VtfFileImage The address of the VTF file. If this is the end of the FV
+ image, no VTF exists and no pad file is needed.
+
+Returns:
+
+ EFI_SUCCESS Completed successfully.
+ EFI_INVALID_PARAMETER One of the input parameters was NULL.
+
+--*/
+{
+ EFI_FFS_FILE_HEADER *PadFile;
+ UINTN FileSize;
+
+ //
+ // If there is no VTF or the VTF naturally follows the previous file without a
+ // pad file, then there's nothing to do
+ //
+ if ((UINTN) VtfFileImage == (UINTN) FvImage->Eof || (void *) FvImage->CurrentFilePointer == (void *) VtfFileImage) {
+ return EFI_SUCCESS;
+ }
+ //
+ // Pad file starts at beginning of free space
+ //
+ PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer;
+
+ //
+ // write header
+ //
+ memset (PadFile, 0, sizeof (EFI_FFS_FILE_HEADER));
+ memcpy (&PadFile->Name, &DefaultFvPadFileNameGuid, sizeof (EFI_GUID));
+ PadFile->Type = EFI_FV_FILETYPE_FFS_PAD;
+ PadFile->Attributes = 0;
+
+ //
+ // FileSize includes the EFI_FFS_FILE_HEADER
+ //
+ FileSize = (UINTN) VtfFileImage - (UINTN) FvImage->CurrentFilePointer;
+ PadFile->Size[0] = (UINT8) (FileSize & 0x000000FF);
+ PadFile->Size[1] = (UINT8) ((FileSize & 0x0000FF00) >> 8);
+ PadFile->Size[2] = (UINT8) ((FileSize & 0x00FF0000) >> 16);
+
+ //
+ // Fill in checksums and state, must be zero during checksum calculation.
+ //
+ PadFile->IntegrityCheck.Checksum.Header = 0;
+ PadFile->IntegrityCheck.Checksum.File = 0;
+ PadFile->State = 0;
+ PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER));
+ if (PadFile->Attributes & FFS_ATTRIB_CHECKSUM) {
+ PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) PadFile, FileSize);
+ } else {
+ PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
+ }
+
+ PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
+
+ UpdateFfsFileState (
+ (EFI_FFS_FILE_HEADER *) PadFile,
+ (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage
+ );
+ //
+ // Update the current FV pointer
+ //
+ FvImage->CurrentFilePointer = FvImage->Eof;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+UpdateResetVector (
+ IN MEMORY_FILE *FvImage,
+ IN FV_INFO *FvInfo,
+ IN EFI_FFS_FILE_HEADER *VtfFile
+ )
+/*++
+
+Routine Description:
+
+ This parses the FV looking for the PEI core and then plugs the address into
+ the SALE_ENTRY point of the BSF/VTF for IPF and does BUGBUG TBD action to
+ complete an IA32 Bootstrap FV.
+
+Arguments:
+
+ FvImage Memory file for the FV memory image
+ FvInfo Information read from INF file.
+ VtfFile Pointer to the VTF file in the FV image.
+
+Returns:
+
+ EFI_SUCCESS Function Completed successfully.
+ EFI_ABORTED Error encountered.
+ EFI_INVALID_PARAMETER A required parameter was NULL.
+ EFI_NOT_FOUND PEI Core file not found.
+
+--*/
+{
+ EFI_FFS_FILE_HEADER *PeiCoreFile;
+ EFI_FFS_FILE_HEADER *SecCoreFile;
+ EFI_STATUS Status;
+ EFI_FILE_SECTION_POINTER Pe32Section;
+ UINT32 EntryPoint;
+ UINT32 BaseOfCode;
+ UINT16 MachineType;
+ EFI_PHYSICAL_ADDRESS PeiCorePhysicalAddress;
+ EFI_PHYSICAL_ADDRESS SecCorePhysicalAddress;
+ EFI_PHYSICAL_ADDRESS *SecCoreEntryAddressPtr;
+ UINT32 *Ia32ResetAddressPtr;
+ UINT8 *BytePointer;
+ UINT8 *BytePointer2;
+ UINT16 *WordPointer;
+ UINT16 CheckSum;
+ UINTN Index;
+ EFI_FFS_FILE_STATE SavedState;
+ UINT32 TailSize;
+ UINT64 FitAddress;
+ FIT_TABLE *FitTablePtr;
+#if (PI_SPECIFICATION_VERSION < 0x00010000)
+ EFI_FFS_FILE_TAIL TailValue;
+#endif
+ //
+ // Verify input parameters
+ //
+ if (FvImage == NULL || FvInfo == NULL || VtfFile == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Initialize FV library
+ //
+ InitializeFvLib (FvImage->FileImage, (UINTN) FvImage->Eof - (UINTN) FvImage->FileImage);
+
+ //
+ // Verify VTF file
+ //
+ Status = VerifyFfsFile (VtfFile);
+ if (EFI_ERROR (Status)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Find the PEI Core
+ //
+ Status = GetFileByType (EFI_FV_FILETYPE_PEI_CORE, 1, &PeiCoreFile);
+ if (EFI_ERROR (Status) || PeiCoreFile == NULL) {
+ Error (NULL, 0, 0, "could not find the PEI core in the FV", NULL);
+ return EFI_ABORTED;
+ }
+ //
+ // PEI Core found, now find PE32 or TE section
+ //
+ Status = GetSectionByType (PeiCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);
+ if (Status == EFI_NOT_FOUND) {
+ Status = GetSectionByType (PeiCoreFile, EFI_SECTION_TE, 1, &Pe32Section);
+ }
+
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "could not find PE32 or TE section in PEI core file", NULL);
+ return EFI_ABORTED;
+ }
+
+ Status = GetPe32Info (
+ (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),
+ &EntryPoint,
+ &BaseOfCode,
+ &MachineType
+ );
+
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "could not get PE32 entry point for PEI core", NULL);
+ return EFI_ABORTED;
+ }
+ //
+ // Physical address is FV base + offset of PE32 + offset of the entry point
+ //
+ PeiCorePhysicalAddress = FvInfo->BaseAddress;
+ PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;
+ PeiCorePhysicalAddress += EntryPoint;
+
+ if (MachineType == EFI_IMAGE_MACHINE_IA64) {
+ //
+ // Update PEI_CORE address
+ //
+ //
+ // Set the uncached attribute bit in the physical address
+ //
+ PeiCorePhysicalAddress |= 0x8000000000000000;
+
+ //
+ // Check if address is aligned on a 16 byte boundary
+ //
+ if (PeiCorePhysicalAddress & 0xF) {
+ printf (
+ "ERROR: PEI_CORE entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n",
+ PeiCorePhysicalAddress
+ );
+ return EFI_ABORTED;
+ }
+ //
+ // First Get the FIT table address
+ //
+ FitAddress = (*(UINT64 *) (FvImage->Eof - IPF_FIT_ADDRESS_OFFSET)) & 0xFFFFFFFF;
+
+ FitTablePtr = (FIT_TABLE *) (FvImage->FileImage + (FitAddress - FvInfo->BaseAddress));
+
+ Status = UpdatePeiCoreEntryInFit (FitTablePtr, PeiCorePhysicalAddress);
+
+ if (!EFI_ERROR (Status)) {
+ UpdateFitCheckSum (FitTablePtr);
+ }
+ //
+ // Find the Sec Core
+ //
+ Status = GetFileByType (EFI_FV_FILETYPE_SECURITY_CORE, 1, &SecCoreFile);
+ if (EFI_ERROR (Status) || SecCoreFile == NULL) {
+ Error (NULL, 0, 0, "could not find the Sec core in the FV", NULL);
+ return EFI_ABORTED;
+ }
+ //
+ // Sec Core found, now find PE32 section
+ //
+ Status = GetSectionByType (SecCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "could not find PE32 section in SEC core file", NULL);
+ return EFI_ABORTED;
+ }
+
+ Status = GetPe32Info (
+ (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),
+ &EntryPoint,
+ &BaseOfCode,
+ &MachineType
+ );
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "could not get PE32 entry point for SEC core", NULL);
+ return EFI_ABORTED;
+ }
+ //
+ // Physical address is FV base + offset of PE32 + offset of the entry point
+ //
+ SecCorePhysicalAddress = FvInfo->BaseAddress;
+ SecCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;
+ SecCorePhysicalAddress += EntryPoint;
+
+ //
+ // Update SEC_CORE address
+ //
+ //
+ // Set the uncached attribute bit in the physical address
+ //
+ SecCorePhysicalAddress |= 0x8000000000000000;
+
+ //
+ // Update the address
+ //
+ SecCoreEntryAddressPtr = (EFI_PHYSICAL_ADDRESS *) ((UINTN) FvImage->Eof - IPF_SALE_ENTRY_ADDRESS_OFFSET);
+ *SecCoreEntryAddressPtr = SecCorePhysicalAddress;
+
+ //
+ // Check if address is aligned on a 16 byte boundary
+ //
+ if (SecCorePhysicalAddress & 0xF) {
+ printf (
+ "ERROR: SALE_ENTRY entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n",
+ SecCorePhysicalAddress
+ );
+ return EFI_ABORTED;
+ }
+ } else if ((MachineType == EFI_IMAGE_MACHINE_IA32) ||
+ (MachineType == EFI_IMAGE_MACHINE_X64)) {
+ //
+ // Get the location to update
+ //
+ Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - IA32_PEI_CORE_ENTRY_OFFSET);
+
+ //
+ // Write lower 32 bits of physical address
+ //
+ *Ia32ResetAddressPtr = (UINT32) PeiCorePhysicalAddress;
+
+ //
+ // Update the BFV base address
+ //
+ Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - 4);
+ *Ia32ResetAddressPtr = (UINT32) (FvInfo->BaseAddress);
+
+ CheckSum = 0x0000;
+
+ //
+ // Update the Startup AP in the FVH header block ZeroVector region.
+ //
+ BytePointer = (UINT8 *) ((UINTN) FvImage->FileImage);
+ BytePointer2 = (FvInfo->Size == 0x10000) ? m64kRecoveryStartupApDataArray : m128kRecoveryStartupApDataArray;
+ for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY; Index++) {
+ *BytePointer++ = *BytePointer2++;
+ }
+ //
+ // Calculate the checksum
+ //
+ WordPointer = (UINT16 *) ((UINTN) FvImage->FileImage);
+ for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY / 2; Index++) {
+ CheckSum = (UINT16) (CheckSum + ((UINT16) *WordPointer));
+ WordPointer++;
+ }
+ //
+ // Update the checksum field
+ //
+ BytePointer = (UINT8 *) ((UINTN) FvImage->FileImage);
+ BytePointer += (SIZEOF_STARTUP_DATA_ARRAY - 2);
+ WordPointer = (UINT16 *) BytePointer;
+ *WordPointer = (UINT16) (0x10000 - (UINT32) CheckSum);
+ } else {
+ Error (NULL, 0, 0, "invalid machine type in PEI core", "machine type=0x%X", (UINT32) MachineType);
+ return EFI_ABORTED;
+ }
+ //
+ // Determine if it has an FFS file tail.
+ //
+ if (VtfFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
+ TailSize = sizeof (EFI_FFS_FILE_TAIL);
+ } else {
+ TailSize = 0;
+ }
+ //
+ // Now update file checksum
+ //
+ SavedState = VtfFile->State;
+ VtfFile->IntegrityCheck.Checksum.File = 0;
+ VtfFile->State = 0;
+ if (VtfFile->Attributes & FFS_ATTRIB_CHECKSUM) {
+ VtfFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (
+ (UINT8 *) VtfFile,
+ GetLength (VtfFile->Size) - TailSize
+ );
+ } else {
+ VtfFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
+ }
+
+ VtfFile->State = SavedState;
+
+#if (PI_SPECIFICATION_VERSION < 0x00010000)
+ //
+ // Update tail if present
+ //
+ if (VtfFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
+ TailValue = (EFI_FFS_FILE_TAIL) (~(VtfFile->IntegrityCheck.TailReference));
+ *(EFI_FFS_FILE_TAIL *) (((UINTN) (VtfFile) + GetLength (VtfFile->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;
+ }
+#endif
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetPe32Info (
+ IN UINT8 *Pe32,
+ OUT UINT32 *EntryPoint,
+ OUT UINT32 *BaseOfCode,
+ OUT UINT16 *MachineType
+ )
+/*++
+
+Routine Description:
+
+ Retrieves the PE32 entry point offset and machine type from PE image or TE image.
+ See EfiImage.h for machine types. The entry point offset is from the beginning
+ of the PE32 buffer passed in.
+
+Arguments:
+
+ Pe32 Beginning of the PE32.
+ EntryPoint Offset from the beginning of the PE32 to the image entry point.
+ BaseOfCode Base address of code.
+ MachineType Magic number for the machine type.
+
+Returns:
+
+ EFI_SUCCESS Function completed successfully.
+ EFI_ABORTED Error encountered.
+ EFI_INVALID_PARAMETER A required parameter was NULL.
+ EFI_UNSUPPORTED The operation is unsupported.
+
+--*/
+{
+ EFI_IMAGE_DOS_HEADER *DosHeader;
+ EFI_IMAGE_NT_HEADERS *NtHeader;
+ EFI_TE_IMAGE_HEADER *TeHeader;
+
+ //
+ // Verify input parameters
+ //
+ if (Pe32 == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // First check whether it is one TE Image.
+ //
+ TeHeader = (EFI_TE_IMAGE_HEADER *) Pe32;
+ if (TeHeader->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
+ //
+ // By TeImage Header to get output
+ //
+ *EntryPoint = TeHeader->AddressOfEntryPoint + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader->StrippedSize;
+ *BaseOfCode = TeHeader->BaseOfCode + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader->StrippedSize;
+ *MachineType = TeHeader->Machine;
+ } else {
+ //
+ // Then check whether
+ // is the DOS header
+ //
+ DosHeader = (EFI_IMAGE_DOS_HEADER *) Pe32;
+
+ //
+ // Verify DOS header is expected
+ //
+ if (DosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
+ printf ("ERROR: Unknown magic number in the DOS header, 0x%04X.\n", DosHeader->e_magic);
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Immediately following is the NT header.
+ //
+ NtHeader = (EFI_IMAGE_NT_HEADERS *) ((UINTN) Pe32 + DosHeader->e_lfanew);
+
+ //
+ // Verify NT header is expected
+ //
+ if (NtHeader->Signature != EFI_IMAGE_NT_SIGNATURE) {
+ printf ("ERROR: Unrecognized image signature 0x%08X.\n", NtHeader->Signature);
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Get output
+ //
+ *EntryPoint = NtHeader->OptionalHeader.AddressOfEntryPoint;
+ *BaseOfCode = NtHeader->OptionalHeader.BaseOfCode;
+ *MachineType = NtHeader->FileHeader.Machine;
+ }
+
+ //
+ // Verify machine type is supported
+ //
+ if (*MachineType != EFI_IMAGE_MACHINE_IA32 &&
+ *MachineType != EFI_IMAGE_MACHINE_IA64 &&
+ *MachineType != EFI_IMAGE_MACHINE_X64) {
+ printf ("ERROR: Unrecognized machine type in the PE32 file.\n");
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+//
+// Exposed function implementations (prototypes are defined in GenFvImageLib.h)
+//
+EFI_STATUS
+GenerateFvImage (
+ IN CHAR8 *InfFileImage,
+ IN UINTN InfFileSize,
+ OUT UINT8 **FvImage,
+ OUT UINTN *FvImageSize,
+ OUT CHAR8 **FvFileName,
+ OUT UINT8 **SymImage,
+ OUT UINTN *SymImageSize,
+ OUT CHAR8 **SymFileName
+ )
+/*++
+
+Routine Description:
+
+ This is the main function which will be called from application.
+
+Arguments:
+
+ InfFileImage Buffer containing the INF file contents.
+ InfFileSize Size of the contents of the InfFileImage buffer.
+ FvImage Pointer to the FV image created.
+ FvImageSize Size of the FV image created and pointed to by FvImage.
+ FvFileName Requested name for the FV file.
+ SymImage Pointer to the Sym image created.
+ SymImageSize Size of the Sym image created and pointed to by SymImage.
+ SymFileName Requested name for the Sym file.
+
+Returns:
+
+ EFI_SUCCESS Function completed successfully.
+ EFI_OUT_OF_RESOURCES Could not allocate required resources.
+ EFI_ABORTED Error encountered.
+ EFI_INVALID_PARAMETER A required parameter was NULL.
+
+--*/
+{
+ EFI_STATUS Status;
+ MEMORY_FILE InfMemoryFile;
+ MEMORY_FILE FvImageMemoryFile;
+ MEMORY_FILE SymImageMemoryFile;
+ FV_INFO FvInfo;
+ UINTN Index;
+ EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
+ EFI_FFS_FILE_HEADER *VtfFileImage;
+
+ //
+ // Check for invalid parameter
+ //
+ if (InfFileImage == NULL || FvImage == NULL || FvImageSize == NULL || FvFileName == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Initialize file structures
+ //
+ InfMemoryFile.FileImage = InfFileImage;
+ InfMemoryFile.CurrentFilePointer = InfFileImage;
+ InfMemoryFile.Eof = InfFileImage + InfFileSize;
+
+ //
+ // Parse the FV inf file for header information
+ //
+ Status = ParseFvInf (&InfMemoryFile, &FvInfo);
+ if (EFI_ERROR (Status)) {
+ printf ("ERROR: Could not parse the input INF file.\n");
+ return EFI_ABORTED;
+ }
+ //
+ // Update the file name return values
+ //
+ strcpy (*FvFileName, FvInfo.FvName);
+ strcpy (*SymFileName, FvInfo.SymName);
+
+ //
+ // Calculate the FV size
+ //
+ *FvImageSize = FvInfo.Size;
+
+ //
+ // Allocate the FV
+ //
+ *FvImage = malloc (*FvImageSize);
+ if (*FvImage == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Allocate space for symbol file storage
+ //
+ *SymImage = malloc (SYMBOL_FILE_SIZE);
+ if (*SymImage == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Initialize the FV to the erase polarity
+ //
+ if (FvInfo.FvAttributes & EFI_FVB_ERASE_POLARITY) {
+ memset (*FvImage, -1, *FvImageSize);
+ } else {
+ memset (*FvImage, 0, *FvImageSize);
+ }
+ //
+ // Initialize FV header
+ //
+ FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) *FvImage;
+
+ //
+ // Initialize the zero vector to all zeros.
+ //
+ memset (FvHeader->ZeroVector, 0, 16);
+
+ //
+ // Copy the FFS GUID
+ //
+ memcpy (&FvHeader->FileSystemGuid, &FvInfo.FvGuid, sizeof (EFI_GUID));
+
+ FvHeader->FvLength = *FvImageSize;
+ FvHeader->Signature = EFI_FVH_SIGNATURE;
+ FvHeader->Attributes = FvInfo.FvAttributes;
+#if (PI_SPECIFICATION_VERSION < 0x00010000)
+ FvHeader->Revision = EFI_FVH_REVISION;
+ FvHeader->Reserved[0] = 0;
+ FvHeader->Reserved[1] = 0;
+ FvHeader->Reserved[2] = 0;
+#else
+ FvHeader->Revision = EFI_FVH_PI_REVISION;
+ FvHeader->ExtHeaderOffset = 0;
+ FvHeader->Reserved[0] = 0;
+#endif
+ //
+ // Copy firmware block map
+ //
+ for (Index = 0; FvInfo.FvBlocks[Index].NumBlocks != 0; Index++) {
+ FvHeader->FvBlockMap[Index].NumBlocks = FvInfo.FvBlocks[Index].NumBlocks;
+ FvHeader->FvBlockMap[Index].BlockLength = FvInfo.FvBlocks[Index].BlockLength;
+ }
+ //
+ // Add block map terminator
+ //
+ FvHeader->FvBlockMap[Index].NumBlocks = 0;
+ FvHeader->FvBlockMap[Index].BlockLength = 0;
+
+ //
+ // Complete the header
+ //
+ FvHeader->HeaderLength = (UINT16) (((UINTN) &(FvHeader->FvBlockMap[Index + 1])) - (UINTN) *FvImage);
+ FvHeader->Checksum = 0;
+ FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));
+
+ //
+ // If there is no FFS file, find and generate each components of the FV
+ //
+ if (FvInfo.FvFiles[0][0] == 0) {
+ Status = GenNonFFSFv (*FvImage, &FvInfo);
+ if (EFI_ERROR (Status)) {
+ printf ("ERROR: Could not generate NonFFS FV.\n");
+ free (*FvImage);
+ return EFI_ABORTED;
+ }
+
+ return EFI_SUCCESS;
+ }
+ //
+ // Initialize our "file" view of the buffer
+ //
+ FvImageMemoryFile.FileImage = *FvImage;
+ FvImageMemoryFile.CurrentFilePointer = *FvImage + FvHeader->HeaderLength;
+ FvImageMemoryFile.Eof = *FvImage +*FvImageSize;
+
+ //
+ // Initialize our "file" view of the symbol file.
+ //
+ SymImageMemoryFile.FileImage = *SymImage;
+ SymImageMemoryFile.CurrentFilePointer = *SymImage;
+ SymImageMemoryFile.Eof = *FvImage + SYMBOL_FILE_SIZE;
+
+ //
+ // Initialize the FV library.
+ //
+ InitializeFvLib (FvImageMemoryFile.FileImage, FvInfo.Size);
+
+ //
+ // Files start on 8 byte alignments, so move to the next 8 byte aligned
+ // address. For now, just assert if it isn't. Currently FV header is
+ // always a multiple of 8 bytes.
+ // BUGBUG: Handle this better
+ //
+ assert ((((UINTN) FvImageMemoryFile.CurrentFilePointer) % 8) == 0);
+
+ //
+ // Initialize the VTF file address.
+ //
+ VtfFileImage = (EFI_FFS_FILE_HEADER *) FvImageMemoryFile.Eof;
+
+ //
+ // Add files to FV
+ //
+ for (Index = 0; FvInfo.FvFiles[Index][0] != 0; Index++) {
+ //
+ // Add the file
+ //
+ Status = AddFile (&FvImageMemoryFile, &FvInfo, Index, &VtfFileImage, &SymImageMemoryFile);
+
+ //
+ // Exit if error detected while adding the file
+ //
+ if (EFI_ERROR (Status)) {
+ printf ("ERROR: Could not add file %s.\n", FvInfo.FvFiles[Index]);
+ free (*FvImage);
+ return EFI_ABORTED;
+ }
+ }
+ //
+ // If there is a VTF file, some special actions need to occur.
+ //
+ if ((UINTN) VtfFileImage != (UINTN) FvImageMemoryFile.Eof) {
+ //
+ // Pad from the end of the last file to the beginning of the VTF file.
+ //
+ Status = PadFvImage (&FvImageMemoryFile, VtfFileImage);
+ if (EFI_ERROR (Status)) {
+ printf ("ERROR: Could not create the pad file between the last file and the VTF file.\n");
+ free (*FvImage);
+ return EFI_ABORTED;
+ }
+ //
+ // Update reset vector (SALE_ENTRY for IPF)
+ // Now for IA32 and IA64 platform, the fv which has bsf file must have the
+ // EndAddress of 0xFFFFFFFF. Thus, only this type fv needs to update the
+ // reset vector. If the PEI Core is found, the VTF file will probably get
+ // corrupted by updating the entry point.
+ //
+ if ((FvInfo.BaseAddress + FvInfo.Size) == FV_IMAGES_TOP_ADDRESS) {
+ Status = UpdateResetVector (&FvImageMemoryFile, &FvInfo, VtfFileImage);
+ if (EFI_ERROR(Status)) {
+ printf ("ERROR: Could not update the reset vector.\n");
+ free (*FvImage);
+ return EFI_ABORTED;
+ }
+ }
+ }
+ //
+ // Determine final Sym file size
+ //
+ *SymImageSize = SymImageMemoryFile.CurrentFilePointer - SymImageMemoryFile.FileImage;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+UpdatePeiCoreEntryInFit (
+ IN FIT_TABLE *FitTablePtr,
+ IN UINT64 PeiCorePhysicalAddress
+ )
+/*++
+
+Routine Description:
+
+ This function is used to update the Pei Core address in FIT, this can be used by Sec core to pass control from
+ Sec to Pei Core
+
+Arguments:
+
+ FitTablePtr - The pointer of FIT_TABLE.
+ PeiCorePhysicalAddress - The address of Pei Core entry.
+
+Returns:
+
+ EFI_SUCCESS - The PEI_CORE FIT entry was updated successfully.
+ EFI_NOT_FOUND - Not found the PEI_CORE FIT entry.
+
+--*/
+{
+ FIT_TABLE *TmpFitPtr;
+ UINTN Index;
+ UINTN NumFitComponents;
+
+ TmpFitPtr = FitTablePtr;
+ NumFitComponents = TmpFitPtr->CompSize;
+
+ for (Index = 0; Index < NumFitComponents; Index++) {
+ if ((TmpFitPtr->CvAndType & FIT_TYPE_MASK) == COMP_TYPE_FIT_PEICORE) {
+ TmpFitPtr->CompAddress = PeiCorePhysicalAddress;
+ return EFI_SUCCESS;
+ }
+
+ TmpFitPtr++;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+VOID
+UpdateFitCheckSum (
+ IN FIT_TABLE *FitTablePtr
+ )
+/*++
+
+Routine Description:
+
+ This function is used to update the checksum for FIT.
+
+
+Arguments:
+
+ FitTablePtr - The pointer of FIT_TABLE.
+
+Returns:
+
+ None.
+
+--*/
+{
+ if ((FitTablePtr->CvAndType & CHECKSUM_BIT_MASK) >> 7) {
+ FitTablePtr->CheckSum = 0;
+ FitTablePtr->CheckSum = CalculateChecksum8 ((UINT8 *) FitTablePtr, FitTablePtr->CompSize * 16);
+ }
+}
|