前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >2. uboot 2021.07移植记录--分析start.S

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

作者头像
锦小年
发布2022-01-10 09:37:27
4590
发布2022-01-10 09:37:27
举报
文章被收录于专栏:锦小年的博客锦小年的博客

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

代码语言:javascript
复制
_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 宏定义在配置选项中被设置,所以以下代码会被运行。

代码语言:javascript
复制
#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等级,初始化异常向量表。

代码语言:javascript
复制
#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:

代码语言:javascript
复制
	/* cpu 勘误修正,一般都不用 */
	bl	apply_core_errata
	bl	lowlevel_init
	bl _main

而_main 是再crt0_64.S文件中。

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

代码语言:javascript
复制
(1)如果定义了CONFIG_POSITION_INDEPENDENT,则根据实际运行地址和链接地址来修正rel_dyn 段,参照arm位置无关代码。
(2)根据当前el等级,把中断向量表放到对应的el的寄存器中
(3)lowlevel_init中根据中断控制器的类型初始化中断控制器
(4)跳转到_main
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-12-31 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档