summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHung-Te Lin <hungte@chromium.org>2022-04-28 17:29:22 +0800
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-05-05 09:03:25 +0000
commit2f21f0f1928aa9e92fc9e69900eafaa9933f836c (patch)
tree70547010f493a53a3c119c90187141a27e58184a
parentc059f03ac296d9d439a87887e4dbd1e3494840d1 (diff)
downloadvboot-2f21f0f1928aa9e92fc9e69900eafaa9933f836c.tar.gz
futility: updater: create a manifest from the signer config
The signer_config.csv contains almost everything we need for mapping from models to image files so that can be an alternative when models/*/setvars.sh files are not available. This can be shared by /firmware in future. Verified by comparing the manifest.json from existing firmware updaters on the following boards: volteer (share target), sarien (no ec), octopus (custom-label), and hatch (share target). for BOARD in volteer sarien octopus hatch; do /build/$BOARD/usr/sbin/chromeos-firmwareupdate --unpack test/$BOARD jq -S . <test/$BOARD/manifest.json >old rm -rf test/$BOARD/models futility update --manifest -a test/$BOARD | jq -S . >new diff new old >diff.$BOARD done # all diff.$BOARD are empty, e.g., no difference. BUG=b:230679721 TEST=make; run test BRANCH=None Change-Id: I17393c941d2577a2b1c5f00f60b25e98fa3f3a6f Signed-off-by: Hung-Te Lin <hungte@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/3612646 Reviewed-by: Julius Werner <jwerner@chromium.org> Commit-Queue: Yu-Ping Wu <yupingso@chromium.org>
-rw-r--r--futility/updater_archive.c134
1 files changed, 128 insertions, 6 deletions
diff --git a/futility/updater_archive.c b/futility/updater_archive.c
index 58774fc4..4ed12aab 100644
--- a/futility/updater_archive.c
+++ b/futility/updater_archive.c
@@ -85,6 +85,7 @@ static const char * const SETVARS_IMAGE_MAIN = "IMAGE_MAIN",
* const VPD_CUSTOMIZATION_ID = "customization_id",
* const ENV_VAR_MODEL_DIR = "${MODEL_DIR}",
* const PATH_STARTSWITH_KEYSET = "keyset/",
+ * const PATH_SIGNER_CONFIG = "signer_config.csv",
* const PATH_ENDSWITH_SETVARS = "/setvars.sh";
struct archive {
@@ -571,7 +572,7 @@ static int model_config_parse_setvars_file(
uint8_t *data;
uint32_t len;
- char *ptr_line, *ptr_token;
+ char *ptr_line = NULL, *ptr_token = NULL;
char *line, *k, *v;
int valid = 0;
@@ -867,6 +868,118 @@ static int manifest_scan_raw_entries(const char *name, void *arg)
return !manifest_add_model(manifest, &model);
}
+/* Returns the matched model config from the manifest, or NULL if not found. */
+static struct model_config *manifest_get_model_config(
+ const struct manifest *manifest, const char *name)
+{
+ int i = 0;
+
+ for (i = 0; i < manifest->num; i++) {
+ if (!strcmp(name, manifest->models[i].name))
+ return &manifest->models[i];
+ }
+ return NULL;
+}
+
+/*
+ * Creates the manifest from the 'signer_config.csv' file.
+ * Returns 0 on success (loaded), otherwise failure.
+ */
+static int manifest_from_signer_config(struct manifest *manifest)
+{
+ struct archive *archive = manifest->archive;
+ uint32_t size;
+ uint8_t *data;
+ char *s, *tok_ptr = NULL;
+
+ if (!archive_has_entry(archive, PATH_SIGNER_CONFIG))
+ return -1;
+
+ /*
+ * CSV format: model_name,firmware_image,key_id,ec_image
+ *
+ * Note the key_id is not signature_id and won't be used, and ec_image
+ * may be optional (for example sarien).
+ */
+
+ if (archive_read_file(archive, PATH_SIGNER_CONFIG, &data, &size,NULL)) {
+ ERROR("Failed reading: %s\n", PATH_SIGNER_CONFIG);
+ return -1;
+ }
+
+ /* Skip headers. */
+ s = strtok_r((char *)data, "\n", &tok_ptr);
+ if (!s || !strchr(s, ',')) {
+ ERROR("Invalid %s: missing header.\n", PATH_SIGNER_CONFIG);
+ free(data);
+ return -1;
+ }
+
+ for (s = strtok_r(NULL, "\n", &tok_ptr); s != NULL;
+ s = strtok_r(NULL, "\n", &tok_ptr)) {
+
+ struct model_config model = {0};
+ int discard_model = 0;
+
+ /*
+ * Both keyid (%3) and ec_image (%4) are optional so we want to
+ * read at least 2 fields.
+ */
+ if (sscanf(s, "%m[^,],%m[^,],%*[^,],%m[^,]",
+ &model.name, &model.image, &model.ec_image) < 2) {
+ ERROR("Invalid entry(%s): %s\n", PATH_SIGNER_CONFIG, s);
+ discard_model = 1;
+ } else if (strchr(model.name, '-')) {
+ /* format: BaseModel-CustomLabel */
+ char *tok_dash;
+ char *base_model;
+ struct model_config *base_model_config;
+
+ VB2_DEBUG("Found custom-label: %s\n", model.name);
+ discard_model = 1;
+ base_model = strtok_r(model.name, "-", &tok_dash);
+ assert(base_model);
+
+ /*
+ * Currently we assume the base model (e.g., base_model)
+ * is always listed before CL models in the CSV file -
+ * this is based on how the signerbot and the
+ * chromeos-config works today (validated on octopus).
+ */
+ base_model_config = manifest_get_model_config(
+ manifest, base_model);
+
+ if (!base_model_config) {
+ ERROR("Invalid CL-model: %s\n", base_model);
+ } else if (!base_model_config->is_custom_label) {
+ base_model_config->is_custom_label = 1;
+ /*
+ * Rewriting signature_id is not necessary,
+ * but in order to generate the same manifest
+ * from setvars, we want to temporarily use
+ * the special value.
+ */
+ free(base_model_config->signature_id);
+ base_model_config->signature_id = strdup(
+ "sig-id-in-customization-id");
+ }
+ }
+
+ if (discard_model) {
+ free(model.name);
+ free(model.image);
+ free(model.ec_image);
+ continue;
+ }
+
+ model.signature_id = strdup(model.name);
+ if (!manifest_add_model(manifest, &model))
+ break;
+ }
+ free(data);
+ return 0;
+}
+
/**
* get_manifest_key() - Wrapper to get the firmware manifest key from crosid
*
@@ -927,10 +1040,8 @@ const struct model_config *manifest_find_model(const struct manifest *manifest,
model_name = manifest_key;
}
- for (i = 0; !model && i < manifest->num; i++) {
- if (strcmp(model_name, manifest->models[i].name) == 0)
- model = &manifest->models[i];
- }
+ model = manifest_get_model_config(manifest, model_name);
+
if (!model) {
ERROR("Unsupported model: '%s'.\n", model_name);
@@ -1054,14 +1165,25 @@ struct manifest *new_manifest_from_archive(struct archive *archive)
manifest.archive = archive;
manifest.default_model = -1;
+
+ VB2_DEBUG("Try to build a manifest from *%s\n", PATH_ENDSWITH_SETVARS);
archive_walk(archive, &manifest, manifest_scan_entries);
- if (manifest.num == 0)
+
+ if (manifest.num == 0) {
+ VB2_DEBUG("Try to build a manifest from %s\n",
+ PATH_SIGNER_CONFIG);
+ manifest_from_signer_config(&manifest);
+ }
+ if (manifest.num == 0) {
+ VB2_DEBUG("Try to build a manifest from a */firmware folder\n");
archive_walk(archive, &manifest, manifest_scan_raw_entries);
+ }
if (manifest.num == 0) {
const char *image_name = NULL;
struct firmware_image image = {0};
+ VB2_DEBUG("Try to build a manifest from a simple folder\n");
/* Try to load from current folder. */
if (archive_has_entry(archive, old_host_image_name))
image_name = old_host_image_name;