target/arm_dap: fix memory leak in error path of dap_create()
[fw/openocd] / src / target / arm_dap.c
1 /***************************************************************************
2  *   Copyright (C) 2016 by Matthias Welwarsky                              *
3  *                                                                         *
4  *   This program is free software; you can redistribute it and/or modify  *
5  *   it under the terms of the GNU General Public License as published by  *
6  *   the Free Software Foundation; either version 2 of the License, or     *
7  *   (at your option) any later version.                                   *
8  *                                                                         *
9  *   This program is distributed in the hope that it will be useful,       *
10  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12  *   GNU General Public License for more details.                          *
13  *                                                                         *
14  *   You should have received a copy of the GNU General Public License     *
15  *   along with this program; if not, write to the                         *
16  *   Free Software Foundation, Inc.,                                       *
17  *                                                                         *
18  ***************************************************************************/
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include <stdlib.h>
25 #include <stdint.h>
26 #include "target/arm_adi_v5.h"
27 #include "target/arm.h"
28 #include "helper/list.h"
29 #include "helper/command.h"
30 #include "transport/transport.h"
31 #include "jtag/interface.h"
32
33 static LIST_HEAD(all_dap);
34
35 extern const struct dap_ops swd_dap_ops;
36 extern const struct dap_ops jtag_dp_ops;
37 extern struct adapter_driver *adapter_driver;
38
39 /* DAP command support */
40 struct arm_dap_object {
41         struct list_head lh;
42         struct adiv5_dap dap;
43         char *name;
44         const struct swd_driver *swd;
45 };
46
47 static void dap_instance_init(struct adiv5_dap *dap)
48 {
49         int i;
50         /* Set up with safe defaults */
51         for (i = 0; i <= DP_APSEL_MAX; i++) {
52                 dap->ap[i].dap = dap;
53                 dap->ap[i].ap_num = i;
54                 /* memaccess_tck max is 255 */
55                 dap->ap[i].memaccess_tck = 255;
56                 /* Number of bits for tar autoincrement, impl. dep. at least 10 */
57                 dap->ap[i].tar_autoincr_block = (1<<10);
58                 /* default CSW value */
59                 dap->ap[i].csw_default = CSW_AHB_DEFAULT;
60                 dap->ap[i].cfg_reg = MEM_AP_REG_CFG_INVALID; /* mem_ap configuration reg (large physical addr, etc.) */
61         }
62         INIT_LIST_HEAD(&dap->cmd_journal);
63         INIT_LIST_HEAD(&dap->cmd_pool);
64 }
65
66 const char *adiv5_dap_name(struct adiv5_dap *self)
67 {
68         struct arm_dap_object *obj = container_of(self, struct arm_dap_object, dap);
69         return obj->name;
70 }
71
72 const struct swd_driver *adiv5_dap_swd_driver(struct adiv5_dap *self)
73 {
74         struct arm_dap_object *obj = container_of(self, struct arm_dap_object, dap);
75         return obj->swd;
76 }
77
78 struct adiv5_dap *adiv5_get_dap(struct arm_dap_object *obj)
79 {
80         return &obj->dap;
81 }
82 struct adiv5_dap *dap_instance_by_jim_obj(Jim_Interp *interp, Jim_Obj *o)
83 {
84         struct arm_dap_object *obj = NULL;
85         const char *name;
86         bool found = false;
87
88         name = Jim_GetString(o, NULL);
89
90         list_for_each_entry(obj, &all_dap, lh) {
91                 if (!strcmp(name, obj->name)) {
92                         found = true;
93                         break;
94                 }
95         }
96
97         if (found)
98                 return &obj->dap;
99         return NULL;
100 }
101
102 static int dap_init_all(void)
103 {
104         struct arm_dap_object *obj;
105         int retval;
106
107         LOG_DEBUG("Initializing all DAPs ...");
108
109         list_for_each_entry(obj, &all_dap, lh) {
110                 struct adiv5_dap *dap = &obj->dap;
111
112                 /* with hla, dap is just a dummy */
113                 if (transport_is_hla())
114                         continue;
115
116                 /* skip taps that are disabled */
117                 if (!dap->tap->enabled)
118                         continue;
119
120                 if (transport_is_swd()) {
121                         dap->ops = &swd_dap_ops;
122                         obj->swd = adapter_driver->swd_ops;
123                 } else if (transport_is_dapdirect_swd()) {
124                         dap->ops = adapter_driver->dap_swd_ops;
125                 } else if (transport_is_dapdirect_jtag()) {
126                         dap->ops = adapter_driver->dap_jtag_ops;
127                 } else
128                         dap->ops = &jtag_dp_ops;
129
130                 retval = dap->ops->connect(dap);
131                 if (retval != ERROR_OK)
132                         return retval;
133         }
134
135         return ERROR_OK;
136 }
137
138 int dap_cleanup_all(void)
139 {
140         struct arm_dap_object *obj, *tmp;
141         struct adiv5_dap *dap;
142
143         list_for_each_entry_safe(obj, tmp, &all_dap, lh) {
144                 dap = &obj->dap;
145                 if (dap->ops && dap->ops->quit)
146                         dap->ops->quit(dap);
147
148                 free(obj->name);
149                 free(obj);
150         }
151
152         return ERROR_OK;
153 }
154
155 enum dap_cfg_param {
156         CFG_CHAIN_POSITION,
157         CFG_IGNORE_SYSPWRUPACK,
158 };
159
160 static const struct jim_nvp nvp_config_opts[] = {
161         { .name = "-chain-position",   .value = CFG_CHAIN_POSITION },
162         { .name = "-ignore-syspwrupack", .value = CFG_IGNORE_SYSPWRUPACK },
163         { .name = NULL, .value = -1 }
164 };
165
166 static int dap_configure(struct jim_getopt_info *goi, struct arm_dap_object *dap)
167 {
168         struct jtag_tap *tap = NULL;
169         struct jim_nvp *n;
170         int e;
171
172         /* parse config or cget options ... */
173         while (goi->argc > 0) {
174                 Jim_SetEmptyResult(goi->interp);
175
176                 e = jim_getopt_nvp(goi, nvp_config_opts, &n);
177                 if (e != JIM_OK) {
178                         jim_getopt_nvp_unknown(goi, nvp_config_opts, 0);
179                         return e;
180                 }
181                 switch (n->value) {
182                 case CFG_CHAIN_POSITION: {
183                         Jim_Obj *o_t;
184                         e = jim_getopt_obj(goi, &o_t);
185                         if (e != JIM_OK)
186                                 return e;
187                         tap = jtag_tap_by_jim_obj(goi->interp, o_t);
188                         if (!tap) {
189                                 Jim_SetResultString(goi->interp, "-chain-position is invalid", -1);
190                                 return JIM_ERR;
191                         }
192                         /* loop for more */
193                         break;
194                 }
195                 case CFG_IGNORE_SYSPWRUPACK:
196                         dap->dap.ignore_syspwrupack = true;
197                         break;
198                 default:
199                         break;
200                 }
201         }
202
203         if (!tap) {
204                 Jim_SetResultString(goi->interp, "-chain-position required when creating DAP", -1);
205                 return JIM_ERR;
206         }
207
208         dap_instance_init(&dap->dap);
209         dap->dap.tap = tap;
210
211         return JIM_OK;
212 }
213
214 static int dap_create(struct jim_getopt_info *goi)
215 {
216         struct command_context *cmd_ctx;
217         static struct arm_dap_object *dap;
218         Jim_Obj *new_cmd;
219         Jim_Cmd *cmd;
220         const char *cp;
221         int e;
222
223         cmd_ctx = current_command_context(goi->interp);
224         assert(cmd_ctx);
225
226         if (goi->argc < 3) {
227                 Jim_WrongNumArgs(goi->interp, 1, goi->argv, "?name? ..options...");
228                 return JIM_ERR;
229         }
230         /* COMMAND */
231         jim_getopt_obj(goi, &new_cmd);
232         /* does this command exist? */
233         cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_NONE);
234         if (cmd) {
235                 cp = Jim_GetString(new_cmd, NULL);
236                 Jim_SetResultFormatted(goi->interp, "Command: %s Exists", cp);
237                 return JIM_ERR;
238         }
239
240         /* Create it */
241         dap = calloc(1, sizeof(struct arm_dap_object));
242         if (!dap)
243                 return JIM_ERR;
244
245         e = dap_configure(goi, dap);
246         if (e != JIM_OK) {
247                 free(dap);
248                 return e;
249         }
250
251         cp = Jim_GetString(new_cmd, NULL);
252         dap->name = strdup(cp);
253
254         struct command_registration dap_commands[] = {
255                 {
256                         .name = cp,
257                         .mode = COMMAND_ANY,
258                         .help = "dap instance command group",
259                         .usage = "",
260                         .chain = dap_instance_commands,
261                 },
262                 COMMAND_REGISTRATION_DONE
263         };
264
265         /* don't expose the instance commands when using hla */
266         if (transport_is_hla())
267                 dap_commands[0].chain = NULL;
268
269         e = register_commands_with_data(cmd_ctx, NULL, dap_commands, dap);
270         if (e != ERROR_OK) {
271                 free(dap->name);
272                 free(dap);
273                 return JIM_ERR;
274         }
275
276         list_add_tail(&dap->lh, &all_dap);
277
278         return JIM_OK;
279 }
280
281 static int jim_dap_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
282 {
283         struct jim_getopt_info goi;
284         jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
285         if (goi.argc < 2) {
286                 Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv,
287                         "<name> [<dap_options> ...]");
288                 return JIM_ERR;
289         }
290         return dap_create(&goi);
291 }
292
293 static int jim_dap_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
294 {
295         struct arm_dap_object *obj;
296
297         if (argc != 1) {
298                 Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
299                 return JIM_ERR;
300         }
301         Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
302         list_for_each_entry(obj, &all_dap, lh) {
303                 Jim_ListAppendElement(interp, Jim_GetResult(interp),
304                         Jim_NewStringObj(interp, obj->name, -1));
305         }
306         return JIM_OK;
307 }
308
309 COMMAND_HANDLER(handle_dap_init)
310 {
311         return dap_init_all();
312 }
313
314 COMMAND_HANDLER(handle_dap_info_command)
315 {
316         struct target *target = get_current_target(CMD_CTX);
317         struct arm *arm = target_to_arm(target);
318         struct adiv5_dap *dap = arm->dap;
319         uint32_t apsel;
320
321         if (!dap) {
322                 LOG_ERROR("DAP instance not available. Probably a HLA target...");
323                 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
324         }
325
326         switch (CMD_ARGC) {
327                 case 0:
328                         apsel = dap->apsel;
329                         break;
330                 case 1:
331                         COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel);
332                         if (apsel > DP_APSEL_MAX)
333                                 return ERROR_COMMAND_SYNTAX_ERROR;
334                         break;
335                 default:
336                         return ERROR_COMMAND_SYNTAX_ERROR;
337         }
338
339         return dap_info_command(CMD, &dap->ap[apsel]);
340 }
341
342 static const struct command_registration dap_subcommand_handlers[] = {
343         {
344                 .name = "create",
345                 .mode = COMMAND_ANY,
346                 .jim_handler = jim_dap_create,
347                 .usage = "name '-chain-position' name",
348                 .help = "Creates a new DAP instance",
349         },
350         {
351                 .name = "names",
352                 .mode = COMMAND_ANY,
353                 .jim_handler = jim_dap_names,
354                 .usage = "",
355                 .help = "Lists all registered DAP instances by name",
356         },
357         {
358                 .name = "init",
359                 .mode = COMMAND_ANY,
360                 .handler = handle_dap_init,
361                 .usage = "",
362                 .help = "Initialize all registered DAP instances"
363         },
364         {
365                 .name = "info",
366                 .handler = handle_dap_info_command,
367                 .mode = COMMAND_EXEC,
368                 .help = "display ROM table for MEM-AP of current target "
369                 "(default currently selected AP)",
370                 .usage = "[ap_num]",
371         },
372         COMMAND_REGISTRATION_DONE
373 };
374
375 static const struct command_registration dap_commands[] = {
376         {
377                 .name = "dap",
378                 .mode = COMMAND_CONFIG,
379                 .help = "DAP commands",
380                 .chain = dap_subcommand_handlers,
381                 .usage = "",
382         },
383         COMMAND_REGISTRATION_DONE
384 };
385
386 int dap_register_commands(struct command_context *cmd_ctx)
387 {
388         return register_commands(cmd_ctx, NULL, dap_commands);
389 }