From patchwork Fri Jul 6 16:27:29 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 940615 X-Patchwork-Delegate: sjg@chromium.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=chromium.org Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 41MgTF5G77z9s4Z for ; Sat, 7 Jul 2018 02:40:49 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 4C979C2205C; Fri, 6 Jul 2018 16:36:24 +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=none 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 69E4EC220AA; Fri, 6 Jul 2018 16:29:26 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 174C1C220AC; Fri, 6 Jul 2018 16:28:41 +0000 (UTC) Received: from mail-it0-f73.google.com (mail-it0-f73.google.com [209.85.214.73]) by lists.denx.de (Postfix) with ESMTPS id 17E4BC2204D for ; Fri, 6 Jul 2018 16:28:36 +0000 (UTC) Received: by mail-it0-f73.google.com with SMTP id z8-v6so9907452itc.9 for ; Fri, 06 Jul 2018 09:28:36 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:date:in-reply-to:message-id :references:subject:from:to:cc; bh=Eb5mbqa8t2vGjx+2QnWcyuQwD26C82MJrIJnSGUBA1s=; b=ny5LN2KmPmos4FjS4+fuzC+2wbdOn5asorhUeTFhdATmySvEbdi6m5L8WkT86EBKkn 0bHpUMshBh5PXGoI4qZFR3QZDNepfsK3wzjj+qjyYvLEZLNpzO0/Ca6mdpsT5TwgK7Oa rULpV57TEHE9/wM87di6UUK0nH6tO0yY4tshMSQKIzREoNaxICcKexBR+Skv7P/PDer0 XTF3GI//H47w5ZJQ7FvLMrzi96mNQckMh5W/1wnr6qnvA/L3dc3Q80MGsKv7vxzIR2gL O2XL9/GMDoSIxdPehbqFwgvqDMaYWj6ISDOsO0YYTRpeFmKUmGP169sa7/ZCyBXuRvOi epUQ== X-Gm-Message-State: APt69E3OIWZ00jO5NqEhsaQ5/B2WG+i+sUI42J9VIe1gQ99yoBKzZtXG b+EaDkWIXF2GXSfJKlwiUOQm+o4= X-Google-Smtp-Source: AAOMgpeNtCDHHJGdkUFC0Hg6y6WMYg49uE+7kgqfwTlva6rmOzm4JTVFP08AGKj9eB95gFqaQkdfhO8= MIME-Version: 1.0 X-Received: by 2002:a5e:9413:: with SMTP id q19-v6mr4657761ioj.106.1530894515153; Fri, 06 Jul 2018 09:28:35 -0700 (PDT) Date: Fri, 6 Jul 2018 10:27:29 -0600 In-Reply-To: <20180706162742.186950-1-sjg@chromium.org> Message-Id: <20180706162742.186950-17-sjg@chromium.org> References: <20180706162742.186950-1-sjg@chromium.org> X-Mailer: git-send-email 2.18.0.203.gfac676dfb9-goog From: Simon Glass To: U-Boot Mailing List Cc: Tom Rini Subject: [U-Boot] [PATCH v2 16/29] dtoc: Keep track of property offsets 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: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" At present the Fdt class does not keep track of property offsets if they change due to removal of properties. Update the code to handle this, and add a test. Signed-off-by: Simon Glass --- Changes in v2: None tools/dtoc/fdt.py | 20 +++++++++++++ tools/dtoc/test_fdt.py | 65 +++++++++++++++++++++++++++++++++++++----- 2 files changed, 78 insertions(+), 7 deletions(-) diff --git a/tools/dtoc/fdt.py b/tools/dtoc/fdt.py index fd016bb8ce..274c142e7a 100644 --- a/tools/dtoc/fdt.py +++ b/tools/dtoc/fdt.py @@ -49,6 +49,9 @@ class Prop: return self.type, self.value = self.BytesToValue(bytes) + def RefreshOffset(self, poffset): + self._offset = poffset + def Widen(self, newprop): """Figure out which property type is more general @@ -154,6 +157,7 @@ class Prop: Returns: The offset of the property (struct fdt_property) within the file """ + self._node._fdt.CheckCache() return self._node._fdt.GetStructOffset(self._offset) class Node: @@ -233,8 +237,23 @@ class Node: self._offset = my_offset offset = fdt_obj.first_subnode(self._offset, QUIET_NOTFOUND) for subnode in self.subnodes: + if subnode.name != fdt_obj.get_name(offset): + raise ValueError('Internal error, node name mismatch %s != %s' % + (subnode.name, fdt_obj.get_name(offset))) subnode.Refresh(offset) offset = fdt_obj.next_subnode(offset, QUIET_NOTFOUND) + if offset != -libfdt.FDT_ERR_NOTFOUND: + raise ValueError('Internal error, offset == %d' % offset) + + poffset = fdt_obj.first_property_offset(self._offset, QUIET_NOTFOUND) + while poffset >= 0: + p = fdt_obj.get_property_by_offset(poffset) + prop = self.props.get(p.name) + if not prop: + raise ValueError("Internal error, property '%s' missing, " + 'offset %d' % (p.name, poffset)) + prop.RefreshOffset(poffset) + poffset = fdt_obj.next_property_offset(poffset, QUIET_NOTFOUND) def DeleteProp(self, prop_name): """Delete a property of a node @@ -278,6 +297,7 @@ class Fdt: TODO(sjg@chromium.org): Implement the 'root' parameter """ + self._cached_offsets = True self._root = self.Node(self, None, 0, '/', '/') self._root.Scan() diff --git a/tools/dtoc/test_fdt.py b/tools/dtoc/test_fdt.py index d44e4dd842..e57298dbe7 100755 --- a/tools/dtoc/test_fdt.py +++ b/tools/dtoc/test_fdt.py @@ -24,6 +24,30 @@ import libfdt import test_util import tools +def _GetPropertyValue(dtb, node, prop_name): + """Low-level function to get the property value based on its offset + + This looks directly in the device tree at the property's offset to find + its value. It is useful as a check that the property is in the correct + place. + + Args: + node: Node to look in + prop_name: Property name to find + + Returns: + Tuple: + Prop object found + Value of property as a string (found using property offset) + """ + prop = node.props[prop_name] + + # Add 12, which is sizeof(struct fdt_property), to get to start of data + offset = prop.GetOffset() + 12 + data = dtb.GetContents()[offset:offset + len(prop.value)] + return prop, [chr(x) for x in data] + + class TestFdt(unittest.TestCase): """Tests for the Fdt module @@ -124,6 +148,12 @@ class TestNode(unittest.TestCase): with self.assertRaises(libfdt.FdtException): self.node.DeleteProp('missing') + def testDeleteGetOffset(self): + """Test that property offset update when properties are deleted""" + self.node.DeleteProp('intval') + prop, value = _GetPropertyValue(self.dtb, self.node, 'longbytearray') + self.assertEqual(prop.value, value) + def testFindNode(self): """Tests that we can find a node using the _FindNode() functoin""" node = self.dtb.GetRoot()._FindNode('i2c@0') @@ -132,6 +162,32 @@ class TestNode(unittest.TestCase): self.assertEqual('pmic@9', subnode.name) self.assertEqual(None, node._FindNode('missing')) + def testRefreshMissingNode(self): + """Test refreshing offsets when an extra node is present in dtb""" + # Delete it from our tables, not the device tree + del self.dtb._root.subnodes[-1] + with self.assertRaises(ValueError) as e: + self.dtb.Refresh() + self.assertIn('Internal error, offset', str(e.exception)) + + def testRefreshExtraNode(self): + """Test refreshing offsets when an expected node is missing""" + # Delete it from the device tre, not our tables + self.dtb.GetFdtObj().del_node(self.node.Offset()) + with self.assertRaises(ValueError) as e: + self.dtb.Refresh() + self.assertIn('Internal error, node name mismatch ' + 'spl-test != spl-test2', str(e.exception)) + + def testRefreshMissingProp(self): + """Test refreshing offsets when an extra property is present in dtb""" + # Delete it from our tables, not the device tree + del self.node.props['notstring'] + with self.assertRaises(ValueError) as e: + self.dtb.Refresh() + self.assertIn("Internal error, property 'notstring' missing, offset ", + str(e.exception)) + class TestProp(unittest.TestCase): """Test operation of the Prop class""" @@ -210,13 +266,8 @@ class TestProp(unittest.TestCase): def testGetOffset(self): """Test we can get the offset of a property""" - prop = self.node.props['longbytearray'] - - # Add 12, which is sizeof(struct fdt_property), to get to start of data - offset = prop.GetOffset() + 12 - data = self.dtb.GetContents()[offset:offset + len(prop.value)] - bytes = [chr(x) for x in data] - self.assertEqual(bytes, prop.value) + prop, value = _GetPropertyValue(self.dtb, self.node, 'longbytearray') + self.assertEqual(prop.value, value) def testWiden(self): """Test widening of values"""