summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--futility/cmd_update.c5
-rw-r--r--futility/updater.c58
-rw-r--r--futility/updater.h15
-rw-r--r--futility/updater_archive.c96
-rwxr-xr-xtests/futility/models/whitetip/setvars.sh21
-rwxr-xr-xtests/futility/test_update.sh47
6 files changed, 229 insertions, 13 deletions
diff --git a/futility/cmd_update.c b/futility/cmd_update.c
index ce81660d..2ba8a4e8 100644
--- a/futility/cmd_update.c
+++ b/futility/cmd_update.c
@@ -27,6 +27,7 @@ static struct option const long_opts[] = {
{"list-quirks", 0, NULL, 'L'},
{"mode", 1, NULL, 'm'},
{"model", 1, NULL, 'M'},
+ {"signature_id", 1, NULL, 'G'},
{"manifest", 0, NULL, 'A'},
{"factory", 0, NULL, 'Y'},
{"force", 0, NULL, 'F'},
@@ -66,6 +67,7 @@ static void print_help(int argc, char *argv[])
" --wp=1|0 \tSpecify write protection status\n"
" --emulate=FILE \tEmulate system firmware using file\n"
" --model=MODEL \tOverride system model for images\n"
+ " --signature_id=S\tOverride signature ID for key files\n"
" --sys_props=LIST\tList of system properties to override\n"
"-d, --debug \tPrint debugging messages\n"
"-v, --verbose \tPrint verbose messages\n"
@@ -113,6 +115,9 @@ static int do_update(int argc, char *argv[])
case 'M':
args.model = optarg;
break;
+ case 'G':
+ args.signature_id = optarg;
+ break;
case 'A':
args.do_manifest = 1;
break;
diff --git a/futility/updater.c b/futility/updater.c
index 17b12a2b..0d69641b 100644
--- a/futility/updater.c
+++ b/futility/updater.c
@@ -1668,13 +1668,49 @@ static int updater_load_images(struct updater_config *cfg,
}
/*
+ * Applies white label information to an existing model config.
+ * Returns 0 on success, otherwise failure.
+ */
+static int updater_apply_white_label(struct updater_config *cfg,
+ struct model_config *model,
+ const char *signature_id)
+{
+ const char *tmp_image = NULL;
+
+ assert(model->is_white_label);
+ if (!signature_id) {
+ if (cfg->image_current.data) {
+ tmp_image = updater_create_temp_file(cfg);
+ if (!tmp_image)
+ return 1;
+ if (vb2_write_file(tmp_image, cfg->image_current.data,
+ cfg->image_current.size)) {
+ ERROR("Failed writing temporary image file.");
+ return 1;
+ }
+ } else {
+ printf("Loading system firmware for white label..\n");
+ load_system_firmware(cfg, &cfg->image_current);
+ tmp_image = cfg->image_current.file_name;
+ }
+ if (!tmp_image) {
+ ERROR("Failed to get system current firmware");
+ return 1;
+ }
+ }
+ return !!model_apply_white_label(
+ model, cfg->archive, signature_id, tmp_image);
+}
+
+/*
* Setup what the updater has to do against an archive.
* Returns number of failures, or 0 on success.
*/
static int updater_setup_archive(
struct updater_config *cfg,
const struct updater_config_arguments *arg,
- struct manifest *manifest)
+ struct manifest *manifest,
+ int is_factory)
{
int errorcnt = 0;
struct archive *ar = cfg->archive;
@@ -1691,6 +1727,23 @@ static int updater_setup_archive(
if (!model)
return ++errorcnt;
+ if (model->is_white_label) {
+ /*
+ * It is fine to fail in updater_apply_white_label for factory
+ * mode so we are not checking the return value; instead we
+ * verify if the patches do contain new root key.
+ */
+ updater_apply_white_label(cfg, (struct model_config *)model,
+ arg->signature_id);
+ if (!model->patches.rootkey) {
+ if (!is_factory) {
+ ERROR("Need VPD set for white label.");
+ return ++errorcnt;
+ }
+ fprintf(stderr, "Warning: No VPD for white label.\n");
+ }
+ }
+
errorcnt += updater_load_images(
cfg, model->image, model->ec_image, model->pd_image);
errorcnt += patch_image_by_model(&cfg->image, model, ar);
@@ -1796,7 +1849,8 @@ int updater_setup_config(struct updater_config *cfg,
if (arg->archive) {
struct manifest *m = new_manifest_from_archive(cfg->archive);
if (m) {
- errorcnt += updater_setup_archive(cfg, arg, m);
+ errorcnt += updater_setup_archive(
+ cfg, arg, m, cfg->factory_update);
delete_manifest(m);
} else {
ERROR("Failure in archive: %s", arg->archive);
diff --git a/futility/updater.h b/futility/updater.h
index c1405663..ae6db16a 100644
--- a/futility/updater.h
+++ b/futility/updater.h
@@ -114,7 +114,7 @@ struct updater_config {
struct updater_config_arguments {
char *image, *ec_image, *pd_image;
char *archive, *quirks, *mode;
- char *programmer, *model;
+ char *programmer, *model, *signature_id;
char *emulation, *sys_props, *write_protection;
int is_factory, try_update, force_update, do_manifest;
int verbosity;
@@ -131,6 +131,7 @@ struct model_config {
char *image, *ec_image, *pd_image;
struct patch_config patches;
char *signature_id;
+ int is_white_label;
};
struct manifest {
@@ -324,4 +325,16 @@ int patch_image_by_model(
const struct model_config *manifest_find_model(const struct manifest *manifest,
const char *model_name);
+/*
+ * Applies white label information to an existing model configuration.
+ * Collects signature ID information from either parameter signature_id or
+ * image file (via VPD) and updates model.patches for key files.
+ * Returns 0 on success, otherwise failure.
+ */
+int model_apply_white_label(
+ struct model_config *model,
+ struct archive *archive,
+ const char *signature_id,
+ const char *image);
+
#endif /* VBOOT_REFERENCE_FUTILITY_UPDATER_H_ */
diff --git a/futility/updater_archive.c b/futility/updater_archive.c
index e08f736a..7ce210f3 100644
--- a/futility/updater_archive.c
+++ b/futility/updater_archive.c
@@ -65,6 +65,8 @@ static const char * const SETVARS_IMAGE_MAIN = "IMAGE_MAIN",
* const DIR_KEYSET = "keyset",
* const DIR_MODELS = "models",
* const DEFAULT_MODEL_NAME = "default",
+ * const VPD_WHITELABEL_TAG = "whitelabel_tag",
+ * const VPD_CUSTOMIZATION_ID = "customization_id",
* const ENV_VAR_MODEL_DIR = "${MODEL_DIR}",
* const PATH_STARTSWITH_KEYSET = "keyset/",
* const PATH_ENDSWITH_SERVARS = "/setvars.sh";
@@ -365,16 +367,16 @@ int archive_read_file(struct archive *ar, const char *fname,
* -- End of archive implementations --
*/
-/* Utility function to convert a string to all lowercase. */
-static void str_tolower(char *s)
+/* Utility function to convert a string. */
+static void str_convert(char *s, int (*convert)(int c))
{
int c;
for (; *s; s++) {
c = *s;
- if (!isascii(c) || !isalpha(c))
+ if (!isascii(c))
continue;
- *s = tolower(c);
+ *s = convert(c);
}
}
@@ -393,6 +395,23 @@ static int str_startswith(const char *name, const char *pattern)
return strncmp(name, pattern, strlen(pattern)) == 0;
}
+/* Returns the VPD value by given key name, or NULL on error (or no value). */
+static char *vpd_get_value(const char *fpath, const char *key)
+{
+ char *command, *result;
+
+ assert(fpath);
+ ASPRINTF(&command, "vpd -g %s -f %s 2>/dev/null", key, fpath);
+ result = host_shell(command);
+ free(command);
+
+ if (result && !*result) {
+ free(result);
+ result = NULL;
+ }
+ return result;
+}
+
/*
* Reads and parses a setvars type file from archive, then stores into config.
* Returns 0 on success (at least one entry found), otherwise failure.
@@ -442,9 +461,11 @@ static int model_config_parse_setvars_file(
cfg->ec_image = strdup(v);
else if (strcmp(k, SETVARS_IMAGE_PD) == 0)
cfg->pd_image = strdup(v);
- else if (strcmp(k, SETVARS_SIGNATURE_ID) == 0)
+ else if (strcmp(k, SETVARS_SIGNATURE_ID) == 0) {
cfg->signature_id = strdup(v);
- else
+ if (str_startswith(v, SIG_ID_IN_VPD_PREFIX))
+ cfg->is_white_label = 1;
+ } else
found_valid = 0;
free(expand_path);
valid += found_valid;
@@ -690,6 +711,65 @@ const struct model_config *manifest_find_model(const struct manifest *manifest,
}
/*
+ * Applies white label information to an existing model configuration.
+ * Collects signature ID information from either parameter signature_id or
+ * image file (via VPD) and updates model.patches for key files.
+ * Returns 0 on success, otherwise failure.
+ */
+int model_apply_white_label(
+ struct model_config *model,
+ struct archive *archive,
+ const char *signature_id,
+ const char *image)
+{
+ char *sig_id = NULL;
+ int r = 0;
+
+ if (!signature_id) {
+ int remove_dash = 0, prefix_model = model->signature_id ? 1 : 0;
+ char *wl_tag = vpd_get_value(image, VPD_WHITELABEL_TAG);
+
+ if (!wl_tag) {
+ if (model->signature_id)
+ return -1;
+ wl_tag = vpd_get_value(image, VPD_CUSTOMIZATION_ID);
+ /* customization_id in format LOEM[-VARIANT]. */
+ remove_dash = 1;
+
+ }
+ if (!wl_tag)
+ return 1;
+
+ if (remove_dash) {
+ char *dash = strchr(wl_tag, '-');
+ if (dash)
+ *dash = '\0';
+ }
+ if (!prefix_model)
+ str_convert(wl_tag, toupper);
+
+ sig_id = wl_tag;
+ if (prefix_model)
+ ASPRINTF(&sig_id, "%s-%s", model->name, wl_tag);
+ else
+ wl_tag = NULL;
+ free(wl_tag);
+ signature_id = sig_id;
+ }
+
+ DEBUG("Find white label patches by signature ID: '%s'.", signature_id);
+ find_patches_for_model(model, archive, signature_id);
+ if (!model->patches.rootkey) {
+ ERROR("No keys found for signature_id: '%s'", signature_id);
+ r = 1;
+ } else {
+ printf("Applied for white label: %s\n", signature_id);
+ }
+ free(sig_id);
+ return r;
+}
+
+/*
* Creates a new manifest object by scanning files in archive.
* Returns the manifest on success, otherwise NULL for failure.
*/
@@ -720,13 +800,15 @@ struct manifest *new_manifest_from_archive(struct archive *archive)
if (strtok(image.ro_version, "_"))
token = strtok(NULL, ".");
if (token && *token) {
- str_tolower(token);
+ str_convert(token, tolower);
model.name = strdup(token);
}
free_firmware_image(&image);
}
if (!model.name)
model.name = strdup(DEFAULT_MODEL_NAME);
+ if (manifest.has_keyset)
+ model.is_white_label = 1;
manifest_add_model(&manifest, &model);
manifest.default_model = manifest.num - 1;
}
diff --git a/tests/futility/models/whitetip/setvars.sh b/tests/futility/models/whitetip/setvars.sh
new file mode 100755
index 00000000..4b9cb406
--- /dev/null
+++ b/tests/futility/models/whitetip/setvars.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+# Copyright 2017 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.
+
+# This is a template file which provides settings for firmware update of a
+# particular model. The pack_firmware.py script uses this to create a working
+# setvars-model.sh script.
+
+# Version information for model whitetip
+TARGET_RO_FWID="Google_Coral.10068.45.0"
+TARGET_FWID="Google_Coral.10068.45.0"
+TARGET_ECID="coral_v1.1.7272-0b44fba22"
+TARGET_PDID=""
+TARGET_PLATFORM="Google_Coral"
+
+# Image and key files for model whitetip
+IMAGE_MAIN="images/bios_coral.bin"
+IMAGE_EC=""
+IMAGE_PD=""
+SIGNATURE_ID="sig-id-in-customization-id"
diff --git a/tests/futility/test_update.sh b/tests/futility/test_update.sh
index 32fe921e..215f9918 100755
--- a/tests/futility/test_update.sh
+++ b/tests/futility/test_update.sh
@@ -296,7 +296,10 @@ test_update "Full update (--quirks min_platform_version)" \
# Test archive and manifest.
A="${TMP}.archive"
-mkdir -p "${A}"
+mkdir -p "${A}/bin"
+echo 'echo "${WL_TAG}"' >"${A}/bin/vpd"
+chmod +x "${A}/bin/vpd"
+
cp -f "${LINK_BIOS}" "${A}/bios.bin"
echo "TEST: Manifest (--manifest)"
${FUTILITY} update -a "${A}" --manifest >"${TMP}.json.out"
@@ -307,12 +310,41 @@ test_update "Full update (--archive, single package)" \
"${FROM_IMAGE}" "${TMP}.expected.full" \
-a "${A}" --wp=0 --sys_props 0,0x10001,1,3
-rm -f "${A}/bios.bin"
+mkdir -p "${A}/keyset"
+cp -f "${LINK_BIOS}" "${A}/bios.bin"
+cp -f "${TMP}.to/rootkey" "${A}/keyset/rootkey.WL"
+cp -f "${TMP}.to/VBLOCK_A" "${A}/keyset/vblock_A.WL"
+cp -f "${TMP}.to/VBLOCK_B" "${A}/keyset/vblock_B.WL"
+${FUTILITY} gbb -s --rootkey="${TMP}.from/rootkey" "${A}/bios.bin"
+${FUTILITY} load_fmap "${A}/bios.bin" VBLOCK_A:"${TMP}.from/VBLOCK_A"
+${FUTILITY} load_fmap "${A}/bios.bin" VBLOCK_B:"${TMP}.from/VBLOCK_B"
+
+test_update "Full update (--archive, whitelabel, no VPD)" \
+ "${A}/bios.bin" "!Need VPD set for white" \
+ -a "${A}" --wp=0 --sys_props 0,0x10001,1,3
+
+test_update "Full update (--archive, whitelabel, no VPD - factory mode)" \
+ "${LINK_BIOS}" "${A}/bios.bin" \
+ -a "${A}" --wp=0 --sys_props 0,0x10001,1,3 --mode=factory
+
+test_update "Full update (--archive, WL, single package)" \
+ "${A}/bios.bin" "${LINK_BIOS}" \
+ -a "${A}" --wp=0 --sys_props 0,0x10001,1,3 --signature_id=WL
+
+WL_TAG="WL" PATH="${A}/bin:${PATH}" \
+ test_update "Full update (--archive, WL, fake vpd)" \
+ "${A}/bios.bin" "${LINK_BIOS}" \
+ -a "${A}" --wp=0 --sys_props 0,0x10001,1,3
+
+# Test archive with Unified Build contents.
cp -r "${SCRIPTDIR}/models" "${A}/"
mkdir -p "${A}/images"
+mv "${A}/bios.bin" "${A}/images/bios_coral.bin"
cp -f "${PEPPY_BIOS}" "${A}/images/bios_peppy.bin"
cp -f "${LINK_BIOS}" "${A}/images/bios_link.bin"
-
+cp -f "${TMP}.to/rootkey" "${A}/keyset/rootkey.whitetip-wl"
+cp -f "${TMP}.to/VBLOCK_A" "${A}/keyset/vblock_A.whitetip-wl"
+cp -f "${TMP}.to/VBLOCK_B" "${A}/keyset/vblock_B.whitetip-wl"
cp -f "${PEPPY_BIOS}" "${FROM_IMAGE}.ap"
cp -f "${LINK_BIOS}" "${FROM_IMAGE}.al"
patch_file ${FROM_IMAGE}.ap FW_MAIN_A 0 "corrupted"
@@ -326,6 +358,15 @@ test_update "Full update (--archive, model=peppy)" \
test_update "Full update (--archive, model=unknown)" \
"${FROM_IMAGE}.ap" "!Model 'unknown' is not defined" \
-a "${A}" --wp=0 --sys_props 0,0x10001,1,3 --model=unknown
+test_update "Full update (--archive, model=whitetip, signature_id=WL)" \
+ "${FROM_IMAGE}.al" "${LINK_BIOS}" \
+ -a "${A}" --wp=0 --sys_props 0,0x10001,1,3 --model=whitetip \
+ --signature_id=whitetip-wl
+
+WL_TAG="wl" PATH="${A}/bin:${PATH}" \
+ test_update "Full update (-a, model=WL, fake VPD)" \
+ "${FROM_IMAGE}.al" "${LINK_BIOS}" \
+ -a "${A}" --wp=0 --sys_props 0,0x10001,1,3 --model=whitetip
# Test special programmer
if type flashrom >/dev/null 2>&1; then