基础知识
开机 logo 和充电 logo 资源位置
vendor\sprd\release\bmp\unisoc_bmp
根据你的编译选项使用对应 logo bmp
vendor\sprd\release\pac_config\sl9832e_1h10_64b.ini
BootLogo=1@./vendor/sprd/release/bmp/unisoc_bmp/samsung_720_1280_24bit.bmp
Fastboot_Logo=1@./vendor/sprd/release/bmp/unisoc_bmp/samsung_720_1280_24bit.bmp
编译后开机 logo 位置
vendor\sprd\release\IDH\sl9832e_1h10_64b_Natv-user\SHARKLE_9832e_64b_halo
代码流程
正常启动模式和 fastboot 启动模式
最终都是通过 lcd_splash(LOGO_PART); 进行绘制显示 logo
bsp\bootloader\u-boot\common\loader\boot_mode.c
void normal_mode(void) { #ifndef CONFIG_ZEBU vibrator_hw_init(); set_vibrator(1); vlx_nand_boot(BOOT_PART, BACKLIGHT_ON, LCD_ON); #else vlx_nand_boot_zebu(BOOT_PART, BACKLIGHT_ON, LCD_ON); #endif return; } void fastboot_mode(void) { debugf("enter\n"); #ifdef CONFIG_SPLASH_SCREEN extern int drv_lcd_init (void); debug("[LCD] Drawing the logo...\n"); drv_lcd_init(); lcd_splash(LOGO_PART); lcd_enable(); vibrator_hw_init(); set_vibrator(1); extern void set_backlight(uint32_t value); fastboot_lcd_printf(); set_backlight(BACKLIGHT_ON); mdelay(400); set_vibrator(0); #endif #if (defined CONFIG_X86) && (defined CONFIG_MOBILEVISOR) && (defined CONFIG_SPRD_SOC_SP9853I) tos_start_notify(); #endif #ifdef CONFIG_SECBOOT if (get_lock_status() == VBOOT_STATUS_UNLOCK){ debugf("INFO: LOCK FLAG IS : UNLOCK!!!\n"); lcd_printf("\n INFO: LOCK FLAG IS : UNLOCK!!!\n"); } get_secboot_base_from_dt(); #endif do_fastboot(); return; }
BOOT_PART 其实就是 logo 字符串,搜索找到定义位于
bsp\bootloader\u-boot\include\loader_common.h
#define SPL_PART "spl" #define LOGO_PART "logo" #define CHARGER_LOGO_PART "chargelogo" #define BOOT_PART "boot" #define RECOVERY_PART "recovery" #define FACTORY_PART "prodnv" #define PRODUCTINFO_FILE_PATITION "miscdata" #define DT_PART "dt"
继续跟进正常启动模式下,vlx_nand_boot(BOOT_PART, BACKLIGHT_ON, LCD_ON);
bsp\bootloader\u-boot\common\loader\loader_nvm.c
uint32_t uboot_start_time; void vlx_nand_boot(char *kernel_pname, int backlight_set, int lcd_enable) { boot_img_hdr *hdr = (void *)raw_header; char *mode_ptr = NULL; uchar *partition = NULL; int i = 0; int j = 0; int ret = 0; uchar *dt_adr = DT_ADR; uint32_t lcd_init_time; uint32_t backlight_on_time; uint32_t uboot_consume_time; #ifdef CONFIG_SOC_IWHALE2 aon_lpc_config(); #endif wakeup_source_enable(); ap_clk_doze_enable(); #ifdef CONFIG_SPLASH_SCREEN lcd_init_time = SCI_GetTickCount(); printf("lcd start init time:%dms\n", lcd_init_time); if(lcd_enable) { extern void lcd_enable(void); debug("[LCD] Drawing the logo...\n"); drv_lcd_init(); lcd_splash(LOGO_PART); lcd_enable(); } ........
再来看看 lcd_splash(LOGO_PART) 干了啥
bsp\bootloader\u-boot\common\splash.c
int lcd_splash(uchar *logo_part_name) { int x = 0, y = 0, ret; u8 *addr; u8 *s; s = getenv("splashimage"); if (!s) { debugf("%s: failed to get env from splashimage\n"); return -1; } addr = (u8 *) simple_strtoul(s, NULL, 16); ret = splash_screen_prepare(logo_part_name, addr); if (ret) return ret; splash_get_pos(&x, &y); return bmp_display(addr, x, y); }
logo_part_name 值可能是 "logo 或 “chargelogo”,还有显示充电logo的时候
从指定分区中读取出 logo bmp存储地址 addr
其实就是 bmp_image
bsp\bootloader\u-boot\common\cmd_bmp.c
int bmp_display(ulong addr, int x, int y) { int ret; struct bmp_image *bmp = (struct bmp_image *)addr; void *bmp_alloc_addr = NULL; unsigned long len; if (!((bmp->header.signature[0]=='B') && (bmp->header.signature[1]=='M'))) bmp = gunzip_bmp(addr, &len, &bmp_alloc_addr); if (!bmp) { printf("There is no valid bmp file at the given address\n"); return 1; } #if defined(CONFIG_LCD) ret = lcd_display_bitmap((ulong)bmp, x, y); #elif defined(CONFIG_VIDEO) ret = video_display_bitmap((unsigned long)bmp, x, y); #else # error bmp_display() requires CONFIG_LCD or CONFIG_VIDEO #endif if (bmp_alloc_addr) free(bmp_alloc_addr); return ret; }
最终在 lcd 中绘制 logo
bsp\bootloader\u-boot\common\lcd.c
int lcd_display_bitmap(ulong bmp_image, int x, int y) { u8 bmp_bpix; u16 width, height, bmp_width, fb_width, hdr_size; u32 colors; u8 *fb, *bmap, *bmap8; u16 *fb16, *bmap16, *cmap_base = NULL; u32 *fb32; rgb24_t *bmap24; rgb32_t *bmap32; struct bmp_image *bmp = (struct bmp_image *)map_sysmem(bmp_image, 0); struct bmp_color_table_entry *palette = bmp->color_table; ..... switch (bmp_bpix) { case 1: case 8: cmap_base = configuration_get_cmap(); #ifdef CONFIG_LCD_BMP_RLE8 u32 compression = get_unaligned_le32(&bmp->header.compression); debug("compressed %d %d\n", compression, BMP_BI_RLE8); if (compression == BMP_BI_RLE8) { lcd_display_rle8_bitmap(bmp, cmap_base, fb, x, y); break; } #endif if (cmap_base) BMP_TO_FB(fb16, u16, bmap8, u8, PIXEL8_TO_INT16, cmap_base); else BMP_TO_FB(fb16, u16, bmap8, u8, PIXEL16_TO_INT16, palette); break; case 16: BMP_TO_FB(fb16, u16, bmap16, u16, RGB16_TO_INT16); break; case 24: BMP_TO_FB(fb32, u32, bmap24, rgb24_t, RGB24_TO_INT32); break; case 32: BMP_TO_FB(fb32, u32, bmap32, rgb32_t, RGB32_TO_INT32); break; default: break; }; lcd_sync(); return 0; }