[U-Boot] [PATCH v2 35/37] binman: Add support for Intel IFWI entries

Simon Glass sjg at chromium.org
Mon Jul 8 19:18:54 UTC 2019


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 <sjg at chromium.org>
---

Changes in v2: None

 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 65ba2391e69..adea578080c 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 00000000000..8c79b2dd291
--- /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 <sjg at chromium.org>
+#
+# 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 14abfbf774f..1355c4f55d3 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 00000000000..63b5972cc8e
--- /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 00000000000..21ec4654ffe
--- /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 00000000000..62486fd990e
--- /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%<mnt9=#BWpO4b~+vLOWC+N
zGEDm5X){K_?udv=$0N5mnzpvuJ8;ilP_{_yCCgv&e=NC2ifq&M3zhD9#`K=wJm+M&
zU)r}bMQPpNTX@)B&#nJbw@>iwic{C_dF=b~^?`Hc!()y2E=_)}AHVn9-x@!`?a$ax
zzr0fzJx_kkYyR8jE{kOgS41Cs at VMwo&FeqCWk3Jr%+r+;%-1{H_bktB+NF)6b33x4
z?USzmm^aJ#Y{$DD#{X{4Ib_Ss!0 at N1-23<Agx?9(x4wTguZTXCquni7ta;GiB<ODE
z)vRjW>+epq8>v6)m>F|_ozktf7elWHSAVcnPA}eC<?nat<*ii`=}-Ttxo1gQUESUO
z_-KLp!k&+;hO><;S6z<LY<_>{YtX#wvvQZDZ at j17wrsB+0|SF}?!$`zF6VB#UbHIP
zbp7 at 7vLCOGW?OR4^M31Ud8#$@&lMHrGHJt8&lZ2&`sT)7<8$91 at 9(yk30u6kb@%qm
z5nI>)HMz>Y{Cr8$<dW-YPwLI*-?}JaxA^bL8~yWo<NyA<v!^aK*dFLJh7aL4dU7p+
z3?OKTH+%bkGaH06N{)sALtRd);UbUqoo=hFH%8^2o?9L2vRV|BY#z)vd;6DtG=xS&
zU^E0qLjWxVZg7p(A!tD|${h`X(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R
z7!85Z5Eu=C(GVC7fzc2c4S~@RASnd?cT7Fnq181bW63Vz)mOj$$Z=mg?_|5t*296j
zwUWZu&Rcyob?v?2)yx0xlsx%5z9#i=dhzn9QMaQQ85nX{xsU%=FZ!k3b?x!yy>a$i
lx9Z%On{wd&ldm8bY};eMGaRUj;m<t(^-=eBGaRU9006rUF!lfd

literal 0
HcmV?d00001

diff --git a/tools/binman/test/ifwi.bin.gz b/tools/binman/test/ifwi.bin.gz
new file mode 100644
index 0000000000000000000000000000000000000000..25d72892944d7de2813cede71ec96f581cece949
GIT binary patch
literal 1884
zcmb2|=HQs3%ooeRoS9ahsh5<Q$ME*HwfErw5rzlCua);be)Q%-<dPjbMM?!jc5(FW
zT3zyioug^9y<<4L`N5-S|1bS+cI~)|leg%8{W;&hn3$WZo-EM&@=hViuIokil0BmS
zPfKcMoYYSi46T}d;-{<R#-OW<cWLG+J+pgj|6eoSD{$$?)LWG{;-4I^-P at OQ{ioCV
zdHrEeGG8$o&OE33Jae7jk(_h=pY{mq^PF+6`Ra3i#d>ZAh64*sw_Dxbd0ww8D>=P*
z^W@~OUw-I(Z)(?+JN{~)!PWBLwn at 7MOY`Hd->*LY?P+wqeChi7+oxY`ZC%|RqCGwQ
zUGTj-xATuq*m6Jp$^K}cjdFXdw_ILdTb}>t%TLSq^LW0RGXTN<Lk82Hf*3$hmviO+
zW;O_WlpGBKhJEGb0)b1`uAlfR%w}rv&%>pXfuSFnfC2L-b8%e#XaJ3dz-S1J%n+#C
OAO70lJukxo2?hX1K&cV{

literal 0
HcmV?d00001

-- 
2.22.0.410.gd8fdbe21b5-goog



More information about the U-Boot mailing list