1 /*
2 * cmd_fru.c
3 *
4 * A command interpreter for OpenIPMI
5 *
6 * Author: MontaVista Software, Inc.
7 * Corey Minyard <minyard@mvista.com>
8 * source@mvista.com
9 *
10 * Copyright 2004 MontaVista Software Inc.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 2 of
15 * the License, or (at your option) any later version.
16 *
17 *
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
19 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
24 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
26 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
27 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * You should have received a copy of the GNU Lesser General Public
30 * License along with this program; if not, write to the Free
31 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32 */
33
34 #include <errno.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <OpenIPMI/ipmiif.h>
40 #include <OpenIPMI/ipmi_mc.h>
41 #include <OpenIPMI/ipmi_cmdlang.h>
42 #include <OpenIPMI/ipmi_fru.h>
43
44 /* Internal includes, do not use in your programs */
45 #include <OpenIPMI/internal/ipmi_malloc.h>
46
47 /* Don't pollute the namespace iwth ipmi_fru_t. */
48 void ipmi_cmdlang_dump_fru_info(ipmi_cmd_info_t *cmd_info, ipmi_fru_t *fru);
49
50 static void
fru_list_handler(ipmi_fru_t * fru,void * cb_data)51 fru_list_handler(ipmi_fru_t *fru, void *cb_data)
52 {
53 ipmi_cmd_info_t *cmd_info = cb_data;
54 ipmi_cmdlang_t *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
55 char fru_name[IPMI_FRU_NAME_LEN];
56
57 if (cmdlang->err)
58 return;
59
60 ipmi_fru_get_name(fru, fru_name, sizeof(fru_name));
61
62 ipmi_cmdlang_out(cmd_info, "Name", fru_name);
63 }
64
65 static void
fru_list(ipmi_domain_t * domain,void * cb_data)66 fru_list(ipmi_domain_t *domain, void *cb_data)
67 {
68 ipmi_cmd_info_t *cmd_info = cb_data;
69 char domain_name[IPMI_DOMAIN_NAME_LEN];
70
71 ipmi_domain_get_name(domain, domain_name, sizeof(domain_name));
72 ipmi_cmdlang_out(cmd_info, "Domain", NULL);
73 ipmi_cmdlang_down(cmd_info);
74 ipmi_cmdlang_out(cmd_info, "Name", domain_name);
75 ipmi_cmdlang_out(cmd_info, "FRUs", NULL);
76 ipmi_cmdlang_down(cmd_info);
77 ipmi_fru_iterate_frus(domain, fru_list_handler, cmd_info);
78 ipmi_cmdlang_up(cmd_info);
79 ipmi_cmdlang_up(cmd_info);
80 }
81
82 static void
fru_info(ipmi_fru_t * fru,void * cb_data)83 fru_info(ipmi_fru_t *fru, void *cb_data)
84 {
85 ipmi_cmd_info_t *cmd_info = cb_data;
86 char fru_name[IPMI_FRU_NAME_LEN];
87
88 ipmi_fru_get_name(fru, fru_name, sizeof(fru_name));
89
90 ipmi_cmdlang_dump_fru_info(cmd_info, fru);
91 }
92
93 static char *areas[IPMI_FRU_FTR_NUMBER] =
94 {
95 "internal_use",
96 "chassis_info",
97 "board_info",
98 "product_info",
99 "multi_record"
100 };
101
102 static void
fru_areainfo(ipmi_fru_t * fru,void * cb_data)103 fru_areainfo(ipmi_fru_t *fru, void *cb_data)
104 {
105 ipmi_cmd_info_t *cmd_info = cb_data;
106 char fru_name[IPMI_FRU_NAME_LEN];
107 int i;
108 int rv;
109
110 ipmi_fru_get_name(fru, fru_name, sizeof(fru_name));
111
112 ipmi_cmdlang_out(cmd_info, "FRU", NULL);
113 ipmi_cmdlang_down(cmd_info);
114 ipmi_cmdlang_out(cmd_info, "Name", fru_name);
115 ipmi_cmdlang_out_int(cmd_info, "FRU Length",
116 ipmi_fru_get_data_length(fru));
117 for (i=0; i<IPMI_FRU_FTR_NUMBER; i++) {
118 unsigned int offset, length, used_length;
119 rv = ipmi_fru_area_get_offset(fru, i, &offset);
120 rv |= ipmi_fru_area_get_length(fru, i, &length);
121 rv |= ipmi_fru_area_get_used_length(fru, i, &used_length);
122 if (rv)
123 continue;
124 ipmi_cmdlang_out(cmd_info, "Area", NULL);
125 ipmi_cmdlang_down(cmd_info);
126 ipmi_cmdlang_out(cmd_info, "Name", areas[i]);
127 ipmi_cmdlang_out_int(cmd_info, "Number", i);
128 ipmi_cmdlang_out_int(cmd_info, "Offset", offset);
129 ipmi_cmdlang_out_int(cmd_info, "Length", length);
130 ipmi_cmdlang_out_int(cmd_info, "Used Length", used_length);
131 ipmi_cmdlang_up(cmd_info);
132 }
133 ipmi_cmdlang_up(cmd_info);
134 }
135
136 static void
fru_written(ipmi_domain_t * domain,ipmi_fru_t * fru,int err,void * cb_data)137 fru_written(ipmi_domain_t *domain, ipmi_fru_t *fru, int err, void *cb_data)
138 {
139 ipmi_cmd_info_t *cmd_info = cb_data;
140 ipmi_cmdlang_t *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
141 char fru_name[IPMI_FRU_NAME_LEN];
142
143 if (err) {
144 cmdlang->errstr = "Unable to write FRU";
145 cmdlang->err = err;
146 ipmi_fru_get_name(fru, cmdlang->objstr,
147 cmdlang->objstr_len);
148 cmdlang->location = "cmd_fru.c(fru_written)";
149 } else {
150 ipmi_fru_get_name(fru, fru_name, sizeof(fru_name));
151 ipmi_cmdlang_out(cmd_info, "FRU written", fru_name);
152 }
153
154 ipmi_cmdlang_cmd_info_put(cmd_info);
155 }
156
157 static void
fru_write(ipmi_fru_t * fru,void * cb_data)158 fru_write(ipmi_fru_t *fru, void *cb_data)
159 {
160 ipmi_cmd_info_t *cmd_info = cb_data;
161 ipmi_cmdlang_t *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
162 int rv;
163
164 ipmi_cmdlang_cmd_info_get(cmd_info);
165 rv = ipmi_fru_write(fru, fru_written, cmd_info);
166 if (rv) {
167 ipmi_cmdlang_cmd_info_put(cmd_info);
168 cmdlang->errstr = "Unable to write FRU";
169 cmdlang->err = rv;
170 goto out_err;
171 }
172
173 return;
174
175 out_err:
176 ipmi_fru_get_name(fru, cmdlang->objstr,
177 cmdlang->objstr_len);
178 cmdlang->location = "cmd_fru.c(fru_write)";
179 }
180
181 static void
fru_deleted(ipmi_fru_t * fru,void * cb_data)182 fru_deleted(ipmi_fru_t *fru, void *cb_data)
183 {
184 ipmi_cmd_info_t *cmd_info = cb_data;
185 char fru_name[IPMI_FRU_NAME_LEN];
186
187 ipmi_fru_get_name(fru, fru_name, sizeof(fru_name));
188 ipmi_cmdlang_out(cmd_info, "FRU deleted", fru_name);
189 ipmi_cmdlang_cmd_info_put(cmd_info);
190 }
191
192 static void
fru_close(ipmi_fru_t * fru,void * cb_data)193 fru_close(ipmi_fru_t *fru, void *cb_data)
194 {
195 ipmi_cmd_info_t *cmd_info = cb_data;
196 ipmi_cmdlang_t *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
197 int rv;
198
199 ipmi_cmdlang_cmd_info_get(cmd_info);
200 /* We need to be holding our own reference to the FRU because
201 ipmi_fru_destroy will do a deref on it, but the calling code
202 will also be doing a deref.. */
203 ipmi_fru_ref(fru);
204 rv = ipmi_fru_destroy(fru, fru_deleted, cmd_info);
205 if (rv) {
206 ipmi_cmdlang_cmd_info_put(cmd_info);
207 cmdlang->errstr = "Unable to close domain";
208 cmdlang->err = rv;
209 goto out_err;
210 }
211
212 return;
213
214 out_err:
215 ipmi_fru_get_name(fru, cmdlang->objstr,
216 cmdlang->objstr_len);
217 cmdlang->location = "cmd_fru.c(fru_close)";
218 }
219
220 static void
fru_setval(ipmi_fru_t * fru,void * cb_data)221 fru_setval(ipmi_fru_t *fru, void *cb_data)
222 {
223 ipmi_cmd_info_t *cmd_info = cb_data;
224 ipmi_cmdlang_t *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
225 int curr_arg = ipmi_cmdlang_get_curr_arg(cmd_info);
226 int argc = ipmi_cmdlang_get_argc(cmd_info);
227 char **argv = ipmi_cmdlang_get_argv(cmd_info);
228 char fru_name[IPMI_FRU_NAME_LEN];
229 enum ipmi_fru_data_type_e dtype;
230 int i;
231 int num;
232 const char *name;
233 int ival;
234 double dval;
235 int rv;
236 int len;
237 unsigned char *data;
238 int j;
239 int type;
240 int version;
241
242 if ((argc - curr_arg) < 2) {
243 /* Not enough parameters */
244 cmdlang->errstr = "Not enough parameters";
245 cmdlang->err = EINVAL;
246 goto out_err;
247 }
248
249 if (strcmp(argv[curr_arg], "multi_record") == 0)
250 goto do_multi_record;
251
252 for (i=0; ; i++) {
253 num = -2;
254 rv = ipmi_fru_get(fru, i, &name, &num, &dtype, NULL, NULL, NULL, NULL);
255 if (rv == EINVAL) {
256 cmdlang->errstr = "Name not found";
257 cmdlang->err = EINVAL;
258 goto out_err;
259 }
260 if (strcmp(name, argv[curr_arg]) == 0)
261 break;
262 }
263 curr_arg++;
264
265 if (num != -2) {
266 /* Need the number */
267 ipmi_cmdlang_get_int(argv[curr_arg], &num, cmd_info);
268 if (cmdlang->err) {
269 cmdlang->errstr = "value number";
270 goto out_err;
271 }
272 curr_arg++;
273
274 if ((argc - curr_arg) < 1) {
275 /* Not enough parameters */
276 cmdlang->errstr = "Not enough parameters";
277 cmdlang->err = EINVAL;
278 goto out_err;
279 }
280 }
281
282 switch (dtype) {
283 case IPMI_FRU_DATA_TIME:
284 ipmi_cmdlang_get_int(argv[curr_arg], &ival, cmd_info);
285 if (cmdlang->err) {
286 cmdlang->errstr = "value invalid";
287 goto out_err;
288 }
289 curr_arg++;
290 rv = ipmi_fru_set_time_val(fru, i, num, ival);
291 if (rv) {
292 cmdlang->errstr = "value invalid";
293 cmdlang->err = EINVAL;
294 goto out_err;
295 }
296 break;
297
298 case IPMI_FRU_DATA_INT:
299 ipmi_cmdlang_get_int(argv[curr_arg], &ival, cmd_info);
300 if (cmdlang->err) {
301 cmdlang->errstr = "value invalid";
302 goto out_err;
303 }
304 curr_arg++;
305 rv = ipmi_fru_set_int_val(fru, i, num, ival);
306 if (rv) {
307 cmdlang->errstr = "value invalid";
308 cmdlang->err = EINVAL;
309 goto out_err;
310 }
311 break;
312
313 case IPMI_FRU_DATA_BOOLEAN:
314 ipmi_cmdlang_get_bool(argv[curr_arg], &ival, cmd_info);
315 if (cmdlang->err) {
316 cmdlang->errstr = "value invalid";
317 goto out_err;
318 }
319 curr_arg++;
320 rv = ipmi_fru_set_int_val(fru, i, num, ival);
321 if (rv) {
322 cmdlang->errstr = "value invalid";
323 cmdlang->err = EINVAL;
324 goto out_err;
325 }
326 break;
327
328 case IPMI_FRU_DATA_FLOAT:
329 ipmi_cmdlang_get_double(argv[curr_arg], &dval, cmd_info);
330 if (cmdlang->err) {
331 cmdlang->errstr = "value invalid";
332 goto out_err;
333 }
334 curr_arg++;
335 rv = ipmi_fru_set_float_val(fru, i, num, dval);
336 if (rv) {
337 cmdlang->errstr = "value invalid";
338 cmdlang->err = EINVAL;
339 goto out_err;
340 }
341 break;
342
343 case IPMI_FRU_DATA_ASCII:
344 case IPMI_FRU_DATA_BINARY:
345 case IPMI_FRU_DATA_UNICODE:
346 if ((argc - curr_arg) < 1) {
347 /* Not enough parameters */
348 cmdlang->errstr = "Not enough parameters";
349 cmdlang->err = EINVAL;
350 goto out_err;
351 }
352 if (strcasecmp(argv[curr_arg], "binary") == 0) {
353 dtype = IPMI_FRU_DATA_BINARY;
354 } else if (strcasecmp(argv[curr_arg], "ascii") == 0) {
355 dtype = IPMI_FRU_DATA_ASCII;
356 } else if (strcasecmp(argv[curr_arg], "unicode") == 0) {
357 dtype = IPMI_FRU_DATA_UNICODE;
358 } else {
359 cmdlang->errstr = "Invalid data type";
360 cmdlang->err = EINVAL;
361 goto out_err;
362 }
363 curr_arg++;
364 if (dtype == IPMI_FRU_DATA_ASCII) {
365 char *str;
366 int len;
367 if (curr_arg < argc) {
368 str = argv[curr_arg];
369 len = strlen(str);
370 } else {
371 str = NULL;
372 len = 0;
373 }
374 rv = ipmi_fru_set_data_val(fru, i, num, dtype, str, len);
375 } else {
376 len = argc - curr_arg;
377
378 if (len == 0)
379 data = ipmi_mem_alloc(1);
380 else
381 data = ipmi_mem_alloc(len);
382 if (!data) {
383 cmdlang->errstr = "Out of memory";
384 cmdlang->err = ENOMEM;
385 goto out_err;
386 }
387 j = 0;
388 while (curr_arg < argc) {
389 ipmi_cmdlang_get_int(argv[curr_arg], &ival, cmd_info);
390 if (cmdlang->err) {
391 cmdlang->errstr = "value invalid";
392 ipmi_mem_free(data);
393 goto out_err;
394 }
395 data[j] = ival;
396 curr_arg++;
397 j++;
398 }
399 rv = ipmi_fru_set_data_val(fru, i, num, dtype, (char *) data, len);
400 ipmi_mem_free(data);
401 }
402 if (rv) {
403 cmdlang->errstr = "Error setting data value";
404 cmdlang->err = rv;
405 goto out_err;
406 }
407
408 case IPMI_FRU_DATA_SUB_NODE:
409 /* Not relevant for normal FRU data. */
410 break;
411 }
412
413 goto out;
414
415 do_multi_record:
416 curr_arg++;
417 if ((argc - curr_arg) < 1) {
418 /* Not enough parameters */
419 cmdlang->errstr = "Not enough parameters";
420 cmdlang->err = EINVAL;
421 goto out_err;
422 }
423
424 ipmi_cmdlang_get_int(argv[curr_arg], &num, cmd_info);
425 if (cmdlang->err) {
426 cmdlang->errstr = "value number";
427 goto out_err;
428 }
429 curr_arg++;
430
431 if ((argc - curr_arg) == 0) {
432 /* Deleting the record. */
433 rv = ipmi_fru_set_multi_record(fru, num, 0, 0, NULL, 0);
434 if (rv) {
435 cmdlang->errstr = "Error clearing data value";
436 cmdlang->err = rv;
437 goto out_err;
438 }
439 goto out;
440 }
441
442 if ((argc - curr_arg) < 2) {
443 /* Not enough parameters */
444 cmdlang->errstr = "Not enough parameters";
445 cmdlang->err = EINVAL;
446 goto out_err;
447 }
448
449 ipmi_cmdlang_get_int(argv[curr_arg], &type, cmd_info);
450 if (cmdlang->err) {
451 cmdlang->errstr = "type number";
452 goto out_err;
453 }
454 curr_arg++;
455
456 ipmi_cmdlang_get_int(argv[curr_arg], &version, cmd_info);
457 if (cmdlang->err) {
458 cmdlang->errstr = "version number";
459 goto out_err;
460 }
461 curr_arg++;
462
463 len = argc - curr_arg;
464
465 if (len == 0)
466 data = ipmi_mem_alloc(1);
467 else
468 data = ipmi_mem_alloc(len);
469 if (!data) {
470 cmdlang->errstr = "Out of memory";
471 cmdlang->err = ENOMEM;
472 goto out_err;
473 }
474 j = 0;
475 while (curr_arg < argc) {
476 ipmi_cmdlang_get_int(argv[curr_arg], &ival, cmd_info);
477 if (cmdlang->err) {
478 cmdlang->errstr = "value invalid";
479 ipmi_mem_free(data);
480 goto out_err;
481 }
482 data[j] = ival;
483 curr_arg++;
484 j++;
485 }
486 rv = ipmi_fru_set_multi_record(fru, num, type, version, data, len);
487 ipmi_mem_free(data);
488 if (rv) {
489 cmdlang->errstr = "Error setting data value";
490 cmdlang->err = rv;
491 goto out_err;
492 }
493
494 out:
495 ipmi_fru_get_name(fru, fru_name, sizeof(fru_name));
496 ipmi_cmdlang_out(cmd_info, "FRU value set", fru_name);
497
498 return;
499
500 out_err:
501 ipmi_fru_get_name(fru, cmdlang->objstr,
502 cmdlang->objstr_len);
503 cmdlang->location = "cmd_fru.c(fru_setval)";
504 }
505
506 static void
get_fru_by_name(char * name,ipmi_cmdlang_t * cmdlang,unsigned int * area)507 get_fru_by_name(char *name, ipmi_cmdlang_t *cmdlang, unsigned int *area)
508 {
509 if (strcmp(name, "internal_data") == 0) {
510 *area = IPMI_FRU_FTR_INTERNAL_USE_AREA;
511 } else if (strcmp(name, "chassis_info") == 0) {
512 *area = IPMI_FRU_FTR_CHASSIS_INFO_AREA;
513 } else if (strcmp(name, "board_info") == 0) {
514 *area = IPMI_FRU_FTR_BOARD_INFO_AREA ;
515 } else if (strcmp(name, "product_info") == 0) {
516 *area = IPMI_FRU_FTR_PRODUCT_INFO_AREA;
517 } else if (strcmp(name, "multi_record") == 0) {
518 *area = IPMI_FRU_FTR_MULTI_RECORD_AREA;
519 } else {
520 cmdlang->errstr = "Invalid area name";
521 cmdlang->err = EINVAL;
522 }
523 }
524
525 static void
fru_area_offset(ipmi_fru_t * fru,void * cb_data)526 fru_area_offset(ipmi_fru_t *fru, void *cb_data)
527 {
528 ipmi_cmd_info_t *cmd_info = cb_data;
529 ipmi_cmdlang_t *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
530 int curr_arg = ipmi_cmdlang_get_curr_arg(cmd_info);
531 int argc = ipmi_cmdlang_get_argc(cmd_info);
532 char **argv = ipmi_cmdlang_get_argv(cmd_info);
533 char fru_name[IPMI_FRU_NAME_LEN];
534 unsigned int area;
535 int offset;
536 int rv;
537
538 if ((argc - curr_arg) < 2) {
539 /* Not enough parameters */
540 cmdlang->errstr = "Not enough parameters";
541 cmdlang->err = EINVAL;
542 goto out_err;
543 }
544
545 get_fru_by_name(argv[curr_arg], cmdlang, &area);
546 if (cmdlang->err)
547 goto out_err;
548 curr_arg++;
549
550 ipmi_cmdlang_get_int(argv[curr_arg], &offset, cmd_info);
551 if (cmdlang->err) {
552 cmdlang->errstr = "offset invalid";
553 goto out_err;
554 }
555
556 rv = ipmi_fru_area_set_offset(fru, area, offset);
557 if (rv) {
558 cmdlang->errstr = "Error setting area offset";
559 cmdlang->err = rv;
560 goto out_err;
561 }
562
563 ipmi_fru_get_name(fru, fru_name, sizeof(fru_name));
564 ipmi_cmdlang_out(cmd_info, "FRU area offset set", fru_name);
565 return;
566
567 out_err:
568 ipmi_fru_get_name(fru, cmdlang->objstr,
569 cmdlang->objstr_len);
570 cmdlang->location = "cmd_fru.c(fru_area_offset)";
571 }
572
573 static void
fru_area_length(ipmi_fru_t * fru,void * cb_data)574 fru_area_length(ipmi_fru_t *fru, void *cb_data)
575 {
576 ipmi_cmd_info_t *cmd_info = cb_data;
577 ipmi_cmdlang_t *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
578 int curr_arg = ipmi_cmdlang_get_curr_arg(cmd_info);
579 int argc = ipmi_cmdlang_get_argc(cmd_info);
580 char **argv = ipmi_cmdlang_get_argv(cmd_info);
581 char fru_name[IPMI_FRU_NAME_LEN];
582 unsigned int area;
583 int length;
584 int rv;
585
586 if ((argc - curr_arg) < 2) {
587 /* Not enough parameters */
588 cmdlang->errstr = "Not enough parameters";
589 cmdlang->err = EINVAL;
590 goto out_err;
591 }
592
593 get_fru_by_name(argv[curr_arg], cmdlang, &area);
594 if (cmdlang->err)
595 goto out_err;
596 curr_arg++;
597
598 ipmi_cmdlang_get_int(argv[curr_arg], &length, cmd_info);
599 if (cmdlang->err) {
600 cmdlang->errstr = "length invalid";
601 goto out_err;
602 }
603
604 rv = ipmi_fru_area_set_length(fru, area, length);
605 if (rv) {
606 cmdlang->errstr = "Error setting area length";
607 cmdlang->err = rv;
608 goto out_err;
609 }
610
611 ipmi_fru_get_name(fru, fru_name, sizeof(fru_name));
612 ipmi_cmdlang_out(cmd_info, "FRU area length set", fru_name);
613 return;
614
615 out_err:
616 ipmi_fru_get_name(fru, cmdlang->objstr,
617 cmdlang->objstr_len);
618 cmdlang->location = "cmd_fru.c(fru_area_length)";
619 }
620
621 static void
fru_area_add(ipmi_fru_t * fru,void * cb_data)622 fru_area_add(ipmi_fru_t *fru, void *cb_data)
623 {
624 ipmi_cmd_info_t *cmd_info = cb_data;
625 ipmi_cmdlang_t *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
626 int curr_arg = ipmi_cmdlang_get_curr_arg(cmd_info);
627 int argc = ipmi_cmdlang_get_argc(cmd_info);
628 char **argv = ipmi_cmdlang_get_argv(cmd_info);
629 char fru_name[IPMI_FRU_NAME_LEN];
630 unsigned int area;
631 int length, offset;
632 int rv;
633
634 if ((argc - curr_arg) < 3) {
635 /* Not enough parameters */
636 cmdlang->errstr = "Not enough parameters";
637 cmdlang->err = EINVAL;
638 goto out_err;
639 }
640
641 get_fru_by_name(argv[curr_arg], cmdlang, &area);
642 if (cmdlang->err)
643 goto out_err;
644 curr_arg++;
645
646 ipmi_cmdlang_get_int(argv[curr_arg], &offset, cmd_info);
647 if (cmdlang->err) {
648 cmdlang->errstr = "offset invalid";
649 goto out_err;
650 }
651 curr_arg++;
652
653 ipmi_cmdlang_get_int(argv[curr_arg], &length, cmd_info);
654 if (cmdlang->err) {
655 cmdlang->errstr = "length invalid";
656 goto out_err;
657 }
658 curr_arg++;
659
660 rv = ipmi_fru_add_area(fru, area, offset, length);
661 if (rv) {
662 cmdlang->errstr = "Error adding area";
663 cmdlang->err = rv;
664 goto out_err;
665 }
666
667 ipmi_fru_get_name(fru, fru_name, sizeof(fru_name));
668 ipmi_cmdlang_out(cmd_info, "FRU area added", fru_name);
669 return;
670
671 out_err:
672 ipmi_fru_get_name(fru, cmdlang->objstr,
673 cmdlang->objstr_len);
674 cmdlang->location = "cmd_fru.c(fru_area_add)";
675 }
676
677 static void
fru_area_delete(ipmi_fru_t * fru,void * cb_data)678 fru_area_delete(ipmi_fru_t *fru, void *cb_data)
679 {
680 ipmi_cmd_info_t *cmd_info = cb_data;
681 ipmi_cmdlang_t *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
682 int curr_arg = ipmi_cmdlang_get_curr_arg(cmd_info);
683 int argc = ipmi_cmdlang_get_argc(cmd_info);
684 char **argv = ipmi_cmdlang_get_argv(cmd_info);
685 char fru_name[IPMI_FRU_NAME_LEN];
686 unsigned int area;
687 int rv;
688
689 if ((argc - curr_arg) < 1) {
690 /* Not enough parameters */
691 cmdlang->errstr = "Not enough parameters";
692 cmdlang->err = EINVAL;
693 goto out_err;
694 }
695
696 get_fru_by_name(argv[curr_arg], cmdlang, &area);
697 if (cmdlang->err)
698 goto out_err;
699 curr_arg++;
700
701 rv = ipmi_fru_delete_area(fru, area);
702 if (rv) {
703 cmdlang->errstr = "Error deleting area";
704 cmdlang->err = rv;
705 goto out_err;
706 }
707
708 ipmi_fru_get_name(fru, fru_name, sizeof(fru_name));
709 ipmi_cmdlang_out(cmd_info, "FRU area deleted", fru_name);
710 return;
711
712 out_err:
713 ipmi_fru_get_name(fru, cmdlang->objstr,
714 cmdlang->objstr_len);
715 cmdlang->location = "cmd_fru.c(fru_area_delete)";
716 }
717
718 static ipmi_cmdlang_cmd_t *fru_cmds;
719
720 static ipmi_cmdlang_init_t cmds_fru[] =
721 {
722 { "fru", NULL,
723 "- Commands dealing with FRUs",
724 NULL, NULL, &fru_cmds},
725 { "list", &fru_cmds,
726 "- List all the frus in the system",
727 ipmi_cmdlang_domain_handler, fru_list, NULL },
728 { "info", &fru_cmds,
729 "<fru> - Dump information about a FRU",
730 ipmi_cmdlang_fru_handler, fru_info, NULL },
731 { "areainfo", &fru_cmds,
732 "<fru> - Dump the info about the FRU's areas",
733 ipmi_cmdlang_fru_handler, fru_areainfo, NULL },
734 { "write", &fru_cmds,
735 "<fru> - Write the local FRU data out into the FRU",
736 ipmi_cmdlang_fru_handler, fru_write, NULL },
737 { "close", &fru_cmds,
738 "<fru> - Delete the FRU",
739 ipmi_cmdlang_fru_handler, fru_close, NULL },
740 { "setval", &fru_cmds,
741 "<fru> <name> [num] value - Set the value of a FRU element. The"
742 " name is the record name, or multi_record. The number is required"
743 " for fields that need it (custom and multi-record). The value is"
744 " an a single value for integers. For strings it is a string"
745 " type (either binary, ascii, or unicode) and the info. Binary and"
746 " unicode data is specified as numbers. ascii data is specified in"
747 " a string. Note that setting a ascii value with no string will"
748 " clear the value. Zero length strings and data is valid. For"
749 " multi_record, the value is <type> <version> [<data> ...]",
750 ipmi_cmdlang_fru_handler, fru_setval, NULL },
751 { "area_offset", &fru_cmds,
752 "<fru> <area name> <offset> - Set the offset of the given area"
753 " to the given value. Area names are internal_data, chassis_info,"
754 " board_info, product_info, and multi_record",
755 ipmi_cmdlang_fru_handler, fru_area_offset, NULL },
756 { "area_length", &fru_cmds,
757 "<fru> <area name> <length> - Set the length of the given area"
758 " to the given value. Area names are internal_data, chassis_info,"
759 " board_info, product_info, and multi_record",
760 ipmi_cmdlang_fru_handler, fru_area_length, NULL },
761 { "area_add", &fru_cmds,
762 "<fru> <area name> <offset> <length> - Add the given area to the FRU",
763 ipmi_cmdlang_fru_handler, fru_area_add, NULL },
764 { "area_delete", &fru_cmds,
765 "<fru> <area name> - Delete the given area from the FRU",
766 ipmi_cmdlang_fru_handler, fru_area_delete, NULL },
767 };
768 #define CMDS_FRU_LEN (sizeof(cmds_fru)/sizeof(ipmi_cmdlang_init_t))
769
770 int
ipmi_cmdlang_fru_init(os_handler_t * os_hnd)771 ipmi_cmdlang_fru_init(os_handler_t *os_hnd)
772 {
773 return ipmi_cmdlang_reg_table(cmds_fru, CMDS_FRU_LEN);
774 }
775