1.概述
Android的Recovery模式用于系统软件升级。
将特定的update.zip文件置于特定的存储位置,比如/flash/update.zip,或者/mnt/storage/update.zip,然后通过Recovery模式重启进行软件升级。
从应用程序调用到JAVA框架层,再到Kernel中的JNI的调用,以及底层的C语言本地代码的调用过程来看,除了与boolloader相关的系统调用reboot需要跟相应的硬件平台关联起来之外,其他都是通用的调用过程。
不同硬件平台所需要做的修改在于,驱动层面需要对arch_reset函数重定向,如:
void (*arch_reset)(char, const char *) = rk30_arch_reset
2.函数调用过程
RecoverSystem.java
PowerManager pm= (PowerManager) context.getSystemService(Context.POWER_SERVICE);
pm.reboot("recovery");
-->
\frameworks\base\services\java\com\android\server\PowerManagerService.java
public voidreboot(String reason)
ShutdownThread.reboot(mContext,finalReason, false);
-->
\frameworks\base\services\java\com\android\server\pm\ShutdownThread.java
shutdownInner(context,confirm);
-->
beginShutdownSequence(context);
-->
run
-->
rebootOrShutdown
-->
PowerManagerService.lowLevelReboot(reason);
-->
\frameworks\base\services\java\com\android\server\PowerManagerService.java
nativeReboot();
-->
private staticnative void nativeReboot(String reason) throws IOException;
-->
\frameworks\base\services\jni\com_android_server_PowerManagerService.cpp
android_reboot(ANDROID_RB_RESTART2,0, (char *) chars);
\system\core\libcutils\android_reboot.c
caseANDROID_RB_RESTART2:
ret =__reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
LINUX_REBOOT_CMD_RESTART2, arg);
-->
\kernel\kernel\sys.c
SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsignedint, cmd,
void __user *,arg)
{
kernel_restart(buffer);
}
-->
machine_restart(cmd);
-->
\kernel\arch\arm\kernel\process.c
arm_pm_restart(reboot_mode, cmd);
-->
arm_machine_restart(char str, const char *cmd)
-->
/*
* Now call the architecture specific rebootcode.
*/
调用每个平台自己的重启函数。因为这里的重启的参数的使用与各个平台具体的bootloader相关,只能由各个平台自己去实现。
arch_reset(mode,cmd);
-->
\kernel\arch\arm\mach-rk30\reset.c
void(*arch_reset)(char, const char *) = rk30_arch_reset;
static void rk30_arch_reset(char mode, const char *cmd)
{
u32 boot_flag = 0;
u32 boot_mode =BOOT_MODE_REBOOT;
if (cmd) {
if(!strcmp(cmd, "loader") || !strcmp(cmd, "bootloader"))
boot_flag =SYS_LOADER_REBOOT_FLAG + BOOT_LOADER;
elseif(!strcmp(cmd, "recovery"))
boot_flag =SYS_LOADER_REBOOT_FLAG + BOOT_RECOVER;
else if(!strcmp(cmd, "charge"))
boot_mode =BOOT_MODE_CHARGE;
} else {
if(system_state != SYSTEM_RESTART)
boot_mode =BOOT_MODE_PANIC;
}
writel_relaxed(boot_flag,RK30_PMU_BASE + PMU_SYS_REG0); // forloader
writel_relaxed(boot_mode,RK30_PMU_BASE + PMU_SYS_REG1); // forlinux
dsb();
/* disable remap */
writel_relaxed(1<< (12 + 16), RK30_GRF_BASE + GRF_SOC_CON0);
/* pll enter slowmode */
writel_relaxed(PLL_MODE_SLOW(APLL_ID)| PLL_MODE_SLOW(CPLL_ID) | PLL_MODE_SLOW(GPLL_ID), RK30_CRU_BASE +CRU_MODE_CON);
dsb();
writel_relaxed(0xeca8,RK30_CRU_BASE + CRU_GLB_SRST_SND);
dsb();
}