diff options
Diffstat (limited to 'usr/src/cmd/acpihpd')
-rw-r--r-- | usr/src/cmd/acpihpd/Makefile | 62 | ||||
-rw-r--r-- | usr/src/cmd/acpihpd/Makefile.com | 46 | ||||
-rw-r--r-- | usr/src/cmd/acpihpd/Makefile.targ | 62 | ||||
-rw-r--r-- | usr/src/cmd/acpihpd/acpihpd.c | 325 | ||||
-rw-r--r-- | usr/src/cmd/acpihpd/acpihpd.xml | 93 | ||||
-rw-r--r-- | usr/src/cmd/acpihpd/i386/Makefile | 37 | ||||
-rw-r--r-- | usr/src/cmd/acpihpd/notify.c | 353 | ||||
-rw-r--r-- | usr/src/cmd/acpihpd/svc-acpihpd | 39 |
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 |