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