summaryrefslogtreecommitdiff
path: root/usr/src/cmd/acpihpd
diff options
context:
space:
mode:
authorGerry Liu <jiang.liu@intel.com>2010-03-25 15:36:50 -0700
committerGerry Liu <jiang.liu@intel.com>2010-03-25 15:36:50 -0700
commita31148363f598def767ac48c5d82e1572e44b935 (patch)
tree756cfb0c3c9a79f98087875bb4731e0366f895b7 /usr/src/cmd/acpihpd
parent19843f01b1bef3453f717c23c8f89fb9313f6749 (diff)
downloadillumos-joyent-a31148363f598def767ac48c5d82e1572e44b935.tar.gz
PSARC/2009/104 Hot-Plug Support for ACPI-based Systems
PSARC/2009/550 PSMI Extensions for CPU Hotplug PSARC/2009/551 acpihpd ACPI Hotplug Daemon PSARC/2009/591 Attachment Points for Hotpluggable x86 Systems 6862510 provide support for cpu hot add on x86 6883891 cmi interface needs to support dynamic reconfiguration 6884154 x2APIC and kmdb may not function properly during CPU hotplug event. 6904971 low priority acpi nexus code review feedback 6877301 lgrp should support memory hotplug flag in SRAT table
Diffstat (limited to 'usr/src/cmd/acpihpd')
-rw-r--r--usr/src/cmd/acpihpd/Makefile62
-rw-r--r--usr/src/cmd/acpihpd/Makefile.com46
-rw-r--r--usr/src/cmd/acpihpd/Makefile.targ62
-rw-r--r--usr/src/cmd/acpihpd/acpihpd.c325
-rw-r--r--usr/src/cmd/acpihpd/acpihpd.xml93
-rw-r--r--usr/src/cmd/acpihpd/i386/Makefile37
-rw-r--r--usr/src/cmd/acpihpd/notify.c353
-rw-r--r--usr/src/cmd/acpihpd/svc-acpihpd39
8 files changed, 1017 insertions, 0 deletions
diff --git a/usr/src/cmd/acpihpd/Makefile b/usr/src/cmd/acpihpd/Makefile
new file mode 100644
index 0000000000..33a26fb2be
--- /dev/null
+++ b/usr/src/cmd/acpihpd/Makefile
@@ -0,0 +1,62 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# Copyright (c) 2010, Intel Corporation.
+# All rights reserved.
+#
+# cmd/acpihpd/Makefile
+#
+
+PLATFORM = i86pc
+MANIFEST = acpihpd.xml
+SVCMETHOD = svc-acpihpd
+
+include ../Makefile.cmd
+
+$(64ONLY)SUBDIRS= $(MACH)
+
+ROOTMANIFESTDIR = $(ROOTSVCPLATFORM)/${PLATFORM}
+
+all := TARGET = all
+install := TARGET = install
+clean := TARGET = clean
+clobber := TARGET = clobber
+lint := TARGET = lint
+
+.KEEP_STATE:
+
+all: $(SUBDIRS)
+
+install: $(SUBDIRS) $(ROOTMANIFEST) $(ROOTSVCMETHOD)
+
+clean clobber lint: $(SUBDIRS)
+
+check: $(CHKMANIFEST)
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
+
+include ../Makefile.targ
diff --git a/usr/src/cmd/acpihpd/Makefile.com b/usr/src/cmd/acpihpd/Makefile.com
new file mode 100644
index 0000000000..287a48d896
--- /dev/null
+++ b/usr/src/cmd/acpihpd/Makefile.com
@@ -0,0 +1,46 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# Copyright (c) 2010, Intel Corporation.
+# All rights reserved.
+#
+# cmd/acpihpd/Makefile.com
+#
+
+LIBS = acpihpd
+PLATFORM = i86pc
+
+include ../../Makefile.cmd
+include ../../../Makefile.psm
+
+OBJS = acpihpd.o notify.o
+SRCS = $(OBJS:%.o=../%.c)
+LINTFILES = $(SRCS:%.c=%.ln)
+CLOBBERFILES = $(LIBS)
+
+CFLAGS += $(CCVERBOSE)
+CPPFLAGS += -I$(USR_PSM_INCL_DIR)
+LDLIBS += -lsysevent -lnvpair -lcfgadm
+
+FILEMODE = 0755
diff --git a/usr/src/cmd/acpihpd/Makefile.targ b/usr/src/cmd/acpihpd/Makefile.targ
new file mode 100644
index 0000000000..89da583847
--- /dev/null
+++ b/usr/src/cmd/acpihpd/Makefile.targ
@@ -0,0 +1,62 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# Copyright (c) 2010, Intel Corporation.
+# All rights reserved.
+#
+# cmd/acpihpd/Makefile.targ
+#
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+clean:
+ $(RM) $(OBJS)
+
+lint:
+ $(LINT.c) $(SRCS) $(LDLIBS)
+
+$(LIBS): $(OBJS)
+ $(LINK.c) $(OBJS) -o $@ $(LDLIBS)
+ $(POST_PROCESS)
+
+%.o: ../%.c
+ $(COMPILE.c) $<
+ $(POST_PROCESS_O)
+
+$(USR_PLAT_DIR):
+ -$(INS.dir)
+
+$(USR_PSM_DIR): $(USR_PLAT_DIR)
+ -$(INS.dir)
+
+$(USR_PSM_LIB_DIR): $(USR_PSM_DIR)
+ -$(INS.dir)
+
+$(USR_PSM_LIB_DIR)/%: % $(USR_PSM_LIB_DIR)
+ $(INS.file)
+
+include ../../Makefile.targ
+
diff --git a/usr/src/cmd/acpihpd/acpihpd.c b/usr/src/cmd/acpihpd/acpihpd.c
new file mode 100644
index 0000000000..6beee85f54
--- /dev/null
+++ b/usr/src/cmd/acpihpd/acpihpd.c
@@ -0,0 +1,325 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+/*
+ * Copyright (c) 2010, Intel Corporation.
+ * All rights reserved.
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/sysevent/eventdefs.h>
+#include <sys/sysevent/dr.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <syslog.h>
+#include <string.h>
+#include <strings.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <time.h>
+#include <config_admin.h>
+#include <libscf.h>
+#include <libsysevent.h>
+#include <stdarg.h>
+
+/* Signal handler type */
+typedef void (sig_handler_t)(int);
+
+#define ACPIHPD_PID_FILE "/var/run/acpihpd.pid" /* lock file path */
+
+/* Program Name */
+char *g_prog_name;
+int g_debuglevel = 0;
+
+static int s_pid_fd;
+static sysevent_handle_t *s_acpihpd_hdl;
+
+static int daemon_init(void);
+static void daemon_quit(int);
+static int set_sig_handler(int, sig_handler_t *);
+static int acpihpd_init(void);
+static void acpihpd_fini(void);
+static void acpihpd_event(sysevent_t *);
+extern void notify_hotplug(sysevent_t *ev);
+void debug_print(int, const char *, ...);
+
+int
+main(int argc, char *argv[])
+{
+ int c;
+
+ /* Get Program Name */
+ if ((g_prog_name = strrchr(argv[0], '/')) == NULL) {
+ g_prog_name = argv[0];
+ } else {
+ g_prog_name++;
+ }
+
+ while ((c = getopt(argc, argv, ":d:")) != -1) {
+ switch (c) {
+ case 'd':
+ g_debuglevel = atoi(optarg);
+ if ((g_debuglevel < 0) || (g_debuglevel > 2)) {
+ g_debuglevel = 0;
+ }
+ break;
+
+ case ':':
+ syslog(LOG_ERR,
+ "missed argument for option %c.", optopt);
+ break;
+
+ case '?':
+ syslog(LOG_ERR, "unrecognized option %c.", optopt);
+ break;
+ }
+ }
+
+ s_acpihpd_hdl = NULL;
+
+ /* Check the daemon running lock and initialize the signal */
+ if (daemon_init() != 0) {
+ debug_print(0, "%s could not startup!", g_prog_name);
+ exit(SMF_EXIT_ERR_FATAL);
+ }
+
+ /* Subscribe to the hotplug event */
+ if (acpihpd_init() != 0) {
+ debug_print(0, "%s could not startup!", g_prog_name);
+ daemon_quit(SMF_EXIT_ERR_FATAL);
+ }
+
+ debug_print(2, "daemon is running.");
+ /*CONSTCOND*/
+ while (1) {
+ (void) pause();
+ }
+
+ return (SMF_EXIT_OK);
+}
+
+static int
+daemon_init(void)
+{
+ int i, ret;
+ pid_t pid;
+ char pid_str[32];
+
+ if (geteuid() != 0) {
+ debug_print(0, "must be root to execute %s", g_prog_name);
+ return (1);
+ }
+
+ if ((pid = fork()) < 0) {
+ return (1);
+ }
+
+ if (pid > 0) {
+ /* Parent to exit. */
+ exit(SMF_EXIT_OK);
+ }
+
+ (void) setsid();
+ (void) chdir("/");
+ (void) umask(0);
+ (void) closefrom(0);
+ (void) open("/dev/null", O_RDONLY);
+ (void) open("/dev/null", O_WRONLY);
+ (void) dup(1);
+ (void) openlog(g_prog_name, LOG_PID, LOG_DAEMON);
+
+ /*
+ * Create the lock file for singleton
+ */
+ if ((s_pid_fd = open(ACPIHPD_PID_FILE, O_RDWR | O_CREAT, 0644)) < 0) {
+ debug_print(0, "could not create pid file: %s",
+ strerror(errno));
+ return (1);
+ }
+
+ if (lockf(s_pid_fd, F_TLOCK, 0L) < 0) {
+ if (errno == EACCES || errno == EAGAIN) {
+ debug_print(0, "another acpihpd is already running");
+ } else {
+ debug_print(0, "could not lock pid file");
+ }
+
+ return (1);
+ }
+
+ (void) ftruncate(s_pid_fd, 0);
+ i = sprintf(pid_str, "%ld", (long)getpid());
+ while ((ret = write(s_pid_fd, pid_str, i)) != i) {
+ if (errno == EINTR) {
+ continue;
+ }
+ if (ret < 0) {
+ debug_print(0, "pid file write failed: %s",
+ strerror(errno));
+ return (1);
+ }
+ }
+
+ if (set_sig_handler(SIGTERM, (sig_handler_t *)daemon_quit) != 0) {
+ debug_print(2, "could not set signal handler(SIGTERM)");
+ return (1);
+ }
+
+ if (set_sig_handler(SIGQUIT, (sig_handler_t *)daemon_quit) != 0) {
+ debug_print(2, "could not set signal handler(SIGQUIT)");
+ return (1);
+ }
+
+ if (set_sig_handler(SIGINT, (sig_handler_t *)daemon_quit) != 0) {
+ debug_print(2, "could not set signal handler(SIGINT)");
+ return (1);
+ }
+
+ if (set_sig_handler(SIGCHLD, SIG_IGN) != 0) {
+ debug_print(2, "could not set signal handler(SIGCHLD)");
+ return (1);
+ }
+
+ return (0);
+}
+
+static void
+daemon_quit(int signo)
+{
+ int status = 0;
+ id_t pgid;
+
+ debug_print(1, "daemon quit [signal#:%d].", signo);
+
+ acpihpd_fini();
+ (void) set_sig_handler(SIGTERM, SIG_IGN);
+ pgid = getpgrp();
+ (void) kill(-pgid, SIGTERM);
+ (void) close(s_pid_fd);
+ (void) unlink(ACPIHPD_PID_FILE);
+
+ if (signo < 0) {
+ status = signo;
+ }
+ _exit(status);
+}
+
+static int
+set_sig_handler(int sig, sig_handler_t *handler)
+{
+ struct sigaction act;
+
+ act.sa_handler = handler;
+ act.sa_flags = 0;
+ if (sig == SIGCHLD && handler == SIG_IGN) {
+ act.sa_flags |= SA_NOCLDWAIT;
+ }
+
+ (void) sigemptyset(&act.sa_mask);
+ if (sigaction(sig, &act, NULL) < 0) {
+ return (1);
+ }
+
+ return (0);
+}
+
+static int
+acpihpd_init(void)
+{
+ const char *subclass = ESC_DR_REQ;
+
+ debug_print(2, "acpihpd_init");
+
+ if ((s_acpihpd_hdl = sysevent_bind_handle(acpihpd_event)) == NULL) {
+ debug_print(2, "could not bind to sysevent.");
+ return (-1);
+ }
+
+ if (sysevent_subscribe_event(s_acpihpd_hdl, EC_DR, &subclass, 1) != 0) {
+ debug_print(2, "could not subscribe an event.");
+ sysevent_unbind_handle(s_acpihpd_hdl);
+ s_acpihpd_hdl = NULL;
+ return (-1);
+ }
+
+ return (0);
+}
+
+static void
+acpihpd_fini(void)
+{
+ debug_print(2, "acpihpd_fini");
+
+ if (s_acpihpd_hdl != NULL) {
+ sysevent_unsubscribe_event(s_acpihpd_hdl, EC_DR);
+ sysevent_unbind_handle(s_acpihpd_hdl);
+ }
+}
+
+static void
+acpihpd_event(sysevent_t *ev)
+{
+ debug_print(2, "*** got an event ***");
+
+ /* Inform cfgadm of the hot-plug event. */
+ notify_hotplug(ev);
+}
+
+void
+debug_print(int level, const char *fmt, ...)
+{
+ va_list ap;
+ int pri, pr_out = 0;
+
+ if (level <= g_debuglevel) {
+ switch (level) {
+ case 0:
+ pri = LOG_ERR;
+ pr_out = 1;
+ break;
+
+ case 1:
+ pri = LOG_NOTICE;
+ pr_out = 1;
+ break;
+
+ case 2:
+ pri = LOG_DEBUG;
+ pr_out = 1;
+ break;
+ }
+
+ if (pr_out) {
+ va_start(ap, fmt);
+ vsyslog(pri, fmt, ap);
+ va_end(ap);
+ }
+ }
+}
diff --git a/usr/src/cmd/acpihpd/acpihpd.xml b/usr/src/cmd/acpihpd/acpihpd.xml
new file mode 100644
index 0000000000..e8e799de08
--- /dev/null
+++ b/usr/src/cmd/acpihpd/acpihpd.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0"?>
+<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
+<!--
+
+ Copyright (c) 2010, Intel Corporation.
+ All rights reserved.
+
+ CDDL HEADER START
+
+ The contents of this file are subject to the terms of the
+ Common Development and Distribution License (the "License").
+ You may not use this file except in compliance with the License.
+
+ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ or http://www.opensolaris.org/os/licensing.
+ See the License for the specific language governing permissions
+ and limitations under the License.
+
+ When distributing Covered Code, include this CDDL HEADER in each
+ file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ If applicable, add the following below this CDDL HEADER, with the
+ fields enclosed by brackets "[]" replaced with your own identifying
+ information: Portions Copyright [yyyy] [name of copyright owner]
+
+ CDDL HEADER END
+
+ Note:
+ NOTE: This service manifest is not editable; its contents will
+ be overwritten by package or patch operations, including
+ operating system upgrade. Make customizations in a different
+ file.
+-->
+
+<service_bundle type='manifest' name='SUNWacpihpd:acpihpd'>
+
+<service
+ name='platform/i86pc/acpihpd'
+ type='service'
+ version='1'>
+
+ <create_default_instance enabled='true' />
+
+ <single_instance/>
+
+ <!--
+ acpihpd should be started after syseventd is running.
+ -->
+ <dependency
+ name='startup_req'
+ grouping='require_all'
+ restart_on='none'
+ type='service'>
+ <service_fmri value='svc:/system/sysevent' />
+ </dependency>
+
+ <exec_method
+ type='method'
+ name='start'
+ exec='/lib/svc/method/svc-acpihpd'
+ timeout_seconds='60' >
+ <method_context>
+ <method_credential user='root' group='root'
+ privileges='basic,!proc_info,sys_config,sys_mount,sys_devices' />
+ </method_context>
+ </exec_method>
+
+ <exec_method
+ type='method'
+ name='stop'
+ exec=':kill'
+ timeout_seconds='60' >
+ <method_context>
+ <method_credential user='root' group='root' />
+ </method_context>
+ </exec_method>
+
+ <stability value='Unstable' />
+
+ <template>
+ <common_name>
+ <loctext xml:lang='C'>
+ Intel ACPI hot-plug daemon
+ </loctext>
+ </common_name>
+ <documentation>
+ <manpage title='acpihpd' section='1M'
+ manpath='/usr/share/man' />
+ </documentation>
+ </template>
+</service>
+
+</service_bundle>
+
diff --git a/usr/src/cmd/acpihpd/i386/Makefile b/usr/src/cmd/acpihpd/i386/Makefile
new file mode 100644
index 0000000000..4356b38b82
--- /dev/null
+++ b/usr/src/cmd/acpihpd/i386/Makefile
@@ -0,0 +1,37 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# Copyright (c) 2010, Intel Corporation.
+# All rights reserved.
+#
+# cmd/acpihpd/i386/Makefile
+#
+
+include ../Makefile.com
+
+.KEEP_STATE:
+
+install: all $(USR_PSM_LIBS)
+
+include ../Makefile.targ
diff --git a/usr/src/cmd/acpihpd/notify.c b/usr/src/cmd/acpihpd/notify.c
new file mode 100644
index 0000000000..138b1a233d
--- /dev/null
+++ b/usr/src/cmd/acpihpd/notify.c
@@ -0,0 +1,353 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2010, Intel Corporation.
+ * All rights reserved.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <config_admin.h>
+#include <strings.h>
+#include <syslog.h>
+#include <libsysevent.h>
+#include <libdevinfo.h>
+#include <libnvpair.h>
+#include <assert.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stropts.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/sysevent/eventdefs.h>
+#include <sys/sysevent/dr.h>
+#include <sys/sbd_ioctl.h>
+#include <sys/acpidev.h>
+
+#define PMCONFIG_PATH "/usr/sbin/pmconfig"
+
+#define CFGADM_CMD_ASSIGN "assign"
+#define CFGADM_CMD_POWERON "poweron"
+#define CFGADM_CMD_PASSTHRU "passthru"
+
+#define STATUS_INPROGRESS 0
+#define STATUS_SUCCESS 1
+#define STATUS_FAILURE 2
+#define STATUS_NOOP 3
+
+static char *s_status_array[] = {
+ ACPIDEV_CMD_OST_INPROGRESS,
+ ACPIDEV_CMD_OST_SUCCESS,
+ ACPIDEV_CMD_OST_FAILURE,
+ ACPIDEV_CMD_OST_NOOP
+};
+
+extern void debug_print(int, const char *, ...);
+
+/*ARGSUSED*/
+static int
+confirm_no(void *appdata_ptr, const char *message)
+{
+ return (0);
+}
+
+/*ARGSUSED*/
+static int
+message_output(void *appdata_ptr, const char *message)
+{
+ debug_print(2, "cfgadm message: %s", message);
+ return (CFGA_OK);
+}
+
+static char *
+plat_opt_str_alloc(int cmd, char *acpi_event_type, int status)
+{
+ char *opt;
+ size_t len;
+
+ if (cmd == SBD_CMD_PASSTHRU) {
+ len = strlen(s_status_array[status]) +
+ strlen(ACPIDEV_EVENT_TYPE_ATTR_NAME) +
+ strlen(acpi_event_type) + 10;
+ if ((opt = malloc(len)) != NULL) {
+ (void) snprintf(opt, len, "%s %s=%s",
+ s_status_array[status],
+ ACPIDEV_EVENT_TYPE_ATTR_NAME,
+ acpi_event_type);
+ debug_print(2, "plat_opt_str_alloc = '%s'", opt);
+ }
+ } else {
+ len = strlen("platform=''") +
+ strlen(s_status_array[status]) +
+ strlen(ACPIDEV_EVENT_TYPE_ATTR_NAME) +
+ strlen(acpi_event_type) + 10;
+ if ((opt = malloc(len)) != NULL) {
+ (void) snprintf(opt, len, "platform='%s %s=%s'",
+ s_status_array[status],
+ ACPIDEV_EVENT_TYPE_ATTR_NAME,
+ acpi_event_type);
+ debug_print(2, "plat_opt_str_alloc = '%s'", opt);
+ }
+ }
+
+ return (opt);
+}
+
+static int
+cfgadm_cmd_wrapper(int cmd, int apid_num, char **apids,
+ char *acpi_event_type, int status,
+ struct cfga_confirm *confirm, struct cfga_msg *message)
+{
+ cfga_err_t ret;
+ char *plat_opts;
+ char *estrp = NULL;
+
+ assert(apid_num == 1);
+ assert(apids != NULL);
+
+ plat_opts = plat_opt_str_alloc(cmd, acpi_event_type, status);
+ if (plat_opts == NULL) {
+ debug_print(0,
+ "failed to generate platform option string for cfgadm");
+ return (-1);
+ }
+
+ switch (cmd) {
+ case SBD_CMD_CONNECT:
+ ret = config_change_state(CFGA_CMD_CONNECT, apid_num, apids,
+ plat_opts, confirm, message, &estrp, 0);
+ if (ret != CFGA_OK) {
+ debug_print(0, "cfgadm('connect', '%s') failed, "
+ "ret = %d, errstr = '%s'", apids[0], ret, estrp);
+ }
+ break;
+
+ case SBD_CMD_CONFIGURE:
+ ret = config_change_state(CFGA_CMD_CONFIGURE, apid_num, apids,
+ plat_opts, confirm, message, &estrp, 0);
+ if (ret != CFGA_OK) {
+ debug_print(0, "cfgadm('configure', '%s') failed, "
+ "ret = %d, errstr = '%s'", apids[0], ret, estrp);
+ }
+ break;
+
+ case SBD_CMD_ASSIGN:
+ ret = config_private_func(CFGADM_CMD_ASSIGN, apid_num, apids,
+ plat_opts, confirm, message, &estrp, 0);
+ if (ret != CFGA_OK) {
+ debug_print(0, "cfgadm('assign', '%s') failed, "
+ "ret = %d, errstr = '%s'", apids[0], ret, estrp);
+ }
+ break;
+
+ case SBD_CMD_POWERON:
+ ret = config_private_func(CFGADM_CMD_POWERON, apid_num, apids,
+ plat_opts, confirm, message, &estrp, 0);
+ if (ret != CFGA_OK) {
+ debug_print(0, "cfgadm('poweron', '%s') failed, "
+ "ret = %d, errstr = '%s'", apids[0], ret, estrp);
+ }
+ break;
+
+ case SBD_CMD_PASSTHRU:
+ ret = config_private_func(CFGADM_CMD_PASSTHRU, apid_num, apids,
+ plat_opts, confirm, message, &estrp, 0);
+ if (ret != CFGA_OK) {
+ debug_print(0, "cfgadm('passthru', '%s') failed, "
+ "ret = %d, errstr = '%s'", apids[0], ret, estrp);
+ }
+ break;
+
+ default:
+ debug_print(2, "unknown command (%d) to cfgadm_cmd_wrapper()");
+ ret = CFGA_ERROR;
+ break;
+ }
+
+ if (plat_opts != NULL)
+ free(plat_opts);
+
+ return (ret == CFGA_OK ? 0 : -1);
+}
+
+static int
+event_process(char *ap_id, char *req, char *acpi_event_type)
+{
+ char *apids[1];
+ struct cfga_msg message;
+ struct cfga_confirm confirm;
+
+ if (strcmp(req, DR_REQ_INCOMING_RES) != 0) {
+ debug_print(2,
+ "Event is not supported (ap_id = %s, req = %s)",
+ ap_id, req);
+ return (-1);
+ }
+
+ apids[0] = ap_id;
+ (void) memset(&confirm, 0, sizeof (confirm));
+ confirm.confirm = confirm_no;
+ (void) memset(&message, 0, sizeof (message));
+ message.message_routine = message_output;
+
+ if (cfgadm_cmd_wrapper(SBD_CMD_ASSIGN, 1, apids,
+ acpi_event_type, STATUS_NOOP, &confirm, &message) != 0) {
+ goto L_ERR;
+ }
+ syslog(LOG_NOTICE,
+ "board '%s' has been assigned successfully", ap_id);
+ (void) cfgadm_cmd_wrapper(SBD_CMD_PASSTHRU, 1, apids,
+ acpi_event_type, STATUS_INPROGRESS, &confirm, &message);
+
+ if (cfgadm_cmd_wrapper(SBD_CMD_POWERON, 1, apids,
+ acpi_event_type, STATUS_NOOP, &confirm, &message) != 0) {
+ goto L_ERR_SIG;
+ }
+ syslog(LOG_NOTICE,
+ "board '%s' has been powered on successfully", ap_id);
+ (void) cfgadm_cmd_wrapper(SBD_CMD_PASSTHRU, 1, apids,
+ acpi_event_type, STATUS_INPROGRESS, &confirm, &message);
+
+ if (cfgadm_cmd_wrapper(SBD_CMD_CONNECT, 1, apids,
+ acpi_event_type, STATUS_INPROGRESS, &confirm, &message) != 0) {
+ goto L_ERR_SIG;
+ }
+ syslog(LOG_NOTICE,
+ "board '%s' has been connected successfully", ap_id);
+ (void) cfgadm_cmd_wrapper(SBD_CMD_PASSTHRU, 1, apids,
+ acpi_event_type, STATUS_INPROGRESS, &confirm, &message);
+
+ if (cfgadm_cmd_wrapper(SBD_CMD_CONFIGURE, 1, apids,
+ acpi_event_type, STATUS_INPROGRESS, &confirm, &message) != 0) {
+ goto L_ERR_SIG;
+ }
+ syslog(LOG_NOTICE,
+ "board '%s' has been configured successfully", ap_id);
+ (void) cfgadm_cmd_wrapper(SBD_CMD_PASSTHRU, 1, apids,
+ acpi_event_type, STATUS_SUCCESS, &confirm, &message);
+
+ (void) system(PMCONFIG_PATH);
+ syslog(LOG_NOTICE,
+ "board '%s' has been added into system successfully", ap_id);
+
+ return (0);
+
+L_ERR_SIG:
+ (void) cfgadm_cmd_wrapper(SBD_CMD_PASSTHRU, 1, apids,
+ acpi_event_type, STATUS_FAILURE, &confirm, &message);
+L_ERR:
+ syslog(LOG_ERR, "failed to add board '%s' into system", ap_id);
+
+ return (-1);
+}
+
+void
+notify_hotplug(sysevent_t *ev)
+{
+ char *vendor = NULL;
+ nvlist_t *attr_list = NULL;
+ char *class, *subclass;
+ char *ap_id, *req, *acpi_event_type;
+
+ vendor = sysevent_get_vendor_name(ev);
+ debug_print(2, "message_vendor = '%s'", vendor ? vendor : "unknown");
+ if (vendor == NULL || strcmp(vendor, SUNW_VENDOR) != 0) {
+ debug_print(2,
+ "vendor id of message is not '%s'", SUNW_VENDOR);
+ goto L_EXIT;
+ }
+
+ class = sysevent_get_class_name(ev);
+ debug_print(2, "message_class = '%s'", class ? class : "unknown");
+ if (class == NULL || strcmp(class, EC_DR) != 0) {
+ debug_print(2, "class of message is not '%s'", EC_DR);
+ goto L_EXIT;
+ }
+
+ subclass = sysevent_get_subclass_name(ev);
+ debug_print(2,
+ "message_subclass = '%s'", subclass ? subclass : "unknown");
+ if (subclass == NULL || strcmp(subclass, ESC_DR_REQ) != 0) {
+ debug_print(2,
+ "subclass of message is not '%s'", ESC_DR_REQ);
+ goto L_EXIT;
+ }
+
+ if (sysevent_get_attr_list(ev, &attr_list) != 0) {
+ debug_print(2,
+ "can't retrieve attribute list from DR message");
+ goto L_EXIT;
+ }
+
+ if (nvlist_lookup_string(attr_list, DR_AP_ID, &ap_id) != 0) {
+ debug_print(2,
+ "can't retrieve '%s' property from attribute list",
+ DR_AP_ID);
+ goto L_EXIT;
+ }
+ debug_print(2, "%s = '%s'", DR_AP_ID, ap_id ? ap_id : "<null>");
+ if ((ap_id == NULL) || (strlen(ap_id) == 0)) {
+ debug_print(2, "'%s' property in message is NULL", DR_AP_ID);
+ goto L_EXIT;
+ }
+
+ if (nvlist_lookup_string(attr_list, DR_REQ_TYPE, &req) != 0) {
+ debug_print(2,
+ "can't retrieve '%s' property from attribute list",
+ DR_REQ_TYPE);
+ goto L_EXIT;
+ }
+ debug_print(2, "%s = '%s'", DR_REQ_TYPE, req ? req : "<null>");
+ if ((req == NULL) || (strlen(req) == 0)) {
+ debug_print(2, "'%s' property in message is NULL", DR_REQ_TYPE);
+ goto L_EXIT;
+ }
+
+ if (nvlist_lookup_string(attr_list, ACPIDEV_EVENT_TYPE_ATTR_NAME,
+ &acpi_event_type) != 0) {
+ debug_print(2,
+ "can't retrieve '%s' property from attribute list",
+ ACPIDEV_EVENT_TYPE_ATTR_NAME);
+ goto L_EXIT;
+ }
+ debug_print(2, "%s = '%s'", ACPIDEV_EVENT_TYPE_ATTR_NAME,
+ acpi_event_type ? acpi_event_type : "<null>");
+ if ((acpi_event_type == NULL) || (strlen(acpi_event_type) == 0)) {
+ debug_print(2, "'%s' property in message is NULL",
+ ACPIDEV_EVENT_TYPE_ATTR_NAME);
+ goto L_EXIT;
+ }
+
+ (void) event_process(ap_id, req, acpi_event_type);
+
+L_EXIT:
+ if (vendor != NULL) {
+ free(vendor);
+ }
+
+ if (attr_list != NULL) {
+ nvlist_free(attr_list);
+ }
+
+ /* No need to free class & subclass. */
+}
diff --git a/usr/src/cmd/acpihpd/svc-acpihpd b/usr/src/cmd/acpihpd/svc-acpihpd
new file mode 100644
index 0000000000..f45f05ed06
--- /dev/null
+++ b/usr/src/cmd/acpihpd/svc-acpihpd
@@ -0,0 +1,39 @@
+#!/bin/sh
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright (c) 2010, Intel Corporation.
+# All rights reserved.
+#
+
+. /lib/svc/share/smf_include.sh
+
+PLATFORM="i86pc"
+ACPIHPD=/usr/platform/${PLATFORM}/lib/acpihpd
+
+/usr/sbin/prtconf -D /devices/fw/acpidr@0 > /dev/null 2>&1
+if [ $? -ne 0 ]; then
+ svcadm disable -t $SMF_FMRI
+ sleep 5&
+ exit $SMF_EXIT_OK
+fi
+
+$ACPIHPD && exit $SMF_EXIT_OK || exit $SMF_EXIT_ERR_FATAL