2 * Copyright (C) 2011 by Maxim Ignatenko
4 * Copyright (C) 2015 Sascha Wildner
5 * swildner@dragonflybsd.org
7 * All rights reserved. *
9 * Redistribution and use in source and binary forms, with or without *
10 * modification, are permitted provided that the following conditions *
12 * * Redistributions of source code must retain the above copyright *
13 * notice, this list of conditions and the following disclaimer. *
14 * * Redistributions in binary form must reproduce the above copyright *
15 * notice, this list of conditions and the following disclaimer in *
16 * the documentation and/or other materials provided with the *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR *
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT *
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE *
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
33 #include <sys/param.h>
34 #include <sys/ioctl.h>
42 #include <contrib/dev/acpica/source/include/acpi.h>
43 #include <dev/acpica/acpiio_mcall.h>
45 #define MAX_ACPI_PATH 4096
47 static char dev_path
[MAXPATHLEN
] = "/dev/acpi";
48 static char method_path
[MAX_ACPI_PATH
] = "";
49 static size_t result_buf_size
= 1024;
50 static char output_format
= 'o';
52 static ACPI_OBJECT args
[ACPI_METHOD_NUM_ARGS
];
53 static struct acpi_mcall_ioctl_arg params
;
55 static void usage(void);
56 static int parse_buffer(ACPI_OBJECT
*, char *);
57 static void print_params(struct acpi_mcall_ioctl_arg
*);
58 static void print_acpi_object(ACPI_OBJECT
*);
59 static void print_acpi_buffer(ACPI_BUFFER
*, char);
62 main(int argc
, char *argv
[])
68 bzero(¶ms
, sizeof(params
));
69 params
.path
= method_path
;
70 params
.args
.Count
= 0;
71 params
.args
.Pointer
= args
;
73 while ((c
= getopt(argc
, argv
, "b:d:i:o:s:U:v")) != -1) {
79 i
= params
.args
.Count
;
80 if (i
>= ACPI_METHOD_NUM_ARGS
) {
82 "maximum number of %d args exceeded\n",
83 ACPI_METHOD_NUM_ARGS
);
88 if (parse_buffer(&args
[i
], optarg
) != 0) {
90 "unable to parse hexstring: %s\n",
96 args
[i
].Type
= ACPI_TYPE_INTEGER
;
97 args
[i
].Integer
.Value
=
98 strtol(optarg
, NULL
, 10);
101 args
[i
].Type
= ACPI_TYPE_STRING
;
102 args
[i
].String
.Length
= strlen(optarg
);
103 args
[i
].String
.Pointer
= optarg
;
106 uuid_from_string(optarg
, &uuid
, &status
);
107 if (status
!= uuid_s_ok
) {
108 fprintf(stderr
, "invalid uuid %s\n",
112 args
[i
].Type
= ACPI_TYPE_BUFFER
;
113 args
[i
].Buffer
.Length
= 16;
114 if ((args
[i
].Buffer
.Pointer
= malloc(16)) == NULL
) {
115 fprintf(stderr
, "malloc failure\n");
118 uuid_enc_le(args
[i
].Buffer
.Pointer
, &uuid
);
124 strlcpy(dev_path
, optarg
, MAXPATHLEN
);
132 output_format
= optarg
[0];
136 "incorrect output format: %c\n",
155 strlcpy(method_path
, argv
[0], MAX_ACPI_PATH
);
157 params
.result
.Length
= result_buf_size
;
158 params
.result
.Pointer
= malloc(result_buf_size
);
160 if (params
.result
.Pointer
== NULL
) {
165 if (method_path
[0] == 0) {
167 "please specify path to method with -p flag\n");
172 print_params(¶ms
);
174 fd
= open(dev_path
, O_RDWR
);
179 if (ioctl(fd
, ACPIIO_DO_MCALL
, ¶ms
) == -1) {
185 printf("status: %d\nresult: ", params
.retval
);
186 print_acpi_buffer(¶ms
.result
, output_format
);
189 return params
.retval
;
196 "usage: acpicall [-v] [-b hexstring] [-d file] [-i number] "
197 "[-o i | s | b | o]\n");
198 fprintf(stderr
, " [-s string] [-U uuid] path\n");
203 parse_buffer(ACPI_OBJECT
*dst
, char *src
)
206 size_t len
= strlen(src
) / 2, i
;
208 dst
->Type
= ACPI_TYPE_BUFFER
;
209 dst
->Buffer
.Length
= len
;
210 if ((dst
->Buffer
.Pointer
= malloc(len
)) == NULL
) {
212 "%s: failed to allocate %zd bytes\n", __func__
, len
);
216 for (i
= 0; i
< len
; i
++) {
218 tmp
[1] = src
[i
* 2 + 1];
219 dst
->Buffer
.Pointer
[i
] = strtol(tmp
, NULL
, 16);
226 print_params(struct acpi_mcall_ioctl_arg
*p
)
230 printf("path: %s\n", p
->path
);
231 printf("number of arguments: %d\n", p
->args
.Count
);
232 for (i
= 0; i
< (int)p
->args
.Count
; i
++) {
233 printf("argument %d type: ", i
+ 1);
234 switch (p
->args
.Pointer
[i
].Type
) {
235 case ACPI_TYPE_INTEGER
:
238 case ACPI_TYPE_STRING
:
241 case ACPI_TYPE_BUFFER
:
245 printf("argument %d value: ", i
+ 1);
246 print_acpi_object(&(p
->args
.Pointer
[i
]));
252 print_acpi_object(ACPI_OBJECT
*obj
)
257 case ACPI_TYPE_INTEGER
:
258 printf("%ju", (uintmax_t)obj
->Integer
.Value
);
260 case ACPI_TYPE_STRING
:
261 printf("%s", obj
->String
.Pointer
);
263 case ACPI_TYPE_BUFFER
:
264 for (i
= 0; i
< (int)obj
->Buffer
.Length
; i
++)
265 printf("%02x", obj
->Buffer
.Pointer
[i
]);
268 printf("unknown object type '%d'", obj
->Type
);
274 print_acpi_buffer(ACPI_BUFFER
*buf
, char format
)
280 printf("%ju", (uintmax_t)*((UINT64
*)buf
->Pointer
));
283 printf("%s", (char *)buf
->Pointer
);
286 for (i
= 0; i
< (int)buf
->Length
; i
++)
287 printf("%02x", ((UINT8
*)(buf
->Pointer
))[i
]);
290 print_acpi_object((ACPI_OBJECT
*)buf
->Pointer
);