当前位置 博文首页 > liuwanpeng:uboot1: 启动流程和移植框架

    liuwanpeng:uboot1: 启动流程和移植框架

    作者:liuwanpeng 时间:2021-05-17 18:29

    目录
    • 0 环境
    • 1 移植框架
    • 3 执行流程
      • 3.0 链接地址
      • 3.1 start.S, 入口
      • 3.2 __main
      • 3.3 board_init_f()和init_sequence_f[]
      • 3.4 relocate
      • 3.5 board_init_r()
        • 3.5.1 init_sequence_r
        • 3.5.2 main_loop
    • 参考

    0 环境

    ARMV8,uboot 2020.10,rpi3平台

    1 移植框架

    • board,不用说了,板级,uboot使用dts后,这块代码应尽量简化
    • machine, SOC级,主要是一些外设
    • ARCH, 如arm(包含armv7和armv8)
    • CPU, 如armv8

    各框架启动时的关系:

    配置相关文件:

    configs/xxx_defconfig: 平台的默认配置,make ***_defconfig时会用到
    include/conigs/***.h: 各平台的一些额外CONFIG_配置项,写在头文件里
    

    3 执行流程

    3.0 链接地址

    Makefile中:

    LDFLAGS_u-boot += -Ttext $(CONFIG_SYS_TEXT_BASE)
    

    链接文件

    ENTRY(_start)
    SECTIONS
    {
     . = 0x00000000; /*text段在lds文件的偏移0*/
     . = ALIGN(8);
     .text :
     {
      *(.__image_copy_start)
      arch/arm/cpu/armv8/start.o (.text*)
     }
     ...
    
    • CONFIG_SYS_TEXT_BASE: lds文件中偏移为0,再结合-Ttext选项, 所以CONFIG_SYS_TEXT_BASE是重定位之前,最初的uboot起始地址

    3.1 start.S, 入口

    此阶段的CONFIG_

    已定义:
    CONFIG_SYS_TEXT_BASE: uboot realocate之前的起始地址,代码里 _TEXT_BASE = CONFIG_SYS_TEXT_BASE
    
    未定义:
    CONFIG_SYS_RESET_SCTRL, 设置 little endian, 关cache, 关MMU
    CONFIG_ARMV8_SET_SMPEN, 若为EL3,使能SMPEN, EL2/1无动作
    CONFIG_ARMV8_SPIN_TABLE和CONFIG_ARMV8_MULTIENTRY,像是两种处理slave core的方式,不过rpi3应该只有core0执行uboot,所以都没有定义
    

    代码加注释:arch/arm/cpu/armv8/start.S

    /*************************************************************************
     *
     * Startup Code (reset vector)
     *
     *************************************************************************/
    
    .globl	_start
    _start:
    #if defined(CONFIG_LINUX_KERNEL_IMAGE_HEADER)
    #include <asm/boot0-linux-kernel-header.h>
    #elif defined(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>
    #else
    	b	reset     // 执行此分支
    #endif
    
    	.align 3    #  2^3 = 8 Bytes对齐
    
    /*
     * 计算几个变量的值,并写入bin文件里,这些变量后面会用到
     */
    .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:
    	/* Allow the board to save important registers */
    	b	save_boot_params    // 一般为空,直接跳到save_boot_params_ret
    .globl	save_boot_params_ret
    save_boot_params_ret:
    
    #if CONFIG_POSITION_INDEPENDENT // 未定义
    	/*
    	 * Fix .rela.dyn relocations. This allows U-Boot to be loaded to and
    	 * executed at a different address than it was linked at.
    	 */
    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
    
    // 未定义此宏,设置 little endian, 关cache、 关MMU
    #ifdef CONFIG_SYS_RESET_SCTRL  
    	bl reset_sctrl
    #endif
    
    #if defined(CONFIG_ARMV8_SPL_EXCEPTION_VECTORS) || !defined(CONFIG_SPL_BUILD)
    .macro	set_vbar, regname, reg
    	msr	\regname, \reg
    .endm
    	adr	x0, vectors     # vectors是中断向量表,在arch/arm/cpu/armv8/exception.S中定义
    #else
    .macro	set_vbar, regname, reg
    .endm
    #endif
    	/*
    	 * Could be EL3/EL2/EL1, Initial State:
    	 * Little Endian, MMU Disabled, i/dCache Disabled
    	 */
    	switch_el x1, 3f, 2f, 1f
    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 */
    #ifdef COUNTER_FREQUENCY
    	ldr	x0, =COUNTER_FREQUENCY
    	msr	cntfrq_el0, x0			/* Initialize CNTFRQ */
    #endif
    	b	0f
    2:	set_vbar	vbar_el2, x0
    	mov	x0, #0x33ff
    	msr	cptr_el2, x0			/* Enable FP/SIMD */
    	b	0f
    1:	set_vbar	vbar_el1, x0    /* 设置中断向量表,x0 = vectors */
    	mov	x0, #3 << 20
    	msr	cpacr_el1, x0			/* Enable FP/SIMD */
    0:
    	isb
    
    	/*
    	 * Enable SMPEN bit for coherency.
    	 * This register is not architectural but at the moment
    	 * this bit should be set for A53/A57/A72.
    	 */
    #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
    	isb
    1:
    #endif
    
    	/* Apply ARM core specific erratas,处理一些已知的芯片bug */
    	bl	apply_core_errata
    
    	/*
    	 * 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 */
    	// 初始化临时sp, 实现一个weak函数s_init,给各个平台一个早期初始化的机会
        // 不过重新实现s_init的厂商不多
    	bl	lowlevel_init
    
    #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 */
    master_cpu:
    	bl	_main   /*  跳转后不返回*/
    
    

    3.2 __main


    此阶段的CONFIG_

    已定义:
    CONFIG_SYS_INIT_SP_ADDR: 调用board_init_f和relocate_code之前用的SP
    CONFIG_SYS_MALLOC_F_LEN: 早期用于malloc的空间大小
    
    未定义:
    CONFIG_TPL_BUILD:TPL跟SPL差不多,是第三级程序加载器,也是一个精简版的u-boot,很少用到,参见 doc/README.TPL
    

    代码加注释:arch/arm/lib/crt0_64.S

    ENTRY(_main)
    
    /*
     * Set up initial C runtime environment and call board_init_f(0).
     * 先分配SP地址(CONFIG_SYS_INIT_SP_ADDR), 在sp上分配大名鼎鼎的gd_t空间,gd_t是重要的全局数据,地址保存在X18里,整个uboot都在使用
     */
    #if defined(CONFIG_TPL_BUILD) && defined(CONFIG_TPL_NEEDS_SEPARATE_STACK)
    	ldr	x0, =(CONFIG_TPL_STACK)
    #elif defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
    	ldr	x0, =(CONFIG_SPL_STACK)
    #elif defined(CONFIG_INIT_SP_RELATIVE)
    	adr	x0, __bss_start
    	add	x0, x0, #CONFIG_SYS_INIT_SP_BSS_OFFSET
    #else
    	ldr	x0, =(CONFIG_SYS_INIT_SP_ADDR)      // 进此分支, CONFIG_SYS_INIT_SP_ADDR一般在include/configs/****.h中定义
    #endif
    	bic	sp, x0, #0xf	/* 16-byte alignment for ABI compliance */
    	mov	x0, sp
    	bl	board_init_f_alloc_reserve    // 从sp顶端分配早期malloc空间(受CONFIG_SYS_MALLOC_F_LEN控制),分配global_data(gd)空间
    	mov	sp, x0
    	/* set up gd here, outside any C code, 把global_data的地址赋给X18,X18始终保存着gd的地址 */
    	mov	x18, x0
    	bl	board_init_f_init_reserve      // gd初始化为0, gd->malloc_base赋值(受CONFIG_SYS_MALLOC_F_LEN控制)
    
    	mov	x0, #0
    	bl	board_init_f                // front, 前置初始化.执行函数指针数组init_sequence_f里的若干初始化函数,会把重定位时需要的若干信息写给gd
    
    #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	x0, [x18, #GD_START_ADDR_SP]	/* x0 <- gd->start_addr_sp, 获取重定位后的sp地址*/
    	bic	sp, x0, #0xf	/* 16-byte alignment for ABI compliance ,将重定位后的地址赋给sp */
    	ldr	x18, [x18, #GD_NEW_GD]		/* x18 <- gd->new_gd, 将重定位后的gd地址赋给X18 */
    
       /* 先把relocation_return给lr,此时lr的地址是为重定位前的relocation_return
        * 后面会给lr增加重定位的offset,保证重定位执行完毕返回lr时,能找到重定位后的relocation_return
        */
    	adr	lr, relocation_return       
    #if CONFIG_POSITION_INDEPENDENT      // 未定义
    	/* Add in link-vs-runtime offset */
    	adr	x0, _start		/* x0 <- Runtime value of _start */
    	ldr	x9, _TEXT_BASE		/* x9 <- Linked value of _start */
    	sub	x9, x9, x0		/* x9 <- Run-vs-link offset */
    	add	lr, lr, x9
    #endif
    	/* Add in link-vs-relocation offset */
    	ldr	x9, [x18, #GD_RELOC_OFF]	/* x9 <- gd->reloc_off */
    	add	lr, lr, x9	/* new return address after relocation, 给lr加上重定位offset,此时lr已经指向重定位后的relocation_return */
    	ldr	x0, [x18, #GD_RELOCADDR]	/* x0 <- gd->relocaddr, 重定位后的起始地址 */
    	b	relocate_code               /* 重定位,拷贝text、data、rodata段, 拷贝并重写rel_dyn段,具体原理单独描述 */
    
    relocation_return:
    
    /*
     * Set up final (full) environment
     */
    	bl	c_runtime_cpu_setup		/* still call old routine, 设置中断向量表vbar_elX */
    #endif /* !CONFIG_SPL_BUILD */
    #if !defined(CONFIG_SPL_BUILD) || CONFIG_IS_ENABLED(FRAMEWORK)
    #if defined(CONFIG_SPL_BUILD)
    	bl	spl_relocate_stack_gd           /* may return NULL */
    	/* set up gd here, outside any C code, if new stack is returned */
    	cmp	x0, #0
    	csel	x18, x0, x18, ne
    	/*
    	 * Perform 'sp = (x0 != NULL) ? x0 : sp' while working
    	 * around the constraint that conditional moves can not
    	 * have 'sp' as an operand
    	 */
    	mov	x1, sp
    	cmp	x0, #0
    	csel	x0, x0, x1, ne
    	mov	sp, x0
    #endif
    
    /*
     * Clear BSS section
     */
    	ldr	x0, =__bss_start		/* this is auto-relocated! */
    	ldr	x1, =__bss_end			/* this is auto-relocated! */
    clear_loop:
    	str	xzr, [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,重定位后的初始化和main loop, rear后置初始化 */
    
    	/* NOTREACHED - board_init_r() does not return */
    #endif
    
    ENDPROC(_main)
    

    3.3 board_init_f()和init_sequence_f[]

    此阶段的CONFIG_选项:

    已定义:
    CONFIG_OF_CONTROL:使用device tree
    CONFIG_OF_EMBED: dts与uboot集成到一起,一般都用此方式。makefile连接时会把dtb放到__dtb_dt_begin的位置
    CONFIG_DM: 使能driver model,驱动模型,一套抽象且统一的驱动框架,复杂了,也为标准化
    CONFIG_BAUDRATE, 默认串口波特率
    CONFIG_SERIAL_PRESENT,存在串口
    CONFIG_DM_VIDEO,
    
    未定义:
    CONFIG_OF_SEPARATE:dts与uboot分开,一般不用
    CONFIG_TIMER_EARLY:尽早使用timer
    CONFIG_BOARD_EARLY_INIT_F: 早期board初始化,给board提供一个hook
    CONFIG_SYSRESET
    CONFIG_DISPLAY_CPUINFO
    CONFIG_DISPLAY_BOARDINFO
    CONFIG_SYS_I2C
    CONFIG_SYS_DRAM_TEST
    CONFIG_SYS_MEM_TOP_HIDE: 让uboot对上面的内存不可见,将ram_size -= CONFIG_SYS_MEM_TOP_HIDE
    CONFIG_SYS_SDRAM_BASE: DDR的起始地址,没啥意义,0
    CONFIG_PRAM: protected RAM, 可以预留一段不被uboot使用
    CONFIG_SYS_NONCACHED_MEMORY:分配non-cache区域
    

    board_init_f()直接执行init_sequence_f[]里的若干函数,黄底层为board移植时一般需要实现的。

    • setup_mon_len(), gd->mon_len = 整个程序大小(text/data/bss等)
    • fdtdec_setup(),gd->fdt_blob = __dtb_dt_begin,dts用
    • initf_malloc(), 初始化gd的malloc相关成员,gd->malloc_limit和gd->malloc_ptr
    • log_init(),log相关初始化,暂不关注
    • initf_bootstage(),初始化bootstage功能,用于标记启动到哪个阶段了
    • arch_cpu_init(),cpu级别的初始化操作,可以在需要的时候由CPU有关的code实现,weak实现啥也没干
    • mach_cpu_init(), SoC/machine级别初始化,在mach_***里可以覆盖weak实现
    • initf_dm(), driver model有关的初始化操作
    • arch_cpu_init_dm(), cpu相关的dm初始化
    • board_early_init_f(), 早期board级初始化,一般没用
    • timer_init(), timer初始化
    • env_init,environment系统初始化
    • init_baud_rate,gd->baudrate = env_get_ulong("baudrate", 10, CONFIG_BAUDRATE),优先从环境变量“baudrate”中获取
    • serial_init, 初始化串口,之后串口可用
    • console_init_f
    • display_options,显示版本信息等
    • display_text_info,进一步显示信息
    • checkcpu
    • announce_dram_init,打印一句话
    • dram_init, ddr初始化,如果其他boot已经初始化了,初始化gd->ram_size = ***
    • testdram, dram测试
    • 后面是重定位后的地址分配相关内容,分配空间的函数以reserve_***开头,见下图

      uboot把自己重定位到高地址,linux启动后在低地址
    • dram_init_banksize(),设置:
    	gd->bd->bi_dram[bank].start
    	gd->bd->bi_dram[bank].size
        gd->ram_size
    	gd->ram_base 
    
    • show_dram_config(), 显示dram信息
    • setup_bdinfo(), bd->bi_memstart和bd->bi_memsize
    • display_new_sp(), 显示sp
    • reloc_fdt(),reloc_bootstage(), reloc_bloblist(),如果定义了相关宏,则把对应内容放到上面图中对位的位置
    • setup_reloc(), 计算gd->reloc_off,将gd拷贝到新地址

    3.4 relocate

    • relocate的历史:可能是早期SOC,uboot可能在ROM中执行,效率低,所以要拷贝到RAM里,虽然当前SOC, 一般UBOOT在一开始就在RAM里了,但relocate这个环节被保留了。
    • arch/arm/lib/relocate_64.S, 对text、data、rel_dyn做重定位处理,返回时,已经在新地址运行了。
    • relocate是uboot比较难理解的部分,需要一些基础知识。

      1.每个func后面有label,PC+offset找labal;2.label中存全局变量地址;3.func后面的label作为text段的一部分; 4.rel_dyn段再保存所有label的地址;5.重定位时从rel_dyn段找lable地址,再修改lable里的内容,即修改了全局变量的地址
    • rel_dyn里保存的数据格式(arm64)
    -objdump -D u-boot > uboot_objdump.txt可得:
    
    Disassembly of section .rela.dyn:
    00000000000f6940 <__image_copy_end>:
       ...
       f6970:	00082ad0 	.inst	0x00082ad0 ; undefined
       f6974:	00000000 	udf	#0       // 8B, lable 地址
       f6978:	00000403 	udf	#1027
       f697c:	00000000 	udf	#0       // 8B, 标记
       f6980:	00102070 	.inst	0x00102070 ; undefined
       f6984:	00000000 	udf	#0      // 8B, lable中保存的数据,即地址0x00082ad0里保存的值(全局变量地址)
       ...
      f69a0:	000d71b8 	.inst	0x000d71b8 ; undefined
       f69a4:	00000000 	udf	#0
       f69a8:	00000403 	udf	#1027
       f69ac:	00000000 	udf	#0
       f69b0:	000e85e6 	.inst	0x000e85e6 ; undefined
       f69b4:	00000000 	udf	#0
    

    rel_dyn的格式为:

    long lable_addr;        label地址
    long flag = 1027;
    long val_in_lable;      labal里存的内容,即全局变量地址
    

    所以rel_dyn重定位就很简单了, [lable_addr + rel_off] = val_in_lable + rel_off,, 段.rela.dyn本身没有拷贝,重定位后就不用了。

    源码分析:

    /*
     * void relocate_code(addr_moni)
     *
     * This function relocates the monitor code.
     * x0 holds the destination address.
     */
    ENTRY(relocate_code)
    	stp	x29, x30, [sp, #-32]!	/* create a stack frame */
    	mov	x29, sp
    	str	x0, [sp, #16]
    	/*
    	 * Copy u-boot from flash to RAM
    	 * __image_copy_start = _TEXT_BASE = CONFIG_SYS_TEXT_BASE = 0x80000, 初始加载地址
    	 */
    	adrp	x1, __image_copy_start		/* x1 <- address bits [31:12] */
    	add	x1, x1, :lo12:__image_copy_start/* x1 <- address bits [11:00] */
    	subs	x9, x0, x1			/* x9 <- Run to copy offset, X9 = 重定位前后地址的offset */
    	b.eq	relocate_done			/* skip relocation */
    	/*
    	 * Don't ldr x1, __image_copy_start here, since if the code is already
    	 * running at an address other than it was linked to, that instruction
    	 * will load the relocated value of __image_copy_start. To
    	 * correctly apply relocations, we need to know the linked value.
    	 *
    	 * Linked &__image_copy_start, which we know was at
    	 * CONFIG_SYS_TEXT_BASE, which is stored in _TEXT_BASE, as a non-
    	 * relocated value, since it isn't a symbol reference.
    	 */
    	ldr	x1, _TEXT_BASE		/* x1 <- Linked &__image_copy_start */
    	subs	x9, x0, x1		/* x9 <- Link to copy offset, X9 = 重定位前后地址的offset */
    
    	adrp	x1, __image_copy_start		/* x1 <- address bits [31:12] */
    	add	x1, x1, :lo12:__image_copy_start/* x1 <- address bits [11:00] */
    	adrp	x2, __image_copy_end		/* x2 <- address bits [31:12] */
    	add	x2, x2, :lo12:__image_copy_end	/* x2 <- address bits [11:00] */
    copy_loop:
    	ldp	x10, x11, [x1], #16	/* copy from source address [x1] */
    	stp	x10, x11, [x0], #16	/* copy to   target address [x0] */
    	cmp	x1, x2			/* until source end address [x2] */
    	b.lo	copy_loop
    	str	x0, [sp, #24]
    	
    	/* 上面代码完成__image_copy_start、__image_copy_end之间的代码拷贝,包括text和data段 */
    	
    	/*
    	 * Fix .rela.dyn relocations
    	 * rela.dyn里1个LABEL结构是:
    	 * 8 Bytes 地址
    	 * 8 Bytes 标记
    	 * 8 Bytes addend
    	 */
    	adrp	x2, __rel_dyn_start		/* x2 <- address bits [31:12] */
    	add	x2, x2, :lo12:__rel_dyn_start	/* x2 <- address bits [11:00] */
    	adrp	x3, __rel_dyn_end		/* x3 <- address bits [31:12] */
    	add	x3, x3, :lo12:__rel_dyn_end	/* x3 <- address bits [11:00] */
    fixloop:
    	ldp	x0, x1, [x2], #16	/* (x0,x1) <- (SRC location, fixup), X0是label地址,X1存标记 */
    	ldr	x4, [x2], #8		/* x4 <- label地址里的值 */
    	and	x1, x1, #0xffffffff
    	cmp	x1, #R_AARCH64_RELATIVE
    	bne	fixnext
    
    	/* relative fix: store addend plus offset at dest location */
    	add	x0, x0, x9       
    	add	x4, x4, x9
    	str	x4, [x0]       /* label值 + offset =  lable里的值(全局变量地址) +offset */
    fixnext:
    	cmp	x2, x3
    	b.lo	fixloop
    
    relocate_done:
    	switch_el x1, 3f, 2f, 1f
    	bl	hang
    3:	mrs	x0, sctlr_el3
    	b	0f
    2:	mrs	x0, sctlr_el2
    	b	0f
    1:	mrs	x0, sctlr_el1
    0:	tbz	w0, #2, 5f	/* skip flushing cache if disabled */
    	tbz	w0, #12, 4f	/* skip invalidating i-cache if disabled */
    	ic	iallu		/* i-cache invalidate all */
    	isb	sy
    4:	ldp	x0, x1, [sp, #16]
    	bl	__asm_flush_dcache_range
    	bl     __asm_flush_l3_dcache
    5:	ldp	x29, x30, [sp],#32
    	ret
    ENDPROC(relocate_code)
    

    3.5 board_init_r()

    3.5.1 init_sequence_r

    relocate之后的初始化及主函数,执行init_sequence_r[]里的函数指针。

    • initr_trace,初始化并使能u-boot的tracing system,涉及的配置项有CONFIG_TRACE。
    • initr_reloc,设置relocation完成的标志。
    • initr_caches,使能dcache、icache等,涉及的配置项有CONFIG_ARM。
    • initr_reloc_global_data(), 重定位gd相关内容,gd->env_addr,gd->fdt_blob,efi相关初始化
    • initr_malloc,malloc有关的初始化
    • log_init, log相关初始化
    • initr_dm, relocate之后,重新初始化DM,涉及的配置项有CONFIG_DM
    • board_init,具体的板级初始化,需要由board代码根据需要实现,涉及的配置项有CONFIG_ARM。
    • set_cpu_clk_info,Initialize clock framework,涉及的配置项有CONFIG_CLOCKS。
    • efi_memory_init, efi相关初始化
    • initr_binman() ?
    • initr_dm_devices, CONFIG_TIMER_EARLY决定是否初始化timer
    • stdio_init_tables
    • serial_initialize
    • initr_announce, 打印
    • board_early_init_r, CONFIG_BOARD_EARLY_INIT_R控制是否调用,板级实现
    • arch_early_init_r,由arch代码实现,涉及的配置项有CONFIG_ARCH_EARLY_INIT_R。
    • power_init_board,板级的power init代码,由板级代码实现,例如hold住power。
    • initr_flash,initr_nand,initr_onenand,initr_mmc,根据各宏调用各存储设备初始化
    • initr_env, 环境变量相关初始化
    • initr_secondary_cpu,其他core初始化
    • stdio_add_devices,各种输入输出设备的初始化,如LCD driver等
    • initr_jumptable ?
    • console_init_r
    • arch_misc_init, 受CONFIG_ARCH_MISC_INIT控制的arch杂项
    • misc_init_r, 受CONFIG_MISC_INIT_R控制
    • interrupt_init, 使能中断
    • initr_status_led,状态指示LED的初始化,涉及的配置项有CONFIG_STATUS_LED、STATUS_LED_BOOT。
    • initr_ethaddr,Ethernet的初始化,涉及的配置项有CONFIG_CMD_NET。
    • board_late_init, 由板级代码实现,涉及的配置项有CONFIG_BOARD_LATE_INIT
    • initr_net。网络初始化,CONFIG_CMD_NET
    • run_main_loop/main_loop,主循环

    3.5.2 main_loop

    参考

    http://www.wowotech.net/u-boot/boot_flow_1.html
    https://blog.csdn.net/skyflying2012/article/details/37660265
    https://blog.csdn.net/ooonebook/article/details/53047992

    bk
    下一篇:没有了