StyxRngDxe.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /** @file
  2. This driver produces an EFI_RNG_PROTOCOL instance for the AMD Seattle CCP
  3. Copyright (C) 2016, Linaro Ltd. All rights reserved.<BR>
  4. This program and the accompanying materials are licensed and made available
  5. under the terms and conditions of the BSD License which accompanies this
  6. distribution. The full text of the license may be found at
  7. http://opensource.org/licenses/bsd-license.php
  8. THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
  9. WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
  10. **/
  11. #include <Library/BaseMemoryLib.h>
  12. #include <Library/PcdLib.h>
  13. #include <Library/IoLib.h>
  14. #include <Protocol/Rng.h>
  15. #define CCP_TRNG_OFFSET 0xc
  16. #define CCP_TNRG_RETRIES 5
  17. STATIC EFI_PHYSICAL_ADDRESS mCcpRngOutputReg;
  18. STATIC EFI_HANDLE mHandle;
  19. /**
  20. Returns information about the random number generation implementation.
  21. @param[in] This A pointer to the EFI_RNG_PROTOCOL
  22. instance.
  23. @param[in,out] RNGAlgorithmListSize On input, the size in bytes of
  24. RNGAlgorithmList.
  25. On output with a return code of
  26. EFI_SUCCESS, the size in bytes of the
  27. data returned in RNGAlgorithmList. On
  28. output with a return code of
  29. EFI_BUFFER_TOO_SMALL, the size of
  30. RNGAlgorithmList required to obtain the
  31. list.
  32. @param[out] RNGAlgorithmList A caller-allocated memory buffer filled
  33. by the driver with one EFI_RNG_ALGORITHM
  34. element for each supported RNG algorithm.
  35. The list must not change across multiple
  36. calls to the same driver. The first
  37. algorithm in the list is the default
  38. algorithm for the driver.
  39. @retval EFI_SUCCESS The RNG algorithm list was returned
  40. successfully.
  41. @retval EFI_UNSUPPORTED The services is not supported by this
  42. driver.
  43. @retval EFI_DEVICE_ERROR The list of algorithms could not be
  44. retrieved due to a hardware or firmware
  45. error.
  46. @retval EFI_INVALID_PARAMETER One or more of the parameters are
  47. incorrect.
  48. @retval EFI_BUFFER_TOO_SMALL The buffer RNGAlgorithmList is too small
  49. to hold the result.
  50. **/
  51. STATIC
  52. EFI_STATUS
  53. EFIAPI
  54. StyxRngGetInfo (
  55. IN EFI_RNG_PROTOCOL *This,
  56. IN OUT UINTN *RNGAlgorithmListSize,
  57. OUT EFI_RNG_ALGORITHM *RNGAlgorithmList
  58. )
  59. {
  60. if (This == NULL || RNGAlgorithmListSize == NULL) {
  61. return EFI_INVALID_PARAMETER;
  62. }
  63. if (*RNGAlgorithmListSize < sizeof (EFI_RNG_ALGORITHM)) {
  64. *RNGAlgorithmListSize = sizeof (EFI_RNG_ALGORITHM);
  65. return EFI_BUFFER_TOO_SMALL;
  66. }
  67. if (RNGAlgorithmList == NULL) {
  68. return EFI_INVALID_PARAMETER;
  69. }
  70. *RNGAlgorithmListSize = sizeof (EFI_RNG_ALGORITHM);
  71. CopyGuid (RNGAlgorithmList, &gEfiRngAlgorithmRaw);
  72. return EFI_SUCCESS;
  73. }
  74. /**
  75. Produces and returns an RNG value using either the default or specified RNG
  76. algorithm.
  77. @param[in] This A pointer to the EFI_RNG_PROTOCOL
  78. instance.
  79. @param[in] RNGAlgorithm A pointer to the EFI_RNG_ALGORITHM that
  80. identifies the RNG algorithm to use. May
  81. be NULL in which case the function will
  82. use its default RNG algorithm.
  83. @param[in] RNGValueLength The length in bytes of the memory buffer
  84. pointed to by RNGValue. The driver shall
  85. return exactly this numbers of bytes.
  86. @param[out] RNGValue A caller-allocated memory buffer filled
  87. by the driver with the resulting RNG
  88. value.
  89. @retval EFI_SUCCESS The RNG value was returned successfully.
  90. @retval EFI_UNSUPPORTED The algorithm specified by RNGAlgorithm
  91. is not supported by this driver.
  92. @retval EFI_DEVICE_ERROR An RNG value could not be retrieved due
  93. to a hardware or firmware error.
  94. @retval EFI_NOT_READY There is not enough random data available
  95. to satisfy the length requested by
  96. RNGValueLength.
  97. @retval EFI_INVALID_PARAMETER RNGValue is NULL or RNGValueLength is
  98. zero.
  99. **/
  100. STATIC
  101. EFI_STATUS
  102. EFIAPI
  103. StyxRngGetRNG (
  104. IN EFI_RNG_PROTOCOL *This,
  105. IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL
  106. IN UINTN RNGValueLength,
  107. OUT UINT8 *RNGValue
  108. )
  109. {
  110. UINT32 Val;
  111. UINT32 Retries;
  112. UINT32 Loop;
  113. if (This == NULL || RNGValueLength == 0 || RNGValue == NULL) {
  114. return EFI_INVALID_PARAMETER;
  115. }
  116. //
  117. // We only support the raw algorithm, so reject requests for anything else
  118. //
  119. if (RNGAlgorithm != NULL &&
  120. !CompareGuid (RNGAlgorithm, &gEfiRngAlgorithmRaw)) {
  121. return EFI_UNSUPPORTED;
  122. }
  123. do {
  124. Retries = CCP_TNRG_RETRIES;
  125. do {
  126. Val = MmioRead32 (mCcpRngOutputReg);
  127. } while (!Val && Retries-- > 0);
  128. if (!Val) {
  129. return EFI_DEVICE_ERROR;
  130. }
  131. for (Loop = 0; Loop < 4 && RNGValueLength > 0; Loop++, RNGValueLength--) {
  132. *RNGValue++ = (UINT8)Val;
  133. Val >>= 8;
  134. }
  135. } while (RNGValueLength > 0);
  136. return EFI_SUCCESS;
  137. }
  138. STATIC EFI_RNG_PROTOCOL mStyxRngProtocol = {
  139. StyxRngGetInfo,
  140. StyxRngGetRNG
  141. };
  142. //
  143. // Entry point of this driver.
  144. //
  145. EFI_STATUS
  146. EFIAPI
  147. StyxRngEntryPoint (
  148. IN EFI_HANDLE ImageHandle,
  149. IN EFI_SYSTEM_TABLE *SystemTable
  150. )
  151. {
  152. mCcpRngOutputReg = PcdGet64 (PcdCCPBase) + CCP_TRNG_OFFSET;
  153. return SystemTable->BootServices->InstallMultipleProtocolInterfaces (
  154. &mHandle,
  155. &gEfiRngProtocolGuid, &mStyxRngProtocol,
  156. NULL
  157. );
  158. }