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 <stdlib.h> 29 #include <alloca.h> 30 #include <sys/byteorder.h> 31 #include "fru_access_impl.h" 32 #include "fruraw.h" 33 34 #pragma init(initialize_raw_access) 35 36 static hash_obj_t *hash_table[TABLE_SIZE]; 37 extern raw_list_t *g_raw; 38 39 static void 40 initialize_raw_access(void) 41 { 42 int count; 43 44 for (count = 0; count < TABLE_SIZE; count++) { 45 hash_table[count] = NULL; 46 } 47 } 48 49 50 static hash_obj_t * 51 lookup_handle_object(handle_t handle, int object_type) 52 { 53 handle_t index_to_hash; 54 hash_obj_t *first_hash_obj; 55 hash_obj_t *next_hash_obj; 56 57 index_to_hash = (handle % TABLE_SIZE); 58 59 first_hash_obj = hash_table[index_to_hash]; 60 for (next_hash_obj = first_hash_obj; next_hash_obj != NULL; 61 next_hash_obj = next_hash_obj->next) { 62 if ((handle == next_hash_obj->obj_hdl) && 63 (object_type == next_hash_obj->object_type)) { 64 return (next_hash_obj); 65 } 66 } 67 return (NULL); 68 } 69 70 71 static void 72 add_hashobject_to_hashtable(hash_obj_t *hash_obj) 73 { 74 handle_t index_to_hash; 75 static uint64_t handle_count = 0; 76 77 hash_obj->obj_hdl = ++handle_count; /* store the handle */ 78 79 /* where to add ? */ 80 index_to_hash = ((hash_obj->obj_hdl) % TABLE_SIZE); 81 82 hash_obj->next = hash_table[index_to_hash]; 83 hash_table[index_to_hash] = hash_obj; /* hash obj. added */ 84 85 if (hash_obj->next != NULL) { 86 hash_obj->next->prev = hash_obj; 87 } 88 } 89 90 91 static hash_obj_t * 92 create_container_hash_object(void) 93 { 94 hash_obj_t *hash_obj; 95 container_obj_t *cont_obj; 96 97 cont_obj = malloc(sizeof (container_obj_t)); 98 if (cont_obj == NULL) { 99 return (NULL); 100 } 101 102 hash_obj = malloc(sizeof (hash_obj_t)); 103 if (hash_obj == NULL) { 104 free(cont_obj); 105 return (NULL); 106 } 107 108 cont_obj->sec_obj_list = NULL; 109 110 hash_obj->object_type = CONTAINER_TYPE; 111 hash_obj->u.cont_obj = cont_obj; 112 hash_obj->next = NULL; 113 hash_obj->prev = NULL; 114 115 return (hash_obj); 116 } 117 118 119 static hash_obj_t * 120 create_section_hash_object(void) 121 { 122 hash_obj_t *hash_obj; 123 section_obj_t *sec_obj; 124 125 sec_obj = malloc(sizeof (section_obj_t)); 126 if (sec_obj == NULL) { 127 return (NULL); 128 } 129 130 hash_obj = malloc(sizeof (hash_obj_t)); 131 if (hash_obj == NULL) { 132 free(sec_obj); 133 return (NULL); 134 } 135 136 sec_obj->next = NULL; 137 sec_obj->seg_obj_list = NULL; 138 139 hash_obj->u.sec_obj = sec_obj; 140 hash_obj->object_type = SECTION_TYPE; 141 hash_obj->next = NULL; 142 hash_obj->prev = NULL; 143 144 return (hash_obj); 145 } 146 147 148 static hash_obj_t * 149 create_segment_hash_object(void) 150 { 151 hash_obj_t *hash_obj; 152 segment_obj_t *seg_obj; 153 154 seg_obj = malloc(sizeof (segment_obj_t)); 155 if (seg_obj == NULL) { 156 return (NULL); 157 } 158 159 hash_obj = malloc(sizeof (hash_obj_t)); 160 if (hash_obj == NULL) { 161 free(seg_obj); 162 return (NULL); 163 } 164 165 seg_obj->next = NULL; 166 seg_obj->pkt_obj_list = NULL; 167 168 hash_obj->object_type = SEGMENT_TYPE; 169 hash_obj->u.seg_obj = seg_obj; 170 hash_obj->next = NULL; 171 hash_obj->prev = NULL; 172 173 return (hash_obj); 174 } 175 176 177 static hash_obj_t * 178 create_packet_hash_object(void) 179 { 180 hash_obj_t *hash_obj; 181 packet_obj_t *pkt_obj; 182 183 pkt_obj = malloc(sizeof (packet_obj_t)); 184 if (pkt_obj == NULL) { 185 return (NULL); 186 } 187 188 hash_obj = malloc(sizeof (hash_obj_t)); 189 if (hash_obj == NULL) { 190 free(pkt_obj); 191 return (NULL); 192 } 193 194 pkt_obj->next = NULL; 195 196 hash_obj->object_type = PACKET_TYPE; 197 hash_obj->u.pkt_obj = pkt_obj; 198 hash_obj->next = NULL; 199 hash_obj->prev = NULL; 200 201 return (hash_obj); 202 } 203 204 205 206 static hash_obj_t * 207 get_container_hash_object(int object_type, handle_t handle) 208 { 209 hash_obj_t *hash_obj; 210 211 switch (object_type) { 212 case CONTAINER_TYPE: 213 break; 214 case SECTION_TYPE: 215 hash_obj = lookup_handle_object(handle, CONTAINER_TYPE); 216 if (hash_obj == NULL) { 217 return (NULL); 218 } 219 break; 220 case SEGMENT_TYPE: 221 hash_obj = lookup_handle_object(handle, SECTION_TYPE); 222 if (hash_obj == NULL) { 223 return (NULL); 224 } 225 hash_obj = lookup_handle_object(hash_obj->u.sec_obj->cont_hdl, 226 CONTAINER_TYPE); 227 break; 228 case PACKET_TYPE: 229 break; 230 default: 231 return (NULL); 232 } 233 234 return (hash_obj); 235 } 236 237 238 static void 239 add_to_pkt_object_list(hash_obj_t *parent_obj, hash_obj_t *child_obj) 240 { 241 hash_obj_t *next_hash; 242 243 /* add the packet object in the end of list */ 244 child_obj->u.pkt_obj->segment_hdl = parent_obj->obj_hdl; 245 246 if (parent_obj->u.seg_obj->pkt_obj_list == NULL) { 247 parent_obj->u.seg_obj->pkt_obj_list = child_obj; 248 return; 249 } 250 251 for (next_hash = parent_obj->u.seg_obj->pkt_obj_list; 252 next_hash->u.pkt_obj->next != NULL; 253 next_hash = next_hash->u.pkt_obj->next) { 254 ; 255 } 256 257 next_hash->u.pkt_obj->next = child_obj; 258 } 259 260 261 static void 262 free_pkt_object_list(hash_obj_t *hash_obj) 263 { 264 hash_obj_t *next_obj; 265 hash_obj_t *free_obj; 266 267 next_obj = hash_obj->u.seg_obj->pkt_obj_list; 268 while (next_obj != NULL) { 269 free_obj = next_obj; 270 next_obj = next_obj->u.pkt_obj->next; 271 /* if prev is NULL it's the first object in the list */ 272 if (free_obj->prev == NULL) { 273 hash_table[(free_obj->obj_hdl % TABLE_SIZE)] = 274 free_obj->next; 275 if (free_obj->next != NULL) { 276 free_obj->next->prev = free_obj->prev; 277 } 278 } else { 279 free_obj->prev->next = free_obj->next; 280 if (free_obj->next != NULL) { 281 free_obj->next->prev = free_obj->prev; 282 } 283 } 284 285 free(free_obj->u.pkt_obj->payload); 286 free(free_obj->u.pkt_obj); 287 free(free_obj); 288 } 289 290 hash_obj->u.seg_obj->pkt_obj_list = NULL; 291 } 292 293 294 static void 295 free_segment_hash(handle_t handle, hash_obj_t *sec_hash) 296 { 297 hash_obj_t *seg_hash; 298 hash_obj_t *next_hash; 299 300 seg_hash = sec_hash->u.sec_obj->seg_obj_list; 301 if (seg_hash == NULL) { 302 return; 303 } 304 305 if (seg_hash->obj_hdl == handle) { 306 sec_hash->u.sec_obj->seg_obj_list = seg_hash->u.seg_obj->next; 307 } else { 308 while (seg_hash->obj_hdl != handle) { 309 next_hash = seg_hash; 310 seg_hash = seg_hash->u.seg_obj->next; 311 if (seg_hash == NULL) { 312 return; 313 } 314 } 315 next_hash->u.seg_obj->next = seg_hash->u.seg_obj->next; 316 } 317 318 if (seg_hash->prev == NULL) { 319 hash_table[(seg_hash->obj_hdl % TABLE_SIZE)] = seg_hash->next; 320 if (seg_hash->next != NULL) { 321 seg_hash->next->prev = NULL; 322 } 323 } else { 324 seg_hash->prev->next = seg_hash->next; 325 if (seg_hash->next != NULL) { 326 seg_hash->next->prev = seg_hash->prev; 327 } 328 } 329 330 free_pkt_object_list(seg_hash); 331 free(seg_hash->u.seg_obj); 332 free(seg_hash); 333 } 334 335 336 337 static void 338 add_to_sec_object_list(hash_obj_t *parent_obj, hash_obj_t *child_obj) 339 { 340 hash_obj_t *next_hash; 341 342 child_obj->u.sec_obj->cont_hdl = parent_obj->obj_hdl; 343 if (parent_obj->u.cont_obj->sec_obj_list == NULL) { 344 parent_obj->u.cont_obj->sec_obj_list = child_obj; 345 return; 346 } 347 348 for (next_hash = parent_obj->u.cont_obj->sec_obj_list; 349 next_hash->u.sec_obj->next != NULL; 350 next_hash = next_hash->u.sec_obj->next) { 351 ; 352 } 353 354 next_hash->u.sec_obj->next = child_obj; 355 } 356 357 358 static void 359 add_to_seg_object_list(hash_obj_t *parent_obj, hash_obj_t *child_obj) 360 { 361 hash_obj_t *next_hash; 362 363 child_obj->u.seg_obj->section_hdl = parent_obj->obj_hdl; 364 if (parent_obj->u.sec_obj->seg_obj_list == NULL) { 365 parent_obj->u.sec_obj->seg_obj_list = child_obj; 366 return; 367 } 368 369 for (next_hash = parent_obj->u.sec_obj->seg_obj_list; 370 next_hash->u.seg_obj->next != NULL; 371 next_hash = next_hash->u.seg_obj->next) { 372 ; 373 } 374 375 next_hash->u.seg_obj->next = child_obj; 376 } 377 378 379 static char * 380 tokenizer(char *buf, char *separator, char **nextBuf, char *matched) 381 { 382 int i = 0; 383 int j = 0; 384 385 for (i = 0; buf[i] != '\0'; i++) { 386 for (j = 0; j < strlen(separator); j++) { 387 if (buf[i] == separator[j]) { 388 buf[i] = '\0'; 389 *nextBuf = &(buf[i+1]); 390 *matched = separator[j]; 391 return (buf); 392 } 393 } 394 } 395 396 *nextBuf = buf; 397 *matched = '\0'; 398 return (NULL); 399 } 400 401 402 static void 403 copy_segment_layout(segment_t *seghdr, void *layout) 404 { 405 segment_layout_t *seg_layout; 406 407 seg_layout = (segment_layout_t *)layout; 408 (void) memcpy(seghdr->name, &seg_layout->name, SEG_NAME_LEN); 409 seghdr->descriptor = GET_SEGMENT_DESCRIPTOR; 410 seghdr->offset = BE_16(seg_layout->offset); 411 seghdr->length = BE_16(seg_layout->length); 412 } 413 414 415 static int 416 get_container_info(const char *def_file, const char *cont_desc_str, 417 container_info_t *cont_info) 418 { 419 char *item; 420 char *token; 421 char *field; 422 char matched; 423 char buf[1024]; 424 int foundIt = 0; 425 FILE *file = fopen(def_file, "r"); 426 427 if (file == NULL) 428 return (-1); 429 430 cont_info->num_sections = 0; 431 432 while (fgets(buf, sizeof (buf), file) != NULL) { 433 /* ignore all comments */ 434 token = tokenizer(buf, "#", &field, &matched); 435 /* find the names */ 436 token = tokenizer(buf, ":", &field, &matched); 437 if (token != 0x00) { 438 token = tokenizer(token, "|", &item, &matched); 439 while (token != 0x00) { 440 if (strcmp(token, cont_desc_str) == 0) { 441 foundIt = 1; 442 goto found; 443 } 444 token = tokenizer(item, "|", &item, &matched); 445 } 446 /* check the last remaining item */ 447 if ((item != 0x00) && 448 (strcmp(item, cont_desc_str) == 0)) { 449 foundIt = 1; 450 goto found; 451 } 452 } 453 } 454 455 found : 456 if (foundIt == 1) { 457 token = tokenizer(field, ":", &field, &matched); 458 if (token == 0x00) { 459 (void) fclose(file); 460 return (-1); 461 } 462 cont_info->header_ver = (headerrev_t)atoi(token); 463 464 token = tokenizer(field, ":\n", &field, &matched); 465 while (token != 0x00) { 466 token = tokenizer(token, ",", &item, &matched); 467 if (token == 0x00) { 468 (void) fclose(file); 469 return (-1); 470 } 471 if (atoi(token) == 1) { 472 cont_info->section_info[cont_info-> 473 num_sections].description.field.read_only 474 = 1; 475 } else if (atoi(token) == 0) { 476 cont_info->section_info[cont_info-> 477 num_sections].description.field.read_only 478 = 0; 479 } else { 480 (void) fclose(file); 481 return (-1); 482 } 483 484 token = tokenizer(item, ",", &item, &matched); 485 if (token == 0x00) { 486 (void) fclose(file); 487 return (-1); 488 } 489 490 cont_info->section_info[cont_info-> 491 num_sections].address = atoi(token); 492 if (item == '\0') { 493 (void) fclose(file); 494 return (-1); 495 } 496 cont_info->section_info[cont_info->num_sections].size = 497 atoi(item); 498 (cont_info->num_sections)++; 499 500 token = tokenizer(field, ":\n ", &field, &matched); 501 } 502 } 503 (void) fclose(file); 504 505 return (0); 506 } 507 508 509 /* ARGSUSED */ 510 int 511 fru_get_segments(section_hdl_t section, segment_t *segment, int maxseg, 512 door_cred_t *cred) 513 { 514 int count; 515 hash_obj_t *sec_object; 516 hash_obj_t *seg_object; 517 section_obj_t *sec_obj; 518 519 sec_object = lookup_handle_object(section, SECTION_TYPE); 520 if (sec_object == NULL) { 521 return (-1); 522 } 523 524 sec_obj = sec_object->u.sec_obj; 525 if (sec_obj == NULL) { 526 return (-1); 527 } 528 529 if (sec_obj->num_of_segment > maxseg) { 530 return (-1); 531 } 532 533 seg_object = sec_object->u.sec_obj->seg_obj_list; 534 if (seg_object == NULL) { 535 return (-1); 536 } 537 538 for (count = 0; count < sec_obj->num_of_segment; count++) { 539 540 /* populate segment_t */ 541 segment->handle = seg_object->obj_hdl; 542 (void) memcpy(segment->name, 543 seg_object->u.seg_obj->segment.name, SEG_NAME_LEN); 544 segment->descriptor = seg_object->u.seg_obj->segment.descriptor; 545 546 segment->offset = seg_object->u.seg_obj->segment.offset; 547 segment->length = seg_object->u.seg_obj->segment.length; 548 seg_object = seg_object->u.seg_obj->next; 549 segment++; 550 } 551 return (0); 552 } 553 554 555 static int 556 raw_memcpy(void *buffer, raw_list_t *rawlist, int offset, int size) 557 { 558 if (offset + size > rawlist->size) { 559 size = rawlist->size - offset; 560 } 561 562 (void) memcpy(buffer, &rawlist->raw[offset], size); 563 564 return (size); 565 } 566 567 568 static int 569 verify_header_crc8(headerrev_t head_ver, unsigned char *bytes, int length) 570 { 571 int crc_offset = 0; 572 unsigned char orig_crc8 = 0; 573 unsigned char calc_crc8 = 0; 574 575 switch (head_ver) { 576 case SECTION_HDR_VER: 577 crc_offset = 4; 578 break; 579 default: 580 errno = EINVAL; 581 return (0); 582 } 583 584 orig_crc8 = bytes[crc_offset]; 585 bytes[crc_offset] = 0x00; /* clear for calc */ 586 calc_crc8 = compute_crc8(bytes, length); 587 bytes[crc_offset] = orig_crc8; /* restore */ 588 589 return (orig_crc8 == calc_crc8); 590 } 591 592 593 static int 594 get_section(raw_list_t *rawlist, hash_obj_t *sec_hash, section_t *section) 595 { 596 int retval; 597 int size; 598 int count; 599 uint16_t hdrver; 600 hash_obj_t *seg_hash; 601 unsigned char *buffer; 602 section_obj_t *sec_obj; 603 section_layout_t sec_hdr; 604 segment_layout_t *seg_hdr; 605 segment_layout_t *seg_buf; 606 607 sec_obj = sec_hash->u.sec_obj; 608 if (sec_obj == NULL) { 609 return (-1); 610 } 611 612 /* populate section_t */ 613 section->handle = sec_hash->obj_hdl; 614 section->offset = sec_obj->section.offset; 615 section->length = sec_obj->section.length; 616 section->protection = sec_obj->section.protection; 617 section->version = sec_obj->section.version; 618 619 /* read section header layout */ 620 retval = raw_memcpy(&sec_hdr, rawlist, sec_obj->section.offset, 621 sizeof (sec_hdr)); 622 623 if (retval != sizeof (sec_hdr)) { 624 return (-1); 625 } 626 627 628 hdrver = GET_SECTION_HDR_VERSION; 629 630 if ((sec_hdr.headertag != SECTION_HDR_TAG) && 631 (hdrver != section->version)) { 632 return (-1); 633 } 634 635 /* size = section layout + total sizeof segment header */ 636 size = sizeof (sec_hdr) + ((sec_hdr.segmentcount) 637 * sizeof (segment_layout_t)); 638 639 buffer = alloca(size); 640 if (buffer == NULL) { 641 return (-1); 642 } 643 644 /* segment header buffer */ 645 seg_buf = alloca(size - sizeof (sec_hdr)); 646 if (seg_buf == NULL) { 647 return (-1); 648 } 649 650 /* read segment header */ 651 retval = raw_memcpy(seg_buf, rawlist, 652 sec_obj->section.offset + sizeof (sec_hdr), 653 size - sizeof (sec_hdr)); 654 655 if (retval != (size - sizeof (sec_hdr))) { 656 return (-1); 657 } 658 659 /* copy section header layout */ 660 (void) memcpy(buffer, &sec_hdr, sizeof (sec_hdr)); 661 662 /* copy segment header layout */ 663 (void) memcpy(buffer + sizeof (sec_hdr), seg_buf, size - 664 sizeof (sec_hdr)); 665 666 /* verify crc8 */ 667 retval = verify_header_crc8(hdrver, buffer, size); 668 if (retval != TRUE) { 669 return (-1); 670 } 671 672 section->version = hdrver; 673 sec_obj->section.version = hdrver; 674 675 seg_hdr = (segment_layout_t *)seg_buf; 676 677 /* bug fix for frutool */ 678 if (sec_hash->u.sec_obj->seg_obj_list != NULL) { 679 return (0); 680 } else { 681 sec_obj->num_of_segment = 0; 682 } 683 for (count = 0; count < sec_hdr.segmentcount; count++, seg_hdr++) { 684 685 seg_hash = create_segment_hash_object(); 686 if (seg_hash == NULL) { 687 return (-1); 688 } 689 add_hashobject_to_hashtable(seg_hash); 690 copy_segment_layout(&seg_hash->u.seg_obj->segment, seg_hdr); 691 add_to_seg_object_list(sec_hash, seg_hash); 692 sec_obj->num_of_segment++; 693 } 694 return (0); 695 } 696 697 /* ARGSUSED */ 698 int 699 fru_get_sections(container_hdl_t container, section_t *section, int maxsec, 700 door_cred_t *cred) 701 { 702 int count; 703 int num_sec = 0; 704 hash_obj_t *cont_object; 705 hash_obj_t *sec_hash; 706 707 cont_object = lookup_handle_object(container, CONTAINER_TYPE); 708 if (cont_object == NULL) { 709 return (-1); 710 } 711 712 if (cont_object->u.cont_obj->num_of_section > maxsec) { 713 return (-1); 714 } 715 716 sec_hash = cont_object->u.cont_obj->sec_obj_list; 717 if (sec_hash == NULL) { 718 return (-1); 719 } 720 721 for (count = 0; count < cont_object->u.cont_obj->num_of_section; 722 count++) { 723 section->version = -1; 724 /* populate section_t */ 725 if (get_section(g_raw, sec_hash, section) == 0) { 726 section++; 727 num_sec++; 728 } 729 sec_hash = sec_hash->u.sec_obj->next; 730 } 731 return (num_sec); 732 } 733 734 735 static uint32_t 736 get_checksum_crc(hash_obj_t *seg_hash, int data_size) 737 { 738 int protection; 739 int offset = 0; 740 uint32_t crc; 741 hash_obj_t *sec_hash; 742 hash_obj_t *pkt_hash; 743 unsigned char *buffer; 744 745 sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl, 746 SECTION_TYPE); 747 if (sec_hash == NULL) { 748 return ((uint32_t)-1); 749 } 750 751 buffer = alloca(data_size); 752 if (buffer == NULL) { 753 return ((uint32_t)-1); 754 } 755 756 /* traverse the packet object list for all the tags and payload */ 757 for (pkt_hash = seg_hash->u.seg_obj->pkt_obj_list; pkt_hash != NULL; 758 pkt_hash = pkt_hash->u.pkt_obj->next) { 759 (void) memcpy(buffer + offset, &pkt_hash->u.pkt_obj->tag, 760 pkt_hash->u.pkt_obj->tag_size); 761 offset += pkt_hash->u.pkt_obj->tag_size; 762 (void) memcpy(buffer + offset, pkt_hash->u.pkt_obj->payload, 763 pkt_hash->u.pkt_obj->paylen); 764 offset += pkt_hash->u.pkt_obj->paylen; 765 } 766 767 protection = sec_hash->u.sec_obj->section.protection; 768 769 if (protection == READ_ONLY_SECTION) { /* read-only section */ 770 crc = compute_crc32(buffer, data_size); 771 } else { /* read/write section */ 772 crc = compute_checksum32(buffer, data_size); 773 } 774 return (crc); /* computed crc */ 775 } 776 777 778 static int 779 get_packet(raw_list_t *rawlist, void *buffer, int size, int offset) 780 { 781 int retval; 782 783 retval = raw_memcpy(buffer, rawlist, offset, size); 784 785 if (retval != -1) { 786 return (0); 787 } 788 return (-1); 789 } 790 791 792 static int 793 get_packets(hash_obj_t *seg_hash, raw_list_t *rawlist, int offset, int length) 794 { 795 int tag_size; 796 int paylen; 797 int retval; 798 int seg_limit = 0; 799 int pktcnt = 0; 800 char *data; 801 uint32_t crc; 802 uint32_t origcrc; 803 fru_tag_t tag; 804 hash_obj_t *pkt_hash_obj; 805 hash_obj_t *sec_hash; 806 fru_segdesc_t *segdesc; 807 fru_tagtype_t tagtype; 808 char *ignore_flag; 809 810 retval = get_packet(rawlist, &tag, sizeof (fru_tag_t), offset); 811 if (retval == -1) { 812 return (-1); 813 } 814 815 /* section hash object */ 816 sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl, 817 SECTION_TYPE); 818 819 if (sec_hash == NULL) { 820 return (-1); 821 } 822 823 seg_hash->u.seg_obj->trailer_offset = offset; 824 825 data = (char *)&tag; 826 while (data[0] != SEG_TRAILER_TAG) { 827 tagtype = get_tag_type(&tag); /* verify tag type */ 828 if (tagtype == -1) { 829 return (-1); 830 } 831 832 tag_size = get_tag_size(tagtype); 833 if (tag_size == -1) { 834 return (-1); 835 } 836 837 seg_limit += tag_size; 838 if (seg_limit > length) { 839 return (-1); 840 } 841 842 paylen = get_payload_length((void *)&tag); 843 if (paylen == -1) { 844 return (-1); 845 } 846 847 seg_limit += paylen; 848 if (seg_limit > length) { 849 return (-1); 850 } 851 if ((offset + tag_size + paylen) > 852 (sec_hash->u.sec_obj->section.offset + 853 sec_hash->u.sec_obj->section.length)) { 854 return (-1); 855 } 856 857 pkt_hash_obj = create_packet_hash_object(); 858 if (pkt_hash_obj == NULL) { 859 return (-1); 860 } 861 862 pkt_hash_obj->u.pkt_obj->payload = malloc(paylen); 863 if (pkt_hash_obj->u.pkt_obj->payload == NULL) { 864 free(pkt_hash_obj); 865 return (-1); 866 } 867 868 offset += tag_size; 869 870 retval = raw_memcpy(pkt_hash_obj->u.pkt_obj->payload, rawlist, 871 offset, paylen); 872 873 if (retval != paylen) { 874 free(pkt_hash_obj->u.pkt_obj->payload); 875 free(pkt_hash_obj); 876 return (-1); 877 } 878 879 /* don't change this */ 880 pkt_hash_obj->u.pkt_obj->tag.raw_data = 0; 881 (void) memcpy(&pkt_hash_obj->u.pkt_obj->tag, &tag, tag_size); 882 pkt_hash_obj->u.pkt_obj->paylen = paylen; 883 pkt_hash_obj->u.pkt_obj->tag_size = tag_size; 884 pkt_hash_obj->u.pkt_obj->payload_offset = offset; 885 886 offset += paylen; 887 888 add_hashobject_to_hashtable(pkt_hash_obj); 889 add_to_pkt_object_list(seg_hash, pkt_hash_obj); 890 891 pktcnt++; 892 893 retval = get_packet(rawlist, &tag, sizeof (fru_tag_t), 894 offset); 895 if (retval == -1) { 896 return (retval); 897 } 898 899 data = (char *)&tag; 900 } 901 902 segdesc = (fru_segdesc_t *)&seg_hash->u.seg_obj->segment.descriptor; 903 904 seg_hash->u.seg_obj->trailer_offset = offset; 905 906 if (!segdesc->field.ignore_checksum) { 907 crc = get_checksum_crc(seg_hash, seg_limit); 908 offset = seg_hash->u.seg_obj->segment.offset; 909 910 retval = raw_memcpy(&origcrc, rawlist, offset + seg_limit + 1, 911 sizeof (origcrc)); 912 913 ignore_flag = getenv(IGNORE_CHECK); 914 if (ignore_flag != NULL) { 915 return (pktcnt); 916 } 917 918 if (retval != sizeof (origcrc)) { 919 return (-1); 920 } 921 922 origcrc = BE_32(origcrc); 923 if (origcrc != crc) { 924 seg_hash->u.seg_obj->trailer_offset = offset; 925 return (-1); 926 } 927 } 928 929 return (pktcnt); 930 } 931 932 /* ARGSUSED */ 933 int 934 fru_get_num_sections(container_hdl_t container, door_cred_t *cred) 935 { 936 hash_obj_t *hash_object; 937 938 hash_object = lookup_handle_object(container, CONTAINER_TYPE); 939 if (hash_object == NULL) { 940 return (-1); 941 } 942 943 return (hash_object->u.cont_obj->num_of_section); 944 } 945 946 /* ARGSUSED */ 947 int 948 fru_get_num_segments(section_hdl_t section, door_cred_t *cred) 949 { 950 hash_obj_t *sec_object; 951 section_obj_t *sec_obj; 952 953 sec_object = lookup_handle_object(section, SECTION_TYPE); 954 if (sec_object == NULL) { 955 return (-1); 956 } 957 958 sec_obj = sec_object->u.sec_obj; 959 if (sec_obj == NULL) { 960 return (-1); 961 } 962 963 return (sec_obj->num_of_segment); 964 } 965 966 /* ARGSUSED */ 967 int 968 fru_get_num_packets(segment_hdl_t segment, door_cred_t *cred) 969 { 970 int pktcnt; 971 int length; 972 uint16_t offset; 973 hash_obj_t *cont_hash_obj; 974 hash_obj_t *seg_hash; 975 hash_obj_t *sec_hash; 976 fru_segdesc_t *segdesc; 977 segment_obj_t *segment_object; 978 979 seg_hash = lookup_handle_object(segment, SEGMENT_TYPE); 980 if (seg_hash == NULL) { 981 return (-1); 982 } 983 984 segment_object = seg_hash->u.seg_obj; 985 if (segment_object == NULL) { 986 return (-1); 987 } 988 989 segdesc = (fru_segdesc_t *)&segment_object->segment.descriptor; 990 if (segdesc->field.opaque) { 991 return (0); 992 } 993 994 offset = segment_object->segment.offset; 995 length = segment_object->segment.length; 996 997 cont_hash_obj = get_container_hash_object(SEGMENT_TYPE, 998 segment_object->section_hdl); 999 1000 if (cont_hash_obj == NULL) { 1001 return (-1); 1002 } 1003 1004 if (seg_hash->u.seg_obj->pkt_obj_list != NULL) { 1005 return (segment_object->num_of_packets); 1006 } 1007 /* section hash object */ 1008 sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl, 1009 SECTION_TYPE); 1010 if (sec_hash == NULL) { 1011 return (-1); 1012 } 1013 1014 /* valid segment header b'cos crc8 already validated */ 1015 if (offset < sec_hash->u.sec_obj->section.offset) { 1016 return (-1); 1017 } 1018 1019 segment_object->num_of_packets = 0; 1020 1021 pktcnt = get_packets(seg_hash, g_raw, offset, length); 1022 if (pktcnt == -1) { 1023 free_pkt_object_list(seg_hash); 1024 seg_hash->u.seg_obj->pkt_obj_list = NULL; 1025 } 1026 1027 segment_object->num_of_packets = pktcnt; 1028 1029 return (segment_object->num_of_packets); 1030 } 1031 1032 /* ARGSUSED */ 1033 int 1034 fru_get_packets(segment_hdl_t segment, packet_t *packet, int maxpackets, 1035 door_cred_t *cred) 1036 { 1037 int count; 1038 hash_obj_t *seg_hash_obj; 1039 hash_obj_t *pkt_hash_obj; 1040 1041 /* segment hash object */ 1042 seg_hash_obj = lookup_handle_object(segment, SEGMENT_TYPE); 1043 if (seg_hash_obj == NULL) { 1044 return (-1); 1045 } 1046 1047 if (seg_hash_obj->u.seg_obj->num_of_packets != maxpackets) { 1048 return (-1); 1049 } 1050 1051 pkt_hash_obj = seg_hash_obj->u.seg_obj->pkt_obj_list; 1052 if (pkt_hash_obj == NULL) { 1053 return (-1); 1054 } 1055 1056 for (count = 0; count < maxpackets; count++, packet++) { 1057 packet->handle = pkt_hash_obj->obj_hdl; 1058 packet->tag = 0; 1059 (void) memcpy(&packet->tag, &pkt_hash_obj->u.pkt_obj->tag, 1060 pkt_hash_obj->u.pkt_obj->tag_size); 1061 pkt_hash_obj = pkt_hash_obj->u.pkt_obj->next; 1062 } 1063 1064 return (0); 1065 } 1066 1067 /* ARGSUSED */ 1068 ssize_t 1069 fru_get_payload(packet_hdl_t packet, void *buffer, size_t nbytes, 1070 door_cred_t *cred) 1071 { 1072 hash_obj_t *packet_hash_obj; 1073 1074 /* packet hash object */ 1075 packet_hash_obj = lookup_handle_object(packet, PACKET_TYPE); 1076 if (packet_hash_obj == NULL) { 1077 return (-1); 1078 } 1079 1080 /* verify payload length */ 1081 if (nbytes != packet_hash_obj->u.pkt_obj->paylen) { 1082 return (-1); 1083 } 1084 1085 (void) memcpy(buffer, packet_hash_obj->u.pkt_obj->payload, nbytes); 1086 return (nbytes); 1087 } 1088 1089 1090 container_hdl_t 1091 open_raw_data(raw_list_t *node) 1092 { 1093 char *cont_conf_file = NULL; 1094 hash_obj_t *cont_hash_obj; 1095 hash_obj_t *sec_hash_obj; 1096 container_info_t cont_info; 1097 int retval; 1098 int count; 1099 1100 cont_hash_obj = create_container_hash_object(); 1101 if (cont_hash_obj == NULL) { 1102 return (NULL); 1103 } 1104 1105 add_hashobject_to_hashtable(cont_hash_obj); 1106 1107 (void) strncpy(cont_hash_obj->u.cont_obj->device_pathname, "unknown", 1108 sizeof (cont_hash_obj->u.cont_obj->device_pathname)); 1109 1110 cont_conf_file = getenv(FRU_CONT_CONF_ENV_VAR); 1111 if (cont_conf_file == NULL) { 1112 cont_conf_file = FRU_CONT_CONF_SPARC; 1113 retval = get_container_info(cont_conf_file, node->cont_type, 1114 &cont_info); 1115 if (retval < 0) { 1116 cont_conf_file = FRU_CONT_CONF_X86; 1117 retval = get_container_info(cont_conf_file, 1118 node->cont_type, &cont_info); 1119 } 1120 } else { 1121 retval = get_container_info(cont_conf_file, node->cont_type, 1122 &cont_info); 1123 } 1124 1125 if (retval < 0) { 1126 return (NULL); 1127 } 1128 1129 cont_hash_obj->u.cont_obj->num_of_section = cont_info.num_sections; 1130 cont_hash_obj->u.cont_obj->sec_obj_list = NULL; 1131 1132 for (count = 0; count < cont_info.num_sections; count++) { 1133 sec_hash_obj = create_section_hash_object(); 1134 if (sec_hash_obj == NULL) { 1135 return (NULL); 1136 } 1137 1138 add_hashobject_to_hashtable(sec_hash_obj); 1139 1140 sec_hash_obj->u.sec_obj->section.offset = 1141 cont_info.section_info[count].address; 1142 1143 sec_hash_obj->u.sec_obj->section.protection = 1144 cont_info.section_info[count].description.field.read_only; 1145 1146 sec_hash_obj->u.sec_obj->section.length = 1147 cont_info.section_info[count].size; 1148 sec_hash_obj->u.sec_obj->section.version = 1149 cont_info.header_ver; 1150 1151 add_to_sec_object_list(cont_hash_obj, sec_hash_obj); 1152 } 1153 1154 return (cont_hash_obj->obj_hdl); 1155 } 1156 1157 1158 int 1159 fru_close_container(container_hdl_t container) 1160 { 1161 hash_obj_t *hash_obj; 1162 hash_obj_t *prev_hash; 1163 hash_obj_t *sec_hash_obj; 1164 handle_t obj_hdl; 1165 1166 /* lookup for container hash object */ 1167 hash_obj = lookup_handle_object(container, CONTAINER_TYPE); 1168 if (hash_obj == NULL) { 1169 return (0); 1170 } 1171 1172 /* points to section object list */ 1173 sec_hash_obj = hash_obj->u.cont_obj->sec_obj_list; 1174 1175 /* traverse section object list */ 1176 while (sec_hash_obj != NULL) { 1177 1178 /* traverse segment hash object in the section */ 1179 while (sec_hash_obj->u.sec_obj->seg_obj_list != NULL) { 1180 /* object handle of the segment hash object */ 1181 obj_hdl = 1182 sec_hash_obj->u.sec_obj->seg_obj_list->obj_hdl; 1183 free_segment_hash(obj_hdl, sec_hash_obj); 1184 } 1185 1186 /* going to free section hash object, relink the hash object */ 1187 if (sec_hash_obj->prev == NULL) { 1188 hash_table[(sec_hash_obj->obj_hdl % TABLE_SIZE)] = 1189 sec_hash_obj->next; 1190 if (sec_hash_obj->next != NULL) { 1191 sec_hash_obj->next->prev = NULL; 1192 } 1193 } else { 1194 sec_hash_obj->prev->next = sec_hash_obj->next; 1195 if (sec_hash_obj->next != NULL) { 1196 sec_hash_obj->next->prev = sec_hash_obj->prev; 1197 } 1198 } 1199 1200 free(sec_hash_obj->u.sec_obj); /* free section hash object */ 1201 1202 prev_hash = sec_hash_obj; 1203 1204 sec_hash_obj = sec_hash_obj->u.sec_obj->next; 1205 1206 free(prev_hash); /* free section hash */ 1207 } 1208 1209 /* free container hash object */ 1210 if (hash_obj->prev == NULL) { 1211 hash_table[(hash_obj->obj_hdl % TABLE_SIZE)] = 1212 hash_obj->next; 1213 if (hash_obj->next != NULL) { 1214 hash_obj->next->prev = NULL; 1215 } 1216 } else { 1217 hash_obj->prev->next = hash_obj->next; 1218 if (hash_obj->next != NULL) { 1219 hash_obj->next->prev = hash_obj->prev; 1220 } 1221 } 1222 1223 free(hash_obj->u.cont_obj); 1224 free(hash_obj); 1225 1226 return (0); 1227 } 1228