From c5ac138828c504812f09971a7a95bd73e186782e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 8 Jul 2019 13:18:54 -0600 Subject: [PATCH] binman: Add support for Intel IFWI entries An Integrated Firmware Image is used to hold various binaries used for booting with Apollolake and some later devices. Add support for this. Signed-off-by: Simon Glass --- tools/binman/etype/intel_descriptor.py | 6 +- tools/binman/etype/intel_ifwi.py | 100 ++++++++++++++++++ tools/binman/ftest.py | 55 ++++++++++ tools/binman/test/111_x86-rom-ifwi.dts | 29 +++++ tools/binman/test/112_x86-rom-ifwi-nodesc.dts | 28 +++++ tools/binman/test/113_x86-rom-ifwi-nodata.dts | 29 +++++ tools/binman/test/fitimage.bin.gz | Bin 0 -> 8418 bytes tools/binman/test/ifwi.bin.gz | Bin 0 -> 1884 bytes 8 files changed, 245 insertions(+), 2 deletions(-) create mode 100644 tools/binman/etype/intel_ifwi.py create mode 100644 tools/binman/test/111_x86-rom-ifwi.dts create mode 100644 tools/binman/test/112_x86-rom-ifwi-nodesc.dts create mode 100644 tools/binman/test/113_x86-rom-ifwi-nodata.dts create mode 100644 tools/binman/test/fitimage.bin.gz create mode 100644 tools/binman/test/ifwi.bin.gz diff --git a/tools/binman/etype/intel_descriptor.py b/tools/binman/etype/intel_descriptor.py index 65ba2391e6..adea578080 100644 --- a/tools/binman/etype/intel_descriptor.py +++ b/tools/binman/etype/intel_descriptor.py @@ -60,10 +60,12 @@ class Entry_intel_descriptor(Entry_blob): for i in range(MAX_REGIONS): self._regions.append(Region(self.data, frba, i)) - # Set the offset for ME (Management Engine) only, for now, since the - # others are not used + # Set the offset for ME (Management Engine) and IFWI (Integrated + # Firmware Image), for now, since the others are not used. info = {} if self.HasSibling('intel-me'): info['intel-me'] = [self._regions[REGION_ME].base, self._regions[REGION_ME].size] + if self.HasSibling('intel-ifwi'): + info['intel-ifwi'] = [self._regions[REGION_BIOS].base, None] return info diff --git a/tools/binman/etype/intel_ifwi.py b/tools/binman/etype/intel_ifwi.py new file mode 100644 index 0000000000..8c79b2dd29 --- /dev/null +++ b/tools/binman/etype/intel_ifwi.py @@ -0,0 +1,100 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright (c) 2016 Google, Inc +# Written by Simon Glass +# +# Entry-type module for Intel Management Engine binary blob +# + +from collections import OrderedDict + +from entry import Entry +from blob import Entry_blob +import fdt_util +import tools + +class Entry_intel_ifwi(Entry_blob): + """Entry containing an Intel Integrated Firmware Image (IFWI) file + + Properties / Entry arguments: + - filename: Filename of file to read into entry. This is either the + IFWI file itself, or a file that can be converted into one using a + tool + - convert-fit: If present this indicates that the ifwitool should be + used to convert the provided file into a IFWI. + + This file contains code and data used by the SoC that is required to make + it work. It includes U-Boot TPL, microcode, things related to the CSE + (Converged Security Engine, the microcontroller that loads all the firmware) + and other items beyond the wit of man. + + A typical filename is 'ifwi.bin' for an IFWI file, or 'fitimage.bin' for a + file that will be converted to an IFWI. + + The position of this entry is generally set by the intel-descriptor entry. + + The contents of the IFWI are specified by the subnodes of the IFWI node. + Each subnode describes an entry which is placed into the IFWFI with a given + sub-partition (and optional entry name). + + See README.x86 for information about x86 binary blobs. + """ + def __init__(self, section, etype, node): + Entry_blob.__init__(self, section, etype, node) + self._convert_fit = fdt_util.GetBool(self._node, 'convert-fit') + self._ifwi_entries = OrderedDict() + self._ReadSubnodes() + + def ObtainContents(self): + """Get the contects for the IFWI + + Unfortunately we cannot create anything from scratch here, as Intel has + tools which create precursor binaries with lots of data and settings, + and these are not incorporated into binman. + + The first step is to get a file in the IFWI format. This is either + supplied directly or is extracted from a fitimage using the 'create' + subcommand. + + After that we delete the OBBP sub-partition and add each of the files + that we want in the IFWI file, one for each sub-entry of the IWFI node. + """ + self._pathname = tools.GetInputFilename(self._filename) + + # Create the IFWI file if needed + if self._convert_fit: + inname = self._pathname + outname = tools.GetOutputFilename('ifwi.bin') + tools.RunIfwiTool(inname, tools.CMD_CREATE, outname) + self._filename = 'ifwi.bin' + self._pathname = outname + else: + # Provide a different code path here to ensure we have test coverage + inname = self._pathname + + # Delete OBBP if it is there, then add the required new items. + tools.RunIfwiTool(inname, tools.CMD_DELETE, subpart='OBBP') + + for entry in self._ifwi_entries.values(): + # First get the input data and put it in a file + if not entry.ObtainContents(): + return False + data = entry.GetData() + uniq = self.GetUniqueName() + input_fname = tools.GetOutputFilename('input.%s' % uniq) + tools.WriteFile(input_fname, data) + + tools.RunIfwiTool(inname, + tools.CMD_REPLACE if entry._ifwi_replace else tools.CMD_ADD, + input_fname, entry._ifwi_subpart, entry._ifwi_entry_name) + + self.ReadBlobContents() + return True + + def _ReadSubnodes(self): + """Read the subnodes to find out what should go in this IFWI""" + for node in self._node.subnodes: + entry = Entry.Create(self.section, node) + entry._ifwi_replace = fdt_util.GetBool(node, 'replace') + entry._ifwi_subpart = fdt_util.GetString(node, 'ifwi-subpart') + entry._ifwi_entry_name = fdt_util.GetString(node, 'ifwi-entry') + self._ifwi_entries[entry._ifwi_subpart] = entry diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 14abfbf774..1355c4f55d 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -27,6 +27,7 @@ import fdt import fdt_util import fmap_util import test_util +import gzip import state import tools import tout @@ -876,6 +877,9 @@ class TestFunctional(unittest.TestCase): def testPackX86RomMe(self): """Test that an x86 ROM with an ME region can be created""" data = self._DoReadFile('031_x86-rom-me.dts') + expected_desc = tools.ReadFile(self.TestFile('descriptor.bin')) + if data[:0x1000] != expected_desc: + self.fail('Expected descriptor binary at start of image') self.assertEqual(ME_DATA, data[0x1000:0x1000 + len(ME_DATA)]) def testPackVga(self): @@ -1956,6 +1960,57 @@ class TestFunctional(unittest.TestCase): cfile2 = cbfs.files['hello'] self.assertEqual(U_BOOT_DTB_DATA, cfile2.data) + def _SetupIfwi(self, fname): + """Set up to run an IFWI test + + Args: + fname: Filename of input file to provide (fitimage.bin or ifwi.bin) + """ + self._SetupSplElf() + + # Intel Integrated Firmware Image (IFWI) file + with gzip.open(self.TestFile('%s.gz' % fname), 'rb') as fd: + data = fd.read() + TestFunctional._MakeInputFile(fname,data) + + def _CheckIfwi(self, data): + """Check that an image with an IFWI contains the correct output + + Args: + data: Conents of output file + """ + expected_desc = tools.ReadFile(self.TestFile('descriptor.bin')) + if data[:0x1000] != expected_desc: + self.fail('Expected descriptor binary at start of image') + + # We expect to find the TPL wil in subpart IBBP entry IBBL + image_fname = tools.GetOutputFilename('image.bin') + tpl_fname = tools.GetOutputFilename('tpl.out') + tools.RunIfwiTool(image_fname, tools.CMD_EXTRACT, fname=tpl_fname, + subpart='IBBP', entry_name='IBBL') + + tpl_data = tools.ReadFile(tpl_fname) + self.assertEqual(tpl_data[:len(U_BOOT_TPL_DATA)], U_BOOT_TPL_DATA) + + def testPackX86RomIfwi(self): + """Test that an x86 ROM with Integrated Firmware Image can be created""" + self._SetupIfwi('fitimage.bin') + data = self._DoReadFile('111_x86-rom-ifwi.dts') + self._CheckIfwi(data) + + def testPackX86RomIfwiNoDesc(self): + """Test that an x86 ROM with IFWI can be created from an ifwi.bin file""" + self._SetupIfwi('ifwi.bin') + data = self._DoReadFile('112_x86-rom-ifwi-nodesc.dts') + self._CheckIfwi(data) + + def testPackX86RomIfwiNoData(self): + """Test that an x86 ROM with IFWI handles missing data""" + self._SetupIfwi('ifwi.bin') + with self.assertRaises(ValueError) as e: + data = self._DoReadFile('113_x86-rom-ifwi-nodata.dts') + self.assertIn('Could not complete processing of contents', + str(e.exception)) if __name__ == "__main__": unittest.main() diff --git a/tools/binman/test/111_x86-rom-ifwi.dts b/tools/binman/test/111_x86-rom-ifwi.dts new file mode 100644 index 0000000000..63b5972cc8 --- /dev/null +++ b/tools/binman/test/111_x86-rom-ifwi.dts @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + sort-by-offset; + end-at-4gb; + size = <0x800000>; + intel-descriptor { + filename = "descriptor.bin"; + }; + + intel-ifwi { + offset-unset; + filename = "fitimage.bin"; + convert-fit; + + u-boot-tpl { + replace; + ifwi-subpart = "IBBP"; + ifwi-entry = "IBBL"; + }; + }; + }; +}; diff --git a/tools/binman/test/112_x86-rom-ifwi-nodesc.dts b/tools/binman/test/112_x86-rom-ifwi-nodesc.dts new file mode 100644 index 0000000000..21ec4654ff --- /dev/null +++ b/tools/binman/test/112_x86-rom-ifwi-nodesc.dts @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + sort-by-offset; + end-at-4gb; + size = <0x800000>; + intel-descriptor { + filename = "descriptor.bin"; + }; + + intel-ifwi { + offset-unset; + filename = "ifwi.bin"; + + u-boot-tpl { + replace; + ifwi-subpart = "IBBP"; + ifwi-entry = "IBBL"; + }; + }; + }; +}; diff --git a/tools/binman/test/113_x86-rom-ifwi-nodata.dts b/tools/binman/test/113_x86-rom-ifwi-nodata.dts new file mode 100644 index 0000000000..62486fd990 --- /dev/null +++ b/tools/binman/test/113_x86-rom-ifwi-nodata.dts @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + sort-by-offset; + end-at-4gb; + size = <0x800000>; + intel-descriptor { + filename = "descriptor.bin"; + }; + + intel-ifwi { + offset-unset; + filename = "ifwi.bin"; + + _testing { + return-unknown-contents; + replace; + ifwi-subpart = "IBBP"; + ifwi-entry = "IBBL"; + }; + }; + }; +}; diff --git a/tools/binman/test/fitimage.bin.gz b/tools/binman/test/fitimage.bin.gz new file mode 100644 index 0000000000000000000000000000000000000000..0a9dcfc424845c89436f119eeda8983e12191364 GIT binary patch literal 8418 zcmb2|=HM`q;)`WqPRlIG%uP&B)l16EV|aVpI$I=Ag6%iwic{C_dF=b~^?`Hc!()y2E=_)}AHVn9-x@!`?a$ax zzr0fzJx_kkYyR8jE{kOgS41Cs@VMwo&FeqCWk3Jr%+r+;%-1{H_bktB+NF)6b33x4 z?USzmm^aJ#Y{$DD#{X{4Ib_Ss!0@N1-23+epq8>v6)m>F|_ozktf7elWHSAVcnPA}eC<;S6z{YtX#wvvQZDZ@j17wrsB+0|SF}?!$`zF6VB#UbHIP zbp7@7vLCOGW?OR4^M31Ud8#$@&lMHrGHJt8&lZ2&`sT)7<8$91@9(yk30u6kb@%qm z5nI>)HMz>Y{Cr8$a$i lx9Z%On{wd&ldm8bY};eMGaRUj;mZAh64*sw_Dxbd0ww8D>=P* z^W@~OUw-I(Z)(?+JN{~)!PWBLwn@7MOY`Hd->*LY?P+wqeChi7+oxY`ZC%|RqCGwQ zUGTj-xATuq*m6Jp$^K}cjdFXdw_ILdTb}>t%TLSq^LW0RGXTNpXfuSFnfC2L-b8%e#XaJ3dz-S1J%n+#C OAO70lJukxo2?hX1K&cV{ literal 0 HcmV?d00001 -- 2.39.5