summaryrefslogtreecommitdiff
path: root/tools/binman/etype
diff options
context:
space:
mode:
Diffstat (limited to 'tools/binman/etype')
-rw-r--r--tools/binman/etype/_testing.py26
-rw-r--r--tools/binman/etype/blob.py37
-rw-r--r--tools/binman/etype/entry.py200
-rw-r--r--tools/binman/etype/intel_cmc.py17
-rw-r--r--tools/binman/etype/intel_descriptor.py55
-rw-r--r--tools/binman/etype/intel_fsp.py17
-rw-r--r--tools/binman/etype/intel_me.py17
-rw-r--r--tools/binman/etype/intel_mrc.py17
-rw-r--r--tools/binman/etype/intel_vga.py17
-rw-r--r--tools/binman/etype/u_boot.py17
-rw-r--r--tools/binman/etype/u_boot_dtb.py17
-rw-r--r--tools/binman/etype/u_boot_dtb_with_ucode.py78
-rw-r--r--tools/binman/etype/u_boot_img.py17
-rw-r--r--tools/binman/etype/u_boot_nodtb.py17
-rw-r--r--tools/binman/etype/u_boot_spl.py17
-rw-r--r--tools/binman/etype/u_boot_spl_bss_pad.py26
-rw-r--r--tools/binman/etype/u_boot_spl_with_ucode_ptr.py28
-rw-r--r--tools/binman/etype/u_boot_ucode.py84
-rw-r--r--tools/binman/etype/u_boot_with_ucode_ptr.py87
-rw-r--r--tools/binman/etype/x86_start16.py17
-rw-r--r--tools/binman/etype/x86_start16_spl.py17
21 files changed, 825 insertions, 0 deletions
diff --git a/tools/binman/etype/_testing.py b/tools/binman/etype/_testing.py
new file mode 100644
index 0000000..1783098
--- /dev/null
+++ b/tools/binman/etype/_testing.py
@@ -0,0 +1,26 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for testing purposes. Not used in real images.
+#
+
+from entry import Entry
+import fdt_util
+import tools
+
+class Entry__testing(Entry):
+ def __init__(self, image, etype, node):
+ Entry.__init__(self, image, etype, node)
+
+ def ObtainContents(self):
+ self.data = 'a'
+ self.contents_size = len(self.data)
+ return True
+
+ def ReadContents(self):
+ return True
+
+ def GetPositions(self):
+ return {'invalid-entry': [1, 2]}
diff --git a/tools/binman/etype/blob.py b/tools/binman/etype/blob.py
new file mode 100644
index 0000000..def2164
--- /dev/null
+++ b/tools/binman/etype/blob.py
@@ -0,0 +1,37 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for blobs, which are binary objects read from files
+#
+
+from entry import Entry
+import fdt_util
+import tools
+
+class Entry_blob(Entry):
+ def __init__(self, image, etype, node):
+ Entry.__init__(self, image, etype, node)
+ self._filename = fdt_util.GetString(self._node, "filename", self.etype)
+
+ def ObtainContents(self):
+ self._filename = self.GetDefaultFilename()
+ self._pathname = tools.GetInputFilename(self._filename)
+ self.ReadContents()
+ return True
+
+ def ReadContents(self):
+ with open(self._pathname) as fd:
+ # We assume the data is small enough to fit into memory. If this
+ # is used for large filesystem image that might not be true.
+ # In that case, Image.BuildImage() could be adjusted to use a
+ # new Entry method which can read in chunks. Then we could copy
+ # the data in chunks and avoid reading it all at once. For now
+ # this seems like an unnecessary complication.
+ self.data = fd.read()
+ self.contents_size = len(self.data)
+ return True
+
+ def GetDefaultFilename(self):
+ return self._filename
diff --git a/tools/binman/etype/entry.py b/tools/binman/etype/entry.py
new file mode 100644
index 0000000..67c5734
--- /dev/null
+++ b/tools/binman/etype/entry.py
@@ -0,0 +1,200 @@
+# Copyright (c) 2016 Google, Inc
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Base class for all entries
+#
+
+# importlib was introduced in Python 2.7 but there was a report of it not
+# working in 2.7.12, so we work around this:
+# http://lists.denx.de/pipermail/u-boot/2016-October/269729.html
+try:
+ import importlib
+ have_importlib = True
+except:
+ have_importlib = False
+
+import fdt_util
+import tools
+
+modules = {}
+
+class Entry(object):
+ """An Entry in the image
+
+ An entry corresponds to a single node in the device-tree description
+ of the image. Each entry ends up being a part of the final image.
+ Entries can be placed either right next to each other, or with padding
+ between them. The type of the entry determines the data that is in it.
+
+ This class is not used by itself. All entry objects are subclasses of
+ Entry.
+
+ Attributes:
+ image: The image containing this entry
+ node: The node that created this entry
+ pos: Absolute position of entry within the image, None if not known
+ size: Entry size in bytes, None if not known
+ contents_size: Size of contents in bytes, 0 by default
+ align: Entry start position alignment, or None
+ align_size: Entry size alignment, or None
+ align_end: Entry end position alignment, or None
+ pad_before: Number of pad bytes before the contents, 0 if none
+ pad_after: Number of pad bytes after the contents, 0 if none
+ data: Contents of entry (string of bytes)
+ """
+ def __init__(self, image, etype, node, read_node=True):
+ self.image = image
+ self.etype = etype
+ self._node = node
+ self.pos = None
+ self.size = None
+ self.contents_size = 0
+ self.align = None
+ self.align_size = None
+ self.align_end = None
+ self.pad_before = 0
+ self.pad_after = 0
+ self.pos_unset = False
+ if read_node:
+ self.ReadNode()
+
+ @staticmethod
+ def Create(image, node, etype=None):
+ """Create a new entry for a node.
+
+ Args:
+ image: Image object containing this node
+ node: Node object containing information about the entry to create
+ etype: Entry type to use, or None to work it out (used for tests)
+
+ Returns:
+ A new Entry object of the correct type (a subclass of Entry)
+ """
+ if not etype:
+ etype = fdt_util.GetString(node, 'type', node.name)
+ module_name = etype.replace('-', '_')
+ module = modules.get(module_name)
+
+ # Import the module if we have not already done so.
+ if not module:
+ try:
+ if have_importlib:
+ module = importlib.import_module(module_name)
+ else:
+ module = __import__(module_name)
+ except ImportError:
+ raise ValueError("Unknown entry type '%s' in node '%s'" %
+ (etype, node.path))
+ modules[module_name] = module
+
+ # Call its constructor to get the object we want.
+ obj = getattr(module, 'Entry_%s' % module_name)
+ return obj(image, etype, node)
+
+ def ReadNode(self):
+ """Read entry information from the node
+
+ This reads all the fields we recognise from the node, ready for use.
+ """
+ self.pos = fdt_util.GetInt(self._node, 'pos')
+ self.size = fdt_util.GetInt(self._node, 'size')
+ self.align = fdt_util.GetInt(self._node, 'align')
+ if tools.NotPowerOfTwo(self.align):
+ raise ValueError("Node '%s': Alignment %s must be a power of two" %
+ (self._node.path, self.align))
+ self.pad_before = fdt_util.GetInt(self._node, 'pad-before', 0)
+ self.pad_after = fdt_util.GetInt(self._node, 'pad-after', 0)
+ self.align_size = fdt_util.GetInt(self._node, 'align-size')
+ if tools.NotPowerOfTwo(self.align_size):
+ raise ValueError("Node '%s': Alignment size %s must be a power "
+ "of two" % (self._node.path, self.align_size))
+ self.align_end = fdt_util.GetInt(self._node, 'align-end')
+ self.pos_unset = fdt_util.GetBool(self._node, 'pos-unset')
+
+ def ObtainContents(self):
+ """Figure out the contents of an entry.
+
+ Returns:
+ True if the contents were found, False if another call is needed
+ after the other entries are processed.
+ """
+ # No contents by default: subclasses can implement this
+ return True
+
+ def Pack(self, pos):
+ """Figure out how to pack the entry into the image
+
+ Most of the time the entries are not fully specified. There may be
+ an alignment but no size. In that case we take the size from the
+ contents of the entry.
+
+ If an entry has no hard-coded position, it will be placed at @pos.
+
+ Once this function is complete, both the position and size of the
+ entry will be know.
+
+ Args:
+ Current image position pointer
+
+ Returns:
+ New image position pointer (after this entry)
+ """
+ if self.pos is None:
+ if self.pos_unset:
+ self.Raise('No position set with pos-unset: should another '
+ 'entry provide this correct position?')
+ self.pos = tools.Align(pos, self.align)
+ needed = self.pad_before + self.contents_size + self.pad_after
+ needed = tools.Align(needed, self.align_size)
+ size = self.size
+ if not size:
+ size = needed
+ new_pos = self.pos + size
+ aligned_pos = tools.Align(new_pos, self.align_end)
+ if aligned_pos != new_pos:
+ size = aligned_pos - self.pos
+ new_pos = aligned_pos
+
+ if not self.size:
+ self.size = size
+
+ if self.size < needed:
+ self.Raise("Entry contents size is %#x (%d) but entry size is "
+ "%#x (%d)" % (needed, needed, self.size, self.size))
+ # Check that the alignment is correct. It could be wrong if the
+ # and pos or size values were provided (i.e. not calculated), but
+ # conflict with the provided alignment values
+ if self.size != tools.Align(self.size, self.align_size):
+ self.Raise("Size %#x (%d) does not match align-size %#x (%d)" %
+ (self.size, self.size, self.align_size, self.align_size))
+ if self.pos != tools.Align(self.pos, self.align):
+ self.Raise("Position %#x (%d) does not match align %#x (%d)" %
+ (self.pos, self.pos, self.align, self.align))
+
+ return new_pos
+
+ def Raise(self, msg):
+ """Convenience function to raise an error referencing a node"""
+ raise ValueError("Node '%s': %s" % (self._node.path, msg))
+
+ def GetPath(self):
+ """Get the path of a node
+
+ Returns:
+ Full path of the node for this entry
+ """
+ return self._node.path
+
+ def GetData(self):
+ return self.data
+
+ def GetPositions(self):
+ return {}
+
+ def SetPositionSize(self, pos, size):
+ self.pos = pos
+ self.size = size
+
+ def ProcessContents(self):
+ pass
diff --git a/tools/binman/etype/intel_cmc.py b/tools/binman/etype/intel_cmc.py
new file mode 100644
index 0000000..9bce8ae
--- /dev/null
+++ b/tools/binman/etype/intel_cmc.py
@@ -0,0 +1,17 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for Intel Chip Microcode binary blob
+#
+
+from entry import Entry
+from blob import Entry_blob
+
+class Entry_intel_cmc(Entry_blob):
+ def __init__(self, image, etype, node):
+ Entry_blob.__init__(self, image, etype, node)
+
+ def GetDefaultFilename(self):
+ return 'cmc.bin'
diff --git a/tools/binman/etype/intel_descriptor.py b/tools/binman/etype/intel_descriptor.py
new file mode 100644
index 0000000..7f4ea0b
--- /dev/null
+++ b/tools/binman/etype/intel_descriptor.py
@@ -0,0 +1,55 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for 'u-boot'
+#
+
+import struct
+
+from entry import Entry
+from blob import Entry_blob
+
+FD_SIGNATURE = struct.pack('<L', 0x0ff0a55a)
+MAX_REGIONS = 5
+
+(REGION_DESCRIPTOR, REGION_BIOS, REGION_ME, REGION_GBE,
+ REGION_PDATA) = range(5)
+
+class Region:
+ def __init__(self, data, frba, region_num):
+ pos = frba + region_num * 4
+ val = struct.unpack('<L', data[pos:pos + 4])[0]
+ self.base = (val & 0xfff) << 12
+ self.limit = ((val & 0x0fff0000) >> 4) | 0xfff
+ self.size = self.limit - self.base + 1
+
+class Entry_intel_descriptor(Entry_blob):
+ """Intel flash descriptor block (4KB)
+
+ This is placed at the start of flash and provides information about
+ the SPI flash regions. In particular it provides the base address and
+ size of the ME region, allowing us to place the ME binary in the right
+ place.
+ """
+ def __init__(self, image, etype, node):
+ Entry_blob.__init__(self, image, etype, node)
+ self._regions = []
+
+ def GetDefaultFilename(self):
+ return 'descriptor.bin'
+
+ def GetPositions(self):
+ pos = self.data.find(FD_SIGNATURE)
+ if pos == -1:
+ self.Raise('Cannot find FD signature')
+ flvalsig, flmap0, flmap1, flmap2 = struct.unpack('<LLLL',
+ self.data[pos:pos + 16])
+ frba = ((flmap0 >> 16) & 0xff) << 4
+ for i in range(MAX_REGIONS):
+ self._regions.append(Region(self.data, frba, i))
+
+ # Set the offset for ME only, for now, since the others are not used
+ return {'intel-me': [self._regions[REGION_ME].base,
+ self._regions[REGION_ME].size]}
diff --git a/tools/binman/etype/intel_fsp.py b/tools/binman/etype/intel_fsp.py
new file mode 100644
index 0000000..d75be5b
--- /dev/null
+++ b/tools/binman/etype/intel_fsp.py
@@ -0,0 +1,17 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for Intel Firmware Support Package binary blob
+#
+
+from entry import Entry
+from blob import Entry_blob
+
+class Entry_intel_fsp(Entry_blob):
+ def __init__(self, image, etype, node):
+ Entry_blob.__init__(self, image, etype, node)
+
+ def GetDefaultFilename(self):
+ return 'fsp.bin'
diff --git a/tools/binman/etype/intel_me.py b/tools/binman/etype/intel_me.py
new file mode 100644
index 0000000..45ab50c
--- /dev/null
+++ b/tools/binman/etype/intel_me.py
@@ -0,0 +1,17 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for Intel Management Engine binary blob
+#
+
+from entry import Entry
+from blob import Entry_blob
+
+class Entry_intel_me(Entry_blob):
+ def __init__(self, image, etype, node):
+ Entry_blob.__init__(self, image, etype, node)
+
+ def GetDefaultFilename(self):
+ return 'me.bin'
diff --git a/tools/binman/etype/intel_mrc.py b/tools/binman/etype/intel_mrc.py
new file mode 100644
index 0000000..f6cedb7
--- /dev/null
+++ b/tools/binman/etype/intel_mrc.py
@@ -0,0 +1,17 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for Intel Memory Reference Code binary blob
+#
+
+from entry import Entry
+from blob import Entry_blob
+
+class Entry_intel_mrc(Entry_blob):
+ def __init__(self, image, etype, node):
+ Entry_blob.__init__(self, image, etype, node)
+
+ def GetDefaultFilename(self):
+ return 'mrc.bin'
diff --git a/tools/binman/etype/intel_vga.py b/tools/binman/etype/intel_vga.py
new file mode 100644
index 0000000..d8f270b
--- /dev/null
+++ b/tools/binman/etype/intel_vga.py
@@ -0,0 +1,17 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for x86 VGA ROM binary blob
+#
+
+from entry import Entry
+from blob import Entry_blob
+
+class Entry_intel_vga(Entry_blob):
+ def __init__(self, image, etype, node):
+ Entry_blob.__init__(self, image, etype, node)
+
+ def GetDefaultFilename(self):
+ return 'vga.bin'
diff --git a/tools/binman/etype/u_boot.py b/tools/binman/etype/u_boot.py
new file mode 100644
index 0000000..1fcff73
--- /dev/null
+++ b/tools/binman/etype/u_boot.py
@@ -0,0 +1,17 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for U-Boot binary
+#
+
+from entry import Entry
+from blob import Entry_blob
+
+class Entry_u_boot(Entry_blob):
+ def __init__(self, image, etype, node):
+ Entry_blob.__init__(self, image, etype, node)
+
+ def GetDefaultFilename(self):
+ return 'u-boot.bin'
diff --git a/tools/binman/etype/u_boot_dtb.py b/tools/binman/etype/u_boot_dtb.py
new file mode 100644
index 0000000..1122c95
--- /dev/null
+++ b/tools/binman/etype/u_boot_dtb.py
@@ -0,0 +1,17 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for U-Boot device tree
+#
+
+from entry import Entry
+from blob import Entry_blob
+
+class Entry_u_boot_dtb(Entry_blob):
+ def __init__(self, image, etype, node):
+ Entry_blob.__init__(self, image, etype, node)
+
+ def GetDefaultFilename(self):
+ return 'u-boot.dtb'
diff --git a/tools/binman/etype/u_boot_dtb_with_ucode.py b/tools/binman/etype/u_boot_dtb_with_ucode.py
new file mode 100644
index 0000000..fc02c67
--- /dev/null
+++ b/tools/binman/etype/u_boot_dtb_with_ucode.py
@@ -0,0 +1,78 @@
+# Copyright (c) 2016 Google, Inc
+## Written by Simon Glass <sjg@chromium.org>
+
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for U-Boot device tree with the microcode removed
+#
+
+import fdt_select
+from entry import Entry
+from blob import Entry_blob
+import tools
+
+class Entry_u_boot_dtb_with_ucode(Entry_blob):
+ """A U-Boot device tree file, with the microcode removed
+
+ See Entry_u_boot_ucode for full details of the 3 entries involved in this
+ process.
+ """
+ def __init__(self, image, etype, node):
+ Entry_blob.__init__(self, image, etype, node)
+ self.ucode_data = ''
+ self.collate = False
+ self.ucode_offset = None
+ self.ucode_size = None
+
+ def GetDefaultFilename(self):
+ return 'u-boot.dtb'
+
+ def ObtainContents(self):
+ Entry_blob.ObtainContents(self)
+
+ # If the image does not need microcode, there is nothing to do
+ ucode_dest_entry = self.image.FindEntryType('u-boot-spl-with-ucode-ptr')
+ if not ucode_dest_entry or not ucode_dest_entry.target_pos:
+ ucode_dest_entry = self.image.FindEntryType('u-boot-with-ucode-ptr')
+ if not ucode_dest_entry or not ucode_dest_entry.target_pos:
+ return True
+
+ # Create a new file to hold the copied device tree
+ dtb_name = 'u-boot-dtb-with-ucode.dtb'
+ fname = tools.GetOutputFilename(dtb_name)
+ with open(fname, 'wb') as fd:
+ fd.write(self.data)
+
+ # Remove the microcode
+ fdt = fdt_select.FdtScan(fname)
+ fdt.Scan()
+ ucode = fdt.GetNode('/microcode')
+ if not ucode:
+ raise self.Raise("No /microcode node found in '%s'" % fname)
+
+ # There's no need to collate it (move all microcode into one place)
+ # if we only have one chunk of microcode.
+ self.collate = len(ucode.subnodes) > 1
+ for node in ucode.subnodes:
+ data_prop = node.props.get('data')
+ if data_prop:
+ self.ucode_data += ''.join(data_prop.bytes)
+ if not self.collate:
+ poffset = data_prop.GetOffset()
+ if poffset is None:
+ # We cannot obtain a property offset. Collate instead.
+ self.collate = True
+ else:
+ # Find the offset in the device tree of the ucode data
+ self.ucode_offset = poffset + 12
+ self.ucode_size = len(data_prop.bytes)
+ if self.collate:
+ prop = node.DeleteProp('data')
+ if self.collate:
+ fdt.Pack()
+ fdt.Flush()
+
+ # Make this file the contents of this entry
+ self._pathname = fname
+ self.ReadContents()
+ return True
diff --git a/tools/binman/etype/u_boot_img.py b/tools/binman/etype/u_boot_img.py
new file mode 100644
index 0000000..744f1b4
--- /dev/null
+++ b/tools/binman/etype/u_boot_img.py
@@ -0,0 +1,17 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for U-Boot binary
+#
+
+from entry import Entry
+from blob import Entry_blob
+
+class Entry_u_boot_img(Entry_blob):
+ def __init__(self, image, etype, node):
+ Entry_blob.__init__(self, image, etype, node)
+
+ def GetDefaultFilename(self):
+ return 'u-boot.img'
diff --git a/tools/binman/etype/u_boot_nodtb.py b/tools/binman/etype/u_boot_nodtb.py
new file mode 100644
index 0000000..3721c3b
--- /dev/null
+++ b/tools/binman/etype/u_boot_nodtb.py
@@ -0,0 +1,17 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for 'u-boot-nodtb.bin'
+#
+
+from entry import Entry
+from blob import Entry_blob
+
+class Entry_u_boot_nodtb(Entry_blob):
+ def __init__(self, image, etype, node):
+ Entry_blob.__init__(self, image, etype, node)
+
+ def GetDefaultFilename(self):
+ return 'u-boot-nodtb.bin'
diff --git a/tools/binman/etype/u_boot_spl.py b/tools/binman/etype/u_boot_spl.py
new file mode 100644
index 0000000..68b0148
--- /dev/null
+++ b/tools/binman/etype/u_boot_spl.py
@@ -0,0 +1,17 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for spl/u-boot-spl.bin
+#
+
+from entry import Entry
+from blob import Entry_blob
+
+class Entry_u_boot_spl(Entry_blob):
+ def __init__(self, image, etype, node):
+ Entry_blob.__init__(self, image, etype, node)
+
+ def GetDefaultFilename(self):
+ return 'spl/u-boot-spl.bin'
diff --git a/tools/binman/etype/u_boot_spl_bss_pad.py b/tools/binman/etype/u_boot_spl_bss_pad.py
new file mode 100644
index 0000000..c005f28
--- /dev/null
+++ b/tools/binman/etype/u_boot_spl_bss_pad.py
@@ -0,0 +1,26 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for BSS padding for spl/u-boot-spl.bin. This padding
+# can be added after the SPL binary to ensure that anything concatenated
+# to it will appear to SPL to be at the end of BSS rather than the start.
+#
+
+import command
+from entry import Entry
+from blob import Entry_blob
+import tools
+
+class Entry_u_boot_spl_bss_pad(Entry_blob):
+ def __init__(self, image, etype, node):
+ Entry_blob.__init__(self, image, etype, node)
+
+ def ObtainContents(self):
+ fname = tools.GetInputFilename('spl/u-boot-spl')
+ args = [['nm', fname], ['grep', '__bss_size']]
+ out = command.RunPipe(args, capture=True).stdout.splitlines()
+ bss_size = int(out[0].split()[0], 16)
+ self.data = chr(0) * bss_size
+ self.contents_size = bss_size
diff --git a/tools/binman/etype/u_boot_spl_with_ucode_ptr.py b/tools/binman/etype/u_boot_spl_with_ucode_ptr.py
new file mode 100644
index 0000000..764c282
--- /dev/null
+++ b/tools/binman/etype/u_boot_spl_with_ucode_ptr.py
@@ -0,0 +1,28 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for an SPL binary with an embedded microcode pointer
+#
+
+import struct
+
+import command
+from entry import Entry
+from blob import Entry_blob
+from u_boot_with_ucode_ptr import Entry_u_boot_with_ucode_ptr
+import tools
+
+class Entry_u_boot_spl_with_ucode_ptr(Entry_u_boot_with_ucode_ptr):
+ """U-Boot SPL with embedded microcode pointer
+
+ See Entry_u_boot_ucode for full details of the entries involved in this
+ process.
+ """
+ def __init__(self, image, etype, node):
+ Entry_blob.__init__(self, image, etype, node)
+ self.elf_fname = 'spl/u-boot-spl'
+
+ def GetDefaultFilename(self):
+ return 'spl/u-boot-spl.bin'
diff --git a/tools/binman/etype/u_boot_ucode.py b/tools/binman/etype/u_boot_ucode.py
new file mode 100644
index 0000000..8fe27ac
--- /dev/null
+++ b/tools/binman/etype/u_boot_ucode.py
@@ -0,0 +1,84 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for a U-Boot binary with an embedded microcode pointer
+#
+
+from entry import Entry
+from blob import Entry_blob
+import tools
+
+class Entry_u_boot_ucode(Entry_blob):
+ """U-Boot microcode block
+
+ U-Boot on x86 needs a single block of microcode. This is collected from
+ the various microcode update nodes in the device tree. It is also unable
+ to read the microcode from the device tree on platforms that use FSP
+ (Firmware Support Package) binaries, because the API requires that the
+ microcode is supplied before there is any SRAM available to use (i.e.
+ the FSP sets up the SRAM / cache-as-RAM but does so in the call that
+ requires the microcode!). To keep things simple, all x86 platforms handle
+ microcode the same way in U-Boot (even non-FSP platforms). This is that
+ a table is placed at _dt_ucode_base_size containing the base address and
+ size of the microcode. This is either passed to the FSP (for FSP
+ platforms), or used to set up the microcode (for non-FSP platforms).
+ This all happens in the build system since it is the only way to get
+ the microcode into a single blob and accessible without SRAM.
+
+ There are two cases to handle. If there is only one microcode blob in
+ the device tree, then the ucode pointer it set to point to that. This
+ entry (u-boot-ucode) is empty. If there is more than one update, then
+ this entry holds the concatenation of all updates, and the device tree
+ entry (u-boot-dtb-with-ucode) is updated to remove the microcode. This
+ last step ensures that that the microcode appears in one contiguous
+ block in the image and is not unnecessarily duplicated in the device
+ tree. It is referred to as 'collation' here.
+
+ Entry types that have a part to play in handling microcode:
+
+ Entry_u_boot_with_ucode_ptr:
+ Contains u-boot-nodtb.bin (i.e. U-Boot without the device tree).
+ It updates it with the address and size of the microcode so that
+ U-Boot can find it early on start-up.
+ Entry_u_boot_dtb_with_ucode:
+ Contains u-boot.dtb. It stores the microcode in a
+ 'self.ucode_data' property, which is then read by this class to
+ obtain the microcode if needed. If collation is performed, it
+ removes the microcode from the device tree.
+ Entry_u_boot_ucode:
+ This class. If collation is enabled it reads the microcode from
+ the Entry_u_boot_dtb_with_ucode entry, and uses it as the
+ contents of this entry.
+ """
+ def __init__(self, image, etype, node):
+ Entry_blob.__init__(self, image, etype, node)
+
+ def ObtainContents(self):
+ # If the image does not need microcode, there is nothing to do
+ ucode_dest_entry = self.image.FindEntryType('u-boot-with-ucode-ptr')
+ if ucode_dest_entry and not ucode_dest_entry.target_pos:
+ self.data = ''
+ return True
+
+ # Get the microcode from the device tree entry
+ fdt_entry = self.image.FindEntryType('u-boot-dtb-with-ucode')
+ if not fdt_entry or not fdt_entry.ucode_data:
+ return False
+
+ if not fdt_entry.collate:
+ # This section can be empty
+ self.data = ''
+ return True
+
+ # Write it out to a file
+ dtb_name = 'u-boot-ucode.bin'
+ fname = tools.GetOutputFilename(dtb_name)
+ with open(fname, 'wb') as fd:
+ fd.write(fdt_entry.ucode_data)
+
+ self._pathname = fname
+ self.ReadContents()
+
+ return True
diff --git a/tools/binman/etype/u_boot_with_ucode_ptr.py b/tools/binman/etype/u_boot_with_ucode_ptr.py
new file mode 100644
index 0000000..6f01adb
--- /dev/null
+++ b/tools/binman/etype/u_boot_with_ucode_ptr.py
@@ -0,0 +1,87 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for a U-Boot binary with an embedded microcode pointer
+#
+
+import struct
+
+import command
+from entry import Entry
+from blob import Entry_blob
+import fdt_util
+import tools
+
+class Entry_u_boot_with_ucode_ptr(Entry_blob):
+ """U-Boot with embedded microcode pointer
+
+ See Entry_u_boot_ucode for full details of the 3 entries involved in this
+ process.
+ """
+ def __init__(self, image, etype, node):
+ Entry_blob.__init__(self, image, etype, node)
+ self.elf_fname = 'u-boot'
+ self.target_pos = None
+
+ def GetDefaultFilename(self):
+ return 'u-boot-nodtb.bin'
+
+ def ObtainContents(self):
+ # Figure out where to put the microcode pointer
+ fname = tools.GetInputFilename(self.elf_fname)
+ args = [['nm', fname], ['grep', '-w', '_dt_ucode_base_size']]
+ out = (command.RunPipe(args, capture=True, raise_on_error=False).
+ stdout.splitlines())
+ if len(out) == 1:
+ self.target_pos = int(out[0].split()[0], 16)
+ elif not fdt_util.GetBool(self._node, 'optional-ucode'):
+ self.Raise('Cannot locate _dt_ucode_base_size symbol in u-boot')
+
+ return Entry_blob.ObtainContents(self)
+
+ def ProcessContents(self):
+ # If the image does not need microcode, there is nothing to do
+ if not self.target_pos:
+ return
+
+ # Get the position of the microcode
+ ucode_entry = self.image.FindEntryType('u-boot-ucode')
+ if not ucode_entry:
+ self.Raise('Cannot find microcode region u-boot-ucode')
+
+ # Check the target pos is in the image. If it is not, then U-Boot is
+ # being linked incorrectly, or is being placed at the wrong position
+ # in the image.
+ #
+ # The image must be set up so that U-Boot is placed at the
+ # flash address to which it is linked. For example, if
+ # CONFIG_SYS_TEXT_BASE is 0xfff00000, and the ROM is 8MB, then
+ # the U-Boot region must start at position 7MB in the image. In this
+ # case the ROM starts at 0xff800000, so the position of the first
+ # entry in the image corresponds to that.
+ if (self.target_pos < self.pos or
+ self.target_pos >= self.pos + self.size):
+ self.Raise('Microcode pointer _dt_ucode_base_size at %08x is '
+ 'outside the image ranging from %08x to %08x' %
+ (self.target_pos, self.pos, self.pos + self.size))
+
+ # Get the microcode, either from u-boot-ucode or u-boot-dtb-with-ucode.
+ # If we have left the microcode in the device tree, then it will be
+ # in the former. If we extracted the microcode from the device tree
+ # and collated it in one place, it will be in the latter.
+ if ucode_entry.size:
+ pos, size = ucode_entry.pos, ucode_entry.size
+ else:
+ dtb_entry = self.image.FindEntryType('u-boot-dtb-with-ucode')
+ if not dtb_entry:
+ self.Raise('Cannot find microcode region u-boot-dtb-with-ucode')
+ pos = dtb_entry.pos + dtb_entry.ucode_offset
+ size = dtb_entry.ucode_size
+
+ # Write the microcode position and size into the entry
+ pos_and_size = struct.pack('<2L', pos, size)
+ self.target_pos -= self.pos
+ self.data = (self.data[:self.target_pos] + pos_and_size +
+ self.data[self.target_pos + 8:])
diff --git a/tools/binman/etype/x86_start16.py b/tools/binman/etype/x86_start16.py
new file mode 100644
index 0000000..a44ea68
--- /dev/null
+++ b/tools/binman/etype/x86_start16.py
@@ -0,0 +1,17 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for the 16-bit x86 start-up code for U-Boot
+#
+
+from entry import Entry
+from blob import Entry_blob
+
+class Entry_x86_start16(Entry_blob):
+ def __init__(self, image, etype, node):
+ Entry_blob.__init__(self, image, etype, node)
+
+ def GetDefaultFilename(self):
+ return 'u-boot-x86-16bit.bin'
diff --git a/tools/binman/etype/x86_start16_spl.py b/tools/binman/etype/x86_start16_spl.py
new file mode 100644
index 0000000..3679a43
--- /dev/null
+++ b/tools/binman/etype/x86_start16_spl.py
@@ -0,0 +1,17 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for the 16-bit x86 start-up code for U-Boot SPL
+#
+
+from entry import Entry
+from blob import Entry_blob
+
+class Entry_x86_start16_spl(Entry_blob):
+ def __init__(self, image, etype, node):
+ Entry_blob.__init__(self, image, etype, node)
+
+ def GetDefaultFilename(self):
+ return 'spl/u-boot-x86-16bit-spl.bin'