From patchwork Thu Jun 13 22:10:08 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 251185 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 809C62C00A3 for ; Fri, 14 Jun 2013 08:14:11 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 4CB314A13F; Fri, 14 Jun 2013 00:13:41 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 4Se+2e6TNZ5e; Fri, 14 Jun 2013 00:13:40 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id E28024A140; Fri, 14 Jun 2013 00:11:44 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id B81994A16E for ; Fri, 14 Jun 2013 00:11:36 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id pYClKdYv8xhn for ; Fri, 14 Jun 2013 00:11:21 +0200 (CEST) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mail-qe0-f74.google.com (mail-qe0-f74.google.com [209.85.128.74]) by theia.denx.de (Postfix) with ESMTPS id 038454A133 for ; Fri, 14 Jun 2013 00:10:35 +0200 (CEST) Received: by mail-qe0-f74.google.com with SMTP id a11so609814qen.1 for ; Thu, 13 Jun 2013 15:10:34 -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 :x-gm-message-state; bh=lsKA54hVWcAnv2AiOv4p03DrlGS/ZCQZPNZyitNZdIU=; b=h2xFbnZUYaaztYenkfsc+SYCuSKUhlfekuF9+QtwBrq7XVaqFcI6qjlJUauLShk3fw 5CQ58Qdie/5xY1WWdbsEwB2foBvS3TuiAPDUV+h8dLk+ro6hZw2bKD1B+KmRb7H3aGiW mXbbqxnivtnnVd0NQvjECN4iYeOsllBf1TRtDPtqRTU1/PmSVTMxrcq2Ulj02Xa6IVJ0 oJ6nO3GL5giDiv2O+CsMeMqEoRjTZ5NK6eRtdGR7Azp+yl3pTgZUpuve8Sk0EcWywaV+ CT32bRmg9qCm/aFd05Ykv1nDwwUbQxx3l7Y8CCM+PzlP7OGiOGitXfA9ki0E0fj/xT3J cHEA== X-Received: by 10.236.21.198 with SMTP id r46mr1230437yhr.12.1371161434338; Thu, 13 Jun 2013 15:10:34 -0700 (PDT) Received: from corp2gmr1-1.hot.corp.google.com (corp2gmr1-1.hot.corp.google.com [172.24.189.92]) by gmr-mx.google.com with ESMTPS id y4si1464368yhi.3.2013.06.13.15.10.34 for (version=TLSv1.1 cipher=AES128-SHA bits=128/128); Thu, 13 Jun 2013 15:10:34 -0700 (PDT) Received: from kaka.mtv.corp.google.com (kaka.mtv.corp.google.com [172.22.83.1]) by corp2gmr1-1.hot.corp.google.com (Postfix) with ESMTP id 20DAA31C1CE; Thu, 13 Jun 2013 15:10:34 -0700 (PDT) Received: by kaka.mtv.corp.google.com (Postfix, from userid 121222) id F3E5D160954; Thu, 13 Jun 2013 15:10:33 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Date: Thu, 13 Jun 2013 15:10:08 -0700 Message-Id: <1371161411-2834-10-git-send-email-sjg@chromium.org> X-Mailer: git-send-email 1.8.3 In-Reply-To: <1371161411-2834-1-git-send-email-sjg@chromium.org> References: <1371161411-2834-1-git-send-email-sjg@chromium.org> X-Gm-Message-State: ALoCoQkkQaJLHqW7NYfdzjXikK4ysdmyGsKqlsbtmaEb6SBXqQMvuY5MoyTKp8OYunECwQti+4bARiXZW4D2BWpZWl8yIGfcHYhl+Tm1cmPOqm+DI5bRjHdIhWvevgb/XweYVat7v4ZFHHdoF1mkCGBMuVNbAxDvOjowp8V1LAW69BMqrE1OrPJMSkAeM/FrAP+sd4ae/U9k Cc: Joel A Fernandes , Will Drewry , Devicetree Discuss , u-boot-review@google.com, Bill Richardson , Randall Spangler , Tom Rini , Vadim Bendebury , =?UTF-8?q?Andreas=20B=C3=A4ck?= , Kees Cook Subject: [U-Boot] [PATCH v3 09/12] libfdt: Add fdt_find_regions() X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de Add a function to find regions in device tree given a list of nodes to include and properties to exclude. See the header file for full documentation. Signed-off-by: Simon Glass --- Changes in v3: None Changes in v2: - Fix checkpatch checks about parenthesis alignment include/libfdt.h | 64 +++++++++++++++++++++++++ lib/libfdt/fdt_wip.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 193 insertions(+) diff --git a/include/libfdt.h b/include/libfdt.h index c5ec2ac..765d84f 100644 --- a/include/libfdt.h +++ b/include/libfdt.h @@ -1511,4 +1511,68 @@ int fdt_del_node(void *fdt, int nodeoffset); const char *fdt_strerror(int errval); +struct fdt_region { + int offset; + int size; +}; + +/** + * fdt_find_regions() - find regions in device tree + * + * Given a list of nodes to include and properties to exclude, find + * the regions of the device tree which describe those included parts. + * + * The intent is to get a list of regions which will be invariant provided + * those parts are invariant. For example, if you request a list of regions + * for all nodes but exclude the property "data", then you will get the + * same region contents regardless of any change to "data" properties. + * + * This function can be used to produce a byte-stream to send to a hashing + * function to verify that critical parts of the FDT have not changed. + * + * Nodes which are given in 'inc' are included in the region list, as + * are the names of the immediate subnodes nodes (but not the properties + * or subnodes of those subnodes). + * + * For eaxample "/" means to include the root node, all root properties + * and the FDT_BEGIN_NODE and FDT_END_NODE of all subnodes of /. The latter + * ensures that we capture the names of the subnodes. In a hashing situation + * it prevents the root node from changing at all Any change to non-excluded + * properties, names of subnodes or number of subnodes would be detected. + * + * When used with FITs this provides the ability to hash and sign parts of + * the FIT based on different configurations in the FIT. Then it is + * impossible to change anything about that configuration (include images + * attached to the configuration), but it may be possible to add new + * configurations, new images or new signatures within the existing + * framework. + * + * Adding new properties to a device tree may result in the string table + * being extended (if the new property names are different from those + * already added). This function can optionally include a region for + * the string table so that this can be part of the hash too. + * + * The device tree header is not included in the list. + * + * @fdt: Device tree to check + * @inc: List of node paths to included + * @inc_count: Number of node paths in list + * @exc_prop: List of properties names to exclude + * @exc_prop_count: Number of properties in exclude list + * @region: Returns list of regions + * @max_region: Maximum length of region list + * @path: Pointer to a temporary string for the function to use for + * building path names + * @path_len: Length of path, must be large enough to hold the longest + * path in the tree + * @add_string_tab: 1 to add a region for the string table + * @return number of regions in list. If this is >max_regions then the + * region array was exhausted. You should increase max_regions and try + * the call again. + */ +int fdt_find_regions(const void *fdt, char * const inc[], int inc_count, + char * const exc_prop[], int exc_prop_count, + struct fdt_region region[], int max_regions, + char *path, int path_len, int add_string_tab); + #endif /* _LIBFDT_H */ diff --git a/lib/libfdt/fdt_wip.c b/lib/libfdt/fdt_wip.c index 63e67b7..b9e3c4a 100644 --- a/lib/libfdt/fdt_wip.c +++ b/lib/libfdt/fdt_wip.c @@ -120,3 +120,132 @@ int fdt_nop_node(void *fdt, int nodeoffset) endoffset - nodeoffset); return 0; } + +#define FDT_MAX_DEPTH 32 + +static int str_in_list(const char *str, char * const list[], int count) +{ + int i; + + for (i = 0; i < count; i++) + if (!strcmp(list[i], str)) + return 1; + + return 0; +} + +int fdt_find_regions(const void *fdt, char * const inc[], int inc_count, + char * const exc_prop[], int exc_prop_count, + struct fdt_region region[], int max_regions, + char *path, int path_len, int add_string_tab) +{ + int stack[FDT_MAX_DEPTH]; + char *end; + int nextoffset = 0; + uint32_t tag; + int count = 0; + int start = -1; + int depth = -1; + int want = 0; + int base = fdt_off_dt_struct(fdt); + + end = path; + *end = '\0'; + do { + const struct fdt_property *prop; + const char *name; + const char *str; + int include = 0; + int stop_at = 0; + int offset; + int len; + + offset = nextoffset; + tag = fdt_next_tag(fdt, offset, &nextoffset); + stop_at = nextoffset; + + switch (tag) { + case FDT_PROP: + include = want >= 2; + stop_at = offset; + prop = fdt_get_property_by_offset(fdt, offset, NULL); + str = fdt_string(fdt, fdt32_to_cpu(prop->nameoff)); + if (str_in_list(str, exc_prop, exc_prop_count)) + include = 0; + break; + + case FDT_NOP: + include = want >= 2; + stop_at = offset; + break; + + case FDT_BEGIN_NODE: + depth++; + if (depth == FDT_MAX_DEPTH) + return -FDT_ERR_BADSTRUCTURE; + name = fdt_get_name(fdt, offset, &len); + if (end - path + 2 + len >= path_len) + return -FDT_ERR_NOSPACE; + if (end != path + 1) + *end++ = '/'; + strcpy(end, name); + end += len; + stack[depth] = want; + if (want == 1) + stop_at = offset; + if (str_in_list(path, inc, inc_count)) + want = 2; + else if (want) + want--; + else + stop_at = offset; + include = want; + break; + + case FDT_END_NODE: + include = want; + want = stack[depth--]; + while (end > path && *--end != '/') + ; + *end = '\0'; + break; + + case FDT_END: + include = 1; + break; + } + + if (include && start == -1) { + /* Should we merge with previous? */ + if (count && count <= max_regions && + offset == region[count - 1].offset + + region[count - 1].size - base) + start = region[--count].offset - base; + else + start = offset; + } + + if (!include && start != -1) { + if (count < max_regions) { + region[count].offset = base + start; + region[count].size = stop_at - start; + } + count++; + start = -1; + } + } while (tag != FDT_END); + + if (nextoffset != fdt_size_dt_struct(fdt)) + return -FDT_ERR_BADLAYOUT; + + /* Add a region for the END tag and the string table */ + if (count < max_regions) { + region[count].offset = base + start; + region[count].size = nextoffset - start; + if (add_string_tab) + region[count].size += fdt_size_dt_strings(fdt); + } + count++; + + return count; +}