sb_firmware: update arguments and configs

- Updated arguments to support two sub commands:
   - check: check if AC adapter is connect.
   - update: trigger battery firmware update.

- All Delay values are from .cfg file.

BUG=chrome-os-partner:36310
BRANCH=none
CQ-DEPEND=CL:260868
TEST=Verified on Glimmer.
crosh> battery_firmware check
crosh> battery_firmware update

Change-Id: I7324e1f329383cf5ee62660f4ac4cb0b1c30c056
Signed-off-by: Sheng-Liang Song <ssl@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/260210
Reviewed-by: Shawn N <shawnn@chromium.org>
This commit is contained in:
Sheng-Liang Song
2015-03-15 21:51:18 -07:00
committed by ChromeOS Commit Bot
parent be42949a4f
commit bf931b2cce

View File

@@ -8,34 +8,43 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lock/gec_lock.h"
#include "comm-host.h"
#include "misc_util.h"
#include "ec_sb_firmware_update.h"
#include "ec_commands.h"
#include <unistd.h>
#include "comm-host.h"
#include "ec_sb_firmware_update.h"
#include "ec_commands.h"
#include "lock/gec_lock.h"
#include "misc_util.h"
#include "powerd_lock.h"
/* Subcommands: [check|update] */
enum {
OP_UNKNOWN = 0,
OP_CHECK = 1,
OP_UPDATE = 2,
};
#define SETUP_DELAY_STEPS 11
#define WRITE_DELAY_STEPS (SETUP_DELAY_STEPS+512)
/* Delay Configure Indexes */
enum {
BEGIN_DELAY = 0,
SETUP_DELAY = 1,
WRITE_DELAY = 2,
END_DELAY = 3,
NUM_DELAYS = 4
};
enum {
F_AC_PRESENT = 1,/* AC Present */
F_VERSION_CHECK = 2 /* do firmware version check */
WRITE1_DELAY = 2,
WRITE2_DELAY = 3,
END_DELAY = 4,
NUM_DELAYS = 5
};
const char *delay_names[NUM_DELAYS] = {
"BEGIN",
"SETUP",
"WRITE",
"END"
[BEGIN_DELAY] = "BEGIN",
[SETUP_DELAY] = "SETUP",
[WRITE1_DELAY] = "WRITE1",
[WRITE2_DELAY] = "WRITE2",
[END_DELAY] = "END"
};
uint32_t delay_values[NUM_DELAYS];
static uint32_t delay_values[NUM_DELAYS];
enum fw_update_state {
S0_READ_STATUS = 0,
@@ -52,6 +61,16 @@ enum fw_update_state {
};
#define MAX_FW_IMAGE_NAME_SIZE 80
/* Firmware Update Control Flags */
enum {
F_AC_PRESENT = 0x1, /* AC Present */
F_VERSION_CHECK = 0x2, /* do firmware version check */
F_UPDATE = 0x4, /* do firmware update */
F_NEED_UPDATE = 0x8, /* need firmware update */
F_POWERD_DISABLED = 0x10 /* powerd is disabled */
};
struct fw_update_ctrl {
uint32_t flags; /* fw update control flags */
int size; /* size of battery firmware image */
@@ -82,11 +101,6 @@ static int get_key_value(const char *filename,
int i = BEGIN_DELAY;
FILE *fp = fopen(filename, "r");
values[BEGIN_DELAY] = 500000;
values[SETUP_DELAY] = 9000000;
values[WRITE_DELAY] = 500000;
values[END_DELAY] = 1000000;
if (fp == NULL)
return -1;
@@ -95,7 +109,8 @@ static int get_key_value(const char *filename,
continue;
sprintf(cmd, "%s=%%d", keys[i]);
sscanf(line, cmd, &values[i]);
if (0 == values[i])
sscanf(line, cmd, &values[i]);
if (++i == NUM_DELAYS)
break;
@@ -328,19 +343,21 @@ static int send_subcmd(int subcmd)
return EC_RES_SUCCESS;
}
static int write_block(const uint8_t *ptr, int bsize)
static int write_block(struct fw_update_ctrl *fw_update,
int offset, int bsize)
{
int rv;
struct ec_params_sb_fw_update *param =
(struct ec_params_sb_fw_update *)ec_outbuf;
memcpy(param->write.data, ptr, bsize);
memcpy(param->write.data, fw_update->ptr+offset, bsize);
param->hdr.subcmd = EC_SB_FW_UPDATE_WRITE;
rv = ec_command(EC_CMD_SB_FW_UPDATE, 0,
param, sizeof(struct ec_params_sb_fw_update), NULL, 0);
if (rv < 0) {
printf("Firmware Update Write Error offset@%p\n", ptr);
printf("Firmware Update Write Error ptr:%p offset@%x\n",
fw_update->ptr, offset);
return -EC_RES_ERROR;
}
return EC_RES_SUCCESS;
@@ -438,7 +455,7 @@ static enum fw_update_state s1_read_battery_info(
rv = check_if_valid_fw(fw_update->fw_img_hdr, &fw_update->info);
if (rv == 0) {
fw_update->rv = EC_RES_INVALID_PARAM;
fw_update->rv = -EC_RES_INVALID_PARAM;
log_msg(fw_update, S1_READ_INFO, "Invalid Firmware");
return S10_TERMINAL;
}
@@ -450,6 +467,13 @@ static enum fw_update_state s1_read_battery_info(
return S10_TERMINAL;
}
fw_update->flags |= F_NEED_UPDATE;
if (!(fw_update->flags & F_UPDATE)) {
fw_update->rv = 0;
return S10_TERMINAL;
}
if (!(fw_update->flags & F_AC_PRESENT)) {
fw_update->rv = 0;
log_msg(fw_update, S1_READ_INFO,
@@ -462,6 +486,14 @@ static enum fw_update_state s1_read_battery_info(
static enum fw_update_state s2_write_prepare(struct fw_update_ctrl *fw_update)
{
int rv;
rv = disable_power_management();
if (rv) {
fw_update->rv = -1;
log_msg(fw_update, S2_WRITE_PREPARE,
"disable power management error");
return S10_TERMINAL;
}
fw_update->flags |= F_POWERD_DISABLED;
rv = send_subcmd(EC_SB_FW_UPDATE_PREPARE);
if (rv) {
fw_update->rv = -1;
@@ -537,17 +569,19 @@ static enum fw_update_state s6_write_block(struct fw_update_ctrl *fw_update)
}
fw_update->fec_err_retry_cnt--;
rv = write_block(fw_update->ptr+offset, bsize);
rv = write_block(fw_update, offset, bsize);
if (rv) {
fw_update->rv = -1;
log_msg(fw_update, S6_WRITE_BLOCK, "Interface Error");
return S10_TERMINAL;
}
if (offset <= fw_update->step_size * 10)
if (offset < (fw_update->step_size * SETUP_DELAY_STEPS))
usleep(delay_values[SETUP_DELAY]);
else if (offset < (fw_update->step_size * WRITE_DELAY_STEPS))
usleep(delay_values[WRITE1_DELAY]);
else
usleep(delay_values[WRITE_DELAY]);
usleep(delay_values[WRITE2_DELAY]);
return S7_READ_STATUS;
}
@@ -635,6 +669,7 @@ static enum fw_update_state s9_read_status(struct fw_update_ctrl *fw_update)
return S9_READ_STATUS;
}
log_msg(fw_update, S9_READ_STATUS, "Complete");
fw_update->flags &= ~F_NEED_UPDATE;
return S10_TERMINAL;
}
@@ -682,26 +717,37 @@ static int ec_sb_firmware_update(struct fw_update_ctrl *fw_update)
}
#define GEC_LOCK_TIMEOUT_SECS 30 /* 30 secs */
void usage(char *argv[])
{
printf("Usage: %s [check|update]\n"
" check: check if AC Adaptor is connected.\n"
" update: trigger battery firmware update.\n",
argv[0]);
}
int main(int argc, char *argv[])
{
int rv = 0, interfaces = COMM_LPC;
int op = OP_UNKNOWN;
uint8_t val = 0;
/* local test flags */
int protect = 1;
int version_check = 1;
uint8_t val = 0;
if (argc > 3) {
printf("Usage: %s [protect] [version_check]\n"
" protect: 0 or 1, default 1\n"
" version_check: 0 or 1, default 1\n",
argv[0]);
if (argc != 2) {
usage(argv);
return -1;
}
if (argc >= 2)
protect = atoi(argv[1]);
if (argc >= 3)
version_check = atoi(argv[2]);
if (!strcmp(argv[1], "check"))
op = OP_CHECK;
else if (!strcmp(argv[1], "update"))
op = OP_UPDATE;
else {
op = OP_UNKNOWN;
usage(argv);
return -1;
}
if (acquire_gec_lock(GEC_LOCK_TIMEOUT_SECS) < 0) {
printf("Could not acquire GEC lock.\n");
@@ -720,23 +766,38 @@ int main(int argc, char *argv[])
goto out;
}
if (val & EC_BATT_FLAG_AC_PRESENT) {
fw_update.flags |= F_AC_PRESENT;
printf("AC_PRESENT\n");
}
if (op == OP_UPDATE)
fw_update.flags |= F_UPDATE;
if (version_check)
fw_update.flags |= F_VERSION_CHECK;
if (val & EC_BATT_FLAG_AC_PRESENT)
fw_update.flags |= F_AC_PRESENT;
rv = ec_sb_firmware_update(&fw_update);
printf("Battery Firmware Update:0x%02x %s%s\n",
printf("Battery Firmware Update:0x%02x (%d %d %d %d %d) %s\n%s\n",
fw_update.flags,
delay_values[BEGIN_DELAY],
delay_values[SETUP_DELAY],
delay_values[WRITE1_DELAY],
delay_values[WRITE2_DELAY],
delay_values[END_DELAY],
((rv) ? "FAIL " : " "),
fw_update.msg);
/* Update battery firmware update interface to be protected */
if (protect)
if (protect && !(fw_update.flags & F_NEED_UPDATE))
rv |= send_subcmd(EC_SB_FW_UPDATE_PROTECT);
if (fw_update.flags & F_POWERD_DISABLED)
rv |= restore_power_management();
out:
release_gec_lock();
return rv;
if (rv)
return -1;
else
return fw_update.flags & F_NEED_UPDATE;
}