From 5609bc8b34745b70d18916aa3b74f3272648e490 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Wed, 20 Jun 2018 00:30:48 -0700 Subject: applypatch: Refactor applypatch(). applypatch() was initially designed for file-based OTA, operating on individual files. It was later extended to allow patching eMMC targets as a whole, in favor of block-based updates. As we have deprecated file-based OTA since Oreo, part of the code in applypatch() has become obsolete. This CL refactors the related functions, by removing the obsolete logic and focusing on eMMC targets. Since this CL substantially changes applypatch APIs, it adds new functions to avoid unintentionally mixing them together. In particular, it removes `applypatch()`, `applypatch_check()`, `applypatch_flash()`, and adds `PatchPartition()`, `PatchPartitionCheck()`, `FlashPartition()` and `CheckPartition()`. It also replaces the old Edify functions `apply_patch()` and `apply_patch_check()` with `patch_partition()` and `patch_partition_check()` respectively. This CL requires matching changes to OTA generation script (in the same topic). Bug: 110106408 Test: Run recovery_unit_test and recovery_component_test on marlin. Test: `m dist` with non-A/B target. Verify /system/bin/install-recovery.sh on device. Test: `m dist` with non-A/B target using BOARD_USES_FULL_RECOVERY_IMAGE. Verify /system/bin/install-recovery.sh on device. Test: Install an incremental OTA with the new updater and scripts. Change-Id: Ia34a90114bb227f4216eb478c22dc98c8194cb7f --- applypatch/include/applypatch/applypatch.h | 85 +++++++++++++++++------------- 1 file changed, 47 insertions(+), 38 deletions(-) (limited to 'applypatch/include') diff --git a/applypatch/include/applypatch/applypatch.h b/applypatch/include/applypatch/applypatch.h index cf65f3f22..70eee1c16 100644 --- a/applypatch/include/applypatch/applypatch.h +++ b/applypatch/include/applypatch/applypatch.h @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -44,44 +45,52 @@ int ShowLicenses(); // digest or be of the form ":". Returns 0 on success, or -1 on any error. int ParseSha1(const std::string& str, uint8_t* digest); -// Applies binary patches to eMMC target files in a way that is safe (the original file is not -// touched until we have the desired replacement for it) and idempotent (it's okay to run this -// program multiple times). -// -// - If the SHA-1 hash of 'target_filename' is 'target_sha1_string', does nothing and returns -// successfully. -// -// - Otherwise, if the SHA-1 hash of 'source_filename' is one of the entries in 'patch_sha1s', the -// corresponding patch from 'patch_data' (which must be a VAL_BLOB) is applied to produce a new -// file (the type of patch is automatically detected from the blob data). If that new file has -// SHA-1 hash 'target_sha1_str', moves it to replace 'target_filename', and exits successfully. -// Note that if 'source_filename' and 'target_filename' are not the same, 'source_filename' is -// NOT deleted on success. 'target_filename' may be the string "-" to mean -// "the same as 'source_filename'". -// -// - Otherwise, or if any error is encountered, exits with non-zero status. -// -// 'source_filename' must refer to an eMMC partition to read the source data. See the comments for -// the LoadPartitionContents() function for the format of such a filename. 'target_size' has become -// obsolete since we have dropped the support for patching non-eMMC targets (eMMC targets have the -// size embedded in the filename). -int applypatch(const char* source_filename, const char* target_filename, - const char* target_sha1_str, size_t target_size, - const std::vector& patch_sha1s, - const std::vector>& patch_data, const Value* bonus_data); - -// Returns 0 if the contents of the eMMC target or the cached file match any of the given SHA-1's. -// Returns nonzero otherwise. 'filename' must refer to an eMMC partition target. It would only use -// 'sha1s' to find a match on /cache if the hashes embedded in the filename fail to match. -int applypatch_check(const std::string& filename, const std::vector& sha1s); - -// Flashes a given image to the eMMC target partition. It verifies the target cheksum first, and -// will return if target already has the desired hash. Otherwise it checks the checksum of the -// given source image before flashing, and verifies the target partition afterwards. -// 'target_filename' must refer to an eMMC partition, of the form "EMMC:::". -// The function is idempotent. Returns zero on success. -int applypatch_flash(const char* source_filename, const char* target_filename, - const char* target_sha1_str, size_t target_size); +struct Partition { + Partition() = default; + + Partition(const std::string& name, size_t size, const std::string& hash) + : name(name), size(size), hash(hash) {} + + // Parses and returns the given string into a Partition object. The input string is of the form + // "EMMC:::". Returns the parsed Partition, or an empty object on error. + static Partition Parse(const std::string& partition, std::string* err); + + std::string ToString() const; + + // Returns whether the current Partition object is valid. + explicit operator bool() const { + return !name.empty(); + } + + std::string name; + size_t size; + std::string hash; +}; + +std::ostream& operator<<(std::ostream& os, const Partition& partition); + +// Applies the given 'patch' to the 'source' Partition, verifies then writes the patching result to +// the 'target' Partition. While patching, it will backup the data on the source partition to +// /cache, so that the patching could be resumed on interruption even if both of the source and +// target partitions refer to the same device. The function is idempotent if called multiple times. +// An optional arg 'bonus' can be provided, if the patch was generated with a bonus output. +// Returns the patching result. +bool PatchPartition(const Partition& target, const Partition& source, const Value& patch, + const Value* bonus); + +// Returns whether the contents of the eMMC target or the cached file match the embedded hash. +// It will look for the backup on /cache if the given partition doesn't match the checksum. +bool PatchPartitionCheck(const Partition& target, const Partition& source); + +// Checks whether the contents of the given partition has the desired hash. It will NOT look for +// the backup on /cache if the given partition doesn't have the expected checksum. +bool CheckPartition(const Partition& target); + +// Flashes a given image in 'source_filename' to the eMMC target partition. It verifies the target +// checksum first, and will return if target already has the desired hash. Otherwise it checks the +// checksum of the given source image, flashes, and verifies the target partition afterwards. The +// function is idempotent. Returns the flashing result. +bool FlashPartition(const Partition& target, const std::string& source_filename); // Reads a file into memory; stores the file contents and associated metadata in *file. Returns 0 // on success, or -1 on error. -- cgit v1.2.3