Page MenuHomeFreeBSD

D18506.id51885.diff
No OneTemporary

D18506.id51885.diff

Index: share/man/man9/efirt.9
===================================================================
--- share/man/man9/efirt.9
+++ share/man/man9/efirt.9
@@ -26,7 +26,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd August 12, 2018
+.Dd December 11, 2018
.Dt EFIRT 9
.Os
.Sh NAME
@@ -54,7 +54,7 @@
.Ft int
.Fn efi_get_time_capabilities "struct efi_tmcap *tmcap"
.Ft int
-.Fn efi_reset_system "void"
+.Fn efi_reset_system "enum efi_reset type"
.Ft int
.Fn efi_set_time "struct efi_tm *tm"
.Ft int
@@ -123,7 +123,20 @@
.Pp
The
.Fn efi_reset_system
-function requests a warm reset and reboot of the system.
+function requests a reset of the system.
+The
+.Fa type
+argument may be one of the
+.Vt enum efi_reset
+values:
+.Bl -tag -width ".Dv EFI_RESET_SHUTDOWN"
+.It Dv EFI_RESET_COLD
+Perform a cold reset of the system, and reboot.
+.It Dv EFI_RESET_WARM
+Perform a warm reset of the system, and reboot.
+.It Dv EFI_RESET_SHUTDOWN
+Power off the system.
+.El
.Pp
The
.Fn efi_set_time
@@ -239,7 +252,7 @@
.It Dv EROFS
The variable in question is read-only or may not be deleted.
.It Dv EDOOFUS
-The varialbe could not be set due to an authentication failure.
+The variable could not be set due to an authentication failure.
.It Dv ENOENT
The variable trying to be updated or deleted was not found.
.El
Index: sys/dev/efidev/efirt.c
===================================================================
--- sys/dev/efidev/efirt.c
+++ sys/dev/efidev/efirt.c
@@ -34,6 +34,7 @@
#include <sys/param.h>
#include <sys/efi.h>
+#include <sys/eventhandler.h>
#include <sys/kernel.h>
#include <sys/linker.h>
#include <sys/lock.h>
@@ -41,6 +42,7 @@
#include <sys/mutex.h>
#include <sys/clock.h>
#include <sys/proc.h>
+#include <sys/reboot.h>
#include <sys/rwlock.h>
#include <sys/sched.h>
#include <sys/sysctl.h>
@@ -106,6 +108,10 @@
}
static struct mtx efi_lock;
+static SYSCTL_NODE(_hw, OID_AUTO, efi, CTLFLAG_RWTUN, NULL, "EFI");
+static bool efi_poweroff = true;
+SYSCTL_BOOL(_hw_efi, OID_AUTO, poweroff, CTLFLAG_RWTUN, &efi_poweroff, 0,
+ "If true, use EFI runtime services to power off in preference to ACPI");
static bool
efi_is_in_map(struct efi_md *map, int ndesc, int descsz, vm_offset_t addr)
@@ -126,6 +132,19 @@
return (false);
}
+static void
+efi_shutdown_final(void *dummy __unused, int howto)
+{
+
+ /*
+ * On some systems, ACPI S5 is missing or does not function properly.
+ * When present, shutdown via EFI Runtime Services instead, unless
+ * disabled.
+ */
+ if ((howto & RB_POWEROFF) != 0 && efi_poweroff)
+ (void)efi_reset_system(EFI_RESET_SHUTDOWN);
+}
+
static int
efi_init(void)
{
@@ -214,6 +233,12 @@
}
#endif
+ /*
+ * We use SHUTDOWN_PRI_LAST - 1 to trigger after IPMI, but before ACPI.
+ */
+ EVENTHANDLER_REGISTER(shutdown_final, efi_shutdown_final, NULL,
+ SHUTDOWN_PRI_LAST - 1);
+
return (0);
}
@@ -411,16 +436,24 @@
}
int
-efi_reset_system(void)
+efi_reset_system(enum efi_reset type)
{
struct efirt_callinfo ec;
+ switch (type) {
+ case EFI_RESET_COLD:
+ case EFI_RESET_WARM:
+ case EFI_RESET_SHUTDOWN:
+ break;
+ default:
+ return (EINVAL);
+ }
if (efi_runtime == NULL)
return (ENXIO);
bzero(&ec, sizeof(ec));
ec.ec_name = "rt_reset";
ec.ec_argcnt = 4;
- ec.ec_arg1 = (uintptr_t)EFI_RESET_WARM;
+ ec.ec_arg1 = (uintptr_t)type;
ec.ec_arg2 = (uintptr_t)0;
ec.ec_arg3 = (uintptr_t)0;
ec.ec_arg4 = (uintptr_t)NULL;
Index: sys/dev/ipmi/ipmi.c
===================================================================
--- sys/dev/ipmi/ipmi.c
+++ sys/dev/ipmi/ipmi.c
@@ -938,14 +938,14 @@
} else if (!on)
(void)ipmi_set_watchdog(sc, 0);
/*
- * Power cycle the system off using IPMI. We use last - 1 since we don't
+ * Power cycle the system off using IPMI. We use last - 2 since we don't
* handle all the other kinds of reboots. We'll let others handle them.
* We only try to do this if the BMC supports the Chassis device.
*/
if (sc->ipmi_dev_support & IPMI_ADS_CHASSIS) {
device_printf(dev, "Establishing power cycle handler\n");
sc->ipmi_power_cycle_tag = EVENTHANDLER_REGISTER(shutdown_final,
- ipmi_power_cycle, sc, SHUTDOWN_PRI_LAST - 1);
+ ipmi_power_cycle, sc, SHUTDOWN_PRI_LAST - 2);
}
}
Index: sys/sys/efi.h
===================================================================
--- sys/sys/efi.h
+++ sys/sys/efi.h
@@ -42,8 +42,9 @@
{0xeb9d2d32,0x2d88,0x11d3,0x9a,0x16,{0x00,0x90,0x27,0x3f,0xc1,0x4d}}
enum efi_reset {
- EFI_RESET_COLD,
- EFI_RESET_WARM
+ EFI_RESET_COLD = 0,
+ EFI_RESET_WARM = 1,
+ EFI_RESET_SHUTDOWN = 2,
};
typedef uint16_t efi_char;
@@ -184,7 +185,7 @@
int efi_get_table(struct uuid *uuid, void **ptr);
int efi_get_time(struct efi_tm *tm);
int efi_get_time_capabilities(struct efi_tmcap *tmcap);
-int efi_reset_system(void);
+int efi_reset_system(enum efi_reset type);
int efi_set_time(struct efi_tm *tm);
int efi_var_get(uint16_t *name, struct uuid *vendor, uint32_t *attrib,
size_t *datasize, void *data);

File Metadata

Mime Type
text/plain
Expires
Sat, Dec 21, 11:02 AM (17 h, 57 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15540640
Default Alt Text
D18506.id51885.diff (4 KB)

Event Timeline