]> git.ipfire.org Git - thirdparty/qemu.git/commitdiff
ui/console: default vc encoding to cp437 for machine < 11.1
authorMarc-André Lureau <marcandre.lureau@redhat.com>
Thu, 23 Apr 2026 11:41:22 +0000 (15:41 +0400)
committerMarc-André Lureau <marcandre.lureau@redhat.com>
Sat, 9 May 2026 06:24:33 +0000 (10:24 +0400)
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>
hw/core/machine.c
include/chardev/char.h
ui/console-vc.c
ui/dbus.c

index 1b661fd36aedc16c4996ebc1a07fb8081dd9121d..63baff859f3d34ab57095b4ef96c67fd958de2b6 100644 (file)
@@ -39,7 +39,9 @@
 #include "hw/acpi/generic_event_device.h"
 #include "qemu/audio.h"
 
-GlobalProperty hw_compat_11_0[] = {};
+GlobalProperty hw_compat_11_0[] = {
+    { "chardev-vc", "encoding", "cp437" },
+};
 const size_t hw_compat_11_0_len = G_N_ELEMENTS(hw_compat_11_0);
 
 GlobalProperty hw_compat_10_2[] = {
index f05e8dba0a914e5b9e7f6971a690594f9fa2332e..7377d8e60a084de9c1efdb55f42e7171973d60ce 100644 (file)
@@ -332,4 +332,23 @@ void resume_mux_open(void);
 char *qemu_chr_get_pty_name(Chardev *chr);
 char *qemu_chr_get_filename(Chardev *chr);
 
+#define CHARDEV_VC_ENCODING_PROPERTY_DEFINE(cast_func)          \
+static int get_encoding(Object *obj, Error **errp)              \
+{                                                               \
+    return cast_func(obj)->encoding;                            \
+}                                                               \
+                                                                \
+static void set_encoding(Object *obj, int value, Error **errp)  \
+{                                                               \
+    cast_func(obj)->encoding = value;                           \
+}
+
+static inline void chardev_vc_add_encoding_prop(ObjectClass *oc,
+    int (*get)(Object *, Error **),
+    void (*set)(Object *, int, Error **))
+{
+    object_class_property_add_enum(oc, "encoding", "ChardevVCEncoding",
+                                   &ChardevVCEncoding_lookup, get, set);
+}
+
 #endif
index 7bb6a483753dff46215b5e46254b65a461fb0952..fd7e6fb7b064ee8582cae168370b342b038c1698 100644 (file)
@@ -9,6 +9,7 @@
 #include "qemu/fifo8.h"
 #include "qemu/option.h"
 #include "qemu/queue.h"
+#include "qom/compat-properties.h"
 #include "ui/console.h"
 #include "ui/vgafont.h"
 
@@ -109,6 +110,7 @@ struct VCChardev {
     TextAttributes t_attrib; /* currently active text attributes */
     TextAttributes t_attrib_saved;
     int x_saved, y_saved;
+    ChardevVCEncoding encoding;
 };
 typedef struct VCChardev VCChardev;
 
@@ -1189,6 +1191,9 @@ static bool vc_chr_open(Chardev *chr, ChardevBackend *backend, Error **errp)
 
     s->chr = chr;
     drv->console = s;
+    if (vc->has_encoding) {
+        drv->encoding = vc->encoding;
+    }
 
     /* set current text attributes to default */
     drv->t_attrib = TEXT_ATTRIBUTES_DEFAULT;
@@ -1253,6 +1258,8 @@ static void vc_chr_parse(QemuOpts *opts, ChardevBackend *backend, Error **errp)
     }
 }
 
+CHARDEV_VC_ENCODING_PROPERTY_DEFINE(VC_CHARDEV)
+
 static void char_vc_class_init(ObjectClass *oc, const void *data)
 {
     ChardevClass *cc = CHARDEV_CLASS(oc);
@@ -1264,12 +1271,23 @@ static void char_vc_class_init(ObjectClass *oc, const void *data)
     cc->chr_set_echo = vc_chr_set_echo;
     cc->supports_size_opts = true;
     cc->supports_encoding_opts = true;
+
+    chardev_vc_add_encoding_prop(oc, get_encoding, set_encoding);
+}
+
+static void char_vc_init(Object *obj)
+{
+    VCChardev *vc = VC_CHARDEV(obj);
+
+    vc->encoding = CHARDEV_VC_ENCODING_UTF8;
 }
 
 static const TypeInfo char_vc_type_info = {
     .name = TYPE_CHARDEV_VC,
     .parent = TYPE_CHARDEV,
     .instance_size = sizeof(VCChardev),
+    .instance_init = char_vc_init,
+    .instance_post_init = object_apply_compat_props,
     .class_init = char_vc_class_init,
 };
 
index 721cc71d39b4933030115e72c4f6e14e3f5725c2..59b73e0aa946082aa00a31bcfe3564f6cc4c6f77 100644 (file)
--- a/ui/dbus.c
+++ b/ui/dbus.c
@@ -28,6 +28,7 @@
 #include "qemu/main-loop.h"
 #include "qemu/option.h"
 #include "qom/object_interfaces.h"
+#include "qapi-types-char.h"
 #include "system/system.h"
 #include "ui/dbus-module.h"
 #ifdef CONFIG_OPENGL
@@ -455,12 +456,20 @@ dbus_display_class_init(ObjectClass *oc, const void *data)
 
 #define TYPE_CHARDEV_VC "chardev-vc"
 
+typedef struct DBusVCChardev {
+    DBusChardev parent;
+
+    ChardevVCEncoding encoding;
+} DBusVCChardev;
+
 typedef struct DBusVCClass {
     DBusChardevClass parent_class;
 
     void (*parent_parse)(QemuOpts *opts, ChardevBackend *b, Error **errp);
 } DBusVCClass;
 
+DECLARE_INSTANCE_CHECKER(DBusVCChardev, DBUS_VC_CHARDEV,
+                         TYPE_CHARDEV_VC)
 DECLARE_CLASS_CHECKERS(DBusVCClass, DBUS_VC,
                        TYPE_CHARDEV_VC)
 
@@ -500,6 +509,23 @@ dbus_vc_parse(QemuOpts *opts, ChardevBackend *backend,
     }
 }
 
+CHARDEV_VC_ENCODING_PROPERTY_DEFINE(DBUS_VC_CHARDEV)
+
+static bool
+dbus_vc_open(Chardev *chr, ChardevBackend *backend, Error **errp)
+{
+    DBusVCChardev *vc = DBUS_VC_CHARDEV(chr);
+    ChardevClass *parent =
+        CHARDEV_CLASS(object_class_by_name(TYPE_CHARDEV_DBUS));
+    ChardevDBus *be = backend->u.dbus.data;
+
+    if (be->has_encoding) {
+        vc->encoding = be->encoding;
+    }
+
+    return parent->chr_open(chr, backend, errp);
+}
+
 static void
 dbus_vc_class_init(ObjectClass *oc, const void *data)
 {
@@ -508,12 +534,26 @@ dbus_vc_class_init(ObjectClass *oc, const void *data)
 
     klass->parent_parse = cc->chr_parse;
     cc->chr_parse = dbus_vc_parse;
+    cc->chr_open = dbus_vc_open;
     cc->supports_encoding_opts = true;
+
+    chardev_vc_add_encoding_prop(oc, get_encoding, set_encoding);
+}
+
+static void
+dbus_vc_init(Object *obj)
+{
+    DBusVCChardev *vc = DBUS_VC_CHARDEV(obj);
+
+    vc->encoding = CHARDEV_VC_ENCODING_UTF8;
 }
 
 static const TypeInfo dbus_vc_type_info = {
     .name = TYPE_CHARDEV_VC,
     .parent = TYPE_CHARDEV_DBUS,
+    .instance_size = sizeof(DBusVCChardev),
+    .instance_init = dbus_vc_init,
+    .instance_post_init = object_apply_compat_props,
     .class_size = sizeof(DBusVCClass),
     .class_init = dbus_vc_class_init,
 };