xref: /illumos-gate/usr/src/cmd/picl/plugins/sun4u/taco/envd/piclenvsetup.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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 /*
30  * This file contains code for setting up environmental related nodes
31  * and properties in the PICL tree.
32  *
33  */
34 
35 #include <stdio.h>
36 #include <fcntl.h>
37 #include <unistd.h>
38 #include <syslog.h>
39 #include <stdlib.h>
40 #include <errno.h>
41 #include <limits.h>
42 #include <sys/open.h>
43 #include <ctype.h>
44 #include <string.h>
45 #include <alloca.h>
46 #include <libintl.h>
47 #include <sys/systeminfo.h>
48 #include <picl.h>
49 #include <picltree.h>
50 #include <picld_pluginutil.h>
51 #include <pthread.h>
52 #include <sys/utsname.h>
53 #include <sys/systeminfo.h>
54 #include "picldefs.h"
55 #include "envd.h"
56 
57 /*
58  * Volatile property read/write function typedef
59  */
60 typedef int ptree_vol_rdfunc_t(ptree_rarg_t *parg, void *buf);
61 typedef int ptree_vol_wrfunc_t(ptree_warg_t *parg, const void *buf);
62 
63 
64 extern sensor_ctrl_blk_t sensor_ctrl[];
65 extern fan_ctrl_blk_t fan_ctrl[];
66 extern env_tuneable_t	tuneables[];
67 extern int ntuneables;
68 
69 #define	PROP_FAN_SPEED_UNIT_VALUE	"rpm"
70 
71 /*
72  * Sensor node data structure
73  */
74 typedef struct {
75 	char		*parent_path;	/* parent path */
76 	char		*sensor_name;	/* sensor name */
77 	env_sensor_t	*sensorp;	/* sensor info */
78 	picl_nodehdl_t	nodeh;		/* sensor node handle */
79 	picl_prophdl_t	proph;		/* "Temperature" property handle */
80 	picl_prophdl_t	target_proph;	/* "TargetTemp" property handle */
81 } sensor_node_t;
82 
83 
84 /*
85  * Sensor nodes array
86  */
87 static sensor_node_t sensor_nodes[] = {
88 	{"/platform/pci@1e,600000/isa@7/i2c@0,320/hardware-monitor@0,5c",
89 	SENSOR_CPU_DIE, NULL,
90 	NULL, NULL, NULL},
91 
92 	{"/platform/pci@1e,600000/isa@7/i2c@0,320/hardware-monitor@0,5c",
93 	SENSOR_INT_AMB, NULL,
94 	NULL, NULL, NULL},
95 
96 	{"/platform/pci@1e,600000/isa@7/i2c@0,320/hardware-monitor@0,5c",
97 	SENSOR_SYS_IN, NULL,
98 	NULL, NULL, NULL}
99 };
100 #define	NSENSORS	(sizeof (sensor_nodes)/sizeof (sensor_nodes[0]))
101 
102 
103 /*
104  * Fan node data structure
105  */
106 typedef struct {
107 	char		*parent_path;	/* parent node path */
108 	char		*fan_name;	/* fan name */
109 	env_fan_t 	*fanp;		/* fan information */
110 	char		*speed_unit;	/* speed unit string */
111 	picl_nodehdl_t	nodeh;		/* "fan" node handle */
112 	picl_prophdl_t	proph;		/* "Speed" property handle */
113 } fan_node_t;
114 
115 
116 /*
117  * Fan node array
118  */
119 static fan_node_t fan_nodes[] =  {
120 	{"/platform/pci@1e,600000/isa@7/i2c@0,320/hardware-monitor@0,5c",
121 	ENV_CPU_FAN, NULL, PROP_FAN_SPEED_UNIT_VALUE, NULL, NULL},
122 
123 	{"/platform/pci@1e,600000/isa@7/i2c@0,320/hardware-monitor@0,5c",
124 	ENV_SYSTEM_INTAKE_FAN, NULL, PROP_FAN_SPEED_UNIT_VALUE, NULL, NULL},
125 
126 	{"/platform/pci@1e,600000/isa@7/i2c@0,320/hardware-monitor@0,5c",
127 	ENV_SYSTEM_OUT_FAN, NULL, PROP_FAN_SPEED_UNIT_VALUE, NULL, NULL}
128 };
129 #define	NFANS	(sizeof (fan_nodes)/sizeof (fan_nodes[0]))
130 
131 /*
132  * Miscellaneous declarations
133  */
134 static void delete_sensor_nodes_and_props(void);
135 static void delete_fan_nodes_and_props(void);
136 
137 
138 /*
139  * Read function for volatile "Temperature" property
140  */
141 static int
142 get_current_temp(ptree_rarg_t *parg, void *buf)
143 {
144 	tempr_t 	temp;
145 	picl_prophdl_t	proph;
146 	sensor_node_t	*snodep;
147 	int		i;
148 
149 	/*
150 	 * Locate the sensor in our sensor_nodes table by matching the
151 	 * property handle and get its temperature.
152 	 */
153 	proph = parg->proph;
154 	for (i = 0; i < NSENSORS; ++i) {
155 		snodep = &sensor_nodes[i];
156 		if (snodep->proph != proph)
157 			continue;
158 
159 		if (get_temperature(snodep->sensorp, &temp) < 0)
160 			break;
161 		(void) memcpy(buf, (caddr_t)&temp, sizeof (tempr_t));
162 		return (PICL_SUCCESS);
163 	}
164 	return (PICL_FAILURE);
165 }
166 /*
167  * Read function for volatile "Speed" property on "fan" class node
168  */
169 static int
170 set_current_speed(ptree_warg_t *parg, const void *buf)
171 {
172 	fanspeed_t	speed;
173 	picl_prophdl_t	proph;
174 	fan_node_t	*fnodep;
175 	int		i, ret;
176 
177 	/*
178 	 * Locate the fan in our fan_nodes table by matching the
179 	 * property handle and get fan speed.
180 	 */
181 	proph = parg->proph;
182 	for (i = 0; i < NFANS; ++i) {
183 		fnodep = &fan_nodes[i];
184 		if (fnodep->proph != proph)
185 			continue;
186 		if (fnodep->fanp->fd == -1)
187 			continue;
188 
189 		(void) memcpy((caddr_t)&speed, buf, sizeof (speed));
190 
191 		ret = set_fan_speed(fnodep->fanp, speed);
192 
193 		if (ret < 0) {
194 			if (ret == -1 && errno == EBUSY)
195 				return (PICL_NOTWRITABLE);
196 			if (ret == -2)
197 				return (PICL_INVALIDARG);
198 			break;
199 		}
200 
201 		return (PICL_SUCCESS);
202 	}
203 	return (PICL_FAILURE);
204 }
205 
206 
207 /*
208  * Read function for volatile "Speed" property on "fan" class node
209  */
210 static int
211 get_current_speed(ptree_rarg_t *parg, void *buf)
212 {
213 	fanspeed_t	speed;
214 	picl_prophdl_t	proph;
215 	fan_node_t	*fnodep;
216 	int		i;
217 
218 	/*
219 	 * Locate the fan in our fan_nodes table by matching the
220 	 * property handle and get fan speed.
221 	 */
222 	proph = parg->proph;
223 	for (i = 0; i < NFANS; ++i) {
224 		fnodep = &fan_nodes[i];
225 		if (fnodep->proph != proph)
226 			continue;
227 		if (fnodep->fanp->fd == -1)
228 			continue;
229 		if (get_fan_speed(fnodep->fanp, &speed) < 0)
230 			break;
231 
232 		(void) memcpy(buf, (caddr_t)&speed, sizeof (speed));
233 		return (PICL_SUCCESS);
234 	}
235 	return (PICL_FAILURE);
236 }
237 
238 /*
239  * Create and add the specified regular property
240  */
241 
242 static int
243 add_regular_prop(picl_nodehdl_t nodeh, char *name, int type, int access,
244     int size, void *valbuf, picl_prophdl_t *prophp)
245 {
246 	int			err;
247 	ptree_propinfo_t	propinfo;
248 	picl_prophdl_t		proph;
249 
250 	err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
251 	    type, access, size, name, NULL, NULL);
252 	if (err != PICL_SUCCESS)
253 		return (err);
254 
255 	err = ptree_create_and_add_prop(nodeh, &propinfo, valbuf, &proph);
256 	if (err == PICL_SUCCESS && prophp)
257 		*prophp = proph;
258 	return (err);
259 }
260 
261 
262 /*
263  * Create and add the specified volatile property
264  */
265 static int
266 add_volatile_prop(picl_nodehdl_t nodeh, char *name, int type, int access,
267     int size, ptree_vol_rdfunc_t *rdfunc, ptree_vol_wrfunc_t *wrfunc,
268     picl_prophdl_t *prophp)
269 {
270 	int			err;
271 	ptree_propinfo_t	propinfo;
272 	picl_prophdl_t		proph;
273 
274 	err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
275 	    type, (access|PICL_VOLATILE), size, name, rdfunc, wrfunc);
276 	if (err != PICL_SUCCESS)
277 		return (err);
278 
279 	err = ptree_create_and_add_prop(nodeh, &propinfo, NULL, &proph);
280 	if (err == PICL_SUCCESS && prophp)
281 		*prophp = proph;
282 	return (err);
283 }
284 
285 /*
286  * Add temperature threshold properties
287  */
288 static void
289 add_sensor_thresh_props(picl_nodehdl_t nodeh, sensor_ctrl_blk_t *threshp)
290 {
291 	picl_prophdl_t	proph;
292 
293 	(void) add_regular_prop(nodeh, PICL_PROP_LOW_POWER_OFF,
294 	    PICL_PTYPE_INT, PICL_READ,
295 	    sizeof (threshp->low_power_off),
296 	    (void *)&(threshp->low_power_off), &proph);
297 
298 	(void) add_regular_prop(nodeh, PICL_PROP_LOW_SHUTDOWN,
299 	    PICL_PTYPE_INT, PICL_READ,
300 	    sizeof (threshp->low_shutdown),
301 	    (void *)&(threshp->low_shutdown), &proph);
302 
303 	(void) add_regular_prop(nodeh, PICL_PROP_LOW_WARNING,
304 	    PICL_PTYPE_INT, PICL_READ,
305 	    sizeof (threshp->low_warning),
306 	    (void *)&(threshp->low_warning), &proph);
307 
308 	(void) add_regular_prop(nodeh, PICL_PROP_HIGH_WARNING,
309 	    PICL_PTYPE_INT, PICL_READ,
310 	    sizeof (threshp->high_warning),
311 	    (void *)&(threshp->high_warning), &proph);
312 
313 	(void) add_regular_prop(nodeh, PICL_PROP_HIGH_SHUTDOWN,
314 	    PICL_PTYPE_INT, PICL_READ,
315 	    sizeof (threshp->high_shutdown),
316 	    (void *)&(threshp->high_shutdown), &proph);
317 
318 	(void) add_regular_prop(nodeh, PICL_PROP_HIGH_POWER_OFF,
319 	    PICL_PTYPE_INT, PICL_READ,
320 	    sizeof (threshp->high_power_off),
321 	    (void *)&(threshp->high_power_off), &proph);
322 }
323 
324 /*
325  * Go through the sensor_nodes array and create those nodes
326  * and the Temperature property to report the temperature.
327  */
328 static int
329 add_sensor_nodes_and_props(void)
330 {
331 	int		err;
332 	char		*pname, *nodename, *devfs_path;
333 	sensor_node_t	*snodep;
334 	sensor_ctrl_blk_t *threshp;
335 	picl_nodehdl_t	nodeh, cnodeh;
336 	picl_prophdl_t	proph;
337 	env_sensor_t	*sensorp;
338 	int		i;
339 
340 	for (i = 0; i < NSENSORS; ++i) {
341 		snodep = &sensor_nodes[i];
342 		/*
343 		 * Get the parent nodeh
344 		 */
345 		err = ptree_get_node_by_path(snodep->parent_path, &nodeh);
346 		if (err != PICL_SUCCESS)
347 			continue;
348 		sensorp = snodep->sensorp;
349 
350 		/*
351 		 * Create temperature-sensor node
352 		 */
353 		nodename = snodep->sensor_name;
354 		err = ptree_create_and_add_node(nodeh, nodename,
355 		    PICL_CLASS_TEMPERATURE_SENSOR, &cnodeh);
356 		if (env_debug)
357 			envd_log(LOG_INFO,
358 			    "Creating PICL sensor node '%s' err:%d\n",
359 			    nodename, err);
360 		if (err != PICL_SUCCESS)
361 			break;
362 
363 		/* save node handle */
364 		snodep->nodeh = cnodeh;
365 
366 		/*
367 		 * Add "devfs_path" property in child node
368 		 */
369 		devfs_path = sensorp->devfs_path;
370 		pname = PICL_PROP_DEVFS_PATH;
371 		err = add_regular_prop(cnodeh, pname,
372 		    PICL_PTYPE_CHARSTRING, PICL_READ,
373 		    strlen(devfs_path)+1, (void *)devfs_path, &proph);
374 		if (err != PICL_SUCCESS)
375 			break;
376 
377 		/*
378 		 * Now add volatile "temperature" volatile property
379 		 * in this "temperature-sensor" class node.
380 		 */
381 		pname = PICL_PROP_TEMPERATURE;
382 		err = add_volatile_prop(cnodeh, pname,
383 		    PICL_PTYPE_INT, PICL_READ, sizeof (tempr_t),
384 		    get_current_temp, NULL, &proph);
385 		if (err != PICL_SUCCESS)
386 			break;
387 
388 		/* Save prop handle */
389 		snodep->proph = proph;
390 
391 		/*
392 		 * Add threshold related properties
393 		 */
394 		threshp = sensorp->es_ptr;
395 
396 		if (threshp != NULL)
397 			add_sensor_thresh_props(cnodeh, threshp);
398 
399 	}
400 	if (err != PICL_SUCCESS) {
401 		delete_sensor_nodes_and_props();
402 		if (env_debug)
403 			envd_log(LOG_INFO,
404 			    "Can't create prop/node for sensor '%s'\n",
405 			    nodename);
406 		return (err);
407 	}
408 	return (PICL_SUCCESS);
409 }
410 
411 /*
412  * Delete all sensor nodes and related properties created by the
413  * add_sensor_prop() for each sensor node in the PICL tree.
414  */
415 static void
416 delete_sensor_nodes_and_props(void)
417 {
418 	sensor_node_t	*snodep;
419 	int		i;
420 
421 	/*
422 	 * Delete/destroy any property created in the sensed device
423 	 * as well as the sensor node and all properties under it.
424 	 * Note that deleiing/destroying a node deletes/destroys
425 	 * all properties within that node.
426 	 */
427 
428 	for (i = 0; i < NSENSORS; ++i) {
429 		snodep = &sensor_nodes[i];
430 		if (snodep->nodeh != NULL) {
431 			/* delete node and all properties under it */
432 			(void) ptree_delete_node(snodep->nodeh);
433 			(void) ptree_destroy_node(snodep->nodeh);
434 			snodep->nodeh = NULL;
435 			snodep->proph = NULL;
436 		}
437 	}
438 }
439 
440 
441 /*
442  * For each entry in fan_nodes[] array, do the following:
443  *	- Create specified "fan" class node.
444  *	- Create "Speed" volatile propery under "fan" class node.
445  *	- Create "SpeedUnit" property under "fan" class node.
446  */
447 static int
448 add_fan_nodes_and_props()
449 {
450 	int		err;
451 	char		*pname, *nodename, *devfs_path;
452 	env_fan_t	*fanp;
453 	fan_node_t	*fnodep;
454 	picl_nodehdl_t	nodeh, cnodeh;
455 	picl_prophdl_t	proph;
456 	int		i;
457 
458 
459 	for (i = 0; i < NFANS; ++i) {
460 		/*
461 		 * Add various fan nodes and properties
462 		 */
463 		fnodep = &fan_nodes[i];
464 		/*
465 		 * get parent nodeh
466 		 */
467 		err = ptree_get_node_by_path(fnodep->parent_path, &nodeh);
468 		if (err != PICL_SUCCESS)
469 			continue;
470 
471 		/*
472 		 * Create "fan" class node and save node handle
473 		 */
474 		nodename = fnodep->fan_name;
475 		err = ptree_create_and_add_node(nodeh, nodename,
476 		    PICL_CLASS_FAN, &cnodeh);
477 		if (env_debug)
478 			envd_log(LOG_INFO,
479 			    "Creating PICL fan node '%s' err:%d\n",
480 			    nodename, err);
481 
482 		if (err != PICL_SUCCESS)
483 			break;
484 		fnodep->nodeh = cnodeh;
485 
486 		/*
487 		 * Add "devfs_path" property in child node
488 		 */
489 		fanp = fnodep->fanp;
490 		devfs_path  = fanp->devfs_path;
491 		pname = PICL_PROP_DEVFS_PATH;
492 		err = add_regular_prop(cnodeh, pname,
493 		    PICL_PTYPE_CHARSTRING, PICL_READ,
494 		    strlen(devfs_path)+1, (void *)devfs_path, &proph);
495 
496 		if (err != PICL_SUCCESS)
497 
498 			break;
499 
500 		/*
501 		 * Add "Speed" volatile property in this "fan"
502 		 * class node and save prop handle.
503 		 */
504 		pname = PICL_PROP_FAN_SPEED;
505 		err = add_volatile_prop(cnodeh, pname, PICL_PTYPE_INT,
506 		    PICL_READ|PICL_WRITE, sizeof (fanspeed_t),
507 		    get_current_speed,
508 		    set_current_speed, &proph);
509 
510 		if (err != PICL_SUCCESS)
511 			break;
512 		fnodep->proph = proph;
513 
514 		/*
515 		 * Add other "fan" class properties
516 		 */
517 		pname = PICL_PROP_FAN_SPEED_UNIT;
518 		err = add_regular_prop(cnodeh, pname,
519 		    PICL_PTYPE_CHARSTRING, PICL_READ,
520 		    strlen(fnodep->speed_unit)+1,
521 		    (void *)fnodep->speed_unit, &proph);
522 
523 		if (err != PICL_SUCCESS)
524 			break;
525 	}
526 	if (err != PICL_SUCCESS) {
527 		delete_fan_nodes_and_props();
528 		if (env_debug)
529 			envd_log(LOG_WARNING,
530 			    "Can't create prop/node for fan '%s'\n",
531 			    nodename);
532 		return (err);
533 	}
534 	return (PICL_SUCCESS);
535 }
536 
537 
538 /*
539  * Delete all fan nodes and related properties created by the
540  * add_fan_props() for each fan node in the PICL tree.
541  */
542 static void
543 delete_fan_nodes_and_props(void)
544 {
545 	fan_node_t	*fnodep;
546 	int		i;
547 
548 	/*
549 	 * Delete/destroy fan node and all properties under it.
550 	 * Note that deleiing/destroying a node deletes/destroys
551 	 * all properties within that node.
552 	 */
553 
554 	for (i = 0; i < NFANS; ++i) {
555 		fnodep = &fan_nodes[i];
556 		if (fnodep->nodeh != NULL) {
557 			(void) ptree_delete_node(fnodep->nodeh);
558 			(void) ptree_destroy_node(fnodep->nodeh);
559 			fnodep->nodeh = NULL;
560 		}
561 	}
562 }
563 
564 /*
565  * Tuneables publishing functions
566  */
567 static int
568 copy_persistent_tuneable(env_tuneable_t *tune, char *buf)
569 {
570 
571 	switch (tune->type) {
572 
573 	case PICL_PTYPE_INT : {
574 		(void) memcpy((int *)tune->value,
575 		    buf, tune->nbytes);
576 		break;
577 	}
578 	case PICL_PTYPE_CHARSTRING : {
579 		(void) memcpy((caddr_t)tune->value,
580 		    buf, tune->nbytes);
581 		break;
582 	}
583 	default	: {
584 		return (PICL_FAILURE);
585 	}
586 	}
587 	return (PICL_SUCCESS);
588 }
589 
590 static void
591 env_parse_tunables(picl_nodehdl_t rooth)
592 {
593 	char	nmbuf[SYS_NMLN];
594 	char    pname[PATH_MAX];
595 
596 	if (sysinfo(SI_PLATFORM, nmbuf, sizeof (nmbuf)) != -1) {
597 		(void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf);
598 		(void) strlcat(pname, TUNABLE_CONF_FILE, PATH_MAX);
599 		if (access(pname, R_OK) == 0) {
600 			(void) picld_pluginutil_parse_config_file(rooth, pname);
601 			return;
602 		}
603 	}
604 }
605 
606 int
607 env_picl_setup_tuneables(void)
608 {
609 	int		err;
610 	int		i;
611 	picl_nodehdl_t	nodeh;
612 	picl_nodehdl_t	rooth;
613 	picl_prophdl_t	proph;
614 	env_tuneable_t	*tuneablep;
615 	char		read_buf[BUFSIZ];
616 
617 	if (ptree_get_root(&rooth) != PICL_SUCCESS) {
618 		return (PICL_FAILURE);
619 	}
620 	err = ptree_create_and_add_node(rooth, PICL_PLUGINS_NODE,
621 	    PICL_CLASS_PICL, &nodeh);
622 	if (err != PICL_SUCCESS)
623 		return (PICL_FAILURE);
624 	err = ptree_create_and_add_node(nodeh, PICL_ENVIRONMENTAL_NODE,
625 	    PICL_CLASS_PICL, &nodeh);
626 	if (err != PICL_SUCCESS) {
627 		return (PICL_FAILURE);
628 	}
629 
630 	/*
631 	 * Parse the conf file
632 	 */
633 	env_parse_tunables(rooth);
634 	for (i = 0; i < ntuneables; i++) {
635 		tuneablep = &tuneables[i];
636 		err = ptree_get_propval_by_name(nodeh, tuneablep->name,
637 		    read_buf, tuneablep->nbytes);
638 
639 		if (err != PICL_SUCCESS) {
640 			/*
641 			 * Add volitle functions to environmental node
642 			 */
643 			err = add_volatile_prop(nodeh, tuneablep->name,
644 			    tuneablep->type,
645 			    PICL_READ|PICL_WRITE, tuneablep->nbytes,
646 			    tuneablep->rfunc,
647 			    tuneablep->wfunc, &proph);
648 
649 			tuneablep->proph = proph;
650 		} else {
651 			/*
652 			 * property is persistent
653 			 */
654 			(void) copy_persistent_tuneable(tuneablep,
655 			    read_buf);
656 		}
657 	}
658 
659 	return	(PICL_SUCCESS);
660 }
661 
662 /*
663  * Find the ENVMODEL_CONF_FILE file.
664  */
665 static int
666 get_envmodel_conf_file(char *outfilename)
667 {
668 	char	nmbuf[SYS_NMLN];
669 	char    pname[PATH_MAX];
670 
671 	if (sysinfo(SI_PLATFORM, nmbuf, sizeof (nmbuf)) != -1) {
672 		(void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf);
673 		(void) strlcat(pname, ENV_CONF_FILE, PATH_MAX);
674 		if (access(pname, R_OK) == 0) {
675 			(void) strlcpy(outfilename, pname, PATH_MAX);
676 			return (0);
677 		}
678 	}
679 
680 	if (sysinfo(SI_MACHINE, nmbuf, sizeof (nmbuf)) != -1) {
681 		(void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf);
682 		(void) strlcat(pname, ENV_CONF_FILE, PATH_MAX);
683 		if (access(pname, R_OK) == 0) {
684 			(void) strlcpy(outfilename, pname, PATH_MAX);
685 			return (0);
686 		}
687 	}
688 
689 	(void) snprintf(pname, PATH_MAX, "%s/%s", PICLD_COMMON_PLUGIN_DIR,
690 	    ENV_CONF_FILE);
691 
692 	if (access(pname, R_OK) == 0) {
693 		(void) strlcpy(outfilename, pname, PATH_MAX);
694 		return (0);
695 	}
696 
697 	return (-1);
698 }
699 
700 /* Delete all sensor/fan nodes and any properties created by this plugin */
701 void
702 env_picl_destroy(void)
703 {
704 	delete_fan_nodes_and_props();
705 	delete_sensor_nodes_and_props();
706 }
707 
708 void
709 env_picl_setup(void)
710 {
711 	int		err;
712 	sensor_node_t	*snodep;
713 	fan_node_t	*fnodep;
714 	char		fullfilename[PATH_MAX];
715 	picl_nodehdl_t  rooth;
716 	int		i;
717 
718 
719 	/*
720 	 * Initialize sensorp and other fields in the sensor_nodes[] array
721 	 */
722 
723 	for (i = 0; i < NSENSORS; ++i) {
724 		snodep = &sensor_nodes[i];
725 		snodep->sensorp = sensor_lookup(snodep->sensor_name);
726 		snodep->nodeh = NULL;
727 		snodep->proph = NULL;
728 		snodep->target_proph = NULL;
729 	}
730 
731 	/*
732 	 * Initialize fanp and other fields in the fan_nodes[] array
733 	 */
734 	for (i = 0; i < NFANS; ++i) {
735 		fnodep = &fan_nodes[i];
736 		fnodep->fanp = fan_lookup(fnodep->fan_name);
737 		fnodep->nodeh = NULL;
738 		fnodep->proph = NULL;
739 	}
740 
741 	/*
742 	 * Get platform handle and populate PICL tree with environmental
743 	 * nodes and properties
744 	 */
745 
746 	err = add_sensor_nodes_and_props();
747 
748 	if (err == PICL_SUCCESS)
749 		err = add_fan_nodes_and_props();
750 
751 
752 	if (err != PICL_SUCCESS) {
753 		delete_sensor_nodes_and_props();
754 		envd_log(LOG_CRIT, ENVD_PICL_SETUP_FAILED);
755 		return;
756 	}
757 
758 	/*
759 	 * Parse the envmodel.conf file and populate the PICL tree
760 	 */
761 	if (get_envmodel_conf_file(fullfilename) < 0)
762 		envd_log(LOG_CRIT, ENVD_PICL_SETUP_FAILED);
763 	if (ptree_get_root(&rooth) != PICL_SUCCESS)
764 		envd_log(LOG_CRIT, ENVD_PICL_SETUP_FAILED);
765 	err = picld_pluginutil_parse_config_file(rooth, fullfilename);
766 
767 	if (err != PICL_SUCCESS)
768 		envd_log(LOG_CRIT, ENVD_PICL_SETUP_FAILED);
769 }
770