Browse Source

[cmdline] Add "poweroff" command

Modified-by: Michael Brown <mcb30@ipxe.org>
Signed-off-by: Marin Hannache <git@mareo.fr>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Marin Hannache 11 years ago
parent
commit
c0af8c0433

+ 108
- 0
src/arch/i386/interface/pcbios/apm.c View File

@@ -0,0 +1,108 @@
1
+/*
2
+ * Copyright (C) 2013 Marin Hannache <ipxe@mareo.fr>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17
+ * 02110-1301, USA.
18
+ */
19
+
20
+FILE_LICENCE ( GPL2_OR_LATER );
21
+
22
+/**
23
+ * @file
24
+ *
25
+ * Advanced Power Management
26
+ *
27
+ */
28
+
29
+#include <errno.h>
30
+#include <realmode.h>
31
+#include <ipxe/reboot.h>
32
+
33
+/**
34
+ * Power off the computer using APM
35
+ *
36
+ * @ret rc		Return status code
37
+ */
38
+static int apm_poweroff ( void ) {
39
+	uint16_t apm_version;
40
+	uint16_t apm_signature;
41
+	uint16_t apm_flags;
42
+	uint16_t carry;
43
+
44
+	/* APM check */
45
+	__asm__ __volatile__ ( REAL_CODE ( "int $0x15\n\t"
46
+	                                   "adc %%edx,0\n\t" )
47
+	                       : "=a" ( apm_version ), "=b" ( apm_signature ),
48
+                                 "=c" ( apm_flags ), "=d" ( carry )
49
+	                       : "a" ( 0x5300 ), "b" ( 0x0000 ),
50
+				 "d" ( 0x0000 ) );
51
+	if ( carry ) {
52
+		DBG ( "APM not present\n" );
53
+		return -ENOTSUP;
54
+	}
55
+	if ( apm_signature != 0x504d ) { /* signature 'PM' */
56
+		DBG ( "APM not present\n" );
57
+		return -ENOTSUP;
58
+	}
59
+	if ( apm_version < 0x0101 ) { /* Need version 1.1+ */
60
+		DBG ( "APM 1.1+ not supported\n" );
61
+		return -ENOTSUP;
62
+	}
63
+	if ( ( apm_flags & 0x8 ) == 0x8 ) {
64
+		DBG ( "APM power management disabled\n" );
65
+		return -EPERM;
66
+	}
67
+	DBG2 ( "APM check completed\n" );
68
+
69
+	/* APM initialisation */
70
+	__asm__ __volatile__ ( REAL_CODE ( "int $0x15\n\t"
71
+	                                   "adc %%edx,0\n\t" )
72
+	                       : "=d" ( carry )
73
+	                       : "a" ( 0x5301 ), "b" ( 0x0000 ),
74
+	                         "d" ( 0x0000 ) );
75
+	if ( carry ) {
76
+		DBG ( "APM initialisation failed\n" );
77
+		return -EIO;
78
+	}
79
+	DBG2 ( "APM initialisation completed\n" );
80
+
81
+	/* Set APM driver version */
82
+	__asm__ __volatile__ ( REAL_CODE ( "int $0x15\n\t"
83
+	                                   "adc %%edx,0\n\t" )
84
+	                       : "=d" ( carry )
85
+	                       : "a" ( 0x530e ), "b" ( 0x0000 ),
86
+	                         "c" ( 0x0101 ), "d" ( 0x0000 ) );
87
+	if ( carry ) {
88
+		DBG ( "APM setting driver version failed\n" );
89
+		return -EIO;
90
+	}
91
+	DBG2 ( "APM driver version set\n" );
92
+
93
+	/* Setting power state to off */
94
+	__asm__ __volatile__ ( REAL_CODE ( "int $0x15\n\t"
95
+	                                   "adc %%edx,0\n\t" )
96
+	                       : "=d" ( carry )
97
+	                       : "a" ( 0x5307 ), "b" ( 0x0001 ),
98
+	                         "c" ( 0x0003 ), "d" ( 0x0000) );
99
+	if ( carry ) {
100
+		DBG ( "APM setting power state failed\n" );
101
+		return -ENOTTY;
102
+	}
103
+
104
+	/* Should never happen */
105
+	return -ECANCELED;
106
+}
107
+
108
+PROVIDE_REBOOT ( pcbios, poweroff, apm_poweroff );

+ 1
- 0
src/arch/x86/include/bits/errfile.h View File

@@ -19,6 +19,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
19 19
 #define ERRFILE_vmware		( ERRFILE_ARCH | ERRFILE_CORE | 0x00080000 )
20 20
 #define ERRFILE_guestrpc	( ERRFILE_ARCH | ERRFILE_CORE | 0x00090000 )
21 21
 #define ERRFILE_guestinfo	( ERRFILE_ARCH | ERRFILE_CORE | 0x000a0000 )
22
+#define ERRFILE_apm		( ERRFILE_ARCH | ERRFILE_CORE | 0x000b0000 )
22 23
 
23 24
 #define ERRFILE_bootsector     ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00000000 )
24 25
 #define ERRFILE_bzimage	       ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00010000 )

+ 3
- 0
src/config/config.c View File

@@ -242,6 +242,9 @@ REQUIRE_OBJECT ( lotest_cmd );
242 242
 #ifdef VLAN_CMD
243 243
 REQUIRE_OBJECT ( vlan_cmd );
244 244
 #endif
245
+#ifdef POWEROFF_CMD
246
+REQUIRE_OBJECT ( poweroff_cmd );
247
+#endif
245 248
 #ifdef REBOOT_CMD
246 249
 REQUIRE_OBJECT ( reboot_cmd );
247 250
 #endif

+ 1
- 0
src/config/general.h View File

@@ -126,6 +126,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
126 126
 //#define VLAN_CMD		/* VLAN commands */
127 127
 //#define PXE_CMD		/* PXE commands */
128 128
 //#define REBOOT_CMD		/* Reboot command */
129
+//#define POWEROFF_CMD		/* Power off command */
129 130
 //#define IMAGE_TRUST_CMD	/* Image trust management commands */
130 131
 
131 132
 /*

+ 12
- 0
src/core/null_reboot.c View File

@@ -27,6 +27,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
27 27
  */
28 28
 
29 29
 #include <stdio.h>
30
+#include <errno.h>
30 31
 #include <ipxe/reboot.h>
31 32
 
32 33
 /**
@@ -40,4 +41,15 @@ static void null_reboot ( int warm __unused ) {
40 41
 	while ( 1 ) {}
41 42
 }
42 43
 
44
+/**
45
+ * Power off system
46
+ *
47
+ * @ret rc		Return status code
48
+ */
49
+static int null_poweroff ( void ) {
50
+
51
+	return -ENOTSUP;
52
+}
53
+
43 54
 PROVIDE_REBOOT ( null, reboot, null_reboot );
55
+PROVIDE_REBOOT ( null, poweroff, null_poweroff );

+ 72
- 0
src/hci/commands/poweroff_cmd.c View File

@@ -0,0 +1,72 @@
1
+/*
2
+ * Copyright (C) 2013 Marin Hannache <ipxe@mareo.fr>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17
+ * 02110-1301, USA.
18
+ */
19
+
20
+#include <stdio.h>
21
+#include <string.h>
22
+#include <getopt.h>
23
+#include <ipxe/command.h>
24
+#include <ipxe/parseopt.h>
25
+#include <ipxe/reboot.h>
26
+
27
+FILE_LICENCE ( GPL2_OR_LATER );
28
+
29
+/** @file
30
+ *
31
+ * Power off command
32
+ *
33
+ */
34
+
35
+/** "poweroff" options */
36
+struct poweroff_options {};
37
+
38
+/** "poweroff" option list */
39
+static struct option_descriptor poweroff_opts[] = {};
40
+
41
+/** "poweroff" command descriptor */
42
+static struct command_descriptor poweroff_cmd =
43
+	COMMAND_DESC ( struct poweroff_options, poweroff_opts, 0, 0, "" );
44
+
45
+/**
46
+ * The "poweroff" command
47
+ *
48
+ * @v argc		Argument count
49
+ * @v argv		Argument list
50
+ * @ret rc		Return status code
51
+ */
52
+static int poweroff_exec ( int argc, char **argv ) {
53
+	struct poweroff_options opts;
54
+	int rc;
55
+
56
+	/* Parse options */
57
+	if ( ( rc = parse_options ( argc, argv, &poweroff_cmd, &opts ) ) != 0 )
58
+		return rc;
59
+
60
+	/* Power off system */
61
+	rc = poweroff();
62
+	if ( rc != 0 )
63
+		printf ( "Could not power off: %s\n", strerror ( rc ) );
64
+
65
+	return rc;
66
+}
67
+
68
+/** "poweroff" command */
69
+struct command poweroff_command __command = {
70
+	.name = "poweroff",
71
+	.exec = poweroff_exec,
72
+};

+ 2
- 0
src/include/ipxe/errfile.h View File

@@ -63,6 +63,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
63 63
 #define ERRFILE_test		       ( ERRFILE_CORE | 0x00170000 )
64 64
 #define ERRFILE_xferbuf		       ( ERRFILE_CORE | 0x00180000 )
65 65
 #define ERRFILE_pending		       ( ERRFILE_CORE | 0x00190000 )
66
+#define ERRFILE_null_reboot	       ( ERRFILE_CORE | 0x001a0000 )
66 67
 
67 68
 #define ERRFILE_eisa		     ( ERRFILE_DRIVER | 0x00000000 )
68 69
 #define ERRFILE_isa		     ( ERRFILE_DRIVER | 0x00010000 )
@@ -277,6 +278,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
277 278
 #define ERRFILE_efi_umalloc	      ( ERRFILE_OTHER | 0x003b0000 )
278 279
 #define ERRFILE_linux_pci	      ( ERRFILE_OTHER | 0x003c0000 )
279 280
 #define ERRFILE_pci_settings	      ( ERRFILE_OTHER | 0x003d0000 )
281
+#define ERRFILE_efi_reboot	      ( ERRFILE_OTHER | 0x003e0000 )
280 282
 
281 283
 /** @} */
282 284
 

+ 10
- 0
src/include/ipxe/reboot.h View File

@@ -55,4 +55,14 @@ FILE_LICENCE ( GPL2_OR_LATER );
55 55
  */
56 56
 void reboot ( int warm );
57 57
 
58
+/**
59
+ * Power off system
60
+ *
61
+ * @ret rc		Return status code
62
+ *
63
+ * This function may fail, since not all systems support being powered
64
+ * off by software.
65
+ */
66
+int poweroff ( void );
67
+
58 68
 #endif /* _IPXE_REBOOT_H */

+ 17
- 0
src/interface/efi/efi_reboot.c View File

@@ -26,6 +26,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
26 26
  *
27 27
  */
28 28
 
29
+#include <errno.h>
29 30
 #include <ipxe/efi/efi.h>
30 31
 #include <ipxe/reboot.h>
31 32
 
@@ -41,4 +42,20 @@ static void efi_reboot ( int warm ) {
41 42
 	rs->ResetSystem ( ( warm ? EfiResetWarm : EfiResetCold ), 0, 0, NULL );
42 43
 }
43 44
 
45
+/**
46
+ * Power off system
47
+ *
48
+ * @ret rc		Return status code
49
+ */
50
+static int efi_poweroff ( void ) {
51
+	EFI_RUNTIME_SERVICES *rs = efi_systab->RuntimeServices;
52
+
53
+	/* Use runtime services to power off system */
54
+	rs->ResetSystem ( EfiResetShutdown, 0, 0, NULL );
55
+
56
+	/* Should never happen */
57
+	return -ECANCELED;
58
+}
59
+
44 60
 PROVIDE_REBOOT ( efi, reboot, efi_reboot );
61
+PROVIDE_REBOOT ( efi, poweroff, efi_poweroff );

Loading…
Cancel
Save