From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pg1-f171.google.com (mail-pg1-f171.google.com [209.85.215.171]) by mx.groups.io with SMTP id smtpd.web09.6632.1662550654874842676 for ; Wed, 07 Sep 2022 04:37:35 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@ventanamicro.com header.s=google header.b=cwa6SD2a; spf=pass (domain: ventanamicro.com, ip: 209.85.215.171, mailfrom: sunilvl@ventanamicro.com) Received: by mail-pg1-f171.google.com with SMTP id bh13so13324318pgb.4 for ; Wed, 07 Sep 2022 04:37:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ventanamicro.com; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date; bh=oVMWXU1d4XgrJkOz/+uoNfV61FXR1+3IrDz9DuHU5Gs=; b=cwa6SD2aUaeEs2gC0l5ob3QIvOC0KVYkNdV+yZPk+cfU4q5IE1aqNd2WMjcjJe7EFM pkCfSJvLG8rSLbVuRlWy9iYxt7KtKgZPCGM+htlJoMAGrjBTBqY5LcfJMABUhsUO/Ot0 VnHfTp9cFR1dRXm4vQuaW+JKBzyTe8uZ+22k24AwqUFstyzu2V0MotqdlHwDj6ed7etj P64PUiBNRPlLkEYOhpdRaW1iQNQpMtH3/6p9psIELygKKijFtsQV4RPOHPneQ8XzOXrR jjt7+M7cIL8aEjaaesCM3Jg/Hp01QR5fDPIf7PdAvvceOrwqZ4zO+0hy/0E7/h+gYSS6 E5MQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date; bh=oVMWXU1d4XgrJkOz/+uoNfV61FXR1+3IrDz9DuHU5Gs=; b=it3kqbCOZiWju0k12YAGqgIwiz34m+ib8R7sUJagu5cSLpkuTdYwvZrx0CKnEBegz2 YvDr8aKO5f3ZO05KggBI2MpQTHpDmVQHOXkJqJ+amLbvcxE3c1Ayn0WwB1fGxrODJ02V mw1N0YfGfT+/+/NDDQSD+Je1WS0NtUpYShv8Q8LpRePHNEHjfAQP6f+ofdKYZ8aXLflJ Ms+xjc2KgnOnvDWc21ph2Iyn31Qsuzv47cm1II5ZEVFUX0h7gfpOStrMivB/rsB5OPni b17AXANsnGdwDu0Gvd07x2dxYfqYEuR1kQjKlok53/45kXJoipE/zaL1ayY/hyJ2WKzS CTFA== X-Gm-Message-State: ACgBeo2527RzNfKXtniYFoiN6pXRwuOOfwUlJtfPNabDGV0XX0n2lkPB fjg5kqDGUiBdYwQbj/BsV+0hP033fIgT6Y/4 X-Google-Smtp-Source: AA6agR4fPmxbD5bmk7xGHNW2eX3N8iykfAdz/WqZHWqnQb7g3SPSnPgy8l/6ERUaKtTmXDdz33mguA== X-Received: by 2002:a63:886:0:b0:434:8606:ce93 with SMTP id 128-20020a630886000000b004348606ce93mr2999533pgi.281.1662550653811; Wed, 07 Sep 2022 04:37:33 -0700 (PDT) Return-Path: Received: from localhost.localdomain ([49.206.11.92]) by smtp.gmail.com with ESMTPSA id 8-20020a17090a000800b001fd77933fb3sm10797230pja.17.2022.09.07.04.37.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 07 Sep 2022 04:37:33 -0700 (PDT) From: "Sunil V L" To: devel@edk2.groups.io Cc: Jian J Wang , Liming Gao , Eric Dong , Ray Ni , Rahul Kumar , Debkumar De , Catharine West , Daniel Schaefer , Abner Chang , Leif Lindholm , Andrew Fish , Ard Biesheuvel , Heinrich Schuchardt , Anup Patel , Sunil V L Subject: [RFC PATCH V2 12/19] UefiCpuPkg/SecCore: Add SEC startup code for RISC-V Date: Wed, 7 Sep 2022 17:06:19 +0530 Message-Id: <20220907113626.540065-13-sunilvl@ventanamicro.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220907113626.540065-1-sunilvl@ventanamicro.com> References: <20220907113626.540065-1-sunilvl@ventanamicro.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Generic RISC-V platforms will start in S-mode directly. Previous M-mode firmware like opensbi will branch to the entry point in this module. This module initializes the firmware context pointer and branches to the PEI phase. Signed-off-by: Sunil V L --- UefiCpuPkg/SecCore/SecCoreRiscV.inf | 59 ++ UefiCpuPkg/SecCore/RiscV64/SecMain.h | 63 ++ UefiCpuPkg/SecCore/RiscV64/SecMain.c | 796 ++++++++++++++++++++ UefiCpuPkg/SecCore/RiscV64/SecEntry.S | 23 + 4 files changed, 941 insertions(+) diff --git a/UefiCpuPkg/SecCore/SecCoreRiscV.inf b/UefiCpuPkg/SecCore/SecCoreRiscV.inf new file mode 100644 index 000000000000..8ba6400f5319 --- /dev/null +++ b/UefiCpuPkg/SecCore/SecCoreRiscV.inf @@ -0,0 +1,59 @@ +## @file +# RISC-V SEC module which boots in S-mode. +# +# Copyright (c) 2021, Hewlett Packard Enterprise Development LP. All rights reserved.
+# Copyright (c) 2022, Ventana Micro Systems Inc. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x0001001b + BASE_NAME = SecMain + FILE_GUID = 42C30D8E-BFAD-4E77-9041-E7DAAE88DF7A + MODULE_TYPE = SEC + VERSION_STRING = 1.0 + ENTRY_POINT = SecMain + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = RISCV64 +# + +[Sources] + RiscV64/SecEntry.S + RiscV64/SecMain.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiCpuPkg/UefiCpuPkg.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + PlatformSecLib + PcdLib + CpuLib + PeCoffGetEntryPointLib + PeCoffExtraActionLib + RiscVSbiLib + +[Ppis] + gEfiTemporaryRamSupportPpiGuid # PPI ALWAYS_PRODUCED + gEfiTemporaryRamDonePpiGuid # PPI ALWAYS_PRODUCED + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdSecMemFvBase + gEfiMdeModulePkgTokenSpaceGuid.PcdSecMemFvSize + gEfiMdeModulePkgTokenSpaceGuid.PcdPeiMemFvBase + gEfiMdeModulePkgTokenSpaceGuid.PcdPeiMemFvSize + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeMemFvBase + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeMemFvSize + gEfiMdeModulePkgTokenSpaceGuid.PcdSecPeiTempRamBase + gEfiMdeModulePkgTokenSpaceGuid.PcdSecPeiTempRamSize + +[UserExtensions.TianoCore."ExtraFiles"] + SecCoreExtra.uni diff --git a/UefiCpuPkg/SecCore/RiscV64/SecMain.h b/UefiCpuPkg/SecCore/RiscV64/SecMain.h new file mode 100644 index 000000000000..eeb368de02a2 --- /dev/null +++ b/UefiCpuPkg/SecCore/RiscV64/SecMain.h @@ -0,0 +1,63 @@ +/** @file + Master header file for SecCore. + + Copyright (c) 2019-2022, Hewlett Packard Enterprise Development LP. All rights reserved.
+ Copyright (c) 2022, Ventana Micro Systems Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _SEC_MAIN_H_ +#define _SEC_MAIN_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + Entry point to the C language phase of SEC. After the SEC assembly + code has initialized some temporary memory and set up the stack, + the control is transferred to this function. + + @param SizeOfRam Size of the temporary memory available for use. + @param TempRamBase Base address of temporary ram + @param BootFirmwareVolume Base address of the Boot Firmware Volume. +**/ +VOID +NORETURN +EFIAPI +SecStartup ( + IN UINTN BootHartId, + IN VOID *DeviceTreeAddress + ); + +/** + Auto-generated function that calls the library constructors for all of the module's + dependent libraries. This function must be called by the SEC Core once a stack has + been established. + +**/ +VOID +EFIAPI +ProcessLibraryConstructorList ( + VOID + ); + +#endif diff --git a/UefiCpuPkg/SecCore/RiscV64/SecMain.c b/UefiCpuPkg/SecCore/RiscV64/SecMain.c new file mode 100644 index 000000000000..d9dacce319dc --- /dev/null +++ b/UefiCpuPkg/SecCore/RiscV64/SecMain.c @@ -0,0 +1,796 @@ +/** @file + RISC-V SEC phase module. + + Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.
+ Copyright (c) 2021-2022, Hewlett Packard Enterprise Development LP. All rights reserved.
+ Copyright (c) 2022, Ventana Micro Systems Inc. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "SecMain.h" + +EFI_STATUS +EFIAPI +TemporaryRamMigration ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase, + IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase, + IN UINTN CopySize + ); + +EFI_STATUS +EFIAPI +TemporaryRamDone ( + VOID + ); + +STATIC EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mTemporaryRamSupportPpi = { + TemporaryRamMigration +}; + +STATIC EFI_PEI_TEMPORARY_RAM_DONE_PPI mTemporaryRamDonePpi = { + TemporaryRamDone +}; + +STATIC EFI_PEI_PPI_DESCRIPTOR mPrivateDispatchTable[] = { + { + EFI_PEI_PPI_DESCRIPTOR_PPI, + &gEfiTemporaryRamSupportPpiGuid, + &mTemporaryRamSupportPpi + }, + { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiTemporaryRamDonePpiGuid, + &mTemporaryRamDonePpi + }, +}; + +/** Temporary RAM migration function. + + This function migrates the data from temporary RAM to permanent + memory. + + @param[in] PeiServices PEI service + @param[in] TemporaryMemoryBase Temporary memory base address + @param[in] PermanentMemoryBase Permanent memory base address + @param[in] CopySize Size to copy + +**/ +EFI_STATUS +EFIAPI +TemporaryRamMigration ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase, + IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase, + IN UINTN CopySize + ) +{ + VOID *OldHeap; + VOID *NewHeap; + VOID *OldStack; + VOID *NewStack; + EFI_RISCV_FIRMWARE_CONTEXT *FirmwareContext; + + DEBUG ((DEBUG_INFO, + "%a: Temp Mem Base:0x%Lx, Permanent Mem Base:0x%Lx, CopySize:0x%Lx\n", + __FUNCTION__, + TemporaryMemoryBase, + PermanentMemoryBase, + (UINT64)CopySize + )); + + OldHeap = (VOID*)(UINTN)TemporaryMemoryBase; + NewHeap = (VOID*)((UINTN)PermanentMemoryBase + (CopySize >> 1)); + + OldStack = (VOID*)((UINTN)TemporaryMemoryBase + (CopySize >> 1)); + NewStack = (VOID*)(UINTN)PermanentMemoryBase; + + CopyMem (NewHeap, OldHeap, CopySize >> 1); // Migrate Heap + CopyMem (NewStack, OldStack, CopySize >> 1); // Migrate Stack + + // + // Reset firmware context pointer + // + GetFirmwareContextPointer (&FirmwareContext); + FirmwareContext = (VOID *)FirmwareContext + (unsigned long)((UINTN)NewStack - (UINTN)OldStack); + SetFirmwareContextPointer (FirmwareContext); + + DEBUG ((DEBUG_INFO, "%a: Firmware Context is relocated to 0x%x\n", __FUNCTION__, FirmwareContext)); + + register UINTN a0 asm ("a0") = (UINTN)((UINTN)NewStack - (UINTN)OldStack); + asm volatile ("add sp, sp, a0"::"r"(a0):); + return EFI_SUCCESS; +} + +/** Temprary RAM done function. + +**/ +EFI_STATUS EFIAPI TemporaryRamDone ( + VOID + ) +{ + DEBUG ((DEBUG_INFO, "%a: 2nd time PEI core, temporary ram done.\n", __FUNCTION__)); + return EFI_SUCCESS; +} +/** Return platform SEC PPI before PEI Core + + @param[in,out] ThisPpiList Pointer to retrieve EFI_PEI_PPI_DESCRIPTOR. + +**/ +STATIC EFI_STATUS +GetPlatformPrePeiCorePpiDescriptor ( + IN OUT EFI_PEI_PPI_DESCRIPTOR **ThisPpiList +) +{ + *ThisPpiList = mPrivateDispatchTable; + return EFI_SUCCESS; +} + +/** + Locates the main boot firmware volume. + + @param[in,out] BootFv On input, the base of the BootFv + On output, the decompressed main firmware volume + + @retval EFI_SUCCESS The main firmware volume was located and decompressed + @retval EFI_NOT_FOUND The main firmware volume was not found + +**/ +EFI_STATUS +FindMainFv ( + IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv + ) +{ + EFI_FIRMWARE_VOLUME_HEADER *Fv; + UINTN Distance; + + ASSERT (((UINTN)*BootFv & EFI_PAGE_MASK) == 0); + + Fv = *BootFv; + Distance = (UINTN)(*BootFv)->FvLength; + do { + Fv = (EFI_FIRMWARE_VOLUME_HEADER *)((UINT8 *)Fv + EFI_PAGE_SIZE); + Distance += EFI_PAGE_SIZE; + if (Distance > SIZE_32MB) { + return EFI_NOT_FOUND; + } + + if (Fv->Signature != EFI_FVH_SIGNATURE) { + continue; + } + + if ((UINTN)Fv->FvLength < Distance) { + continue; + } + + *BootFv = Fv; + return EFI_SUCCESS; + } while (TRUE); +} + +/** + Locates a section within a series of sections + with the specified section type. + + The Instance parameter indicates which instance of the section + type to return. (0 is first instance, 1 is second...) + + @param[in] Sections The sections to search + @param[in] SizeOfSections Total size of all sections + @param[in] SectionType The section type to locate + @param[in] Instance The section instance number + @param[out] FoundSection The FFS section if found + + @retval EFI_SUCCESS The file and section was found + @retval EFI_NOT_FOUND The file and section was not found + @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted + +**/ +EFI_STATUS +FindFfsSectionInstance ( + IN VOID *Sections, + IN UINTN SizeOfSections, + IN EFI_SECTION_TYPE SectionType, + IN UINTN Instance, + OUT EFI_COMMON_SECTION_HEADER **FoundSection + ) +{ + EFI_PHYSICAL_ADDRESS CurrentAddress; + UINT32 Size; + EFI_PHYSICAL_ADDRESS EndOfSections; + EFI_COMMON_SECTION_HEADER *Section; + EFI_PHYSICAL_ADDRESS EndOfSection; + + // + // Loop through the FFS file sections within the PEI Core FFS file + // + EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN)Sections; + EndOfSections = EndOfSection + SizeOfSections; + for ( ; ;) { + if (EndOfSection == EndOfSections) { + break; + } + + CurrentAddress = (EndOfSection + 3) & ~(3ULL); + if (CurrentAddress >= EndOfSections) { + return EFI_VOLUME_CORRUPTED; + } + + Section = (EFI_COMMON_SECTION_HEADER *)(UINTN)CurrentAddress; + + Size = SECTION_SIZE (Section); + if (Size < sizeof (*Section)) { + return EFI_VOLUME_CORRUPTED; + } + + EndOfSection = CurrentAddress + Size; + if (EndOfSection > EndOfSections) { + return EFI_VOLUME_CORRUPTED; + } + + // + // Look for the requested section type + // + if (Section->Type == SectionType) { + if (Instance == 0) { + *FoundSection = Section; + return EFI_SUCCESS; + } else { + Instance--; + } + } + } + + return EFI_NOT_FOUND; +} + +/** + Locates a section within a series of sections + with the specified section type. + + @param[in] Sections The sections to search + @param[in] SizeOfSections Total size of all sections + @param[in] SectionType The section type to locate + @param[out] FoundSection The FFS section if found + + @retval EFI_SUCCESS The file and section was found + @retval EFI_NOT_FOUND The file and section was not found + @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted + +**/ +EFI_STATUS +FindFfsSectionInSections ( + IN VOID *Sections, + IN UINTN SizeOfSections, + IN EFI_SECTION_TYPE SectionType, + OUT EFI_COMMON_SECTION_HEADER **FoundSection + ) +{ + return FindFfsSectionInstance ( + Sections, + SizeOfSections, + SectionType, + 0, + FoundSection + ); +} + +/** + Locates a FFS file with the specified file type and a section + within that file with the specified section type. + + @param[in] Fv The firmware volume to search + @param[in] FileType The file type to locate + @param[in] SectionType The section type to locate + @param[out] FoundSection The FFS section if found + + @retval EFI_SUCCESS The file and section was found + @retval EFI_NOT_FOUND The file and section was not found + @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted + +**/ +EFI_STATUS +FindFfsFileAndSection ( + IN EFI_FIRMWARE_VOLUME_HEADER *Fv, + IN EFI_FV_FILETYPE FileType, + IN EFI_SECTION_TYPE SectionType, + OUT EFI_COMMON_SECTION_HEADER **FoundSection + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS CurrentAddress; + EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume; + EFI_FFS_FILE_HEADER *File; + UINT32 Size; + EFI_PHYSICAL_ADDRESS EndOfFile; + + if (Fv->Signature != EFI_FVH_SIGNATURE) { + DEBUG ((DEBUG_ERROR, "FV at %p does not have FV header signature\n", Fv)); + return EFI_VOLUME_CORRUPTED; + } + + CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Fv; + EndOfFirmwareVolume = CurrentAddress + Fv->FvLength; + + // + // Loop through the FFS files in the Boot Firmware Volume + // + for (EndOfFile = CurrentAddress + Fv->HeaderLength; ; ) { + CurrentAddress = (EndOfFile + 7) & ~(7ULL); + if (CurrentAddress > EndOfFirmwareVolume) { + return EFI_VOLUME_CORRUPTED; + } + + File = (EFI_FFS_FILE_HEADER *)(UINTN)CurrentAddress; + Size = FFS_FILE_SIZE (File); + if (Size < (sizeof (*File) + sizeof (EFI_COMMON_SECTION_HEADER))) { + return EFI_VOLUME_CORRUPTED; + } + + EndOfFile = CurrentAddress + Size; + if (EndOfFile > EndOfFirmwareVolume) { + return EFI_VOLUME_CORRUPTED; + } + + // + // Look for the request file type + // + if (File->Type != FileType) { + continue; + } + + Status = FindFfsSectionInSections ( + (VOID *)(File + 1), + (UINTN)EndOfFile - (UINTN)(File + 1), + SectionType, + FoundSection + ); + if (!EFI_ERROR (Status) || (Status == EFI_VOLUME_CORRUPTED)) { + return Status; + } + } +} + +/** + Locates the compressed main firmware volume and decompresses it. + + @param[in,out] Fv On input, the firmware volume to search + On output, the decompressed BOOT/PEI FV + + @retval EFI_SUCCESS The file and section was found + @retval EFI_NOT_FOUND The file and section was not found + @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted + +**/ +EFI_STATUS +DecompressMemFvs ( + IN OUT EFI_FIRMWARE_VOLUME_HEADER **Fv + ) +{ + EFI_STATUS Status; + EFI_GUID_DEFINED_SECTION *Section; + UINT32 OutputBufferSize; + UINT32 ScratchBufferSize; + UINT16 SectionAttribute; + UINT32 AuthenticationStatus; + VOID *OutputBuffer; + VOID *ScratchBuffer; + EFI_COMMON_SECTION_HEADER *FvSection; + EFI_FIRMWARE_VOLUME_HEADER *PeiMemFv; + EFI_FIRMWARE_VOLUME_HEADER *DxeMemFv; + UINT32 FvHeaderSize; + UINT32 FvSectionSize; + + FvSection = (EFI_COMMON_SECTION_HEADER *)NULL; + + Status = FindFfsFileAndSection ( + *Fv, + EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, + EFI_SECTION_GUID_DEFINED, + (EFI_COMMON_SECTION_HEADER **)&Section + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Unable to find GUID defined section\n")); + return Status; + } + + Status = ExtractGuidedSectionGetInfo ( + Section, + &OutputBufferSize, + &ScratchBufferSize, + &SectionAttribute + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Unable to GetInfo for GUIDed section\n")); + return Status; + } + + OutputBuffer = (VOID *)((UINT8 *)(UINTN)PcdGet32 (PcdDxeMemFvBase) + SIZE_1MB); + ScratchBuffer = ALIGN_POINTER ((UINT8 *)OutputBuffer + OutputBufferSize, SIZE_1MB); + + Status = ExtractGuidedSectionDecode ( + Section, + &OutputBuffer, + ScratchBuffer, + &AuthenticationStatus + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Error during GUID section decode\n")); + return Status; + } + + Status = FindFfsSectionInstance ( + OutputBuffer, + OutputBufferSize, + EFI_SECTION_FIRMWARE_VOLUME_IMAGE, + 0, + &FvSection + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Unable to find PEI FV section\n")); + return Status; + } + + ASSERT ( + SECTION_SIZE (FvSection) == + (PcdGet32 (PcdPeiMemFvSize) + sizeof (*FvSection)) + ); + ASSERT (FvSection->Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE); + + PeiMemFv = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)PcdGet32 (PcdPeiMemFvBase); + CopyMem (PeiMemFv, (VOID *)(FvSection + 1), PcdGet32 (PcdPeiMemFvSize)); + + if (PeiMemFv->Signature != EFI_FVH_SIGNATURE) { + DEBUG ((DEBUG_ERROR, "Extracted FV at %p does not have FV header signature\n", PeiMemFv)); + CpuDeadLoop (); + return EFI_VOLUME_CORRUPTED; + } + + Status = FindFfsSectionInstance ( + OutputBuffer, + OutputBufferSize, + EFI_SECTION_FIRMWARE_VOLUME_IMAGE, + 1, + &FvSection + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Unable to find DXE FV section\n")); + return Status; + } + + ASSERT (FvSection->Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE); + + if (IS_SECTION2 (FvSection)) { + FvSectionSize = SECTION2_SIZE (FvSection); + FvHeaderSize = sizeof (EFI_COMMON_SECTION_HEADER2); + } else { + FvSectionSize = SECTION_SIZE (FvSection); + FvHeaderSize = sizeof (EFI_COMMON_SECTION_HEADER); + } + + ASSERT (FvSectionSize == (PcdGet32 (PcdDxeMemFvSize) + FvHeaderSize)); + + DxeMemFv = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)PcdGet32 (PcdDxeMemFvBase); + CopyMem (DxeMemFv, (VOID *)((UINTN)FvSection + FvHeaderSize), PcdGet32 (PcdDxeMemFvSize)); + + if (DxeMemFv->Signature != EFI_FVH_SIGNATURE) { + DEBUG ((DEBUG_ERROR, "Extracted FV at %p does not have FV header signature\n", DxeMemFv)); + CpuDeadLoop (); + return EFI_VOLUME_CORRUPTED; + } + *Fv = PeiMemFv; + return EFI_SUCCESS; +} + +/** + Locates the PEI Core entry point address + + @param[in] Fv The firmware volume to search + @param[out] PeiCoreEntryPoint The entry point of the PEI Core image + + @retval EFI_SUCCESS The file and section was found + @retval EFI_NOT_FOUND The file and section was not found + @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted + +**/ +EFI_STATUS +FindPeiCoreImageBaseInFv ( + IN EFI_FIRMWARE_VOLUME_HEADER *Fv, + OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase + ) +{ + EFI_STATUS Status; + EFI_COMMON_SECTION_HEADER *Section; + + Status = FindFfsFileAndSection ( + Fv, + EFI_FV_FILETYPE_PEI_CORE, + EFI_SECTION_PE32, + &Section + ); + if (EFI_ERROR (Status)) { + Status = FindFfsFileAndSection ( + Fv, + EFI_FV_FILETYPE_PEI_CORE, + EFI_SECTION_TE, + &Section + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Unable to find PEI Core image\n")); + return Status; + } + } + + *PeiCoreImageBase = (EFI_PHYSICAL_ADDRESS)(UINTN)(Section + 1); + return EFI_SUCCESS; +} + +/** + Locates the PEI Core entry point address + + @param[in,out] Fv The firmware volume to search + @param[out] PeiCoreEntryPoint The entry point of the PEI Core image + + @retval EFI_SUCCESS The file and section was found + @retval EFI_NOT_FOUND The file and section was not found + @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted + +**/ +VOID +FindPeiCoreImageBase ( + IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv, + OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase + ) +{ + + *PeiCoreImageBase = 0; + + FindMainFv (BootFv); + + DecompressMemFvs (BootFv); + + FindPeiCoreImageBaseInFv (*BootFv, PeiCoreImageBase); +} + +/** + Find core image base. + +**/ +EFI_STATUS +FindImageBase ( + IN EFI_FIRMWARE_VOLUME_HEADER *BootFirmwareVolumePtr, + OUT EFI_PHYSICAL_ADDRESS *SecCoreImageBase + ) +{ + EFI_PHYSICAL_ADDRESS CurrentAddress; + EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume; + EFI_FFS_FILE_HEADER *File; + UINT32 Size; + EFI_PHYSICAL_ADDRESS EndOfFile; + EFI_COMMON_SECTION_HEADER *Section; + EFI_PHYSICAL_ADDRESS EndOfSection; + + *SecCoreImageBase = 0; + + CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)BootFirmwareVolumePtr; + EndOfFirmwareVolume = CurrentAddress + BootFirmwareVolumePtr->FvLength; + + // + // Loop through the FFS files in the Boot Firmware Volume + // + for (EndOfFile = CurrentAddress + BootFirmwareVolumePtr->HeaderLength; ; ) { + CurrentAddress = (EndOfFile + 7) & 0xfffffffffffffff8ULL; + if (CurrentAddress > EndOfFirmwareVolume) { + return EFI_NOT_FOUND; + } + + File = (EFI_FFS_FILE_HEADER *)(UINTN)CurrentAddress; + Size = FFS_FILE_SIZE (File); + if (Size < sizeof (*File)) { + return EFI_NOT_FOUND; + } + + EndOfFile = CurrentAddress + Size; + if (EndOfFile > EndOfFirmwareVolume) { + return EFI_NOT_FOUND; + } + + // + // Look for SEC Core + // + if (File->Type != EFI_FV_FILETYPE_SECURITY_CORE) { + continue; + } + + // + // Loop through the FFS file sections within the FFS file + // + EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN)(File + 1); + for ( ; ;) { + CurrentAddress = (EndOfSection + 3) & 0xfffffffffffffffcULL; + Section = (EFI_COMMON_SECTION_HEADER *)(UINTN)CurrentAddress; + + Size = SECTION_SIZE (Section); + if (Size < sizeof (*Section)) { + return EFI_NOT_FOUND; + } + + EndOfSection = CurrentAddress + Size; + if (EndOfSection > EndOfFile) { + return EFI_NOT_FOUND; + } + + // + // Look for executable sections + // + if ((Section->Type == EFI_SECTION_PE32) || (Section->Type == EFI_SECTION_TE)) { + if (File->Type == EFI_FV_FILETYPE_SECURITY_CORE) { + *SecCoreImageBase = (PHYSICAL_ADDRESS)(UINTN)(Section + 1); + } + + break; + } + } + + // + // SEC Core image found + // + if (*SecCoreImageBase != 0) { + return EFI_SUCCESS; + } + } +} + +/* + Find and return Pei Core entry point. + + It also find SEC and PEI Core file debug information. It will report them if + remote debug is enabled. + +**/ +VOID +FindAndReportEntryPoints ( + IN EFI_FIRMWARE_VOLUME_HEADER **BootFirmwareVolumePtr, + OUT EFI_PEI_CORE_ENTRY_POINT *PeiCoreEntryPoint + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS SecCoreImageBase; + EFI_PHYSICAL_ADDRESS PeiCoreImageBase; + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + + // + // Find SEC Core and PEI Core image base + // + Status = FindImageBase (*BootFirmwareVolumePtr, &SecCoreImageBase); + ASSERT_EFI_ERROR (Status); + + FindPeiCoreImageBase (BootFirmwareVolumePtr, &PeiCoreImageBase); + + ZeroMem ((VOID *)&ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT)); + // + // Report SEC Core debug information when remote debug is enabled + // + ImageContext.ImageAddress = SecCoreImageBase; + ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageContext.ImageAddress); + PeCoffLoaderRelocateImageExtraAction (&ImageContext); + + // + // Report PEI Core debug information when remote debug is enabled + // + ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)PeiCoreImageBase; + ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageContext.ImageAddress); + PeCoffLoaderRelocateImageExtraAction (&ImageContext); + + // + // Find PEI Core entry point + // + Status = PeCoffLoaderGetEntryPoint ((VOID *)(UINTN)PeiCoreImageBase, (VOID **)PeiCoreEntryPoint); + if (EFI_ERROR (Status)) { + *PeiCoreEntryPoint = 0; + } + + return; +} + +/** + + Entry point to the C language phase of SEC. After the SEC assembly + code has initialized some temporary memory and set up the stack, + the control is transferred to this function. + + + @param[in] BootHartId Hardware thread ID of boot hart. + @param[in] DeviceTreeAddress Pointer to Device Tree (DTB) +**/ +VOID +NORETURN +EFIAPI +SecStartup ( + IN UINTN BootHartId, + IN VOID *DeviceTreeAddress + ) +{ + EFI_RISCV_FIRMWARE_CONTEXT FirmwareContext; + EFI_FIRMWARE_VOLUME_HEADER *BootFv; + EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint; + EFI_PEI_PPI_DESCRIPTOR *PpiList; + EFI_SEC_PEI_HAND_OFF SecCoreData; + EFI_STATUS Status; + + // + // Report Status Code to indicate entering SEC core + // + DEBUG (( + DEBUG_INFO, + "%a() BootHartId: 0x%x, DeviceTreeAddress=0x%x\n", + __FUNCTION__, + BootHartId, + DeviceTreeAddress + )); + + // + // Process all libraries constructor function linked to SecCore. + // + ProcessLibraryConstructorList (); + + BootFv = (EFI_FIRMWARE_VOLUME_HEADER *)FixedPcdGet32 (PcdSecMemFvBase); + + ASSERT(BootFv != NULL); + SecCoreData.DataSize = (UINT16)sizeof (EFI_SEC_PEI_HAND_OFF); + SecCoreData.BootFirmwareVolumeBase = BootFv; + SecCoreData.BootFirmwareVolumeSize = (UINTN)FixedPcdGet32 (PcdSecMemFvSize); + SecCoreData.TemporaryRamBase = (VOID *)(UINT64)FixedPcdGet32 (PcdSecPeiTempRamBase); + SecCoreData.TemporaryRamSize = (UINTN)FixedPcdGet32 (PcdSecPeiTempRamSize); + SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase; + SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize >> 1; + SecCoreData.StackBase = (UINT8 *)SecCoreData.TemporaryRamBase + (SecCoreData.TemporaryRamSize >> 1); + SecCoreData.StackSize = SecCoreData.TemporaryRamSize >> 1; + + DEBUG (( + DEBUG_INFO, + "%a() BFV Base: 0x%x, BFV Size: 0x%x, TempRAM Base: 0x%x, TempRAM Size: 0x%x, PeiTempRamBase: 0x%x, PeiTempRamSize: 0x%x, StackBase: 0x%x, StackSize: 0x%x\n", + __FUNCTION__, + SecCoreData.BootFirmwareVolumeBase, + SecCoreData.BootFirmwareVolumeSize, + SecCoreData.TemporaryRamBase, + SecCoreData.TemporaryRamSize, + SecCoreData.PeiTemporaryRamBase, + SecCoreData.PeiTemporaryRamSize, + SecCoreData.StackBase, + SecCoreData.StackSize + )); + + FindAndReportEntryPoints ( + &BootFv, + &PeiCoreEntryPoint + ); + if (PeiCoreEntryPoint == NULL) { + CpuDeadLoop (); + } + + SecCoreData.BootFirmwareVolumeBase = BootFv; + SecCoreData.BootFirmwareVolumeSize = (UINTN) BootFv->FvLength; + + Status = GetPlatformPrePeiCorePpiDescriptor (&PpiList); + if (EFI_ERROR (Status)) { + PpiList = NULL; + } + + FirmwareContext.BootHartId = BootHartId; + FirmwareContext.FlattenedDeviceTree = (UINT64)DeviceTreeAddress; + SetFirmwareContextPointer (&FirmwareContext); + + // + // Transfer the control to the PEI core + // + ASSERT (PeiCoreEntryPoint != NULL); + (*PeiCoreEntryPoint)(&SecCoreData, PpiList); + + // + // Should not come here. + // + UNREACHABLE (); +} diff --git a/UefiCpuPkg/SecCore/RiscV64/SecEntry.S b/UefiCpuPkg/SecCore/RiscV64/SecEntry.S new file mode 100644 index 000000000000..1bd0174e278e --- /dev/null +++ b/UefiCpuPkg/SecCore/RiscV64/SecEntry.S @@ -0,0 +1,23 @@ +/* + Copyright (c) 2021-2022 , Hewlett Packard Enterprise Development LP. All rights reserved. + Copyright (c) 2019 Western Digital Corporation or its affiliates. + Copyright (c) 2022 Ventana Micro Systems Inc. + + SPDX-License-Identifier: BSD-2-Clause-Patent + + */ + +#include "SecMain.h" + +.text +.align 3 + +ASM_FUNC (_ModuleEntryPoint) + /* Use Temp memory as the stack for calling to C code */ + li a4, FixedPcdGet32 (PcdSecPeiTempRamBase) + li a5, FixedPcdGet32 (PcdSecPeiTempRamSize) + + /* Use Temp memory as the stack for calling to C code */ + add sp, a4, a5 + + call SecStartup -- 2.25.1