1# SPDX-License-Identifier: GPL-2.0+ 2# Copyright (c) 2018 Google, Inc 3# Written by Simon Glass <sjg@chromium.org> 4 5"""# Entry-type module for a full map of the firmware image 6 7This handles putting an FDT into the image with just the information about the 8image. 9""" 10 11from binman.entry import Entry 12from patman import tools 13from patman import tout 14 15FDTMAP_MAGIC = b'_FDTMAP_' 16FDTMAP_HDR_LEN = 16 17 18def LocateFdtmap(data): 19 """Search an image for an fdt map 20 21 Args: 22 data: Data to search 23 24 Returns: 25 Position of fdt map in data, or None if not found. Note that the 26 position returned is of the FDT header, i.e. before the FDT data 27 """ 28 hdr_pos = data.find(FDTMAP_MAGIC) 29 size = len(data) 30 if hdr_pos != -1: 31 hdr = data[hdr_pos:hdr_pos + FDTMAP_HDR_LEN] 32 if len(hdr) == FDTMAP_HDR_LEN: 33 return hdr_pos 34 return None 35 36class Entry_fdtmap(Entry): 37 """An entry which contains an FDT map 38 39 Properties / Entry arguments: 40 None 41 42 An FDT map is just a header followed by an FDT containing a list of all the 43 entries in the image. The root node corresponds to the image node in the 44 original FDT, and an image-name property indicates the image name in that 45 original tree. 46 47 The header is the string _FDTMAP_ followed by 8 unused bytes. 48 49 When used, this entry will be populated with an FDT map which reflects the 50 entries in the current image. Hierarchy is preserved, and all offsets and 51 sizes are included. 52 53 Note that the -u option must be provided to ensure that binman updates the 54 FDT with the position of each entry. 55 56 Example output for a simple image with U-Boot and an FDT map: 57 58 / { 59 image-name = "binman"; 60 size = <0x00000112>; 61 image-pos = <0x00000000>; 62 offset = <0x00000000>; 63 u-boot { 64 size = <0x00000004>; 65 image-pos = <0x00000000>; 66 offset = <0x00000000>; 67 }; 68 fdtmap { 69 size = <0x0000010e>; 70 image-pos = <0x00000004>; 71 offset = <0x00000004>; 72 }; 73 }; 74 75 If allow-repack is used then 'orig-offset' and 'orig-size' properties are 76 added as necessary. See the binman README. 77 """ 78 def __init__(self, section, etype, node): 79 # Put these here to allow entry-docs and help to work without libfdt 80 global libfdt 81 global state 82 global Fdt 83 84 import libfdt 85 from binman import state 86 from dtoc.fdt import Fdt 87 88 super().__init__(section, etype, node) 89 90 def _GetFdtmap(self): 91 """Build an FDT map from the entries in the current image 92 93 Returns: 94 FDT map binary data 95 """ 96 def _AddNode(node): 97 """Add a node to the FDT map""" 98 for pname, prop in node.props.items(): 99 fsw.property(pname, prop.bytes) 100 for subnode in node.subnodes: 101 with fsw.add_node(subnode.name): 102 _AddNode(subnode) 103 104 data = state.GetFdtContents('fdtmap')[1] 105 # If we have an fdtmap it means that we are using this as the 106 # fdtmap for this image. 107 if data is None: 108 # Get the FDT data into an Fdt object 109 data = state.GetFdtContents()[1] 110 infdt = Fdt.FromData(data) 111 infdt.Scan() 112 113 # Find the node for the image containing the Fdt-map entry 114 path = self.section.GetPath() 115 self.Detail("Fdtmap: Using section '%s' (path '%s')" % 116 (self.section.name, path)) 117 node = infdt.GetNode(path) 118 if not node: 119 self.Raise("Internal error: Cannot locate node for path '%s'" % 120 path) 121 122 # Build a new tree with all nodes and properties starting from that 123 # node 124 fsw = libfdt.FdtSw() 125 fsw.finish_reservemap() 126 with fsw.add_node(''): 127 fsw.property_string('image-node', node.name) 128 _AddNode(node) 129 fdt = fsw.as_fdt() 130 131 # Pack this new FDT and return its contents 132 fdt.pack() 133 outfdt = Fdt.FromData(fdt.as_bytearray()) 134 data = outfdt.GetContents() 135 data = FDTMAP_MAGIC + tools.GetBytes(0, 8) + data 136 return data 137 138 def ObtainContents(self): 139 """Obtain a placeholder for the fdt-map contents""" 140 self.SetContents(self._GetFdtmap()) 141 return True 142 143 def ProcessContents(self): 144 """Write an updated version of the FDT map to this entry 145 146 This is necessary since new data may have been written back to it during 147 processing, e.g. the image-pos properties. 148 """ 149 return self.ProcessContentsUpdate(self._GetFdtmap()) 150