轉載請註明文章出處和作者!
出處: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下所需的一些服務或工具。
另外關機充電功能的實現也是按照這種架構實現的!