summaryrefslogtreecommitdiffstats
path: root/updater/include/private/commands.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--updater/include/private/commands.h290
1 files changed, 284 insertions, 6 deletions
diff --git a/updater/include/private/commands.h b/updater/include/private/commands.h
index b36000072..784892fb5 100644
--- a/updater/include/private/commands.h
+++ b/updater/include/private/commands.h
@@ -16,20 +16,298 @@
#pragma once
+#include <ostream>
#include <string>
+#include <vector>
-struct Command {
+#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();
+ }
+ }
+
+ 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 };
+};
+
+// 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
+//
+class Command {
+ public:
enum class Type {
- ZERO,
- NEW,
- ERASE,
- MOVE,
BSDIFF,
+ ERASE,
+ FREE,
IMGDIFF,
+ MOVE,
+ NEW,
STASH,
- FREE,
+ 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_(std::move(patch)),
+ target_(std::move(target)),
+ source_(std::move(source)),
+ stash_(std::move(stash)) {}
+
+ // 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_;
+ }
+
+ constexpr explicit operator bool() const {
+ return type_ != Type::LAST;
+ }
+
+ private:
+ 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);
+
+ // 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_;
};
+
+std::ostream& operator<<(std::ostream& os, const Command& command);