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 <sjg@chromium.org>
This commit is contained in:
Simon Glass 2019-07-08 13:18:54 -06:00
parent ac62fba459
commit c5ac138828
8 changed files with 245 additions and 2 deletions

View file

@ -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

View file

@ -0,0 +1,100 @@
# SPDX-License-Identifier: GPL-2.0+
# Copyright (c) 2016 Google, Inc
# Written by Simon Glass <sjg@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

View file

@ -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()

View file

@ -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";
};
};
};
};

View file

@ -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";
};
};
};
};

View file

@ -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";
};
};
};
};

Binary file not shown.

Binary file not shown.