1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 /*
  23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #pragma ident   "%Z%%M% %I%     %E% SMI"
  28 
  29 #include <unistd.h>
  30 #include <picl.h>
  31 #include <picltree.h>
  32 #include <picldefs.h>
  33 #include <pthread.h>
  34 #include <syslog.h>
  35 #include <string.h>
  36 #include <libnvpair.h>
  37 #include <libintl.h>
  38 #include "piclenvmond.h"
  39 
  40 /* external funcs and varaibles */
  41 extern void env_handle_event(const char *, const void *, size_t);
  42 extern picl_errno_t env_init();
  43 extern void env_platmod_fini();
  44 extern int sensor_fd;
  45 extern pthread_t env_temp_thr_tid;
  46 
  47 /* local defines */
  48 #define TIMEOUT (10)
  49 
  50 #pragma init(piclenvmond_register)
  51 
  52 /*
  53  * Plugin registration entry points
  54  */
  55 static void piclenvmond_register(void);
  56 static void piclenvmond_init(void);
  57 static void piclenvmond_fini(void);
  58 static void piclenvmond_evhandler(const char *, const void *, size_t, void *);
  59 
  60 int env_debug = 0x0;
  61 
  62 static picld_plugin_reg_t envmond_reg_info = {
  63         PICLD_PLUGIN_VERSION_1,
  64         PICLD_PLUGIN_CRITICAL,
  65         "SUNW_piclenvmond",
  66         piclenvmond_init,
  67         piclenvmond_fini
  68 };
  69 
  70 typedef struct {
  71         picl_nodehdl_t nodehdl;
  72         char node_name[PICL_PROPNAMELEN_MAX];
  73 } env_callback_args_t;
  74 
  75 /*
  76  * picld entry points
  77  */
  78 static void
  79 piclenvmond_register(void)
  80 {
  81         (void) picld_plugin_register(&envmond_reg_info);
  82 }
  83 
  84 /*
  85  * picld entry point
  86  *  - do all the initialization
  87  *  - register for interested picl events
  88  */
  89 static void
  90 piclenvmond_init(void)
  91 {
  92         picl_errno_t rc = PICL_SUCCESS;
  93 
  94         if ((rc = env_init()) != PICL_SUCCESS) {
  95                 syslog(LOG_ERR, gettext("SUNW_envmond:envmond init failed, "
  96                         "error = %d"), rc);
  97                 return;
  98         }
  99 
 100         /* register handler for state change events */
 101         (void) ptree_register_handler(PICLEVENT_STATE_CHANGE,
 102                 piclenvmond_evhandler, NULL);
 103         /* register handler for condition change events */
 104         (void) ptree_register_handler(PICLEVENT_CONDITION_CHANGE,
 105                 piclenvmond_evhandler, NULL);
 106 
 107 }
 108 
 109 static void
 110 piclenvmond_fini(void)
 111 {
 112         void            *exitval;
 113 
 114         /* unregister event handler */
 115         (void) ptree_unregister_handler(PICLEVENT_STATE_CHANGE,
 116                 piclenvmond_evhandler, NULL);
 117         (void) ptree_unregister_handler(PICLEVENT_CONDITION_CHANGE,
 118                 piclenvmond_evhandler, NULL);
 119 
 120         /* cancel all the threads */
 121         (void) pthread_cancel(env_temp_thr_tid);
 122         (void) pthread_join(env_temp_thr_tid, &exitval);
 123 
 124         /* do any platform specific cleanups required */
 125         env_platmod_fini();
 126         (void) close(sensor_fd);
 127 }
 128 
 129 /*ARGSUSED*/
 130 static void
 131 piclenvmond_evhandler(const char *ename, const void *earg, size_t size,
 132         void *cookie)
 133 {
 134         env_handle_event(ename, earg, size);
 135 }
 136 
 137 /*
 138  * Utility functions
 139  */
 140 
 141 /*
 142  * create_property -- Create a PICL property
 143  */
 144 picl_errno_t
 145 env_create_property(int ptype, int pmode, size_t psize, char *pname,
 146         int (*readfn)(ptree_rarg_t *, void *),
 147         int (*writefn)(ptree_warg_t *, const void *),
 148         picl_nodehdl_t nodeh, picl_prophdl_t *propp, void *vbuf)
 149 {
 150         picl_errno_t            rc;             /* return code */
 151         ptree_propinfo_t        propinfo;       /* propinfo structure */
 152         picl_prophdl_t          proph;
 153 
 154         rc = ptree_get_prop_by_name(nodeh, pname, &proph);
 155         if (rc == PICL_SUCCESS) {       /* prop. already exists */
 156                 return (rc);
 157         }
 158 
 159         rc = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
 160                 ptype, pmode, psize, pname, readfn, writefn);
 161         if (rc != PICL_SUCCESS) {
 162                 syslog(LOG_ERR, PTREE_INIT_PROPINFO_FAILED_MSG, rc);
 163                 return (rc);
 164         }
 165 
 166         rc = ptree_create_and_add_prop(nodeh, &propinfo, vbuf, propp);
 167         if (rc != PICL_SUCCESS) {
 168                 syslog(LOG_ERR, PTREE_CREATE_AND_ADD_PROP_FAILED_MSG, rc);
 169                 return (rc);
 170         }
 171         return (PICL_SUCCESS);
 172 }
 173 
 174 /*
 175  * The picl event completion handler.
 176  */
 177 /* ARGSUSED */
 178 static void
 179 event_completion_handler(char *ename, void *earg, size_t size)
 180 {
 181         free(earg);
 182         free(ename);
 183 }
 184 
 185 /*
 186  * utility routine to post PICL events
 187  */
 188 /*ARGSUSED*/
 189 static int
 190 post_picl_event(const char *ename, char *envl, size_t elen,
 191         picl_nodehdl_t nodeh, int cond_wait)
 192 {
 193         nvlist_t        *nvlp;
 194         size_t          nvl_size;
 195         char            *pack_buf = NULL;
 196         char            *evname;
 197 
 198         if (nodeh == 0) {
 199                 return (PICL_FAILURE);
 200         }
 201         if ((evname = strdup(ename)) == NULL)
 202                 return (PICL_FAILURE);
 203         if (envl) {
 204                 if (nvlist_unpack(envl, elen, &nvlp, 0) < 0) {
 205                         nvlist_free(nvlp);
 206                         free(evname);
 207                         return (PICL_FAILURE);
 208                 }
 209         } else {
 210                 if (nvlist_alloc(&nvlp, NV_UNIQUE_NAME_TYPE, NULL)) {
 211                         free(evname);
 212                         return (PICL_FAILURE);
 213                 }
 214         }
 215 
 216         if (nvlist_add_uint64(nvlp, PICLEVENTARG_NODEHANDLE, nodeh) == -1) {
 217                 nvlist_free(nvlp);
 218                 free(evname);
 219                 return (PICL_FAILURE);
 220         }
 221 
 222         if (nvlist_pack(nvlp, &pack_buf, &nvl_size, NV_ENCODE_NATIVE, NULL)) {
 223                 nvlist_free(nvlp);
 224                 free(evname);
 225                 return (PICL_FAILURE);
 226         }
 227         nvlist_free(nvlp);
 228 
 229         if (env_debug & EVENTS) {
 230                 char enodename[PICL_PROPNAMELEN_MAX];
 231                 if (ptree_get_propval_by_name(nodeh, PICL_PROP_NAME,
 232                         enodename, sizeof (enodename)) == PICL_SUCCESS)
 233                         syslog(LOG_INFO, "envmond:Posting %s on %s\n",
 234                                 ename, enodename);
 235         }
 236 
 237         if (ptree_post_event(evname, pack_buf, nvl_size,
 238                 event_completion_handler) != 0) {
 239                 syslog(LOG_ERR, gettext("SUNW_envmond: Error posting %s PICL"
 240                         " event."), ename);
 241                 free(pack_buf);
 242                 free(evname);
 243                 return (PICL_FAILURE);
 244         }
 245         return (PICL_SUCCESS);
 246 }
 247 
 248 /*
 249  * post dr_req events
 250  */
 251 picl_errno_t
 252 post_dr_req_event(picl_nodehdl_t fruh, char *dr_req_type, uint8_t wait)
 253 {
 254         nvlist_t        *nvlp;  /* nvlist of event specific args */
 255         size_t          nvl_size;
 256         char            *pack_buf = NULL;
 257         char            dr_ap_id[PICL_PROPNAMELEN_MAX];
 258         int rc = PICL_SUCCESS;
 259 
 260         if (env_debug & DEBUG)
 261                 syslog(LOG_DEBUG, "Post %s on %llx", dr_req_type, fruh);
 262         if (fruh == 0) {
 263                 return (PICL_INVALIDARG);
 264         }
 265         if ((rc = ptree_get_propval_by_name(fruh, PICL_PROP_NAME,
 266                 dr_ap_id, sizeof (dr_ap_id))) != PICL_SUCCESS) {
 267                 return (rc);
 268         }
 269 
 270         if (nvlist_alloc(&nvlp, NV_UNIQUE_NAME_TYPE, NULL)) {
 271                 return (PICL_FAILURE);
 272         }
 273 
 274         if (nvlist_add_string(nvlp, PICLEVENTARG_AP_ID, dr_ap_id) == -1) {
 275                 nvlist_free(nvlp);
 276                 return (PICL_FAILURE);
 277         }
 278         if (nvlist_add_string(nvlp, PICLEVENTARG_DR_REQ_TYPE, dr_req_type)
 279                 == -1) {
 280                 nvlist_free(nvlp);
 281                 return (PICL_FAILURE);
 282         }
 283         if (nvlist_pack(nvlp, &pack_buf, &nvl_size, NV_ENCODE_NATIVE, NULL)) {
 284                 nvlist_free(nvlp);
 285                 return (PICL_FAILURE);
 286         }
 287         nvlist_free(nvlp);
 288 
 289         if (env_debug & DEBUG)
 290                 syslog(LOG_DEBUG, "Posting %s on %s", dr_req_type, dr_ap_id);
 291         rc = post_picl_event(PICLEVENT_DR_REQ, pack_buf, nvl_size, fruh,
 292                 wait);
 293 
 294         free(pack_buf);
 295         return (rc);
 296 }
 297 
 298 /*
 299  * routine to post dr_ap_state change events
 300  */
 301 picl_errno_t
 302 post_dr_ap_state_change_event(picl_nodehdl_t nodehdl, char *dr_hint,
 303         uint8_t wait)
 304 {
 305         nvlist_t        *nvlp;  /* nvlist of event specific args */
 306         size_t          nvl_size;
 307         char            *pack_buf = NULL;
 308         char            dr_ap_id[PICL_PROPNAMELEN_MAX];
 309         int rc = PICL_SUCCESS;
 310 
 311         if (nodehdl == 0) {
 312                 return (PICL_FAILURE);
 313         }
 314         if ((rc = ptree_get_propval_by_name(nodehdl, PICL_PROP_NAME,
 315                 dr_ap_id, sizeof (dr_ap_id))) != PICL_SUCCESS) {
 316                 return (rc);
 317         }
 318         if (nvlist_alloc(&nvlp, NV_UNIQUE_NAME_TYPE, NULL)) {
 319                 return (PICL_FAILURE);
 320         }
 321 
 322         if (nvlist_add_string(nvlp, PICLEVENTARG_AP_ID, dr_ap_id) == -1) {
 323                 nvlist_free(nvlp);
 324                 return (PICL_FAILURE);
 325         }
 326         if (nvlist_add_string(nvlp, PICLEVENTARG_HINT, dr_hint) == -1) {
 327                 nvlist_free(nvlp);
 328                 return (PICL_FAILURE);
 329         }
 330         if (nvlist_pack(nvlp, &pack_buf, &nvl_size, NV_ENCODE_NATIVE, NULL)) {
 331                 nvlist_free(nvlp);
 332                 return (PICL_FAILURE);
 333         }
 334         nvlist_free(nvlp);
 335         rc = post_picl_event(PICLEVENT_DR_AP_STATE_CHANGE, pack_buf,
 336                 nvl_size, nodehdl, wait);
 337         free(pack_buf);
 338         return (rc);
 339 }
 340 
 341 picl_errno_t
 342 post_cpu_state_change_event(picl_nodehdl_t fruh, char *event_type, uint8_t wait)
 343 {
 344         nvlist_t        *nvlp;  /* nvlist of event specific args */
 345         size_t          nvl_size;
 346         char            *pack_buf = NULL;
 347         int rc = PICL_SUCCESS;
 348 
 349         if (fruh == 0) {
 350                 return (PICL_FAILURE);
 351         }
 352 
 353         if (nvlist_alloc(&nvlp, NV_UNIQUE_NAME_TYPE, NULL))
 354                 return (PICL_FAILURE);
 355 
 356         if (nvlist_add_int64(nvlp, PICLEVENTARG_NODEHANDLE, fruh)) {
 357                 nvlist_free(nvlp);
 358                 return (PICL_FAILURE);
 359         }
 360 
 361         if (nvlist_add_string(nvlp, PICLEVENTARG_CPU_EV_TYPE,
 362                 event_type) == -1) {
 363                 nvlist_free(nvlp);
 364                 return (PICL_FAILURE);
 365         }
 366 
 367         if (nvlist_pack(nvlp, &pack_buf, &nvl_size, NV_ENCODE_NATIVE, NULL)) {
 368                 nvlist_free(nvlp);
 369                 return (PICL_FAILURE);
 370         }
 371         nvlist_free(nvlp);
 372         rc = post_picl_event(PICLEVENT_CPU_STATE_CHANGE, pack_buf,
 373                 nvl_size, fruh, wait);
 374         free(pack_buf);
 375         return (rc);
 376 }
 377 
 378 int
 379 post_sensor_event(picl_nodehdl_t hdl, char *sensor_evalue, uint8_t wait)
 380 {
 381         nvlist_t        *nvlp;  /* nvlist of event specific args */
 382         size_t          nvl_size;
 383         char            *pack_buf = NULL;
 384         char            dr_ap_id[PICL_PROPNAMELEN_MAX];
 385         int rc = PICL_SUCCESS;
 386 
 387         if (env_debug & DEBUG)
 388                 syslog(LOG_DEBUG, "Post %s on %llx", sensor_evalue, hdl);
 389         if (hdl == 0)
 390                 return (PICL_FAILURE);
 391 
 392         if (nvlist_alloc(&nvlp, NV_UNIQUE_NAME_TYPE, NULL))
 393                 return (PICL_FAILURE);
 394 
 395         if (nvlist_add_string(nvlp, PICLEVENTARG_CONDITION,
 396                 sensor_evalue) == -1) {
 397                 nvlist_free(nvlp);
 398                 return (PICL_FAILURE);
 399         }
 400         if (nvlist_pack(nvlp, &pack_buf, &nvl_size, NV_ENCODE_NATIVE, NULL)) {
 401                 nvlist_free(nvlp);
 402                 return (PICL_FAILURE);
 403         }
 404         nvlist_free(nvlp);
 405 
 406         if (env_debug & DEBUG) {
 407                 if (ptree_get_propval_by_name(hdl, PICL_PROP_NAME, dr_ap_id,
 408                         sizeof (dr_ap_id)) == PICL_SUCCESS)
 409                         syslog(LOG_DEBUG, "Posting %s on %s", sensor_evalue,
 410                                 dr_ap_id);
 411         }
 412         rc = post_picl_event(PICLEVENT_CONDITION_CHANGE, pack_buf, nvl_size,
 413                 hdl, wait);
 414         free(pack_buf);
 415         return (rc);
 416 }
 417 
 418 /*
 419  * return B_TRUE if admin lock is enabled
 420  * return B_FALSE if admin lock is disabled
 421  */
 422 boolean_t
 423 env_admin_lock_enabled(picl_nodehdl_t fruh)
 424 {
 425         char            adminlock[PICL_PROPNAMELEN_MAX];
 426 
 427         if (ptree_get_propval_by_name(fruh, PICL_PROP_ADMIN_LOCK,
 428                 adminlock, sizeof (adminlock))
 429                 != PICL_SUCCESS) {
 430                 return (B_FALSE);
 431         }
 432         if (strcmp(adminlock, PICL_ADMINLOCK_ENABLED) == 0) {
 433                 return (B_TRUE);
 434         }
 435         return (B_FALSE);
 436 }