【SemiDrive源码分析】【X9芯片启动流程】29 - AP1 Android Bootloader启动流程分析(加载并跳转kernel)
本 SemiDrive源码分析 之 Yocto源码分析 系列文章汇总如下:
- 《【SemiDrive源码分析】【Yocto源码分析】01 - yocto/base目录源码分析(编译环境初始化流程)》
- 《【SemiDrive源码分析】【Yocto源码分析】02 - yocto/meta-openembedded目录源码分析》
- 《【SemiDrive源码分析】【Yocto源码分析】03 - yocto/meta-semidrive目录及Yocto Kernel编译过程分析(上)》
- 《【SemiDrive源码分析】【Yocto源码分析】04 - yocto/meta-semidrive目录及Yocto Kernel编译过程分析(下)》
- 《【SemiDrive源码分析】【Yocto源码分析】05 - 找一找Yocto Kernel编译过程中所有Task的源码在哪定义的呢?》
- 《【SemiDrive源码分析】【Yocto源码分析】06 - Kernel编译生成的Image.bin、Image_nobt.dtb、modules.tgz 这三个文件分别是如何生成的?》
- 《【SemiDrive源码分析】【Yocto源码分析】07 - core-image-base-x9h_ref_serdes.rootfs.ext4 文件系统是如何生成的》
- 《【SemiDrive源码分析】【X9芯片启动流程】08 - X9平台 lk 目录源码分析 之 目录介绍》
- 《【SemiDrive源码分析】【X9芯片启动流程】09 - X9平台系统启动流程分析》
- 《【SemiDrive源码分析】【X9芯片启动流程】10 - BareMetal_Suite目录R5 DIL.bin 引导程序源代码分析》
- 《【SemiDrive源码分析】【X9芯片启动流程】11 - freertos_safetyos目录Cortex-R5 DIL2.bin 引导程序源代码分析》
- 《【SemiDrive源码分析】【X9芯片启动流程】12 - freertos_safetyos目录Cortex-R5 DIL2.bin 之 sdm_display_init 显示初始化源码分析》
- 《【SemiDrive源码分析】【X9芯片驱动调试】13 - GPIO 配置方法》
- 《【SemiDrive源码分析】【X9芯片启动流程】14 - freertos_safetyos目录Cortex-R5 SafetyOS/RTOS工作流程分析》
- 《【SemiDrive源码分析】【X9芯片启动流程】15 - freertos_safetyos目录 R5 SafetyOS 之 tcpip_init() 代码流程分析》
- 《【SemiDrive源码分析】【X9 Audio音频模块分析】16 - 音频模块框图及硬件原理图分析》
- 《【SemiDrive源码分析】【X9芯片启动流程】17 - R5 SafetyOS 之 LK_INIT_LEVEL_PLATFORM 阶段代码流程分析(上)dcf_init 核间通信初始化》
- 《【SemiDrive源码分析】【X9芯片启动流程】18 - R5 SafetyOS 之 LK_INIT_LEVEL_PLATFORM 阶段代码流程(下)启动QNX、Android》
- 《【SemiDrive源码分析】【X9芯片启动流程】19 - MailBox 核间通信机制介绍(理论篇)》
- 《【SemiDrive源码分析】【X9芯片启动流程】20 - MailBox 核间通信机制介绍(代码分析篇)之 MailBox for RTOS 篇》
- 《【SemiDrive源码分析】【X9芯片启动流程】21 - MailBox 核间通信机制介绍(代码分析篇)之 Mailbox for Linux 篇》
- 《【SemiDrive源码分析】【X9芯片启动流程】22 - MailBox 核间通信机制介绍(代码分析篇)之 RPMSG-VIRTIO Kernel 篇》
- 《【SemiDrive源码分析】【X9芯片启动流程】23 - MailBox 核间通信机制介绍(代码分析篇)之 RPMSG-IPCC Kernel 篇》
- 《【SemiDrive源码分析】【X9芯片启动流程】24 - MailBox 核间通信机制相关寄存器介绍》
- 《【SemiDrive源码分析】【X9芯片启动流程】25 - MailBox 核间通信机制介绍(代码分析篇)之 RPMSG-IPCC RTOS & QNX篇》
- 《【SemiDrive源码分析】【X9芯片启动流程】26 - R5 SafetyOS 之 LK_INIT_LEVEL_TARGET 阶段代码流程分析(TP Drvier、Audio Server初始化)》
- 《【SemiDrive源码分析】【X9芯片启动流程】27 - AP1 Android Preloader启动流程分析(加载atf、tos、bootloader镜像后进入BL31环境)》
- 《【SemiDrive源码分析】【X9芯片启动流程】28 - AP1 Android SMC 指令进入 EL3 环境执行 ATF 镜像(加载并跳转 bootloader)》
- 《【SemiDrive源码分析】【X9芯片启动流程】29 - AP1 Android Bootloader启动流程分析(加载并跳转kernel)》
. - 《【SemiDrive源码分析】【X9芯片启动流程】28 - MailBox 核间通信机制介绍(代码分析篇)之 Property篇》
- 《【SemiDrive源码分析】【X9芯片启动流程】29 - MailBox 核间通信机制介绍(代码分析篇)之 RPCall篇》
- 《【SemiDrive源码分析】【X9芯片启动流程】30 - MailBox 核间通信机制介绍(代码分析篇)之 Notify篇》
- 《【SemiDrive源码分析】【X9芯片启动流程】31 - MailBox 核间通信机制介绍(代码分析篇)之 Socket篇》
- 《【SemiDrive源码分析】【X9芯片启动流程】32 - MailBox 核间通信机制介绍(代码分析篇)之 /dev/vircan篇》
我们前面看到:
AP1 preloader 在触发 AP2 watchdog 后,接着从 eMMC 中加载 ATF ,TOS ,bootloader , 然后 进入 ATF ,由 ATF 切换到 non-secure world 运行 bootloader , bootloader 从 eMMC 中加载 kernel , dtb 等镜像并运行。
本文我们来看下 bootloader 的启动流程。
由于RTOS 的存在,传统高通 Android 中很多SBL 、preloader 、bootloader 的代码均被放入 rtos 中执行了, 所以 preloder 、bootloader 中基本没啥功能, 最大的作用还是 preloader 加载 ATF ,ATF 加载bootloader ,bootloader 加载 kernel , 所以代码流程估计也没啥好写的,我们来看看吧。
一、Android Bootloader
1.1 汇编入口 start.S:跳转 lk_main() 函数
从 system-onesegment-sd.ld 可以看出,bootloader 使用的代码和 preloader 是一样的,都是 start.s ,然后bl lk_main() 这种启动汇编代码,前面我分析的太多了,就不细写了,没啥意义,有兴趣的兄弟自行分析。
# buildsystem\rtos\lk_boot\build-ivi_bootloader_x9_plus_ref_serdes\system-onesegment-sd.ld
OUTPUT_FORMAT("elf64-littleaarch64", "elf64-bigaarch64", "elf64-littleaarch64")
OUTPUT_ARCH(aarch64)
ENTRY(_start)
SECTIONS
{
. = 0xffff000000000000 + 0;
. = 0xffff000000000000 + 0x59800000;
# buildsystem\rtos\lk\arch\arm64\start.S
FUNCTION(_start)
...... 省略.......
bl lk_main
b .
1.2 lk_main() 函数:创建并运行 bootstrap2 线程
整套代码跟 preloader 走的一模一样,没啥好分析,详细看注释。
# buildsystem\rtos\lk\top\main.c
void lk_main(ulong arg0, ulong arg1, ulong arg2, ulong arg3)
{
lk_boot_args[0] = arg0;
lk_boot_args[1] = arg1;
lk_boot_args[2] = arg2;
lk_boot_args[3] = arg3;
thread_init_early();
lk_primary_cpu_init_level(LK_INIT_LEVEL_EARLIEST, LK_INIT_LEVEL_ARCH_EARLY - 1);
arch_early_init();
lk_primary_cpu_init_level(LK_INIT_LEVEL_ARCH_EARLY, LK_INIT_LEVEL_PLATFORM_EARLY - 1);
platform_early_init();
lk_primary_cpu_init_level(LK_INIT_LEVEL_PLATFORM_EARLY, LK_INIT_LEVEL_TARGET_EARLY - 1);
target_early_init();
dprintf(INFO, "\nwelcome to lk/MP\n\n");
dprintf(INFO, "boot args 0x%lx 0x%lx 0x%lx 0x%lx\n", lk_boot_args[0], lk_boot_args[1], lk_boot_args[2], lk_boot_args[3]);
lk_primary_cpu_init_level(LK_INIT_LEVEL_TARGET_EARLY, LK_INIT_LEVEL_HEAP - 1);
dprintf(SPEW, "initializing heap\n");
heap_init();
dprintf(SPEW, "calling constructors\n");
call_constructors();
lk_primary_cpu_init_level(LK_INIT_LEVEL_HEAP, LK_INIT_LEVEL_KERNEL - 1);
kernel_init();
lk_primary_cpu_init_level(LK_INIT_LEVEL_KERNEL, LK_INIT_LEVEL_THREADING - 1);
dprintf(SPEW, "creating bootstrap completion thread\n");
thread_t *t = thread_create("bootstrap2", &bootstrap2, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE);
thread_set_pinned_cpu(t, 0);
thread_detach(t);
thread_resume(t);
thread_become_idle();
}
1.3 .lk_init段代码任务分析
下面是 bootloader 阶段的 TASK 任务,我看了下,没啥重要的函数,没啥好分析,直接跳过。
# buildsystem\rtos\lk_boot\build-ivi_bootloader_x9_plus_ref_serdes\lk.elf.map
.lk_init 0xffff000059851a40 0xd8 load address 0x0000000059851a40
0xffff000059851a40 __lk_init = .
*(.lk_init)
.lk_init 0xffff000059851a40 0x18 lk_boot/build-ivi_bootloader_x9_plus_ref_serdes/lk_boot/platform/kunlun/ap1.mod.o
0xffff000059851a40 _init_struct_demo
.lk_init 0xffff000059851a58 0x48 lk_boot/build-ivi_bootloader_x9_plus_ref_serdes/lk_boot/chipdev/interrupt/arm_gic.mod.o
0xffff000059851a58 _init_struct_arm_gic_resume_cpu
0xffff000059851a70 _init_struct_arm_gic_suspend_cpu
0xffff000059851a88 _init_struct_arm_gic_init_percpu
.lk_init 0xffff000059851aa0 0x18 lk_boot/build-ivi_bootloader_x9_plus_ref_serdes/lk_boot/hal/crypto_hal/.mod.o
0xffff000059851aa0 _init_struct_cryto_init
.lk_init 0xffff000059851ab8 0x18 lk_boot/build-ivi_bootloader_x9_plus_ref_serdes/lk/lib/version.mod.o
0xffff000059851ab8 _init_struct_version
.lk_init 0xffff000059851ad0 0x18 lk_boot/build-ivi_bootloader_x9_plus_ref_serdes/lk_boot/platform/kunlun/common.mod.o
0xffff000059851ad0 _init_struct_nocache
.lk_init 0xffff000059851ae8 0x30 lk_boot/build-ivi_bootloader_x9_plus_ref_serdes/lk/kernel/vm.mod.o
0xffff000059851ae8 _init_struct_vm
0xffff000059851b00 _init_struct_vm_preheap
0xffff000059851b18 __lk_init_end = .
1.4 .app段代码任务分析
# buildsystem\rtos\lk_boot\build-ivi_bootloader_x9_plus_ref_serdes\lk.elf.map
.apps 0xffff0000598519f0 0x50 load address 0x00000000598519f0
0xffff0000598519f0 __apps_start = .
*(.apps)
.apps 0xffff0000598519f0 0x28 lk_boot/build-ivi_bootloader_x9_plus_ref_serdes/lk/app/shell.mod.o
0xffff0000598519f0 _app_shell
.apps 0xffff000059851a18 0x28 lk_boot/build-ivi_bootloader_x9_plus_ref_serdes/lk_boot/application/system/bootloader.mod.o
0xffff000059851a18 _app_bootloader
0xffff000059851a40 __apps_end = .
从 .app 段可以看出,主要是 shell 和 bootloadr 两个app,我们先来看下 shell 支持哪些命令
1.4.1 _app_shell 命令
commands 段中,惟一一个有作用的就是 _cmd_block_bootloader ,其他的基本没啥意义,不分析。
# buildsystem\rtos\lk_boot\build-ivi_bootloader_x9_plus_ref_serdes\lk.elf.map
.commands 0xffff0000598535f8 0x120 load address 0x00000000598535f8
0xffff0000598535f8 __commands_start = .
*(.commands)
.commands 0xffff0000598535f8 0x18 lk_boot/build-ivi_bootloader_x9_plus_ref_serdes/lk_boot/application/system/bootloader.mod.o
0xffff0000598535f8 _cmd_block_bootloader
.commands 0xffff000059853610 0x18 lk_boot/build-ivi_bootloader_x9_plus_ref_serdes/lk_boot/chipdev/fuse_ctrl.mod.o
0xffff000059853610 _cmd_block_fuse
.commands 0xffff000059853628 0x18 lk_boot/build-ivi_bootloader_x9_plus_ref_serdes/lk/kernel.mod.o
0xffff000059853628 _cmd_block_kernel
.commands 0xffff000059853640 0x18 lk_boot/build-ivi_bootloader_x9_plus_ref_serdes/lk/lib/version.mod.o
0xffff000059853640 _cmd_block_version
.commands 0xffff000059853658 0x18 lk_boot/build-ivi_bootloader_x9_plus_ref_serdes/lk/platform.mod.o
0xffff000059853658 _cmd_block_platform_power
.commands 0xffff000059853670 0x48 lk_boot/build-ivi_bootloader_x9_plus_ref_serdes/lk/kernel/vm.mod.o
0xffff000059853670 _cmd_block_pmm
0xffff000059853688 _cmd_block_vm
0xffff0000598536a0 _cmd_block_vmm
.commands 0xffff0000598536b8 0x18 lk_boot/build-ivi_bootloader_x9_plus_ref_serdes/lk/lib/console.mod.o
0xffff0000598536b8 _cmd_block_help
.commands 0xffff0000598536d0 0x18 lk_boot/build-ivi_bootloader_x9_plus_ref_serdes/lk_boot/lib/dloader.mod.o
0xffff0000598536d0 _cmd_block_dloader
.commands 0xffff0000598536e8 0x18 lk_boot/build-ivi_bootloader_x9_plus_ref_serdes/lk/external/lib/cksum.mod.o
0xffff0000598536e8 _cmd_block_crc
.commands 0xffff000059853700 0x18 lk_boot/build-ivi_bootloader_x9_plus_ref_serdes/lk_boot/lib/sdunittest.mod.o
0xffff000059853700 _cmd_block_unittest
0xffff000059853718 __commands_end = .
1.4.2 _app_bootloader 代码分析: 根据镜像头信息,解析是否跳转qnx\android\linux,此处我们正式加载 kernel镜像跳转android
可以看出,在 bootloader app 中,主要同样了实现了 fastboot 命令:
# buildsystem\rtos\lk_boot\application\system\bootloader\bootloader.c
static void bootloader_entry(const struct app_descriptor *app, void *args){
_bootloader_main();
}
STATIC_COMMAND("bootloader", "bootloader",(console_cmd)&bootloader_main)
STATIC_COMMAND("fastboot", "fastboot", (console_cmd)&fastboot)
STATIC_COMMAND_END(bootloader);
APP_START(bootloader)
.flags = 0,
.entry = bootloader_entry,
APP_END
我们进入 _bootloader_main 函数中看一下,主要工作如下:
- 根据
boot pin 来配置启动的设备,如emmc1 、ospi1 等 - 如果支持
USB 或 SdCard 启动,如果检测到 /updata/sdrv_update.img 文件,则进入recovery 升级模式 - 初始化启动设备,如
emmc 的 mmcblk0 ,根据 btdev_cfg->cfg 中的信息,配置相关的电压、clk 、位宽等信息 - 读取启动设备分区信息
- 如果
boot reason 是 HALT_REASON_SW_UPDATE ,则进入 fastboot 模式 - 申请
block_size 倍数的内存,解析镜像头信息,如果是QNX 镜像内则直接 jump_to_kernel(startup_hadr) 进入qnx kernel - 申请
IO 内存空间 fdt ,加载 DTB 分区内存,保存在fdt 中 - 如果
dtb 分区,不是 flattened device tree ,就直接启动进入android - 如果
dtb 分区,不是 xen compatible ,就直接启动进入android xen 是虚拟机 Hypervisor 的方式,我们不用这个,先忽略掉- 正式进入启动
android 的代码 - 通过调用
smc(SMC_DIS_HCE) 的方式,来禁止 HVC CAALL - 申请
block_size 的内存空间,加载并解析 bootimage 镜像 - 解析
dtb 设备树,,如果没有设备树分区,说明进入纯 linux 镜像 - 检查头信息,主要是检查
sub dtb 如果不是 flattened device tree ,说明进入纯 linux 镜像 - 解析
dtbo 信息保存在 dtbo_info , 将 dtbo 加入verified_image_list - 通过
verified_images_list 解析部分 cmdline 信息 - 拷贝
cmdline 到 cmdline_board 中 - 将
cmdline 写入对应的内存中 - 配置
kernel 物理地址 entry_p ,以及dtb 物理地址 dtb_p - 禁止中断,正式通过
arm_chain_load 来加载 kernel 地址 entry_p 及 dtb 地址 dtb_p
# buildsystem\rtos\lk_boot\application\system\bootloader\bootloader.c
int _bootloader_main(void)
{
int ret = 0, root_type;
boot_img_hdr *hdr;
unsigned char *cmdline_board;
char *storage_type;
dtbo_img_info dtbo_info;
partition_device_t *ptdev;
storage_device_t *storage_dev = NULL;
boot_device_cfg_t *btdev_cfg = NULL;
unsigned ramdisk_addr, ramdisk_size;
uint64_t memory_start[MEMORY_BANKS_MAX] = {0};
uint64_t memory_size[MEMORY_BANKS_MAX] = {0};
void *rootfs_buf = NULL;
void *fdt, *dom0_buf, *dtb_buf, *xen_buf, *kernel;
unsigned long dtb_p;
struct list_node verified_images_list;
struct startup_header *startup_hdr = NULL;
uint64_t ret_smc;
void *entry_p;
uint64_t ddr_size = get_ddr_size();
uint32_t pin = boot_get_pin();
if (BOOT_PIN_0 == pin) {
uint32_t pin_ap = boot_get_pin_scr_overwrite();
pin = pin_ap;
}
btdev_pin_cfg_t *btdev_pin = find_btdev(pin);
=========> return &btdev_pin_mapping[pin];
KEY_NODE_INFO("bootloader start!\n");
#if SUPPORT_USB_BOOT || SUPPORT_SDCARD_BOOT
static FATFS fs;
ret = recovery_file_detect(&fs);
if (0 == ret) {
dprintf(CRITICAL, "recovery file detect success.\n");
KEY_NODE_INFO("start recovery from u disk!\n");
return boot_recovery_file(&fs);
}
#endif
if (btdev_pin) {
btdev_cfg = btdev_pin->ap;
}
if (btdev_cfg) {
disk_name = btdev_cfg->disk_name;
storage_type = btdev_cfg->storage_type;
storage_dev = setup_storage_dev(btdev_cfg->device_type, btdev_cfg->res_idex, (void *)&btdev_cfg->cfg);
}
list_initialize(&verified_images_list);
ptdev = ptdev_setup(storage_dev, 0);
if (ptdev) {
ptdev_read_table(ptdev);
}
uint32_t block_size = storage_dev->get_block_size(storage_dev);
if (is_software_update()) {
storage_dev_destroy(storage_dev);
KEY_NODE_INFO("start fastboot mode!\n");
return fastboot(block_size);
}
boot_qnx:
startup_hdr = memalign(block_size, ROUNDUP(sizeof(struct startup_header), block_size));
bootloader_entry_qnx(ptdev, startup_hdr);
KEY_NODE_INFO("The next os is not qnx!\n");
fdt = (void *)_ioaddr(REE_MEMBASE + BOARD_TARS_OFFSET);
ret = partition_load(ptdev, dtb_part, fdt,BOARD_KERNEL_OFFSET - BOARD_TARS_OFFSET, NULL);
ret = fdt_check_header(fdt);
if (ret) {
dprintf(INFO, "not a flattened device tree.\n");
goto boot_android;
}
if (!check_xen_compatible(fdt)) {
dprintf(INFO, "no xen compatible found.\n");
goto boot_android;
}
boot_xen:
uint64_t dom0_img_sz = DOM0_MEMSIZE;
dom0_buf = (void *)_ioaddr(memory_start[0] + DOM0_KERNEL_OFFSET);
ret = partition_load(ptdev, dom0_kernel, dom0_buf, DOM0_MEMSIZE, &dom0_img_sz);
xen_buf = (void *)_ioaddr(memory_start[0] + XEN_IMG_OFFSET);
ret = partition_load(ptdev, xen_part, xen_buf, HYP_MEMSIZE, NULL);
fdt = relocate_fdt(fdt, (void *)_ioaddr(memory_start[0] + XEN_FDT_OFFSET));
if (root_type == 1)
update_root_dev(ptdev, cmdline_board, dom0_rootfs);
merge_fdt_bootargs(fdt, (const char *)cmdline_board);
merge_fdt_bootargs(fdt, vbmeta_cmdline);
merge_fdt_bootargs(fdt, get_verified_state());
merge_fdt_bootargs(fdt, get_serialno());
unsigned long fdt_p = _paddr(fdt);
unsigned long xen_p = _paddr(xen_buf);
KEY_NODE_INFO("start xen Hypervisor!\n");
hvc(xen_p, fdt_p, 0, 0, 0, 0, 0, 0);
return 0;
boot_android:
smc(SMC_DIS_HCE, 0, 0, 0, 0, 0, 0, 0);
hdr = memalign(block_size, ROUNDUP(sizeof(boot_img_hdr), block_size));
ret = parse_bootimage(hdr, ptdev);
ret = partition_load(ptdev, dtb_part, fdt, BOARD_KERNEL_OFFSET - BOARD_TARS_OFFSET, NULL);
if (ret) {
dprintf(INFO, "%s dtb load failed.\n", dtb_part);
free(hdr); goto boot_linux;
}
ret = fdt_check_header(fdt);
if (ret) {
dprintf(INFO, "sub dtb not a flattened device tree.\n");
free(hdr); goto boot_linux;
}
memset(&dtbo_info, 0x0, sizeof(dtbo_info));
if (load_dtbo_image(ptdev, &dtbo_info) &&
!add_verified_image_list(&verified_images_list, dtbo_info.base, dtbo_info.size, dtbo_info.pt_name)) {
goto error;
}
if (!add_verified_image_list(&verified_images_list, fdt, BOARD_KERNEL_OFFSET - BOARD_TARS_OFFSET, dtb_part)) {
goto error;
}
if (!get_cmdline_by_verified_image(ptdev, &verified_images_list)) {
goto error;
}
free_image_info_list(&verified_images_list);
if (dtbo_info.base)
dtbo_find_apply_match(fdt, dtbo_info.base, dtbo_find_hw_match);
ret = fdt_update_memory_range(fdt, HYP_MEMBASE, 0, ddr_size);
ret_smc = smc(SMCCC_ARCH_FEATURES, SMCCC_ARCH_FEATURES, 0, 0, 0, 0, 0, 0);
if (ret_smc != SMC_OK) {
update_dt_psci_method(fdt, "native");
}
dtb_buf = (void *)_ioaddr((paddr_t)(hdr->tags_addr));
if (dtb_buf != fdt) {
dprintf(CRITICAL, "tags addr do not meet memory layout.\n");
hdr->tags_addr = REE_MEMBASE + BOARD_TARS_OFFSET;
dtb_buf = fdt;
}
ramdisk_addr = hdr->ramdisk_addr;
ramdisk_size = hdr->ramdisk_size;
ret = update_fdt_initrd(dtb_buf, ramdisk_addr, ramdisk_size);
cmdline_board = calloc(1, COMMAND_LINE_PARTITION);
strcpy((char *)cmdline_board, (const char *)&hdr->cmdline);
dprintf(INFO, "board cmdline %s\n", cmdline_board);
int slot;
slot = ptdev_find_boot_slot(ptdev);
strcat((char *)cmdline_board, " androidboot.slot_suffix=");
if (slot != SLOT_A && slot != SLOT_B) {
dprintf(CRITICAL, "invalid slot, set default slot A, slot:%d\n", slot);
slot = SLOT_A;
}
strcat((char *)cmdline_board, suffix_slot[slot]);
#if SUPPORT_BOARDINFO
hwid = calloc(sizeof(char), 64);
property = calloc(sizeof(char), 96);
get_hwid_friendly_name(hwid, 64);
sprintf(property, " androidboot.hwid=%s ", hwid);
merge_fdt_bootargs(dtb_buf, property);
free(hwid);
free(property);
#endif
ret = generate_storage_cmdline(cmdline_board, storage_type);
merge_fdt_bootargs(dtb_buf, (const char *)cmdline_board);
merge_fdt_bootargs(dtb_buf, vbmeta_cmdline);
merge_fdt_bootargs(dtb_buf, get_verified_state());
merge_fdt_bootargs(dtb_buf, get_android_boot_mode(ptdev));
merge_fdt_bootargs(dtb_buf, get_serialno());
if (is_recovery())
merge_fdt_bootargs(dtb_buf, "recovery_mode");
entry_p = (void *)_ioaddr((paddr_t)(hdr->kernel_addr));
dtb_p = _paddr(dtb_buf);
KEY_NODE_INFO("start native android!\n");
arch_chain_load(entry_p, dtb_p, 0, 0, 0);
=====================>
arch_disable_ints();
target_quiesce();
platform_quiesce();
entry_pa = (paddr_t)entry;
loader_pa = (paddr_t)arm_chain_load;
arch_quiesce();
void (*loader)(paddr_t entry, ulong, ulong, ulong, ulong) __NO_RETURN = (void *)loader_pa;
loader(entry_pa, arg0, arg1, arg2, arg3);
<====================
return 0;
boot_linux:
smc(SMC_DIS_HCE, 0, 0, 0, 0, 0, 0, 0);
fdt = (void *)_ioaddr(REE_MEMBASE + BOARD_TARS_OFFSET);
ret = partition_load(ptdev, alias_dtb, fdt, BOARD_KERNEL_OFFSET - BOARD_TARS_OFFSET, NULL);
ret = fdt_check_header(fdt);
kernel = (void *)_ioaddr(REE_MEMBASE + BOARD_KERNEL_OFFSET);
ret = partition_load(ptdev, alias_kernel_part, kernel, BOARD_RAMDISK_OFFSET - BOARD_KERNEL_OFFSET, NULL);
root_type = check_root_type(fdt);
if (root_type == 0) {
rootfs_buf = (void *)_ioaddr(REE_MEMBASE + BOARD_RAMDISK_OFFSET);
ret = partition_load(ptdev, alias_rootfs_part, rootfs_buf, ROOTFS_MEMSIZE, NULL);
}
memset(&dtbo_info, 0x0, sizeof(dtbo_info));
if (load_dtbo_image(ptdev, &dtbo_info) && !add_verified_image_list(&verified_images_list, dtbo_info.base,
dtbo_info.size, dtbo_info.pt_name)) {
goto error;
}
if (!add_verified_image_list(&verified_images_list, fdt,BOARD_KERNEL_OFFSET - BOARD_TARS_OFFSET, alias_dtb)
|| !add_verified_image_list(&verified_images_list, kernel,BOARD_RAMDISK_OFFSET - BOARD_KERNEL_OFFSET, alias_kernel_part)
|| (rootfs_buf && !add_verified_image_list(&verified_images_list, rootfs_buf, ROOTFS_MEMSIZE,
alias_rootfs_part))) {
goto error;
}
if (!get_cmdline_by_verified_image(ptdev, &verified_images_list)) {
goto error;
}
free_image_info_list(&verified_images_list);
if (dtbo_info.base)
dtbo_find_apply_match(fdt, dtbo_info.base, dtbo_find_hw_match);
ret = fdt_update_memory_range(fdt, HYP_MEMBASE, 0, ddr_size);
if (ret)
dprintf(CRITICAL, "failed to update memory range.\n");
ret_smc = smc(SMCCC_ARCH_FEATURES, SMCCC_ARCH_FEATURES, 0, 0,
0, 0, 0, 0);
if (ret_smc != SMC_OK) {
update_dt_psci_method(fdt, "native");
}
if (root_type == 0)
ret = update_fdt_initrd(fdt, REE_MEMBASE + BOARD_RAMDISK_OFFSET,
ROOTFS_MEMSIZE);
cmdline_board = calloc(1, COMMAND_LINE_PARTITION);
if (!cmdline_board) {
dprintf(CRITICAL, "alloc cmdline buf failed\n");
goto error;
}
#if SUPPORT_CMDLINE_PART
ret = generate_active_part_cmdline(cmdline_board, ptdev);
if (ret) {
dprintf(CRITICAL, "failed to get all part.\n");
free(cmdline_board);
goto error;
}
#endif
if (root_type == 1) {
remove_root_dev_fdt_bootargs(fdt);
if (is_recovery()) {
update_root_dev(ptdev, cmdline_board, "recovery");
merge_fdt_bootargs(fdt, "recovery_mode");
}
else {
update_root_dev(ptdev, cmdline_board, alias_rootfs_part);
}
}
merge_fdt_bootargs(fdt, (const char *)cmdline_board);
subst_dm_root_device_bootargs(fdt);
free(cmdline_board);
if (vbmeta_cmdline)
free(vbmeta_cmdline);
if (dm_table)
free(dm_table);
if (dtbo_info.base)
free(dtbo_info.base);
fdt_pack(fdt);
arch_clean_cache_range((addr_t)fdt, BOARD_KERNEL_OFFSET);
dtb_p = _paddr(fdt);
KEY_NODE_INFO("start native linux!\n");
arch_chain_load(kernel, dtb_p, 0, 0, 0);
return 0;
error:
dprintf(CRITICAL, "no os is available to boot\n");
return -1;
}
int bootloader_main(int argc, const cmd_args *argv)
{
#ifndef BACKDOOR_DDR
_bootloader_main();
#endif
return 0;
}
1.4.3 BOOT Pin Map
有关 pin map ,我也贴一下吧,如下:
# buildsystem\rtos\lk_boot\chipcfg\generate\x9_high-plus\projects\serdes\boot_device_cfg.h
btdev_pin_cfg_t btdev_pin_mapping[] = {
[0] = {
.pin_val = BOOT_PIN_0,
.ap = &mmc1,
.safety = &ospi1, },
[1] = {
.pin_val = BOOT_PIN_1,
.ap = &mmc1,
.safety = &ospi1, },
[2] = {
.pin_val = BOOT_PIN_2,
.ap = &mmc2,
.safety = &ospi1, },
[3] = {
.pin_val = BOOT_PIN_3,
.ap = &mmc3,
.safety = &ospi1, },
[4] = {
.pin_val = BOOT_PIN_4,
.ap = &ospi2,
.safety = &ospi1, },
[5] = {
.pin_val = BOOT_PIN_5,
.ap = NULL,
.safety = &ospi1, },
[6] = {
.pin_val = BOOT_PIN_6,
.ap = NULL,
.safety = NULL, },
[7] = {
.pin_val = BOOT_PIN_7,
.ap = NULL,
.safety = NULL, },
[8] = {
.pin_val = BOOT_PIN_8,
.ap = NULL,
.safety = NULL, },
[9] = {
.pin_val = BOOT_PIN_9,
.ap = &mmc1,
.safety = NULL, },
[10] = {
.pin_val = BOOT_PIN_10,
.ap = &mmc2,
.safety = NULL, },
[11] = {
.pin_val = BOOT_PIN_11,
.ap = &mmc3,
.safety = NULL, },
[12] = {
.pin_val = BOOT_PIN_12,
.ap = &ospi2,
.safety = NULL, },
[13] = {
.pin_val = BOOT_PIN_13,
.ap = NULL,
.safety = NULL, },
[14] = {
.pin_val = BOOT_PIN_14,
.ap = NULL,
.safety = NULL, },
[15] = {
.pin_val = BOOT_PIN_15,
.ap = NULL,
.safety = NULL, },
};
# buildsystem\rtos\lk_boot\chipcfg\generate\x9_high-plus\projects\serdes\boot_device_cfg.h
boot_device_cfg_t mmc1 =
{
.device_type = MMC,
.res_idex = RES_MSHC_SD1,
.disk_name = "mmcblk0:",
.storage_type = "emmc",
.cfg = {
.mmc_cfg = {
.voltage = MMC_VOL_1_8,
.max_clk_rate = MMC_CLK_200MHZ,
.bus_width = MMC_BUS_WIDTH_8BIT,
.hs400_support = 1,
},
},
};
boot_device_cfg_t mmc2 =
{
.device_type = MMC,
.res_idex = RES_MSHC_SD2,
.disk_name = "mmcblk0:",
.storage_type = "emmc",
.cfg = {
.mmc_cfg = {
.voltage = MMC_VOL_1_8,
.max_clk_rate = MMC_CLK_100MHZ,
.bus_width = MMC_BUS_WIDTH_8BIT,
},
},
};
boot_device_cfg_t mmc3 =
{
.device_type = MMC,
.res_idex = RES_MSHC_SD3,
.disk_name = "mmcblk1:",
.storage_type = "sd",
.cfg = {
.mmc_cfg = {
.voltage = MMC_VOL_3_3,
.max_clk_rate = MMC_CLK_25MHZ,
.bus_width = MMC_BUS_WIDTH_4BIT,
},
},
};
boot_device_cfg_t ospi1 =
{
.device_type = OSPI,
.res_idex = RES_OSPI_REG_OSPI1,
.cfg = {
.ospi_cfg = {
.cs = SPI_NOR_CS0,
.bus_clk = SPI_NOR_CLK_25MHZ,
.octal_ddr_en = 0,
},
},
};
boot_device_cfg_t ospi2 =
{
.device_type = OSPI,
.res_idex = RES_OSPI_REG_OSPI2,
.cfg = {
.ospi_cfg = {
.cs = SPI_NOR_CS0,
.bus_clk = SPI_NOR_CLK_25MHZ,
.octal_ddr_en = 0,
},
},
};
|