jtag: rewrite commands 'jtag newtap' and 'swd newdap' as COMMAND_HANDLER
[openocd.git] / src / jtag / commands.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4 * Copyright (C) 2005 by Dominic Rath *
5 * Dominic.Rath@gmx.de *
6 * *
7 * Copyright (C) 2007,2008 Øyvind Harboe *
8 * oyvind.harboe@zylin.com *
9 * *
10 * Copyright (C) 2009 SoftPLC Corporation *
11 * http://softplc.com *
12 * dick@softplc.com *
13 * *
14 * Copyright (C) 2009 Zachary T Welch *
15 * zw@superlucidity.net *
16 ***************************************************************************/
17
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21
22 #include <jtag/jtag.h>
23 #include <transport/transport.h>
24 #include "commands.h"
25
26 struct cmd_queue_page {
27 struct cmd_queue_page *next;
28 void *address;
29 size_t used;
30 };
31
32 #define CMD_QUEUE_PAGE_SIZE (1024 * 1024)
33 static struct cmd_queue_page *cmd_queue_pages;
34 static struct cmd_queue_page *cmd_queue_pages_tail;
35
36 struct jtag_command *jtag_command_queue;
37 static struct jtag_command **next_command_pointer = &jtag_command_queue;
38
39 void jtag_queue_command(struct jtag_command *cmd)
40 {
41 if (!transport_is_jtag()) {
42 /*
43 * FIXME: This should not happen!
44 * There could be old code that queues jtag commands with non jtag interfaces so, for
45 * the moment simply highlight it by log an error.
46 * We should fix it quitting with assert(0) because it is an internal error, or returning
47 * an error after call to jtag_command_queue_reset() to free the jtag queue and avoid
48 * memory leaks.
49 * The fix can be applied immediately after next release (v0.11.0 ?)
50 */
51 LOG_ERROR("JTAG API jtag_queue_command() called on non JTAG interface");
52 }
53
54 /* this command goes on the end, so ensure the queue terminates */
55 cmd->next = NULL;
56
57 struct jtag_command **last_cmd = next_command_pointer;
58 assert(last_cmd);
59 assert(!*last_cmd);
60 *last_cmd = cmd;
61
62 /* store location where the next command pointer will be stored */
63 next_command_pointer = &cmd->next;
64 }
65
66 void *cmd_queue_alloc(size_t size)
67 {
68 struct cmd_queue_page **p_page = &cmd_queue_pages;
69 int offset;
70 uint8_t *t;
71
72 /*
73 * WARNING:
74 * We align/round the *SIZE* per below
75 * so that all pointers returned by
76 * this function are reasonably well
77 * aligned.
78 *
79 * If we did not, then an "odd-length" request would cause the
80 * *next* allocation to be at an *odd* address, and because
81 * this function has the same type of api as malloc() - we
82 * must also return pointers that have the same type of
83 * alignment.
84 *
85 * What I do not/have is a reasonable portable means
86 * to align by...
87 *
88 * The solution here, is based on these suggestions.
89 * http://gcc.gnu.org/ml/gcc-help/2008-12/msg00041.html
90 *
91 */
92 union worse_case_align {
93 int i;
94 long l;
95 float f;
96 void *v;
97 };
98 #define ALIGN_SIZE (sizeof(union worse_case_align))
99
100 /* The alignment process. */
101 size = (size + ALIGN_SIZE - 1) & (~(ALIGN_SIZE - 1));
102 /* Done... */
103
104 if (*p_page) {
105 p_page = &cmd_queue_pages_tail;
106 if (CMD_QUEUE_PAGE_SIZE - (*p_page)->used < size)
107 p_page = &((*p_page)->next);
108 }
109
110 if (!*p_page) {
111 *p_page = malloc(sizeof(struct cmd_queue_page));
112 (*p_page)->used = 0;
113 size_t alloc_size = (size < CMD_QUEUE_PAGE_SIZE) ?
114 CMD_QUEUE_PAGE_SIZE : size;
115 (*p_page)->address = malloc(alloc_size);
116 (*p_page)->next = NULL;
117 cmd_queue_pages_tail = *p_page;
118 }
119
120 offset = (*p_page)->used;
121 (*p_page)->used += size;
122
123 t = (*p_page)->address;
124 return t + offset;
125 }
126
127 static void cmd_queue_free(void)
128 {
129 struct cmd_queue_page *page = cmd_queue_pages;
130
131 while (page) {
132 struct cmd_queue_page *last = page;
133 free(page->address);
134 page = page->next;
135 free(last);
136 }
137
138 cmd_queue_pages = NULL;
139 cmd_queue_pages_tail = NULL;
140 }
141
142 void jtag_command_queue_reset(void)
143 {
144 cmd_queue_free();
145
146 jtag_command_queue = NULL;
147 next_command_pointer = &jtag_command_queue;
148 }
149
150 /**
151 * Copy a struct scan_field for insertion into the queue.
152 *
153 * This allocates a new copy of out_value using cmd_queue_alloc.
154 */
155 void jtag_scan_field_clone(struct scan_field *dst, const struct scan_field *src)
156 {
157 dst->num_bits = src->num_bits;
158 dst->out_value = buf_cpy(src->out_value, cmd_queue_alloc(DIV_ROUND_UP(src->num_bits, 8)), src->num_bits);
159 dst->in_value = src->in_value;
160 }
161
162 enum scan_type jtag_scan_type(const struct scan_command *cmd)
163 {
164 int i;
165 int type = 0;
166
167 for (i = 0; i < cmd->num_fields; i++) {
168 if (cmd->fields[i].in_value)
169 type |= SCAN_IN;
170 if (cmd->fields[i].out_value)
171 type |= SCAN_OUT;
172 }
173
174 return type;
175 }
176
177 int jtag_scan_size(const struct scan_command *cmd)
178 {
179 int bit_count = 0;
180 int i;
181
182 /* count bits in scan command */
183 for (i = 0; i < cmd->num_fields; i++)
184 bit_count += cmd->fields[i].num_bits;
185
186 return bit_count;
187 }
188
189 int jtag_build_buffer(const struct scan_command *cmd, uint8_t **buffer)
190 {
191 int bit_count = 0;
192 int i;
193
194 bit_count = jtag_scan_size(cmd);
195 *buffer = calloc(1, DIV_ROUND_UP(bit_count, 8));
196
197 bit_count = 0;
198
199 LOG_DEBUG_IO("%s num_fields: %i",
200 cmd->ir_scan ? "IRSCAN" : "DRSCAN",
201 cmd->num_fields);
202
203 for (i = 0; i < cmd->num_fields; i++) {
204 if (cmd->fields[i].out_value) {
205 if (LOG_LEVEL_IS(LOG_LVL_DEBUG_IO)) {
206 char *char_buf = buf_to_hex_str(cmd->fields[i].out_value,
207 (cmd->fields[i].num_bits > DEBUG_JTAG_IOZ)
208 ? DEBUG_JTAG_IOZ
209 : cmd->fields[i].num_bits);
210
211 LOG_DEBUG("fields[%i].out_value[%i]: 0x%s", i,
212 cmd->fields[i].num_bits, char_buf);
213 free(char_buf);
214 }
215 buf_set_buf(cmd->fields[i].out_value, 0, *buffer,
216 bit_count, cmd->fields[i].num_bits);
217 } else {
218 LOG_DEBUG_IO("fields[%i].out_value[%i]: NULL",
219 i, cmd->fields[i].num_bits);
220 }
221
222 bit_count += cmd->fields[i].num_bits;
223 }
224
225 /*LOG_DEBUG_IO("bit_count totalling: %i", bit_count); */
226
227 return bit_count;
228 }
229
230 int jtag_read_buffer(uint8_t *buffer, const struct scan_command *cmd)
231 {
232 int i;
233 int bit_count = 0;
234 int retval;
235
236 /* we return ERROR_OK, unless a check fails, or a handler reports a problem */
237 retval = ERROR_OK;
238
239 for (i = 0; i < cmd->num_fields; i++) {
240 /* if neither in_value nor in_handler
241 * are specified we don't have to examine this field
242 */
243 if (cmd->fields[i].in_value) {
244 int num_bits = cmd->fields[i].num_bits;
245 uint8_t *captured = buf_set_buf(buffer, bit_count,
246 malloc(DIV_ROUND_UP(num_bits, 8)), 0, num_bits);
247
248 if (LOG_LEVEL_IS(LOG_LVL_DEBUG_IO)) {
249 char *char_buf = buf_to_hex_str(captured,
250 (num_bits > DEBUG_JTAG_IOZ)
251 ? DEBUG_JTAG_IOZ
252 : num_bits);
253
254 LOG_DEBUG("fields[%i].in_value[%i]: 0x%s",
255 i, num_bits, char_buf);
256 free(char_buf);
257 }
258
259 if (cmd->fields[i].in_value)
260 buf_cpy(captured, cmd->fields[i].in_value, num_bits);
261
262 free(captured);
263 }
264 bit_count += cmd->fields[i].num_bits;
265 }
266
267 return retval;
268 }

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)