首页 > 学院 > 开发设计 > 正文

kernel 调用uefi的run time service 关机

2019-11-09 15:45:58
字体:
来源:转载
供稿:网友
当上层调用reboot命令时,就会调用到arch/arm64/kernel/PRocess.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;        mutex_lock(&reboot_mutex);    switch (cmd) {    case linux_REBOOT_CMD_RESTART:        kernel_restart(NULL);        break;    case LINUX_REBOOT_CMD_POWER_OFF:        kernel_power_off();        do_exit(0);        break;}我们重点开看请参数是LINUX_REBOOT_CMD_RESTART时,会调用kernel_restart->machine_restartvoid machine_restart(char *cmd){    /* Disable interrupts first */    local_irq_disable();    smp_send_stop();    /*     * UpdateCapsule() depends on the system being reset via     * ResetSystem().     */    if (efi_enabled(EFI_RUNTIME_SERVICES))        efi_reboot(reboot_mode, NULL);    /* Now call the architecture specific reboot code. */    if (arm_pm_restart)        arm_pm_restart(reboot_mode, cmd);    else        do_kernel_restart(cmd);    /*     * Whoops - the architecture was unable to reboot.     */    printk("Reboot failed -- System halted/n");    while (1);}在machine_restart 中,可以看到如果kernel可以使用uefi的runtime service的话,就会调用efi_rebootvoid efi_reboot(enum reboot_mode reboot_mode, const char *__unused){    const char *str[] = { "cold", "warm", "shutdown", "platform" };    int efi_mode, cap_reset_mode;    if (!efi_enabled(EFI_RUNTIME_SERVICES))        return;    switch (reboot_mode) {    case REBOOT_WARM:    case REBOOT_SOFT:        efi_mode = EFI_RESET_WARM;        break;    default:        efi_mode = EFI_RESET_COLD;        break;    }    /*     * If a quirk forced an EFI reset mode, always use that.     */    if (efi_reboot_quirk_mode != -1)        efi_mode = efi_reboot_quirk_mode;    if (efi_capsule_pending(&cap_reset_mode)) {        if (efi_mode != cap_reset_mode)            printk(KERN_CRIT "efi: %s reset requested but pending "                   "capsule update requires %s reset... Performing "                   "%s reset./n", str[efi_mode], str[cap_reset_mode],                   str[cap_reset_mode]);        efi_mode = cap_reset_mode;    }    efi.reset_system(efi_mode, EFI_SUCCESS, 0, NULL);}在efi_reboot 中可以看到reboot分为四中"cold", "warm", "shutdown", "platform",最终转成两种mode EFI_RESET_WARM和 EFI_RESET_COLD最后通过    efi.reset_system(efi_mode, EFI_SUCCESS, 0, NULL);来reboot系统.在reboot命令中如果参数是LINUX_REBOOT_CMD_POWER_OFF的话kernel_power_off->machine_power_offvoid machine_power_off(void){    local_irq_disable();    smp_send_stop();    if (pm_power_off)        pm_power_off();}可见最后是调用pm_power_off 来关机的.static int __init efi_shutdown_init(void){    if (!efi_enabled(EFI_RUNTIME_SERVICES))        return -ENODEV;    if (efi_poweroff_required())        pm_power_off = efi_power_off;    return 0;}late_initcall(efi_shutdown_init);同上肯定是可以使用uefi的runtime service ,而efi_poweroff_required 也是判断是否可以使用runtime service,这两者感觉有的重复。bool efi_poweroff_required(void){    return efi_enabled(EFI_RUNTIME_SERVICES);}总之会调用efi_power_off来关机而static void efi_power_off(void){    efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, NULL);}也是调用efi接口来实现关机.
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表