1#!/usr/bin/env python3 2# SPDX-License-Identifier: GPL-2.0+ 3# 4# Copyright (C) 2016 Google, Inc 5# Written by Simon Glass <sjg@chromium.org> 6# 7 8"""Device tree to C tool 9 10This tool converts a device tree binary file (.dtb) into two C files. The 11indent is to allow a C program to access data from the device tree without 12having to link against libfdt. By putting the data from the device tree into 13C structures, normal C code can be used. This helps to reduce the size of the 14compiled program. 15 16Dtoc produces several output files - see OUTPUT_FILES in dtb_platdata.py 17 18This tool is used in U-Boot to provide device tree data to SPL without 19increasing the code size of SPL. This supports the CONFIG_SPL_OF_PLATDATA 20options. For more information about the use of this options and tool please 21see doc/driver-model/of-plat.rst 22""" 23 24from argparse import ArgumentParser 25import os 26import pathlib 27import sys 28 29# Bring in the patman libraries 30our_path = os.path.dirname(os.path.realpath(__file__)) 31sys.path.append(os.path.join(our_path, '..')) 32 33# Bring in the libfdt module 34sys.path.insert(0, 'scripts/dtc/pylibfdt') 35sys.path.insert(0, os.path.join(our_path, 36 '../../build-sandbox_spl/scripts/dtc/pylibfdt')) 37 38from dtoc import dtb_platdata 39from u_boot_pylib import test_util 40 41DTOC_DIR = pathlib.Path(__file__).parent 42HAVE_TESTS = (DTOC_DIR / 'test_dtoc.py').exists() 43 44def run_tests(processes, args): 45 """Run all the test we have for dtoc 46 47 Args: 48 processes: Number of processes to use to run tests (None=same as #CPUs) 49 args: List of positional args provided to dtoc. This can hold a test 50 name to execute (as in 'dtoc -t test_empty_file', for example) 51 """ 52 from dtoc import test_src_scan 53 from dtoc import test_dtoc 54 55 sys.argv = [sys.argv[0]] 56 test_name = args.files and args.files[0] or None 57 58 test_dtoc.setup() 59 60 result = test_util.run_test_suites( 61 toolname='dtoc', debug=True, verbosity=1, no_capture=False, 62 test_preserve_dirs=False, processes=processes, test_name=test_name, 63 toolpath=[], 64 class_and_module_list=[test_dtoc.TestDtoc,test_src_scan.TestSrcScan]) 65 66 return (0 if result.wasSuccessful() else 1) 67 68 69def RunTestCoverage(build_dir): 70 """Run the tests and check that we get 100% coverage""" 71 sys.argv = [sys.argv[0]] 72 test_util.run_test_coverage('tools/dtoc/dtoc', '/main.py', 73 ['tools/patman/*.py', 'tools/u_boot_pylib/*','*/fdt*', '*test*'], 74 build_dir) 75 76 77def run_dtoc(): 78 epilog = 'Generate C code from devicetree files. See of-plat.rst for details' 79 80 parser = ArgumentParser(epilog=epilog) 81 parser.add_argument('-B', '--build-dir', type=str, default='b', 82 help='Directory containing the build output') 83 parser.add_argument('-c', '--c-output-dir', action='store', 84 help='Select output directory for C files') 85 parser.add_argument( 86 '-C', '--h-output-dir', action='store', 87 help='Select output directory for H files (defaults to --c-output-di)') 88 parser.add_argument('-d', '--dtb-file', action='store', 89 help='Specify the .dtb input file') 90 parser.add_argument( 91 '-i', '--instantiate', action='store_true', default=False, 92 help='Instantiate devices to avoid needing device_bind()') 93 parser.add_argument('--include-disabled', action='store_true', 94 help='Include disabled nodes') 95 parser.add_argument('-o', '--output', action='store', 96 help='Select output filename') 97 parser.add_argument( 98 '-p', '--phase', type=str, 99 help='set phase of U-Boot this invocation is for (spl/tpl)') 100 parser.add_argument('-P', '--processes', type=int, 101 help='set number of processes to use for running tests') 102 if HAVE_TESTS: 103 parser.add_argument('-t', '--test', action='store_true', dest='test', 104 default=False, help='run tests') 105 parser.add_argument( 106 '-T', '--test-coverage', action='store_true', 107 default=False, help='run tests and check for 100%% coverage') 108 parser.add_argument('files', nargs='*') 109 args = parser.parse_args() 110 111 # Run our meagre tests 112 if HAVE_TESTS and args.test: 113 ret_code = run_tests(args.processes, args) 114 sys.exit(ret_code) 115 116 elif HAVE_TESTS and args.test_coverage: 117 RunTestCoverage(args.build_dir) 118 119 else: 120 dtb_platdata.run_steps(args.files, args.dtb_file, args.include_disabled, 121 args.output, 122 [args.c_output_dir, args.h_output_dir], 123 args.phase, instantiate=args.instantiate) 124 125 126if __name__ == '__main__': 127 run_dtoc() 128