1c55a50f5SSimon Glass# SPDX-License-Identifier: GPL-2.0+ 2c55a50f5SSimon Glass# Copyright 2018 Google, Inc 3c55a50f5SSimon Glass# Written by Simon Glass <sjg@chromium.org> 4c55a50f5SSimon Glass# 5c55a50f5SSimon Glass# Holds and modifies the state information held by binman 6c55a50f5SSimon Glass# 7c55a50f5SSimon Glass 8*e0e5df93SSimon Glassimport hashlib 9c55a50f5SSimon Glassimport re 10c55a50f5SSimon Glassfrom sets import Set 11c55a50f5SSimon Glass 12c55a50f5SSimon Glassimport os 13c55a50f5SSimon Glassimport tools 14c55a50f5SSimon Glass 15c55a50f5SSimon Glass# Records the device-tree files known to binman, keyed by filename (e.g. 16c55a50f5SSimon Glass# 'u-boot-spl.dtb') 17c55a50f5SSimon Glassfdt_files = {} 18c55a50f5SSimon Glass 19c55a50f5SSimon Glass# Arguments passed to binman to provide arguments to entries 20c55a50f5SSimon Glassentry_args = {} 21c55a50f5SSimon Glass 22539aece5SSimon Glass# True to use fake device-tree files for testing (see U_BOOT_DTB_DATA in 23539aece5SSimon Glass# ftest.py) 2493d17413SSimon Glassuse_fake_dtb = False 25539aece5SSimon Glass 262a72cc72SSimon Glass# Set of all device tree files references by images 272a72cc72SSimon Glassfdt_set = Set() 282a72cc72SSimon Glass 292a72cc72SSimon Glass# Same as above, but excluding the main one 302a72cc72SSimon Glassfdt_subset = Set() 312a72cc72SSimon Glass 322a72cc72SSimon Glass# The DTB which contains the full image information 332a72cc72SSimon Glassmain_dtb = None 342a72cc72SSimon Glass 35c55a50f5SSimon Glassdef GetFdt(fname): 36c55a50f5SSimon Glass """Get the Fdt object for a particular device-tree filename 37c55a50f5SSimon Glass 38c55a50f5SSimon Glass Binman keeps track of at least one device-tree file called u-boot.dtb but 39c55a50f5SSimon Glass can also have others (e.g. for SPL). This function looks up the given 40c55a50f5SSimon Glass filename and returns the associated Fdt object. 41c55a50f5SSimon Glass 42c55a50f5SSimon Glass Args: 43c55a50f5SSimon Glass fname: Filename to look up (e.g. 'u-boot.dtb'). 44c55a50f5SSimon Glass 45c55a50f5SSimon Glass Returns: 46c55a50f5SSimon Glass Fdt object associated with the filename 47c55a50f5SSimon Glass """ 48c55a50f5SSimon Glass return fdt_files[fname] 49c55a50f5SSimon Glass 50c55a50f5SSimon Glassdef GetFdtPath(fname): 51c55a50f5SSimon Glass """Get the full pathname of a particular Fdt object 52c55a50f5SSimon Glass 53c55a50f5SSimon Glass Similar to GetFdt() but returns the pathname associated with the Fdt. 54c55a50f5SSimon Glass 55c55a50f5SSimon Glass Args: 56c55a50f5SSimon Glass fname: Filename to look up (e.g. 'u-boot.dtb'). 57c55a50f5SSimon Glass 58c55a50f5SSimon Glass Returns: 59c55a50f5SSimon Glass Full path name to the associated Fdt 60c55a50f5SSimon Glass """ 61c55a50f5SSimon Glass return fdt_files[fname]._fname 62c55a50f5SSimon Glass 636ed45ba0SSimon Glassdef GetFdtContents(fname): 646ed45ba0SSimon Glass """Looks up the FDT pathname and contents 656ed45ba0SSimon Glass 666ed45ba0SSimon Glass This is used to obtain the Fdt pathname and contents when needed by an 676ed45ba0SSimon Glass entry. It supports a 'fake' dtb, allowing tests to substitute test data for 686ed45ba0SSimon Glass the real dtb. 696ed45ba0SSimon Glass 706ed45ba0SSimon Glass Args: 716ed45ba0SSimon Glass fname: Filename to look up (e.g. 'u-boot.dtb'). 726ed45ba0SSimon Glass 736ed45ba0SSimon Glass Returns: 746ed45ba0SSimon Glass tuple: 756ed45ba0SSimon Glass pathname to Fdt 766ed45ba0SSimon Glass Fdt data (as bytes) 776ed45ba0SSimon Glass """ 786ed45ba0SSimon Glass if fname in fdt_files and not use_fake_dtb: 796ed45ba0SSimon Glass pathname = GetFdtPath(fname) 806ed45ba0SSimon Glass data = GetFdt(fname).GetContents() 816ed45ba0SSimon Glass else: 826ed45ba0SSimon Glass pathname = tools.GetInputFilename(fname) 836ed45ba0SSimon Glass data = tools.ReadFile(pathname) 846ed45ba0SSimon Glass return pathname, data 856ed45ba0SSimon Glass 86c55a50f5SSimon Glassdef SetEntryArgs(args): 87c55a50f5SSimon Glass """Set the value of the entry args 88c55a50f5SSimon Glass 89c55a50f5SSimon Glass This sets up the entry_args dict which is used to supply entry arguments to 90c55a50f5SSimon Glass entries. 91c55a50f5SSimon Glass 92c55a50f5SSimon Glass Args: 93c55a50f5SSimon Glass args: List of entry arguments, each in the format "name=value" 94c55a50f5SSimon Glass """ 95c55a50f5SSimon Glass global entry_args 96c55a50f5SSimon Glass 97c55a50f5SSimon Glass entry_args = {} 98c55a50f5SSimon Glass if args: 99c55a50f5SSimon Glass for arg in args: 100c55a50f5SSimon Glass m = re.match('([^=]*)=(.*)', arg) 101c55a50f5SSimon Glass if not m: 102c55a50f5SSimon Glass raise ValueError("Invalid entry arguemnt '%s'" % arg) 103c55a50f5SSimon Glass entry_args[m.group(1)] = m.group(2) 104c55a50f5SSimon Glass 105c55a50f5SSimon Glassdef GetEntryArg(name): 106c55a50f5SSimon Glass """Get the value of an entry argument 107c55a50f5SSimon Glass 108c55a50f5SSimon Glass Args: 109c55a50f5SSimon Glass name: Name of argument to retrieve 110c55a50f5SSimon Glass 111c55a50f5SSimon Glass Returns: 112c55a50f5SSimon Glass String value of argument 113c55a50f5SSimon Glass """ 114c55a50f5SSimon Glass return entry_args.get(name) 1152a72cc72SSimon Glass 116539aece5SSimon Glassdef Prepare(images, dtb): 1172a72cc72SSimon Glass """Get device tree files ready for use 1182a72cc72SSimon Glass 1192a72cc72SSimon Glass This sets up a set of device tree files that can be retrieved by GetFdts(). 1202a72cc72SSimon Glass At present there is only one, that for U-Boot proper. 1212a72cc72SSimon Glass 1222a72cc72SSimon Glass Args: 123539aece5SSimon Glass images: List of images being used 1242a72cc72SSimon Glass dtb: Main dtb 1252a72cc72SSimon Glass """ 1262a72cc72SSimon Glass global fdt_set, fdt_subset, fdt_files, main_dtb 1272a72cc72SSimon Glass # Import these here in case libfdt.py is not available, in which case 1282a72cc72SSimon Glass # the above help option still works. 1292a72cc72SSimon Glass import fdt 1302a72cc72SSimon Glass import fdt_util 1312a72cc72SSimon Glass 1322a72cc72SSimon Glass # If we are updating the DTBs we need to put these updated versions 1332a72cc72SSimon Glass # where Entry_blob_dtb can find them. We can ignore 'u-boot.dtb' 1342a72cc72SSimon Glass # since it is assumed to be the one passed in with options.dt, and 1352a72cc72SSimon Glass # was handled just above. 1362a72cc72SSimon Glass main_dtb = dtb 1372a72cc72SSimon Glass fdt_files.clear() 1382a72cc72SSimon Glass fdt_files['u-boot.dtb'] = dtb 1392a72cc72SSimon Glass fdt_subset = Set() 140539aece5SSimon Glass if not use_fake_dtb: 141539aece5SSimon Glass for image in images.values(): 142539aece5SSimon Glass fdt_subset.update(image.GetFdtSet()) 143539aece5SSimon Glass fdt_subset.discard('u-boot.dtb') 144539aece5SSimon Glass for other_fname in fdt_subset: 145539aece5SSimon Glass infile = tools.GetInputFilename(other_fname) 146539aece5SSimon Glass other_fname_dtb = fdt_util.EnsureCompiled(infile) 147539aece5SSimon Glass out_fname = tools.GetOutputFilename('%s.out' % 148539aece5SSimon Glass os.path.split(other_fname)[1]) 149539aece5SSimon Glass tools.WriteFile(out_fname, tools.ReadFile(other_fname_dtb)) 150539aece5SSimon Glass other_dtb = fdt.FdtScan(out_fname) 151539aece5SSimon Glass fdt_files[other_fname] = other_dtb 1522a72cc72SSimon Glass 1532a72cc72SSimon Glassdef GetFdts(): 1542a72cc72SSimon Glass """Yield all device tree files being used by binman 1552a72cc72SSimon Glass 1562a72cc72SSimon Glass Yields: 1572a72cc72SSimon Glass Device trees being used (U-Boot proper, SPL, TPL) 1582a72cc72SSimon Glass """ 1592a72cc72SSimon Glass yield main_dtb 1606ed45ba0SSimon Glass for other_fname in fdt_subset: 1616ed45ba0SSimon Glass yield fdt_files[other_fname] 1622a72cc72SSimon Glass 163f46621d2SSimon Glassdef GetUpdateNodes(node): 164f46621d2SSimon Glass """Yield all the nodes that need to be updated in all device trees 165f46621d2SSimon Glass 166f46621d2SSimon Glass The property referenced by this node is added to any device trees which 167f46621d2SSimon Glass have the given node. Due to removable of unwanted notes, SPL and TPL may 168f46621d2SSimon Glass not have this node. 169f46621d2SSimon Glass 170f46621d2SSimon Glass Args: 171f46621d2SSimon Glass node: Node object in the main device tree to look up 172f46621d2SSimon Glass 173f46621d2SSimon Glass Yields: 174f46621d2SSimon Glass Node objects in each device tree that is in use (U-Boot proper, which 175f46621d2SSimon Glass is node, SPL and TPL) 176f46621d2SSimon Glass """ 177f46621d2SSimon Glass yield node 1786ed45ba0SSimon Glass for dtb in fdt_files.values(): 1796ed45ba0SSimon Glass if dtb != node.GetFdt(): 1806ed45ba0SSimon Glass other_node = dtb.GetNode(node.path) 1816ed45ba0SSimon Glass if other_node: 1826ed45ba0SSimon Glass yield other_node 183f46621d2SSimon Glass 184f46621d2SSimon Glassdef AddZeroProp(node, prop): 185f46621d2SSimon Glass """Add a new property to affected device trees with an integer value of 0. 186f46621d2SSimon Glass 187f46621d2SSimon Glass Args: 188f46621d2SSimon Glass prop_name: Name of property 189f46621d2SSimon Glass """ 190f46621d2SSimon Glass for n in GetUpdateNodes(node): 191f46621d2SSimon Glass n.AddZeroProp(prop) 192f46621d2SSimon Glass 1930a98b28bSSimon Glassdef AddSubnode(node, name): 1940a98b28bSSimon Glass """Add a new subnode to a node in affected device trees 1950a98b28bSSimon Glass 1960a98b28bSSimon Glass Args: 1970a98b28bSSimon Glass node: Node to add to 1980a98b28bSSimon Glass name: name of node to add 1990a98b28bSSimon Glass 2000a98b28bSSimon Glass Returns: 2010a98b28bSSimon Glass New subnode that was created in main tree 2020a98b28bSSimon Glass """ 2030a98b28bSSimon Glass first = None 2040a98b28bSSimon Glass for n in GetUpdateNodes(node): 2050a98b28bSSimon Glass subnode = n.AddSubnode(name) 2060a98b28bSSimon Glass if not first: 2070a98b28bSSimon Glass first = subnode 2080a98b28bSSimon Glass return first 2090a98b28bSSimon Glass 2100a98b28bSSimon Glassdef AddString(node, prop, value): 2110a98b28bSSimon Glass """Add a new string property to affected device trees 2120a98b28bSSimon Glass 2130a98b28bSSimon Glass Args: 2140a98b28bSSimon Glass prop_name: Name of property 2150a98b28bSSimon Glass value: String value (which will be \0-terminated in the DT) 2160a98b28bSSimon Glass """ 2170a98b28bSSimon Glass for n in GetUpdateNodes(node): 2180a98b28bSSimon Glass n.AddString(prop, value) 2190a98b28bSSimon Glass 220f46621d2SSimon Glassdef SetInt(node, prop, value): 221f46621d2SSimon Glass """Update an integer property in affected device trees with an integer value 222f46621d2SSimon Glass 223f46621d2SSimon Glass This is not allowed to change the size of the FDT. 224f46621d2SSimon Glass 225f46621d2SSimon Glass Args: 226f46621d2SSimon Glass prop_name: Name of property 227f46621d2SSimon Glass """ 228f46621d2SSimon Glass for n in GetUpdateNodes(node): 229f46621d2SSimon Glass n.SetInt(prop, value) 230*e0e5df93SSimon Glass 231*e0e5df93SSimon Glassdef CheckAddHashProp(node): 232*e0e5df93SSimon Glass hash_node = node.FindNode('hash') 233*e0e5df93SSimon Glass if hash_node: 234*e0e5df93SSimon Glass algo = hash_node.props.get('algo') 235*e0e5df93SSimon Glass if not algo: 236*e0e5df93SSimon Glass return "Missing 'algo' property for hash node" 237*e0e5df93SSimon Glass if algo.value == 'sha256': 238*e0e5df93SSimon Glass size = 32 239*e0e5df93SSimon Glass else: 240*e0e5df93SSimon Glass return "Unknown hash algorithm '%s'" % algo 241*e0e5df93SSimon Glass for n in GetUpdateNodes(hash_node): 242*e0e5df93SSimon Glass n.AddEmptyProp('value', size) 243*e0e5df93SSimon Glass 244*e0e5df93SSimon Glassdef CheckSetHashValue(node, get_data_func): 245*e0e5df93SSimon Glass hash_node = node.FindNode('hash') 246*e0e5df93SSimon Glass if hash_node: 247*e0e5df93SSimon Glass algo = hash_node.props.get('algo').value 248*e0e5df93SSimon Glass if algo == 'sha256': 249*e0e5df93SSimon Glass m = hashlib.sha256() 250*e0e5df93SSimon Glass m.update(get_data_func()) 251*e0e5df93SSimon Glass data = m.digest() 252*e0e5df93SSimon Glass for n in GetUpdateNodes(hash_node): 253*e0e5df93SSimon Glass n.SetData('value', data) 254