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 }