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