- struct arm *armv4_5 = target_to_armv4_5(target);
- uint32_t r0 = buf_get_u32(armv4_5->core_cache->reg_list[0].value, 0, 32);
- uint32_t r1 = buf_get_u32(armv4_5->core_cache->reg_list[1].value, 0, 32);
- uint32_t lr = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, ARMV4_5_MODE_SVC, 14).value, 0, 32);
- uint32_t spsr = buf_get_u32(armv4_5->spsr->value, 0, 32);;
- uint8_t params[16];
- int retval, result;
-
- /*
- * TODO: lots of security issues are not considered yet, such as:
- * - no validation on target provided file descriptors
- * - no safety checks on opened/deleted/renamed file paths
- * Beware the target app you use this support with.
- */
- switch (r0) {
- case 0x01: /* SYS_OPEN */
- retval = target_read_memory(target, r1, 4, 3, params);
- if (retval != ERROR_OK)
- return retval;
- else {
- uint32_t a = target_buffer_get_u32(target, params+0);
- uint32_t m = target_buffer_get_u32(target, params+4);
- uint32_t l = target_buffer_get_u32(target, params+8);
- if (l <= 255 && m <= 11) {
- uint8_t fn[256];
- int mode;
- retval = target_read_memory(target, a, 1, l, fn);
- if (retval != ERROR_OK)
- return retval;
- fn[l] = 0;
- if (m & 0x2)
- mode = O_RDWR;
- else if (m & 0xc)
- mode = O_WRONLY;
- else
- mode = O_RDONLY;
- if (m >= 8)
- mode |= O_CREAT|O_APPEND;
- else if (m >= 4)
- mode |= O_CREAT|O_TRUNC;
- if (strcmp((char *)fn, ":tt") == 0) {
- if ((mode & 3) == 0)
- result = dup(0);
- else
- result = dup(1);
- } else
- result = open((char *)fn, mode);
- semihosting_errno = errno;
- } else {
- result = -1;
- semihosting_errno = EINVAL;
- }
- }
- break;
-
- case 0x02: /* SYS_CLOSE */
- retval = target_read_memory(target, r1, 4, 1, params);
- if (retval != ERROR_OK)
- return retval;
- else {
- int fd = target_buffer_get_u32(target, params+0);
- result = close(fd);
- semihosting_errno = errno;
- }
- break;
-
- case 0x03: /* SYS_WRITEC */
- {
- unsigned char c;
- retval = target_read_memory(target, r1, 1, 1, &c);
- if (retval != ERROR_OK)
- return retval;
- putchar(c);
- result = 0;
- }
- break;
-
- case 0x04: /* SYS_WRITE0 */
- do {
- unsigned char c;
- retval = target_read_memory(target, r1, 1, 1, &c);
- if (retval != ERROR_OK)
- return retval;
- if (!c)
- break;
- putchar(c);
- } while (1);
- result = 0;
- break;
-
- case 0x05: /* SYS_WRITE */
- retval = target_read_memory(target, r1, 4, 3, params);
- if (retval != ERROR_OK)
- return retval;
- else {
- int fd = target_buffer_get_u32(target, params+0);
- uint32_t a = target_buffer_get_u32(target, params+4);
- size_t l = target_buffer_get_u32(target, params+8);
- uint8_t *buf = malloc(l);
- if (!buf) {
- result = -1;
- semihosting_errno = ENOMEM;
- } else {
- retval = target_read_buffer(target, a, l, buf);
- if (retval != ERROR_OK) {
- free(buf);
- return retval;
- }
- result = write(fd, buf, l);
- semihosting_errno = errno;
- if (result >= 0)
- result = l - result;
- free(buf);
- }
- }
- break;
-
- case 0x06: /* SYS_READ */
- retval = target_read_memory(target, r1, 4, 3, params);
- if (retval != ERROR_OK)
- return retval;
- else {
- int fd = target_buffer_get_u32(target, params+0);
- uint32_t a = target_buffer_get_u32(target, params+4);
- ssize_t l = target_buffer_get_u32(target, params+8);
- uint8_t *buf = malloc(l);
- if (!buf) {
- result = -1;
- semihosting_errno = ENOMEM;
- } else {
- result = read(fd, buf, l);
- semihosting_errno = errno;
- if (result > 0) {
- retval = target_write_buffer(target, a, result, buf);
- if (retval != ERROR_OK) {
- free(buf);
- return retval;
- }
- result = l - result;
- }
- free(buf);
- }
- }
- break;
-
- case 0x07: /* SYS_READC */
- result = getchar();
- break;
-
- case 0x08: /* SYS_ISERROR */
- retval = target_read_memory(target, r1, 4, 1, params);
- if (retval != ERROR_OK)
- return retval;
- result = (target_buffer_get_u32(target, params+0) != 0);
- break;
-
- case 0x09: /* SYS_ISTTY */
- retval = target_read_memory(target, r1, 4, 1, params);
- if (retval != ERROR_OK)
- return retval;
- result = isatty(target_buffer_get_u32(target, params+0));
- break;
-
- case 0x0a: /* SYS_SEEK */
- retval = target_read_memory(target, r1, 4, 2, params);
- if (retval != ERROR_OK)
- return retval;
- else {
- int fd = target_buffer_get_u32(target, params+0);
- off_t pos = target_buffer_get_u32(target, params+4);
- result = lseek(fd, pos, SEEK_SET);
- semihosting_errno = errno;
- if (result == pos)
- result = 0;
- }
- break;
-
- case 0x0c: /* SYS_FLEN */
- retval = target_read_memory(target, r1, 4, 1, params);
- if (retval != ERROR_OK)
- return retval;
- else {
- int fd = target_buffer_get_u32(target, params+0);
- off_t cur = lseek(fd, 0, SEEK_CUR);
- if (cur == (off_t)-1) {
- semihosting_errno = errno;
- result = -1;
- break;
- }
- result = lseek(fd, 0, SEEK_END);
- semihosting_errno = errno;
- if (lseek(fd, cur, SEEK_SET) == (off_t)-1) {
- semihosting_errno = errno;
- result = -1;
- }
- }
- break;
-
- case 0x0e: /* SYS_REMOVE */
- retval = target_read_memory(target, r1, 4, 2, params);
- if (retval != ERROR_OK)
- return retval;
- else {
- uint32_t a = target_buffer_get_u32(target, params+0);
- uint32_t l = target_buffer_get_u32(target, params+4);
- if (l <= 255) {
- uint8_t fn[256];
- retval = target_read_memory(target, a, 1, l, fn);
- if (retval != ERROR_OK)
- return retval;
- fn[l] = 0;
- result = remove((char *)fn);
- semihosting_errno = errno;
- } else {
- result = -1;
- semihosting_errno = EINVAL;
- }
- }
- break;
-
- case 0x0f: /* SYS_RENAME */
- retval = target_read_memory(target, r1, 4, 4, params);
- if (retval != ERROR_OK)
- return retval;
- else {
- uint32_t a1 = target_buffer_get_u32(target, params+0);
- uint32_t l1 = target_buffer_get_u32(target, params+4);
- uint32_t a2 = target_buffer_get_u32(target, params+8);
- uint32_t l2 = target_buffer_get_u32(target, params+12);
- if (l1 <= 255 && l2 <= 255) {
- uint8_t fn1[256], fn2[256];
- retval = target_read_memory(target, a1, 1, l1, fn1);
- if (retval != ERROR_OK)
- return retval;
- retval = target_read_memory(target, a2, 1, l2, fn2);
- if (retval != ERROR_OK)
- return retval;
- fn1[l1] = 0;
- fn2[l2] = 0;
- result = rename((char *)fn1, (char *)fn2);
- semihosting_errno = errno;
- } else {
- result = -1;
- semihosting_errno = EINVAL;
- }
- }
- break;
-
- case 0x11: /* SYS_TIME */
- result = time(NULL);
- break;
-
- case 0x13: /* SYS_ERRNO */
- result = semihosting_errno;
- break;
-
- case 0x15: /* SYS_GET_CMDLINE */
- retval = target_read_memory(target, r1, 4, 2, params);
- if (retval != ERROR_OK)
- return retval;
- else {
- uint32_t a = target_buffer_get_u32(target, params+0);
- uint32_t l = target_buffer_get_u32(target, params+4);
- char *arg = "foobar";
- uint32_t s = strlen(arg) + 1;
- if (l < s)
- result = -1;
- else {
- retval = target_write_buffer(target, a, s, (void*)arg);
- if (retval != ERROR_OK)
- return retval;
- result = 0;