高通芯片启动流程
QSEE 运行在安全模式并且只能被OEM签名。
- UEFI启动:
bootable/bootloader/edk2/QcomModulePkg/Library/BootLib/BootLinux.c 加载boot.img流程
signer:manual
NEPTUNE: Kernel Image Signing Verification successful
No Ffbm cookie found, ignore: Not Found
Memory Base Address: 0x80000000
Decompressing kernel image start: 3488 ms//解压内核镜像
Decompressing kernel image done: 3818 ms
amzn_verify_unlock: Failed to get unlock keyPON Reason is 16 cold_boot:1 charger path: 1
Cmdline: console=ttyMSM0,921600,n8 androidboot.console=ttyMSM0 earlycon=msm_serial_dm,0xc170000 androidboot.hardware=qcom user_debug=31 msm_rtb.filter=0x37 ehci-hcd.park=3 lpm_levels.sleep_disabled=1 sched_enable_hmp=1 sched_enable_power_aware=1 service_lError getting pmic info ext: Device Error
Error finding board pmic info: Device Error
DEBUG((EFI_D_VERBOSE, "Kernel Size Actual: 0x%x\n", KernelSizeActual));
DEBUG((EFI_D_VERBOSE, "Second Size Actual: 0x%x\n", SecondSizeActual));
DEBUG((EFI_D_VERBOSE, "Ramdisk Size Actual: 0x%x\n", RamdiskSizeActual));
DEBUG((EFI_D_VERBOSE, "Ramdisk Offset: 0x%x\n", RamdiskOffset));
DEBUG((EFI_D_VERBOSE, "Device TreeOffset: 0x%x\n", DeviceTreeOffset));
VOID *DeviceTreeAppended(VOID *kernel, UINT32 kernel_size, UINT32 dtb_offset, VOID *tags)
{EFI_STATUS Status;uintptr_t kernel_end = (uintptr_t)kernel + kernel_size;VOID *dtb = NULL;VOID *bestmatch_tag = NULL;UINT64 RamdiskLoadAddr;UINT64 BaseMemory = 0;struct dt_entry *best_match_dt_entry = NULL;UINT32 bestmatch_tag_size;struct dt_entry_node *dt_entry_queue = NULL;struct dt_entry_node *dt_node_tmp1 = NULL;struct dt_entry_node *dt_node_tmp2 = NULL;/* Initialize the dtb entry node*/dt_entry_queue = (struct dt_entry_node *) AllocatePool(sizeof(struct dt_entry_node));if (!dt_entry_queue) {DEBUG((EFI_D_ERROR, "Out of memory\n"));return NULL;}memset(dt_entry_queue, 0, sizeof(struct dt_entry_node));list_initialize(&dt_entry_queue->node);if (!dtb_offset){DEBUG((EFI_D_ERROR, "DTB offset is NULL\n"));goto out;}if (((uintptr_t)kernel + (uintptr_t)dtb_offset) < (uintptr_t)kernel) {goto out;}dtb = kernel + dtb_offset;while (((uintptr_t)dtb + sizeof(struct fdt_header)) < (uintptr_t)kernel_end) {struct fdt_header dtb_hdr;UINT32 dtb_size;/* the DTB could be unaligned, so extract the header,* and operate on it separately */CopyMem(&dtb_hdr, dtb, sizeof(struct fdt_header));if (fdt_check_header((const VOID *)&dtb_hdr) != 0 ||fdt_check_header_ext((VOID *)&dtb_hdr) != 0 ||((uintptr_t)dtb + (uintptr_t)fdt_totalsize((const VOID *)&dtb_hdr) < (uintptr_t)dtb) ||((uintptr_t)dtb + (uintptr_t)fdt_totalsize((const VOID *)&dtb_hdr) > (uintptr_t)kernel_end))break;dtb_size = fdt_totalsize(&dtb_hdr);if (!DeviceTreeCompatible(dtb, dtb_size, dt_entry_queue)) {DEBUG((EFI_D_VERBOSE, "Error while DTB parse continue with next DTB\n"));}/* goto the next device tree if any */dtb += dtb_size;}best_match_dt_entry = platform_dt_match_best(dt_entry_queue);
设备树匹配,遍历所有设备树
STATIC struct dt_entry *platform_dt_match_best(struct dt_entry_node *dt_list)
{struct dt_entry_node *dt_node_tmp1 = NULL;/* check Foundry id* the foundry id must exact match board founddry id, this is compatibility check,* if couldn't find the exact match from DTB, will exact match 0x0.*/if (!platform_dt_absolute_compat_match(dt_list, DTB_FOUNDRY))//匹配DTB版本return NULL;/* check PMIC model* the PMIC model must exact match board PMIC model, this is compatibility check,* if couldn't find the exact match from DTB, will exact match 0x0.*/if (!platform_dt_absolute_compat_match(dt_list, DTB_PMIC_MODEL))//匹配PMIC版本return NULL;/* check soc version* the suitable soc version must less than or equal to board soc version*/if (!update_dtb_entry_node(dt_list, DTB_SOC))return NULL;/*check major and minor version* the suitable major&minor version must less than or equal to board major&minor version*/if (!update_dtb_entry_node(dt_list, DTB_MAJOR_MINOR)) ///检查subtypereturn NULL;
3. Linux kernel层
asmlinkage void __init start_kernel(void)
{local_irq_disable();early_boot_irqs_off();early_init_irq_lock_class();/*1. Interrupts are still disabled. Do necessary setups, then2. enable them*/lock_kernel();tick_init();boot_cpu_init();page_address_init();printk(KERN_NOTICE);printk(linux_banner);setup_arch(command_line);//初始化setup_command_line(command_line);printk(KERN_NOTICE "Kernel command line: %s\n", boot_command_line);parse_early_param();parse_args("Booting kernel", static_command_line, __start___param,__stop___param - __start___param,&unknown_bootoption);init_IRQ();//中断初始化profile_init();if (!irqs_disabled())printk("start_kernel(): bug: interrupts were enabled early\n");early_boot_irqs_on();local_irq_enable();console_init();rest_init();//会通过kernel_thread来生成1个内核进程
}
4. System init:
代码路径System/core/init.cpp
对应的log如下
[ 7.900996] init: init first stage started!
[ 7.983229] audit: type=1403 audit(12.809:2): policy loaded auid=4294967295 ses=4294967295
[ 7.983950] audit: type=1404 audit(12.809:3): enforcing=1 old_enforcing=0 auid=4294967295 ses=4294967295
[ 7.990647] init: (Initializing SELinux enforcing took 0.09s.)
[ 8.003941] init: init second stage started!
[ 8.013583] init: Running restorecon...
[ 8.323897] init: waitpid failed: No child processes
[ 8.324841] init: (Loading properties from /default.prop took 0.00s.)
[ 8.328755] init: could not import file '/init.recovery.qcom.rc' from '/init.rc': No such file or directory
[ 8.334335] init: (Parsing /init.rc took 0.01s.)
[ 8.344019] init: Starting service 'ueventd'...
[ 8.349071] init: Starting service 'healthd'...