]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/C/GenFv/GenFvInternalLib.c
BaseTools: BaseTools changes for RISC-V platform.
[mirror_edk2.git] / BaseTools / Source / C / GenFv / GenFvInternalLib.c
index daebfe894c77b2dbf204e531e917dfd921726261..d29a891c9c31353221b84ff5136ef3fb9314cf77 100644 (file)
@@ -4,6 +4,7 @@ This file contains the internal functions required to generate a Firmware Volume
 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
 Portions Copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.<BR>\r
 Portions Copyright (c) 2016 HP Development Company, L.P.<BR>\r
+Portions Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>\r
 SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
@@ -37,6 +38,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #define ARM64_UNCONDITIONAL_JUMP_INSTRUCTION      0x14000000\r
 \r
 BOOLEAN mArm = FALSE;\r
+BOOLEAN mRiscV = FALSE;\r
 STATIC UINT32   MaxFfsAlignment = 0;\r
 BOOLEAN VtfFileFlag = FALSE;\r
 \r
@@ -2291,6 +2293,104 @@ Returns:
   return EFI_SUCCESS;\r
 }\r
 \r
+EFI_STATUS\r
+UpdateRiscvResetVectorIfNeeded (\r
+  MEMORY_FILE            *FvImage,\r
+  FV_INFO                *FvInfo\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  This parses the FV looking for SEC and patches that address into the\r
+  beginning of the FV header.\r
+\r
+  For RISC-V ISA, the reset vector is at 0xfff~ff00h or 200h\r
+\r
+Arguments:\r
+  FvImage       Memory file for the FV memory image/\r
+  FvInfo        Information read from INF file.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS             Function Completed successfully.\r
+  EFI_ABORTED             Error encountered.\r
+  EFI_INVALID_PARAMETER   A required parameter was NULL.\r
+  EFI_NOT_FOUND           PEI Core file not found.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                Status;\r
+  UINT16                    MachineType;\r
+  EFI_FILE_SECTION_POINTER  SecPe32;\r
+  EFI_PHYSICAL_ADDRESS      SecCoreEntryAddress;\r
+\r
+  UINT32 bSecCore;\r
+  UINT32 tmp;\r
+\r
+\r
+  //\r
+  // Verify input parameters\r
+  //\r
+  if (FvImage == NULL || FvInfo == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  //\r
+  // Initialize FV library\r
+  //\r
+  InitializeFvLib (FvImage->FileImage, FvInfo->Size);\r
+\r
+  //\r
+  // Find the Sec Core\r
+  //\r
+  Status = FindCorePeSection(FvImage->FileImage, FvInfo->Size, EFI_FV_FILETYPE_SECURITY_CORE, &SecPe32);\r
+  if(EFI_ERROR(Status)) {\r
+    printf("skip because Secutiry Core not found\n");\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  DebugMsg (NULL, 0, 9, "Update SEC core in FV Header", NULL);\r
+\r
+  Status = GetCoreMachineType(SecPe32, &MachineType);\r
+  if(EFI_ERROR(Status)) {\r
+    Error(NULL, 0, 3000, "Invalid", "Could not get the PE32 machine type for SEC core.");\r
+    return EFI_ABORTED;\r
+  }\r
+\r
+  if (MachineType != EFI_IMAGE_MACHINE_RISCV64) {\r
+    Error(NULL, 0, 3000, "Invalid", "Could not update SEC core because Machine type is not RiscV.");\r
+    return EFI_ABORTED;\r
+  }\r
+\r
+  Status = GetCoreEntryPointAddress(FvImage->FileImage, FvInfo, SecPe32, &SecCoreEntryAddress);\r
+  if(EFI_ERROR(Status)) {\r
+    Error(NULL, 0, 3000, "Invalid", "Could not get the PE32 entry point address for SEC Core.");\r
+    return EFI_ABORTED;\r
+  }\r
+\r
+  VerboseMsg("SecCore entry point Address = 0x%llX", (unsigned long long) SecCoreEntryAddress);\r
+  VerboseMsg("BaseAddress = 0x%llX", (unsigned long long) FvInfo->BaseAddress);\r
+  bSecCore = (UINT32)(SecCoreEntryAddress - FvInfo->BaseAddress);\r
+  VerboseMsg("offset = 0x%llX", bSecCore);\r
+\r
+  if(bSecCore > 0x0fffff) {\r
+    Error(NULL, 0, 3000, "Invalid", "SEC Entry point must be within 1MB of start of the FV");\r
+    return EFI_ABORTED;\r
+  }\r
+\r
+  tmp = bSecCore;\r
+  bSecCore = 0;\r
+  //J-type\r
+  bSecCore  = (tmp&0x100000)<<11; //imm[20]    at bit[31]\r
+  bSecCore |= (tmp&0x0007FE)<<20; //imm[10:1]  at bit[30:21]\r
+  bSecCore |= (tmp&0x000800)<<9;  //imm[11]    at bit[20]\r
+  bSecCore |= (tmp&0x0FF000);     //imm[19:12] at bit[19:12]\r
+  bSecCore |= 0x6F; //JAL opcode\r
+\r
+  memcpy(FvImage->FileImage, &bSecCore, sizeof(bSecCore));\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
 EFI_STATUS\r
 GetPe32Info (\r
   IN UINT8                  *Pe32,\r
@@ -2383,7 +2483,8 @@ Returns:
   // Verify machine type is supported\r
   //\r
   if ((*MachineType != EFI_IMAGE_MACHINE_IA32) &&  (*MachineType != EFI_IMAGE_MACHINE_X64) && (*MachineType != EFI_IMAGE_MACHINE_EBC) &&\r
-      (*MachineType != EFI_IMAGE_MACHINE_ARMT) && (*MachineType != EFI_IMAGE_MACHINE_AARCH64)) {\r
+      (*MachineType != EFI_IMAGE_MACHINE_ARMT) && (*MachineType != EFI_IMAGE_MACHINE_AARCH64) &&\r
+      (*MachineType != EFI_IMAGE_MACHINE_RISCV64)) {\r
     Error (NULL, 0, 3000, "Invalid", "Unrecognized machine type in the PE32 file.");\r
     return EFI_UNSUPPORTED;\r
   }\r
@@ -2826,7 +2927,8 @@ Returns:
       Error (NULL, 0, 4002, "Resource", "FV space is full, cannot add pad file between the last file and the VTF file.");\r
       goto Finish;\r
     }\r
-    if (!mArm) {\r
+\r
+    if (!mArm && !mRiscV) {\r
       //\r
       // Update reset vector (SALE_ENTRY for IPF)\r
       // Now for IA32 and IA64 platform, the fv which has bsf file must have the\r
@@ -2861,6 +2963,22 @@ Returns:
     FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));\r
   }\r
 \r
+  if (mRiscV) {\r
+     //\r
+     // Update RISCV reset vector.\r
+     //\r
+     Status = UpdateRiscvResetVectorIfNeeded (&FvImageMemoryFile, &mFvDataInfo);\r
+     if (EFI_ERROR (Status)) {\r
+       Error (NULL, 0, 3000, "Invalid", "Could not update the reset vector for RISC-V.");\r
+       goto Finish;\r
+    }\r
+    //\r
+    // Update Checksum for FvHeader\r
+    //\r
+    FvHeader->Checksum = 0;\r
+    FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));\r
+  }\r
+\r
   //\r
   // Update FV Alignment attribute to the largest alignment of all the FFS files in the FV\r
   //\r
@@ -3448,6 +3566,10 @@ Returns:
       mArm = TRUE;\r
     }\r
 \r
+    if (ImageContext.Machine == EFI_IMAGE_MACHINE_RISCV64) {\r
+      mRiscV = TRUE;\r
+    }\r
+\r
     //\r
     // Keep Image Context for PE image in FV\r
     //\r
@@ -3601,7 +3723,7 @@ Returns:
     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
+      Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s Status=%d", FileName, Status);\r
       free ((VOID *) MemoryImagePointer);\r
       return Status;\r
     }\r