blob: a293f572d5b8a0c4582056d847d7db0fabf36255 [file] [log] [blame]
# Copyright 2017 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.
"""Chrome OS Configuration access library (FDT).
Chrome OS Configuration access library for a master configuration using flat
device tree.
"""
from __future__ import print_function
from collections import OrderedDict
from . import fdt
import libcros_config_host
class CrosConfigFdt(libcros_config_host.CrosConfigImpl):
"""Flat Device Tree implementation of CrosConfig.
This uses a device-tree file to hold this config. This provides efficient
run-time access since there is no need to parse the whole file. It also
supports links from one node to another, reducing redundancy in the config.
Properties:
phandle_to_node: Map of phandles to the assocated CrosConfigImpl.Node:
key: Integer phandle value (>= 1)
value: Associated CrosConfigImpl.Node object
family: Family node (CrosConigImpl.Node object)
"""
def __init__(self, infile):
super(CrosConfigFdt, self).__init__(infile)
self._fdt = fdt.Fdt(self.infile)
self._fdt.Scan()
self.phandle_to_node = {}
self.root = CrosConfigFdt.MakeNode(self, self._fdt.GetRoot())
self.family = self.root.subnodes['chromeos'].subnodes['family']
@staticmethod
def MakeNode(cros_config, fdt_node):
"""Make a new Node in the tree
This create a new Node or Model object in the tree and recursively adds all
subnodes to it. Any phandles found update the phandle_to_node map.
Args:
cros_config: CrosConfig object
fdt_node: fdt.Node object containing the device-tree node
"""
node = CrosConfigFdt.Node(cros_config, fdt_node)
if fdt_node.parent and fdt_node.parent.name == 'models':
cros_config.models[node.name] = node
if 'phandle' in node.properties:
phandle = fdt_node.props['phandle'].GetPhandle()
cros_config.phandle_to_node[phandle] = node
node.default = node.FollowPhandle('default')
for subnode in fdt_node.subnodes.values():
node.subnodes[subnode.name] = CrosConfigFdt.MakeNode(cros_config, subnode)
node.ScanSubnodes()
return node
class Node(libcros_config_host.CrosConfigImpl.Node):
"""FDT implementation of a node"""
def __init__(self, cros_config, fdt_node):
super(CrosConfigFdt.Node, self).__init__(cros_config)
self._fdt_node = fdt_node
self.name = fdt_node.name
# Subnodes are set up in Model.ScanSubnodes()
self.properties = OrderedDict((n, CrosConfigFdt.Property(p))
for n, p in fdt_node.props.iteritems())
def GetPath(self):
"""Get the full path to a node.
Returns:
path to node as a string
"""
return self._fdt_node.path
def FollowPhandle(self, prop_name):
"""Follow a property's phandle
Args:
prop_name: Property name to check
Returns:
Node that the property's phandle points to, or None if none
"""
prop = self.properties.get(prop_name)
if not prop:
return None
return self.cros_config.phandle_to_node[prop.GetPhandle()]
class Property(libcros_config_host.CrosConfigImpl.Property):
"""FDT implementation of a property
Properties:
name: The name of the property.
value: The value of the property.
type: The Python type of the property.
"""
def __init__(self, fdt_prop):
super(CrosConfigFdt.Property, self).__init__()
self._fdt_prop = fdt_prop
self.name = fdt_prop.name
self.value = fdt_prop.value
self.type = fdt_prop.type
def GetPhandle(self):
"""Get the value of a property as a phandle
Returns:
Property's phandle as an integer (> 0)
"""
return self._fdt_prop.GetPhandle()