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 (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 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" 32 33 #pragma init(initialize_raw_access) 34 35 static hash_obj_t *hash_table[TABLE_SIZE]; 36 extern raw_list_t *g_raw; 37 38 static void 39 initialize_raw_access(void) 40 { 41 int count; 42 43 for (count = 0; count < TABLE_SIZE; count++) { 44 hash_table[count] = NULL; 45 } 46 } 47 48 49 static hash_obj_t * 50 lookup_handle_object(handle_t handle, int object_type) 51 { 52 handle_t index_to_hash; 53 hash_obj_t *first_hash_obj; 54 hash_obj_t *next_hash_obj; 55 56 index_to_hash = (handle % TABLE_SIZE); 57 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); 64 } 65 } 66 return (NULL); 67 } 68 69 70 static void 71 add_hashobject_to_hashtable(hash_obj_t *hash_obj) 72 { 73 handle_t index_to_hash; 74 static uint64_t handle_count = 0; 75 76 hash_obj->obj_hdl = ++handle_count; /* store the handle */ 77 78 /* where to add ? */ 79 index_to_hash = ((hash_obj->obj_hdl) % TABLE_SIZE); 80 81 hash_obj->next = hash_table[index_to_hash]; 82 hash_table[index_to_hash] = hash_obj; /* hash obj. added */ 83 84 if (hash_obj->next != NULL) { 85 hash_obj->next->prev = hash_obj; 86 } 87 } 88 89 90 static hash_obj_t * 91 create_container_hash_object(void) 92 { 93 hash_obj_t *hash_obj; 94 container_obj_t *cont_obj; 95 96 cont_obj = malloc(sizeof (container_obj_t)); 97 if (cont_obj == NULL) { 98 return (NULL); 99 } 100 101 hash_obj = malloc(sizeof (hash_obj_t)); 102 if (hash_obj == NULL) { 103 free(cont_obj); 104 return (NULL); 105 } 106 107 cont_obj->sec_obj_list = NULL; 108 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; 113 114 return (hash_obj); 115 } 116 117 118 static hash_obj_t * 119 create_section_hash_object(void) 120 { 121 hash_obj_t *hash_obj; 122 section_obj_t *sec_obj; 123 124 sec_obj = malloc(sizeof (section_obj_t)); 125 if (sec_obj == NULL) { 126 return (NULL); 127 } 128 129 hash_obj = malloc(sizeof (hash_obj_t)); 130 if (hash_obj == NULL) { 131 free(sec_obj); 132 return (NULL); 133 } 134 135 sec_obj->next = NULL; 136 sec_obj->seg_obj_list = NULL; 137 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; 142 143 return (hash_obj); 144 } 145 146 147 static hash_obj_t * 148 create_segment_hash_object(void) 149 { 150 hash_obj_t *hash_obj; 151 segment_obj_t *seg_obj; 152 153 seg_obj = malloc(sizeof (segment_obj_t)); 154 if (seg_obj == NULL) { 155 return (NULL); 156 } 157 158 hash_obj = malloc(sizeof (hash_obj_t)); 159 if (hash_obj == NULL) { 160 free(seg_obj); 161 return (NULL); 162 } 163 164 seg_obj->next = NULL; 165 seg_obj->pkt_obj_list = NULL; 166 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; 171 172 return (hash_obj); 173 } 174 175 176 static hash_obj_t * 177 create_packet_hash_object(void) 178 { 179 hash_obj_t *hash_obj; 180 packet_obj_t *pkt_obj; 181 182 pkt_obj = malloc(sizeof (packet_obj_t)); 183 if (pkt_obj == NULL) { 184 return (NULL); 185 } 186 187 hash_obj = malloc(sizeof (hash_obj_t)); 188 if (hash_obj == NULL) { 189 free(pkt_obj); 190 return (NULL); 191 } 192 193 pkt_obj->next = NULL; 194 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; 199 200 return (hash_obj); 201 } 202 203 204 205 static hash_obj_t * 206 get_container_hash_object(int object_type, handle_t handle) 207 { 208 hash_obj_t *hash_obj; 209 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); 217 } 218 break; 219 case SEGMENT_TYPE: 220 hash_obj = lookup_handle_object(handle, SECTION_TYPE); 221 if (hash_obj == NULL) { 222 return (NULL); 223 } 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); 231 } 232 233 return (hash_obj); 234 } 235 236 237 static void 238 add_to_pkt_object_list(hash_obj_t *parent_obj, hash_obj_t *child_obj) 239 { 240 hash_obj_t *next_hash; 241 242 /* add the packet object in the end of list */ 243 child_obj->u.pkt_obj->segment_hdl = parent_obj->obj_hdl; 244 245 if (parent_obj->u.seg_obj->pkt_obj_list == NULL) { 246 parent_obj->u.seg_obj->pkt_obj_list = child_obj; 247 return; 248 } 249 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) { 253 ; 254 } 255 256 next_hash->u.pkt_obj->next = child_obj; 257 } 258 259 260 static void 261 free_pkt_object_list(hash_obj_t *hash_obj) 262 { 263 hash_obj_t *next_obj; 264 hash_obj_t *free_obj; 265 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; 276 } 277 } else { 278 free_obj->prev->next = free_obj->next; 279 if (free_obj->next != NULL) { 280 free_obj->next->prev = free_obj->prev; 281 } 282 } 283 284 free(free_obj->u.pkt_obj->payload); 285 free(free_obj->u.pkt_obj); 286 free(free_obj); 287 } 288 289 hash_obj->u.seg_obj->pkt_obj_list = NULL; 290 } 291 292 293 static void 294 free_segment_hash(handle_t handle, hash_obj_t *sec_hash) 295 { 296 hash_obj_t *seg_hash; 297 hash_obj_t *next_hash; 298 299 seg_hash = sec_hash->u.sec_obj->seg_obj_list; 300 if (seg_hash == NULL) { 301 return; 302 } 303 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; 312 } 313 } 314 next_hash->u.seg_obj->next = seg_hash->u.seg_obj->next; 315 } 316 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; 321 } 322 } else { 323 seg_hash->prev->next = seg_hash->next; 324 if (seg_hash->next != NULL) { 325 seg_hash->next->prev = seg_hash->prev; 326 } 327 } 328 329 free_pkt_object_list(seg_hash); 330 free(seg_hash->u.seg_obj); 331 free(seg_hash); 332 } 333 334 335 336 static void 337 add_to_sec_object_list(hash_obj_t *parent_obj, hash_obj_t *child_obj) 338 { 339 hash_obj_t *next_hash; 340 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; 345 } 346 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) { 350 ; 351 } 352 353 next_hash->u.sec_obj->next = child_obj; 354 } 355 356 357 static void 358 add_to_seg_object_list(hash_obj_t *parent_obj, hash_obj_t *child_obj) 359 { 360 hash_obj_t *next_hash; 361 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; 366 } 367 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) { 371 ; 372 } 373 374 next_hash->u.seg_obj->next = child_obj; 375 } 376 377 378 static char * 379 tokenizer(char *buf, char *separator, char **nextBuf, char *matched) 380 { 381 int i = 0; 382 int j = 0; 383 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); 391 } 392 } 393 } 394 395 *nextBuf = buf; 396 *matched = '\0'; 397 return (NULL); 398 } 399 400 401 static void 402 copy_segment_layout(segment_t *seghdr, void *layout) 403 { 404 segment_layout_t *seg_layout; 405 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); 411 } 412 413 414 static int 415 get_container_info(const char *def_file, const char *cont_desc_str, 416 container_info_t *cont_info) 417 { 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"); 425 426 if (file == NULL) 427 return (-1); 428 429 cont_info->num_sections = 0; 430 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; 442 } 443 token = tokenizer(item, "|", &item, &matched); 444 } 445 /* check the last remaining item */ 446 if ((item != 0x00) && 447 (strcmp(item, cont_desc_str) == 0)) { 448 foundIt = 1; 449 goto found; 450 } 451 } 452 } 453 454 found : 455 if (foundIt == 1) { 456 token = tokenizer(field, ":", &field, &matched); 457 if (token == 0x00) { 458 (void) fclose(file); 459 return (-1); 460 } 461 cont_info->header_ver = (headerrev_t)atoi(token); 462 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); 469 } 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); 481 } 482 483 token = tokenizer(item, ",", &item, &matched); 484 if (token == 0x00) { 485 (void) fclose(file); 486 return (-1); 487 } 488 489 cont_info->section_info[cont_info-> 490 num_sections].address = atoi(token); 491 if (item == '\0') { 492 (void) fclose(file); 493 return (-1); 494 } 495 cont_info->section_info[cont_info->num_sections].size = 496 atoi(item); 497 (cont_info->num_sections)++; 498 499 token = tokenizer(field, ":\n ", &field, &matched); 500 } 501 } 502 (void) fclose(file); 503 504 return (0); 505 } 506 507 508 /* ARGSUSED */ 509 int 510 fru_get_segments(section_hdl_t section, segment_t *segment, int maxseg, 511 door_cred_t *cred) 512 { 513 int count; 514 hash_obj_t *sec_object; 515 hash_obj_t *seg_object; 516 section_obj_t *sec_obj; 517 518 sec_object = lookup_handle_object(section, SECTION_TYPE); 519 if (sec_object == NULL) { 520 return (-1); 521 } 522 523 sec_obj = sec_object->u.sec_obj; 524 if (sec_obj == NULL) { 525 return (-1); 526 } 527 528 if (sec_obj->num_of_segment > maxseg) { 529 return (-1); 530 } 531 532 seg_object = sec_object->u.sec_obj->seg_obj_list; 533 if (seg_object == NULL) { 534 return (-1); 535 } 536 537 for (count = 0; count < sec_obj->num_of_segment; count++) { 538 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; 544 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++; 549 } 550 return (0); 551 } 552 553 554 static int 555 raw_memcpy(void *buffer, raw_list_t *rawlist, int offset, int size) 556 { 557 if (offset + size > rawlist->size) { 558 size = rawlist->size - offset; 559 } 560 561 (void) memcpy(buffer, &rawlist->raw[offset], size); 562 563 return (size); 564 } 565 566 567 static int 568 verify_header_crc8(headerrev_t head_ver, unsigned char *bytes, int length) 569 { 570 int crc_offset = 0; 571 unsigned char orig_crc8 = 0; 572 unsigned char calc_crc8 = 0; 573 574 switch (head_ver) { 575 case SECTION_HDR_VER: 576 crc_offset = 4; 577 break; 578 default: 579 errno = EINVAL; 580 return (0); 581 } 582 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 */ 587 588 return (orig_crc8 == calc_crc8); 589 } 590 591 592 static int 593 get_section(raw_list_t *rawlist, hash_obj_t *sec_hash, section_t *section) 594 { 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; 605 606 sec_obj = sec_hash->u.sec_obj; 607 if (sec_obj == NULL) { 608 return (-1); 609 } 610 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; 617 618 /* read section header layout */ 619 retval = raw_memcpy(&sec_hdr, rawlist, sec_obj->section.offset, 620 sizeof (sec_hdr)); 621 622 if (retval != sizeof (sec_hdr)) { 623 return (-1); 624 } 625 626 627 hdrver = GET_SECTION_HDR_VERSION; 628 629 if ((sec_hdr.headertag != SECTION_HDR_TAG) && 630 (hdrver != section->version)) { 631 return (-1); 632 } 633 634 /* size = section layout + total sizeof segment header */ 635 size = sizeof (sec_hdr) + ((sec_hdr.segmentcount) 636 * sizeof (segment_layout_t)); 637 638 buffer = alloca(size); 639 if (buffer == NULL) { 640 return (-1); 641 } 642 643 /* segment header buffer */ 644 seg_buf = alloca(size - sizeof (sec_hdr)); 645 if (seg_buf == NULL) { 646 return (-1); 647 } 648 649 /* read segment header */ 650 retval = raw_memcpy(seg_buf, rawlist, 651 sec_obj->section.offset + sizeof (sec_hdr), 652 size - sizeof (sec_hdr)); 653 654 if (retval != (size - sizeof (sec_hdr))) { 655 return (-1); 656 } 657 658 /* copy section header layout */ 659 (void) memcpy(buffer, &sec_hdr, sizeof (sec_hdr)); 660 661 /* copy segment header layout */ 662 (void) memcpy(buffer + sizeof (sec_hdr), seg_buf, size - 663 sizeof (sec_hdr)); 664 665 /* verify crc8 */ 666 retval = verify_header_crc8(hdrver, buffer, size); 667 if (retval != TRUE) { 668 return (-1); 669 } 670 671 section->version = hdrver; 672 sec_obj->section.version = hdrver; 673 674 seg_hdr = (segment_layout_t *)seg_buf; 675 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; 681 } 682 for (count = 0; count < sec_hdr.segmentcount; count++, seg_hdr++) { 683 684 seg_hash = create_segment_hash_object(); 685 if (seg_hash == NULL) { 686 return (-1); 687 } 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++; 692 } 693 return (0); 694 } 695 696 /* ARGSUSED */ 697 int 698 fru_get_sections(container_hdl_t container, section_t *section, int maxsec, 699 door_cred_t *cred) 700 { 701 int count; 702 int num_sec = 0; 703 hash_obj_t *cont_object; 704 hash_obj_t *sec_hash; 705 706 cont_object = lookup_handle_object(container, CONTAINER_TYPE); 707 if (cont_object == NULL) { 708 return (-1); 709 } 710 711 if (cont_object->u.cont_obj->num_of_section > maxsec) { 712 return (-1); 713 } 714 715 sec_hash = cont_object->u.cont_obj->sec_obj_list; 716 if (sec_hash == NULL) { 717 return (-1); 718 } 719 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++; 727 } 728 sec_hash = sec_hash->u.sec_obj->next; 729 } 730 return (num_sec); 731 } 732 733 734 static uint32_t 735 get_checksum_crc(hash_obj_t *seg_hash, int data_size) 736 { 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; 743 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); 748 } 749 750 buffer = alloca(data_size); 751 if (buffer == NULL) { 752 return ((uint32_t)-1); 753 } 754 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; 764 } 765 766 protection = sec_hash->u.sec_obj->section.protection; 767 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); 772 } 773 return (crc); /* computed crc */ 774 } 775 776 777 static int 778 get_packet(raw_list_t *rawlist, void *buffer, int size, int offset) 779 { 780 int retval; 781 782 retval = raw_memcpy(buffer, rawlist, offset, size); 783 784 if (retval != -1) { 785 return (0); 786 } 787 return (-1); 788 } 789 790 791 static int 792 get_packets(hash_obj_t *seg_hash, raw_list_t *rawlist, int offset, int length) 793 { 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; 808 809 retval = get_packet(rawlist, &tag, sizeof (fru_tag_t), offset); 810 if (retval == -1) { 811 return (-1); 812 } 813 814 /* section hash object */ 815 sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl, 816 SECTION_TYPE); 817 818 if (sec_hash == NULL) { 819 return (-1); 820 } 821 822 seg_hash->u.seg_obj->trailer_offset = offset; 823 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); 829 } 830 831 tag_size = get_tag_size(tagtype); 832 if (tag_size == -1) { 833 return (-1); 834 } 835 836 seg_limit += tag_size; 837 if (seg_limit > length) { 838 return (-1); 839 } 840 841 paylen = get_payload_length((void *)&tag); 842 if (paylen == -1) { 843 return (-1); 844 } 845 846 seg_limit += paylen; 847 if (seg_limit > length) { 848 return (-1); 849 } 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); 854 } 855 856 pkt_hash_obj = create_packet_hash_object(); 857 if (pkt_hash_obj == NULL) { 858 return (-1); 859 } 860 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); 865 } 866 867 offset += tag_size; 868 869 retval = raw_memcpy(pkt_hash_obj->u.pkt_obj->payload, rawlist, 870 offset, paylen); 871 872 if (retval != paylen) { 873 free(pkt_hash_obj->u.pkt_obj->payload); 874 free(pkt_hash_obj); 875 return (-1); 876 } 877 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; 884 885 offset += paylen; 886 887 add_hashobject_to_hashtable(pkt_hash_obj); 888 add_to_pkt_object_list(seg_hash, pkt_hash_obj); 889 890 pktcnt++; 891 892 retval = get_packet(rawlist, &tag, sizeof (fru_tag_t), 893 offset); 894 if (retval == -1) { 895 return (retval); 896 } 897 898 data = (char *)&tag; 899 } 900 901 segdesc = (fru_segdesc_t *)&seg_hash->u.seg_obj->segment.descriptor; 902 903 seg_hash->u.seg_obj->trailer_offset = offset; 904 905 if (!segdesc->field.ignore_checksum) { 906 crc = get_checksum_crc(seg_hash, seg_limit); 907 offset = seg_hash->u.seg_obj->segment.offset; 908 909 retval = raw_memcpy(&origcrc, rawlist, offset + seg_limit + 1, 910 sizeof (origcrc)); 911 912 ignore_flag = getenv(IGNORE_CHECK); 913 if (ignore_flag != NULL) { 914 return (pktcnt); 915 } 916 917 if (retval != sizeof (origcrc)) { 918 return (-1); 919 } 920 921 origcrc = BE_32(origcrc); 922 if (origcrc != crc) { 923 seg_hash->u.seg_obj->trailer_offset = offset; 924 return (-1); 925 } 926 } 927 928 return (pktcnt); 929 } 930 931 /* ARGSUSED */ 932 int 933 fru_get_num_sections(container_hdl_t container, door_cred_t *cred) 934 { 935 hash_obj_t *hash_object; 936 937 hash_object = lookup_handle_object(container, CONTAINER_TYPE); 938 if (hash_object == NULL) { 939 return (-1); 940 } 941 942 return (hash_object->u.cont_obj->num_of_section); 943 } 944 945 /* ARGSUSED */ 946 int 947 fru_get_num_segments(section_hdl_t section, door_cred_t *cred) 948 { 949 hash_obj_t *sec_object; 950 section_obj_t *sec_obj; 951 952 sec_object = lookup_handle_object(section, SECTION_TYPE); 953 if (sec_object == NULL) { 954 return (-1); 955 } 956 957 sec_obj = sec_object->u.sec_obj; 958 if (sec_obj == NULL) { 959 return (-1); 960 } 961 962 return (sec_obj->num_of_segment); 963 } 964 965 /* ARGSUSED */ 966 int 967 fru_get_num_packets(segment_hdl_t segment, door_cred_t *cred) 968 { 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; 977 978 seg_hash = lookup_handle_object(segment, SEGMENT_TYPE); 979 if (seg_hash == NULL) { 980 return (-1); 981 } 982 983 segment_object = seg_hash->u.seg_obj; 984 if (segment_object == NULL) { 985 return (-1); 986 } 987 988 segdesc = (fru_segdesc_t *)&segment_object->segment.descriptor; 989 if (segdesc->field.opaque) { 990 return (0); 991 } 992 993 offset = segment_object->segment.offset; 994 length = segment_object->segment.length; 995 996 cont_hash_obj = get_container_hash_object(SEGMENT_TYPE, 997 segment_object->section_hdl); 998 999 if (cont_hash_obj == NULL) { 1000 return (-1); 1001 } 1002 1003 if (seg_hash->u.seg_obj->pkt_obj_list != NULL) { 1004 return (segment_object->num_of_packets); 1005 } 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); 1011 } 1012 1013 /* valid segment header b'cos crc8 already validated */ 1014 if (offset < sec_hash->u.sec_obj->section.offset) { 1015 return (-1); 1016 } 1017 1018 segment_object->num_of_packets = 0; 1019 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; 1024 } 1025 1026 segment_object->num_of_packets = pktcnt; 1027 1028 return (segment_object->num_of_packets); 1029 } 1030 1031 /* ARGSUSED */ 1032 int 1033 fru_get_packets(segment_hdl_t segment, packet_t *packet, int maxpackets, 1034 door_cred_t *cred) 1035 { 1036 int count; 1037 hash_obj_t *seg_hash_obj; 1038 hash_obj_t *pkt_hash_obj; 1039 1040 /* segment hash object */ 1041 seg_hash_obj = lookup_handle_object(segment, SEGMENT_TYPE); 1042 if (seg_hash_obj == NULL) { 1043 return (-1); 1044 } 1045 1046 if (seg_hash_obj->u.seg_obj->num_of_packets != maxpackets) { 1047 return (-1); 1048 } 1049 1050 pkt_hash_obj = seg_hash_obj->u.seg_obj->pkt_obj_list; 1051 if (pkt_hash_obj == NULL) { 1052 return (-1); 1053 } 1054 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; 1061 } 1062 1063 return (0); 1064 } 1065 1066 /* ARGSUSED */ 1067 ssize_t 1068 fru_get_payload(packet_hdl_t packet, void *buffer, size_t nbytes, 1069 door_cred_t *cred) 1070 { 1071 hash_obj_t *packet_hash_obj; 1072 1073 /* packet hash object */ 1074 packet_hash_obj = lookup_handle_object(packet, PACKET_TYPE); 1075 if (packet_hash_obj == NULL) { 1076 return (-1); 1077 } 1078 1079 /* verify payload length */ 1080 if (nbytes != packet_hash_obj->u.pkt_obj->paylen) { 1081 return (-1); 1082 } 1083 1084 (void) memcpy(buffer, packet_hash_obj->u.pkt_obj->payload, nbytes); 1085 return (nbytes); 1086 } 1087 1088 1089 container_hdl_t 1090 open_raw_data(raw_list_t *node) 1091 { 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; 1098 1099 cont_hash_obj = create_container_hash_object(); 1100 if (cont_hash_obj == NULL) { 1101 return (NULL); 1102 } 1103 1104 add_hashobject_to_hashtable(cont_hash_obj); 1105 1106 (void) strncpy(cont_hash_obj->u.cont_obj->device_pathname, "unknown", 1107 sizeof (cont_hash_obj->u.cont_obj->device_pathname)); 1108 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); 1118 } 1119 } else { 1120 retval = get_container_info(cont_conf_file, node->cont_type, 1121 &cont_info); 1122 } 1123 1124 if (retval < 0) { 1125 return (NULL); 1126 } 1127 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; 1130 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 (NULL); 1135 } 1136 1137 add_hashobject_to_hashtable(sec_hash_obj); 1138 1139 sec_hash_obj->u.sec_obj->section.offset = 1140 cont_info.section_info[count].address; 1141 1142 sec_hash_obj->u.sec_obj->section.protection = 1143 cont_info.section_info[count].description.field.read_only; 1144 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; 1149 1150 add_to_sec_object_list(cont_hash_obj, sec_hash_obj); 1151 } 1152 1153 return (cont_hash_obj->obj_hdl); 1154 } 1155 1156 1157 int 1158 fru_close_container(container_hdl_t container) 1159 { 1160 hash_obj_t *hash_obj; 1161 hash_obj_t *prev_hash; 1162 hash_obj_t *sec_hash_obj; 1163 handle_t obj_hdl; 1164 1165 /* lookup for container hash object */ 1166 hash_obj = lookup_handle_object(container, CONTAINER_TYPE); 1167 if (hash_obj == NULL) { 1168 return (0); 1169 } 1170 1171 /* points to section object list */ 1172 sec_hash_obj = hash_obj->u.cont_obj->sec_obj_list; 1173 1174 /* traverse section object list */ 1175 while (sec_hash_obj != NULL) { 1176 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); 1183 } 1184 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; 1191 } 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; 1196 } 1197 } 1198 1199 prev_hash = sec_hash_obj; 1200 sec_hash_obj = sec_hash_obj->u.sec_obj->next; 1201 1202 free(prev_hash->u.sec_obj); /* free section hash object */ 1203 free(prev_hash); /* free section hash */ 1204 } 1205 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; 1212 } 1213 } else { 1214 hash_obj->prev->next = hash_obj->next; 1215 if (hash_obj->next != NULL) { 1216 hash_obj->next->prev = hash_obj->prev; 1217 } 1218 } 1219 1220 free(hash_obj->u.cont_obj); 1221 free(hash_obj); 1222 1223 return (0); 1224 } 1225