internal-storage.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  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 = lfs_mount(&internal_storage->lfs, &internal_storage->config);
  107. if(err == 0) {
  108. FURI_LOG_I("internal-storage", "Mounted");
  109. internal_storage->state = InternalStorageStateReady;
  110. } else {
  111. FURI_LOG_E("internal-storage", "Mount failed, formatting");
  112. err = lfs_format(&internal_storage->lfs, &internal_storage->config);
  113. if(err == 0) {
  114. FURI_LOG_I("internal-storage", "Format successful, trying to mount");
  115. err = lfs_mount(&internal_storage->lfs, &internal_storage->config);
  116. if(err == 0) {
  117. FURI_LOG_I("internal-storage", "Mounted");
  118. internal_storage->state = InternalStorageStateReady;
  119. } else {
  120. FURI_LOG_E("internal-storage", "Mount after format failed");
  121. internal_storage->state = InternalStorageStateBroken;
  122. }
  123. } else {
  124. FURI_LOG_E("internal-storage", "Format failed");
  125. internal_storage->state = InternalStorageStateBroken;
  126. }
  127. }
  128. furi_record_create("internal-storage", internal_storage);
  129. InternalStorageCommand command;
  130. while(1) {
  131. furi_check(
  132. osMessageQueueGet(internal_storage->queue, &command, NULL, osWaitForever) == osOK);
  133. command.function(internal_storage, command.data);
  134. osThreadFlagsSet(command.thread, INTERNAL_STORAGE_THREAD_FLAG_CALL_COMPLETE);
  135. }
  136. lfs_unmount(&internal_storage->lfs);
  137. internal_storage_free(internal_storage);
  138. return 0;
  139. }
  140. void _internal_storage_read_key(InternalStorage* internal_storage, InternalStorageCommandKey* data) {
  141. lfs_file_t file;
  142. int ret = lfs_file_open(&internal_storage->lfs, &file, data->key, LFS_O_RDONLY);
  143. if(ret == 0) {
  144. ret = lfs_file_read(&internal_storage->lfs, &file, data->buffer, data->size);
  145. lfs_file_close(&internal_storage->lfs, &file);
  146. }
  147. data->ret = ret;
  148. }
  149. int internal_storage_read_key(
  150. InternalStorage* internal_storage,
  151. const char* key,
  152. uint8_t* buffer,
  153. size_t size) {
  154. osThreadId_t caller_thread = osThreadGetId();
  155. if(caller_thread == 0) {
  156. return -1;
  157. }
  158. InternalStorageCommandKey data = {.key = key, .buffer = buffer, .size = size, .ret = 0};
  159. InternalStorageCommand command = {
  160. .thread = caller_thread,
  161. .function = (InternalStorageCommandFunction)_internal_storage_read_key,
  162. .data = &data,
  163. };
  164. furi_check(osMessageQueuePut(internal_storage->queue, &command, 0, osWaitForever) == osOK);
  165. osThreadFlagsWait(INTERNAL_STORAGE_THREAD_FLAG_CALL_COMPLETE, osFlagsWaitAny, osWaitForever);
  166. return data.ret;
  167. }
  168. void _internal_storage_write_key(
  169. InternalStorage* internal_storage,
  170. InternalStorageCommandKey* data) {
  171. lfs_file_t file;
  172. int ret = lfs_file_open(
  173. &internal_storage->lfs, &file, data->key, LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC);
  174. if(ret == 0) {
  175. ret = lfs_file_write(&internal_storage->lfs, &file, data->buffer, data->size);
  176. lfs_file_close(&internal_storage->lfs, &file);
  177. }
  178. data->ret = ret;
  179. }
  180. int internal_storage_write_key(
  181. InternalStorage* internal_storage,
  182. const char* key,
  183. uint8_t* buffer,
  184. size_t size) {
  185. osThreadId_t caller_thread = osThreadGetId();
  186. if(caller_thread == 0) {
  187. return -1;
  188. }
  189. InternalStorageCommandKey data = {.key = key, .buffer = buffer, .size = size, .ret = 0};
  190. InternalStorageCommand command = {
  191. .thread = caller_thread,
  192. .function = (InternalStorageCommandFunction)_internal_storage_write_key,
  193. .data = &data,
  194. };
  195. furi_check(osMessageQueuePut(internal_storage->queue, &command, 0, osWaitForever) == osOK);
  196. osThreadFlagsWait(INTERNAL_STORAGE_THREAD_FLAG_CALL_COMPLETE, osFlagsWaitAny, osWaitForever);
  197. return data.ret;
  198. }