mirror of
https://github.com/X11Libre/xserver.git
synced 2026-03-24 08:04:30 +00:00
fbdevhw: Only accept framebuffers that match the passed pci device in the pci probe
The pci probe was broken already, lots of pci devices were not detected as such. Since fixing it properly required a bit of extra code complexity, and those devices would be detected on the fallback probe, I didn't bother fixing it untill now. However, there is another problem created by this. The pci probe was accepting the device passed by the user without doing any checks on it. This means that in multi-card setups, fbdevhw might claim the wrong pci slot. Fixing this requires fixing the pci probe in order to try and determine whether the device passed by the user is the same as the pci device passed to the pci probe. This commit fixes the pci probe. If no device is passed by the user, the probe finds a pci framebuffer device. If a device is passed, the pci probe only return TRUE if the pci device passed to it is the same as the device passed by the user. Signed-off-by: stefan11111 <stefan11111@shitposting.expert>
This commit is contained in:
committed by
Enrico Weigelt
parent
c6d39ecc3f
commit
698d8a631a
@@ -3,8 +3,24 @@
|
||||
#include <xorg-config.h>
|
||||
#endif
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <glob.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#ifdef HAVE_SYS_SYSMACROS_H
|
||||
#include <sys/sysmacros.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_MKDEV_H
|
||||
#include <sys/mkdev.h> /* for minor() on Solaris */
|
||||
#endif
|
||||
|
||||
#include "xf86.h"
|
||||
#include "xf86Modes.h"
|
||||
@@ -39,14 +55,6 @@ _X_EXPORT XF86ModuleData fbdevhwModuleData = {
|
||||
.vers = &fbdevHWVersRec
|
||||
};
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* our private data, and two functions to allocate/free this */
|
||||
|
||||
@@ -289,43 +297,111 @@ fbdev_check_user_devices(int scrnIndex, const char* dev, char **namep)
|
||||
|
||||
/**
|
||||
* Try to find the framebuffer device for a given PCI device
|
||||
* This probe works in the following way:
|
||||
*
|
||||
* 1. If we have device passed by the user, we store it's minor number.
|
||||
* We then look through the framebuffers associated to the pPci pci device.
|
||||
* If we find one that has the same minor as the one passed by the user, we
|
||||
* open the filename passed by the user and return an fd to it.
|
||||
* Otherwise, we return -1;
|
||||
*
|
||||
* 2. If we don't have a device passed by the user,
|
||||
* we look through the framebuffers associated to the pPci pci device.
|
||||
* If we find one that is valid, we return an fd to it.
|
||||
* Otherwise, we return -1;
|
||||
*/
|
||||
static int
|
||||
fbdev_open_pci(int scrnIndex, struct pci_device *pPci, const char *device, char **namep)
|
||||
{
|
||||
char filename[256];
|
||||
int fd, i;
|
||||
/*
|
||||
* We really don't care what pci slot we claim when using the fbdev driver
|
||||
* However, due to how the probe interface is designed,
|
||||
* we have to be careful to not claim the wrong pci slot.
|
||||
*/
|
||||
char pattern[PATH_MAX];
|
||||
int fd;
|
||||
int fbdev_minor = -1;
|
||||
|
||||
fd = fbdev_check_user_devices(scrnIndex, device, namep);
|
||||
|
||||
int tfd;
|
||||
snprintf(pattern, sizeof(pattern),
|
||||
"/sys/bus/pci/devices/%04x:%02x:%02x.%d",
|
||||
pPci->domain, pPci->bus, pPci->dev, pPci->func);
|
||||
tfd = open(pattern, O_RDONLY);
|
||||
if (tfd == -1) {
|
||||
xf86DrvMsg(scrnIndex, X_WARNING,
|
||||
"Sysfs interface cannot be used."
|
||||
"Pci probe for framebuffer devices cannot function properly.\n");
|
||||
if (fd != -1) {
|
||||
xf86DrvMsg(scrnIndex, X_WARNING,
|
||||
"Using device: %s without further checks\n", device);
|
||||
return fd;
|
||||
}
|
||||
xf86DrvMsg(scrnIndex, X_ERROR, "Unable to find a valid framebuffer device\n");
|
||||
return -1;
|
||||
}
|
||||
close(tfd);
|
||||
|
||||
if (fd != -1) {
|
||||
/* fbdev was provided by the user and not guessed, skip pci check */
|
||||
return fd;
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
snprintf(filename, sizeof(filename),
|
||||
"/sys/bus/pci/devices/%04x:%02x:%02x.%d/graphics/fb%d",
|
||||
pPci->domain, pPci->bus, pPci->dev, pPci->func, i);
|
||||
|
||||
fd = open(filename, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
snprintf(filename, sizeof(filename),
|
||||
"/sys/bus/pci/devices/%04x:%02x:%02x.%d/graphics:fb%d",
|
||||
pPci->domain, pPci->bus, pPci->dev, pPci->func, i);
|
||||
fd = open(filename, O_RDONLY);
|
||||
struct stat res;
|
||||
if (fstat(fd, &res) == 0) {
|
||||
fbdev_minor = minor(res.st_rdev);
|
||||
}
|
||||
if (fd >= 0) {
|
||||
close(fd);
|
||||
snprintf(filename, sizeof(filename), "/dev/fb%d", i);
|
||||
|
||||
fd = fbdev_open_device(scrnIndex, filename, namep);
|
||||
if (fd != -1) {
|
||||
return fd;
|
||||
}
|
||||
close(fd);
|
||||
fd = -1;
|
||||
if (namep) {
|
||||
free(*namep);
|
||||
*namep = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#define FBDEV_CHECK_PCI_GLOB(glob_pattern) \
|
||||
do { \
|
||||
glob_t res; \
|
||||
snprintf(pattern, sizeof(pattern), \
|
||||
"/sys/bus/pci/devices/%04x:%02x:%02x.%d/" glob_pattern "/dev", \
|
||||
pPci->domain, pPci->bus, pPci->dev, pPci->func); \
|
||||
if (!glob(pattern, GLOB_NOSORT | GLOB_NOESCAPE, NULL, &res)) { \
|
||||
char filename[PATH_MAX] = "/dev/"; \
|
||||
for (int i = 0; i < res.gl_pathc; i++) { \
|
||||
int maj, min = -1; \
|
||||
FILE *f = fopen(res.gl_pathv[i], "r"); \
|
||||
if (f) { \
|
||||
fscanf(f, "%d:%d", &maj, &min); \
|
||||
fclose(f); \
|
||||
} \
|
||||
if (fbdev_minor != -1) { \
|
||||
if (fbdev_minor != min) { \
|
||||
continue; \
|
||||
} \
|
||||
/* We have determined the the device the user gave us matches this pci device */ \
|
||||
/* However, the name could be different than /dev/fb* */ \
|
||||
/* Since we already have a filename from the user, use that instead of guessing */ \
|
||||
return fbdev_check_user_devices(scrnIndex, device, namep); \
|
||||
} \
|
||||
char *src = strstr(res.gl_pathv[i], "graphics") + sizeof("graphics/") - 1; /* Has to match */ \
|
||||
char *dst = filename + sizeof("/dev/") - 1; \
|
||||
while (*src != '/') { \
|
||||
*dst++ = *src++; \
|
||||
} \
|
||||
*dst = '\0'; \
|
||||
fd = fbdev_open_device(scrnIndex, filename, namep); \
|
||||
if (fd != -1) { \
|
||||
return fd; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
globfree(&res); \
|
||||
} while(0)
|
||||
|
||||
FBDEV_CHECK_PCI_GLOB("graphics/fb*");
|
||||
FBDEV_CHECK_PCI_GLOB("graphics:fb*");
|
||||
FBDEV_CHECK_PCI_GLOB("*/graphics/fb*");
|
||||
FBDEV_CHECK_PCI_GLOB("*/graphics:fb*");
|
||||
|
||||
#undef FBDEV_CHECK_PCI_GLOB
|
||||
|
||||
xf86DrvMsg(scrnIndex, X_ERROR, "Unable to find a valid framebuffer device\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user