mklfs.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. /*
  2. * Copyright (C) 2015 - 2018, IBEROXARXA SERVICIOS INTEGRALES, S.L.
  3. * Copyright (C) 2015 - 2018, Jaume Olivé Petrus (jolive@whitecatboard.org)
  4. *
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are met:
  9. *
  10. * * Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * * Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * * Neither the name of the <organization> nor the
  16. * names of its contributors may be used to endorse or promote products
  17. * derived from this software without specific prior written permission.
  18. * * The WHITECAT logotype cannot be changed, you can remove it, but you
  19. * cannot change it in any way. The WHITECAT logotype is:
  20. *
  21. * /\ /\
  22. * / \_____/ \
  23. * /_____________\
  24. * W H I T E C A T
  25. *
  26. * * Redistributions in binary form must retain all copyright notices printed
  27. * to any local or remote output device. This include any reference to
  28. * Lua RTOS, whitecatboard.org, Lua, and other copyright notices that may
  29. * appear in the future.
  30. *
  31. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  32. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  33. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  34. * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
  35. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  36. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  37. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  38. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  39. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  40. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  41. *
  42. * Lua RTOS, a tool for make a LFS file system image
  43. *
  44. */
  45. #include "lfs/lfs.h"
  46. #include <ctype.h>
  47. #include <stdio.h>
  48. #include <stdlib.h>
  49. #include <string.h>
  50. #include <unistd.h>
  51. #include <errno.h>
  52. #include <limits.h>
  53. #include <dirent.h>
  54. #include <sys/types.h>
  55. #include <sys/stat.h>
  56. static struct lfs_config cfg;
  57. static lfs_t lfs;
  58. static uint8_t *data;
  59. static int lfs_read(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size) {
  60. memcpy(buffer, data + (block * c->block_size) + off, size);
  61. return 0;
  62. }
  63. static int lfs_prog(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size) {
  64. memcpy(data + (block * c->block_size) + off, buffer, size);
  65. return 0;
  66. }
  67. static int lfs_erase(const struct lfs_config *c, lfs_block_t block) {
  68. memset(data + (block * c->block_size), 0, c->block_size);
  69. return 0;
  70. }
  71. static int lfs_sync(const struct lfs_config *c) {
  72. return 0;
  73. }
  74. static void create_dir(char *src) {
  75. char *path;
  76. int ret;
  77. path = strchr(src, '/');
  78. if (path) {
  79. fprintf(stdout, "%s\r\n", path);
  80. if ((ret = lfs_mkdir(&lfs, path)) < 0) {
  81. fprintf(stderr,"can't create directory %s: error=%d\r\n", path, ret);
  82. exit(1);
  83. }
  84. }
  85. }
  86. static void create_file(char *src) {
  87. char *path;
  88. int ret;
  89. path = strchr(src, '/');
  90. if (path) {
  91. fprintf(stdout, "%s\r\n", path);
  92. // Open source file
  93. FILE *srcf = fopen(src,"rb");
  94. if (!srcf) {
  95. fprintf(stderr,"can't open source file %s: errno=%d (%s)\r\n", src, errno, strerror(errno));
  96. exit(1);
  97. }
  98. // Open destination file
  99. lfs_file_t dstf;
  100. if ((ret = lfs_file_open(&lfs, &dstf, path, LFS_O_WRONLY | LFS_O_CREAT)) < 0) {
  101. fprintf(stderr,"can't open destination file %s: error=%d\r\n", path, ret);
  102. exit(1);
  103. }
  104. char c = fgetc(srcf);
  105. while (!feof(srcf)) {
  106. ret = lfs_file_write(&lfs, &dstf, &c, 1);
  107. if (ret < 0) {
  108. fprintf(stderr,"can't write to destination file %s: error=%d\r\n", path, ret);
  109. exit(1);
  110. }
  111. c = fgetc(srcf);
  112. }
  113. // Close destination file
  114. ret = lfs_file_close(&lfs, &dstf);
  115. if (ret < 0) {
  116. fprintf(stderr,"can't close destination file %s: error=%d\r\n", path, ret);
  117. exit(1);
  118. }
  119. // Close source file
  120. fclose(srcf);
  121. }
  122. }
  123. static void compact(char *src) {
  124. DIR *dir;
  125. struct dirent *ent;
  126. char curr_path[PATH_MAX];
  127. struct stat _stat;
  128. unsigned int cnt = 0;
  129. dir = opendir(src);
  130. if (dir) {
  131. while ((ent = readdir(dir))) {
  132. // Skip . and .. directories
  133. if ((strcmp(ent->d_name,".") != 0) && (strcmp(ent->d_name,"..") != 0)) {
  134. cnt++;
  135. // Update the current path
  136. strcpy(curr_path, src);
  137. strcat(curr_path, "/");
  138. strcat(curr_path, ent->d_name);
  139. stat(curr_path, &_stat);
  140. if (S_ISDIR(_stat.st_mode)) {
  141. create_dir(curr_path);
  142. compact(curr_path);
  143. } else if (S_ISREG(_stat.st_mode)) {
  144. create_file(curr_path);
  145. }
  146. }
  147. }
  148. closedir(dir);
  149. if(cnt == 0) exit(1);
  150. }else{
  151. exit(1);
  152. }
  153. }
  154. void usage() {
  155. fprintf(stdout, "usage: mklfs -c <pack-dir> -b <block-size> -r <read-size> -p <prog-size> -s <filesystem-size> -i <image-file-path>\r\n");
  156. }
  157. static int is_number(const char *s) {
  158. const char *c = s;
  159. while (*c) {
  160. if ((*c < '0') || (*c > '9')) {
  161. return 0;
  162. }
  163. c++;
  164. }
  165. return 1;
  166. }
  167. static int is_hex(const char *s) {
  168. const char *c = s;
  169. if (*c++ != '0') {
  170. return 0;
  171. }
  172. if (*c++ != 'x') {
  173. return 0;
  174. }
  175. while (*c) {
  176. if (((*c < '0') || (*c > '9')) && ((*c < 'A') || (*c > 'F')) && ((*c < 'a') || (*c > 'f'))) {
  177. return 0;
  178. }
  179. c++;
  180. }
  181. return 1;
  182. }
  183. static int to_int(const char *s) {
  184. if (is_number(s)) {
  185. return atoi(s);
  186. } else if (is_hex(s)) {
  187. return (int)strtol(s, NULL, 16);
  188. }
  189. return -1;
  190. }
  191. #define FLASH_FS_REGION_OFFSET 0x350000
  192. #define FLASH_FS_REGION_END 0x3A4000
  193. #define FLASH_FS_REGION_SIZE (FLASH_FS_REGION_END-FLASH_FS_REGION_OFFSET) // 336KB
  194. #define LFS_BLOCK_DEVICE_READ_SIZE (256)
  195. #define LFS_BLOCK_DEVICE_PROG_SIZE (256)
  196. #define LFS_BLOCK_DEVICE_ERASE_SIZE (4096) // one sector 4KB
  197. #define LFS_BLOCK_DEVICE_TOTOAL_SIZE (FLASH_FS_REGION_SIZE)
  198. #define LFS_BLOCK_DEVICE_LOOK_AHEAD (16)
  199. #define LFS_BLOCK_DEVICE_CACHE_SIZE (256)
  200. int main(int argc, char **argv) {
  201. char *src = "disk"; // Source directory
  202. char *dst = "disk.fs"; // Destination image
  203. int err = 0;
  204. int fs_size = LFS_BLOCK_DEVICE_TOTOAL_SIZE;
  205. if (argc > 1 && !strcmp("-size", argv[1])) {
  206. fs_size = atoi(argv[2]) * 1024;
  207. }
  208. for (size_t i = 0; i < argc; i++)
  209. {
  210. //printf("argv[%d] %s\n", i, argv[i]);
  211. }
  212. // Mount the file system
  213. cfg.read = lfs_read;
  214. cfg.prog = lfs_prog;
  215. cfg.erase = lfs_erase;
  216. cfg.sync = lfs_sync;
  217. cfg.read_size = LFS_BLOCK_DEVICE_READ_SIZE;
  218. cfg.prog_size = LFS_BLOCK_DEVICE_PROG_SIZE;
  219. cfg.block_size = LFS_BLOCK_DEVICE_ERASE_SIZE;
  220. cfg.block_count = fs_size / LFS_BLOCK_DEVICE_ERASE_SIZE;
  221. cfg.block_cycles = 200;
  222. cfg.cache_size = LFS_BLOCK_DEVICE_CACHE_SIZE;
  223. cfg.lookahead_size = LFS_BLOCK_DEVICE_LOOK_AHEAD;
  224. // cfg.read_buffer = lfs_read_buf,
  225. // cfg.prog_buffer = lfs_prog_buf,
  226. // cfg.lookahead_buffer = lfs_lookahead_buf,
  227. cfg.name_max = 63;
  228. cfg.file_max = 0;
  229. cfg.attr_max = 0;
  230. data = calloc(1, fs_size);
  231. if (!data) {
  232. fprintf(stderr, "no memory for mount\r\n");
  233. return -1;
  234. }
  235. err = lfs_format(&lfs, &cfg);
  236. if (err < 0) {
  237. fprintf(stderr, "format error: error=%d\r\n", err);
  238. return -1;
  239. }
  240. err = lfs_mount(&lfs, &cfg);
  241. if (err < 0) {
  242. fprintf(stderr, "mount error: error=%d\r\n", err);
  243. return -1;
  244. }
  245. compact(src);
  246. FILE *img = fopen(dst, "wb");
  247. if (!img) {
  248. fprintf(stderr, "can't create image file: errno=%d (%s)\r\n", errno, strerror(errno));
  249. return -1;
  250. }
  251. fwrite(data, 1, fs_size, img);
  252. fclose(img);
  253. return 0;
  254. }