Update build system to support the feature of Load Module At Fix Address (LMFA).
authorlgao4 <lgao4@c2973edb-eda0-4c78-bc6a-9341b269661f>
Thu, 4 Feb 2010 02:34:53 +0000 (02:34 +0000)
committerlgao4 <lgao4@c2973edb-eda0-4c78-bc6a-9341b269661f>
Thu, 4 Feb 2010 02:34:53 +0000 (02:34 +0000)
1. Build.exe tool will calculate the required memory, assign the memory for the different modules, automatically patch LMFA PCDs into EFI image after build, and create the address map file when this feature is enabled by set FIX_LOAD_TOP_MEMORY_ADDRESS macro value.
2. New PatchPcdValue tool is developed to patch the value into binary image.
3. New GenPatchPcdTable tool is added to parse EFI image and map file to get the offset of Patchable PCD in EFI image.
4. GenFv tool don’t assign the memory address for the loaded module, which has been taken over by Build.exe tool.

git-svn-id: https://edk2-buildtools.svn.sourceforge.net/svnroot/edk2-buildtools/trunk/BaseTools@1838 c2973edb-eda0-4c78-bc6a-9341b269661f

Source/C/GenFv/GenFv.c
Source/C/GenFv/GenFvInternalLib.c
Source/C/GenFv/GenFvInternalLib.h
Source/Python/Common/Misc.py
Source/Python/GenPatchPcdTable/GenPatchPcdTable.py [new file with mode: 0644]
Source/Python/GenPatchPcdTable/__init__.py [new file with mode: 0644]
Source/Python/Makefile
Source/Python/PatchPcdValue/PatchPcdValue.py [new file with mode: 0644]
Source/Python/PatchPcdValue/__init__.py [new file with mode: 0644]
Source/Python/build/build.py

index f3d0aff..454a94f 100644 (file)
@@ -1,6 +1,6 @@
 /** @file\r
 \r
-Copyright (c) 2007 - 2009, Intel Corporation                                                         \r
+Copyright (c) 2007 - 2010, Intel Corporation                                                         \r
 All rights reserved. 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
@@ -40,7 +40,7 @@ Abstract:
 //\r
 #define UTILITY_MAJOR_VERSION 0\r
 #define UTILITY_MINOR_VERSION 1\r
-#define GENFV_UPDATE_TIME           " updated on 2008/11/21"\r
+#define GENFV_UPDATE_TIME           " updated on 2010/2/1"\r
 \r
 EFI_GUID  mEfiFirmwareFileSystem2Guid = EFI_FIRMWARE_FILE_SYSTEM2_GUID;\r
 \r
@@ -97,7 +97,7 @@ Returns:
   //\r
   // Copyright declaration\r
   // \r
-  fprintf (stdout, "Copyright (c) 2007, Intel Corporation. All rights reserved.\n\n");\r
+  fprintf (stdout, "Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.\n\n");\r
 \r
   //\r
   // Details Option\r
@@ -126,11 +126,8 @@ Returns:
                         run in Flash. It supports DEC or HEX digital format.\n\\r
                         If it is set to zero, no rebase action will be taken\n");\r
   fprintf (stdout, "  -a AddressFile, --addrfile AddressFile\n\\r
-                        AddressFile is one file used to record boot driver base\n\\r
-                        address and runtime driver base address. And this tool\n\\r
-                        will update these two addresses after it relocates all\n\\r
-                        boot drivers and runtime drivers in this fv iamge to\n\\r
-                        the preferred loaded memory address.\n");\r
+                        AddressFile is one file used to record the child\n\\r
+                        FV base address when current FV base address is set.\n");\r
   fprintf (stdout, "  -m logfile, --map logfile\n\\r
                         Logfile is the output fv map file name. if it is not\n\\r
                         given, the FvName.map will be the default map file name\n"); \r
@@ -194,10 +191,8 @@ Returns:
   CHAR8                 *InfFileImage;\r
   UINT32                InfFileSize;\r
   CHAR8                 *OutFileName;\r
-  CHAR8                 ValueString[_MAX_PATH];\r
   BOOLEAN               CapsuleFlag;\r
   BOOLEAN               DumpCapsule;\r
-  MEMORY_FILE           AddrMemoryFile;\r
   FILE                  *FpFile;\r
   EFI_CAPSULE_HEADER    *CapsuleHeader;\r
   UINT64                LogLevel, TempNumber;\r
@@ -545,62 +540,6 @@ Returns:
     VerboseMsg ("the output file name is %s", OutFileName);\r
   }\r
   \r
-  //\r
-  // Read boot and runtime address from address file\r
-  //\r
-  if (AddrFileName != NULL) {\r
-    VerboseMsg ("the input address file name is %s", AddrFileName);\r
-    Status = GetFileImage (AddrFileName, &InfFileImage, &InfFileSize);\r
-    if (EFI_ERROR (Status)) {\r
-      return STATUS_ERROR;\r
-    }\r
-\r
-    AddrMemoryFile.FileImage           = InfFileImage;\r
-    AddrMemoryFile.CurrentFilePointer  = InfFileImage;\r
-    AddrMemoryFile.Eof                 = InfFileImage + InfFileSize;\r
-\r
-    //\r
-    // Read the boot driver base address for this FV image\r
-    //\r
-    Status = FindToken (&AddrMemoryFile, OPTIONS_SECTION_STRING, EFI_FV_BOOT_DRIVER_BASE_ADDRESS_STRING, 0, ValueString);\r
-    if (Status == EFI_SUCCESS) {\r
-      //\r
-      // Get the base address\r
-      //\r
-      Status = AsciiStringToUint64 (ValueString, FALSE, &TempNumber);\r
-      if (EFI_ERROR (Status)) {\r
-        Error (NULL, 0, 2000, "Invalid parameter", "%s = %s", EFI_FV_BOOT_DRIVER_BASE_ADDRESS_STRING, ValueString);\r
-        return STATUS_ERROR;\r
-      }\r
-      mFvDataInfo.BootBaseAddress = TempNumber;\r
-      DebugMsg (NULL, 0, 9, "Boot driver base address", "%s = %s", EFI_FV_BOOT_DRIVER_BASE_ADDRESS_STRING, ValueString);\r
-    }\r
-  \r
-    //\r
-    // Read the FV runtime driver base address\r
-    //\r
-    Status = FindToken (&AddrMemoryFile, OPTIONS_SECTION_STRING, EFI_FV_RUNTIME_DRIVER_BASE_ADDRESS_STRING, 0, ValueString);\r
-    if (Status == EFI_SUCCESS) {\r
-      //\r
-      // Get the base address\r
-      //\r
-      Status = AsciiStringToUint64 (ValueString, FALSE, &TempNumber);\r
-      if (EFI_ERROR (Status)) {\r
-        Error (NULL, 0, 2000, "Invalid parameter", "%s = %s", EFI_FV_RUNTIME_DRIVER_BASE_ADDRESS_STRING, ValueString);\r
-        return STATUS_ERROR;\r
-      }\r
-      mFvDataInfo.RuntimeBaseAddress = TempNumber;\r
-      DebugMsg (NULL, 0, 9, "Runtime driver base address", "%s = %s", EFI_FV_RUNTIME_DRIVER_BASE_ADDRESS_STRING, ValueString);\r
-    }\r
-    \r
-    //\r
-    // free the allocated memory space for addr file.\r
-    //\r
-    free (InfFileImage);\r
-    InfFileImage = NULL;\r
-    InfFileSize  = 0;\r
-  }\r
-\r
   //\r
   // Read the INF file image\r
   //\r
@@ -683,42 +622,20 @@ Returns:
   //\r
   //  update boot driver address and runtime driver address in address file\r
   //\r
-  if (Status == EFI_SUCCESS && AddrFileName != NULL) {\r
+  if (Status == EFI_SUCCESS && AddrFileName != NULL && mFvBaseAddressNumber > 0) {\r
     FpFile = fopen (AddrFileName, "w");\r
     if (FpFile == NULL) {\r
       Error (NULL, 0, 0001, "Error opening file", AddrFileName);\r
       return STATUS_ERROR;\r
     }\r
-    fprintf (FpFile, OPTIONS_SECTION_STRING);\r
+    fprintf (FpFile, FV_BASE_ADDRESS_STRING);\r
     fprintf (FpFile, "\n");\r
-    if (mFvDataInfo.BootBaseAddress != 0) {\r
-      fprintf (FpFile, EFI_FV_BOOT_DRIVER_BASE_ADDRESS_STRING);\r
-      fprintf (\r
-        FpFile,\r
-        " = 0x%llx\n",\r
-        (unsigned long long)mFvDataInfo.BootBaseAddress\r
-        );\r
-      DebugMsg (NULL, 0, 9, "Updated boot driver base address", "%s = 0x%llx", EFI_FV_RUNTIME_DRIVER_BASE_ADDRESS_STRING, (unsigned long long) mFvDataInfo.BootBaseAddress);\r
-    }\r
-    if (mFvDataInfo.RuntimeBaseAddress != 0) {\r
-      fprintf (FpFile, EFI_FV_RUNTIME_DRIVER_BASE_ADDRESS_STRING);\r
+    for (Index = 0; Index < mFvBaseAddressNumber; Index ++) {\r
       fprintf (\r
         FpFile,\r
-        " = 0x%llx\n",\r
-        (unsigned long long)mFvDataInfo.RuntimeBaseAddress\r
+        "0x%llx\n",\r
+        (unsigned long long)mFvBaseAddress[Index]\r
         );\r
-      DebugMsg (NULL, 0, 9, "Updated runtime driver base address", "%s = 0x%llx", EFI_FV_RUNTIME_DRIVER_BASE_ADDRESS_STRING, (unsigned long long) mFvDataInfo.RuntimeBaseAddress);\r
-    }\r
-    if (mFvBaseAddressNumber > 0) {\r
-      fprintf (FpFile, FV_BASE_ADDRESS_STRING);\r
-      fprintf (FpFile, "\n");\r
-      for (Index = 0; Index < mFvBaseAddressNumber; Index ++) {\r
-        fprintf (\r
-          FpFile,\r
-          "0x%llx\n",\r
-          (unsigned long long)mFvBaseAddress[Index]\r
-          );\r
-      }\r
     }\r
     fclose (FpFile);\r
   }\r
index f3cbdd5..0295165 100644 (file)
@@ -719,6 +719,7 @@ Returns:
   EFI_TE_IMAGE_HEADER                 *TEImageHeader;\r
   EFI_IMAGE_SECTION_HEADER            *SectionHeader;\r
   unsigned long long                  TempLongAddress;\r
+  \r
   //\r
   // Init local variable\r
   //\r
@@ -798,23 +799,23 @@ Returns:
   //\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 (", KeyWord);\r
-    fprintf (FvMapFile, "BaseAddress=%08llx, ", (unsigned long long) (ImageBaseAddress + Offset));\r
+    fprintf (FvMapFile, "%s (Fixed Flash Address, ", KeyWord);\r
+    fprintf (FvMapFile, "BaseAddress=0x%010llx, ", (unsigned long long) (ImageBaseAddress + Offset));\r
   }\r
-  fprintf (FvMapFile, "EntryPoint=%08llx, ", (unsigned long long) (ImageBaseAddress + AddressOfEntryPoint));\r
-  fprintf (FvMapFile, "GUID=%s", FileGuidName);\r
+  fprintf (FvMapFile, "EntryPoint=0x%010llx", (unsigned long long) (ImageBaseAddress + AddressOfEntryPoint));\r
   fprintf (FvMapFile, ")\n"); \r
   \r
+  fprintf (FvMapFile, "(GUID=%s", FileGuidName);\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
+               fprintf (FvMapFile, " .textbaseaddress=0x%010llx", (unsigned long long) (ImageBaseAddress + SectionHeader->VirtualAddress));\r
        } else if (stricmp ((CHAR8 *)SectionHeader->Name, ".data") == 0) {\r
-         fprintf (FvMapFile, ".databaseaddress=%08llx ", (unsigned long long) (ImageBaseAddress + SectionHeader->VirtualAddress));\r
+         fprintf (FvMapFile, " .databaseaddress=0x%010llx", (unsigned long long) (ImageBaseAddress + SectionHeader->VirtualAddress));\r
        }\r
   }\r
-  fprintf (FvMapFile, "\n\n"); \r
+  fprintf (FvMapFile, ")\n\n"); \r
    \r
   //\r
   // Open PeMapFile\r
@@ -864,24 +865,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));\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));\r
         fprintf (FvMapFile, "%s\n", FunctionName);\r
       }\r
     }\r
@@ -2688,11 +2679,9 @@ Returns:
 \r
 EFI_STATUS\r
 GetChildFvFromFfs (\r
-  IN      UINT8                 FixupFlags,\r
   IN      FV_INFO               *FvInfo, \r
   IN      EFI_FFS_FILE_HEADER   *FfsFile,\r
-  IN      UINTN                 XipOffset,\r
-  IN      FILE                  *FvMapFile\r
+  IN      UINTN                 XipOffset\r
   )\r
 /*++\r
 \r
@@ -2714,18 +2703,9 @@ Returns:
   EFI_STATUS                          Status;\r
   UINTN                               Index;\r
   EFI_FILE_SECTION_POINTER            SubFvSection;\r
-  EFI_FFS_FILE_STATE                  SavedState;\r
-  EFI_FFS_FILE_HEADER                 *SubFfsFile;\r
-  EFI_FFS_FILE_HEADER                 *NextFfsFile;\r
-  EFI_FIRMWARE_VOLUME_HEADER          *SavedFvHeader;\r
-  UINT32                              SavedFvSize;\r
   EFI_FIRMWARE_VOLUME_HEADER          *SubFvImageHeader;\r
-  CHAR8                               SubFfsName[PRINTED_GUID_BUFFER_SIZE];\r
   EFI_PHYSICAL_ADDRESS                SubFvBaseAddress;\r
 \r
-  ZeroMem (SubFfsName, PRINTED_GUID_BUFFER_SIZE);\r
-  GetFvHeader (&SavedFvHeader, &SavedFvSize);\r
-\r
   for (Index = 1;; Index++) {\r
     //\r
     // Find FV section \r
@@ -2735,52 +2715,13 @@ Returns:
       break;\r
     }\r
     SubFvImageHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINT8 *) SubFvSection.FVImageSection + sizeof (EFI_FIRMWARE_VOLUME_IMAGE_SECTION));\r
-    if ((FixupFlags & REBASE_XIP_FILE) == REBASE_XIP_FILE) {\r
-      //\r
-      // Rebase on Flash\r
-      //\r
-      SubFvBaseAddress = FvInfo->BaseAddress + (UINTN) SubFvImageHeader - (UINTN) FfsFile + XipOffset;\r
-      mFvBaseAddress[mFvBaseAddressNumber ++ ] = SubFvBaseAddress;\r
-    } else {\r
-      //\r
-      // Rebase on Memory\r
-      //\r
-      InitializeFvLib (SubFvImageHeader, (UINT32) SubFvImageHeader->FvLength);\r
-      //\r
-      // Go through FFS in this insided FvImage one by one.\r
-      //\r
-      SubFfsFile = NULL;\r
-      while (TRUE) {\r
-        GetNextFile (SubFfsFile, &NextFfsFile);\r
-        if (NextFfsFile == NULL) {\r
-          break;\r
-        }\r
-        SubFfsFile = NextFfsFile;\r
-        //\r
-        // Use FFS GUID as its File Name.\r
-        //\r
-        PrintGuidToBuffer (&SubFfsFile->Name, (UINT8 *) SubFfsName, PRINTED_GUID_BUFFER_SIZE, TRUE);\r
-        FfsRebase (FvInfo, SubFfsName, SubFfsFile, (UINTN) SubFfsFile - (UINTN) FfsFile + XipOffset, FvMapFile);\r
-      }\r
-    }\r
-  }\r
-\r
-  //\r
-  // Now update file checksum\r
-  //\r
-  if (((FixupFlags & REBASE_XIP_FILE) == 0) && (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM)) {\r
-    SavedState  = FfsFile->State;\r
-    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
-      );\r
-    FfsFile->State = SavedState;\r
+    //\r
+    // Rebase on Flash\r
+    //\r
+    SubFvBaseAddress = FvInfo->BaseAddress + (UINTN) SubFvImageHeader - (UINTN) FfsFile + XipOffset;\r
+    mFvBaseAddress[mFvBaseAddressNumber ++ ] = SubFvBaseAddress;\r
   }\r
 \r
-  InitializeFvLib (SavedFvHeader, SavedFvSize);\r
-\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -2828,7 +2769,6 @@ Returns:
   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
@@ -2849,26 +2789,12 @@ Returns:
   PeFileBuffer       = NULL;\r
 \r
   //\r
-  // Check XipAddress, BootAddress and RuntimeAddress\r
+  // Don't need to relocate image when BaseAddress is not set.\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) {\r
+    return EFI_SUCCESS;\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
-  //\r
+  XipBase = FvInfo->BaseAddress + XipOffset;\r
 \r
   //\r
   // We only process files potentially containing PE32 sections.\r
@@ -2885,9 +2811,8 @@ Returns:
       //\r
       // Rebase the inside FvImage.\r
       //\r
-      if (Flags != 0) {\r
-        GetChildFvFromFfs (Flags, FvInfo, FfsFile, XipOffset, FvMapFile);\r
-      }\r
+      GetChildFvFromFfs (FvInfo, FfsFile, XipOffset);\r
+\r
       //\r
       // Search PE/TE section in FV sectin.\r
       //\r
@@ -2952,13 +2877,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
@@ -3032,70 +2950,18 @@ Returns:
 \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 + sizeof (EFI_PE32_SECTION) - (UINTN)FfsFile;\r
+        BaseToUpdate = &XipBase;                       \r
         break;\r
 \r
       default:\r
@@ -3106,68 +2972,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) & (~((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
-      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 + sizeof (EFI_COMMON_SECTION_HEADER) + 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
@@ -3176,11 +3048,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
@@ -3198,7 +3065,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
@@ -3266,13 +3133,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
@@ -3283,7 +3143,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
@@ -3338,70 +3198,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) & (~(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
+      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
+    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
@@ -3423,7 +3288,7 @@ WritePeMap:
     //\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
index ea79478..b82fac8 100644 (file)
@@ -1,6 +1,6 @@
 /** @file\r
 \r
-Copyright (c) 2004 - 2008, Intel Corporation                                                         \r
+Copyright (c) 2004 - 2010, Intel Corporation                                                         \r
 All rights reserved. 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
@@ -83,8 +83,6 @@ Abstract:
 #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
-#define EFI_FV_BOOT_DRIVER_BASE_ADDRESS_STRING    "EFI_BOOT_DRIVER_BASE_ADDRESS"\r
-#define EFI_FV_RUNTIME_DRIVER_BASE_ADDRESS_STRING "EFI_RUNTIME_DRIVER_BASE_ADDRESS"\r
 \r
 #define EFI_FV_TOTAL_SIZE_STRING    "EFI_FV_TOTAL_SIZE"\r
 #define EFI_FV_TAKEN_SIZE_STRING    "EFI_FV_TAKEN_SIZE"\r
@@ -205,13 +203,6 @@ Abstract:
 #define FIT_TYPE_MASK         0x7F\r
 #define CHECKSUM_BIT_MASK     0x80\r
 \r
-//\r
-// Rebase File type\r
-//\r
-#define REBASE_XIP_FILE       0x1\r
-#define REBASE_BOOTTIME_FILE  0x2\r
-#define REBASE_RUNTIME_FILE   0x4\r
-\r
 //\r
 // Private data types\r
 //\r
@@ -229,8 +220,6 @@ typedef struct {
 typedef struct {\r
   BOOLEAN                 BaseAddressSet;\r
   EFI_PHYSICAL_ADDRESS    BaseAddress;\r
-  EFI_PHYSICAL_ADDRESS    BootBaseAddress;\r
-  EFI_PHYSICAL_ADDRESS    RuntimeBaseAddress;  \r
   EFI_GUID                FvFileSystemGuid;\r
   BOOLEAN                 FvFileSystemGuidSet;\r
   EFI_GUID                FvNameGuid;\r
index 2883169..546dd37 100755 (executable)
@@ -22,6 +22,7 @@ import threading
 import time
 import re
 import cPickle
+import array
 from UserDict import IterableUserDict
 from UserList import UserList
 
@@ -1343,6 +1344,90 @@ class PathClass(object):
 
     Key = property(_GetFileKey)
 
+## Parse PE image to get the required PE informaion.
+#
+class PeImageClass():
+    ## Constructor
+    #
+    #   @param  File FilePath of PeImage
+    #
+    def __init__(self, PeFile):
+        self.FileName   = PeFile
+        self.IsValid    = False
+        self.Size       = 0
+        self.EntryPoint = 0
+        self.SectionAlignment  = 0
+        self.SectionHeaderList = []
+        self.ErrorInfo = ''
+        try:
+             PeObject = open(PeFile, 'rb')
+        except:
+            self.ErrorInfo = self.FileName + ' can not be found\n'
+            return
+        # Read DOS header
+        ByteArray = array.array('B')
+        ByteArray.fromfile(PeObject, 0x3E)
+        ByteList = ByteArray.tolist()
+        # DOS signature should be 'MZ'
+        if self._ByteListToStr (ByteList[0x0:0x2]) != 'MZ':
+            self.ErrorInfo = self.FileName + ' has no valid DOS signature MZ'
+            return
+
+        # Read 4 byte PE Signature
+        PeOffset = self._ByteListToInt(ByteList[0x3C:0x3E])
+        PeObject.seek(PeOffset)
+        ByteArray = array.array('B')
+        ByteArray.fromfile(PeObject, 4)
+        # PE signature should be 'PE\0\0'
+        if ByteArray.tostring() != 'PE\0\0':
+            self.ErrorInfo = self.FileName + ' has no valid PE signature PE00'
+            return
+
+        # Read PE file header
+        ByteArray = array.array('B')
+        ByteArray.fromfile(PeObject, 0x14)
+        ByteList = ByteArray.tolist()
+        SecNumber = self._ByteListToInt(ByteList[0x2:0x4])
+        if SecNumber == 0:
+            self.ErrorInfo = self.FileName + ' has no section header'
+            return
+
+        # Read PE optional header
+        OptionalHeaderSize = self._ByteListToInt(ByteArray[0x10:0x12])
+        ByteArray = array.array('B')
+        ByteArray.fromfile(PeObject, OptionalHeaderSize)
+        ByteList = ByteArray.tolist()
+        self.EntryPoint       = self._ByteListToInt(ByteList[0x10:0x14])
+        self.SectionAlignment = self._ByteListToInt(ByteList[0x20:0x24])
+        self.Size             = self._ByteListToInt(ByteList[0x38:0x3C])
+
+        # Read each Section Header
+        for Index in range(SecNumber):
+            ByteArray = array.array('B')
+            ByteArray.fromfile(PeObject, 0x28)
+            ByteList = ByteArray.tolist()
+            SecName  = self._ByteListToStr(ByteList[0:8])
+            SecVirtualSize = self._ByteListToInt(ByteList[8:12])
+            SecRawAddress  = self._ByteListToInt(ByteList[20:24])
+            SecVirtualAddress = self._ByteListToInt(ByteList[12:16])
+            self.SectionHeaderList.append((SecName, SecVirtualAddress, SecRawAddress, SecVirtualSize))
+        self.IsValid = True
+        PeObject.close()
+
+    def _ByteListToStr(self, ByteList):
+        String = ''
+        for index in range(len(ByteList)):
+            if ByteList[index] == 0: 
+                break
+            String += chr(ByteList[index])
+        return String
+
+    def _ByteListToInt(self, ByteList):
+        Value = 0
+        for index in range(len(ByteList) - 1, -1, -1):
+            Value = (Value << 8) | int(ByteList[index])
+        return Value
+        
 ##
 #
 # This acts like the main() function for the script, unless it is 'import'ed into another
diff --git a/Source/Python/GenPatchPcdTable/GenPatchPcdTable.py b/Source/Python/GenPatchPcdTable/GenPatchPcdTable.py
new file mode 100644 (file)
index 0000000..3839822
--- /dev/null
@@ -0,0 +1,189 @@
+## @file\r
+# Generate PCD table for 'Patchable In Module' type PCD with given .map file.\r
+#    The Patch PCD table like:
+#    
+#    PCD Name    Offset in binary
+#    ========    ================\r
+#\r
+# Copyright (c) 2008 - 2010, Intel Corporation\r
+# All rights reserved. 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
+#\r
+# 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
+#
+
+#======================================  External Libraries ========================================
+import optparse
+import os
+import re
+import array
+
+from Common.BuildToolError import *
+import Common.EdkLogger as EdkLogger
+from Common.Misc import PeImageClass\r
+
+# Version and Copyright
+__version_number__ = "0.10"
+__version__ = "%prog Version " + __version_number__
+__copyright__ = "Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved."
+
+#======================================  Internal Libraries ========================================
+
+#============================================== Code ===============================================
+secRe = re.compile('^([\da-fA-F]+):([\da-fA-F]+) +([\da-fA-F]+)[Hh]? +([.\w\$]+) +(\w+)', re.UNICODE)
+symRe = re.compile('^([\da-fA-F]+):([\da-fA-F]+) +([\.:\\\\\w\?@\$]+) +([\da-fA-F]+)', re.UNICODE)
+
+def parsePcdInfoFromMapFile(mapfilepath, efifilepath):
+    """ Parse map file to get binary patch pcd information 
+    @param path    Map file absolution path
+    
+    @return a list which element hold (PcdName, Offset, SectionName)
+    """
+    lines = []
+    try:
+        f = open(mapfilepath, 'r')
+        lines = f.readlines()
+        f.close()
+    except:
+        return None
+    
+    if len(lines) == 0: return None
+    if lines[0].strip().find("Archive member included because of file (symbol)") != -1:
+        return _parseForGCC(lines)
+    return _parseGeneral(lines, efifilepath)
+    
+def _parseForGCC(lines):
+    """ Parse map file generated by GCC linker """
+    status       = 0
+    imageBase    = -1
+    lastSectionName = None
+    pcds         = []
+    for line in lines:
+        line = line.strip()
+        # status machine transection
+        if status == 0 and line == "Linker script and memory map":
+            status = 1
+            continue
+        elif status == 1 and line == 'START GROUP':
+            status = 2
+            continue
+        
+        # status handler:
+        if status == 1:
+            m = re.match('^[\da-fA-FxhH]+ +__image_base__ += +([\da-fA-FhxH]+)', line)
+            if m != None:
+                imageBase = int(m.groups(0)[0], 16)
+        if status == 2:
+            m = re.match('^([\w_\.]+) +([\da-fA-Fx]+) +([\da-fA-Fx]+)', line)
+            if m != None:
+                lastSectionName = m.groups(0)[0]
+        if status == 2:
+            m = re.match("^([\da-fA-Fx]+) +[_]+gPcd_BinaryPatch_([\w_\d]+)", line)
+            if m != None:
+                assert imageBase != -1, "Fail to get Binary PCD offsest for unknown image base address"
+                pcds.append((m.groups(0)[1], int(m.groups(0)[0], 16) - imageBase, lastSectionName))
+    return pcds
+                
+def _parseGeneral(lines, efifilepath):
+    """ For MSFT, ICC, EBC 
+    @param lines    line array for map file
+    
+    @return a list which element hold (PcdName, Offset, SectionName)
+    """    
+    status = 0    #0 - beginning of file; 1 - PE section definition; 2 - symbol table
+    secs  = []    # key = section name
+    bPcds = []
+    
+
+    for line in lines:
+        line = line.strip()
+        if re.match("^Start[' ']+Length[' ']+Name[' ']+Class", line):
+            status = 1
+            continue
+        if re.match("^Address[' ']+Publics by Value[' ']+Rva\+Base", line):
+            status = 2
+            continue
+        if re.match("^entry point at", line):
+            status = 3
+            continue        
+        if status == 1 and len(line) != 0:
+            m =  secRe.match(line)
+            assert m != None, "Fail to parse the section in map file , line is %s" % line
+            sec_no, sec_start, sec_length, sec_name, sec_class = m.groups(0)
+            secs.append([int(sec_no, 16), int(sec_start, 16), int(sec_length, 16), sec_name, sec_class])
+        if status == 2 and len(line) != 0:
+            m = symRe.match(line)
+            assert m != None, "Fail to parse the symbol in map file, line is %s" % line
+            sec_no, sym_offset, sym_name, vir_addr = m.groups(0)
+            sec_no     = int(sec_no,     16)
+            sym_offset = int(sym_offset, 16)
+            vir_addr   = int(vir_addr,   16)
+            m2 = re.match('^[_]+gPcd_BinaryPatch_([\w]+)', sym_name)
+            if m2 != None:
+                # fond a binary pcd entry in map file
+                for sec in secs:
+                    if sec[0] == sec_no and (sym_offset >= sec[1] and sym_offset < sec[1] + sec[2]):
+                        bPcds.append([m2.groups(0)[0], sec[3], sym_offset, vir_addr, sec_no])
+
+    if len(bPcds) == 0: return None
+
+    # get section information from efi file
+    efisecs = PeImageClass(efifilepath).SectionHeaderList
+    if efisecs == None or len(efisecs) == 0:
+        return None
+    
+    pcds = []
+    for pcd in bPcds:
+        index = 0
+        for efisec in efisecs:
+            index = index + 1
+            if pcd[1].strip() == efisec[0].strip():
+                pcds.append([pcd[0], efisec[2] + pcd[2], efisec[0]])
+            elif pcd[4] == index:
+                pcds.append([pcd[0], efisec[2] + pcd[2], efisec[0]])
+    return pcds
+    
+def generatePcdTable(list, pcdpath):
+    try:
+        f = open(pcdpath, 'w')
+    except:
+        pass
+
+    f.write('PCD Name                       Offset    Section Name\r\n')
+    
+    for pcditem in list:
+        f.write('%-30s 0x%-08X %-6s\r\n' % (pcditem[0], pcditem[1], pcditem[2]))
+    f.close()
+
+    #print 'Success to generate Binary Patch PCD table at %s!' % pcdpath 
+    
+if __name__ == '__main__':
+    UsageString = "%prog -m <MapFile> -e <EfiFile> -o <OutFile>"
+    AdditionalNotes = "\nPCD table is generated in file name with .BinaryPcdTable.txt postfix"
+    parser = optparse.OptionParser(description=__copyright__, version=__version__, usage=UsageString)
+    parser.add_option('-m', '--mapfile', action='store', dest='mapfile',
+                      help='Absolute path of module map file.')
+    parser.add_option('-e', '--efifile', action='store', dest='efifile',
+                      help='Absolute path of EFI binary file.')
+    parser.add_option('-o', '--outputfile', action='store', dest='outfile',
+                      help='Absolute path of output file to store the got patchable PCD table.')
+  
+    (options, args) = parser.parse_args()
+
+    if options.mapfile == None or options.efifile == None:
+        print parser.get_usage()
+    elif os.path.exists(options.mapfile) and os.path.exists(options.efifile):
+        list = parsePcdInfoFromMapFile(options.mapfile, options.efifile) 
+        if list != None:
+            if options.outfile != None:
+                generatePcdTable(list, options.outfile)
+            else:
+                generatePcdTable(list, options.mapfile.replace('.map', '.BinaryPcdTable.txt')) 
+        else:
+            print 'Fail to generate Patch PCD Table based on map file and efi file'
+    else:
+        print 'Fail to generate Patch PCD Table for fail to find map file or efi file!'
diff --git a/Source/Python/GenPatchPcdTable/__init__.py b/Source/Python/GenPatchPcdTable/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
index a4e7659..dd2780f 100644 (file)
@@ -10,7 +10,7 @@ MODULES=encodings.cp437,encodings.gbk,encodings.utf_16,encodings.utf_8,encodings
 BIN_DIR=$(EDK_TOOLS_PATH)\Bin\Win32
 
 
-APPLICATIONS=$(BIN_DIR)\build.exe $(BIN_DIR)\GenFds.exe $(BIN_DIR)\Trim.exe $(BIN_DIR)\MigrationMsa2Inf.exe $(BIN_DIR)\Fpd2Dsc.exe $(BIN_DIR)\TargetTool.exe $(BIN_DIR)\spd2dec.exe $(BIN_DIR)\GenDepex.exe
+APPLICATIONS=$(BIN_DIR)\build.exe $(BIN_DIR)\GenFds.exe $(BIN_DIR)\Trim.exe $(BIN_DIR)\MigrationMsa2Inf.exe $(BIN_DIR)\Fpd2Dsc.exe $(BIN_DIR)\TargetTool.exe $(BIN_DIR)\spd2dec.exe $(BIN_DIR)\GenDepex.exe $(BIN_DIR)\GenPatchPcdTable.exe $(BIN_DIR)\PatchPcdValue.exe
 \r
 COMMON_PYTHON=$(BASE_TOOLS_PATH)\Source\Python\Common\BuildToolError.py \\r
               $(BASE_TOOLS_PATH)\Source\Python\Common\Database.py \\r
@@ -82,6 +82,12 @@ $(BIN_DIR)\GenDepex.exe: $(BASE_TOOLS_PATH)\Source\Python\AutoGen\GenDepex.py $(
 $(BIN_DIR)\TargetTool.exe: $(BASE_TOOLS_PATH)\Source\Python\TargetTool\TargetTool.py $(COMMON_PYTHON)\r
   @pushd . & @cd TargetTool & @$(FREEZE) --include-modules=$(MODULES) --install-dir=$(BIN_DIR) TargetTool.py & @popd\r
 \r
+$(BIN_DIR)\GenPatchPcdTable.exe: $(BASE_TOOLS_PATH)\Source\Python\GenPatchPcdTable\GenPatchPcdTable.py $(COMMON_PYTHON)
+  @pushd . & @cd GenPatchPcdTable & @$(FREEZE) --include-modules=$(MODULES) --install-dir=$(BIN_DIR) GenPatchPcdTable.py & @popd
+\r
+$(BIN_DIR)\PatchPcdValue.exe: $(BASE_TOOLS_PATH)\Source\Python\PatchPcdValue\PatchPcdValue.py $(COMMON_PYTHON)
+  @pushd . & @cd PatchPcdValue & @$(FREEZE) --include-modules=$(MODULES) --install-dir=$(BIN_DIR) PatchPcdValue.py & @popd
+\r
 clean:\r
 cleanall:  
   @del /f /q $(BIN_DIR)\*.pyd $(BIN_DIR)\*.dll
diff --git a/Source/Python/PatchPcdValue/PatchPcdValue.py b/Source/Python/PatchPcdValue/PatchPcdValue.py
new file mode 100644 (file)
index 0000000..9a9f1d0
--- /dev/null
@@ -0,0 +1,287 @@
+## @file
+# Patch value into the binary file.
+#
+# Copyright (c) 2010, Intel Corporation
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution.  The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+
+##
+# Import Modules
+#
+import os
+import sys
+import re
+
+from optparse import OptionParser
+from optparse import make_option
+from Common.BuildToolError import *
+import Common.EdkLogger as EdkLogger
+import array
+
+# Version and Copyright
+__version_number__ = "0.10"
+__version__ = "%prog Version " + __version_number__
+__copyright__ = "Copyright (c) 2010, Intel Corporation. All rights reserved."
+
+## PatchBinaryFile method
+#
+# This method mainly patches the data into binary file.
+# 
+# @param FileName    File path of the binary file
+# @param ValueOffset Offset value 
+# @param TypeName    DataType Name
+# @param Value       Value String
+# @param MaxSize     MaxSize value
+#
+# @retval 0     File is updated successfully.
+# @retval not 0 File is updated failed.
+#
+def PatchBinaryFile(FileName, ValueOffset, TypeName, ValueString, MaxSize=0):
+    #
+    # Length of Binary File
+    #
+    FileHandle = open (FileName, 'rb')
+    FileHandle.seek (0, 2)
+    FileLength = FileHandle.tell()
+    FileHandle.close()
+    #
+    # Unify string to upper string
+    #
+    TypeName = TypeName.upper()
+    #
+    # Get PCD value data length
+    #
+    ValueLength = 0
+    if TypeName == 'BOOLEAN':
+        ValueLength = 1
+    elif TypeName == 'UINT8':
+        ValueLength = 1
+    elif TypeName == 'UINT16':
+        ValueLength = 2
+    elif TypeName == 'UINT32':
+        ValueLength = 4
+    elif TypeName == 'UINT64':
+        ValueLength = 8
+    elif TypeName == 'VOID*':
+        if MaxSize == 0:
+            return OPTION_MISSING, "PcdMaxSize is not specified for VOID* type PCD."
+        ValueLength = MaxSize
+    else:
+        return PARAMETER_INVALID,  "PCD type %s is not valid." %(CommandOptions.PcdTypeName)
+    #
+    # Check PcdValue is in the input binary file.
+    #
+    if ValueOffset + ValueLength > FileLength:
+        return PARAMETER_INVALID, "PcdOffset + PcdMaxSize(DataType) is larger than the input file size."
+    #
+    # Read binary file into array
+    #
+    FileHandle = open (FileName, 'rb')
+    ByteArray = array.array('B')
+    ByteArray.fromfile(FileHandle, FileLength)
+    FileHandle.close()
+    OrigByteList = ByteArray.tolist()
+    ByteList = ByteArray.tolist()
+    #
+    # Clear the data in file
+    #
+    for Index in range(ValueLength):
+        ByteList[ValueOffset + Index] = 0
+    #
+    # Patch value into offset
+    #
+    ValueString = ValueString.upper()
+    ValueNumber = 0
+    if TypeName == 'BOOLEAN':
+        #
+        # Get PCD value for BOOLEAN data type
+        #
+        try:
+            if ValueString == 'TRUE':
+                ValueNumber = 1
+            elif ValueString == 'FALSE':
+                ValueNumber = 0
+            elif ValueString.startswith('0X'):
+                ValueNumber = int (Value, 16)
+            else:
+                ValueNumber = int (Value)
+            if ValueNumber != 0:
+                ValueNumber = 1
+        except:
+            return PARAMETER_INVALID, "PCD Value %s is not valid dec or hex string." %(ValueString)
+        #
+        # Set PCD value into binary data
+        #
+        ByteList[ValueOffset] = ValueNumber
+    elif TypeName in ['UINT8', 'UINT16', 'UINT32', 'UINT64']:
+        #
+        # Get PCD value for UINT* data type
+        #
+        try:
+            if ValueString.startswith('0X'):
+                ValueNumber = int (ValueString, 16)
+            else:
+                ValueNumber = int (ValueString)
+        except:
+            return PARAMETER_INVALID, "PCD Value %s is not valid dec or hex string." %(ValueString)
+        #
+        # Set PCD value into binary data
+        #
+        for Index in range(ValueLength):
+            ByteList[ValueOffset + Index] = ValueNumber % 0x100
+            ValueNumber = ValueNumber / 0x100
+    elif TypeName == 'VOID*':
+        if ValueString.startswith("L "):
+            #
+            # Patch Unicode String
+            #
+            Index = 0
+            for ByteString in ValueString[2:]:
+                #
+                # Reserve zero as unicode tail
+                #
+                if Index + 2 >= ValueLength:
+                    break
+                #
+                # Set string value one by one
+                #
+                ByteList[ValueOffset + Index] = ord(ByteString)
+                Index = Index + 2
+        elif ValueString.startswith("{") and ValueString.endswith("}"):
+            #
+            # Patch {0x1, 0x2, ...} byte by byte
+            #
+            ValueList = ValueString[1 : len(ValueString) - 1].split(', ')
+            Index = 0
+            try:
+                for ByteString in ValueList:
+                    if ByteString.upper().startswith('0X'):
+                        ByteValue = int(ByteString, 16)
+                    else:
+                        ByteValue = int(ByteString)
+                    ByteList[ValueOffset + Index] = ByteValue % 0x100
+                    Index = Index + 1
+                    if Index >= ValueLength:
+                        break
+            except:
+                return PARAMETER_INVALID, "PCD Value %s is not valid dec or hex string array." %(ValueString)
+        else:
+            #
+            # Patch ascii string 
+            #
+            Index = 0
+            for ByteString in ValueString:
+                #
+                # Reserve zero as string tail
+                #
+                if Index + 1 >= ValueLength:
+                    break
+                #
+                # Set string value one by one
+                #
+                ByteList[ValueOffset + Index] = ord(ByteString)
+                Index = Index + 1
+    #
+    # Update new data into input file.
+    #
+    if ByteList != OrigByteList:
+        ByteArray = array.array('B')
+        ByteArray.fromlist(ByteList)
+        FileHandle = open (FileName, 'wb')
+        ByteArray.tofile(FileHandle)
+        FileHandle.close()
+    return 0, "Patch Value into File %s successfully." %(FileName)
+
+## Parse command line options
+#
+# Using standard Python module optparse to parse command line option of this tool.
+#
+# @retval Options   A optparse.Values object containing the parsed options
+# @retval InputFile Path of file to be trimmed
+#
+def Options():
+    OptionList = [
+        make_option("-f", "--offset", dest="PcdOffset", action="store", type="int",
+                          help="Start offset to the image is used to store PCD value."),
+        make_option("-u", "--value", dest="PcdValue", action="store",
+                          help="PCD value will be updated into the image."),
+        make_option("-t", "--type", dest="PcdTypeName", action="store",
+                          help="The name of PCD data type may be one of VOID*,BOOLEAN, UINT8, UINT16, UINT32, UINT64."),
+        make_option("-s", "--maxsize", dest="PcdMaxSize", action="store", type="int",
+                          help="Max size of data buffer is taken by PCD value.It must be set when PCD type is VOID*."),
+        make_option("-v", "--verbose", dest="LogLevel", action="store_const", const=EdkLogger.VERBOSE,
+                          help="Run verbosely"),
+        make_option("-d", "--debug", dest="LogLevel", type="int",
+                          help="Run with debug information"),
+        make_option("-q", "--quiet", dest="LogLevel", action="store_const", const=EdkLogger.QUIET,
+                          help="Run quietly"),
+        make_option("-?", action="help", help="show this help message and exit"),
+    ]
+
+    # use clearer usage to override default usage message
+    UsageString = "%prog -f Offset -u Value -t Type [-s MaxSize] <input_file>"
+
+    Parser = OptionParser(description=__copyright__, version=__version__, option_list=OptionList, usage=UsageString)
+    Parser.set_defaults(LogLevel=EdkLogger.INFO)
+
+    Options, Args = Parser.parse_args()
+
+    # error check
+    if len(Args) == 0:
+        EdkLogger.error("PatchPcdValue", PARAMETER_INVALID, ExtraData=Parser.get_usage())
+
+    InputFile = Args[len(Args) - 1]
+    return Options, InputFile
+
+## Entrance method
+#
+# This method mainly dispatch specific methods per the command line options.
+# If no error found, return zero value so the caller of this tool can know
+# if it's executed successfully or not.
+#
+# @retval 0     Tool was successful
+# @retval 1     Tool failed
+#
+def Main():
+    try:
+        #
+        # Check input parameter
+        #
+        EdkLogger.Initialize()
+        CommandOptions, InputFile = Options()
+        if CommandOptions.LogLevel < EdkLogger.DEBUG_9:
+            EdkLogger.SetLevel(CommandOptions.LogLevel + 1)
+        else:
+            EdkLogger.SetLevel(CommandOptions.LogLevel)
+        if not os.path.exists (InputFile):
+            EdkLogger.error("PatchPcdValue", FILE_NOT_FOUND, ExtraData=InputFile)
+            return 1
+        if CommandOptions.PcdOffset == None or CommandOptions.PcdValue == None or CommandOptions.PcdTypeName == None:
+            EdkLogger.error("PatchPcdValue", OPTION_MISSING, ExtraData="PcdOffset or PcdValue of PcdTypeName is not specified.")
+            return 1
+        if CommandOptions.PcdTypeName.upper() not in ["BOOLEAN", "UINT8", "UINT16", "UINT32", "UINT64", "VOID*"]:
+            EdkLogger.error("PatchPcdValue", PARAMETER_INVALID, ExtraData="PCD type %s is not valid." %(CommandOptions.PcdTypeName))
+            return 1
+        if CommandOptions.PcdTypeName.upper() == "VOID*" and CommandOptions.PcdMaxSize == None:
+            EdkLogger.error("PatchPcdValue", OPTION_MISSING, ExtraData="PcdMaxSize is not specified for VOID* type PCD.")
+            return 1
+        #
+        # Patch value into binary image.
+        #
+        ReturnValue, ErrorInfo = PatchBinaryFile (InputFile, CommandOptions.PcdOffset, CommandOptions.PcdTypeName, CommandOptions.PcdValue, CommandOptions.PcdMaxSize)
+        if ReturnValue != 0:
+            EdkLogger.error("PatchPcdValue", ReturnValue, ExtraData=ErrorInfo)
+            return 1
+        return 0
+    except:
+        return 1
+
+if __name__ == '__main__':
+    r = Main()
+    sys.exit(r)
diff --git a/Source/Python/PatchPcdValue/__init__.py b/Source/Python/PatchPcdValue/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
index 539fd77..90ac1c2 100644 (file)
 #\r
 import os\r
 import re\r
+import StringIO\r
 import sys\r
 import glob\r
 import time\r
 import platform\r
 import traceback\r
 \r
+from struct import *\r
 from threading import *\r
 from optparse import OptionParser\r
 from subprocess import *\r
@@ -36,6 +38,8 @@ from Common.BuildToolError import *
 from Workspace.WorkspaceDatabase import *\r
 \r
 from BuildReport import BuildReport\r
+from GenPatchPcdTable.GenPatchPcdTable import *\r
+from PatchPcdValue.PatchPcdValue import *\r
 \r
 import Common.EdkLogger\r
 import Common.GlobalData as GlobalData\r
@@ -642,6 +646,25 @@ class BuildTask:
         self.BuildTread.setDaemon(False)\r
         self.BuildTread.start()\r
 \r
+## The class contains the information related to EFI image\r
+#\r
+class PeImageInfo():\r
+    ## Constructor\r
+    #\r
+    # Constructor will load all required image information.\r
+    #\r
+    #   @param  FileName          The full file path of image. \r
+    #   @param  Size              The required memory size of image.\r
+    #   @param  EntryPointOffset  The entry point offset to image base.\r
+    #   @param  Guid              The GUID for image.\r
+    #   @param  OutpuDir          The output directory for image.\r
+    #\r
+    def __init__(self, BaseName, Guid, OutpuDir, ImageClass):\r
+        self.BaseName         = BaseName\r
+        self.Guid             = Guid\r
+        self.OutpuDir         = OutpuDir\r
+        self.Image            = ImageClass\r
+\r
 ## The class implementing the EDK2 build process\r
 #\r
 #   The build process includes:\r
@@ -705,6 +728,7 @@ class Build():
         #self.Db             = WorkspaceDatabase(None, {}, self.Reparse)\r
         self.BuildDatabase  = self.Db.BuildObject\r
         self.Platform       = None\r
+        self.LoadFixAddress = 0\r
 \r
         # print dot charater during doing some time-consuming work\r
         self.Progress = Utils.Progressor()\r
@@ -835,6 +859,23 @@ class Build():
         self.Platform = self.BuildDatabase[self.PlatformFile, 'COMMON']\r
         if not self.Fdf:\r
             self.Fdf = self.Platform.FlashDefinition\r
+        \r
+        LoadFixAddressString = None\r
+        if TAB_FIX_LOAD_TOP_MEMORY_ADDRESS in GlobalData.gGlobalDefines:\r
+            LoadFixAddressString = GlobalData.gGlobalDefines[TAB_FIX_LOAD_TOP_MEMORY_ADDRESS]\r
+        else:\r
+            LoadFixAddressString = self.Platform.LoadFixAddress\r
+\r
+        if LoadFixAddressString != None and LoadFixAddressString != '':\r
+            try:\r
+                if LoadFixAddressString.upper().startswith('0X'):\r
+                    self.LoadFixAddress = int (LoadFixAddressString, 16)\r
+                else:\r
+                    self.LoadFixAddress = int (LoadFixAddressString)\r
+            except:
+                EdkLogger.error("build", PARAMETER_INVALID, "FIX_LOAD_TOP_MEMORY_ADDRESS %s is not valid dec or hex string" % (LoadFixAddressString))\r
+            if self.LoadFixAddress < 0:\r
+                EdkLogger.error("build", PARAMETER_INVALID, "FIX_LOAD_TOP_MEMORY_ADDRESS can't be set to negative value %s" % (LoadFixAddressString))\r
 \r
         if self.SkuId == None or self.SkuId == '':\r
             self.SkuId = self.Platform.SkuName\r
@@ -940,6 +981,239 @@ class Build():
                 EdkLogger.error("build", FILE_DELETE_FAILURE, ExtraData=str(X))\r
         return True\r
 \r
+    ## Rebase module image and Get function address for the inpug module list.\r
+    #\r
+    def _RebaseModule (self, MapBuffer, BaseAddress, ModuleList, AddrIsOffset = True, ModeIsSmm = False):\r
+        if ModeIsSmm:\r
+            AddrIsOffset = False\r
+        InfFileNameList = ModuleList.keys()\r
+        #InfFileNameList.sort()\r
+        for InfFile in InfFileNameList:\r
+            sys.stdout.write (".")
+            sys.stdout.flush()
+            ModuleInfo = ModuleList[InfFile]\r
+            ModuleName = ModuleInfo.BaseName\r
+            ## for SMM module in SMRAM, the SMRAM will be allocated from base to top.\r
+            if not ModeIsSmm:\r
+                BaseAddress = BaseAddress - ModuleInfo.Image.Size\r
+                #\r
+                # Update Image to new BaseAddress by GenFw tool\r
+                #\r
+                LaunchCommand(["GenFw", "--rebase", str(BaseAddress), "-r", ModuleInfo.Image.FileName], ModuleInfo.OutpuDir)\r
+            else:\r
+                #\r
+                # Set new address to the section header only for SMM driver.\r
+                #\r
+                LaunchCommand(["GenFw", "--address", str(BaseAddress), "-r", ModuleInfo.Image.FileName], ModuleInfo.OutpuDir)\r
+            #\r
+            # Add general information.\r
+            #\r
+            if ModeIsSmm:\r
+                MapBuffer.write('\n\n%s (Fix SMRAM Offset,   BaseAddress=0x%010X,  EntryPoint=0x%010X)\n' % (ModuleName, BaseAddress, BaseAddress + ModuleInfo.Image.EntryPoint))\r
+            elif AddrIsOffset:\r
+                MapBuffer.write('\n\n%s (Fix Memory Offset,  BaseAddress=-0x%010X, EntryPoint=-0x%010X)\n' % (ModuleName, 0 - BaseAddress, 0 - (BaseAddress + ModuleInfo.Image.EntryPoint)))\r
+            else:\r
+                MapBuffer.write('\n\n%s (Fix Memory Address, BaseAddress=0x%010X,  EntryPoint=0x%010X)\n' % (ModuleName, BaseAddress, BaseAddress + ModuleInfo.Image.EntryPoint))\r
+            #\r
+            # Add guid and general seciton section.\r
+            #\r
+            TextSectionAddress = 0\r
+            DataSectionAddress = 0\r
+            for SectionHeader in ModuleInfo.Image.SectionHeaderList:\r
+                if SectionHeader[0] == '.text':\r
+                    TextSectionAddress = SectionHeader[1]\r
+                elif SectionHeader[1] == '.data':\r
+                    DataSectionAddress = SectionHeader[1]\r
+            if AddrIsOffset:\r
+                MapBuffer.write('(GUID=%s, .textbaseaddress=-0x%010X, .databaseaddress=-0x%010X)\n\n' % (ModuleInfo.Guid, 0 - (BaseAddress + TextSectionAddress), 0 - (BaseAddress + DataSectionAddress))) \r
+            else:\r
+                MapBuffer.write('(GUID=%s, .textbaseaddress=0x%010X, .databaseaddress=0x%010X)\n\n' % (ModuleInfo.Guid, BaseAddress + TextSectionAddress, BaseAddress + DataSectionAddress)) \r
+            #\r
+            # Add funtion address\r
+            #\r
+            ImageMapTable = ModuleInfo.Image.FileName.replace('.efi', '.map')\r
+            if not os.path.exists(ImageMapTable):\r
+                continue\r
+            ImageMap = open (ImageMapTable, 'r')\r
+            for LinStr in ImageMap:\r
+                if len (LinStr.strip()) == 0:\r
+                    continue\r
+                StrList = LinStr.split()\r
+                if len (StrList) > 4:\r
+                    if StrList[3] == 'f' or StrList[3] =='F':\r
+                        if AddrIsOffset:\r
+                            MapBuffer.write('  -0x%010X    %s\n' % (0 - (BaseAddress + int (StrList[2], 16)), StrList[1]))\r
+                        else:\r
+                            MapBuffer.write('  0x%010X    %s\n' % (BaseAddress + int (StrList[2], 16), StrList[1]))\r
+            ImageMap.close()\r
+\r
+            #\r
+            # for SMM module in SMRAM, the SMRAM will be allocated from base to top.\r
+            #\r
+            if ModeIsSmm:\r
+                BaseAddress = BaseAddress + ModuleInfo.Image.Size\r
+\r
+    ## Collect MAP information of all FVs\r
+    #\r
+    def _CollectFvMapBuffer (self, MapBuffer, Wa):\r
+        if self.Fdf != '':\r
+            # First get the XIP base address for FV map file.\r
+            for FvName in Wa.FdfProfile.FvDict.keys():\r
+                FvMapBuffer = os.path.join(Wa.FvDir, FvName + '.Fv.map')\r
+                if not os.path.exists(FvMapBuffer):\r
+                    continue\r
+                FvMap = open (FvMapBuffer, 'r')\r
+                #skip FV size information\r
+                FvMap.readline()\r
+                FvMap.readline()\r
+                FvMap.readline()\r
+                FvMap.readline()\r
+                MapBuffer.write(FvMap.read())\r
+                FvMap.close()\r
+\r
+    ## Collect MAP information of all modules\r
+    #\r
+    def _CollectModuleMapBuffer (self, MapBuffer, ModuleList):\r
+        sys.stdout.write ("Generate Load Module At Fix Address Map")
+        sys.stdout.flush()
+        PatchEfiImageList = []\r
+        PeiModuleList  = {}\r
+        BtModuleList   = {}\r
+        RtModuleList   = {}\r
+        SmmModuleList  = {}\r
+        PeiSize = 0\r
+        BtSize  = 0\r
+        RtSize  = 0\r
+        # reserve 4K size in SMRAM to make SMM module address not from 0.\r
+        SmmSize = 0x1000\r
+        for Module in ModuleList:\r
+            GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (Module.MetaFile, Module.Arch, Module.ToolChain, Module.BuildTarget)\r
+            \r
+            OutputImageFile = ''\r
+            for ResultFile in Module.CodaTargetList:\r
+                if str(ResultFile.Target).endswith('.efi'):\r
+                    #\r
+                    # module list for PEI, DXE, RUNTIME and SMM\r
+                    #\r
+                    OutputImageFile = os.path.join(Module.OutputDir, Module.Name + '.efi')\r
+                    ImageClass = PeImageClass (OutputImageFile)\r
+                    if not ImageClass.IsValid:\r
+                        EdkLogger.error("build", FILE_PARSE_FAILURE, ExtraData=ImageClass.ErrorInfo)\r
+                    ImageInfo = PeImageInfo(Module.Name, Module.Guid, Module.OutputDir, ImageClass)\r
+                    if Module.ModuleType in ['PEI_CORE', 'PEIM', 'COMBINED_PEIM_DRIVER','PIC_PEIM', 'RELOCATABLE_PEIM', 'DXE_CORE']:\r
+                        PeiModuleList[Module.MetaFile] = ImageInfo\r
+                        PeiSize += ImageClass.Size\r
+                    elif Module.ModuleType in ['BS_DRIVER', 'DXE_DRIVER', 'UEFI_DRIVER']:\r
+                        BtModuleList[Module.MetaFile] = ImageInfo\r
+                        BtSize += ImageClass.Size\r
+                    elif Module.ModuleType in ['DXE_RUNTIME_DRIVER', 'RT_DRIVER', 'DXE_SAL_DRIVER', 'SAL_RT_DRIVER']:\r
+                        RtModuleList[Module.MetaFile] = ImageInfo\r
+                        RtSize += ImageClass.Size\r
+                    elif Module.ModuleType in ['SMM_CORE', 'DXE_SMM_DRIVER']:\r
+                        SmmModuleList[Module.MetaFile] = ImageInfo\r
+                        SmmSize += ImageClass.Size\r
+                        if Module.ModuleType == 'DXE_SMM_DRIVER':\r
+                            PiSpecVersion = 0
+                            if 'PI_SPECIFICATION_VERSION' in Module.Module.Specification:
+                                PiSpecVersion = Module.Module.Specification['PI_SPECIFICATION_VERSION']
+                            # for PI specification < PI1.1, DXE_SMM_DRIVER also runs as BOOT time driver.\r
+                            if PiSpecVersion < 0x0001000A:\r
+                                BtModuleList[Module.MetaFile] = ImageInfo\r
+                                BtSize += ImageClass.Size\r
+                    break\r
+            #\r
+            # EFI image is final target.\r
+            # Check EFI image contains patchable FixAddress related PCDs.\r
+            #\r
+            if OutputImageFile != '':\r
+                ModuleIsPatch = False\r
+                for Pcd in Module.ModulePcdList:\r
+                    if Pcd.Type == TAB_PCDS_PATCHABLE_IN_MODULE and Pcd.TokenCName in TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_LIST:\r
+                        ModuleIsPatch = True\r
+                        break\r
+                if not ModuleIsPatch:\r
+                    for Pcd in Module.LibraryPcdList:\r
+                        if Pcd.Type == TAB_PCDS_PATCHABLE_IN_MODULE and Pcd.TokenCName in TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_LIST:\r
+                            ModuleIsPatch = True\r
+                            break\r
+                \r
+                if not ModuleIsPatch:\r
+                    continue\r
+                #\r
+                # Module includes the patchable load fix address PCDs.\r
+                # It will be fixed up later. \r
+                #\r
+                PatchEfiImageList.append (OutputImageFile)\r
+        \r
+        #\r
+        # Patch FixAddress related PCDs into EFI image\r
+        #\r
+        for EfiImage in PatchEfiImageList: \r
+            EfiImageMap = EfiImage.replace('.efi', '.map')\r
+            if not os.path.exists(EfiImageMap):\r
+                continue\r
+            #\r
+            # Get PCD offset in EFI image by GenPatchPcdTable function\r
+            #\r
+            PcdTable = parsePcdInfoFromMapFile(EfiImageMap, EfiImage) 
+            #\r
+            # Patch real PCD value by PatchPcdValue tool\r
+            #\r
+            for PcdInfo in PcdTable:\r
+                ReturnValue = 0\r
+                if PcdInfo[0] == TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_PEI_PAGE_SIZE:\r
+                    ReturnValue, ErrorInfo = PatchBinaryFile (EfiImage, PcdInfo[1], TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_PEI_PAGE_SIZE_DATA_TYPE, str (PeiSize/0x1000))\r
+                elif PcdInfo[0] == TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_DXE_PAGE_SIZE:\r
+                    ReturnValue, ErrorInfo = PatchBinaryFile (EfiImage, PcdInfo[1], TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_DXE_PAGE_SIZE_DATA_TYPE, str (BtSize/0x1000))\r
+                elif PcdInfo[0] == TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_RUNTIME_PAGE_SIZE:\r
+                    ReturnValue, ErrorInfo = PatchBinaryFile (EfiImage, PcdInfo[1], TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_RUNTIME_PAGE_SIZE_DATA_TYPE, str (RtSize/0x1000))\r
+                elif PcdInfo[0] == TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_SMM_PAGE_SIZE:\r
+                    ReturnValue, ErrorInfo = PatchBinaryFile (EfiImage, PcdInfo[1], TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_SMM_PAGE_SIZE_DATA_TYPE, str (SmmSize/0x1000))\r
+                if ReturnValue != 0:\r
+                    EdkLogger.error("build", PARAMETER_INVALID, "Patch PCD value failed", ExtraData=ErrorInfo)\r
+        #\r
+        # Get Top Memory address\r
+        #\r
+        TopMemoryAddress = 0\r
+        if self.LoadFixAddress == 0xFFFFFFFFFFFFFFFF:\r
+            TopMemoryAddress = 0\r
+        else:\r
+            TopMemoryAddress = self.LoadFixAddress\r
+            if TopMemoryAddress < RtSize + BtSize + PeiSize:\r
+                EdkLogger.error("build", PARAMETER_INVALID, "TopMemoryAddress is too low to load driver")\r
+        \r
+        MapBuffer.write('PEI_CODE_PAGE_NUMBER      = 0x%x\n' % (PeiSize/0x1000))\r
+        MapBuffer.write('BOOT_CODE_PAGE_NUMBER     = 0x%x\n' % (BtSize/0x1000))\r
+        MapBuffer.write('RUNTIME_CODE_PAGE_NUMBER  = 0x%x\n' % (RtSize/0x1000))\r
+        MapBuffer.write('SMM_CODE_PAGE_NUMBER      = 0x%x\n' % (SmmSize/0x1000))\r
+        \r
+        PeiBaseAddr = TopMemoryAddress - RtSize - BtSize\r
+        BtBaseAddr  = TopMemoryAddress - RtSize\r
+        RtBaseAddr  = TopMemoryAddress\r
+\r
+        self._RebaseModule (MapBuffer, PeiBaseAddr, PeiModuleList, TopMemoryAddress == 0)\r
+        self._RebaseModule (MapBuffer, BtBaseAddr, BtModuleList, TopMemoryAddress == 0)\r
+        self._RebaseModule (MapBuffer, RtBaseAddr, RtModuleList, TopMemoryAddress == 0)\r
+        self._RebaseModule (MapBuffer, 0x1000, SmmModuleList, AddrIsOffset = False, ModeIsSmm = True)\r
+        MapBuffer.write('\n\n')\r
+        sys.stdout.write ("\n")
+        sys.stdout.flush()
+    \r
+    ## Save platform Map file\r
+    #\r
+    def _SaveMapFile (self, MapBuffer, Wa):\r
+        #\r
+        # Map file path is got.\r
+        #\r
+        MapFilePath = os.path.join(Wa.BuildDir, Wa.Name + '.map')\r
+        #\r
+        # Save address map into MAP file.\r
+        #\r
+        SaveFileOnChange(MapFilePath, MapBuffer.getvalue(), False)\r
+        MapBuffer.close()\r
+        sys.stdout.write ("\nLoad Module At Fix Address Map file saved to %s\n" %(MapFilePath))
+        sys.stdout.flush()
+\r
     ## Build active platform for different build targets and different tool chains\r
     #\r
     def _BuildPlatform(self):\r
@@ -962,6 +1236,44 @@ class Build():
                 self.BuildReport.AddPlatformReport(Wa)\r
                 self.Progress.Stop("done!")\r
                 self._Build(self.Target, Wa)\r
+                \r
+                # Create MAP file when Load Fix Address is enabled.\r
+                if self.Target in ["", "all", "fds"] and self.LoadFixAddress != 0:\r
+                    for Arch in self.ArchList:\r
+                        #\r
+                        # Check whether the set fix address is above 4G for 32bit image.\r
+                        #\r
+                        if (Arch == 'IA32' or Arch == 'ARM') and self.LoadFixAddress != 0xFFFFFFFFFFFFFFFF and self.LoadFixAddress >= 0x100000000:\r
+                            EdkLogger.error("build", PARAMETER_INVALID, "FIX_LOAD_TOP_MEMORY_ADDRESS can't be set to larger than 4G for the platorm with IA32 arch modules")\r
+                    #\r
+                    # Get Module List\r
+                    #\r
+                    ModuleList = []\r
+                    for Pa in Wa.AutoGenObjectList:\r
+                        for Ma in Pa.ModuleAutoGenList:\r
+                            if Ma == None:\r
+                                continue\r
+                            if not Ma.IsLibrary:\r
+                                ModuleList.append (Ma)\r
+\r
+                    MapBuffer = StringIO('')\r
+                    #\r
+                    # Rebase module to the preferred memory address before GenFds\r
+                    #\r
+                    self._CollectModuleMapBuffer(MapBuffer, ModuleList)\r
+                    if self.Fdf != '':\r
+                        #\r
+                        # create FDS again for the updated EFI image\r
+                        #\r
+                        self._Build("fds", Wa)\r
+                        #\r
+                        # Create MAP file for all platform FVs after GenFds.\r
+                        #\r
+                        self._CollectFvMapBuffer(MapBuffer, Wa)\r
+                    #\r
+                    # Save MAP buffer into MAP file.\r
+                    #\r
+                    self._SaveMapFile (MapBuffer, Wa)\r
 \r
     ## Build active module for different build targets, different tool chains and different archs\r
     #\r
@@ -1085,10 +1397,46 @@ class Build():
                 if BuildTask.HasError():\r
                     EdkLogger.error("build", BUILD_ERROR, "Failed to build module", ExtraData=GlobalData.gBuildingModule)\r
 \r
+                # Create MAP file when Load Fix Address is enabled.\r
+                if self.Target in ["", "all", "fds"] and self.LoadFixAddress != 0:\r
+                    for Arch in self.ArchList:\r
+                        #\r
+                        # Check whether the set fix address is above 4G for 32bit image.\r
+                        #\r
+                        if (Arch == 'IA32' or Arch == 'ARM') and self.LoadFixAddress != 0xFFFFFFFFFFFFFFFF and self.LoadFixAddress >= 0x100000000:\r
+                            EdkLogger.error("build", PARAMETER_INVALID, "FIX_LOAD_TOP_MEMORY_ADDRESS can't be set to larger than 4G for the platorm with IA32 arch modules")\r
+                    #\r
+                    # Get Module List\r
+                    #\r
+                    ModuleList = []\r
+                    for Pa in Wa.AutoGenObjectList:\r
+                        for Ma in Pa.ModuleAutoGenList:\r
+                            if Ma == None:\r
+                                continue\r
+                            if not Ma.IsLibrary:\r
+                                ModuleList.append (Ma)\r
+                    #\r
+                    # Rebase module to the preferred memory address before GenFds\r
+                    #\r
+                    MapBuffer = StringIO('')\r
+                    self._CollectModuleMapBuffer(MapBuffer, ModuleList)\r
+\r
                 # Generate FD image if there's a FDF file found\r
                 if self.Fdf != '' and self.Target in ["", "all", "fds"]:\r
                     LaunchCommand(Wa.BuildCommand + ["fds"], Wa.MakeFileDir)\r
 \r
+                # Create MAP file for all platform FV after GenFds\r
+                if self.Target in ["", "all", "fds"] and self.LoadFixAddress != 0:\r
+                    if self.Fdf != '':\r
+                        #\r
+                        # Create MAP file for all platform FVs after GenFds.\r
+                        #\r
+                        self._CollectFvMapBuffer(MapBuffer, Wa)\r
+                    #\r
+                    # Save MAP buffer into MAP file.\r
+                    #\r
+                    self._SaveMapFile(MapBuffer, Wa)\r
+\r
     ## Generate GuidedSectionTools.txt in the FV directories.\r
     #\r
     def CreateGuidedSectionToolsFile(self):\r
@@ -1347,18 +1695,27 @@ def Main():
                 Option.ModuleFile = NormFile(FileList[0], Workspace)\r
 \r
         if Option.ModuleFile:\r
+            if os.path.isabs (Option.ModuleFile):\r
+                if os.path.normcase (os.path.normpath(Option.ModuleFile)).find (Workspace) == 0:\r
+                    Option.ModuleFile = NormFile(os.path.normpath(Option.ModuleFile), Workspace)\r
             Option.ModuleFile = PathClass(Option.ModuleFile, Workspace)\r
             ErrorCode, ErrorInfo = Option.ModuleFile.Validate(".inf", False)\r
             if ErrorCode != 0:\r
                 EdkLogger.error("build", ErrorCode, ExtraData=ErrorInfo)\r
 \r
         if Option.PlatformFile != None:\r
+            if os.path.isabs (Option.PlatformFile):\r
+                if os.path.normcase (os.path.normpath(Option.PlatformFile)).find (Workspace) == 0:\r
+                    Option.PlatformFile = NormFile(os.path.normpath(Option.PlatformFile), Workspace)\r
             Option.PlatformFile = PathClass(Option.PlatformFile, Workspace)\r
             ErrorCode, ErrorInfo = Option.PlatformFile.Validate(".dsc", False)\r
             if ErrorCode != 0:\r
                 EdkLogger.error("build", ErrorCode, ExtraData=ErrorInfo)\r
 \r
         if Option.FdfFile != None:\r
+            if os.path.isabs (Option.FdfFile):\r
+                if os.path.normcase (os.path.normpath(Option.FdfFile)).find (Workspace) == 0:\r
+                    Option.FdfFile = NormFile(os.path.normpath(Option.FdfFile), Workspace)\r
             Option.FdfFile = PathClass(Option.FdfFile, Workspace)\r
             ErrorCode, ErrorInfo = Option.FdfFile.Validate(".fdf", False)\r
             if ErrorCode != 0:\r