summaryrefslogtreecommitdiff
path: root/util/ec_sb_firmware_update.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/ec_sb_firmware_update.c')
-rw-r--r--util/ec_sb_firmware_update.c846
1 files changed, 0 insertions, 846 deletions
diff --git a/util/ec_sb_firmware_update.c b/util/ec_sb_firmware_update.c
deleted file mode 100644
index a959cd6fe9..0000000000
--- a/util/ec_sb_firmware_update.c
+++ /dev/null
@@ -1,846 +0,0 @@
-/* Copyright 2014 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 <unistd.h>
-
-#include "comm-host.h"
-#include "compile_time_macros.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,
-};
-
-struct delay_value {
- uint32_t steps;
- uint32_t value;
-};
-
-/* Default retry counter on errors */
-#define SB_FW_UPDATE_DEFAULT_RETRY_CNT 3
-/* Default delay value */
-#define SB_FW_UPDATE_DEFAULT_DELAY 1000
-
-#define DELAY_US_BEGIN 500000
-#define DELAY_US_END 1000000
-#define DELAY_US_BUSY 1000000
-#define DELAY_US_WRITE_END 50000
-
-static struct delay_value sb_delays[] = {
- {1, 100000},
- {2, 9000000},
- {4, 100000},
- {771, 30000},
- {2200, 10000},
- {0xFFFFFF, 50000},
-};
-
-enum fw_update_state {
- S0_READ_STATUS = 0,
- S1_READ_INFO = 1,
- S2_WRITE_PREPARE = 2,
- S3_READ_STATUS = 3,
- S4_WRITE_UPDATE = 4,
- S5_READ_STATUS = 5,
- S6_WRITE_BLOCK = 6,
- S7_READ_STATUS = 7,
- S8_WRITE_END = 8,
- S9_READ_STATUS = 9,
- S10_TERMINAL = 10
-};
-
-#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 */
- F_LFCC_ZERO = 0x20, /* last full charge is zero */
- F_BATT_DISCHARGE = 0x40 /* battery discharging */
-};
-
-struct fw_update_ctrl {
- uint32_t flags; /* fw update control flags */
- int size; /* size of battery firmware image */
- char *ptr; /* current read pointer of the firmware image */
- int offset; /* current block write offset */
- struct sb_fw_header *fw_img_hdr; /*pointer to firmware image header*/
- struct sb_fw_update_status status;
- struct sb_fw_update_info info;
- int err_retry_cnt;
- int fec_err_retry_cnt;
- int busy_retry_cnt;
- int step_size;
- int rv;
- char image_name[MAX_FW_IMAGE_NAME_SIZE];
- char msg[256];
-};
-
-/*
- * Global Firmware Update Control Data Structure
- */
-static struct fw_update_ctrl fw_update;
-
-static uint32_t get_delay_value(uint32_t offset, uint32_t step_size)
-{
- int sz = ARRAY_SIZE(sb_delays);
- int i;
- for (i = 0; i < sz; i++) {
- if (offset <= sb_delays[i].steps * step_size)
- return sb_delays[i].value;
- }
- return sb_delays[sz-1].value;
-}
-
-static void print_battery_firmware_image_hdr(
- struct sb_fw_header *hdr)
-{
- printf("Latest Battery Firmware:\n");
- printf("\t%c%c%c%c hdr_ver:%04x major_minor:%04x\n",
- hdr->signature[0],
- hdr->signature[1],
- hdr->signature[2],
- hdr->signature[3],
- hdr->hdr_version, hdr->pkg_version_major_minor);
-
- printf("\tmaker:0x%04x hwid:0x%04x fw_ver:0x%04x tbl_ver:0x%04x\n",
- hdr->vendor_id, hdr->battery_type, hdr->fw_version,
- hdr->data_table_version);
-
- printf("\tbinary offset:0x%08x size:0x%08x chk_sum:0x%02x\n",
- hdr->fw_binary_offset, hdr->fw_binary_size, hdr->checksum);
-}
-
-static void print_info(struct sb_fw_update_info *info)
-{
- printf("\nCurrent Battery Firmware:\n");
- printf("\tmaker:0x%04x hwid:0x%04x fw_ver:0x%04x tbl_ver:0x%04x\n",
- info->maker_id,
- info->hardware_id,
- info->fw_version,
- info->data_version);
- return;
-}
-
-static void print_status(struct sb_fw_update_status *sts)
-{
- printf("f_maker_id:%d f_hw_id:%d f_fw_ver:%d f_permnent:%d\n",
- sts->v_fail_maker_id,
- sts->v_fail_hw_id,
- sts->v_fail_fw_version,
- sts->v_fail_permanent);
- printf("permanent failure:%d abnormal:%d fw_update:%d\n",
- sts->permanent_failure,
- sts->abnormal_condition,
- sts->fw_update_supported);
- printf("fw_update_mode:%d fw_corrupted:%d cmd_reject:%d\n",
- sts->fw_update_mode,
- sts->fw_corrupted,
- sts->cmd_reject);
- printf("invliad data:%d fw_fatal_err:%d fec_err:%d busy:%d\n",
- sts->invalid_data,
- sts->fw_fatal_error,
- sts->fec_error,
- sts->busy);
- printf("\n");
- return;
-}
-
-/* @return 1 (True) if img signature is valid */
-static int check_battery_firmware_image_signature(
- struct sb_fw_header *hdr)
-{
- return (hdr->signature[0] == 'B') &&
- (hdr->signature[1] == 'T') &&
- (hdr->signature[2] == 'F') &&
- (hdr->signature[3] == 'W');
-}
-
-/* @return 1 (True) if img checksum is valid. */
-static int check_battery_firmware_image_checksum(
- struct sb_fw_header *hdr)
-{
- int i;
- uint8_t sum = 0;
- uint8_t *img = (uint8_t *)hdr;
-
- img += hdr->fw_binary_offset;
- for (i = 0; i < hdr->fw_binary_size; i++)
- sum += img[i];
- sum += hdr->checksum;
- return sum == 0;
-}
-
-/* @return 1 (True) if img versions are ok to update. */
-static int check_battery_firmware_image_version(
- struct sb_fw_header *hdr,
- struct sb_fw_update_info *p)
-{
- /*
- * If the battery firmware has a newer fw version
- * or a newer data table version, then it is ok to update.
- */
- return (hdr->fw_version > p->fw_version)
- || (hdr->data_table_version > p->data_version);
-}
-
-
-static int check_battery_firmware_ids(
- struct sb_fw_header *hdr,
- struct sb_fw_update_info *p)
-{
- return ((hdr->vendor_id == p->maker_id) &&
- (hdr->battery_type == p->hardware_id));
-}
-
-/* check_if_need_update_fw
- * @return 1 (true) if need; 0 (false) if not.
- */
-static int check_if_valid_fw(
- struct sb_fw_header *hdr,
- struct sb_fw_update_info *info)
-{
- return check_battery_firmware_image_signature(hdr)
- && check_battery_firmware_ids(hdr, info)
- && check_battery_firmware_image_checksum(hdr);
-}
-
-/* check_if_need_update_fw
- * @return 1 (true) if need; 0 (false) if not.
- */
-static int check_if_need_update_fw(
- struct sb_fw_header *hdr,
- struct sb_fw_update_info *info)
-{
- return check_battery_firmware_image_version(hdr, info);
-}
-
-static void log_msg(struct fw_update_ctrl *fw_update,
- enum fw_update_state state, const char *msg)
-{
- sprintf(fw_update->msg,
- "Battery Firmware Updater State:%d %s", state, msg);
-}
-
-
-static char *read_fw_image(struct fw_update_ctrl *fw_update)
-{
- int size;
- char *buf;
- fw_update->size = 0;
- fw_update->ptr = NULL;
- fw_update->fw_img_hdr = (struct sb_fw_header *)NULL;
-
- /* Read the input file */
- buf = read_file(fw_update->image_name, &size);
- if (!buf)
- return NULL;
-
- fw_update->size = size;
- fw_update->ptr = buf;
- fw_update->fw_img_hdr = (struct sb_fw_header *)buf;
- print_battery_firmware_image_hdr(fw_update->fw_img_hdr);
-
- if (fw_update->fw_img_hdr->fw_binary_offset >= fw_update->size ||
- fw_update->size < 256) {
- printf("Load Firmware Image[%s] Error offset:%d size:%d\n",
- fw_update->image_name,
- fw_update->fw_img_hdr->fw_binary_offset,
- fw_update->size);
- free(buf);
- return NULL;
- }
- return buf;
-}
-
-static int get_status(struct sb_fw_update_status *status)
-{
- int rv = EC_RES_SUCCESS;
- int cnt = 0;
-
- struct ec_params_sb_fw_update *param =
- (struct ec_params_sb_fw_update *)ec_outbuf;
-
- struct ec_response_sb_fw_update *resp =
- (struct ec_response_sb_fw_update *)ec_inbuf;
-
- param->hdr.subcmd = EC_SB_FW_UPDATE_STATUS;
- do {
- usleep(SB_FW_UPDATE_DEFAULT_DELAY);
- rv = ec_command(EC_CMD_SB_FW_UPDATE, 0,
- param, sizeof(struct ec_sb_fw_update_header),
- resp, SB_FW_UPDATE_CMD_STATUS_SIZE);
- } while ((rv < 0) && (cnt++ < SB_FW_UPDATE_DEFAULT_RETRY_CNT));
-
- if (rv < 0) {
- memset(status, 0, SB_FW_UPDATE_CMD_STATUS_SIZE);
- return -EC_RES_ERROR;
- }
-
- memcpy(status, resp->status.data, SB_FW_UPDATE_CMD_STATUS_SIZE);
- return EC_RES_SUCCESS;
-}
-
-static int get_info(struct sb_fw_update_info *info)
-{
- int rv = EC_RES_SUCCESS;
- int cnt = 0;
-
- struct ec_params_sb_fw_update *param =
- (struct ec_params_sb_fw_update *)ec_outbuf;
-
- struct ec_response_sb_fw_update *resp =
- (struct ec_response_sb_fw_update *)ec_inbuf;
-
- param->hdr.subcmd = EC_SB_FW_UPDATE_INFO;
- do {
- usleep(SB_FW_UPDATE_DEFAULT_DELAY);
- rv = ec_command(EC_CMD_SB_FW_UPDATE, 0,
- param, sizeof(struct ec_sb_fw_update_header),
- resp, SB_FW_UPDATE_CMD_INFO_SIZE);
- } while ((rv < 0) && (cnt++ < SB_FW_UPDATE_DEFAULT_RETRY_CNT));
-
- if (rv < 0) {
- memset(info, 0, SB_FW_UPDATE_CMD_INFO_SIZE);
- return -EC_RES_ERROR;
- }
-
- memcpy(info, resp->info.data, SB_FW_UPDATE_CMD_INFO_SIZE);
- return EC_RES_SUCCESS;
-}
-
-static int send_subcmd(int subcmd)
-{
- int rv = EC_RES_SUCCESS;
-
- struct ec_params_sb_fw_update *param =
- (struct ec_params_sb_fw_update *)ec_outbuf;
-
- param->hdr.subcmd = subcmd;
- rv = ec_command(EC_CMD_SB_FW_UPDATE, 0,
- param, sizeof(struct ec_sb_fw_update_header), NULL, 0);
- if (rv < 0) {
- printf("Firmware Update subcmd:%d Error\n", subcmd);
- return -EC_RES_ERROR;
- }
- return EC_RES_SUCCESS;
-}
-
-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, 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 ptr:%p offset@%x\n",
- fw_update->ptr, offset);
- return -EC_RES_ERROR;
- }
- return EC_RES_SUCCESS;
-}
-
-static void dump_data(char *data, int offset, int size)
-{
- int i = 0;
-
- if (data == NULL)
- return;
-
- printf("Offset:0x%X\n", offset);
- for (i = 0; i < size; i++) {
- if ((i%16) == 0)
- printf("\n");
- printf("%02X ", data[i]);
- }
- printf("\n");
-}
-
-static enum fw_update_state s0_read_status(struct fw_update_ctrl *fw_update)
-{
- if (fw_update->busy_retry_cnt == 0) {
- fw_update->rv = -1;
- log_msg(fw_update, S0_READ_STATUS, "Busy");
- return S10_TERMINAL;
- }
-
- fw_update->busy_retry_cnt--;
-
- fw_update->rv = get_status(&fw_update->status);
- if (fw_update->rv) {
- fw_update->rv = -1;
- log_msg(fw_update, S0_READ_STATUS, "Interface Error");
- return S10_TERMINAL;
- }
-
- if (!((fw_update->status.abnormal_condition == 0)
- && (fw_update->status.fw_update_supported == 1))) {
- return S0_READ_STATUS;
- }
-
- if (fw_update->status.busy) {
- usleep(DELAY_US_BUSY);
- return S0_READ_STATUS;
- } else
- return S1_READ_INFO;
-}
-
-static enum fw_update_state s1_read_battery_info(
- struct fw_update_ctrl *fw_update)
-{
- int rv;
-
- if (fw_update->err_retry_cnt == 0) {
- fw_update->rv = -1;
- log_msg(fw_update, S1_READ_INFO, "Retry Error");
- return S10_TERMINAL;
- }
-
- fw_update->err_retry_cnt--;
-
- rv = get_info(&fw_update->info);
- if (rv) {
- fw_update->rv = -1;
- log_msg(fw_update, S1_READ_INFO, "Interface Error");
- return S10_TERMINAL;
- }
- print_info(&fw_update->info);
-
- sprintf(fw_update->image_name,
- "/lib/firmware/battery/maker.%04x.hwid.%04x.bin",
- fw_update->info.maker_id,
- fw_update->info.hardware_id);
-
- if (NULL == read_fw_image(fw_update)) {
- fw_update->rv = 0;
- log_msg(fw_update, S1_READ_INFO, "Open Image File");
- return S10_TERMINAL;
- }
-
- rv = get_status(&fw_update->status);
- if (rv) {
- fw_update->rv = -1;
- log_msg(fw_update, S1_READ_INFO, "Interface Error");
- return S10_TERMINAL;
- }
-
- rv = check_if_valid_fw(fw_update->fw_img_hdr, &fw_update->info);
- if (rv == 0) {
- fw_update->rv = -EC_RES_INVALID_PARAM;
- log_msg(fw_update, S1_READ_INFO, "Invalid Firmware");
- return S10_TERMINAL;
- }
-
- rv = check_if_need_update_fw(fw_update->fw_img_hdr, &fw_update->info);
- if (rv == 0 && (fw_update->flags & F_VERSION_CHECK)) {
- fw_update->rv = 0;
- log_msg(fw_update, S1_READ_INFO, "Latest Firmware");
- 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,
- "Require AC Adapter Connected.");
- return S10_TERMINAL;
- }
-
- if ((fw_update->flags & F_BATT_DISCHARGE) &&
- (fw_update->flags & F_AC_PRESENT)) {
- /*
- * If battery discharge due to battery learning mode,
- * we can't update battery FW, because device will shutdown
- * during FW update.
- */
- fw_update->rv = 0;
- log_msg(fw_update, S1_READ_INFO,
- "battery can't update in learning mode");
- return S10_TERMINAL;
- }
-
- return S2_WRITE_PREPARE;
-}
-
-static enum fw_update_state s2_write_prepare(struct fw_update_ctrl *fw_update)
-{
- int rv;
-
- rv = disable_power_management();
- if (0 == rv)
- fw_update->flags |= F_POWERD_DISABLED;
-
- rv = send_subcmd(EC_SB_FW_UPDATE_PREPARE);
- if (rv) {
- fw_update->rv = -1;
- log_msg(fw_update, S2_WRITE_PREPARE, "Interface Error");
- return S10_TERMINAL;
- }
- return S3_READ_STATUS;
-}
-
-static enum fw_update_state s3_read_status(struct fw_update_ctrl *fw_update)
-{
- int rv;
-
- rv = get_status(&fw_update->status);
- if (rv) {
- fw_update->rv = -1;
- log_msg(fw_update, S3_READ_STATUS, "Interface Error");
- return S10_TERMINAL;
- }
- return S4_WRITE_UPDATE;
-
-}
-
-static enum fw_update_state s4_write_update(struct fw_update_ctrl *fw_update)
-{
- int rv;
-
- rv = send_subcmd(EC_SB_FW_UPDATE_BEGIN);
- if (rv) {
- fw_update->rv = -1;
- log_msg(fw_update, S4_WRITE_UPDATE, "Interface Error");
- return S10_TERMINAL;
- }
- usleep(DELAY_US_BEGIN);
- return S5_READ_STATUS;
-}
-
-static enum fw_update_state s5_read_status(struct fw_update_ctrl *fw_update)
-{
- int rv = get_status(&fw_update->status);
-
- if (rv) {
- fw_update->rv = -1;
- log_msg(fw_update, S5_READ_STATUS, "Interface Error");
- return S10_TERMINAL;
- }
- if (fw_update->status.fw_update_mode == 0)
- return S2_WRITE_PREPARE;
-
- /* Init Write Block Loop Controls */
- fw_update->ptr += fw_update->fw_img_hdr->fw_binary_offset;
- fw_update->size -= fw_update->fw_img_hdr->fw_binary_offset;
- fw_update->offset = 0;
-
- return S6_WRITE_BLOCK;
-}
-
-static enum fw_update_state s6_write_block(struct fw_update_ctrl *fw_update)
-{
- int rv;
- int bsize;
- int offset = fw_update->offset;
-
- if (offset >= fw_update->size)
- return S8_WRITE_END;
-
- bsize = fw_update->step_size;
-
- if ((offset & 0xFFFF) == 0x0)
- printf("\n%X\n", offset);
-
- if (fw_update->fec_err_retry_cnt == 0) {
- fw_update->rv = -1;
- log_msg(fw_update, S6_WRITE_BLOCK, "FEC Retry Error");
- return S10_TERMINAL;
- }
- fw_update->fec_err_retry_cnt--;
-
- 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;
- }
-
- /*
- * Add more delays after the last few (3) block writes.
- * 3 is chosen based on current test results.
- */
- if ((offset + 3*fw_update->step_size) >= fw_update->size)
- usleep(DELAY_US_WRITE_END);
-
- usleep(get_delay_value(offset, fw_update->step_size));
-
- return S7_READ_STATUS;
-}
-
-static enum fw_update_state s7_read_status(struct fw_update_ctrl *fw_update)
-{
- int rv;
- int offset = fw_update->offset;
- int bsize;
- int cnt = 0;
-
- bsize = fw_update->step_size;
- do {
- usleep(SB_FW_UPDATE_DEFAULT_DELAY);
- rv = get_status(&fw_update->status);
- if (rv) {
- dump_data(fw_update->ptr+offset, offset, bsize);
- print_status(&fw_update->status);
- fw_update->rv = -1;
- log_msg(fw_update, S7_READ_STATUS, "Interface Error");
- return S10_TERMINAL;
- }
- } while (fw_update->status.busy &&
- (cnt++ < SB_FW_UPDATE_DEFAULT_RETRY_CNT));
-
- if (fw_update->status.fec_error) {
- dump_data(fw_update->ptr+offset, offset, bsize);
- print_status(&fw_update->status);
- fw_update->rv = 0;
- return S6_WRITE_BLOCK;
- }
- if (fw_update->status.permanent_failure ||
- fw_update->status.v_fail_permanent) {
- dump_data(fw_update->ptr+offset, offset, bsize);
- print_status(&fw_update->status);
- fw_update->rv = -1;
- log_msg(fw_update, S7_READ_STATUS, "Battery Permanent Error");
- return S8_WRITE_END;
- }
- if (fw_update->status.v_fail_maker_id ||
- fw_update->status.v_fail_hw_id ||
- fw_update->status.v_fail_fw_version ||
- fw_update->status.fw_corrupted ||
- fw_update->status.cmd_reject ||
- fw_update->status.invalid_data ||
- fw_update->status.fw_fatal_error) {
-
- dump_data(fw_update->ptr+offset, offset, bsize);
- print_status(&fw_update->status);
- fw_update->rv = 0;
- return S1_READ_INFO;
- }
-
- fw_update->fec_err_retry_cnt = SB_FW_UPDATE_FEC_ERROR_RETRY_CNT;
- fw_update->offset += fw_update->step_size;
- return S6_WRITE_BLOCK;
-}
-
-
-static enum fw_update_state s8_write_end(struct fw_update_ctrl *fw_update)
-{
- int rv;
-
- rv = send_subcmd(EC_SB_FW_UPDATE_END);
- if (rv && (0 == fw_update->rv)) {
- fw_update->rv = -1;
- log_msg(fw_update, S8_WRITE_END, "Interface Error");
- }
-
- if (fw_update->rv)
- return S10_TERMINAL;
-
- usleep(DELAY_US_END);
- fw_update->busy_retry_cnt = SB_FW_UPDATE_BUSY_ERROR_RETRY_CNT;
- return S9_READ_STATUS;
-}
-
-static enum fw_update_state s9_read_status(struct fw_update_ctrl *fw_update)
-{
- int rv;
-
- if (fw_update->busy_retry_cnt == 0) {
- fw_update->rv = -1;
- log_msg(fw_update, S9_READ_STATUS, "Busy");
- return S10_TERMINAL;
- }
-
- rv = get_status(&fw_update->status);
- if (rv) {
- fw_update->rv = -1;
- log_msg(fw_update, S9_READ_STATUS, "Interface Error");
- return S10_TERMINAL;
- }
- if ((fw_update->status.fw_update_mode == 1)
- || (fw_update->status.busy == 1)) {
- usleep(SB_FW_UPDATE_DEFAULT_DELAY);
- fw_update->busy_retry_cnt--;
- return S9_READ_STATUS;
- }
- log_msg(fw_update, S9_READ_STATUS, "Complete");
- fw_update->flags &= ~F_NEED_UPDATE;
- return S10_TERMINAL;
-}
-
-
-typedef enum fw_update_state (*fw_state_func)(struct fw_update_ctrl *fw_update);
-
-fw_state_func state_table[] = {
- s0_read_status,
- s1_read_battery_info,
- s2_write_prepare,
- s3_read_status,
- s4_write_update,
- s5_read_status,
- s6_write_block,
- s7_read_status,
- s8_write_end,
- s9_read_status
-};
-
-
-/**
- * Update Smart Battery Firmware
- *
- * @param fw_update struct fw_update_ctrl
- *
- * @return 0 if success, negative if error.
- */
-static int ec_sb_firmware_update(struct fw_update_ctrl *fw_update)
-{
- enum fw_update_state state;
-
- fw_update->err_retry_cnt = SB_FW_UPDATE_ERROR_RETRY_CNT;
- fw_update->fec_err_retry_cnt = SB_FW_UPDATE_FEC_ERROR_RETRY_CNT;
- fw_update->busy_retry_cnt = SB_FW_UPDATE_BUSY_ERROR_RETRY_CNT;
- fw_update->step_size = SB_FW_UPDATE_CMD_WRITE_BLOCK_SIZE;
-
- state = S0_READ_STATUS;
- while (state != S10_TERMINAL)
- state = state_table[state](fw_update);
-
- if (fw_update->fw_img_hdr)
- free(fw_update->fw_img_hdr);
-
- return fw_update->rv;
-}
-
-#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;
- int op = OP_UNKNOWN;
- uint8_t val = 0;
-
- if (argc != 2) {
- usage(argv);
- return -1;
- }
-
- 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 (comm_init_dev(NULL)) {
- printf("Couldn't initialize /dev.\n");
- return -1;
- }
-
- if (comm_init_buffer()) {
- fprintf(stderr, "Couldn't initialize buffers\n");
- return -1;
- }
-
- fw_update.flags = 0;
- rv = ec_readmem(EC_MEMMAP_BATT_FLAG, sizeof(val), &val);
- if (rv <= 0) {
- printf("EC Memmap read error:%d\n", rv);
- goto out;
- }
-
- rv = get_status(&fw_update.status);
- if (rv) {
- fw_update.rv = -1;
- log_msg(&fw_update, S1_READ_INFO, "Interface Error");
- return S10_TERMINAL;
- }
-
- if (fw_update.status.fw_update_mode) {
- /*
- * Previous battery firmware update was interrupted,
- * and we may not detect the presence of AC correctly.
- * Therefore, lie about our AC status.
- */
- fw_update.flags |= F_AC_PRESENT;
- printf("Assuming AC_PRESENT due to interrupted FW update\n");
- } else {
- if (val & EC_BATT_FLAG_AC_PRESENT) {
- fw_update.flags |= F_AC_PRESENT;
- printf("AC_PRESENT\n");
- }
- }
-
- if (val & EC_BATT_FLAG_DISCHARGING) {
- fw_update.flags |= F_BATT_DISCHARGE;
- printf("Battery is in discharge state\n");
- }
- rv = ec_readmem(EC_MEMMAP_BATT_LFCC, sizeof(val), &val);
- if (rv <= 0) {
- printf("EC Memmap read error:%d\n", rv);
- goto out;
- }
- if (val == 0)
- fw_update.flags |= F_LFCC_ZERO;
-
- if (op == OP_UPDATE)
- fw_update.flags |= F_UPDATE;
-
- fw_update.flags |= F_VERSION_CHECK;
-
- rv = ec_sb_firmware_update(&fw_update);
- printf("Battery Firmware Update:0x%02x %s\n%s\n",
- fw_update.flags,
- ((rv) ? "FAIL " : " "),
- fw_update.msg);
-
- /* Update battery firmware update interface to be protected */
- if (!(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:
- if (rv)
- return -1;
- else
- return fw_update.flags & (F_LFCC_ZERO | F_NEED_UPDATE);
-}