/** @file Arm Monitor Library that chooses the conduit based on the PSCI node in the device tree provided by the VMM. Copyright (c) 2022, Arm Limited. All rights reserved.
Copyright (c) 2024, Google LLC. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include #include #include #include #include #include #include STATIC UINT32 mArmSmcccMethod; /** Library constructor. Assign the global variable mArmSmcccMethod based on the PSCI node in the device tree. **/ RETURN_STATUS EFIAPI ArmVirtMonitorLibConstructor ( VOID ) { EFI_STATUS Status; FDT_CLIENT_PROTOCOL *FdtClient; CONST VOID *Prop; Status = gBS->LocateProtocol ( &gFdtClientProtocolGuid, NULL, (VOID **)&FdtClient ); ASSERT_EFI_ERROR (Status); Status = FdtClient->FindCompatibleNodeProperty ( FdtClient, "arm,psci-0.2", "method", &Prop, NULL ); if (EFI_ERROR (Status)) { return Status; } if (AsciiStrnCmp (Prop, "hvc", 3) == 0) { mArmSmcccMethod = 1; } else if (AsciiStrnCmp (Prop, "smc", 3) == 0) { mArmSmcccMethod = 2; } else { DEBUG (( DEBUG_ERROR, "%a: Unknown SMCCC method \"%a\"\n", __func__, Prop )); return EFI_NOT_FOUND; } return EFI_SUCCESS; } /** Monitor call. An HyperVisor Call (HVC) or System Monitor Call (SMC) will be issued depending on the default conduit. @param [in,out] Args Arguments for the HVC/SMC. **/ VOID EFIAPI ArmMonitorCall ( IN OUT ARM_MONITOR_ARGS *Args ) { if (mArmSmcccMethod == 1) { ArmCallHvc ((ARM_HVC_ARGS *)Args); } else if (mArmSmcccMethod == 2) { ArmCallSmc ((ARM_SMC_ARGS *)Args); } else { ASSERT ((mArmSmcccMethod == 1) || (mArmSmcccMethod == 2)); } }