• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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