From patchwork Fri Jun 30 16:23:00 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pantelis Antoniou X-Patchwork-Id: 782924 X-Patchwork-Delegate: sjg@chromium.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3wzhjN1W8fz9sNW for ; Sat, 1 Jul 2017 02:26:00 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=konsulko.com header.i=@konsulko.com header.b="puIBaOMZ"; dkim-atps=neutral Received: by lists.denx.de (Postfix, from userid 105) id EB0E3C21D6F; Fri, 30 Jun 2017 16:24:04 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 4B24BC21D75; Fri, 30 Jun 2017 16:23:27 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id A7533C21D85; Fri, 30 Jun 2017 16:23:18 +0000 (UTC) Received: from mail-wm0-f42.google.com (mail-wm0-f42.google.com [74.125.82.42]) by lists.denx.de (Postfix) with ESMTPS id 47BA1C21D60 for ; Fri, 30 Jun 2017 16:23:14 +0000 (UTC) Received: by mail-wm0-f42.google.com with SMTP id b184so51167825wme.1 for ; Fri, 30 Jun 2017 09:23:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=konsulko.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=WhpMT6druJCBgSwsG1uY6/3xAXqtYtLKEQH31dAGLMc=; b=puIBaOMZ1siB4d4SvvyAsF0PDUANr0+TznD+/0pvcat4LpJQHFXoSvnFsWSC8hNoCM yC/YofSFbaygM6sq++Q5KhrnjXJ2bXGvPJxcf6rzzNl80FhioZiNcvwkZ6k3QhByfqxy 5vosFtcxNwPfrIB2Hx9tRx1lcwRi95gd7/Fcg= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=WhpMT6druJCBgSwsG1uY6/3xAXqtYtLKEQH31dAGLMc=; b=Nm6h1GXql1I3F3P1hajkW8VigYncueYioPZ/x08QjRELIUF41SAH8bK2NSuYDvuaBQ cAX8x6aYeJnfvx/47XPPLVVCxBSyu/FRzyoR0ddq3/xugJGZlgdq55VYmSA03nFjq+kE 00PF4dxixyIR9ZuTHgZTRc+4odQXHQ+DpvcR/Y+jfhiZJ4bQXSOM+D3XFAPh+1IDFlOX ZQw0oGX828Ghp26FUm6jLshN/MHykjhsc/C9IlDGXNxzDsN6yjkzJEc0kz/B5tbOv5Fi dC056FHYPFh6QtYWu5au9xSKYRSbu1Yg1zqiY4nxpMnMdjxuMQC+56848nmIpAI/m9gg 07Aw== X-Gm-Message-State: AKS2vOwtlWlOmyyqMVUlbSrfocckh3Qs5gkJdE/w/fU8tB++0Dox8nut MaWixim9UMP/zI3S X-Received: by 10.28.51.11 with SMTP id z11mr6683183wmz.115.1498839793911; Fri, 30 Jun 2017 09:23:13 -0700 (PDT) Received: from localhost.localdomain ([195.97.110.117]) by smtp.gmail.com with ESMTPSA id a126sm4264955wmh.14.2017.06.30.09.23.12 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 30 Jun 2017 09:23:13 -0700 (PDT) From: Pantelis Antoniou To: Tom Rini Date: Fri, 30 Jun 2017 19:23:00 +0300 Message-Id: <1498839782-4702-4-git-send-email-pantelis.antoniou@konsulko.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1498839782-4702-1-git-send-email-pantelis.antoniou@konsulko.com> References: <1498839782-4702-1-git-send-email-pantelis.antoniou@konsulko.com> Cc: Marek Vasut , Pantelis Antoniou , Tero Kristo , u-boot@lists.denx.de, Maxime Ripard , Stefan Roese , Alan Ott Subject: [U-Boot] [PATCH 3/5] fdt: Allow stacked overlays phandle references X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" This patch enables an overlay to refer to a previous overlay's labels by performing a merge of symbol information at application time. In a nutshell it allows an overlay to refer to a symbol that a previous overlay has defined. It requires both the base and all the overlays to be compiled with the -@ command line switch so that symbol information is included. base.dts -------- /dts-v1/; / { foo: foonode { foo-property; }; }; $ dtc -@ -I dts -O dtb -o base.dtb base.dts bar.dts ------- /dts-v1/; /plugin/; / { fragment@1 { target = <&foo>; __overlay__ { overlay-1-property; bar: barnode { bar-property; }; }; }; }; $ dtc -@ -I dts -O dtb -o bar.dtb bar.dts baz.dts ------- /dts-v1/; /plugin/; / { fragment@1 { target = <&bar>; __overlay__ { overlay-2-property; baz: baznode { baz-property; }; }; }; }; $ dtc -@ -I dts -O dtb -o baz.dtb baz.dts Applying the overlays: $ fdtoverlay -i base.dtb -o target.dtb bar.dtb baz.dtb Dumping: $ fdtdump target.dtb / { foonode { overlay-1-property; foo-property; linux,phandle = <0x00000001>; phandle = <0x00000001>; barnode { overlay-2-property; phandle = <0x00000002>; linux,phandle = <0x00000002>; bar-property; baznode { phandle = <0x00000003>; linux,phandle = <0x00000003>; baz-property; }; }; }; __symbols__ { baz = "/foonode/barnode/baznode"; bar = "/foonode/barnode"; foo = "/foonode"; }; }; Signed-off-by: Pantelis Antoniou Reviewed-by: Simon Glass --- lib/libfdt/fdt_overlay.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 147 insertions(+), 1 deletion(-) diff --git a/lib/libfdt/fdt_overlay.c b/lib/libfdt/fdt_overlay.c index ceb9687..59fd7f3 100644 --- a/lib/libfdt/fdt_overlay.c +++ b/lib/libfdt/fdt_overlay.c @@ -590,7 +590,7 @@ static int overlay_apply_node(void *fdt, int target, * * overlay_merge() merges an overlay into its base device tree. * - * This is the final step in the device tree overlay application + * This is the next to last step in the device tree overlay application * process, when all the phandles have been adjusted and resolved and * you just have to merge overlay into the base device tree. * @@ -630,6 +630,148 @@ static int overlay_merge(void *fdt, void *fdto) return 0; } +/** + * overlay_symbol_update - Update the symbols of base tree after a merge + * @fdt: Base Device Tree blob + * @fdto: Device tree overlay blob + * + * overlay_symbol_update() updates the symbols of the base tree with the + * symbols of the applied overlay + * + * This is the last step in the device tree overlay application + * process, allowing the reference of overlay symbols by subsequent + * overlay operations. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_symbol_update(void *fdt, void *fdto) +{ + int root_sym, ov_sym, prop, path_len, fragment, target; + int len, frag_name_len, ret, rel_path_len; + const char *s; + const char *path; + const char *name; + const char *frag_name; + const char *rel_path; + char *buf = NULL; + + root_sym = fdt_subnode_offset(fdt, 0, "__symbols__"); + ov_sym = fdt_subnode_offset(fdto, 0, "__symbols__"); + + /* if neither exist we can't update symbols, but that's OK */ + if (root_sym < 0 || ov_sym < 0) + return 0; + + buf = malloc(FDT_PATH_MAX); + if (!buf) + return -FDT_ERR_NOSPACE; + + /* iterate over each overlay symbol */ + fdt_for_each_property_offset(prop, fdto, ov_sym) { + + path = fdt_getprop_by_offset(fdto, prop, &name, &path_len); + if (!path) { + ret = path_len; + goto out; + } + + /* skip autogenerated properties */ + if (!strcmp(name, "name")) + continue; + + /* format: //__overlay__/ */ + + if (*path != '/') { + ret = -FDT_ERR_BADVALUE; + goto out; + } + + /* get frag name first */ + s = strchr(path + 1, '/'); + if (!s) { + ret = -FDT_ERR_BADVALUE; + goto out; + } + frag_name = path + 1; + frag_name_len = s - path - 1; + + /* verify format */ + len = strlen("/__overlay__/"); + if (strncmp(s, "/__overlay__/", len)) { + ret = -FDT_ERR_NOTFOUND; + goto out; + } + + rel_path = s + len; + rel_path_len = strlen(rel_path); + + /* find the fragment index in which the symbol lies */ + fdt_for_each_subnode(fragment, fdto, 0) { + + s = fdt_get_name(fdto, fragment, &len); + if (!s) + continue; + + /* name must match */ + if (len == frag_name_len && !memcmp(s, frag_name, len)) + break; + } + + /* not found? */ + if (fragment < 0) { + ret = -FDT_ERR_NOTFOUND; + goto out; + } + + /* an __overlay__ subnode must exist */ + ret = fdt_subnode_offset(fdto, fragment, "__overlay__"); + if (ret < 0) + goto out; + + /* get the target of the fragment */ + ret = overlay_get_target(fdt, fdto, fragment); + if (ret < 0) + goto out; + target = ret; + + /* get the path of the target */ + ret = fdt_get_path(fdt, target, buf, FDT_PATH_MAX); + if (ret < 0) + goto out; + + len = strlen(buf); + + /* if the target is root strip leading / */ + if (len == 1 && buf[0] == '/') + len = 0; + + /* make sure we have enough space */ + if (len + 1 + rel_path_len + 1 > FDT_PATH_MAX) { + ret = -FDT_ERR_NOSPACE; + goto out; + } + + /* create new symbol path in place */ + buf[len] = '/'; + memcpy(buf + len + 1, rel_path, rel_path_len); + buf[len + 1 + rel_path_len] = '\0'; + + ret = fdt_setprop_string(fdt, root_sym, name, buf); + if (ret < 0) + goto out; + } + + ret = 0; + +out: + if (buf) + free(buf); + + return ret; +} + int fdt_overlay_apply(void *fdt, void *fdto) { uint32_t delta = fdt_get_max_phandle(fdt); @@ -654,6 +796,10 @@ int fdt_overlay_apply(void *fdt, void *fdto) if (ret) goto err; + ret = overlay_symbol_update(fdt, fdto); + if (ret) + goto err; + /* * The overlay has been damaged, erase its magic. */