blob: 784892fb53288ff4e4241192a03bbb05208395d5 [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//
216class Command {
217 public:
Tao Baoc3901232018-05-21 16:05:56 -0700218 enum class Type {
Tao Baoc3901232018-05-21 16:05:56 -0700219 BSDIFF,
Tao Bao6a7e4af2018-06-14 21:57:43 -0700220 ERASE,
Tao Baoc3901232018-05-21 16:05:56 -0700221 FREE,
Tao Bao6a7e4af2018-06-14 21:57:43 -0700222 IMGDIFF,
223 MOVE,
224 NEW,
225 STASH,
226 ZERO,
Tao Baoc3901232018-05-21 16:05:56 -0700227 LAST, // Not a valid type.
228 };
229
Tao Bao6a7e4af2018-06-14 21:57:43 -0700230 Command() = default;
231
232 Command(Type type, size_t index, std::string cmdline, PatchInfo patch, TargetInfo target,
233 SourceInfo source, StashInfo stash)
234 : type_(type),
235 index_(index),
236 cmdline_(std::move(cmdline)),
237 patch_(std::move(patch)),
238 target_(std::move(target)),
239 source_(std::move(source)),
240 stash_(std::move(stash)) {}
241
242 // Parses the given command 'line' into a Command object and returns it. The 'index' is specified
243 // by the caller to index the object. On parsing error, it returns an empty Command object that
244 // evaluates to false, and the specific error message will be set in 'err'.
245 static Command Parse(const std::string& line, size_t index, std::string* err);
246
247 // Parses the command type from the given string.
Tao Baoc3901232018-05-21 16:05:56 -0700248 static Type ParseType(const std::string& type_str);
Tao Bao6a7e4af2018-06-14 21:57:43 -0700249
250 Type type() const {
251 return type_;
252 }
253
254 size_t index() const {
255 return index_;
256 }
257
258 const std::string& cmdline() const {
259 return cmdline_;
260 }
261
262 const PatchInfo& patch() const {
263 return patch_;
264 }
265
266 const TargetInfo& target() const {
267 return target_;
268 }
269
270 const SourceInfo& source() const {
271 return source_;
272 }
273
274 const StashInfo& stash() const {
275 return stash_;
276 }
277
278 constexpr explicit operator bool() const {
279 return type_ != Type::LAST;
280 }
281
282 private:
283 FRIEND_TEST(CommandsTest, ParseTargetInfoAndSourceInfo_InvalidInput);
284 FRIEND_TEST(CommandsTest, ParseTargetInfoAndSourceInfo_StashesOnly);
285 FRIEND_TEST(CommandsTest, ParseTargetInfoAndSourceInfo_SourceBlocksAndStashes);
286 FRIEND_TEST(CommandsTest, ParseTargetInfoAndSourceInfo_SourceBlocksOnly);
287
288 // Parses the target and source info from the given 'tokens' vector. Saves the parsed info into
289 // 'target' and 'source' objects. Returns the parsing result. Error message will be set in 'err'
290 // on parsing error, and the contents in 'target' and 'source' will be undefined.
291 static bool ParseTargetInfoAndSourceInfo(const std::vector<std::string>& tokens,
292 const std::string& tgt_hash, TargetInfo* target,
293 const std::string& src_hash, SourceInfo* source,
294 std::string* err);
295
296 // The type of the command.
297 Type type_{ Type::LAST };
298 // The index of the Command object, which is specified by the caller.
299 size_t index_{ 0 };
300 // The input string that the Command object is parsed from.
301 std::string cmdline_;
302 // The patch info. Only meaningful for BSDIFF and IMGDIFF commands.
303 PatchInfo patch_;
304 // The target info, where the command should be written to.
305 TargetInfo target_;
306 // The source info to load the source blocks for the command.
307 SourceInfo source_;
308 // The stash info. Only meaningful for STASH and FREE commands. Note that although SourceInfo may
309 // also load data from stash, such info will be owned and managed by SourceInfo (i.e. in source_).
310 StashInfo stash_;
Tao Baoc3901232018-05-21 16:05:56 -0700311};
Tao Bao6a7e4af2018-06-14 21:57:43 -0700312
313std::ostream& operator<<(std::ostream& os, const Command& command);