uboot初步学习

来源:互联网 发布:淘宝有哪些正品鞋店 编辑:程序博客网 时间:2024/06/18 10:02

文中使用树莓派的uboot说明。


bootloader是系统起来以后执行的起点。比如arm cpu从地址为0的地址开始执行执行。

一般地址为0的位置映射了rom .我们把bootloader放到这里。加电以后就从bootloader的第一句代码执行开始,假定我们的bootload是uboot


uboot 最初编译初来的时候是一个elf文件名字就叫uboot。CPU从0开始执行指令。遇到的是一个ELF头部肯定是有问题的。CPU只认得可以执行的代码。所以后续会将uboot中间代码段部分抽取初来。也就是去掉elf头部和其他不要的信息。只留下可执行的代码段。


uboot的起始点在 Start.s 的_start函数。(arch/armcpu/arm1176/start.s),那怎么保证start.s里面的_start函数在第一位呢?在看到/arm/cpu/u-boot.lds

里面

OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = 0x00000000;


.......

这里表明了连接器进行链接的时候。将_start函数放到第一个连接处。地址为相对0000000。也就是text段的0地址。

cpu上电以后 就从start.s这开始


查看一下start的初期几条指令


_start: b reset

b代表跳转的意思。

就是跳转到reset执行

类似于 jmp 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

这几条指令都是类似

ldr 目的寄存器  <存储器地址>

相当于 mov eax,[_undefined_instruction]

也就是将 _undefined_instruction里面的值存放到pc寄存器里面。

pc寄存器始终指向下一条要执行的指令。相当于epi。所以执行完 ldr pc, _undefined_instruction 以后执行的第一条指令一定是

[_undefined_instruction] 这个地址上的函数。 [_undefined_instruction]=xxx_function

我们看到后面有

_undefined_instruction:
.word undefined_instruction

表明 _undefined_instruction是指针 里面包含了undefined_instruction的地址。


c语言理解为

*_undefined_instruction = undefined_instruction

后续的

_pad:
.word 0x12345678 /* now 16*4=64 */

主要是用于对齐附加的一些pad


//这里表示后续需要用16字节对齐 不足的用0xdeadbeef填充

.global _end_vect
_end_vect:
.balignl 16,0xdeadbeef


在接下来 有一个标号是_TEXT_BASE 里面的数据是 CONFIG_SYS_TEXT_BASE

.globl _TEXT_BASE
_TEXT_BASE:
.word CONFIG_SYS_TEXT_BASE

我们来看看CONFIG_SYS_TEXT_BASE是多少

在rpi_uboot/include/configs的rpi_b.h里面的到了这个数据。

#define CONFIG_SYS_TEXT_BASE0x00008000

说明textbase要放在8000的地方 也就是代码段放在 0X8000的地方。由于_start定义了要放在相对位置为0的地方。所以实际上绝对位置就是8000

后续还有几个这样的定义。一并讲了。对应的值去rpi_b.h里面找


.globl _TEXT_BASE
_TEXT_BASE:
.word CONFIG_SYS_TEXT_BASE


*TEXT_BASE=CONFIG_SYS_TEXT_BASE=0x8000


_TEXT_PHY_BASE:
.word CONFIG_SYS_PHY_UBOOT_BASE


*_TEXT_PHY_BASE=CONFIG_SYS_PHY_UBOOT_BASE=0x8000


接下来遇到了一个 __bss_start 以及__bss_end__以及  _end 没有在start.s里面 ,而是在/arm/cpu/u-boot.lds 里面定义了。

使用.globl导出了这三个地址。作为全局变量。后续会要用到的

.globl _bss_start_ofs
_bss_start_ofs:
.word __bss_start - _start


.globl _bss_end_ofs
_bss_end_ofs:
.word __bss_end__ - _start

.globl _end_ofs
_end_ofs:
.word _end - _start


lds的定义一般就是告诉某些 数据应该放在哪个位置而已。


后续是

.globl IRQ_STACK_START_IN
IRQ_STACK_START_IN:
.word 0x0badc0de

这里定义了irql栈的位置


后续就是reset函数了。

也就是开始的b reset跳转到的地方


reset:
/*
* set the cpu to SVC32 mode
*/
mrs r0, cpsr

       将cpsr的值赋值给r0
bic r0, r0, #0x3f
orr r0, r0, #0xd3
msr cpsr, r0


CPSR 是当前的程序状态寄存器(Current Program Status Register),

而 SPSR 是保存的程序状态寄存器(Saved Program Status Register)。

操作CPSR和SPSR的只能是mrs和msr指令。

上面的操作就是去除cpsr寄存器 设置某些标记位。然后在放回去。使得cpu进入svc32模式
















0 0
原创粉丝点击