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