android 9 reboot流程

发布时间:2024年01月11日

机器出现开机 自动进入fastboot模式。可能是init 那个进程挂了 然后调用了
RebootSystem(ANDROID_RB_RESTART2, “bootloader”); 函数进入重启流程,然后重启后进入fastboot
浅读一下reboot流程和怎么进入的fastboot
比如说是那个进程挂了调用了这个函数,然后就是会调用到 RebootSystem
在这里插入图片描述
在查看一下RebootSystem(unsigned int cmd, const std::string& rebootTarget)的paramete
paramete 1 :cmd 就是 reboot 命令是poweroff 还是restart
paramete 2: rebootTarget 就是重启的参数只有restart才会用到这个参数(reboot recovery/bootloader)重启后进入指定模式 例如fastboot
recovery模式
在这里插入图片描述
看重启流程:
syscall是一个系统调用 在这调用_NR_reboot指令
系统调用之后就是进入内核
include\linux\syscall.h 中调用SYSCALL_DEFINE4 因为 _NR_reboot后面带4个参数 实际
SYSCALL_DEFINE4会根据你的命令(reboot star stop 等一下关于内核的命令调用实际函数)
在这里插入图片描述
就是这个name
-------------------------分界线---------------
比如_NR_reboot 就是调用sys_reboot函数,其他exit或者shutdown同理
在这里插入图片描述
那么我们就在内核中调用了sys_reboot并且系统层给了参数
asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void __user *arg);
syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,LINUX_REBOOT_CMD_RESTART2, rebootTarget.c_str()
对应就是 magic1 = LINUX_REBOOT_MAGIC1
magic2 =LINUX_REBOOT_MAGIC2
cmd = LINUX_REBOOT_CMD_RESTART2(重启)
rebootTarget.c_str() = 重启参数在开头给的是“bootloder”
--------------------------分界线-------------------------------------------
分界线内的说明好像不正确,他不是调用的sys_reboot函数,而是把函数重新定义
在这里插入图片描述
实际调用的还是SYSCALL_DEFINE4(name ,arg…)
reboot: SYSCALL_DEFINE4(reboot ,arg…)

kernel-4.9/kernel/reboot.c中
SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
		void __user *, arg)
{
	struct pid_namespace *pid_ns = task_active_pid_ns(current);
	char buffer[256];
	int ret = 0;

	/* We only trust the superuser with rebooting the system. */
	if (!ns_capable(pid_ns->user_ns, 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;

	/*
	 * If pid namespaces are enabled and the current task is in a child
	 * pid_namespace, the command is handled by reboot_pid_ns() which will
	 * call do_exit().
	 */
	ret = reboot_pid_ns(pid_ns, cmd);
	if (ret)
		return ret;

	/* 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:
		ret = strncpy_from_user(&buffer[0], arg, sizeof(buffer) - 1);
		if (ret < 0) {
			ret = -EFAULT;
			break;
		}
		buffer[sizeof(buffer) - 1] = '\0';

		kernel_restart(buffer);
		break;

#ifdef CONFIG_KEXEC_CORE
	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;
}

如果走重启流程调用:kernel_restart(buffer);

void kernel_restart(char *cmd)
{
	kernel_restart_prepare(cmd);
	migrate_to_reboot_cpu();
	syscore_shutdown();
	if (!cmd)
		pr_emerg("Restarting system\n");
	else
		pr_emerg("Restarting system with command '%s'\n", cmd);
	kmsg_dump(KMSG_DUMP_RESTART);
	machine_restart(cmd);
}

调用 machine_restart(cmd)
kernel4.9/arch/arm/kernel/reboot.c
在这里插入图片描述
调用do_kernel_restart

void do_kernel_restart(char *cmd)
{
	atomic_notifier_call_chain(&restart_handler_list, reboot_mode, cmd);
}

atomic_notifier_call_chain做的是向注册restart_handler_list的驱动发送一个通知,通知各个通过register_restart_handler注册的钩子函数,执行这个关机函数
在kernel4.9/drivers/watchdog_core.c
__watchdog_register_device函数中注册
在这里插入图片描述
调用:watchdog_restart_notifier
在这里插入图片描述
调用:wdd->ops->restart(wdd, action, data);
看一下restart的实现在哪里
mtk_wdt.c

static int mtk_reset_handler(struct notifier_block *this, unsigned long mode,
				void *cmd)
{
	struct mtk_wdt_dev *mtk_wdt;
	void __iomem *wdt_base;
	u32 reg;

	mtk_wdt = container_of(this, struct mtk_wdt_dev, restart_handler);
	wdt_base = mtk_wdt->wdt_base;

/*
 * WDT_STATUS will be cleared to  zero after writing to WDT_MODE, so we backup it in WDT_NONRST_REG,
 * and then print it out in mtk_wdt_probe() after reset
 */
	writel(__raw_readl(wdt_base + WDT_STATUS), wdt_base + WDT_NONRST_REG);

	reg = ioread32(wdt_base + WDT_MODE);
	reg &= ~(WDT_MODE_DUAL_EN | WDT_MODE_IRQ_EN | WDT_MODE_EN);
	reg |= WDT_MODE_KEY;
	iowrite32(reg, wdt_base + WDT_MODE);

	if (cmd && (strcmp(cmd, "rpmbpk") == 0)) {
		iowrite32(ioread32(wdt_base + WDT_NONRST_REG2) | (1U << 0), wdt_base + WDT_NONRST_REG2);
	} else if (cmd && (strcmp(cmd, "recovery") == 0)) {
		iowrite32(ioread32(wdt_base + WDT_NONRST_REG2) | (1U << 1), wdt_base + WDT_NONRST_REG2);
		#ifdef CONFIG_MT6397_MISC
		mtk_misc_mark_recovery();
		#endif
	} else if (cmd && (strcmp(cmd, "bootloader") == 0)) {
		iowrite32(ioread32(wdt_base + WDT_NONRST_REG2) | (1U << 2), wdt_base + WDT_NONRST_REG2);
		#ifdef CONFIG_MT6397_MISC
		mtk_misc_mark_fast();
		#endif
	} else {
		//do nothing
	}

	if (!arm_pm_restart) {
		while (1) {
			writel(WDT_SWRST_KEY, wdt_base + WDT_SWRST);
			mdelay(5);
		}
	}
	return NOTIFY_DONE;
}

这里就是resart实现的地方,那么我们传下来的参数是bootloader
iowrite32(ioread32(wdt_base + WDT_NONRST_REG2) | (1U << 2), wdt_base + WDT_NONRST_REG2);
看到这是写看了一个寄存器,这要看数据手册才知道写的是那个寄存器了,不过在lk阶段就是判断RTC的寄存器来判断进入fasterboot模式的。
vendor\mediatek\proprietary\bootable\bootloader\lk\platform\mt8163\boot_mode.c

void boot_mode_select(void)
{

    int factory_forbidden = 0;
  //  int forbid_mode;
/*We put conditions here to filer some cases that can not do key detection*/
    extern int kedump_mini(void) __attribute__((weak));
    if (kedump_mini)
    {
        if (kedump_mini())
        {
            mrdump_check();
            return;
        }
    }
    if (meta_detection())
    {
      return;
    }
    mrdump_check();

#if defined (HAVE_LK_TEXT_MENU)
/*Check RTC to know if system want to reboot to Fastboot*/
    if(Check_RTC_PDN1_bit13())
    {
     dprintf(CRITICAL, "[FASTBOOT] reboot to boot loader\n");
      g_boot_mode = FASTBOOT;
      Set_Clr_RTC_PDN1_bit13(false);
          return;
    }
    /*If forbidden mode is factory, cacel the factory key detection*/
    if(g_boot_arg->sec_limit.magic_num == 0x4C4C4C4C)
    {
        if(g_boot_arg->sec_limit.forbid_mode == F_FACTORY_MODE)
        {
            //Forbid to enter factory mode
           dprintf(CRITICAL, "%s Forbidden\n",MODULE_NAME);
            factory_forbidden=1;
        }
    }
  //  forbid_mode = g_boot_arg->boot_mode &= 0x000000FF;
    /*If boot reason is power key + volumn down, then
     disable factory mode dectection*/
    if(mtk_detect_pmic_just_rst())
    {
          factory_forbidden=1;
    }
    /*Check RTC to know if system want to reboot to Recovery*/
    if(Check_RTC_Recovery_Mode())
    {
          g_boot_mode = RECOVERY_BOOT;
          return;
    }
    /*If MISC Write has not completed  in recovery mode
     before system reboot, go to recovery mode to
    finish remain tasks*/
    if(unshield_recovery_detection())
    {
        return;
    }
    ulong begin = get_timer(0);

/*we put key dectection here to detect key which is pressed*/

所以这俩个就是通过判断RTC_PDN1_bit13这个位进入fastboot模式。
同理我们使用adb 命令 adb reboot bootloader 就是reboot d带bootloader参数也是一样的进fastboot

不一样的是系统层下发命令进入fastboot是由于系统崩溃导致,可以查看在哪里崩溃的日志定位问题。

文章来源:https://blog.csdn.net/wzf_Cql/article/details/135499913
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。