我这边主要讲下android reboot走的流程及所设计的代码,直接从framework层开始。
framework会提供系统重启的接口:
代码路径:framework/base/core/java/android/os/Power.java

而嵌套的rebootNative(reason);其实是个native接口,其实现是在frameworks/base/core/jni/android_os_Power.cpp.

其中android_os_Power_reboot函数如下:

最终会调用到__reboot这个函数,其带4个参数,具体函数定义是在内核里kernel/sys.c
定义如下:
SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
void __user *, arg)
{
.......
.......
/* For safety, we require "magic" arguments. */
if (magic1 != LINUX_REBOOT_MAGIC1 || //从这里可以看出其实magic1和magic2这两个参数其实没啥用,只是linux为了自身安全而带的两个参数
(magic2 != LINUX_REBOOT_MAGIC2 && //重点在cmd这个参数
magic2 != LINUX_REBOOT_MAGIC2A &&
magic2 != LINUX_REBOOT_MAGIC2B &&
magic2 != LINUX_REBOOT_MAGIC2C))
return -EINVAL;
.......
.......
.......
根据不同的cmd内核会选择做不同的事,停止、下电或者重启,我们这里主要讲重启的流程,那就接着从LINUX_REBOOT_CMD_RESTART2往下看吧
case LINUX_REBOOT_CMD_HALT:
kernel_halt();
do_exit(0);
panic("cannot halt");
case LINUX_REBOOT_CMD_POWER_OFF:
kernel_power_off();
do_exit(0);
break;
case LINUX_REBOOT_CMD_RESTART2:
if (strncpy_from_user(&buffer[0], arg, sizeof(buffer) - 1) < 0) {
ret = -EFAULT;
break;
}
buffer[sizeof(buffer) - 1] = '\0';
kernel_restart(buffer);
break;
}
我们接着从kernel_restart(buffer);往下走,看调用
kernel/sys.c:
void kernel_restart(char *cmd)
{
......
......
machine_restart(cmd);
}
----->arch/arm/kernel/process.c:
void machine_restart(char *cmd)
{
arm_pm_restart(reboot_mode, cmd);
}
----->arch/arm/kernel/process.c:
void arm_machine_restart(char mode, const char *cmd)
{
......
......
arch_reset(mode, cmd);
/*
* Whoops - the architecture was unable to reboot.
* Tell the user!
*/
mdelay(1000);
printk("Reboot failed -- System halted\n");
while (1);
}
----->arch/arm/mach-mmp/reset.c:
void arch_reset(char mode, const char *cmd)
{
if (cpu_is_pxa910() || cpu_is_pxa168())
pxa_arch_reset(mode, cmd);
else
return;
}
----->arch/arm/mach-mmp/reset.c:
static void pxa_arch_reset(char mode, const char *cmd)
{
switch (mode) {
case 's':
/* Jump into ROM at address 0 */
cpu_reset(0);
break;
case 'w':
default:
do_wdt_reset(cmd);
break;
}
}
----->arch/arm/mach-mmp/reset.c:
static void do_wdt_reset(const char *cmd)
{
......
......
if (cpu_is_pxa910())
watchdog_virt_base = CP_TIMERS2_VIRT_BASE;
else if (cpu_is_pxa168())
watchdog_virt_base = TIMERS1_VIRT_BASE;
else
return;
/* reset/enable WDT clock */
writel(0x7, MPMU_WDTPCR);
readl(MPMU_WDTPCR);
writel(0x3, MPMU_WDTPCR);
readl(MPMU_WDTPCR);
if (cpu_is_pxa910()) {
if (cmd && !strcmp(cmd, "recovery")) {
for (i = 0, backup = 0; i < 4; i++) {
backup <<= 8;
backup |= *(cmd + i);
}
do {
writel(backup, REG_RTC_BR0);
} while (readl(REG_RTC_BR0) != backup);
.......
.......
.......
}
最终就会走到对应平台的reset函数里,根据不同平台会设置自己的一些寄存器参数,并且可以根据用户层传下的arg值来
做不同的事情,比如这里
if (cmd && !strcmp(cmd, "recovery")) {
for (i = 0, backup = 0; i < 4; i++) {
backup <<= 8;
backup |= *(cmd + i);
}
如果传下来的字符串是recovery那么,就在RTC寄存器里设置某个特定值,当uboot里读取RTC寄存器的时候如果获取了这个特定值,那就可以起recovery这个动作了,大致流程是这样,希望对大家有帮助,偶人比较懒不喜欢多写注释,有兴趣的可以根据这个路径自己看代码理解。
466

被折叠的 条评论
为什么被折叠?



