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