- Boot Flow Overview
- BootROM Introduce
- BL2 stage
- TEE+ATF
- BL33 stage
- MT2712 Image Format
Boot Flow Overview
ARM64处理器上电以后,首先执行地址0x0000_0000的bootroom代码,bootrom将引导程序加载到内部SRAM执行。MTK平台使用little kernel (lk)作为引导程序,lk分为两个阶段运行,分别为bl2阶段和bl33阶段,其中bl2运行在内部SRAM(L2_cache 256K),bl2阶段完成DRAM和eMMC的初始化,然后将ATF和BL33加载到DRAM,接下来就跳转到对应的地址运行ATF或者BL33,在BL33的中将跳转到linux kernel的地址,释放CPU的控制权并运行linux kernel。

BootROM Introduce
- BootROM Flow
-

- BootROM Features
BootROM的主要任务是初始化配置CPU0从0地址运行,初始化L2_cache为bl2的运行搭好环境,BootROM中会根据硬件pin脚的配置来选择启动的设备,并且BootROM软件支持三种模式:
支持3种模式:normal boot、USB download、UART download
支持5种设备:eMMC boot 分区,eMMC user分区,SLC NAND,SPI NOR, SD 卡
通过配置I2SO1_DATA0、I2SO1_BCK来选择boot device,目前项目使用eMMC Boot Mode:

BL2 stage
MTK平台用LK作为bootloader,BL2是bootloader的第一阶段, BL33是bootloader的第二阶段。之所以将LK分为两个阶段因为BOOT ROM启动后,DRAM尚未初始化,ROM Code只将SOC的L2_Cache做了初始化,MTK将L2_Cache分出256K作为SRAM,而LK编译出来的完整镜像超过256K,所以BL2作为第一阶段bootloader运行在SRAM中,BL33作为第二阶段bootloader运行在DRAM中。
BL2最主要的功能是完成eMMC初始化、DRAM初始化、DRAM校校验、加载ATF和BL33。从lk/top/main.c中的lk_main()函数是BL2阶段的开始,遵循的初始化顺序:CPU 架构 -> 目标平台 -> 目标设备。
lk_main@main.c
arch_early_init();
...
platform_early_init();
...
target_early_init();
...
heap_init();
...
call_constructors();
...
kernel_init();
...
thread_create("bootstrap2", &bootstrap2, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE);

lk_main()函数最后会创建bootstrap2线程继续完成初始化任务,bootstrap2最后会调用到lk/app/app.c中的apps_init函数来完成应用功能初始化,apps_init() 遍历所有在__apps_start 到__apps_end段里的函数,并调用lk中所谓的app的init函数,然后调用start_app(app)来启动app。start_app()函数中调用thread_create来创建一个APP线程。
apps_init@lk/app/app.c
/* one time setup */
void apps_init(void)
{
const struct app_descriptor *app;
/* call all the init routines */
for (app = __apps_start; app != __apps_end; app++) {
if (app->init)
app->init(app);
}
/* start any that want to start on boot */
for (app = __apps_start; app != __apps_end; app++) {
if (app->entry && (app->flags & APP_FLAG_DONT_START_ON_BOOT) == 0) {
start_app(app);
}
}
}

static void start_app(const struct app_descriptor *app)
{
uint32_t stack_size = (app->flags & APP_FLAG_CUSTOM_STACK_SIZE) ? app->stack_size : DEFAULT_STACK_SIZE;
printf("starting app %s\n", app->name);
thread_t *t = thread_create(app->name, &app_thread_entry, (void *)app, DEFAULT_PRIORITY, stack_size);
thread_detach(t);
thread_resume(t);
}
哪些app被放入 boot thread section, 则定义在 include/app.h 中的 APP_START(appname)。
比如apps_init()通过下面方式进入blxboot_task()函数:
APP_START(blxboot)
.entry = blxboot_task,
.flags = 0,
APP_END
blxboot_task函数中完成blxobj的创建,然后通过get_boot_mode函数来判断是download流程、normal boot流程还是recovery流程。get_suffix函数获取ab镜像后缀,启动image_a或者image_b(这里的image在BL2 和BL33阶段不一样)。get_overlay_image将会获取dtbo,dtbo会覆盖掉dtb中某些域,最终系统使用的dtb-in-use=dtb+dtbo。最后blxboot_task将会调用arch_chain_load来跳转到要执行的image。
BL2阶段将会加载TEE和BL33镜像:

TEE+ATF
arm-trusted-firmware 主要负责Non-Secure和Secure的切换,atf的初始化在vendor/mediatek/proprietary/trustzone/atf/v1.6/mt2xxxbl31/aarch64/bl31_entrypoint.S,保存BL2传递过来的参数,比较重要的是LK的入口地址保存到了BL33_START_ADDRESS中;设置异常限量表的基地址到VBAR中;早期平台初始化,这里面完成了Non-secure world与Secure world上下文的初始化;进入ATF的main函数中进行环境和服务的初始化;el3_exit退出ATF进入LK.
简单了解atf的作用即可,atf的详细流程暂时不介绍。
BL33 stage
BL33是MTK平台的第二阶段bootloader,和BL2共用同一套的代码,根据mk和config文件还有一些宏来做区分,BL33第一句log和BL2一样都是:Watchdog Status: 0 , boot from normal。
BL33和BL2的区别主要体现在运行的位置不一样,BL33运行在DRAM中,BL2运行在SOC内部的SRAM。在platform_early_init()函数会根据当前BLx选择不同的函数platform_early_init_blx()
另外需要注意的是在BL33阶段加载的image包括:boot、dtbo、vpd、vbmeta,这一点和BL2 stage不一样。BL33运行结束就会跳到地址0x4008_0000运行Linux Kernel,至此lk运行结束。


BL33阶段将会加载boot、dtbo、vpd、vbmeta镜像:


479

被折叠的 条评论
为什么被折叠?



