dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libfru / libfruraw / raw_access.c
blob50e070ca9e2adcf9ac8b38c521885bbbfd24651e
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 <stdlib.h>
28 #include <alloca.h>
29 #include <sys/byteorder.h>
30 #include "fru_access_impl.h"
31 #include "fruraw.h"
33 #pragma init(initialize_raw_access)
35 static hash_obj_t *hash_table[TABLE_SIZE];
36 extern raw_list_t *g_raw;
38 static void
39 initialize_raw_access(void)
41 int count;
43 for (count = 0; count < TABLE_SIZE; count++) {
44 hash_table[count] = NULL;
49 static hash_obj_t *
50 lookup_handle_object(handle_t handle, int object_type)
52 handle_t index_to_hash;
53 hash_obj_t *first_hash_obj;
54 hash_obj_t *next_hash_obj;
56 index_to_hash = (handle % TABLE_SIZE);
58 first_hash_obj = hash_table[index_to_hash];
59 for (next_hash_obj = first_hash_obj; next_hash_obj != NULL;
60 next_hash_obj = next_hash_obj->next) {
61 if ((handle == next_hash_obj->obj_hdl) &&
62 (object_type == next_hash_obj->object_type)) {
63 return (next_hash_obj);
66 return (NULL);
70 static void
71 add_hashobject_to_hashtable(hash_obj_t *hash_obj)
73 handle_t index_to_hash;
74 static uint64_t handle_count = 0;
76 hash_obj->obj_hdl = ++handle_count; /* store the handle */
78 /* where to add ? */
79 index_to_hash = ((hash_obj->obj_hdl) % TABLE_SIZE);
81 hash_obj->next = hash_table[index_to_hash];
82 hash_table[index_to_hash] = hash_obj; /* hash obj. added */
84 if (hash_obj->next != NULL) {
85 hash_obj->next->prev = hash_obj;
90 static hash_obj_t *
91 create_container_hash_object(void)
93 hash_obj_t *hash_obj;
94 container_obj_t *cont_obj;
96 cont_obj = malloc(sizeof (container_obj_t));
97 if (cont_obj == NULL) {
98 return (NULL);
101 hash_obj = malloc(sizeof (hash_obj_t));
102 if (hash_obj == NULL) {
103 free(cont_obj);
104 return (NULL);
107 cont_obj->sec_obj_list = NULL;
109 hash_obj->object_type = CONTAINER_TYPE;
110 hash_obj->u.cont_obj = cont_obj;
111 hash_obj->next = NULL;
112 hash_obj->prev = NULL;
114 return (hash_obj);
118 static hash_obj_t *
119 create_section_hash_object(void)
121 hash_obj_t *hash_obj;
122 section_obj_t *sec_obj;
124 sec_obj = malloc(sizeof (section_obj_t));
125 if (sec_obj == NULL) {
126 return (NULL);
129 hash_obj = malloc(sizeof (hash_obj_t));
130 if (hash_obj == NULL) {
131 free(sec_obj);
132 return (NULL);
135 sec_obj->next = NULL;
136 sec_obj->seg_obj_list = NULL;
138 hash_obj->u.sec_obj = sec_obj;
139 hash_obj->object_type = SECTION_TYPE;
140 hash_obj->next = NULL;
141 hash_obj->prev = NULL;
143 return (hash_obj);
147 static hash_obj_t *
148 create_segment_hash_object(void)
150 hash_obj_t *hash_obj;
151 segment_obj_t *seg_obj;
153 seg_obj = malloc(sizeof (segment_obj_t));
154 if (seg_obj == NULL) {
155 return (NULL);
158 hash_obj = malloc(sizeof (hash_obj_t));
159 if (hash_obj == NULL) {
160 free(seg_obj);
161 return (NULL);
164 seg_obj->next = NULL;
165 seg_obj->pkt_obj_list = NULL;
167 hash_obj->object_type = SEGMENT_TYPE;
168 hash_obj->u.seg_obj = seg_obj;
169 hash_obj->next = NULL;
170 hash_obj->prev = NULL;
172 return (hash_obj);
176 static hash_obj_t *
177 create_packet_hash_object(void)
179 hash_obj_t *hash_obj;
180 packet_obj_t *pkt_obj;
182 pkt_obj = malloc(sizeof (packet_obj_t));
183 if (pkt_obj == NULL) {
184 return (NULL);
187 hash_obj = malloc(sizeof (hash_obj_t));
188 if (hash_obj == NULL) {
189 free(pkt_obj);
190 return (NULL);
193 pkt_obj->next = NULL;
195 hash_obj->object_type = PACKET_TYPE;
196 hash_obj->u.pkt_obj = pkt_obj;
197 hash_obj->next = NULL;
198 hash_obj->prev = NULL;
200 return (hash_obj);
205 static hash_obj_t *
206 get_container_hash_object(int object_type, handle_t handle)
208 hash_obj_t *hash_obj;
210 switch (object_type) {
211 case CONTAINER_TYPE:
212 break;
213 case SECTION_TYPE:
214 hash_obj = lookup_handle_object(handle, CONTAINER_TYPE);
215 if (hash_obj == NULL) {
216 return (NULL);
218 break;
219 case SEGMENT_TYPE:
220 hash_obj = lookup_handle_object(handle, SECTION_TYPE);
221 if (hash_obj == NULL) {
222 return (NULL);
224 hash_obj = lookup_handle_object(hash_obj->u.sec_obj->cont_hdl,
225 CONTAINER_TYPE);
226 break;
227 case PACKET_TYPE:
228 break;
229 default:
230 return (NULL);
233 return (hash_obj);
237 static void
238 add_to_pkt_object_list(hash_obj_t *parent_obj, hash_obj_t *child_obj)
240 hash_obj_t *next_hash;
242 /* add the packet object in the end of list */
243 child_obj->u.pkt_obj->segment_hdl = parent_obj->obj_hdl;
245 if (parent_obj->u.seg_obj->pkt_obj_list == NULL) {
246 parent_obj->u.seg_obj->pkt_obj_list = child_obj;
247 return;
250 for (next_hash = parent_obj->u.seg_obj->pkt_obj_list;
251 next_hash->u.pkt_obj->next != NULL;
252 next_hash = next_hash->u.pkt_obj->next) {
256 next_hash->u.pkt_obj->next = child_obj;
260 static void
261 free_pkt_object_list(hash_obj_t *hash_obj)
263 hash_obj_t *next_obj;
264 hash_obj_t *free_obj;
266 next_obj = hash_obj->u.seg_obj->pkt_obj_list;
267 while (next_obj != NULL) {
268 free_obj = next_obj;
269 next_obj = next_obj->u.pkt_obj->next;
270 /* if prev is NULL it's the first object in the list */
271 if (free_obj->prev == NULL) {
272 hash_table[(free_obj->obj_hdl % TABLE_SIZE)] =
273 free_obj->next;
274 if (free_obj->next != NULL) {
275 free_obj->next->prev = free_obj->prev;
277 } else {
278 free_obj->prev->next = free_obj->next;
279 if (free_obj->next != NULL) {
280 free_obj->next->prev = free_obj->prev;
284 free(free_obj->u.pkt_obj->payload);
285 free(free_obj->u.pkt_obj);
286 free(free_obj);
289 hash_obj->u.seg_obj->pkt_obj_list = NULL;
293 static void
294 free_segment_hash(handle_t handle, hash_obj_t *sec_hash)
296 hash_obj_t *seg_hash;
297 hash_obj_t *next_hash;
299 seg_hash = sec_hash->u.sec_obj->seg_obj_list;
300 if (seg_hash == NULL) {
301 return;
304 if (seg_hash->obj_hdl == handle) {
305 sec_hash->u.sec_obj->seg_obj_list = seg_hash->u.seg_obj->next;
306 } else {
307 while (seg_hash->obj_hdl != handle) {
308 next_hash = seg_hash;
309 seg_hash = seg_hash->u.seg_obj->next;
310 if (seg_hash == NULL) {
311 return;
314 next_hash->u.seg_obj->next = seg_hash->u.seg_obj->next;
317 if (seg_hash->prev == NULL) {
318 hash_table[(seg_hash->obj_hdl % TABLE_SIZE)] = seg_hash->next;
319 if (seg_hash->next != NULL) {
320 seg_hash->next->prev = NULL;
322 } else {
323 seg_hash->prev->next = seg_hash->next;
324 if (seg_hash->next != NULL) {
325 seg_hash->next->prev = seg_hash->prev;
329 free_pkt_object_list(seg_hash);
330 free(seg_hash->u.seg_obj);
331 free(seg_hash);
336 static void
337 add_to_sec_object_list(hash_obj_t *parent_obj, hash_obj_t *child_obj)
339 hash_obj_t *next_hash;
341 child_obj->u.sec_obj->cont_hdl = parent_obj->obj_hdl;
342 if (parent_obj->u.cont_obj->sec_obj_list == NULL) {
343 parent_obj->u.cont_obj->sec_obj_list = child_obj;
344 return;
347 for (next_hash = parent_obj->u.cont_obj->sec_obj_list;
348 next_hash->u.sec_obj->next != NULL;
349 next_hash = next_hash->u.sec_obj->next) {
353 next_hash->u.sec_obj->next = child_obj;
357 static void
358 add_to_seg_object_list(hash_obj_t *parent_obj, hash_obj_t *child_obj)
360 hash_obj_t *next_hash;
362 child_obj->u.seg_obj->section_hdl = parent_obj->obj_hdl;
363 if (parent_obj->u.sec_obj->seg_obj_list == NULL) {
364 parent_obj->u.sec_obj->seg_obj_list = child_obj;
365 return;
368 for (next_hash = parent_obj->u.sec_obj->seg_obj_list;
369 next_hash->u.seg_obj->next != NULL;
370 next_hash = next_hash->u.seg_obj->next) {
374 next_hash->u.seg_obj->next = child_obj;
378 static char *
379 tokenizer(char *buf, char *separator, char **nextBuf, char *matched)
381 int i = 0;
382 int j = 0;
384 for (i = 0; buf[i] != '\0'; i++) {
385 for (j = 0; j < strlen(separator); j++) {
386 if (buf[i] == separator[j]) {
387 buf[i] = '\0';
388 *nextBuf = &(buf[i+1]);
389 *matched = separator[j];
390 return (buf);
395 *nextBuf = buf;
396 *matched = '\0';
397 return (NULL);
401 static void
402 copy_segment_layout(segment_t *seghdr, void *layout)
404 segment_layout_t *seg_layout;
406 seg_layout = (segment_layout_t *)layout;
407 (void) memcpy(seghdr->name, &seg_layout->name, SEG_NAME_LEN);
408 seghdr->descriptor = GET_SEGMENT_DESCRIPTOR;
409 seghdr->offset = BE_16(seg_layout->offset);
410 seghdr->length = BE_16(seg_layout->length);
414 static int
415 get_container_info(const char *def_file, const char *cont_desc_str,
416 container_info_t *cont_info)
418 char *item;
419 char *token;
420 char *field;
421 char matched;
422 char buf[1024];
423 int foundIt = 0;
424 FILE *file = fopen(def_file, "r");
426 if (file == NULL)
427 return (-1);
429 cont_info->num_sections = 0;
431 while (fgets(buf, sizeof (buf), file) != NULL) {
432 /* ignore all comments */
433 token = tokenizer(buf, "#", &field, &matched);
434 /* find the names */
435 token = tokenizer(buf, ":", &field, &matched);
436 if (token != 0x00) {
437 token = tokenizer(token, "|", &item, &matched);
438 while (token != 0x00) {
439 if (strcmp(token, cont_desc_str) == 0) {
440 foundIt = 1;
441 goto found;
443 token = tokenizer(item, "|", &item, &matched);
445 /* check the last remaining item */
446 if ((item != 0x00) &&
447 (strcmp(item, cont_desc_str) == 0)) {
448 foundIt = 1;
449 goto found;
454 found :
455 if (foundIt == 1) {
456 token = tokenizer(field, ":", &field, &matched);
457 if (token == 0x00) {
458 (void) fclose(file);
459 return (-1);
461 cont_info->header_ver = (headerrev_t)atoi(token);
463 token = tokenizer(field, ":\n", &field, &matched);
464 while (token != 0x00) {
465 token = tokenizer(token, ",", &item, &matched);
466 if (token == 0x00) {
467 (void) fclose(file);
468 return (-1);
470 if (atoi(token) == 1) {
471 cont_info->section_info[cont_info->
472 num_sections].description.field.read_only
473 = 1;
474 } else if (atoi(token) == 0) {
475 cont_info->section_info[cont_info->
476 num_sections].description.field.read_only
477 = 0;
478 } else {
479 (void) fclose(file);
480 return (-1);
483 token = tokenizer(item, ",", &item, &matched);
484 if (token == 0x00) {
485 (void) fclose(file);
486 return (-1);
489 cont_info->section_info[cont_info->
490 num_sections].address = atoi(token);
491 if (item == '\0') {
492 (void) fclose(file);
493 return (-1);
495 cont_info->section_info[cont_info->num_sections].size =
496 atoi(item);
497 (cont_info->num_sections)++;
499 token = tokenizer(field, ":\n ", &field, &matched);
502 (void) fclose(file);
504 return (0);
508 /* ARGSUSED */
510 fru_get_segments(section_hdl_t section, segment_t *segment, int maxseg,
511 door_cred_t *cred)
513 int count;
514 hash_obj_t *sec_object;
515 hash_obj_t *seg_object;
516 section_obj_t *sec_obj;
518 sec_object = lookup_handle_object(section, SECTION_TYPE);
519 if (sec_object == NULL) {
520 return (-1);
523 sec_obj = sec_object->u.sec_obj;
524 if (sec_obj == NULL) {
525 return (-1);
528 if (sec_obj->num_of_segment > maxseg) {
529 return (-1);
532 seg_object = sec_object->u.sec_obj->seg_obj_list;
533 if (seg_object == NULL) {
534 return (-1);
537 for (count = 0; count < sec_obj->num_of_segment; count++) {
539 /* populate segment_t */
540 segment->handle = seg_object->obj_hdl;
541 (void) memcpy(segment->name,
542 seg_object->u.seg_obj->segment.name, SEG_NAME_LEN);
543 segment->descriptor = seg_object->u.seg_obj->segment.descriptor;
545 segment->offset = seg_object->u.seg_obj->segment.offset;
546 segment->length = seg_object->u.seg_obj->segment.length;
547 seg_object = seg_object->u.seg_obj->next;
548 segment++;
550 return (0);
554 static int
555 raw_memcpy(void *buffer, raw_list_t *rawlist, int offset, int size)
557 if (offset + size > rawlist->size) {
558 size = rawlist->size - offset;
561 (void) memcpy(buffer, &rawlist->raw[offset], size);
563 return (size);
567 static int
568 verify_header_crc8(headerrev_t head_ver, unsigned char *bytes, int length)
570 int crc_offset = 0;
571 unsigned char orig_crc8 = 0;
572 unsigned char calc_crc8 = 0;
574 switch (head_ver) {
575 case SECTION_HDR_VER:
576 crc_offset = 4;
577 break;
578 default:
579 errno = EINVAL;
580 return (0);
583 orig_crc8 = bytes[crc_offset];
584 bytes[crc_offset] = 0x00; /* clear for calc */
585 calc_crc8 = compute_crc8(bytes, length);
586 bytes[crc_offset] = orig_crc8; /* restore */
588 return (orig_crc8 == calc_crc8);
592 static int
593 get_section(raw_list_t *rawlist, hash_obj_t *sec_hash, section_t *section)
595 int retval;
596 int size;
597 int count;
598 uint16_t hdrver;
599 hash_obj_t *seg_hash;
600 unsigned char *buffer;
601 section_obj_t *sec_obj;
602 section_layout_t sec_hdr;
603 segment_layout_t *seg_hdr;
604 segment_layout_t *seg_buf;
606 sec_obj = sec_hash->u.sec_obj;
607 if (sec_obj == NULL) {
608 return (-1);
611 /* populate section_t */
612 section->handle = sec_hash->obj_hdl;
613 section->offset = sec_obj->section.offset;
614 section->length = sec_obj->section.length;
615 section->protection = sec_obj->section.protection;
616 section->version = sec_obj->section.version;
618 /* read section header layout */
619 retval = raw_memcpy(&sec_hdr, rawlist, sec_obj->section.offset,
620 sizeof (sec_hdr));
622 if (retval != sizeof (sec_hdr)) {
623 return (-1);
627 hdrver = GET_SECTION_HDR_VERSION;
629 if ((sec_hdr.headertag != SECTION_HDR_TAG) &&
630 (hdrver != section->version)) {
631 return (-1);
634 /* size = section layout + total sizeof segment header */
635 size = sizeof (sec_hdr) + ((sec_hdr.segmentcount)
636 * sizeof (segment_layout_t));
638 buffer = alloca(size);
639 if (buffer == NULL) {
640 return (-1);
643 /* segment header buffer */
644 seg_buf = alloca(size - sizeof (sec_hdr));
645 if (seg_buf == NULL) {
646 return (-1);
649 /* read segment header */
650 retval = raw_memcpy(seg_buf, rawlist,
651 sec_obj->section.offset + sizeof (sec_hdr),
652 size - sizeof (sec_hdr));
654 if (retval != (size - sizeof (sec_hdr))) {
655 return (-1);
658 /* copy section header layout */
659 (void) memcpy(buffer, &sec_hdr, sizeof (sec_hdr));
661 /* copy segment header layout */
662 (void) memcpy(buffer + sizeof (sec_hdr), seg_buf, size -
663 sizeof (sec_hdr));
665 /* verify crc8 */
666 retval = verify_header_crc8(hdrver, buffer, size);
667 if (retval != 1) {
668 return (-1);
671 section->version = hdrver;
672 sec_obj->section.version = hdrver;
674 seg_hdr = (segment_layout_t *)seg_buf;
676 /* bug fix for frutool */
677 if (sec_hash->u.sec_obj->seg_obj_list != NULL) {
678 return (0);
679 } else {
680 sec_obj->num_of_segment = 0;
682 for (count = 0; count < sec_hdr.segmentcount; count++, seg_hdr++) {
684 seg_hash = create_segment_hash_object();
685 if (seg_hash == NULL) {
686 return (-1);
688 add_hashobject_to_hashtable(seg_hash);
689 copy_segment_layout(&seg_hash->u.seg_obj->segment, seg_hdr);
690 add_to_seg_object_list(sec_hash, seg_hash);
691 sec_obj->num_of_segment++;
693 return (0);
696 /* ARGSUSED */
698 fru_get_sections(container_hdl_t container, section_t *section, int maxsec,
699 door_cred_t *cred)
701 int count;
702 int num_sec = 0;
703 hash_obj_t *cont_object;
704 hash_obj_t *sec_hash;
706 cont_object = lookup_handle_object(container, CONTAINER_TYPE);
707 if (cont_object == NULL) {
708 return (-1);
711 if (cont_object->u.cont_obj->num_of_section > maxsec) {
712 return (-1);
715 sec_hash = cont_object->u.cont_obj->sec_obj_list;
716 if (sec_hash == NULL) {
717 return (-1);
720 for (count = 0; count < cont_object->u.cont_obj->num_of_section;
721 count++) {
722 section->version = -1;
723 /* populate section_t */
724 if (get_section(g_raw, sec_hash, section) == 0) {
725 section++;
726 num_sec++;
728 sec_hash = sec_hash->u.sec_obj->next;
730 return (num_sec);
734 static uint32_t
735 get_checksum_crc(hash_obj_t *seg_hash, int data_size)
737 int protection;
738 int offset = 0;
739 uint32_t crc;
740 hash_obj_t *sec_hash;
741 hash_obj_t *pkt_hash;
742 unsigned char *buffer;
744 sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl,
745 SECTION_TYPE);
746 if (sec_hash == NULL) {
747 return ((uint32_t)-1);
750 buffer = alloca(data_size);
751 if (buffer == NULL) {
752 return ((uint32_t)-1);
755 /* traverse the packet object list for all the tags and payload */
756 for (pkt_hash = seg_hash->u.seg_obj->pkt_obj_list; pkt_hash != NULL;
757 pkt_hash = pkt_hash->u.pkt_obj->next) {
758 (void) memcpy(buffer + offset, &pkt_hash->u.pkt_obj->tag,
759 pkt_hash->u.pkt_obj->tag_size);
760 offset += pkt_hash->u.pkt_obj->tag_size;
761 (void) memcpy(buffer + offset, pkt_hash->u.pkt_obj->payload,
762 pkt_hash->u.pkt_obj->paylen);
763 offset += pkt_hash->u.pkt_obj->paylen;
766 protection = sec_hash->u.sec_obj->section.protection;
768 if (protection == READ_ONLY_SECTION) { /* read-only section */
769 crc = compute_crc32(buffer, data_size);
770 } else { /* read/write section */
771 crc = compute_checksum32(buffer, data_size);
773 return (crc); /* computed crc */
777 static int
778 get_packet(raw_list_t *rawlist, void *buffer, int size, int offset)
780 int retval;
782 retval = raw_memcpy(buffer, rawlist, offset, size);
784 if (retval != -1) {
785 return (0);
787 return (-1);
791 static int
792 get_packets(hash_obj_t *seg_hash, raw_list_t *rawlist, int offset, int length)
794 int tag_size;
795 int paylen;
796 int retval;
797 int seg_limit = 0;
798 int pktcnt = 0;
799 char *data;
800 uint32_t crc;
801 uint32_t origcrc;
802 fru_tag_t tag;
803 hash_obj_t *pkt_hash_obj;
804 hash_obj_t *sec_hash;
805 fru_segdesc_t *segdesc;
806 fru_tagtype_t tagtype;
807 char *ignore_flag;
809 retval = get_packet(rawlist, &tag, sizeof (fru_tag_t), offset);
810 if (retval == -1) {
811 return (-1);
814 /* section hash object */
815 sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl,
816 SECTION_TYPE);
818 if (sec_hash == NULL) {
819 return (-1);
822 seg_hash->u.seg_obj->trailer_offset = offset;
824 data = (char *)&tag;
825 while (data[0] != SEG_TRAILER_TAG) {
826 tagtype = get_tag_type(&tag); /* verify tag type */
827 if (tagtype == -1) {
828 return (-1);
831 tag_size = get_tag_size(tagtype);
832 if (tag_size == -1) {
833 return (-1);
836 seg_limit += tag_size;
837 if (seg_limit > length) {
838 return (-1);
841 paylen = get_payload_length((void *)&tag);
842 if (paylen == -1) {
843 return (-1);
846 seg_limit += paylen;
847 if (seg_limit > length) {
848 return (-1);
850 if ((offset + tag_size + paylen) >
851 (sec_hash->u.sec_obj->section.offset +
852 sec_hash->u.sec_obj->section.length)) {
853 return (-1);
856 pkt_hash_obj = create_packet_hash_object();
857 if (pkt_hash_obj == NULL) {
858 return (-1);
861 pkt_hash_obj->u.pkt_obj->payload = malloc(paylen);
862 if (pkt_hash_obj->u.pkt_obj->payload == NULL) {
863 free(pkt_hash_obj);
864 return (-1);
867 offset += tag_size;
869 retval = raw_memcpy(pkt_hash_obj->u.pkt_obj->payload, rawlist,
870 offset, paylen);
872 if (retval != paylen) {
873 free(pkt_hash_obj->u.pkt_obj->payload);
874 free(pkt_hash_obj);
875 return (-1);
878 /* don't change this */
879 pkt_hash_obj->u.pkt_obj->tag.raw_data = 0;
880 (void) memcpy(&pkt_hash_obj->u.pkt_obj->tag, &tag, tag_size);
881 pkt_hash_obj->u.pkt_obj->paylen = paylen;
882 pkt_hash_obj->u.pkt_obj->tag_size = tag_size;
883 pkt_hash_obj->u.pkt_obj->payload_offset = offset;
885 offset += paylen;
887 add_hashobject_to_hashtable(pkt_hash_obj);
888 add_to_pkt_object_list(seg_hash, pkt_hash_obj);
890 pktcnt++;
892 retval = get_packet(rawlist, &tag, sizeof (fru_tag_t),
893 offset);
894 if (retval == -1) {
895 return (retval);
898 data = (char *)&tag;
901 segdesc = (fru_segdesc_t *)&seg_hash->u.seg_obj->segment.descriptor;
903 seg_hash->u.seg_obj->trailer_offset = offset;
905 if (!segdesc->field.ignore_checksum) {
906 crc = get_checksum_crc(seg_hash, seg_limit);
907 offset = seg_hash->u.seg_obj->segment.offset;
909 retval = raw_memcpy(&origcrc, rawlist, offset + seg_limit + 1,
910 sizeof (origcrc));
912 ignore_flag = getenv(IGNORE_CHECK);
913 if (ignore_flag != NULL) {
914 return (pktcnt);
917 if (retval != sizeof (origcrc)) {
918 return (-1);
921 origcrc = BE_32(origcrc);
922 if (origcrc != crc) {
923 seg_hash->u.seg_obj->trailer_offset = offset;
924 return (-1);
928 return (pktcnt);
931 /* ARGSUSED */
933 fru_get_num_sections(container_hdl_t container, door_cred_t *cred)
935 hash_obj_t *hash_object;
937 hash_object = lookup_handle_object(container, CONTAINER_TYPE);
938 if (hash_object == NULL) {
939 return (-1);
942 return (hash_object->u.cont_obj->num_of_section);
945 /* ARGSUSED */
947 fru_get_num_segments(section_hdl_t section, door_cred_t *cred)
949 hash_obj_t *sec_object;
950 section_obj_t *sec_obj;
952 sec_object = lookup_handle_object(section, SECTION_TYPE);
953 if (sec_object == NULL) {
954 return (-1);
957 sec_obj = sec_object->u.sec_obj;
958 if (sec_obj == NULL) {
959 return (-1);
962 return (sec_obj->num_of_segment);
965 /* ARGSUSED */
967 fru_get_num_packets(segment_hdl_t segment, door_cred_t *cred)
969 int pktcnt;
970 int length;
971 uint16_t offset;
972 hash_obj_t *cont_hash_obj;
973 hash_obj_t *seg_hash;
974 hash_obj_t *sec_hash;
975 fru_segdesc_t *segdesc;
976 segment_obj_t *segment_object;
978 seg_hash = lookup_handle_object(segment, SEGMENT_TYPE);
979 if (seg_hash == NULL) {
980 return (-1);
983 segment_object = seg_hash->u.seg_obj;
984 if (segment_object == NULL) {
985 return (-1);
988 segdesc = (fru_segdesc_t *)&segment_object->segment.descriptor;
989 if (segdesc->field.opaque) {
990 return (0);
993 offset = segment_object->segment.offset;
994 length = segment_object->segment.length;
996 cont_hash_obj = get_container_hash_object(SEGMENT_TYPE,
997 segment_object->section_hdl);
999 if (cont_hash_obj == NULL) {
1000 return (-1);
1003 if (seg_hash->u.seg_obj->pkt_obj_list != NULL) {
1004 return (segment_object->num_of_packets);
1006 /* section hash object */
1007 sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl,
1008 SECTION_TYPE);
1009 if (sec_hash == NULL) {
1010 return (-1);
1013 /* valid segment header b'cos crc8 already validated */
1014 if (offset < sec_hash->u.sec_obj->section.offset) {
1015 return (-1);
1018 segment_object->num_of_packets = 0;
1020 pktcnt = get_packets(seg_hash, g_raw, offset, length);
1021 if (pktcnt == -1) {
1022 free_pkt_object_list(seg_hash);
1023 seg_hash->u.seg_obj->pkt_obj_list = NULL;
1026 segment_object->num_of_packets = pktcnt;
1028 return (segment_object->num_of_packets);
1031 /* ARGSUSED */
1033 fru_get_packets(segment_hdl_t segment, packet_t *packet, int maxpackets,
1034 door_cred_t *cred)
1036 int count;
1037 hash_obj_t *seg_hash_obj;
1038 hash_obj_t *pkt_hash_obj;
1040 /* segment hash object */
1041 seg_hash_obj = lookup_handle_object(segment, SEGMENT_TYPE);
1042 if (seg_hash_obj == NULL) {
1043 return (-1);
1046 if (seg_hash_obj->u.seg_obj->num_of_packets != maxpackets) {
1047 return (-1);
1050 pkt_hash_obj = seg_hash_obj->u.seg_obj->pkt_obj_list;
1051 if (pkt_hash_obj == NULL) {
1052 return (-1);
1055 for (count = 0; count < maxpackets; count++, packet++) {
1056 packet->handle = pkt_hash_obj->obj_hdl;
1057 packet->tag = 0;
1058 (void) memcpy(&packet->tag, &pkt_hash_obj->u.pkt_obj->tag,
1059 pkt_hash_obj->u.pkt_obj->tag_size);
1060 pkt_hash_obj = pkt_hash_obj->u.pkt_obj->next;
1063 return (0);
1066 /* ARGSUSED */
1067 ssize_t
1068 fru_get_payload(packet_hdl_t packet, void *buffer, size_t nbytes,
1069 door_cred_t *cred)
1071 hash_obj_t *packet_hash_obj;
1073 /* packet hash object */
1074 packet_hash_obj = lookup_handle_object(packet, PACKET_TYPE);
1075 if (packet_hash_obj == NULL) {
1076 return (-1);
1079 /* verify payload length */
1080 if (nbytes != packet_hash_obj->u.pkt_obj->paylen) {
1081 return (-1);
1084 (void) memcpy(buffer, packet_hash_obj->u.pkt_obj->payload, nbytes);
1085 return (nbytes);
1089 container_hdl_t
1090 open_raw_data(raw_list_t *node)
1092 char *cont_conf_file = NULL;
1093 hash_obj_t *cont_hash_obj;
1094 hash_obj_t *sec_hash_obj;
1095 container_info_t cont_info;
1096 int retval;
1097 int count;
1099 cont_hash_obj = create_container_hash_object();
1100 if (cont_hash_obj == NULL) {
1101 return ((uintptr_t)NULL);
1104 add_hashobject_to_hashtable(cont_hash_obj);
1106 (void) strncpy(cont_hash_obj->u.cont_obj->device_pathname, "unknown",
1107 sizeof (cont_hash_obj->u.cont_obj->device_pathname));
1109 cont_conf_file = getenv(FRU_CONT_CONF_ENV_VAR);
1110 if (cont_conf_file == NULL) {
1111 cont_conf_file = FRU_CONT_CONF_SPARC;
1112 retval = get_container_info(cont_conf_file, node->cont_type,
1113 &cont_info);
1114 if (retval < 0) {
1115 cont_conf_file = FRU_CONT_CONF_X86;
1116 retval = get_container_info(cont_conf_file,
1117 node->cont_type, &cont_info);
1119 } else {
1120 retval = get_container_info(cont_conf_file, node->cont_type,
1121 &cont_info);
1124 if (retval < 0) {
1125 return ((uintptr_t)NULL);
1128 cont_hash_obj->u.cont_obj->num_of_section = cont_info.num_sections;
1129 cont_hash_obj->u.cont_obj->sec_obj_list = NULL;
1131 for (count = 0; count < cont_info.num_sections; count++) {
1132 sec_hash_obj = create_section_hash_object();
1133 if (sec_hash_obj == NULL) {
1134 return ((uintptr_t)NULL);
1137 add_hashobject_to_hashtable(sec_hash_obj);
1139 sec_hash_obj->u.sec_obj->section.offset =
1140 cont_info.section_info[count].address;
1142 sec_hash_obj->u.sec_obj->section.protection =
1143 cont_info.section_info[count].description.field.read_only;
1145 sec_hash_obj->u.sec_obj->section.length =
1146 cont_info.section_info[count].size;
1147 sec_hash_obj->u.sec_obj->section.version =
1148 cont_info.header_ver;
1150 add_to_sec_object_list(cont_hash_obj, sec_hash_obj);
1153 return (cont_hash_obj->obj_hdl);
1158 fru_close_container(container_hdl_t container)
1160 hash_obj_t *hash_obj;
1161 hash_obj_t *prev_hash;
1162 hash_obj_t *sec_hash_obj;
1163 handle_t obj_hdl;
1165 /* lookup for container hash object */
1166 hash_obj = lookup_handle_object(container, CONTAINER_TYPE);
1167 if (hash_obj == NULL) {
1168 return (0);
1171 /* points to section object list */
1172 sec_hash_obj = hash_obj->u.cont_obj->sec_obj_list;
1174 /* traverse section object list */
1175 while (sec_hash_obj != NULL) {
1177 /* traverse segment hash object in the section */
1178 while (sec_hash_obj->u.sec_obj->seg_obj_list != NULL) {
1179 /* object handle of the segment hash object */
1180 obj_hdl =
1181 sec_hash_obj->u.sec_obj->seg_obj_list->obj_hdl;
1182 free_segment_hash(obj_hdl, sec_hash_obj);
1185 /* going to free section hash object, relink the hash object */
1186 if (sec_hash_obj->prev == NULL) {
1187 hash_table[(sec_hash_obj->obj_hdl % TABLE_SIZE)] =
1188 sec_hash_obj->next;
1189 if (sec_hash_obj->next != NULL) {
1190 sec_hash_obj->next->prev = NULL;
1192 } else {
1193 sec_hash_obj->prev->next = sec_hash_obj->next;
1194 if (sec_hash_obj->next != NULL) {
1195 sec_hash_obj->next->prev = sec_hash_obj->prev;
1199 prev_hash = sec_hash_obj;
1200 sec_hash_obj = sec_hash_obj->u.sec_obj->next;
1202 free(prev_hash->u.sec_obj); /* free section hash object */
1203 free(prev_hash); /* free section hash */
1206 /* free container hash object */
1207 if (hash_obj->prev == NULL) {
1208 hash_table[(hash_obj->obj_hdl % TABLE_SIZE)] =
1209 hash_obj->next;
1210 if (hash_obj->next != NULL) {
1211 hash_obj->next->prev = NULL;
1213 } else {
1214 hash_obj->prev->next = hash_obj->next;
1215 if (hash_obj->next != NULL) {
1216 hash_obj->next->prev = hash_obj->prev;
1220 free(hash_obj->u.cont_obj);
1221 free(hash_obj);
1223 return (0);