• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/sha.h>
41 
42 #include "fake_avb_ops.h"
43 
44 namespace avb {
45 
get_partition_names_read_from()46 std::set<std::string> FakeAvbOps::get_partition_names_read_from() {
47   return partition_names_read_from_;
48 }
49 
preload_partition(const std::string & partition,const base::FilePath & path)50 bool FakeAvbOps::preload_partition(const std::string& partition,
51                                    const base::FilePath& path) {
52   if (preloaded_partitions_.count(partition) > 0) {
53     fprintf(stderr, "Partition '%s' already preloaded\n", partition.c_str());
54     return false;
55   }
56 
57   int64_t file_size;
58   if (!base::GetFileSize(path, &file_size)) {
59     fprintf(stderr, "Error getting size of file '%s'\n", path.value().c_str());
60     return false;
61   }
62 
63   int fd = open(path.value().c_str(), O_RDONLY);
64   if (fd < 0) {
65     fprintf(stderr,
66             "Error opening file '%s': %s\n",
67             path.value().c_str(),
68             strerror(errno));
69     return false;
70   }
71 
72   uint8_t* buffer = static_cast<uint8_t*>(malloc(file_size));
73   ssize_t num_read = read(fd, buffer, file_size);
74   if (num_read != file_size) {
75     fprintf(stderr,
76             "Error reading %zd bytes from file '%s': %s\n",
77             file_size,
78             path.value().c_str(),
79             strerror(errno));
80     free(buffer);
81     return false;
82   }
83   close(fd);
84 
85   preloaded_partitions_[partition] = buffer;
86   return true;
87 }
88 
read_from_partition(const char * partition,int64_t offset,size_t num_bytes,void * buffer,size_t * out_num_read)89 AvbIOResult FakeAvbOps::read_from_partition(const char* partition,
90                                             int64_t offset,
91                                             size_t num_bytes,
92                                             void* buffer,
93                                             size_t* out_num_read) {
94   base::FilePath path =
95       partition_dir_.Append(std::string(partition)).AddExtension("img");
96 
97   partition_names_read_from_.insert(partition);
98 
99   if (offset < 0) {
100     int64_t file_size;
101     if (!base::GetFileSize(path, &file_size)) {
102       fprintf(
103           stderr, "Error getting size of file '%s'\n", path.value().c_str());
104       return AVB_IO_RESULT_ERROR_IO;
105     }
106     offset = file_size - (-offset);
107   }
108 
109   int fd = open(path.value().c_str(), O_RDONLY);
110   if (fd < 0) {
111     fprintf(stderr,
112             "Error opening file '%s': %s\n",
113             path.value().c_str(),
114             strerror(errno));
115     if (errno == ENOENT) {
116       return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
117     } else {
118       return AVB_IO_RESULT_ERROR_IO;
119     }
120   }
121   if (lseek(fd, offset, SEEK_SET) != offset) {
122     fprintf(stderr,
123             "Error seeking to pos %zd in file %s: %s\n",
124             offset,
125             path.value().c_str(),
126             strerror(errno));
127     close(fd);
128     return AVB_IO_RESULT_ERROR_IO;
129   }
130   ssize_t num_read = read(fd, buffer, num_bytes);
131   if (num_read < 0) {
132     fprintf(stderr,
133             "Error reading %zd bytes from pos %" PRId64 " in file %s: %s\n",
134             num_bytes,
135             offset,
136             path.value().c_str(),
137             strerror(errno));
138     close(fd);
139     return AVB_IO_RESULT_ERROR_IO;
140   }
141   close(fd);
142 
143   if (out_num_read != NULL) {
144     *out_num_read = num_read;
145   }
146 
147   return AVB_IO_RESULT_OK;
148 }
149 
get_preloaded_partition(const char * partition,size_t num_bytes,uint8_t ** out_pointer,size_t * out_num_bytes_preloaded)150 AvbIOResult FakeAvbOps::get_preloaded_partition(
151     const char* partition,
152     size_t num_bytes,
153     uint8_t** out_pointer,
154     size_t* out_num_bytes_preloaded) {
155   std::map<std::string, uint8_t*>::iterator it =
156       preloaded_partitions_.find(std::string(partition));
157   if (it == preloaded_partitions_.end()) {
158     *out_pointer = NULL;
159     *out_num_bytes_preloaded = 0;
160     return AVB_IO_RESULT_OK;
161   }
162 
163   uint64_t size;
164   AvbIOResult result = get_size_of_partition(avb_ops(), partition, &size);
165   if (result != AVB_IO_RESULT_OK) {
166     return result;
167   }
168   if (size != num_bytes) {
169     return AVB_IO_RESULT_ERROR_IO;
170   }
171 
172   *out_num_bytes_preloaded = num_bytes;
173   *out_pointer = it->second;
174   return AVB_IO_RESULT_OK;
175 }
176 
write_to_partition(const char * partition,int64_t offset,size_t num_bytes,const void * buffer)177 AvbIOResult FakeAvbOps::write_to_partition(const char* partition,
178                                            int64_t offset,
179                                            size_t num_bytes,
180                                            const void* buffer) {
181   base::FilePath path =
182       partition_dir_.Append(std::string(partition)).AddExtension("img");
183 
184   if (offset < 0) {
185     int64_t file_size;
186     if (!base::GetFileSize(path, &file_size)) {
187       fprintf(
188           stderr, "Error getting size of file '%s'\n", path.value().c_str());
189       return AVB_IO_RESULT_ERROR_IO;
190     }
191     offset = file_size - (-offset);
192   }
193 
194   int fd = open(path.value().c_str(), O_WRONLY);
195   if (fd < 0) {
196     fprintf(stderr,
197             "Error opening file '%s': %s\n",
198             path.value().c_str(),
199             strerror(errno));
200     if (errno == ENOENT) {
201       return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
202     } else {
203       return AVB_IO_RESULT_ERROR_IO;
204     }
205   }
206   if (lseek(fd, offset, SEEK_SET) != offset) {
207     fprintf(stderr,
208             "Error seeking to pos %zd in file %s: %s\n",
209             offset,
210             path.value().c_str(),
211             strerror(errno));
212     close(fd);
213     return AVB_IO_RESULT_ERROR_IO;
214   }
215   ssize_t num_written = write(fd, buffer, num_bytes);
216   if (num_written < 0) {
217     fprintf(stderr,
218             "Error writing %zd bytes at pos %" PRId64 " in file %s: %s\n",
219             num_bytes,
220             offset,
221             path.value().c_str(),
222             strerror(errno));
223     close(fd);
224     return AVB_IO_RESULT_ERROR_IO;
225   }
226   close(fd);
227 
228   return AVB_IO_RESULT_OK;
229 }
230 
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)231 AvbIOResult FakeAvbOps::validate_vbmeta_public_key(
232     AvbOps* ops,
233     const uint8_t* public_key_data,
234     size_t public_key_length,
235     const uint8_t* public_key_metadata,
236     size_t public_key_metadata_length,
237     bool* out_key_is_trusted) {
238   if (out_key_is_trusted != NULL) {
239     bool pk_matches = (public_key_length == expected_public_key_.size() &&
240                        (memcmp(expected_public_key_.c_str(),
241                                public_key_data,
242                                public_key_length) == 0));
243     bool pkmd_matches =
244         (public_key_metadata_length == expected_public_key_metadata_.size() &&
245          (memcmp(expected_public_key_metadata_.c_str(),
246                  public_key_metadata,
247                  public_key_metadata_length) == 0));
248     *out_key_is_trusted = pk_matches && pkmd_matches;
249   }
250   return AVB_IO_RESULT_OK;
251 }
252 
read_rollback_index(AvbOps * ops,size_t rollback_index_location,uint64_t * out_rollback_index)253 AvbIOResult FakeAvbOps::read_rollback_index(AvbOps* ops,
254                                             size_t rollback_index_location,
255                                             uint64_t* out_rollback_index) {
256   if (stored_rollback_indexes_.count(rollback_index_location) == 0) {
257     fprintf(stderr,
258             "No rollback index for location %zd (has %zd locations).\n",
259             rollback_index_location,
260             stored_rollback_indexes_.size());
261     return AVB_IO_RESULT_ERROR_IO;
262   }
263   *out_rollback_index = stored_rollback_indexes_[rollback_index_location];
264   return AVB_IO_RESULT_OK;
265 }
266 
write_rollback_index(AvbOps * ops,size_t rollback_index_location,uint64_t rollback_index)267 AvbIOResult FakeAvbOps::write_rollback_index(AvbOps* ops,
268                                              size_t rollback_index_location,
269                                              uint64_t rollback_index) {
270   if (stored_rollback_indexes_.count(rollback_index_location) == 0) {
271     fprintf(stderr,
272             "No rollback index for location %zd (has %zd locations).\n",
273             rollback_index_location,
274             stored_rollback_indexes_.size());
275     return AVB_IO_RESULT_ERROR_IO;
276   }
277   stored_rollback_indexes_[rollback_index_location] = rollback_index;
278   return AVB_IO_RESULT_OK;
279 }
280 
read_is_device_unlocked(AvbOps * ops,bool * out_is_device_unlocked)281 AvbIOResult FakeAvbOps::read_is_device_unlocked(AvbOps* ops,
282                                                 bool* out_is_device_unlocked) {
283   *out_is_device_unlocked = stored_is_device_unlocked_ ? 1 : 0;
284   return AVB_IO_RESULT_OK;
285 }
286 
get_unique_guid_for_partition(AvbOps * ops,const char * partition,char * guid_buf,size_t guid_buf_size)287 AvbIOResult FakeAvbOps::get_unique_guid_for_partition(AvbOps* ops,
288                                                       const char* partition,
289                                                       char* guid_buf,
290                                                       size_t guid_buf_size) {
291   // This is faking it a bit but makes testing easy. It works
292   // because avb_slot_verify.c doesn't check that the returned GUID
293   // is wellformed.
294   snprintf(guid_buf, guid_buf_size, "1234-fake-guid-for:%s", partition);
295   return AVB_IO_RESULT_OK;
296 }
297 
get_size_of_partition(AvbOps * ops,const char * partition,uint64_t * out_size)298 AvbIOResult FakeAvbOps::get_size_of_partition(AvbOps* ops,
299                                               const char* partition,
300                                               uint64_t* out_size) {
301   base::FilePath path =
302       partition_dir_.Append(std::string(partition)).AddExtension("img");
303 
304   int64_t file_size;
305   if (!base::GetFileSize(path, &file_size)) {
306     fprintf(stderr, "Error getting size of file '%s'\n", path.value().c_str());
307     return AVB_IO_RESULT_ERROR_IO;
308   }
309   *out_size = file_size;
310   return AVB_IO_RESULT_OK;
311 }
312 
read_persistent_value(const char * name,size_t buffer_size,uint8_t * out_buffer,size_t * out_num_bytes_read)313 AvbIOResult FakeAvbOps::read_persistent_value(const char* name,
314                                               size_t buffer_size,
315                                               uint8_t* out_buffer,
316                                               size_t* out_num_bytes_read) {
317   if (out_buffer == NULL && buffer_size > 0) {
318     return AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE;
319   }
320   if (stored_values_.count(name) == 0) {
321     return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
322   }
323   if (stored_values_[name].size() > buffer_size) {
324     *out_num_bytes_read = stored_values_[name].size();
325     return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE;
326   }
327   memcpy(out_buffer, stored_values_[name].data(), stored_values_[name].size());
328   *out_num_bytes_read = stored_values_[name].size();
329   return AVB_IO_RESULT_OK;
330 }
331 
write_persistent_value(const char * name,size_t value_size,const uint8_t * value)332 AvbIOResult FakeAvbOps::write_persistent_value(const char* name,
333                                                size_t value_size,
334                                                const uint8_t* value) {
335   stored_values_[name] =
336       std::string(reinterpret_cast<const char*>(value), value_size);
337   return AVB_IO_RESULT_OK;
338 }
339 
read_permanent_attributes(AvbAtxPermanentAttributes * attributes)340 AvbIOResult FakeAvbOps::read_permanent_attributes(
341     AvbAtxPermanentAttributes* attributes) {
342   *attributes = permanent_attributes_;
343   return AVB_IO_RESULT_OK;
344 }
345 
read_permanent_attributes_hash(uint8_t hash[AVB_SHA256_DIGEST_SIZE])346 AvbIOResult FakeAvbOps::read_permanent_attributes_hash(
347     uint8_t hash[AVB_SHA256_DIGEST_SIZE]) {
348   if (permanent_attributes_hash_.empty()) {
349     SHA256(reinterpret_cast<const unsigned char*>(&permanent_attributes_),
350            sizeof(AvbAtxPermanentAttributes),
351            hash);
352     return AVB_IO_RESULT_OK;
353   }
354   memset(hash, 0, AVB_SHA256_DIGEST_SIZE);
355   permanent_attributes_hash_.copy(reinterpret_cast<char*>(hash),
356                                   AVB_SHA256_DIGEST_SIZE);
357   return AVB_IO_RESULT_OK;
358 }
359 
set_key_version(size_t rollback_index_location,uint64_t key_version)360 void FakeAvbOps::set_key_version(size_t rollback_index_location,
361                                  uint64_t key_version) {
362   verified_rollback_indexes_[rollback_index_location] = key_version;
363 }
364 
my_ops_read_from_partition(AvbOps * ops,const char * partition,int64_t offset,size_t num_bytes,void * buffer,size_t * out_num_read)365 static AvbIOResult my_ops_read_from_partition(AvbOps* ops,
366                                               const char* partition,
367                                               int64_t offset,
368                                               size_t num_bytes,
369                                               void* buffer,
370                                               size_t* out_num_read) {
371   return FakeAvbOps::GetInstanceFromAvbOps(ops)
372       ->delegate()
373       ->read_from_partition(partition, offset, num_bytes, buffer, out_num_read);
374 }
375 
my_ops_get_preloaded_partition(AvbOps * ops,const char * partition,size_t num_bytes,uint8_t ** out_pointer,size_t * out_num_bytes_preloaded)376 static AvbIOResult my_ops_get_preloaded_partition(
377     AvbOps* ops,
378     const char* partition,
379     size_t num_bytes,
380     uint8_t** out_pointer,
381     size_t* out_num_bytes_preloaded) {
382   return FakeAvbOps::GetInstanceFromAvbOps(ops)
383       ->delegate()
384       ->get_preloaded_partition(
385           partition, num_bytes, out_pointer, out_num_bytes_preloaded);
386 }
387 
my_ops_write_to_partition(AvbOps * ops,const char * partition,int64_t offset,size_t num_bytes,const void * buffer)388 static AvbIOResult my_ops_write_to_partition(AvbOps* ops,
389                                              const char* partition,
390                                              int64_t offset,
391                                              size_t num_bytes,
392                                              const void* buffer) {
393   return FakeAvbOps::GetInstanceFromAvbOps(ops)->delegate()->write_to_partition(
394       partition, offset, num_bytes, buffer);
395 }
396 
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)397 static AvbIOResult my_ops_validate_vbmeta_public_key(
398     AvbOps* ops,
399     const uint8_t* public_key_data,
400     size_t public_key_length,
401     const uint8_t* public_key_metadata,
402     size_t public_key_metadata_length,
403     bool* out_key_is_trusted) {
404   return FakeAvbOps::GetInstanceFromAvbOps(ops)
405       ->delegate()
406       ->validate_vbmeta_public_key(ops,
407                                    public_key_data,
408                                    public_key_length,
409                                    public_key_metadata,
410                                    public_key_metadata_length,
411                                    out_key_is_trusted);
412 }
413 
my_ops_read_rollback_index(AvbOps * ops,size_t rollback_index_location,uint64_t * out_rollback_index)414 static AvbIOResult my_ops_read_rollback_index(AvbOps* ops,
415                                               size_t rollback_index_location,
416                                               uint64_t* out_rollback_index) {
417   return FakeAvbOps::GetInstanceFromAvbOps(ops)
418       ->delegate()
419       ->read_rollback_index(ops, rollback_index_location, out_rollback_index);
420 }
421 
my_ops_write_rollback_index(AvbOps * ops,size_t rollback_index_location,uint64_t rollback_index)422 static AvbIOResult my_ops_write_rollback_index(AvbOps* ops,
423                                                size_t rollback_index_location,
424                                                uint64_t rollback_index) {
425   return FakeAvbOps::GetInstanceFromAvbOps(ops)
426       ->delegate()
427       ->write_rollback_index(ops, rollback_index_location, rollback_index);
428 }
429 
my_ops_read_is_device_unlocked(AvbOps * ops,bool * out_is_device_unlocked)430 static AvbIOResult my_ops_read_is_device_unlocked(
431     AvbOps* ops, bool* out_is_device_unlocked) {
432   return FakeAvbOps::GetInstanceFromAvbOps(ops)
433       ->delegate()
434       ->read_is_device_unlocked(ops, out_is_device_unlocked);
435 }
436 
my_ops_get_unique_guid_for_partition(AvbOps * ops,const char * partition,char * guid_buf,size_t guid_buf_size)437 static AvbIOResult my_ops_get_unique_guid_for_partition(AvbOps* ops,
438                                                         const char* partition,
439                                                         char* guid_buf,
440                                                         size_t guid_buf_size) {
441   return FakeAvbOps::GetInstanceFromAvbOps(ops)
442       ->delegate()
443       ->get_unique_guid_for_partition(ops, partition, guid_buf, guid_buf_size);
444 }
445 
my_ops_get_size_of_partition(AvbOps * ops,const char * partition,uint64_t * out_size)446 static AvbIOResult my_ops_get_size_of_partition(AvbOps* ops,
447                                                 const char* partition,
448                                                 uint64_t* out_size) {
449   return FakeAvbOps::GetInstanceFromAvbOps(ops)
450       ->delegate()
451       ->get_size_of_partition(ops, partition, out_size);
452 }
453 
my_ops_read_persistent_value(AvbOps * ops,const char * name,size_t buffer_size,uint8_t * out_buffer,size_t * out_num_bytes_read)454 static AvbIOResult my_ops_read_persistent_value(AvbOps* ops,
455                                                 const char* name,
456                                                 size_t buffer_size,
457                                                 uint8_t* out_buffer,
458                                                 size_t* out_num_bytes_read) {
459   return FakeAvbOps::GetInstanceFromAvbOps(ops)
460       ->delegate()
461       ->read_persistent_value(
462           name, buffer_size, out_buffer, out_num_bytes_read);
463 }
464 
my_ops_write_persistent_value(AvbOps * ops,const char * name,size_t value_size,const uint8_t * value)465 static AvbIOResult my_ops_write_persistent_value(AvbOps* ops,
466                                                  const char* name,
467                                                  size_t value_size,
468                                                  const uint8_t* value) {
469   return FakeAvbOps::GetInstanceFromAvbOps(ops)
470       ->delegate()
471       ->write_persistent_value(name, value_size, value);
472 }
473 
my_ops_read_permanent_attributes(AvbAtxOps * atx_ops,AvbAtxPermanentAttributes * attributes)474 static AvbIOResult my_ops_read_permanent_attributes(
475     AvbAtxOps* atx_ops, AvbAtxPermanentAttributes* attributes) {
476   return FakeAvbOps::GetInstanceFromAvbOps(atx_ops->ops)
477       ->delegate()
478       ->read_permanent_attributes(attributes);
479 }
480 
my_ops_read_permanent_attributes_hash(AvbAtxOps * atx_ops,uint8_t hash[AVB_SHA256_DIGEST_SIZE])481 static AvbIOResult my_ops_read_permanent_attributes_hash(
482     AvbAtxOps* atx_ops, uint8_t hash[AVB_SHA256_DIGEST_SIZE]) {
483   return FakeAvbOps::GetInstanceFromAvbOps(atx_ops->ops)
484       ->delegate()
485       ->read_permanent_attributes_hash(hash);
486 }
487 
my_ops_set_key_version(AvbAtxOps * atx_ops,size_t rollback_index_location,uint64_t key_version)488 static void my_ops_set_key_version(AvbAtxOps* atx_ops,
489                                    size_t rollback_index_location,
490                                    uint64_t key_version) {
491   return FakeAvbOps::GetInstanceFromAvbOps(atx_ops->ops)
492       ->delegate()
493       ->set_key_version(rollback_index_location, key_version);
494 }
495 
FakeAvbOps()496 FakeAvbOps::FakeAvbOps() {
497   memset(&avb_ops_, 0, sizeof(avb_ops_));
498   avb_ops_.ab_ops = &avb_ab_ops_;
499   avb_ops_.atx_ops = &avb_atx_ops_;
500   avb_ops_.user_data = this;
501   avb_ops_.read_from_partition = my_ops_read_from_partition;
502   avb_ops_.write_to_partition = my_ops_write_to_partition;
503   avb_ops_.validate_vbmeta_public_key = my_ops_validate_vbmeta_public_key;
504   avb_ops_.read_rollback_index = my_ops_read_rollback_index;
505   avb_ops_.write_rollback_index = my_ops_write_rollback_index;
506   avb_ops_.read_is_device_unlocked = my_ops_read_is_device_unlocked;
507   avb_ops_.get_unique_guid_for_partition = my_ops_get_unique_guid_for_partition;
508   avb_ops_.get_size_of_partition = my_ops_get_size_of_partition;
509   avb_ops_.read_persistent_value = my_ops_read_persistent_value;
510   avb_ops_.write_persistent_value = my_ops_write_persistent_value;
511 
512   // Just use the built-in A/B metadata read/write routines.
513   avb_ab_ops_.ops = &avb_ops_;
514   avb_ab_ops_.read_ab_metadata = avb_ab_data_read;
515   avb_ab_ops_.write_ab_metadata = avb_ab_data_write;
516 
517   avb_atx_ops_.ops = &avb_ops_;
518   avb_atx_ops_.read_permanent_attributes = my_ops_read_permanent_attributes;
519   avb_atx_ops_.read_permanent_attributes_hash =
520       my_ops_read_permanent_attributes_hash;
521   avb_atx_ops_.set_key_version = my_ops_set_key_version;
522 
523   delegate_ = this;
524 }
525 
~FakeAvbOps()526 FakeAvbOps::~FakeAvbOps() {
527   std::map<std::string, uint8_t*>::iterator it;
528   for (it = preloaded_partitions_.begin(); it != preloaded_partitions_.end();
529        it++) {
530     free(it->second);
531   }
532 }
533 
enable_get_preloaded_partition()534 void FakeAvbOps::enable_get_preloaded_partition() {
535   avb_ops_.get_preloaded_partition = my_ops_get_preloaded_partition;
536 }
537 
538 }  // namespace avb
539