mirror of https://github.com/xemu-project/xemu.git
device_tree: introduce load_device_tree_from_sysfs
This function returns the host device tree blob from sysfs (/proc/device-tree). It uses a recursive function inspired from dtc read_fstree. Signed-off-by: Eric Auger <eric.auger@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
This commit is contained in:
parent
62d9551247
commit
60e43e987c
100
device_tree.c
100
device_tree.c
|
@ -13,6 +13,10 @@
|
|||
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#ifdef CONFIG_LINUX
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "sysemu/device_tree.h"
|
||||
|
@ -112,6 +116,102 @@ fail:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LINUX
|
||||
|
||||
#define SYSFS_DT_BASEDIR "/proc/device-tree"
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_LINUX */
|
||||
|
||||
static int findnode_nofail(void *fdt, const char *node_path)
|
||||
{
|
||||
int offset;
|
||||
|
|
|
@ -16,6 +16,14 @@
|
|||
|
||||
void *create_device_tree(int *sizep);
|
||||
void *load_device_tree(const char *filename_path, int *sizep);
|
||||
#ifdef CONFIG_LINUX
|
||||
/**
|
||||
* load_device_tree_from_sysfs: reads the device tree information in the
|
||||
* /proc/device-tree directory and return the corresponding binary blob
|
||||
* buffer pointer. Asserts in case of error.
|
||||
*/
|
||||
void *load_device_tree_from_sysfs(void);
|
||||
#endif
|
||||
|
||||
int qemu_fdt_setprop(void *fdt, const char *node_path,
|
||||
const char *property, const void *val, int size);
|
||||
|
|
Loading…
Reference in New Issue