merge_dtbs: Sort DTBOs based on needed symbols
Some DTBOs might use symbols from other DTBOs and require them to be applied before them. Sort them based on the __symbols__ and __fixups__ nodes, by creating a dependency graph. Change-Id: I40acf5da6b673b636a91f75ae3f3c634f2b5c505
This commit is contained in:
@@ -29,6 +29,7 @@
|
|||||||
# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
|
import graphlib
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import subprocess
|
import subprocess
|
||||||
@@ -291,6 +292,14 @@ class DeviceTree(DeviceTreeInfo):
|
|||||||
if not self.has_any_properties():
|
if not self.has_any_properties():
|
||||||
logging.warning('{} has no properties and may match with any other devicetree'.format(os.path.basename(self.filename)))
|
logging.warning('{} has no properties and may match with any other devicetree'.format(os.path.basename(self.filename)))
|
||||||
|
|
||||||
|
def list_props(self, node):
|
||||||
|
r = subprocess.run(["fdtget", "-p", self.filename, node],
|
||||||
|
check=False, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
|
||||||
|
if r.returncode != 0:
|
||||||
|
return []
|
||||||
|
out = r.stdout.decode("utf-8").strip()
|
||||||
|
return out.splitlines()[:-1]
|
||||||
|
|
||||||
def get_prop(self, node, property, prop_type='i', check_output=True):
|
def get_prop(self, node, property, prop_type='i', check_output=True):
|
||||||
r = subprocess.run(["fdtget", "-t", prop_type, self.filename, node, property],
|
r = subprocess.run(["fdtget", "-t", prop_type, self.filename, node, property],
|
||||||
check=check_output, stdout=subprocess.PIPE,
|
check=check_output, stdout=subprocess.PIPE,
|
||||||
@@ -458,6 +467,25 @@ class MergedDeviceTree(object):
|
|||||||
for mdt in self.merged_devicetrees:
|
for mdt in self.merged_devicetrees:
|
||||||
yield mdt.save(name, out_dir)
|
yield mdt.save(name, out_dir)
|
||||||
|
|
||||||
|
def create_adjacency(devicetrees):
|
||||||
|
graph = {}
|
||||||
|
symbol_map = {}
|
||||||
|
|
||||||
|
for dt in devicetrees:
|
||||||
|
for symbol in dt.list_props('/__symbols__'):
|
||||||
|
symbol_map.setdefault(symbol, []).append(dt.filename)
|
||||||
|
|
||||||
|
for dt in devicetrees:
|
||||||
|
graph[dt.filename] = set()
|
||||||
|
|
||||||
|
for fixup in dt.list_props('/__fixups__'):
|
||||||
|
if fixup not in symbol_map:
|
||||||
|
continue
|
||||||
|
|
||||||
|
graph[dt.filename].update(symbol_map[fixup])
|
||||||
|
|
||||||
|
return graph
|
||||||
|
|
||||||
def parse_dt_files(dt_folder):
|
def parse_dt_files(dt_folder):
|
||||||
devicetrees = []
|
devicetrees = []
|
||||||
for root, dirs, files in os.walk(dt_folder):
|
for root, dirs, files in os.walk(dt_folder):
|
||||||
@@ -468,6 +496,14 @@ def parse_dt_files(dt_folder):
|
|||||||
devicetrees.append(DeviceTree(filepath))
|
devicetrees.append(DeviceTree(filepath))
|
||||||
return devicetrees
|
return devicetrees
|
||||||
|
|
||||||
|
def parse_tech_dt_files(dt_folder):
|
||||||
|
devicetrees = parse_dt_files(dt_folder)
|
||||||
|
graph = create_adjacency(devicetrees)
|
||||||
|
order = graphlib.TopologicalSorter(graph).static_order()
|
||||||
|
order_index = {node: i for i, node in enumerate(order)}
|
||||||
|
devicetrees.sort(key=lambda dt: order_index[dt.filename])
|
||||||
|
return devicetrees
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description='Merge devicetree blobs of techpacks with Kernel Platform SoCs')
|
parser = argparse.ArgumentParser(description='Merge devicetree blobs of techpacks with Kernel Platform SoCs')
|
||||||
@@ -487,7 +523,7 @@ def main():
|
|||||||
logging.info('Parsed bases: \n{}'.format(all_bases))
|
logging.info('Parsed bases: \n{}'.format(all_bases))
|
||||||
|
|
||||||
logging.info('Parsing techpack dtb files from {}'.format(args.techpack))
|
logging.info('Parsing techpack dtb files from {}'.format(args.techpack))
|
||||||
techpacks = parse_dt_files(args.techpack)
|
techpacks = parse_tech_dt_files(args.techpack)
|
||||||
all_techpacks = '\n'.join(list(map(lambda x: str(x), techpacks)))
|
all_techpacks = '\n'.join(list(map(lambda x: str(x), techpacks)))
|
||||||
logging.info('Parsed techpacks: \n{}'.format(all_techpacks))
|
logging.info('Parsed techpacks: \n{}'.format(all_techpacks))
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user