mirror of https://github.com/acidanthera/audk.git
96 lines
2.2 KiB
C
96 lines
2.2 KiB
C
/** @file
|
|
Arm Monitor Library that chooses the conduit based on the PSCI node in the
|
|
device tree provided by QEMU
|
|
|
|
Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
|
|
Copyright (c) 2024, Google LLC. All rights reserved.<BR>
|
|
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
**/
|
|
|
|
#include <PiDxe.h>
|
|
|
|
#include <Library/BaseLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/ArmHvcLib.h>
|
|
#include <Library/ArmMonitorLib.h>
|
|
#include <Library/ArmSmcLib.h>
|
|
#include <Library/UefiBootServicesTableLib.h>
|
|
|
|
#include <Protocol/FdtClient.h>
|
|
|
|
STATIC UINT32 mArmSmcccMethod;
|
|
|
|
/** Library constructor.
|
|
|
|
Assign the global variable mArmSmcccMethod based on the PSCI node in the
|
|
device tree.
|
|
**/
|
|
RETURN_STATUS
|
|
EFIAPI
|
|
ArmVirtQemuMonitorLibConstructor (
|
|
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));
|
|
}
|
|
}
|