You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

316 lines
8.3 KiB

  1. /***************************************************************************
  2. * Copyright (C) 2007 by Dominic Rath *
  3. * Dominic.Rath@gmx.de *
  4. * *
  5. * Copyright (C) 2007,2008 Øyvind Harboe *
  6. * oyvind.harboe@zylin.com *
  7. * *
  8. * Copyright (C) 2008 by Spencer Oliver *
  9. * spen@spen-soft.co.uk *
  10. * *
  11. * This program is free software; you can redistribute it and/or modify *
  12. * it under the terms of the GNU General Public License as published by *
  13. * the Free Software Foundation; either version 2 of the License, or *
  14. * (at your option) any later version. *
  15. * *
  16. * This program is distributed in the hope that it will be useful, *
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  19. * GNU General Public License for more details. *
  20. * *
  21. * You should have received a copy of the GNU General Public License *
  22. * along with this program. If not, see <http://www.gnu.org/licenses/>. *
  23. ***************************************************************************/
  24. #ifdef HAVE_CONFIG_H
  25. #include "config.h"
  26. #endif
  27. #include <helper/log.h>
  28. #include <helper/binarybuffer.h>
  29. #include "target.h"
  30. #include "target_request.h"
  31. #include "target_type.h"
  32. #include "trace.h"
  33. static bool got_message;
  34. bool target_got_message(void)
  35. {
  36. bool t = got_message;
  37. got_message = false;
  38. return t;
  39. }
  40. static int charmsg_mode;
  41. static int target_asciimsg(struct target *target, uint32_t length)
  42. {
  43. char *msg = malloc(DIV_ROUND_UP(length + 1, 4) * 4);
  44. struct debug_msg_receiver *c = target->dbgmsg;
  45. target->type->target_request_data(target, DIV_ROUND_UP(length, 4), (uint8_t *)msg);
  46. msg[length] = 0;
  47. LOG_DEBUG("%s", msg);
  48. while (c) {
  49. command_output_text(c->cmd_ctx, msg);
  50. c = c->next;
  51. }
  52. return ERROR_OK;
  53. }
  54. static int target_charmsg(struct target *target, uint8_t msg)
  55. {
  56. LOG_USER_N("%c", msg);
  57. return ERROR_OK;
  58. }
  59. static int target_hexmsg(struct target *target, int size, uint32_t length)
  60. {
  61. uint8_t *data = malloc(DIV_ROUND_UP(length * size, 4) * 4);
  62. char line[128];
  63. int line_len;
  64. struct debug_msg_receiver *c = target->dbgmsg;
  65. uint32_t i;
  66. LOG_DEBUG("size: %i, length: %i", (int)size, (int)length);
  67. target->type->target_request_data(target, DIV_ROUND_UP(length * size, 4), (uint8_t *)data);
  68. line_len = 0;
  69. for (i = 0; i < length; i++) {
  70. switch (size) {
  71. case 4:
  72. line_len += snprintf(line + line_len, 128 - line_len, "%8.8" PRIx32 " ", le_to_h_u32(data + (4*i)));
  73. break;
  74. case 2:
  75. line_len += snprintf(line + line_len, 128 - line_len, "%4.4x ", le_to_h_u16(data + (2*i)));
  76. break;
  77. case 1:
  78. line_len += snprintf(line + line_len, 128 - line_len, "%2.2x ", data[i]);
  79. break;
  80. }
  81. if ((i%8 == 7) || (i == length - 1)) {
  82. LOG_DEBUG("%s", line);
  83. while (c) {
  84. command_output_text(c->cmd_ctx, line);
  85. c = c->next;
  86. }
  87. c = target->dbgmsg;
  88. line_len = 0;
  89. }
  90. }
  91. free(data);
  92. return ERROR_OK;
  93. }
  94. /* handle requests from the target received by a target specific
  95. * side-band channel (e.g. ARM7/9 DCC)
  96. */
  97. int target_request(struct target *target, uint32_t request)
  98. {
  99. target_req_cmd_t target_req_cmd = request & 0xff;
  100. assert(target->type->target_request_data);
  101. /* Record that we got a target message for back-off algorithm */
  102. got_message = true;
  103. if (charmsg_mode) {
  104. target_charmsg(target, target_req_cmd);
  105. return ERROR_OK;
  106. }
  107. switch (target_req_cmd) {
  108. case TARGET_REQ_TRACEMSG:
  109. trace_point(target, (request & 0xffffff00) >> 8);
  110. break;
  111. case TARGET_REQ_DEBUGMSG:
  112. if (((request & 0xff00) >> 8) == 0)
  113. target_asciimsg(target, (request & 0xffff0000) >> 16);
  114. else
  115. target_hexmsg(target, (request & 0xff00) >> 8, (request & 0xffff0000) >> 16);
  116. break;
  117. case TARGET_REQ_DEBUGCHAR:
  118. target_charmsg(target, (request & 0x00ff0000) >> 16);
  119. break;
  120. /* case TARGET_REQ_SEMIHOSTING:
  121. * break;
  122. */
  123. default:
  124. LOG_ERROR("unknown target request: %2.2x", target_req_cmd);
  125. break;
  126. }
  127. return ERROR_OK;
  128. }
  129. static int add_debug_msg_receiver(struct command_context *cmd_ctx, struct target *target)
  130. {
  131. struct debug_msg_receiver **p = &target->dbgmsg;
  132. if (!target)
  133. return ERROR_COMMAND_SYNTAX_ERROR;
  134. /* see if there's already a list */
  135. if (*p) {
  136. /* find end of linked list */
  137. while ((*p)->next)
  138. p = &((*p)->next);
  139. p = &((*p)->next);
  140. }
  141. /* add new debug message receiver */
  142. (*p) = malloc(sizeof(struct debug_msg_receiver));
  143. (*p)->cmd_ctx = cmd_ctx;
  144. (*p)->next = NULL;
  145. /* enable callback */
  146. target->dbg_msg_enabled = 1;
  147. return ERROR_OK;
  148. }
  149. static struct debug_msg_receiver *find_debug_msg_receiver(struct command_context *cmd_ctx,
  150. struct target *target)
  151. {
  152. int do_all_targets = 0;
  153. /* if no target has been specified search all of them */
  154. if (!target) {
  155. /* if no targets haven been specified */
  156. if (!all_targets)
  157. return NULL;
  158. target = all_targets;
  159. do_all_targets = 1;
  160. }
  161. /* so we target != null */
  162. struct debug_msg_receiver **p = &target->dbgmsg;
  163. do {
  164. while (*p) {
  165. if ((*p)->cmd_ctx == cmd_ctx)
  166. return *p;
  167. p = &((*p)->next);
  168. }
  169. target = target->next;
  170. } while (target && do_all_targets);
  171. return NULL;
  172. }
  173. int delete_debug_msg_receiver(struct command_context *cmd_ctx, struct target *target)
  174. {
  175. struct debug_msg_receiver **p;
  176. struct debug_msg_receiver *c;
  177. int do_all_targets = 0;
  178. /* if no target has been specified search all of them */
  179. if (!target) {
  180. /* if no targets haven been specified */
  181. if (!all_targets)
  182. return ERROR_OK;
  183. target = all_targets;
  184. do_all_targets = 1;
  185. }
  186. do {
  187. p = &target->dbgmsg;
  188. c = *p;
  189. while (c) {
  190. struct debug_msg_receiver *next = c->next;
  191. if (c->cmd_ctx == cmd_ctx) {
  192. *p = next;
  193. free(c);
  194. if (!*p) {
  195. /* disable callback */
  196. target->dbg_msg_enabled = 0;
  197. }
  198. return ERROR_OK;
  199. } else
  200. p = &(c->next);
  201. c = next;
  202. }
  203. target = target->next;
  204. } while (target && do_all_targets);
  205. return ERROR_OK;
  206. }
  207. COMMAND_HANDLER(handle_target_request_debugmsgs_command)
  208. {
  209. struct target *target = get_current_target(CMD_CTX);
  210. int receiving = 0;
  211. if (!target->type->target_request_data) {
  212. LOG_ERROR("Target %s does not support target requests", target_name(target));
  213. return ERROR_OK;
  214. }
  215. /* see if receiver is already registered */
  216. if (find_debug_msg_receiver(CMD_CTX, target) != NULL)
  217. receiving = 1;
  218. if (CMD_ARGC > 0) {
  219. if (!strcmp(CMD_ARGV[0], "enable") || !strcmp(CMD_ARGV[0], "charmsg")) {
  220. /* don't register if this command context is already receiving */
  221. if (!receiving) {
  222. receiving = 1;
  223. add_debug_msg_receiver(CMD_CTX, target);
  224. }
  225. charmsg_mode = !strcmp(CMD_ARGV[0], "charmsg");
  226. } else if (!strcmp(CMD_ARGV[0], "disable")) {
  227. /* no need to delete a receiver if none is registered */
  228. if (receiving) {
  229. receiving = 0;
  230. delete_debug_msg_receiver(CMD_CTX, target);
  231. }
  232. } else
  233. return ERROR_COMMAND_SYNTAX_ERROR;
  234. }
  235. command_print(CMD, "receiving debug messages from current target %s",
  236. (receiving) ? (charmsg_mode ? "charmsg" : "enabled") : "disabled");
  237. return ERROR_OK;
  238. }
  239. static const struct command_registration target_req_exec_command_handlers[] = {
  240. {
  241. .name = "debugmsgs",
  242. .handler = handle_target_request_debugmsgs_command,
  243. .mode = COMMAND_EXEC,
  244. .help = "display and/or modify reception of debug messages from target",
  245. .usage = "['enable'|'charmsg'|'disable']",
  246. },
  247. COMMAND_REGISTRATION_DONE
  248. };
  249. static const struct command_registration target_req_command_handlers[] = {
  250. {
  251. .name = "target_request",
  252. .mode = COMMAND_ANY,
  253. .help = "target request command group",
  254. .usage = "",
  255. .chain = target_req_exec_command_handlers,
  256. },
  257. COMMAND_REGISTRATION_DONE
  258. };
  259. int target_request_register_commands(struct command_context *cmd_ctx)
  260. {
  261. return register_commands(cmd_ctx, NULL, target_req_command_handlers);
  262. }