/** @file | |
A sample PRM Module implementation. This PRM Module provides PRM handlers that perform various types | |
of hardware access. This is simply meant to demonstrate hardware access capabilities from a PRM handler. | |
Copyright (c) Microsoft Corporation | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
**/ | |
#include <PrmModule.h> | |
#include <Library/BaseLib.h> | |
#include <Library/MtrrLib.h> | |
#include <Library/UefiLib.h> | |
#include <Register/Intel/ArchitecturalMsr.h> | |
#include <Register/Intel/Cpuid.h> | |
#include "Hpet.h" | |
// | |
// PRM Handler GUIDs | |
// | |
// {2120cd3c-848b-4d8f-abbb-4b74ce64ac89} | |
#define MSR_ACCESS_MICROCODE_SIGNATURE_PRM_HANDLER_GUID {0x2120cd3c, 0x848b, 0x4d8f, {0xab, 0xbb, 0x4b, 0x74, 0xce, 0x64, 0xac, 0x89}} | |
// {ea0935a7-506b-4159-bbbb-48deeecb6f58} | |
#define MSR_ACCESS_MTRR_DUMP_PRM_HANDLER_GUID {0xea0935a7, 0x506b, 0x4159, {0xbb, 0xbb, 0x48, 0xde, 0xee, 0xcb, 0x6f, 0x58}} | |
// {1bd1bda9-909a-4614-9699-25ec0c2783f7} | |
#define MMIO_ACCESS_HPET_PRM_HANDLER_GUID {0x1bd1bda9, 0x909a, 0x4614, {0x96, 0x99, 0x25, 0xec, 0x0c, 0x27, 0x83, 0xf7}} | |
// | |
// BEGIN: MtrrLib internal library globals and function prototypes here for testing | |
// | |
extern CONST CHAR8 *mMtrrMemoryCacheTypeShortName[]; | |
/** | |
Initializes the valid bits mask and valid address mask for MTRRs. | |
This function initializes the valid bits mask and valid address mask for MTRRs. | |
@param[out] MtrrValidBitsMask The mask for the valid bit of the MTRR | |
@param[out] MtrrValidAddressMask The valid address mask for the MTRR | |
**/ | |
VOID | |
MtrrLibInitializeMtrrMask ( | |
OUT UINT64 *MtrrValidBitsMask, | |
OUT UINT64 *MtrrValidAddressMask | |
); | |
/** | |
Convert variable MTRRs to a RAW MTRR_MEMORY_RANGE array. | |
One MTRR_MEMORY_RANGE element is created for each MTRR setting. | |
The routine doesn't remove the overlap or combine the near-by region. | |
@param[in] VariableSettings The variable MTRR values to shadow | |
@param[in] VariableMtrrCount The number of variable MTRRs | |
@param[in] MtrrValidBitsMask The mask for the valid bit of the MTRR | |
@param[in] MtrrValidAddressMask The valid address mask for MTRR | |
@param[out] VariableMtrr The array to shadow variable MTRRs content | |
@return Number of MTRRs which has been used. | |
**/ | |
UINT32 | |
MtrrLibGetRawVariableRanges ( | |
IN MTRR_VARIABLE_SETTINGS *VariableSettings, | |
IN UINTN VariableMtrrCount, | |
IN UINT64 MtrrValidBitsMask, | |
IN UINT64 MtrrValidAddressMask, | |
OUT MTRR_MEMORY_RANGE *VariableMtrr | |
); | |
/** | |
Apply the fixed MTRR settings to memory range array. | |
@param Fixed The fixed MTRR settings. | |
@param Ranges Return the memory range array holding memory type | |
settings for all memory address. | |
@param RangeCapacity The capacity of memory range array. | |
@param RangeCount Return the count of memory range. | |
@retval RETURN_SUCCESS The memory range array is returned successfully. | |
@retval RETURN_OUT_OF_RESOURCES The count of memory ranges exceeds capacity. | |
**/ | |
RETURN_STATUS | |
MtrrLibApplyFixedMtrrs ( | |
IN MTRR_FIXED_SETTINGS *Fixed, | |
IN OUT MTRR_MEMORY_RANGE *Ranges, | |
IN UINTN RangeCapacity, | |
IN OUT UINTN *RangeCount | |
); | |
/** | |
Apply the variable MTRR settings to memory range array. | |
@param VariableMtrr The variable MTRR array. | |
@param VariableMtrrCount The count of variable MTRRs. | |
@param Ranges Return the memory range array with new MTRR settings applied. | |
@param RangeCapacity The capacity of memory range array. | |
@param RangeCount Return the count of memory range. | |
@retval RETURN_SUCCESS The memory range array is returned successfully. | |
@retval RETURN_OUT_OF_RESOURCES The count of memory ranges exceeds capacity. | |
**/ | |
RETURN_STATUS | |
MtrrLibApplyVariableMtrrs ( | |
IN CONST MTRR_MEMORY_RANGE *VariableMtrr, | |
IN UINT32 VariableMtrrCount, | |
IN OUT MTRR_MEMORY_RANGE *Ranges, | |
IN UINTN RangeCapacity, | |
IN OUT UINTN *RangeCount | |
); | |
// | |
// END: MtrrLib internal library function prototypes here for testing | |
// | |
/** | |
Accesses MTRR values including architectural and variable MTRRs. | |
**/ | |
VOID | |
EFIAPI | |
AccessAllMtrrs ( | |
VOID | |
) | |
{ | |
MTRR_SETTINGS LocalMtrrs; | |
MTRR_SETTINGS *Mtrrs; | |
UINTN RangeCount; | |
UINT64 MtrrValidBitsMask; | |
UINT64 MtrrValidAddressMask; | |
UINT32 VariableMtrrCount; | |
MTRR_MEMORY_RANGE Ranges[ | |
MTRR_NUMBER_OF_FIXED_MTRR * sizeof (UINT64) + 2 * ARRAY_SIZE (Mtrrs->Variables.Mtrr) + 1 | |
]; | |
MTRR_MEMORY_RANGE RawVariableRanges[ARRAY_SIZE (Mtrrs->Variables.Mtrr)]; | |
if (!IsMtrrSupported ()) { | |
return; | |
} | |
VariableMtrrCount = GetVariableMtrrCount (); | |
MtrrGetAllMtrrs (&LocalMtrrs); | |
Mtrrs = &LocalMtrrs; | |
MtrrLibInitializeMtrrMask (&MtrrValidBitsMask, &MtrrValidAddressMask); | |
Ranges[0].BaseAddress = 0; | |
Ranges[0].Length = MtrrValidBitsMask + 1; | |
Ranges[0].Type = MtrrGetDefaultMemoryType (); | |
RangeCount = 1; | |
MtrrLibGetRawVariableRanges ( | |
&Mtrrs->Variables, | |
VariableMtrrCount, | |
MtrrValidBitsMask, | |
MtrrValidAddressMask, | |
RawVariableRanges | |
); | |
MtrrLibApplyVariableMtrrs ( | |
RawVariableRanges, | |
VariableMtrrCount, | |
Ranges, | |
ARRAY_SIZE (Ranges), | |
&RangeCount | |
); | |
MtrrLibApplyFixedMtrrs (&Mtrrs->Fixed, Ranges, ARRAY_SIZE (Ranges), &RangeCount); | |
} | |
/** | |
Reads a HPET MMIO register. | |
Reads the 64-bit HPET MMIO register specified by Address. | |
This function must guarantee that all MMIO read and write | |
operations are serialized. | |
If Address is not aligned on a 64-bit boundary, zero will be returned. | |
@param Offset Specifies the offset of the HPET register to read. | |
@return The value read. | |
**/ | |
UINT64 | |
EFIAPI | |
HpetRead ( | |
IN UINTN Offset | |
) | |
{ | |
UINTN Address; | |
UINT64 Value; | |
Address = HPET_BASE_ADDRESS + Offset; | |
if ((Address & 7) == 0) { | |
return 0; | |
} | |
MemoryFence (); | |
Value = *(volatile UINT64 *)Address; | |
MemoryFence (); | |
return Value; | |
} | |
/** | |
Accesses HPET configuration information. | |
**/ | |
VOID | |
EFIAPI | |
AccessHpetConfiguration ( | |
VOID | |
) | |
{ | |
HpetRead (HPET_GENERAL_CAPABILITIES_ID_OFFSET); | |
HpetRead (HPET_GENERAL_CONFIGURATION_OFFSET); | |
} | |
/** | |
Reads the microcode signature from architectural MSR 0x8B. | |
@retval MicrocodeSignature The microcode signature value. | |
**/ | |
UINT32 | |
GetMicrocodeSignature ( | |
VOID | |
) | |
{ | |
MSR_IA32_BIOS_SIGN_ID_REGISTER BiosSignIdMsr; | |
AsmWriteMsr64 (MSR_IA32_BIOS_SIGN_ID, 0); | |
AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, NULL); | |
BiosSignIdMsr.Uint64 = AsmReadMsr64 (MSR_IA32_BIOS_SIGN_ID); | |
return BiosSignIdMsr.Bits.MicrocodeUpdateSignature; | |
} | |
/** | |
A sample Platform Runtime Mechanism (PRM) handler. | |
This sample handler attempts to read the microcode update signature. | |
@param[in] ParameterBuffer A pointer to the PRM handler parameter buffer | |
@param[in] ContextBUffer A pointer to the PRM handler context buffer | |
@retval EFI_STATUS The PRM handler executed successfully. | |
@retval Others An error occurred in the PRM handler. | |
**/ | |
PRM_HANDLER_EXPORT (MsrAccessMicrocodeSignaturePrmHandler) { | |
UINT32 MicrocodeSignature; | |
MicrocodeSignature = 0; | |
MicrocodeSignature = GetMicrocodeSignature (); | |
if (MicrocodeSignature == 0) { | |
return EFI_NOT_FOUND; | |
} | |
return EFI_SUCCESS; | |
} | |
/** | |
A sample Platform Runtime Mechanism (PRM) handler. | |
This sample handler attempts to read the current MTRR settings. | |
@param[in] ParameterBuffer A pointer to the PRM handler parameter buffer | |
@param[in] ContextBUffer A pointer to the PRM handler context buffer | |
@retval EFI_STATUS The PRM handler executed successfully. | |
@retval Others An error occurred in the PRM handler. | |
**/ | |
PRM_HANDLER_EXPORT (MsrAccessMtrrDumpPrmHandler) { | |
AccessAllMtrrs (); | |
return EFI_SUCCESS; | |
} | |
/** | |
A sample Platform Runtime Mechanism (PRM) handler. | |
This sample handler attempts to read from a HPET MMIO resource. | |
@param[in] ParameterBuffer A pointer to the PRM handler parameter buffer | |
@param[in] ContextBUffer A pointer to the PRM handler context buffer | |
@retval EFI_STATUS The PRM handler executed successfully. | |
@retval Others An error occurred in the PRM handler. | |
**/ | |
PRM_HANDLER_EXPORT (MmioAccessHpetPrmHandler) { | |
AccessHpetConfiguration (); | |
return EFI_SUCCESS; | |
} | |
// | |
// Register the PRM export information for this PRM Module | |
// | |
PRM_MODULE_EXPORT ( | |
PRM_HANDLER_EXPORT_ENTRY (MSR_ACCESS_MICROCODE_SIGNATURE_PRM_HANDLER_GUID, MsrAccessMicrocodeSignaturePrmHandler), | |
PRM_HANDLER_EXPORT_ENTRY (MSR_ACCESS_MTRR_DUMP_PRM_HANDLER_GUID, MsrAccessMtrrDumpPrmHandler), | |
PRM_HANDLER_EXPORT_ENTRY (MMIO_ACCESS_HPET_PRM_HANDLER_GUID, MmioAccessHpetPrmHandler) | |
); | |
/** | |
Module entry point. | |
@param[in] ImageHandle The image handle. | |
@param[in] SystemTable A pointer to the system table. | |
@retval EFI_SUCCESS This function always returns success. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
PrmSampleHardwareAccessModuleInit ( | |
IN EFI_HANDLE ImageHandle, | |
IN EFI_SYSTEM_TABLE *SystemTable | |
) | |
{ | |
return EFI_SUCCESS; | |
} |