Update GenFw and GenFv tool to support more features based on base tools spec.
authorlgao4 <lgao4@7335b38e-4728-0410-8992-fb3ffe349368>
Thu, 12 Jul 2007 02:43:56 +0000 (02:43 +0000)
committerlgao4 <lgao4@7335b38e-4728-0410-8992-fb3ffe349368>
Thu, 12 Jul 2007 02:43:56 +0000 (02:43 +0000)
git-svn-id: https://buildtools.tianocore.org/svn/buildtools/trunk/BaseTools@308 7335b38e-4728-0410-8992-fb3ffe349368

Source/C/GenFv/GenFv.c
Source/C/GenFv/GenFvInternalLib.c
Source/C/GenFv/GenFvInternalLib.h
Source/C/GenFw/GenFw.c
Source/C/PeCoffLoader/BasePeCoff.c

index 1dd2447..ff3bf6b 100644 (file)
@@ -43,6 +43,11 @@ Abstract:
 #define UTILITY_MAJOR_VERSION 0\r
 #define UTILITY_MINOR_VERSION 1\r
 \r
+EFI_STATUS\r
+ParseCapInf (\r
+  IN  MEMORY_FILE  *InfFile,\r
+  OUT CAP_INFO     *CapInfo\r
+  );\r
 \r
 static\r
 void \r
@@ -94,9 +99,10 @@ Returns:
   Version();\r
 \r
   printf ("\nUsage: " UTILITY_NAME "\n\\r
-        -i, --inputfile [FileName (FV.inf)]\n\\r
+        -i, --inputfile [FileName (FV.inf or Cap.inf)]\n\\r
         -o, --outputfile [FileName (FileName.fv)]\n\\r
         -r, --baseaddress (0x##### or #####)\n\\r
+        -c, --capsule\n\\r
         -h, --help\n\\r
         -V, --version\n");\r
 }\r
@@ -131,18 +137,35 @@ Returns:
 \r
 --*/\r
 {\r
-  EFI_STATUS  Status;\r
-  CHAR8       *InfFileName;\r
-  CHAR8       *InfFileImage;\r
-  UINTN       InfFileSize;\r
-  CHAR8       *FvFileName;\r
-  EFI_PHYSICAL_ADDRESS XipBase;\r
+  EFI_STATUS            Status;\r
+  CHAR8                 *InfFileName;\r
+  CHAR8                 *InfFileImage;\r
+  UINTN                 InfFileSize;\r
+  CHAR8                 *OutFileName;\r
+  EFI_PHYSICAL_ADDRESS  XipBase;\r
+  UINT8                 CapsuleFlag;\r
+  CAP_INFO              CapInfo;\r
+  MEMORY_FILE           InfMemoryFile;\r
+  FILE                  *fpin, *fpout;\r
+  UINT32                FileSize;\r
+  UINT32                CapSize;\r
+  UINT8                 *CapBuffer;\r
+  EFI_CAPSULE_HEADER    *CapsuleHeader;\r
+  UINT32                Index;\r
 \r
   InfFileName   = NULL;\r
   InfFileImage  = NULL;\r
-  FvFileName    = NULL;\r
+  OutFileName   = NULL;\r
   XipBase       = -1;\r
   InfFileSize   = 0;\r
+  CapsuleFlag   = 0;\r
+  fpin          = NULL;\r
+  fpout         = NULL;\r
+  FileSize      = 0;\r
+  CapSize       = 0;\r
+  Index         = 0;\r
+  CapBuffer     = NULL;\r
+  CapsuleHeader = NULL;\r
 \r
   SetUtilityName (UTILITY_NAME);\r
 \r
@@ -179,8 +202,8 @@ Returns:
     }\r
 \r
     if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) {\r
-      FvFileName = argv[1];\r
-      if (FvFileName == NULL) {\r
+      OutFileName = argv[1];\r
+      if (OutFileName == NULL) {\r
         Warning (NULL, 0, 0, NULL, "No output file specified.");\r
       }\r
       argc -= 2;\r
@@ -198,7 +221,13 @@ Returns:
       argv += 2;\r
       continue; \r
     }\r
-    \r
+\r
+    if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--capsule") == 0)) {\r
+      CapsuleFlag = 1;\r
+      argc --;\r
+      argv ++;\r
+      continue; \r
+    }\r
     //\r
     // Don't recognize the paramter.\r
     //\r
@@ -215,54 +244,245 @@ Returns:
   }\r
 \r
   //\r
-  // Call the GenFvImageFunction to generate Fv Image\r
+  // Create Capsule Header\r
   //\r
-  Status = GenerateFvImage (\r
-            InfFileImage,\r
-            InfFileSize,\r
-            FvFileName,\r
-            XipBase\r
-            );\r
+  if (CapsuleFlag) {\r
+    //\r
+    // Initialize file structures\r
+    //\r
+    InfMemoryFile.FileImage           = InfFileImage;\r
+    InfMemoryFile.CurrentFilePointer  = InfFileImage;\r
+    InfMemoryFile.Eof                 = InfFileImage + InfFileSize;\r
 \r
+    //\r
+    // Parse the Cap inf file for header information\r
+    //\r
+    Status = ParseCapInf (&InfMemoryFile, &CapInfo);\r
+    if (Status != EFI_SUCCESS) {\r
+      goto Finish;\r
+    }\r
+    \r
+    if (CapInfo.HeaderSize == 0) {\r
+      CapInfo.HeaderSize = sizeof (EFI_CAPSULE_HEADER);\r
+    }\r
+\r
+    if (CapInfo.HeaderSize < sizeof (EFI_CAPSULE_HEADER)) {\r
+      Error (NULL, 0, 0, NULL, "The specified HeaderSize can't be less than the size of EFI_CAPSULE_HEADER.");\r
+      goto Finish;\r
+    }\r
+    \r
+    //\r
+    // Calculate the size of capsule image.\r
+    //\r
+    Index    = 0;\r
+    FileSize = 0;\r
+    CapSize  = sizeof (EFI_CAPSULE_HEADER);\r
+    while (CapInfo.CapFiles [Index][0] != '\0') {\r
+      fpin = fopen (CapInfo.CapFiles[Index], "rb");\r
+      if (fpin == NULL) {\r
+        Error (NULL, 0, 0, NULL, "%s could not open for reading", CapInfo.CapFiles[Index]);\r
+        goto Finish;\r
+      }\r
+      FileSize  = _filelength (fileno (fpin));\r
+      CapSize  += FileSize;\r
+      fclose (fpin);\r
+      Index ++;\r
+    }\r
+\r
+    //\r
+    // Allocate buffer for capsule image.\r
+    //\r
+    CapBuffer = (UINT8 *) malloc (CapSize);\r
+    if (CapBuffer == NULL) {\r
+      Error (NULL, 0, 0, NULL, "could not allocate enough memory space for capsule");\r
+      goto Finish;\r
+    }\r
+\r
+    //\r
+    // Initialize the capsule header to zero\r
+    //\r
+    memset (CapBuffer, 0, sizeof (EFI_CAPSULE_HEADER));\r
+    \r
+    //\r
+    // create capsule header and get capsule body\r
+    //\r
+    CapsuleHeader = (EFI_CAPSULE_HEADER *) CapBuffer;\r
+    memcpy (&CapsuleHeader->CapsuleGuid, &CapInfo.CapGuid, sizeof (EFI_GUID));\r
+    CapsuleHeader->HeaderSize       = CapInfo.HeaderSize;\r
+    CapsuleHeader->Flags            = CapInfo.Flags;\r
+    CapsuleHeader->CapsuleImageSize = CapSize;\r
+\r
+    Index    = 0;\r
+    FileSize = 0;\r
+    CapSize  = CapsuleHeader->HeaderSize;\r
+    while (CapInfo.CapFiles [Index][0] != '\0') {\r
+      fpin = fopen (CapInfo.CapFiles[Index], "rb");\r
+      if (fpin == NULL) {\r
+        Error (NULL, 0, 0, NULL, "%s could not open for reading", CapInfo.CapFiles[Index]);\r
+        goto Finish;\r
+      }\r
+      FileSize = _filelength (fileno (fpin));\r
+      fread (CapBuffer + CapSize, 1, FileSize, fpin);\r
+      fclose (fpin);\r
+      Index ++;\r
+      CapSize += FileSize;\r
+    }\r
+    \r
+    //\r
+    // write capsule data into the output file\r
+    //\r
+    if (OutFileName == NULL) {\r
+      fpout = stdout;\r
+    } else {\r
+      fpout = fopen (OutFileName, "wb");\r
+      if (fpout == NULL) {\r
+        Error (NULL, 0, 0, NULL, "could not open %s file for writing", OutFileName);\r
+        free (CapBuffer);\r
+        goto Finish;\r
+      }\r
+    }\r
+    fwrite (CapBuffer, 1, CapSize, fpout);\r
+    fclose (fpout);\r
+\r
+  } else {\r
+    //\r
+    // Call the GenFvImageFunction to generate Fv Image\r
+    //\r
+    GenerateFvImage (\r
+      InfFileImage,\r
+      InfFileSize,\r
+      OutFileName,\r
+      XipBase\r
+      );\r
+  }\r
+\r
+Finish:\r
   //\r
   // free InfFileImage memory\r
   //\r
   free (InfFileImage);\r
 \r
-  if (EFI_ERROR (Status)) {\r
-    switch (Status) {\r
+  return GetUtilityStatus ();\r
+}\r
 \r
-    case EFI_INVALID_PARAMETER:\r
-      Error (NULL, 0, 0, "invalid parameter passed to GenerateFvImage", NULL);\r
-      return GetUtilityStatus ();\r
-      break;\r
+EFI_STATUS\r
+ParseCapInf (\r
+  IN  MEMORY_FILE  *InfFile,\r
+  OUT CAP_INFO     *CapInfo\r
+  )\r
+/*++\r
 \r
-    case EFI_ABORTED:\r
-      Error (NULL, 0, 0, "error detected while creating the file image", NULL);\r
-      return GetUtilityStatus ();\r
-      break;\r
+Routine Description:\r
 \r
-    case EFI_OUT_OF_RESOURCES:\r
-      Error (NULL, 0, 0, "GenFvImage Lib could not allocate required resources", NULL);\r
-      return GetUtilityStatus ();\r
-      break;\r
+  This function parses a Cap.INF file and copies info into a CAP_INFO structure.\r
 \r
-    case EFI_VOLUME_CORRUPTED:\r
-      Error (NULL, 0, 0, "no base address was specified, but the FV.INF included a PEI or BSF file", NULL);\r
-      return GetUtilityStatus ();\r
-      break;\r
+Arguments:\r
 \r
-    case EFI_LOAD_ERROR:\r
-      Error (NULL, 0, 0, "could not load FV image generation library", NULL);\r
-      return GetUtilityStatus ();\r
-      break;\r
+  InfFile        Memory file image.\r
+  CapInfo        Information read from INF file.\r
+\r
+Returns:\r
 \r
-    default:\r
-      Error (NULL, 0, 0, "GenFvImage Lib returned unknown status", "status returned = 0x%X", Status);\r
-      return GetUtilityStatus ();\r
+  EFI_SUCCESS       INF file information successfully retrieved.\r
+  EFI_ABORTED       INF file has an invalid format.\r
+  EFI_NOT_FOUND     A required string was not found in the INF file.\r
+--*/\r
+{\r
+  CHAR8       Value[_MAX_PATH];\r
+  UINT64      Value64;\r
+  UINTN       Index;\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // Initialize Cap info\r
+  //\r
+  memset (CapInfo, 0, sizeof (CAP_INFO));\r
+\r
+  //\r
+  // Read the Capsule Guid\r
+  //\r
+  Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_CAPSULE_GUID_STRING, 0, Value);\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Get the Capsule Guid\r
+    //\r
+    Status = StringToGuid (Value, &CapInfo->CapGuid);\r
+    if (EFI_ERROR (Status)) {\r
+      Error (NULL, 0, 0, EFI_CAPSULE_GUID_STRING, "not valid guid value");\r
+      return EFI_ABORTED;\r
+    }\r
+  } else {\r
+    Error (NULL, 0, 0, EFI_CAPSULE_GUID_STRING, "is not specified.");\r
+    return EFI_ABORTED;\r
+  }\r
+\r
+  //\r
+  // Read the Capsule Header Size\r
+  //\r
+  Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_CAPSULE_HEADER_SIZE_STRING, 0, Value);\r
+  if (Status == EFI_SUCCESS) {\r
+    Status = AsciiStringToUint64 (Value, FALSE, &Value64);\r
+    if (EFI_ERROR (Status)) {\r
+      Error (NULL, 0, 0, Value, "invalid value for %s", EFI_CAPSULE_HEADER_SIZE_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+    CapInfo->HeaderSize = (UINT32) Value64;\r
+  }\r
+\r
+  //\r
+  // Read the Capsule Flag\r
+  //\r
+  Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_CAPSULE_FLAGS_STRING, 0, Value);\r
+  if (Status == EFI_SUCCESS) {\r
+    if (stricmp (Value, "PersistAcrossReset") == 0) {\r
+      CapInfo->Flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET; \r
+    } else if (stricmp (Value, "PopulateSystemTable") == 0) {\r
+      CapInfo->Flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE;\r
+    } else {\r
+      Error (NULL, 0, 0, Value, "invalid Flag setting for %s", EFI_CAPSULE_FLAGS_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+  }\r
+  \r
+  //\r
+  // Read the Capsule Version\r
+  //\r
+  Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_CAPSULE_VERSION_STRING, 0, Value);\r
+  if (Status == EFI_SUCCESS) {\r
+    if (stricmp (Value, "UEFI") == 0) {\r
+      CapInfo->Version = 0x20000;  \r
+    } else if (stricmp (Value, "FRAMEWORK") == 0) {\r
+      CapInfo->Version = 0x10010;\r
+      Error (NULL, 0, 0, Value, "is not supported Version for %s", EFI_CAPSULE_VERSION_STRING);\r
+      return EFI_ABORTED;\r
+    } else {\r
+      Error (NULL, 0, 0, Value, "invalid Version setting for %s", EFI_CAPSULE_VERSION_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Read the Capsule FileImage\r
+  //\r
+  for (Index = 0; Index < MAX_NUMBER_OF_FILES_IN_CAP; Index++) {\r
+    //\r
+    // Read the capsule file name\r
+    //\r
+    Status = FindToken (InfFile, FILES_SECTION_STRING, EFI_FILE_NAME_STRING, Index, Value);\r
+\r
+    if (Status == EFI_SUCCESS) {\r
+      //\r
+      // Add the file\r
+      //\r
+      strcpy (CapInfo->CapFiles[Index], Value);\r
+    } else {\r
       break;\r
     }\r
   }\r
+  \r
+  if (Index == 0) {\r
+    printf("Cap Files are not specified.\n");\r
+  }\r
 \r
-  return GetUtilityStatus ();\r
-}\r
+  return EFI_SUCCESS;\r
+}
\ No newline at end of file
index 8da3295..f137414 100644 (file)
@@ -38,6 +38,12 @@ Abstract:
 #include "EfiUtilityMsgs.h"\r
 #include "WinNtInclude.h"\r
 \r
+EFI_STATUS\r
+FindApResetVectorPosition (\r
+  IN  MEMORY_FILE  *FvImage,\r
+  OUT UINT8        **Pointer\r
+  ); \r
+\r
 EFI_STATUS\r
 CalculateFvSize (\r
   FV_INFO *FvInfoPtr\r
@@ -620,7 +626,7 @@ Returns:
   // Subtract the starting offset to get size\r
   //\r
   PadFileSize -= (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage;\r
-\r
+  \r
   //\r
   // Write pad file size (calculated size minus next file header size)\r
   //\r
@@ -1031,6 +1037,7 @@ Returns:
   EFI_PHYSICAL_ADDRESS      PeiCorePhysicalAddress;\r
   EFI_PHYSICAL_ADDRESS      SecCorePhysicalAddress;\r
   EFI_PHYSICAL_ADDRESS      *SecCoreEntryAddressPtr;\r
+  INT32                     Ia32SecEntryOffset;\r
   UINT32                    *Ia32ResetAddressPtr;\r
   UINT8                     *BytePointer;\r
   UINT8                     *BytePointer2;\r
@@ -1040,6 +1047,7 @@ Returns:
   EFI_FFS_FILE_STATE        SavedState;\r
   UINT64                    FitAddress;\r
   FIT_TABLE                 *FitTablePtr;\r
+  UINT32                    IpiVector;\r
 \r
   //\r
   // Verify input parameters\r
@@ -1059,6 +1067,46 @@ Returns:
   if (EFI_ERROR (Status)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
+\r
+  //\r
+  // Find the Sec Core\r
+  //\r
+  Status = GetFileByType (EFI_FV_FILETYPE_SECURITY_CORE, 1, &SecCoreFile);\r
+  if (EFI_ERROR (Status) || SecCoreFile == NULL) {\r
+    Error (NULL, 0, 0, "could not find the Sec core in the FV", NULL);\r
+    return EFI_ABORTED;\r
+  }\r
+  //\r
+  // Sec Core found, now find PE32 section\r
+  //\r
+  Status = GetSectionByType (SecCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);\r
+  if (Status == EFI_NOT_FOUND) {\r
+    Status = GetSectionByType (SecCoreFile, EFI_SECTION_TE, 1, &Pe32Section);\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    Error (NULL, 0, 0, "could not find PE32 section in SEC core file", NULL);\r
+    return EFI_ABORTED;\r
+  }\r
+\r
+  Status = GetPe32Info (\r
+            (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),\r
+            &EntryPoint,\r
+            &BaseOfCode,\r
+            &MachineType\r
+            );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    Error (NULL, 0, 0, "could not get PE32 entry point for SEC core", NULL);\r
+    return EFI_ABORTED;\r
+  }\r
+  //\r
+  // 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 += EntryPoint;\r
+\r
   //\r
   // Find the PEI Core\r
   //\r
@@ -1067,7 +1115,6 @@ Returns:
     Error (NULL, 0, 0, "could not find the PEI core in the FV", NULL);\r
     return EFI_ABORTED;\r
   }\r
-\r
   //\r
   // PEI Core found, now find PE32 or TE section\r
   //\r
@@ -1130,39 +1177,6 @@ Returns:
     if (!EFI_ERROR (Status)) {\r
       UpdateFitCheckSum (FitTablePtr);\r
     }\r
-    //\r
-    // Find the Sec Core\r
-    //\r
-    Status = GetFileByType (EFI_FV_FILETYPE_SECURITY_CORE, 1, &SecCoreFile);\r
-    if (EFI_ERROR (Status) || SecCoreFile == NULL) {\r
-      Error (NULL, 0, 0, "could not find the Sec core in the FV", NULL);\r
-      return EFI_ABORTED;\r
-    }\r
-    //\r
-    // Sec Core found, now find PE32 section\r
-    //\r
-    Status = GetSectionByType (SecCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);\r
-    if (EFI_ERROR (Status)) {\r
-      Error (NULL, 0, 0, "could not find PE32 section in SEC core file", NULL);\r
-      return EFI_ABORTED;\r
-    }\r
-\r
-    Status = GetPe32Info (\r
-              (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),\r
-              &EntryPoint,\r
-              &BaseOfCode,\r
-              &MachineType\r
-              );\r
-    if (EFI_ERROR (Status)) {\r
-      Error (NULL, 0, 0, "could not get PE32 entry point for SEC core", NULL);\r
-      return EFI_ABORTED;\r
-    }\r
-    //\r
-    // 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 += EntryPoint;\r
 \r
     //\r
     // Update SEC_CORE address\r
@@ -1191,12 +1205,25 @@ Returns:
     //\r
     // Get the location to update\r
     //\r
-    Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - IA32_PEI_CORE_ENTRY_OFFSET);\r
+    Ia32ResetAddressPtr  = (UINT32 *) ((UINTN) FvImage->Eof - IA32_PEI_CORE_ENTRY_OFFSET);\r
 \r
     //\r
-    // Write lower 32 bits of physical address\r
+    // Write lower 32 bits of physical address for Pei Core entry\r
     //\r
     *Ia32ResetAddressPtr = (UINT32) PeiCorePhysicalAddress;\r
+    \r
+    //\r
+    // Write SecCore Entry point relative address into the jmp instruction in reset vector.\r
+    // \r
+    Ia32ResetAddressPtr  = (UINT32 *) ((UINTN) FvImage->Eof - IA32_SEC_CORE_ENTRY_OFFSET);\r
+    \r
+    Ia32SecEntryOffset   = SecCorePhysicalAddress - (FV_IMAGES_TOP_ADDRESS - IA32_SEC_CORE_ENTRY_OFFSET + 2);\r
+    if (Ia32SecEntryOffset <= -65536) {\r
+      Error (NULL, 0, 0, NULL, "The SEC EXE file size is too big");\r
+      return STATUS_ERROR;\r
+    }\r
+    \r
+    *(UINT16 *) Ia32ResetAddressPtr = (UINT16) Ia32SecEntryOffset;\r
 \r
     //\r
     // Update the BFV base address\r
@@ -1204,20 +1231,37 @@ Returns:
     Ia32ResetAddressPtr   = (UINT32 *) ((UINTN) FvImage->Eof - 4);\r
     *Ia32ResetAddressPtr  = (UINT32) (FvInfo->BaseAddress);\r
 \r
-    CheckSum              = 0x0000;\r
-\r
     //\r
     // Update the Startup AP in the FVH header block ZeroVector region.\r
     //\r
     BytePointer   = (UINT8 *) ((UINTN) FvImage->FileImage);\r
-    BytePointer2  = (FvInfo->Size == 0x10000) ? m64kRecoveryStartupApDataArray : m128kRecoveryStartupApDataArray;\r
+    if (FvInfo->Size == 0x10000) {\r
+      BytePointer2 = m64kRecoveryStartupApDataArray;\r
+    } else if (FvInfo->Size == 0x20000) {\r
+      BytePointer2 = m128kRecoveryStartupApDataArray;\r
+    } else if (FvInfo->Size > 0x20000) {\r
+      BytePointer2 = m128kRecoveryStartupApDataArray;\r
+      //\r
+      // Find the position to place Ap reset vector, the offset\r
+      // between the position and the end of Fvrecovery.fv file\r
+      // should not exceed 128kB to prevent Ap reset vector from\r
+      // outside legacy E and F segment\r
+      //\r
+      Status = FindApResetVectorPosition (FvImage, &BytePointer);\r
+      if (EFI_ERROR (Status)) {\r
+        Error (NULL, 0, 0, NULL, "Can't find the appropriate space in FvImage to add Ap reset vector!");\r
+        return EFI_ABORTED;\r
+      }\r
+    }\r
+\r
     for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY; Index++) {\r
-      *BytePointer++ = *BytePointer2++;\r
+      BytePointer[Index] = BytePointer2[Index];\r
     }\r
     //\r
     // Calculate the checksum\r
     //\r
-    WordPointer = (UINT16 *) ((UINTN) FvImage->FileImage);\r
+    CheckSum              = 0x0000;\r
+    WordPointer = (UINT16 *) (BytePointer);\r
     for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY / 2; Index++) {\r
       CheckSum = (UINT16) (CheckSum + ((UINT16) *WordPointer));\r
       WordPointer++;\r
@@ -1225,10 +1269,21 @@ Returns:
     //\r
     // Update the checksum field\r
     //\r
-    BytePointer = (UINT8 *) ((UINTN) FvImage->FileImage);\r
-    BytePointer += (SIZEOF_STARTUP_DATA_ARRAY - 2);\r
-    WordPointer   = (UINT16 *) BytePointer;\r
+    WordPointer   = (UINT16 *) (BytePointer + SIZEOF_STARTUP_DATA_ARRAY - 2);\r
     *WordPointer  = (UINT16) (0x10000 - (UINT32) CheckSum);\r
+    \r
+    //\r
+    // IpiVector at the 4k aligned address in the top 2 blocks in the PEI FV. \r
+    //\r
+    IpiVector  = FV_IMAGES_TOP_ADDRESS - ((UINTN) FvImage->Eof - (UINTN) BytePointer);\r
+    IpiVector  = IpiVector >> 12;\r
+    IpiVector  = IpiVector & 0xFF;\r
+\r
+    //\r
+    // Write IPI Vector at Offset FvrecoveryFileSize - 8\r
+    //\r
+    Ia32ResetAddressPtr   = (UINT32 *) ((UINTN) FvImage->Eof - 8);\r
+    *Ia32ResetAddressPtr  = IpiVector;\r
   } else {\r
     Error (NULL, 0, 0, "invalid machine type in PEI core", "machine type=0x%X", (UINT32) MachineType);\r
     return EFI_ABORTED;\r
@@ -2001,7 +2056,7 @@ Returns:
           //\r
           // Xip module has the same section alignment and file alignment.\r
           //\r
-          Warning (NULL, 0, 0, "Section-Alignment and File-Alignment does not match", FileName);\r
+          printf("Section-Alignment and File-Alignment does not match : %s\n", FileName);\r
           return EFI_ABORTED;\r
         }\r
 \r
@@ -2231,4 +2286,67 @@ Returns:
   }\r
  \r
   return EFI_SUCCESS;\r
-}
\ No newline at end of file
+}\r
+\r
+EFI_STATUS\r
+FindApResetVectorPosition (\r
+  IN  MEMORY_FILE  *FvImage,\r
+  OUT UINT8        **Pointer\r
+  )\r
+{\r
+  EFI_FFS_FILE_HEADER   *PadFile;\r
+  UINT32                Index;\r
+  EFI_STATUS            Status;\r
+  UINT8                 *FixPoint;\r
+  UINT32                FileLength;\r
+\r
+  for (Index = 1; ;Index ++) {\r
+    //\r
+    // Find Pad File to add ApResetVector info\r
+    //\r
+    Status = GetFileByType (EFI_FV_FILETYPE_FFS_PAD, Index, &PadFile);\r
+    if (EFI_ERROR (Status) || (PadFile == NULL)) {\r
+      //\r
+      // No Pad file to be found.\r
+      //\r
+      break;\r
+    }\r
+    //\r
+    // Get Pad file size.\r
+    //\r
+    FileLength = (*(UINT32 *)(PadFile->Size)) & 0x00FFFFFF;\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 = FixPoint + 0x1000 - (((UINTN) FixPoint - (UINTN) FvImage->FileImage) & 0xFFF);\r
+    //\r
+    // FixPoint be larger at the last place of one fv image.\r
+    //\r
+    while (((UINTN) FixPoint + SIZEOF_STARTUP_DATA_ARRAY - (UINTN) PadFile) <= FileLength) {\r
+      FixPoint += 0x1000;\r
+    }\r
+    FixPoint -= 0x1000;\r
+    \r
+    if ((UINTN) FixPoint < ((UINTN) PadFile + sizeof (EFI_FFS_FILE_HEADER))) {\r
+      //\r
+      // No alignment FixPoint in this Pad File.\r
+      //\r
+      continue;\r
+    }\r
+\r
+    if ((UINTN) FvImage->Eof - (UINTN)FixPoint <= 0x20000) {    \r
+      //\r
+      // Find the position to place ApResetVector\r
+      //\r
+      *Pointer = FixPoint;\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+  \r
+  return EFI_NOT_FOUND;\r
+}\r
+  \r
+  \r
+  
\ No newline at end of file
index 606e147..a74de6f 100644 (file)
@@ -30,6 +30,7 @@ Abstract:
 \r
 #include <Common/UefiBaseTypes.h>\r
 #include <Common/MultiPhase.h>\r
+#include <Common/UefiCapsule.h>\r
 \r
 #include <Common/FirmwareVolumeImageFormat.h>\r
 #include <Common/PiFirmwareVolumeHeader.h>\r
@@ -66,6 +67,7 @@ Abstract:
 // The maximum number of files in the FV supported by the library\r
 //\r
 #define MAX_NUMBER_OF_FILES_IN_FV       1000\r
+#define MAX_NUMBER_OF_FILES_IN_CAP      1000\r
 #define EFI_FFS_FILE_HEADER_ALIGNMENT   8\r
 \r
 //\r
@@ -83,6 +85,10 @@ Abstract:
 #define EFI_NUM_BLOCKS_STRING             "EFI_NUM_BLOCKS"\r
 #define EFI_BLOCK_SIZE_STRING             "EFI_BLOCK_SIZE"\r
 #define EFI_FV_GUID_STRING                "EFI_FV_GUID"\r
+#define EFI_CAPSULE_GUID_STRING           "EFI_CAPSULE_GUID"\r
+#define EFI_CAPSULE_HEADER_SIZE_STRING    "EFI_CAPSULE_HEADER_SIZE"\r
+#define EFI_CAPSULE_FLAGS_STRING          "EFI_CAPSULE_FLAGS"\r
+#define EFI_CAPSULE_VERSION_STRING        "EFI_CAPSULE_VERSION"\r
 \r
 //\r
 // Attributes section\r
@@ -156,6 +162,11 @@ Abstract:
 //\r
 #define IA32_PEI_CORE_ENTRY_OFFSET    0x20\r
 \r
+//\r
+// Defines to calculate the offset for IA32 SEC CORE entry point\r
+//\r
+#define IA32_SEC_CORE_ENTRY_OFFSET     0xD\r
+\r
 //\r
 // Defines to calculate the FIT table\r
 //\r
@@ -215,6 +226,14 @@ typedef struct {
   CHAR8                   FvFiles[MAX_NUMBER_OF_FILES_IN_FV][_MAX_PATH];\r
 } FV_INFO;\r
 \r
+typedef struct {\r
+  EFI_GUID                CapGuid;\r
+  UINT32                  HeaderSize;\r
+  UINT32                  Flags;\r
+  UINT32                  Version;\r
+  CHAR8                   CapFiles[MAX_NUMBER_OF_FILES_IN_CAP][_MAX_PATH];\r
+} CAP_INFO;\r
+\r
 #pragma pack(1)\r
 \r
 typedef struct {\r
index a474010..0ebdff5 100644 (file)
@@ -66,14 +66,34 @@ Abstract:
 \r
 UINT8 *InImageName;\r
 \r
-#define FW_DUMMY_IMAGE   0\r
-#define FW_EFI_IMAGE     1\r
-#define FW_TE_IMAGE      2\r
-#define FW_ACPI_IMAGE    3\r
-\r
+#define FW_DUMMY_IMAGE       0\r
+#define FW_EFI_IMAGE         1\r
+#define FW_TE_IMAGE          2\r
+#define FW_ACPI_IMAGE        3\r
+#define FW_BIN_IMAGE         4\r
+#define FW_ZERO_DEBUG_IMAGE  5\r
+#define FW_SET_STAMP_IMAGE   6\r
+\r
+#define DUMP_TE_HEADER       0x11\r
+#define FW_REPLACE_IMAGE     0x100\r
+\r
\r
 #define MAX_STRING_LENGTH 100\r
 \r
 STATIC\r
+EFI_STATUS\r
+ZeroDebugData (\r
+  IN OUT UINT8   *FileBuffer\r
+  );\r
+\r
+STATIC \r
+EFI_STATUS\r
+SetStamp (\r
+  IN OUT UINT8  *FileBuffer, \r
+  IN     CHAR8  *TimeStamp\r
+  );\r
+\r
+static\r
 VOID\r
 Version (\r
   VOID\r
@@ -99,6 +119,11 @@ Usage (
                         BS_DRIVER|RT_DRIVER|SAL_RT_DRIVER|APPLICATION>\n\\r
         -c, --acpi\n\\r
         -t, --terse\n\\r
+        -u, --dump\n\\r
+        -z, --zero\n\\r
+        -b, --exe2bin\n\\r
+        -r, --replace\n\\r
+        -s, --stamp [time-data] <NOW|\"####-##-## ##:##:##\">\n\\r
         -h, --help\n\\r
         -V, --version\n");\r
 }\r
@@ -282,40 +307,6 @@ FCopyFile (
   return STATUS_SUCCESS;\r
 }\r
 \r
-static\r
-STATUS\r
-FReadFile (\r
-  FILE    *in,\r
-  VOID    **Buffer,\r
-  UINTN   *Length\r
-  )\r
-{\r
-  fseek (in, 0, SEEK_END);\r
-  *Length = ftell (in);\r
-  *Buffer = malloc (*Length);\r
-  fseek (in, 0, SEEK_SET);\r
-  fread (*Buffer, *Length, 1, in);\r
-  return STATUS_SUCCESS;\r
-}\r
-\r
-static\r
-STATUS\r
-FWriteFile (\r
-  FILE    *out,\r
-  VOID    *Buffer,\r
-  UINTN   Length\r
-  )\r
-{\r
-  fseek (out, 0, SEEK_SET);\r
-  fwrite (Buffer, Length, 1, out);\r
-  if ((UINT32 ) ftell (out) != Length) {\r
-    Error (NULL, 0, 0, "write error", NULL);\r
-    return STATUS_ERROR;\r
-  }\r
-  free (Buffer);\r
-  return STATUS_SUCCESS;\r
-}\r
-\r
 #ifdef HAVE_ELF
 INTN
 IsElfHeader(
@@ -903,11 +894,12 @@ Returns:
   UINT32            Type;\r
   UINT8             *OutImageName;\r
   UINT8             *ModuleType;\r
+  CHAR8             *TimeStamp;\r
   CHAR8             FileName[MAX_STRING_LENGTH];\r
-  UINT            OutImageType;\r
+  UINT32            OutImageType;\r
   FILE              *fpIn;\r
   FILE              *fpOut;\r
-  VOID              *ZeroBuffer;\r
+  FILE              *fpInOut;\r
   UINT32            Index;\r
   UINT32            Index1;\r
   UINT32            Index2;\r
@@ -941,6 +933,8 @@ Returns:
   FileBuffer        = NULL;\r
   fpIn              = NULL;\r
   fpOut             = NULL;\r
+  fpInOut           = NULL;\r
+  TimeStamp         = NULL;\r
 \r
   if (argc == 1) {\r
     Usage();\r
@@ -992,6 +986,42 @@ Returns:
       continue;\r
     }\r
 \r
+    if ((stricmp (argv[0], "-u") == 0) || (stricmp (argv[0], "--dump") == 0)) {\r
+      OutImageType = DUMP_TE_HEADER;\r
+      argc --;\r
+      argv ++;\r
+      continue;\r
+    }\r
+\r
+    if ((stricmp (argv[0], "-b") == 0) || (stricmp (argv[0], "--exe2bin") == 0)) {\r
+      OutImageType = FW_BIN_IMAGE;\r
+      argc --;\r
+      argv ++;\r
+      continue;\r
+    }\r
+\r
+    if ((stricmp (argv[0], "-z") == 0) || (stricmp (argv[0], "--zero") == 0)) {\r
+      OutImageType = FW_ZERO_DEBUG_IMAGE;\r
+      argc --;\r
+      argv ++;\r
+      continue;\r
+    }\r
+\r
+    if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--stamp") == 0)) {\r
+      OutImageType = FW_SET_STAMP_IMAGE;\r
+      TimeStamp    = argv[1];\r
+      argc -= 2;\r
+      argv += 2;\r
+      continue;\r
+    }\r
+\r
+    if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--replace") == 0)) {\r
+      OutImageType |= FW_REPLACE_IMAGE;\r
+      argc --;\r
+      argv ++;\r
+      continue;\r
+    }\r
+\r
     InImageName = argv[0];\r
     argc --;\r
     argv ++;\r
@@ -1003,6 +1033,68 @@ Returns:
     return STATUS_ERROR;    \r
   }\r
 \r
+\r
+  //\r
+  // get InImageName from stdin\r
+  //\r
+  if (InImageName == NULL) {\r
+    fscanf (stdin, "%s", FileName);\r
+    InImageName = (UINT8 *) FileName;\r
+  }\r
+\r
+  //\r
+  // Open input file and read file data into file buffer.\r
+  //\r
+  fpIn = fopen (InImageName, "rb");\r
+  if (!fpIn) {\r
+    Error (NULL, 0, 0, InImageName, "failed to open input file for reading");\r
+    goto Finish;\r
+  }\r
+\r
+  FileLength = _filelength (fileno (fpIn));\r
+  FileBuffer = malloc (FileLength);\r
+  if (FileBuffer == NULL) {\r
+    Error (NULL, 0, 0, NULL, "can't allocate enough memory space");\r
+    fclose (fpIn);\r
+    goto Finish;\r
+  }\r
+  \r
+  fread (FileBuffer, 1, FileLength, fpIn);\r
+  fclose (fpIn);\r
+\r
+  //\r
+  // Open output file and Write image into the output file.\r
+  // if OutImageName == NULL, output data to stdout.\r
+  //\r
+  if (OutImageName == NULL) {\r
+    if ((OutImageType & FW_REPLACE_IMAGE) != 0) {\r
+      fpOut = fopen (InImageName, "wb");\r
+      if (!fpOut) {\r
+        Error (NULL, 0, 0, InImageName, "could not open input file for modify");\r
+        goto Finish;\r
+      }\r
+      OutImageType = OutImageType & ~FW_REPLACE_IMAGE;\r
+    } else {\r
+      // binary stream can't be output to string strem stdout\r
+      // because 0x0A can be auto converted to 0x0D 0x0A.\r
+      fpOut = stdout;\r
+    } \r
+  } else {\r
+    fpOut = fopen (OutImageName, "wb");\r
+    if (!fpOut) {\r
+      Error (NULL, 0, 0, OutImageName, "could not open output file for writing");\r
+      goto Finish;\r
+    }\r
+    if ((OutImageType & FW_REPLACE_IMAGE) != 0) {\r
+      fpInOut = fopen (InImageName, "wb");\r
+      if (!fpInOut) {\r
+        Error (NULL, 0, 0, InImageName, "could not open input file for modify");\r
+        goto Finish;\r
+      }\r
+      OutImageType = OutImageType & ~FW_REPLACE_IMAGE;\r
+    }\r
+  }
+\r
   //\r
   // Following code to convert dll to efi image or te image.\r
   // Get new image type\r
@@ -1047,42 +1139,30 @@ Returns:
       goto Finish;\r
     }\r
   }\r
-\r
-  //\r
-  // get InImageName from stdin\r
-  //\r
-  if (InImageName == NULL) {\r
-    fscanf (stdin, "%s", FileName);\r
-    InImageName = (UINT8 *) FileName;\r
-  }\r
-\r
\r
   //\r
-  // Open input file\r
+  // Dump TeImage Header into output file.\r
   //\r
-  fpIn = fopen (InImageName, "rb");\r
-  if (!fpIn) {\r
-    Error (NULL, 0, 0, InImageName, "failed to open input file for reading");\r
+  if (OutImageType == DUMP_TE_HEADER) {\r
+    memcpy (&TEImageHeader, FileBuffer, sizeof (TEImageHeader));\r
+    if (TEImageHeader.Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
+      Error (NULL, 0, 0, InImageName, "TE header signature is not correct");\r
+      goto Finish;      \r
+    }\r
+    fprintf (fpOut, "Dump of file %s\n\n", InImageName);\r
+    fprintf (fpOut, "TE IMAGE HEADER VALUES\n");\r
+    fprintf (fpOut, "%17X machine\n", TEImageHeader.Machine);\r
+    fprintf (fpOut, "%17X number of sections\n", TEImageHeader.NumberOfSections);\r
+    fprintf (fpOut, "%17X subsystems\n", TEImageHeader.Subsystem);\r
+    fprintf (fpOut, "%17X stripped size\n", TEImageHeader.StrippedSize);\r
+    fprintf (fpOut, "%17X entry point\n", TEImageHeader.AddressOfEntryPoint);\r
+    fprintf (fpOut, "%17X base of code\n", TEImageHeader.BaseOfCode);\r
+    fprintf (fpOut, "%17X image base\n", TEImageHeader.ImageBase);\r
+    fprintf (fpOut, "%17X [%8X] RVA [size] of Base Relocation Directory\n", TEImageHeader.DataDirectory[0].VirtualAddress, TEImageHeader.DataDirectory[0].Size);\r
+    fprintf (fpOut, "%17X [%8X] RVA [size] of Debug Directory\n", TEImageHeader.DataDirectory[1].VirtualAddress, TEImageHeader.DataDirectory[1].Size);\r
     goto Finish;\r
   }\r
 \r
-  FReadFile (fpIn, (VOID **)&FileBuffer, &FileLength);\r
-  fclose (fpIn);\r
-\r
-  //\r
-  // Open output file and Write image into the output file.\r
-  // if OutImageName == NULL, output data to stdout.\r
-  //\r
-  if (OutImageName == NULL) {\r
-    fpOut = stdout; // binary stream can't be output to string strem stdout\r
-                    // because 0x0A can be auto converted to 0x0D 0x0A.\r
-  } else {\r
-    fpOut = fopen (OutImageName, "w+b");\r
-  }\r
-  if (!fpOut) {\r
-    Error (NULL, 0, 0, OutImageName, "could not open output file for writing");\r
-    goto Finish;\r
-  }
-\r
   //\r
   // Convert EFL image to PeImage\r
   //\r
@@ -1107,6 +1187,59 @@ Returns:
     goto Finish;\r
   }\r
   \r
+  //\r
+  // Extract bin data from Pe image.\r
+  //\r
+  if (OutImageType == FW_BIN_IMAGE) {\r
+    if (FileLength < PeHdr->OptionalHeader.SizeOfHeaders) {\r
+      Error (NULL, 0, 0, InImageName, "FileSize is not a legal size.");\r
+      goto Finish;\r
+    }\r
+    //\r
+    // Output bin data from exe file\r
+    //\r
+    fwrite (FileBuffer + PeHdr->OptionalHeader.SizeOfHeaders, 1, FileLength - PeHdr->OptionalHeader.SizeOfHeaders, fpOut);\r
+    if (fpInOut != NULL) {\r
+      fwrite (FileBuffer + PeHdr->OptionalHeader.SizeOfHeaders, 1, FileLength - PeHdr->OptionalHeader.SizeOfHeaders, fpInOut);\r
+    }\r
+    goto Finish;\r
+  }\r
+\r
+  //\r
+  // Zero Debug Information of Pe Image\r
+  //\r
+  if (OutImageType == FW_ZERO_DEBUG_IMAGE) {\r
+    Status = ZeroDebugData (FileBuffer);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Finish;\r
+    }\r
+\r
+    fwrite (FileBuffer, 1, FileLength, fpOut);\r
+    if (fpInOut != NULL) {\r
+      fwrite (FileBuffer, 1, FileLength, fpInOut);\r
+    }\r
+    goto Finish; \r
+  }\r
+\r
+  //\r
+  // Set Time Stamp of Pe Image\r
+  //\r
+  if (OutImageType == FW_SET_STAMP_IMAGE) {\r
+    Status = SetStamp (FileBuffer, TimeStamp);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Finish;\r
+    }\r
+\r
+    fwrite (FileBuffer, 1, FileLength, fpOut);\r
+    if (fpInOut != NULL) {\r
+      fwrite (FileBuffer, 1, FileLength, fpInOut);\r
+    }\r
+    goto Finish;\r
+  }\r
+\r
+  //\r
+  // Extract acpi data from pe image.\r
+  //\r
   if (OutImageType == FW_ACPI_IMAGE) {\r
     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->OptionalHeader) + PeHdr->FileHeader.SizeOfOptionalHeader); \r
     for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index ++, SectionHeader ++) {\r
@@ -1128,10 +1261,11 @@ Returns:
         //\r
         // Output Apci data to file\r
         //\r
-        memcpy (FileBuffer, FileBuffer + SectionHeader->PointerToRawData, FileLength);\r
-        FWriteFile (fpOut, FileBuffer, FileLength);\r
-        fclose (fpOut);\r
-        return STATUS_SUCCESS;\r
+        fwrite (FileBuffer + SectionHeader->PointerToRawData, 1, FileLength, fpOut);\r
+        if (fpInOut != NULL) {\r
+          fwrite (FileBuffer + SectionHeader->PointerToRawData, 1, FileLength, fpInOut);\r
+        }\r
+        goto Finish;\r
       }\r
     }\r
     Error (NULL, 0, 0, InImageName, "failed to get ACPI table");\r
@@ -1351,13 +1485,22 @@ Returns:
     //\r
     // Update Image to TeImage\r
     //\r
-    FileLength = FileLength - TEImageHeader.StrippedSize;\r
-    memcpy (FileBuffer + sizeof (EFI_TE_IMAGE_HEADER), FileBuffer + TEImageHeader.StrippedSize, FileLength);\r
-    memcpy (FileBuffer, &TEImageHeader, sizeof (EFI_TE_IMAGE_HEADER));\r
+    fwrite (&TEImageHeader, 1, sizeof (EFI_TE_IMAGE_HEADER), fpOut);\r
+    fwrite (FileBuffer + TEImageHeader.StrippedSize, 1, FileLength - TEImageHeader.StrippedSize, fpOut);\r
+    if (fpInOut != NULL) {\r
+      fwrite (&TEImageHeader, 1, sizeof (EFI_TE_IMAGE_HEADER), fpOut);\r
+      fwrite (FileBuffer + TEImageHeader.StrippedSize, 1, FileLength - TEImageHeader.StrippedSize, fpOut);\r
+    }\r
+    goto Finish;\r
+  }\r
+  \r
+  //\r
+  // Update Image to EfiImage\r
+  //\r
+  fwrite (FileBuffer, 1, FileLength, fpOut);\r
+  if (fpInOut != NULL) {\r
+    fwrite (FileBuffer, 1, FileLength, fpInOut);\r
   }\r
-\r
-  FWriteFile (fpOut, FileBuffer, FileLength);\r
-  FileBuffer = NULL;\r
 \r
 Finish:\r
   if (FileBuffer != NULL) {\r
@@ -1370,6 +1513,264 @@ Finish:
     //\r
     fclose (fpOut);\r
   }\r
-  \r
+\r
+  if (fpInOut != NULL) {\r
+    //\r
+    // Write converted data into fpInOut file and close input file.\r
+    //\r
+    fclose (fpInOut);\r
+  }\r
+\r
   return GetUtilityStatus ();\r
 }\r
+\r
+STATIC\r
+EFI_STATUS\r
+ZeroDebugData (\r
+  IN OUT UINT8   *FileBuffer\r
+  )\r
+{\r
+  UINTN                           Index;\r
+  UINTN                           DebugDirectoryEntryRva;\r
+  UINTN                           DebugDirectoryEntryFileOffset;\r
+  EFI_IMAGE_DOS_HEADER            *DosHdr;\r
+  EFI_IMAGE_FILE_HEADER           *FileHdr;\r
+  EFI_IMAGE_OPTIONAL_HEADER32     *Optional32Hdr;\r
+  EFI_IMAGE_OPTIONAL_HEADER64     *Optional64Hdr;\r
+  EFI_IMAGE_SECTION_HEADER        *SectionHeader;\r
+  EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;\r
+   \r
+  DosHdr   = (EFI_IMAGE_DOS_HEADER *)  FileBuffer;\r
+  FileHdr  = (EFI_IMAGE_FILE_HEADER *) (FileBuffer + DosHdr->e_lfanew + sizeof (UINT32));\r
+  DebugDirectoryEntryRva = 0;\r
+\r
+  //\r
+  // Get DebugEntryTable RVA address.\r
+  //\r
+  if (FileHdr->Machine == EFI_IMAGE_MACHINE_IA32) {\r
+    Optional32Hdr = (EFI_IMAGE_OPTIONAL_HEADER32 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));\r
+    SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional32Hdr +  FileHdr->SizeOfOptionalHeader);\r
+    if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \\r
+        Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {\r
+      DebugDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
+    } else {\r
+      //\r
+      // No Debug Data, nothing to do.\r
+      //\r
+      return EFI_SUCCESS;\r
+    }\r
+  } else {\r
+    Optional64Hdr = (EFI_IMAGE_OPTIONAL_HEADER64 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));\r
+    SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional64Hdr +  FileHdr->SizeOfOptionalHeader);\r
+    if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \\r
+        Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {\r
+      DebugDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
+    } else {\r
+      //\r
+      // No Debug Data, nothing to do.\r
+      //\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+  \r
+  //\r
+  // Get DebugEntryTable file offset.\r
+  //\r
+  for (Index = 0; Index < FileHdr->NumberOfSections; Index ++, SectionHeader ++) {\r
+    if (DebugDirectoryEntryRva >= SectionHeader->VirtualAddress &&\r
+        DebugDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {\r
+        DebugDirectoryEntryFileOffset =\r
+        DebugDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;\r
+      break;\r
+    }\r
+  }\r
+  \r
+  if (Index >= FileHdr->NumberOfSections) {\r
+    Error (NULL, 0, 0, NULL, "Invalid PeImage.");\r
+    return EFI_ABORTED;\r
+  }\r
+  \r
+  //\r
+  // Zero Debug Data and TimeStamp\r
+  //\r
+  DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (FileBuffer + DebugDirectoryEntryFileOffset);\r
+  DebugEntry->TimeDateStamp = 0;\r
+  memset (FileBuffer + DebugEntry->FileOffset, 0, DebugEntry->SizeOfData);\r
+  \r
+  return EFI_SUCCESS;\r
+}\r
+\r
+STATIC \r
+EFI_STATUS\r
+SetStamp (\r
+  IN OUT UINT8  *FileBuffer, \r
+  IN     CHAR8  *TimeStamp\r
+  )\r
+{\r
+  struct tm stime;\r
+  time_t    newtime;\r
+  UINTN                           Index;\r
+  UINTN                           DebugDirectoryEntryRva;\r
+  UINTN                           DebugDirectoryEntryFileOffset;\r
+  UINTN                           ExportDirectoryEntryRva;\r
+  UINTN                           ExportDirectoryEntryFileOffset;\r
+  UINTN                           ResourceDirectoryEntryRva;\r
+  UINTN                           ResourceDirectoryEntryFileOffset;\r
+  EFI_IMAGE_DOS_HEADER            *DosHdr;\r
+  EFI_IMAGE_FILE_HEADER           *FileHdr;\r
+  EFI_IMAGE_OPTIONAL_HEADER32     *Optional32Hdr;\r
+  EFI_IMAGE_OPTIONAL_HEADER64     *Optional64Hdr;\r
+  EFI_IMAGE_SECTION_HEADER        *SectionHeader;\r
+  UINT32                          *NewTimeStamp;\r
+  \r
+  //\r
+  // Init variable.\r
+  //  \r
+  DebugDirectoryEntryRva    = 0;\r
+  ExportDirectoryEntryRva   = 0;\r
+  ResourceDirectoryEntryRva = 0;\r
+\r
+  //\r
+  // Get time and date that will be set.\r
+  //\r
+  \r
+  //\r
+  // compare the value with "NOW", if yes, current system time is set.\r
+  //\r
+  if (stricmp (TimeStamp, "NOW") == 0) {\r
+    //\r
+    // get system current time and date\r
+    //\r
+    time (&newtime);\r
+  } else {\r
+    //\r
+    // get the date and time from TimeStamp\r
+    //\r
+    if (sscanf (TimeStamp, "%d-%d-%d %d:%d:%d",\r
+            &stime.tm_year,\r
+            &stime.tm_mon,\r
+            &stime.tm_mday,\r
+            &stime.tm_hour,\r
+            &stime.tm_min,\r
+            &stime.tm_sec\r
+            ) != 6) {\r
+      Error (NULL, 0, 0, TimeStamp, "Invaild date or time!");\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    //\r
+    // in struct, Month (0 - 11; Jan = 0). So decrease 1 from it\r
+    //\r
+    stime.tm_mon -= 1;\r
+  \r
+    //\r
+    // in struct, Year (current year minus 1900)\r
+    // and only the dates can be handled from Jan 1, 1970 to Jan 18, 2038\r
+    //\r
+    //\r
+    // convert 0 -> 100 (2000), 1 -> 101 (2001), ..., 38 -> 138 (2038)\r
+    //\r
+    if (stime.tm_year <= 38) {\r
+      stime.tm_year += 100;\r
+    } else if (stime.tm_year >= 1970) {\r
+      //\r
+      // convert 1970 -> 70, 2000 -> 100, ...\r
+      //\r
+      stime.tm_year -= 1900;\r
+    }\r
+\r
+    //\r
+    // convert the date and time to time_t format\r
+    //\r
+    newtime = mktime (&stime);\r
+    if (newtime == (time_t) - 1) {\r
+      Error (NULL, 0, 0, TimeStamp, "Invaild date or time!");\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  }\r
+  \r
+  //\r
+  // Set new time and data into PeImage.\r
+  //\r
+  DosHdr   = (EFI_IMAGE_DOS_HEADER *)  FileBuffer;\r
+  FileHdr  = (EFI_IMAGE_FILE_HEADER *) (FileBuffer + DosHdr->e_lfanew + sizeof (UINT32));\r
+  \r
+  //\r
+  // Get Debug, Export and Resource EntryTable RVA address.\r
+  // Resource Directory entry need to review.\r
+  //\r
+  if (FileHdr->Machine == EFI_IMAGE_MACHINE_IA32) {\r
+    Optional32Hdr = (EFI_IMAGE_OPTIONAL_HEADER32 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));\r
+    SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional32Hdr +  FileHdr->SizeOfOptionalHeader);\r
+    if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \\r
+        Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {\r
+      ExportDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;\r
+    }\r
+    if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \\r
+        Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {\r
+      ResourceDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;\r
+    }\r
+    if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \\r
+        Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {\r
+      DebugDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
+    }\r
+  } else {\r
+    Optional64Hdr = (EFI_IMAGE_OPTIONAL_HEADER64 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));\r
+    SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional64Hdr +  FileHdr->SizeOfOptionalHeader);\r
+    if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \\r
+        Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {\r
+      ExportDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;\r
+    }\r
+    if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \\r
+        Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {\r
+      ResourceDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;\r
+    }\r
+    if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \\r
+        Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {\r
+      DebugDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Get DirectoryEntryTable file offset.\r
+  //\r
+  for (Index = 0; Index < FileHdr->NumberOfSections; Index ++, SectionHeader ++) {\r
+    if (DebugDirectoryEntryRva >= SectionHeader->VirtualAddress &&\r
+        DebugDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {\r
+        DebugDirectoryEntryFileOffset =\r
+        DebugDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;\r
+    }\r
+    if (ExportDirectoryEntryRva >= SectionHeader->VirtualAddress &&\r
+        ExportDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {\r
+        ExportDirectoryEntryFileOffset =\r
+        ExportDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;\r
+    }\r
+    if (ResourceDirectoryEntryRva >= SectionHeader->VirtualAddress &&\r
+        ResourceDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {\r
+        ResourceDirectoryEntryFileOffset =\r
+        ResourceDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;\r
+    }\r
+  }\r
+  \r
+  //\r
+  // Set new stamp\r
+  //\r
+  FileHdr->TimeDateStamp = (UINT32) newtime;\r
+\r
+  if (ExportDirectoryEntryRva != 0) {\r
+    NewTimeStamp  = (UINT32 *) (FileBuffer + ExportDirectoryEntryFileOffset + sizeof (UINT32));\r
+    *NewTimeStamp = (UINT32) newtime;\r
+  }\r
+\r
+  if (ResourceDirectoryEntryRva != 0) {\r
+    NewTimeStamp  = (UINT32 *) (FileBuffer + ResourceDirectoryEntryFileOffset + sizeof (UINT32));\r
+    *NewTimeStamp = (UINT32) newtime;\r
+  }\r
+\r
+  if (DebugDirectoryEntryRva != 0) {\r
+    NewTimeStamp  = (UINT32 *) (FileBuffer + DebugDirectoryEntryFileOffset + sizeof (UINT32));\r
+    *NewTimeStamp = (UINT32) newtime;\r
+  }\r
+  \r
+  return EFI_SUCCESS;\r
+}
\ No newline at end of file
index 5ddd837..e60bcdb 100644 (file)
@@ -262,6 +262,7 @@ Returns:
 \r
   PeHdr = NULL;\r
   TeHdr = NULL;\r
+  DebugDirectoryEntry    = NULL;\r
   DebugDirectoryEntryRva = 0;\r
 \r
   if (NULL == ImageContext) {\r
@@ -406,7 +407,7 @@ Returns:
           Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);    \r
           Status = ImageContext->ImageRead (\r
                                    ImageContext->Handle,\r
-                                   DebugDirectoryEntryFileOffset,\r
+                                   DebugDirectoryEntryFileOffset + Index,\r
                                    &Size,\r
                                    &DebugEntry\r
                                    );\r