2. uboot 2021.07移植记录--分析start.S

lds文件可以看出,程序入口函数为_start,下面从_start 开始分析start.s文件中有用的部分。

_start:
	b reset @do nothing, jump to save_boot_params
	b save_boot_params @do nothing,jump to save_boot_params_ret
	b save_boot_params_ret

接下来在运行save_boot_params_ret标号段的代码。

CONFIG_POSITION_INDEPENDENT 宏定义在配置选项中被设置,所以以下代码会被运行。

#if CONFIG_POSITION_INDEPENDENT
	/* Verify that we're 4K aligned.  */
	adr	x0, _start
	ands	x0, x0, #0xfff
	b.eq	1f
0:
	/*
	 * FATAL, can't continue.
	 * U-Boot needs to be loaded at a 4K aligned address.
	 *
	 * We use ADRP and ADD to load some symbol addresses during startup.
	 * The ADD uses an absolute (non pc-relative) lo12 relocation
	 * thus requiring 4K alignment.
	 */
	wfi
	b	0b
1:

	/*
	 * 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 */
	subs	x9, x0, x1		/* x9 <- Run-vs-link offset */
	beq	pie_fixup_done
	adrp    x2, __rel_dyn_start     /* x2 <- Runtime &__rel_dyn_start */
	add     x2, x2, #:lo12:__rel_dyn_start
	adrp    x3, __rel_dyn_end       /* x3 <- Runtime &__rel_dyn_end */
	add     x3, x3, #:lo12:__rel_dyn_end
pie_fix_loop:
	/* 对于AArch64架构,一组rela.dyn数据有3个64位数据组成,
	* 从上到下分别是需要重定向的原始地址,重定向类型,重定向的原始数据。
	* x0=原始地址,x1=重定向类型,这里类型为1027,x2=原始数据。
	* 重定向的目标则是将原始地址和数据修改为运行时对应的地址和数据*/
	/* x0 = [x2], x1 = [x2+8], x2 = x2+16*/
	ldp	x0, x1, [x2], #16	/* (x0, x1) <- (Link location, fixup) */
	/* x4=[x2], x2=x2+8*/
	ldr	x4, [x2], #8		/* x4 <- addend */
	/* */
	cmp	w1, #1027		    /* relative fixup? */
	/*如果不为1027,则不属于此次应该重定向的数据,则跳过 */
	bne	pie_skip_reloc
	/* relative fix: store addend plus offset at dest location */
	/* x0=x0+x9,x9是运行地址相对于链接地址的偏移量*/
	add	x0, x0, x9
	/* x4=x4+x9,x9是运行地址相对于链接地址的偏移量*/
	add	x4, x4, x9
	/* 将新数据放到新的地址上*/
	str	x4, [x0]
pie_skip_reloc:
	/* start=end,跳转到pie_fixup_done运行,如果不等,则跳转到pie_fix_loop继续*/
	cmp	x2, x3
	b.lo	pie_fix_loop
pie_fixup_done:
#endif

这段代码用于位置无关代码段的rel.dyn段,判断代码实际运行地址与链接地址是否相等,如果不相等,则需要吧rel_dyn段搬运到运行处对应的位置。
对于AArch64架构,一组rela.dyn数据有3个64位数据组成,从上到下分别是需要重定向的原始地址,重定向类型,重定向的原始数据(这里的原始数据也是地址:全局变量的地址等)。

接下来根据实际运行的el等级,初始化异常向量表。

#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
	/*
	 * 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
	mov	x0, #3 << 20
	msr	cpacr_el1, x0			/* Enable FP/SIMD */
0:
	isb

vectors是excecption.S文件中的代码,定义了异常向量表和中断函数。
至此,cpu进入了关闭mmu,cache,tlb的状态。

最后主cpu跳转到_main:

	/* cpu 勘误修正,一般都不用 */
	bl	apply_core_errata
	bl	lowlevel_init
	bl _main

而_main 是再crt0_64.S文件中。

综上,start.S里面做了以下事情:

(1)如果定义了CONFIG_POSITION_INDEPENDENT,则根据实际运行地址和链接地址来修正rel_dyn 段,参照arm位置无关代码。
(2)根据当前el等级,把中断向量表放到对应的el的寄存器中
(3)lowlevel_init中根据中断控制器的类型初始化中断控制器
(4)跳转到_main
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值