• uboot启动流程-uboot代码重定位说明一


    一.  uboot启动流程

    本文学习 uboot 的启动流程中涉及的 uboot 代码重定位部分。

    _main 函数中会调用 relocate_code 函数,本文继续简单分析一下 relocate_code 函数。

    relocate_code 函数分两个部分:

    1.  拷贝 uboot 代码部分

    2.  有关 " 重定位后有关函数调用或全局变量地址的问题"的解决方法。

    二.  uboot代码重定位

    1.  uboot一些变量的地址

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

    程序的链接是由链接脚本来决定的,所以通过链接脚本可以找到程序的入口。连接脚本在uboot的根目录下u-boot.lds文件。

    在 u-boot.lds 中有一些跟地址有关的“变量”,我所编译后的uboot源码涉及的变量的值如下:

    变量数值描述
    __image_copy_start0X87800000uboot拷贝的首地址
    __image_copy_end0X8786B03Cuboot拷贝的结束地址

    __rel_dyn_start

    0X8786B03C

    .rel.dyn 段起始地址

    __rel_dyn_end

    0X8787459C

    .rel.dyn 段结束地址

    _image_binary_end

    0X8787459C

    镜像结束地址

    __bss_start

    0X8786B03C

    .bss 段起始地址

    __bss_end

    0X878B7314

    .bss 段结束地址

    2.   _main函数

    _main 函数中会调用 relocate_code 函数,调用的地方如下:

    1. ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */
    2. b relocate_code

    可以看出,relocate_code函数有一个参数,r0=gd->relocaddr=0X8FF38000uboot重定位后的首地址。

    3.  relocate_code 函数:拷贝代码部分

    relocate_code 函数是用于代码拷贝的,此函数定义在文件 arch/arm/lib/relocate.S 中。relocate_code 函数的前半部分代码如下:

    1. 79 ENTRY(relocate_code)
    2. 80 ldr r1, =__image_copy_start /* r1 <- SRC &__image_copy_start */
    3. 81 subs r4, r0, r1 /* r4 <- relocation offset */
    4. 82 beq relocate_done /* skip relocation */
    5. 83 ldr r2, =__image_copy_end /* r2 <- SRC &__image_copy_end */
    6. 84
    7. 85 copy_loop:
    8. 86 ldmia r1!, {r10-r11} /* copy from source address [r1] */
    9. 87 stmia r0!, {r10-r11} /* copy to target address [r0] */
    10. 88 cmp r1, r2 /* until source end address [r2] */
    11. 89 blo copy_loop

    80 行, r1=__image_copy_start ,也就是 r1 寄存器保存源地址,获取到镜像起始地址,
    __image_copy_start=0X87800000
    81 行,r0= 0X8FF38000 ,这个地址就是 uboot 拷贝的目标首地址
    r4 = r0-r1 = 0X8FF38000 - 0X87800000=0X18747000 ,因此, r4寄存器 保存偏移量。
    82 行,如果在第 81 中, r0-r1 等于 0 ,说明 r0 r1 相等,也就是源地址和目的地址是 一样的,那肯定就不需要拷贝了!即执行 relocate_done 函数。
    83 行, r2 = __image_copy_end 保存拷贝之前的代码结束地址由之前的
    __image_copy_end = 0X8786B03C
    84 行,函数 copy_loop 完成代码拷贝工作!从 r1 ,也就是 __image_copy_start 开始,读 uboot 代码保存到 r10 r11 中,一次就只拷贝这 2 32 位的数据。拷贝完成以后 r1 的值会 更新,保存下一个要拷贝的数据地址。
    87 行,将 r10 r11 的数据写到 r0 开始的地方,也就是目的地址。写完以后 r0 的值会 更新,更新为下一个要写入的数据地址。
    88 行,比较 r1 是否和 r2 相等,也就是检查是否拷贝完成,如果不相等的话说明没有拷 贝完成,则跳转到 copy_loop 接着拷贝,直至拷贝完成。
    下一篇文章继续学习 uboot重定位部分。具体学习 relocate_code 函数 的第二部分:
    有关 " 重定位后有关函数调用或全局变量地址的问题"的解决方法。

    我们知道,一个可执行的 bin 文件,其链接地址和运行地址要相等,也就是链接到哪个地址, 在运行之前,就要拷贝到哪个地址去。现在我们重定位以后,运行地址就和链接地址不同了,这 样寻址的时候不会出问题吗?

  • 相关阅读:
    30岁了开始自学编程,家里比较困难还来得及吗?
    卡尔曼滤波算法的matlab实现
    Linux下gcc和gdb的基本使用
    Maven入门
    CentOs 7 PHP安装和配置
    量子计算(三):有哪些机构或公司参与量子计算的研发
    AVR单片机与C语言的一些入门简要概述
    Python实战 | 使用 Python 和 TensorFlow 构建卷积神经网络(CNN)进行人脸识别
    护理管理学选择题汇总(人卫第三版)
    【Web3 系列开发教程——创建你的第一个 NFT(8)】如何开发一个成功的 NFT 项目 | NFT 社区建设技巧
  • 原文地址:https://blog.csdn.net/wojiaxiaohuang2014/article/details/133639483