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