bundle_firmware: allow blobs to defer their processing
In order to make it easier for blobs to be generated from
other other blobs (which are also generated) provide mechanism
for a blob to defer its processing. That way the ordering of the
nodes in the device tree doesn't matter nor is it required to
ensure the ordering is hard coded within the code itself.
BUG=chrome-os-partner:44827
BUG=chromium:445938
BRANCH=None
TEST=Built and ran on glados.
Change-Id: I0dcfa5f4a67044839a65591d5c6522537c2576c3
Signed-off-by: Aaron Durbin <adurbin@chromiium.org>
Reviewed-on: https://chromium-review.googlesource.com/319320
Commit-Ready: Aaron Durbin <adurbin@chromium.org>
Tested-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-by: Patrick Georgi <pgeorgi@chromium.org>
diff --git a/host/lib/bundle_firmware.py b/host/lib/bundle_firmware.py
index d4f99c5..af51fc9 100644
--- a/host/lib/bundle_firmware.py
+++ b/host/lib/bundle_firmware.py
@@ -86,6 +86,10 @@
for name, value in gbb_flag_properties.iteritems():
print ' %-30s %02x' % (name, value)
+class BlobDeferral(Exception):
+ """An error indicating deferal of blob generation."""
+ pass
+
class Bundle:
"""This class encapsulates the entire bundle firmware logic.
@@ -888,6 +892,7 @@
Raises:
CmdError if a command fails.
+ BlobDeferral if a blob is waiting for a dependency.
"""
# stupid pylint insists that sha256 is not in hashlib.
# pylint: disable=E1101
@@ -950,6 +955,42 @@
raise CmdError("Unknown blob type '%s' required in flash map" %
blob_type)
+ def _BuildBlobs(self, pack, fdt):
+ """Build the blob data for the list of blobs in the pack.
+
+ Args:
+ pack: a PackFirmware object describing the firmware image to build.
+ fdt: an fdt object including image layout information
+
+ Raises:
+ CmdError if a command fails.
+ BlobDeferral if dependencies cannot be met because of cycles.
+ """
+ blob_list = pack.GetBlobList()
+ self._out.Info('Building blobs %s\n' % blob_list)
+
+ complete = False
+ deferred_list = []
+
+ # Build blobs allowing for dependencies between blobs. While this is
+ # an potential O(n^2) operation, in practice most blobs aren't dependent
+ # and should resolve in a few passes.
+ while not complete:
+ orig = set(blob_list)
+ for blob_type in blob_list:
+ try:
+ self._BuildBlob(pack, fdt, blob_type)
+ except (BlobDeferral):
+ deferred_list.append(blob_type)
+ if not deferred_list:
+ complete = True
+ # If deferred is the same as the original no progress is being made.
+ if not orig - set(deferred_list):
+ raise BlobDeferral("Blob cyle '%s'" % orig)
+ # Process the deferred blobs
+ blob_list = deferred_list[:]
+ deferred_list = []
+
def _CreateImage(self, gbb, fdt):
"""Create a full firmware image, along with various by-products.
@@ -991,10 +1032,9 @@
if gbb:
pack.AddProperty('gbb', gbb)
- blob_list = pack.GetBlobList()
- self._out.Info('Building blobs %s\n' % blob_list)
- for blob_type in pack.GetBlobList():
- self._BuildBlob(pack, fdt, blob_type)
+
+ # Build the blobs out.
+ self._BuildBlobs(pack, fdt)
self._out.Progress('Packing image')
if gbb:
@@ -1040,7 +1080,7 @@
# Fix up the coreboot image here, since we can't do this until we have
# a final device tree binary.
- if 'coreboot' in blob_list:
+ if 'coreboot' in pack.GetBlobList():
bootstub = pack.GetProperty('coreboot')
fdt = fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
if self.coreboot_elf: