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 <string.h>
26
27 #include <map>
28 #include <vector>
29
30 #include <gtest/gtest.h>
31
32 #include <libavb_ab/libavb_ab.h>
33
34 #include "avb_unittest_util.h"
35 #include "fake_avb_ops.h"
36
37 namespace avb {
38
39 static_assert(sizeof(AvbABSlotData) == 4, "AvbABSlotData has wrong size");
40 static_assert(sizeof(AvbABData) == AVB_AB_DATA_SIZE,
41 "AvbABData has wrong size");
42 static_assert(offsetof(AvbABData, slots) % 8 == 0,
43 "AvbABData slots member has wrong offset");
44
45 // Subclass BaseAvbToolTest to check for memory leaks.
46 class ABTest : public BaseAvbToolTest {
47 public:
ABTest()48 ABTest() {}
49 };
50
TEST_F(ABTest,InitData)51 TEST_F(ABTest, InitData) {
52 AvbABData data;
53 avb_ab_data_init(&data);
54 EXPECT_EQ(0,
55 strncmp(reinterpret_cast<const char*>(data.magic),
56 AVB_AB_MAGIC,
57 AVB_AB_MAGIC_LEN));
58 EXPECT_EQ(AVB_AB_MAX_PRIORITY, data.slots[0].priority);
59 EXPECT_EQ(AVB_AB_MAX_TRIES_REMAINING, data.slots[0].tries_remaining);
60 EXPECT_EQ(0, data.slots[0].successful_boot);
61 EXPECT_EQ(AVB_AB_MAX_PRIORITY - 1, data.slots[1].priority);
62 EXPECT_EQ(AVB_AB_MAX_TRIES_REMAINING, data.slots[1].tries_remaining);
63 EXPECT_EQ(0, data.slots[1].successful_boot);
64 EXPECT_EQ(uint32_t(0), data.crc32);
65 }
66
TEST_F(ABTest,DataSerialization)67 TEST_F(ABTest, DataSerialization) {
68 AvbABData data;
69 AvbABData serialized;
70 AvbABData restored;
71
72 avb_ab_data_init(&data);
73 EXPECT_EQ(uint32_t(0), data.crc32);
74 avb_ab_data_update_crc_and_byteswap(&data, &serialized);
75 EXPECT_NE(uint32_t(0), serialized.crc32);
76 EXPECT_TRUE(avb_ab_data_verify_and_byteswap(&serialized, &restored));
77 EXPECT_EQ(std::string(reinterpret_cast<const char*>(data.magic), 4),
78 std::string(reinterpret_cast<const char*>(restored.magic), 4));
79 EXPECT_EQ(data.version_major, restored.version_major);
80 EXPECT_EQ(data.version_minor, restored.version_minor);
81 EXPECT_EQ(0,
82 memcmp(reinterpret_cast<void*>(data.slots),
83 reinterpret_cast<void*>(restored.slots),
84 sizeof(AvbABSlotData) * 2));
85 }
86
TEST_F(ABTest,CatchBadCRC)87 TEST_F(ABTest, CatchBadCRC) {
88 AvbABData data;
89 AvbABData serialized;
90 AvbABData restored;
91
92 avb_ab_data_init(&data);
93 avb_ab_data_update_crc_and_byteswap(&data, &serialized);
94 serialized.crc32 += 1;
95 EXPECT_FALSE(avb_ab_data_verify_and_byteswap(&serialized, &restored));
96 }
97
TEST_F(ABTest,CatchUnsupportedMajorVersion)98 TEST_F(ABTest, CatchUnsupportedMajorVersion) {
99 AvbABData data;
100 AvbABData serialized;
101 AvbABData restored;
102
103 avb_ab_data_init(&data);
104 data.version_major += 1;
105 avb_ab_data_update_crc_and_byteswap(&data, &serialized);
106 EXPECT_FALSE(avb_ab_data_verify_and_byteswap(&serialized, &restored));
107 }
108
TEST_F(ABTest,SupportSameMajorFutureMinorVersion)109 TEST_F(ABTest, SupportSameMajorFutureMinorVersion) {
110 AvbABData data;
111 AvbABData serialized;
112 AvbABData restored;
113
114 avb_ab_data_init(&data);
115 data.version_minor += 1;
116 avb_ab_data_update_crc_and_byteswap(&data, &serialized);
117 EXPECT_TRUE(avb_ab_data_verify_and_byteswap(&serialized, &restored));
118 }
119
120 #define MISC_PART_SIZE 8 * 1024
121
122 // These values are kept short since they are used in SetMD() and it's
123 // helpful if the information for a slot fits in one 80-character
124 // line.
125 enum SlotValidity {
126 SV_OK, // Slot is valid and verified.
127 SV_INV, // Slot is invalid.
128 SV_UNV, // Slot is valid but unverified.
129 };
130
131 class AvbABFlowTest : public BaseAvbToolTest {
132 public:
AvbABFlowTest()133 AvbABFlowTest() {}
134
SetUp()135 virtual void SetUp() override {
136 BaseAvbToolTest::SetUp();
137 ops_.set_partition_dir(testdir_);
138 ops_.set_stored_rollback_indexes({{0, 0}, {1, 0}, {2, 0}, {3, 0}});
139 ops_.set_stored_is_device_unlocked(false);
140
141 // Create large enough 'misc' partition and initialize it with
142 // zeroes.
143 std::vector<uint8_t> misc;
144 misc.resize(MISC_PART_SIZE);
145 base::FilePath misc_path = testdir_.Append("misc.img");
146 EXPECT_EQ(misc.size(),
147 static_cast<const size_t>(
148 base::WriteFile(misc_path,
149 reinterpret_cast<const char*>(misc.data()),
150 misc.size())));
151
152 // We're going to use this key for all images.
153 ops_.set_expected_public_key(
154 PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
155 }
156
GenerateSlot(unsigned int slot_number,SlotValidity slot_validity,uint64_t rollback_boot,uint64_t rollback_odm)157 void GenerateSlot(unsigned int slot_number,
158 SlotValidity slot_validity,
159 uint64_t rollback_boot,
160 uint64_t rollback_odm) {
161 std::string boot_name = "boot_a.img";
162 std::string vbmeta_name = "vbmeta_a.img";
163 std::string odm_name = "odm_a.img";
164 if (slot_number > 0) {
165 boot_name = "boot_b.img";
166 vbmeta_name = "vbmeta_b.img";
167 odm_name = "odm_b.img";
168 }
169
170 // If asked to make an invalid slot, just generate 1MiB garbage
171 // for each the three images in the slot.
172 if (slot_validity == SV_INV) {
173 GenerateImage(boot_name, 1024 * 1024);
174 GenerateImage(vbmeta_name, 1024 * 1024);
175 GenerateImage(odm_name, 1024 * 1024);
176 return;
177 }
178
179 const size_t boot_partition_size = 16 * 1024 * 1024;
180 const size_t boot_image_size = 5 * 1024 * 1024;
181 base::FilePath boot_path = GenerateImage(boot_name, boot_image_size);
182 EXPECT_COMMAND(0,
183 "./avbtool add_hash_footer"
184 " --image %s"
185 " --rollback_index %" PRIu64
186 " --partition_name boot"
187 " --partition_size %zd"
188 " --salt deadbeef",
189 boot_path.value().c_str(),
190 rollback_boot,
191 boot_partition_size);
192
193 const size_t odm_partition_size = 512 * 1024;
194 const size_t odm_image_size = 80 * 1024;
195 base::FilePath odm_path = GenerateImage(odm_name, odm_image_size);
196 EXPECT_COMMAND(0,
197 "./avbtool add_hashtree_footer"
198 " --image %s"
199 " --rollback_index %" PRIu64
200 " --partition_name odm"
201 " --partition_size %zd"
202 " --salt deadbeef"
203 " --algorithm SHA512_RSA4096 "
204 " --key test/data/testkey_rsa4096.pem",
205 odm_path.value().c_str(),
206 rollback_odm,
207 odm_partition_size);
208
209 base::FilePath pk_path = testdir_.Append("testkey_rsa4096.avbpubkey");
210 EXPECT_COMMAND(
211 0,
212 "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
213 " --output %s",
214 pk_path.value().c_str());
215
216 // If requested to make the image unverified, just use another key
217 // in the chain_partition descriptor since this will cause
218 // avb_slot_verify() to return ERROR_PUBLIC_KEY_REJECTED.
219 if (slot_validity == SV_UNV) {
220 pk_path = GenerateImage("dummy.avbpubkey", 32);
221 }
222
223 GenerateVBMetaImage(vbmeta_name,
224 "SHA256_RSA2048",
225 rollback_boot,
226 base::FilePath("test/data/testkey_rsa2048.pem"),
227 base::StringPrintf("--include_descriptors_from_image %s"
228 " --chain_partition odm:1:%s",
229 boot_path.value().c_str(),
230 pk_path.value().c_str()));
231 }
232
SetMD(int a_pri,int a_tries,bool a_success,SlotValidity a_slot_validity,uint64_t a_rollback_boot,uint64_t a_rollback_odm,int b_pri,int b_tries,bool b_success,SlotValidity b_slot_validity,uint64_t b_rollback_boot,uint64_t b_rollback_odm,const std::map<size_t,uint64_t> & stored_rollback_indexes)233 void SetMD(int a_pri,
234 int a_tries,
235 bool a_success,
236 SlotValidity a_slot_validity,
237 uint64_t a_rollback_boot,
238 uint64_t a_rollback_odm,
239 int b_pri,
240 int b_tries,
241 bool b_success,
242 SlotValidity b_slot_validity,
243 uint64_t b_rollback_boot,
244 uint64_t b_rollback_odm,
245 const std::map<size_t, uint64_t>& stored_rollback_indexes) {
246 AvbABData data;
247 avb_ab_data_init(&data);
248 data.slots[0].priority = a_pri;
249 data.slots[0].tries_remaining = a_tries;
250 data.slots[0].successful_boot = (a_success ? 1 : 0);
251 data.slots[1].priority = b_pri;
252 data.slots[1].tries_remaining = b_tries;
253 data.slots[1].successful_boot = (b_success ? 1 : 0);
254 EXPECT_EQ(AVB_IO_RESULT_OK,
255 ops_.avb_ab_ops()->write_ab_metadata(ops_.avb_ab_ops(), &data));
256 GenerateSlot(0, a_slot_validity, a_rollback_boot, a_rollback_odm);
257 GenerateSlot(1, b_slot_validity, b_rollback_boot, b_rollback_odm);
258 ops_.set_stored_rollback_indexes(stored_rollback_indexes);
259 }
260
MakeRollbackIndexes(uint64_t slot_0_value,uint64_t slot_1_value)261 std::map<size_t, uint64_t> MakeRollbackIndexes(uint64_t slot_0_value,
262 uint64_t slot_1_value) {
263 return std::map<size_t, uint64_t>{{0, slot_0_value}, {1, slot_1_value}};
264 }
265
266 FakeAvbOps ops_;
267 };
268
269 #define ExpMD(a_pri, \
270 a_tries, \
271 a_success, \
272 b_pri, \
273 b_tries, \
274 b_success, \
275 stored_rollback_indexes) \
276 do { \
277 AvbABData data; \
278 EXPECT_EQ(AVB_IO_RESULT_OK, \
279 ops_.avb_ab_ops()->read_ab_metadata(ops_.avb_ab_ops(), &data)); \
280 EXPECT_EQ(a_pri, data.slots[0].priority); \
281 EXPECT_EQ(a_tries, data.slots[0].tries_remaining); \
282 EXPECT_EQ(a_success ? 1 : 0, data.slots[0].successful_boot); \
283 EXPECT_EQ(b_pri, data.slots[1].priority); \
284 EXPECT_EQ(b_tries, data.slots[1].tries_remaining); \
285 EXPECT_EQ(b_success ? 1 : 0, data.slots[1].successful_boot); \
286 EXPECT_EQ(stored_rollback_indexes, ops_.get_stored_rollback_indexes()); \
287 } while (0);
288
TEST_F(AvbABFlowTest,MetadataReadAndWrite)289 TEST_F(AvbABFlowTest, MetadataReadAndWrite) {
290 AvbABData data;
291 AvbABData loaded;
292
293 // First load from an uninitialized 'misc' partition. This should
294 // not fail and just returned initialized data.
295 EXPECT_EQ(AVB_IO_RESULT_OK, avb_ab_data_read(ops_.avb_ab_ops(), &loaded));
296 EXPECT_EQ(AVB_AB_MAX_PRIORITY, loaded.slots[0].priority);
297 EXPECT_EQ(AVB_AB_MAX_TRIES_REMAINING, loaded.slots[0].tries_remaining);
298 EXPECT_EQ(0, loaded.slots[0].successful_boot);
299 EXPECT_EQ(AVB_AB_MAX_PRIORITY - 1, loaded.slots[1].priority);
300 EXPECT_EQ(AVB_AB_MAX_TRIES_REMAINING, loaded.slots[1].tries_remaining);
301 EXPECT_EQ(0, loaded.slots[1].successful_boot);
302
303 // Then initialize and save well-known A/B metadata and check we
304 // read back the same thing.
305 avb_ab_data_init(&data);
306 data.slots[0].priority = 2;
307 data.slots[0].tries_remaining = 3;
308 EXPECT_EQ(AVB_IO_RESULT_OK, avb_ab_data_write(ops_.avb_ab_ops(), &data));
309 EXPECT_EQ(AVB_IO_RESULT_OK, avb_ab_data_read(ops_.avb_ab_ops(), &loaded));
310 EXPECT_EQ(2, loaded.slots[0].priority);
311 EXPECT_EQ(3, loaded.slots[0].tries_remaining);
312 }
313
TEST_F(AvbABFlowTest,EverythingIsValid)314 TEST_F(AvbABFlowTest, EverythingIsValid) {
315 AvbSlotVerifyData* data;
316 const char* requested_partitions[] = {"boot", NULL};
317
318 SetMD(14,
319 0,
320 1,
321 SV_OK,
322 0,
323 0, // A: pri, tries, success, slot_validity, RIs
324 15,
325 0,
326 1,
327 SV_OK,
328 0,
329 0, // B: pri, tries, success, slot_validity, RIs
330 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
331 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
332 avb_ab_flow(ops_.avb_ab_ops(),
333 requested_partitions,
334 false /* allow_verification_error */,
335 &data));
336 ExpMD(14,
337 0,
338 1, // A: pri, tries, successful
339 15,
340 0,
341 1, // B: pri, tries, successful
342 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
343 ASSERT_NE(nullptr, data);
344 EXPECT_EQ("_b", std::string(data->ab_suffix));
345 avb_slot_verify_data_free(data);
346
347 // Also check the other slot.
348 SetMD(15,
349 0,
350 1,
351 SV_OK,
352 0,
353 0, // A: pri, tries, success, slot_validity, RIs
354 14,
355 0,
356 1,
357 SV_OK,
358 0,
359 0, // B: pri, tries, success, slot_validity, RIs
360 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
361 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
362 avb_ab_flow(ops_.avb_ab_ops(),
363 requested_partitions,
364 false /* allow_verification_error */,
365 &data));
366 ExpMD(15,
367 0,
368 1, // A: pri, tries, successful
369 14,
370 0,
371 1, // B: pri, tries, successful
372 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
373 ASSERT_NE(nullptr, data);
374 EXPECT_EQ("_a", std::string(data->ab_suffix));
375 avb_slot_verify_data_free(data);
376 }
377
TEST_F(AvbABFlowTest,NoBootableSlots)378 TEST_F(AvbABFlowTest, NoBootableSlots) {
379 AvbSlotVerifyData* data;
380 const char* requested_partitions[] = {"boot", NULL};
381
382 SetMD(0,
383 0,
384 0,
385 SV_OK,
386 0,
387 0, // A: pri, tries, success, slot_validity, RIs
388 0,
389 0,
390 0,
391 SV_OK,
392 0,
393 0, // B: pri, tries, success, slot_validity, RIs
394 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
395 EXPECT_EQ(AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS,
396 avb_ab_flow(ops_.avb_ab_ops(),
397 requested_partitions,
398 false /* allow_verification_error */,
399 &data));
400 ExpMD(0,
401 0,
402 0, // A: pri, tries, successful
403 0,
404 0,
405 0, // B: pri, tries, successful
406 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
407 ASSERT_EQ(nullptr, data);
408 }
409
TEST_F(AvbABFlowTest,TriesRemainingDecreasing)410 TEST_F(AvbABFlowTest, TriesRemainingDecreasing) {
411 AvbSlotVerifyData* data;
412 const char* requested_partitions[] = {"boot", NULL};
413
414 SetMD(15,
415 3,
416 0,
417 SV_OK,
418 0,
419 0, // A: pri, tries, success, slot_validity, RIs
420 0,
421 0,
422 0,
423 SV_OK,
424 0,
425 0, // B: pri, tries, success, slot_validity, RIs
426 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
427
428 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
429 avb_ab_flow(ops_.avb_ab_ops(),
430 requested_partitions,
431 false /* allow_verification_error */,
432 &data));
433 ExpMD(15,
434 2,
435 0, // A: pri, tries, successful
436 0,
437 0,
438 0, // B: pri, tries, successful
439 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
440 ASSERT_NE(nullptr, data);
441 EXPECT_EQ("_a", std::string(data->ab_suffix));
442 avb_slot_verify_data_free(data);
443
444 // Keep counting down...
445 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
446 avb_ab_flow(ops_.avb_ab_ops(),
447 requested_partitions,
448 false /* allow_verification_error */,
449 &data));
450 ExpMD(15,
451 1,
452 0, // A: pri, tries, successful
453 0,
454 0,
455 0, // B: pri, tries, successful
456 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
457 ASSERT_NE(nullptr, data);
458 EXPECT_EQ("_a", std::string(data->ab_suffix));
459 avb_slot_verify_data_free(data);
460
461 // Last try...
462 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
463 avb_ab_flow(ops_.avb_ab_ops(),
464 requested_partitions,
465 false /* allow_verification_error */,
466 &data));
467 ExpMD(15,
468 0,
469 0, // A: pri, tries, successful
470 0,
471 0,
472 0, // B: pri, tries, successful
473 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
474 ASSERT_NE(nullptr, data);
475 EXPECT_EQ("_a", std::string(data->ab_suffix));
476 avb_slot_verify_data_free(data);
477
478 // And we're out of tries. At this point, (15, 0, 0) is normalized
479 // to (0, 0, 0) so expect that.
480 EXPECT_EQ(AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS,
481 avb_ab_flow(ops_.avb_ab_ops(),
482 requested_partitions,
483 false /* allow_verification_error */,
484 &data));
485 ExpMD(0,
486 0,
487 0, // A: pri, tries, successful
488 0,
489 0,
490 0, // B: pri, tries, successful
491 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
492 ASSERT_EQ(nullptr, data);
493 }
494
TEST_F(AvbABFlowTest,TryingThenFallback)495 TEST_F(AvbABFlowTest, TryingThenFallback) {
496 AvbSlotVerifyData* data;
497 const char* requested_partitions[] = {"boot", NULL};
498
499 SetMD(15,
500 2,
501 0,
502 SV_OK,
503 0,
504 0, // A: pri, tries, success, slot_validity, RIs
505 14,
506 0,
507 1,
508 SV_OK,
509 0,
510 0, // B: pri, tries, success, slot_validity, RIs
511 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
512 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
513 avb_ab_flow(ops_.avb_ab_ops(),
514 requested_partitions,
515 false /* allow_verification_error */,
516 &data));
517 ExpMD(15,
518 1,
519 0, // A: pri, tries, successful
520 14,
521 0,
522 1, // B: pri, tries, successful
523 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
524 ASSERT_NE(nullptr, data);
525 EXPECT_EQ("_a", std::string(data->ab_suffix));
526 avb_slot_verify_data_free(data);
527
528 // Last try...
529 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
530 avb_ab_flow(ops_.avb_ab_ops(),
531 requested_partitions,
532 false /* allow_verification_error */,
533 &data));
534 ExpMD(15,
535 0,
536 0, // A: pri, tries, successful
537 14,
538 0,
539 1, // B: pri, tries, successful
540 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
541 ASSERT_NE(nullptr, data);
542 EXPECT_EQ("_a", std::string(data->ab_suffix));
543 avb_slot_verify_data_free(data);
544
545 // And we're out of tries. Check we fall back to slot B.
546 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
547 avb_ab_flow(ops_.avb_ab_ops(),
548 requested_partitions,
549 false /* allow_verification_error */,
550 &data));
551 ExpMD(0,
552 0,
553 0, // A: pri, tries, successful
554 14,
555 0,
556 1, // B: pri, tries, successful
557 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
558 ASSERT_NE(nullptr, data);
559 EXPECT_EQ("_b", std::string(data->ab_suffix));
560 avb_slot_verify_data_free(data);
561 }
562
TEST_F(AvbABFlowTest,TriesRemainingNotDecreasingIfNotPriority)563 TEST_F(AvbABFlowTest, TriesRemainingNotDecreasingIfNotPriority) {
564 AvbSlotVerifyData* data;
565 const char* requested_partitions[] = {"boot", NULL};
566
567 SetMD(15,
568 0,
569 1,
570 SV_OK,
571 0,
572 0, // A: pri, tries, success, slot_validity, RIs
573 14,
574 7,
575 0,
576 SV_OK,
577 0,
578 0, // B: pri, tries, success, slot_validity, RIs
579 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
580 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
581 avb_ab_flow(ops_.avb_ab_ops(),
582 requested_partitions,
583 false /* allow_verification_error */,
584 &data));
585 ExpMD(15,
586 0,
587 1, // A: pri, tries, successful
588 14,
589 7,
590 0, // B: pri, tries, successful
591 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
592 ASSERT_NE(nullptr, data);
593 EXPECT_EQ("_a", std::string(data->ab_suffix));
594 avb_slot_verify_data_free(data);
595 }
596
TEST_F(AvbABFlowTest,InvalidSlotIsMarkedAsSuch)597 TEST_F(AvbABFlowTest, InvalidSlotIsMarkedAsSuch) {
598 AvbSlotVerifyData* data;
599 const char* requested_partitions[] = {"boot", NULL};
600
601 // Slot A is invalid.
602 SetMD(15,
603 0,
604 1,
605 SV_INV,
606 0,
607 0, // A: pri, tries, success, slot_validity, RIs
608 14,
609 0,
610 1,
611 SV_OK,
612 0,
613 0, // B: pri, tries, success, slot_validity, RIs
614 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
615 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
616 avb_ab_flow(ops_.avb_ab_ops(),
617 requested_partitions,
618 false /* allow_verification_error */,
619 &data));
620 ExpMD(0,
621 0,
622 0, // A: pri, tries, successful
623 14,
624 0,
625 1, // B: pri, tries, successful
626 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
627 ASSERT_NE(nullptr, data);
628 EXPECT_EQ("_b", std::string(data->ab_suffix));
629 avb_slot_verify_data_free(data);
630
631 // Slot B is invalid.
632 SetMD(15,
633 0,
634 1,
635 SV_OK,
636 0,
637 0, // A: pri, tries, success, slot_validity, RIs
638 14,
639 0,
640 1,
641 SV_INV,
642 0,
643 0, // B: pri, tries, success, slot_validity, RIs
644 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
645 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
646 avb_ab_flow(ops_.avb_ab_ops(),
647 requested_partitions,
648 false /* allow_verification_error */,
649 &data));
650 ExpMD(15,
651 0,
652 1, // A: pri, tries, successful
653 0,
654 0,
655 0, // B: pri, tries, successful
656 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
657 ASSERT_NE(nullptr, data);
658 EXPECT_EQ("_a", std::string(data->ab_suffix));
659 avb_slot_verify_data_free(data);
660
661 // Both slots are invalid.
662 SetMD(15,
663 0,
664 1,
665 SV_INV,
666 0,
667 0, // A: pri, tries, success, slot_validity, RIs
668 14,
669 0,
670 1,
671 SV_INV,
672 0,
673 0, // B: pri, tries, success, slot_validity, RIs
674 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
675 EXPECT_EQ(AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS,
676 avb_ab_flow(ops_.avb_ab_ops(),
677 requested_partitions,
678 false /* allow_verification_error */,
679 &data));
680 ExpMD(0,
681 0,
682 0, // A: pri, tries, successful
683 0,
684 0,
685 0, // B: pri, tries, successful
686 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
687 ASSERT_EQ(nullptr, data);
688 }
689
TEST_F(AvbABFlowTest,UnverifiedSlotIsMarkedAsSuch)690 TEST_F(AvbABFlowTest, UnverifiedSlotIsMarkedAsSuch) {
691 AvbSlotVerifyData* data;
692 const char* requested_partitions[] = {"boot", NULL};
693
694 // Slot A fails verification.
695 SetMD(15,
696 0,
697 1,
698 SV_UNV,
699 0,
700 0, // A: pri, tries, success, slot_validity, RIs
701 14,
702 0,
703 1,
704 SV_OK,
705 0,
706 0, // B: pri, tries, success, slot_validity, RIs
707 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
708 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
709 avb_ab_flow(ops_.avb_ab_ops(),
710 requested_partitions,
711 false /* allow_verification_error */,
712 &data));
713 ExpMD(0,
714 0,
715 0, // A: pri, tries, successful
716 14,
717 0,
718 1, // B: pri, tries, successful
719 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
720 ASSERT_NE(nullptr, data);
721 EXPECT_EQ("_b", std::string(data->ab_suffix));
722 avb_slot_verify_data_free(data);
723
724 // Slot B fails verification.
725 SetMD(15,
726 0,
727 1,
728 SV_OK,
729 0,
730 0, // A: pri, tries, success, slot_validity, RIs
731 14,
732 0,
733 1,
734 SV_UNV,
735 0,
736 0, // B: pri, tries, success, slot_validity, RIs
737 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
738 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
739 avb_ab_flow(ops_.avb_ab_ops(),
740 requested_partitions,
741 false /* allow_verification_error */,
742 &data));
743 ExpMD(15,
744 0,
745 1, // A: pri, tries, successful
746 0,
747 0,
748 0, // B: pri, tries, successful
749 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
750 ASSERT_NE(nullptr, data);
751 EXPECT_EQ("_a", std::string(data->ab_suffix));
752 avb_slot_verify_data_free(data);
753
754 // Both slots fail verification.
755 SetMD(15,
756 0,
757 1,
758 SV_UNV,
759 0,
760 0, // A: pri, tries, success, slot_validity, RIs
761 14,
762 0,
763 1,
764 SV_UNV,
765 0,
766 0, // B: pri, tries, success, slot_validity, RIs
767 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
768 EXPECT_EQ(AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS,
769 avb_ab_flow(ops_.avb_ab_ops(),
770 requested_partitions,
771 false /* allow_verification_error */,
772 &data));
773 ExpMD(0,
774 0,
775 0, // A: pri, tries, successful
776 0,
777 0,
778 0, // B: pri, tries, successful
779 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
780 ASSERT_EQ(nullptr, data);
781 }
782
TEST_F(AvbABFlowTest,RollbackIndexFailures)783 TEST_F(AvbABFlowTest, RollbackIndexFailures) {
784 AvbSlotVerifyData* data;
785 const char* requested_partitions[] = {"boot", NULL};
786
787 // Slot A rollback index failure for 'boot'.
788 SetMD(15,
789 0,
790 1,
791 SV_OK,
792 0,
793 2, // A: pri, tries, success, slot_validity, RIs
794 14,
795 0,
796 1,
797 SV_OK,
798 2,
799 2, // B: pri, tries, success, slot_validity, RIs
800 MakeRollbackIndexes(2, 2)); // stored_rollback_indexes
801 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
802 avb_ab_flow(ops_.avb_ab_ops(),
803 requested_partitions,
804 false /* allow_verification_error */,
805 &data));
806 ExpMD(0,
807 0,
808 0, // A: pri, tries, successful
809 14,
810 0,
811 1, // B: pri, tries, successful
812 MakeRollbackIndexes(2, 2)); // stored_rollback_indexes
813 ASSERT_NE(nullptr, data);
814 EXPECT_EQ("_b", std::string(data->ab_suffix));
815 avb_slot_verify_data_free(data);
816
817 // Slot A rollback index failure for 'odm'.
818 SetMD(15,
819 0,
820 1,
821 SV_OK,
822 2,
823 0, // A: pri, tries, success, slot_validity, RIs
824 14,
825 0,
826 1,
827 SV_OK,
828 2,
829 2, // B: pri, tries, success, slot_validity, RIs
830 MakeRollbackIndexes(2, 2)); // stored_rollback_indexes
831 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
832 avb_ab_flow(ops_.avb_ab_ops(),
833 requested_partitions,
834 false /* allow_verification_error */,
835 &data));
836 ExpMD(0,
837 0,
838 0, // A: pri, tries, successful
839 14,
840 0,
841 1, // B: pri, tries, successful
842 MakeRollbackIndexes(2, 2)); // stored_rollback_indexes
843 ASSERT_NE(nullptr, data);
844 EXPECT_EQ("_b", std::string(data->ab_suffix));
845 avb_slot_verify_data_free(data);
846 }
847
TEST_F(AvbABFlowTest,StoredRollbackIndexBumped)848 TEST_F(AvbABFlowTest, StoredRollbackIndexBumped) {
849 AvbSlotVerifyData* data;
850 const char* requested_partitions[] = {"boot", NULL};
851
852 SetMD(15,
853 0,
854 1,
855 SV_OK,
856 3,
857 3, // A: pri, tries, success, slot_validity, RIs
858 14,
859 0,
860 1,
861 SV_OK,
862 3,
863 3, // B: pri, tries, success, slot_validity, RIs
864 MakeRollbackIndexes(2, 2)); // stored_rollback_indexes
865 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
866 avb_ab_flow(ops_.avb_ab_ops(),
867 requested_partitions,
868 false /* allow_verification_error */,
869 &data));
870 ExpMD(15,
871 0,
872 1, // A: pri, tries, successful
873 14,
874 0,
875 1, // B: pri, tries, successful
876 MakeRollbackIndexes(3, 3)); // stored_rollback_indexes
877 ASSERT_NE(nullptr, data);
878 EXPECT_EQ("_a", std::string(data->ab_suffix));
879 avb_slot_verify_data_free(data);
880
881 // The case where different partitions have different rollback
882 // index values.
883 SetMD(15,
884 0,
885 1,
886 SV_OK,
887 4,
888 9, // A: pri, tries, success, slot_validity, RIs
889 14,
890 0,
891 1,
892 SV_OK,
893 5,
894 7, // B: pri, tries, success, slot_validity, RIs
895 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
896 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
897 avb_ab_flow(ops_.avb_ab_ops(),
898 requested_partitions,
899 false /* allow_verification_error */,
900 &data));
901 ExpMD(15,
902 0,
903 1, // A: pri, tries, successful
904 14,
905 0,
906 1, // B: pri, tries, successful
907 MakeRollbackIndexes(4, 7)); // stored_rollback_indexes
908 ASSERT_NE(nullptr, data);
909 EXPECT_EQ("_a", std::string(data->ab_suffix));
910 avb_slot_verify_data_free(data);
911
912 // If the slot with the low RI fails verification (or is invalid),
913 // check that these low Rollback Indexs are not taken into account
914 // after marking it as unbootable.
915 SetMD(15,
916 0,
917 1,
918 SV_INV,
919 4,
920 9, // A: pri, tries, success, slot_validity, RIs
921 14,
922 0,
923 1,
924 SV_OK,
925 5,
926 7, // B: pri, tries, success, slot_validity, RIs
927 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
928 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
929 avb_ab_flow(ops_.avb_ab_ops(),
930 requested_partitions,
931 false /* allow_verification_error */,
932 &data));
933 ExpMD(0,
934 0,
935 0, // A: pri, tries, successful
936 14,
937 0,
938 1, // B: pri, tries, successful
939 MakeRollbackIndexes(5, 7)); // stored_rollback_indexes
940 ASSERT_NE(nullptr, data);
941 EXPECT_EQ("_b", std::string(data->ab_suffix));
942 avb_slot_verify_data_free(data);
943 }
944
TEST_F(AvbABFlowTest,MarkSlotActive)945 TEST_F(AvbABFlowTest, MarkSlotActive) {
946 SetMD(15,
947 0,
948 1,
949 SV_INV,
950 0,
951 0, // A: pri, tries, success, slot_validity, RIs
952 11,
953 0,
954 1,
955 SV_OK,
956 0,
957 0, // B: pri, tries, success, slot_validity, RIs
958 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
959 EXPECT_EQ(AVB_IO_RESULT_OK, avb_ab_mark_slot_active(ops_.avb_ab_ops(), 0));
960 ExpMD(15,
961 7,
962 0, // A: pri, tries, successful
963 11,
964 0,
965 1, // B: pri, tries, successful
966 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
967
968 // Note how priority of slot A is altered to make room for newly
969 // activated slot.
970 SetMD(15,
971 0,
972 1,
973 SV_INV,
974 0,
975 0, // A: pri, tries, success, slot_validity, RIs
976 14,
977 0,
978 1,
979 SV_OK,
980 0,
981 0, // B: pri, tries, success, slot_validity, RIs
982 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
983 EXPECT_EQ(AVB_IO_RESULT_OK, avb_ab_mark_slot_active(ops_.avb_ab_ops(), 1));
984 ExpMD(14,
985 0,
986 1, // A: pri, tries, successful
987 15,
988 7,
989 0, // B: pri, tries, successful
990 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
991 }
992
TEST_F(AvbABFlowTest,MarkSlotUnbootable)993 TEST_F(AvbABFlowTest, MarkSlotUnbootable) {
994 SetMD(15,
995 0,
996 1,
997 SV_INV,
998 0,
999 0, // A: pri, tries, success, slot_validity, RIs
1000 11,
1001 0,
1002 1,
1003 SV_OK,
1004 0,
1005 0, // B: pri, tries, success, slot_validity, RIs
1006 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1007 EXPECT_EQ(AVB_IO_RESULT_OK,
1008 avb_ab_mark_slot_unbootable(ops_.avb_ab_ops(), 0));
1009 ExpMD(0,
1010 0,
1011 0, // A: pri, tries, successful
1012 11,
1013 0,
1014 1, // B: pri, tries, successful
1015 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1016
1017 SetMD(15,
1018 0,
1019 1,
1020 SV_INV,
1021 0,
1022 0, // A: pri, tries, success, slot_validity, RIs
1023 14,
1024 0,
1025 1,
1026 SV_OK,
1027 0,
1028 0, // B: pri, tries, success, slot_validity, RIs
1029 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1030 EXPECT_EQ(AVB_IO_RESULT_OK,
1031 avb_ab_mark_slot_unbootable(ops_.avb_ab_ops(), 1));
1032 ExpMD(15,
1033 0,
1034 1, // A: pri, tries, successful
1035 0,
1036 0,
1037 0, // B: pri, tries, successful
1038 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1039 }
1040
TEST_F(AvbABFlowTest,MarkSlotSuccessful)1041 TEST_F(AvbABFlowTest, MarkSlotSuccessful) {
1042 SetMD(15,
1043 5,
1044 0,
1045 SV_INV,
1046 0,
1047 0, // A: pri, tries, success, slot_validity, RIs
1048 11,
1049 3,
1050 0,
1051 SV_OK,
1052 0,
1053 0, // B: pri, tries, success, slot_validity, RIs
1054 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1055 EXPECT_EQ(AVB_IO_RESULT_OK,
1056 avb_ab_mark_slot_successful(ops_.avb_ab_ops(), 0));
1057 ExpMD(15,
1058 0,
1059 1, // A: pri, tries, successful
1060 11,
1061 3,
1062 0, // B: pri, tries, successful
1063 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1064
1065 SetMD(15,
1066 5,
1067 0,
1068 SV_INV,
1069 0,
1070 0, // A: pri, tries, success, slot_validity, RIs
1071 14,
1072 0,
1073 1,
1074 SV_OK,
1075 0,
1076 0, // B: pri, tries, success, slot_validity, RIs
1077 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1078 EXPECT_EQ(AVB_IO_RESULT_OK,
1079 avb_ab_mark_slot_successful(ops_.avb_ab_ops(), 1));
1080 ExpMD(15,
1081 5,
1082 0, // A: pri, tries, successful
1083 14,
1084 0,
1085 1, // B: pri, tries, successful
1086 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1087
1088 // Marking an unbootable slot (A) as successful won't work (it's a
1089 // programmer error to do so)... notice however that the unbootable
1090 // slot is normalized in the process.
1091 SetMD(0,
1092 3,
1093 2,
1094 SV_INV,
1095 0,
1096 0, // A: pri, tries, success, slot_validity, RIs
1097 14,
1098 0,
1099 1,
1100 SV_OK,
1101 0,
1102 0, // B: pri, tries, success, slot_validity, RIs
1103 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1104 EXPECT_EQ(AVB_IO_RESULT_OK,
1105 avb_ab_mark_slot_successful(ops_.avb_ab_ops(), 0));
1106 ExpMD(0,
1107 0,
1108 0, // A: pri, tries, successful
1109 14,
1110 0,
1111 1, // B: pri, tries, successful
1112 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1113 }
1114
1115 static AvbABData my_serialized_data;
1116
my_write_ab_metadata(AvbABOps * ops,const struct AvbABData * data)1117 static AvbIOResult my_write_ab_metadata(AvbABOps* ops,
1118 const struct AvbABData* data) {
1119 avb_ab_data_update_crc_and_byteswap(data, &my_serialized_data);
1120 return AVB_IO_RESULT_OK;
1121 }
1122
my_read_ab_metadata(AvbABOps * ops,struct AvbABData * data)1123 static AvbIOResult my_read_ab_metadata(AvbABOps* ops, struct AvbABData* data) {
1124 if (!avb_ab_data_verify_and_byteswap(&my_serialized_data, data)) {
1125 avb_error(
1126 "Error validating A/B metadata from persistent storage. "
1127 "Resetting and writing new A/B metadata to persistent storage.\n");
1128 avb_ab_data_init(data);
1129 return my_write_ab_metadata(ops, data);
1130 }
1131 return AVB_IO_RESULT_OK;
1132 }
1133
TEST_F(AvbABFlowTest,OtherMetadataStorage)1134 TEST_F(AvbABFlowTest, OtherMetadataStorage) {
1135 AvbSlotVerifyData* data;
1136 const char* requested_partitions[] = {"boot", NULL};
1137
1138 // Use our own A/B storage routines (see above).
1139 ops_.avb_ab_ops()->read_ab_metadata = my_read_ab_metadata;
1140 ops_.avb_ab_ops()->write_ab_metadata = my_write_ab_metadata;
1141
1142 SetMD(14,
1143 0,
1144 1,
1145 SV_OK,
1146 0,
1147 0, // A: pri, tries, success, slot_validity, RIs
1148 15,
1149 0,
1150 1,
1151 SV_OK,
1152 0,
1153 0, // B: pri, tries, success, slot_validity, RIs
1154 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1155 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
1156 avb_ab_flow(ops_.avb_ab_ops(),
1157 requested_partitions,
1158 false /* allow_verification_error */,
1159 &data));
1160 ExpMD(14,
1161 0,
1162 1, // A: pri, tries, successful
1163 15,
1164 0,
1165 1, // B: pri, tries, successful
1166 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1167 ASSERT_NE(nullptr, data);
1168 EXPECT_EQ("_b", std::string(data->ab_suffix));
1169 avb_slot_verify_data_free(data);
1170
1171 // Also check the other slot.
1172 SetMD(15,
1173 0,
1174 1,
1175 SV_OK,
1176 0,
1177 0, // A: pri, tries, success, slot_validity, RIs
1178 14,
1179 0,
1180 1,
1181 SV_OK,
1182 0,
1183 0, // B: pri, tries, success, slot_validity, RIs
1184 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1185 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK,
1186 avb_ab_flow(ops_.avb_ab_ops(),
1187 requested_partitions,
1188 false /* allow_verification_error */,
1189 &data));
1190 ExpMD(15,
1191 0,
1192 1, // A: pri, tries, successful
1193 14,
1194 0,
1195 1, // B: pri, tries, successful
1196 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1197 ASSERT_NE(nullptr, data);
1198 EXPECT_EQ("_a", std::string(data->ab_suffix));
1199 avb_slot_verify_data_free(data);
1200
1201 // Check that 'misc' hasn't been written to at all.
1202 std::string misc_data;
1203 base::FilePath misc_path = testdir_.Append("misc.img");
1204 ASSERT_TRUE(base::ReadFileToString(misc_path, &misc_data));
1205 EXPECT_EQ(size_t(MISC_PART_SIZE), misc_data.size());
1206 for (size_t n = 0; n < misc_data.size(); n++) {
1207 ASSERT_EQ(uint8_t(misc_data[n]), 0);
1208 }
1209 }
1210
TEST_F(AvbABFlowTest,UnlockedUnverifiedSlot)1211 TEST_F(AvbABFlowTest, UnlockedUnverifiedSlot) {
1212 AvbSlotVerifyData* data;
1213 const char* requested_partitions[] = {"boot", NULL};
1214
1215 SetMD(14,
1216 0,
1217 1,
1218 SV_OK,
1219 0,
1220 0, // A: pri, tries, success, slot_validity, RIs
1221 15,
1222 0,
1223 1,
1224 SV_UNV,
1225 0,
1226 0, // B: pri, tries, success, slot_validity, RIs
1227 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1228 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR,
1229 avb_ab_flow(ops_.avb_ab_ops(),
1230 requested_partitions,
1231 true /* allow_verification_error */,
1232 &data));
1233 ExpMD(14,
1234 0,
1235 1, // A: pri, tries, successful
1236 15,
1237 0,
1238 1, // B: pri, tries, successful
1239 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1240 ASSERT_NE(nullptr, data);
1241 EXPECT_EQ("_b", std::string(data->ab_suffix));
1242 avb_slot_verify_data_free(data);
1243
1244 // Also check the other slot.
1245 SetMD(15,
1246 0,
1247 1,
1248 SV_UNV,
1249 0,
1250 0, // A: pri, tries, success, slot_validity, RIs
1251 14,
1252 0,
1253 1,
1254 SV_OK,
1255 0,
1256 0, // B: pri, tries, success, slot_validity, RIs
1257 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1258 EXPECT_EQ(AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR,
1259 avb_ab_flow(ops_.avb_ab_ops(),
1260 requested_partitions,
1261 true /* allow_verification_error */,
1262 &data));
1263 ExpMD(15,
1264 0,
1265 1, // A: pri, tries, successful
1266 14,
1267 0,
1268 1, // B: pri, tries, successful
1269 MakeRollbackIndexes(0, 0)); // stored_rollback_indexes
1270 ASSERT_NE(nullptr, data);
1271 EXPECT_EQ("_a", std::string(data->ab_suffix));
1272 avb_slot_verify_data_free(data);
1273 }
1274
TEST_F(AvbABFlowTest,AvbtoolMetadataGeneratorEmptyFile)1275 TEST_F(AvbABFlowTest, AvbtoolMetadataGeneratorEmptyFile) {
1276 AvbABData data;
1277
1278 base::FilePath misc_path = testdir_.Append("misc.img");
1279 EXPECT_COMMAND(0,
1280 "./avbtool set_ab_metadata"
1281 " --misc_image %s"
1282 " --slot_data 13:3:0:11:2:1",
1283 misc_path.value().c_str());
1284
1285 EXPECT_EQ(AVB_IO_RESULT_OK,
1286 ops_.avb_ab_ops()->read_ab_metadata(ops_.avb_ab_ops(), &data));
1287 EXPECT_EQ(13, data.slots[0].priority);
1288 EXPECT_EQ(3, data.slots[0].tries_remaining);
1289 EXPECT_EQ(0, data.slots[0].successful_boot);
1290 EXPECT_EQ(11, data.slots[1].priority);
1291 EXPECT_EQ(2, data.slots[1].tries_remaining);
1292 EXPECT_EQ(1, data.slots[1].successful_boot);
1293 }
1294
TEST_F(AvbABFlowTest,AvbtoolMetadataGeneratorExistingFile)1295 TEST_F(AvbABFlowTest, AvbtoolMetadataGeneratorExistingFile) {
1296 AvbABData data;
1297 size_t n;
1298
1299 size_t misc_size = 1024 * 1024;
1300 base::FilePath misc_path = GenerateImage("misc.img", misc_size);
1301 EXPECT_COMMAND(0,
1302 "./avbtool set_ab_metadata"
1303 " --misc_image %s"
1304 " --slot_data 12:2:1:10:5:0",
1305 misc_path.value().c_str());
1306
1307 EXPECT_EQ(AVB_IO_RESULT_OK,
1308 ops_.avb_ab_ops()->read_ab_metadata(ops_.avb_ab_ops(), &data));
1309 EXPECT_EQ(12, data.slots[0].priority);
1310 EXPECT_EQ(2, data.slots[0].tries_remaining);
1311 EXPECT_EQ(1, data.slots[0].successful_boot);
1312 EXPECT_EQ(10, data.slots[1].priority);
1313 EXPECT_EQ(5, data.slots[1].tries_remaining);
1314 EXPECT_EQ(0, data.slots[1].successful_boot);
1315
1316 std::string misc_data;
1317 ASSERT_TRUE(base::ReadFileToString(misc_path, &misc_data));
1318 EXPECT_EQ(misc_size, misc_data.size());
1319 for (n = 0; n < 2048; n++) {
1320 ASSERT_EQ(uint8_t(misc_data[n]), uint8_t(n));
1321 }
1322 for (n = 2048 + 32; n < misc_data.size(); n++) {
1323 ASSERT_EQ(uint8_t(misc_data[n]), uint8_t(n));
1324 }
1325 }
1326
1327 } // namespace avb
1328