PageRenderTime 56ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/user/mtd-utils/36d8de81049c9c908740b690c664b5bd3703ccd6/mtd_debug.c

https://bitbucket.org/thelearninglabs/uclinux-distro-tll-public
C | 394 lines | 319 code | 34 blank | 41 comment | 86 complexity | e74683ed62271c74670461cf36cf1599 MD5 | raw file
Possible License(s): LGPL-2.1, BSD-3-Clause, MPL-2.0-no-copyleft-exception, LGPL-3.0, Unlicense, GPL-2.0, GPL-3.0, CC-BY-SA-3.0, AGPL-1.0, ISC, MIT, 0BSD, LGPL-2.0
  1. /*
  2. * Copyright (c) 2d3D, Inc.
  3. * Written by Abraham vd Merwe <abraham@2d3d.co.za>
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. Neither the name of the author nor the names of other contributors
  15. * may be used to endorse or promote products derived from this software
  16. * without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  19. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  20. * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  21. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  22. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  23. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  24. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  25. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  26. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  27. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. */
  29. #define PROGRAM_NAME "mtd_debug"
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <errno.h>
  33. #include <string.h>
  34. #include <unistd.h>
  35. #include <sys/ioctl.h>
  36. #include <sys/types.h>
  37. #include <sys/stat.h>
  38. #include <fcntl.h>
  39. #include <mtd/mtd-user.h>
  40. #include "common.h"
  41. /*
  42. * MEMGETINFO
  43. */
  44. static int getmeminfo(int fd, struct mtd_info_user *mtd)
  45. {
  46. return ioctl(fd, MEMGETINFO, mtd);
  47. }
  48. /*
  49. * MEMERASE
  50. */
  51. static int memerase(int fd, struct erase_info_user *erase)
  52. {
  53. return ioctl(fd, MEMERASE, erase);
  54. }
  55. /*
  56. * MEMGETREGIONCOUNT
  57. * MEMGETREGIONINFO
  58. */
  59. static int getregions(int fd, struct region_info_user *regions, int *n)
  60. {
  61. int i, err;
  62. err = ioctl(fd, MEMGETREGIONCOUNT, n);
  63. if (err)
  64. return err;
  65. for (i = 0; i < *n; i++) {
  66. regions[i].regionindex = i;
  67. err = ioctl(fd, MEMGETREGIONINFO, &regions[i]);
  68. if (err)
  69. return err;
  70. }
  71. return 0;
  72. }
  73. int erase_flash(int fd, u_int32_t offset, u_int32_t bytes)
  74. {
  75. int err;
  76. struct erase_info_user erase;
  77. erase.start = offset;
  78. erase.length = bytes;
  79. err = memerase(fd, &erase);
  80. if (err < 0) {
  81. perror("MEMERASE");
  82. return 1;
  83. }
  84. fprintf(stderr, "Erased %d bytes from address 0x%.8x in flash\n", bytes, offset);
  85. return 0;
  86. }
  87. void printsize(u_int32_t x)
  88. {
  89. int i;
  90. static const char *flags = "KMGT";
  91. printf("%u ", x);
  92. for (i = 0; x >= 1024 && flags[i] != '\0'; i++)
  93. x /= 1024;
  94. i--;
  95. if (i >= 0)
  96. printf("(%u%c)", x, flags[i]);
  97. }
  98. int flash_to_file(int fd, u_int32_t offset, size_t len, const char *filename)
  99. {
  100. u_int8_t *buf = NULL;
  101. int outfd, err;
  102. int size = len * sizeof(u_int8_t);
  103. int n = len;
  104. if (offset != lseek(fd, offset, SEEK_SET)) {
  105. perror("lseek()");
  106. goto err0;
  107. }
  108. outfd = creat(filename, 0666);
  109. if (outfd < 0) {
  110. perror("creat()");
  111. goto err1;
  112. }
  113. retry:
  114. if ((buf = (u_int8_t *) malloc(size)) == NULL) {
  115. #define BUF_SIZE (64 * 1024 * sizeof(u_int8_t))
  116. fprintf(stderr, "%s: malloc(%#x)\n", __func__, size);
  117. if (size != BUF_SIZE) {
  118. size = BUF_SIZE;
  119. fprintf(stderr, "%s: trying buffer size %#x\n", __func__, size);
  120. goto retry;
  121. }
  122. perror("malloc()");
  123. goto err0;
  124. }
  125. do {
  126. if (n <= size)
  127. size = n;
  128. err = read(fd, buf, size);
  129. if (err < 0) {
  130. fprintf(stderr, "%s: read, size %#x, n %#x\n", __func__, size, n);
  131. perror("read()");
  132. goto err2;
  133. }
  134. err = write(outfd, buf, size);
  135. if (err < 0) {
  136. fprintf(stderr, "%s: write, size %#x, n %#x\n", __func__, size, n);
  137. perror("write()");
  138. goto err2;
  139. }
  140. if (err != size) {
  141. fprintf(stderr, "Couldn't copy entire buffer to %s. (%d/%d bytes copied)\n", filename, err, size);
  142. goto err2;
  143. }
  144. n -= size;
  145. } while (n > 0);
  146. if (buf != NULL)
  147. free(buf);
  148. close(outfd);
  149. printf("Copied %zu bytes from address 0x%.8x in flash to %s\n", len, offset, filename);
  150. return 0;
  151. err2:
  152. close(outfd);
  153. err1:
  154. if (buf != NULL)
  155. free(buf);
  156. err0:
  157. return 1;
  158. }
  159. int file_to_flash(int fd, u_int32_t offset, u_int32_t len, const char *filename)
  160. {
  161. u_int8_t *buf = NULL;
  162. FILE *fp;
  163. int err;
  164. int size = len * sizeof(u_int8_t);
  165. int n = len;
  166. if (offset != lseek(fd, offset, SEEK_SET)) {
  167. perror("lseek()");
  168. return 1;
  169. }
  170. if ((fp = fopen(filename, "r")) == NULL) {
  171. perror("fopen()");
  172. return 1;
  173. }
  174. retry:
  175. if ((buf = (u_int8_t *) malloc(size)) == NULL) {
  176. fprintf(stderr, "%s: malloc(%#x) failed\n", __func__, size);
  177. if (size != BUF_SIZE) {
  178. size = BUF_SIZE;
  179. fprintf(stderr, "%s: trying buffer size %#x\n", __func__, size);
  180. goto retry;
  181. }
  182. perror("malloc()");
  183. fclose(fp);
  184. return 1;
  185. }
  186. do {
  187. if (n <= size)
  188. size = n;
  189. if (fread(buf, size, 1, fp) != 1 || ferror(fp)) {
  190. fprintf(stderr, "%s: fread, size %#x, n %#x\n", __func__, size, n);
  191. perror("fread()");
  192. free(buf);
  193. fclose(fp);
  194. return 1;
  195. }
  196. err = write(fd, buf, size);
  197. if (err < 0) {
  198. fprintf(stderr, "%s: write, size %#x, n %#x\n", __func__, size, n);
  199. perror("write()");
  200. free(buf);
  201. fclose(fp);
  202. return 1;
  203. }
  204. n -= size;
  205. } while (n > 0);
  206. if (buf != NULL)
  207. free(buf);
  208. fclose(fp);
  209. printf("Copied %d bytes from %s to address 0x%.8x in flash\n", len, filename, offset);
  210. return 0;
  211. }
  212. int showinfo(int fd)
  213. {
  214. int i, err, n;
  215. struct mtd_info_user mtd;
  216. static struct region_info_user region[1024];
  217. err = getmeminfo(fd, &mtd);
  218. if (err < 0) {
  219. perror("MEMGETINFO");
  220. return 1;
  221. }
  222. err = getregions(fd, region, &n);
  223. if (err < 0) {
  224. perror("MEMGETREGIONCOUNT");
  225. return 1;
  226. }
  227. printf("mtd.type = ");
  228. switch (mtd.type) {
  229. case MTD_ABSENT:
  230. printf("MTD_ABSENT");
  231. break;
  232. case MTD_RAM:
  233. printf("MTD_RAM");
  234. break;
  235. case MTD_ROM:
  236. printf("MTD_ROM");
  237. break;
  238. case MTD_NORFLASH:
  239. printf("MTD_NORFLASH");
  240. break;
  241. case MTD_NANDFLASH:
  242. printf("MTD_NANDFLASH");
  243. break;
  244. case MTD_DATAFLASH:
  245. printf("MTD_DATAFLASH");
  246. break;
  247. case MTD_UBIVOLUME:
  248. printf("MTD_UBIVOLUME");
  249. default:
  250. printf("(unknown type - new MTD API maybe?)");
  251. }
  252. printf("\nmtd.flags = ");
  253. if (mtd.flags == MTD_CAP_ROM)
  254. printf("MTD_CAP_ROM");
  255. else if (mtd.flags == MTD_CAP_RAM)
  256. printf("MTD_CAP_RAM");
  257. else if (mtd.flags == MTD_CAP_NORFLASH)
  258. printf("MTD_CAP_NORFLASH");
  259. else if (mtd.flags == MTD_CAP_NANDFLASH)
  260. printf("MTD_CAP_NANDFLASH");
  261. else if (mtd.flags == MTD_WRITEABLE)
  262. printf("MTD_WRITEABLE");
  263. else {
  264. int first = 1;
  265. static struct {
  266. const char *name;
  267. int value;
  268. } flags[] =
  269. {
  270. { "MTD_WRITEABLE", MTD_WRITEABLE },
  271. { "MTD_BIT_WRITEABLE", MTD_BIT_WRITEABLE },
  272. { "MTD_NO_ERASE", MTD_NO_ERASE },
  273. { "MTD_POWERUP_LOCK", MTD_POWERUP_LOCK },
  274. { NULL, -1 }
  275. };
  276. for (i = 0; flags[i].name != NULL; i++) {
  277. if (mtd.flags & flags[i].value) {
  278. if (first) {
  279. printf("%s", flags[i].name);
  280. first = 0;
  281. } else {
  282. printf(" | %s", flags[i].name);
  283. }
  284. }
  285. }
  286. }
  287. printf("\nmtd.size = ");
  288. printsize(mtd.size);
  289. printf("\nmtd.erasesize = ");
  290. printsize(mtd.erasesize);
  291. printf("\nmtd.writesize = ");
  292. printsize(mtd.writesize);
  293. printf("\nmtd.oobsize = ");
  294. printsize(mtd.oobsize);
  295. printf("\nregions = %d\n\n", n);
  296. for (i = 0; i < n; i++) {
  297. printf("region[%d].offset = 0x%.8x\n"
  298. "region[%d].erasesize = ",
  299. i, region[i].offset, i);
  300. printsize(region[i].erasesize);
  301. printf("\nregion[%d].numblocks = %d\n"
  302. "region[%d].regionindex = %d\n",
  303. i, region[i].numblocks,
  304. i, region[i].regionindex);
  305. }
  306. return 0;
  307. }
  308. void showusage(void)
  309. {
  310. fprintf(stderr, "usage: %1$s info <device>\n"
  311. " %1$s read <device> <offset> <len> <dest-filename>\n"
  312. " %1$s write <device> <offset> <len> <source-filename>\n"
  313. " %1$s erase <device> <offset> <len>\n",
  314. PROGRAM_NAME);
  315. exit(EXIT_FAILURE);
  316. }
  317. int main(int argc, char *argv[])
  318. {
  319. int err = 0, fd;
  320. int open_flag;
  321. enum {
  322. OPT_INFO,
  323. OPT_READ,
  324. OPT_WRITE,
  325. OPT_ERASE
  326. } option = OPT_INFO;
  327. /* parse command-line options */
  328. if (argc == 3 && !strcmp(argv[1], "info"))
  329. option = OPT_INFO;
  330. else if (argc == 6 && !strcmp(argv[1], "read"))
  331. option = OPT_READ;
  332. else if (argc == 6 && !strcmp(argv[1], "write"))
  333. option = OPT_WRITE;
  334. else if (argc == 5 && !strcmp(argv[1], "erase"))
  335. option = OPT_ERASE;
  336. else
  337. showusage();
  338. /* open device */
  339. open_flag = (option == OPT_INFO || option == OPT_READ) ? O_RDONLY : O_RDWR;
  340. if ((fd = open(argv[2], O_SYNC | open_flag)) < 0)
  341. errmsg_die("open()");
  342. switch (option) {
  343. case OPT_INFO:
  344. showinfo(fd);
  345. break;
  346. case OPT_READ:
  347. err = flash_to_file(fd, strtol(argv[3], NULL, 0), strtol(argv[4], NULL, 0), argv[5]);
  348. break;
  349. case OPT_WRITE:
  350. err = file_to_flash(fd, strtol(argv[3], NULL, 0), strtol(argv[4], NULL, 0), argv[5]);
  351. break;
  352. case OPT_ERASE:
  353. err = erase_flash(fd, strtol(argv[3], NULL, 0), strtol(argv[4], NULL, 0));
  354. break;
  355. }
  356. /* close device */
  357. if (close(fd) < 0)
  358. errmsg_die("close()");
  359. return err;
  360. }