summaryrefslogtreecommitdiff
path: root/usr/src/cmd/acpihpd
diff options
context:
space:
mode:
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