summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMary Ruthven <mruthven@chromium.org>2022-09-22 16:36:05 -0500
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-11-02 23:46:57 +0000
commit26600812484d8baf5b713c33147cdf747bd1d0e4 (patch)
tree0ae255b6003b0c33ccf56c656ad475380a6fb457
parentef3613e4a73f2df56cf653527ae03f7b8bceb7f4 (diff)
downloadchrome-ec-26600812484d8baf5b713c33147cdf747bd1d0e4.tar.gz
apro: refactor writing AP RO check data
We'll need to reuse this code. Move it to its own function. BUG=b:236844541 TEST=erase the hash, write it, and trigger verification. Make sure ap_ro_info looks ok after reboot. Change-Id: If49fff3ad7e56d8685e08b480301e439fa715241 Signed-off-by: Mary Ruthven <mruthven@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3914999 Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
-rw-r--r--common/ap_ro_integrity_check.c101
1 files changed, 75 insertions, 26 deletions
diff --git a/common/ap_ro_integrity_check.c b/common/ap_ro_integrity_check.c
index d038c320c5..17abeacf70 100644
--- a/common/ap_ro_integrity_check.c
+++ b/common/ap_ro_integrity_check.c
@@ -258,6 +258,72 @@ static int ap_ro_erase_hash(void)
return rv;
}
+/**
+ * Write data to the AP RO data space of H1 flash.
+ *
+ * @param version the payload version
+ * @param type payload type
+ * @param num_ranges number of ranges in the AP RO payload.
+ * @param data_offset offset to write AP RO data to. It must be in the AP RO
+ * flash region.
+ * @param p_data pointer to the saved data. This is used to make sure the
+ * region is empty.
+ * @param buf data to write to AP RO flash.
+ * @param input_size the amount of data to write.
+ *
+ * @return ARCVE_OK on success, ARCVE_ALREADY_PROGRAMMED if there's already
+ * data stored in the region, or ARCVE_FLASH_WRITE_FAILED if writing
+ * flash failed..
+ */
+static enum ap_ro_check_vc_errors write_ap_ro_check_data(uint8_t version,
+ uint8_t type,
+ uint16_t num_ranges,
+ uint32_t data_offset,
+ uint32_t *p_data,
+ void *buf,
+ size_t input_size)
+{
+ uint32_t i;
+ struct ap_ro_check_header check_header;
+ int rv;
+ size_t prog_size = sizeof(struct ap_ro_check_header) + input_size;
+
+ /* Verify the ap ro data will fit in the ap ro data flash */
+ if ((data_offset < h1_flash_offset_) ||
+ ((data_offset + prog_size) >
+ (h1_flash_offset_ + AP_RO_DATA_SPACE_SIZE)))
+ return ARCVE_BAD_PAYLOAD_SIZE;
+
+ /*
+ * If prog_size isn't divisible by 4, then the remaining bytes won't get
+ * checked. The payload should be divisible by 4. Reject the data if it
+ * isn't.
+ */
+ if (prog_size % sizeof(uint32_t))
+ return ARCVE_BAD_PAYLOAD_SIZE;
+ /* Verify the entire data region is erased. */
+ for (i = 0; i < (prog_size / sizeof(uint32_t)); i++)
+ if (p_data[i] != ~0)
+ return ARCVE_ALREADY_PROGRAMMED;
+
+ check_header.version = version;
+ check_header.type = type;
+ check_header.num_ranges = num_ranges;
+ app_compute_hash(buf, input_size, &check_header.checksum,
+ sizeof(check_header.checksum));
+
+ flash_open_ro_window(data_offset, prog_size);
+ rv = flash_physical_write(data_offset, sizeof(check_header),
+ (char *)&check_header);
+ if (rv == EC_SUCCESS)
+ rv = flash_physical_write(data_offset + sizeof(check_header),
+ input_size, buf);
+ flash_close_ro_window();
+ if (rv != EC_SUCCESS)
+ return ARCVE_FLASH_WRITE_FAILED;
+ return ARCVE_OK;
+}
+
/*
* Leaving this function available for testing, will not be necessary in prod
* signed images.
@@ -266,12 +332,10 @@ static enum vendor_cmd_rc vc_seed_ap_ro_check(enum vendor_cmd_cc code,
void *buf, size_t input_size,
size_t *response_size)
{
- struct ap_ro_check_header check_header;
const struct ap_ro_check_payload *vc_payload = buf;
uint32_t vc_num_of_ranges;
uint32_t i;
uint8_t *response = buf;
- size_t prog_size;
int rv;
*response_size = 1; /* Just in case there is an error. */
@@ -341,30 +405,15 @@ static enum vendor_cmd_rc vc_seed_ap_ro_check(enum vendor_cmd_cc code,
}
}
- prog_size = sizeof(struct ap_ro_check_header) + input_size;
- for (i = 0; i < (prog_size / sizeof(uint32_t)); i++)
- if (((uint32_t *)p_chk)[i] != ~0) {
- *response = ARCVE_ALREADY_PROGRAMMED;
- return VENDOR_RC_NOT_ALLOWED;
- }
-
- check_header.version = AP_RO_HASH_LAYOUT_VERSION_1;
- check_header.type = AP_RO_HASH_TYPE_FACTORY;
- check_header.num_ranges = vc_num_of_ranges;
- app_compute_hash(buf, input_size, &check_header.checksum,
- sizeof(check_header.checksum));
-
- flash_open_ro_window(h1_flash_offset_, prog_size);
- rv = flash_physical_write(h1_flash_offset_, sizeof(check_header),
- (char *)&check_header);
- if (rv == EC_SUCCESS)
- rv = flash_physical_write(h1_flash_offset_ +
- sizeof(check_header),
- input_size, buf);
- flash_close_ro_window();
-
- if (rv != EC_SUCCESS) {
- *response = ARCVE_FLASH_WRITE_FAILED;
+ rv = write_ap_ro_check_data(AP_RO_HASH_LAYOUT_VERSION_1,
+ AP_RO_HASH_TYPE_FACTORY,
+ vc_num_of_ranges,
+ h1_flash_offset_,
+ (uint32_t *)p_chk,
+ buf,
+ input_size);
+ if (rv != ARCVE_OK) {
+ *response = rv;
return VENDOR_RC_WRITE_FLASH_FAIL;
}