1 /*- 2 * Copyright (C) 2011 by Maxim Ignatenko 3 * gelraen.ua@gmail.com 4 * 5 * All rights reserved. * 6 * * 7 * Redistribution and use in source and binary forms, with or without * 8 * modification, are permitted provided that the following conditions * 9 * are met: * 10 * * Redistributions of source code must retain the above copyright * 11 * notice, this list of conditions and the following disclaimer. * 12 * * Redistributions in binary form must reproduce the above copyright * 13 * notice, this list of conditions and the following disclaimer in * 14 * the documentation and/or other materials provided with the * 15 * distribution. * 16 * * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * 18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * 19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * 20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * 21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * 22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * 23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * 27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * 28 * 29 */ 30 31 //#include "acpi_call_io.h" 32 33 #include <fcntl.h> 34 #include <sys/ioctl.h> 35 #include <unistd.h> 36 #include <sys/param.h> 37 #include <stdlib.h> 38 #include <stdio.h> 39 #include <string.h> 40 41 #include "acpi.h" 42 43 44 struct acpi_call_descr 45 { 46 char* path; 47 ACPI_OBJECT_LIST args; 48 ACPI_STATUS retval; 49 ACPI_BUFFER result; 50 ACPI_SIZE reslen; 51 }; 52 53 54 #define MAX_ACPI_PATH 1024 // XXX 55 #define MAX_ACPI_ARGS 7 56 57 char dev_path[MAXPATHLEN] = "/dev/acpi/call"; 58 char method_path[MAX_ACPI_PATH] = ""; 59 size_t result_buf_size = 1024; 60 char output_format = 'o'; 61 62 int verbose; 63 64 ACPI_OBJECT args[MAX_ACPI_ARGS]; 65 struct acpi_call_descr params; 66 67 void parse_opts(int, char *[]); 68 void show_help(FILE*); 69 int parse_buffer(ACPI_OBJECT*, char*); 70 void print_params(struct acpi_call_descr*); 71 void print_acpi_object(ACPI_OBJECT*); 72 void print_acpi_buffer(ACPI_BUFFER*, char); 73 74 int main(int argc, char * argv[]) 75 { 76 int fd; 77 78 bzero(¶ms, sizeof(params)); 79 params.path = method_path; 80 params.args.Count = 0; 81 params.args.Pointer = args; 82 83 verbose = 0; 84 85 parse_opts(argc, argv); 86 87 params.result.Length = result_buf_size; 88 params.result.Pointer = malloc(result_buf_size); 89 90 if (params.result.Pointer == NULL) 91 { 92 perror("malloc"); 93 return 1; 94 } 95 96 if (method_path[0] == 0) 97 { 98 fprintf(stderr, "Please specify path to method with -p flag\n"); 99 return 1; 100 } 101 102 if (verbose) 103 print_params(¶ms); 104 105 fd = open(dev_path, O_RDWR); 106 if (fd < 0) 107 { 108 perror("open"); 109 return 1; 110 } 111 if (ioctl(fd, 'ACCA', ¶ms) == -1) 112 { 113 perror("ioctl"); 114 return 1; 115 } 116 117 if (verbose) 118 printf("Status: %d\nResult: ", params.retval); 119 print_acpi_buffer(¶ms.result, output_format); 120 printf("\n"); 121 122 return params.retval; 123 } 124 125 void parse_opts(int argc, char * argv[]) 126 { 127 char c; 128 int i; 129 130 while ((c = getopt(argc, argv, "hvd:p:i:s:b:o:")) != -1) 131 { 132 switch(c) 133 { 134 case 'h': 135 show_help(stdout); 136 exit(0); 137 break; 138 case 'v': 139 verbose = 1; 140 break; 141 case 'd': 142 strlcpy(dev_path, optarg, MAXPATHLEN); 143 break; 144 case 'p': 145 strlcpy(method_path, optarg, MAX_ACPI_PATH); 146 break; 147 case 'i': 148 case 's': 149 case 'b': 150 i = params.args.Count; 151 if (i >= MAX_ACPI_ARGS) 152 { 153 fprintf(stderr, "Maximum number of arguments exceeded\n"); 154 exit(1); 155 } 156 switch (optopt) 157 { 158 case 'i': 159 args[i].Type = ACPI_TYPE_INTEGER; 160 args[i].Integer.Value = strtol(optarg, NULL, 10); 161 break; 162 case 's': 163 args[i].Type = ACPI_TYPE_STRING; 164 args[i].String.Length = strlen(optarg); 165 args[i].String.Pointer = optarg; 166 break; 167 case 'b': 168 if (parse_buffer(&args[i], optarg)) 169 { 170 fprintf(stderr, "Unable to parse hexstring to buffer: %s\n", optarg); 171 exit(1); 172 } 173 break; 174 } 175 params.args.Count++; 176 break; 177 case 'o': 178 output_format = optarg[0]; 179 switch (optarg[0]) 180 { 181 case 'i': 182 case 's': 183 case 'b': 184 case 'o': 185 break; 186 default: 187 fprintf(stderr, "Incorrect output format: %c\n", optarg[0]); 188 show_help(stderr); 189 exit(1); 190 } 191 break; 192 default: 193 show_help(stderr); 194 exit(1); 195 } 196 } 197 } 198 199 void show_help(FILE* f) 200 { 201 fprintf(f, "Options:\n"); 202 fprintf(f, " -h - print this help\n"); 203 fprintf(f, " -v - be verbose\n"); 204 fprintf(f, " -d filename - specify path to ACPI control pseudo-device. Default: /dev/acpi/call\n"); 205 fprintf(f, " -p path - full path to ACPI method\n"); 206 fprintf(f, " -i number - add integer argument\n"); 207 fprintf(f, " -s string - add string argument\n"); 208 fprintf(f, " -b hexstring - add buffer argument\n"); 209 fprintf(f, " -o i|s|b|o - print result as integer|string|hexstring|object\n"); 210 } 211 212 int parse_buffer(ACPI_OBJECT *dst, char *src) 213 { 214 char tmp[3] = {0}; 215 size_t len = strlen(src)/2, i; 216 217 dst->Type = ACPI_TYPE_BUFFER; 218 dst->Buffer.Length = len; 219 if ((dst->Buffer.Pointer = (UINT8*)malloc(len)) == NULL) 220 { 221 fprintf(stderr, "parse_buffer: Failed to allocate %" B_PRIuSIZE " bytes\n", len); 222 exit(1); 223 } 224 225 for(i = 0; i < len; i++) 226 { 227 tmp[0] = src[i*2]; 228 tmp[1] = src[i*2+1]; 229 dst->Buffer.Pointer[i] = strtol(tmp, NULL, 16); 230 } 231 232 return 0; 233 } 234 235 void print_params(struct acpi_call_descr* p) 236 { 237 printf("Path: %s\n", p->path); 238 printf("Number of arguments: %d\n", p->args.Count); 239 for(uint32 i = 0; i < p->args.Count; i++) 240 { 241 switch (p->args.Pointer[i].Type) 242 { 243 case ACPI_TYPE_INTEGER: 244 printf("Argument %d type: Integer\n", i+1); 245 break; 246 case ACPI_TYPE_STRING: 247 printf("Argument %d type: String\n", i+1); 248 break; 249 case ACPI_TYPE_BUFFER: 250 printf("Argument %d type: Buffer\n", i+1); 251 break; 252 } 253 printf("Argument %d value: ", i+1); 254 print_acpi_object(&(p->args.Pointer[i])); 255 printf("\n"); 256 } 257 } 258 259 void print_acpi_object(ACPI_OBJECT* obj) 260 { 261 switch (obj->Type) 262 { 263 case ACPI_TYPE_INTEGER: 264 printf("%" B_PRIu64, obj->Integer.Value); 265 break; 266 case ACPI_TYPE_STRING: 267 printf("%s", obj->String.Pointer); 268 break; 269 case ACPI_TYPE_BUFFER: 270 for(uint32 i = 0; i < obj->Buffer.Length; i++) 271 { 272 printf("%02X", obj->Buffer.Pointer[i]); 273 } 274 break; 275 default: 276 printf("Unknown object type '%d'", obj->Type); 277 } 278 } 279 280 void print_acpi_buffer(ACPI_BUFFER* buf, char format) 281 { 282 switch (format) 283 { 284 case 'i': 285 printf("%" B_PRIu64, *((ACPI_INTEGER*)(buf->Pointer))); 286 break; 287 case 's': 288 printf("%s", (char*)buf->Pointer); 289 break; 290 case 'b': 291 for(uint32 i = 0; i < buf->Length; i++) 292 { 293 printf("%02X", ((UINT8*)(buf->Pointer))[i]); 294 } 295 break; 296 case 'o': 297 print_acpi_object((ACPI_OBJECT*)(buf->Pointer)); 298 break; 299 } 300 } 301