cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

fbcmap.c (8611B)


      1/*
      2 *  linux/drivers/video/fbcmap.c -- Colormap handling for frame buffer devices
      3 *
      4 *	Created 15 Jun 1997 by Geert Uytterhoeven
      5 *
      6 *	2001 - Documented with DocBook
      7 *	- Brad Douglas <brad@neruo.com>
      8 *
      9 *  This file is subject to the terms and conditions of the GNU General Public
     10 *  License.  See the file COPYING in the main directory of this archive for
     11 *  more details.
     12 */
     13
     14#include <linux/string.h>
     15#include <linux/module.h>
     16#include <linux/fb.h>
     17#include <linux/slab.h>
     18#include <linux/uaccess.h>
     19
     20static u16 red2[] __read_mostly = {
     21    0x0000, 0xaaaa
     22};
     23static u16 green2[] __read_mostly = {
     24    0x0000, 0xaaaa
     25};
     26static u16 blue2[] __read_mostly = {
     27    0x0000, 0xaaaa
     28};
     29
     30static u16 red4[] __read_mostly = {
     31    0x0000, 0xaaaa, 0x5555, 0xffff
     32};
     33static u16 green4[] __read_mostly = {
     34    0x0000, 0xaaaa, 0x5555, 0xffff
     35};
     36static u16 blue4[] __read_mostly = {
     37    0x0000, 0xaaaa, 0x5555, 0xffff
     38};
     39
     40static u16 red8[] __read_mostly = {
     41    0x0000, 0x0000, 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0xaaaa, 0xaaaa
     42};
     43static u16 green8[] __read_mostly = {
     44    0x0000, 0x0000, 0xaaaa, 0xaaaa, 0x0000, 0x0000, 0x5555, 0xaaaa
     45};
     46static u16 blue8[] __read_mostly = {
     47    0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa
     48};
     49
     50static u16 red16[] __read_mostly = {
     51    0x0000, 0x0000, 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0xaaaa, 0xaaaa,
     52    0x5555, 0x5555, 0x5555, 0x5555, 0xffff, 0xffff, 0xffff, 0xffff
     53};
     54static u16 green16[] __read_mostly = {
     55    0x0000, 0x0000, 0xaaaa, 0xaaaa, 0x0000, 0x0000, 0x5555, 0xaaaa,
     56    0x5555, 0x5555, 0xffff, 0xffff, 0x5555, 0x5555, 0xffff, 0xffff
     57};
     58static u16 blue16[] __read_mostly = {
     59    0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa,
     60    0x5555, 0xffff, 0x5555, 0xffff, 0x5555, 0xffff, 0x5555, 0xffff
     61};
     62
     63static const struct fb_cmap default_2_colors = {
     64    .len=2, .red=red2, .green=green2, .blue=blue2
     65};
     66static const struct fb_cmap default_8_colors = {
     67    .len=8, .red=red8, .green=green8, .blue=blue8
     68};
     69static const struct fb_cmap default_4_colors = {
     70    .len=4, .red=red4, .green=green4, .blue=blue4
     71};
     72static const struct fb_cmap default_16_colors = {
     73    .len=16, .red=red16, .green=green16, .blue=blue16
     74};
     75
     76
     77
     78/**
     79 *	fb_alloc_cmap_gfp - allocate a colormap
     80 *	@cmap: frame buffer colormap structure
     81 *	@len: length of @cmap
     82 *	@transp: boolean, 1 if there is transparency, 0 otherwise
     83 *	@flags: flags for kmalloc memory allocation
     84 *
     85 *	Allocates memory for a colormap @cmap.  @len is the
     86 *	number of entries in the palette.
     87 *
     88 *	Returns negative errno on error, or zero on success.
     89 *
     90 */
     91
     92int fb_alloc_cmap_gfp(struct fb_cmap *cmap, int len, int transp, gfp_t flags)
     93{
     94	int size = len * sizeof(u16);
     95	int ret = -ENOMEM;
     96
     97	flags |= __GFP_NOWARN;
     98
     99	if (cmap->len != len) {
    100		fb_dealloc_cmap(cmap);
    101		if (!len)
    102			return 0;
    103
    104		cmap->red = kzalloc(size, flags);
    105		if (!cmap->red)
    106			goto fail;
    107		cmap->green = kzalloc(size, flags);
    108		if (!cmap->green)
    109			goto fail;
    110		cmap->blue = kzalloc(size, flags);
    111		if (!cmap->blue)
    112			goto fail;
    113		if (transp) {
    114			cmap->transp = kzalloc(size, flags);
    115			if (!cmap->transp)
    116				goto fail;
    117		} else {
    118			cmap->transp = NULL;
    119		}
    120	}
    121	cmap->start = 0;
    122	cmap->len = len;
    123	ret = fb_copy_cmap(fb_default_cmap(len), cmap);
    124	if (ret)
    125		goto fail;
    126	return 0;
    127
    128fail:
    129	fb_dealloc_cmap(cmap);
    130	return ret;
    131}
    132
    133int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp)
    134{
    135	return fb_alloc_cmap_gfp(cmap, len, transp, GFP_ATOMIC);
    136}
    137
    138/**
    139 *      fb_dealloc_cmap - deallocate a colormap
    140 *      @cmap: frame buffer colormap structure
    141 *
    142 *      Deallocates a colormap that was previously allocated with
    143 *      fb_alloc_cmap().
    144 *
    145 */
    146
    147void fb_dealloc_cmap(struct fb_cmap *cmap)
    148{
    149	kfree(cmap->red);
    150	kfree(cmap->green);
    151	kfree(cmap->blue);
    152	kfree(cmap->transp);
    153
    154	cmap->red = cmap->green = cmap->blue = cmap->transp = NULL;
    155	cmap->len = 0;
    156}
    157
    158/**
    159 *	fb_copy_cmap - copy a colormap
    160 *	@from: frame buffer colormap structure
    161 *	@to: frame buffer colormap structure
    162 *
    163 *	Copy contents of colormap from @from to @to.
    164 */
    165
    166int fb_copy_cmap(const struct fb_cmap *from, struct fb_cmap *to)
    167{
    168	unsigned int tooff = 0, fromoff = 0;
    169	size_t size;
    170
    171	if (to->start > from->start)
    172		fromoff = to->start - from->start;
    173	else
    174		tooff = from->start - to->start;
    175	if (fromoff >= from->len || tooff >= to->len)
    176		return -EINVAL;
    177
    178	size = min_t(size_t, to->len - tooff, from->len - fromoff);
    179	if (size == 0)
    180		return -EINVAL;
    181	size *= sizeof(u16);
    182
    183	memcpy(to->red+tooff, from->red+fromoff, size);
    184	memcpy(to->green+tooff, from->green+fromoff, size);
    185	memcpy(to->blue+tooff, from->blue+fromoff, size);
    186	if (from->transp && to->transp)
    187		memcpy(to->transp+tooff, from->transp+fromoff, size);
    188	return 0;
    189}
    190
    191int fb_cmap_to_user(const struct fb_cmap *from, struct fb_cmap_user *to)
    192{
    193	unsigned int tooff = 0, fromoff = 0;
    194	size_t size;
    195
    196	if (to->start > from->start)
    197		fromoff = to->start - from->start;
    198	else
    199		tooff = from->start - to->start;
    200	if (fromoff >= from->len || tooff >= to->len)
    201		return -EINVAL;
    202
    203	size = min_t(size_t, to->len - tooff, from->len - fromoff);
    204	if (size == 0)
    205		return -EINVAL;
    206	size *= sizeof(u16);
    207
    208	if (copy_to_user(to->red+tooff, from->red+fromoff, size))
    209		return -EFAULT;
    210	if (copy_to_user(to->green+tooff, from->green+fromoff, size))
    211		return -EFAULT;
    212	if (copy_to_user(to->blue+tooff, from->blue+fromoff, size))
    213		return -EFAULT;
    214	if (from->transp && to->transp)
    215		if (copy_to_user(to->transp+tooff, from->transp+fromoff, size))
    216			return -EFAULT;
    217	return 0;
    218}
    219
    220/**
    221 *	fb_set_cmap - set the colormap
    222 *	@cmap: frame buffer colormap structure
    223 *	@info: frame buffer info structure
    224 *
    225 *	Sets the colormap @cmap for a screen of device @info.
    226 *
    227 *	Returns negative errno on error, or zero on success.
    228 *
    229 */
    230
    231int fb_set_cmap(struct fb_cmap *cmap, struct fb_info *info)
    232{
    233	int i, start, rc = 0;
    234	u16 *red, *green, *blue, *transp;
    235	u_int hred, hgreen, hblue, htransp = 0xffff;
    236
    237	red = cmap->red;
    238	green = cmap->green;
    239	blue = cmap->blue;
    240	transp = cmap->transp;
    241	start = cmap->start;
    242
    243	if (start < 0 || (!info->fbops->fb_setcolreg &&
    244			  !info->fbops->fb_setcmap))
    245		return -EINVAL;
    246	if (info->fbops->fb_setcmap) {
    247		rc = info->fbops->fb_setcmap(cmap, info);
    248	} else {
    249		for (i = 0; i < cmap->len; i++) {
    250			hred = *red++;
    251			hgreen = *green++;
    252			hblue = *blue++;
    253			if (transp)
    254				htransp = *transp++;
    255			if (info->fbops->fb_setcolreg(start++,
    256						      hred, hgreen, hblue,
    257						      htransp, info))
    258				break;
    259		}
    260	}
    261	if (rc == 0)
    262		fb_copy_cmap(cmap, &info->cmap);
    263
    264	return rc;
    265}
    266
    267int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *info)
    268{
    269	int rc, size = cmap->len * sizeof(u16);
    270	struct fb_cmap umap;
    271
    272	if (size < 0 || size < cmap->len)
    273		return -E2BIG;
    274
    275	memset(&umap, 0, sizeof(struct fb_cmap));
    276	rc = fb_alloc_cmap_gfp(&umap, cmap->len, cmap->transp != NULL,
    277				GFP_KERNEL);
    278	if (rc)
    279		return rc;
    280	if (copy_from_user(umap.red, cmap->red, size) ||
    281	    copy_from_user(umap.green, cmap->green, size) ||
    282	    copy_from_user(umap.blue, cmap->blue, size) ||
    283	    (cmap->transp && copy_from_user(umap.transp, cmap->transp, size))) {
    284		rc = -EFAULT;
    285		goto out;
    286	}
    287	umap.start = cmap->start;
    288	lock_fb_info(info);
    289	rc = fb_set_cmap(&umap, info);
    290	unlock_fb_info(info);
    291out:
    292	fb_dealloc_cmap(&umap);
    293	return rc;
    294}
    295
    296/**
    297 *	fb_default_cmap - get default colormap
    298 *	@len: size of palette for a depth
    299 *
    300 *	Gets the default colormap for a specific screen depth.  @len
    301 *	is the size of the palette for a particular screen depth.
    302 *
    303 *	Returns pointer to a frame buffer colormap structure.
    304 *
    305 */
    306
    307const struct fb_cmap *fb_default_cmap(int len)
    308{
    309    if (len <= 2)
    310	return &default_2_colors;
    311    if (len <= 4)
    312	return &default_4_colors;
    313    if (len <= 8)
    314	return &default_8_colors;
    315    return &default_16_colors;
    316}
    317
    318
    319/**
    320 *	fb_invert_cmaps - invert all defaults colormaps
    321 *
    322 *	Invert all default colormaps.
    323 *
    324 */
    325
    326void fb_invert_cmaps(void)
    327{
    328    u_int i;
    329
    330    for (i = 0; i < ARRAY_SIZE(red2); i++) {
    331	red2[i] = ~red2[i];
    332	green2[i] = ~green2[i];
    333	blue2[i] = ~blue2[i];
    334    }
    335    for (i = 0; i < ARRAY_SIZE(red4); i++) {
    336	red4[i] = ~red4[i];
    337	green4[i] = ~green4[i];
    338	blue4[i] = ~blue4[i];
    339    }
    340    for (i = 0; i < ARRAY_SIZE(red8); i++) {
    341	red8[i] = ~red8[i];
    342	green8[i] = ~green8[i];
    343	blue8[i] = ~blue8[i];
    344    }
    345    for (i = 0; i < ARRAY_SIZE(red16); i++) {
    346	red16[i] = ~red16[i];
    347	green16[i] = ~green16[i];
    348	blue16[i] = ~blue16[i];
    349    }
    350}
    351
    352
    353    /*
    354     *  Visible symbols for modules
    355     */
    356
    357EXPORT_SYMBOL(fb_alloc_cmap);
    358EXPORT_SYMBOL(fb_dealloc_cmap);
    359EXPORT_SYMBOL(fb_copy_cmap);
    360EXPORT_SYMBOL(fb_set_cmap);
    361EXPORT_SYMBOL(fb_default_cmap);
    362EXPORT_SYMBOL(fb_invert_cmaps);