diff options
author | Bill Richardson <wfrichar@chromium.org> | 2013-05-29 18:00:03 -0700 |
---|---|---|
committer | ChromeBot <chrome-bot@google.com> | 2013-06-05 14:12:23 -0700 |
commit | d0d1564434ae991ac99a6ce54f6f3360f47017a8 (patch) | |
tree | 68ce6707147fbf828fef543222fcde756da1acf2 /util | |
parent | 26475135b551a742f2d148d426c4aa18b338f5ca (diff) | |
download | chrome-ec-d0d1564434ae991ac99a6ce54f6f3360f47017a8.tar.gz |
ectool prefers /dev/cros_ec, then falls back to i2c, lpc
This is preparation for the common userspace EC interface. If/when that
appears, this will be ready.
BUG=chromium:239197
BRANCH=all
TEST=manual
Build, install, run it. Shouldn't be any change.
Change-Id: I9fa78515ec5443ba659f10a66bbaadcb7f4802b0
Signed-off-by: Bill Richardson <wfrichar@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/56131
Diffstat (limited to 'util')
-rw-r--r-- | util/build.mk | 2 | ||||
-rw-r--r-- | util/comm-dev.c | 82 | ||||
-rw-r--r-- | util/comm-host.c | 77 | ||||
-rw-r--r-- | util/comm-host.h | 27 | ||||
-rw-r--r-- | util/comm-i2c.c | 151 | ||||
-rw-r--r-- | util/comm-lpc.c | 155 | ||||
-rw-r--r-- | util/cros_ec_dev.h | 53 | ||||
-rw-r--r-- | util/ectool.c | 69 |
8 files changed, 405 insertions, 211 deletions
diff --git a/util/build.mk b/util/build.mk index 62b25b4e6b..062e34c708 100644 --- a/util/build.mk +++ b/util/build.mk @@ -7,7 +7,7 @@ # host-util-bin=ectool lbplay burn_my_ec -host-util-common=ectool_keyscan +host-util-common=ectool_keyscan comm-host comm-dev ifeq ($(CONFIG_LPC),y) host-util-common+=comm-lpc else diff --git a/util/comm-dev.c b/util/comm-dev.c new file mode 100644 index 0000000000..2802aeca24 --- /dev/null +++ b/util/comm-dev.c @@ -0,0 +1,82 @@ +/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include <errno.h> +#include <fcntl.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +#include "cros_ec_dev.h" +#include "comm-host.h" +#include "ec_commands.h" + +static int fd = -1; + +static int ec_command_dev(int command, int version, + const void *outdata, int outsize, + void *indata, int insize) +{ + struct cros_ec_command s_cmd; + + s_cmd.command = command; + s_cmd.version = version; + s_cmd.result = 0xff; + s_cmd.outsize = outsize; + s_cmd.outdata = (uint8_t *)outdata; + s_cmd.insize = insize; + s_cmd.indata = indata; + + if (ioctl(fd, CROS_EC_DEV_IOCXCMD, &s_cmd)) + return -1; + + return s_cmd.insize; +} + +static int ec_readmem_dev(int offset, int bytes, void *dest) +{ + struct cros_ec_readmem s_mem; + + s_mem.offset = offset; + s_mem.bytes = bytes; + s_mem.buffer = dest; + + return ioctl(fd, CROS_EC_DEV_IOCRDMEM, &s_mem); +} + +int comm_init_dev(void) +{ + char version[80]; + int r; + char *s; + + fd = open("/dev/" CROS_EC_DEV_NAME, O_RDWR); + if (fd < 0) + return 1; + + r = read(fd, version, sizeof(version)-1); + if (r <= 0) { + close(fd); + return 2; + } + version[r] = '\0'; + s = strchr(version, '\n'); + if (s) + *s = '\0'; + if (strcmp(version, CROS_EC_DEV_VERSION)) { + close(fd); + return 3; + } + + ec_command = ec_command_dev; + if (ec_readmem_dev(EC_MEMMAP_ID, 2, version) == 2) + ec_readmem = ec_readmem_dev; + + return 0; +} diff --git a/util/comm-host.c b/util/comm-host.c new file mode 100644 index 0000000000..bf94927361 --- /dev/null +++ b/util/comm-host.c @@ -0,0 +1,77 @@ +/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include <errno.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> + +#include "comm-host.h" +#include "ec_commands.h" + +int (*ec_command)(int command, int version, + const void *outdata, int outsize, + void *indata, int insize); + +int (*ec_readmem)(int offset, int bytes, void *dest); + +int comm_init_dev(void) __attribute__((weak)); +int comm_init_lpc(void) __attribute__((weak)); +int comm_init_i2c(void) __attribute__((weak)); + +static int fake_readmem(int offset, int bytes, void *dest) +{ + struct ec_params_read_memmap p; + int c; + char *buf; + + p.offset = offset; + + if (bytes) { + p.size = bytes; + c = ec_command(EC_CMD_READ_MEMMAP, 0, &p, sizeof(p), + dest, p.size); + if (c < 0) + return c; + return p.size; + } + + p.size = EC_MEMMAP_TEXT_MAX; + + c = ec_command(EC_CMD_READ_MEMMAP, 0, &p, sizeof(p), dest, p.size); + if (c < 0) + return c; + + buf = dest; + for (c = 0; c < EC_MEMMAP_TEXT_MAX; c++) { + if (buf[c] == 0) + return c; + } + + buf[EC_MEMMAP_TEXT_MAX - 1] = 0; + return EC_MEMMAP_TEXT_MAX - 1; +} + +int comm_init(void) +{ + /* Default memmap access */ + ec_readmem = fake_readmem; + + /* Prefer new /dev method */ + if (comm_init_dev && !comm_init_dev()) + return 0; + + /* Fallback to direct LPC on x86 */ + if (comm_init_lpc && !comm_init_lpc()) + return 0; + + /* Fallback to direct i2c on ARM */ + if (comm_init_i2c && !comm_init_i2c()) + return 0; + + /* Give up */ + fprintf(stderr, "Unable to establish host communication\n"); + return 1; +} diff --git a/util/comm-host.h b/util/comm-host.h index a16057abf5..d890156af0 100644 --- a/util/comm-host.h +++ b/util/comm-host.h @@ -1,6 +1,9 @@ -/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved. +/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. + * + * For hysterical raisins, there are several mechanisms for communicating with + * the EC. This abstracts them. */ #ifndef COMM_HOST_H @@ -16,24 +19,18 @@ int comm_init(void); /* * Send a command to the EC. Returns the length of output data returned (0 if - * none), or a negative number if error; errors are -EC_RES_* constants from - * ec_commands.h. + * none), or negative on error. */ -int ec_command(int command, int version, const void *indata, int insize, - void *outdata, int outsize); +extern int (*ec_command)(int command, int version, + const void *outdata, int outsize, /* to the EC */ + void *indata, int insize); /* from the EC */ /* * Return the content of the EC information area mapped as "memory". - * The offsets are defined by the EC_MEMMAP_ constants. - */ -uint8_t read_mapped_mem8(uint8_t offset); -uint16_t read_mapped_mem16(uint8_t offset); -uint32_t read_mapped_mem32(uint8_t offset); -/* - * Read a memory-mapped string at the specified offset and store into buf, - * which must be at least size EC_MEMMAP_TEXT_MAX. Returns the length of - * the copied string, not counting the terminating '\0', or <0 if error. + * The offsets are defined by the EC_MEMMAP_ constants. Returns the number + * of bytes read, or negative on error. Specifying bytes=0 will read a + * string (always including the trailing '\0'). */ -int read_mapped_string(uint8_t offset, char *buf); +extern int (*ec_readmem)(int offset, int bytes, void *dest); #endif /* COMM_HOST_H */ diff --git a/util/comm-i2c.c b/util/comm-i2c.c index d1471495c8..8f75320b48 100644 --- a/util/comm-i2c.c +++ b/util/comm-i2c.c @@ -40,44 +40,6 @@ static int i2c_fd = -1; -int comm_init(void) -{ - char *file_path; - char buffer[64]; - FILE *f; - int i; - - /* find the device number based on the adapter name */ - for (i = 0; i < I2C_MAX_ADAPTER; i++) { - if (asprintf(&file_path, I2C_ADAPTER_NODE, i) < 0) - return -1; - f = fopen(file_path, "r"); - if (f) { - if (fgets(buffer, sizeof(buffer), f) && - !strncmp(buffer, I2C_ADAPTER_NAME, 6)) { - free(file_path); - break; - } - fclose(f); - } - free(file_path); - } - if (i == I2C_MAX_ADAPTER) { - fprintf(stderr, "Cannot find I2C adapter\n"); - return -1; - } - - if (asprintf(&file_path, I2C_NODE, i) < 0) - return -1; - debug("using I2C adapter %s\n", file_path); - i2c_fd = open(file_path, O_RDWR); - if (i2c_fd < 0) - fprintf(stderr, "Cannot open %s : %d\n", file_path, errno); - - free(file_path); - return 0; -} - /* * Sends a command to the EC (protocol v2). Returns the command status code, or @@ -86,8 +48,9 @@ int comm_init(void) * Returns >= 0 for success, or negative if error. * */ -int ec_command(int command, int version, const void *indata, int insize, - void *outdata, int outsize) +static int ec_command_i2c(int command, int version, + const void *outdata, int outsize, + void *indata, int insize) { struct i2c_rdwr_ioctl_data data; int ret = -1; @@ -127,7 +90,7 @@ int ec_command(int command, int version, const void *indata, int insize, * allocate larger packet * (version, command, size, ..., checksum) */ - req_len = insize + PROTO_V2_IN; + req_len = outsize + PROTO_V2_IN; req_buf = calloc(1, req_len); if (!req_buf) goto done; @@ -135,12 +98,12 @@ int ec_command(int command, int version, const void *indata, int insize, i2c_msg[0].buf = (char *)req_buf; req_buf[0] = version + EC_CMD_VERSION0; req_buf[1] = command; - req_buf[2] = insize; + req_buf[2] = outsize; debug("i2c req %02x:", command); sum = req_buf[0] + req_buf[1] + req_buf[2]; /* copy message payload and compute checksum */ - for (i = 0, c = indata; i < insize; i++, c++) { + for (i = 0, c = outdata; i < outsize; i++, c++) { req_buf[i + 3] = *c; sum += *c; debug(" %02x", *c); @@ -152,7 +115,7 @@ int ec_command(int command, int version, const void *indata, int insize, * allocate larger packet * (result, size, ..., checksum) */ - resp_len = outsize + PROTO_V2_OUT; + resp_len = insize + PROTO_V2_OUT; resp_buf = calloc(1, resp_len); if (!resp_buf) goto done; @@ -173,9 +136,9 @@ int ec_command(int command, int version, const void *indata, int insize, /* TODO: handle EC_RES_IN_PROGRESS case. */ resp_len = resp_buf[1]; - if (resp_len > outsize) { + if (resp_len > insize) { fprintf(stderr, "response size is too large %d > %d\n", - resp_len, outsize); + resp_len, insize); ret = -EC_RES_ERROR; goto done; } @@ -185,11 +148,11 @@ int ec_command(int command, int version, const void *indata, int insize, command, i2c_msg[1].buf[0]); /* Translate ERROR to -ERROR */ ret = -ret; - } else if (outsize) { + } else if (insize) { debug("i2c resp :"); /* copy response packet payload and compute checksum */ sum = resp_buf[0] + resp_buf[1]; - for (i = 0, d = outdata; i < resp_len; i++, d++) { + for (i = 0, d = indata; i < resp_len; i++, d++) { *d = resp_buf[i + 2]; sum += *d; debug(" %02x", *d); @@ -213,70 +176,42 @@ done: return ret; } -uint8_t read_mapped_mem8(uint8_t offset) +int comm_init_i2c(void) { - struct ec_params_read_memmap p; - uint8_t val; - - p.offset = offset; - p.size = sizeof(val); - - if (ec_command(EC_CMD_READ_MEMMAP, 0, &p, sizeof(p), - &val, sizeof(val)) < 0) - return 0xff; - - return val; -} - -uint16_t read_mapped_mem16(uint8_t offset) -{ - struct ec_params_read_memmap p; - uint16_t val; - - p.offset = offset; - p.size = sizeof(val); - - if (ec_command(EC_CMD_READ_MEMMAP, 0, &p, sizeof(p), - &val, sizeof(val)) < 0) - return 0xffff; - - return val; -} - -uint32_t read_mapped_mem32(uint8_t offset) -{ - struct ec_params_read_memmap p; - uint32_t val; - - p.offset = offset; - p.size = sizeof(val); - - if (ec_command(EC_CMD_READ_MEMMAP, 0, &p, sizeof(p), - &val, sizeof(val)) < 0) - return 0xffffffff; - - return val; -} - -int read_mapped_string(uint8_t offset, char *buf) -{ - struct ec_params_read_memmap p; - int c; - - p.offset = offset; - p.size = EC_MEMMAP_TEXT_MAX; + char *file_path; + char buffer[64]; + FILE *f; + int i; - if (ec_command(EC_CMD_READ_MEMMAP, 0, &p, sizeof(p), - buf, EC_MEMMAP_TEXT_MAX) < 0) { - *buf = 0; + /* find the device number based on the adapter name */ + for (i = 0; i < I2C_MAX_ADAPTER; i++) { + if (asprintf(&file_path, I2C_ADAPTER_NODE, i) < 0) + return -1; + f = fopen(file_path, "r"); + if (f) { + if (fgets(buffer, sizeof(buffer), f) && + !strncmp(buffer, I2C_ADAPTER_NAME, 6)) { + free(file_path); + break; + } + fclose(f); + } + free(file_path); + } + if (i == I2C_MAX_ADAPTER) { + fprintf(stderr, "Cannot find I2C adapter\n"); return -1; } - for (c = 0; c < EC_MEMMAP_TEXT_MAX; c++) { - if (buf[c] == 0) - return c; - } + if (asprintf(&file_path, I2C_NODE, i) < 0) + return -1; + debug("using I2C adapter %s\n", file_path); + i2c_fd = open(file_path, O_RDWR); + if (i2c_fd < 0) + fprintf(stderr, "Cannot open %s : %d\n", file_path, errno); - buf[EC_MEMMAP_TEXT_MAX - 1] = 0; - return EC_MEMMAP_TEXT_MAX - 1; + free(file_path); + + ec_command = ec_command_i2c; + return 0; } diff --git a/util/comm-lpc.c b/util/comm-lpc.c index dbae5a7ecc..3548f4eb29 100644 --- a/util/comm-lpc.c +++ b/util/comm-lpc.c @@ -14,59 +14,6 @@ #define INITIAL_UDELAY 5 /* 5 us */ #define MAXIMUM_UDELAY 10000 /* 10 ms */ -int comm_init(void) -{ - int i; - int byte = 0xff; - - /* Request I/O privilege */ - if (iopl(3) < 0) { - perror("Error getting I/O privilege"); - return -3; - } - - /* - * Test if the I/O port has been configured for Chromium EC LPC - * interface. If all the bytes are 0xff, very likely that Chromium EC - * is not present. - * - * TODO: (crosbug.com/p/10963) Should only need to look at the command - * byte, since we don't support ACPI burst mode and thus bit 4 should - * be 0. - */ - byte &= inb(EC_LPC_ADDR_HOST_CMD); - byte &= inb(EC_LPC_ADDR_HOST_DATA); - for (i = 0; i < EC_HOST_PARAM_SIZE && byte == 0xff; ++i) - byte &= inb(EC_LPC_ADDR_HOST_PARAM + i); - if (byte == 0xff) { - fprintf(stderr, "Port 0x%x,0x%x,0x%x-0x%x are all 0xFF.\n", - EC_LPC_ADDR_HOST_CMD, EC_LPC_ADDR_HOST_DATA, - EC_LPC_ADDR_HOST_PARAM, - EC_LPC_ADDR_HOST_PARAM + EC_HOST_PARAM_SIZE - 1); - fprintf(stderr, - "Very likely this board doesn't have a Chromium EC.\n"); - return -4; - } - - /* - * Test if LPC command args are supported. - * - * The cheapest way to do this is by looking for the memory-mapped - * flag. This is faster than sending a new-style 'hello' command and - * seeing whether the EC sets the EC_HOST_ARGS_FLAG_FROM_HOST flag - * in args when it responds. - */ - if (inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID) != 'E' || - inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID + 1) != 'C' || - !(inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_HOST_CMD_FLAGS) & - EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED)) { - fprintf(stderr, "EC doesn't support command args.\n"); - return -5; - } - - return 0; -} - /* * Wait for the EC to be unbusy. Returns 0 if unbusy, non-zero if * timeout. @@ -97,9 +44,10 @@ static int wait_for_ec(int status_addr, int timeout_usec) return -1; /* Timeout */ } -int ec_command(int command, int version, const void *indata, int insize, - void *outdata, int outsize) { - +static int ec_command_lpc(int command, int version, + const void *outdata, int outsize, + void *indata, int insize) +{ struct ec_lpc_host_args args; const uint8_t *d; uint8_t *dout; @@ -109,13 +57,13 @@ int ec_command(int command, int version, const void *indata, int insize, /* Fill in args */ args.flags = EC_HOST_ARGS_FLAG_FROM_HOST; args.command_version = version; - args.data_size = insize; + args.data_size = outsize; /* Initialize checksum */ csum = command + args.flags + args.command_version + args.data_size; /* Write data and update checksum */ - for (i = 0, d = (uint8_t *)indata; i < insize; i++, d++) { + for (i = 0, d = (uint8_t *)outdata; i < outsize; i++, d++) { outb(*d, EC_LPC_ADDR_HOST_PARAM + i); csum += *d; } @@ -153,7 +101,7 @@ int ec_command(int command, int version, const void *indata, int insize, return -EC_RES_INVALID_RESPONSE; } - if (args.data_size > outsize) { + if (args.data_size > insize) { fprintf(stderr, "EC returned too much data\n"); return -EC_RES_INVALID_RESPONSE; } @@ -162,7 +110,7 @@ int ec_command(int command, int version, const void *indata, int insize, csum = command + args.flags + args.command_version + args.data_size; /* Read response and update checksum */ - for (i = 0, dout = (uint8_t *)outdata; i < args.data_size; + for (i = 0, dout = (uint8_t *)indata; i < args.data_size; i++, dout++) { *dout = inb(EC_LPC_ADDR_HOST_PARAM + i); csum += *dout; @@ -179,31 +127,82 @@ int ec_command(int command, int version, const void *indata, int insize, } -uint8_t read_mapped_mem8(uint8_t offset) +static int ec_readmem_lpc(int offset, int bytes, void *dest) { - return inb(EC_LPC_ADDR_MEMMAP + offset); -} + int i = offset; + char *s = dest; + int cnt = 0; + + if (offset >= EC_MEMMAP_SIZE - bytes) + return -1; + + if (bytes) { /* fixed length */ + for (; cnt < bytes; i++, s++, cnt++) + *s = inb(EC_LPC_ADDR_MEMMAP + i); + } else { /* string */ + for (; i < EC_MEMMAP_SIZE; i++, s++) { + *s = inb(EC_LPC_ADDR_MEMMAP + i); + cnt++; + if (!*s) + break; + } + } -uint16_t read_mapped_mem16(uint8_t offset) -{ - return inw(EC_LPC_ADDR_MEMMAP + offset); + return cnt; } -uint32_t read_mapped_mem32(uint8_t offset) +int comm_init_lpc(void) { - return inl(EC_LPC_ADDR_MEMMAP + offset); -} + int i; + int byte = 0xff; -int read_mapped_string(uint8_t offset, char *buf) -{ - int c; + /* Request I/O privilege */ + if (iopl(3) < 0) { + perror("Error getting I/O privilege"); + return -3; + } + + /* + * Test if the I/O port has been configured for Chromium EC LPC + * interface. If all the bytes are 0xff, very likely that Chromium EC + * is not present. + * + * TODO: (crosbug.com/p/10963) Should only need to look at the command + * byte, since we don't support ACPI burst mode and thus bit 4 should + * be 0. + */ + byte &= inb(EC_LPC_ADDR_HOST_CMD); + byte &= inb(EC_LPC_ADDR_HOST_DATA); + for (i = 0; i < EC_HOST_PARAM_SIZE && byte == 0xff; ++i) + byte &= inb(EC_LPC_ADDR_HOST_PARAM + i); + if (byte == 0xff) { + fprintf(stderr, "Port 0x%x,0x%x,0x%x-0x%x are all 0xFF.\n", + EC_LPC_ADDR_HOST_CMD, EC_LPC_ADDR_HOST_DATA, + EC_LPC_ADDR_HOST_PARAM, + EC_LPC_ADDR_HOST_PARAM + EC_HOST_PARAM_SIZE - 1); + fprintf(stderr, + "Very likely this board doesn't have a Chromium EC.\n"); + return -4; + } - for (c = 0; c < EC_MEMMAP_TEXT_MAX; c++) { - buf[c] = inb(EC_LPC_ADDR_MEMMAP + offset + c); - if (buf[c] == 0) - return c; + /* + * Test if LPC command args are supported. + * + * The cheapest way to do this is by looking for the memory-mapped + * flag. This is faster than sending a new-style 'hello' command and + * seeing whether the EC sets the EC_HOST_ARGS_FLAG_FROM_HOST flag + * in args when it responds. + */ + if (inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID) != 'E' || + inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID + 1) != 'C' || + !(inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_HOST_CMD_FLAGS) & + EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED)) { + fprintf(stderr, "EC doesn't support command args.\n"); + return -5; } - buf[EC_MEMMAP_TEXT_MAX - 1] = 0; - return EC_MEMMAP_TEXT_MAX - 1; + /* Okay, this works */ + ec_command = ec_command_lpc; + ec_readmem = ec_readmem_lpc; + return 0; } diff --git a/util/cros_ec_dev.h b/util/cros_ec_dev.h new file mode 100644 index 0000000000..f56c3ef67f --- /dev/null +++ b/util/cros_ec_dev.h @@ -0,0 +1,53 @@ +/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _CROS_EC_DEV_H_ +#define _CROS_EC_DEV_H_ + +#include <linux/ioctl.h> +#include <linux/types.h> + +#define CROS_EC_DEV_NAME "cros_ec" +#define CROS_EC_DEV_VERSION "1.0.0" + + +/* + * @version: Command version number (often 0) + * @command: Command to send (EC_CMD_...) + * @outdata: Outgoing data to EC + * @outsize: Outgoing length in bytes + * @indata: Where to put the incoming data from EC + * @insize: Incoming length in bytes (filled in by EC) + * @result: EC's response to the command (separate from communication failure) + * ioctl returns zero on success, negative on error + */ +struct cros_ec_command { + uint32_t version; + uint32_t command; + uint8_t *outdata; + uint32_t outsize; + uint8_t *indata; + uint32_t insize; + uint32_t result; +}; + +/* + * @offset: within EC_LPC_ADDR_MEMMAP region + * @bytes: number of bytes to read. zero means "read a string" (including '\0') + * (at most only EC_MEMMAP_SIZE bytes can be read) + * @buffer: where to store the result + * ioctl returns the number of bytes read, negative on error + */ +struct cros_ec_readmem { + uint32_t offset; + uint32_t bytes; + char *buffer; +}; + +#define CROS_EC_DEV_IOC ':' +#define CROS_EC_DEV_IOCXCMD _IOWR(':', 0, struct cros_ec_command) +#define CROS_EC_DEV_IOCRDMEM _IOWR(':', 1, struct cros_ec_readmem) + +#endif /* _CROS_EC_DEV_H_ */ diff --git a/util/ectool.c b/util/ectool.c index 5deb582742..521ebea767 100644 --- a/util/ectool.c +++ b/util/ectool.c @@ -256,6 +256,56 @@ void print_help(const char *prog) puts(help_str); } +static uint8_t read_mapped_mem8(uint8_t offset) +{ + int ret; + uint8_t val; + + ret = ec_readmem(offset, sizeof(val), &val); + if (ret <= 0) { + fprintf(stderr, "failure in %s(): %d\n", __func__, ret); + exit(1); + } + return val; +} + +static uint16_t read_mapped_mem16(uint8_t offset) +{ + int ret; + uint16_t val; + + ret = ec_readmem(offset, sizeof(val), &val); + if (ret <= 0) { + fprintf(stderr, "failure in %s(): %d\n", __func__, ret); + exit(1); + } + return val; +} + +static uint32_t read_mapped_mem32(uint8_t offset) +{ + int ret; + uint32_t val; + + ret = ec_readmem(offset, sizeof(val), &val); + if (ret <= 0) { + fprintf(stderr, "failure in %s(): %d\n", __func__, ret); + exit(1); + } + return val; +} + +static int read_mapped_string(uint8_t offset, char *buffer) +{ + int ret; + + ret = ec_readmem(offset, 0, buffer); + if (ret <= 0) { + fprintf(stderr, "failure in %s(): %d\n", __func__, ret); + exit(1); + } + return ret; +} int cmd_hello(int argc, char *argv[]) { @@ -2394,7 +2444,7 @@ int cmd_battery(int argc, char *argv[]) val = read_mapped_mem8(EC_MEMMAP_BATTERY_VERSION); if (val < 1) { - printf("Command not supported\n"); + fprintf(stderr, "Battery version %d is not supported\n", val); return -1; } @@ -2469,7 +2519,7 @@ int cmd_battery(int argc, char *argv[]) return 0; cmd_error: - fprintf(stderr, "Bad battery info value. Check protocol version."); + fprintf(stderr, "Bad battery info value. Check protocol version.\n"); return -1; } @@ -3031,23 +3081,25 @@ const struct command commands[] = { int main(int argc, char *argv[]) { const struct command *cmd; - int rv; + int rv = 1; BUILD_ASSERT(ARRAY_SIZE(lb_command_paramcount) == LIGHTBAR_NUM_CMDS); if (argc < 2 || !strcasecmp(argv[1], "-?") || !strcasecmp(argv[1], "help")) { print_help(argv[0]); - return -2; + exit(1); } if (acquire_gec_lock(GEC_LOCK_TIMEOUT_SECS) < 0) { fprintf(stderr, "Could not acquire GEC lock.\n"); - return 1; + exit(1); } - if (comm_init() < 0) - return -3; + if (comm_init() < 0) { + fprintf(stderr, "Couldn't find EC\n"); + goto out; + } /* Handle commands */ for (cmd = commands; cmd->name; cmd++) { @@ -3060,9 +3112,8 @@ int main(int argc, char *argv[]) /* If we're still here, command was unknown */ fprintf(stderr, "Unknown command '%s'\n\n", argv[1]); print_help(argv[0]); - rv = -2; out: release_gec_lock(); - return rv; + return !!rv; } |