예제 #1
0
/*
 * Windows compatible x86 hardware expects the following on reboot:
 *
 * 1) If the FADT has the ACPI reboot register flag set, try it
 * 2) If still alive, write to the keyboard controller
 * 3) If still alive, write to the ACPI reboot register again
 * 4) If still alive, write to the keyboard controller again
 *
 * If the machine is still alive at this stage, it gives up. We default to
 * following the same pattern, except that if we're still alive after (4) we'll
 * try to force a triple fault and then cycle between hitting the keyboard
 * controller and doing that
 */
static void native_machine_emergency_restart(void)
{
    int i;
    int attempt = 0;
    int orig_reboot_type = reboot_type;

    if (reboot_emergency)
        emergency_vmx_disable_all();

    tboot_shutdown(TB_SHUTDOWN_REBOOT);

    /* Tell the BIOS if we want cold or warm reboot */
    *((unsigned short *)__va(0x472)) = reboot_mode;

    for (;;) {
        /* Could also try the reset bit in the Hammer NB */
        switch (reboot_type) {
        case BOOT_KBD:
            mach_reboot_fixups(); /* for board specific fixups */

            for (i = 0; i < 10; i++) {
                kb_wait();
                udelay(50);
                outb(0xfe, 0x64); /* pulse reset low */
                udelay(50);
            }
            if (attempt == 0 && orig_reboot_type == BOOT_ACPI) {
                attempt = 1;
                reboot_type = BOOT_ACPI;
            } else {
                reboot_type = BOOT_TRIPLE;
            }
            break;

        case BOOT_TRIPLE:
            load_idt(&no_idt);
            __asm__ __volatile__("int3");

            reboot_type = BOOT_KBD;
            break;

#ifdef CONFIG_X86_32
        case BOOT_BIOS:
            machine_real_restart(MRR_BIOS);

            reboot_type = BOOT_KBD;
            break;
#endif

        case BOOT_ACPI:
            acpi_reboot();
            reboot_type = BOOT_KBD;
            break;

        case BOOT_EFI:
            if (efi_enabled)
                efi.reset_system(reboot_mode ?
                                 EFI_RESET_WARM :
                                 EFI_RESET_COLD,
                                 EFI_SUCCESS, 0, NULL);
            reboot_type = BOOT_KBD;
            break;

        case BOOT_CF9:
            port_cf9_safe = true;
        /* fall through */

        case BOOT_CF9_COND:
            if (port_cf9_safe) {
                u8 cf9 = inb(0xcf9) & ~6;
                outb(cf9|2, 0xcf9); /* Request hard reset */
                udelay(50);
                outb(cf9|6, 0xcf9); /* Actually do the reset */
                udelay(50);
            }
            reboot_type = BOOT_KBD;
            break;
        }
    }
}
예제 #2
0
파일: reboot.c 프로젝트: sourcejedi/linux
/*
 * To the best of our knowledge Windows compatible x86 hardware expects
 * the following on reboot:
 *
 * 1) If the FADT has the ACPI reboot register flag set, try it
 * 2) If still alive, write to the keyboard controller
 * 3) If still alive, write to the ACPI reboot register again
 * 4) If still alive, write to the keyboard controller again
 * 5) If still alive, call the EFI runtime service to reboot
 * 6) If no EFI runtime service, call the BIOS to do a reboot
 *
 * We default to following the same pattern. We also have
 * two other reboot methods: 'triple fault' and 'PCI', which
 * can be triggered via the reboot= kernel boot option or
 * via quirks.
 *
 * This means that this function can never return, it can misbehave
 * by not rebooting properly and hanging.
 */
static void native_machine_emergency_restart(void)
{
    int i;
    int attempt = 0;
    int orig_reboot_type = reboot_type;
    unsigned short mode;

    if (reboot_emergency)
        emergency_vmx_disable_all();

    tboot_shutdown(TB_SHUTDOWN_REBOOT);

    /* Tell the BIOS if we want cold or warm reboot */
    mode = reboot_mode == REBOOT_WARM ? 0x1234 : 0;
    *((unsigned short *)__va(0x472)) = mode;

    /*
     * If an EFI capsule has been registered with the firmware then
     * override the reboot= parameter.
     */
    if (efi_capsule_pending(NULL)) {
        pr_info("EFI capsule is pending, forcing EFI reboot.\n");
        reboot_type = BOOT_EFI;
    }

    for (;;) {
        /* Could also try the reset bit in the Hammer NB */
        switch (reboot_type) {
        case BOOT_ACPI:
            acpi_reboot();
            reboot_type = BOOT_KBD;
            break;

        case BOOT_KBD:
            mach_reboot_fixups(); /* For board specific fixups */

            for (i = 0; i < 10; i++) {
                kb_wait();
                udelay(50);
                outb(0xfe, 0x64); /* Pulse reset low */
                udelay(50);
            }
            if (attempt == 0 && orig_reboot_type == BOOT_ACPI) {
                attempt = 1;
                reboot_type = BOOT_ACPI;
            } else {
                reboot_type = BOOT_EFI;
            }
            break;

        case BOOT_EFI:
            efi_reboot(reboot_mode, NULL);
            reboot_type = BOOT_BIOS;
            break;

        case BOOT_BIOS:
            machine_real_restart(MRR_BIOS);

            /* We're probably dead after this, but... */
            reboot_type = BOOT_CF9_SAFE;
            break;

        case BOOT_CF9_FORCE:
            port_cf9_safe = true;
        /* Fall through */

        case BOOT_CF9_SAFE:
            if (port_cf9_safe) {
                u8 reboot_code = reboot_mode == REBOOT_WARM ?  0x06 : 0x0E;
                u8 cf9 = inb(0xcf9) & ~reboot_code;
                outb(cf9|2, 0xcf9); /* Request hard reset */
                udelay(50);
                /* Actually do the reset */
                outb(cf9|reboot_code, 0xcf9);
                udelay(50);
            }
            reboot_type = BOOT_TRIPLE;
            break;

        case BOOT_TRIPLE:
            load_idt(&no_idt);
            __asm__ __volatile__("int3");

            /* We're probably dead after this, but... */
            reboot_type = BOOT_KBD;
            break;
        }
    }
}