struct boot_info *dt_from_fs(const char *dirname) { struct node *tree; tree = read_fstree(dirname); tree = name_node(tree, ""); return build_boot_info(NULL, tree, guess_boot_cpuid(tree)); }
static struct node *read_fstree(const char *dirname) { DIR *d; struct dirent *de; struct stat st; struct node *tree; d = opendir(dirname); if (!d) die("Couldn't opendir() \"%s\": %s\n", dirname, strerror(errno)); tree = build_node(NULL, NULL); while ((de = readdir(d)) != NULL) { char *tmpnam; if (streq(de->d_name, ".") || streq(de->d_name, "..")) continue; tmpnam = join_path(dirname, de->d_name); if (lstat(tmpnam, &st) < 0) die("stat(%s): %s\n", tmpnam, strerror(errno)); if (S_ISREG(st.st_mode)) { struct property *prop; FILE *pfile; pfile = fopen(tmpnam, "r"); if (! pfile) { fprintf(stderr, "WARNING: Cannot open %s: %s\n", tmpnam, strerror(errno)); } else { prop = build_property(xstrdup(de->d_name), data_copy_file(pfile, st.st_size)); add_property(tree, prop); fclose(pfile); } } else if (S_ISDIR(st.st_mode)) { struct node *newchild; newchild = read_fstree(tmpnam); newchild = name_node(newchild, xstrdup(de->d_name)); add_child(tree, newchild); } free(tmpnam); } closedir(d); return tree; }
/* load_device_tree_from_sysfs: extract the dt blob from host sysfs */ void *load_device_tree_from_sysfs(void) { void *host_fdt; int host_fdt_size; host_fdt = create_device_tree(&host_fdt_size); read_fstree(host_fdt, SYSFS_DT_BASEDIR); if (fdt_check_header(host_fdt)) { error_setg(&error_fatal, "%s host device tree extracted into memory is invalid", __func__); } return host_fdt; }
/** * read_fstree: this function is inspired from dtc read_fstree * @fdt: preallocated fdt blob buffer, to be populated * @dirname: directory to scan under SYSFS_DT_BASEDIR * the search is recursive and the tree is searched down to the * leaves (property files). * * the function asserts in case of error */ static void read_fstree(void *fdt, const char *dirname) { DIR *d; struct dirent *de; struct stat st; const char *root_dir = SYSFS_DT_BASEDIR; const char *parent_node; if (strstr(dirname, root_dir) != dirname) { error_setg(&error_fatal, "%s: %s must be searched within %s", __func__, dirname, root_dir); } parent_node = &dirname[strlen(SYSFS_DT_BASEDIR)]; d = opendir(dirname); if (!d) { error_setg(&error_fatal, "%s cannot open %s", __func__, dirname); } while ((de = readdir(d)) != NULL) { char *tmpnam; if (!g_strcmp0(de->d_name, ".") || !g_strcmp0(de->d_name, "..")) { continue; } tmpnam = g_strdup_printf("%s/%s", dirname, de->d_name); if (lstat(tmpnam, &st) < 0) { error_setg(&error_fatal, "%s cannot lstat %s", __func__, tmpnam); } if (S_ISREG(st.st_mode)) { gchar *val; gsize len; if (!g_file_get_contents(tmpnam, &val, &len, NULL)) { error_setg(&error_fatal, "%s not able to extract info from %s", __func__, tmpnam); } if (strlen(parent_node) > 0) { qemu_fdt_setprop(fdt, parent_node, de->d_name, val, len); } else { qemu_fdt_setprop(fdt, "/", de->d_name, val, len); } g_free(val); } else if (S_ISDIR(st.st_mode)) { char *node_name; node_name = g_strdup_printf("%s/%s", parent_node, de->d_name); qemu_fdt_add_subnode(fdt, node_name); g_free(node_name); read_fstree(fdt, tmpnam); } g_free(tmpnam); } closedir(d); }