| 517 | */ |
| 518 | template <typename Callback> |
| 519 | [[nodiscard]] auto ForEachDeviceNode(Callback&& callback) const |
| 520 | -> Expected<void> { |
| 521 | assert(fdt_header_ != nullptr && "ForEachDeviceNode: fdt_header_ is null"); |
| 522 | |
| 523 | int offset = -1; |
| 524 | int depth = 0; |
| 525 | |
| 526 | while (true) { |
| 527 | offset = fdt_next_node(fdt_header_, offset, &depth); |
| 528 | if (offset < 0) { |
| 529 | if (offset == -FDT_ERR_NOTFOUND) { |
| 530 | break; |
| 531 | } |
| 532 | return std::unexpected(Error(ErrorCode::kFdtParseFailed)); |
| 533 | } |
| 534 | |
| 535 | const char* node_name = fdt_get_name(fdt_header_, offset, nullptr); |
| 536 | if (node_name == nullptr) { |
| 537 | continue; |
| 538 | } |
| 539 | |
| 540 | // status 过滤(与 ForEachNode 相同) |
| 541 | int status_len = 0; |
| 542 | const auto* status_prop = |
| 543 | fdt_get_property(fdt_header_, offset, "status", &status_len); |
| 544 | if (status_prop != nullptr) { |
| 545 | const char* status = reinterpret_cast<const char*>(status_prop->data); |
| 546 | if (strcmp(status, "okay") != 0 && strcmp(status, "ok") != 0) { |
| 547 | continue; |
| 548 | } |
| 549 | } |
| 550 | |
| 551 | // 基础设施节点过滤 |
| 552 | if (fdt_getprop(fdt_header_, offset, "interrupt-controller", nullptr) != |
| 553 | nullptr) { |
| 554 | continue; |
| 555 | } |
| 556 | if (fdt_getprop(fdt_header_, offset, "#clock-cells", nullptr) != |
| 557 | nullptr) { |
| 558 | continue; |
| 559 | } |
| 560 | { |
| 561 | int dt_len = 0; |
| 562 | const auto* dt_prop = |
| 563 | fdt_get_property(fdt_header_, offset, "device_type", &dt_len); |
| 564 | if (dt_prop != nullptr) { |
| 565 | const char* dt = reinterpret_cast<const char*>(dt_prop->data); |
| 566 | if (strcmp(dt, "cpu") == 0 || strcmp(dt, "memory") == 0) { |
| 567 | continue; |
| 568 | } |
| 569 | } |
| 570 | } |
| 571 | |
| 572 | // compatible 提取 |
| 573 | const char* compatible_data = nullptr; |
| 574 | size_t compatible_len = 0; |
| 575 | int compat_len = 0; |
| 576 | const auto* compat_prop = |