123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- # SPDX-License-Identifier: GPL-2.0+
- # Copyright (c) 2018 Google, Inc
- # Written by Simon Glass <sjg@chromium.org>
- """# Entry-type module for a full map of the firmware image
- This handles putting an FDT into the image with just the information about the
- image.
- """
- from binman.entry import Entry
- from patman import tools
- from patman import tout
- FDTMAP_MAGIC = b'_FDTMAP_'
- FDTMAP_HDR_LEN = 16
- def LocateFdtmap(data):
- """Search an image for an fdt map
- Args:
- data: Data to search
- Returns:
- Position of fdt map in data, or None if not found. Note that the
- position returned is of the FDT header, i.e. before the FDT data
- """
- hdr_pos = data.find(FDTMAP_MAGIC)
- size = len(data)
- if hdr_pos != -1:
- hdr = data[hdr_pos:hdr_pos + FDTMAP_HDR_LEN]
- if len(hdr) == FDTMAP_HDR_LEN:
- return hdr_pos
- return None
- class Entry_fdtmap(Entry):
- """An entry which contains an FDT map
- Properties / Entry arguments:
- None
- An FDT map is just a header followed by an FDT containing a list of all the
- entries in the image. The root node corresponds to the image node in the
- original FDT, and an image-name property indicates the image name in that
- original tree.
- The header is the string _FDTMAP_ followed by 8 unused bytes.
- When used, this entry will be populated with an FDT map which reflects the
- entries in the current image. Hierarchy is preserved, and all offsets and
- sizes are included.
- Note that the -u option must be provided to ensure that binman updates the
- FDT with the position of each entry.
- Example output for a simple image with U-Boot and an FDT map::
- / {
- image-name = "binman";
- size = <0x00000112>;
- image-pos = <0x00000000>;
- offset = <0x00000000>;
- u-boot {
- size = <0x00000004>;
- image-pos = <0x00000000>;
- offset = <0x00000000>;
- };
- fdtmap {
- size = <0x0000010e>;
- image-pos = <0x00000004>;
- offset = <0x00000004>;
- };
- };
- If allow-repack is used then 'orig-offset' and 'orig-size' properties are
- added as necessary. See the binman README.
- """
- def __init__(self, section, etype, node):
- # Put these here to allow entry-docs and help to work without libfdt
- global libfdt
- global state
- global Fdt
- import libfdt
- from binman import state
- from dtoc.fdt import Fdt
- super().__init__(section, etype, node)
- def _GetFdtmap(self):
- """Build an FDT map from the entries in the current image
- Returns:
- FDT map binary data
- """
- def _AddNode(node):
- """Add a node to the FDT map"""
- for pname, prop in node.props.items():
- fsw.property(pname, prop.bytes)
- for subnode in node.subnodes:
- with fsw.add_node(subnode.name):
- _AddNode(subnode)
- data = state.GetFdtContents('fdtmap')[1]
- # If we have an fdtmap it means that we are using this as the
- # fdtmap for this image.
- if data is None:
- # Get the FDT data into an Fdt object
- data = state.GetFdtContents()[1]
- infdt = Fdt.FromData(data)
- infdt.Scan()
- # Find the node for the image containing the Fdt-map entry
- path = self.section.GetPath()
- self.Detail("Fdtmap: Using section '%s' (path '%s')" %
- (self.section.name, path))
- node = infdt.GetNode(path)
- if not node:
- self.Raise("Internal error: Cannot locate node for path '%s'" %
- path)
- # Build a new tree with all nodes and properties starting from that
- # node
- fsw = libfdt.FdtSw()
- fsw.finish_reservemap()
- with fsw.add_node(''):
- fsw.property_string('image-node', node.name)
- _AddNode(node)
- fdt = fsw.as_fdt()
- # Pack this new FDT and return its contents
- fdt.pack()
- outfdt = Fdt.FromData(fdt.as_bytearray())
- data = outfdt.GetContents()
- data = FDTMAP_MAGIC + tools.GetBytes(0, 8) + data
- return data
- def ObtainContents(self):
- """Obtain a placeholder for the fdt-map contents"""
- self.SetContents(self._GetFdtmap())
- return True
- def ProcessContents(self):
- """Write an updated version of the FDT map to this entry
- This is necessary since new data may have been written back to it during
- processing, e.g. the image-pos properties.
- """
- return self.ProcessContentsUpdate(self._GetFdtmap())
|