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, test_preserve_dirs=False, 62 processes=processes, test_name=test_name, toolpath=[], 63 class_and_module_list=[test_dtoc.TestDtoc,test_src_scan.TestSrcScan]) 64 65 return (0 if result.wasSuccessful() else 1) 66 67 68def RunTestCoverage(build_dir): 69 """Run the tests and check that we get 100% coverage""" 70 sys.argv = [sys.argv[0]] 71 test_util.run_test_coverage('tools/dtoc/dtoc', '/main.py', 72 ['tools/patman/*.py', 'tools/u_boot_pylib/*','*/fdt*', '*test*'], 73 build_dir) 74 75 76def run_dtoc(): 77 epilog = 'Generate C code from devicetree files. See of-plat.rst for details' 78 79 parser = ArgumentParser(epilog=epilog) 80 parser.add_argument('-B', '--build-dir', type=str, default='b', 81 help='Directory containing the build output') 82 parser.add_argument('-c', '--c-output-dir', action='store', 83 help='Select output directory for C files') 84 parser.add_argument( 85 '-C', '--h-output-dir', action='store', 86 help='Select output directory for H files (defaults to --c-output-di)') 87 parser.add_argument('-d', '--dtb-file', action='store', 88 help='Specify the .dtb input file') 89 parser.add_argument( 90 '-i', '--instantiate', action='store_true', default=False, 91 help='Instantiate devices to avoid needing device_bind()') 92 parser.add_argument('--include-disabled', action='store_true', 93 help='Include disabled nodes') 94 parser.add_argument('-o', '--output', action='store', 95 help='Select output filename') 96 parser.add_argument( 97 '-p', '--phase', type=str, 98 help='set phase of U-Boot this invocation is for (spl/tpl)') 99 parser.add_argument('-P', '--processes', type=int, 100 help='set number of processes to use for running tests') 101 if HAVE_TESTS: 102 parser.add_argument('-t', '--test', action='store_true', dest='test', 103 default=False, help='run tests') 104 parser.add_argument( 105 '-T', '--test-coverage', action='store_true', 106 default=False, help='run tests and check for 100%% coverage') 107 parser.add_argument('files', nargs='*') 108 args = parser.parse_args() 109 110 # Run our meagre tests 111 if HAVE_TESTS and args.test: 112 ret_code = run_tests(args.processes, args) 113 sys.exit(ret_code) 114 115 elif HAVE_TESTS and args.test_coverage: 116 RunTestCoverage(args.build_dir) 117 118 else: 119 dtb_platdata.run_steps(args.files, args.dtb_file, args.include_disabled, 120 args.output, 121 [args.c_output_dir, args.h_output_dir], 122 args.phase, instantiate=args.instantiate) 123 124 125if __name__ == '__main__': 126 run_dtoc() 127