Commit a89c8f2111bc647b697b776a40227673cfc713e3

Authored by Heiko Thiery
Committed by Tom Rini
1 parent a14af7216a
Exists in emb_lf_v2022.04

binman: add support for creating dummy files for external blobs

While converting to binman for an imx8mq board, it has been found that
building in the u-boot CI fails. This is because an imx8mq requires an
external binary (signed_hdmi_imx8m.bin). If this file cannot be found
mkimage fails.
To be able to build this board in the u-boot CI a binman option
(--fake-ext-blobs) is introduced that can be switched on via the u-boot
makefile option BINMAN_FAKE_EXT_BLOBS. With that the needed dummy files are
created.

Signed-off-by: Heiko Thiery <heiko.thiery@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

Showing 10 changed files with 139 additions and 8 deletions Side-by-side Diff

... ... @@ -1315,6 +1315,7 @@
1315 1315 -a tpl-bss-pad=$(if $(CONFIG_TPL_SEPARATE_BSS),,1) \
1316 1316 -a spl-dtb=$(CONFIG_SPL_OF_REAL) \
1317 1317 -a tpl-dtb=$(CONFIG_TPL_OF_REAL) \
  1318 + $(if $(BINMAN_FAKE_EXT_BLOBS),--fake-ext-blobs) \
1318 1319 $(BINMAN_$(@F))
1319 1320  
1320 1321 OBJCOPYFLAGS_u-boot.ldr.hex := -I binary -O ihex
tools/binman/cmdline.py
... ... @@ -52,6 +52,8 @@
52 52 help='Configuration file (.dtb) to use')
53 53 build_parser.add_argument('--fake-dtb', action='store_true',
54 54 help='Use fake device tree contents (for testing only)')
  55 + build_parser.add_argument('--fake-ext-blobs', action='store_true',
  56 + help='Create fake ext blobs with dummy content (for testing only)')
55 57 build_parser.add_argument('-i', '--image', type=str, action='append',
56 58 help='Image filename to build (if not specified, build all)')
57 59 build_parser.add_argument('-I', '--indir', action='append',
tools/binman/control.py
... ... @@ -479,7 +479,8 @@
479 479  
480 480  
481 481 def ProcessImage(image, update_fdt, write_map, get_contents=True,
482   - allow_resize=True, allow_missing=False):
  482 + allow_resize=True, allow_missing=False,
  483 + allow_fake_blobs=False):
483 484 """Perform all steps for this image, including checking and # writing it.
484 485  
485 486 This means that errors found with a later image will be reported after
486 487  
487 488  
... ... @@ -495,12 +496,15 @@
495 496 allow_resize: True to allow entries to change size (this does a re-pack
496 497 of the entries), False to raise an exception
497 498 allow_missing: Allow blob_ext objects to be missing
  499 + allow_fake_blobs: Allow blob_ext objects to be faked with dummy files
498 500  
499 501 Returns:
500   - True if one or more external blobs are missing, False if all are present
  502 + True if one or more external blobs are missing or faked,
  503 + False if all are present
501 504 """
502 505 if get_contents:
503 506 image.SetAllowMissing(allow_missing)
  507 + image.SetAllowFakeBlob(allow_fake_blobs)
504 508 image.GetEntryContents()
505 509 image.GetEntryOffsets()
506 510  
... ... @@ -549,7 +553,13 @@
549 553 tout.Warning("Image '%s' is missing external blobs and is non-functional: %s" %
550 554 (image.name, ' '.join([e.name for e in missing_list])))
551 555 _ShowHelpForMissingBlobs(missing_list)
552   - return bool(missing_list)
  556 + faked_list = []
  557 + image.CheckFakedBlobs(faked_list)
  558 + if faked_list:
  559 + tout.Warning("Image '%s:%s' has faked external blobs and is non-functional: %s" %
  560 + (image.name, image.image_name,
  561 + ' '.join([e.GetDefaultFilename() for e in faked_list])))
  562 + return bool(missing_list) or bool(faked_list)
553 563  
554 564  
555 565 def Binman(args):
556 566  
557 567  
... ... @@ -636,13 +646,15 @@
636 646  
637 647 images = PrepareImagesAndDtbs(dtb_fname, args.image,
638 648 args.update_fdt, use_expanded)
  649 +
639 650 if args.test_section_timeout:
640 651 # Set the first image to timeout, used in testThreadTimeout()
641 652 images[list(images.keys())[0]].test_section_timeout = True
642   - missing = False
  653 + invalid = False
643 654 for image in images.values():
644   - missing |= ProcessImage(image, args.update_fdt, args.map,
645   - allow_missing=args.allow_missing)
  655 + invalid |= ProcessImage(image, args.update_fdt, args.map,
  656 + allow_missing=args.allow_missing,
  657 + allow_fake_blobs=args.fake_ext_blobs)
646 658  
647 659 # Write the updated FDTs to our output files
648 660 for dtb_item in state.GetAllFdts():
... ... @@ -652,7 +664,7 @@
652 664 data = state.GetFdtForEtype('u-boot-dtb').GetContents()
653 665 elf.UpdateFile(*elf_params, data)
654 666  
655   - if missing:
  667 + if invalid:
656 668 tout.Warning("\nSome images are invalid")
657 669  
658 670 # Use this to debug the time take to pack the image
tools/binman/entry.py
... ... @@ -70,6 +70,8 @@
70 70 missing: True if this entry is missing its contents
71 71 allow_missing: Allow children of this entry to be missing (used by
72 72 subclasses such as Entry_section)
  73 + allow_fake: Allow creating a dummy fake file if the blob file is not
  74 + available. This is mainly used for testing.
73 75 external: True if this entry contains an external binary blob
74 76 """
75 77 def __init__(self, section, etype, node, name_prefix=''):
76 78  
... ... @@ -98,8 +100,10 @@
98 100 self._expand_size = False
99 101 self.compress = 'none'
100 102 self.missing = False
  103 + self.faked = False
101 104 self.external = False
102 105 self.allow_missing = False
  106 + self.allow_fake = False
103 107  
104 108 @staticmethod
105 109 def Lookup(node_path, etype, expanded):
... ... @@ -898,6 +902,14 @@
898 902 # This is meaningless for anything other than sections
899 903 pass
900 904  
  905 + def SetAllowFakeBlob(self, allow_fake):
  906 + """Set whether a section allows to create a fake blob
  907 +
  908 + Args:
  909 + allow_fake: True if allowed, False if not allowed
  910 + """
  911 + pass
  912 +
901 913 def CheckMissing(self, missing_list):
902 914 """Check if any entries in this section have missing external blobs
903 915  
... ... @@ -908,6 +920,17 @@
908 920 """
909 921 if self.missing:
910 922 missing_list.append(self)
  923 +
  924 + def CheckFakedBlobs(self, faked_blobs_list):
  925 + """Check if any entries in this section have faked external blobs
  926 +
  927 + If there are faked blobs, the entries are added to the list
  928 +
  929 + Args:
  930 + fake_blobs_list: List of Entry objects to be added to
  931 + """
  932 + # This is meaningless for anything other than blobs
  933 + pass
911 934  
912 935 def GetAllowMissing(self):
913 936 """Get whether a section allows missing external blobs
tools/binman/etype/blob.py
... ... @@ -5,6 +5,8 @@
5 5 # Entry-type module for blobs, which are binary objects read from files
6 6 #
7 7  
  8 +import pathlib
  9 +
8 10 from binman.entry import Entry
9 11 from binman import state
10 12 from dtoc import fdt_util
... ... @@ -36,6 +38,11 @@
36 38 self._filename = fdt_util.GetString(self._node, 'filename', self.etype)
37 39  
38 40 def ObtainContents(self):
  41 + if self.allow_fake and not pathlib.Path(self._filename).is_file():
  42 + with open(self._filename, "wb") as out:
  43 + out.truncate(1024)
  44 + self.faked = True
  45 +
39 46 self._filename = self.GetDefaultFilename()
40 47 self._pathname = tools.GetInputFilename(self._filename,
41 48 self.external and self.section.GetAllowMissing())
... ... @@ -75,4 +82,15 @@
75 82 def ProcessContents(self):
76 83 # The blob may have changed due to WriteSymbols()
77 84 return self.ProcessContentsUpdate(self.data)
  85 +
  86 + def CheckFakedBlobs(self, faked_blobs_list):
  87 + """Check if any entries in this section have faked external blobs
  88 +
  89 + If there are faked blobs, the entries are added to the list
  90 +
  91 + Args:
  92 + fake_blobs_list: List of Entry objects to be added to
  93 + """
  94 + if self.faked:
  95 + faked_blobs_list.append(self)
tools/binman/etype/blob_ext.py
... ... @@ -26,4 +26,12 @@
26 26 def __init__(self, section, etype, node):
27 27 Entry_blob.__init__(self, section, etype, node)
28 28 self.external = True
  29 +
  30 + def SetAllowFakeBlob(self, allow_fake):
  31 + """Set whether the entry allows to create a fake blob
  32 +
  33 + Args:
  34 + allow_fake_blob: True if allowed, False if not allowed
  35 + """
  36 + self.allow_fake = allow_fake
tools/binman/etype/mkimage.py
... ... @@ -61,4 +61,24 @@
61 61 entry = Entry.Create(self, node)
62 62 entry.ReadNode()
63 63 self._mkimage_entries[entry.name] = entry
  64 +
  65 + def SetAllowFakeBlob(self, allow_fake):
  66 + """Set whether the sub nodes allows to create a fake blob
  67 +
  68 + Args:
  69 + allow_fake: True if allowed, False if not allowed
  70 + """
  71 + for entry in self._mkimage_entries.values():
  72 + entry.SetAllowFakeBlob(allow_fake)
  73 +
  74 + def CheckFakedBlobs(self, faked_blobs_list):
  75 + """Check if any entries in this section have faked external blobs
  76 +
  77 + If there are faked blobs, the entries are added to the list
  78 +
  79 + Args:
  80 + faked_blobs_list: List of Entry objects to be added to
  81 + """
  82 + for entry in self._mkimage_entries.values():
  83 + entry.CheckFakedBlobs(faked_blobs_list)
tools/binman/etype/section.py
... ... @@ -689,6 +689,15 @@
689 689 for entry in self._entries.values():
690 690 entry.SetAllowMissing(allow_missing)
691 691  
  692 + def SetAllowFakeBlob(self, allow_fake):
  693 + """Set whether a section allows to create a fake blob
  694 +
  695 + Args:
  696 + allow_fake_blob: True if allowed, False if not allowed
  697 + """
  698 + for entry in self._entries.values():
  699 + entry.SetAllowFakeBlob(allow_fake)
  700 +
692 701 def CheckMissing(self, missing_list):
693 702 """Check if any entries in this section have missing external blobs
694 703  
... ... @@ -699,6 +708,17 @@
699 708 """
700 709 for entry in self._entries.values():
701 710 entry.CheckMissing(missing_list)
  711 +
  712 + def CheckFakedBlobs(self, faked_blobs_list):
  713 + """Check if any entries in this section have faked external blobs
  714 +
  715 + If there are faked blobs, the entries are added to the list
  716 +
  717 + Args:
  718 + fake_blobs_list: List of Entry objects to be added to
  719 + """
  720 + for entry in self._entries.values():
  721 + entry.CheckFakedBlobs(faked_blobs_list)
702 722  
703 723 def _CollectEntries(self, entries, entries_by_name, add_entry):
704 724 """Collect all the entries in an section
tools/binman/ftest.py
... ... @@ -308,7 +308,7 @@
308 308 def _DoTestFile(self, fname, debug=False, map=False, update_dtb=False,
309 309 entry_args=None, images=None, use_real_dtb=False,
310 310 use_expanded=False, verbosity=None, allow_missing=False,
311   - extra_indirs=None, threads=None,
  311 + allow_fake_blobs=False, extra_indirs=None, threads=None,
312 312 test_section_timeout=False, update_fdt_in_elf=None):
313 313 """Run binman with a given test file
314 314  
... ... @@ -331,6 +331,7 @@
331 331 verbosity: Verbosity level to use (0-3, None=don't set it)
332 332 allow_missing: Set the '--allow-missing' flag so that missing
333 333 external binaries just produce a warning instead of an error
  334 + allow_fake_blobs: Set the '--fake-ext-blobs' flag
334 335 extra_indirs: Extra input directories to add using -I
335 336 threads: Number of threads to use (None for default, 0 for
336 337 single-threaded)
... ... @@ -369,6 +370,8 @@
369 370 args.append('-a%s=%s' % (arg, value))
370 371 if allow_missing:
371 372 args.append('-M')
  373 + if allow_fake_blobs:
  374 + args.append('--fake-ext-blobs')
372 375 if update_fdt_in_elf:
373 376 args += ['--update-fdt-in-elf', update_fdt_in_elf]
374 377 if images:
... ... @@ -4660,6 +4663,16 @@
4660 4663 self.assertRegex(
4661 4664 str(e.exception),
4662 4665 "Not enough space in '.*u_boot_binman_embed_sm' for data length.*")
  4666 +
  4667 + def testFakeBlob(self):
  4668 + """Test handling of faking an external blob"""
  4669 + with test_util.capture_sys_output() as (stdout, stderr):
  4670 + self._DoTestFile('203_fake_blob.dts', allow_missing=True,
  4671 + allow_fake_blobs=True)
  4672 + err = stderr.getvalue()
  4673 + self.assertRegex(err,
  4674 + "Image '.*' has faked external blobs and is non-functional: .*")
  4675 + os.remove('binman_faking_test_blob')
4663 4676  
4664 4677  
4665 4678 if __name__ == "__main__":
tools/binman/test/203_fake_blob.dts
  1 +// SPDX-License-Identifier: GPL-2.0+
  2 +
  3 +/dts-v1/;
  4 +
  5 +/ {
  6 + #address-cells = <1>;
  7 + #size-cells = <1>;
  8 +
  9 + binman {
  10 + blob-ext {
  11 + filename = "binman_faking_test_blob";
  12 + };
  13 + };
  14 +};