root/tools/power/acpi/tools/ec/ec_access.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. usage
  2. parse_opts
  3. dump_ec
  4. read_ec_val
  5. write_ec_val
  6. main

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * ec_access.c
   4  *
   5  * Copyright (C) 2010 SUSE Linux Products GmbH
   6  * Author:
   7  *      Thomas Renninger <trenn@suse.de>
   8  */
   9 
  10 #include <fcntl.h>
  11 #include <err.h>
  12 #include <stdio.h>
  13 #include <stdlib.h>
  14 #include <libgen.h>
  15 #include <unistd.h>
  16 #include <getopt.h>
  17 #include <stdint.h>
  18 #include <sys/types.h>
  19 #include <sys/stat.h>
  20 
  21 
  22 #define EC_SPACE_SIZE 256
  23 #define SYSFS_PATH "/sys/kernel/debug/ec/ec0/io"
  24 
  25 /* TBD/Enhancements:
  26    - Provide param for accessing different ECs (not supported by kernel yet)
  27 */
  28 
  29 static int read_mode = -1;
  30 static int sleep_time;
  31 static int write_byte_offset = -1;
  32 static int read_byte_offset = -1;
  33 static uint8_t write_value = -1;
  34 
  35 void usage(char progname[], int exit_status)
  36 {
  37         printf("Usage:\n");
  38         printf("1) %s -r [-s sleep]\n", basename(progname));
  39         printf("2) %s -b byte_offset\n", basename(progname));
  40         printf("3) %s -w byte_offset -v value\n\n", basename(progname));
  41 
  42         puts("\t-r [-s sleep]      : Dump EC registers");
  43         puts("\t                     If sleep is given, sleep x seconds,");
  44         puts("\t                     re-read EC registers and show changes");
  45         puts("\t-b offset          : Read value at byte_offset (in hex)");
  46         puts("\t-w offset -v value : Write value at byte_offset");
  47         puts("\t-h                 : Print this help\n\n");
  48         puts("Offsets and values are in hexadecimal number system.");
  49         puts("The offset and value must be between 0 and 0xff.");
  50         exit(exit_status);
  51 }
  52 
  53 void parse_opts(int argc, char *argv[])
  54 {
  55         int c;
  56 
  57         while ((c = getopt(argc, argv, "rs:b:w:v:h")) != -1) {
  58 
  59                 switch (c) {
  60                 case 'r':
  61                         if (read_mode != -1)
  62                                 usage(argv[0], EXIT_FAILURE);
  63                         read_mode = 1;
  64                         break;
  65                 case 's':
  66                         if (read_mode != -1 && read_mode != 1)
  67                                 usage(argv[0], EXIT_FAILURE);
  68 
  69                         sleep_time = atoi(optarg);
  70                         if (sleep_time <= 0) {
  71                                 sleep_time = 0;
  72                                 usage(argv[0], EXIT_FAILURE);
  73                                 printf("Bad sleep time: %s\n", optarg);
  74                         }
  75                         break;
  76                 case 'b':
  77                         if (read_mode != -1)
  78                                 usage(argv[0], EXIT_FAILURE);
  79                         read_mode = 1;
  80                         read_byte_offset = strtoul(optarg, NULL, 16);
  81                         break;
  82                 case 'w':
  83                         if (read_mode != -1)
  84                                 usage(argv[0], EXIT_FAILURE);
  85                         read_mode = 0;
  86                         write_byte_offset = strtoul(optarg, NULL, 16);
  87                         break;
  88                 case 'v':
  89                         write_value = strtoul(optarg, NULL, 16);
  90                         break;
  91                 case 'h':
  92                         usage(argv[0], EXIT_SUCCESS);
  93                 default:
  94                         fprintf(stderr, "Unknown option!\n");
  95                         usage(argv[0], EXIT_FAILURE);
  96                 }
  97         }
  98         if (read_mode == 0) {
  99                 if (write_byte_offset < 0 ||
 100                     write_byte_offset >= EC_SPACE_SIZE) {
 101                         fprintf(stderr, "Wrong byte offset 0x%.2x, valid: "
 102                                 "[0-0x%.2x]\n",
 103                                 write_byte_offset, EC_SPACE_SIZE - 1);
 104                         usage(argv[0], EXIT_FAILURE);
 105                 }
 106                 if (write_value < 0 ||
 107                     write_value >= 255) {
 108                         fprintf(stderr, "Wrong byte offset 0x%.2x, valid:"
 109                                 "[0-0xff]\n", write_byte_offset);
 110                         usage(argv[0], EXIT_FAILURE);
 111                 }
 112         }
 113         if (read_mode == 1 && read_byte_offset != -1) {
 114                 if (read_byte_offset < -1 ||
 115                     read_byte_offset >= EC_SPACE_SIZE) {
 116                         fprintf(stderr, "Wrong byte offset 0x%.2x, valid: "
 117                                 "[0-0x%.2x]\n",
 118                                 read_byte_offset, EC_SPACE_SIZE - 1);
 119                         usage(argv[0], EXIT_FAILURE);
 120                 }
 121         }
 122         /* Add additional parameter checks here */
 123 }
 124 
 125 void dump_ec(int fd)
 126 {
 127         char buf[EC_SPACE_SIZE];
 128         char buf2[EC_SPACE_SIZE];
 129         int byte_off, bytes_read;
 130 
 131         bytes_read = read(fd, buf, EC_SPACE_SIZE);
 132 
 133         if (bytes_read == -1)
 134                 err(EXIT_FAILURE, "Could not read from %s\n", SYSFS_PATH);
 135 
 136         if (bytes_read != EC_SPACE_SIZE)
 137                 fprintf(stderr, "Could only read %d bytes\n", bytes_read);
 138 
 139         printf("     00  01  02  03  04  05  06  07  08  09  0A  0B  0C  0D  0E  0F");
 140         for (byte_off = 0; byte_off < bytes_read; byte_off++) {
 141                 if ((byte_off % 16) == 0)
 142                         printf("\n%.2X: ", byte_off);
 143                 printf(" %.2x ", (uint8_t)buf[byte_off]);
 144         }
 145         printf("\n");
 146 
 147         if (!sleep_time)
 148                 return;
 149 
 150         printf("\n");
 151         lseek(fd, 0, SEEK_SET);
 152         sleep(sleep_time);
 153 
 154         bytes_read = read(fd, buf2, EC_SPACE_SIZE);
 155 
 156         if (bytes_read == -1)
 157                 err(EXIT_FAILURE, "Could not read from %s\n", SYSFS_PATH);
 158 
 159         if (bytes_read != EC_SPACE_SIZE)
 160                 fprintf(stderr, "Could only read %d bytes\n", bytes_read);
 161 
 162         printf("     00  01  02  03  04  05  06  07  08  09  0A  0B  0C  0D  0E  0F");
 163         for (byte_off = 0; byte_off < bytes_read; byte_off++) {
 164                 if ((byte_off % 16) == 0)
 165                         printf("\n%.2X: ", byte_off);
 166 
 167                 if (buf[byte_off] == buf2[byte_off])
 168                         printf(" %.2x ", (uint8_t)buf2[byte_off]);
 169                 else
 170                         printf("*%.2x ", (uint8_t)buf2[byte_off]);
 171         }
 172         printf("\n");
 173 }
 174 
 175 void read_ec_val(int fd, int byte_offset)
 176 {
 177         uint8_t buf;
 178         int error;
 179 
 180         error = lseek(fd, byte_offset, SEEK_SET);
 181         if (error != byte_offset)
 182                 err(EXIT_FAILURE, "Cannot set offset to 0x%.2x", byte_offset);
 183 
 184         error = read(fd, &buf, 1);
 185         if (error != 1)
 186                 err(EXIT_FAILURE, "Could not read byte 0x%.2x from %s\n",
 187                     byte_offset, SYSFS_PATH);
 188         printf("0x%.2x\n", buf);
 189         return;
 190 }
 191 
 192 void write_ec_val(int fd, int byte_offset, uint8_t value)
 193 {
 194         int error;
 195 
 196         error = lseek(fd, byte_offset, SEEK_SET);
 197         if (error != byte_offset)
 198                 err(EXIT_FAILURE, "Cannot set offset to 0x%.2x", byte_offset);
 199 
 200         error = write(fd, &value, 1);
 201         if (error != 1)
 202                 err(EXIT_FAILURE, "Cannot write value 0x%.2x to offset 0x%.2x",
 203                     value, byte_offset);
 204 }
 205 
 206 int main(int argc, char *argv[])
 207 {
 208         int file_mode = O_RDONLY;
 209         int fd;
 210 
 211         parse_opts(argc, argv);
 212 
 213         if (read_mode == 0)
 214                 file_mode = O_WRONLY;
 215         else if (read_mode == 1)
 216                 file_mode = O_RDONLY;
 217         else
 218                 usage(argv[0], EXIT_FAILURE);
 219 
 220         fd = open(SYSFS_PATH, file_mode);
 221         if (fd == -1)
 222                 err(EXIT_FAILURE, "%s", SYSFS_PATH);
 223 
 224         if (read_mode)
 225                 if (read_byte_offset == -1)
 226                         dump_ec(fd);
 227                 else if (read_byte_offset < 0 ||
 228                          read_byte_offset >= EC_SPACE_SIZE)
 229                         usage(argv[0], EXIT_FAILURE);
 230                 else
 231                         read_ec_val(fd, read_byte_offset);
 232         else
 233                 write_ec_val(fd, write_byte_offset, write_value);
 234         close(fd);
 235 
 236         exit(EXIT_SUCCESS);
 237 }

/* [<][>][^][v][top][bottom][index][help] */