fdtmap.py 4.8 KB

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