Analysis of the boot LOGO display function in uboot, ubootlogo
Analysis of the boot LOGO display function in uboot
The boot LOGO is essential for the vast majority of electronic products with a display screen. It is the first impression of the product boot. The importance is self-evident. Let's take a look at how this is achieved.
To display the LOGO as soon as possible, you need to be in the boot phase before the system really can get through the display, and this task is mostly to the role of U-BOOT to act, the quanzhi platform is implemented on the android 4.4 platform in u-boot and supports BMP images. There are several steps: first read the image, parse the image data, and then send it to the display part. This is the case. It is simple to say, simple to understand, and the people who actually write it are not easy to understand. Of course, for the platform, not too difficult. Let's take a look!
/*************************************** **************************************** **********************/
Statement: the content of this blog is created at http://blog.csdn.net/edsam49. please refer to it for help. Thank you!
/*************************************** **************************************** **********************/
First, load the image to the memory. For loading, you are familiar with fatload, that is, mounting a fat file system. Read the data of this file from this file system to the specified memory location. Let's look at the code, it's not hard!
char *const bmp_argv[6] = { "fatload", "sunxi_flash", "0", "40000000", bmp_name, NULL };memset(bmp_name, 0, 32);strcpy(bmp_name, name); if(do_fat_fsload(0, 0, 5, bmp_argv)){ printf("sunxi bmp info error : unable to open logo file %s\n", bmp_argv[4]); return -1; }
Second, we need to parse the original image data. Of course, the data format of the BMP image is also determined, and the data header is determined, which is usually 54 bytes. Let's look at the data structure of the data header:
typedef struct bmp_header {/* Header */char signature[2];__u32file_size;__u32reserved;__u32data_offset;/* InfoHeader */__u32size;__u32width;__u32height;__u16planes;__u16bit_count;__u32compression;__u32image_size;__u32x_pixels_per_m;__u32y_pixels_per_m;__u32colors_used;__u32colors_important;/* ColorTable */} __attribute__ ((packed)) bmp_header_t;
What is the output? As follows:
bmp signature[] B, Mbmp file_size 1536054bmp reserved -1bmp data_offset 54bmp size 40bmp width 800bmp height -480bmp planes 1bmp bit_count 32bmp compression 0bmp image_size 1536000bmp x_pixels_per_m 0bmp y_pixels_per_m 0bmp colors_used 0bmp colors_important 0bmp x = 320, bmp y = 1e0
The BMP image I tested has been processed by a tool, that is, the transparency of the image is adjusted. Therefore, the displayed height is a little abnormal and it is better to reverse the image. Take a look at the following processing:
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);printf("bmp x = %x, bmp y = %x\n", x, y);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);
Then it is sent to the display location, because the address of the decoded buffer is determined. You only need to hook up in the parameters of the display layer. Apply for a layer, set parameters, open the layer, it's just a matter of course! The simple code is as follows:
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");
board_display_layer_para_set();board_display_layer_open();
The whole process is indeed like this. In depth, it means that all parts are organically linked up and organized. It's hard to do things that won't be done, and it's hard to do things that will be done! Of course, we should not comment on this case if we don't understand it! Modest and prudent, low-key and potential behavior!