@samitouri / QOSamiQemu / commits / 0b1f036753

ui/console: default vc encoding to cp437 for machine < 11.1

Add a QOM "encoding" enum property to some chardev-vc backends (console-vc & dbus - gtk and spice don't make use of it) so that the machine compat mechanism can override the default. For machine versions prior to 11.1, the charset defaults to cp437 (raw 8-bit VGA) instead of utf8, preserving the historical behaviour. The following commits are going to wire this to VT100 emulation code and an extra exported D-Bus property. Note that GTK libvte uses utf8 unconditionally, and Spice doesn't have a way to set the encoding, and typically just use libvte in client too. Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>

Marc-André Lureau committed Apr 23, 2026 at 15:41 UTC 0b1f0367533eb2dc91688f45f18e7da7890aed88
4 files changed +80 -1
hw/core/machine.c
+3 -1
@@ -39,7 +39,9 @@
39 #include "hw/acpi/generic_event_device.h"
40 #include "qemu/audio.h"
41
42 -GlobalProperty hw_compat_11_0[] = {};
42 +GlobalProperty hw_compat_11_0[] = {
43 + { "chardev-vc", "encoding", "cp437" },
44 +};
45 const size_t hw_compat_11_0_len = G_N_ELEMENTS(hw_compat_11_0);
46
47 GlobalProperty hw_compat_10_2[] = {
include/chardev/char.h
+19
@@ -332,4 +332,23 @@ void resume_mux_open(void);
332 char *qemu_chr_get_pty_name(Chardev *chr);
333 char *qemu_chr_get_filename(Chardev *chr);
334
335 +#define CHARDEV_VC_ENCODING_PROPERTY_DEFINE(cast_func) \
336 +static int get_encoding(Object *obj, Error **errp) \
337 +{ \
338 + return cast_func(obj)->encoding; \
339 +} \
340 + \
341 +static void set_encoding(Object *obj, int value, Error **errp) \
342 +{ \
343 + cast_func(obj)->encoding = value; \
344 +}
345 +
346 +static inline void chardev_vc_add_encoding_prop(ObjectClass *oc,
347 + int (*get)(Object *, Error **),
348 + void (*set)(Object *, int, Error **))
349 +{
350 + object_class_property_add_enum(oc, "encoding", "ChardevVCEncoding",
351 + &ChardevVCEncoding_lookup, get, set);
352 +}
353 +
354 #endif
ui/console-vc.c
+18
@@ -9,6 +9,7 @@
9 #include "qemu/fifo8.h"
10 #include "qemu/option.h"
11 #include "qemu/queue.h"
12 +#include "qom/compat-properties.h"
13 #include "ui/console.h"
14 #include "ui/vgafont.h"
15
@@ -109,6 +110,7 @@ struct VCChardev {
110 TextAttributes t_attrib; /* currently active text attributes */
111 TextAttributes t_attrib_saved;
112 int x_saved, y_saved;
113 + ChardevVCEncoding encoding;
114 };
115 typedef struct VCChardev VCChardev;
116
@@ -1189,6 +1191,9 @@ static bool vc_chr_open(Chardev *chr, ChardevBackend *backend, Error **errp)
1191
1192 s->chr = chr;
1193 drv->console = s;
1194 + if (vc->has_encoding) {
1195 + drv->encoding = vc->encoding;
1196 + }
1197
1198 /* set current text attributes to default */
1199 drv->t_attrib = TEXT_ATTRIBUTES_DEFAULT;
@@ -1253,6 +1258,8 @@ static void vc_chr_parse(QemuOpts *opts, ChardevBackend *backend, Error **errp)
1258 }
1259 }
1260
1261 +CHARDEV_VC_ENCODING_PROPERTY_DEFINE(VC_CHARDEV)
1262 +
1263 static void char_vc_class_init(ObjectClass *oc, const void *data)
1264 {
1265 ChardevClass *cc = CHARDEV_CLASS(oc);
@@ -1264,12 +1271,23 @@ static void char_vc_class_init(ObjectClass *oc, const void *data)
1271 cc->chr_set_echo = vc_chr_set_echo;
1272 cc->supports_size_opts = true;
1273 cc->supports_encoding_opts = true;
1274 +
1275 + chardev_vc_add_encoding_prop(oc, get_encoding, set_encoding);
1276 +}
1277 +
1278 +static void char_vc_init(Object *obj)
1279 +{
1280 + VCChardev *vc = VC_CHARDEV(obj);
1281 +
1282 + vc->encoding = CHARDEV_VC_ENCODING_UTF8;
1283 }
1284
1285 static const TypeInfo char_vc_type_info = {
1286 .name = TYPE_CHARDEV_VC,
1287 .parent = TYPE_CHARDEV,
1288 .instance_size = sizeof(VCChardev),
1289 + .instance_init = char_vc_init,
1290 + .instance_post_init = object_apply_compat_props,
1291 .class_init = char_vc_class_init,
1292 };
1293
ui/dbus.c
+40
@@ -28,6 +28,7 @@
28 #include "qemu/main-loop.h"
29 #include "qemu/option.h"
30 #include "qom/object_interfaces.h"
31 +#include "qapi-types-char.h"
32 #include "system/system.h"
33 #include "ui/dbus-module.h"
34 #ifdef CONFIG_OPENGL
@@ -455,12 +456,20 @@ dbus_display_class_init(ObjectClass *oc, const void *data)
456
457 #define TYPE_CHARDEV_VC "chardev-vc"
458
459 +typedef struct DBusVCChardev {
460 + DBusChardev parent;
461 +
462 + ChardevVCEncoding encoding;
463 +} DBusVCChardev;
464 +
465 typedef struct DBusVCClass {
466 DBusChardevClass parent_class;
467
468 void (*parent_parse)(QemuOpts *opts, ChardevBackend *b, Error **errp);
469 } DBusVCClass;
470
471 +DECLARE_INSTANCE_CHECKER(DBusVCChardev, DBUS_VC_CHARDEV,
472 + TYPE_CHARDEV_VC)
473 DECLARE_CLASS_CHECKERS(DBusVCClass, DBUS_VC,
474 TYPE_CHARDEV_VC)
475
@@ -500,6 +509,23 @@ dbus_vc_parse(QemuOpts *opts, ChardevBackend *backend,
509 }
510 }
511
512 +CHARDEV_VC_ENCODING_PROPERTY_DEFINE(DBUS_VC_CHARDEV)
513 +
514 +static bool
515 +dbus_vc_open(Chardev *chr, ChardevBackend *backend, Error **errp)
516 +{
517 + DBusVCChardev *vc = DBUS_VC_CHARDEV(chr);
518 + ChardevClass *parent =
519 + CHARDEV_CLASS(object_class_by_name(TYPE_CHARDEV_DBUS));
520 + ChardevDBus *be = backend->u.dbus.data;
521 +
522 + if (be->has_encoding) {
523 + vc->encoding = be->encoding;
524 + }
525 +
526 + return parent->chr_open(chr, backend, errp);
527 +}
528 +
529 static void
530 dbus_vc_class_init(ObjectClass *oc, const void *data)
531 {
@@ -508,12 +534,26 @@ dbus_vc_class_init(ObjectClass *oc, const void *data)
534
535 klass->parent_parse = cc->chr_parse;
536 cc->chr_parse = dbus_vc_parse;
537 + cc->chr_open = dbus_vc_open;
538 cc->supports_encoding_opts = true;
539 +
540 + chardev_vc_add_encoding_prop(oc, get_encoding, set_encoding);
541 +}
542 +
543 +static void
544 +dbus_vc_init(Object *obj)
545 +{
546 + DBusVCChardev *vc = DBUS_VC_CHARDEV(obj);
547 +
548 + vc->encoding = CHARDEV_VC_ENCODING_UTF8;
549 }
550
551 static const TypeInfo dbus_vc_type_info = {
552 .name = TYPE_CHARDEV_VC,
553 .parent = TYPE_CHARDEV_DBUS,
554 + .instance_size = sizeof(DBusVCChardev),
555 + .instance_init = dbus_vc_init,
556 + .instance_post_init = object_apply_compat_props,
557 .class_size = sizeof(DBusVCClass),
558 .class_init = dbus_vc_class_init,
559 };