uboot启动流程-uboot链接脚本u-boot.lds

一.  uboot 启动流程

本文我们来详细的分析一下 uboot 的启动流程,理清 uboot 是如何启动的。通过对 uboot 启动流程的梳理。

们就可以掌握一些外设是在哪里被初始化的,这样当我们需要修改这些外设驱动的时候就会心里有数。另外,通过分析 uboot 的启动流程可以了解 Linux 内核是如何被启动的。

注意: 分析 uboot启动流程的前提是,uboot源码需要经过编译。

二.   链接脚本 u-boot.lds

要分析 uboot 的启动流程,首先要找到“入口”,找到第一行程序在哪里。

程序的链接是由链接脚本来决定的,所以通过链接脚本可以找到程序的入口。连接脚本在uboot的根目录下u-boot.lds文件。
注意:如果没有编译过 uboot 的话链接脚本为 arch/arm/cpu/u-boot.lds。但这个不是最终使用的链接脚本,最终的链接脚本是在这个链接脚本的基础上生成的。编译一下 uboot,编译完成以后就会在 uboot 根目录下生成 u-boot.lds 文件。
只有编译 u-boot 以后才会在根目录下出现 u-boot.lds 文件!!!

打开链接脚本 u-boot.lds ,内容如下:
1 OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
2 OUTPUT_ARCH(arm)
3 ENTRY(_start)
4 SECTIONS
5 {
6 . = 0x00000000;
7 . = ALIGN(4);
8 .text :
9 {
10 *(.__image_copy_start)
11 *(.vectors)
12 arch/arm/cpu/armv7/start.o (.text*)
13 *(.text*)
14 }
15 . = ALIGN(4);
16 .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
17 . = ALIGN(4);
18 .data : {
19 *(.data*)
20 }
21 . = ALIGN(4);
22 . = .;
23 . = ALIGN(4);
24 .u_boot_list : {
25 KEEP(*(SORT(.u_boot_list*)));
26 }
27 . = ALIGN(4);
28 .image_copy_end :
29 {
30 *(.__image_copy_end)
31 }
32 .rel_dyn_start :
33 {
34 *(.__rel_dyn_start)
35 }
36 .rel.dyn : {
37 *(.rel*)
38 }
39 .rel_dyn_end :
40 {
41 *(.__rel_dyn_end)
42 }
43 .end :
44 {
45 *(.__end)
46 }
47 _image_binary_end = .;
48 . = ALIGN(4096);
49 .mmutable : {
50 *(.mmutable)
51 }
52 .bss_start __rel_dyn_start (OVERLAY) : {
53 KEEP(*(.__bss_start));
54 __bss_base = .;
55 }
56 .bss __bss_base (OVERLAY) : {
57 *(.bss*)
58 . = ALIGN(4);
59 __bss_limit = .;
60 }
61 .bss_end __bss_limit (OVERLAY) : {
62 KEEP(*(.__bss_end));
63 }
......
73 .gnu.linkonce.armexidx : { *(.gnu.linkonce.armexidx.*) }
74 }

3 行为代码当前入口点: _start ,_start 在文件 arch/arm/lib/vectors.S 中有定义。
vectors.S 如下所示:
/*
 *************************************************************************
 *
 * Vectors have their own section so linker script can map them easily
 *
 *************************************************************************
 */
    .section ".vectors", "ax"
/*
 *************************************************************************
 *
 * Exception vectors as described in ARM reference manuals
 *
 * Uses indirect branch to allow reaching handlers anywhere in memory.
 *
 *************************************************************************
 */

_start:

#ifdef CONFIG_SYS_DV_NOR_BOOT_CFG
    .word   CONFIG_SYS_DV_NOR_BOOT_CFG
#endif

    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

vectors.S 可以看出, _start 后面就是中断向量表,从图中的 .section ".vectors", "ax 可以得到,此代码存放在 .vectors 段里面。
u-boot.map uboot 的内存映射文件,打开 u-boot.map:
段 .text 的地址设置为 0x87800000
                0x0000000000000000                . = 0x0
                0x0000000000000000                . = ALIGN (0x4)

.text           0x0000000087800000    0x47aa0
 *(.__image_copy_start)
 .__image_copy_start
                0x0000000087800000        0x0 arch/arm/lib/built-in.o
                0x0000000087800000                __image_copy_start
 *(.vectors)
 .vectors       0x0000000087800000      0x300 arch/arm/lib/built-in.o
                0x0000000087800000                _start
                0x0000000087800020                _undefined_instruction
                0x0000000087800024                _software_interrupt
                0x0000000087800028                _prefetch_abort
                0x000000008780002c                _data_abort
                0x0000000087800030                _not_used
                0x0000000087800034                _irq
                0x0000000087800038                _fiq
                0x0000000087800040                IRQ_STACK_START_IN
从 u-boot.map 可以看到,某个文件或者函数链接到了哪个地址,  第 958 行可以看到 __image_copy_start 0X87800000 ,而 .text 的起始地址也是 0X87800000

继续链接脚本 u-boot.lds, u-boot.lds 文件的 第 11 行是 vectors 段, vectors 段保存中断向表。

vectors.S 中,我们知道了 vectors.S 的代码是存在 vectors 段中的。

u-boot.map 文件可以看出:vectors 段的起始地址也是 0X87800000 ,说明整个 uboot 的起始地址就是 0X87800000 ,这也是为什么我们裸机 例程的链接起始地址选择 0X87800000 了,目的就是为了和 uboot 一致。

从链接脚本 u-boot.lds看出: 第 12 行将 arch/arm/cpu/armv7/start.s 编译出来的代码放到中断向量表后面。
13 行为 text 段,其他的代码段就放到这里。
u-boot.lds 中有一些跟地址有关的“变量”需要我们注意一下,后面分析 u-boot 源码的
时候会用到,这些变量要最终编译完成才能确定的!!!例如,我编译完成以后这些“变量”的值。
如下所示:
变量 数值 描述
__image_copy_start 0x87800000 uboot拷贝的首地址
__image_copy_end 0x8786b03c uboot拷贝的结束地址
__rel_dyn_start
0x8786b03c
.rel.dyn 段起始地址
__rel_dyn_end
0x8787459c
.rel.dyn 段结束地址
_image_binary_end
0x8787459c
镜像结束地址
__bss_start
0x8786b03c
.bss 段起始地址
__bss_end
0x878b7314
.bss 段结束地址

上表中的 “变量” 值可以在 u-boot.map 文件中查找, 除了__image_copy_start 以外,其他的变量值每次编译的时候可能会变化,如果修改了 uboot 代码、修改了 uboot 配置、 选用不同的优化等级等等都会影响到这些值。所以,一切以实际值为准!

猜你喜欢

转载自blog.csdn.net/wojiaxiaohuang2014/article/details/133394689