IpmiProtocolCommon.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /** @file
  2. IPMI Manageability Protocol common file.
  3. Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include <Uefi.h>
  7. #include <Library/BaseMemoryLib.h>
  8. #include <Library/DebugLib.h>
  9. #include <Library/MemoryAllocationLib.h>
  10. #include <Library/ManageabilityTransportIpmiLib.h>
  11. #include <Library/ManageabilityTransportLib.h>
  12. #include "IpmiProtocolCommon.h"
  13. /**
  14. This functions setup the IPMI transport hardware information according
  15. to the specification of transport token acquired from transport library.
  16. @param[in] TransportToken The transport interface.
  17. @param[out] HardwareInformation Pointer to receive the hardware information.
  18. @retval EFI_SUCCESS Hardware information is returned in HardwareInformation.
  19. Caller must free the memory allocated for HardwareInformation
  20. once it doesn't need it.
  21. @retval EFI_UNSUPPORTED No hardware information for the specification specified
  22. in the transport token.
  23. #retval EFI_OUT_OF_RESOURCES Not enough memory for MANAGEABILITY_TRANSPORT_KCS_HARDWARE_INFO.
  24. **/
  25. EFI_STATUS
  26. SetupIpmiTransportHardwareInformation (
  27. IN MANAGEABILITY_TRANSPORT_TOKEN *TransportToken,
  28. OUT MANAGEABILITY_TRANSPORT_HARDWARE_INFORMATION *HardwareInformation
  29. )
  30. {
  31. MANAGEABILITY_TRANSPORT_KCS_HARDWARE_INFO *KcsHardwareInfo;
  32. KcsHardwareInfo = AllocatePool (sizeof (MANAGEABILITY_TRANSPORT_KCS_HARDWARE_INFO));
  33. if (KcsHardwareInfo == NULL) {
  34. DEBUG ((DEBUG_ERROR, "%a: Not enough memory for MANAGEABILITY_TRANSPORT_KCS_HARDWARE_INFO.\n", __FUNCTION__));
  35. return EFI_OUT_OF_RESOURCES;
  36. }
  37. if (CompareGuid (&gManageabilityTransportKcsGuid, TransportToken->Transport->ManageabilityTransportSpecification)) {
  38. // This is KCS transport interface.
  39. KcsHardwareInfo->MemoryMap = MANAGEABILITY_TRANSPORT_KCS_IO_MAP_IO;
  40. KcsHardwareInfo->IoBaseAddress.IoAddress16 = IPMI_KCS_BASE_ADDRESS;
  41. KcsHardwareInfo->IoDataInAddress.IoAddress16 = IPMI_KCS_REG_DATA_IN;
  42. KcsHardwareInfo->IoDataOutAddress.IoAddress16 = IPMI_KCS_REG_DATA_OUT;
  43. KcsHardwareInfo->IoCommandAddress.IoAddress16 = IPMI_KCS_REG_COMMAND;
  44. KcsHardwareInfo->IoStatusAddress.IoAddress16 = IPMI_KCS_REG_STATUS;
  45. *HardwareInformation =
  46. (MANAGEABILITY_TRANSPORT_HARDWARE_INFORMATION)KcsHardwareInfo;
  47. return EFI_SUCCESS;
  48. } else {
  49. DEBUG ((DEBUG_ERROR, "%a: No implementation of setting hardware information.", __FUNCTION__));
  50. ASSERT (FALSE);
  51. }
  52. return EFI_UNSUPPORTED;
  53. }
  54. /**
  55. This functions setup the final header/body/trailer packets for
  56. the acquired transport interface.
  57. @param[in] TransportToken The transport interface.
  58. @param[in] NetFunction IPMI function.
  59. @param[in] Command IPMI command.
  60. @param[out] PacketHeader The pointer to receive header of request.
  61. @param[in, out] PacketBody The request body.
  62. When IN, it is the caller's request body.
  63. When OUT and NULL, the request body is not
  64. changed.
  65. When OUT and non-NULL, the request body is
  66. changed to conform the transport interface.
  67. @param[in, out] PacketBodySize The request body size.
  68. When OUT and non-zero, it is the new data
  69. length of request body.
  70. When OUT and zero, the request body is unchanged.
  71. @param[out] PacketTrailer The pointer to receive trailer of request.
  72. @retval EFI_SUCCESS Request packet is returned.
  73. @retval EFI_UNSUPPORTED Request packet is not returned because
  74. the unsupported transport interface.
  75. **/
  76. EFI_STATUS
  77. SetupIpmiRequestTransportPacket (
  78. IN MANAGEABILITY_TRANSPORT_TOKEN *TransportToken,
  79. IN UINT8 NetFunction,
  80. IN UINT8 Command,
  81. OUT MANAGEABILITY_TRANSPORT_HEADER *PacketHeader OPTIONAL,
  82. IN OUT UINT8 **PacketBody OPTIONAL,
  83. IN OUT UINT32 *PacketBodySize OPTIONAL,
  84. OUT MANAGEABILITY_TRANSPORT_TRAILER *PacketTrailer OPTIONAL
  85. )
  86. {
  87. MANAGEABILITY_IPMI_TRANSPORT_HEADER *IpmiHeader;
  88. if (CompareGuid (&gManageabilityTransportKcsGuid, TransportToken->Transport->ManageabilityTransportSpecification)) {
  89. // This is KCS transport interface.
  90. IpmiHeader = AllocateZeroPool (sizeof (MANAGEABILITY_IPMI_TRANSPORT_HEADER));
  91. if (IpmiHeader == NULL) {
  92. return EFI_OUT_OF_RESOURCES;
  93. }
  94. IpmiHeader->Command = Command;
  95. IpmiHeader->Lun = 0;
  96. IpmiHeader->NetFn = NetFunction;
  97. if (PacketHeader != NULL) {
  98. *PacketHeader = (MANAGEABILITY_TRANSPORT_HEADER *)IpmiHeader;
  99. }
  100. if (PacketTrailer != NULL) {
  101. *PacketTrailer = NULL;
  102. }
  103. if (PacketBody != NULL) {
  104. *PacketBody = NULL;
  105. }
  106. if (PacketBodySize != NULL) {
  107. *PacketBodySize = 0;
  108. }
  109. } else {
  110. DEBUG ((DEBUG_ERROR, "%a: No implementation of building up packet.", __FUNCTION__));
  111. ASSERT (FALSE);
  112. }
  113. return EFI_SUCCESS;
  114. }
  115. /**
  116. Common code to submit IPMI commands
  117. @param[in] TransportToken TRansport token.
  118. @param[in] NetFunction Net function of the command.
  119. @param[in] Command IPMI Command.
  120. @param[in] RequestData Command Request Data.
  121. @param[in] RequestDataSize Size of Command Request Data.
  122. @param[out] ResponseData Command Response Data. The completion code is the first byte of response data.
  123. @param[in, out] ResponseDataSize Size of Command Response Data.
  124. @retval EFI_SUCCESS The command byte stream was successfully submit to the device and a response was successfully received.
  125. @retval EFI_NOT_FOUND The command was not successfully sent to the device or a response was not successfully received from the device.
  126. @retval EFI_NOT_READY Ipmi Device is not ready for Ipmi command access.
  127. @retval EFI_DEVICE_ERROR Ipmi Device hardware error.
  128. @retval EFI_TIMEOUT The command time out.
  129. @retval EFI_UNSUPPORTED The command was not successfully sent to the device.
  130. @retval EFI_OUT_OF_RESOURCES The resource allocation is out of resource or data size error.
  131. **/
  132. EFI_STATUS
  133. CommonIpmiSubmitCommand (
  134. IN MANAGEABILITY_TRANSPORT_TOKEN *TransportToken,
  135. IN UINT8 NetFunction,
  136. IN UINT8 Command,
  137. IN UINT8 *RequestData OPTIONAL,
  138. IN UINT32 RequestDataSize,
  139. OUT UINT8 *ResponseData OPTIONAL,
  140. IN OUT UINT32 *ResponseDataSize OPTIONAL
  141. )
  142. {
  143. EFI_STATUS Status;
  144. UINT8 *ThisRequestData;
  145. UINT32 ThisRequestDataSize;
  146. MANAGEABILITY_TRANSFER_TOKEN TransferToken;
  147. MANAGEABILITY_TRANSPORT_HEADER IpmiTransportHeader;
  148. MANAGEABILITY_TRANSPORT_TRAILER IpmiTransportTrailer;
  149. MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS TransportAdditionalStatus;
  150. if (TransportToken == NULL) {
  151. DEBUG ((DEBUG_ERROR, "%a: No transport toke for IPMI\n", __FUNCTION__));
  152. return EFI_UNSUPPORTED;
  153. }
  154. Status = TransportToken->Transport->Function.Version1_0->TransportStatus (
  155. TransportToken,
  156. &TransportAdditionalStatus
  157. );
  158. if (EFI_ERROR (Status)) {
  159. DEBUG ((DEBUG_ERROR, "%a: Transport for IPMI has problem - (%r)\n", __FUNCTION__, Status));
  160. return Status;
  161. }
  162. ThisRequestData = RequestData;
  163. ThisRequestDataSize = RequestDataSize;
  164. IpmiTransportHeader = NULL;
  165. IpmiTransportTrailer = NULL;
  166. Status = SetupIpmiRequestTransportPacket (
  167. TransportToken,
  168. NetFunction,
  169. Command,
  170. &IpmiTransportHeader,
  171. &ThisRequestData,
  172. &ThisRequestDataSize,
  173. &IpmiTransportTrailer
  174. );
  175. if (EFI_ERROR (Status)) {
  176. DEBUG ((DEBUG_ERROR, "%a: Fail to build packets - (%r)\n", __FUNCTION__, Status));
  177. return Status;
  178. }
  179. ZeroMem (&TransferToken, sizeof (MANAGEABILITY_TRANSFER_TOKEN));
  180. TransferToken.TransmitHeader = IpmiTransportHeader;
  181. TransferToken.TransmitTrailer = IpmiTransportTrailer;
  182. // Transmit packet.
  183. if ((ThisRequestData == NULL) || (ThisRequestDataSize == 0)) {
  184. // Transmit parameter were not changed by SetupIpmiRequestTransportPacket().
  185. TransferToken.TransmitPackage.TransmitPayload = RequestData;
  186. TransferToken.TransmitPackage.TransmitSizeInByte = RequestDataSize;
  187. } else {
  188. TransferToken.TransmitPackage.TransmitPayload = ThisRequestData;
  189. TransferToken.TransmitPackage.TransmitSizeInByte = ThisRequestDataSize;
  190. }
  191. TransferToken.TransmitPackage.TransmitTimeoutInMillisecond = MANAGEABILITY_TRANSPORT_NO_TIMEOUT;
  192. // Receive packet.
  193. TransferToken.ReceivePackage.ReceiveBuffer = ResponseData;
  194. TransferToken.ReceivePackage.ReceiveSizeInByte = *ResponseDataSize;
  195. TransferToken.ReceivePackage.TransmitTimeoutInMillisecond = MANAGEABILITY_TRANSPORT_NO_TIMEOUT;
  196. TransportToken->Transport->Function.Version1_0->TransportTransmitReceive (
  197. TransportToken,
  198. &TransferToken
  199. );
  200. if (IpmiTransportHeader != NULL) {
  201. FreePool ((VOID *)IpmiTransportHeader);
  202. }
  203. if (IpmiTransportTrailer != NULL) {
  204. FreePool ((VOID *)IpmiTransportTrailer);
  205. }
  206. if (ThisRequestData != NULL) {
  207. FreePool ((VOID *)ThisRequestData);
  208. }
  209. // Return transfer status.
  210. //
  211. Status = TransferToken.TransferStatus;
  212. TransportAdditionalStatus = TransferToken.TransportAdditionalStatus;
  213. if (EFI_ERROR (Status)) {
  214. DEBUG ((DEBUG_ERROR, "%a: Failed to send IPMI command.\n", __FUNCTION__));
  215. return Status;
  216. }
  217. if (ResponseDataSize != NULL) {
  218. *ResponseDataSize = TransferToken.ReceivePackage.ReceiveSizeInByte;
  219. }
  220. return Status;
  221. }