EL0 -- app
EL1 -- Linux kernel 、lk
EL2 -- hypervisor(虚拟化)
EL3 -- ARM trust firmware 、pre-loader
1.设备上电起来后,跳转到BootROM(不是flash)中的bootcode中执行把preloader加载起到ISRAM, 因为当前DRAM(RAM分SRAM跟DRAM,简单来说SRAM就是cache,DRAM就是普通内存)还没有准备好,所以要先把pre-loaderload到芯片内部的ISRAM(Internal SRAM)中。
2.preloder的主要工作是初始化环境,包括c环境,timer,gpio,pmic,uart,i2c等以及装载LK镜像至DRAM中,建立起最基本的运行环境,最重要的就是初始化DRAM。
3.如果实现了ATF,preloader加载完lk分区后,还会加载tee分区,在设置好环境后,会先跳转到EL3。
4.EL3回到lk,执行lk流程,preloader流程结束。
5.若平台未实现EL3(atf),pre-loader直接加载lk:
6.若平台实现EL3,则需要先加载完ATF再由ATF去加载lk:
preloader除了具有启动功能之外,还具有下载功能。首先还是需要明确的是mtk芯片都的有个boot rom,如果没有这个rom那么,那么程序是无法被下载到nandflash中的,然后此时的flash上是为空的,没有任何数据的。系统在上电之后它会检测是启动模式还是下载模式,如果是下载模式,它会初始化一个usb的串口,将preloader加载到内部的SRAM中,跳转到preloader中去执行,初始化好flash和外部RAM之后,依次将preloader、lk、kernel、android下载到nand flash中去。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s9XNs9u4-1584339412240)(/pax/image/1.jpg)]
vendor\mediatek\proprietary\bootable\bootloader\preloader\platform\mt6765\link_descriptor.ld
:OUTPUT_ARCH(arm)
ENTRY(_start)
vendor\mediatek\proprietary\bootable\bootloader\preloader\platform\mt6765\src\init\init.S
:init.S定义了_start,并跳转到main执.globl _start
_start:
b resethandler
/*
* 设置svc32模式
* 禁止中断fiq&irq
* clear BSS
* setup stack
* 跳转main执行
*/
......
entry :
LDR r0, =bldr_args_addr
B main
vendor\mediatek\proprietary\bootable\bootloader\preloader\platform\mt6765\src\core\main.c
:
void main(u32 *arg)
{
struct bldr_command_handler handler;
u32 jump_addr, jump_arg;
/* get the bldr argument */
p_bldr_param = &bldr_param;
memcpy((void *)p_bldr_param, (void *)*arg, sizeof(bl_param_t));
mtk_uart_init(UART_SRC_CLK_FRQ, CFG_LOG_BAUDRATE);
bldr_pre_process(); //必要的硬件初始化
bldr_handshake(&handler); //usb/uart握手,没深入看
#if !CFG_FPGA_PLATFORM //CFG_FPGA_PLATFORM :=0 进行一些安全检查
/* security check */
device_APC_dom_setup();
#endif
#if CFG_ATF_SUPPORT
trustzone_pre_init(); //trustzone初始化
BOOTING_TIME_PROFILING_LOG("trustzone pre init");
#endif
#if (defined(MTK_AB_OTA_UPDATER) && !CFG_DRAM_CALIB_OPTIMIZATION)
//在启用CFG_DRAM_CALIB_OPTIMIZATION时,在这里调用ab_ota_boot_check来尽可能早地检测ota引导状态
ab_ota_boot_check();
#endif
#if !(CFG_BYPASS_LOAD_IMG_FORCE_ATF) //条件为真
/* Do not load ATF, lk, load by JTAG */
if (0 != bldr_load_images(&jump_addr)) { //jump_addr = 0 应该会失败
pal_log_err("%s Second Bootloader Load Failed\n", MOD);
#if !CFG_BYPASS_EMI
goto error;
#endif
}
#else
jump_addr = CFG_UBOOT_MEMADDR; //跳转到uboot地址
#endif
BOOTING_TIME_PROFILING_LOG("load images");
bldr_post_process(); //检测电池是否插上,并且初始化bootarg
#ifdef SLT
mt_usb_phy_recover(); //USB PHY的recover配置
#endif
#if CFG_ATF_SUPPORT //条件为真
trustzone_post_init(); //trustzone初始化2,初始化atf_boot_arg /*初始化所有的安全相关环境。*/
#endif
#if CFG_BOOT_ARGUMENT_BY_ATAG //条件为真
jump_arg = (u32)&(g_dram_buf->boottag);
#else
jump_arg = (u32)&bootarg;
#endif
/* 64S3,32S1,32S1 (MTK_ATF_BOOT_OPTION = 0)
* re-loader jump to LK directly and then LK jump to kernel directly */
/*设置向lk传递参数的地址*/
#if CFG_ATF_SUPPORT
/*支持ATF,跳转到EL3,然后再跳转到lk*/
pal_log_info("%s Others, jump to ATF\n", MOD);
bldr_jump64(jump_addr, jump_arg, sizeof(boot_arg_t));
#else
/*跳转到lk*/
bldr_jump(jump_addr, jump_arg, sizeof(boot_arg_t));
#endif
error:
platform_error_handler();
}
platform/mt6765/default.mak
:定义了很多宏,分析main函数时可在里面查询。CFG_BYPASS_EMI :=0
# DRAM Calibration Optimization:
# DRAM calib data will be stored to storage device to enhance DRAM init speed.
CFG_DRAM_CALIB_OPTIMIZATION :=1
# no load ATF/LK, and force booting to ATF
CFG_BYPASS_LOAD_IMG_FORCE_ATF :=0
CFG_USB_DOWNLOAD :=1
CFG_LOG_LEVEL :=3
# image loading options
###################################################################
#For Normal Boot
CFG_LOAD_UBOOT :=1
#For Dummy AP
CFG_LOAD_MD_ROM :=0
CFG_LOAD_MD_RAMDISK :=0
CFG_LOAD_MD_DSP :=0
CFG_LOAD_MD3_ROM :=0
#For SLT and Dummy AP
CFG_LOAD_AP_ROM :=0
CFG_BOOT_ARGUMENT_BY_ATAG := 1
#For CTP
CFG_LOAD_CONN_SYS :=0
#For SLT
CFG_LOAD_SLT_MD :=0
CFG_LOAD_SLT_SCP :=0
CFG_LOAD_SLT_MD32 :=0
CFG_LOAD_SLT_SSPM :=0
bldr_pre_process()
函数完成各种的平台硬件(timer,pmic,gpio,wdt,dram,i2c,usb,emmc,pll,rtc,uart…)初始化工作,接下来看详细流程。bldr_load_images()
函数主要完成工作是加载lk到DRAM中,用于后续preloader跳转。
bldr_post_process()
函数主要检测电池是否插上,并且初始化bootarg
CFG_UART_COMMON :=1
CFG_LOG_BAUDRATE :=921600
CFG_EVB_UART_CLOCK :=26000000
CFG_FPGA_UART_CLOCK :=12000000
CFG_META_BAUDRATE :=115200
CFG_UART_LOG :=UART1
CFG_UART_META :=UART1
打开调试时间戳,查看每个阶段的运行时间
在platform//makefile.mak中添加
C_OPTION += -DPL_PROFILING
platform/mt6765/default.mak
:
10 CFG_BOOT_DEV :=BOOTDEV_SDMMC
Android.mk
:
12 PRELOADER_UFS_HEADER_BLOCK := $(LOCAL_PATH)/platform/$(MTK_PLATFORM_DIR)/headerblock_for_ota_fastboot_ufs
13 PRELOADER_EMMC_HEADER_BLOCK := $(LOCAL_PATH)/platform/$(MTK_PLATFORM_DIR)/headerblock_for_ota_fastboot_emmc
15 ifeq ("$(CFG_BOiOT_DEV)", "BOOTDEV_UFS")
16 PRELOADER_HEADER_BLOCK := $(LOCAL_PATH)/platform/$(MTK_PLATFORM_DIR)/headerblock_for_ota_fastboot_ufs
17 else
18 ifeq ("$(CFG_BOOT_DEV)", "BOOTDEV_SDMMC")
19 PRELOADER_HEADER_BLOCK := $(LOCAL_PATH)/platform/$(MTK_PLATFORM_DIR)/headerblock_for_ota_fastboot_emmc
20 endif
21 endif
build_preloader.mk
:
17 INSTALLED_PRELOADER_TARGET := $(PRODUCT_OUT)/preloader_$(PRELOADER_TARGET_PRODUCT).bin
18 BUILT_PRELOADER_TARGET := $(PRELOADER_OUT)/bin/preloader_$(PRELOADER_TARGET_PRODUCT).bin
20 TARGET_PRELOADER := $(PRODUCT_OUT)/preloader.img
-------------------------preloader_k62v1_64_bsp.img start----------------------------------
49 ifneq ($(INSTALLED_PRELOADER_TARGET),$(BUILT_PRELOADER_TARGET))
50 $(INSTALLED_PRELOADER_TARGET): $(BUILT_PRELOADER_TARGET) | $(ACP)
51 $(copy-file-to-target)
52 endif
-------------------------preloader_k62v1_64_bsp.bin end----------------------------------
-------------------------preloader.bin start----------------------------------
54 $(PRELOADER_BIN): $(INSTALLED_PRELOADER_TARGET)
55 $(hide) mkdir -p $(dir $@)
56 $(hide) cp -f $< $@
-------------------------preloader.bin end----------------------------------
-------------------------preloader.img start----------------------------------
58 $(TARGET_PRELOADER): PRIVATE_INSTALLED_PRELOADER_TARGET := $(INSTALLED_PRELOADER_TARGET)
59 $(TARGET_PRELOADER): $(INSTALLED_PRELOADER_TARGET) $(PRELOADER_DIR)/tools/gen-preloader-img.py
60 ifneq ("$(wildcard $(PRELOADER_HEADER_BLOCK))","")
61 cat $(PRELOADER_HEADER_BLOCK) $(PRIVATE_INSTALLED_PRELOADER_TARGET) > $@
62 else
63 $(hide) $(PRELOADER_DIR)/tools/gen-preloader-img.py $< $@
64 endif
-------------------------preloader.img end----------------------------------
-------------------------preloader_ufs.img start----------------------------------
66 ifeq (,$(PL_MODE))
67 ifneq ($(wildcard $(PRELOADER_UFS_HEADER_BLOCK)),)
68 preloader pl: $(PRODUCT_OUT)/preloader_ufs.img
69 $(PRODUCT_OUT)/preloader_ufs.img: $(PRELOADER_UFS_HEADER_BLOCK) $(INSTALLED_PRELOADER_TARGET)
70 $(hide) mkdir -p $(dir $@)
71 $(hide) cat $^ > $@
72
73 endif
-------------------------preloader_emmc.img start----------------------------------
74 ifneq ($(wildcard $(PRELOADER_EMMC_HEADER_BLOCK)),)
75 preloader pl: $(PRODUCT_OUT)/preloader_emmc.img
76 $(PRODUCT_OUT)/preloader_emmc.img: $(PRELOADER_EMMC_HEADER_BLOCK) $(INSTALLED_PRELOADER_TARGET)
77 $(hide) mkdir -p $(dir $@)
78 $(hide) cat $^ > $@
79
80 endif
81 endif
-------------------------preloader_ufs.img preloader_emmc.img end----------------------------------
从以上代码可得知:
镜像 | 说明 |
---|---|
preloader_k62v1_64_bsp.bin | 适配平台的烧录文件,直接从BUILT_PRELOADER_TARGET中拷贝而来 |
preloader.bin | 等同于preloader_k62v1_64_bsp.bin |
preloader.img | 根据在platform/mt6765/default.mak 中的配置,目前是在preloader_k62v1_64_bsp.bin基础上增加emmc启动帧头,用于ota升级,等同于preloader_emmc.img |
preloader_ufs.img | 在preloader_k62v1_64_bsp.bin基础上增加ufs启动帧头,用于启动介质为ufs时的ota升级 |
preloader_emmc.img | 在preloader_k62v1_64_bsp.bin基础上增加emmc启动帧头,用于启动介质为emmc时的ota升级 |