blob: 0e41e19750a076daef1535d36b5eccfed63b6690 [file] [log] [blame]
Andrew Boie945af952017-08-22 13:15:23 -07001#!/usr/bin/env python3
2#
3# Copyright (c) 2017 Intel Corporation
4#
5# SPDX-License-Identifier: Apache-2.0
6
7import sys
8import argparse
9import pprint
10import os
11import struct
Andy Gross6042ae92018-01-22 14:26:49 -060012from elf_helper import ElfHelper
Andrew Boie945af952017-08-22 13:15:23 -070013
Andrew Boie5bd891d2017-09-27 12:59:28 -070014kobjects = [
Anas Nashif72565532017-12-12 08:19:25 -050015 "k_alert",
16 "k_msgq",
17 "k_mutex",
18 "k_pipe",
19 "k_sem",
20 "k_stack",
21 "k_thread",
22 "k_timer",
23 "_k_thread_stack_element",
24 "device"
25]
Andrew Boie5bd891d2017-09-27 12:59:28 -070026
27subsystems = [
Anas Nashif72565532017-12-12 08:19:25 -050028 "adc_driver_api",
29 "aio_cmp_driver_api",
30 "counter_driver_api",
31 "crypto_driver_api",
Andrew Boiece6c8f32018-02-09 13:58:37 -080032 "dma_driver_api",
Anas Nashif72565532017-12-12 08:19:25 -050033 "flash_driver_api",
34 "gpio_driver_api",
35 "i2c_driver_api",
36 "i2s_driver_api",
37 "ipm_driver_api",
Manivannan Sadhasivam26babfc2018-05-03 23:46:58 +053038 "led_driver_api",
Anas Nashif72565532017-12-12 08:19:25 -050039 "pinmux_driver_api",
40 "pwm_driver_api",
41 "entropy_driver_api",
42 "rtc_driver_api",
43 "sensor_driver_api",
44 "spi_driver_api",
45 "uart_driver_api",
46]
Andrew Boie5bd891d2017-09-27 12:59:28 -070047
48
Andrew Boie945af952017-08-22 13:15:23 -070049header = """%compare-lengths
50%define lookup-function-name _k_object_lookup
51%language=ANSI-C
Andrew Boie47f8fd12017-10-05 11:11:02 -070052%global-table
Andrew Boie945af952017-08-22 13:15:23 -070053%struct-type
54%{
55#include <kernel.h>
Andrew Boie31bdfc02017-11-08 16:38:03 -080056#include <toolchain.h>
Andrew Boie47f8fd12017-10-05 11:11:02 -070057#include <syscall_handler.h>
Andrew Boie945af952017-08-22 13:15:23 -070058#include <string.h>
59%}
60struct _k_object;
61%%
62"""
63
64
Andy Gross6042ae92018-01-22 14:26:49 -060065# Different versions of gperf have different prototypes for the lookup
66# function, best to implement the wrapper here. The pointer value itself is
67# turned into a string, we told gperf to expect binary strings that are not
Anas Nashif72565532017-12-12 08:19:25 -050068# NULL-terminated.
Andrew Boie945af952017-08-22 13:15:23 -070069footer = """%%
Andrew Boie31bdfc02017-11-08 16:38:03 -080070struct _k_object *_k_object_gperf_find(void *obj)
Andrew Boie945af952017-08-22 13:15:23 -070071{
72 return _k_object_lookup((const char *)obj, sizeof(void *));
73}
Andrew Boie47f8fd12017-10-05 11:11:02 -070074
Andrew Boie31bdfc02017-11-08 16:38:03 -080075void _k_object_gperf_wordlist_foreach(_wordlist_cb_func_t func, void *context)
Andrew Boie47f8fd12017-10-05 11:11:02 -070076{
77 int i;
78
79 for (i = MIN_HASH_VALUE; i <= MAX_HASH_VALUE; i++) {
80 if (wordlist[i].name) {
81 func(&wordlist[i], context);
82 }
83 }
84}
Andrew Boie31bdfc02017-11-08 16:38:03 -080085
86#ifndef CONFIG_DYNAMIC_OBJECTS
87struct _k_object *_k_object_find(void *obj)
88 ALIAS_OF(_k_object_gperf_find);
89
90void _k_object_wordlist_foreach(_wordlist_cb_func_t func, void *context)
91 ALIAS_OF(_k_object_gperf_wordlist_foreach);
92#endif
Andrew Boie945af952017-08-22 13:15:23 -070093"""
94
95
Andy Gross6042ae92018-01-22 14:26:49 -060096def write_gperf_table(fp, eh, objs, static_begin, static_end):
Andrew Boie945af952017-08-22 13:15:23 -070097 fp.write(header)
98
Andrew Boiebca15da2017-10-15 14:17:48 -070099 for obj_addr, ko in objs.items():
100 obj_type = ko.type_name
Andrew Boie945af952017-08-22 13:15:23 -0700101 # pre-initialized objects fall within this memory range, they are
102 # either completely initialized at build time, or done automatically
103 # at boot during some PRE_KERNEL_* phase
104 initialized = obj_addr >= static_begin and obj_addr < static_end
105
Andy Gross6042ae92018-01-22 14:26:49 -0600106 byte_str = struct.pack("<I" if eh.little_endian else ">I", obj_addr)
Andrew Boie945af952017-08-22 13:15:23 -0700107 fp.write("\"")
108 for byte in byte_str:
109 val = "\\x%02x" % byte
110 fp.write(val)
111
Anas Nashif72565532017-12-12 08:19:25 -0500112 fp.write(
113 "\",{},%s,%s,%d\n" %
114 (obj_type,
115 "K_OBJ_FLAG_INITIALIZED" if initialized else "0",
116 ko.data))
Andrew Boie945af952017-08-22 13:15:23 -0700117
118 fp.write(footer)
119
120
Leandro Pereirac2003672018-04-04 13:50:32 -0700121driver_macro_tpl = """
122#define _SYSCALL_DRIVER_%(driver_upper)s(ptr, op) _SYSCALL_DRIVER_GEN(ptr, op, %(driver_lower)s, %(driver_upper)s)
123"""
124
125def write_validation_output(fp):
126 fp.write("#ifndef __DRIVER_VALIDATION_GEN_H__\n")
127 fp.write("#define __DRIVER_VALIDATION_GEN_H__\n")
128
129 fp.write("""#define _SYSCALL_DRIVER_GEN(ptr, op, driver_lower_case, driver_upper_case) \\
130 do { \\
131 _SYSCALL_OBJ(ptr, K_OBJ_DRIVER_##driver_upper_case); \\
132 _SYSCALL_DRIVER_OP(ptr, driver_lower_case##_driver_api, op); \\
133 } while (0)\n\n""");
134
135 for subsystem in subsystems:
136 subsystem = subsystem.replace("_driver_api", "")
137
138 fp.write(driver_macro_tpl % {
139 "driver_lower": subsystem.lower(),
140 "driver_upper": subsystem.upper(),
141 })
142
143 fp.write("#endif /* __DRIVER_VALIDATION_GEN_H__ */\n")
144
Leandro Pereira39dc7d02018-04-05 13:59:33 -0700145
146def write_kobj_types_output(fp):
147 fp.write("/* Core kernel objects */\n")
148 for kobj in kobjects:
149 if kobj == "device":
150 continue
151
152 if kobj.startswith("k_"):
153 kobj = kobj[2:]
154 elif kobj.startswith("_k_"):
155 kobj = kobj[2:]
156
157 fp.write("K_OBJ_%s,\n" % kobj.upper())
158
159 fp.write("/* Driver subsystems */\n")
160 for subsystem in subsystems:
161 subsystem = subsystem.replace("_driver_api", "").upper()
162 fp.write("K_OBJ_DRIVER_%s,\n" % subsystem)
163
164
165def write_kobj_otype_output(fp):
166 fp.write("/* Core kernel objects */\n")
167 for kobj in kobjects:
168 if kobj == "device":
169 continue
170
171 if kobj.startswith("k_"):
172 kobj = kobj[2:]
173 elif kobj.startswith("_k_"):
174 kobj = kobj[2:]
175
176 fp.write('case K_OBJ_%s: return "%s";\n' % (
177 kobj.upper(),
178 kobj
179 ))
180
181 fp.write("/* Driver subsystems */\n")
182 for subsystem in subsystems:
183 subsystem = subsystem.replace("_driver_api", "")
184 fp.write('case K_OBJ_DRIVER_%s: return "%s driver";\n' % (
185 subsystem.upper(),
186 subsystem
187 ))
188
189
Andrew Boie945af952017-08-22 13:15:23 -0700190def parse_args():
191 global args
192
Anas Nashif72565532017-12-12 08:19:25 -0500193 parser = argparse.ArgumentParser(
194 description=__doc__,
195 formatter_class=argparse.RawDescriptionHelpFormatter)
Andrew Boie945af952017-08-22 13:15:23 -0700196
Leandro Pereirac2003672018-04-04 13:50:32 -0700197 parser.add_argument("-k", "--kernel", required=False,
Anas Nashif72565532017-12-12 08:19:25 -0500198 help="Input zephyr ELF binary")
199 parser.add_argument(
Leandro Pereirac2003672018-04-04 13:50:32 -0700200 "-g", "--gperf-output", required=False,
Anas Nashif72565532017-12-12 08:19:25 -0500201 help="Output list of kernel object addresses for gperf use")
Leandro Pereirac2003672018-04-04 13:50:32 -0700202 parser.add_argument(
203 "-V", "--validation-output", required=False,
204 help="Output driver validation macros")
Leandro Pereira39dc7d02018-04-05 13:59:33 -0700205 parser.add_argument(
206 "-K", "--kobj-types-output", required=False,
207 help="Output k_object enum values")
208 parser.add_argument(
209 "-S", "--kobj-otype-output", required=False,
210 help="Output case statements for otype_to_str()")
Andrew Boie945af952017-08-22 13:15:23 -0700211 parser.add_argument("-v", "--verbose", action="store_true",
Anas Nashif72565532017-12-12 08:19:25 -0500212 help="Print extra debugging information")
Andrew Boie945af952017-08-22 13:15:23 -0700213 args = parser.parse_args()
Sebastian Bøe4971d2a2017-12-28 17:34:50 +0100214 if "VERBOSE" in os.environ:
215 args.verbose = 1
Andrew Boie945af952017-08-22 13:15:23 -0700216
217
218def main():
219 parse_args()
220
Leandro Pereirac2003672018-04-04 13:50:32 -0700221 if args.gperf_output:
222 eh = ElfHelper(args.kernel, args.verbose, kobjects, subsystems)
223 syms = eh.get_symbols()
224 max_threads = syms["CONFIG_MAX_THREAD_BYTES"] * 8
225 objs = eh.find_kobjects(syms)
Andrew Boie945af952017-08-22 13:15:23 -0700226
Leandro Pereirac2003672018-04-04 13:50:32 -0700227 if eh.get_thread_counter() > max_threads:
228 sys.stderr.write("Too many thread objects (%d)\n" % thread_counter)
229 sys.stderr.write("Increase CONFIG_MAX_THREAD_BYTES to %d\n",
230 -(-thread_counter // 8))
231 sys.exit(1)
Andrew Boie818a96d2017-11-03 09:00:35 -0700232
Leandro Pereirac2003672018-04-04 13:50:32 -0700233 with open(args.gperf_output, "w") as fp:
234 write_gperf_table(fp, eh, objs,
235 syms["_static_kernel_objects_begin"],
236 syms["_static_kernel_objects_end"])
237
238 if args.validation_output:
239 with open(args.validation_output, "w") as fp:
240 write_validation_output(fp)
Anas Nashif72565532017-12-12 08:19:25 -0500241
Leandro Pereira39dc7d02018-04-05 13:59:33 -0700242 if args.kobj_types_output:
243 with open(args.kobj_types_output, "w") as fp:
244 write_kobj_types_output(fp)
245
246 if args.kobj_otype_output:
247 with open(args.kobj_otype_output, "w") as fp:
248 write_kobj_otype_output(fp)
Andrew Boie945af952017-08-22 13:15:23 -0700249
250if __name__ == "__main__":
251 main()