]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/C/GenFv/GenFvInternalLib.c
SecurityPkg Variable: Remove mStorageData buffer allocation and use Scratch buffer...
[mirror_edk2.git] / BaseTools / Source / C / GenFv / GenFvInternalLib.c
index 00d008573a3c65f0a0772d7ea068a3e47edce612..dd0e9ec3be6ae53dedc4ac863da387d686898a31 100644 (file)
@@ -1,7 +1,8 @@
 /** @file\r
 \r
-Copyright (c) 2004 - 2010, Intel Corporation                                                         \r
-All rights reserved. This program and the accompanying materials                          \r
+Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<BR>\r
+Portions Copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.<BR>\r
+This program and the accompanying materials                          \r
 are licensed and made available under the terms and conditions of the BSD License         \r
 which accompanies this distribution.  The full text of the license may be found at        \r
 http://opensource.org/licenses/bsd-license.php                                            \r
@@ -84,7 +85,7 @@ CHAR8      *mFvbAlignmentName[] = {
   EFI_FVB2_ALIGNMENT_64K_STRING, \r
   EFI_FVB2_ALIGNMENT_128K_STRING,\r
   EFI_FVB2_ALIGNMENT_256K_STRING,\r
-  EFI_FVB2_ALIGNMNET_512K_STRING,\r
+  EFI_FVB2_ALIGNMENT_512K_STRING,\r
   EFI_FVB2_ALIGNMENT_1M_STRING,  \r
   EFI_FVB2_ALIGNMENT_2M_STRING,  \r
   EFI_FVB2_ALIGNMENT_4M_STRING,  \r
@@ -209,6 +210,7 @@ Returns:
       DebugMsg (NULL, 0, 9, "rebase address", "%s = %s", EFI_FV_BASE_ADDRESS_STRING, Value);\r
 \r
       FvInfo->BaseAddress = Value64;\r
+      FvInfo->BaseAddressSet = TRUE;\r
     }\r
   }\r
 \r
@@ -677,7 +679,7 @@ EFI_STATUS
 WriteMapFile (\r
   IN OUT FILE                  *FvMapFile,\r
   IN     CHAR8                 *FileName,\r
-  IN     EFI_GUID              *FileGuidPtr\r
+  IN     EFI_FFS_FILE_HEADER   *FfsFile\r
   IN     EFI_PHYSICAL_ADDRESS  ImageBaseAddress,\r
   IN     PE_COFF_LOADER_IMAGE_CONTEXT *pImageContext\r
   )\r
@@ -692,7 +694,7 @@ Arguments:
 \r
   FvMapFile             A pointer to FvMap File\r
   FileName              Ffs File PathName\r
-  FileGuidPtr           Guid Value of Ffs file\r
+  FfsFile               A pointer to Ffs file image.\r
   ImageBaseAddress      PeImage Base Address.\r
   pImageContext         Image Context Information.\r
 \r
@@ -723,7 +725,6 @@ Returns:
   UINT32                              DataVirtualAddress;\r
   EFI_PHYSICAL_ADDRESS                LinkTimeBaseAddress;\r
 \r
-  \r
   //\r
   // Init local variable\r
   //\r
@@ -731,7 +732,7 @@ Returns:
   //\r
   // Print FileGuid to string buffer. \r
   //\r
-  PrintGuidToBuffer (FileGuidPtr, (UINT8 *)FileGuidName, MAX_LINE_LEN, TRUE);\r
+  PrintGuidToBuffer (&FfsFile->Name, (UINT8 *)FileGuidName, MAX_LINE_LEN, TRUE);\r
   \r
   //\r
   // Construct Map file Name \r
@@ -808,7 +809,16 @@ Returns:
     fprintf (FvMapFile, "%s (Fixed Flash Address, ", KeyWord);\r
     fprintf (FvMapFile, "BaseAddress=0x%010llx, ", (unsigned long long) (ImageBaseAddress + Offset));\r
   }\r
-  fprintf (FvMapFile, "EntryPoint=0x%010llx", (unsigned long long) (ImageBaseAddress + AddressOfEntryPoint));\r
+\r
+  if (FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE && pImageContext->Machine == EFI_IMAGE_MACHINE_IA64) {\r
+    //\r
+    // Process IPF PLABEL to get the real address after the image has been rebased. \r
+    // PLABEL structure is got by AddressOfEntryPoint offset to ImageBuffer stored in pImageContext->Handle.\r
+    //\r
+    fprintf (FvMapFile, "EntryPoint=0x%010llx", (unsigned long long) (*(UINT64 *)((UINTN) pImageContext->Handle + (UINTN) AddressOfEntryPoint)));\r
+  } else {\r
+    fprintf (FvMapFile, "EntryPoint=0x%010llx", (unsigned long long) (ImageBaseAddress + AddressOfEntryPoint));\r
+  }\r
   fprintf (FvMapFile, ")\n"); \r
   \r
   fprintf (FvMapFile, "(GUID=%s", FileGuidName);\r
@@ -1012,7 +1022,7 @@ Returns:
   Status = VerifyFfsFile ((EFI_FFS_FILE_HEADER *)FileBuffer);\r
   if (EFI_ERROR (Status)) {\r
     free (FileBuffer);\r
-    Error (NULL, 0, 3000, "Invalid", "%s is a FFS file.", FvInfo->FvFiles[Index]);\r
+    Error (NULL, 0, 3000, "Invalid", "%s is not a valid FFS file.", FvInfo->FvFiles[Index]);\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
@@ -1077,7 +1087,11 @@ Returns:
       // Rebase the PE or TE image in FileBuffer of FFS file for XIP \r
       // Rebase for the debug genfvmap tool\r
       //\r
-      FfsRebase (FvInfo, FvInfo->FvFiles[Index], (EFI_FFS_FILE_HEADER *) FileBuffer, (UINTN) *VtfFileImage - (UINTN) FvImage->FileImage, FvMapFile);\r
+      Status = FfsRebase (FvInfo, FvInfo->FvFiles[Index], (EFI_FFS_FILE_HEADER *) FileBuffer, (UINTN) *VtfFileImage - (UINTN) FvImage->FileImage, FvMapFile);\r
+      if (EFI_ERROR (Status)) {\r
+        Error (NULL, 0, 3000, "Invalid", "Could not rebase %s.", FvInfo->FvFiles[Index]);\r
+        return Status;\r
+      }          \r
       //\r
       // copy VTF File\r
       //\r
@@ -1116,7 +1130,11 @@ Returns:
     // Rebase the PE or TE image in FileBuffer of FFS file for XIP. \r
     // Rebase Bs and Rt drivers for the debug genfvmap tool.\r
     //\r
-    FfsRebase (FvInfo, FvInfo->FvFiles[Index], (EFI_FFS_FILE_HEADER *) FileBuffer, (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage, FvMapFile);\r
+    Status = FfsRebase (FvInfo, FvInfo->FvFiles[Index], (EFI_FFS_FILE_HEADER *) FileBuffer, (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage, FvMapFile);\r
+       if (EFI_ERROR (Status)) {\r
+         Error (NULL, 0, 3000, "Invalid", "Could not rebase %s.", FvInfo->FvFiles[Index]);\r
+         return Status;\r
+       }               \r
     //\r
     // Copy the file\r
     //\r
@@ -1518,7 +1536,7 @@ Returns:
       //\r
       Status = FindApResetVectorPosition (FvImage, &BytePointer);\r
       if (EFI_ERROR (Status)) {\r
-        Error (NULL, 0, 3000, "Invalid", "Cannot find the appropriate location in FvImage to add Ap reset vector!");\r
+        Error (NULL, 0, 3000, "Invalid", "FV image does not have enough space to place AP reset vector. The FV image needs to reserve at least 4KB of unused space.");\r
         return EFI_ABORTED;\r
       }\r
     }\r
@@ -1563,6 +1581,11 @@ Returns:
     // Since the ARM reset vector is in the FV Header you really don't need a\r
     // Volume Top File, but if you have one for some reason don't crash...\r
     //\r
+  } else if (MachineType == EFI_IMAGE_MACHINE_AARCH64) {\r
+    //\r
+    // Since the AArch64 reset vector is in the FV Header you really don't need a\r
+    // Volume Top File, but if you have one for some reason don't crash...\r
+    //\r
   } else {\r
     Error (NULL, 0, 3000, "Invalid", "machine type=0x%X in PEI core.", MachineType);\r
     return EFI_ABORTED;\r
@@ -1600,9 +1623,11 @@ Routine Description:
   This parses the FV looking for SEC and patches that address into the \r
   beginning of the FV header.\r
 \r
-  For ARM the reset vector is at 0x00000000 or 0xFFFF0000.\r
+  For ARM32 the reset vector is at 0x00000000 or 0xFFFF0000.\r
+  For AArch64 the reset vector is at 0x00000000.\r
+\r
   This would commonly map to the first entry in the ROM. \r
-  ARM Exceptions:\r
+  ARM32 Exceptions:\r
   Reset            +0    \r
   Undefined        +4\r
   SWI              +8\r
@@ -1616,11 +1641,10 @@ Routine Description:
   2) Reset vector is data bytes FDF file and that code branches to reset vector \r
     in the beginning of the FV (fixed size offset).\r
 \r
-\r
   Need to have the jump for the reset vector at location zero.\r
   We also need to store the address or PEI (if it exists).\r
   We stub out a return from interrupt in case the debugger \r
-   is using SWI.\r
+   is using SWI (not done for AArch64, not enough space in struct).\r
   The optional entry to the common exception handler is \r
    to support full featured exception handling from ROM and is currently \r
     not support by this tool.\r
@@ -1647,10 +1671,14 @@ Returns:
   UINT16                    MachineType;\r
   EFI_PHYSICAL_ADDRESS      PeiCorePhysicalAddress;\r
   EFI_PHYSICAL_ADDRESS      SecCorePhysicalAddress;\r
-  INT32                     ResetVector[4]; // 0 - is branch relative to SEC entry point\r
+  INT32                     ResetVector[4]; // ARM32:\r
+                                            // 0 - is branch relative to SEC entry point\r
                                             // 1 - PEI Entry Point\r
                                             // 2 - movs pc,lr for a SWI handler\r
                                             // 3 - Place holder for Common Exception Handler\r
+                                            // AArch64: Used as UINT64 ResetVector[2]\r
+                                            // 0 - is branch relative to SEC entry point\r
+                                            // 1 - PEI Entry Point\r
 \r
   //\r
   // Verify input parameters\r
@@ -1710,7 +1738,7 @@ Returns:
       PeiCorePhysicalAddress += EntryPoint;\r
       DebugMsg (NULL, 0, 9, "PeiCore physical entry point address", "Address = 0x%llX", (unsigned long long) PeiCorePhysicalAddress);\r
 \r
-      if (MachineType == EFI_IMAGE_MACHINE_ARMT) {\r
+      if (MachineType == EFI_IMAGE_MACHINE_ARMT || MachineType == EFI_IMAGE_MACHINE_AARCH64) {\r
         memset (ResetVector, 0, sizeof (ResetVector));\r
         // Address of PEI Core, if we have one\r
         ResetVector[1] = (UINT32)PeiCorePhysicalAddress;\r
@@ -1750,7 +1778,7 @@ Returns:
     return EFI_ABORTED;\r
   }\r
   \r
-  if (MachineType != EFI_IMAGE_MACHINE_ARMT) {\r
+  if ((MachineType != EFI_IMAGE_MACHINE_ARMT) && (MachineType != EFI_IMAGE_MACHINE_AARCH64)) {\r
     //\r
     // If SEC is not ARM we have nothing to do\r
     //\r
@@ -1804,31 +1832,60 @@ Returns:
     DebugMsg (NULL, 0, 9, "PeiCore physical entry point address", "Address = 0x%llX", (unsigned long long) PeiCorePhysicalAddress);\r
   }\r
   \r
+  if (MachineType == EFI_IMAGE_MACHINE_ARMT) {\r
+    // B SecEntryPoint - signed_immed_24 part +/-32MB offset\r
+    // on ARM, the PC is always 8 ahead, so we're not really jumping from the base address, but from base address + 8\r
+    ResetVector[0] = (INT32)(SecCorePhysicalAddress - FvInfo->BaseAddress - 8) >> 2;\r
+\r
+    if (ResetVector[0] > 0x00FFFFFF) {\r
+      Error (NULL, 0, 3000, "Invalid", "SEC Entry point must be within 32MB of the start of the FV");\r
+      return EFI_ABORTED;\r
+    }\r
   \r
-  // B SecEntryPoint - signed_immed_24 part +/-32MB offset\r
-  // on ARM, the PC is always 8 ahead, so we're not really jumping from the base address, but from base address + 8\r
-  ResetVector[0] = (INT32)(SecCorePhysicalAddress - FvInfo->BaseAddress - 8) >> 2;\r
-  \r
-  if (ResetVector[0] > 0x00FFFFFF) {\r
-    Error (NULL, 0, 3000, "Invalid", "SEC Entry point must be within 32MB of the start of the FV");\r
-    return EFI_ABORTED;    \r
-  }\r
-  \r
-  // Add opcode for an uncondional branch with no link. AKA B SecEntryPoint\r
-  ResetVector[0] |= 0xEA000000;\r
+    // Add opcode for an uncondional branch with no link. AKA B SecEntryPoint\r
+    ResetVector[0] |= 0xEB000000;\r
   \r
   \r
-  // Address of PEI Core, if we have one\r
-  ResetVector[1] = (UINT32)PeiCorePhysicalAddress;\r
+    // Address of PEI Core, if we have one\r
+    ResetVector[1] = (UINT32)PeiCorePhysicalAddress;\r
   \r
-  // SWI handler movs   pc,lr. Just in case a debugger uses SWI\r
-  ResetVector[2] = 0xE1B0F07E;\r
+    // SWI handler movs   pc,lr. Just in case a debugger uses SWI\r
+    ResetVector[2] = 0xE1B0F07E;\r
   \r
-  // Place holder to support a common interrupt handler from ROM. \r
-  // Currently not suppprted. For this to be used the reset vector would not be in this FV\r
-  // and the exception vectors would be hard coded in the ROM and just through this address \r
-  // to find a common handler in the a module in the FV.\r
-  ResetVector[3] = 0;\r
+    // Place holder to support a common interrupt handler from ROM.\r
+    // Currently not suppprted. For this to be used the reset vector would not be in this FV\r
+    // and the exception vectors would be hard coded in the ROM and just through this address\r
+    // to find a common handler in the a module in the FV.\r
+    ResetVector[3] = 0;\r
+  } else if (MachineType == EFI_IMAGE_MACHINE_AARCH64) {\r
+\r
+  /* NOTE:\r
+    ARMT above has an entry in ResetVector[2] for SWI. The way we are using the ResetVector\r
+    array at the moment, for AArch64, does not allow us space for this as the header only\r
+    allows for a fixed amount of bytes at the start. If we are sure that UEFI will live\r
+    within the first 4GB of addressable RAM we could potensioally adopt the same ResetVector\r
+    layout as above. But for the moment we replace the four 32bit vectors with two 64bit\r
+    vectors in the same area of the Image heasder. This allows UEFI to start from a 64bit\r
+    base.\r
+  */\r
+\r
+    ((UINT64*)ResetVector)[0] = (UINT64)(SecCorePhysicalAddress - FvInfo->BaseAddress) >> 2;\r
+\r
+    // B SecEntryPoint - signed_immed_26 part +/-128MB offset\r
+    if ( ((UINT64*)ResetVector)[0] > 0x03FFFFFF) {\r
+      Error (NULL, 0, 3000, "Invalid", "SEC Entry point must be within 128MB of the start of the FV");\r
+      return EFI_ABORTED;\r
+    }\r
+    // Add opcode for an uncondional branch with no link. AKA B SecEntryPoint\r
+    ((UINT64*)ResetVector)[0] |= 0x14000000;\r
+\r
+    // Address of PEI Core, if we have one\r
+    ((UINT64*)ResetVector)[1] = (UINT64)PeiCorePhysicalAddress;\r
+\r
+  } else {\r
+    Error (NULL, 0, 3000, "Invalid", "Unknown ARM machine type");\r
+    return EFI_ABORTED;\r
+  }\r
 \r
   //\r
   // Copy to the beginning of the FV \r
@@ -1931,8 +1988,8 @@ Returns:
   //\r
   // Verify machine type is supported\r
   //\r
-  if (*MachineType != EFI_IMAGE_MACHINE_IA32 && *MachineType != EFI_IMAGE_MACHINE_IA64 && *MachineType != EFI_IMAGE_MACHINE_X64 && *MachineType != EFI_IMAGE_MACHINE_EBC && \r
-      *MachineType != EFI_IMAGE_MACHINE_ARMT) {\r
+  if ((*MachineType != EFI_IMAGE_MACHINE_IA32) && (*MachineType != EFI_IMAGE_MACHINE_IA64) && (*MachineType != EFI_IMAGE_MACHINE_X64) && (*MachineType != EFI_IMAGE_MACHINE_EBC) && \r
+      (*MachineType != EFI_IMAGE_MACHINE_ARMT) && (*MachineType != EFI_IMAGE_MACHINE_AARCH64)) {\r
     Error (NULL, 0, 3000, "Invalid", "Unrecognized machine type in the PE32 file.");\r
     return EFI_UNSUPPORTED;\r
   }\r
@@ -2784,7 +2841,6 @@ Returns:
   PE_COFF_LOADER_IMAGE_CONTEXT          OrigImageContext;  \r
   EFI_PHYSICAL_ADDRESS                  XipBase;\r
   EFI_PHYSICAL_ADDRESS                  NewPe32BaseAddress;\r
-  EFI_PHYSICAL_ADDRESS                  *BaseToUpdate;\r
   UINTN                                 Index;\r
   EFI_FILE_SECTION_POINTER              CurrentPe32Section;\r
   EFI_FFS_FILE_STATE                    SavedState;\r
@@ -2801,7 +2857,6 @@ Returns:
 \r
   Index              = 0;  \r
   MemoryImagePointer = NULL;\r
-  BaseToUpdate       = NULL;\r
   TEImageHeader      = NULL;\r
   ImgHdr             = NULL;\r
   SectionHeader      = NULL;\r
@@ -2810,11 +2865,20 @@ Returns:
   PeFileBuffer       = NULL;\r
 \r
   //\r
-  // Don't need to relocate image when BaseAddress is not set.\r
+  // Don't need to relocate image when BaseAddress is zero and no ForceRebase Flag specified.\r
+  //\r
+  if ((FvInfo->BaseAddress == 0) && (FvInfo->ForceRebase == -1)) {\r
+    return EFI_SUCCESS;\r
+  }\r
+  \r
+  //\r
+  // If ForceRebase Flag specified to FALSE, will always not take rebase action.\r
   //\r
-  if (FvInfo->BaseAddress == 0) {\r
+  if (FvInfo->ForceRebase == 0) {\r
     return EFI_SUCCESS;\r
   }\r
+\r
+\r
   XipBase = FvInfo->BaseAddress + XipOffset;\r
 \r
   //\r
@@ -2871,7 +2935,8 @@ Returns:
       return Status;\r
     }\r
 \r
-    if (ImageContext.Machine == EFI_IMAGE_MACHINE_ARMT) {\r
+    if ( (ImageContext.Machine == EFI_IMAGE_MACHINE_ARMT) ||\r
+         (ImageContext.Machine == EFI_IMAGE_MACHINE_AARCH64) ) {\r
       mArm = TRUE;\r
     }\r
 \r
@@ -2966,7 +3031,6 @@ Returns:
         }\r
 \r
         NewPe32BaseAddress = XipBase + (UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION) - (UINTN)FfsFile;\r
-        BaseToUpdate = &XipBase;\r
         break;\r
 \r
       case EFI_FV_FILETYPE_DRIVER:\r
@@ -2982,7 +3046,6 @@ Returns:
           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
@@ -3012,7 +3075,7 @@ Returns:
       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
+    ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~((UINTN) ImageContext.SectionAlignment - 1));\r
     \r
     Status =  PeCoffLoaderLoadImage (&ImageContext);\r
     if (EFI_ERROR (Status)) {\r
@@ -3094,7 +3157,7 @@ Returns:
       PdbPointer = FileName;\r
     }\r
 \r
-    WriteMapFile (FvMapFile, PdbPointer, (EFI_GUID *) FfsFile, NewPe32BaseAddress, &OrigImageContext);\r
+    WriteMapFile (FvMapFile, PdbPointer, FfsFile, NewPe32BaseAddress, &OrigImageContext);\r
   }\r
 \r
   if (FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE &&\r
@@ -3141,7 +3204,8 @@ Returns:
       return Status;\r
     }\r
 \r
-    if (ImageContext.Machine == EFI_IMAGE_MACHINE_ARMT) {\r
+    if ( (ImageContext.Machine == EFI_IMAGE_MACHINE_ARMT) ||\r
+         (ImageContext.Machine == EFI_IMAGE_MACHINE_AARCH64) ) {\r
       mArm = TRUE;\r
     }\r
 \r
@@ -3239,7 +3303,7 @@ Returns:
       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
+    ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~((UINTN) ImageContext.SectionAlignment - 1));\r
 \r
     Status =  PeCoffLoaderLoadImage (&ImageContext);\r
     if (EFI_ERROR (Status)) {\r
@@ -3320,7 +3384,7 @@ Returns:
     WriteMapFile (\r
       FvMapFile, \r
       PdbPointer, \r
-      (EFI_GUID *) FfsFile,\r
+      FfsFile,\r
       NewPe32BaseAddress, \r
       &OrigImageContext\r
       );\r