u-boot-brain/tools/binman/etype/fdtmap.py
Simon Glass e1925fa520 binman: Support locating an FDT map
Add support for locating an image's Fdt map which is used to determine
the contents and structure of the image.

Signed-off-by: Simon Glass <sjg@chromium.org>
2019-07-24 12:54:08 -07:00

131 lines
3.9 KiB
Python

# 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.
"""
import libfdt
from entry import Entry
from fdt import Fdt
import state
import tools
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:
/ {
size = <0x00000112>;
image-pos = <0x00000000>;
offset = <0x00000000>;
u-boot {
size = <0x00000004>;
image-pos = <0x00000000>;
offset = <0x00000000>;
};
fdtmap {
size = <0x0000010e>;
image-pos = <0x00000004>;
offset = <0x00000004>;
};
};
"""
def __init__(self, section, etype, node):
Entry.__init__(self, 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)
# 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()
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(''):
_AddNode(node)
fdt = fsw.as_fdt()
# Pack this new FDT and return its contents
fdt.pack()
outfdt = Fdt.FromData(fdt.as_bytearray())
data = FDTMAP_MAGIC + tools.GetBytes(0, 8) + outfdt.GetContents()
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())