binman: Support optional external blobs

Some blobs are actually not necessary for the board to work correctly. Add
a property to allow this to be indicated. Missing optional blobs do not
cause a build failure.

Signed-off-by: Simon Glass <sjg@chromium.org>
diff --git a/tools/binman/entry.py b/tools/binman/entry.py
index de51d29..d73f301 100644
--- a/tools/binman/entry.py
+++ b/tools/binman/entry.py
@@ -73,7 +73,9 @@
         compress: Compression algoithm used (e.g. 'lz4'), 'none' if none
         orig_offset: Original offset value read from node
         orig_size: Original size value read from node
-        missing: True if this entry is missing its contents
+        missing: True if this entry is missing its contents. Note that if it is
+            optional, this entry will not appear in the list generated by
+            entry.CheckMissing() since it is considered OK for it to be missing.
         allow_missing: Allow children of this entry to be missing (used by
             subclasses such as Entry_section)
         allow_fake: Allow creating a dummy fake file if the blob file is not
@@ -95,6 +97,7 @@
             the entry itself, allowing it to vanish in certain circumstances.
             An absent entry is removed during processing so that it does not
             appear in the map
+        optional (bool): True if this entry contains an optional external blob
     """
     fake_dir = None
 
@@ -138,6 +141,7 @@
         self.elf_fname = None
         self.auto_write_symbols = auto_write_symbols
         self.absent = False
+        self.optional = False
 
     @staticmethod
     def FindEntryClass(etype, expanded):
@@ -289,6 +293,7 @@
         self.offset_unset = fdt_util.GetBool(self._node, 'offset-unset')
         self.extend_size = fdt_util.GetBool(self._node, 'extend-size')
         self.missing_msg = fdt_util.GetString(self._node, 'missing-msg')
+        self.optional = fdt_util.GetBool(self._node, 'optional')
 
         # This is only supported by blobs and sections at present
         self.compress = fdt_util.GetString(self._node, 'compress', 'none')
@@ -1039,14 +1044,15 @@
         self.allow_fake = allow_fake
 
     def CheckMissing(self, missing_list):
-        """Check if any entries in this section have missing external blobs
+        """Check if the entry has missing external blobs
 
-        If there are missing blobs, the entries are added to the list
+        If there are missing (non-optional) blobs, the entries are added to the
+        list
 
         Args:
             missing_list: List of Entry objects to be added to
         """
-        if self.missing:
+        if self.missing and not self.optional:
             missing_list.append(self)
 
     def check_fake_fname(self, fname, size=0):
@@ -1085,6 +1091,17 @@
         # This is meaningless for anything other than blobs
         pass
 
+    def CheckOptional(self, optional_list):
+        """Check if the entry has missing but optional external blobs
+
+        If there are missing (optional) blobs, the entries are added to the list
+
+        Args:
+            optional_list (list): List of Entry objects to be added to
+        """
+        if self.missing and self.optional:
+            optional_list.append(self)
+
     def GetAllowMissing(self):
         """Get whether a section allows missing external blobs