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 memoryUsage:
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 宣告退休,直到下一次重启。