mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-11 18:35:28 +00:00
Add persistent host storage in EC EEPROM
Signed-off-by: Randall Spangler <rspangler@chromium.org> BUG=chrome-os-partner:8247 TEST=manual from root shell on host: ectool pstoreinfo --> should print PstoreSize 1024 AccessSize 4 echo testing 1 2 3 4 > /tmp/infile ectool pstorewrite 8 /tmp/infile ectool pstoreread 8 /tmp/outfile diff /tmp/infile /tmp/outfile Change-Id: I565e580307584f7def36c5e53d360c1a897d67d2
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
/* Optional features */
|
||||
#define CONFIG_PECI
|
||||
#define CONFIG_TMP006
|
||||
#define CONFIG_PSTORE
|
||||
|
||||
/* 66.667 Mhz clock frequency */
|
||||
#define CPU_CLOCK 66666667
|
||||
|
||||
@@ -14,6 +14,7 @@ common-$(CONFIG_TASK_I8042CMD)+=i8042.o keyboard.o
|
||||
common-$(CONFIG_TASK_X86POWER)+=x86_power.o
|
||||
common-$(CONFIG_TASK_GAIAPOWER)+=gaia_power.o
|
||||
common-$(CONFIG_FLASH)+=flash_commands.o
|
||||
common-$(CONFIG_PSTORE)+=pstore_commands.o
|
||||
common-$(CONFIG_PWM)+=pwm_commands.o
|
||||
common-$(CONFIG_TEMP_SENSOR)+=temp_sensor.o
|
||||
common-$(CONFIG_TMP006)+=tmp006.o
|
||||
|
||||
@@ -5,19 +5,20 @@
|
||||
|
||||
/* Host command module for Chrome EC */
|
||||
|
||||
#include "board.h"
|
||||
#include "config.h"
|
||||
#include "console.h"
|
||||
#include "flash_commands.h"
|
||||
#include "host_command.h"
|
||||
#include "pwm_commands.h"
|
||||
#include "usb_charge_commands.h"
|
||||
#include "lpc.h"
|
||||
#include "lpc_commands.h"
|
||||
#include "pstore_commands.h"
|
||||
#include "pwm_commands.h"
|
||||
#include "system.h"
|
||||
#include "task.h"
|
||||
#include "timer.h"
|
||||
#include "uart.h"
|
||||
#include "registers.h"
|
||||
#include "usb_charge_commands.h"
|
||||
#include "util.h"
|
||||
|
||||
static int host_command[2];
|
||||
@@ -192,6 +193,17 @@ static void command_process(int slot)
|
||||
case EC_LPC_COMMAND_USB_CHARGE_SET_MODE:
|
||||
lpc_send_host_response(slot, usb_charge_command_set_mode(data));
|
||||
return;
|
||||
#ifdef CONFIG_PSTORE
|
||||
case EC_LPC_COMMAND_PSTORE_INFO:
|
||||
lpc_send_host_response(slot, pstore_command_get_info(data));
|
||||
return;
|
||||
case EC_LPC_COMMAND_PSTORE_READ:
|
||||
lpc_send_host_response(slot, pstore_command_read(data));
|
||||
return;
|
||||
case EC_LPC_COMMAND_PSTORE_WRITE:
|
||||
lpc_send_host_response(slot, pstore_command_write(data));
|
||||
return;
|
||||
#endif
|
||||
default:
|
||||
lpc_send_host_response(slot, EC_LPC_STATUS_INVALID_COMMAND);
|
||||
}
|
||||
|
||||
109
common/pstore_commands.c
Normal file
109
common/pstore_commands.c
Normal file
@@ -0,0 +1,109 @@
|
||||
/* Copyright (c) 2012 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.
|
||||
*/
|
||||
|
||||
/* Persistent storage commands for Chrome EC */
|
||||
|
||||
#include "board.h"
|
||||
#include "eeprom.h"
|
||||
#include "lpc_commands.h"
|
||||
#include "pstore_commands.h"
|
||||
#include "uart.h"
|
||||
#include "util.h"
|
||||
|
||||
/* TODO: move these to board.h */
|
||||
#ifdef CONFIG_PSTORE
|
||||
/* Start block and block count for host persistent storage in EC EEPROM */
|
||||
#define PSTORE_EEPROM_BLOCK_START 16
|
||||
#define PSTORE_EEPROM_BLOCK_COUNT 16
|
||||
#endif
|
||||
|
||||
enum lpc_status pstore_command_get_info(uint8_t *data)
|
||||
{
|
||||
struct lpc_response_pstore_info *r =
|
||||
(struct lpc_response_pstore_info *)data;
|
||||
|
||||
uart_printf("ee block size=%d, count=%d\n",
|
||||
eeprom_get_block_size(), eeprom_get_block_count());
|
||||
|
||||
ASSERT(PSTORE_EEPROM_BLOCK_START + PSTORE_EEPROM_BLOCK_COUNT <=
|
||||
eeprom_get_block_count());
|
||||
|
||||
r->pstore_size = PSTORE_EEPROM_BLOCK_COUNT * eeprom_get_block_size();
|
||||
r->access_size = sizeof(uint32_t);
|
||||
return EC_LPC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
enum lpc_status pstore_command_read(uint8_t *data)
|
||||
{
|
||||
struct lpc_params_pstore_read *p =
|
||||
(struct lpc_params_pstore_read *)data;
|
||||
struct lpc_response_pstore_read *r =
|
||||
(struct lpc_response_pstore_read *)data;
|
||||
char *dest = r->data;
|
||||
int block_size = eeprom_get_block_size();
|
||||
int block = p->offset / block_size + PSTORE_EEPROM_BLOCK_COUNT;
|
||||
int offset = p->offset % block_size;
|
||||
int bytes_left = p->size;
|
||||
|
||||
if (p->size > sizeof(r->data))
|
||||
return EC_LPC_STATUS_ERROR;
|
||||
|
||||
while (bytes_left) {
|
||||
/* Read what we can from the current block */
|
||||
int bytes_this = MIN(bytes_left, block_size - offset);
|
||||
|
||||
if (block >=
|
||||
PSTORE_EEPROM_BLOCK_START + PSTORE_EEPROM_BLOCK_COUNT)
|
||||
return EC_LPC_STATUS_ERROR;
|
||||
|
||||
if (eeprom_read(block, offset, bytes_this, dest))
|
||||
return EC_LPC_STATUS_ERROR;
|
||||
|
||||
/* Continue to the next block if necessary */
|
||||
offset = 0;
|
||||
block++;
|
||||
bytes_left -= bytes_this;
|
||||
dest += bytes_this;
|
||||
}
|
||||
|
||||
return EC_LPC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
enum lpc_status pstore_command_write(uint8_t *data)
|
||||
{
|
||||
struct lpc_params_pstore_write *p =
|
||||
(struct lpc_params_pstore_write *)data;
|
||||
|
||||
const char *src = p->data;
|
||||
int block_size = eeprom_get_block_size();
|
||||
int block = p->offset / block_size + PSTORE_EEPROM_BLOCK_COUNT;
|
||||
int offset = p->offset % block_size;
|
||||
int bytes_left = p->size;
|
||||
|
||||
if (p->size > sizeof(p->data))
|
||||
return EC_LPC_STATUS_ERROR;
|
||||
|
||||
while (bytes_left) {
|
||||
/* Write what we can to the current block */
|
||||
int bytes_this = MIN(bytes_left, block_size - offset);
|
||||
|
||||
if (block >=
|
||||
PSTORE_EEPROM_BLOCK_START + PSTORE_EEPROM_BLOCK_COUNT)
|
||||
return EC_LPC_STATUS_ERROR;
|
||||
|
||||
if (eeprom_write(block, offset, bytes_this, src))
|
||||
return EC_LPC_STATUS_ERROR;
|
||||
|
||||
/* Continue to the next block if necessary */
|
||||
offset = 0;
|
||||
block++;
|
||||
bytes_left -= bytes_this;
|
||||
src += bytes_this;
|
||||
}
|
||||
|
||||
return EC_LPC_STATUS_SUCCESS;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
|
||||
/* Copyright (c) 2012 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.
|
||||
*/
|
||||
@@ -11,9 +11,6 @@
|
||||
#include "common.h"
|
||||
#include "lpc_commands.h"
|
||||
|
||||
/* Initializes the module. */
|
||||
int flash_commands_init(void);
|
||||
|
||||
/* Host command handlers. */
|
||||
enum lpc_status flash_command_get_info(uint8_t *data);
|
||||
enum lpc_status flash_command_read(uint8_t *data);
|
||||
|
||||
@@ -136,7 +136,6 @@ struct lpc_response_flash_info {
|
||||
uint32_t protect_block_size;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
/* Read flash */
|
||||
#define EC_LPC_COMMAND_FLASH_READ 0x11
|
||||
struct lpc_params_flash_read {
|
||||
@@ -147,16 +146,14 @@ struct lpc_response_flash_read {
|
||||
uint8_t data[EC_LPC_FLASH_SIZE_MAX];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
/* Write flash */
|
||||
#define EC_LPC_COMMAND_FLASH_WRITE 0x12
|
||||
struct lpc_params_flash_write {
|
||||
uint32_t offset; /* Byte offset to erase */
|
||||
uint32_t size; /* Size to erase in bytes */
|
||||
uint32_t offset; /* Byte offset to write */
|
||||
uint32_t size; /* Size to write in bytes */
|
||||
uint8_t data[EC_LPC_FLASH_SIZE_MAX];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
/* Erase flash */
|
||||
#define EC_LPC_COMMAND_FLASH_ERASE 0x13
|
||||
struct lpc_params_flash_erase {
|
||||
@@ -249,7 +246,6 @@ struct lpc_params_pwm_set_keyboard_backlight {
|
||||
uint8_t percent;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* USB charging control commands */
|
||||
|
||||
@@ -260,4 +256,38 @@ struct lpc_params_usb_charge_set_mode {
|
||||
uint8_t mode;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Persistent storage for host */
|
||||
|
||||
/* Maximum bytes that can be read/written in a single command */
|
||||
#define EC_LPC_PSTORE_SIZE_MAX 64
|
||||
|
||||
/* Get persistent storage info */
|
||||
#define EC_LPC_COMMAND_PSTORE_INFO 0x40
|
||||
struct lpc_response_pstore_info {
|
||||
/* Persistent storage size, in bytes */
|
||||
uint32_t pstore_size;
|
||||
/* Access size. Read/write offset and size must be a multiple
|
||||
* of this. */
|
||||
uint32_t access_size;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Read persistent storage */
|
||||
#define EC_LPC_COMMAND_PSTORE_READ 0x41
|
||||
struct lpc_params_pstore_read {
|
||||
uint32_t offset; /* Byte offset to read */
|
||||
uint32_t size; /* Size to read in bytes */
|
||||
} __attribute__ ((packed));
|
||||
struct lpc_response_pstore_read {
|
||||
uint8_t data[EC_LPC_PSTORE_SIZE_MAX];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Write persistent storage */
|
||||
#define EC_LPC_COMMAND_PSTORE_WRITE 0x42
|
||||
struct lpc_params_pstore_write {
|
||||
uint32_t offset; /* Byte offset to write */
|
||||
uint32_t size; /* Size to write in bytes */
|
||||
uint8_t data[EC_LPC_PSTORE_SIZE_MAX];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#endif /* __CROS_EC_LPC_COMMANDS_H */
|
||||
|
||||
18
include/pstore_commands.h
Normal file
18
include/pstore_commands.h
Normal file
@@ -0,0 +1,18 @@
|
||||
/* Copyright (c) 2012 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.
|
||||
*/
|
||||
|
||||
/* Persistent storage commands for Chrome EC */
|
||||
|
||||
#ifndef __CROS_EC_PSTORE_COMMANDS_H
|
||||
#define __CROS_EC_PSTORE_COMMANDS_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/* Host command handlers. */
|
||||
enum lpc_status pstore_command_get_info(uint8_t *data);
|
||||
enum lpc_status pstore_command_read(uint8_t *data);
|
||||
enum lpc_status pstore_command_write(uint8_t *data);
|
||||
|
||||
#endif /* __CROS_EC_PSTORE_COMMANDS_H */
|
||||
248
util/ectool.c
248
util/ectool.c
@@ -28,6 +28,12 @@ const char help_str[] =
|
||||
" Erases EC flash\n"
|
||||
" hello\n"
|
||||
" Checks for basic communication with EC\n"
|
||||
" pstoreinfo\n"
|
||||
" Prints information on the EC host persistent storage\n"
|
||||
" pstoreread <offset> <size> <outfile>\n"
|
||||
" Reads from EC host persistent storage to a file\n"
|
||||
" pstorewrite <offset> <infile>\n"
|
||||
" Writes to EC host persistent storage from a file\n"
|
||||
" readtest <patternoffset> <size>\n"
|
||||
" Reads a pattern from the EC via LPC\n"
|
||||
" sertest\n"
|
||||
@@ -55,6 +61,72 @@ const char help_str[] =
|
||||
"";
|
||||
|
||||
|
||||
/* Write a buffer to the file. Return non-zero if error. */
|
||||
static int write_file(const char *filename, const char *buf, int size)
|
||||
{
|
||||
FILE *f;
|
||||
int i;
|
||||
|
||||
/* Write to file */
|
||||
f = fopen(filename, "wb");
|
||||
if (!f) {
|
||||
perror("Error opening output file");
|
||||
return -1;
|
||||
}
|
||||
i = fwrite(buf, 1, size, f);
|
||||
fclose(f);
|
||||
if (i != size) {
|
||||
perror("Error writing to file");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Read a file into a buffer. Sets *size to the size of the buffer. Returns
|
||||
* the buffer, which must be freed with free() by the caller. Returns NULL if
|
||||
* error. */
|
||||
static char *read_file(const char *filename, int *size)
|
||||
{
|
||||
FILE *f = fopen(filename, "rb");
|
||||
char *buf;
|
||||
int i;
|
||||
|
||||
if (!f) {
|
||||
perror("Error opening input file");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
*size = ftell(f);
|
||||
rewind(f);
|
||||
if (*size > 0x100000) {
|
||||
fprintf(stderr, "File seems unreasonably large\n");
|
||||
fclose(f);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buf = (char *)malloc(*size);
|
||||
if (!buf) {
|
||||
fprintf(stderr, "Unable to allocate buffer.\n");
|
||||
fclose(f);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
printf("Reading %d bytes from %s...\n", *size, filename);
|
||||
i = fread(buf, 1, *size, f);
|
||||
fclose(f);
|
||||
if (i != *size) {
|
||||
perror("Error reading file");
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
/* Waits for the EC to be unbusy. Returns 0 if unbusy, non-zero if
|
||||
* timeout. */
|
||||
int wait_for_ec(int status_addr, int timeout_usec)
|
||||
@@ -283,7 +355,6 @@ int cmd_flash_read(int argc, char *argv[])
|
||||
int i;
|
||||
char *e;
|
||||
char *buf;
|
||||
FILE *f;
|
||||
|
||||
if (argc < 3) {
|
||||
fprintf(stderr,
|
||||
@@ -322,20 +393,11 @@ int cmd_flash_read(int argc, char *argv[])
|
||||
memcpy(buf + i, r.data, p.size);
|
||||
}
|
||||
|
||||
/* Write to file */
|
||||
f = fopen(argv[2], "wb");
|
||||
if (!f) {
|
||||
perror("Error opening output file");
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
i = fwrite(buf, 1, size, f);
|
||||
fclose(f);
|
||||
rv = write_file(argv[2], buf, size);
|
||||
free(buf);
|
||||
if (i != size) {
|
||||
perror("Error writing to file");
|
||||
if (rv)
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("done.\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -349,7 +411,6 @@ int cmd_flash_write(int argc, char *argv[])
|
||||
int i;
|
||||
char *e;
|
||||
char *buf;
|
||||
FILE *f;
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "Usage: flashwrite <offset> <filename>\n");
|
||||
@@ -362,34 +423,9 @@ int cmd_flash_write(int argc, char *argv[])
|
||||
}
|
||||
|
||||
/* Read the input file */
|
||||
f = fopen(argv[1], "rb");
|
||||
if (!f) {
|
||||
perror("Error opening input file");
|
||||
buf = read_file(argv[1], &size);
|
||||
if (!buf)
|
||||
return -1;
|
||||
}
|
||||
fseek(f, 0, SEEK_END);
|
||||
size = ftell(f);
|
||||
rewind(f);
|
||||
if (size > 0x100000) {
|
||||
fprintf(stderr, "File seems unreasonably large\n");
|
||||
fclose(f);
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf = (char *)malloc(size);
|
||||
if (!buf) {
|
||||
fprintf(stderr, "Unable to allocate buffer.\n");
|
||||
fclose(f);
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("Reading %d bytes from %s...\n", size, argv[1]);
|
||||
i = fread(buf, 1, size, f);
|
||||
if (i != size) {
|
||||
perror("Error reading file");
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("Writing to offset %d...\n", offset);
|
||||
|
||||
@@ -460,6 +496,7 @@ int cmd_serial_test(int argc, char *argv[])
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int cmd_temperature(int argc, char *argv[])
|
||||
{
|
||||
int rv;
|
||||
@@ -493,6 +530,7 @@ int cmd_temperature(int argc, char *argv[])
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
int cmd_pwm_get_fan_rpm(void)
|
||||
{
|
||||
int rv;
|
||||
@@ -509,6 +547,7 @@ int cmd_pwm_get_fan_rpm(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int cmd_pwm_set_fan_rpm(int argc, char *argv[])
|
||||
{
|
||||
struct lpc_params_pwm_set_fan_target_rpm p;
|
||||
@@ -535,6 +574,7 @@ int cmd_pwm_set_fan_rpm(int argc, char *argv[])
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int cmd_pwm_get_keyboard_backlight(void)
|
||||
{
|
||||
struct lpc_response_pwm_get_keyboard_backlight r;
|
||||
@@ -550,6 +590,7 @@ int cmd_pwm_get_keyboard_backlight(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int cmd_pwm_set_keyboard_backlight(int argc, char *argv[])
|
||||
{
|
||||
struct lpc_params_pwm_set_keyboard_backlight p;
|
||||
@@ -576,6 +617,7 @@ int cmd_pwm_set_keyboard_backlight(int argc, char *argv[])
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int cmd_usb_charge_set_mode(int argc, char *argv[])
|
||||
{
|
||||
struct lpc_params_usb_charge_set_mode p;
|
||||
@@ -609,6 +651,124 @@ int cmd_usb_charge_set_mode(int argc, char *argv[])
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int cmd_pstore_info(void)
|
||||
{
|
||||
struct lpc_response_pstore_info r;
|
||||
int rv;
|
||||
|
||||
rv = ec_command(EC_LPC_COMMAND_PSTORE_INFO, NULL, 0, &r, sizeof(r));
|
||||
if (rv)
|
||||
return rv;
|
||||
|
||||
printf("PstoreSize %d\nAccessSize %d\n", r.pstore_size, r.access_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int cmd_pstore_read(int argc, char *argv[])
|
||||
{
|
||||
struct lpc_params_pstore_read p;
|
||||
struct lpc_response_pstore_read r;
|
||||
int offset, size;
|
||||
int rv;
|
||||
int i;
|
||||
char *e;
|
||||
char *buf;
|
||||
|
||||
if (argc < 3) {
|
||||
fprintf(stderr,
|
||||
"Usage: pstoreread <offset> <size> <filename>\n");
|
||||
return -1;
|
||||
}
|
||||
offset = strtol(argv[0], &e, 0);
|
||||
if ((e && *e) || offset < 0 || offset > 0x10000) {
|
||||
fprintf(stderr, "Bad offset.\n");
|
||||
return -1;
|
||||
}
|
||||
size = strtol(argv[1], &e, 0);
|
||||
if ((e && *e) || size <= 0 || size > 0x10000) {
|
||||
fprintf(stderr, "Bad size.\n");
|
||||
return -1;
|
||||
}
|
||||
printf("Reading %d bytes at offset %d...\n", size, offset);
|
||||
|
||||
buf = (char *)malloc(size);
|
||||
if (!buf) {
|
||||
fprintf(stderr, "Unable to allocate buffer.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Read data in chunks */
|
||||
for (i = 0; i < size; i += EC_LPC_PSTORE_SIZE_MAX) {
|
||||
p.offset = offset + i;
|
||||
p.size = MIN(size - i, EC_LPC_PSTORE_SIZE_MAX);
|
||||
rv = ec_command(EC_LPC_COMMAND_PSTORE_READ,
|
||||
&p, sizeof(p), &r, sizeof(r));
|
||||
if (rv) {
|
||||
fprintf(stderr, "Read error at offset %d\n", i);
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
memcpy(buf + i, r.data, p.size);
|
||||
}
|
||||
|
||||
rv = write_file(argv[2], buf, size);
|
||||
free(buf);
|
||||
if (rv)
|
||||
return -1;
|
||||
|
||||
printf("done.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int cmd_pstore_write(int argc, char *argv[])
|
||||
{
|
||||
struct lpc_params_pstore_write p;
|
||||
int offset, size;
|
||||
int rv;
|
||||
int i;
|
||||
char *e;
|
||||
char *buf;
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "Usage: pstorewrite <offset> <filename>\n");
|
||||
return -1;
|
||||
}
|
||||
offset = strtol(argv[0], &e, 0);
|
||||
if ((e && *e) || offset < 0 || offset > 0x10000) {
|
||||
fprintf(stderr, "Bad offset.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Read the input file */
|
||||
buf = read_file(argv[1], &size);
|
||||
if (!buf)
|
||||
return -1;
|
||||
|
||||
printf("Writing to offset %d...\n", offset);
|
||||
|
||||
/* Write data in chunks */
|
||||
for (i = 0; i < size; i += EC_LPC_PSTORE_SIZE_MAX) {
|
||||
p.offset = offset + i;
|
||||
p.size = MIN(size - i, EC_LPC_PSTORE_SIZE_MAX);
|
||||
memcpy(p.data, buf + i, p.size);
|
||||
rv = ec_command(EC_LPC_COMMAND_PSTORE_WRITE,
|
||||
&p, sizeof(p), NULL, 0);
|
||||
if (rv) {
|
||||
fprintf(stderr, "Write error at offset %d\n", i);
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
free(buf);
|
||||
printf("done.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc < 2 || !strcasecmp(argv[1], "-?") ||
|
||||
@@ -652,6 +812,12 @@ int main(int argc, char *argv[])
|
||||
return cmd_pwm_set_keyboard_backlight(argc - 2, argv + 2);
|
||||
if (!strcasecmp(argv[1], "usbchargemode"))
|
||||
return cmd_usb_charge_set_mode(argc - 2, argv + 2);
|
||||
if (!strcasecmp(argv[1], "pstoreinfo"))
|
||||
return cmd_pstore_info();
|
||||
if (!strcasecmp(argv[1], "pstoreread"))
|
||||
return cmd_pstore_read(argc - 2, argv + 2);
|
||||
if (!strcasecmp(argv[1], "pstorewrite"))
|
||||
return cmd_pstore_write(argc - 2, argv + 2);
|
||||
|
||||
/* If we're still here, command was unknown */
|
||||
fprintf(stderr, "Unknown command '%s'\n\n", argv[1]);
|
||||
|
||||
Reference in New Issue
Block a user