summaryrefslogtreecommitdiff
path: root/util/ec_sb_firmware_update.c
diff options
context:
space:
mode:
authorJack Rosenthal <jrosenth@chromium.org>2021-11-04 12:11:58 -0600
committerCommit Bot <commit-bot@chromium.org>2021-11-05 04:22:34 +0000
commit252457d4b21f46889eebad61d4c0a65331919cec (patch)
tree01856c4d31d710b20e85a74c8d7b5836e35c3b98 /util/ec_sb_firmware_update.c
parent08f5a1e6fc2c9467230444ac9b582dcf4d9f0068 (diff)
downloadchrome-ec-stabilize-quickfix-14695.187.B-ish.tar.gz
In the interest of making long-term branch maintenance incur as little technical debt on us as possible, we should not maintain any files on the branch we are not actually using. This has the added effect of making it extremely clear when merging CLs from the main branch when changes have the possibility to affect us. The follow-on CL adds a convenience script to actually pull updates from the main branch and generate a CL for the update. BUG=b:204206272 BRANCH=ish TEST=make BOARD=arcada_ish && make BOARD=drallion_ish Signed-off-by: Jack Rosenthal <jrosenth@chromium.org> Change-Id: I17e4694c38219b5a0823e0a3e55a28d1348f4b18 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3262038 Reviewed-by: Jett Rink <jettrink@chromium.org> Reviewed-by: Tom Hughes <tomhughes@chromium.org>
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);
-}