Overhaul of semihosting. Remove dependence of target on gdb_packet.
This commit is contained in:
parent
b03cc59bea
commit
b644724520
|
@ -31,6 +31,7 @@ SRC = \
|
|||
exception.c \
|
||||
gdb_if.c \
|
||||
gdb_main.c \
|
||||
gdb_hostio.c \
|
||||
gdb_packet.c \
|
||||
hex_utils.c \
|
||||
jtag_scan.c \
|
||||
|
|
133
src/cortexm.c
133
src/cortexm.c
|
@ -30,14 +30,10 @@
|
|||
#include "adiv5.h"
|
||||
#include "target.h"
|
||||
#include "target_internal.h"
|
||||
#include "gdb_packet.h"
|
||||
#include "cortexm.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
/* On some systems this is a macro and causes problems */
|
||||
#undef errno
|
||||
|
||||
static char cortexm_driver_str[] = "ARM Cortex-M";
|
||||
|
||||
static bool cortexm_vector_catch(target *t, int argc, char *argv[]);
|
||||
|
@ -78,7 +74,6 @@ static int cortexm_check_hw_wp(target *t, uint32_t *addr);
|
|||
#define CORTEXM_MAX_BREAKPOINTS 6 /* architecture says up to 127, no implementation has > 6 */
|
||||
|
||||
static int cortexm_hostio_request(target *t);
|
||||
static void cortexm_hostio_reply(target *t, int32_t retcode, uint32_t errcode);
|
||||
|
||||
struct cortexm_priv {
|
||||
ADIv5_AP_t *ap;
|
||||
|
@ -97,10 +92,6 @@ struct cortexm_priv {
|
|||
unsigned hw_breakpoint_max;
|
||||
/* Copy of DEMCR for vector-catch */
|
||||
uint32_t demcr;
|
||||
/* Semihosting state */
|
||||
uint32_t syscall;
|
||||
uint32_t errno;
|
||||
uint32_t byte_count;
|
||||
};
|
||||
|
||||
/* Register number tables */
|
||||
|
@ -255,8 +246,6 @@ bool cortexm_probe(ADIv5_AP_t *ap)
|
|||
t->halt_resume = cortexm_halt_resume;
|
||||
t->regs_size = sizeof(regnum_cortex_m);
|
||||
|
||||
t->hostio_reply = cortexm_hostio_reply;
|
||||
|
||||
target_add_commands(t, cortexm_cmd_list, cortexm_driver_str);
|
||||
|
||||
/* Probe for FP extension */
|
||||
|
@ -531,12 +520,11 @@ static int cortexm_halt_wait(target *t)
|
|||
uint16_t bkpt_instr;
|
||||
bkpt_instr = target_mem_read16(t, pc);
|
||||
if (bkpt_instr == 0xBEAB) {
|
||||
int n = cortexm_hostio_request(t);
|
||||
if (n > 0) {
|
||||
if (cortexm_hostio_request(t)) {
|
||||
return SIGINT;
|
||||
} else {
|
||||
target_halt_resume(t, priv->stepping);
|
||||
return 0;
|
||||
} else if (n < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -876,40 +864,30 @@ static bool cortexm_vector_catch(target *t, int argc, char *argv[])
|
|||
#define SYS_WRITEC 0x03
|
||||
#define SYS_WRITE0 0x04
|
||||
|
||||
#define FILEIO_O_RDONLY 0
|
||||
#define FILEIO_O_WRONLY 1
|
||||
#define FILEIO_O_RDWR 2
|
||||
#define FILEIO_O_APPEND 0x008
|
||||
#define FILEIO_O_CREAT 0x200
|
||||
#define FILEIO_O_TRUNC 0x400
|
||||
|
||||
#define FILEIO_SEEK_SET 0
|
||||
#define FILEIO_SEEK_CUR 1
|
||||
#define FILEIO_SEEK_END 2
|
||||
|
||||
static int cortexm_hostio_request(target *t)
|
||||
{
|
||||
struct cortexm_priv *priv = t->priv;
|
||||
uint32_t arm_regs[t->regs_size];
|
||||
uint32_t params[4];
|
||||
|
||||
t->tc->interrupted = false;
|
||||
target_regs_read(t, arm_regs);
|
||||
target_mem_read(t, params, arm_regs[1], sizeof(params));
|
||||
priv->syscall = arm_regs[0];
|
||||
uint32_t syscall = arm_regs[0];
|
||||
int32_t ret = 0;
|
||||
|
||||
DEBUG("syscall 0x%x (%x %x %x %x)\n", priv->syscall,
|
||||
DEBUG("syscall 0x%x (%x %x %x %x)\n", syscall,
|
||||
params[0], params[1], params[2], params[3]);
|
||||
switch (priv->syscall) {
|
||||
switch (syscall) {
|
||||
case SYS_OPEN:{ /* open */
|
||||
/* Translate stupid fopen modes to open flags.
|
||||
* See DUI0471C, Table 8-3 */
|
||||
const uint32_t flags[] = {
|
||||
FILEIO_O_RDONLY, /* r, rb */
|
||||
FILEIO_O_RDWR, /* r+, r+b */
|
||||
FILEIO_O_WRONLY | FILEIO_O_CREAT | FILEIO_O_TRUNC,/*w*/
|
||||
FILEIO_O_RDWR | FILEIO_O_CREAT | FILEIO_O_TRUNC,/*w+*/
|
||||
FILEIO_O_WRONLY | FILEIO_O_CREAT | FILEIO_O_APPEND,/*a*/
|
||||
FILEIO_O_RDWR | FILEIO_O_CREAT | FILEIO_O_APPEND,/*a+*/
|
||||
TARGET_O_RDONLY, /* r, rb */
|
||||
TARGET_O_RDWR, /* r+, r+b */
|
||||
TARGET_O_WRONLY | TARGET_O_CREAT | TARGET_O_TRUNC,/*w*/
|
||||
TARGET_O_RDWR | TARGET_O_CREAT | TARGET_O_TRUNC,/*w+*/
|
||||
TARGET_O_WRONLY | TARGET_O_CREAT | TARGET_O_APPEND,/*a*/
|
||||
TARGET_O_RDWR | TARGET_O_CREAT | TARGET_O_APPEND,/*a+*/
|
||||
};
|
||||
uint32_t pflag = flags[params[1] >> 1];
|
||||
char filename[4];
|
||||
|
@ -917,91 +895,70 @@ static int cortexm_hostio_request(target *t)
|
|||
target_mem_read(t, filename, params[0], sizeof(filename));
|
||||
/* handle requests for console i/o */
|
||||
if (!strcmp(filename, ":tt")) {
|
||||
if (pflag == FILEIO_O_RDONLY)
|
||||
arm_regs[0] = STDIN_FILENO;
|
||||
else if (pflag & FILEIO_O_TRUNC)
|
||||
arm_regs[0] = STDOUT_FILENO;
|
||||
if (pflag == TARGET_O_RDONLY)
|
||||
ret = STDIN_FILENO;
|
||||
else if (pflag & TARGET_O_TRUNC)
|
||||
ret = STDOUT_FILENO;
|
||||
else
|
||||
arm_regs[0] = STDERR_FILENO;
|
||||
arm_regs[0]++;
|
||||
target_regs_write(t, arm_regs);
|
||||
return 1;
|
||||
ret = STDERR_FILENO;
|
||||
ret++;
|
||||
break;
|
||||
}
|
||||
|
||||
gdb_putpacket_f("Fopen,%08X/%X,%08X,%08X",
|
||||
params[0], params[2] + 1,
|
||||
pflag, 0644);
|
||||
ret = tc_open(t, params[0], params[2] + 1, pflag, 0644);
|
||||
if (ret != -1)
|
||||
ret++;
|
||||
break;
|
||||
}
|
||||
case SYS_CLOSE: /* close */
|
||||
gdb_putpacket_f("Fclose,%08X", params[0] - 1);
|
||||
ret = tc_close(t, params[0] - 1);
|
||||
break;
|
||||
case SYS_READ: /* read */
|
||||
priv->byte_count = params[2];
|
||||
gdb_putpacket_f("Fread,%08X,%08X,%08X",
|
||||
params[0] - 1, params[1], params[2]);
|
||||
ret = tc_read(t, params[0] - 1, params[1], params[2]);
|
||||
if (ret > 0)
|
||||
ret = params[2] - ret;
|
||||
break;
|
||||
case SYS_WRITE: /* write */
|
||||
priv->byte_count = params[2];
|
||||
gdb_putpacket_f("Fwrite,%08X,%08X,%08X",
|
||||
params[0] - 1, params[1], params[2]);
|
||||
ret = tc_write(t, params[0] - 1, params[1], params[2]);
|
||||
if (ret > 0)
|
||||
ret = params[2] - ret;
|
||||
break;
|
||||
case SYS_WRITEC: /* writec */
|
||||
gdb_putpacket_f("Fwrite,2,%08X,1", arm_regs[1]);
|
||||
ret = tc_write(t, 2, arm_regs[1], 1);
|
||||
break;
|
||||
case SYS_ISTTY: /* isatty */
|
||||
gdb_putpacket_f("Fisatty,%08X", params[0] - 1);
|
||||
ret = tc_isatty(t, params[0] - 1);
|
||||
break;
|
||||
case SYS_SEEK: /* lseek */
|
||||
gdb_putpacket_f("Flseek,%08X,%08X,%08X",
|
||||
params[0] - 1, params[1], FILEIO_SEEK_SET);
|
||||
ret = tc_lseek(t, params[0] - 1, params[1], TARGET_SEEK_SET);
|
||||
break;
|
||||
case SYS_RENAME:/* rename */
|
||||
gdb_putpacket_f("Frename,%08X/%X,%08X/%X",
|
||||
params[0] - 1, params[1] + 1,
|
||||
ret = tc_rename(t, params[0] - 1, params[1] + 1,
|
||||
params[2], params[3] + 1);
|
||||
break;
|
||||
case SYS_REMOVE:/* unlink */
|
||||
gdb_putpacket_f("Funlink,%08X/%X", params[0] - 1,
|
||||
params[1] + 1);
|
||||
ret = tc_unlink(t, params[0] - 1, params[1] + 1);
|
||||
break;
|
||||
case SYS_SYSTEM:/* system */
|
||||
gdb_putpacket_f("Fsystem,%08X/%X", params[0] - 1,
|
||||
params[1] + 1);
|
||||
ret = tc_system(t, params[0] - 1, params[1] + 1);
|
||||
break;
|
||||
|
||||
case SYS_FLEN: /* Not supported, fake success */
|
||||
priv->errno = 0;
|
||||
return 1;
|
||||
t->tc->errno_ = 0;
|
||||
break;
|
||||
|
||||
case SYS_ERRNO: /* Return last errno from GDB */
|
||||
arm_regs[0] = priv->errno;
|
||||
target_regs_write(t, arm_regs);
|
||||
return 1;
|
||||
ret = t->tc->errno_;
|
||||
break;
|
||||
|
||||
case SYS_TIME: /* gettimeofday */
|
||||
/* FIXME How do we use gdb's gettimeofday? */
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void cortexm_hostio_reply(target *t, int32_t retcode, uint32_t errcode)
|
||||
{
|
||||
struct cortexm_priv *priv = t->priv;
|
||||
uint32_t arm_regs[t->regs_size];
|
||||
|
||||
DEBUG("syscall return ret=%d errno=%d\n", retcode, errcode);
|
||||
target_regs_read(t, arm_regs);
|
||||
if (((priv->syscall == SYS_READ) || (priv->syscall == SYS_WRITE)) &&
|
||||
(retcode > 0))
|
||||
retcode = priv->byte_count - retcode;
|
||||
if ((priv->syscall == SYS_OPEN) && (retcode != -1))
|
||||
retcode++;
|
||||
arm_regs[0] = retcode;
|
||||
arm_regs[0] = ret;
|
||||
target_regs_write(t, arm_regs);
|
||||
priv->errno = errcode;
|
||||
|
||||
return t->tc->interrupted;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* This file is part of the Black Magic Debug project.
|
||||
*
|
||||
* Copyright (C) 2016 Black Sphere Technologies Ltd.
|
||||
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "general.h"
|
||||
#include "target.h"
|
||||
#include "gdb_main.h"
|
||||
#include "gdb_hostio.h"
|
||||
#include "gdb_packet.h"
|
||||
|
||||
int gdb_main_loop(struct target_controller *, bool in_syscall);
|
||||
|
||||
int hostio_reply(struct target_controller *tc, char *pbuf, int len)
|
||||
{
|
||||
(void)len;
|
||||
int retcode, items;
|
||||
char c, *p;
|
||||
if (pbuf[1] == '-')
|
||||
p = &pbuf[2];
|
||||
else
|
||||
p = &pbuf[1];
|
||||
items = sscanf(p, "%x,%x,%c", &retcode, &tc->errno_, &c);
|
||||
if (pbuf[1] == '-')
|
||||
retcode = -retcode;
|
||||
|
||||
/* if break is requested */
|
||||
tc->interrupted = items == 3 && c == 'C';
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
/* Interface to host system calls */
|
||||
int hostio_open(struct target_controller *tc,
|
||||
target_addr path, unsigned path_len,
|
||||
enum target_open_flags flags, mode_t mode)
|
||||
{
|
||||
gdb_putpacket_f("Fopen,%08X/%X,%08X,%08X", path, path_len, flags, mode);;;;
|
||||
return gdb_main_loop(tc, true);
|
||||
}
|
||||
|
||||
int hostio_close(struct target_controller *tc, int fd)
|
||||
{
|
||||
gdb_putpacket_f("Fclose,%08X", fd);
|
||||
return gdb_main_loop(tc, true);
|
||||
}
|
||||
|
||||
int hostio_read(struct target_controller *tc,
|
||||
int fd, target_addr buf, unsigned int count)
|
||||
{
|
||||
gdb_putpacket_f("Fread,%08X,%08X,%08X", fd, buf, count);
|
||||
return gdb_main_loop(tc, true);
|
||||
}
|
||||
|
||||
int hostio_write(struct target_controller *tc,
|
||||
int fd, target_addr buf, unsigned int count)
|
||||
{
|
||||
gdb_putpacket_f("Fwrite,%08X,%08X,%08X", fd, buf, count);
|
||||
return gdb_main_loop(tc, true);
|
||||
}
|
||||
|
||||
long hostio_lseek(struct target_controller *tc,
|
||||
int fd, long offset, enum target_seek_flag flag)
|
||||
{
|
||||
gdb_putpacket_f("Flseek,%08X,%08X,%08X", fd, offset, flag);
|
||||
return gdb_main_loop(tc, true);
|
||||
}
|
||||
|
||||
int hostio_rename(struct target_controller *tc,
|
||||
target_addr oldpath, unsigned old_len,
|
||||
target_addr newpath, unsigned new_len)
|
||||
{
|
||||
gdb_putpacket_f("Frename,%08X/%X,%08X/%X",
|
||||
oldpath, old_len, newpath, new_len);
|
||||
return gdb_main_loop(tc, true);
|
||||
}
|
||||
|
||||
int hostio_unlink(struct target_controller *tc,
|
||||
target_addr path, unsigned path_len)
|
||||
{
|
||||
gdb_putpacket_f("Funlink,%08X/%X", path, path_len);
|
||||
return gdb_main_loop(tc, true);
|
||||
}
|
||||
|
||||
int hostio_stat(struct target_controller *tc,
|
||||
target_addr path, unsigned path_len, target_addr buf)
|
||||
{
|
||||
gdb_putpacket_f("Fstat,%08X/%X,%08X", path, path_len, buf);
|
||||
return gdb_main_loop(tc, true);
|
||||
}
|
||||
|
||||
int hostio_fstat(struct target_controller *tc, int fd, target_addr buf)
|
||||
{
|
||||
gdb_putpacket_f("Ffstat,%X,%08X", fd, buf);
|
||||
return gdb_main_loop(tc, true);
|
||||
}
|
||||
|
||||
int hostio_gettimeofday(struct target_controller *tc,
|
||||
target_addr tv, target_addr tz)
|
||||
{
|
||||
gdb_putpacket_f("Fgettimeofday,%08X,%08X", tv, tz);
|
||||
return gdb_main_loop(tc, true);
|
||||
}
|
||||
|
||||
int hostio_isatty(struct target_controller *tc, int fd)
|
||||
{
|
||||
gdb_putpacket_f("Fisatty,%08X", fd);
|
||||
return gdb_main_loop(tc, true);
|
||||
}
|
||||
|
||||
int hostio_system(struct target_controller *tc,
|
||||
target_addr cmd, unsigned cmd_len)
|
||||
{
|
||||
gdb_putpacket_f("Fsystem,%08X/%X", cmd, cmd_len);
|
||||
return gdb_main_loop(tc, true);
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* This file is part of the Black Magic Debug project.
|
||||
*
|
||||
* Copyright (C) 2016 Black Sphere Technologies Ltd.
|
||||
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef __GDB_SYSCALLS_H
|
||||
#define __GDB_SYSCALLS_H
|
||||
|
||||
#include "target.h"
|
||||
|
||||
int hostio_reply(struct target_controller *tc, char *packet, int len);
|
||||
|
||||
/* Interface to host system calls */
|
||||
int hostio_open(struct target_controller *,
|
||||
target_addr path, unsigned path_len,
|
||||
enum target_open_flags flags, mode_t mode);
|
||||
int hostio_close(struct target_controller *, int fd);
|
||||
int hostio_read(struct target_controller *,
|
||||
int fd, target_addr buf, unsigned int count);
|
||||
int hostio_write(struct target_controller *,
|
||||
int fd, target_addr buf, unsigned int count);
|
||||
long hostio_lseek(struct target_controller *,
|
||||
int fd, long offset, enum target_seek_flag flag);
|
||||
int hostio_rename(struct target_controller *,
|
||||
target_addr oldpath, unsigned old_len,
|
||||
target_addr newpath, unsigned new_len);
|
||||
int hostio_unlink(struct target_controller *,
|
||||
target_addr path, unsigned path_len);
|
||||
int hostio_stat(struct target_controller *,
|
||||
target_addr path, unsigned path_len, target_addr buf);
|
||||
int hostio_fstat(struct target_controller *, int fd, target_addr buf);
|
||||
int hostio_gettimeofday(struct target_controller *,
|
||||
target_addr tv, target_addr tz);
|
||||
int hostio_isatty(struct target_controller *, int fd);
|
||||
int hostio_system(struct target_controller *,
|
||||
target_addr cmd, unsigned cmd_len);
|
||||
|
||||
#endif
|
||||
|
|
@ -29,6 +29,7 @@
|
|||
#include "gdb_if.h"
|
||||
#include "gdb_packet.h"
|
||||
#include "gdb_main.h"
|
||||
#include "gdb_hostio.h"
|
||||
#include "target.h"
|
||||
#include "command.h"
|
||||
#include "crc32.h"
|
||||
|
@ -67,14 +68,25 @@ static void gdb_target_printf(struct target_controller *tc,
|
|||
static struct target_controller gdb_controller = {
|
||||
.destroy_callback = gdb_target_destroy_callback,
|
||||
.printf = gdb_target_printf,
|
||||
|
||||
.open = hostio_open,
|
||||
.close = hostio_close,
|
||||
.read = hostio_read,
|
||||
.write = hostio_write,
|
||||
.lseek = hostio_lseek,
|
||||
.rename = hostio_rename,
|
||||
.unlink = hostio_unlink,
|
||||
.stat = hostio_stat,
|
||||
.fstat = hostio_fstat,
|
||||
.gettimeofday = hostio_gettimeofday,
|
||||
.isatty = hostio_isatty,
|
||||
.system = hostio_system,
|
||||
};
|
||||
|
||||
void
|
||||
gdb_main(void)
|
||||
int gdb_main_loop(struct target_controller *tc, bool in_syscall)
|
||||
{
|
||||
int size;
|
||||
bool single_step = false;
|
||||
char last_activity = 0;
|
||||
|
||||
DEBUG("Entring GDB protocol main loop\n");
|
||||
/* GDB protocol main loop */
|
||||
|
@ -82,7 +94,6 @@ gdb_main(void)
|
|||
SET_IDLE_STATE(1);
|
||||
size = gdb_getpacket(pbuf, BUF_SIZE);
|
||||
SET_IDLE_STATE(0);
|
||||
continue_activity:
|
||||
switch(pbuf[0]) {
|
||||
/* Implementation of these is mandatory! */
|
||||
case 'g': { /* 'g': Read general registers */
|
||||
|
@ -154,13 +165,11 @@ gdb_main(void)
|
|||
break;
|
||||
}
|
||||
|
||||
last_activity = pbuf[0];
|
||||
/* Wait for target halt */
|
||||
while(!(sig = target_halt_wait(cur_target))) {
|
||||
unsigned char c = gdb_if_getchar_to(0);
|
||||
if((c == '\x03') || (c == '\x04')) {
|
||||
target_halt_request(cur_target);
|
||||
last_activity = 's';
|
||||
}
|
||||
}
|
||||
SET_RUN_STATE(0);
|
||||
|
@ -184,28 +193,14 @@ gdb_main(void)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case 'F': { /* Semihosting call finished */
|
||||
int retcode, errcode, items;
|
||||
char c, *p;
|
||||
if (pbuf[1] == '-')
|
||||
p = &pbuf[2];
|
||||
else
|
||||
p = &pbuf[1];
|
||||
items = sscanf(p, "%x,%x,%c", &retcode, &errcode, &c);
|
||||
if (pbuf[1] == '-')
|
||||
retcode = -retcode;
|
||||
|
||||
target_hostio_reply(cur_target, retcode, errcode);
|
||||
|
||||
/* if break is requested */
|
||||
if (items == 3 && c == 'C') {
|
||||
gdb_putpacketz("T02");
|
||||
break;
|
||||
case 'F': /* Semihosting call finished */
|
||||
if (in_syscall) {
|
||||
return hostio_reply(tc, pbuf, size);
|
||||
} else {
|
||||
DEBUG("*** F packet when not in syscall! '%s'\n", pbuf);
|
||||
gdb_putpacketz("");
|
||||
}
|
||||
|
||||
pbuf[0] = last_activity;
|
||||
goto continue_activity;
|
||||
}
|
||||
break;
|
||||
|
||||
/* Optional GDB packet support */
|
||||
case '!': /* Enable Extended GDB Protocol. */
|
||||
|
@ -480,3 +475,8 @@ handle_z_packet(char *packet, int plen)
|
|||
gdb_putpacketz("E01");
|
||||
}
|
||||
|
||||
void gdb_main(void)
|
||||
{
|
||||
gdb_main_loop(&gdb_controller, false);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,10 @@
|
|||
#ifndef __TARGET_H
|
||||
#define __TARGET_H
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
typedef struct target_s target;
|
||||
typedef uint32_t target_addr;
|
||||
|
||||
int adiv5_swdp_scan(void);
|
||||
int jtag_scan(const uint8_t *lrlens);
|
||||
|
@ -33,9 +36,51 @@ int jtag_scan(const uint8_t *lrlens);
|
|||
bool target_foreach(void (*cb)(int i, target *t, void *context), void *context);
|
||||
void target_list_free(void);
|
||||
|
||||
enum target_open_flags {
|
||||
TARGET_O_RDONLY = 0,
|
||||
TARGET_O_WRONLY = 1,
|
||||
TARGET_O_RDWR = 2,
|
||||
TARGET_O_APPEND = 0x008,
|
||||
TARGET_O_CREAT = 0x200,
|
||||
TARGET_O_TRUNC = 0x400,
|
||||
};
|
||||
|
||||
enum target_seek_flag {
|
||||
TARGET_SEEK_SET = 0,
|
||||
TARGET_SEEK_CUR = 1,
|
||||
TARGET_SEEK_END = 2,
|
||||
};
|
||||
|
||||
struct target_controller {
|
||||
void (*destroy_callback)(struct target_controller *, target *t);
|
||||
void (*printf)(struct target_controller *, const char *fmt, va_list);
|
||||
|
||||
/* Interface to host system calls */
|
||||
int (*open)(struct target_controller *,
|
||||
target_addr path, unsigned path_len,
|
||||
enum target_open_flags flags, mode_t mode);
|
||||
int (*close)(struct target_controller *, int fd);
|
||||
int (*read)(struct target_controller *,
|
||||
int fd, target_addr buf, unsigned int count);
|
||||
int (*write)(struct target_controller *,
|
||||
int fd, target_addr buf, unsigned int count);
|
||||
long (*lseek)(struct target_controller *,
|
||||
int fd, long offset, enum target_seek_flag flag);
|
||||
int (*rename)(struct target_controller *,
|
||||
target_addr oldpath, unsigned old_len,
|
||||
target_addr newpath, unsigned new_len);
|
||||
int (*unlink)(struct target_controller *,
|
||||
target_addr path, unsigned path_len);
|
||||
int (*stat)(struct target_controller *,
|
||||
target_addr path, unsigned path_len, target_addr buf);
|
||||
int (*fstat)(struct target_controller *, int fd, target_addr buf);
|
||||
int (*gettimeofday)(struct target_controller *,
|
||||
target_addr tv, target_addr tz);
|
||||
int (*isatty)(struct target_controller *, int fd);
|
||||
int (*system)(struct target_controller *,
|
||||
target_addr cmd, unsigned cmd_len);
|
||||
int errno_;
|
||||
bool interrupted;
|
||||
};
|
||||
|
||||
/* Halt/resume functions */
|
||||
|
@ -72,9 +117,6 @@ int target_flash_erase(target *t, uint32_t addr, size_t len);
|
|||
int target_flash_write(target *t, uint32_t dest, const void *src, size_t len);
|
||||
int target_flash_done(target *t);
|
||||
|
||||
/* Host I/O */
|
||||
void target_hostio_reply(target *t, int32_t retcode, uint32_t errcode);
|
||||
|
||||
/* Accessor functions */
|
||||
int target_regs_size(target *t);
|
||||
const char *target_tdesc(target *t);
|
||||
|
|
69
src/target.c
69
src/target.c
|
@ -344,12 +344,6 @@ int target_check_hw_wp(target *t, uint32_t *addr)
|
|||
return t->check_hw_wp(t, addr);
|
||||
}
|
||||
|
||||
/* Host I/O */
|
||||
void target_hostio_reply(target *t, int32_t retcode, uint32_t errcode)
|
||||
{
|
||||
t->hostio_reply(t, retcode, errcode);
|
||||
}
|
||||
|
||||
/* Accessor functions */
|
||||
int target_regs_size(target *t)
|
||||
{
|
||||
|
@ -429,3 +423,66 @@ void tc_printf(target *t, const char *fmt, ...)
|
|||
va_end(ap);
|
||||
}
|
||||
|
||||
/* Interface to host system calls */
|
||||
int tc_open(target *t, target_addr path, unsigned plen,
|
||||
enum target_open_flags flags, mode_t mode)
|
||||
{
|
||||
return t->tc->open(t->tc, path, plen, flags, mode);
|
||||
}
|
||||
|
||||
int tc_close(target *t, int fd)
|
||||
{
|
||||
return t->tc->close(t->tc, fd);
|
||||
}
|
||||
|
||||
int tc_read(target *t, int fd, target_addr buf, unsigned int count)
|
||||
{
|
||||
return t->tc->read(t->tc, fd, buf, count);
|
||||
}
|
||||
|
||||
int tc_write(target *t, int fd, target_addr buf, unsigned int count)
|
||||
{
|
||||
return t->tc->write(t->tc, fd, buf, count);
|
||||
}
|
||||
|
||||
long tc_lseek(target *t, int fd, long offset, enum target_seek_flag flag)
|
||||
{
|
||||
return t->tc->lseek(t->tc, fd, offset, flag);
|
||||
}
|
||||
|
||||
int tc_rename(target *t, target_addr oldpath, unsigned oldlen,
|
||||
target_addr newpath, unsigned newlen)
|
||||
{
|
||||
return t->tc->rename(t->tc, oldpath, oldlen, newpath, newlen);
|
||||
}
|
||||
|
||||
int tc_unlink(target *t, target_addr path, unsigned plen)
|
||||
{
|
||||
return t->tc->unlink(t->tc, path, plen);
|
||||
}
|
||||
|
||||
int tc_stat(target *t, target_addr path, unsigned plen, target_addr buf)
|
||||
{
|
||||
return t->tc->stat(t->tc, path, plen, buf);
|
||||
}
|
||||
|
||||
int tc_fstat(target *t, int fd, target_addr buf)
|
||||
{
|
||||
return t->tc->fstat(t->tc, fd, buf);
|
||||
}
|
||||
|
||||
int tc_gettimeofday(target *t, target_addr tv, target_addr tz)
|
||||
{
|
||||
return t->tc->gettimeofday(t->tc, tv, tz);
|
||||
}
|
||||
|
||||
int tc_isatty(target *t, int fd)
|
||||
{
|
||||
return t->tc->isatty(t->tc, fd);
|
||||
}
|
||||
|
||||
int tc_system(target *t, target_addr cmd, unsigned cmdlen)
|
||||
{
|
||||
return t->tc->system(t->tc, cmd, cmdlen);
|
||||
}
|
||||
|
||||
|
|
|
@ -113,9 +113,7 @@ struct target_s {
|
|||
struct target_ram *ram;
|
||||
struct target_flash *flash;
|
||||
|
||||
/* Host I/O support */
|
||||
void (*hostio_reply)(target *t, int32_t retcode, uint32_t errcode);
|
||||
|
||||
/* Other stuff */
|
||||
const char *driver;
|
||||
struct target_command_s *commands;
|
||||
|
||||
|
@ -143,6 +141,23 @@ void target_mem_write8(target *t, uint32_t addr, uint8_t value);
|
|||
/* Access to host controller interface */
|
||||
void tc_printf(target *t, const char *fmt, ...);
|
||||
|
||||
/* Interface to host system calls */
|
||||
int tc_open(target *, target_addr path, unsigned plen,
|
||||
enum target_open_flags flags, mode_t mode);
|
||||
int tc_close(target *t, int fd);
|
||||
int tc_read(target *t, int fd, target_addr buf, unsigned int count);
|
||||
int tc_write(target *t, int fd, target_addr buf, unsigned int count);
|
||||
long tc_lseek(target *t, int fd, long offset,
|
||||
enum target_seek_flag flag);
|
||||
int tc_rename(target *t, target_addr oldpath, unsigned oldlen,
|
||||
target_addr newpath, unsigned newlen);
|
||||
int tc_unlink(target *t, target_addr path, unsigned plen);
|
||||
int tc_stat(target *t, target_addr path, unsigned plen, target_addr buf);
|
||||
int tc_fstat(target *t, int fd, target_addr buf);
|
||||
int tc_gettimeofday(target *t, target_addr tv, target_addr tz);
|
||||
int tc_isatty(target *t, int fd);
|
||||
int tc_system(target *t, target_addr cmd, unsigned cmdlen);
|
||||
|
||||
/* Probe for various targets.
|
||||
* Actual functions implemented in their respective drivers.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue