1 /*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25 #include <iostream>
26
27 #include <endian.h>
28 #include <errno.h>
29 #include <inttypes.h>
30 #include <string.h>
31
32 #include <fcntl.h>
33 #include <sys/stat.h>
34 #include <sys/types.h>
35 #include <unistd.h>
36
37 #include <base/files/file_util.h>
38 #include <base/strings/string_util.h>
39 #include <base/strings/stringprintf.h>
40 #include <openssl/rand.h>
41 #include <openssl/sha.h>
42
43 #include "fake_avb_ops.h"
44
45 namespace avb {
46
get_partition_names_read_from()47 std::set<std::string> FakeAvbOps::get_partition_names_read_from() {
48 return partition_names_read_from_;
49 }
50
preload_partition(const std::string & partition,const base::FilePath & path)51 bool FakeAvbOps::preload_partition(const std::string& partition,
52 const base::FilePath& path) {
53 if (preloaded_partitions_.count(partition) > 0) {
54 fprintf(stderr, "Partition '%s' already preloaded\n", partition.c_str());
55 return false;
56 }
57
58 int64_t file_size;
59 if (!base::GetFileSize(path, &file_size)) {
60 fprintf(stderr, "Error getting size of file '%s'\n", path.value().c_str());
61 return false;
62 }
63
64 int fd = open(path.value().c_str(), O_RDONLY);
65 if (fd < 0) {
66 fprintf(stderr,
67 "Error opening file '%s': %s\n",
68 path.value().c_str(),
69 strerror(errno));
70 return false;
71 }
72
73 uint8_t* buffer = static_cast<uint8_t*>(malloc(file_size));
74 ssize_t num_read = read(fd, buffer, file_size);
75 if (num_read != file_size) {
76 fprintf(stderr,
77 "Error reading %zd bytes from file '%s': %s\n",
78 file_size,
79 path.value().c_str(),
80 strerror(errno));
81 free(buffer);
82 return false;
83 }
84 close(fd);
85
86 preloaded_partitions_[partition] = buffer;
87 return true;
88 }
89
read_from_partition(const char * partition,int64_t offset,size_t num_bytes,void * buffer,size_t * out_num_read)90 AvbIOResult FakeAvbOps::read_from_partition(const char* partition,
91 int64_t offset,
92 size_t num_bytes,
93 void* buffer,
94 size_t* out_num_read) {
95 if (hidden_partitions_.find(partition) != hidden_partitions_.end()) {
96 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
97 }
98
99 base::FilePath path =
100 partition_dir_.Append(std::string(partition)).AddExtension("img");
101
102 partition_names_read_from_.insert(partition);
103
104 if (offset < 0) {
105 int64_t file_size;
106 if (!base::GetFileSize(path, &file_size)) {
107 fprintf(
108 stderr, "Error getting size of file '%s'\n", path.value().c_str());
109 return AVB_IO_RESULT_ERROR_IO;
110 }
111 offset = file_size - (-offset);
112 }
113
114 int fd = open(path.value().c_str(), O_RDONLY);
115 if (fd < 0) {
116 fprintf(stderr,
117 "Error opening file '%s': %s\n",
118 path.value().c_str(),
119 strerror(errno));
120 if (errno == ENOENT) {
121 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
122 } else {
123 return AVB_IO_RESULT_ERROR_IO;
124 }
125 }
126 if (lseek(fd, offset, SEEK_SET) != offset) {
127 fprintf(stderr,
128 "Error seeking to pos %zd in file %s: %s\n",
129 offset,
130 path.value().c_str(),
131 strerror(errno));
132 close(fd);
133 return AVB_IO_RESULT_ERROR_IO;
134 }
135 ssize_t num_read = read(fd, buffer, num_bytes);
136 if (num_read < 0) {
137 fprintf(stderr,
138 "Error reading %zd bytes from pos %" PRId64 " in file %s: %s\n",
139 num_bytes,
140 offset,
141 path.value().c_str(),
142 strerror(errno));
143 close(fd);
144 return AVB_IO_RESULT_ERROR_IO;
145 }
146 close(fd);
147
148 if (out_num_read != NULL) {
149 *out_num_read = num_read;
150 }
151
152 return AVB_IO_RESULT_OK;
153 }
154
get_preloaded_partition(const char * partition,size_t num_bytes,uint8_t ** out_pointer,size_t * out_num_bytes_preloaded)155 AvbIOResult FakeAvbOps::get_preloaded_partition(
156 const char* partition,
157 size_t num_bytes,
158 uint8_t** out_pointer,
159 size_t* out_num_bytes_preloaded) {
160 if (hidden_partitions_.find(partition) != hidden_partitions_.end()) {
161 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
162 }
163 std::map<std::string, uint8_t*>::iterator it =
164 preloaded_partitions_.find(std::string(partition));
165 if (it == preloaded_partitions_.end()) {
166 *out_pointer = NULL;
167 *out_num_bytes_preloaded = 0;
168 return AVB_IO_RESULT_OK;
169 }
170
171 uint64_t size;
172 AvbIOResult result = get_size_of_partition(avb_ops(), partition, &size);
173 if (result != AVB_IO_RESULT_OK) {
174 return result;
175 }
176 if (size != num_bytes) {
177 return AVB_IO_RESULT_ERROR_IO;
178 }
179
180 *out_num_bytes_preloaded = num_bytes;
181 *out_pointer = it->second;
182 return AVB_IO_RESULT_OK;
183 }
184
write_to_partition(const char * partition,int64_t offset,size_t num_bytes,const void * buffer)185 AvbIOResult FakeAvbOps::write_to_partition(const char* partition,
186 int64_t offset,
187 size_t num_bytes,
188 const void* buffer) {
189 if (hidden_partitions_.find(partition) != hidden_partitions_.end()) {
190 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
191 }
192
193 base::FilePath path =
194 partition_dir_.Append(std::string(partition)).AddExtension("img");
195
196 if (offset < 0) {
197 int64_t file_size;
198 if (!base::GetFileSize(path, &file_size)) {
199 fprintf(
200 stderr, "Error getting size of file '%s'\n", path.value().c_str());
201 return AVB_IO_RESULT_ERROR_IO;
202 }
203 offset = file_size - (-offset);
204 }
205
206 int fd = open(path.value().c_str(), O_WRONLY);
207 if (fd < 0) {
208 fprintf(stderr,
209 "Error opening file '%s': %s\n",
210 path.value().c_str(),
211 strerror(errno));
212 if (errno == ENOENT) {
213 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
214 } else {
215 return AVB_IO_RESULT_ERROR_IO;
216 }
217 }
218 if (lseek(fd, offset, SEEK_SET) != offset) {
219 fprintf(stderr,
220 "Error seeking to pos %zd in file %s: %s\n",
221 offset,
222 path.value().c_str(),
223 strerror(errno));
224 close(fd);
225 return AVB_IO_RESULT_ERROR_IO;
226 }
227 ssize_t num_written = write(fd, buffer, num_bytes);
228 if (num_written < 0) {
229 fprintf(stderr,
230 "Error writing %zd bytes at pos %" PRId64 " in file %s: %s\n",
231 num_bytes,
232 offset,
233 path.value().c_str(),
234 strerror(errno));
235 close(fd);
236 return AVB_IO_RESULT_ERROR_IO;
237 }
238 close(fd);
239
240 return AVB_IO_RESULT_OK;
241 }
242
validate_vbmeta_public_key(AvbOps * ops,const uint8_t * public_key_data,size_t public_key_length,const uint8_t * public_key_metadata,size_t public_key_metadata_length,bool * out_key_is_trusted)243 AvbIOResult FakeAvbOps::validate_vbmeta_public_key(
244 AvbOps* ops,
245 const uint8_t* public_key_data,
246 size_t public_key_length,
247 const uint8_t* public_key_metadata,
248 size_t public_key_metadata_length,
249 bool* out_key_is_trusted) {
250 if (out_key_is_trusted != NULL) {
251 bool pk_matches = (public_key_length == expected_public_key_.size() &&
252 (memcmp(expected_public_key_.c_str(),
253 public_key_data,
254 public_key_length) == 0));
255 bool pkmd_matches =
256 (public_key_metadata_length == expected_public_key_metadata_.size() &&
257 (memcmp(expected_public_key_metadata_.c_str(),
258 public_key_metadata,
259 public_key_metadata_length) == 0));
260 *out_key_is_trusted = pk_matches && pkmd_matches;
261 }
262 return AVB_IO_RESULT_OK;
263 }
264
read_rollback_index(AvbOps * ops,size_t rollback_index_location,uint64_t * out_rollback_index)265 AvbIOResult FakeAvbOps::read_rollback_index(AvbOps* ops,
266 size_t rollback_index_location,
267 uint64_t* out_rollback_index) {
268 if (stored_rollback_indexes_.count(rollback_index_location) == 0) {
269 fprintf(stderr,
270 "No rollback index for location %zd (has %zd locations).\n",
271 rollback_index_location,
272 stored_rollback_indexes_.size());
273 return AVB_IO_RESULT_ERROR_IO;
274 }
275 *out_rollback_index = stored_rollback_indexes_[rollback_index_location];
276 return AVB_IO_RESULT_OK;
277 }
278
write_rollback_index(AvbOps * ops,size_t rollback_index_location,uint64_t rollback_index)279 AvbIOResult FakeAvbOps::write_rollback_index(AvbOps* ops,
280 size_t rollback_index_location,
281 uint64_t rollback_index) {
282 if (stored_rollback_indexes_.count(rollback_index_location) == 0) {
283 fprintf(stderr,
284 "No rollback index for location %zd (has %zd locations).\n",
285 rollback_index_location,
286 stored_rollback_indexes_.size());
287 return AVB_IO_RESULT_ERROR_IO;
288 }
289 stored_rollback_indexes_[rollback_index_location] = rollback_index;
290 return AVB_IO_RESULT_OK;
291 }
292
read_is_device_unlocked(AvbOps * ops,bool * out_is_device_unlocked)293 AvbIOResult FakeAvbOps::read_is_device_unlocked(AvbOps* ops,
294 bool* out_is_device_unlocked) {
295 *out_is_device_unlocked = stored_is_device_unlocked_ ? 1 : 0;
296 return AVB_IO_RESULT_OK;
297 }
298
get_unique_guid_for_partition(AvbOps * ops,const char * partition,char * guid_buf,size_t guid_buf_size)299 AvbIOResult FakeAvbOps::get_unique_guid_for_partition(AvbOps* ops,
300 const char* partition,
301 char* guid_buf,
302 size_t guid_buf_size) {
303 if (hidden_partitions_.find(partition) != hidden_partitions_.end()) {
304 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
305 }
306 // This is faking it a bit but makes testing easy. It works
307 // because avb_slot_verify.c doesn't check that the returned GUID
308 // is wellformed.
309 snprintf(guid_buf, guid_buf_size, "1234-fake-guid-for:%s", partition);
310 return AVB_IO_RESULT_OK;
311 }
312
get_size_of_partition(AvbOps * ops,const char * partition,uint64_t * out_size)313 AvbIOResult FakeAvbOps::get_size_of_partition(AvbOps* ops,
314 const char* partition,
315 uint64_t* out_size) {
316 if (hidden_partitions_.find(partition) != hidden_partitions_.end()) {
317 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
318 }
319
320 base::FilePath path =
321 partition_dir_.Append(std::string(partition)).AddExtension("img");
322
323 int64_t file_size;
324 if (!base::GetFileSize(path, &file_size)) {
325 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
326 }
327 *out_size = file_size;
328 return AVB_IO_RESULT_OK;
329 }
330
read_persistent_value(const char * name,size_t buffer_size,uint8_t * out_buffer,size_t * out_num_bytes_read)331 AvbIOResult FakeAvbOps::read_persistent_value(const char* name,
332 size_t buffer_size,
333 uint8_t* out_buffer,
334 size_t* out_num_bytes_read) {
335 if (out_buffer == NULL && buffer_size > 0) {
336 return AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE;
337 }
338 if (stored_values_.count(name) == 0) {
339 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
340 }
341 if (stored_values_[name].size() > buffer_size) {
342 *out_num_bytes_read = stored_values_[name].size();
343 return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE;
344 }
345 memcpy(out_buffer, stored_values_[name].data(), stored_values_[name].size());
346 *out_num_bytes_read = stored_values_[name].size();
347 return AVB_IO_RESULT_OK;
348 }
349
write_persistent_value(const char * name,size_t value_size,const uint8_t * value)350 AvbIOResult FakeAvbOps::write_persistent_value(const char* name,
351 size_t value_size,
352 const uint8_t* value) {
353 stored_values_[name] =
354 std::string(reinterpret_cast<const char*>(value), value_size);
355 return AVB_IO_RESULT_OK;
356 }
357
read_permanent_attributes(AvbAtxPermanentAttributes * attributes)358 AvbIOResult FakeAvbOps::read_permanent_attributes(
359 AvbAtxPermanentAttributes* attributes) {
360 *attributes = permanent_attributes_;
361 return AVB_IO_RESULT_OK;
362 }
363
read_permanent_attributes_hash(uint8_t hash[AVB_SHA256_DIGEST_SIZE])364 AvbIOResult FakeAvbOps::read_permanent_attributes_hash(
365 uint8_t hash[AVB_SHA256_DIGEST_SIZE]) {
366 if (permanent_attributes_hash_.empty()) {
367 SHA256(reinterpret_cast<const unsigned char*>(&permanent_attributes_),
368 sizeof(AvbAtxPermanentAttributes),
369 hash);
370 return AVB_IO_RESULT_OK;
371 }
372 memset(hash, 0, AVB_SHA256_DIGEST_SIZE);
373 permanent_attributes_hash_.copy(reinterpret_cast<char*>(hash),
374 AVB_SHA256_DIGEST_SIZE);
375 return AVB_IO_RESULT_OK;
376 }
377
set_key_version(size_t rollback_index_location,uint64_t key_version)378 void FakeAvbOps::set_key_version(size_t rollback_index_location,
379 uint64_t key_version) {
380 verified_rollback_indexes_[rollback_index_location] = key_version;
381 }
382
get_random(size_t num_bytes,uint8_t * output)383 AvbIOResult FakeAvbOps::get_random(size_t num_bytes, uint8_t* output) {
384 if (!RAND_bytes(output, num_bytes)) {
385 return AVB_IO_RESULT_ERROR_IO;
386 }
387 return AVB_IO_RESULT_OK;
388 }
389
my_ops_read_from_partition(AvbOps * ops,const char * partition,int64_t offset,size_t num_bytes,void * buffer,size_t * out_num_read)390 static AvbIOResult my_ops_read_from_partition(AvbOps* ops,
391 const char* partition,
392 int64_t offset,
393 size_t num_bytes,
394 void* buffer,
395 size_t* out_num_read) {
396 return FakeAvbOps::GetInstanceFromAvbOps(ops)
397 ->delegate()
398 ->read_from_partition(partition, offset, num_bytes, buffer, out_num_read);
399 }
400
my_ops_get_preloaded_partition(AvbOps * ops,const char * partition,size_t num_bytes,uint8_t ** out_pointer,size_t * out_num_bytes_preloaded)401 static AvbIOResult my_ops_get_preloaded_partition(
402 AvbOps* ops,
403 const char* partition,
404 size_t num_bytes,
405 uint8_t** out_pointer,
406 size_t* out_num_bytes_preloaded) {
407 return FakeAvbOps::GetInstanceFromAvbOps(ops)
408 ->delegate()
409 ->get_preloaded_partition(
410 partition, num_bytes, out_pointer, out_num_bytes_preloaded);
411 }
412
my_ops_write_to_partition(AvbOps * ops,const char * partition,int64_t offset,size_t num_bytes,const void * buffer)413 static AvbIOResult my_ops_write_to_partition(AvbOps* ops,
414 const char* partition,
415 int64_t offset,
416 size_t num_bytes,
417 const void* buffer) {
418 return FakeAvbOps::GetInstanceFromAvbOps(ops)->delegate()->write_to_partition(
419 partition, offset, num_bytes, buffer);
420 }
421
my_ops_validate_vbmeta_public_key(AvbOps * ops,const uint8_t * public_key_data,size_t public_key_length,const uint8_t * public_key_metadata,size_t public_key_metadata_length,bool * out_key_is_trusted)422 static AvbIOResult my_ops_validate_vbmeta_public_key(
423 AvbOps* ops,
424 const uint8_t* public_key_data,
425 size_t public_key_length,
426 const uint8_t* public_key_metadata,
427 size_t public_key_metadata_length,
428 bool* out_key_is_trusted) {
429 return FakeAvbOps::GetInstanceFromAvbOps(ops)
430 ->delegate()
431 ->validate_vbmeta_public_key(ops,
432 public_key_data,
433 public_key_length,
434 public_key_metadata,
435 public_key_metadata_length,
436 out_key_is_trusted);
437 }
438
my_ops_read_rollback_index(AvbOps * ops,size_t rollback_index_location,uint64_t * out_rollback_index)439 static AvbIOResult my_ops_read_rollback_index(AvbOps* ops,
440 size_t rollback_index_location,
441 uint64_t* out_rollback_index) {
442 return FakeAvbOps::GetInstanceFromAvbOps(ops)
443 ->delegate()
444 ->read_rollback_index(ops, rollback_index_location, out_rollback_index);
445 }
446
my_ops_write_rollback_index(AvbOps * ops,size_t rollback_index_location,uint64_t rollback_index)447 static AvbIOResult my_ops_write_rollback_index(AvbOps* ops,
448 size_t rollback_index_location,
449 uint64_t rollback_index) {
450 return FakeAvbOps::GetInstanceFromAvbOps(ops)
451 ->delegate()
452 ->write_rollback_index(ops, rollback_index_location, rollback_index);
453 }
454
my_ops_read_is_device_unlocked(AvbOps * ops,bool * out_is_device_unlocked)455 static AvbIOResult my_ops_read_is_device_unlocked(
456 AvbOps* ops, bool* out_is_device_unlocked) {
457 return FakeAvbOps::GetInstanceFromAvbOps(ops)
458 ->delegate()
459 ->read_is_device_unlocked(ops, out_is_device_unlocked);
460 }
461
my_ops_get_unique_guid_for_partition(AvbOps * ops,const char * partition,char * guid_buf,size_t guid_buf_size)462 static AvbIOResult my_ops_get_unique_guid_for_partition(AvbOps* ops,
463 const char* partition,
464 char* guid_buf,
465 size_t guid_buf_size) {
466 return FakeAvbOps::GetInstanceFromAvbOps(ops)
467 ->delegate()
468 ->get_unique_guid_for_partition(ops, partition, guid_buf, guid_buf_size);
469 }
470
my_ops_get_size_of_partition(AvbOps * ops,const char * partition,uint64_t * out_size)471 static AvbIOResult my_ops_get_size_of_partition(AvbOps* ops,
472 const char* partition,
473 uint64_t* out_size) {
474 return FakeAvbOps::GetInstanceFromAvbOps(ops)
475 ->delegate()
476 ->get_size_of_partition(ops, partition, out_size);
477 }
478
my_ops_read_persistent_value(AvbOps * ops,const char * name,size_t buffer_size,uint8_t * out_buffer,size_t * out_num_bytes_read)479 static AvbIOResult my_ops_read_persistent_value(AvbOps* ops,
480 const char* name,
481 size_t buffer_size,
482 uint8_t* out_buffer,
483 size_t* out_num_bytes_read) {
484 return FakeAvbOps::GetInstanceFromAvbOps(ops)
485 ->delegate()
486 ->read_persistent_value(
487 name, buffer_size, out_buffer, out_num_bytes_read);
488 }
489
my_ops_write_persistent_value(AvbOps * ops,const char * name,size_t value_size,const uint8_t * value)490 static AvbIOResult my_ops_write_persistent_value(AvbOps* ops,
491 const char* name,
492 size_t value_size,
493 const uint8_t* value) {
494 return FakeAvbOps::GetInstanceFromAvbOps(ops)
495 ->delegate()
496 ->write_persistent_value(name, value_size, value);
497 }
498
my_ops_read_permanent_attributes(AvbAtxOps * atx_ops,AvbAtxPermanentAttributes * attributes)499 static AvbIOResult my_ops_read_permanent_attributes(
500 AvbAtxOps* atx_ops, AvbAtxPermanentAttributes* attributes) {
501 return FakeAvbOps::GetInstanceFromAvbOps(atx_ops->ops)
502 ->delegate()
503 ->read_permanent_attributes(attributes);
504 }
505
my_ops_read_permanent_attributes_hash(AvbAtxOps * atx_ops,uint8_t hash[AVB_SHA256_DIGEST_SIZE])506 static AvbIOResult my_ops_read_permanent_attributes_hash(
507 AvbAtxOps* atx_ops, uint8_t hash[AVB_SHA256_DIGEST_SIZE]) {
508 return FakeAvbOps::GetInstanceFromAvbOps(atx_ops->ops)
509 ->delegate()
510 ->read_permanent_attributes_hash(hash);
511 }
512
my_ops_set_key_version(AvbAtxOps * atx_ops,size_t rollback_index_location,uint64_t key_version)513 static void my_ops_set_key_version(AvbAtxOps* atx_ops,
514 size_t rollback_index_location,
515 uint64_t key_version) {
516 return FakeAvbOps::GetInstanceFromAvbOps(atx_ops->ops)
517 ->delegate()
518 ->set_key_version(rollback_index_location, key_version);
519 }
520
my_ops_get_random(AvbAtxOps * atx_ops,size_t num_bytes,uint8_t * output)521 static AvbIOResult my_ops_get_random(AvbAtxOps* atx_ops,
522 size_t num_bytes,
523 uint8_t* output) {
524 return FakeAvbOps::GetInstanceFromAvbOps(atx_ops->ops)
525 ->delegate()
526 ->get_random(num_bytes, output);
527 }
528
FakeAvbOps()529 FakeAvbOps::FakeAvbOps() {
530 memset(&avb_ops_, 0, sizeof(avb_ops_));
531 avb_ops_.ab_ops = &avb_ab_ops_;
532 avb_ops_.atx_ops = &avb_atx_ops_;
533 avb_ops_.user_data = this;
534 avb_ops_.read_from_partition = my_ops_read_from_partition;
535 avb_ops_.write_to_partition = my_ops_write_to_partition;
536 avb_ops_.validate_vbmeta_public_key = my_ops_validate_vbmeta_public_key;
537 avb_ops_.read_rollback_index = my_ops_read_rollback_index;
538 avb_ops_.write_rollback_index = my_ops_write_rollback_index;
539 avb_ops_.read_is_device_unlocked = my_ops_read_is_device_unlocked;
540 avb_ops_.get_unique_guid_for_partition = my_ops_get_unique_guid_for_partition;
541 avb_ops_.get_size_of_partition = my_ops_get_size_of_partition;
542 avb_ops_.read_persistent_value = my_ops_read_persistent_value;
543 avb_ops_.write_persistent_value = my_ops_write_persistent_value;
544
545 // Just use the built-in A/B metadata read/write routines.
546 avb_ab_ops_.ops = &avb_ops_;
547 avb_ab_ops_.read_ab_metadata = avb_ab_data_read;
548 avb_ab_ops_.write_ab_metadata = avb_ab_data_write;
549
550 avb_atx_ops_.ops = &avb_ops_;
551 avb_atx_ops_.read_permanent_attributes = my_ops_read_permanent_attributes;
552 avb_atx_ops_.read_permanent_attributes_hash =
553 my_ops_read_permanent_attributes_hash;
554 avb_atx_ops_.set_key_version = my_ops_set_key_version;
555 avb_atx_ops_.get_random = my_ops_get_random;
556
557 delegate_ = this;
558 }
559
~FakeAvbOps()560 FakeAvbOps::~FakeAvbOps() {
561 std::map<std::string, uint8_t*>::iterator it;
562 for (it = preloaded_partitions_.begin(); it != preloaded_partitions_.end();
563 it++) {
564 free(it->second);
565 }
566 }
567
enable_get_preloaded_partition()568 void FakeAvbOps::enable_get_preloaded_partition() {
569 avb_ops_.get_preloaded_partition = my_ops_get_preloaded_partition;
570 }
571
572 } // namespace avb
573