ses: SUN plugin doesn't actually need libnvfru
[unleashed.git] / usr / src / lib / libfru / libfruraw / fruraw.c
blob2e5ab31ce63520330699fcca0f5aaa98fb140a0a
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
26 #include <stdio.h>
27 #include <stdarg.h>
28 #include <stdlib.h>
29 #include <errno.h>
30 #include <string.h>
32 #include "fru_access_impl.h"
34 #include "libfruds.h"
35 #include "libfrup.h"
36 #include "fru_access.h"
37 #include "fruraw.h"
40 raw_list_t *g_raw = NULL;
43 /* ARGSUSED */
44 static raw_list_t *
45 treehdl_to_rawlist(fru_treehdl_t handle)
47 return (g_raw);
51 static container_hdl_t
52 treehdl_to_conthdl(fru_treehdl_t handle)
54 raw_list_t *ptr;
56 ptr = treehdl_to_rawlist(handle);
57 if (ptr == NULL) {
58 return (-1);
61 return (ptr->cont);
65 static fru_errno_t
66 map_errno(int err)
68 switch (err) {
69 case ENFILE:
70 case EEXIST:
71 return (FRU_DUPSEG);
72 case EAGAIN:
73 return (FRU_NOSPACE);
74 case EPERM:
75 return (FRU_INVALPERM);
76 default :
77 return (FRU_IOERROR);
82 static raw_list_t *
83 make_raw(uint8_t *buffer, size_t size, char *cont_type)
85 raw_list_t *node;
87 node = (raw_list_t *)malloc(sizeof (raw_list_t));
88 if (node == NULL) {
89 return (NULL);
92 node->hdl = 0;
93 node->raw = buffer;
94 node->size = size;
95 node->cont_type = strdup(cont_type);
96 if (node->cont_type == NULL) {
97 free(node);
98 return (NULL);
100 node->segs = NULL;
102 return (node);
107 * Arguments :
108 * 0 - pointer to byte buffer (in)
109 * 1 - size of buffer (in)
110 * 2 - container type, string (in)
112 static fru_errno_t
113 frt_initialize(int num, char **args)
117 if (num != 3) {
118 return (FRU_FAILURE);
121 g_raw = make_raw((uint8_t *)args[0], (size_t)args[1], args[2]);
122 if (g_raw == NULL) {
123 return (FRU_FAILURE);
126 g_raw->cont = open_raw_data(g_raw);
127 if (g_raw->cont == 0) {
128 return (FRU_FAILURE);
131 return (FRU_SUCCESS);
135 static fru_errno_t
136 frt_shutdown(void)
138 segment_list_t *lptr, *lptr2;
140 (void) fru_close_container(g_raw->cont);
141 free(g_raw->cont_type);
142 lptr = g_raw->segs;
143 while (lptr) {
144 lptr2 = lptr;
145 lptr = lptr->next;
146 free(lptr2);
148 g_raw = NULL;
150 return (FRU_SUCCESS);
154 static fru_errno_t
155 frt_get_root(fru_treehdl_t *node)
157 *node = g_raw->hdl;
159 return (FRU_SUCCESS);
162 /* ARGSUSED */
163 static fru_errno_t
164 frt_get_peer(fru_treehdl_t sibling, fru_treehdl_t *peer)
166 return (FRU_NODENOTFOUND);
168 /* ARGSUSED */
169 static fru_errno_t
170 frt_get_child(fru_treehdl_t handle, fru_treehdl_t *child)
172 return (FRU_NODENOTFOUND);
175 /* ARGSUSED */
176 static fru_errno_t
177 frt_get_parent(fru_treehdl_t handle, fru_treehdl_t *parent)
179 return (FRU_NODENOTFOUND);
182 /* ARGSUSED */
183 static fru_errno_t
184 frt_get_name_from_hdl(fru_treehdl_t handle, char **name)
186 *name = strdup("unknown");
187 return (FRU_SUCCESS);
190 /* ARGSUSED */
191 static fru_errno_t
192 frt_get_node_type(fru_treehdl_t node, fru_node_t *type)
194 *type = FRU_NODE_CONTAINER;
195 return (FRU_SUCCESS);
200 static fru_errno_t
201 add_segs_for_section(section_t *section, fru_strlist_t *list)
203 int i = 0;
204 segment_t *segs = NULL;
205 int acc_err = 0;
207 int num_segment = fru_get_num_segments(section->handle, NULL);
208 if (num_segment == -1) {
209 return (map_errno(errno));
210 } else if (num_segment == 0) {
211 return (FRU_SUCCESS);
214 segs = malloc(sizeof (*segs) * (num_segment));
215 if (segs == NULL) {
216 return (FRU_FAILURE);
219 acc_err = fru_get_segments(section->handle, segs, num_segment, NULL);
220 if (acc_err == -1) {
221 free(segs);
222 return (map_errno(errno));
225 list->strs = reallocarray(list->strs, list->num + num_segment,
226 sizeof (char *));
228 for (i = 0; i < num_segment; i++) {
229 /* ensure NULL terminated. */
230 char *tmp = malloc(sizeof (*tmp) * (sizeof (segs[i].name)+1));
231 if (tmp == NULL) {
232 free(segs);
233 return (FRU_FAILURE);
235 (void) memcpy(tmp, segs[i].name, sizeof (segs[i].name));
236 tmp[sizeof (segs[i].name)] = '\0';
238 list->strs[(list->num)++] = tmp;
241 free(segs);
243 return (FRU_SUCCESS);
248 static fru_errno_t
249 frt_get_seg_list(fru_treehdl_t handle, fru_strlist_t *list)
251 fru_strlist_t rc_list;
252 fru_errno_t err = FRU_SUCCESS;
253 int acc_err = 0;
254 int i = 0;
255 int num_section = 0;
256 section_t *sects = NULL;
257 container_hdl_t cont;
259 cont = treehdl_to_conthdl(handle);
261 num_section = fru_get_num_sections(cont, NULL);
262 if (num_section == -1) {
263 return (map_errno(errno));
266 sects = malloc(sizeof (*sects) * (num_section));
267 if (sects == NULL) {
268 return (FRU_FAILURE);
271 acc_err = fru_get_sections(cont, sects, num_section, NULL);
272 if (acc_err == -1) {
273 free(sects);
274 return (map_errno(errno));
277 rc_list.num = 0;
278 rc_list.strs = NULL;
279 for (i = 0; i < num_section; i++) {
280 if ((err = add_segs_for_section(&(sects[i]), &rc_list))
281 != FRU_SUCCESS) {
282 fru_destroy_strlist(&rc_list);
283 free(sects);
284 return (err);
288 list->strs = rc_list.strs;
289 list->num = rc_list.num;
291 return (FRU_SUCCESS);
295 static fru_errno_t
296 find_seg_in_sect(section_t *sect, const char *seg_name, int *prot_flg,
297 segment_t *segment)
299 int j = 0;
300 int acc_err = 0;
301 segment_t *segs = NULL;
303 int num_seg = fru_get_num_segments(sect->handle, NULL);
304 if (num_seg == -1) {
305 return (FRU_FAILURE);
308 segs = malloc(sizeof (*segs) * (num_seg));
309 if (segs == NULL) {
310 return (FRU_FAILURE);
313 acc_err = fru_get_segments(sect->handle, segs, num_seg, NULL);
314 if (acc_err == -1) {
315 free(segs);
316 return (map_errno(errno));
319 for (j = 0; j < num_seg; j++) {
320 /* NULL terminate */
321 char tmp[SEG_NAME_LEN+1];
322 (void) memcpy(tmp, segs[j].name, SEG_NAME_LEN);
323 tmp[SEG_NAME_LEN] = '\0';
324 if (strcmp(tmp, seg_name) == 0) {
325 *segment = segs[j];
326 *prot_flg = (sect->protection ? 1 : 0);
327 free(segs);
328 return (FRU_SUCCESS);
332 free(segs);
333 return (FRU_INVALSEG);
337 static fru_errno_t
338 find_segment(fru_treehdl_t handle, const char *seg_name, int *prot_flg,
339 segment_t *segment)
341 int i = 0;
342 int acc_err = 0;
343 section_t *sect = NULL;
344 container_hdl_t cont;
345 int num_sect;
347 cont = treehdl_to_conthdl(handle);
349 num_sect = fru_get_num_sections(cont, NULL);
350 if (num_sect == -1) {
351 return (map_errno(errno));
354 sect = malloc(sizeof (*sect) * (num_sect));
355 if (sect == NULL) {
356 return (FRU_FAILURE);
359 acc_err = fru_get_sections(cont, sect, num_sect, NULL);
360 if (acc_err == -1) {
361 free(sect);
362 return (map_errno(errno));
365 for (i = 0; i < num_sect; i++) {
366 if (find_seg_in_sect(&(sect[i]), seg_name, prot_flg, segment)
367 == FRU_SUCCESS) {
368 free(sect);
369 return (FRU_SUCCESS);
373 free(sect);
374 return (FRU_INVALSEG);
378 static fru_errno_t
379 frt_get_seg_def(fru_treehdl_t handle, const char *seg_name, fru_segdef_t *def)
381 fru_errno_t err = FRU_SUCCESS;
382 int prot_flg = 0;
383 segment_t segment;
385 if ((err = find_segment(handle, seg_name, &prot_flg, &segment))
386 != FRU_SUCCESS) {
387 return (err);
390 (void) memcpy(def->name, segment.name, SEG_NAME_LEN);
391 def->name[SEG_NAME_LEN] = '\0';
392 def->desc.raw_data = segment.descriptor;
393 def->size = segment.length;
394 def->address = segment.offset;
396 if (prot_flg == 0)
397 def->hw_desc.field.read_only = 0;
398 else
399 def->hw_desc.field.read_only = 1;
401 return (FRU_SUCCESS);
405 /* ARGSUSED */
406 static fru_errno_t
407 frt_add_seg(fru_treehdl_t handle, fru_segdef_t *def)
409 /* NOT SUPPORTED */
410 return (FRU_NOTSUP);
413 /* ARGSUSED */
414 static fru_errno_t
415 frt_delete_seg(fru_treehdl_t handle, const char *seg_name)
417 /* NOT SUPPORTED */
418 return (FRU_NOTSUP);
421 /* ARGSUSED */
422 static fru_errno_t
423 frt_for_each_segment(fru_nodehdl_t node,
424 int (*function)(fru_seghdl_t hdl, void *args), void *args)
426 int num_segment;
427 int cnt;
428 int num_sect;
429 int each_seg;
430 section_t *sects;
431 segment_t *segs;
432 segment_list_t *tmp_list;
433 int acc_err;
434 int status;
435 container_hdl_t cont;
437 cont = g_raw->cont;
439 num_sect = fru_get_num_sections(cont, NULL);
440 if (num_sect == -1) {
441 return (map_errno(errno));
444 sects = malloc((num_sect + 1) * sizeof (section_t));
445 if (sects == NULL) {
446 return (FRU_FAILURE);
448 num_sect = fru_get_sections(cont, sects, num_sect, NULL);
449 if (num_sect == -1) {
450 free(sects);
451 return (map_errno(errno));
453 for (cnt = 0; cnt < num_sect; cnt++) {
454 num_segment = fru_get_num_segments(sects[cnt].handle, NULL);
455 if (num_segment == -1) {
456 return (map_errno(errno));
457 } else if (num_segment == 0) {
458 continue;
460 segs = malloc((num_segment + 1) * sizeof (segment_t));
461 if (segs == NULL) {
462 free(sects);
463 return (FRU_FAILURE);
465 acc_err = fru_get_segments(sects[cnt].handle, segs,
466 num_segment, NULL);
467 if (acc_err == -1) {
468 free(sects);
469 free(segs);
470 return (map_errno(errno));
472 for (each_seg = 0; each_seg < num_segment; each_seg++) {
473 tmp_list = malloc(sizeof (segment_list_t));
474 tmp_list->segment = &segs[each_seg];
475 tmp_list->next = NULL;
476 if (g_raw->segs == NULL) {
477 g_raw->segs = tmp_list;
478 } else {
479 tmp_list->next = g_raw->segs;
480 g_raw->segs = tmp_list;
483 if ((status = function(segs[each_seg].handle, args))
484 != FRU_SUCCESS) {
485 free(segs);
486 free(sects);
487 return (status);
490 free(segs);
491 free(sects);
494 return (FRU_SUCCESS);
498 static fru_errno_t
499 frt_get_segment_name(fru_seghdl_t node, char **name)
501 int num_sect;
502 int acc_err;
503 int cnt;
504 int num_segment;
505 section_t *sects;
506 segment_t *segs;
507 int each_seg;
508 container_hdl_t cont;
510 cont = treehdl_to_conthdl(node);
512 num_sect = fru_get_num_sections(cont, NULL);
513 if (num_sect == -1) {
514 return (map_errno(errno));
517 sects = malloc(sizeof (*sects) * (num_sect));
518 if (sects == NULL) {
519 return (FRU_FAILURE);
521 acc_err = fru_get_sections(cont, sects, num_sect, NULL);
522 if (acc_err == -1) {
523 free(sects);
524 return (map_errno(errno));
527 for (cnt = 0; cnt < num_sect; cnt++) {
528 num_segment = fru_get_num_segments(sects[cnt].handle, NULL);
529 if (num_segment == -1) {
530 free(sects);
531 return (map_errno(errno));
532 } else if (num_segment == 0) {
533 continue;
536 segs = malloc(sizeof (*segs) * (num_segment));
537 if (segs == NULL) {
538 free(sects);
539 return (FRU_FAILURE);
542 acc_err = fru_get_segments(sects[cnt].handle, segs,
543 num_segment, NULL);
544 if (acc_err == -1) {
545 free(sects);
546 free(segs);
547 return (map_errno(errno));
550 for (each_seg = 0; each_seg < num_segment; each_seg++) {
551 if (segs[each_seg].handle == node) {
552 segs[each_seg].name[FRU_SEGNAMELEN] = '\0';
553 *name = strdup(segs[each_seg].name);
554 free(sects);
555 free(segs);
556 return (FRU_SUCCESS);
559 free(segs);
562 return (FRU_FAILURE);
566 /* ARGSUSED */
567 static fru_errno_t
568 frt_add_tag_to_seg(fru_treehdl_t handle, const char *seg_name,
569 fru_tag_t tag, uint8_t *data, size_t data_len)
571 /* NOT SUPPORTED */
572 return (FRU_NOTSUP);
576 /* ARGSUSED */
577 static fru_errno_t
578 frt_get_tag_list(fru_treehdl_t handle, const char *seg_name,
579 fru_tag_t **tags, int *number)
581 /* NOT SUPPORTED */
582 return (FRU_NOTSUP);
586 /* ARGSUSED */
587 static fru_errno_t
588 frt_get_tag_data(fru_treehdl_t handle, const char *seg_name, fru_tag_t tag,
589 int instance, uint8_t **data, size_t *data_len)
591 /* NOT SUPPORTED */
592 return (FRU_NOTSUP);
596 /* ARGSUSED */
597 static fru_errno_t
598 frt_set_tag_data(fru_treehdl_t handle, const char *seg_name, fru_tag_t tag,
599 int instance, uint8_t *data, size_t data_len)
601 /* NOT SUPPORTED */
602 return (FRU_NOTSUP);
606 /* ARGSUSED */
607 static fru_errno_t
608 frt_delete_tag(fru_treehdl_t handle, const char *seg_name, fru_tag_t tag,
609 int instance)
611 /* NOT SUPPORTED */
612 return (FRU_NOTSUP);
616 static fru_errno_t
617 frt_for_each_packet(fru_seghdl_t node, int (*function)(fru_tag_t *tag,
618 uint8_t *payload, size_t length, void *args), void *args)
620 int rc_num;
621 int status;
622 char *rc_data;
623 int i;
624 packet_t *packets = NULL;
625 segment_list_t *tmp_list;
626 fru_segdesc_t *descriptor;
628 tmp_list = g_raw->segs;
630 /* num of packet */
631 rc_num = fru_get_num_packets(node, NULL);
632 if (rc_num == -1) {
633 return (map_errno(errno));
634 } else if (rc_num == 0) {
635 return (FRU_SUCCESS);
637 while (tmp_list) {
638 if (node == tmp_list->segment->handle) {
639 break;
641 tmp_list = tmp_list->next;
643 if (tmp_list) {
644 descriptor = (fru_segdesc_t *)&tmp_list->segment->descriptor;
645 if (descriptor->field.opaque) {
646 return (FRU_SUCCESS);
649 if (descriptor->field.encrypted && (encrypt_func == NULL)) {
650 return (FRU_SUCCESS);
654 packets = malloc(sizeof (*packets) * (rc_num));
655 if (packets == NULL) {
656 return (FRU_FAILURE);
658 /* get all packets */
659 if (fru_get_packets(node, packets, rc_num, NULL) == -1) {
660 free(packets);
661 return (map_errno(errno));
664 /* number of tags */
665 for (i = 0; i < rc_num; i++) {
666 size_t rc_len =
667 get_payload_length((fru_tag_t *)&packets[i].tag);
669 rc_data = malloc(sizeof (*rc_data) * (rc_len));
670 if (rc_data == NULL) {
671 free(packets);
672 return (FRU_FAILURE);
674 /* get the payload data */
675 (void) fru_get_payload(packets[i].handle, (void *)rc_data,
676 rc_len, NULL);
678 if (tmp_list) {
679 descriptor =
680 (fru_segdesc_t *)&tmp_list->segment->descriptor;
682 if ((descriptor->field.encrypted) &&
683 ((status = encrypt_func(FRU_DECRYPT,
684 (void *)rc_data, rc_len))
685 != FRU_SUCCESS)) {
686 return (status);
689 /* print packet */
690 if ((status = function((fru_tag_t *)&packets[i].tag,
691 (uint8_t *)rc_data, rc_len, args)) != FRU_SUCCESS) {
692 free(rc_data);
693 free(packets);
694 return (status);
696 free(rc_data);
698 return (FRU_SUCCESS);
703 /* object for libfru to link to */
704 fru_datasource_t data_source =
706 LIBFRU_DS_VER,
707 frt_initialize,
708 frt_shutdown,
709 frt_get_root,
710 frt_get_child,
711 frt_get_peer,
712 frt_get_parent,
713 frt_get_name_from_hdl,
714 frt_get_node_type,
715 frt_get_seg_list,
716 frt_get_seg_def,
717 frt_add_seg,
718 frt_delete_seg,
719 frt_for_each_segment,
720 frt_get_segment_name,
721 frt_add_tag_to_seg,
722 frt_get_tag_list,
723 frt_get_tag_data,
724 frt_set_tag_data,
725 frt_delete_tag,
726 frt_for_each_packet