rk_fb: logo: get kernel logo addr from protect memory region
authorMark Yao <mark.yao@rock-chips.com>
Thu, 11 Dec 2014 05:49:03 +0000 (13:49 +0800)
committerMark Yao <mark.yao@rock-chips.com>
Thu, 11 Dec 2014 06:09:30 +0000 (14:09 +0800)
Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
drivers/video/rockchip/bmp_helper.c
drivers/video/rockchip/rk_fb.c

index 75e8c3ae1aedd4f9e8d876eb9f586c6224f25c92..aa4f4f072917fb9e1e2707b3b9f048497a19b907 100755 (executable)
@@ -344,6 +344,11 @@ int bmpdecoder(void *bmp_addr, void *pdst, int *width, int *height, int *bits)
 
        memcpy(&header, src, sizeof(header));
        src += sizeof(header);
+
+       if (header.type != 0x4d42) {
+               pr_err("not bmp file type[%x], can't support\n", header.type);
+               return -1;
+       }
        memcpy(&infoheader, src, sizeof(infoheader));
        *width = infoheader.width;
        *height = infoheader.height;
index cf41a1635959398fba88042f9ea63a2c2a07dda5..67a32855eaa1752d74dfac9128518b5f638fc797 100755 (executable)
@@ -24,6 +24,7 @@
 #include <linux/kthread.h>
 #include <linux/fb.h>
 #include <linux/init.h>
+#include <linux/vmalloc.h>
 #include <asm/div64.h>
 #include <linux/uaccess.h>
 #include <linux/rk_fb.h>
@@ -67,16 +68,9 @@ int (*video_data_to_mirroring) (struct fb_info *info, u32 yuv_phy[2]);
 EXPORT_SYMBOL(video_data_to_mirroring);
 #endif
 
-static uint32_t kernel_logo_addr;
-static int __init kernel_logo_setup(char *str)
-{
-       if(str) {
-               sscanf(str, "%x", &kernel_logo_addr);
-       }
-
-       return 0;
-}
-early_param("kernel_logo", kernel_logo_setup);
+extern phys_addr_t uboot_logo_base;
+extern phys_addr_t uboot_logo_size;
+extern phys_addr_t uboot_logo_offset;
 static struct rk_fb_trsm_ops *trsm_lvds_ops;
 static struct rk_fb_trsm_ops *trsm_edp_ops;
 static struct rk_fb_trsm_ops *trsm_mipi_ops;
@@ -4178,17 +4172,50 @@ int rk_fb_register(struct rk_lcdc_driver *dev_drv,
                rk_fb_alloc_buffer(main_fbi, 0);        /* only alloc memory for main fb */
                dev_drv->uboot_logo = support_uboot_display();
 
-               if (kernel_logo_addr) {
+               if (uboot_logo_offset && uboot_logo_base) {
                        struct rk_lcdc_win *win = dev_drv->win[0];
-                       char *addr = phys_to_virt(kernel_logo_addr);
                        int width, height, bits;
+                       phys_addr_t start = uboot_logo_base + uboot_logo_offset;
+                       unsigned int size = uboot_logo_size - uboot_logo_offset;
+                       unsigned int nr_pages;
+                       struct page **pages;
+                       char *vaddr;
+                       int i = 0;
+
+                       nr_pages = size >> PAGE_SHIFT;
+                       pages = kzalloc(sizeof(struct page) * nr_pages,
+                                       GFP_KERNEL);
+                       while (i < nr_pages) {
+                               pages[i] = phys_to_page(start);
+                               start += PAGE_SIZE;
+                               i++;
+                       }
+                       vaddr = vmap(pages, nr_pages, VM_MAP,
+                                       pgprot_writecombine(PAGE_KERNEL));
+                       if (!vaddr) {
+                               pr_err("failed to vmap phy addr %x\n",
+                                       uboot_logo_base + uboot_logo_offset);
+                               return -1;
+                       }
+
+                       if(bmpdecoder(vaddr, main_fbi->screen_base, &width,
+                                     &height, &bits)) {
+                               kfree(pages);
+                               vunmap(vaddr);
+                               return 0;
+                       }
+                       kfree(pages);
+                       vunmap(vaddr);
+                       if (width > main_fbi->var.xres ||
+                           height > main_fbi->var.yres) {
+                               pr_err("ERROR: logo size out of screen range");
+                               return 0;
+                       }
 
-                       bmpdecoder(addr, main_fbi->screen_base,
-                                  &width, &height, &bits);
                        win->area[0].format = rk_fb_data_fmt(0, bits);
                        win->area[0].y_vir_stride = width * bits >> 5;
                        win->area[0].xpos = (main_fbi->var.xres - width) >> 1;
-                       win->area[0].ypos = (main_fbi->var.yres - height) >> 1;;
+                       win->area[0].ypos = (main_fbi->var.yres - height) >> 1;
                        win->area[0].xsize = width;
                        win->area[0].ysize = height;
                        win->area[0].xact = width;