]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/C/GenFv/GenFvInternalLib.c
BaseTools: Enhance GenFv Tool to report error message
[mirror_edk2.git] / BaseTools / Source / C / GenFv / GenFvInternalLib.c
index dd0e9ec3be6ae53dedc4ac863da387d686898a31..10bb88b0a88c3625b7aaa5b7c9a7669bd938fe1e 100644 (file)
@@ -1,6 +1,7 @@
 /** @file\r
+This file contains the internal functions required to generate a Firmware Volume.\r
 \r
-Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2004 - 2014, 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
@@ -10,21 +11,18 @@ http://opensource.org/licenses/bsd-license.php
 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
 \r
-Module Name:\r
-\r
-  GenFvInternalLib.c\r
-\r
-Abstract:\r
-\r
-  This file contains the internal functions required to generate a Firmware Volume.\r
-\r
 **/\r
 \r
 //\r
 // Include files\r
 //\r
-#ifdef __GNUC__\r
+\r
+#if defined(__FreeBSD__)\r
+#include <uuid.h>\r
+#elif defined(__GNUC__)\r
 #include <uuid/uuid.h>\r
+#endif\r
+#ifdef __GNUC__\r
 #include <sys/stat.h>\r
 #endif\r
 #include <string.h>\r
@@ -33,6 +31,8 @@ Abstract:
 #endif\r
 #include <assert.h>\r
 \r
+#include <Guid/FfsSectionAlignmentPadding.h>\r
+\r
 #include "GenFvInternalLib.h"\r
 #include "FvLib.h"\r
 #include "PeCoffLib.h"\r
@@ -41,10 +41,11 @@ Abstract:
 BOOLEAN mArm = FALSE;\r
 STATIC UINT32   MaxFfsAlignment = 0;\r
 \r
-EFI_GUID  mEfiFirmwareVolumeTopFileGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;\r
+EFI_GUID  mEfiFirmwareVolumeTopFileGuid       = EFI_FFS_VOLUME_TOP_FILE_GUID;\r
 EFI_GUID  mFileGuidArray [MAX_NUMBER_OF_FILES_IN_FV];\r
-EFI_GUID  mZeroGuid                 = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};\r
-EFI_GUID  mDefaultCapsuleGuid       = {0x3B6686BD, 0x0D76, 0x4030, { 0xB7, 0x0E, 0xB5, 0x51, 0x9E, 0x2F, 0xC5, 0xA0 }};\r
+EFI_GUID  mZeroGuid                           = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};\r
+EFI_GUID  mDefaultCapsuleGuid                 = {0x3B6686BD, 0x0D76, 0x4030, { 0xB7, 0x0E, 0xB5, 0x51, 0x9E, 0x2F, 0xC5, 0xA0 }};\r
+EFI_GUID  mEfiFfsSectionAlignmentPaddingGuid  = EFI_FFS_SECTION_ALIGNMENT_PADDING_GUID;\r
 \r
 CHAR8      *mFvbAttributeName[] = {\r
   EFI_FVB2_READ_DISABLED_CAP_STRING, \r
@@ -159,6 +160,7 @@ 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
@@ -186,7 +188,7 @@ Returns:
   EFI_NOT_FOUND     A required string was not found in the INF file.\r
 --*/\r
 {\r
-  CHAR8       Value[_MAX_PATH];\r
+  CHAR8       Value[MAX_LONG_FILE_PATH];\r
   UINT64      Value64;\r
   UINTN       Index;\r
   UINTN       Number;\r
@@ -280,6 +282,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
@@ -444,9 +459,9 @@ Returns:
 \r
   case 0:\r
     //\r
-    // 8 byte alignment, mini alignment requirement for FFS file. \r
+    // 1 byte alignment\r
     //\r
-    *Alignment = 3;\r
+    *Alignment = 0;\r
     break;\r
 \r
   case 1:\r
@@ -510,7 +525,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
@@ -538,7 +554,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
@@ -546,43 +565,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
@@ -606,9 +627,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
@@ -616,7 +643,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
@@ -634,8 +661,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
@@ -704,7 +731,7 @@ Returns:
 \r
 --*/\r
 {\r
-  CHAR8                               PeMapFileName [_MAX_PATH];\r
+  CHAR8                               PeMapFileName [MAX_LONG_FILE_PATH];\r
   CHAR8                               *Cptr, *Cptr2;\r
   CHAR8                               FileGuidName [MAX_LINE_LEN];\r
   FILE                                *PeMapFile;\r
@@ -840,7 +867,7 @@ Returns:
   //\r
   // Open PeMapFile\r
   //\r
-  PeMapFile = fopen (PeMapFileName, "r");\r
+  PeMapFile = fopen (LongFilePath (PeMapFileName), "r");\r
   if (PeMapFile == NULL) {\r
     // fprintf (stdout, "can't open %s file to reading\n", PeMapFileName);\r
     return EFI_ABORTED;\r
@@ -910,6 +937,153 @@ Returns:
   return EFI_SUCCESS;\r
 }\r
 \r
+STATIC\r
+BOOLEAN\r
+AdjustInternalFfsPadding (\r
+  IN OUT  EFI_FFS_FILE_HEADER   *FfsFile,\r
+  IN OUT  MEMORY_FILE           *FvImage,\r
+  IN      UINTN                 Alignment,\r
+  IN OUT  UINTN                 *FileSize\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function looks for a dedicated alignment padding section in the FFS, and\r
+  shrinks it to the size required to line up subsequent sections correctly.\r
+\r
+Arguments:\r
+\r
+  FfsFile               A pointer to Ffs file image.\r
+  FvImage               The memory image of the FV to adjust it to.\r
+  Alignment             Current file alignment\r
+  FileSize              Reference to a variable holding the size of the FFS file\r
+\r
+Returns:\r
+\r
+  TRUE                  Padding section was found and updated successfully\r
+  FALSE                 Otherwise\r
+\r
+--*/\r
+{\r
+  EFI_FILE_SECTION_POINTER  PadSection;\r
+  UINT8                     *Remainder;\r
+  EFI_STATUS                Status;\r
+  UINT32                    FfsHeaderLength;\r
+  UINT32                    FfsFileLength;\r
+  UINT32                    PadSize;\r
+  UINTN                     Misalignment;\r
+  EFI_FFS_INTEGRITY_CHECK   *IntegrityCheck;\r
+\r
+  //\r
+  // Figure out the misalignment: all FFS sections are aligned relative to the\r
+  // start of the FFS payload, so use that as the base of the misalignment\r
+  // computation.\r
+  //\r
+  FfsHeaderLength = GetFfsHeaderLength(FfsFile);\r
+  Misalignment = (UINTN) FvImage->CurrentFilePointer -\r
+                 (UINTN) FvImage->FileImage + FfsHeaderLength;\r
+  Misalignment &= Alignment - 1;\r
+  if (Misalignment == 0) {\r
+    // Nothing to do, return success\r
+    return TRUE;\r
+  }\r
+\r
+  //\r
+  // We only apply this optimization to FFS files with the FIXED attribute set,\r
+  // since the FFS will not be loadable at arbitrary offsets anymore after\r
+  // we adjust the size of the padding section.\r
+  //\r
+  if ((FfsFile->Attributes & FFS_ATTRIB_FIXED) == 0) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Look for a dedicated padding section that we can adjust to compensate\r
+  // for the misalignment. If such a padding section exists, it precedes all\r
+  // sections with alignment requirements, and so the adjustment will correct\r
+  // all of them.\r
+  //\r
+  Status = GetSectionByType (FfsFile, EFI_SECTION_FREEFORM_SUBTYPE_GUID, 1,\r
+             &PadSection);\r
+  if (EFI_ERROR (Status) ||\r
+      CompareGuid (&PadSection.FreeformSubtypeSection->SubTypeGuid,\r
+        &mEfiFfsSectionAlignmentPaddingGuid) != 0) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Find out if the size of the padding section is sufficient to compensate\r
+  // for the misalignment.\r
+  //\r
+  PadSize = GetSectionFileLength (PadSection.CommonHeader);\r
+  if (Misalignment > PadSize - sizeof (EFI_FREEFORM_SUBTYPE_GUID_SECTION)) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Move the remainder of the FFS file towards the front, and adjust the\r
+  // file size output parameter.\r
+  //\r
+  Remainder = (UINT8 *) PadSection.CommonHeader + PadSize;\r
+  memmove (Remainder - Misalignment, Remainder,\r
+           *FileSize - (UINTN) (Remainder - (UINTN) FfsFile));\r
+  *FileSize -= Misalignment;\r
+\r
+  //\r
+  // Update the padding section's length with the new values. Note that the\r
+  // padding is always < 64 KB, so we can ignore EFI_COMMON_SECTION_HEADER2\r
+  // ExtendedSize.\r
+  //\r
+  PadSize -= Misalignment;\r
+  PadSection.CommonHeader->Size[0] = (UINT8) (PadSize & 0xff);\r
+  PadSection.CommonHeader->Size[1] = (UINT8) ((PadSize & 0xff00) >> 8);\r
+  PadSection.CommonHeader->Size[2] = (UINT8) ((PadSize & 0xff0000) >> 16);\r
+\r
+  //\r
+  // Update the FFS header with the new overall length\r
+  //\r
+  FfsFileLength = GetFfsFileLength (FfsFile) - Misalignment;\r
+  if (FfsHeaderLength > sizeof(EFI_FFS_FILE_HEADER)) {\r
+    ((EFI_FFS_FILE_HEADER2 *)FfsFile)->ExtendedSize = FfsFileLength;\r
+  } else {\r
+    FfsFile->Size[0] = (UINT8) (FfsFileLength & 0x000000FF);\r
+    FfsFile->Size[1] = (UINT8) ((FfsFileLength & 0x0000FF00) >> 8);\r
+    FfsFile->Size[2] = (UINT8) ((FfsFileLength & 0x00FF0000) >> 16);\r
+  }\r
+\r
+  //\r
+  // Clear the alignment bits: these have become meaningless now that we have\r
+  // adjusted the padding section.\r
+  //\r
+  FfsFile->Attributes &= ~FFS_ATTRIB_DATA_ALIGNMENT;\r
+\r
+  //\r
+  // Recalculate the FFS header checksum. Instead of setting Header and State\r
+  // both to zero, set Header to (UINT8)(-State) so State preserves its original\r
+  // value\r
+  //\r
+  IntegrityCheck = &FfsFile->IntegrityCheck;\r
+  IntegrityCheck->Checksum.Header = (UINT8) (0x100 - FfsFile->State);\r
+  IntegrityCheck->Checksum.File = 0;\r
+\r
+  IntegrityCheck->Checksum.Header = CalculateChecksum8 (\r
+                                      (UINT8 *) FfsFile, FfsHeaderLength);\r
+\r
+  if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {\r
+    //\r
+    // Ffs header checksum = zero, so only need to calculate ffs body.\r
+    //\r
+    IntegrityCheck->Checksum.File = CalculateChecksum8 (\r
+                                      (UINT8 *) FfsFile + FfsHeaderLength,\r
+                                      FfsFileLength - FfsHeaderLength);\r
+  } else {\r
+    IntegrityCheck->Checksum.File = FFS_FIXED_CHECKSUM;\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
 EFI_STATUS\r
 AddFile (\r
   IN OUT MEMORY_FILE          *FvImage,\r
@@ -966,7 +1140,7 @@ Returns:
   //\r
   // Read the file to add\r
   //\r
-  NewFile = fopen (FvInfo->FvFiles[Index], "rb");\r
+  NewFile = fopen (LongFilePath (FvInfo->FvFiles[Index]), "rb");\r
 \r
   if (NewFile == NULL) {\r
     Error (NULL, 0, 0001, "Error opening file", FvInfo->FvFiles[Index]);\r
@@ -1078,7 +1252,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
@@ -1116,11 +1290,14 @@ Returns:
   //\r
   // Add pad file if necessary\r
   //\r
-  Status = AddPadFile (FvImage, 1 << CurrentFileAlignment, *VtfFileImage, NULL);\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
-    return EFI_ABORTED;\r
+  if (!AdjustInternalFfsPadding ((EFI_FFS_FILE_HEADER *) FileBuffer, FvImage,\r
+         1 << CurrentFileAlignment, &FileSize)) {\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
+      return EFI_ABORTED;\r
+    }\r
   }\r
   //\r
   // Add file\r
@@ -1190,6 +1367,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
@@ -1219,9 +1397,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
@@ -1229,7 +1416,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
@@ -1297,6 +1484,8 @@ Returns:
   UINT64                    FitAddress;\r
   FIT_TABLE                 *FitTablePtr;\r
   BOOLEAN                   Vtf0Detected;\r
+  UINT32                    FfsHeaderSize;\r
+  UINT32                    SecHeaderSize;\r
 \r
   //\r
   // Verify input parameters\r
@@ -1359,8 +1548,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
@@ -1388,7 +1578,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
@@ -1413,8 +1603,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
@@ -1428,7 +1619,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
@@ -1598,9 +1789,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
@@ -1720,7 +1912,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
@@ -1734,7 +1926,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 + 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
@@ -1768,7 +1960,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
@@ -1789,7 +1981,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
@@ -1813,7 +2005,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
@@ -1827,7 +2019,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 + 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
@@ -2036,12 +2228,12 @@ Returns:
   UINT8                           *FvImage;\r
   UINTN                           FvImageSize;\r
   FILE                            *FvFile;\r
-  CHAR8                           FvMapName [_MAX_PATH];\r
+  CHAR8                           FvMapName [MAX_LONG_FILE_PATH];\r
   FILE                            *FvMapFile;\r
   EFI_FIRMWARE_VOLUME_EXT_HEADER  *FvExtHeader;\r
   FILE                            *FvExtHeaderFile;\r
   UINTN                           FileSize;\r
-  CHAR8                           FvReportName[_MAX_PATH];\r
+  CHAR8                           FvReportName[MAX_LONG_FILE_PATH];\r
   FILE                            *FvReportFile;\r
 \r
   FvBufferHeader = NULL;\r
@@ -2111,7 +2303,7 @@ Returns:
     //\r
     // Open the FV Extension Header file\r
     //\r
-    FvExtHeaderFile = fopen (mFvDataInfo.FvExtHeaderFile, "rb");\r
+    FvExtHeaderFile = fopen (LongFilePath (mFvDataInfo.FvExtHeaderFile), "rb");\r
 \r
     //\r
     // Get the file size\r
@@ -2171,7 +2363,8 @@ Returns:
                   mFvDataInfo.FvNameGuid.Data4[7]);\r
   }\r
 \r
-  if (CompareGuid (&mFvDataInfo.FvFileSystemGuid, &mEfiFirmwareFileSystem2Guid) == 0) {\r
+  if (CompareGuid (&mFvDataInfo.FvFileSystemGuid, &mEfiFirmwareFileSystem2Guid) == 0 ||\r
+    CompareGuid (&mFvDataInfo.FvFileSystemGuid, &mEfiFirmwareFileSystem3Guid) == 0) {\r
     mFvDataInfo.IsPiFvImage = TRUE;\r
   }\r
 \r
@@ -2301,7 +2494,7 @@ Returns:
   //\r
   // Open FvMap file\r
   //\r
-  FvMapFile = fopen (FvMapName, "w");\r
+  FvMapFile = fopen (LongFilePath (FvMapName), "w");\r
   if (FvMapFile == NULL) {\r
     Error (NULL, 0, 0001, "Error opening file", FvMapName);\r
     return EFI_ABORTED;\r
@@ -2310,7 +2503,7 @@ Returns:
   //\r
   // Open FvReport file\r
   //\r
-  FvReportFile = fopen(FvReportName, "w");\r
+  FvReportFile = fopen (LongFilePath (FvReportName), "w");\r
   if (FvReportFile == NULL) {\r
     Error (NULL, 0, 0001, "Error opening file", FvReportName);\r
     return EFI_ABORTED;\r
@@ -2344,7 +2537,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
@@ -2419,7 +2612,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
@@ -2428,11 +2622,20 @@ 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
   //\r
-  FvFile = fopen (FvFileName, "wb");\r
+  FvFile = fopen (LongFilePath (FvFileName), "wb");\r
   if (FvFile == NULL) {\r
     Error (NULL, 0, 0001, "Error opening file", FvFileName);\r
     Status = EFI_ABORTED;\r
@@ -2564,6 +2767,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
@@ -2598,14 +2802,19 @@ Returns:
   // Calculate PI extension header\r
   //\r
   if (mFvDataInfo.FvExtHeaderFile[0] != '\0') {\r
-    fpin = fopen (mFvDataInfo.FvExtHeaderFile, "rb");\r
+    fpin = fopen (LongFilePath (mFvDataInfo.FvExtHeaderFile), "rb");\r
     if (fpin == NULL) {\r
       Error (NULL, 0, 0001, "Error opening file", mFvDataInfo.FvExtHeaderFile);\r
       return EFI_ABORTED;\r
     }\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
@@ -2620,7 +2829,7 @@ Returns:
     // Open FFS file\r
     //\r
     fpin = NULL;\r
-    fpin = fopen (FvInfoPtr->FvFiles[Index], "rb");\r
+    fpin = fopen (LongFilePath (FvInfoPtr->FvFiles[Index]), "rb");\r
     if (fpin == NULL) {\r
       Error (NULL, 0, 0001, "Error opening file", FvInfoPtr->FvFiles[Index]);\r
       return EFI_ABORTED;\r
@@ -2629,6 +2838,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
@@ -2639,17 +2854,18 @@ Returns:
     fclose (fpin);\r
     \r
     if (FvInfoPtr->IsPiFvImage) {\r
-           //\r
-           // Check whether this ffs file is vtf file\r
-           //\r
-           if (IsVtfFile (&FfsHeader)) {\r
-             if (VtfFileFlag) {\r
-               //\r
-               // One Fv image can't have two vtf files.\r
-               //\r
-               return EFI_ABORTED;\r
-             }\r
-             VtfFileFlag = TRUE;\r
+        //\r
+        // Check whether this ffs file is vtf file\r
+        //\r
+        if (IsVtfFile (&FfsHeader)) {\r
+          if (VtfFileFlag) {\r
+            //\r
+            // One Fv image can't have two vtf files.\r
+            //\r
+            Error (NULL, 0, 3000,"Invalid", "One Fv image can't have two vtf files.");\r
+            return EFI_ABORTED;\r
+          }\r
+          VtfFileFlag = TRUE;\r
         VtfFileSize = FfsFileSize;\r
         continue;\r
       }\r
@@ -2662,9 +2878,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
@@ -2792,7 +3011,7 @@ Returns:
     if (EFI_ERROR (Status)) {\r
       break;\r
     }\r
-    SubFvImageHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINT8 *) SubFvSection.FVImageSection + sizeof (EFI_FIRMWARE_VOLUME_IMAGE_SECTION));\r
+    SubFvImageHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINT8 *) SubFvSection.FVImageSection + GetSectionHeaderLength(SubFvSection.FVImageSection));\r
     //\r
     // Rebase on Flash\r
     //\r
@@ -2848,12 +3067,14 @@ Returns:
   EFI_TE_IMAGE_HEADER                   *TEImageHeader;\r
   UINT8                                 *MemoryImagePointer;\r
   EFI_IMAGE_SECTION_HEADER              *SectionHeader;\r
-  CHAR8                                 PeFileName [_MAX_PATH];\r
+  CHAR8                                 PeFileName [MAX_LONG_FILE_PATH];\r
   CHAR8                                 *Cptr;\r
   FILE                                  *PeFile;\r
   UINT8                                 *PeFileBuffer;\r
   UINT32                                PeFileSize;\r
   CHAR8                                 *PdbPointer;\r
+  UINT32                                FfsHeaderSize;\r
+  UINT32                                CurSecHdrSize;\r
 \r
   Index              = 0;  \r
   MemoryImagePointer = NULL;\r
@@ -2905,6 +3126,8 @@ Returns:
     default:\r
       return EFI_SUCCESS;\r
   }\r
+\r
+  FfsHeaderSize = GetFfsHeaderLength(FfsFile);\r
   //\r
   // Rebase each PE32 section\r
   //\r
@@ -2922,12 +3145,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
@@ -2953,7 +3177,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
@@ -2994,7 +3218,7 @@ Returns:
             *(Cptr + 3) = 'i';\r
             *(Cptr + 4) = '\0';\r
           }\r
-          PeFile = fopen (PeFileName, "rb");\r
+          PeFile = fopen (LongFilePath (PeFileName), "rb");\r
           if (PeFile == NULL) {\r
             Warning (NULL, 0, 0, "Invalid", "The file %s has no .reloc section.", FileName);\r
             //Error (NULL, 0, 3000, "Invalid", "The file %s has no .reloc section.", FileName);\r
@@ -3030,7 +3254,7 @@ Returns:
           ImageContext.RelocationsStripped = FALSE;\r
         }\r
 \r
-        NewPe32BaseAddress = XipBase + (UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION) - (UINTN)FfsFile;\r
+        NewPe32BaseAddress = XipBase + (UINTN) CurrentPe32Section.Pe32Section + CurSecHdrSize - (UINTN)FfsFile;\r
         break;\r
 \r
       case EFI_FV_FILETYPE_DRIVER:\r
@@ -3045,7 +3269,7 @@ Returns:
           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
+        NewPe32BaseAddress = XipBase + (UINTN) CurrentPe32Section.Pe32Section + CurSecHdrSize - (UINTN)FfsFile;\r
         break;\r
 \r
       default:\r
@@ -3104,7 +3328,7 @@ Returns:
     \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
+        (UINT8 *) CurrentPe32Section.Pe32Section + CurSecHdrSize + SectionHeader->PointerToRawData, \r
         (VOID*) (UINTN) (ImageContext.ImageAddress + SectionHeader->VirtualAddress), \r
         SectionHeader->SizeOfRawData\r
         );\r
@@ -3140,8 +3364,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
@@ -3185,12 +3409,14 @@ Returns:
     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
@@ -3248,7 +3474,7 @@ Returns:
         *(Cptr + 4) = '\0';\r
       }\r
 \r
-      PeFile = fopen (PeFileName, "rb");\r
+      PeFile = fopen (LongFilePath (PeFileName), "rb");\r
       if (PeFile == NULL) {\r
         Warning (NULL, 0, 0, "Invalid", "The file %s has no .reloc section.", FileName);\r
         //Error (NULL, 0, 3000, "Invalid", "The file %s has no .reloc section.", FileName);\r
@@ -3365,8 +3591,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
@@ -3436,12 +3662,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
@@ -3451,7 +3677,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
@@ -3493,7 +3719,7 @@ Returns:
   EFI_NOT_FOUND     A required string was not found in the INF file.\r
 --*/\r
 {\r
-  CHAR8       Value[_MAX_PATH];\r
+  CHAR8       Value[MAX_LONG_FILE_PATH];\r
   UINT64      Value64;\r
   UINTN       Index, Number;\r
   EFI_STATUS  Status;\r
@@ -3556,6 +3782,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
@@ -3686,7 +3925,7 @@ Returns:
   FileSize = 0;\r
   CapSize  = mCapDataInfo.HeaderSize;\r
   while (mCapDataInfo.CapFiles [Index][0] != '\0') {\r
-    fpin = fopen (mCapDataInfo.CapFiles[Index], "rb");\r
+    fpin = fopen (LongFilePath (mCapDataInfo.CapFiles[Index]), "rb");\r
     if (fpin == NULL) {\r
       Error (NULL, 0, 0001, "Error opening file", mCapDataInfo.CapFiles[Index]);\r
       return EFI_ABORTED;\r
@@ -3724,7 +3963,7 @@ Returns:
   FileSize = 0;\r
   CapSize  = CapsuleHeader->HeaderSize;\r
   while (mCapDataInfo.CapFiles [Index][0] != '\0') {\r
-    fpin = fopen (mCapDataInfo.CapFiles[Index], "rb");\r
+    fpin = fopen (LongFilePath (mCapDataInfo.CapFiles[Index]), "rb");\r
     if (fpin == NULL) {\r
       Error (NULL, 0, 0001, "Error opening file", mCapDataInfo.CapFiles[Index]);\r
       free (CapBuffer);\r
@@ -3740,7 +3979,7 @@ Returns:
   //\r
   // write capsule data into the output file\r
   //\r
-  fpout = fopen (CapFileName, "wb");\r
+  fpout = fopen (LongFilePath (CapFileName), "wb");\r
   if (fpout == NULL) {\r
     Error (NULL, 0, 0001, "Error opening file", CapFileName);\r
     free (CapBuffer);\r