]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/C/GenFv/GenFvInternalLib.c
Sync BaseTool trunk (version r2610) into EDKII BaseTools.
[mirror_edk2.git] / BaseTools / Source / C / GenFv / GenFvInternalLib.c
index d17a2ff1a8f3c030f92445c0b5c3e671aa4cda7c..d0df4ac13daa80c2e13c3e8d541cec4c969ad5fd 100644 (file)
@@ -1,7 +1,8 @@
 /** @file\r
 \r
-Copyright (c) 2004 - 2009, Intel Corporation                                                         \r
-All rights reserved. This program and the accompanying materials                          \r
+Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.<BR>\r
+Portions Copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.<BR>\r
+This program and the accompanying materials                          \r
 are licensed and made available under the terms and conditions of the BSD License         \r
 which accompanies this distribution.  The full text of the license may be found at        \r
 http://opensource.org/licenses/bsd-license.php                                            \r
@@ -84,7 +85,7 @@ CHAR8      *mFvbAlignmentName[] = {
   EFI_FVB2_ALIGNMENT_64K_STRING, \r
   EFI_FVB2_ALIGNMENT_128K_STRING,\r
   EFI_FVB2_ALIGNMENT_256K_STRING,\r
-  EFI_FVB2_ALIGNMNET_512K_STRING,\r
+  EFI_FVB2_ALIGNMENT_512K_STRING,\r
   EFI_FVB2_ALIGNMENT_1M_STRING,  \r
   EFI_FVB2_ALIGNMENT_2M_STRING,  \r
   EFI_FVB2_ALIGNMENT_4M_STRING,  \r
@@ -158,6 +159,10 @@ UINT8                                   m64kRecoveryStartupApDataArray[SIZEOF_ST
 \r
 FV_INFO                     mFvDataInfo;\r
 CAP_INFO                    mCapDataInfo;\r
+BOOLEAN                     mIsLargeFfs = FALSE;\r
+\r
+EFI_PHYSICAL_ADDRESS mFvBaseAddress[0x10];\r
+UINT32               mFvBaseAddressNumber = 0;\r
 \r
 EFI_STATUS\r
 ParseFvInf (\r
@@ -206,6 +211,7 @@ Returns:
       DebugMsg (NULL, 0, 9, "rebase address", "%s = %s", EFI_FV_BASE_ADDRESS_STRING, Value);\r
 \r
       FvInfo->BaseAddress = Value64;\r
+      FvInfo->BaseAddressSet = TRUE;\r
     }\r
   }\r
 \r
@@ -275,6 +281,19 @@ Returns:
     }\r
   }\r
 \r
+  //\r
+  // Read weak alignment flag\r
+  //\r
+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FV_WEAK_ALIGNMENT_STRING, 0, Value);\r
+  if (Status == EFI_SUCCESS) {\r
+    if ((strcmp (Value, TRUE_STRING) == 0) || (strcmp (Value, ONE_STRING) == 0)) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_WEAK_ALIGNMENT;\r
+    } else if ((strcmp (Value, FALSE_STRING) != 0) && (strcmp (Value, ZERO_STRING) != 0)) {\r
+      Error (NULL, 0, 2000, "Invalid parameter", "Weak alignment value expected one of TRUE, FALSE, 1 or 0.");\r
+      return EFI_ABORTED;\r
+    }\r
+  }\r
+\r
   //\r
   // Read block maps\r
   //\r
@@ -505,7 +524,8 @@ AddPadFile (
   IN OUT MEMORY_FILE  *FvImage,\r
   IN UINT32           DataAlignment,\r
   IN VOID             *FvEnd,\r
-  IN EFI_FIRMWARE_VOLUME_EXT_HEADER *ExtHeader\r
+  IN EFI_FIRMWARE_VOLUME_EXT_HEADER *ExtHeader,\r
+  IN UINT32           NextFfsSize\r
   )\r
 /*++\r
 \r
@@ -533,7 +553,10 @@ Returns:
 {\r
   EFI_FFS_FILE_HEADER *PadFile;\r
   UINTN               PadFileSize;\r
+  UINT32              NextFfsHeaderSize;\r
+  UINT32              CurFfsHeaderSize;\r
 \r
+  CurFfsHeaderSize = sizeof (EFI_FFS_FILE_HEADER);\r
   //\r
   // Verify input parameters.\r
   //\r
@@ -541,43 +564,45 @@ Returns:
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  //\r
-  // Check if a pad file is necessary\r
-  //\r
-  if ((ExtHeader == NULL) && (((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + sizeof (EFI_FFS_FILE_HEADER)) % DataAlignment == 0)) {\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
   //\r
   // Calculate the pad file size\r
   //\r
-  //\r
-  // This is the earliest possible valid offset (current plus pad file header\r
-  // plus the next file header)\r
-  //\r
-  PadFileSize = (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + (sizeof (EFI_FFS_FILE_HEADER) * 2);\r
-\r
-  //\r
-  // Add whatever it takes to get to the next aligned address\r
-  //\r
-  while ((PadFileSize % DataAlignment) != 0) {\r
-    PadFileSize++;\r
-  }\r
-  //\r
-  // Subtract the next file header size\r
-  //\r
-  PadFileSize -= sizeof (EFI_FFS_FILE_HEADER);\r
 \r
-  //\r
-  // Subtract the starting offset to get size\r
-  //\r
-  PadFileSize -= (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage;\r
-  \r
   //\r
   // Append extension header size\r
   //\r
   if (ExtHeader != NULL) {\r
-    PadFileSize = PadFileSize + ExtHeader->ExtHeaderSize;\r
+    PadFileSize = ExtHeader->ExtHeaderSize;\r
+    if (PadFileSize + sizeof (EFI_FFS_FILE_HEADER) >= MAX_FFS_SIZE) {\r
+      CurFfsHeaderSize = sizeof (EFI_FFS_FILE_HEADER2);\r
+    }\r
+    PadFileSize += CurFfsHeaderSize;\r
+  } else {\r
+    NextFfsHeaderSize = sizeof (EFI_FFS_FILE_HEADER);\r
+    if (NextFfsSize >= MAX_FFS_SIZE) {\r
+      NextFfsHeaderSize = sizeof (EFI_FFS_FILE_HEADER2);\r
+    }\r
+    //\r
+    // Check if a pad file is necessary\r
+    //\r
+    if (((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + NextFfsHeaderSize) % DataAlignment == 0) {\r
+      return EFI_SUCCESS;\r
+    }\r
+    PadFileSize = (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + sizeof (EFI_FFS_FILE_HEADER) + NextFfsHeaderSize;\r
+    //\r
+    // Add whatever it takes to get to the next aligned address\r
+    //\r
+    while ((PadFileSize % DataAlignment) != 0) {\r
+      PadFileSize++;\r
+    }\r
+    //\r
+    // Subtract the next file header size\r
+    //\r
+    PadFileSize -= NextFfsHeaderSize;\r
+    //\r
+    // Subtract the starting offset to get size\r
+    //\r
+    PadFileSize -= (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage;\r
   }\r
 \r
   //\r
@@ -601,9 +626,15 @@ Returns:
   //\r
   // Write pad file size (calculated size minus next file header size)\r
   //\r
-  PadFile->Size[0]  = (UINT8) (PadFileSize & 0xFF);\r
-  PadFile->Size[1]  = (UINT8) ((PadFileSize >> 8) & 0xFF);\r
-  PadFile->Size[2]  = (UINT8) ((PadFileSize >> 16) & 0xFF);\r
+  if (PadFileSize >= MAX_FFS_SIZE) {\r
+    memset(PadFile->Size, 0, sizeof(UINT8) * 3);\r
+    ((EFI_FFS_FILE_HEADER2 *)PadFile)->ExtendedSize = PadFileSize;\r
+    PadFile->Attributes |= FFS_ATTRIB_LARGE_FILE;\r
+  } else {\r
+    PadFile->Size[0]  = (UINT8) (PadFileSize & 0xFF);\r
+    PadFile->Size[1]  = (UINT8) ((PadFileSize >> 8) & 0xFF);\r
+    PadFile->Size[2]  = (UINT8) ((PadFileSize >> 16) & 0xFF);\r
+  }\r
 \r
   //\r
   // Fill in checksums and state, they must be 0 for checksumming.\r
@@ -611,7 +642,7 @@ Returns:
   PadFile->IntegrityCheck.Checksum.Header = 0;\r
   PadFile->IntegrityCheck.Checksum.File   = 0;\r
   PadFile->State                          = 0;\r
-  PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER));\r
+  PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, CurFfsHeaderSize);\r
   PadFile->IntegrityCheck.Checksum.File   = FFS_FIXED_CHECKSUM;\r
 \r
   PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;\r
@@ -629,8 +660,8 @@ Returns:
     //\r
     // Copy Fv Extension Header and Set Fv Extension header offset\r
     //\r
-    memcpy (PadFile + 1, ExtHeader, ExtHeader->ExtHeaderSize);\r
-    ((EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage)->ExtHeaderOffset = (UINT16) ((UINTN) (PadFile + 1) - (UINTN) FvImage->FileImage);\r
+    memcpy ((UINT8 *)PadFile + CurFfsHeaderSize, ExtHeader, ExtHeader->ExtHeaderSize);\r
+    ((EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage)->ExtHeaderOffset = (UINT16) ((UINTN) ((UINT8 *)PadFile + CurFfsHeaderSize) - (UINTN) FvImage->FileImage);\r
          //\r
          // Make next file start at QWord Boundry\r
          //\r
@@ -674,7 +705,7 @@ EFI_STATUS
 WriteMapFile (\r
   IN OUT FILE                  *FvMapFile,\r
   IN     CHAR8                 *FileName,\r
-  IN     EFI_GUID              *FileGuidPtr\r
+  IN     EFI_FFS_FILE_HEADER   *FfsFile\r
   IN     EFI_PHYSICAL_ADDRESS  ImageBaseAddress,\r
   IN     PE_COFF_LOADER_IMAGE_CONTEXT *pImageContext\r
   )\r
@@ -689,7 +720,7 @@ Arguments:
 \r
   FvMapFile             A pointer to FvMap File\r
   FileName              Ffs File PathName\r
-  FileGuidPtr           Guid Value of Ffs file\r
+  FfsFile               A pointer to Ffs file image.\r
   ImageBaseAddress      PeImage Base Address.\r
   pImageContext         Image Context Information.\r
 \r
@@ -716,6 +747,10 @@ Returns:
   EFI_TE_IMAGE_HEADER                 *TEImageHeader;\r
   EFI_IMAGE_SECTION_HEADER            *SectionHeader;\r
   unsigned long long                  TempLongAddress;\r
+  UINT32                              TextVirtualAddress;\r
+  UINT32                              DataVirtualAddress;\r
+  EFI_PHYSICAL_ADDRESS                LinkTimeBaseAddress;\r
+\r
   //\r
   // Init local variable\r
   //\r
@@ -723,7 +758,7 @@ Returns:
   //\r
   // Print FileGuid to string buffer. \r
   //\r
-  PrintGuidToBuffer (FileGuidPtr, (UINT8 *)FileGuidName, MAX_LINE_LEN, TRUE);\r
+  PrintGuidToBuffer (&FfsFile->Name, (UINT8 *)FileGuidName, MAX_LINE_LEN, TRUE);\r
   \r
   //\r
   // Construct Map file Name \r
@@ -789,29 +824,44 @@ Returns:
     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (TEImageHeader + 1);\r
     Index = TEImageHeader->NumberOfSections;\r
   }\r
-  \r
+\r
   //\r
   // module information output\r
   //\r
   if (ImageBaseAddress == 0) {\r
     fprintf (FvMapFile, "%s (dummy) (", KeyWord);\r
-    fprintf (FvMapFile, "BaseAddress=%08llx, ", (unsigned long long) ImageBaseAddress);\r
+    fprintf (FvMapFile, "BaseAddress=%010llx, ", (unsigned long long) ImageBaseAddress);\r
+  } else {\r
+    fprintf (FvMapFile, "%s (Fixed Flash Address, ", KeyWord);\r
+    fprintf (FvMapFile, "BaseAddress=0x%010llx, ", (unsigned long long) (ImageBaseAddress + Offset));\r
+  }\r
+\r
+  if (FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE && pImageContext->Machine == EFI_IMAGE_MACHINE_IA64) {\r
+    //\r
+    // Process IPF PLABEL to get the real address after the image has been rebased. \r
+    // PLABEL structure is got by AddressOfEntryPoint offset to ImageBuffer stored in pImageContext->Handle.\r
+    //\r
+    fprintf (FvMapFile, "EntryPoint=0x%010llx", (unsigned long long) (*(UINT64 *)((UINTN) pImageContext->Handle + (UINTN) AddressOfEntryPoint)));\r
   } else {\r
-    fprintf (FvMapFile, "%s (", KeyWord);\r
-    fprintf (FvMapFile, "BaseAddress=%08llx, ", (unsigned long long) (ImageBaseAddress + Offset));\r
+    fprintf (FvMapFile, "EntryPoint=0x%010llx", (unsigned long long) (ImageBaseAddress + AddressOfEntryPoint));\r
   }\r
-  fprintf (FvMapFile, "EntryPoint=%08llx, ", (unsigned long long) (ImageBaseAddress + AddressOfEntryPoint));\r
-  fprintf (FvMapFile, "GUID=%s", FileGuidName);\r
   fprintf (FvMapFile, ")\n"); \r
   \r
+  fprintf (FvMapFile, "(GUID=%s", FileGuidName);\r
+  TextVirtualAddress = 0;\r
+  DataVirtualAddress = 0;\r
   for (; Index > 0; Index --, SectionHeader ++) {\r
-        if (stricmp ((CHAR8 *)SectionHeader->Name, ".text") == 0) {\r
-               fprintf (FvMapFile, ".textbaseaddress=%08llx ", (unsigned long long) (ImageBaseAddress + SectionHeader->VirtualAddress));\r
+    if (stricmp ((CHAR8 *)SectionHeader->Name, ".text") == 0) {\r
+               TextVirtualAddress = SectionHeader->VirtualAddress;\r
        } else if (stricmp ((CHAR8 *)SectionHeader->Name, ".data") == 0) {\r
-         fprintf (FvMapFile, ".databaseaddress=%08llx ", (unsigned long long) (ImageBaseAddress + SectionHeader->VirtualAddress));\r
+         DataVirtualAddress = SectionHeader->VirtualAddress;\r
+       } else if (stricmp ((CHAR8 *)SectionHeader->Name, ".sdata") == 0) {\r
+         DataVirtualAddress = SectionHeader->VirtualAddress;\r
        }\r
   }\r
-  fprintf (FvMapFile, "\n\n"); \r
+  fprintf (FvMapFile, " .textbaseaddress=0x%010llx", (unsigned long long) (ImageBaseAddress + TextVirtualAddress));\r
+  fprintf (FvMapFile, " .databaseaddress=0x%010llx", (unsigned long long) (ImageBaseAddress + DataVirtualAddress));\r
+  fprintf (FvMapFile, ")\n\n");\r
    \r
   //\r
   // Open PeMapFile\r
@@ -826,6 +876,7 @@ Returns:
   //\r
   // Output Functions information into Fv Map file\r
   //\r
+  LinkTimeBaseAddress = 0;\r
   while (fgets (Line, MAX_LINE_LEN, PeMapFile) != NULL) {\r
     //\r
     // Skip blank line\r
@@ -851,6 +902,9 @@ Returns:
         //\r
         FunctionType = 2;\r
         fgets (Line, MAX_LINE_LEN, PeMapFile);\r
+      } else if (stricmp (KeyWord, "Preferred") ==0) {\r
+        sscanf (Line + strlen (" Preferred load address is"), "%llx", &TempLongAddress);\r
+        LinkTimeBaseAddress = (UINT64) TempLongAddress;\r
       }\r
       continue;\r
     }\r
@@ -861,24 +915,14 @@ Returns:
       sscanf (Line, "%s %s %llx %s", KeyWord, FunctionName, &TempLongAddress, FunctionTypeName);\r
       FunctionAddress = (UINT64) TempLongAddress;\r
       if (FunctionTypeName [1] == '\0' && (FunctionTypeName [0] == 'f' || FunctionTypeName [0] == 'F')) {\r
-        fprintf (FvMapFile, "  %016llx ", (unsigned long long) (ImageBaseAddress + FunctionAddress));\r
-        fprintf (FvMapFile, "(%08llx) F  ", (unsigned long long) (FunctionAddress - Offset));\r
-        fprintf (FvMapFile, "%s\n", FunctionName);\r
-    } else {\r
-        fprintf (FvMapFile, "  %016llx ", (unsigned long long) (ImageBaseAddress + FunctionAddress));\r
-        fprintf (FvMapFile, "(%08llx)    ", (unsigned long long) (FunctionAddress - Offset));\r
+        fprintf (FvMapFile, "  0x%010llx    ", (unsigned long long) (ImageBaseAddress + FunctionAddress - LinkTimeBaseAddress));\r
         fprintf (FvMapFile, "%s\n", FunctionName);\r
       }\r
     } else if (FunctionType == 2) {\r
       sscanf (Line, "%s %s %llx %s", KeyWord, FunctionName, &TempLongAddress, FunctionTypeName);\r
       FunctionAddress = (UINT64) TempLongAddress;\r
       if (FunctionTypeName [1] == '\0' && (FunctionTypeName [0] == 'f' || FunctionTypeName [0] == 'F')) {\r
-        fprintf (FvMapFile, "  %016llx ", (unsigned long long) (ImageBaseAddress + FunctionAddress));\r
-        fprintf (FvMapFile, "(%08llx) FS ", (unsigned long long) (FunctionAddress - Offset));\r
-        fprintf (FvMapFile, "%s\n", FunctionName);\r
-      } else {\r
-        fprintf (FvMapFile, "  %016llx ", (unsigned long long) (ImageBaseAddress + FunctionAddress));\r
-        fprintf (FvMapFile, "(%08llx)    ", (unsigned long long) (FunctionAddress - Offset));\r
+        fprintf (FvMapFile, "  0x%010llx    ", (unsigned long long) (ImageBaseAddress + FunctionAddress - LinkTimeBaseAddress));\r
         fprintf (FvMapFile, "%s\n", FunctionName);\r
       }\r
     }\r
@@ -898,7 +942,8 @@ AddFile (
   IN FV_INFO                  *FvInfo,\r
   IN UINTN                    Index,\r
   IN OUT EFI_FFS_FILE_HEADER  **VtfFileImage,\r
-  IN FILE                     *FvMapFile  \r
+  IN FILE                     *FvMapFile,\r
+  IN FILE                     *FvReportFile\r
   )\r
 /*++\r
 \r
@@ -916,6 +961,7 @@ Arguments:
   VtfFileImage  A pointer to the VTF file within the FvImage.  If this is equal\r
                 to the end of the FvImage then no VTF previously found.\r
   FvMapFile     Pointer to FvMap File\r
+  FvReportFile  Pointer to FvReport File\r
 \r
 Returns:\r
 \r
@@ -933,6 +979,7 @@ Returns:
   UINT32                CurrentFileAlignment;\r
   EFI_STATUS            Status;\r
   UINTN                 Index1;\r
+  UINT8                 FileGuidString[PRINTED_GUID_BUFFER_SIZE];\r
   \r
   Index1 = 0;\r
   //\r
@@ -1001,7 +1048,7 @@ Returns:
   Status = VerifyFfsFile ((EFI_FFS_FILE_HEADER *)FileBuffer);\r
   if (EFI_ERROR (Status)) {\r
     free (FileBuffer);\r
-    Error (NULL, 0, 3000, "Invalid", "%s is a FFS file.", FvInfo->FvFiles[Index]);\r
+    Error (NULL, 0, 3000, "Invalid", "%s is not a valid FFS file.", FvInfo->FvFiles[Index]);\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
@@ -1057,7 +1104,7 @@ Returns:
       //\r
       // Sanity check. The file MUST align appropriately\r
       //\r
-      if (((UINTN) *VtfFileImage + sizeof (EFI_FFS_FILE_HEADER) - (UINTN) FvImage->FileImage) % (1 << CurrentFileAlignment)) {\r
+      if (((UINTN) *VtfFileImage + GetFfsHeaderLength((EFI_FFS_FILE_HEADER *)FileBuffer) - (UINTN) FvImage->FileImage) % (1 << CurrentFileAlignment)) {\r
         Error (NULL, 0, 3000, "Invalid", "VTF file cannot be aligned on a %u-byte boundary.", (unsigned) (1 << CurrentFileAlignment));\r
         free (FileBuffer);\r
         return EFI_ABORTED;\r
@@ -1066,11 +1113,19 @@ Returns:
       // Rebase the PE or TE image in FileBuffer of FFS file for XIP \r
       // Rebase for the debug genfvmap tool\r
       //\r
-      FfsRebase (FvInfo, FvInfo->FvFiles[Index], (EFI_FFS_FILE_HEADER *) FileBuffer, (UINTN) *VtfFileImage - (UINTN) FvImage->FileImage, FvMapFile);\r
+      Status = FfsRebase (FvInfo, FvInfo->FvFiles[Index], (EFI_FFS_FILE_HEADER *) FileBuffer, (UINTN) *VtfFileImage - (UINTN) FvImage->FileImage, FvMapFile);\r
+      if (EFI_ERROR (Status)) {\r
+        Error (NULL, 0, 3000, "Invalid", "Could not rebase %s.", FvInfo->FvFiles[Index]);\r
+        return Status;\r
+      }          \r
       //\r
       // copy VTF File\r
       //\r
       memcpy (*VtfFileImage, FileBuffer, FileSize);\r
+      \r
+      PrintGuidToBuffer ((EFI_GUID *) FileBuffer, FileGuidString, sizeof (FileGuidString), TRUE); \r
+      fprintf (FvReportFile, "0x%08X %s\n", (unsigned)(UINTN) (((UINT8 *)*VtfFileImage) - (UINTN)FvImage->FileImage), FileGuidString);\r
+\r
       free (FileBuffer);\r
       DebugMsg (NULL, 0, 9, "Add VTF FFS file in FV image", NULL);\r
       return EFI_SUCCESS;\r
@@ -1087,7 +1142,7 @@ Returns:
   //\r
   // Add pad file if necessary\r
   //\r
-  Status = AddPadFile (FvImage, 1 << CurrentFileAlignment, *VtfFileImage, NULL);\r
+  Status = AddPadFile (FvImage, 1 << CurrentFileAlignment, *VtfFileImage, NULL, FileSize);\r
   if (EFI_ERROR (Status)) {\r
     Error (NULL, 0, 4002, "Resource", "FV space is full, could not add pad file for data alignment property.");\r
     free (FileBuffer);\r
@@ -1101,11 +1156,17 @@ Returns:
     // Rebase the PE or TE image in FileBuffer of FFS file for XIP. \r
     // Rebase Bs and Rt drivers for the debug genfvmap tool.\r
     //\r
-    FfsRebase (FvInfo, FvInfo->FvFiles[Index], (EFI_FFS_FILE_HEADER *) FileBuffer, (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage, FvMapFile);\r
+    Status = FfsRebase (FvInfo, FvInfo->FvFiles[Index], (EFI_FFS_FILE_HEADER *) FileBuffer, (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage, FvMapFile);\r
+       if (EFI_ERROR (Status)) {\r
+         Error (NULL, 0, 3000, "Invalid", "Could not rebase %s.", FvInfo->FvFiles[Index]);\r
+         return Status;\r
+       }               \r
     //\r
     // Copy the file\r
     //\r
     memcpy (FvImage->CurrentFilePointer, FileBuffer, FileSize);\r
+    PrintGuidToBuffer ((EFI_GUID *) FileBuffer, FileGuidString, sizeof (FileGuidString), TRUE); \r
+    fprintf (FvReportFile, "0x%08X %s\n", (unsigned) (FvImage->CurrentFilePointer - FvImage->FileImage), FileGuidString);\r
     FvImage->CurrentFilePointer += FileSize;\r
   } else {\r
     Error (NULL, 0, 4002, "Resource", "FV space is full, cannot add file %s.", FvInfo->FvFiles[Index]);\r
@@ -1155,6 +1216,7 @@ Returns:
 {\r
   EFI_FFS_FILE_HEADER *PadFile;\r
   UINTN               FileSize;\r
+  UINT32              FfsHeaderSize;\r
 \r
   //\r
   // If there is no VTF or the VTF naturally follows the previous file without a\r
@@ -1184,9 +1246,18 @@ Returns:
   // FileSize includes the EFI_FFS_FILE_HEADER\r
   //\r
   FileSize          = (UINTN) VtfFileImage - (UINTN) FvImage->CurrentFilePointer;\r
-  PadFile->Size[0]  = (UINT8) (FileSize & 0x000000FF);\r
-  PadFile->Size[1]  = (UINT8) ((FileSize & 0x0000FF00) >> 8);\r
-  PadFile->Size[2]  = (UINT8) ((FileSize & 0x00FF0000) >> 16);\r
+  if (FileSize >= MAX_FFS_SIZE) {\r
+    PadFile->Attributes |= FFS_ATTRIB_LARGE_FILE;\r
+    memset(PadFile->Size, 0, sizeof(UINT8) * 3);\r
+    ((EFI_FFS_FILE_HEADER2 *)PadFile)->ExtendedSize = FileSize;\r
+    FfsHeaderSize = sizeof(EFI_FFS_FILE_HEADER2);\r
+    mIsLargeFfs = TRUE;\r
+  } else {\r
+    PadFile->Size[0]  = (UINT8) (FileSize & 0x000000FF);\r
+    PadFile->Size[1]  = (UINT8) ((FileSize & 0x0000FF00) >> 8);\r
+    PadFile->Size[2]  = (UINT8) ((FileSize & 0x00FF0000) >> 16);\r
+    FfsHeaderSize = sizeof(EFI_FFS_FILE_HEADER);\r
+  }\r
 \r
   //\r
   // Fill in checksums and state, must be zero during checksum calculation.\r
@@ -1194,7 +1265,7 @@ Returns:
   PadFile->IntegrityCheck.Checksum.Header = 0;\r
   PadFile->IntegrityCheck.Checksum.File   = 0;\r
   PadFile->State                          = 0;\r
-  PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER));\r
+  PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, FfsHeaderSize);\r
   PadFile->IntegrityCheck.Checksum.File   = FFS_FIXED_CHECKSUM;\r
 \r
   PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;\r
@@ -1262,6 +1333,8 @@ Returns:
   UINT64                    FitAddress;\r
   FIT_TABLE                 *FitTablePtr;\r
   BOOLEAN                   Vtf0Detected;\r
+  UINT32                    FfsHeaderSize;\r
+  UINT32                    SecHeaderSize;\r
 \r
   //\r
   // Verify input parameters\r
@@ -1324,8 +1397,9 @@ Returns:
     return EFI_ABORTED;\r
   }\r
 \r
+  SecHeaderSize = GetSectionHeaderLength(Pe32Section.CommonHeader);\r
   Status = GetPe32Info (\r
-            (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),\r
+            (VOID *) ((UINTN) Pe32Section.Pe32Section + SecHeaderSize),\r
             &EntryPoint,\r
             &BaseOfCode,\r
             &MachineType\r
@@ -1353,7 +1427,7 @@ Returns:
   // Physical address is FV base + offset of PE32 + offset of the entry point\r
   //\r
   SecCorePhysicalAddress = FvInfo->BaseAddress;\r
-  SecCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;\r
+  SecCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + SecHeaderSize - (UINTN) FvImage->FileImage;\r
   SecCorePhysicalAddress += EntryPoint;\r
   DebugMsg (NULL, 0, 9, "SecCore physical entry point address", "Address = 0x%llX", (unsigned long long) SecCorePhysicalAddress); \r
 \r
@@ -1378,8 +1452,9 @@ Returns:
     return EFI_ABORTED;\r
   }\r
 \r
+  SecHeaderSize = GetSectionHeaderLength(Pe32Section.CommonHeader);\r
   Status = GetPe32Info (\r
-            (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),\r
+            (VOID *) ((UINTN) Pe32Section.Pe32Section + SecHeaderSize),\r
             &EntryPoint,\r
             &BaseOfCode,\r
             &MachineType\r
@@ -1393,7 +1468,7 @@ Returns:
   // Physical address is FV base + offset of PE32 + offset of the entry point\r
   //\r
   PeiCorePhysicalAddress = FvInfo->BaseAddress;\r
-  PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;\r
+  PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + SecHeaderSize - (UINTN) FvImage->FileImage;\r
   PeiCorePhysicalAddress += EntryPoint;\r
   DebugMsg (NULL, 0, 9, "PeiCore physical entry point address", "Address = 0x%llX", (unsigned long long) PeiCorePhysicalAddress);\r
 \r
@@ -1501,7 +1576,7 @@ Returns:
       //\r
       Status = FindApResetVectorPosition (FvImage, &BytePointer);\r
       if (EFI_ERROR (Status)) {\r
-        Error (NULL, 0, 3000, "Invalid", "Cannot find the appropriate location in FvImage to add Ap reset vector!");\r
+        Error (NULL, 0, 3000, "Invalid", "FV image does not have enough space to place AP reset vector. The FV image needs to reserve at least 4KB of unused space.");\r
         return EFI_ABORTED;\r
       }\r
     }\r
@@ -1546,6 +1621,11 @@ Returns:
     // Since the ARM reset vector is in the FV Header you really don't need a\r
     // Volume Top File, but if you have one for some reason don't crash...\r
     //\r
+  } else if (MachineType == EFI_IMAGE_MACHINE_AARCH64) {\r
+    //\r
+    // Since the AArch64 reset vector is in the FV Header you really don't need a\r
+    // Volume Top File, but if you have one for some reason don't crash...\r
+    //\r
   } else {\r
     Error (NULL, 0, 3000, "Invalid", "machine type=0x%X in PEI core.", MachineType);\r
     return EFI_ABORTED;\r
@@ -1558,9 +1638,10 @@ Returns:
   VtfFile->IntegrityCheck.Checksum.File = 0;\r
   VtfFile->State                        = 0;\r
   if (VtfFile->Attributes & FFS_ATTRIB_CHECKSUM) {\r
+    FfsHeaderSize = GetFfsHeaderLength(VtfFile);\r
     VtfFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (\r
-                                              (UINT8 *) (VtfFile + 1),\r
-                                              GetLength (VtfFile->Size) - sizeof (EFI_FFS_FILE_HEADER)\r
+                                              (UINT8 *) ((UINT8 *)VtfFile + FfsHeaderSize),\r
+                                              GetFfsFileLength (VtfFile) - FfsHeaderSize\r
                                               );\r
   } else {\r
     VtfFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
@@ -1583,9 +1664,11 @@ Routine Description:
   This parses the FV looking for SEC and patches that address into the \r
   beginning of the FV header.\r
 \r
-  For ARM the reset vector is at 0x00000000 or 0xFFFF0000.\r
+  For ARM32 the reset vector is at 0x00000000 or 0xFFFF0000.\r
+  For AArch64 the reset vector is at 0x00000000.\r
+\r
   This would commonly map to the first entry in the ROM. \r
-  ARM Exceptions:\r
+  ARM32 Exceptions:\r
   Reset            +0    \r
   Undefined        +4\r
   SWI              +8\r
@@ -1599,11 +1682,10 @@ Routine Description:
   2) Reset vector is data bytes FDF file and that code branches to reset vector \r
     in the beginning of the FV (fixed size offset).\r
 \r
-\r
   Need to have the jump for the reset vector at location zero.\r
   We also need to store the address or PEI (if it exists).\r
   We stub out a return from interrupt in case the debugger \r
-   is using SWI.\r
+   is using SWI (not done for AArch64, not enough space in struct).\r
   The optional entry to the common exception handler is \r
    to support full featured exception handling from ROM and is currently \r
     not support by this tool.\r
@@ -1630,10 +1712,14 @@ Returns:
   UINT16                    MachineType;\r
   EFI_PHYSICAL_ADDRESS      PeiCorePhysicalAddress;\r
   EFI_PHYSICAL_ADDRESS      SecCorePhysicalAddress;\r
-  INT32                     ResetVector[4]; // 0 - is branch relative to SEC entry point\r
+  INT32                     ResetVector[4]; // ARM32:\r
+                                            // 0 - is branch relative to SEC entry point\r
                                             // 1 - PEI Entry Point\r
                                             // 2 - movs pc,lr for a SWI handler\r
                                             // 3 - Place holder for Common Exception Handler\r
+                                            // AArch64: Used as UINT64 ResetVector[2]\r
+                                            // 0 - is branch relative to SEC entry point\r
+                                            // 1 - PEI Entry Point\r
 \r
   //\r
   // Verify input parameters\r
@@ -1675,7 +1761,7 @@ Returns:
       }\r
     \r
       Status = GetPe32Info (\r
-                (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),\r
+                (VOID *) ((UINTN) Pe32Section.Pe32Section + GetSectionHeaderLength(Pe32Section.CommonHeader)),\r
                 &EntryPoint,\r
                 &BaseOfCode,\r
                 &MachineType\r
@@ -1689,11 +1775,11 @@ Returns:
       // Physical address is FV base + offset of PE32 + offset of the entry point\r
       //\r
       PeiCorePhysicalAddress = FvInfo->BaseAddress;\r
-      PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;\r
+      PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + GetSectionHeaderLength(Pe32Section.CommonHeader) - (UINTN) FvImage->FileImage;\r
       PeiCorePhysicalAddress += EntryPoint;\r
       DebugMsg (NULL, 0, 9, "PeiCore physical entry point address", "Address = 0x%llX", (unsigned long long) PeiCorePhysicalAddress);\r
 \r
-      if (MachineType == EFI_IMAGE_MACHINE_ARMT) {\r
+      if (MachineType == EFI_IMAGE_MACHINE_ARMT || MachineType == EFI_IMAGE_MACHINE_AARCH64) {\r
         memset (ResetVector, 0, sizeof (ResetVector));\r
         // Address of PEI Core, if we have one\r
         ResetVector[1] = (UINT32)PeiCorePhysicalAddress;\r
@@ -1723,7 +1809,7 @@ Returns:
   }\r
 \r
   Status = GetPe32Info (\r
-            (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),\r
+            (VOID *) ((UINTN) Pe32Section.Pe32Section + GetSectionHeaderLength(Pe32Section.CommonHeader)),\r
             &EntryPoint,\r
             &BaseOfCode,\r
             &MachineType\r
@@ -1733,7 +1819,7 @@ Returns:
     return EFI_ABORTED;\r
   }\r
   \r
-  if (MachineType != EFI_IMAGE_MACHINE_ARMT) {\r
+  if ((MachineType != EFI_IMAGE_MACHINE_ARMT) && (MachineType != EFI_IMAGE_MACHINE_AARCH64)) {\r
     //\r
     // If SEC is not ARM we have nothing to do\r
     //\r
@@ -1744,7 +1830,7 @@ Returns:
   // Physical address is FV base + offset of PE32 + offset of the entry point\r
   //\r
   SecCorePhysicalAddress = FvInfo->BaseAddress;\r
-  SecCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;\r
+  SecCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + GetSectionHeaderLength(Pe32Section.CommonHeader) - (UINTN) FvImage->FileImage;\r
   SecCorePhysicalAddress += EntryPoint;\r
   DebugMsg (NULL, 0, 9, "SecCore physical entry point address", "Address = 0x%llX", (unsigned long long) SecCorePhysicalAddress); \r
 \r
@@ -1768,7 +1854,7 @@ Returns:
     }\r
   \r
     Status = GetPe32Info (\r
-              (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),\r
+              (VOID *) ((UINTN) Pe32Section.Pe32Section + GetSectionHeaderLength(Pe32Section.CommonHeader)),\r
               &EntryPoint,\r
               &BaseOfCode,\r
               &MachineType\r
@@ -1782,36 +1868,65 @@ Returns:
     // Physical address is FV base + offset of PE32 + offset of the entry point\r
     //\r
     PeiCorePhysicalAddress = FvInfo->BaseAddress;\r
-    PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;\r
+    PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + GetSectionHeaderLength(Pe32Section.CommonHeader) - (UINTN) FvImage->FileImage;\r
     PeiCorePhysicalAddress += EntryPoint;\r
     DebugMsg (NULL, 0, 9, "PeiCore physical entry point address", "Address = 0x%llX", (unsigned long long) PeiCorePhysicalAddress);\r
   }\r
   \r
+  if (MachineType == EFI_IMAGE_MACHINE_ARMT) {\r
+    // B SecEntryPoint - signed_immed_24 part +/-32MB offset\r
+    // on ARM, the PC is always 8 ahead, so we're not really jumping from the base address, but from base address + 8\r
+    ResetVector[0] = (INT32)(SecCorePhysicalAddress - FvInfo->BaseAddress - 8) >> 2;\r
+\r
+    if (ResetVector[0] > 0x00FFFFFF) {\r
+      Error (NULL, 0, 3000, "Invalid", "SEC Entry point must be within 32MB of the start of the FV");\r
+      return EFI_ABORTED;\r
+    }\r
   \r
-  // B SecEntryPoint - signed_immed_24 part +/-32MB offset\r
-  // on ARM, the PC is always 8 ahead, so we're not really jumping from the base address, but from base address + 8\r
-  ResetVector[0] = (INT32)(SecCorePhysicalAddress - FvInfo->BaseAddress - 8) >> 2;\r
-  \r
-  if (ResetVector[0] > 0x00FFFFFF) {\r
-    Error (NULL, 0, 3000, "Invalid", "SEC Entry point must be within 32MB of the start of the FV");\r
-    return EFI_ABORTED;    \r
-  }\r
-  \r
-  // Add opcode for an uncondional branch with no link. AKA B SecEntryPoint\r
-  ResetVector[0] |= 0xEA000000;\r
+    // Add opcode for an uncondional branch with no link. AKA B SecEntryPoint\r
+    ResetVector[0] |= 0xEB000000;\r
   \r
   \r
-  // Address of PEI Core, if we have one\r
-  ResetVector[1] = (UINT32)PeiCorePhysicalAddress;\r
+    // Address of PEI Core, if we have one\r
+    ResetVector[1] = (UINT32)PeiCorePhysicalAddress;\r
   \r
-  // SWI handler movs   pc,lr. Just in case a debugger uses SWI\r
-  ResetVector[2] = 0xE1B0F07E;\r
+    // SWI handler movs   pc,lr. Just in case a debugger uses SWI\r
+    ResetVector[2] = 0xE1B0F07E;\r
   \r
-  // Place holder to support a common interrupt handler from ROM. \r
-  // Currently not suppprted. For this to be used the reset vector would not be in this FV\r
-  // and the exception vectors would be hard coded in the ROM and just through this address \r
-  // to find a common handler in the a module in the FV.\r
-  ResetVector[3] = 0;\r
+    // Place holder to support a common interrupt handler from ROM.\r
+    // Currently not suppprted. For this to be used the reset vector would not be in this FV\r
+    // and the exception vectors would be hard coded in the ROM and just through this address\r
+    // to find a common handler in the a module in the FV.\r
+    ResetVector[3] = 0;\r
+  } else if (MachineType == EFI_IMAGE_MACHINE_AARCH64) {\r
+\r
+  /* NOTE:\r
+    ARMT above has an entry in ResetVector[2] for SWI. The way we are using the ResetVector\r
+    array at the moment, for AArch64, does not allow us space for this as the header only\r
+    allows for a fixed amount of bytes at the start. If we are sure that UEFI will live\r
+    within the first 4GB of addressable RAM we could potensioally adopt the same ResetVector\r
+    layout as above. But for the moment we replace the four 32bit vectors with two 64bit\r
+    vectors in the same area of the Image heasder. This allows UEFI to start from a 64bit\r
+    base.\r
+  */\r
+\r
+    ((UINT64*)ResetVector)[0] = (UINT64)(SecCorePhysicalAddress - FvInfo->BaseAddress) >> 2;\r
+\r
+    // B SecEntryPoint - signed_immed_26 part +/-128MB offset\r
+    if ( ((UINT64*)ResetVector)[0] > 0x03FFFFFF) {\r
+      Error (NULL, 0, 3000, "Invalid", "SEC Entry point must be within 128MB of the start of the FV");\r
+      return EFI_ABORTED;\r
+    }\r
+    // Add opcode for an uncondional branch with no link. AKA B SecEntryPoint\r
+    ((UINT64*)ResetVector)[0] |= 0x14000000;\r
+\r
+    // Address of PEI Core, if we have one\r
+    ((UINT64*)ResetVector)[1] = (UINT64)PeiCorePhysicalAddress;\r
+\r
+  } else {\r
+    Error (NULL, 0, 3000, "Invalid", "Unknown ARM machine type");\r
+    return EFI_ABORTED;\r
+  }\r
 \r
   //\r
   // Copy to the beginning of the FV \r
@@ -1914,8 +2029,8 @@ Returns:
   //\r
   // Verify machine type is supported\r
   //\r
-  if (*MachineType != EFI_IMAGE_MACHINE_IA32 && *MachineType != EFI_IMAGE_MACHINE_IA64 && *MachineType != EFI_IMAGE_MACHINE_X64 && *MachineType != EFI_IMAGE_MACHINE_EBC && \r
-      *MachineType != EFI_IMAGE_MACHINE_ARMT) {\r
+  if ((*MachineType != EFI_IMAGE_MACHINE_IA32) && (*MachineType != EFI_IMAGE_MACHINE_IA64) && (*MachineType != EFI_IMAGE_MACHINE_X64) && (*MachineType != EFI_IMAGE_MACHINE_EBC) && \r
+      (*MachineType != EFI_IMAGE_MACHINE_ARMT) && (*MachineType != EFI_IMAGE_MACHINE_AARCH64)) {\r
     Error (NULL, 0, 3000, "Invalid", "Unrecognized machine type in the PE32 file.");\r
     return EFI_UNSUPPORTED;\r
   }\r
@@ -1967,10 +2082,13 @@ Returns:
   EFI_FIRMWARE_VOLUME_EXT_HEADER  *FvExtHeader;\r
   FILE                            *FvExtHeaderFile;\r
   UINTN                           FileSize;\r
+  CHAR8                           FvReportName[_MAX_PATH];\r
+  FILE                            *FvReportFile;\r
 \r
   FvBufferHeader = NULL;\r
   FvFile         = NULL;\r
   FvMapFile      = NULL;\r
+  FvReportFile   = NULL;\r
 \r
   if (InfFileImage != NULL) {\r
     //\r
@@ -2109,6 +2227,12 @@ Returns:
   }\r
   VerboseMsg ("FV Map file name is %s", FvMapName);\r
 \r
+  //\r
+  // FvReport file to log the FV information in one Fvimage\r
+  //\r
+  strcpy (FvReportName, FvFileName);\r
+  strcat (FvReportName, ".txt");\r
+\r
   //\r
   // Calculate the FV size and Update Fv Size based on the actual FFS files.\r
   // And Update mFvDataInfo data.\r
@@ -2224,6 +2348,14 @@ Returns:
     return EFI_ABORTED;\r
   }\r
   \r
+  //\r
+  // Open FvReport file\r
+  //\r
+  FvReportFile = fopen(FvReportName, "w");\r
+  if (FvReportFile == NULL) {\r
+    Error (NULL, 0, 0001, "Error opening file", FvReportName);\r
+    return EFI_ABORTED;\r
+  }\r
   //\r
   // record FV size information into FvMap file.\r
   //\r
@@ -2240,6 +2372,12 @@ Returns:
     fprintf (FvMapFile, " = 0x%x\n\n", (unsigned) (mFvTotalSize - mFvTakenSize));\r
   }\r
 \r
+  //\r
+  // record FV size information to FvReportFile.\r
+  //\r
+  fprintf (FvReportFile, "%s = 0x%x\n", EFI_FV_TOTAL_SIZE_STRING, (unsigned) mFvTotalSize);\r
+  fprintf (FvReportFile, "%s = 0x%x\n", EFI_FV_TAKEN_SIZE_STRING, (unsigned) mFvTakenSize);\r
+\r
   //\r
   // Add PI FV extension header\r
   //\r
@@ -2247,7 +2385,7 @@ Returns:
     //\r
     // Add FV Extended Header contents to the FV as a PAD file\r
     //\r
-    AddPadFile (&FvImageMemoryFile, 4, VtfFileImage, FvExtHeader);\r
+    AddPadFile (&FvImageMemoryFile, 4, VtfFileImage, FvExtHeader, 0);\r
 \r
     //\r
     // Fv Extension header change update Fv Header Check sum\r
@@ -2263,7 +2401,7 @@ Returns:
     //\r
     // Add the file\r
     //\r
-    Status = AddFile (&FvImageMemoryFile, &mFvDataInfo, Index, &VtfFileImage, FvMapFile);\r
+    Status = AddFile (&FvImageMemoryFile, &mFvDataInfo, Index, &VtfFileImage, FvMapFile, FvReportFile);\r
 \r
     //\r
     // Exit if error detected while adding the file\r
@@ -2322,7 +2460,8 @@ Returns:
   //\r
   // Update FV Alignment attribute to the largest alignment of all the FFS files in the FV\r
   //\r
-  if ((((FvHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16)) < MaxFfsAlignment) {\r
+  if (((FvHeader->Attributes & EFI_FVB2_WEAK_ALIGNMENT) != EFI_FVB2_WEAK_ALIGNMENT) &&\r
+      (((FvHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16)) < MaxFfsAlignment) {\r
     FvHeader->Attributes = ((MaxFfsAlignment << 16) | (FvHeader->Attributes & 0xFFFF));\r
     //\r
     // Update Checksum for FvHeader\r
@@ -2331,6 +2470,15 @@ Returns:
     FvHeader->Checksum      = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));\r
   }\r
 \r
+  //\r
+  // If there are large FFS in FV, the file system GUID should set to system 3 GUID.\r
+  //\r
+  if (mIsLargeFfs && CompareGuid (&FvHeader->FileSystemGuid, &mEfiFirmwareFileSystem2Guid) == 0) {\r
+    memcpy (&FvHeader->FileSystemGuid, &mEfiFirmwareFileSystem3Guid, sizeof (EFI_GUID));\r
+    FvHeader->Checksum      = 0;\r
+    FvHeader->Checksum      = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));\r
+  }\r
+\r
 WriteFile: \r
   //\r
   // Write fv file\r
@@ -2358,13 +2506,19 @@ Finish:
   }\r
   \r
   if (FvFile != NULL) {\r
+    fflush (FvFile);\r
     fclose (FvFile);\r
   }\r
   \r
   if (FvMapFile != NULL) {\r
+    fflush (FvMapFile);\r
     fclose (FvMapFile);\r
   }\r
 \r
+  if (FvReportFile != NULL) {\r
+    fflush (FvReportFile);\r
+    fclose (FvReportFile);\r
+  }\r
   return Status;\r
 }\r
 \r
@@ -2461,6 +2615,7 @@ Returns:
   UINTN               FfsFileSize;\r
   UINTN               FvExtendHeaderSize;\r
   UINT32              FfsAlignment;\r
+  UINT32              FfsHeaderSize;\r
   EFI_FFS_FILE_HEADER FfsHeader;\r
   BOOLEAN             VtfFileFlag;\r
   UINTN               VtfFileSize;\r
@@ -2502,7 +2657,12 @@ Returns:
     }\r
     FvExtendHeaderSize = _filelength (fileno (fpin));\r
     fclose (fpin);\r
-    CurrentOffset += sizeof (EFI_FFS_FILE_HEADER) + FvExtendHeaderSize;\r
+    if (sizeof (EFI_FFS_FILE_HEADER) + FvExtendHeaderSize >= MAX_FFS_SIZE) {\r
+      CurrentOffset += sizeof (EFI_FFS_FILE_HEADER2) + FvExtendHeaderSize;\r
+      mIsLargeFfs = TRUE;\r
+    } else {\r
+      CurrentOffset += sizeof (EFI_FFS_FILE_HEADER) + FvExtendHeaderSize;\r
+    }\r
     CurrentOffset = (CurrentOffset + 7) & (~7);\r
   } else if (mFvDataInfo.FvNameGuidSet) {\r
     CurrentOffset += sizeof (EFI_FFS_FILE_HEADER) + sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER);\r
@@ -2526,6 +2686,12 @@ Returns:
     // Get the file size\r
     //\r
     FfsFileSize = _filelength (fileno (fpin));\r
+    if (FfsFileSize >= MAX_FFS_SIZE) {\r
+      FfsHeaderSize = sizeof(EFI_FFS_FILE_HEADER2);\r
+      mIsLargeFfs = TRUE;\r
+    } else {\r
+      FfsHeaderSize = sizeof(EFI_FFS_FILE_HEADER);\r
+    }\r
     //\r
     // Read Ffs File header\r
     //\r
@@ -2559,9 +2725,12 @@ Returns:
       //\r
       // Add Pad file\r
       //\r
-      if (((CurrentOffset + sizeof (EFI_FFS_FILE_HEADER)) % FfsAlignment) != 0) {\r
-        CurrentOffset = (CurrentOffset + sizeof (EFI_FFS_FILE_HEADER) * 2 + FfsAlignment - 1) & ~(FfsAlignment - 1);\r
-        CurrentOffset -= sizeof (EFI_FFS_FILE_HEADER);\r
+      if (((CurrentOffset + FfsHeaderSize) % FfsAlignment) != 0) {\r
+        //\r
+        // Only EFI_FFS_FILE_HEADER is needed for a pad section.\r
+        //\r
+        CurrentOffset = (CurrentOffset + FfsHeaderSize + sizeof(EFI_FFS_FILE_HEADER) + FfsAlignment - 1) & ~(FfsAlignment - 1);\r
+        CurrentOffset -= FfsHeaderSize;\r
       }\r
          }\r
 \r
@@ -2652,6 +2821,54 @@ Returns:
   return EFI_SUCCESS;\r
 }\r
 \r
+EFI_STATUS\r
+GetChildFvFromFfs (\r
+  IN      FV_INFO               *FvInfo, \r
+  IN      EFI_FFS_FILE_HEADER   *FfsFile,\r
+  IN      UINTN                 XipOffset\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function gets all child FvImages in the input FfsFile, and records\r
+  their base address to the parent image.\r
+\r
+Arguments:\r
+  FvInfo            A pointer to FV_INFO struture.\r
+  FfsFile           A pointer to Ffs file image that may contain FvImage.\r
+  XipOffset         The offset address to the parent FvImage base.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS        Base address of child Fv image is recorded.\r
+--*/\r
+{\r
+  EFI_STATUS                          Status;\r
+  UINTN                               Index;\r
+  EFI_FILE_SECTION_POINTER            SubFvSection;\r
+  EFI_FIRMWARE_VOLUME_HEADER          *SubFvImageHeader;\r
+  EFI_PHYSICAL_ADDRESS                SubFvBaseAddress;\r
+\r
+  for (Index = 1;; Index++) {\r
+    //\r
+    // Find FV section \r
+    //\r
+    Status = GetSectionByType (FfsFile, EFI_SECTION_FIRMWARE_VOLUME_IMAGE, Index, &SubFvSection);\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+    SubFvImageHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINT8 *) SubFvSection.FVImageSection + GetSectionHeaderLength(SubFvSection.FVImageSection));\r
+    //\r
+    // Rebase on Flash\r
+    //\r
+    SubFvBaseAddress = FvInfo->BaseAddress + (UINTN) SubFvImageHeader - (UINTN) FfsFile + XipOffset;\r
+    mFvBaseAddress[mFvBaseAddressNumber ++ ] = SubFvBaseAddress;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
 EFI_STATUS\r
 FfsRebase ( \r
   IN OUT  FV_INFO               *FvInfo, \r
@@ -2690,13 +2907,11 @@ Returns:
   PE_COFF_LOADER_IMAGE_CONTEXT          OrigImageContext;  \r
   EFI_PHYSICAL_ADDRESS                  XipBase;\r
   EFI_PHYSICAL_ADDRESS                  NewPe32BaseAddress;\r
-  EFI_PHYSICAL_ADDRESS                  *BaseToUpdate;\r
   UINTN                                 Index;\r
   EFI_FILE_SECTION_POINTER              CurrentPe32Section;\r
   EFI_FFS_FILE_STATE                    SavedState;\r
   EFI_IMAGE_OPTIONAL_HEADER_UNION       *ImgHdr;\r
   EFI_TE_IMAGE_HEADER                   *TEImageHeader;\r
-  UINT8                                 Flags;\r
   UINT8                                 *MemoryImagePointer;\r
   EFI_IMAGE_SECTION_HEADER              *SectionHeader;\r
   CHAR8                                 PeFileName [_MAX_PATH];\r
@@ -2705,10 +2920,11 @@ Returns:
   UINT8                                 *PeFileBuffer;\r
   UINT32                                PeFileSize;\r
   CHAR8                                 *PdbPointer;\r
+  UINT32                                FfsHeaderSize;\r
+  UINT32                                CurSecHdrSize;\r
 \r
   Index              = 0;  \r
   MemoryImagePointer = NULL;\r
-  BaseToUpdate       = NULL;\r
   TEImageHeader      = NULL;\r
   ImgHdr             = NULL;\r
   SectionHeader      = NULL;\r
@@ -2717,26 +2933,21 @@ Returns:
   PeFileBuffer       = NULL;\r
 \r
   //\r
-  // Check XipAddress, BootAddress and RuntimeAddress\r
+  // Don't need to relocate image when BaseAddress is zero and no ForceRebase Flag specified.\r
   //\r
-  Flags   = 0;\r
-  XipBase = 0;\r
-  if (FvInfo->BaseAddress != 0) {\r
-    Flags  |= REBASE_XIP_FILE;\r
-    XipBase = FvInfo->BaseAddress + XipOffset;\r
-  }\r
-  if (FvInfo->BootBaseAddress != 0) {\r
-    Flags  |= REBASE_BOOTTIME_FILE;\r
-  }\r
-  if (FvInfo->RuntimeBaseAddress != 0) {\r
-    Flags  |= REBASE_RUNTIME_FILE;\r
+  if ((FvInfo->BaseAddress == 0) && (FvInfo->ForceRebase == -1)) {\r
+    return EFI_SUCCESS;\r
   }\r
-\r
+  \r
   //\r
-  //  Don't Rebase this FFS.\r
-  //  Only copy the original map file into the FvMap file \r
-  //  for the image that is not required to be relocated.\r
+  // If ForceRebase Flag specified to FALSE, will always not take rebase action.\r
   //\r
+  if (FvInfo->ForceRebase == 0) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+\r
+  XipBase = FvInfo->BaseAddress + XipOffset;\r
 \r
   //\r
   // We only process files potentially containing PE32 sections.\r
@@ -2749,9 +2960,21 @@ Returns:
     case EFI_FV_FILETYPE_DRIVER:\r
     case EFI_FV_FILETYPE_DXE_CORE:\r
       break;\r
+    case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE:\r
+      //\r
+      // Rebase the inside FvImage.\r
+      //\r
+      GetChildFvFromFfs (FvInfo, FfsFile, XipOffset);\r
+\r
+      //\r
+      // Search PE/TE section in FV sectin.\r
+      //\r
+      break;\r
     default:\r
       return EFI_SUCCESS;\r
   }\r
+\r
+  FfsHeaderSize = GetFfsHeaderLength(FfsFile);\r
   //\r
   // Rebase each PE32 section\r
   //\r
@@ -2769,12 +2992,13 @@ Returns:
     if (EFI_ERROR (Status)) {\r
       break;\r
     }\r
+    CurSecHdrSize = GetSectionHeaderLength(CurrentPe32Section.CommonHeader);\r
 \r
     //\r
     // Initialize context\r
     //\r
     memset (&ImageContext, 0, sizeof (ImageContext));\r
-    ImageContext.Handle     = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION));\r
+    ImageContext.Handle     = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + CurSecHdrSize);\r
     ImageContext.ImageRead  = (PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;\r
     Status                  = PeCoffLoaderGetImageInfo (&ImageContext);\r
     if (EFI_ERROR (Status)) {\r
@@ -2782,7 +3006,8 @@ Returns:
       return Status;\r
     }\r
 \r
-    if (ImageContext.Machine == EFI_IMAGE_MACHINE_ARMT) {\r
+    if ( (ImageContext.Machine == EFI_IMAGE_MACHINE_ARMT) ||\r
+         (ImageContext.Machine == EFI_IMAGE_MACHINE_AARCH64) ) {\r
       mArm = TRUE;\r
     }\r
 \r
@@ -2799,7 +3024,7 @@ Returns:
     //\r
     // Get PeHeader pointer\r
     //\r
-    ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION) + ImageContext.PeCoffHeaderOffset);\r
+    ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((UINTN) CurrentPe32Section.Pe32Section + CurSecHdrSize + ImageContext.PeCoffHeaderOffset);\r
 \r
     //\r
     // Calculate the PE32 base address, based on file type\r
@@ -2809,13 +3034,6 @@ Returns:
       case EFI_FV_FILETYPE_PEI_CORE:\r
       case EFI_FV_FILETYPE_PEIM:\r
       case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER:\r
-        if ((Flags & REBASE_XIP_FILE) == 0) {\r
-          //\r
-          // We aren't relocating XIP code, so skip it.\r
-          //\r
-          goto WritePeMap;\r
-        }\r
-        \r
         //\r
         // Check if section-alignment and file-alignment match or not\r
         //\r
@@ -2883,76 +3101,22 @@ Returns:
           ImageContext.RelocationsStripped = FALSE;\r
         }\r
 \r
-        NewPe32BaseAddress = XipBase + (UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION) - (UINTN)FfsFile;\r
-        BaseToUpdate = &XipBase;\r
+        NewPe32BaseAddress = XipBase + (UINTN) CurrentPe32Section.Pe32Section + CurSecHdrSize - (UINTN)FfsFile;\r
         break;\r
 \r
       case EFI_FV_FILETYPE_DRIVER:\r
       case EFI_FV_FILETYPE_DXE_CORE:\r
-        switch (ImgHdr->Pe32.OptionalHeader.Subsystem) {\r
-          case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:\r
-                                               if ((Flags & REBASE_XIP_FILE) == REBASE_XIP_FILE) {\r
-                               //\r
-                               // Check if section-alignment and file-alignment match or not\r
-                               //\r
-                               if ((ImgHdr->Pe32.OptionalHeader.SectionAlignment != ImgHdr->Pe32.OptionalHeader.FileAlignment)) {\r
-                                 //\r
-                                 // Xip module has the same section alignment and file alignment.\r
-                                 //\r
-                                 Error (NULL, 0, 3000, "Invalid", "Section-Alignment and File-Alignment do not match : %s.", FileName);\r
-                                 return EFI_ABORTED;\r
-                               }\r
-                               NewPe32BaseAddress = XipBase + (UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION) - (UINTN)FfsFile;\r
-                               BaseToUpdate = &XipBase;                        \r
-                 } else if ((Flags & REBASE_RUNTIME_FILE) == REBASE_RUNTIME_FILE) {\r
-                   //\r
-                   // make sure image base address at the section alignment\r
-                   //\r
-                   FvInfo->RuntimeBaseAddress = (FvInfo->RuntimeBaseAddress - ImageContext.ImageSize) & (~(ImageContext.SectionAlignment - 1));\r
-                   FvInfo->RuntimeBaseAddress = FvInfo->RuntimeBaseAddress & (~(EFI_PAGE_SIZE - 1));\r
-                   NewPe32BaseAddress = FvInfo->RuntimeBaseAddress;\r
-                   BaseToUpdate = &(FvInfo->RuntimeBaseAddress);\r
-                 } else {\r
-              //\r
-              // RT drivers aren't supposed to be relocated\r
-              //\r
-              goto WritePeMap;\r
-            }\r
-            break;\r
-\r
-          default:\r
-            //\r
-            // We treat all other subsystems the same as BS_DRIVER\r
-            //\r
-                                               if ((Flags & REBASE_XIP_FILE) == REBASE_XIP_FILE) {\r
-                               //\r
-                               // Check if section-alignment and file-alignment match or not\r
-                               //\r
-                               if ((ImgHdr->Pe32.OptionalHeader.SectionAlignment != ImgHdr->Pe32.OptionalHeader.FileAlignment)) {\r
-                                 //\r
-                                 // Xip module has the same section alignment and file alignment.\r
-                                 //\r
-                                 Error (NULL, 0, 3000, "Invalid", "Section-Alignment and File-Alignment do not match : %s.", FileName);\r
-                                 return EFI_ABORTED;\r
-                               }\r
-                               NewPe32BaseAddress = XipBase + (UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION) - (UINTN)FfsFile;\r
-                               BaseToUpdate = &XipBase;                        \r
-                 } else if ((Flags & REBASE_BOOTTIME_FILE) == REBASE_BOOTTIME_FILE) {\r
-                   //\r
-                   // make sure image base address at the Section and Page alignment\r
-                   //\r
-                   FvInfo->BootBaseAddress = (FvInfo->BootBaseAddress - ImageContext.ImageSize) & (~(ImageContext.SectionAlignment - 1));\r
-                   FvInfo->BootBaseAddress = FvInfo->BootBaseAddress & (~(EFI_PAGE_SIZE - 1));\r
-                   NewPe32BaseAddress = FvInfo->BootBaseAddress;\r
-                   BaseToUpdate = &(FvInfo->BootBaseAddress);\r
-                 } else {\r
-              //\r
-              // Skip all BS_DRIVER's\r
-              //\r
-              goto WritePeMap;\r
-            }\r
-            break;\r
+        //\r
+        // Check if section-alignment and file-alignment match or not\r
+        //\r
+        if ((ImgHdr->Pe32.OptionalHeader.SectionAlignment != ImgHdr->Pe32.OptionalHeader.FileAlignment)) {\r
+          //\r
+          // Xip module has the same section alignment and file alignment.\r
+          //\r
+          Error (NULL, 0, 3000, "Invalid", "Section-Alignment and File-Alignment do not match : %s.", FileName);\r
+          return EFI_ABORTED;\r
         }\r
+        NewPe32BaseAddress = XipBase + (UINTN) CurrentPe32Section.Pe32Section + CurSecHdrSize - (UINTN)FfsFile;\r
         break;\r
 \r
       default:\r
@@ -2963,68 +3127,74 @@ Returns:
     }\r
     \r
     //\r
-    // Relocation exist and rebase\r
+    // Relocation doesn't exist\r
     //\r
-    if (!ImageContext.RelocationsStripped) {  \r
-      //\r
-      // Load and Relocate Image Data\r
-      //\r
-      MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);\r
-      if (MemoryImagePointer == NULL) {\r
-        Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName);\r
-        return EFI_OUT_OF_RESOURCES;\r
-      }\r
-      memset ((VOID *) MemoryImagePointer, 0, (UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);\r
-      ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~((INT64)ImageContext.SectionAlignment - 1));\r
-      \r
-      Status =  PeCoffLoaderLoadImage (&ImageContext);\r
-      if (EFI_ERROR (Status)) {\r
-        Error (NULL, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName);\r
-        free ((VOID *) MemoryImagePointer);\r
-        return Status;\r
-      }\r
-           \r
-      ImageContext.DestinationAddress = NewPe32BaseAddress;\r
-      Status                          = PeCoffLoaderRelocateImage (&ImageContext);\r
-      if (EFI_ERROR (Status)) {\r
-        Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName);\r
-        free ((VOID *) MemoryImagePointer);\r
-        return Status;\r
-      }\r
+    if (ImageContext.RelocationsStripped) {\r
+      Warning (NULL, 0, 0, "Invalid", "The file %s has no .reloc section.", FileName);\r
+      continue;\r
+    }\r
 \r
-      //\r
-      // Copy Relocated data to raw image file.\r
-      //\r
-      SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (\r
-                         (UINTN) ImgHdr +\r
-                         sizeof (UINT32) + \r
-                         sizeof (EFI_IMAGE_FILE_HEADER) +  \r
-                         ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader\r
-                         );\r
-      \r
-      for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {\r
-        CopyMem (\r
-          (UINT8 *) CurrentPe32Section.Pe32Section + sizeof (EFI_COMMON_SECTION_HEADER) + SectionHeader->PointerToRawData, \r
-          (VOID*) (UINTN) (ImageContext.ImageAddress + SectionHeader->VirtualAddress), \r
-          SectionHeader->SizeOfRawData\r
-          );\r
-      }\r
-  \r
+    //\r
+    // Relocation exist and rebase\r
+    //\r
+    //\r
+    // Load and Relocate Image Data\r
+    //\r
+    MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);\r
+    if (MemoryImagePointer == NULL) {\r
+      Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    memset ((VOID *) MemoryImagePointer, 0, (UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);\r
+    ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~((UINTN) ImageContext.SectionAlignment - 1));\r
+    \r
+    Status =  PeCoffLoaderLoadImage (&ImageContext);\r
+    if (EFI_ERROR (Status)) {\r
+      Error (NULL, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName);\r
       free ((VOID *) MemoryImagePointer);\r
-      MemoryImagePointer = NULL;\r
-      if (PeFileBuffer != NULL) {\r
-        free (PeFileBuffer);\r
-        PeFileBuffer = NULL;\r
-      }\r
+      return Status;\r
+    }\r
+         \r
+    ImageContext.DestinationAddress = NewPe32BaseAddress;\r
+    Status                          = PeCoffLoaderRelocateImage (&ImageContext);\r
+    if (EFI_ERROR (Status)) {\r
+      Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName);\r
+      free ((VOID *) MemoryImagePointer);\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Copy Relocated data to raw image file.\r
+    //\r
+    SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (\r
+                       (UINTN) ImgHdr +\r
+                       sizeof (UINT32) + \r
+                       sizeof (EFI_IMAGE_FILE_HEADER) +  \r
+                       ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader\r
+                       );\r
+    \r
+    for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {\r
+      CopyMem (\r
+        (UINT8 *) CurrentPe32Section.Pe32Section + CurSecHdrSize + SectionHeader->PointerToRawData, \r
+        (VOID*) (UINTN) (ImageContext.ImageAddress + SectionHeader->VirtualAddress), \r
+        SectionHeader->SizeOfRawData\r
+        );\r
+    }\r
+\r
+    free ((VOID *) MemoryImagePointer);\r
+    MemoryImagePointer = NULL;\r
+    if (PeFileBuffer != NULL) {\r
+      free (PeFileBuffer);\r
+      PeFileBuffer = NULL;\r
     }\r
     \r
     //\r
     // Update Image Base Address\r
     //\r
     if (ImgHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
-      ImgHdr->Pe32.OptionalHeader.ImageBase     = (UINT32) NewPe32BaseAddress;\r
+      ImgHdr->Pe32.OptionalHeader.ImageBase = (UINT32) NewPe32BaseAddress;\r
     } else if (ImgHdr->Pe32Plus.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
-      ImgHdr->Pe32Plus.OptionalHeader.ImageBase     = NewPe32BaseAddress;\r
+      ImgHdr->Pe32Plus.OptionalHeader.ImageBase = NewPe32BaseAddress;\r
     } else {\r
       Error (NULL, 0, 3000, "Invalid", "unknown PE magic signature %X in PE32 image %s",\r
         ImgHdr->Pe32.OptionalHeader.Magic,\r
@@ -3033,11 +3203,6 @@ Returns:
       return EFI_ABORTED;\r
     }\r
 \r
-    //\r
-    // Update BASE address by add one page size.\r
-    //\r
-    *BaseToUpdate -= EFI_PAGE_SIZE;\r
-\r
     //\r
     // Now update file checksum\r
     //\r
@@ -3046,8 +3211,8 @@ Returns:
       FfsFile->IntegrityCheck.Checksum.File = 0;\r
       FfsFile->State                        = 0;\r
       FfsFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (\r
-                                                (UINT8 *) (FfsFile + 1),\r
-                                                GetLength (FfsFile->Size) - sizeof (EFI_FFS_FILE_HEADER)\r
+                                                (UINT8 *) ((UINT8 *)FfsFile + FfsHeaderSize),\r
+                                                GetFfsFileLength (FfsFile) - FfsHeaderSize\r
                                                 );\r
       FfsFile->State = SavedState;\r
     }\r
@@ -3055,7 +3220,7 @@ Returns:
     //\r
     // Get this module function address from ModulePeMapFile and add them into FvMap file\r
     //\r
-WritePeMap:\r
+\r
     //\r
     // Default use FileName as map file path\r
     //\r
@@ -3063,13 +3228,14 @@ WritePeMap:
       PdbPointer = FileName;\r
     }\r
 \r
-    WriteMapFile (FvMapFile, PdbPointer, (EFI_GUID *) FfsFile, NewPe32BaseAddress, &OrigImageContext);\r
+    WriteMapFile (FvMapFile, PdbPointer, FfsFile, NewPe32BaseAddress, &OrigImageContext);\r
   }\r
 \r
   if (FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE &&\r
       FfsFile->Type != EFI_FV_FILETYPE_PEI_CORE &&\r
       FfsFile->Type != EFI_FV_FILETYPE_PEIM &&\r
-      FfsFile->Type != EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER\r
+      FfsFile->Type != EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER &&\r
+      FfsFile->Type != EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE\r
       ) {\r
     //\r
     // Only Peim code may have a TE section\r
@@ -3090,12 +3256,14 @@ WritePeMap:
     if (EFI_ERROR (Status)) {\r
       break;\r
     }\r
+\r
+    CurSecHdrSize = GetSectionHeaderLength(CurrentPe32Section.CommonHeader);\r
     \r
     //\r
     // Calculate the TE base address, the FFS file base plus the offset of the TE section less the size stripped off\r
     // by GenTEImage\r
     //\r
-    TEImageHeader = (EFI_TE_IMAGE_HEADER *) ((UINT8 *) CurrentPe32Section.Pe32Section + sizeof (EFI_COMMON_SECTION_HEADER));\r
+    TEImageHeader = (EFI_TE_IMAGE_HEADER *) ((UINT8 *) CurrentPe32Section.Pe32Section + CurSecHdrSize);\r
 \r
     //\r
     // Initialize context, load image info.\r
@@ -3109,7 +3277,8 @@ WritePeMap:
       return Status;\r
     }\r
 \r
-    if (ImageContext.Machine == EFI_IMAGE_MACHINE_ARMT) {\r
+    if ( (ImageContext.Machine == EFI_IMAGE_MACHINE_ARMT) ||\r
+         (ImageContext.Machine == EFI_IMAGE_MACHINE_AARCH64) ) {\r
       mArm = TRUE;\r
     }\r
 \r
@@ -3122,13 +3291,6 @@ WritePeMap:
     // Get File PdbPointer\r
     //\r
     PdbPointer = PeCoffLoaderGetPdbPointer (ImageContext.Handle);\r
-    \r
-    if ((Flags & REBASE_XIP_FILE) == 0) {\r
-      //\r
-      // For none XIP PEIM module, their map info also are collected.\r
-      //\r
-      goto WriteTeMap;\r
-    }\r
 \r
     //\r
     // Set new rebased address.\r
@@ -3139,7 +3301,7 @@ WritePeMap:
     //\r
     // if reloc is stripped, try to get the original efi image to get reloc info.\r
     //\r
-    if (ImageContext.RelocationsStripped == TRUE) {\r
+    if (ImageContext.RelocationsStripped) {\r
       //\r
       // Construct the original efi file name \r
       //\r
@@ -3194,70 +3356,75 @@ WritePeMap:
         ImageContext.RelocationsStripped = FALSE;\r
       }\r
     }\r
+    //\r
+    // Relocation doesn't exist\r
+    //\r
+    if (ImageContext.RelocationsStripped) {\r
+      Warning (NULL, 0, 0, "Invalid", "The file %s has no .reloc section.", FileName);\r
+      continue;\r
+    }\r
 \r
     //\r
     // Relocation exist and rebase\r
     //\r
-    if (!ImageContext.RelocationsStripped) {\r
-      //\r
-      // Load and Relocate Image Data\r
-      //\r
-      MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);\r
-      if (MemoryImagePointer == NULL) {\r
-        Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName);\r
-        return EFI_OUT_OF_RESOURCES;\r
-      }\r
-      memset ((VOID *) MemoryImagePointer, 0, (UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);\r
-      ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~(ImageContext.SectionAlignment - 1));\r
-  \r
-      Status =  PeCoffLoaderLoadImage (&ImageContext);\r
-      if (EFI_ERROR (Status)) {\r
-        Error (NULL, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName);\r
-        free ((VOID *) MemoryImagePointer);\r
-        return Status;\r
-      }\r
-      //\r
-      // Reloacate TeImage\r
-      // \r
-      ImageContext.DestinationAddress = NewPe32BaseAddress;\r
-      Status                          = PeCoffLoaderRelocateImage (&ImageContext);\r
-      if (EFI_ERROR (Status)) {\r
-        Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of TE image %s", FileName);\r
-        free ((VOID *) MemoryImagePointer);\r
-        return Status;\r
-      }\r
-      \r
-      //\r
-      // Copy the relocated image into raw image file.\r
-      //\r
-      SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (TEImageHeader + 1);\r
-      for (Index = 0; Index < TEImageHeader->NumberOfSections; Index ++, SectionHeader ++) {\r
-        if (!ImageContext.IsTeImage) {\r
-          CopyMem (\r
-            (UINT8 *) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize + SectionHeader->PointerToRawData, \r
-            (VOID*) (UINTN) (ImageContext.ImageAddress + SectionHeader->VirtualAddress), \r
-            SectionHeader->SizeOfRawData\r
-            );\r
-        } else {\r
-          CopyMem (\r
-            (UINT8 *) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize + SectionHeader->PointerToRawData, \r
-            (VOID*) (UINTN) (ImageContext.ImageAddress + sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize + SectionHeader->VirtualAddress), \r
-            SectionHeader->SizeOfRawData\r
-            );\r
-        }\r
-      }\r
-      \r
-      //\r
-      // Free the allocated memory resource\r
-      //\r
+    //\r
+    // Load and Relocate Image Data\r
+    //\r
+    MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);\r
+    if (MemoryImagePointer == NULL) {\r
+      Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    memset ((VOID *) MemoryImagePointer, 0, (UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);\r
+    ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~((UINTN) ImageContext.SectionAlignment - 1));\r
+\r
+    Status =  PeCoffLoaderLoadImage (&ImageContext);\r
+    if (EFI_ERROR (Status)) {\r
+      Error (NULL, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName);\r
+      free ((VOID *) MemoryImagePointer);\r
+      return Status;\r
+    }\r
+    //\r
+    // Reloacate TeImage\r
+    // \r
+    ImageContext.DestinationAddress = NewPe32BaseAddress;\r
+    Status                          = PeCoffLoaderRelocateImage (&ImageContext);\r
+    if (EFI_ERROR (Status)) {\r
+      Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of TE image %s", FileName);\r
       free ((VOID *) MemoryImagePointer);\r
-      MemoryImagePointer = NULL;\r
-      if (PeFileBuffer != NULL) {\r
-        free (PeFileBuffer);\r
-        PeFileBuffer = NULL;\r
+      return Status;\r
+    }\r
+    \r
+    //\r
+    // Copy the relocated image into raw image file.\r
+    //\r
+    SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (TEImageHeader + 1);\r
+    for (Index = 0; Index < TEImageHeader->NumberOfSections; Index ++, SectionHeader ++) {\r
+      if (!ImageContext.IsTeImage) {\r
+        CopyMem (\r
+          (UINT8 *) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize + SectionHeader->PointerToRawData, \r
+          (VOID*) (UINTN) (ImageContext.ImageAddress + SectionHeader->VirtualAddress), \r
+          SectionHeader->SizeOfRawData\r
+          );\r
+      } else {\r
+        CopyMem (\r
+          (UINT8 *) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize + SectionHeader->PointerToRawData, \r
+          (VOID*) (UINTN) (ImageContext.ImageAddress + sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize + SectionHeader->VirtualAddress), \r
+          SectionHeader->SizeOfRawData\r
+          );\r
       }\r
     }\r
     \r
+    //\r
+    // Free the allocated memory resource\r
+    //\r
+    free ((VOID *) MemoryImagePointer);\r
+    MemoryImagePointer = NULL;\r
+    if (PeFileBuffer != NULL) {\r
+      free (PeFileBuffer);\r
+      PeFileBuffer = NULL;\r
+    }\r
+    \r
     //\r
     // Update Image Base Address\r
     //\r
@@ -3271,15 +3438,15 @@ WritePeMap:
       FfsFile->IntegrityCheck.Checksum.File = 0;\r
       FfsFile->State                        = 0;\r
       FfsFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (\r
-                                                (UINT8 *)(FfsFile + 1),\r
-                                                GetLength (FfsFile->Size) - sizeof (EFI_FFS_FILE_HEADER)\r
+                                                (UINT8 *)((UINT8 *)FfsFile + FfsHeaderSize),\r
+                                                GetFfsFileLength (FfsFile) - FfsHeaderSize\r
                                                 );\r
       FfsFile->State = SavedState;\r
     }\r
     //\r
     // Get this module function address from ModulePeMapFile and add them into FvMap file\r
     //\r
-WriteTeMap:\r
+\r
     //\r
     // Default use FileName as map file path\r
     //\r
@@ -3290,7 +3457,7 @@ WriteTeMap:
     WriteMapFile (\r
       FvMapFile, \r
       PdbPointer, \r
-      (EFI_GUID *) FfsFile,\r
+      FfsFile,\r
       NewPe32BaseAddress, \r
       &OrigImageContext\r
       );\r
@@ -3342,12 +3509,12 @@ Returns:
     //\r
     // Get Pad file size.\r
     //\r
-    FileLength = (*(UINT32 *)(PadFile->Size)) & 0x00FFFFFF;\r
+    FileLength = GetFfsFileLength(PadFile);\r
     FileLength = (FileLength + EFI_FFS_FILE_HEADER_ALIGNMENT - 1) & ~(EFI_FFS_FILE_HEADER_ALIGNMENT - 1); \r
     //\r
     // FixPoint must be align on 0x1000 relative to FvImage Header\r
     //\r
-    FixPoint = (UINT8*) PadFile + sizeof (EFI_FFS_FILE_HEADER);\r
+    FixPoint = (UINT8*) PadFile + GetFfsHeaderLength(PadFile);\r
     FixPoint = FixPoint + 0x1000 - (((UINTN) FixPoint - (UINTN) FvImage->FileImage) & 0xFFF);\r
     //\r
     // FixPoint be larger at the last place of one fv image.\r
@@ -3357,7 +3524,7 @@ Returns:
     }\r
     FixPoint -= 0x1000;\r
     \r
-    if ((UINTN) FixPoint < ((UINTN) PadFile + sizeof (EFI_FFS_FILE_HEADER))) {\r
+    if ((UINTN) FixPoint < ((UINTN) PadFile + GetFfsHeaderLength(PadFile))) {\r
       //\r
       // No alignment FixPoint in this Pad File.\r
       //\r
@@ -3462,6 +3629,19 @@ Returns:
     DebugMsg (NULL, 0, 9, "Capsule Flag", Value);\r
   }\r
 \r
+  Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_OEM_CAPSULE_FLAGS_STRING, 0, Value);\r
+  if (Status == EFI_SUCCESS) {\r
+    Status = AsciiStringToUint64 (Value, FALSE, &Value64);\r
+    if (EFI_ERROR (Status) || Value64 > 0xffff) {\r
+      Error (NULL, 0, 2000, "Invalid parameter",\r
+        "invalid Flag setting for %s. Must be integer value between 0x0000 and 0xffff.",\r
+        EFI_OEM_CAPSULE_FLAGS_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+    CapInfo->Flags |= Value64;\r
+    DebugMsg (NULL, 0, 9, "Capsule Extend Flag", Value);\r
+  }\r
+\r
   //\r
   // Read Capsule File name\r
   //\r