[A133]uboot启动流程

[A133]uboot启动流程

hongxi.zhu 2024-6-21

1. 第一阶段

lds描述

u-boot.lds中能找到程序的汇编入口ENTRY(_start)

brandy/brandy-2.0/u-boot-2018/u-boot.lds

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
...

ENTRY(_start)的实现在start.S中,根据平台架构, 有对应的实现,当前平台是armv8

_start

brandy/brandy-2.0/u-boot-2018/arch/arm/cpu/armv8/start.S

.globl	_start
_start:
#if defined(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  /* 跳转到reset块 */
#endif

reset

brandy/brandy-2.0/u-boot-2018/arch/arm/cpu/armv8/start.S

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:

	/*
	 * Could be EL3/EL2/EL1, Initial State:
	 * Little Endian, MMU Disabled, i/dCache Disabled
	 */
	adr	x0, vectors 	/*将异常向量表基地址写到x0*/
	switch_el x1, 3f, 2f, 1f	/*根据异常等级选择el3/el2/el1情况处理*/
3:	msr	vbar_el3, x0  /*el3*/
	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 */
	b	0f	/*设置完上述相关寄存器,跳出*/
2:	msr	vbar_el2, x0	/*el2*/
	mov	x0, #0x33ff
	msr	cptr_el2, x0			/* Enable FP/SIMD */
	b	0f
1:	msr	vbar_el1, x0	/*el1*/
	mov	x0, #3 << 20
	msr	cpacr_el1, x0			/* Enable FP/SIMD */
0:  /* 空执行,相当于跳出 */


	/* Apply ARM core specific erratas */
	bl	apply_core_errata  /*arm核的特殊配置*/

	/*
	 * 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  /* A133看起来没做啥事情 */

master_cpu:
	bl	_main  /*跳转到_main*/

_main

brandy/brandy-2.0/u-boot-2018/arch/arm/lib/crt0_64.S

ENTRY(_main)

/*
 * Set up initial C runtime environment and call board_init_f(0).
 */
 	/*清除x0寄存器的最低四位(#0xf即二进制1111)并赋值给sp栈指针, x0寄存器的值是调用方传递*/
	bic	sp, x0, #0xf	/* 16-byte alignment for ABI compliance */
	mov	x0, sp		/*将栈指针sp的值写入x0寄存器作为下一条bl命令的参数,这个参数就是global区域的顶部地址top*/
	bl	board_init_f_alloc_reserve		/*跳转到C中的board_init_f_alloc_reserve,给全局gd变量分配内存*/
	mov	sp, x0		/*上面的bl命令执行后,它的返回值存放在x0中,将这个新的栈指针值赋值给sp指针*/
	/* set up gd here, outside any C code */
	mov	x18, x0		/*x18寄存器用作全局数据(Global Data, gd)的指针,上面board_init_f_alloc_reserve的返回值就是需要设置的gd的指针地址*/
	bl	board_init_f_init_reserve	/*跳转到C中的board_init_f_init_reserve, 初始化gd变量的内容为0,并确定后续分配的gd变量内容偏移基地址*/

	mov	x0, #0		/*x0清零,下一个bl命令传入参数值为0*/
	bl	board_init_f		/*跳转到C中的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.
 */
	ldr	x0, [x18, #GD_START_ADDR_SP]	/* x0 <- gd->start_addr_sp */
	bic	sp, x0, #0xf	/* 16-byte alignment for ABI compliance */
	ldr	x18, [x18, #GD_NEW_GD]		/* x18 <- gd->new_gd */

	adr	lr, relocation_return

	/* 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 */
	ldr	x0, [x18, #GD_RELOCADDR]	/* x0 <- gd->relocaddr */
	b	relocate_code

relocation_return:

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

/*
 * 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 */

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

ENDPROC(_main)
board_init_f_alloc_reserve

brandy/brandy-2.0/u-boot-2018/common/init/board_init.c

ulong board_init_f_alloc_reserve(ulong top)
{
   
   
	...
	/* LAST : reserve GD (rounded up to a multiple of 16 bytes) */
 	// 从global区域分配一块大小为struct global_data大小的16字节对齐的内存存放全局的global_data变量
    // top就是x0寄存器传入的值(具体值需要调试才知道)
	top = rounddown(top-sizeof(struct global_data), 16);

	return top;
}
board_init_f_init_reserve

brandy/brandy-2.0/u-boot-2018/common/init/board_init.c

void board_init_f_init_reserve(ulong base)
{
   
   
	struct global_data *gd_ptr;

	/*
	 * clear GD entirely and set it up.
	 * Use gd_ptr, as gd may not be properly set yet.
	 */

	gd_ptr = (struct global_data *)base;  // 拿到寄存器x18里存的gd变量内存地址
	/* zero the area */
	memset(gd_ptr, '\0', sizeof(*gd));  //将这块内存数据,初始化为0
	/* set GD unless architecture did it already */
	...
	/* next alloc will be higher by one GD plus 16-byte alignment */
	base += roundup(sizeof(struct global_data), 16);  //内存向上对齐16字节,这个地址就是gd变量后续分配内容的偏移基地址

	/*
	 * record early malloc arena start.
	 * Use gd as it is now properly set for all architectures.
	 */

	...
}
board_init_f

brandy/brandy-2.0/u-boot-2018/common/board_f.c

void board_init_f(ulong boot_flags)
{
   
   
	gd->flags = boot_flags; // 这里汇编传入的x0是0,所以boot_flags = 0
	gd->have_console = 0;

    //执行init_sequence_f数组中的每一个函数指针,会依次初始化cpu/dm/外设总线/串口/optee/等
	if (initcall_run_list(init_sequence_f))
		hang();
}

init_sequence_f数组中特别注意的是下面的函数,将接下来的链接重定位息息相关:

static const init_fnc_t init_sequence_f[] = {
   
   
	setup_mon_len, /*设置内存区域长度 gd->mon_len = __bss_end - __image_copy_start;*/
#ifdef CONFIG_OF_CONTROL
	fdtdec_setup, /*设置dtb的地址gd->fdt_blob*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

坂田民工

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值