From 6c2f17a5e02198a0fd0cbc62dc07c9360b64b53f Mon Sep 17 00:00:00 2001 From: Tautvis Date: Tue, 1 Jul 2025 13:23:20 +0200 Subject: [PATCH 1/8] xf86vidmode: fix result copying in ProcVidModeGetMonitor() The monitor values (vendor and model) accidentally had been copied at the start of the payload, instead of being appended after the previously copied data, and also moving the wrong pointer, thus corrupting the reply and causing some clients to hang. Signed-off-by: Tautvis Signed-off-by: Enrico Weigelt, metux IT consult --- Xext/vidmode.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Xext/vidmode.c b/Xext/vidmode.c index f9bbf9830..a192cff29 100644 --- a/Xext/vidmode.c +++ b/Xext/vidmode.c @@ -1280,7 +1280,7 @@ ProcVidModeGetMonitor(ClientPtr client) + nHsync + nVrefresh + nVendorItems + nModelItems }; - const int buflen = nHsync * nVrefresh + nVendorItems + nModelItems; + const int buflen = nHsync + nVrefresh + nVendorItems + nModelItems; CARD32 *sendbuf = calloc(buflen, sizeof(CARD32)); if (!sendbuf) @@ -1302,22 +1302,22 @@ ProcVidModeGetMonitor(ClientPtr client) bufwalk++; } - memcpy(sendbuf, + memcpy(bufwalk, pVidMode->GetMonitorValue(pScreen, VIDMODE_MON_VENDOR, 0).ptr, vendorLength); - sendbuf += nVendorItems; + bufwalk += nVendorItems; - memcpy(sendbuf, + memcpy(bufwalk, pVidMode->GetMonitorValue(pScreen, VIDMODE_MON_MODEL, 0).ptr, modelLength); - sendbuf += nModelItems; + bufwalk += nModelItems; if (client->swapped) { swaps(&rep.sequenceNumber); swapl(&rep.length); } - WriteToClient(client, SIZEOF(xXF86VidModeGetMonitorReply), &rep); + WriteToClient(client, sizeof(xXF86VidModeGetMonitorReply), &rep); WriteToClient(client, buflen * sizeof(CARD32), sendbuf); free(sendbuf); From 3d266528a977de931f58a2f8d309e968bbc7a211 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Mon, 30 Jun 2025 13:44:54 +0300 Subject: [PATCH 2/8] kdrive: ephyr: use c99 struct initialization For better readability and robustness against future changes, it's better to use named struct initializers instead of array-like lists. Signed-off-by: stefan11111 Signed-off-by: Enrico Weigelt, metux IT consult --- hw/kdrive/ephyr/ephyr.c | 26 ++++++++++++-------------- hw/kdrive/ephyr/ephyrinit.c | 26 +++++++++++--------------- 2 files changed, 23 insertions(+), 29 deletions(-) diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c index 9b00ed11f..cdc22cecf 100644 --- a/hw/kdrive/ephyr/ephyr.c +++ b/hw/kdrive/ephyr/ephyr.c @@ -1435,12 +1435,11 @@ MouseFini(KdPointerInfo * pi) } KdPointerDriver EphyrMouseDriver = { - "ephyr", - MouseInit, - MouseEnable, - MouseDisable, - MouseFini, - NULL, + .name = "ephyr", + .Init = MouseInit, + .Enable = MouseEnable, + .Disable = MouseDisable, + .Fini = MouseFini, }; /* Keyboard */ @@ -1509,12 +1508,11 @@ EphyrKeyboardBell(KdKeyboardInfo * ki, int volume, int frequency, int duration) } KdKeyboardDriver EphyrKeyboardDriver = { - "ephyr", - EphyrKeyboardInit, - EphyrKeyboardEnable, - EphyrKeyboardLeds, - EphyrKeyboardBell, - EphyrKeyboardDisable, - EphyrKeyboardFini, - NULL, + .name = "ephyr", + .Init = EphyrKeyboardInit, + .Enable = EphyrKeyboardEnable, + .Leds = EphyrKeyboardLeds, + .Bell = EphyrKeyboardBell, + .Disable = EphyrKeyboardDisable, + .Fini = EphyrKeyboardFini, }; diff --git a/hw/kdrive/ephyr/ephyrinit.c b/hw/kdrive/ephyr/ephyrinit.c index ff0d5d0cc..fd5e73f82 100644 --- a/hw/kdrive/ephyr/ephyrinit.c +++ b/hw/kdrive/ephyr/ephyrinit.c @@ -390,23 +390,19 @@ OsVendorInit(void) } KdCardFuncs ephyrFuncs = { - ephyrCardInit, /* cardinit */ - ephyrScreenInitialize, /* scrinit */ - ephyrInitScreen, /* initScreen */ - ephyrFinishInitScreen, /* finishInitScreen */ - ephyrCreateResources, /* createRes */ - ephyrScreenFini, /* scrfini */ - ephyrCardFini, /* cardfini */ + .cardinit = ephyrCardInit, + .scrinit = ephyrScreenInitialize, + .initScreen = ephyrInitScreen, + .finishInitScreen = ephyrFinishInitScreen, + .createRes = ephyrCreateResources, - 0, /* initCursor */ + .scrfini = ephyrScreenFini, + .cardfini = ephyrCardFini, - 0, /* initAccel */ - 0, /* enableAccel */ - 0, /* disableAccel */ - 0, /* finiAccel */ + /* no cursor or accel funcs here */ - ephyrGetColors, /* getColors */ - ephyrPutColors, /* putColors */ + .getColors = ephyrGetColors, + .putColors = ephyrPutColors, - ephyrCloseScreen, /* closeScreen */ + .closeScreen = ephyrCloseScreen, }; From a4c3c9da4d2f0333f75637bb94cb103495ee1754 Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Tue, 1 Jul 2025 12:36:44 +0200 Subject: [PATCH 3/8] xf86bigfont: fix compiler warning on unused variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit > ../Xext/xf86bigfont.c: In function ‘SProcXF86BigfontQueryVersion’: > ../include/dix.h:65:12: warning: unused variable ‘stuff’ [-Wunused-variable] > 65 | type * stuff = (type *)client->requestBuffer; Signed-off-by: Enrico Weigelt, metux IT consult --- Xext/xf86bigfont.c | 1 - 1 file changed, 1 deletion(-) diff --git a/Xext/xf86bigfont.c b/Xext/xf86bigfont.c index 13ad79a98..fb62c463c 100644 --- a/Xext/xf86bigfont.c +++ b/Xext/xf86bigfont.c @@ -647,7 +647,6 @@ ProcXF86BigfontDispatch(ClientPtr client) static int _X_COLD SProcXF86BigfontQueryVersion(ClientPtr client) { - REQUEST(xXF86BigfontQueryVersionReq); return ProcXF86BigfontQueryVersion(client); } From 28e739e05b2725b7ddfec9e4515c85b221b7a636 Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Tue, 1 Jul 2025 12:42:18 +0200 Subject: [PATCH 4/8] xfree86: loadmod: locally scope the errtype variable In CheckVersion() the errtype variable is used in two separate scopes, but not globally, so it's cleaner to have it only in the scopes that are actually using it. Signed-off-by: Enrico Weigelt, metux IT consult --- hw/xfree86/loader/loadmod.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/xfree86/loader/loadmod.c b/hw/xfree86/loader/loadmod.c index be9335dd5..2cdf91fd2 100644 --- a/hw/xfree86/loader/loadmod.c +++ b/hw/xfree86/loader/loadmod.c @@ -417,7 +417,6 @@ CheckVersion(const char *module, XF86ModuleVersionInfo * data, { int vercode[4]; long ver = data->xf86version; - MessageType errtype; LogMessage(X_INFO, "Module %s: vendor=\"%s\"\n", data->modname ? data->modname : "UNKNOWN!", @@ -458,6 +457,7 @@ CheckVersion(const char *module, XF86ModuleVersionInfo * data, vermaj = GET_ABI_MAJOR(ver); vermin = GET_ABI_MINOR(ver); if (abimaj != vermaj) { + MessageType errtype; if (LoaderOptions & LDR_OPT_ABI_MISMATCH_NONFATAL) errtype = X_WARNING; else @@ -469,6 +469,7 @@ CheckVersion(const char *module, XF86ModuleVersionInfo * data, return FALSE; } else if (abimin > vermin) { + MessageType errtype; if (LoaderOptions & LDR_OPT_ABI_MISMATCH_NONFATAL) errtype = X_WARNING; else From c24372893bc69cec93cabb72d44cb4e5658f789f Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Thu, 26 Jun 2025 13:04:02 +0200 Subject: [PATCH 5/8] xfree86: compat: consolidate logging Consolidate the redundant warnings into generic functions. Signed-off-by: Enrico Weigelt, metux IT consult --- hw/xfree86/compat/README | 4 ++++ hw/xfree86/compat/clientexception.c | 9 +++------ hw/xfree86/compat/log.c | 10 ++++------ hw/xfree86/compat/meson.build | 1 + hw/xfree86/compat/nvidiabug.c | 31 +++++++++++++++++++++++++++++ hw/xfree86/compat/xf86_compat.h | 12 +++++++++++ 6 files changed, 55 insertions(+), 12 deletions(-) create mode 100644 hw/xfree86/compat/nvidiabug.c create mode 100644 hw/xfree86/compat/xf86_compat.h diff --git a/hw/xfree86/compat/README b/hw/xfree86/compat/README index 19af90339..fd8c3b0f7 100644 --- a/hw/xfree86/compat/README +++ b/hw/xfree86/compat/README @@ -1 +1,5 @@ special compat code for legacy drivers, namely Nvidia proprietary + +NVidia is lacking behind for at least a year and don't actually clean up +their spaghetti code. That's why we need to keep several special compat +functions to emulate prehistoric behaviour. diff --git a/hw/xfree86/compat/clientexception.c b/hw/xfree86/compat/clientexception.c index 6005f22c4..cabde3ff2 100644 --- a/hw/xfree86/compat/clientexception.c +++ b/hw/xfree86/compat/clientexception.c @@ -4,6 +4,8 @@ #include "dix/dix_priv.h" +#include "xf86_compat.h" + /* * this is specifically for NVidia proprietary driver: they're again lagging * behind a year, doing at least some minimal cleanup of their code base. @@ -13,12 +15,7 @@ _X_EXPORT void MarkClientException(ClientPtr pClient); void MarkClientException(ClientPtr pClient) { - LogMessageVerb(X_WARNING, 0, "Bogus driver calling DIX-internal function MarkClientException() !\n"); - LogMessageVerb(X_WARNING, 0, "External drivers really should never ever call this function.\n"); - LogMessageVerb(X_WARNING, 0, "Nor should they ever DIX-internal fields like ClientRec->noClientException\n"); - LogMessageVerb(X_WARNING, 0, "File a bug report to driver vendor or use a FOSS driver.\n"); - LogMessageVerb(X_WARNING, 0, "Proprietary drivers are inherently unstable, they just can't be done right.\n"); - LogMessageVerb(X_WARNING, 0, "And just don't buy Nvidia hardware, ever.\n"); + xf86NVidiaBugInternalFunc("MarkClientException()"); dixMarkClientException(pClient); } diff --git a/hw/xfree86/compat/log.c b/hw/xfree86/compat/log.c index 97f238071..64014e205 100644 --- a/hw/xfree86/compat/log.c +++ b/hw/xfree86/compat/log.c @@ -4,6 +4,8 @@ #include "include/os.h" +#include "xf86_compat.h" + #undef xf86Msg #undef xf86MsgVerb @@ -17,9 +19,7 @@ _X_EXPORT void xf86Msg(MessageType type, const char *format, ...) void xf86Msg(MessageType type, const char *format, ...) { - LogMessageVerb(X_WARNING, 0, "Outdated driver still using xf86Msg() !\n"); - LogMessageVerb(X_WARNING, 0, "File a bug report to driver vendor or use a FOSS driver.\n"); - LogMessageVerb(X_WARNING, 0, "Proprietary drivers are inherently unstable, they just can't be done right.\n"); + xf86NVidiaBugInternalFunc("xf86Msg()"); va_list ap; @@ -39,9 +39,7 @@ _X_EXPORT void xf86MsgVerb(MessageType type, int verb, const char *format, ...) void xf86MsgVerb(MessageType type, int verb, const char *format, ...) { - LogMessageVerb(X_WARNING, 0, "Outdated driver still using xf86MsgVerb() !\n"); - LogMessageVerb(X_WARNING, 0, "File a bug report to driver vendor or use a FOSS driver.\n"); - LogMessageVerb(X_WARNING, 0, "Proprietary drivers are inherently unstable, they just can't be done right.\n"); + xf86NVidiaBugInternalFunc("xf86MsgVerb()"); va_list ap; va_start(ap, format); diff --git a/hw/xfree86/compat/meson.build b/hw/xfree86/compat/meson.build index d863ab2d8..b3835efdc 100644 --- a/hw/xfree86/compat/meson.build +++ b/hw/xfree86/compat/meson.build @@ -1,6 +1,7 @@ srcs_xorg_compat = [ 'clientexception.c', 'log.c', + 'nvidiabug.c', 'ones.c', 'xf86Helper.c', ] diff --git a/hw/xfree86/compat/nvidiabug.c b/hw/xfree86/compat/nvidiabug.c new file mode 100644 index 000000000..7c2c138fc --- /dev/null +++ b/hw/xfree86/compat/nvidiabug.c @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: MIT OR X11 + * + * Copyright © 2024 Enrico Weigelt, metux IT consult + */ +#include + +#include "include/os.h" + +#include "xf86_compat.h" + +void xf86NVidiaBug(void) +{ + LogMessageVerb(X_WARNING, 0, "[DRIVER BUG] file a bug report to driver vendor or use a free Xlibre driver.\n"); + LogMessageVerb(X_WARNING, 0, "[DRIVER BUG] Proprietary drivers are inherently unstable, they just can't be done right.\n"); + LogMessageVerb(X_WARNING, 0, "[DRIVER BUG] For NVidia report here: https://forums.developer.nvidia.com/c/gpu-graphics/linux/148\n"); + LogMessageVerb(X_WARNING, 0, "[DRIVER BUG] And better don't buy NVidia HW until they've fixed their mess.\n"); +} + +void xf86NVidiaBugInternalFunc(const char* name) +{ + LogMessageVerb(X_WARNING, 0, "[DRIVER BUG] calling internal function: %s\n", name); + LogMessageVerb(X_WARNING, 0, "[DRIVER BUG] this function is not supposed to be by drivers ever\n"); + xf86NVidiaBug(); +} + +void xf86NVidiaBugObsoleteFunc(const char* name) +{ + LogMessageVerb(X_WARNING, 0, "[DRIVER BUG] calling obsolete function: %s\n", name); + LogMessageVerb(X_WARNING, 0, "[DRIVER BUG] this function is not supposed to be by drivers ever\n"); + xf86NVidiaBug(); +} diff --git a/hw/xfree86/compat/xf86_compat.h b/hw/xfree86/compat/xf86_compat.h new file mode 100644 index 000000000..34c46e819 --- /dev/null +++ b/hw/xfree86/compat/xf86_compat.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: MIT OR X11 + * + * Copyright © 2024 Enrico Weigelt, metux IT consult + */ +#ifndef __XFREE86_COMPAT_XF86_COMPAT_H +#define __XFREE86_COMPAT_XF86_COMPAT_H + +void xf86NVidiaBug(void); +void xf86NVidiaBugInternalFunc(const char* name); +void xf86NVidiaBugObsoleteFunc(const char* name); + +#endif /* __XFREE86_COMPAT_XF86_COMPAT_H */ From 4036b8c163379b8edd9b29c4e260953effd626bf Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 30 Jun 2025 10:10:32 +0200 Subject: [PATCH 6/8] os: log: vpnprintf(): ignore reverse justification modifier The only caller is libinput, and we don't really need it, just silencing bug message. Signed-off-by: Enrico Weigelt, metux IT consult --- os/log.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/os/log.c b/os/log.c index 60837b10d..c0ff0ee93 100644 --- a/os/log.c +++ b/os/log.c @@ -410,6 +410,10 @@ vpnprintf(char *string, int size_in, const char *f, va_list args) f_idx++; + /* silently ignore reverse justification */ + if (f[f_idx] == '-') + f_idx++; + /* silently swallow minimum field width */ if (f[f_idx] == '*') { f_idx++; From 18d0455e0138373d70c8a66077787e0db0d9970b Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Mon, 30 Jun 2025 13:50:11 +0300 Subject: [PATCH 7/8] kdrive: add KdOsInit Kdrive X servers used to do the OS-speciffic init part using KdOsInit. This was changed in modern Xorg because Xephyr is the only kdrive X server there, so there was no need to keep this generic. Since we want to eventually add Xfbdev, we need to add this back. Signed-off-by: stefan11111 --- hw/kdrive/src/kdrive.c | 21 +++++++++++++++++++++ hw/kdrive/src/kdrive.h | 15 +++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/hw/kdrive/src/kdrive.c b/hw/kdrive/src/kdrive.c index 36bda4153..4637bb6be 100644 --- a/hw/kdrive/src/kdrive.c +++ b/hw/kdrive/src/kdrive.c @@ -91,6 +91,14 @@ const char *kdGlobalXkbLayout = NULL; const char *kdGlobalXkbVariant = NULL; const char *kdGlobalXkbOptions = NULL; + +/* + * Carry arguments from InitOutput through driver initialization + * to KdScreenInit + */ + +KdOsFuncs *kdOsFuncs = NULL; + void KdDisableScreen(ScreenPtr pScreen) { @@ -517,6 +525,19 @@ KdProcessArgument(int argc, char **argv, int i) return 0; } +void +KdOsInit(KdOsFuncs * pOsFuncs) +{ + kdOsFuncs = pOsFuncs; + if (pOsFuncs) { + if (serverGeneration == 1) { + KdDoSwitchCmd("start"); + if (pOsFuncs->Init) + (*pOsFuncs->Init) (); + } + } +} + static Bool KdAllocatePrivates(ScreenPtr pScreen) { diff --git a/hw/kdrive/src/kdrive.h b/hw/kdrive/src/kdrive.h index a4b7576d0..7ce181f42 100644 --- a/hw/kdrive/src/kdrive.h +++ b/hw/kdrive/src/kdrive.h @@ -278,6 +278,16 @@ int KdAddConfigKeyboard(char *pointer); int KdAddKeyboard(KdKeyboardInfo * ki); void KdRemoveKeyboard(KdKeyboardInfo * ki); +typedef struct _KdOsFuncs { + int (*Init) (void); /* Only called when the X server is started, when serverGeneration == 1 */ + void (*Enable) (void); + Bool (*SpecialKey) (KeySym); + void (*Disable) (void); + void (*Fini) (void); + void (*pollEvents) (void); + void (*Bell) (int, int, int); +} KdOsFuncs; + typedef struct _KdPointerMatrix { int matrix[2][3]; } KdPointerMatrix; @@ -289,6 +299,8 @@ extern DevPrivateKeyRec kdScreenPrivateKeyRec; extern Bool kdEmulateMiddleButton; extern Bool kdDisableZaphod; +extern KdOsFuncs *kdOsFuncs; + #define KdGetScreenPriv(pScreen) ((KdPrivScreenPtr) \ dixLookupPrivate(&(pScreen)->devPrivates, kdScreenPrivateKey)) #define KdSetScreenPriv(pScreen,v) \ @@ -345,6 +357,9 @@ void int KdProcessArgument(int argc, char **argv, int i); +void + KdOsInit(KdOsFuncs * pOsFuncs); + void KdOsAddInputDrivers(void); From 01ba7a7f40997312256f79884db7ddef81ef43c8 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Mon, 30 Jun 2025 14:16:23 +0300 Subject: [PATCH 8/8] kdrive: ephyr: initialize OS specific callback vectors These will be used by subsequent commits for generic Kdrive functions calling back into the OS specific parts Signed-off-by: stefan11111 --- hw/kdrive/ephyr/ephyrinit.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/hw/kdrive/ephyr/ephyrinit.c b/hw/kdrive/ephyr/ephyrinit.c index fd5e73f82..f65cef052 100644 --- a/hw/kdrive/ephyr/ephyrinit.c +++ b/hw/kdrive/ephyr/ephyrinit.c @@ -370,6 +370,23 @@ ddxProcessArgument(int argc, char **argv, int i) return KdProcessArgument(argc, argv, i); } +static int +EphyrInit(void) +{ + /* + * make sure at least one screen + * has been added to the system. + */ + if (!KdCardInfoLast()) { + processScreenArg("640x480", NULL); + } + return hostx_init(); +} + +KdOsFuncs EphyrOsFuncs = { + .Init = EphyrInit, +}; + void OsVendorInit(void) { @@ -381,12 +398,7 @@ OsVendorInit(void) if (hostx_want_host_cursor()) ephyrFuncs.initCursor = &ephyrCursorInit; - if (serverGeneration == 1) { - if (!KdCardInfoLast()) { - processScreenArg("640x480", NULL); - } - hostx_init(); - } + KdOsInit(&EphyrOsFuncs); } KdCardFuncs ephyrFuncs = {