1 /*
2  * Command for accessing Arcturus factory environment.
3  *
4  * Copyright 2013-2015 Arcturus Networks Inc.
5  *           http://www.arcturusnetworks.com/products/ucp1020/
6  *           by Oleksandr G Zhadan et al.
7  *
8  * SPDX-License-Identifier: GPL-2.0+ BSD-3-Clause
9  *
10  */
11 
12 #include <common.h>
13 #include <div64.h>
14 #include <malloc.h>
15 #include <spi_flash.h>
16 
17 #include <asm/io.h>
18 
19 #ifndef CONFIG_SF_DEFAULT_SPEED
20 #   define CONFIG_SF_DEFAULT_SPEED	1000000
21 #endif
22 #ifndef CONFIG_SF_DEFAULT_MODE
23 #   define CONFIG_SF_DEFAULT_MODE	SPI_MODE0
24 #endif
25 #ifndef CONFIG_SF_DEFAULT_CS
26 #   define CONFIG_SF_DEFAULT_CS		0
27 #endif
28 #ifndef CONFIG_SF_DEFAULT_BUS
29 #   define CONFIG_SF_DEFAULT_BUS	0
30 #endif
31 
32 #define MAX_SERIAL_SIZE 15
33 #define MAX_HWADDR_SIZE 17
34 
35 #define FIRM_ADDR1 (0x200 - sizeof(smac))
36 #define FIRM_ADDR2 (0x400 - sizeof(smac))
37 #define FIRM_ADDR3 (CONFIG_ENV_SECT_SIZE + 0x200 - sizeof(smac))
38 #define FIRM_ADDR4 (CONFIG_ENV_SECT_SIZE + 0x400 - sizeof(smac))
39 
40 static struct spi_flash *flash;
41 char smac[4][18];
42 
43 static int ishwaddr(char *hwaddr)
44 {
45 	if (strlen(hwaddr) == MAX_HWADDR_SIZE)
46 		if (hwaddr[2] == ':' &&
47 		    hwaddr[5] == ':' &&
48 		    hwaddr[8] == ':' &&
49 		    hwaddr[11] == ':' &&
50 		    hwaddr[14] == ':')
51 			return 0;
52 	return -1;
53 }
54 
55 static int set_arc_product(int argc, char *const argv[])
56 {
57 	int err = 0;
58 	char *mystrerr = "ERROR: Failed to save factory info in spi location";
59 
60 	if (argc != 5)
61 		return -1;
62 
63 	/* Check serial number */
64 	if (strlen(argv[1]) != MAX_SERIAL_SIZE)
65 		return -1;
66 
67 	/* Check HWaddrs */
68 	if (ishwaddr(argv[2]) || ishwaddr(argv[3]) || ishwaddr(argv[4]))
69 		return -1;
70 
71 	strcpy(smac[3], argv[1]);
72 	strcpy(smac[2], argv[2]);
73 	strcpy(smac[1], argv[3]);
74 	strcpy(smac[0], argv[4]);
75 
76 	flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
77 				CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
78 
79 	/*
80 	 * Save factory defaults
81 	 */
82 
83 	if (spi_flash_write(flash, FIRM_ADDR1, sizeof(smac), smac)) {
84 		printf("%s: %s [1]\n", __func__, mystrerr);
85 		err++;
86 	}
87 	if (spi_flash_write(flash, FIRM_ADDR2, sizeof(smac), smac)) {
88 		printf("%s: %s [2]\n", __func__, mystrerr);
89 		err++;
90 	}
91 
92 	if (spi_flash_write(flash, FIRM_ADDR3, sizeof(smac), smac)) {
93 		printf("%s: %s [3]\n", __func__, mystrerr);
94 		err++;
95 	}
96 
97 	if (spi_flash_write(flash, FIRM_ADDR4, sizeof(smac), smac)) {
98 		printf("%s: %s [4]\n", __func__, mystrerr);
99 		err++;
100 	}
101 
102 	if (err == 4) {
103 		printf("%s: %s [ALL]\n", __func__, mystrerr);
104 		return -2;
105 	}
106 
107 	return 0;
108 }
109 
110 int get_arc_info(void)
111 {
112 	int location = 1;
113 	char *myerr = "ERROR: Failed to read all 4 factory info spi locations";
114 
115 	flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
116 				CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
117 
118 	if (spi_flash_read(flash, FIRM_ADDR1, sizeof(smac), smac)) {
119 		location++;
120 		if (spi_flash_read(flash, FIRM_ADDR2, sizeof(smac), smac)) {
121 			location++;
122 			if (spi_flash_read(flash, FIRM_ADDR3, sizeof(smac),
123 					   smac)) {
124 				location++;
125 				if (spi_flash_read(flash, FIRM_ADDR4,
126 						   sizeof(smac), smac)) {
127 					printf("%s: %s\n", __func__, myerr);
128 					return -2;
129 				}
130 			}
131 		}
132 	}
133 	if (smac[3][0] != 0) {
134 		if (location > 1)
135 			printf("Using region %d\n", location);
136 		printf("SERIAL: ");
137 		if (smac[3][0] == 0xFF) {
138 			printf("\t<not found>\n");
139 		} else {
140 			printf("\t%s\n", smac[3]);
141 			setenv("SERIAL", smac[3]);
142 		}
143 	}
144 
145 	if (strcmp(smac[2], "00:00:00:00:00:00") == 0)
146 		return 0;
147 
148 	printf("HWADDR0:");
149 	if (smac[2][0] == 0xFF) {
150 		printf("\t<not found>\n");
151 	} else {
152 		char *ret = getenv("ethaddr");
153 
154 		if (strcmp(ret, __stringify(CONFIG_ETHADDR)) == 0) {
155 			setenv("ethaddr", smac[2]);
156 			printf("\t%s (factory)\n", smac[2]);
157 		} else {
158 			printf("\t%s\n", ret);
159 		}
160 	}
161 
162 	if (strcmp(smac[1], "00:00:00:00:00:00") == 0) {
163 		setenv("eth1addr", smac[2]);
164 		setenv("eth2addr", smac[2]);
165 		return 0;
166 	}
167 
168 	printf("HWADDR1:");
169 	if (smac[1][0] == 0xFF) {
170 		printf("\t<not found>\n");
171 	} else {
172 		char *ret = getenv("eth1addr");
173 
174 		if (strcmp(ret, __stringify(CONFIG_ETH1ADDR)) == 0) {
175 			setenv("eth1addr", smac[1]);
176 			printf("\t%s (factory)\n", smac[1]);
177 		} else {
178 			printf("\t%s\n", ret);
179 		}
180 	}
181 
182 	if (strcmp(smac[0], "00:00:00:00:00:00") == 0) {
183 		setenv("eth2addr", smac[1]);
184 		return 0;
185 	}
186 
187 	printf("HWADDR2:");
188 	if (smac[0][0] == 0xFF) {
189 		printf("\t<not found>\n");
190 	} else {
191 		char *ret = getenv("eth2addr");
192 
193 		if (strcmp(ret, __stringify(CONFIG_ETH2ADDR)) == 0) {
194 			setenv("eth2addr", smac[0]);
195 			printf("\t%s (factory)\n", smac[0]);
196 		} else {
197 			printf("\t%s\n", ret);
198 		}
199 	}
200 
201 	return 0;
202 }
203 
204 static int do_arc_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
205 {
206 	const char *cmd;
207 	int ret = -1;
208 
209 	cmd = argv[1];
210 	--argc;
211 	++argv;
212 
213 	if (strcmp(cmd, "product") == 0) {
214 		ret = set_arc_product(argc, argv);
215 		goto done;
216 	}
217 	if (strcmp(cmd, "info") == 0) {
218 		ret = get_arc_info();
219 		goto done;
220 	}
221 done:
222 	if (ret == -1)
223 		return CMD_RET_USAGE;
224 
225 	return ret;
226 }
227 
228 U_BOOT_CMD(arc, 6, 1, do_arc_cmd,
229 	   "Arcturus product command sub-system",
230 	   "product serial hwaddr0 hwaddr1 hwaddr2    - save Arcturus factory env\n"
231 	   "info                                      - show Arcturus factory env\n\n");
232