xref: /titanic_41/usr/src/cmd/hal/addons/cpufreq/addon-cpufreq.c (revision de7d23d85e06f547e8cd4ed4bce494209d63612a)
1a9da3307Snp146283 /***************************************************************************
2a9da3307Snp146283  *
3a9da3307Snp146283  * addon-cpufreq.c : Routines to support CPUFreq interface
4a9da3307Snp146283  *
5*de7d23d8SLin Guo - Sun Microsystems  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
6a9da3307Snp146283  * Use is subject to license terms.
7a9da3307Snp146283  *
8a9da3307Snp146283  * Licensed under the Academic Free License version 2.1
9a9da3307Snp146283  *
10a9da3307Snp146283  ***************************************************************************/
11a9da3307Snp146283 
12a9da3307Snp146283 
13a9da3307Snp146283 #ifdef HAVE_CONFIG_H
14a9da3307Snp146283 #include <config.h>
15a9da3307Snp146283 #endif
16a9da3307Snp146283 
17a9da3307Snp146283 #include <stdio.h>
18a9da3307Snp146283 #include <errno.h>
19a9da3307Snp146283 #include <string.h>
20a9da3307Snp146283 #include <strings.h>
21a9da3307Snp146283 #include <stdarg.h>
22a9da3307Snp146283 #include <unistd.h>
23a9da3307Snp146283 #include <sys/types.h>
24a9da3307Snp146283 #include <sys/wait.h>
25a9da3307Snp146283 #include <stdlib.h>
26a9da3307Snp146283 #include <fcntl.h>
27a9da3307Snp146283 #include <sys/dkio.h>
28a9da3307Snp146283 #include <sys/stat.h>
29a9da3307Snp146283 #include <sys/types.h>
30a9da3307Snp146283 #include <glib.h>
31a9da3307Snp146283 #include <dbus/dbus-glib-lowlevel.h>
32a9da3307Snp146283 #include <dbus/dbus-glib.h>
33a9da3307Snp146283 #include <priv.h>
34a9da3307Snp146283 #include <pwd.h>
35a9da3307Snp146283 
36a9da3307Snp146283 #include <syslog.h>
37a9da3307Snp146283 
38a9da3307Snp146283 #include <libhal.h>
39a9da3307Snp146283 #include "../../hald/logger.h"
40a9da3307Snp146283 #include "../../utils/adt_data.h"
41a9da3307Snp146283 
42a9da3307Snp146283 #include <pwd.h>
43a9da3307Snp146283 #ifdef HAVE_POLKIT
44a9da3307Snp146283 #include <libpolkit.h>
45a9da3307Snp146283 #endif
46a9da3307Snp146283 
47a9da3307Snp146283 #ifdef sun
48a9da3307Snp146283 #include <bsm/adt.h>
49a9da3307Snp146283 #include <bsm/adt_event.h>
50a9da3307Snp146283 #include <sys/pm.h>
51a9da3307Snp146283 #endif
52a9da3307Snp146283 
53a9da3307Snp146283 #define	POWER_CONF_FILE "/etc/power.conf"
54a9da3307Snp146283 #define	PMCONFIG "/usr/sbin/pmconfig -f"
55a9da3307Snp146283 #define	PM "/dev/pm"
56a9da3307Snp146283 
57a9da3307Snp146283 #define	FILE_ARR_SIZE 256
58a9da3307Snp146283 #define	EDIT_TYPE_SIZE 64
59a9da3307Snp146283 #define	ERR_BUF_SIZE 256
60a9da3307Snp146283 
61a9da3307Snp146283 #define	WAIT_TIME 30
62a9da3307Snp146283 
63a9da3307Snp146283 char TMP_CONF_FILE[64] = "/tmp/power.conf.XXXXXX";
64a9da3307Snp146283 const char *sender;
65a9da3307Snp146283 unsigned long 	uid;
66a9da3307Snp146283 
67a9da3307Snp146283 /*
68a9da3307Snp146283  * Specify different CPUFreq related HAL activities that can be done
69a9da3307Snp146283  */
70a9da3307Snp146283 enum hal_type {
71a9da3307Snp146283 	CPU_GOV,
72a9da3307Snp146283 	CPU_PERFORMANCE
73a9da3307Snp146283 };
74a9da3307Snp146283 typedef enum hal_type power_conf_hal_type;
75a9da3307Snp146283 
76a9da3307Snp146283 /*
77a9da3307Snp146283  * Various CPUFreq related editable parameters in the power.conf file
78a9da3307Snp146283  */
79a9da3307Snp146283 typedef struct {
80a9da3307Snp146283 	char	cpu_gov[EDIT_TYPE_SIZE];
81a9da3307Snp146283 	int	cpu_th;
82a9da3307Snp146283 } pconf_edit_type;
83a9da3307Snp146283 
84a9da3307Snp146283 /*
85a9da3307Snp146283  * CPUFreq interospect XML that exports the various CPUFreq HAL interface
86a9da3307Snp146283  * supported methods
87a9da3307Snp146283  */
88a9da3307Snp146283 const char *cpufreq_introspect_xml = \
89a9da3307Snp146283 	"	<method name= \"SetCPUFreqGovernor\">\n \
90a9da3307Snp146283 		<arg type= \"s\" name= \"governor\" direction= \"in\"/>\n \
91a9da3307Snp146283 	</method>\n \
92a9da3307Snp146283 	<method name= \"GetCPUFreqGovernor\">\n \
93a9da3307Snp146283 		<type= \"s\" direction= \"out\"/>\n \
94a9da3307Snp146283 	</method>\n \
95a9da3307Snp146283 	<method name= \"SetCPUFreqPerformance\">\n \
96a9da3307Snp146283 		<arg type=\"i\" direction=\"in\"/>\n \
97a9da3307Snp146283 	</method>\n \
98a9da3307Snp146283 	<method name= \"GetCPUFreqPerformance\">\n \
99a9da3307Snp146283 		<type=\"i\" direction=\"out\"/>\n \
100a9da3307Snp146283 	</method>\n \
101a9da3307Snp146283 	<method name= \"GetCPUFreqAvailableGovernors\">\n \
102*de7d23d8SLin Guo - Sun Microsystems 		<type=\"s\" direction=\"out\"/>\n \
103a9da3307Snp146283 	</method>\n";
104a9da3307Snp146283 
105a9da3307Snp146283 /*
106a9da3307Snp146283  * List of governors that are currently supported
107a9da3307Snp146283  */
108a9da3307Snp146283 char *const gov_list[] = {
109a9da3307Snp146283 	"ondemand",
110a9da3307Snp146283 	"performance",
111a9da3307Snp146283 	NULL
112a9da3307Snp146283 };
113a9da3307Snp146283 
114a9da3307Snp146283 static char current_gov[EDIT_TYPE_SIZE];
115a9da3307Snp146283 
116a9da3307Snp146283 /*
117a9da3307Snp146283  * Free up the mem allocated to hold the DBusError
118a9da3307Snp146283  */
119a9da3307Snp146283 static void
check_and_free_error(DBusError * error)120a9da3307Snp146283 check_and_free_error(DBusError *error)
121a9da3307Snp146283 {
122a9da3307Snp146283 	if (dbus_error_is_set (error)) {
123a9da3307Snp146283 		dbus_error_free (error);
124a9da3307Snp146283 	}
125a9da3307Snp146283 }
126a9da3307Snp146283 
127a9da3307Snp146283 /*
128a9da3307Snp146283  * Edit the /etc/power.conf file to update the cpupm and cpupm_threshold values
129a9da3307Snp146283  * Return 0 on success
130a9da3307Snp146283  *	  1 if the governor is not available or supported
131a9da3307Snp146283  *	 -1 all other errors
132a9da3307Snp146283  * NOTE: Before modifying power.conf, it is first copied into a temp file, and
133a9da3307Snp146283  * pmconfig is executed on the temp file with -f option, which uses temp file
134a9da3307Snp146283  * to set the PM config and then replaces power.conf with the temp file.
135a9da3307Snp146283  */
136a9da3307Snp146283 static int
edit_power_conf_file(pconf_edit_type pc_edit_type,power_conf_hal_type pc_hal_type,char * tmp_file)137a9da3307Snp146283 edit_power_conf_file(pconf_edit_type pc_edit_type,
138a9da3307Snp146283     power_conf_hal_type pc_hal_type, char *tmp_file)
139a9da3307Snp146283 {
140a9da3307Snp146283 	FILE	*pfile;
141a9da3307Snp146283 	char  	tstr[FILE_ARR_SIZE];
142a9da3307Snp146283 	char	temp_str[FILE_ARR_SIZE];
143a9da3307Snp146283 	long	fset = 0;
144a9da3307Snp146283 	long	next_fset = 0;
145a9da3307Snp146283 	char	*file_edit_type;
146a9da3307Snp146283 	char    *file_edit_value;
147a9da3307Snp146283 	char    file_edit_threshold[FILE_ARR_SIZE];
148a9da3307Snp146283 	char	file_update_str[FILE_ARR_SIZE];
149a9da3307Snp146283 	int	res = 0;
150a9da3307Snp146283 	char	cp_cmd_str[128];
151a9da3307Snp146283 	int	tmp_fd;
152a9da3307Snp146283 
153a9da3307Snp146283 	/*
154a9da3307Snp146283 	 * Copy /etc/power.conf to temp file
155a9da3307Snp146283 	 */
156a9da3307Snp146283 	if (tmp_file == NULL) {
157a9da3307Snp146283 		HAL_INFO ((" Invalid temp file name"));
158a9da3307Snp146283 		return (EINVAL);
159a9da3307Snp146283 	}
160a9da3307Snp146283 	sprintf (cp_cmd_str, "/usr/bin/cp %s %s", POWER_CONF_FILE, tmp_file);
161a9da3307Snp146283 	if (system (cp_cmd_str) != 0) {
162a9da3307Snp146283 		HAL_ERROR ((" Error in copying %s to %s, %s",
163a9da3307Snp146283 		    POWER_CONF_FILE, tmp_file, strerror (errno)));
164a9da3307Snp146283 		return (errno);
165a9da3307Snp146283 	}
166a9da3307Snp146283 
167a9da3307Snp146283 	pfile = fopen (tmp_file, "r+");
168a9da3307Snp146283 	if (pfile == NULL) {
169a9da3307Snp146283 		HAL_INFO (("Cannot open file %s: %s",
170a9da3307Snp146283 		    tmp_file, strerror (errno)));
171a9da3307Snp146283 		return (errno);
172a9da3307Snp146283 	}
173a9da3307Snp146283 
174a9da3307Snp146283 	switch (pc_hal_type) {
175a9da3307Snp146283 	case CPU_GOV:
176a9da3307Snp146283 		if ((pc_edit_type.cpu_gov == NULL) ||
177a9da3307Snp146283 		    ((strcmp (pc_edit_type.cpu_gov, "ondemand") != 0) &&
178a9da3307Snp146283 		    (strcmp (pc_edit_type.cpu_gov, "performance") != 0))) {
179a9da3307Snp146283 			HAL_INFO ((" CPU governor is not available/valid."
180a9da3307Snp146283 			    " Should be either ondemand or performance"));
181a9da3307Snp146283 			res = EINVAL;
182a9da3307Snp146283 			goto out;
183a9da3307Snp146283 		}
184a9da3307Snp146283 		file_edit_type = "cpupm";
185a9da3307Snp146283 		if (strcmp (pc_edit_type.cpu_gov, "ondemand") == 0) {
186a9da3307Snp146283 			file_edit_value = " enable";
187a9da3307Snp146283 		} else {
188a9da3307Snp146283 			file_edit_value = "disable";
189a9da3307Snp146283 		}
190a9da3307Snp146283 		break;
191a9da3307Snp146283 	case CPU_PERFORMANCE:
192a9da3307Snp146283 		if (pc_edit_type.cpu_th == NULL) {
193a9da3307Snp146283 			HAL_INFO ((" CPU Threshold is not valid."));
194a9da3307Snp146283 			res = EINVAL;
195a9da3307Snp146283 			goto out;
196a9da3307Snp146283 		}
197a9da3307Snp146283 		file_edit_type = "cpu-threshold";
198a9da3307Snp146283 		sprintf (file_edit_threshold, "%d", pc_edit_type.cpu_th);
199a9da3307Snp146283 		file_edit_value = file_edit_threshold;
200a9da3307Snp146283 		break;
201a9da3307Snp146283 	default:
202a9da3307Snp146283 		HAL_DEBUG ((" Cannot recognize the type of change being"
203a9da3307Snp146283 		    " made to /etc/power.conf"));
204a9da3307Snp146283 			res = EINVAL;
205a9da3307Snp146283 			goto out;
206a9da3307Snp146283 	}
207a9da3307Snp146283 
208a9da3307Snp146283 	while (fgets (tstr, FILE_ARR_SIZE, pfile) != NULL) {
209a9da3307Snp146283 		if ((tstr == NULL) || (strlen (tstr) <= 0))
210a9da3307Snp146283 			continue;
211a9da3307Snp146283 		/*
212a9da3307Snp146283 		 * Look for line containing "cpupm" or "cpu-threshold"
213a9da3307Snp146283 		 */
214a9da3307Snp146283 
215a9da3307Snp146283 		if (strstr (tstr, file_edit_type) == NULL) {
216a9da3307Snp146283 			fset = fset + strlen (tstr);
217a9da3307Snp146283 			continue;
218a9da3307Snp146283 		}
219a9da3307Snp146283 		/*
220a9da3307Snp146283 		 * If the required value already present. Just
221a9da3307Snp146283 		 * return
222a9da3307Snp146283 		 */
223a9da3307Snp146283 		if (strstr (tstr, file_edit_value) != NULL) {
224a9da3307Snp146283 			res = 0;
225a9da3307Snp146283 			goto out;
226a9da3307Snp146283 		}
227a9da3307Snp146283 
228a9da3307Snp146283 		if (fseek (pfile, fset, SEEK_SET) != 0) {
229a9da3307Snp146283 			HAL_ERROR (("\n Error in fseek %s: %s",
230a9da3307Snp146283 			    POWER_CONF_FILE, strerror (errno)));
231a9da3307Snp146283 			res = errno;
232a9da3307Snp146283 			goto out;
233a9da3307Snp146283 		}
234a9da3307Snp146283 		/*
235a9da3307Snp146283 		 * Update the file with new values
236a9da3307Snp146283 		 */
237a9da3307Snp146283 		sprintf (file_update_str, "%s %s \n",
238a9da3307Snp146283 		    file_edit_type, file_edit_value);
239a9da3307Snp146283 
240a9da3307Snp146283 		/*
241a9da3307Snp146283 		 * Check if the currrent line is the last one. If not,
242a9da3307Snp146283 		 * to avoid overwriting and wasting space, move remaining
243a9da3307Snp146283 		 * lines upwards and update at the end
244a9da3307Snp146283 		 */
245a9da3307Snp146283 		next_fset = fset + strlen(tstr);
246a9da3307Snp146283 		if (fseek (pfile, next_fset, SEEK_SET) != 0) {
247a9da3307Snp146283 			HAL_ERROR (("\n Error in fseek %s: %s",
248a9da3307Snp146283 			    tmp_file, strerror (errno)));
249a9da3307Snp146283 			res = errno;
250a9da3307Snp146283 			goto out;
251a9da3307Snp146283 		}
252a9da3307Snp146283 		if (fgets (tstr, FILE_ARR_SIZE, pfile) != NULL) {
253a9da3307Snp146283 			do {
254a9da3307Snp146283 				snprintf (temp_str, FILE_ARR_SIZE,
255a9da3307Snp146283 				    "%s\n", tstr);
256a9da3307Snp146283 				fseek (pfile, fset, SEEK_SET);
257a9da3307Snp146283 				fputs (temp_str, pfile);
258a9da3307Snp146283 				fset = fset + strlen(tstr);
259a9da3307Snp146283 				next_fset = next_fset + strlen(tstr);
260a9da3307Snp146283 				fseek (pfile, next_fset, SEEK_SET);
261a9da3307Snp146283 
262a9da3307Snp146283 			} while (fgets (tstr, FILE_ARR_SIZE, pfile) != NULL);
263a9da3307Snp146283 		}
264a9da3307Snp146283 
265a9da3307Snp146283 		fseek (pfile, fset, SEEK_SET);
266a9da3307Snp146283 
267a9da3307Snp146283 		if (fputs (file_update_str, pfile) == EOF) {
268a9da3307Snp146283 			HAL_ERROR (("\n Error in writing to"
269a9da3307Snp146283 			    " %s: %s", POWER_CONF_FILE,
270a9da3307Snp146283 			    strerror (errno)));
271a9da3307Snp146283 			res = errno;
272a9da3307Snp146283 			goto out;
273a9da3307Snp146283 		}
274a9da3307Snp146283 
275a9da3307Snp146283 		if (fflush (pfile) == EOF) {
276a9da3307Snp146283 			HAL_ERROR (("\n Error in flushing to"
277a9da3307Snp146283 			    " %s: %s", POWER_CONF_FILE,
278a9da3307Snp146283 			    strerror (errno)));
279a9da3307Snp146283 		}
280a9da3307Snp146283 		res = 0;
281a9da3307Snp146283 		goto out;
282a9da3307Snp146283 	}
283a9da3307Snp146283 
284a9da3307Snp146283 	/*
285a9da3307Snp146283 	 * If the pointer comes here, then the property is not already present.
286a9da3307Snp146283 	 * Have to append to the file
287a9da3307Snp146283 	 */
288a9da3307Snp146283 	HAL_DEBUG (("\n Passed value not found. Will append to the file"));
289a9da3307Snp146283 	if (fseek (pfile, 0, SEEK_END) != 0) {
290a9da3307Snp146283 		HAL_ERROR (("\n Error in fseek to %s: %s",
291a9da3307Snp146283 		    POWER_CONF_FILE, strerror (errno)));
292a9da3307Snp146283 		res = errno;
293a9da3307Snp146283 		goto out;
294a9da3307Snp146283 	}
295a9da3307Snp146283 
296a9da3307Snp146283 	/*
297a9da3307Snp146283 	 * Update the file with new values
298a9da3307Snp146283 	 */
299a9da3307Snp146283 	sprintf (file_update_str, "%s %s \n", file_edit_type, file_edit_value);
300a9da3307Snp146283 
301a9da3307Snp146283 	if (fputs (file_update_str, pfile) == EOF) {
302a9da3307Snp146283 		HAL_ERROR (("Error in writing to file %s: %s",
303a9da3307Snp146283 		    POWER_CONF_FILE, strerror (errno)));
304a9da3307Snp146283 		res = errno;
305a9da3307Snp146283 		goto out;
306a9da3307Snp146283 	}
307a9da3307Snp146283 
308a9da3307Snp146283 	if (fflush (pfile) == EOF) {
309a9da3307Snp146283 		HAL_ERROR (("\n Error in flushing to %s: %s",
310a9da3307Snp146283 		    POWER_CONF_FILE, strerror (errno)));
311a9da3307Snp146283 	}
312a9da3307Snp146283 	res = 0;
313a9da3307Snp146283 out:
314a9da3307Snp146283 	fclose (pfile);
315a9da3307Snp146283 	return (res);
316a9da3307Snp146283 }
317a9da3307Snp146283 
318a9da3307Snp146283 /*
319a9da3307Snp146283  * Depending on the type(cpupm or cpu-threshold) to read, check if they are
320a9da3307Snp146283  * present. If present, return the corresponding value through pc_value arg
321a9da3307Snp146283  * and return 1 from the function. If there is no corresponding entry,return 0.
322a9da3307Snp146283  * Return -1 on error
323a9da3307Snp146283  */
324a9da3307Snp146283 
325a9da3307Snp146283 static int
read_power_conf_file(pconf_edit_type * pc_value,power_conf_hal_type pc_hal_type)326a9da3307Snp146283 read_power_conf_file(pconf_edit_type *pc_value,
327a9da3307Snp146283     power_conf_hal_type pc_hal_type)
328a9da3307Snp146283 {
329a9da3307Snp146283 
330a9da3307Snp146283 	FILE	*pfile;
331a9da3307Snp146283 	char  	tstr[FILE_ARR_SIZE];
332a9da3307Snp146283 	long	fset = 0;
333a9da3307Snp146283 	char	*file_edit_type;
334a9da3307Snp146283 	char	*tpstr;
335a9da3307Snp146283 	int	res = 0;
336a9da3307Snp146283 
337a9da3307Snp146283 	pfile = fopen (POWER_CONF_FILE, "r");
338a9da3307Snp146283 	if (pfile == NULL) {
339a9da3307Snp146283 		HAL_INFO (("\n Cannot open the file %s: %s",
340a9da3307Snp146283 		    POWER_CONF_FILE, strerror (errno)));
341a9da3307Snp146283 		return (-1);
342a9da3307Snp146283 	}
343a9da3307Snp146283 
344a9da3307Snp146283 	switch (pc_hal_type) {
345a9da3307Snp146283 	case CPU_GOV:
346a9da3307Snp146283 		file_edit_type = "cpupm";
347a9da3307Snp146283 		break;
348a9da3307Snp146283 	case CPU_PERFORMANCE:
349a9da3307Snp146283 		file_edit_type = "cpu-threshold";
350a9da3307Snp146283 		break;
351a9da3307Snp146283 	default :
352a9da3307Snp146283 		HAL_DEBUG (("Cannot recognize the HAL type to get value"));
353a9da3307Snp146283 		res = -1;
354a9da3307Snp146283 		goto out;
355a9da3307Snp146283 	}
356a9da3307Snp146283 
357a9da3307Snp146283 	while (fgets (tstr, FILE_ARR_SIZE, pfile) != NULL) {
358a9da3307Snp146283 		if ((tstr == NULL) || (strlen (tstr) <= 0))
359a9da3307Snp146283 			continue;
360a9da3307Snp146283 		/*
361a9da3307Snp146283 		 * Look for line containing "cpupm" or "cpu-threshold"
362a9da3307Snp146283 		 */
363a9da3307Snp146283 		if (strstr (tstr, file_edit_type) == NULL)
364a9da3307Snp146283 			continue;
365a9da3307Snp146283 
366a9da3307Snp146283 		/*
367a9da3307Snp146283 		 * If the required value already present. Just
368a9da3307Snp146283 		 * get the value
369a9da3307Snp146283 		 */
370a9da3307Snp146283 		tpstr = strtok (tstr, " ");
371a9da3307Snp146283 		tpstr = strtok (NULL, " ");
372a9da3307Snp146283 		if (tpstr == NULL) {
373a9da3307Snp146283 			HAL_INFO (("Value of %s in %s is not valid",
374a9da3307Snp146283 			    file_edit_type, POWER_CONF_FILE));
375a9da3307Snp146283 			res = -1;
376a9da3307Snp146283 			goto out;
377a9da3307Snp146283 		}
378a9da3307Snp146283 
379a9da3307Snp146283 		if (pc_hal_type == CPU_GOV) {
380a9da3307Snp146283 			/*
381a9da3307Snp146283 			 * Copy the corresponding governor
382a9da3307Snp146283 			 */
383a9da3307Snp146283 			if (strcmp (tpstr, "enable") == 0) {
384a9da3307Snp146283 				sprintf (pc_value->cpu_gov,
385a9da3307Snp146283 				    "%s", "ondemand");
386a9da3307Snp146283 			} else {
387a9da3307Snp146283 				sprintf (pc_value->cpu_gov,
388a9da3307Snp146283 				    "%s", "performance");
389a9da3307Snp146283 			}
390a9da3307Snp146283 		} else {
391a9da3307Snp146283 			pc_value->cpu_th = atoi (tpstr);
392a9da3307Snp146283 		}
393a9da3307Snp146283 		res = 1;
394a9da3307Snp146283 		goto out;
395a9da3307Snp146283 	}
396a9da3307Snp146283 	/*
397a9da3307Snp146283 	 * Entry not found in the file
398a9da3307Snp146283 	 */
399a9da3307Snp146283 	HAL_DEBUG ((" No entry of %s in %s", file_edit_type, POWER_CONF_FILE));
400a9da3307Snp146283 	res = 0;
401a9da3307Snp146283 
402a9da3307Snp146283 out:
403a9da3307Snp146283 	fclose (pfile);
404a9da3307Snp146283 	return (res);
405a9da3307Snp146283 }
406a9da3307Snp146283 
407a9da3307Snp146283 
408a9da3307Snp146283 /*
409a9da3307Snp146283  * Depending on the type(Governor or Perfromance) to read, get the current
410a9da3307Snp146283  * values through PM ioctls().
411a9da3307Snp146283  * For "Governor", return the cpupm state and for "Performance" return the
412a9da3307Snp146283  * current cpu threshold.
413a9da3307Snp146283  * Return the corresponding value through cur_value and return 1 from the
414a9da3307Snp146283  * function for success. Return -1 on error
415a9da3307Snp146283  */
416a9da3307Snp146283 
417a9da3307Snp146283 static int
get_cur_val(pconf_edit_type * cur_value,power_conf_hal_type pc_hal_type)418a9da3307Snp146283 get_cur_val(pconf_edit_type *cur_value,
419a9da3307Snp146283     power_conf_hal_type pc_hal_type)
420a9da3307Snp146283 {
421a9da3307Snp146283 
422a9da3307Snp146283 	int pm_fd;
423a9da3307Snp146283 	int res = -1;
424a9da3307Snp146283 	int pm_ret;
425a9da3307Snp146283 
426a9da3307Snp146283 	pm_fd = open (PM, O_RDONLY);
427a9da3307Snp146283 	if (pm_fd == -1) {
428a9da3307Snp146283 		HAL_ERROR (("Error opening %s: %s \n", PM, strerror (errno)));
429a9da3307Snp146283 		return (res);
430a9da3307Snp146283 	}
431a9da3307Snp146283 
432a9da3307Snp146283 	switch (pc_hal_type) {
433a9da3307Snp146283 	case CPU_GOV:
434a9da3307Snp146283 		/*
435a9da3307Snp146283 		 * First check the PM_GET_CPUPM_STATE. If it is not available
436a9da3307Snp146283 		 * then check PM_GET_PM_STATE
437a9da3307Snp146283 		 */
438a9da3307Snp146283 		pm_ret = ioctl (pm_fd, PM_GET_CPUPM_STATE);
439a9da3307Snp146283 		if (pm_ret < 0) {
440a9da3307Snp146283 			HAL_ERROR (("Error in ioctl PM_GET_CPUPM_STATE: %s \n",
441a9da3307Snp146283 			    strerror (errno)));
442a9da3307Snp146283 			goto out;
443a9da3307Snp146283 		}
444a9da3307Snp146283 		switch (pm_ret) {
445a9da3307Snp146283 		case PM_CPU_PM_ENABLED:
446a9da3307Snp146283 			sprintf (cur_value->cpu_gov, "%s", "ondemand");
447a9da3307Snp146283 			res = 1;
448a9da3307Snp146283 			goto out;
449a9da3307Snp146283 		case PM_CPU_PM_DISABLED:
450a9da3307Snp146283 			sprintf (cur_value->cpu_gov, "%s", "performance");
451a9da3307Snp146283 			res = 1;
452a9da3307Snp146283 			goto out;
453a9da3307Snp146283 		case PM_CPU_PM_NOTSET:
454a9da3307Snp146283 			/*
455a9da3307Snp146283 			 * Check for PM_GET_PM_STATE
456a9da3307Snp146283 			 */
457a9da3307Snp146283 			pm_ret = ioctl (pm_fd, PM_GET_PM_STATE);
458a9da3307Snp146283 			if (pm_ret < 0) {
459a9da3307Snp146283 				HAL_ERROR (("Error in ioctl PM_GET_PM_STATE: "
460a9da3307Snp146283 				    "%s", strerror (errno)));
461a9da3307Snp146283 				goto out;
462a9da3307Snp146283 			}
463a9da3307Snp146283 			switch (pm_ret) {
464a9da3307Snp146283 			case PM_SYSTEM_PM_ENABLED:
465a9da3307Snp146283 				sprintf (cur_value->cpu_gov, "%s", "ondemand");
466a9da3307Snp146283 				res = 1;
467a9da3307Snp146283 				goto out;
468a9da3307Snp146283 			case PM_SYSTEM_PM_DISABLED:
469a9da3307Snp146283 				sprintf (cur_value->cpu_gov, "%s",
470a9da3307Snp146283 				    "performance");
471a9da3307Snp146283 				res = 1;
472a9da3307Snp146283 				goto out;
473a9da3307Snp146283 			default:
474a9da3307Snp146283 				HAL_ERROR (("PM Internal error during ioctl "
475a9da3307Snp146283 				    "PM_GET_PM_STATE"));
476a9da3307Snp146283 				goto out;
477a9da3307Snp146283 			}
478a9da3307Snp146283 		default:
479a9da3307Snp146283 			HAL_ERROR (("Unknown value ioctl PM_GET_CPUPM_STATE"));
480a9da3307Snp146283 			goto out;
481a9da3307Snp146283 		}
482a9da3307Snp146283 	case CPU_PERFORMANCE:
483a9da3307Snp146283 		/*
484a9da3307Snp146283 		 * First check the PM_GET_CPU_THRESHOLD. If it is not available
485a9da3307Snp146283 		 * then check PM_GET_SYSTEM_THRESHOLD
486a9da3307Snp146283 		 */
487a9da3307Snp146283 		pm_ret = ioctl (pm_fd, PM_GET_CPU_THRESHOLD);
488a9da3307Snp146283 		if (pm_ret >= 0) {
489a9da3307Snp146283 			cur_value->cpu_th = pm_ret;
490a9da3307Snp146283 			res = 1;
491a9da3307Snp146283 			goto out;
492a9da3307Snp146283 		} else if ((pm_ret == EINVAL) || (pm_ret == ENOTTY)) {
493a9da3307Snp146283 			/*
494a9da3307Snp146283 			 * PM_GET_CPU_THRESHOLD is not available
495a9da3307Snp146283 			 */
496a9da3307Snp146283 			pm_ret = ioctl (pm_fd, PM_GET_SYSTEM_THRESHOLD);
497a9da3307Snp146283 			if (res >= 0) {
498a9da3307Snp146283 				cur_value->cpu_th = pm_ret;
499a9da3307Snp146283 				res = 1;
500a9da3307Snp146283 				goto out;
501a9da3307Snp146283 			} else {
502a9da3307Snp146283 				HAL_ERROR (("Error in PM_GET_CPU_THRESHOLD: %s",
503a9da3307Snp146283 				    strerror (errno)));
504a9da3307Snp146283 				goto out;
505a9da3307Snp146283 			}
506a9da3307Snp146283 		} else {
507a9da3307Snp146283 			HAL_ERROR ((" Error in ioctl PM_GET_CPU_THRESHOLD: %s",
508a9da3307Snp146283 			    strerror (errno)));
509a9da3307Snp146283 			goto out;
510a9da3307Snp146283 		}
511a9da3307Snp146283 	default :
512a9da3307Snp146283 		HAL_DEBUG (("Cannot recognize the HAL type to get value"));
513a9da3307Snp146283 		goto out;
514a9da3307Snp146283 	}
515a9da3307Snp146283 out:
516a9da3307Snp146283 	close (pm_fd);
517a9da3307Snp146283 	return (res);
518a9da3307Snp146283 }
519a9da3307Snp146283 /*
520a9da3307Snp146283  * Send an error message as a response to the pending call
521a9da3307Snp146283  */
522a9da3307Snp146283 static void
generate_err_msg(DBusConnection * con,DBusMessage * msg,const char * err_name,char * fmt,...)523a9da3307Snp146283 generate_err_msg(DBusConnection *con,
524a9da3307Snp146283     DBusMessage *msg,
525a9da3307Snp146283     const char *err_name,
526a9da3307Snp146283     char *fmt, ...)
527a9da3307Snp146283 {
528a9da3307Snp146283 
529a9da3307Snp146283 	DBusMessage	*err_msg;
530a9da3307Snp146283 	char		err_buf[ERR_BUF_SIZE];
531a9da3307Snp146283 	va_list		va_args;
532a9da3307Snp146283 
533a9da3307Snp146283 	va_start (va_args, fmt);
534a9da3307Snp146283 	vsnprintf (err_buf, ERR_BUF_SIZE, fmt, va_args);
535a9da3307Snp146283 	va_end (va_args);
536a9da3307Snp146283 
537a9da3307Snp146283 	HAL_DEBUG ((" Sending error message: %s", err_buf));
538a9da3307Snp146283 
539a9da3307Snp146283 	err_msg = dbus_message_new_error (msg, err_name, err_buf);
540a9da3307Snp146283 	if (err_msg == NULL) {
541a9da3307Snp146283 		HAL_ERROR (("No Memory for DBUS error msg"));
542a9da3307Snp146283 		return;
543a9da3307Snp146283 	}
544a9da3307Snp146283 
545a9da3307Snp146283 	if (!dbus_connection_send (con, err_msg, NULL)) {
546a9da3307Snp146283 		HAL_ERROR ((" Out Of Memory!"));
547a9da3307Snp146283 	}
548a9da3307Snp146283 	dbus_connection_flush (con);
549a9da3307Snp146283 
550a9da3307Snp146283 }
551a9da3307Snp146283 
552a9da3307Snp146283 static void
gen_unknown_gov_err(DBusConnection * con,DBusMessage * msg,char * err_str)553a9da3307Snp146283 gen_unknown_gov_err(DBusConnection *con,
554a9da3307Snp146283     DBusMessage *msg,
555a9da3307Snp146283     char *err_str)
556a9da3307Snp146283 {
557a9da3307Snp146283 
558a9da3307Snp146283 	generate_err_msg (con,
559a9da3307Snp146283 	    msg,
560a9da3307Snp146283 	    "org.freedesktop.Hal.CPUFreq.UnknownGovernor",
561a9da3307Snp146283 	    "Unknown CPUFreq Governor: %s",
562a9da3307Snp146283 	    err_str);
563a9da3307Snp146283 }
564a9da3307Snp146283 
565a9da3307Snp146283 static void
gen_no_suitable_gov_err(DBusConnection * con,DBusMessage * msg,char * err_str)566a9da3307Snp146283 gen_no_suitable_gov_err(DBusConnection *con,
567a9da3307Snp146283     DBusMessage *msg,
568a9da3307Snp146283     char *err_str)
569a9da3307Snp146283 {
570a9da3307Snp146283 
571a9da3307Snp146283 	generate_err_msg (con,
572a9da3307Snp146283 	    msg,
573a9da3307Snp146283 	    "org.freedesktop.Hal.CPUFreq.NoSuitableGovernor",
574a9da3307Snp146283 	    "Could not find a suitable governor: %s",
575a9da3307Snp146283 	    err_str);
576a9da3307Snp146283 }
577a9da3307Snp146283 
578a9da3307Snp146283 static void
gen_cpufreq_err(DBusConnection * con,DBusMessage * msg,char * err_str)579a9da3307Snp146283 gen_cpufreq_err(DBusConnection *con,
580a9da3307Snp146283     DBusMessage *msg,
581a9da3307Snp146283     char *err_str)
582a9da3307Snp146283 {
583a9da3307Snp146283 	generate_err_msg (con,
584a9da3307Snp146283 	    msg,
585a9da3307Snp146283 	    "org.freedesktop.Hal.CPUFreq.Error",
586a9da3307Snp146283 	    "%s: Syslog might give more information",
587a9da3307Snp146283 	    err_str);
588a9da3307Snp146283 }
589a9da3307Snp146283 
590a9da3307Snp146283 
591a9da3307Snp146283 /*
592a9da3307Snp146283  * Puts the required cpufreq audit data and calls adt_put_event()
593a9da3307Snp146283  * to generate auditing
594a9da3307Snp146283  */
595a9da3307Snp146283 static void
audit_cpufreq(const adt_export_data_t * imported_state,au_event_t event_id,int result,const char * auth_used,const int cpu_thr_value)596a9da3307Snp146283 audit_cpufreq(const adt_export_data_t *imported_state, au_event_t event_id,
597a9da3307Snp146283     int result, const char *auth_used, const int cpu_thr_value)
598a9da3307Snp146283 {
599a9da3307Snp146283 	adt_session_data_t	*ah;
600a9da3307Snp146283 	adt_event_data_t	*event;
601a9da3307Snp146283 	struct passwd		*msg_pwd;
602a9da3307Snp146283 	uid_t			gid;
603a9da3307Snp146283 
604a9da3307Snp146283 	if (adt_start_session (&ah, imported_state, 0) != 0) {
605a9da3307Snp146283 		HAL_INFO (("adt_start_session failed: %s", strerror (errno)));
606a9da3307Snp146283 		return;
607a9da3307Snp146283 	}
608a9da3307Snp146283 
609a9da3307Snp146283 	if ((event = adt_alloc_event (ah, event_id)) == NULL) {
610a9da3307Snp146283 		HAL_INFO(("adt_alloc_event audit_cpufreq failed: %s",
611a9da3307Snp146283 		    strerror (errno)));
612a9da3307Snp146283 		return;
613a9da3307Snp146283 	}
614a9da3307Snp146283 
615a9da3307Snp146283 	switch (event_id) {
616a9da3307Snp146283 	case ADT_cpu_ondemand:
617a9da3307Snp146283 		event->adt_cpu_ondemand.auth_used = (char *)auth_used;
618a9da3307Snp146283 		break;
619a9da3307Snp146283 	case ADT_cpu_performance:
620a9da3307Snp146283 		event->adt_cpu_performance.auth_used = (char *)auth_used;
621a9da3307Snp146283 		break;
622a9da3307Snp146283 	case ADT_cpu_threshold:
623a9da3307Snp146283 		event->adt_cpu_threshold.auth_used = (char *)auth_used;
624a9da3307Snp146283 		event->adt_cpu_threshold.threshold = cpu_thr_value;
625a9da3307Snp146283 		break;
626a9da3307Snp146283 	default:
627a9da3307Snp146283 		goto clean;
628a9da3307Snp146283 	}
629a9da3307Snp146283 
630a9da3307Snp146283 	if (result == 0) {
631a9da3307Snp146283 		if (adt_put_event (event, ADT_SUCCESS, ADT_SUCCESS) != 0) {
632a9da3307Snp146283 			HAL_INFO (("adt_put_event(%d, ADT_SUCCESS) failed",
633a9da3307Snp146283 			    event_id));
634a9da3307Snp146283 		}
635a9da3307Snp146283 	} else {
636a9da3307Snp146283 		if (adt_put_event (event, ADT_FAILURE, result) != 0) {
637a9da3307Snp146283 			HAL_INFO (("adt_put_event(%d, ADT_FAILURE) failed",
638a9da3307Snp146283 			    event_id));
639a9da3307Snp146283 		}
640a9da3307Snp146283 	}
641a9da3307Snp146283 
642a9da3307Snp146283 clean:
643a9da3307Snp146283 	adt_free_event (event);
644a9da3307Snp146283 	(void) adt_end_session (ah);
645a9da3307Snp146283 }
646a9da3307Snp146283 
647a9da3307Snp146283 /*
648a9da3307Snp146283  * Check if the cpufreq related operations are authorized
649a9da3307Snp146283  */
650a9da3307Snp146283 
651a9da3307Snp146283 static int
check_authorization(DBusConnection * con,DBusMessage * msg)652a9da3307Snp146283 check_authorization(DBusConnection *con, DBusMessage *msg)
653a9da3307Snp146283 {
654a9da3307Snp146283 	int		adt_res = 0;
655a9da3307Snp146283 #ifdef HAVE_POLKIT
656a9da3307Snp146283 	char		user_id[128];
657a9da3307Snp146283 	char		*udi;
658a9da3307Snp146283 	char		*privilege;
659a9da3307Snp146283 	DBusError	error;
660a9da3307Snp146283 	gboolean	is_priv_allowed;
661a9da3307Snp146283 	gboolean	is_priv_temporary;
662a9da3307Snp146283 	DBusConnection	*system_bus = NULL;
663a9da3307Snp146283 	LibPolKitContext *pol_ctx = NULL;
664a9da3307Snp146283 
665a9da3307Snp146283 	/*
666a9da3307Snp146283 	 * Check for authorization before proceeding
667a9da3307Snp146283 	 */
668a9da3307Snp146283 	udi = getenv ("HAL_PROP_INFO_UDI");
669a9da3307Snp146283 	privilege = "hal-power-cpu";
670a9da3307Snp146283 
671a9da3307Snp146283 	dbus_error_init (&error);
672a9da3307Snp146283 	system_bus = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
673a9da3307Snp146283 	if (system_bus == NULL) {
674a9da3307Snp146283 		HAL_INFO (("Cannot connect to the system bus"));
675a9da3307Snp146283 		LIBHAL_FREE_DBUS_ERROR (&error);
676a9da3307Snp146283 		gen_cpufreq_err (con, msg, "Cannot connect to the system bus");
677a9da3307Snp146283 		adt_res = EINVAL;
678a9da3307Snp146283 		goto out;
679a9da3307Snp146283 	}
680a9da3307Snp146283 
681a9da3307Snp146283 	sender = dbus_message_get_sender (msg);
682a9da3307Snp146283 	HAL_INFO (("Auth Sender: %s", sender));
683a9da3307Snp146283 
684a9da3307Snp146283 	if (sender == NULL) {
685a9da3307Snp146283 		HAL_INFO (("Could not get the sender of the message"));
686a9da3307Snp146283 		gen_cpufreq_err (con, msg,
687a9da3307Snp146283 		    "Could not get the sender of the message");
688a9da3307Snp146283 		adt_res = ADT_FAIL_VALUE_AUTH;
689a9da3307Snp146283 		goto out;
690a9da3307Snp146283 	}
691a9da3307Snp146283 
692a9da3307Snp146283 	dbus_error_init (&error);
693a9da3307Snp146283 	uid = dbus_bus_get_unix_user (system_bus, sender, &error);
694a9da3307Snp146283 	if (dbus_error_is_set (&error)) {
695a9da3307Snp146283 		HAL_INFO (("Could not get the user id of the message"));
696a9da3307Snp146283 		LIBHAL_FREE_DBUS_ERROR (&error);
697a9da3307Snp146283 		gen_cpufreq_err (con, msg,
698a9da3307Snp146283 		    "Could not get the user id of the message sender");
699a9da3307Snp146283 		adt_res = ADT_FAIL_VALUE_AUTH;
700a9da3307Snp146283 		goto out;
701a9da3307Snp146283 	}
702a9da3307Snp146283 
703a9da3307Snp146283 	snprintf (user_id, sizeof (user_id), "%d", uid);
704a9da3307Snp146283 	HAL_DEBUG ((" User id is : %d", uid));
705a9da3307Snp146283 
706a9da3307Snp146283 	pol_ctx = libpolkit_new_context (system_bus);
707a9da3307Snp146283 	if (pol_ctx == NULL) {
708a9da3307Snp146283 		HAL_INFO (("Cannot get libpolkit context"));
709a9da3307Snp146283 		gen_cpufreq_err (con, msg,
710a9da3307Snp146283 		    "Cannot get libpolkit context to check privileges");
711a9da3307Snp146283 		adt_res = ADT_FAIL_VALUE_AUTH;
712a9da3307Snp146283 		goto out;
713a9da3307Snp146283 	}
714a9da3307Snp146283 
715a9da3307Snp146283 	if (libpolkit_is_uid_allowed_for_privilege (pol_ctx,
716a9da3307Snp146283 	    NULL,
717a9da3307Snp146283 	    user_id,
718a9da3307Snp146283 	    privilege,
719a9da3307Snp146283 	    udi,
720a9da3307Snp146283 	    &is_priv_allowed,
721a9da3307Snp146283 	    &is_priv_temporary,
722a9da3307Snp146283 	    NULL) != LIBPOLKIT_RESULT_OK) {
723a9da3307Snp146283 		HAL_INFO (("Cannot lookup privilege from PolicyKit"));
724a9da3307Snp146283 		gen_cpufreq_err (con, msg,
725a9da3307Snp146283 		    "Error looking up privileges from Policykit");
726a9da3307Snp146283 		adt_res = ADT_FAIL_VALUE_AUTH;
727a9da3307Snp146283 		goto out;
728a9da3307Snp146283 	}
729a9da3307Snp146283 
730a9da3307Snp146283 	if (!is_priv_allowed) {
731a9da3307Snp146283 		HAL_INFO (("Caller doesn't possess required privilege to"
732a9da3307Snp146283 		    " change the governor"));
733a9da3307Snp146283 		gen_cpufreq_err (con, msg,
734a9da3307Snp146283 		    "Caller doesn't possess required "
735a9da3307Snp146283 		    "privilege to change the governor");
736a9da3307Snp146283 		adt_res = ADT_FAIL_VALUE_AUTH;
737a9da3307Snp146283 		goto out;
738a9da3307Snp146283 	}
739a9da3307Snp146283 
740a9da3307Snp146283 	HAL_DEBUG ((" Privilege Succeed"));
741a9da3307Snp146283 
742a9da3307Snp146283 #endif
743a9da3307Snp146283 out:
744a9da3307Snp146283 	return (adt_res);
745a9da3307Snp146283 }
746a9da3307Snp146283 
747a9da3307Snp146283 /*
748a9da3307Snp146283  * Sets the CPU Freq governor. It sets the gov name in the /etc/power.conf
749a9da3307Snp146283  * and executes pmconfig. If governor is "ondemand" then "cpupm" is enabled in
750a9da3307Snp146283  * and if governor is performance, then "cpupm" is disabled
751a9da3307Snp146283  */
752a9da3307Snp146283 static void
set_cpufreq_gov(DBusConnection * con,DBusMessage * msg,void * udata)753a9da3307Snp146283 set_cpufreq_gov(DBusConnection *con, DBusMessage *msg, void *udata)
754a9da3307Snp146283 {
755a9da3307Snp146283 	DBusMessageIter arg_iter;
756a9da3307Snp146283 	DBusMessage	*msg_reply;
757a9da3307Snp146283 	char		*arg_val;
758a9da3307Snp146283 	int		arg_type;
759a9da3307Snp146283 	int		pid;
760a9da3307Snp146283 	int		done_flag = 0;
761a9da3307Snp146283 	int		sleep_time = 0;
762a9da3307Snp146283 	int		status;
763a9da3307Snp146283 	int		adt_res = 0;
764a9da3307Snp146283 	char		tmp_conf_file[64] = "/tmp/power.conf.XXXXXX";
765a9da3307Snp146283 	int		tmp_fd;
766a9da3307Snp146283 	char		pmconfig_cmd[128];
767a9da3307Snp146283 	pconf_edit_type pc_edit_type;
768a9da3307Snp146283 #ifdef sun
769a9da3307Snp146283 	adt_export_data_t *adt_data;
770a9da3307Snp146283 	size_t 		adt_data_size;
771a9da3307Snp146283 	DBusConnection 	*system_bus = NULL;
772a9da3307Snp146283 	DBusError 	error;
773a9da3307Snp146283 #endif
774a9da3307Snp146283 
775a9da3307Snp146283 	if (! dbus_message_iter_init (msg, &arg_iter)) {
776a9da3307Snp146283 		HAL_DEBUG (("Incoming message has no arguments"));
777a9da3307Snp146283 		gen_unknown_gov_err (con, msg, "No governor specified");
778a9da3307Snp146283 		adt_res = EINVAL;
779a9da3307Snp146283 		goto out;
780a9da3307Snp146283 	}
781a9da3307Snp146283 	arg_type = dbus_message_iter_get_arg_type (&arg_iter);
782a9da3307Snp146283 
783a9da3307Snp146283 	if (arg_type != DBUS_TYPE_STRING) {
784a9da3307Snp146283 		HAL_DEBUG (("Incomming message arg type is not string"));
785a9da3307Snp146283 		gen_unknown_gov_err (con, msg,
786a9da3307Snp146283 		    "Specified governor is not a string");
787a9da3307Snp146283 		adt_res = EINVAL;
788a9da3307Snp146283 		goto out;
789a9da3307Snp146283 	}
790a9da3307Snp146283 	dbus_message_iter_get_basic (&arg_iter, &arg_val);
791a9da3307Snp146283 	if (arg_val != NULL) {
792a9da3307Snp146283 		HAL_DEBUG (("SetCPUFreqGov is: %s", arg_val));
793a9da3307Snp146283 	} else {
794a9da3307Snp146283 		HAL_DEBUG (("Could not get SetCPUFreqGov from message iter"));
795a9da3307Snp146283 		adt_res = EINVAL;
796a9da3307Snp146283 		goto out;
797a9da3307Snp146283 	}
798a9da3307Snp146283 
799a9da3307Snp146283 	adt_res = check_authorization (con, msg);
800a9da3307Snp146283 
801a9da3307Snp146283 	if (adt_res != 0) {
802a9da3307Snp146283 		goto out;
803a9da3307Snp146283 	}
804a9da3307Snp146283 
805a9da3307Snp146283 	/*
806a9da3307Snp146283 	 * Update the /etc/power.conf file.
807a9da3307Snp146283 	 */
808a9da3307Snp146283 	tmp_fd = mkstemp (tmp_conf_file);
809a9da3307Snp146283 	if (tmp_fd == -1) {
810a9da3307Snp146283 		HAL_ERROR ((" Error in creating a temp conf file"));
811a9da3307Snp146283 		adt_res = EINVAL;
812a9da3307Snp146283 		goto out;
813a9da3307Snp146283 	}
814a9da3307Snp146283 	strcpy (pc_edit_type.cpu_gov, arg_val);
815a9da3307Snp146283 	adt_res = edit_power_conf_file (pc_edit_type, CPU_GOV, tmp_conf_file);
816a9da3307Snp146283 	if (adt_res != 0) {
817a9da3307Snp146283 		HAL_DEBUG (("Error in edit /etc/power.conf"));
818a9da3307Snp146283 		gen_cpufreq_err (con, msg,
819a9da3307Snp146283 		    "Internal Error while setting the governor");
820a9da3307Snp146283 		unlink (tmp_conf_file);
821a9da3307Snp146283 		goto out;
822a9da3307Snp146283 	}
823a9da3307Snp146283 
824a9da3307Snp146283 	/*
825a9da3307Snp146283 	 * Execute pmconfig
826a9da3307Snp146283 	 */
827a9da3307Snp146283 	sprintf (pmconfig_cmd, "%s %s", PMCONFIG, tmp_conf_file);
828a9da3307Snp146283 	if (system (pmconfig_cmd) != 0) {
829a9da3307Snp146283 		HAL_ERROR ((" Error in executing pmconfig: %s",
830a9da3307Snp146283 		    strerror (errno)));
831a9da3307Snp146283 		adt_res = errno;
832a9da3307Snp146283 		gen_cpufreq_err (con, msg, "Error in executing pmconfig");
833a9da3307Snp146283 		unlink (tmp_conf_file);
834a9da3307Snp146283 		goto out;
835a9da3307Snp146283 	}
836a9da3307Snp146283 	unlink (tmp_conf_file);
837a9da3307Snp146283 	HAL_DEBUG (("Executed pmconfig"));
838a9da3307Snp146283 	sprintf (current_gov, "%s", arg_val);
839a9da3307Snp146283 
840a9da3307Snp146283 	/*
841a9da3307Snp146283 	 * Just return an empty response, so that if the client
842a9da3307Snp146283 	 * is waiting for any response will not keep waiting
843a9da3307Snp146283 	 */
844a9da3307Snp146283 	msg_reply = dbus_message_new_method_return (msg);
845a9da3307Snp146283 	if (msg_reply == NULL) {
846a9da3307Snp146283 		HAL_ERROR (("Out of memory to msg reply"));
847a9da3307Snp146283 		gen_cpufreq_err (con, msg,
848a9da3307Snp146283 		    "Out of memory to create a response");
849a9da3307Snp146283 		adt_res = ENOMEM;
850a9da3307Snp146283 		goto out;
851a9da3307Snp146283 	}
852a9da3307Snp146283 
853a9da3307Snp146283 	if (!dbus_connection_send (con, msg_reply, NULL)) {
854a9da3307Snp146283 		HAL_ERROR (("Out of memory to msg reply"));
855a9da3307Snp146283 		gen_cpufreq_err (con, msg,
856a9da3307Snp146283 		    "Out of memory to create a response");
857a9da3307Snp146283 		adt_res = ENOMEM;
858a9da3307Snp146283 		goto out;
859a9da3307Snp146283 	}
860a9da3307Snp146283 
861a9da3307Snp146283 	dbus_connection_flush (con);
862a9da3307Snp146283 
863a9da3307Snp146283 out:
864a9da3307Snp146283 
865a9da3307Snp146283 #ifdef sun
866a9da3307Snp146283 	/*
867a9da3307Snp146283 	 * Audit the new governor change
868a9da3307Snp146283 	 */
869a9da3307Snp146283 	dbus_error_init (&error);
870a9da3307Snp146283 	system_bus = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
871a9da3307Snp146283 	if (system_bus == NULL) {
872a9da3307Snp146283 		HAL_INFO (("Cannot connect to the system bus %s",
873a9da3307Snp146283 		    error.message));
874a9da3307Snp146283 		LIBHAL_FREE_DBUS_ERROR (&error);
875a9da3307Snp146283 		return;
876a9da3307Snp146283 	}
877a9da3307Snp146283 
878a9da3307Snp146283 	adt_data = get_audit_export_data (system_bus, sender, &adt_data_size);
879a9da3307Snp146283 	if (adt_data != NULL) {
880a9da3307Snp146283 		if (strcmp (arg_val, "ondemand") == 0) {
881a9da3307Snp146283 			audit_cpufreq (adt_data, ADT_cpu_ondemand, adt_res,
882a9da3307Snp146283 			    "solaris.system.power.cpu", 0);
883a9da3307Snp146283 		} else if (strcmp (arg_val, "performance") == 0) {
884a9da3307Snp146283 			audit_cpufreq (adt_data, ADT_cpu_performance, adt_res,
885a9da3307Snp146283 			    "solaris.system.power.cpu", 0);
886a9da3307Snp146283 		}
887a9da3307Snp146283 		free (adt_data);
888a9da3307Snp146283 	} else {
889a9da3307Snp146283 		HAL_INFO ((" Could not get audit export data"));
890a9da3307Snp146283 	}
891a9da3307Snp146283 #endif /* sun */
892a9da3307Snp146283 }
893a9da3307Snp146283 
894a9da3307Snp146283 /*
895a9da3307Snp146283  * Sets the CPU Freq performance. It sets the cpu-threshold in the
896a9da3307Snp146283  * /etc/power.conf and executes pmconfig. The performnace value should
897a9da3307Snp146283  * be between 1 to 100. The cpu-threshold = ((performance val) * 15) secs.
898a9da3307Snp146283  */
899a9da3307Snp146283 static void
set_cpufreq_performance(DBusConnection * con,DBusMessage * msg,void * udata)900a9da3307Snp146283 set_cpufreq_performance(DBusConnection *con, DBusMessage *msg, void *udata)
901a9da3307Snp146283 {
902a9da3307Snp146283 
903a9da3307Snp146283 	DBusMessageIter arg_iter;
904a9da3307Snp146283 	DBusMessage	*msg_reply;
905a9da3307Snp146283 	int		arg_val;
906a9da3307Snp146283 	int		arg_type;
907a9da3307Snp146283 	int		pid;
908a9da3307Snp146283 	int		done_flag = 0;
909a9da3307Snp146283 	int		sleep_time = 0;
910a9da3307Snp146283 	int		adt_res = 0;
911a9da3307Snp146283 	char		tmp_conf_file[64] = "/tmp/power.conf.XXXXXX";
912a9da3307Snp146283 	int		tmp_fd;
913a9da3307Snp146283 	char		pmconfig_cmd[128];
914a9da3307Snp146283 	pconf_edit_type pc_edit_type;
915a9da3307Snp146283 #ifdef sun
916a9da3307Snp146283 	adt_export_data_t *adt_data;
917a9da3307Snp146283 	size_t 		adt_data_size;
918a9da3307Snp146283 	DBusConnection 	*system_bus = NULL;
919a9da3307Snp146283 	DBusError 	error;
920a9da3307Snp146283 #endif
921a9da3307Snp146283 
922a9da3307Snp146283 	adt_res = check_authorization (con, msg);
923a9da3307Snp146283 
924a9da3307Snp146283 	if (adt_res != 0) {
925a9da3307Snp146283 		goto out;
926a9da3307Snp146283 	}
927a9da3307Snp146283 
928a9da3307Snp146283 	/*
929a9da3307Snp146283 	 * Performance can only be set to dynamic governors. Currently the
930a9da3307Snp146283 	 * only supported dynamic governor is ondemand.
931a9da3307Snp146283 	 */
932a9da3307Snp146283 	if (current_gov[0] == 0) {
933a9da3307Snp146283 		/*
934a9da3307Snp146283 		 * Read the current governor from /etc/power.conf
935a9da3307Snp146283 		 */
936a9da3307Snp146283 		if (read_power_conf_file (&pc_edit_type, CPU_GOV) != 1) {
937a9da3307Snp146283 			HAL_ERROR ((" Error in reading from /etc/power.conf"));
938a9da3307Snp146283 			gen_cpufreq_err (con, msg, "Internal error while "
939a9da3307Snp146283 			    "getting the governor");
940a9da3307Snp146283 			adt_res = EINVAL;
941a9da3307Snp146283 			goto out;
942a9da3307Snp146283 		}
943a9da3307Snp146283 		sprintf (current_gov, "%s", pc_edit_type.cpu_gov);
944a9da3307Snp146283 	}
945a9da3307Snp146283 
946a9da3307Snp146283 	if (strcmp (current_gov, "ondemand") != 0) {
947a9da3307Snp146283 		HAL_DEBUG (("To set performance the current gov should be "
948a9da3307Snp146283 		    "dynamic like ondemand"));
949a9da3307Snp146283 		gen_no_suitable_gov_err (con, msg, "Cannot set performance "
950a9da3307Snp146283 		    "to the current governor");
951a9da3307Snp146283 		adt_res = EINVAL;
952a9da3307Snp146283 		goto out;
953a9da3307Snp146283 	}
954a9da3307Snp146283 
955a9da3307Snp146283 	if (! dbus_message_iter_init (msg, &arg_iter)) {
956a9da3307Snp146283 		HAL_DEBUG (("Incoming message has no arguments"));
957a9da3307Snp146283 		gen_no_suitable_gov_err(con, msg, "No performance specified");
958a9da3307Snp146283 		adt_res = EINVAL;
959a9da3307Snp146283 		goto out;
960a9da3307Snp146283 	}
961a9da3307Snp146283 	arg_type = dbus_message_iter_get_arg_type (&arg_iter);
962a9da3307Snp146283 
963a9da3307Snp146283 	if (arg_type != DBUS_TYPE_INT32) {
964a9da3307Snp146283 		HAL_DEBUG (("Incomming message arg type is not Integer"));
965a9da3307Snp146283 		gen_no_suitable_gov_err (con, msg,
966a9da3307Snp146283 		    "Specified performance is not a Integer");
967a9da3307Snp146283 		adt_res = EINVAL;
968a9da3307Snp146283 		goto out;
969a9da3307Snp146283 	}
970a9da3307Snp146283 	dbus_message_iter_get_basic (&arg_iter, &arg_val);
971a9da3307Snp146283 	if ((arg_val < 1) || (arg_val > 100)) {
972a9da3307Snp146283 		HAL_INFO (("SetCPUFreqPerformance should be between 1 to 100"
973a9da3307Snp146283 		    ": %d", arg_val));
974a9da3307Snp146283 		gen_no_suitable_gov_err (con, msg,
975a9da3307Snp146283 		    "Performance value should be between 1 and 100");
976a9da3307Snp146283 		adt_res = EINVAL;
977a9da3307Snp146283 		goto out;
978a9da3307Snp146283 	}
979a9da3307Snp146283 
980a9da3307Snp146283 	HAL_DEBUG (("SetCPUFreqPerformance is: %d", arg_val));
981a9da3307Snp146283 
982a9da3307Snp146283 	/*
983a9da3307Snp146283 	 * Update the /etc/power.conf file
984a9da3307Snp146283 	 */
985a9da3307Snp146283 	tmp_fd = mkstemp (tmp_conf_file);
986a9da3307Snp146283 	if (tmp_fd == -1) {
987a9da3307Snp146283 		HAL_ERROR ((" Error in creating a temp conf file"));
988a9da3307Snp146283 		adt_res = EINVAL;
989a9da3307Snp146283 		goto out;
990a9da3307Snp146283 	}
991a9da3307Snp146283 	pc_edit_type.cpu_th = arg_val * 15;
992a9da3307Snp146283 	adt_res = edit_power_conf_file (pc_edit_type, CPU_PERFORMANCE,
993a9da3307Snp146283 	    tmp_conf_file);
994a9da3307Snp146283 	if (adt_res != 0) {
995a9da3307Snp146283 		HAL_DEBUG (("Error while editing /etc/power.conf"));
996a9da3307Snp146283 		gen_cpufreq_err (con, msg,
997a9da3307Snp146283 		    "Internal error while setting the performance");
998a9da3307Snp146283 		unlink (tmp_conf_file);
999a9da3307Snp146283 		goto out;
1000a9da3307Snp146283 	}
1001a9da3307Snp146283 
1002a9da3307Snp146283 	/*
1003a9da3307Snp146283 	 * Execute pmconfig
1004a9da3307Snp146283 	 */
1005a9da3307Snp146283 	sprintf (pmconfig_cmd, "%s %s", PMCONFIG, tmp_conf_file);
1006a9da3307Snp146283 	if (system (pmconfig_cmd) != 0) {
1007a9da3307Snp146283 		HAL_ERROR ((" Error in executing pmconfig: %s",
1008a9da3307Snp146283 		    strerror (errno)));
1009a9da3307Snp146283 		adt_res = errno;
1010a9da3307Snp146283 		gen_cpufreq_err (con, msg,
1011a9da3307Snp146283 		    "Internal error while setting the performance");
1012a9da3307Snp146283 		unlink (tmp_conf_file);
1013a9da3307Snp146283 		goto out;
1014a9da3307Snp146283 	}
1015a9da3307Snp146283 	unlink (tmp_conf_file);
1016a9da3307Snp146283 	HAL_DEBUG (("Executed pmconfig"));
1017a9da3307Snp146283 
1018a9da3307Snp146283 	/*
1019a9da3307Snp146283 	 * Just return an empty response, so that if the client
1020a9da3307Snp146283 	 * is waiting for any response will not keep waiting
1021a9da3307Snp146283 	 */
1022a9da3307Snp146283 
1023a9da3307Snp146283 	msg_reply = dbus_message_new_method_return (msg);
1024a9da3307Snp146283 	if (msg_reply == NULL) {
1025a9da3307Snp146283 		HAL_ERROR (("Out of memory to msg reply"));
1026a9da3307Snp146283 		gen_cpufreq_err (con, msg,
1027a9da3307Snp146283 		    "Out of memory to create a response");
1028a9da3307Snp146283 		adt_res = ENOMEM;
1029a9da3307Snp146283 		goto out;
1030a9da3307Snp146283 	}
1031a9da3307Snp146283 
1032a9da3307Snp146283 	if (!dbus_connection_send (con, msg_reply, NULL)) {
1033a9da3307Snp146283 		HAL_ERROR (("Out of memory to msg reply"));
1034a9da3307Snp146283 		gen_cpufreq_err (con, msg,
1035a9da3307Snp146283 		    "Out of memory to create a response");
1036a9da3307Snp146283 		adt_res = ENOMEM;
1037a9da3307Snp146283 		goto out;
1038a9da3307Snp146283 	}
1039a9da3307Snp146283 
1040a9da3307Snp146283 	dbus_connection_flush (con);
1041a9da3307Snp146283 out:
1042a9da3307Snp146283 #ifdef sun
1043a9da3307Snp146283 
1044a9da3307Snp146283 	/*
1045a9da3307Snp146283 	 * Audit the new performance change
1046a9da3307Snp146283 	 */
1047a9da3307Snp146283 	dbus_error_init (&error);
1048a9da3307Snp146283 	system_bus = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
1049a9da3307Snp146283 	if (system_bus == NULL) {
1050a9da3307Snp146283 		HAL_INFO (("Cannot connect to the system bus %s",
1051a9da3307Snp146283 		    error.message));
1052a9da3307Snp146283 		LIBHAL_FREE_DBUS_ERROR (&error);
1053a9da3307Snp146283 		return;
1054a9da3307Snp146283 	}
1055a9da3307Snp146283 
1056a9da3307Snp146283 	adt_data = get_audit_export_data (system_bus, sender, &adt_data_size);
1057a9da3307Snp146283 	if (adt_data != NULL) {
1058a9da3307Snp146283 		audit_cpufreq (adt_data, ADT_cpu_threshold, adt_res,
1059a9da3307Snp146283 		    "solaris.system.power.cpu", arg_val);
1060a9da3307Snp146283 		free (adt_data);
1061a9da3307Snp146283 	} else {
1062a9da3307Snp146283 		HAL_INFO ((" Could not get audit export data"));
1063a9da3307Snp146283 	}
1064a9da3307Snp146283 
1065a9da3307Snp146283 #endif /* sun */
1066a9da3307Snp146283 }
1067a9da3307Snp146283 
1068a9da3307Snp146283 /*
1069a9da3307Snp146283  * Returns in the dbus message the current gov.
1070a9da3307Snp146283  */
1071a9da3307Snp146283 static void
get_cpufreq_gov(DBusConnection * con,DBusMessage * msg,void * udata)1072a9da3307Snp146283 get_cpufreq_gov(DBusConnection *con, DBusMessage *msg, void *udata)
1073a9da3307Snp146283 {
1074a9da3307Snp146283 
1075a9da3307Snp146283 	DBusMessageIter rep_iter;
1076a9da3307Snp146283 	DBusMessage	*msg_reply;
1077a9da3307Snp146283 	int 		res;
1078a9da3307Snp146283 	pconf_edit_type pc_type;
1079a9da3307Snp146283 	char		*param;
1080a9da3307Snp146283 
1081a9da3307Snp146283 	/*
1082a9da3307Snp146283 	 * Get the governor type from /etc/power.conf if it is present.
1083a9da3307Snp146283 	 */
1084a9da3307Snp146283 	res = get_cur_val (&pc_type, CPU_GOV);
1085a9da3307Snp146283 	if (res != 1) {
1086a9da3307Snp146283 		HAL_INFO ((" Error in getting the current governor"));
1087a9da3307Snp146283 		gen_cpufreq_err (con, msg, "Internal error while getting"
1088a9da3307Snp146283 		    " the governor");
1089a9da3307Snp146283 		return;
1090a9da3307Snp146283 	}
1091a9da3307Snp146283 
1092a9da3307Snp146283 	HAL_DEBUG ((" Current governor is: %s", pc_type.cpu_gov));
1093a9da3307Snp146283 
1094a9da3307Snp146283 	msg_reply = dbus_message_new_method_return (msg);
1095a9da3307Snp146283 	if (msg_reply == NULL) {
1096a9da3307Snp146283 		HAL_ERROR (("Out of memory to msg reply"));
1097a9da3307Snp146283 		gen_cpufreq_err (con, msg,
1098a9da3307Snp146283 		    "Internal error while getting the governor");
1099a9da3307Snp146283 		return;
1100a9da3307Snp146283 	}
1101a9da3307Snp146283 
1102a9da3307Snp146283 	/*
1103a9da3307Snp146283 	 * Append reply arguments
1104a9da3307Snp146283 	 */
1105a9da3307Snp146283 	param = (char *) malloc (sizeof (char) * 250);
1106a9da3307Snp146283 	if (param == NULL) {
1107a9da3307Snp146283 		HAL_ERROR (("\n Could not allocate mem to param"));
1108a9da3307Snp146283 		gen_cpufreq_err (con, msg, "Internal error while getting"
1109a9da3307Snp146283 		    " the governor");
1110a9da3307Snp146283 		return;
1111a9da3307Snp146283 	}
1112a9da3307Snp146283 	sprintf (param, "%s",  pc_type.cpu_gov);
1113a9da3307Snp146283 
1114a9da3307Snp146283 	dbus_message_iter_init_append (msg_reply, &rep_iter);
1115a9da3307Snp146283 	if (!dbus_message_iter_append_basic (&rep_iter, DBUS_TYPE_STRING,
1116a9da3307Snp146283 	    &param)) {
1117a9da3307Snp146283 		HAL_ERROR (("\n Out Of Memory!\n"));
1118a9da3307Snp146283 		gen_cpufreq_err (con, msg, "Internal error while getting"
1119a9da3307Snp146283 		    " the governor");
1120a9da3307Snp146283 		free (param);
1121a9da3307Snp146283 		return;
1122a9da3307Snp146283 	}
1123a9da3307Snp146283 
1124a9da3307Snp146283 	if (!dbus_connection_send (con, msg_reply, NULL)) {
1125a9da3307Snp146283 		HAL_ERROR (("\n Out Of Memory!\n"));
1126a9da3307Snp146283 		gen_cpufreq_err (con, msg, "Internal error while getting"
1127a9da3307Snp146283 		    " the governor");
1128a9da3307Snp146283 		free (param);
1129a9da3307Snp146283 		return;
1130a9da3307Snp146283 	}
1131a9da3307Snp146283 	dbus_connection_flush (con);
1132a9da3307Snp146283 	free (param);
1133a9da3307Snp146283 }
1134a9da3307Snp146283 
1135a9da3307Snp146283 /*
1136a9da3307Snp146283  * Returns in the dbus message the current performance value
1137a9da3307Snp146283  */
1138a9da3307Snp146283 static void
get_cpufreq_performance(DBusConnection * con,DBusMessage * msg,void * udata)1139a9da3307Snp146283 get_cpufreq_performance(DBusConnection *con, DBusMessage *msg, void *udata)
1140a9da3307Snp146283 {
1141a9da3307Snp146283 
1142a9da3307Snp146283 	DBusMessageIter rep_iter;
1143a9da3307Snp146283 	DBusMessage	*msg_reply;
1144a9da3307Snp146283 	int 		res;
1145a9da3307Snp146283 	pconf_edit_type pc_type;
1146a9da3307Snp146283 	int		param_int;
1147a9da3307Snp146283 
1148a9da3307Snp146283 	/*
1149a9da3307Snp146283 	 * Get the performance value
1150a9da3307Snp146283 	 */
1151a9da3307Snp146283 	res = get_cur_val (&pc_type, CPU_PERFORMANCE);
1152a9da3307Snp146283 	if (res != 1) {
1153a9da3307Snp146283 		HAL_INFO ((" Error in getting current performance"));
1154a9da3307Snp146283 		gen_cpufreq_err (con, msg, "Internal error while getting"
1155a9da3307Snp146283 		    " the performance value");
1156a9da3307Snp146283 		return;
1157a9da3307Snp146283 	}
1158a9da3307Snp146283 
1159a9da3307Snp146283 	HAL_DEBUG ((" The current performance: %d", pc_type.cpu_th));
1160a9da3307Snp146283 
1161a9da3307Snp146283 	msg_reply = dbus_message_new_method_return (msg);
1162a9da3307Snp146283 	if (msg_reply == NULL) {
1163a9da3307Snp146283 		HAL_ERROR (("Out of memory to msg reply"));
1164a9da3307Snp146283 		gen_cpufreq_err (con, msg, "Internal error while getting"
1165a9da3307Snp146283 		    " the performance value");
1166a9da3307Snp146283 		return;
1167a9da3307Snp146283 	}
1168a9da3307Snp146283 
1169a9da3307Snp146283 	/*
1170a9da3307Snp146283 	 * Append reply arguments.pc_type.cpu_th gives the current cputhreshold
1171a9da3307Snp146283 	 * vlaue in seconds. Have to convert it into CPU HAL interface
1172a9da3307Snp146283 	 * performance value
1173a9da3307Snp146283 	 */
1174a9da3307Snp146283 	if (pc_type.cpu_th < 15)
1175a9da3307Snp146283 		param_int = 1;
1176a9da3307Snp146283 	else
1177a9da3307Snp146283 		param_int = (pc_type.cpu_th / 15);
1178a9da3307Snp146283 
1179a9da3307Snp146283 	HAL_DEBUG (("Performance: %d \n", param_int));
1180a9da3307Snp146283 
1181a9da3307Snp146283 	dbus_message_iter_init_append (msg_reply, &rep_iter);
1182a9da3307Snp146283 	if (!dbus_message_iter_append_basic (&rep_iter, DBUS_TYPE_INT32,
1183a9da3307Snp146283 	    &param_int)) {
1184a9da3307Snp146283 		HAL_ERROR (("\n Out Of Memory!\n"));
1185a9da3307Snp146283 		gen_cpufreq_err (con, msg, "Internal error while getting"
1186a9da3307Snp146283 		    " the performance value");
1187a9da3307Snp146283 		return;
1188a9da3307Snp146283 	}
1189a9da3307Snp146283 
1190a9da3307Snp146283 	if (!dbus_connection_send (con, msg_reply, NULL)) {
1191a9da3307Snp146283 		HAL_ERROR (("\n Out Of Memory!\n"));
1192a9da3307Snp146283 		gen_cpufreq_err (con, msg, "Internal error while getting"
1193a9da3307Snp146283 		    " the performance value");
1194a9da3307Snp146283 		return;
1195a9da3307Snp146283 	}
1196a9da3307Snp146283 	dbus_connection_flush (con);
1197a9da3307Snp146283 }
1198a9da3307Snp146283 
1199a9da3307Snp146283 /*
1200a9da3307Snp146283  * Returns list of available governors. Currently just two governors are
1201a9da3307Snp146283  * supported. They are "ondemand" and "performance"
1202a9da3307Snp146283  */
1203a9da3307Snp146283 
1204a9da3307Snp146283 static void
get_cpufreq_avail_gov(DBusConnection * con,DBusMessage * msg,void * udata)1205a9da3307Snp146283 get_cpufreq_avail_gov(DBusConnection *con, DBusMessage *msg, void *udata)
1206a9da3307Snp146283 {
1207a9da3307Snp146283 
1208a9da3307Snp146283 	DBusMessageIter rep_iter;
1209a9da3307Snp146283 	DBusMessageIter array_iter;
1210a9da3307Snp146283 	DBusMessage	*msg_reply;
1211a9da3307Snp146283 	int		ngov;
1212a9da3307Snp146283 
1213a9da3307Snp146283 	msg_reply = dbus_message_new_method_return (msg);
1214a9da3307Snp146283 	if (msg_reply == NULL) {
1215a9da3307Snp146283 		HAL_ERROR (("Out of memory to msg reply"));
1216a9da3307Snp146283 		gen_cpufreq_err (con, msg, "Internal error while getting"
1217a9da3307Snp146283 		    " the list of governors");
1218a9da3307Snp146283 		return;
1219a9da3307Snp146283 	}
1220a9da3307Snp146283 
1221a9da3307Snp146283 	/*
1222a9da3307Snp146283 	 * Append reply arguments
1223a9da3307Snp146283 	 */
1224a9da3307Snp146283 	dbus_message_iter_init_append (msg_reply, &rep_iter);
1225a9da3307Snp146283 
1226a9da3307Snp146283 	if (!dbus_message_iter_open_container (&rep_iter,
1227a9da3307Snp146283 	    DBUS_TYPE_ARRAY,
1228a9da3307Snp146283 	    DBUS_TYPE_STRING_AS_STRING,
1229a9da3307Snp146283 	    &array_iter)) {
1230a9da3307Snp146283 		HAL_ERROR (("\n Out of memory to msg reply array"));
1231a9da3307Snp146283 		gen_cpufreq_err (con, msg, "Internal error while getting"
1232a9da3307Snp146283 		    " the list of governors");
1233a9da3307Snp146283 		return;
1234a9da3307Snp146283 	}
1235a9da3307Snp146283 
1236a9da3307Snp146283 	for (ngov = 0; gov_list[ngov] != NULL; ngov++) {
1237a9da3307Snp146283 		if (gov_list[ngov])
1238a9da3307Snp146283 			HAL_DEBUG (("\n%d Gov Name: %s", ngov, gov_list[ngov]));
1239a9da3307Snp146283 			dbus_message_iter_append_basic (&array_iter,
1240a9da3307Snp146283 			    DBUS_TYPE_STRING,
1241a9da3307Snp146283 			    &gov_list[ngov]);
1242a9da3307Snp146283 	}
1243a9da3307Snp146283 	dbus_message_iter_close_container (&rep_iter, &array_iter);
1244a9da3307Snp146283 
1245a9da3307Snp146283 	if (!dbus_connection_send (con, msg_reply, NULL)) {
1246a9da3307Snp146283 		HAL_ERROR (("\n Out Of Memory!\n"));
1247a9da3307Snp146283 		gen_cpufreq_err (con, msg, "Internal error while getting"
1248a9da3307Snp146283 		    " the list of governors");
1249a9da3307Snp146283 		return;
1250a9da3307Snp146283 	}
1251a9da3307Snp146283 	dbus_connection_flush (con);
1252a9da3307Snp146283 }
1253a9da3307Snp146283 
1254a9da3307Snp146283 static DBusHandlerResult
hald_dbus_cpufreq_filter(DBusConnection * con,DBusMessage * msg,void * udata)1255a9da3307Snp146283 hald_dbus_cpufreq_filter(DBusConnection *con, DBusMessage *msg, void *udata)
1256a9da3307Snp146283 {
1257a9da3307Snp146283 	HAL_DEBUG ((" Inside CPUFreq filter:%s", dbus_message_get_path(msg)));
1258a9da3307Snp146283 	/*
1259a9da3307Snp146283 	 * Check for method types
1260a9da3307Snp146283 	 */
1261a9da3307Snp146283 	if (!dbus_connection_get_is_connected (con))
1262a9da3307Snp146283 		HAL_DEBUG (("Connection disconnected in cpufreq addon"));
1263a9da3307Snp146283 
1264a9da3307Snp146283 	if (dbus_message_is_method_call (msg,
1265a9da3307Snp146283 	    "org.freedesktop.Hal.Device.CPUFreq",
1266a9da3307Snp146283 	    "SetCPUFreqGovernor")) {
1267a9da3307Snp146283 		HAL_DEBUG (("---- SetCPUFreqGovernor is called "));
1268a9da3307Snp146283 
1269a9da3307Snp146283 		set_cpufreq_gov (con, msg, udata);
1270a9da3307Snp146283 
1271a9da3307Snp146283 	} else if (dbus_message_is_method_call (msg,
1272a9da3307Snp146283 	    "org.freedesktop.Hal.Device.CPUFreq",
1273a9da3307Snp146283 	    "GetCPUFreqGovernor")) {
1274a9da3307Snp146283 		HAL_DEBUG (("---- GetCPUFreqGovernor is called "));
1275a9da3307Snp146283 
1276a9da3307Snp146283 		get_cpufreq_gov (con, msg, udata);
1277a9da3307Snp146283 	} else if (dbus_message_is_method_call (msg,
1278a9da3307Snp146283 	    "org.freedesktop.Hal.Device.CPUFreq",
1279a9da3307Snp146283 	    "GetCPUFreqAvailableGovernors")) {
1280a9da3307Snp146283 		HAL_DEBUG (("---- GetCPUFreqAvailableGovernors is called "));
1281a9da3307Snp146283 
1282a9da3307Snp146283 		get_cpufreq_avail_gov (con, msg, udata);
1283a9da3307Snp146283 	} else if (dbus_message_is_method_call (msg,
1284a9da3307Snp146283 	    "org.freedesktop.Hal.Device.CPUFreq",
1285a9da3307Snp146283 	    "SetCPUFreqPerformance")) {
1286a9da3307Snp146283 		HAL_DEBUG (("---- SetCPUFreqPerformance is called "));
1287a9da3307Snp146283 
1288a9da3307Snp146283 		set_cpufreq_performance (con, msg, udata);
1289a9da3307Snp146283 	} else if (dbus_message_is_method_call (msg,
1290a9da3307Snp146283 	    "org.freedesktop.Hal.Device.CPUFreq",
1291a9da3307Snp146283 	    "GetCPUFreqPerformance")) {
1292a9da3307Snp146283 		HAL_DEBUG (("---- GetCPUFreqPerformance is called "));
1293a9da3307Snp146283 
1294a9da3307Snp146283 		get_cpufreq_performance (con, msg, udata);
1295a9da3307Snp146283 	} else {
1296a9da3307Snp146283 		HAL_DEBUG (("---Not Set/Get cpufreq gov---"));
1297a9da3307Snp146283 	}
1298a9da3307Snp146283 
1299a9da3307Snp146283 	return (DBUS_HANDLER_RESULT_HANDLED);
1300a9da3307Snp146283 
1301a9da3307Snp146283 }
1302a9da3307Snp146283 
1303a9da3307Snp146283 static void
drop_privileges()1304a9da3307Snp146283 drop_privileges()
1305a9da3307Snp146283 {
1306a9da3307Snp146283 	priv_set_t *pPrivSet = NULL;
1307a9da3307Snp146283 	priv_set_t *lPrivSet = NULL;
1308a9da3307Snp146283 
1309a9da3307Snp146283 	/*
1310a9da3307Snp146283 	 * Start with the 'basic' privilege set and then add any
1311a9da3307Snp146283 	 * of the privileges that will be required.
1312a9da3307Snp146283 	 */
1313a9da3307Snp146283 	if ((pPrivSet = priv_str_to_set ("basic", ",", NULL)) == NULL) {
1314a9da3307Snp146283 		HAL_INFO (("Error in setting the priv"));
1315a9da3307Snp146283 		return;
1316a9da3307Snp146283 	}
1317a9da3307Snp146283 
1318a9da3307Snp146283 	(void) priv_addset (pPrivSet, PRIV_SYS_DEVICES);
1319a9da3307Snp146283 
1320a9da3307Snp146283 	if (setppriv (PRIV_SET, PRIV_INHERITABLE, pPrivSet) != 0) {
1321a9da3307Snp146283 		HAL_INFO (("Could not set the privileges"));
1322a9da3307Snp146283 		priv_freeset (pPrivSet);
1323a9da3307Snp146283 		return;
1324a9da3307Snp146283 	}
1325a9da3307Snp146283 
1326a9da3307Snp146283 	(void) priv_addset (pPrivSet, PRIV_PROC_AUDIT);
1327a9da3307Snp146283 	(void) priv_addset (pPrivSet, PRIV_SYS_CONFIG);
1328a9da3307Snp146283 
1329a9da3307Snp146283 	if (setppriv (PRIV_SET, PRIV_PERMITTED, pPrivSet) != 0) {
1330a9da3307Snp146283 		HAL_INFO (("Could not set the privileges"));
1331a9da3307Snp146283 		priv_freeset (pPrivSet);
1332a9da3307Snp146283 		return;
1333a9da3307Snp146283 	}
1334a9da3307Snp146283 
1335a9da3307Snp146283 	priv_freeset (pPrivSet);
1336a9da3307Snp146283 
1337a9da3307Snp146283 }
1338a9da3307Snp146283 
1339a9da3307Snp146283 int
main(int argc,char ** argv)1340a9da3307Snp146283 main(int argc, char **argv)
1341a9da3307Snp146283 {
1342a9da3307Snp146283 
1343a9da3307Snp146283 	LibHalContext *ctx = NULL;
1344a9da3307Snp146283 	char *udi;
1345a9da3307Snp146283 	DBusError error;
1346a9da3307Snp146283 	DBusConnection *conn;
1347a9da3307Snp146283 
1348a9da3307Snp146283 	GMainLoop *loop = g_main_loop_new (NULL, FALSE);
1349a9da3307Snp146283 
1350a9da3307Snp146283 	drop_privileges ();
1351a9da3307Snp146283 	openlog ("hald-addon-cpufreq", LOG_PID, LOG_DAEMON);
1352a9da3307Snp146283 	setup_logger ();
1353a9da3307Snp146283 
1354a9da3307Snp146283 	bzero (current_gov, EDIT_TYPE_SIZE-1);
1355a9da3307Snp146283 
1356a9da3307Snp146283 	if ((udi = getenv ("UDI")) == NULL) {
1357a9da3307Snp146283 		HAL_INFO (("\n Could not get the UDI in addon-cpufreq"));
1358a9da3307Snp146283 		return (0);
1359a9da3307Snp146283 	}
1360a9da3307Snp146283 
1361a9da3307Snp146283 	dbus_error_init (&error);
1362a9da3307Snp146283 	if ((ctx = libhal_ctx_init_direct (&error)) == NULL) {
1363a9da3307Snp146283 		HAL_ERROR (("main(): init_direct failed\n"));
1364a9da3307Snp146283 		return (0);
1365a9da3307Snp146283 	}
1366a9da3307Snp146283 	dbus_error_init (&error);
1367a9da3307Snp146283 	if (!libhal_device_addon_is_ready (ctx, getenv ("UDI"), &error)) {
1368a9da3307Snp146283 		check_and_free_error (&error);
1369a9da3307Snp146283 		return (0);
1370a9da3307Snp146283 	}
1371a9da3307Snp146283 
1372a9da3307Snp146283 	/*
1373a9da3307Snp146283 	 * Claim the cpufreq interface
1374a9da3307Snp146283 	 */
1375a9da3307Snp146283 
1376a9da3307Snp146283 	HAL_DEBUG (("cpufreq Introspect XML: %s", cpufreq_introspect_xml));
1377a9da3307Snp146283 
1378a9da3307Snp146283 	if (!libhal_device_claim_interface (ctx,
1379a9da3307Snp146283 	    udi,
1380a9da3307Snp146283 	    "org.freedesktop.Hal.Device.CPUFreq",
1381a9da3307Snp146283 	    cpufreq_introspect_xml,
1382a9da3307Snp146283 	    &error)) {
1383a9da3307Snp146283 		HAL_DEBUG ((" Cannot claim the CPUFreq interface"));
1384a9da3307Snp146283 		check_and_free_error (&error);
1385a9da3307Snp146283 		return (0);
1386a9da3307Snp146283 	}
1387a9da3307Snp146283 
1388a9da3307Snp146283 	conn = libhal_ctx_get_dbus_connection (ctx);
1389a9da3307Snp146283 
1390a9da3307Snp146283 	/*
1391a9da3307Snp146283 	 * Add the cpufreq capability
1392a9da3307Snp146283 	 */
1393a9da3307Snp146283 	if (!libhal_device_add_capability (ctx,
1394a9da3307Snp146283 	    udi,
1395a9da3307Snp146283 	    "cpufreq_control",
1396a9da3307Snp146283 	    &error)) {
1397a9da3307Snp146283 		HAL_DEBUG ((" Could not add cpufreq_control capability"));
1398a9da3307Snp146283 		check_and_free_error (&error);
1399a9da3307Snp146283 		return (0);
1400a9da3307Snp146283 	}
1401a9da3307Snp146283 	/*
1402a9da3307Snp146283 	 * Watches and times incoming messages
1403a9da3307Snp146283 	 */
1404a9da3307Snp146283 
1405a9da3307Snp146283 	dbus_connection_setup_with_g_main (conn, NULL);
1406a9da3307Snp146283 
1407a9da3307Snp146283 	/*
1408a9da3307Snp146283 	 * Add a filter function which gets called when a message comes in
1409a9da3307Snp146283 	 * and processes the message
1410a9da3307Snp146283 	 */
1411a9da3307Snp146283 
1412a9da3307Snp146283 	if (!dbus_connection_add_filter (conn,
1413a9da3307Snp146283 	    hald_dbus_cpufreq_filter,
1414a9da3307Snp146283 	    NULL,
1415a9da3307Snp146283 	    NULL)) {
1416a9da3307Snp146283 		HAL_INFO ((" Cannot add the CPUFreq filter function"));
1417a9da3307Snp146283 		return (0);
1418a9da3307Snp146283 	}
1419a9da3307Snp146283 
1420a9da3307Snp146283 	dbus_connection_set_exit_on_disconnect (conn, 0);
1421a9da3307Snp146283 
1422a9da3307Snp146283 	g_main_loop_run (loop);
1423a9da3307Snp146283 }
1424