diff options
author | Keith Packard <keithp@keithp.com> | 2018-01-18 18:07:29 -0800 |
---|---|---|
committer | Keith Packard <keithp@keithp.com> | 2018-03-01 15:33:52 -0800 |
commit | e0a204719bba01ba0b71e7c9f0c5c3eb02b6b08c (patch) | |
tree | c876655f13cf3b203a9eabbfd5302f6bf97f77c8 | |
parent | 2af0a50a4bb9be9f58681d417ceb9a7029caaf3b (diff) |
modesetting: Allow a DRM fd to be passed on command line with -masterfddrm-lease
This lets an application open a suitable DRM device and pass the file
descriptor to the mode setting driver through an X server command line
option, '-masterfd'.
There's a companion application, xlease, which creates a DRM master by
leasing an output from another X server. That is available at
git clone git://people.freedesktop.org/~keithp/xlease
Signed-off-by: Keith Packard <keithp@keithp.com>
-rw-r--r-- | hw/xfree86/common/xf86Globals.c | 2 | ||||
-rw-r--r-- | hw/xfree86/common/xf86Priv.h | 1 | ||||
-rw-r--r-- | hw/xfree86/drivers/modesetting/driver.c | 26 | ||||
-rw-r--r-- | hw/xfree86/drivers/modesetting/driver.h | 1 | ||||
-rw-r--r-- | hw/xfree86/os-support/linux/lnx_init.c | 22 |
5 files changed, 51 insertions, 1 deletions
diff --git a/hw/xfree86/common/xf86Globals.c b/hw/xfree86/common/xf86Globals.c index e890f05c2..7cc7401a2 100644 --- a/hw/xfree86/common/xf86Globals.c +++ b/hw/xfree86/common/xf86Globals.c @@ -53,6 +53,8 @@ DevPrivateKeyRec xf86ScreenKeyRec; ScrnInfoPtr *xf86Screens = NULL; /* List of ScrnInfos */ ScrnInfoPtr *xf86GPUScreens = NULL; /* List of ScrnInfos */ +int xf86DRMMasterFd = -1; /* Command line argument for DRM master file descriptor */ + const unsigned char byte_reversed[256] = { 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, diff --git a/hw/xfree86/common/xf86Priv.h b/hw/xfree86/common/xf86Priv.h index 4fe2b5f33..393af3900 100644 --- a/hw/xfree86/common/xf86Priv.h +++ b/hw/xfree86/common/xf86Priv.h @@ -93,6 +93,7 @@ extern _X_EXPORT int xf86LogVerbose; /* log file verbosity level */ extern ScrnInfoPtr *xf86GPUScreens; /* List of pointers to ScrnInfoRecs */ extern int xf86NumGPUScreens; +extern _X_EXPORT int xf86DRMMasterFd; /* Command line argument for DRM master file descriptor */ #ifndef DEFAULT_VERBOSE #define DEFAULT_VERBOSE 0 #endif diff --git a/hw/xfree86/drivers/modesetting/driver.c b/hw/xfree86/drivers/modesetting/driver.c index ec2aa9a27..1d84e113d 100644 --- a/hw/xfree86/drivers/modesetting/driver.c +++ b/hw/xfree86/drivers/modesetting/driver.c @@ -36,6 +36,7 @@ #include <unistd.h> #include <fcntl.h> #include "xf86.h" +#include "xf86Priv.h" #include "xf86_OSproc.h" #include "compiler.h" #include "xf86Pci.h" @@ -195,10 +196,23 @@ modesettingEntPtr ms_ent_priv(ScrnInfoPtr scrn) } static int +get_passed_fd(void) +{ + if (xf86DRMMasterFd >= 0) { + xf86DrvMsg(-1, X_INFO, "Using passed DRM master file descriptor %d\n", xf86DRMMasterFd); + return dup(xf86DRMMasterFd); + } + return -1; +} + +static int open_hw(const char *dev) { int fd; + if ((fd = get_passed_fd()) != -1) + return fd; + if (dev) fd = open(dev, O_RDWR, 0); else { @@ -822,6 +836,12 @@ ms_get_drm_master_fd(ScrnInfoPtr pScrn) return TRUE; } + ms->fd_passed = FALSE; + if ((ms->fd = get_passed_fd()) >= 0) { + ms->fd_passed = TRUE; + return TRUE; + } + #ifdef XSERVER_PLATFORM_BUS if (pEnt->location.type == BUS_PLATFORM) { if (pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD) @@ -1495,6 +1515,9 @@ SetMaster(ScrnInfoPtr pScrn) (ms->pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD)) return TRUE; + if (ms->fd_passed) + return TRUE; + ret = drmSetMaster(ms->fd); if (ret) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "drmSetMaster failed: %s\n", @@ -1746,7 +1769,8 @@ LeaveVT(ScrnInfoPtr pScrn) (ms->pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD)) return; - drmDropMaster(ms->fd); + if (!ms->fd_passed) + drmDropMaster(ms->fd); } /* diff --git a/hw/xfree86/drivers/modesetting/driver.h b/hw/xfree86/drivers/modesetting/driver.h index fe835918b..6be51e01b 100644 --- a/hw/xfree86/drivers/modesetting/driver.h +++ b/hw/xfree86/drivers/modesetting/driver.h @@ -84,6 +84,7 @@ struct ms_drm_queue { typedef struct _modesettingRec { int fd; + Bool fd_passed; int Chipset; EntityInfoPtr pEnt; diff --git a/hw/xfree86/os-support/linux/lnx_init.c b/hw/xfree86/os-support/linux/lnx_init.c index 9e5ddcd50..b654f7618 100644 --- a/hw/xfree86/os-support/linux/lnx_init.c +++ b/hw/xfree86/os-support/linux/lnx_init.c @@ -356,6 +356,13 @@ xf86CloseConsole(void) close(xf86Info.consoleFd); /* make the vt-manager happy */ } +#define CHECK_FOR_REQUIRED_ARGUMENT() \ + if (((i + 1) >= argc) || (!argv[i + 1])) { \ + ErrorF("Required argument to %s not specified\n", argv[i]); \ + UseMsg(); \ + FatalError("Required argument to %s not specified\n", argv[i]); \ + } + int xf86ProcessArgument(int argc, char *argv[], int i) { @@ -376,6 +383,19 @@ xf86ProcessArgument(int argc, char *argv[], int i) } return 1; } + + if (!strcmp(argv[i], "-masterfd")) { + CHECK_FOR_REQUIRED_ARGUMENT(); + if (xf86PrivsElevated()) + FatalError("\nCannot specify -masterfd when server is setuid/setgid\n"); + if (sscanf(argv[++i], "%d", &xf86DRMMasterFd) != 1) { + UseMsg(); + xf86DRMMasterFd = -1; + return 0; + } + return 2; + } + return 0; } @@ -385,4 +405,6 @@ xf86UseMsg(void) ErrorF("vtXX use the specified VT number\n"); ErrorF("-keeptty "); ErrorF("don't detach controlling tty (for debugging only)\n"); + if (!xf86PrivsElevated()) + ErrorF("-masterfd <fd> use the specified fd as the DRM master fd\n"); } |