From patchwork Mon Sep 17 09:02:58 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Peter A. G. Crosthwaite" X-Patchwork-Id: 184353 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id ACA102C0085 for ; Mon, 17 Sep 2012 19:24:22 +1000 (EST) Received: from localhost ([::1]:46436 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TDXYy-0003MV-P9 for incoming@patchwork.ozlabs.org; Mon, 17 Sep 2012 05:24:20 -0400 Received: from eggs.gnu.org ([208.118.235.92]:35711) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TDXFV-0003PG-B8 for qemu-devel@nongnu.org; Mon, 17 Sep 2012 05:04:19 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TDXFQ-0001dA-3J for qemu-devel@nongnu.org; Mon, 17 Sep 2012 05:04:13 -0400 Received: from mail-ie0-f173.google.com ([209.85.223.173]:39068) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TDXFP-0001XC-Tw for qemu-devel@nongnu.org; Mon, 17 Sep 2012 05:04:08 -0400 Received: by mail-ie0-f173.google.com with SMTP id c10so8784577ieb.4 for ; Mon, 17 Sep 2012 02:04:07 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references :in-reply-to:references:x-gm-message-state; bh=Vzlk0vNtvCR8+mjEDbhkRi5yn4B45GlO9ai9a24zGl4=; b=OoL8Syj2J/ycGVD9y50dHSQDhsbw32O5x53+EPS+r0upGU/BwUj0bzC6881WcoRDNP 41WekZF4D1u2FV9nnlFCtG/xJjVeeJVT9wqSmPs1B+q5fkf+FFmAxw9golzVJyma3x0z Mal27AYdaWNwoRJyYkL0ufD8z6CzKg01B1nwIK9oSpKWuEqC2acdTvDl6RndfOYHmA/X 7Vz+ReN1uE0/rYv5YoCwxfT2Fm5hJ7jyHfi7X77qwsGPFAgx1nzV6PyH9wA9hfIh7hu/ 8TPChdQka3DDoSkFNAUaAsyfxPwBngkNs1JwbiV58m21YFb57KdU4/iZtGGv0G5v8YO1 Ta5w== Received: by 10.50.184.196 with SMTP id ew4mr6065952igc.5.1347872647672; Mon, 17 Sep 2012 02:04:07 -0700 (PDT) Received: from localhost ([124.148.20.9]) by mx.google.com with ESMTPS id y9sm16571919igm.10.2012.09.17.02.04.04 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 17 Sep 2012 02:04:07 -0700 (PDT) From: "Peter A. G. Crosthwaite" To: qemu-devel@nongnu.org, edgar.iglesias@gmail.com Date: Mon, 17 Sep 2012 19:02:58 +1000 Message-Id: <7764a2561683b38963f49807965ececd5c1eee43.1347871922.git.peter.crosthwaite@petalogix.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: References: In-Reply-To: References: X-Gm-Message-State: ALoCoQkM+4FW7hbzV3xWlkY4t0TrqmQw9gIprDuFe+GBGn8YS+o16++002EBUQPhGi6YWVvEuuAc X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.85.223.173 Cc: peter.crosthwaite@petalogix.com, crwulff@gmail.com Subject: [Qemu-devel] [RFC v0 06/10] device_tree: Extended interface for fdt_generic X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Extended the wrapper interface (around libfdt) for device tree. Node Property getters have been added (qemu_devtree_getprop*) as well as helpers to search/ navigate the nodes of a FDT blob. Signed-off-by: Peter A. G. Crosthwaite --- device_tree.c | 158 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ device_tree.h | 27 ++++++++++ 2 files changed, 185 insertions(+), 0 deletions(-) diff --git a/device_tree.c b/device_tree.c index 3e22286..2c5c9ef 100644 --- a/device_tree.c +++ b/device_tree.c @@ -323,3 +323,161 @@ int qemu_devtree_add_subnode(void *fdt, const char *name) g_free(dupname); return retval; } + +char *qemu_devtree_get_node_name(void *fdt, const char *node_path) +{ + const char *ret = fdt_get_name(fdt, fdt_path_offset(fdt, node_path), NULL); + return ret ? strdup(ret) : NULL; +} + +int qemu_devtree_get_node_depth(void *fdt, const char *node_path) +{ + return fdt_node_depth(fdt, fdt_path_offset(fdt, node_path)); +} + +static void qemu_devtree_children_info(void *fdt, const char *node_path, + int depth, int *num, char **returned_paths) { + int offset = fdt_path_offset(fdt, node_path); + int root_depth = fdt_node_depth(fdt, offset); + int cur_depth = root_depth; + + *num = 0; + for (;;) { + offset = fdt_next_node(fdt, offset, &cur_depth); + if (cur_depth <= root_depth) { + break; + } + if (cur_depth <= root_depth + depth || depth == 0) { + if (returned_paths) { + returned_paths[*num] = g_malloc0(DT_PATH_LENGTH); + fdt_get_path(fdt, offset, returned_paths[*num], DT_PATH_LENGTH); + } + (*num)++; + } + } +} + +char **qemu_devtree_get_children(void *fdt, const char *node_path, int depth) +{ + int num_children = qemu_devtree_get_num_children(fdt, node_path, depth); + char **ret = g_malloc0(sizeof(*ret) * num_children); + + qemu_devtree_children_info(fdt, node_path, depth, &num_children, ret); + return ret; +} + +int qemu_devtree_get_num_children(void *fdt, const char *node_path, int depth) +{ + int ret; + + qemu_devtree_children_info(fdt, node_path, depth, &ret, NULL); + return ret; +} + +int qemu_devtree_node_by_compatible(void *fdt, char *node_path, + const char *compats) +{ + int offset = fdt_node_offset_by_compatible(fdt, 0, compats); + return offset > 0 ? + fdt_get_path(fdt, offset, node_path, DT_PATH_LENGTH) : 1; +} + +int qemu_devtree_get_node_by_name(void *fdt, char *node_path, + const char *cmpname) { + int offset = 0; + char *name = NULL; + + do { + offset = fdt_next_node(fdt, offset, NULL); + name = (void *)fdt_get_name(fdt, offset, NULL); + if (!name) { + continue; + } + if (!strncmp(name, cmpname, strlen(cmpname))) { + break; + } + } while (offset > 0); + return offset > 0 ? + fdt_get_path(fdt, offset, node_path, DT_PATH_LENGTH) : 1; +} + +int qemu_devtree_get_node_by_phandle(void *fdt, char *node_path, int phandle) +{ + return fdt_get_path(fdt, fdt_node_offset_by_phandle(fdt, phandle), + node_path, DT_PATH_LENGTH); +} + +int qemu_devtree_getparent(void *fdt, char *node_path, const char *current) +{ + int offset = fdt_path_offset(fdt, current); + int parent_offset = fdt_supernode_atdepth_offset(fdt, offset, + fdt_node_depth(fdt, offset) - 1, NULL); + + return parent_offset > 0 ? + fdt_get_path(fdt, parent_offset, node_path, DT_PATH_LENGTH) : 1; +} + +int qemu_devtree_get_root_node(void *fdt, char *node_path) +{ + return fdt_get_path(fdt, 0, node_path, DT_PATH_LENGTH); +} + +static void devtree_scan(void *fdt, int *num_nodes, int info_dump) +{ + int depth = 0, offset = 0; + + if (num_nodes) { + *num_nodes = 0; + } + for (;;) { + offset = fdt_next_node(fdt, offset, &depth); + if (num_nodes) { + (*num_nodes)++; + } + if (offset <= 0 || depth <= 0) { + break; + } + + if (info_dump) { + char node_path[DT_PATH_LENGTH]; + char *all_compats = NULL; + int compat_len; + Error *errp = NULL; + + if (fdt_get_path(fdt, offset, node_path, DT_PATH_LENGTH)) { + sprintf(node_path, "(none)"); + } else { + all_compats = qemu_devtree_getprop(fdt, node_path, "compatible", + &compat_len, false, &errp); + } + if (!errp) { + char *i = all_compats; + for (;;) { + char *j = rawmemchr(i, '\0'); + compat_len -= ((j+1)-i); + if (!compat_len) { + break; + } + *j = ' '; + i = j+1; + } + } + printf("OFFSET: %d, DEPTH: %d, PATH: %s, COMPATS: %s\n", + offset, depth, node_path, + all_compats ? all_compats : "(none)"); + } + } +} + +void devtree_info_dump(void *fdt) +{ + devtree_scan(fdt, NULL, 1); +} + +int devtree_get_num_nodes(void *fdt) +{ + int ret; + + devtree_scan(fdt, &ret, 0); + return ret; +} diff --git a/device_tree.h b/device_tree.h index 2bc188a..e741c2a 100644 --- a/device_tree.h +++ b/device_tree.h @@ -20,6 +20,8 @@ void *create_device_tree(int *sizep); void *load_device_tree(const char *filename_path, int *sizep); +/* property setters */ + int qemu_devtree_setprop(void *fdt, const char *node_path, const char *property, const void *val_array, int size); int qemu_devtree_setprop_cell(void *fdt, const char *node_path, @@ -54,4 +56,29 @@ int qemu_devtree_add_subnode(void *fdt, const char *name); sizeof(qdt_tmp)); \ } while (0) +/* node queries */ + +char *qemu_devtree_get_node_name(void *fdt, const char *node_path); +int qemu_devtree_get_node_depth(void *fdt, const char *node_path); +int qemu_devtree_get_num_children(void *fdt, const char *node_path, int depth); +char **qemu_devtree_get_children(void *fdt, const char *node_path, int depth); + +/* node getters */ + +int qemu_devtree_node_by_compatible(void *fdt, char *node_path, + const char *compats); +int qemu_devtree_get_node_by_name(void *fdt, char *node_path, + const char *cmpname); +int qemu_devtree_get_node_by_phandle(void *fdt, char *node_path, int phandle); +int qemu_devtree_getparent(void *fdt, char *node_path, + const char *current); +int qemu_devtree_get_root_node(void *fdt, char *node_path); + +/* misc */ + +int devtree_get_num_nodes(void *fdt); +void devtree_info_dump(void *fdt); + +#define DT_PATH_LENGTH 1024 + #endif /* __DEVICE_TREE_H__ */