fdt: Use an Enum for the data type

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@chromium.org>
This commit is contained in:
Simon Glass 2020-11-08 20:36:17 -07:00
parent ddaa949785
commit 5ea9dccf02
5 changed files with 77 additions and 59 deletions

View File

@ -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)

View File

@ -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

View File

@ -5,6 +5,7 @@
# Written by Simon Glass <sjg@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):

View File

@ -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"""

View File

@ -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