~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/scripts/make_fit.py

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /scripts/make_fit.py (Version linux-6.11.5) and /scripts/make_fit.py (Version linux-2.6.0)


  1 #!/usr/bin/env python3                            
  2 # SPDX-License-Identifier: GPL-2.0+               
  3 #                                                 
  4 # Copyright 2024 Google LLC                       
  5 # Written by Simon Glass <sjg@chromium.org>        
  6 #                                                 
  7                                                   
  8 """Build a FIT containing a lot of devicetree     
  9                                                   
 10 Usage:                                            
 11     make_fit.py -A arm64 -n 'Linux-6.6' -O lin    
 12         -o arch/arm64/boot/image.fit -k /tmp/k    
 13         @arch/arm64/boot/dts/dtbs-list -E -c g    
 14                                                   
 15 Creates a FIT containing the supplied kernel a    
 16 either specified individually or listed in a f    
 17                                                   
 18 Use -E to generate an external FIT (where the     
 19 FIT data structure). This allows parsing of th    
 20 the entire FIT.                                   
 21                                                   
 22 Use -c to compress the data, using bzip2, gzip    
 23 zstd algorithms.                                  
 24                                                   
 25 Use -D to decompose "composite" DTBs into thei    
 26 deduplicate the resulting base DTBs and DTB ov    
 27 DTBs to be sourced from the kernel build direc    
 28 looks at the .cmd files produced by the kernel    
 29                                                   
 30 The resulting FIT can be booted by bootloaders    
 31 as U-Boot, Linuxboot, Tianocore, etc.             
 32                                                   
 33 Note that this tool does not yet support addin    
 34 """                                               
 35                                                   
 36 import argparse                                   
 37 import collections                                
 38 import os                                         
 39 import subprocess                                 
 40 import sys                                        
 41 import tempfile                                   
 42 import time                                       
 43                                                   
 44 import libfdt                                     
 45                                                   
 46                                                   
 47 # Tool extension and the name of the command-l    
 48 CompTool = collections.namedtuple('CompTool',     
 49                                                   
 50 COMP_TOOLS = {                                    
 51     'bzip2': CompTool('.bz2', 'bzip2'),           
 52     'gzip': CompTool('.gz', 'pigz,gzip'),         
 53     'lz4': CompTool('.lz4', 'lz4'),               
 54     'lzma': CompTool('.lzma', 'lzma'),            
 55     'lzo': CompTool('.lzo', 'lzop'),              
 56     'zstd': CompTool('.zstd', 'zstd'),            
 57 }                                                 
 58                                                   
 59                                                   
 60 def parse_args():                                 
 61     """Parse the program ArgumentParser           
 62                                                   
 63     Returns:                                      
 64         Namespace object containing the argume    
 65     """                                           
 66     epilog = 'Build a FIT from a directory tre    
 67     parser = argparse.ArgumentParser(epilog=ep    
 68     parser.add_argument('-A', '--arch', type=s    
 69           help='Specifies the architecture')      
 70     parser.add_argument('-c', '--compress', ty    
 71           help='Specifies the compression')       
 72     parser.add_argument('-D', '--decompose-dtb    
 73           help='Decompose composite DTBs into     
 74     parser.add_argument('-E', '--external', ac    
 75           help='Convert the FIT to use externa    
 76     parser.add_argument('-n', '--name', type=s    
 77           help='Specifies the name')              
 78     parser.add_argument('-o', '--output', type    
 79           help='Specifies the output file (.fi    
 80     parser.add_argument('-O', '--os', type=str    
 81           help='Specifies the operating system    
 82     parser.add_argument('-k', '--kernel', type    
 83           help='Specifies the (uncompressed) k    
 84     parser.add_argument('-v', '--verbose', act    
 85                         help='Enable verbose o    
 86     parser.add_argument('dtbs', type=str, narg    
 87           help='Specifies the devicetree files    
 88                                                   
 89     return parser.parse_args()                    
 90                                                   
 91                                                   
 92 def setup_fit(fsw, name):                         
 93     """Make a start on writing the FIT            
 94                                                   
 95     Outputs the root properties and the 'image    
 96                                                   
 97     Args:                                         
 98         fsw (libfdt.FdtSw): Object to use for     
 99         name (str): Name of kernel image          
100     """                                           
101     fsw.INC_SIZE = 65536                          
102     fsw.finish_reservemap()                       
103     fsw.begin_node('')                            
104     fsw.property_string('description', f'{name    
105     fsw.property_u32('#address-cells', 1)         
106                                                   
107     fsw.property_u32('timestamp', int(time.tim    
108     fsw.begin_node('images')                      
109                                                   
110                                                   
111 def write_kernel(fsw, data, args):                
112     """Write out the kernel image                 
113                                                   
114     Writes a kernel node along with the requir    
115                                                   
116     Args:                                         
117         fsw (libfdt.FdtSw): Object to use for     
118         data (bytes): Data to write (possibly     
119         args (Namespace): Contains necessary s    
120             arch: FIT architecture, e.g. 'arm6    
121             fit_os: Operating Systems, e.g. 'l    
122             name: Name of OS, e.g. 'Linux-6.6.    
123             compress: Compression algorithm to    
124     """                                           
125     with fsw.add_node('kernel'):                  
126         fsw.property_string('description', arg    
127         fsw.property_string('type', 'kernel_no    
128         fsw.property_string('arch', args.arch)    
129         fsw.property_string('os', args.os)        
130         fsw.property_string('compression', arg    
131         fsw.property('data', data)                
132         fsw.property_u32('load', 0)               
133         fsw.property_u32('entry', 0)              
134                                                   
135                                                   
136 def finish_fit(fsw, entries):                     
137     """Finish the FIT ready for use               
138                                                   
139     Writes the /configurations node and subnod    
140                                                   
141     Args:                                         
142         fsw (libfdt.FdtSw): Object to use for     
143         entries (list of tuple): List of confi    
144             str: Description of model             
145             str: Compatible stringlist            
146     """                                           
147     fsw.end_node()                                
148     seq = 0                                       
149     with fsw.add_node('configurations'):          
150         for model, compat, files in entries:      
151             seq += 1                              
152             with fsw.add_node(f'conf-{seq}'):     
153                 fsw.property('compatible', byt    
154                 fsw.property_string('descripti    
155                 fsw.property('fdt', bytes(''.j    
156                 fsw.property_string('kernel',     
157     fsw.end_node()                                
158                                                   
159                                                   
160 def compress_data(inf, compress):                 
161     """Compress data using a selected algorith    
162                                                   
163     Args:                                         
164         inf (IOBase): Filename containing the     
165         compress (str): Compression algorithm,    
166                                                   
167     Return:                                       
168         bytes: Compressed data                    
169     """                                           
170     if compress == 'none':                        
171         return inf.read()                         
172                                                   
173     comp = COMP_TOOLS.get(compress)               
174     if not comp:                                  
175         raise ValueError(f"Unknown compression    
176                                                   
177     with tempfile.NamedTemporaryFile() as comp    
178         with open(comp_fname.name, 'wb') as ou    
179             done = False                          
180             for tool in comp.tools.split(','):    
181                 try:                              
182                     subprocess.call([tool, '-c    
183                     done = True                   
184                     break                         
185                 except FileNotFoundError:         
186                     pass                          
187             if not done:                          
188                 raise ValueError(f'Missing too    
189             with open(comp_fname.name, 'rb') a    
190                 comp_data = compf.read()          
191     return comp_data                              
192                                                   
193                                                   
194 def output_dtb(fsw, seq, fname, arch, compress    
195     """Write out a single devicetree to the FI    
196                                                   
197     Args:                                         
198         fsw (libfdt.FdtSw): Object to use for     
199         seq (int): Sequence number (1 for firs    
200         fname (str): Filename containing the D    
201         arch: FIT architecture, e.g. 'arm64'      
202         compress (str): Compressed algorithm,     
203     """                                           
204     with fsw.add_node(f'fdt-{seq}'):              
205         fsw.property_string('description', os.    
206         fsw.property_string('type', 'flat_dt')    
207         fsw.property_string('arch', arch)         
208         fsw.property_string('compression', com    
209                                                   
210         with open(fname, 'rb') as inf:            
211             compressed = compress_data(inf, co    
212         fsw.property('data', compressed)          
213                                                   
214                                                   
215 def process_dtb(fname, args):                     
216     """Process an input DTB, decomposing it if    
217                                                   
218     Args:                                         
219         fname (str): Filename containing the D    
220         args (Namespace): Program arguments       
221     Returns:                                      
222         tuple:                                    
223             str: Model name string                
224             str: Root compatible string           
225             files: list of filenames correspon    
226     """                                           
227     # Get the compatible / model information      
228     with open(fname, 'rb') as inf:                
229         data = inf.read()                         
230     fdt = libfdt.FdtRo(data)                      
231     model = fdt.getprop(0, 'model').as_str()      
232     compat = fdt.getprop(0, 'compatible')         
233                                                   
234     if args.decompose_dtbs:                       
235         # Check if the DTB needs to be decompo    
236         path, basename = os.path.split(fname)     
237         cmd_fname = os.path.join(path, f'.{bas    
238         with open(cmd_fname, 'r', encoding='as    
239             cmd = inf.read()                      
240                                                   
241         if 'scripts/dtc/fdtoverlay' in cmd:       
242             # This depends on the structure of    
243             files = cmd.split()                   
244             files = files[files.index('-i') +     
245         else:                                     
246             files = [fname]                       
247     else:                                         
248         files = [fname]                           
249                                                   
250     return (model, compat, files)                 
251                                                   
252 def build_fit(args):                              
253     """Build the FIT from the provided files a    
254                                                   
255     Args:                                         
256         args (Namespace): Program arguments       
257                                                   
258     Returns:                                      
259         tuple:                                    
260             bytes: FIT data                       
261             int: Number of configurations gene    
262             size: Total uncompressed size of d    
263     """                                           
264     seq = 0                                       
265     size = 0                                      
266     fsw = libfdt.FdtSw()                          
267     setup_fit(fsw, args.name)                     
268     entries = []                                  
269     fdts = {}                                     
270                                                   
271     # Handle the kernel                           
272     with open(args.kernel, 'rb') as inf:          
273         comp_data = compress_data(inf, args.co    
274     size += os.path.getsize(args.kernel)          
275     write_kernel(fsw, comp_data, args)            
276                                                   
277     for fname in args.dtbs:                       
278         # Ignore non-DTB (*.dtb) files            
279         if os.path.splitext(fname)[1] != '.dtb    
280             continue                              
281                                                   
282         (model, compat, files) = process_dtb(f    
283                                                   
284         for fn in files:                          
285             if fn not in fdts:                    
286                 seq += 1                          
287                 size += os.path.getsize(fn)       
288                 output_dtb(fsw, seq, fn, args.    
289                 fdts[fn] = seq                    
290                                                   
291         files_seq = [fdts[fn] for fn in files]    
292                                                   
293         entries.append([model, compat, files_s    
294                                                   
295     finish_fit(fsw, entries)                      
296                                                   
297     # Include the kernel itself in the returne    
298     return fsw.as_fdt().as_bytearray(), seq +     
299                                                   
300                                                   
301 def run_make_fit():                               
302     """Run the tool's main logic"""               
303     args = parse_args()                           
304                                                   
305     out_data, count, size = build_fit(args)       
306     with open(args.output, 'wb') as outf:         
307         outf.write(out_data)                      
308                                                   
309     ext_fit_size = None                           
310     if args.external:                             
311         mkimage = os.environ.get('MKIMAGE', 'm    
312         subprocess.check_call([mkimage, '-E',     
313                               stdout=subproces    
314                                                   
315         with open(args.output, 'rb') as inf:      
316             data = inf.read()                     
317         ext_fit = libfdt.FdtRo(data)              
318         ext_fit_size = ext_fit.totalsize()        
319                                                   
320     if args.verbose:                              
321         comp_size = len(out_data)                 
322         print(f'FIT size {comp_size:#x}/{comp_    
323               end='')                             
324         if ext_fit_size:                          
325             print(f', header {ext_fit_size:#x}    
326                   end='')                         
327         print(f', {count} files, uncompressed     
328                                                   
329                                                   
330 if __name__ == "__main__":                        
331     sys.exit(run_make_fit())                      
                                                      

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php