@samitouri / QOSamiQemu / commits / b389b87d3c

ui/console: add vc encoding=utf8/cp437 option

Expose a new "encoding" QemuOpt option. Add the corresponding QAPI type and properties. This is going to be wired in the following commits. Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>

Marc-André Lureau committed Apr 20, 2026 at 12:11 UTC b389b87d3c8accf21e7a77a65d2ed675499cc6fa
6 files changed +69 -4
chardev/char.c
+10
@@ -650,6 +650,13 @@ ChardevBackend *qemu_chr_parse_opts(QemuOpts *opts, Error **errp)
650 return NULL;
651 }
652 }
653 + if (!cc->supports_encoding_opts) {
654 + if (qemu_opt_get(opts, "encoding")) {
655 + error_setg(errp, "chardev '%s' does not support encoding option",
656 + qemu_opts_id(opts));
657 + return NULL;
658 + }
659 + }
660
661 backend = g_new0(ChardevBackend, 1);
662 backend->type = CHARDEV_BACKEND_KIND_NULL;
@@ -972,6 +979,9 @@ QemuOptsList qemu_chardev_opts = {
979 },{
980 .name = "rows",
981 .type = QEMU_OPT_NUMBER,
982 + },{
983 + .name = "encoding",
984 + .type = QEMU_OPT_STRING,
985 },{
986 .name = "mux",
987 .type = QEMU_OPT_BOOL,
include/chardev/char.h
+1
@@ -255,6 +255,7 @@ struct ChardevClass {
255 bool internal; /* TODO: eventually use TYPE_USER_CREATABLE */
256 bool supports_yank;
257 bool supports_size_opts;
258 + bool supports_encoding_opts;
259
260 /* parse command line options and populate QAPI @backend */
261 void (*chr_parse)(QemuOpts *opts, ChardevBackend *backend, Error **errp);
qapi/char.json
+28 -2
@@ -377,6 +377,24 @@
377 'base': 'ChardevCommon',
378 'if': 'CONFIG_SPICE' }
379
380 +##
381 +# @ChardevVCEncoding:
382 +#
383 +# Character encoding expected from the guest on a virtual console.
384 +#
385 +# @cp437: CP437 (8-bit Extended ASCII / VGA). Every byte maps
386 +# directly to a glyph; suitable for DOS or other guests that
387 +# output raw CP437.
388 +#
389 +# @utf8: UTF-8. Multi-byte sequences are decoded and then mapped
390 +# back to CP437 glyphs for display; unmappable codepoints are
391 +# shown as '?'. Suitable for modern Linux guests.
392 +#
393 +# Since: 11.1
394 +##
395 +{ 'enum': 'ChardevVCEncoding',
396 + 'data': [ 'cp437', 'utf8' ] }
397 +
398 ##
399 # @ChardevDBus:
400 #
@@ -384,10 +402,14 @@
402 #
403 # @name: name of the channel (following docs/spice-port-fqdn.txt)
404 #
405 +# @encoding: character encoding the guest is expected to use
406 +# (since 11.1)
407 +#
408 # Since: 7.0
409 ##
410 { 'struct': 'ChardevDBus',
390 - 'data': { 'name': 'str' },
411 + 'data': { 'name': 'str',
412 + '*encoding': 'ChardevVCEncoding' },
413 'base': 'ChardevCommon',
414 'if': 'CONFIG_DBUS_DISPLAY' }
415
@@ -404,6 +426,9 @@
426 #
427 # @rows: console height, in chars
428 #
429 +# @encoding: character encoding the guest is expected to use
430 +# (since 11.1)
431 +#
432 # .. note:: The options are only effective when the VNC or SDL
433 # graphical display backend is active. They are ignored with the
434 # GTK, Spice, VNC and D-Bus display backends.
@@ -414,7 +439,8 @@
439 'data': { '*width': 'int',
440 '*height': 'int',
441 '*cols': 'int',
417 - '*rows': 'int' },
442 + '*rows': 'int',
443 + '*encoding': 'ChardevVCEncoding' },
444 'base': 'ChardevCommon' }
445
446 ##
qemu-options.hx
+5 -2
@@ -4053,7 +4053,7 @@ DEF("chardev", HAS_ARG, QEMU_OPTION_chardev,
4053 " [,logfile=PATH][,logappend=on|off]\n"
4054 "-chardev msmouse,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
4055 "-chardev vc,id=id[[,width=width][,height=height]][[,cols=cols][,rows=rows]]\n"
4056 - " [,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
4056 + " [,mux=on|off][,logfile=PATH][,logappend=on|off][,encoding=ENCODING]\n"
4057 "-chardev ringbuf,id=id[,size=size][,logfile=PATH][,logappend=on|off]\n"
4058 "-chardev file,id=id,path=path[,input-path=input-file][,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
4059 "-chardev pipe,id=id,path=path[,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
@@ -4285,7 +4285,7 @@ The available backends are:
4285 Several frontend devices is not supported. Stacking of multiplexers
4286 and hub devices is not supported as well.
4287
4288 -``-chardev vc,id=id[[,width=width][,height=height]][[,cols=cols][,rows=rows]]``
4288 +``-chardev vc,id=id[[,width=width][,height=height]][[,cols=cols][,rows=rows]][,encoding=ENCODING]``
4289 Connect to a QEMU text console. The implementation and supported feature
4290 set depend on the selected display backend.
4291
@@ -4304,6 +4304,9 @@ The available backends are:
4304 ``cols`` and ``rows`` specify that the console be sized to fit a
4305 text console with the given dimensions.
4306
4307 + ``encoding`` specifies the character set expected from the guest:
4308 + ``utf8`` or ``cp437`` (8-bit Extended ASCII / VGA).
4309 +
4310 ``-chardev ringbuf,id=id[,size=size]``
4311 Create a ring buffer with fixed size ``size``. size must be a power
4312 of two and defaults to ``64K``.
ui/console-vc.c
+12
@@ -1211,6 +1211,7 @@ static bool vc_chr_open(Chardev *chr, ChardevBackend *backend, Error **errp)
1211 static void vc_chr_parse(QemuOpts *opts, ChardevBackend *backend, Error **errp)
1212 {
1213 int val;
1214 + const char *str;
1215 ChardevVC *vc;
1216
1217 backend->type = CHARDEV_BACKEND_KIND_VC;
@@ -1240,6 +1241,16 @@ static void vc_chr_parse(QemuOpts *opts, ChardevBackend *backend, Error **errp)
1241 vc->has_rows = true;
1242 vc->rows = val;
1243 }
1244 +
1245 + str = qemu_opt_get(opts, "encoding");
1246 + if (str) {
1247 + int cs = qapi_enum_parse(&ChardevVCEncoding_lookup, str, -1, errp);
1248 + if (cs < 0) {
1249 + return;
1250 + }
1251 + vc->has_encoding = true;
1252 + vc->encoding = cs;
1253 + }
1254 }
1255
1256 static void char_vc_class_init(ObjectClass *oc, const void *data)
@@ -1252,6 +1263,7 @@ static void char_vc_class_init(ObjectClass *oc, const void *data)
1263 cc->chr_accept_input = vc_chr_accept_input;
1264 cc->chr_set_echo = vc_chr_set_echo;
1265 cc->supports_size_opts = true;
1266 + cc->supports_encoding_opts = true;
1267 }
1268
1269 static const TypeInfo char_vc_type_info = {
ui/dbus.c
+13
@@ -471,6 +471,8 @@ dbus_vc_parse(QemuOpts *opts, ChardevBackend *backend,
471 DBusVCClass *klass = DBUS_VC_CLASS(object_class_by_name(TYPE_CHARDEV_VC));
472 const char *name = qemu_opt_get(opts, "name");
473 const char *id = qemu_opts_id(opts);
474 + const char *str;
475 + ChardevDBus *dbus;
476
477 if (name == NULL) {
478 if (g_str_has_prefix(id, "compat_monitor")) {
@@ -486,6 +488,16 @@ dbus_vc_parse(QemuOpts *opts, ChardevBackend *backend,
488 }
489
490 klass->parent_parse(opts, backend, errp);
491 + dbus = backend->u.dbus.data;
492 + str = qemu_opt_get(opts, "encoding");
493 + if (str) {
494 + int cs = qapi_enum_parse(&ChardevVCEncoding_lookup, str, -1, errp);
495 + if (cs < 0) {
496 + return;
497 + }
498 + dbus->has_encoding = true;
499 + dbus->encoding = cs;
500 + }
501 }
502
503 static void
@@ -496,6 +508,7 @@ dbus_vc_class_init(ObjectClass *oc, const void *data)
508
509 klass->parent_parse = cc->chr_parse;
510 cc->chr_parse = dbus_vc_parse;
511 + cc->supports_encoding_opts = true;
512 }
513
514 static const TypeInfo dbus_vc_type_info = {