blob: 1b371f9c4947f70260a0e28e0b9e28791b25f00c [file] [log] [blame]
/* 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_RW_VBLOCK_A = "VBLOCK_A",
* const FMAP_RW_VBLOCK_B = "VBLOCK_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_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 {
QUIRK_ENLARGE_IMAGE,
QUIRK_MIN_PLATFORM_VERSION,
QUIRK_UNLOCK_ME_FOR_UPDATE,
QUIRK_UNLOCK_WILCO_ME_FOR_UPDATE,
QUIRK_EVE_SMM_STORE,
QUIRK_ALLOW_EMPTY_CUSTOM_LABEL_TAG,
QUIRK_EC_PARTIAL_RECOVERY,
QUIRK_OVERRIDE_SIGNATURE_ID,
QUIRK_PRESERVE_ME,
QUIRK_NO_CHECK_PLATFORM,
QUIRK_NO_VERIFY,
QUIRK_EXTRA_RETRIES,
QUIRK_EXTERNAL_FLASHROM,
QUIRK_CLEAR_MRC_DATA,
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, pd_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;
int override_gbb_flags;
uint32_t gbb_flags;
bool detect_model;
bool dut_is_remote;
};
struct updater_config_arguments {
char *image, *ec_image, *pd_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;
};
/*
* 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", 0, 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 \tDo fast,force,wp=0,p=raiden_debug_spi\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, *pd_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_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.
*/
int updater_setup_config(struct updater_config *cfg,
const struct updater_config_arguments *arg,
int *do_update);
/* 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);
/*
* Writes a single section from the given firmware image to the system.
* Writes the whole firmware image if the section_name is NULL.
* Returns 0 if success, non-zero if error.
*/
int write_firmware(struct updater_config *cfg,
const struct firmware_image *image,
const char *section_name);
/* 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_ */