| 280 | } |
| 281 | |
| 282 | static char *dt_find_compat(const char *parent, const char *compat, int *addr_cells_ptr, |
| 283 | int *size_cells_ptr) |
| 284 | { |
| 285 | char *ret = NULL; |
| 286 | struct dirent *entry; |
| 287 | DIR *dir; |
| 288 | |
| 289 | if (!(dir = opendir(parent))) { |
| 290 | perror(parent); |
| 291 | return NULL; |
| 292 | } |
| 293 | |
| 294 | /* Loop through all files in the directory (DT node). */ |
| 295 | while ((entry = readdir(dir))) { |
| 296 | /* We only care about compatible props or subnodes. */ |
| 297 | if (entry->d_name[0] == '.' || |
| 298 | !((entry->d_type & DT_DIR) || !strcmp(entry->d_name, "compatible"))) |
| 299 | continue; |
| 300 | |
| 301 | /* Assemble the file name (on the stack, for speed). */ |
| 302 | size_t plen = strlen(parent); |
| 303 | char *name = alloca(plen + strlen(entry->d_name) + 2); |
| 304 | |
| 305 | strcpy(name, parent); |
| 306 | name[plen] = '/'; |
| 307 | strcpy(name + plen + 1, entry->d_name); |
| 308 | |
| 309 | /* If it's a subnode, recurse. */ |
| 310 | if (entry->d_type & DT_DIR) { |
| 311 | ret = dt_find_compat(name, compat, addr_cells_ptr, size_cells_ptr); |
| 312 | |
| 313 | /* There is only one matching node to find, abort. */ |
| 314 | if (ret) { |
| 315 | /* Gather cells values on the way up. */ |
| 316 | dt_update_cells(parent, addr_cells_ptr, size_cells_ptr); |
| 317 | break; |
| 318 | } |
| 319 | continue; |
| 320 | } |
| 321 | |
| 322 | /* If it's a compatible string, see if it's the right one. */ |
| 323 | int fd = open(name, O_RDONLY); |
| 324 | int clen = strlen(compat); |
| 325 | char *buffer = alloca(clen + 1); |
| 326 | |
| 327 | if (fd < 0) { |
| 328 | perror(name); |
| 329 | continue; |
| 330 | } |
| 331 | |
| 332 | if (read(fd, buffer, clen + 1) < 0) { |
| 333 | perror(name); |
| 334 | close(fd); |
| 335 | continue; |
| 336 | } |
| 337 | close(fd); |
| 338 | |
| 339 | if (!strcmp(compat, buffer)) { |
no test coverage detected