blob: 85b52883bbfa83025f6174cd8d5041e60c7f71ad [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
Tianjie Xu8f64bf62018-08-07 00:22:19 -0700169// The arguments to build a hash tree from blocks on the block device.
170class HashTreeInfo {
171 public:
172 HashTreeInfo() = default;
173
174 HashTreeInfo(RangeSet hash_tree_ranges, RangeSet source_ranges, std::string hash_algorithm,
175 std::string salt_hex, std::string root_hash)
176 : hash_tree_ranges_(std::move(hash_tree_ranges)),
177 source_ranges_(std::move(source_ranges)),
178 hash_algorithm_(std::move(hash_algorithm)),
179 salt_hex_(std::move(salt_hex)),
180 root_hash_(std::move(root_hash)) {}
181
182 const RangeSet& hash_tree_ranges() const {
183 return hash_tree_ranges_;
184 }
185 const RangeSet& source_ranges() const {
186 return source_ranges_;
187 }
188
189 const std::string& hash_algorithm() const {
190 return hash_algorithm_;
191 }
192 const std::string& salt_hex() const {
193 return salt_hex_;
194 }
195 const std::string& root_hash() const {
196 return root_hash_;
197 }
198
199 bool operator==(const HashTreeInfo& other) const {
200 return hash_tree_ranges_ == other.hash_tree_ranges_ && source_ranges_ == other.source_ranges_ &&
201 hash_algorithm_ == other.hash_algorithm_ && salt_hex_ == other.salt_hex_ &&
202 root_hash_ == other.root_hash_;
203 }
204
205 private:
206 RangeSet hash_tree_ranges_;
207 RangeSet source_ranges_;
208 std::string hash_algorithm_;
209 std::string salt_hex_;
210 std::string root_hash_;
211};
212
Tao Bao6a7e4af2018-06-14 21:57:43 -0700213// Command class holds the info for an update command that performs block-based OTA (BBOTA). Each
214// command consists of one or several args, namely TargetInfo, SourceInfo, StashInfo and PatchInfo.
215// The currently used BBOTA version is v4.
216//
217// zero <tgt_ranges>
218// - Fill the indicated blocks with zeros.
219// - Meaningful args: TargetInfo
220//
221// new <tgt_ranges>
222// - Fill the blocks with data read from the new_data file.
223// - Meaningful args: TargetInfo
224//
225// erase <tgt_ranges>
226// - Mark the given blocks as empty.
227// - Meaningful args: TargetInfo
228//
229// move <hash> <...>
230// - Read the source blocks, write result to target blocks.
231// - Meaningful args: TargetInfo, SourceInfo
232//
233// See the note below for <...>.
234//
235// bsdiff <patchstart> <patchlen> <srchash> <dsthash> <...>
236// imgdiff <patchstart> <patchlen> <srchash> <dsthash> <...>
237// - Read the source blocks, apply a patch, and write result to target blocks.
238// - Meaningful args: PatchInfo, TargetInfo, SourceInfo
239//
240// It expects <...> in one of the following formats:
241//
242// <tgt_ranges> <src_block_count> - <[stash_id:stash_location] ...>
243// (loads data from stashes only)
244//
245// <tgt_ranges> <src_block_count> <src_ranges>
246// (loads data from source image only)
247//
248// <tgt_ranges> <src_block_count> <src_ranges> <src_ranges_location>
249// <[stash_id:stash_location] ...>
250// (loads data from both of source image and stashes)
251//
252// stash <stash_id> <src_ranges>
253// - Load the given source blocks and stash the data in the given slot of the stash table.
254// - Meaningful args: StashInfo
255//
256// free <stash_id>
257// - Free the given stash data.
258// - Meaningful args: StashInfo
259//
Tianjie Xu69ffa152018-08-01 16:40:00 -0700260// compute_hash_tree <hash_tree_ranges> <source_ranges> <hash_algorithm> <salt_hex> <root_hash>
261// - Computes the hash_tree bytes and writes the result to the specified range on the
262// block_device.
263//
Tao Bao91a649a2018-05-21 16:05:56 -0700264// abort
265// - Abort the current update. Allowed for testing code only.
266//
Tao Bao6a7e4af2018-06-14 21:57:43 -0700267class Command {
268 public:
Tao Baoc3901232018-05-21 16:05:56 -0700269 enum class Type {
Tao Bao91a649a2018-05-21 16:05:56 -0700270 ABORT,
Tao Baoc3901232018-05-21 16:05:56 -0700271 BSDIFF,
Tianjie Xu69ffa152018-08-01 16:40:00 -0700272 COMPUTE_HASH_TREE,
Tao Bao6a7e4af2018-06-14 21:57:43 -0700273 ERASE,
Tao Baoc3901232018-05-21 16:05:56 -0700274 FREE,
Tao Bao6a7e4af2018-06-14 21:57:43 -0700275 IMGDIFF,
276 MOVE,
277 NEW,
278 STASH,
279 ZERO,
Tao Baoc3901232018-05-21 16:05:56 -0700280 LAST, // Not a valid type.
281 };
282
Tao Bao6a7e4af2018-06-14 21:57:43 -0700283 Command() = default;
284
285 Command(Type type, size_t index, std::string cmdline, PatchInfo patch, TargetInfo target,
286 SourceInfo source, StashInfo stash)
287 : type_(type),
288 index_(index),
289 cmdline_(std::move(cmdline)),
290 patch_(std::move(patch)),
291 target_(std::move(target)),
292 source_(std::move(source)),
293 stash_(std::move(stash)) {}
294
Tianjie Xu8f64bf62018-08-07 00:22:19 -0700295 Command(Type type, size_t index, std::string cmdline, HashTreeInfo hash_tree_info);
296
Tao Bao6a7e4af2018-06-14 21:57:43 -0700297 // Parses the given command 'line' into a Command object and returns it. The 'index' is specified
298 // by the caller to index the object. On parsing error, it returns an empty Command object that
299 // evaluates to false, and the specific error message will be set in 'err'.
300 static Command Parse(const std::string& line, size_t index, std::string* err);
301
302 // Parses the command type from the given string.
Tao Baoc3901232018-05-21 16:05:56 -0700303 static Type ParseType(const std::string& type_str);
Tao Bao6a7e4af2018-06-14 21:57:43 -0700304
305 Type type() const {
306 return type_;
307 }
308
309 size_t index() const {
310 return index_;
311 }
312
313 const std::string& cmdline() const {
314 return cmdline_;
315 }
316
317 const PatchInfo& patch() const {
318 return patch_;
319 }
320
321 const TargetInfo& target() const {
322 return target_;
323 }
324
325 const SourceInfo& source() const {
326 return source_;
327 }
328
329 const StashInfo& stash() const {
330 return stash_;
331 }
332
Tianjie Xu8f64bf62018-08-07 00:22:19 -0700333 const HashTreeInfo& hash_tree_info() const {
334 return hash_tree_info_;
335 }
336
Tao Bao6a7e4af2018-06-14 21:57:43 -0700337 constexpr explicit operator bool() const {
338 return type_ != Type::LAST;
339 }
340
341 private:
Tao Bao91a649a2018-05-21 16:05:56 -0700342 friend class ResumableUpdaterTest;
343 friend class UpdaterTest;
344
345 FRIEND_TEST(CommandsTest, Parse_ABORT_Allowed);
346 FRIEND_TEST(CommandsTest, Parse_InvalidNumberOfArgs);
Tao Bao6a7e4af2018-06-14 21:57:43 -0700347 FRIEND_TEST(CommandsTest, ParseTargetInfoAndSourceInfo_InvalidInput);
348 FRIEND_TEST(CommandsTest, ParseTargetInfoAndSourceInfo_StashesOnly);
349 FRIEND_TEST(CommandsTest, ParseTargetInfoAndSourceInfo_SourceBlocksAndStashes);
350 FRIEND_TEST(CommandsTest, ParseTargetInfoAndSourceInfo_SourceBlocksOnly);
351
352 // Parses the target and source info from the given 'tokens' vector. Saves the parsed info into
353 // 'target' and 'source' objects. Returns the parsing result. Error message will be set in 'err'
354 // on parsing error, and the contents in 'target' and 'source' will be undefined.
355 static bool ParseTargetInfoAndSourceInfo(const std::vector<std::string>& tokens,
356 const std::string& tgt_hash, TargetInfo* target,
357 const std::string& src_hash, SourceInfo* source,
358 std::string* err);
359
Tao Bao91a649a2018-05-21 16:05:56 -0700360 // Allows parsing ABORT command, which should be used for testing purpose only.
361 static bool abort_allowed_;
362
Tao Bao6a7e4af2018-06-14 21:57:43 -0700363 // The type of the command.
364 Type type_{ Type::LAST };
365 // The index of the Command object, which is specified by the caller.
366 size_t index_{ 0 };
367 // The input string that the Command object is parsed from.
368 std::string cmdline_;
369 // The patch info. Only meaningful for BSDIFF and IMGDIFF commands.
370 PatchInfo patch_;
371 // The target info, where the command should be written to.
372 TargetInfo target_;
373 // The source info to load the source blocks for the command.
374 SourceInfo source_;
375 // The stash info. Only meaningful for STASH and FREE commands. Note that although SourceInfo may
376 // also load data from stash, such info will be owned and managed by SourceInfo (i.e. in source_).
377 StashInfo stash_;
Tianjie Xu8f64bf62018-08-07 00:22:19 -0700378 // The hash_tree info. Only meaningful for COMPUTE_HASH_TREE.
379 HashTreeInfo hash_tree_info_;
Tao Baoc3901232018-05-21 16:05:56 -0700380};
Tao Bao6a7e4af2018-06-14 21:57:43 -0700381
382std::ostream& operator<<(std::ostream& os, const Command& command);