summaryrefslogtreecommitdiff
path: root/tools/binman/etype/fdtmap.py
blob: ddb9738e5cb85415359d00f1b42bed7faf350309 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# 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())