/** @file Instance of the SBI ecall library. It allows calling an SBI function via an ecall from S-Mode. Copyright (c) 2021-2022, Hewlett Packard Development LP. All rights reserved.
Copyright (c) 2023, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include #include #include // // Maximum arguments for SBI ecall #define SBI_CALL_MAX_ARGS 6 /** Call SBI call using ecall instruction. Asserts when NumArgs exceeds SBI_CALL_MAX_ARGS. @param[in] ExtId SBI extension ID. @param[in] FuncId SBI function ID. @param[in] NumArgs Number of arguments to pass to the ecall. @param[in] ... Argument list for the ecall. @retval Returns SBI_RET structure with value and error code. **/ SBI_RET EFIAPI SbiCall ( IN UINTN ExtId, IN UINTN FuncId, IN UINTN NumArgs, ... ) { UINTN I; SBI_RET Ret; UINTN Args[SBI_CALL_MAX_ARGS]; VA_LIST ArgList; VA_START (ArgList, NumArgs); if (NumArgs > SBI_CALL_MAX_ARGS) { Ret.Error = SBI_ERR_INVALID_PARAM; Ret.Value = -1; return Ret; } for (I = 0; I < SBI_CALL_MAX_ARGS; I++) { if (I < NumArgs) { Args[I] = VA_ARG (ArgList, UINTN); } else { // Default to 0 for all arguments that are not given Args[I] = 0; } } VA_END (ArgList); // ECALL updates the a0 and a1 registers as return values. RiscVSbiEcall ( &Args[0], &Args[1], Args[2], Args[3], Args[4], Args[5], (UINTN)(FuncId), (UINTN)(ExtId) ); Ret.Error = Args[0]; Ret.Value = Args[1]; return Ret; } /** Translate SBI error code to EFI status. @param[in] SbiError SBI error code @retval EFI_STATUS **/ EFI_STATUS EFIAPI TranslateError ( IN UINTN SbiError ) { switch (SbiError) { case SBI_SUCCESS: return EFI_SUCCESS; case SBI_ERR_FAILED: return EFI_DEVICE_ERROR; break; case SBI_ERR_NOT_SUPPORTED: return EFI_UNSUPPORTED; break; case SBI_ERR_INVALID_PARAM: return EFI_INVALID_PARAMETER; break; case SBI_ERR_DENIED: return EFI_ACCESS_DENIED; break; case SBI_ERR_INVALID_ADDRESS: return EFI_LOAD_ERROR; break; case SBI_ERR_ALREADY_AVAILABLE: return EFI_ALREADY_STARTED; break; default: // // Reaches here only if SBI has defined a new error type // ASSERT (FALSE); return EFI_UNSUPPORTED; break; } } /** Clear pending timer interrupt bit and set timer for next event after Time. To clear the timer without scheduling a timer event, set Time to a practically infinite value or mask the timer interrupt by clearing sie.STIE. @param[in] Time The time offset to the next scheduled timer interrupt. **/ VOID EFIAPI SbiSetTimer ( IN UINT64 Time ) { SbiCall (SBI_EXT_TIME, SBI_EXT_TIME_SET_TIMER, 1, Time); } /** Reset the system using SRST SBI extenion @param[in] ResetType The SRST System Reset Type. @param[in] ResetReason The SRST System Reset Reason. **/ EFI_STATUS EFIAPI SbiSystemReset ( IN UINTN ResetType, IN UINTN ResetReason ) { SBI_RET Ret; Ret = SbiCall ( SBI_EXT_SRST, SBI_EXT_SRST_RESET, 2, ResetType, ResetReason ); return TranslateError (Ret.Error); } /** Get firmware context of the calling hart. @param[out] FirmwareContext The firmware context pointer. **/ VOID EFIAPI GetFirmwareContext ( OUT EFI_RISCV_FIRMWARE_CONTEXT **FirmwareContext ) { *FirmwareContext = (EFI_RISCV_FIRMWARE_CONTEXT *)RiscVGetSupervisorScratch (); } /** Set firmware context of the calling hart. @param[in] FirmwareContext The firmware context pointer. **/ VOID EFIAPI SetFirmwareContext ( IN EFI_RISCV_FIRMWARE_CONTEXT *FirmwareContext ) { RiscVSetSupervisorScratch ((UINT64)FirmwareContext); } /** Get pointer to OpenSBI Firmware Context Get the pointer of firmware context through OpenSBI FW Extension SBI. @param FirmwareContextPtr Pointer to retrieve pointer to the Firmware Context. **/ VOID EFIAPI GetFirmwareContextPointer ( IN OUT EFI_RISCV_FIRMWARE_CONTEXT **FirmwareContextPtr ) { GetFirmwareContext (FirmwareContextPtr); } /** Set the pointer to OpenSBI Firmware Context Set the pointer of firmware context through OpenSBI FW Extension SBI. @param FirmwareContextPtr Pointer to Firmware Context. **/ VOID EFIAPI SetFirmwareContextPointer ( IN EFI_RISCV_FIRMWARE_CONTEXT *FirmwareContextPtr ) { SetFirmwareContext (FirmwareContextPtr); }