u-boot链接分析

学习提速专享!AI工具全家桶免费用 限时购周边加赠Coding Plan Lite,解锁20+主流AI工具,写代码、查资料快人一步! 阅读详情

作者:于连庆,华清远见嵌入式培训中心讲师。

一个典型的嵌入式系统中,bootloader代码放在NOR Flash或NAND Flash里面,系统加电或复位后,首先运行这段代码。通常把bootloader代码放在NOR Flash里面,NAND Flash由于硬件原因不能随机访问,需要特殊的硬件支持机制。

bootloader代码除了初始化以外就是搬运程序,即地址重定位(relocate)。我们为什么需要relocate?主要是经济方面和速度方面的原因。经济方面,NOR Flash和NAND Flash每兆价格相差悬殊,bootloader代码一般在几十到几百K大小,而应用程序通常都很大,几M到几十M的大小,所以用价格低廉的NAND Flash存储。速度方面,程序在NOR Flash里执行的速度远远小于在SDRAM中执行的速度,为了追求更高的速度,也需要relocate,让程序在SDRAM里面执行。

relocate涉及到加载域(VMA)和运行域(LMA)两个概念。加载域是程序代码在ROM、FLASH中的排列次序及地址安排,运行域是程序运行时代码在SRAM、SDRAM中地址安排。存储代码时按照加载域存放在FLASH中,运行时再从FLASH中取出代码到RAM运行域运行,一段代码的加载域和存储域可以不同。(可以参考杜春雷的《arm体系结构与编程》一书的有关章节)。

以smdk2410为例,密切相关的就两个文件夹/board/smdk2410和/cpu/arm920t,里面核心文件就u-boot.lds 、config.mk 、start.S。

/cpu/arm920t/u-boot.lds
        OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
        OUTPUT_ARCH(arm)
        ENTRY(_start)
        SECTIONS
        {
                . = 0x00000000; // 从0地址起始

        . = ALIGN(4);
                .text :
                {
                        cpu/arm920t/start.o (.text)
                        *(.text)
                }

        . = ALIGN(4);
                .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.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);
                __bss_start = .;
                .bss (NOLOAD) : { *(.bss) . = ALIGN(4); }
                _end = .;
        }

连接脚本文件lds中没有设置LMA,只是设置了VMA。VMA的设置是通过顶层目录下的config.mk文件中的LDFLAGS实现的,TEXT_BASE在/board/smdk2410/config.mk中定义为0x33F80000(SDRAM地址)。

LDFLAGS += -Bstatic -T $(obj)u-boot.lds $(PLATFORM_LDFLAGS)
        ifneq ($(TEXT_BASE),)
        LDFLAGS += -Ttext $(TEXT_BASE)
        endif

查看u-boot.map文件,代码的连接地址是从0x33F80000开始的。

167 .text         0x33f80000        0x232c8
        168        cpu/arm920t/start.o(.text)
        169        .text                0x33f80000                0x4a0 cpu/arm920t/start.o
        170                                0x33f80048                _bss_start
        171                                0x33f8004c                _bss_end
        172                                0x33f80044                _armboot_start
        173                                0x33f80000                _start
        174        board/samsung/fs2410/lowlevel_init.o(.text)
        175        .text                0x33f804a0         0x64 board/samsung/fs2410/lowlevel_init.o
        176                                0x33f804a4                lowlevel_init
        177        board/samsung/fs2410/nand_read.o(.text)
        178        .text                0x33f80504        0xe8 board/samsung/fs2410/nand_read.o
        179                                0x33f80504                wait_idle
        180                                0x33f80518                nand_read_ll

bootloader代码上电之后之所以能够正确执行,有个很重要的原因,就是最初执行的bootloader代码是地址无关的,即这个映象文件可以被放在内存中的任何一个地址上运行。

对于地址无关的代码, 寻址是基于pc值的, 在pc值上+/-一个偏移值得到运行地址,如跳转指令B。当执行完代码搬运,就需要跳到和地址相关的地方去执行,即RAM中。一般是跳转到一个标号,这时地址相关代码就开始运行了,如:ldr pc,_start_armboot。

因为在bin映象生成的时候,就已经把_start_armboot这个符号和实际地址绑定在一起,当执行ldr pc,_start_armboot 语句时,程序就从在ROM中执行跳入到RAM中了,前提是进行了代码搬移。如果没有代码搬运就执行ldr pc,_start_armboot,因为RAM中没有正确的可执行代码,程序就马上飞掉了,所有在搬运之前不能寻址绝对地址有关代码,必须执行代码地址无关.

下面的代码是从NOR Flash向SDRAM搬运的代码:

relocate:
                adr r0, _start
                ldr r1, _TEXT_BASE
                cmp r0, r1
                beq stack_setup
                ldr r2, _armboot_start
                ldr r3, _bss_start
                sub r2, r3, r2
                add r2, r0, r2
        copy_loop:
                ldmia r0!, {r3-r10}
                stmia r1!, {r3-r10}
                cmp r0, r2
                ble copy_loop

注意其中的 adr r0, _start,这是一条伪指令,一般被编译器替换为sub r0, pc,#offset ,不要理解为读取符合表中_start符号的地址(0x33F80000)。上电开始执行时,pc从0开始,所以现在r0值为0+offset,不等于_TEXT_BASE(0x33F80000)。接下来要用到链接时确定的符号地址_armboot_start(0x33F80044)了,把_start:0x0 (NOR Flash)里的.text、.data的代码往SDRAM里_TEXT_BASE确定的地址: 0x33f80000搬运。s3c2410的SDRAM基地址是0x3000_0000,由于uboot支持的这个board SDRAM64M(0x3000_0000-0x3400_0000),所以把u-boot.bin搬运到内存的高端地址.然后跳到内存中执行,提高速度。
嵌入式及3G相关资源及学习请点击:嵌入式开发视频 android开发视频 android培训 3G培训 QT培训 QT开发视频 物联网培训 物联网技术视频 嵌入式学习   

【ARM 嵌入式 编译系列 7.3 -- GCC 链接脚本中 NOLOAD 和 GROUP 的详细介绍】 在使用工具链中的链接器脚本时,链接脚本使用链接器命令语言来描述如何生成最终的可执行文件。其中,noload和group是两个用于控制链接过程的关键字。 阅读详情

相关推荐

U-boot最后链接选项和objcopy的选项分析

下面这一整行是链接出u-boot文件的命令,这个u-boot是elf格式的。UNDEF_SYM=`arm-linux-objdump -x lib_generic/libgeneric.a board/samsung/mini6410/libmini6410.a cpu/s3c64xx/libs3c64xx.a cpu/s3c64xx/s3c6410/libs3c6410.a lib_arm/libarm.a fs/cramfs/libcramfs.a fs/fat/libfat.a fs/fdos/lib

RichardYSteven的专栏 3629

U-Boot之四:u-boot.lds分析

u-boot.lds决定了u-boot可执行映像的连接方式,以及各个段的装载地址(装载域)和执行地址(运行域)。 GNU官方网站上对.lds文件形式的完整描述: SECTIONS{ ... secname start BLOCK(align) (NOLOAD) : AT ( ldadr ) {contents } >region :phdr=fill ... } secname和c

寂静生长 624

Armv8架构UBOOT 启动篇——SPL(u-boot-spl.lds链接脚本)

背景 UBOOT版本:2016 架构:Armv8 Cortex A53 DEMO板:freescale ls1043ardb 引言 从uboot 2011版本之后便引入了SPL架构,将之前所有secondary program loader相关的代码实现进行规范,这样也使得各类单板的相关代码实现可以复用,也有效的避免了重复代码和符号链接问题。众所周知,对于不同类型的CPU以及其对应的不同...

XingYu.Liao的博客 6239

嵌入式linux bootloader,嵌入式系统启动之bootloader 源码解析

要探讨bootloader ,我们首先从全局来看看,嵌入式系统启动流程是怎么样的。大体上一个嵌入式Linux系统从软件角度分析可以分为四个部分:引导加载程序(bootloader),Linux内核,文件系统,应用程序。当系统首次引导时,或系统被重置时,bootloader 首先被执行(位于Flash/ROM中的已知位置处)的代码。它主要用来初始化处理器及外设,然后调用Linux 内核。Linux ...

weixin_33805938的博客 941

u-boot (2) —— 链接分析

前面讲了 u-boot 的编译分析,编译完以后,需要将 .o、.a 进行链接成为最后的 u-boot 的 elf 文件; 在上一章里面(u-boot (1) —— 编译分析)提到了 Makefile 错综复杂的包含关系;链接的时候,我们注意几点: Makefile 包含了它源码目录下的那个 config.mk 文件,其中需要注意的: # Load generated board configuration sinclude $(OBJTREE)/include/autoconf.mk ifdef

StephenZhou 1834

u-boot链接脚本分析

boazheng的博客 182

u-boot 链接脚本内容分析

根据之前写的《u-boot makefile内容分析》里中写到的,u-boot执行make之后最终会使用 u-boot-1.1.6/board/100ask24x0/u-boot.lds来做为链接文件。 以下是此文件的简单分析 OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")//定义3种输出文件的格...

yogach的博客 233

lds链接脚本基础及u-boot.lds链接脚本分析

在 目标文件中的内容至少包括编译后的机器指令代码、数据,还包括了链接时所需要的的一些信息,比如符号表、调试信息、字符串等。目标文件将这些信息按不同的属性以“ 段 ”(segment)的形式存储。以下就是一些常见的段。并且还根据一个简单程序说明编译后的目标文件的结构。主要分析表格中常见的段信息,其实还有其他段例如注释信息段( .comment ),但这不是我们关注的重点。编译过程编译: arm-linux-gcc -c -o led_on.o led_on.S #或led_on.c。

tecoes的博客 269

【u-boot-2018.11】链接脚本分析

1. 链接脚本生成 1.1 指定链接脚本模板文件 在顶层Makefile中会根据设置指定链接脚本的模板文件: # If board code explicitly specified LDSCRIPT or CONFIG_SYS_LDSCRIPT, use # that (or fail if absent). Otherwise, search for a linker script in a # standard location. ifndef LDSCRIPT #LDSCRIPT := $(srct

linuxweiyh的博客 1330

imx6ull-系统移植篇6——U-Boot 链接脚本分析

本文详细分析了U-Boot链接脚本:u-boot.lds的结构与功能。

m0_62228566的博客 896

u-boot链接文件u-boot.lds分析

对于u-boot-2010.03版本的smdk2410这个平台的链接文件是/cpu/arm920t/u-boot.lds,下面就来分析下该文件的每一句是什么意思。   //;三个分别指定在缺省、大端、小端情况下的输出可执行文件格式,这里都指定输出格式是elf32,小端和arm体系结构。 OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "

516

U-Boot学习(4):u-boot.lds链接脚本分析

lds链接脚本基础与例子分析。SECTIONS {......secname和contents是必须的,前者用来命名这个段,后者用来确定代码中的什么部分放在这个段中。start:段重定位地址,也称为VMA,即运行地址。如果代码中有位置相关的指令,程序在运行时,这个段必须放在这个地址上。:虽然start指定了运行地址,但是仍可以使用BLOCK(align)来指定对齐的要求一这个对齐的地址才是真正的运行地址。(NOLOAD):用来告诉加载器,在运行时不用加载这个段。

主要分享嵌入式软件、人工智能部分知识 2856

u-boot链接脚本文件u-boot.lds分析

u-boot 版本: 2016.03,NXP更改过的版本,正点原子再次更改,详细可参见正点原子的教程。 这里先贴出来链接脚本文件,它是生成过程,可以参考https://blog.csdn.net/xiaoyink/article/details/108508415,里面有简略的提到,这里主要分析此文件的含义,如下: OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") OUTPUT_ARCH(arm) ENTRY(

吾生也有涯,而知也无涯 1021

u-boot-1.1.6分析(二)编译链接过程

分析顶层Makefile: 117行包含了配置过程生成的config.mk文件: include $(OBJTREE)/include/config.mk 选择对应的交叉编译工具链 ifndef CROSS_COMPILE ifeq ($(HOSTARCH),ppc) CROSS_COMPILE = else ifeq ($(ARCH),ppc) CROSS_COMPILE = po...

floatinglong的博客 330

嵌入式移植】7、U-Boot源码分析4—链接脚本分析

第32行~57行为sram中其它段的定义。

TTZZWWW 1066
上一篇: u-boot链接分析
下一篇: 关于linux中的软链接和硬链接
华清远见嵌入式学院
博客等级 码龄17年 2149粉丝 842原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值