1/* $Id: shutdown_xenbus.c,v 1.7 2011/09/20 00:12:24 jym Exp $ */
2
3/*-
4 * Copyright (c)2006 YAMAMOTO Takashi,
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29/*
30 * Copyright (c) 2005 Manuel Bouyer.
31 *
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
34 * are met:
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 *
41 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
42 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
43 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
44 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
45 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
47 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
48 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
49 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
50 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51 *
52 */
53
54/*
55 * watch "control/shutdown" and generate sysmon events.
56 */
57
58#include <sys/cdefs.h>
59__KERNEL_RCSID(0, "$NetBSD: shutdown_xenbus.c,v 1.7 2011/09/20 00:12:24 jym Exp $");
60
61#include <sys/param.h>
62#include <sys/malloc.h>
63
64#include <dev/sysmon/sysmonvar.h>
65
66#include <xen/xenbus.h>
67#include <xen/shutdown_xenbus.h>
68
69#define SHUTDOWN_PATH "control"
70#define SHUTDOWN_NAME "shutdown"
71
72static struct sysmon_pswitch xenbus_power = {
73 .smpsw_type = PSWITCH_TYPE_POWER,
74 .smpsw_name = "xenbus",
75};
76static struct sysmon_pswitch xenbus_reset = {
77 .smpsw_type = PSWITCH_TYPE_RESET,
78 .smpsw_name = "xenbus",
79};
80static struct sysmon_pswitch xenbus_sleep = {
81 .smpsw_type = PSWITCH_TYPE_SLEEP,
82 .smpsw_name = "xenbus",
83};
84
85static void
86xenbus_shutdown_handler(struct xenbus_watch *watch, const char **vec,
87 unsigned int len)
88{
89
90 struct xenbus_transaction *xbt;
91 int error;
92 char *reqstr;
93 unsigned int reqstrlen;
94
95again:
96 xbt = xenbus_transaction_start();
97 if (xbt == NULL) {
98 return;
99 }
100 error = xenbus_read(xbt, SHUTDOWN_PATH, SHUTDOWN_NAME,
101 &reqstrlen, &reqstr);
102 if (error) {
103 if (error != ENOENT) {
104 printf("%s: xenbus_read %d\n", __func__, error);
105 }
106 error = xenbus_transaction_end(xbt, 1);
107 if (error != 0) {
108 printf("%s: xenbus_transaction_end 1 %d\n",
109 __func__, error);
110 }
111 return;
112 }
113 KASSERT(strlen(reqstr) == reqstrlen);
114 error = xenbus_rm(xbt, SHUTDOWN_PATH, SHUTDOWN_NAME);
115 if (error) {
116 printf("%s: xenbus_rm %d\n", __func__, error);
117 }
118 error = xenbus_transaction_end(xbt, 0);
119 if (error == EAGAIN) {
120 free(reqstr, M_DEVBUF);
121 goto again;
122 }
123 if (error != 0) {
124 printf("%s: xenbus_transaction_end 2 %d\n", __func__, error);
125 }
126 if (strcmp(reqstr, "poweroff") == 0) {
127 sysmon_pswitch_event(&xenbus_power, PSWITCH_EVENT_PRESSED);
128 } else if (strcmp(reqstr, "halt") == 0) { /* XXX eventually halt without -p */
129 sysmon_pswitch_event(&xenbus_power, PSWITCH_EVENT_PRESSED);
130 } else if (strcmp(reqstr, "reboot") == 0) {
131 sysmon_pswitch_event(&xenbus_reset, PSWITCH_EVENT_PRESSED);
132 } else if (strcmp(reqstr, "suspend") == 0) {
133 xen_suspend_allow = true;
134 sysmon_pswitch_event(&xenbus_sleep, PSWITCH_EVENT_PRESSED);
135 } else {
136 printf("ignore shutdown request: %s\n", reqstr);
137 }
138 free(reqstr, M_DEVBUF);
139}
140
141static struct xenbus_watch xenbus_shutdown_watch = {
142 .node = __UNCONST(SHUTDOWN_PATH "/" SHUTDOWN_NAME), /* XXX */
143 .xbw_callback = xenbus_shutdown_handler,
144};
145
146void
147shutdown_xenbus_setup(void)
148{
149 xen_suspend_allow = false;
150
151 if (sysmon_pswitch_register(&xenbus_power) != 0 ||
152 sysmon_pswitch_register(&xenbus_reset) != 0 ||
153 sysmon_pswitch_register(&xenbus_sleep) != 0) {
154 aprint_error("%s: unable to register with sysmon\n", __func__);
155 return;
156 }
157 if (register_xenbus_watch(&xenbus_shutdown_watch)) {
158 aprint_error("%s: unable to watch control/shutdown\n", __func__);
159 }
160}
161