/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * A reference implementation for AP (and supporting images) firmware updater. */ #ifndef VBOOT_REFERENCE_FUTILITY_UPDATER_H_ #define VBOOT_REFERENCE_FUTILITY_UPDATER_H_ #include "futility.h" #include "updater_utils.h" /* FMAP section names. */ static const char * const FMAP_RO = "WP_RO", * const FMAP_RO_FMAP = "FMAP", * const FMAP_RO_FRID = "RO_FRID", * const FMAP_RO_SECTION = "RO_SECTION", * const FMAP_RO_CBFS = "COREBOOT", * const FMAP_RO_GBB = "GBB", * const FMAP_RO_GSCVD = "RO_GSCVD", * const FMAP_RO_VPD = "RO_VPD", * const FMAP_RW_VBLOCK_A = "VBLOCK_A", * const FMAP_RW_VBLOCK_B = "VBLOCK_B", * const FMAP_RW_FW_MAIN_A = "FW_MAIN_A", * const FMAP_RW_FW_MAIN_B = "FW_MAIN_B", * 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_LEGACY = "RW_LEGACY", * const FMAP_RW_VPD = "RW_VPD", * const FMAP_SI_DESC = "SI_DESC", * const FMAP_SI_ME = "SI_ME"; struct updater_config; struct quirk_entry { const char *name; const char *help; int (*apply)(struct updater_config *cfg); int value; }; enum quirk_types { /* Platform-independent quirks */ QUIRK_NO_CHECK_PLATFORM, QUIRK_NO_VERIFY, QUIRK_ENLARGE_IMAGE, QUIRK_MIN_PLATFORM_VERSION, QUIRK_EXTRA_RETRIES, /* Arch-specific quirks */ QUIRK_EC_PARTIAL_RECOVERY, QUIRK_CLEAR_MRC_DATA, QUIRK_PRESERVE_ME, /* Platform-specific quirks (removed after AUE) */ QUIRK_ALLOW_EMPTY_CUSTOM_LABEL_TAG, QUIRK_OVERRIDE_SIGNATURE_ID, QUIRK_EVE_SMM_STORE, QUIRK_UNLOCK_CSME_EVE, QUIRK_UNLOCK_CSME, /* End of quirks */ QUIRK_MAX, }; /* Return values from QUIRK_EC_PARTIAL_RECOVERY. */ enum { EC_RECOVERY_FULL = 0, /* Must be 0 as default value of quirks. */ EC_RECOVERY_RO, EC_RECOVERY_DONE }; enum try_update_type { TRY_UPDATE_OFF = 0, TRY_UPDATE_AUTO, TRY_UPDATE_DEFERRED_HOLD, TRY_UPDATE_DEFERRED_APPLY, }; struct updater_config { struct firmware_image image, image_current; struct firmware_image ec_image; struct dut_property dut_properties[DUT_PROP_MAX]; struct quirk_entry quirks[QUIRK_MAX]; struct u_archive *archive; struct tempfile tempfiles; enum try_update_type try_update; int force_update; int legacy_update; int factory_update; int check_platform; int use_diff_image; int do_verify; int verbosity; const char *emulation; char *emulation_programmer; const char *original_programmer; const char *prepare_ctrl_name; int override_gbb_flags; uint32_t gbb_flags; bool detect_model; bool dut_is_remote; }; struct updater_config_arguments { char *image, *ec_image; char *archive, *quirks, *mode; const char *programmer, *write_protection; char *model, *signature_id; char *emulation, *sys_props; char *output_dir; char *repack, *unpack; int is_factory, try_update, force_update, do_manifest, host_only; int fast_update; int verbosity; int override_gbb_flags; int detect_servo; int use_flash; uint32_t gbb_flags; bool detect_model_only; bool unlock_me; }; /* * Shared getopt arguments controlling flash behaviour. * These are shared by multiple commands. */ enum { OPT_CCD = 0x100, OPT_EMULATE, OPT_SERVO, OPT_SERVO_PORT, }; #ifdef USE_FLASHROM #define SHARED_FLASH_ARGS_SHORTOPTS "p:" #define SHARED_FLASH_ARGS_LONGOPTS \ {"programmer", 1, NULL, 'p'}, \ {"ccd_without_servod", 2, NULL, OPT_CCD}, \ {"servo", 0, NULL, OPT_SERVO}, \ {"servo_port", 1, NULL, OPT_SERVO_PORT}, \ {"emulate", 1, NULL, OPT_EMULATE}, #define SHARED_FLASH_ARGS_HELP \ "-p, --programmer=PRG\tChange AP (host) flashrom programmer\n" \ " --ccd_without_servod[=SERIAL] \tFlash via CCD without servod\n" \ " --emulate=FILE \tEmulate system firmware using file\n" \ " --servo \tFlash using Servo (v2, v4, micro, ...)\n" \ " --servo_port=PRT\tOverride servod port, implies --servo\n" #else #define SHARED_FLASH_ARGS_HELP #define SHARED_FLASH_ARGS_LONGOPTS #define SHARED_FLASH_ARGS_SHORTOPTS #endif /* USE_FLASHROM */ struct patch_config { char *rootkey; char *vblock_a; char *vblock_b; char *gscvd; }; struct model_config { char *name; char *image, *ec_image; struct patch_config patches; char *signature_id; int is_custom_label; }; struct manifest { int num; struct model_config *models; struct u_archive *archive; int default_model; int has_keyset; }; enum updater_error_codes { UPDATE_ERR_DONE, UPDATE_ERR_NEED_RO_UPDATE, UPDATE_ERR_NO_IMAGE, UPDATE_ERR_SYSTEM_IMAGE, UPDATE_ERR_INVALID_IMAGE, UPDATE_ERR_SET_COOKIES, UPDATE_ERR_WRITE_FIRMWARE, UPDATE_ERR_PLATFORM, UPDATE_ERR_TARGET, UPDATE_ERR_ROOT_KEY, UPDATE_ERR_TPM_ROLLBACK, UPDATE_ERR_UNLOCK_CSME, UPDATE_ERR_UNKNOWN, }; /* Messages explaining enum updater_error_codes. */ extern const char * const updater_error_messages[]; /* * Returns a valid root key from GBB header, or NULL on failure. */ const struct vb2_packed_key *get_rootkey( const struct vb2_gbb_header *gbb); /* * The main updater to update system firmware using the configuration parameter. * Returns UPDATE_ERR_DONE if success, otherwise failure. */ enum updater_error_codes update_firmware(struct updater_config *cfg); /* * Allocates and initializes a updater_config object with default values. * Returns the newly allocated object, or NULL on error. */ struct updater_config *updater_new_config(void); /* * Releases all resources in an updater configuration object. */ void updater_delete_config(struct updater_config *cfg); /* * Handle an argument if it is a shared updater option. * Returns 1 if argument was used. */ int handle_flash_argument(struct updater_config_arguments *args, int opt, char *optarg); /** * Helper function to setup an allocated updater_config object. * Returns number of failures, or 0 on success. * @param[out] updater_config, * @param[int] updater_config_arguments, */ int updater_setup_config(struct updater_config *cfg, const struct updater_config_arguments *arg); /** * Helper function to determine if to perform a update. * Returns true to perform update otherwise false. * @param[in] updater_config_arguments, */ bool updater_should_update(const struct updater_config_arguments *arg); /* 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); /* 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 default quirk config string from target image name. * Returns a string (in same format as --quirks) to load or NULL if no quirks. */ const char * const updater_get_model_quirks(struct updater_config *cfg); /* * Gets the quirk config string from target image CBFS. * Returns a string (in same format as --quirks) to load or NULL if no quirks. */ char * updater_get_cbfs_quirks(struct updater_config *cfg); /* * Overrides signature id if the device was shipped with known * special rootkey. */ int quirk_override_signature_id(struct updater_config *cfg, struct model_config *model, const char **signature_id); /* Functions from updater_archive.c */ /* * Opens an archive from given path. * The type of archive will be determined automatically. * Returns a pointer to reference to archive (must be released by archive_close * when not used), otherwise NULL on error. */ struct u_archive *archive_open(const char *path); /* * Closes an archive reference. * Returns 0 on success, otherwise non-zero as failure. */ int archive_close(struct u_archive *ar); /* * Checks if an entry (either file or directory) exists in archive. * Returns 1 if exists, otherwise 0 */ int archive_has_entry(struct u_archive *ar, const char *name); /* * Reads a file from archive. * Returns 0 on success (data and size reflects the file content), * otherwise non-zero as failure. */ int archive_read_file(struct u_archive *ar, const char *fname, uint8_t **data, uint32_t *size, int64_t *mtime); /* * Writes a file into archive. * If entry name (fname) is an absolute path (/file), always write into real * file system. * Returns 0 on success, otherwise non-zero as failure. */ int archive_write_file(struct u_archive *ar, const char *fname, uint8_t *data, uint32_t size, int64_t mtime); /* * Traverses all files within archive (directories are ignored). * For every entry, the path (relative the archive root) will be passed to * callback function, until the callback returns non-zero. * The arg argument will also be passed to callback. * Returns 0 on success otherwise non-zero as failure. */ int archive_walk(struct u_archive *ar, void *arg, int (*callback)(const char *path, void *arg)); /* * Copies all entries from one archive to another. * Returns 0 on success, otherwise non-zero as failure. */ int archive_copy(struct u_archive *from, struct u_archive *to); /* * Creates a new manifest object by scanning files in archive. * Returns the manifest on success, otherwise NULL for failure. */ struct manifest *new_manifest_from_archive(struct u_archive *archive); /* Releases all resources allocated by given manifest object. */ void delete_manifest(struct manifest *manifest); /* Prints the information of objects in manifest (models and images) in JSON. */ void print_json_manifest(const struct manifest *manifest); /* * Modifies a firmware image from patch information specified in model config. * Returns 0 on success, otherwise number of failures. */ int patch_image_by_model( struct firmware_image *image, const struct model_config *model, struct u_archive *archive); /* * Finds the existing model_config from manifest that best matches current * system (as defined by model_name). * Returns a model_config from manifest, or NULL if not found. */ const struct model_config *manifest_find_model(struct updater_config *cfg, const struct manifest *manifest, const char *model_name); /* * Finds the first existing model_config from manifest that matches current * system by reading RO_FRID from the existing host firmware. * Returns a model_config from manifest, or NULL if not found. */ const struct model_config * manifest_detect_model_from_frid(struct updater_config *cfg, struct manifest *manifest); /* * Applies custom 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_custom_label( struct model_config *model, struct u_archive *archive, const char *signature_id, const char *image); #endif /* VBOOT_REFERENCE_FUTILITY_UPDATER_H_ */