Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | #!/usr/bin/env python3 # SPDX-License-Identifier: GPL-2.0+ """ Expo utility - used for testing of expo features Copyright 2023 Google LLC Written by Simon Glass <sjg@chromium.org> """ import argparse import collections import io import re import subprocess import sys #from u_boot_pylib import cros_subprocess from u_boot_pylib import tools # Parse: # SCENE1 = 7, # or SCENE1 = EXPOID_BASE_ID, # or SCENE2, RE_ENUM = re.compile(r'(\S*)(\s*= ([0-9A-Z_]+))?,') # Parse #define <name> "string" RE_DEF = re.compile(r'#define (\S*)\s*"(.*)"') # Parse EXPOID_BASE_ID = 5, RE_BASE_ID = re.compile(r'\s*EXPOID_BASE_ID\s*= (\d+),') def calc_ids(fname, base_id): """Figure out the value of the enums in a C file Args: fname (str): Filename to parse base_id (int): Base ID (value of EXPOID_BASE_ID) Returns: OrderedDict(): key (str): enum name value (int or str): Value of enum, if int Value of #define, if string """ vals = collections.OrderedDict() with open(fname, 'r', encoding='utf-8') as inf: in_enum = False cur_id = 0 for line in inf.readlines(): line = line.strip() if line == 'enum {': in_enum = True continue if in_enum and line == '};': in_enum = False if in_enum: if not line or line.startswith('/*'): continue m_enum = RE_ENUM.match(line) enum_name = m_enum.group(3) if enum_name: if enum_name == 'EXPOID_BASE_ID': cur_id = base_id else: cur_id = int(enum_name) vals[m_enum.group(1)] = cur_id cur_id += 1 else: m_def = RE_DEF.match(line) if m_def: vals[m_def.group(1)] = tools.to_bytes(m_def.group(2)) return vals def find_base_id(): fname = 'include/expo.h' base_id = None with open(fname, 'r', encoding='utf-8') as inf: for line in inf.readlines(): m_base_id = RE_BASE_ID.match(line) if m_base_id: base_id = int(m_base_id.group(1)) if base_id is None: raise ValueError('EXPOID_BASE_ID not found in expo.h') #print(f'EXPOID_BASE_ID={base_id}') return base_id def run_expo(args): """Run the expo program""" base_id = find_base_id() fname = args.enum_fname or args.layout ids = calc_ids(fname, base_id) if not ids: print(f"Warning: No enum ID values found in file '{fname}'") indata = tools.read_file(args.layout) outf = io.BytesIO() for name, val in ids.items(): if isinstance(val, int): outval = b'%d' % val else: outval = b'"%s"' % val find_str = r'\b%s\b' % name indata = re.sub(tools.to_bytes(find_str), outval, indata) outf.write(indata) data = outf.getvalue() with open('/tmp/asc', 'wb') as outf: outf.write(data) proc = subprocess.run('dtc', input=data, capture_output=True) edtb = proc.stdout if proc.stderr: print(f"Devicetree compiler error:\n{proc.stderr.decode('utf-8')}") return 1 tools.write_file(args.outfile, edtb) return 0 def parse_args(argv): """Parse the command-line arguments Args: argv (list of str): List of string arguments Returns: tuple: (options, args) with the command-line options and arugments. options provides access to the options (e.g. option.debug) args is a list of string arguments """ parser = argparse.ArgumentParser() parser.add_argument('-D', '--debug', action='store_true', help='Enable full debug traceback') parser.add_argument('-e', '--enum-fname', type=str, help='.dts or C file containing enum declaration for expo items') parser.add_argument('-l', '--layout', type=str, required=True, help='Devicetree file source .dts for expo layout (and perhaps enums)') parser.add_argument('-o', '--outfile', type=str, required=True, help='Filename to write expo layout dtb') return parser.parse_args(argv) def start_expo(): """Start the expo program""" args = parse_args(sys.argv[1:]) if not args.debug: sys.tracebacklimit = 0 ret_code = run_expo(args) sys.exit(ret_code) if __name__ == "__main__": start_expo() |