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