semihosting: Split out guestfd.c
In arm-compat-semi.c, we have more advanced treatment of guest file descriptors than we do in other implementations. Split out GuestFD and related functions to a new file so that they can be shared. Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
3d5e2b4f26
commit
1c6ff7205b
@ -2,4 +2,5 @@ TARGET_ARCH=aarch64
|
|||||||
TARGET_BASE_ARCH=arm
|
TARGET_BASE_ARCH=arm
|
||||||
TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml
|
TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml
|
||||||
TARGET_HAS_BFLT=y
|
TARGET_HAS_BFLT=y
|
||||||
|
CONFIG_SEMIHOSTING=y
|
||||||
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
|
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
|
||||||
|
@ -3,4 +3,5 @@ TARGET_BASE_ARCH=arm
|
|||||||
TARGET_BIG_ENDIAN=y
|
TARGET_BIG_ENDIAN=y
|
||||||
TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml
|
TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml
|
||||||
TARGET_HAS_BFLT=y
|
TARGET_HAS_BFLT=y
|
||||||
|
CONFIG_SEMIHOSTING=y
|
||||||
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
|
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
|
||||||
|
@ -3,4 +3,5 @@ TARGET_SYSTBL_ABI=common,oabi
|
|||||||
TARGET_SYSTBL=syscall.tbl
|
TARGET_SYSTBL=syscall.tbl
|
||||||
TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml gdb-xml/arm-m-profile-mve.xml
|
TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml gdb-xml/arm-m-profile-mve.xml
|
||||||
TARGET_HAS_BFLT=y
|
TARGET_HAS_BFLT=y
|
||||||
|
CONFIG_SEMIHOSTING=y
|
||||||
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
|
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
|
||||||
|
@ -4,4 +4,5 @@ TARGET_SYSTBL=syscall.tbl
|
|||||||
TARGET_BIG_ENDIAN=y
|
TARGET_BIG_ENDIAN=y
|
||||||
TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml gdb-xml/arm-m-profile-mve.xml
|
TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml gdb-xml/arm-m-profile-mve.xml
|
||||||
TARGET_HAS_BFLT=y
|
TARGET_HAS_BFLT=y
|
||||||
|
CONFIG_SEMIHOSTING=y
|
||||||
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
|
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
|
||||||
|
@ -2,4 +2,5 @@ TARGET_ARCH=riscv32
|
|||||||
TARGET_BASE_ARCH=riscv
|
TARGET_BASE_ARCH=riscv
|
||||||
TARGET_ABI_DIR=riscv
|
TARGET_ABI_DIR=riscv
|
||||||
TARGET_XML_FILES= gdb-xml/riscv-32bit-cpu.xml gdb-xml/riscv-32bit-fpu.xml gdb-xml/riscv-64bit-fpu.xml gdb-xml/riscv-32bit-virtual.xml
|
TARGET_XML_FILES= gdb-xml/riscv-32bit-cpu.xml gdb-xml/riscv-32bit-fpu.xml gdb-xml/riscv-64bit-fpu.xml gdb-xml/riscv-32bit-virtual.xml
|
||||||
|
CONFIG_SEMIHOSTING=y
|
||||||
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
|
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
|
||||||
|
@ -2,4 +2,5 @@ TARGET_ARCH=riscv64
|
|||||||
TARGET_BASE_ARCH=riscv
|
TARGET_BASE_ARCH=riscv
|
||||||
TARGET_ABI_DIR=riscv
|
TARGET_ABI_DIR=riscv
|
||||||
TARGET_XML_FILES= gdb-xml/riscv-64bit-cpu.xml gdb-xml/riscv-32bit-fpu.xml gdb-xml/riscv-64bit-fpu.xml gdb-xml/riscv-64bit-virtual.xml
|
TARGET_XML_FILES= gdb-xml/riscv-64bit-cpu.xml gdb-xml/riscv-32bit-fpu.xml gdb-xml/riscv-64bit-fpu.xml gdb-xml/riscv-64bit-virtual.xml
|
||||||
|
CONFIG_SEMIHOSTING=y
|
||||||
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
|
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
|
||||||
|
83
include/semihosting/guestfd.h
Normal file
83
include/semihosting/guestfd.h
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* Hosted file support for semihosting syscalls.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2005, 2007 CodeSourcery.
|
||||||
|
* Copyright (c) 2019 Linaro
|
||||||
|
* Copyright © 2020 by Keith Packard <keithp@keithp.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SEMIHOSTING_GUESTFD_H
|
||||||
|
#define SEMIHOSTING_GUESTFD_H
|
||||||
|
|
||||||
|
typedef enum GuestFDType {
|
||||||
|
GuestFDUnused = 0,
|
||||||
|
GuestFDHost = 1,
|
||||||
|
GuestFDGDB = 2,
|
||||||
|
GuestFDStatic = 3,
|
||||||
|
} GuestFDType;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Guest file descriptors are integer indexes into an array of
|
||||||
|
* these structures (we will dynamically resize as necessary).
|
||||||
|
*/
|
||||||
|
typedef struct GuestFD {
|
||||||
|
GuestFDType type;
|
||||||
|
union {
|
||||||
|
int hostfd;
|
||||||
|
struct {
|
||||||
|
const uint8_t *data;
|
||||||
|
size_t len;
|
||||||
|
size_t off;
|
||||||
|
} staticfile;
|
||||||
|
};
|
||||||
|
} GuestFD;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* alloc_guestfd:
|
||||||
|
*
|
||||||
|
* Allocate an unused GuestFD index. The associated guestfd index
|
||||||
|
* will still be GuestFDUnused until it is initialized.
|
||||||
|
*/
|
||||||
|
int alloc_guestfd(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dealloc_guestfd:
|
||||||
|
* @guestfd: GuestFD index
|
||||||
|
*
|
||||||
|
* Deallocate a GuestFD index. The associated GuestFD structure
|
||||||
|
* will be recycled for a subsequent allocation.
|
||||||
|
*/
|
||||||
|
void dealloc_guestfd(int guestfd);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get_guestfd:
|
||||||
|
* @guestfd: GuestFD index
|
||||||
|
*
|
||||||
|
* Return the GuestFD structure associated with an initialized @guestfd,
|
||||||
|
* or NULL if it has not been allocated, or hasn't been initialized.
|
||||||
|
*/
|
||||||
|
GuestFD *get_guestfd(int guestfd);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* associate_guestfd:
|
||||||
|
* @guestfd: GuestFD index
|
||||||
|
* @hostfd: host file descriptor
|
||||||
|
*
|
||||||
|
* Initialize the GuestFD for @guestfd to GuestFDHost using @hostfd.
|
||||||
|
*/
|
||||||
|
void associate_guestfd(int guestfd, int hostfd);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* staticfile_guestfd:
|
||||||
|
* @guestfd: GuestFD index
|
||||||
|
* @data: data to be read
|
||||||
|
* @len: length of @data
|
||||||
|
*
|
||||||
|
* Initialize the GuestFD for @guestfd to GuestFDStatic.
|
||||||
|
* The @len bytes at @data will be returned to the guest on reads.
|
||||||
|
*/
|
||||||
|
void staticfile_guestfd(int guestfd, const uint8_t *data, size_t len);
|
||||||
|
|
||||||
|
#endif /* SEMIHOSTING_GUESTFD_H */
|
@ -32,12 +32,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
|
|
||||||
#include "semihosting/semihost.h"
|
#include "semihosting/semihost.h"
|
||||||
#include "semihosting/console.h"
|
#include "semihosting/console.h"
|
||||||
#include "semihosting/common-semi.h"
|
#include "semihosting/common-semi.h"
|
||||||
|
#include "semihosting/guestfd.h"
|
||||||
#include "qemu/timer.h"
|
#include "qemu/timer.h"
|
||||||
#include "exec/gdbstub.h"
|
#include "exec/gdbstub.h"
|
||||||
|
|
||||||
#ifdef CONFIG_USER_ONLY
|
#ifdef CONFIG_USER_ONLY
|
||||||
#include "qemu.h"
|
#include "qemu.h"
|
||||||
|
|
||||||
@ -123,27 +124,6 @@ static int open_modeflags[12] = {
|
|||||||
O_RDWR | O_CREAT | O_APPEND | O_BINARY
|
O_RDWR | O_CREAT | O_APPEND | O_BINARY
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum GuestFDType {
|
|
||||||
GuestFDUnused = 0,
|
|
||||||
GuestFDHost = 1,
|
|
||||||
GuestFDGDB = 2,
|
|
||||||
GuestFDFeatureFile = 3,
|
|
||||||
} GuestFDType;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Guest file descriptors are integer indexes into an array of
|
|
||||||
* these structures (we will dynamically resize as necessary).
|
|
||||||
*/
|
|
||||||
typedef struct GuestFD {
|
|
||||||
GuestFDType type;
|
|
||||||
union {
|
|
||||||
int hostfd;
|
|
||||||
target_ulong featurefile_offset;
|
|
||||||
};
|
|
||||||
} GuestFD;
|
|
||||||
|
|
||||||
static GArray *guestfd_array;
|
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -268,98 +248,6 @@ common_semi_sys_exit_extended(CPUState *cs, int nr)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* Allocate a new guest file descriptor and return it; if we
|
|
||||||
* couldn't allocate a new fd then return -1.
|
|
||||||
* This is a fairly simplistic implementation because we don't
|
|
||||||
* expect that most semihosting guest programs will make very
|
|
||||||
* heavy use of opening and closing fds.
|
|
||||||
*/
|
|
||||||
static int alloc_guestfd(void)
|
|
||||||
{
|
|
||||||
guint i;
|
|
||||||
|
|
||||||
if (!guestfd_array) {
|
|
||||||
/* New entries zero-initialized, i.e. type GuestFDUnused */
|
|
||||||
guestfd_array = g_array_new(FALSE, TRUE, sizeof(GuestFD));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* SYS_OPEN should return nonzero handle on success. Start guestfd from 1 */
|
|
||||||
for (i = 1; i < guestfd_array->len; i++) {
|
|
||||||
GuestFD *gf = &g_array_index(guestfd_array, GuestFD, i);
|
|
||||||
|
|
||||||
if (gf->type == GuestFDUnused) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* All elements already in use: expand the array */
|
|
||||||
g_array_set_size(guestfd_array, i + 1);
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Look up the guestfd in the data structure; return NULL
|
|
||||||
* for out of bounds, but don't check whether the slot is unused.
|
|
||||||
* This is used internally by the other guestfd functions.
|
|
||||||
*/
|
|
||||||
static GuestFD *do_get_guestfd(int guestfd)
|
|
||||||
{
|
|
||||||
if (!guestfd_array) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (guestfd <= 0 || guestfd >= guestfd_array->len) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return &g_array_index(guestfd_array, GuestFD, guestfd);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Associate the specified guest fd (which must have been
|
|
||||||
* allocated via alloc_fd() and not previously used) with
|
|
||||||
* the specified host/gdb fd.
|
|
||||||
*/
|
|
||||||
static void associate_guestfd(int guestfd, int hostfd)
|
|
||||||
{
|
|
||||||
GuestFD *gf = do_get_guestfd(guestfd);
|
|
||||||
|
|
||||||
assert(gf);
|
|
||||||
gf->type = use_gdb_syscalls() ? GuestFDGDB : GuestFDHost;
|
|
||||||
gf->hostfd = hostfd;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Deallocate the specified guest file descriptor. This doesn't
|
|
||||||
* close the host fd, it merely undoes the work of alloc_fd().
|
|
||||||
*/
|
|
||||||
static void dealloc_guestfd(int guestfd)
|
|
||||||
{
|
|
||||||
GuestFD *gf = do_get_guestfd(guestfd);
|
|
||||||
|
|
||||||
assert(gf);
|
|
||||||
gf->type = GuestFDUnused;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Given a guest file descriptor, get the associated struct.
|
|
||||||
* If the fd is not valid, return NULL. This is the function
|
|
||||||
* used by the various semihosting calls to validate a handle
|
|
||||||
* from the guest.
|
|
||||||
* Note: calling alloc_guestfd() or dealloc_guestfd() will
|
|
||||||
* invalidate any GuestFD* obtained by calling this function.
|
|
||||||
*/
|
|
||||||
static GuestFD *get_guestfd(int guestfd)
|
|
||||||
{
|
|
||||||
GuestFD *gf = do_get_guestfd(guestfd);
|
|
||||||
|
|
||||||
if (!gf || gf->type == GuestFDUnused) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return gf;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The semihosting API has no concept of its errno being thread-safe,
|
* The semihosting API has no concept of its errno being thread-safe,
|
||||||
* as the API design predates SMP CPUs and was intended as a simple
|
* as the API design predates SMP CPUs and was intended as a simple
|
||||||
@ -665,22 +553,13 @@ static const uint8_t featurefile_data[] = {
|
|||||||
SH_EXT_EXIT_EXTENDED | SH_EXT_STDOUT_STDERR, /* Feature byte 0 */
|
SH_EXT_EXIT_EXTENDED | SH_EXT_STDOUT_STDERR, /* Feature byte 0 */
|
||||||
};
|
};
|
||||||
|
|
||||||
static void init_featurefile_guestfd(int guestfd)
|
static uint32_t staticfile_closefn(CPUState *cs, GuestFD *gf)
|
||||||
{
|
|
||||||
GuestFD *gf = do_get_guestfd(guestfd);
|
|
||||||
|
|
||||||
assert(gf);
|
|
||||||
gf->type = GuestFDFeatureFile;
|
|
||||||
gf->featurefile_offset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t featurefile_closefn(CPUState *cs, GuestFD *gf)
|
|
||||||
{
|
{
|
||||||
/* Nothing to do */
|
/* Nothing to do */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t featurefile_writefn(CPUState *cs, GuestFD *gf,
|
static uint32_t staticfile_writefn(CPUState *cs, GuestFD *gf,
|
||||||
target_ulong buf, uint32_t len)
|
target_ulong buf, uint32_t len)
|
||||||
{
|
{
|
||||||
/* This fd can never be open for writing */
|
/* This fd can never be open for writing */
|
||||||
@ -689,7 +568,7 @@ static uint32_t featurefile_writefn(CPUState *cs, GuestFD *gf,
|
|||||||
return set_swi_errno(cs, -1);
|
return set_swi_errno(cs, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t featurefile_readfn(CPUState *cs, GuestFD *gf,
|
static uint32_t staticfile_readfn(CPUState *cs, GuestFD *gf,
|
||||||
target_ulong buf, uint32_t len)
|
target_ulong buf, uint32_t len)
|
||||||
{
|
{
|
||||||
CPUArchState *env = cs->env_ptr;
|
CPUArchState *env = cs->env_ptr;
|
||||||
@ -703,11 +582,11 @@ static uint32_t featurefile_readfn(CPUState *cs, GuestFD *gf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
if (gf->featurefile_offset >= sizeof(featurefile_data)) {
|
if (gf->staticfile.off >= gf->staticfile.len) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
s[i] = featurefile_data[gf->featurefile_offset];
|
s[i] = gf->staticfile.data[gf->staticfile.off];
|
||||||
gf->featurefile_offset++;
|
gf->staticfile.off++;
|
||||||
}
|
}
|
||||||
|
|
||||||
unlock_user(s, buf, len);
|
unlock_user(s, buf, len);
|
||||||
@ -716,21 +595,21 @@ static uint32_t featurefile_readfn(CPUState *cs, GuestFD *gf,
|
|||||||
return len - i;
|
return len - i;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t featurefile_isattyfn(CPUState *cs, GuestFD *gf)
|
static uint32_t staticfile_isattyfn(CPUState *cs, GuestFD *gf)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t featurefile_seekfn(CPUState *cs, GuestFD *gf,
|
static uint32_t staticfile_seekfn(CPUState *cs, GuestFD *gf,
|
||||||
target_ulong offset)
|
target_ulong offset)
|
||||||
{
|
{
|
||||||
gf->featurefile_offset = offset;
|
gf->staticfile.off = offset;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t featurefile_flenfn(CPUState *cs, GuestFD *gf)
|
static uint32_t staticfile_flenfn(CPUState *cs, GuestFD *gf)
|
||||||
{
|
{
|
||||||
return sizeof(featurefile_data);
|
return gf->staticfile.len;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct GuestFDFunctions {
|
typedef struct GuestFDFunctions {
|
||||||
@ -759,13 +638,13 @@ static const GuestFDFunctions guestfd_fns[] = {
|
|||||||
.seekfn = gdb_seekfn,
|
.seekfn = gdb_seekfn,
|
||||||
.flenfn = gdb_flenfn,
|
.flenfn = gdb_flenfn,
|
||||||
},
|
},
|
||||||
[GuestFDFeatureFile] = {
|
[GuestFDStatic] = {
|
||||||
.closefn = featurefile_closefn,
|
.closefn = staticfile_closefn,
|
||||||
.writefn = featurefile_writefn,
|
.writefn = staticfile_writefn,
|
||||||
.readfn = featurefile_readfn,
|
.readfn = staticfile_readfn,
|
||||||
.isattyfn = featurefile_isattyfn,
|
.isattyfn = staticfile_isattyfn,
|
||||||
.seekfn = featurefile_seekfn,
|
.seekfn = staticfile_seekfn,
|
||||||
.flenfn = featurefile_flenfn,
|
.flenfn = staticfile_flenfn,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -886,7 +765,8 @@ target_ulong do_common_semihosting(CPUState *cs)
|
|||||||
errno = EACCES;
|
errno = EACCES;
|
||||||
return set_swi_errno(cs, -1);
|
return set_swi_errno(cs, -1);
|
||||||
}
|
}
|
||||||
init_featurefile_guestfd(guestfd);
|
staticfile_guestfd(guestfd, featurefile_data,
|
||||||
|
sizeof(featurefile_data));
|
||||||
return guestfd;
|
return guestfd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
118
semihosting/guestfd.c
Normal file
118
semihosting/guestfd.c
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
* Hosted file support for semihosting syscalls.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2005, 2007 CodeSourcery.
|
||||||
|
* Copyright (c) 2019 Linaro
|
||||||
|
* Copyright © 2020 by Keith Packard <keithp@keithp.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "exec/gdbstub.h"
|
||||||
|
#include "semihosting/guestfd.h"
|
||||||
|
|
||||||
|
static GArray *guestfd_array;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate a new guest file descriptor and return it; if we
|
||||||
|
* couldn't allocate a new fd then return -1.
|
||||||
|
* This is a fairly simplistic implementation because we don't
|
||||||
|
* expect that most semihosting guest programs will make very
|
||||||
|
* heavy use of opening and closing fds.
|
||||||
|
*/
|
||||||
|
int alloc_guestfd(void)
|
||||||
|
{
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
if (!guestfd_array) {
|
||||||
|
/* New entries zero-initialized, i.e. type GuestFDUnused */
|
||||||
|
guestfd_array = g_array_new(FALSE, TRUE, sizeof(GuestFD));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SYS_OPEN should return nonzero handle on success. Start guestfd from 1 */
|
||||||
|
for (i = 1; i < guestfd_array->len; i++) {
|
||||||
|
GuestFD *gf = &g_array_index(guestfd_array, GuestFD, i);
|
||||||
|
|
||||||
|
if (gf->type == GuestFDUnused) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* All elements already in use: expand the array */
|
||||||
|
g_array_set_size(guestfd_array, i + 1);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look up the guestfd in the data structure; return NULL
|
||||||
|
* for out of bounds, but don't check whether the slot is unused.
|
||||||
|
* This is used internally by the other guestfd functions.
|
||||||
|
*/
|
||||||
|
static GuestFD *do_get_guestfd(int guestfd)
|
||||||
|
{
|
||||||
|
if (!guestfd_array) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (guestfd <= 0 || guestfd >= guestfd_array->len) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &g_array_index(guestfd_array, GuestFD, guestfd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given a guest file descriptor, get the associated struct.
|
||||||
|
* If the fd is not valid, return NULL. This is the function
|
||||||
|
* used by the various semihosting calls to validate a handle
|
||||||
|
* from the guest.
|
||||||
|
* Note: calling alloc_guestfd() or dealloc_guestfd() will
|
||||||
|
* invalidate any GuestFD* obtained by calling this function.
|
||||||
|
*/
|
||||||
|
GuestFD *get_guestfd(int guestfd)
|
||||||
|
{
|
||||||
|
GuestFD *gf = do_get_guestfd(guestfd);
|
||||||
|
|
||||||
|
if (!gf || gf->type == GuestFDUnused) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return gf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Associate the specified guest fd (which must have been
|
||||||
|
* allocated via alloc_fd() and not previously used) with
|
||||||
|
* the specified host/gdb fd.
|
||||||
|
*/
|
||||||
|
void associate_guestfd(int guestfd, int hostfd)
|
||||||
|
{
|
||||||
|
GuestFD *gf = do_get_guestfd(guestfd);
|
||||||
|
|
||||||
|
assert(gf);
|
||||||
|
gf->type = use_gdb_syscalls() ? GuestFDGDB : GuestFDHost;
|
||||||
|
gf->hostfd = hostfd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void staticfile_guestfd(int guestfd, const uint8_t *data, size_t len)
|
||||||
|
{
|
||||||
|
GuestFD *gf = do_get_guestfd(guestfd);
|
||||||
|
|
||||||
|
assert(gf);
|
||||||
|
gf->type = GuestFDStatic;
|
||||||
|
gf->staticfile.data = data;
|
||||||
|
gf->staticfile.len = len;
|
||||||
|
gf->staticfile.off = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Deallocate the specified guest file descriptor. This doesn't
|
||||||
|
* close the host fd, it merely undoes the work of alloc_fd().
|
||||||
|
*/
|
||||||
|
void dealloc_guestfd(int guestfd)
|
||||||
|
{
|
||||||
|
GuestFD *gf = do_get_guestfd(guestfd);
|
||||||
|
|
||||||
|
assert(gf);
|
||||||
|
gf->type = GuestFDUnused;
|
||||||
|
}
|
@ -1,3 +1,7 @@
|
|||||||
|
specific_ss.add(when: 'CONFIG_SEMIHOSTING', if_true: files(
|
||||||
|
'guestfd.c',
|
||||||
|
))
|
||||||
|
|
||||||
specific_ss.add(when: ['CONFIG_SEMIHOSTING', 'CONFIG_SOFTMMU'], if_true: files(
|
specific_ss.add(when: ['CONFIG_SEMIHOSTING', 'CONFIG_SOFTMMU'], if_true: files(
|
||||||
'config.c',
|
'config.c',
|
||||||
'console.c',
|
'console.c',
|
||||||
|
Loading…
Reference in New Issue
Block a user