@@ -4163,9 +4163,12 @@ int drm_mode_getblob_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv)
{
struct drm_mode_get_blob *out_resp = data;
- struct drm_property_blob *blob;
+ const struct drm_property_blob *blob = NULL;
+ const struct drm_display_mode *mode = NULL;
+ void __user *user_ptr = (void __user *)(unsigned long)out_resp->data;
+ u32 length;
+ const void *data_src;
int ret = 0;
- void __user *blob_ptr;
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL;
@@ -4173,18 +4176,29 @@ int drm_mode_getblob_ioctl(struct drm_device *dev,
drm_modeset_lock_all(dev);
blob = drm_property_blob_find(dev, out_resp->blob_id);
if (!blob) {
+ /* If we don't find a blob, they might be trying to get a mode
+ * instead. */
+ mode = drm_mode_find(dev, out_resp->blob_id);
+ }
+
+ if (blob) {
+ length = blob->length;
+ data_src = blob->data;
+ } else if (mode) {
+ length = sizeof(mode->umode);
+ data_src = &mode->umode;
+ } else {
ret = -ENOENT;
goto done;
}
- if (out_resp->length == blob->length) {
- blob_ptr = (void __user *)(unsigned long)out_resp->data;
- if (copy_to_user(blob_ptr, blob->data, blob->length)) {
+ if (out_resp->length == length) {
+ if (copy_to_user(user_ptr, data_src, length)) {
ret = -EFAULT;
goto done;
}
}
- out_resp->length = blob->length;
+ out_resp->length = length;
done:
drm_modeset_unlock_all(dev);
@@ -1533,6 +1533,14 @@ drm_property_blob_find(struct drm_device *dev, uint32_t id)
return mo ? obj_to_blob(mo) : NULL;
}
+static inline struct drm_display_mode *drm_mode_find(struct drm_device *dev,
+ uint32_t id)
+{
+ struct drm_mode_object *mo;
+ mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_MODE);
+ return mo ? obj_to_mode(mo) : NULL;
+}
+
/* Plane list iterator for legacy (overlay only) planes. */
#define drm_for_each_legacy_plane(plane, planelist) \
list_for_each_entry(plane, planelist, head) \
Overload the getblob ioctl to allow passing in a mode ID, which will return the userspace representation (drm_mode_modeinfo) of that mode. Signed-off-by: Daniel Stone <daniels@collabora.com> --- drivers/gpu/drm/drm_crtc.c | 26 ++++++++++++++++++++------ include/drm/drm_crtc.h | 8 ++++++++ 2 files changed, 28 insertions(+), 6 deletions(-)