ManageabilityTransportKcs.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. /** @file
  2. KCS instance of Manageability Transport Library
  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 <IndustryStandard/IpmiKcs.h>
  8. #include <Library/IoLib.h>
  9. #include <Library/DebugLib.h>
  10. #include <Library/MemoryAllocationLib.h>
  11. #include <Library/ManageabilityTransportLib.h>
  12. #include <Library/ManageabilityTransportIpmiLib.h>
  13. #include <Library/ManageabilityTransportHelperLib.h>
  14. #include "ManageabilityTransportKcs.h"
  15. MANAGEABILITY_TRANSPORT_KCS *mSingleSessionToken = NULL;
  16. EFI_GUID *SupportedManageabilityProtocol[] = {
  17. &gManageabilityProtocolIpmiGuid,
  18. &gManageabilityProtocolMctpGuid
  19. };
  20. UINT8 NumberOfSupportedProtocol = (sizeof (SupportedManageabilityProtocol)/sizeof (EFI_GUID *));
  21. MANAGEABILITY_TRANSPORT_KCS_HARDWARE_INFO mKcsHardwareInfo;
  22. /**
  23. This function initializes the transport interface.
  24. @param [in] TransportToken The transport token acquired through
  25. AcquireTransportSession function.
  26. @param [in] HardwareInfo The hardware information
  27. assigned to KCS transport interface.
  28. @retval EFI_SUCCESS Transport interface is initialized
  29. successfully.
  30. @retval EFI_INVALID_PARAMETER The invalid transport token.
  31. @retval EFI_NOT_READY The transport interface works fine but
  32. @retval is not ready.
  33. @retval EFI_DEVICE_ERROR The transport interface has problems.
  34. @retval EFI_ALREADY_STARTED Teh protocol interface has already initialized.
  35. @retval Otherwise Other errors.
  36. **/
  37. EFI_STATUS
  38. EFIAPI
  39. KcsTransportInit (
  40. IN MANAGEABILITY_TRANSPORT_TOKEN *TransportToken,
  41. IN MANAGEABILITY_TRANSPORT_HARDWARE_INFORMATION HardwareInfo OPTIONAL
  42. )
  43. {
  44. CHAR16 *ManageabilityProtocolName;
  45. if (TransportToken == NULL) {
  46. DEBUG ((DEBUG_ERROR, "%a: Invalid transport token.\n", __FUNCTION__));
  47. return EFI_INVALID_PARAMETER;
  48. }
  49. if (HardwareInfo.Kcs == NULL) {
  50. DEBUG ((DEBUG_INFO, "%a: Hardware information is not provided, use dfault settings.\n", __FUNCTION__));
  51. mKcsHardwareInfo.MemoryMap = MANAGEABILITY_TRANSPORT_KCS_IO_MAP_IO;
  52. mKcsHardwareInfo.IoBaseAddress.IoAddress16 = PcdGet16 (PcdIpmiKcsIoBaseAddress);
  53. mKcsHardwareInfo.IoDataInAddress.IoAddress16 = mKcsHardwareInfo.IoBaseAddress.IoAddress16 + IPMI_KCS_DATA_IN_REGISTER_OFFSET;
  54. mKcsHardwareInfo.IoDataOutAddress.IoAddress16 = mKcsHardwareInfo.IoBaseAddress.IoAddress16 + IPMI_KCS_DATA_OUT_REGISTER_OFFSET;
  55. mKcsHardwareInfo.IoCommandAddress.IoAddress16 = mKcsHardwareInfo.IoBaseAddress.IoAddress16 + IPMI_KCS_COMMAND_REGISTER_OFFSET;
  56. mKcsHardwareInfo.IoStatusAddress.IoAddress16 = mKcsHardwareInfo.IoBaseAddress.IoAddress16 + IPMI_KCS_STATUS_REGISTER_OFFSET;
  57. } else {
  58. mKcsHardwareInfo.MemoryMap = ((MANAGEABILITY_TRANSPORT_KCS_HARDWARE_INFO *)HardwareInfo.Kcs)->MemoryMap;
  59. mKcsHardwareInfo.IoBaseAddress = ((MANAGEABILITY_TRANSPORT_KCS_HARDWARE_INFO *)HardwareInfo.Kcs)->IoBaseAddress;
  60. mKcsHardwareInfo.IoDataInAddress = ((MANAGEABILITY_TRANSPORT_KCS_HARDWARE_INFO *)HardwareInfo.Kcs)->IoDataInAddress;
  61. mKcsHardwareInfo.IoDataOutAddress = ((MANAGEABILITY_TRANSPORT_KCS_HARDWARE_INFO *)HardwareInfo.Kcs)->IoDataOutAddress;
  62. mKcsHardwareInfo.IoCommandAddress = ((MANAGEABILITY_TRANSPORT_KCS_HARDWARE_INFO *)HardwareInfo.Kcs)->IoCommandAddress;
  63. mKcsHardwareInfo.IoStatusAddress = ((MANAGEABILITY_TRANSPORT_KCS_HARDWARE_INFO *)HardwareInfo.Kcs)->IoStatusAddress;
  64. }
  65. // Get protocol specification name.
  66. ManageabilityProtocolName = HelperManageabilitySpecName (TransportToken->ManageabilityProtocolSpecification);
  67. DEBUG ((DEBUG_INFO, "%a: KCS transport hardware for %s is:\n", __FUNCTION__, ManageabilityProtocolName));
  68. if (mKcsHardwareInfo.MemoryMap) {
  69. DEBUG ((DEBUG_INFO, "Memory Map I/O\n", __FUNCTION__));
  70. DEBUG ((DEBUG_INFO, "Base Memory Address : 0x%08x\n", mKcsHardwareInfo.IoBaseAddress.IoAddress32));
  71. DEBUG ((DEBUG_INFO, "Data in Address : 0x%08x\n", mKcsHardwareInfo.IoDataInAddress.IoAddress32));
  72. DEBUG ((DEBUG_INFO, "Data out Address : 0x%08x\n", mKcsHardwareInfo.IoDataOutAddress.IoAddress32));
  73. DEBUG ((DEBUG_INFO, "Command Address : 0x%08x\n", mKcsHardwareInfo.IoCommandAddress.IoAddress32));
  74. DEBUG ((DEBUG_INFO, "Status Address : 0x%08x\n", mKcsHardwareInfo.IoStatusAddress.IoAddress32));
  75. } else {
  76. DEBUG ((DEBUG_INFO, "I/O Map I/O\n"));
  77. DEBUG ((DEBUG_INFO, "Base I/O port : 0x%04x\n", mKcsHardwareInfo.IoBaseAddress.IoAddress16));
  78. DEBUG ((DEBUG_INFO, "Data in I/O port : 0x%04x\n", mKcsHardwareInfo.IoDataInAddress.IoAddress16));
  79. DEBUG ((DEBUG_INFO, "Data out I/O port: 0x%04x\n", mKcsHardwareInfo.IoDataOutAddress.IoAddress16));
  80. DEBUG ((DEBUG_INFO, "Command I/O port : 0x%04x\n", mKcsHardwareInfo.IoCommandAddress.IoAddress16));
  81. DEBUG ((DEBUG_INFO, "Status I/O port : 0x%04x\n", mKcsHardwareInfo.IoStatusAddress.IoAddress16));
  82. }
  83. return EFI_SUCCESS;
  84. }
  85. /**
  86. This function returns the transport interface status.
  87. The generic EFI_STATUS is returned to caller directly, The additional
  88. information of transport interface could be optionally returned in
  89. TransportAdditionalStatus to describes the status that can't be
  90. described obviously through EFI_STATUS.
  91. See the definition of MANAGEABILITY_TRANSPORT_STATUS.
  92. @param [in] TransportToken The transport token acquired through
  93. AcquireTransportSession function.
  94. @param [out] TransportAdditionalStatus The additional status of transport
  95. interface.
  96. NULL means no additional status of this
  97. transport interface.
  98. @retval EFI_SUCCESS Transport interface status is returned.
  99. @retval EFI_INVALID_PARAMETER The invalid transport token.
  100. @retval EFI_DEVICE_ERROR The transport interface has problems to return
  101. @retval EFI_UNSUPPORTED The transport interface doesn't have status report.
  102. Otherwise Other errors.
  103. **/
  104. EFI_STATUS
  105. EFIAPI
  106. KcsTransportStatus (
  107. IN MANAGEABILITY_TRANSPORT_TOKEN *TransportToken,
  108. OUT MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS *TransportAdditionalStatus OPTIONAL
  109. )
  110. {
  111. UINT8 TransportStatus;
  112. if (TransportToken == NULL) {
  113. DEBUG ((DEBUG_ERROR, "%a: Invalid transport token.\n", __FUNCTION__));
  114. return EFI_INVALID_PARAMETER;
  115. }
  116. if (TransportAdditionalStatus == NULL) {
  117. return EFI_SUCCESS;
  118. }
  119. TransportStatus = IPMI_KCS_GET_STATE (KcsRegisterRead8 (KCS_REG_STATUS));
  120. *TransportAdditionalStatus = MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS_NO_ERRORS;
  121. if (TransportStatus != IpmiKcsIdleState) {
  122. if (TransportStatus == IpmiKcsReadState) {
  123. //
  124. // Transport is in read state.
  125. *TransportAdditionalStatus |= MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS_BUSY_IN_READ;
  126. return EFI_NOT_READY;
  127. } else if (TransportStatus == IpmiKcsWriteState) {
  128. //
  129. // Transport is in read state.
  130. *TransportAdditionalStatus |= MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS_BUSY_IN_WRITE;
  131. return EFI_NOT_READY;
  132. } else {
  133. return EFI_DEVICE_ERROR;
  134. }
  135. }
  136. return EFI_SUCCESS;
  137. }
  138. /**
  139. This function resets the transport interface.
  140. The generic EFI_STATUS is returned to caller directly after reseting transport
  141. interface. The additional information of transport interface could be optionally
  142. returned in TransportAdditionalStatus to describes the status that can't be
  143. described obviously through EFI_STATUS.
  144. See the definition of MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS.
  145. @param [in] TransportToken The transport token acquired through
  146. AcquireTransportSession function.
  147. @param [out] TransportAdditionalStatus The additional status of specific transport
  148. interface after the reset.
  149. NULL means no additional status of this
  150. transport interface.
  151. @retval EFI_SUCCESS Transport interface status is returned.
  152. @retval EFI_INVALID_PARAMETER The invalid transport token.
  153. @retval EFI_TIMEOUT The reset process is time out.
  154. @retval EFI_DEVICE_ERROR The transport interface has problems to return
  155. status.
  156. Otherwise Other errors.
  157. **/
  158. EFI_STATUS
  159. EFIAPI
  160. KcsTransportReset (
  161. IN MANAGEABILITY_TRANSPORT_TOKEN *TransportToken,
  162. OUT MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS *TransportAdditionalStatus OPTIONAL
  163. )
  164. {
  165. return EFI_UNSUPPORTED;
  166. }
  167. /**
  168. This function transmit the request over target transport interface.
  169. The generic EFI_STATUS is returned to caller directly after reseting transport
  170. interface. The additional information of transport interface could be optionally
  171. returned in TransportAdditionalStatus to describes the status that can't be
  172. described obviously through EFI_STATUS.
  173. See the definition of MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS.
  174. @param [in] TransportToken The transport token acquired through
  175. AcquireTransportSession function.
  176. @param [in] TransferToken The transfer token, see the definition of
  177. MANAGEABILITY_TRANSFER_TOKEN.
  178. @retval The EFI status is returned in MANAGEABILITY_TRANSFER_TOKEN.
  179. **/
  180. VOID
  181. EFIAPI
  182. KcsTransportTransmitReceive (
  183. IN MANAGEABILITY_TRANSPORT_TOKEN *TransportToken,
  184. IN MANAGEABILITY_TRANSFER_TOKEN *TransferToken
  185. )
  186. {
  187. EFI_STATUS Status;
  188. MANAGEABILITY_IPMI_TRANSPORT_HEADER *TransmitHeader;
  189. if (TransportToken == NULL || TransferToken == NULL) {
  190. DEBUG ((DEBUG_ERROR, "%a: Invalid transport token or transfer token.\n", __FUNCTION__));
  191. return;
  192. }
  193. TransmitHeader = (MANAGEABILITY_IPMI_TRANSPORT_HEADER *)TransferToken->TransmitHeader;
  194. if (TransmitHeader == NULL) {
  195. TransferToken->TransferStatus = EFI_INVALID_PARAMETER;
  196. return;
  197. }
  198. Status = KcsTransportSendCommand (
  199. TransmitHeader->NetFn,
  200. TransmitHeader->Command,
  201. TransferToken->TransmitPackage.TransmitPayload,
  202. TransferToken->TransmitPackage.TransmitSizeInByte,
  203. TransferToken->ReceivePackage.ReceiveBuffer,
  204. &TransferToken->ReceivePackage.ReceiveSizeInByte
  205. );
  206. TransferToken->TransferStatus = Status;
  207. KcsTransportStatus (TransportToken, &TransferToken->TransportAdditionalStatus);
  208. }
  209. /**
  210. This function acquires to create a transport session to transmit manageability
  211. packet. A transport token is returned to caller for the follow up operations.
  212. @param [in] ManageabilityProtocolSpec The protocol spec the transport interface is acquired.
  213. @param [out] TransportToken The pointer to receive the transport token created by
  214. the target transport interface library.
  215. @retval EFI_SUCCESS Token is created successfully.
  216. @retval EFI_OUT_OF_RESOURCES Out of resource to create a new transport session.
  217. @retval EFI_UNSUPPORTED Protocol is not supported on this transport interface.
  218. @retval Otherwise Other errors.
  219. **/
  220. EFI_STATUS
  221. AcquireTransportSession (
  222. IN EFI_GUID *ManageabilityProtocolSpec,
  223. OUT MANAGEABILITY_TRANSPORT_TOKEN **TransportToken
  224. )
  225. {
  226. EFI_STATUS Status;
  227. MANAGEABILITY_TRANSPORT_KCS *KcsTransportToken;
  228. if (ManageabilityProtocolSpec == NULL) {
  229. DEBUG ((DEBUG_ERROR, "%a: No Manageability protocol specification specified.\n", __FUNCTION__));
  230. return EFI_INVALID_PARAMETER;
  231. }
  232. if (TransportToken == NULL) {
  233. DEBUG ((DEBUG_ERROR, "%a: TransportToken is NULL.\n", __FUNCTION__));
  234. return EFI_INVALID_PARAMETER;
  235. }
  236. Status = HelperManageabilityCheckSupportedSpec (
  237. &gManageabilityTransportKcsGuid,
  238. SupportedManageabilityProtocol,
  239. NumberOfSupportedProtocol,
  240. ManageabilityProtocolSpec
  241. );
  242. if (EFI_ERROR (Status)) {
  243. DEBUG ((DEBUG_ERROR, "%a: Protocol is not supported on this transport interface.\n", __FUNCTION__));
  244. return EFI_UNSUPPORTED;
  245. }
  246. if (mSingleSessionToken != NULL) {
  247. DEBUG ((DEBUG_ERROR, "%a: This manageability transport library only supports one session transport token.\n", __FUNCTION__));
  248. return EFI_OUT_OF_RESOURCES;
  249. }
  250. KcsTransportToken = AllocateZeroPool (sizeof (MANAGEABILITY_TRANSPORT_KCS));
  251. if (KcsTransportToken == NULL) {
  252. DEBUG ((DEBUG_ERROR, "%a: Fail to allocate memory for MANAGEABILITY_TRANSPORT_KCS\n", __FUNCTION__));
  253. return EFI_OUT_OF_RESOURCES;
  254. }
  255. KcsTransportToken->Token.Transport = AllocateZeroPool (sizeof (MANAGEABILITY_TRANSPORT));
  256. if (KcsTransportToken->Token.Transport == NULL) {
  257. FreePool (KcsTransportToken);
  258. DEBUG ((DEBUG_ERROR, "%a: Fail to allocate memory for MANAGEABILITY_TRANSPORT\n", __FUNCTION__));
  259. return EFI_OUT_OF_RESOURCES;
  260. }
  261. KcsTransportToken->Signature = MANAGEABILITY_TRANSPORT_KCS_SIGNATURE;
  262. KcsTransportToken->Token.ManageabilityProtocolSpecification = ManageabilityProtocolSpec;
  263. KcsTransportToken->Token.Transport->TransportVersion = MANAGEABILITY_TRANSPORT_TOKEN_VERSION;
  264. KcsTransportToken->Token.Transport->ManageabilityTransportSpecification = &gManageabilityTransportKcsGuid;
  265. KcsTransportToken->Token.Transport->TransportName = L"KCS";
  266. KcsTransportToken->Token.Transport->Function.Version1_0 = AllocateZeroPool (sizeof (MANAGEABILITY_TRANSPORT_FUNCTION_V1_0));
  267. if (KcsTransportToken->Token.Transport->Function.Version1_0 == NULL) {
  268. DEBUG ((DEBUG_ERROR, "%a: Fail to allocate memory for MANAGEABILITY_TRANSPORT_FUNCTION_V1_0\n", __FUNCTION__));
  269. FreePool (KcsTransportToken);
  270. FreePool (KcsTransportToken->Token.Transport);
  271. return EFI_OUT_OF_RESOURCES;
  272. }
  273. KcsTransportToken->Token.Transport->Function.Version1_0->TransportInit = KcsTransportInit;
  274. KcsTransportToken->Token.Transport->Function.Version1_0->TransportReset = KcsTransportReset;
  275. KcsTransportToken->Token.Transport->Function.Version1_0->TransportStatus = KcsTransportStatus;
  276. KcsTransportToken->Token.Transport->Function.Version1_0->TransportTransmitReceive = KcsTransportTransmitReceive;
  277. mSingleSessionToken = KcsTransportToken;
  278. *TransportToken = &KcsTransportToken->Token;
  279. return EFI_SUCCESS;
  280. }
  281. /**
  282. This function returns the transport capabilities.
  283. @param [out] TransportFeature Pointer to receive transport capabilities.
  284. See the definitions of
  285. MANAGEABILITY_TRANSPORT_CAPABILITY.
  286. **/
  287. VOID
  288. GetTransportCapability (
  289. OUT MANAGEABILITY_TRANSPORT_CAPABILITY *TransportCapability
  290. )
  291. {
  292. if (TransportCapability != NULL) {
  293. *TransportCapability = 0;
  294. }
  295. }
  296. /**
  297. This function releases the manageability session.
  298. @param [in] TransportToken The transport token acquired through
  299. AcquireTransportSession.
  300. @retval EFI_SUCCESS Token is released successfully.
  301. @retval EFI_INVALID_PARAMETER Invalid TransportToken.
  302. @retval Otherwise Other errors.
  303. **/
  304. EFI_STATUS
  305. ReleaseTransportSession (
  306. IN MANAGEABILITY_TRANSPORT_TOKEN *TransportToken
  307. )
  308. {
  309. EFI_STATUS Status;
  310. MANAGEABILITY_TRANSPORT_KCS *KcsTransportToken;
  311. if (TransportToken == NULL) {
  312. Status = EFI_INVALID_PARAMETER;
  313. }
  314. KcsTransportToken = MANAGEABILITY_TRANSPORT_KCS_FROM_LINK (TransportToken);
  315. if (mSingleSessionToken != KcsTransportToken) {
  316. Status = EFI_INVALID_PARAMETER;
  317. }
  318. if (KcsTransportToken != NULL) {
  319. FreePool (KcsTransportToken->Token.Transport->Function.Version1_0);
  320. FreePool (KcsTransportToken->Token.Transport);
  321. FreePool (KcsTransportToken);
  322. mSingleSessionToken = NULL;
  323. Status = EFI_SUCCESS;
  324. }
  325. if (EFI_ERROR (Status)) {
  326. DEBUG ((DEBUG_ERROR, "%a: Fail to release KCS transport token (%r).\n", __FUNCTION__, Status));
  327. }
  328. return Status;
  329. }