uboot启动第一阶段——start.S(一)

1. 引入 start.S

(1)通过对链接脚本的分析可知,整个程序的入口取决于链接脚本中 ENTRY 声明的地方。在 uboot.lds 中可以看到 ENTRY(_start),因此 _start 就是整个程序的入口,而 _start 所在的文件就是整个程序的起始文件。通过搜索可知,_start 存在 start.S 中,因此 start.S 就是整个程序的起始文件。

2. 头文件

代码:28 ~ 33 行

#include <config.h>
#include <version.h>
#if defined(CONFIG_ENABLE_MMU)
#include <asm/proc/domain.h>
#endif
#include <regs.h>

(1)#include <config.h>

include/config.h 文件不是源码中自带的,而是通过配置文件 mkconfig 自动生成的。它的内容很简单,如下所示:

        #include <configs/x210_sd.h>

通过分析可知,这里包含的是 include/configs/x210_sd.h 文件(这个文件是整个 uboot 移植时的配置文件,里面有很多宏)。因此分析 start.S 时,要考虑 include/configs/x210_sd.h 。

(2)#include <version.h>

include/version.h 文件的内容如下所示:

        #include "version_autogenerated.h"。

include/version_autogenerated.h 头文件是在编译时自动生成的,这里面只有一个宏定义,如下所示:

        #define U_BOOT_VERSION "U-Boot 1.3.4"

这个宏来自于主 Makefile 的配置值,并且在程序中被调用。在 uboot 启动过程中,串口打印出的 uboot 的版本号就来源于这里。

(3)#include <asm/proc/domain.h>

include/asm 是一个软链接,在 uboot 中本来是没有的,是在配置时创建的(详情参考 mkconfig),实际指向 include/asm-arm 目录。经过以上分析可知,这里实际包含的是 include/asm-arm/proc/domain.h 文件。

(4)#include <regs.h>

include/regs.h 也是一个软连接,也是在配置时创建的,实际指向 include/s5pc110.h 。

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

(6)思考:这里为什么不直接包含,而是要用符号链接的方式?

这样的设计主要是为了可移植性。因为如果直接包含,则start.S文件和CPU架构(和硬件)相关了,可移植性就差了,假如把uboot移植到mips架构下,则start.S源代码中所有的头文件包含全部要修改。但是用了符号链接之后,start.S中源代码就不需要改,只需要在移植时,根据硬件确定在符号链接的指向,这样就具有可移植性了。

3. 启动代码的 16 字节头部

代码:49 ~ 54 行

#if defined(CONFIG_EVT1) && !defined(CONFIG_FUSED)
	.word 0x2000
	.word 0x0
	.word 0x0
	.word 0x0
#endif

(1)从代码中可以看出:若定义了 CONFIG_EVT1 并且没有定义 CONFIG_FUSED,那么就定义 4 字节空间。

(2)在裸机部分,SD 卡启动(或 Nand 启动)启动时,需要 16 字节的校验头(mkv210image.c 就是用来计算这个校验头的),但是当时并没有详细考虑过这个问题,是因为:dnw 方式启动时不需要这 16 字节;SD 卡启动时,mkv210image.c 会给镜像加上 16 字节的校验头。

(3)这里只是在开头位置放置了 16 字节的填充占位,这里的占位只是保证了镜像头部有 16 字节,并不保证它的内容是对的,这 16 个字节的值还需要后面去重新计算和填充的。

4. 异常向量表构建

代码:56 ~ 83 行

.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

_undefined_instruction:
	.word undefined_instruction
_software_interrupt:
	.word software_interrupt
_prefetch_abort:
	.word prefetch_abort
_data_abort:
	.word data_abort
_not_used:
	.word not_used
_irq:
	.word irq
_fiq:
	.word fiq
_pad:
	.word 0x12345678 /* now 16*4=64 */
.global _end_vect
_end_vect:

(1)异常向量表是 CPU 设计时决定的,是硬件决定的。

(2)异常向量表的所有异常都应被处理,否则程序会飞。

(3)复位异常处理的代码时:

        b reset

CPU 复位后真正去执行的有效的代码是 reset 处的代码,因此符号 reset 处的代码才是真正的有意义的代码的开始地方。

5. 有点意思的 deadbeef

代码:85 行

	.balignl 16,0xdeadbeef

(1)该条指令是让当前地址按 16 字节对其,若没有对齐,用 0xdeadbeef 数字来填充,直到对齐。

(2)0xdeadbeef 没有什么特别的意义,但是内容很有意思,刚好组成了一个单词 dead beep (坏牛肉)。

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

6. 一些定义

代码:86 ~ 135 行

/*
 *************************************************************************
 *
 * Startup Code (reset vector)
 *
 * do important init only if we don't start from memory!
 * setup Memory and board specific bits prior to relocation.
 * relocate armboot to ram
 * setup stack
 *
 *************************************************************************
 */

_TEXT_BASE:
	.word	TEXT_BASE

/*
 * Below variable is very important because we use MMU in U-Boot.
 * Without it, we cannot run code correctly before MMU is ON.
 * by scsuh.
 */
_TEXT_PHY_BASE:
	.word	CFG_PHY_UBOOT_BASE

.globl _armboot_start
_armboot_start:
	.word _start

/*
 * These are defined in the board-specific linker script.
 */
.globl _bss_start
_bss_start:
	.word __bss_start

.globl _bss_end
_bss_end:
	.word _end

#if defined(CONFIG_USE_IRQ)
/* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START
IRQ_STACK_START:
	.word	0x0badc0de

/* IRQ stack memory (calculated at run-time) */
.globl FIQ_STACK_START
FIQ_STACK_START:
	.word 0x0badc0de
#endif

(1)TEXT_BASE

第 100 行的这个 TEXT_BASE 是在 Makefile 配置阶段时的那个 TEXT_BASE,也就是链接时指定的 uboot 中的那个链接地址,它的值时 0xc3e00000 。

在源代码中和配置的 Makefile 中,很多变量是互相关联的,有些符号的值可以从 Makefile中 传递到源代码中。

(2)CFG_PHY_UBOOT_BASE

uboot 在DDR中的物理地址  ——  0x33e00000,它的定义放在 include/configs/x210_sd.h,如下所示:

        #define CFG_PHY_UBOOT_BASE    MEMORY_BASE_ADDRESS + 0x3e00000

(3)_armboot_start

这个会在重定位时用到

(4)_bss_start、_bss_end

用于清理 bss 段用的

猜你喜欢

转载自blog.csdn.net/linuxweiyh/article/details/82427725