xref: /openbmc/ipmitool/lib/ipmi_sunoem.c (revision 2d79e69f)
1c18ec02fSPetter Reinholdtsen /*
2*a88db0d1SZdenek Styblik  * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
3c18ec02fSPetter Reinholdtsen  *
4c18ec02fSPetter Reinholdtsen  * Redistribution and use in source and binary forms, with or without
5c18ec02fSPetter Reinholdtsen  * modification, are permitted provided that the following conditions
6c18ec02fSPetter Reinholdtsen  * are met:
7c18ec02fSPetter Reinholdtsen  *
8c18ec02fSPetter Reinholdtsen  * Redistribution of source code must retain the above copyright
9c18ec02fSPetter Reinholdtsen  * notice, this list of conditions and the following disclaimer.
10c18ec02fSPetter Reinholdtsen  *
11c18ec02fSPetter Reinholdtsen  * Redistribution in binary form must reproduce the above copyright
12c18ec02fSPetter Reinholdtsen  * notice, this list of conditions and the following disclaimer in the
13c18ec02fSPetter Reinholdtsen  * documentation and/or other materials provided with the distribution.
14c18ec02fSPetter Reinholdtsen  *
15c18ec02fSPetter Reinholdtsen  * Neither the name of Sun Microsystems, Inc. or the names of
16c18ec02fSPetter Reinholdtsen  * contributors may be used to endorse or promote products derived
17c18ec02fSPetter Reinholdtsen  * from this software without specific prior written permission.
18c18ec02fSPetter Reinholdtsen  *
19c18ec02fSPetter Reinholdtsen  * This software is provided "AS IS," without a warranty of any kind.
20c18ec02fSPetter Reinholdtsen  * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
21c18ec02fSPetter Reinholdtsen  * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
22c18ec02fSPetter Reinholdtsen  * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
23c18ec02fSPetter Reinholdtsen  * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
24c18ec02fSPetter Reinholdtsen  * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
25c18ec02fSPetter Reinholdtsen  * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.  IN NO EVENT WILL
26c18ec02fSPetter Reinholdtsen  * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
27c18ec02fSPetter Reinholdtsen  * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
28c18ec02fSPetter Reinholdtsen  * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
29c18ec02fSPetter Reinholdtsen  * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
30c18ec02fSPetter Reinholdtsen  * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
31c18ec02fSPetter Reinholdtsen  */
32c18ec02fSPetter Reinholdtsen 
33c18ec02fSPetter Reinholdtsen #include <stdlib.h>
34c18ec02fSPetter Reinholdtsen #include <stdio.h>
35c18ec02fSPetter Reinholdtsen #include <string.h>
36*a88db0d1SZdenek Styblik #include <strings.h>
37c18ec02fSPetter Reinholdtsen #include <sys/types.h>
38c18ec02fSPetter Reinholdtsen #include <sys/socket.h>
39*a88db0d1SZdenek Styblik #include <sys/time.h>
40c18ec02fSPetter Reinholdtsen #include <netinet/in.h>
41c18ec02fSPetter Reinholdtsen #include <arpa/inet.h>
42c18ec02fSPetter Reinholdtsen #include <errno.h>
43*a88db0d1SZdenek Styblik #include <time.h>
44c18ec02fSPetter Reinholdtsen #include <unistd.h>
45c18ec02fSPetter Reinholdtsen #include <signal.h>
46c18ec02fSPetter Reinholdtsen #include <ctype.h>
47*a88db0d1SZdenek Styblik #include <sys/time.h>
48*a88db0d1SZdenek Styblik #include <limits.h>
49*a88db0d1SZdenek Styblik #include <fcntl.h>
50*a88db0d1SZdenek Styblik 
51*a88db0d1SZdenek Styblik #include <termios.h>
52c18ec02fSPetter Reinholdtsen 
53c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi.h>
54c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_intf.h>
55c18ec02fSPetter Reinholdtsen #include <ipmitool/helper.h>
56c18ec02fSPetter Reinholdtsen #include <ipmitool/log.h>
57c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_sel.h>
58c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_sdr.h>
59c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_strings.h>
60c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_channel.h>
61c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_sunoem.h>
62c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_raw.h>
63c18ec02fSPetter Reinholdtsen 
64c18ec02fSPetter Reinholdtsen static const struct valstr sunoem_led_type_vals[] = {
65c18ec02fSPetter Reinholdtsen 	{ 0, "OK2RM" },
66c18ec02fSPetter Reinholdtsen 	{ 1, "SERVICE" },
67c18ec02fSPetter Reinholdtsen 	{ 2, "ACT" },
68c18ec02fSPetter Reinholdtsen 	{ 3, "LOCATE" },
69c18ec02fSPetter Reinholdtsen 	{ 0xFF, NULL },
70c18ec02fSPetter Reinholdtsen };
71c18ec02fSPetter Reinholdtsen 
72c18ec02fSPetter Reinholdtsen static const struct valstr sunoem_led_mode_vals[] = {
73c18ec02fSPetter Reinholdtsen 	{ 0, "OFF" },
74c18ec02fSPetter Reinholdtsen 	{ 1, "ON" },
75c18ec02fSPetter Reinholdtsen 	{ 2, "STANDBY" },
76c18ec02fSPetter Reinholdtsen 	{ 3, "SLOW" },
77c18ec02fSPetter Reinholdtsen 	{ 4, "FAST" },
78c18ec02fSPetter Reinholdtsen 	{ 0xFF, NULL },
79c18ec02fSPetter Reinholdtsen };
80*a88db0d1SZdenek Styblik 
81c18ec02fSPetter Reinholdtsen static const struct valstr sunoem_led_mode_optvals[] = {
82c18ec02fSPetter Reinholdtsen 	{ 0, "STEADY_OFF" },
83c18ec02fSPetter Reinholdtsen 	{ 1, "STEADY_ON" },
84c18ec02fSPetter Reinholdtsen 	{ 2, "STANDBY_BLINK" },
85c18ec02fSPetter Reinholdtsen 	{ 3, "SLOW_BLINK" },
86c18ec02fSPetter Reinholdtsen 	{ 4, "FAST_BLINK" },
87c18ec02fSPetter Reinholdtsen 	{ 0xFF, NULL },
88c18ec02fSPetter Reinholdtsen };
89c18ec02fSPetter Reinholdtsen 
90*a88db0d1SZdenek Styblik #define SUNOEM_SUCCESS 1
91*a88db0d1SZdenek Styblik 
92*a88db0d1SZdenek Styblik #define IPMI_SUNOEM_GETFILE_VERSION {3,2,0,0}
93*a88db0d1SZdenek Styblik #define IPMI_SUNOEM_GETBEHAVIOR_VERSION {3,2,0,0}
94*a88db0d1SZdenek Styblik 
95*a88db0d1SZdenek Styblik /*
96*a88db0d1SZdenek Styblik  * PRINT_NORMAL: print out the LED value as normal
97*a88db0d1SZdenek Styblik  * PRINT_ERROR: print out "na" for the LED value
98*a88db0d1SZdenek Styblik  */
99*a88db0d1SZdenek Styblik typedef enum
100*a88db0d1SZdenek Styblik {
101*a88db0d1SZdenek Styblik 	PRINT_NORMAL = 0, PRINT_ERROR
102*a88db0d1SZdenek Styblik } print_status_t;
103*a88db0d1SZdenek Styblik 
104*a88db0d1SZdenek Styblik int ret_get = 0;
105*a88db0d1SZdenek Styblik int ret_set = 0;
106c18ec02fSPetter Reinholdtsen 
107c18ec02fSPetter Reinholdtsen static void
ipmi_sunoem_usage(void)108c18ec02fSPetter Reinholdtsen ipmi_sunoem_usage(void)
109c18ec02fSPetter Reinholdtsen {
110*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "Usage: sunoem <command> [option...]");
111c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "");
112*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "Commands:");
113*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, " - cli [<command string> ...]");
114*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "      Execute SP CLI commands.");
115c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "");
116*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, " - led get [<sensor_id>] [ledtype]");
117*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "      - Read status of LED found in Generic Device Locator.");
118c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "");
119*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, " - led set <sensor_id> <led_mode> [led_type]");
120*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "      - Set mode of LED found in Generic Device Locator.");
121*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "      - You can pass 'all' as the <senso_rid> to change the LED mode of all sensors.");
122*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "      - Use 'sdr list generic' command to get list of Generic");
123*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "      - Devices that are controllable LEDs.");
124c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "");
125*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "      - Required SIS LED Mode:");
126c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "          OFF          Off");
127c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "          ON           Steady On");
128c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "          STANDBY      100ms on 2900ms off blink rate");
129c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "          SLOW         1HZ blink rate");
130c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "          FAST         4HZ blink rate");
131c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "");
132*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "      - Optional SIS LED Type:");
133c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "          OK2RM        OK to Remove");
134c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "          SERVICE      Service Required");
135c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "          ACT          Activity");
136c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "          LOCATE       Locate");
137c18ec02fSPetter Reinholdtsen 	lprintf(LOG_NOTICE, "");
138*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, " - nacname <ipmi_nac_name>");
139*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "      - Returns the full nac name");
140*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "");
141*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, " - ping NUMBER <q>");
142*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "      - Send and Receive NUMBER (64 Byte) packets.");
143*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "");
144*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "      - q - Quiet. Displays output at start and end");
145*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "");
146*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, " - getval <target_name>");
147*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "      - Returns the ILOM property value");
148*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "");
149*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, " - setval <property name> <property value> <timeout>");
150*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "      - Sets the ILOM property value");
151*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "      - If timeout is not specified, the default is 5 sec.");
152*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "      - NOTE: must be executed locally on host, not remotely over LAN!");
153*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "");
154*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, " - sshkey del <user_id>");
155*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "      - Delete ssh key for user id from authorized_keys,");
156*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "      - view users with 'user list' command.");
157*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "");
158*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, " - sshkey set <user_id> <id_rsa.pub>");
159*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "      - Set ssh key for a userid into authorized_keys,");
160*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "      - view users with 'user list' command.");
161*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "");
162*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, " - version");
163*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "      - Display the software version");
164*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "");
165*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, " - nacname <ipmi_nac_name>");
166*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "      - Returns the full nac name");
167*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "");
168*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, " - getfile <file_string_id> <destination_file_name>");
169*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "      - Copy file <file_string_id> to <destination_file_name>");
170*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "");
171*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "      - File string ids:");
172*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "          SSH_PUBKEYS");
173*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "          DIAG_PASSED");
174*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "          DIAG_FAILED");
175*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "          DIAG_END_TIME");
176*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "          DIAG_INVENTORY");
177*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "          DIAG_TEST_LOG");
178*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "          DIAG_START_TIME");
179*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "          DIAG_UEFI_LOG");
180*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "          DIAG_TEST_LOG");
181*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "          DIAG_LAST_LOG");
182*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "          DIAG_LAST_CMD");
183*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "");
184*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, " - getbehavior <behavior_string_id>");
185*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "      - Test if ILOM behavior is enabled");
186*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "");
187*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "      - Behavior string ids:");
188*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "          SUPPORTS_SIGNED_PACKAGES");
189*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "          REQUIRES_SIGNED_PACKAGES");
190*a88db0d1SZdenek Styblik 	lprintf(LOG_NOTICE, "");
191c18ec02fSPetter Reinholdtsen }
192c18ec02fSPetter Reinholdtsen 
193*a88db0d1SZdenek Styblik #define SUNOEM_FAN_MODE_AUTO    0x00
194*a88db0d1SZdenek Styblik #define SUNOEM_FAN_MODE_MANUAL  0x01
195c18ec02fSPetter Reinholdtsen 
196c18ec02fSPetter Reinholdtsen static void
__sdr_list_empty(struct sdr_record_list * head)197c18ec02fSPetter Reinholdtsen __sdr_list_empty(struct sdr_record_list * head)
198c18ec02fSPetter Reinholdtsen {
199c18ec02fSPetter Reinholdtsen 	struct sdr_record_list * e, *f;
200c18ec02fSPetter Reinholdtsen 	for (e = head; e != NULL; e = f) {
201c18ec02fSPetter Reinholdtsen 		f = e->next;
202c18ec02fSPetter Reinholdtsen 		free(e);
203c18ec02fSPetter Reinholdtsen 	}
204c18ec02fSPetter Reinholdtsen 	head = NULL;
205c18ec02fSPetter Reinholdtsen }
206c18ec02fSPetter Reinholdtsen 
207*a88db0d1SZdenek Styblik /*
208*a88db0d1SZdenek Styblik  *  led_print
209*a88db0d1SZdenek Styblik  *  Print out the led name and the state, if stat is PRINT_NORMAL.
210*a88db0d1SZdenek Styblik  *  Otherwise, print out the led name and "na".
211*a88db0d1SZdenek Styblik  *  The state parameter is not referenced if stat is not PRINT_NORMAL.
212*a88db0d1SZdenek Styblik  */
213c18ec02fSPetter Reinholdtsen static void
led_print(const char * name,print_status_t stat,uint8_t state)214*a88db0d1SZdenek Styblik led_print(const char * name, print_status_t stat, uint8_t state)
215c18ec02fSPetter Reinholdtsen {
216*a88db0d1SZdenek Styblik 	const char *theValue;
217*a88db0d1SZdenek Styblik 
218*a88db0d1SZdenek Styblik 	if (stat == PRINT_NORMAL) {
219*a88db0d1SZdenek Styblik 		theValue = val2str(state, sunoem_led_mode_vals);
220*a88db0d1SZdenek Styblik 	} else {
221*a88db0d1SZdenek Styblik 		theValue = "na";
222c18ec02fSPetter Reinholdtsen 	}
223c18ec02fSPetter Reinholdtsen 
224*a88db0d1SZdenek Styblik 	if (csv_output) {
225*a88db0d1SZdenek Styblik 		printf("%s,%s\n", name, theValue);
226*a88db0d1SZdenek Styblik 	} else {
227*a88db0d1SZdenek Styblik 		printf("%-16s | %s\n", name, theValue);
228*a88db0d1SZdenek Styblik 	}
229*a88db0d1SZdenek Styblik }
230*a88db0d1SZdenek Styblik 
231*a88db0d1SZdenek Styblik #define CC_NORMAL                  0x00
232*a88db0d1SZdenek Styblik #define CC_PARAM_OUT_OF_RANGE      0xc9
233*a88db0d1SZdenek Styblik #define CC_DEST_UNAVAILABLE        0xd3
234*a88db0d1SZdenek Styblik #define CC_UNSPECIFIED_ERR         0xff
235*a88db0d1SZdenek Styblik #define CC_INSUFFICIENT_PRIVILEGE  0xd4
236*a88db0d1SZdenek Styblik #define CC_INV_CMD                 0xc1
237*a88db0d1SZdenek Styblik #define CC_INV_DATA_FIELD          0xcc
238*a88db0d1SZdenek Styblik 
239*a88db0d1SZdenek Styblik /*
240*a88db0d1SZdenek Styblik  * sunoem_led_get(....)
241*a88db0d1SZdenek Styblik  *
242*a88db0d1SZdenek Styblik  * OUTPUT:
243*a88db0d1SZdenek Styblik  *   SUNOEM_EC_INVALID_ARG         if dev is NULL,
244*a88db0d1SZdenek Styblik  *   SUNOEM_EC_BMC_NOT_RESPONDING  if no reply is obtained from BMC,
245*a88db0d1SZdenek Styblik  *   SUNOEM_EC_BMC_CCODE_NONZERO   if completion code is nonzero,
246*a88db0d1SZdenek Styblik  *   SUNOEM_EC_SUCCESS             otherwise.
247*a88db0d1SZdenek Styblik  */
248*a88db0d1SZdenek Styblik static sunoem_ec_t
sunoem_led_get(struct ipmi_intf * intf,struct sdr_record_generic_locator * dev,int ledtype,struct ipmi_rs ** loc_rsp)249*a88db0d1SZdenek Styblik sunoem_led_get(struct ipmi_intf * intf,	struct sdr_record_generic_locator * dev,
250*a88db0d1SZdenek Styblik 		int ledtype, struct ipmi_rs **loc_rsp)
251c18ec02fSPetter Reinholdtsen {
252c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
253c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
254c18ec02fSPetter Reinholdtsen 	uint8_t rqdata[7];
255*a88db0d1SZdenek Styblik 	int rqdata_len;
256c18ec02fSPetter Reinholdtsen 
257*a88db0d1SZdenek Styblik 	if (dev == NULL) {
258*a88db0d1SZdenek Styblik 		*loc_rsp = NULL;
259*a88db0d1SZdenek Styblik 		return (SUNOEM_EC_INVALID_ARG);
260*a88db0d1SZdenek Styblik 	}
261c18ec02fSPetter Reinholdtsen 
262c18ec02fSPetter Reinholdtsen 	rqdata[0] = dev->dev_slave_addr;
263c18ec02fSPetter Reinholdtsen 	if (ledtype == 0xFF)
264c18ec02fSPetter Reinholdtsen 		rqdata[1] = dev->oem;
265c18ec02fSPetter Reinholdtsen 	else
266c18ec02fSPetter Reinholdtsen 		rqdata[1] = ledtype;
267*a88db0d1SZdenek Styblik 
268c18ec02fSPetter Reinholdtsen 	rqdata[2] = dev->dev_access_addr;
269c18ec02fSPetter Reinholdtsen 	rqdata[3] = dev->oem;
270c18ec02fSPetter Reinholdtsen 	rqdata[4] = dev->entity.id;
271c18ec02fSPetter Reinholdtsen 	rqdata[5] = dev->entity.instance;
272c18ec02fSPetter Reinholdtsen 	rqdata[6] = 0;
273c18ec02fSPetter Reinholdtsen 	rqdata_len = 7;
274c18ec02fSPetter Reinholdtsen 
275c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_SUNOEM;
276c18ec02fSPetter Reinholdtsen 	req.msg.cmd = IPMI_SUNOEM_LED_GET;
277c18ec02fSPetter Reinholdtsen 	req.msg.lun = dev->lun;
278c18ec02fSPetter Reinholdtsen 	req.msg.data = rqdata;
279c18ec02fSPetter Reinholdtsen 	req.msg.data_len = rqdata_len;
280c18ec02fSPetter Reinholdtsen 
281c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
282*a88db0d1SZdenek Styblik 	/*
283*a88db0d1SZdenek Styblik 	 * Just return NULL if there was
284*a88db0d1SZdenek Styblik 	 * an error.
285*a88db0d1SZdenek Styblik 	 */
286c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
287*a88db0d1SZdenek Styblik 		*loc_rsp = NULL;
288*a88db0d1SZdenek Styblik 		return (SUNOEM_EC_BMC_NOT_RESPONDING);
289*a88db0d1SZdenek Styblik 	} else if (rsp->ccode > 0) {
290*a88db0d1SZdenek Styblik 		*loc_rsp = rsp;
291*a88db0d1SZdenek Styblik 		return (SUNOEM_EC_BMC_CCODE_NONZERO);
292*a88db0d1SZdenek Styblik 	} else {
293*a88db0d1SZdenek Styblik 		*loc_rsp = rsp;
294*a88db0d1SZdenek Styblik 		return (SUNOEM_EC_SUCCESS);
295c18ec02fSPetter Reinholdtsen 	}
296c18ec02fSPetter Reinholdtsen }
297c18ec02fSPetter Reinholdtsen 
298*a88db0d1SZdenek Styblik static struct ipmi_rs *
sunoem_led_set(struct ipmi_intf * intf,struct sdr_record_generic_locator * dev,int ledtype,int ledmode)299*a88db0d1SZdenek Styblik sunoem_led_set(struct ipmi_intf * intf, struct sdr_record_generic_locator * dev,
300c18ec02fSPetter Reinholdtsen 		int ledtype, int ledmode)
301c18ec02fSPetter Reinholdtsen {
302c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
303c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
304c18ec02fSPetter Reinholdtsen 	uint8_t rqdata[9];
305*a88db0d1SZdenek Styblik 	int rqdata_len;
306c18ec02fSPetter Reinholdtsen 
307c18ec02fSPetter Reinholdtsen 	if (dev == NULL)
308c18ec02fSPetter Reinholdtsen 		return NULL;
309c18ec02fSPetter Reinholdtsen 
310c18ec02fSPetter Reinholdtsen 	rqdata[0] = dev->dev_slave_addr;
311*a88db0d1SZdenek Styblik 
312c18ec02fSPetter Reinholdtsen 	if (ledtype == 0xFF)
313c18ec02fSPetter Reinholdtsen 		rqdata[1] = dev->oem;
314c18ec02fSPetter Reinholdtsen 	else
315c18ec02fSPetter Reinholdtsen 		rqdata[1] = ledtype;
316*a88db0d1SZdenek Styblik 
317c18ec02fSPetter Reinholdtsen 	rqdata[2] = dev->dev_access_addr;
318c18ec02fSPetter Reinholdtsen 	rqdata[3] = dev->oem;
319c18ec02fSPetter Reinholdtsen 	rqdata[4] = ledmode;
320c18ec02fSPetter Reinholdtsen 	rqdata[5] = dev->entity.id;
321c18ec02fSPetter Reinholdtsen 	rqdata[6] = dev->entity.instance;
322c18ec02fSPetter Reinholdtsen 	rqdata[7] = 0;
323c18ec02fSPetter Reinholdtsen 	rqdata[8] = 0;
324c18ec02fSPetter Reinholdtsen 	rqdata_len = 9;
325c18ec02fSPetter Reinholdtsen 
326c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_SUNOEM;
327c18ec02fSPetter Reinholdtsen 	req.msg.cmd = IPMI_SUNOEM_LED_SET;
328c18ec02fSPetter Reinholdtsen 	req.msg.lun = dev->lun;
329c18ec02fSPetter Reinholdtsen 	req.msg.data = rqdata;
330c18ec02fSPetter Reinholdtsen 	req.msg.data_len = rqdata_len;
331c18ec02fSPetter Reinholdtsen 
332c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
333c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
334*a88db0d1SZdenek Styblik 		lprintf(LOG_ERR, "Sun OEM Set LED command failed.");
335c18ec02fSPetter Reinholdtsen 		return NULL;
336*a88db0d1SZdenek Styblik 	} else if (rsp->ccode > 0) {
337c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Sun OEM Set LED command failed: %s",
338c18ec02fSPetter Reinholdtsen 				val2str(rsp->ccode, completion_code_vals));
339c18ec02fSPetter Reinholdtsen 		return NULL;
340c18ec02fSPetter Reinholdtsen 	}
341c18ec02fSPetter Reinholdtsen 
342*a88db0d1SZdenek Styblik 	return (rsp);
343c18ec02fSPetter Reinholdtsen }
344c18ec02fSPetter Reinholdtsen 
345c18ec02fSPetter Reinholdtsen static void
sunoem_led_get_byentity(struct ipmi_intf * intf,uint8_t entity_id,uint8_t entity_inst,int ledtype)346c18ec02fSPetter Reinholdtsen sunoem_led_get_byentity(struct ipmi_intf * intf, uint8_t entity_id,
347c18ec02fSPetter Reinholdtsen 		uint8_t entity_inst, int ledtype)
348c18ec02fSPetter Reinholdtsen {
349c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
350c18ec02fSPetter Reinholdtsen 	struct sdr_record_list *elist, *e;
351c18ec02fSPetter Reinholdtsen 	struct entity_id entity;
352*a88db0d1SZdenek Styblik 	sunoem_ec_t res;
353c18ec02fSPetter Reinholdtsen 
354c18ec02fSPetter Reinholdtsen 	if (entity_id == 0)
355c18ec02fSPetter Reinholdtsen 		return;
356c18ec02fSPetter Reinholdtsen 
357c18ec02fSPetter Reinholdtsen 	/* lookup sdrs with this entity */
358c18ec02fSPetter Reinholdtsen 	memset(&entity, 0, sizeof(struct entity_id));
359c18ec02fSPetter Reinholdtsen 	entity.id = entity_id;
360c18ec02fSPetter Reinholdtsen 	entity.instance = entity_inst;
361c18ec02fSPetter Reinholdtsen 
362c18ec02fSPetter Reinholdtsen 	elist = ipmi_sdr_find_sdr_byentity(intf, &entity);
363c18ec02fSPetter Reinholdtsen 
364*a88db0d1SZdenek Styblik 	if (elist == NULL)
365*a88db0d1SZdenek Styblik 		ret_get = -1;
366*a88db0d1SZdenek Styblik 
367*a88db0d1SZdenek Styblik 	/* for each generic sensor get its led state */
368c18ec02fSPetter Reinholdtsen 	for (e = elist; e != NULL; e = e->next) {
369c18ec02fSPetter Reinholdtsen 		if (e->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR)
370c18ec02fSPetter Reinholdtsen 			continue;
371c18ec02fSPetter Reinholdtsen 
372*a88db0d1SZdenek Styblik 		res = sunoem_led_get(intf, e->record.genloc, ledtype, &rsp);
373*a88db0d1SZdenek Styblik 
374*a88db0d1SZdenek Styblik 		if (res == SUNOEM_EC_SUCCESS && rsp && rsp->data_len == 1) {
375*a88db0d1SZdenek Styblik 			led_print((const char *) e->record.genloc->id_string, PRINT_NORMAL,
376*a88db0d1SZdenek Styblik 					rsp->data[0]);
377*a88db0d1SZdenek Styblik 		} else {
378*a88db0d1SZdenek Styblik 			led_print((const char *) e->record.genloc->id_string, PRINT_ERROR,
379*a88db0d1SZdenek Styblik 					0);
380*a88db0d1SZdenek Styblik 			if (res != SUNOEM_EC_BMC_CCODE_NONZERO|| !rsp
381*a88db0d1SZdenek Styblik 			|| rsp->ccode != CC_DEST_UNAVAILABLE) {
382*a88db0d1SZdenek Styblik 				ret_get = -1;
383*a88db0d1SZdenek Styblik 			}
384*a88db0d1SZdenek Styblik 		}
385*a88db0d1SZdenek Styblik 	}
386c18ec02fSPetter Reinholdtsen 	__sdr_list_empty(elist);
387c18ec02fSPetter Reinholdtsen }
388c18ec02fSPetter Reinholdtsen 
389c18ec02fSPetter Reinholdtsen static void
sunoem_led_set_byentity(struct ipmi_intf * intf,uint8_t entity_id,uint8_t entity_inst,int ledtype,int ledmode)390c18ec02fSPetter Reinholdtsen sunoem_led_set_byentity(struct ipmi_intf * intf, uint8_t entity_id,
391c18ec02fSPetter Reinholdtsen 		uint8_t entity_inst, int ledtype, int ledmode)
392c18ec02fSPetter Reinholdtsen {
393c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
394c18ec02fSPetter Reinholdtsen 	struct sdr_record_list *elist, *e;
395c18ec02fSPetter Reinholdtsen 	struct entity_id entity;
396c18ec02fSPetter Reinholdtsen 
397c18ec02fSPetter Reinholdtsen 	if (entity_id == 0)
398c18ec02fSPetter Reinholdtsen 		return;
399c18ec02fSPetter Reinholdtsen 
400c18ec02fSPetter Reinholdtsen 	/* lookup sdrs with this entity */
401c18ec02fSPetter Reinholdtsen 	memset(&entity, 0, sizeof(struct entity_id));
402c18ec02fSPetter Reinholdtsen 	entity.id = entity_id;
403c18ec02fSPetter Reinholdtsen 	entity.instance = entity_inst;
404c18ec02fSPetter Reinholdtsen 
405c18ec02fSPetter Reinholdtsen 	elist = ipmi_sdr_find_sdr_byentity(intf, &entity);
406c18ec02fSPetter Reinholdtsen 
407*a88db0d1SZdenek Styblik 	if (elist == NULL)
408*a88db0d1SZdenek Styblik 		ret_set = -1;
409*a88db0d1SZdenek Styblik 
410c18ec02fSPetter Reinholdtsen 	/* for each generic sensor set its led state */
411c18ec02fSPetter Reinholdtsen 	for (e = elist; e != NULL; e = e->next) {
412*a88db0d1SZdenek Styblik 
413c18ec02fSPetter Reinholdtsen 		if (e->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR)
414c18ec02fSPetter Reinholdtsen 			continue;
415*a88db0d1SZdenek Styblik 
416c18ec02fSPetter Reinholdtsen 		rsp = sunoem_led_set(intf, e->record.genloc, ledtype, ledmode);
417c18ec02fSPetter Reinholdtsen 		if (rsp && rsp->data_len == 0) {
418*a88db0d1SZdenek Styblik 			led_print((const char *) e->record.genloc->id_string, PRINT_NORMAL,
419*a88db0d1SZdenek Styblik 					ledmode);
420*a88db0d1SZdenek Styblik 		} else if (rsp == NULL) {
421*a88db0d1SZdenek Styblik 			ret_set = -1;
422c18ec02fSPetter Reinholdtsen 		}
423c18ec02fSPetter Reinholdtsen 	}
424c18ec02fSPetter Reinholdtsen 
425c18ec02fSPetter Reinholdtsen 	__sdr_list_empty(elist);
426c18ec02fSPetter Reinholdtsen }
427c18ec02fSPetter Reinholdtsen 
428c18ec02fSPetter Reinholdtsen /*
429c18ec02fSPetter Reinholdtsen  * IPMI Request Data: 5 bytes
430c18ec02fSPetter Reinholdtsen  *
431c18ec02fSPetter Reinholdtsen  * [byte 0]  devAddr     Value from the "Device Slave Address" field in
432c18ec02fSPetter Reinholdtsen  *                       LED's Generic Device Locator record in the SDR
433c18ec02fSPetter Reinholdtsen  * [byte 1]  led         LED Type: OK2RM, ACT, LOCATE, SERVICE
434c18ec02fSPetter Reinholdtsen  * [byte 2]  ctrlrAddr   Controller address; value from the "Device
435c18ec02fSPetter Reinholdtsen  *                       Access Address" field, 0x20 if the LED is local
436c18ec02fSPetter Reinholdtsen  * [byte 3]  hwInfo      The OEM field from the SDR record
437c18ec02fSPetter Reinholdtsen  * [byte 4]  force       1 = directly access the device
438c18ec02fSPetter Reinholdtsen  *                       0 = go thru its controller
439c18ec02fSPetter Reinholdtsen  *                       Ignored if LED is local
440c18ec02fSPetter Reinholdtsen  *
441c18ec02fSPetter Reinholdtsen  * The format below is for Sun Blade Modular systems only
442c18ec02fSPetter Reinholdtsen  * [byte 4]  entityID    The entityID field from the SDR record
443c18ec02fSPetter Reinholdtsen  * [byte 5]  entityIns   The entityIns field from the SDR record
444c18ec02fSPetter Reinholdtsen  * [byte 6]  force       1 = directly access the device
445c18ec02fSPetter Reinholdtsen  *                       0 = go thru its controller
446c18ec02fSPetter Reinholdtsen  *                       Ignored if LED is local
447c18ec02fSPetter Reinholdtsen  */
448c18ec02fSPetter Reinholdtsen static int
ipmi_sunoem_led_get(struct ipmi_intf * intf,int argc,char ** argv)449c18ec02fSPetter Reinholdtsen ipmi_sunoem_led_get(struct ipmi_intf * intf, int argc, char ** argv)
450c18ec02fSPetter Reinholdtsen {
451c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
452c18ec02fSPetter Reinholdtsen 	struct sdr_record_list *sdr;
453c18ec02fSPetter Reinholdtsen 	struct sdr_record_list *alist, *a;
454c18ec02fSPetter Reinholdtsen 	struct sdr_record_entity_assoc *assoc;
455c18ec02fSPetter Reinholdtsen 	int ledtype = 0xFF;
456c18ec02fSPetter Reinholdtsen 	int i;
457*a88db0d1SZdenek Styblik 	sunoem_ec_t res;
458c18ec02fSPetter Reinholdtsen 
459c18ec02fSPetter Reinholdtsen 	/*
460c18ec02fSPetter Reinholdtsen 	 * sunoem led/sbled get <id> [type]
461c18ec02fSPetter Reinholdtsen 	 */
462c18ec02fSPetter Reinholdtsen 
463c18ec02fSPetter Reinholdtsen 	if (argc < 1 || strncmp(argv[0], "help", 4) == 0) {
464c18ec02fSPetter Reinholdtsen 		ipmi_sunoem_usage();
465*a88db0d1SZdenek Styblik 		return (0);
466c18ec02fSPetter Reinholdtsen 	}
467c18ec02fSPetter Reinholdtsen 
468c18ec02fSPetter Reinholdtsen 	if (argc > 1) {
469c18ec02fSPetter Reinholdtsen 		ledtype = str2val(argv[1], sunoem_led_type_vals);
470c18ec02fSPetter Reinholdtsen 		if (ledtype == 0xFF)
471*a88db0d1SZdenek Styblik 			lprintf(LOG_ERR,
472*a88db0d1SZdenek Styblik 					"Unknow ledtype, will use data from the SDR oem field");
473c18ec02fSPetter Reinholdtsen 	}
474c18ec02fSPetter Reinholdtsen 
475c18ec02fSPetter Reinholdtsen 	if (strncasecmp(argv[0], "all", 3) == 0) {
476c18ec02fSPetter Reinholdtsen 		/* do all generic sensors */
477c18ec02fSPetter Reinholdtsen 		alist = ipmi_sdr_find_sdr_bytype(intf,
478c18ec02fSPetter Reinholdtsen 		SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR);
479*a88db0d1SZdenek Styblik 
480*a88db0d1SZdenek Styblik 		if (alist == NULL)
481*a88db0d1SZdenek Styblik 			return (-1);
482*a88db0d1SZdenek Styblik 
483c18ec02fSPetter Reinholdtsen 		for (a = alist; a != NULL; a = a->next) {
484c18ec02fSPetter Reinholdtsen 			if (a->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR)
485c18ec02fSPetter Reinholdtsen 				continue;
486c18ec02fSPetter Reinholdtsen 			if (a->record.genloc->entity.logical)
487c18ec02fSPetter Reinholdtsen 				continue;
488*a88db0d1SZdenek Styblik 
489*a88db0d1SZdenek Styblik 			res = sunoem_led_get(intf, a->record.genloc, ledtype, &rsp);
490*a88db0d1SZdenek Styblik 
491*a88db0d1SZdenek Styblik 			if (res == SUNOEM_EC_SUCCESS && rsp && rsp->data_len == 1) {
492*a88db0d1SZdenek Styblik 				led_print((const char *) a->record.genloc->id_string,
493*a88db0d1SZdenek Styblik 						PRINT_NORMAL, rsp->data[0]);
494*a88db0d1SZdenek Styblik 			} else {
495*a88db0d1SZdenek Styblik 				led_print((const char *) a->record.genloc->id_string,
496*a88db0d1SZdenek Styblik 						PRINT_ERROR, 0);
497*a88db0d1SZdenek Styblik 				if (res != SUNOEM_EC_BMC_CCODE_NONZERO|| !rsp ||
498*a88db0d1SZdenek Styblik 				rsp->ccode != CC_DEST_UNAVAILABLE) {
499*a88db0d1SZdenek Styblik 					ret_get = -1;
500*a88db0d1SZdenek Styblik 				}
501c18ec02fSPetter Reinholdtsen 			}
502c18ec02fSPetter Reinholdtsen 		}
503c18ec02fSPetter Reinholdtsen 		__sdr_list_empty(alist);
504*a88db0d1SZdenek Styblik 
505*a88db0d1SZdenek Styblik 		if (ret_get == -1)
506*a88db0d1SZdenek Styblik 			return (-1);
507*a88db0d1SZdenek Styblik 
508*a88db0d1SZdenek Styblik 		return (0);
509c18ec02fSPetter Reinholdtsen 	}
510c18ec02fSPetter Reinholdtsen 
511c18ec02fSPetter Reinholdtsen 	/* look up generic device locator record in SDR */
512c18ec02fSPetter Reinholdtsen 	sdr = ipmi_sdr_find_sdr_byid(intf, argv[0]);
513c18ec02fSPetter Reinholdtsen 
514c18ec02fSPetter Reinholdtsen 	if (sdr == NULL) {
515c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "No Sensor Data Record found for %s", argv[0]);
516*a88db0d1SZdenek Styblik 		return (-1);
517c18ec02fSPetter Reinholdtsen 	}
518c18ec02fSPetter Reinholdtsen 
519c18ec02fSPetter Reinholdtsen 	if (sdr->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR) {
520c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Invalid SDR type %d", sdr->type);
521*a88db0d1SZdenek Styblik 		return (-1);
522c18ec02fSPetter Reinholdtsen 	}
523c18ec02fSPetter Reinholdtsen 
524c18ec02fSPetter Reinholdtsen 	if (!sdr->record.genloc->entity.logical) {
525c18ec02fSPetter Reinholdtsen 		/*
526c18ec02fSPetter Reinholdtsen 		 * handle physical entity
527c18ec02fSPetter Reinholdtsen 		 */
528*a88db0d1SZdenek Styblik 
529*a88db0d1SZdenek Styblik 		res = sunoem_led_get(intf, sdr->record.genloc, ledtype, &rsp);
530*a88db0d1SZdenek Styblik 
531*a88db0d1SZdenek Styblik 		if (res == SUNOEM_EC_SUCCESS && rsp && rsp->data_len == 1) {
532*a88db0d1SZdenek Styblik 			led_print((const char *) sdr->record.genloc->id_string,
533*a88db0d1SZdenek Styblik 					PRINT_NORMAL, rsp->data[0]);
534*a88db0d1SZdenek Styblik 
535*a88db0d1SZdenek Styblik 		} else {
536*a88db0d1SZdenek Styblik 			led_print((const char *) sdr->record.genloc->id_string, PRINT_ERROR,
537*a88db0d1SZdenek Styblik 					0);
538*a88db0d1SZdenek Styblik 			if (res != SUNOEM_EC_BMC_CCODE_NONZERO|| !rsp
539*a88db0d1SZdenek Styblik 			|| rsp->ccode != CC_DEST_UNAVAILABLE) {
540*a88db0d1SZdenek Styblik 				ret_get = -1;
541c18ec02fSPetter Reinholdtsen 			}
542*a88db0d1SZdenek Styblik 		}
543*a88db0d1SZdenek Styblik 
544*a88db0d1SZdenek Styblik 		if (ret_get == -1)
545*a88db0d1SZdenek Styblik 			return (-1);
546*a88db0d1SZdenek Styblik 
547*a88db0d1SZdenek Styblik 		return (0);
548c18ec02fSPetter Reinholdtsen 	}
549c18ec02fSPetter Reinholdtsen 
550c18ec02fSPetter Reinholdtsen 	/*
551c18ec02fSPetter Reinholdtsen 	 * handle logical entity for LED grouping
552c18ec02fSPetter Reinholdtsen 	 */
553c18ec02fSPetter Reinholdtsen 
554c18ec02fSPetter Reinholdtsen 	lprintf(LOG_INFO, "LED %s is logical device", argv[0]);
555c18ec02fSPetter Reinholdtsen 
556c18ec02fSPetter Reinholdtsen 	/* get entity assoc records */
557c18ec02fSPetter Reinholdtsen 	alist = ipmi_sdr_find_sdr_bytype(intf, SDR_RECORD_TYPE_ENTITY_ASSOC);
558*a88db0d1SZdenek Styblik 
559*a88db0d1SZdenek Styblik 	if (alist == NULL)
560*a88db0d1SZdenek Styblik 		return (-1);
561*a88db0d1SZdenek Styblik 
562c18ec02fSPetter Reinholdtsen 	for (a = alist; a != NULL; a = a->next) {
563c18ec02fSPetter Reinholdtsen 		if (a->type != SDR_RECORD_TYPE_ENTITY_ASSOC)
564c18ec02fSPetter Reinholdtsen 			continue;
565c18ec02fSPetter Reinholdtsen 		assoc = a->record.entassoc;
566c18ec02fSPetter Reinholdtsen 		if (assoc == NULL)
567c18ec02fSPetter Reinholdtsen 			continue;
568c18ec02fSPetter Reinholdtsen 
569c18ec02fSPetter Reinholdtsen 		/* check that the entity id/instance matches our generic record */
570*a88db0d1SZdenek Styblik 		if (assoc->entity.id != sdr->record.genloc->entity.id
571*a88db0d1SZdenek Styblik 				|| assoc->entity.instance
572*a88db0d1SZdenek Styblik 						!= sdr->record.genloc->entity.instance)
573c18ec02fSPetter Reinholdtsen 			continue;
574c18ec02fSPetter Reinholdtsen 
575c18ec02fSPetter Reinholdtsen 		if (assoc->flags.isrange) {
576c18ec02fSPetter Reinholdtsen 			/*
577c18ec02fSPetter Reinholdtsen 			 * handle ranged entity associations
578c18ec02fSPetter Reinholdtsen 			 *
579c18ec02fSPetter Reinholdtsen 			 * the test for non-zero entity id is handled in
580c18ec02fSPetter Reinholdtsen 			 * sunoem_led_get_byentity()
581c18ec02fSPetter Reinholdtsen 			 */
582c18ec02fSPetter Reinholdtsen 
583c18ec02fSPetter Reinholdtsen 			/* first range set - id 1 and 2 must be equal */
584c18ec02fSPetter Reinholdtsen 			if (assoc->entity_id_1 == assoc->entity_id_2)
585c18ec02fSPetter Reinholdtsen 				for (i = assoc->entity_inst_1; i <= assoc->entity_inst_2; i++)
586*a88db0d1SZdenek Styblik 					sunoem_led_get_byentity(intf, assoc->entity_id_1, i,
587*a88db0d1SZdenek Styblik 							ledtype);
588c18ec02fSPetter Reinholdtsen 
589c18ec02fSPetter Reinholdtsen 			/* second range set - id 3 and 4 must be equal */
590c18ec02fSPetter Reinholdtsen 			if (assoc->entity_id_3 == assoc->entity_id_4)
591c18ec02fSPetter Reinholdtsen 				for (i = assoc->entity_inst_3; i <= assoc->entity_inst_4; i++)
592*a88db0d1SZdenek Styblik 					sunoem_led_get_byentity(intf, assoc->entity_id_3, i,
593*a88db0d1SZdenek Styblik 							ledtype);
594*a88db0d1SZdenek Styblik 		} else {
595c18ec02fSPetter Reinholdtsen 			/*
596c18ec02fSPetter Reinholdtsen 			 * handle entity list
597c18ec02fSPetter Reinholdtsen 			 */
598c18ec02fSPetter Reinholdtsen 			sunoem_led_get_byentity(intf, assoc->entity_id_1,
599c18ec02fSPetter Reinholdtsen 					assoc->entity_inst_1, ledtype);
600c18ec02fSPetter Reinholdtsen 			sunoem_led_get_byentity(intf, assoc->entity_id_2,
601c18ec02fSPetter Reinholdtsen 					assoc->entity_inst_2, ledtype);
602c18ec02fSPetter Reinholdtsen 			sunoem_led_get_byentity(intf, assoc->entity_id_3,
603c18ec02fSPetter Reinholdtsen 					assoc->entity_inst_3, ledtype);
604c18ec02fSPetter Reinholdtsen 			sunoem_led_get_byentity(intf, assoc->entity_id_4,
605c18ec02fSPetter Reinholdtsen 					assoc->entity_inst_4, ledtype);
606c18ec02fSPetter Reinholdtsen 		}
607c18ec02fSPetter Reinholdtsen 	}
608c18ec02fSPetter Reinholdtsen 
609c18ec02fSPetter Reinholdtsen 	__sdr_list_empty(alist);
610c18ec02fSPetter Reinholdtsen 
611*a88db0d1SZdenek Styblik 	if (ret_get == -1)
612*a88db0d1SZdenek Styblik 		return (-1);
613*a88db0d1SZdenek Styblik 
614*a88db0d1SZdenek Styblik 	return (0);
615c18ec02fSPetter Reinholdtsen }
616c18ec02fSPetter Reinholdtsen 
617c18ec02fSPetter Reinholdtsen /*
618c18ec02fSPetter Reinholdtsen  * IPMI Request Data: 7 bytes
619c18ec02fSPetter Reinholdtsen  *
620c18ec02fSPetter Reinholdtsen  * [byte 0]  devAddr     Value from the "Device Slave Address" field in
621c18ec02fSPetter Reinholdtsen  *                       LED's Generic Device Locator record in the SDR
622c18ec02fSPetter Reinholdtsen  * [byte 1]  led         LED Type: OK2RM, ACT, LOCATE, SERVICE
623c18ec02fSPetter Reinholdtsen  * [byte 2]  ctrlrAddr   Controller address; value from the "Device
624c18ec02fSPetter Reinholdtsen  *                       Access Address" field, 0x20 if the LED is local
625c18ec02fSPetter Reinholdtsen  * [byte 3]  hwInfo      The OEM field from the SDR record
626c18ec02fSPetter Reinholdtsen  * [byte 4]  mode        LED Mode: OFF, ON, STANDBY, SLOW, FAST
627c18ec02fSPetter Reinholdtsen  * [byte 5]  force       TRUE - directly access the device
628c18ec02fSPetter Reinholdtsen  *                       FALSE - go thru its controller
629c18ec02fSPetter Reinholdtsen  *                       Ignored if LED is local
630c18ec02fSPetter Reinholdtsen  * [byte 6]  role        Used by BMC for authorization purposes
631c18ec02fSPetter Reinholdtsen  *
632c18ec02fSPetter Reinholdtsen  * The format below is for Sun Blade Modular systems only
633c18ec02fSPetter Reinholdtsen  * [byte 5]  entityID    The entityID field from the SDR record
634c18ec02fSPetter Reinholdtsen  * [byte 6]  entityIns   The entityIns field from the SDR record
635c18ec02fSPetter Reinholdtsen  * [byte 7]  force       TRUE - directly access the device
636c18ec02fSPetter Reinholdtsen  *                       FALSE - go thru its controller
637c18ec02fSPetter Reinholdtsen  *                       Ignored if LED is local
638c18ec02fSPetter Reinholdtsen  * [byte 8]  role        Used by BMC for authorization purposes
639c18ec02fSPetter Reinholdtsen  *
640c18ec02fSPetter Reinholdtsen  *
641c18ec02fSPetter Reinholdtsen  * IPMI Response Data: 1 byte
642c18ec02fSPetter Reinholdtsen  *
643c18ec02fSPetter Reinholdtsen  * [byte 0]  mode     LED Mode: OFF, ON, STANDBY, SLOW, FAST
644c18ec02fSPetter Reinholdtsen  */
645c18ec02fSPetter Reinholdtsen 
646c18ec02fSPetter Reinholdtsen static int
ipmi_sunoem_led_set(struct ipmi_intf * intf,int argc,char ** argv)647c18ec02fSPetter Reinholdtsen ipmi_sunoem_led_set(struct ipmi_intf * intf, int argc, char ** argv)
648c18ec02fSPetter Reinholdtsen {
649c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
650c18ec02fSPetter Reinholdtsen 	struct sdr_record_list *sdr;
651c18ec02fSPetter Reinholdtsen 	struct sdr_record_list *alist, *a;
652c18ec02fSPetter Reinholdtsen 	struct sdr_record_entity_assoc *assoc;
653c18ec02fSPetter Reinholdtsen 	int ledmode;
654c18ec02fSPetter Reinholdtsen 	int ledtype = 0xFF;
655c18ec02fSPetter Reinholdtsen 	int i;
656c18ec02fSPetter Reinholdtsen 
657c18ec02fSPetter Reinholdtsen 	/*
658c18ec02fSPetter Reinholdtsen 	 * sunoem led/sbled set <id> <mode> [type]
659c18ec02fSPetter Reinholdtsen 	 */
660c18ec02fSPetter Reinholdtsen 
661c18ec02fSPetter Reinholdtsen 	if (argc < 2 || strncmp(argv[0], "help", 4) == 0) {
662c18ec02fSPetter Reinholdtsen 		ipmi_sunoem_usage();
663*a88db0d1SZdenek Styblik 		return (0);
664c18ec02fSPetter Reinholdtsen 	}
665c18ec02fSPetter Reinholdtsen 
666c18ec02fSPetter Reinholdtsen 	ledmode = str2val(argv[1], sunoem_led_mode_vals);
667c18ec02fSPetter Reinholdtsen 	if (ledmode == 0xFF) {
668c18ec02fSPetter Reinholdtsen 		ledmode = str2val(argv[1], sunoem_led_mode_optvals);
669c18ec02fSPetter Reinholdtsen 		if (ledmode == 0xFF) {
670c18ec02fSPetter Reinholdtsen 			lprintf(LOG_NOTICE, "Invalid LED Mode: %s", argv[1]);
671*a88db0d1SZdenek Styblik 			return (-1);
672c18ec02fSPetter Reinholdtsen 		}
673c18ec02fSPetter Reinholdtsen 	}
674c18ec02fSPetter Reinholdtsen 
675c18ec02fSPetter Reinholdtsen 	if (argc > 3) {
676c18ec02fSPetter Reinholdtsen 		ledtype = str2val(argv[2], sunoem_led_type_vals);
677c18ec02fSPetter Reinholdtsen 		if (ledtype == 0xFF)
678*a88db0d1SZdenek Styblik 			lprintf(LOG_ERR,
679*a88db0d1SZdenek Styblik 					"Unknow ledtype, will use data from the SDR oem field");
680c18ec02fSPetter Reinholdtsen 	}
681c18ec02fSPetter Reinholdtsen 
682c18ec02fSPetter Reinholdtsen 	if (strncasecmp(argv[0], "all", 3) == 0) {
683c18ec02fSPetter Reinholdtsen 		/* do all generic sensors */
684c18ec02fSPetter Reinholdtsen 		alist = ipmi_sdr_find_sdr_bytype(intf,
685c18ec02fSPetter Reinholdtsen 		SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR);
686*a88db0d1SZdenek Styblik 
687*a88db0d1SZdenek Styblik 		if (alist == NULL)
688*a88db0d1SZdenek Styblik 			return (-1);
689*a88db0d1SZdenek Styblik 
690c18ec02fSPetter Reinholdtsen 		for (a = alist; a != NULL; a = a->next) {
691c18ec02fSPetter Reinholdtsen 			if (a->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR)
692c18ec02fSPetter Reinholdtsen 				continue;
693c18ec02fSPetter Reinholdtsen 			if (a->record.genloc->entity.logical)
694c18ec02fSPetter Reinholdtsen 				continue;
695c18ec02fSPetter Reinholdtsen 			rsp = sunoem_led_set(intf, a->record.genloc, ledtype, ledmode);
696*a88db0d1SZdenek Styblik 			if (rsp && rsp->ccode == 0)
697*a88db0d1SZdenek Styblik 				led_print((const char *) a->record.genloc->id_string,
698*a88db0d1SZdenek Styblik 						PRINT_NORMAL, ledmode);
699*a88db0d1SZdenek Styblik 			else
700*a88db0d1SZdenek Styblik 				ret_set = -1;
701c18ec02fSPetter Reinholdtsen 		}
702c18ec02fSPetter Reinholdtsen 		__sdr_list_empty(alist);
703*a88db0d1SZdenek Styblik 
704*a88db0d1SZdenek Styblik 		if (ret_set == -1)
705*a88db0d1SZdenek Styblik 			return (-1);
706*a88db0d1SZdenek Styblik 
707*a88db0d1SZdenek Styblik 		return (0);
708c18ec02fSPetter Reinholdtsen 	}
709c18ec02fSPetter Reinholdtsen 
710c18ec02fSPetter Reinholdtsen 	/* look up generic device locator records in SDR */
711c18ec02fSPetter Reinholdtsen 	sdr = ipmi_sdr_find_sdr_byid(intf, argv[0]);
712c18ec02fSPetter Reinholdtsen 
713c18ec02fSPetter Reinholdtsen 	if (sdr == NULL) {
714*a88db0d1SZdenek Styblik 		lprintf(LOG_ERR, "No Sensor Data Record found for %s", argv[0]);
715*a88db0d1SZdenek Styblik 		return (-1);
716c18ec02fSPetter Reinholdtsen 	}
717c18ec02fSPetter Reinholdtsen 
718c18ec02fSPetter Reinholdtsen 	if (sdr->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR) {
719c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Invalid SDR type %d", sdr->type);
720*a88db0d1SZdenek Styblik 		return (-1);
721c18ec02fSPetter Reinholdtsen 	}
722c18ec02fSPetter Reinholdtsen 
723c18ec02fSPetter Reinholdtsen 	if (!sdr->record.genloc->entity.logical) {
724c18ec02fSPetter Reinholdtsen 		/*
725c18ec02fSPetter Reinholdtsen 		 * handle physical entity
726c18ec02fSPetter Reinholdtsen 		 */
727c18ec02fSPetter Reinholdtsen 		rsp = sunoem_led_set(intf, sdr->record.genloc, ledtype, ledmode);
728*a88db0d1SZdenek Styblik 		if (rsp && rsp->ccode == 0)
729*a88db0d1SZdenek Styblik 			led_print(argv[0], PRINT_NORMAL, ledmode);
730*a88db0d1SZdenek Styblik 		else
731*a88db0d1SZdenek Styblik 			return (-1);
732*a88db0d1SZdenek Styblik 
733*a88db0d1SZdenek Styblik 		return (0);
734c18ec02fSPetter Reinholdtsen 	}
735c18ec02fSPetter Reinholdtsen 
736c18ec02fSPetter Reinholdtsen 	/*
737c18ec02fSPetter Reinholdtsen 	 * handle logical entity for LED grouping
738c18ec02fSPetter Reinholdtsen 	 */
739c18ec02fSPetter Reinholdtsen 
740c18ec02fSPetter Reinholdtsen 	lprintf(LOG_INFO, "LED %s is logical device", argv[0]);
741c18ec02fSPetter Reinholdtsen 
742c18ec02fSPetter Reinholdtsen 	/* get entity assoc records */
743c18ec02fSPetter Reinholdtsen 	alist = ipmi_sdr_find_sdr_bytype(intf, SDR_RECORD_TYPE_ENTITY_ASSOC);
744*a88db0d1SZdenek Styblik 
745*a88db0d1SZdenek Styblik 	if (alist == NULL)
746*a88db0d1SZdenek Styblik 		return (-1);
747*a88db0d1SZdenek Styblik 
748c18ec02fSPetter Reinholdtsen 	for (a = alist; a != NULL; a = a->next) {
749c18ec02fSPetter Reinholdtsen 		if (a->type != SDR_RECORD_TYPE_ENTITY_ASSOC)
750c18ec02fSPetter Reinholdtsen 			continue;
751c18ec02fSPetter Reinholdtsen 		assoc = a->record.entassoc;
752c18ec02fSPetter Reinholdtsen 		if (assoc == NULL)
753c18ec02fSPetter Reinholdtsen 			continue;
754c18ec02fSPetter Reinholdtsen 
755c18ec02fSPetter Reinholdtsen 		/* check that the entity id/instance matches our generic record */
756*a88db0d1SZdenek Styblik 		if (assoc->entity.id != sdr->record.genloc->entity.id
757*a88db0d1SZdenek Styblik 				|| assoc->entity.instance
758*a88db0d1SZdenek Styblik 						!= sdr->record.genloc->entity.instance)
759c18ec02fSPetter Reinholdtsen 			continue;
760c18ec02fSPetter Reinholdtsen 
761c18ec02fSPetter Reinholdtsen 		if (assoc->flags.isrange) {
762c18ec02fSPetter Reinholdtsen 			/*
763c18ec02fSPetter Reinholdtsen 			 * handle ranged entity associations
764c18ec02fSPetter Reinholdtsen 			 *
765c18ec02fSPetter Reinholdtsen 			 * the test for non-zero entity id is handled in
766c18ec02fSPetter Reinholdtsen 			 * sunoem_led_get_byentity()
767c18ec02fSPetter Reinholdtsen 			 */
768c18ec02fSPetter Reinholdtsen 
769c18ec02fSPetter Reinholdtsen 			/* first range set - id 1 and 2 must be equal */
770c18ec02fSPetter Reinholdtsen 			if (assoc->entity_id_1 == assoc->entity_id_2)
771c18ec02fSPetter Reinholdtsen 				for (i = assoc->entity_inst_1; i <= assoc->entity_inst_2; i++)
772*a88db0d1SZdenek Styblik 					sunoem_led_set_byentity(intf, assoc->entity_id_1, i,
773*a88db0d1SZdenek Styblik 							ledtype, ledmode);
774c18ec02fSPetter Reinholdtsen 
775c18ec02fSPetter Reinholdtsen 			/* second range set - id 3 and 4 must be equal */
776c18ec02fSPetter Reinholdtsen 			if (assoc->entity_id_3 == assoc->entity_id_4)
777c18ec02fSPetter Reinholdtsen 				for (i = assoc->entity_inst_3; i <= assoc->entity_inst_4; i++)
778*a88db0d1SZdenek Styblik 					sunoem_led_set_byentity(intf, assoc->entity_id_3, i,
779*a88db0d1SZdenek Styblik 							ledtype, ledmode);
780*a88db0d1SZdenek Styblik 		} else {
781c18ec02fSPetter Reinholdtsen 			/*
782c18ec02fSPetter Reinholdtsen 			 * handle entity list
783c18ec02fSPetter Reinholdtsen 			 */
784c18ec02fSPetter Reinholdtsen 			sunoem_led_set_byentity(intf, assoc->entity_id_1,
785c18ec02fSPetter Reinholdtsen 					assoc->entity_inst_1, ledtype, ledmode);
786c18ec02fSPetter Reinholdtsen 			sunoem_led_set_byentity(intf, assoc->entity_id_2,
787c18ec02fSPetter Reinholdtsen 					assoc->entity_inst_2, ledtype, ledmode);
788c18ec02fSPetter Reinholdtsen 			sunoem_led_set_byentity(intf, assoc->entity_id_3,
789c18ec02fSPetter Reinholdtsen 					assoc->entity_inst_3, ledtype, ledmode);
790c18ec02fSPetter Reinholdtsen 			sunoem_led_set_byentity(intf, assoc->entity_id_4,
791c18ec02fSPetter Reinholdtsen 					assoc->entity_inst_4, ledtype, ledmode);
792c18ec02fSPetter Reinholdtsen 		}
793c18ec02fSPetter Reinholdtsen 	}
794c18ec02fSPetter Reinholdtsen 
795c18ec02fSPetter Reinholdtsen 	__sdr_list_empty(alist);
796c18ec02fSPetter Reinholdtsen 
797*a88db0d1SZdenek Styblik 	if (ret_set == -1)
798*a88db0d1SZdenek Styblik 		return (-1);
799*a88db0d1SZdenek Styblik 
800*a88db0d1SZdenek Styblik 	return (0);
801c18ec02fSPetter Reinholdtsen }
802c18ec02fSPetter Reinholdtsen 
803c18ec02fSPetter Reinholdtsen static int
ipmi_sunoem_sshkey_del(struct ipmi_intf * intf,uint8_t uid)804c18ec02fSPetter Reinholdtsen ipmi_sunoem_sshkey_del(struct ipmi_intf * intf, uint8_t uid)
805c18ec02fSPetter Reinholdtsen {
806c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
807c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
808c18ec02fSPetter Reinholdtsen 
809c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(struct ipmi_rq));
810c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_SUNOEM;
811c18ec02fSPetter Reinholdtsen 	req.msg.cmd = IPMI_SUNOEM_DEL_SSH_KEY;
812c18ec02fSPetter Reinholdtsen 	req.msg.data = &uid;
813c18ec02fSPetter Reinholdtsen 	req.msg.data_len = 1;
814c18ec02fSPetter Reinholdtsen 
815c18ec02fSPetter Reinholdtsen 	rsp = intf->sendrecv(intf, &req);
816c18ec02fSPetter Reinholdtsen 	if (rsp == NULL) {
817c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Unable to delete ssh key for UID %d", uid);
818*a88db0d1SZdenek Styblik 		return (-1);
819*a88db0d1SZdenek Styblik 	} else if (rsp->ccode > 0) {
820c18ec02fSPetter Reinholdtsen 		lprintf(LOG_ERR, "Unable to delete ssh key for UID %d: %s", uid,
821c18ec02fSPetter Reinholdtsen 				val2str(rsp->ccode, completion_code_vals));
822*a88db0d1SZdenek Styblik 		return (-1);
823c18ec02fSPetter Reinholdtsen 	}
824c18ec02fSPetter Reinholdtsen 
825c18ec02fSPetter Reinholdtsen 	printf("Deleted SSH key for user id %d\n", uid);
826*a88db0d1SZdenek Styblik 	return (0);
827c18ec02fSPetter Reinholdtsen }
828c18ec02fSPetter Reinholdtsen 
829c18ec02fSPetter Reinholdtsen #define SSHKEY_BLOCK_SIZE	64
830c18ec02fSPetter Reinholdtsen static int
ipmi_sunoem_sshkey_set(struct ipmi_intf * intf,uint8_t uid,char * ifile)831c18ec02fSPetter Reinholdtsen ipmi_sunoem_sshkey_set(struct ipmi_intf * intf, uint8_t uid, char * ifile)
832c18ec02fSPetter Reinholdtsen {
833c18ec02fSPetter Reinholdtsen 	struct ipmi_rs * rsp;
834c18ec02fSPetter Reinholdtsen 	struct ipmi_rq req;
835c18ec02fSPetter Reinholdtsen 	FILE * fp;
836*a88db0d1SZdenek Styblik 	int count = 0;
837c18ec02fSPetter Reinholdtsen 	uint8_t wbuf[SSHKEY_BLOCK_SIZE + 3];
838*a88db0d1SZdenek Styblik 	int32_t i_size = 0;
839*a88db0d1SZdenek Styblik 	int32_t r = 0;
840*a88db0d1SZdenek Styblik 	int32_t size = 0;
841c18ec02fSPetter Reinholdtsen 
842c18ec02fSPetter Reinholdtsen 	if (ifile == NULL) {
843*a88db0d1SZdenek Styblik 		lprintf(LOG_ERR, "Invalid or misisng input filename.");
844*a88db0d1SZdenek Styblik 		return (-1);
845c18ec02fSPetter Reinholdtsen 	}
846c18ec02fSPetter Reinholdtsen 
847c18ec02fSPetter Reinholdtsen 	fp = ipmi_open_file_read(ifile);
848c18ec02fSPetter Reinholdtsen 	if (fp == NULL) {
849*a88db0d1SZdenek Styblik 		lprintf(LOG_ERR, "Unable to open file '%s' for reading.", ifile);
850*a88db0d1SZdenek Styblik 		return (-1);
851c18ec02fSPetter Reinholdtsen 	}
852c18ec02fSPetter Reinholdtsen 
853c18ec02fSPetter Reinholdtsen 	memset(&req, 0, sizeof(struct ipmi_rq));
854c18ec02fSPetter Reinholdtsen 	req.msg.netfn = IPMI_NETFN_SUNOEM;
855c18ec02fSPetter Reinholdtsen 	req.msg.cmd = IPMI_SUNOEM_SET_SSH_KEY;
856c18ec02fSPetter Reinholdtsen 	req.msg.data = wbuf;
857c18ec02fSPetter Reinholdtsen 
858*a88db0d1SZdenek Styblik 	if (fseek(fp, 0, SEEK_END) == (-1)) {
859*a88db0d1SZdenek Styblik 		lprintf(LOG_ERR, "Failed to seek in file '%s'.", ifile);
860*a88db0d1SZdenek Styblik 		if (fp != NULL)
861*a88db0d1SZdenek Styblik 			fclose(fp);
862*a88db0d1SZdenek Styblik 
863*a88db0d1SZdenek Styblik 		return (-1);
864*a88db0d1SZdenek Styblik 	}
865*a88db0d1SZdenek Styblik 
866*a88db0d1SZdenek Styblik 	size = (int32_t) ftell(fp);
867*a88db0d1SZdenek Styblik 	if (size < 0) {
868*a88db0d1SZdenek Styblik 		lprintf(LOG_ERR, "Failed to seek in file '%s'.", ifile);
869*a88db0d1SZdenek Styblik 		if (fp != NULL)
870*a88db0d1SZdenek Styblik 			fclose(fp);
871*a88db0d1SZdenek Styblik 
872*a88db0d1SZdenek Styblik 		return (-1);
873*a88db0d1SZdenek Styblik 	} else if (size == 0) {
874*a88db0d1SZdenek Styblik 		lprintf(LOG_ERR, "File '%s' is empty.", ifile);
875*a88db0d1SZdenek Styblik 		if (fp != NULL)
876*a88db0d1SZdenek Styblik 			fclose(fp);
877*a88db0d1SZdenek Styblik 
878*a88db0d1SZdenek Styblik 		return (-1);
879*a88db0d1SZdenek Styblik 	}
880*a88db0d1SZdenek Styblik 
881*a88db0d1SZdenek Styblik 	if (fseek(fp, 0, SEEK_SET) == (-1)) {
882*a88db0d1SZdenek Styblik 		lprintf(LOG_ERR, "Failed to seek in file '%s'.", ifile);
883*a88db0d1SZdenek Styblik 		if (fp != NULL)
884*a88db0d1SZdenek Styblik 			fclose(fp);
885*a88db0d1SZdenek Styblik 
886*a88db0d1SZdenek Styblik 		return (-1);
887*a88db0d1SZdenek Styblik 	}
888*a88db0d1SZdenek Styblik 
889*a88db0d1SZdenek Styblik 	printf("Setting SSH key for user id %d...", uid);
890c18ec02fSPetter Reinholdtsen 
891c18ec02fSPetter Reinholdtsen 	for (r = 0; r < size; r += i_size) {
892c18ec02fSPetter Reinholdtsen 		i_size = size - r;
893c18ec02fSPetter Reinholdtsen 		if (i_size > SSHKEY_BLOCK_SIZE)
894c18ec02fSPetter Reinholdtsen 			i_size = SSHKEY_BLOCK_SIZE;
895c18ec02fSPetter Reinholdtsen 
896c18ec02fSPetter Reinholdtsen 		memset(wbuf, 0, SSHKEY_BLOCK_SIZE);
897*a88db0d1SZdenek Styblik 		fseek(fp, r, SEEK_SET);
898c18ec02fSPetter Reinholdtsen 		count = fread(wbuf + 3, 1, i_size, fp);
899c18ec02fSPetter Reinholdtsen 		if (count != i_size) {
900*a88db0d1SZdenek Styblik 			printf("failed\n");
901*a88db0d1SZdenek Styblik 			lprintf(LOG_ERR, "Unable to read %ld bytes from file '%s'.", i_size,
902*a88db0d1SZdenek Styblik 					ifile);
903*a88db0d1SZdenek Styblik 			if (fp != NULL)
904c18ec02fSPetter Reinholdtsen 				fclose(fp);
905*a88db0d1SZdenek Styblik 
906*a88db0d1SZdenek Styblik 			return (-1);
907c18ec02fSPetter Reinholdtsen 		}
908c18ec02fSPetter Reinholdtsen 
909c18ec02fSPetter Reinholdtsen 		printf(".");
910c18ec02fSPetter Reinholdtsen 		fflush(stdout);
911c18ec02fSPetter Reinholdtsen 
912c18ec02fSPetter Reinholdtsen 		wbuf[0] = uid;
913c18ec02fSPetter Reinholdtsen 		if ((r + SSHKEY_BLOCK_SIZE) >= size)
914c18ec02fSPetter Reinholdtsen 			wbuf[1] = 0xff;
915*a88db0d1SZdenek Styblik 		else {
916*a88db0d1SZdenek Styblik 			if ((r / SSHKEY_BLOCK_SIZE) > UINT8_MAX) {
917*a88db0d1SZdenek Styblik 				printf("failed\n");
918*a88db0d1SZdenek Styblik 				lprintf(LOG_ERR, "Unable to pack byte %ld from file '%s'.", r,
919*a88db0d1SZdenek Styblik 						ifile);
920*a88db0d1SZdenek Styblik 				if (fp != NULL)
921*a88db0d1SZdenek Styblik 					fclose(fp);
922*a88db0d1SZdenek Styblik 
923*a88db0d1SZdenek Styblik 				return (-1);
924*a88db0d1SZdenek Styblik 			}
925c18ec02fSPetter Reinholdtsen 			wbuf[1] = (uint8_t) (r / SSHKEY_BLOCK_SIZE);
926*a88db0d1SZdenek Styblik 		}
927*a88db0d1SZdenek Styblik 
928*a88db0d1SZdenek Styblik 		wbuf[2] = (uint8_t) i_size;
929*a88db0d1SZdenek Styblik 
930c18ec02fSPetter Reinholdtsen 		req.msg.data_len = i_size + 3;
931c18ec02fSPetter Reinholdtsen 
932c18ec02fSPetter Reinholdtsen 		rsp = intf->sendrecv(intf, &req);
933c18ec02fSPetter Reinholdtsen 		if (rsp == NULL) {
934*a88db0d1SZdenek Styblik 			printf("failed\n");
935*a88db0d1SZdenek Styblik 			lprintf(LOG_ERR, "Unable to set ssh key for UID %d.", uid);
936*a88db0d1SZdenek Styblik 			if (fp != NULL)
937*a88db0d1SZdenek Styblik 				fclose(fp);
938*a88db0d1SZdenek Styblik 
939*a88db0d1SZdenek Styblik 			return (-1);
940*a88db0d1SZdenek Styblik 		} /* if (rsp == NULL) */
941*a88db0d1SZdenek Styblik 		if (rsp->ccode != 0) {
942*a88db0d1SZdenek Styblik 			printf("failed\n");
943*a88db0d1SZdenek Styblik 			lprintf(LOG_ERR, "Unable to set ssh key for UID %d, %s.", uid,
944*a88db0d1SZdenek Styblik 					val2str(rsp->ccode, completion_code_vals));
945*a88db0d1SZdenek Styblik 			if (fp != NULL)
946*a88db0d1SZdenek Styblik 				fclose(fp);
947*a88db0d1SZdenek Styblik 
948*a88db0d1SZdenek Styblik 			return (-1);
949*a88db0d1SZdenek Styblik 		} /* if (rsp->ccode != 0) */
950c18ec02fSPetter Reinholdtsen 	}
951c18ec02fSPetter Reinholdtsen 
952c18ec02fSPetter Reinholdtsen 	printf("done\n");
953c18ec02fSPetter Reinholdtsen 
954c18ec02fSPetter Reinholdtsen 	fclose(fp);
955*a88db0d1SZdenek Styblik 	return (0);
956c18ec02fSPetter Reinholdtsen }
957c18ec02fSPetter Reinholdtsen 
958*a88db0d1SZdenek Styblik /*
959*a88db0d1SZdenek Styblik  * This structure is used in both the request to and response from the BMC.
960*a88db0d1SZdenek Styblik  */
961*a88db0d1SZdenek Styblik #define SUNOEM_CLI_LEGACY_VERSION       1
962*a88db0d1SZdenek Styblik #define SUNOEM_CLI_SEQNUM_VERSION       2
963*a88db0d1SZdenek Styblik #define SUNOEM_CLI_VERSION       SUNOEM_CLI_SEQNUM_VERSION
964*a88db0d1SZdenek Styblik #define SUNOEM_CLI_HEADER        8 /* command + spare + handle */
965*a88db0d1SZdenek Styblik #define SUNOEM_CLI_BUF_SIZE      (80 - SUNOEM_CLI_HEADER) /* Total 80 bytes */
966*a88db0d1SZdenek Styblik #define SUNOEM_CLI_MSG_SIZE(msg) (SUNOEM_CLI_HEADER + strlen((msg).buf) + 1)
967*a88db0d1SZdenek Styblik 
968*a88db0d1SZdenek Styblik #ifdef HAVE_PRAGMA_PACK
969*a88db0d1SZdenek Styblik #pragma pack(push, 1)
970*a88db0d1SZdenek Styblik #endif
971*a88db0d1SZdenek Styblik typedef struct
972*a88db0d1SZdenek Styblik {
973*a88db0d1SZdenek Styblik 	/*
974*a88db0d1SZdenek Styblik 	 * Set version to SUNOEM_CLI_VERSION.
975*a88db0d1SZdenek Styblik 	 */
976*a88db0d1SZdenek Styblik 	uint8_t version;
977*a88db0d1SZdenek Styblik 	/*
978*a88db0d1SZdenek Styblik 	 * The command in a request, or in a response indicates an error if
979*a88db0d1SZdenek Styblik 	 * non-zero.
980*a88db0d1SZdenek Styblik 	 */
981*a88db0d1SZdenek Styblik 	uint8_t command_response;
982*a88db0d1SZdenek Styblik 	uint8_t seqnum;
983*a88db0d1SZdenek Styblik 	uint8_t spare;
984*a88db0d1SZdenek Styblik 	/*
985*a88db0d1SZdenek Styblik 	 * Opaque 4-byte handle, supplied in the response to an OPEN request,
986*a88db0d1SZdenek Styblik 	 * and used in all subsequent POLL and CLOSE requests.
987*a88db0d1SZdenek Styblik 	 */
988*a88db0d1SZdenek Styblik 	uint8_t handle[4];
989*a88db0d1SZdenek Styblik 	/*
990*a88db0d1SZdenek Styblik 	 * The client data in a request, or the server data in a response. Must
991*a88db0d1SZdenek Styblik 	 * by null terminated, i.e., it must be at least one byte, but can be
992*a88db0d1SZdenek Styblik 	 * smaller if there's less data.
993*a88db0d1SZdenek Styblik 	 */
994*a88db0d1SZdenek Styblik 	char buf[SUNOEM_CLI_BUF_SIZE];
995*a88db0d1SZdenek Styblik }__attribute__((packed)) sunoem_cli_msg_t;
996*a88db0d1SZdenek Styblik #ifdef HAVE_PRAGMA_PACK
997*a88db0d1SZdenek Styblik #pragma pack(pop)
998*a88db0d1SZdenek Styblik #endif
999*a88db0d1SZdenek Styblik 
1000*a88db0d1SZdenek Styblik /*
1001*a88db0d1SZdenek Styblik  * Command codes for the command_request field in each request.
1002*a88db0d1SZdenek Styblik  */
1003*a88db0d1SZdenek Styblik #define SUNOEM_CLI_CMD_OPEN   0 /* Open a new connection */
1004*a88db0d1SZdenek Styblik #define SUNOEM_CLI_CMD_FORCE  1 /* Close any existing connection, then open */
1005*a88db0d1SZdenek Styblik #define SUNOEM_CLI_CMD_CLOSE  2 /* Close the current connection */
1006*a88db0d1SZdenek Styblik #define SUNOEM_CLI_CMD_POLL   3 /* Poll for new data to/from the server */
1007*a88db0d1SZdenek Styblik #define SUNOEM_CLI_CMD_EOF    4 /* Poll, client is out of data */
1008*a88db0d1SZdenek Styblik 
1009*a88db0d1SZdenek Styblik #define SUNOEM_CLI_MAX_RETRY  3 /* Maximum number of retries */
1010*a88db0d1SZdenek Styblik 
1011*a88db0d1SZdenek Styblik #define SUNOEM_CLI_INVALID_VER_ERR "Invalid version"
1012*a88db0d1SZdenek Styblik #define SUNOEM_CLI_BUSY_ERR        "Busy"
1013*a88db0d1SZdenek Styblik 
1014*a88db0d1SZdenek Styblik typedef enum
1015*a88db0d1SZdenek Styblik {
1016*a88db0d1SZdenek Styblik 	C_CTL_B = 0x02, /* same as left arrow */
1017*a88db0d1SZdenek Styblik 	C_CTL_C = 0x03,
1018*a88db0d1SZdenek Styblik 	C_CTL_D = 0x04,
1019*a88db0d1SZdenek Styblik 	C_CTL_F = 0x06, /* same as right arrow */
1020*a88db0d1SZdenek Styblik 	C_CTL_N = 0x0E, /* same as down arrow */
1021*a88db0d1SZdenek Styblik 	C_CTL_P = 0x10, /* same as up arrow */
1022*a88db0d1SZdenek Styblik 	C_DEL = 0x7f
1023*a88db0d1SZdenek Styblik } canon_char_t;
1024*a88db0d1SZdenek Styblik 
1025*a88db0d1SZdenek Styblik static int
sunoem_cli_unbufmode_start(FILE * f,struct termios * orig_ts)1026*a88db0d1SZdenek Styblik sunoem_cli_unbufmode_start(FILE *f, struct termios *orig_ts)
1027*a88db0d1SZdenek Styblik {
1028*a88db0d1SZdenek Styblik 	struct termios ts;
1029*a88db0d1SZdenek Styblik 	int rc;
1030*a88db0d1SZdenek Styblik 
1031*a88db0d1SZdenek Styblik 	if ((rc = tcgetattr(fileno(f), &ts))) {
1032*a88db0d1SZdenek Styblik 		return (rc);
1033*a88db0d1SZdenek Styblik 	}
1034*a88db0d1SZdenek Styblik 	*orig_ts = ts;
1035*a88db0d1SZdenek Styblik 	ts.c_lflag &= ~(ICANON | ECHO | ISIG);
1036*a88db0d1SZdenek Styblik 	ts.c_cc[VMIN] = 1;
1037*a88db0d1SZdenek Styblik 	if ((rc = tcsetattr(fileno(f), TCSAFLUSH, &ts))) {
1038*a88db0d1SZdenek Styblik 		return (rc);
1039*a88db0d1SZdenek Styblik 	}
1040*a88db0d1SZdenek Styblik 
1041*a88db0d1SZdenek Styblik 	return (0);
1042*a88db0d1SZdenek Styblik }
1043*a88db0d1SZdenek Styblik 
1044*a88db0d1SZdenek Styblik static int
sunoem_cli_unbufmode_stop(FILE * f,struct termios * ts)1045*a88db0d1SZdenek Styblik sunoem_cli_unbufmode_stop(FILE *f, struct termios *ts)
1046*a88db0d1SZdenek Styblik {
1047*a88db0d1SZdenek Styblik 	int rc;
1048*a88db0d1SZdenek Styblik 
1049*a88db0d1SZdenek Styblik 	if ((rc = tcsetattr(fileno(f), TCSAFLUSH, ts))) {
1050*a88db0d1SZdenek Styblik 		return (rc);
1051*a88db0d1SZdenek Styblik 	}
1052*a88db0d1SZdenek Styblik 
1053*a88db0d1SZdenek Styblik 	return (0);
1054*a88db0d1SZdenek Styblik }
1055*a88db0d1SZdenek Styblik 
1056*a88db0d1SZdenek Styblik static int
ipmi_sunoem_cli(struct ipmi_intf * intf,int argc,char * argv[])1057*a88db0d1SZdenek Styblik ipmi_sunoem_cli(struct ipmi_intf * intf, int argc, char *argv[])
1058*a88db0d1SZdenek Styblik {
1059*a88db0d1SZdenek Styblik 	struct ipmi_rs *rsp;
1060*a88db0d1SZdenek Styblik 	struct ipmi_rq req;
1061*a88db0d1SZdenek Styblik 	sunoem_cli_msg_t cli_req;
1062*a88db0d1SZdenek Styblik 	sunoem_cli_msg_t *cli_rsp;
1063*a88db0d1SZdenek Styblik 	int arg_num = 0;
1064*a88db0d1SZdenek Styblik 	int arg_pos = 0;
1065*a88db0d1SZdenek Styblik 	time_t wait_time = 0;
1066*a88db0d1SZdenek Styblik 	int retries;
1067*a88db0d1SZdenek Styblik 	static uint8_t SunOemCliActingVersion = SUNOEM_CLI_VERSION;
1068*a88db0d1SZdenek Styblik 
1069*a88db0d1SZdenek Styblik 	unsigned short first_char = 0; /*first char on the line*/
1070*a88db0d1SZdenek Styblik 	struct termios orig_ts;
1071*a88db0d1SZdenek Styblik 	int error = 0;
1072*a88db0d1SZdenek Styblik 
1073*a88db0d1SZdenek Styblik 	time_t now = 0;
1074*a88db0d1SZdenek Styblik 	int delay = 0;
1075*a88db0d1SZdenek Styblik 
1076*a88db0d1SZdenek Styblik 	/* Prepare to open an SP shell session */
1077*a88db0d1SZdenek Styblik 	memset(&cli_req, 0, sizeof(cli_req));
1078*a88db0d1SZdenek Styblik 	cli_req.version = SunOemCliActingVersion;
1079*a88db0d1SZdenek Styblik 	cli_req.command_response = SUNOEM_CLI_CMD_OPEN;
1080*a88db0d1SZdenek Styblik 	if (argc > 0 && strcmp(argv[0], "force") == 0) {
1081*a88db0d1SZdenek Styblik 		cli_req.command_response = SUNOEM_CLI_CMD_FORCE;
1082*a88db0d1SZdenek Styblik 		argc--;
1083*a88db0d1SZdenek Styblik 		argv++;
1084*a88db0d1SZdenek Styblik 	}
1085*a88db0d1SZdenek Styblik 	memset(&req, 0, sizeof(req));
1086*a88db0d1SZdenek Styblik 	req.msg.netfn = IPMI_NETFN_SUNOEM;
1087*a88db0d1SZdenek Styblik 	req.msg.cmd = IPMI_SUNOEM_CLI;
1088*a88db0d1SZdenek Styblik 	req.msg.data = (uint8_t *) &cli_req;
1089*a88db0d1SZdenek Styblik 	req.msg.data_len = SUNOEM_CLI_HEADER + 1;
1090*a88db0d1SZdenek Styblik 	retries = 0;
1091*a88db0d1SZdenek Styblik 	while (1) {
1092*a88db0d1SZdenek Styblik 		cli_req.version = SunOemCliActingVersion;
1093*a88db0d1SZdenek Styblik 		rsp = intf->sendrecv(intf, &req);
1094*a88db0d1SZdenek Styblik 		if (rsp == NULL) {
1095*a88db0d1SZdenek Styblik 			lprintf(LOG_ERR, "Sun OEM cli command failed");
1096*a88db0d1SZdenek Styblik 			return (-1);
1097*a88db0d1SZdenek Styblik 		}
1098*a88db0d1SZdenek Styblik 		cli_rsp = (sunoem_cli_msg_t *) rsp->data;
1099*a88db0d1SZdenek Styblik 		if ((cli_rsp->command_response != 0) || (rsp->ccode != 0)) {
1100*a88db0d1SZdenek Styblik 			if (strncmp(cli_rsp->buf, SUNOEM_CLI_INVALID_VER_ERR,
1101*a88db0d1SZdenek Styblik 					sizeof(SUNOEM_CLI_INVALID_VER_ERR) - 1) == 0
1102*a88db0d1SZdenek Styblik 					|| strncmp(&(cli_rsp->buf[1]), SUNOEM_CLI_INVALID_VER_ERR,
1103*a88db0d1SZdenek Styblik 							sizeof(SUNOEM_CLI_INVALID_VER_ERR) - 1) == 0) {
1104*a88db0d1SZdenek Styblik 				if (SunOemCliActingVersion == SUNOEM_CLI_VERSION) {
1105*a88db0d1SZdenek Styblik 					/* Server doesn't support version SUNOEM_CLI_VERSION
1106*a88db0d1SZdenek Styblik 					 Fall back to legacy version, and try again*/
1107*a88db0d1SZdenek Styblik 					SunOemCliActingVersion = SUNOEM_CLI_LEGACY_VERSION;
1108*a88db0d1SZdenek Styblik 					continue;
1109*a88db0d1SZdenek Styblik 				}
1110*a88db0d1SZdenek Styblik 				/* Server doesn't support legacy version either */
1111*a88db0d1SZdenek Styblik 				lprintf(LOG_ERR, "Failed to connect: %s", cli_rsp->buf);
1112*a88db0d1SZdenek Styblik 				return (-1);
1113*a88db0d1SZdenek Styblik 			} else if (strncmp(cli_rsp->buf, SUNOEM_CLI_BUSY_ERR,
1114*a88db0d1SZdenek Styblik 					sizeof(SUNOEM_CLI_BUSY_ERR) - 1) == 0) {
1115*a88db0d1SZdenek Styblik 				if (retries++ < SUNOEM_CLI_MAX_RETRY) {
1116*a88db0d1SZdenek Styblik 					lprintf(LOG_INFO, "Failed to connect: %s, retrying",
1117*a88db0d1SZdenek Styblik 							cli_rsp->buf);
1118*a88db0d1SZdenek Styblik 					sleep(2);
1119*a88db0d1SZdenek Styblik 					continue;
1120*a88db0d1SZdenek Styblik 				}
1121*a88db0d1SZdenek Styblik 				lprintf(LOG_ERR, "Failed to connect: %s", cli_rsp->buf);
1122*a88db0d1SZdenek Styblik 				return (-1);
1123*a88db0d1SZdenek Styblik 			} else {
1124*a88db0d1SZdenek Styblik 				lprintf(LOG_ERR, "Failed to connect: %s", cli_rsp->buf);
1125*a88db0d1SZdenek Styblik 				return (-1);
1126*a88db0d1SZdenek Styblik 			}
1127*a88db0d1SZdenek Styblik 		}
1128*a88db0d1SZdenek Styblik 		break;
1129*a88db0d1SZdenek Styblik 	}
1130*a88db0d1SZdenek Styblik 	if (SunOemCliActingVersion == SUNOEM_CLI_SEQNUM_VERSION) {
1131*a88db0d1SZdenek Styblik 		/*
1132*a88db0d1SZdenek Styblik 		 * Bit 1 of seqnum is used as an alternating sequence number
1133*a88db0d1SZdenek Styblik 		 * to allow a server that supports it to detect when a retry is being sent from the host IPMI driver.
1134*a88db0d1SZdenek Styblik 		 * Typically when this occurs, the server's last response message would have been dropped.
1135*a88db0d1SZdenek Styblik 		 * Once the server detects this condition, it will know that it should retry sending the response.
1136*a88db0d1SZdenek Styblik 		 */
1137*a88db0d1SZdenek Styblik 		cli_req.seqnum ^= 0x1;
1138*a88db0d1SZdenek Styblik 	}
1139*a88db0d1SZdenek Styblik 	printf("Connected. Use ^D to exit.\n");
1140*a88db0d1SZdenek Styblik 	fflush(NULL);
1141*a88db0d1SZdenek Styblik 
1142*a88db0d1SZdenek Styblik 	/*
1143*a88db0d1SZdenek Styblik 	 * Remember the handle provided in the response, and issue a
1144*a88db0d1SZdenek Styblik 	 * series of "poll" commands to send and get data
1145*a88db0d1SZdenek Styblik 	 */
1146*a88db0d1SZdenek Styblik 	memcpy(cli_req.handle, cli_rsp->handle, 4);
1147*a88db0d1SZdenek Styblik 	cli_req.command_response = SUNOEM_CLI_CMD_POLL;
1148*a88db0d1SZdenek Styblik 	/*
1149*a88db0d1SZdenek Styblik 	 * If no arguments make input unbuffered and so interactive
1150*a88db0d1SZdenek Styblik 	 */
1151*a88db0d1SZdenek Styblik 	if (argc == 0) {
1152*a88db0d1SZdenek Styblik 		if (sunoem_cli_unbufmode_start(stdin, &orig_ts)) {
1153*a88db0d1SZdenek Styblik 			lprintf(LOG_ERR, "Failed to set interactive mode: %s",
1154*a88db0d1SZdenek Styblik 					strerror(errno));
1155*a88db0d1SZdenek Styblik 			return (-1);
1156*a88db0d1SZdenek Styblik 		}
1157*a88db0d1SZdenek Styblik 	}
1158*a88db0d1SZdenek Styblik 	while (rsp->ccode == 0 && cli_rsp->command_response == 0) {
1159*a88db0d1SZdenek Styblik 		int rc = 0;
1160*a88db0d1SZdenek Styblik 		int count = 0;
1161*a88db0d1SZdenek Styblik 		cli_req.buf[0] = '\0';
1162*a88db0d1SZdenek Styblik 		if (argc == 0) {
1163*a88db0d1SZdenek Styblik 			/*
1164*a88db0d1SZdenek Styblik 			 * Accept input from stdin. Use select so we don't hang if
1165*a88db0d1SZdenek Styblik 			 * there's no input to read. Select timeout is 500 msec.
1166*a88db0d1SZdenek Styblik 			 */
1167*a88db0d1SZdenek Styblik 			struct timeval tv = { 0, 500000 }; /* 500 msec */
1168*a88db0d1SZdenek Styblik 			fd_set rfds;
1169*a88db0d1SZdenek Styblik 			FD_ZERO(&rfds);
1170*a88db0d1SZdenek Styblik 			FD_SET(0, &rfds);
1171*a88db0d1SZdenek Styblik 			rc = select(1, &rfds, NULL, NULL, &tv);
1172*a88db0d1SZdenek Styblik 			if (rc < 0) {
1173*a88db0d1SZdenek Styblik 				/* Select returned an error so close and exit */
1174*a88db0d1SZdenek Styblik 				printf("Broken pipe\n");
1175*a88db0d1SZdenek Styblik 				cli_req.command_response = SUNOEM_CLI_CMD_CLOSE;
1176*a88db0d1SZdenek Styblik 			} else if (rc > 0) {
1177*a88db0d1SZdenek Styblik 				/* Read data from stdin */
1178*a88db0d1SZdenek Styblik 				count = read(0, cli_req.buf, 1 /* sizeof (cli_req.buf) - 1 */);
1179*a88db0d1SZdenek Styblik 				/*
1180*a88db0d1SZdenek Styblik 				 * If select said there was data but there was nothing to
1181*a88db0d1SZdenek Styblik 				 * read. This implies user hit ^D.
1182*a88db0d1SZdenek Styblik 				 * Also handle ^D input when pressed as first char at a new line.
1183*a88db0d1SZdenek Styblik 				 */
1184*a88db0d1SZdenek Styblik 				if (count <= 0 || (first_char && cli_req.buf[0] == C_CTL_D)) {
1185*a88db0d1SZdenek Styblik 					cli_req.command_response = SUNOEM_CLI_CMD_EOF;
1186*a88db0d1SZdenek Styblik 					count = 0;
1187*a88db0d1SZdenek Styblik 				}
1188*a88db0d1SZdenek Styblik 				first_char = cli_req.buf[0] == '\n' || cli_req.buf[0] == '\r';
1189*a88db0d1SZdenek Styblik 			}
1190*a88db0d1SZdenek Styblik 		} else {
1191*a88db0d1SZdenek Styblik 			/*
1192*a88db0d1SZdenek Styblik 			 * Get data from command line arguments
1193*a88db0d1SZdenek Styblik 			 */
1194*a88db0d1SZdenek Styblik 			now = time(NULL);
1195*a88db0d1SZdenek Styblik 			if (now < wait_time) {
1196*a88db0d1SZdenek Styblik 				/* Do nothing; we're waiting */
1197*a88db0d1SZdenek Styblik 			} else if (arg_num >= argc) {
1198*a88db0d1SZdenek Styblik 				/* Last arg was sent. Set EOF */
1199*a88db0d1SZdenek Styblik 				cli_req.command_response = SUNOEM_CLI_CMD_EOF;
1200*a88db0d1SZdenek Styblik 			} else if (strncmp(argv[arg_num], "@wait=", 6) == 0) {
1201*a88db0d1SZdenek Styblik 				/* This is a wait command */
1202*a88db0d1SZdenek Styblik 				char *s = &argv[arg_num][6];
1203*a88db0d1SZdenek Styblik 				delay = 0;
1204*a88db0d1SZdenek Styblik 				if (*s != '\0') {
1205*a88db0d1SZdenek Styblik 					if (str2int(s, &delay)) {
1206*a88db0d1SZdenek Styblik 						delay = 0;
1207*a88db0d1SZdenek Styblik 					}
1208*a88db0d1SZdenek Styblik 					if (delay < 0) {
1209*a88db0d1SZdenek Styblik 						delay = 0;
1210*a88db0d1SZdenek Styblik 					}
1211*a88db0d1SZdenek Styblik 				}
1212*a88db0d1SZdenek Styblik 				wait_time = now + delay;
1213*a88db0d1SZdenek Styblik 				arg_num++;
1214*a88db0d1SZdenek Styblik 			} else {
1215*a88db0d1SZdenek Styblik 				/*
1216*a88db0d1SZdenek Styblik 				 * Take data from args. It may be that the argument is larger
1217*a88db0d1SZdenek Styblik 				 * than the request buffer can hold. So pull off BUF_SIZE
1218*a88db0d1SZdenek Styblik 				 * number of characters at a time. When we've consumed the
1219*a88db0d1SZdenek Styblik 				 * entire arg, append a newline and advance to the next arg.
1220*a88db0d1SZdenek Styblik 				 */
1221*a88db0d1SZdenek Styblik 				int i;
1222*a88db0d1SZdenek Styblik 				char *s = argv[arg_num];
1223*a88db0d1SZdenek Styblik 				for (i = arg_pos;
1224*a88db0d1SZdenek Styblik 						s[i] != '\0' && count < (SUNOEM_CLI_BUF_SIZE - 2);
1225*a88db0d1SZdenek Styblik 						i++, count++) {
1226*a88db0d1SZdenek Styblik 					cli_req.buf[count] = s[i];
1227*a88db0d1SZdenek Styblik 				}
1228*a88db0d1SZdenek Styblik 				if (s[i] == '\0') {
1229*a88db0d1SZdenek Styblik 					/* Reached end of the arg string, so append a newline */
1230*a88db0d1SZdenek Styblik 					cli_req.buf[count++] = '\n';
1231*a88db0d1SZdenek Styblik 					/* Reset pos to 0 and advance to the next arg next time */
1232*a88db0d1SZdenek Styblik 					arg_pos = 0;
1233*a88db0d1SZdenek Styblik 					arg_num++;
1234*a88db0d1SZdenek Styblik 				} else {
1235*a88db0d1SZdenek Styblik 					/*
1236*a88db0d1SZdenek Styblik 					 * Otherwise, there's still more characters in the arg
1237*a88db0d1SZdenek Styblik 					 * to send, so remember where we left off
1238*a88db0d1SZdenek Styblik 					 */
1239*a88db0d1SZdenek Styblik 					arg_pos = i;
1240*a88db0d1SZdenek Styblik 				}
1241*a88db0d1SZdenek Styblik 			}
1242*a88db0d1SZdenek Styblik 		}
1243*a88db0d1SZdenek Styblik 		/*
1244*a88db0d1SZdenek Styblik 		 * Now send the clients's data (if any) and get data back from the
1245*a88db0d1SZdenek Styblik 		 * server. Loop while the server is giving us data until we suck
1246*a88db0d1SZdenek Styblik 		 * it dry.
1247*a88db0d1SZdenek Styblik 		 */
1248*a88db0d1SZdenek Styblik 		do {
1249*a88db0d1SZdenek Styblik 			cli_req.buf[count++] = '\0'; /* Terminate the string */
1250*a88db0d1SZdenek Styblik 			memset(&req, 0, sizeof(req));
1251*a88db0d1SZdenek Styblik 			req.msg.netfn = IPMI_NETFN_SUNOEM;
1252*a88db0d1SZdenek Styblik 			req.msg.cmd = 0x19;
1253*a88db0d1SZdenek Styblik 			req.msg.data = (uint8_t *) &cli_req;
1254*a88db0d1SZdenek Styblik 			req.msg.data_len = SUNOEM_CLI_HEADER + count;
1255*a88db0d1SZdenek Styblik 			for (retries = 0; retries <= SUNOEM_CLI_MAX_RETRY; retries++) {
1256*a88db0d1SZdenek Styblik 				rsp = intf->sendrecv(intf, &req);
1257*a88db0d1SZdenek Styblik 				if (rsp == NULL) {
1258*a88db0d1SZdenek Styblik 					lprintf(LOG_ERR, "Communication error.");
1259*a88db0d1SZdenek Styblik 					error = 1;
1260*a88db0d1SZdenek Styblik 					goto cleanup;
1261*a88db0d1SZdenek Styblik 				}
1262*a88db0d1SZdenek Styblik 				if (rsp->ccode == IPMI_CC_TIMEOUT) { /* Retry if timed out. */
1263*a88db0d1SZdenek Styblik 					if (retries == SUNOEM_CLI_MAX_RETRY) { /* If it's the last retry. */
1264*a88db0d1SZdenek Styblik 						lprintf(LOG_ERR, "Excessive timeout.");
1265*a88db0d1SZdenek Styblik 						error = 1;
1266*a88db0d1SZdenek Styblik 						goto cleanup;
1267*a88db0d1SZdenek Styblik 					}
1268*a88db0d1SZdenek Styblik 					continue;
1269*a88db0d1SZdenek Styblik 				}
1270*a88db0d1SZdenek Styblik 				break;
1271*a88db0d1SZdenek Styblik 			} /* for (retries = 0; retries <= SUNOEM_CLI_MAX_RETRY; retries++) */
1272*a88db0d1SZdenek Styblik 
1273*a88db0d1SZdenek Styblik 			if (SunOemCliActingVersion == SUNOEM_CLI_SEQNUM_VERSION) {
1274*a88db0d1SZdenek Styblik 				cli_req.seqnum ^= 0x1; /* Toggle sequence number after request is sent */
1275*a88db0d1SZdenek Styblik 			}
1276*a88db0d1SZdenek Styblik 
1277*a88db0d1SZdenek Styblik 			cli_rsp = (sunoem_cli_msg_t *) rsp->data;
1278*a88db0d1SZdenek Styblik 			/* Make sure response string is null terminated */
1279*a88db0d1SZdenek Styblik 			cli_rsp->buf[sizeof(cli_rsp->buf) - 1] = '\0';
1280*a88db0d1SZdenek Styblik 			printf("%s", cli_rsp->buf);
1281*a88db0d1SZdenek Styblik 			fflush(NULL); /* Flush partial lines to stdout */
1282*a88db0d1SZdenek Styblik 			count = 0; /* Don't re-send the client's data */
1283*a88db0d1SZdenek Styblik 			if (cli_req.command_response == SUNOEM_CLI_CMD_EOF
1284*a88db0d1SZdenek Styblik 					&& cli_rsp->command_response != 0 && rsp->ccode == 0) {
1285*a88db0d1SZdenek Styblik 				cli_rsp->command_response = 1;
1286*a88db0d1SZdenek Styblik 			}
1287*a88db0d1SZdenek Styblik 		} while (cli_rsp->command_response == 0 && cli_rsp->buf[0] != '\0');
1288*a88db0d1SZdenek Styblik 	}
1289*a88db0d1SZdenek Styblik 
1290*a88db0d1SZdenek Styblik cleanup:
1291*a88db0d1SZdenek Styblik 	/* Restore original input mode if cli was running interactively */
1292*a88db0d1SZdenek Styblik 	if (argc == 0) {
1293*a88db0d1SZdenek Styblik 		if (sunoem_cli_unbufmode_stop(stdin, &orig_ts)) {
1294*a88db0d1SZdenek Styblik 			lprintf(LOG_ERR, "Failed to restore interactive mode: %s",
1295*a88db0d1SZdenek Styblik 					strerror(errno));
1296*a88db0d1SZdenek Styblik 			return (-1);
1297*a88db0d1SZdenek Styblik 		}
1298*a88db0d1SZdenek Styblik 	}
1299*a88db0d1SZdenek Styblik 
1300*a88db0d1SZdenek Styblik 	return ((error == 0 && cli_rsp->command_response == SUNOEM_SUCCESS) ? 0 : -1);
1301*a88db0d1SZdenek Styblik }
1302*a88db0d1SZdenek Styblik #define ECHO_DATA_SIZE 64
1303*a88db0d1SZdenek Styblik 
1304*a88db0d1SZdenek Styblik #ifdef HAVE_PRAGMA_PACK
1305*a88db0d1SZdenek Styblik #pragma pack(push, 1)
1306*a88db0d1SZdenek Styblik #endif
1307*a88db0d1SZdenek Styblik typedef struct
1308*a88db0d1SZdenek Styblik {
1309*a88db0d1SZdenek Styblik 	uint16_t seq_num;
1310*a88db0d1SZdenek Styblik 	unsigned char data[ECHO_DATA_SIZE];
1311*a88db0d1SZdenek Styblik }__attribute__((packed)) sunoem_echo_msg_t;
1312*a88db0d1SZdenek Styblik #ifdef HAVE_PRAGMA_PACK
1313*a88db0d1SZdenek Styblik #pragma pack(pop)
1314*a88db0d1SZdenek Styblik #endif
1315*a88db0d1SZdenek Styblik 
1316*a88db0d1SZdenek Styblik /*
1317*a88db0d1SZdenek Styblik  * Send and receive X packets to the BMC. Each packet has a
1318*a88db0d1SZdenek Styblik  * payload size of (sunoem_echo_msg_t) bytes. Each packet is tagged with a
1319*a88db0d1SZdenek Styblik  * sequence number
1320*a88db0d1SZdenek Styblik  */
1321*a88db0d1SZdenek Styblik static int
ipmi_sunoem_echo(struct ipmi_intf * intf,int argc,char * argv[])1322*a88db0d1SZdenek Styblik ipmi_sunoem_echo(struct ipmi_intf * intf, int argc, char *argv[])
1323*a88db0d1SZdenek Styblik {
1324*a88db0d1SZdenek Styblik 	struct ipmi_rs *rsp;
1325*a88db0d1SZdenek Styblik 	struct ipmi_rq req;
1326*a88db0d1SZdenek Styblik 	sunoem_echo_msg_t echo_req;
1327*a88db0d1SZdenek Styblik 	sunoem_echo_msg_t *echo_rsp;
1328*a88db0d1SZdenek Styblik 	struct timeval start_time;
1329*a88db0d1SZdenek Styblik 	struct timeval end_time;
1330*a88db0d1SZdenek Styblik 
1331*a88db0d1SZdenek Styblik 	int rc = 0;
1332*a88db0d1SZdenek Styblik 	int received = 0;
1333*a88db0d1SZdenek Styblik 	int transmitted = 0;
1334*a88db0d1SZdenek Styblik 	int quiet_mode = 0;
1335*a88db0d1SZdenek Styblik 
1336*a88db0d1SZdenek Styblik 	uint16_t num, i, j;
1337*a88db0d1SZdenek Styblik 	uint32_t total_time, resp_time, min_time, max_time;
1338*a88db0d1SZdenek Styblik 
1339*a88db0d1SZdenek Styblik 	if (argc < 1) {
1340*a88db0d1SZdenek Styblik 		return (1);
1341*a88db0d1SZdenek Styblik 	}
1342*a88db0d1SZdenek Styblik 
1343*a88db0d1SZdenek Styblik 	if (argc == 2) {
1344*a88db0d1SZdenek Styblik 		if (*(argv[1]) == 'q') {
1345*a88db0d1SZdenek Styblik 			quiet_mode = 1;
1346*a88db0d1SZdenek Styblik 		} else {
1347*a88db0d1SZdenek Styblik 			lprintf(LOG_ERR, "Unknown option '%s' given.", argv[1]);
1348*a88db0d1SZdenek Styblik 			return (-1);
1349*a88db0d1SZdenek Styblik 		}
1350*a88db0d1SZdenek Styblik 	} else if (argc > 2) {
1351*a88db0d1SZdenek Styblik 		lprintf(LOG_ERR,
1352*a88db0d1SZdenek Styblik 				"Too many parameters given. See help for more information.");
1353*a88db0d1SZdenek Styblik 		return (-1);
1354*a88db0d1SZdenek Styblik 	}
1355*a88db0d1SZdenek Styblik 	/* The number of packets to send/receive */
1356*a88db0d1SZdenek Styblik 	if (str2ushort(argv[0], &num) != 0) {
1357*a88db0d1SZdenek Styblik 		lprintf(LOG_ERR,
1358*a88db0d1SZdenek Styblik 				"Given number of packets is either invalid or out of range.");
1359*a88db0d1SZdenek Styblik 		return (-1);
1360*a88db0d1SZdenek Styblik 	}
1361*a88db0d1SZdenek Styblik 
1362*a88db0d1SZdenek Styblik 	/* Fill in data packet */
1363*a88db0d1SZdenek Styblik 	for (i = 0; i < ECHO_DATA_SIZE; i++) {
1364*a88db0d1SZdenek Styblik 		echo_req.data[i] = (uint8_t) i;
1365*a88db0d1SZdenek Styblik 	}
1366*a88db0d1SZdenek Styblik 
1367*a88db0d1SZdenek Styblik 	memset(&req, 0, sizeof(req));
1368*a88db0d1SZdenek Styblik 	req.msg.netfn = IPMI_NETFN_SUNOEM;
1369*a88db0d1SZdenek Styblik 	req.msg.cmd = IPMI_SUNOEM_ECHO;
1370*a88db0d1SZdenek Styblik 	req.msg.data = (uint8_t *) &echo_req;
1371*a88db0d1SZdenek Styblik 	req.msg.data_len = sizeof(sunoem_echo_msg_t);
1372*a88db0d1SZdenek Styblik 	echo_req.seq_num = i;
1373*a88db0d1SZdenek Styblik 	min_time = INT_MAX;
1374*a88db0d1SZdenek Styblik 	max_time = 0;
1375*a88db0d1SZdenek Styblik 	total_time = 0;
1376*a88db0d1SZdenek Styblik 	for (i = 0; i < num; i++) {
1377*a88db0d1SZdenek Styblik 		echo_req.seq_num = i;
1378*a88db0d1SZdenek Styblik 		transmitted++;
1379*a88db0d1SZdenek Styblik 		gettimeofday(&start_time, NULL);
1380*a88db0d1SZdenek Styblik 		rsp = intf->sendrecv(intf, &req);
1381*a88db0d1SZdenek Styblik 		gettimeofday(&end_time, NULL);
1382*a88db0d1SZdenek Styblik 		resp_time = ((end_time.tv_sec - start_time.tv_sec) * 1000)
1383*a88db0d1SZdenek Styblik 				+ ((end_time.tv_usec - start_time.tv_usec) / 1000);
1384*a88db0d1SZdenek Styblik 		if ((rsp == NULL) || (rsp->ccode != 0)) {
1385*a88db0d1SZdenek Styblik 			lprintf(LOG_ERR, "Sun OEM echo command failed. Seq # %d",
1386*a88db0d1SZdenek Styblik 					echo_req.seq_num);
1387*a88db0d1SZdenek Styblik 			rc = (-2);
1388*a88db0d1SZdenek Styblik 			break;
1389*a88db0d1SZdenek Styblik 		}
1390*a88db0d1SZdenek Styblik 		echo_rsp = (sunoem_echo_msg_t *) rsp->data;
1391*a88db0d1SZdenek Styblik 
1392*a88db0d1SZdenek Styblik 		/* Test if sequence # is valid */
1393*a88db0d1SZdenek Styblik 		if (echo_rsp->seq_num != echo_req.seq_num) {
1394*a88db0d1SZdenek Styblik 			printf("Invalid Seq # Expecting %d Received %d\n", echo_req.seq_num,
1395*a88db0d1SZdenek Styblik 					echo_rsp->seq_num);
1396*a88db0d1SZdenek Styblik 			rc = (-2);
1397*a88db0d1SZdenek Styblik 			break;
1398*a88db0d1SZdenek Styblik 		}
1399*a88db0d1SZdenek Styblik 
1400*a88db0d1SZdenek Styblik 		/* Test if response length is valid */
1401*a88db0d1SZdenek Styblik 		if (rsp->session.msglen == req.msg.data_len) {
1402*a88db0d1SZdenek Styblik 			printf("Invalid payload size for seq # %d. "
1403*a88db0d1SZdenek Styblik 					"Expecting %d Received %d\n", echo_rsp->seq_num,
1404*a88db0d1SZdenek Styblik 					req.msg.data_len, rsp->session.msglen);
1405*a88db0d1SZdenek Styblik 			rc = (-2);
1406*a88db0d1SZdenek Styblik 			break;
1407*a88db0d1SZdenek Styblik 		}
1408*a88db0d1SZdenek Styblik 
1409*a88db0d1SZdenek Styblik 		/* Test if the data is valid */
1410*a88db0d1SZdenek Styblik 		for (j = 0; j < ECHO_DATA_SIZE; j++) {
1411*a88db0d1SZdenek Styblik 			if (echo_rsp->data[j] != j) {
1412*a88db0d1SZdenek Styblik 				printf("Corrupt data packet. Seq # %d Offset %d\n",
1413*a88db0d1SZdenek Styblik 						echo_rsp->seq_num, j);
1414*a88db0d1SZdenek Styblik 				break;
1415*a88db0d1SZdenek Styblik 			}
1416*a88db0d1SZdenek Styblik 		} /* for (j = 0; j < ECHO_DATA_SIZE; j++) */
1417*a88db0d1SZdenek Styblik 
1418*a88db0d1SZdenek Styblik 		/* If the for loop terminated early - data is corrupt */
1419*a88db0d1SZdenek Styblik 		if (j != ECHO_DATA_SIZE) {
1420*a88db0d1SZdenek Styblik 			rc = (-2);
1421*a88db0d1SZdenek Styblik 			break;
1422*a88db0d1SZdenek Styblik 		}
1423*a88db0d1SZdenek Styblik 
1424*a88db0d1SZdenek Styblik 		/* cumalative time */
1425*a88db0d1SZdenek Styblik 		total_time += resp_time;
1426*a88db0d1SZdenek Styblik 
1427*a88db0d1SZdenek Styblik 		/* min time */
1428*a88db0d1SZdenek Styblik 		if (resp_time < min_time) {
1429*a88db0d1SZdenek Styblik 			min_time = resp_time;
1430*a88db0d1SZdenek Styblik 		}
1431*a88db0d1SZdenek Styblik 
1432*a88db0d1SZdenek Styblik 		/* max time */
1433*a88db0d1SZdenek Styblik 		if (resp_time > max_time) {
1434*a88db0d1SZdenek Styblik 			max_time = resp_time;
1435*a88db0d1SZdenek Styblik 		}
1436*a88db0d1SZdenek Styblik 
1437*a88db0d1SZdenek Styblik 		received++;
1438*a88db0d1SZdenek Styblik 		if (!quiet_mode) {
1439*a88db0d1SZdenek Styblik 			printf("Receive %u Bytes - Seq. # %d time=%d ms\n",
1440*a88db0d1SZdenek Styblik 					sizeof(sunoem_echo_msg_t), echo_rsp->seq_num, resp_time);
1441*a88db0d1SZdenek Styblik 		}
1442*a88db0d1SZdenek Styblik 	} /* for (i = 0; i < num; i++) */
1443*a88db0d1SZdenek Styblik 	printf("%d packets transmitted, %d packets received\n", transmitted,
1444*a88db0d1SZdenek Styblik 			received);
1445*a88db0d1SZdenek Styblik 	if (received) {
1446*a88db0d1SZdenek Styblik 		printf("round-trip min/avg/max = %d/%d/%d ms\n", min_time,
1447*a88db0d1SZdenek Styblik 				total_time / received, max_time);
1448*a88db0d1SZdenek Styblik 	}
1449*a88db0d1SZdenek Styblik 
1450*a88db0d1SZdenek Styblik 	return (rc);
1451*a88db0d1SZdenek Styblik } /* ipmi_sunoem_echo(...) */
1452*a88db0d1SZdenek Styblik 
1453*a88db0d1SZdenek Styblik #ifdef HAVE_PRAGMA_PACK
1454*a88db0d1SZdenek Styblik #pragma pack(push, 1)
1455*a88db0d1SZdenek Styblik #endif
1456*a88db0d1SZdenek Styblik typedef struct
1457*a88db0d1SZdenek Styblik {
1458*a88db0d1SZdenek Styblik 	unsigned char oem_record_ver_num;
1459*a88db0d1SZdenek Styblik 	unsigned char major;
1460*a88db0d1SZdenek Styblik 	unsigned char minor;
1461*a88db0d1SZdenek Styblik 	unsigned char update;
1462*a88db0d1SZdenek Styblik 	unsigned char micro;
1463*a88db0d1SZdenek Styblik 	char nano[10];
1464*a88db0d1SZdenek Styblik 	char revision[10];
1465*a88db0d1SZdenek Styblik 	char version[40];
1466*a88db0d1SZdenek Styblik 	/*
1467*a88db0d1SZdenek Styblik 	 * When adding new fields (using the spare bytes),
1468*a88db0d1SZdenek Styblik 	 * add it immediately after the spare field to
1469*a88db0d1SZdenek Styblik 	 * ensure backward compatability.
1470*a88db0d1SZdenek Styblik 	 *
1471*a88db0d1SZdenek Styblik 	 * e.g.   char version[40];
1472*a88db0d1SZdenek Styblik 	 *        unsigned char spare[11];
1473*a88db0d1SZdenek Styblik 	 *        int new_item;
1474*a88db0d1SZdenek Styblik 	 *    } sunoem_version_response_t;
1475*a88db0d1SZdenek Styblik 	 */
1476*a88db0d1SZdenek Styblik 	unsigned char spare[15];
1477*a88db0d1SZdenek Styblik }__attribute__((packed)) sunoem_version_response_t;
1478*a88db0d1SZdenek Styblik #ifdef HAVE_PRAGMA_PACK
1479*a88db0d1SZdenek Styblik #pragma pack(pop)
1480*a88db0d1SZdenek Styblik #endif
1481*a88db0d1SZdenek Styblik 
1482*a88db0d1SZdenek Styblik typedef struct
1483*a88db0d1SZdenek Styblik {
1484*a88db0d1SZdenek Styblik 	unsigned char major;
1485*a88db0d1SZdenek Styblik 	unsigned char minor;
1486*a88db0d1SZdenek Styblik 	unsigned char update;
1487*a88db0d1SZdenek Styblik 	unsigned char micro;
1488*a88db0d1SZdenek Styblik } supported_version_t;
1489*a88db0d1SZdenek Styblik 
1490*a88db0d1SZdenek Styblik static int
ipmi_sunoem_getversion(struct ipmi_intf * intf,sunoem_version_response_t ** version_rsp)1491*a88db0d1SZdenek Styblik ipmi_sunoem_getversion(struct ipmi_intf * intf,
1492*a88db0d1SZdenek Styblik 		sunoem_version_response_t **version_rsp)
1493*a88db0d1SZdenek Styblik {
1494*a88db0d1SZdenek Styblik 	struct ipmi_rs *rsp;
1495*a88db0d1SZdenek Styblik 	struct ipmi_rq req;
1496*a88db0d1SZdenek Styblik 
1497*a88db0d1SZdenek Styblik 	memset(&req, 0, sizeof(req));
1498*a88db0d1SZdenek Styblik 	req.msg.netfn = IPMI_NETFN_SUNOEM;
1499*a88db0d1SZdenek Styblik 	req.msg.cmd = IPMI_SUNOEM_VERSION;
1500*a88db0d1SZdenek Styblik 	req.msg.data = NULL;
1501*a88db0d1SZdenek Styblik 	req.msg.data_len = 0;
1502*a88db0d1SZdenek Styblik 	rsp = intf->sendrecv(intf, &req);
1503*a88db0d1SZdenek Styblik 
1504*a88db0d1SZdenek Styblik 	if (rsp == NULL) {
1505*a88db0d1SZdenek Styblik 		lprintf(LOG_ERR, "Sun OEM Get SP Version Failed.");
1506*a88db0d1SZdenek Styblik 		return (-1);
1507*a88db0d1SZdenek Styblik 	}
1508*a88db0d1SZdenek Styblik 	if (rsp->ccode != 0) {
1509*a88db0d1SZdenek Styblik 		lprintf(LOG_ERR, "Sun OEM Get SP Version Failed: %d", rsp->ccode);
1510*a88db0d1SZdenek Styblik 		return (-1);
1511*a88db0d1SZdenek Styblik 	}
1512*a88db0d1SZdenek Styblik 
1513*a88db0d1SZdenek Styblik 	*version_rsp = (sunoem_version_response_t *) rsp->data;
1514*a88db0d1SZdenek Styblik 
1515*a88db0d1SZdenek Styblik 	return (0);
1516*a88db0d1SZdenek Styblik }
1517*a88db0d1SZdenek Styblik 
1518*a88db0d1SZdenek Styblik static void
ipmi_sunoem_print_required_version(const supported_version_t * supp_ver)1519*a88db0d1SZdenek Styblik ipmi_sunoem_print_required_version(const supported_version_t* supp_ver)
1520*a88db0d1SZdenek Styblik {
1521*a88db0d1SZdenek Styblik 	lprintf(LOG_ERR, "Command is not supported by this version of ILOM,"
1522*a88db0d1SZdenek Styblik 			" required at least: %d.%d.%d.%d", supp_ver->major, supp_ver->minor,
1523*a88db0d1SZdenek Styblik 			supp_ver->update, supp_ver->micro);
1524*a88db0d1SZdenek Styblik }
1525*a88db0d1SZdenek Styblik 
1526*a88db0d1SZdenek Styblik /*
1527*a88db0d1SZdenek Styblik  * Function checks current version result against required version.
1528*a88db0d1SZdenek Styblik  * Returns:
1529*a88db0d1SZdenek Styblik  *  - negative value if current ILOM version is smaller than required or
1530*a88db0d1SZdenek Styblik  *    in case of error
1531*a88db0d1SZdenek Styblik  *  - positive value if current ILOM version is greater than required
1532*a88db0d1SZdenek Styblik  *  - 0 if there is an exact ILOM version match
1533*a88db0d1SZdenek Styblik  */
1534*a88db0d1SZdenek Styblik static int
ipmi_sunoem_checkversion(struct ipmi_intf * intf,supported_version_t * supp_ver)1535*a88db0d1SZdenek Styblik ipmi_sunoem_checkversion(struct ipmi_intf * intf, supported_version_t* supp_ver)
1536*a88db0d1SZdenek Styblik {
1537*a88db0d1SZdenek Styblik 	sunoem_version_response_t *version_rsp;
1538*a88db0d1SZdenek Styblik 	int i = 1;
1539*a88db0d1SZdenek Styblik 
1540*a88db0d1SZdenek Styblik 	if (ipmi_sunoem_getversion(intf, &version_rsp)) {
1541*a88db0d1SZdenek Styblik 		lprintf(LOG_ERR, "Unable to get ILOM version");
1542*a88db0d1SZdenek Styblik 		return (-1);
1543*a88db0d1SZdenek Styblik 	}
1544*a88db0d1SZdenek Styblik 
1545*a88db0d1SZdenek Styblik 	if (version_rsp->major < supp_ver->major) return (-i);
1546*a88db0d1SZdenek Styblik 	if (version_rsp->major > supp_ver->major) return (i);
1547*a88db0d1SZdenek Styblik 	/*version_rsp->major == supp_ver->major*/
1548*a88db0d1SZdenek Styblik 	++i;
1549*a88db0d1SZdenek Styblik 
1550*a88db0d1SZdenek Styblik 	if (version_rsp->minor < supp_ver->minor) return (-i);
1551*a88db0d1SZdenek Styblik 	if (version_rsp->minor > supp_ver->minor) return (i);
1552*a88db0d1SZdenek Styblik 	/*version_rsp->minor == supp_ver->minor*/
1553*a88db0d1SZdenek Styblik 	++i;
1554*a88db0d1SZdenek Styblik 
1555*a88db0d1SZdenek Styblik 	if (version_rsp->update < supp_ver->update) return (-i);
1556*a88db0d1SZdenek Styblik 	if (version_rsp->update > supp_ver->update) return (i);
1557*a88db0d1SZdenek Styblik 	/*version_rsp->update == supp_ver->update*/
1558*a88db0d1SZdenek Styblik 	++i;
1559*a88db0d1SZdenek Styblik 
1560*a88db0d1SZdenek Styblik 	if (version_rsp->micro < supp_ver->micro) return (-i);
1561*a88db0d1SZdenek Styblik 	if (version_rsp->micro > supp_ver->micro) return (i);
1562*a88db0d1SZdenek Styblik 	/*version_rsp->micro == supp_ver->micro*/
1563*a88db0d1SZdenek Styblik 
1564*a88db0d1SZdenek Styblik 	return (0);
1565*a88db0d1SZdenek Styblik }
1566*a88db0d1SZdenek Styblik 
1567*a88db0d1SZdenek Styblik /*
1568*a88db0d1SZdenek Styblik  * Extract the SP version data including
1569*a88db0d1SZdenek Styblik  * - major #
1570*a88db0d1SZdenek Styblik  * - minor #
1571*a88db0d1SZdenek Styblik  * - update #
1572*a88db0d1SZdenek Styblik  * - micro #
1573*a88db0d1SZdenek Styblik  * - nano #
1574*a88db0d1SZdenek Styblik  * - Revision/Build #
1575*a88db0d1SZdenek Styblik  */
1576*a88db0d1SZdenek Styblik static int
ipmi_sunoem_version(struct ipmi_intf * intf)1577*a88db0d1SZdenek Styblik ipmi_sunoem_version(struct ipmi_intf * intf)
1578*a88db0d1SZdenek Styblik {
1579*a88db0d1SZdenek Styblik 	sunoem_version_response_t *version_rsp;
1580*a88db0d1SZdenek Styblik 	int rc = ipmi_sunoem_getversion(intf, &version_rsp);
1581*a88db0d1SZdenek Styblik 
1582*a88db0d1SZdenek Styblik 	if (!rc) {
1583*a88db0d1SZdenek Styblik 		printf("Version: %s\n", version_rsp->version);
1584*a88db0d1SZdenek Styblik 	}
1585*a88db0d1SZdenek Styblik 
1586*a88db0d1SZdenek Styblik 	return (rc);
1587*a88db0d1SZdenek Styblik }
1588*a88db0d1SZdenek Styblik 
1589*a88db0d1SZdenek Styblik /*
1590*a88db0d1SZdenek Styblik  * IPMI Max string length is 16 bytes
1591*a88db0d1SZdenek Styblik  * define in usr/src/common/include/ami/IPMI_SDRRecord.h
1592*a88db0d1SZdenek Styblik  */
1593*a88db0d1SZdenek Styblik #define MAX_ID_STR_LEN  16
1594*a88db0d1SZdenek Styblik #define MAX_SUNOEM_NAC_SIZE 64
1595*a88db0d1SZdenek Styblik #define LUAPI_MAX_OBJ_PATH_LEN 256
1596*a88db0d1SZdenek Styblik #define LUAPI_MAX_OBJ_VAL_LEN 1024
1597*a88db0d1SZdenek Styblik 
1598*a88db0d1SZdenek Styblik #ifdef HAVE_PRAGMA_PACK
1599*a88db0d1SZdenek Styblik #pragma pack(push, 1)
1600*a88db0d1SZdenek Styblik #endif
1601*a88db0d1SZdenek Styblik typedef struct
1602*a88db0d1SZdenek Styblik {
1603*a88db0d1SZdenek Styblik 	unsigned char seq_num;
1604*a88db0d1SZdenek Styblik 	char nac_name[MAX_SUNOEM_NAC_SIZE];
1605*a88db0d1SZdenek Styblik }__attribute__((packed)) sunoem_nacname_t;
1606*a88db0d1SZdenek Styblik #ifdef HAVE_PRAGMA_PACK
1607*a88db0d1SZdenek Styblik #pragma pack(pop)
1608*a88db0d1SZdenek Styblik #endif
1609*a88db0d1SZdenek Styblik 
1610*a88db0d1SZdenek Styblik /*
1611*a88db0d1SZdenek Styblik  * Retrieve the full NAC name of the IPMI target.
1612*a88db0d1SZdenek Styblik  *
1613*a88db0d1SZdenek Styblik  * The returned nac name may be larger than the payload size.
1614*a88db0d1SZdenek Styblik  * In which case, it make take several request/payload to retrieve
1615*a88db0d1SZdenek Styblik  * the entire full path name
1616*a88db0d1SZdenek Styblik  *
1617*a88db0d1SZdenek Styblik  * The initial seq_num is set to 0. If the return seq_num is incremented,
1618*a88db0d1SZdenek Styblik  * only the 1st 72 bytes of the nac name is returned and the caller
1619*a88db0d1SZdenek Styblik  * needs to get the next set of string data.
1620*a88db0d1SZdenek Styblik  * If the returned seq_num is identical to the input seq_num, all data
1621*a88db0d1SZdenek Styblik  * has been returned.
1622*a88db0d1SZdenek Styblik  */
1623*a88db0d1SZdenek Styblik static int
ipmi_sunoem_nacname(struct ipmi_intf * intf,int argc,char * argv[])1624*a88db0d1SZdenek Styblik ipmi_sunoem_nacname(struct ipmi_intf * intf, int argc, char *argv[])
1625*a88db0d1SZdenek Styblik {
1626*a88db0d1SZdenek Styblik 	struct ipmi_rs *rsp;
1627*a88db0d1SZdenek Styblik 	struct ipmi_rq req;
1628*a88db0d1SZdenek Styblik 	sunoem_nacname_t nacname_req;
1629*a88db0d1SZdenek Styblik 	sunoem_nacname_t *nacname_rsp;
1630*a88db0d1SZdenek Styblik 	char full_nac_name[LUAPI_MAX_OBJ_PATH_LEN];
1631*a88db0d1SZdenek Styblik 
1632*a88db0d1SZdenek Styblik 	if (argc < 1) {
1633*a88db0d1SZdenek Styblik 		return (1);
1634*a88db0d1SZdenek Styblik 	}
1635*a88db0d1SZdenek Styblik 
1636*a88db0d1SZdenek Styblik 	if (strlen(argv[0]) > MAX_ID_STR_LEN) {
1637*a88db0d1SZdenek Styblik 		lprintf(LOG_ERR,
1638*a88db0d1SZdenek Styblik 				"Sun OEM nacname command failed: Max size on IPMI name");
1639*a88db0d1SZdenek Styblik 		return (-1);
1640*a88db0d1SZdenek Styblik 	}
1641*a88db0d1SZdenek Styblik 
1642*a88db0d1SZdenek Styblik 	nacname_req.seq_num = 0;
1643*a88db0d1SZdenek Styblik 	strcpy(nacname_req.nac_name, argv[0]);
1644*a88db0d1SZdenek Styblik 
1645*a88db0d1SZdenek Styblik 	full_nac_name[0] = '\0';
1646*a88db0d1SZdenek Styblik 	while (1) {
1647*a88db0d1SZdenek Styblik 		memset(&req, 0, sizeof(req));
1648*a88db0d1SZdenek Styblik 		req.msg.netfn = IPMI_NETFN_SUNOEM;
1649*a88db0d1SZdenek Styblik 		req.msg.cmd = IPMI_SUNOEM_NACNAME;
1650*a88db0d1SZdenek Styblik 		req.msg.data = (uint8_t *) &nacname_req;
1651*a88db0d1SZdenek Styblik 		req.msg.data_len = sizeof(sunoem_nacname_t);
1652*a88db0d1SZdenek Styblik 		rsp = intf->sendrecv(intf, &req);
1653*a88db0d1SZdenek Styblik 
1654*a88db0d1SZdenek Styblik 		if (rsp == NULL) {
1655*a88db0d1SZdenek Styblik 			lprintf(LOG_ERR, "Sun OEM nacname command failed.");
1656*a88db0d1SZdenek Styblik 			return (-1);
1657*a88db0d1SZdenek Styblik 		}
1658*a88db0d1SZdenek Styblik 		if (rsp->ccode != 0) {
1659*a88db0d1SZdenek Styblik 			lprintf(LOG_ERR, "Sun OEM nacname command failed: %d", rsp->ccode);
1660*a88db0d1SZdenek Styblik 			return (-1);
1661*a88db0d1SZdenek Styblik 		}
1662*a88db0d1SZdenek Styblik 
1663*a88db0d1SZdenek Styblik 		nacname_rsp = (sunoem_nacname_t *) rsp->data;
1664*a88db0d1SZdenek Styblik 		strncat(full_nac_name, nacname_rsp->nac_name, MAX_SUNOEM_NAC_SIZE);
1665*a88db0d1SZdenek Styblik 
1666*a88db0d1SZdenek Styblik 		/*
1667*a88db0d1SZdenek Styblik 		 * break out of the loop if there is no more data
1668*a88db0d1SZdenek Styblik 		 * In most cases, if not all, the NAC name fits into a
1669*a88db0d1SZdenek Styblik 		 * single payload
1670*a88db0d1SZdenek Styblik 		 */
1671*a88db0d1SZdenek Styblik 		if (nacname_req.seq_num == nacname_rsp->seq_num) {
1672*a88db0d1SZdenek Styblik 			break;
1673*a88db0d1SZdenek Styblik 		}
1674*a88db0d1SZdenek Styblik 
1675*a88db0d1SZdenek Styblik 		/* Get the next seq of string bytes */
1676*a88db0d1SZdenek Styblik 		nacname_req.seq_num = nacname_rsp->seq_num;
1677*a88db0d1SZdenek Styblik 
1678*a88db0d1SZdenek Styblik 		/* Check if we exceeded the size of the full nac name */
1679*a88db0d1SZdenek Styblik 		if ((nacname_req.seq_num * MAX_SUNOEM_NAC_SIZE) > LUAPI_MAX_OBJ_PATH_LEN) {
1680*a88db0d1SZdenek Styblik 			lprintf(LOG_ERR,
1681*a88db0d1SZdenek Styblik 					"Sun OEM nacname command failed: invalid path length");
1682*a88db0d1SZdenek Styblik 			return (-1);
1683*a88db0d1SZdenek Styblik 		}
1684*a88db0d1SZdenek Styblik 	}
1685*a88db0d1SZdenek Styblik 
1686*a88db0d1SZdenek Styblik 	printf("NAC Name: %s\n", full_nac_name);
1687*a88db0d1SZdenek Styblik 	return (0);
1688*a88db0d1SZdenek Styblik }
1689*a88db0d1SZdenek Styblik 
1690*a88db0d1SZdenek Styblik /* Constants used by ipmi_sunoem_getval */
1691*a88db0d1SZdenek Styblik #define MAX_SUNOEM_VAL_PAYLOAD 79
1692*a88db0d1SZdenek Styblik #define MAX_SUNOEM_VAL_COMPACT_PAYLOAD 56
1693*a88db0d1SZdenek Styblik 
1694*a88db0d1SZdenek Styblik /*
1695*a88db0d1SZdenek Styblik  * SUNOEM GET/SET LUAPI Commands
1696*a88db0d1SZdenek Styblik  *
1697*a88db0d1SZdenek Styblik  * SUNOEM_REQ_VAL - Request LUAPI Property Value
1698*a88db0d1SZdenek Styblik  * SUNOEM_GET_VAL - Return the value from  SUNOEM_REQ_VAL
1699*a88db0d1SZdenek Styblik  * SUNOEM_SET_VAL - Set the LUAPI Property value
1700*a88db0d1SZdenek Styblik  * SUNOEM_GET_STATUS - Return the Status from SUNOEM_SET_VAL
1701*a88db0d1SZdenek Styblik  */
1702*a88db0d1SZdenek Styblik #define SUNOEM_REQ_VAL 1
1703*a88db0d1SZdenek Styblik #define SUNOEM_GET_VAL 2
1704*a88db0d1SZdenek Styblik #define SUNOEM_SET_VAL 3
1705*a88db0d1SZdenek Styblik #define SUNOEM_GET_STATUS 4
1706*a88db0d1SZdenek Styblik 
1707*a88db0d1SZdenek Styblik /* Status Code */
1708*a88db0d1SZdenek Styblik #define SUNOEM_REQ_RECV 1
1709*a88db0d1SZdenek Styblik #define SUNOEM_REQ_FAILED 2
1710*a88db0d1SZdenek Styblik #define SUNOEM_DATA_READY 3
1711*a88db0d1SZdenek Styblik #define SUNOEM_DATA_NOT_READY 4
1712*a88db0d1SZdenek Styblik #define SUNOEM_DATA_NOT_FOUND 5
1713*a88db0d1SZdenek Styblik #define GETVAL_MAX_RETRIES 5
1714*a88db0d1SZdenek Styblik 
1715*a88db0d1SZdenek Styblik /* Parameter type Codes */
1716*a88db0d1SZdenek Styblik #define SUNOEM_LUAPI_TARGET 0
1717*a88db0d1SZdenek Styblik #define SUNOEM_LUAPI_VALUE  1
1718*a88db0d1SZdenek Styblik 
1719*a88db0d1SZdenek Styblik #ifdef HAVE_PRAGMA_PACK
1720*a88db0d1SZdenek Styblik #pragma pack(push, 1)
1721*a88db0d1SZdenek Styblik #endif
1722*a88db0d1SZdenek Styblik typedef struct
1723*a88db0d1SZdenek Styblik {
1724*a88db0d1SZdenek Styblik 	unsigned char cmd_code;
1725*a88db0d1SZdenek Styblik 	unsigned char luapi_value[MAX_SUNOEM_VAL_PAYLOAD];
1726*a88db0d1SZdenek Styblik }__attribute__((packed)) sunoem_getval_t;
1727*a88db0d1SZdenek Styblik #ifdef HAVE_PRAGMA_PACK
1728*a88db0d1SZdenek Styblik #pragma pack(pop)
1729*a88db0d1SZdenek Styblik #endif
1730*a88db0d1SZdenek Styblik 
1731*a88db0d1SZdenek Styblik /*
1732*a88db0d1SZdenek Styblik  * REQUEST PAYLOAD
1733*a88db0d1SZdenek Styblik  *
1734*a88db0d1SZdenek Styblik  * cmd_code - SUNOEM GET/SET LUAPI Cmds - see above
1735*a88db0d1SZdenek Styblik  * param_type: 0: luapi_data contains the luapi property name
1736*a88db0d1SZdenek Styblik  *             1: luapi_data contains the luapi value
1737*a88db0d1SZdenek Styblik  * luapi_data: Either luapi property name or value
1738*a88db0d1SZdenek Styblik  * tid: Transaction ID. If 0. This is the initial request for the
1739*a88db0d1SZdenek Styblik  *      param_type. If tid > 0, this luapi_data string is a concatenation
1740*a88db0d1SZdenek Styblik  *      of the previous request. Handle cases where the LUAPI target name
1741*a88db0d1SZdenek Styblik  *      or value is > MAX_SUNOEM_VAL_COMPACT_PAYLOAD
1742*a88db0d1SZdenek Styblik  * eof: If non zero, this is the last payload for the request
1743*a88db0d1SZdenek Styblik  */
1744*a88db0d1SZdenek Styblik #ifdef HAVE_PRAGMA_PACK
1745*a88db0d1SZdenek Styblik #pragma pack(push, 1)
1746*a88db0d1SZdenek Styblik #endif
1747*a88db0d1SZdenek Styblik typedef struct
1748*a88db0d1SZdenek Styblik {
1749*a88db0d1SZdenek Styblik 	unsigned char cmd_code;
1750*a88db0d1SZdenek Styblik 	unsigned char param_type;
1751*a88db0d1SZdenek Styblik 	unsigned char tid;
1752*a88db0d1SZdenek Styblik 	unsigned char eof;
1753*a88db0d1SZdenek Styblik 	char luapi_data[MAX_SUNOEM_VAL_COMPACT_PAYLOAD];
1754*a88db0d1SZdenek Styblik }__attribute__((packed)) sunoem_setval_t;
1755*a88db0d1SZdenek Styblik #ifdef HAVE_PRAGMA_PACK
1756*a88db0d1SZdenek Styblik #pragma pack(pop)
1757*a88db0d1SZdenek Styblik #endif
1758*a88db0d1SZdenek Styblik 
1759*a88db0d1SZdenek Styblik /*
1760*a88db0d1SZdenek Styblik  * RESPONSE PAYLOAD
1761*a88db0d1SZdenek Styblik  *
1762*a88db0d1SZdenek Styblik  * status_code - see above for code definitions
1763*a88db0d1SZdenek Styblik  * tid - transaction ID - assigned ny the ILOM stack
1764*a88db0d1SZdenek Styblik  */
1765*a88db0d1SZdenek Styblik #ifdef HAVE_PRAGMA_PACK
1766*a88db0d1SZdenek Styblik #pragma pack(push, 1)
1767*a88db0d1SZdenek Styblik #endif
1768*a88db0d1SZdenek Styblik typedef struct
1769*a88db0d1SZdenek Styblik {
1770*a88db0d1SZdenek Styblik 	unsigned char status_code;
1771*a88db0d1SZdenek Styblik 	unsigned char tid;
1772*a88db0d1SZdenek Styblik }__attribute__((packed)) sunoem_setval_resp_t;
1773*a88db0d1SZdenek Styblik #ifdef HAVE_PRAGMA_PACK
1774*a88db0d1SZdenek Styblik #pragma pack(pop)
1775*a88db0d1SZdenek Styblik #endif
1776*a88db0d1SZdenek Styblik 
1777*a88db0d1SZdenek Styblik /*
1778*a88db0d1SZdenek Styblik  * Return the ILOM target property value
1779*a88db0d1SZdenek Styblik  */
1780*a88db0d1SZdenek Styblik static int
ipmi_sunoem_getval(struct ipmi_intf * intf,int argc,char * argv[])1781*a88db0d1SZdenek Styblik ipmi_sunoem_getval(struct ipmi_intf * intf, int argc, char *argv[])
1782*a88db0d1SZdenek Styblik {
1783*a88db0d1SZdenek Styblik 	struct ipmi_rs *rsp;
1784*a88db0d1SZdenek Styblik 	struct ipmi_rq req;
1785*a88db0d1SZdenek Styblik 	sunoem_getval_t getval_req;
1786*a88db0d1SZdenek Styblik 	sunoem_getval_t *getval_rsp;
1787*a88db0d1SZdenek Styblik 	int i;
1788*a88db0d1SZdenek Styblik 
1789*a88db0d1SZdenek Styblik 	const char* sp_path = "/SP";
1790*a88db0d1SZdenek Styblik 	supported_version_t supp_ver = { 3, 2, 0, 0 };
1791*a88db0d1SZdenek Styblik 
1792*a88db0d1SZdenek Styblik 	if (argc < 1) {
1793*a88db0d1SZdenek Styblik 		return (1);
1794*a88db0d1SZdenek Styblik 	}
1795*a88db0d1SZdenek Styblik 
1796*a88db0d1SZdenek Styblik 	if (strlen(argv[0]) > MAX_SUNOEM_VAL_PAYLOAD) {
1797*a88db0d1SZdenek Styblik 		lprintf(LOG_ERR,
1798*a88db0d1SZdenek Styblik 				"Sun OEM get value command failed: Max size on IPMI name");
1799*a88db0d1SZdenek Styblik 		return (-1);
1800*a88db0d1SZdenek Styblik 	}
1801*a88db0d1SZdenek Styblik 
1802*a88db0d1SZdenek Styblik 	if ((ipmi_sunoem_checkversion(intf, &supp_ver) < 0)
1803*a88db0d1SZdenek Styblik 			&& (!strncmp(argv[0], sp_path, strlen(sp_path)))) {
1804*a88db0d1SZdenek Styblik 		argv[0][1] = 'X'; /*replace SP by X to gain access to hidden properties*/
1805*a88db0d1SZdenek Styblik 		memmove(&argv[0][2], &argv[0][3], strlen(argv[0]) - 2);
1806*a88db0d1SZdenek Styblik 	}
1807*a88db0d1SZdenek Styblik 
1808*a88db0d1SZdenek Styblik 	/*
1809*a88db0d1SZdenek Styblik 	 * Setup the initial request to fetch the data.
1810*a88db0d1SZdenek Styblik 	 * Upon function return, the next cmd (SUNOEM_GET_VAL)
1811*a88db0d1SZdenek Styblik 	 * can be requested.
1812*a88db0d1SZdenek Styblik 	 */
1813*a88db0d1SZdenek Styblik 	memset(&getval_req, 0, sizeof(getval_req));
1814*a88db0d1SZdenek Styblik 	strncpy((char*) getval_req.luapi_value, argv[0], MAX_SUNOEM_VAL_PAYLOAD);
1815*a88db0d1SZdenek Styblik 	getval_req.cmd_code = SUNOEM_REQ_VAL;
1816*a88db0d1SZdenek Styblik 
1817*a88db0d1SZdenek Styblik 	memset(&req, 0, sizeof(req));
1818*a88db0d1SZdenek Styblik 	req.msg.netfn = IPMI_NETFN_SUNOEM;
1819*a88db0d1SZdenek Styblik 	req.msg.cmd = IPMI_SUNOEM_GETVAL;
1820*a88db0d1SZdenek Styblik 	req.msg.data = (uint8_t *) &getval_req;
1821*a88db0d1SZdenek Styblik 	req.msg.data_len = sizeof(sunoem_getval_t);
1822*a88db0d1SZdenek Styblik 	rsp = intf->sendrecv(intf, &req);
1823*a88db0d1SZdenek Styblik 
1824*a88db0d1SZdenek Styblik 	if (rsp == NULL) {
1825*a88db0d1SZdenek Styblik 		lprintf(LOG_ERR, "Sun OEM getval1 command failed.");
1826*a88db0d1SZdenek Styblik 		return (-1);
1827*a88db0d1SZdenek Styblik 	}
1828*a88db0d1SZdenek Styblik 	if (rsp->ccode != 0) {
1829*a88db0d1SZdenek Styblik 		lprintf(LOG_ERR, "Sun OEM getval1 command failed: %d", rsp->ccode);
1830*a88db0d1SZdenek Styblik 		return (-1);
1831*a88db0d1SZdenek Styblik 	}
1832*a88db0d1SZdenek Styblik 
1833*a88db0d1SZdenek Styblik 	/*
1834*a88db0d1SZdenek Styblik 	 * Fetch the data value - if it is not ready,
1835*a88db0d1SZdenek Styblik 	 * retry the request up to GETVAL_MAX_RETRIES
1836*a88db0d1SZdenek Styblik 	 */
1837*a88db0d1SZdenek Styblik 	for (i = 0; i < GETVAL_MAX_RETRIES; i++) {
1838*a88db0d1SZdenek Styblik 		memset(&req, 0, sizeof(req));
1839*a88db0d1SZdenek Styblik 		req.msg.netfn = IPMI_NETFN_SUNOEM;
1840*a88db0d1SZdenek Styblik 		req.msg.cmd = IPMI_SUNOEM_GETVAL;
1841*a88db0d1SZdenek Styblik 		getval_req.cmd_code = SUNOEM_GET_VAL;
1842*a88db0d1SZdenek Styblik 		req.msg.data = (uint8_t *) &getval_req;
1843*a88db0d1SZdenek Styblik 		req.msg.data_len = sizeof(sunoem_getval_t);
1844*a88db0d1SZdenek Styblik 		rsp = intf->sendrecv(intf, &req);
1845*a88db0d1SZdenek Styblik 
1846*a88db0d1SZdenek Styblik 		if (rsp == NULL) {
1847*a88db0d1SZdenek Styblik 			lprintf(LOG_ERR, "Sun OEM getval2 command failed.");
1848*a88db0d1SZdenek Styblik 			return (-1);
1849*a88db0d1SZdenek Styblik 		}
1850*a88db0d1SZdenek Styblik 
1851*a88db0d1SZdenek Styblik 		if (rsp->ccode != 0) {
1852*a88db0d1SZdenek Styblik 			lprintf(LOG_ERR, "Sun OEM getval2 command failed: %d", rsp->ccode);
1853*a88db0d1SZdenek Styblik 			return (-1);
1854*a88db0d1SZdenek Styblik 		}
1855*a88db0d1SZdenek Styblik 
1856*a88db0d1SZdenek Styblik 		getval_rsp = (sunoem_getval_t *) rsp->data;
1857*a88db0d1SZdenek Styblik 
1858*a88db0d1SZdenek Styblik 		if (getval_rsp->cmd_code == SUNOEM_DATA_READY) {
1859*a88db0d1SZdenek Styblik 			printf("Target Value: %s\n", getval_rsp->luapi_value);
1860*a88db0d1SZdenek Styblik 			return (0);
1861*a88db0d1SZdenek Styblik 		} else if (getval_rsp->cmd_code == SUNOEM_DATA_NOT_FOUND) {
1862*a88db0d1SZdenek Styblik 			lprintf(LOG_ERR, "Target: %s not found", getval_req.luapi_value);
1863*a88db0d1SZdenek Styblik 			return (-1);
1864*a88db0d1SZdenek Styblik 		}
1865*a88db0d1SZdenek Styblik 
1866*a88db0d1SZdenek Styblik 		sleep(1);
1867*a88db0d1SZdenek Styblik 	}
1868*a88db0d1SZdenek Styblik 
1869*a88db0d1SZdenek Styblik 	lprintf(LOG_ERR, "Unable to retrieve target value.");
1870*a88db0d1SZdenek Styblik 	return (-1);
1871*a88db0d1SZdenek Styblik }
1872*a88db0d1SZdenek Styblik 
1873*a88db0d1SZdenek Styblik static int
send_luapi_prop_name(struct ipmi_intf * intf,int len,char * prop_name,unsigned char * tid_num)1874*a88db0d1SZdenek Styblik send_luapi_prop_name(struct ipmi_intf * intf, int len, char *prop_name,
1875*a88db0d1SZdenek Styblik 		unsigned char *tid_num)
1876*a88db0d1SZdenek Styblik {
1877*a88db0d1SZdenek Styblik 	int i = 0;
1878*a88db0d1SZdenek Styblik 	struct ipmi_rs *rsp;
1879*a88db0d1SZdenek Styblik 	struct ipmi_rq req;
1880*a88db0d1SZdenek Styblik 	sunoem_setval_t setval_req;
1881*a88db0d1SZdenek Styblik 	sunoem_setval_resp_t *setval_rsp;
1882*a88db0d1SZdenek Styblik 
1883*a88db0d1SZdenek Styblik 	*tid_num = 0;
1884*a88db0d1SZdenek Styblik 	while (i < len) {
1885*a88db0d1SZdenek Styblik 		/*
1886*a88db0d1SZdenek Styblik 		 * Setup the request,
1887*a88db0d1SZdenek Styblik 		 * Upon function return, the next cmd (SUNOEM_SET_VAL)
1888*a88db0d1SZdenek Styblik 		 * can be requested.
1889*a88db0d1SZdenek Styblik 		 */
1890*a88db0d1SZdenek Styblik 		memset(&req, 0, sizeof(req));
1891*a88db0d1SZdenek Styblik 		memset(&setval_req, 0, sizeof(sunoem_setval_t));
1892*a88db0d1SZdenek Styblik 		req.msg.netfn = IPMI_NETFN_SUNOEM;
1893*a88db0d1SZdenek Styblik 		req.msg.cmd = IPMI_SUNOEM_SETVAL;
1894*a88db0d1SZdenek Styblik 		setval_req.cmd_code = SUNOEM_SET_VAL;
1895*a88db0d1SZdenek Styblik 		setval_req.param_type = SUNOEM_LUAPI_TARGET;
1896*a88db0d1SZdenek Styblik 		setval_req.tid = *tid_num;
1897*a88db0d1SZdenek Styblik 		setval_req.eof = 0;
1898*a88db0d1SZdenek Styblik 		/*
1899*a88db0d1SZdenek Styblik 		 * If the property name is > payload, only copy
1900*a88db0d1SZdenek Styblik 		 * the payload size and increment the string offset (i)
1901*a88db0d1SZdenek Styblik 		 * for the next payload
1902*a88db0d1SZdenek Styblik 		 */
1903*a88db0d1SZdenek Styblik 		if (strlen(&(prop_name[i])) > MAX_SUNOEM_VAL_COMPACT_PAYLOAD) {
1904*a88db0d1SZdenek Styblik 			strncpy(setval_req.luapi_data, &(prop_name[i]),
1905*a88db0d1SZdenek Styblik 			MAX_SUNOEM_VAL_COMPACT_PAYLOAD);
1906*a88db0d1SZdenek Styblik 		} else {
1907*a88db0d1SZdenek Styblik 			strncpy(setval_req.luapi_data, &(prop_name[i]),
1908*a88db0d1SZdenek Styblik 					strlen(&(prop_name[i])));
1909*a88db0d1SZdenek Styblik 		}
1910*a88db0d1SZdenek Styblik 		req.msg.data = (uint8_t *) &setval_req;
1911*a88db0d1SZdenek Styblik 		req.msg.data_len = sizeof(sunoem_setval_t);
1912*a88db0d1SZdenek Styblik 		rsp = intf->sendrecv(intf, &req);
1913*a88db0d1SZdenek Styblik 
1914*a88db0d1SZdenek Styblik 		if (rsp == NULL) {
1915*a88db0d1SZdenek Styblik 			lprintf(LOG_ERR, "Sun OEM setval prop name: response is NULL");
1916*a88db0d1SZdenek Styblik 			return (-1);
1917*a88db0d1SZdenek Styblik 		}
1918*a88db0d1SZdenek Styblik 
1919*a88db0d1SZdenek Styblik 		if (rsp->ccode != 0) {
1920*a88db0d1SZdenek Styblik 			lprintf(LOG_ERR, "Sun OEM setval prop name: request failed: %d",
1921*a88db0d1SZdenek Styblik 					rsp->ccode);
1922*a88db0d1SZdenek Styblik 			return (-1);
1923*a88db0d1SZdenek Styblik 		}
1924*a88db0d1SZdenek Styblik 
1925*a88db0d1SZdenek Styblik 		setval_rsp = (sunoem_setval_resp_t *) rsp->data;
1926*a88db0d1SZdenek Styblik 
1927*a88db0d1SZdenek Styblik 		/*
1928*a88db0d1SZdenek Styblik 		 * If the return code is other than data received, the
1929*a88db0d1SZdenek Styblik 		 * request failed
1930*a88db0d1SZdenek Styblik 		 */
1931*a88db0d1SZdenek Styblik 		if (setval_rsp->status_code != SUNOEM_REQ_RECV) {
1932*a88db0d1SZdenek Styblik 			lprintf(LOG_ERR,
1933*a88db0d1SZdenek Styblik 					"Sun OEM setval prop name: invalid status code: %d",
1934*a88db0d1SZdenek Styblik 					setval_rsp->status_code);
1935*a88db0d1SZdenek Styblik 			return (-1);
1936*a88db0d1SZdenek Styblik 		}
1937*a88db0d1SZdenek Styblik 		/* Use the tid returned by ILOM */
1938*a88db0d1SZdenek Styblik 		*tid_num = setval_rsp->tid;
1939*a88db0d1SZdenek Styblik 		/* Increment the string offset */
1940*a88db0d1SZdenek Styblik 		i += MAX_SUNOEM_VAL_COMPACT_PAYLOAD;
1941*a88db0d1SZdenek Styblik 	}
1942*a88db0d1SZdenek Styblik 
1943*a88db0d1SZdenek Styblik 	return (0);
1944*a88db0d1SZdenek Styblik }
1945*a88db0d1SZdenek Styblik 
1946*a88db0d1SZdenek Styblik static int
send_luapi_prop_value(struct ipmi_intf * intf,int len,char * prop_value,unsigned char tid_num)1947*a88db0d1SZdenek Styblik send_luapi_prop_value(struct ipmi_intf * intf, int len,	char *prop_value,
1948*a88db0d1SZdenek Styblik 		unsigned char tid_num)
1949*a88db0d1SZdenek Styblik {
1950*a88db0d1SZdenek Styblik 	int i = 0;
1951*a88db0d1SZdenek Styblik 	struct ipmi_rs *rsp;
1952*a88db0d1SZdenek Styblik 	struct ipmi_rq req;
1953*a88db0d1SZdenek Styblik 	sunoem_setval_t setval_req;
1954*a88db0d1SZdenek Styblik 	sunoem_setval_resp_t *setval_rsp;
1955*a88db0d1SZdenek Styblik 
1956*a88db0d1SZdenek Styblik 	while (i < len) {
1957*a88db0d1SZdenek Styblik 		/*
1958*a88db0d1SZdenek Styblik 		 * Setup the request,
1959*a88db0d1SZdenek Styblik 		 * Upon function return, the next cmd (SUNOEM_GET_VAL)
1960*a88db0d1SZdenek Styblik 		 * can be requested.
1961*a88db0d1SZdenek Styblik 		 */
1962*a88db0d1SZdenek Styblik 		memset(&req, 0, sizeof(req));
1963*a88db0d1SZdenek Styblik 		memset(&setval_req, 0, sizeof(sunoem_setval_t));
1964*a88db0d1SZdenek Styblik 		req.msg.netfn = IPMI_NETFN_SUNOEM;
1965*a88db0d1SZdenek Styblik 		req.msg.cmd = IPMI_SUNOEM_SETVAL;
1966*a88db0d1SZdenek Styblik 		setval_req.cmd_code = SUNOEM_SET_VAL;
1967*a88db0d1SZdenek Styblik 		setval_req.param_type = SUNOEM_LUAPI_VALUE;
1968*a88db0d1SZdenek Styblik 		setval_req.tid = tid_num;
1969*a88db0d1SZdenek Styblik 		/*
1970*a88db0d1SZdenek Styblik 		 * If the property name is > payload, only copy the
1971*a88db0d1SZdenek Styblik 		 * the payload size and increment the string offset
1972*a88db0d1SZdenek Styblik 		 * for the next payload
1973*a88db0d1SZdenek Styblik 		 */
1974*a88db0d1SZdenek Styblik 		if (strlen(&(prop_value[i])) > MAX_SUNOEM_VAL_COMPACT_PAYLOAD) {
1975*a88db0d1SZdenek Styblik 			strncpy(setval_req.luapi_data, &(prop_value[i]),
1976*a88db0d1SZdenek Styblik 			MAX_SUNOEM_VAL_COMPACT_PAYLOAD);
1977*a88db0d1SZdenek Styblik 		} else {
1978*a88db0d1SZdenek Styblik 			/* Captured the entire string, mark this as the last payload */
1979*a88db0d1SZdenek Styblik 			strncpy(setval_req.luapi_data, &(prop_value[i]),
1980*a88db0d1SZdenek Styblik 					strlen(&(prop_value[i])));
1981*a88db0d1SZdenek Styblik 			setval_req.eof = 1;
1982*a88db0d1SZdenek Styblik 		}
1983*a88db0d1SZdenek Styblik 		req.msg.data = (uint8_t *) &setval_req;
1984*a88db0d1SZdenek Styblik 		req.msg.data_len = sizeof(sunoem_setval_t);
1985*a88db0d1SZdenek Styblik 		rsp = intf->sendrecv(intf, &req);
1986*a88db0d1SZdenek Styblik 
1987*a88db0d1SZdenek Styblik 		if (rsp == NULL) {
1988*a88db0d1SZdenek Styblik 			lprintf(LOG_ERR, "Sun OEM setval prop value: response is NULL");
1989*a88db0d1SZdenek Styblik 			return (-1);
1990*a88db0d1SZdenek Styblik 		}
1991*a88db0d1SZdenek Styblik 
1992*a88db0d1SZdenek Styblik 		if (rsp->ccode != 0) {
1993*a88db0d1SZdenek Styblik 			lprintf(LOG_ERR, "Sun OEM setval prop value: request failed: %d",
1994*a88db0d1SZdenek Styblik 					rsp->ccode);
1995*a88db0d1SZdenek Styblik 			return (-1);
1996*a88db0d1SZdenek Styblik 		}
1997*a88db0d1SZdenek Styblik 
1998*a88db0d1SZdenek Styblik 		setval_rsp = (sunoem_setval_resp_t *) rsp->data;
1999*a88db0d1SZdenek Styblik 
2000*a88db0d1SZdenek Styblik 		/*
2001*a88db0d1SZdenek Styblik 		 * If the return code is other than data received, the
2002*a88db0d1SZdenek Styblik 		 * request failed
2003*a88db0d1SZdenek Styblik 		 */
2004*a88db0d1SZdenek Styblik 		if (setval_rsp->status_code != SUNOEM_REQ_RECV) {
2005*a88db0d1SZdenek Styblik 			lprintf(LOG_ERR,
2006*a88db0d1SZdenek Styblik 					"Sun OEM setval prop value: invalid status code: %d",
2007*a88db0d1SZdenek Styblik 					setval_rsp->status_code);
2008*a88db0d1SZdenek Styblik 			return (-1);
2009*a88db0d1SZdenek Styblik 		}
2010*a88db0d1SZdenek Styblik 
2011*a88db0d1SZdenek Styblik 		/* Increment the string offset */
2012*a88db0d1SZdenek Styblik 		i += MAX_SUNOEM_VAL_COMPACT_PAYLOAD;
2013*a88db0d1SZdenek Styblik 	}
2014*a88db0d1SZdenek Styblik 	return (0);
2015*a88db0d1SZdenek Styblik }
2016*a88db0d1SZdenek Styblik 
2017*a88db0d1SZdenek Styblik static int
ipmi_sunoem_setval(struct ipmi_intf * intf,int argc,char * argv[])2018*a88db0d1SZdenek Styblik ipmi_sunoem_setval(struct ipmi_intf * intf, int argc, char *argv[])
2019*a88db0d1SZdenek Styblik {
2020*a88db0d1SZdenek Styblik 	struct ipmi_rs *rsp;
2021*a88db0d1SZdenek Styblik 	struct ipmi_rq req;
2022*a88db0d1SZdenek Styblik 	sunoem_setval_t setval_req;
2023*a88db0d1SZdenek Styblik 	sunoem_setval_resp_t *setval_rsp;
2024*a88db0d1SZdenek Styblik 	int prop_len;
2025*a88db0d1SZdenek Styblik 	int value_len;
2026*a88db0d1SZdenek Styblik 	int i;
2027*a88db0d1SZdenek Styblik 	unsigned char tid_num;
2028*a88db0d1SZdenek Styblik 	int retries;
2029*a88db0d1SZdenek Styblik 
2030*a88db0d1SZdenek Styblik 	prop_len = strlen(argv[0]);
2031*a88db0d1SZdenek Styblik 	value_len = strlen(argv[1]);
2032*a88db0d1SZdenek Styblik 	if (prop_len > LUAPI_MAX_OBJ_PATH_LEN) {
2033*a88db0d1SZdenek Styblik 		lprintf(LOG_ERR,
2034*a88db0d1SZdenek Styblik 				"Sun OEM set value command failed: Max size on property name");
2035*a88db0d1SZdenek Styblik 		return (-1);
2036*a88db0d1SZdenek Styblik 	}
2037*a88db0d1SZdenek Styblik 	if (value_len > LUAPI_MAX_OBJ_VAL_LEN) {
2038*a88db0d1SZdenek Styblik 		lprintf(LOG_ERR,
2039*a88db0d1SZdenek Styblik 				"Sun OEM set value command failed: Max size on property value");
2040*a88db0d1SZdenek Styblik 		return (-1);
2041*a88db0d1SZdenek Styblik 	}
2042*a88db0d1SZdenek Styblik 
2043*a88db0d1SZdenek Styblik 	/* Test if there is a timeout specified */
2044*a88db0d1SZdenek Styblik 	if (argc == 3) {
2045*a88db0d1SZdenek Styblik 		if ((str2int(argv[2], &retries) != 0) || retries < 0) {
2046*a88db0d1SZdenek Styblik 			lprintf(LOG_ERR,
2047*a88db0d1SZdenek Styblik 					"Invalid input given or out of range for time-out parameter.");
2048*a88db0d1SZdenek Styblik 			return (-1);
2049*a88db0d1SZdenek Styblik 		}
2050*a88db0d1SZdenek Styblik 	} else {
2051*a88db0d1SZdenek Styblik 		retries = GETVAL_MAX_RETRIES;
2052*a88db0d1SZdenek Styblik 	}
2053*a88db0d1SZdenek Styblik 
2054*a88db0d1SZdenek Styblik 	/* Send the property name 1st */
2055*a88db0d1SZdenek Styblik 	if (send_luapi_prop_name(intf, prop_len, argv[0], &tid_num) != 0) {
2056*a88db0d1SZdenek Styblik 		/* return if there is an error */
2057*a88db0d1SZdenek Styblik 		return (-1);
2058*a88db0d1SZdenek Styblik 	}
2059*a88db0d1SZdenek Styblik 
2060*a88db0d1SZdenek Styblik 	if (send_luapi_prop_value(intf, value_len, argv[1], tid_num) != 0) {
2061*a88db0d1SZdenek Styblik 		/* return if there is an error */
2062*a88db0d1SZdenek Styblik 		return (-1);
2063*a88db0d1SZdenek Styblik 	}
2064*a88db0d1SZdenek Styblik 
2065*a88db0d1SZdenek Styblik 	/*
2066*a88db0d1SZdenek Styblik 	 * Get The status of the command.
2067*a88db0d1SZdenek Styblik 	 * if it is not ready, retry the request up to
2068*a88db0d1SZdenek Styblik 	 * GETVAL_MAX_RETRIES
2069*a88db0d1SZdenek Styblik 	 */
2070*a88db0d1SZdenek Styblik 	for (i = 0; i < retries; i++) {
2071*a88db0d1SZdenek Styblik 		memset(&req, 0, sizeof(req));
2072*a88db0d1SZdenek Styblik 		req.msg.netfn = IPMI_NETFN_SUNOEM;
2073*a88db0d1SZdenek Styblik 		req.msg.cmd = IPMI_SUNOEM_SETVAL;
2074*a88db0d1SZdenek Styblik 		setval_req.cmd_code = SUNOEM_GET_STATUS;
2075*a88db0d1SZdenek Styblik 		setval_req.tid = tid_num;
2076*a88db0d1SZdenek Styblik 		req.msg.data = (uint8_t *) &setval_req;
2077*a88db0d1SZdenek Styblik 		req.msg.data_len = sizeof(sunoem_setval_t);
2078*a88db0d1SZdenek Styblik 		rsp = intf->sendrecv(intf, &req);
2079*a88db0d1SZdenek Styblik 
2080*a88db0d1SZdenek Styblik 		if (rsp == NULL) {
2081*a88db0d1SZdenek Styblik 			lprintf(LOG_ERR, "Sun OEM setval command failed.");
2082*a88db0d1SZdenek Styblik 			return (-1);
2083*a88db0d1SZdenek Styblik 		}
2084*a88db0d1SZdenek Styblik 
2085*a88db0d1SZdenek Styblik 		if (rsp->ccode != 0) {
2086*a88db0d1SZdenek Styblik 			lprintf(LOG_ERR, "Sun OEM setval command failed: %d", rsp->ccode);
2087*a88db0d1SZdenek Styblik 			return (-1);
2088*a88db0d1SZdenek Styblik 		}
2089*a88db0d1SZdenek Styblik 
2090*a88db0d1SZdenek Styblik 		setval_rsp = (sunoem_setval_resp_t *) rsp->data;
2091*a88db0d1SZdenek Styblik 
2092*a88db0d1SZdenek Styblik 		if (setval_rsp->status_code == SUNOEM_DATA_READY) {
2093*a88db0d1SZdenek Styblik 			printf("Sun OEM setval command successful.\n");
2094*a88db0d1SZdenek Styblik 			return (0);
2095*a88db0d1SZdenek Styblik 		} else if (setval_rsp->status_code != SUNOEM_DATA_NOT_READY) {
2096*a88db0d1SZdenek Styblik 			lprintf(LOG_ERR, "Sun OEM setval command failed.");
2097*a88db0d1SZdenek Styblik 			return (-1);
2098*a88db0d1SZdenek Styblik 		}
2099*a88db0d1SZdenek Styblik 
2100*a88db0d1SZdenek Styblik 		sleep(1);
2101*a88db0d1SZdenek Styblik 	}
2102*a88db0d1SZdenek Styblik 	/* If we reached here, retries exceeded */
2103*a88db0d1SZdenek Styblik 	lprintf(LOG_ERR, "Sun OEM setval command failed: Command Timed Out");
2104*a88db0d1SZdenek Styblik 
2105*a88db0d1SZdenek Styblik 	return (-1);
2106*a88db0d1SZdenek Styblik }
2107*a88db0d1SZdenek Styblik 
2108*a88db0d1SZdenek Styblik #define MAX_FILE_DATA_SIZE            1024
2109*a88db0d1SZdenek Styblik #define MAX_FILEID_LEN                16
2110*a88db0d1SZdenek Styblik #define CORE_TUNNEL_SUBCMD_GET_FILE   11
2111*a88db0d1SZdenek Styblik 
2112*a88db0d1SZdenek Styblik #ifdef HAVE_PRAGMA_PACK
2113*a88db0d1SZdenek Styblik #pragma pack(push, 1)
2114*a88db0d1SZdenek Styblik #endif
2115*a88db0d1SZdenek Styblik typedef struct
2116*a88db0d1SZdenek Styblik {
2117*a88db0d1SZdenek Styblik 	unsigned char cmd_code;
2118*a88db0d1SZdenek Styblik 	unsigned char file_id[MAX_FILEID_LEN];
2119*a88db0d1SZdenek Styblik 	unsigned int block_num;
2120*a88db0d1SZdenek Styblik }__attribute__((packed)) getfile_req_t;
2121*a88db0d1SZdenek Styblik 
2122*a88db0d1SZdenek Styblik typedef struct
2123*a88db0d1SZdenek Styblik {
2124*a88db0d1SZdenek Styblik 	unsigned int block_num;
2125*a88db0d1SZdenek Styblik 	unsigned int data_size;
2126*a88db0d1SZdenek Styblik 	unsigned char eof;
2127*a88db0d1SZdenek Styblik 	unsigned char data[MAX_FILE_DATA_SIZE];
2128*a88db0d1SZdenek Styblik }__attribute__((packed)) getfile_rsp_t;
2129*a88db0d1SZdenek Styblik #ifdef HAVE_PRAGMA_PACK
2130*a88db0d1SZdenek Styblik #pragma pack(pop)
2131*a88db0d1SZdenek Styblik #endif
2132*a88db0d1SZdenek Styblik 
2133*a88db0d1SZdenek Styblik static int
ipmi_sunoem_getfile(struct ipmi_intf * intf,int argc,char * argv[])2134*a88db0d1SZdenek Styblik ipmi_sunoem_getfile(struct ipmi_intf * intf, int argc, char *argv[])
2135*a88db0d1SZdenek Styblik {
2136*a88db0d1SZdenek Styblik 	struct ipmi_rs *rsp;
2137*a88db0d1SZdenek Styblik 	struct ipmi_rq req;
2138*a88db0d1SZdenek Styblik 	getfile_req_t getfile_req;
2139*a88db0d1SZdenek Styblik 	getfile_rsp_t *getfile_rsp;
2140*a88db0d1SZdenek Styblik 	int block_num = 0;
2141*a88db0d1SZdenek Styblik 	int nbo_blk_num; /* Network Byte Order Block Num */
2142*a88db0d1SZdenek Styblik 	FILE *fp;
2143*a88db0d1SZdenek Styblik 	unsigned data_size;
2144*a88db0d1SZdenek Styblik 	supported_version_t supp_ver = IPMI_SUNOEM_GETFILE_VERSION;
2145*a88db0d1SZdenek Styblik 
2146*a88db0d1SZdenek Styblik 	if (argc < 1) {
2147*a88db0d1SZdenek Styblik 		return (-1);
2148*a88db0d1SZdenek Styblik 	}
2149*a88db0d1SZdenek Styblik 
2150*a88db0d1SZdenek Styblik 	/*check if command is supported by this version of ilom*/
2151*a88db0d1SZdenek Styblik 	if (ipmi_sunoem_checkversion(intf, &supp_ver) < 0) {
2152*a88db0d1SZdenek Styblik 		ipmi_sunoem_print_required_version(&supp_ver);
2153*a88db0d1SZdenek Styblik 		return (-1);
2154*a88db0d1SZdenek Styblik 	}
2155*a88db0d1SZdenek Styblik 
2156*a88db0d1SZdenek Styblik 	/*
2157*a88db0d1SZdenek Styblik 	 * File ID is < MAX_FILEID_LEN
2158*a88db0d1SZdenek Styblik 	 * Save 1 byte for null Terminated string
2159*a88db0d1SZdenek Styblik 	 */
2160*a88db0d1SZdenek Styblik 	if (strlen(argv[0]) >= MAX_FILE_DATA_SIZE) {
2161*a88db0d1SZdenek Styblik 		lprintf(LOG_ERR, "File ID >= %d characters", MAX_FILEID_LEN);
2162*a88db0d1SZdenek Styblik 		return (-1);
2163*a88db0d1SZdenek Styblik 	}
2164*a88db0d1SZdenek Styblik 
2165*a88db0d1SZdenek Styblik 	memset(&getfile_req, 0, sizeof(getfile_req));
2166*a88db0d1SZdenek Styblik 	strncpy((char*) getfile_req.file_id, argv[0], MAX_FILEID_LEN - 1);
2167*a88db0d1SZdenek Styblik 
2168*a88db0d1SZdenek Styblik 	/* Create the destination file */
2169*a88db0d1SZdenek Styblik 	fp = ipmi_open_file_write(argv[1]);
2170*a88db0d1SZdenek Styblik 	if (fp == NULL) {
2171*a88db0d1SZdenek Styblik 		lprintf(LOG_ERR, "Unable to open file: %s", argv[1]);
2172*a88db0d1SZdenek Styblik 		return (-1);
2173*a88db0d1SZdenek Styblik 	}
2174*a88db0d1SZdenek Styblik 
2175*a88db0d1SZdenek Styblik 	memset(&req, 0, sizeof(req));
2176*a88db0d1SZdenek Styblik 	req.msg.netfn = IPMI_NETFN_SUNOEM;
2177*a88db0d1SZdenek Styblik 	req.msg.cmd = IPMI_SUNOEM_CORE_TUNNEL;
2178*a88db0d1SZdenek Styblik 	req.msg.data = (uint8_t *) &getfile_req;
2179*a88db0d1SZdenek Styblik 	req.msg.data_len = sizeof(getfile_req_t);
2180*a88db0d1SZdenek Styblik 	getfile_req.cmd_code = CORE_TUNNEL_SUBCMD_GET_FILE;
2181*a88db0d1SZdenek Styblik 
2182*a88db0d1SZdenek Styblik 	do {
2183*a88db0d1SZdenek Styblik 
2184*a88db0d1SZdenek Styblik 		nbo_blk_num = htonl(block_num);
2185*a88db0d1SZdenek Styblik 		/* Block Num must be in network byte order */
2186*a88db0d1SZdenek Styblik 		memcpy(&(getfile_req.block_num), &nbo_blk_num,
2187*a88db0d1SZdenek Styblik 				sizeof(getfile_req.block_num));
2188*a88db0d1SZdenek Styblik 
2189*a88db0d1SZdenek Styblik 		rsp = intf->sendrecv(intf, &req);
2190*a88db0d1SZdenek Styblik 
2191*a88db0d1SZdenek Styblik 		if (rsp == NULL) {
2192*a88db0d1SZdenek Styblik 			lprintf(LOG_ERR, "Sun OEM getfile command failed.");
2193*a88db0d1SZdenek Styblik 			fclose(fp);
2194*a88db0d1SZdenek Styblik 			return (-1);
2195*a88db0d1SZdenek Styblik 		}
2196*a88db0d1SZdenek Styblik 		if (rsp->ccode != 0) {
2197*a88db0d1SZdenek Styblik 			lprintf(LOG_ERR, "Sun OEM getfile command failed: %d", rsp->ccode);
2198*a88db0d1SZdenek Styblik 			fclose(fp);
2199*a88db0d1SZdenek Styblik 			return (-1);
2200*a88db0d1SZdenek Styblik 		}
2201*a88db0d1SZdenek Styblik 
2202*a88db0d1SZdenek Styblik 		getfile_rsp = (getfile_rsp_t *) rsp->data;
2203*a88db0d1SZdenek Styblik 
2204*a88db0d1SZdenek Styblik 		memcpy(&data_size, &(getfile_rsp->data_size),
2205*a88db0d1SZdenek Styblik 				sizeof(getfile_rsp->data_size));
2206*a88db0d1SZdenek Styblik 		data_size = ntohl(data_size);
2207*a88db0d1SZdenek Styblik 
2208*a88db0d1SZdenek Styblik 		if (data_size > MAX_FILE_DATA_SIZE) {
2209*a88db0d1SZdenek Styblik 			lprintf(LOG_ERR, "Sun OEM getfile invalid data size: %d",
2210*a88db0d1SZdenek Styblik 					data_size);
2211*a88db0d1SZdenek Styblik 			fclose(fp);
2212*a88db0d1SZdenek Styblik 			return (-1);
2213*a88db0d1SZdenek Styblik 		}
2214*a88db0d1SZdenek Styblik 
2215*a88db0d1SZdenek Styblik 		/* Check if Block Num matches */
2216*a88db0d1SZdenek Styblik 		if (memcmp(&(getfile_req.block_num), &(getfile_rsp->block_num),
2217*a88db0d1SZdenek Styblik 				sizeof(getfile_req.block_num)) != 0) {
2218*a88db0d1SZdenek Styblik 			lprintf(LOG_ERR, "Sun OEM getfile Incorrect Block Num Returned");
2219*a88db0d1SZdenek Styblik 			lprintf(LOG_ERR, "Expecting: %x Received: %x",
2220*a88db0d1SZdenek Styblik 					getfile_req.block_num, getfile_rsp->block_num);
2221*a88db0d1SZdenek Styblik 			fclose(fp);
2222*a88db0d1SZdenek Styblik 			return (-1);
2223*a88db0d1SZdenek Styblik 		}
2224*a88db0d1SZdenek Styblik 
2225*a88db0d1SZdenek Styblik 		if (fwrite(getfile_rsp->data, 1, data_size, fp) != data_size) {
2226*a88db0d1SZdenek Styblik 			lprintf(LOG_ERR, "Sun OEM getfile write failed: %d", rsp->ccode);
2227*a88db0d1SZdenek Styblik 			fclose(fp);
2228*a88db0d1SZdenek Styblik 			return (-1);
2229*a88db0d1SZdenek Styblik 		}
2230*a88db0d1SZdenek Styblik 
2231*a88db0d1SZdenek Styblik 		block_num++;
2232*a88db0d1SZdenek Styblik 	} while (getfile_rsp->eof == 0);
2233*a88db0d1SZdenek Styblik 
2234*a88db0d1SZdenek Styblik 	fclose(fp);
2235*a88db0d1SZdenek Styblik 
2236*a88db0d1SZdenek Styblik 	return (0);
2237*a88db0d1SZdenek Styblik }
2238*a88db0d1SZdenek Styblik 
2239*a88db0d1SZdenek Styblik /*
2240*a88db0d1SZdenek Styblik  * Query BMC for capability/behavior.
2241*a88db0d1SZdenek Styblik  */
2242*a88db0d1SZdenek Styblik 
2243*a88db0d1SZdenek Styblik #define CORE_TUNNEL_SUBCMD_GET_BEHAVIOR   15
2244*a88db0d1SZdenek Styblik #define SUNOEM_BEHAVIORID_SIZE            32
2245*a88db0d1SZdenek Styblik 
2246*a88db0d1SZdenek Styblik #ifdef HAVE_PRAGMA_PACK
2247*a88db0d1SZdenek Styblik #pragma pack(push, 1)
2248*a88db0d1SZdenek Styblik #endif
2249*a88db0d1SZdenek Styblik typedef struct
2250*a88db0d1SZdenek Styblik {
2251*a88db0d1SZdenek Styblik 	unsigned char cmd_code;
2252*a88db0d1SZdenek Styblik 	unsigned char behavior_id[SUNOEM_BEHAVIORID_SIZE];
2253*a88db0d1SZdenek Styblik }__attribute__((packed)) getbehavior_req_t;
2254*a88db0d1SZdenek Styblik 
2255*a88db0d1SZdenek Styblik typedef struct
2256*a88db0d1SZdenek Styblik {
2257*a88db0d1SZdenek Styblik 	unsigned char enabled;
2258*a88db0d1SZdenek Styblik }__attribute__((packed)) getbehavior_rsp_t;
2259*a88db0d1SZdenek Styblik #ifdef HAVE_PRAGMA_PACK
2260*a88db0d1SZdenek Styblik #pragma pack(pop)
2261*a88db0d1SZdenek Styblik #endif
2262*a88db0d1SZdenek Styblik 
2263*a88db0d1SZdenek Styblik static int
ipmi_sunoem_getbehavior(struct ipmi_intf * intf,int argc,char * argv[])2264*a88db0d1SZdenek Styblik ipmi_sunoem_getbehavior(struct ipmi_intf * intf, int argc, char *argv[])
2265*a88db0d1SZdenek Styblik {
2266*a88db0d1SZdenek Styblik 	struct ipmi_rq req;
2267*a88db0d1SZdenek Styblik 	struct ipmi_rs *rsp;
2268*a88db0d1SZdenek Styblik 	getbehavior_req_t getbehavior_req;
2269*a88db0d1SZdenek Styblik 	getbehavior_rsp_t *getbehavior_rsp;
2270*a88db0d1SZdenek Styblik 	supported_version_t supp_ver = IPMI_SUNOEM_GETBEHAVIOR_VERSION;
2271*a88db0d1SZdenek Styblik 
2272*a88db0d1SZdenek Styblik 	if (argc < 1) {
2273*a88db0d1SZdenek Styblik 		return (-1);
2274*a88db0d1SZdenek Styblik 	}
2275*a88db0d1SZdenek Styblik 
2276*a88db0d1SZdenek Styblik 	/*check if command is supported by this version of ilom*/
2277*a88db0d1SZdenek Styblik 	if (ipmi_sunoem_checkversion(intf, &supp_ver) < 0) {
2278*a88db0d1SZdenek Styblik 		ipmi_sunoem_print_required_version(&supp_ver);
2279*a88db0d1SZdenek Styblik 		return (-1);
2280*a88db0d1SZdenek Styblik 	}
2281*a88db0d1SZdenek Styblik 
2282*a88db0d1SZdenek Styblik 	/*
2283*a88db0d1SZdenek Styblik 	 * Behavior ID is < SUNOEM_BEHAVIORID_SIZE.
2284*a88db0d1SZdenek Styblik 	 * Save 1 byte for null terminated string
2285*a88db0d1SZdenek Styblik 	 */
2286*a88db0d1SZdenek Styblik 	if (strlen(argv[0]) >= SUNOEM_BEHAVIORID_SIZE) {
2287*a88db0d1SZdenek Styblik 		lprintf(LOG_ERR, "Behavior ID >= %d characters",
2288*a88db0d1SZdenek Styblik 		SUNOEM_BEHAVIORID_SIZE);
2289*a88db0d1SZdenek Styblik 		return (-1);
2290*a88db0d1SZdenek Styblik 	}
2291*a88db0d1SZdenek Styblik 
2292*a88db0d1SZdenek Styblik 	memset(&getbehavior_req, 0, sizeof(getbehavior_req));
2293*a88db0d1SZdenek Styblik 	strncpy(getbehavior_req.behavior_id, argv[0], SUNOEM_BEHAVIORID_SIZE - 1);
2294*a88db0d1SZdenek Styblik 
2295*a88db0d1SZdenek Styblik 	memset(&req, 0, sizeof(req));
2296*a88db0d1SZdenek Styblik 	req.msg.netfn = IPMI_NETFN_SUNOEM;
2297*a88db0d1SZdenek Styblik 	req.msg.cmd = IPMI_SUNOEM_CORE_TUNNEL;
2298*a88db0d1SZdenek Styblik 	req.msg.data = (uint8_t *) &getbehavior_req;
2299*a88db0d1SZdenek Styblik 	req.msg.data_len = sizeof(getbehavior_req_t);
2300*a88db0d1SZdenek Styblik 	getbehavior_req.cmd_code = CORE_TUNNEL_SUBCMD_GET_BEHAVIOR;
2301*a88db0d1SZdenek Styblik 
2302*a88db0d1SZdenek Styblik 	rsp = intf->sendrecv(intf, &req);
2303*a88db0d1SZdenek Styblik 
2304*a88db0d1SZdenek Styblik 	if (rsp == NULL) {
2305*a88db0d1SZdenek Styblik 		lprintf(LOG_ERR, "Sun OEM getbehavior command failed.");
2306*a88db0d1SZdenek Styblik 		return (-1);
2307*a88db0d1SZdenek Styblik 	}
2308*a88db0d1SZdenek Styblik 
2309*a88db0d1SZdenek Styblik 	if (rsp->ccode != 0) {
2310*a88db0d1SZdenek Styblik 		lprintf(LOG_ERR, "Sun OEM getbehavior command failed: %d", rsp->ccode);
2311*a88db0d1SZdenek Styblik 		return (-1);
2312*a88db0d1SZdenek Styblik 	}
2313*a88db0d1SZdenek Styblik 
2314*a88db0d1SZdenek Styblik 	getbehavior_rsp = (getbehavior_rsp_t *) rsp->data;
2315*a88db0d1SZdenek Styblik 	printf("ILOM behavior %s %s enabled\n", getbehavior_req.behavior_id,
2316*a88db0d1SZdenek Styblik 			getbehavior_rsp->enabled ? "is" : "is not");
2317*a88db0d1SZdenek Styblik 
2318*a88db0d1SZdenek Styblik 	return (0);
2319*a88db0d1SZdenek Styblik }
2320c18ec02fSPetter Reinholdtsen 
2321c18ec02fSPetter Reinholdtsen int
ipmi_sunoem_main(struct ipmi_intf * intf,int argc,char ** argv)2322c18ec02fSPetter Reinholdtsen ipmi_sunoem_main(struct ipmi_intf * intf, int argc, char ** argv)
2323c18ec02fSPetter Reinholdtsen {
2324*a88db0d1SZdenek Styblik 	int rc = 0;
2325c18ec02fSPetter Reinholdtsen 
2326*a88db0d1SZdenek Styblik 	if (argc == 0 || strcmp(argv[0], "help") == 0) {
2327c18ec02fSPetter Reinholdtsen 		ipmi_sunoem_usage();
2328*a88db0d1SZdenek Styblik 		return (0);
2329*a88db0d1SZdenek Styblik 	} /* if (argc == 0 || strcmp(argv[0], "help") == 0) */
2330c18ec02fSPetter Reinholdtsen 
2331*a88db0d1SZdenek Styblik 	if (strcmp(argv[0], "cli") == 0) {
2332*a88db0d1SZdenek Styblik 		rc = ipmi_sunoem_cli(intf, argc - 1, &argv[1]);
2333*a88db0d1SZdenek Styblik 	} else if ((strcmp(argv[0], "led") == 0) || (strcmp(argv[0], "sbled") == 0)) {
2334c18ec02fSPetter Reinholdtsen 		if (argc < 2) {
2335c18ec02fSPetter Reinholdtsen 			ipmi_sunoem_usage();
2336c18ec02fSPetter Reinholdtsen 			return (-1);
2337c18ec02fSPetter Reinholdtsen 		}
2338*a88db0d1SZdenek Styblik 
2339*a88db0d1SZdenek Styblik 		if (strcmp(argv[1], "get") == 0) {
2340c18ec02fSPetter Reinholdtsen 			if (argc < 3) {
2341c18ec02fSPetter Reinholdtsen 				char * arg[] = { "all" };
2342c18ec02fSPetter Reinholdtsen 				rc = ipmi_sunoem_led_get(intf, 1, arg);
2343*a88db0d1SZdenek Styblik 			} else {
2344c18ec02fSPetter Reinholdtsen 				rc = ipmi_sunoem_led_get(intf, argc - 2, &(argv[2]));
2345c18ec02fSPetter Reinholdtsen 			}
2346*a88db0d1SZdenek Styblik 		} else if (strcmp(argv[1], "set") == 0) {
2347c18ec02fSPetter Reinholdtsen 			if (argc < 4) {
2348c18ec02fSPetter Reinholdtsen 				ipmi_sunoem_usage();
2349c18ec02fSPetter Reinholdtsen 				return (-1);
2350c18ec02fSPetter Reinholdtsen 			}
2351c18ec02fSPetter Reinholdtsen 			rc = ipmi_sunoem_led_set(intf, argc - 2, &(argv[2]));
2352*a88db0d1SZdenek Styblik 		} else {
2353c18ec02fSPetter Reinholdtsen 			ipmi_sunoem_usage();
2354c18ec02fSPetter Reinholdtsen 			return (-1);
2355c18ec02fSPetter Reinholdtsen 		}
2356*a88db0d1SZdenek Styblik 	} else if (strcmp(argv[0], "sshkey") == 0) {
2357c18ec02fSPetter Reinholdtsen 		uint8_t uid = 0;
2358c18ec02fSPetter Reinholdtsen 		if (argc < 3) {
2359c18ec02fSPetter Reinholdtsen 			ipmi_sunoem_usage();
2360c18ec02fSPetter Reinholdtsen 			return (-1);
2361c18ec02fSPetter Reinholdtsen 		}
2362*a88db0d1SZdenek Styblik 		rc = str2uchar(argv[2], &uid);
2363*a88db0d1SZdenek Styblik 		if (rc == 0) {
2364*a88db0d1SZdenek Styblik 			/* conversion should be OK. */
2365*a88db0d1SZdenek Styblik 		} else if (rc == 2) {
2366*a88db0d1SZdenek Styblik 			lprintf(LOG_NOTICE, "Invalid interval given.");
2367*a88db0d1SZdenek Styblik 			return (-1);
2368*a88db0d1SZdenek Styblik 		} else {
2369*a88db0d1SZdenek Styblik 			/* defaults to rc = 3 */
2370*a88db0d1SZdenek Styblik 			lprintf(LOG_NOTICE, "Given interval is too big.");
2371c18ec02fSPetter Reinholdtsen 			return (-1);
2372c18ec02fSPetter Reinholdtsen 		}
2373c18ec02fSPetter Reinholdtsen 
2374*a88db0d1SZdenek Styblik 		if (strcmp(argv[1], "del") == 0) {
2375*a88db0d1SZdenek Styblik 			/* number of arguments, three, is already checked at this point */
2376c18ec02fSPetter Reinholdtsen 			rc = ipmi_sunoem_sshkey_del(intf, uid);
2377*a88db0d1SZdenek Styblik 		} else if (strcmp(argv[1], "set") == 0) {
2378*a88db0d1SZdenek Styblik 			if (argc < 4) {
2379*a88db0d1SZdenek Styblik 				ipmi_sunoem_usage();
2380*a88db0d1SZdenek Styblik 				return (-1);
2381c18ec02fSPetter Reinholdtsen 			}
2382c18ec02fSPetter Reinholdtsen 			rc = ipmi_sunoem_sshkey_set(intf, uid, argv[3]);
2383*a88db0d1SZdenek Styblik 		} else {
2384c18ec02fSPetter Reinholdtsen 			ipmi_sunoem_usage();
2385c18ec02fSPetter Reinholdtsen 			return (-1);
2386c18ec02fSPetter Reinholdtsen 		}
2387*a88db0d1SZdenek Styblik 	} else if (strcmp(argv[0], "ping") == 0) {
2388*a88db0d1SZdenek Styblik 		if (argc < 2) {
2389c18ec02fSPetter Reinholdtsen 			ipmi_sunoem_usage();
2390c18ec02fSPetter Reinholdtsen 			return (-1);
2391c18ec02fSPetter Reinholdtsen 		}
2392*a88db0d1SZdenek Styblik 		rc = ipmi_sunoem_echo(intf, argc - 1, &(argv[1]));
2393*a88db0d1SZdenek Styblik 	} else if (strcmp(argv[0], "version") == 0) {
2394*a88db0d1SZdenek Styblik 		rc = ipmi_sunoem_version(intf);
2395*a88db0d1SZdenek Styblik 	} else if (strcmp(argv[0], "nacname") == 0) {
2396*a88db0d1SZdenek Styblik 		if (argc < 2) {
2397*a88db0d1SZdenek Styblik 			ipmi_sunoem_usage();
2398*a88db0d1SZdenek Styblik 			return (-1);
2399*a88db0d1SZdenek Styblik 		}
2400*a88db0d1SZdenek Styblik 		rc = ipmi_sunoem_nacname(intf, argc - 1, &(argv[1]));
2401*a88db0d1SZdenek Styblik 	} else if (strcmp(argv[0], "getval") == 0) {
2402*a88db0d1SZdenek Styblik 		if (argc < 2) {
2403*a88db0d1SZdenek Styblik 			ipmi_sunoem_usage();
2404*a88db0d1SZdenek Styblik 			return (-1);
2405*a88db0d1SZdenek Styblik 		}
2406*a88db0d1SZdenek Styblik 		rc = ipmi_sunoem_getval(intf, argc - 1, &(argv[1]));
2407*a88db0d1SZdenek Styblik 	} else if (strcmp(argv[0], "setval") == 0) {
2408*a88db0d1SZdenek Styblik 		if (argc < 3) {
2409*a88db0d1SZdenek Styblik 			ipmi_sunoem_usage();
2410*a88db0d1SZdenek Styblik 			return (-1);
2411*a88db0d1SZdenek Styblik 		}
2412*a88db0d1SZdenek Styblik 		rc = ipmi_sunoem_setval(intf, argc - 1, &(argv[1]));
2413*a88db0d1SZdenek Styblik 	} else if (strcmp(argv[0], "getfile") == 0) {
2414*a88db0d1SZdenek Styblik 		if (argc < 3) {
2415*a88db0d1SZdenek Styblik 			ipmi_sunoem_usage();
2416*a88db0d1SZdenek Styblik 			return (-1);
2417*a88db0d1SZdenek Styblik 		}
2418*a88db0d1SZdenek Styblik 		rc = ipmi_sunoem_getfile(intf, argc - 1, &(argv[1]));
2419*a88db0d1SZdenek Styblik 	} else if (strcmp(argv[0], "getbehavior") == 0) {
2420*a88db0d1SZdenek Styblik 		if (argc < 2) {
2421*a88db0d1SZdenek Styblik 			ipmi_sunoem_usage();
2422*a88db0d1SZdenek Styblik 			return (-1);
2423*a88db0d1SZdenek Styblik 		}
2424*a88db0d1SZdenek Styblik 		rc = ipmi_sunoem_getbehavior(intf, argc - 1, &(argv[1]));
2425*a88db0d1SZdenek Styblik 	} else {
2426*a88db0d1SZdenek Styblik 		lprintf(LOG_ERR, "Invalid sunoem command: %s", argv[0]);
2427*a88db0d1SZdenek Styblik 		return (-1);
2428*a88db0d1SZdenek Styblik 	} /* if (strcmp(argv[0], "cli") == 0) */
2429c18ec02fSPetter Reinholdtsen 
2430*a88db0d1SZdenek Styblik 	return (rc);
2431c18ec02fSPetter Reinholdtsen }
2432