fruraw.c revision 11015:0a0751599d31
1/*
2 * CDDL HEADER START
3 *
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.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#include <stdio.h>
28#include <stdarg.h>
29#include <stdlib.h>
30#include <errno.h>
31#include <string.h>
32
33#include "fru_access_impl.h"
34
35#include "libfruds.h"
36#include "libfrup.h"
37#include "fru_access.h"
38#include "fruraw.h"
39
40
41raw_list_t *g_raw = NULL;
42
43
44/* ARGSUSED */
45static raw_list_t *
46treehdl_to_rawlist(fru_treehdl_t handle)
47{
48	return (g_raw);
49}
50
51
52static container_hdl_t
53treehdl_to_conthdl(fru_treehdl_t handle)
54{
55	raw_list_t *ptr;
56
57	ptr = treehdl_to_rawlist(handle);
58	if (ptr == NULL) {
59		return (-1);
60	}
61
62	return (ptr->cont);
63}
64
65
66static fru_errno_t
67map_errno(int err)
68{
69	switch (err) {
70	case ENFILE:
71	case EEXIST:
72		return (FRU_DUPSEG);
73	case EAGAIN:
74		return (FRU_NOSPACE);
75	case EPERM:
76		return (FRU_INVALPERM);
77	default :
78		return (FRU_IOERROR);
79	}
80}
81
82
83static raw_list_t *
84make_raw(uint8_t *buffer, size_t size, char *cont_type)
85{
86	raw_list_t *node;
87
88	node = (raw_list_t *)malloc(sizeof (raw_list_t));
89	if (node == NULL) {
90		return (NULL);
91	}
92
93	node->hdl = 0;
94	node->raw = buffer;
95	node->size = size;
96	node->cont_type = strdup(cont_type);
97	if (node->cont_type == NULL) {
98		free(node);
99		return (NULL);
100	}
101	node->segs = NULL;
102
103	return (node);
104}
105
106
107/*
108 * Arguments :
109 * 0 - pointer to byte buffer (in)
110 * 1 - size of buffer (in)
111 * 2 - container type, string (in)
112 */
113static fru_errno_t
114frt_initialize(int num, char **args)
115{
116
117
118	if (num != 3) {
119		return (FRU_FAILURE);
120	}
121
122	g_raw = make_raw((uint8_t *)args[0], (size_t)args[1], args[2]);
123	if (g_raw == NULL) {
124		return (FRU_FAILURE);
125	}
126
127	g_raw->cont = open_raw_data(g_raw);
128	if (g_raw->cont == NULL) {
129		return (FRU_FAILURE);
130	}
131
132	return (FRU_SUCCESS);
133}
134
135
136static fru_errno_t
137frt_shutdown(void)
138{
139	segment_list_t *lptr, *lptr2;
140
141	(void) fru_close_container(g_raw->cont);
142	free(g_raw->cont_type);
143	lptr = g_raw->segs;
144	while (lptr) {
145		lptr2 = lptr;
146		lptr = lptr->next;
147		free(lptr2);
148	}
149	g_raw = NULL;
150
151	return (FRU_SUCCESS);
152}
153
154
155static fru_errno_t
156frt_get_root(fru_treehdl_t *node)
157{
158	*node = g_raw->hdl;
159
160	return (FRU_SUCCESS);
161}
162
163/* ARGSUSED */
164static fru_errno_t
165frt_get_peer(fru_treehdl_t sibling, fru_treehdl_t *peer)
166{
167	return (FRU_NODENOTFOUND);
168}
169/* ARGSUSED */
170static fru_errno_t
171frt_get_child(fru_treehdl_t handle, fru_treehdl_t *child)
172{
173	return (FRU_NODENOTFOUND);
174}
175
176/* ARGSUSED */
177static fru_errno_t
178frt_get_parent(fru_treehdl_t handle, fru_treehdl_t *parent)
179{
180	return (FRU_NODENOTFOUND);
181}
182
183/* ARGSUSED */
184static fru_errno_t
185frt_get_name_from_hdl(fru_treehdl_t handle, char **name)
186{
187	*name = strdup("unknown");
188	return (FRU_SUCCESS);
189}
190
191/* ARGSUSED */
192static fru_errno_t
193frt_get_node_type(fru_treehdl_t node, fru_node_t *type)
194{
195	*type = FRU_NODE_CONTAINER;
196	return (FRU_SUCCESS);
197}
198
199
200
201static fru_errno_t
202add_segs_for_section(section_t *section, fru_strlist_t *list)
203{
204	int i = 0;
205	segment_t *segs = NULL;
206	int acc_err = 0;
207
208	int num_segment = fru_get_num_segments(section->handle, NULL);
209	if (num_segment == -1) {
210		return (map_errno(errno));
211	} else if (num_segment == 0) {
212		return (FRU_SUCCESS);
213	}
214
215	segs = malloc(sizeof (*segs) * (num_segment));
216	if (segs == NULL) {
217		return (FRU_FAILURE);
218	}
219
220	acc_err = fru_get_segments(section->handle, segs, num_segment, NULL);
221	if (acc_err == -1) {
222		free(segs);
223		return (map_errno(errno));
224	}
225
226	list->strs = realloc(list->strs, sizeof (char *)
227	    * (list->num + num_segment));
228
229	for (i = 0; i < num_segment; i++) {
230		/* ensure NULL terminated. */
231		char *tmp = malloc(sizeof (*tmp) * (sizeof (segs[i].name)+1));
232		if (tmp == NULL) {
233			free(segs);
234			return (FRU_FAILURE);
235		}
236		(void) memcpy(tmp, segs[i].name, sizeof (segs[i].name));
237		tmp[sizeof (segs[i].name)] = '\0';
238
239		list->strs[(list->num)++] = tmp;
240	}
241
242	free(segs);
243
244	return (FRU_SUCCESS);
245}
246
247
248
249static fru_errno_t
250frt_get_seg_list(fru_treehdl_t handle, fru_strlist_t *list)
251{
252	fru_strlist_t rc_list;
253	fru_errno_t err = FRU_SUCCESS;
254	int acc_err = 0;
255	int i = 0;
256	int num_section = 0;
257	section_t *sects = NULL;
258	container_hdl_t cont;
259
260	cont = treehdl_to_conthdl(handle);
261
262	num_section = fru_get_num_sections(cont, NULL);
263	if (num_section == -1) {
264		return (map_errno(errno));
265	}
266
267	sects = malloc(sizeof (*sects) * (num_section));
268	if (sects == NULL) {
269		return (FRU_FAILURE);
270	}
271
272	acc_err = fru_get_sections(cont, sects, num_section, NULL);
273	if (acc_err == -1) {
274		free(sects);
275		return (map_errno(errno));
276	}
277
278	rc_list.num = 0;
279	rc_list.strs = NULL;
280	for (i = 0; i < num_section; i++) {
281		if ((err = add_segs_for_section(&(sects[i]), &rc_list))
282		    != FRU_SUCCESS) {
283			fru_destroy_strlist(&rc_list);
284			free(sects);
285			return (err);
286		}
287	}
288
289	list->strs = rc_list.strs;
290	list->num = rc_list.num;
291
292	return (FRU_SUCCESS);
293}
294
295
296static fru_errno_t
297find_seg_in_sect(section_t *sect, const char *seg_name, int *prot_flg,
298    segment_t *segment)
299{
300	int j = 0;
301	int acc_err = 0;
302	segment_t *segs = NULL;
303
304	int num_seg = fru_get_num_segments(sect->handle, NULL);
305	if (num_seg == -1) {
306		return (FRU_FAILURE);
307	}
308
309	segs = malloc(sizeof (*segs) * (num_seg));
310	if (segs == NULL) {
311		return (FRU_FAILURE);
312	}
313
314	acc_err = fru_get_segments(sect->handle, segs, num_seg, NULL);
315	if (acc_err == -1) {
316		free(segs);
317		return (map_errno(errno));
318	}
319
320	for (j = 0; j < num_seg; j++) {
321		/* NULL terminate */
322		char tmp[SEG_NAME_LEN+1];
323		(void) memcpy(tmp, segs[j].name, SEG_NAME_LEN);
324		tmp[SEG_NAME_LEN] = '\0';
325		if (strcmp(tmp, seg_name) == 0) {
326			*segment = segs[j];
327			*prot_flg = (sect->protection ? 1 : 0);
328			free(segs);
329			return (FRU_SUCCESS);
330		}
331	}
332
333	free(segs);
334	return (FRU_INVALSEG);
335}
336
337
338static fru_errno_t
339find_segment(fru_treehdl_t handle, const char *seg_name, int *prot_flg,
340    segment_t *segment)
341{
342	int i = 0;
343	int acc_err = 0;
344	section_t *sect = NULL;
345	container_hdl_t cont;
346	int num_sect;
347
348	cont = treehdl_to_conthdl(handle);
349
350	num_sect = fru_get_num_sections(cont, NULL);
351	if (num_sect == -1) {
352		return (map_errno(errno));
353	}
354
355	sect = malloc(sizeof (*sect) * (num_sect));
356	if (sect == NULL) {
357		return (FRU_FAILURE);
358	}
359
360	acc_err = fru_get_sections(cont, sect, num_sect, NULL);
361	if (acc_err == -1) {
362		free(sect);
363		return (map_errno(errno));
364	}
365
366	for (i = 0; i < num_sect; i++) {
367		if (find_seg_in_sect(&(sect[i]), seg_name, prot_flg, segment)
368		    == FRU_SUCCESS) {
369			free(sect);
370			return (FRU_SUCCESS);
371		}
372	}
373
374	free(sect);
375	return (FRU_INVALSEG);
376}
377
378
379static fru_errno_t
380frt_get_seg_def(fru_treehdl_t handle, const char *seg_name, fru_segdef_t *def)
381{
382	fru_errno_t err = FRU_SUCCESS;
383	int prot_flg = 0;
384	segment_t segment;
385
386	if ((err = find_segment(handle, seg_name, &prot_flg, &segment))
387	    != FRU_SUCCESS) {
388		return (err);
389	}
390
391	(void) memcpy(def->name, segment.name, SEG_NAME_LEN);
392	def->name[SEG_NAME_LEN] = '\0';
393	def->desc.raw_data = segment.descriptor;
394	def->size = segment.length;
395	def->address = segment.offset;
396
397	if (prot_flg == 0)
398		def->hw_desc.field.read_only = 0;
399	else
400		def->hw_desc.field.read_only = 1;
401
402	return (FRU_SUCCESS);
403
404}
405
406/* ARGSUSED */
407static fru_errno_t
408frt_add_seg(fru_treehdl_t handle, fru_segdef_t *def)
409{
410	/* NOT SUPPORTED */
411	return (FRU_NOTSUP);
412}
413
414/* ARGSUSED */
415static fru_errno_t
416frt_delete_seg(fru_treehdl_t handle, const char *seg_name)
417{
418	/* NOT SUPPORTED */
419	return (FRU_NOTSUP);
420}
421
422/* ARGSUSED */
423static fru_errno_t
424frt_for_each_segment(fru_nodehdl_t node,
425    int (*function)(fru_seghdl_t hdl, void *args), void *args)
426{
427	int num_segment;
428	int cnt;
429	int num_sect;
430	int each_seg;
431	section_t *sects;
432	segment_t *segs;
433	segment_list_t *tmp_list;
434	int acc_err;
435	int status;
436	container_hdl_t cont;
437
438	cont = g_raw->cont;
439
440	num_sect = fru_get_num_sections(cont, NULL);
441	if (num_sect == -1) {
442		return (map_errno(errno));
443	}
444
445	sects = malloc((num_sect + 1) * sizeof (section_t));
446	if (sects == NULL) {
447		return (FRU_FAILURE);
448	}
449	num_sect = fru_get_sections(cont, sects, num_sect, NULL);
450	if (num_sect == -1) {
451		free(sects);
452		return (map_errno(errno));
453	}
454	for (cnt = 0; cnt < num_sect; cnt++) {
455		num_segment = fru_get_num_segments(sects[cnt].handle, NULL);
456		if (num_segment == -1) {
457			return (map_errno(errno));
458		} else if (num_segment == 0) {
459			continue;
460		}
461		segs = malloc((num_segment + 1) * sizeof (segment_t));
462		if (segs == NULL) {
463			free(sects);
464			return (FRU_FAILURE);
465		}
466		acc_err = fru_get_segments(sects[cnt].handle, segs,
467		    num_segment, NULL);
468		if (acc_err == -1) {
469			free(sects);
470			free(segs);
471			return (map_errno(errno));
472		}
473		for (each_seg = 0; each_seg < num_segment; each_seg++) {
474			tmp_list = malloc(sizeof (segment_list_t));
475			tmp_list->segment = &segs[each_seg];
476			tmp_list->next = NULL;
477			if (g_raw->segs == NULL) {
478				g_raw->segs = tmp_list;
479			} else {
480				tmp_list->next = g_raw->segs;
481				g_raw->segs = tmp_list;
482			}
483
484			if ((status = function(segs[each_seg].handle, args))
485			    != FRU_SUCCESS) {
486				free(segs);
487				free(sects);
488				return (status);
489			}
490		}
491		free(segs);
492		free(sects);
493
494	}
495	return (FRU_SUCCESS);
496}
497
498
499static fru_errno_t
500frt_get_segment_name(fru_seghdl_t node, char **name)
501{
502	int num_sect;
503	int acc_err;
504	int cnt;
505	int num_segment;
506	section_t *sects;
507	segment_t *segs;
508	int each_seg;
509	container_hdl_t cont;
510
511	cont = treehdl_to_conthdl(node);
512
513	num_sect = fru_get_num_sections(cont, NULL);
514	if (num_sect == -1) {
515		return (map_errno(errno));
516	}
517
518	sects = malloc(sizeof (*sects) * (num_sect));
519	if (sects == NULL) {
520		return (FRU_FAILURE);
521	}
522	acc_err = fru_get_sections(cont, sects, num_sect, NULL);
523	if (acc_err == -1) {
524		free(sects);
525		return (map_errno(errno));
526	}
527
528	for (cnt = 0; cnt < num_sect; cnt++) {
529		num_segment = fru_get_num_segments(sects[cnt].handle, NULL);
530		if (num_segment == -1) {
531			free(sects);
532			return (map_errno(errno));
533		} else if (num_segment == 0) {
534			continue;
535		}
536
537		segs = malloc(sizeof (*segs) * (num_segment));
538		if (segs == NULL) {
539			free(sects);
540			return (FRU_FAILURE);
541		}
542
543		acc_err = fru_get_segments(sects[cnt].handle, segs,
544		    num_segment, NULL);
545		if (acc_err == -1) {
546			free(sects);
547			free(segs);
548			return (map_errno(errno));
549		}
550
551		for (each_seg = 0; each_seg < num_segment; each_seg++) {
552			if (segs[each_seg].handle == node) {
553				segs[each_seg].name[FRU_SEGNAMELEN] = '\0';
554				*name = segs[each_seg].name;
555				free(sects);
556				return (FRU_SUCCESS);
557			}
558		}
559		free(segs);
560	}
561
562	return (FRU_FAILURE);
563}
564
565
566/* ARGSUSED */
567static fru_errno_t
568frt_add_tag_to_seg(fru_treehdl_t handle, const char *seg_name,
569    fru_tag_t tag, uint8_t *data, size_t data_len)
570{
571	/* NOT SUPPORTED */
572	return (FRU_NOTSUP);
573}
574
575
576/* ARGSUSED */
577static fru_errno_t
578frt_get_tag_list(fru_treehdl_t handle, const char *seg_name,
579		fru_tag_t **tags, int *number)
580{
581	/* NOT SUPPORTED */
582	return (FRU_NOTSUP);
583}
584
585
586/* ARGSUSED */
587static fru_errno_t
588frt_get_tag_data(fru_treehdl_t handle, const char *seg_name,
589		fru_tag_t tag, int instance,
590		uint8_t **data, size_t *data_len)
591{
592	/* NOT SUPPORTED */
593	return (FRU_NOTSUP);
594}
595
596
597/* ARGSUSED */
598static fru_errno_t
599frt_set_tag_data(fru_treehdl_t handle, const char *seg_name,
600		fru_tag_t tag, int instance,
601		uint8_t *data, size_t data_len)
602{
603	/* NOT SUPPORTED */
604	return (FRU_NOTSUP);
605}
606
607
608/* ARGSUSED */
609static fru_errno_t
610frt_delete_tag(fru_treehdl_t handle, const char *seg_name, fru_tag_t tag,
611    int instance)
612{
613	/* NOT SUPPORTED */
614	return (FRU_NOTSUP);
615}
616
617
618static fru_errno_t
619frt_for_each_packet(fru_seghdl_t node,
620    int (*function)(fru_tag_t *tag, uint8_t *payload, size_t length,
621	void *args), void *args)
622{
623	int rc_num;
624	int status;
625	char *rc_tags;
626	char *rc_data;
627	int i;
628	packet_t *packets = NULL;
629	segment_list_t *tmp_list;
630	fru_segdesc_t *descriptor;
631
632	tmp_list = g_raw->segs;
633
634	/* num of packet */
635	rc_num = fru_get_num_packets(node, NULL);
636	if (rc_num == -1) {
637		return (map_errno(errno));
638	} else if (rc_num == 0) {
639		return (FRU_SUCCESS);
640	}
641	while (tmp_list) {
642		if (node == tmp_list->segment->handle) {
643			break;
644		}
645		tmp_list = tmp_list->next;
646	}
647	if (tmp_list) {
648		descriptor = (fru_segdesc_t *)&tmp_list->segment->descriptor;
649		if (descriptor->field.opaque) {
650			return (FRU_SUCCESS);
651		}
652
653		if (descriptor->field.encrypted && (encrypt_func == NULL)) {
654			return (FRU_SUCCESS);
655		}
656	}
657
658	packets = malloc(sizeof (*packets) * (rc_num));
659	if (packets == NULL) {
660		return (FRU_FAILURE);
661	}
662	/* get all packets */
663	if (fru_get_packets(node, packets, rc_num, NULL) == -1) {
664		free(packets);
665		return (map_errno(errno));
666	}
667
668	rc_tags = malloc(sizeof (*rc_tags) * (rc_num));
669	if (rc_tags == NULL) {
670		free(packets);
671		return (FRU_FAILURE);
672	}
673
674	/* number of tags */
675	for (i = 0; i < rc_num; i++) {
676		size_t rc_len =
677		    get_payload_length((fru_tag_t *)&packets[i].tag);
678
679		rc_data = malloc(sizeof (*rc_data) * (rc_len));
680		if (rc_data == NULL) {
681			free(packets);
682			return (FRU_FAILURE);
683		}
684		/* get the payload data */
685		(void) fru_get_payload(packets[i].handle, (void *)rc_data,
686		    rc_len, NULL);
687
688		if (tmp_list) {
689			descriptor =
690			    (fru_segdesc_t *)&tmp_list->segment->descriptor;
691
692			if ((descriptor->field.encrypted) &&
693			    ((status = encrypt_func(FRU_DECRYPT,
694			    (void *)rc_data, rc_len))
695			    != FRU_SUCCESS)) {
696				return (status);
697			}
698		}
699		/* print packet */
700		if ((status = function((fru_tag_t *)&packets[i].tag,
701		    (uint8_t *)rc_data, rc_len, args)) != FRU_SUCCESS) {
702			free(rc_data);
703			free(packets);
704			return (status);
705		}
706		free(rc_data);
707	}
708	return (FRU_SUCCESS);
709
710}
711
712
713/* object for libfru to link to */
714fru_datasource_t data_source =
715{
716	LIBFRU_DS_VER,
717	frt_initialize,
718	frt_shutdown,
719	frt_get_root,
720	frt_get_child,
721	frt_get_peer,
722	frt_get_parent,
723	frt_get_name_from_hdl,
724	frt_get_node_type,
725	frt_get_seg_list,
726	frt_get_seg_def,
727	frt_add_seg,
728	frt_delete_seg,
729	frt_for_each_segment,
730	frt_get_segment_name,
731	frt_add_tag_to_seg,
732	frt_get_tag_list,
733	frt_get_tag_data,
734	frt_set_tag_data,
735	frt_delete_tag,
736	frt_for_each_packet
737};
738