^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2014 Intel Corporation; author Matt Fleming
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (c) 2014 Red Hat, Inc., Mark Salter <msalter@redhat.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/efi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/reboot.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) static void (*orig_pm_power_off)(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) int efi_reboot_quirk_mode = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) void efi_reboot(enum reboot_mode reboot_mode, const char *__unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) const char *str[] = { "cold", "warm", "shutdown", "platform" };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) int efi_mode, cap_reset_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) if (!efi_rt_services_supported(EFI_RT_SUPPORTED_RESET_SYSTEM))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) switch (reboot_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) case REBOOT_WARM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) case REBOOT_SOFT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) efi_mode = EFI_RESET_WARM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) efi_mode = EFI_RESET_COLD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * If a quirk forced an EFI reset mode, always use that.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) if (efi_reboot_quirk_mode != -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) efi_mode = efi_reboot_quirk_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) if (efi_capsule_pending(&cap_reset_mode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) if (efi_mode != cap_reset_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) printk(KERN_CRIT "efi: %s reset requested but pending "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) "capsule update requires %s reset... Performing "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) "%s reset.\n", str[efi_mode], str[cap_reset_mode],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) str[cap_reset_mode]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) efi_mode = cap_reset_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) efi.reset_system(efi_mode, EFI_SUCCESS, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) bool __weak efi_poweroff_required(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static void efi_power_off(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * The above call should not return, if it does fall back to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * the original power off method (typically ACPI poweroff).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (orig_pm_power_off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) orig_pm_power_off();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static int __init efi_shutdown_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (!efi_rt_services_supported(EFI_RT_SUPPORTED_RESET_SYSTEM))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (efi_poweroff_required()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) orig_pm_power_off = pm_power_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) pm_power_off = efi_power_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) late_initcall(efi_shutdown_init);