cmd_arc.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
  2. /*
  3. * Command for accessing Arcturus factory environment.
  4. *
  5. * Copyright 2013-2019 Arcturus Networks Inc.
  6. * https://www.arcturusnetworks.com/products/
  7. * by Oleksandr G Zhadan et al.
  8. *
  9. */
  10. #include <common.h>
  11. #include <div64.h>
  12. #include <env.h>
  13. #include <malloc.h>
  14. #include <spi_flash.h>
  15. #include <mmc.h>
  16. #include <version.h>
  17. #include <asm/io.h>
  18. static ulong fwenv_addr[MAX_FWENV_ADDR];
  19. const char mystrerr[] = "ERROR: Failed to save factory info";
  20. static int ishwaddr(char *hwaddr)
  21. {
  22. if (strlen(hwaddr) == MAX_HWADDR_SIZE)
  23. if (hwaddr[2] == ':' &&
  24. hwaddr[5] == ':' &&
  25. hwaddr[8] == ':' &&
  26. hwaddr[11] == ':' &&
  27. hwaddr[14] == ':')
  28. return 0;
  29. return -1;
  30. }
  31. #if (FWENV_TYPE == FWENV_MMC)
  32. static char smac[29][18] __attribute__ ((aligned(0x200))); /* 1 MMC block is 512 bytes */
  33. int set_mmc_arc_product(int argc, char *const argv[])
  34. {
  35. struct mmc *mmc;
  36. u32 blk, cnt, n;
  37. int i, err = 1;
  38. void *addr;
  39. const u8 mmc_dev_num = CONFIG_SYS_MMC_ENV_DEV;
  40. mmc = find_mmc_device(mmc_dev_num);
  41. if (!mmc) {
  42. printf("No SD/MMC/eMMC card found\n");
  43. return 0;
  44. }
  45. if (mmc_init(mmc)) {
  46. printf("%s(%d) init failed\n", IS_SD(mmc) ? "SD" : "MMC",
  47. mmc_dev_num);
  48. return 0;
  49. }
  50. if (mmc_getwp(mmc) == 1) {
  51. printf("Error: card is write protected!\n");
  52. return CMD_RET_FAILURE;
  53. }
  54. /* Save factory defaults */
  55. addr = (void *)smac;
  56. cnt = 1; /* One 512 bytes block */
  57. for (i = 0; i < MAX_FWENV_ADDR; i++)
  58. if (fwenv_addr[i] != -1) {
  59. blk = fwenv_addr[i] / 512;
  60. n = blk_dwrite(mmc_get_blk_desc(mmc), blk, cnt, addr);
  61. if (n != cnt)
  62. printf("%s: %s [%d]\n", __func__, mystrerr, i);
  63. else
  64. err = 0;
  65. }
  66. if (err)
  67. return -2;
  68. return err;
  69. }
  70. static int read_mmc_arc_info(void)
  71. {
  72. struct mmc *mmc;
  73. u32 blk, cnt, n;
  74. int i;
  75. void *addr;
  76. const u8 mmc_dev_num = CONFIG_SYS_MMC_ENV_DEV;
  77. mmc = find_mmc_device(mmc_dev_num);
  78. if (!mmc) {
  79. printf("No SD/MMC/eMMC card found\n");
  80. return 0;
  81. }
  82. if (mmc_init(mmc)) {
  83. printf("%s(%d) init failed\n", IS_SD(mmc) ? "SD" : "MMC",
  84. mmc_dev_num);
  85. return 0;
  86. }
  87. addr = (void *)smac;
  88. cnt = 1; /* One 512 bytes block */
  89. for (i = 0; i < MAX_FWENV_ADDR; i++)
  90. if (fwenv_addr[i] != -1) {
  91. blk = fwenv_addr[i] / 512;
  92. n = blk_dread(mmc_get_blk_desc(mmc), blk, cnt, addr);
  93. flush_cache((ulong) addr, 512);
  94. if (n == cnt)
  95. return (i + 1);
  96. }
  97. return 0;
  98. }
  99. #endif
  100. #if (FWENV_TYPE == FWENV_SPI_FLASH)
  101. static struct spi_flash *flash;
  102. static char smac[4][18];
  103. int set_spi_arc_product(int argc, char *const argv[])
  104. {
  105. int i, err = 1;
  106. flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
  107. CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
  108. if (!flash) {
  109. printf("Failed to initialize SPI flash at %u:%u\n",
  110. CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS);
  111. return -1;
  112. }
  113. /* Save factory defaults */
  114. for (i = 0; i < MAX_FWENV_ADDR; i++)
  115. if (fwenv_addr[i] != -1)
  116. if (spi_flash_write
  117. (flash, fwenv_addr[i], sizeof(smac), smac))
  118. printf("%s: %s [%d]\n", __func__, mystrerr, i);
  119. else
  120. err = 0;
  121. if (err)
  122. return -2;
  123. return err;
  124. }
  125. static int read_spi_arc_info(void)
  126. {
  127. int i;
  128. flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
  129. CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
  130. if (!flash) {
  131. printf("Failed to initialize SPI flash at %u:%u\n",
  132. CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS);
  133. return 0;
  134. }
  135. for (i = 0; i < MAX_FWENV_ADDR; i++)
  136. if (fwenv_addr[i] != -1)
  137. if (!spi_flash_read
  138. (flash, fwenv_addr[i], sizeof(smac), smac))
  139. return (i + 1);
  140. return 0;
  141. }
  142. #endif
  143. #if (FWENV_TYPE == FWENV_NOR_FLASH)
  144. static char smac[4][18];
  145. int set_nor_arc_product(int argc, char *const argv[])
  146. {
  147. int i, err = 1;
  148. /* Save factory defaults */
  149. for (i = 0; i < MAX_FWENV_ADDR; i++)
  150. if (fwenv_addr[i] != -1) {
  151. ulong fwenv_end = fwenv_addr[i] + 4;
  152. flash_sect_roundb(&fwenv_end);
  153. flash_sect_protect(0, fwenv_addr[i], fwenv_end);
  154. if (flash_write
  155. ((char *)smac, fwenv_addr[i], sizeof(smac)))
  156. printf("%s: %s [%d]\n", __func__, mystrerr, i);
  157. else
  158. err = 0;
  159. flash_sect_protect(1, fwenv_addr[i], fwenv_end);
  160. }
  161. if (err)
  162. return -2;
  163. return err;
  164. }
  165. static int read_nor_arc_info(void)
  166. {
  167. int i;
  168. for (i = 0; i < MAX_FWENV_ADDR; i++)
  169. if (fwenv_addr[i] != -1) {
  170. memcpy(smac, (void *)fwenv_addr[i], sizeof(smac));
  171. return (i + 1);
  172. }
  173. return 0;
  174. }
  175. #endif
  176. int set_arc_product(int argc, char *const argv[])
  177. {
  178. if (argc != 5)
  179. return -1;
  180. /* Check serial number */
  181. if (strlen(argv[1]) != MAX_SERIAL_SIZE)
  182. return -1;
  183. /* Check HWaddrs */
  184. if (ishwaddr(argv[2]) || ishwaddr(argv[3]) || ishwaddr(argv[4]))
  185. return -1;
  186. strcpy(smac[0], argv[1]);
  187. strcpy(smac[1], argv[2]);
  188. strcpy(smac[2], argv[3]);
  189. strcpy(smac[3], argv[4]);
  190. #if (FWENV_TYPE == FWENV_NOR_FLASH)
  191. return set_nor_arc_product(argc, argv);
  192. #endif
  193. #if (FWENV_TYPE == FWENV_SPI_FLASH)
  194. return set_spi_arc_product(argc, argv);
  195. #endif
  196. #if (FWENV_TYPE == FWENV_MMC)
  197. return set_mmc_arc_product(argc, argv);
  198. #endif
  199. return -2;
  200. }
  201. static int read_arc_info(void)
  202. {
  203. #if (FWENV_TYPE == FWENV_NOR_FLASH)
  204. return read_nor_arc_info();
  205. #endif
  206. #if (FWENV_TYPE == FWENV_SPI_FLASH)
  207. return read_spi_arc_info();
  208. #endif
  209. #if (FWENV_TYPE == FWENV_MMC)
  210. return read_mmc_arc_info();
  211. #endif
  212. return 0;
  213. }
  214. static int do_get_arc_info(void)
  215. {
  216. int l = read_arc_info();
  217. char *oldserial = env_get("SERIAL");
  218. char *oldversion = env_get("VERSION");
  219. if (oldversion != NULL)
  220. if (strcmp(oldversion, U_BOOT_VERSION) != 0)
  221. oldversion = NULL;
  222. if (l == 0) {
  223. printf("%s: failed to read factory info\n", __func__);
  224. return -2;
  225. }
  226. printf("\rSERIAL: ");
  227. if (smac[0][0] == EMPY_CHAR) {
  228. printf("<not found>\n");
  229. } else {
  230. printf("%s\n", smac[0]);
  231. env_set("SERIAL", smac[0]);
  232. }
  233. if (strcmp(smac[1], "00:00:00:00:00:00") == 0) {
  234. env_set("ethaddr", NULL);
  235. env_set("eth1addr", NULL);
  236. env_set("eth2addr", NULL);
  237. goto done;
  238. }
  239. printf("HWADDR0: ");
  240. if (smac[1][0] == EMPY_CHAR) {
  241. printf("<not found>\n");
  242. } else {
  243. char *ret = env_get("ethaddr");
  244. if (ret == NULL) {
  245. env_set("ethaddr", smac[1]);
  246. printf("%s\n", smac[1]);
  247. } else if (strcmp(ret, __stringify(CONFIG_ETHADDR)) == 0) {
  248. env_set("ethaddr", smac[1]);
  249. printf("%s (factory)\n", smac[1]);
  250. } else {
  251. printf("%s\n", ret);
  252. }
  253. }
  254. if (strcmp(smac[2], "00:00:00:00:00:00") == 0) {
  255. env_set("eth1addr", NULL);
  256. env_set("eth2addr", NULL);
  257. goto done;
  258. }
  259. printf("HWADDR1: ");
  260. if (smac[2][0] == EMPY_CHAR) {
  261. printf("<not found>\n");
  262. } else {
  263. char *ret = env_get("eth1addr");
  264. if (ret == NULL) {
  265. env_set("ethaddr", smac[2]);
  266. printf("%s\n", smac[2]);
  267. } else if (strcmp(ret, __stringify(CONFIG_ETH1ADDR)) == 0) {
  268. env_set("eth1addr", smac[2]);
  269. printf("%s (factory)\n", smac[2]);
  270. } else {
  271. printf("%s\n", ret);
  272. }
  273. }
  274. if (strcmp(smac[3], "00:00:00:00:00:00") == 0) {
  275. env_set("eth2addr", NULL);
  276. goto done;
  277. }
  278. printf("HWADDR2: ");
  279. if (smac[3][0] == EMPY_CHAR) {
  280. printf("<not found>\n");
  281. } else {
  282. char *ret = env_get("eth2addr");
  283. if (ret == NULL) {
  284. env_set("ethaddr", smac[3]);
  285. printf("%s\n", smac[3]);
  286. } else if (strcmp(ret, __stringify(CONFIG_ETH2ADDR)) == 0) {
  287. env_set("eth2addr", smac[3]);
  288. printf("%s (factory)\n", smac[3]);
  289. } else {
  290. printf("%s\n", ret);
  291. }
  292. }
  293. done:
  294. if (oldserial == NULL || oldversion == NULL) {
  295. if (oldversion == NULL)
  296. env_set("VERSION", U_BOOT_VERSION);
  297. env_save();
  298. }
  299. return 0;
  300. }
  301. static int init_fwenv(void)
  302. {
  303. int i, ret = -1;
  304. fwenv_addr[0] = FWENV_ADDR1;
  305. fwenv_addr[1] = FWENV_ADDR2;
  306. fwenv_addr[2] = FWENV_ADDR3;
  307. fwenv_addr[3] = FWENV_ADDR4;
  308. for (i = 0; i < MAX_FWENV_ADDR; i++)
  309. if (fwenv_addr[i] != -1)
  310. ret = 0;
  311. if (ret)
  312. printf("%s: No firmfare info storage address is defined\n",
  313. __func__);
  314. return ret;
  315. }
  316. void get_arc_info(void)
  317. {
  318. if (!init_fwenv())
  319. do_get_arc_info();
  320. }
  321. static int do_arc_cmd(cmd_tbl_t * cmdtp, int flag, int argc, char *const argv[])
  322. {
  323. const char *cmd;
  324. int ret = -1;
  325. cmd = argv[1];
  326. --argc;
  327. ++argv;
  328. if (init_fwenv())
  329. return ret;
  330. if (strcmp(cmd, "product") == 0)
  331. ret = set_arc_product(argc, argv);
  332. else if (strcmp(cmd, "info") == 0)
  333. ret = do_get_arc_info();
  334. if (ret == -1)
  335. return CMD_RET_USAGE;
  336. return ret;
  337. }
  338. U_BOOT_CMD(arc, 6, 1, do_arc_cmd,
  339. "Arcturus product command sub-system",
  340. "product serial hwaddr0 hwaddr1 hwaddr2 - save Arcturus factory env\n"
  341. "info - show Arcturus factory env\n\n");