mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-03 15:53:54 -06:00
semihosting: Move hw/semihosting/ -> semihosting/
With the exception of hw/core/, the hw/ directory only contains device models used in system emulation. Semihosting is also used by user emulation. As a generic feature, move it out of hw/ directory. Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Signed-off-by: Alex Bennée <alex.bennee@linaro.org> Message-Id: <20210226131356.3964782-3-f4bug@amsat.org> Message-Id: <20210305135451.15427-3-alex.bennee@linaro.org>
This commit is contained in:
parent
6b5fe13786
commit
8df9f0c3d7
11 changed files with 3 additions and 3 deletions
187
semihosting/config.c
Normal file
187
semihosting/config.c
Normal file
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
* Semihosting configuration
|
||||
*
|
||||
* Copyright (c) 2015 Imagination Technologies
|
||||
* Copyright (c) 2019 Linaro Ltd
|
||||
*
|
||||
* This controls the configuration of semihosting for all guest
|
||||
* targets that support it. Architecture specific handling is handled
|
||||
* in target/HW/HW-semi.c
|
||||
*
|
||||
* Semihosting is sightly strange in that it is also supported by some
|
||||
* linux-user targets. However in that use case no configuration of
|
||||
* the outputs and command lines is supported.
|
||||
*
|
||||
* The config module is common to all softmmu targets however as vl.c
|
||||
* needs to link against the helpers.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/option.h"
|
||||
#include "qemu/config-file.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "semihosting/semihost.h"
|
||||
#include "chardev/char.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
|
||||
QemuOptsList qemu_semihosting_config_opts = {
|
||||
.name = "semihosting-config",
|
||||
.implied_opt_name = "enable",
|
||||
.head = QTAILQ_HEAD_INITIALIZER(qemu_semihosting_config_opts.head),
|
||||
.desc = {
|
||||
{
|
||||
.name = "enable",
|
||||
.type = QEMU_OPT_BOOL,
|
||||
}, {
|
||||
.name = "target",
|
||||
.type = QEMU_OPT_STRING,
|
||||
}, {
|
||||
.name = "chardev",
|
||||
.type = QEMU_OPT_STRING,
|
||||
}, {
|
||||
.name = "arg",
|
||||
.type = QEMU_OPT_STRING,
|
||||
},
|
||||
{ /* end of list */ }
|
||||
},
|
||||
};
|
||||
|
||||
typedef struct SemihostingConfig {
|
||||
bool enabled;
|
||||
SemihostingTarget target;
|
||||
Chardev *chardev;
|
||||
const char **argv;
|
||||
int argc;
|
||||
const char *cmdline; /* concatenated argv */
|
||||
} SemihostingConfig;
|
||||
|
||||
static SemihostingConfig semihosting;
|
||||
static const char *semihost_chardev;
|
||||
|
||||
bool semihosting_enabled(void)
|
||||
{
|
||||
return semihosting.enabled;
|
||||
}
|
||||
|
||||
SemihostingTarget semihosting_get_target(void)
|
||||
{
|
||||
return semihosting.target;
|
||||
}
|
||||
|
||||
const char *semihosting_get_arg(int i)
|
||||
{
|
||||
if (i >= semihosting.argc) {
|
||||
return NULL;
|
||||
}
|
||||
return semihosting.argv[i];
|
||||
}
|
||||
|
||||
int semihosting_get_argc(void)
|
||||
{
|
||||
return semihosting.argc;
|
||||
}
|
||||
|
||||
const char *semihosting_get_cmdline(void)
|
||||
{
|
||||
if (semihosting.cmdline == NULL && semihosting.argc > 0) {
|
||||
semihosting.cmdline = g_strjoinv(" ", (gchar **)semihosting.argv);
|
||||
}
|
||||
return semihosting.cmdline;
|
||||
}
|
||||
|
||||
static int add_semihosting_arg(void *opaque,
|
||||
const char *name, const char *val,
|
||||
Error **errp)
|
||||
{
|
||||
SemihostingConfig *s = opaque;
|
||||
if (strcmp(name, "arg") == 0) {
|
||||
s->argc++;
|
||||
/* one extra element as g_strjoinv() expects NULL-terminated array */
|
||||
s->argv = g_realloc(s->argv, (s->argc + 1) * sizeof(void *));
|
||||
s->argv[s->argc - 1] = val;
|
||||
s->argv[s->argc] = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Use strings passed via -kernel/-append to initialize semihosting.argv[] */
|
||||
void semihosting_arg_fallback(const char *file, const char *cmd)
|
||||
{
|
||||
char *cmd_token;
|
||||
|
||||
/* argv[0] */
|
||||
add_semihosting_arg(&semihosting, "arg", file, NULL);
|
||||
|
||||
/* split -append and initialize argv[1..n] */
|
||||
cmd_token = strtok(g_strdup(cmd), " ");
|
||||
while (cmd_token) {
|
||||
add_semihosting_arg(&semihosting, "arg", cmd_token, NULL);
|
||||
cmd_token = strtok(NULL, " ");
|
||||
}
|
||||
}
|
||||
|
||||
Chardev *semihosting_get_chardev(void)
|
||||
{
|
||||
return semihosting.chardev;
|
||||
}
|
||||
|
||||
void qemu_semihosting_enable(void)
|
||||
{
|
||||
semihosting.enabled = true;
|
||||
semihosting.target = SEMIHOSTING_TARGET_AUTO;
|
||||
}
|
||||
|
||||
int qemu_semihosting_config_options(const char *optarg)
|
||||
{
|
||||
QemuOptsList *opt_list = qemu_find_opts("semihosting-config");
|
||||
QemuOpts *opts = qemu_opts_parse_noisily(opt_list, optarg, false);
|
||||
|
||||
semihosting.enabled = true;
|
||||
|
||||
if (opts != NULL) {
|
||||
semihosting.enabled = qemu_opt_get_bool(opts, "enable",
|
||||
true);
|
||||
const char *target = qemu_opt_get(opts, "target");
|
||||
/* setup of chardev is deferred until they are initialised */
|
||||
semihost_chardev = qemu_opt_get(opts, "chardev");
|
||||
if (target != NULL) {
|
||||
if (strcmp("native", target) == 0) {
|
||||
semihosting.target = SEMIHOSTING_TARGET_NATIVE;
|
||||
} else if (strcmp("gdb", target) == 0) {
|
||||
semihosting.target = SEMIHOSTING_TARGET_GDB;
|
||||
} else if (strcmp("auto", target) == 0) {
|
||||
semihosting.target = SEMIHOSTING_TARGET_AUTO;
|
||||
} else {
|
||||
error_report("unsupported semihosting-config %s",
|
||||
optarg);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
semihosting.target = SEMIHOSTING_TARGET_AUTO;
|
||||
}
|
||||
/* Set semihosting argument count and vector */
|
||||
qemu_opt_foreach(opts, add_semihosting_arg,
|
||||
&semihosting, NULL);
|
||||
} else {
|
||||
error_report("unsupported semihosting-config %s", optarg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void qemu_semihosting_connect_chardevs(void)
|
||||
{
|
||||
/* We had to defer this until chardevs were created */
|
||||
if (semihost_chardev) {
|
||||
Chardev *chr = qemu_chr_find(semihost_chardev);
|
||||
if (chr == NULL) {
|
||||
error_report("semihosting chardev '%s' not found",
|
||||
semihost_chardev);
|
||||
exit(1);
|
||||
}
|
||||
semihosting.chardev = chr;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue