Andorid 7.1.1 lk启动流程

little kernel 是小内核小操作系统,简称lk,主要用来引导运行OS系统,lk启动后根据一些参数值,引导启动进入不同模式。其实Android手机有四种启动方式,四种方式分别为:

  1. 正常开机启动;
  2. recovery启动;
  3. fastboot启动;
  4. ffbm启动

下面就以高通代码为例,分析下这四种启动方式分别是在什么条件下启动的手机上电后,会从固定的地址(固化在ROM中)加载bootloader到RAM,然后跳转到bootloader的入口函数开始执行

    bootable/bootloader/lk/arch/arm/crt0.Sblkmain

kmain的代码位于bootable/bootloader/lk/kernel/main.c

  /* called from crt0.S */void kmain(void) __NO_RETURN __EXTERNALLY_VISIBLE;void kmain(void){thread_t *thr;// get us into some sort of thread contextthread_init_early();  //初始化线程上下文// early arch stuffarch_early_init(); //架构初始化,如关闭cache,使能mmu// do any super early platform initializationplatform_early_init(); //平台早期初始化// do any super early target initializationtarget_early_init(); //目标设备早期初始化,初始化串口dprintf(INFO, "welcome to lk\n\n");bs_set_timestamp(BS_BL_START);// deal with any static constructorsdprintf(SPEW, "calling constructors\n");call_constructors();// bring up the kernel heapdprintf(SPEW, "initializing heap\n");heap_init(); //堆初始化__stack_chk_guard_setup();// initialize the threading systemdprintf(SPEW, "initializing threads\n");thread_init();  //线程初始化// initialize the dpc systemdprintf(SPEW, "initializing dpc\n");dpc_init(); //lk系统控制器初始化// initialize kernel timersdprintf(SPEW, "initializing timers\n");timer_init(); //kernel时钟初始化#if (!ENABLE_NANDWRITE)// create a thread to complete system initializationdprintf(SPEW, "creating bootstrap completion thread\n");thr = thread_create("bootstrap2", &bootstrap2, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE);if (!thr){panic("failed to create thread bootstrap2\n");}thread_resume(thr); //创建一个线程初始化系统// enable interruptsexit_critical_section(); //使能中断// become the idle threadthread_become_idle();//本线程切换成idle线程,idle为空闲线程,当没有更高优先级的线程时才执行#elsebootstrap_nandwrite(); #endif}

如果定义了ENABLE_NANDWRITE在timer_init之后将执行bootstrap_nandwrite。我们接下来先以没有定义ENABLE_NANDWRITE来进行分析。从代码可知,会创建一个bootstrap2线程,并使能中断

 bootable/bootloader/lk/kernel/main.cstatic int bootstrap2(void *arg){dprintf(SPEW, "top of bootstrap2()\n");arch_init();  //架构初始化,此函数为空,什么都没做// XXX put this somewhere else#if WITH_LIB_BIObio_init();#endif#if WITH_LIB_FSfs_init();#endif// initialize the rest of the platformdprintf(SPEW, "initializing platform\n");platform_init(); // 平台初始化,不同的平台要做的事情不一样,可以是初始化系统时钟,超频等// initialize the targetdprintf(SPEW, "initializing target\n");target_init();  //目标设备初始化,主要初始化Flash,整合分区表等dprintf(SPEW, "calling apps_init()\n");apps_init();   //应用功能初始化,主要调用boot_init,启动kernel,加载boot/recovery镜像等return 0;}

在app.c中定义了apps_init如下:

    bootable/bootloader/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){thread_t *thr;printf("starting app %s\n", app->name);thr = thread_create(app->name, &app_thread_entry, (void *)app, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE);if(!thr){return;}thread_resume(thr);}

__apps_start和__apps_end都是在连接脚本中定义的, 在 bootable/bootloader/lk/arch/arm/system-onesegment.ld中有:

    __apps_start = .;KEEP (*(.apps))__apps_end = .;

__apps_start和__apps_end都代表两个链接地址,KEEP (*(.apps))表示所有.apps段都链接在__apps_start和__apps_end之间。
因为在bootable/bootloader/lk/include/app.h中有定义

    bootable/bootloader/lk/include/app.h#define APP_START(appname) struct app_descriptor _app_##appname __SECTION(".apps") = { .name = #appname,#define APP_END };

所以这里将会执行在APP_START(appname)中定义的appname函数。在代码里搜索APP_START,会发现在bootable/bootloader/lk/app/aboot/aboot.c中调用APP_START来执行aboot_init函数

    bootable/bootloader/lk/app/aboot/aboot.cAPP_START(aboot).init = aboot_init,APP_END

接下来就是这篇文章的重点aboot.c中的aboot_init,如下:

    void aboot_init(const struct app_descriptor *app){unsigned reboot_mode = 0;unsigned hard_reboot_mode = 0;//bug 8046int ret;/* Initialise wdog to catch early lk crashes */#if WDOG_SUPPORTmsm_wdog_init();#endif/* Setup page size information for nv storage */if (target_is_emmc_boot()) 检测是emmc还是flash存储,并设置页大小,一般是2048{page_size = mmc_page_size();page_mask = page_size - 1;mmc_blocksize = mmc_get_device_blocksize();mmc_blocksize_mask = mmc_blocksize - 1;}else{page_size = flash_page_size();page_mask = page_size - 1;}ASSERT((MEMBASE + MEMSIZE) > MEMBASE); //断言,如果内存基地址+内存大小小于内存基地址,则直接终止错误read_device_info(&device); //从devinfo分区表read data到device结构体    read_allow_oem_unlock(&device); //devinfo分区里记录了unlock状态,从device中读取此信息if(target_enter_ffbm_mode()) //判断是否进入ffbm模式{boot_into_ffbm = true;dprintf(ALWAYS," gpio24 lcd te pull up  ------boot_into_ffbm----\n");}/* Display splash screen if enabled */#if DISPLAY_SPLASH_SCREEN#if NO_ALARM_DISPLAYif (!check_alarm_boot()) { //检测开机原因是否是由于关机闹钟导致#endifdprintf(SPEW, "Display Init: Start\n");#if DISPLAY_HDMI_PRIMARYif (!strlen(device.display_panel))strlcpy(device.display_panel, DISPLAY_PANEL_HDMI,sizeof(device.display_panel));#endif#if ENABLE_WBC/* Wait if the display shutdown is in progress */while(pm_app_display_shutdown_in_prgs());if (!pm_appsbl_display_init_done())target_display_init(device.display_panel); //显示splash,Splash也就是应用程序启动之前先启动一个画面,上面简单的介绍应用程序的厂商,厂商的LOGO,名称和版本等信息,多为一张图片 elsedisplay_image_on_screen();#elsetarget_display_init(device.display_panel);#endifdprintf(SPEW, "Display Init: Done\n");#if NO_ALARM_DISPLAY}#endif#endiftarget_serialno((unsigned char *) sn_buf);dprintf(SPEW,"serial number: %s\n",sn_buf);memset(display_panel_buf, '\0', MAX_PANEL_BUF_SIZE);/** Check power off reason if user force reset,* if yes phone will do normal boot.*/if (is_user_force_reset()) //如果强制重启,直接进入normal_bootgoto normal_boot;/* Check if we should do something other than booting up */if (keys_get_state(KEY_VOLUMEUP) && keys_get_state(KEY_VOLUMEDOWN))//同时按住音量上下键进入fastboot 模式{dprintf(ALWAYS,"dload mode key sequence detected\n");reboot_device(EMERGENCY_DLOAD);dprintf(CRITICAL,"Failed to reboot into dload mode\n");boot_into_fastboot = true;}if (keys_get_state(KEY_VOLUMEUP))  //按住音量上键进入recovery 模式{dprintf(ALWAYS,"KEY_VOLUMEUP------------------\n");boot_into_recovery = true;}if (keys_get_state(KEY_VOLUMEDOWN)) //按住音量下键进入fastboot 模式{dprintf(ALWAYS,"KEY_VOLUMEDOWN------------------\n");boot_into_fastboot = true;  }if (!boot_into_fastboot){if (keys_get_state(KEY_HOME) || keys_get_state(KEY_VOLUMEUP))boot_into_recovery = 1;if (!boot_into_recovery &&(keys_get_state(KEY_BACK) /*|| keys_get_state(KEY_VOLUMEDOWN)*/)) boot_into_fastboot = true;}#if NO_KEYPAD_DRIVERif (fastboot_trigger())boot_into_fastboot = true;#endifhard_reboot_mode = check_hard_reboot_mode();reboot_mode = check_reboot_mode();//检查重启原因dprintf(CRITICAL,"aboot_init  reboot_mode=%x,hard_reboot_mode=%x\n",reboot_mode,hard_reboot_mode);if (reboot_mode == RECOVERY_MODE || hard_reboot_mode == RECOVERY_HARD_RESET_MODE){boot_into_recovery = 1;}else if(reboot_mode == FASTBOOT_MODE || hard_reboot_mode == FASTBOOT_HARD_RESET_MODE){boot_into_fastboot = true;}else if(reboot_mode == ALARM_BOOT || hard_reboot_mode == RTC_HARD_RESET_MODE){boot_reason_alarm = true;}normal_boot:if (!boot_into_fastboot) //如果不是fastboot模式{if (target_is_emmc_boot()){if(emmc_recovery_init())dprintf(ALWAYS,"error in emmc_recovery_init\n");if(target_use_signed_kernel()){if((device.is_unlocked) || (device.is_tampered)){#ifdef TZ_TAMPER_FUSEset_tamper_fuse_cmd();#endif#if USE_PCOM_SECBOOTset_tamper_flag(device.is_tampered);#endif}}boot_linux_from_mmc(); //程序会跑到这里,又一个重点内容,下面会独立分析这个函数。}else{recovery_init();#if USE_PCOM_SECBOOTif((device.is_unlocked) || (device.is_tampered))set_tamper_flag(device.is_tampered);#endifboot_linux_from_flash();}dprintf(CRITICAL, "ERROR: Could not do normal boot. Reverting ""to fastboot mode.\n");}//下面的代码是fastboot的准备工作,从中可以看出,进入fastboot模式是不启动kernel的/* We are here means regular boot did not happen. Start fastboot. *//* register aboot specific fastboot commands */aboot_fastboot_register_commands();  //注册fastboot命令,建议看下此函数的源码,此函数是fastboot支持的命令,如flash、erase等等/* dump partition table for debug info */partition_dump();dprintf(0,"run in fastboot %s %s\r\n",__DATE__,__TIME__);display_image_on_screen_fastboot(); //显示fastboot界面/* initialize and start fastboot */fastboot_init(target_get_scratch_address(), target_get_max_flash_size());#if FBCON_DISPLAY_MSGdisplay_fastboot_menu();#endif}

从上面可以看出boot_init主要工作如下:

1、确定page_size大小;

2、从devinfo分区获取devinfo信息;

3、根据条件判断进入不同模式,设置对应标志位boot_into_xxx;

4、进入fastboot模式,初始化fastboot命令等

来源:https://blog.csdn.net/yin1031468524/article/details/78984805

https://blog.csdn.net/qq_23327993/article/details/88735298

Android lk启动流程相关推荐

  1. Android系统 lk启动流程简析

    本篇文章是对初步学习Android系统lk启动流程的一个大致简介.方便掌握lk启动流程的大致框架,具体细节后续再进行更新 1. 前言 需要了解的文件类型: 1)编译LK的链接文件(.ld) 2)汇编文 ...

  2. lk启动流程详细分析

    转载请注明来源:cuixiaolei的技术博客 这篇文章是lk启动流程分析(以高通为例),将会详细介绍下面的内容: 1).正常开机引导流程 2).recovery引导流程 3).fastboot引导流 ...

  3. Android开机启动流程

    Android开机启动流程 一.APPS PBL(Application primary boot loader:主引导加载程序) 二.XBL(Extensible boot loader:可扩展引导 ...

  4. 【SemiDrive源码分析】【X9芯片启动流程】30 - AP1 Android Kernel 启动流程 start_kernel 函数详细分析(一)

    [SemiDrive源码分析][X9芯片启动流程]30 - AP1 Android Kernel 启动流程 start_kernel 函数详细分析(一) 一.Android Kernel 启动流程分析 ...

  5. 【Android 逆向】加壳的 Android 应用启动流程 | 使用反射替换 LoadedApk 中的类加载器流程

    文章目录 一.加壳的 Android 应用启动流程 二.使用反射替换 LoadedApk 中的类加载器流程 一.加壳的 Android 应用启动流程 加壳的 Android 应用启动流程 : 加壳的 ...

  6. 【Android 逆向】Android 进程简介 ( Android 应用启动流程 )

    文章目录 前言 一.Android 进程 二.Android 应用启动流程 前言 参考 [Android 逆向]Android 系统文件分析 ( /proc/pid 进程号对应进程目录 | oom_a ...

  7. Android开机启动流程简析

    Android开机启动流程简析 (一) 文章目录 Android开机启动流程简析 (一) 前言 一.开机启动的流程概述 二.Android的启动过程分析 (1).总体流程 init简述 Zygote简 ...

  8. Android -- Wifi启动流程分析

    Android -- Wifi启动流程分析 Android网络各个模式中,Wifi应该是目前最常用的一种网络方式了:下面就简单介绍下Android中Wifi的启动流程. 当我在Setting菜单里点击 ...

  9. 【SemiDrive源码分析】【X9芯片启动流程】27 - AP1 Android Preloader启动流程分析(加载atf、tos、bootloader镜像后进入BL31环境)

    [SemiDrive源码分析][X9芯片启动流程]27 - AP1 Android Preloader启动流程分析(加载atf.tos.bootloader镜像后进入BL31环境) 一.Android ...

最新文章

  1. 一文带你读懂Python的5大特点与8大应用方向!
  2. mxnet可视化模型中间层feature map输出
  3. [***]HZOJ 优美序列
  4. MySQL中的索引(唯一索引篇)
  5. 栈和队列----用栈求解汉诺塔问题
  6. Windows Intellij环境下Gradle的 “Could not determine Java version from ‘9.0.1’”的解决方式...
  7. Python 进程互斥锁 Lock - Python零基础入门教程
  8. ClippingNode实现新手引导高亮裁切
  9. 机器学习实战系列(五):SVM支持向量机
  10. docker 中文目录及文件乱码_解决docker容器中文乱码,修改docker容器编码格式
  11. foobar android 目录,最强手机音乐播放器?Foobar2K安卓版体验
  12. Cain嗅探工具的https数据捕获
  13. 2021年中国图书出版行业经营现状及重点企业对比分析:凤凰传媒优势明显[图]
  14. 傻瓜式抠图工具,不用photoshop也能搞定抠图!
  15. UNIX时间戳的UTC(协调世界时)
  16. 头牌知产介绍减肥药商标注册属于哪一类?
  17. TortoiseSVN配置外部对比工具
  18. 微分的定义和介绍习题
  19. android 表情的输入 Unicode实现表情展示 无需图片素材及相关解析
  20. C/C++数学计算库

热门文章

  1. 轻量级 Linux 发行版CRUX 发布 3.4 版
  2. Linux内核学习笔记(一) 虚拟文件系统VFS
  3. 计算机点火工作原理,简述汽车发动机ECU工作原理
  4. 以下不是python内置数据类型的是_以下不是python内置数据类型的是
  5. Vue 中 强制组件重新渲染的正确方法
  6. python生成分析图_Pyflame 生成火焰图分析 Python 程序
  7. FDTD Solutions时域有限差分法仿真学习相关操作(二)——圆偏振光和椭圆偏振光光源
  8. 纳米二氧化硅/分解酶/聚己内酯复合微球/银纳米颗粒修饰二氧化硅微球SERS基底的应用
  9. LindDotNetCore~基于模块化注入的介绍
  10. 前端必看的8个HTML+CSS技巧