From patchwork Thu Feb 20 18:06:48 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomasz Figa X-Patchwork-Id: 3689171 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 9DC2B9F2EC for ; Thu, 20 Feb 2014 18:15:24 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 8962F20145 for ; Thu, 20 Feb 2014 18:15:23 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 3FF5120131 for ; Thu, 20 Feb 2014 18:15:22 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1WGY7h-0001wc-Hq; Thu, 20 Feb 2014 18:13:26 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1WGY2n-00081o-Ex; Thu, 20 Feb 2014 18:08:21 +0000 Received: from mailout3.w1.samsung.com ([210.118.77.13]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1WGY28-0007xf-87 for linux-arm-kernel@lists.infradead.org; Thu, 20 Feb 2014 18:07:46 +0000 Received: from eucpsbgm1.samsung.com (unknown [203.254.199.244]) by mailout3.w1.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0N1B000QV3O01O80@mailout3.w1.samsung.com> for linux-arm-kernel@lists.infradead.org; Thu, 20 Feb 2014 18:07:12 +0000 (GMT) X-AuditID: cbfec7f4-b7f796d000005a13-d7-530644509296 Received: from eusync3.samsung.com ( [203.254.199.213]) by eucpsbgm1.samsung.com (EUCPMTA) with SMTP id E0.B6.23059.05446035; Thu, 20 Feb 2014 18:07:12 +0000 (GMT) Received: from AMDC1227.digital.local ([106.116.147.199]) by eusync3.samsung.com (Oracle Communications Messaging Server 7u4-23.01(7.0.4.23.0) 64bit (built Aug 10 2011)) with ESMTPA id <0N1B00D1E3NTAA00@eusync3.samsung.com>; Thu, 20 Feb 2014 18:07:12 +0000 (GMT) From: Tomasz Figa To: devicetree-compiler@vger.kernel.org Subject: [PATCH RFC 2/5] dtc: livetree: Add more tree parsing helpers Date: Thu, 20 Feb 2014 19:06:48 +0100 Message-id: <1392919611-10746-3-git-send-email-t.figa@samsung.com> X-Mailer: git-send-email 1.8.5.2 In-reply-to: <1392919611-10746-1-git-send-email-t.figa@samsung.com> References: <1392919611-10746-1-git-send-email-t.figa@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrDLMWRmVeSWpSXmKPExsVy+t/xq7oBLmzBBu9+cFncWneO1eLvpGPs Fnfm/2W12Hmoldniw8FtTBbzjwAl+t8sZLV4dWYjm8XrSQvZLL7fMLXY9Pgaq8XaI3fZLZZe v8hkcer6ZzaLCdPXsli8OtjGYrF+xmsWB0GPNfPWMHr8/jWJ0eP9jVZ2j8t9vUweExe8Z/P4 fPYgu8fmJfUeV040sXp839HL6NG3ZRWjx8+XOh6fN8l5bJwbGsAbxWWTkpqTWZZapG+XwJXR 9GIjS8FWh4qb7+YwNzBeMuhi5OSQEDCRmNiwkBXCFpO4cG89WxcjF4eQwFJGia9LlzNDOH1M Em829zGBVLEJqEl8bnjEBmKLCKhLPJh2ggmkiFngBLPEvRPvwRLCAq4Sn263MYPYLAKqEovf nGMHsXkFnCRmdt8GsjmA1ilIrL4uBBLmFHCWePtxLdh8IaCS3lPP2CYw8i5gZFjFKJpamlxQ nJSea6hXnJhbXJqXrpecn7uJERIDX3YwLj5mdYhRgINRiYe3QIItWIg1say4MvcQowQHs5II b5MNUIg3JbGyKrUoP76oNCe1+BAjEwenVAPjVIP4U5GL+dh5fk/6lC7wwvfKVIHTBh/EvQ99 NjSKiL+U81BQ6tfmuMcqHybFTqu+rLnaSldL5HTkqq3PFEKvzu04MVeEK+VRWAWfjwsjT7/+ k3u5cprnbvcrxh36rcEhZJrENcFk0SHTZcXLi+ZHneQ4mpBTZRfoHh++3uDKZaUoJrHX2fOV WIozEg21mIuKEwHarUSJXwIAAA== X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140220_130740_501886_FC33B708 X-CRM114-Status: GOOD ( 17.30 ) X-Spam-Score: -4.5 (----) Cc: mark.rutland@arm.com, devicetree@vger.kernel.org, jdl@jdl.com, Arnd Bergmann , pawel.moll@arm.com, Stephen Warren , Tomasz Figa , jgunthorpe@obsidianresearch.com, grant.likely@secretlab.ca, a.hajda@samsung.com, bcousson@baylibre.com, galak@codeaurora.org, olof@lixom.net, david@gibson.dropbear.id.au, linux-arm-kernel@lists.infradead.org, Marek Szyprowski X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00,KHOP_BIG_TO_CC, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch extends the set of parsing helpers available in dtc with string and phandle parsing. Signed-off-by: Tomasz Figa --- dtc.h | 28 ++++++++ livetree.c | 230 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 258 insertions(+) diff --git a/dtc.h b/dtc.h index e95bed7..9ce9d12 100644 --- a/dtc.h +++ b/dtc.h @@ -163,6 +163,13 @@ struct node { struct label *labels; }; +#define MAX_PHANDLE_ARGS 16 +struct of_phandle_args { + struct node *np; + int args_count; + uint32_t args[MAX_PHANDLE_ARGS]; +}; + #define for_each_label_withdel(l0, l) \ for ((l) = (l0); (l); (l) = (l)->next) @@ -184,6 +191,11 @@ struct node { for_each_child_withdel(n, c) \ if (!(c)->deleted) +#define for_each_propval_string(p, s) \ + for (s = propval_next_string(p, NULL); \ + s; \ + s = propval_next_string(p, s)) + void add_label(struct label **labels, char *label); void delete_labels(struct label **labels); @@ -208,6 +220,22 @@ void delete_node(struct node *node); const char *get_unitname(struct node *node); struct property *get_property(struct node *node, const char *propname); cell_t propval_cell(struct property *prop); +int propval_string_count(struct node *np, struct property *prop); +const char *propval_next_string(struct property *prop, const char *cur); +int propval_match_string(struct property *prop, const char *string); +struct node *propval_parse_phandle(struct node *root, + struct property *prop, int index); +int propval_parse_phandle_with_args(struct node *root, + struct property *prop, + const char *cells_name, int index, + struct of_phandle_args *out_args); +int propval_parse_phandle_with_fixed_args(struct node *root, + struct property *prop, int cell_count, + int index, + struct of_phandle_args *out_args); +int propval_count_phandle_with_args(struct node *root, + struct property *prop, + const char *cells_name); struct property *get_property_by_label(struct node *tree, const char *label, struct node **node); struct marker *get_marker_label(struct node *tree, const char *label, diff --git a/livetree.c b/livetree.c index b61465f..015ed06 100644 --- a/livetree.c +++ b/livetree.c @@ -377,6 +377,230 @@ cell_t propval_cell(struct property *prop) return fdt32_to_cpu(*((cell_t *)prop->val.val)); } +int propval_string_count(struct node *np, struct property *prop) +{ + int i = 0; + size_t l = 0, total = 0; + const char *p; + + if (!prop) + return -EINVAL; + if (!prop->val.val) + return -ENODATA; + if (strnlen(prop->val.val, prop->val.len) >= prop->val.len) + return -EILSEQ; + + p = prop->val.val; + + for (i = 0; total < prop->val.len; total += l, p += l, i++) + l = strlen(p) + 1; + + return i; +} + +const char *propval_next_string(struct property *prop, const char *cur) +{ + const char *curv = cur; + + if (!prop) + return NULL; + + if (!cur) + return prop->val.val; + + curv += strlen(cur) + 1; + if (curv >= prop->val.val + prop->val.len) + return NULL; + + return curv; +} + +int propval_match_string(struct property *prop, const char *string) +{ + size_t l; + int i; + const char *p, *end; + + if (!prop) + return -EINVAL; + if (!prop->val.val) + return -ENODATA; + + p = prop->val.val; + end = p + prop->val.len; + + for (i = 0; p < end; i++, p += l) { + l = strlen(p) + 1; + if (p + l > end) + return -EILSEQ; + if (strcmp(string, p) == 0) + return i; /* Found it; return index */ + } + return -ENODATA; +} + +static int parse_phandle_with_args(struct node *root, + struct property *prop, + const char *cells_name, + int cell_count, int index, + struct of_phandle_args *out_args) +{ + const cell_t *list, *list_end; + int rc = 0, size, cur_index = 0; + uint32_t count = 0; + struct node *node = NULL; + cell_t phandle; + + /* Retrieve the phandle list property */ + size = prop->val.len; + list = (const cell_t *)prop->val.val; + if (!list) + return -ENOENT; + list_end = list + size / sizeof(*list); + + /* Loop over the phandles until all the requested entry is found */ + while (list < list_end) { + rc = -EINVAL; + count = 0; + + /* + * If phandle is 0, then it is an empty entry with no + * arguments. Skip forward to the next entry. + */ + phandle = fdt32_to_cpu(*list++); + if (phandle) { + /* + * Find the provider node and parse the #*-cells + * property to determine the argument length. + * + * This is not needed if the cell count is hard-coded + * (i.e. cells_name not set, but cell_count is set), + * except when we're going to return the found node + * below. + */ + if (cells_name || cur_index == index) { + node = get_node_by_phandle(root, phandle); + if (!node) { + pr_err("could not find phandle %u\n", + phandle); + goto err; + } + } + + if (cells_name) { + struct property *cells_prop; + + cells_prop = get_property(node, cells_name); + if (!cells_prop) { + pr_err("could not get %s for %s\n", + cells_name, + node->fullpath); + goto err; + } + + count = propval_cell(cells_prop); + } else { + count = cell_count; + } + + /* + * Make sure that the arguments actually fit in the + * remaining property data length + */ + if (list + count > list_end) { + pr_err("arguments longer than property\n"); + goto err; + } + } + + /* + * All of the error cases above bail out of the loop, so at + * this point, the parsing is successful. If the requested + * index matches, then fill the out_args structure and return, + * or return -ENOENT for an empty entry. + */ + rc = -ENOENT; + if (cur_index == index) { + if (!phandle) + goto err; + + if (out_args) { + int i; + if (count > MAX_PHANDLE_ARGS) { + pr_warn("argument count higher than MAX_PHANDLE_ARGS\n"); + count = MAX_PHANDLE_ARGS; + } + out_args->np = node; + out_args->args_count = count; + for (i = 0; i < count; i++) + out_args->args[i] = fdt32_to_cpu(*list++); + } + + /* Found it! return success */ + return 0; + } + + node = NULL; + list += count; + cur_index++; + } + + /* + * Unlock node before returning result; will be one of: + * -ENOENT : index is for empty phandle + * -EINVAL : parsing error on data + * [1..n] : Number of phandle (count mode; when index = -1) + */ + rc = index < 0 ? cur_index : -ENOENT; + err: + return rc; +} + +struct node *propval_parse_phandle(struct node *root, + struct property *prop, int index) +{ + struct of_phandle_args args; + + if (index < 0) + return NULL; + + if (parse_phandle_with_args(root, prop, NULL, 0, + index, &args)) + return NULL; + + return args.np; +} + +int propval_parse_phandle_with_args(struct node *root, + struct property *prop, + const char *cells_name, int index, + struct of_phandle_args *out_args) +{ + if (index < 0) + return -EINVAL; + return parse_phandle_with_args(root, prop, cells_name, 0, + index, out_args); +} + +int propval_parse_phandle_with_fixed_args(struct node *root, + struct property *prop, int cell_count, + int index, + struct of_phandle_args *out_args) +{ + if (index < 0) + return -EINVAL; + return parse_phandle_with_args(root, prop, NULL, cell_count, + index, out_args); +} + +int propval_count_phandle_with_args(struct node *root, + struct property *prop, + const char *cells_name) +{ + return parse_phandle_with_args(root, prop, cells_name, 0, -1, + NULL); +} + struct property *get_property_by_label(struct node *tree, const char *label, struct node **node) { @@ -456,6 +680,12 @@ struct node *get_node_by_path(struct node *tree, const char *path) while (path[0] == '/') path++; + if (!(*path)) { + if (tree->deleted) + return NULL; + return tree; + } + p = strchr(path, '/'); for_each_child(tree, child) {