Linux u-boot加载过程

来源:互联网 发布:linux echo<> 编辑:程序博客网 时间:2024/06/06 00:06

Linux u-boot加载过程
----基于freescale i.MX6

近期做项目需要修改u-boot,刚好趁机研究一把linux u-boot。

以前没接触过u-boot,所以学习只能从头开始。
既然是从头开始, 那就从u-boot的加载过程起步吧。

本文主要包括以下内容:
1、cpu如何开始加载u-boot。
2、加载u-boot时的初期处理。
3、如何跳转到c代码。
c代码中的处理过程,以及后续处理,本文不作介绍。

做我们这个行当的,都知道程序需要跑在内存上(能够XIP的flash除外,此处不作介绍)。
但刚上电时,cpu并不知道它连了些什么东西,甚至连没连接内存也不知道,另外想在内存上执行,也总要把程序加载到内存才行。
如此看来,机器上电的处理比想象的要复杂不少!习惯了开机只是按下开关,想不到还有这么多东东隐藏在背后!!!
那么,程序到底是如何开始跑的呢?
启动过程一般在cpu的参考手册中都有介绍,我这边就不作详细介绍,但相关的部分,会稍微提一下。
上电后,cpu内部会做一些检查,如电压是否稳定,启动模式等等,之后会从地址0x00000000开始执行命令。
从地址0x00000000开始,一般是cpu的rom code,也就是cpu芯片上写死的。
rom code开始执行,会作很多处理,会处理什么呢?cpu厂商很清楚,呵呵。
其实,多数处理可以看看参考手册中的启动时序。
我们关心的:根据启动模式,确定启动设备;然后对启动设备进行验证,并进行初步初始化。
(也就是参考手册中有很多地方会说的,在启动过程中是什么样子,例如始终是 XX M,启动过程之后是另外一个样子,例如时钟变为 YY M)
初始化好了,然后就是去加载我们的程序了,也就是从启动设备上读取我们的程序。
从哪儿开始读取呢,当然是有道道的。参考手册中一般会指定各种启动设备中程序存放的地址。如i.MX6中,若从emmc启动,会从emmc的0x400 bytes地址开始读取程序(1K bytes的地方).
读过来的是个什么东东呢?直接可以跑的程序?
不是,参考手册中有说明。
i.MX6中读到的是一个IVT(image vector table)结构体,结构体的定义肯定是规定好的,不然rom code怎么知道如何解析该结构体?
i.MX6中对IVT结构体的定义:
header
entry: Absolute address of the first instruction to execute from the image
reserved1: Reserved and should be zero
dcd: Absolute address of the image DCD. The DCD is optional so this field may be set to NULL if no DCD is required. See
Device Configuration Data (DCD) for further details on DCD.
boot data: Absolute address of the Boot Data
self: Absolute address of the IVT. Used internally by the ROM
csf: Absolute address of Command Sequence File (CSF) used by the HAB library. See High Assurance Boot (HAB) for
details on secure boot using HAB. This field must be set to NULL when not performing a secure boot
reserved2: Reserved and should be zero

我们关系以下几个:
entry: 入口函数,在程序中指定,如:ENTRY(_start)
dcd: Device Configuration Data, 设备配置数据,用来配置设备的。因为刚上电,设备的参数都是默认的,不能达到最优效果,甚至有些设备不进行初始化根本就无法工作。
那怎么办呢?就需要在使用这些设备之前,进行一些设置,如内存等等。
dcd中可以设置如下这些东东:
Address range                                      Start address       Last Address
IOMUX Control (IOMUXC) registers     0x020E0000        0x020E3FFF
CCM register set                                   0x020C4000        0x020C7FFF
ANADIG registers                                 0x020C8000        0x020C8FFF
MMDC register set                                0x021B0000        0x021B7FFF
IRAM Free Space                                 0x00907000        0x00937FF0
EIM                                                       0x08000000        0x0FFEFFFF
DDR                                                      0x10000000        0xFFFFFFFF
DCD中命令的格式这儿就不介绍了,参考手册中有详细说明。

来看看IVT定义的例子吧:

.section ".text.flasheader", "x" b _start .org CONFIG_FLASH_HEADER_OFFSET ivt_header:       .word 0x402000D1 /* Tag=0xD1, Len=0x0020, Ver=0x40 */app_code_jump_v:  .word _startreserv1:          .word 0x0dcd_ptr:          .word dcd_hdrboot_data_ptr:   .word boot_dataself_ptr:         .word ivt_headerapp_code_csf:     .word 0x0reserv2:          .word 0x0



在该例子中,入口函数为_start,在start.S中定义;dcd_hdr 指向dcd image,在flashheader.S中定义;IVT结构体也定义在flashheader.S中;
boot_data是个结构体,定义在flashheader.S中:

boot_data:        .word TEXT_BASEimage_len:        .word _end_of_copy  - TEXT_BASE + CONFIG_FLASH_HEADER_OFFSETplugin:           .word 0x0



TEXT_BASE定义在config.mk中:

 TEXT_BASE = 0x27800000



CONFIG_FLASH_HEADER_OFFSET,看字面意思,就是flash header的偏移地址,flash header? 我们前面有个flashheader.S难道就是这个?
看了下其定义:

 #define CONFIG_FLASH_HEADER_OFFSET 0x400



原来就是flash header在启动设备上的偏移地址,也就IVT结构体在启动设备中的偏移。
_end_of_copy的定义在u-boot.lds中定义,应该就是u-boot结束的地方。
image_len为 _end_of_copy  - TEXT_BASE还可以理解,为什还要加个CONFIG_FLASH_HEADER_OFFSET?
难道是rom code是按照image len从启动设备的开始地址加载u-boot,所以要包含CONFIG_FLASH_HEADER_OFFSET??
另外在.text.flasheader段定义的地方有下面一行代码:

 .org CONFIG_FLASH_HEADER_OFFSET



难道是.text.flasheader段的头部故意空出来了CONFIG_FLASH_HEADER_OFFSET个bytes的空间?
看了下System.map,有如下:

27800400 t ivt_header



其中27800000是u-boot加载地址,而IVT开始的地方,即ivt_header在u-boot加载地址偏移CONFIG_FLASH_HEADER_OFFSET(0x400)的地方。
注意,这儿说的是加载地址,也就是内存中的地址,不是在启动设备上存储的地址。

知道了IVT的定义,并且知道rom code是从启动设备的固定地址来加载IVT,那么是如何将IVT放到启动设备的固定地址的呢?
我们知道,u-boot是被写到了启动设备的固定地址,也就是说,只要IVT结构体在u-boot的头部,就能够保证rom code能够加载到IVT。
的确是这样的,IVT在flashheader.S的头部,而flashheader.o又在u-boot的头部,所以IVT就在u-boot的头部。
这是通过u-boot.lds来实现的:
(u-boot.lds文件不长,干脆全列出来吧)

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")OUTPUT_ARCH(arm)ENTRY(_start)SECTIONS{ . = 0x00000000; . = ALIGN(4); .text    : {   /* WARNING - the following is hand-optimized to fit within */   /* the sector layout of our flash chips! XXX FIXME XXX */   board/freescale/mx6dl_14cytmap/flash_header.o (.text.flasheader)   cpu/arm_cortexa8/start.o   drivers/mmc/libmmc.a  (.text)   /* 其他 text 段*/   *(.text) } . = ALIGN(4); .rodata : { *(.rodata) } . = ALIGN(4); .data : { *(.data) } . = ALIGN(4); .got : { *(.got) } . = .; __u_boot_cmd_start = .; .u_boot_cmd : { *(.u_boot_cmd) } __u_boot_cmd_end = .; . = ALIGN(4); _end_of_copy = .; /* end_of ROM copy code here */ __bss_start = .; .bss : { *(.bss) } _end = .;}



从u-boot.lds可知,flashheader.o在代码段的首部,并且代码段在最前面,因此就保证了前面所说的IVT在启动设备上的固定位置。

rom code最初加载了哪些东东呢?
rom code根据启动设备的偏移地址,首先把uboot加载到iRame。
然后开始解析IVT结构体。
之后找到DCD所在的地址(在IVT)中,逐条执行DCD命令。主要是初始化内存等。
之后呢,找到entry函数,也就是IVT结构体中的entry成员,对应到上面的例子是_start函数,开始执行。
_start函数中start.S中定义:

.globl _start_start: b reset ldr pc, _undefined_instruction ldr pc, _software_interrupt ldr pc, _prefetch_abort ldr pc, _data_abort ldr pc, _not_used ldr pc, _irq ldr pc, _fiq ...



 
可见_start的第一句就跳转到了reset。之后是一些异常处理的东东。
再看看reset,也在start.S中。
reset的名称是自定义的,有些地方称为start_code。
reset主要完成以下工作:
1、set the cpu to SVC32 mode
2、初始化cpu的一些东东,如果需要的话
3、如果有必要,重新定位u-boot。其实就是判断启动地址,即_start的地址,与加载地址,即TEXT_BASE是否相同,如果不同,则将uboot从启动地址copy到加载地址。
4、设置stack、bss、irq、fiq,其实就是在内存中留出来一些空间。
5、看是否需要配置MMU。
6、最后:

 ldr pc, _start_armboot @ jump to C code



 将_start_armboot加载到pc寄存器,pc寄存器保存的是吓一条指令的地址,所以也就是跳到_start_armboot执行。
_start_armboot定义:

_start_armboot: .word start_armboot



start_armboot 是c代码中定义的函数。在代码Board.c中定义。
终于从汇编出来了。

 

2 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 官换机过保坏了怎么办 官换机在保坏了怎么办 留学生美国东西寄回国怎么办便宜 淘宝东西没到收货了怎么办 在淘宝上买东西被骗怎么办 网上把钱骗走了怎么办 在淘宝上卖号被骗了怎么办 如果淘宝商家保证金不够退款怎么办 天猫账号忘记了怎么办 姨妈来了10天了怎么办 微店商品无资质被下架怎么办 微店商品无资质怎么办 淘宝买东西提前确认收货了怎么办 苹果手机王者荣耀充值充多了怎么办 买家淘宝账号出现虚拟交易怎么办 贵州通登录不上怎么办 华为手机媒体声音小怎么办 苹果七内存满了怎么办 华为p9玩王者卡怎么办 鞋放健身房丢了怎么办 京东商家搞虚假活动怎么办 淘宝买的商品出现质量问题怎么办 买了重复的东西怎么办 借记卡在atm用不了怎么办 淘宝评论视频审核不通过怎么办 京东票据丢了怎么办 开拼多多找不到低价货源怎么办 要是校花追你该怎么办 苏宁自提逾期怎么办 天猫超市有问题怎么办 买的东西质量有问题怎么办 淘宝优惠额度大做不了怎么办 淘宝天猫拒绝退货退款怎么办 u盘变成活动分区怎么办 学生上课纪律差家长老师怎么办 老师管纪律学生打老师怎么办? 淘宝店铺层级排名下降怎么办 网购不支持该地区销售怎么办 分销公司佣金不给业务员怎么办 淘宝买家账号违规了怎么办 王者荣耀打野被队友抢野怎么办