Commit 70109354 authored by Chris Wilson's avatar Chris Wilson

drm: Reject unknown legacy bpp and depth for drm_mode_addfb ioctl

Since this is handling user provided bpp and depth, we need to sanity
check and propagate the EINVAL back rather than assume what the insane
client intended and fill the logs with DRM_ERROR.

v2: Check both bpp and depth match the builtin pixel format, and
introduce a canonical DRM_FORMAT_INVALID to reserve 0 against any future
fourcc.

v3: Mark up DRM_FORMAT_C8 as being {bpp:8, depth:8}

Testcase: igt/kms_addfb_basic/legacy-format
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Michel Dänzer <michel.daenzer@amd.com>
Reviewed-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Link: https://patchwork.freedesktop.org/patch/msgid/20180905153116.28924-1-chris@chris-wilson.co.uk
parent 6960e6da
...@@ -45,32 +45,49 @@ static char printable_char(int c) ...@@ -45,32 +45,49 @@ static char printable_char(int c)
*/ */
uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth) uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth)
{ {
uint32_t fmt; uint32_t fmt = DRM_FORMAT_INVALID;
switch (bpp) { switch (bpp) {
case 8: case 8:
if (depth == 8)
fmt = DRM_FORMAT_C8; fmt = DRM_FORMAT_C8;
break; break;
case 16: case 16:
if (depth == 15) switch (depth) {
case 15:
fmt = DRM_FORMAT_XRGB1555; fmt = DRM_FORMAT_XRGB1555;
else break;
case 16:
fmt = DRM_FORMAT_RGB565; fmt = DRM_FORMAT_RGB565;
break; break;
default:
break;
}
break;
case 24: case 24:
if (depth == 24)
fmt = DRM_FORMAT_RGB888; fmt = DRM_FORMAT_RGB888;
break; break;
case 32: case 32:
if (depth == 24) switch (depth) {
case 24:
fmt = DRM_FORMAT_XRGB8888; fmt = DRM_FORMAT_XRGB8888;
else if (depth == 30) break;
case 30:
fmt = DRM_FORMAT_XRGB2101010; fmt = DRM_FORMAT_XRGB2101010;
else break;
case 32:
fmt = DRM_FORMAT_ARGB8888; fmt = DRM_FORMAT_ARGB8888;
break; break;
default: default:
DRM_ERROR("bad bpp, assuming x8r8g8b8 pixel format\n"); break;
fmt = DRM_FORMAT_XRGB8888; }
break;
default:
break; break;
} }
......
...@@ -112,12 +112,17 @@ int drm_mode_addfb(struct drm_device *dev, struct drm_mode_fb_cmd *or, ...@@ -112,12 +112,17 @@ int drm_mode_addfb(struct drm_device *dev, struct drm_mode_fb_cmd *or,
struct drm_mode_fb_cmd2 r = {}; struct drm_mode_fb_cmd2 r = {};
int ret; int ret;
r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth);
if (r.pixel_format == DRM_FORMAT_INVALID) {
DRM_DEBUG("bad {bpp:%d, depth:%d}\n", or->bpp, or->depth);
return -EINVAL;
}
/* convert to new format and call new ioctl */ /* convert to new format and call new ioctl */
r.fb_id = or->fb_id; r.fb_id = or->fb_id;
r.width = or->width; r.width = or->width;
r.height = or->height; r.height = or->height;
r.pitches[0] = or->pitch; r.pitches[0] = or->pitch;
r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth);
r.handles[0] = or->handle; r.handles[0] = or->handle;
if (dev->mode_config.quirk_addfb_prefer_xbgr_30bpp && if (dev->mode_config.quirk_addfb_prefer_xbgr_30bpp &&
......
...@@ -71,6 +71,9 @@ extern "C" { ...@@ -71,6 +71,9 @@ extern "C" {
#define DRM_FORMAT_BIG_ENDIAN (1<<31) /* format is big endian instead of little endian */ #define DRM_FORMAT_BIG_ENDIAN (1<<31) /* format is big endian instead of little endian */
/* Reserve 0 for the invalid format specifier */
#define DRM_FORMAT_INVALID 0
/* color index */ /* color index */
#define DRM_FORMAT_C8 fourcc_code('C', '8', ' ', ' ') /* [7:0] C */ #define DRM_FORMAT_C8 fourcc_code('C', '8', ' ', ' ') /* [7:0] C */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment