33
33
import shutil
34
34
import os
35
35
import warnings
36
+ import fnmatch
37
+ import hashlib
38
+ import gzip
39
+ from dataclasses import dataclass
40
+
36
41
# anytree module is defined in Zephyr build requirements
37
42
from anytree import AnyNode , RenderTree
38
43
from packaging import version
@@ -293,6 +298,7 @@ def execute_command(*run_args, **run_kwargs):
293
298
294
299
return subprocess .run (* run_args , ** run_kwargs )
295
300
301
+
296
302
def show_installed_files ():
297
303
"""[summary] Scans output directory building binary tree from files and folders
298
304
then presents them in similar way to linux tree command."""
@@ -309,8 +315,37 @@ def show_installed_files():
309
315
matches = [node for node in nodes if node .long_name == str (entry .parent )]
310
316
assert len (matches ) == 1 , f'"{ entry } " does not have exactly one parent'
311
317
nodes .append (AnyNode (name = entry .name , long_name = str (entry ), parent = matches [0 ]))
318
+
312
319
for pre , _ , node in RenderTree (graph_root ):
313
- print (f"{ pre } { node .name } " )
320
+ fpath = STAGING_DIR / node .long_name
321
+ stem = node .name [:- 3 ] if node .name .endswith (".gz" ) else node .name
322
+
323
+ shasum_trailer = ""
324
+ if checksum_wanted (stem ) and fpath .is_file () and not fpath .is_symlink ():
325
+ shasum_trailer = "\t sha256=" + checksum (fpath )
326
+
327
+ print (f"{ pre } { node .name } { shasum_trailer } " )
328
+
329
+
330
+ # TODO: among other things in this file it should be less SOF-specific;
331
+ # try to move as much as possible to generic Zephyr code. See
332
+ # discussions in https://github.com/zephyrproject-rtos/zephyr/pull/51954
333
+ def checksum_wanted (stem ):
334
+ for pattern in CHECKSUM_WANTED :
335
+ if fnmatch .fnmatch (stem , pattern ):
336
+ return True
337
+ return False
338
+
339
+
340
+ def checksum (fpath ):
341
+ if fpath .suffix == ".gz" :
342
+ inputf = gzip .GzipFile (fpath , "rb" )
343
+ else :
344
+ inputf = open (fpath , "rb" )
345
+ chksum = hashlib .sha256 (inputf .read ()).hexdigest ()
346
+ inputf .close ()
347
+ return chksum
348
+
314
349
315
350
def check_west_installation ():
316
351
west_path = shutil .which ("west" )
@@ -681,6 +716,64 @@ def install_platform(platform, sof_platform_output_dir):
681
716
shutil .copy2 (fw_file_to_copy , install_key_dir )
682
717
683
718
719
+ # sof-info/ directory
720
+
721
+ @dataclass
722
+ class InstFile :
723
+ 'How to install one file'
724
+ name : str
725
+ renameTo : str = None
726
+ # TODO: upgrade this to 3 states: optional/warning/error
727
+ optional : bool = False
728
+ gzip : bool = True
729
+
730
+ installed_files = [
731
+ # Fail if one of these is missing
732
+ InstFile (".config" , "config" ),
733
+ InstFile (BIN_NAME + ".elf" ),
734
+ InstFile (BIN_NAME + ".lst" ),
735
+ InstFile (BIN_NAME + ".map" ),
736
+
737
+ # CONFIG_BUILD_OUTPUT_STRIPPED
738
+ InstFile (BIN_NAME + '.strip' , optional = True ),
739
+
740
+ # Not every platform has intermediate rimage modules
741
+ InstFile ("main-stripped.mod" , optional = True ),
742
+ InstFile ("boot.mod" , optional = True ),
743
+ InstFile ("main.mod" , optional = True ),
744
+ ]
745
+
746
+ sof_info = pathlib .Path (STAGING_DIR ) / "sof-info" / platform
747
+ sof_info .mkdir (parents = True , exist_ok = True )
748
+ for f in installed_files :
749
+ if not pathlib .Path (abs_build_dir / f .name ).is_file () and f .optional :
750
+ continue
751
+ dstname = f .renameTo or f .name
752
+ shutil .copy2 (abs_build_dir / f .name , sof_info / dstname )
753
+ if f .gzip :
754
+ gzip_compress (sof_info / dstname )
755
+
756
+
757
+ # Zephyr's CONFIG_KERNEL_BIN_NAME default value
758
+ BIN_NAME = 'zephyr'
759
+
760
+ CHECKSUM_WANTED = [
761
+ '*.ri' , # Some .ri files have a non-deterministic signature, others not
762
+ '*.strip' , '*stripped*' , # stripped ELF files are reproducible
763
+ 'boot.mod' , # no debug section -> no need to strip this ELF
764
+ BIN_NAME + '.lst' , # objdump --disassemble
765
+ '*.ldc' ,
766
+ ]
767
+
768
+ def gzip_compress (fname , gzdst = None ):
769
+ gzdst = gzdst or pathlib .Path (f"{ fname } .gz" )
770
+ with open (fname , 'rb' ) as inputf :
771
+ # mtime=0 for recursive diff convenience
772
+ with gzip .GzipFile (gzdst , 'wb' , mtime = 0 ) as gzf :
773
+ shutil .copyfileobj (inputf , gzf )
774
+ os .remove (fname )
775
+
776
+
684
777
# As of October 2022, sof_ri_info.py expects .ri files to include a CSE manifest / signature.
685
778
# Don't run sof_ri_info and ignore silently .ri files that don't have one.
686
779
RI_INFO_UNSUPPORTED = []
0 commit comments