SmartAudio/lichee/brandy/u-boot-2014.07/common/cmd_sunxi_bmp.c

869 lines
22 KiB
C
Executable File

/*
* (C) Copyright 2002
* Detlev Zundel, DENX Software Engineering, dzu@denx.de.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
/*
* BMP handling routines
*/
#include <common.h>
#include <bmp_layout.h>
#include <command.h>
#include <malloc.h>
#include <sunxi_bmp.h>
#include <sunxi_board.h>
#include <sunxi_advert.h>
#include <sys_partition.h>
#include <fdt_support.h>
static int sunxi_bmp_probe_info (uint addr);
static int sunxi_bmp_show(sunxi_bmp_store_t bmp_info);
DECLARE_GLOBAL_DATA_PTR;
/*
* Allocate and decompress a BMP image using gunzip().
*
* Returns a pointer to the decompressed image data. Must be freed by
* the caller after use.
*
* Returns NULL if decompression failed, or if the decompressed data
* didn't contain a valid BMP signature.
*/
static int do_sunxi_bmp_info(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
{
uint addr;
if(argc == 2)
{
/* use argument only*/
addr = simple_strtoul(argv[1], NULL, 16);
debug("bmp addr=%x\n", addr);
}
else if(argc == 3)
{
char load_addr[8];
char filename[32];
char *const bmp_argv[6] = { "fatload", "sunxi_flash", "0:0", load_addr, filename, NULL };
addr = simple_strtoul(argv[1], NULL, 16);
memcpy(load_addr, argv[1], 8);
memset(filename, 0, 32);
memcpy(filename, argv[2], strlen(argv[2]));
#ifdef DEBUG
int i;
for(i=0;i<6;i++)
{
printf("argv[%d] = %s\n", i, argv[i]);
}
#endif
if(do_fat_fsload(0, 0, 5, bmp_argv))
{
printf("sunxi bmp info error : unable to open bmp file %s\n", argv[2]);
return cmd_usage(cmdtp);
}
}
else
{
return cmd_usage(cmdtp);
}
return (sunxi_bmp_probe_info(addr));
}
U_BOOT_CMD(
sunxi_bmp_info, 3, 1, do_sunxi_bmp_info,
"manipulate BMP image data",
"only one para : the address where the bmp stored\n"
);
static int do_sunxi_bmp_display(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
{
uint addr;
uint de_addr;
sunxi_bmp_store_t bmp_info;
if(argc == 2)
{
/* use argument only*/
addr = simple_strtoul(argv[1], NULL, 16);
#if defined(CONFIG_SUNXI_LOGBUFFER)
de_addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size - SUNXI_DISPLAY_FRAME_BUFFER_SIZE;
#else
de_addr = SUNXI_DISPLAY_FRAME_BUFFER_ADDR;
#endif
}
else if(argc == 3)
{
addr = simple_strtoul(argv[1], NULL, 16);
de_addr = simple_strtoul(argv[2], NULL, 16);
}
else if(argc == 4)
{
char load_addr[8];
char filename[32];
char *const bmp_argv[6] = { "fatload", "sunxi_flash", "0:0", load_addr, filename, NULL };
addr = simple_strtoul(argv[1], NULL, 16);
memcpy(load_addr, argv[1], 8);
memset(filename, 0, 32);
memcpy(filename, argv[3], strlen(argv[3]));
de_addr = simple_strtoul(argv[2], NULL, 16);
#ifdef DEBUG
int i;
for(i=0;i<6;i++)
{
printf("argv[%d] = %s\n", i, argv[i]);
}
#endif
if(do_fat_fsload(0, 0, 5, bmp_argv))
{
printf("sunxi bmp info error : unable to open bmp file %s\n", argv[2]);
return cmd_usage(cmdtp);
}
}
else
{
return cmd_usage(cmdtp);
}
if(de_addr < CONFIG_SYS_SDRAM_BASE)
{
#if defined(CONFIG_SUNXI_LOGBUFFER)
de_addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size - SUNXI_DISPLAY_FRAME_BUFFER_SIZE;
#else
de_addr = SUNXI_DISPLAY_FRAME_BUFFER_ADDR;
#endif
}
debug("bmp addr %x, display addr %x\n", addr, de_addr);
bmp_info.buffer = (void *)de_addr;
if(!sunxi_bmp_decode(addr, &bmp_info))
{
debug("decode bmp ok\n");
return sunxi_bmp_show(bmp_info);
}
debug("decode bmp error\n");
return -1;
}
U_BOOT_CMD(
sunxi_bmp_show, 4, 1, do_sunxi_bmp_display,
"manipulate BMP image data",
"sunxi_bmp_display addr [de addr]\n"
"parameters 1 : the address where the bmp stored\n"
"parameters 2 : option para, the address where the bmp display\n"
);
#ifdef CONFIG_BOOT_GUI
int show_bmp_on_fb(char *bmp_head_addr, unsigned int fb_id)
{
bmp_image_t *bmp = (bmp_image_t *)bmp_head_addr;
struct canvas *cv = NULL;
char *src_addr;
int src_width, src_height, src_stride, src_cp_bytes;
char *dst_addr_b, *dst_addr_e;
rect_t dst_crop;
int need_set_bg = 0;
cv = fb_lock(fb_id);
if ((NULL == cv) || (NULL == cv->base)) {
printf("cv=%p, base= %p\n", cv, (cv != NULL) ? cv->base : 0x0);
goto err_out;
}
if ((bmp->header.signature[0] != 'B') ||
(bmp->header.signature[1] != 'M')) {
printf("this is not a bmp picture\n");
goto err_out;
}
if ((24 != bmp->header.bit_count) && (32 != bmp->header.bit_count)) {
printf("no support %dbit bmp\n", bmp->header.bit_count);
goto err_out;
}
src_width = bmp->header.width;
if (bmp->header.height & 0x80000000)
src_height = -bmp->header.height;
else
src_height = bmp->header.height;
if ((src_width > cv->width) || (src_height > cv->height)) {
printf("no support big size bmp[%dx%d] on fb[%dx%d]\n",
src_width, src_height, cv->width, cv->height);
goto err_out;
}
src_cp_bytes = src_width * bmp->header.bit_count >> 3;
src_stride = ((src_width * bmp->header.bit_count + 31) >> 5) << 2;
src_addr = (char *)(bmp_head_addr + bmp->header.data_offset);
if (!(bmp->header.height & 0x80000000)) {
src_addr += (src_stride * (src_height - 1));
src_stride = -src_stride;
}
dst_crop.left = (cv->width - src_width) >> 1;
dst_crop.right = dst_crop.left + src_width;
dst_crop.top = (cv->height - src_height) >> 1;
dst_crop.bottom = dst_crop.top + src_height;
dst_addr_b = (char *)cv->base + cv->stride * dst_crop.top +
(dst_crop.left * cv->bpp >> 3);
dst_addr_e = dst_addr_b + cv->stride * src_height;
need_set_bg = cv->set_interest_region(cv, &dst_crop, 1, NULL);
if (0 != need_set_bg) {
if (src_width != cv->width) {
debug("memset full fb\n");
memset((void *)(cv->base), 0, cv->stride * cv->height);
} else if (0 != dst_crop.top) {
debug("memset top fb\n");
memset((void *)(cv->base), 0,
cv->stride * dst_crop.top);
}
}
if (cv->bpp == bmp->header.bit_count) {
for (; dst_addr_b != dst_addr_e; dst_addr_b += cv->stride) {
memcpy((void *)dst_addr_b, (void *)src_addr,
src_cp_bytes);
src_addr += src_stride;
}
} else {
if ((24 == bmp->header.bit_count) && (32 == cv->bpp)) {
for (; dst_addr_b != dst_addr_e;
dst_addr_b += cv->stride) {
int *d = (int *)dst_addr_b;
char *c_b = src_addr;
char *c_end = c_b + src_cp_bytes;
for (; c_b < c_end;) {
*d++ = 0xFF000000 |
((*(c_b + 2)) << 16) |
((*(c_b + 1)) << 8) | (*c_b);
c_b += 3;
}
src_addr += src_stride;
}
} else {
printf("no support %dbit bmp picture on %dbit fb\n",
bmp->header.bit_count, cv->bpp);
}
}
if (0 != need_set_bg) {
if ((cv->height != dst_crop.bottom) &&
(src_width == cv->width)) {
debug("memset bottom fb\n");
memset(
(void *)(cv->base + cv->stride * dst_crop.bottom),
0, cv->stride * (cv->height - dst_crop.bottom));
}
}
if (32 == cv->bpp)
fb_set_alpha_mode(fb_id, FB_GLOBAL_ALPHA_MODE, 0xFF);
fb_unlock(fb_id, NULL, 1);
save_disp_cmd();
return 0;
err_out:
if (NULL != cv)
fb_unlock(fb_id, NULL, 0);
return -1;
}
int sunxi_bmp_display(char *name)
{
int ret = 0;
char *argv[6];
char bmp_head[32];
char bmp_name[32];
char *bmp_head_addr = (char *)CONFIG_SYS_SDRAM_BASE;
if (NULL != bmp_head_addr) {
sprintf(bmp_head, "%lx", (ulong)bmp_head_addr);
} else {
printf("sunxi bmp: alloc buffer for %s fail\n", name);
return -1;
}
strncpy(bmp_name, name, sizeof(bmp_name));
printf("bmp_name=%s\n", bmp_name);
argv[0] = "fatload";
argv[1] = "sunxi_flash";
#ifdef CONFIG_GPT_SUPPORT
argv[2] = "1:0";
#else
argv[2] = "0:0";
#endif
argv[3] = bmp_head;
argv[4] = bmp_name;
argv[5] = NULL;
if (do_fat_fsload(0, 0, 5, argv)) {
printf("sunxi bmp info error : unable to open logo file %s\n", argv[4]);
return -1;
}
ret = show_bmp_on_fb(bmp_head_addr, FB_ID_0);
if (0 != ret)
printf("show bmp on fb failed !%d\n", ret);
return ret;
}
int sunxi_bmp_dipslay_screen(sunxi_bmp_store_t bmp_info)
{
return show_bmp_on_fb(bmp_info.buffer, FB_ID_0);
}
#else
int bmp_buffer_change2Gray(sunxi_bmp_store_t *bmp_info, char *dst_buf)
{
int ret = 1;
if (bmp_info->bit == 24) {
int i, j;
char *tmp;
tmp = bmp_info->buffer;
for (i = 0; i < bmp_info->y; i++) {
for (j = 0; j < bmp_info->x; j++) {
*dst_buf = (unsigned char) (0.299 * tmp[0] + 0.587 * tmp[1] + 0.114 * tmp[2]); /* set Y */
dst_buf++;
tmp += 3;
}
}
} else if (bmp_info->bit == 32) {
int i, j;
char *tmp;
tmp = bmp_info->buffer;
for (i = 0; i < bmp_info->y; i++) {
for (j = 0; j < bmp_info->x; j++) {
*dst_buf = (unsigned char) (0.299 * tmp[0] + 0.587 * tmp[1] + 0.114 * tmp[2]); /* set Y */
dst_buf++;
tmp += 4;
}
}
} else
ret = -1;
return ret;
}
#if 0
int bmp_buffer_change2Gray(sunxi_bmp_store_t *bmp_info, char *dst_buf)
{
int i, j;
unsigned char *RgbPixe;
unsigned char RgbPixel[800 * 600 * 4] = {0};
/*unsigned char RgbPixel24[800 * 600 * 3] = {0};*/
unsigned char YuvPixel24[800 * 600 * 4] = {0};
RgbPixe = RgbPixel;
/* fread(RgbPixel, sizeof(char), 800 * 600 * 3, bmp_info);*/
memcpy(RgbPixel, bmp_info->buffer, 800 * 600 * 4);
for (i = 0; i < 600; i++) {
for (j = 0; j < 800; j++) {
if (bmp_info->bit == 24) {
YuvPixel24[i * 800 + j] = (unsigned char) (0.299 * RgbPixe[0] + 0.587 * RgbPixe[1] + 0.114 * RgbPixe[2]); /* set Y */
YuvPixel24[(i + 600) * 800 + j] = (unsigned char) (0.5 * RgbPixe[0] - 0.4187 * RgbPixe[1] - 0.0813 * RgbPixe[2] + 128); /* set U */
YuvPixel24[(i + 2 * 600) * 800 + j] = (unsigned char)(-0.1687 * RgbPixe[0] - 0.3313 * RgbPixe[1] + 0.5 * RgbPixe[2] + 128); /* set V */
RgbPixe = RgbPixe + 3 ;
} else if (bmp_info->bit == 32) {
YuvPixel24[i * 800 + j] = (unsigned char) (0.299 * RgbPixe[0] + 0.587 * RgbPixe[1] + 0.114 * RgbPixe[2]); /* set Y */
YuvPixel24[(i + 600) * 800 + j] = (unsigned char) (0.5 * RgbPixe[0] - 0.4187 * RgbPixe[1] - 0.0813 * RgbPixe[2] + 128); /* set U */
YuvPixel24[(i + 2 * 600) * 800 + j] = (unsigned char)(-0.1687 * RgbPixe[0] - 0.3313 * RgbPixe[1] + 0.5 * RgbPixe[2] + 128); /* set V */
YuvPixel24[(i + 3 * 600) * 800 + j] = (unsigned char)(1.0 * RgbPixe[3]); /* set A */
RgbPixe = RgbPixe + 4 ;
}
}
}
/*fwrite(YuvPixel, sizeof(char), 600*800, dst_buf);*/
memcpy(dst_buf, YuvPixel24, 600*800);
return 1; /* 1 means it is done well */
}
#endif
int sunxi_Eink_Get_bmp_buffer(char *name, char *bmp_gray_buf)
{
int ret;
sunxi_bmp_store_t bmp_info;
char bmp_addr[32] = {0};
char bmp_name[32];
char *bmp_argv[6] = {"fatload", "sunxi_flash", "0:0", "00000000", bmp_name, NULL};
#ifdef CONFIG_GPT_SUPPORT
bmp_argv[2] = "1:0";
#endif
if (bmp_gray_buf == NULL) {
printf("sunxi_Eink_Get_bmp_buffer: bmp_gray_buffor is null for %s\n", name);
return -1;
}
sprintf(bmp_addr, "%lx", (ulong)bmp_gray_buf);
bmp_argv[3] = bmp_addr;
memset(bmp_name, 0, 32);
strcpy(bmp_name, name);
if (do_fat_fsload(0, 0, 5, bmp_argv)) {
printf("sunxi_Eink_Get_bmp_buffer error : unable to open logo file %s\n", bmp_argv[4]);
return -1;
}
#if defined(CONFIG_SUNXI_LOGBUFFER)
bmp_info.buffer = (void *)(CONFIG_SYS_SDRAM_BASE + gd->ram_size - SUNXI_DISPLAY_FRAME_BUFFER_SIZE);
#else
bmp_info.buffer = (void *)(SUNXI_DISPLAY_FRAME_BUFFER_ADDR);
#endif
if (sunxi_bmp_decode((ulong)bmp_gray_buf, &bmp_info)) {
debug("decode bmp fail\n");
return -1;
}
ret = bmp_buffer_change2Gray(&bmp_info, bmp_gray_buf);
return ret;
}
int sunxi_bmp_display(char *name)
{
sunxi_bmp_store_t bmp_info;
char *argv[6];
char bmp_head[32];
char bmp_name[32] = {0};
ulong bmp_buff = CONFIG_SYS_SDRAM_BASE;
int ret = -1;
/* set bmp decode addr is CONFIG_SYS_SDRAM_BASE */
sprintf(bmp_head, "%lx", (ulong)bmp_buff);
strncpy(bmp_name, name, sizeof(bmp_name));
argv[0] = "fatload";
argv[1] = "sunxi_flash";
#ifdef CONFIG_GPT_SUPPORT
argv[2] = "1:0";
#else
argv[2] = "0:0";
#endif
argv[3] = bmp_head;
argv[4] = bmp_name;
argv[5] = NULL;
if (do_fat_fsload(0, 0, 5, argv))
{
pr_error("unable to open logo file %s\n", argv[4]);
return -1;
}
#if defined(CONFIG_SUNXI_LOGBUFFER)
bmp_info.buffer = (void *)(CONFIG_SYS_SDRAM_BASE + gd->ram_size - SUNXI_DISPLAY_FRAME_BUFFER_SIZE);
#else
bmp_info.buffer = (void *)(SUNXI_DISPLAY_FRAME_BUFFER_ADDR);
#endif
pr_msg("bmp file buffer: 0x%lx, bmp_info.buffer: %lx\n",
bmp_buff, (ulong)bmp_info.buffer);
if (sunxi_bmp_decode(bmp_buff, &bmp_info))
return -1;
ret = sunxi_bmp_show(bmp_info);
return ret;
}
int sunxi_bmp_display_mem(unsigned char *source, sunxi_bmp_store_t *bmp_info)
{
int ret = -1;
#if defined(CONFIG_SUNXI_LOGBUFFER)
bmp_info->buffer = (void *)(CONFIG_SYS_SDRAM_BASE + gd->ram_size - SUNXI_DISPLAY_FRAME_BUFFER_SIZE);
#else
bmp_info->buffer = (void *)(SUNXI_DISPLAY_FRAME_BUFFER_ADDR);
#endif
pr_notice("bmp file buffer: 0x%lx, bmp_info.buffer: %lx\n",(ulong)source,(ulong)bmp_info->buffer);
ret = sunxi_bmp_decode((ulong)source, bmp_info);
if (!ret)
debug("decode bmp ok\n");
return ret;
}
int sunxi_bmp_dipslay_screen(sunxi_bmp_store_t bmp_info)
{
return sunxi_bmp_show(bmp_info);
}
#endif
/*
* Subroutine: bmp_info
*
* Description: Show information about bmp file in memory
*
* Inputs: addr address of the bmp file
*
* Return: None
*
*/
static int sunxi_bmp_probe_info(uint addr)
{
bmp_image_t *bmp=(bmp_image_t *)addr;
if((bmp->header.signature[0]!='B') || (bmp->header.signature[1]!='M'))
{
printf("this is not a bmp picture\n");
return -1;
}
debug("bmp picture dectede\n");
printf("Image size : %d x %d\n", bmp->header.width, (bmp->header.height & 0x80000000) ? (-bmp->header.height):(bmp->header.height));
printf("Bits per pixel: %d\n", bmp->header.bit_count);
return(0);
}
/*
* Subroutine: bmp_display
*
* Description: Display bmp file located in memory
*
* Inputs: addr address of the bmp file
*
* Return: None
*
*/
int sunxi_bmp_decode(unsigned long addr, sunxi_bmp_store_t *bmp_info)
{
char *tmp_buffer;
char *bmp_data;
int zero_num = 0;
bmp_image_t *bmp = (bmp_image_t *)addr;
int x, y, bmp_bpix;
int tmp;
if((bmp->header.signature[0]!='B') || (bmp->header.signature[1] !='M'))
{
printf("this is not a bmp picture\n");
return -1;
}
debug("bmp dectece\n");
bmp_bpix = bmp->header.bit_count/8;
if((bmp_bpix != 3) && (bmp_bpix != 4))
{
printf("no support bmp picture without bpix 24 or 32\n");
return -1;
}
if(bmp_bpix ==3)
{
zero_num = (4 - ((3*bmp->header.width) % 4))&3;
}
debug("bmp bitcount %d\n", bmp->header.bit_count);
x = bmp->header.width;
y = (bmp->header.height & 0x80000000) ? (-bmp->header.height):(bmp->header.height);
debug("bmp x = %x, bmp y = %x\n", x, y);
tmp = bmp->header.height;
if (0 == (bmp->header.height & 0x80000000))
bmp->header.height = (-bmp->header.height);
memcpy(bmp_info->buffer, bmp, sizeof(bmp_header_t));
bmp_info->buffer += sizeof(bmp_header_t);
bmp->header.height = tmp;
tmp_buffer = (char *)bmp_info->buffer;
bmp_data = (char *)(addr + bmp->header.data_offset);
if(bmp->header.height & 0x80000000)
{
if(zero_num == 0)
{
memcpy(tmp_buffer,bmp_data,x*y*bmp_bpix);
}
else
{
int i, line_bytes, real_line_byte;
char *src;
line_bytes = (x * bmp_bpix) + zero_num;
real_line_byte = x * bmp_bpix;
for(i=0; i<y; i++)
{
src = bmp_data + i*line_bytes;
memcpy(tmp_buffer, src, real_line_byte);
tmp_buffer += real_line_byte;
}
}
}
else
{
uint i, line_bytes, real_line_byte;
char *src;
line_bytes = (x * bmp_bpix) + zero_num;
real_line_byte = x * bmp_bpix;
for(i=0; i<y; i++)
{
src = bmp_data + (y - i - 1) * line_bytes;
memcpy(tmp_buffer, src, real_line_byte);
tmp_buffer += real_line_byte;
}
}
bmp_info->x = x;
bmp_info->y = y;
bmp_info->bit = bmp->header.bit_count;
//flush_cache((uint)bmp_info->buffer, x * y * bmp_bpix);
flush_cache((uint)bmp_info->buffer-sizeof(bmp_header_t) , x * y * bmp_bpix+sizeof(bmp_header_t));
return 0;
}
static int sunxi_bmp_show(sunxi_bmp_store_t bmp_info)
{
debug("begin to set framebuffer\n");
if(board_display_framebuffer_set(bmp_info.x, bmp_info.y, bmp_info.bit, (void *)bmp_info.buffer))
{
printf("sunxi bmp display error : set frame buffer error\n");
return -2;
}
debug("begin to show layer\n");
board_display_show(0);
debug("bmp display finish\n");
return 0;
}
static int fat_read_file_ex(char *fatname, char *filename, char *addr)
{
char file_name[32];
char fat_name[32];
char partition[32];
int partition_num = -1;
char *bmp_buff = NULL;
char bmp_addr[32] = {0};
memset(file_name, 0, 32);
strcpy(file_name, filename);
memset(fat_name, 0, 32);
strcpy(fat_name, fatname);
partition_num = sunxi_partition_get_partno_byname(fat_name);
if (partition_num < 0) {
printf("[boot disp] can not find the partition %s\n", fat_name);
return -1;
}
sprintf(partition, "%x:0", partition_num);
bmp_buff = addr;
if (bmp_buff == NULL) {
printf("sunxi bmp: alloc buffer fail\n");
return -1;
}
char *bmp_argv[6] = {"fatload", "sunxi_flash", "0:0",
"00000000", file_name, NULL};
bmp_argv[2] = partition;
sprintf(bmp_addr, "%lx", (ulong)bmp_buff);
bmp_argv[3] = bmp_addr;
if (do_fat_fsload(0, 0, 5, bmp_argv)) {
printf("sunxi bmp info error : unable to open logo file %s\n",
bmp_argv[1]);
return -1;
}
return 0;
}
static int sunxi_advert_verify_head(struct __advert_head *adv_head)
{
char *addr = (char *)CONFIG_SYS_SDRAM_BASE;
if ((0 > fat_read_file_ex("Reserve0", "advert.crc", addr))) {
return -1;
};
memcpy((u32 *)adv_head, (u32 *)addr, sizeof(*adv_head));
if (memcmp((char *)(adv_head->magic), ADVERT_MAGIC,
strlen(ADVERT_MAGIC))) {
printf("advert magic not equal,%s\n",
(char *)(adv_head->magic));
return -1;
}
if ((SUNXI_DISPLAY_FRAME_BUFFER_SIZE < adv_head->length) ||
(0 == adv_head->length)) {
printf("advert length=%d to big or to short\n",
adv_head->length);
return -1;
}
return 0;
}
static __s32 check_sum(void *mem_base, __u32 size, __u32 src_sum)
{
__u32 *buf = (__u32 *)mem_base;
__u32 count = 0;
__u32 sum = 0;
__u32 last = 0;
__u32 curlen = 0;
__s32 i = 0;
count = size >> 2;
do {
sum += *buf++;
sum += *buf++;
sum += *buf++;
sum += *buf++;
} while ((count -= 4) > (4 - 1));
for (i = 0; i < count; i++)
sum += *buf++;
curlen = size % 4;
if ((size & 0x03) != 0) {
memcpy(&last, mem_base + size - curlen, curlen);
sum += last;
}
if (sum == src_sum) {
return 0;
} else {
printf("err: sum=%x; src_sum=%x\n", sum, src_sum);
return -1;
}
}
int sunxi_advert_logo_load(char *fatname, char *filename)
{
struct __advert_head advert_head;
if (0 > sunxi_advert_verify_head(&advert_head))
return -1;
if ((0 > fat_read_file_ex("Reserve0", "advert.bmp",
(char *)CONFIG_SYS_SDRAM_BASE)) ||
(0 > check_sum((u32 *)CONFIG_SYS_SDRAM_BASE, advert_head.length,
advert_head.check_sum))) {
return -1;
}
return 0;
}
int sunxi_advert_display(char *fatname, char *filename)
{
struct __advert_head advert_head;
if (0 > sunxi_advert_verify_head(&advert_head))
return -1;
if ((0 > fat_read_file_ex("Reserve0", "advert.bmp",
(char *)CONFIG_SYS_SDRAM_BASE)) ||
(0 > check_sum((u32 *)CONFIG_SYS_SDRAM_BASE, advert_head.length,
advert_head.check_sum))) {
return -1;
}
#ifdef CONFIG_BOOT_GUI
return show_bmp_on_fb((char *)CONFIG_SYS_SDRAM_BASE, FB_ID_0);
#else
sunxi_bmp_store_t bmp_info;
#if defined(CONFIG_SUNXI_LOGBUFFER)
bmp_info.buffer = (void *)(CONFIG_SYS_SDRAM_BASE + gd->ram_size -
SUNXI_DISPLAY_FRAME_BUFFER_SIZE);
#else
bmp_info.buffer = (void *)(SUNXI_DISPLAY_FRAME_BUFFER_ADDR);
#endif
debug("check_sum advert bmp ok\n");
if (!sunxi_bmp_decode(CONFIG_SYS_SDRAM_BASE, &bmp_info)) {
debug("decode bmp ok\n");
return sunxi_bmp_show(bmp_info);
}
return -1;
#endif /*#ifdef CONFIG_BOOT_GUI*/
}
int sunxi_bmp_load(char *name)
{
int ret = 0;
char *argv[6];
char bmp_head[32];
char bmp_name[32];
char *bmp_head_addr = (char *)CONFIG_SYS_SDRAM_BASE;
#ifdef ENABLE_ADVERT_PICTURE
/*if no advert.bmp in Reserve0, will not search bootlogo.bmp in
* bootloader partition */
if (!strcmp(name, "bootlogo.bmp")) {
if (!sunxi_advert_logo_load("Reserve0", "advert.bmp"))
return 0;
else
return -1;
}
#endif
if (NULL != bmp_head_addr) {
sprintf(bmp_head, "%lx", (ulong)bmp_head_addr);
} else {
printf("sunxi bmp: alloc buffer for %s fail\n", name);
return -1;
}
strncpy(bmp_name, name, sizeof(bmp_name));
printf("bmp_name=%s\n", bmp_name);
argv[0] = "fatload";
argv[1] = "sunxi_flash";
argv[2] = "0:0";
argv[3] = bmp_head;
argv[4] = bmp_name;
argv[5] = NULL;
if (do_fat_fsload(0, 0, 5, argv)) {
printf("sunxi bmp info error : unable to open logo file %s\n",
argv[4]);
return -1;
}
return ret;
}
int do_sunxi_logo(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
{
return sunxi_bmp_display("bootlogo.bmp");
}
U_BOOT_CMD(
logo, 1, 0, do_sunxi_logo,
"show default logo",
"no args\n"
);