u-boot代码之启动

u-boot版本,u-boot-2016.11

硬件环境,  HI3559av100

 

u-boot系统启动流程分为stage1和stage2两部分,stage1是依赖于CPU体系结构的代码。通常stage1用汇编语言来实现,stage2则用C语言来实现,这样可以实现复杂的功能,而且有更好的可读性和移植性。

有个小技巧可以快速确定.globl    _start  等一些全局变量的地址,那就是反编译u-boot文件。因为这些个地址都是链接脚本(.lds文件)指定,看代码时不好确定其地址,等它编译出来,反编译出来就很清楚了。同时结合System.map、u-boot.map、u-boot.sym文件来看,就比较清晰了。

.lds文件中指定了入口、定义了各个SECTIONS,如常见的.text、.rodata、.data,另外大部分,都是不常见的。

反编译命令:

aarch64-himix100-linux-objdump -SD u-boot > /home/share/work/uboot0819.s

 

/*

 * u-boot-2016.11/arch/arm/cpu/armv8/start.S

 */

/*
 * (C) Copyright 2013
 * David Feng <fenghua@phytium.com.cn>
 *
 * SPDX-License-Identifier:    GPL-2.0+
 */

#include <asm-offsets.h>
#include <config.h>
#include <linux/linkage.h>
#include <asm/macro.h>
#include <asm/armv8/mmu.h>

/*************************************************************************
 *
 * Startup Code (reset vector)
 *
 *************************************************************************/

.globl    _start            /* u-boot启动入口, _start's address value  0000000048800000 */
_start:
    b    reset        /* 跳转到reset */

#ifdef CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK
/*
 * Various SoCs need something special and SoC-specific up front in
 * order to boot, allow them to set that in their boot0.h file and then
 * use it here.
 */
#include <asm/arch/boot0.h>
ARM_SOC_BOOT0_HOOK
#endif

    .align 3

.globl    _TEXT_BASE        /* _TEXT_BASE's address value 0000000048800008 */    
_TEXT_BASE:
    .quad    CONFIG_SYS_TEXT_BASE        /* 0x48800000 */

/*
 * These are defined in the linker script.
 */
.globl    _end_ofs            /* _end_ofs's address value 0000000048800010 */
_end_ofs:
    .quad    _end - _start        /* 00000000488afa58 -     0000000048800000 = 0x000afa58 */

.globl    _bss_start_ofs            /* _bss_start_ofs's address value 0000000048800018 */
_bss_start_ofs:
    .quad    __bss_start - _start    /* 00000000488afa58 -     0000000048800000 = 0x000afa58 */

.globl    _bss_end_ofs            /* _bss_end_ofs's address value 0000000048800020 */
_bss_end_ofs:
    .quad    __bss_end - _start    /* 0000000048906758 - 0000000048800000 = 0x106758 */

reset:                    /* reset's address value 0000000048800028 */
    /* Allow the board to save important registers */
    b    save_boot_params
.globl    save_boot_params_ret
save_boot_params_ret:

#ifdef CONFIG_SYS_RESET_SCTRL
    bl reset_sctrl
#endif
    /*
     * Could be EL3/EL2/EL1, Initial State: // Defines the ARMv8 Exception model, with up to four Exception levels, EL0 - EL3, that
                        // provide an execution privilege hierarchy. OS(EL1), Hypervisor (EL2), Secure Monitor (EL3)
     * Little Endian, MMU Disabled, i/dCache Disabled
     */
    adr    x0, vectors            /* exceptions.S */
    switch_el x1, 3f, 2f, 1f        /* 汇编宏,按异常级别选择下面3、2、1、0的分支, macro.h */
3:    msr    vbar_el3, x0            /* Vector Base Address Register (EL3) */
    mrs    x0, scr_el3            /* Secure Configuration Register */
    orr    x0, x0, #0xf            /* SCR_EL3.NS|IRQ|FIQ|EA */
    msr    scr_el3, x0
    msr    cptr_el3, xzr            /* Enable FP/SIMD , Architectural Feature Trap Register (EL3) */
#ifdef COUNTER_FREQUENCY
    ldr    x0, =COUNTER_FREQUENCY        /* 0x1800000 */
    msr    cntfrq_el0, x0            /* Initialize CNTFRQ. Counter-timer Frequency register */
#endif
    b    0f
2:    msr    vbar_el2, x0            /* Vector Base Address Register (EL2) */
    mov    x0, #0x33ff
    msr    cptr_el2, x0            /* Enable FP/SIMD. Architectural Feature Trap Register (EL2) */
    b    0f
1:    msr    vbar_el1, x0            /* ector Base Address Register (EL1) */
    mov    x0, #3 << 20
    msr    cpacr_el1, x0            /* Enable FP/SIMD. Architectural Feature Trap Register (EL1) */
0:

    /* Apply ARM core specific erratas */
    bl    apply_core_errata        /* WEAK函数, 本文件实现 */

    /*
     * 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            /* 处理器特定初始化, 本文件实现  */

#if CONFIG_IS_ENABLED(ARMV8_SPIN_TABLE) /* 无定义,不执行 */
    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 */
master_cpu:
    bl    _main            /* crt0_64.S */

#ifdef CONFIG_SYS_RESET_SCTRL  /* 无定义,不执行 */
reset_sctrl:
    switch_el x1, 3f, 2f, 1f
3:
    mrs    x0, sctlr_el3        /* system Control Register (EL3), save x0 */
    b    0f
2:
    mrs    x0, sctlr_el2        /* system Control Register (EL2), save x0 */
    b    0f
1:
    mrs    x0, sctlr_el1        /* system Control Register (EL1), save x0 */

0:
    ldr    x1, =0xfdfffffa
    and    x0, x0, x1

    switch_el x1, 6f, 5f, 4f
6:
    msr    sctlr_el3, x0
    b    7f
5:
    msr    sctlr_el2, x0
    b    7f
4:
    msr    sctlr_el1, x0

7:
    dsb    sy
    isb
    b    __asm_invalidate_tlb_all
    ret
#endif

/*-----------------------------------------------------------------------*/

WEAK(apply_core_errata)

    mov    x29, lr            /* Save LR */
    /* For now, we support Cortex-A57 specific errata only */

    /* Check if we are running on a Cortex-A57 core */
    branch_if_a57_core x0, apply_a57_core_errata        /* macro.h, 如果当前处理器是Cortex-A57内核,则进行分支 */
0:
    mov    lr, x29            /* Restore LR */
    ret

apply_a57_core_errata:    /* 如果是Cortex-A57 MPCore processor, 由上面 branch_if_a57_core 判断是后调用 */

#ifdef CONFIG_ARM_ERRATA_828024        /* 都无定义,不执行 */
    mrs    x0, S3_1_c15_c2_0    /* cpuactlr_el1 */
    /* Disable non-allocate hint of w-b-n-a memory type */
    orr    x0, x0, #1 << 49
    /* Disable write streaming no L1-allocate threshold */
    orr    x0, x0, #3 << 25
    /* Disable write streaming no-allocate threshold */
    orr    x0, x0, #3 << 27
    msr    S3_1_c15_c2_0, x0    /* cpuactlr_el1 */
#endif

#ifdef CONFIG_ARM_ERRATA_826974    /* 无定义,不执行 */
    mrs    x0, S3_1_c15_c2_0    /* cpuactlr_el1 */
    /* Disable speculative load execution ahead of a DMB */
    orr    x0, x0, #1 << 59
    msr    S3_1_c15_c2_0, x0    /* cpuactlr_el1 */
#endif

#ifdef CONFIG_ARM_ERRATA_833471    /* 无定义,不执行 */
    mrs    x0, S3_1_c15_c2_0    /* cpuactlr_el1 */
    /* FPSCR write flush.
     * Note that in some cases where a flush is unnecessary this
        could impact performance. */
    orr    x0, x0, #1 << 38
    msr    S3_1_c15_c2_0, x0    /* cpuactlr_el1 */
#endif

#ifdef CONFIG_ARM_ERRATA_829520   /* 无定义,不执行 */
    mrs    x0, S3_1_c15_c2_0    /* cpuactlr_el1 */
    /* Disable Indirect Predictor bit will prevent this erratum
        from occurring
     * Note that in some cases where a flush is unnecessary this
        could impact performance. */
    orr    x0, x0, #1 << 4
    msr    S3_1_c15_c2_0, x0    /* cpuactlr_el1 */
#endif

#ifdef CONFIG_ARM_ERRATA_833069   /* 无定义,不执行 */
    mrs    x0, S3_1_c15_c2_0    /* cpuactlr_el1 */
    /* Disable Enable Invalidates of BTB bit */
    and    x0, x0, #0xE
    msr    S3_1_c15_c2_0, x0    /* cpuactlr_el1 */
#endif
    b 0b
ENDPROC(apply_core_errata)

/*-----------------------------------------------------------------------*/

WEAK(lowlevel_init)    /* 底层初始化 */
    mov    x29, lr            /* Save LR */

#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)  /* 无定义,不执行 */
    branch_if_slave x0, 1f
    ldr    x0, =GICD_BASE
    bl    gic_init_secure
1:
#if defined(CONFIG_GICV3)   /* 无定义,不执行 */
    ldr    x0, =GICR_BASE
    bl    gic_init_secure_percpu
#elif defined(CONFIG_GICV2)   /* 无定义,不执行 */
    ldr    x0, =GICD_BASE
    ldr    x1, =GICC_BASE
    bl    gic_init_secure_percpu
#endif
#endif

#ifdef CONFIG_ARMV8_MULTIENTRY   /* 无定义,不执行 */
    branch_if_master x0, x1, 2f

    /*
     * Slave should wait for master clearing spin table.
     * This sync prevent salves observing incorrect
     * value of spin table and jumping to wrong place.
     */
#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)  /* 无定义,不执行 */
#ifdef CONFIG_GICV2
    ldr    x0, =GICC_BASE
#endif
    bl    gic_wait_for_interrupt
#endif

    /*
     * All slaves will enter EL2 and optionally EL1.
     */
    bl    armv8_switch_to_el2        /* transition.S */
#ifdef CONFIG_ARMV8_SWITCH_TO_EL1
    bl    armv8_switch_to_el1
#endif

#endif /* CONFIG_ARMV8_MULTIENTRY */

2:
    mov    lr, x29            /* Restore LR */
    ret
ENDPROC(lowlevel_init)

WEAK(smp_kick_all_cpus)
    /* Kick secondary cpus up by SGI 0 interrupt */
#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
    ldr    x0, =GICD_BASE
    b    gic_kick_secondary_cpus
#endif
    ret
ENDPROC(smp_kick_all_cpus)

/*-----------------------------------------------------------------------*/

ENTRY(c_runtime_cpu_setup)
    /* Relocate vBAR */
    adr    x0, vectors
    switch_el x1, 3f, 2f, 1f    /* 按异常级别选择分支后把vectors赋给vbar_elX */
3:    msr    vbar_el3, x0
    b    0f
2:    msr    vbar_el2, x0
    b    0f
1:    msr    vbar_el1, x0
0:

    ret
ENDPROC(c_runtime_cpu_setup)

WEAK(save_boot_params)
    b    save_boot_params_ret    /* back to my caller */
ENDPROC(save_boot_params)

 

从start.S调转至crt0_64.S

/*

 * u-boot-2016.11/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).
 */
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)    /* 无定义,不执行 */
    ldr    x0, =(CONFIG_SPL_STACK)
#else
    ldr    x0, =(CONFIG_SYS_INIT_SP_ADDR)            /* 0x08004000 , 系统初始化堆栈地址 */
#endif
    bic    sp, x0, #0xf    /* 16-byte alignment for ABI compliance, 符合ABI的16字节对齐 */
    mov    x0, sp
    bl    board_init_f_alloc_reserve    /* 减掉CONFIG_SYS_MALLOC_F_LEN,再减掉sizeof(struct global_data)并16字节对齐后生成一个新的堆栈地址 */
    mov    sp, x0                /* x0 为新的堆栈地址 */
    /* set up gd here, outside any C code 在这里设置gd,在任何C代码之外 */
    mov    x18, x0                /* x18 = x0, register volatile gd_t *gd asm ("x18") */
    bl    board_init_f_init_reserve    /* 初始化保留空间(已从C运行时环境处理代码安全地分配到C堆栈上) */

    mov    x0, #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.
 */
/*
 * 设置中间环境(新的sp和gd)并调用relocate_code(addr_moni)。这里的诀窍是我们将返回"这里",但重新安置。
 */
    ldr    x0, [x18, #GD_START_ADDR_SP]    /* x0 <- gd->start_addr_sp */    /* #GD_START_ADDR_SP=120 */
    bic    sp, x0, #0xf    /* 16-byte alignment for ABI compliance */
    ldr    x18, [x18, #GD_BD]        /* x18 <- gd->bd */        /* #GD_BD=0 */
    sub    x18, x18, #GD_SIZE        /* new GD is below bd */    /* #GD_SIZE=360 */

    adr    lr, relocation_return
    ldr    x0, [x18, #GD_RELOCADDR]    /* x0 <- gd->relocaddr */    /* GD_RELOCADDR=88 */
    adr x9, _start
    sub x9, x0, x9                /* x9 <- gd->reloc_off */
    add    lr, lr, x9    /* new return address after relocation */
    b    relocate_code    /* relocate_64.S */        

relocation_return:

/*
 * Set up final (full) environment
 */
    bl    c_runtime_cpu_setup        /* still call old routine */
#endif /* !CONFIG_SPL_BUILD */

/* TODO: For SPL, call spl_relocate_stack_gd() to alloc stack relocation */

/*
 * 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]    /* _bss_start = 0 */
    add    x0, x0, #8    /* _bss_start += 8 */    
    cmp    x0, x1        /* __bss_start ?= __bss_end */
    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 */    /* run_main_loop */

    /* NOTREACHED - board_init_r() does not return */

ENDPROC(_main)

调用 board_init_r 后,uboot开始死循环,已经准备好启动命令了。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值