stm32mp1 uboot启动流程分析

news2024/11/21 0:26:20

stm32mp1 uboot启动流程分析

本节主要关注uboot启动linux的流程,首先关注下uboot的环境变量

uboot环境变量

进入uboot以后回车输入print即可看到uboot的所有环境变量:
在这里插入图片描述这里很多变量嵌套了一些流程,整理一下格式:

altbootcmd=run bootcmd
arch=arm
autoload=no
baudrate=115200
board=stm32mp1
board_name=stm32mp157d-robot
boot_a_script=load ${devtype} ${devnum}:${distro_bootpart} ${scriptaddr} ${prefix}${script}; source ${scriptaddr}
boot_device=mmc
boot_efi_binary=
	if fdt addr ${fdt_addr_r}; then 
		bootefi bootmgr ${fdt_addr_r};
	else 
		bootefi bootmgr ${fdtcontroladdr};
	fi;
	load ${devtype} ${devnum}:${distro_bootpart} ${kernel_addr_r} efi/boot/bootarm.efi; 
	if fdt addr ${fdt_addr_r}; then 
		bootefi ${kernel_addr_r} ${fdt_addr_r};
	else 
		bootefi ${kernel_addr_r} ${fdtcontroladdr};
	fi
boot_extlinux=sysboot ${devtype} ${devnum}:${distro_bootpart} any ${scriptaddr} ${prefix}${boot_syslinux_conf}
boot_instance=0
boot_m4fw=rproc init; rproc load 0 ${m4fw_addr} ${filesize}; rproc start 0
boot_net_usb_start=true
boot_prefixes=/ /boot/
boot_script_dhcp=boot.scr.uimg
boot_scripts=boot.scr.uimg boot.scr
boot_syslinux_conf=extlinux/extlinux.conf
boot_targets=mmc1 ubifs0 mmc0 mmc2 pxe 
bootcmd=run bootcmd_stm32mp
bootcmd_mmc0=devnum=0; run mmc_boot
bootcmd_mmc1=devnum=1; run mmc_boot
bootcmd_mmc2=devnum=2; run mmc_boot
bootcmd_pxe=run boot_net_usb_start; dhcp; if pxe get; then pxe boot; fi
bootcmd_stm32mp=
	echo "Boot over ${boot_device}${boot_instance}!";
	if test ${boot_device} = serial || test ${boot_device} = usb;then 
		stm32prog ${boot_device} ${boot_instance}; 
	else 
		run env_check;
		if test ${boot_device} = mmc;then 
			env set boot_targets "mmc${boot_instance}"; 
		fi;
		if test  ${boot_device} = nand || test ${boot_device} = spi-nand ;then 
			env set boot_targets ubifs0; 
		fi;
		if test ${boot_device} = nor;then 
			env set boot_targets mmc0; 
		fi;
		run distro_bootcmd;
	fi;
bootcmd_ubifs0=devnum=0; run ubifs_boot
bootcount=4
bootdelay=1
bootfstype=ext4
cpu=armv7
distro_bootcmd=
	for target in ${boot_targets}; 
	do 
		run bootcmd_${target}; 
	done
efi_dtb_prefixes=/ /dtb/ /dtb/current/
env_check=if env info -p -d -q; then env save; fi
fdt_addr_r=0xc4000000
fdtcontroladdr=f3ae4d20
fdtfile=stm32mp157d-robot.dtb
fdtoverlay_addr_r=0xc4100000
fileaddr=c4100000
filesize=b7f
kernel_addr_r=0xc2000000
load_efi_dtb=load ${devtype} ${devnum}:${distro_bootpart} ${fdt_addr_r} ${prefix}${efi_fdtfile}
loadaddr=0xc2000000
m4fw_addr=0xc2000000
m4fw_name=rproc-m4-fw.elf
mmc_boot=
	if mmc dev ${devnum}; then 
		devtype=mmc; 
		run scan_dev_for_boot_part; 
	fi
pxefile_addr_r=0xc4200000
ramdisk_addr_r=0xc4400000
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;
scan_dev_for_boot_part=
	part list ${devtype} ${devnum} -bootable devplist; 
	env exists devplist || setenv devplist 1; 
	for distro_bootpart in ${devplist}; 
	do 
		if fstype ${devtype} ${devnum}:${distro_bootpart} bootfstype; then 
			run scan_dev_for_boot; 
		fi; 
	done; 
	setenv devplist
scan_dev_for_efi=
	setenv efi_fdtfile ${fdtfile}; 
	if test -z "${fdtfile}" -a -n "${soc}"; then 
		setenv efi_fdtfile ${soc}-${board}${boardver}.dtb; 
	fi; 
	for prefix in ${efi_dtb_prefixes}; 
	do 
		if test -e ${devtype} ${devnum}:${distro_bootpart} ${prefix}${efi_fdtfile}; then 
			run load_efi_dtb; 
		fi;
	done;
	if test -e ${devtype} ${devnum}:${distro_bootpart} efi/boot/bootarm.efi; then 
		echo Found EFI removable media binary efi/boot/bootarm.efi; 
		run boot_efi_binary; echo EFI LOAD FAILED: continuing...; 
	fi; 
	setenv efi_fdtfile
scan_dev_for_extlinux=
	if test -e ${devtype} ${devnum}:${distro_bootpart} ${prefix}${boot_syslinux_conf}; then 
		echo Found ${prefix}${boot_syslinux_conf}; 
		run boot_extlinux; 
		echo SCRIPT FAILED: continuing...; 
	fi
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}; 
			run boot_a_script; 
			echo SCRIPT FAILED: continuing...; 
		fi; 
	done
scan_m4fw=
	if test -e ${devtype} ${devnum}:${distro_bootpart} ${m4fw_name};then 
		echo Found M4 FW $m4fw_name; 
		if load ${devtype} ${devnum}:${distro_bootpart} ${m4fw_addr} ${m4fw_name}; then 
			run boot_m4fw; 
		fi; 
	fi;
scriptaddr=0xc4100000
serial#=003A002B3030511039383538
serverip=192.168.1.1
soc=stm32mp
splashimage=0xc4300000
ubifs_boot=
	env exists bootubipart || env set bootubipart UBI; 
	env exists bootubivol || env set bootubivol boot; 
	if ubi part ${bootubipart} && ubifsmount ubi${devnum}:${bootubivol}; then 
		devtype=ubi; 
		run scan_dev_for_boot; 
	fi
usb_boot=
	usb start; 
	if usb dev ${devnum}; then 
		devtype=usb; 
		run scan_dev_for_boot_part; 
	fi
vendor=st

Environment size: 4413/8187 bytes

我们都知道uboot bootcmd环境变量 保存着 uboot 默认命令, uboot 倒计时结束以后就会执行 bootcmd 中的命令。我们从bootcmd 开始梳理一下启动linux的流程:

bootcmd=run bootcmd_stm32mp
bootcmd_stm32mp=
	echo "Boot over ${boot_device}${boot_instance}!";     #  ${boot_device}${boot_instance}: mmc0(sdcard 启动)
	run env_check;
	if test ${boot_device} = mmc;then 
		env set boot_targets "mmc${boot_instance}";            # 设置boot_targets mmc0
	fi;
	run distro_bootcmd;

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

bootcmd_mmc0=
	devnum=0;                                                                                    # devnum=0
	run mmc_boot
	
mmc_boot=
	if mmc dev ${devnum}; then 
		devtype=mmc;                                                                         # devtype=mmc
		run scan_dev_for_boot_part; 
	fi

下面重点看下scan_dev_for_boot_part 这个变量:

scan_dev_for_boot_part=
	part list ${devtype} ${devnum} -bootable devplist;        #查看mmc0的boot分区
	env exists devplist || setenv devplist 1; 
	for distro_bootpart in ${devplist}; 
	do 
		if fstype ${devtype} ${devnum}:${distro_bootpart} bootfstype; then 
			run scan_dev_for_boot; 
		fi; 
	done; 
	setenv devplist

part list mmc 0 就是查看mmc0的分区情况,如下图所示
在这里插入图片描述
所以上面scan_dev_for_boot_part就是查看mmc0的分区里面是否有bootfs的分区lable,如果有找到分区号,对应上面的4分区,接着执行scan_dev_for_boot,接着看

scan_dev_for_boot=
	echo Scanning ${devtype} ${devnum}:${distro_bootpart}...;   # 变量对应mmc0:4
	for prefix in ${boot_prefixes};                                                                 #  ${boot_prefixes}:/  /boot/
	do 
		run scan_dev_for_extlinux; 
		run scan_dev_for_scripts; 
	done;
	run scan_dev_for_efi;

scan_dev_for_extlinux=

下面重要的两个函数scan_dev_for_extlinux 和 scan_dev_for_scripts,先看scan_dev_for_extlinux:

scan_dev_for_extlinux=
	if test -e ${devtype} ${devnum}:${distro_bootpart} ${prefix}${boot_syslinux_conf}; then     #变量对应:mmc 0:4 (/extlinux/extlinux.conf    /boot/extlinux/extlinux.conf)
		echo Found ${prefix}${boot_syslinux_conf}; 
		run boot_extlinux; 
		echo SCRIPT FAILED: continuing...; 
	fi

boot_extlinux=
	sysboot ${devtype} ${devnum}:${distro_bootpart} any ${scriptaddr} ${prefix}${boot_syslinux_conf}
	---> sysboot mmc 0:4 any  0xc4100000   (/extlinux/extlinux.conf    /boot/extlinux/extlinux.conf)

主要就是查找SD卡boot分区里面/ 和/boot两个路径下是否存在extlinux.conf文件,如果存在就执行boot_extlinux

接着看scan_dev_for_scripts:

scan_dev_for_scripts=
	for script in ${boot_scripts};                                                                                                    # boot.scr.uimg  boot.scr
	do 
		if test -e ${devtype} ${devnum}:${distro_bootpart} ${prefix}${script}; then       # mmc 0:4 (/boot.scr.uimg  /boot.scr  /boot/boot.scr.uimg  /boot/boot.scr)
			echo Found U-Boot script ${prefix}${script}; 
			run boot_a_script; 
			echo SCRIPT FAILED: continuing...; 
		fi; 
	done

boot_a_script=
	load ${devtype} ${devnum}:${distro_bootpart} ${scriptaddr} ${prefix}${script}; source ${scriptaddr}
		---> load mmc 0:4 0xc4100000 (/boot.scr.uimg  /boot.scr  /boot/boot.scr.uimg  /boot/boot.scr)
		---> source 0xc4100000

scan_dev_for_scripts主要就是查找SD卡boot分区里面/ 和/boot两个路径下是否存在boot.scr.uimg和boot.scr文件,如果存在就执行boot_a_script

以原子开发板为例,我们使用ls mmc 0:4查看下boot分区的具体内容如下,可以看到没有提供extlinux.conf,提供了一个boot.scr.uimg
在这里插入图片描述
搜以执行到这里其实最后会走到
load mmc 0:4 0xc4100000 /boot.scr.uimg
source 0xc4100000

boot.scr.uimg这个其实是一个脚本, st 在yocto里描述boot.scr.uimg可以使用mkimage来生成在这里插入图片描述我这里直接贴st yocto里面 boot.src.cmd 的源码:


echo "Executing SCRIPT on target=${target}"

# M4 Firmware load
env set m4fw_name "rproc-m4-fw.elf"
env set m4fw_addr ${kernel_addr_r}
env set boot_m4fw 'rproc init; rproc load 0 ${m4fw_addr} ${filesize}; rproc start 0'

# boot M4 Firmware when available
env set scan_m4fw 'if test -e ${devtype} ${devnum}:${distro_bootpart} ${m4fw_name};then echo Found M4 FW $m4fw_name; if load ${devtype} ${devnum}:${distro_bootpart} ${m4fw_addr} ${m4fw_name}; then run boot_m4fw; fi; fi;'

# management of overlay
env set ov_init 'load ${devtype} ${devnum}:${distro_bootpart} ${fdt_addr_r} ${fdtfile} && env set fdt_addr ${fdt_addr_r} && fdt addr ${fdt_addr} && setexpr fdtovaddr ${fdt_addr} + C0000'
env set ov_apply 'test -n ${fdtovaddr} && test -n ${overlay} && for ov in ${overlay}; do echo overlaying ${ov}...; load ${devtype} ${devnum}:${distro_bootpart} ${fdtovaddr} /overlays/${ov}.dtbo && fdt resize ${filesize} && fdt apply ${fdtovaddr}; done'
env set scan_overlays 'if test -e ${devtype} ${devnum}:${distro_bootpart} /overlays/overlays.txt && load ${devtype} ${devnum}:${distro_bootpart} ${loadaddr} /overlays/overlays.txt && env import -t ${loadaddr} ${filesize}; then echo loaded overlay.txt: ${overlay}; run ov_init; run ov_apply; fi'

# Update the DISTRO command to search in sub-directory and load M4 firmware
env set boot_prefixes "/${boot_device}${boot_instance}_"
env set boot_extlinux "run scan_m4fw;run scan_overlays; ${boot_extlinux}"

# save the boot config for the 2nd boot
env set boot_targets ${target}

# when {boot_device} = nor, use ${target} = the location of U-Boot
# script boot.scr.img found in DISTRO script
# value can be "mmc0" (SD Card), "mmc1" (eMMC) or "ubifs0" (NAND)

if test ${target} = mmc0; then
   if test -d ${devtype} ${devnum}:${distro_bootpart} /mmc0_extlinux; then
       env set boot_prefixes "/mmc0_"
   fi
elif test ${target} = mmc1; then
   if test -d ${devtype} ${devnum}:${distro_bootpart} /mmc1_extlinux; then
       env set boot_prefixes "/mmc1_"
   fi
elif test ${target} = ubifs0; then
   if test -d ${devtype} ${devnum}:${distro_bootpart} /nand0_extlinux; then
       env set boot_prefixes "/nand0_"
   fi
fi

if test -e ${devtype} ${devnum}:${distro_bootpart} ${boot_prefixes}extlinux/${board_name}_extlinux.conf; then
   echo FOUND ${boot_prefixes}extlinux/${board_name}_extlinux.conf
   env set boot_syslinux_conf "extlinux/${board_name}_extlinux.conf"
fi

# don't save the updated content of bootfile variable to avoid conflict
env delete bootfile

# save the boot config the 2nd boot (boot_prefixes/boot_extlinux)
env save

# start the correct exlinux.conf
run bootcmd_${target}

echo SCRIPT FAILED... ${boot_prefixes}${boot_syslinux_conf} not found !

# restore environment to default value when failed
env default boot_targets
env default boot_prefixes
env default boot_extlinux
env default boot_syslinux_conf
env save

我们简单过一下boot.src.cmd的流程:

  1. 设置一些环境变量用来启动M4内核
  2. 查找bootfs分区下面的extlinux.conf来选择特定的启动配置,包括设备树、镜像、启动命令等等
  3. 确定号上面的配置以后最后再

我这边uboot是我自己移植的,暂时还没有修改boot分区里面的东西暂时服用原子的,可以看到我运行出错了:
在这里插入图片描述
这里脚本找的路径是mmc0_extlinux/extlinux.conf ,而上面原子的boot分区里面只有mmc0_extlinux/stm32mp157d-atk_extlinux.conf。
这里就涉及到yocto bootfs镜像里面的内容了,这部分下节单独再开一章来分析。

找到extlinux.conf 以后执行 sysboot mmc 0:4 any 0xc4100000 xxx_extlinux.conf 就会根据配置启动linux内核了。

本节告一段落

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/162815.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

实现系统调用

文章目录前言前置知识实验操作实现一实验二实验三实验四实验五前言 博客记录《操作系统真象还原》第十二章实验的操作~ 实验环境:ubuntu18.04VMware , Bochs下载安装 实验内容: 实现系统调用。实现write系统调用。实现printf。 3.1 仅支持…

Simulink 自动代码生成电机控制:关于无传感控制开环启动控制的仿真和开发板运行

目录 开环启动原理 开环启动建模实现 开环启动仿真 代码生成和验证 总结 开环启动原理 永磁同步电机开环三步启动是比较传统也是比较常用的启动方式,典型的启动有: 对齐:也说是说的转子预定位,就是通过手动给定一个初始角度…

mybatis 初始化加载xml解析

一、标题解析xml 的三大对象:XMLConfigBuilder、XMLMapperBuilder、XMLStatementBuilder XMLConfigBuilder 会把mybatis-config.xml所有元素进行解析。当碰到mappers时,会进行遍历。mappers中有几个mapper,就会创建几个XMLMapperBuilder 去进…

【Day3】链表理论基础、203移除链表元素、707设计链表、206反转链表

【Day3】链表理论基础、203移除链表元素、707设计链表、206反转链表链表理论基础链表的类型链表的存储方式链表的定义链表的操作203 移除链表元素设置虚拟头节点无虚拟头节点707设计链表206反转链表双指针法递归法while和for链表理论基础 链表是一种通过指针串联在一起的线性结…

C++版Android实时投屏软件系统源码,安卓手机投屏软件源码,无需root权限

QtScrcpy QtScrcpy 可以通过 USB / 网络连接Android设备,并进行显示和控制。无需root权限。 同时支持 GNU/Linux ,Windows 和 MacOS 三大主流桌面平台。 完整代码下载地址:C版Android实时投屏软件系统源码 它专注于: 精致 (仅显示设备屏幕…

sentence-transformers(SBert)中文文本相似度预测(附代码)

前言 训练文本相似度数据集并进行评估:sentence-transformers(SBert)预训练模型:chinese-roberta-wwm-ext数据集:蚂蚁金融文本相似度数据集前端:Vue2elementuiaxios后端:flask 训练模型 创建网络:使用Sb…

c语言公司考勤系统

1.要求 考勤系统是公司人事管理重要环节,用于记录员工迟到、早退、缺席、请假等出勤情况,并能提供数据统计功能。系统需求如下: 认证用户,如密码方式; 设置上下班时间,并能判断是否迟到、早退; 记录出勤状况,能记录每日…

基础IO(2)--文件描述符以及输入输出重定向

文件描述符fd 文件操作的本质是进程和被打开文件的关系。 进程可以打开多个文件&#xff0c;这些被打开的文件由OS管理&#xff0c;所以操作系统必定要为文件创建对应的内核数据结构标识文件–struct file{}【与C语言的FILE无关】 通过如下程序 #include <stdio.h> #…

uni-app在真机调试下兼容ethers的方法

目录 一、安装ethers 二、renderjs 三、注意事项 uni-app开发跨平台应用程序&#xff0c;项目搭建主要前端框是Uni-app Vue3 TS Vite&#xff0c;项目搭建参考文章Uni-app Vue3 TS Vite 创建项目 Hbuilderx版本是3.6.17 一、安装ethers yarn add ethers 如果像ether…

【Python】用xpath爬取2022热梗保存到txt中并生成词云

本文收录于《python学习笔记》专栏&#xff0c;这个专栏主要是我学习Python中遇到的问题&#xff0c;学习的新知识&#xff0c;或总结的一些知识点&#xff0c;我也是初学者&#xff0c;可能遇到的问题和大部分新人差不多&#xff0c;在这篇专栏里&#xff0c;我尽可能的分享出…

MySQL 索引 学习

索引 主键索引&#xff08;PRIMARY KEY&#xff09; 唯一标识&#xff0c;主键不可重复&#xff0c;只能有一个主键 唯一索引&#xff08;UNIQUE KEY&#xff09; 索引列 常规索引&#xff08;KEY/INDEX&#xff09;全文索引&#xff08;FullText&#xff09; 可以快速定位数据…

excel拆分技巧:如何快速对金额数字进行分列

金额数字分列&#xff0c;相信是做财务的小伙伴们经常遇到的问题。网上关于金额数字分列的方法很多&#xff0c;但用到的公式大都比较复杂。今天我们就来分享一个最简单的公式&#xff0c;仅用LEFT、RIGHT和COLUMN三个函数&#xff0c;就能达到效果&#xff01;在财务工作中&am…

Tapdata Cloud 场景通关系列:将数据导入阿里云 Tablestore,获得毫秒级在线查询和检索能力

【前言】作为中国的 “Fivetran/Airbyte”, Tapdata Cloud 自去年发布云版公测以来&#xff0c;吸引了近万名用户的注册使用。应社区用户上生产系统的要求&#xff0c;Tapdata Cloud 3.0 将正式推出商业版服务&#xff0c;提供对生产系统的 SLA 支撑。Tapdata 目前专注在实时数…

【论文阅读 CIKM2014】Extending Faceted Search to the General Web

文章目录ForewordMotivationMethodQuery facet generation:Facet feedbackEvaluationForeword This paper is from CIKM 2014, so we only consider the insightsI have read this paper last month and today i share this blogThere are many papers that have not been sha…

Docker网络原理详解

文章目录理解Docker0Docker 是如何处理容器网络访问的&#xff1f;Docker0网络模型图容器互联--Link自定义网络网络连通理解Docker0 查看本机IP ip addr1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00…

application.properties的作用

springboot这个配置文件可以配置哪些东西 官方配置过多了解原理 这个properties文件其实是可以删掉的&#xff0c;官方是不推荐使用这个文件的&#xff0c;可以将其换成安排application.yaml。名字不能变&#xff0c;因为SpringBoot使用的是一个全局的配置文件 application.…

linux系统中使用QT实现CAN通信的方法

大家好&#xff0c;今天主要和大家分享一下&#xff0c;如何使用QT中的CAN Bus的具体实现方法。 目录 第一&#xff1a;CAN Bus的基本简介 第二&#xff1a;CAN通信应用实例 第三&#xff1a;程序的运行效果 第一&#xff1a;CAN Bus的基本简介 从QT5.8开始&#xff0c;提供…

C语言-柔性数组与几道动态内存相关的经典笔试题(12.2)

目录 思维导图&#xff1a; 1.柔性数组 1.1柔性数组的特点 1.2柔性数组的使用 1.3柔性数组的优势 2.几道经典笔试题 2.1题目1 2.2题目2 2.3题目3 2.4题目4 写在最后&#xff1a; 思维导图&#xff1a; 1.柔性数组 1.1柔性数组的特点 例&#xff1a; #include <…

javaEE 初阶 — java对于的操作文件

文章目录1. File 类概述2. 代码示例2.1 示例1&#xff1a;以绝对路径为例&#xff0c;演示获取文件路径2.2 示例2&#xff1a;以相对路径为例&#xff0c;演示获取文件路径2.3 示例3&#xff1a;测试文件是否存在、测试是不是文件、测试是不是目录2.4 示例4&#xff1a;创建文件…

27.函数指针变量的定义, 调用函数的方法,函数指针数组

函数指针变量的定义 返回值类型&#xff08;*函数指针变量名&#xff09;&#xff08;形参列表&#xff09;; int( *p )( int , int );//定义了一个函数指针变量p&#xff0c;p指向的函数必须有一个整型的返回值&#xff0c;有两个整型参数。 int max(int x, int y) { } int m…