target: remove unused function target_buffer_get_u8()
[openocd.git] / src / target / semihosting_common.c
1 /***************************************************************************
2 * Copyright (C) 2018 by Liviu Ionescu *
3 * <ilg@livius.net> *
4 * *
5 * Copyright (C) 2018 by Marvell Technology Group Ltd. *
6 * Written by Nicolas Pitre <nico@marvell.com> *
7 * *
8 * Copyright (C) 2010 by Spencer Oliver *
9 * spen@spen-soft.co.uk *
10 * *
11 * Copyright (C) 2016 by Square, Inc. *
12 * Steven Stallion <stallion@squareup.com> *
13 * *
14 * This program is free software; you can redistribute it and/or modify *
15 * it under the terms of the GNU General Public License as published by *
16 * the Free Software Foundation; either version 2 of the License, or *
17 * (at your option) any later version. *
18 * *
19 * This program is distributed in the hope that it will be useful, *
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
22 * GNU General Public License for more details. *
23 * *
24 * You should have received a copy of the GNU General Public License *
25 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
26 ***************************************************************************/
27
28 /**
29 * @file
30 * Common ARM semihosting support.
31 *
32 * Semihosting enables code running on a target to use some of the I/O
33 * facilities on the host computer. The target application must be linked
34 * against a library that forwards operation requests by using an
35 * instruction trapped by the debugger.
36 *
37 * Details can be found in
38 * "Semihosting for AArch32 and AArch64, Release 2.0"
39 * https://static.docs.arm.com/100863/0200/semihosting.pdf
40 * from ARM Ltd.
41 */
42
43 #ifdef HAVE_CONFIG_H
44 #include "config.h"
45 #endif
46
47 #include "target.h"
48 #include "target_type.h"
49 #include "semihosting_common.h"
50
51 #include <helper/binarybuffer.h>
52 #include <helper/log.h>
53 #include <sys/stat.h>
54
55 static const int open_modeflags[12] = {
56 O_RDONLY,
57 O_RDONLY | O_BINARY,
58 O_RDWR,
59 O_RDWR | O_BINARY,
60 O_WRONLY | O_CREAT | O_TRUNC,
61 O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
62 O_RDWR | O_CREAT | O_TRUNC,
63 O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
64 O_WRONLY | O_CREAT | O_APPEND,
65 O_WRONLY | O_CREAT | O_APPEND | O_BINARY,
66 O_RDWR | O_CREAT | O_APPEND,
67 O_RDWR | O_CREAT | O_APPEND | O_BINARY
68 };
69
70 static int semihosting_common_fileio_info(struct target *target,
71 struct gdb_fileio_info *fileio_info);
72 static int semihosting_common_fileio_end(struct target *target, int result,
73 int fileio_errno, bool ctrl_c);
74
75 static int semihosting_read_fields(struct target *target, size_t number,
76 uint8_t *fields);
77 static int semihosting_write_fields(struct target *target, size_t number,
78 uint8_t *fields);
79 static uint64_t semihosting_get_field(struct target *target, size_t index,
80 uint8_t *fields);
81 static void semihosting_set_field(struct target *target, uint64_t value,
82 size_t index,
83 uint8_t *fields);
84
85 /* Attempts to include gdb_server.h failed. */
86 extern int gdb_actual_connections;
87
88 /**
89 * Initialize common semihosting support.
90 *
91 * @param target Pointer to the target to initialize.
92 * @return An error status if there is a problem during initialization.
93 */
94 int semihosting_common_init(struct target *target, void *setup,
95 void *post_result)
96 {
97 LOG_DEBUG(" ");
98
99 target->fileio_info = malloc(sizeof(*target->fileio_info));
100 if (target->fileio_info == NULL) {
101 LOG_ERROR("out of memory");
102 return ERROR_FAIL;
103 }
104 memset(target->fileio_info, 0, sizeof(*target->fileio_info));
105
106 struct semihosting *semihosting;
107 semihosting = malloc(sizeof(*target->semihosting));
108 if (semihosting == NULL) {
109 LOG_ERROR("out of memory");
110 return ERROR_FAIL;
111 }
112
113 semihosting->is_active = false;
114 semihosting->is_fileio = false;
115 semihosting->hit_fileio = false;
116 semihosting->is_resumable = false;
117 semihosting->has_resumable_exit = false;
118 semihosting->word_size_bytes = 0;
119 semihosting->op = -1;
120 semihosting->param = 0;
121 semihosting->result = -1;
122 semihosting->sys_errno = -1;
123 semihosting->cmdline = NULL;
124
125 /* If possible, update it in setup(). */
126 semihosting->setup_time = clock();
127
128 semihosting->setup = setup;
129 semihosting->post_result = post_result;
130
131 target->semihosting = semihosting;
132
133 target->type->get_gdb_fileio_info = semihosting_common_fileio_info;
134 target->type->gdb_fileio_end = semihosting_common_fileio_end;
135
136 return ERROR_OK;
137 }
138
139 /**
140 * Portable implementation of ARM semihosting calls.
141 * Performs the currently pending semihosting operation
142 * encoded in target->semihosting.
143 */
144 int semihosting_common(struct target *target)
145 {
146 struct semihosting *semihosting = target->semihosting;
147 if (!semihosting) {
148 /* Silently ignore if the semhosting field was not set. */
149 return ERROR_OK;
150 }
151
152 struct gdb_fileio_info *fileio_info = target->fileio_info;
153
154 /*
155 * By default return an error.
156 * The actual result must be set by each function
157 */
158 semihosting->result = -1;
159
160 /* Most operations are resumable, except the two exit calls. */
161 semihosting->is_resumable = true;
162
163 int retval;
164
165 /* Enough space to hold 4 long words. */
166 uint8_t fields[4*8];
167
168 LOG_DEBUG("op=0x%x, param=0x%" PRIx64, (int)semihosting->op,
169 semihosting->param);
170
171 switch (semihosting->op) {
172
173 case SEMIHOSTING_SYS_CLOCK: /* 0x10 */
174 /*
175 * Returns the number of centiseconds (hundredths of a second)
176 * since the execution started.
177 *
178 * Values returned can be of limited use for some benchmarking
179 * purposes because of communication overhead or other
180 * agent-specific factors. For example, with a debug hardware
181 * unit the request is passed back to the host for execution.
182 * This can lead to unpredictable delays in transmission and
183 * process scheduling.
184 *
185 * Use this function to calculate time intervals, by calculating
186 * differences between intervals with and without the code
187 * sequence to be timed.
188 *
189 * Entry
190 * The PARAMETER REGISTER must contain 0. There are no other
191 * parameters.
192 *
193 * Return
194 * On exit, the RETURN REGISTER contains:
195 * - The number of centiseconds since some arbitrary start
196 * point, if the call is successful.
197 * - –1 if the call is not successful. For example, because
198 * of a communications error.
199 */
200 {
201 clock_t delta = clock() - semihosting->setup_time;
202
203 semihosting->result = delta / (CLOCKS_PER_SEC / 100);
204 }
205 break;
206
207 case SEMIHOSTING_SYS_CLOSE: /* 0x02 */
208 /*
209 * Closes a file on the host system. The handle must reference
210 * a file that was opened with SYS_OPEN.
211 *
212 * Entry
213 * On entry, the PARAMETER REGISTER contains a pointer to a
214 * one-field argument block:
215 * - field 1 Contains a handle for an open file.
216 *
217 * Return
218 * On exit, the RETURN REGISTER contains:
219 * - 0 if the call is successful
220 * - –1 if the call is not successful.
221 */
222 retval = semihosting_read_fields(target, 1, fields);
223 if (retval != ERROR_OK)
224 return retval;
225 else {
226 int fd = semihosting_get_field(target, 0, fields);
227 if (semihosting->is_fileio) {
228 if (fd == 0 || fd == 1 || fd == 2) {
229 semihosting->result = 0;
230 break;
231 }
232 semihosting->hit_fileio = true;
233 fileio_info->identifier = "close";
234 fileio_info->param_1 = fd;
235 } else {
236 semihosting->result = close(fd);
237 semihosting->sys_errno = errno;
238
239 LOG_DEBUG("close(%d)=%d", fd, (int)semihosting->result);
240 }
241 }
242 break;
243
244 case SEMIHOSTING_SYS_ERRNO: /* 0x13 */
245 /*
246 * Returns the value of the C library errno variable that is
247 * associated with the semihosting implementation. The errno
248 * variable can be set by a number of C library semihosted
249 * functions, including:
250 * - SYS_REMOVE
251 * - SYS_OPEN
252 * - SYS_CLOSE
253 * - SYS_READ
254 * - SYS_WRITE
255 * - SYS_SEEK.
256 *
257 * Whether errno is set or not, and to what value, is entirely
258 * host-specific, except where the ISO C standard defines the
259 * behavior.
260 *
261 * Entry
262 * There are no parameters. The PARAMETER REGISTER must be 0.
263 *
264 * Return
265 * On exit, the RETURN REGISTER contains the value of the C
266 * library errno variable.
267 */
268 semihosting->result = semihosting->sys_errno;
269 break;
270
271 case SEMIHOSTING_SYS_EXIT: /* 0x18 */
272 /*
273 * Note: SYS_EXIT was called angel_SWIreason_ReportException in
274 * previous versions of the documentation.
275 *
276 * An application calls this operation to report an exception
277 * to the debugger directly. The most common use is to report
278 * that execution has completed, using ADP_Stopped_ApplicationExit.
279 *
280 * Note: This semihosting operation provides no means for 32-bit
281 * callers to indicate an application exit with a specified exit
282 * code. Semihosting callers may prefer to check for the presence
283 * of the SH_EXT_EXTENDED_REPORT_EXCEPTION extension and use
284 * the SYS_REPORT_EXCEPTION_EXTENDED operation instead, if it
285 * is available.
286 *
287 * Entry (32-bit)
288 * On entry, the PARAMETER register is set to a reason code
289 * describing the cause of the trap. Not all semihosting client
290 * implementations will necessarily trap every corresponding
291 * event. Important reason codes are:
292 *
293 * - ADP_Stopped_ApplicationExit 0x20026
294 * - ADP_Stopped_RunTimeErrorUnknown 0x20023
295 *
296 * Entry (64-bit)
297 * On entry, the PARAMETER REGISTER contains a pointer to a
298 * two-field argument block:
299 * - field 1 The exception type, which is one of the set of
300 * reason codes in the above tables.
301 * - field 2 A subcode, whose meaning depends on the reason
302 * code in field 1.
303 * In particular, if field 1 is ADP_Stopped_ApplicationExit
304 * then field 2 is an exit status code, as passed to the C
305 * standard library exit() function. A simulator receiving
306 * this request must notify a connected debugger, if present,
307 * and then exit with the specified status.
308 *
309 * Return
310 * No return is expected from these calls. However, it is
311 * possible for the debugger to request that the application
312 * continues by performing an RDI_Execute request or equivalent.
313 * In this case, execution continues with the registers as they
314 * were on entry to the operation, or as subsequently modified
315 * by the debugger.
316 */
317 if (semihosting->word_size_bytes == 8) {
318 retval = semihosting_read_fields(target, 2, fields);
319 if (retval != ERROR_OK)
320 return retval;
321 else {
322 int type = semihosting_get_field(target, 0, fields);
323 int code = semihosting_get_field(target, 1, fields);
324
325 if (type == ADP_STOPPED_APPLICATION_EXIT) {
326 if (!gdb_actual_connections)
327 exit(code);
328 else {
329 fprintf(stderr,
330 "semihosting: *** application exited with %d ***\n",
331 code);
332 }
333 } else {
334 fprintf(stderr,
335 "semihosting: application exception %#x\n",
336 type);
337 }
338 }
339 } else {
340 if (semihosting->param == ADP_STOPPED_APPLICATION_EXIT) {
341 if (!gdb_actual_connections)
342 exit(0);
343 else {
344 fprintf(stderr,
345 "semihosting: *** application exited normally ***\n");
346 }
347 } else if (semihosting->param == ADP_STOPPED_RUN_TIME_ERROR) {
348 /* Chosen more or less arbitrarly to have a nicer message,
349 * otherwise all other return the same exit code 1. */
350 if (!gdb_actual_connections)
351 exit(1);
352 else {
353 fprintf(stderr,
354 "semihosting: *** application exited with error ***\n");
355 }
356 } else {
357 if (!gdb_actual_connections)
358 exit(1);
359 else {
360 fprintf(stderr,
361 "semihosting: application exception %#x\n",
362 (unsigned) semihosting->param);
363 }
364 }
365 }
366 if (!semihosting->has_resumable_exit) {
367 semihosting->is_resumable = false;
368 return target_call_event_callbacks(target, TARGET_EVENT_HALTED);
369 }
370 break;
371
372 case SEMIHOSTING_SYS_EXIT_EXTENDED: /* 0x20 */
373 /*
374 * This operation is only supported if the semihosting extension
375 * SH_EXT_EXIT_EXTENDED is implemented. SH_EXT_EXIT_EXTENDED is
376 * reported using feature byte 0, bit 0. If this extension is
377 * supported, then the implementation provides a means to
378 * report a normal exit with a nonzero exit status in both 32-bit
379 * and 64-bit semihosting APIs.
380 *
381 * The implementation must provide the semihosting call
382 * SYS_EXIT_EXTENDED for both A64 and A32/T32 semihosting APIs.
383 *
384 * SYS_EXIT_EXTENDED is used by an application to report an
385 * exception or exit to the debugger directly. The most common
386 * use is to report that execution has completed, using
387 * ADP_Stopped_ApplicationExit.
388 *
389 * Entry
390 * On entry, the PARAMETER REGISTER contains a pointer to a
391 * two-field argument block:
392 * - field 1 The exception type, which should be one of the set
393 * of reason codes that are documented for the SYS_EXIT
394 * (0x18) call. For example, ADP_Stopped_ApplicationExit.
395 * - field 2 A subcode, whose meaning depends on the reason
396 * code in field 1. In particular, if field 1 is
397 * ADP_Stopped_ApplicationExit then field 2 is an exit status
398 * code, as passed to the C standard library exit() function.
399 * A simulator receiving this request must notify a connected
400 * debugger, if present, and then exit with the specified status.
401 *
402 * Return
403 * No return is expected from these calls.
404 *
405 * For the A64 API, this call is identical to the behavior of
406 * the mandatory SYS_EXIT (0x18) call. If this extension is
407 * supported, then both calls must be implemented.
408 */
409 retval = semihosting_read_fields(target, 2, fields);
410 if (retval != ERROR_OK)
411 return retval;
412 else {
413 int type = semihosting_get_field(target, 0, fields);
414 int code = semihosting_get_field(target, 1, fields);
415
416 if (type == ADP_STOPPED_APPLICATION_EXIT) {
417 if (!gdb_actual_connections)
418 exit(code);
419 else {
420 fprintf(stderr,
421 "semihosting: *** application exited with %d ***\n",
422 code);
423 }
424 } else {
425 fprintf(stderr, "semihosting: exception %#x\n",
426 type);
427 }
428 }
429 if (!semihosting->has_resumable_exit) {
430 semihosting->is_resumable = false;
431 return target_call_event_callbacks(target, TARGET_EVENT_HALTED);
432 }
433 break;
434
435 case SEMIHOSTING_SYS_FLEN: /* 0x0C */
436 /*
437 * Returns the length of a specified file.
438 *
439 * Entry
440 * On entry, the PARAMETER REGISTER contains a pointer to a
441 * one-field argument block:
442 * - field 1 A handle for a previously opened, seekable file
443 * object.
444 *
445 * Return
446 * On exit, the RETURN REGISTER contains:
447 * - The current length of the file object, if the call is
448 * successful.
449 * - –1 if an error occurs.
450 */
451 if (semihosting->is_fileio) {
452 semihosting->result = -1;
453 semihosting->sys_errno = EINVAL;
454 }
455 retval = semihosting_read_fields(target, 1, fields);
456 if (retval != ERROR_OK)
457 return retval;
458 else {
459 int fd = semihosting_get_field(target, 0, fields);
460 struct stat buf;
461 semihosting->result = fstat(fd, &buf);
462 if (semihosting->result == -1) {
463 semihosting->sys_errno = errno;
464 LOG_DEBUG("fstat(%d)=%d", fd, (int)semihosting->result);
465 break;
466 }
467 LOG_DEBUG("fstat(%d)=%d", fd, (int)semihosting->result);
468 semihosting->result = buf.st_size;
469 }
470 break;
471
472 case SEMIHOSTING_SYS_GET_CMDLINE: /* 0x15 */
473 /*
474 * Returns the command line that is used for the call to the
475 * executable, that is, argc and argv.
476 *
477 * Entry
478 * On entry, the PARAMETER REGISTER points to a two-field data
479 * block to be used for returning the command string and its length:
480 * - field 1 A pointer to a buffer of at least the size that is
481 * specified in field 2.
482 * - field 2 The length of the buffer in bytes.
483 *
484 * Return
485 * On exit:
486 * If the call is successful, then the RETURN REGISTER contains 0,
487 * the PARAMETER REGISTER is unchanged, and the data block is
488 * updated as follows:
489 * - field 1 A pointer to a null-terminated string of the command
490 * line.
491 * - field 2 The length of the string in bytes.
492 * If the call is not successful, then the RETURN REGISTER
493 * contains -1.
494 *
495 * Note: The semihosting implementation might impose limits on
496 * the maximum length of the string that can be transferred.
497 * However, the implementation must be able to support a
498 * command-line length of at least 80 bytes.
499 */
500 retval = semihosting_read_fields(target, 2, fields);
501 if (retval != ERROR_OK)
502 return retval;
503 else {
504 uint64_t addr = semihosting_get_field(target, 0, fields);
505 size_t size = semihosting_get_field(target, 1, fields);
506
507 char *arg = semihosting->cmdline != NULL ?
508 semihosting->cmdline : "";
509 uint32_t len = strlen(arg) + 1;
510 if (len > size)
511 semihosting->result = -1;
512 else {
513 semihosting_set_field(target, len, 1, fields);
514 retval = target_write_buffer(target, addr, len,
515 (uint8_t *)arg);
516 if (retval != ERROR_OK)
517 return retval;
518 semihosting->result = 0;
519
520 retval = semihosting_write_fields(target, 2, fields);
521 if (retval != ERROR_OK)
522 return retval;
523 }
524 LOG_DEBUG("SYS_GET_CMDLINE=[%s],%d", arg,
525 (int)semihosting->result);
526 }
527 break;
528
529 case SEMIHOSTING_SYS_HEAPINFO: /* 0x16 */
530 /*
531 * Returns the system stack and heap parameters.
532 *
533 * Entry
534 * On entry, the PARAMETER REGISTER contains the address of a
535 * pointer to a four-field data block. The contents of the data
536 * block are filled by the function. The following C-like
537 * pseudocode describes the layout of the block:
538 * struct block {
539 * void* heap_base;
540 * void* heap_limit;
541 * void* stack_base;
542 * void* stack_limit;
543 * };
544 *
545 * Return
546 * On exit, the PARAMETER REGISTER is unchanged and the data
547 * block has been updated.
548 */
549 retval = semihosting_read_fields(target, 1, fields);
550 if (retval != ERROR_OK)
551 return retval;
552 else {
553 uint64_t addr = semihosting_get_field(target, 0, fields);
554 /* tell the remote we have no idea */
555 memset(fields, 0, 4 * semihosting->word_size_bytes);
556 retval = target_write_memory(target, addr, 4,
557 semihosting->word_size_bytes,
558 fields);
559 if (retval != ERROR_OK)
560 return retval;
561 semihosting->result = 0;
562 }
563 break;
564
565 case SEMIHOSTING_SYS_ISERROR: /* 0x08 */
566 /*
567 * Determines whether the return code from another semihosting
568 * call is an error status or not.
569 *
570 * This call is passed a parameter block containing the error
571 * code to examine.
572 *
573 * Entry
574 * On entry, the PARAMETER REGISTER contains a pointer to a
575 * one-field data block:
576 * - field 1 The required status word to check.
577 *
578 * Return
579 * On exit, the RETURN REGISTER contains:
580 * - 0 if the status field is not an error indication
581 * - A nonzero value if the status field is an error indication.
582 */
583 retval = semihosting_read_fields(target, 1, fields);
584 if (retval != ERROR_OK)
585 return retval;
586
587 uint64_t code = semihosting_get_field(target, 0, fields);
588 semihosting->result = (code != 0);
589 break;
590
591 case SEMIHOSTING_SYS_ISTTY: /* 0x09 */
592 /*
593 * Checks whether a file is connected to an interactive device.
594 *
595 * Entry
596 * On entry, the PARAMETER REGISTER contains a pointer to a
597 * one-field argument block:
598 * field 1 A handle for a previously opened file object.
599 *
600 * Return
601 * On exit, the RETURN REGISTER contains:
602 * - 1 if the handle identifies an interactive device.
603 * - 0 if the handle identifies a file.
604 * - A value other than 1 or 0 if an error occurs.
605 */
606 if (semihosting->is_fileio) {
607 semihosting->hit_fileio = true;
608 fileio_info->identifier = "isatty";
609 fileio_info->param_1 = semihosting->param;
610 } else {
611 retval = semihosting_read_fields(target, 1, fields);
612 if (retval != ERROR_OK)
613 return retval;
614 int fd = semihosting_get_field(target, 0, fields);
615 semihosting->result = isatty(fd);
616 LOG_DEBUG("isatty(%d)=%d", fd, (int)semihosting->result);
617 }
618 break;
619
620 case SEMIHOSTING_SYS_OPEN: /* 0x01 */
621 /*
622 * Opens a file on the host system.
623 *
624 * The file path is specified either as relative to the current
625 * directory of the host process, or absolute, using the path
626 * conventions of the host operating system.
627 *
628 * Semihosting implementations must support opening the special
629 * path name :semihosting-features as part of the semihosting
630 * extensions reporting mechanism.
631 *
632 * ARM targets interpret the special path name :tt as meaning
633 * the console input stream, for an open-read or the console
634 * output stream, for an open-write. Opening these streams is
635 * performed as part of the standard startup code for those
636 * applications that reference the C stdio streams. The
637 * semihosting extension SH_EXT_STDOUT_STDERR allows the
638 * semihosting caller to open separate output streams
639 * corresponding to stdout and stderr. This extension is
640 * reported using feature byte 0, bit 1. Use SYS_OPEN with
641 * the special path name :semihosting-features to access the
642 * feature bits.
643 *
644 * If this extension is supported, the implementation must
645 * support the following additional semantics to SYS_OPEN:
646 * - If the special path name :tt is opened with an fopen
647 * mode requesting write access (w, wb, w+, or w+b), then
648 * this is a request to open stdout.
649 * - If the special path name :tt is opened with a mode
650 * requesting append access (a, ab, a+, or a+b), then this is
651 * a request to open stderr.
652 *
653 * Entry
654 * On entry, the PARAMETER REGISTER contains a pointer to a
655 * three-field argument block:
656 * - field 1 A pointer to a null-terminated string containing
657 * a file or device name.
658 * - field 2 An integer that specifies the file opening mode.
659 * - field 3 An integer that gives the length of the string
660 * pointed to by field 1.
661 *
662 * The length does not include the terminating null character
663 * that must be present.
664 *
665 * Return
666 * On exit, the RETURN REGISTER contains:
667 * - A nonzero handle if the call is successful.
668 * - –1 if the call is not successful.
669 */
670 retval = semihosting_read_fields(target, 3, fields);
671 if (retval != ERROR_OK)
672 return retval;
673 else {
674 uint64_t addr = semihosting_get_field(target, 0, fields);
675 uint32_t mode = semihosting_get_field(target, 1, fields);
676 size_t len = semihosting_get_field(target, 2, fields);
677
678 if (mode > 11) {
679 semihosting->result = -1;
680 semihosting->sys_errno = EINVAL;
681 break;
682 }
683 uint8_t *fn = malloc(len+1);
684 if (!fn) {
685 semihosting->result = -1;
686 semihosting->sys_errno = ENOMEM;
687 } else {
688 retval = target_read_memory(target, addr, 1, len, fn);
689 if (retval != ERROR_OK) {
690 free(fn);
691 return retval;
692 }
693 fn[len] = 0;
694 /* TODO: implement the :semihosting-features special file.
695 * */
696 if (semihosting->is_fileio) {
697 if (strcmp((char *)fn, ":semihosting-features") == 0) {
698 semihosting->result = -1;
699 semihosting->sys_errno = EINVAL;
700 } else if (strcmp((char *)fn, ":tt") == 0) {
701 if (mode == 0)
702 semihosting->result = 0;
703 else if (mode == 4)
704 semihosting->result = 1;
705 else if (mode == 8)
706 semihosting->result = 2;
707 else
708 semihosting->result = -1;
709 } else {
710 semihosting->hit_fileio = true;
711 fileio_info->identifier = "open";
712 fileio_info->param_1 = addr;
713 fileio_info->param_2 = len;
714 fileio_info->param_3 = open_modeflags[mode];
715 fileio_info->param_4 = 0644;
716 }
717 } else {
718 if (strcmp((char *)fn, ":tt") == 0) {
719 /* Mode is:
720 * - 0-3 ("r") for stdin,
721 * - 4-7 ("w") for stdout,
722 * - 8-11 ("a") for stderr */
723 if (mode < 4) {
724 semihosting->result = dup(
725 STDIN_FILENO);
726 semihosting->sys_errno = errno;
727 LOG_DEBUG("dup(STDIN)=%d",
728 (int)semihosting->result);
729 } else if (mode < 8) {
730 semihosting->result = dup(
731 STDOUT_FILENO);
732 semihosting->sys_errno = errno;
733 LOG_DEBUG("dup(STDOUT)=%d",
734 (int)semihosting->result);
735 } else {
736 semihosting->result = dup(
737 STDERR_FILENO);
738 semihosting->sys_errno = errno;
739 LOG_DEBUG("dup(STDERR)=%d",
740 (int)semihosting->result);
741 }
742 } else {
743 /* cygwin requires the permission setting
744 * otherwise it will fail to reopen a previously
745 * written file */
746 semihosting->result = open((char *)fn,
747 open_modeflags[mode],
748 0644);
749 semihosting->sys_errno = errno;
750 LOG_DEBUG("open('%s')=%d", fn,
751 (int)semihosting->result);
752 }
753 }
754 free(fn);
755 }
756 }
757 break;
758
759 case SEMIHOSTING_SYS_READ: /* 0x06 */
760 /*
761 * Reads the contents of a file into a buffer. The file position
762 * is specified either:
763 * - Explicitly by a SYS_SEEK.
764 * - Implicitly one byte beyond the previous SYS_READ or
765 * SYS_WRITE request.
766 *
767 * The file position is at the start of the file when it is
768 * opened, and is lost when the file is closed. Perform the
769 * file operation as a single action whenever possible. For
770 * example, do not split a read of 16KB into four 4KB chunks
771 * unless there is no alternative.
772 *
773 * Entry
774 * On entry, the PARAMETER REGISTER contains a pointer to a
775 * three-field data block:
776 * - field 1 Contains a handle for a file previously opened
777 * with SYS_OPEN.
778 * - field 2 Points to a buffer.
779 * - field 3 Contains the number of bytes to read to the buffer
780 * from the file.
781 *
782 * Return
783 * On exit, the RETURN REGISTER contains the number of bytes not
784 * filled in the buffer (buffer_length - bytes_read) as follows:
785 * - If the RETURN REGISTER is 0, the entire buffer was
786 * successfully filled.
787 * - If the RETURN REGISTER is the same as field 3, no bytes
788 * were read (EOF can be assumed).
789 * - If the RETURN REGISTER contains a value smaller than
790 * field 3, the read succeeded but the buffer was only partly
791 * filled. For interactive devices, this is the most common
792 * return value.
793 */
794 retval = semihosting_read_fields(target, 3, fields);
795 if (retval != ERROR_OK)
796 return retval;
797 else {
798 int fd = semihosting_get_field(target, 0, fields);
799 uint64_t addr = semihosting_get_field(target, 1, fields);
800 size_t len = semihosting_get_field(target, 2, fields);
801 if (semihosting->is_fileio) {
802 semihosting->hit_fileio = true;
803 fileio_info->identifier = "read";
804 fileio_info->param_1 = fd;
805 fileio_info->param_2 = addr;
806 fileio_info->param_3 = len;
807 } else {
808 uint8_t *buf = malloc(len);
809 if (!buf) {
810 semihosting->result = -1;
811 semihosting->sys_errno = ENOMEM;
812 } else {
813 semihosting->result = read(fd, buf, len);
814 semihosting->sys_errno = errno;
815 LOG_DEBUG("read(%d, 0x%" PRIx64 ", %zu)=%d",
816 fd,
817 addr,
818 len,
819 (int)semihosting->result);
820 if (semihosting->result >= 0) {
821 retval = target_write_buffer(target, addr,
822 semihosting->result,
823 buf);
824 if (retval != ERROR_OK) {
825 free(buf);
826 return retval;
827 }
828 /* the number of bytes NOT filled in */
829 semihosting->result = len -
830 semihosting->result;
831 }
832 free(buf);
833 }
834 }
835 }
836 break;
837
838 case SEMIHOSTING_SYS_READC: /* 0x07 */
839 /*
840 * Reads a byte from the console.
841 *
842 * Entry
843 * The PARAMETER REGISTER must contain 0. There are no other
844 * parameters or values possible.
845 *
846 * Return
847 * On exit, the RETURN REGISTER contains the byte read from
848 * the console.
849 */
850 if (semihosting->is_fileio) {
851 LOG_ERROR("SYS_READC not supported by semihosting fileio");
852 return ERROR_FAIL;
853 }
854 semihosting->result = getchar();
855 LOG_DEBUG("getchar()=%d", (int)semihosting->result);
856 break;
857
858 case SEMIHOSTING_SYS_REMOVE: /* 0x0E */
859 /*
860 * Deletes a specified file on the host filing system.
861 *
862 * Entry
863 * On entry, the PARAMETER REGISTER contains a pointer to a
864 * two-field argument block:
865 * - field 1 Points to a null-terminated string that gives the
866 * path name of the file to be deleted.
867 * - field 2 The length of the string.
868 *
869 * Return
870 * On exit, the RETURN REGISTER contains:
871 * - 0 if the delete is successful
872 * - A nonzero, host-specific error code if the delete fails.
873 */
874 retval = semihosting_read_fields(target, 2, fields);
875 if (retval != ERROR_OK)
876 return retval;
877 else {
878 uint64_t addr = semihosting_get_field(target, 0, fields);
879 size_t len = semihosting_get_field(target, 1, fields);
880 if (semihosting->is_fileio) {
881 semihosting->hit_fileio = true;
882 fileio_info->identifier = "unlink";
883 fileio_info->param_1 = addr;
884 fileio_info->param_2 = len;
885 } else {
886 uint8_t *fn = malloc(len+1);
887 if (!fn) {
888 semihosting->result = -1;
889 semihosting->sys_errno = ENOMEM;
890 } else {
891 retval =
892 target_read_memory(target, addr, 1, len,
893 fn);
894 if (retval != ERROR_OK) {
895 free(fn);
896 return retval;
897 }
898 fn[len] = 0;
899 semihosting->result = remove((char *)fn);
900 semihosting->sys_errno = errno;
901 LOG_DEBUG("remove('%s')=%d", fn,
902 (int)semihosting->result);
903
904 free(fn);
905 }
906 }
907 }
908 break;
909
910 case SEMIHOSTING_SYS_RENAME: /* 0x0F */
911 /*
912 * Renames a specified file.
913 *
914 * Entry
915 * On entry, the PARAMETER REGISTER contains a pointer to a
916 * four-field data block:
917 * - field 1 A pointer to the name of the old file.
918 * - field 2 The length of the old filename.
919 * - field 3 A pointer to the new filename.
920 * - field 4 The length of the new filename. Both strings are
921 * null-terminated.
922 *
923 * Return
924 * On exit, the RETURN REGISTER contains:
925 * - 0 if the rename is successful.
926 * - A nonzero, host-specific error code if the rename fails.
927 */
928 retval = semihosting_read_fields(target, 4, fields);
929 if (retval != ERROR_OK)
930 return retval;
931 else {
932 uint64_t addr1 = semihosting_get_field(target, 0, fields);
933 size_t len1 = semihosting_get_field(target, 1, fields);
934 uint64_t addr2 = semihosting_get_field(target, 2, fields);
935 size_t len2 = semihosting_get_field(target, 3, fields);
936 if (semihosting->is_fileio) {
937 semihosting->hit_fileio = true;
938 fileio_info->identifier = "rename";
939 fileio_info->param_1 = addr1;
940 fileio_info->param_2 = len1;
941 fileio_info->param_3 = addr2;
942 fileio_info->param_4 = len2;
943 } else {
944 uint8_t *fn1 = malloc(len1+1);
945 uint8_t *fn2 = malloc(len2+1);
946 if (!fn1 || !fn2) {
947 semihosting->result = -1;
948 semihosting->sys_errno = ENOMEM;
949 } else {
950 retval = target_read_memory(target, addr1, 1, len1,
951 fn1);
952 if (retval != ERROR_OK) {
953 free(fn1);
954 free(fn2);
955 return retval;
956 }
957 retval = target_read_memory(target, addr2, 1, len2,
958 fn2);
959 if (retval != ERROR_OK) {
960 free(fn1);
961 free(fn2);
962 return retval;
963 }
964 fn1[len1] = 0;
965 fn2[len2] = 0;
966 semihosting->result = rename((char *)fn1,
967 (char *)fn2);
968 semihosting->sys_errno = errno;
969 LOG_DEBUG("rename('%s', '%s')=%d", fn1, fn2,
970 (int)semihosting->result);
971
972 free(fn1);
973 free(fn2);
974 }
975 }
976 }
977 break;
978
979 case SEMIHOSTING_SYS_SEEK: /* 0x0A */
980 /*
981 * Seeks to a specified position in a file using an offset
982 * specified from the start of the file. The file is assumed
983 * to be a byte array and the offset is given in bytes.
984 *
985 * Entry
986 * On entry, the PARAMETER REGISTER contains a pointer to a
987 * two-field data block:
988 * - field 1 A handle for a seekable file object.
989 * - field 2 The absolute byte position to seek to.
990 *
991 * Return
992 * On exit, the RETURN REGISTER contains:
993 * - 0 if the request is successful.
994 * - A negative value if the request is not successful.
995 * Use SYS_ERRNO to read the value of the host errno variable
996 * describing the error.
997 *
998 * Note: The effect of seeking outside the current extent of
999 * the file object is undefined.
1000 */
1001 retval = semihosting_read_fields(target, 2, fields);
1002 if (retval != ERROR_OK)
1003 return retval;
1004 else {
1005 int fd = semihosting_get_field(target, 0, fields);
1006 off_t pos = semihosting_get_field(target, 1, fields);
1007 if (semihosting->is_fileio) {
1008 semihosting->hit_fileio = true;
1009 fileio_info->identifier = "lseek";
1010 fileio_info->param_1 = fd;
1011 fileio_info->param_2 = pos;
1012 fileio_info->param_3 = SEEK_SET;
1013 } else {
1014 semihosting->result = lseek(fd, pos, SEEK_SET);
1015 semihosting->sys_errno = errno;
1016 LOG_DEBUG("lseek(%d, %d)=%d", fd, (int)pos,
1017 (int)semihosting->result);
1018 if (semihosting->result == pos)
1019 semihosting->result = 0;
1020 }
1021 }
1022 break;
1023
1024 case SEMIHOSTING_SYS_SYSTEM: /* 0x12 */
1025 /*
1026 * Passes a command to the host command-line interpreter.
1027 * This enables you to execute a system command such as dir,
1028 * ls, or pwd. The terminal I/O is on the host, and is not
1029 * visible to the target.
1030 *
1031 * Entry
1032 * On entry, the PARAMETER REGISTER contains a pointer to a
1033 * two-field argument block:
1034 * - field 1 Points to a string to be passed to the host
1035 * command-line interpreter.
1036 * - field 2 The length of the string.
1037 *
1038 * Return
1039 * On exit, the RETURN REGISTER contains the return status.
1040 */
1041
1042 /* Provide SYS_SYSTEM functionality. Uses the
1043 * libc system command, there may be a reason *NOT*
1044 * to use this, but as I can't think of one, I
1045 * implemented it this way.
1046 */
1047 retval = semihosting_read_fields(target, 2, fields);
1048 if (retval != ERROR_OK)
1049 return retval;
1050 else {
1051 uint64_t addr = semihosting_get_field(target, 0, fields);
1052 size_t len = semihosting_get_field(target, 1, fields);
1053 if (semihosting->is_fileio) {
1054 semihosting->hit_fileio = true;
1055 fileio_info->identifier = "system";
1056 fileio_info->param_1 = addr;
1057 fileio_info->param_2 = len;
1058 } else {
1059 uint8_t *cmd = malloc(len+1);
1060 if (!cmd) {
1061 semihosting->result = -1;
1062 semihosting->sys_errno = ENOMEM;
1063 } else {
1064 retval = target_read_memory(target,
1065 addr,
1066 1,
1067 len,
1068 cmd);
1069 if (retval != ERROR_OK) {
1070 free(cmd);
1071 return retval;
1072 } else {
1073 cmd[len] = 0;
1074 semihosting->result = system(
1075 (const char *)cmd);
1076 LOG_DEBUG("system('%s')=%d",
1077 cmd,
1078 (int)semihosting->result);
1079 }
1080
1081 free(cmd);
1082 }
1083 }
1084 }
1085 break;
1086
1087 case SEMIHOSTING_SYS_TIME: /* 0x11 */
1088 /*
1089 * Returns the number of seconds since 00:00 January 1, 1970.
1090 * This value is real-world time, regardless of any debug agent
1091 * configuration.
1092 *
1093 * Entry
1094 * There are no parameters.
1095 *
1096 * Return
1097 * On exit, the RETURN REGISTER contains the number of seconds.
1098 */
1099 semihosting->result = time(NULL);
1100 break;
1101
1102 case SEMIHOSTING_SYS_WRITE: /* 0x05 */
1103 /*
1104 * Writes the contents of a buffer to a specified file at the
1105 * current file position. The file position is specified either:
1106 * - Explicitly, by a SYS_SEEK.
1107 * - Implicitly as one byte beyond the previous SYS_READ or
1108 * SYS_WRITE request.
1109 *
1110 * The file position is at the start of the file when the file
1111 * is opened, and is lost when the file is closed.
1112 *
1113 * Perform the file operation as a single action whenever
1114 * possible. For example, do not split a write of 16KB into
1115 * four 4KB chunks unless there is no alternative.
1116 *
1117 * Entry
1118 * On entry, the PARAMETER REGISTER contains a pointer to a
1119 * three-field data block:
1120 * - field 1 Contains a handle for a file previously opened
1121 * with SYS_OPEN.
1122 * - field 2 Points to the memory containing the data to be written.
1123 * - field 3 Contains the number of bytes to be written from
1124 * the buffer to the file.
1125 *
1126 * Return
1127 * On exit, the RETURN REGISTER contains:
1128 * - 0 if the call is successful.
1129 * - The number of bytes that are not written, if there is an error.
1130 */
1131 retval = semihosting_read_fields(target, 3, fields);
1132 if (retval != ERROR_OK)
1133 return retval;
1134 else {
1135 int fd = semihosting_get_field(target, 0, fields);
1136 uint64_t addr = semihosting_get_field(target, 1, fields);
1137 size_t len = semihosting_get_field(target, 2, fields);
1138 if (semihosting->is_fileio) {
1139 semihosting->hit_fileio = true;
1140 fileio_info->identifier = "write";
1141 fileio_info->param_1 = fd;
1142 fileio_info->param_2 = addr;
1143 fileio_info->param_3 = len;
1144 } else {
1145 uint8_t *buf = malloc(len);
1146 if (!buf) {
1147 semihosting->result = -1;
1148 semihosting->sys_errno = ENOMEM;
1149 } else {
1150 retval = target_read_buffer(target, addr, len, buf);
1151 if (retval != ERROR_OK) {
1152 free(buf);
1153 return retval;
1154 }
1155 semihosting->result = write(fd, buf, len);
1156 semihosting->sys_errno = errno;
1157 LOG_DEBUG("write(%d, 0x%" PRIx64 ", %zu)=%d",
1158 fd,
1159 addr,
1160 len,
1161 (int)semihosting->result);
1162 if (semihosting->result >= 0) {
1163 /* The number of bytes that are NOT written.
1164 * */
1165 semihosting->result = len -
1166 semihosting->result;
1167 }
1168
1169 free(buf);
1170 }
1171 }
1172 }
1173 break;
1174
1175 case SEMIHOSTING_SYS_WRITEC: /* 0x03 */
1176 /*
1177 * Writes a character byte, pointed to by the PARAMETER REGISTER,
1178 * to the debug channel. When executed under a semihosting
1179 * debugger, the character appears on the host debugger console.
1180 *
1181 * Entry
1182 * On entry, the PARAMETER REGISTER contains a pointer to the
1183 * character.
1184 *
1185 * Return
1186 * None. The RETURN REGISTER is corrupted.
1187 */
1188 if (semihosting->is_fileio) {
1189 semihosting->hit_fileio = true;
1190 fileio_info->identifier = "write";
1191 fileio_info->param_1 = 1;
1192 fileio_info->param_2 = semihosting->param;
1193 fileio_info->param_3 = 1;
1194 } else {
1195 uint64_t addr = semihosting->param;
1196 unsigned char c;
1197 retval = target_read_memory(target, addr, 1, 1, &c);
1198 if (retval != ERROR_OK)
1199 return retval;
1200 putchar(c);
1201 semihosting->result = 0;
1202 }
1203 break;
1204
1205 case SEMIHOSTING_SYS_WRITE0: /* 0x04 */
1206 /*
1207 * Writes a null-terminated string to the debug channel.
1208 * When executed under a semihosting debugger, the characters
1209 * appear on the host debugger console.
1210 *
1211 * Entry
1212 * On entry, the PARAMETER REGISTER contains a pointer to the
1213 * first byte of the string.
1214 *
1215 * Return
1216 * None. The RETURN REGISTER is corrupted.
1217 */
1218 if (semihosting->is_fileio) {
1219 size_t count = 0;
1220 uint64_t addr = semihosting->param;
1221 for (;; addr++) {
1222 unsigned char c;
1223 retval = target_read_memory(target, addr, 1, 1, &c);
1224 if (retval != ERROR_OK)
1225 return retval;
1226 if (c == '\0')
1227 break;
1228 count++;
1229 }
1230 semihosting->hit_fileio = true;
1231 fileio_info->identifier = "write";
1232 fileio_info->param_1 = 1;
1233 fileio_info->param_2 = semihosting->param;
1234 fileio_info->param_3 = count;
1235 } else {
1236 uint64_t addr = semihosting->param;
1237 do {
1238 unsigned char c;
1239 retval = target_read_memory(target, addr++, 1, 1, &c);
1240 if (retval != ERROR_OK)
1241 return retval;
1242 if (!c)
1243 break;
1244 putchar(c);
1245 } while (1);
1246 semihosting->result = 0;
1247 }
1248 break;
1249
1250 case SEMIHOSTING_SYS_ELAPSED: /* 0x30 */
1251 /*
1252 * Returns the number of elapsed target ticks since execution
1253 * started.
1254 * Use SYS_TICKFREQ to determine the tick frequency.
1255 *
1256 * Entry (32-bit)
1257 * On entry, the PARAMETER REGISTER points to a two-field data
1258 * block to be used for returning the number of elapsed ticks:
1259 * - field 1 The least significant field and is at the low address.
1260 * - field 2 The most significant field and is at the high address.
1261 *
1262 * Entry (64-bit)
1263 * On entry the PARAMETER REGISTER points to a one-field data
1264 * block to be used for returning the number of elapsed ticks:
1265 * - field 1 The number of elapsed ticks as a 64-bit value.
1266 *
1267 * Return
1268 * On exit:
1269 * - On success, the RETURN REGISTER contains 0, the PARAMETER
1270 * REGISTER is unchanged, and the data block pointed to by the
1271 * PARAMETER REGISTER is filled in with the number of elapsed
1272 * ticks.
1273 * - On failure, the RETURN REGISTER contains -1, and the
1274 * PARAMETER REGISTER contains -1.
1275 *
1276 * Note: Some semihosting implementations might not support this
1277 * semihosting operation, and they always return -1 in the
1278 * RETURN REGISTER.
1279 */
1280
1281 case SEMIHOSTING_SYS_TICKFREQ: /* 0x31 */
1282 /*
1283 * Returns the tick frequency.
1284 *
1285 * Entry
1286 * The PARAMETER REGISTER must contain 0 on entry to this routine.
1287 *
1288 * Return
1289 * On exit, the RETURN REGISTER contains either:
1290 * - The number of ticks per second.
1291 * - –1 if the target does not know the value of one tick.
1292 *
1293 * Note: Some semihosting implementations might not support
1294 * this semihosting operation, and they always return -1 in the
1295 * RETURN REGISTER.
1296 */
1297
1298 case SEMIHOSTING_SYS_TMPNAM: /* 0x0D */
1299 /*
1300 * Returns a temporary name for a file identified by a system
1301 * file identifier.
1302 *
1303 * Entry
1304 * On entry, the PARAMETER REGISTER contains a pointer to a
1305 * three-word argument block:
1306 * - field 1 A pointer to a buffer.
1307 * - field 2 A target identifier for this filename. Its value
1308 * must be an integer in the range 0-255.
1309 * - field 3 Contains the length of the buffer. The length must
1310 * be at least the value of L_tmpnam on the host system.
1311 *
1312 * Return
1313 * On exit, the RETURN REGISTER contains:
1314 * - 0 if the call is successful.
1315 * - –1 if an error occurs.
1316 *
1317 * The buffer pointed to by the PARAMETER REGISTER contains
1318 * the filename, prefixed with a suitable directory name.
1319 * If you use the same target identifier again, the same
1320 * filename is returned.
1321 *
1322 * Note: The returned string must be null-terminated.
1323 */
1324
1325 default:
1326 fprintf(stderr, "semihosting: unsupported call %#x\n",
1327 (unsigned) semihosting->op);
1328 semihosting->result = -1;
1329 semihosting->sys_errno = ENOTSUP;
1330 }
1331
1332 if (!semihosting->hit_fileio) {
1333 retval = semihosting->post_result(target);
1334 if (retval != ERROR_OK) {
1335 LOG_ERROR("Failed to post semihosting result");
1336 return retval;
1337 }
1338 }
1339
1340 return ERROR_OK;
1341 }
1342
1343 /* -------------------------------------------------------------------------
1344 * Local functions. */
1345
1346 static int semihosting_common_fileio_info(struct target *target,
1347 struct gdb_fileio_info *fileio_info)
1348 {
1349 struct semihosting *semihosting = target->semihosting;
1350 if (!semihosting)
1351 return ERROR_FAIL;
1352
1353 /*
1354 * To avoid unnecessary duplication, semihosting prepares the
1355 * fileio_info structure out-of-band when the target halts. See
1356 * do_semihosting for more detail.
1357 */
1358 if (!semihosting->is_fileio || !semihosting->hit_fileio)
1359 return ERROR_FAIL;
1360
1361 return ERROR_OK;
1362 }
1363
1364 static int semihosting_common_fileio_end(struct target *target, int result,
1365 int fileio_errno, bool ctrl_c)
1366 {
1367 struct gdb_fileio_info *fileio_info = target->fileio_info;
1368 struct semihosting *semihosting = target->semihosting;
1369 if (!semihosting)
1370 return ERROR_FAIL;
1371
1372 /* clear pending status */
1373 semihosting->hit_fileio = false;
1374
1375 semihosting->result = result;
1376 semihosting->sys_errno = fileio_errno;
1377
1378 /*
1379 * Some fileio results do not match up with what the semihosting
1380 * operation expects; for these operations, we munge the results
1381 * below:
1382 */
1383 switch (semihosting->op) {
1384 case SEMIHOSTING_SYS_WRITE: /* 0x05 */
1385 if (result < 0)
1386 semihosting->result = fileio_info->param_3;
1387 else
1388 semihosting->result = 0;
1389 break;
1390
1391 case SEMIHOSTING_SYS_READ: /* 0x06 */
1392 if (result == (int)fileio_info->param_3)
1393 semihosting->result = 0;
1394 if (result <= 0)
1395 semihosting->result = fileio_info->param_3;
1396 break;
1397
1398 case SEMIHOSTING_SYS_SEEK: /* 0x0a */
1399 if (result > 0)
1400 semihosting->result = 0;
1401 break;
1402 }
1403
1404 return semihosting->post_result(target);
1405 }
1406
1407 /**
1408 * Read all fields of a command from target to buffer.
1409 */
1410 static int semihosting_read_fields(struct target *target, size_t number,
1411 uint8_t *fields)
1412 {
1413 struct semihosting *semihosting = target->semihosting;
1414 /* Use 4-byte multiples to trigger fast memory access. */
1415 return target_read_memory(target, semihosting->param, 4,
1416 number * (semihosting->word_size_bytes / 4), fields);
1417 }
1418
1419 /**
1420 * Write all fields of a command from buffer to target.
1421 */
1422 static int semihosting_write_fields(struct target *target, size_t number,
1423 uint8_t *fields)
1424 {
1425 struct semihosting *semihosting = target->semihosting;
1426 /* Use 4-byte multiples to trigger fast memory access. */
1427 return target_write_memory(target, semihosting->param, 4,
1428 number * (semihosting->word_size_bytes / 4), fields);
1429 }
1430
1431 /**
1432 * Extract a field from the buffer, considering register size and endianness.
1433 */
1434 static uint64_t semihosting_get_field(struct target *target, size_t index,
1435 uint8_t *fields)
1436 {
1437 struct semihosting *semihosting = target->semihosting;
1438 if (semihosting->word_size_bytes == 8)
1439 return target_buffer_get_u64(target, fields + (index * 8));
1440 else
1441 return target_buffer_get_u32(target, fields + (index * 4));
1442 }
1443
1444 /**
1445 * Store a field in the buffer, considering register size and endianness.
1446 */
1447 static void semihosting_set_field(struct target *target, uint64_t value,
1448 size_t index,
1449 uint8_t *fields)
1450 {
1451 struct semihosting *semihosting = target->semihosting;
1452 if (semihosting->word_size_bytes == 8)
1453 target_buffer_set_u64(target, fields + (index * 8), value);
1454 else
1455 target_buffer_set_u32(target, fields + (index * 4), value);
1456 }
1457
1458
1459 /* -------------------------------------------------------------------------
1460 * Common semihosting commands handlers. */
1461
1462 __COMMAND_HANDLER(handle_common_semihosting_command)
1463 {
1464 struct target *target = get_current_target(CMD_CTX);
1465
1466 if (target == NULL) {
1467 LOG_ERROR("No target selected");
1468 return ERROR_FAIL;
1469 }
1470
1471 struct semihosting *semihosting = target->semihosting;
1472 if (!semihosting) {
1473 command_print(CMD, "semihosting not supported for current target");
1474 return ERROR_FAIL;
1475 }
1476
1477 if (CMD_ARGC > 0) {
1478 int is_active;
1479
1480 COMMAND_PARSE_ENABLE(CMD_ARGV[0], is_active);
1481
1482 if (!target_was_examined(target)) {
1483 LOG_ERROR("Target not examined yet");
1484 return ERROR_FAIL;
1485 }
1486
1487 if (semihosting && semihosting->setup(target, is_active) != ERROR_OK) {
1488 LOG_ERROR("Failed to Configure semihosting");
1489 return ERROR_FAIL;
1490 }
1491
1492 /* FIXME never let that "catch" be dropped! (???) */
1493 semihosting->is_active = is_active;
1494 }
1495
1496 command_print(CMD, "semihosting is %s",
1497 semihosting->is_active
1498 ? "enabled" : "disabled");
1499
1500 return ERROR_OK;
1501 }
1502
1503
1504 __COMMAND_HANDLER(handle_common_semihosting_fileio_command)
1505 {
1506 struct target *target = get_current_target(CMD_CTX);
1507
1508 if (target == NULL) {
1509 LOG_ERROR("No target selected");
1510 return ERROR_FAIL;
1511 }
1512
1513 struct semihosting *semihosting = target->semihosting;
1514 if (!semihosting) {
1515 command_print(CMD, "semihosting not supported for current target");
1516 return ERROR_FAIL;
1517 }
1518
1519 if (!semihosting->is_active) {
1520 command_print(CMD, "semihosting not yet enabled for current target");
1521 return ERROR_FAIL;
1522 }
1523
1524 if (CMD_ARGC > 0)
1525 COMMAND_PARSE_ENABLE(CMD_ARGV[0], semihosting->is_fileio);
1526
1527 command_print(CMD, "semihosting fileio is %s",
1528 semihosting->is_fileio
1529 ? "enabled" : "disabled");
1530
1531 return ERROR_OK;
1532 }
1533
1534 __COMMAND_HANDLER(handle_common_semihosting_cmdline)
1535 {
1536 struct target *target = get_current_target(CMD_CTX);
1537 unsigned int i;
1538
1539 if (target == NULL) {
1540 LOG_ERROR("No target selected");
1541 return ERROR_FAIL;
1542 }
1543
1544 struct semihosting *semihosting = target->semihosting;
1545 if (!semihosting) {
1546 command_print(CMD, "semihosting not supported for current target");
1547 return ERROR_FAIL;
1548 }
1549
1550 free(semihosting->cmdline);
1551 semihosting->cmdline = CMD_ARGC > 0 ? strdup(CMD_ARGV[0]) : NULL;
1552
1553 for (i = 1; i < CMD_ARGC; i++) {
1554 char *cmdline = alloc_printf("%s %s", semihosting->cmdline, CMD_ARGV[i]);
1555 if (cmdline == NULL)
1556 break;
1557 free(semihosting->cmdline);
1558 semihosting->cmdline = cmdline;
1559 }
1560
1561 command_print(CMD, "semihosting command line is [%s]",
1562 semihosting->cmdline);
1563
1564 return ERROR_OK;
1565 }
1566
1567 __COMMAND_HANDLER(handle_common_semihosting_resumable_exit_command)
1568 {
1569 struct target *target = get_current_target(CMD_CTX);
1570
1571 if (target == NULL) {
1572 LOG_ERROR("No target selected");
1573 return ERROR_FAIL;
1574 }
1575
1576 struct semihosting *semihosting = target->semihosting;
1577 if (!semihosting) {
1578 command_print(CMD, "semihosting not supported for current target");
1579 return ERROR_FAIL;
1580 }
1581
1582 if (!semihosting->is_active) {
1583 command_print(CMD, "semihosting not yet enabled for current target");
1584 return ERROR_FAIL;
1585 }
1586
1587 if (CMD_ARGC > 0)
1588 COMMAND_PARSE_ENABLE(CMD_ARGV[0], semihosting->has_resumable_exit);
1589
1590 command_print(CMD, "semihosting resumable exit is %s",
1591 semihosting->has_resumable_exit
1592 ? "enabled" : "disabled");
1593
1594 return ERROR_OK;
1595 }

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)