rockchip uboot 應用dts overlays

Amumu1發表於2024-05-15

提供一種基於rkSDK buildroot使用dtbo的方法

簡單說明:

  1. uboot中預設載入default-dtb-overlay.dtbo
  2. app/dtbo-tools/S03checkDTBO 開機檢查撥碼開關,並將/boot/overlays/default-dtb-overlay.dtbo連結到目標dtbo,有效的dtbo名全部存放於dtbo_table變數中
  3. build.sh中:新增dtbo編譯選項,根據RK_KERNEL_DTS_OVERLAYS配置自動更新S03checkDTBOdtbo_table變數,並將dtbo與S03checkDTBO安裝到rootfs
  4. 在.BoardConfig 新增RK_KERNEL_DTS_OVERLAYS環境變數

uboot補丁

diff --git a/arch/arm/mach-rockchip/boot_rkimg.c b/arch/arm/mach-rockchip/boot_rkimg.c
index 097d976b1f..1ace5da174 100644
--- a/arch/arm/mach-rockchip/boot_rkimg.c
+++ b/arch/arm/mach-rockchip/boot_rkimg.c
@@ -35,6 +35,7 @@
 #include <u-boot/sha1.h>
 #include <u-boot/sha256.h>
 #include <linux/usb/phy-rockchip-usb2.h>
+#include <mapmem.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -552,6 +553,136 @@ static int rkimg_traverse_read_dtb(void *fdt, int where)
        return -EINVAL;
 }
 
+static int do_get_ext2(cmd_tbl_t *cmdtp, const char *file_path, char *file_addr)
+{
+       static char *fs_argv[5];
+       disk_partition_t part_info;
+       char part_num[4]= {0};
+
+       int ret = part_get_info_by_name(dev_desc, "rootfs", &part_info);
+       if (ret < 0){
+               printf("[warning] not found partion:%s\n","rootfs");
+               return ret;
+       }
+
+       sprintf(part_num, "%s:%d", env_get("devnum"), ret);
+
+       fs_argv[0] = "ext2load";
+       fs_argv[1] = env_get("devtype");
+       fs_argv[2] = part_num;
+       fs_argv[3] = file_addr;
+       fs_argv[4] = (void *)file_path;
+
+       printf("runcmd: <%s %s %s %s %s>\n",fs_argv[0],fs_argv[1],fs_argv[2],fs_argv[3],fs_argv[4]);
+
+       if (!do_ext2load(cmdtp, 0, 5, fs_argv))
+               return 1;
+       return -ENOENT;
+}
+
+static int get_relfile_envaddr(cmd_tbl_t *cmdtp, const char *file_path, const char *envaddr_name)
+{
+       unsigned long file_addr;
+       char *envaddr;
+       char addr_buf[18];
+
+       envaddr = env_get(envaddr_name);
+
+       if (!envaddr){
+               printf("missing environment variable: %s\n", envaddr_name);
+               return -ENOENT;
+       }
+
+       if (strict_strtoul(envaddr, 16, &file_addr) < 0)
+               return -EINVAL;
+
+       sprintf(addr_buf, "%lx", file_addr);
+
+       return do_get_ext2(cmdtp, file_path, addr_buf);
+}
+
+static void kernel_fdt_overlay_apply( char *fdtoverlay)
+{
+       struct fdt_header *working_fdt;
+       char *fdtoverlay_addr_env;
+       ulong fdtoverlay_addr;
+       ulong fdt_addr;
+       int err;
+
+       /* Get the main fdt and map it */
+       fdt_addr = simple_strtoul(env_get("fdt_addr_r"), NULL, 16);
+       working_fdt = map_sysmem(fdt_addr, 0);
+       err = fdt_check_header(working_fdt);
+       if (err){
+               printf("Invalid fdt_addr_r for loading dtb\n");
+               return;
+       }
+       /* Get the specific overlay loading address */
+       env_set("fdtoverlay_addr_r","0x08000000");
+       fdtoverlay_addr_env =  env_get("fdtoverlay_addr_r");
+       if (!fdtoverlay_addr_env) {
+               printf("Invalid fdtoverlay_addr_r for loading overlays\n");
+               return;
+       }
+
+       fdtoverlay_addr = simple_strtoul(fdtoverlay_addr_env, NULL, 16);
+
+       /* Cycle over the overlay files and apply them in order */
+       do {
+               struct fdt_header *blob;
+               char *overlayfile;
+               char *end;
+               int len;
+
+               /* Drop leading spaces */
+               while (*fdtoverlay == ' ')
+                       ++fdtoverlay;
+
+               /* Copy a single filename if multiple provided */
+               end = strstr(fdtoverlay, " ");
+               if (end) {
+                       len = (int)(end - fdtoverlay);
+                       overlayfile = malloc(len + 1);
+                       strncpy(overlayfile, fdtoverlay, len);
+                       overlayfile[len] = '\0';
+               } else
+                       overlayfile = fdtoverlay;
+
+               if (!strlen(overlayfile))
+                       goto skip_overlay;
+
+               /* Load overlay file */
+               err = get_relfile_envaddr(NULL, overlayfile,
+                                         "fdtoverlay_addr_r");
+               if (err < 0) {
+                       printf("Failed loading overlay %s\n", overlayfile);
+                       goto skip_overlay;
+               }
+
+               /* Resize main fdt */
+               fdt_shrink_to_minimum(working_fdt, 8192);
+
+               blob = map_sysmem(fdtoverlay_addr, 0);
+               err = fdt_check_header(blob);
+               if (err) {
+                       printf("Invalid overlay %s, skipping\n",
+                              overlayfile);
+                       goto skip_overlay;
+               }
+
+               err = fdt_overlay_apply_verbose(working_fdt, blob);
+               if (err) {
+                       printf("Failed to apply overlay %s, skipping\n",
+                              overlayfile);
+                       goto skip_overlay;
+               }
+
+skip_overlay:
+               if (end)
+                       free(overlayfile);
+       } while ((fdtoverlay = strstr(fdtoverlay, " ")));
+}
+
 int rockchip_read_dtb_file(void *fdt)
 {
        int locate, ret;
@@ -584,7 +715,7 @@ int rockchip_read_dtb_file(void *fdt)
 #if defined(CONFIG_ANDROID_BOOT_IMAGE) && defined(CONFIG_OF_LIBFDT_OVERLAY)
        android_fdt_overlay_apply((void *)fdt);
 #endif
-
+       kernel_fdt_overlay_apply("/boot/overlays/default-dtb-overlay.dtbo");
        return 0;
 }
 #endif

build.sh 補丁


+function build_kernel_dtbo(){
+
+       fs_overlay_dir="$TOP_DIR/buildroot/board/rockchip/rk356x/huaqi/fs-overlay"
+       fs_dtbo_dir="$fs_overlay_dir/boot/overlays"
+       kernel_dts_dir="$TOP_DIR/kernel/arch/arm64/boot/dts/rockchip"
+       DTC="dtc-1.6.0"
+       dtbo_tools="$TOP_DIR/app/dtbo-tools/S03checkDTBO"
+
+       if [ -z "$RK_KERNEL_DTS_OVERLAYS" ];then
+               echo "Don't set RK_KERNEL_DTS_OVERLAYS, exit ..."
+               rm $fs_overlay_dir/etc/init.d/S03checkDTBO
+               rm $fs_overlay_dir/boot -r
+               return
+       fi
+
+       cd $kernel_dts_dir
+       echo "cd $kernel_dts_dir"
+
+       for dts in $RK_KERNEL_DTS_OVERLAYS
+       do      
+               if [ -e "$dts.dts" ];then
+                       $DTC -I dts -O dtb $dts.dts -o $dts.dtbo
+                       if [ "$?" = "0" ];then
+                               echo "[DTC]     $dts.dtbo"
+                       fi
+                       dtbo_table="$dtbo_table $dts.dtbo"
+               else
+                       echo "[DTC]     $dts.dtbo failed,no such file $dts.dts"
+               fi
+       done
+       
+       if [ -e "$fs_overlay_dir" ];then
+               mkdir -p "$fs_dtbo_dir"
+       fi
+
+       echo "Install `ls *.dtbo` to $fs_dtbo_dir"
+
+
+       cp $kernel_dts_dir/*.dtbo $fs_dtbo_dir
+
+       if [ -e "$dtbo_tools" ];then
+               sed  "s/dtbo_table=/dtbo_table=($dtbo_table)/g" $dtbo_tools > $fs_overlay_dir/etc/init.d/S03checkDTBO
+               echo "Install $dtbo_tools to $fs_overlay_dir/etc/init.d/S03checkDTBO"
+               chmod +x $fs_overlay_dir/etc/init.d/S03checkDTBO
+               cat $fs_overlay_dir/etc/init.d/S03checkDTBO | grep "dtbo_table="
+       else
+               echo "[WARN]: Not found $dtbo_tools!!!"
+       fi
+
+       finish_build
+}
+
 function build_kernel(){
        check_config RK_KERNEL_DTS RK_KERNEL_DEFCONFIG || return 0
 
@@ -670,8 +723,9 @@ function build_kernel(){
        fi
 
        build_check_power_domain
-
        finish_build
+
+       build_kernel_dtbo
 }
 
 function build_modules(){
@@ -1015,6 +1069,7 @@ function build_all(){
        check_security_condition
        build_loader
        build_kernel
+       build_kernel_dtbo
        build_toolchain
        build_rootfs ${RK_ROOTFS_SYSTEM:-buildroot}
        build_recovery
@@ -1272,6 +1327,7 @@ for option in ${OPTIONS}; do
                uefi) build_uefi ;;
                loader) build_loader ;;
                kernel) build_kernel ;;
+               dtbo) build_kernel_dtbo;;
                modules) build_modules ;;
                rootfs|buildroot|debian|yocto) build_rootfs $option ;;
                pcba) build_pcba ;;

BoardConfig-rk3568-evb1-ddr4-v10.mk 中新增環境變數

+export RK_KERNEL_DTS_OVERLAYS="rk3568-test rk3568-test2 rk3568-test3 rk3568-test4"

app/dtbo-tools/S03checkDTBO

build.sh中根據RK_KERNEL_DTS_OVERLAYS配置自動更新dtbo_table

#!/bin/sh

### BEGIN INIT INFO
# Provides:             check device tree overlay plugin
# Required-Start:
# Required-Stop:
# Default-Start:        S
# Default-Stop:
### END INIT INFO

OverlaysPath="/boot/overlays"
OverlaysHeader="rk3568-huaqi-overlays"
dtbo_table=
EXE_NAME=$0
switchGPIO="28 29 30"

function log()
{
	logger -s -t "[$EXE_NAME]" $@
}

function getSwichValue(){

	for i in $switchGPIO
	do
		value="$value`gpioget -l 2 $i`" 
	done

	val_hex=$(printf "%02x" $((2#$value)))
	echo "0x$val_hex"
}

start() {
	log "checkDTBO start ..."
	if [ -d "$OverlaysPath" ];then
		cd $OverlaysPath
	else
		log "Not found dir:$OverlaysPath,skip check device tree overlay!!!"
	fi
	
	if [ -z "${dtbo_table[0]}" ];then
		log "dtbo_table is empty,skip check device tree overlay!!!"
		return
	fi

	OLD_DTBO=`readlink default-dtb-overlay.dtbo`

	let swichValue="`getSwichValue`"

	if [ $swichValue -gt ${#dtbo_table[@]} ];then
		log "dtbo_table[0-${#dtbo_table[@]}]:<${dtbo_table[@]}>"
		log "Not define dtbo_table[$swichValue],exit..."
		return
	fi

	NEW_DTBO=${dtbo_table[$swichValue]}

	if [ ! -e "$NEW_DTBO" ];then
		log "No such file:$NEW_DTBO"
		log "skip set default-dtb-overlay.dtbo link to $NEW_DTBO!!!"
		syslog 
		return
	fi

	if  [ "$OLD_DTBO" != "$NEW_DTBO" ];then
		log "set default-dtb-overlay.dtbo link to $NEW_DTBO"
		ln -sf $NEW_DTBO default-dtb-overlay.dtbo
		sync
		reboot
	fi	
}

stop() {
	echo "checkDTBO stop ..."
}

restart() {
	echo "checkDTBO restart ..."
	stop
	start
}

case "$1" in
	start|stop|restart)
		"$1";;
	reload)
		# Restart, since there is no true "reload" feature.
		restart;;
	*)
		echo "Desc: Check device tree overlay plugin script"
		echo "Usage: $0 {start|stop|restart|reload}"
		exit 1
esac

相關文章