blob: 7f9dc79f4f488a71af18c11acca5f27ccc0d1a57 [file] [log] [blame]
Tao Baoc3901232018-05-21 16:05:56 -07001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#pragma once
18
Tao Bao6a7e4af2018-06-14 21:57:43 -070019#include <ostream>
Tao Baoc3901232018-05-21 16:05:56 -070020#include <string>
Tao Bao6a7e4af2018-06-14 21:57:43 -070021#include <vector>
Tao Baoc3901232018-05-21 16:05:56 -070022
Tao Bao6a7e4af2018-06-14 21:57:43 -070023#include <gtest/gtest_prod.h> // FRIEND_TEST
24
25#include "otautil/rangeset.h"
26
27// Represents the target info used in a Command. TargetInfo contains the ranges of the blocks and
28// the expected hash.
29class TargetInfo {
30 public:
31 TargetInfo() = default;
32
33 TargetInfo(std::string hash, RangeSet ranges)
34 : hash_(std::move(hash)), ranges_(std::move(ranges)) {}
35
36 const std::string& hash() const {
37 return hash_;
38 }
39
40 const RangeSet& ranges() const {
41 return ranges_;
42 }
43
44 size_t blocks() const {
45 return ranges_.blocks();
46 }
47
48 bool operator==(const TargetInfo& other) const {
49 return hash_ == other.hash_ && ranges_ == other.ranges_;
50 }
51
52 private:
53 friend std::ostream& operator<<(std::ostream& os, const TargetInfo& source);
54
55 // The hash of the data represented by the object.
56 std::string hash_;
57 // The block ranges that the data should be written to.
58 RangeSet ranges_;
59};
60
61std::ostream& operator<<(std::ostream& os, const TargetInfo& source);
62
63// Represents the stash info used in a Command.
64class StashInfo {
65 public:
66 StashInfo() = default;
67
68 StashInfo(std::string id, RangeSet ranges) : id_(std::move(id)), ranges_(std::move(ranges)) {}
69
70 size_t blocks() const {
71 return ranges_.blocks();
72 }
73
74 const std::string& id() const {
75 return id_;
76 }
77
78 const RangeSet& ranges() const {
79 return ranges_;
80 }
81
82 bool operator==(const StashInfo& other) const {
83 return id_ == other.id_ && ranges_ == other.ranges_;
84 }
85
86 private:
87 friend std::ostream& operator<<(std::ostream& os, const StashInfo& stash);
88
89 // The id (i.e. hash) of the stash.
90 std::string id_;
91 // The matching location of the stash.
92 RangeSet ranges_;
93};
94
95std::ostream& operator<<(std::ostream& os, const StashInfo& stash);
96
97// Represents the source info in a Command, whose data could come from source image, stashed blocks,
98// or both.
99class SourceInfo {
100 public:
101 SourceInfo() = default;
102
103 SourceInfo(std::string hash, RangeSet ranges, RangeSet location, std::vector<StashInfo> stashes)
104 : hash_(std::move(hash)),
105 ranges_(std::move(ranges)),
106 location_(std::move(location)),
107 stashes_(std::move(stashes)) {
108 blocks_ = ranges_.blocks();
109 for (const auto& stash : stashes_) {
110 blocks_ += stash.ranges().blocks();
111 }
112 }
113
114 const std::string& hash() const {
115 return hash_;
116 }
117
118 size_t blocks() const {
119 return blocks_;
120 }
121
122 bool operator==(const SourceInfo& other) const {
123 return hash_ == other.hash_ && ranges_ == other.ranges_ && location_ == other.location_ &&
124 stashes_ == other.stashes_;
125 }
126
127 private:
128 friend std::ostream& operator<<(std::ostream& os, const SourceInfo& source);
129
130 // The hash of the data represented by the object.
131 std::string hash_;
132 // The block ranges from the source image to read data from. This could be a subset of all the
133 // blocks represented by the object, or empty if all the data should be loaded from stash.
134 RangeSet ranges_;
135 // The location in the buffer to load ranges_ into. Empty if ranges_ alone covers all the blocks
136 // (i.e. nothing needs to be loaded from stash).
137 RangeSet location_;
138 // The info for the stashed blocks that are part of the source. Empty if there's none.
139 std::vector<StashInfo> stashes_;
140 // Total number of blocks represented by the object.
141 size_t blocks_{ 0 };
142};
143
144std::ostream& operator<<(std::ostream& os, const SourceInfo& source);
145
146class PatchInfo {
147 public:
148 PatchInfo() = default;
149
150 PatchInfo(size_t offset, size_t length) : offset_(offset), length_(length) {}
151
152 size_t offset() const {
153 return offset_;
154 }
155
156 size_t length() const {
157 return length_;
158 }
159
160 bool operator==(const PatchInfo& other) const {
161 return offset_ == other.offset_ && length_ == other.length_;
162 }
163
164 private:
165 size_t offset_{ 0 };
166 size_t length_{ 0 };
167};
168
169// Command class holds the info for an update command that performs block-based OTA (BBOTA). Each
170// command consists of one or several args, namely TargetInfo, SourceInfo, StashInfo and PatchInfo.
171// The currently used BBOTA version is v4.
172//
173// zero <tgt_ranges>
174// - Fill the indicated blocks with zeros.
175// - Meaningful args: TargetInfo
176//
177// new <tgt_ranges>
178// - Fill the blocks with data read from the new_data file.
179// - Meaningful args: TargetInfo
180//
181// erase <tgt_ranges>
182// - Mark the given blocks as empty.
183// - Meaningful args: TargetInfo
184//
185// move <hash> <...>
186// - Read the source blocks, write result to target blocks.
187// - Meaningful args: TargetInfo, SourceInfo
188//
189// See the note below for <...>.
190//
191// bsdiff <patchstart> <patchlen> <srchash> <dsthash> <...>
192// imgdiff <patchstart> <patchlen> <srchash> <dsthash> <...>
193// - Read the source blocks, apply a patch, and write result to target blocks.
194// - Meaningful args: PatchInfo, TargetInfo, SourceInfo
195//
196// It expects <...> in one of the following formats:
197//
198// <tgt_ranges> <src_block_count> - <[stash_id:stash_location] ...>
199// (loads data from stashes only)
200//
201// <tgt_ranges> <src_block_count> <src_ranges>
202// (loads data from source image only)
203//
204// <tgt_ranges> <src_block_count> <src_ranges> <src_ranges_location>
205// <[stash_id:stash_location] ...>
206// (loads data from both of source image and stashes)
207//
208// stash <stash_id> <src_ranges>
209// - Load the given source blocks and stash the data in the given slot of the stash table.
210// - Meaningful args: StashInfo
211//
212// free <stash_id>
213// - Free the given stash data.
214// - Meaningful args: StashInfo
215//
Tianjie Xu69ffa152018-08-01 16:40:00 -0700216// compute_hash_tree <hash_tree_ranges> <source_ranges> <hash_algorithm> <salt_hex> <root_hash>
217// - Computes the hash_tree bytes and writes the result to the specified range on the
218// block_device.
219//
Tao Bao91a649a2018-05-21 16:05:56 -0700220// abort
221// - Abort the current update. Allowed for testing code only.
222//
Tao Bao6a7e4af2018-06-14 21:57:43 -0700223class Command {
224 public:
Tao Baoc3901232018-05-21 16:05:56 -0700225 enum class Type {
Tao Bao91a649a2018-05-21 16:05:56 -0700226 ABORT,
Tao Baoc3901232018-05-21 16:05:56 -0700227 BSDIFF,
Tianjie Xu69ffa152018-08-01 16:40:00 -0700228 COMPUTE_HASH_TREE,
Tao Bao6a7e4af2018-06-14 21:57:43 -0700229 ERASE,
Tao Baoc3901232018-05-21 16:05:56 -0700230 FREE,
Tao Bao6a7e4af2018-06-14 21:57:43 -0700231 IMGDIFF,
232 MOVE,
233 NEW,
234 STASH,
235 ZERO,
Tao Baoc3901232018-05-21 16:05:56 -0700236 LAST, // Not a valid type.
237 };
238
Tao Bao6a7e4af2018-06-14 21:57:43 -0700239 Command() = default;
240
241 Command(Type type, size_t index, std::string cmdline, PatchInfo patch, TargetInfo target,
242 SourceInfo source, StashInfo stash)
243 : type_(type),
244 index_(index),
245 cmdline_(std::move(cmdline)),
246 patch_(std::move(patch)),
247 target_(std::move(target)),
248 source_(std::move(source)),
249 stash_(std::move(stash)) {}
250
251 // Parses the given command 'line' into a Command object and returns it. The 'index' is specified
252 // by the caller to index the object. On parsing error, it returns an empty Command object that
253 // evaluates to false, and the specific error message will be set in 'err'.
254 static Command Parse(const std::string& line, size_t index, std::string* err);
255
256 // Parses the command type from the given string.
Tao Baoc3901232018-05-21 16:05:56 -0700257 static Type ParseType(const std::string& type_str);
Tao Bao6a7e4af2018-06-14 21:57:43 -0700258
259 Type type() const {
260 return type_;
261 }
262
263 size_t index() const {
264 return index_;
265 }
266
267 const std::string& cmdline() const {
268 return cmdline_;
269 }
270
271 const PatchInfo& patch() const {
272 return patch_;
273 }
274
275 const TargetInfo& target() const {
276 return target_;
277 }
278
279 const SourceInfo& source() const {
280 return source_;
281 }
282
283 const StashInfo& stash() const {
284 return stash_;
285 }
286
287 constexpr explicit operator bool() const {
288 return type_ != Type::LAST;
289 }
290
291 private:
Tao Bao91a649a2018-05-21 16:05:56 -0700292 friend class ResumableUpdaterTest;
293 friend class UpdaterTest;
294
295 FRIEND_TEST(CommandsTest, Parse_ABORT_Allowed);
296 FRIEND_TEST(CommandsTest, Parse_InvalidNumberOfArgs);
Tao Bao6a7e4af2018-06-14 21:57:43 -0700297 FRIEND_TEST(CommandsTest, ParseTargetInfoAndSourceInfo_InvalidInput);
298 FRIEND_TEST(CommandsTest, ParseTargetInfoAndSourceInfo_StashesOnly);
299 FRIEND_TEST(CommandsTest, ParseTargetInfoAndSourceInfo_SourceBlocksAndStashes);
300 FRIEND_TEST(CommandsTest, ParseTargetInfoAndSourceInfo_SourceBlocksOnly);
301
302 // Parses the target and source info from the given 'tokens' vector. Saves the parsed info into
303 // 'target' and 'source' objects. Returns the parsing result. Error message will be set in 'err'
304 // on parsing error, and the contents in 'target' and 'source' will be undefined.
305 static bool ParseTargetInfoAndSourceInfo(const std::vector<std::string>& tokens,
306 const std::string& tgt_hash, TargetInfo* target,
307 const std::string& src_hash, SourceInfo* source,
308 std::string* err);
309
Tao Bao91a649a2018-05-21 16:05:56 -0700310 // Allows parsing ABORT command, which should be used for testing purpose only.
311 static bool abort_allowed_;
312
Tao Bao6a7e4af2018-06-14 21:57:43 -0700313 // The type of the command.
314 Type type_{ Type::LAST };
315 // The index of the Command object, which is specified by the caller.
316 size_t index_{ 0 };
317 // The input string that the Command object is parsed from.
318 std::string cmdline_;
319 // The patch info. Only meaningful for BSDIFF and IMGDIFF commands.
320 PatchInfo patch_;
321 // The target info, where the command should be written to.
322 TargetInfo target_;
323 // The source info to load the source blocks for the command.
324 SourceInfo source_;
325 // The stash info. Only meaningful for STASH and FREE commands. Note that although SourceInfo may
326 // also load data from stash, such info will be owned and managed by SourceInfo (i.e. in source_).
327 StashInfo stash_;
Tao Baoc3901232018-05-21 16:05:56 -0700328};
Tao Bao6a7e4af2018-06-14 21:57:43 -0700329
330std::ostream& operator<<(std::ostream& os, const Command& command);