2025年3月30日 星期日 甲辰(龙)年 月廿九 夜 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 精彩资源

(二)u-boot启动流程分析(汇编部分)

时间:04-17来源:作者:点击数:39

下面的代码基于amlogic的SDK的code示例。

start.S为整个u-boot的入口

start.S(arch\arm\cpu\armv8\start.S)

  • #include <asm-offsets.h>
  • #include <config.h>
  • #include <version.h>
  • #include <linux/linkage.h>
  • #include <asm/macro.h>
  • #include <asm/armv8/mmu.h>
  • /*************************************************************************
  • *
  • * Startup Code (reset vector)
  • *
  • *************************************************************************/
  • .globl _start
  • _start:
  • b reset
  • .align 3
  • .globl _TEXT_BASE
  • _TEXT_BASE:
  • .quad CONFIG_SYS_TEXT_BASE
  • /*
  • * These are defined in the linker script.
  • */
  • .globl _end_ofs
  • _end_ofs:
  • .quad _end - _start
  • .globl _bss_start_ofs
  • _bss_start_ofs:
  • .quad __bss_start - _start
  • .globl _bss_end_ofs
  • _bss_end_ofs:
  • .quad __bss_end - _start
  • reset:
  • /*
  • * Could be EL3/EL2/EL1, Initial State:
  • * Little Endian, MMU Disabled, i/dCache Disabled
  • */
  • adr x0, vectors
  • switch_el x1, 3f, 2f, 1f
  • 3: msr vbar_el3, x0
  • mrs x0, scr_el3
  • orr x0, x0, #0xf /* SCR_EL3.NS|IRQ|FIQ|EA */
  • msr scr_el3, x0
  • msr cptr_el3, xzr /* Enable FP/SIMD */
  • ldr x0, =COUNTER_FREQUENCY
  • msr cntfrq_el0, x0 /* Initialize CNTFRQ */
  • b 0f
  • 2: msr vbar_el2, x0
  • mov x0, #0x33ff
  • msr cptr_el2, x0 /* Enable FP/SIMD */
  • b 0f
  • 1: msr vbar_el1, x0
  • mov x0, #3 << 20
  • msr cpacr_el1, x0 /* Enable FP/SIMD */
  • 0:
  • /*
  • * Cache/BPB/TLB Invalidate
  • * i-cache is invalidated before enabled in icache_enable()
  • * tlb is invalidated before mmu is enabled in dcache_enable()
  • * d-cache is invalidated before enabled in dcache_enable()
  • */
  • /* Processor specific initialization */
  • bl lowlevel_init
  • branch_if_master x0, x1, master_cpu
  • /*
  • * Slave CPUs
  • */
  • slave_cpu:
  • wfe
  • ldr x1, =CPU_RELEASE_ADDR
  • ldr x0, [x1]
  • cbz x0, slave_cpu
  • br x0 /* branch to the given address */
  • /*
  • * Master CPU
  • */
  • master_cpu:
  • bl _main

主要的流程如下:

(1)根据当前的EL级别,配置中断向量、MMU、Endian、i/d Cache等。

(2)配置ARM的勘误表,具体可参考apply_core_errata函数。

(3)调用lowlevel_init。

(4)如果是多CPU的场景,处理其它的CPU的boot。

(5)跳转到arm公共的_main中执行。

跳转到crt0_64.S(arch\arm\lib\crt0_64.S)中:

  • #include <config.h>
  • #include <asm-offsets.h>
  • #include <asm/macro.h>
  • #include <linux/linkage.h>
  • ENTRY(_main)
  • /*
  • * Set up initial C runtime environment and call board_init_f(0).
  • */
  • ldr x0, =(CONFIG_SYS_INIT_SP_ADDR)
  • sub x0, x0, #GD_SIZE /* allocate one GD above SP */
  • bic sp, x0, #0xf /* 16-byte alignment for ABI compliance */
  • mov x18, sp /* GD is above SP */
  • mov x0, #0
  • bl board_init_f
  • /*
  • * 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 x0, [x18, #GD_START_ADDR_SP] /* x0 <- gd->start_addr_sp */
  • bic sp, x0, #0xf /* 16-byte alignment for ABI compliance */
  • ldr x18, [x18, #GD_BD] /* x18 <- gd->bd */
  • sub x18, x18, #GD_SIZE /* new GD is below bd */
  • adr lr, relocation_return
  • ldr x9, [x18, #GD_RELOC_OFF] /* x9 <- gd->reloc_off */
  • add lr, lr, x9 /* new return address after relocation */
  • ldr x0, [x18, #GD_RELOCADDR] /* x0 <- gd->relocaddr */
  • b relocate_code
  • relocation_return:
  • /*
  • * Set up final (full) environment
  • */
  • bl c_runtime_cpu_setup /* still call old routine */
  • /*
  • * Clear BSS section
  • */
  • ldr x0, =__bss_start /* this is auto-relocated! */
  • ldr x1, =__bss_end /* this is auto-relocated! */
  • mov x2, #0
  • clear_loop:
  • str x2, [x0]
  • add x0, x0, #8
  • cmp x0, x1
  • b.lo clear_loop
  • /* call board_init_r(gd_t *id, ulong dest_addr) */
  • mov x0, x18 /* gd_t */
  • ldr x1, [x18, #GD_RELOCADDR] /* dest_addr */
  • b board_init_r /* PC relative jump */
  • /* NOTREACHED - board_init_r() does not return */
  • ENDPROC(_main)

主要流程如下(源码注释翻译):

(1)设置board_init_f()初始化环境。

(2)调用board_init_f()。

如果是非SPL,则执行(3)-(6)

(3)设置board_init_f()在系统内存中分配的堆栈和GD中间环境,BSS 和非常量数据任然不可用。

(4)调用relocate_code()。

(5)设置calling board_init_r()调用环境。

(6)调用calling board_init_r()。

后续board_init_f()及board_init_r()都是C语言实现了,汇编部分到此为止,喜欢深入研究的可以多了解,下节我们分析C语言实现部分,也是我们日常经常需要修改的地方。

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门