/* 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 #include #include #include #include #include #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(¤t); 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(¤t); 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; }