internal-storage.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. #include "internal-storage-i.h"
  2. int internal_storage_device_read(
  3. const struct lfs_config* c,
  4. lfs_block_t block,
  5. lfs_off_t off,
  6. void* buffer,
  7. lfs_size_t size) {
  8. InternalStorage* internal_storage = c->context;
  9. size_t address = internal_storage->start_address + block * c->block_size + off;
  10. FURI_LOG_D(
  11. "internal-storage",
  12. "Device read: block %d, off %d, buffer: %p, size %d, translated address: %p",
  13. block,
  14. off,
  15. buffer,
  16. size,
  17. address);
  18. memcpy(buffer, (void*)address, size);
  19. return 0;
  20. }
  21. int internal_storage_device_prog(
  22. const struct lfs_config* c,
  23. lfs_block_t block,
  24. lfs_off_t off,
  25. const void* buffer,
  26. lfs_size_t size) {
  27. InternalStorage* internal_storage = c->context;
  28. size_t address = internal_storage->start_address + block * c->block_size + off;
  29. FURI_LOG_D(
  30. "internal-storage",
  31. "Device prog: block %d, off %d, buffer: %p, size %d, translated address: %p",
  32. block,
  33. off,
  34. buffer,
  35. size,
  36. address);
  37. int ret = 0;
  38. while(size > 0) {
  39. if(!api_hal_flash_write_dword(address, *(uint64_t*)buffer)) {
  40. ret = -1;
  41. break;
  42. }
  43. address += c->prog_size;
  44. buffer += c->prog_size;
  45. size -= c->prog_size;
  46. }
  47. return ret;
  48. }
  49. int internal_storage_device_erase(const struct lfs_config* c, lfs_block_t block) {
  50. InternalStorage* internal_storage = c->context;
  51. size_t page = internal_storage->start_page + block;
  52. FURI_LOG_D("internal-storage", "Device erase: page %d, translated page: %d", block, page);
  53. if(api_hal_flash_erase(page, 1)) {
  54. return 0;
  55. } else {
  56. return -1;
  57. }
  58. }
  59. int internal_storage_device_sync(const struct lfs_config* c) {
  60. FURI_LOG_D("internal-storage", "Device sync: skipping, cause ");
  61. return 0;
  62. }
  63. InternalStorage* internal_storage_alloc() {
  64. InternalStorage* internal_storage = furi_alloc(sizeof(InternalStorage));
  65. internal_storage->queue = osMessageQueueNew(8, sizeof(InternalStorageCommand), NULL);
  66. // Internal storage start address
  67. internal_storage->state = InternalStorageStateInitializing;
  68. // Internal storage start address
  69. *(size_t*)(&internal_storage->start_address) = api_hal_flash_get_free_page_start_address();
  70. *(size_t*)(&internal_storage->start_page) =
  71. (internal_storage->start_address - api_hal_flash_get_base()) /
  72. api_hal_flash_get_page_size();
  73. // LFS configuration
  74. // Glue and context
  75. internal_storage->config.context = internal_storage;
  76. internal_storage->config.read = internal_storage_device_read;
  77. internal_storage->config.prog = internal_storage_device_prog;
  78. internal_storage->config.erase = internal_storage_device_erase;
  79. internal_storage->config.sync = internal_storage_device_sync;
  80. // Block device description
  81. internal_storage->config.read_size = api_hal_flash_get_read_block_size();
  82. internal_storage->config.prog_size = api_hal_flash_get_write_block_size();
  83. internal_storage->config.block_size = api_hal_flash_get_page_size();
  84. internal_storage->config.block_count = api_hal_flash_get_free_page_count();
  85. internal_storage->config.block_cycles = api_hal_flash_get_cycles_count();
  86. internal_storage->config.cache_size = 16;
  87. internal_storage->config.lookahead_size = 16;
  88. return internal_storage;
  89. }
  90. void internal_storage_free(InternalStorage* internal_storage) {
  91. furi_assert(internal_storage);
  92. free(internal_storage);
  93. }
  94. int32_t internal_storage_task(void* p) {
  95. FURI_LOG_I("internal-storage", "Starting");
  96. InternalStorage* internal_storage = internal_storage_alloc();
  97. FURI_LOG_I(
  98. "internal-storage",
  99. "Config: start %p, read %d, write %d, page size: %d, page count: %d, cycles: %d",
  100. internal_storage->start_address,
  101. internal_storage->config.read_size,
  102. internal_storage->config.prog_size,
  103. internal_storage->config.block_size,
  104. internal_storage->config.block_count,
  105. internal_storage->config.block_cycles);
  106. int err;
  107. ApiHalBootFlag boot_flags = api_hal_boot_get_flags();
  108. if(boot_flags & ApiHalBootFlagFactoryReset) {
  109. // Factory reset
  110. err = lfs_format(&internal_storage->lfs, &internal_storage->config);
  111. if(err == 0) {
  112. FURI_LOG_I("internal-storage", "Factory reset: Format successful, trying to mount");
  113. api_hal_boot_set_flags(boot_flags & ~ApiHalBootFlagFactoryReset);
  114. err = lfs_mount(&internal_storage->lfs, &internal_storage->config);
  115. if(err == 0) {
  116. FURI_LOG_I("internal-storage", "Factory reset: Mounted");
  117. internal_storage->state = InternalStorageStateReady;
  118. } else {
  119. FURI_LOG_E("internal-storage", "Factory reset: Mount after format failed");
  120. internal_storage->state = InternalStorageStateBroken;
  121. }
  122. } else {
  123. FURI_LOG_E("internal-storage", "Factory reset: Format failed");
  124. internal_storage->state = InternalStorageStateBroken;
  125. }
  126. } else {
  127. // Normal
  128. err = lfs_mount(&internal_storage->lfs, &internal_storage->config);
  129. if(err == 0) {
  130. FURI_LOG_I("internal-storage", "Mounted");
  131. internal_storage->state = InternalStorageStateReady;
  132. } else {
  133. FURI_LOG_E("internal-storage", "Mount failed, formatting");
  134. err = lfs_format(&internal_storage->lfs, &internal_storage->config);
  135. if(err == 0) {
  136. FURI_LOG_I("internal-storage", "Format successful, trying to mount");
  137. err = lfs_mount(&internal_storage->lfs, &internal_storage->config);
  138. if(err == 0) {
  139. FURI_LOG_I("internal-storage", "Mounted");
  140. internal_storage->state = InternalStorageStateReady;
  141. } else {
  142. FURI_LOG_E("internal-storage", "Mount after format failed");
  143. internal_storage->state = InternalStorageStateBroken;
  144. }
  145. } else {
  146. FURI_LOG_E("internal-storage", "Format failed");
  147. internal_storage->state = InternalStorageStateBroken;
  148. }
  149. }
  150. }
  151. furi_record_create("internal-storage", internal_storage);
  152. InternalStorageCommand command;
  153. while(1) {
  154. furi_check(
  155. osMessageQueueGet(internal_storage->queue, &command, NULL, osWaitForever) == osOK);
  156. command.function(internal_storage, command.data);
  157. osThreadFlagsSet(command.thread, INTERNAL_STORAGE_THREAD_FLAG_CALL_COMPLETE);
  158. }
  159. lfs_unmount(&internal_storage->lfs);
  160. internal_storage_free(internal_storage);
  161. return 0;
  162. }
  163. void _internal_storage_read_key(InternalStorage* internal_storage, InternalStorageCommandKey* data) {
  164. lfs_file_t file;
  165. int ret = lfs_file_open(&internal_storage->lfs, &file, data->key, LFS_O_RDONLY);
  166. if(ret == 0) {
  167. ret = lfs_file_read(&internal_storage->lfs, &file, data->buffer, data->size);
  168. lfs_file_close(&internal_storage->lfs, &file);
  169. }
  170. data->ret = ret;
  171. }
  172. int internal_storage_read_key(
  173. InternalStorage* internal_storage,
  174. const char* key,
  175. uint8_t* buffer,
  176. size_t size) {
  177. osThreadId_t caller_thread = osThreadGetId();
  178. if(caller_thread == 0) {
  179. return -1;
  180. }
  181. InternalStorageCommandKey data = {.key = key, .buffer = buffer, .size = size, .ret = 0};
  182. InternalStorageCommand command = {
  183. .thread = caller_thread,
  184. .function = (InternalStorageCommandFunction)_internal_storage_read_key,
  185. .data = &data,
  186. };
  187. furi_check(osMessageQueuePut(internal_storage->queue, &command, 0, osWaitForever) == osOK);
  188. osThreadFlagsWait(INTERNAL_STORAGE_THREAD_FLAG_CALL_COMPLETE, osFlagsWaitAny, osWaitForever);
  189. return data.ret;
  190. }
  191. void _internal_storage_write_key(
  192. InternalStorage* internal_storage,
  193. InternalStorageCommandKey* data) {
  194. lfs_file_t file;
  195. int ret = lfs_file_open(
  196. &internal_storage->lfs, &file, data->key, LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC);
  197. if(ret == 0) {
  198. ret = lfs_file_write(&internal_storage->lfs, &file, data->buffer, data->size);
  199. lfs_file_close(&internal_storage->lfs, &file);
  200. }
  201. data->ret = ret;
  202. }
  203. int internal_storage_write_key(
  204. InternalStorage* internal_storage,
  205. const char* key,
  206. uint8_t* buffer,
  207. size_t size) {
  208. osThreadId_t caller_thread = osThreadGetId();
  209. if(caller_thread == 0) {
  210. return -1;
  211. }
  212. InternalStorageCommandKey data = {.key = key, .buffer = buffer, .size = size, .ret = 0};
  213. InternalStorageCommand command = {
  214. .thread = caller_thread,
  215. .function = (InternalStorageCommandFunction)_internal_storage_write_key,
  216. .data = &data,
  217. };
  218. furi_check(osMessageQueuePut(internal_storage->queue, &command, 0, osWaitForever) == osOK);
  219. osThreadFlagsWait(INTERNAL_STORAGE_THREAD_FLAG_CALL_COMPLETE, osFlagsWaitAny, osWaitForever);
  220. return data.ret;
  221. }