Add common interface to EC flash commands

ectool and burn_my_ec need to use the same lower-level interface to
the EC flash commands, rather than duplicating calling the low-level
flash read/write/erase commands.

This is a precursor to refactoring the low-level commands to support
SPI/STM32L in a follow-up CL.

BUG=chrome-os-partner:20571
BRANCH=none
TEST=in a root shell, burn_my_ec flashes both RO and RW EC code

Change-Id: I4c72690100d86dbff03b7dacc2fb248b571d3820
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/60266
This commit is contained in:
Randall Spangler
2013-06-27 13:06:19 -07:00
committed by ChromeBot
parent 23dd3f5f9b
commit 267dbb74d2
5 changed files with 184 additions and 72 deletions

View File

@@ -7,7 +7,7 @@
#
host-util-bin=ectool lbplay burn_my_ec
host-util-common=ectool_keyscan comm-host comm-dev misc_util
host-util-common=ectool_keyscan comm-host comm-dev misc_util ec_flash
ifeq ($(CONFIG_LPC),y)
host-util-common+=comm-lpc
else

View File

@@ -11,6 +11,7 @@
#include <unistd.h>
#include "comm-host.h"
#include "ec_flash.h"
#define STR0(name) #name
#define STR(name) STR0(name)
@@ -54,12 +55,7 @@ int flash_partition(enum ec_current_image part, const uint8_t *payload,
uint32_t offset, uint32_t size)
{
struct ec_params_reboot_ec rst_req;
struct ec_params_flash_erase er_req;
struct ec_params_flash_write wr_req;
struct ec_params_flash_read rd_req;
uint8_t rd_resp[EC_HOST_PARAM_SIZE];
int res;
uint32_t i;
enum ec_current_image current = EC_IMAGE_UNKNOWN;
res = get_version(&current);
@@ -74,15 +70,12 @@ int flash_partition(enum ec_current_image part, const uint8_t *payload,
ec_command(EC_CMD_REBOOT_EC, 0, &rst_req, sizeof(rst_req),
NULL, 0);
/* wait EC reboot */
usleep(500000);
usleep(1000000);
}
printf("Erasing partition %s : 0x%x bytes at 0x%08x\n",
part_name[part], size, offset);
er_req.size = size;
er_req.offset = offset;
res = ec_command(EC_CMD_FLASH_ERASE, 0,
&er_req, sizeof(er_req), NULL, 0);
res = ec_flash_erase(offset, size);
if (res < 0) {
fprintf(stderr, "Erase failed : %d\n", res);
return -1;
@@ -90,35 +83,20 @@ int flash_partition(enum ec_current_image part, const uint8_t *payload,
printf("Writing partition %s : 0x%x bytes at 0x%08x\n",
part_name[part], size, offset);
/* Write data in chunks */
for (i = 0; i < size; i += sizeof(wr_req.data)) {
wr_req.offset = offset + i;
wr_req.size = MIN(size - i, sizeof(wr_req.data));
memcpy(wr_req.data, payload + i, wr_req.size);
res = ec_command(EC_CMD_FLASH_WRITE, 0,
&wr_req, sizeof(wr_req), NULL, 0);
if (res < 0) {
fprintf(stderr, "Write error at 0x%08x : %d\n", i, res);
return -1;
}
res = ec_flash_write(payload, offset, size);
if (res < 0) {
fprintf(stderr, "Write failed : %d\n", res);
return -1;
}
printf("Verifying partition %s : 0x%x bytes at 0x%08x\n",
part_name[part], size, offset);
/* Read data in chunks */
for (i = 0; i < size; i += sizeof(rd_resp)) {
rd_req.offset = offset + i;
rd_req.size = MIN(size - i, sizeof(rd_resp));
res = ec_command(EC_CMD_FLASH_READ, 0, &rd_req, sizeof(rd_req),
&rd_resp, sizeof(rd_resp));
if (res < 0) {
fprintf(stderr, "Read error at 0x%08x : %d\n", i, res);
return -1;
}
if (memcmp(payload + i, rd_resp, rd_req.size))
fprintf(stderr, "ERR: @%08x->%08x\n",
offset + i, offset + i + size);
res = ec_flash_verify(payload, offset, size);
if (res < 0) {
fprintf(stderr, "Verify failed : %d\n", res);
return -1;
}
printf("Done.\n");
return get_version(NULL);

99
util/ec_flash.c Normal file
View File

@@ -0,0 +1,99 @@
/* 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 <stdlib.h>
#include <string.h>
#include "comm-host.h"
#include "misc_util.h"
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)) {
p.offset = offset + i;
p.size = MIN(size - i, sizeof(rdata));
rv = ec_command(EC_CMD_FLASH_READ, 0,
&p, sizeof(p), rdata, sizeof(rdata));
if (rv < 0) {
fprintf(stderr, "Read error at offset %d\n", i);
return rv;
}
memcpy(buf + i, rdata, p.size);
}
return 0;
}
int ec_flash_verify(const uint8_t *buf, int offset, int size)
{
uint8_t *rbuf = malloc(size);
int rv;
int i;
if (!rbuf) {
fprintf(stderr, "Unable to allocate buffer.\n");
return -1;
}
rv = ec_flash_read(rbuf, offset, size);
if (rv < 0) {
free(rbuf);
return rv;
}
for (i = 0; i < size; i++) {
if (buf[i] != rbuf[i]) {
fprintf(stderr, "Mismatch at offset 0x%x: "
"want 0x%02x, got 0x%02x\n",
i, buf[i], rbuf[i]);
free(rbuf);
return -1;
}
}
free(rbuf);
return 0;
}
int ec_flash_write(const uint8_t *buf, int offset, int size)
{
struct ec_params_flash_write p;
int rv;
int i;
/* Write data in chunks */
for (i = 0; i < size; i += sizeof(p.data)) {
p.offset = offset + i;
p.size = MIN(size - i, sizeof(p.data));
memcpy(p.data, buf + i, p.size);
rv = ec_command(EC_CMD_FLASH_WRITE, 0, &p, sizeof(p), NULL, 0);
if (rv < 0) {
fprintf(stderr, "Write error at offset %d\n", i);
return rv;
}
}
return 0;
}
int ec_flash_erase(int offset, int size)
{
struct ec_params_flash_erase p;
p.offset = offset;
p.size = size;
return ec_command(EC_CMD_FLASH_ERASE, 0, &p, sizeof(p), NULL, 0);
}

52
util/ec_flash.h Normal file
View File

@@ -0,0 +1,52 @@
/* 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_EC_FLASH_H
#define __CROS_EC_EC_FLASH_H
/**
* Read EC flash memory
*
* @param buf Destination buffer
* @param offset Offset in EC flash to read
* @param size Number of bytes to read
*
* @return 0 if success, negative if error.
*/
int ec_flash_read(uint8_t *buf, int offset, int size);
/**
* Verify EC flash memory
*
* @param buf Source buffer to verify against EC flash
* @param offset Offset in EC flash to check
* @param size Number of bytes to check
*
* @return 0 if success, negative if error.
*/
int ec_flash_verify(const uint8_t *buf, int offset, int size);
/**
* Write EC flash memory
*
* @param buf Source buffer
* @param offset Offset in EC flash to write
* @param size Number of bytes to write
*
* @return 0 if success, negative if error.
*/
int ec_flash_write(const uint8_t *buf, int offset, int size);
/**
* Erase EC flash memory
*
* @param offset Offset in EC flash to erase
* @param size Number of bytes to erase
*
* @return 0 if success, negative if error.
*/
int ec_flash_erase(int offset, int size);
#endif

View File

@@ -15,6 +15,7 @@
#include "battery.h"
#include "comm-host.h"
#include "compile_time_macros.h"
#include "ec_flash.h"
#include "ectool.h"
#include "lightbar.h"
#include "lock/gec_lock.h"
@@ -487,14 +488,10 @@ int cmd_flash_info(int argc, char *argv[])
return 0;
}
int cmd_flash_read(int argc, char *argv[])
{
struct ec_params_flash_read p;
uint8_t rdata[EC_HOST_PARAM_SIZE];
int offset, size;
int rv;
int i;
char *e;
char *buf;
@@ -522,17 +519,10 @@ int cmd_flash_read(int argc, char *argv[])
}
/* Read data in chunks */
for (i = 0; i < size; i += sizeof(rdata)) {
p.offset = offset + i;
p.size = MIN(size - i, sizeof(rdata));
rv = ec_command(EC_CMD_FLASH_READ, 0,
&p, sizeof(p), rdata, sizeof(rdata));
if (rv < 0) {
fprintf(stderr, "Read error at offset %d\n", i);
free(buf);
return rv;
}
memcpy(buf + i, rdata, p.size);
rv = ec_flash_read(buf, offset, size);
if (rv < 0) {
free(buf);
return rv;
}
rv = write_file(argv[3], buf, size);
@@ -544,13 +534,10 @@ int cmd_flash_read(int argc, char *argv[])
return 0;
}
int cmd_flash_write(int argc, char *argv[])
{
struct ec_params_flash_write p;
int offset, size;
int rv;
int i;
char *e;
char *buf;
@@ -558,6 +545,7 @@ int cmd_flash_write(int argc, char *argv[])
fprintf(stderr, "Usage: %s <offset> <filename>\n", argv[0]);
return -1;
}
offset = strtol(argv[1], &e, 0);
if ((e && *e) || offset < 0 || offset > 0x100000) {
fprintf(stderr, "Bad offset.\n");
@@ -572,27 +560,20 @@ int cmd_flash_write(int argc, char *argv[])
printf("Writing to offset %d...\n", offset);
/* Write data in chunks */
for (i = 0; i < size; i += sizeof(p.data)) {
p.offset = offset + i;
p.size = MIN(size - i, sizeof(p.data));
memcpy(p.data, buf + i, p.size);
rv = ec_command(EC_CMD_FLASH_WRITE, 0, &p, sizeof(p), NULL, 0);
if (rv < 0) {
fprintf(stderr, "Write error at offset %d\n", i);
free(buf);
return rv;
}
}
rv = ec_flash_write(buf, offset, size);
free(buf);
if (rv < 0)
return rv;
printf("done.\n");
return 0;
}
int cmd_flash_erase(int argc, char *argv[])
{
struct ec_params_flash_erase p;
int offset, size;
char *e;
int rv;
@@ -600,19 +581,21 @@ int cmd_flash_erase(int argc, char *argv[])
fprintf(stderr, "Usage: %s <offset> <size>\n", argv[0]);
return -1;
}
p.offset = strtol(argv[1], &e, 0);
if ((e && *e) || p.offset < 0 || p.offset > 0x100000) {
offset = strtol(argv[1], &e, 0);
if ((e && *e) || offset < 0 || offset > 0x100000) {
fprintf(stderr, "Bad offset.\n");
return -1;
}
p.size = strtol(argv[2], &e, 0);
if ((e && *e) || p.size <= 0 || p.size > 0x100000) {
size = strtol(argv[2], &e, 0);
if ((e && *e) || size <= 0 || size > 0x100000) {
fprintf(stderr, "Bad size.\n");
return -1;
}
printf("Erasing %d bytes at offset %d...\n", p.size, p.offset);
rv = ec_command(EC_CMD_FLASH_ERASE, 0, &p, sizeof(p), NULL, 0);
printf("Erasing %d bytes at offset %d...\n", size, offset);
rv = ec_flash_erase(offset, size);
if (rv < 0)
return rv;