1 /* $Id: shutdown_xenbus.c,v 1.9 2020/05/13 22:13:49 jdolecek 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.9 2020/05/13 22:13:49 jdolecek Exp $"); 60 61 #include <sys/param.h> 62 63 #include <dev/sysmon/sysmonvar.h> 64 65 #include <xen/xenbus.h> 66 #include <xen/shutdown_xenbus.h> 67 68 #define SHUTDOWN_PATH "control" 69 #define SHUTDOWN_NAME "shutdown" 70 71 static struct sysmon_pswitch xenbus_power = { 72 .smpsw_type = PSWITCH_TYPE_POWER, 73 .smpsw_name = "xenbus", 74 }; 75 static struct sysmon_pswitch xenbus_reset = { 76 .smpsw_type = PSWITCH_TYPE_RESET, 77 .smpsw_name = "xenbus", 78 }; 79 static struct sysmon_pswitch xenbus_sleep = { 80 .smpsw_type = PSWITCH_TYPE_SLEEP, 81 .smpsw_name = "xenbus", 82 }; 83 84 static void 85 xenbus_shutdown_handler(struct xenbus_watch *watch, const char **vec, 86 unsigned int len) 87 { 88 89 struct xenbus_transaction *xbt; 90 int error; 91 char reqstr[32]; 92 93 again: 94 xbt = xenbus_transaction_start(); 95 if (xbt == NULL) { 96 return; 97 } 98 error = xenbus_read(xbt, SHUTDOWN_PATH, SHUTDOWN_NAME, 99 reqstr, sizeof(reqstr)); 100 /* Ignore if read error or empty value */ 101 if (error || reqstr[0] == '\0') { 102 if (error && error != ENOENT) { 103 printf("%s: xenbus_read %d\n", __func__, error); 104 } 105 error = xenbus_transaction_end(xbt, 1); 106 if (error != 0) { 107 printf("%s: xenbus_transaction_end 1 %d\n", 108 __func__, error); 109 } 110 return; 111 } 112 113 /* Acknowledge the command */ 114 error = xenbus_write(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 goto again; 121 } 122 if (error != 0) { 123 printf("%s: xenbus_transaction_end 2 %d\n", __func__, error); 124 } 125 if (strcmp(reqstr, "poweroff") == 0) { 126 sysmon_pswitch_event(&xenbus_power, PSWITCH_EVENT_PRESSED); 127 } else if (strcmp(reqstr, "halt") == 0) { /* XXX eventually halt without -p */ 128 sysmon_pswitch_event(&xenbus_power, PSWITCH_EVENT_PRESSED); 129 } else if (strcmp(reqstr, "reboot") == 0) { 130 sysmon_pswitch_event(&xenbus_reset, PSWITCH_EVENT_PRESSED); 131 } else if (strcmp(reqstr, "suspend") == 0) { 132 xen_suspend_allow = true; 133 sysmon_pswitch_event(&xenbus_sleep, PSWITCH_EVENT_PRESSED); 134 } else { 135 printf("ignore shutdown request: %s\n", reqstr); 136 } 137 } 138 139 static struct xenbus_watch xenbus_shutdown_watch = { 140 .node = __UNCONST(SHUTDOWN_PATH "/" SHUTDOWN_NAME), /* XXX */ 141 .xbw_callback = xenbus_shutdown_handler, 142 }; 143 144 void 145 shutdown_xenbus_setup(void) 146 { 147 xen_suspend_allow = false; 148 149 if (sysmon_pswitch_register(&xenbus_power) != 0 || 150 sysmon_pswitch_register(&xenbus_reset) != 0 || 151 sysmon_pswitch_register(&xenbus_sleep) != 0) { 152 aprint_error("%s: unable to register with sysmon\n", __func__); 153 return; 154 } 155 if (register_xenbus_watch(&xenbus_shutdown_watch)) { 156 aprint_error("%s: unable to watch control/shutdown\n", __func__); 157 } 158 } 159