ipmi_chassis.c 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389
  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. #define _SVID_SOURCE || _BSD_SOURCE || _POSIX_C_SOURCE >= 1 || \
  33. _XOPEN_SOURCE || _POSIX_SOURCE
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #include <stdio.h>
  37. #include <time.h>
  38. #include <ipmitool/bswap.h>
  39. #include <ipmitool/helper.h>
  40. #include <ipmitool/ipmi.h>
  41. #include <ipmitool/log.h>
  42. #include <ipmitool/ipmi_intf.h>
  43. #include <ipmitool/ipmi_strings.h>
  44. #include <ipmitool/ipmi_chassis.h>
  45. extern int verbose;
  46. int
  47. ipmi_chassis_power_status(struct ipmi_intf * intf)
  48. {
  49. struct ipmi_rs * rsp;
  50. struct ipmi_rq req;
  51. memset(&req, 0, sizeof(req));
  52. req.msg.netfn = IPMI_NETFN_CHASSIS;
  53. req.msg.cmd = 0x1;
  54. req.msg.data_len = 0;
  55. rsp = intf->sendrecv(intf, &req);
  56. if (rsp == NULL) {
  57. lprintf(LOG_ERR, "Unable to get Chassis Power Status");
  58. return -1;
  59. }
  60. if (rsp->ccode > 0) {
  61. lprintf(LOG_ERR, "Get Chassis Power Status failed: %s",
  62. val2str(rsp->ccode, completion_code_vals));
  63. return -1;
  64. }
  65. return rsp->data[0] & 1;
  66. }
  67. static int
  68. ipmi_chassis_print_power_status(struct ipmi_intf * intf)
  69. {
  70. int ps = ipmi_chassis_power_status(intf);
  71. if (ps < 0)
  72. return -1;
  73. printf("Chassis Power is %s\n", ps ? "on" : "off");
  74. return 0;
  75. }
  76. int
  77. ipmi_chassis_power_control(struct ipmi_intf * intf, uint8_t ctl)
  78. {
  79. struct ipmi_rs * rsp;
  80. struct ipmi_rq req;
  81. memset(&req, 0, sizeof(req));
  82. req.msg.netfn = IPMI_NETFN_CHASSIS;
  83. req.msg.cmd = 0x2;
  84. req.msg.data = &ctl;
  85. req.msg.data_len = 1;
  86. rsp = intf->sendrecv(intf, &req);
  87. if (rsp == NULL) {
  88. lprintf(LOG_ERR, "Unable to set Chassis Power Control to %s",
  89. val2str(ctl, ipmi_chassis_power_control_vals));
  90. return -1;
  91. }
  92. if (rsp->ccode > 0) {
  93. lprintf(LOG_ERR, "Set Chassis Power Control to %s failed: %s",
  94. val2str(ctl, ipmi_chassis_power_control_vals),
  95. val2str(rsp->ccode, completion_code_vals));
  96. return -1;
  97. }
  98. printf("Chassis Power Control: %s\n",
  99. val2str(ctl, ipmi_chassis_power_control_vals));
  100. return 0;
  101. }
  102. static int
  103. ipmi_chassis_identify(struct ipmi_intf * intf, char * arg)
  104. {
  105. struct ipmi_rq req;
  106. struct ipmi_rs * rsp;
  107. int rc = (-3);
  108. struct {
  109. uint8_t interval;
  110. uint8_t force_on;
  111. } identify_data = { .interval = 0, .force_on = 0 };
  112. memset(&req, 0, sizeof(req));
  113. req.msg.netfn = IPMI_NETFN_CHASSIS;
  114. req.msg.cmd = 0x4;
  115. if (arg != NULL) {
  116. if (strncmp(arg, "force", 5) == 0) {
  117. identify_data.force_on = 1;
  118. } else {
  119. if ( (rc = str2uchar(arg, &identify_data.interval)) != 0) {
  120. if (rc == (-2)) {
  121. lprintf(LOG_ERR, "Invalid interval given.");
  122. } else {
  123. lprintf(LOG_ERR, "Given interval is too big.");
  124. }
  125. return (-1);
  126. }
  127. }
  128. req.msg.data = (uint8_t *)&identify_data;
  129. /* The Force Identify On byte is optional and not
  130. * supported by all devices-- if force is not specified,
  131. * we pass only one data byte; if specified, we pass two
  132. * data bytes and check for an error completion code
  133. */
  134. req.msg.data_len = (identify_data.force_on) ? 2 : 1;
  135. }
  136. rsp = intf->sendrecv(intf, &req);
  137. if (rsp == NULL) {
  138. lprintf(LOG_ERR, "Unable to set Chassis Identify");
  139. return -1;
  140. }
  141. if (rsp->ccode > 0) {
  142. lprintf(LOG_ERR, "Set Chassis Identify failed: %s",
  143. val2str(rsp->ccode, completion_code_vals));
  144. if (identify_data.force_on != 0) {
  145. /* Intel SE7501WV2 F/W 1.2 returns CC 0xC7, but
  146. * the IPMI v1.5 spec does not standardize a CC
  147. * if unsupported, so we warn
  148. */
  149. lprintf(LOG_WARNING, "Chassis may not support Force Identify On\n");
  150. }
  151. return -1;
  152. }
  153. printf("Chassis identify interval: ");
  154. if (arg == NULL) {
  155. printf("default (15 seconds)\n");
  156. } else {
  157. if (identify_data.force_on != 0) {
  158. printf("indefinite\n");
  159. } else {
  160. if (identify_data.interval == 0)
  161. printf("off\n");
  162. else
  163. printf("%i seconds\n", identify_data.interval);
  164. }
  165. }
  166. return 0;
  167. }
  168. static int
  169. ipmi_chassis_poh(struct ipmi_intf * intf)
  170. {
  171. struct ipmi_rs * rsp;
  172. struct ipmi_rq req;
  173. uint8_t mins_per_count;
  174. uint32_t count;
  175. float minutes;
  176. uint32_t days, hours;
  177. memset(&req, 0, sizeof(req));
  178. req.msg.netfn = IPMI_NETFN_CHASSIS;
  179. req.msg.cmd = 0xf;
  180. rsp = intf->sendrecv(intf, &req);
  181. if (rsp == NULL) {
  182. lprintf(LOG_ERR, "Unable to get Chassis Power-On-Hours");
  183. return -1;
  184. }
  185. if (rsp->ccode > 0) {
  186. lprintf(LOG_ERR, "Get Chassis Power-On-Hours failed: %s",
  187. val2str(rsp->ccode, completion_code_vals));
  188. return -1;
  189. }
  190. mins_per_count = rsp->data[0];
  191. memcpy(&count, rsp->data+1, 4);
  192. #if WORDS_BIGENDIAN
  193. count = BSWAP_32(count);
  194. #endif
  195. minutes = (float)count * mins_per_count;
  196. days = minutes / 1440;
  197. minutes -= (float)days * 1440;
  198. hours = minutes / 60;
  199. minutes -= hours * 60;
  200. if (mins_per_count < 60) {
  201. printf("POH Counter : %i days, %i hours, %li minutes\n",
  202. days, hours, (long)minutes);
  203. } else {
  204. printf("POH Counter : %i days, %i hours\n", days, hours);
  205. }
  206. return 0;
  207. }
  208. static int
  209. ipmi_chassis_restart_cause(struct ipmi_intf * intf)
  210. {
  211. struct ipmi_rs * rsp;
  212. struct ipmi_rq req;
  213. memset(&req, 0, sizeof(req));
  214. req.msg.netfn = IPMI_NETFN_CHASSIS;
  215. req.msg.cmd = 0x7;
  216. rsp = intf->sendrecv(intf, &req);
  217. if (rsp == NULL) {
  218. lprintf(LOG_ERR, "Unable to get Chassis Restart Cause");
  219. return -1;
  220. }
  221. if (rsp->ccode > 0) {
  222. lprintf(LOG_ERR, "Get Chassis Restart Cause failed: %s",
  223. val2str(rsp->ccode, completion_code_vals));
  224. return -1;
  225. }
  226. printf("System restart cause: ");
  227. switch (rsp->data[0] & 0xf) {
  228. case 0:
  229. printf("unknown\n");
  230. break;
  231. case 1:
  232. printf("chassis power control command\n");
  233. break;
  234. case 2:
  235. printf("reset via pushbutton\n");
  236. break;
  237. case 3:
  238. printf("power-up via pushbutton\n");
  239. break;
  240. case 4:
  241. printf("watchdog expired\n");
  242. break;
  243. case 5:
  244. printf("OEM\n");
  245. break;
  246. case 6:
  247. printf("power-up due to always-restore power policy\n");
  248. break;
  249. case 7:
  250. printf("power-up due to restore-previous power policy\n");
  251. break;
  252. case 8:
  253. printf("reset via PEF\n");
  254. break;
  255. case 9:
  256. printf("power-cycle via PEF\n");
  257. break;
  258. default:
  259. printf("invalid\n");
  260. }
  261. return 0;
  262. }
  263. int
  264. ipmi_chassis_status(struct ipmi_intf * intf)
  265. {
  266. struct ipmi_rs * rsp;
  267. struct ipmi_rq req;
  268. memset(&req, 0, sizeof(req));
  269. req.msg.netfn = IPMI_NETFN_CHASSIS;
  270. req.msg.cmd = 0x1;
  271. rsp = intf->sendrecv(intf, &req);
  272. if (rsp == NULL) {
  273. lprintf(LOG_ERR, "Error sending Chassis Status command");
  274. return -1;
  275. }
  276. if (rsp->ccode > 0) {
  277. lprintf(LOG_ERR, "Error sending Chassis Status command: %s",
  278. val2str(rsp->ccode, completion_code_vals));
  279. return -1;
  280. }
  281. /* byte 1 */
  282. printf("System Power : %s\n", (rsp->data[0] & 0x1) ? "on" : "off");
  283. printf("Power Overload : %s\n", (rsp->data[0] & 0x2) ? "true" : "false");
  284. printf("Power Interlock : %s\n", (rsp->data[0] & 0x4) ? "active" : "inactive");
  285. printf("Main Power Fault : %s\n", (rsp->data[0] & 0x8) ? "true" : "false");
  286. printf("Power Control Fault : %s\n", (rsp->data[0] & 0x10) ? "true" : "false");
  287. printf("Power Restore Policy : ");
  288. switch ((rsp->data[0] & 0x60) >> 5) {
  289. case 0x0:
  290. printf("always-off\n");
  291. break;
  292. case 0x1:
  293. printf("previous\n");
  294. break;
  295. case 0x2:
  296. printf("always-on\n");
  297. break;
  298. case 0x3:
  299. default:
  300. printf("unknown\n");
  301. }
  302. /* byte 2 */
  303. printf("Last Power Event : ");
  304. if (rsp->data[1] & 0x1)
  305. printf("ac-failed ");
  306. if (rsp->data[1] & 0x2)
  307. printf("overload ");
  308. if (rsp->data[1] & 0x4)
  309. printf("interlock ");
  310. if (rsp->data[1] & 0x8)
  311. printf("fault ");
  312. if (rsp->data[1] & 0x10)
  313. printf("command");
  314. printf("\n");
  315. /* byte 3 */
  316. printf("Chassis Intrusion : %s\n", (rsp->data[2] & 0x1) ? "active" : "inactive");
  317. printf("Front-Panel Lockout : %s\n", (rsp->data[2] & 0x2) ? "active" : "inactive");
  318. printf("Drive Fault : %s\n", (rsp->data[2] & 0x4) ? "true" : "false");
  319. printf("Cooling/Fan Fault : %s\n", (rsp->data[2] & 0x8) ? "true" : "false");
  320. if (rsp->data_len > 3) {
  321. /* optional byte 4 */
  322. if (rsp->data[3] == 0) {
  323. printf("Front Panel Control : none\n");
  324. } else {
  325. printf("Sleep Button Disable : %s\n", (rsp->data[3] & 0x80) ? "allowed" : "not allowed");
  326. printf("Diag Button Disable : %s\n", (rsp->data[3] & 0x40) ? "allowed" : "not allowed");
  327. printf("Reset Button Disable : %s\n", (rsp->data[3] & 0x20) ? "allowed" : "not allowed");
  328. printf("Power Button Disable : %s\n", (rsp->data[3] & 0x10) ? "allowed" : "not allowed");
  329. printf("Sleep Button Disabled: %s\n", (rsp->data[3] & 0x08) ? "true" : "false");
  330. printf("Diag Button Disabled : %s\n", (rsp->data[3] & 0x04) ? "true" : "false");
  331. printf("Reset Button Disabled: %s\n", (rsp->data[3] & 0x02) ? "true" : "false");
  332. printf("Power Button Disabled: %s\n", (rsp->data[3] & 0x01) ? "true" : "false");
  333. }
  334. }
  335. return 0;
  336. }
  337. static int
  338. ipmi_chassis_selftest(struct ipmi_intf * intf)
  339. {
  340. struct ipmi_rs * rsp;
  341. struct ipmi_rq req;
  342. memset(&req, 0, sizeof(req));
  343. req.msg.netfn = IPMI_NETFN_APP;
  344. req.msg.cmd = 0x4;
  345. rsp = intf->sendrecv(intf, &req);
  346. if (rsp == NULL) {
  347. lprintf(LOG_ERR, "Error sending Get Self Test command");
  348. return -1;
  349. }
  350. if (rsp->ccode > 0) {
  351. lprintf(LOG_ERR, "Error sending Get Self Test command: %s",
  352. val2str(rsp->ccode, completion_code_vals));
  353. return -1;
  354. }
  355. printf("Self Test Results : ");
  356. switch (rsp->data[0]) {
  357. case 0x55:
  358. printf("passed\n");
  359. break;
  360. case 0x56:
  361. printf("not implemented\n");
  362. break;
  363. case 0x57:
  364. {
  365. int i;
  366. const struct valstr broken_dev_vals[] = {
  367. { 0, "firmware corrupted" },
  368. { 1, "boot block corrupted" },
  369. { 2, "FRU Internal Use Area corrupted" },
  370. { 3, "SDR Repository empty" },
  371. { 4, "IPMB not responding" },
  372. { 5, "cannot access BMC FRU" },
  373. { 6, "cannot access SDR Repository" },
  374. { 7, "cannot access SEL Device" },
  375. { 0xff, NULL },
  376. };
  377. printf("device error\n");
  378. for (i=0; i<8; i++) {
  379. if (rsp->data[1] & (1<<i)) {
  380. printf(" [%s]\n",
  381. val2str(i, broken_dev_vals));
  382. }
  383. }
  384. }
  385. break;
  386. case 0x58:
  387. printf("Fatal hardware error: %02xh\n", rsp->data[1]);
  388. break;
  389. default:
  390. printf("Device-specific failure %02xh:%02xh\n",
  391. rsp->data[0], rsp->data[1]);
  392. break;
  393. }
  394. return 0;
  395. }
  396. static int
  397. ipmi_chassis_set_bootparam(struct ipmi_intf * intf, uint8_t param, uint8_t * data, int len)
  398. {
  399. struct ipmi_rs * rsp;
  400. struct ipmi_rq req;
  401. uint8_t msg_data[16];
  402. memset(msg_data, 0, 16);
  403. msg_data[0] = param & 0x7f;
  404. memcpy(msg_data+1, data, len);
  405. memset(&req, 0, sizeof(req));
  406. req.msg.netfn = IPMI_NETFN_CHASSIS;
  407. req.msg.cmd = 0x8;
  408. req.msg.data = msg_data;
  409. req.msg.data_len = len + 1;
  410. rsp = intf->sendrecv(intf, &req);
  411. if (rsp == NULL) {
  412. lprintf(LOG_ERR, "Error setting Chassis Boot Parameter %d", param);
  413. return -1;
  414. }
  415. if (rsp->ccode > 0) {
  416. if (param != 0) {
  417. lprintf(LOG_ERR, "Set Chassis Boot Parameter %d failed: %s",
  418. param, val2str(rsp->ccode, completion_code_vals));
  419. }
  420. return -1;
  421. }
  422. lprintf(LOG_DEBUG, "Chassis Set Boot Parameter %d to %s", param, buf2str(data, len));
  423. return 0;
  424. }
  425. static int
  426. ipmi_chassis_get_bootparam(struct ipmi_intf * intf, char * arg)
  427. {
  428. struct ipmi_rs * rsp;
  429. struct ipmi_rq req;
  430. uint8_t msg_data[3];
  431. uint8_t param_id = 0;
  432. if (arg == NULL)
  433. return -1;
  434. if (str2uchar(arg, &param_id) != 0) {
  435. lprintf(LOG_ERR, "Invalid parameter '%s' given instead of bootparam.",
  436. arg);
  437. return (-1);
  438. }
  439. memset(msg_data, 0, 3);
  440. msg_data[0] = param_id & 0x7f;
  441. msg_data[1] = 0;
  442. msg_data[2] = 0;
  443. memset(&req, 0, sizeof(req));
  444. req.msg.netfn = IPMI_NETFN_CHASSIS;
  445. req.msg.cmd = 0x9;
  446. req.msg.data = msg_data;
  447. req.msg.data_len = 3;
  448. rsp = intf->sendrecv(intf, &req);
  449. if (rsp == NULL) {
  450. lprintf(LOG_ERR, "Error Getting Chassis Boot Parameter %s", arg);
  451. return -1;
  452. }
  453. if (rsp->ccode > 0) {
  454. lprintf(LOG_ERR, "Get Chassis Boot Parameter %s failed: %s",
  455. arg, val2str(rsp->ccode, completion_code_vals));
  456. return -1;
  457. }
  458. if (verbose > 2)
  459. printbuf(rsp->data, rsp->data_len, "Boot Option");
  460. param_id = 0;
  461. param_id = (rsp->data[1] & 0x7f);
  462. printf("Boot parameter version: %d\n", rsp->data[0]);
  463. printf("Boot parameter %d is %s\n", rsp->data[1] & 0x7f,
  464. (rsp->data[1] & 0x80) ? "invalid/locked" : "valid/unlocked");
  465. printf("Boot parameter data: %s\n", buf2str(rsp->data+2, rsp->data_len - 2));
  466. switch(param_id)
  467. {
  468. case 0:
  469. {
  470. printf(" Set In Progress : ");
  471. switch((rsp->data[2]) &0x03)
  472. {
  473. case 0: printf("set complete\n"); break;
  474. case 1: printf("set in progress\n"); break;
  475. case 2: printf("commit write\n"); break;
  476. default: printf("error, reserved bit\n"); break;
  477. }
  478. }
  479. break;
  480. case 1:
  481. {
  482. printf(" Service Partition Selector : ");
  483. if((rsp->data[2]) == 0)
  484. {
  485. printf("unspecified\n");
  486. }
  487. else
  488. {
  489. printf("%d\n",(rsp->data[2]));
  490. }
  491. }
  492. break;
  493. case 2:
  494. {
  495. printf( " Service Partition Scan :\n");
  496. if((rsp->data[2]&0x03) != 0)
  497. {
  498. if((rsp->data[2]&0x01) == 0x01)
  499. printf(" - Request BIOS to scan\n");
  500. if((rsp->data[2]&0x02) == 0x02)
  501. printf(" - Service Partition Discovered\n");
  502. }
  503. else
  504. {
  505. printf(" No flag set\n");
  506. }
  507. }
  508. break;
  509. case 3:
  510. {
  511. printf( " BMC boot flag valid bit clearing :\n");
  512. if((rsp->data[2]&0x1f) != 0)
  513. {
  514. if((rsp->data[2]&0x10) == 0x10)
  515. printf(" - Don't clear valid bit on reset/power cycle cause by PEF\n");
  516. if((rsp->data[2]&0x08) == 0x08)
  517. printf(" - Don't automatically clear boot flag valid bit on timeout\n");
  518. if((rsp->data[2]&0x04) == 0x04)
  519. printf(" - Don't clear valid bit on reset/power cycle cause by watchdog\n");
  520. if((rsp->data[2]&0x02) == 0x02)
  521. printf(" - Don't clear valid bit on push button reset // soft reset\n");
  522. if((rsp->data[2]&0x01) == 0x01)
  523. printf(" - Don't clear valid bit on power up via power push button or wake event\n");
  524. }
  525. else
  526. {
  527. printf(" No flag set\n");
  528. }
  529. }
  530. break;
  531. case 4:
  532. {
  533. printf( " Boot Info Acknowledge :\n");
  534. if((rsp->data[3]&0x1f) != 0)
  535. {
  536. if((rsp->data[3]&0x10) == 0x10)
  537. printf(" - OEM has handled boot info\n");
  538. if((rsp->data[3]&0x08) == 0x08)
  539. printf(" - SMS has handled boot info\n");
  540. if((rsp->data[3]&0x04) == 0x04)
  541. printf(" - OS // service partition has handled boot info\n");
  542. if((rsp->data[3]&0x02) == 0x02)
  543. printf(" - OS Loader has handled boot info\n");
  544. if((rsp->data[3]&0x01) == 0x01)
  545. printf(" - BIOS/POST has handled boot info\n");
  546. }
  547. else
  548. {
  549. printf(" No flag set\n");
  550. }
  551. }
  552. break;
  553. case 5:
  554. {
  555. printf( " Boot Flags :\n");
  556. if((rsp->data[2]&0x80) == 0x80)
  557. printf(" - Boot Flag Valid\n");
  558. else
  559. printf(" - Boot Flag Invalid\n");
  560. if((rsp->data[2]&0x40) == 0x40)
  561. printf(" - Options apply to all future boots\n");
  562. else
  563. printf(" - Options apply to only next boot\n");
  564. if((rsp->data[2]&0x20) == 0x20)
  565. printf(" - BIOS EFI boot \n");
  566. else
  567. printf(" - BIOS PC Compatible (legacy) boot \n");
  568. if((rsp->data[3]&0x80) == 0x80)
  569. printf(" - CMOS Clear\n");
  570. if((rsp->data[3]&0x40) == 0x40)
  571. printf(" - Lock Keyboard\n");
  572. printf(" - Boot Device Selector : ");
  573. switch( ((rsp->data[3]>>2)&0x0f))
  574. {
  575. case 0: printf("No override\n"); break;
  576. case 1: printf("Force PXE\n"); break;
  577. case 2: printf("Force Boot from default Hard-Drive\n"); break;
  578. case 3: printf("Force Boot from default Hard-Drive, request Safe-Mode\n"); break;
  579. case 4: printf("Force Boot from Diagnostic Partition\n"); break;
  580. case 5: printf("Force Boot from CD/DVD\n"); break;
  581. case 6: printf("Force Boot into BIOS Setup\n"); break;
  582. case 15: printf("Force Boot from Floppy/primary removable media\n"); break;
  583. default: printf("Flag error\n"); break;
  584. }
  585. if((rsp->data[3]&0x02) == 0x02)
  586. printf(" - Screen blank\n");
  587. if((rsp->data[3]&0x01) == 0x01)
  588. printf(" - Lock out Reset buttons\n");
  589. if((rsp->data[4]&0x80) == 0x80)
  590. printf(" - Lock out (power off/sleep request) vi Power Button\n");
  591. printf(" - Console Redirection control : ");
  592. switch( ((rsp->data[4]>>5)&0x03))
  593. {
  594. case 0: printf("System Default\n"); break;
  595. case 1: printf("Request Quiet Display\n"); break;
  596. case 2: printf("Request Verbose Display\n"); break;
  597. default: printf("Flag error\n"); break;
  598. }
  599. if((rsp->data[4]&0x10) == 0x10)
  600. printf(" - Force progress event traps\n");
  601. if((rsp->data[4]&0x08) == 0x08)
  602. printf(" - User password bypass\n");
  603. if((rsp->data[4]&0x04) == 0x04)
  604. printf(" - Lock Out Sleep Button\n");
  605. if((rsp->data[4]&0x02) == 0x02)
  606. printf(" - Lock Out Sleep Button\n");
  607. printf(" - BIOS verbosity : ");
  608. switch( ((rsp->data[4]>>0)&0x03))
  609. {
  610. case 0: printf("Console redirection occurs per BIOS configuration setting (default)\n"); break;
  611. case 1: printf("Suppress (skip) console redirection if enabled\n"); break;
  612. case 2: printf("Request console redirection be enabled\n"); break;
  613. default: printf("Flag error\n"); break;
  614. }
  615. if((rsp->data[5]&0x08) == 0x08)
  616. printf(" - BIOS Shared Mode Override\n");
  617. printf(" - BIOS Mux Control Override : ");
  618. switch( ((rsp->data[5]>>0)&0x07))
  619. {
  620. case 0: printf("BIOS uses recommended setting of the mux at the end of POST\n"); break;
  621. case 1: printf("Requests BIOS to force mux to BMC at conclusion of POST/start of OS boot\n"); break;
  622. case 2: printf("Requests BIOS to force mux to system at conclusion of POST/start of OS boot\n"); break;
  623. default: printf("Flag error\n"); break;
  624. }
  625. }
  626. break;
  627. case 6:
  628. {
  629. unsigned long session_id;
  630. unsigned long timestamp;
  631. char time_buf[40];
  632. time_t out_time;
  633. session_id = ((unsigned long) rsp->data[3]);
  634. session_id |= (((unsigned long) rsp->data[4])<<8);
  635. session_id |= (((unsigned long) rsp->data[5])<<16);
  636. session_id |= (((unsigned long) rsp->data[6])<<24);
  637. timestamp = ((unsigned long) rsp->data[7]);
  638. timestamp |= (((unsigned long) rsp->data[8])<<8);
  639. timestamp |= (((unsigned long) rsp->data[9])<<16);
  640. timestamp |= (((unsigned long) rsp->data[10])<<24);
  641. memset(time_buf, 0, 40);
  642. strftime(
  643. time_buf,
  644. sizeof(time_buf),
  645. "%m/%d/%Y %H:%M:%S", localtime(&out_time)
  646. );
  647. printf(" Boot Initiator Info :\n");
  648. printf(" Channel Number : %d\n", (rsp->data[2] & 0x0f));
  649. printf(" Session Id : %08lXh\n",session_id);
  650. if(timestamp != 0)
  651. {
  652. printf(" Timestamp : %08lXh, %s\n",timestamp,time_buf);
  653. }
  654. else
  655. {
  656. printf(" Timestamp : %08lXh, undefined\n",timestamp);
  657. }
  658. }
  659. break;
  660. case 7:
  661. {
  662. printf(" Selector : %d\n", rsp->data[2] );
  663. printf(" Block Data : %s\n", buf2str(rsp->data+3, rsp->data_len - 2));
  664. }
  665. break;
  666. default:
  667. printf(" Undefined byte\n");
  668. break;
  669. }
  670. return 0;
  671. }
  672. static int
  673. get_bootparam_options(char *optstring,
  674. unsigned char *set_flag, unsigned char *clr_flag)
  675. {
  676. char *token;
  677. char *saveptr = NULL;
  678. int optionError = 0;
  679. *set_flag = 0;
  680. *clr_flag = 0;
  681. static struct {
  682. char *name;
  683. unsigned char value;
  684. char *desc;
  685. } options[] = {
  686. {"PEF", 0x10,
  687. "Clear valid bit on reset/power cycle cause by PEF"},
  688. {"timeout", 0x08,
  689. "Automatically clear boot flag valid bit on timeout"},
  690. {"watchdog", 0x04,
  691. "Clear valid bit on reset/power cycle cause by watchdog"},
  692. {"reset", 0x02,
  693. "Clear valid bit on push button reset/soft reset"},
  694. {"power", 0x01,
  695. "Clear valid bit on power up via power push button or wake event"},
  696. {NULL} /* End marker */
  697. }, *op;
  698. if (strncmp(optstring, "options=", 8) != 0) {
  699. lprintf(LOG_ERR, "No options= keyword found \"%s\"", optstring);
  700. return -1;
  701. }
  702. token = strtok_r(optstring + 8, ",", &saveptr);
  703. while (token != NULL) {
  704. int setbit = 0;
  705. if (strcmp(token, "help") == 0) {
  706. optionError = 1;
  707. break;
  708. }
  709. if (strncmp(token, "no-", 3) == 0) {
  710. setbit = 1;
  711. token += 3;
  712. }
  713. for (op = options; op->name != NULL; ++op) {
  714. if (strncmp(token, op->name, strlen(op->name)) == 0) {
  715. if (setbit) {
  716. *set_flag |= op->value;
  717. } else {
  718. *clr_flag |= op->value;
  719. }
  720. break;
  721. }
  722. }
  723. if (op->name == NULL) {
  724. /* Option not found */
  725. optionError = 1;
  726. if (setbit) {
  727. token -=3;
  728. }
  729. lprintf(LOG_ERR, "Invalid option: %s", token);
  730. }
  731. token = strtok_r(NULL, ",", &saveptr);
  732. }
  733. if (optionError) {
  734. lprintf(LOG_NOTICE, " Legal options are:");
  735. lprintf(LOG_NOTICE, " %-8s: print this message", "help");
  736. for (op = options; op->name != NULL; ++op) {
  737. lprintf(LOG_NOTICE, " %-8s: %s", op->name, op->desc);
  738. }
  739. lprintf(LOG_NOTICE, " Any Option may be prepended with no-"
  740. " to invert sense of operation\n");
  741. return (-1);
  742. }
  743. return (0);
  744. }
  745. static int
  746. ipmi_chassis_get_bootvalid(struct ipmi_intf * intf)
  747. {
  748. struct ipmi_rs * rsp;
  749. struct ipmi_rq req;
  750. uint8_t msg_data[3];
  751. uint8_t param_id = IPMI_CHASSIS_BOOTPARAM_FLAG_VALID;
  752. memset(msg_data, 0, 3);
  753. msg_data[0] = param_id & 0x7f;
  754. msg_data[1] = 0;
  755. msg_data[2] = 0;
  756. memset(&req, 0, sizeof(req));
  757. req.msg.netfn = IPMI_NETFN_CHASSIS;
  758. req.msg.cmd = 0x9;
  759. req.msg.data = msg_data;
  760. req.msg.data_len = 3;
  761. rsp = intf->sendrecv(intf, &req);
  762. if (rsp == NULL) {
  763. lprintf(LOG_ERR,
  764. "Error Getting Chassis Boot Parameter %d", param_id);
  765. return -1;
  766. }
  767. if (rsp->ccode > 0) {
  768. lprintf(LOG_ERR, "Get Chassis Boot Parameter %d failed: %s",
  769. param_id, val2str(rsp->ccode, completion_code_vals));
  770. return -1;
  771. }
  772. if (verbose > 2)
  773. printbuf(rsp->data, rsp->data_len, "Boot Option");
  774. return(rsp->data[2]);
  775. }
  776. static int
  777. ipmi_chassis_set_bootvalid(struct ipmi_intf *intf, uint8_t set_flag, uint8_t clr_flag)
  778. {
  779. int bootvalid;
  780. uint8_t flags[5];
  781. int rc = 0;
  782. int use_progress = 1;
  783. uint8_t param_id = IPMI_CHASSIS_BOOTPARAM_FLAG_VALID;
  784. if (use_progress) {
  785. /* set set-in-progress flag */
  786. memset(flags, 0, 5);
  787. flags[0] = 0x01;
  788. rc = ipmi_chassis_set_bootparam(intf,
  789. IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS, flags, 1);
  790. if (rc < 0)
  791. use_progress = 0;
  792. }
  793. memset(flags, 0, 5);
  794. flags[0] = 0x01;
  795. flags[1] = 0x01;
  796. rc = ipmi_chassis_set_bootparam(intf, IPMI_CHASSIS_BOOTPARAM_INFO_ACK,
  797. flags, 2);
  798. if (rc < 0) {
  799. if (use_progress) {
  800. /* set-in-progress = set-complete */
  801. memset(flags, 0, 5);
  802. ipmi_chassis_set_bootparam(intf,
  803. IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS,
  804. flags, 1);
  805. }
  806. return -1;
  807. }
  808. bootvalid = ipmi_chassis_get_bootvalid(intf);
  809. if (bootvalid < 0) {
  810. if (use_progress) {
  811. /* set-in-progress = set-complete */
  812. memset(flags, 0, 5);
  813. ipmi_chassis_set_bootparam(intf,
  814. IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS,
  815. flags, 1);
  816. }
  817. return -1;
  818. }
  819. flags[0] = (bootvalid & ~clr_flag) | set_flag;
  820. rc = ipmi_chassis_set_bootparam(intf, param_id, flags, 1);
  821. if (rc == 0) {
  822. if (use_progress) {
  823. /* set-in-progress = commit-write */
  824. memset(flags, 0, 5);
  825. flags[0] = 0x02;
  826. ipmi_chassis_set_bootparam(intf,
  827. IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS,
  828. flags, 1);
  829. }
  830. }
  831. if (use_progress) {
  832. /* set-in-progress = set-complete */
  833. memset(flags, 0, 5);
  834. ipmi_chassis_set_bootparam(intf,
  835. IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS,
  836. flags, 1);
  837. }
  838. return rc;
  839. }
  840. static int
  841. ipmi_chassis_set_bootdev(struct ipmi_intf * intf, char * arg, uint8_t *iflags)
  842. {
  843. uint8_t flags[5];
  844. int rc = 0;
  845. int use_progress = 1;
  846. if (use_progress) {
  847. /* set set-in-progress flag */
  848. memset(flags, 0, 5);
  849. flags[0] = 0x01;
  850. rc = ipmi_chassis_set_bootparam(intf,
  851. IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS, flags, 1);
  852. if (rc < 0)
  853. use_progress = 0;
  854. }
  855. memset(flags, 0, 5);
  856. flags[0] = 0x01;
  857. flags[1] = 0x01;
  858. rc = ipmi_chassis_set_bootparam(intf, IPMI_CHASSIS_BOOTPARAM_INFO_ACK,
  859. flags, 2);
  860. if (rc < 0) {
  861. if (use_progress) {
  862. /* set-in-progress = set-complete */
  863. memset(flags, 0, 5);
  864. ipmi_chassis_set_bootparam(intf,
  865. IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS,
  866. flags, 1);
  867. }
  868. return -1;
  869. }
  870. if (iflags == NULL)
  871. memset(flags, 0, 5);
  872. else
  873. memcpy(flags, iflags, sizeof (flags));
  874. if (arg == NULL)
  875. flags[1] |= 0x00;
  876. else if (strncmp(arg, "none", 4) == 0)
  877. flags[1] |= 0x00;
  878. else if (strncmp(arg, "pxe", 3) == 0 ||
  879. strncmp(arg, "force_pxe", 9) == 0)
  880. flags[1] |= 0x04;
  881. else if (strncmp(arg, "disk", 4) == 0 ||
  882. strncmp(arg, "force_disk", 10) == 0)
  883. flags[1] |= 0x08;
  884. else if (strncmp(arg, "safe", 4) == 0 ||
  885. strncmp(arg, "force_safe", 10) == 0)
  886. flags[1] |= 0x0c;
  887. else if (strncmp(arg, "diag", 4) == 0 ||
  888. strncmp(arg, "force_diag", 10) == 0)
  889. flags[1] |= 0x10;
  890. else if (strncmp(arg, "cdrom", 5) == 0 ||
  891. strncmp(arg, "force_cdrom", 11) == 0)
  892. flags[1] |= 0x14;
  893. else if (strncmp(arg, "floppy", 6) == 0 ||
  894. strncmp(arg, "force_floppy", 12) == 0)
  895. flags[1] |= 0x3c;
  896. else if (strncmp(arg, "bios", 4) == 0 ||
  897. strncmp(arg, "force_bios", 10) == 0)
  898. flags[1] |= 0x18;
  899. else {
  900. lprintf(LOG_ERR, "Invalid argument: %s", arg);
  901. if (use_progress) {
  902. /* set-in-progress = set-complete */
  903. memset(flags, 0, 5);
  904. ipmi_chassis_set_bootparam(intf,
  905. IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS,
  906. flags, 1);
  907. }
  908. return -1;
  909. }
  910. /* set flag valid bit */
  911. flags[0] |= 0x80;
  912. rc = ipmi_chassis_set_bootparam(intf, IPMI_CHASSIS_BOOTPARAM_BOOT_FLAGS,
  913. flags, 5);
  914. if (rc == 0) {
  915. if (use_progress) {
  916. /* set-in-progress = commit-write */
  917. memset(flags, 0, 5);
  918. flags[0] = 0x02;
  919. ipmi_chassis_set_bootparam(intf,
  920. IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS,
  921. flags, 1);
  922. }
  923. printf("Set Boot Device to %s\n", arg);
  924. }
  925. if (use_progress) {
  926. /* set-in-progress = set-complete */
  927. memset(flags, 0, 5);
  928. ipmi_chassis_set_bootparam(intf,
  929. IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS,
  930. flags, 1);
  931. }
  932. return rc;
  933. }
  934. static int
  935. ipmi_chassis_power_policy(struct ipmi_intf * intf, uint8_t policy)
  936. {
  937. struct ipmi_rs * rsp;
  938. struct ipmi_rq req;
  939. memset(&req, 0, sizeof(req));
  940. req.msg.netfn = IPMI_NETFN_CHASSIS;
  941. req.msg.cmd = 0x6;
  942. req.msg.data = &policy;
  943. req.msg.data_len = 1;
  944. rsp = intf->sendrecv(intf, &req);
  945. if (rsp == NULL) {
  946. lprintf(LOG_ERR, "Error in Power Restore Policy command");
  947. return -1;
  948. }
  949. if (rsp->ccode > 0) {
  950. lprintf(LOG_ERR, "Power Restore Policy command failed: %s",
  951. val2str(rsp->ccode, completion_code_vals));
  952. return -1;
  953. }
  954. if (policy == IPMI_CHASSIS_POLICY_NO_CHANGE) {
  955. printf("Supported chassis power policy: ");
  956. if (rsp->data[0] & (1<<IPMI_CHASSIS_POLICY_ALWAYS_OFF))
  957. printf("always-off ");
  958. if (rsp->data[0] & (1<<IPMI_CHASSIS_POLICY_ALWAYS_ON))
  959. printf("always-on ");
  960. if (rsp->data[0] & (1<<IPMI_CHASSIS_POLICY_PREVIOUS))
  961. printf("previous");
  962. printf("\n");
  963. }
  964. else {
  965. printf("Set chassis power restore policy to ");
  966. switch (policy) {
  967. case IPMI_CHASSIS_POLICY_ALWAYS_ON:
  968. printf("always-on\n");
  969. break;
  970. case IPMI_CHASSIS_POLICY_ALWAYS_OFF:
  971. printf("always-off\n");
  972. break;
  973. case IPMI_CHASSIS_POLICY_PREVIOUS:
  974. printf("previous\n");
  975. break;
  976. default:
  977. printf("unknown\n");
  978. }
  979. }
  980. return 0;
  981. }
  982. int
  983. ipmi_power_main(struct ipmi_intf * intf, int argc, char ** argv)
  984. {
  985. int rc = 0;
  986. uint8_t ctl = 0;
  987. if ((argc < 1) || (strncmp(argv[0], "help", 4) == 0)) {
  988. lprintf(LOG_NOTICE, "chassis power Commands: status, on, off, cycle, reset, diag, soft");
  989. return 0;
  990. }
  991. if (strncmp(argv[0], "status", 6) == 0) {
  992. rc = ipmi_chassis_print_power_status(intf);
  993. return rc;
  994. }
  995. if ((strncmp(argv[0], "up", 2) == 0) || (strncmp(argv[0], "on", 2) == 0))
  996. ctl = IPMI_CHASSIS_CTL_POWER_UP;
  997. else if ((strncmp(argv[0], "down", 4) == 0) || (strncmp(argv[0], "off", 3) == 0))
  998. ctl = IPMI_CHASSIS_CTL_POWER_DOWN;
  999. else if (strncmp(argv[0], "cycle", 5) == 0)
  1000. ctl = IPMI_CHASSIS_CTL_POWER_CYCLE;
  1001. else if (strncmp(argv[0], "reset", 5) == 0)
  1002. ctl = IPMI_CHASSIS_CTL_HARD_RESET;
  1003. else if (strncmp(argv[0], "diag", 4) == 0)
  1004. ctl = IPMI_CHASSIS_CTL_PULSE_DIAG;
  1005. else if ((strncmp(argv[0], "acpi", 4) == 0) || (strncmp(argv[0], "soft", 4) == 0))
  1006. ctl = IPMI_CHASSIS_CTL_ACPI_SOFT;
  1007. else {
  1008. lprintf(LOG_ERR, "Invalid chassis power command: %s", argv[0]);
  1009. return -1;
  1010. }
  1011. rc = ipmi_chassis_power_control(intf, ctl);
  1012. return rc;
  1013. }
  1014. void
  1015. ipmi_chassis_set_bootflag_help()
  1016. {
  1017. unsigned char set_flag;
  1018. unsigned char clr_flag;
  1019. lprintf(LOG_NOTICE, "bootparam set bootflag <device> [options=...]");
  1020. lprintf(LOG_NOTICE, " Legal devices are:");
  1021. lprintf(LOG_NOTICE, " none : No override");
  1022. lprintf(LOG_NOTICE, " force_pxe : Force PXE boot");
  1023. lprintf(LOG_NOTICE, " force_disk : Force boot from default Hard-drive");
  1024. lprintf(LOG_NOTICE, " force_safe : Force boot from default Hard-drive, request Safe Mode");
  1025. lprintf(LOG_NOTICE, " force_diag : Force boot from Diagnostic Partition");
  1026. lprintf(LOG_NOTICE, " force_cdrom : Force boot from CD/DVD");
  1027. lprintf(LOG_NOTICE, " force_bios : Force boot into BIOS Setup");
  1028. get_bootparam_options("options=help", &set_flag, &clr_flag);
  1029. }
  1030. int
  1031. ipmi_chassis_main(struct ipmi_intf * intf, int argc, char ** argv)
  1032. {
  1033. int rc = 0;
  1034. if ((argc == 0) || (strncmp(argv[0], "help", 4) == 0)) {
  1035. lprintf(LOG_NOTICE, "Chassis Commands: status, power, identify, policy, restart_cause, poh, bootdev, bootparam, selftest");
  1036. }
  1037. else if (strncmp(argv[0], "status", 6) == 0) {
  1038. rc = ipmi_chassis_status(intf);
  1039. }
  1040. else if (strncmp(argv[0], "selftest", 8) == 0) {
  1041. rc = ipmi_chassis_selftest(intf);
  1042. }
  1043. else if (strncmp(argv[0], "power", 5) == 0) {
  1044. uint8_t ctl = 0;
  1045. if ((argc < 2) || (strncmp(argv[1], "help", 4) == 0)) {
  1046. lprintf(LOG_NOTICE, "chassis power Commands: status, on, off, cycle, reset, diag, soft");
  1047. return 0;
  1048. }
  1049. if (strncmp(argv[1], "status", 6) == 0) {
  1050. rc = ipmi_chassis_print_power_status(intf);
  1051. return rc;
  1052. }
  1053. if ((strncmp(argv[1], "up", 2) == 0) || (strncmp(argv[1], "on", 2) == 0))
  1054. ctl = IPMI_CHASSIS_CTL_POWER_UP;
  1055. else if ((strncmp(argv[1], "down", 4) == 0) || (strncmp(argv[1], "off", 3) == 0))
  1056. ctl = IPMI_CHASSIS_CTL_POWER_DOWN;
  1057. else if (strncmp(argv[1], "cycle", 5) == 0)
  1058. ctl = IPMI_CHASSIS_CTL_POWER_CYCLE;
  1059. else if (strncmp(argv[1], "reset", 5) == 0)
  1060. ctl = IPMI_CHASSIS_CTL_HARD_RESET;
  1061. else if (strncmp(argv[1], "diag", 4) == 0)
  1062. ctl = IPMI_CHASSIS_CTL_PULSE_DIAG;
  1063. else if ((strncmp(argv[1], "acpi", 4) == 0) || (strncmp(argv[1], "soft", 4) == 0))
  1064. ctl = IPMI_CHASSIS_CTL_ACPI_SOFT;
  1065. else {
  1066. lprintf(LOG_ERR, "Invalid chassis power command: %s", argv[1]);
  1067. return -1;
  1068. }
  1069. rc = ipmi_chassis_power_control(intf, ctl);
  1070. }
  1071. else if (strncmp(argv[0], "identify", 8) == 0) {
  1072. if (argc < 2) {
  1073. rc = ipmi_chassis_identify(intf, NULL);
  1074. }
  1075. else if (strncmp(argv[1], "help", 4) == 0) {
  1076. lprintf(LOG_NOTICE, "chassis identify <interval>");
  1077. lprintf(LOG_NOTICE, " default is 15 seconds");
  1078. lprintf(LOG_NOTICE, " 0 to turn off");
  1079. lprintf(LOG_NOTICE, " force to turn on indefinitely");
  1080. } else {
  1081. rc = ipmi_chassis_identify(intf, argv[1]);
  1082. }
  1083. }
  1084. else if (strncmp(argv[0], "poh", 3) == 0) {
  1085. rc = ipmi_chassis_poh(intf);
  1086. }
  1087. else if (strncmp(argv[0], "restart_cause", 13) == 0) {
  1088. rc = ipmi_chassis_restart_cause(intf);
  1089. }
  1090. else if (strncmp(argv[0], "policy", 4) == 0) {
  1091. if ((argc < 2) || (strncmp(argv[1], "help", 4) == 0)) {
  1092. lprintf(LOG_NOTICE, "chassis policy <state>");
  1093. lprintf(LOG_NOTICE, " list : return supported policies");
  1094. lprintf(LOG_NOTICE, " always-on : turn on when power is restored");
  1095. lprintf(LOG_NOTICE, " previous : return to previous state when power is restored");
  1096. lprintf(LOG_NOTICE, " always-off : stay off after power is restored");
  1097. } else {
  1098. uint8_t ctl;
  1099. if (strncmp(argv[1], "list", 4) == 0)
  1100. ctl = IPMI_CHASSIS_POLICY_NO_CHANGE;
  1101. else if (strncmp(argv[1], "always-on", 9) == 0)
  1102. ctl = IPMI_CHASSIS_POLICY_ALWAYS_ON;
  1103. else if (strncmp(argv[1], "previous", 8) == 0)
  1104. ctl = IPMI_CHASSIS_POLICY_PREVIOUS;
  1105. else if (strncmp(argv[1], "always-off", 10) == 0)
  1106. ctl = IPMI_CHASSIS_POLICY_ALWAYS_OFF;
  1107. else {
  1108. lprintf(LOG_ERR, "Invalid chassis policy: %s", argv[1]);
  1109. return -1;
  1110. }
  1111. rc = ipmi_chassis_power_policy(intf, ctl);
  1112. }
  1113. }
  1114. else if (strncmp(argv[0], "bootparam", 9) == 0) {
  1115. if ((argc < 3) || (strncmp(argv[1], "help", 4) == 0)) {
  1116. lprintf(LOG_NOTICE, "bootparam get <param #>");
  1117. ipmi_chassis_set_bootflag_help();
  1118. }
  1119. else {
  1120. if (strncmp(argv[1], "get", 3) == 0) {
  1121. rc = ipmi_chassis_get_bootparam(intf, argv[2]);
  1122. }
  1123. else if (strncmp(argv[1], "set", 3) == 0) {
  1124. unsigned char set_flag=0;
  1125. unsigned char clr_flag=0;
  1126. if (strncmp(argv[2], "help", 4) == 0 ||
  1127. argc < 4 || (argc >= 4 &&
  1128. strncmp(argv[2], "bootflag", 8) != 0)) {
  1129. ipmi_chassis_set_bootflag_help();
  1130. } else {
  1131. if (argc == 5) {
  1132. get_bootparam_options(argv[4], &set_flag, &clr_flag);
  1133. }
  1134. rc = ipmi_chassis_set_bootdev(intf, argv[3], NULL);
  1135. if (argc == 5 && (set_flag != 0 || clr_flag != 0)) {
  1136. rc = ipmi_chassis_set_bootvalid(intf, set_flag, clr_flag);
  1137. }
  1138. }
  1139. }
  1140. else
  1141. lprintf(LOG_NOTICE, "bootparam get|set <option> [value ...]");
  1142. }
  1143. }
  1144. else if (strncmp(argv[0], "bootdev", 7) == 0) {
  1145. if ((argc < 2) || (strncmp(argv[1], "help", 4) == 0)) {
  1146. lprintf(LOG_NOTICE, "bootdev <device> [clear-cmos=yes|no]");
  1147. lprintf(LOG_NOTICE, "bootdev <device> [options=help,...]");
  1148. lprintf(LOG_NOTICE, " none : Do not change boot device order");
  1149. lprintf(LOG_NOTICE, " pxe : Force PXE boot");
  1150. lprintf(LOG_NOTICE, " disk : Force boot from default Hard-drive");
  1151. lprintf(LOG_NOTICE, " safe : Force boot from default Hard-drive, request Safe Mode");
  1152. lprintf(LOG_NOTICE, " diag : Force boot from Diagnostic Partition");
  1153. lprintf(LOG_NOTICE, " cdrom : Force boot from CD/DVD");
  1154. lprintf(LOG_NOTICE, " bios : Force boot into BIOS Setup");
  1155. lprintf(LOG_NOTICE, " floppy: Force boot from Floppy/primary removable media");
  1156. } else {
  1157. if (argc < 3)
  1158. rc = ipmi_chassis_set_bootdev(intf, argv[1], NULL);
  1159. else if (strncmp(argv[2], "clear-cmos=", 11) == 0) {
  1160. if (strncmp(argv[2]+11, "yes", 3) == 0) {
  1161. uint8_t flags[5] = {0, (1<<7), 0, 0, 0};
  1162. rc = ipmi_chassis_set_bootdev(intf, argv[1], flags);
  1163. } else
  1164. rc = ipmi_chassis_set_bootdev(intf, argv[1], NULL);
  1165. }
  1166. else if (strncmp(argv[2], "options=", 8) == 0) {
  1167. char *token;
  1168. char *saveptr = NULL;
  1169. int optionError = 0;
  1170. unsigned char flags[5];
  1171. static struct {
  1172. char *name;
  1173. int i;
  1174. unsigned char mask;
  1175. unsigned char value;
  1176. char *desc;
  1177. } options[] = {
  1178. /* data 1 */
  1179. {"valid", 0, (1<<7), (1<<7),
  1180. "Boot flags valid"},
  1181. {"persistent", 0, (1<<6), (1<<6),
  1182. "Changes are persistent for all future boots"},
  1183. {"efiboot", 0, (1<<5), (1<<5),
  1184. "Extensible Firmware Interface Boot (EFI)"},
  1185. /* data 2 */
  1186. {"clear-cmos", 1, (1<<7), (1<<7),
  1187. "CMOS clear"},
  1188. {"lockkbd", 1, (1<<6), (1<<6),
  1189. "Lock Keyboard"},
  1190. /* data2[5:2] is parsed elsewhere */
  1191. {"screenblank", 1, (1<<1), (1<<1),
  1192. "Screen Blank"},
  1193. {"lockoutreset", 1, (1<<0), (1<<0),
  1194. "Lock out Resetbuttons"},
  1195. /* data 3 */
  1196. {"lockout_power", 2, (1<<7), (1<<7),
  1197. "Lock out (power off/sleep request) via Power Button"},
  1198. {"verbose=default", 2, (3<<5), (0<<5),
  1199. "Request quiet BIOS display"},
  1200. {"verbose=no", 2, (3<<5), (1<<5),
  1201. "Request quiet BIOS display"},
  1202. {"verbose=yes", 2, (3<<5), (2<<5),
  1203. "Request verbose BIOS display"},
  1204. {"force_pet", 2, (1<<4), (1<<4),
  1205. "Force progress event traps"},
  1206. {"upw_bypass", 2, (1<<3), (1<<3),
  1207. "User password bypass"},
  1208. {"lockout_sleep", 2, (1<<2), (1<<2),
  1209. "Log Out Sleep Button"},
  1210. {"cons_redirect=default", 2, (3<<0), (0<<0),
  1211. "Console redirection occurs per BIOS configuration setting"},
  1212. {"cons_redirect=skip", 2, (3<<0), (1<<0),
  1213. "Suppress (skip) console redirection if enabled"},
  1214. {"cons_redirect=enable", 2, (3<<0), (2<<0),
  1215. "Suppress (skip) console redirection if enabled"},
  1216. /* data 4 */
  1217. /* data4[7:4] reserved */
  1218. /* data4[3] BIOS Shared Mode Override, not implemented here */
  1219. /* data4[2:0] BIOS Mux Control Override, not implemented here */
  1220. /* data5 reserved */
  1221. {NULL} /* End marker */
  1222. }, *op;
  1223. memset(&flags[0], 0, sizeof(flags));
  1224. token = strtok_r(argv[2] + 8, ",", &saveptr);
  1225. while (token != NULL) {
  1226. if (strcmp(token, "help") == 0) {
  1227. optionError = 1;
  1228. break;
  1229. }
  1230. for (op = options; op->name != NULL; ++op) {
  1231. if (strcmp(token, op->name) == 0) {
  1232. flags[op->i] &= op->mask;
  1233. flags[op->i] |= op->value;
  1234. break;
  1235. }
  1236. }
  1237. if (op->name == NULL) {
  1238. /* Option not found */
  1239. optionError = 1;
  1240. lprintf(LOG_ERR, "Invalid option: %s", token);
  1241. }
  1242. token = strtok_r(NULL, ",", &saveptr);
  1243. }
  1244. if (optionError) {
  1245. lprintf(LOG_NOTICE, "Legal options settings are:");
  1246. lprintf(LOG_NOTICE, "\thelp:\tprint this message");
  1247. for (op = options; op->name != NULL; ++op) {
  1248. lprintf(LOG_NOTICE, "\t%s:\t%s", op->name, op->desc);
  1249. }
  1250. return (-1);
  1251. }
  1252. rc = ipmi_chassis_set_bootdev(intf, argv[1], flags);
  1253. }
  1254. else
  1255. rc = ipmi_chassis_set_bootdev(intf, argv[1], NULL);
  1256. }
  1257. }
  1258. else {
  1259. lprintf(LOG_ERR, "Invalid chassis command: %s", argv[0]);
  1260. return -1;
  1261. }
  1262. return rc;
  1263. }