cmd_flash.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. /*
  2. * (C) Copyright 2000
  3. * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  4. *
  5. * SPDX-License-Identifier: GPL-2.0+
  6. */
  7. /*
  8. * FLASH support
  9. */
  10. #include <common.h>
  11. #include <command.h>
  12. #include <flash.h>
  13. #if defined(CONFIG_CMD_FLASH)
  14. extern flash_info_t flash_info[]; /* info for FLASH chips */
  15. /*
  16. * The user interface starts numbering for Flash banks with 1
  17. * for historical reasons.
  18. */
  19. /*
  20. * this routine looks for an abbreviated flash range specification.
  21. * the syntax is B:SF[-SL], where B is the bank number, SF is the first
  22. * sector to erase, and SL is the last sector to erase (defaults to SF).
  23. * bank numbers start at 1 to be consistent with other specs, sector numbers
  24. * start at zero.
  25. *
  26. * returns: 1 - correct spec; *pinfo, *psf and *psl are
  27. * set appropriately
  28. * 0 - doesn't look like an abbreviated spec
  29. * -1 - looks like an abbreviated spec, but got
  30. * a parsing error, a number out of range,
  31. * or an invalid flash bank.
  32. */
  33. static int
  34. abbrev_spec(char *str, flash_info_t **pinfo, int *psf, int *psl)
  35. {
  36. flash_info_t *fp;
  37. int bank, first, last;
  38. char *p, *ep;
  39. if ((p = strchr(str, ':')) == NULL)
  40. return 0;
  41. *p++ = '\0';
  42. bank = simple_strtoul(str, &ep, 10);
  43. if (ep == str || *ep != '\0' ||
  44. bank < 1 || bank > CONFIG_SYS_MAX_FLASH_BANKS ||
  45. (fp = &flash_info[bank - 1])->flash_id == FLASH_UNKNOWN)
  46. return -1;
  47. str = p;
  48. if ((p = strchr(str, '-')) != NULL)
  49. *p++ = '\0';
  50. first = simple_strtoul(str, &ep, 10);
  51. if (ep == str || *ep != '\0' || first >= fp->sector_count)
  52. return -1;
  53. if (p != NULL) {
  54. last = simple_strtoul(p, &ep, 10);
  55. if (ep == p || *ep != '\0' ||
  56. last < first || last >= fp->sector_count)
  57. return -1;
  58. }
  59. else
  60. last = first;
  61. *pinfo = fp;
  62. *psf = first;
  63. *psl = last;
  64. return 1;
  65. }
  66. int do_flinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
  67. {
  68. ulong bank;
  69. if (argc == 1) { /* print info for all FLASH banks */
  70. for (bank=0; bank <CONFIG_SYS_MAX_FLASH_BANKS; ++bank) {
  71. printf ("\nBank # %ld: ", bank+1);
  72. flash_print_info (&flash_info[bank]);
  73. }
  74. return 0;
  75. }
  76. bank = simple_strtoul(argv[1], NULL, 16);
  77. if ((bank < 1) || (bank > CONFIG_SYS_MAX_FLASH_BANKS)) {
  78. printf ("Only FLASH Banks # 1 ... # %d supported\n",
  79. CONFIG_SYS_MAX_FLASH_BANKS);
  80. return 1;
  81. }
  82. printf ("\nBank # %ld: ", bank);
  83. flash_print_info (&flash_info[bank-1]);
  84. return 0;
  85. }
  86. int do_flerase(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
  87. {
  88. flash_info_t *info;
  89. ulong bank, addr_first, addr_last;
  90. int n, sect_first, sect_last;
  91. int rcode = 0;
  92. if (argc < 2)
  93. return cmd_usage(cmdtp);
  94. if (strcmp(argv[1], "all") == 0) {
  95. for (bank=1; bank<=CONFIG_SYS_MAX_FLASH_BANKS; ++bank) {
  96. printf ("Erase Flash Bank # %ld ", bank);
  97. info = &flash_info[bank-1];
  98. rcode = flash_erase (info, 0, info->sector_count-1);
  99. }
  100. return rcode;
  101. }
  102. if ((n = abbrev_spec(argv[1], &info, &sect_first, &sect_last)) != 0) {
  103. if (n < 0) {
  104. printf("Bad sector specification\n");
  105. return 1;
  106. }
  107. printf ("Erase Flash Sectors %d-%d in Bank # %d ",
  108. sect_first, sect_last, (info-flash_info)+1);
  109. rcode = flash_erase(info, sect_first, sect_last);
  110. return rcode;
  111. }
  112. if (argc != 3)
  113. return cmd_usage(cmdtp);
  114. if (strcmp(argv[1], "bank") == 0) {
  115. bank = simple_strtoul(argv[2], NULL, 16);
  116. if ((bank < 1) || (bank > CONFIG_SYS_MAX_FLASH_BANKS)) {
  117. printf ("Only FLASH Banks # 1 ... # %d supported\n",
  118. CONFIG_SYS_MAX_FLASH_BANKS);
  119. return 1;
  120. }
  121. printf ("Erase Flash Bank # %ld ", bank);
  122. info = &flash_info[bank-1];
  123. rcode = flash_erase (info, 0, info->sector_count-1);
  124. return rcode;
  125. }
  126. addr_first = simple_strtoul(argv[1], NULL, 16);
  127. addr_last = simple_strtoul(argv[2], NULL, 16);
  128. if (addr_first >= addr_last)
  129. return cmd_usage(cmdtp);
  130. printf ("Erase Flash from 0x%08lx to 0x%08lx ", addr_first, addr_last);
  131. rcode = flash_sect_erase(addr_first, addr_last);
  132. return rcode;
  133. }
  134. int flash_sect_erase (ulong addr_first, ulong addr_last)
  135. {
  136. flash_info_t *info;
  137. ulong bank;
  138. int s_first, s_last;
  139. int erased;
  140. int rcode = 0;
  141. erased = 0;
  142. for (bank=0,info = &flash_info[0]; bank < CONFIG_SYS_MAX_FLASH_BANKS; ++bank, ++info) {
  143. ulong b_end;
  144. int sect;
  145. if (info->flash_id == FLASH_UNKNOWN) {
  146. continue;
  147. }
  148. b_end = info->start[0] + info->size - 1; /* bank end addr */
  149. s_first = -1; /* first sector to erase */
  150. s_last = -1; /* last sector to erase */
  151. for (sect=0; sect < info->sector_count; ++sect) {
  152. ulong end; /* last address in current sect */
  153. short s_end;
  154. s_end = info->sector_count - 1;
  155. end = (sect == s_end) ? b_end : info->start[sect + 1] - 1;
  156. if (addr_first > end)
  157. continue;
  158. if (addr_last < info->start[sect])
  159. continue;
  160. if (addr_first == info->start[sect]) {
  161. s_first = sect;
  162. }
  163. if (addr_last == end) {
  164. s_last = sect;
  165. }
  166. }
  167. if (s_first>=0 && s_first<=s_last) {
  168. erased += s_last - s_first + 1;
  169. rcode = flash_erase (info, s_first, s_last);
  170. }
  171. }
  172. if (erased) {
  173. /* printf ("Erased %d sectors\n", erased); */
  174. } else {
  175. printf ("Error: start and/or end address"
  176. " not on sector boundary\n");
  177. rcode = 1;
  178. }
  179. return rcode;
  180. }
  181. int do_protect(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
  182. {
  183. flash_info_t *info;
  184. ulong bank, addr_first, addr_last;
  185. int i, p, n, sect_first, sect_last;
  186. int rcode = 0;
  187. if (argc < 3)
  188. return cmd_usage(cmdtp);
  189. if (strcmp(argv[1], "off") == 0)
  190. p = 0;
  191. else if (strcmp(argv[1], "on") == 0)
  192. p = 1;
  193. else
  194. return cmd_usage(cmdtp);
  195. if (strcmp(argv[2], "all") == 0) {
  196. for (bank=1; bank<=CONFIG_SYS_MAX_FLASH_BANKS; ++bank) {
  197. info = &flash_info[bank-1];
  198. if (info->flash_id == FLASH_UNKNOWN) {
  199. continue;
  200. }
  201. /*printf ("%sProtect Flash Bank # %ld\n", */
  202. /* p ? "" : "Un-", bank); */
  203. for (i=0; i<info->sector_count; ++i) {
  204. #if defined(CONFIG_SYS_FLASH_PROTECTION)
  205. if (flash_real_protect(info, i, p))
  206. rcode = 1;
  207. putc ('.');
  208. #else
  209. info->protect[i] = p;
  210. #endif /* CONFIG_SYS_FLASH_PROTECTION */
  211. }
  212. }
  213. #if defined(CONFIG_SYS_FLASH_PROTECTION)
  214. if (!rcode) puts (" done\n");
  215. #endif /* CONFIG_SYS_FLASH_PROTECTION */
  216. return rcode;
  217. }
  218. if ((n = abbrev_spec(argv[2], &info, &sect_first, &sect_last)) != 0) {
  219. if (n < 0) {
  220. printf("Bad sector specification\n");
  221. return 1;
  222. }
  223. /*printf("%sProtect Flash Sectors %d-%d in Bank # %d\n", */
  224. /* p ? "" : "Un-", sect_first, sect_last, */
  225. /* (info-flash_info)+1); */
  226. for (i = sect_first; i <= sect_last; i++) {
  227. #if defined(CONFIG_SYS_FLASH_PROTECTION)
  228. if (flash_real_protect(info, i, p))
  229. rcode = 1;
  230. putc ('.');
  231. #else
  232. info->protect[i] = p;
  233. #endif /* CONFIG_SYS_FLASH_PROTECTION */
  234. }
  235. #if defined(CONFIG_SYS_FLASH_PROTECTION)
  236. if (!rcode) puts (" done\n");
  237. #endif /* CONFIG_SYS_FLASH_PROTECTION */
  238. return rcode;
  239. }
  240. if (argc != 4)
  241. return cmd_usage(cmdtp);
  242. if (strcmp(argv[2], "bank") == 0) {
  243. bank = simple_strtoul(argv[3], NULL, 16);
  244. if ((bank < 1) || (bank > CONFIG_SYS_MAX_FLASH_BANKS)) {
  245. printf ("Only FLASH Banks # 1 ... # %d supported\n",
  246. CONFIG_SYS_MAX_FLASH_BANKS);
  247. return 1;
  248. }
  249. printf ("%sProtect Flash Bank # %ld\n",
  250. p ? "" : "Un-", bank);
  251. info = &flash_info[bank-1];
  252. if (info->flash_id == FLASH_UNKNOWN) {
  253. printf ("missing or unknown FLASH type\n");
  254. return 1;
  255. }
  256. for (i=0; i<info->sector_count; ++i) {
  257. #if defined(CONFIG_SYS_FLASH_PROTECTION)
  258. if (flash_real_protect(info, i, p))
  259. rcode = 1;
  260. putc ('.');
  261. #else
  262. info->protect[i] = p;
  263. #endif /* CONFIG_SYS_FLASH_PROTECTION */
  264. }
  265. #if defined(CONFIG_SYS_FLASH_PROTECTION)
  266. if (!rcode)
  267. puts(" done\n");
  268. #endif /* CONFIG_SYS_FLASH_PROTECTION */
  269. return rcode;
  270. }
  271. addr_first = simple_strtoul(argv[2], NULL, 16);
  272. addr_last = simple_strtoul(argv[3], NULL, 16);
  273. if (addr_first >= addr_last)
  274. return cmd_usage(cmdtp);
  275. return flash_sect_protect (p, addr_first, addr_last);
  276. }
  277. int flash_sect_protect (int p, ulong addr_first, ulong addr_last)
  278. {
  279. flash_info_t *info;
  280. ulong bank;
  281. int s_first, s_last;
  282. int protected, i;
  283. int rcode = 0;
  284. protected = 0;
  285. for (bank=0,info = &flash_info[0]; bank < CONFIG_SYS_MAX_FLASH_BANKS; ++bank, ++info) {
  286. ulong b_end;
  287. int sect;
  288. if (info->flash_id == FLASH_UNKNOWN) {
  289. continue;
  290. }
  291. b_end = info->start[0] + info->size - 1; /* bank end addr */
  292. s_first = -1; /* first sector to erase */
  293. s_last = -1; /* last sector to erase */
  294. for (sect=0; sect < info->sector_count; ++sect) {
  295. ulong end; /* last address in current sect */
  296. short s_end;
  297. s_end = info->sector_count - 1;
  298. end = (sect == s_end) ? b_end : info->start[sect + 1] - 1;
  299. if (addr_first > end)
  300. continue;
  301. if (addr_last < info->start[sect])
  302. continue;
  303. if (addr_first == info->start[sect]) {
  304. s_first = sect;
  305. }
  306. if (addr_last == end) {
  307. s_last = sect;
  308. }
  309. }
  310. if (s_first>=0 && s_first<=s_last) {
  311. protected += s_last - s_first + 1;
  312. for (i=s_first; i<=s_last; ++i) {
  313. #if defined(CONFIG_SYS_FLASH_PROTECTION)
  314. if (flash_real_protect(info, i, p))
  315. rcode = 1;
  316. putc ('.');
  317. #else
  318. info->protect[i] = p;
  319. #endif /* CONFIG_SYS_FLASH_PROTECTION */
  320. }
  321. }
  322. #if defined(CONFIG_SYS_FLASH_PROTECTION)
  323. if (!rcode) putc ('\n');
  324. #endif /* CONFIG_SYS_FLASH_PROTECTION */
  325. }
  326. if (protected) {
  327. /* printf ("%sProtected %d sectors\n", */
  328. /* p ? "" : "Un-", protected); */
  329. } else {
  330. printf ("Error: start and/or end address"
  331. " not on sector boundary\n");
  332. rcode = 1;
  333. }
  334. return rcode;
  335. }
  336. #endif