ota_breakpoint.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /*
  2. * Copyright (c) 2012-2014 Wind River Systems, Inc.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <kernel.h>
  7. #include <string.h>
  8. #include <drivers/nvram_config.h>
  9. #include <partition/partition.h>
  10. #include "ota_manifest.h"
  11. #include "ota_breakpoint.h"
  12. #include <os_common_api.h>
  13. #include <ota_storage.h>
  14. #ifdef CONFIG_WATCHDOG
  15. #include <watchdog_hal.h>
  16. #endif
  17. void ota_breakpoint_dump(struct ota_breakpoint *bp)
  18. {
  19. #if CONFIG_SYS_LOG_DEFAULT_LEVEL > 2
  20. struct ota_file *cur_file = &bp->cur_file;
  21. int i;
  22. SYS_LOG_INF("breakpoint: %p", bp);
  23. SYS_LOG_INF(" old_version 0x%x, new_version 0x%x, data_checksum 0x%x",
  24. bp->old_version, bp->new_version, bp->data_checksum);
  25. SYS_LOG_INF(" bp_id %d, state %d, backend_type %d",
  26. bp->bp_id, bp->state, bp->backend_type);
  27. for (i = 0; i < ARRAY_SIZE(bp->file_state); i++) {
  28. SYS_LOG_INF(" [%d] file_id %d state 0x%x", i,
  29. bp->file_state[i].file_id, bp->file_state[i].state);
  30. }
  31. SYS_LOG_INF(" cur file %s: file_id %d, offset 0x%x, size 0x%x(0x%x)",
  32. cur_file->name, cur_file->file_id, cur_file->offset, cur_file->size, cur_file->orig_size);
  33. SYS_LOG_INF(" write_offset 0x%x(0x%x)\n",
  34. bp->cur_file_write_offset, bp->cur_orig_write_offset);
  35. #endif
  36. }
  37. int ota_breakpoint_save(struct ota_breakpoint *bp)
  38. {
  39. int err;
  40. SYS_LOG_INF("save bp: state %d\n", bp->state);
  41. /* update seq id */
  42. bp->bp_id++;
  43. ota_breakpoint_dump(bp);
  44. err = nvram_config_set("OTA_BP", bp, sizeof(struct ota_breakpoint));
  45. if (err) {
  46. return -1;
  47. }
  48. return 0;
  49. }
  50. int ota_breakpoint_file_state(struct ota_breakpoint *bp)
  51. {
  52. int err;
  53. SYS_LOG_INF("save bp: state %d\n", bp->state);
  54. /* update seq id */
  55. bp->bp_id++;
  56. ota_breakpoint_dump(bp);
  57. err = nvram_config_set("OTA_BP", bp, sizeof(struct ota_breakpoint));
  58. if (err) {
  59. return -1;
  60. }
  61. return 0;
  62. }
  63. int ota_breakpoint_load(struct ota_breakpoint *bp)
  64. {
  65. int rlen;
  66. SYS_LOG_INF("save bp: state %d\n", bp->state);
  67. rlen = nvram_config_get("OTA_BP", bp, sizeof(struct ota_breakpoint));
  68. if (rlen < 0) {
  69. SYS_LOG_INF("cannot found OTA_BP");
  70. return -1;
  71. }
  72. ota_breakpoint_dump(bp);
  73. return 0;
  74. }
  75. int ota_breakpoint_get_current_state(struct ota_breakpoint *bp)
  76. {
  77. return bp->state;
  78. }
  79. int ota_breakpoint_set_file_state(struct ota_breakpoint *bp, int file_id, int state)
  80. {
  81. int i;
  82. for (i = 0; i < ARRAY_SIZE(bp->file_state); i++) {
  83. if (bp->file_state[i].file_id == file_id) {
  84. //SYS_LOG_INF("set file_id %d file state 0x%x\n", file_id, state);
  85. bp->file_state[i].state = state;
  86. return 0;
  87. }
  88. }
  89. /* not found, allocate new slot for this file */
  90. for (i = 0; i < ARRAY_SIZE(bp->file_state); i++) {
  91. if (bp->file_state[i].file_id == 0) {
  92. //SYS_LOG_INF("set file_id %d file state 0x%x\n", file_id, state);
  93. bp->file_state[i].file_id = file_id;
  94. bp->file_state[i].state = state;
  95. return 0;
  96. }
  97. }
  98. /* no slot? */
  99. SYS_LOG_INF("cannot found state slot for file_id %d\n", file_id);
  100. return -1;
  101. }
  102. int ota_breakpoint_get_file_state(struct ota_breakpoint *bp, int file_id)
  103. {
  104. int i;
  105. for (i = 0; i < ARRAY_SIZE(bp->file_state); i++) {
  106. if (bp->file_state[i].file_id == file_id) {
  107. return bp->file_state[i].state;
  108. }
  109. }
  110. /* no slot? */
  111. SYS_LOG_INF("cannot found state slot of file_id %d\n", file_id);
  112. return -1;
  113. }
  114. int ota_breakpoint_clear_all_file_state(struct ota_breakpoint *bp)
  115. {
  116. int i;
  117. SYS_LOG_INF("clear all file state");
  118. for (i = 0; i < ARRAY_SIZE(bp->file_state); i++) {
  119. bp->file_state[i].file_id = 0;
  120. bp->file_state[i].state = 0;
  121. }
  122. memset(&bp->cur_file, 0x0, sizeof(struct ota_file));
  123. bp->cur_file_write_offset = 0;
  124. bp->cur_orig_write_offset = 0;
  125. return 0;
  126. }
  127. int ota_breakpoint_update_state(struct ota_breakpoint *bp, int state)
  128. {
  129. SYS_LOG_INF("update breakpoint state %d", state);
  130. bp->state = state;
  131. if (state == OTA_BP_STATE_UPGRADE_DONE ||
  132. state == OTA_BP_STATE_UPGRADE_PENDING) {
  133. ota_breakpoint_clear_all_file_state(bp);
  134. }
  135. ota_breakpoint_save(bp);
  136. return 0;
  137. }
  138. extern struct ota_storage *ota_upgrade_storage_fine(struct ota_file *file);
  139. int ota_breakpoint_update_file_state(struct ota_breakpoint *bp, struct ota_file *file,
  140. int state, int cur_file_offset, int cur_orig_offset, int force)
  141. {
  142. int need_save;
  143. SYS_LOG_DBG("update bp file_id %d state %d offs 0x%x(0x%x)",
  144. file->file_id, state, cur_file_offset, cur_orig_offset);
  145. need_save = 0;
  146. /* aligned with erase sector */
  147. switch (state) {
  148. case OTA_BP_FILE_STATE_WRITE_START:
  149. memcpy(&bp->cur_file, file, sizeof(struct ota_file));
  150. bp->cur_file_write_offset = cur_file_offset;
  151. bp->cur_orig_write_offset = cur_orig_offset;
  152. break;
  153. case OTA_BP_FILE_STATE_WRITING:
  154. if (force || (cur_orig_offset - bp->cur_orig_write_offset) == 0 ||
  155. (cur_orig_offset - bp->cur_orig_write_offset) >= OTA_BP_SAVE_SIZE) {
  156. need_save = 1;
  157. bp->cur_file_write_offset = cur_file_offset;
  158. bp->cur_orig_write_offset = cur_orig_offset;
  159. }
  160. break;
  161. default:
  162. need_save = 1;
  163. break;
  164. }
  165. ota_breakpoint_set_file_state(bp, file->file_id, state);
  166. if (need_save){
  167. ota_storage_sync(ota_upgrade_storage_fine(file));
  168. ota_breakpoint_save(bp);
  169. #ifdef CONFIG_WATCHDOG
  170. watchdog_clear();
  171. #endif
  172. }
  173. return 0;
  174. }
  175. int ota_breakpoint_init_default_value(struct ota_breakpoint *bp)
  176. {
  177. memset(bp, 0x0, sizeof(struct ota_breakpoint));
  178. bp->old_version = fw_version_get_code();
  179. bp->mirror_id = !partition_get_current_mirror_id();
  180. bp->state = OTA_BP_STATE_UNKOWN;
  181. return 0;
  182. }
  183. int ota_breakpoint_init(struct ota_breakpoint *bp)
  184. {
  185. int err;
  186. SYS_LOG_INF("init bp %p\n", bp);
  187. err = ota_breakpoint_load(bp);
  188. if (err) {
  189. SYS_LOG_INF("no bp in nvram, use default bp");
  190. ota_breakpoint_init_default_value(bp);
  191. ota_breakpoint_save(bp);
  192. }
  193. return 0;
  194. }
  195. void ota_breakpoint_exit(struct ota_breakpoint *bp)
  196. {
  197. SYS_LOG_INF("deinit bp %p\n", bp);
  198. }