转载请注明文章出处和作者!
出处:http://blog.csdn.net/xl19862005
大家多多支持偶家媳妇的网店:http://wen1991.taobao.com
作者:大熊(Xandy)
1、总述
在android系统中有好几个子系统(recovery、factory及power off charge),那么这些子系统是如何与主系统之间进行切换的呢?
(recovery系统的切换与启动已经在另一篇博客里写过了
http://blog.csdn.net/xl19862005/article/details/8517918
)
今天理了一下factory这个子系统启动过程,现在将其记录如下
由于目前所用的平台方案是MTK的6572,代码路径等会和其它的方案不一样
先来看一个图:
进入factory子系统与recovery系统不同的是:
factory:是在init这个进程中激活并启动的
recovery:则是通过bootcmdline跳转到相应的地址上启动的
2、lk(uboot)检测factory mult key
在mediatek/platform/mt6572/lk/factory.c这个文件中有如下代码
BOOL factory_check_key_trigger(void) { //wait ulong begin = get_timer(0); printf("\n%s Check factory boot\n",MODULE_NAME); printf("%s Wait 50ms for special keys\n",MODULE_NAME); /* If the boot reason is RESET, than we will NOT enter factory mode. */ if(mtk_detect_pmic_just_rst()) { return false; } while(get_timer(begin)<50) { if(mtk_detect_key(MT65XX_FACTORY_KEY)) { printf("%s Detect key\n",MODULE_NAME); printf("%s Enable factory mode\n",MODULE_NAME); g_boot_mode = FACTORY_BOOT; //video_printf("%s : detect factory mode !\n",MODULE_NAME); return TRUE; } } return FALSE; }当检测到factory key按下时会在这里设置
g_boot_mode = FACTORY_BOOT;g_boot_mode是一个typedef类型的全局变量
类型定义如下:
typedef enum { NORMAL_BOOT = 0, META_BOOT = 1, RECOVERY_BOOT = 2, SW_REBOOT = 3, FACTORY_BOOT = 4, ADVMETA_BOOT = 5, ATE_FACTORY_BOOT = 6, ALARM_BOOT = 7, #if defined (MTK_KERNEL_POWER_OFF_CHARGING) KERNEL_POWER_OFF_CHARGING_BOOT = 8, LOW_POWER_OFF_CHARGING_BOOT = 9, #endif FASTBOOT = 99, DOWNLOAD_BOOT = 100, UNKNOWN_BOOT } BOOTMODE;可以看出这里定义的FACTORY_BOOT模式的值为4!
3、kernel中启动init进程
lk(uboot)引导内核之后,我们来看看在kernel/init/main.c中这个文件中的kernel_init这个函数,这是一个线程回调函数,
在同文件中的rest_init函数中
kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
注册到线程中去并得到执行
在kernel_init中有如下代码:
if (!ramdisk_execute_command) ramdisk_execute_command = "/init"; if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) { ramdisk_execute_command = NULL; prepare_namespace(); }可以看出这里将/init这个根目录中的bin文件路径传递给了ramdisk_execute_command这个全局的字符指针,另外根目录中的init bin文件是
打包到ramdisk.img中的(请查看android源码编译后相应的root目录下的文件)
再来看看init_post这个函数中的如下代码:
if (ramdisk_execute_command) { run_init_process(ramdisk_execute_command); printk(KERN_WARNING "Failed to execute %s\n", ramdisk_execute_command); }在这里内核就引导进入到用户空间的程序了
另外在mediatek/platform/mt6572/kernel/core/mt_boot.c这个文件中有如下代码:
/* create proc entry at /proc/boot_mode */ create_proc_read_entry(boot_mode, S_IRUGO, NULL, boot_mode_proc, NULL);在这里创建了一个名为“boot_mode”的属性,用于内核和用户空间的init程序传递参数!
4、init进程
system/core/init/init.c这是生成根目录中init bin的源码
在这个文件的main函数中对系统启动所需的各种资源进行了准备和初始化……
这里有如下代码:
static int is_factory_boot(void) { int fd; size_t s; char boot_mode; fd = open("/sys/class/BOOT/BOOT/boot/boot_mode", O_RDWR); if (fd < 0) { printf("fail to open: %s\n", "/sys/class/BOOT/BOOT/boot/boot_mode"); return 0; } s = read(fd, (void *)&boot_mode, sizeof(boot_mode)); close(fd); if(s <= 0){ ERROR("could not read boot mode sys file\n"); return 0; } // Factory Mode, '4' // ATE Factory Mode, '6' if ((boot_mode != '4') && (boot_mode != '6')){ ERROR("Unsupported factory mode\n"); return 0; } printf("Factory Mode Booting.....\n"); return 1; }
"/sys/class/BOOT/BOOT/boot/boot_mode"这个路径的属性文件是在内核中的mt_boot.c这个文件中创建的,在init中读取这个文件的属性从而获得系统启动状态
可以看出当boot_mode被设置成“4”时(对应前面提到的FACTORY_BOOT = 4)就会进入到factory子系统了
if (is_factory_boot()) { ERROR("This is factory boot"); property_set("sys.mtk.no.factoryimage","1"); init_parse_config_file("/factory_init.rc"); INFO("reading project config file\n"); init_parse_config_file("/factory_init.project.rc"); }在这里加载factory_init.rc用于启动factory下所需的一些服务或工具。
另外关机充电功能的实现也是按照这种架构实现的!