1 #include <string.h>
2 #include "ota_port.h"
3 #include "hal_trace.h"
4 #include "hal_norflash.h"
5 #include "cmsis_os.h"
6 #include "cmsis.h"
7 #include "pmu.h"
8 #include "aos/hal/flash.h"
9 #include "aos/mtd.h"
10 #include <vfsdev/flash_dev.h>
11 #include "aos/mtdpart.h"
12
13 extern const hal_logic_partition_t hal_partitions[];
14 extern osMutexId FlashMutex;
15 extern osMutexDef_t os_mutex_def_flash;
16 extern enum ota_link ota_current_link;
17
18 #define EXCEPTION_REBOOT_COUNT_MAX 5
19
20 ota_bin_partition ota_bin[] =
21 {
22 {"ota_boot2a.bin", HAL_PARTITION_BOOT1},
23 {"ota_boot2b.bin", HAL_PARTITION_BOOT1_REDUND},
24 {"ota_rtos.bin", HAL_PARTITION_APPLICATION},
25 {"littlefs.bin", HAL_PARTITION_LITTLEFS},
26 };
27
FlashosMutexWait(void)28 static void FlashosMutexWait(void)
29 {
30 if(FlashMutex == NULL)
31 {
32 FlashMutex = osMutexCreate(&os_mutex_def_flash);
33 }
34
35 osMutexWait(FlashMutex, osWaitForever);
36 }
37
ota_get_bootinfo(struct ota_boot_info * info,enum bootinfo_zone zone)38 int ota_get_bootinfo(struct ota_boot_info *info, enum bootinfo_zone zone)
39 {
40 uint32_t lock = 0;
41 uint32_t start_addr = 0;
42 mtd_partition_t* partition_info;
43 volatile char *flashPointer = NULL;
44
45 if (zone >= OTA_BOOTINFO_ZONEMAX) {
46 TRACE("error %s %d, zone:%d", __func__, __LINE__, zone);
47 return OTA_FAILE;
48 }
49 partition_info = (mtd_partition_t *)&mtd_partitions[MTD_PART_ID_ENV2];
50 if(partition_info == NULL) {
51 return OTA_FAILE;
52 }
53 if (zone == OTA_BOOTINFO_ZONEA) {
54 start_addr = partition_info->partition_start_addr;
55 } else if (zone == OTA_BOOTINFO_ZONEB) {
56 start_addr = partition_info->partition_start_addr + OTA_BOOT_INFO_SIZE;
57 }
58
59 lock = int_lock();
60 flashPointer = (volatile char *)(FLASH_NC_BASE + start_addr);
61 memcpy((uint8_t*)info, (void *)flashPointer, sizeof(struct ota_boot_info));
62 int_unlock(lock);
63
64 return 0;
65 }
66
ota_set_bootinfo_crc32value(struct ota_boot_info * info)67 int ota_set_bootinfo_crc32value(struct ota_boot_info *info)
68 {
69 uint32_t crc32_value = 0;
70 uint8_t *flash_pointer = NULL;
71
72 flash_pointer = (uint8_t *)(info);
73 crc32_value = crc32(crc32_value, (uint8_t *)(flash_pointer + OTA_BOOT_INFO_HEAD_LEN), info->info_len);
74 info->crc32 = crc32_value;
75
76 return 0;
77 }
78
ota_set_bootinfo(struct ota_boot_info * info,enum bootinfo_zone zone)79 int ota_set_bootinfo(struct ota_boot_info *info, enum bootinfo_zone zone)
80 {
81 int ret = 0;
82 uint32_t lock = 0;
83 uint32_t start_addr = 0;
84 uint8_t buffer[FLASH_SECTOR_SIZE_IN_BYTES] = {0};
85 mtd_partition_t* partition_info = NULL;
86
87 if (zone >= OTA_BOOTINFO_ZONEMAX) {
88 TRACE("error %s %d, zone:%d", __func__, __LINE__, zone);
89 return OTA_FAILE;
90 }
91
92 ret = ota_set_bootinfo_crc32value(info);
93 if (ret) {
94 return OTA_FAILE;
95 }
96 partition_info = (mtd_partition_t *)&mtd_partitions[MTD_PART_ID_ENV2];
97 if(partition_info == NULL) {
98 return OTA_FAILE;
99 }
100 if (zone == OTA_BOOTINFO_ZONEA) {
101 start_addr = partition_info->partition_start_addr;
102 } else if (zone == OTA_BOOTINFO_ZONEB) {
103 start_addr = partition_info->partition_start_addr + OTA_BOOT_INFO_SIZE;
104 }
105
106 lock = int_lock();
107 pmu_flash_write_config();
108
109 memcpy(buffer, (uint8_t *)info, sizeof(struct ota_boot_info));
110 ret = hal_norflash_erase(HAL_NORFLASH_ID_0, start_addr, FLASH_SECTOR_SIZE_IN_BYTES);
111 if (ret != HAL_NORFLASH_OK) {
112 TRACE("error %s %d, ret:%d", __func__, __LINE__, ret);
113 goto end;
114 }
115
116 ret = hal_norflash_write(HAL_NORFLASH_ID_0, start_addr, buffer, FLASH_SECTOR_SIZE_IN_BYTES);
117 if (ret != HAL_NORFLASH_OK) {
118 TRACE("error %s %d, ret:%d", __func__, __LINE__, ret);
119 goto end;
120 }
121
122 end:
123 pmu_flash_read_config();
124 int_unlock(lock);
125
126 return ret;
127 }
128
ota_set_bootinfo_to_zoneAB(struct ota_boot_info * info)129 int ota_set_bootinfo_to_zoneAB(struct ota_boot_info *info)
130 {
131 int ret = 0;
132
133 ret = ota_set_bootinfo(info, OTA_BOOTINFO_ZONEA);
134 if (ret) {
135 TRACE("error %s %d, ota_set_bootinfo return %d", __func__, __LINE__, ret);
136 }
137
138 ret = ota_set_bootinfo(info, OTA_BOOTINFO_ZONEB);
139 if (ret) {
140 TRACE("error %s %d, ota_set_bootinfo return %d", __func__, __LINE__, ret);
141 }
142
143 return ret;
144 }
145
ota_check_bootinfo(enum bootinfo_zone zone)146 int ota_check_bootinfo(enum bootinfo_zone zone)
147 {
148 uint32_t crc32_value = 0;
149 uint32_t flash_offset = 0;
150 uint8_t *flash_pointer = NULL;
151 mtd_partition_t *partition_info = NULL;
152 const struct ota_boot_info *info;
153
154 if (zone >= OTA_BOOTINFO_ZONEMAX) {
155 TRACE("%s %d, error zone:%d", __func__, __LINE__, zone);
156 return OTA_FAILE;
157 }
158 partition_info = (mtd_partition_t *)&mtd_partitions[MTD_PART_ID_ENV2];
159 if(partition_info == NULL) {
160 return OTA_FAILE;
161 }
162
163 //get boot info to choose linkA or linkB.
164 if (zone == OTA_BOOTINFO_ZONEA) {
165 flash_offset = partition_info->partition_start_addr;
166 } else if (zone == OTA_BOOTINFO_ZONEB) {
167 flash_offset = partition_info->partition_start_addr + OTA_BOOT_INFO_SIZE; //boot info zoneB start address
168 }
169
170 info = (const struct ota_boot_info *)(FLASH_NC_BASE + flash_offset);
171 if (info->update_link >= OTA_LINK_MAX) {
172 TRACE("%s %d, error info->update_link:%d", __func__, __LINE__, info->update_link);
173 return OTA_FAILE;
174 } else if ((info->update_link == OTA_LINK_A) && (info->linkA_used_flag != OTA_LINK_USED)) {
175 TRACE("%s %d, error info->linkA_used_flag:%d", __func__, __LINE__, info->linkA_used_flag);
176 return OTA_FAILE;
177 } else if ((info->update_link == OTA_LINK_B) && (info->linkB_used_flag != OTA_LINK_USED)) {
178 TRACE("%s %d, error info->linkB_used_flag:%d", __func__, __LINE__, info->linkB_used_flag);
179 return OTA_FAILE;
180 }
181
182 flash_pointer = (uint8_t *)(info);
183 crc32_value = crc32(crc32_value, (uint8_t *)(flash_pointer + OTA_BOOT_INFO_HEAD_LEN), info->info_len);
184 if (crc32_value != info->crc32) {
185 TRACE("%s %d, error info->crc32:0x%x, crc32_value:0x%x", __func__, __LINE__, info->crc32, crc32_value);
186 return OTA_FAILE;
187 }
188
189 return OTA_OK;
190 }
191
ota_set_zoneAB_bootinfo_to_default(void)192 void ota_set_zoneAB_bootinfo_to_default(void)
193 {
194 struct ota_boot_info info;
195 int ret = 0;
196
197 TRACE("%s %d", __func__, __LINE__);
198
199 //set boot info to A and B.
200 memset(&info, 0, sizeof(struct ota_boot_info));
201 info.linkA_used_flag = OTA_LINK_USED;
202 info.linkB_used_flag = OTA_LINK_USED; //if RTOSB not write, set OTA_LINK_NOTUSED.
203 info.info_len = OTA_BOOT_INFO_BODY_LEN;
204 info.odm_type = 0;
205 info.reserved = 0;
206 info.update_link = OTA_LINK_A; //default:OTA_LINK_A
207 info.reboot_reason = 0;
208 info.crash_reboot_count = 0;
209 info.secureERR_reboot_count = 0;
210 info.reboot_count_max = EXCEPTION_REBOOT_COUNT_MAX;
211 info.fallback_disable = 1;
212
213 ret = ota_set_bootinfo_to_zoneAB(&info);
214 if (ret) {
215 TRACE("error %s %d, ret:%d", __func__, __LINE__, ret);
216 return;
217 }
218 }
219
ota_get_valid_bootinfo_zone(void)220 enum bootinfo_zone ota_get_valid_bootinfo_zone(void)
221 {
222 enum bootinfo_zone ret = OTA_BOOTINFO_ZONEA;
223
224 //get boot info to choose linkA or linkB.
225 ret = ota_check_bootinfo(OTA_BOOTINFO_ZONEA);
226 if (!ret) {
227 return OTA_BOOTINFO_ZONEA;
228 } else {
229 ret = ota_check_bootinfo(OTA_BOOTINFO_ZONEB);
230 if (!ret) {
231 return OTA_BOOTINFO_ZONEB;
232 } else { //first boot or both boot info bad, set both to default.
233 ota_set_zoneAB_bootinfo_to_default();
234 return OTA_BOOTINFO_ZONEA;
235 }
236 }
237 }
238
ota_adapt_get_odm_type(void)239 ODM_TYPE ota_adapt_get_odm_type(void)
240 {
241 int32_t ret = 0;
242 struct ota_boot_info boot_info;
243 enum bootinfo_zone zone;
244
245 zone = ota_get_valid_bootinfo_zone();
246 ret = ota_get_bootinfo(&boot_info, zone);
247 if (ret) {
248 TRACE("error %s %d, ret:%d", __func__, __LINE__, ret);
249 return ALI_ODM_MAX;
250 }
251
252 return boot_info.odm_type;
253 }
254
ota_adapt_set_odm_type(ODM_TYPE type)255 int ota_adapt_set_odm_type(ODM_TYPE type)
256 {
257 int32_t ret = 0;
258 struct ota_boot_info boot_info;
259 enum bootinfo_zone zone;
260
261 if (type >= ALI_ODM_MAX) {
262 return -1;
263 }
264
265 zone = ota_get_valid_bootinfo_zone();
266 ret = ota_get_bootinfo(&boot_info, zone);
267 if (ret) {
268 TRACE("error %s %d, ret:%d", __func__, __LINE__, ret);
269 return ret;
270 }
271
272 boot_info.odm_type = type;
273 ret = ota_set_bootinfo_to_zoneAB(&boot_info);
274 if (ret) {
275 TRACE("error %s %d, ret:%d", __func__, __LINE__, ret);
276 }
277
278 return ret;
279 }
280
ota_copy_bootinfo_fromone_toanother(enum bootinfo_zone to_zone,enum bootinfo_zone from_zone)281 int ota_copy_bootinfo_fromone_toanother(enum bootinfo_zone to_zone, enum bootinfo_zone from_zone)
282 {
283 struct ota_boot_info info;
284 int32_t ret = 0;
285
286 if ((to_zone >= OTA_BOOTINFO_ZONEMAX) || (from_zone >= OTA_BOOTINFO_ZONEMAX)) {
287 //TRACE("%s %d, error zone:%d", __func__, __LINE__, zone);
288 return -1;
289 }
290
291 //get boot info from from_zone.
292 ret = ota_get_bootinfo(&info, from_zone);
293 if (ret) {
294 TRACE("%s %d, ota_get_bootinfo return fail", __func__, __LINE__);
295 return -1;
296 }
297
298 //set boot info to to_zone.
299 ret = ota_set_bootinfo(&info, to_zone);
300 if (ret) {
301 TRACE("%s %d, ota_get_bootinfo return fail", __func__, __LINE__);
302 return -1;
303 }
304
305 return ret;
306 }
307
308 /**
309 * @brief Get current active A/B slot
310 *
311 * @returns "a" if current slot is A, or "b" if current slot is B.
312 */
tg_ota_get_current_ab(void)313 const char* tg_ota_get_current_ab(void)
314 {
315 int32_t ret = 0;
316 struct ota_boot_info boot_info;
317 enum bootinfo_zone zone;
318
319 zone = ota_get_valid_bootinfo_zone();
320 ret = ota_get_bootinfo(&boot_info, zone);
321 if (ret) {
322 return NULL;
323 }
324
325 if (boot_info.update_link == OTA_LINK_A) {
326 return "a";
327 } else if (boot_info.update_link == OTA_LINK_B) {
328 return "b";
329 }
330 return NULL;
331 }
332
333 /**
334 * @return: - 0: success; - -1: fail
335 */
ota_upgrade_link()336 int ota_upgrade_link()
337 {
338 int32_t ret = -1;
339 struct ota_boot_info info;
340 enum bootinfo_zone zone;
341
342 if (ota_current_link == OTA_LINK_ERR) {
343 zone = ota_get_valid_bootinfo_zone();
344 ret = ota_get_bootinfo(&info, zone);
345 if (ret != 0) {
346 return -1;
347 }
348 ota_current_link = info.update_link;
349 }
350
351 if ((ota_current_link == OTA_LINK_A) || (ota_current_link == OTA_LINK_B)) {
352 zone = ota_get_valid_bootinfo_zone();
353 ret = ota_get_bootinfo(&info, zone);
354 if (ret != 0) {
355 return -1;
356 }
357
358 if (ota_current_link == OTA_LINK_B) {
359 info.linkA_used_flag = OTA_LINK_USED;
360 info.update_link = OTA_LINK_A;
361 } if (ota_current_link == OTA_LINK_A) {
362 info.linkB_used_flag = OTA_LINK_USED;
363 info.update_link = OTA_LINK_B;
364 }
365
366 info.crash_reboot_count = 0; //reset to 0
367 info.secureERR_reboot_count = 0; //reset to 0
368 info.reboot_reason = 0;
369 info.fallback_disable = 0; //enable fallback
370
371 ret = ota_set_bootinfo_to_zoneAB(&info); //sync bootinfo A with B
372 if (ret) {
373 TRACE("error %s %d, return:%d", __func__, __LINE__, ret);
374 return -1;
375 } else {
376 ota_current_link = info.update_link;
377 }
378 TRACE("%s %d, ota_current_link:%d, zone:%d", __func__, __LINE__, ota_current_link, zone);
379 }
380
381 return ret;
382 }
383
ota_clear_reboot_count(void)384 int ota_clear_reboot_count(void)
385 {
386 int32_t ret = 0;
387 struct ota_boot_info info;
388 enum bootinfo_zone zone;
389
390 zone = ota_get_valid_bootinfo_zone();
391 ret = ota_get_bootinfo(&info, zone);
392 if (ret) {
393 return OTA_FAILE;
394 }
395
396 if ((info.crash_reboot_count != 0) ||(info.secureERR_reboot_count != 0) ) {
397 info.crash_reboot_count = 0; //reset to 0
398 info.secureERR_reboot_count = 0; //reset to 0
399 info.reboot_reason = 0;
400 info.fallback_disable = 0; //enable fallback
401
402 ret = ota_set_bootinfo_to_zoneAB(&info); //sync bootinfo A with B
403 if (ret) {
404 TRACE("error %s %d, return:%d", __func__, __LINE__, ret);
405 return ret;
406 }
407 }
408
409 return ret;
410 }
411
ota_get_boot_type()412 int ota_get_boot_type()
413 {
414 int boot_type = 1;
415 return boot_type;
416 }
417
ota_set_user_bootinfo(void * param)418 int ota_set_user_bootinfo(void *param)
419 {
420 (void *)param;
421 return ota_upgrade_link();
422 }
423
ota_hal_rollback_platform_hook(void)424 int ota_hal_rollback_platform_hook(void)
425 {
426 return ota_clear_reboot_count();
427 }
428
ota_hal_platform_boot_type(void)429 int ota_hal_platform_boot_type(void)
430 {
431 return ota_get_boot_type();
432 }
433
ota_get_running_index(void)434 int ota_get_running_index(void)
435 {
436 int32_t ret = 0;
437 struct ota_boot_info info;
438 enum bootinfo_zone zone;
439
440 zone = ota_get_valid_bootinfo_zone();
441 ret = ota_get_bootinfo(&info, zone);
442 if (ret) {
443 printf("%s err \r\n", __FUNCTION__);
444 return -1;
445 }
446 return info.update_link;
447 }
448
ota_hal_final(void)449 int ota_hal_final(void)
450 {
451 return ota_set_user_bootinfo(NULL);
452 }
453