mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-30 18:41:11 +00:00
Comm interface now provides max I/O sizes and preallocated buffers
The maximum packet / param size differs depending on interface and protocol version. Commands can now ask the comm interface what the limits are, and can use preallocated buffers to avoid needless malloc/free. BUG=chrome-os-partner:20571 BRANCH=none TEST=the following all work on link burn_my_ec ectool version ectool chargedump ectool console ectool i2cxfer 5 0x41 2 Change-Id: Ib847994da3f79721e7fb4e347231b9147a3f485f Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/60275
This commit is contained in:
committed by
ChromeBot
parent
267dbb74d2
commit
2730daa567
@@ -21,21 +21,21 @@ static const char * const part_name[] = {"unknown", "RO", "RW"};
|
||||
enum ec_current_image get_version(enum ec_current_image *version_ptr)
|
||||
{
|
||||
struct ec_response_get_version r;
|
||||
char build_info[EC_HOST_PARAM_SIZE];
|
||||
char *build_info = (char *)ec_inbuf;
|
||||
int res;
|
||||
|
||||
res = ec_command(EC_CMD_GET_VERSION, 0, NULL, 0, &r, sizeof(r));
|
||||
if (res < 0)
|
||||
return res;
|
||||
res = ec_command(EC_CMD_GET_BUILD_INFO, 0, NULL, 0, build_info,
|
||||
sizeof(build_info));
|
||||
res = ec_command(EC_CMD_GET_BUILD_INFO, 0, NULL, 0,
|
||||
ec_inbuf, ec_max_insize);
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
/* Ensure versions are null-terminated before we print them */
|
||||
r.version_string_ro[sizeof(r.version_string_ro) - 1] = '\0';
|
||||
r.version_string_rw[sizeof(r.version_string_rw) - 1] = '\0';
|
||||
build_info[sizeof(build_info) - 1] = '\0';
|
||||
build_info[ec_max_insize - 1] = '\0';
|
||||
|
||||
/* Print versions */
|
||||
printf("RO version: %s\n", r.version_string_ro);
|
||||
|
||||
@@ -85,5 +85,11 @@ int comm_init_dev(void)
|
||||
if (ec_readmem_dev(EC_MEMMAP_ID, 2, version) == 2)
|
||||
ec_readmem = ec_readmem_dev;
|
||||
|
||||
/*
|
||||
* TODO: need a way to get this from the driver and EC. For now,
|
||||
* pick a magic lowest common denominator value.
|
||||
*/
|
||||
ec_max_outsize = EC_HOST_PARAM_SIZE - 8;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,10 @@ int (*ec_command)(int command, int version,
|
||||
|
||||
int (*ec_readmem)(int offset, int bytes, void *dest);
|
||||
|
||||
int ec_max_outsize, ec_max_insize;
|
||||
void *ec_outbuf;
|
||||
void *ec_inbuf;
|
||||
|
||||
int comm_init_dev(void) __attribute__((weak));
|
||||
int comm_init_lpc(void) __attribute__((weak));
|
||||
int comm_init_i2c(void) __attribute__((weak));
|
||||
@@ -61,17 +65,29 @@ int comm_init(void)
|
||||
|
||||
/* Prefer new /dev method */
|
||||
if (comm_init_dev && !comm_init_dev())
|
||||
return 0;
|
||||
goto init_ok;
|
||||
|
||||
/* Fallback to direct LPC on x86 */
|
||||
if (comm_init_lpc && !comm_init_lpc())
|
||||
return 0;
|
||||
goto init_ok;
|
||||
|
||||
/* Fallback to direct i2c on ARM */
|
||||
if (comm_init_i2c && !comm_init_i2c())
|
||||
return 0;
|
||||
goto init_ok;
|
||||
|
||||
/* Give up */
|
||||
fprintf(stderr, "Unable to establish host communication\n");
|
||||
return 1;
|
||||
|
||||
init_ok:
|
||||
/* Allocate shared I/O buffers */
|
||||
ec_outbuf = malloc(ec_max_outsize);
|
||||
ec_inbuf = malloc(ec_max_insize);
|
||||
if (!ec_outbuf || !ec_inbuf) {
|
||||
fprintf(stderr, "Unable to allocate buffers\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
@@ -12,12 +12,23 @@
|
||||
#include "common.h"
|
||||
#include "ec_commands.h"
|
||||
|
||||
/* Perform initializations needed for subsequent requests
|
||||
/* Maximum output and input sizes for EC command, in bytes */
|
||||
extern int ec_max_outsize, ec_max_insize;
|
||||
|
||||
/*
|
||||
* Maximum-size output and input buffers, for use by callers. This saves each
|
||||
* caller needing to allocate/free its own buffers.
|
||||
*/
|
||||
extern void *ec_outbuf;
|
||||
extern void *ec_inbuf;
|
||||
|
||||
/**
|
||||
* Perform initializations needed for subsequent requests
|
||||
*
|
||||
* returns 0 in case of success or error code. */
|
||||
int comm_init(void);
|
||||
|
||||
/*
|
||||
/**
|
||||
* Send a command to the EC. Returns the length of output data returned (0 if
|
||||
* none), or negative on error.
|
||||
*/
|
||||
@@ -25,7 +36,7 @@ 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. Returns the number
|
||||
* of bytes read, or negative on error. Specifying bytes=0 will read a
|
||||
|
||||
@@ -213,5 +213,7 @@ int comm_init_i2c(void)
|
||||
free(file_path);
|
||||
|
||||
ec_command = ec_command_i2c;
|
||||
ec_max_outsize = ec_max_insize = EC_HOST_PARAM_SIZE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -297,14 +297,21 @@ int comm_init_lpc(void)
|
||||
|
||||
if (i & EC_HOST_CMD_FLAG_VERSION_3) {
|
||||
ec_command = ec_command_lpc_3;
|
||||
ec_max_outsize = EC_LPC_HOST_PACKET_SIZE -
|
||||
sizeof(struct ec_host_request);
|
||||
ec_max_insize = EC_LPC_HOST_PACKET_SIZE -
|
||||
sizeof(struct ec_host_response);
|
||||
|
||||
} else if (i & EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED) {
|
||||
ec_command = ec_command_lpc;
|
||||
ec_max_outsize = ec_max_insize = EC_HOST_PARAM_SIZE;
|
||||
|
||||
} else {
|
||||
fprintf(stderr, "EC doesn't support protocols we need.\n");
|
||||
return -5;
|
||||
}
|
||||
|
||||
/* Either one supports reading mapped memory directly */
|
||||
/* Either one supports reading mapped memory directly. */
|
||||
ec_readmem = ec_readmem_lpc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -15,22 +15,20 @@
|
||||
int ec_flash_read(uint8_t *buf, int offset, int size)
|
||||
{
|
||||
struct ec_params_flash_read p;
|
||||
/* TODO(rspangler): need better way to determine max read size */
|
||||
uint8_t rdata[EC_HOST_PARAM_SIZE - sizeof(struct ec_host_response)];
|
||||
int rv;
|
||||
int i;
|
||||
|
||||
/* Read data in chunks */
|
||||
for (i = 0; i < size; i += sizeof(rdata)) {
|
||||
for (i = 0; i < size; i += ec_max_insize) {
|
||||
p.offset = offset + i;
|
||||
p.size = MIN(size - i, sizeof(rdata));
|
||||
p.size = MIN(size - i, ec_max_insize);
|
||||
rv = ec_command(EC_CMD_FLASH_READ, 0,
|
||||
&p, sizeof(p), rdata, sizeof(rdata));
|
||||
&p, sizeof(p), ec_inbuf, p.size);
|
||||
if (rv < 0) {
|
||||
fprintf(stderr, "Read error at offset %d\n", i);
|
||||
return rv;
|
||||
}
|
||||
memcpy(buf + i, rdata, p.size);
|
||||
memcpy(buf + i, ec_inbuf, p.size);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -323,17 +323,16 @@ int cmd_cmdversions(int argc, char *argv[])
|
||||
int cmd_version(int argc, char *argv[])
|
||||
{
|
||||
struct ec_response_get_version r;
|
||||
char build_string[EC_HOST_PARAM_SIZE];
|
||||
char *build_string = (char *)ec_inbuf;
|
||||
int rv;
|
||||
|
||||
rv = ec_command(EC_CMD_GET_VERSION, 0,
|
||||
NULL, 0, &r, sizeof(r));
|
||||
rv = ec_command(EC_CMD_GET_VERSION, 0, NULL, 0, &r, sizeof(r));
|
||||
if (rv < 0) {
|
||||
fprintf(stderr, "ERROR: EC_CMD_GET_VERSION failed: %d\n", rv);
|
||||
return rv;
|
||||
}
|
||||
rv = ec_command(EC_CMD_GET_BUILD_INFO, 0,
|
||||
NULL, 0, build_string, sizeof(build_string));
|
||||
NULL, 0, ec_inbuf, ec_max_insize);
|
||||
if (rv < 0) {
|
||||
fprintf(stderr, "ERROR: EC_CMD_GET_BUILD_INFO failed: %d\n",
|
||||
rv);
|
||||
@@ -343,7 +342,7 @@ int cmd_version(int argc, char *argv[])
|
||||
/* Ensure versions are null-terminated before we print them */
|
||||
r.version_string_ro[sizeof(r.version_string_ro) - 1] = '\0';
|
||||
r.version_string_rw[sizeof(r.version_string_rw) - 1] = '\0';
|
||||
build_string[sizeof(build_string) - 1] = '\0';
|
||||
build_string[ec_max_insize - 1] = '\0';
|
||||
|
||||
/* Print versions */
|
||||
printf("RO version: %s\n", r.version_string_ro);
|
||||
@@ -1599,15 +1598,15 @@ static void print_panic_reg(int regnum, const uint32_t *regs, int index)
|
||||
|
||||
int cmd_panic_info(int argc, char *argv[])
|
||||
{
|
||||
char out[EC_HOST_PARAM_SIZE];
|
||||
int rv;
|
||||
struct panic_data *pdata = (struct panic_data *)out;
|
||||
struct panic_data *pdata = (struct panic_data *)ec_inbuf;
|
||||
const uint32_t *lregs = pdata->regs;
|
||||
const uint32_t *sregs = NULL;
|
||||
int in_handler;
|
||||
int i;
|
||||
|
||||
rv = ec_command(EC_CMD_GET_PANIC_INFO, 0, NULL, 0, out, sizeof(out));
|
||||
rv = ec_command(EC_CMD_GET_PANIC_INFO, 0, NULL, 0,
|
||||
ec_inbuf, ec_max_insize);
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
|
||||
@@ -2151,16 +2150,10 @@ int cmd_i2c_write(int argc, char *argv[])
|
||||
|
||||
int cmd_i2c_xfer(int argc, char *argv[])
|
||||
{
|
||||
union {
|
||||
struct ec_params_i2c_passthru p;
|
||||
uint8_t outbuf[EC_HOST_PARAM_SIZE];
|
||||
} params;
|
||||
union {
|
||||
struct ec_response_i2c_passthru r;
|
||||
uint8_t inbuf[EC_HOST_PARAM_SIZE];
|
||||
} response;
|
||||
struct ec_params_i2c_passthru *p = ¶ms.p;
|
||||
struct ec_response_i2c_passthru *r = &response.r;
|
||||
struct ec_params_i2c_passthru *p =
|
||||
(struct ec_params_i2c_passthru *)ec_outbuf;
|
||||
struct ec_response_i2c_passthru *r =
|
||||
(struct ec_response_i2c_passthru *)ec_inbuf;
|
||||
struct ec_params_i2c_passthru_msg *msg = p->msg;
|
||||
unsigned int addr;
|
||||
uint8_t *pdata;
|
||||
@@ -2201,11 +2194,11 @@ int cmd_i2c_xfer(int argc, char *argv[])
|
||||
p->num_msgs = (read_len != 0) + (write_len != 0);
|
||||
|
||||
size = sizeof(*p) + p->num_msgs * sizeof(*msg);
|
||||
if (size + write_len > sizeof(params)) {
|
||||
if (size + write_len > ec_max_outsize) {
|
||||
fprintf(stderr, "Params too large for buffer\n");
|
||||
return -1;
|
||||
}
|
||||
if (sizeof(*r) + read_len > sizeof(response)) {
|
||||
if (sizeof(*r) + read_len > ec_max_insize) {
|
||||
fprintf(stderr, "Read length too big for buffer\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -2364,10 +2357,11 @@ int cmd_charge_force_idle(int argc, char *argv[])
|
||||
|
||||
int cmd_charge_dump(int argc, char *argv[])
|
||||
{
|
||||
unsigned char out[EC_HOST_PARAM_SIZE];
|
||||
unsigned char *out = ec_inbuf;
|
||||
int rv, i;
|
||||
|
||||
rv = ec_command(EC_CMD_CHARGE_DUMP, 0, NULL, 0, out, sizeof(out));
|
||||
rv = ec_command(EC_CMD_CHARGE_DUMP, 0, NULL, 0,
|
||||
ec_inbuf, ec_max_insize);
|
||||
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
@@ -2749,7 +2743,7 @@ int cmd_rtc_set(int argc, char *argv[])
|
||||
|
||||
int cmd_console(int argc, char *argv[])
|
||||
{
|
||||
char out[EC_HOST_PARAM_SIZE];
|
||||
char *out = (char *)ec_inbuf;
|
||||
int rv;
|
||||
|
||||
/* Snapshot the EC console */
|
||||
@@ -2760,7 +2754,7 @@ int cmd_console(int argc, char *argv[])
|
||||
/* Loop and read from the snapshot until it's done */
|
||||
while (1) {
|
||||
rv = ec_command(EC_CMD_CONSOLE_READ, 0,
|
||||
NULL, 0, out, sizeof(out));
|
||||
NULL, 0, ec_inbuf, ec_max_insize);
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
|
||||
@@ -2768,7 +2762,7 @@ int cmd_console(int argc, char *argv[])
|
||||
break; /* Empty response means done */
|
||||
|
||||
/* Make sure output is null-terminated, then dump it */
|
||||
out[sizeof(out) - 1] = '\0';
|
||||
out[ec_max_insize - 1] = '\0';
|
||||
fputs(out, stdout);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
Reference in New Issue
Block a user