diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/video/fbmem.c | 147 |
1 files changed, 142 insertions, 5 deletions
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 81b6cd23ea1d..9f180096c896 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/config.h> | 14 | #include <linux/config.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | 16 | ||
17 | #include <linux/compat.h> | ||
17 | #include <linux/types.h> | 18 | #include <linux/types.h> |
18 | #include <linux/errno.h> | 19 | #include <linux/errno.h> |
19 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
@@ -933,18 +934,154 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
933 | } | 934 | } |
934 | 935 | ||
935 | #ifdef CONFIG_COMPAT | 936 | #ifdef CONFIG_COMPAT |
937 | struct fb_fix_screeninfo32 { | ||
938 | char id[16]; | ||
939 | compat_caddr_t smem_start; | ||
940 | u32 smem_len; | ||
941 | u32 type; | ||
942 | u32 type_aux; | ||
943 | u32 visual; | ||
944 | u16 xpanstep; | ||
945 | u16 ypanstep; | ||
946 | u16 ywrapstep; | ||
947 | u32 line_length; | ||
948 | compat_caddr_t mmio_start; | ||
949 | u32 mmio_len; | ||
950 | u32 accel; | ||
951 | u16 reserved[3]; | ||
952 | }; | ||
953 | |||
954 | struct fb_cmap32 { | ||
955 | u32 start; | ||
956 | u32 len; | ||
957 | compat_caddr_t red; | ||
958 | compat_caddr_t green; | ||
959 | compat_caddr_t blue; | ||
960 | compat_caddr_t transp; | ||
961 | }; | ||
962 | |||
963 | static int fb_getput_cmap(struct inode *inode, struct file *file, | ||
964 | unsigned int cmd, unsigned long arg) | ||
965 | { | ||
966 | struct fb_cmap_user __user *cmap; | ||
967 | struct fb_cmap32 __user *cmap32; | ||
968 | __u32 data; | ||
969 | int err; | ||
970 | |||
971 | cmap = compat_alloc_user_space(sizeof(*cmap)); | ||
972 | cmap32 = compat_ptr(arg); | ||
973 | |||
974 | if (copy_in_user(&cmap->start, &cmap32->start, 2 * sizeof(__u32))) | ||
975 | return -EFAULT; | ||
976 | |||
977 | if (get_user(data, &cmap32->red) || | ||
978 | put_user(compat_ptr(data), &cmap->red) || | ||
979 | get_user(data, &cmap32->green) || | ||
980 | put_user(compat_ptr(data), &cmap->green) || | ||
981 | get_user(data, &cmap32->blue) || | ||
982 | put_user(compat_ptr(data), &cmap->blue) || | ||
983 | get_user(data, &cmap32->transp) || | ||
984 | put_user(compat_ptr(data), &cmap->transp)) | ||
985 | return -EFAULT; | ||
986 | |||
987 | err = fb_ioctl(inode, file, cmd, (unsigned long) cmap); | ||
988 | |||
989 | if (!err) { | ||
990 | if (copy_in_user(&cmap32->start, | ||
991 | &cmap->start, | ||
992 | 2 * sizeof(__u32))) | ||
993 | err = -EFAULT; | ||
994 | } | ||
995 | return err; | ||
996 | } | ||
997 | |||
998 | static int do_fscreeninfo_to_user(struct fb_fix_screeninfo *fix, | ||
999 | struct fb_fix_screeninfo32 __user *fix32) | ||
1000 | { | ||
1001 | __u32 data; | ||
1002 | int err; | ||
1003 | |||
1004 | err = copy_to_user(&fix32->id, &fix->id, sizeof(fix32->id)); | ||
1005 | |||
1006 | data = (__u32) (unsigned long) fix->smem_start; | ||
1007 | err |= put_user(data, &fix32->smem_start); | ||
1008 | |||
1009 | err |= put_user(fix->smem_len, &fix32->smem_len); | ||
1010 | err |= put_user(fix->type, &fix32->type); | ||
1011 | err |= put_user(fix->type_aux, &fix32->type_aux); | ||
1012 | err |= put_user(fix->visual, &fix32->visual); | ||
1013 | err |= put_user(fix->xpanstep, &fix32->xpanstep); | ||
1014 | err |= put_user(fix->ypanstep, &fix32->ypanstep); | ||
1015 | err |= put_user(fix->ywrapstep, &fix32->ywrapstep); | ||
1016 | err |= put_user(fix->line_length, &fix32->line_length); | ||
1017 | |||
1018 | data = (__u32) (unsigned long) fix->mmio_start; | ||
1019 | err |= put_user(data, &fix32->mmio_start); | ||
1020 | |||
1021 | err |= put_user(fix->mmio_len, &fix32->mmio_len); | ||
1022 | err |= put_user(fix->accel, &fix32->accel); | ||
1023 | err |= copy_to_user(fix32->reserved, fix->reserved, | ||
1024 | sizeof(fix->reserved)); | ||
1025 | |||
1026 | return err; | ||
1027 | } | ||
1028 | |||
1029 | static int fb_get_fscreeninfo(struct inode *inode, struct file *file, | ||
1030 | unsigned int cmd, unsigned long arg) | ||
1031 | { | ||
1032 | mm_segment_t old_fs; | ||
1033 | struct fb_fix_screeninfo fix; | ||
1034 | struct fb_fix_screeninfo32 __user *fix32; | ||
1035 | int err; | ||
1036 | |||
1037 | fix32 = compat_ptr(arg); | ||
1038 | |||
1039 | old_fs = get_fs(); | ||
1040 | set_fs(KERNEL_DS); | ||
1041 | err = fb_ioctl(inode, file, cmd, (unsigned long) &fix); | ||
1042 | set_fs(old_fs); | ||
1043 | |||
1044 | if (!err) | ||
1045 | err = do_fscreeninfo_to_user(&fix, fix32); | ||
1046 | |||
1047 | return err; | ||
1048 | } | ||
1049 | |||
936 | static long | 1050 | static long |
937 | fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 1051 | fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
938 | { | 1052 | { |
939 | int fbidx = iminor(file->f_dentry->d_inode); | 1053 | struct inode *inode = file->f_dentry->d_inode; |
1054 | int fbidx = iminor(inode); | ||
940 | struct fb_info *info = registered_fb[fbidx]; | 1055 | struct fb_info *info = registered_fb[fbidx]; |
941 | struct fb_ops *fb = info->fbops; | 1056 | struct fb_ops *fb = info->fbops; |
942 | long ret; | 1057 | long ret = -ENOIOCTLCMD; |
943 | 1058 | ||
944 | if (fb->fb_compat_ioctl == NULL) | ||
945 | return -ENOIOCTLCMD; | ||
946 | lock_kernel(); | 1059 | lock_kernel(); |
947 | ret = fb->fb_compat_ioctl(file, cmd, arg, info); | 1060 | switch(cmd) { |
1061 | case FBIOGET_VSCREENINFO: | ||
1062 | case FBIOPUT_VSCREENINFO: | ||
1063 | case FBIOPAN_DISPLAY: | ||
1064 | case FBIOGET_CON2FBMAP: | ||
1065 | case FBIOPUT_CON2FBMAP: | ||
1066 | arg = (unsigned long) compat_ptr(arg); | ||
1067 | case FBIOBLANK: | ||
1068 | ret = fb_ioctl(inode, file, cmd, arg); | ||
1069 | break; | ||
1070 | |||
1071 | case FBIOGET_FSCREENINFO: | ||
1072 | ret = fb_get_fscreeninfo(inode, file, cmd, arg); | ||
1073 | break; | ||
1074 | |||
1075 | case FBIOGETCMAP: | ||
1076 | case FBIOPUTCMAP: | ||
1077 | ret = fb_getput_cmap(inode, file, cmd, arg); | ||
1078 | break; | ||
1079 | |||
1080 | default: | ||
1081 | if (fb->fb_compat_ioctl) | ||
1082 | ret = fb->fb_compat_ioctl(file, cmd, arg, info); | ||
1083 | break; | ||
1084 | } | ||
948 | unlock_kernel(); | 1085 | unlock_kernel(); |
949 | return ret; | 1086 | return ret; |
950 | } | 1087 | } |