jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / rtos / chromium-ec.c
1 // SPDX-License-Identifier: GPL-2.0-only
2
3 /*
4 * Copyright (c) 2018 National Instruments Corp
5 * Author: Moritz Fischer <moritz.fischer@ettus.com>
6 *
7 * Chromium-EC RTOS Task Awareness
8 */
9
10 #ifdef HAVE_CONFIG_H
11 #include "config.h"
12 #endif
13
14 #include <helper/bits.h>
15 #include <rtos/rtos.h>
16 #include <target/target.h>
17 #include <target/target_type.h>
18
19 #include "rtos_standard_stackings.h"
20
21 #define CROS_EC_MAX_TASKS 32
22 #define CROS_EC_MAX_NAME 200
23 #define CROS_EC_IDLE_STRING "<< idle >>"
24
25 struct chromium_ec_params {
26 const char *target_name;
27 size_t ptr_size;
28 off_t task_offset_next;
29 off_t task_offset_sp;
30 off_t task_offset_events;
31 off_t task_offset_runtime;
32 const struct rtos_register_stacking *stacking;
33 };
34
35 static const struct chromium_ec_params chromium_ec_params_list[] = {
36 {
37 .target_name = "hla_target",
38 .ptr_size = 4,
39 .task_offset_next = 24,
40 .task_offset_sp = 0,
41 .task_offset_events = 4,
42 .task_offset_runtime = 8,
43 .stacking = &rtos_standard_cortex_m3_stacking,
44
45 },
46 {
47 .target_name = "cortex_m",
48 .ptr_size = 4,
49 .task_offset_next = 24,
50 .task_offset_sp = 0,
51 .task_offset_events = 4,
52 .task_offset_runtime = 8,
53 .stacking = &rtos_standard_cortex_m3_stacking,
54 },
55 };
56
57 static const char * const chromium_ec_symbol_list[] = {
58 "start_called",
59 "current_task",
60 "tasks",
61 "tasks_enabled",
62 "tasks_ready",
63 "task_names",
64 "build_info",
65 NULL,
66 };
67
68 enum chromium_ec_symbol_values {
69 CHROMIUM_EC_VAL_START_CALLED = 0,
70 CHROMIUM_EC_VAL_CURRENT_TASK,
71 CHROMIUM_EC_VAL_TASKS,
72 CHROMIUM_EC_VAL_TASKS_ENABLED,
73 CHROMIUM_EC_VAL_TASKS_READY,
74 CHROMIUM_EC_VAL_TASK_NAMES,
75 CHROMIUM_EC_VAL_BUILD_INFO,
76
77 CHROMIUM_EC_VAL_COUNT,
78 };
79
80 #define CROS_EC_MAX_BUILDINFO 512
81
82 static bool chromium_ec_detect_rtos(struct target *target)
83 {
84 char build_info_buf[CROS_EC_MAX_BUILDINFO];
85 enum chromium_ec_symbol_values sym;
86 int ret;
87
88 if (!target || !target->rtos || !target->rtos->symbols)
89 return false;
90
91 for (sym = CHROMIUM_EC_VAL_START_CALLED;
92 sym < CHROMIUM_EC_VAL_COUNT; sym++) {
93 if (target->rtos->symbols[sym].address) {
94 LOG_DEBUG("Chromium-EC: Symbol \"%s\" found",
95 chromium_ec_symbol_list[sym]);
96 } else {
97 LOG_ERROR("Chromium-EC: Symbol \"%s\" missing",
98 chromium_ec_symbol_list[sym]);
99 return false;
100 }
101 }
102
103 ret = target_read_buffer(target,
104 target->rtos->symbols[CHROMIUM_EC_VAL_BUILD_INFO].address,
105 sizeof(build_info_buf),
106 (uint8_t *)build_info_buf);
107
108 if (ret != ERROR_OK)
109 return false;
110
111 LOG_INFO("Chromium-EC: Buildinfo: %s", build_info_buf);
112
113 return target->rtos->symbols &&
114 target->rtos->symbols[CHROMIUM_EC_VAL_START_CALLED].address;
115 }
116
117 static int chromium_ec_create(struct target *target)
118 {
119 struct chromium_ec_params *params;
120 size_t t;
121
122 for (t = 0; t < ARRAY_SIZE(chromium_ec_params_list); t++)
123 if (!strcmp(chromium_ec_params_list[t].target_name, target->type->name)) {
124 params = malloc(sizeof(*params));
125 if (!params) {
126 LOG_ERROR("Chromium-EC: out of memory");
127 return ERROR_FAIL;
128 }
129
130 memcpy(params, &chromium_ec_params_list[t], sizeof(*params));
131 target->rtos->rtos_specific_params = (void *)params;
132 target->rtos->current_thread = 0;
133 target->rtos->thread_details = NULL;
134 target->rtos->thread_count = 0;
135
136 LOG_INFO("Chromium-EC: Using target: %s", target->type->name);
137 return ERROR_OK;
138 }
139
140 LOG_ERROR("Chromium-EC: target not supported: %s", target->type->name);
141 return ERROR_FAIL;
142 }
143
144 static int chromium_ec_get_current_task_ptr(struct rtos *rtos, uint32_t *current_task)
145 {
146 if (!rtos || !rtos->symbols)
147 return ERROR_FAIL;
148
149 return target_read_u32(rtos->target,
150 rtos->symbols[CHROMIUM_EC_VAL_CURRENT_TASK].address,
151 current_task);
152 }
153
154 static int chromium_ec_get_num_tasks(struct rtos *rtos, int *num_tasks)
155 {
156 uint32_t tasks_enabled;
157 int ret, t, found;
158
159 ret = target_read_u32(rtos->target,
160 rtos->symbols[CHROMIUM_EC_VAL_TASKS_ENABLED].address,
161 &tasks_enabled);
162 if (ret != ERROR_OK) {
163 LOG_ERROR("Failed to determine #of tasks");
164 return ret;
165 }
166
167 found = 0;
168 for (t = 0; t < CROS_EC_MAX_TASKS; t++)
169 if (tasks_enabled & BIT(t))
170 found++;
171
172 *num_tasks = found;
173
174 return ERROR_OK;
175 }
176
177 static int chromium_ec_update_threads(struct rtos *rtos)
178 {
179 uint32_t tasks_enabled, tasks_ready, start_called;
180 uint32_t current_task, thread_ptr, name_ptr;
181 char thread_str_buf[CROS_EC_MAX_NAME];
182 int ret, t, num_tasks, tasks_found;
183 struct chromium_ec_params *params;
184 uint8_t runtime_buf[8];
185 uint64_t runtime;
186 uint32_t events;
187
188 params = rtos->rtos_specific_params;
189 if (!params)
190 return ERROR_FAIL;
191
192 if (!rtos->symbols)
193 return ERROR_FAIL;
194
195 num_tasks = 0;
196 ret = chromium_ec_get_num_tasks(rtos, &num_tasks);
197 if (ret != ERROR_OK) {
198 LOG_ERROR("Failed to get number of tasks");
199 return ret;
200 }
201
202 current_task = 0;
203 ret = chromium_ec_get_current_task_ptr(rtos, &current_task);
204 if (ret != ERROR_OK) {
205 LOG_ERROR("Failed to get current task");
206 return ret;
207 }
208 LOG_DEBUG("Current task: %lx tasks_found: %d",
209 (unsigned long)current_task,
210 num_tasks);
211
212 /* set current task to what we read */
213 rtos->current_thread = current_task;
214
215 /* Nuke the old tasks */
216 rtos_free_threadlist(rtos);
217
218 /* One check if task switching has started ... */
219 start_called = 0;
220 ret = target_read_u32(rtos->target, rtos->symbols[CHROMIUM_EC_VAL_START_CALLED].address,
221 &start_called);
222 if (ret != ERROR_OK) {
223 LOG_ERROR("Failed to load start_called");
224 return ret;
225 }
226
227 if (!rtos->current_thread || !num_tasks || !start_called) {
228 num_tasks++;
229
230 rtos->thread_details = malloc(
231 sizeof(struct thread_detail) * num_tasks);
232 rtos->thread_details->threadid = 1;
233 rtos->thread_details->exists = true;
234 rtos->thread_details->extra_info_str = NULL;
235 rtos->thread_details->thread_name_str = strdup("Current Execution");
236
237 if (!num_tasks || !start_called) {
238 rtos->thread_count = 1;
239 return ERROR_OK;
240 }
241 } else {
242 /* create space for new thread details */
243 rtos->thread_details = malloc(
244 sizeof(struct thread_detail) * num_tasks);
245 }
246
247 tasks_enabled = 0;
248 ret = target_read_u32(rtos->target, rtos->symbols[CHROMIUM_EC_VAL_TASKS_ENABLED].address,
249 &tasks_enabled);
250 if (ret != ERROR_OK) {
251 LOG_ERROR("Failed to load tasks_enabled");
252 return ret;
253 }
254
255 tasks_ready = 0;
256 ret = target_read_u32(rtos->target, rtos->symbols[CHROMIUM_EC_VAL_TASKS_READY].address,
257 &tasks_ready);
258 if (ret != ERROR_OK) {
259 LOG_ERROR("Failed to load tasks_ready");
260 return ret;
261 }
262
263 thread_ptr = rtos->symbols[CHROMIUM_EC_VAL_TASKS].address;
264
265 tasks_found = 0;
266 for (t = 0; t < CROS_EC_MAX_TASKS; t++) {
267 if (!(tasks_enabled & BIT(t)))
268 continue;
269
270 if (thread_ptr == current_task)
271 rtos->current_thread = thread_ptr;
272
273 rtos->thread_details[tasks_found].threadid = thread_ptr;
274 ret = target_read_u32(rtos->target,
275 rtos->symbols[CHROMIUM_EC_VAL_TASK_NAMES].address +
276 params->ptr_size * t, &name_ptr);
277 if (ret != ERROR_OK) {
278 LOG_ERROR("Failed to read name_ptr");
279 return ret;
280 }
281
282 /* read name buffer */
283 ret = target_read_buffer(rtos->target, name_ptr, CROS_EC_MAX_NAME,
284 (uint8_t *)thread_str_buf);
285 if (ret != ERROR_OK) {
286 LOG_ERROR("Failed to read task name");
287 return ret;
288 }
289
290 /* sanitize string, gdb chokes on "<< idle >>" */
291 if (thread_str_buf[CROS_EC_MAX_NAME - 1] != '\0')
292 thread_str_buf[CROS_EC_MAX_NAME - 1] = '\0';
293 if (!strncmp(thread_str_buf, CROS_EC_IDLE_STRING, CROS_EC_MAX_NAME))
294 rtos->thread_details[tasks_found].thread_name_str = strdup("IDLE");
295 else
296 rtos->thread_details[tasks_found].thread_name_str = strdup(thread_str_buf);
297
298 events = 0;
299 ret = target_read_u32(rtos->target,
300 thread_ptr + params->task_offset_events,
301 &events);
302 if (ret != ERROR_OK)
303 LOG_ERROR("Failed to get task %d's events", t);
304
305 /* this is a bit kludgy but will do for now */
306 ret = target_read_buffer(rtos->target,
307 thread_ptr + params->task_offset_runtime,
308 sizeof(runtime_buf), runtime_buf);
309 if (ret != ERROR_OK)
310 LOG_ERROR("Failed to get task %d's runtime", t);
311 runtime = target_buffer_get_u64(rtos->target, runtime_buf);
312
313 /* Priority is simply the position in the array */
314 if (thread_ptr == current_task)
315 snprintf(thread_str_buf, sizeof(thread_str_buf),
316 "State: Running, Priority: %u, Events: %" PRIx32 ", Runtime: %" PRIu64 "\n",
317 t, events, runtime);
318 else
319 snprintf(thread_str_buf, sizeof(thread_str_buf),
320 "State: %s, Priority: %u, Events: %" PRIx32 ", Runtime: %" PRIu64 "\n",
321 tasks_ready & BIT(t) ? "Ready" : "Waiting", t,
322 events, runtime);
323
324 rtos->thread_details[tasks_found].extra_info_str = strdup(thread_str_buf);
325 rtos->thread_details[tasks_found].exists = true;
326
327 thread_ptr += params->task_offset_next;
328
329 tasks_found++;
330 }
331
332 rtos->thread_count = tasks_found;
333
334 return ERROR_OK;
335 }
336
337 static int chromium_ec_get_thread_reg_list(struct rtos *rtos,
338 threadid_t threadid,
339 struct rtos_reg **reg_list,
340 int *num_regs)
341 {
342 struct chromium_ec_params *params = rtos->rtos_specific_params;
343 uint32_t stack_ptr = 0;
344 int ret, t;
345
346 for (t = 0; t < rtos->thread_count; t++)
347 if (threadid == rtos->thread_details[t].threadid)
348 break;
349
350 /* if we didn't find threadid, bail */
351 if (t == rtos->thread_count)
352 return ERROR_FAIL;
353
354 ret = target_read_u32(rtos->target,
355 rtos->symbols[CHROMIUM_EC_VAL_TASKS].address +
356 params->task_offset_next * t,
357 &stack_ptr);
358 if (ret != ERROR_OK) {
359 LOG_ERROR("Failed to load TCB");
360 return ret;
361 }
362
363 return rtos_generic_stack_read(rtos->target, params->stacking,
364 stack_ptr, reg_list, num_regs);
365 }
366
367 static int chromium_ec_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
368 {
369 size_t s;
370
371 *symbol_list = calloc(ARRAY_SIZE(chromium_ec_symbol_list),
372 sizeof(struct symbol_table_elem));
373 if (!(*symbol_list)) {
374 LOG_ERROR("Chromium-EC: out of memory");
375 return ERROR_FAIL;
376 }
377
378 for (s = 0; s < ARRAY_SIZE(chromium_ec_symbol_list); s++)
379 (*symbol_list)[s].symbol_name = chromium_ec_symbol_list[s];
380
381 return ERROR_OK;
382 }
383
384 const struct rtos_type chromium_ec_rtos = {
385 .name = "Chromium-EC",
386 .detect_rtos = chromium_ec_detect_rtos,
387 .create = chromium_ec_create,
388 .update_threads = chromium_ec_update_threads,
389 .get_thread_reg_list = chromium_ec_get_thread_reg_list,
390 .get_symbol_list_to_lookup = chromium_ec_get_symbol_list_to_lookup,
391 };

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)