summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--futility/updater.c212
-rw-r--r--futility/updater.h117
-rw-r--r--futility/updater_quirks.c147
4 files changed, 275 insertions, 202 deletions
diff --git a/Makefile b/Makefile
index da62e04b..b717c3bd 100644
--- a/Makefile
+++ b/Makefile
@@ -688,6 +688,7 @@ FUTIL_SRCS = \
futility/misc.c \
futility/ryu_root_header.c \
futility/updater.c \
+ futility/updater_quirks.c \
futility/vb1_helper.c \
futility/vb2_helper.c
diff --git a/futility/updater.c b/futility/updater.c
index 113ffc59..df706485 100644
--- a/futility/updater.c
+++ b/futility/updater.c
@@ -15,7 +15,6 @@
#include "2rsa.h"
#include "crossystem.h"
-#include "fmap.h"
#include "host_misc.h"
#include "updater.h"
#include "utility.h"
@@ -27,27 +26,6 @@
#define RETURN_ON_FAILURE(x) do {int r = (x); if (r) return r;} while (0);
#define FLASHROM_OUTPUT_WP_PATTERN "write protect is "
-/* FMAP section names. */
-static const char * const FMAP_RO_FRID = "RO_FRID",
- * const FMAP_RO_SECTION = "RO_SECTION",
- * const FMAP_RO_GBB = "GBB",
- * const FMAP_RO_PRESERVE = "RO_PRESERVE",
- * const FMAP_RO_VPD = "RO_VPD",
- * const FMAP_RW_VPD = "RW_VPD",
- * const FMAP_RW_VBLOCK_A = "VBLOCK_A",
- * const FMAP_RW_SECTION_A = "RW_SECTION_A",
- * const FMAP_RW_SECTION_B = "RW_SECTION_B",
- * const FMAP_RW_FWID = "RW_FWID",
- * const FMAP_RW_FWID_A = "RW_FWID_A",
- * const FMAP_RW_FWID_B = "RW_FWID_B",
- * const FMAP_RW_SHARED = "RW_SHARED",
- * const FMAP_RW_NVRAM = "RW_NVRAM",
- * const FMAP_RW_ELOG = "RW_ELOG",
- * const FMAP_RW_PRESERVE = "RW_PRESERVE",
- * const FMAP_RW_LEGACY = "RW_LEGACY",
- * const FMAP_SI_DESC = "SI_DESC",
- * const FMAP_SI_ME = "SI_ME";
-
/* System environment values. */
static const char * const FWACT_A = "A",
* const FWACT_B = "B",
@@ -84,75 +62,13 @@ enum flashrom_ops {
FLASHROM_WP_STATUS,
};
-struct firmware_image {
- const char *programmer;
- uint32_t size;
- uint8_t *data;
- char *file_name;
- char *ro_version, *rw_version_a, *rw_version_b;
- FmapHeader *fmap_header;
-};
-
-struct firmware_section {
- uint8_t *data;
- size_t size;
-};
-
-struct system_property {
- int (*getter)();
- int value;
- int initialized;
-};
-
-enum system_property_type {
- SYS_PROP_MAINFW_ACT,
- SYS_PROP_TPM_FWVER,
- SYS_PROP_FW_VBOOT2,
- SYS_PROP_PLATFORM_VER,
- SYS_PROP_WP_HW,
- SYS_PROP_WP_SW,
- SYS_PROP_MAX
-};
-
-struct updater_config;
-struct quirk_entry {
- const char *name;
- const char *help;
- int (*apply)(struct updater_config *cfg);
- int value;
-};
-
-enum quirk_types {
- QUIRK_ENLARGE_IMAGE,
- QUIRK_UNLOCK_ME_FOR_UPDATE,
- QUIRK_MIN_PLATFORM_VERSION,
- QUIRK_MAX,
-};
-
-struct tempfile {
- char *filepath;
- struct tempfile *next;
-};
-
-struct updater_config {
- struct firmware_image image, image_current;
- struct firmware_image ec_image, pd_image;
- struct system_property system_properties[SYS_PROP_MAX];
- struct quirk_entry quirks[QUIRK_MAX];
- struct tempfile *tempfiles;
- int try_update;
- int force_update;
- int legacy_update;
- const char *emulation;
-};
-
/*
* Helper function to create a new temporary file.
* All files created will be removed by function remove_all_temp_files().
* Returns the path of new file, or NULL on failure.
*/
-static const char *create_temp_file(struct updater_config *cfg)
+const char *create_temp_file(struct updater_config *cfg)
{
struct tempfile *new_temp;
char new_path[] = P_tmpdir "/fwupdater.XXXXXX";
@@ -401,8 +317,8 @@ static int host_get_wp_sw()
* and cache the result.
* Returns the property value.
*/
-static int get_system_property(enum system_property_type property_type,
- struct updater_config *cfg)
+int get_system_property(enum system_property_type property_type,
+ struct updater_config *cfg)
{
struct system_property *prop;
@@ -497,8 +413,7 @@ static void override_properties_from_list(const char *override_list,
}
/* Gets the value (setting) of specified quirks from updater configuration. */
-static int get_config_quirk(enum quirk_types quirk,
- const struct updater_config *cfg)
+int get_config_quirk(enum quirk_types quirk, const struct updater_config *cfg)
{
assert(quirk < QUIRK_MAX);
return cfg->quirks[quirk].value;
@@ -586,9 +501,9 @@ static int setup_config_quirks(const char *quirks, struct updater_config *cfg)
* If successful, return zero and *section argument contains the address and
* size of the section; otherwise failure.
*/
-static int find_firmware_section(struct firmware_section *section,
- const struct firmware_image *image,
- const char *section_name)
+int find_firmware_section(struct firmware_section *section,
+ const struct firmware_image *image,
+ const char *section_name)
{
FmapAreaHeader *fah = NULL;
uint8_t *ptr;
@@ -658,7 +573,7 @@ static int load_firmware_version(struct firmware_image *image,
* Loads a firmware image from file.
* Returns 0 on success, otherwise failure.
*/
-static int load_image(const char *file_name, struct firmware_image *image)
+int load_image(const char *file_name, struct firmware_image *image)
{
DEBUG("Load image file from %s...", file_name);
@@ -717,7 +632,7 @@ static int load_system_image(struct updater_config *cfg,
/*
* Frees the allocated resource from a firmware image object.
*/
-static void free_image(struct firmware_image *image)
+void free_image(struct firmware_image *image)
{
free(image->data);
free(image->file_name);
@@ -1413,96 +1328,6 @@ static int check_compatible_tpm_keys(struct updater_config *cfg,
return 0;
}
-/*
- * Quirk to enlarge a firmware image to match flash size. This is needed by
- * devices using multiple SPI flash with different sizes, for example 8M and
- * 16M. The image_to will be padded with 0xFF using the size of image_from.
- * Returns 0 on success, otherwise failure.
- */
-static int quirk_enlarge_image(struct updater_config *cfg)
-{
- struct firmware_image *image_from = &cfg->image_current,
- *image_to = &cfg->image;
- const char *tmp_path;
- size_t to_write;
- FILE *fp;
-
- if (image_from->size <= image_to->size)
- return 0;
-
- tmp_path = create_temp_file(cfg);
- if (!tmp_path)
- return -1;
-
- DEBUG("Resize image from %u to %u.", image_to->size, image_from->size);
- to_write = image_from->size - image_to->size;
- vb2_write_file(tmp_path, image_to->data, image_to->size);
- fp = fopen(tmp_path, "ab");
- if (!fp) {
- ERROR("Cannot open temporary file %s.", tmp_path);
- return -1;
- }
- while (to_write-- > 0)
- fputc('\xff', fp);
- fclose(fp);
- free_image(image_to);
- return load_image(tmp_path, image_to);
-}
-
-/*
- * Quirk to unlock a firmware image with SI_ME (management engine) when updating
- * so the system has a chance to make sure SI_ME won't be corrupted on next boot
- * before locking the Flash Master values in SI_DESC.
- * Returns 0 on success, otherwise failure.
- */
-static int quirk_unlock_me_for_update(struct updater_config *cfg)
-{
- struct firmware_section section;
- struct firmware_image *image_to = &cfg->image;
- const int flash_master_offset = 128;
- const uint8_t flash_master[] = {
- 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
- 0xff, 0xff
- };
-
- find_firmware_section(&section, image_to, FMAP_SI_DESC);
- if (section.size < flash_master_offset + ARRAY_SIZE(flash_master))
- return 0;
- if (memcmp(section.data + flash_master_offset, flash_master,
- ARRAY_SIZE(flash_master)) == 0) {
- DEBUG("Target ME not locked.");
- return 0;
- }
- /*
- * b/35568719: We should only update with unlocked ME and let
- * board-postinst lock it.
- */
- printf("%s: Changed Flash Master Values to unlocked.\n", __FUNCTION__);
- memcpy(section.data + flash_master_offset, flash_master,
- ARRAY_SIZE(flash_master));
- return 0;
-}
-
-/*
- * Checks and returns 0 if the platform version of current system is larger
- * or equal to given number, otherwise non-zero.
- */
-static int quirk_min_platform_version(struct updater_config *cfg)
-{
- int min_version = get_config_quirk(QUIRK_MIN_PLATFORM_VERSION, cfg);
- int platform_version = get_system_property(SYS_PROP_PLATFORM_VER, cfg);
-
- DEBUG("Minimum required version=%d, current platform version=%d",
- min_version, platform_version);
-
- if (platform_version >= min_version)
- return 0;
- ERROR("Need platform version >= %d (current is %d). "
- "This firmware will only run on newer systems.",
- min_version, platform_version);
- return -1;
-}
-
const char * const updater_error_messages[] = {
[UPDATE_ERR_DONE] = "Done (no error)",
[UPDATE_ERR_NEED_RO_UPDATE] = "RO changed and no WP. Need full update.",
@@ -1739,7 +1564,6 @@ enum updater_error_codes update_firmware(struct updater_config *cfg)
struct updater_config *updater_new_config()
{
struct system_property *props;
- struct quirk_entry *quirks;
struct updater_config *cfg = (struct updater_config *)calloc(
1, sizeof(struct updater_config));
if (!cfg)
@@ -1757,23 +1581,7 @@ struct updater_config *updater_new_config()
props[SYS_PROP_WP_HW].getter = host_get_wp_hw;
props[SYS_PROP_WP_SW].getter = host_get_wp_sw;
- quirks = &cfg->quirks[QUIRK_ENLARGE_IMAGE];
- quirks->name = "enlarge_image";
- quirks->help = "Enlarge firmware image by flash size.";
- quirks->apply = quirk_enlarge_image;
-
- quirks = &cfg->quirks[QUIRK_UNLOCK_ME_FOR_UPDATE];
- quirks->name = "unlock_me_for_update";
- quirks->help = "b/35568719: Only lock management engine by "
- "board-postinst.";
- quirks->apply = quirk_unlock_me_for_update;
-
- quirks = &cfg->quirks[QUIRK_MIN_PLATFORM_VERSION];
- quirks->name = "min_platform_version";
- quirks->help = "Minimum compatible platform version "
- "(also known as Board ID version).";
- quirks->apply = quirk_min_platform_version;
-
+ updater_register_quirks(cfg);
return cfg;
}
diff --git a/futility/updater.h b/futility/updater.h
index 85540a90..02c1d8e5 100644
--- a/futility/updater.h
+++ b/futility/updater.h
@@ -8,11 +8,95 @@
#ifndef VBOOT_REFERENCE_FUTILITY_UPDATER_H_
#define VBOOT_REFERENCE_FUTILITY_UPDATER_H_
+#include "fmap.h"
#include "futility.h"
#define DEBUG(format, ...) Debug("%s: " format "\n", __FUNCTION__,##__VA_ARGS__)
#define ERROR(format, ...) Error("%s: " format "\n", __FUNCTION__,##__VA_ARGS__)
+/* FMAP section names. */
+static const char * const FMAP_RO_FRID = "RO_FRID",
+ * const FMAP_RO_SECTION = "RO_SECTION",
+ * const FMAP_RO_GBB = "GBB",
+ * const FMAP_RO_PRESERVE = "RO_PRESERVE",
+ * const FMAP_RO_VPD = "RO_VPD",
+ * const FMAP_RW_VPD = "RW_VPD",
+ * const FMAP_RW_VBLOCK_A = "VBLOCK_A",
+ * const FMAP_RW_SECTION_A = "RW_SECTION_A",
+ * const FMAP_RW_SECTION_B = "RW_SECTION_B",
+ * const FMAP_RW_FWID = "RW_FWID",
+ * const FMAP_RW_FWID_A = "RW_FWID_A",
+ * const FMAP_RW_FWID_B = "RW_FWID_B",
+ * const FMAP_RW_SHARED = "RW_SHARED",
+ * const FMAP_RW_NVRAM = "RW_NVRAM",
+ * const FMAP_RW_ELOG = "RW_ELOG",
+ * const FMAP_RW_PRESERVE = "RW_PRESERVE",
+ * const FMAP_RW_LEGACY = "RW_LEGACY",
+ * const FMAP_SI_DESC = "SI_DESC",
+ * const FMAP_SI_ME = "SI_ME";
+
+struct firmware_image {
+ const char *programmer;
+ uint32_t size;
+ uint8_t *data;
+ char *file_name;
+ char *ro_version, *rw_version_a, *rw_version_b;
+ FmapHeader *fmap_header;
+};
+
+struct firmware_section {
+ uint8_t *data;
+ size_t size;
+};
+
+struct system_property {
+ int (*getter)();
+ int value;
+ int initialized;
+};
+
+enum system_property_type {
+ SYS_PROP_MAINFW_ACT,
+ SYS_PROP_TPM_FWVER,
+ SYS_PROP_FW_VBOOT2,
+ SYS_PROP_PLATFORM_VER,
+ SYS_PROP_WP_HW,
+ SYS_PROP_WP_SW,
+ SYS_PROP_MAX
+};
+
+struct updater_config;
+struct quirk_entry {
+ const char *name;
+ const char *help;
+ int (*apply)(struct updater_config *cfg);
+ int value;
+};
+
+enum quirk_types {
+ QUIRK_ENLARGE_IMAGE,
+ QUIRK_MIN_PLATFORM_VERSION,
+ QUIRK_UNLOCK_ME_FOR_UPDATE,
+ QUIRK_MAX,
+};
+
+struct tempfile {
+ char *filepath;
+ struct tempfile *next;
+};
+
+struct updater_config {
+ struct firmware_image image, image_current;
+ struct firmware_image ec_image, pd_image;
+ struct system_property system_properties[SYS_PROP_MAX];
+ struct quirk_entry quirks[QUIRK_MAX];
+ struct tempfile *tempfiles;
+ int try_update;
+ int force_update;
+ int legacy_update;
+ const char *emulation;
+};
+
enum updater_error_codes {
UPDATE_ERR_DONE,
UPDATE_ERR_NEED_RO_UPDATE,
@@ -71,4 +155,37 @@ int updater_setup_config(struct updater_config *cfg,
/* Prints the name and description from all supported quirks. */
void updater_list_config_quirks(const struct updater_config *cfg);
+/*
+ * Registers known quirks to a updater_config object.
+ */
+void updater_register_quirks(struct updater_config *cfg);
+
+/*
+ * Helper function to create a new temporary file.
+ * Returns the path of new file, or NULL on failure.
+ */
+const char *create_temp_file(struct updater_config *cfg);
+
+/*
+ * Finds a firmware section by given name in the firmware image.
+ * If successful, return zero and *section argument contains the address and
+ * size of the section; otherwise failure.
+ */
+int find_firmware_section(struct firmware_section *section,
+ const struct firmware_image *image,
+ const char *section_name);
+
+/* Loads a firmware image from file. Returns 0 on success, otherwise failure. */
+int load_image(const char *file_name, struct firmware_image *image);
+
+/* Frees the allocated resource from a firmware image object. */
+void free_image(struct firmware_image *image);
+
+/* Gets the value (setting) of specified quirks from updater configuration. */
+int get_config_quirk(enum quirk_types quirk, const struct updater_config *cfg);
+
+/* Gets the system property by given type. Returns the property value. */
+int get_system_property(enum system_property_type property_type,
+ struct updater_config *cfg);
+
#endif /* VBOOT_REFERENCE_FUTILITY_UPDATER_H_ */
diff --git a/futility/updater_quirks.c b/futility/updater_quirks.c
new file mode 100644
index 00000000..df3c9983
--- /dev/null
+++ b/futility/updater_quirks.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2018 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.
+ *
+ * The board-specific quirks needed by firmware updater.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+
+#include "updater.h"
+#include "host_misc.h"
+
+/*
+ * Helper function to write a firmware image into file on disk.
+ * Returns the result from vb2_write_file.
+ */
+static int write_image(const char *file_path, struct firmware_image *image)
+{
+ return vb2_write_file(file_path, image->data, image->size);
+}
+
+/* Preserves meta data and reload image contents from given file path. */
+static int reload_image(const char *file_path, struct firmware_image *image)
+{
+ const char *programmer = image->programmer;
+ free_image(image);
+ image->programmer = programmer;
+ return load_image(file_path, image);
+}
+
+/*
+ * Quirk to enlarge a firmware image to match flash size. This is needed by
+ * devices using multiple SPI flash with different sizes, for example 8M and
+ * 16M. The image_to will be padded with 0xFF using the size of image_from.
+ * Returns 0 on success, otherwise failure.
+ */
+static int quirk_enlarge_image(struct updater_config *cfg)
+{
+ struct firmware_image *image_from = &cfg->image_current,
+ *image_to = &cfg->image;
+ const char *tmp_path;
+ size_t to_write;
+ FILE *fp;
+
+ if (image_from->size <= image_to->size)
+ return 0;
+
+ tmp_path = create_temp_file(cfg);
+ if (!tmp_path)
+ return -1;
+
+ DEBUG("Resize image from %u to %u.", image_to->size, image_from->size);
+ to_write = image_from->size - image_to->size;
+ write_image(tmp_path, image_to);
+ fp = fopen(tmp_path, "ab");
+ if (!fp) {
+ ERROR("Cannot open temporary file %s.", tmp_path);
+ return -1;
+ }
+ while (to_write-- > 0)
+ fputc('\xff', fp);
+ fclose(fp);
+ return reload_image(tmp_path, image_to);
+}
+
+/*
+ * Quirk to unlock a firmware image with SI_ME (management engine) when updating
+ * so the system has a chance to make sure SI_ME won't be corrupted on next boot
+ * before locking the Flash Master values in SI_DESC.
+ * Returns 0 on success, otherwise failure.
+ */
+static int quirk_unlock_me_for_update(struct updater_config *cfg)
+{
+ struct firmware_section section;
+ struct firmware_image *image_to = &cfg->image;
+ const int flash_master_offset = 128;
+ const uint8_t flash_master[] = {
+ 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff
+ };
+
+ find_firmware_section(&section, image_to, FMAP_SI_DESC);
+ if (section.size < flash_master_offset + ARRAY_SIZE(flash_master))
+ return 0;
+ if (memcmp(section.data + flash_master_offset, flash_master,
+ ARRAY_SIZE(flash_master)) == 0) {
+ DEBUG("Target ME not locked.");
+ return 0;
+ }
+ /*
+ * b/35568719: We should only update with unlocked ME and let
+ * board-postinst lock it.
+ */
+ printf("%s: Changed Flash Master Values to unlocked.\n", __FUNCTION__);
+ memcpy(section.data + flash_master_offset, flash_master,
+ ARRAY_SIZE(flash_master));
+ return 0;
+}
+
+/*
+ * Checks and returns 0 if the platform version of current system is larger
+ * or equal to given number, otherwise non-zero.
+ */
+static int quirk_min_platform_version(struct updater_config *cfg)
+{
+ int min_version = get_config_quirk(QUIRK_MIN_PLATFORM_VERSION, cfg);
+ int platform_version = get_system_property(SYS_PROP_PLATFORM_VER, cfg);
+
+ DEBUG("Minimum required version=%d, current platform version=%d",
+ min_version, platform_version);
+
+ if (platform_version >= min_version)
+ return 0;
+ ERROR("Need platform version >= %d (current is %d). "
+ "This firmware will only run on newer systems.",
+ min_version, platform_version);
+ return -1;
+}
+
+/*
+ * Registers known quirks to a updater_config object.
+ */
+void updater_register_quirks(struct updater_config *cfg)
+{
+ struct quirk_entry *quirks;
+
+ assert(ARRAY_SIZE(cfg->quirks) == QUIRK_MAX);
+ quirks = &cfg->quirks[QUIRK_ENLARGE_IMAGE];
+ quirks->name = "enlarge_image";
+ quirks->help = "Enlarge firmware image by flash size.";
+ quirks->apply = quirk_enlarge_image;
+
+ quirks = &cfg->quirks[QUIRK_MIN_PLATFORM_VERSION];
+ quirks->name = "min_platform_version";
+ quirks->help = "Minimum compatible platform version "
+ "(also known as Board ID version).";
+ quirks->apply = quirk_min_platform_version;
+
+ quirks = &cfg->quirks[QUIRK_UNLOCK_ME_FOR_UPDATE];
+ quirks->name = "unlock_me_for_update";
+ quirks->help = "b/35568719; only lock management engine in "
+ "board-postinst.";
+ quirks->apply = quirk_unlock_me_for_update;
+
+}