OpenOCD
xtensa_fileio.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /***************************************************************************
4  * Xtensa Target File-I/O Support for OpenOCD *
5  * Copyright (C) 2020-2023 Cadence Design Systems, Inc. *
6  ***************************************************************************/
7 
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11 
12 #include "xtensa_chip.h"
13 #include "xtensa_fileio.h"
14 #include "xtensa.h"
15 
16 #define XTENSA_SYSCALL(x) XT_INS_BREAK(x, 1, 14)
17 #define XTENSA_SYSCALL_SZ 3
18 #define XTENSA_SYSCALL_LEN_MAX 255
19 
20 
22 {
23  char *idmem = malloc(XTENSA_SYSCALL_LEN_MAX + 1);
24  target->fileio_info = malloc(sizeof(struct gdb_fileio_info));
25  if (!idmem || !target->fileio_info) {
26  LOG_TARGET_ERROR(target, "Out of memory!");
27  free(idmem);
28  free(target->fileio_info);
29  return ERROR_FAIL;
30  }
31  target->fileio_info->identifier = idmem;
32  return ERROR_OK;
33 }
34 
42 {
44  int retval;
45 
47  if ((dbg_cause & (DEBUGCAUSE_BI | DEBUGCAUSE_BN)) == 0 || xtensa->halt_request)
48  return ERROR_FAIL;
49 
50  uint8_t brk_insn_buf[sizeof(uint32_t)] = {0};
52  retval = target_read_memory(target,
53  pc,
55  1,
56  (uint8_t *)brk_insn_buf);
57  if (retval != ERROR_OK) {
58  LOG_ERROR("Failed to read break instruction!");
59  return ERROR_FAIL;
60  }
61  if (buf_get_u32(brk_insn_buf, 0, 32) != XTENSA_SYSCALL(xtensa))
62  return ERROR_FAIL;
63 
64  LOG_TARGET_DEBUG(target, "File-I/O: syscall breakpoint found at 0x%x", pc);
65  xtensa->proc_syscall = true;
66  return ERROR_OK;
67 }
68 
69 int xtensa_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info)
70 {
71  /* fill syscall parameters to file-I/O info */
72  if (!fileio_info) {
73  LOG_ERROR("File-I/O data structure uninitialized");
74  return ERROR_FAIL;
75  }
76 
78  if (!xtensa->proc_syscall)
79  return ERROR_FAIL;
80 
86  int retval = ERROR_OK;
87 
88  LOG_TARGET_DEBUG(target, "File-I/O: syscall 0x%x 0x%x 0x%x 0x%x 0x%x",
89  syscall, arg0, arg1, arg2, arg3);
90 
91  switch (syscall) {
93  snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "open");
94  fileio_info->param_1 = arg0; // pathp
95  fileio_info->param_2 = arg3; // len
96  fileio_info->param_3 = arg1; // flags
97  fileio_info->param_4 = arg2; // mode
98  break;
100  snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "close");
101  fileio_info->param_1 = arg0; // fd
102  break;
103  case XTENSA_SYSCALL_READ:
104  snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "read");
105  fileio_info->param_1 = arg0; // fd
106  fileio_info->param_2 = arg1; // bufp
107  fileio_info->param_3 = arg2; // count
108  break;
110  snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "write");
111  fileio_info->param_1 = arg0; // fd
112  fileio_info->param_2 = arg1; // bufp
113  fileio_info->param_3 = arg2; // count
114  break;
116  snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "lseek");
117  fileio_info->param_1 = arg0; // fd
118  fileio_info->param_2 = arg1; // offset
119  fileio_info->param_3 = arg2; // flags
120  break;
122  snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "rename");
123  fileio_info->param_1 = arg0; // old pathp
124  fileio_info->param_2 = arg3; // old len
125  fileio_info->param_3 = arg1; // new pathp
126  fileio_info->param_4 = arg2; // new len
127  break;
129  snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "unlink");
130  fileio_info->param_1 = arg0; // pathnamep
131  fileio_info->param_2 = arg1; // len
132  break;
133  case XTENSA_SYSCALL_STAT:
134  snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "stat");
135  fileio_info->param_1 = arg0; // pathnamep
136  fileio_info->param_2 = arg2; // len
137  fileio_info->param_3 = arg1; // bufp
138  break;
140  snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "fstat");
141  fileio_info->param_1 = arg0; // fd
142  fileio_info->param_2 = arg1; // bufp
143  break;
145  snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "gettimeofday");
146  fileio_info->param_1 = arg0; // tvp
147  fileio_info->param_2 = arg1; // tzp
148  break;
150  snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "isatty");
151  fileio_info->param_1 = arg0; // fd
152  break;
154  snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "system");
155  fileio_info->param_1 = arg0; // cmdp
156  fileio_info->param_2 = arg1; // len
157  break;
158  default:
159  snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "unknown");
160  LOG_TARGET_DEBUG(target, "File-I/O: syscall unknown (%d), pc=0x%08X",
161  syscall, xtensa_reg_get(target, XT_REG_IDX_PC));
162  LOG_INFO("File-I/O: syscall unknown (%d), pc=0x%08X",
163  syscall, xtensa_reg_get(target, XT_REG_IDX_PC));
164  retval = ERROR_FAIL;
165  break;
166  }
167 
168  return retval;
169 }
170 
171 int xtensa_gdb_fileio_end(struct target *target, int retcode, int fileio_errno, bool ctrl_c)
172 {
174  if (!xtensa->proc_syscall)
175  return ERROR_FAIL;
176 
177  LOG_TARGET_DEBUG(target, "File-I/O: syscall return code: 0x%x, errno: 0x%x , ctrl_c: %s",
178  retcode, fileio_errno, ctrl_c ? "true" : "false");
179 
180  /* If interrupt was requested before FIO completion (ERRNO==4), halt and repeat
181  * syscall. Otherwise, set File-I/O Ax and underlying ARx registers, increment PC.
182  * NOTE: sporadic cases of ((ERRNO==4) && !ctrl_c) were observed; most have ctrl_c.
183  */
184  if (fileio_errno != 4) {
187 
190  }
191 
192  xtensa->proc_syscall = false;
193  xtensa->halt_request = true;
194  return ctrl_c ? ERROR_FAIL : ERROR_OK;
195 }
static uint32_t buf_get_u32(const uint8_t *_buffer, unsigned first, unsigned num)
Retrieves num bits from _buffer, starting at the first bit, returning the bits in a 32-bit word.
Definition: binarybuffer.h:99
#define XTENSA_SYSCALL_OP_REG
#define XTENSA_SYSCALL_RETVAL_REG
#define XTENSA_SYSCALL_ERRNO_REG
#define ERROR_FAIL
Definition: log.h:170
#define LOG_TARGET_ERROR(target, fmt_str,...)
Definition: log.h:158
#define LOG_TARGET_DEBUG(target, fmt_str,...)
Definition: log.h:149
#define LOG_ERROR(expr ...)
Definition: log.h:132
#define LOG_INFO(expr ...)
Definition: log.h:126
#define ERROR_OK
Definition: log.h:164
uint64_t param_1
Definition: target.h:219
uint64_t param_4
Definition: target.h:222
uint64_t param_3
Definition: target.h:221
char * identifier
Definition: target.h:218
uint64_t param_2
Definition: target.h:220
Definition: target.h:116
struct gdb_fileio_info * fileio_info
Definition: target.h:202
Represents a generic Xtensa core.
Definition: xtensa.h:241
bool halt_request
Definition: xtensa.h:283
bool proc_syscall
Definition: xtensa.h:282
int target_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer)
Read count items of size bytes from the memory of target at the address given.
Definition: target.c:1237
void xtensa_reg_set_deep_relgen(struct target *target, enum xtensa_reg_id a_idx, xtensa_reg_val_t value)
Definition: xtensa.c:1015
uint32_t xtensa_cause_get(struct target *target)
Definition: xtensa.c:1030
void xtensa_reg_set(struct target *target, enum xtensa_reg_id reg_id, xtensa_reg_val_t value)
Definition: xtensa.c:1005
xtensa_reg_val_t xtensa_reg_get(struct target *target, enum xtensa_reg_id reg_id)
Definition: xtensa.c:998
Holds the interface to Xtensa cores.
static struct xtensa * target_to_xtensa(struct target *target)
Definition: xtensa.h:290
#define DEBUGCAUSE_BI
#define DEBUGCAUSE_BN
#define XTENSA_SYSCALL_LEN_MAX
Definition: xtensa_fileio.c:18
int xtensa_fileio_detect_proc(struct target *target)
Checks for and processes an Xtensa File-IO request.
Definition: xtensa_fileio.c:41
#define XTENSA_SYSCALL(x)
Definition: xtensa_fileio.c:16
int xtensa_gdb_fileio_end(struct target *target, int retcode, int fileio_errno, bool ctrl_c)
int xtensa_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info)
Definition: xtensa_fileio.c:69
#define XTENSA_SYSCALL_SZ
Definition: xtensa_fileio.c:17
int xtensa_fileio_init(struct target *target)
Definition: xtensa_fileio.c:21
#define XTENSA_SYSCALL_READ
Definition: xtensa_fileio.h:21
#define XTENSA_SYSCALL_UNLINK
Definition: xtensa_fileio.h:25
#define XTENSA_SYSCALL_STAT
Definition: xtensa_fileio.h:26
#define XTENSA_SYSCALL_RENAME
Definition: xtensa_fileio.h:24
#define XTENSA_SYSCALL_SYSTEM
Definition: xtensa_fileio.h:30
#define XTENSA_SYSCALL_CLOSE
Definition: xtensa_fileio.h:20
#define XTENSA_SYSCALL_WRITE
Definition: xtensa_fileio.h:22
#define XTENSA_SYSCALL_LSEEK
Definition: xtensa_fileio.h:23
#define XTENSA_SYSCALL_GETTIMEOFDAY
Definition: xtensa_fileio.h:28
#define XTENSA_SYSCALL_ISATTY
Definition: xtensa_fileio.h:29
#define XTENSA_SYSCALL_FSTAT
Definition: xtensa_fileio.h:27
#define XTENSA_SYSCALL_OPEN
Definition: xtensa_fileio.h:19
@ XT_REG_IDX_PC
Definition: xtensa_regs.h:16
@ XT_REG_IDX_A3
Definition: xtensa_regs.h:54
@ XT_REG_IDX_A6
Definition: xtensa_regs.h:57
@ XT_REG_IDX_A4
Definition: xtensa_regs.h:55
@ XT_REG_IDX_A5
Definition: xtensa_regs.h:56
uint32_t xtensa_reg_val_t
Definition: xtensa_regs.h:70