mklfs.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  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. dir = opendir(src);
  129. if (dir) {
  130. while ((ent = readdir(dir))) {
  131. // Skip . and .. directories
  132. if ((strcmp(ent->d_name,".") != 0) && (strcmp(ent->d_name,"..") != 0)) {
  133. // Update the current path
  134. strcpy(curr_path, src);
  135. strcat(curr_path, "/");
  136. strcat(curr_path, ent->d_name);
  137. stat(curr_path, &_stat);
  138. if (S_ISDIR(_stat.st_mode)) {
  139. create_dir(curr_path);
  140. compact(curr_path);
  141. } else if (S_ISREG(_stat.st_mode)) {
  142. create_file(curr_path);
  143. }
  144. }
  145. }
  146. closedir(dir);
  147. }
  148. }
  149. void usage() {
  150. 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");
  151. }
  152. static int is_number(const char *s) {
  153. const char *c = s;
  154. while (*c) {
  155. if ((*c < '0') || (*c > '9')) {
  156. return 0;
  157. }
  158. c++;
  159. }
  160. return 1;
  161. }
  162. static int is_hex(const char *s) {
  163. const char *c = s;
  164. if (*c++ != '0') {
  165. return 0;
  166. }
  167. if (*c++ != 'x') {
  168. return 0;
  169. }
  170. while (*c) {
  171. if (((*c < '0') || (*c > '9')) && ((*c < 'A') || (*c > 'F')) && ((*c < 'a') || (*c > 'f'))) {
  172. return 0;
  173. }
  174. c++;
  175. }
  176. return 1;
  177. }
  178. static int to_int(const char *s) {
  179. if (is_number(s)) {
  180. return atoi(s);
  181. } else if (is_hex(s)) {
  182. return (int)strtol(s, NULL, 16);
  183. }
  184. return -1;
  185. }
  186. #define FLASH_FS_REGION_OFFSET 0x1E0000
  187. #define FLASH_FS_REGION_END 0x1FC000
  188. #define FLASH_FS_REGION_SIZE (FLASH_FS_REGION_END-FLASH_FS_REGION_OFFSET) // 112KB
  189. #define LFS_BLOCK_DEVICE_READ_SIZE (256)
  190. #define LFS_BLOCK_DEVICE_PROG_SIZE (256)
  191. #define LFS_BLOCK_DEVICE_ERASE_SIZE (4096) // one sector 4KB
  192. #define LFS_BLOCK_DEVICE_TOTOAL_SIZE (FLASH_FS_REGION_SIZE)
  193. #define LFS_BLOCK_DEVICE_LOOK_AHEAD (16)
  194. #define LFS_BLOCK_DEVICE_CACHE_SIZE (256)
  195. int main(int argc, char **argv) {
  196. char *src = "disk"; // Source directory
  197. char *dst = "script.bin"; // Destination image
  198. int err = 0;
  199. int fs_size = LFS_BLOCK_DEVICE_TOTOAL_SIZE;
  200. // Mount the file system
  201. cfg.read = lfs_read;
  202. cfg.prog = lfs_prog;
  203. cfg.erase = lfs_erase;
  204. cfg.sync = lfs_sync;
  205. cfg.read_size = LFS_BLOCK_DEVICE_READ_SIZE;
  206. cfg.prog_size = LFS_BLOCK_DEVICE_PROG_SIZE;
  207. cfg.block_size = LFS_BLOCK_DEVICE_ERASE_SIZE;
  208. cfg.block_count = LFS_BLOCK_DEVICE_TOTOAL_SIZE / LFS_BLOCK_DEVICE_ERASE_SIZE;
  209. cfg.block_cycles = 200;
  210. cfg.cache_size = LFS_BLOCK_DEVICE_CACHE_SIZE;
  211. cfg.lookahead_size = LFS_BLOCK_DEVICE_LOOK_AHEAD;
  212. // cfg.read_buffer = lfs_read_buf,
  213. // cfg.prog_buffer = lfs_prog_buf,
  214. // cfg.lookahead_buffer = lfs_lookahead_buf,
  215. cfg.name_max = 63;
  216. cfg.file_max = 0;
  217. cfg.attr_max = 0;
  218. data = calloc(1, fs_size);
  219. if (!data) {
  220. fprintf(stderr, "no memory for mount\r\n");
  221. return -1;
  222. }
  223. err = lfs_format(&lfs, &cfg);
  224. if (err < 0) {
  225. fprintf(stderr, "format error: error=%d\r\n", err);
  226. return -1;
  227. }
  228. err = lfs_mount(&lfs, &cfg);
  229. if (err < 0) {
  230. fprintf(stderr, "mount error: error=%d\r\n", err);
  231. return -1;
  232. }
  233. compact(src);
  234. FILE *img = fopen(dst, "wb");
  235. if (!img) {
  236. fprintf(stderr, "can't create image file: errno=%d (%s)\r\n", errno, strerror(errno));
  237. return -1;
  238. }
  239. fwrite(data, 1, fs_size, img);
  240. fclose(img);
  241. return 0;
  242. }