1 /* $NetBSD: ieee1212.c,v 1.3 2002/05/23 00:10:46 jmc Exp $ */ 2 3 /* 4 * Copyright (c) 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by James Chacon. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/device.h> 42 #include <sys/kernel.h> 43 #include <sys/malloc.h> 44 45 #include <dev/std/ieee1212reg.h> 46 #include <dev/std/ieee1212var.h> 47 48 static const char * const p1212_keytype_strings[] = P1212_KEYTYPE_STRINGS ; 49 static const char * const p1212_keyvalue_strings[] = P1212_KEYVALUE_STRINGS ; 50 51 static u_int16_t p1212_calc_crc(u_int32_t, u_int32_t *, int, int); 52 static int p1212_parse_directory(struct p1212_dir *, u_int32_t *, u_int32_t); 53 static struct p1212_leafdata *p1212_parse_leaf(u_int32_t *); 54 static int p1212_parse_textdir(struct p1212_com *, u_int32_t *); 55 static struct p1212_textdata *p1212_parse_text_desc(u_int32_t *); 56 static void p1212_print_node(struct p1212_key *, void *); 57 static int p1212_validate_offset(u_int16_t, u_int32_t); 58 static int p1212_validate_immed(u_int16_t, u_int32_t); 59 static int p1212_validate_leaf(u_int16_t, u_int32_t); 60 static int p1212_validate_dir(u_int16_t, u_int32_t); 61 62 #ifdef P1212_DEBUG 63 #define DPRINTF(x) if (p1212debug) printf x 64 #define DPRINTFN(n,x) if (p1212debug>(n)) printf x 65 int p1212debug = 1; 66 #else 67 #define DPRINTF(x) 68 #define DPRINTFN(n,x) 69 #endif 70 71 /* 72 * Routines to parse the ROM into a tree that's usable. Also verify integrity 73 * vs. the P1212 standard 74 */ 75 76 /* 77 * A buffer of u_int32_t's and a size in quads gets passed in. The output will 78 * return -1 on error, or 0 on success and possibly reset *size to a larger 79 * value. 80 * 81 * NOTE: Rom's are guarentee'd per the ISO spec to be contiguous but only the 82 * first 1k is directly mapped. Anything past 1k is supposed to use a loop 83 * around the indirect registers to read in the rom. This code only assumes the 84 * buffer passed in represents a total rom regardless of end size. It is the 85 * callers responsibility to treat a size > 1024 as a special case. 86 */ 87 88 int 89 p1212_iscomplete(u_int32_t *t, u_int32_t *size) 90 { 91 u_int16_t infolen, crclen, len; 92 u_int32_t newlen, offset, test; 93 int complete, i, numdirs, type, val, *dirs; 94 95 dirs = NULL; 96 97 if (*size == 0) { 98 DPRINTF(("Invalid size for ROM: %d\n", (unsigned int)*size)); 99 return -1; 100 } 101 102 infolen = P1212_ROMFMT_GET_INFOLEN((ntohl(t[0]))); 103 if (infolen <= 1) { 104 DPRINTF(("ROM not initialized or minimal ROM: Info " 105 "length: %d\n", infolen)); 106 return -1; 107 } 108 crclen = P1212_ROMFMT_GET_CRCLEN((ntohl(t[0]))); 109 if (crclen < infolen) { 110 DPRINTF(("CRC len less than info len. CRC len: %d, " 111 "Info len: %d\n", crclen, infolen)); 112 return -1; 113 } 114 115 /* 116 * Now loop through it to check if all the offsets referenced are 117 * within the image stored so far. If not, get those as well. 118 */ 119 120 offset = P1212_ROMFMT_GET_INFOLEN((ntohl(t[0]))) + 1; 121 122 /* 123 * Make sure at least the bus info block is in memory + the root dir 124 * header quad. Add 1 here since offset is an array offset and size is 125 * the total array size we want. If this is getting the root dir 126 * then add another since infolen doesn't end on the root dir entry but 127 * right before it. 128 */ 129 130 if ((*size == 1) || (*size < (offset + 1))) { 131 *size = (crclen > infolen) ? crclen : infolen; 132 if (crclen == infolen) 133 (*size)++; 134 (*size)++; 135 return 0; 136 } 137 138 complete = 0; 139 numdirs = 0; 140 newlen = 0; 141 142 while (!complete) { 143 144 /* 145 * Make sure the whole directory is in memory. If not, bail now 146 * and read it in. 147 */ 148 149 newlen = P1212_DIRENT_GET_LEN((ntohl(t[offset]))); 150 if ((offset + newlen + 1) > *size) { 151 newlen += offset + 1; 152 break; 153 } 154 155 if (newlen == 0) { 156 DPRINTF(("Impossible directory length of 0!\n")); 157 return -1; 158 } 159 160 /* 161 * Starting with the first byte of the directory, read through 162 * and check the values found. On offsets and directories read 163 * them in if appropriate (always for offsets, if not in memory 164 * for leaf/directories). 165 */ 166 167 offset++; 168 len = newlen; 169 newlen = 0; 170 for (i = 0; i < len; i++) { 171 type = P1212_DIRENT_GET_KEYTYPE((ntohl(t[offset+i]))); 172 val = P1212_DIRENT_GET_VALUE((ntohl(t[offset+i]))); 173 switch (type) { 174 case P1212_KEYTYPE_Immediate: 175 case P1212_KEYTYPE_Offset: 176 break; 177 case P1212_KEYTYPE_Leaf: 178 179 /* 180 * If a leaf is found, and it's beyond the 181 * current rom length and it's beyond the 182 * current newlen setting, 183 * then set newlen accordingly. 184 */ 185 186 test = offset + i + val + 1; 187 if ((test > *size) && (test > newlen)) { 188 newlen = test; 189 break; 190 } 191 192 /* 193 * For leaf nodes just make sure the whole leaf 194 * length is in the buffer. There's no data 195 * inside of them that can refer to outside 196 * nodes. (Uless it's vendor specific and then 197 * you're on your own anyways). 198 */ 199 200 test--; 201 infolen = 202 P1212_DIRENT_GET_LEN((ntohl(t[test]))); 203 test++; 204 test += infolen; 205 if ((test > *size) && (test > newlen)) { 206 newlen = test; 207 } 208 break; 209 210 case P1212_KEYTYPE_Directory: 211 212 /* Make sure the first quad is in memory. */ 213 214 test = offset + i + val + 1; 215 if ((test > *size) && (test > newlen)) { 216 newlen = test; 217 break; 218 } 219 220 /* 221 * Can't just walk the ROM looking at type 222 * codes since these are only valid on 223 * directory entries. So save any directories 224 * we find into a queue and the bottom of the 225 * while loop will pop the last one off and 226 * walk that directory. 227 */ 228 229 test--; 230 dirs = realloc(dirs, 231 sizeof(int) * (numdirs + 1), M_DEVBUF, 232 M_WAITOK); 233 dirs[numdirs++] = test; 234 break; 235 default: 236 panic("Impossible type code: 0x%04hx", 237 (unsigned short)type); 238 break; 239 } 240 } 241 242 if (newlen) { 243 /* Cleanup. */ 244 if (dirs) 245 free(dirs, M_DEVBUF); 246 break; 247 } 248 if (dirs) { 249 offset = dirs[--numdirs]; 250 dirs = realloc(dirs, sizeof(int) * numdirs, M_DEVBUF, 251 M_WAITOK); 252 } else 253 complete = 1; 254 } 255 256 if (newlen) 257 *size = newlen; 258 return 0; 259 260 } 261 262 struct p1212_rom * 263 p1212_parse(u_int32_t *t, u_int32_t size, u_int32_t mask) 264 { 265 266 u_int16_t crc, romcrc, crc1; 267 u_int32_t next, check; 268 struct p1212_rom *rom; 269 int i; 270 271 check = size; 272 273 if (p1212_iscomplete(t, &check) == -1) { 274 DPRINTF(("ROM is not complete\n")); 275 return NULL; 276 } 277 if (check != size) { 278 DPRINTF(("ROM is not complete (check != size)\n")); 279 return NULL; 280 } 281 282 /* Calculate both a good and known bad crc. */ 283 284 /* CRC's are calculated from everything except the first quad. */ 285 286 crc = p1212_calc_crc(0, &t[1], P1212_ROMFMT_GET_CRCLEN((ntohl(t[0]))), 287 0); 288 289 romcrc = P1212_ROMFMT_GET_CRC((ntohl(t[0]))); 290 if (crc != romcrc) { 291 crc1 = p1212_calc_crc(0, &t[1], 292 P1212_ROMFMT_GET_CRCLEN((ntohl(t[0]))), 1); 293 if (crc1 != romcrc) { 294 DPRINTF(("Invalid ROM: CRC: 0x%04hx, Calculated " 295 "CRC: 0x%04hx, CRC1: 0x%04hx\n", 296 (unsigned short)romcrc, (unsigned short)crc, 297 (unsigned short)crc1)); 298 return NULL; 299 } 300 } 301 302 /* Now, walk the ROM. */ 303 304 /* Get the initial offset for the root dir. */ 305 306 rom = malloc(sizeof(struct p1212_rom), M_DEVBUF, M_WAITOK); 307 rom->len = P1212_ROMFMT_GET_INFOLEN((ntohl(t[0]))); 308 next = rom->len + 1; 309 310 if ((rom->len < 1) || (rom->len > size)) { 311 DPRINTF(("Invalid ROM info length: %d\n", rom->len)); 312 free(rom, M_DEVBUF); 313 return NULL; 314 } 315 316 /* Exclude the quad which covers the bus name. */ 317 rom->len--; 318 319 if (rom->len) { 320 rom->data = malloc(sizeof(u_int32_t) * rom->len, M_DEVBUF, 321 M_WAITOK); 322 /* Add 2 to account for info/crc and bus name skipped. */ 323 for (i = 0; i < rom->len; i++) 324 rom->data[i] = t[i + 2]; 325 } 326 327 /* The name field is always 4 bytes and always the 2nd field. */ 328 strncpy(rom->name, (char *)&t[1], 4); 329 rom->name[4] = 0; 330 331 /* 332 * Fill out the root directory. All these values are hardcoded so the 333 * parse/print/match routines have a standard layout to work against. 334 */ 335 336 rom->root = malloc(sizeof(*rom->root), M_DEVBUF, M_WAITOK|M_ZERO); 337 rom->root->com.key.key_type = P1212_KEYTYPE_Directory; 338 rom->root->com.key.key_value = 0; 339 rom->root->com.key.key = (u_int8_t)P1212_KEYTYPE_Directory; 340 rom->root->com.key.val = 0; 341 TAILQ_INIT(&rom->root->data_root); 342 TAILQ_INIT(&rom->root->subdir_root); 343 344 if (p1212_parse_directory(rom->root, &t[next], mask)) { 345 DPRINTF(("Parse error in ROM. Bailing\n")); 346 p1212_free(rom); 347 return NULL; 348 } 349 return rom; 350 } 351 352 static int 353 p1212_parse_directory(struct p1212_dir *root, u_int32_t *addr, u_int32_t mask) 354 { 355 struct p1212_dir *dir, *sdir; 356 struct p1212_data *data; 357 struct p1212_com *com; 358 u_int32_t *t, desc; 359 u_int16_t crclen, crc, crc1, romcrc; 360 u_int8_t type, val; 361 unsigned long size; 362 int i, module_vendor_flag, module_sw_flag, node_sw_flag, unit_sw_flag; 363 int node_capabilities_flag, offset, unit_location_flag, unitdir_cnt; 364 int leafoff; 365 366 t = addr; 367 dir = root; 368 369 module_vendor_flag = 0; 370 module_sw_flag = 0; 371 node_sw_flag = 0; 372 node_capabilities_flag = 0; 373 unitdir_cnt = 0; 374 offset = 0; 375 376 while (dir) { 377 dir->match = 0; 378 crclen = P1212_DIRENT_GET_LEN((ntohl(t[offset]))); 379 romcrc = P1212_DIRENT_GET_CRC((ntohl(t[offset]))); 380 381 crc = p1212_calc_crc(0, &t[offset + 1], crclen, 0); 382 if (crc != romcrc) { 383 crc1 = p1212_calc_crc(0, &t[offset + 1], crclen, 1); 384 if (crc1 != romcrc) { 385 DPRINTF(("Invalid ROM: CRC: 0x%04hx, " 386 "Calculated CRC: " 387 "0x%04hx, CRC1: 0x%04hx\n", 388 (unsigned short)romcrc, 389 (unsigned short)crc, 390 (unsigned short)crc1)); 391 return 1; 392 } 393 } 394 com = NULL; 395 unit_sw_flag = 0; 396 unit_location_flag = 0; 397 offset++; 398 399 if ((dir->parent == NULL) && dir->com.key.val) { 400 DPRINTF(("Invalid root dir. key.val is 0x%0x and not" 401 " 0x0\n", dir->com.key.val)); 402 return 1; 403 } 404 405 for (i = offset; i < (offset + crclen); i++) { 406 desc = ntohl(t[i]); 407 type = P1212_DIRENT_GET_KEYTYPE(desc); 408 val = P1212_DIRENT_GET_KEYVALUE(desc); 409 410 /* 411 * Sanity check for valid types/locations/etc. 412 * 413 * See pages 79-100 of 414 * ISO/IEC 13213:1194(ANSI/IEEE Std 1212, 1994 edition) 415 * for specifics. 416 * 417 * XXX: These all really should be broken out into 418 * subroutines as it's grown large and complicated 419 * in certain cases. 420 */ 421 422 switch (val) { 423 case P1212_KEYVALUE_Unit_Spec_Id: 424 case P1212_KEYVALUE_Unit_Sw_Version: 425 case P1212_KEYVALUE_Unit_Dependent_Info: 426 case P1212_KEYVALUE_Unit_Location: 427 case P1212_KEYVALUE_Unit_Poll_Mask: 428 if (dir->parent == NULL) { 429 DPRINTF(("Invalid ROM: %s is not " 430 "valid in the root directory.\n", 431 p1212_keyvalue_strings[val])); 432 return 1; 433 } 434 break; 435 default: 436 if (dir->com.key.val == 437 P1212_KEYVALUE_Unit_Directory) { 438 DPRINTF(("Invalid ROM: %s is " 439 "not valid in a unit directory.\n", 440 p1212_keyvalue_strings[val])); 441 return 1; 442 } 443 break; 444 } 445 446 switch (type) { 447 case P1212_KEYTYPE_Immediate: 448 if (p1212_validate_immed(val, mask)) { 449 DPRINTF(("Invalid ROM: Can't have an " 450 "immediate type with %s value. Key" 451 " used at location 0x%0x in ROM\n", 452 p1212_keyvalue_strings[val], 453 (unsigned int)(&t[i]-&addr[0]))); 454 return 1; 455 } 456 break; 457 case P1212_KEYTYPE_Offset: 458 if (p1212_validate_offset(val, mask)) { 459 DPRINTF(("Invalid ROM: Can't have " 460 "an offset type with key %s." 461 " Used at location 0x%0x in ROM\n", 462 p1212_keyvalue_strings[val], 463 (unsigned int)(&t[i]-&addr[0]))); 464 return 1; 465 } 466 break; 467 case P1212_KEYTYPE_Leaf: 468 if (p1212_validate_leaf(val, mask)) { 469 DPRINTF(("Invalid ROM: Can't have a " 470 "leaf type with %s value. Key " 471 "used at location 0x%0x in ROM\n", 472 p1212_keyvalue_strings[val], 473 (unsigned int)(&t[i]-&addr[0]))); 474 return 1; 475 } 476 break; 477 case P1212_KEYTYPE_Directory: 478 if (p1212_validate_dir(val, mask)) { 479 DPRINTF(("Invalid ROM: Can't have a " 480 "directory type with %s value. Key" 481 " used at location 0x%0x in ROM\n", 482 p1212_keyvalue_strings[val], 483 (unsigned int)(&t[i]-&addr[0]))); 484 return 1; 485 } 486 break; 487 default: 488 panic("Impossible type code: 0x%04hx", 489 (unsigned short)type); 490 break; 491 } 492 493 /* Note flags for required fields. */ 494 495 if (val == P1212_KEYVALUE_Module_Vendor_Id) { 496 module_vendor_flag = 1; 497 } 498 499 if (val == P1212_KEYVALUE_Node_Capabilities) { 500 node_capabilities_flag = 1; 501 } 502 503 if (val == P1212_KEYVALUE_Unit_Sw_Version) 504 unit_sw_flag = 1; 505 506 if (val == P1212_KEYVALUE_Unit_Location) 507 unit_location_flag = 1; 508 509 /* 510 * This is just easier to spell out. You can't have 511 * a module sw version if you include a node sw version 512 * and vice-versa. Both aren't allowed if you have unit 513 * dirs. 514 */ 515 516 if (val == P1212_KEYVALUE_Module_Sw_Version) { 517 if (node_sw_flag) { 518 DPRINTF(("Can't have a module software" 519 " version along with a node " 520 "software version entry\n")); 521 return 1; 522 } 523 if (unitdir_cnt) { 524 DPRINTF(("Can't have unit directories " 525 "with module software version " 526 "defined.\n")); 527 return 1; 528 } 529 module_sw_flag = 1; 530 } 531 532 if (val == P1212_KEYVALUE_Node_Sw_Version) { 533 if (module_sw_flag) { 534 DPRINTF(("Can't have a node software " 535 "version along with a module " 536 "software version entry\n")); 537 return 1; 538 } 539 if (unitdir_cnt) { 540 DPRINTF(("Can't have unit directories " 541 "with node software version " 542 "defined.\n")); 543 return 1; 544 } 545 node_sw_flag = 1; 546 } 547 548 if (val == P1212_KEYVALUE_Unit_Directory) { 549 if (module_sw_flag || node_sw_flag) { 550 DPRINTF(("Can't have unit directories " 551 "with either module or node " 552 "software version defined.\n")); 553 return 1; 554 } 555 unitdir_cnt++; 556 } 557 558 /* 559 * Text descriptors are special. They describe the 560 * last entry they follow. So they need to be included 561 * with it's struct and there's nothing in the spec 562 * preventing one from putting text descriptors after 563 * directory descriptors. Also they can be a single 564 * value or a list of them in a directory format so 565 * account for either. Finally if they're in a 566 * directory those can be the only types in a 567 * directory. 568 */ 569 570 if (val == P1212_KEYVALUE_Textual_Descriptor) { 571 572 size = sizeof(struct p1212_textdata *); 573 leafoff = P1212_DIRENT_GET_VALUE(desc); 574 leafoff += i; 575 576 if (com == NULL) { 577 DPRINTF(("Can't have a text descriptor" 578 " as the first entry in a " 579 "directory\n")); 580 return 1; 581 } 582 583 if (com->textcnt != 0) { 584 DPRINTF(("Text descriptors can't " 585 "follow each other in a " 586 "directory\n")); 587 return 1; 588 } 589 590 if (type == P1212_KEYTYPE_Leaf) { 591 com->text = 592 malloc(size, M_DEVBUF, M_WAITOK); 593 com->text[0] = 594 p1212_parse_text_desc(&t[leafoff]); 595 if (com->text[0] == NULL) { 596 DPRINTF(("Got an error parsing" 597 " text descriptor at " 598 "offset 0x%0x\n", 599 &t[leafoff]-&addr[0])); 600 free(com->text, M_DEVBUF); 601 return 1; 602 } 603 com->textcnt = 1; 604 } else { 605 i = p1212_parse_textdir(com, 606 &t[leafoff]); 607 if (i) 608 return 1; 609 } 610 } 611 612 if ((type != P1212_KEYTYPE_Directory) && 613 (val != P1212_KEYVALUE_Textual_Descriptor)) { 614 data = malloc(sizeof(struct p1212_data), 615 M_DEVBUF, M_WAITOK|M_ZERO); 616 data->com.key.key_type = type; 617 data->com.key.key_value = val; 618 data->com.key.key = 619 P1212_DIRENT_GET_KEY((ntohl(t[i]))); 620 data->com.key.val = 621 P1212_DIRENT_GET_VALUE((ntohl(t[i]))); 622 com = &data->com; 623 624 /* 625 * Don't try and read the offset. It may be 626 * a register or something special. Generally 627 * these are node specific so let the upper 628 * level code figure it out. 629 */ 630 631 if ((type == P1212_KEYTYPE_Immediate) || 632 (type == P1212_KEYTYPE_Offset)) 633 data->val = data->com.key.val; 634 635 data->leafdata = NULL; 636 TAILQ_INSERT_TAIL(&dir->data_root, data, data); 637 638 if (type == P1212_KEYTYPE_Leaf) { 639 leafoff = i + data->com.key.val; 640 data->leafdata = 641 p1212_parse_leaf(&t[leafoff]); 642 if (data->leafdata == NULL) { 643 DPRINTF(("Error parsing leaf\n")); 644 return 1; 645 } 646 } 647 } 648 if (type == P1212_KEYTYPE_Directory) { 649 650 sdir = malloc(sizeof(struct p1212_dir), 651 M_DEVBUF, M_WAITOK|M_ZERO); 652 sdir->parent = dir; 653 sdir->com.key.key_type = type; 654 sdir->com.key.key_value = val; 655 sdir->com.key.key = 656 P1212_DIRENT_GET_KEY((ntohl(t[i]))); 657 sdir->com.key.val = 658 P1212_DIRENT_GET_VALUE((ntohl(t[i]))); 659 com = &sdir->com; 660 sdir->match = sdir->com.key.val + i; 661 TAILQ_INIT(&sdir->data_root); 662 TAILQ_INIT(&sdir->subdir_root); 663 TAILQ_INSERT_TAIL(&dir->subdir_root, sdir,dir); 664 } 665 } 666 667 /* More validity checks. */ 668 669 if (dir->parent == NULL) { 670 if (module_vendor_flag == 0) { 671 DPRINTF(("Missing module vendor entry in root " 672 "directory.\n")); 673 return 1; 674 } 675 if (node_capabilities_flag == 0) { 676 DPRINTF(("Missing node capabilities entry in " 677 "root directory.\n")); 678 return 1; 679 } 680 } else { 681 if ((unitdir_cnt > 1) && (unit_location_flag == 0)) { 682 DPRINTF(("Must have a unit location in each " 683 "unit directory when more than one unit " 684 "directory exists.\n")); 685 return 1; 686 } 687 } 688 689 /* 690 * Ok, done with this directory and it's sanity checked. Now 691 * loop through and either find an unparsed subdir or one 692 * farther back up the chain. 693 */ 694 695 if (!TAILQ_EMPTY(&dir->subdir_root)) { 696 sdir = TAILQ_FIRST(&dir->subdir_root); 697 } else { 698 do { 699 sdir = TAILQ_NEXT(dir, dir); 700 if (sdir == NULL) { 701 dir = dir->parent; 702 } 703 } while ((sdir == NULL) && (dir != NULL)); 704 } 705 if (dir) { 706 dir = sdir; 707 if (!dir->match) { 708 DPRINTF(("Invalid subdir..Has no offset\n")); 709 return 1; 710 } 711 offset = dir->match; 712 } 713 } 714 return 0; 715 } 716 717 static struct p1212_leafdata * 718 p1212_parse_leaf(u_int32_t *t) 719 { 720 u_int16_t crclen, crc, crc1, romcrc; 721 struct p1212_leafdata *leafdata; 722 int i; 723 724 crclen = P1212_DIRENT_GET_LEN((ntohl(t[0]))); 725 romcrc = P1212_DIRENT_GET_CRC((ntohl(t[0]))); 726 crc = p1212_calc_crc(0, &t[1], crclen, 0); 727 crc1 = p1212_calc_crc(0,&t[1], crclen, 1); 728 if ((crc != romcrc) && (crc1 != romcrc)) { 729 DPRINTF(("Invalid ROM: CRC: 0x%04hx, Calculated CRC: " 730 "0x%04hx, CRC1: 0x%04hx\n", (unsigned short)romcrc, 731 (unsigned short)crc, (unsigned short)crc1)); 732 return NULL; 733 } 734 t++; 735 736 /* 737 * Most of these are vendor specific so don't bother trying to map them 738 * out. Anything which needs them later on can extract them. 739 */ 740 741 leafdata = malloc(sizeof(struct p1212_leafdata), M_DEVBUF, M_WAITOK); 742 leafdata->data = malloc((sizeof(u_int32_t) * crclen), M_DEVBUF, 743 M_WAITOK); 744 leafdata->len = crclen; 745 for (i = 0; i < crclen; i++) 746 leafdata->data[i] = ntohl(t[i]); 747 return leafdata; 748 } 749 750 static int 751 p1212_parse_textdir(struct p1212_com *com, u_int32_t *addr) 752 { 753 u_int32_t *t, entry, new; 754 u_int16_t crclen, crc, crc1, romcrc; 755 u_int8_t type, val; 756 757 int i, size; 758 759 /* 760 * A bit more complicated. A directory for a text descriptor can 761 * contain text descriptor leaf nodes only. 762 */ 763 764 com->text = NULL; 765 size = sizeof(struct p1212_text *); 766 767 crclen = P1212_DIRENT_GET_LEN((ntohl(t[0]))); 768 romcrc = P1212_DIRENT_GET_CRC((ntohl(t[0]))); 769 crc = p1212_calc_crc(0, &t[1], crclen, 0); 770 crc1 = p1212_calc_crc(0,&t[1], crclen, 1); 771 if ((crc != romcrc) && (crc1 != romcrc)) { 772 DPRINTF(("Invalid ROM: CRC: 0x%04hx, Calculated CRC: " 773 "0x%04hx, CRC1: 0x%04hx\n", (unsigned short)romcrc, 774 (unsigned short)crc, (unsigned short)crc1)); 775 return 1; 776 } 777 t++; 778 for (i = 0; i < crclen; i++) { 779 entry = ntohl(t[i]); 780 781 type = P1212_DIRENT_GET_KEYTYPE(entry); 782 val = P1212_DIRENT_GET_KEYVALUE(entry); 783 if ((type != P1212_KEYTYPE_Leaf) || 784 (val != P1212_KEYVALUE_Textual_Descriptor)) { 785 DPRINTF(("Text descriptor directories can only " 786 "contain text descriptors. Type: %s, value: %s " 787 "isn't valid at offset 0x%0x\n", 788 p1212_keytype_strings[type], 789 p1212_keyvalue_strings[val], &t[i]-&addr[0])); 790 return 1; 791 } 792 793 new = P1212_DIRENT_GET_VALUE(entry); 794 com->text = realloc(com->text, size * (com->textcnt + 1), 795 M_DEVBUF, M_WAITOK); 796 if ((com->text[i] = p1212_parse_text_desc(&t[i+new])) == NULL) { 797 DPRINTF(("Got an error parsing text descriptor.\n")); 798 if (com->textcnt == 0) 799 free(com->text, M_DEVBUF); 800 return 1; 801 } 802 com->textcnt++; 803 } 804 return 0; 805 } 806 807 static struct p1212_textdata * 808 p1212_parse_text_desc(u_int32_t *addr) 809 { 810 u_int32_t *t; 811 u_int16_t crclen, crc, crc1, romcrc; 812 struct p1212_textdata *text; 813 int size; 814 815 t = addr; 816 817 crclen = P1212_DIRENT_GET_LEN((ntohl(t[0]))); 818 romcrc = P1212_DIRENT_GET_CRC((ntohl(t[0]))); 819 820 if (crclen < P1212_TEXT_Min_Leaf_Length) { 821 DPRINTF(("Invalid ROM: text descriptor too short\n")); 822 return NULL; 823 } 824 825 crc = p1212_calc_crc(0, &t[1], crclen, 0); 826 if (crc != romcrc) { 827 crc1 = p1212_calc_crc(0, &t[1], crclen, 1); 828 if (crc1 != romcrc) { 829 DPRINTF(("Invalid ROM: CRC: 0x%04hx, Calculated CRC: " 830 "0x%04hx, CRC1: 0x%04hx\n", (unsigned short)romcrc, 831 (unsigned short)crc, (unsigned short)crc1)); 832 return NULL; 833 } 834 } 835 836 t++; 837 text = malloc(sizeof(struct p1212_textdata), M_DEVBUF, M_WAITOK); 838 text->spec_type = P1212_TEXT_GET_Spec_Type((ntohl(t[0]))); 839 text->spec_id = P1212_TEXT_GET_Spec_Id((ntohl(t[0]))); 840 text->lang_id = ntohl(t[1]); 841 842 t++; 843 t++; 844 crclen -= 2; 845 size = (crclen * sizeof(u_int32_t)); 846 847 text->text = malloc(size + 1, M_DEVBUF, M_WAITOK|M_ZERO); 848 849 memcpy(text->text, &t[0], size); 850 851 return text; 852 } 853 854 struct p1212_key ** 855 p1212_find(struct p1212_dir *root, int type, int value, int flags) 856 { 857 struct p1212_key **retkeys; 858 struct p1212_dir *dir, *sdir, *parent; 859 struct p1212_data *data; 860 int numkeys; 861 862 numkeys = 0; 863 retkeys = NULL; 864 865 if ((type < P1212_KEYTYPE_Immediate) || 866 (type > P1212_KEYTYPE_Directory)) { 867 #ifdef DIAGNOSTIC 868 printf("p1212_find: invalid type - %d\n", type); 869 #endif 870 return NULL; 871 } 872 873 if ((value < -1) || 874 (value > (sizeof(p1212_keyvalue_strings) / sizeof(char *)))) { 875 #ifdef DIAGNOSTIC 876 printf("p1212_find: invalid value - %d\n", value); 877 #endif 878 return NULL; 879 } 880 881 if (flags & ~(P1212_FIND_SEARCHALL | P1212_FIND_RETURNALL)) { 882 #ifdef DIAGNOSTIC 883 printf("p1212_find: invalid flags - %d\n", flags); 884 #endif 885 return NULL; 886 } 887 888 /* 889 * Part of this is copied from p1212_walk to do depth first traversal 890 * without using recursion. Using the walk API would have made things 891 * more complicated in trying to build up the return struct otherwise. 892 */ 893 894 dir = root; 895 sdir = NULL; 896 897 parent = root->parent; 898 root->parent = NULL; 899 900 while (dir) { 901 if (type == P1212_KEYTYPE_Directory) { 902 TAILQ_FOREACH(sdir, &dir->subdir_root, dir) { 903 if ((sdir->com.key.key_value == value) || 904 (value == -1)) { 905 numkeys++; 906 retkeys = realloc(retkeys, 907 sizeof(struct p1212_key *) * 908 (numkeys + 1), M_WAITOK, M_DEVBUF); 909 retkeys[numkeys - 1] = &sdir->com.key; 910 retkeys[numkeys] = NULL; 911 if ((flags & P1212_FIND_RETURNALL) 912 == 0) { 913 root->parent = parent; 914 return retkeys; 915 } 916 } 917 } 918 } else { 919 TAILQ_FOREACH(data, &dir->data_root, data) { 920 if (((data->com.key.key_type == type) && 921 (data->com.key.key_value == value)) || 922 ((data->com.key.key_type == type) && 923 (value == -1))) { 924 numkeys++; 925 retkeys = realloc(retkeys, 926 sizeof(struct p1212_key *) * 927 (numkeys + 1), M_WAITOK, M_DEVBUF); 928 retkeys[numkeys - 1] = &data->com.key; 929 retkeys[numkeys] = NULL; 930 if ((flags & P1212_FIND_RETURNALL) 931 == 0) { 932 root->parent = parent; 933 return retkeys; 934 } 935 } 936 } 937 } 938 if (flags & P1212_FIND_SEARCHALL) { 939 do { 940 sdir = TAILQ_NEXT(dir, dir); 941 if (sdir == NULL) { 942 dir = dir->parent; 943 } 944 } while ((sdir == NULL) && (dir != NULL)); 945 dir = sdir; 946 } else 947 dir = NULL; 948 } 949 root->parent = parent; 950 return retkeys; 951 } 952 953 void 954 p1212_walk(struct p1212_dir *root, void *arg, 955 void (*func)(struct p1212_key *, void *)) 956 { 957 struct p1212_data *data; 958 struct p1212_dir *sdir, *dir, *parent; 959 960 dir = root; 961 sdir = NULL; 962 963 if (func == NULL) { 964 #ifdef DIAGNOSTIC 965 printf("p1212_walk: Passed in NULL function\n"); 966 #endif 967 return; 968 } 969 if (root == NULL) { 970 #ifdef DIAGNOSTIC 971 printf("p1212_walk: Called with NULL root\n"); 972 #endif 973 return; 974 } 975 976 /* Allow walking from any point. Just mark the starting point. */ 977 parent = root->parent; 978 root->parent = NULL; 979 980 /* 981 * Depth first traversal that doesn't use recursion. 982 * 983 * Call the function first for the directory node and then loop through 984 * all the data nodes and call the function for them. 985 * 986 * Finally, figure out the next possible directory node if one is 987 * available or bail out. 988 */ 989 990 while (dir) { 991 func((struct p1212_key *) dir, arg); 992 TAILQ_FOREACH(data, &dir->data_root, data) 993 func((struct p1212_key *) data, arg); 994 if (!TAILQ_EMPTY(&dir->subdir_root)) { 995 sdir = TAILQ_FIRST(&dir->subdir_root); 996 } else { 997 do { 998 sdir = TAILQ_NEXT(dir, dir); 999 if (sdir == NULL) { 1000 dir = dir->parent; 1001 } 1002 } while ((sdir == NULL) && dir); 1003 } 1004 dir = sdir; 1005 } 1006 1007 root->parent = parent; 1008 } 1009 1010 void 1011 p1212_print(struct p1212_dir *dir) 1012 { 1013 int indent; 1014 1015 indent = 0; 1016 1017 p1212_walk(dir, &indent, p1212_print_node); 1018 printf("\n"); 1019 } 1020 1021 static void 1022 p1212_print_node(struct p1212_key *key, void *arg) 1023 { 1024 1025 struct p1212_data *data; 1026 struct p1212_dir *sdir, *dir; 1027 int i, j, *indent; 1028 1029 indent = arg; 1030 1031 if (key->key_type == P1212_KEYTYPE_Directory) { 1032 dir = (struct p1212_dir *) key; 1033 data = NULL; 1034 } else { 1035 data = (struct p1212_data *) key; 1036 dir = NULL; 1037 } 1038 1039 /* Recompute the indent level on each directory. */ 1040 if (dir) { 1041 *indent = 0; 1042 sdir = dir->parent; 1043 while (sdir != NULL) { 1044 (*indent)++; 1045 sdir = sdir->parent; 1046 } 1047 } 1048 1049 if (dir && dir->parent) 1050 printf("\n"); 1051 1052 /* Set the indent string up. 4 spaces per level. */ 1053 for (i = 0; i < (*indent * 4); i++) 1054 printf(" "); 1055 1056 if (dir) { 1057 printf("Directory: "); 1058 if (dir->print) 1059 dir->print(dir); 1060 else { 1061 if (key->key_value >= 1062 (sizeof(p1212_keyvalue_strings) / sizeof(char *))) 1063 printf("Unknown type 0x%04hx\n", 1064 (unsigned short)key->key_value); 1065 else 1066 printf("%s\n", 1067 p1212_keyvalue_strings[key->key_value]); 1068 } 1069 if (dir->com.textcnt) { 1070 for (i = 0; i < dir->com.textcnt; i++) { 1071 for (j = 0; j < (*indent * 4); j++) 1072 printf(" "); 1073 printf("Text descriptor: %s\n", 1074 dir->com.text[i]->text); 1075 } 1076 } 1077 printf("\n"); 1078 } else { 1079 if (data->print) 1080 data->print(data); 1081 else { 1082 if (key->key_value >= 1083 (sizeof(p1212_keyvalue_strings) / sizeof(char *))) 1084 printf("Unknown type 0x%04hx: ", 1085 (unsigned short)key->key_value); 1086 else 1087 printf("%s: ", 1088 p1212_keyvalue_strings[key->key_value]); 1089 1090 printf("0x%08x\n", key->val); 1091 #ifdef DIAGNOSTIC 1092 if ((data->com.key.key_type == P1212_KEYTYPE_Leaf) && 1093 (data->leafdata == NULL)) 1094 panic("Invalid data node in configrom tree"); 1095 #endif 1096 1097 if (data->leafdata) { 1098 for (i = 0; i < data->leafdata->len; i++) { 1099 for (j = 0; j < (*indent * 4); j++) 1100 printf(" "); 1101 printf ("Leaf data: 0x%08x\n", 1102 data->leafdata->data[i]); 1103 } 1104 } 1105 if (data->com.textcnt) 1106 for (i = 0; i < data->com.textcnt; i++) { 1107 for (j = 0; j < (*indent * 4); j++) 1108 printf(" "); 1109 printf("Text descriptor: %s\n", 1110 data->com.text[i]->text); 1111 } 1112 1113 } 1114 } 1115 } 1116 1117 1118 void 1119 p1212_free(struct p1212_rom *rom) 1120 { 1121 struct p1212_dir *sdir, *dir; 1122 struct p1212_data *data; 1123 int i; 1124 1125 dir = rom->root; 1126 1127 /* Avoid recursing. Find the bottom most node and work back. */ 1128 while (dir) { 1129 if (!TAILQ_EMPTY(&dir->subdir_root)) { 1130 sdir = TAILQ_FIRST(&dir->subdir_root); 1131 if (TAILQ_EMPTY(&sdir->subdir_root)) { 1132 TAILQ_REMOVE(&dir->subdir_root, sdir, dir); 1133 dir = sdir; 1134 } 1135 else { 1136 dir = sdir; 1137 continue; 1138 } 1139 } else { 1140 if (dir->parent) 1141 TAILQ_REMOVE(&dir->parent->subdir_root, dir, 1142 dir); 1143 } 1144 1145 while ((data = TAILQ_FIRST(&dir->data_root))) { 1146 if (data->leafdata) { 1147 if (data->leafdata->data) 1148 free(data->leafdata->data, M_DEVBUF); 1149 free(data->leafdata, M_DEVBUF); 1150 } 1151 TAILQ_REMOVE(&dir->data_root, data, data); 1152 if (data->com.textcnt) { 1153 for (i = 0; i < data->com.textcnt; i++) 1154 free(data->com.text[i], M_DEVBUF); 1155 free(data->com.text, M_DEVBUF); 1156 } 1157 free(data, M_DEVBUF); 1158 } 1159 sdir = dir; 1160 if (dir->parent) 1161 dir = dir->parent; 1162 else 1163 dir = NULL; 1164 if (sdir->com.textcnt) { 1165 for (i = 0; i < sdir->com.textcnt; i++) 1166 free(sdir->com.text[i], M_DEVBUF); 1167 free(sdir->com.text, M_DEVBUF); 1168 } 1169 free(sdir, M_DEVBUF); 1170 } 1171 if (rom->len) 1172 free(rom->data, M_DEVBUF); 1173 free(rom, M_DEVBUF); 1174 } 1175 1176 /* 1177 * A fairly well published reference implementation of the CRC routine had 1178 * a typo in it and some devices may be using it rather than the correct one 1179 * in calculating their ROM CRC's. To compensate an interface for generating 1180 * either is provided. 1181 * 1182 * len is the number of u_int32_t entries, not bytes. 1183 */ 1184 1185 static u_int16_t 1186 p1212_calc_crc(u_int32_t crc, u_int32_t *data, int len, int broke) 1187 { 1188 int shift; 1189 u_int32_t sum; 1190 int i; 1191 1192 for (i = 0; i < len; i++) { 1193 for (shift = 28; shift > 0; shift -= 4) { 1194 sum = ((crc >> 12) ^ (ntohl(data[i]) >> shift)) & 1195 0x0000000f; 1196 crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ sum; 1197 } 1198 1199 1200 /* The broken implementation doesn't do the last shift. */ 1201 if (!broke) { 1202 sum = ((crc >> 12) ^ ntohl(data[i])) & 0x0000000f; 1203 crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ sum; 1204 } 1205 } 1206 return (u_int16_t)crc; 1207 } 1208 1209 /* 1210 * This is almost identical to the standard autoconf *match idea except it 1211 * can match and attach multiple children in one pass. 1212 */ 1213 1214 struct device ** 1215 p1212_match_units(struct device *sc, struct p1212_dir *dir, 1216 int (*print)(void *, const char *)) 1217 { 1218 struct p1212_dir **udirs; 1219 struct device **devret, *dev; 1220 int numdev; 1221 1222 /* 1223 * Setup typical return val. Always allocate one extra pointer for a 1224 * NULL guard end pointer. 1225 */ 1226 1227 numdev = 0; 1228 devret = malloc(sizeof(struct device *) * 2, M_DEVBUF, M_WAITOK); 1229 devret[1] = NULL; 1230 1231 udirs = (struct p1212_dir **)p1212_find(dir, P1212_KEYTYPE_Directory, 1232 P1212_KEYVALUE_Unit_Directory, 1233 P1212_FIND_SEARCHALL|P1212_FIND_RETURNALL); 1234 1235 if (udirs) { 1236 do { 1237 dev = config_found_sm(sc, udirs, print, NULL); 1238 if (dev && numdev) { 1239 devret = realloc(devret, 1240 sizeof(struct device *) * 1241 (numdev + 2), M_DEVBUF, M_WAITOK); 1242 devret[numdev++] = dev; 1243 devret[numdev] = NULL; 1244 } else if (dev) { 1245 devret[0] = dev; 1246 numdev++; 1247 } 1248 udirs++; 1249 } while (*udirs); 1250 } 1251 if (numdev == 0) { 1252 free(devret, M_DEVBUF); 1253 return NULL; 1254 } 1255 return devret; 1256 } 1257 1258 /* 1259 * Make these their own functions as they have slightly complicated rules. 1260 * 1261 * For example: 1262 * 1263 * Under normal circumstances only the 2 extent types can be offset 1264 * types. However some spec's which use p1212 like SBP2 for 1265 * firewire/1394 will define a dependent info type as an offset value. 1266 * Allow the upper level code to flag this and pass it down during 1267 * parsing. The same thing applies to immediate types. 1268 */ 1269 1270 static int 1271 p1212_validate_offset(u_int16_t val, u_int32_t mask) 1272 { 1273 if ((val == P1212_KEYVALUE_Node_Units_Extent) || 1274 (val == P1212_KEYVALUE_Node_Memory_Extent) || 1275 ((mask & P1212_ALLOW_DEPENDENT_INFO_OFFSET_TYPE) && 1276 ((val == P1212_KEYVALUE_Unit_Dependent_Info) || 1277 (val == P1212_KEYVALUE_Node_Dependent_Info) || 1278 (val == P1212_KEYVALUE_Module_Dependent_Info)))) 1279 return 0; 1280 return 1; 1281 } 1282 1283 static int 1284 p1212_validate_immed(u_int16_t val, u_int32_t mask) 1285 { 1286 switch (val) { 1287 case P1212_KEYVALUE_Textual_Descriptor: 1288 case P1212_KEYVALUE_Bus_Dependent_Info: 1289 case P1212_KEYVALUE_Module_Dependent_Info: 1290 case P1212_KEYVALUE_Node_Unique_Id: 1291 case P1212_KEYVALUE_Node_Dependent_Info: 1292 case P1212_KEYVALUE_Unit_Directory: 1293 case P1212_KEYVALUE_Unit_Dependent_Info: 1294 case P1212_KEYVALUE_Unit_Location: 1295 if ((mask & P1212_ALLOW_DEPENDENT_INFO_IMMED_TYPE) && 1296 ((val == P1212_KEYVALUE_Module_Dependent_Info) || 1297 (val == P1212_KEYVALUE_Node_Dependent_Info) || 1298 (val == P1212_KEYVALUE_Unit_Dependent_Info))) 1299 break; 1300 return 1; 1301 break; 1302 default: 1303 break; 1304 } 1305 return 0; 1306 } 1307 1308 static int 1309 p1212_validate_leaf(u_int16_t val, u_int32_t mask) 1310 { 1311 switch(val) { 1312 case P1212_KEYVALUE_Textual_Descriptor: 1313 case P1212_KEYVALUE_Bus_Dependent_Info: 1314 case P1212_KEYVALUE_Module_Dependent_Info: 1315 case P1212_KEYVALUE_Node_Unique_Id: 1316 case P1212_KEYVALUE_Node_Dependent_Info: 1317 case P1212_KEYVALUE_Unit_Dependent_Info: 1318 case P1212_KEYVALUE_Unit_Location: 1319 break; 1320 default: 1321 return 1; 1322 break; 1323 } 1324 return 0; 1325 } 1326 1327 static int 1328 p1212_validate_dir(u_int16_t val, u_int32_t mask) 1329 { 1330 switch(val) { 1331 case P1212_KEYVALUE_Textual_Descriptor: 1332 case P1212_KEYVALUE_Bus_Dependent_Info: 1333 case P1212_KEYVALUE_Module_Dependent_Info: 1334 case P1212_KEYVALUE_Node_Dependent_Info: 1335 case P1212_KEYVALUE_Unit_Directory: 1336 case P1212_KEYVALUE_Unit_Dependent_Info: 1337 break; 1338 default: 1339 if ((mask & P1212_ALLOW_VENDOR_DIRECTORY_TYPE) && 1340 (val == P1212_KEYVALUE_Module_Vendor_Id)) 1341 break; 1342 return 1; 1343 break; 1344 } 1345 return 0; 1346 } 1347