IpmiProtocolCommon.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  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->Kcs = KcsHardwareInfo;
  46. return EFI_SUCCESS;
  47. } else {
  48. DEBUG ((DEBUG_ERROR, "%a: No implementation of setting hardware information.", __FUNCTION__));
  49. ASSERT (FALSE);
  50. }
  51. return EFI_UNSUPPORTED;
  52. }
  53. /**
  54. This functions setup the final header/body/trailer packets for
  55. the acquired transport interface.
  56. @param[in] TransportToken The transport interface.
  57. @param[in] NetFunction IPMI function.
  58. @param[in] Command IPMI command.
  59. @param[out] PacketHeader The pointer to receive header of request.
  60. @param[in, out] PacketBody The request body.
  61. When IN, it is the caller's request body.
  62. When OUT and NULL, the request body is not
  63. changed.
  64. When OUT and non-NULL, the request body is
  65. changed to conform the transport interface.
  66. @param[in, out] PacketBodySize The request body size.
  67. When OUT and non-zero, it is the new data
  68. length of request body.
  69. When OUT and zero, the request body is unchanged.
  70. @param[out] PacketTrailer The pointer to receive trailer of request.
  71. @retval EFI_SUCCESS Request packet is returned.
  72. @retval EFI_UNSUPPORTED Request packet is not returned because
  73. the unsupported transport interface.
  74. **/
  75. EFI_STATUS
  76. SetupIpmiRequestTransportPacket (
  77. IN MANAGEABILITY_TRANSPORT_TOKEN *TransportToken,
  78. IN UINT8 NetFunction,
  79. IN UINT8 Command,
  80. OUT MANAGEABILITY_TRANSPORT_HEADER *PacketHeader OPTIONAL,
  81. IN OUT UINT8 **PacketBody OPTIONAL,
  82. IN OUT UINT32 *PacketBodySize OPTIONAL,
  83. OUT MANAGEABILITY_TRANSPORT_TRAILER *PacketTrailer OPTIONAL
  84. )
  85. {
  86. MANAGEABILITY_IPMI_TRANSPORT_HEADER *IpmiHeader;
  87. if (CompareGuid (&gManageabilityTransportKcsGuid, TransportToken->Transport->ManageabilityTransportSpecification)) {
  88. // This is KCS transport interface.
  89. IpmiHeader = AllocateZeroPool (sizeof (MANAGEABILITY_IPMI_TRANSPORT_HEADER));
  90. if (IpmiHeader == NULL) {
  91. return EFI_OUT_OF_RESOURCES;
  92. }
  93. IpmiHeader->Command = Command;
  94. IpmiHeader->Lun = 0;
  95. IpmiHeader->NetFn = NetFunction;
  96. if (PacketHeader != NULL) {
  97. *PacketHeader = (MANAGEABILITY_TRANSPORT_HEADER *)IpmiHeader;
  98. }
  99. if (PacketTrailer != NULL) {
  100. *PacketTrailer = NULL;
  101. }
  102. if (PacketBody != NULL) {
  103. *PacketBody = NULL;
  104. }
  105. if (PacketBodySize != NULL) {
  106. *PacketBodySize = 0;
  107. }
  108. } else {
  109. DEBUG ((DEBUG_ERROR, "%a: No implementation of building up packet.", __FUNCTION__));
  110. ASSERT (FALSE);
  111. }
  112. return EFI_SUCCESS;
  113. }
  114. /**
  115. Common code to submit IPMI commands
  116. @param[in] TransportToken TRansport token.
  117. @param[in] NetFunction Net function of the command.
  118. @param[in] Command IPMI Command.
  119. @param[in] RequestData Command Request Data.
  120. @param[in] RequestDataSize Size of Command Request Data.
  121. @param[out] ResponseData Command Response Data. The completion code is the first byte of response data.
  122. @param[in, out] ResponseDataSize Size of Command Response Data.
  123. @retval EFI_SUCCESS The command byte stream was successfully submit to the device and a response was successfully received.
  124. @retval EFI_NOT_FOUND The command was not successfully sent to the device or a response was not successfully received from the device.
  125. @retval EFI_NOT_READY Ipmi Device is not ready for Ipmi command access.
  126. @retval EFI_DEVICE_ERROR Ipmi Device hardware error.
  127. @retval EFI_TIMEOUT The command time out.
  128. @retval EFI_UNSUPPORTED The command was not successfully sent to the device.
  129. @retval EFI_OUT_OF_RESOURCES The resource allocation is out of resource or data size error.
  130. **/
  131. EFI_STATUS
  132. CommonIpmiSubmitCommand (
  133. IN MANAGEABILITY_TRANSPORT_TOKEN *TransportToken,
  134. IN UINT8 NetFunction,
  135. IN UINT8 Command,
  136. IN UINT8 *RequestData OPTIONAL,
  137. IN UINT32 RequestDataSize,
  138. OUT UINT8 *ResponseData OPTIONAL,
  139. IN OUT UINT32 *ResponseDataSize OPTIONAL
  140. )
  141. {
  142. EFI_STATUS Status;
  143. UINT8 *ThisRequestData;
  144. UINT32 ThisRequestDataSize;
  145. MANAGEABILITY_TRANSFER_TOKEN TransferToken;
  146. MANAGEABILITY_TRANSPORT_HEADER IpmiTransportHeader;
  147. MANAGEABILITY_TRANSPORT_TRAILER IpmiTransportTrailer;
  148. MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS TransportAdditionalStatus;
  149. if (TransportToken == NULL) {
  150. DEBUG ((DEBUG_ERROR, "%a: No transport toke for IPMI\n", __FUNCTION__));
  151. return EFI_UNSUPPORTED;
  152. }
  153. Status = TransportToken->Transport->Function.Version1_0->TransportStatus (
  154. TransportToken,
  155. &TransportAdditionalStatus
  156. );
  157. if (EFI_ERROR (Status)) {
  158. DEBUG ((DEBUG_ERROR, "%a: Transport for IPMI has problem - (%r)\n", __FUNCTION__, Status));
  159. return Status;
  160. }
  161. ThisRequestData = RequestData;
  162. ThisRequestDataSize = RequestDataSize;
  163. IpmiTransportHeader = NULL;
  164. IpmiTransportTrailer = NULL;
  165. Status = SetupIpmiRequestTransportPacket (
  166. TransportToken,
  167. NetFunction,
  168. Command,
  169. &IpmiTransportHeader,
  170. &ThisRequestData,
  171. &ThisRequestDataSize,
  172. &IpmiTransportTrailer
  173. );
  174. if (EFI_ERROR (Status)) {
  175. DEBUG ((DEBUG_ERROR, "%a: Fail to build packets - (%r)\n", __FUNCTION__, Status));
  176. return Status;
  177. }
  178. ZeroMem (&TransferToken, sizeof (MANAGEABILITY_TRANSFER_TOKEN));
  179. TransferToken.TransmitHeader = IpmiTransportHeader;
  180. TransferToken.TransmitTrailer = IpmiTransportTrailer;
  181. // Transmit packet.
  182. if ((ThisRequestData == NULL) || (ThisRequestDataSize == 0)) {
  183. // Transmit parameter were not changed by SetupIpmiRequestTransportPacket().
  184. TransferToken.TransmitPackage.TransmitPayload = RequestData;
  185. TransferToken.TransmitPackage.TransmitSizeInByte = RequestDataSize;
  186. } else {
  187. TransferToken.TransmitPackage.TransmitPayload = ThisRequestData;
  188. TransferToken.TransmitPackage.TransmitSizeInByte = ThisRequestDataSize;
  189. }
  190. TransferToken.TransmitPackage.TransmitTimeoutInMillisecond = MANAGEABILITY_TRANSPORT_NO_TIMEOUT;
  191. // Receive packet.
  192. TransferToken.ReceivePackage.ReceiveBuffer = ResponseData;
  193. TransferToken.ReceivePackage.ReceiveSizeInByte = *ResponseDataSize;
  194. TransferToken.ReceivePackage.TransmitTimeoutInMillisecond = MANAGEABILITY_TRANSPORT_NO_TIMEOUT;
  195. TransportToken->Transport->Function.Version1_0->TransportTransmitReceive (
  196. TransportToken,
  197. &TransferToken
  198. );
  199. if (IpmiTransportHeader != NULL) {
  200. FreePool ((VOID *)IpmiTransportHeader);
  201. }
  202. if (IpmiTransportTrailer != NULL) {
  203. FreePool ((VOID *)IpmiTransportTrailer);
  204. }
  205. if (ThisRequestData != NULL) {
  206. FreePool ((VOID *)ThisRequestData);
  207. }
  208. // Return transfer status.
  209. //
  210. Status = TransferToken.TransferStatus;
  211. TransportAdditionalStatus = TransferToken.TransportAdditionalStatus;
  212. if (EFI_ERROR (Status)) {
  213. DEBUG ((DEBUG_ERROR, "%a: Failed to send IPMI command.\n", __FUNCTION__));
  214. return Status;
  215. }
  216. if (ResponseDataSize != NULL) {
  217. *ResponseDataSize = TransferToken.ReceivePackage.ReceiveSizeInByte;
  218. }
  219. return Status;
  220. }