hpm2.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. /*
  2. * Copyright (c) 2012 Pigeon Point Systems. All Rights Reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * Redistribution of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. *
  11. * Redistribution in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. *
  15. * Neither the name of Pigeon Point Systems nor the names of
  16. * contributors may be used to endorse or promote products derived
  17. * from this software without specific prior written permission.
  18. *
  19. * This software is provided "AS IS," without a warranty of any kind.
  20. * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
  21. * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
  22. * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
  23. * PIGEON POINT SYSTEMS ("PPS") AND ITS LICENSORS SHALL NOT BE LIABLE
  24. * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
  25. * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
  26. * PPS OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
  27. * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
  28. * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
  29. * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
  30. * EVEN IF PPS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
  31. */
  32. #include <ipmitool/bswap.h>
  33. #include <ipmitool/hpm2.h>
  34. #include <ipmitool/ipmi_intf.h>
  35. //#include <ipmitool/log.h>
  36. #include <ipmitool/bswap.h>
  37. /* From src/plugins/ipmi_intf.c: */
  38. void
  39. ipmi_intf_set_max_request_data_size(struct ipmi_intf * intf, uint16_t size);
  40. void
  41. ipmi_intf_set_max_response_data_size(struct ipmi_intf * intf, uint16_t size);
  42. #if HAVE_PRAGMA_PACK
  43. # pragma pack(push, 1)
  44. #endif
  45. /* HPM.x Get Capabilities request */
  46. struct hpmx_cmd_get_capabilities_rq {
  47. uint8_t picmg_id;
  48. uint8_t hpmx_id;
  49. } ATTRIBUTE_PACKING;
  50. /* HPM.2 Get Capabilities response */
  51. struct hpm2_cmd_get_capabilities_rp {
  52. uint8_t picmg_id;
  53. struct hpm2_lan_attach_capabilities caps;
  54. } ATTRIBUTE_PACKING;
  55. #if HAVE_PRAGMA_PACK
  56. # pragma pack(pop)
  57. #endif
  58. /* IPMI Get LAN Configuration Parameters command */
  59. #define IPMI_LAN_GET_CONFIG 0x02
  60. int hpm2_get_capabilities(struct ipmi_intf * intf,
  61. struct hpm2_lan_attach_capabilities * caps)
  62. {
  63. struct ipmi_rq req;
  64. struct ipmi_rs * rsp;
  65. struct hpmx_cmd_get_capabilities_rq rq;
  66. /* reset result */
  67. memset(caps, 0, sizeof(struct hpm2_lan_attach_capabilities));
  68. /* prepare request */
  69. rq.picmg_id = 0;
  70. rq.hpmx_id = 2;
  71. /* prepare request */
  72. memset(&req, 0, sizeof(req));
  73. req.msg.netfn = IPMI_NETFN_PICMG;
  74. req.msg.cmd = HPM2_GET_LAN_ATTACH_CAPABILITIES;
  75. req.msg.data = (uint8_t *)&rq;
  76. req.msg.data_len = sizeof(rq);
  77. /* send */
  78. rsp = intf->sendrecv(intf, &req);
  79. if (!rsp) {
  80. printf( "Error sending request.");
  81. return -1;
  82. }
  83. if (rsp->ccode == 0xC1) {
  84. printf( "IPM Controller is not HPM.2 compatible");
  85. return rsp->ccode;
  86. } else if (rsp->ccode) {
  87. printf( "Get HPM.x Capabilities request failed,"
  88. " compcode = %x", rsp->ccode);
  89. return rsp->ccode;
  90. }
  91. /* check response length */
  92. if (rsp->data_len < 2 || rsp->data_len > 10) {
  93. printf( "Bad response length, len=%d", rsp->data_len);
  94. return -1;
  95. }
  96. /* check HPM.x identifier */
  97. if (rsp->data[1] != 2) {
  98. printf( "Bad HPM.x ID, id=%d", rsp->data[1]);
  99. return rsp->ccode;
  100. }
  101. /*
  102. * this hardly can happen, since completion code is already checked.
  103. * but check for safety
  104. */
  105. if (rsp->data_len < 4) {
  106. printf( "Bad response length, len=%d", rsp->data_len);
  107. return -1;
  108. }
  109. /* copy HPM.2 capabilities */
  110. memcpy(caps, rsp->data + 2, rsp->data_len - 2);
  111. #if WORDS_BIGENDIAN
  112. /* swap bytes to convert from little-endian format */
  113. caps->lan_channel_mask = BSWAP_16(caps->lan_channel_mask);
  114. #endif
  115. /* check HPM.2 revision */
  116. if (caps->hpm2_revision_id == 0) {
  117. printf( "Bad HPM.2 revision, rev=%d",
  118. caps->hpm2_revision_id);
  119. return -1;
  120. }
  121. if (!caps->lan_channel_mask) {
  122. return -1;
  123. }
  124. /* check response length */
  125. if (rsp->data_len < 8) {
  126. printf( "Bad response length, len=%d", rsp->data_len);
  127. return -1;
  128. }
  129. /* check HPM.2 LAN parameters start */
  130. if (caps->hpm2_lan_params_start < 0xC0) {
  131. printf( "Bad HPM.2 LAN params start, start=%x",
  132. caps->hpm2_lan_params_start);
  133. return -1;
  134. }
  135. /* check HPM.2 LAN parameters revision */
  136. if (caps->hpm2_lan_params_rev != HPM2_LAN_PARAMS_REV) {
  137. printf( "Bad HPM.2 LAN params revision, rev=%d",
  138. caps->hpm2_lan_params_rev);
  139. return -1;
  140. }
  141. /* check for HPM.2 SOL extension */
  142. if (!(caps->hpm2_caps & HPM2_CAPS_SOL_EXTENSION)) {
  143. /* no further checks */
  144. return 0;
  145. }
  146. /* check response length */
  147. if (rsp->data_len < 10) {
  148. printf( "Bad response length, len=%d", rsp->data_len);
  149. return -1;
  150. }
  151. /* check HPM.2 SOL parameters start */
  152. if (caps->hpm2_sol_params_start < 0xC0) {
  153. printf( "Bad HPM.2 SOL params start, start=%x",
  154. caps->hpm2_sol_params_start);
  155. return -1;
  156. }
  157. /* check HPM.2 SOL parameters revision */
  158. if (caps->hpm2_sol_params_rev != HPM2_SOL_PARAMS_REV) {
  159. printf( "Bad HPM.2 SOL params revision, rev=%d",
  160. caps->hpm2_sol_params_rev);
  161. return -1;
  162. }
  163. return 0;
  164. }
  165. int hpm2_get_lan_channel_capabilities(struct ipmi_intf * intf,
  166. uint8_t hpm2_lan_params_start,
  167. struct hpm2_lan_channel_capabilities * caps)
  168. {
  169. struct ipmi_rq req;
  170. struct ipmi_rs * rsp;
  171. uint8_t rq[4];
  172. /* reset result */
  173. memset(caps, 0, sizeof(struct hpm2_lan_channel_capabilities));
  174. /* prepare request */
  175. memset(&req, 0, sizeof(req));
  176. req.msg.netfn = IPMI_NETFN_TRANSPORT;
  177. req.msg.cmd = IPMI_LAN_GET_CONFIG;
  178. req.msg.data = (uint8_t *)&rq;
  179. req.msg.data_len = sizeof(rq);
  180. /* prepare request data */
  181. rq[0] = 0xE; /* sending channel */
  182. rq[1] = hpm2_lan_params_start; /* HPM.2 Channel Caps */
  183. rq[2] = rq[3] = 0;
  184. /* send */
  185. rsp = intf->sendrecv(intf, &req);
  186. if (!rsp) {
  187. printf( "Error sending request.");
  188. return -1;
  189. }
  190. if (rsp->ccode == 0x80) {
  191. printf( "HPM.2 Channel Caps parameter is not supported");
  192. return rsp->ccode;
  193. } else if (rsp->ccode) {
  194. printf( "Get LAN Configuration Parameters request failed,"
  195. " compcode = %x", rsp->ccode);
  196. return rsp->ccode;
  197. }
  198. /* check response length */
  199. if (rsp->data_len != sizeof (struct hpm2_lan_channel_capabilities) + 1) {
  200. printf( "Bad response length, len=%d", rsp->data_len);
  201. return -1;
  202. }
  203. /* check parameter revision */
  204. if (rsp->data[0] !=
  205. LAN_PARAM_REV(HPM2_LAN_PARAMS_REV, HPM2_LAN_PARAMS_REV)) {
  206. printf( "Bad HPM.2 LAN parameter revision, rev=%d",
  207. rsp->data[0]);
  208. return -1;
  209. }
  210. /* copy parameter data */
  211. memcpy(caps, &rsp->data[1], sizeof (struct hpm2_lan_channel_capabilities));
  212. #if WORDS_BIGENDIAN
  213. /* swap bytes to convert from little-endian format */
  214. caps->max_inbound_pld_size = BSWAP_16(caps->max_inbound_pld_size);
  215. caps->max_outbound_pld_size = BSWAP_16(caps->max_outbound_pld_size);
  216. #endif
  217. return 0;
  218. }
  219. int hpm2_detect_max_payload_size(struct ipmi_intf * intf)
  220. {
  221. struct hpm2_lan_attach_capabilities attach_caps;
  222. struct hpm2_lan_channel_capabilities channel_caps;
  223. int err;
  224. /* query HPM.2 support */
  225. err = hpm2_get_capabilities(intf, &attach_caps);
  226. /* check if HPM.2 is supported */
  227. if (err != 0 || !attach_caps.lan_channel_mask) {
  228. return err;
  229. }
  230. /* query channel capabilities */
  231. err = hpm2_get_lan_channel_capabilities(intf,
  232. attach_caps.hpm2_lan_params_start, &channel_caps);
  233. /* check if succeeded */
  234. if (err != 0) {
  235. return err;
  236. }
  237. /* update request and response sizes */
  238. ipmi_intf_set_max_request_data_size(intf,
  239. channel_caps.max_inbound_pld_size - 7);
  240. ipmi_intf_set_max_response_data_size(intf,
  241. channel_caps.max_outbound_pld_size - 8);
  242. /* print debug info */
  243. printf( "Set maximum request size to %d\n"
  244. "Set maximum response size to %d",
  245. intf->max_request_data_size, intf->max_response_data_size);
  246. return 0;
  247. }