Restore applypatch/updater/edify for non-A/B OTA support
Google deleted this source from bootable/recovery outright (commit c7ebad5f, "rm -rf non-AB code", 2024-04-05) — confirmed present at android-14, absent at android-16.0.0_r4. The runtime side (install.cpp's SetUpNonAbUpdateCommands) and build-side packaging (ota_from_target_files.py's GenerateNonAbOtaPackage) both survived; only the source that builds the update-binary executable itself was removed. Sourced from TeamWin's android_bootable_recovery (android-14.1), the only living copy found, with install/ZipUtil.cpp, get_args.cpp, and set_metadata.cpp intentionally left out (only wired into TeamWin's modified install.cpp, which PawletOS isn't adopting — twrpinstall carries its own independent copies). Kept as its own repo, not folded into a recovery fork, so it's buildable independent of whichever recovery UI ends up in use.
This commit is contained in:
@@ -0,0 +1,475 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <functional>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <gtest/gtest_prod.h> // FRIEND_TEST
|
||||
|
||||
#include "otautil/rangeset.h"
|
||||
|
||||
// Represents the target info used in a Command. TargetInfo contains the ranges of the blocks and
|
||||
// the expected hash.
|
||||
class TargetInfo {
|
||||
public:
|
||||
TargetInfo() = default;
|
||||
|
||||
TargetInfo(std::string hash, RangeSet ranges)
|
||||
: hash_(std::move(hash)), ranges_(std::move(ranges)) {}
|
||||
|
||||
const std::string& hash() const {
|
||||
return hash_;
|
||||
}
|
||||
|
||||
const RangeSet& ranges() const {
|
||||
return ranges_;
|
||||
}
|
||||
|
||||
size_t blocks() const {
|
||||
return ranges_.blocks();
|
||||
}
|
||||
|
||||
bool operator==(const TargetInfo& other) const {
|
||||
return hash_ == other.hash_ && ranges_ == other.ranges_;
|
||||
}
|
||||
|
||||
private:
|
||||
friend std::ostream& operator<<(std::ostream& os, const TargetInfo& source);
|
||||
|
||||
// The hash of the data represented by the object.
|
||||
std::string hash_;
|
||||
// The block ranges that the data should be written to.
|
||||
RangeSet ranges_;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const TargetInfo& source);
|
||||
|
||||
// Represents the stash info used in a Command.
|
||||
class StashInfo {
|
||||
public:
|
||||
StashInfo() = default;
|
||||
|
||||
StashInfo(std::string id, RangeSet ranges) : id_(std::move(id)), ranges_(std::move(ranges)) {}
|
||||
|
||||
size_t blocks() const {
|
||||
return ranges_.blocks();
|
||||
}
|
||||
|
||||
const std::string& id() const {
|
||||
return id_;
|
||||
}
|
||||
|
||||
const RangeSet& ranges() const {
|
||||
return ranges_;
|
||||
}
|
||||
|
||||
bool operator==(const StashInfo& other) const {
|
||||
return id_ == other.id_ && ranges_ == other.ranges_;
|
||||
}
|
||||
|
||||
private:
|
||||
friend std::ostream& operator<<(std::ostream& os, const StashInfo& stash);
|
||||
|
||||
// The id (i.e. hash) of the stash.
|
||||
std::string id_;
|
||||
// The matching location of the stash.
|
||||
RangeSet ranges_;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const StashInfo& stash);
|
||||
|
||||
// Represents the source info in a Command, whose data could come from source image, stashed blocks,
|
||||
// or both.
|
||||
class SourceInfo {
|
||||
public:
|
||||
SourceInfo() = default;
|
||||
|
||||
SourceInfo(std::string hash, RangeSet ranges, RangeSet location, std::vector<StashInfo> stashes)
|
||||
: hash_(std::move(hash)),
|
||||
ranges_(std::move(ranges)),
|
||||
location_(std::move(location)),
|
||||
stashes_(std::move(stashes)) {
|
||||
blocks_ = ranges_.blocks();
|
||||
for (const auto& stash : stashes_) {
|
||||
blocks_ += stash.ranges().blocks();
|
||||
}
|
||||
}
|
||||
|
||||
// Reads all the data specified by this SourceInfo object into the given 'buffer', by calling the
|
||||
// given readers. Caller needs to specify the block size for the represented blocks. The given
|
||||
// buffer needs to be sufficiently large. Otherwise it returns false. 'block_reader' and
|
||||
// 'stash_reader' read the specified data into the given buffer (guaranteed to be large enough)
|
||||
// respectively. The readers should return 0 on success, or -1 on error.
|
||||
bool ReadAll(
|
||||
std::vector<uint8_t>* buffer, size_t block_size,
|
||||
const std::function<int(const RangeSet&, std::vector<uint8_t>*)>& block_reader,
|
||||
const std::function<int(const std::string&, std::vector<uint8_t>*)>& stash_reader) const;
|
||||
|
||||
// Whether this SourceInfo overlaps with the given TargetInfo object.
|
||||
bool Overlaps(const TargetInfo& target) const;
|
||||
|
||||
// Dumps the hashes in hex for the given buffer that's loaded from this SourceInfo object
|
||||
// (excluding the stashed blocks which are handled separately).
|
||||
void DumpBuffer(const std::vector<uint8_t>& buffer, size_t block_size) const;
|
||||
|
||||
const std::string& hash() const {
|
||||
return hash_;
|
||||
}
|
||||
|
||||
size_t blocks() const {
|
||||
return blocks_;
|
||||
}
|
||||
|
||||
bool operator==(const SourceInfo& other) const {
|
||||
return hash_ == other.hash_ && ranges_ == other.ranges_ && location_ == other.location_ &&
|
||||
stashes_ == other.stashes_;
|
||||
}
|
||||
|
||||
private:
|
||||
friend std::ostream& operator<<(std::ostream& os, const SourceInfo& source);
|
||||
|
||||
// The hash of the data represented by the object.
|
||||
std::string hash_;
|
||||
// The block ranges from the source image to read data from. This could be a subset of all the
|
||||
// blocks represented by the object, or empty if all the data should be loaded from stash.
|
||||
RangeSet ranges_;
|
||||
// The location in the buffer to load ranges_ into. Empty if ranges_ alone covers all the blocks
|
||||
// (i.e. nothing needs to be loaded from stash).
|
||||
RangeSet location_;
|
||||
// The info for the stashed blocks that are part of the source. Empty if there's none.
|
||||
std::vector<StashInfo> stashes_;
|
||||
// Total number of blocks represented by the object.
|
||||
size_t blocks_{ 0 };
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const SourceInfo& source);
|
||||
|
||||
class PatchInfo {
|
||||
public:
|
||||
PatchInfo() = default;
|
||||
|
||||
PatchInfo(size_t offset, size_t length) : offset_(offset), length_(length) {}
|
||||
|
||||
size_t offset() const {
|
||||
return offset_;
|
||||
}
|
||||
|
||||
size_t length() const {
|
||||
return length_;
|
||||
}
|
||||
|
||||
bool operator==(const PatchInfo& other) const {
|
||||
return offset_ == other.offset_ && length_ == other.length_;
|
||||
}
|
||||
|
||||
private:
|
||||
size_t offset_{ 0 };
|
||||
size_t length_{ 0 };
|
||||
};
|
||||
|
||||
// The arguments to build a hash tree from blocks on the block device.
|
||||
class HashTreeInfo {
|
||||
public:
|
||||
HashTreeInfo() = default;
|
||||
|
||||
HashTreeInfo(RangeSet hash_tree_ranges, RangeSet source_ranges, std::string hash_algorithm,
|
||||
std::string salt_hex, std::string root_hash)
|
||||
: hash_tree_ranges_(std::move(hash_tree_ranges)),
|
||||
source_ranges_(std::move(source_ranges)),
|
||||
hash_algorithm_(std::move(hash_algorithm)),
|
||||
salt_hex_(std::move(salt_hex)),
|
||||
root_hash_(std::move(root_hash)) {}
|
||||
|
||||
const RangeSet& hash_tree_ranges() const {
|
||||
return hash_tree_ranges_;
|
||||
}
|
||||
const RangeSet& source_ranges() const {
|
||||
return source_ranges_;
|
||||
}
|
||||
|
||||
const std::string& hash_algorithm() const {
|
||||
return hash_algorithm_;
|
||||
}
|
||||
const std::string& salt_hex() const {
|
||||
return salt_hex_;
|
||||
}
|
||||
const std::string& root_hash() const {
|
||||
return root_hash_;
|
||||
}
|
||||
|
||||
bool operator==(const HashTreeInfo& other) const {
|
||||
return hash_tree_ranges_ == other.hash_tree_ranges_ && source_ranges_ == other.source_ranges_ &&
|
||||
hash_algorithm_ == other.hash_algorithm_ && salt_hex_ == other.salt_hex_ &&
|
||||
root_hash_ == other.root_hash_;
|
||||
}
|
||||
|
||||
private:
|
||||
RangeSet hash_tree_ranges_;
|
||||
RangeSet source_ranges_;
|
||||
std::string hash_algorithm_;
|
||||
std::string salt_hex_;
|
||||
std::string root_hash_;
|
||||
};
|
||||
|
||||
// Command class holds the info for an update command that performs block-based OTA (BBOTA). Each
|
||||
// command consists of one or several args, namely TargetInfo, SourceInfo, StashInfo and PatchInfo.
|
||||
// The currently used BBOTA version is v4.
|
||||
//
|
||||
// zero <tgt_ranges>
|
||||
// - Fill the indicated blocks with zeros.
|
||||
// - Meaningful args: TargetInfo
|
||||
//
|
||||
// new <tgt_ranges>
|
||||
// - Fill the blocks with data read from the new_data file.
|
||||
// - Meaningful args: TargetInfo
|
||||
//
|
||||
// erase <tgt_ranges>
|
||||
// - Mark the given blocks as empty.
|
||||
// - Meaningful args: TargetInfo
|
||||
//
|
||||
// move <hash> <...>
|
||||
// - Read the source blocks, write result to target blocks.
|
||||
// - Meaningful args: TargetInfo, SourceInfo
|
||||
//
|
||||
// See the note below for <...>.
|
||||
//
|
||||
// bsdiff <patchstart> <patchlen> <srchash> <dsthash> <...>
|
||||
// imgdiff <patchstart> <patchlen> <srchash> <dsthash> <...>
|
||||
// - Read the source blocks, apply a patch, and write result to target blocks.
|
||||
// - Meaningful args: PatchInfo, TargetInfo, SourceInfo
|
||||
//
|
||||
// It expects <...> in one of the following formats:
|
||||
//
|
||||
// <tgt_ranges> <src_block_count> - <[stash_id:stash_location] ...>
|
||||
// (loads data from stashes only)
|
||||
//
|
||||
// <tgt_ranges> <src_block_count> <src_ranges>
|
||||
// (loads data from source image only)
|
||||
//
|
||||
// <tgt_ranges> <src_block_count> <src_ranges> <src_ranges_location>
|
||||
// <[stash_id:stash_location] ...>
|
||||
// (loads data from both of source image and stashes)
|
||||
//
|
||||
// stash <stash_id> <src_ranges>
|
||||
// - Load the given source blocks and stash the data in the given slot of the stash table.
|
||||
// - Meaningful args: StashInfo
|
||||
//
|
||||
// free <stash_id>
|
||||
// - Free the given stash data.
|
||||
// - Meaningful args: StashInfo
|
||||
//
|
||||
// compute_hash_tree <hash_tree_ranges> <source_ranges> <hash_algorithm> <salt_hex> <root_hash>
|
||||
// - Computes the hash_tree bytes and writes the result to the specified range on the
|
||||
// block_device.
|
||||
//
|
||||
// abort
|
||||
// - Abort the current update. Allowed for testing code only.
|
||||
//
|
||||
class Command {
|
||||
public:
|
||||
enum class Type {
|
||||
ABORT,
|
||||
BSDIFF,
|
||||
COMPUTE_HASH_TREE,
|
||||
ERASE,
|
||||
FREE,
|
||||
IMGDIFF,
|
||||
MOVE,
|
||||
NEW,
|
||||
STASH,
|
||||
ZERO,
|
||||
LAST, // Not a valid type.
|
||||
};
|
||||
|
||||
Command() = default;
|
||||
|
||||
Command(Type type, size_t index, std::string cmdline, PatchInfo patch, TargetInfo target,
|
||||
SourceInfo source, StashInfo stash)
|
||||
: type_(type),
|
||||
index_(index),
|
||||
cmdline_(std::move(cmdline)),
|
||||
patch_(patch),
|
||||
target_(std::move(target)),
|
||||
source_(std::move(source)),
|
||||
stash_(std::move(stash)) {}
|
||||
|
||||
Command(Type type, size_t index, std::string cmdline, HashTreeInfo hash_tree_info);
|
||||
|
||||
// Parses the given command 'line' into a Command object and returns it. The 'index' is specified
|
||||
// by the caller to index the object. On parsing error, it returns an empty Command object that
|
||||
// evaluates to false, and the specific error message will be set in 'err'.
|
||||
static Command Parse(const std::string& line, size_t index, std::string* err);
|
||||
|
||||
// Parses the command type from the given string.
|
||||
static Type ParseType(const std::string& type_str);
|
||||
|
||||
Type type() const {
|
||||
return type_;
|
||||
}
|
||||
|
||||
size_t index() const {
|
||||
return index_;
|
||||
}
|
||||
|
||||
const std::string& cmdline() const {
|
||||
return cmdline_;
|
||||
}
|
||||
|
||||
const PatchInfo& patch() const {
|
||||
return patch_;
|
||||
}
|
||||
|
||||
const TargetInfo& target() const {
|
||||
return target_;
|
||||
}
|
||||
|
||||
const SourceInfo& source() const {
|
||||
return source_;
|
||||
}
|
||||
|
||||
const StashInfo& stash() const {
|
||||
return stash_;
|
||||
}
|
||||
|
||||
const HashTreeInfo& hash_tree_info() const {
|
||||
return hash_tree_info_;
|
||||
}
|
||||
|
||||
size_t block_size() const {
|
||||
return block_size_;
|
||||
}
|
||||
|
||||
constexpr explicit operator bool() const {
|
||||
return type_ != Type::LAST;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class ResumableUpdaterTest;
|
||||
friend class UpdaterTest;
|
||||
|
||||
FRIEND_TEST(CommandsTest, Parse_ABORT_Allowed);
|
||||
FRIEND_TEST(CommandsTest, Parse_InvalidNumberOfArgs);
|
||||
FRIEND_TEST(CommandsTest, ParseTargetInfoAndSourceInfo_InvalidInput);
|
||||
FRIEND_TEST(CommandsTest, ParseTargetInfoAndSourceInfo_StashesOnly);
|
||||
FRIEND_TEST(CommandsTest, ParseTargetInfoAndSourceInfo_SourceBlocksAndStashes);
|
||||
FRIEND_TEST(CommandsTest, ParseTargetInfoAndSourceInfo_SourceBlocksOnly);
|
||||
|
||||
// Parses the target and source info from the given 'tokens' vector. Saves the parsed info into
|
||||
// 'target' and 'source' objects. Returns the parsing result. Error message will be set in 'err'
|
||||
// on parsing error, and the contents in 'target' and 'source' will be undefined.
|
||||
static bool ParseTargetInfoAndSourceInfo(const std::vector<std::string>& tokens,
|
||||
const std::string& tgt_hash, TargetInfo* target,
|
||||
const std::string& src_hash, SourceInfo* source,
|
||||
std::string* err);
|
||||
|
||||
// Allows parsing ABORT command, which should be used for testing purpose only.
|
||||
static bool abort_allowed_;
|
||||
|
||||
// The type of the command.
|
||||
Type type_{ Type::LAST };
|
||||
// The index of the Command object, which is specified by the caller.
|
||||
size_t index_{ 0 };
|
||||
// The input string that the Command object is parsed from.
|
||||
std::string cmdline_;
|
||||
// The patch info. Only meaningful for BSDIFF and IMGDIFF commands.
|
||||
PatchInfo patch_;
|
||||
// The target info, where the command should be written to.
|
||||
TargetInfo target_;
|
||||
// The source info to load the source blocks for the command.
|
||||
SourceInfo source_;
|
||||
// The stash info. Only meaningful for STASH and FREE commands. Note that although SourceInfo may
|
||||
// also load data from stash, such info will be owned and managed by SourceInfo (i.e. in source_).
|
||||
StashInfo stash_;
|
||||
// The hash_tree info. Only meaningful for COMPUTE_HASH_TREE.
|
||||
HashTreeInfo hash_tree_info_;
|
||||
// The unit size of each block to be used in this command.
|
||||
size_t block_size_{ 4096 };
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const Command& command);
|
||||
|
||||
// TransferList represents the info for a transfer list, which is parsed from input text lines
|
||||
// containing commands to transfer data from one place to another on the target partition.
|
||||
//
|
||||
// The creator of the transfer list will guarantee that no block is read (i.e., used as the source
|
||||
// for a patch or move) after it has been written.
|
||||
//
|
||||
// The creator will guarantee that a given stash is loaded (with a stash command) before it's used
|
||||
// in a move/bsdiff/imgdiff command.
|
||||
//
|
||||
// Within one command the source and target ranges may overlap so in general we need to read the
|
||||
// entire source into memory before writing anything to the target blocks.
|
||||
//
|
||||
// All the patch data is concatenated into one patch_data file in the update package. It must be
|
||||
// stored uncompressed because we memory-map it in directly from the archive. (Since patches are
|
||||
// already compressed, we lose very little by not compressing their concatenation.)
|
||||
//
|
||||
// Commands that read data from the partition (i.e. move/bsdiff/imgdiff/stash) have one or more
|
||||
// additional hashes before the range parameters, which are used to check if the command has
|
||||
// already been completed and verify the integrity of the source data.
|
||||
class TransferList {
|
||||
public:
|
||||
// Number of header lines.
|
||||
static constexpr size_t kTransferListHeaderLines = 4;
|
||||
|
||||
TransferList() = default;
|
||||
|
||||
// Parses the given input string and returns a TransferList object. Sets error message if any.
|
||||
static TransferList Parse(const std::string& transfer_list_str, std::string* err);
|
||||
|
||||
int version() const {
|
||||
return version_;
|
||||
}
|
||||
|
||||
size_t total_blocks() const {
|
||||
return total_blocks_;
|
||||
}
|
||||
|
||||
size_t stash_max_entries() const {
|
||||
return stash_max_entries_;
|
||||
}
|
||||
|
||||
size_t stash_max_blocks() const {
|
||||
return stash_max_blocks_;
|
||||
}
|
||||
|
||||
const std::vector<Command>& commands() const {
|
||||
return commands_;
|
||||
}
|
||||
|
||||
// Returns whether the TransferList is valid.
|
||||
constexpr explicit operator bool() const {
|
||||
return version_ != 0;
|
||||
}
|
||||
|
||||
private:
|
||||
// BBOTA version.
|
||||
int version_{ 0 };
|
||||
// Total number of blocks to be written in this transfer.
|
||||
size_t total_blocks_;
|
||||
// Maximum number of stashes that exist at the same time.
|
||||
size_t stash_max_entries_;
|
||||
// Maximum number of blocks to be stashed.
|
||||
size_t stash_max_blocks_;
|
||||
// Commands in this transfer.
|
||||
std::vector<Command> commands_;
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
bool SetUpdatedMarker(const std::string& marker);
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _UPDATER_BLOCKIMG_H_
|
||||
#define _UPDATER_BLOCKIMG_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
void RegisterBlockImageFunctions();
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include <android-base/file.h>
|
||||
|
||||
// This class serves as the aggregation of the fake block device information during update
|
||||
// simulation on host. In specific, it has the name of the block device, its mount point, and the
|
||||
// path to the temporary file that fakes this block device.
|
||||
class FakeBlockDevice {
|
||||
public:
|
||||
FakeBlockDevice(std::string block_device, std::string mount_point, std::string temp_file_path)
|
||||
: blockdev_name(std::move(block_device)),
|
||||
mount_point(std::move(mount_point)),
|
||||
mounted_file_path(std::move(temp_file_path)) {}
|
||||
|
||||
std::string blockdev_name;
|
||||
std::string mount_point;
|
||||
std::string mounted_file_path; // path to the temp file that mocks the block device
|
||||
};
|
||||
|
||||
// This class stores the information of the source build. For example, it creates and maintains
|
||||
// the temporary files to simulate the block devices on host. Therefore, the simulator runtime can
|
||||
// query the information and run the update on host.
|
||||
class BuildInfo {
|
||||
public:
|
||||
BuildInfo(const std::string_view work_dir, bool keep_images)
|
||||
: work_dir_(work_dir), keep_images_(keep_images) {}
|
||||
// Returns the value of the build properties.
|
||||
std::string GetProperty(const std::string_view key, const std::string_view default_value) const;
|
||||
// Returns the path to the mock block device.
|
||||
std::string FindBlockDeviceName(const std::string_view name) const;
|
||||
// Parses the given target-file, initializes the build properties and extracts the images.
|
||||
bool ParseTargetFile(const std::string_view target_file_path, bool extracted_input);
|
||||
|
||||
std::string GetOemSettings() const {
|
||||
return oem_settings_;
|
||||
}
|
||||
void SetOemSettings(const std::string_view oem_settings) {
|
||||
oem_settings_ = oem_settings;
|
||||
}
|
||||
|
||||
private:
|
||||
// A map to store the system properties during simulation.
|
||||
std::map<std::string, std::string, std::less<>> build_props_;
|
||||
// A file that contains the oem properties.
|
||||
std::string oem_settings_;
|
||||
// A map from the blockdev_name to the FakeBlockDevice object, which contains the path to the
|
||||
// temporary file.
|
||||
std::map<std::string, FakeBlockDevice, std::less<>> blockdev_map_;
|
||||
|
||||
std::list<TemporaryFile> temp_files_;
|
||||
std::string work_dir_; // A temporary directory to store the extracted image files
|
||||
bool keep_images_;
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
void RegisterDynamicPartitionsFunctions();
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2009 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
void RegisterInstallFunctions();
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "edify/updater_runtime_interface.h"
|
||||
#include "updater/build_info.h"
|
||||
|
||||
class SimulatorRuntime : public UpdaterRuntimeInterface {
|
||||
public:
|
||||
explicit SimulatorRuntime(BuildInfo* source) : source_(source) {}
|
||||
|
||||
bool IsSimulator() const override {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string GetProperty(const std::string_view key,
|
||||
const std::string_view default_value) const override;
|
||||
|
||||
int Mount(const std::string_view location, const std::string_view mount_point,
|
||||
const std::string_view fs_type, const std::string_view mount_options) override;
|
||||
bool IsMounted(const std::string_view mount_point) const override;
|
||||
std::pair<bool, int> Unmount(const std::string_view mount_point) override;
|
||||
|
||||
bool ReadFileToString(const std::string_view filename, std::string* content) const override;
|
||||
bool WriteStringToFile(const std::string_view content,
|
||||
const std::string_view filename) const override;
|
||||
|
||||
int WipeBlockDevice(const std::string_view filename, size_t len) const override;
|
||||
int RunProgram(const std::vector<std::string>& args, bool is_vfork) const override;
|
||||
int Tune2Fs(const std::vector<std::string>& args) const override;
|
||||
|
||||
bool MapPartitionOnDeviceMapper(const std::string& partition_name, std::string* path) override;
|
||||
bool UnmapPartitionOnDeviceMapper(const std::string& partition_name) override;
|
||||
bool UpdateDynamicPartitions(const std::string_view op_list_value) override;
|
||||
std::string AddSlotSuffix(const std::string_view arg) const override;
|
||||
|
||||
private:
|
||||
std::string FindBlockDeviceName(const std::string_view name) const override;
|
||||
|
||||
BuildInfo* source_;
|
||||
std::map<std::string, std::string, std::less<>> mounted_partitions_;
|
||||
};
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include <android-base/file.h>
|
||||
#include <ziparchive/zip_archive.h>
|
||||
|
||||
// This class represents the mount information for each line in a fstab file.
|
||||
class FstabInfo {
|
||||
public:
|
||||
FstabInfo(std::string blockdev_name, std::string mount_point, std::string fs_type)
|
||||
: blockdev_name(std::move(blockdev_name)),
|
||||
mount_point(std::move(mount_point)),
|
||||
fs_type(std::move(fs_type)) {}
|
||||
|
||||
std::string blockdev_name;
|
||||
std::string mount_point;
|
||||
std::string fs_type;
|
||||
};
|
||||
|
||||
// This class parses a target file from a zip file or an extracted directory. It also provides the
|
||||
// function to read the its content for simulation.
|
||||
class TargetFile {
|
||||
public:
|
||||
TargetFile(std::string path, bool extracted_input)
|
||||
: path_(std::move(path)), extracted_input_(extracted_input) {}
|
||||
|
||||
// Opens the input target file (or extracted directory) and parses the misc_info.txt.
|
||||
bool Open();
|
||||
// Parses the build properties in all possible locations and save them in |props_map|
|
||||
bool GetBuildProps(std::map<std::string, std::string, std::less<>>* props_map) const;
|
||||
// Parses the fstab and save the information about each partition to mount into |fstab_info_list|.
|
||||
bool ParseFstabInfo(std::vector<FstabInfo>* fstab_info_list) const;
|
||||
// Returns true if the given entry exists in the target file.
|
||||
bool EntryExists(const std::string_view name) const;
|
||||
// Extracts the image file |entry_name|. Returns true on success.
|
||||
bool ExtractImage(const std::string_view entry_name, const FstabInfo& fstab_info,
|
||||
const std::string_view work_dir, TemporaryFile* image_file) const;
|
||||
|
||||
private:
|
||||
// Wrapper functions to read the entry from either the zipped target-file, or the extracted input
|
||||
// directory.
|
||||
bool ReadEntryToString(const std::string_view name, std::string* content) const;
|
||||
bool ExtractEntryToTempFile(const std::string_view name, TemporaryFile* temp_file) const;
|
||||
|
||||
std::string path_; // Path to the zipped target-file or an extracted directory.
|
||||
bool extracted_input_; // True if the target-file has been extracted.
|
||||
ZipArchiveHandle handle_{ nullptr };
|
||||
|
||||
// The properties under META/misc_info.txt
|
||||
std::map<std::string, std::string, std::less<>> misc_info_;
|
||||
};
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (C) 2009 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include <ziparchive/zip_archive.h>
|
||||
|
||||
#include "edify/expr.h"
|
||||
#include "edify/updater_interface.h"
|
||||
#include "otautil/error_code.h"
|
||||
#include "otautil/sysutil.h"
|
||||
|
||||
class Updater : public UpdaterInterface {
|
||||
public:
|
||||
explicit Updater(std::unique_ptr<UpdaterRuntimeInterface> run_time)
|
||||
: runtime_(std::move(run_time)) {}
|
||||
|
||||
~Updater() override;
|
||||
|
||||
// Memory-maps the OTA package and opens it as a zip file. Also sets up the command pipe and
|
||||
// UpdaterRuntime.
|
||||
bool Init(int fd, const std::string_view package_filename, bool is_retry);
|
||||
|
||||
// Parses and evaluates the updater-script in the OTA package. Reports the error code if the
|
||||
// evaluation fails.
|
||||
bool RunUpdate();
|
||||
|
||||
// Writes the message to command pipe, adds a new line in the end.
|
||||
void WriteToCommandPipe(const std::string_view message, bool flush = false) const override;
|
||||
|
||||
// Sends over the message to recovery to print it on the screen.
|
||||
void UiPrint(const std::string_view message) const override;
|
||||
|
||||
std::string FindBlockDeviceName(const std::string_view name) const override;
|
||||
|
||||
UpdaterRuntimeInterface* GetRuntime() const override {
|
||||
return runtime_.get();
|
||||
}
|
||||
ZipArchiveHandle GetPackageHandle() const override {
|
||||
return package_handle_;
|
||||
}
|
||||
std::string GetResult() const override {
|
||||
return result_;
|
||||
}
|
||||
uint8_t* GetMappedPackageAddress() const override {
|
||||
return mapped_package_.addr;
|
||||
}
|
||||
size_t GetMappedPackageLength() const override {
|
||||
return mapped_package_.length;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class UpdaterTestBase;
|
||||
friend class UpdaterTest;
|
||||
// Where in the package we expect to find the edify script to execute.
|
||||
// (Note it's "updateR-script", not the older "update-script".)
|
||||
static constexpr const char* SCRIPT_NAME = "META-INF/com/google/android/updater-script";
|
||||
|
||||
// Reads the entry |name| in the zip archive and put the result in |content|.
|
||||
bool ReadEntryToString(ZipArchiveHandle za, const std::string& entry_name, std::string* content);
|
||||
|
||||
// Parses the error code embedded in state->errmsg; and reports the error code and cause code.
|
||||
void ParseAndReportErrorCode(State* state);
|
||||
|
||||
std::unique_ptr<UpdaterRuntimeInterface> runtime_;
|
||||
|
||||
MemMapping mapped_package_;
|
||||
ZipArchiveHandle package_handle_{ nullptr };
|
||||
std::string updater_script_;
|
||||
|
||||
bool is_retry_{ false };
|
||||
std::unique_ptr<FILE, decltype(&fclose)> cmd_pipe_{ nullptr, fclose };
|
||||
|
||||
std::string result_;
|
||||
std::vector<std::string> skipped_functions_;
|
||||
};
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "edify/updater_runtime_interface.h"
|
||||
|
||||
struct selabel_handle;
|
||||
|
||||
class UpdaterRuntime : public UpdaterRuntimeInterface {
|
||||
public:
|
||||
explicit UpdaterRuntime(struct selabel_handle* sehandle) : sehandle_(sehandle) {}
|
||||
~UpdaterRuntime() override = default;
|
||||
|
||||
bool IsSimulator() const override {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string GetProperty(const std::string_view key,
|
||||
const std::string_view default_value) const override;
|
||||
|
||||
std::string FindBlockDeviceName(const std::string_view name) const override;
|
||||
|
||||
int Mount(const std::string_view location, const std::string_view mount_point,
|
||||
const std::string_view fs_type, const std::string_view mount_options) override;
|
||||
bool IsMounted(const std::string_view mount_point) const override;
|
||||
std::pair<bool, int> Unmount(const std::string_view mount_point) override;
|
||||
|
||||
bool ReadFileToString(const std::string_view filename, std::string* content) const override;
|
||||
bool WriteStringToFile(const std::string_view content,
|
||||
const std::string_view filename) const override;
|
||||
|
||||
int WipeBlockDevice(const std::string_view filename, size_t len) const override;
|
||||
int RunProgram(const std::vector<std::string>& args, bool is_vfork) const override;
|
||||
int Tune2Fs(const std::vector<std::string>& args) const override;
|
||||
|
||||
bool MapPartitionOnDeviceMapper(const std::string& partition_name, std::string* path) override;
|
||||
bool UnmapPartitionOnDeviceMapper(const std::string& partition_name) override;
|
||||
bool UpdateDynamicPartitions(const std::string_view op_list_value) override;
|
||||
std::string AddSlotSuffix(const std::string_view arg) const override;
|
||||
|
||||
private:
|
||||
struct selabel_handle* sehandle_{ nullptr };
|
||||
};
|
||||
Reference in New Issue
Block a user