qemu/semihosting/config.c
Stefan Hajnoczi 1527c6b6fa * util/log: re-allow switching away from stderr log file
* finish audio configuration rework
 * cleanup HVF stubs
 * remove more mentions of softmmu
 -----BEGIN PGP SIGNATURE-----
 
 iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmUi/kIUHHBib256aW5p
 QHJlZGhhdC5jb20ACgkQv/vSX3jHroOXWwf/YW16QMzqdAPVHYRf9NcCneRF16El
 t3lEod0q0sHhchPbh9e04aKbh+oBNeWu9sFyTl11Fwsi+DGmp/b28ziva75/4rfd
 h5N9aX/z2jwPqy93IwPDu3soKXCCgTK+ywtD/5GLQwBGqxs7W2xUEEb7eCnVefHa
 zwL3MOUqPICeqOnR1TNw9k3N3veF04D+rmchTwbAjAmx1f8EI+mK9VlGK9V8TUjP
 3HjpZYJluc0a92lR5VONJ7V25QfttsjLysTgpFwVAQPS6Frzatc/hWclfLYgw9vl
 2Irk83FV8gXPRl0XKNcqSDsv6h/yGP6TDFIB8QwRSRGBqIQi5aOlfBJzsQ==
 =qbm7
 -----END PGP SIGNATURE-----

Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging

* util/log: re-allow switching away from stderr log file
* finish audio configuration rework
* cleanup HVF stubs
* remove more mentions of softmmu

# -----BEGIN PGP SIGNATURE-----
#
# iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmUi/kIUHHBib256aW5p
# QHJlZGhhdC5jb20ACgkQv/vSX3jHroOXWwf/YW16QMzqdAPVHYRf9NcCneRF16El
# t3lEod0q0sHhchPbh9e04aKbh+oBNeWu9sFyTl11Fwsi+DGmp/b28ziva75/4rfd
# h5N9aX/z2jwPqy93IwPDu3soKXCCgTK+ywtD/5GLQwBGqxs7W2xUEEb7eCnVefHa
# zwL3MOUqPICeqOnR1TNw9k3N3veF04D+rmchTwbAjAmx1f8EI+mK9VlGK9V8TUjP
# 3HjpZYJluc0a92lR5VONJ7V25QfttsjLysTgpFwVAQPS6Frzatc/hWclfLYgw9vl
# 2Irk83FV8gXPRl0XKNcqSDsv6h/yGP6TDFIB8QwRSRGBqIQi5aOlfBJzsQ==
# =qbm7
# -----END PGP SIGNATURE-----
# gpg: Signature made Sun 08 Oct 2023 15:08:50 EDT
# gpg:                using RSA key F13338574B662389866C7682BFFBD25F78C7AE83
# gpg:                issuer "pbonzini@redhat.com"
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full]
# gpg:                 aka "Paolo Bonzini <pbonzini@redhat.com>" [full]
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4  E2F7 7E15 100C CD36 69B1
#      Subkey fingerprint: F133 3857 4B66 2389 866C  7682 BFFB D25F 78C7 AE83

* tag 'for-upstream' of https://gitlab.com/bonzini/qemu: (25 commits)
  audio, qtest: get rid of QEMU_AUDIO_DRV
  audio: reintroduce default audio backend for VNC
  audio: do not use first -audiodev as default audio device
  audio: extend -audio to allow creating a default backend
  audio: extract audio_define_default
  audio: disable default backends if -audio/-audiodev is used
  audio: error hints need a trailing \n
  cutils: squelch compiler warnings with custom paths
  configure: change $softmmu to $system
  system: Rename softmmu/ directory as system/
  meson: Rename target_softmmu_arch -> target_system_arch
  meson: Rename softmmu_mods -> system_mods
  target/i386: Rename i386_softmmu_kvm_ss -> i386_kvm_ss
  semihosting: Rename softmmu_FOO_user() -> uaccess_FOO_user()
  gdbstub: Rename 'softmmu' -> 'system'
  accel: Rename accel_softmmu* -> accel_system*
  tcg: Correct invalid mentions of 'softmmu' by 'system-mode'
  fuzz: Correct invalid mentions of 'softmmu' by 'system'
  cpu: Correct invalid mentions of 'softmmu' by 'system-mode'
  travis-ci: Correct invalid mentions of 'softmmu' by 'system'
  ...

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2023-10-09 10:11:18 -04:00

191 lines
5.4 KiB
C

/*
* 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 slightly 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 system 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"
QemuOptsList qemu_semihosting_config_opts = {
.name = "semihosting-config",
.merge_lists = true,
.implied_opt_name = "enable",
.head = QTAILQ_HEAD_INITIALIZER(qemu_semihosting_config_opts.head),
.desc = {
{
.name = "enable",
.type = QEMU_OPT_BOOL,
}, {
.name = "userspace",
.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;
bool userspace_enabled;
SemihostingTarget target;
char **argv;
int argc;
const char *cmdline; /* concatenated argv */
} SemihostingConfig;
static SemihostingConfig semihosting;
static const char *semihost_chardev;
bool semihosting_enabled(bool is_user)
{
return semihosting.enabled && (!is_user || semihosting.userspace_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_renew(char *, s->argv, s->argc + 1);
s->argv[s->argc - 1] = g_strdup(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, " ");
}
}
void qemu_semihosting_enable(void)
{
semihosting.enabled = true;
semihosting.target = SEMIHOSTING_TARGET_AUTO;
}
int qemu_semihosting_config_options(const char *optstr)
{
QemuOptsList *opt_list = qemu_find_opts("semihosting-config");
QemuOpts *opts = qemu_opts_parse_noisily(opt_list, optstr, false);
semihosting.enabled = true;
if (opts != NULL) {
semihosting.enabled = qemu_opt_get_bool(opts, "enable",
true);
semihosting.userspace_enabled = qemu_opt_get_bool(opts, "userspace",
false);
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",
optstr);
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", optstr);
return 1;
}
return 0;
}
/* We had to defer this until chardevs were created */
void qemu_semihosting_chardev_init(void)
{
Chardev *chr = NULL;
if (semihost_chardev) {
chr = qemu_chr_find(semihost_chardev);
if (chr == NULL) {
error_report("semihosting chardev '%s' not found",
semihost_chardev);
exit(1);
}
}
qemu_semihosting_console_init(chr);
}