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
#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
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
// 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
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
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
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
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