ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

U-Boot _main函数

2022-02-04 19:02:20  阅读:173  来源: 互联网

标签:GD r0 函数 Boot init gd board main CONFIG


_main函数主要完成的工作:

  • 先设置用于调用board_init_f()函数的初始环境,该环境仅仅是提供了堆栈和存储位置GD('global data')结构,两者都是位于可以使用的RAM(SRAM,locked cache...)中,在调用board_init_f()函数前,GD应该被清0;
  • 调用board_init_f()函数,该函数的功能为从system RAM(DRAM,DDR...)中执行准备硬件,当system RAM还不能够使用的时,必须要使用目前的GD存储传递到后续阶段的所有数据,这些数据包括重定位的目标,将来的堆栈和GD的位置;
  • 设置中间环境,其中堆栈和GD是由board_init_f()函数在system RAM中进行分配的,但此时的bss和初始化的非常量仍然不能使用;
  • 对于正常的uboot引导(非SPL),调用relocate_code()函数,该函数的功能将uboot从当前的位置重新转移到由board_init_f()函数计算的目标位置;
  • 对于SPL,board_init_f()函数仅仅是返回(crt0),没有代码的重定位;
  • 设置用于调用board_init_r()函数的最终环境,该环境将有bss段(初始化为0),初始化非常量数据(初始化为预期值),并入栈到system RAM中,GD保留了board_init_f()函数设置的值;
  • 为了使uboot正常运行(非SPL),某些CPU还有一些关于内存的工作要做,调用c_runtime_cpu_setup()函数;
  • 调用board_init_r()函数。
ENTRY(_main)

 

/*  * Set up initial C runtime environment and call board_init_f(0).  */

 

#if defined(CONFIG_TPL_BUILD) && defined(CONFIG_TPL_NEEDS_SEPARATE_STACK)     ldr r0, =(CONFIG_TPL_STACK) #elif defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)     ldr r0, =(CONFIG_SPL_STACK) #else     ldr r0, =(CONFIG_SYS_INIT_SP_ADDR) #endif     bic r0, r0, #7  /* 8-byte alignment for ABI compliance */     mov sp, r0     bl  board_init_f_alloc_reserve     mov sp, r0     /* set up gd here, outside any C code */     mov r9, r0     bl  board_init_f_init_reserve

 

#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_EARLY_BSS)     CLEAR_BSS #endif

 

    mov r0, #0     bl  board_init_f

 

#if ! defined(CONFIG_SPL_BUILD)

 

/*  * Set up intermediate environment (new sp and gd) and call  * relocate_code(addr_moni). Trick here is that we'll return  * 'here' but relocated.  */

 

    ldr r0, [r9, #GD_START_ADDR_SP] /* sp = gd->start_addr_sp */     bic r0, r0, #7  /* 8-byte alignment for ABI compliance */     mov sp, r0     ldr r9, [r9, #GD_NEW_GD]        /* r9 <- gd->new_gd */

 

    adr lr, here     ldr r0, [r9, #GD_RELOC_OFF]     /* r0 = gd->reloc_off */     add lr, lr, r0 #if defined(CONFIG_CPU_V7M)     orr lr, #1              /* As required by Thumb-only */ #endif     ldr r0, [r9, #GD_RELOCADDR]     /* r0 = gd->relocaddr */     b   relocate_code here: /*  * now relocate vectors  */

 

    bl  relocate_vectors

 

/* Set up final (full) environment */

 

    bl  c_runtime_cpu_setup /* we still call old routine here */ #endif #if !defined(CONFIG_SPL_BUILD) || CONFIG_IS_ENABLED(FRAMEWORK)

 

#if !defined(CONFIG_SPL_BUILD) || !defined(CONFIG_SPL_EARLY_BSS)     CLEAR_BSS #endif

 

# ifdef CONFIG_SPL_BUILD     /* Use a DRAM stack for the rest of SPL, if requested */
 //调用spl_relocate_stack_gd函数 重定位新的gd栈指针
//在定义了CONFIG_SPL_STACK_R等情况下,将片内SRAM中的GD复制到系统RAM中。
    bl  spl_relocate_stack_gd     cmp r0, #0 //如果spl_relocate_stack_gd返回为0,即未定义CONFIG_SPL_STACK_R,GD依旧在SRAM中     movne   sp, r0 //如果r0不等于0,则sp=r0,即sp等于SDRAM中GD的地址     movne   r9, r0 //如果r0不等于0,则r9=r0,即r9等于SDRAM中GD的地址
#endif # endif

 

#if ! defined(CONFIG_SPL_BUILD)     bl coloured_LED_init     bl red_led_on #endif     /* call board_init_r(gd_t *id, ulong dest_addr) */     mov     r0, r9                  /* gd_t */     ldr r1, [r9, #GD_RELOCADDR] /* dest_addr */     /* call board_init_r */ #if CONFIG_IS_ENABLED(SYS_THUMB_BUILD)     ldr lr, =board_init_r   /* this is auto-relocated! */     bx  lr #else     ldr pc, =board_init_r   /* this is auto-relocated! */ #endif     /* we should not return here. */ #endif

 

ENDPROC(_main)  

1、初始栈指针设置:

首先加载的栈地址,将其保存到r0中,对其进行16byte对齐后指向sp指针。在board_init_f_alloc_reserve之前保存sp指针栈到r0,作为函数的输入参数,函数调用结束时作为返回参数。同理 r0作为输入参数board_init_f_alloc_reserve执行后为保留区域清零,同时需要还原sp栈指针。  

2、board_init_f_alloc_reserve

 

从“top”(这里指sp指针)地址分配保留空间用作“全局变量”,返回分配空间的“top”地址(返回sp指针地址)

GD 在 16 字节边界上向下对齐。早期的 malloc area 未对齐,因此它遵循堆栈我们正在构建的架构的对齐约束。GD 是最后分配的,所以这个函数的返回值是保留区的底部和GD的地址,都应该调用上下文需要它。

top参数是汇编语言所对应的r0,作为指针为globle_data保留内存区域。内存分配在高位区域,保留区域内存指针减小。

ulong board_init_f_alloc_reserve(ulong top)
{
    /* Reserve early malloc arena */
#if CONFIG_VAL(SYS_MALLOC_F_LEN)
    top -= CONFIG_VAL(SYS_MALLOC_F_LEN);
#endif
    /* LAST : reserve GD (rounded up to a multiple of 16 bytes) */
    top = rounddown(top-sizeof(struct global_data), 16);

    return top;
}

3、board_init_f_init_reserve

board_init_f_alloc_reserve预留了global_data结构体空间,未进行初始化处理,board_init_f_init_reserve现在可以开始初始化gd结构了。board_init_f_init_stack_protection_addr为gd->start_addr_sp设置了栈指针一个保护边沿,然后调整向上以对齐16字节方式回到栈顶。将早期malloc空间的基地址保存到gd->malloc_base;board_init_f_init_stack_protection设置栈指针底部,保留20字节对于栈区进行memset设置。

void board_init_f_init_reserve(ulong base) {     struct global_data *gd_ptr;
    /*      * clear GD entirely and set it up.      * Use gd_ptr, as gd may not be properly set yet.      */
    gd_ptr = (struct global_data *)base;     /* zero the area */     memset(gd_ptr, '\0', sizeof(*gd));     /* set GD unless architecture did it already */ #if !defined(CONFIG_ARM)     arch_setup_gd(gd_ptr); #endif
    if (CONFIG_IS_ENABLED(SYS_REPORT_STACK_F_USAGE))         board_init_f_init_stack_protection_addr(base);
    /* next alloc will be higher by one GD plus 16-byte alignment */     base += roundup(sizeof(struct global_data), 16);
    /*      * record early malloc arena start.      * Use gd as it is now properly set for all architectures.      */
#if CONFIG_VAL(SYS_MALLOC_F_LEN)     /* go down one 'early malloc arena' */     gd->malloc_base = base; #endif
    if (CONFIG_IS_ENABLED(SYS_REPORT_STACK_F_USAGE))         board_init_f_init_stack_protection(); }

4、CONFIG_SYS_MALLOC_F 

如果定义了CONFIG_SYS_MALLOC_F,会先预留出early malloc所需的空间。会初始化gd->malloc_base。

5、设置初始的堆栈

基址由CONFIG_SYS_INIT_SP_ADDR定义。

6、清除BBS段

7、uboot的重定向动作

#if ! defined(CONFIG_SPL_BUILD)

/*
 * Set up intermediate environment (new sp and gd) and call
 * relocate_code(addr_moni). Trick here is that we'll return
 * 'here' but relocated.
 */

    ldr    r0, [r9, #GD_START_ADDR_SP]    /* sp = gd->start_addr_sp */
    bic    r0, r0, #7    /* 8-byte alignment for ABI compliance */
    mov    sp, r0
    ldr    r9, [r9, #GD_NEW_GD]        /* r9 <- gd->new_gd */
@@ 把新的global_data地址放在r9寄存器中
    adr    lr, here
    ldr    r0, [r9, #GD_RELOC_OFF]        /* r0 = gd->reloc_off */
    add    lr, lr, r0
@@ 计算返回地址在新的uboot空间中的地址。b调用函数返回之后,就跳到了新的uboot代码空间中。 #if defined(CONFIG_CPU_V7M) orr lr, #1 /* As required by Thumb-only */ #endif ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */
@@ 把uboot的新的地址空间放到r0寄存器中,作为relocate_code的参数
b relocate_code

@@ 跳转到relocate_code中,在这里面实现了
@@ (1)relocate旧的uboot代码空间到新的空间上去
@@ (2)修改relocate之后全局变量的label
@@ 注意,由于上述已经把lr寄存器重定义到uboot新的代码空间中了,所以返回之后,就已经跳到了新的代码空间了!!!!!!

here:

/*
 * now relocate vectors
 */

    bl    relocate_vectors
@@ relocate中断向量表
/* Set up final (full) environment */

    bl    c_runtime_cpu_setup    /* we still call old routine here */
#endif

1)从global data中取出relocation之后的堆栈基址,16-byte对齐后,保存到sp中。

2)将新的global data的指针,保存在r9寄存器中。

3)计算relocation之后的执行地址(relocation_return处),计算的方法就是当前的relocation_return位置加上gd->reloc_off。

4)以relocation的目的地址(gd->relocaddr)为参数,调用relocate_code执行实际的relocation动作,就是将u-boot的代码段、data段、bss段等数据,拷贝到新的位置(gd->relocaddr)。

 

 

@@ 在board_init_f里面实现了
@@ (1)对relocate进行空间规划
@@ (2)计算uboot代码空间到relocation的位置的偏移
@@ (3)relocate旧的global_data到新的global_data的空间上

 

 

标签:GD,r0,函数,Boot,init,gd,board,main,CONFIG
来源: https://www.cnblogs.com/liujunhuasd/p/15737369.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有