ARM uboot源码分析1-启动第一阶段

news2025/6/9 22:53:00

一、start.S 引入

1、u-boot.lds 中找到 start.S 入口

(1) 在 C 语言中整个项目的入口就是 main 函数(这是 C 语言规定的),所以譬如说一个有 10000 个.c 文件的项目,第一个要分析的文件就是包含了 main 函数的那个文件。

(2) 在 uboot 中因为有汇编阶段参与,因此不能直接找 main.c。整个程序的入口取决于链接脚本中 ENTRY 声明的地方
ENTRY(_start) 。因此 _start 符号所在的文件就是整个程序的起始文件,_start 所在处的代码就是整个程序的起始代码。

在这里插入图片描述


二、start.S 解析1

在这里插入图片描述

1、不简单的头文件包含

(1) #include <config.h>config.h 是在 include 目录下的,这个文件不是源码中本身存在的文件,而是配置过程中自动生成的文件。(详见 mkconfig 脚本)。这个文件的内容其实是包含了一个头文件:#include <configs/x210_sd.h>".
在这里插入图片描述


(2) 经过分析后,发现 start.S 中包含的第一个头文件就是:include/configs/x210_sd.h,这个文件是整个 uboot 移植时的配置文件。这里面是好多宏。因此这个头文件包含将 include/configs/x210_sd.h 文件和 start.S 文件关联了起来。因此之后在分析start.S 文件时,主要要考虑的就是 x210_sd.h 文件。

在这里插入图片描述


(3) #include <version.h>include/version.h 中包含了 include/version_autogenerated.h ,这个头文件就是配置过程中自动生成的。里面就一行内容:#define U_BOOT_VERSION "U-Boot 1.3.4"。这里面定义的宏 U_BOOT_VERSION 的值是一个字符串,字符串中的版本号信息来自于 Makefile 中的配置值。这个宏在程序中会被调用,在 uboot 启动过程中会串口打印出 uboot 的版本号,那个版本号信息就是从这来的。

在这里插入图片描述


在这里插入图片描述

(4) #include <asm/proc/domain.h>。asm 目录不是 uboot 中的原生目录,uboot 中本来是没有这个目录的。asm 目录是配置时创建的一个符号链接,实际指向的就是 asm-arm(详解上一章节分析 mkconfig 脚本时).

在这里插入图片描述


(5) 经过分析后发现,实际文件是:include/asm-arm/proc-armv/domain.h


(6) 从这里可以看出之前配置时创建的符号链接的作用,如果没有这些符号链接则编译时根本通不过,因为找不到头文件。(所以 uboot 不能在 windows 的共享文件夹下配置编译,因为 windows 中没有符号链接)


思考:为什么 start.S 不直接包含 asm-arm/proc-armv/domain.h,而要用 asm/proc/domain.h。这样的设计主要是为了可移植性。因为如果直接包含,则 start.S 文件和 CPU 架构(和硬件)有关了,可移植性就差了。譬如我要把 uboot 移植到 mips 架构下,则 start.S 源代码中所有的头文件包含全部要修改。我们用了符号链接之后,则 start.S 中源代码不用改,只需要在具体的硬件移植时配置不同,创建的符号链接指向的不同,则可以具有可移植性。


三、start.S 解析2

1、启动代码的 16 字节头部

在这里插入图片描述

(1) 裸机中讲过,在 SD 卡启动/ Nand 启动等,整个镜像开头需要 16 字节的校验头。(mkv210image.c 中就是为了计算这个校验头)。我们以前做裸机程序时根本没考虑这 16 字节校验头,因为:

  1. 如果我们是 usb 启动直接下载的方式启动的,则不需要 16 字节校验头(irom application note)
  2. 如果是 SD 卡启动,mkv210image.c 中会给原镜像前加 16 字节的校验头。

在这里插入图片描述


在这里插入图片描述


(2) uboot 这里 start.S 中在开头位置放了 16 字节的填充占位,这个占位的 16 字节只是保证正式的 image 的头部确实有 16 字节,但是这 16 字节的内容是不对的,还是需要后面去计算校验和然后重新填充的。


2、异常向量表的构建

在这里插入图片描述

(1) 异常向量表是硬件决定的,软件只是参照硬件的设计来实现它。

(2) 异常向量表中每种异常都应该被处理,否则真遇到了这种异常就跑飞了。但是我们在 uboot 中并未非常细致的处理各种异常。

(3) 复位异常处的代码是:b reset,因此在 CPU 复位后真正去执行的有效代码是 reset 处的代码,因此 reset 符号处才是真正的有意义的代码开始的地方。


3、有点意思的 deadbeef

在这里插入图片描述

(1) .balignl 16,0xdeadbeef. 这一句指令是让当前地址对齐排布;如果当前地址不对齐,则自动向后走地址直到对齐,并且向后走的那些内存要用 0xdeadbeef 来填充。

(2) 0xdeadbeef 这是一个十六进制的数字,这个数字很有意思,组成这个数字的十六进制数全是 abcdef 之中的字母,而且这 8 个字母刚好组成了英文的 dead beef 这两个单词,字面意思是坏牛肉。

(3) 为什么要对齐访问?有时候是效率的要求,有时候是硬件的特殊要求。


4、TEXT_BASE 等

在这里插入图片描述

(1) 第 100 行这个 TEXT_BASE 就是上个课程中分析 Makefile 时讲到的那个配置阶段的 TEXT_BASE其实就是我们链接时指定的 uboot 的链接地址。(值就是 c3e00000)

(2) 源代码中和配置 Makefile 中很多变量是可以互相运送的。简单来说有些符号的值可以从 Makefile 中传递到源代码中。

在这里插入图片描述


四、start.S 解析3

在这里插入图片描述

(1) CFG_PHY_UBOOT_BASE 33e00000 uboot 在 DDR 中的物理地址


1、设置 CPU 为 SVC 模式

在这里插入图片描述

(1) msr cpsr_c, #0xd3 将 CPU 设置为禁止 FIQ 、IRQ,ARM 状态,SVC 模式。

(2) 其实 ARM CPU 在复位时默认就会进入 SVC 模式,但是这里还是使用软件将其置为 SVC 模式。整个 uboot 工作时 CPU 一直处于 SVC 模式。


2、设置 L2、L1cache 和 MMU

在这里插入图片描述
在这里插入图片描述

(1) bl disable_l2cache // 禁止L2 cache
(2) bl set_l2cache_auxctrl_cycle // l2 cache 相关初始化
(3) bl enable_l2cache // 使能 l2 cache
(4) 刷新 L1 cacheicachedcache
(5) 关闭 MMU.
总结:上面这 5 步都是和 CPU 的 cache 和 mmu 有关的,不用去细看,大概知道即可。


3、识别并暂存启动介质的选择

在这里插入图片描述

(1) 从哪里启动是由 SoC 的 OM5:OM0 这 6 个引脚的高低电平决定的。

(2) 实际上在 210 内部有一个寄存器(地址是0xE0000004),这个寄存器中的值是硬件根据 OM 引脚的设置而自动设置值的。这个值反映的就是 OM 引脚的接法(电平高低),也就是真正的启动介质是谁。

(3) 我们代码中可以通过读取这个寄存器的值然后判断其值来确定当前选中的启动介质是 Nand 还是 SD 还是其他的。

(4) start.S 的 225-227 行执行完后,在 r2 寄存器中存储了一个数字,这个数字等于某个特定值时就表示 SD 启动,等于另一个特定值时表示从 Nand 启动····

(5) 260 行中给 r3 中赋值#BOOT_MMCSD(0x03),这个在 SD 启动时实际会被执行,因此执行完这一段代码后 r3 中存储了0x03,以后备用。

在这里插入图片描述


4、设置栈(SRAM 中的栈)并调用 lowlevel_init

在这里插入图片描述

(1) 284-286 行:第一次设置栈。这次设置栈是在 SRAM 中设置的,因为当前整个代码还在 SRAM 中运行,此时 DDR 还未被初始化,还不能用。栈地址 0xd0036000 是自己指定的,指定的原则就是这块空间只给栈用,不会被别人占用。

在这里插入图片描述


(2) 在调用函数前初始化栈,主要原因是在被调用的函数内还有再次调用函数,而 BL 只会将返回地址存储到 LR 寄存器中,但是我们只有一个 LR 寄存器,所以在第二层调用函数前,要先将 LR 寄存器入栈,否则函数返回时第一层函数的返回地址就丢了。


五、start.S 解析4

进入函数:lowlevel_init。

在这里插入图片描述


(1) 找到 lowlevel_init 函数真正的地方,是在 uboot/board/samsumg/x210/lowlevel_init.S 中。

在这里插入图片描述


1、检查复位状态

在这里插入图片描述

(1) 复杂 CPU 允许多种复位情况。譬如直接冷上电、热启动、睡眠(低功耗)状态下的唤醒等,这些情况都属于复位。所以我们在复位代码中要去检测复位状态,来判断到底是哪种情况。

(2) 判断哪种复位的意义在于:冷上电时,DDR 是需要初始化才能用的;而热启动或者低功耗状态下的复位,则不需要再次初始化 DDR


2、IO 状态恢复

在这里插入图片描述

(1) 这个和上一个 “1、检查复位状态”,与我们的主线启动代码都无关,因此不用去管他。


3、关看门狗

在这里插入图片描述

(1) 参考裸机中看门狗章节


4、一些 SRAM SROM 相关 GPIO 设置

在这里插入图片描述

(1) 与主线启动代码无关,不用管。


5、供电锁存

在这里插入图片描述

(1) lowlevel_init.S 的第 100-104 行,开发板供电锁存。


总结:在前 100 行,lowlevel_init.S 中并没有做太多有意义的事情(除了关看门狗、供电锁存外),然后下面从 110 行才开始进行有意义的操作。


源自朱有鹏老师.

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

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

相关文章

分享75个JS焦点图代码,总有一款适合您

分享75个JS焦点图代码&#xff0c;总有一款适合您 75个JS焦点图代码下载链接&#xff1a;https://pan.baidu.com/s/1WuydBKN3eYd3H64lPXv0Fw?pwd0nq7 提取码&#xff1a;0nq7 Python采集代码下载链接&#xff1a;https://wwgn.lanzoul.com/iKGwb0kye3wj base_url "…

MySQL面试题:关系型数据库SQL和非关系型数据库NoSQL

文章目录一、四大非关系型数据库与关系型数据库的对比1. 关系型数据库2. 基于列的数据库3. 键值对存储4. 文档存储5. 图形数据库参考文章&#xff08;金文&#xff09;&#xff1a;四大非关系型数据库类型&#xff0c;你知道多少 参考文章&#xff1a;“行式存储”和“列式存储…

2022虎符CTF-WEB赛后复现

1、ezphp 参考Jacko师傅的这篇虎符CTF 写的已经很详细了&#xff0c;先简单梳理一下题目&#xff0c;题目与P师傅的这篇文章类似我是如何利用环境变量注入执行任意命令。简单来说就是不同的系统&#xff0c;他的system命令调用的命令不同。 php中调用system本质上是调用了sh…

UDP报文结构

UDP协议 基本特点&#xff1a;无连接、不可靠传输、面向数据报、全双工 UDP协议报文结构 &#xff0c;以下分别是种画法 对上图进行解释&#xff1a; UDP就会把载荷数据&#xff08;就通过UDP socket ,也就是send方法拿来的数据&#xff0c;基础上再在前面拼接上几个字节的…

appium ios真机自动化环境搭建运行(送源码)

appium ios真机自动化环境搭建&运行&#xff08;送源码&#xff09; 目录&#xff1a;导读 &#xff08;1&#xff09;安装JDK&#xff0c;并配置环境变量&#xff0c;方法如下&#xff1a; &#xff08;2&#xff09;安装Xcode、Xcode commandline tools和iOS模拟器 &…

如何判断反馈电路的类型-反馈类型-三极管

如何判断反馈电路的类型 反馈电路类型很多&#xff0c;可根据不同的标准分类&#xff1a; ①根据反馈的极性分&#xff1a;有正反馈和负反馈。 ②根据反馈信号和输出信号的关系分&#xff1a;有电压反馈和电流反馈。 ③根据反馈信号和输入信号的关系分&#xff1a;有串联反…

渗透测试 -- IP、端口信息收集

数据来源 01 IP信息收集 1&#xff09;IP反查域名 同IP网站查询&#xff0c;同服务器网站查询 - 站长工具 专业精准的IP库服务商_IPIP 2&#xff09;域名查询IP IP/IPv6查询&#xff0c;服务器地址查询 - 站长工具 或直接 ping 一下域名就会返回IP 3&#xff09;CDN 如…

补天平台安全问题收录情况分享记录

声明 本文是学习2017年上半年 补天平台漏洞收录分析报告. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 补天平台及补天白帽大会介绍 “补天平台”&#xff0c;成立于2013年3月&#xff0c;全称为“补天漏洞响应平台”。平台旨在收集散落在民间的安…

MySQL8.0之前实现row_number以及计算玩家连续登录天数

使用MySQL 5.7版本统计 玩家连续登录天数 原始数据 玩家同一天多次登录只保留一条 select DISTINCT(FROM_UNIXTIME(login_time,%Y-%m-%d)) as login_date,rid from t_log_login order by rid; 借助两个变量统计每个玩家登录日期对应的次数 SELECT * FROM(SELECT DISTINCT …

云镜CVE-2022-25578复现

CVE-2022-25578复现漏洞信息漏洞复现读取flag&#x1f349; shell来源&#xff1a;https://yunjing.ichunqiu.com/cve/detail/960?type1&pay2漏洞信息 漏洞名称taocms v3.0.2允许攻击者通过编辑.htaccess文件执行任意代码漏洞编号CVE-2022-25578危害等级超危漏洞类型任意…

day34|343. 整数拆分、96.不同的二叉搜索树

343. 整数拆分 给定一个正整数 n &#xff0c;将其拆分为 k 个 正整数 的和&#xff08; k > 2 &#xff09;&#xff0c;并使这些整数的乘积最大化。 返回 你可以获得的最大乘积 。 示例 1: 输入: n 2 输出: 1 解释: 2 1 1, 1 1 1。 示例 2: 输入: n 10 输出: 36 解…

电子技术——共栅(共基)放大器

电子技术——共栅&#xff08;共基&#xff09;放大器 在本节我们学习IC中共栅&#xff08;共基&#xff09;放大器的配置&#xff0c;虽然我们之前在分立电路中学习过共栅&#xff08;共基&#xff09;放大器的配置。但是在IC中共栅&#xff08;共基&#xff09;放大器主要作为…

MES系统助力电子厂行业,打造高能效工厂

ES主要包括生产计划系统、工艺管理系统、质量管理系统、生产过程管理系统、设备管理系统、仓储管理系统及数据采集和统计分析系统等。实现生产过程可视化、可追溯。管理人员可以在管理界面对生产实时控制&#xff0c;从而根据需要精准调整生产&#xff0c;达到提高生产效率、缩…

算法与数据结构理解

目录1、数据结构与算法1.1 定义1.2 常见数据结构1.3 常用算法2、插入排序3、希尔排序4、归并排序1、数据结构与算法 1.1 定义 数据结构&#xff1a;是计算机中存储、组织数据的方式。具有一定逻辑关系&#xff0c;应用某种存储结构&#xff0c;并且封装了相应操作的数据元素集…

HTML浪漫动态表白代码+音乐(附源码)

HTML浪漫表白求爱(附源码)&#xff0c;内含4款浪漫的表白源码&#xff0c;可用于520&#xff0c;情人节&#xff0c;生日&#xff0c;求爱场景&#xff0c;下载直接使用。 直接上源码吧 一.红色爱心 1.效果 实际效果是动态的哦 2.源码 复制粘贴即可运行哦 <!DOCTYPE…

JVM 线程本地分配缓存TLAB

什么是TLAB 从内存模型而不是垃圾收集的角度&#xff0c;对 Eden 区域继续进行划分&#xff0c;JVM 为每个线程分配了一个私有缓存区域&#xff0c;它包含在 Eden 空间内 多线程同时分配内存时&#xff0c;使用 TLAB 可以避免一系列的非线程安全问题&#xff0c;同时还能提升…

一文读懂CXL协议

2001年&#xff0c;英特尔公布了第三代I/O技术——3GIO技术&#xff08;后更名为PCI Express&#xff0c;即PCIe&#xff09;&#xff0c;以高性能、高扩展性、高可靠性及出色的兼容性取代了包括AGP和PCI在内所有的内部总线并且不断升格。例如&#xff0c;2019年5月底公布的PCI…

JUC锁与AQS技术【我的Android开发技术】

JUC锁与AQS技术【我的Android开发技术】 AQS原理 AQS就是一个同步器&#xff0c;要做的事情就相当于一个锁&#xff0c;所以就会有两个动作&#xff1a;一个是获取&#xff0c;一个是释放。获取释放的时候该有一个东西来记住他是被用还是没被用&#xff0c;这个东西就是一个状…

六、Linux文件 - lseek函数

目录 1.lseek函数 2.lseek函数实战 2.1宏SEEK_CUR的用法 2.2宏SEEK_END的用法 3.Open函数实战 - O_APPEND的用法 4.Linux在库函数中寻找相应的宏定义 1.lseek函数 off_t lseek(int fd,off_t offset,int whence);光标的偏移量 fd:文件描述符offset:偏移量whence: SEEK_…

macOS中虚拟机桥接模式分配静态ip

1.首先使用dhclient命令&#xff0c;在局域网中分配一个C类地址。 2.获得地址后&#xff0c;输入ifconfig&#xff0c;查看分配的地址。 3.然后编辑vi /etc/sysconfig/network-scripts/ifcfg-en***文件 在该配置文件中编辑&#xff0c;设置ONBOOTyes&#xff0c;而后添加静态配…