18f1da50cSSimon Glass# SPDX-License-Identifier: GPL-2.0+ 28f1da50cSSimon Glass# Copyright (c) 2018 Google, Inc 38f1da50cSSimon Glass# Written by Simon Glass <sjg@chromium.org> 48f1da50cSSimon Glass# 58f1da50cSSimon Glass# Base class for sections (collections of entries) 68f1da50cSSimon Glass# 78f1da50cSSimon Glass 88f1da50cSSimon Glassfrom __future__ import print_function 98f1da50cSSimon Glass 108f1da50cSSimon Glassfrom collections import OrderedDict 11539aece5SSimon Glassfrom sets import Set 128f1da50cSSimon Glassimport sys 138f1da50cSSimon Glass 148f1da50cSSimon Glassimport fdt_util 158f1da50cSSimon Glassimport re 16f46621d2SSimon Glassimport state 178f1da50cSSimon Glassimport tools 188f1da50cSSimon Glass 198f1da50cSSimon Glassclass Section(object): 208f1da50cSSimon Glass """A section which contains multiple entries 218f1da50cSSimon Glass 228f1da50cSSimon Glass A section represents a collection of entries. There must be one or more 238f1da50cSSimon Glass sections in an image. Sections are used to group entries together. 248f1da50cSSimon Glass 258f1da50cSSimon Glass Attributes: 268f1da50cSSimon Glass _node: Node object that contains the section definition in device tree 2708723a7aSSimon Glass _parent_section: Parent Section object which created this Section 288f1da50cSSimon Glass _size: Section size in bytes, or None if not known yet 298f1da50cSSimon Glass _align_size: Section size alignment, or None 308f1da50cSSimon Glass _pad_before: Number of bytes before the first entry starts. This 313ab9598dSSimon Glass effectively changes the place where entry offset 0 starts 328f1da50cSSimon Glass _pad_after: Number of bytes after the last entry ends. The last 338f1da50cSSimon Glass entry will finish on or before this boundary 348f1da50cSSimon Glass _pad_byte: Byte to use to pad the section where there is no entry 353ab9598dSSimon Glass _sort: True if entries should be sorted by offset, False if they 368f1da50cSSimon Glass must be in-order in the device tree description 378f1da50cSSimon Glass _skip_at_start: Number of bytes before the first entry starts. These 383ab9598dSSimon Glass effectively adjust the starting offset of entries. For example, 398f1da50cSSimon Glass if _pad_before is 16, then the first entry would start at 16. 403ab9598dSSimon Glass An entry with offset = 20 would in fact be written at offset 4 418f1da50cSSimon Glass in the image file. 428f1da50cSSimon Glass _end_4gb: Indicates that the section ends at the 4GB boundary. This is 433ab9598dSSimon Glass used for x86 images, which want to use offsets such that a memory 443ab9598dSSimon Glass address (like 0xff800000) is the first entry offset. This causes 453ab9598dSSimon Glass _skip_at_start to be set to the starting memory address. 46c8d48efbSSimon Glass _name_prefix: Prefix to add to the name of all entries within this 47c8d48efbSSimon Glass section 488f1da50cSSimon Glass _entries: OrderedDict() of entries 498f1da50cSSimon Glass """ 5008723a7aSSimon Glass def __init__(self, name, parent_section, node, image, test=False): 518f1da50cSSimon Glass global entry 528f1da50cSSimon Glass global Entry 538f1da50cSSimon Glass import entry 548f1da50cSSimon Glass from entry import Entry 558f1da50cSSimon Glass 5608723a7aSSimon Glass self._parent_section = parent_section 578122f396SSimon Glass self._name = name 588f1da50cSSimon Glass self._node = node 5908723a7aSSimon Glass self._image = image 603ab9598dSSimon Glass self._offset = 0 618f1da50cSSimon Glass self._size = None 628f1da50cSSimon Glass self._align_size = None 638f1da50cSSimon Glass self._pad_before = 0 648f1da50cSSimon Glass self._pad_after = 0 658f1da50cSSimon Glass self._pad_byte = 0 668f1da50cSSimon Glass self._sort = False 6794b57db0SJagdish Gediya self._skip_at_start = None 688f1da50cSSimon Glass self._end_4gb = False 69c8d48efbSSimon Glass self._name_prefix = '' 708f1da50cSSimon Glass self._entries = OrderedDict() 71*f8f8df6eSSimon Glass self._image_pos = None 728f1da50cSSimon Glass if not test: 738f1da50cSSimon Glass self._ReadNode() 748f1da50cSSimon Glass self._ReadEntries() 758f1da50cSSimon Glass 768f1da50cSSimon Glass def _ReadNode(self): 778f1da50cSSimon Glass """Read properties from the section node""" 788f1da50cSSimon Glass self._size = fdt_util.GetInt(self._node, 'size') 798f1da50cSSimon Glass self._align_size = fdt_util.GetInt(self._node, 'align-size') 808f1da50cSSimon Glass if tools.NotPowerOfTwo(self._align_size): 818f1da50cSSimon Glass self._Raise("Alignment size %s must be a power of two" % 828f1da50cSSimon Glass self._align_size) 838f1da50cSSimon Glass self._pad_before = fdt_util.GetInt(self._node, 'pad-before', 0) 848f1da50cSSimon Glass self._pad_after = fdt_util.GetInt(self._node, 'pad-after', 0) 858f1da50cSSimon Glass self._pad_byte = fdt_util.GetInt(self._node, 'pad-byte', 0) 863ab9598dSSimon Glass self._sort = fdt_util.GetBool(self._node, 'sort-by-offset') 878f1da50cSSimon Glass self._end_4gb = fdt_util.GetBool(self._node, 'end-at-4gb') 8894b57db0SJagdish Gediya self._skip_at_start = fdt_util.GetInt(self._node, 'skip-at-start') 898f1da50cSSimon Glass if self._end_4gb: 9094b57db0SJagdish Gediya if not self._size: 9194b57db0SJagdish Gediya self._Raise("Section size must be provided when using end-at-4gb") 9294b57db0SJagdish Gediya if self._skip_at_start is not None: 9394b57db0SJagdish Gediya self._Raise("Provide either 'end-at-4gb' or 'skip-at-start'") 9494b57db0SJagdish Gediya else: 958f1da50cSSimon Glass self._skip_at_start = 0x100000000 - self._size 9694b57db0SJagdish Gediya else: 9794b57db0SJagdish Gediya if self._skip_at_start is None: 9894b57db0SJagdish Gediya self._skip_at_start = 0 99c8d48efbSSimon Glass self._name_prefix = fdt_util.GetString(self._node, 'name-prefix') 1008f1da50cSSimon Glass 1018f1da50cSSimon Glass def _ReadEntries(self): 1028f1da50cSSimon Glass for node in self._node.subnodes: 103e0e5df93SSimon Glass if node.name == 'hash': 104e0e5df93SSimon Glass continue 105c8d48efbSSimon Glass entry = Entry.Create(self, node) 106c8d48efbSSimon Glass entry.SetPrefix(self._name_prefix) 107c8d48efbSSimon Glass self._entries[node.name] = entry 1088f1da50cSSimon Glass 109539aece5SSimon Glass def GetFdtSet(self): 110539aece5SSimon Glass """Get the set of device tree files used by this image""" 111539aece5SSimon Glass fdt_set = Set() 112539aece5SSimon Glass for entry in self._entries.values(): 113539aece5SSimon Glass fdt_set.update(entry.GetFdtSet()) 114539aece5SSimon Glass return fdt_set 115539aece5SSimon Glass 1168122f396SSimon Glass def SetOffset(self, offset): 1178122f396SSimon Glass self._offset = offset 1188122f396SSimon Glass 1190a98b28bSSimon Glass def ExpandEntries(self): 1200a98b28bSSimon Glass for entry in self._entries.values(): 1210a98b28bSSimon Glass entry.ExpandEntries() 1220a98b28bSSimon Glass 123078ab1a2SSimon Glass def AddMissingProperties(self): 1248122f396SSimon Glass """Add new properties to the device tree as needed for this entry""" 125dbf6be9fSSimon Glass for prop in ['offset', 'size', 'image-pos']: 1268122f396SSimon Glass if not prop in self._node.props: 127f46621d2SSimon Glass state.AddZeroProp(self._node, prop) 128e0e5df93SSimon Glass state.CheckAddHashProp(self._node) 129078ab1a2SSimon Glass for entry in self._entries.values(): 130078ab1a2SSimon Glass entry.AddMissingProperties() 131078ab1a2SSimon Glass 132078ab1a2SSimon Glass def SetCalculatedProperties(self): 133f46621d2SSimon Glass state.SetInt(self._node, 'offset', self._offset) 134f46621d2SSimon Glass state.SetInt(self._node, 'size', self._size) 135*f8f8df6eSSimon Glass image_pos = self._image_pos 136*f8f8df6eSSimon Glass if self._parent_section: 137*f8f8df6eSSimon Glass image_pos -= self._parent_section.GetRootSkipAtStart() 138*f8f8df6eSSimon Glass state.SetInt(self._node, 'image-pos', image_pos) 139078ab1a2SSimon Glass for entry in self._entries.values(): 140078ab1a2SSimon Glass entry.SetCalculatedProperties() 141078ab1a2SSimon Glass 142ecab8973SSimon Glass def ProcessFdt(self, fdt): 143ecab8973SSimon Glass todo = self._entries.values() 144ecab8973SSimon Glass for passnum in range(3): 145ecab8973SSimon Glass next_todo = [] 146ecab8973SSimon Glass for entry in todo: 147ecab8973SSimon Glass if not entry.ProcessFdt(fdt): 148ecab8973SSimon Glass next_todo.append(entry) 149ecab8973SSimon Glass todo = next_todo 150ecab8973SSimon Glass if not todo: 151ecab8973SSimon Glass break 152ecab8973SSimon Glass if todo: 153ecab8973SSimon Glass self._Raise('Internal error: Could not complete processing of Fdt: ' 154ecab8973SSimon Glass 'remaining %s' % todo) 155ecab8973SSimon Glass return True 156ecab8973SSimon Glass 1578f1da50cSSimon Glass def CheckSize(self): 1588f1da50cSSimon Glass """Check that the section contents does not exceed its size, etc.""" 1598f1da50cSSimon Glass contents_size = 0 1608f1da50cSSimon Glass for entry in self._entries.values(): 1613ab9598dSSimon Glass contents_size = max(contents_size, entry.offset + entry.size) 1628f1da50cSSimon Glass 1638f1da50cSSimon Glass contents_size -= self._skip_at_start 1648f1da50cSSimon Glass 1658f1da50cSSimon Glass size = self._size 1668f1da50cSSimon Glass if not size: 1678f1da50cSSimon Glass size = self._pad_before + contents_size + self._pad_after 1688f1da50cSSimon Glass size = tools.Align(size, self._align_size) 1698f1da50cSSimon Glass 1708f1da50cSSimon Glass if self._size and contents_size > self._size: 1718f1da50cSSimon Glass self._Raise("contents size %#x (%d) exceeds section size %#x (%d)" % 1728f1da50cSSimon Glass (contents_size, contents_size, self._size, self._size)) 1738f1da50cSSimon Glass if not self._size: 1748f1da50cSSimon Glass self._size = size 1758f1da50cSSimon Glass if self._size != tools.Align(self._size, self._align_size): 1768f1da50cSSimon Glass self._Raise("Size %#x (%d) does not match align-size %#x (%d)" % 1778f1da50cSSimon Glass (self._size, self._size, self._align_size, self._align_size)) 1788f1da50cSSimon Glass return size 1798f1da50cSSimon Glass 1808f1da50cSSimon Glass def _Raise(self, msg): 1818f1da50cSSimon Glass """Raises an error for this section 1828f1da50cSSimon Glass 1838f1da50cSSimon Glass Args: 1848f1da50cSSimon Glass msg: Error message to use in the raise string 1858f1da50cSSimon Glass Raises: 1868f1da50cSSimon Glass ValueError() 1878f1da50cSSimon Glass """ 1888f1da50cSSimon Glass raise ValueError("Section '%s': %s" % (self._node.path, msg)) 1898f1da50cSSimon Glass 1908f1da50cSSimon Glass def GetPath(self): 1918f1da50cSSimon Glass """Get the path of an image (in the FDT) 1928f1da50cSSimon Glass 1938f1da50cSSimon Glass Returns: 1948f1da50cSSimon Glass Full path of the node for this image 1958f1da50cSSimon Glass """ 1968f1da50cSSimon Glass return self._node.path 1978f1da50cSSimon Glass 1988f1da50cSSimon Glass def FindEntryType(self, etype): 1998f1da50cSSimon Glass """Find an entry type in the section 2008f1da50cSSimon Glass 2018f1da50cSSimon Glass Args: 2028f1da50cSSimon Glass etype: Entry type to find 2038f1da50cSSimon Glass Returns: 2048f1da50cSSimon Glass entry matching that type, or None if not found 2058f1da50cSSimon Glass """ 2068f1da50cSSimon Glass for entry in self._entries.values(): 2078f1da50cSSimon Glass if entry.etype == etype: 2088f1da50cSSimon Glass return entry 2098f1da50cSSimon Glass return None 2108f1da50cSSimon Glass 2118f1da50cSSimon Glass def GetEntryContents(self): 2128f1da50cSSimon Glass """Call ObtainContents() for each entry 2138f1da50cSSimon Glass 2148f1da50cSSimon Glass This calls each entry's ObtainContents() a few times until they all 2158f1da50cSSimon Glass return True. We stop calling an entry's function once it returns 2168f1da50cSSimon Glass True. This allows the contents of one entry to depend on another. 2178f1da50cSSimon Glass 2188f1da50cSSimon Glass After 3 rounds we give up since it's likely an error. 2198f1da50cSSimon Glass """ 2208f1da50cSSimon Glass todo = self._entries.values() 2218f1da50cSSimon Glass for passnum in range(3): 2228f1da50cSSimon Glass next_todo = [] 2238f1da50cSSimon Glass for entry in todo: 2248f1da50cSSimon Glass if not entry.ObtainContents(): 2258f1da50cSSimon Glass next_todo.append(entry) 2268f1da50cSSimon Glass todo = next_todo 2278f1da50cSSimon Glass if not todo: 2288f1da50cSSimon Glass break 229736bb0aeSSimon Glass if todo: 230736bb0aeSSimon Glass self._Raise('Internal error: Could not complete processing of ' 231736bb0aeSSimon Glass 'contents: remaining %s' % todo) 232736bb0aeSSimon Glass return True 2338f1da50cSSimon Glass 2343ab9598dSSimon Glass def _SetEntryOffsetSize(self, name, offset, size): 2353ab9598dSSimon Glass """Set the offset and size of an entry 2368f1da50cSSimon Glass 2378f1da50cSSimon Glass Args: 2388f1da50cSSimon Glass name: Entry name to update 2393ab9598dSSimon Glass offset: New offset 2408f1da50cSSimon Glass size: New size 2418f1da50cSSimon Glass """ 2428f1da50cSSimon Glass entry = self._entries.get(name) 2438f1da50cSSimon Glass if not entry: 2443ab9598dSSimon Glass self._Raise("Unable to set offset/size for unknown entry '%s'" % 2453ab9598dSSimon Glass name) 2463ab9598dSSimon Glass entry.SetOffsetSize(self._skip_at_start + offset, size) 2478f1da50cSSimon Glass 2483ab9598dSSimon Glass def GetEntryOffsets(self): 2493ab9598dSSimon Glass """Handle entries that want to set the offset/size of other entries 2508f1da50cSSimon Glass 2513ab9598dSSimon Glass This calls each entry's GetOffsets() method. If it returns a list 2528f1da50cSSimon Glass of entries to update, it updates them. 2538f1da50cSSimon Glass """ 2548f1da50cSSimon Glass for entry in self._entries.values(): 2553ab9598dSSimon Glass offset_dict = entry.GetOffsets() 2563ab9598dSSimon Glass for name, info in offset_dict.iteritems(): 2573ab9598dSSimon Glass self._SetEntryOffsetSize(name, *info) 2588f1da50cSSimon Glass 2598f1da50cSSimon Glass def PackEntries(self): 2608f1da50cSSimon Glass """Pack all entries into the section""" 2613ab9598dSSimon Glass offset = self._skip_at_start 2628f1da50cSSimon Glass for entry in self._entries.values(): 2633ab9598dSSimon Glass offset = entry.Pack(offset) 2643ab9598dSSimon Glass self._size = self.CheckSize() 2658f1da50cSSimon Glass 2668f1da50cSSimon Glass def _SortEntries(self): 2673ab9598dSSimon Glass """Sort entries by offset""" 2683ab9598dSSimon Glass entries = sorted(self._entries.values(), key=lambda entry: entry.offset) 2698f1da50cSSimon Glass self._entries.clear() 2708f1da50cSSimon Glass for entry in entries: 2718f1da50cSSimon Glass self._entries[entry._node.name] = entry 2728f1da50cSSimon Glass 273ba64a0bbSSimon Glass def _ExpandEntries(self): 274ba64a0bbSSimon Glass """Expand any entries that are permitted to""" 275ba64a0bbSSimon Glass exp_entry = None 276ba64a0bbSSimon Glass for entry in self._entries.values(): 277ba64a0bbSSimon Glass if exp_entry: 278ba64a0bbSSimon Glass exp_entry.ExpandToLimit(entry.offset) 279ba64a0bbSSimon Glass exp_entry = None 280ba64a0bbSSimon Glass if entry.expand_size: 281ba64a0bbSSimon Glass exp_entry = entry 282ba64a0bbSSimon Glass if exp_entry: 283ba64a0bbSSimon Glass exp_entry.ExpandToLimit(self._size) 284ba64a0bbSSimon Glass 2858f1da50cSSimon Glass def CheckEntries(self): 286ba64a0bbSSimon Glass """Check that entries do not overlap or extend outside the section 287ba64a0bbSSimon Glass 288ba64a0bbSSimon Glass This also sorts entries, if needed and expands 289ba64a0bbSSimon Glass """ 2908f1da50cSSimon Glass if self._sort: 2918f1da50cSSimon Glass self._SortEntries() 292ba64a0bbSSimon Glass self._ExpandEntries() 2933ab9598dSSimon Glass offset = 0 2948f1da50cSSimon Glass prev_name = 'None' 2958f1da50cSSimon Glass for entry in self._entries.values(): 2963ab9598dSSimon Glass entry.CheckOffset() 2973ab9598dSSimon Glass if (entry.offset < self._skip_at_start or 298b4e1a38cSSimon Glass entry.offset + entry.size > self._skip_at_start + self._size): 2993ab9598dSSimon Glass entry.Raise("Offset %#x (%d) is outside the section starting " 3008f1da50cSSimon Glass "at %#x (%d)" % 3013ab9598dSSimon Glass (entry.offset, entry.offset, self._skip_at_start, 3028f1da50cSSimon Glass self._skip_at_start)) 3033ab9598dSSimon Glass if entry.offset < offset: 3043ab9598dSSimon Glass entry.Raise("Offset %#x (%d) overlaps with previous entry '%s' " 3058f1da50cSSimon Glass "ending at %#x (%d)" % 3063ab9598dSSimon Glass (entry.offset, entry.offset, prev_name, offset, offset)) 3073ab9598dSSimon Glass offset = entry.offset + entry.size 3088f1da50cSSimon Glass prev_name = entry.GetPath() 3098f1da50cSSimon Glass 310dbf6be9fSSimon Glass def SetImagePos(self, image_pos): 311dbf6be9fSSimon Glass self._image_pos = image_pos 312dbf6be9fSSimon Glass for entry in self._entries.values(): 313dbf6be9fSSimon Glass entry.SetImagePos(image_pos) 314dbf6be9fSSimon Glass 3158f1da50cSSimon Glass def ProcessEntryContents(self): 3168f1da50cSSimon Glass """Call the ProcessContents() method for each entry 3178f1da50cSSimon Glass 3188f1da50cSSimon Glass This is intended to adjust the contents as needed by the entry type. 3198f1da50cSSimon Glass """ 3208f1da50cSSimon Glass for entry in self._entries.values(): 3218f1da50cSSimon Glass entry.ProcessContents() 3228f1da50cSSimon Glass 3238f1da50cSSimon Glass def WriteSymbols(self): 3248f1da50cSSimon Glass """Write symbol values into binary files for access at run time""" 3258f1da50cSSimon Glass for entry in self._entries.values(): 3268f1da50cSSimon Glass entry.WriteSymbols(self) 3278f1da50cSSimon Glass 3283ab9598dSSimon Glass def BuildSection(self, fd, base_offset): 3298f1da50cSSimon Glass """Write the section to a file""" 3303ab9598dSSimon Glass fd.seek(base_offset) 3318f1da50cSSimon Glass fd.write(self.GetData()) 3328f1da50cSSimon Glass 3338f1da50cSSimon Glass def GetData(self): 3348122f396SSimon Glass """Get the contents of the section""" 3358f1da50cSSimon Glass section_data = chr(self._pad_byte) * self._size 3368f1da50cSSimon Glass 3378f1da50cSSimon Glass for entry in self._entries.values(): 3388f1da50cSSimon Glass data = entry.GetData() 3393ab9598dSSimon Glass base = self._pad_before + entry.offset - self._skip_at_start 3408f1da50cSSimon Glass section_data = (section_data[:base] + data + 3418f1da50cSSimon Glass section_data[base + len(data):]) 3428f1da50cSSimon Glass return section_data 3438f1da50cSSimon Glass 3448f1da50cSSimon Glass def LookupSymbol(self, sym_name, optional, msg): 3458f1da50cSSimon Glass """Look up a symbol in an ELF file 3468f1da50cSSimon Glass 3478f1da50cSSimon Glass Looks up a symbol in an ELF file. Only entry types which come from an 3488f1da50cSSimon Glass ELF image can be used by this function. 3498f1da50cSSimon Glass 3503ab9598dSSimon Glass At present the only entry property supported is offset. 3518f1da50cSSimon Glass 3528f1da50cSSimon Glass Args: 3538f1da50cSSimon Glass sym_name: Symbol name in the ELF file to look up in the format 3548f1da50cSSimon Glass _binman_<entry>_prop_<property> where <entry> is the name of 3558f1da50cSSimon Glass the entry and <property> is the property to find (e.g. 3563ab9598dSSimon Glass _binman_u_boot_prop_offset). As a special case, you can append 3578f1da50cSSimon Glass _any to <entry> to have it search for any matching entry. E.g. 3583ab9598dSSimon Glass _binman_u_boot_any_prop_offset will match entries called u-boot, 3598f1da50cSSimon Glass u-boot-img and u-boot-nodtb) 3608f1da50cSSimon Glass optional: True if the symbol is optional. If False this function 3618f1da50cSSimon Glass will raise if the symbol is not found 3628f1da50cSSimon Glass msg: Message to display if an error occurs 3638f1da50cSSimon Glass 3648f1da50cSSimon Glass Returns: 3658f1da50cSSimon Glass Value that should be assigned to that symbol, or None if it was 3668f1da50cSSimon Glass optional and not found 3678f1da50cSSimon Glass 3688f1da50cSSimon Glass Raises: 3698f1da50cSSimon Glass ValueError if the symbol is invalid or not found, or references a 3708f1da50cSSimon Glass property which is not supported 3718f1da50cSSimon Glass """ 3728f1da50cSSimon Glass m = re.match(r'^_binman_(\w+)_prop_(\w+)$', sym_name) 3738f1da50cSSimon Glass if not m: 3748f1da50cSSimon Glass raise ValueError("%s: Symbol '%s' has invalid format" % 3758f1da50cSSimon Glass (msg, sym_name)) 3768f1da50cSSimon Glass entry_name, prop_name = m.groups() 3778f1da50cSSimon Glass entry_name = entry_name.replace('_', '-') 3788f1da50cSSimon Glass entry = self._entries.get(entry_name) 3798f1da50cSSimon Glass if not entry: 3808f1da50cSSimon Glass if entry_name.endswith('-any'): 3818f1da50cSSimon Glass root = entry_name[:-4] 3828f1da50cSSimon Glass for name in self._entries: 3838f1da50cSSimon Glass if name.startswith(root): 3848f1da50cSSimon Glass rest = name[len(root):] 3858f1da50cSSimon Glass if rest in ['', '-img', '-nodtb']: 3868f1da50cSSimon Glass entry = self._entries[name] 3878f1da50cSSimon Glass if not entry: 3888f1da50cSSimon Glass err = ("%s: Entry '%s' not found in list (%s)" % 3898f1da50cSSimon Glass (msg, entry_name, ','.join(self._entries.keys()))) 3908f1da50cSSimon Glass if optional: 3918f1da50cSSimon Glass print('Warning: %s' % err, file=sys.stderr) 3928f1da50cSSimon Glass return None 3938f1da50cSSimon Glass raise ValueError(err) 3943ab9598dSSimon Glass if prop_name == 'offset': 3953ab9598dSSimon Glass return entry.offset 396dbf6be9fSSimon Glass elif prop_name == 'image_pos': 397dbf6be9fSSimon Glass return entry.image_pos 3988f1da50cSSimon Glass else: 3998f1da50cSSimon Glass raise ValueError("%s: No such property '%s'" % (msg, prop_name)) 4008f1da50cSSimon Glass 4018f1da50cSSimon Glass def GetEntries(self): 4028122f396SSimon Glass """Get the number of entries in a section 4038122f396SSimon Glass 4048122f396SSimon Glass Returns: 4058122f396SSimon Glass Number of entries in a section 4068122f396SSimon Glass """ 4078f1da50cSSimon Glass return self._entries 4083b0c3821SSimon Glass 4098122f396SSimon Glass def GetSize(self): 4108122f396SSimon Glass """Get the size of a section in bytes 4118122f396SSimon Glass 4128122f396SSimon Glass This is only meaningful if the section has a pre-defined size, or the 4138122f396SSimon Glass entries within it have been packed, so that the size has been 4148122f396SSimon Glass calculated. 4158122f396SSimon Glass 4168122f396SSimon Glass Returns: 4178122f396SSimon Glass Entry size in bytes 4188122f396SSimon Glass """ 4198122f396SSimon Glass return self._size 4208122f396SSimon Glass 4213b0c3821SSimon Glass def WriteMap(self, fd, indent): 4223b0c3821SSimon Glass """Write a map of the section to a .map file 4233b0c3821SSimon Glass 4243b0c3821SSimon Glass Args: 4253b0c3821SSimon Glass fd: File to write the map to 4263b0c3821SSimon Glass """ 4271be70d20SSimon Glass Entry.WriteMapLine(fd, indent, self._name, self._offset, self._size, 4281be70d20SSimon Glass self._image_pos) 4293b0c3821SSimon Glass for entry in self._entries.values(): 4308122f396SSimon Glass entry.WriteMap(fd, indent + 1) 43124d0d3c3SSimon Glass 43224d0d3c3SSimon Glass def GetContentsByPhandle(self, phandle, source_entry): 43324d0d3c3SSimon Glass """Get the data contents of an entry specified by a phandle 43424d0d3c3SSimon Glass 43524d0d3c3SSimon Glass This uses a phandle to look up a node and and find the entry 43624d0d3c3SSimon Glass associated with it. Then it returnst he contents of that entry. 43724d0d3c3SSimon Glass 43824d0d3c3SSimon Glass Args: 43924d0d3c3SSimon Glass phandle: Phandle to look up (integer) 44024d0d3c3SSimon Glass source_entry: Entry containing that phandle (used for error 44124d0d3c3SSimon Glass reporting) 44224d0d3c3SSimon Glass 44324d0d3c3SSimon Glass Returns: 44424d0d3c3SSimon Glass data from associated entry (as a string), or None if not found 44524d0d3c3SSimon Glass """ 44624d0d3c3SSimon Glass node = self._node.GetFdt().LookupPhandle(phandle) 44724d0d3c3SSimon Glass if not node: 44824d0d3c3SSimon Glass source_entry.Raise("Cannot find node for phandle %d" % phandle) 44924d0d3c3SSimon Glass for entry in self._entries.values(): 45024d0d3c3SSimon Glass if entry._node == node: 451*f8f8df6eSSimon Glass return entry.GetData() 45224d0d3c3SSimon Glass source_entry.Raise("Cannot find entry for node '%s'" % node.name) 453ba64a0bbSSimon Glass 454ba64a0bbSSimon Glass def ExpandSize(self, size): 455ba64a0bbSSimon Glass if size != self._size: 456ba64a0bbSSimon Glass self._size = size 457*f8f8df6eSSimon Glass 458*f8f8df6eSSimon Glass def GetRootSkipAtStart(self): 459*f8f8df6eSSimon Glass if self._parent_section: 460*f8f8df6eSSimon Glass return self._parent_section.GetRootSkipAtStart() 461*f8f8df6eSSimon Glass return self._skip_at_start 462*f8f8df6eSSimon Glass 463*f8f8df6eSSimon Glass def GetImageSize(self): 464*f8f8df6eSSimon Glass return self._image._size 465