|
112 | 112 | #include <linux/if_alg.h>
|
113 | 113 | #include <linux/rtc.h>
|
114 | 114 | #include <sound/asound.h>
|
| 115 | +#ifdef HAVE_DRM_H |
| 116 | +#include <libdrm/drm.h> |
| 117 | +#endif |
115 | 118 | #include "linux_loop.h"
|
116 | 119 | #include "uname.h"
|
117 | 120 |
|
@@ -5276,6 +5279,101 @@ static abi_long do_ioctl_tiocgptpeer(const IOCTLEntry *ie, uint8_t *buf_temp,
|
5276 | 5279 | }
|
5277 | 5280 | #endif
|
5278 | 5281 |
|
| 5282 | +#ifdef HAVE_DRM_H |
| 5283 | + |
| 5284 | +static void unlock_drm_version(struct drm_version *host_ver, |
| 5285 | + struct target_drm_version *target_ver, |
| 5286 | + bool copy) |
| 5287 | +{ |
| 5288 | + unlock_user(host_ver->name, target_ver->name, |
| 5289 | + copy ? host_ver->name_len : 0); |
| 5290 | + unlock_user(host_ver->date, target_ver->date, |
| 5291 | + copy ? host_ver->date_len : 0); |
| 5292 | + unlock_user(host_ver->desc, target_ver->desc, |
| 5293 | + copy ? host_ver->desc_len : 0); |
| 5294 | +} |
| 5295 | + |
| 5296 | +static inline abi_long target_to_host_drmversion(struct drm_version *host_ver, |
| 5297 | + struct target_drm_version *target_ver) |
| 5298 | +{ |
| 5299 | + memset(host_ver, 0, sizeof(*host_ver)); |
| 5300 | + |
| 5301 | + __get_user(host_ver->name_len, &target_ver->name_len); |
| 5302 | + if (host_ver->name_len) { |
| 5303 | + host_ver->name = lock_user(VERIFY_WRITE, target_ver->name, |
| 5304 | + target_ver->name_len, 0); |
| 5305 | + if (!host_ver->name) { |
| 5306 | + return -EFAULT; |
| 5307 | + } |
| 5308 | + } |
| 5309 | + |
| 5310 | + __get_user(host_ver->date_len, &target_ver->date_len); |
| 5311 | + if (host_ver->date_len) { |
| 5312 | + host_ver->date = lock_user(VERIFY_WRITE, target_ver->date, |
| 5313 | + target_ver->date_len, 0); |
| 5314 | + if (!host_ver->date) { |
| 5315 | + goto err; |
| 5316 | + } |
| 5317 | + } |
| 5318 | + |
| 5319 | + __get_user(host_ver->desc_len, &target_ver->desc_len); |
| 5320 | + if (host_ver->desc_len) { |
| 5321 | + host_ver->desc = lock_user(VERIFY_WRITE, target_ver->desc, |
| 5322 | + target_ver->desc_len, 0); |
| 5323 | + if (!host_ver->desc) { |
| 5324 | + goto err; |
| 5325 | + } |
| 5326 | + } |
| 5327 | + |
| 5328 | + return 0; |
| 5329 | +err: |
| 5330 | + unlock_drm_version(host_ver, target_ver, false); |
| 5331 | + return -EFAULT; |
| 5332 | +} |
| 5333 | + |
| 5334 | +static inline void host_to_target_drmversion( |
| 5335 | + struct target_drm_version *target_ver, |
| 5336 | + struct drm_version *host_ver) |
| 5337 | +{ |
| 5338 | + __put_user(host_ver->version_major, &target_ver->version_major); |
| 5339 | + __put_user(host_ver->version_minor, &target_ver->version_minor); |
| 5340 | + __put_user(host_ver->version_patchlevel, &target_ver->version_patchlevel); |
| 5341 | + __put_user(host_ver->name_len, &target_ver->name_len); |
| 5342 | + __put_user(host_ver->date_len, &target_ver->date_len); |
| 5343 | + __put_user(host_ver->desc_len, &target_ver->desc_len); |
| 5344 | + unlock_drm_version(host_ver, target_ver, true); |
| 5345 | +} |
| 5346 | + |
| 5347 | +static abi_long do_ioctl_drm(const IOCTLEntry *ie, uint8_t *buf_temp, |
| 5348 | + int fd, int cmd, abi_long arg) |
| 5349 | +{ |
| 5350 | + struct drm_version *ver; |
| 5351 | + struct target_drm_version *target_ver; |
| 5352 | + abi_long ret; |
| 5353 | + |
| 5354 | + switch (ie->host_cmd) { |
| 5355 | + case DRM_IOCTL_VERSION: |
| 5356 | + if (!lock_user_struct(VERIFY_WRITE, target_ver, arg, 0)) { |
| 5357 | + return -TARGET_EFAULT; |
| 5358 | + } |
| 5359 | + ver = (struct drm_version *)buf_temp; |
| 5360 | + ret = target_to_host_drmversion(ver, target_ver); |
| 5361 | + if (!is_error(ret)) { |
| 5362 | + ret = get_errno(safe_ioctl(fd, ie->host_cmd, ver)); |
| 5363 | + if (is_error(ret)) { |
| 5364 | + unlock_drm_version(ver, target_ver, false); |
| 5365 | + } else { |
| 5366 | + host_to_target_drmversion(target_ver, ver); |
| 5367 | + } |
| 5368 | + } |
| 5369 | + unlock_user_struct(target_ver, arg, 0); |
| 5370 | + return ret; |
| 5371 | + } |
| 5372 | + return -TARGET_ENOSYS; |
| 5373 | +} |
| 5374 | + |
| 5375 | +#endif |
| 5376 | + |
5279 | 5377 | static IOCTLEntry ioctl_entries[] = {
|
5280 | 5378 | #define IOCTL(cmd, access, ...) \
|
5281 | 5379 | { TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } },
|
|
0 commit comments