1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2021, Linaro Limited 4 * Copyright (c) 2021, Bootlin 5 * Copyright (c) 2021, Linaro Limited 6 * Copyright (c) 2021, STMicroelectronics 7 */ 8 9 #include <assert.h> 10 #include <config.h> 11 #include <initcall.h> 12 #include <kernel/boot.h> 13 #include <kernel/dt.h> 14 #include <kernel/dt_driver.h> 15 #include <libfdt.h> 16 #include <malloc.h> 17 #include <sys/queue.h> 18 #include <tee_api_defines_extensions.h> 19 #include <tee_api_types.h> 20 21 /* 22 * struct dt_driver_probe - Node instance in secure FDT to probe a driver for 23 * 24 * @link: List hook 25 * @nodeoffset: Node offset of device referenced in the FDT 26 * @type: One of DT_DRIVER_* or DT_DRIVER_NOTYPE. 27 * @deferrals: Driver probe deferrals count 28 * @dt_drv: Matching driver to probe if found or NULL 29 * @dm: Matching reference if applicable or NULL 30 */ 31 struct dt_driver_probe { 32 int nodeoffset; 33 enum dt_driver_type type; 34 unsigned int deferrals; 35 const struct dt_driver *dt_drv; 36 const struct dt_device_match *dm; 37 TAILQ_ENTRY(dt_driver_probe) link; 38 }; 39 40 /* 41 * struct dt_driver_provider - DT related info on probed device 42 * 43 * Saves information on the probed device so that device 44 * drivers can get resources from DT phandle and related arguments. 45 * 46 * @nodeoffset: Node offset of device referenced in the FDT 47 * @type: One of DT_DRIVER_* or DT_DRIVER_NOTYPE. 48 * @provider_cells: Cells count in the FDT used by the driver's references 49 * @get_of_device: Function to get driver's device ref from phandle data 50 * @priv_data: Driver private data passed as @get_of_device argument 51 * @link: Reference in DT driver providers list 52 */ 53 struct dt_driver_provider { 54 int nodeoffset; 55 enum dt_driver_type type; 56 unsigned int provider_cells; 57 uint32_t phandle; 58 get_of_device_func get_of_device; 59 void *priv_data; 60 SLIST_ENTRY(dt_driver_provider) link; 61 }; 62 63 /* 64 * Device driver providers are able to provide a driver specific instance 65 * related to device phandle arguments found in the secure embedded FDT. 66 */ 67 static SLIST_HEAD(, dt_driver_provider) dt_driver_provider_list = 68 SLIST_HEAD_INITIALIZER(dt_driver_provider_list); 69 70 /* FDT nodes for which a matching driver is to be probed */ 71 static TAILQ_HEAD(dt_driver_probe_head, dt_driver_probe) dt_driver_probe_list = 72 TAILQ_HEAD_INITIALIZER(dt_driver_probe_list); 73 74 /* FDT nodes for which a matching driver has been successfully probed */ 75 static TAILQ_HEAD(, dt_driver_probe) dt_driver_ready_list = 76 TAILQ_HEAD_INITIALIZER(dt_driver_ready_list); 77 78 /* Flag enabled when a new node (possibly typed) is added in the probe list */ 79 static bool added_node; 80 81 static void assert_type_is_valid(enum dt_driver_type type) 82 { 83 switch (type) { 84 case DT_DRIVER_NOTYPE: 85 case DT_DRIVER_UART: 86 case DT_DRIVER_CLK: 87 return; 88 default: 89 assert(0); 90 } 91 } 92 93 /* 94 * Driver provider registering API functions 95 */ 96 97 TEE_Result dt_driver_register_provider(const void *fdt, int nodeoffset, 98 get_of_device_func get_of_device, 99 void *priv, enum dt_driver_type type) 100 { 101 struct dt_driver_provider *prv = NULL; 102 int provider_cells = 0; 103 uint32_t phandle = 0; 104 105 assert_type_is_valid(type); 106 107 provider_cells = fdt_get_dt_driver_cells(fdt, nodeoffset, type); 108 if (provider_cells < 0) { 109 DMSG("Failed to find provider cells: %d", provider_cells); 110 return TEE_ERROR_GENERIC; 111 } 112 113 phandle = fdt_get_phandle(fdt, nodeoffset); 114 if (!phandle || phandle == (uint32_t)-1) { 115 DMSG("Failed to find provide phandle"); 116 return TEE_ERROR_GENERIC; 117 } 118 119 prv = calloc(1, sizeof(*prv)); 120 if (!prv) 121 return TEE_ERROR_OUT_OF_MEMORY; 122 123 prv->nodeoffset = nodeoffset; 124 prv->type = type; 125 prv->provider_cells = provider_cells; 126 prv->phandle = phandle; 127 prv->get_of_device = get_of_device; 128 prv->priv_data = priv; 129 130 SLIST_INSERT_HEAD(&dt_driver_provider_list, prv, link); 131 132 return TEE_SUCCESS; 133 } 134 135 /* Release driver provider references once all dt_drivers are initialized */ 136 static TEE_Result dt_driver_release_provider(void) 137 { 138 struct dt_driver_provider *prv = NULL; 139 140 while (!SLIST_EMPTY(&dt_driver_provider_list)) { 141 prv = SLIST_FIRST(&dt_driver_provider_list); 142 SLIST_REMOVE_HEAD(&dt_driver_provider_list, link); 143 free(prv); 144 } 145 146 return TEE_SUCCESS; 147 } 148 149 release_init_resource(dt_driver_release_provider); 150 151 /* 152 * Helper functions for dt_drivers querying driver provider information 153 */ 154 155 int fdt_get_dt_driver_cells(const void *fdt, int nodeoffset, 156 enum dt_driver_type type) 157 { 158 const char *cells_name = NULL; 159 const fdt32_t *c = NULL; 160 int len = 0; 161 162 switch (type) { 163 case DT_DRIVER_CLK: 164 cells_name = "#clock-cells"; 165 break; 166 default: 167 panic(); 168 } 169 170 c = fdt_getprop(fdt, nodeoffset, cells_name, &len); 171 if (!c) 172 return len; 173 174 if (len != sizeof(*c)) 175 return -FDT_ERR_BADNCELLS; 176 177 return fdt32_to_cpu(*c); 178 } 179 180 unsigned int dt_driver_provider_cells(struct dt_driver_provider *prv) 181 { 182 return prv->provider_cells; 183 } 184 185 struct dt_driver_provider * 186 dt_driver_get_provider_by_node(int nodeoffset, enum dt_driver_type type) 187 { 188 struct dt_driver_provider *prv = NULL; 189 190 SLIST_FOREACH(prv, &dt_driver_provider_list, link) 191 if (prv->nodeoffset == nodeoffset && prv->type == type) 192 return prv; 193 194 return NULL; 195 } 196 197 struct dt_driver_provider * 198 dt_driver_get_provider_by_phandle(uint32_t phandle, enum dt_driver_type type) 199 { 200 struct dt_driver_provider *prv = NULL; 201 202 SLIST_FOREACH(prv, &dt_driver_provider_list, link) 203 if (prv->phandle == phandle && prv->type == type) 204 return prv; 205 206 return NULL; 207 } 208 209 static void *device_from_provider_prop(struct dt_driver_provider *prv, 210 const uint32_t *prop, 211 TEE_Result *res) 212 { 213 struct dt_driver_phandle_args *pargs = NULL; 214 unsigned int n = 0; 215 void *device = NULL; 216 217 pargs = calloc(1, prv->provider_cells * sizeof(uint32_t *) + 218 sizeof(*pargs)); 219 if (!pargs) { 220 *res = TEE_ERROR_OUT_OF_MEMORY; 221 return NULL; 222 } 223 224 pargs->args_count = prv->provider_cells; 225 for (n = 0; n < prv->provider_cells; n++) 226 pargs->args[n] = fdt32_to_cpu(prop[n + 1]); 227 228 device = prv->get_of_device(pargs, prv->priv_data, res); 229 230 free(pargs); 231 232 return device; 233 } 234 235 void *dt_driver_device_from_node_idx_prop(const char *prop_name, 236 const void *fdt, int nodeoffset, 237 unsigned int prop_idx, 238 enum dt_driver_type type, 239 TEE_Result *res) 240 { 241 int len = 0; 242 int idx = 0; 243 int idx32 = 0; 244 int prv_cells = 0; 245 uint32_t phandle = 0; 246 const uint32_t *prop = NULL; 247 struct dt_driver_provider *prv = NULL; 248 249 prop = fdt_getprop(fdt, nodeoffset, prop_name, &len); 250 if (!prop) { 251 DMSG("Property %s missing in node %s", prop_name, 252 fdt_get_name(fdt, nodeoffset, NULL)); 253 *res = TEE_ERROR_GENERIC; 254 return NULL; 255 } 256 257 while (idx < len) { 258 idx32 = idx / sizeof(uint32_t); 259 phandle = fdt32_to_cpu(prop[idx32]); 260 261 prv = dt_driver_get_provider_by_phandle(phandle, type); 262 if (!prv) { 263 /* No provider registered yet */ 264 *res = TEE_ERROR_DEFER_DRIVER_INIT; 265 return NULL; 266 } 267 268 prv_cells = dt_driver_provider_cells(prv); 269 if (prop_idx) { 270 prop_idx--; 271 idx += sizeof(phandle) + prv_cells * sizeof(uint32_t); 272 continue; 273 } 274 275 return device_from_provider_prop(prv, prop + idx32, res); 276 } 277 278 *res = TEE_ERROR_GENERIC; 279 return NULL; 280 } 281 282 static unsigned int __maybe_unused probe_list_count(void) 283 { 284 struct dt_driver_probe *elt = NULL; 285 unsigned int count = 0; 286 287 TAILQ_FOREACH(elt, &dt_driver_probe_list, link) 288 count++; 289 290 return count; 291 } 292 293 static void __maybe_unused print_probe_list(const void *fdt __maybe_unused) 294 { 295 struct dt_driver_probe *elt = NULL; 296 297 DMSG("Probe list: %u elements", probe_list_count()); 298 299 TAILQ_FOREACH(elt, &dt_driver_probe_list, link) 300 DMSG("- Driver %s probes on node %s", 301 elt->dt_drv->name, 302 fdt_get_name(fdt, elt->nodeoffset, NULL)); 303 304 DMSG("Probe list end"); 305 } 306 307 /* 308 * Probe element: push to ready list if succeeds, push to probe list if probe 309 * if deferred, panic with an error trace otherwise. 310 */ 311 static TEE_Result probe_driver_node(const void *fdt, 312 struct dt_driver_probe *elt) 313 { 314 TEE_Result res = TEE_ERROR_GENERIC; 315 const char __maybe_unused *drv_name = NULL; 316 const char __maybe_unused *node_name = NULL; 317 318 node_name = fdt_get_name(fdt, elt->nodeoffset, NULL); 319 drv_name = elt->dt_drv->name; 320 321 if (!elt->dt_drv->probe) { 322 DMSG("No probe operator for driver %s, skipped", drv_name); 323 return TEE_SUCCESS; 324 } 325 326 FMSG("Probing %s on node %s", drv_name, node_name); 327 328 res = elt->dt_drv->probe(fdt, elt->nodeoffset, elt->dm->compat_data); 329 switch (res) { 330 case TEE_SUCCESS: 331 TAILQ_INSERT_HEAD(&dt_driver_ready_list, elt, link); 332 333 DMSG("element: %s on node %s initialized", drv_name, node_name); 334 break; 335 case TEE_ERROR_DEFER_DRIVER_INIT: 336 elt->deferrals++; 337 TAILQ_INSERT_TAIL(&dt_driver_probe_list, elt, link); 338 339 DMSG("element: %s on node %s deferred %u time(s)", drv_name, 340 node_name, elt->deferrals); 341 break; 342 default: 343 EMSG("Fail to probe %s on node %s: %#"PRIx32, 344 drv_name, node_name, res); 345 panic(); 346 } 347 348 return res; 349 } 350 351 static TEE_Result alloc_elt_and_probe(const void *fdt, int node, 352 const struct dt_driver *dt_drv, 353 const struct dt_device_match *dm) 354 { 355 struct dt_driver_probe *elt = NULL; 356 357 /* Will be freed when lists are released */ 358 elt = calloc(1, sizeof(*elt)); 359 if (!elt) 360 return TEE_ERROR_OUT_OF_MEMORY; 361 362 elt->nodeoffset = node; 363 elt->dt_drv = dt_drv; 364 elt->dm = dm; 365 elt->type = dt_drv->type; 366 367 return probe_driver_node(fdt, elt); 368 } 369 370 /* Lookup a compatible driver, possibly of a specific @type, for the FDT node */ 371 static TEE_Result probe_device_by_compat(const void *fdt, int node, 372 const char *compat, 373 enum dt_driver_type type) 374 { 375 const struct dt_driver *drv = NULL; 376 const struct dt_device_match *dm = NULL; 377 378 for_each_dt_driver(drv) { 379 if (drv->type != type) 380 continue; 381 382 for (dm = drv->match_table; dm && dm->compatible; dm++) 383 if (strcmp(dm->compatible, compat) == 0) 384 return alloc_elt_and_probe(fdt, node, drv, dm); 385 } 386 387 return TEE_ERROR_ITEM_NOT_FOUND; 388 } 389 390 /* 391 * Lookup the best matching compatible driver, possibly of a specific @type, 392 * for the FDT node. 393 */ 394 TEE_Result dt_driver_probe_device_by_node(const void *fdt, int nodeoffset, 395 enum dt_driver_type type) 396 { 397 int idx = 0; 398 int len = 0; 399 int count = 0; 400 const char *compat = NULL; 401 TEE_Result res = TEE_ERROR_GENERIC; 402 403 assert_type_is_valid(type); 404 405 count = fdt_stringlist_count(fdt, nodeoffset, "compatible"); 406 if (count < 0) 407 return TEE_ERROR_ITEM_NOT_FOUND; 408 409 for (idx = 0; idx < count; idx++) { 410 compat = fdt_stringlist_get(fdt, nodeoffset, "compatible", 411 idx, &len); 412 if (!compat) 413 return TEE_ERROR_GENERIC; 414 415 res = probe_device_by_compat(fdt, nodeoffset, compat, type); 416 417 if (res != TEE_ERROR_ITEM_NOT_FOUND) 418 return res; 419 } 420 421 return TEE_ERROR_ITEM_NOT_FOUND; 422 } 423 424 static TEE_Result process_probe_list(const void *fdt) 425 { 426 struct dt_driver_probe *elt = NULL; 427 struct dt_driver_probe *prev = NULL; 428 unsigned int __maybe_unused loop_count = 0; 429 unsigned int __maybe_unused deferral_loop_count = 0; 430 bool __maybe_unused one_deferred = false; 431 bool one_probed_ok = false; 432 433 do { 434 loop_count++; 435 FMSG("Probe loop %u after %u for deferral(s)", loop_count, 436 deferral_loop_count); 437 438 /* Hack here for TRACE_DEBUG messages on probe list elements */ 439 if (TRACE_LEVEL >= TRACE_FLOW) 440 print_probe_list(fdt); 441 442 if (TAILQ_EMPTY(&dt_driver_probe_list)) 443 return TEE_SUCCESS; 444 445 /* 446 * Probe from current end to top. Deferred probed node are 447 * pushed back after current tail for the next probe round. 448 * Reset probe result flags and see status after probe round. 449 */ 450 one_deferred = false; 451 one_probed_ok = false; 452 added_node = false; 453 454 TAILQ_FOREACH_REVERSE_SAFE(elt, &dt_driver_probe_list, 455 dt_driver_probe_head, link, prev) { 456 TAILQ_REMOVE(&dt_driver_probe_list, elt, link); 457 458 switch (probe_driver_node(fdt, elt)) { 459 case TEE_SUCCESS: 460 one_probed_ok = true; 461 break; 462 case TEE_ERROR_DEFER_DRIVER_INIT: 463 one_deferred = true; 464 break; 465 default: 466 /* We don't expect error return codes */ 467 assert(0); 468 } 469 } 470 471 if (one_deferred) 472 deferral_loop_count++; 473 474 } while (added_node || one_probed_ok); 475 476 EMSG("Panic on unresolved dependencies after %u rounds, %u deferred:", 477 loop_count, deferral_loop_count); 478 479 TAILQ_FOREACH(elt, &dt_driver_probe_list, link) 480 EMSG("- %s on node %s", elt->dt_drv->name, 481 fdt_get_name(fdt, elt->nodeoffset, NULL)); 482 483 panic(); 484 } 485 486 static int driver_probe_compare(struct dt_driver_probe *candidate, 487 struct dt_driver_probe *elt) 488 { 489 if (candidate->nodeoffset != elt->nodeoffset || 490 candidate->type != elt->type) 491 return 1; 492 493 assert(elt->dt_drv == candidate->dt_drv); 494 return 0; 495 } 496 497 /* 498 * Return TEE_SUCCESS if compatible found 499 * TEE_ERROR_OUT_OF_MEMORY if heap is exhausted 500 */ 501 static TEE_Result add_node_to_probe(const void *fdt, int node, 502 const struct dt_driver *dt_drv, 503 const struct dt_device_match *dm) 504 { 505 const char __maybe_unused *node_name = fdt_get_name(fdt, node, NULL); 506 const char __maybe_unused *drv_name = dt_drv->name; 507 struct dt_driver_probe *elt = NULL; 508 struct dt_driver_probe elt_new = { 509 .dm = dm, 510 .dt_drv = dt_drv, 511 .nodeoffset = node, 512 .type = dt_drv->type, 513 }; 514 515 /* If node/type found in probe list or ready list, nothing to do */ 516 TAILQ_FOREACH(elt, &dt_driver_probe_list, link) 517 if (!driver_probe_compare(&elt_new, elt)) 518 return TEE_SUCCESS; 519 520 TAILQ_FOREACH(elt, &dt_driver_ready_list, link) 521 if (!driver_probe_compare(&elt_new, elt)) 522 return TEE_SUCCESS; 523 524 elt = malloc(sizeof(*elt)); 525 if (!elt) 526 return TEE_ERROR_OUT_OF_MEMORY; 527 528 DMSG("element: %s on node %s", node_name, drv_name); 529 530 memcpy(elt, &elt_new, sizeof(*elt)); 531 532 added_node = true; 533 534 TAILQ_INSERT_TAIL(&dt_driver_probe_list, elt, link); 535 536 /* Hack here for TRACE_DEBUG messages on current probe list elements */ 537 if (TRACE_LEVEL >= TRACE_FLOW) 538 print_probe_list(fdt); 539 540 return TEE_SUCCESS; 541 } 542 543 /* 544 * Add a node to the probe list if a dt_driver matches target compatible. 545 * 546 * If @type is DT_DRIVER_ANY, probe list can hold only 1 driver to probe for 547 * the node. A node may probe several drivers if have a unique driver type. 548 * 549 * Return TEE_SUCCESS if compatible found 550 * TEE_ERROR_ITEM_NOT_FOUND if no matching driver 551 * TEE_ERROR_OUT_OF_MEMORY if heap is exhausted 552 */ 553 static TEE_Result add_probe_node_by_compat(const void *fdt, int node, 554 const char *compat) 555 { 556 TEE_Result res = TEE_ERROR_ITEM_NOT_FOUND; 557 const struct dt_driver *dt_drv = NULL; 558 const struct dt_device_match *dm = NULL; 559 uint32_t found_types = 0; 560 561 for_each_dt_driver(dt_drv) { 562 for (dm = dt_drv->match_table; dm && dm->compatible; dm++) { 563 if (strcmp(dm->compatible, compat) == 0) { 564 assert(dt_drv->type < 32); 565 566 res = add_node_to_probe(fdt, node, dt_drv, dm); 567 if (res) 568 return res; 569 570 if (found_types & BIT(dt_drv->type)) { 571 EMSG("Driver %s multi hit on type %u", 572 dt_drv->name, dt_drv->type); 573 panic(); 574 } 575 found_types |= BIT(dt_drv->type); 576 577 /* Matching found for this driver, try next */ 578 break; 579 } 580 } 581 } 582 583 return res; 584 } 585 586 /* 587 * Add the node to the probe list if matching compatible drivers are found. 588 * Follow node's compatible property list ordering to find matching driver. 589 */ 590 TEE_Result dt_driver_maybe_add_probe_node(const void *fdt, int node) 591 { 592 int idx = 0; 593 int len = 0; 594 int count = 0; 595 const char *compat = NULL; 596 TEE_Result res = TEE_ERROR_GENERIC; 597 598 if (_fdt_get_status(fdt, node) == DT_STATUS_DISABLED) 599 return TEE_SUCCESS; 600 601 count = fdt_stringlist_count(fdt, node, "compatible"); 602 if (count < 0) 603 return TEE_SUCCESS; 604 605 for (idx = 0; idx < count; idx++) { 606 compat = fdt_stringlist_get(fdt, node, "compatible", idx, &len); 607 assert(compat && len > 0); 608 609 res = add_probe_node_by_compat(fdt, node, compat); 610 611 /* Stop lookup if something was found */ 612 if (res != TEE_ERROR_ITEM_NOT_FOUND) 613 return res; 614 } 615 616 return TEE_SUCCESS; 617 } 618 619 static void parse_node(const void *fdt, int node) 620 { 621 TEE_Result __maybe_unused res = TEE_ERROR_GENERIC; 622 int subnode = 0; 623 624 fdt_for_each_subnode(subnode, fdt, node) { 625 res = dt_driver_maybe_add_probe_node(fdt, subnode); 626 if (res) { 627 EMSG("Failed on node %s with %#"PRIx32, 628 fdt_get_name(fdt, subnode, NULL), res); 629 panic(); 630 } 631 632 /* 633 * Rescursively parse the FDT, skipping disabled nodes. 634 * FDT is expected reliable and core shall have sufficient 635 * stack depth to possibly parse all DT nodes. 636 */ 637 if (IS_ENABLED(CFG_DRIVERS_DT_RECURSIVE_PROBE)) { 638 if (_fdt_get_status(fdt, subnode) == DT_STATUS_DISABLED) 639 continue; 640 641 parse_node(fdt, subnode); 642 } 643 } 644 } 645 646 /* 647 * Parse FDT for nodes and save in probe list the node for which a dt_driver 648 * matches node's compatible property. 649 */ 650 static TEE_Result probe_dt_drivers(void) 651 { 652 const void *fdt = NULL; 653 654 if (!IS_ENABLED(CFG_EMBED_DTB)) 655 return TEE_SUCCESS; 656 657 fdt = get_embedded_dt(); 658 assert(fdt); 659 660 parse_node(fdt, fdt_path_offset(fdt, "/")); 661 662 return process_probe_list(fdt); 663 } 664 665 driver_init(probe_dt_drivers); 666 667 static TEE_Result release_probe_lists(void) 668 { 669 struct dt_driver_probe *elt = NULL; 670 struct dt_driver_probe *next = NULL; 671 const void * __maybe_unused fdt = NULL; 672 673 if (!IS_ENABLED(CFG_EMBED_DTB)) 674 return TEE_SUCCESS; 675 676 fdt = get_embedded_dt(); 677 678 assert(fdt && TAILQ_EMPTY(&dt_driver_probe_list)); 679 680 TAILQ_FOREACH_SAFE(elt, &dt_driver_ready_list, link, next) { 681 DMSG("element: %s on node %s", elt->dt_drv->name, 682 fdt_get_name(fdt, elt->nodeoffset, NULL)); 683 free(elt); 684 } 685 686 return TEE_SUCCESS; 687 } 688 689 release_init_resource(release_probe_lists); 690 691 /* 692 * Simple bus support: handy to parse subnodes 693 */ 694 static TEE_Result simple_bus_probe(const void *fdt, int node, 695 const void *compat_data __unused) 696 { 697 TEE_Result res = TEE_ERROR_GENERIC; 698 int subnode = 0; 699 700 fdt_for_each_subnode(subnode, fdt, node) { 701 res = dt_driver_maybe_add_probe_node(fdt, subnode); 702 if (res) { 703 EMSG("Failed on node %s with %#"PRIx32, 704 fdt_get_name(fdt, subnode, NULL), res); 705 panic(); 706 } 707 } 708 709 return TEE_SUCCESS; 710 } 711 712 static const struct dt_device_match simple_bus_match_table[] = { 713 { .compatible = "simple-bus" }, 714 { } 715 }; 716 717 const struct dt_driver simple_bus_dt_driver __dt_driver = { 718 .name = "simple-bus", 719 .match_table = simple_bus_match_table, 720 .probe = simple_bus_probe, 721 }; 722