aboutsummaryrefslogtreecommitdiff
path: root/tools/binman/etype
diff options
context:
space:
mode:
Diffstat (limited to 'tools/binman/etype')
-rw-r--r--tools/binman/etype/intel_descriptor.py55
-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_dtb_with_ucode.py76
-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
8 files changed, 370 insertions, 0 deletions
diff --git a/tools/binman/etype/intel_descriptor.py b/tools/binman/etype/intel_descriptor.py
new file mode 100644
index 00000000000..7f4ea0b21be
--- /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_me.py b/tools/binman/etype/intel_me.py
new file mode 100644
index 00000000000..45ab50c1ec3
--- /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 00000000000..f6cedb70586
--- /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 00000000000..d8f270bbd95
--- /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_dtb_with_ucode.py b/tools/binman/etype/u_boot_dtb_with_ucode.py
new file mode 100644
index 00000000000..732d10a14ee
--- /dev/null
+++ b/tools/binman/etype/u_boot_dtb_with_ucode.py
@@ -0,0 +1,76 @@
+# 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-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_ucode.py b/tools/binman/etype/u_boot_ucode.py
new file mode 100644
index 00000000000..8fe27acb245
--- /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 00000000000..6f01adb9701
--- /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 00000000000..a44ea68ac47
--- /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'