Add support for Semihosting v2 support for ARM in libgloss.
Semihosting v2 changes are documented here: https://developer.arm.com/docs/100863/latest/ The biggest change is the addition of an extensions mechanism to add more extensions in the future. Signed-off-by: Tamar Christina <tamar.christina@arm.com>
This commit is contained in:
committed by
Corinna Vinschen
parent
cc142edbe7
commit
d7d6ad7b6b
@ -47,6 +47,9 @@ static int checkerror _PARAMS ((int));
|
||||
static int error _PARAMS ((int));
|
||||
static int get_errno _PARAMS ((void));
|
||||
|
||||
/* Semihosting utilities. */
|
||||
static void initialise_semihosting_exts _PARAMS ((void));
|
||||
|
||||
/* Struct used to keep track of the file position, just so we
|
||||
can implement fseek(fh,x,SEEK_CUR). */
|
||||
struct fdent
|
||||
@ -95,6 +98,9 @@ static int monitor_stdin;
|
||||
static int monitor_stdout;
|
||||
static int monitor_stderr;
|
||||
|
||||
static int supports_ext_exit_extended = -1;
|
||||
static int supports_ext_stdout_stderr = -1;
|
||||
|
||||
/* Return a pointer to the structure associated with
|
||||
the user file descriptor fd. */
|
||||
static struct fdent*
|
||||
@ -154,15 +160,21 @@ initialise_monitor_handles (void)
|
||||
block[1] = 0; /* mode "r" */
|
||||
monitor_stdin = do_AngelSWI (AngelSWI_Reason_Open, (void *) block);
|
||||
|
||||
block[0] = (int) ":tt";
|
||||
block[2] = 3; /* length of filename */
|
||||
block[1] = 4; /* mode "w" */
|
||||
monitor_stdout = do_AngelSWI (AngelSWI_Reason_Open, (void *) block);
|
||||
for (i = 0; i < MAX_OPEN_FILES; i ++)
|
||||
openfiles[i].handle = -1;
|
||||
|
||||
block[0] = (int) ":tt";
|
||||
block[2] = 3; /* length of filename */
|
||||
block[1] = 8; /* mode "a" */
|
||||
monitor_stderr = do_AngelSWI (AngelSWI_Reason_Open, (void *) block);
|
||||
if (_has_ext_stdout_stderr ())
|
||||
{
|
||||
block[0] = (int) ":tt";
|
||||
block[2] = 3; /* length of filename */
|
||||
block[1] = 4; /* mode "w" */
|
||||
monitor_stdout = do_AngelSWI (AngelSWI_Reason_Open, (void *) block);
|
||||
|
||||
block[0] = (int) ":tt";
|
||||
block[2] = 3; /* length of filename */
|
||||
block[1] = 8; /* mode "a" */
|
||||
monitor_stderr = do_AngelSWI (AngelSWI_Reason_Open, (void *) block);
|
||||
}
|
||||
#else
|
||||
int fh;
|
||||
const char * name;
|
||||
@ -174,34 +186,135 @@ initialise_monitor_handles (void)
|
||||
: "r0","r1");
|
||||
monitor_stdin = fh;
|
||||
|
||||
name = ":tt";
|
||||
asm ("mov r0,%2; mov r1, #4; swi %a1; mov %0, r0"
|
||||
: "=r"(fh)
|
||||
: "i" (SWI_Open),"r"(name)
|
||||
: "r0","r1");
|
||||
monitor_stdout = fh;
|
||||
if (_has_ext_stdout_stderr ())
|
||||
{
|
||||
name = ":tt";
|
||||
asm ("mov r0,%2; mov r1, #4; swi %a1; mov %0, r0"
|
||||
: "=r"(fh)
|
||||
: "i" (SWI_Open),"r"(name)
|
||||
: "r0","r1");
|
||||
monitor_stdout = fh;
|
||||
|
||||
name = ":tt";
|
||||
asm ("mov r0,%2; mov r1, #8; swi %a1; mov %0, r0"
|
||||
: "=r"(fh)
|
||||
: "i" (SWI_Open),"r"(name)
|
||||
: "r0","r1");
|
||||
monitor_stderr = fh;
|
||||
name = ":tt";
|
||||
asm ("mov r0,%2; mov r1, #8; swi %a1; mov %0, r0"
|
||||
: "=r"(fh)
|
||||
: "i" (SWI_Open),"r"(name)
|
||||
: "r0","r1");
|
||||
monitor_stderr = fh;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If we failed to open stderr, redirect to stdout. */
|
||||
if (monitor_stderr == -1)
|
||||
monitor_stderr = monitor_stdout;
|
||||
|
||||
for (i = 0; i < MAX_OPEN_FILES; i ++)
|
||||
openfiles[i].handle = -1;
|
||||
|
||||
openfiles[0].handle = monitor_stdin;
|
||||
openfiles[0].pos = 0;
|
||||
openfiles[1].handle = monitor_stdout;
|
||||
openfiles[1].pos = 0;
|
||||
openfiles[2].handle = monitor_stderr;
|
||||
openfiles[2].pos = 0;
|
||||
|
||||
if (_has_ext_stdout_stderr ())
|
||||
{
|
||||
openfiles[1].handle = monitor_stdout;
|
||||
openfiles[1].pos = 0;
|
||||
openfiles[2].handle = monitor_stderr;
|
||||
openfiles[2].pos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
_has_ext_exit_extended (void)
|
||||
{
|
||||
if (supports_ext_exit_extended < 0)
|
||||
{
|
||||
initialise_semihosting_exts ();
|
||||
}
|
||||
|
||||
return supports_ext_exit_extended;
|
||||
}
|
||||
|
||||
int
|
||||
_has_ext_stdout_stderr (void)
|
||||
{
|
||||
if (supports_ext_stdout_stderr < 0)
|
||||
{
|
||||
initialise_semihosting_exts ();
|
||||
}
|
||||
|
||||
return supports_ext_stdout_stderr;
|
||||
}
|
||||
|
||||
static void
|
||||
initialise_semihosting_exts (void)
|
||||
{
|
||||
supports_ext_exit_extended = 0;
|
||||
supports_ext_stdout_stderr = 1;
|
||||
|
||||
#if SEMIHOST_V2
|
||||
char features[1];
|
||||
if (_get_semihosting_exts (features, 0, 1) > 0)
|
||||
{
|
||||
supports_ext_exit_extended
|
||||
= features[0] & (1 << SH_EXT_EXIT_EXTENDED_BITNUM);
|
||||
supports_ext_stdout_stderr
|
||||
= features[0] & (1 << SH_EXT_STDOUT_STDERR_BITNUM);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
_get_semihosting_exts (char* features, int offset, int num)
|
||||
{
|
||||
int len;
|
||||
struct fdent *pfd;
|
||||
int fd = _open (":semihosting-features", O_RDONLY);
|
||||
memset (features, 0, num);
|
||||
|
||||
if (fd == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
pfd = findslot (fd);
|
||||
|
||||
#ifdef ARM_RDI_MONITOR
|
||||
len = checkerror (do_AngelSWI (AngelSWI_Reason_FLen, &pfd->handle));
|
||||
#else
|
||||
asm ("mov r0,%2; swi %a1; mov %0, r0"
|
||||
: "=r"(len)
|
||||
: "i" (SWI_Flen),"r"(pfd->handle)
|
||||
: "r0");
|
||||
#endif
|
||||
|
||||
if (len < NUM_SHFB_MAGIC
|
||||
|| num > (len - NUM_SHFB_MAGIC))
|
||||
{
|
||||
_close (fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
char buffer[NUM_SHFB_MAGIC];
|
||||
int n_read = _read (fd, buffer, NUM_SHFB_MAGIC);
|
||||
|
||||
if (n_read < NUM_SHFB_MAGIC
|
||||
|| buffer[0] != SHFB_MAGIC_0
|
||||
|| buffer[1] != SHFB_MAGIC_1
|
||||
|| buffer[2] != SHFB_MAGIC_2
|
||||
|| buffer[3] != SHFB_MAGIC_3)
|
||||
{
|
||||
_close (fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_lseek (fd, offset, SEEK_CUR) < 0)
|
||||
{
|
||||
_close (fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
n_read = _read (fd, features, num);
|
||||
|
||||
_close (fd);
|
||||
|
||||
return checkerror (n_read);
|
||||
}
|
||||
|
||||
static int
|
||||
|
Reference in New Issue
Block a user