- /system/core/android_reboot.c
int android_reboot(int cmd, int flags, char *arg)
该函数作为通用API, 可以分别用在如下地方:- adb shell mode reboot
- fastboot downloading mode reboot
- recovery mode reboot
- Charging mode reboot
- /kernel/include/linux/reboot.h
- 定义了 __reboot() 系统调用的 magic value
- 定义了 __reboot 系统调用的 command
- 需要关注一下某些函数是体系结构无关的,某些是有体系结构依赖的
/* * Architecture-specific implementations of sys_reboot commands. */ extern void machine_restart(char *cmd); extern void machine_halt(void); extern void machine_power_off(void); extern void machine_shutdown(void); struct pt_regs; extern void machine_crash_shutdown(struct pt_regs *); /* * Architecture independent implemenations of sys_reboot commands. */ extern void kernel_restart_prepare(char *cmd); extern void kernel_restart(char *cmd); extern void kernel_halt(void); extern void kernel_power_off(void); extern int C_A_D; /* for sysctl */ void ctrl_alt_del(void); #define POWEROFF_CMD_PATH_LEN 256 extern char poweroff_cmd[POWEROFF_CMD_PATH_LEN]; extern int orderly_poweroff(bool force); /* * Emergency restart, callable from an interrupt handler. */ extern void emergency_restart(void); #include <asm/emergency-restart.h>
- 展开 <asm/emergency-restart.h> 后如下
static inline void machine_emergency_restart(void) { machine_restart(NULL); }
- /kernel/kernel/sys.c reboot() system call
reboot() 系统调用需要:
- Only root may call it with obvious reasons
- root needs to setup some magic numbers in registers 以避免错误
- 这里可以添加 ctrl-alt-del-key 响应
- reboot() 不做sync() 动作, 需要自己显式调用 sync()
SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd, void __user *, arg) { char buffer[256]; int ret = 0; /* We only trust the superuser with rebooting the system. */ if (!capable(CAP_SYS_BOOT)) return -EPERM; /* For safety, we require "magic" arguments. */ if (magic1 != LINUX_REBOOT_MAGIC1 || (magic2 != LINUX_REBOOT_MAGIC2 && magic2 != LINUX_REBOOT_MAGIC2A && magic2 != LINUX_REBOOT_MAGIC2B && magic2 != LINUX_REBOOT_MAGIC2C)) return -EINVAL; /* Instead of trying to make the power_off code look like * halt when pm_power_off is not set do it the easy way. */ if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !pm_power_off) cmd = LINUX_REBOOT_CMD_HALT; mutex_lock(&reboot_mutex); switch (cmd) { case LINUX_REBOOT_CMD_RESTART: kernel_restart(NULL); break; case LINUX_REBOOT_CMD_CAD_ON: C_A_D = 1; break; case LINUX_REBOOT_CMD_CAD_OFF: C_A_D = 0; break; 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; #ifdef CONFIG_KEXEC case LINUX_REBOOT_CMD_KEXEC: ret = kernel_kexec(); break; #endif #ifdef CONFIG_HIBERNATION case LINUX_REBOOT_CMD_SW_SUSPEND: ret = hibernate(); break; #endif default: ret = -EINVAL; break; } mutex_unlock(&reboot_mutex); return ret; }
- 体系结构无关的 API 将会调用平台体系结构相关的 API
/** * kernel_restart - reboot the system * @cmd: pointer to buffer containing command to execute for restart * or %NULL * * Shutdown everything and perform a clean reboot. * This is not safe to call in interrupt context. */ void kernel_restart(char *cmd) { kernel_restart_prepare(cmd); if (!cmd) printk(KERN_EMERG "Restarting system.\n"); else printk(KERN_EMERG "Restarting system with command '%s'.\n", cmd); kmsg_dump(KMSG_DUMP_RESTART); machine_restart(cmd); }
- 对于 arm platform, 下一步是 /kernel/arch/arm/kernel/process.c
void machine_restart(char *cmd) { machine_shutdown(); arm_pm_restart(reboot_mode, cmd); }
- 同文件里面进行了函数指针转换
void (*arm_pm_restart)(char str, const char *cmd) = arm_machine_restart; EXPORT_SYMBOL_GPL(arm_pm_restart);
- arm_machine_restart() 如下
void arm_machine_restart(char mode, const char *cmd) { /* Flush the console to make sure all the relevant messages make it * out to the console drivers */ arm_machine_flush_console(); /* Disable interrupts first */ local_irq_disable(); local_fiq_disable(); /* * Tell the mm system that we are going to reboot - * we may need it to insert some 1:1 mappings so that * soft boot works. */ setup_mm_for_reboot(mode, NULL); /* Clean and invalidate caches */ flush_cache_all(); /* Turn off caching */ cpu_proc_fin(); /* Push out any further dirty data, and ensure cache is empty */ flush_cache_all(); /* * Now call the architecture specific reboot code. */ arch_reset(mode, cmd); /* * Whoops - the architecture was unable to reboot. * Tell the user! */ mdelay(1000); printk("Reboot failed -- System halted\n"); while (1); }
- 然后是 /kernel/arch/arm/plat-xxxx/include/mach/system.h
对于Qualcomm是
#include <mach/hardware.h> void arch_idle(void); static inline void arch_reset(char mode, const char *cmd) { for (;;) ; /* depends on IPC w/ other core */ } /* low level hardware reset hook -- for example, hitting the * PSHOLD line on the PMIC to hard reset the system */ extern void (*msm_hw_reset_hook)(void);
对于Samsung S3C2410是
extern void (*s3c24xx_reset_hook)(void); static void arch_reset(char mode, const char *cmd) { if (mode == 's') { cpu_reset(0); } if (s3c24xx_reset_hook) s3c24xx_reset_hook(); arch_wdt_reset(); /* we'll take a jump through zero as a poor second */ cpu_reset(0); }
典型的示例如下:
static inline void arch_idle(void) { cpu_do_idle(); } static inline void arch_reset(char mode, const char *cmd) { cpu_reset(0); }
Android reboot分析
最新推荐文章于 2021-10-29 09:43:19 发布