diff options
Diffstat (limited to 'tools/binman/etype')
-rw-r--r-- | tools/binman/etype/intel_descriptor.py | 55 | ||||
-rw-r--r-- | tools/binman/etype/intel_me.py | 17 | ||||
-rw-r--r-- | tools/binman/etype/intel_mrc.py | 17 | ||||
-rw-r--r-- | tools/binman/etype/intel_vga.py | 17 | ||||
-rw-r--r-- | tools/binman/etype/u_boot_dtb_with_ucode.py | 76 | ||||
-rw-r--r-- | tools/binman/etype/u_boot_ucode.py | 84 | ||||
-rw-r--r-- | tools/binman/etype/u_boot_with_ucode_ptr.py | 87 | ||||
-rw-r--r-- | tools/binman/etype/x86_start16.py | 17 |
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' |