def get_num_cells(node): """Get the number of cells in addresses and sizes for this node Args: node (fdt.None): Node to check Returns: Tuple: Number of address cells for this node Number of size cells for this node """ parent = node.parent if parent and not parent.props: raise ValueError( "Parent node '%s' has no properties - do you need u-boot,dm-spl or similar?" % parent.path) num_addr, num_size = 2, 2 if parent: addr_prop = parent.props.get('#address-cells') size_prop = parent.props.get('#size-cells') if addr_prop: num_addr = fdt_util.fdt32_to_cpu(addr_prop.value) if size_prop: num_size = fdt_util.fdt32_to_cpu(size_prop.value) return num_addr, num_size
def testAddMore(self): """Test various other methods for adding and setting properties""" self.node.AddZeroProp('one') self.dtb.Sync(auto_resize=True) data = self.fdt.getprop(self.node.Offset(), 'one') self.assertEqual(0, fdt32_to_cpu(data)) self.node.SetInt('one', 1) self.dtb.Sync(auto_resize=False) data = self.fdt.getprop(self.node.Offset(), 'one') self.assertEqual(1, fdt32_to_cpu(data)) val = 1234 self.node.AddInt('integer', val) self.dtb.Sync(auto_resize=True) data = self.fdt.getprop(self.node.Offset(), 'integer') self.assertEqual(val, fdt32_to_cpu(data)) val = '123' + chr(0) + '456' self.node.AddString('string', val) self.dtb.Sync(auto_resize=True) data = self.fdt.getprop(self.node.Offset(), 'string') self.assertEqual(tools.to_bytes(val) + b'\0', data) self.fdt.pack() self.node.SetString('string', val + 'x') with self.assertRaises(libfdt.FdtException) as e: self.dtb.Sync(auto_resize=False) self.assertIn('FDT_ERR_NOSPACE', str(e.exception)) self.node.SetString('string', val[:-1]) prop = self.node.props['string'] prop.SetData(tools.to_bytes(val)) self.dtb.Sync(auto_resize=False) data = self.fdt.getprop(self.node.Offset(), 'string') self.assertEqual(tools.to_bytes(val), data) self.node.AddEmptyProp('empty', 5) self.dtb.Sync(auto_resize=True) prop = self.node.props['empty'] prop.SetData(tools.to_bytes(val)) self.dtb.Sync(auto_resize=False) data = self.fdt.getprop(self.node.Offset(), 'empty') self.assertEqual(tools.to_bytes(val), data) self.node.SetData('empty', b'123') self.assertEqual(b'123', prop.bytes) # Trying adding a lot of data at once self.node.AddData('data', tools.get_bytes(65, 20000)) self.dtb.Sync(auto_resize=True)
def get_phandle_argc(self, prop, node_name): """Check if a node contains phandles We have no reliable way of detecting whether a node uses a phandle or not. As an interim measure, use a list of known property names. Args: prop (fdt.Prop): Prop object to check node_name (str): Node name, only used for raising an error Returns: int or None: Number of argument cells is this is a phandle, else None Raises: ValueError: if the phandle cannot be parsed or the required property is not present """ if prop.name in ['clocks', 'cd-gpios']: if not isinstance(prop.value, list): prop.value = [prop.value] val = prop.value i = 0 max_args = 0 args = [] while i < len(val): phandle = fdt_util.fdt32_to_cpu(val[i]) # If we get to the end of the list, stop. This can happen # since some nodes have more phandles in the list than others, # but we allocate enough space for the largest list. So those # nodes with shorter lists end up with zeroes at the end. if not phandle: break target = self._fdt.phandle_to_node.get(phandle) if not target: raise ValueError("Cannot parse '%s' in node '%s'" % (prop.name, node_name)) cells = None for prop_name in ['#clock-cells', '#gpio-cells']: cells = target.props.get(prop_name) if cells: break if not cells: raise ValueError("Node '%s' has no cells property" % (target.name)) num_args = fdt_util.fdt32_to_cpu(cells.value) max_args = max(max_args, num_args) args.append(num_args) i += 1 + num_args return PhandleInfo(max_args, args) return None
def BuildSectionData(self, required): """Build FIT entry contents This adds the 'data' properties to the input ITB (Image-tree Binary) then runs mkimage to process it. Args: required (bool): True if the data must be present, False if it is OK to return None Returns: bytes: Contents of the section """ data = self._build_input() uniq = self.GetUniqueName() input_fname = tools.get_output_filename(f'{uniq}.itb') output_fname = tools.get_output_filename(f'{uniq}.fit') tools.write_file(input_fname, data) tools.write_file(output_fname, data) args = {} ext_offset = self._fit_props.get('fit,external-offset') if ext_offset is not None: args = { 'external': True, 'pad': fdt_util.fdt32_to_cpu(ext_offset.value) } if self.mkimage.run(reset_timestamp=True, output_fname=output_fname, **args) is None: # Bintool is missing; just use empty data as the output self.record_missing_bintool(self.mkimage) return tools.get_bytes(0, 1024) return tools.read_file(output_fname)
def ObtainContents(self): """Obtain the contents of the FIT This adds the 'data' properties to the input ITB (Image-tree Binary) then runs mkimage to process it. """ # self._BuildInput() either returns bytes or raises an exception. data = self._BuildInput(self._fdt) uniq = self.GetUniqueName() input_fname = tools.GetOutputFilename('%s.itb' % uniq) output_fname = tools.GetOutputFilename('%s.fit' % uniq) tools.WriteFile(input_fname, data) tools.WriteFile(output_fname, data) args = [] ext_offset = self._fit_props.get('fit,external-offset') if ext_offset is not None: args += [ '-E', '-p', '%x' % fdt_util.fdt32_to_cpu(ext_offset.value) ] tools.Run('mkimage', '-t', '-F', output_fname, *args) self.SetContents(tools.ReadFile(output_fname)) return True
def ObtainContents(self): """Obtain the contents of the FIT This adds the 'data' properties to the input ITB (Image-tree Binary) then runs mkimage to process it. """ # self._BuildInput() either returns bytes or raises an exception. data = self._BuildInput(self._fdt) uniq = self.GetUniqueName() input_fname = tools.GetOutputFilename('%s.itb' % uniq) output_fname = tools.GetOutputFilename('%s.fit' % uniq) tools.WriteFile(input_fname, data) tools.WriteFile(output_fname, data) args = {} ext_offset = self._fit_props.get('fit,external-offset') if ext_offset is not None: args = { 'external': True, 'pad': fdt_util.fdt32_to_cpu(ext_offset.value) } if self.mkimage.run(reset_timestamp=True, output_fname=output_fname, **args) is not None: self.SetContents(tools.ReadFile(output_fname)) else: # Bintool is missing; just use empty data as the output self.record_missing_bintool(self.mkimage) self.SetContents(tools.GetBytes(0, 1024)) return True
def get_value(ftype, value): """Get a value as a C expression For integers this returns a byte-swapped (little-endian) hex string For bytes this returns a hex string, e.g. 0x12 For strings this returns a literal string enclosed in quotes For booleans this return 'true' Args: ftype (fdt.Type): Data type (fdt_util) value (bytes): Data value, as a string of bytes Returns: str: String representation of the value """ if ftype == fdt.Type.INT: val = '%#x' % fdt_util.fdt32_to_cpu(value) elif ftype == fdt.Type.BYTE: char = value[0] val = '%#x' % (ord(char) if isinstance(char, str) else char) 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 val = '"%s"' % value.replace('\\', '\\\\') elif ftype == fdt.Type.BOOL: val = 'true' else: # ftype == fdt.Type.INT64: val = '%#x' % value return val
def testLookupPhandle(self): """Test looking up a single phandle""" dtb = fdt.FdtScan(find_dtb_file('dtoc_test_phandle.dts')) node = dtb.GetNode('/phandle-source2') prop = node.props['clocks'] target = dtb.GetNode('/phandle-target') self.assertEqual(target, dtb.LookupPhandle(fdt32_to_cpu(prop.value)))
def scan_phandles(self): """Figure out what phandles each node uses We need to be careful when outputing nodes that use phandles since they must come after the declaration of the phandles in the C file. Otherwise we get a compiler error since the phandle struct is not yet declared. This function adds to each node a list of phandle nodes that the node depends on. This allows us to output things in the right order. """ for node in self._valid_nodes: node.phandles = set() for pname, prop in node.props.items(): if pname in PROP_IGNORE_LIST or pname[0] == '#': continue info = self.get_phandle_argc(prop, node.name) if info: # Process the list as pairs of (phandle, id) pos = 0 for args in info.args: phandle_cell = prop.value[pos] phandle = fdt_util.fdt32_to_cpu(phandle_cell) target_node = self._fdt.phandle_to_node[phandle] node.phandles.add(target_node) pos += 1 + args
def testWiden(self): """Test widening of values""" node2 = self.dtb.GetNode('/spl-test2') node3 = self.dtb.GetNode('/spl-test3') prop = self.node.props['intval'] # No action prop2 = node2.props['intval'] prop.Widen(prop2) 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(Type.INT, prop.type) self.assertTrue(isinstance(prop.value, list)) # A 4-byte array looks like a single integer. When widened by a longer # byte array, it should turn into an array. prop = self.node.props['longbytearray'] prop2 = node2.props['longbytearray'] prop3 = node3.props['longbytearray'] self.assertFalse(isinstance(prop2.value, list)) self.assertEqual(4, len(prop2.value)) self.assertEqual(b'\x09\x0a\x0b\x0c', prop2.value) prop2.Widen(prop) self.assertTrue(isinstance(prop2.value, list)) self.assertEqual(9, len(prop2.value)) self.assertEqual( ['\x09', '\x0a', '\x0b', '\x0c', '\0', '\0', '\0', '\0', '\0'], prop2.value) prop3.Widen(prop) self.assertTrue(isinstance(prop3.value, list)) self.assertEqual(9, len(prop3.value)) self.assertEqual([ '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f', '\x10', '\0' ], prop3.value) # Similarly for a string array prop = self.node.props['stringval'] prop2 = node2.props['stringarray'] self.assertFalse(isinstance(prop.value, list)) self.assertEqual(7, len(prop.value)) prop.Widen(prop2) self.assertTrue(isinstance(prop.value, list)) self.assertEqual(3, len(prop.value)) # Enlarging an existing array prop = self.node.props['stringarray'] prop2 = node2.props['stringarray'] self.assertTrue(isinstance(prop.value, list)) self.assertEqual(2, len(prop.value)) prop.Widen(prop2) self.assertTrue(isinstance(prop.value, list)) self.assertEqual(3, len(prop.value))
def _output_list(node, prop): """Output the C code for a devicetree property that holds a list Args: node (fdt.Node): Node to output prop (fdt.Prop): Prop to output """ self.buf('{') vals = [] # For phandles, output a reference to the platform data # of the target node. info = self.get_phandle_argc(prop, node.name) if info: # Process the list as pairs of (phandle, id) pos = 0 item = 0 for args in info.args: phandle_cell = prop.value[pos] phandle = fdt_util.fdt32_to_cpu(phandle_cell) target_node = self._fdt.phandle_to_node[phandle] name = conv_name_to_c(target_node.name) arg_values = [] for i in range(args): arg_values.append( str(fdt_util.fdt32_to_cpu(prop.value[pos + 1 + i]))) pos += 1 + args vals.append('\t{%d, {%s}}' % (target_node.idx, ', '.join(arg_values))) item += 1 for val in vals: self.buf('\n\t\t%s,' % val) else: for val in prop.value: vals.append(get_value(prop.type, val)) # Put 8 values per line to avoid very long lines. for i in range(0, len(vals), 8): if i: self.buf(',\n\t\t') self.buf(', '.join(vals[i:i + 8])) self.buf('}')
def get_num_cells(node): """Get the number of cells in addresses and sizes for this node Args: node (fdt.None): Node to check Returns: Tuple: Number of address cells for this node Number of size cells for this node """ parent = node.parent num_addr, num_size = 2, 2 if parent: addr_prop = parent.props.get('#address-cells') size_prop = parent.props.get('#size-cells') if addr_prop: num_addr = fdt_util.fdt32_to_cpu(addr_prop.value) if size_prop: num_size = fdt_util.fdt32_to_cpu(size_prop.value) return num_addr, num_size
def get_num_cells(node): """Get the number of cells in addresses and sizes for this node Args: node: Node to check Returns: Tuple: Number of address cells for this node Number of size cells for this node """ parent = node.parent na, ns = 2, 2 if parent: na_prop = parent.props.get('#address-cells') ns_prop = parent.props.get('#size-cells') if na_prop: na = fdt_util.fdt32_to_cpu(na_prop.value) if ns_prop: ns = fdt_util.fdt32_to_cpu(ns_prop.value) return na, ns
def testMakeProp(self): """Test we can convert all the the types that are supported""" prop = self._ConvertProp('boolval') self.assertEqual(Type.BOOL, prop.type) self.assertEqual(True, prop.value) prop = self._ConvertProp('intval') self.assertEqual(Type.INT, prop.type) self.assertEqual(1, fdt32_to_cpu(prop.value)) prop = self._ConvertProp('int64val') self.assertEqual(Type.INT, prop.type) self.assertEqual(0x123456789abcdef0, fdt64_to_cpu(prop.value)) prop = self._ConvertProp('intarray') 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(Type.BYTE, prop.type) self.assertEqual(5, ord(prop.value)) prop = self._ConvertProp('longbytearray') 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(Type.STRING, prop.type) self.assertEqual('message', prop.value) prop = self._ConvertProp('stringarray') self.assertEqual(Type.STRING, prop.type) self.assertEqual(['multi-word', 'message'], prop.value) prop = self._ConvertProp('notstring') self.assertEqual(Type.BYTE, prop.type) val = [ord(val) for val in prop.value] self.assertEqual([0x20, 0x21, 0x22, 0x10, 0], val)
def testFdtNormalProp(self): fname = self.GetCompiled('045_prop_test.dts') dt = FdtScan(fname) node = dt.GetNode('/binman/intel-me') self.assertEquals('intel-me', node.name) val = fdt_util.GetString(node, 'filename') self.assertEquals(str, type(val)) self.assertEquals('me.bin', val) prop = node.props['intval'] 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(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(chr(8), prop.value) prop = node.props['bytearray'] 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(0x090a0b0c, fdt_util.GetInt(node, 'longbytearray')) prop = node.props['stringval'] 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(list, type(prop.value)) self.assertEquals(3, len(prop.value)) self.assertEquals(['another', 'multi-word', 'message'], prop.value)
def get_value(ftype, value): """Get a value as a C expression For integers this returns a byte-swapped (little-endian) hex string For bytes this returns a hex string, e.g. 0x12 For strings this returns a literal string enclosed in quotes For booleans this return 'true' Args: type: Data type (fdt_util) value: Data value, as a string of bytes """ if ftype == fdt.TYPE_INT: return '%#x' % fdt_util.fdt32_to_cpu(value) elif ftype == fdt.TYPE_BYTE: return '%#x' % tools.ToByte(value[0]) elif ftype == fdt.TYPE_STRING: return '"%s"' % value elif ftype == fdt.TYPE_BOOL: return 'true' elif ftype == fdt.TYPE_INT64: return '%#x' % value
def get_value(ftype, value): """Get a value as a C expression For integers this returns a byte-swapped (little-endian) hex string For bytes this returns a hex string, e.g. 0x12 For strings this returns a literal string enclosed in quotes For booleans this return 'true' Args: type: Data type (fdt_util) value: Data value, as a string of bytes """ if ftype == fdt.TYPE_INT: return '%#x' % fdt_util.fdt32_to_cpu(value) elif ftype == fdt.TYPE_BYTE: return '%#x' % tools.ToByte(value[0]) 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: return 'true' elif ftype == fdt.TYPE_INT64: return '%#x' % value
def testPhandle(self): dtb = fdt.FdtScan(find_dtb_file('dtoc_test_phandle.dts')) node = dtb.GetNode('/phandle-source2') prop = node.props['clocks'] self.assertTrue(fdt32_to_cpu(prop.value) > 0)
def output_node(self, node): """Output the C code for a node Args: node: node to output """ struct_name, _ = self.get_normalized_compat_name(node) var_name = conv_name_to_c(node.name) self.buf('static struct %s%s %s%s = {\n' % (STRUCT_PREFIX, struct_name, VAL_PREFIX, var_name)) for pname in sorted(node.props): prop = node.props[pname] if pname in PROP_IGNORE_LIST or pname[0] == '#': continue member_name = conv_name_to_c(prop.name) self.buf('\t%s= ' % tab_to(3, '.' + member_name)) # Special handling for lists if isinstance(prop.value, list): self.buf('{') vals = [] # For phandles, output a reference to the platform data # of the target node. info = self.get_phandle_argc(prop, node.name) if info: # Process the list as pairs of (phandle, id) pos = 0 item = 0 for args in info.args: phandle_cell = prop.value[pos] phandle = fdt_util.fdt32_to_cpu(phandle_cell) target_node = self._fdt.phandle_to_node[phandle] name = conv_name_to_c(target_node.name) arg_values = [] for i in range(args): arg_values.append(str(fdt_util.fdt32_to_cpu(prop.value[pos + 1 + i]))) pos += 1 + args # node member is filled with NULL as the real value # will be update at run-time during dm_init_and_scan() # by dm_populate_phandle_data() vals.append('\t{NULL, {%s}}' % (', '.join(arg_values))) var_node = '%s%s.%s[%d].node' % \ (VAL_PREFIX, var_name, member_name, item) # Save the the link information to be use to define # dm_populate_phandle_data() self._links.append({'var_node': var_node, 'dev_name': name}) item += 1 for val in vals: self.buf('\n\t\t%s,' % val) else: for val in prop.value: vals.append(get_value(prop.type, val)) # Put 8 values per line to avoid very long lines. for i in range(0, len(vals), 8): if i: self.buf(',\n\t\t') self.buf(', '.join(vals[i:i + 8])) self.buf('}') else: self.buf(get_value(prop.type, prop.value)) self.buf(',\n') self.buf('};\n') # Add a device declaration self.buf('U_BOOT_DEVICE(%s) = {\n' % var_name) self.buf('\t.name\t\t= "%s",\n' % struct_name) self.buf('\t.platdata\t= &%s%s,\n' % (VAL_PREFIX, var_name)) self.buf('\t.platdata_size\t= sizeof(%s%s),\n' % (VAL_PREFIX, var_name)) self.buf('};\n') self.buf('\n') self.out(''.join(self.get_buf()))