-//\r
-// Bit mask used to determine if RdRand instruction is supported.\r
-//\r
-#define RDRAND_MASK 0x40000000\r
-\r
-/**\r
- Determines whether or not RDRAND instruction is supported by the host hardware.\r
-\r
- @retval EFI_SUCCESS RDRAND instruction supported.\r
- @retval EFI_UNSUPPORTED RDRAND instruction not supported.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-IsRdRandSupported (\r
- VOID\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINT32 RegEax;\r
- UINT32 RegEbx;\r
- UINT32 RegEcx;\r
- UINT32 RegEdx;\r
- BOOLEAN IsIntelCpu;\r
-\r
- Status = EFI_UNSUPPORTED;\r
- IsIntelCpu = FALSE;\r
- \r
- //\r
- // Checks whether the current processor is an Intel product by CPUID.\r
- //\r
- AsmCpuid (0, &RegEax, &RegEbx, &RegEcx, &RegEdx);\r
- if ((CompareMem ((CHAR8 *)(&RegEbx), "Genu", 4) == 0) &&\r
- (CompareMem ((CHAR8 *)(&RegEdx), "ineI", 4) == 0) &&\r
- (CompareMem ((CHAR8 *)(&RegEcx), "ntel", 4) == 0)) {\r
- IsIntelCpu = TRUE;\r
- }\r
-\r
- if (IsIntelCpu) {\r
- //\r
- // Determine RDRAND support by examining bit 30 of the ECX register returned by CPUID.\r
- // A value of 1 indicates that processor supports RDRAND instruction.\r
- //\r
- AsmCpuid (1, 0, 0, &RegEcx, 0);\r
-\r
- if ((RegEcx & RDRAND_MASK) == RDRAND_MASK) {\r
- Status = EFI_SUCCESS;\r
- }\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Calls RDRAND to obtain a 16-bit random number.\r
-\r
- @param[out] Rand Buffer pointer to store the random result.\r
- @param[in] NeedRetry Determine whether or not to loop retry.\r
-\r
- @retval EFI_SUCCESS RDRAND call was successful.\r
- @retval EFI_NOT_READY Failed attempts to call RDRAND.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-RdRand16 (\r
- OUT UINT16 *Rand,\r
- IN BOOLEAN NeedRetry\r
- )\r
-{\r
- UINT32 Index;\r
- UINT32 RetryCount;\r
-\r
- if (NeedRetry) {\r
- RetryCount = RETRY_LIMIT;\r
- } else {\r
- RetryCount = 1;\r
- }\r
-\r
- //\r
- // Perform a single call to RDRAND, or enter a loop call until RDRAND succeeds.\r
- //\r
- for (Index = 0; Index < RetryCount; Index++) {\r
- if (RdRand16Step (Rand)) {\r
- return EFI_SUCCESS;\r
- }\r
- }\r
- \r
- return EFI_NOT_READY;\r
-}\r
-\r
-/**\r
- Calls RDRAND to obtain a 32-bit random number.\r
-\r
- @param[out] Rand Buffer pointer to store the random result.\r
- @param[in] NeedRetry Determine whether or not to loop retry.\r
-\r
- @retval EFI_SUCCESS RDRAND call was successful.\r
- @retval EFI_NOT_READY Failed attempts to call RDRAND.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-RdRand32 (\r
- OUT UINT32 *Rand,\r
- IN BOOLEAN NeedRetry\r
- )\r
-{\r
- UINT32 Index;\r
- UINT32 RetryCount;\r
-\r
- if (NeedRetry) {\r
- RetryCount = RETRY_LIMIT;\r
- } else {\r
- RetryCount = 1;\r
- }\r
-\r
- //\r
- // Perform a single call to RDRAND, or enter a loop call until RDRAND succeeds.\r
- //\r
- for (Index = 0; Index < RetryCount; Index++) {\r
- if (RdRand32Step (Rand)) {\r
- return EFI_SUCCESS;\r
- }\r
- }\r
- \r
- return EFI_NOT_READY;\r
-}\r
-\r
-/**\r
- Calls RDRAND to obtain a 64-bit random number.\r
-\r
- @param[out] Rand Buffer pointer to store the random result.\r
- @param[in] NeedRetry Determine whether or not to loop retry.\r
-\r
- @retval EFI_SUCCESS RDRAND call was successful.\r
- @retval EFI_NOT_READY Failed attempts to call RDRAND.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-RdRand64 (\r
- OUT UINT64 *Rand,\r
- IN BOOLEAN NeedRetry\r
- )\r
-{\r
- UINT32 Index;\r
- UINT32 RetryCount;\r
-\r
- if (NeedRetry) {\r
- RetryCount = RETRY_LIMIT;\r
- } else {\r
- RetryCount = 1;\r
- }\r
-\r
- //\r
- // Perform a single call to RDRAND, or enter a loop call until RDRAND succeeds.\r
- //\r
- for (Index = 0; Index < RetryCount; Index++) {\r
- if (RdRand64Step (Rand)) {\r
- return EFI_SUCCESS;\r
- }\r
- }\r
- \r
- return EFI_NOT_READY;\r
-}\r
-\r