cb424d7448
verify-patch-sanity.py validates every active recipe .patch has internally- consistent hunk line counts — catching the 'malformed patch at line N' failure at commit/CI/preflight time instead of hours into a cook. This cycle hit that class three times (qtwaylandscanner, sddm, xwayland), each only discovered when cookbook tried to apply the patch. Running it across the repo found 29 latent malformed patches (validated against GNU patch: e.g. relibc/P3-sysv-ipc reproduces 'malformed patch at line 22'). They were harmless only because they sit in vendored recipes (baked, not re- applied) — but would fail on any version-bump re-derivation. --fix recounts the hunk headers (body untouched) and repaired all 29. Wired into build-preflight.sh (Phase 1.0D) and redbear-ci.yml, with a unit test (test-patch-sanity.sh). Skips archived/legacy trees and unvalidatable formats (empty placeholders, bare-@@ git hunks).
841 lines
25 KiB
Diff
841 lines
25 KiB
Diff
diff --git a/xf86drm.c b/xf86drm.c
|
|
index 3a10589..207c456 100644
|
|
--- a/xf86drm.c
|
|
+++ b/xf86drm.c
|
|
@@ -88,8 +88,10 @@
|
|
#endif
|
|
|
|
#include "xf86drm.h"
|
|
+#include "xf86drm_redox.h"
|
|
#include "libdrm_macros.h"
|
|
#include "drm_fourcc.h"
|
|
+#include "virtgpu_drm.h"
|
|
|
|
#include "util_math.h"
|
|
|
|
@@ -113,7 +115,7 @@
|
|
#define DRM_MAJOR 226 /* Linux */
|
|
#endif
|
|
|
|
-#if defined(__OpenBSD__) || defined(__DragonFly__)
|
|
+#if defined(__OpenBSD__) || defined(__DragonFly__) || defined(__redox__)
|
|
struct drm_pciinfo {
|
|
uint16_t domain;
|
|
uint8_t bus;
|
|
@@ -313,7 +315,6 @@ drmGetFormatModifierNameFromArm(uint64_t modifier)
|
|
uint64_t type = (modifier >> 52) & 0xf;
|
|
|
|
FILE *fp;
|
|
- size_t size = 0;
|
|
char *modifier_name = NULL;
|
|
bool result = false;
|
|
|
|
@@ -321,6 +322,7 @@ drmGetFormatModifierNameFromArm(uint64_t modifier)
|
|
fprintf(stderr, "open_memstream not available on Redox\n");
|
|
return NULL;
|
|
#else
|
|
+ size_t size = 0;
|
|
fp = open_memstream(&modifier_name, &size);
|
|
if (!fp)
|
|
return NULL;
|
|
@@ -425,12 +427,12 @@ drmGetFormatModifierNameFromAmd(uint64_t modifier)
|
|
uint64_t tile_version = AMD_FMT_MOD_GET(TILE_VERSION, modifier);
|
|
FILE *fp;
|
|
char *mod_amd = NULL;
|
|
- size_t size = 0;
|
|
|
|
#if defined(__redox__)
|
|
fprintf(stderr, "open_memstream not available on Redox\n");
|
|
return NULL;
|
|
#else
|
|
+ size_t size = 0;
|
|
fp = open_memstream(&mod_amd, &size);
|
|
if (!fp)
|
|
return NULL;
|
|
@@ -703,3 +705,159 @@ drm_public void drmFree(void *pt)
|
|
free(pt);
|
|
}
|
|
|
|
+#if defined(__redox__)
|
|
+static int redox_drm_write_all(int fd, const void *buf, size_t len)
|
|
+{
|
|
+ const uint8_t *bytes = buf;
|
|
+ size_t offset = 0;
|
|
+
|
|
+ while (offset < len) {
|
|
+ ssize_t written = write(fd, bytes + offset, len - offset);
|
|
+ if (written < 0) {
|
|
+ if (errno == EINTR || errno == EAGAIN)
|
|
+ continue;
|
|
+ return -1;
|
|
+ }
|
|
+ if (written == 0) {
|
|
+ errno = EIO;
|
|
+ return -1;
|
|
+ }
|
|
+ offset += (size_t)written;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int redox_drm_read_all(int fd, void *buf, size_t len)
|
|
+{
|
|
+ uint8_t *bytes = buf;
|
|
+ size_t offset = 0;
|
|
+
|
|
+ while (offset < len) {
|
|
+ ssize_t read_count = read(fd, bytes + offset, len - offset);
|
|
+ if (read_count < 0) {
|
|
+ if (errno == EINTR || errno == EAGAIN)
|
|
+ continue;
|
|
+ return -1;
|
|
+ }
|
|
+ if (read_count == 0) {
|
|
+ errno = EIO;
|
|
+ return -1;
|
|
+ }
|
|
+ offset += (size_t)read_count;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int redox_drm_send_request(int fd, unsigned long request_code,
|
|
+ const void *payload, size_t payload_size)
|
|
+{
|
|
+ const size_t request_word_size = sizeof(uintptr_t);
|
|
+ const size_t total_size = request_word_size + payload_size;
|
|
+ uint8_t stack_request[sizeof(uintptr_t)];
|
|
+ uint8_t *request_bytes = stack_request;
|
|
+ uintptr_t request_word = (uintptr_t)request_code;
|
|
+ size_t i;
|
|
+
|
|
+ if (total_size > sizeof(stack_request)) {
|
|
+ request_bytes = drmMalloc(total_size);
|
|
+ if (!request_bytes) {
|
|
+ errno = ENOMEM;
|
|
+ return -1;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < request_word_size; ++i)
|
|
+ request_bytes[i] = (uint8_t)((request_word >> (i * 8)) & 0xffU);
|
|
+
|
|
+ if (payload_size != 0)
|
|
+ memcpy(request_bytes + request_word_size, payload, payload_size);
|
|
+
|
|
+ if (redox_drm_write_all(fd, request_bytes, total_size) != 0) {
|
|
+ if (request_bytes != stack_request)
|
|
+ drmFree(request_bytes);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if (request_bytes != stack_request)
|
|
+ drmFree(request_bytes);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int redox_drm_get_response_size(int fd, size_t *response_size)
|
|
+{
|
|
+ stat_t st;
|
|
+
|
|
+ if (fstat(fd, &st) != 0)
|
|
+ return -1;
|
|
+
|
|
+ *response_size = (size_t)st.st_size;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+unsigned long redox_translate_request(unsigned long linux_nr)
|
|
+{
|
|
+ switch (linux_nr) {
|
|
+ case 0x0C:
|
|
+ return REDOX_DRM_IOCTL_GET_CAP;
|
|
+ case 0x0D:
|
|
+ return REDOX_DRM_IOCTL_SET_CLIENT_CAP;
|
|
+ case 0x09:
|
|
+ return REDOX_DRM_IOCTL_GEM_CLOSE;
|
|
+ case 0xA6:
|
|
+ return REDOX_DRM_IOCTL_MODE_GETENCODER;
|
|
+ case 0xB3:
|
|
+ return REDOX_DRM_IOCTL_MODE_MAP_DUMB;
|
|
+ case 0xB4:
|
|
+ return REDOX_DRM_IOCTL_MODE_DESTROY_DUMB;
|
|
+ case 0xAF:
|
|
+ return REDOX_DRM_IOCTL_MODE_RMFB;
|
|
+ /* VirtGPU ioctls (NR 0x41-0x4B) */
|
|
+ case 0x41:
|
|
+ return REDOX_DRM_IOCTL_VIRTGPU_MAP;
|
|
+ case 0x42:
|
|
+ return REDOX_DRM_IOCTL_VIRTGPU_EXECBUFFER;
|
|
+ case 0x43:
|
|
+ return REDOX_DRM_IOCTL_VIRTGPU_GETPARAM;
|
|
+ case 0x44:
|
|
+ return REDOX_DRM_IOCTL_VIRTGPU_RESOURCE_CREATE;
|
|
+ case 0x45:
|
|
+ return REDOX_DRM_IOCTL_VIRTGPU_RESOURCE_INFO;
|
|
+ case 0x46:
|
|
+ return REDOX_DRM_IOCTL_VIRTGPU_TRANSFER_FROM_HOST;
|
|
+ case 0x47:
|
|
+ return REDOX_DRM_IOCTL_VIRTGPU_TRANSFER_TO_HOST;
|
|
+ case 0x48:
|
|
+ return REDOX_DRM_IOCTL_VIRTGPU_WAIT;
|
|
+ case 0x49:
|
|
+ return REDOX_DRM_IOCTL_VIRTGPU_GET_CAPS;
|
|
+ case 0x4A:
|
|
+ return REDOX_DRM_IOCTL_VIRTGPU_RESOURCE_CREATE_BLOB;
|
|
+ case 0x4B:
|
|
+ return REDOX_DRM_IOCTL_VIRTGPU_CONTEXT_INIT;
|
|
+ /* Additional standard DRM ioctls */
|
|
+ case 0x00:
|
|
+ return REDOX_DRM_IOCTL_VERSION;
|
|
+ case 0xA0:
|
|
+ return REDOX_DRM_IOCTL_MODE_GETRESOURCES;
|
|
+ case 0xA1:
|
|
+ return REDOX_DRM_IOCTL_MODE_GETCRTC;
|
|
+ case 0xA2:
|
|
+ return REDOX_DRM_IOCTL_MODE_SETCRTC;
|
|
+ case 0xA3:
|
|
+ return REDOX_DRM_IOCTL_MODE_GETCONNECTOR;
|
|
+ case 0xA4:
|
|
+ return REDOX_DRM_IOCTL_MODE_PAGE_FLIP;
|
|
+ case 0xA8:
|
|
+ return REDOX_DRM_IOCTL_MODE_CREATE_DUMB;
|
|
+ case 0xAC:
|
|
+ return REDOX_DRM_IOCTL_MODE_ADDFB;
|
|
+ case 0x2B:
|
|
+ return REDOX_DRM_IOCTL_PRIME_HANDLE_TO_FD;
|
|
+ case 0x2C:
|
|
+ return REDOX_DRM_IOCTL_PRIME_FD_TO_HANDLE;
|
|
+ /* DRM_IOCTL_GET_PCIINFO — PCI device information for driver discovery */
|
|
+ case 0x15:
|
|
+ return REDOX_DRM_IOCTL_GET_PCI_INFO;
|
|
/* i915 UAPI translation. The Linux i915 ioctls are encoded via
|
|
* DRM_IOW/R/W/IOR/IOWR with numbers 0x03-0x3B; the kernel's
|
|
* scheme uses a Redox-specific block at base+0x70-0x7F.
|
|
* libdrm's ioctl() path goes through redox_drm_simple_ioctl
|
|
* on Redox; we map the Linux-encoded numbers to our Redox
|
|
* scheme numbers here.
|
|
*/
|
|
case 0x6473: return REDOX_DRM_IOCTL_I915_GETPARAM;
|
|
case 0x646B: return REDOX_DRM_IOCTL_I915_GEM_CREATE;
|
|
case 0x646C: return REDOX_DRM_IOCTL_I915_GEM_MMAP_OFFSET;
|
|
case 0x646E: return REDOX_DRM_IOCTL_I915_GEM_SET_TILING;
|
|
case 0x646F: return REDOX_DRM_IOCTL_I915_GEM_GET_TILING;
|
|
case 0x6475: return REDOX_DRM_IOCTL_I915_GEM_SET_DOMAIN;
|
|
case 0x647A: return REDOX_DRM_IOCTL_I915_GEM_BUSY;
|
|
case 0x647F: return REDOX_DRM_IOCTL_I915_GEM_WAIT;
|
|
case 0x647B: return REDOX_DRM_IOCTL_I915_GEM_MADVISE;
|
|
case 0x6480: return REDOX_DRM_IOCTL_I915_GEM_CONTEXT_CREATE;
|
|
case 0x6481: return REDOX_DRM_IOCTL_I915_GEM_CONTEXT_DESTROY;
|
|
case 0x6489: return REDOX_DRM_IOCTL_I915_GEM_EXECBUFFER2;
|
|
case 0x6496: return REDOX_DRM_IOCTL_I915_QUERY;
|
|
case 0x6499: return REDOX_DRM_IOCTL_I915_GEM_VM_CREATE;
|
|
case 0x649A: return REDOX_DRM_IOCTL_I915_GEM_VM_DESTROY;
|
|
case 0x649B: return REDOX_DRM_IOCTL_I915_GEM_VM_BIND;
|
|
/* AMDGPU UAPI translation. Linux amdgpu uses DRM_IOWR(0x1B,...)
|
|
* etc; we map to the Redox scheme block at base+0x90-0x97.
|
|
*/
|
|
case 0x655B: return REDOX_DRM_IOCTL_AMDGPU_GEM_CREATE;
|
|
case 0x655C: return REDOX_DRM_IOCTL_AMDGPU_CTX;
|
|
case 0x655D: return REDOX_DRM_IOCTL_AMDGPU_CS;
|
|
case 0x655E: return REDOX_DRM_IOCTL_AMDGPU_VM;
|
|
case 0x655F: return REDOX_DRM_IOCTL_AMDGPU_BO_LIST;
|
|
case 0x6560: return REDOX_DRM_IOCTL_AMDGPU_WAIT_FENCES;
|
|
case 0x6561: return REDOX_DRM_IOCTL_AMDGPU_INFO;
|
|
case 0x6562: return REDOX_DRM_IOCTL_AMDGPU_FENCE_TO_HANDLE;
|
|
+ /* DRM auth/master ioctls */
|
|
+ case 0x02: /* GET_MAGIC — DRM_IOR(0x02, struct drm_auth) */
|
|
+ return REDOX_DRM_IOCTL_GET_MAGIC;
|
|
+ case 0x11: /* AUTH_MAGIC — DRM_IOW(0x11, struct drm_auth) */
|
|
+ return REDOX_DRM_IOCTL_AUTH_MAGIC;
|
|
+ case 0x1e: /* SET_MASTER — DRM_IO(0x1e) */
|
|
+ return REDOX_DRM_IOCTL_SET_MASTER;
|
|
+ case 0x1f: /* DROP_MASTER — DRM_IO(0x1f) */
|
|
+ return REDOX_DRM_IOCTL_DROP_MASTER;
|
|
+ default:
|
|
+ return 0;
|
|
+ }
|
|
+}
|
|
+
|
|
+int redox_drm_exchange(int fd, unsigned long request_code,
|
|
+ const void *payload, size_t payload_size,
|
|
+ void *response, size_t response_capacity,
|
|
+ size_t *response_size)
|
|
+{
|
|
+ uint8_t stack_buffer[64];
|
|
+ uint8_t *response_buffer = stack_buffer;
|
|
+ size_t actual_response_size = 0;
|
|
+
|
|
+ if (redox_drm_send_request(fd, request_code, payload, payload_size) != 0)
|
|
+ return -1;
|
|
+
|
|
+ if (redox_drm_get_response_size(fd, &actual_response_size) != 0)
|
|
+ return -1;
|
|
+
|
|
+ if (response_size)
|
|
+ *response_size = actual_response_size;
|
|
+
|
|
+ if (actual_response_size == 0)
|
|
+ return 0;
|
|
+
|
|
+ if (response && response_capacity >= actual_response_size) {
|
|
+ return redox_drm_read_all(fd, response, actual_response_size);
|
|
+ }
|
|
+
|
|
+ if (actual_response_size > sizeof(stack_buffer)) {
|
|
+ response_buffer = drmMalloc(actual_response_size);
|
|
+ if (!response_buffer) {
|
|
+ errno = ENOMEM;
|
|
+ return -1;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (redox_drm_read_all(fd, response_buffer, actual_response_size) != 0) {
|
|
+ if (response_buffer != stack_buffer)
|
|
+ drmFree(response_buffer);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if (response_buffer != stack_buffer)
|
|
+ drmFree(response_buffer);
|
|
+
|
|
+ if (response && response_capacity < actual_response_size) {
|
|
+ errno = EMSGSIZE;
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int redox_drm_exchange_alloc(int fd, unsigned long request_code,
|
|
+ const void *payload, size_t payload_size,
|
|
+ void **response, size_t *response_size)
|
|
+{
|
|
+ size_t actual_response_size = 0;
|
|
+ void *allocated_response = NULL;
|
|
+
|
|
+ if (!response) {
|
|
+ errno = EINVAL;
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if (redox_drm_send_request(fd, request_code, payload, payload_size) != 0)
|
|
+ return -1;
|
|
+
|
|
+ if (redox_drm_get_response_size(fd, &actual_response_size) != 0)
|
|
+ return -1;
|
|
+
|
|
+ if (actual_response_size != 0) {
|
|
+ allocated_response = drmMalloc(actual_response_size);
|
|
+ if (!allocated_response) {
|
|
+ errno = ENOMEM;
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if (redox_drm_read_all(fd, allocated_response, actual_response_size) != 0) {
|
|
+ drmFree(allocated_response);
|
|
+ return -1;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ *response = allocated_response;
|
|
+ if (response_size)
|
|
+ *response_size = actual_response_size;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static size_t redox_drm_expected_response_size(unsigned long linux_nr, size_t arg_size)
|
|
+{
|
|
+ switch (linux_nr) {
|
|
+ case 0x00: /* VERSION */
|
|
+ case 0x0C:
|
|
+ case 0x2B: /* PRIME_HANDLE_TO_FD */
|
|
+ case 0x2C: /* PRIME_FD_TO_HANDLE */
|
|
+ case 0x41: /* VIRTGPU_MAP */
|
|
+ case 0x43: /* VIRTGPU_GETPARAM */
|
|
+ case 0x44: /* VIRTGPU_RESOURCE_CREATE */
|
|
+ case 0x45: /* VIRTGPU_RESOURCE_INFO */
|
|
+ case 0xA0: /* MODE_GETRESOURCES */
|
|
+ case 0xA1: /* MODE_GETCRTC */
|
|
+ case 0xA3: /* MODE_GETCONNECTOR */
|
|
+ case 0xA8: /* MODE_CREATE_DUMB */
|
|
+ case 0xAC: /* MODE_ADDFB */
|
|
+ case 0xA6:
|
|
+ case 0xB3:
|
|
+ return arg_size;
|
|
+ case 0x02: /* GET_MAGIC — returns struct drm_auth (magic u32) */
|
|
+ return arg_size;
|
|
+ case 0x11: /* AUTH_MAGIC — returns struct drm_auth (magic u32) */
|
|
+ return arg_size;
|
|
+ default:
|
|
+ return 0;
|
|
+ }
|
|
+}
|
|
+
|
|
+int redox_drm_simple_ioctl(int fd, unsigned long request, void *arg)
|
|
+{
|
|
+ const unsigned long linux_nr = REDOX_LINUX_IOCTL_NR(request);
|
|
+ const unsigned long request_code = redox_translate_request(linux_nr);
|
|
+ const size_t arg_size = REDOX_LINUX_IOCTL_SIZE(request);
|
|
+ const size_t expected_response_size = redox_drm_expected_response_size(linux_nr, arg_size);
|
|
+
|
|
+ if (request_code == 0) {
|
|
+ errno = ENOTTY;
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if (linux_nr == 0x42) { /* VIRTGPU_EXECBUFFER */
|
|
+ struct drm_virtgpu_execbuffer *eb = arg;
|
|
+ size_t total = arg_size + eb->size;
|
|
+ uint8_t *buf = drmMalloc((int)total);
|
|
+ int ret;
|
|
+
|
|
+ if (!buf)
|
|
+ return -1;
|
|
+
|
|
+ memcpy(buf, arg, arg_size);
|
|
+ if (eb->size > 0 && eb->command)
|
|
+ memcpy(buf + arg_size, (void *)(uintptr_t)eb->command, eb->size);
|
|
+
|
|
+ ret = redox_drm_exchange(fd, request_code, buf, total, NULL, 0, NULL);
|
|
+ drmFree(buf);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ if (linux_nr == 0x49) { /* VIRTGPU_GET_CAPS */
|
|
+ struct drm_virtgpu_get_caps *gc = arg;
|
|
+ void *resp;
|
|
+ size_t resp_size;
|
|
+ int ret;
|
|
+
|
|
+ ret = redox_drm_exchange_alloc(fd, request_code, arg, arg_size, &resp, &resp_size);
|
|
+ if (ret == 0 && resp && resp_size > 0) {
|
|
+ size_t copy = resp_size < gc->size ? resp_size : gc->size;
|
|
+
|
|
+ memcpy((void *)(uintptr_t)gc->addr, resp, copy);
|
|
+ drmFree(resp);
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ if (redox_drm_exchange(fd, request_code,
|
|
+ arg, arg ? arg_size : 0,
|
|
+ expected_response_size ? arg : NULL,
|
|
+ expected_response_size,
|
|
+ NULL) != 0) {
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+#endif
|
|
+
|
|
/**
|
|
* Call ioctl, restarting if it is interrupted
|
|
*/
|
|
drm_public int
|
|
drmIoctl(int fd, unsigned long request, void *arg)
|
|
{
|
|
+ #if defined(__redox__)
|
|
+ return redox_drm_simple_ioctl(fd, request, arg);
|
|
+ #else
|
|
int ret;
|
|
|
|
do {
|
|
ret = ioctl(fd, request, arg);
|
|
} while (ret == -1 && (errno == EINTR || errno == EAGAIN));
|
|
return ret;
|
|
+ #endif
|
|
}
|
|
|
|
static unsigned long drmGetKeyFromFd(int fd)
|
|
@@ -1093,6 +1443,7 @@ static int drmGetMinorType(int major, int minor)
|
|
return -1;
|
|
}
|
|
|
|
+#if !defined(__redox__)
|
|
static const char *drmGetMinorName(int type)
|
|
{
|
|
switch (type) {
|
|
@@ -1104,6 +1455,7 @@ static const char *drmGetMinorName(int type)
|
|
return NULL;
|
|
}
|
|
}
|
|
+#endif
|
|
|
|
/**
|
|
* Open the device by bus ID.
|
|
@@ -1201,7 +1553,11 @@ static int drmOpenByName(const char *name, int type)
|
|
for (i = base; i < base + DRM_MAX_MINOR; i++) {
|
|
if ((fd = drmOpenMinor(i, 1, type)) >= 0) {
|
|
if ((version = drmGetVersion(fd))) {
|
|
+ #if defined(__redox__)
|
|
+ if (!version->name || !strcmp(version->name, name)) {
|
|
+ #else
|
|
if (!strcmp(version->name, name)) {
|
|
+ #endif
|
|
drmFreeVersion(version);
|
|
id = drmGetBusid(fd);
|
|
drmMsg("drmGetBusid returned '%s'\n", id ? id : "NULL");
|
|
@@ -1354,6 +1710,7 @@ drm_public void drmFreeVersion(drmVersionPtr v)
|
|
* Used by drmGetVersion() to free the memory pointed by \p %v as well as all
|
|
* the non-null strings pointers in it.
|
|
*/
|
|
+#if !defined(__redox__)
|
|
static void drmFreeKernelVersion(drm_version_t *v)
|
|
{
|
|
if (!v)
|
|
@@ -1363,6 +1720,7 @@ static void drmFreeKernelVersion(drm_version_t *v)
|
|
drmFree(v->desc);
|
|
drmFree(v);
|
|
}
|
|
+#endif
|
|
|
|
|
|
/**
|
|
@@ -1375,6 +1733,7 @@ static void drmFreeKernelVersion(drm_version_t *v)
|
|
* Used by drmGetVersion() to translate the information returned by the ioctl
|
|
* interface in a private structure into the public structure counterpart.
|
|
*/
|
|
+#if !defined(__redox__)
|
|
static void drmCopyVersion(drmVersionPtr d, const drm_version_t *s)
|
|
{
|
|
d->version_major = s->version_major;
|
|
@@ -1387,6 +1746,7 @@ static void drmCopyVersion(drmVersionPtr d, const drm_version_t *s)
|
|
d->desc_len = s->desc_len;
|
|
d->desc = s->desc ? strdup(s->desc) : NULL;
|
|
}
|
|
+#endif
|
|
|
|
|
|
/**
|
|
@@ -1406,6 +1766,50 @@ static void drmCopyVersion(drmVersionPtr d, const drm_version_t *s)
|
|
*/
|
|
drm_public drmVersionPtr drmGetVersion(int fd)
|
|
{
|
|
+ #if defined(__redox__)
|
|
+ drmVersionPtr retval = drmMalloc(sizeof(*retval));
|
|
+ struct redox_drm_version_wire version;
|
|
+
|
|
+ if (!retval)
|
|
+ return NULL;
|
|
+
|
|
+ if (redox_drm_exchange(fd, REDOX_DRM_IOCTL_VERSION,
|
|
+ NULL, 0,
|
|
+ &version, sizeof(version),
|
|
+ NULL) != 0) {
|
|
+ drmFree(retval);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ memclear(*retval);
|
|
+ retval->version_major = version.major;
|
|
+ retval->version_minor = version.minor;
|
|
+ retval->version_patchlevel = version.patch;
|
|
+
|
|
+ /* The scheme returns a NUL-terminated driver name in version.name.
|
|
+ * KWin drm_gpu.cpp dereferences version->name unconditionally
|
|
+ * (strstr checks for "i915", "amdgpu", "virtio" etc.) so it must
|
|
+ * never be NULL.
|
|
+ */
|
|
+ version.name[sizeof(version.name) - 1] = '\0';
|
|
+ if (version.name[0] != '\0') {
|
|
+ size_t len = strlen(version.name);
|
|
+ retval->name = drmMalloc(len + 1);
|
|
+ if (retval->name) {
|
|
+ memcpy(retval->name, version.name, len + 1);
|
|
+ retval->name_len = len;
|
|
+ }
|
|
+ } else {
|
|
+ const char fallback[] = "redox-drm";
|
|
+ retval->name = drmMalloc(sizeof(fallback));
|
|
+ if (retval->name) {
|
|
+ memcpy(retval->name, fallback, sizeof(fallback));
|
|
+ retval->name_len = sizeof(fallback) - 1;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return retval;
|
|
+ #else
|
|
drmVersionPtr retval;
|
|
drm_version_t *version = drmMalloc(sizeof(*version));
|
|
|
|
@@ -1436,6 +1840,7 @@ drm_public drmVersionPtr drmGetVersion(int fd)
|
|
drmCopyVersion(retval, version);
|
|
drmFreeKernelVersion(version);
|
|
return retval;
|
|
+ #endif
|
|
}
|
|
|
|
|
|
@@ -3400,6 +3805,23 @@ drm_public int drmGetNodeTypeFromFd(int fd)
|
|
drm_public int drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags,
|
|
int *prime_fd)
|
|
{
|
|
+ #if defined(__redox__)
|
|
+ struct redox_drm_prime_handle_to_fd_wire request;
|
|
+ struct redox_drm_prime_handle_to_fd_response_wire response;
|
|
+
|
|
+ memclear(request);
|
|
+ request.handle = handle;
|
|
+ request.flags = flags;
|
|
+ if (redox_drm_exchange(fd, REDOX_DRM_IOCTL_PRIME_HANDLE_TO_FD,
|
|
+ &request, sizeof(request),
|
|
+ &response, sizeof(response),
|
|
+ NULL) != 0) {
|
|
+ return -errno;
|
|
+ }
|
|
+
|
|
+ *prime_fd = response.fd;
|
|
+ return 0;
|
|
+ #else
|
|
struct drm_prime_handle args;
|
|
int ret;
|
|
|
|
@@ -3413,10 +3835,27 @@ drm_public int drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags,
|
|
|
|
*prime_fd = args.fd;
|
|
return 0;
|
|
+ #endif
|
|
}
|
|
|
|
drm_public int drmPrimeFDToHandle(int fd, int prime_fd, uint32_t *handle)
|
|
{
|
|
+ #if defined(__redox__)
|
|
+ struct redox_drm_prime_fd_to_handle_wire request;
|
|
+ struct redox_drm_prime_fd_to_handle_response_wire response;
|
|
+
|
|
+ memclear(request);
|
|
+ request.fd = prime_fd;
|
|
+ if (redox_drm_exchange(fd, REDOX_DRM_IOCTL_PRIME_FD_TO_HANDLE,
|
|
+ &request, sizeof(request),
|
|
+ &response, sizeof(response),
|
|
+ NULL) != 0) {
|
|
+ return -errno;
|
|
+ }
|
|
+
|
|
+ *handle = response.handle;
|
|
+ return 0;
|
|
+ #else
|
|
struct drm_prime_handle args;
|
|
int ret;
|
|
|
|
@@ -3428,6 +3867,7 @@ drm_public int drmPrimeFDToHandle(int fd, int prime_fd, uint32_t *handle)
|
|
|
|
*handle = args.handle;
|
|
return 0;
|
|
+ #endif
|
|
}
|
|
|
|
drm_public int drmCloseBufferHandle(int fd, uint32_t handle)
|
|
@@ -3544,7 +3984,7 @@ static char *drmGetMinorNameForFD(int fd, int type)
|
|
n = drmGetNodePath(buf, sizeof(buf), type, min);
|
|
if (n < 0)
|
|
return NULL;
|
|
- if (n == -1 || n >= sizeof(buf))
|
|
+ if ((size_t)n >= sizeof(buf))
|
|
return NULL;
|
|
|
|
return strdup(buf);
|
|
@@ -3666,7 +4106,7 @@ static int drmParseSubsystemType(int maj, int min)
|
|
return DRM_BUS_VIRTIO;
|
|
}
|
|
return subsystem_type;
|
|
-#elif defined(__OpenBSD__) || defined(__DragonFly__) || defined(__FreeBSD__)
|
|
+#elif defined(__OpenBSD__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__redox__)
|
|
return DRM_BUS_PCI;
|
|
#else
|
|
#warning "Missing implementation of drmParseSubsystemType"
|
|
@@ -3800,6 +4240,21 @@ static int drmParsePciBusInfo(int maj, int min, drmPciBusInfoPtr info)
|
|
return 0;
|
|
#elif defined(__FreeBSD__)
|
|
return get_sysctl_pci_bus_info(maj, min, info);
|
|
+#elif defined(__redox__)
|
|
+ int rfd = open("/scheme/drm/card0", O_RDONLY);
|
|
+ if (rfd < 0)
|
|
+ return -errno;
|
|
+ uint8_t buf[22];
|
|
+ size_t rsize = 0;
|
|
+ int ret = redox_drm_exchange(rfd, REDOX_DRM_IOCTL_GET_PCI_INFO, NULL, 0, buf, sizeof(buf), &rsize);
|
|
+ close(rfd);
|
|
+ if (ret != 0 || rsize < 17)
|
|
+ return -EIO;
|
|
+ info->domain = buf[10] | (buf[11] << 8) | (buf[12] << 16) | (buf[13] << 24);
|
|
+ info->bus = buf[14];
|
|
+ info->dev = buf[15];
|
|
+ info->func = buf[16];
|
|
+ return 0;
|
|
#else
|
|
#warning "Missing implementation of drmParsePciBusInfo"
|
|
return -EINVAL;
|
|
@@ -4009,6 +4464,23 @@ static int drmParsePciDeviceInfo(int maj, int min,
|
|
device->revision_id = results[0].pc_revid;
|
|
|
|
return 0;
|
|
+#elif defined(__redox__)
|
|
+ int rfd2 = open("/scheme/drm/card0", O_RDONLY);
|
|
+ if (rfd2 < 0)
|
|
+ return -errno;
|
|
+ uint8_t dbuf[22];
|
|
+ size_t drsize = 0;
|
|
+ int dret = redox_drm_exchange(rfd2, REDOX_DRM_IOCTL_GET_PCI_INFO, NULL, 0, dbuf, sizeof(dbuf), &drsize);
|
|
+ close(rfd2);
|
|
+ if (dret != 0 || drsize < 9)
|
|
+ return -EIO;
|
|
+ device->vendor_id = dbuf[0] | (dbuf[1] << 8);
|
|
+ device->device_id = dbuf[2] | (dbuf[3] << 8);
|
|
+ device->subvendor_id = dbuf[4] | (dbuf[5] << 8);
|
|
+ device->subdevice_id = dbuf[6] | (dbuf[7] << 8);
|
|
+ if (drsize >= 9)
|
|
+ device->revision_id = dbuf[8];
|
|
+ return 0;
|
|
#else
|
|
#warning "Missing implementation of drmParsePciDeviceInfo"
|
|
return -EINVAL;
|
|
@@ -4661,6 +5133,66 @@ drm_public int drmGetDeviceFromDevId(dev_t find_rdev, uint32_t flags, drmDeviceP
|
|
|
|
*device = d;
|
|
|
|
+ return 0;
|
|
+#elif defined(__redox__)
|
|
+ /* On Redox there is no /dev/dri/ directory to enumerate.
|
|
+ * Instead, open /scheme/drm/card0 and query PCI info to
|
|
+ * construct a single drmDevice that serves as both primary
|
|
+ * and render node. */
|
|
+ drmDevicePtr devp;
|
|
+ char *pptr;
|
|
+ int max_node_length = 64, i;
|
|
+ size_t extra, psize;
|
|
+ uint8_t pbuf[22];
|
|
+ size_t prsize = 0;
|
|
+ int pret, fd;
|
|
+
|
|
+ if (device == NULL)
|
|
+ return -EINVAL;
|
|
+ if (drm_device_validate_flags(flags))
|
|
+ return -EINVAL;
|
|
+
|
|
+ fd = open("/scheme/drm/card0", O_RDWR | O_CLOEXEC);
|
|
+ if (fd < 0)
|
|
+ return -errno;
|
|
+
|
|
+ pret = redox_drm_exchange(fd, REDOX_DRM_IOCTL_GET_PCI_INFO, NULL, 0,
|
|
+ pbuf, sizeof(pbuf), &prsize);
|
|
+ close(fd);
|
|
+ if (pret != 0 || prsize < 17)
|
|
+ return -EIO;
|
|
+
|
|
+ extra = DRM_NODE_MAX * (sizeof(void *) + max_node_length);
|
|
+ psize = sizeof(drmDevice) + extra + sizeof(drmPciBusInfo) + sizeof(drmPciDeviceInfo);
|
|
+ devp = calloc(1, psize);
|
|
+ if (!devp)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ devp->bustype = DRM_BUS_PCI;
|
|
+ /* Advertise both PRIMARY and RENDER — same path on Redox */
|
|
+ devp->available_nodes = (1 << DRM_NODE_PRIMARY) | (1 << DRM_NODE_RENDER);
|
|
+ pptr = (char *)devp + sizeof(drmDevice);
|
|
+ devp->nodes = (char **)pptr;
|
|
+ pptr += DRM_NODE_MAX * sizeof(void *);
|
|
+ for (i = 0; i < DRM_NODE_MAX; i++) { devp->nodes[i] = pptr; pptr += max_node_length; }
|
|
+ snprintf(devp->nodes[DRM_NODE_PRIMARY], max_node_length, "/scheme/drm/card0");
|
|
+ snprintf(devp->nodes[DRM_NODE_RENDER], max_node_length, "/scheme/drm/card0");
|
|
+
|
|
+ devp->businfo.pci = (drmPciBusInfoPtr)pptr;
|
|
+ pptr += sizeof(drmPciBusInfo);
|
|
+ devp->businfo.pci->domain = pbuf[10] | (pbuf[11] << 8) | (pbuf[12] << 16) | (pbuf[13] << 24);
|
|
+ devp->businfo.pci->bus = pbuf[14];
|
|
+ devp->businfo.pci->dev = pbuf[15];
|
|
+ devp->businfo.pci->func = pbuf[16];
|
|
+
|
|
+ devp->deviceinfo.pci = (drmPciDeviceInfoPtr)pptr;
|
|
+ devp->deviceinfo.pci->vendor_id = pbuf[0] | (pbuf[1] << 8);
|
|
+ devp->deviceinfo.pci->device_id = pbuf[2] | (pbuf[3] << 8);
|
|
+ devp->deviceinfo.pci->subvendor_id = pbuf[4] | (pbuf[5] << 8);
|
|
+ devp->deviceinfo.pci->subdevice_id = pbuf[6] | (pbuf[7] << 8);
|
|
+ devp->deviceinfo.pci->revision_id = pbuf[8];
|
|
+
|
|
+ *device = devp;
|
|
return 0;
|
|
#else
|
|
drmDevicePtr local_devices[MAX_DRM_NODES];
|
|
@@ -4761,6 +5293,66 @@ drm_public int drmGetNodeTypeFromDevId(dev_t devid)
|
|
*/
|
|
drm_public int drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device)
|
|
{
|
|
+#if defined(__redox__)
|
|
+ uint8_t pbuf[22];
|
|
+ size_t prsize = 0;
|
|
+ int pret;
|
|
+ uint16_t pvendor_id, pdevice_id, psubvendor_id, psubdevice_id, pdomain;
|
|
+ uint8_t prevision_id, pbus, pdev, pfunc;
|
|
+ const char *pnode;
|
|
+ int max_node_length, i;
|
|
+ size_t extra, psize;
|
|
+ drmDevicePtr devp;
|
|
+ char *pptr;
|
|
+
|
|
+ pret = redox_drm_exchange(fd, REDOX_DRM_IOCTL_GET_PCI_INFO, NULL, 0,
|
|
+ pbuf, sizeof(pbuf), &prsize);
|
|
+ if (pret != 0 || prsize < 17)
|
|
+ return -EIO;
|
|
+
|
|
+ pvendor_id = pbuf[0] | (pbuf[1] << 8);
|
|
+ pdevice_id = pbuf[2] | (pbuf[3] << 8);
|
|
+ psubvendor_id = pbuf[4] | (pbuf[5] << 8);
|
|
+ psubdevice_id = pbuf[6] | (pbuf[7] << 8);
|
|
+ prevision_id = pbuf[8];
|
|
+ pdomain = pbuf[10] | (pbuf[11] << 8) | (pbuf[12] << 16) | (pbuf[13] << 24);
|
|
+ pbus = pbuf[14];
|
|
+ pdev = pbuf[15];
|
|
+ pfunc = pbuf[16];
|
|
+
|
|
+ pnode = "/scheme/drm/card0";
|
|
+ max_node_length = 64;
|
|
+ extra = DRM_NODE_MAX * (sizeof(void *) + max_node_length);
|
|
+ psize = sizeof(drmDevice) + extra + sizeof(drmPciBusInfo) + sizeof(drmPciDeviceInfo);
|
|
+ devp = calloc(1, psize);
|
|
+ if (!devp)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ devp->bustype = DRM_BUS_PCI;
|
|
+ devp->available_nodes = 1 << DRM_NODE_PRIMARY;
|
|
+ pptr = (char *)devp + sizeof(drmDevice);
|
|
+ devp->nodes = (char **)pptr;
|
|
+ pptr += DRM_NODE_MAX * sizeof(void *);
|
|
+ for (i = 0; i < DRM_NODE_MAX; i++) { devp->nodes[i] = pptr; pptr += max_node_length; }
|
|
+ snprintf(devp->nodes[DRM_NODE_PRIMARY], max_node_length, "%s", pnode);
|
|
+
|
|
+ devp->businfo.pci = (drmPciBusInfoPtr)pptr;
|
|
+ pptr += sizeof(drmPciBusInfo);
|
|
+ devp->businfo.pci->domain = pdomain;
|
|
+ devp->businfo.pci->bus = pbus;
|
|
+ devp->businfo.pci->dev = pdev;
|
|
+ devp->businfo.pci->func = pfunc;
|
|
+
|
|
+ devp->deviceinfo.pci = (drmPciDeviceInfoPtr)pptr;
|
|
+ devp->deviceinfo.pci->vendor_id = pvendor_id;
|
|
+ devp->deviceinfo.pci->device_id = pdevice_id;
|
|
+ devp->deviceinfo.pci->subvendor_id = psubvendor_id;
|
|
+ devp->deviceinfo.pci->subdevice_id = psubdevice_id;
|
|
+ devp->deviceinfo.pci->revision_id = prevision_id;
|
|
+
|
|
+ *device = devp;
|
|
+ return 0;
|
|
+#else
|
|
struct stat sbuf;
|
|
|
|
if (fd == -1)
|
|
@@ -4773,6 +5365,7 @@ drm_public int drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device)
|
|
return -EINVAL;
|
|
|
|
return drmGetDeviceFromDevId(sbuf.st_rdev, flags, device);
|
|
+#endif
|
|
}
|
|
|
|
/**
|