uboot distro_bootcmd 理解

uboot distro_bootcmd 理解

从 run distro_bootcmd 开始

distro_bootcmd=
	for target in ${boot_targets};
	do
		run bootcmd_${target};
	done

我的 sun8-h3 板子中 boot_targets 为:

boot_targets=fel mmc_auto usb0 pxe dhcp 

重点分析 mmc_auto dhcp

bootcmd_mmc_auto

以下变量的值,都可以通过 printenv name 查看的到,不过个别变量定义比较长,无法显示完整,这时需要在源代码中查看: \u-boot-2017.11.git\include\config_distro_bootcmd.h

bootcmd_mmc_auto=run bootcmd_mmc0
bootcmd_mmc0=setenv devnum 0; run mmc_boot
mmc_boot=
if mmc dev ${devnum};then            # 测试mmc 是否有分区,有则
	setenv devtype mmc;              # devtype = mmc
    run scan_dev_for_boot_part;      
fi
scan_dev_for_boot_part=                                         
	part list ${devtype} ${devnum} -bootable devplist;     # 这里正常会设置 devplist = 分区列表
	env exists devplist || setenv devplist 1;              # 如果为空,devplist 设置为 1
	for distro_bootpart in ${devplist}; do 
		if fstype ${devtype} ${devnum}:${distro_bootpart} bootfstype; then  # 检测fstype, 并设置 bootfstype=fstype
			run scan_dev_for_boot;                                          # help fstype 可以查看 fstype 用法说明
		fi; 
	done
scan_dev_for_boot=
	echo Scanning ${devtype} ${devnum}:${distro_bootpart}...;
	for prefix in ${boot_prefixes};
    do 
		run scan_dev_for_extlinux; 
		run scan_dev_for_scripts; 
	done;
		run scan_dev_for_efi;        	

boot_prefixes=/ /boot/
scan_dev_for_extlinux=
	if test -e ${devtype} ${devnum}:${distro_bootpart} ${prefix}extlinux/extlinux.conf; then 
		echo Found ${prefix}extlinux/extlinux.conf;  # 如果找到 ${prefix}extlinux/extlinux.conf 文件,则 boot_extlinux
		run boot_extlinux; 
		echo SCRIPT FAILED: continuing...; 
	fi	
boot_extlinux=
	sysboot ${devtype} ${devnum}:${distro_bootpart} any ${scriptaddr} ${prefix}extlinux/extlinux.conf	
	                                                 # 读取 extlinux.conf 到 $scriptaddr
scan_dev_for_scripts=
	for script in ${boot_scripts}; do
		if test -e ${devtype} ${devnum}:${distro_bootpart} ${prefix}${script}; then 
			echo Found U-Boot script ${prefix}${script};   # 如果找到 boot.scr* 文件,则 boot_a_script
			run boot_a_script;
			echo SCRIPT FAILED: continuing...; 
		fi; 
	done
	
boot_scripts=boot.scr.uimg boot.scr
boot_a_script=
		load ${devtype} ${devnum}:${distro_bootpart} ${scriptaddr} ${prefix}${script};  # 将 script 读到 $scriptaddr
		source ${scriptaddr}                                                            # source 执行 $scriptaddr
	

boot.scr 的原始文件如下

setenv fdt_high ffffffff
setenv loadkernel fatload mmc 0 \$kernel_addr_r uImage
setenv loaddtb fatload mmc 0 \$fdt_addr_r dtb
setenv bootargs console=ttyS0,115200 earlyprintk root=/dev/mmcblk0p2 rootwait
setenv uenvcmd run loadkernel \&\& run loaddtb \&\& bootm \$kernel_addr_r - \$fdt_addr_r
run uenvcmd

bootcmd_dhcp

bootcmd_dhcp=
	if dhcp ${scriptaddr} ${boot_script_dhcp}; then   # 从dhcp server 中下载 boot.scr.uimg 并执行
		source ${scriptaddr}; 
	fi;
boot_script_dhcp=boot.scr.uimg

小结:不论是从mmc 启动还是 dhcp 启动,最终的步骤都是一样的,获取 boot.scr 到 scriptaddr , 然后 source scriptaddr

source

source 的用法,用途是从内存执行脚本

=> help source
source - run script from memory

Usage:
source [addr]

  • run script starting at addr
    valid image header must be present

boot.scr

boot.scr 如何生成

在 openwrt/package/boot/uboot-sunxi/Makefile 中,使用mkiamge 生成,输入文件为 uEnv-default.txt

        mkimage -C none -A arm -T script -d uEnv-$(UENV).txt \
                $(STAGING_DIR_IMAGE)/$(BUILD_DEVICES)-boot.scr

uEnv-default.txt

setenv fdt_high ffffffff
setenv loadkernel fatload mmc 0 \$kernel_addr_r uImage
setenv loaddtb fatload mmc 0 \$fdt_addr_r dtb
setenv bootargs console=ttyS0,115200 earlyprintk root=/dev/nfs nfsroot=172.16.10.67:/home/lql/my_rootfs/rootfs,vers=3 ip=dhcp rootwait
setenv uenvcmd run loadkernel \&\& run loaddtb \&\& bootm \$kernel_addr_r - \$fdt_addr_r
run uenvcmd

读取 kernel 和 dtb 到指定内存位置,最后执行 bootm $kernel_addr_r - $fdt_addr_r

bootm

bootm 使用说明:

=> help bootm
bootm - boot application image from memory

Usage:
bootm [addr [arg ...]]
    - boot application image stored in memory
        passing arguments 'arg ...'; when booting a Linux kernel,
        'arg' can be the address of an initrd image
        When booting a Linux kernel which requires a flat device-tree
        a third argument is required which is the address of the
        device-tree blob. To boot that kernel without an initrd image,
        use a '-' for the second argument. If you do not pass a third
        a bd_info struct will be passed instead

Sub-commands to do part of the bootm sequence.  The sub-commands must be
issued in the order below (it's ok to not issue all sub-commands):
        start [addr [arg ...]]
        loados  - load OS image
        ramdisk - relocate initrd, set env initrd_start/initrd_end
        fdt     - relocate flat device tree
        cmdline - OS specific command line processing/setup
        bdt     - OS specific bd_t processing
        prep    - OS specific prep before relocation or go
        go      - start OS

第一个参数为 kernel 地址 ,当 要使用 dtb 时 加上 - 符号, 后接 dtb 地址。

小结:uboot 的使命就是执行 bootm , bootm 正常后,cpu 权限交给kernel ,uboot 宣告退休,直到下一次重启。

猜你喜欢

转载自blog.csdn.net/agave7/article/details/108774714