softmmu/runstate.c: add RunStateTransition support form COLO to PRELAUNCH
[qemu/kevin.git] / semihosting / config.c
blobe171d4d6bc336968876621726cf4263db072a844
1 /*
2 * Semihosting configuration
4 * Copyright (c) 2015 Imagination Technologies
5 * Copyright (c) 2019 Linaro Ltd
7 * This controls the configuration of semihosting for all guest
8 * targets that support it. Architecture specific handling is handled
9 * in target/HW/HW-semi.c
11 * Semihosting is sightly strange in that it is also supported by some
12 * linux-user targets. However in that use case no configuration of
13 * the outputs and command lines is supported.
15 * The config module is common to all softmmu targets however as vl.c
16 * needs to link against the helpers.
18 * SPDX-License-Identifier: GPL-2.0-or-later
21 #include "qemu/osdep.h"
22 #include "qemu/option.h"
23 #include "qemu/config-file.h"
24 #include "qemu/error-report.h"
25 #include "semihosting/semihost.h"
26 #include "chardev/char.h"
28 QemuOptsList qemu_semihosting_config_opts = {
29 .name = "semihosting-config",
30 .merge_lists = true,
31 .implied_opt_name = "enable",
32 .head = QTAILQ_HEAD_INITIALIZER(qemu_semihosting_config_opts.head),
33 .desc = {
35 .name = "enable",
36 .type = QEMU_OPT_BOOL,
37 }, {
38 .name = "target",
39 .type = QEMU_OPT_STRING,
40 }, {
41 .name = "chardev",
42 .type = QEMU_OPT_STRING,
43 }, {
44 .name = "arg",
45 .type = QEMU_OPT_STRING,
47 { /* end of list */ }
51 typedef struct SemihostingConfig {
52 bool enabled;
53 SemihostingTarget target;
54 char **argv;
55 int argc;
56 const char *cmdline; /* concatenated argv */
57 } SemihostingConfig;
59 static SemihostingConfig semihosting;
60 static const char *semihost_chardev;
62 bool semihosting_enabled(void)
64 return semihosting.enabled;
67 SemihostingTarget semihosting_get_target(void)
69 return semihosting.target;
72 const char *semihosting_get_arg(int i)
74 if (i >= semihosting.argc) {
75 return NULL;
77 return semihosting.argv[i];
80 int semihosting_get_argc(void)
82 return semihosting.argc;
85 const char *semihosting_get_cmdline(void)
87 if (semihosting.cmdline == NULL && semihosting.argc > 0) {
88 semihosting.cmdline = g_strjoinv(" ", (gchar **)semihosting.argv);
90 return semihosting.cmdline;
93 static int add_semihosting_arg(void *opaque,
94 const char *name, const char *val,
95 Error **errp)
97 SemihostingConfig *s = opaque;
98 if (strcmp(name, "arg") == 0) {
99 s->argc++;
100 /* one extra element as g_strjoinv() expects NULL-terminated array */
101 s->argv = g_renew(char *, s->argv, s->argc + 1);
102 s->argv[s->argc - 1] = g_strdup(val);
103 s->argv[s->argc] = NULL;
105 return 0;
108 /* Use strings passed via -kernel/-append to initialize semihosting.argv[] */
109 void semihosting_arg_fallback(const char *file, const char *cmd)
111 char *cmd_token;
113 /* argv[0] */
114 add_semihosting_arg(&semihosting, "arg", file, NULL);
116 /* split -append and initialize argv[1..n] */
117 cmd_token = strtok(g_strdup(cmd), " ");
118 while (cmd_token) {
119 add_semihosting_arg(&semihosting, "arg", cmd_token, NULL);
120 cmd_token = strtok(NULL, " ");
124 void qemu_semihosting_enable(void)
126 semihosting.enabled = true;
127 semihosting.target = SEMIHOSTING_TARGET_AUTO;
130 int qemu_semihosting_config_options(const char *optarg)
132 QemuOptsList *opt_list = qemu_find_opts("semihosting-config");
133 QemuOpts *opts = qemu_opts_parse_noisily(opt_list, optarg, false);
135 semihosting.enabled = true;
137 if (opts != NULL) {
138 semihosting.enabled = qemu_opt_get_bool(opts, "enable",
139 true);
140 const char *target = qemu_opt_get(opts, "target");
141 /* setup of chardev is deferred until they are initialised */
142 semihost_chardev = qemu_opt_get(opts, "chardev");
143 if (target != NULL) {
144 if (strcmp("native", target) == 0) {
145 semihosting.target = SEMIHOSTING_TARGET_NATIVE;
146 } else if (strcmp("gdb", target) == 0) {
147 semihosting.target = SEMIHOSTING_TARGET_GDB;
148 } else if (strcmp("auto", target) == 0) {
149 semihosting.target = SEMIHOSTING_TARGET_AUTO;
150 } else {
151 error_report("unsupported semihosting-config %s",
152 optarg);
153 return 1;
155 } else {
156 semihosting.target = SEMIHOSTING_TARGET_AUTO;
158 /* Set semihosting argument count and vector */
159 qemu_opt_foreach(opts, add_semihosting_arg,
160 &semihosting, NULL);
161 } else {
162 error_report("unsupported semihosting-config %s", optarg);
163 return 1;
166 return 0;
169 /* We had to defer this until chardevs were created */
170 void qemu_semihosting_chardev_init(void)
172 Chardev *chr = NULL;
174 if (semihost_chardev) {
175 chr = qemu_chr_find(semihost_chardev);
176 if (chr == NULL) {
177 error_report("semihosting chardev '%s' not found",
178 semihost_chardev);
179 exit(1);
183 qemu_semihosting_console_init(chr);