Files
OpenCellular/util/burn_my_ec.c
Randall Spangler 177dc398d3 Allow bigger flash write commands
Version 1 of EC_CMD_FLASH_WRITE will use as big a write as possible given
the available command parameter space.  Falls back to 64 byte writes on old
platforms.

BUG=chrome-os-partner:20571
BRANCH=none
TEST=Copy burn_my_ec onto a link and run it.  Write size should be 64 bytes
     for the first half of the update (since the old EC doesn't support ver.1
     of the write command) and 240 bytes for the second half of the update.

Change-Id: I5900de3a5700d7c82a2e0c3cf9921b7ced1c0343
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/60511
2013-07-01 16:14:16 -07:00

143 lines
3.7 KiB
C

/* 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 <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/param.h>
#include <unistd.h>
#include "comm-host.h"
#include "ec_flash.h"
#define STR0(name) #name
#define STR(name) STR0(name)
static const char * const part_name[] = {"unknown", "RO", "RW"};
enum ec_current_image get_version(enum ec_current_image *version_ptr)
{
struct ec_response_get_version r;
char *build_info = (char *)ec_inbuf;
int res;
res = ec_command(EC_CMD_GET_VERSION, 0, NULL, 0, &r, sizeof(r));
if (res < 0)
return res;
res = ec_command(EC_CMD_GET_BUILD_INFO, 0, NULL, 0,
ec_inbuf, ec_max_insize);
if (res < 0)
return res;
/* Ensure versions are null-terminated before we print them */
r.version_string_ro[sizeof(r.version_string_ro) - 1] = '\0';
r.version_string_rw[sizeof(r.version_string_rw) - 1] = '\0';
build_info[ec_max_insize - 1] = '\0';
/* Print versions */
printf("RO version: %s\n", r.version_string_ro);
printf("RW version: %s\n", r.version_string_rw);
printf("Firmware copy: %s\n",
(r.current_image < sizeof(part_name)/sizeof(part_name[0]) ?
part_name[r.current_image] : "?"));
printf("Build info: %s\n", build_info);
if (version_ptr)
*version_ptr = r.current_image;
return 0;
}
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;
int res;
enum ec_current_image current = EC_IMAGE_UNKNOWN;
res = get_version(&current);
if (res < 0) {
fprintf(stderr, "Get version failed : %d\n", res);
return -1;
}
if (current == part) {
printf("Jumping EC to %s partition\n",
part == EC_IMAGE_RO ? "RW" : "RO");
rst_req.cmd = part == EC_IMAGE_RO ?
EC_REBOOT_JUMP_RW : EC_REBOOT_JUMP_RO;
ec_command(EC_CMD_REBOOT_EC, 0, &rst_req, sizeof(rst_req),
NULL, 0);
/*
* Wait for EC to reboot; this may take a while if EC is
* flushing large amounts of debug output.
*/
usleep(2000000);
/* Check partition */
res = get_version(&current);
if (res < 0) {
fprintf(stderr, "Get version failed : %d\n", res);
return -1;
}
if (current == part) {
fprintf(stderr, "Jump failed!\n");
return -1;
}
}
printf("Erasing partition %s : 0x%x bytes at 0x%08x\n",
part_name[part], size, offset);
res = ec_flash_erase(offset, size);
if (res < 0) {
fprintf(stderr, "Erase failed : %d\n", res);
return -1;
}
printf("Writing partition %s : 0x%x bytes at 0x%08x\n",
part_name[part], size, offset);
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);
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);
}
/* black magic to include the EC firmware binary as a payload inside
* the flashing program without relying on external tools such as objcopy or a
* binary to header converter. */
__asm__ (".section .payload, \"ax\"\n"
"_payload_start:\n"
".incbin \""STR(OUTDIR)"/"STR(PROJECT)".bin\"\n");
int main(int argc, char *argv[])
{
extern uint8_t data[] asm("_payload_start");
if (comm_init() < 0)
return -3;
flash_partition(EC_IMAGE_RW, data + CONFIG_FW_RW_OFF,
CONFIG_FW_RW_OFF, CONFIG_FW_RW_SIZE);
flash_partition(EC_IMAGE_RO, data + CONFIG_FW_RO_OFF,
CONFIG_FW_RO_OFF, CONFIG_FW_RO_SIZE);
return 0;
}