1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "nandpart-utils.h"
6
7 #include <fbl/unique_ptr.h>
8 #include <unittest/unittest.h>
9 #include <zircon/types.h>
10
11 namespace nand {
12 namespace {
13
14 constexpr uint32_t kPageSize = ZX_PAGE_SIZE;
15 constexpr uint32_t kPagesPerBlock = 2;
16 constexpr uint32_t kNumBlocks = 5;
17 constexpr uint32_t kOobSize = 8;
18 constexpr fuchsia_hardware_nand_Info kNandInfo = {
19 .page_size = kPageSize,
20 .pages_per_block = kPagesPerBlock,
21 .num_blocks = kNumBlocks,
22 .ecc_bits = 2,
23 .oob_size = kOobSize,
24 .nand_class = fuchsia_hardware_nand_Class_BBS,
25 .partition_guid = {},
26 };
27
MakePartitionMap(uint32_t partition_count)28 zbi_partition_map_t MakePartitionMap(uint32_t partition_count) {
29 return zbi_partition_map_t{
30 .block_count = kNumBlocks * kPagesPerBlock,
31 .block_size = kPageSize,
32 .partition_count = partition_count,
33 .reserved = 0,
34 .guid = {},
35 .partitions = {},
36 };
37 }
38
MakePartition(uint32_t first_block,uint32_t last_block)39 zbi_partition_t MakePartition(uint32_t first_block, uint32_t last_block) {
40 return zbi_partition_t{
41 .type_guid = {},
42 .uniq_guid = {},
43 .first_block = first_block,
44 .last_block = last_block,
45 .flags = 0,
46 .name = {},
47 };
48 }
49
ValidatePartition(zbi_partition_map_t * pmap,size_t partition_number,uint32_t first_block,uint32_t last_block)50 bool ValidatePartition(zbi_partition_map_t* pmap, size_t partition_number, uint32_t first_block,
51 uint32_t last_block) {
52 BEGIN_HELPER;
53 EXPECT_EQ(pmap->partitions[partition_number].first_block, first_block);
54 EXPECT_EQ(pmap->partitions[partition_number].last_block, last_block);
55 END_HELPER;
56 }
57
SanitizeEmptyPartitionMapTest()58 bool SanitizeEmptyPartitionMapTest() {
59 BEGIN_TEST;
60 auto pmap = MakePartitionMap(0);
61 ASSERT_NE(SanitizePartitionMap(&pmap, kNandInfo), ZX_OK);
62 END_TEST;
63 }
64
SanitizeSinglePartitionMapTest()65 bool SanitizeSinglePartitionMapTest() {
66 BEGIN_TEST;
67 fbl::unique_ptr<uint8_t[]> pmap_buffer(new uint8_t[sizeof(zbi_partition_map_t) +
68 sizeof(zbi_partition_t)]);
69 auto* pmap = reinterpret_cast<zbi_partition_map_t*>(pmap_buffer.get());
70 *pmap = MakePartitionMap(1);
71 pmap->partitions[0] = MakePartition(0, 9);
72 ASSERT_EQ(SanitizePartitionMap(pmap, kNandInfo), ZX_OK);
73 ASSERT_TRUE(ValidatePartition(pmap, 0, 0, 4));
74 END_TEST;
75 }
76
SanitizeMultiplePartitionMapTest()77 bool SanitizeMultiplePartitionMapTest() {
78 BEGIN_TEST;
79 fbl::unique_ptr<uint8_t[]> pmap_buffer(new uint8_t[sizeof(zbi_partition_map_t) +
80 3 * sizeof(zbi_partition_t)]);
81 auto* pmap = reinterpret_cast<zbi_partition_map_t*>(pmap_buffer.get());
82 *pmap = MakePartitionMap(3);
83 pmap->partitions[0] = MakePartition(0, 3);
84 pmap->partitions[1] = MakePartition(4, 7);
85 pmap->partitions[2] = MakePartition(8, 9);
86
87 ASSERT_EQ(SanitizePartitionMap(pmap, kNandInfo), ZX_OK);
88 ASSERT_TRUE(ValidatePartition(pmap, 0, 0, 1));
89 ASSERT_TRUE(ValidatePartition(pmap, 1, 2, 3));
90 ASSERT_TRUE(ValidatePartition(pmap, 2, 4, 4));
91 END_TEST;
92 }
93
SanitizeMultiplePartitionMapOutOfOrderTest()94 bool SanitizeMultiplePartitionMapOutOfOrderTest() {
95 BEGIN_TEST;
96 fbl::unique_ptr<uint8_t[]> pmap_buffer(new uint8_t[sizeof(zbi_partition_map_t) +
97 2 * sizeof(zbi_partition_t)]);
98 auto* pmap = reinterpret_cast<zbi_partition_map_t*>(pmap_buffer.get());
99 *pmap = MakePartitionMap(2);
100 pmap->partitions[0] = MakePartition(4, 9);
101 pmap->partitions[1] = MakePartition(0, 3);
102
103 ASSERT_EQ(SanitizePartitionMap(pmap, kNandInfo), ZX_OK);
104 ASSERT_TRUE(ValidatePartition(pmap, 0, 0, 1));
105 ASSERT_TRUE(ValidatePartition(pmap, 1, 2, 4));
106 END_TEST;
107 }
108
SanitizeMultiplePartitionMapOverlappingTest()109 bool SanitizeMultiplePartitionMapOverlappingTest() {
110 BEGIN_TEST;
111 fbl::unique_ptr<uint8_t[]> pmap_buffer(new uint8_t[sizeof(zbi_partition_map_t) +
112 3 * sizeof(zbi_partition_t)]);
113 auto* pmap = reinterpret_cast<zbi_partition_map_t*>(pmap_buffer.get());
114 *pmap = MakePartitionMap(3);
115 pmap->partitions[0] = MakePartition(0, 3);
116 pmap->partitions[1] = MakePartition(8, 9);
117 pmap->partitions[2] = MakePartition(4, 8);
118
119 ASSERT_NE(SanitizePartitionMap(pmap, kNandInfo), ZX_OK);
120 END_TEST;
121 }
122
SanitizePartitionMapBadRangeTest()123 bool SanitizePartitionMapBadRangeTest() {
124 BEGIN_TEST;
125 fbl::unique_ptr<uint8_t[]> pmap_buffer(new uint8_t[sizeof(zbi_partition_map_t) +
126 2 * sizeof(zbi_partition_t)]);
127 auto* pmap = reinterpret_cast<zbi_partition_map_t*>(pmap_buffer.get());
128 *pmap = MakePartitionMap(2);
129 pmap->partitions[0] = MakePartition(1, 0);
130 pmap->partitions[1] = MakePartition(1, 9);
131
132 ASSERT_NE(SanitizePartitionMap(pmap, kNandInfo), ZX_OK);
133 END_TEST;
134 }
135
SanitizePartitionMapUnalignedTest()136 bool SanitizePartitionMapUnalignedTest() {
137 BEGIN_TEST;
138 fbl::unique_ptr<uint8_t[]> pmap_buffer(new uint8_t[sizeof(zbi_partition_map_t) +
139 2 * sizeof(zbi_partition_t)]);
140 auto* pmap = reinterpret_cast<zbi_partition_map_t*>(pmap_buffer.get());
141 *pmap = MakePartitionMap(2);
142 pmap->partitions[0] = MakePartition(0, 3);
143 pmap->partitions[1] = MakePartition(5, 8);
144
145 ASSERT_NE(SanitizePartitionMap(pmap, kNandInfo), ZX_OK);
146 END_TEST;
147 }
148
SanitizePartitionMapOutofBoundsTest()149 bool SanitizePartitionMapOutofBoundsTest() {
150 BEGIN_TEST;
151 fbl::unique_ptr<uint8_t[]> pmap_buffer(new uint8_t[sizeof(zbi_partition_map_t) +
152 2 * sizeof(zbi_partition_t)]);
153 auto* pmap = reinterpret_cast<zbi_partition_map_t*>(pmap_buffer.get());
154 *pmap = MakePartitionMap(2);
155 pmap->partitions[0] = MakePartition(0, 3);
156 pmap->partitions[1] = MakePartition(4, 11);
157
158 ASSERT_NE(SanitizePartitionMap(pmap, kNandInfo), ZX_OK);
159 END_TEST;
160 }
161
162 } // namespace
163 } // namespace nand
164
165 BEGIN_TEST_CASE(NandpartUtilsTests)
166 RUN_TEST(nand::SanitizeEmptyPartitionMapTest)
167 RUN_TEST(nand::SanitizeSinglePartitionMapTest)
168 RUN_TEST(nand::SanitizeMultiplePartitionMapTest)
169 RUN_TEST(nand::SanitizeMultiplePartitionMapOutOfOrderTest)
170 RUN_TEST(nand::SanitizeMultiplePartitionMapOverlappingTest)
171 RUN_TEST(nand::SanitizePartitionMapBadRangeTest)
172 RUN_TEST(nand::SanitizePartitionMapUnalignedTest)
173 RUN_TEST(nand::SanitizePartitionMapOutofBoundsTest)
174 END_TEST_CASE(NandpartUtilsTests);
175