/** * Perform a flash read or write command * * @param dev CROS-EC device to read/write * @param is_write 1 do to a write, 0 to do a read * @param argc Number of arguments * @param argv Arguments (2 is region, 3 is address) * @return 0 for ok, 1 for a usage error or -ve for ec command error * (negative EC_RES_...) */ static int do_read_write(struct cros_ec_dev *dev, int is_write, int argc, char * const argv[]) { uint32_t offset, size = -1U, region_size; unsigned long addr; char *endp; int region; int ret; region = cros_ec_decode_region(argc - 2, argv + 2); if (region == -1) return 1; if (argc < 4) return 1; addr = simple_strtoul(argv[3], &endp, 16); if (*argv[3] == 0 || *endp != 0) return 1; if (argc > 4) { size = simple_strtoul(argv[4], &endp, 16); if (*argv[4] == 0 || *endp != 0) return 1; } ret = cros_ec_flash_offset(dev, region, &offset, ®ion_size); if (ret) { debug("%s: Could not read region info\n", __func__); return ret; } if (size == -1U) size = region_size; ret = is_write ? cros_ec_flash_write(dev, (uint8_t *)addr, offset, size) : cros_ec_flash_read(dev, (uint8_t *)addr, offset, size); if (ret) { debug("%s: Could not %s region\n", __func__, is_write ? "write" : "read"); return ret; } return 0; }
int cros_ec_flash_update_rw(struct udevice *dev, const uint8_t *image, int image_size) { uint32_t rw_offset, rw_size; int ret; if (cros_ec_flash_offset(dev, EC_FLASH_REGION_ACTIVE, &rw_offset, &rw_size)) return -1; if (image_size > (int)rw_size) return -1; /* Invalidate the existing hash, just in case the AP reboots * unexpectedly during the update. If that happened, the EC RW firmware * would be invalid, but the EC would still have the original hash. */ ret = cros_ec_invalidate_hash(dev); if (ret) return ret; /* * Erase the entire RW section, so that the EC doesn't see any garbage * past the new image if it's smaller than the current image. * * TODO: could optimize this to erase just the current image, since * presumably everything past that is 0xff's. But would still need to * round up to the nearest multiple of erase size. */ ret = cros_ec_flash_erase(dev, rw_offset, rw_size); if (ret) return ret; /* Write the image */ ret = cros_ec_flash_write(dev, image, rw_offset, image_size); if (ret) return ret; return 0; }