summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2026-07-10 11:48:04 +0800
committerRichard Qin <richard.qin.x@gmail.com>2026-07-10 11:48:04 +0800
commitb9ff206e6bd3f4d67851263a6f2acb5f575cf3b0 (patch)
tree701314c3aedaa5684e9d4e8f55e261a10b4875f8 /drivers
parente90b72ec3082588b296956730bd2930cf8d5d671 (diff)
downloadlume-b9ff206e6bd3f4d67851263a6f2acb5f575cf3b0.tar.gz
lume-b9ff206e6bd3f4d67851263a6f2acb5f575cf3b0.tar.xz
fix: match all FDT compatible strings
Walk the complete NUL-separated compatible property when binding platform devices so the QEMU PLIC probes correctly and UART receive interrupts reach the TTY. Add a boot-time regression assertion for IRQ-chip binding.
Diffstat (limited to 'drivers')
-rw-r--r--drivers/base/platform.cc25
1 files changed, 21 insertions, 4 deletions
diff --git a/drivers/base/platform.cc b/drivers/base/platform.cc
index 65ec21e..fae8af6 100644
--- a/drivers/base/platform.cc
+++ b/drivers/base/platform.cc
@@ -51,14 +51,31 @@ static int platform_match(device* dev, device_driver* drv)
if (pdrv->of_match_table == nullptr || pdev->of_node == nullptr) {
return 0;
}
- const char* node_compat = pdev->of_node->get_prop_string("compatible");
- if (node_compat == nullptr) {
+ const FdtProperty* compat_prop = pdev->of_node->get_prop("compatible");
+ if (compat_prop == nullptr || compat_prop->value == nullptr ||
+ compat_prop->len == 0) {
return 0;
}
+
+ const char* compat_list = static_cast<const char*>(compat_prop->value);
+ const uint32 compat_len = static_cast<uint32>(compat_prop->len);
for (const of_device_id* id = pdrv->of_match_table;
id->compatible != nullptr; ++id) {
- if (strcmp(id->compatible, node_compat) == 0) {
- return 1;
+ uint32 offset = 0;
+ while (offset < compat_len) {
+ const char* node_compat = compat_list + offset;
+ uint32 remaining = compat_len - offset;
+ uint32 length = 0;
+ while (length < remaining && node_compat[length] != '\0') {
+ ++length;
+ }
+ if (length == remaining) {
+ break; /* malformed property without a terminating NUL */
+ }
+ if (strcmp(id->compatible, node_compat) == 0) {
+ return 1;
+ }
+ offset += length + 1;
}
}
return 0;