1 /*
2 * Copyright (C) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "hc_file_iot_flash_test.h"
17
18 #include <hctest.h>
19 #include <iot_errno.h>
20 #include <iot_flash.h>
21 #include <securec.h>
22 #include <stdbool.h>
23 #include <stdint.h>
24 #include <stdlib.h>
25
26 #include "print_log.h"
27 #include "test_timer.h"
28
29 #ifdef __cplusplus
30 extern "C" {
31 #endif
32
33 #if FLASH_START_ADDRESS_HICHAIN
34
35 #define FLASH_SIZE_4_K 4096
36
37 #define TOTAL_STORAGE_SIZE FLASH_SIZE_4_K // 4K Bytes
38 #define GROUP_OFFSET_ADDR 0x0100 // sizeof(struct FlashHeader)
39 #define TCIS_OFFSET_ADDR 0x0BC0
40 #define KEY_OFFSET_ADDR 0x0DC0
41 #define PART2_OFFSET_ADDR 0x0EC0
42 #define PART3_OFFSET_ADDR 0x0F00
43 #define SALT_OFFSET_ADDR 0x0F40
44 #define MK_OFFSET_ADDR 0x0F80
45 #define MAGIC_NUM 0x07DECADE
46 #define DEFAULT_VERSION 0x01
47
48 typedef enum FileIdEnumT {
49 FILE_ID_GROUP = 0,
50 FILE_ID_TCIS_DATA,
51 FILE_ID_KEYCONTENT,
52 FILE_ID_PART2,
53 FILE_ID_PART3,
54 FILE_ID_SALT,
55 FILE_ID_MK,
56 FILE_ID_LAST,
57 } FileIdEnum;
58
59 static uint32_t g_startAddr = FLASH_START_ADDRESS_HICHAIN;
60
61 static const struct FlashHeader {
62 struct VersionHeader {
63 uint64_t magic;
64 uint16_t version;
65 uint8_t reserved[54]; // 54: Reserved bytes for expansion
66 } versionHeader;
67 struct FileHeader {
68 uint32_t start;
69 uint32_t size;
70 uint32_t end;
71 } fileHeaders[FILE_ID_LAST];
72 uint8_t reserved[108]; // 108: Reserved bytes for expansion
73 } g_flashHeader = {
74 .versionHeader = {
75 .magic = MAGIC_NUM,
76 .version = DEFAULT_VERSION,
77 },
78 .fileHeaders[FILE_ID_GROUP] = {
79 .start = GROUP_OFFSET_ADDR,
80 .size = TCIS_OFFSET_ADDR - GROUP_OFFSET_ADDR,
81 .end = TCIS_OFFSET_ADDR,
82 },
83 .fileHeaders[FILE_ID_TCIS_DATA] = {
84 .start = TCIS_OFFSET_ADDR,
85 .size = KEY_OFFSET_ADDR - TCIS_OFFSET_ADDR,
86 .end = KEY_OFFSET_ADDR,
87 },
88 .fileHeaders[FILE_ID_KEYCONTENT] = {
89 .start = KEY_OFFSET_ADDR,
90 .size = PART2_OFFSET_ADDR - KEY_OFFSET_ADDR,
91 .end = PART2_OFFSET_ADDR,
92 },
93 .fileHeaders[FILE_ID_PART2] = {
94 .start = PART2_OFFSET_ADDR,
95 .size = PART3_OFFSET_ADDR - PART2_OFFSET_ADDR,
96 .end = PART3_OFFSET_ADDR,
97 },
98 .fileHeaders[FILE_ID_PART3] = {
99 .start = PART3_OFFSET_ADDR,
100 .size = SALT_OFFSET_ADDR - PART3_OFFSET_ADDR,
101 .end = SALT_OFFSET_ADDR,
102 },
103 .fileHeaders[FILE_ID_SALT] = {
104 .start = SALT_OFFSET_ADDR,
105 .size = MK_OFFSET_ADDR - SALT_OFFSET_ADDR,
106 .end = MK_OFFSET_ADDR,
107 },
108 .fileHeaders[FILE_ID_MK] = {
109 .start = MK_OFFSET_ADDR,
110 .size = TOTAL_STORAGE_SIZE - MK_OFFSET_ADDR,
111 .end = TOTAL_STORAGE_SIZE,
112 },
113 };
114
115 enum {
116 RANDOM_READ_TIMES = 20,
117 };
118
ReadFlash(uint32_t offset,uint8_t * buffer,uint32_t size)119 static void ReadFlash(uint32_t offset, uint8_t *buffer, uint32_t size)
120 {
121 int res;
122 RUN_AND_PRINT_ELAPSED_TIME(res, IoTFlashInit());
123 TEST_ASSERT_EQUAL(IOT_SUCCESS, res);
124
125 RUN_AND_PRINT_ELAPSED_TIME(res, IoTFlashRead(g_startAddr + offset, size, buffer));
126 TEST_ASSERT_EQUAL(IOT_SUCCESS, res);
127
128 RUN_AND_PRINT_ELAPSED_TIME(res, IoTFlashDeinit());
129 TEST_ASSERT_EQUAL(IOT_SUCCESS, res);
130 }
131
WriteFlash(uint32_t offset,const uint8_t * buffer,uint32_t size)132 static void WriteFlash(uint32_t offset, const uint8_t *buffer, uint32_t size)
133 {
134 int res;
135 RUN_AND_PRINT_ELAPSED_TIME(res, IoTFlashInit());
136 TEST_ASSERT_EQUAL(IOT_SUCCESS, res);
137
138 LOGI("begin write, g_startAddr + offset = %lu, size = %lu, buffer = %p",
139 (unsigned long)(g_startAddr + offset), (unsigned long)(size), buffer);
140 RUN_AND_PRINT_ELAPSED_TIME(res, IoTFlashWrite(g_startAddr + offset, size, buffer, true));
141 TEST_ASSERT_EQUAL(IOT_SUCCESS, res);
142
143 RUN_AND_PRINT_ELAPSED_TIME(res, IoTFlashDeinit());
144 TEST_ASSERT_EQUAL(IOT_SUCCESS, res);
145 }
146
TestIotFlashWrite(const uint8_t * totalDataContent,uint32_t sz)147 static void TestIotFlashWrite(const uint8_t *totalDataContent, uint32_t sz)
148 {
149 LOGI("begin to test writing flash");
150 WriteFlash(0, totalDataContent, sz);
151 LOGI("test writing flash done");
152 }
153
TestIotFlashReadWholeBlock(uint8_t * totalData,uint32_t sz,const uint8_t * totalDataContent,uint32_t contentSz)154 static void TestIotFlashReadWholeBlock(
155 uint8_t *totalData, uint32_t sz, const uint8_t *totalDataContent, uint32_t contentSz)
156 {
157 int res = memset_s(totalData, sz, 0, sz);
158 TEST_ASSERT_EQUAL(EOK, res);
159 LOGI("begin to test read whole flash");
160 ReadFlash(0, totalData, sz);
161 LOGI("test reading whole flash done");
162
163 TEST_ASSERT_EQUAL(sz, contentSz);
164 TEST_ASSERT_EQUAL_HEX8_ARRAY(totalData, totalDataContent, sz);
165 }
166
TestIotFlashReadFlashHeader(struct FlashHeader * flashHeader,const struct FlashHeader * flashHeaderCompare)167 static void TestIotFlashReadFlashHeader(
168 struct FlashHeader *flashHeader, const struct FlashHeader *flashHeaderCompare)
169 {
170 int res = memset_s(flashHeader, sizeof(*flashHeader), 0, sizeof(*flashHeader));
171 TEST_ASSERT_EQUAL(EOK, res);
172 LOGI("begin reading header");
173 ReadFlash(0, (uint8_t *)flashHeader, sizeof(struct FlashHeader));
174 LOGI("end reading header");
175
176 TEST_ASSERT_EQUAL_HEX8_ARRAY((const uint8_t *)flashHeader, (const uint8_t *)flashHeaderCompare,
177 sizeof(struct FlashHeader));
178 }
179
TestIotFlashReadSmallFiles(uint8_t * totalData,uint32_t sz,const uint8_t * totalDataContent,uint32_t contentSz)180 static void TestIotFlashReadSmallFiles(
181 uint8_t *totalData, uint32_t sz, const uint8_t *totalDataContent, uint32_t contentSz)
182 {
183 LOGI("begin reading small files");
184 TEST_ASSERT_EQUAL((uint32_t)(TOTAL_STORAGE_SIZE), contentSz);
185 int res;
186 for (int i = 0; i < FILE_ID_LAST; ++i) {
187 LOGI("test flash file %d/%d", i, FILE_ID_LAST);
188 res = memset_s(totalData, sz, 0, sz);
189 TEST_ASSERT_EQUAL(EOK, res);
190
191 LOGI("test read from %lu, size %lu", (unsigned long)(g_flashHeader.fileHeaders[i].start),
192 (unsigned long)(g_flashHeader.fileHeaders[i].size));
193 ReadFlash(g_flashHeader.fileHeaders[i].start, totalData, g_flashHeader.fileHeaders[i].size);
194
195 TEST_ASSERT_EQUAL_HEX8_ARRAY(totalData, totalDataContent + g_flashHeader.fileHeaders[i].start,
196 g_flashHeader.fileHeaders[i].size);
197 }
198 LOGI("end reading small files");
199 }
200
TestIotFlashReadRandom(uint8_t * totalData,uint32_t sz,const uint8_t * totalDataContent,uint32_t contentSz)201 static void TestIotFlashReadRandom(uint8_t *totalData, uint32_t sz, const uint8_t *totalDataContent, uint32_t contentSz)
202 {
203 LOGI("begin reading random bytes");
204 TEST_ASSERT_EQUAL((uint32_t)(TOTAL_STORAGE_SIZE), contentSz);
205 int res;
206 for (int i = 0; i < RANDOM_READ_TIMES; ++i) {
207 uint32_t startAddr = rand() % TOTAL_STORAGE_SIZE;
208 uint32_t size = rand() % (TOTAL_STORAGE_SIZE - startAddr);
209 LOGI("test random read flash %d/%d, startAddr = %lu, size = %lu", i,
210 RANDOM_READ_TIMES, (unsigned long)(startAddr), (unsigned long)(size));
211 res = memset_s(totalData, sz, 0, sz);
212 TEST_ASSERT_EQUAL(EOK, res);
213 ReadFlash(startAddr, totalData, size);
214 TEST_ASSERT_EQUAL_HEX8_ARRAY(totalData, totalDataContent + startAddr, size);
215 }
216 LOGI("end reading random bytes");
217
218 LOGI("begin reading small bytes");
219 for (int i = 0; i < RANDOM_READ_TIMES; ++i) {
220 uint32_t size = i + 1;
221 uint32_t startAddr = rand() % (TOTAL_STORAGE_SIZE - size);
222 LOGI("test random read flash %d/%d, startAddr = %lu, size = %lu", i,
223 RANDOM_READ_TIMES, (unsigned long)(startAddr), (unsigned long)(size));
224 res = memset_s(totalData, sz, 0, sz);
225 TEST_ASSERT_EQUAL(EOK, res);
226 ReadFlash(startAddr, totalData, size);
227 TEST_ASSERT_EQUAL_HEX8_ARRAY(totalData, totalDataContent + startAddr, size);
228 }
229 LOGI("end reading small bytes");
230 }
231
TestHcFileIotFlash(void)232 void TestHcFileIotFlash(void)
233 {
234 uint8_t *totalData = (uint8_t *)malloc(TOTAL_STORAGE_SIZE);
235 TEST_ASSERT_NOT_NULL(totalData);
236 uint8_t *totalDataContent = (uint8_t *)malloc(TOTAL_STORAGE_SIZE);
237 TEST_ASSERT_NOT_NULL(totalDataContent);
238 LOGI("malloc memory succeed");
239
240 int res, zeroCount = 0;
241 struct FlashHeader flashHeader;
242 res = memset_s(&flashHeader, sizeof(flashHeader), 0, sizeof(flashHeader));
243 TEST_ASSERT_EQUAL(EOK, res);
244 for (uint32_t i = 0; i < TOTAL_STORAGE_SIZE; ++i) {
245 totalDataContent[i] = rand() % UINT8_MAX;
246 if (totalDataContent[i] == 0) {
247 ++zeroCount;
248 }
249 }
250 TEST_ASSERT_NOT_EQUAL(TOTAL_STORAGE_SIZE, zeroCount);
251
252 TestIotFlashWrite(totalDataContent, TOTAL_STORAGE_SIZE);
253
254 TestIotFlashReadWholeBlock(totalData, TOTAL_STORAGE_SIZE, totalDataContent, TOTAL_STORAGE_SIZE);
255
256 TestIotFlashReadFlashHeader(&flashHeader, (struct FlashHeader *)totalDataContent);
257
258 TestIotFlashReadSmallFiles(totalData, TOTAL_STORAGE_SIZE, totalDataContent, TOTAL_STORAGE_SIZE);
259
260 TestIotFlashReadRandom(totalData, TOTAL_STORAGE_SIZE, totalDataContent, TOTAL_STORAGE_SIZE);
261
262 free(totalData);
263 free(totalDataContent);
264 }
265
266 #else // FLASH_START_ADDRESS_HICHAIN
267
268 void TestHcFileIotFlash(void)
269 {
270 LOGE("no FLASH_START_ADDRESS_HICHAIN, do not test iot flash");
271 }
272
273 #endif // FLASH_START_ADDRESS_HICHAIN
274
275 #ifdef __cplusplus
276 }
277 #endif
278