1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335
|
/** @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;
}
|