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