IMX8 UBOOT源码分析(五)start.S分析

start.S文件在arch/arm/cpu/armv8下面,源码如下:

.globl    _start
_start:
#if defined(LINUX_KERNEL_IMAGE_HEADER)
#include <asm/boot0-linux-kernel-header.h>
#elif defined(CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK)
#include <asm/arch/boot0.h>
#else
    b    reset
#endif

//在生成的.config中并没有定义LINUX_KERNEL_IMAGE_HEADER和CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK,故程序直接跳到:   b reset

    .align 3                                                         //定义8字节对齐,可以从汇编文件中看出来

.globl    _TEXT_BASE
_TEXT_BASE:
    .quad    CONFIG_SYS_TEXT_BASE
.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

/*在u-boot的反汇编文件中定义如下:

0000000080020008 <_TEXT_BASE>:
    80020008:    80020000     .word    0x80020000
    8002000c:    00000000     .word    0x00000000

0000000080020010 <_end_ofs>:
    80020010:    00081e48     .word    0x00081e48
    80020014:    00000000     .word    0x00000000

0000000080020018 <_bss_start_ofs>:
    80020018:    00081e48     .word    0x00081e48
    8002001c:    00000000     .word    0x00000000

0000000080020020 <_bss_end_ofs>:
    80020020:    000c7be0     .word    0x000c7be0
    80020024:    00000000     .word    0x00000000

可以看到每个变量之间的地址差为8

reset:
    b    save_boot_params

    /*查看反汇编代码如下:

      0000000080020028 <reset>:
      80020028:    14000036     b    80020100 <save_boot_params>

      0000000080020100 <save_boot_params>:
      80020100:    17ffffcb     b    8002002c <save_boot_params_ret>
      80020104:    00000000     .inst    0x00000000 ; undefined
      80020108:    007a1200     .word    0x007a1200

   可知跳到了本文件中的WEAK(save_boot_params)中,并且啥也没干又跳到了save_boot_params_ret*/
.globl    save_boot_params_ret
save_boot_params_ret:

#if CONFIG_POSITION_INDEPENDENT
pie_fixup:
    adr    x0, _start        /* x0 <- Runtime value of _start */
    ldr    x1, _TEXT_BASE        /* x1 <- Linked value of _start */
    sub    x9, x0, x1        /* x9 <- Run-vs-link offset */
    adr    x2, __rel_dyn_start    /* x2 <- Runtime &__rel_dyn_start */
    adr    x3, __rel_dyn_end    /* x3 <- Runtime &__rel_dyn_end */
pie_fix_loop:
    ldp    x0, x1, [x2], #16    /* (x0, x1) <- (Link location, fixup) */
    ldr    x4, [x2], #8        /* x4 <- addend */
    cmp    w1, #1027        /* relative fixup? */
    bne    pie_skip_reloc
    /* relative fix: store addend plus offset at dest location */
    add    x0, x0, x9
    add    x4, x4, x9
    str    x4, [x0]
pie_skip_reloc:
    cmp    x2, x3
    b.lo    pie_fix_loop
pie_fixup_done:
#endif

//在.config和整个uboot中并没有定义CONFIG_POSITION_INDEPENDENT

#ifdef CONFIG_SYS_RESET_SCTRL
    bl reset_sctrl
#endif

//整个uboot中并没有定义CONFIG_SYS_RESET_SCTRL

#if defined(CONFIG_ARMV8__SPL_EXCEPTION_VECTORS) || !defined(CONFIG_SPL_BUILD)
.macro    set_vbar, regname, reg
    msr    \regname, \reg
.endm
    adr    x0, vectors
#else
.macro    set_vbar, regname, reg
.endm
#endif

/*在U-BOOT中CONFIG_ARMV8__SPL_EXCEPTION_VECTORS和CONFIG_SPL_BUILD都没有定义,故执行:

 .macro    set_vbar, regname, reg
    msr    \regname, \reg
.endm
    adr    x0, vectors
 定义宏set_vbar,将通用寄存器reg的值写入状态寄存器regname中,并将终端向量的地址给到x0*/

    switch_el x1, 3f, 2f, 1f

/*switch_el 的定义如下:

   .macro    switch_el, xreg, el3_label, el2_label, el1_label
    mrs    \xreg, CurrentEL
    cmp    \xreg, 0xc
    b.eq    \el3_label
    cmp    \xreg, 0x8
    b.eq    \el2_label
    cmp    \xreg, 0x4
    b.eq    \el1_label
.endm

此处switch_el定义为:读取CurrentEL状态寄存器的值,如果等于0xc则跳到el3_label,0x8则跳到el2_label,0x4则跳到el1_label,此处为根据中断等级跳到响应的位置*/
3:    set_vbar 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 */

//使能EL3等级下的NS|IRQ|FIQ|EA和FP/SIMD
#ifdef COUNTER_FREQUENCY
    ldr    x0, =COUNTER_FREQUENCY
    msr    cntfrq_el0, x0            /* Initialize CNTFRQ */
#endif

//在include/configs/imx8qxp_mek.h中定义如下#define COUNTER_FREQUENCY        8000000    /* 8MHz */,写入cntfrq_el0
    b    0f
2:    set_vbar    vbar_el2, x0
    mov    x0, #0x33ff
    msr    cptr_el2, x0            /* Enable FP/SIMD */

//使能EL2等级下的FP/SIMD
    b    0f
1:    set_vbar    vbar_el1, x0
    mov    x0, #3 << 20
    msr    cpacr_el1, x0            /* Enable FP/SIMD */

//使能EL1等级下的FP/SIMD
0:
#ifdef CONFIG_ARMV8_SET_SMPEN
    switch_el x1, 3f, 1f, 1f
3:
    mrs     x0, S3_1_c15_c2_1               /* cpuectlr_el1 */
    orr     x0, x0, #0x40
    msr     S3_1_c15_c2_1, x0
1:
#endif

  //在.config中CONFIG_ARMV8_SET_SMPEN未定义
    bl    apply_core_errata

   /*在本文件中定义了:

   WEAK(apply_core_errata)

    mov    x29, lr            /* Save LR */
    branch_if_a53_core x0, apply_a53_core_errata
    branch_if_a57_core x0, apply_a57_core_errata
0:
    mov    lr, x29            /* Restore LR */
    ret

  同时apply_a53_core_errata的定义如下:

apply_a53_core_errata:

#ifdef CONFIG_ARM_ERRATA_855873
    mrs    x0, midr_el1
    tst    x0, #(0xf << 20)
    b.ne    0b

    mrs    x0, midr_el1
    and    x0, x0, #0xf
    cmp    x0, #3
    b.lt    0b

    mrs    x0, S3_1_c15_c2_0    /* cpuactlr_el1 */
    /* Enable data cache clean as data cache clean/invalidate */
    orr    x0, x0, #1 << 44
    msr    S3_1_c15_c2_0, x0    /* cpuactlr_el1 */
#endif
    b 0b

而CONFIG_ARM_ERRATA_855873并没有定义,故跳到0处:

    mov    lr, x29            /* Restore LR */
    ret

返回到主函数继续执行*/

    bl    lowlevel_init

 /*从汇编文件中可以知道跳到了本文件下的lowlevel_init处并什么都没干:

    00000000800200b8 <lowlevel_init>:
    800200b8:    aa1e03fd     mov    x29, x30
    800200bc:    aa1d03fe     mov    x30, x29
    800200c0:    d65f03c0     ret*/

#if defined(CONFIG_ARMV8_SPIN_TABLE) && !defined(CONFIG_SPL_BUILD)
    branch_if_master x0, x1, master_cpu
    b    spin_table_secondary_jump
    /* never return */
#elif defined(CONFIG_ARMV8_MULTIENTRY)
    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 */
#endif /* CONFIG_ARMV8_MULTIENTRY */

//CONFIG_ARMV8_SPIN_TABLE、CONFIG_SPL_BUILD和CONFIG_ARMV8_MULTIENTRY都没有定义
master_cpu:
    bl    _main

跳到main函数执行

这篇博客主要分析start.S文件,main函数在下一篇博客中进行分析

猜你喜欢

转载自blog.csdn.net/yanggx0929/article/details/88597294