xref: /dflybsd-src/usr.sbin/acpi/acpicall/acpicall.c (revision 9317c2d05f3e3069ce1ef6eca78f8dbc1b92dee2)
1279dd846SSascha Wildner /*-
2279dd846SSascha Wildner  *   Copyright (C) 2011 by Maxim Ignatenko
3279dd846SSascha Wildner  *   gelraen.ua@gmail.com
4279dd846SSascha Wildner  *   Copyright (C) 2015  Sascha Wildner
5279dd846SSascha Wildner  *   swildner@dragonflybsd.org
6279dd846SSascha Wildner  *
7279dd846SSascha Wildner  *   All rights reserved.                                                  *
8279dd846SSascha Wildner  *                                                                         *
9279dd846SSascha Wildner  *   Redistribution and use in source and binary forms, with or without    *
10279dd846SSascha Wildner  *    modification, are permitted provided that the following conditions   *
11279dd846SSascha Wildner  *    are met:                                                             *
12279dd846SSascha Wildner  *     * Redistributions of source code must retain the above copyright    *
13279dd846SSascha Wildner  *       notice, this list of conditions and the following disclaimer.     *
14279dd846SSascha Wildner  *     * Redistributions in binary form must reproduce the above copyright *
15279dd846SSascha Wildner  *       notice, this list of conditions and the following disclaimer in   *
16279dd846SSascha Wildner  *       the documentation and/or other materials provided with the        *
17279dd846SSascha Wildner  *       distribution.                                                     *
18279dd846SSascha Wildner  *                                                                         *
19279dd846SSascha Wildner  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   *
20279dd846SSascha Wildner  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     *
21279dd846SSascha Wildner  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR *
22279dd846SSascha Wildner  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  *
23279dd846SSascha Wildner  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *
24279dd846SSascha Wildner  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT      *
25279dd846SSascha Wildner  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
26279dd846SSascha Wildner  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
27279dd846SSascha Wildner  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT   *
28279dd846SSascha Wildner  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE *
29279dd846SSascha Wildner  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  *
30279dd846SSascha Wildner  *
31279dd846SSascha Wildner  */
32279dd846SSascha Wildner 
33279dd846SSascha Wildner #include <sys/param.h>
34279dd846SSascha Wildner #include <sys/ioctl.h>
35279dd846SSascha Wildner #include <fcntl.h>
36279dd846SSascha Wildner #include <unistd.h>
37279dd846SSascha Wildner #include <stdlib.h>
38279dd846SSascha Wildner #include <stdio.h>
39279dd846SSascha Wildner #include <string.h>
405a08817bSSascha Wildner #include <uuid.h>
41279dd846SSascha Wildner 
42279dd846SSascha Wildner #include <contrib/dev/acpica/source/include/acpi.h>
43279dd846SSascha Wildner #include <dev/acpica/acpiio_mcall.h>
44279dd846SSascha Wildner 
45279dd846SSascha Wildner #define	MAX_ACPI_PATH	4096
46279dd846SSascha Wildner 
47279dd846SSascha Wildner static char	dev_path[MAXPATHLEN] = "/dev/acpi";
48279dd846SSascha Wildner static char	method_path[MAX_ACPI_PATH] = "";
49279dd846SSascha Wildner static size_t	result_buf_size = 1024;
50279dd846SSascha Wildner static char	output_format = 'o';
51279dd846SSascha Wildner static int	verbose;
52279dd846SSascha Wildner static ACPI_OBJECT args[ACPI_METHOD_NUM_ARGS];
53279dd846SSascha Wildner static struct acpi_mcall_ioctl_arg params;
54279dd846SSascha Wildner 
55279dd846SSascha Wildner static void	usage(void);
56279dd846SSascha Wildner static int	parse_buffer(ACPI_OBJECT *, char *);
57279dd846SSascha Wildner static void	print_params(struct acpi_mcall_ioctl_arg *);
58279dd846SSascha Wildner static void	print_acpi_object(ACPI_OBJECT *);
59279dd846SSascha Wildner static void	print_acpi_buffer(ACPI_BUFFER *, char);
60279dd846SSascha Wildner 
61279dd846SSascha Wildner int
main(int argc,char * argv[])62279dd846SSascha Wildner main(int argc, char *argv[])
63279dd846SSascha Wildner {
64279dd846SSascha Wildner 	char c;
655a08817bSSascha Wildner 	int i, fd, status;
665a08817bSSascha Wildner 	uuid_t uuid;
67279dd846SSascha Wildner 
68279dd846SSascha Wildner 	bzero(&params, sizeof(params));
69279dd846SSascha Wildner 	params.path = method_path;
70279dd846SSascha Wildner 	params.args.Count = 0;
71279dd846SSascha Wildner 	params.args.Pointer = args;
72279dd846SSascha Wildner 
735a08817bSSascha Wildner 	while ((c = getopt(argc, argv, "b:d:i:o:s:U:v")) != -1) {
74279dd846SSascha Wildner 		switch (c) {
75279dd846SSascha Wildner 		case 'b':
76279dd846SSascha Wildner 		case 'i':
77279dd846SSascha Wildner 		case 's':
785a08817bSSascha Wildner 		case 'U':
79279dd846SSascha Wildner 			i = params.args.Count;
80279dd846SSascha Wildner 			if (i >= ACPI_METHOD_NUM_ARGS) {
81279dd846SSascha Wildner 				fprintf(stderr,
82279dd846SSascha Wildner 				    "maximum number of %d args exceeded\n",
83279dd846SSascha Wildner 				    ACPI_METHOD_NUM_ARGS);
84279dd846SSascha Wildner 				exit(1);
85279dd846SSascha Wildner 			}
86279dd846SSascha Wildner 			switch (optopt) {
87279dd846SSascha Wildner 			case 'b':
88279dd846SSascha Wildner 				if (parse_buffer(&args[i], optarg) != 0) {
89279dd846SSascha Wildner 					fprintf(stderr,
90279dd846SSascha Wildner 					    "unable to parse hexstring: %s\n",
91279dd846SSascha Wildner 					    optarg);
92279dd846SSascha Wildner 					exit(1);
93279dd846SSascha Wildner 				}
94279dd846SSascha Wildner 				break;
95279dd846SSascha Wildner 			case 'i':
96279dd846SSascha Wildner 				args[i].Type = ACPI_TYPE_INTEGER;
97279dd846SSascha Wildner 				args[i].Integer.Value =
98279dd846SSascha Wildner 				    strtol(optarg, NULL, 10);
99279dd846SSascha Wildner 				break;
100279dd846SSascha Wildner 			case 's':
101279dd846SSascha Wildner 				args[i].Type = ACPI_TYPE_STRING;
102279dd846SSascha Wildner 				args[i].String.Length = strlen(optarg);
103279dd846SSascha Wildner 				args[i].String.Pointer = optarg;
104279dd846SSascha Wildner 				break;
1055a08817bSSascha Wildner 			case 'U':
1065a08817bSSascha Wildner 				uuid_from_string(optarg, &uuid, &status);
1075a08817bSSascha Wildner 				if (status != uuid_s_ok) {
1085a08817bSSascha Wildner 					fprintf(stderr, "invalid uuid %s\n",
1095a08817bSSascha Wildner 					    optarg);
1105a08817bSSascha Wildner 					exit(1);
1115a08817bSSascha Wildner 				}
1125a08817bSSascha Wildner 				args[i].Type = ACPI_TYPE_BUFFER;
1135a08817bSSascha Wildner 				args[i].Buffer.Length = 16;
1145a08817bSSascha Wildner 				if ((args[i].Buffer.Pointer = malloc(16)) == NULL) {
1155a08817bSSascha Wildner 					fprintf(stderr, "malloc failure\n");
1165a08817bSSascha Wildner 					exit(1);
1175a08817bSSascha Wildner 				}
1185a08817bSSascha Wildner 				uuid_enc_le(args[i].Buffer.Pointer, &uuid);
1195a08817bSSascha Wildner 				break;
120279dd846SSascha Wildner 			}
121279dd846SSascha Wildner 			params.args.Count++;
122279dd846SSascha Wildner 			break;
123279dd846SSascha Wildner 		case 'd':
124279dd846SSascha Wildner 			strlcpy(dev_path, optarg, MAXPATHLEN);
125279dd846SSascha Wildner 			break;
126279dd846SSascha Wildner 		case 'o':
127279dd846SSascha Wildner 			switch (optarg[0]) {
128279dd846SSascha Wildner 			case 'b':
129279dd846SSascha Wildner 			case 'i':
130279dd846SSascha Wildner 			case 'o':
131279dd846SSascha Wildner 			case 's':
132279dd846SSascha Wildner 				output_format = optarg[0];
133279dd846SSascha Wildner 				break;
134279dd846SSascha Wildner 			default:
135279dd846SSascha Wildner 				fprintf(stderr,
136279dd846SSascha Wildner 				    "incorrect output format: %c\n",
137279dd846SSascha Wildner 				    optarg[0]);
138279dd846SSascha Wildner 				usage();
139279dd846SSascha Wildner 				break;
140279dd846SSascha Wildner 			}
141279dd846SSascha Wildner 			break;
142279dd846SSascha Wildner 		case 'v':
143279dd846SSascha Wildner 			verbose = 1;
144279dd846SSascha Wildner 			break;
145279dd846SSascha Wildner 		default:
146279dd846SSascha Wildner 			usage();
147279dd846SSascha Wildner 			break;
148279dd846SSascha Wildner 		}
149279dd846SSascha Wildner 	}
150279dd846SSascha Wildner 	argc -= optind;
151279dd846SSascha Wildner 	argv += optind;
152279dd846SSascha Wildner 
153279dd846SSascha Wildner 	if (argc != 1)
154279dd846SSascha Wildner 		usage();
155279dd846SSascha Wildner 	strlcpy(method_path, argv[0], MAX_ACPI_PATH);
156279dd846SSascha Wildner 
157279dd846SSascha Wildner 	params.result.Length = result_buf_size;
158279dd846SSascha Wildner 	params.result.Pointer = malloc(result_buf_size);
159279dd846SSascha Wildner 
160279dd846SSascha Wildner 	if (params.result.Pointer == NULL) {
161279dd846SSascha Wildner 		perror("malloc");
162279dd846SSascha Wildner 		return 1;
163279dd846SSascha Wildner 	}
164279dd846SSascha Wildner 
165279dd846SSascha Wildner 	if (method_path[0] == 0) {
166279dd846SSascha Wildner 		fprintf(stderr,
167279dd846SSascha Wildner 		    "please specify path to method with -p flag\n");
168279dd846SSascha Wildner 		return 1;
169279dd846SSascha Wildner 	}
170279dd846SSascha Wildner 
171279dd846SSascha Wildner 	if (verbose)
172279dd846SSascha Wildner 		print_params(&params);
173279dd846SSascha Wildner 
174279dd846SSascha Wildner 	fd = open(dev_path, O_RDWR);
175279dd846SSascha Wildner 	if (fd < 0) {
176279dd846SSascha Wildner 		perror("open");
177279dd846SSascha Wildner 		return 1;
178279dd846SSascha Wildner 	}
179279dd846SSascha Wildner 	if (ioctl(fd, ACPIIO_DO_MCALL, &params) == -1) {
180279dd846SSascha Wildner 		perror("ioctl");
181279dd846SSascha Wildner 		return 1;
182279dd846SSascha Wildner 	}
183279dd846SSascha Wildner 
184279dd846SSascha Wildner 	if (verbose)
185279dd846SSascha Wildner 		printf("status: %d\nresult: ", params.retval);
186279dd846SSascha Wildner 	print_acpi_buffer(&params.result, output_format);
187279dd846SSascha Wildner 	printf("\n");
188279dd846SSascha Wildner 
189279dd846SSascha Wildner 	return params.retval;
190279dd846SSascha Wildner }
191279dd846SSascha Wildner 
192279dd846SSascha Wildner static void
usage(void)193279dd846SSascha Wildner usage(void)
194279dd846SSascha Wildner {
195279dd846SSascha Wildner 	fprintf(stderr,
196279dd846SSascha Wildner 	    "usage: acpicall [-v] [-b hexstring] [-d file] [-i number] "
197279dd846SSascha Wildner 	    "[-o i | s | b | o]\n");
1985a08817bSSascha Wildner 	fprintf(stderr, "                [-s string] [-U uuid] path\n");
199279dd846SSascha Wildner 	exit(1);
200279dd846SSascha Wildner }
201279dd846SSascha Wildner 
202279dd846SSascha Wildner static int
parse_buffer(ACPI_OBJECT * dst,char * src)203279dd846SSascha Wildner parse_buffer(ACPI_OBJECT *dst, char *src)
204279dd846SSascha Wildner {
205279dd846SSascha Wildner 	char tmp[3] = { 0 };
206279dd846SSascha Wildner 	size_t len = strlen(src) / 2, i;
207279dd846SSascha Wildner 
208279dd846SSascha Wildner 	dst->Type = ACPI_TYPE_BUFFER;
209279dd846SSascha Wildner 	dst->Buffer.Length = len;
210279dd846SSascha Wildner 	if ((dst->Buffer.Pointer = malloc(len)) == NULL) {
211279dd846SSascha Wildner 		fprintf(stderr,
212*9317c2d0SSascha Wildner 		    "%s: failed to allocate %zu bytes\n", __func__, len);
213279dd846SSascha Wildner 		exit(1);
214279dd846SSascha Wildner 	}
215279dd846SSascha Wildner 
216279dd846SSascha Wildner 	for (i = 0; i < len; i++) {
217279dd846SSascha Wildner 		tmp[0] = src[i * 2];
218279dd846SSascha Wildner 		tmp[1] = src[i * 2 + 1];
219279dd846SSascha Wildner 		dst->Buffer.Pointer[i] = strtol(tmp, NULL, 16);
220279dd846SSascha Wildner 	}
221279dd846SSascha Wildner 
222279dd846SSascha Wildner 	return 0;
223279dd846SSascha Wildner }
224279dd846SSascha Wildner 
225279dd846SSascha Wildner static void
print_params(struct acpi_mcall_ioctl_arg * p)226279dd846SSascha Wildner print_params(struct acpi_mcall_ioctl_arg *p)
227279dd846SSascha Wildner {
228279dd846SSascha Wildner 	int i;
229279dd846SSascha Wildner 
230279dd846SSascha Wildner 	printf("path: %s\n", p->path);
231279dd846SSascha Wildner 	printf("number of arguments: %d\n", p->args.Count);
232279dd846SSascha Wildner 	for (i = 0; i < (int)p->args.Count; i++) {
233279dd846SSascha Wildner 		printf("argument %d type: ", i + 1);
234279dd846SSascha Wildner 		switch (p->args.Pointer[i].Type) {
235279dd846SSascha Wildner 		case ACPI_TYPE_INTEGER:
236279dd846SSascha Wildner 			printf("integer\n");
237279dd846SSascha Wildner 			break;
238279dd846SSascha Wildner 		case ACPI_TYPE_STRING:
239279dd846SSascha Wildner 			printf("string\n");
240279dd846SSascha Wildner 			break;
241279dd846SSascha Wildner 		case ACPI_TYPE_BUFFER:
242279dd846SSascha Wildner 			printf("buffer\n");
243279dd846SSascha Wildner 			break;
244279dd846SSascha Wildner 		}
245279dd846SSascha Wildner 		printf("argument %d value: ", i + 1);
246279dd846SSascha Wildner 		print_acpi_object(&(p->args.Pointer[i]));
247279dd846SSascha Wildner 		printf("\n");
248279dd846SSascha Wildner 	}
249279dd846SSascha Wildner }
250279dd846SSascha Wildner 
251279dd846SSascha Wildner static void
print_acpi_object(ACPI_OBJECT * obj)252279dd846SSascha Wildner print_acpi_object(ACPI_OBJECT *obj)
253279dd846SSascha Wildner {
254279dd846SSascha Wildner 	int i;
255279dd846SSascha Wildner 
256279dd846SSascha Wildner 	switch (obj->Type) {
257279dd846SSascha Wildner 	case ACPI_TYPE_INTEGER:
258279dd846SSascha Wildner 		printf("%ju", (uintmax_t)obj->Integer.Value);
259279dd846SSascha Wildner 		break;
260279dd846SSascha Wildner 	case ACPI_TYPE_STRING:
261279dd846SSascha Wildner 		printf("%s", obj->String.Pointer);
262279dd846SSascha Wildner 		break;
263279dd846SSascha Wildner 	case ACPI_TYPE_BUFFER:
264279dd846SSascha Wildner 		for (i = 0; i < (int)obj->Buffer.Length; i++)
265279dd846SSascha Wildner 			printf("%02x", obj->Buffer.Pointer[i]);
266279dd846SSascha Wildner 		break;
267279dd846SSascha Wildner 	default:
268279dd846SSascha Wildner 		printf("unknown object type '%d'", obj->Type);
269279dd846SSascha Wildner 		break;
270279dd846SSascha Wildner 	}
271279dd846SSascha Wildner }
272279dd846SSascha Wildner 
273279dd846SSascha Wildner static void
print_acpi_buffer(ACPI_BUFFER * buf,char format)274279dd846SSascha Wildner print_acpi_buffer(ACPI_BUFFER *buf, char format)
275279dd846SSascha Wildner {
276279dd846SSascha Wildner 	int i;
277279dd846SSascha Wildner 
278279dd846SSascha Wildner 	switch (format) {
279279dd846SSascha Wildner 	case 'i':
280279dd846SSascha Wildner 		printf("%ju", (uintmax_t)*((UINT64 *)buf->Pointer));
281279dd846SSascha Wildner 		break;
282279dd846SSascha Wildner 	case 's':
283279dd846SSascha Wildner 		printf("%s", (char *)buf->Pointer);
284279dd846SSascha Wildner 		break;
285279dd846SSascha Wildner 	case 'b':
286279dd846SSascha Wildner 		for (i = 0; i < (int)buf->Length; i++)
287279dd846SSascha Wildner 			printf("%02x", ((UINT8 *)(buf->Pointer))[i]);
288279dd846SSascha Wildner 		break;
289279dd846SSascha Wildner 	case 'o':
290279dd846SSascha Wildner 		print_acpi_object((ACPI_OBJECT *)buf->Pointer);
291279dd846SSascha Wildner 		break;
292279dd846SSascha Wildner 	}
293279dd846SSascha Wildner }
294