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