diff --git a/tools/binman/README b/tools/binman/README index c73fb3c299a18f7a43da3042d7b5b327240ea6e8..45e741e3b39c131413c077049cf147677fac0d48 100644 --- a/tools/binman/README +++ b/tools/binman/README @@ -369,6 +369,17 @@ Examples of the above options can be found in the tests. See the tools/binman/test directory. +Special properties +------------------ + +Some entries support special properties, documented here: + +u-boot-with-ucode-ptr: + optional-ucode: boolean property to make microcode optional. If the + u-boot.bin image does not include microcode, no error will + be generated. + + Order of image creation ----------------------- diff --git a/tools/binman/etype/intel_descriptor.py b/tools/binman/etype/intel_descriptor.py new file mode 100644 index 0000000000000000000000000000000000000000..7f4ea0b21be98c1d68bfa2b97b621794240c2d7d --- /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 0000000000000000000000000000000000000000..45ab50c1ec3e6c7cfd688db43177972acc7b9499 --- /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 0000000000000000000000000000000000000000..f6cedb70586208b2071d0848a1fc5ba363d21b39 --- /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 0000000000000000000000000000000000000000..d8f270bbd9593d66a07c6985fb857693cf5809ab --- /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 0000000000000000000000000000000000000000..732d10a14eed341c1574b0a87e9d436317b53a96 --- /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 0000000000000000000000000000000000000000..8fe27acb2453a25d15bb1525ff864720c0e480fb --- /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 0000000000000000000000000000000000000000..6f01adb9701892cb7277f6c115bad929e7e81939 --- /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 0000000000000000000000000000000000000000..a44ea68ac47268e39a7d4a3e25e390a12ff21ae5 --- /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/func_test.py b/tools/binman/func_test.py index bf6e9ed6c355f3f4dd64e5078654e949ce74c2aa..341957b59f0f13e096013bb35c7d221de1622645 100644 --- a/tools/binman/func_test.py +++ b/tools/binman/func_test.py @@ -65,10 +65,21 @@ class TestFunctional(unittest.TestCase): TestFunctional._MakeInputFile('u-boot.img', U_BOOT_IMG_DATA) TestFunctional._MakeInputFile('spl/u-boot-spl.bin', U_BOOT_SPL_DATA) TestFunctional._MakeInputFile('blobfile', BLOB_DATA) + TestFunctional._MakeInputFile('me.bin', ME_DATA) + TestFunctional._MakeInputFile('vga.bin', VGA_DATA) TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA) + TestFunctional._MakeInputFile('u-boot-x86-16bit.bin', X86_START16_DATA) TestFunctional._MakeInputFile('u-boot-nodtb.bin', U_BOOT_NODTB_DATA) self._output_setup = False + # ELF file with a '_dt_ucode_base_size' symbol + with open(self.TestFile('u_boot_ucode_ptr')) as fd: + TestFunctional._MakeInputFile('u-boot', fd.read()) + + # Intel flash descriptor file + with open(self.TestFile('descriptor.bin')) as fd: + TestFunctional._MakeInputFile('descriptor.bin', fd.read()) + @classmethod def tearDownClass(self): """Remove the temporary input directory and its contents""" @@ -125,6 +136,18 @@ class TestFunctional(unittest.TestCase): '-d', self.TestFile(fname)) def _SetupDtb(self, fname, outfile='u-boot.dtb'): + """Set up a new test device-tree file + + The given file is compiled and set up as the device tree to be used + for ths test. + + Args: + fname: Filename of .dts file to read + outfile: Output filename for compiled device tree binary + + Returns: + Contents of device tree binary + """ if not self._output_setup: tools.PrepareOutputDir(self._indir, True) self._output_setup = True @@ -132,8 +155,9 @@ class TestFunctional(unittest.TestCase): with open(dtb) as fd: data = fd.read() TestFunctional._MakeInputFile(outfile, data) + return data - def _DoReadFile(self, fname, use_real_dtb=False): + def _DoReadFileDtb(self, fname, use_real_dtb=False): """Run binman and return the resulting image This runs binman with a given test file and then reads the resulting @@ -148,10 +172,16 @@ class TestFunctional(unittest.TestCase): the u-boot-dtb entry. Normally this is not needed and the test contents (the U_BOOT_DTB_DATA string) can be used. But in some test we need the real contents. + + Returns: + Tuple: + Resulting image contents + Device tree contents """ + dtb_data = None # Use the compiled test file as the u-boot-dtb input if use_real_dtb: - self._SetupDtb(fname) + dtb_data = self._SetupDtb(fname) try: retcode = self._DoTestFile(fname) @@ -162,12 +192,16 @@ class TestFunctional(unittest.TestCase): fname = tools.GetOutputFilename('image.bin') self.assertTrue(os.path.exists(fname)) with open(fname) as fd: - return fd.read() + return fd.read(), dtb_data finally: # Put the test file back if use_real_dtb: TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA) + def _DoReadFile(self, fname, use_real_dtb=False): + """Helper function which discards the device-tree binary""" + return self._DoReadFileDtb(fname, use_real_dtb)[0] + @classmethod def _MakeInputFile(self, fname, contents): """Create a new test input file, creating directories as needed @@ -213,6 +247,17 @@ class TestFunctional(unittest.TestCase): self.assertEqual(pos, entry.pos) pos += entry.size + def GetFdtLen(self, dtb): + """Get the totalsize field from a device tree binary + + Args: + dtb: Device tree binary contents + + Returns: + Total size of device tree binary, from the header + """ + return struct.unpack('>L', dtb[4:8])[0] + def testRun(self): """Test a basic run with valid args""" result = self._RunBinman('-h') @@ -540,3 +585,131 @@ class TestFunctional(unittest.TestCase): """Test that a device tree can be added to U-Boot""" data = self._DoReadFile('26_pack_u_boot_dtb.dts') self.assertEqual(U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA, data) + + def testPackX86RomNoSize(self): + """Test that the end-at-4gb property requires a size property""" + with self.assertRaises(ValueError) as e: + self._DoTestFile('27_pack_4gb_no_size.dts') + self.assertIn("Image '/binman': Image size must be provided when " + "using end-at-4gb", str(e.exception)) + + def testPackX86RomOutside(self): + """Test that the end-at-4gb property checks for position boundaries""" + with self.assertRaises(ValueError) as e: + self._DoTestFile('28_pack_4gb_outside.dts') + self.assertIn("Node '/binman/u-boot': Position 0x0 (0) is outside " + "the image starting at 0xfffffff0 (4294967280)", + str(e.exception)) + + def testPackX86Rom(self): + """Test that a basic x86 ROM can be created""" + data = self._DoReadFile('29_x86-rom.dts') + self.assertEqual(U_BOOT_DATA + chr(0) * 3 + U_BOOT_SPL_DATA + + chr(0) * 6, data) + + def testPackX86RomMeNoDesc(self): + """Test that an invalid Intel descriptor entry is detected""" + TestFunctional._MakeInputFile('descriptor.bin', '') + with self.assertRaises(ValueError) as e: + self._DoTestFile('31_x86-rom-me.dts') + self.assertIn("Node '/binman/intel-descriptor': Cannot find FD " + "signature", str(e.exception)) + + def testPackX86RomBadDesc(self): + """Test that the Intel requires a descriptor entry""" + with self.assertRaises(ValueError) as e: + self._DoTestFile('30_x86-rom-me-no-desc.dts') + self.assertIn("Node '/binman/intel-me': No position set with " + "pos-unset: should another entry provide this correct " + "position?", str(e.exception)) + + def testPackX86RomMe(self): + """Test that an x86 ROM with an ME region can be created""" + data = self._DoReadFile('31_x86-rom-me.dts') + self.assertEqual(ME_DATA, data[0x1000:0x1000 + len(ME_DATA)]) + + def testPackVga(self): + """Test that an image with a VGA binary can be created""" + data = self._DoReadFile('32_intel-vga.dts') + self.assertEqual(VGA_DATA, data[:len(VGA_DATA)]) + + def testPackStart16(self): + """Test that an image with an x86 start16 region can be created""" + data = self._DoReadFile('33_x86-start16.dts') + self.assertEqual(X86_START16_DATA, data[:len(X86_START16_DATA)]) + + def testPackUbootMicrocode(self): + """Test that x86 microcode can be handled correctly + + We expect to see the following in the image, in order: + u-boot-nodtb.bin with a microcode pointer inserted at the correct + place + u-boot.dtb with the microcode removed + the microcode + """ + data = self._DoReadFile('34_x86_ucode.dts', True) + + # Now check the device tree has no microcode + second = data[len(U_BOOT_NODTB_DATA):] + fname = tools.GetOutputFilename('test.dtb') + with open(fname, 'wb') as fd: + fd.write(second) + fdt = fdt_select.FdtScan(fname) + ucode = fdt.GetNode('/microcode') + self.assertTrue(ucode) + for node in ucode.subnodes: + self.assertFalse(node.props.get('data')) + + fdt_len = self.GetFdtLen(second) + third = second[fdt_len:] + + # Check that the microcode appears immediately after the Fdt + # This matches the concatenation of the data properties in + # the /microcode/update@xxx nodes in x86_ucode.dts. + ucode_data = struct.pack('>4L', 0x12345678, 0x12345679, 0xabcd0000, + 0x78235609) + self.assertEqual(ucode_data, third[:len(ucode_data)]) + ucode_pos = len(U_BOOT_NODTB_DATA) + fdt_len + + # Check that the microcode pointer was inserted. It should match the + # expected position and size + pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos, + len(ucode_data)) + first = data[:len(U_BOOT_NODTB_DATA)] + self.assertEqual('nodtb with microcode' + pos_and_size + + ' somewhere in here', first) + + def _RunPackUbootSingleMicrocode(self, collate): + """Test that x86 microcode can be handled correctly + + We expect to see the following in the image, in order: + u-boot-nodtb.bin with a microcode pointer inserted at the correct + place + u-boot.dtb with the microcode + an empty microcode region + """ + # We need the libfdt library to run this test since only that allows + # finding the offset of a property. This is required by + # Entry_u_boot_dtb_with_ucode.ObtainContents(). + if not fdt_select.have_libfdt: + return + data = self._DoReadFile('35_x86_single_ucode.dts', True) + + second = data[len(U_BOOT_NODTB_DATA):] + + fdt_len = self.GetFdtLen(second) + third = second[fdt_len:] + second = second[:fdt_len] + + if not collate: + ucode_data = struct.pack('>2L', 0x12345678, 0x12345679) + self.assertIn(ucode_data, second) + ucode_pos = second.find(ucode_data) + len(U_BOOT_NODTB_DATA) + + # Check that the microcode pointer was inserted. It should match the + # expected position and size + pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos, + len(ucode_data)) + first = data[:len(U_BOOT_NODTB_DATA)] + self.assertEqual('nodtb with microcode' + pos_and_size + + ' somewhere in here', first) diff --git a/tools/binman/test/27_pack_4gb_no_size.dts b/tools/binman/test/27_pack_4gb_no_size.dts new file mode 100644 index 0000000000000000000000000000000000000000..e0b6519e75bb7652dd83acb848788ebcb019a103 --- /dev/null +++ b/tools/binman/test/27_pack_4gb_no_size.dts @@ -0,0 +1,18 @@ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + sort-by-pos; + end-at-4gb; + u-boot { + pos = <0xfffffff0>; + }; + + u-boot-spl { + pos = <0xfffffff7>; + }; + }; +}; diff --git a/tools/binman/test/28_pack_4gb_outside.dts b/tools/binman/test/28_pack_4gb_outside.dts new file mode 100644 index 0000000000000000000000000000000000000000..ff468c7d41d031aab7bc4a4ce7e0729cdfd2bc54 --- /dev/null +++ b/tools/binman/test/28_pack_4gb_outside.dts @@ -0,0 +1,19 @@ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + sort-by-pos; + end-at-4gb; + size = <16>; + u-boot { + pos = <0>; + }; + + u-boot-spl { + pos = <0xfffffff7>; + }; + }; +}; diff --git a/tools/binman/test/29_x86-rom.dts b/tools/binman/test/29_x86-rom.dts new file mode 100644 index 0000000000000000000000000000000000000000..075ede36ab32e6c8b07a99b2bf0561cd5263861d --- /dev/null +++ b/tools/binman/test/29_x86-rom.dts @@ -0,0 +1,19 @@ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + sort-by-pos; + end-at-4gb; + size = <16>; + u-boot { + pos = <0xfffffff0>; + }; + + u-boot-spl { + pos = <0xfffffff7>; + }; + }; +}; diff --git a/tools/binman/test/30_x86-rom-me-no-desc.dts b/tools/binman/test/30_x86-rom-me-no-desc.dts new file mode 100644 index 0000000000000000000000000000000000000000..4578f660ac01e2679670a3a1122c53d3972eb35c --- /dev/null +++ b/tools/binman/test/30_x86-rom-me-no-desc.dts @@ -0,0 +1,15 @@ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + sort-by-pos; + end-at-4gb; + size = <16>; + intel-me { + pos-unset; + }; + }; +}; diff --git a/tools/binman/test/31_x86-rom-me.dts b/tools/binman/test/31_x86-rom-me.dts new file mode 100644 index 0000000000000000000000000000000000000000..b484ab31cf786335e688d5e4ce775fe168c2a081 --- /dev/null +++ b/tools/binman/test/31_x86-rom-me.dts @@ -0,0 +1,18 @@ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + sort-by-pos; + end-at-4gb; + size = <0x800000>; + intel-descriptor { + }; + + intel-me { + pos-unset; + }; + }; +}; diff --git a/tools/binman/test/32_intel-vga.dts b/tools/binman/test/32_intel-vga.dts new file mode 100644 index 0000000000000000000000000000000000000000..1790833238fa2cb0a0b704651c2ed3f2bee0612d --- /dev/null +++ b/tools/binman/test/32_intel-vga.dts @@ -0,0 +1,13 @@ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + size = <16>; + + intel-vga { + }; + }; +}; diff --git a/tools/binman/test/33_x86-start16.dts b/tools/binman/test/33_x86-start16.dts new file mode 100644 index 0000000000000000000000000000000000000000..2e279dee9d63a5e1fb1652a3d2a38aed1dbf6b03 --- /dev/null +++ b/tools/binman/test/33_x86-start16.dts @@ -0,0 +1,13 @@ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + size = <16>; + + x86-start16 { + }; + }; +}; diff --git a/tools/binman/test/34_x86_ucode.dts b/tools/binman/test/34_x86_ucode.dts new file mode 100644 index 0000000000000000000000000000000000000000..64a6c2c3d5d43f8d60cd3765937f6da21e5853f8 --- /dev/null +++ b/tools/binman/test/34_x86_ucode.dts @@ -0,0 +1,29 @@ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + sort-by-pos; + end-at-4gb; + size = <0x200>; + u-boot-with-ucode-ptr { + }; + + u-boot-dtb-with-ucode { + }; + + u-boot-ucode { + }; + }; + + microcode { + update@0 { + data = <0x12345678 0x12345679>; + }; + update@1 { + data = <0xabcd0000 0x78235609>; + }; + }; +}; diff --git a/tools/binman/test/35_x86_single_ucode.dts b/tools/binman/test/35_x86_single_ucode.dts new file mode 100644 index 0000000000000000000000000000000000000000..973e97f8641dbe294e6aa7fe096ffb1963b60dac --- /dev/null +++ b/tools/binman/test/35_x86_single_ucode.dts @@ -0,0 +1,26 @@ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + sort-by-pos; + end-at-4gb; + size = <0x200>; + u-boot-with-ucode-ptr { + }; + + u-boot-dtb-with-ucode { + }; + + u-boot-ucode { + }; + }; + + microcode { + update@0 { + data = <0x12345678 0x12345679>; + }; + }; +}; diff --git a/tools/binman/test/descriptor.bin b/tools/binman/test/descriptor.bin new file mode 100644 index 0000000000000000000000000000000000000000..3d549436c27c76f0a3b6289a16f68de4c14d70f6 Binary files /dev/null and b/tools/binman/test/descriptor.bin differ diff --git a/tools/binman/test/u_boot_ucode_ptr b/tools/binman/test/u_boot_ucode_ptr new file mode 100755 index 0000000000000000000000000000000000000000..dbfb184cecfbcf55cf43ed4f4ac0ee90a7364d93 Binary files /dev/null and b/tools/binman/test/u_boot_ucode_ptr differ diff --git a/tools/binman/test/u_boot_ucode_ptr.c b/tools/binman/test/u_boot_ucode_ptr.c new file mode 100644 index 0000000000000000000000000000000000000000..434c9f44003720fba57bf0e9bd8bfb73d68ecdec --- /dev/null +++ b/tools/binman/test/u_boot_ucode_ptr.c @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2016 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + * + * Simple program to create a _dt_ucode_base_size symbol which can be read + * by 'nm'. This is used by binman tests. + * + * Build with: + * cc -march=i386 -m32 -o u_boot_ucode_ptr -T u_boot_ucode_ptr.lds -nostdlib \ + u_boot_ucode_ptr.c + */ + +static unsigned long _dt_ucode_base_size[2] + __attribute__((section(".ucode"))) = {1, 2}; diff --git a/tools/binman/test/u_boot_ucode_ptr.lds b/tools/binman/test/u_boot_ucode_ptr.lds new file mode 100644 index 0000000000000000000000000000000000000000..167debfe348630187f3edcba73ba34b4473a45c4 --- /dev/null +++ b/tools/binman/test/u_boot_ucode_ptr.lds @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2016 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") +OUTPUT_ARCH(i386) +ENTRY(_start) + +SECTIONS +{ + . = 0xfffffdf0; + _start = .; + .ucode : { + *(.ucode) + } +}