ipmi_sensor.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995
  1. /*
  2. * Copyright (c) 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc. or 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. * SUN MICROSYSTEMS, INC. ("SUN") 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. * SUN 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 SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
  31. */
  32. #include <string.h>
  33. #include <math.h>
  34. #include <ipmitool/ipmi.h>
  35. #include <ipmitool/helper.h>
  36. #include <ipmitool/log.h>
  37. #include <ipmitool/ipmi_intf.h>
  38. #include <ipmitool/ipmi_sdr.h>
  39. #include <ipmitool/ipmi_sel.h>
  40. #include <ipmitool/ipmi_sensor.h>
  41. extern int verbose;
  42. void print_sensor_get_usage();
  43. void print_sensor_thresh_usage();
  44. // Macro's for Reading the current sensor Data.
  45. #define SCANNING_DISABLED 0x40
  46. #define READING_UNAVAILABLE 0x20
  47. #define INVALID_THRESHOLD "Invalid Threshold data values. Cannot Set Threshold Data."
  48. // static
  49. int
  50. ipmi_sensor_get_sensor_reading_factors(
  51. struct ipmi_intf * intf,
  52. struct sdr_record_full_sensor * sensor,
  53. uint8_t reading)
  54. {
  55. struct ipmi_rq req;
  56. struct ipmi_rs * rsp;
  57. uint8_t req_data[2];
  58. char id[17];
  59. if (intf == NULL || sensor == NULL)
  60. return -1;
  61. memset(id, 0, sizeof(id));
  62. memcpy(id, sensor->id_string, 16);
  63. req_data[0] = sensor->cmn.keys.sensor_num;
  64. req_data[1] = reading;
  65. memset(&req, 0, sizeof(req));
  66. req.msg.netfn = IPMI_NETFN_SE;
  67. req.msg.lun = sensor->cmn.keys.lun;
  68. req.msg.cmd = GET_SENSOR_FACTORS;
  69. req.msg.data = req_data;
  70. req.msg.data_len = sizeof(req_data);
  71. rsp = intf->sendrecv(intf, &req);
  72. if (rsp == NULL) {
  73. lprintf(LOG_ERR, "Error updating reading factor for sensor %s (#%02x)",
  74. id, sensor->cmn.keys.sensor_num);
  75. return -1;
  76. } else if (rsp->ccode) {
  77. return -1;
  78. } else {
  79. /* Update SDR copy with updated Reading Factors for this reading */
  80. /* Note:
  81. * The Format of the returned data is exactly as in the SDR definition (Little Endian Format),
  82. * therefore we can use raw copy operation here.
  83. * Note: rsp->data[0] would point to the next valid entry in the sampling table
  84. */
  85. // BUGBUG: uses 'hardcoded' length information from SDR Definition
  86. memcpy(&sensor->mtol, &rsp->data[1], sizeof(sensor->mtol));
  87. memcpy(&sensor->bacc, &rsp->data[3], sizeof(sensor->bacc));
  88. return 0;
  89. }
  90. }
  91. static
  92. struct ipmi_rs *
  93. ipmi_sensor_set_sensor_thresholds(struct ipmi_intf *intf,
  94. uint8_t sensor,
  95. uint8_t threshold, uint8_t setting,
  96. uint8_t target, uint8_t lun, uint8_t channel)
  97. {
  98. struct ipmi_rq req;
  99. static struct sensor_set_thresh_rq set_thresh_rq;
  100. struct ipmi_rs *rsp;
  101. uint8_t bridged_request = 0;
  102. uint32_t save_addr;
  103. uint32_t save_channel;
  104. memset(&set_thresh_rq, 0, sizeof (set_thresh_rq));
  105. set_thresh_rq.sensor_num = sensor;
  106. set_thresh_rq.set_mask = threshold;
  107. if (threshold == UPPER_NON_RECOV_SPECIFIED)
  108. set_thresh_rq.upper_non_recov = setting;
  109. else if (threshold == UPPER_CRIT_SPECIFIED)
  110. set_thresh_rq.upper_crit = setting;
  111. else if (threshold == UPPER_NON_CRIT_SPECIFIED)
  112. set_thresh_rq.upper_non_crit = setting;
  113. else if (threshold == LOWER_NON_CRIT_SPECIFIED)
  114. set_thresh_rq.lower_non_crit = setting;
  115. else if (threshold == LOWER_CRIT_SPECIFIED)
  116. set_thresh_rq.lower_crit = setting;
  117. else if (threshold == LOWER_NON_RECOV_SPECIFIED)
  118. set_thresh_rq.lower_non_recov = setting;
  119. else
  120. return NULL;
  121. /***** jimbo modify ******/
  122. //忽略Sensor Owner LUN的 bit[7:4] Channel Number位。
  123. channel = intf->target_channel;
  124. /******** end ************/
  125. if (BRIDGE_TO_SENSOR(intf, target, channel)) {
  126. bridged_request = 1;
  127. save_addr = intf->target_addr;
  128. intf->target_addr = target;
  129. save_channel = intf->target_channel;
  130. intf->target_channel = channel;
  131. }
  132. memset(&req, 0, sizeof (req));
  133. req.msg.netfn = IPMI_NETFN_SE;
  134. req.msg.lun = lun;
  135. req.msg.cmd = SET_SENSOR_THRESHOLDS;
  136. req.msg.data = (uint8_t *) & set_thresh_rq;
  137. req.msg.data_len = sizeof (set_thresh_rq);
  138. rsp = intf->sendrecv(intf, &req);
  139. if (bridged_request) {
  140. intf->target_addr = save_addr;
  141. intf->target_channel = save_channel;
  142. }
  143. return rsp;
  144. }
  145. static int
  146. ipmi_sensor_print_fc_discrete(struct ipmi_intf *intf,
  147. struct sdr_record_common_sensor *sensor,
  148. uint8_t sdr_record_type)
  149. {
  150. struct sensor_reading *sr;
  151. sr = ipmi_sdr_read_sensor_value(intf, sensor, sdr_record_type, 3);
  152. if (sr == NULL) {
  153. return -1;
  154. }
  155. if (csv_output) {
  156. /* NOT IMPLEMENTED */
  157. } else {
  158. if (verbose == 0) {
  159. /* output format
  160. * id value units status thresholds....
  161. */
  162. printf("%-16s ", sr->s_id);
  163. if (sr->s_reading_valid) {
  164. if (sr->s_has_analog_value) {
  165. /* don't show discrete component */
  166. printf("| %-10s | %-10s | %-6s",
  167. sr->s_a_str, sr->s_a_units, "ok");
  168. } else {
  169. printf("| 0x%-8x | %-10s | 0x%02x%02x",
  170. sr->s_reading, "discrete",
  171. sr->s_data2, sr->s_data3);
  172. }
  173. } else {
  174. printf("| %-10s | %-10s | %-6s",
  175. "na", "discrete", "na");
  176. }
  177. printf("| %-10s| %-10s| %-10s| %-10s| %-10s| %-10s",
  178. "na", "na", "na", "na", "na", "na");
  179. printf("\n");
  180. } else {
  181. printf("Sensor ID : %s (0x%x)\n",
  182. sr->s_id, sensor->keys.sensor_num);
  183. printf(" Entity ID : %d.%d\n",
  184. sensor->entity.id, sensor->entity.instance);
  185. printf(" Sensor Type (Discrete): %s\n",
  186. ipmi_get_sensor_type(intf, sensor->sensor.
  187. type));
  188. if( sr->s_reading_valid )
  189. {
  190. if (sr->s_has_analog_value) {
  191. printf(" Sensor Reading : %s %s\n", sr->s_a_str, sr->s_a_units);
  192. }
  193. ipmi_sdr_print_discrete_state(intf, "States Asserted",
  194. sensor->sensor.type,
  195. sensor->event_type,
  196. sr->s_data2,
  197. sr->s_data3);
  198. printf("\n");
  199. } else {
  200. printf(" Unable to read sensor: Device Not Present\n\n");
  201. }
  202. }
  203. }
  204. return (sr->s_reading_valid ? 0 : -1 );
  205. }
  206. static void
  207. print_thresh_setting(struct sdr_record_full_sensor *full,
  208. uint8_t thresh_is_avail, uint8_t setting,
  209. const char *field_sep,
  210. const char *analog_fmt,
  211. const char *discrete_fmt,
  212. const char *na_fmt)
  213. {
  214. printf("%s", field_sep);
  215. if (!thresh_is_avail) {
  216. printf(na_fmt, "na");
  217. return;
  218. }
  219. if (full && !UNITS_ARE_DISCRETE(&full->cmn)) {
  220. printf(analog_fmt, sdr_convert_sensor_reading (full, setting));
  221. } else {
  222. printf(discrete_fmt, setting);
  223. }
  224. }
  225. static int
  226. ipmi_sensor_print_fc_threshold(struct ipmi_intf *intf,
  227. struct sdr_record_common_sensor *sensor,
  228. uint8_t sdr_record_type)
  229. {
  230. int thresh_available = 1;
  231. struct ipmi_rs *rsp;
  232. struct sensor_reading *sr;
  233. sr = ipmi_sdr_read_sensor_value(intf, sensor, sdr_record_type, 3);
  234. if (sr == NULL) {
  235. return -1;
  236. }
  237. const char *thresh_status = ipmi_sdr_get_thresh_status(sr, "ns");
  238. /*
  239. * Get sensor thresholds
  240. */
  241. rsp = ipmi_sdr_get_sensor_thresholds(intf,
  242. sensor->keys.sensor_num, sensor->keys.owner_id,
  243. sensor->keys.lun, sensor->keys.channel);
  244. if ((rsp == NULL) || (rsp->ccode > 0) || (rsp->data_len == 0))
  245. thresh_available = 0;
  246. if (csv_output) {
  247. /* NOT IMPLEMENTED */
  248. } else {
  249. if (verbose == 0) {
  250. /* output format
  251. * id value units status thresholds....
  252. */
  253. printf("%-16s ", sr->s_id);
  254. if (sr->s_reading_valid) {
  255. if (sr->s_has_analog_value)
  256. printf("| %-10.3f | %-10s | %-6s",
  257. sr->s_a_val, sr->s_a_units, thresh_status);
  258. else
  259. printf("| 0x%-8x | %-10s | %-6s",
  260. sr->s_reading, sr->s_a_units, thresh_status);
  261. } else {
  262. printf("| %-10s | %-10s | %-6s",
  263. "na", sr->s_a_units, "na");
  264. }
  265. if (thresh_available && sr->full) {
  266. #define PTS(bit, dataidx) { \
  267. print_thresh_setting(sr->full, rsp->data[0] & (bit), \
  268. rsp->data[(dataidx)], "| ", "%-10.3f", "0x-8x", "%-10s"); \
  269. }
  270. PTS(LOWER_NON_RECOV_SPECIFIED, 3);
  271. PTS(LOWER_CRIT_SPECIFIED, 2);
  272. PTS(LOWER_NON_CRIT_SPECIFIED, 1);
  273. PTS(UPPER_NON_CRIT_SPECIFIED, 4);
  274. PTS(UPPER_CRIT_SPECIFIED, 5);
  275. PTS(UPPER_NON_RECOV_SPECIFIED, 6);
  276. #undef PTS
  277. } else {
  278. printf
  279. ("| %-10s| %-10s| %-10s| %-10s| %-10s| %-10s",
  280. "na", "na", "na", "na", "na", "na");
  281. }
  282. printf("\n");
  283. } else {
  284. printf("Sensor ID : %s (0x%x)\n",
  285. sr->s_id, sensor->keys.sensor_num);
  286. printf(" Entity ID : %d.%d\n",
  287. sensor->entity.id, sensor->entity.instance);
  288. printf(" Sensor Type (Threshold) : %s\n",
  289. ipmi_get_sensor_type(intf, sensor->sensor.
  290. type));
  291. printf(" Sensor Reading : ");
  292. if (sr->s_reading_valid) {
  293. if (sr->full) {
  294. uint16_t raw_tol = __TO_TOL(sr->full->mtol);
  295. if (sr->s_has_analog_value) {
  296. double tol =
  297. sdr_convert_sensor_tolerance(sr->full,
  298. raw_tol);
  299. printf("%.*f (+/- %.*f) %s\n",
  300. (sr->s_a_val == (int)
  301. sr->s_a_val) ? 0 : 3,
  302. sr->s_a_val,
  303. (tol == (int) tol) ? 0 : 3, tol,
  304. sr->s_a_units);
  305. } else {
  306. printf("0x%x (+/- 0x%x) %s\n",
  307. sr->s_reading,
  308. raw_tol,
  309. sr->s_a_units);
  310. }
  311. } else {
  312. printf("0x%x %s\n", sr->s_reading,
  313. sr->s_a_units);
  314. }
  315. printf(" Status : %s\n", thresh_status);
  316. if (thresh_available) {
  317. if (sr->full) {
  318. #define PTS(bit, dataidx, str) { \
  319. print_thresh_setting(sr->full, rsp->data[0] & (bit), \
  320. rsp->data[(dataidx)], \
  321. (str), "%.3f\n", "0x%x\n", "%s\n"); \
  322. }
  323. PTS(LOWER_NON_RECOV_SPECIFIED, 3, " Lower Non-Recoverable : ");
  324. PTS(LOWER_CRIT_SPECIFIED, 2, " Lower Critical : ");
  325. PTS(LOWER_NON_CRIT_SPECIFIED, 1, " Lower Non-Critical : ");
  326. PTS(UPPER_NON_CRIT_SPECIFIED, 4, " Upper Non-Critical : ");
  327. PTS(UPPER_CRIT_SPECIFIED, 5, " Upper Critical : ");
  328. PTS(UPPER_NON_RECOV_SPECIFIED, 6, " Upper Non-Recoverable : ");
  329. #undef PTS
  330. }
  331. ipmi_sdr_print_sensor_hysteresis(sensor, sr->full,
  332. sr->full ? sr->full->threshold.hysteresis.positive :
  333. sr->compact->threshold.hysteresis.positive,
  334. "Positive Hysteresis");
  335. ipmi_sdr_print_sensor_hysteresis(sensor, sr->full,
  336. sr->full ? sr->full->threshold.hysteresis.negative :
  337. sr->compact->threshold.hysteresis.negative,
  338. "Negative Hysteresis");
  339. } else {
  340. printf(" Sensor Threshold Settings not available\n");
  341. }
  342. } else {
  343. printf(" Unable to read sensor: Device Not Present\n\n");
  344. }
  345. ipmi_sdr_print_sensor_event_status(intf,
  346. sensor->keys.
  347. sensor_num,
  348. sensor->sensor.type,
  349. sensor->event_type,
  350. ANALOG_SENSOR,
  351. sensor->keys.owner_id,
  352. sensor->keys.lun,
  353. sensor->keys.channel);
  354. ipmi_sdr_print_sensor_event_enable(intf,
  355. sensor->keys.
  356. sensor_num,
  357. sensor->sensor.type,
  358. sensor->event_type,
  359. ANALOG_SENSOR,
  360. sensor->keys.owner_id,
  361. sensor->keys.lun,
  362. sensor->keys.channel);
  363. printf("\n");
  364. }
  365. }
  366. return (sr->s_reading_valid ? 0 : -1 );
  367. }
  368. int
  369. ipmi_sensor_print_fc(struct ipmi_intf *intf,
  370. struct sdr_record_common_sensor *sensor,
  371. uint8_t sdr_record_type)
  372. {
  373. if (IS_THRESHOLD_SENSOR(sensor))
  374. return ipmi_sensor_print_fc_threshold(intf, sensor, sdr_record_type);
  375. else
  376. return ipmi_sensor_print_fc_discrete(intf, sensor, sdr_record_type);
  377. }
  378. static int
  379. ipmi_sensor_list(struct ipmi_intf *intf)
  380. {
  381. struct sdr_get_rs *header;
  382. struct ipmi_sdr_iterator *itr;
  383. int rc = 0;
  384. lprintf(LOG_DEBUG, "Querying SDR for sensor list");
  385. itr = ipmi_sdr_start(intf, 0);
  386. if (itr == NULL) {
  387. lprintf(LOG_ERR, "Unable to open SDR for reading");
  388. return -1;
  389. }
  390. while ((header = ipmi_sdr_get_next_header(intf, itr)) != NULL) {
  391. uint8_t *rec;
  392. rec = ipmi_sdr_get_record(intf, header, itr);
  393. if (rec == NULL) {
  394. lprintf(LOG_DEBUG, "rec == NULL");
  395. continue;
  396. }
  397. switch (header->type) {
  398. case SDR_RECORD_TYPE_FULL_SENSOR:
  399. case SDR_RECORD_TYPE_COMPACT_SENSOR:
  400. ipmi_sensor_print_fc(intf,
  401. (struct
  402. sdr_record_common_sensor *)
  403. rec,
  404. header->type);
  405. break;
  406. }
  407. free(rec);
  408. rec = NULL;
  409. /* fix for CR6604909: */
  410. /* mask failure of individual reads in sensor list command */
  411. /* rc = (r == 0) ? rc : r; */
  412. }
  413. ipmi_sdr_end(intf, itr);
  414. return rc;
  415. }
  416. static const struct valstr threshold_vals[] = {
  417. {UPPER_NON_RECOV_SPECIFIED, "Upper Non-Recoverable"},
  418. {UPPER_CRIT_SPECIFIED, "Upper Critical"},
  419. {UPPER_NON_CRIT_SPECIFIED, "Upper Non-Critical"},
  420. {LOWER_NON_RECOV_SPECIFIED, "Lower Non-Recoverable"},
  421. {LOWER_CRIT_SPECIFIED, "Lower Critical"},
  422. {LOWER_NON_CRIT_SPECIFIED, "Lower Non-Critical"},
  423. {0x00, NULL},
  424. };
  425. static int
  426. __ipmi_sensor_set_threshold(struct ipmi_intf *intf,
  427. uint8_t num, uint8_t mask, uint8_t setting,
  428. uint8_t target, uint8_t lun, uint8_t channel)
  429. {
  430. struct ipmi_rs *rsp;
  431. rsp = ipmi_sensor_set_sensor_thresholds(intf, num, mask, setting,
  432. target, lun, channel);
  433. if (rsp == NULL) {
  434. lprintf(LOG_ERR, "Error setting threshold");
  435. return -1;
  436. }
  437. if (rsp->ccode > 0) {
  438. lprintf(LOG_ERR, "Error setting threshold: %s",
  439. val2str(rsp->ccode, completion_code_vals));
  440. return -1;
  441. }
  442. return 0;
  443. }
  444. static uint8_t
  445. __ipmi_sensor_threshold_value_to_raw(struct sdr_record_full_sensor *full, double value)
  446. {
  447. if (!UNITS_ARE_DISCRETE(&full->cmn)) { /* Has an analog reading */
  448. /* Has an analog reading and supports mx+b */
  449. return sdr_convert_sensor_value_to_raw(full, value);
  450. }
  451. else {
  452. /* Does not have an analog reading and/or does not support mx+b */
  453. if (value > 255) {
  454. return 255;
  455. }
  456. else if (value < 0) {
  457. return 0;
  458. }
  459. else {
  460. return (uint8_t )value;
  461. }
  462. }
  463. }
  464. static int
  465. ipmi_sensor_set_threshold(struct ipmi_intf *intf, int argc, char **argv)
  466. {
  467. char *id, *thresh;
  468. uint8_t settingMask = 0;
  469. double setting1 = 0.0, setting2 = 0.0, setting3 = 0.0;
  470. int allUpper = 0, allLower = 0;
  471. int ret = 0;
  472. struct ipmi_rs *rsp;
  473. int i =0;
  474. double val[10] = {0};
  475. struct sdr_record_list *sdr;
  476. if (argc < 3 || strncmp(argv[0], "help", 4) == 0) {
  477. print_sensor_thresh_usage();
  478. return 0;
  479. }
  480. id = argv[0];
  481. thresh = argv[1];
  482. if (strncmp(thresh, "upper", 5) == 0) {
  483. if (argc < 5) {
  484. lprintf(LOG_ERR,
  485. "usage: sensor thresh <id> upper <unc> <ucr> <unr>");
  486. return -1;
  487. }
  488. allUpper = 1;
  489. if (str2double(argv[2], &setting1) != 0) {
  490. lprintf(LOG_ERR, "Given unc '%s' is invalid.",
  491. argv[2]);
  492. return (-1);
  493. }
  494. if (str2double(argv[3], &setting2) != 0) {
  495. lprintf(LOG_ERR, "Given ucr '%s' is invalid.",
  496. argv[3]);
  497. return (-1);
  498. }
  499. if (str2double(argv[4], &setting3) != 0) {
  500. lprintf(LOG_ERR, "Given unr '%s' is invalid.",
  501. argv[4]);
  502. return (-1);
  503. }
  504. } else if (strncmp(thresh, "lower", 5) == 0) {
  505. if (argc < 5) {
  506. lprintf(LOG_ERR,
  507. "usage: sensor thresh <id> lower <lnr> <lcr> <lnc>");
  508. return -1;
  509. }
  510. allLower = 1;
  511. if (str2double(argv[2], &setting1) != 0) {
  512. lprintf(LOG_ERR, "Given lnc '%s' is invalid.",
  513. argv[2]);
  514. return (-1);
  515. }
  516. if (str2double(argv[3], &setting2) != 0) {
  517. lprintf(LOG_ERR, "Given lcr '%s' is invalid.",
  518. argv[3]);
  519. return (-1);
  520. }
  521. if (str2double(argv[4], &setting3) != 0) {
  522. lprintf(LOG_ERR, "Given lnr '%s' is invalid.",
  523. argv[4]);
  524. return (-1);
  525. }
  526. } else {
  527. if (strncmp(thresh, "unr", 3) == 0)
  528. settingMask = UPPER_NON_RECOV_SPECIFIED;
  529. else if (strncmp(thresh, "ucr", 3) == 0)
  530. settingMask = UPPER_CRIT_SPECIFIED;
  531. else if (strncmp(thresh, "unc", 3) == 0)
  532. settingMask = UPPER_NON_CRIT_SPECIFIED;
  533. else if (strncmp(thresh, "lnc", 3) == 0)
  534. settingMask = LOWER_NON_CRIT_SPECIFIED;
  535. else if (strncmp(thresh, "lcr", 3) == 0)
  536. settingMask = LOWER_CRIT_SPECIFIED;
  537. else if (strncmp(thresh, "lnr", 3) == 0)
  538. settingMask = LOWER_NON_RECOV_SPECIFIED;
  539. else {
  540. lprintf(LOG_ERR,
  541. "Valid threshold '%s' for sensor '%s' not specified!",
  542. thresh, id);
  543. return -1;
  544. }
  545. if (str2double(argv[2], &setting1) != 0) {
  546. lprintf(LOG_ERR,
  547. "Given %s threshold value '%s' is invalid.",
  548. thresh, argv[2]);
  549. return (-1);
  550. }
  551. }
  552. printf("Locating sensor record '%s'...\n", id);
  553. /* lookup by sensor name */
  554. sdr = ipmi_sdr_find_sdr_byid(intf, id);
  555. if (sdr == NULL) {
  556. lprintf(LOG_ERR, "Sensor data record not found!");
  557. return -1;
  558. }
  559. if (sdr->type != SDR_RECORD_TYPE_FULL_SENSOR) {
  560. lprintf(LOG_ERR, "Invalid sensor type %02x", sdr->type);
  561. return -1;
  562. }
  563. if (!IS_THRESHOLD_SENSOR(sdr->record.common)) {
  564. lprintf(LOG_ERR, "Invalid sensor event type %02x", sdr->record.common->event_type);
  565. return -1;
  566. }
  567. if (allUpper) {
  568. settingMask = UPPER_NON_CRIT_SPECIFIED;
  569. printf("Setting sensor \"%s\" %s threshold to %.3f\n",
  570. sdr->record.full->id_string,
  571. val2str(settingMask, threshold_vals), setting1);
  572. ret = __ipmi_sensor_set_threshold(intf,
  573. sdr->record.common->keys.
  574. sensor_num, settingMask,
  575. __ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting1),
  576. sdr->record.common->keys.owner_id,
  577. sdr->record.common->keys.lun,
  578. sdr->record.common->keys.channel);
  579. settingMask = UPPER_CRIT_SPECIFIED;
  580. printf("Setting sensor \"%s\" %s threshold to %.3f\n",
  581. sdr->record.full->id_string,
  582. val2str(settingMask, threshold_vals), setting2);
  583. ret = __ipmi_sensor_set_threshold(intf,
  584. sdr->record.common->keys.
  585. sensor_num, settingMask,
  586. __ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting2),
  587. sdr->record.common->keys.owner_id,
  588. sdr->record.common->keys.lun,
  589. sdr->record.common->keys.channel);
  590. settingMask = UPPER_NON_RECOV_SPECIFIED;
  591. printf("Setting sensor \"%s\" %s threshold to %.3f\n",
  592. sdr->record.full->id_string,
  593. val2str(settingMask, threshold_vals), setting3);
  594. ret = __ipmi_sensor_set_threshold(intf,
  595. sdr->record.common->keys.
  596. sensor_num, settingMask,
  597. __ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting3),
  598. sdr->record.common->keys.owner_id,
  599. sdr->record.common->keys.lun,
  600. sdr->record.common->keys.channel);
  601. } else if (allLower) {
  602. settingMask = LOWER_NON_RECOV_SPECIFIED;
  603. printf("Setting sensor \"%s\" %s threshold to %.3f\n",
  604. sdr->record.full->id_string,
  605. val2str(settingMask, threshold_vals), setting1);
  606. ret = __ipmi_sensor_set_threshold(intf,
  607. sdr->record.common->keys.
  608. sensor_num, settingMask,
  609. __ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting1),
  610. sdr->record.common->keys.owner_id,
  611. sdr->record.common->keys.lun,
  612. sdr->record.common->keys.channel);
  613. settingMask = LOWER_CRIT_SPECIFIED;
  614. printf("Setting sensor \"%s\" %s threshold to %.3f\n",
  615. sdr->record.full->id_string,
  616. val2str(settingMask, threshold_vals), setting2);
  617. ret = __ipmi_sensor_set_threshold(intf,
  618. sdr->record.common->keys.
  619. sensor_num, settingMask,
  620. __ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting2),
  621. sdr->record.common->keys.owner_id,
  622. sdr->record.common->keys.lun,
  623. sdr->record.common->keys.channel);
  624. settingMask = LOWER_NON_CRIT_SPECIFIED;
  625. printf("Setting sensor \"%s\" %s threshold to %.3f\n",
  626. sdr->record.full->id_string,
  627. val2str(settingMask, threshold_vals), setting3);
  628. ret = __ipmi_sensor_set_threshold(intf,
  629. sdr->record.common->keys.
  630. sensor_num, settingMask,
  631. __ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting3),
  632. sdr->record.common->keys.owner_id,
  633. sdr->record.common->keys.lun,
  634. sdr->record.common->keys.channel);
  635. } else {
  636. /*
  637. * Current implementation doesn't check for the valid setting of upper non critical and other thresholds.
  638. * In the below logic:
  639. * Get all the current reading of the sensor i.e. unc, uc, lc,lnc.
  640. * Validate the values given by the user.
  641. * If the values are not correct, then popup with the Error message and return.
  642. */
  643. /*
  644. * Get current reading
  645. */
  646. rsp = ipmi_sdr_get_sensor_reading_ipmb(intf,
  647. sdr->record.common->keys.sensor_num,
  648. sdr->record.common->keys.owner_id,
  649. sdr->record.common->keys.lun,sdr->record.common->keys.channel);
  650. rsp = ipmi_sdr_get_sensor_thresholds(intf,
  651. sdr->record.common->keys.sensor_num,
  652. sdr->record.common->keys.owner_id,
  653. sdr->record.common->keys.lun,
  654. sdr->record.common->keys.channel);
  655. if ((rsp == NULL) || (rsp->ccode > 0)) {
  656. lprintf(LOG_ERR, "Sensor data record not found!");
  657. return -1;
  658. }
  659. for(i=1;i<=6;i++) {
  660. val[i] = sdr_convert_sensor_reading(sdr->record.full, rsp->data[i]);
  661. if(val[i] < 0)
  662. val[i] = 0;
  663. }
  664. /* Check for the valid Upper non recovarable Value.*/
  665. if( (settingMask & UPPER_NON_RECOV_SPECIFIED) ) {
  666. if( (rsp->data[0] & UPPER_NON_RECOV_SPECIFIED) &&
  667. (( (rsp->data[0] & UPPER_CRIT_SPECIFIED) && ( setting1 <= val[5])) ||
  668. ( (rsp->data[0] & UPPER_NON_CRIT_SPECIFIED) && ( setting1 <= val[4]))) )
  669. {
  670. lprintf(LOG_ERR, INVALID_THRESHOLD);
  671. return -1;
  672. }
  673. } else if( (settingMask & UPPER_CRIT_SPECIFIED) ) { /* Check for the valid Upper critical Value.*/
  674. if( (rsp->data[0] & UPPER_CRIT_SPECIFIED) &&
  675. (((rsp->data[0] & UPPER_NON_RECOV_SPECIFIED)&& ( setting1 >= val[6])) ||
  676. ((rsp->data[0] & UPPER_NON_CRIT_SPECIFIED)&&( setting1 <= val[4]))) )
  677. {
  678. lprintf(LOG_ERR, INVALID_THRESHOLD);
  679. return -1;
  680. }
  681. } else if( (settingMask & UPPER_NON_CRIT_SPECIFIED) ) { /* Check for the valid Upper non critical Value.*/
  682. if( (rsp->data[0] & UPPER_NON_CRIT_SPECIFIED) &&
  683. (((rsp->data[0] & UPPER_NON_RECOV_SPECIFIED)&&( setting1 >= val[6])) ||
  684. ((rsp->data[0] & UPPER_CRIT_SPECIFIED)&&( setting1 >= val[5])) ||
  685. ((rsp->data[0] & LOWER_NON_CRIT_SPECIFIED)&&( setting1 <= val[1]))) )
  686. {
  687. lprintf(LOG_ERR, INVALID_THRESHOLD);
  688. return -1;
  689. }
  690. } else if( (settingMask & LOWER_NON_CRIT_SPECIFIED) ) { /* Check for the valid lower non critical Value.*/
  691. if( (rsp->data[0] & LOWER_NON_CRIT_SPECIFIED) &&
  692. (((rsp->data[0] & LOWER_CRIT_SPECIFIED)&&( setting1 <= val[2])) ||
  693. ((rsp->data[0] & LOWER_NON_RECOV_SPECIFIED)&&( setting1 <= val[3]))||
  694. ((rsp->data[0] & UPPER_NON_CRIT_SPECIFIED)&&( setting1 >= val[4]))) )
  695. {
  696. lprintf(LOG_ERR, INVALID_THRESHOLD);
  697. return -1;
  698. }
  699. } else if( (settingMask & LOWER_CRIT_SPECIFIED) ) { /* Check for the valid lower critical Value.*/
  700. if( (rsp->data[0] & LOWER_CRIT_SPECIFIED) &&
  701. (((rsp->data[0] & LOWER_NON_CRIT_SPECIFIED)&&( setting1 >= val[1])) ||
  702. ((rsp->data[0] & LOWER_NON_RECOV_SPECIFIED)&&( setting1 <= val[3]))) )
  703. {
  704. lprintf(LOG_ERR, INVALID_THRESHOLD);
  705. return -1;
  706. }
  707. } else if( (settingMask & LOWER_NON_RECOV_SPECIFIED) ) { /* Check for the valid lower non recovarable Value.*/
  708. if( (rsp->data[0] & LOWER_NON_RECOV_SPECIFIED) &&
  709. (((rsp->data[0] & LOWER_NON_CRIT_SPECIFIED)&&( setting1 >= val[1])) ||
  710. ((rsp->data[0] & LOWER_CRIT_SPECIFIED)&&( setting1 >= val[2]))) )
  711. {
  712. lprintf(LOG_ERR, INVALID_THRESHOLD);
  713. return -1;
  714. }
  715. } else { /* None of this Then Return with error messages.*/
  716. lprintf(LOG_ERR, INVALID_THRESHOLD);
  717. return -1;
  718. }
  719. printf("Setting sensor \"%s\" %s threshold to %.3f\n",
  720. sdr->record.full->id_string,
  721. val2str(settingMask, threshold_vals), setting1);
  722. ret = __ipmi_sensor_set_threshold(intf,
  723. sdr->record.common->keys.
  724. sensor_num, settingMask,
  725. __ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting1),
  726. sdr->record.common->keys.owner_id,
  727. sdr->record.common->keys.lun,
  728. sdr->record.common->keys.channel);
  729. }
  730. return ret;
  731. }
  732. static int
  733. ipmi_sensor_get_reading(struct ipmi_intf *intf, int argc, char **argv)
  734. {
  735. struct sdr_record_list *sdr;
  736. int i, rc=0;
  737. if (argc < 1 || strncmp(argv[0], "help", 4) == 0) {
  738. lprintf(LOG_NOTICE, "sensor reading <id> ... [id]");
  739. lprintf(LOG_NOTICE, " id : name of desired sensor");
  740. return -1;
  741. }
  742. for (i = 0; i < argc; i++) {
  743. sdr = ipmi_sdr_find_sdr_byid(intf, argv[i]);
  744. if (sdr == NULL) {
  745. lprintf(LOG_ERR, "Sensor \"%s\" not found!",
  746. argv[i]);
  747. rc = -1;
  748. continue;
  749. }
  750. switch (sdr->type) {
  751. case SDR_RECORD_TYPE_FULL_SENSOR:
  752. case SDR_RECORD_TYPE_COMPACT_SENSOR:
  753. {
  754. struct sensor_reading *sr;
  755. struct sdr_record_common_sensor *sensor = sdr->record.common;
  756. sr = ipmi_sdr_read_sensor_value(intf, sensor, sdr->type, 3);
  757. if (sr == NULL) {
  758. rc = -1;
  759. continue;
  760. }
  761. if (!sr->full)
  762. continue;
  763. if (!sr->s_reading_valid)
  764. continue;
  765. if (!sr->s_has_analog_value) {
  766. lprintf(LOG_ERR, "Sensor \"%s\" is a discrete sensor!", argv[i]);
  767. continue;
  768. }
  769. if (csv_output)
  770. printf("%s,%s\n", argv[i], sr->s_a_str);
  771. else
  772. printf("%-16s | %s\n", argv[i], sr->s_a_str);
  773. break;
  774. }
  775. default:
  776. continue;
  777. }
  778. }
  779. return rc;
  780. }
  781. static int
  782. ipmi_sensor_get(struct ipmi_intf *intf, int argc, char **argv)
  783. {
  784. int i, v;
  785. int rc = 0;
  786. struct sdr_record_list *sdr;
  787. if (argc < 1) {
  788. lprintf(LOG_ERR, "Not enough parameters given.");
  789. print_sensor_get_usage();
  790. return (-1);
  791. } else if (strcmp(argv[0], "help") == 0) {
  792. print_sensor_get_usage();
  793. return 0;
  794. }
  795. printf("Locating sensor record...\n");
  796. /* lookup by sensor name */
  797. for (i = 0; i < argc; i++) {
  798. sdr = ipmi_sdr_find_sdr_byid(intf, argv[i]);
  799. if (sdr == NULL) {
  800. lprintf(LOG_ERR, "Sensor data record \"%s\" not found!",
  801. argv[i]);
  802. rc = -1;
  803. continue;
  804. }
  805. /* need to set verbose level to 1 */
  806. v = verbose;
  807. verbose = 1;
  808. switch (sdr->type) {
  809. case SDR_RECORD_TYPE_FULL_SENSOR:
  810. case SDR_RECORD_TYPE_COMPACT_SENSOR:
  811. if (ipmi_sensor_print_fc(intf,
  812. (struct sdr_record_common_sensor *) sdr->record.common,
  813. sdr->type)) {
  814. rc = -1;
  815. }
  816. break;
  817. default:
  818. if (ipmi_sdr_print_listentry(intf, sdr) < 0) {
  819. rc = (-1);
  820. }
  821. break;
  822. }
  823. verbose = v;
  824. sdr = NULL;
  825. }
  826. return rc;
  827. }
  828. int
  829. ipmi_sensor_main(struct ipmi_intf *intf, int argc, char **argv)
  830. {
  831. int rc = 0;
  832. if (argc == 0) {
  833. rc = ipmi_sensor_list(intf);
  834. } else if (strncmp(argv[0], "help", 4) == 0) {
  835. lprintf(LOG_NOTICE, "Sensor Commands: list thresh get reading");
  836. } else if (strncmp(argv[0], "list", 4) == 0) {
  837. rc = ipmi_sensor_list(intf);
  838. } else if (strncmp(argv[0], "thresh", 5) == 0) {
  839. rc = ipmi_sensor_set_threshold(intf, argc - 1, &argv[1]);
  840. } else if (strncmp(argv[0], "get", 3) == 0) {
  841. rc = ipmi_sensor_get(intf, argc - 1, &argv[1]);
  842. } else if (strncmp(argv[0], "reading", 7) == 0) {
  843. rc = ipmi_sensor_get_reading(intf, argc - 1, &argv[1]);
  844. } else {
  845. lprintf(LOG_ERR, "Invalid sensor command: %s", argv[0]);
  846. rc = -1;
  847. }
  848. return rc;
  849. }
  850. /* print_sensor_get_usage - print usage for # ipmitool sensor get NAC;
  851. *
  852. * @returns: void
  853. */
  854. void
  855. print_sensor_get_usage()
  856. {
  857. lprintf(LOG_NOTICE, "sensor get <id> ... [id]");
  858. lprintf(LOG_NOTICE, " id : name of desired sensor");
  859. }
  860. /* print_sensor_thresh_set_usage - print usage for # ipmitool sensor thresh;
  861. *
  862. * @returns: void
  863. */
  864. void
  865. print_sensor_thresh_usage()
  866. {
  867. lprintf(LOG_NOTICE,
  868. "sensor thresh <id> <threshold> <setting>");
  869. lprintf(LOG_NOTICE,
  870. " id : name of the sensor for which threshold is to be set");
  871. lprintf(LOG_NOTICE,
  872. " threshold : which threshold to set");
  873. lprintf(LOG_NOTICE,
  874. " unr = upper non-recoverable");
  875. lprintf(LOG_NOTICE,
  876. " ucr = upper critical");
  877. lprintf(LOG_NOTICE,
  878. " unc = upper non-critical");
  879. lprintf(LOG_NOTICE,
  880. " lnc = lower non-critical");
  881. lprintf(LOG_NOTICE,
  882. " lcr = lower critical");
  883. lprintf(LOG_NOTICE,
  884. " lnr = lower non-recoverable");
  885. lprintf(LOG_NOTICE,
  886. " setting : the value to set the threshold to");
  887. lprintf(LOG_NOTICE,
  888. "");
  889. lprintf(LOG_NOTICE,
  890. "sensor thresh <id> lower <lnr> <lcr> <lnc>");
  891. lprintf(LOG_NOTICE,
  892. " Set all lower thresholds at the same time");
  893. lprintf(LOG_NOTICE,
  894. "");
  895. lprintf(LOG_NOTICE,
  896. "sensor thresh <id> upper <unc> <ucr> <unr>");
  897. lprintf(LOG_NOTICE,
  898. " Set all upper thresholds at the same time");
  899. lprintf(LOG_NOTICE, "");
  900. }