diff options
author | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
---|---|---|
committer | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
commit | 7c478bd95313f5f23a4c958a745db2134aa03244 (patch) | |
tree | c871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/lib/librcm | |
download | illumos-gate-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz |
OpenSolaris Launch
Diffstat (limited to 'usr/src/lib/librcm')
-rw-r--r-- | usr/src/lib/librcm/Makefile | 68 | ||||
-rw-r--r-- | usr/src/lib/librcm/Makefile.com | 51 | ||||
-rw-r--r-- | usr/src/lib/librcm/amd64/Makefile | 32 | ||||
-rw-r--r-- | usr/src/lib/librcm/i386/Makefile | 31 | ||||
-rw-r--r-- | usr/src/lib/librcm/librcm.c | 1552 | ||||
-rw-r--r-- | usr/src/lib/librcm/librcm.h | 172 | ||||
-rw-r--r-- | usr/src/lib/librcm/librcm_event.c | 406 | ||||
-rw-r--r-- | usr/src/lib/librcm/librcm_event.h | 53 | ||||
-rw-r--r-- | usr/src/lib/librcm/librcm_impl.h | 163 | ||||
-rw-r--r-- | usr/src/lib/librcm/llib-lrcm | 87 | ||||
-rw-r--r-- | usr/src/lib/librcm/sparc/Makefile | 31 | ||||
-rw-r--r-- | usr/src/lib/librcm/sparcv9/Makefile | 32 | ||||
-rw-r--r-- | usr/src/lib/librcm/spec/Makefile | 30 | ||||
-rw-r--r-- | usr/src/lib/librcm/spec/Makefile.targ | 35 | ||||
-rw-r--r-- | usr/src/lib/librcm/spec/amd64/Makefile | 42 | ||||
-rw-r--r-- | usr/src/lib/librcm/spec/i386/Makefile | 42 | ||||
-rw-r--r-- | usr/src/lib/librcm/spec/rcm.spec | 324 | ||||
-rw-r--r-- | usr/src/lib/librcm/spec/rcm_event.spec | 45 | ||||
-rw-r--r-- | usr/src/lib/librcm/spec/sparc/Makefile | 44 | ||||
-rw-r--r-- | usr/src/lib/librcm/spec/sparcv9/Makefile | 43 | ||||
-rw-r--r-- | usr/src/lib/librcm/spec/versions | 41 |
21 files changed, 3324 insertions, 0 deletions
diff --git a/usr/src/lib/librcm/Makefile b/usr/src/lib/librcm/Makefile new file mode 100644 index 0000000000..88edc674d8 --- /dev/null +++ b/usr/src/lib/librcm/Makefile @@ -0,0 +1,68 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 +# +# +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright (c) 1999-2000 by Sun Microsystems, Inc. +# All rights reserved. +# +# lib/librcm/Makefile +# +# +include ../Makefile.lib + +# +# 64 bit build is turned off pending libsysevent conversion to 64 bit +# +SUBDIRS = spec .WAIT $(MACH) $(BUILD64) $(MACH64) + +# conditional assignments +all := TARGET= all +install := TARGET= install +clean := TARGET= clean +clobber := TARGET= clobber +lint := TARGET= lint +test := TARGET= test + +# definitions for install_h target +HDRS= librcm.h librcm_impl.h librcm_event.h +ROOTHDRDIR= $(ROOT)/usr/include +ROOTHDRS= $(HDRS:%=$(ROOTHDRDIR)/%) +CHECKHDRS= $(HDRS:%.h=%.check) + +.KEEP_STATE: + +all install clean clobber lint: $(SUBDIRS) + +# install rule for install_h target + +$(ROOTHDRDIR)/%: % + $(INS.file) + +install_h: $(ROOTHDRS) + +check: $(CHECKHDRS) + +$(MACH) $(MACH64) spec: FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +FRC: diff --git a/usr/src/lib/librcm/Makefile.com b/usr/src/lib/librcm/Makefile.com new file mode 100644 index 0000000000..81c6440ede --- /dev/null +++ b/usr/src/lib/librcm/Makefile.com @@ -0,0 +1,51 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2005 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +LIBRARY= librcm.a +VERS= .1 +OBJECTS= librcm.o librcm_event.o + +include ../../Makefile.lib + +LIBS = $(DYNLIB) $(LINTLIB) +LDLIBS += -lc -lnvpair +$(LINTLIB) := SRCS = ../llib-lrcm + +SRCDIR = .. +MAPDIR = ../spec/$(TRANSMACH) +SPECMAPFILE = $(MAPDIR)/mapfile + +CFLAGS += $(CCVERBOSE) + +.KEEP_STATE: + +all: $(LIBS) + +lint: lintcheck + +include ../../Makefile.targ diff --git a/usr/src/lib/librcm/amd64/Makefile b/usr/src/lib/librcm/amd64/Makefile new file mode 100644 index 0000000000..cb39a2beff --- /dev/null +++ b/usr/src/lib/librcm/amd64/Makefile @@ -0,0 +1,32 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.com +include ../../Makefile.lib.64 + +install: all $(ROOTLIBS64) $(ROOTLINKS64) diff --git a/usr/src/lib/librcm/i386/Makefile b/usr/src/lib/librcm/i386/Makefile new file mode 100644 index 0000000000..af76f5ab90 --- /dev/null +++ b/usr/src/lib/librcm/i386/Makefile @@ -0,0 +1,31 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.com + +install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/librcm/librcm.c b/usr/src/lib/librcm/librcm.c new file mode 100644 index 0000000000..381cfa8a65 --- /dev/null +++ b/usr/src/lib/librcm/librcm.c @@ -0,0 +1,1552 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "librcm_impl.h" +#include "librcm_event.h" + +#ifdef DEBUG +static int rcm_debug = 1; +#define dprintf(args) if (rcm_debug) (void) fprintf args +#else +#define dprintf(args) /* nothing */ +#endif /* DEBUG */ + +static int extract_info(nvlist_t *, rcm_info_t **); +static int rcm_daemon_is_alive(); +static int rcm_common(int, rcm_handle_t *, char **, uint_t, void *, + rcm_info_t **); +static int rcm_direct_call(int, rcm_handle_t *, char **, uint_t, void *, + rcm_info_t **); +static int rcm_daemon_call(int, rcm_handle_t *, char **, uint_t, void *, + rcm_info_t **); +static int rcm_generate_nvlist(int, rcm_handle_t *, char **, uint_t, void *, + char **, size_t *); +static int rcm_check_permission(void); + +/* + * Allocate a handle structure + */ +/*ARGSUSED2*/ +int +rcm_alloc_handle(char *modname, uint_t flag, void *arg, rcm_handle_t **hdp) +{ + rcm_handle_t *hd; + void *temp; + char namebuf[MAXPATHLEN]; + + if ((hdp == NULL) || (flag & ~RCM_ALLOC_HDL_MASK)) { + errno = EINVAL; + return (RCM_FAILURE); + } + + if (rcm_check_permission() == 0) { + errno = EPERM; + return (RCM_FAILURE); + } + + if ((hd = calloc(1, sizeof (*hd))) == NULL) { + return (RCM_FAILURE); + } + + if (modname) { + (void) snprintf(namebuf, MAXPATHLEN, "%s%s", modname, + RCM_MODULE_SUFFIX); + + if ((hd->modname = strdup(namebuf)) == NULL) { + free(hd); + return (RCM_FAILURE); + } + + if ((temp = rcm_module_open(namebuf)) == NULL) { + free(hd->modname); + free(hd); + errno = EINVAL; + return (RCM_FAILURE); + } + + rcm_module_close(temp); + } + + if (flag & RCM_NOPID) { + hd->pid = (pid_t)0; + } else { + hd->pid = (pid_t)getpid(); + } + + *hdp = hd; + return (RCM_SUCCESS); +} + +/* free handle structure */ +int +rcm_free_handle(rcm_handle_t *hd) +{ + if (hd == NULL) { + errno = EINVAL; + return (RCM_FAILURE); + } + + if (hd->modname) { + free(hd->modname); + } + + free(hd); + return (RCM_SUCCESS); +} + + +/* + * Operations which require daemon processing + */ + +/* get registration and DR information from rcm_daemon */ +int +rcm_get_info(rcm_handle_t *hd, char *rsrcname, uint_t flag, rcm_info_t **infop) +{ + char *rsrcnames[2]; + + if ((flag & ~RCM_GET_INFO_MASK) || (infop == NULL)) { + errno = EINVAL; + return (RCM_FAILURE); + } + + /* + * rsrcname may be NULL if requesting dr operations or modinfo + */ + if ((rsrcname == NULL) && + ((flag & RCM_DR_OPERATION|RCM_MOD_INFO) == 0)) { + errno = EINVAL; + return (RCM_FAILURE); + } + + rsrcnames[0] = rsrcname; + rsrcnames[1] = NULL; + + return (rcm_common(CMD_GETINFO, hd, rsrcnames, flag, NULL, infop)); +} + +/* get registration and DR information from rcm_daemon (list version) */ +int +rcm_get_info_list(rcm_handle_t *hd, char **rsrcnames, uint_t flag, + rcm_info_t **infop) +{ + /* Requesting the current DR operations with a *list() is invalid */ + if ((flag & RCM_DR_OPERATION) || (flag & RCM_MOD_INFO)) { + errno = EINVAL; + return (RCM_FAILURE); + } + + return (rcm_common(CMD_GETINFO, hd, rsrcnames, flag, NULL, infop)); +} + +/* request to offline a resource before DR removal */ +int +rcm_request_offline(rcm_handle_t *hd, char *rsrcname, uint_t flag, + rcm_info_t **infop) +{ + char *rsrcnames[2]; + + rsrcnames[0] = rsrcname; + rsrcnames[1] = NULL; + + return (rcm_request_offline_list(hd, rsrcnames, flag, infop)); +} + +/* request to offline a resource before DR removal (list version) */ +int +rcm_request_offline_list(rcm_handle_t *hd, char **rsrcnames, uint_t flag, + rcm_info_t **infop) +{ + if (flag & ~RCM_REQUEST_MASK) { + errno = EINVAL; + return (RCM_FAILURE); + } + + return (rcm_common(CMD_OFFLINE, hd, rsrcnames, flag, NULL, infop)); +} + +/* cancel offline request and allow apps to use rsrcname */ +int +rcm_notify_online(rcm_handle_t *hd, char *rsrcname, uint_t flag, + rcm_info_t **infop) +{ + char *rsrcnames[2]; + + rsrcnames[0] = rsrcname; + rsrcnames[1] = NULL; + + return (rcm_notify_online_list(hd, rsrcnames, flag, infop)); +} + +/* cancel offline and allow apps to use resources (list version) */ +int +rcm_notify_online_list(rcm_handle_t *hd, char **rsrcnames, uint_t flag, + rcm_info_t **infop) +{ + if (flag & ~RCM_NOTIFY_MASK) { + errno = EINVAL; + return (RCM_FAILURE); + } + + return (rcm_common(CMD_ONLINE, hd, rsrcnames, flag, NULL, infop)); +} + +/* notify that rsrcname has been removed */ +int +rcm_notify_remove(rcm_handle_t *hd, char *rsrcname, uint_t flag, + rcm_info_t **infop) +{ + char *rsrcnames[2]; + + rsrcnames[0] = rsrcname; + rsrcnames[1] = NULL; + + return (rcm_notify_remove_list(hd, rsrcnames, flag, infop)); +} + +/* notify that resrouces have been removed (list form) */ +int +rcm_notify_remove_list(rcm_handle_t *hd, char **rsrcnames, uint_t flag, + rcm_info_t **infop) +{ + if (flag & ~RCM_NOTIFY_MASK) { + errno = EINVAL; + return (RCM_FAILURE); + } + + return (rcm_common(CMD_REMOVE, hd, rsrcnames, flag, NULL, infop)); +} + +/* request for permission to suspend resource of interval time */ +int +rcm_request_suspend(rcm_handle_t *hd, char *rsrcname, uint_t flag, + timespec_t *interval, rcm_info_t **infop) +{ + char *rsrcnames[2]; + + rsrcnames[0] = rsrcname; + rsrcnames[1] = NULL; + + return (rcm_request_suspend_list(hd, rsrcnames, flag, interval, infop)); +} + +/* request for permission to suspend resource of interval time (list form) */ +int +rcm_request_suspend_list(rcm_handle_t *hd, char **rsrcnames, uint_t flag, + timespec_t *interval, rcm_info_t **infop) +{ + if ((flag & ~RCM_REQUEST_MASK) || (interval == NULL) || + (interval->tv_sec < 0) || (interval->tv_nsec < 0)) { + errno = EINVAL; + return (RCM_FAILURE); + } + + return (rcm_common(CMD_SUSPEND, hd, rsrcnames, flag, (void *)interval, + infop)); +} + +/* notify apps of the completion of resource suspension */ +int +rcm_notify_resume(rcm_handle_t *hd, char *rsrcname, uint_t flag, + rcm_info_t **infop) +{ + char *rsrcnames[2]; + + rsrcnames[0] = rsrcname; + rsrcnames[1] = NULL; + + return (rcm_notify_resume_list(hd, rsrcnames, flag, infop)); +} + +/* notify apps of the completion of resource suspension (list form) */ +int +rcm_notify_resume_list(rcm_handle_t *hd, char **rsrcnames, uint_t flag, + rcm_info_t **infop) +{ + if (flag & ~(RCM_NOTIFY_MASK | RCM_SUSPENDED)) { + errno = EINVAL; + return (RCM_FAILURE); + } + + return (rcm_common(CMD_RESUME, hd, rsrcnames, flag, NULL, infop)); +} + +/* request a capacity change from apps */ +int +rcm_request_capacity_change(rcm_handle_t *hd, char *rsrcname, uint_t flag, + nvlist_t *nvl, rcm_info_t **infop) +{ + int rv; + char *rsrcnames[2]; + + if ((nvl == NULL) || (flag & ~RCM_REQUEST_MASK)) { + errno = EINVAL; + return (RCM_FAILURE); + } + + rsrcnames[0] = rsrcname; + rsrcnames[1] = NULL; + + rv = rcm_common(CMD_REQUEST_CHANGE, hd, rsrcnames, flag, (void *)nvl, + infop); + + return (rv); +} + +/* notify apps of a capacity change */ +int +rcm_notify_capacity_change(rcm_handle_t *hd, char *rsrcname, uint_t flag, + nvlist_t *nvl, rcm_info_t **infop) +{ + int rv; + char *rsrcnames[2]; + + if ((nvl == NULL) || (flag & ~RCM_REQUEST_MASK)) { + errno = EINVAL; + return (RCM_FAILURE); + } + + rsrcnames[0] = rsrcname; + rsrcnames[1] = NULL; + + rv = rcm_common(CMD_NOTIFY_CHANGE, hd, rsrcnames, flag, (void *)nvl, + infop); + + return (rv); +} + +/* notify apps of an event */ +int +rcm_notify_event(rcm_handle_t *hd, char *rsrcname, uint_t flag, nvlist_t *nvl, + rcm_info_t **infop) +{ + int rv; + char *rsrcnames[2]; + + /* No flags are defined yet for rcm_notify_event() */ + if ((nvl == NULL) || (flag != 0)) { + errno = EINVAL; + return (RCM_FAILURE); + } + + rsrcnames[0] = rsrcname; + rsrcnames[1] = NULL; + + rv = rcm_common(CMD_EVENT, hd, rsrcnames, 0, (void *)nvl, infop); + + return (rv); +} + +/* + * Register to receive capacity changes. This requires a module to exist in + * module directory. It should be called prior to using a new resource. + */ +/* ARGSUSED */ +int +rcm_register_capacity(rcm_handle_t *hd, char *rsrcname, uint_t flag, + rcm_info_t **infop) +{ + char *rsrcnames[2]; + + if (flag & ~RCM_REGISTER_MASK) { + errno = EINVAL; + return (RCM_FAILURE); + } + + flag |= RCM_REGISTER_CAPACITY; + + rsrcnames[0] = rsrcname; + rsrcnames[1] = NULL; + + return (rcm_common(CMD_REGISTER, hd, rsrcnames, flag, NULL, NULL)); +} + +/* unregister interest in capacity changes */ +int +rcm_unregister_capacity(rcm_handle_t *hd, char *rsrcname, uint_t flag) +{ + char *rsrcnames[2]; + + if (flag & ~RCM_REGISTER_MASK) { + errno = EINVAL; + return (RCM_FAILURE); + } + + flag |= RCM_REGISTER_CAPACITY; + + rsrcnames[0] = rsrcname; + rsrcnames[1] = NULL; + + return (rcm_common(CMD_UNREGISTER, hd, rsrcnames, flag, NULL, NULL)); +} + +/* + * Register to receive events. This requires a module to exist in module + * directory. It should be called prior to using a new resource. + */ +/* ARGSUSED */ +int +rcm_register_event(rcm_handle_t *hd, char *rsrcname, uint_t flag, + rcm_info_t **infop) +{ + char *rsrcnames[2]; + + if (flag & ~RCM_REGISTER_MASK) { + errno = EINVAL; + return (RCM_FAILURE); + } + + flag |= RCM_REGISTER_EVENT; + + rsrcnames[0] = rsrcname; + rsrcnames[1] = NULL; + + return (rcm_common(CMD_REGISTER, hd, rsrcnames, flag, NULL, NULL)); +} + +/* unregister interest in events */ +int +rcm_unregister_event(rcm_handle_t *hd, char *rsrcname, uint_t flag) +{ + char *rsrcnames[2]; + + if (flag & ~RCM_REGISTER_MASK) { + errno = EINVAL; + return (RCM_FAILURE); + } + + flag |= RCM_REGISTER_EVENT; + + rsrcnames[0] = rsrcname; + rsrcnames[1] = NULL; + + return (rcm_common(CMD_UNREGISTER, hd, rsrcnames, flag, NULL, NULL)); +} + +/* + * Register interest in a resource. This requires a module to exist in module + * directory. It should be called prior to using a new resource. + * + * Registration may be denied if it is presently locked by a DR operation. + */ +/* ARGSUSED */ +int +rcm_register_interest(rcm_handle_t *hd, char *rsrcname, uint_t flag, + rcm_info_t **infop) +{ + char *rsrcnames[2]; + + if (flag & ~RCM_REGISTER_MASK) { + errno = EINVAL; + return (RCM_FAILURE); + } + + flag |= RCM_REGISTER_DR; + + rsrcnames[0] = rsrcname; + rsrcnames[1] = NULL; + + return (rcm_common(CMD_REGISTER, hd, rsrcnames, flag, NULL, NULL)); +} + +/* unregister interest in rsrcname */ +int +rcm_unregister_interest(rcm_handle_t *hd, char *rsrcname, uint_t flag) +{ + char *rsrcnames[2]; + + if (flag & ~RCM_REGISTER_MASK) { + errno = EINVAL; + return (RCM_FAILURE); + } + + flag |= RCM_REGISTER_DR; + + rsrcnames[0] = rsrcname; + rsrcnames[1] = NULL; + + return (rcm_common(CMD_UNREGISTER, hd, rsrcnames, flag, NULL, NULL)); +} + +/* get the current state of a resource */ +int +rcm_get_rsrcstate(rcm_handle_t *hd, char *rsrcname, int *statep) +{ + int result; + int flag = 0; + rcm_info_t *infop = NULL; + rcm_info_tuple_t *tuple = NULL; + char *rsrcnames[2]; + + if (statep == NULL) { + errno = EINVAL; + return (RCM_FAILURE); + } + + rsrcnames[0] = rsrcname; + rsrcnames[1] = NULL; + + result = rcm_common(CMD_GETSTATE, hd, rsrcnames, flag, NULL, &infop); + + /* + * A successful result implies the presence of exactly one RCM info + * tuple containing the state of this resource (a combination of each + * client's resources). If that's not true, change the result to + * RCM_FAILURE. + */ + if (result == RCM_SUCCESS) { + if ((infop == NULL) || + ((tuple = rcm_info_next(infop, NULL)) == NULL) || + (rcm_info_next(infop, tuple) != NULL)) { + result = RCM_FAILURE; + } else if (infop && tuple) { + *statep = rcm_info_state(tuple); + } + } + + if (infop) + rcm_free_info(infop); + + return (result); +} + +/* + * RCM helper functions exposed to librcm callers. + */ + +/* Free linked list of registration info */ +void +rcm_free_info(rcm_info_t *info) +{ + while (info) { + rcm_info_t *tmp = info->next; + + if (info->info) + nvlist_free(info->info); + free(info); + + info = tmp; + } +} + +/* return the next tuple in the info structure */ +rcm_info_tuple_t * +rcm_info_next(rcm_info_t *info, rcm_info_tuple_t *tuple) +{ + if (info == NULL) { + errno = EINVAL; + return (NULL); + } + + if (tuple == NULL) { + return ((rcm_info_tuple_t *)info); + } + return ((rcm_info_tuple_t *)tuple->next); +} + +/* return resource name */ +const char * +rcm_info_rsrc(rcm_info_tuple_t *tuple) +{ + char *rsrcname = NULL; + + if (tuple == NULL || tuple->info == NULL) { + errno = EINVAL; + return (NULL); + } + + if (errno = nvlist_lookup_string(tuple->info, RCM_RSRCNAME, &rsrcname)) + return (NULL); + + return (rsrcname); +} + +const char * +rcm_info_info(rcm_info_tuple_t *tuple) +{ + char *info = NULL; + + if (tuple == NULL || tuple->info == NULL) { + errno = EINVAL; + return (NULL); + } + + if (errno = nvlist_lookup_string(tuple->info, RCM_CLIENT_INFO, &info)) + return (NULL); + + return (info); +} + +const char * +rcm_info_error(rcm_info_tuple_t *tuple) +{ + char *errstr = NULL; + + if (tuple == NULL || tuple->info == NULL) { + errno = EINVAL; + return (NULL); + } + + if (errno = nvlist_lookup_string(tuple->info, RCM_CLIENT_ERROR, + &errstr)) + return (NULL); + + return (errstr); +} + +/* return info string in the tuple */ +const char * +rcm_info_modname(rcm_info_tuple_t *tuple) +{ + char *modname = NULL; + + if (tuple == NULL || tuple->info == NULL) { + errno = EINVAL; + return (NULL); + } + + if (errno = nvlist_lookup_string(tuple->info, RCM_CLIENT_MODNAME, + &modname)) + return (NULL); + + return (modname); +} + +/* return client pid in the tuple */ +pid_t +rcm_info_pid(rcm_info_tuple_t *tuple) +{ + uint64_t pid64 = (uint64_t)0; + + if (tuple == NULL || tuple->info == NULL) { + errno = EINVAL; + return ((pid_t)0); + } + + if (errno = nvlist_lookup_uint64(tuple->info, RCM_CLIENT_ID, &pid64)) + return ((pid_t)0); + + return ((pid_t)pid64); +} + +/* return client state in the tuple */ +int +rcm_info_state(rcm_info_tuple_t *tuple) +{ + int state; + + if (tuple == NULL || tuple->info == NULL) { + errno = EINVAL; + return (RCM_STATE_UNKNOWN); + } + + if (errno = nvlist_lookup_int32(tuple->info, RCM_RSRCSTATE, &state)) + return (RCM_STATE_UNKNOWN); + + return (state); +} + +/* return the generic properties in the tuple */ +nvlist_t * +rcm_info_properties(rcm_info_tuple_t *tuple) +{ + char *buf; + uint_t buflen; + nvlist_t *nvl; + + if (tuple == NULL || tuple->info == NULL) { + errno = EINVAL; + return (NULL); + } + + if (errno = nvlist_lookup_byte_array(tuple->info, RCM_CLIENT_PROPERTIES, + (uchar_t **)&buf, &buflen)) + return (NULL); + + if (errno = nvlist_unpack(buf, buflen, &nvl, 0)) { + free(buf); + return (NULL); + } + + return (nvl); +} + +/* + * return operation sequence number + * + * This is private. Called by rcmctl only for testing purposes. + */ +int +rcm_info_seqnum(rcm_info_tuple_t *tuple) +{ + int seqnum; + + if (tuple == NULL || tuple->info == NULL) { + errno = EINVAL; + return (-1); + } + + if (errno = nvlist_lookup_int32(tuple->info, RCM_SEQ_NUM, &seqnum)) + return (-1); + + return (seqnum); +} + + +/* + * The following interfaces are PRIVATE to the RCM framework. They are not + * declared static because they are called by rcm_daemon. + */ + +/* + * Invoke shell to execute command in MT safe manner. + * Returns wait status or -1 on error. + */ +int +rcm_exec_cmd(char *cmd) +{ + pid_t pid; + int status, w; + char *argvec[] = {"sh", "-c", NULL, NULL}; + + argvec[2] = cmd; + if ((pid = fork1()) == 0) { + (void) execv("/bin/sh", argvec); + _exit(127); + } else if (pid == -1) { + return (-1); + } + + do { + w = waitpid(pid, &status, 0); + } while (w == -1 && errno == EINTR); + + return ((w == -1) ? w : status); +} + +/* Append info at the very end */ +int +rcm_append_info(rcm_info_t **head, rcm_info_t *info) +{ + rcm_info_t *tuple; + + if (head == NULL) { + errno = EINVAL; + return (RCM_FAILURE); + } + + if ((tuple = *head) == NULL) { + *head = info; + return (RCM_SUCCESS); + } + + while (tuple->next) { + tuple = tuple->next; + } + tuple->next = info; + return (RCM_SUCCESS); +} + +/* get rcm module and rcm script directory names */ + +#define N_MODULE_DIR 3 /* search 3 directories for modules */ +#define MODULE_DIR_HW "/usr/platform/%s/lib/rcm/modules/" +#define MODULE_DIR_GEN "/usr/lib/rcm/modules/" + +#define N_SCRIPT_DIR 4 /* search 4 directories for scripts */ +#define SCRIPT_DIR_HW "/usr/platform/%s/lib/rcm/scripts/" +#define SCRIPT_DIR_GEN "/usr/lib/rcm/scripts/" +#define SCRIPT_DIR_ETC "/etc/rcm/scripts/" + + +char * +rcm_module_dir(uint_t dirnum) +{ + if (dirnum < N_MODULE_DIR) + return (rcm_dir(dirnum, NULL)); + else + return (NULL); +} + +char * +rcm_script_dir(uint_t dirnum) +{ + if (dirnum < N_SCRIPT_DIR) + return (rcm_dir(dirnum + N_MODULE_DIR, NULL)); + else + return (NULL); +} + +char * +rcm_dir(uint_t dirnum, int *rcm_script) +{ + static char dir_name[N_MODULE_DIR + N_SCRIPT_DIR][MAXPATHLEN]; + + char infobuf[MAXPATHLEN]; + + if (dirnum >= (N_MODULE_DIR + N_SCRIPT_DIR)) + return (NULL); + + if (dir_name[0][0] == '\0') { + /* + * construct the module directory names + */ + if (sysinfo(SI_PLATFORM, infobuf, MAXPATHLEN) == -1) { + dprintf((stderr, "sysinfo %s\n", strerror(errno))); + return (NULL); + } else { + if (snprintf(dir_name[0], MAXPATHLEN, MODULE_DIR_HW, + infobuf) >= MAXPATHLEN || + snprintf(dir_name[N_MODULE_DIR + 1], MAXPATHLEN, + SCRIPT_DIR_HW, infobuf) >= MAXPATHLEN) { + dprintf((stderr, + "invalid module or script directory for " + "platform %s\n", infobuf)); + return (NULL); + } + } + + if (sysinfo(SI_MACHINE, infobuf, MAXPATHLEN) == -1) { + dprintf((stderr, "sysinfo %s\n", strerror(errno))); + return (NULL); + } else { + if (snprintf(dir_name[1], MAXPATHLEN, MODULE_DIR_HW, + infobuf) >= MAXPATHLEN || + snprintf(dir_name[N_MODULE_DIR + 2], MAXPATHLEN, + SCRIPT_DIR_HW, infobuf) >= MAXPATHLEN) { + dprintf((stderr, + "invalid module or script directory for " + "machine type %s\n", infobuf)); + return (NULL); + } + } + + if (strlcpy(dir_name[2], MODULE_DIR_GEN, MAXPATHLEN) >= + MAXPATHLEN || + strlcpy(dir_name[N_MODULE_DIR + 3], SCRIPT_DIR_GEN, + MAXPATHLEN) >= MAXPATHLEN || + strlcpy(dir_name[N_MODULE_DIR + 0], SCRIPT_DIR_ETC, + MAXPATHLEN) >= MAXPATHLEN) { + dprintf((stderr, + "invalid module or script generic directory\n")); + return (NULL); + } + } + + if (rcm_script) + *rcm_script = (dirnum < N_MODULE_DIR) ? 0 : 1; + + return (dir_name[dirnum]); +} + +/* + * Find the directory where the script is located. + * If the script is found return a pointer to the directory where the + * script was found otherwise return NULL. + */ +char * +rcm_get_script_dir(char *script_name) +{ + uint_t i; + char *dir_name; + char path[MAXPATHLEN]; + struct stat stats; + + for (i = 0; (dir_name = rcm_script_dir(i)) != NULL; i++) { + if (snprintf(path, MAXPATHLEN, "%s%s", dir_name, script_name) + >= MAXPATHLEN) { + dprintf((stderr, "invalid script %s skipped\n", + script_name)); + continue; + } + if (stat(path, &stats) == 0) + return (dir_name); + } + + return (NULL); +} + +/* + * Returns 1 if the filename is an rcm script. + * Returns 0 if the filename is an rcm module. + */ +int +rcm_is_script(char *filename) +{ + char *tmp; + + if (((tmp = strstr(filename, RCM_MODULE_SUFFIX)) != NULL) && + (tmp[strlen(RCM_MODULE_SUFFIX)] == '\0')) + return (0); + else + return (1); +} + +/* Locate the module and call dlopen */ +void * +rcm_module_open(char *modname) +{ + unsigned i; + char *dir_name; + void *dlhandle = NULL; + char modpath[MAXPATHLEN]; + +#ifdef DEBUG + struct stat sbuf; +#endif + + /* + * dlopen the module + */ + for (i = 0; (dir_name = rcm_module_dir(i)) != NULL; i++) { + if (snprintf(modpath, MAXPATHLEN, "%s%s", dir_name, modname) + >= MAXPATHLEN) { + dprintf((stderr, "invalid module %s skipped\n", + modname)); + continue; + } + + if ((dlhandle = dlopen(modpath, RTLD_LAZY)) != NULL) { + return (dlhandle); + } + + dprintf((stderr, "failure (dlopen=%s)\n", dlerror())); +#ifdef DEBUG + if (stat(modpath, &sbuf) == 0) { + (void) fprintf(stderr, "%s is not a valid module\n", + modpath); + } +#endif + } + + dprintf((stderr, "module %s not found\n", modname)); + return (NULL); +} + +/* dlclose module */ +void +rcm_module_close(void *dlhandle) +{ + if (dlclose(dlhandle) == 0) + return; + + dprintf((stderr, "dlclose: %s\n", dlerror())); +} + + +/* + * stub implementation of rcm_log_message allows dlopen of rcm modules + * to proceed in absence of rcm_daemon. + * + * This definition is interposed by the definition in rcm_daemon because of the + * default search order implemented by the linker and dlsym(). All RCM modules + * will see the daemon version when loaded by the rcm_daemon. + */ +/* ARGSUSED */ +void +rcm_log_message(int level, char *message, ...) +{ + dprintf((stderr, "rcm_log_message stub\n")); +} + +/* + * Helper functions + */ + +/* + * Common routine for all rcm calls which require daemon processing + */ +static int +rcm_common(int cmd, rcm_handle_t *hd, char **rsrcnames, uint_t flag, void *arg, + rcm_info_t **infop) +{ + int i; + + if (hd == NULL) { + errno = EINVAL; + return (RCM_FAILURE); + } + + if (getuid() != 0) { + errno = EPERM; + return (RCM_FAILURE); + } + + if ((flag & (RCM_DR_OPERATION | RCM_MOD_INFO)) == 0) { + if ((rsrcnames == NULL) || (rsrcnames[0] == NULL)) { + errno = EINVAL; + return (RCM_FAILURE); + } + + for (i = 0; rsrcnames[i] != NULL; i++) { + if (*rsrcnames[i] == '\0') { + errno = EINVAL; + return (RCM_FAILURE); + } + } + } + + /* + * Check if handle is allocated by rcm_daemon. If so, this call came + * from an RCM module, so we make a direct call into rcm_daemon. + */ + if (hd->lrcm_ops != NULL) { + return (rcm_direct_call(cmd, hd, rsrcnames, flag, arg, infop)); + } + + /* + * When not called from a RCM module (i.e. no recursion), zero the + * pointer just in case caller did not do so. For recursive calls, + * we want to append rcm_info_t after infop; zero it may cause + * memory leaks. + */ + if (infop) { + *infop = NULL; + } + + /* + * Now call into the daemon. + */ + return (rcm_daemon_call(cmd, hd, rsrcnames, flag, arg, infop)); +} + +/* + * Caller is an RCM module, call directly into rcm_daemon. + */ +static int +rcm_direct_call(int cmd, rcm_handle_t *hd, char **rsrcnames, uint_t flag, + void *arg, rcm_info_t **infop) +{ + int error; + + librcm_ops_t *ops = (librcm_ops_t *)hd->lrcm_ops; + switch (cmd) { + case CMD_GETINFO: + error = ops->librcm_getinfo(rsrcnames, flag, hd->seq_num, + infop); + break; + + case CMD_OFFLINE: + error = ops->librcm_offline(rsrcnames, hd->pid, flag, + hd->seq_num, infop); + break; + + case CMD_ONLINE: + error = ops->librcm_online(rsrcnames, hd->pid, flag, + hd->seq_num, infop); + break; + + case CMD_REMOVE: + error = ops->librcm_remove(rsrcnames, hd->pid, flag, + hd->seq_num, infop); + break; + + case CMD_SUSPEND: + error = ops->librcm_suspend(rsrcnames, hd->pid, flag, + hd->seq_num, (timespec_t *)arg, infop); + break; + + case CMD_RESUME: + error = ops->librcm_resume(rsrcnames, hd->pid, flag, + hd->seq_num, infop); + break; + + case CMD_REGISTER: + error = ops->librcm_regis(hd->modname, rsrcnames[0], hd->pid, + flag, infop); + break; + + case CMD_UNREGISTER: + error = ops->librcm_unregis(hd->modname, rsrcnames[0], hd->pid, + flag); + break; + + case CMD_REQUEST_CHANGE: + error = ops->librcm_request_change(rsrcnames[0], hd->pid, flag, + hd->seq_num, (nvlist_t *)arg, infop); + break; + + case CMD_NOTIFY_CHANGE: + error = ops->librcm_notify_change(rsrcnames[0], hd->pid, flag, + hd->seq_num, (nvlist_t *)arg, infop); + break; + + case CMD_EVENT: + error = ops->librcm_notify_event(rsrcnames[0], hd->pid, flag, + hd->seq_num, (nvlist_t *)arg, infop); + break; + + case CMD_GETSTATE: + error = ops->librcm_getstate(rsrcnames[0], hd->pid, infop); + break; + + default: + dprintf((stderr, "invalid command: %d\n", cmd)); + error = EFAULT; + } + + if (error > 0) { + errno = error; + error = RCM_FAILURE; + } + return (error); +} + +/* + * Call into rcm_daemon door to process the request + */ +static int +rcm_daemon_call(int cmd, rcm_handle_t *hd, char **rsrcnames, uint_t flag, + void *arg, rcm_info_t **infop) +{ + int errno_found; + int daemon_errno; + int error = RCM_SUCCESS; + int delay = 300; + int maxdelay = 10000; /* 10 seconds */ + char *nvl_packed = NULL; + size_t nvl_size = 0; + nvlist_t *ret = NULL; + nvpair_t *nvp; + size_t rsize = 0; + rcm_info_t *info = NULL; + + errno = 0; + + /* + * Decide whether to start the daemon + */ + switch (cmd) { + case CMD_GETINFO: + case CMD_OFFLINE: + case CMD_ONLINE: + case CMD_REMOVE: + case CMD_SUSPEND: + case CMD_RESUME: + case CMD_REGISTER: + case CMD_UNREGISTER: + case CMD_EVENT: + case CMD_REQUEST_CHANGE: + case CMD_NOTIFY_CHANGE: + case CMD_GETSTATE: + break; + + default: + errno = EFAULT; + return (RCM_FAILURE); + } + + if (rcm_daemon_is_alive() != 1) { + dprintf((stderr, "failed to start rcm_daemon\n")); + errno = EFAULT; + return (RCM_FAILURE); + } + + /* + * Generate a packed nvlist for the request + */ + if (rcm_generate_nvlist(cmd, hd, rsrcnames, flag, arg, &nvl_packed, + &nvl_size) < 0) { + dprintf((stderr, "error in nvlist generation\n")); + errno = EFAULT; + return (RCM_FAILURE); + } + + /* + * Make the door call and get a return event. We go into a retry loop + * when RCM_ET_EAGAIN is returned. + */ +retry: + if (get_event_service(RCM_SERVICE_DOOR, (void *)nvl_packed, nvl_size, + (void **)&ret, &rsize) < 0) { + dprintf((stderr, "rcm_daemon call failed: %s\n", + strerror(errno))); + free(nvl_packed); + return (RCM_FAILURE); + } + + assert(ret != NULL); + + /* + * nvlist_lookup_* routines don't work because the returned nvlist + * was nvlist_alloc'ed without the NV_UNIQUE_NAME flag. Implement + * a sequential search manually, which is fine since there is only + * one RCM_RESULT value in the nvlist. + */ + errno_found = 0; + nvp = NULL; + while (nvp = nvlist_next_nvpair(ret, nvp)) { + if (strcmp(nvpair_name(nvp), RCM_RESULT) == 0) { + if (errno = nvpair_value_int32(nvp, &daemon_errno)) { + error = RCM_FAILURE; + goto out; + } + errno_found++; + break; + } + } + if (errno_found == 0) { + errno = EFAULT; + error = RCM_FAILURE; + goto out; + } + + if (daemon_errno == EAGAIN) { + /* + * Wait and retry + */ + dprintf((stderr, "retry door_call\n")); + + if (delay > maxdelay) { + errno = EAGAIN; + error = RCM_FAILURE; + goto out; + } + + (void) poll(NULL, 0, delay); + delay *= 2; /* exponential back off */ + nvlist_free(ret); + goto retry; + } + + /* + * The door call succeeded. Now extract info from returned event. + */ + if (extract_info(ret, &info) != 0) { + dprintf((stderr, "error in extracting event data\n")); + errno = EFAULT; + error = RCM_FAILURE; + goto out; + } + + if (infop) + *infop = info; + else + rcm_free_info(info); + + if (daemon_errno) { + if (daemon_errno > 0) { + errno = daemon_errno; + error = RCM_FAILURE; + } else { + error = daemon_errno; + } + } + +out: + if (nvl_packed) + free(nvl_packed); + if (ret) + nvlist_free(ret); + dprintf((stderr, "daemon call is done. error = %d, errno = %s\n", error, + strerror(errno))); + return (error); +} + +/* + * Extract registration info from event data. + * Return 0 on success and -1 on failure. + */ +static int +extract_info(nvlist_t *nvl, rcm_info_t **infop) +{ + rcm_info_t *info = NULL; + rcm_info_t *prev = NULL; + rcm_info_t *tmp = NULL; + char *buf; + uint_t buflen; + nvpair_t *nvp = NULL; + + while (nvp = nvlist_next_nvpair(nvl, nvp)) { + + buf = NULL; + buflen = 0; + + if (strcmp(nvpair_name(nvp), RCM_RESULT_INFO) != 0) + continue; + + if ((tmp = calloc(1, sizeof (*tmp))) == NULL) { + dprintf((stderr, "out of memory\n")); + goto fail; + } + + if (errno = nvpair_value_byte_array(nvp, (uchar_t **)&buf, + &buflen)) { + free(tmp); + dprintf((stderr, "failed (nvpair_value=%s)\n", + strerror(errno))); + goto fail; + } + if (errno = nvlist_unpack(buf, buflen, &(tmp->info), 0)) { + free(tmp); + dprintf((stderr, "failed (nvlist_unpack=%s)\n", + strerror(errno))); + goto fail; + } + + if (info == NULL) { + prev = info = tmp; + } else { + prev->next = tmp; + prev = tmp; + } + } + + *infop = info; + return (0); + +fail: + rcm_free_info(info); + *infop = NULL; + return (-1); +} + +/* Generate a packed nvlist for communicating with RCM daemon */ +static int +rcm_generate_nvlist(int cmd, rcm_handle_t *hd, char **rsrcnames, uint_t flag, + void *arg, char **nvl_packed, size_t *nvl_size) +{ + int nrsrcnames; + char *buf = NULL; + size_t buflen = 0; + nvlist_t *nvl = NULL; + + assert((nvl_packed != NULL) && (nvl_size != NULL)); + + *nvl_size = 0; + *nvl_packed = NULL; + + /* Allocate an empty nvlist */ + if ((errno = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) > 0) { + dprintf((stderr, "failed (nvlist_alloc=%s).\n", + strerror(errno))); + return (-1); + } + + /* Stuff in all the arguments for the daemon call */ + if (nvlist_add_int32(nvl, RCM_CMD, cmd) != 0) { + dprintf((stderr, "failed (nvlist_add(CMD)=%s).\n", + strerror(errno))); + goto fail; + } + if (rsrcnames) { + nrsrcnames = 0; + while (rsrcnames[nrsrcnames] != NULL) + nrsrcnames++; + if (nvlist_add_string_array(nvl, RCM_RSRCNAMES, rsrcnames, + nrsrcnames) != 0) { + dprintf((stderr, "failed (nvlist_add(RSRCNAMES)=%s).\n", + strerror(errno))); + goto fail; + } + } + if (hd->modname) { + if (nvlist_add_string(nvl, RCM_CLIENT_MODNAME, hd->modname) + != 0) { + dprintf((stderr, + "failed (nvlist_add(CLIENT_MODNAME)=%s).\n", + strerror(errno))); + goto fail; + } + } + if (hd->pid) { + if (nvlist_add_uint64(nvl, RCM_CLIENT_ID, hd->pid) != 0) { + dprintf((stderr, "failed (nvlist_add(CLIENT_ID)=%s).\n", + strerror(errno))); + goto fail; + } + } + if (flag) { + if (nvlist_add_uint32(nvl, RCM_REQUEST_FLAG, flag) != 0) { + dprintf((stderr, + "failed (nvlist_add(REQUEST_FLAG)=%s).\n", + strerror(errno))); + goto fail; + } + } + if (arg && cmd == CMD_SUSPEND) { + if (nvlist_add_byte_array(nvl, RCM_SUSPEND_INTERVAL, + (uchar_t *)arg, sizeof (timespec_t)) != 0) { + dprintf((stderr, + "failed (nvlist_add(SUSPEND_INTERVAL)=%s).\n", + strerror(errno))); + goto fail; + } + } + if (arg && + ((cmd == CMD_REQUEST_CHANGE) || (cmd == CMD_NOTIFY_CHANGE))) { + if (errno = nvlist_pack(arg, &buf, &buflen, NV_ENCODE_NATIVE, + 0)) { + dprintf((stderr, + "failed (nvlist_pack(CHANGE_DATA)=%s).\n", + strerror(errno))); + goto fail; + } + if (nvlist_add_byte_array(nvl, RCM_CHANGE_DATA, (uchar_t *)buf, + buflen) != 0) { + dprintf((stderr, + "failed (nvlist_add(CHANGE_DATA)=%s).\n", + strerror(errno))); + goto fail; + } + } + if (arg && cmd == CMD_EVENT) { + if (errno = nvlist_pack(arg, &buf, &buflen, NV_ENCODE_NATIVE, + 0)) { + dprintf((stderr, + "failed (nvlist_pack(CHANGE_DATA)=%s).\n", + strerror(errno))); + goto fail; + } + if (nvlist_add_byte_array(nvl, RCM_EVENT_DATA, (uchar_t *)buf, + buflen) != 0) { + dprintf((stderr, + "failed (nvlist_add(EVENT_DATA)=%s).\n", + strerror(errno))); + goto fail; + } + } + + /* Pack the nvlist */ + if (errno = nvlist_pack(nvl, nvl_packed, nvl_size, NV_ENCODE_NATIVE, + 0)) { + dprintf((stderr, "failed (nvlist_pack=%s).\n", + strerror(errno))); + goto fail; + } + + /* If an argument was packed intermediately, free the buffer */ + if (buf) + free(buf); + + /* Free the unpacked version of the nvlist and return the packed list */ + nvlist_free(nvl); + return (0); + +fail: + if (buf) + free(buf); + if (nvl) + nvlist_free(nvl); + if (*nvl_packed) + free(*nvl_packed); + *nvl_packed = NULL; + *nvl_size = 0; + return (-1); +} + +/* check if rcm_daemon is up and running */ +static int +rcm_daemon_is_alive() +{ + int lasttry; + struct stat st; + nvlist_t *nvl; + char *buf = NULL; + size_t buflen = 0; + int delay = 300; + const int maxdelay = 10000; /* 10 sec */ + + /* generate a packed nvlist for the door knocking */ + if (errno = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) { + dprintf((stderr, "nvlist_alloc failed: %s\n", strerror(errno))); + return (0); + } + if (errno = nvlist_add_int32(nvl, RCM_CMD, CMD_KNOCK)) { + dprintf((stderr, "nvlist_add failed: %s\n", strerror(errno))); + nvlist_free(nvl); + return (0); + } + if (errno = nvlist_pack(nvl, &buf, &buflen, NV_ENCODE_NATIVE, 0)) { + dprintf((stderr, "nvlist_pack failed: %s\n", strerror(errno))); + nvlist_free(nvl); + return (0); + } + nvlist_free(nvl); + + /* + * check the door and knock on it + */ + if ((stat(RCM_SERVICE_DOOR, &st) == 0) && + (get_event_service(RCM_SERVICE_DOOR, (void *)buf, buflen, NULL, + NULL) == 0)) { + free(buf); + return (1); /* daemon is alive */ + } + + /* + * Attempt to start the daemon. + * If caller has SIGCHLD set to SIG_IGN or its SA_NOCLDWAIT + * flag set, waitpid(2) (hence rcm_exec_cmd) will fail. + * get_event_service will determine if the rcm_daemon started. + */ + dprintf((stderr, "exec: %s\n", RCM_DAEMON_START)); + (void) rcm_exec_cmd(RCM_DAEMON_START); + + /* + * Wait for daemon to respond, timeout at 10 sec + */ + while (((lasttry = get_event_service(RCM_SERVICE_DOOR, (void *)buf, + buflen, NULL, NULL)) != 0) && + ((errno == EBADF) || (errno == ESRCH))) { + if (delay > maxdelay) { + break; + } + (void) poll(NULL, 0, delay); + delay *= 2; + } + + free(buf); + if (lasttry == 0) + return (1); + return (0); +} + +/* + * Check permission. + * + * The policy is root only for now. Need to relax this when interface level + * is raised. + */ +static int +rcm_check_permission(void) +{ + return (getuid() == 0); +} + +/* + * Project private function - for use by RCM MSTC tests + * + * Get the client name (rcm module name or script name) corresponding to + * the given rcm handle. + */ +const char * +rcm_get_client_name(rcm_handle_t *hd) +{ + return (hd->modname); +} diff --git a/usr/src/lib/librcm/librcm.h b/usr/src/lib/librcm/librcm.h new file mode 100644 index 0000000000..4df3d5cb59 --- /dev/null +++ b/usr/src/lib/librcm/librcm.h @@ -0,0 +1,172 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _LIBRCM_H +#define _LIBRCM_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <libnvpair.h> +#include <sys/types.h> +#include <sys/processor.h> +#include <sys/pset.h> +#include <sys/time_impl.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Flags for rcm requests + */ +#define RCM_INCLUDE_SUBTREE 0x0001 +#define RCM_INCLUDE_DEPENDENT 0x0002 +#define RCM_QUERY 0x0004 +#define RCM_FORCE 0x0008 +#define RCM_FILESYS 0x0010 /* private to filesys module */ +#define RCM_NOPID 0x0020 +#define RCM_DR_OPERATION 0x0040 +#define RCM_MOD_INFO 0x0080 /* private */ +#define RCM_CAPACITY_ADD 0x0100 +#define RCM_CAPACITY_DELETE 0x0200 +#define RCM_QUERY_CANCEL 0x0400 /* private */ +#define RCM_SCOPE 0x0800 +#define RCM_REGISTER_DR 0x1000 /* private */ +#define RCM_REGISTER_EVENT 0x2000 /* private */ +#define RCM_REGISTER_CAPACITY 0x4000 /* private */ +#define RCM_SUSPENDED 0x8000 /* private */ + +/* + * RCM return values + */ +#define RCM_SUCCESS 0 +#define RCM_FAILURE -1 +#define RCM_CONFLICT -2 + +/* + * RCM resource states + */ +#define RCM_STATE_UNKNOWN 0 +#define RCM_STATE_ONLINE 1 +#define RCM_STATE_ONLINING 2 +#define RCM_STATE_OFFLINE_FAIL 3 +#define RCM_STATE_OFFLINING 4 +#define RCM_STATE_OFFLINE 5 +#define RCM_STATE_REMOVING 6 +#define RCM_STATE_RESUMING 10 +#define RCM_STATE_SUSPEND_FAIL 11 +#define RCM_STATE_SUSPENDING 12 +#define RCM_STATE_SUSPEND 13 +#define RCM_STATE_REMOVE 14 /* private to rcm_daemon */ +#define RCM_STATE_OFFLINE_QUERYING 15 +#define RCM_STATE_OFFLINE_QUERY_FAIL 16 +#define RCM_STATE_OFFLINE_QUERY 17 +#define RCM_STATE_SUSPEND_QUERYING 18 +#define RCM_STATE_SUSPEND_QUERY_FAIL 19 +#define RCM_STATE_SUSPEND_QUERY 20 + +/* + * RCM event attr and properties + */ +#define RCM_RSRCNAME "rcm.rsrcname" +#define RCM_CLIENT_NAME "rcm.client_name" +#define RCM_CLIENT_EXPORTS "rcm.client_exports" + +/* Resource name to register for new network resources */ +#define RCM_RESOURCE_NETWORK_NEW "SUNW_event/resource/new/network" +/* Resource name to register for new MAC resources */ +#define RCM_RESOURCE_MAC_NEW "SUNW_event/resource/new/mac" + +/* name-value pair definitions for rcm_notify_event() */ +#define RCM_NV_DRIVER_NAME "driver_name" +#define RCM_NV_INSTANCE "instance" +#define RCM_NV_NODE_NAME "node_name" +#define RCM_NV_DEVFS_PATH "devfs_path" +#define RCM_NV_MINOR_DATA "minor_data" +#define RCM_NV_MINOR_TYPE "minor_type" +#define RCM_NV_MINOR_NAME "minor_name" +#define RCM_NV_MINOR_NODE_TYPE "minor_node_type" + +/* + * rcm handles + */ +typedef struct rcm_handle rcm_handle_t; +typedef struct rcm_info rcm_info_t; +typedef rcm_info_t rcm_info_tuple_t; + +/* + * Interface definitions + */ +int rcm_alloc_handle(char *, uint_t, void *, rcm_handle_t **); +int rcm_free_handle(rcm_handle_t *); +int rcm_get_info(rcm_handle_t *, char *, uint_t, rcm_info_t **); +int rcm_get_info_list(rcm_handle_t *, char **, uint_t, rcm_info_t **); +void rcm_free_info(rcm_info_t *); +int rcm_append_info(rcm_info_t **, rcm_info_t *); +rcm_info_tuple_t *rcm_info_next(rcm_info_t *, rcm_info_tuple_t *); +const char *rcm_info_rsrc(rcm_info_tuple_t *); +const char *rcm_info_info(rcm_info_tuple_t *); +const char *rcm_info_error(rcm_info_tuple_t *); +const char *rcm_info_modname(rcm_info_tuple_t *); +pid_t rcm_info_pid(rcm_info_tuple_t *); +int rcm_info_state(rcm_info_tuple_t *); +int rcm_info_seqnum(rcm_info_tuple_t *); +nvlist_t *rcm_info_properties(rcm_info_tuple_t *); + +int rcm_request_offline(rcm_handle_t *, char *, uint_t, rcm_info_t **); +int rcm_request_offline_list(rcm_handle_t *, char **, uint_t, rcm_info_t **); +int rcm_notify_online(rcm_handle_t *, char *, uint_t, rcm_info_t **); +int rcm_notify_online_list(rcm_handle_t *, char **, uint_t, rcm_info_t **); +int rcm_notify_remove(rcm_handle_t *, char *, uint_t, rcm_info_t **); +int rcm_notify_remove_list(rcm_handle_t *, char **, uint_t, rcm_info_t **); +int rcm_request_suspend(rcm_handle_t *, char *, uint_t, timespec_t *, + rcm_info_t **); +int rcm_request_suspend_list(rcm_handle_t *, char **, uint_t, timespec_t *, + rcm_info_t **); +int rcm_notify_resume(rcm_handle_t *, char *, uint_t, rcm_info_t **); +int rcm_notify_resume_list(rcm_handle_t *, char **, uint_t, rcm_info_t **); +int rcm_notify_capacity_change(rcm_handle_t *, char *, uint_t, nvlist_t *, + rcm_info_t **); +int rcm_request_capacity_change(rcm_handle_t *, char *, uint_t, nvlist_t *, + rcm_info_t **); +int rcm_notify_event(rcm_handle_t *, char *, uint_t, nvlist_t *, rcm_info_t **); + +int rcm_register_event(rcm_handle_t *, char *, uint_t, rcm_info_t **); +int rcm_register_capacity(rcm_handle_t *, char *, uint_t, rcm_info_t **); +int rcm_register_interest(rcm_handle_t *, char *, uint_t, rcm_info_t **); +int rcm_unregister_event(rcm_handle_t *, char *, uint_t); +int rcm_unregister_capacity(rcm_handle_t *, char *, uint_t); +int rcm_unregister_interest(rcm_handle_t *, char *, uint_t); + +int rcm_get_rsrcstate(rcm_handle_t *, char *, int *); +int rcm_exec_cmd(char *); +const char *rcm_get_client_name(rcm_handle_t *); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBRCM_H */ diff --git a/usr/src/lib/librcm/librcm_event.c b/usr/src/lib/librcm/librcm_event.c new file mode 100644 index 0000000000..88f1416bc0 --- /dev/null +++ b/usr/src/lib/librcm/librcm_event.c @@ -0,0 +1,406 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <fcntl.h> +#include <errno.h> +#include <door.h> +#include <unistd.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <synch.h> +#include <sys/stat.h> +#include <librcm_impl.h> + +#include "librcm_event.h" + +#define dprint if (debug) (void) printf +static int debug = 1; + +#define BUF_THRESHOLD 1024 /* larger bufs require a free */ + +/* + * Lookup seq_num. We can not use the standard nvlist_lookup functions since + * the nvlist is not allocated with NV_UNIQUE_NAME or NV_UNIQUE_NAME_TYPE. + */ +static int +lookup_seq_num(nvlist_t *nvl, uint64_t *seq_num) +{ + nvpair_t *nvp = NULL; + + while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) { + if (strcmp(nvpair_name(nvp), RCM_SEQ_NUM) == 0 && + nvpair_type(nvp) == DATA_TYPE_UINT64) + return (nvpair_value_uint64(nvp, seq_num)); + } + + return (ENOENT); +} + +/* + * Get event service from a named door. + * + * This is similar to sysevent_post_event(), except that it deals with + * the "return buffer problem": + * Typically, the door service places the return buffer on the stack + * when calling door_return(). This places an artificial limit on the + * size of the return buffer. + * This problem is solved by placing large buffers on the heap, referenced + * through door_info. When client detects a large buffer, it will make a + * second door_call() to free the buffer. The client and the server agrees + * on a size, which is defined as BUF_THRESHOLD. + * + * Returns -1 if message not delivered. With errno set to cause of error. + * Returns 0 for success with the results returned in posting buffer. + */ +int +get_event_service(char *door_name, void *data, size_t datalen, + void **result, size_t *rlen) +{ + int service_door, error; + door_arg_t door_arg; + + /* + * Open the service door + */ + if ((service_door = open(door_name, O_RDONLY, 0)) == -1) { + errno = ESRCH; + return (-1); + } + +retry1: + door_arg.rbuf = NULL; /* doorfs will provide return buf */ + door_arg.rsize = 0; + door_arg.data_ptr = data; + door_arg.data_size = datalen; + door_arg.desc_ptr = NULL; + door_arg.desc_num = 0; + + /* + * Make door call + * EAGAIN is returned when the door server is temporarily + * out of threads to service the door call. So retry. + */ + if ((error = door_call(service_door, &door_arg)) == -1 && + errno == EAGAIN) { + (void) sleep(1); + goto retry1; + } + + if ((error == 0) && result) { + + uint64_t seq_num = 0; + + *result = NULL; + *rlen = 0; + if (door_arg.rbuf == NULL || door_arg.rsize == 0) { + dprint("bad return from door call\n"); + (void) close(service_door); + errno = EFAULT; + return (-1); + } + + (void) nvlist_unpack(door_arg.rbuf, door_arg.rsize, + (nvlist_t **)result, 0); + (void) munmap(door_arg.rbuf, door_arg.rsize); + + /* + * If requiring a buf free, make another door call. There is + * no need to call munmap() after this door call, though. + */ + if (lookup_seq_num((nvlist_t *)*result, &seq_num) == 0) { +retry2: + door_arg.rbuf = NULL; + door_arg.rsize = 0; + door_arg.data_ptr = (char *)&seq_num; + door_arg.data_size = sizeof (seq_num); + door_arg.desc_ptr = NULL; + door_arg.desc_num = 0; + if (door_call(service_door, &door_arg) == -1) { + if (errno == EAGAIN) { + (void) sleep(1); + goto retry2; + } + dprint("fail to free event buf in server\n"); + } + } + } + + (void) close(service_door); + return (error); +} + +/* + * Export an event service door + */ +struct door_result { + struct door_result *next; + void *data; + uint64_t seq_num; +}; + +typedef struct door_cookie { + uint64_t seq_num; + mutex_t door_lock; + void (*door_func)(void **, size_t *); + struct door_result *results; +} door_cookie_t; + +/* + * add result to cookie, this is only invoked if result size > BUF_THRESHOLD + */ +static void +add_door_result(door_cookie_t *cook, void *data, uint64_t seq_num) +{ + struct door_result *result; + + /* + * Need a better way to handle memory here + */ + result = malloc(sizeof (*result)); + while (result == NULL) { + (void) sleep(1); + result = malloc(sizeof (*result)); + } + result->next = NULL; + result->data = data; + result->seq_num = seq_num; + + /* + * Attach current door result to the door cookie + */ + (void) mutex_lock(&cook->door_lock); + if (cook->results == NULL) { + cook->results = result; + } else { + struct door_result *tmp = cook->results; + while (tmp->next) { + tmp = tmp->next; + } + tmp->next = result; + } + (void) mutex_unlock(&cook->door_lock); +} + +/* + * free a previous door result as described by number. + */ +static void +free_door_result(door_cookie_t *cook, uint64_t num) +{ + struct door_result *prev = NULL, *tmp; + + (void) mutex_lock(&cook->door_lock); + tmp = cook->results; + while (tmp && tmp->seq_num != num) { + prev = tmp; + tmp = tmp->next; + } + + if (tmp == NULL) { + dprint("attempting to free nonexistent buf: %llu\n", + (unsigned long long)num); + (void) mutex_unlock(&cook->door_lock); + return; + } + + if (prev) { + prev->next = tmp->next; + } else { + cook->results = tmp->next; + } + (void) mutex_unlock(&cook->door_lock); + + free(tmp->data); + free(tmp); +} + +/*ARGSUSED*/ +static void +door_service(void *cookie, char *args, size_t alen, + door_desc_t *ddp, uint_t ndid) +{ + nvlist_t *nvl; + size_t nvl_size = 0; + char rbuf[BUF_THRESHOLD]; + door_cookie_t *cook = (door_cookie_t *)cookie; + uint64_t seq_num = 0; + + /* + * Special case for asking to free buffer + */ + if (alen == sizeof (uint64_t)) { + free_door_result(cookie, *(uint64_t *)(void *)args); + (void) door_return(NULL, 0, NULL, 0); + } + + /* + * door_func update args to point to return results. + * memory for results are dynamically allocated. + */ + (*cook->door_func)((void **)&args, &alen); + + /* + * If no results, just return + */ + if (args == NULL) { + dprint("null results returned from door_func().\n"); + (void) door_return(NULL, 0, NULL, 0); + } + + /* Determine the size of the packed nvlist */ + nvl = (nvlist_t *)(void *)args; + args = NULL; + alen = 0; + if (errno = nvlist_size(nvl, &nvl_size, NV_ENCODE_NATIVE)) { + nvlist_free(nvl); + dprint("failure to sizeup door results: %s\n", strerror(errno)); + (void) door_return(NULL, 0, NULL, 0); + } + + /* + * If the size of the packed nvlist would exceed the buffer threshold + * then get a sequence number and add it to the nvlist. + */ + if (nvl_size > BUF_THRESHOLD) { + (void) mutex_lock(&cook->door_lock); + cook->seq_num++; + seq_num = cook->seq_num; + (void) mutex_unlock(&cook->door_lock); + (void) nvlist_add_uint64(nvl, RCM_SEQ_NUM, seq_num); + } + + /* Refill the args with a packed version of the nvlist */ + if (errno = nvlist_pack(nvl, &args, &alen, NV_ENCODE_NATIVE, 0)) { + nvlist_free(nvl); + dprint("failure to pack door results: %s\n", strerror(errno)); + (void) door_return(NULL, 0, NULL, 0); + } + nvlist_free(nvl); + + /* + * Based on the size of the packed nvlist, either use the local buffer + * or add it to the results list. + */ + if (alen <= BUF_THRESHOLD) { + bcopy(args, rbuf, alen); + (void) free(args); + args = rbuf; + } else { + /* + * for long data, append results to end of queue in cook + * and set ndid, ask client to do another door_call + * to free the buffer. + */ + add_door_result(cook, args, seq_num); + } + + (void) door_return(args, alen, NULL, 0); +} + +int +create_event_service(char *door_name, + void (*func)(void **data, size_t *datalen)) +{ + int service_door, fd; + door_cookie_t *cookie; + + /* create an fs file */ + fd = open(door_name, O_EXCL|O_CREAT, S_IREAD|S_IWRITE); + if ((fd == -1) && (errno != EEXIST)) { + return (-1); + } + (void) close(fd); + + /* allocate space for door cookie */ + if ((cookie = calloc(1, sizeof (*cookie))) == NULL) { + return (-1); + } + + cookie->door_func = func; + if ((service_door = door_create(door_service, (void *)cookie, + DOOR_REFUSE_DESC | DOOR_NO_CANCEL)) == -1) { + dprint("door create failed: %s\n", strerror(errno)); + free(cookie); + return (-1); + } + +retry: + (void) fdetach(door_name); + if (fattach(service_door, door_name) != 0) { + if (errno == EBUSY) { + /* + * EBUSY error may occur if anyone references the door + * file while we are fattach'ing. Since librcm, in the + * the process context of a DR initiator program, may + * reference the door file (via open/close/stat/ + * door_call etc.) while we are still fattach'ing, + * retry on EBUSY. + */ + goto retry; + } + dprint("door attaching failed: %s\n", strerror(errno)); + free(cookie); + (void) close(service_door); + return (-1); + } + + return (service_door); +} + +int +revoke_event_service(int fd) +{ + struct door_info info; + door_cookie_t *cookie; + + if (door_info(fd, &info) == -1) { + return (-1); + } + + if (door_revoke(fd) != 0) { + return (-1); + } + + /* wait for existing door calls to finish */ + (void) sleep(1); + + if ((cookie = (door_cookie_t *)info.di_data) != NULL) { + struct door_result *tmp = cookie->results; + while (tmp) { + cookie->results = tmp->next; + free(tmp->data); + free(tmp); + tmp = cookie->results; + } + free(cookie); + } + return (0); +} diff --git a/usr/src/lib/librcm/librcm_event.h b/usr/src/lib/librcm/librcm_event.h new file mode 100644 index 0000000000..d4c82cfd40 --- /dev/null +++ b/usr/src/lib/librcm/librcm_event.h @@ -0,0 +1,53 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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) 1999-2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#ifndef _LIBRCM_EVENT_H +#define _LIBRCM_EVENT_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <sys/types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * librcm message passing interfaces + * + * These are based on libnvpair to leverage its data marshalling. + */ +int get_event_service(char *door_name, void *data, size_t datalen, + void **result, size_t *rlen); +int create_event_service(char *door_name, void (*func)(void **, size_t *)); +int revoke_event_service(int door_fd); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBRCM_EVENT_H */ diff --git a/usr/src/lib/librcm/librcm_impl.h b/usr/src/lib/librcm/librcm_impl.h new file mode 100644 index 0000000000..a534d22e1e --- /dev/null +++ b/usr/src/lib/librcm/librcm_impl.h @@ -0,0 +1,163 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _LIBRCM_IMPL_H +#define _LIBRCM_IMPL_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +#include <assert.h> +#include <stdio.h> +#include <stdarg.h> +#include <dlfcn.h> +#include <errno.h> +#include <fcntl.h> +#include <poll.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <syslog.h> +#include <unistd.h> +#include <sys/mman.h> +#include <sys/wait.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/param.h> +#include <sys/systeminfo.h> +#include <librcm.h> + +/* + * This file contains information private to librcm rcm_daemon. + */ +#define RCM_DAEMON_START "/usr/lib/rcm/rcm_daemon" +#define RCM_SERVICE_DOOR "/var/run/rcm_daemon_door" +#define RCM_MODULE_SUFFIX "_rcm.so" + +/* + * flag fields supported by individual librcm interfaces + */ +#define RCM_ALLOC_HDL_MASK (RCM_NOPID) +#define RCM_GET_INFO_MASK (RCM_INCLUDE_SUBTREE|RCM_INCLUDE_DEPENDENT|\ + RCM_DR_OPERATION|RCM_MOD_INFO|RCM_FILESYS) +#define RCM_REGISTER_MASK (RCM_FILESYS|RCM_REGISTER_DR|\ + RCM_REGISTER_EVENT|RCM_REGISTER_CAPACITY) +#define RCM_REQUEST_MASK (RCM_QUERY|RCM_SCOPE|RCM_FORCE|RCM_FILESYS|\ + RCM_QUERY_CANCEL) +#define RCM_NOTIFY_MASK (RCM_FILESYS) + +/* event data names */ +#define RCM_CMD "rcm.cmd" +#define RCM_RESULT "rcm.result" +#define RCM_RESULT_INFO "rcm.result_info" +#define RCM_RSRCNAMES "rcm.rsrcnames" +#define RCM_RSRCSTATE "rcm.rsrcstate" +#define RCM_CLIENT_ID "rcm.client_id" +#define RCM_CLIENT_INFO "rcm.client_info" +#define RCM_CLIENT_ERROR "rcm.client_error" +#define RCM_CLIENT_MODNAME "rcm.client_modname" +#define RCM_CLIENT_PROPERTIES "rcm.client_properties" +#define RCM_SEQ_NUM "rcm.seq_num" +#define RCM_REQUEST_FLAG "rcm.request_flag" +#define RCM_SUSPEND_INTERVAL "rcm.suspend_interval" +#define RCM_CHANGE_DATA "rcm.change_data" +#define RCM_EVENT_DATA "rcm.event_data" + +/* + * action commands shared by librcm and rcm_daemon + */ +#define CMD_KNOCK 0 +#define CMD_REGISTER 1 +#define CMD_UNREGISTER 2 +#define CMD_GETINFO 3 +#define CMD_SUSPEND 4 +#define CMD_RESUME 5 +#define CMD_OFFLINE 6 +#define CMD_ONLINE 7 +#define CMD_REMOVE 8 +#define CMD_EVENT 9 +#define CMD_REQUEST_CHANGE 10 +#define CMD_NOTIFY_CHANGE 11 +#define CMD_GETSTATE 12 + +/* + * Ops vector for calling directly into daemon from RCM modules + */ +typedef struct { + int (*librcm_regis)(); + int (*librcm_unregis)(); + int (*librcm_getinfo)(); + int (*librcm_suspend)(); + int (*librcm_resume)(); + int (*librcm_offline)(); + int (*librcm_online)(); + int (*librcm_remove)(); + int (*librcm_request_change)(); + int (*librcm_notify_change)(); + int (*librcm_notify_event)(); + int (*librcm_getstate)(); +} librcm_ops_t; + +/* + * rcm handle struture + */ +struct rcm_handle { + char *modname; + pid_t pid; + int seq_num; + librcm_ops_t *lrcm_ops; + struct module *module; +}; + +struct rcm_info { + nvlist_t *info; + struct rcm_info *next; +}; + +/* + * module utility routines + */ +char *rcm_module_dir(uint_t); +void *rcm_module_open(char *); +void rcm_module_close(void *); + +/* + * rcm scripting utility routines + */ +char *rcm_script_dir(uint_t dirnum); +char *rcm_dir(uint_t dirnum, int *rcm_script); +char *rcm_get_script_dir(char *script_name); +int rcm_is_script(char *filename); + + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBRCM_IMPL_H */ diff --git a/usr/src/lib/librcm/llib-lrcm b/usr/src/lib/librcm/llib-lrcm new file mode 100644 index 0000000000..c6c8dd1679 --- /dev/null +++ b/usr/src/lib/librcm/llib-lrcm @@ -0,0 +1,87 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 + */ +/*LINTLIBRARY*/ +/*PROTOLIB1*/ +/* + * Copyright 1999-2000, 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * usr/src/lib/librcm/llib-ldevinfo + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "librcm.h" +#include "librcm_event.h" + +/* librcm interfaces */ + +int rcm_get_handle(char *, uint_t, void *, rcm_handle_t **); +int rcm_free_handle(rcm_handle_t *); +int rcm_get_info(rcm_handle_t *, char *, uint_t, rcm_info_t **); +int rcm_get_rsrcstate(rcm_handle_t *, char *, int *); +void rcm_free_info(rcm_info_t *); +int rcm_append_info(rcm_info_t **, rcm_info_t *); +rcm_info_tuple_t *rcm_info_next(rcm_info_t *, rcm_info_tuple_t *); +const char *rcm_info_rsrc(rcm_info_tuple_t *); +const char *rcm_info_info(rcm_info_tuple_t *); +const char *rcm_info_modname(rcm_info_tuple_t *); +const char *rcm_info_error(rcm_info_tuple_t *); +pid_t rcm_info_pid(rcm_info_tuple_t *); +int rcm_info_state(rcm_info_tuple_t *); +int rcm_info_seqnum(rcm_info_tuple_t *); +nvlist_t *rcm_info_properties(rcm_info_tuple_t *); +int rcm_request_offline(rcm_handle_t *, char *, uint_t, rcm_info_t **); +int rcm_request_offline_list(rcm_handle_t *, char **, uint_t, rcm_info_t **); +int rcm_notify_online(rcm_handle_t *, char *, uint_t, rcm_info_t **); +int rcm_notify_online_list(rcm_handle_t *, char **, uint_t, rcm_info_t **); +int rcm_notify_remove(rcm_handle_t *, char *, uint_t, rcm_info_t **); +int rcm_notify_remove_list(rcm_handle_t *, char **, uint_t, rcm_info_t **); +int rcm_request_suspend(rcm_handle_t *, char *, uint_t, timespec_t *, + rcm_info_t **); +int rcm_request_suspend_list(rcm_handle_t *, char **, uint_t, timespec_t *, + rcm_info_t **); +int rcm_notify_resume(rcm_handle_t *, char *, uint_t, rcm_info_t **); +int rcm_notify_resume_list(rcm_handle_t *, char **, uint_t, rcm_info_t **); +int rcm_notify_event(rcm_handle_t *, char *, uint_t, nvlist_t *, rcm_info_t **); +int rcm_register_event(rcm_handle_t *, char *, uint_t, rcm_info_t **); +int rcm_unregister_event(rcm_handle_t *, char *, uint_t); +int rcm_register_capacity(rcm_handle_t *, char *, uint_t, rcm_info_t **); +int rcm_unregister_capacity(rcm_handle_t *, char *, uint_t); +int rcm_register_interest(rcm_handle_t *, char *, uint_t, rcm_info_t **); +int rcm_unregister_interest(rcm_handle_t *, char *, uint_t); +int rcm_exec_cmd(char *); +char *rcm_module_dir(uint_t); +void *rcm_module_open(char *); +void rcm_module_close(void *); +const char *rcm_get_client_name(rcm_handle_t *); + +char *rcm_script_dir(uint_t); +char *rcm_dir(uint_t, int *); +char *rcm_get_script_dir(char *); +int rcm_is_script(char *); + +/* event related interfaces */ + +int get_event_service(char *, void *, size_t, void **, size_t *); +int create_event_service(char *, void (*)(void **, size_t *)); +int revoke_event_service(int); diff --git a/usr/src/lib/librcm/sparc/Makefile b/usr/src/lib/librcm/sparc/Makefile new file mode 100644 index 0000000000..af76f5ab90 --- /dev/null +++ b/usr/src/lib/librcm/sparc/Makefile @@ -0,0 +1,31 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.com + +install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/librcm/sparcv9/Makefile b/usr/src/lib/librcm/sparcv9/Makefile new file mode 100644 index 0000000000..cb39a2beff --- /dev/null +++ b/usr/src/lib/librcm/sparcv9/Makefile @@ -0,0 +1,32 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.com +include ../../Makefile.lib.64 + +install: all $(ROOTLIBS64) $(ROOTLINKS64) diff --git a/usr/src/lib/librcm/spec/Makefile b/usr/src/lib/librcm/spec/Makefile new file mode 100644 index 0000000000..f181040d29 --- /dev/null +++ b/usr/src/lib/librcm/spec/Makefile @@ -0,0 +1,30 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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) 1999 by Sun Microsystems, Inc. +# All rights reserved. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# lib/librcm/spec/Makefile + +include $(SRC)/lib/Makefile.spec.arch diff --git a/usr/src/lib/librcm/spec/Makefile.targ b/usr/src/lib/librcm/spec/Makefile.targ new file mode 100644 index 0000000000..575ddf3fd6 --- /dev/null +++ b/usr/src/lib/librcm/spec/Makefile.targ @@ -0,0 +1,35 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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) 1999 by Sun Microsystems, Inc. +# All rights reserved. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# lib/librcm/spec/Makefile.targ + +LIBRARY = librcm.a +VERS = .1 + +OBJECTS = rcm.o rcm_event.o + +SPECCPP = -I../.. diff --git a/usr/src/lib/librcm/spec/amd64/Makefile b/usr/src/lib/librcm/spec/amd64/Makefile new file mode 100644 index 0000000000..2a38c1cba9 --- /dev/null +++ b/usr/src/lib/librcm/spec/amd64/Makefile @@ -0,0 +1,42 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.targ + +# Add arch specific objects here +OBJECTS += + +include $(SRC)/lib/Makefile.lib +include $(SRC)/lib/Makefile.lib.64 + +# Uncomment the following if the linker complains +#amd64_C_PICFLAGS = -K PIC + +include $(SRC)/lib/Makefile.spec + +install: $(ROOTABILIB64) diff --git a/usr/src/lib/librcm/spec/i386/Makefile b/usr/src/lib/librcm/spec/i386/Makefile new file mode 100644 index 0000000000..e14fe4ea4d --- /dev/null +++ b/usr/src/lib/librcm/spec/i386/Makefile @@ -0,0 +1,42 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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) 1999 by Sun Microsystems, Inc. +# All rights reserved. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# lib/librcm/spec/i386/Makefile + +include ../Makefile.targ + +# Add arch specific objects here +OBJECTS += + +include $(SRC)/lib/Makefile.lib + +# Uncomment the following if the linker complains +#i386_C_PICFLAGS = -K PIC + +include $(SRC)/lib/Makefile.spec + +install: $(ROOTABILIB) diff --git a/usr/src/lib/librcm/spec/rcm.spec b/usr/src/lib/librcm/spec/rcm.spec new file mode 100644 index 0000000000..775e23db96 --- /dev/null +++ b/usr/src/lib/librcm/spec/rcm.spec @@ -0,0 +1,324 @@ +# +# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# lib/librcm/spec/rcm.spec + +# +# Consolidation private PSARC 1998/460 +# + +function rcm_alloc_handle +include <librcm.h> +declaration int rcm_alloc_handle(char *, uint_t, void *, rcm_handle_t **) +version SUNWprivate_1.1 +end + +function rcm_free_handle +include <librcm.h> +declaration int rcm_free_handle(rcm_handle_t *) +version SUNWprivate_1.1 +end + +function rcm_get_info +include <librcm.h> +include <librcm_impl.h> +declaration int rcm_get_info(rcm_handle_t *, char *, uint_t, rcm_info_t **) +version SUNWprivate_1.1 +end + +function rcm_get_info_list +include <librcm.h> +include <librcm_impl.h> +declaration int rcm_get_info_list(rcm_handle_t *, char **, uint_t, \ + rcm_info_t **) +version SUNWprivate_1.1 +end + +function rcm_free_info +include <librcm.h> +declaration void rcm_free_info(rcm_info_t *) +version SUNWprivate_1.1 +end + +function rcm_append_info +include <librcm.h> +declaration int rcm_append_info(rcm_info_t **, rcm_info_t *) +version SUNWprivate_1.1 +end + +function rcm_info_next +include <librcm.h> +declaration rcm_info_tuple_t *rcm_info_next(rcm_info_t *, \ + rcm_info_tuple_t *) +version SUNWprivate_1.1 +end + +function rcm_info_rsrc +include <librcm.h> +declaration const char *rcm_info_rsrc(rcm_info_tuple_t *) +version SUNWprivate_1.1 +end + +function rcm_info_info +include <librcm.h> +declaration const char *rcm_info_info(rcm_info_tuple_t *) +version SUNWprivate_1.1 +end + +function rcm_info_error +include <librcm.h> +declaration const char *rcm_info_error(rcm_info_tuple_t *) +version SUNWprivate_1.1 +end + +function rcm_info_modname +include <librcm.h> +declaration const char *rcm_info_modname(rcm_info_tuple_t *) +version SUNWprivate_1.1 +end + +function rcm_info_pid +include <librcm.h> +declaration pid_t rcm_info_pid(rcm_info_tuple_t *) +version SUNWprivate_1.1 +end + +function rcm_info_state +include <librcm.h> +declaration int rcm_info_state(rcm_info_tuple_t *) +version SUNWprivate_1.1 +end + +function rcm_info_seqnum +include <librcm.h> +declaration int rcm_info_seqnum(rcm_info_tuple_t *) +version SUNWprivate_1.1 +end + +function rcm_info_properties +include <librcm.h> +declaration nvlist_t *rcm_info_properties(rcm_info_tuple_t *) +version SUNWprivate_1.1 +end + +function rcm_request_offline +include <librcm.h> +declaration int rcm_request_offline(rcm_handle_t *, char *, uint_t, \ + rcm_info_t **) +version SUNWprivate_1.1 +end + +function rcm_request_offline_list +include <librcm.h> +declaration int rcm_request_offline_list(rcm_handle_t *, char **, uint_t, \ + rcm_info_t **) +version SUNWprivate_1.1 +end + +function rcm_notify_online +include <librcm.h> +declaration int rcm_notify_online(rcm_handle_t *, char *, uint_t, \ + rcm_info_t **) +version SUNWprivate_1.1 +end + +function rcm_notify_online_list +include <librcm.h> +declaration int rcm_notify_online_list(rcm_handle_t *, char **, uint_t, \ + rcm_info_t **) +version SUNWprivate_1.1 +end + +function rcm_notify_remove +include <librcm.h> +declaration int rcm_notify_remove(rcm_handle_t *, char *, uint_t, \ + rcm_info_t **) +version SUNWprivate_1.1 +end + +function rcm_notify_remove_list +include <librcm.h> +declaration int rcm_notify_remove_list(rcm_handle_t *, char **, uint_t, \ + rcm_info_t **) +version SUNWprivate_1.1 +end + +function rcm_request_suspend +include <librcm.h> +declaration int rcm_request_suspend(rcm_handle_t *, char *, uint_t, \ + timespec_t *, rcm_info_t **) +version SUNWprivate_1.1 +end + +function rcm_request_suspend_list +include <librcm.h> +declaration int rcm_request_suspend_list(rcm_handle_t *, char **, uint_t, \ + timespec_t *, rcm_info_t **) +version SUNWprivate_1.1 +end + +function rcm_notify_resume +include <librcm.h> +declaration int rcm_notify_resume(rcm_handle_t *, char *, uint_t, \ + rcm_info_t **) +version SUNWprivate_1.1 +end + +function rcm_notify_resume_list +include <librcm.h> +declaration int rcm_notify_resume_list(rcm_handle_t *, char **, uint_t, \ + rcm_info_t **) +version SUNWprivate_1.1 +end + +function rcm_notify_capacity_change +include <librcm.h> +declaration int rcm_notify_capacity_change(rcm_handle_t *, char *, uint_t, \ + nvlist_t *, rcm_info_t **) +version SUNWprivate_1.1 +end + +function rcm_request_capacity_change +include <librcm.h> +declaration int rcm_request_capacity_change(rcm_handle_t *, char *, \ + uint_t, nvlist_t *, rcm_info_t **) +version SUNWprivate_1.1 +end + +function rcm_notify_event +include <librcm.h> +declaration int rcm_notify_event(rcm_handle_t *, char *, uint_t, \ + nvlist_t *, rcm_info_t **) +version SUNWprivate_1.1 +end + +function rcm_register_interest +include <librcm.h> +declaration int rcm_register_interest(rcm_handle_t *, char *, uint_t, \ + rcm_info_t **) +version SUNWprivate_1.1 +end + +function rcm_unregister_interest +include <librcm.h> +declaration int rcm_unregister_interest(rcm_handle_t *, char *, uint_t) +version SUNWprivate_1.1 +end + +function rcm_register_event +include <librcm.h> +declaration int rcm_register_event(rcm_handle_t *, char *, uint_t, \ + rcm_info_t **) +version SUNWprivate_1.1 +end + +function rcm_unregister_event +include <librcm.h> +declaration int rcm_unregister_event(rcm_handle_t *, char *, uint_t) +version SUNWprivate_1.1 +end + +function rcm_register_capacity +include <librcm.h> +declaration int rcm_register_capacity(rcm_handle_t *, char *, uint_t, \ + rcm_info_t **) +version SUNWprivate_1.1 +end + +function rcm_unregister_capacity +include <librcm.h> +declaration int rcm_unregister_capacity(rcm_handle_t *, char *, uint_t) +version SUNWprivate_1.1 +end + +# +# Project private interfaces +# +function rcm_exec_cmd +include <librcm.h> +declaration int rcm_exec_cmd(char *) +version SUNWprivate_1.1 +end + +function rcm_module_dir +include <librcm_impl.h> +declaration char *rcm_module_dir(uint_t) +version SUNWprivate_1.1 +end + +function rcm_script_dir +include <librcm_impl.h> +declaration char *rcm_script_dir(uint_t) +version SUNWprivate_1.1 +end + +function rcm_dir +include <librcm_impl.h> +declaration char *rcm_dir(uint_t, int *) +version SUNWprivate_1.1 +end + +function rcm_get_script_dir +include <librcm_impl.h> +declaration char *rcm_get_script_dir(char *) +version SUNWprivate_1.1 +end + +function rcm_is_script +include <librcm_impl.h> +declaration int rcm_is_script(char *) +version SUNWprivate_1.1 +end + +function rcm_module_open +include <librcm_impl.h> +declaration void *rcm_module_open(char *) +version SUNWprivate_1.1 +end + +function rcm_module_close +include <librcm_impl.h> +declaration void rcm_module_close(void *) +version SUNWprivate_1.1 +end + +function rcm_log_message +include <librcm_impl.h> +declaration void rcm_log_message(int, char *, ...) +version SUNWprivate_1.1 +end + +function rcm_get_rsrcstate +include <librcm_impl.h> +declaration int rcm_get_rsrcstate(rcm_handle_t *, char *, int *) +version SUNWprivate_1.1 +end + +function rcm_get_client_name +include <librcm.h> +declaration const char *rcm_get_client_name(rcm_handle_t *) +version SUNWprivate_1.1 +end diff --git a/usr/src/lib/librcm/spec/rcm_event.spec b/usr/src/lib/librcm/spec/rcm_event.spec new file mode 100644 index 0000000000..f6c238d7eb --- /dev/null +++ b/usr/src/lib/librcm/spec/rcm_event.spec @@ -0,0 +1,45 @@ +# +# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# lib/librcm/spec/rcm_event.spec + +function get_event_service +include <librcm_event.h> +declaration int get_event_service(char *door_name, void *data, size_t datalen, void **result, size_t *rlen) +version SUNWprivate_1.1 +end + +function create_event_service +include <librcm_event.h> +declaration int create_event_service(char *door_name, void (*func)(void **data, size_t *datalen)) +version SUNWprivate_1.1 +end + +function revoke_event_service +include <librcm_event.h> +declaration int revoke_event_service(int fd) +version SUNWprivate_1.1 +end diff --git a/usr/src/lib/librcm/spec/sparc/Makefile b/usr/src/lib/librcm/spec/sparc/Makefile new file mode 100644 index 0000000000..486cdc5f7d --- /dev/null +++ b/usr/src/lib/librcm/spec/sparc/Makefile @@ -0,0 +1,44 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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) 1999 by Sun Microsystems, Inc. +# All rights reserved. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# lib/librcm/spec/sparc/Makefile + +.KEEP_STATE: + +include ../Makefile.targ + +# Add arch specific objects here +OBJECTS += + +include $(SRC)/lib/Makefile.lib + +# Uncomment the following if the linker complains +#sparc_C_PICFLAGS = -K PIC + +include $(SRC)/lib/Makefile.spec + +install: $(ROOTABILIB) diff --git a/usr/src/lib/librcm/spec/sparcv9/Makefile b/usr/src/lib/librcm/spec/sparcv9/Makefile new file mode 100644 index 0000000000..2d5a76c3aa --- /dev/null +++ b/usr/src/lib/librcm/spec/sparcv9/Makefile @@ -0,0 +1,43 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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) 1999 by Sun Microsystems, Inc. +# All rights reserved. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# lib/librcm/spec/sparcv9/Makefile + +include ../Makefile.targ + +# Add arch specific objects here +OBJECTS += + +include $(SRC)/lib/Makefile.lib +include $(SRC)/lib/Makefile.lib.64 + +# Uncomment the following if the linker complains +#sparcv9_C_PICFLAGS = -K PIC + +include $(SRC)/lib/Makefile.spec + +install: $(ROOTABILIB64) diff --git a/usr/src/lib/librcm/spec/versions b/usr/src/lib/librcm/spec/versions new file mode 100644 index 0000000000..a986dca11b --- /dev/null +++ b/usr/src/lib/librcm/spec/versions @@ -0,0 +1,41 @@ +# +# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 +# +# ident "%Z%%M% %I% %E% SMI" +# +# SUNW_1.1: Private (consolidation) PSARC 1998/??? +# + +sparc { + SUNWprivate_1.1; +} +sparcv9 { + SUNWprivate_1.1; +} +i386 { + SUNWprivate_1.1; +} +amd64 { + SUNWprivate_1.1; +} |