协通编程
  • 前端
  • 后端
  • 移动开发
  • 编程语言
  • Jave
  • Python
  • 人工智能
  • 大数据
  • 数据库
  • 算法结构

RK3568 Android/Linux 系统动态更换 U-Boot/Kernel Logo

1天前 • 移动开发

在Android/Linux开发中,开机 Logo 是设备品牌的标志,经常需要根据不同的客户或应用场景进行定制。对于 RK3568 平台,开机 Logo 通常是打包在固件的 img 文件中,这意味着每次更换 Logo 都需要重新编译并烧录整个固件,这无疑增加了开发的复杂性和浪费时间。本文将介绍一种在 RK3568 Android/Linux 系统中动态更换 U-Boot 和 Kernel Logo 的方法。

系列文章:

Android存储分区与Rockchip平台的分区命名及U-Boot配置

Rockchip u-boot阶段命令行和代码方式读取u盘内容并解析

Rockchip 自定义vendorstorages数据再u-boot通过cmdline给kernel传递数据

RK3568 Android/Linux 系统动态更换 U-Boot/Kernel Logo

参考:

RK3399开启开机logo流程

Android存储分区与Rockchip平台的分区命名及U-Boot配置

需求背景

传统的方法要求我们在每次更换 Logo 时重新编译并烧录固件。这不仅耗时,还是耗时^^ , 所以我们来解决这个问题。

解决方案

目标是在设备已经运行的情况下,动态地更换开机 Logo。为此,我提出了以下方案:

  1. 新建一个分区(或者用已有分区):在这个分区中存放 Logo 文件。当设备启动时,系统会首先尝试从这个分区加载 Logo。如果分区中没有 Logo 文件,系统会回退到默认的 Logo。

  2. 修改 U-Boot 源代码:在 U-Boot 的启动过程中,我们修改了 Logo 的加载逻辑。首先尝试从新建的分区加载 Logo,如果失败,则从默认的资源文件中加载。

实现细节

用已有分区存放logo

首先我们需要确定 Logo 文件的存放位置。由于 system 和 vendor 分区是只读的,而 data 分区在恢复出厂设置后会被清空,所以我决定新建一个分区来存放 Logo 文件(其实我之前就建好了 你们搞的话可以用系统已有分区比如/cache,对应的是mmc 0:a)。

rk3568_r:/ $ df
Filesystem            1K-blocks   Used Available Use% Mounted on
tmpfs                   1001716    824   1000892   1% /dev
tmpfs                   1001716     12   1001704   1% /mnt
/dev/block/mmcblk0p11     11760    144     11132   2% /metadata
/dev/block/dm-0          956964 954064         0 100% /
/dev/block/dm-5          692224     96    692128   1% /mnt/scratch
overlay                  692224     96    692128   1% /system
overlay                  692224     96    692128   1% /vendor
overlay                  692224     96    692128   1% /odm
overlay                  692224     96    692128   1% /product
overlay                  692224     96    692128   1% /system_ext
tmpfs                   1001716      0   1001716   0% /apex
tmpfs                   1001716    264   1001452   1% /linkerconfig
/dev/block/mmcblk0p10    364504    916    351792   1% /cache
/dev/block/mmcblk0p12      3952    364      3468  10% /mnt/private
/dev/block/dm-6        25528320  43916  25353332   1% /data
tmpfs                   1001716      0   1001716   0% /data_mirror
/dev/fuse              25528320  43916  25353332   1% /storage/emulated

在Rockchip平台上,分区的命名和配置通常是由设备树(DTB/DTBO)定义的。例如,mmc 0:c中的0代表第0个存储设备,而c是一个十六进制数,代表12,所以它对应于第12个分区。

OK 选好分区之后,我们在分区底下新建一个文件夹比如custom_logo,放入logo.bmp 和logo_kernel.bmp。

rk3568_r:/mnt/private/custom_logo $ ls
logo.bmp  logo_kernel.bmp
rk3568_r:/mnt/private/custom_logo $

如果你们非要用自定义分区的方法可以在CSDN搜找到,这里不再赘述。

修改 U-Boot 源代码

U-Boot 中加载 Logo 的代码位于 /u-boot/drivers/video/drm/rockchip_display.c 中的 load_bmp_logo 方法。我们的策略是先尝试从新建的分区加载 Logo,如果失败,则从默认的资源文件中加载。对了 我验证过Linux和Android 通用!! 只需要换分区就OK了。

以下是修改后的代码片段:

static int load_bmp_logo(struct logo_info *logo, const char *bmp_name)
{
#define BUFFER_SIZE 128
#ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE
	struct rockchip_logo_cache *logo_cache;
	struct bmp_header *header;
	void *dst = NULL, *pdst;
  char cmd[BUFFER_SIZE] = {"0"};
	int size, len;
	int ret = 0;
	int reserved = 0;

	if (!logo || !bmp_name)
		return -EINVAL;
	logo_cache = find_or_alloc_logo_cache(bmp_name);
	if (!logo_cache)
		return -ENOMEM;

	if (logo_cache->logo.mem) {
		memcpy(logo, &logo_cache->logo, sizeof(*logo));
		return 0;
	}

	header = malloc(RK_BLK_SIZE);
	if (!header)
		return -ENOMEM;

	/*len = rockchip_read_resource_file(header, bmp_name, 0, RK_BLK_SIZE);
	if (len != RK_BLK_SIZE) {
		ret = -EINVAL;
		goto free_header;
	}*/
 
	//---add start
  sprintf(cmd, "ext4load mmc 0:c 0x%p custom_logo/%s %x", header,bmp_name, RK_BLK_SIZE);
  printf("load_bmp_logo 尝试从MMC加载 %s...\n", bmp_name);
  if(run_command(cmd, 0)){
      len = rockchip_read_resource_file(header, bmp_name, 0, RK_BLK_SIZE);
      if (len != RK_BLK_SIZE) {
          printf("load_bmp_logo 从资源文件加载 %s 失败\n", bmp_name);
          ret = -EINVAL;
          goto free_header;
      }
   } 
 //---add end

	logo->bpp = get_unaligned_le16(&header->bit_count);
	logo->width = get_unaligned_le32(&header->width);
	logo->height = get_unaligned_le32(&header->height);
	reserved = get_unaligned_le32(&header->reserved);
	if (logo->height height = -logo->height;
	size = get_unaligned_le32(&header->file_size);
	if (!can_direct_logo(logo->bpp)) {
		if (size > MEMORY_POOL_SIZE) {
			printf("failed to use boot buf as temp bmp buffer\n");
			ret = -ENOMEM;
			goto free_header;
		}
		pdst = get_display_buffer(size);

	} else {
		pdst = get_display_buffer(size);
		dst = pdst;
	}

	/*len = rockchip_read_resource_file(pdst, bmp_name, 0, size);
	if (len != size) {
		printf("failed to load bmp %s\n", bmp_name);
		ret = -ENOENT;
		goto free_header;
	}*/
	//---add start
   memset(cmd, 0, BUFFER_SIZE);
   sprintf(cmd, "ext4load mmc 0:c 0x%p custom_logo/%s %x", pdst, bmp_name, size);
   if(run_command(cmd, 0)){
       len = rockchip_read_resource_file(pdst, bmp_name, 0, size);
       if (len != size) {
           printf("load_bmp_logo 加载bmp %s 失败\n", bmp_name);
           printf("failed to load bmp %s\n", bmp_name);
           ret = -ENOENT;
           goto free_header;
       }
    }
	//---add end
	if (!can_direct_logo(logo->bpp)) {
		int dst_size;
		/*
		 * TODO: force use 16bpp if bpp less than 16;
		 */
		logo->bpp = (logo->bpp bpp;
		dst_size = logo->width * logo->height * logo->bpp >> 3;

		dst = get_display_buffer(dst_size);
		if (!dst) {
			ret = -ENOMEM;
			goto free_header;
		}
		if (bmpdecoder(pdst, dst, logo->bpp)) {
			printf("failed to decode bmp %s\n", bmp_name);
			ret = -EINVAL;
			goto free_header;
		}
		flush_dcache_range((ulong)dst,
				   ALIGN((ulong)dst + dst_size,
					 CONFIG_SYS_CACHELINE_SIZE));

		logo->offset = 0;
		logo->ymirror = 0;
	} else {
		logo->offset = get_unaligned_le32(&header->data_offset);
		if (reserved == BMP_PROCESSED_FLAG)
			logo->ymirror = 0;
		else
			logo->ymirror = 1;
	}
	logo->mem = dst;

	memcpy(&logo_cache->logo, logo, sizeof(*logo));

free_header:

	free(header);

	return ret;
#else
	return -EINVAL;
#endif
}

调试

接入串口 按ctrl+c 进入uboot命令行模式,输入ext4ls mmc 0:c /custom_logo就能看到我们push 进去的2个custom logo图片了 OK 准备工作就绪 刷uboot.img即可。

=> ext4ls mmc 0:c /custom_logo
       4096 .
       4096 ..
          170326 logo.bmp
          170326 logo_kernel.bmp
----------下面3行只是调试显示而已 并没什么关系
=> rockchip_show_bmp logo_kernel.bmp      
load_bmp_logo 尝试从MMC加载 logo_kernel.bmp...
512 bytes read in 44 ms (10.7 KiB/s)
170326 bytes read in 48 ms (3.4 MiB/s)
VOP VP0 enable Smart0[654x258->654x258@633x411] fmt[2] addr[0x7dfa7000]
=> rockchip_show_bmp logo.bmp 
VOP VP0 enable Smart0[654x258->654x258@633x411] fmt[2] addr[0x7df2a000]
=>  rockchip_show_logo
VOP VP0 enable Smart0[654x258->654x258@633x411] fmt[2] addr[0x7df2a000]
=> 

其他发现, 我看日志的时候发现load_kernel_bmp_logo函数根本没走? 然后看了注释才发现 , 好吧没什么卵关系 继续。

/* Note: used only for rkfb kernel driver */
static int load_kernel_bmp_logo(struct logo_info *logo, const char *bmp_name)

验证

接入串口,看调试打印日志 可以看到是先读取的logo.bmp 然后读取的logo_kernel.bmp ,对应的也就是uboot logo和kernel logo。搞定! 如果没有这2个custom logo文件 也会走系统默认的。

## Baudrate 1500000 bps not supported
himport_r: can't insert "baudrate=1500000" into hash table
dwmmc@fe2b0000: 1, dwmmc@fe2c0000: 2, sdhci@fe310000: 0
Bootdev(atags): mmc 0
MMC0: HS200, 200Mhz
PartType: EFI
boot mode: recovery (misc)
FIT: No fdt blob
boot mode: None
Android 11.0, Build 2021.7, v2
Found DTB in boot part
DTB: rk-kernel.dtb
HASH(c): OK
ANDROID: fdt overlay OK
I2c0 speed: 100000Hz
vsel-gpios- not found! Error: -2
vdd_cpu init 900000 uV
PMIC:  RK8090 (on=0x40, off=0x00)
vdd_logic init 900000 uV
vdd_gpu init 900000 uV
vdd_npu init 900000 uV
io-domain: OK
Model: Rockchip RK3568 EVB3568 Board
load_bmp_logo 尝试从MMC加载 logo.bmp...
..............
Fdt Ramdisk skip relocation
## Booting Android Image at 0x0027f800 ...
Kernel load addr 0x00280000 size 32057 KiB
RAM disk load addr 0x0a200000 size 804 KiB
## Flattened Device Tree blob at 0x0a100000
   Booting using the fdt blob at 0x0a100000
   XIP Kernel Image from 0x00280000 to 0x00280000 ... OK
  'reserved-memory' linux,cma: addr=10000000 size=800000
  'reserved-memory' ramoops@110000: addr=110000 size=f0000
   Using Device Tree in place at 000000000a100000, end 000000000a1223a7
load_bmp_logo 尝试从MMC加载 logo_kernel.bmp...

在这里插入图片描述

疑问

有个疑问就是 这么改完之后,kernel logo 如果是24位深的,logo 会倒过来 8位却不会?

然后 根据我查资料得出 ,8-bit BMP 图像与 24-bit BMP 图像在存储结构上有所不同,特别是在颜色表和像素数据的处理上。这些差异可能影响到图像的渲染方式和是否需要进行垂直翻转。

因此,如果不进行特殊处理,BMP 图像在显示时会被倒置。

在代码中,有这样一段:

if (reserved == BMP_PROCESSED_FLAG)
    logo->ymirror = 0;
else
    logo->ymirror = 1;

这里的 ymirror 似乎是用来处理这个问题的。当 ymirror 设置为 1 时,图像会被垂直翻转,从而正常显示。而 BMP_PROCESSED_FLAG 似乎是一个标志,用来表示 BMP 图像是否已经经过处理(例如已经被翻转过)。

如果发现 24 位深的 BMP Logo 显示是倒置的,可能需要检查以下几点:

  1. BMP 文件的存储方式:确保你的 BMP 文件是自下而上存储的。如果它已经是自上而下存储的,那么你不需要进行任何翻转。

  2. BMP_PROCESSED_FLAG 的设置:确保这个标志正确地表示了 BMP 图像是否已经经过处理。

  3. ymirror 的使用:确保在渲染图像时正确地使用了 ymirror 标志。

为了解决这个问题,可以考虑总是设置 ymirror 为 1(或根据实际情况进行设置),或者在创建 BMP 文件时,确保它是自上而下存储的(都用8位的)。

总结

通过我上述方法,我们成功地实现了在 RK3568 Android/Linux 系统中动态更换 U-Boot 和 Kernel Logo 的功能。这不仅简化了开发流程,还为设备固件提供了更大的灵活性。

本文来自网络,不代表协通编程立场,如若转载,请注明出处:https://www.net2asp.com/4ae3f31acc.html

androidkernellinuxlogouboot
赞 (0)
生成海报
html实现酷炫的公司年会抽奖(附源码)
« 上一篇 1天前
「Java」Socket实现简单的客户端和服务端通讯 | 公网环境通讯
下一篇 » 1天前

相关推荐

  • Zookeeper+kafka集群部署 大数据

    Zookeeper+kafka集群部署

    Zookeeper+kafka集群部署 需jdk环境 安装包下载地址:Index of /dist/zookeeper 上传到/usr/local tar -zxf zookeep…

    1天前
  • 阿里巴巴内部:全技术栈PPT分享(架构篇+算法篇+大数据) 大数据

    阿里巴巴内部:全技术栈PPT分享(架构篇+算法篇+大数据)

    我只截图不说话,PPT大全,氛围研发篇、算法篇、大数据、Java后端架构!除了大家熟悉的交易、支付场景外,支撑起阿里双十一交易1682亿元的“超级工程”其实包括以下但不限于客服、搜…

    1天前
  • 学习笔记|串口通信的基础知识|同步/异步|RS232|常见的串口软件的参数|STC32G单片机视频开发教程(冲哥)|第二十集:串口通信基础 大数据

    学习笔记|串口通信的基础知识|同步/异步|RS232|常见的串口软件的参数|STC32G单片机视频开发教程(冲哥)|第二十集:串口通信基础

    目录 1.串口通信的基础知识 串口通信(Serial Communication) 同步/异步? 全双工? 常见的串口软件的参数 2.STC32的串口通信实现原理 引脚选择:实现分…

    1天前
  • 倒排索引:ES倒排索引底层原理及FST算法的实现过程 大数据

    倒排索引:ES倒排索引底层原理及FST算法的实现过程

    文章目录 引言 1、倒排索引核心原理 2、倒排索引的存储结构 2.1 倒排表(Posting List) 2.2 词项字典(Term Dictionary) 2.3 ​词项索引(T…

    1天前
  • 2023-DataWorks数仓开发手册收藏版 大数据

    2023-DataWorks数仓开发手册收藏版

     DataWorks开发规范 1 数仓基本概念 1.4.1 ods数据源层表命名规范 1.4.2 dim维表层表命名规范 1.4.3 dwd数据明细层表命名规范 1.4.3 dws…

    1天前
  • RabbitMq——初级+高级(一) 大数据

    RabbitMq——初级+高级(一)

    总括执行流程:生产根据routingkey发送给交换机,而交换机通过routingkey来寻找对应的bindingkey从而把消息发送到队列里面去。 如果只有队列没有交换机的话,r…

    1天前
  • 6款常见的无人机仿真开发平台(附超详细特点功能对比) 人工智能

    6款常见的无人机仿真开发平台(附超详细特点功能对比)

    随着无人机与无人集群的快速发展,开发者对于无人机系统仿真测试环境的需求也日渐显现。本文整理了几款常见的无人机仿真平台,旨在为开发者提供一款更为易用、通用且真实可靠的平台。 软件在环…

    1天前
  • Stable Diffusion+ControlNet+Lora 指导AI+艺术设计的WebUI全流程使用教程 人工智能

    Stable Diffusion+ControlNet+Lora 指导AI+艺术设计的WebUI全流程使用教程

    目录 一. 背景知识 1.1 Stable Diffusion背景知识 1.1.1 安装stable-diffusion-webui 1.2 ControlNet 背景知识 二. …

    1天前
  • 有手就行!Sovits AI人声模型训练 人工智能

    有手就行!Sovits AI人声模型训练

    简介 随着AI孙燕姿的爆火出圈,各大视频平台的AI人声投稿量激增,B站首页频频给我推送相关视频,正好我对AIGC方面也挺感兴趣,心动不如行动,于是我用自己的声音训练了一个模型,发现…

    1天前
  • 利用yolov5进行目标检测,并将检测到的目标裁剪出来 人工智能

    利用yolov5进行目标检测,并将检测到的目标裁剪出来

    利用yolov5进行目标检测,并将检测到的目标裁剪出来 写在前面:关于yolov5的调试运行在这里不做过多赘述,有关yolov5的调试运行请看:https://www.bilibi…

    1天前

最新

  • Zookeeper+kafka集群部署
  • 阿里巴巴内部:全技术栈PPT分享(架构篇+算法篇+大数据)
  • 学习笔记|串口通信的基础知识|同步/异步|RS232|常见的串口软件的参数|STC32G单片机视频开发教程(冲哥)|第二十集:串口通信基础
  • 倒排索引:ES倒排索引底层原理及FST算法的实现过程
  • 2023-DataWorks数仓开发手册收藏版
  • RabbitMq——初级+高级(一)
  • 6款常见的无人机仿真开发平台(附超详细特点功能对比)
  • Stable Diffusion+ControlNet+Lora 指导AI+艺术设计的WebUI全流程使用教程
  • 有手就行!Sovits AI人声模型训练
  • 利用yolov5进行目标检测,并将检测到的目标裁剪出来
  • KataGO(引擎安装及解释)
  • 【复习】人工智能 第7章 专家系统与机器学习
  • 评判需求优先级5大规则和方法(纯干货):
  • Yolo训练时,输出的参数的含义
  • RK3588平台开发系列讲解(AI 篇)RKNN-Toolkit2 模型的加载转换

Copyright © 2022 Www.Net2asp.COM Rights Reserved.

苏ICP备2025168566号-5