一般ROM Code是固化在芯片内部的,BL1是有厂商提供的bin文件,并不会开放源代码,所以从BL2开始。
从系统启动打印的信息可以找到BL2的入口如下,关键是_start函数。
//log
Load uboot, ReadLba = 2000 //加载uboot (BL2)
Load OK, addr=0x200000, size=0x873d4 //uboot 地址和大小 mainload结束
...
INFO: Entry point address = 0x200000 //UBoot 入口地址
//u-boot 符号表
4019: 0000000000200000 0 NOTYPE GLOBAL DEFAULT 1 _start
arch/arm/cpu/armv8/start.S
20 .globl _start
21 _start:
22 nop
23 b reset //jump to reset
68 reset:
69
70 #ifdef CONFIG_ROCKCHIP
71 /*
72 * check loader tag
73 */
74 ldr x0, =__loader_tag
75 ldr w1, [x0]
76 ldr x0, =LoaderTagCheck
77 ldr w2, [x0]
78 cmp w1, w2
79 b.eq checkok
.......
87 * Could be EL3/EL2/EL1, Initial State:
88 * Little Endian, MMU Disabled, i/dCache Disabled
97 ldr x0, =COUNTER_FREQUENCY //hceng:晶振频率:24000000hz
.............
3.配置ARM核心特定勘误表(apply_core_errata)
112 /* Apply ARM core specific erratas */
113 bl apply_core_errata
..........
122 /* Processor specific initialization */
123 bl lowlevel_init ==> 187 WEAK(lowlevel_init)
..........
是否U-Boot开启多核CPU
125 #ifdef CONFIG_ARMV8_MULTIENTRY
bl _main //跳转到_main执行 crt0_64.S
------start.S說明-------------------------------------
CONFIG_ROCKCHIP 說明:
1. make menuconfig
Target select (Support Rockchip arch64 SOC) --->
(X) Support Rockchip arch64 SOC
rockchip platform select (rk33xx platform) --->
(X) rk33xx platform
2./arch/arm/cpu/armv8/rk33xx/Kconfig
如果ROCKCHIP_ARCH64选项选中了则在endif范围内的选项才会被选
if ROCKCHIP_ARCH64
config ROCKCHIP
bool //择可能:TRUE选中、FALSE不选 选中则编译,不选中则不编译。
如果后面没有字符串名称,则表示其不会出现在选择软件列表中
choice
prompt "rockchip platform select" 標題
config PLAT_RK33XX
bool "rk33xx platform" 選項 true/fale
select ROCKCHIP
endchoice
config SYS_CPU
default "armv8"
config SYS_SOC
default "rk33xx"
source "board/rockchip/rk33xx/Kconfig"
source "board/rockchip/common/Kconfig"
endif
~~~~~~~~~~~~~~~~~~
loader_tag 說明
302 #ifdef CONFIG_ROCKCHIP
.section .loader_tag, "ax" //ax是allocation execute的缩写,表示该节区可分配并且可执行
/* rockchip uboot loader tag */
arch/arm/lib/sections.c
char __loader_tag[0] __attribute__((section(".__loader_tag")));
~~~~~~~~~~~~~~~~
LoaderTagCheck 說明
39 .globl LoaderTagCheck
40 LoaderTagCheck:
41 .word 0x4B415351
~~~~~~~~
97 ldr x0, =COUNTER_FREQUENCY //hceng:晶振频率:24000000hz
//include/configs/rk33plat.h:
//#define COUNTER_FREQUENCY CONFIG_SYS_CLK_FREQ_CRYSTAL
//include/configs/rk_default_config.h:
//#define CONFIG_SYS_CLK_FREQ_CRYSTAL 24000000
====crt0_64.S===============================================
參考 uboot启动流程(5)之board_init_f 函数详解_蒋文韬的博客-CSDN博客_board_init_f
arch/arm/lib/crt0_64.S
ENTRY(_main)
1.设置栈
2.board_init_f
bl board_init_f /*调用board_init_f,硬件准备 设置初始化环境*/
调用initcall_run_list(init_sequence_f),init_sequence_f是个数组,里面是将要进行初始化的函数列表
3.重定位
b relocate_code
4.重新设置异常向量表
bl c_runtime_cpu_setup /* still call old routine */
5.清理BSS段
6.board_init_r
b board_init_r /*调用board_init_r,最终完成环境初始化*/
~~~~~~~~~~
crt0_64.S
59 ENTRY(_main)
60
61 /*
62 * Set up initial C runtime environment and call board_init_f(0).
63 */
64 ldr x0, =(CONFIG_SYS_INIT_SP_ADDR)
65 sub x0, x0, #GD_SIZE /* allocate one GD above SP */ 440
66 bic sp, x0, #0xf /* 16-byte alignment for ABI compliance */
67 mov x18, sp /* GD is above SP */
68 mov x0, #0
69 bl board_init_f
71 /*
72 * Set up intermediate environment (new sp and gd) and call
73 * relocate_code(addr_moni). Trick here is that we'll return
74 * 'here' but relocated.
75 */
76 ldr x0, [x18, #GD_START_ADDR_SP] /* x0 <- gd->start_addr_sp */ 152
77 bic sp, x0, #0xf /* 16-byte alignment for ABI compliance */
78 ldr x18, [x18, #GD_BD] /* x18 <- gd->bd */ 0
79 sub x18, x18, #GD_SIZE /* new GD is below bd */
81 #ifndef CONFIG_SKIP_RELOCATE_UBOOT
82 adr lr, relocation_return
83 ldr x9, [x18, #GD_RELOC_OFF] /* x9 <- gd->reloc_off */
84 add lr, lr, x9 /* new return address after relocation */
85 ldr x0, [x18, #GD_RELOCADDR] /* x0 <- gd->relocaddr */
86 b relocate_code
87 #endif
88
89 relocation_return:
90
91 /*
92 * Set up final (full) environment
93 */
94 bl c_runtime_cpu_setup /* still call old routine */
95
96 /*
97 * Clear BSS section
98 */
99 ldr x0, =__bss_start /* this is auto-relocated! */
100 ldr x1, =__bss_end /* this is auto-relocated! */
101 mov x2, #0
102 clear_loop:
103 str x2, [x0]
104 add x0, x0, #8
105 cmp x0, x1
106 b.lo clear_loop
107
108 /* call board_init_r(gd_t *id, ulong dest_addr) */
109 mov x0, x18 /* gd_t */
110 ldr x1, [x18, #GD_RELOCADDR] /* dest_addr */
111 b board_init_r /* PC relative jump */
112
113 /* NOTREACHED - board_init_r() does not return */
114
115 ENDPROC(_main)
-------crt0_64.S 說明----------------------------------------------------------------
64 ldr x0, =(CONFIG_SYS_INIT_SP_ADDR)說明:
CONFIG_SYS_INIT_SP_ADDR =0x08000000
在内部RAM 的末尾预留一些空间给global_data 结构体
rk_default_config.h:#define CONFIG_SYS_INIT_SP_ADDR CONFIG_RAM_PHY_END
rk33plat.h:#define CONFIG_RAM_PHY_END (CONFIG_RAM_PHY_START + CONFIG_RAM_PHY_SIZE)
rk33plat.h:#define CONFIG_RAM_PHY_START 0x00000000
rk33plat.h:#define CONFIG_RAM_PHY_SIZE SZ_128M
include/linux/sizes.h:#define SZ_128M 0x08000000
-------------------------
65 sub x0, x0, #GD_SIZE /* allocate one GD above SP */
include/generated/generic-asm-offsets.h:#define GD_SIZE 440 /* sizeof(struct global_data) // */
76 ldr x0, [x18, #GD_START_ADDR_SP] /* x0 <- gd->start_addr_sp */
include/generated/generic-asm-offsets.h:#define GD_START_ADDR_SP 152 /* offsetof(struct global_data, start_addr_sp) // */
include/generated/generic-asm-offsets.h:#define GD_BD 0 /* offsetof(struct global_data, bd) // */
===================================================
common/board_f.c
CSDN board_init_f() 解析聯結
void board_init_f(ulong boot_flags)
{ if (initcall_run_list(init_sequence_f))
hang();
}
static init_fnc_t init_sequence_f[] = {
#ifdef CONFIG_SANDBOX
setup_ram_buf,
#endif
setup_mon_len,
setup_fdt,
#ifdef CONFIG_TRACE
trace_early_init,
#endif
.........
..........
display_new_sp,
#ifdef CONFIG_SYS_EXTBDINFO
setup_board_extra,
#endif
INIT_FUNC_WATCHDOG_RESET
reloc_fdt,
setup_reloc,
#if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX)
jump_to_copy,
#endif
NULL,
};
common/board_r.c
void board_init_r(gd_t *new_gd, ulong dest_addr)
{
if (initcall_run_list(init_sequence_r))
hang();
-----------------
init_fnc_t init_sequence_r[] = {
initr_trace,
initr_reloc,
#ifdef CONFIG_BOARD_LATE_INIT
board_late_init, board/rockchip/rk33xx/rk33xx.c:int board_late_init(void)
#endif
run_main_loop,
};
board/rockchip/rk33xx/rk33xx.c:int board_late_init(void)
int board_late_init(void)
{
board_fbt_preboot(); board/rockchip/common/rkboot/fastboot.c:
}
void board_fbt_preboot(void) 这里检测了按键并且执行了启动流程
{
rk3288正常启动流程_groundhappy的博客-CSDN博客
RK3399 uboot启动_kernel_my的博客-程序员宅基地 - 程序员宅基地
fbt_fastboot_init
board_fbt_get_reboot_type //读取reboot flag
board_fbt_key_pressed //再次检查key有没有按下来决定进入哪种模式。
board_fbt_low_power_check //电量检查,过低就充电,如果失败就直接关机.
fdtdec_get_int //读取u-boot是否显示logo值
}
static int run_main_loop(void)
{
#ifdef CONFIG_SANDBOX
sandbox_main_loop_init();
#endif
/* main_loop() can return to retry autoboot, if so just run it again */
for (;;)
main_loop();
return 0;
}
~~~~~~~~~~~~~~
common/main.c
void main_loop(void)
{
run_preboot_environment_command();
s = bootdelay_process();
autoboot_command(s); //common/autoboot.c: 只有一条指令。那就是bootrk ???
cli_loop();
}
common/autoboot.c
const char *bootdelay_process(void)
s = getenv("bootcmd");
void autoboot_command(const char *s) s=bootcmd=bootrk
{ run_command_list(const char *cmd, int len, int flag) } common/cli.c
如果倒计时自然结束那么就执行函数
run_command_list,此函数会执行参数 s 指定的一系列命令,也就是环境变量 bootcmd 的命令,
bootcmd 里面保存着默认的启动命令,因此 linux 内核启动!
------------------------------------------------------------------------------------------------------------------
common/autoboot.c
/* bootrk [ <addr> | <partition> ] */
int do_bootrk(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
U_BOOT_CMD(
bootrk, 2, 1, do_bootrk,
"boot rockchip android bootimg",
#ifdef DEBUG
"[ <addr> | <partition> ]\n - boot application image\n"
"\t'addr' should be the address of the boot image which is\n"
"\tzImage+ramdisk.img if in memory. 'partition' is the name\n"
"\tof the partition to boot from. The default is to boot\n"
"\tfrom the 'boot' partition.\n"
#else
"\n"
#endif
);
rk3288正常启动流程_groundhappy的博客-CSDN博客