diff options
-rw-r--r-- | common/rollback.c | 33 |
1 files changed, 22 insertions, 11 deletions
diff --git a/common/rollback.c b/common/rollback.c index 1b2962fc5a..590c1224af 100644 --- a/common/rollback.c +++ b/common/rollback.c @@ -209,14 +209,25 @@ BUILD_ASSERT(SHA256_DIGEST_SIZE == CONFIG_ROLLBACK_SECRET_SIZE); static int rollback_update(int32_t next_min_version, uint8_t *entropy, unsigned int length) { - struct rollback_data data; + /* + * When doing flash_write operation, the data needs to be in blocks + * of CONFIG_FLASH_WRITE_SIZE, pad rollback_data as required. + */ + uint8_t block[CONFIG_FLASH_WRITE_SIZE * + DIV_ROUND_UP(sizeof(struct rollback_data), + CONFIG_FLASH_WRITE_SIZE)]; + struct rollback_data *data = (struct rollback_data *)block; + BUILD_ASSERT(sizeof(block) >= sizeof(*data)); uintptr_t offset; int region; if (flash_get_protect() & EC_FLASH_PROTECT_ROLLBACK_NOW) return EC_ERROR_ACCESS_DENIED; - region = get_latest_rollback(&data); + /* Initialize the rest of the block. */ + memset(&block[sizeof(*data)], 0xff, sizeof(block)-sizeof(*data)); + + region = get_latest_rollback(data); if (region < 0) return EC_ERROR_UNKNOWN; @@ -224,17 +235,17 @@ static int rollback_update(int32_t next_min_version, #ifdef CONFIG_ROLLBACK_SECRET_SIZE if (entropy) { /* Do not accept to decrease the value. */ - if (next_min_version < data.rollback_min_version) - next_min_version = data.rollback_min_version; + if (next_min_version < data->rollback_min_version) + next_min_version = data->rollback_min_version; } else #endif { /* Do not accept to decrease the value. */ - if (next_min_version < data.rollback_min_version) + if (next_min_version < data->rollback_min_version) return EC_ERROR_INVAL; /* No need to update if version is already correct. */ - if (next_min_version == data.rollback_min_version) + if (next_min_version == data->rollback_min_version) return EC_SUCCESS; } @@ -243,19 +254,19 @@ static int rollback_update(int32_t next_min_version, offset = get_rollback_offset(region); - data.id = data.id + 1; - data.rollback_min_version = next_min_version; + data->id = data->id + 1; + data->rollback_min_version = next_min_version; #ifdef CONFIG_ROLLBACK_SECRET_SIZE /* * If we are provided with some entropy, add it to secret. Otherwise, * data.secret is left untouched and written back to the other region. */ if (entropy) { - if (!add_entropy(data.secret, data.secret, entropy, length)) + if (!add_entropy(data->secret, data->secret, entropy, length)) return EC_ERROR_UNCHANGED; } #endif - data.cookie = CROS_EC_ROLLBACK_COOKIE; + data->cookie = CROS_EC_ROLLBACK_COOKIE; /* Offset should never be part of active image. */ if (system_unsafe_to_overwrite(offset, CONFIG_FLASH_ERASE_SIZE)) @@ -264,7 +275,7 @@ static int rollback_update(int32_t next_min_version, if (flash_erase(offset, CONFIG_FLASH_ERASE_SIZE)) return EC_ERROR_UNKNOWN; - if (flash_write(offset, sizeof(data), (char *)&data)) + if (flash_write(offset, sizeof(block), block)) return EC_ERROR_UNKNOWN; return EC_SUCCESS; |