| #!/usr/bin/python |
| |
| # Copyright (c) 2011 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| """This library provides basic access to an fdt blob.""" |
| |
| import binascii |
| import doctest |
| import optparse |
| import os |
| import re |
| import shutil |
| import struct |
| import sys |
| |
| import cros_output |
| from tools import Tools |
| |
| _base = os.path.dirname(sys.argv[0]) |
| |
| |
| class Fdt: |
| """Provides simple access to a flat device tree blob. |
| |
| Properties: |
| fname: Filename of fdt |
| """ |
| |
| def __init__(self, tools, fname): |
| self.fname = fname |
| self.tools = tools |
| _, ext = os.path.splitext(fname) |
| self._is_compiled = ext == '.dtb' |
| |
| def ExtractFromImage(self, fname): |
| """Extract an FDT from a Chrome OS firmware image (FDTMAP). |
| |
| Args: |
| fname: Filename of image |
| |
| Raises: |
| ValueError if no fdtmap is found in the image, or its crc32 is incorrect. |
| """ |
| data = self.tools.ReadFile(fname) |
| pos = data.find('__FDTM__') |
| if pos == -1: |
| raise ValueError("No fdtmap found in image '%s'" % fname) |
| size, crc32 = struct.unpack('<LL', data[pos + 8:pos + 16]) |
| fdt_data = data[pos + 16:pos + 16 + size] |
| check_crc32 = binascii.crc32(fdt_data) & 0xffffffff |
| if check_crc32 != crc32: |
| raise ValueError('Invalid CRC for FDTMAP') |
| self.tools.WriteFile(self.fname, fdt_data) |
| |
| def GetProp(self, node, prop, default=None, typespec=None): |
| """Get a property from a device tree. |
| |
| >>> tools = Tools(cros_output.Output()) |
| >>> fdt = Fdt(tools, os.path.join(_base, '../tests/test.dtb')) |
| >>> fdt.GetProp('/lcd', 'width') |
| '1366' |
| |
| >>> fdt.GetProp('/', 'fluffy') |
| Traceback (most recent call last): |
| ... |
| CmdError: Command failed: fdtget ../tests/test.dtb / fluffy |
| Error at 'fluffy': FDT_ERR_NOTFOUND |
| <BLANKLINE> |
| |
| This looks up the given node and property, and returns the value as a |
| string, |
| |
| If the node or property does not exist, this will return the default value. |
| |
| Args: |
| node: Full path to node to look up. |
| prop: Property name to look up. |
| default: Default value to return if nothing is present in the fdt, or |
| None to raise in this case. This will be converted to a string. |
| typespec: Type character to use (None for default, 's' for string) |
| |
| Returns: |
| string containing the property value. |
| |
| Raises: |
| CmdError: if the property does not exist and no default is provided. |
| """ |
| args = [self.fname, node, prop] |
| if default is not None: |
| args += ['-d', str(default)] |
| if typespec is not None: |
| args += ['-t%s' % typespec] |
| out = self.tools.Run('fdtget', args) |
| return out.strip() |
| |
| def GetBool(self, node, prop): |
| """Get a boolean property from a device tree. |
| |
| If the property is present then it is considered True, else False. |
| |
| >>> tools = Tools(cros_output.Output()) |
| >>> fdt = Fdt(tools, os.path.join(_base, '../tests/test.dtb')) |
| >>> fdt.GetBool('/flash/ro-gbb', 'hash-target') |
| False |
| >>> fdt.GetBool('/flash/ro-onestop', 'hash-target') |
| True |
| |
| Args: |
| node: Full path to node to look up. |
| prop: Property name to look up. |
| |
| Returns: |
| True if property is present, False if not. |
| """ |
| value = self.GetProp(node, prop, '<none>') |
| return value != '<none>' |
| |
| def PutBool(self, node, prop, bool_value): |
| """Write a boolean property to a device tree. |
| |
| If the property is present then it is considered True, else False. At |
| present we can't actually support removing the property since fdtput |
| does not have this option. |
| |
| >>> tools = Tools(cros_output.Output()) |
| >>> fdt = Fdt(tools, os.path.join(_base, '../tests/test.dtb')) |
| >>> fdt.GetBool('/putbool-test', 'dead-silence') |
| False |
| >>> fdt.PutBool('/putbool-test', 'dead-silence', False) |
| >>> fdt.GetBool('/putbool-test', 'dead-silence') |
| False |
| >>> fdt.PutBool('/putbool-test', 'dead-silence', True) |
| >>> fdt.GetBool('/putbool-test', 'dead-silence') |
| True |
| >>> fdt.PutBool('/putbool-test', 'dead-silence', False) |
| Traceback (most recent call last): |
| ... |
| ValueError: ("Cannot set node '%s' property '%s' to False", \ |
| ('/putbool-test', 'dead-silence')) |
| >>> fdt.GetBool('/putbool-test', 'dead-silence') |
| True |
| |
| Args: |
| node: Full path to node to update. |
| prop: Property name to write. |
| bool_value: Boolean to write. |
| |
| Raises: |
| ValueError: if the property is True and we try to set it to False. |
| """ |
| if bool_value: |
| args = ['-p', self.fname, node, prop] |
| self.tools.Run('fdtput', args) |
| elif self.GetBool(node, prop): |
| raise ValueError("Cannot set node '%s' property '%s' to False", |
| (node, prop)) |
| |
| def GetProps(self, node, convert_dashes=False): |
| """Get all properties from a node. |
| |
| >>> tools = Tools(cros_output.Output()) |
| >>> fdt = Fdt(tools, os.path.join(_base, '../tests/test.dtb')) |
| >>> fdt.GetProps('/') |
| {'compatible': 'nvidia,seaboard nvidia,tegra250', '#size-cells': '1', \ |
| 'model': 'NVIDIA Seaboard', '#address-cells': '1', 'interrupt-parent': '1'} |
| |
| Args: |
| node: node name to look in. |
| convert_dashes: True to convert - to _ in node names. |
| |
| Returns: |
| A dictionary containing all the properties, indexed by node name. |
| The entries are simply strings - no decoding of lists or numbers is |
| done. |
| |
| Raises: |
| CmdError: if the node does not exist. |
| """ |
| out = self.tools.Run('fdtget', [self.fname, node, '-p']) |
| props = out.strip().splitlines() |
| props_dict = {} |
| for prop in props: |
| name = prop |
| if convert_dashes: |
| prop = re.sub('-', '_', prop) |
| props_dict[prop] = self.GetProp(node, name) |
| return props_dict |
| |
| def DecodeIntList(self, node, prop, int_list_str, num_values=None): |
| """Decode a string into a list of integers. |
| |
| >>> tools = Tools(cros_output.Output()) |
| >>> fdt = Fdt(tools, os.path.join(_base, '../tests/test.dtb')) |
| >>> fdt.DecodeIntList('/', 'galveston', '1 2 3 4') |
| [1, 2, 3, 4] |
| |
| >>> fdt.DecodeIntList('/', 'galveston', '1 2 3 4', 4) |
| [1, 2, 3, 4] |
| |
| >>> fdt.DecodeIntList('/', 'galveston', '0xff', 1) |
| [255] |
| |
| >>> fdt.DecodeIntList('/', 'galveston', '1 2 3 4', 3) |
| Traceback (most recent call last): |
| ... |
| ValueError: GetIntList of node '/' prop 'galveston' returns \ |
| '<type 'list'>', which has 4 elements, but 3 expected |
| |
| This decodes a string containing a list of integers like '1 2 3' into |
| a list like [1 2 3]. |
| |
| Args: |
| node: Full path to node to report in any error raised. |
| prop: Property name to report in any error raised. |
| int_list_str: String to decode. |
| num_values: If not None, then the array is checked to make sure it |
| has this many values, and an error is raised if not. |
| |
| Returns: |
| List of integers. |
| |
| Raises: |
| ValueError: if the list is the wrong size. |
| """ |
| int_list = int_list_str.split() |
| if num_values and num_values != len(int_list): |
| raise ValueError("GetIntList of node '%s' prop '%s' returns '%s'" |
| ", which has %d elements, but %d expected" % |
| (node, prop, list, len(int_list), num_values)) |
| return [int(item, 0) for item in int_list] |
| |
| def GetIntList(self, node, prop, num_values=None, default=None): |
| """Read a property and decode it into a list of integers. |
| |
| >>> tools = Tools(cros_output.Output()) |
| >>> fdt = Fdt(tools, os.path.join(_base, '../tests/test.dtb')) |
| >>> fdt.GetIntList('/flash@0/shared-dev-cfg@180000', 'reg') |
| [1572864, 262144] |
| |
| >>> fdt.GetIntList('/flash/shared-dev-cfg', 'reg') |
| [1572864, 262144] |
| |
| >>> fdt.GetIntList('/flash/shared-dev-cfg', 'reg', 3) |
| Traceback (most recent call last): |
| ... |
| ValueError: GetIntList of node '/flash/shared-dev-cfg' prop 'reg' returns \ |
| '<type 'list'>', which has 2 elements, but 3 expected |
| |
| >>> fdt.GetIntList('/swaffham', 'bulbeck', 2) |
| Traceback (most recent call last): |
| ... |
| CmdError: Command failed: fdtget ../tests/test.dtb /swaffham bulbeck |
| Error at '/swaffham': FDT_ERR_NOTFOUND |
| <BLANKLINE> |
| >>> fdt.GetIntList('/lcd', 'bulbeck', 2, '5 6') |
| [5, 6] |
| |
| This decodes a property containing a list of integers like '1 2 3' into |
| a list like [1 2 3]. |
| |
| Args: |
| node: Full path to node to look up. |
| prop: Property name to look up. |
| num_values: If not None, then the array is checked to make sure it |
| has this many values, and an error is raised if not. |
| default: Default value to return if nothing is present in the fdt, or |
| None to raise in this case. This will be converted to a string. |
| |
| Returns: |
| List of integers. |
| |
| Raises: |
| ValueError if the list is the wrong size. |
| CmdError: if the property does not exist. |
| """ |
| return self.DecodeIntList(node, prop, self.GetProp(node, prop, default), |
| num_values) |
| |
| def GetInt(self, node, prop, default=None): |
| """Gets an integer from a device tree property. |
| |
| >>> tools = Tools(cros_output.Output()) |
| >>> fdt = Fdt(tools, os.path.join(_base, '../tests/test.dtb')) |
| >>> fdt.GetInt('/lcd', 'width') |
| 1366 |
| >>> fdt.GetInt('/lcd', 'rangiora') |
| Traceback (most recent call last): |
| ... |
| CmdError: Command failed: fdtget ../tests/test.dtb /lcd rangiora |
| Error at 'rangiora': FDT_ERR_NOTFOUND |
| <BLANKLINE> |
| |
| >>> fdt.GetInt('/lcd', 'rangiora', 1366) |
| 1366 |
| |
| Args: |
| node: Full path to node to look up. |
| prop: Property name to look up. |
| default: Default value to return if nothing is present in the fdt, or |
| None to raise in this case. This will be converted to a string. |
| |
| Returns: |
| Value of property, as an integer. |
| |
| Raises: |
| ValueError if the property cannot be converted to an integer. |
| CmdError: if the property does not exist. |
| """ |
| value = self.GetIntList(node, prop, 1, default)[0] |
| return int(value) |
| |
| def GetString(self, node, prop, default=None): |
| """Gets a string from a device tree property. |
| |
| The 's' typespec is used to ask fdtget to convert the property to a |
| string even it is has embedded \0. This allows it to work with |
| compatible strings which contain a list. |
| |
| >>> tools = Tools(cros_output.Output()) |
| >>> fdt = Fdt(tools, os.path.join(_base, '../tests/test.dtb')) |
| >>> fdt.GetString('/display', 'compatible') |
| 'nvidia,tegra250-display' |
| >>> fdt.GetString('/', 'compatible') |
| 'nvidia,seaboard nvidia,tegra250' |
| |
| Args: |
| node: Full path to node to look up. |
| prop: Property name to look up. |
| default: Default value to return if nothing is present in the fdt, or |
| None to raise in this case. |
| |
| Returns: |
| Value of property, as a string. |
| |
| Raises: |
| CmdError: if the property does not exist. |
| """ |
| return self.GetProp(node, prop, default, typespec='s') |
| |
| def GetFlashNode(self, section, part): |
| """Returns the node path to use for a particular flash section/path. |
| |
| Args: |
| section: Section name to look at: ro, rw-a, etc. |
| part: Partition name to look at: gbb, vpd, etc. |
| |
| Returns: |
| Full path to flash node |
| """ |
| return '/flash/%s-%s' % (section, part) |
| |
| def GetFlashPart(self, section, part): |
| """Returns the setup of the given section/part number in the flash map. |
| |
| >>> tools = Tools(cros_output.Output()) |
| >>> fdt = Fdt(tools, os.path.join(_base, '../tests/test.dtb')) |
| >>> fdt.GetFlashPart('ro', 'onestop') |
| [65536, 524288] |
| |
| Args: |
| section: Section name to look at: ro, rw-a, etc. |
| part: Partition name to look at: gbb, vpd, etc. |
| |
| Returns: |
| Tuple (position, size) of flash area in bytes. |
| """ |
| return self.GetIntList(self.GetFlashNode(section, part), 'reg', 2) |
| |
| def GetFlashPartSize(self, section, part): |
| """Returns the size of the given section/part number in the flash map. |
| |
| >>> tools = Tools(cros_output.Output()) |
| >>> fdt = Fdt(tools, os.path.join(_base, '../tests/test.dtb')) |
| >>> fdt.GetFlashPartSize('ro', 'onestop') |
| 524288 |
| >>> fdt.GetFlashPartSize('rw', 'b-onestop') |
| 32768 |
| |
| Args: |
| section: Section name to look at: ro, rw-a, etc. |
| part: Partition name to look at: gbb, vpd, etc. |
| |
| Returns: |
| Size of flash area in bytes. |
| """ |
| size = self.GetInt(self.GetFlashNode(section, part), 'size', -1) |
| if size == -1: |
| size = self.GetFlashPart(section, part)[1] |
| return size |
| |
| def GetFlashPartUsed(self, section, part): |
| """Returns the used part of the given section/part number in the flash map. |
| |
| >>> tools = Tools(cros_output.Output()) |
| >>> fdt = Fdt(tools, os.path.join(_base, '../tests/test.dtb')) |
| >>> fdt.GetFlashPartUsed('ro', 'onestop') |
| 1234 |
| >>> fdt.GetFlashPartUsed('rw-a', 'onestop') |
| |
| Args: |
| section: Section name to look at: ro, rw-a, etc. |
| part: Partition name to look at: gbb, vpd, etc. |
| |
| Returns: |
| Size of flash area in bytes. |
| """ |
| size = self.GetInt(self.GetFlashNode(section, part), 'used', -1) |
| if size == -1: |
| return None |
| return size |
| |
| def GetChildren(self, node): |
| """Returns a list of children of a given node. |
| |
| >>> tools = Tools(cros_output.Output()) |
| >>> fdt = Fdt(tools, os.path.join(_base, '../tests/test.dtb')) |
| >>> fdt.GetChildren('/amba') |
| ['interrupt-controller@50041000'] |
| |
| >>> fdt.GetChildren('/flash@0') |
| ['onestop-layout@0', 'firmware-image@0', 'verification-block@7df00', \ |
| 'firmware-id@7ff00', 'readonly@0', 'bct@0', 'ro-onestop@10000', \ |
| 'ro-gbb@90000', 'ro-data@b0000', 'ro-vpd@c0000', 'fmap@d0000', \ |
| 'readwrite@100000', 'rw-vpd@100000', 'shared-dev-cfg@180000', \ |
| 'shared-data@1c0000', 'shared-env@1ff000', 'readwrite-a@200000', \ |
| 'rw-a-onestop@200000', 'readwrite-b@300000', 'rw-b-onestop@300000'] |
| |
| Args: |
| node: Node to return children from. |
| |
| Returns: |
| List of children in the node. |
| |
| Raises: |
| CmdError: if the node does not exist. |
| """ |
| out = self.tools.Run('fdtget', [self.fname, '-l', node]) |
| return out.strip().splitlines() |
| |
| def GetLabel(self, node): |
| """Returns the label property of a given node. |
| |
| >>> tools = Tools(cros_output.Output()) |
| >>> fdt = Fdt(tools, os.path.join(_base, '../tests/test.dtb')) |
| >>> fdt.GetLabel('/flash/ro-onestop') |
| 'ro-onestop' |
| |
| >>> fdt.GetLabel('/go/hotspurs') |
| Traceback (most recent call last): |
| ... |
| CmdError: Command failed: fdtget ../tests/test.dtb /go/hotspurs label -ts |
| Error at '/go/hotspurs': FDT_ERR_NOTFOUND |
| <BLANKLINE> |
| |
| Args: |
| node: Node to return label property from. |
| |
| Returns: |
| The value of the label property from the node. |
| |
| Raises: |
| CmdError: if the node or property does not exist. |
| """ |
| return self.GetString(node, 'label') |
| |
| def Copy(self, new_name): |
| """Make a copy of the FDT into another file, and return its object. |
| |
| >>> tools = Tools(cros_output.Output()) |
| >>> fdt = Fdt(tools, os.path.join(_base, '../tests/test.dtb')) |
| >>> our_copy = fdt.Copy(os.path.join(_base, '../tests/copy.dtb')) |
| >>> our_copy.PutString('/display', 'compatible', 'north') |
| >>> fdt.GetString('/display', 'compatible') |
| 'nvidia,tegra250-display' |
| >>> our_copy.GetString('/display', 'compatible') |
| 'north' |
| |
| This copies the FDT into a supplied file, then creates an FDT object to |
| access the copy. |
| |
| Args: |
| new_name: Filename to write copy to. |
| |
| Returns: |
| An Fdt object for the copy. |
| """ |
| shutil.copyfile(self.tools.Filename(self.fname), |
| self.tools.Filename(new_name)) |
| return Fdt(self.tools, new_name) |
| |
| def InsertNodes(self, node_list): |
| """Insert a list of new nodes into the FDT. |
| |
| >>> tools = Tools(cros_output.Output()) |
| >>> fdt = Fdt(tools, os.path.join(_base, '../tests/test.dtb')) |
| >>> arg = [{'path': '/new-node/walrus', 'int': 123}] |
| >>> arg.append({'path': '/new-node/walrus', 'bool': True, 'str': 'fred'}) |
| >>> arg.append({'path': '/new-node/seal', 'str': 'frankly'}) |
| >>> arg.append({'path': '/new-node/seal', 'list': [1, 2, 3]}) |
| >>> fdt.InsertNodes(arg) |
| >>> fdt.GetString('/new-node/walrus', 'str') |
| 'fred' |
| >>> fdt.GetInt('/new-node/walrus', 'int') |
| 123 |
| >>> fdt.GetBool('/new-node/walrus', 'bool') |
| True |
| >>> fdt.GetString('/new-node/seal', 'str') |
| 'frankly' |
| >>> fdt.GetIntList('/new-node/seal', 'list') |
| [1, 2, 3] |
| >>> arg = [{'path': '/new-node/dodgy', 'dict': {1: 'fred'}}] |
| >>> fdt.InsertNodes(arg) |
| Traceback (most recent call last): |
| ... |
| ValueError: Unrecognized type for prop 'dict', value '{1: 'fred'}' |
| |
| Args: |
| node_list: A list of nodes, each a dictionary containing the properties |
| of the node. One of the properties must be 'path' which is the full |
| path to the node. Supported types for property values are string, |
| boolean, integer and integer list. |
| |
| Raises: |
| ValueError: if an unrecognized type is provided. |
| """ |
| for node_props in node_list: |
| path = node_props['path'] |
| for prop, value in node_props.iteritems(): |
| if isinstance(value, int): |
| self.PutInteger(path, prop, value) |
| elif isinstance(value, str): |
| self.PutString(path, prop, value) |
| elif isinstance(value, bool): |
| self.PutBool(path, prop, value) |
| elif isinstance(value, list): |
| self.PutIntList(path, prop, value) |
| else: |
| raise ValueError("Unrecognized type for prop '%s', value '%s'" % |
| (prop, value)) |
| |
| def PutString(self, node, prop, value_str): |
| """Writes a string to a property in the fdt. |
| |
| >>> tools = Tools(cros_output.Output()) |
| >>> fdt = Fdt(tools, os.path.join(_base, '../tests/test.dtb')) |
| >>> our_copy = fdt.Copy(os.path.join(_base, '../tests/copy.dtb')) |
| >>> our_copy.PutString('/display', 'compatible', 'north') |
| >>> fdt.GetString('/display', 'compatible') |
| 'nvidia,tegra250-display' |
| >>> our_copy.PutString('/display', 'compatible', 'south') |
| >>> our_copy.GetString('/display', 'compatible') |
| 'south' |
| |
| Args: |
| node: Full path to node to look up. |
| prop: Property name to look up. |
| value_str: String to write. |
| """ |
| args = ['-p', '-t', 's', self.fname, node, prop, value_str] |
| self.tools.Run('fdtput', args) |
| |
| def PutInteger(self, node, prop, value_int): |
| """Writes a string to a property in the fdt. |
| |
| >>> tools = Tools(cros_output.Output()) |
| >>> fdt = Fdt(tools, os.path.join(_base, '../tests/test.dtb')) |
| >>> our_copy = fdt.Copy(os.path.join(_base, '../tests/copy.dtb')) |
| >>> our_copy.PutString('/display', 'compatible', 'north') |
| >>> fdt.GetString('/display', 'compatible') |
| 'nvidia,tegra250-display' |
| >>> our_copy.PutString('/display', 'compatible', 'south') |
| >>> our_copy.GetString('/display', 'compatible') |
| 'south' |
| |
| Args: |
| node: Full path to node to look up. |
| prop: Property name to look up. |
| value_int: Integer to write. |
| """ |
| args = ['-p', '-t', 'i', self.fname, node, prop, str(value_int)] |
| self.tools.Run('fdtput', args) |
| |
| def PutIntList(self, node, prop, int_list): |
| """Write a list of integers into an fdt property. |
| |
| >>> tools = Tools(cros_output.Output()) |
| >>> fdt = Fdt(tools, os.path.join(_base, '../tests/test.dtb')) |
| >>> fdt.GetIntList('/flash@0/shared-dev-cfg@180000', 'reg') |
| [1572864, 262144] |
| |
| >>> fdt.PutIntList('/flash/shared-dev-cfg', 'victoria', [1, 2, 3]) |
| |
| >>> fdt.GetIntList('/flash/shared-dev-cfg', 'victoria', 3) |
| [1, 2, 3] |
| |
| >>> fdt.PutIntList('/flash/shared-dev-cfg', 'victoria', [3]) |
| |
| >>> fdt.GetIntList('/flash/shared-dev-cfg', 'victoria', 1) |
| [3] |
| |
| >>> fdt.PutIntList('/flash/shared-dev-cfg', 'victoria', []) |
| |
| >>> fdt.GetIntList('/flash/shared-dev-cfg', 'victoria', 0) |
| [] |
| |
| Args: |
| node: Full path to node to look up. |
| prop: Property name to look up. |
| int_list: List of integers to write. |
| """ |
| value_list = [str(s) for s in int_list] |
| args = ['-p', '-t', 'i', self.fname, node, prop] |
| args.extend(value_list) |
| self.tools.Run('fdtput', args) |
| |
| def PutBytes(self, node, prop, bytes_list): |
| """Write a sequence of bytes into an fdt property. |
| |
| >>> tools = Tools(cros_output.Output()) |
| >>> fdt = Fdt(tools, os.path.join(_base, '../tests/test.dtb')) |
| >>> out_copy = fdt.Copy(os.path.join(_base, '../tests/copy.dtb')) |
| >>> out_copy.PutBytes('/', 'foo', (0, 1, 2, 3)) |
| >>> out_copy.GetProp('/', 'foo') |
| '66051' |
| >>> out_copy.PutBytes('/', 'foo2', (3, 2, 1, 0, 0, 1, 2, 3)) |
| >>> out_copy.GetProp('/', 'foo2') |
| '50462976 66051' |
| >>> out_copy.PutBytes('/', 'foo3', (3, 2, 1)) |
| >>> out_copy.GetProp('/', 'foo3') |
| '3 2 1' |
| |
| Args: |
| node: Full path to the node to look up. |
| prop: Property name to look up. |
| bytes_list: List of bytes to write. |
| """ |
| value_list = [str(s) for s in bytes_list] |
| args = ['-p', '-t', 'bi', self.fname, node, prop] |
| args.extend(value_list) |
| self.tools.Run('fdtput', args) |
| |
| def Compile(self, arch_dts): |
| """Compile an fdt .dts source file into a .dtb binary blob. |
| |
| >>> tools = Tools(cros_output.Output()) |
| >>> tools.PrepareOutputDir(None) |
| >>> src_path = '../tests/dts' |
| >>> src = os.path.join(src_path, 'source.dts') |
| >>> fdt = Fdt(tools, src) |
| |
| >>> fdt.Compile('') |
| >>> os.path.exists(os.path.join(tools.outdir, 'source.dtb')) |
| True |
| >>> if os.path.exists('../tests/source.dtb'): |
| ... os.remove('../tests/source.dtb') |
| |
| # Now check that search paths work |
| >>> fdt = Fdt(tools, '../tests/source.dts') |
| >>> fdt.Compile('') #doctest:+IGNORE_EXCEPTION_DETAIL |
| Traceback (most recent call last): |
| ... |
| CmdError: Command failed: dtc -I dts -o /tmp/tmpcYO7Fm/source.dtb -O \ |
| dtb -p 4096 ../tests/source.dts |
| DTC: dts->dtb on file "../tests/source.dts" |
| FATAL ERROR: Couldn't open "tegra250.dtsi": No such file or directory |
| <BLANKLINE> |
| >>> tools.search_paths = ['../tests/dts'] |
| >>> #fdt.Compile() |
| |
| Args: |
| arch_dts: Architecture/SOC .dtsi include file. |
| """ |
| if not self._is_compiled: |
| root, _ = os.path.splitext(self.fname) |
| |
| # Upstream U-Boot requires that we invoke the C preprocessor |
| data = self.tools.ReadFile(self.fname) |
| fname = self.fname |
| search_list = [] |
| if 'ARCH_CPU_DTS' in data or '#ifdef' in data: |
| fname = os.path.join(self.tools.outdir, os.path.basename(root) + |
| '.dts') |
| args = ['-E', '-P', '-x', 'assembler-with-cpp', '-D__ASSEMBLY__'] |
| args += ['-Ulinux'] |
| args += ['-DARCH_CPU_DTS="%s"' % arch_dts] |
| args += ['-DCONFIG_CHROMEOS'] |
| args += ['-o', fname, self.fname] |
| self.tools.Run('cc', args) |
| search_list.extend(['-i', os.path.dirname(self.fname)]) |
| |
| # If we don't have a directory, put it in the tools tempdir |
| out_fname = os.path.join(self.tools.outdir, os.path.basename(root) + |
| '.dtb') |
| for path in self.tools.search_paths: |
| search_list.extend(['-i', path]) |
| args = ['-I', 'dts', '-o', out_fname, '-O', 'dtb', '-p', '4096'] |
| args.extend(search_list) |
| args.append(fname) |
| self.tools.Run('dtc', args) |
| self.fname = out_fname |
| self._is_compiled = True |
| |
| |
| def main(): |
| """Main function for cros_bundle_firmware. |
| |
| This just lists out the children of the root node, along with all their |
| properties. |
| """ |
| parser = optparse.OptionParser() |
| parser.add_option('-d', '--dt', dest='fdt', type='string', action='store', |
| help='Path to fdt file to use (binary ,dtb)', |
| default='u-boot.dtb') |
| |
| (options, _) = parser.parse_args(sys.argv) |
| tools = Tools(cros_output.Output()) |
| fdt = Fdt(tools, options.fdt) |
| children = fdt.GetChildren('/') |
| for child in children: |
| print '%s: %s\n' % (child, fdt.GetProps('/' + child)) |
| |
| |
| def _Test(): |
| """Run any built-in tests.""" |
| assert doctest.testmod().failed == 0 |
| |
| if __name__ == '__main__': |
| # If first argument is --test, run testing code. |
| if sys.argv[1:2] == ['--test']: |
| _Test() |
| else: |
| main() |