xref: /openbmc/qemu/chardev/char.c (revision 4305d482)
1 /*
2  * QEMU System Emulator
3  *
4  * Copyright (c) 2003-2008 Fabrice Bellard
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 
25 #include "qemu/osdep.h"
26 #include "qemu/cutils.h"
27 #include "monitor/monitor.h"
28 #include "sysemu/sysemu.h"
29 #include "qemu/config-file.h"
30 #include "qemu/error-report.h"
31 #include "qemu/qemu-print.h"
32 #include "chardev/char.h"
33 #include "qapi/error.h"
34 #include "qapi/qapi-commands-char.h"
35 #include "qapi/qmp/qerror.h"
36 #include "sysemu/replay.h"
37 #include "qemu/help_option.h"
38 #include "qemu/module.h"
39 #include "qemu/option.h"
40 #include "qemu/id.h"
41 
42 #include "chardev/char-mux.h"
43 
44 /***********************************************************/
45 /* character device */
46 
47 static Object *get_chardevs_root(void)
48 {
49     return container_get(object_get_root(), "/chardevs");
50 }
51 
52 static void chr_be_event(Chardev *s, int event)
53 {
54     CharBackend *be = s->be;
55 
56     if (!be || !be->chr_event) {
57         return;
58     }
59 
60     be->chr_event(be->opaque, event);
61 }
62 
63 void qemu_chr_be_event(Chardev *s, int event)
64 {
65     /* Keep track if the char device is open */
66     switch (event) {
67         case CHR_EVENT_OPENED:
68             s->be_open = 1;
69             break;
70         case CHR_EVENT_CLOSED:
71             s->be_open = 0;
72             break;
73     }
74 
75     CHARDEV_GET_CLASS(s)->chr_be_event(s, event);
76 }
77 
78 /* Not reporting errors from writing to logfile, as logs are
79  * defined to be "best effort" only */
80 static void qemu_chr_write_log(Chardev *s, const uint8_t *buf, size_t len)
81 {
82     size_t done = 0;
83     ssize_t ret;
84 
85     if (s->logfd < 0) {
86         return;
87     }
88 
89     while (done < len) {
90     retry:
91         ret = write(s->logfd, buf + done, len - done);
92         if (ret == -1 && errno == EAGAIN) {
93             g_usleep(100);
94             goto retry;
95         }
96 
97         if (ret <= 0) {
98             return;
99         }
100         done += ret;
101     }
102 }
103 
104 static int qemu_chr_write_buffer(Chardev *s,
105                                  const uint8_t *buf, int len,
106                                  int *offset, bool write_all)
107 {
108     ChardevClass *cc = CHARDEV_GET_CLASS(s);
109     int res = 0;
110     *offset = 0;
111 
112     qemu_mutex_lock(&s->chr_write_lock);
113     while (*offset < len) {
114     retry:
115         res = cc->chr_write(s, buf + *offset, len - *offset);
116         if (res < 0 && errno == EAGAIN && write_all) {
117             g_usleep(100);
118             goto retry;
119         }
120 
121         if (res <= 0) {
122             break;
123         }
124 
125         *offset += res;
126         if (!write_all) {
127             break;
128         }
129     }
130     if (*offset > 0) {
131         qemu_chr_write_log(s, buf, *offset);
132     }
133     qemu_mutex_unlock(&s->chr_write_lock);
134 
135     return res;
136 }
137 
138 int qemu_chr_write(Chardev *s, const uint8_t *buf, int len, bool write_all)
139 {
140     int offset = 0;
141     int res;
142 
143     if (qemu_chr_replay(s) && replay_mode == REPLAY_MODE_PLAY) {
144         replay_char_write_event_load(&res, &offset);
145         assert(offset <= len);
146         qemu_chr_write_buffer(s, buf, offset, &offset, true);
147         return res;
148     }
149 
150     res = qemu_chr_write_buffer(s, buf, len, &offset, write_all);
151 
152     if (qemu_chr_replay(s) && replay_mode == REPLAY_MODE_RECORD) {
153         replay_char_write_event_save(res, offset);
154     }
155 
156     if (res < 0) {
157         return res;
158     }
159     return offset;
160 }
161 
162 int qemu_chr_be_can_write(Chardev *s)
163 {
164     CharBackend *be = s->be;
165 
166     if (!be || !be->chr_can_read) {
167         return 0;
168     }
169 
170     return be->chr_can_read(be->opaque);
171 }
172 
173 void qemu_chr_be_write_impl(Chardev *s, uint8_t *buf, int len)
174 {
175     CharBackend *be = s->be;
176 
177     if (be && be->chr_read) {
178         be->chr_read(be->opaque, buf, len);
179     }
180 }
181 
182 void qemu_chr_be_write(Chardev *s, uint8_t *buf, int len)
183 {
184     if (qemu_chr_replay(s)) {
185         if (replay_mode == REPLAY_MODE_PLAY) {
186             return;
187         }
188         replay_chr_be_write(s, buf, len);
189     } else {
190         qemu_chr_be_write_impl(s, buf, len);
191     }
192 }
193 
194 void qemu_chr_be_update_read_handlers(Chardev *s,
195                                       GMainContext *context)
196 {
197     ChardevClass *cc = CHARDEV_GET_CLASS(s);
198 
199     assert(qemu_chr_has_feature(s, QEMU_CHAR_FEATURE_GCONTEXT)
200            || !context);
201     s->gcontext = context;
202     if (cc->chr_update_read_handler) {
203         cc->chr_update_read_handler(s);
204     }
205 }
206 
207 int qemu_chr_add_client(Chardev *s, int fd)
208 {
209     return CHARDEV_GET_CLASS(s)->chr_add_client ?
210         CHARDEV_GET_CLASS(s)->chr_add_client(s, fd) : -1;
211 }
212 
213 static void qemu_char_open(Chardev *chr, ChardevBackend *backend,
214                            bool *be_opened, Error **errp)
215 {
216     ChardevClass *cc = CHARDEV_GET_CLASS(chr);
217     /* Any ChardevCommon member would work */
218     ChardevCommon *common = backend ? backend->u.null.data : NULL;
219 
220     if (common && common->has_logfile) {
221         int flags = O_WRONLY | O_CREAT;
222         if (common->has_logappend &&
223             common->logappend) {
224             flags |= O_APPEND;
225         } else {
226             flags |= O_TRUNC;
227         }
228         chr->logfd = qemu_open(common->logfile, flags, 0666);
229         if (chr->logfd < 0) {
230             error_setg_errno(errp, errno,
231                              "Unable to open logfile %s",
232                              common->logfile);
233             return;
234         }
235     }
236 
237     if (cc->open) {
238         cc->open(chr, backend, be_opened, errp);
239     }
240 }
241 
242 static void char_init(Object *obj)
243 {
244     Chardev *chr = CHARDEV(obj);
245 
246     chr->logfd = -1;
247     qemu_mutex_init(&chr->chr_write_lock);
248 
249     /*
250      * Assume if chr_update_read_handler is implemented it will
251      * take the updated gcontext into account.
252      */
253     if (CHARDEV_GET_CLASS(chr)->chr_update_read_handler) {
254         qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_GCONTEXT);
255     }
256 
257 }
258 
259 static int null_chr_write(Chardev *chr, const uint8_t *buf, int len)
260 {
261     return len;
262 }
263 
264 static void char_class_init(ObjectClass *oc, void *data)
265 {
266     ChardevClass *cc = CHARDEV_CLASS(oc);
267 
268     cc->chr_write = null_chr_write;
269     cc->chr_be_event = chr_be_event;
270 }
271 
272 static void char_finalize(Object *obj)
273 {
274     Chardev *chr = CHARDEV(obj);
275 
276     if (chr->be) {
277         chr->be->chr = NULL;
278     }
279     g_free(chr->filename);
280     g_free(chr->label);
281     if (chr->logfd != -1) {
282         close(chr->logfd);
283     }
284     qemu_mutex_destroy(&chr->chr_write_lock);
285 }
286 
287 static const TypeInfo char_type_info = {
288     .name = TYPE_CHARDEV,
289     .parent = TYPE_OBJECT,
290     .instance_size = sizeof(Chardev),
291     .instance_init = char_init,
292     .instance_finalize = char_finalize,
293     .abstract = true,
294     .class_size = sizeof(ChardevClass),
295     .class_init = char_class_init,
296 };
297 
298 static int chardev_machine_done_notify_one(Object *child, void *opaque)
299 {
300     Chardev *chr = (Chardev *)child;
301     ChardevClass *class = CHARDEV_GET_CLASS(chr);
302 
303     if (class->chr_machine_done) {
304         return class->chr_machine_done(chr);
305     }
306 
307     return 0;
308 }
309 
310 static void chardev_machine_done_hook(Notifier *notifier, void *unused)
311 {
312     int ret = object_child_foreach(get_chardevs_root(),
313                                    chardev_machine_done_notify_one, NULL);
314 
315     if (ret) {
316         error_report("Failed to call chardev machine_done hooks");
317         exit(1);
318     }
319 }
320 
321 static Notifier chardev_machine_done_notify = {
322     .notify = chardev_machine_done_hook,
323 };
324 
325 static bool qemu_chr_is_busy(Chardev *s)
326 {
327     if (CHARDEV_IS_MUX(s)) {
328         MuxChardev *d = MUX_CHARDEV(s);
329         return d->mux_cnt >= 0;
330     } else {
331         return s->be != NULL;
332     }
333 }
334 
335 int qemu_chr_wait_connected(Chardev *chr, Error **errp)
336 {
337     ChardevClass *cc = CHARDEV_GET_CLASS(chr);
338 
339     if (cc->chr_wait_connected) {
340         return cc->chr_wait_connected(chr, errp);
341     }
342 
343     return 0;
344 }
345 
346 QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename,
347                                 bool permit_mux_mon)
348 {
349     char host[65], port[33], width[8], height[8];
350     int pos;
351     const char *p;
352     QemuOpts *opts;
353     Error *local_err = NULL;
354 
355     opts = qemu_opts_create(qemu_find_opts("chardev"), label, 1, &local_err);
356     if (local_err) {
357         error_report_err(local_err);
358         return NULL;
359     }
360 
361     if (strstart(filename, "mon:", &p)) {
362         if (!permit_mux_mon) {
363             error_report("mon: isn't supported in this context");
364             return NULL;
365         }
366         filename = p;
367         qemu_opt_set(opts, "mux", "on", &error_abort);
368         if (strcmp(filename, "stdio") == 0) {
369             /* Monitor is muxed to stdio: do not exit on Ctrl+C by default
370              * but pass it to the guest.  Handle this only for compat syntax,
371              * for -chardev syntax we have special option for this.
372              * This is what -nographic did, redirecting+muxing serial+monitor
373              * to stdio causing Ctrl+C to be passed to guest. */
374             qemu_opt_set(opts, "signal", "off", &error_abort);
375         }
376     }
377 
378     if (strcmp(filename, "null")    == 0 ||
379         strcmp(filename, "pty")     == 0 ||
380         strcmp(filename, "msmouse") == 0 ||
381         strcmp(filename, "wctablet") == 0 ||
382         strcmp(filename, "braille") == 0 ||
383         strcmp(filename, "testdev") == 0 ||
384         strcmp(filename, "stdio")   == 0) {
385         qemu_opt_set(opts, "backend", filename, &error_abort);
386         return opts;
387     }
388     if (strstart(filename, "vc", &p)) {
389         qemu_opt_set(opts, "backend", "vc", &error_abort);
390         if (*p == ':') {
391             if (sscanf(p+1, "%7[0-9]x%7[0-9]", width, height) == 2) {
392                 /* pixels */
393                 qemu_opt_set(opts, "width", width, &error_abort);
394                 qemu_opt_set(opts, "height", height, &error_abort);
395             } else if (sscanf(p+1, "%7[0-9]Cx%7[0-9]C", width, height) == 2) {
396                 /* chars */
397                 qemu_opt_set(opts, "cols", width, &error_abort);
398                 qemu_opt_set(opts, "rows", height, &error_abort);
399             } else {
400                 goto fail;
401             }
402         }
403         return opts;
404     }
405     if (strcmp(filename, "con:") == 0) {
406         qemu_opt_set(opts, "backend", "console", &error_abort);
407         return opts;
408     }
409     if (strstart(filename, "COM", NULL)) {
410         qemu_opt_set(opts, "backend", "serial", &error_abort);
411         qemu_opt_set(opts, "path", filename, &error_abort);
412         return opts;
413     }
414     if (strstart(filename, "file:", &p)) {
415         qemu_opt_set(opts, "backend", "file", &error_abort);
416         qemu_opt_set(opts, "path", p, &error_abort);
417         return opts;
418     }
419     if (strstart(filename, "pipe:", &p)) {
420         qemu_opt_set(opts, "backend", "pipe", &error_abort);
421         qemu_opt_set(opts, "path", p, &error_abort);
422         return opts;
423     }
424     if (strstart(filename, "tcp:", &p) ||
425         strstart(filename, "telnet:", &p) ||
426         strstart(filename, "tn3270:", &p) ||
427         strstart(filename, "websocket:", &p)) {
428         if (sscanf(p, "%64[^:]:%32[^,]%n", host, port, &pos) < 2) {
429             host[0] = 0;
430             if (sscanf(p, ":%32[^,]%n", port, &pos) < 1)
431                 goto fail;
432         }
433         qemu_opt_set(opts, "backend", "socket", &error_abort);
434         qemu_opt_set(opts, "host", host, &error_abort);
435         qemu_opt_set(opts, "port", port, &error_abort);
436         if (p[pos] == ',') {
437             qemu_opts_do_parse(opts, p+pos+1, NULL, &local_err);
438             if (local_err) {
439                 error_report_err(local_err);
440                 goto fail;
441             }
442         }
443         if (strstart(filename, "telnet:", &p)) {
444             qemu_opt_set(opts, "telnet", "on", &error_abort);
445         } else if (strstart(filename, "tn3270:", &p)) {
446             qemu_opt_set(opts, "tn3270", "on", &error_abort);
447         } else if (strstart(filename, "websocket:", &p)) {
448             qemu_opt_set(opts, "websocket", "on", &error_abort);
449         }
450         return opts;
451     }
452     if (strstart(filename, "udp:", &p)) {
453         qemu_opt_set(opts, "backend", "udp", &error_abort);
454         if (sscanf(p, "%64[^:]:%32[^@,]%n", host, port, &pos) < 2) {
455             host[0] = 0;
456             if (sscanf(p, ":%32[^@,]%n", port, &pos) < 1) {
457                 goto fail;
458             }
459         }
460         qemu_opt_set(opts, "host", host, &error_abort);
461         qemu_opt_set(opts, "port", port, &error_abort);
462         if (p[pos] == '@') {
463             p += pos + 1;
464             if (sscanf(p, "%64[^:]:%32[^,]%n", host, port, &pos) < 2) {
465                 host[0] = 0;
466                 if (sscanf(p, ":%32[^,]%n", port, &pos) < 1) {
467                     goto fail;
468                 }
469             }
470             qemu_opt_set(opts, "localaddr", host, &error_abort);
471             qemu_opt_set(opts, "localport", port, &error_abort);
472         }
473         return opts;
474     }
475     if (strstart(filename, "unix:", &p)) {
476         qemu_opt_set(opts, "backend", "socket", &error_abort);
477         qemu_opts_do_parse(opts, p, "path", &local_err);
478         if (local_err) {
479             error_report_err(local_err);
480             goto fail;
481         }
482         return opts;
483     }
484     if (strstart(filename, "/dev/parport", NULL) ||
485         strstart(filename, "/dev/ppi", NULL)) {
486         qemu_opt_set(opts, "backend", "parallel", &error_abort);
487         qemu_opt_set(opts, "path", filename, &error_abort);
488         return opts;
489     }
490     if (strstart(filename, "/dev/", NULL)) {
491         qemu_opt_set(opts, "backend", "serial", &error_abort);
492         qemu_opt_set(opts, "path", filename, &error_abort);
493         return opts;
494     }
495 
496     error_report("'%s' is not a valid char driver", filename);
497 
498 fail:
499     qemu_opts_del(opts);
500     return NULL;
501 }
502 
503 void qemu_chr_parse_common(QemuOpts *opts, ChardevCommon *backend)
504 {
505     const char *logfile = qemu_opt_get(opts, "logfile");
506 
507     backend->has_logfile = logfile != NULL;
508     backend->logfile = g_strdup(logfile);
509 
510     backend->has_logappend = true;
511     backend->logappend = qemu_opt_get_bool(opts, "logappend", false);
512 }
513 
514 static const ChardevClass *char_get_class(const char *driver, Error **errp)
515 {
516     ObjectClass *oc;
517     const ChardevClass *cc;
518     char *typename = g_strdup_printf("chardev-%s", driver);
519 
520     oc = object_class_by_name(typename);
521     g_free(typename);
522 
523     if (!object_class_dynamic_cast(oc, TYPE_CHARDEV)) {
524         error_setg(errp, "'%s' is not a valid char driver name", driver);
525         return NULL;
526     }
527 
528     if (object_class_is_abstract(oc)) {
529         error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "driver",
530                    "abstract device type");
531         return NULL;
532     }
533 
534     cc = CHARDEV_CLASS(oc);
535     if (cc->internal) {
536         error_setg(errp, "'%s' is not a valid char driver name", driver);
537         return NULL;
538     }
539 
540     return cc;
541 }
542 
543 static const struct ChardevAlias {
544     const char *typename;
545     const char *alias;
546 } chardev_alias_table[] = {
547 #ifdef HAVE_CHARDEV_PARPORT
548     { "parallel", "parport" },
549 #endif
550 #ifdef HAVE_CHARDEV_SERIAL
551     { "serial", "tty" },
552 #endif
553 };
554 
555 typedef struct ChadevClassFE {
556     void (*fn)(const char *name, void *opaque);
557     void *opaque;
558 } ChadevClassFE;
559 
560 static void
561 chardev_class_foreach(ObjectClass *klass, void *opaque)
562 {
563     ChadevClassFE *fe = opaque;
564 
565     assert(g_str_has_prefix(object_class_get_name(klass), "chardev-"));
566     if (CHARDEV_CLASS(klass)->internal) {
567         return;
568     }
569 
570     fe->fn(object_class_get_name(klass) + 8, fe->opaque);
571 }
572 
573 static void
574 chardev_name_foreach(void (*fn)(const char *name, void *opaque), void *opaque)
575 {
576     ChadevClassFE fe = { .fn = fn, .opaque = opaque };
577     int i;
578 
579     object_class_foreach(chardev_class_foreach, TYPE_CHARDEV, false, &fe);
580 
581     for (i = 0; i < (int)ARRAY_SIZE(chardev_alias_table); i++) {
582         fn(chardev_alias_table[i].alias, opaque);
583     }
584 }
585 
586 static void
587 help_string_append(const char *name, void *opaque)
588 {
589     GString *str = opaque;
590 
591     g_string_append_printf(str, "\n  %s", name);
592 }
593 
594 static const char *chardev_alias_translate(const char *name)
595 {
596     int i;
597     for (i = 0; i < (int)ARRAY_SIZE(chardev_alias_table); i++) {
598         if (g_strcmp0(chardev_alias_table[i].alias, name) == 0) {
599             return chardev_alias_table[i].typename;
600         }
601     }
602     return name;
603 }
604 
605 ChardevBackend *qemu_chr_parse_opts(QemuOpts *opts, Error **errp)
606 {
607     Error *local_err = NULL;
608     const ChardevClass *cc;
609     ChardevBackend *backend = NULL;
610     const char *name = chardev_alias_translate(qemu_opt_get(opts, "backend"));
611 
612     if (name == NULL) {
613         error_setg(errp, "chardev: \"%s\" missing backend",
614                    qemu_opts_id(opts));
615         return NULL;
616     }
617 
618     cc = char_get_class(name, errp);
619     if (cc == NULL) {
620         return NULL;
621     }
622 
623     backend = g_new0(ChardevBackend, 1);
624     backend->type = CHARDEV_BACKEND_KIND_NULL;
625 
626     if (cc->parse) {
627         cc->parse(opts, backend, &local_err);
628         if (local_err) {
629             error_propagate(errp, local_err);
630             qapi_free_ChardevBackend(backend);
631             return NULL;
632         }
633     } else {
634         ChardevCommon *ccom = g_new0(ChardevCommon, 1);
635         qemu_chr_parse_common(opts, ccom);
636         backend->u.null.data = ccom; /* Any ChardevCommon member would work */
637     }
638 
639     return backend;
640 }
641 
642 Chardev *qemu_chr_new_from_opts(QemuOpts *opts, GMainContext *context,
643                                 Error **errp)
644 {
645     const ChardevClass *cc;
646     Chardev *chr = NULL;
647     ChardevBackend *backend = NULL;
648     const char *name = chardev_alias_translate(qemu_opt_get(opts, "backend"));
649     const char *id = qemu_opts_id(opts);
650     char *bid = NULL;
651 
652     if (name && is_help_option(name)) {
653         GString *str = g_string_new("");
654 
655         chardev_name_foreach(help_string_append, str);
656 
657         qemu_printf("Available chardev backend types: %s\n", str->str);
658         g_string_free(str, true);
659         return NULL;
660     }
661 
662     if (id == NULL) {
663         error_setg(errp, "chardev: no id specified");
664         return NULL;
665     }
666 
667     backend = qemu_chr_parse_opts(opts, errp);
668     if (backend == NULL) {
669         return NULL;
670     }
671 
672     cc = char_get_class(name, errp);
673     if (cc == NULL) {
674         goto out;
675     }
676 
677     if (qemu_opt_get_bool(opts, "mux", 0)) {
678         bid = g_strdup_printf("%s-base", id);
679     }
680 
681     chr = qemu_chardev_new(bid ? bid : id,
682                            object_class_get_name(OBJECT_CLASS(cc)),
683                            backend, context, errp);
684 
685     if (chr == NULL) {
686         goto out;
687     }
688 
689     if (bid) {
690         Chardev *mux;
691         qapi_free_ChardevBackend(backend);
692         backend = g_new0(ChardevBackend, 1);
693         backend->type = CHARDEV_BACKEND_KIND_MUX;
694         backend->u.mux.data = g_new0(ChardevMux, 1);
695         backend->u.mux.data->chardev = g_strdup(bid);
696         mux = qemu_chardev_new(id, TYPE_CHARDEV_MUX, backend, context, errp);
697         if (mux == NULL) {
698             object_unparent(OBJECT(chr));
699             chr = NULL;
700             goto out;
701         }
702         chr = mux;
703     }
704 
705 out:
706     qapi_free_ChardevBackend(backend);
707     g_free(bid);
708     return chr;
709 }
710 
711 Chardev *qemu_chr_new_noreplay(const char *label, const char *filename,
712                                bool permit_mux_mon, GMainContext *context)
713 {
714     const char *p;
715     Chardev *chr;
716     QemuOpts *opts;
717     Error *err = NULL;
718 
719     if (strstart(filename, "chardev:", &p)) {
720         return qemu_chr_find(p);
721     }
722 
723     opts = qemu_chr_parse_compat(label, filename, permit_mux_mon);
724     if (!opts)
725         return NULL;
726 
727     chr = qemu_chr_new_from_opts(opts, context, &err);
728     if (!chr) {
729         error_report_err(err);
730         goto out;
731     }
732 
733     if (qemu_opt_get_bool(opts, "mux", 0)) {
734         assert(permit_mux_mon);
735         monitor_init_hmp(chr, true);
736     }
737 
738 out:
739     qemu_opts_del(opts);
740     return chr;
741 }
742 
743 static Chardev *qemu_chr_new_permit_mux_mon(const char *label,
744                                           const char *filename,
745                                           bool permit_mux_mon,
746                                           GMainContext *context)
747 {
748     Chardev *chr;
749     chr = qemu_chr_new_noreplay(label, filename, permit_mux_mon, context);
750     if (chr) {
751         if (replay_mode != REPLAY_MODE_NONE) {
752             qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_REPLAY);
753         }
754         if (qemu_chr_replay(chr) && CHARDEV_GET_CLASS(chr)->chr_ioctl) {
755             error_report("Replay: ioctl is not supported "
756                          "for serial devices yet");
757         }
758         replay_register_char_driver(chr);
759     }
760     return chr;
761 }
762 
763 Chardev *qemu_chr_new(const char *label, const char *filename,
764                       GMainContext *context)
765 {
766     return qemu_chr_new_permit_mux_mon(label, filename, false, context);
767 }
768 
769 Chardev *qemu_chr_new_mux_mon(const char *label, const char *filename,
770                               GMainContext *context)
771 {
772     return qemu_chr_new_permit_mux_mon(label, filename, true, context);
773 }
774 
775 static int qmp_query_chardev_foreach(Object *obj, void *data)
776 {
777     Chardev *chr = CHARDEV(obj);
778     ChardevInfoList **list = data;
779     ChardevInfoList *info = g_malloc0(sizeof(*info));
780 
781     info->value = g_malloc0(sizeof(*info->value));
782     info->value->label = g_strdup(chr->label);
783     info->value->filename = g_strdup(chr->filename);
784     info->value->frontend_open = chr->be && chr->be->fe_open;
785 
786     info->next = *list;
787     *list = info;
788 
789     return 0;
790 }
791 
792 ChardevInfoList *qmp_query_chardev(Error **errp)
793 {
794     ChardevInfoList *chr_list = NULL;
795 
796     object_child_foreach(get_chardevs_root(),
797                          qmp_query_chardev_foreach, &chr_list);
798 
799     return chr_list;
800 }
801 
802 static void
803 qmp_prepend_backend(const char *name, void *opaque)
804 {
805     ChardevBackendInfoList **list = opaque;
806     ChardevBackendInfoList *info = g_malloc0(sizeof(*info));
807 
808     info->value = g_malloc0(sizeof(*info->value));
809     info->value->name = g_strdup(name);
810     info->next = *list;
811     *list = info;
812 }
813 
814 ChardevBackendInfoList *qmp_query_chardev_backends(Error **errp)
815 {
816     ChardevBackendInfoList *backend_list = NULL;
817 
818     chardev_name_foreach(qmp_prepend_backend, &backend_list);
819 
820     return backend_list;
821 }
822 
823 Chardev *qemu_chr_find(const char *name)
824 {
825     Object *obj = object_resolve_path_component(get_chardevs_root(), name);
826 
827     return obj ? CHARDEV(obj) : NULL;
828 }
829 
830 QemuOptsList qemu_chardev_opts = {
831     .name = "chardev",
832     .implied_opt_name = "backend",
833     .head = QTAILQ_HEAD_INITIALIZER(qemu_chardev_opts.head),
834     .desc = {
835         {
836             .name = "backend",
837             .type = QEMU_OPT_STRING,
838         },{
839             .name = "path",
840             .type = QEMU_OPT_STRING,
841         },{
842             .name = "host",
843             .type = QEMU_OPT_STRING,
844         },{
845             .name = "port",
846             .type = QEMU_OPT_STRING,
847         },{
848             .name = "fd",
849             .type = QEMU_OPT_STRING,
850         },{
851             .name = "localaddr",
852             .type = QEMU_OPT_STRING,
853         },{
854             .name = "localport",
855             .type = QEMU_OPT_STRING,
856         },{
857             .name = "to",
858             .type = QEMU_OPT_NUMBER,
859         },{
860             .name = "ipv4",
861             .type = QEMU_OPT_BOOL,
862         },{
863             .name = "ipv6",
864             .type = QEMU_OPT_BOOL,
865         },{
866             .name = "wait",
867             .type = QEMU_OPT_BOOL,
868         },{
869             .name = "server",
870             .type = QEMU_OPT_BOOL,
871         },{
872             .name = "delay",
873             .type = QEMU_OPT_BOOL,
874         },{
875             .name = "reconnect",
876             .type = QEMU_OPT_NUMBER,
877         },{
878             .name = "telnet",
879             .type = QEMU_OPT_BOOL,
880         },{
881             .name = "tn3270",
882             .type = QEMU_OPT_BOOL,
883         },{
884             .name = "tls-creds",
885             .type = QEMU_OPT_STRING,
886         },{
887             .name = "tls-authz",
888             .type = QEMU_OPT_STRING,
889         },{
890             .name = "websocket",
891             .type = QEMU_OPT_BOOL,
892         },{
893             .name = "width",
894             .type = QEMU_OPT_NUMBER,
895         },{
896             .name = "height",
897             .type = QEMU_OPT_NUMBER,
898         },{
899             .name = "cols",
900             .type = QEMU_OPT_NUMBER,
901         },{
902             .name = "rows",
903             .type = QEMU_OPT_NUMBER,
904         },{
905             .name = "mux",
906             .type = QEMU_OPT_BOOL,
907         },{
908             .name = "signal",
909             .type = QEMU_OPT_BOOL,
910         },{
911             .name = "name",
912             .type = QEMU_OPT_STRING,
913         },{
914             .name = "debug",
915             .type = QEMU_OPT_NUMBER,
916         },{
917             .name = "size",
918             .type = QEMU_OPT_SIZE,
919         },{
920             .name = "chardev",
921             .type = QEMU_OPT_STRING,
922         },{
923             .name = "append",
924             .type = QEMU_OPT_BOOL,
925         },{
926             .name = "logfile",
927             .type = QEMU_OPT_STRING,
928         },{
929             .name = "logappend",
930             .type = QEMU_OPT_BOOL,
931         },
932         { /* end of list */ }
933     },
934 };
935 
936 bool qemu_chr_has_feature(Chardev *chr,
937                           ChardevFeature feature)
938 {
939     return test_bit(feature, chr->features);
940 }
941 
942 void qemu_chr_set_feature(Chardev *chr,
943                            ChardevFeature feature)
944 {
945     return set_bit(feature, chr->features);
946 }
947 
948 static Chardev *chardev_new(const char *id, const char *typename,
949                             ChardevBackend *backend,
950                             GMainContext *gcontext,
951                             Error **errp)
952 {
953     Object *obj;
954     Chardev *chr = NULL;
955     Error *local_err = NULL;
956     bool be_opened = true;
957 
958     assert(g_str_has_prefix(typename, "chardev-"));
959 
960     obj = object_new(typename);
961     chr = CHARDEV(obj);
962     chr->label = g_strdup(id);
963     chr->gcontext = gcontext;
964 
965     qemu_char_open(chr, backend, &be_opened, &local_err);
966     if (local_err) {
967         goto end;
968     }
969 
970     if (!chr->filename) {
971         chr->filename = g_strdup(typename + 8);
972     }
973     if (be_opened) {
974         qemu_chr_be_event(chr, CHR_EVENT_OPENED);
975     }
976 
977     if (id) {
978         object_property_add_child(get_chardevs_root(), id, obj, &local_err);
979         if (local_err) {
980             goto end;
981         }
982         object_unref(obj);
983     }
984 
985 end:
986     if (local_err) {
987         error_propagate(errp, local_err);
988         object_unref(obj);
989         return NULL;
990     }
991 
992     return chr;
993 }
994 
995 Chardev *qemu_chardev_new(const char *id, const char *typename,
996                           ChardevBackend *backend,
997                           GMainContext *gcontext,
998                           Error **errp)
999 {
1000     g_autofree char *genid = NULL;
1001 
1002     if (!id) {
1003         genid = id_generate(ID_CHR);
1004         id = genid;
1005     }
1006 
1007     return chardev_new(id, typename, backend, gcontext, errp);
1008 }
1009 
1010 ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
1011                                Error **errp)
1012 {
1013     const ChardevClass *cc;
1014     ChardevReturn *ret;
1015     Chardev *chr;
1016 
1017     cc = char_get_class(ChardevBackendKind_str(backend->type), errp);
1018     if (!cc) {
1019         return NULL;
1020     }
1021 
1022     chr = chardev_new(id, object_class_get_name(OBJECT_CLASS(cc)),
1023                       backend, NULL, errp);
1024     if (!chr) {
1025         return NULL;
1026     }
1027 
1028     ret = g_new0(ChardevReturn, 1);
1029     if (CHARDEV_IS_PTY(chr)) {
1030         ret->pty = g_strdup(chr->filename + 4);
1031         ret->has_pty = true;
1032     }
1033 
1034     return ret;
1035 }
1036 
1037 ChardevReturn *qmp_chardev_change(const char *id, ChardevBackend *backend,
1038                                   Error **errp)
1039 {
1040     CharBackend *be;
1041     const ChardevClass *cc;
1042     Chardev *chr, *chr_new;
1043     bool closed_sent = false;
1044     ChardevReturn *ret;
1045 
1046     chr = qemu_chr_find(id);
1047     if (!chr) {
1048         error_setg(errp, "Chardev '%s' does not exist", id);
1049         return NULL;
1050     }
1051 
1052     if (CHARDEV_IS_MUX(chr)) {
1053         error_setg(errp, "Mux device hotswap not supported yet");
1054         return NULL;
1055     }
1056 
1057     if (qemu_chr_replay(chr)) {
1058         error_setg(errp,
1059             "Chardev '%s' cannot be changed in record/replay mode", id);
1060         return NULL;
1061     }
1062 
1063     be = chr->be;
1064     if (!be) {
1065         /* easy case */
1066         object_unparent(OBJECT(chr));
1067         return qmp_chardev_add(id, backend, errp);
1068     }
1069 
1070     if (!be->chr_be_change) {
1071         error_setg(errp, "Chardev user does not support chardev hotswap");
1072         return NULL;
1073     }
1074 
1075     cc = char_get_class(ChardevBackendKind_str(backend->type), errp);
1076     if (!cc) {
1077         return NULL;
1078     }
1079 
1080     chr_new = chardev_new(NULL, object_class_get_name(OBJECT_CLASS(cc)),
1081                           backend, chr->gcontext, errp);
1082     if (!chr_new) {
1083         return NULL;
1084     }
1085     chr_new->label = g_strdup(id);
1086 
1087     if (chr->be_open && !chr_new->be_open) {
1088         qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
1089         closed_sent = true;
1090     }
1091 
1092     chr->be = NULL;
1093     qemu_chr_fe_init(be, chr_new, &error_abort);
1094 
1095     if (be->chr_be_change(be->opaque) < 0) {
1096         error_setg(errp, "Chardev '%s' change failed", chr_new->label);
1097         chr_new->be = NULL;
1098         qemu_chr_fe_init(be, chr, &error_abort);
1099         if (closed_sent) {
1100             qemu_chr_be_event(chr, CHR_EVENT_OPENED);
1101         }
1102         object_unref(OBJECT(chr_new));
1103         return NULL;
1104     }
1105 
1106     object_unparent(OBJECT(chr));
1107     object_property_add_child(get_chardevs_root(), chr_new->label,
1108                               OBJECT(chr_new), &error_abort);
1109     object_unref(OBJECT(chr_new));
1110 
1111     ret = g_new0(ChardevReturn, 1);
1112     if (CHARDEV_IS_PTY(chr_new)) {
1113         ret->pty = g_strdup(chr_new->filename + 4);
1114         ret->has_pty = true;
1115     }
1116 
1117     return ret;
1118 }
1119 
1120 void qmp_chardev_remove(const char *id, Error **errp)
1121 {
1122     Chardev *chr;
1123 
1124     chr = qemu_chr_find(id);
1125     if (chr == NULL) {
1126         error_setg(errp, "Chardev '%s' not found", id);
1127         return;
1128     }
1129     if (qemu_chr_is_busy(chr)) {
1130         error_setg(errp, "Chardev '%s' is busy", id);
1131         return;
1132     }
1133     if (qemu_chr_replay(chr)) {
1134         error_setg(errp,
1135             "Chardev '%s' cannot be unplugged in record/replay mode", id);
1136         return;
1137     }
1138     object_unparent(OBJECT(chr));
1139 }
1140 
1141 void qmp_chardev_send_break(const char *id, Error **errp)
1142 {
1143     Chardev *chr;
1144 
1145     chr = qemu_chr_find(id);
1146     if (chr == NULL) {
1147         error_setg(errp, "Chardev '%s' not found", id);
1148         return;
1149     }
1150     qemu_chr_be_event(chr, CHR_EVENT_BREAK);
1151 }
1152 
1153 /*
1154  * Add a timeout callback for the chardev (in milliseconds), return
1155  * the GSource object created. Please use this to add timeout hook for
1156  * chardev instead of g_timeout_add() and g_timeout_add_seconds(), to
1157  * make sure the gcontext that the task bound to is correct.
1158  */
1159 GSource *qemu_chr_timeout_add_ms(Chardev *chr, guint ms,
1160                                  GSourceFunc func, void *private)
1161 {
1162     GSource *source = g_timeout_source_new(ms);
1163 
1164     assert(func);
1165     g_source_set_callback(source, func, private, NULL);
1166     g_source_attach(source, chr->gcontext);
1167 
1168     return source;
1169 }
1170 
1171 void qemu_chr_cleanup(void)
1172 {
1173     object_unparent(get_chardevs_root());
1174 }
1175 
1176 static void register_types(void)
1177 {
1178     type_register_static(&char_type_info);
1179 
1180     /* this must be done after machine init, since we register FEs with muxes
1181      * as part of realize functions like serial_isa_realizefn when -nographic
1182      * is specified
1183      */
1184     qemu_add_machine_init_done_notifier(&chardev_machine_done_notify);
1185 }
1186 
1187 type_init(register_types);
1188