Commit a89c8f2111bc647b697b776a40227673cfc713e3
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
Makefile
... | ... | @@ -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__": |