common_semi_set_ret(cs, arg2 - ret);
}
+/*
+ * Convert from Posix ret+errno to Arm SYS_ISTTY return values.
+ * With gdbstub, err is only ever set for protocol errors to EIO.
+ */
+static void common_semi_istty_cb(CPUState *cs, target_ulong ret,
+ target_ulong err)
+{
+ if (err) {
+ ret = (err == ENOTTY ? 0 : -1);
+ }
+ common_semi_cb(cs, ret, err);
+}
+
/*
* SYS_SEEK returns 0 on success, not the resulting offset.
*/
* do the work and return the required return value to the guest
* via common_semi_cb.
*/
-typedef void sys_isattyfn(CPUState *cs, GuestFD *gf);
typedef void sys_flenfn(CPUState *cs, GuestFD *gf);
-static void host_isattyfn(CPUState *cs, GuestFD *gf)
-{
- common_semi_cb(cs, isatty(gf->hostfd), 0);
-}
-
static void host_flenfn(CPUState *cs, GuestFD *gf)
{
struct stat buf;
}
}
-static void gdb_isattyfn(CPUState *cs, GuestFD *gf)
-{
- gdb_do_syscall(common_semi_cb, "isatty,%x", gf->hostfd);
-}
-
static void gdb_flenfn(CPUState *cs, GuestFD *gf)
{
gdb_do_syscall(common_semi_flen_cb, "fstat,%x,%x",
SH_EXT_EXIT_EXTENDED | SH_EXT_STDOUT_STDERR, /* Feature byte 0 */
};
-static void staticfile_isattyfn(CPUState *cs, GuestFD *gf)
-{
- common_semi_cb(cs, 0, 0);
-}
-
static void staticfile_flenfn(CPUState *cs, GuestFD *gf)
{
common_semi_cb(cs, gf->staticfile.len, 0);
}
typedef struct GuestFDFunctions {
- sys_isattyfn *isattyfn;
sys_flenfn *flenfn;
} GuestFDFunctions;
static const GuestFDFunctions guestfd_fns[] = {
[GuestFDHost] = {
- .isattyfn = host_isattyfn,
.flenfn = host_flenfn,
},
[GuestFDGDB] = {
- .isattyfn = gdb_isattyfn,
.flenfn = gdb_flenfn,
},
[GuestFDStatic] = {
- .isattyfn = staticfile_isattyfn,
.flenfn = staticfile_flenfn,
},
};
case TARGET_SYS_ISTTY:
GET_ARG(0);
-
- gf = get_guestfd(arg0);
- if (!gf) {
- goto do_badf;
- }
- guestfd_fns[gf->type].isattyfn(cs, gf);
+ semihost_sys_isatty(cs, common_semi_istty_cb, arg0);
break;
case TARGET_SYS_SEEK:
(target_ulong)gf->hostfd, off, (target_ulong)gdb_whence);
}
+static void gdb_isatty(CPUState *cs, gdb_syscall_complete_cb complete,
+ GuestFD *gf)
+{
+ gdb_do_syscall(complete, "isatty,%x", (target_ulong)gf->hostfd);
+}
+
/*
* Host semihosting syscall implementations.
*/
complete(cs, ret, err);
}
+static void host_isatty(CPUState *cs, gdb_syscall_complete_cb complete,
+ GuestFD *gf)
+{
+ int ret = isatty(gf->hostfd);
+ complete(cs, ret, ret ? 0 : errno);
+}
+
/*
* Static file semihosting syscall implementations.
*/
g_assert_not_reached();
}
}
+
+void semihost_sys_isatty(CPUState *cs, gdb_syscall_complete_cb complete, int fd)
+{
+ GuestFD *gf = get_guestfd(fd);
+
+ if (!gf) {
+ complete(cs, 0, EBADF);
+ return;
+ }
+ switch (gf->type) {
+ case GuestFDGDB:
+ gdb_isatty(cs, complete, gf);
+ break;
+ case GuestFDHost:
+ host_isatty(cs, complete, gf);
+ break;
+ case GuestFDStatic:
+ complete(cs, 0, ENOTTY);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+}