[PATCH 1/5] fdt: Use an Enum for the data type

Simon Glass sjg at chromium.org
Mon Nov 9 04:36:17 CET 2020


Use an Enum instead of the current ad-hoc constants, so that there is a
data type associated with each 'type' value.

Signed-off-by: Simon Glass <sjg at chromium.org>
---

 tools/binman/fdt_test.py   | 14 +++++-----
 tools/dtoc/dtb_platdata.py | 26 +++++++++---------
 tools/dtoc/fdt.py          | 54 +++++++++++++++++++++++++-------------
 tools/dtoc/test_dtoc.py    | 10 +++----
 tools/dtoc/test_fdt.py     | 32 +++++++++++-----------
 5 files changed, 77 insertions(+), 59 deletions(-)

diff --git a/tools/binman/fdt_test.py b/tools/binman/fdt_test.py
index c491d40e9ee..3e12540f62e 100644
--- a/tools/binman/fdt_test.py
+++ b/tools/binman/fdt_test.py
@@ -50,37 +50,37 @@ class TestFdt(unittest.TestCase):
         self.assertEquals('me.bin', val)
 
         prop = node.props['intval']
-        self.assertEquals(fdt.TYPE_INT, prop.type)
+        self.assertEquals(fdt.Type.INT, prop.type)
         self.assertEquals(3, fdt_util.GetInt(node, 'intval'))
 
         prop = node.props['intarray']
-        self.assertEquals(fdt.TYPE_INT, prop.type)
+        self.assertEquals(fdt.Type.INT, prop.type)
         self.assertEquals(list, type(prop.value))
         self.assertEquals(2, len(prop.value))
         self.assertEquals([5, 6],
                           [fdt_util.fdt32_to_cpu(val) for val in prop.value])
 
         prop = node.props['byteval']
-        self.assertEquals(fdt.TYPE_BYTE, prop.type)
+        self.assertEquals(fdt.Type.BYTE, prop.type)
         self.assertEquals(chr(8), prop.value)
 
         prop = node.props['bytearray']
-        self.assertEquals(fdt.TYPE_BYTE, prop.type)
+        self.assertEquals(fdt.Type.BYTE, prop.type)
         self.assertEquals(list, type(prop.value))
         self.assertEquals(str, type(prop.value[0]))
         self.assertEquals(3, len(prop.value))
         self.assertEquals([chr(1), '#', '4'], prop.value)
 
         prop = node.props['longbytearray']
-        self.assertEquals(fdt.TYPE_INT, prop.type)
+        self.assertEquals(fdt.Type.INT, prop.type)
         self.assertEquals(0x090a0b0c, fdt_util.GetInt(node, 'longbytearray'))
 
         prop = node.props['stringval']
-        self.assertEquals(fdt.TYPE_STRING, prop.type)
+        self.assertEquals(fdt.Type.STRING, prop.type)
         self.assertEquals('message2', fdt_util.GetString(node, 'stringval'))
 
         prop = node.props['stringarray']
-        self.assertEquals(fdt.TYPE_STRING, prop.type)
+        self.assertEquals(fdt.Type.STRING, prop.type)
         self.assertEquals(list, type(prop.value))
         self.assertEquals(3, len(prop.value))
         self.assertEquals(['another', 'multi-word', 'message'], prop.value)
diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py
index 9b27aecc140..7926fe3a792 100644
--- a/tools/dtoc/dtb_platdata.py
+++ b/tools/dtoc/dtb_platdata.py
@@ -35,13 +35,13 @@ PROP_IGNORE_LIST = [
     'u-boot,dm-spl',
 ]
 
-# C type declarations for the tyues we support
+# C type declarations for the types we support
 TYPE_NAMES = {
-    fdt.TYPE_INT: 'fdt32_t',
-    fdt.TYPE_BYTE: 'unsigned char',
-    fdt.TYPE_STRING: 'const char *',
-    fdt.TYPE_BOOL: 'bool',
-    fdt.TYPE_INT64: 'fdt64_t',
+    fdt.Type.INT: 'fdt32_t',
+    fdt.Type.BYTE: 'unsigned char',
+    fdt.Type.STRING: 'const char *',
+    fdt.Type.BOOL: 'bool',
+    fdt.Type.INT64: 'fdt64_t',
 }
 
 STRUCT_PREFIX = 'dtd_'
@@ -106,17 +106,17 @@ def get_value(ftype, value):
         type: Data type (fdt_util)
         value: Data value, as a string of bytes
     """
-    if ftype == fdt.TYPE_INT:
+    if ftype == fdt.Type.INT:
         return '%#x' % fdt_util.fdt32_to_cpu(value)
-    elif ftype == fdt.TYPE_BYTE:
+    elif ftype == fdt.Type.BYTE:
         return '%#x' % tools.ToByte(value[0])
-    elif ftype == fdt.TYPE_STRING:
+    elif ftype == fdt.Type.STRING:
         # Handle evil ACPI backslashes by adding another backslash before them.
         # So "\\_SB.GPO0" in the device tree effectively stays like that in C
         return '"%s"' % value.replace('\\', '\\\\')
-    elif ftype == fdt.TYPE_BOOL:
+    elif ftype == fdt.Type.BOOL:
         return 'true'
-    elif ftype == fdt.TYPE_INT64:
+    elif ftype == fdt.Type.INT64:
         return '%#x' % value
 
 def get_compat_name(node):
@@ -435,7 +435,7 @@ class DtbPlatdata(object):
             na, ns = self.get_num_cells(node)
             total = na + ns
 
-            if reg.type != fdt.TYPE_INT:
+            if reg.type != fdt.Type.INT:
                 raise ValueError("Node '%s' reg property is not an int" %
                                  node.name)
             if len(reg.value) % total:
@@ -445,7 +445,7 @@ class DtbPlatdata(object):
             reg.na = na
             reg.ns = ns
             if na != 1 or ns != 1:
-                reg.type = fdt.TYPE_INT64
+                reg.type = fdt.Type.INT64
                 i = 0
                 new_value = []
                 val = reg.value
diff --git a/tools/dtoc/fdt.py b/tools/dtoc/fdt.py
index 03b86773d5f..cb365ca094a 100644
--- a/tools/dtoc/fdt.py
+++ b/tools/dtoc/fdt.py
@@ -5,6 +5,7 @@
 # Written by Simon Glass <sjg at chromium.org>
 #
 
+from enum import IntEnum
 import struct
 import sys
 
@@ -22,7 +23,25 @@ from patman import tools
 # so it is fairly efficient.
 
 # A list of types we support
-(TYPE_BYTE, TYPE_INT, TYPE_STRING, TYPE_BOOL, TYPE_INT64) = range(5)
+class Type(IntEnum):
+    (BYTE, INT, STRING, BOOL, INT64) = range(5)
+
+    def is_wider_than(self, other):
+        """Check if another type is 'wider' than this one
+
+        A wider type is one that holds more information than an earlier one,
+        similar to the concept of type-widening in C.
+
+        This uses a simple arithmetic comparison, since type values are in order
+        from narrowest (BYTE) to widest (INT64).
+
+        Args:
+            other: Other type to compare against
+
+        Return:
+            True if the other type is wider
+        """
+        return self.value > other.value
 
 def CheckErr(errnum, msg):
     if errnum:
@@ -41,9 +60,9 @@ def BytesToValue(data):
             Type of data
             Data, either a single element or a list of elements. Each element
             is one of:
-                TYPE_STRING: str/bytes value from the property
-                TYPE_INT: a byte-swapped integer stored as a 4-byte str/bytes
-                TYPE_BYTE: a byte stored as a single-byte str/bytes
+                Type.STRING: str/bytes value from the property
+                Type.INT: a byte-swapped integer stored as a 4-byte str/bytes
+                Type.BYTE: a byte stored as a single-byte str/bytes
     """
     data = bytes(data)
     size = len(data)
@@ -63,21 +82,21 @@ def BytesToValue(data):
         is_string = False
     if is_string:
         if count == 1: 
-            return TYPE_STRING, strings[0].decode()
+            return Type.STRING, strings[0].decode()
         else:
-            return TYPE_STRING, [s.decode() for s in strings[:-1]]
+            return Type.STRING, [s.decode() for s in strings[:-1]]
     if size % 4:
         if size == 1:
-            return TYPE_BYTE, tools.ToChar(data[0])
+            return Type.BYTE, tools.ToChar(data[0])
         else:
-            return TYPE_BYTE, [tools.ToChar(ch) for ch in list(data)]
+            return Type.BYTE, [tools.ToChar(ch) for ch in list(data)]
     val = []
     for i in range(0, size, 4):
         val.append(data[i:i + 4])
     if size == 4:
-        return TYPE_INT, val[0]
+        return Type.INT, val[0]
     else:
-        return TYPE_INT, val
+        return Type.INT, val
 
 
 class Prop:
@@ -97,7 +116,7 @@ class Prop:
         self.bytes = bytes(data)
         self.dirty = False
         if not data:
-            self.type = TYPE_BOOL
+            self.type = Type.BOOL
             self.value = True
             return
         self.type, self.value = BytesToValue(bytes(data))
@@ -128,9 +147,8 @@ class Prop:
         update the current property to be like the second, since it is less
         specific.
         """
-        if newprop.type < self.type:
-            # Special handling to convert an int into bytes
-            if self.type == TYPE_INT and newprop.type == TYPE_BYTE:
+        if self.type.is_wider_than(newprop.type):
+            if self.type == Type.INT and newprop.type == Type.BYTE:
                 if type(self.value) == list:
                     new_value = []
                     for val in self.value:
@@ -155,11 +173,11 @@ class Prop:
         Returns:
             A single value of the given type
         """
-        if type == TYPE_BYTE:
+        if type == Type.BYTE:
             return chr(0)
-        elif type == TYPE_INT:
+        elif type == Type.INT:
             return struct.pack('>I', 0);
-        elif type == TYPE_STRING:
+        elif type == Type.STRING:
             return ''
         else:
             return True
@@ -184,7 +202,7 @@ class Prop:
         """
         self.bytes = struct.pack('>I', val);
         self.value = self.bytes
-        self.type = TYPE_INT
+        self.type = Type.INT
         self.dirty = True
 
     def SetData(self, bytes):
diff --git a/tools/dtoc/test_dtoc.py b/tools/dtoc/test_dtoc.py
index a5836e04b7a..6dd8a5ca473 100755
--- a/tools/dtoc/test_dtoc.py
+++ b/tools/dtoc/test_dtoc.py
@@ -134,13 +134,13 @@ class TestDtoc(unittest.TestCase):
     def test_get_value(self):
         """Test operation of get_value() function"""
         self.assertEqual('0x45',
-                         get_value(fdt.TYPE_INT, struct.pack('>I', 0x45)))
+                         get_value(fdt.Type.INT, struct.pack('>I', 0x45)))
         self.assertEqual('0x45',
-                         get_value(fdt.TYPE_BYTE, struct.pack('<I', 0x45)))
+                         get_value(fdt.Type.BYTE, struct.pack('<I', 0x45)))
         self.assertEqual('0x0',
-                         get_value(fdt.TYPE_BYTE, struct.pack('>I', 0x45)))
-        self.assertEqual('"test"', get_value(fdt.TYPE_STRING, 'test'))
-        self.assertEqual('true', get_value(fdt.TYPE_BOOL, None))
+                         get_value(fdt.Type.BYTE, struct.pack('>I', 0x45)))
+        self.assertEqual('"test"', get_value(fdt.Type.STRING, 'test'))
+        self.assertEqual('true', get_value(fdt.Type.BOOL, None))
 
     def test_get_compat_name(self):
         """Test operation of get_compat_name() function"""
diff --git a/tools/dtoc/test_fdt.py b/tools/dtoc/test_fdt.py
index cfe3e04c7ad..10e7f33a595 100755
--- a/tools/dtoc/test_fdt.py
+++ b/tools/dtoc/test_fdt.py
@@ -19,7 +19,7 @@ sys.path.insert(1, os.path.join(our_path, '..'))
 from dtoc import fdt
 from dtoc import fdt_util
 from dtoc.fdt_util import fdt32_to_cpu
-from fdt import TYPE_BYTE, TYPE_INT, TYPE_STRING, TYPE_BOOL, BytesToValue
+from fdt import Type, BytesToValue
 import libfdt
 from patman import command
 from patman import test_util
@@ -127,7 +127,7 @@ class TestFdt(unittest.TestCase):
 
     def testBytesToValue(self):
         self.assertEqual(BytesToValue(b'this\0is\0'),
-                         (TYPE_STRING, ['this', 'is']))
+                         (Type.STRING, ['this', 'is']))
 
 class TestNode(unittest.TestCase):
     """Test operation of the Node class"""
@@ -249,46 +249,46 @@ class TestProp(unittest.TestCase):
     def testMakeProp(self):
         """Test we can convert all the the types that are supported"""
         prop = self._ConvertProp('boolval')
-        self.assertEqual(fdt.TYPE_BOOL, prop.type)
+        self.assertEqual(Type.BOOL, prop.type)
         self.assertEqual(True, prop.value)
 
         prop = self._ConvertProp('intval')
-        self.assertEqual(fdt.TYPE_INT, prop.type)
+        self.assertEqual(Type.INT, prop.type)
         self.assertEqual(1, fdt32_to_cpu(prop.value))
 
         prop = self._ConvertProp('intarray')
-        self.assertEqual(fdt.TYPE_INT, prop.type)
+        self.assertEqual(Type.INT, prop.type)
         val = [fdt32_to_cpu(val) for val in prop.value]
         self.assertEqual([2, 3, 4], val)
 
         prop = self._ConvertProp('byteval')
-        self.assertEqual(fdt.TYPE_BYTE, prop.type)
+        self.assertEqual(Type.BYTE, prop.type)
         self.assertEqual(5, ord(prop.value))
 
         prop = self._ConvertProp('longbytearray')
-        self.assertEqual(fdt.TYPE_BYTE, prop.type)
+        self.assertEqual(Type.BYTE, prop.type)
         val = [ord(val) for val in prop.value]
         self.assertEqual([9, 10, 11, 12, 13, 14, 15, 16, 17], val)
 
         prop = self._ConvertProp('stringval')
-        self.assertEqual(fdt.TYPE_STRING, prop.type)
+        self.assertEqual(Type.STRING, prop.type)
         self.assertEqual('message', prop.value)
 
         prop = self._ConvertProp('stringarray')
-        self.assertEqual(fdt.TYPE_STRING, prop.type)
+        self.assertEqual(Type.STRING, prop.type)
         self.assertEqual(['multi-word', 'message'], prop.value)
 
         prop = self._ConvertProp('notstring')
-        self.assertEqual(fdt.TYPE_BYTE, prop.type)
+        self.assertEqual(Type.BYTE, prop.type)
         val = [ord(val) for val in prop.value]
         self.assertEqual([0x20, 0x21, 0x22, 0x10, 0], val)
 
     def testGetEmpty(self):
         """Tests the GetEmpty() function for the various supported types"""
-        self.assertEqual(True, fdt.Prop.GetEmpty(fdt.TYPE_BOOL))
-        self.assertEqual(chr(0), fdt.Prop.GetEmpty(fdt.TYPE_BYTE))
-        self.assertEqual(tools.GetBytes(0, 4), fdt.Prop.GetEmpty(fdt.TYPE_INT))
-        self.assertEqual('', fdt.Prop.GetEmpty(fdt.TYPE_STRING))
+        self.assertEqual(True, fdt.Prop.GetEmpty(Type.BOOL))
+        self.assertEqual(chr(0), fdt.Prop.GetEmpty(Type.BYTE))
+        self.assertEqual(tools.GetBytes(0, 4), fdt.Prop.GetEmpty(Type.INT))
+        self.assertEqual('', fdt.Prop.GetEmpty(Type.STRING))
 
     def testGetOffset(self):
         """Test we can get the offset of a property"""
@@ -304,13 +304,13 @@ class TestProp(unittest.TestCase):
         # No action
         prop2 = node2.props['intval']
         prop.Widen(prop2)
-        self.assertEqual(fdt.TYPE_INT, prop.type)
+        self.assertEqual(Type.INT, prop.type)
         self.assertEqual(1, fdt32_to_cpu(prop.value))
 
         # Convert singla value to array
         prop2 = self.node.props['intarray']
         prop.Widen(prop2)
-        self.assertEqual(fdt.TYPE_INT, prop.type)
+        self.assertEqual(Type.INT, prop.type)
         self.assertTrue(isinstance(prop.value, list))
 
         # A 4-byte array looks like a single integer. When widened by a longer
-- 
2.29.2.222.g5d2a92d10f8-goog



More information about the U-Boot mailing list