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