El sistema RK3568 Android/Linux reemplaza dinámicamente el logotipo U-Boot/Kernel

En el desarrollo de Android/Linux, el logotipo de arranque es el símbolo de la marca del dispositivo y, a menudo, debe personalizarse según los diferentes clientes o escenarios de aplicación. Para la plataforma RK3568, el logotipo de arranque generalmente está empaquetado en el archivo img del firmware, lo que significa que cada vez que se cambia el logotipo, es necesario volver a compilar y grabar todo el firmware, lo que sin duda aumenta la complejidad del desarrollo y hace perder tiempo. Este artículo presentará un método para reemplazar dinámicamente U-Boot y Kernel Logo en el sistema RK3568 Android/Linux.

referencia:

RK3399 permite el proceso del logotipo de inicio,
el nombramiento de particiones y la configuración U-Boot de la partición de almacenamiento de Android y la plataforma Rockchip.

Antecedentes de la demanda

El método tradicional requiere que recompilemos y grabemos el firmware cada vez que cambiamos el logo. Esto no solo lleva mucho tiempo, sino que también consume tiempo ^^, así que resolvamos este problema.

solución

El objetivo es cambiar dinámicamente el logotipo de inicio cuando el dispositivo ya se está ejecutando. Para ello propuse el siguiente plan:

  1. Cree una nueva partición (o use una partición existente) : almacene el archivo del logotipo en esta partición. Cuando se inicia el dispositivo, el sistema primero intentará cargar el logotipo desde esta partición. Si no hay ningún archivo de logotipo en la partición, el sistema volverá al logotipo predeterminado.

  2. Modificar el código fuente de U-Boot : durante el proceso de inicio de U-Boot, modificamos la lógica de carga de Logo. Primero intente cargar el logotipo desde la partición recién creada. Si falla, cárguelo desde el archivo de recursos predeterminado.

Detalles de implementacion

Utilice la partición existente para almacenar el logotipo

Primero necesitamos determinar dónde se almacena el archivo Logo. Dado que las particiones del sistema y del proveedor son de solo lectura, y la partición de datos se borrará después de restaurar la configuración de fábrica, decidí crear una nueva partición para almacenar el archivo Logo (de hecho, ya la he creado antes. Si quieres Para hacerlo, puede utilizar la partición existente del sistema, como /cache, correspondiente a 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

En la plataforma Rockchip, el nombre y la configuración de las particiones generalmente están definidos por el árbol de dispositivos (DTB/DTBO). Por ejemplo, el 0 en mmc 0:c representa el 0.º dispositivo de almacenamiento y c es un número hexadecimal que representa 12, por lo que corresponde a la 12.ª partición.

OK Después de seleccionar la partición, creamos una nueva carpeta debajo de la partición, por ejemplo custom_logo, colocamos logo.bmp y logo_kernel.bmp.

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

Si insiste en utilizar un método de partición personalizado, puede buscarlo en CSDN y no entrará en detalles aquí.

Modificar el código fuente de U-Boot

El código para cargar el Logo en U-Boot se encuentra /u-boot/drivers/video/drm/rockchip_display.cen load_bmp_logoel método. Nuestra estrategia es intentar primero cargar el logotipo desde la partición recién creada y, si falla, cargarlo desde el archivo de recursos predeterminado. Por cierto, he comprobado que es compatible con Linux y Android!! Solo cambia la partición y estará bien.

Aquí está el fragmento de código modificado:

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 < 0)
	    logo->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 <= 16) ? 16 : logo->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
}

depuración

Conéctese al puerto serie y presione Ctrl + C para ingresar al modo de línea de comando uboot. Después de escribir, puede ext4ls mmc 0:c /custom_logover las dos imágenes del logotipo personalizado que ingresamos. OK, y estará listo para cepillar uboot.img.

=> ext4ls mmc 0:c /custom_logo
<DIR>       4096 .
<DIR>       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]
=> 

Otros hallazgos: cuando leí el registro, descubrí que la función load_kernel_bmp_logo no se ejecutó en absoluto. Luego leí los comentarios y descubrí, está bien, no importa.

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

verificar

Conéctese al puerto serie y observe el registro de impresión de depuración. Puede ver que primero se lee logo.bmp y luego logo_kernel.bmp, que corresponde al logotipo de uboot y al logotipo del kernel. ¡Listo! Si no existen estos dos archivos de logotipos personalizados, se utilizará el valor predeterminado del sistema.

## 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...

Insertar descripción de la imagen aquí

duda

Una pregunta es que después de este cambio, si el logo del kernel tiene 24 bits de profundidad, el logo se invertirá a 8 bits, pero ¿no?

Luego, según mi investigación, descubrí que la estructura de almacenamiento de las imágenes BMP de 8 bits es diferente de la de las imágenes BMP de 24 bits, especialmente en el procesamiento de tablas de colores y datos de píxeles. Estas diferencias pueden afectar la forma en que se representa la imagen y si es necesario voltearla verticalmente.
Por lo tanto, sin un procesamiento especial, las imágenes BMP se mostrarán al revés.

En el código, hay esta sección:

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

Aquí ymirrorparece que se utiliza para abordar este problema. Cuando ymirrorse establece en 1, la imagen se voltea verticalmente y se muestra normalmente. Y BMP_PROCESSED_FLAGparece ser una bandera utilizada para indicar si la imagen BMP ha sido procesada (por ejemplo, ha sido volteada).

Si descubre que el logotipo BMP de 24 bits de profundidad se muestra al revés, es posible que deba verificar los siguientes puntos:

  1. Cómo se almacenan los archivos BMP : asegúrese de que sus archivos BMP se almacenen de abajo hacia arriba. Si ya está almacenado de arriba hacia abajo, no es necesario darle la vuelta.

  2. BMP_PROCESSED_FLAGConfiguración : asegúrese de que esta bandera indique correctamente si la imagen BMP se ha procesado.

  3. ymirrorUso : asegúrese de utilizar la bandera correctamente al renderizar imágenes ymirror.

Para resolver este problema, considere configurarlo siempre ymirroren 1 (o configurarlo según corresponda), o al crear el archivo BMP, asegúrese de que esté almacenado de arriba hacia abajo (ambos con 8 bits).

Resumir

A través de mi método anterior, logramos con éxito la función de cambiar dinámicamente el U-Boot y el logotipo del kernel en el sistema RK3568 Android/Linux. Esto no sólo simplifica el proceso de desarrollo sino que también proporciona una mayor flexibilidad en el firmware del dispositivo.

Supongo que te gusta

Origin blog.csdn.net/SHH_1064994894/article/details/132473026
Recomendado
Clasificación