env: Move env_set() to env.h
[oweals/u-boot.git] / board / Arcturus / ucp1020 / cmd_arc.c
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 <div64.h>
13 #include <env.h>
14 #include <malloc.h>
15 #include <spi_flash.h>
16 #include <mmc.h>
17 #include <version.h>
18 #include <environment.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
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
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
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
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
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
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
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
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
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
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
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
372 void get_arc_info(void)
373 {
374         if (!init_fwenv())
375                 do_get_arc_info();
376 }
377
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");