/*- * Copyright (C) 2011 by Maxim Ignatenko * gelraen.ua@gmail.com * * All rights reserved. * * * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * * Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in * * the documentation and/or other materials provided with the * * distribution. * * * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * */ //#include "acpi_call_io.h" #include #include #include #include #include #include #include #include "acpi.h" struct acpi_call_descr { char* path; ACPI_OBJECT_LIST args; ACPI_STATUS retval; ACPI_BUFFER result; ACPI_SIZE reslen; }; #define MAX_ACPI_PATH 1024 // XXX #define MAX_ACPI_ARGS 7 char dev_path[MAXPATHLEN] = "/dev/acpi/call"; char method_path[MAX_ACPI_PATH] = ""; size_t result_buf_size = 1024; char output_format = 'o'; int verbose; ACPI_OBJECT args[MAX_ACPI_ARGS]; struct acpi_call_descr params; void parse_opts(int, char *[]); void show_help(FILE*); int parse_buffer(ACPI_OBJECT*, char*); void print_params(struct acpi_call_descr*); void print_acpi_object(ACPI_OBJECT*); void print_acpi_buffer(ACPI_BUFFER*, char); int main(int argc, char * argv[]) { int fd; bzero(¶ms, sizeof(params)); params.path = method_path; params.args.Count = 0; params.args.Pointer = args; verbose = 0; parse_opts(argc, argv); params.result.Length = result_buf_size; params.result.Pointer = malloc(result_buf_size); if (params.result.Pointer == NULL) { perror("malloc"); return 1; } if (method_path[0] == 0) { fprintf(stderr, "Please specify path to method with -p flag\n"); return 1; } if (verbose) print_params(¶ms); fd = open(dev_path, O_RDWR); if (fd < 0) { perror("open"); return 1; } if (ioctl(fd, 'ACCA', ¶ms) == -1) { perror("ioctl"); return 1; } if (verbose) printf("Status: %d\nResult: ", params.retval); print_acpi_buffer(¶ms.result, output_format); printf("\n"); return params.retval; } void parse_opts(int argc, char * argv[]) { char c; int i; while ((c = getopt(argc, argv, "hvd:p:i:s:b:o:")) != -1) { switch(c) { case 'h': show_help(stdout); exit(0); break; case 'v': verbose = 1; break; case 'd': strlcpy(dev_path, optarg, MAXPATHLEN); break; case 'p': strlcpy(method_path, optarg, MAX_ACPI_PATH); break; case 'i': case 's': case 'b': i = params.args.Count; if (i >= MAX_ACPI_ARGS) { fprintf(stderr, "Maximum number of arguments exceeded\n"); exit(1); } switch (optopt) { case 'i': args[i].Type = ACPI_TYPE_INTEGER; args[i].Integer.Value = strtol(optarg, NULL, 10); break; case 's': args[i].Type = ACPI_TYPE_STRING; args[i].String.Length = strlen(optarg); args[i].String.Pointer = optarg; break; case 'b': if (parse_buffer(&args[i], optarg)) { fprintf(stderr, "Unable to parse hexstring to buffer: %s\n", optarg); exit(1); } break; } params.args.Count++; break; case 'o': output_format = optarg[0]; switch (optarg[0]) { case 'i': case 's': case 'b': case 'o': break; default: fprintf(stderr, "Incorrect output format: %c\n", optarg[0]); show_help(stderr); exit(1); } break; default: show_help(stderr); exit(1); } } } void show_help(FILE* f) { fprintf(f, "Options:\n"); fprintf(f, " -h - print this help\n"); fprintf(f, " -v - be verbose\n"); fprintf(f, " -d filename - specify path to ACPI control pseudo-device. Default: /dev/acpi/call\n"); fprintf(f, " -p path - full path to ACPI method\n"); fprintf(f, " -i number - add integer argument\n"); fprintf(f, " -s string - add string argument\n"); fprintf(f, " -b hexstring - add buffer argument\n"); fprintf(f, " -o i|s|b|o - print result as integer|string|hexstring|object\n"); } int parse_buffer(ACPI_OBJECT *dst, char *src) { char tmp[3] = {0}; size_t len = strlen(src)/2, i; dst->Type = ACPI_TYPE_BUFFER; dst->Buffer.Length = len; if ((dst->Buffer.Pointer = (UINT8*)malloc(len)) == NULL) { fprintf(stderr, "parse_buffer: Failed to allocate %" B_PRIuSIZE " bytes\n", len); exit(1); } for(i = 0; i < len; i++) { tmp[0] = src[i*2]; tmp[1] = src[i*2+1]; dst->Buffer.Pointer[i] = strtol(tmp, NULL, 16); } return 0; } void print_params(struct acpi_call_descr* p) { printf("Path: %s\n", p->path); printf("Number of arguments: %d\n", p->args.Count); for(uint32 i = 0; i < p->args.Count; i++) { switch (p->args.Pointer[i].Type) { case ACPI_TYPE_INTEGER: printf("Argument %d type: Integer\n", i+1); break; case ACPI_TYPE_STRING: printf("Argument %d type: String\n", i+1); break; case ACPI_TYPE_BUFFER: printf("Argument %d type: Buffer\n", i+1); break; } printf("Argument %d value: ", i+1); print_acpi_object(&(p->args.Pointer[i])); printf("\n"); } } void print_acpi_object(ACPI_OBJECT* obj) { switch (obj->Type) { case ACPI_TYPE_INTEGER: printf("%" B_PRIu64, obj->Integer.Value); break; case ACPI_TYPE_STRING: printf("%s", obj->String.Pointer); break; case ACPI_TYPE_BUFFER: for(uint32 i = 0; i < obj->Buffer.Length; i++) { printf("%02X", obj->Buffer.Pointer[i]); } break; default: printf("Unknown object type '%d'", obj->Type); } } void print_acpi_buffer(ACPI_BUFFER* buf, char format) { switch (format) { case 'i': printf("%" B_PRIu64, *((ACPI_INTEGER*)(buf->Pointer))); break; case 's': printf("%s", (char*)buf->Pointer); break; case 'b': for(uint32 i = 0; i < buf->Length; i++) { printf("%02X", ((UINT8*)(buf->Pointer))[i]); } break; case 'o': print_acpi_object((ACPI_OBJECT*)(buf->Pointer)); break; } }