赞
踩
我这边主要讲下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这个动作了,大致流程是这样,希望对大家有帮助,偶人比较懒不喜欢多写注释,有兴趣的可以根据这个路径自己看代码理解。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。