7a510c61fb015c5d9c08a149f247b4e1e6e2e0bd
[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 <malloc.h>
14 #include <spi_flash.h>
15 #include <mmc.h>
16 #include <version.h>
17 #include <environment.h>
18 #include <asm/io.h>
19
20 static ulong fwenv_addr[MAX_FWENV_ADDR];
21 const char mystrerr[] = "ERROR: Failed to save factory info";
22
23 static int ishwaddr(char *hwaddr)
24 {
25         if (strlen(hwaddr) == MAX_HWADDR_SIZE)
26                 if (hwaddr[2] == ':' &&
27                     hwaddr[5] == ':' &&
28                     hwaddr[8] == ':' &&
29                     hwaddr[11] == ':' &&
30                     hwaddr[14] == ':')
31                         return 0;
32         return -1;
33 }
34
35 #if (FWENV_TYPE == FWENV_MMC)
36
37 static char smac[29][18] __attribute__ ((aligned(0x200)));      /* 1 MMC block is 512 bytes */
38
39 int set_mmc_arc_product(int argc, char *const argv[])
40 {
41         struct mmc *mmc;
42         u32 blk, cnt, n;
43         int i, err = 1;
44         void *addr;
45         const u8 mmc_dev_num = CONFIG_SYS_MMC_ENV_DEV;
46
47         mmc = find_mmc_device(mmc_dev_num);
48         if (!mmc) {
49                 printf("No SD/MMC/eMMC card found\n");
50                 return 0;
51         }
52         if (mmc_init(mmc)) {
53                 printf("%s(%d) init failed\n", IS_SD(mmc) ? "SD" : "MMC",
54                        mmc_dev_num);
55                 return 0;
56         }
57         if (mmc_getwp(mmc) == 1) {
58                 printf("Error: card is write protected!\n");
59                 return CMD_RET_FAILURE;
60         }
61
62         /* Save factory defaults */
63         addr = (void *)smac;
64         cnt = 1;                /* One 512 bytes block */
65
66         for (i = 0; i < MAX_FWENV_ADDR; i++)
67                 if (fwenv_addr[i] != -1) {
68                         blk = fwenv_addr[i] / 512;
69                         n = blk_dwrite(mmc_get_blk_desc(mmc), blk, cnt, addr);
70                         if (n != cnt)
71                                 printf("%s: %s [%d]\n", __func__, mystrerr, i);
72                         else
73                                 err = 0;
74                 }
75         if (err)
76                 return -2;
77
78         return err;
79 }
80
81 static int read_mmc_arc_info(void)
82 {
83         struct mmc *mmc;
84         u32 blk, cnt, n;
85         int i;
86         void *addr;
87         const u8 mmc_dev_num = CONFIG_SYS_MMC_ENV_DEV;
88
89         mmc = find_mmc_device(mmc_dev_num);
90         if (!mmc) {
91                 printf("No SD/MMC/eMMC card found\n");
92                 return 0;
93         }
94         if (mmc_init(mmc)) {
95                 printf("%s(%d) init failed\n", IS_SD(mmc) ? "SD" : "MMC",
96                        mmc_dev_num);
97                 return 0;
98         }
99
100         addr = (void *)smac;
101         cnt = 1;                /* One 512 bytes block */
102
103         for (i = 0; i < MAX_FWENV_ADDR; i++)
104                 if (fwenv_addr[i] != -1) {
105                         blk = fwenv_addr[i] / 512;
106                         n = blk_dread(mmc_get_blk_desc(mmc), blk, cnt, addr);
107                         flush_cache((ulong) addr, 512);
108                         if (n == cnt)
109                                 return (i + 1);
110                 }
111         return 0;
112 }
113 #endif
114
115 #if (FWENV_TYPE == FWENV_SPI_FLASH)
116
117 static struct spi_flash *flash;
118 static char smac[4][18];
119
120 int set_spi_arc_product(int argc, char *const argv[])
121 {
122         int i, err = 1;
123
124         flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
125                                 CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
126         if (!flash) {
127                 printf("Failed to initialize SPI flash at %u:%u\n",
128                        CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS);
129                 return -1;
130         }
131
132         /* Save factory defaults */
133         for (i = 0; i < MAX_FWENV_ADDR; i++)
134                 if (fwenv_addr[i] != -1)
135                         if (spi_flash_write
136                             (flash, fwenv_addr[i], sizeof(smac), smac))
137                                 printf("%s: %s [%d]\n", __func__, mystrerr, i);
138                         else
139                                 err = 0;
140         if (err)
141                 return -2;
142
143         return err;
144 }
145
146 static int read_spi_arc_info(void)
147 {
148         int i;
149
150         flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
151                                 CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
152         if (!flash) {
153                 printf("Failed to initialize SPI flash at %u:%u\n",
154                        CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS);
155                 return 0;
156         }
157         for (i = 0; i < MAX_FWENV_ADDR; i++)
158                 if (fwenv_addr[i] != -1)
159                         if (!spi_flash_read
160                             (flash, fwenv_addr[i], sizeof(smac), smac))
161                                 return (i + 1);
162         return 0;
163 }
164 #endif
165
166 #if (FWENV_TYPE == FWENV_NOR_FLASH)
167
168 static char smac[4][18];
169
170 int set_nor_arc_product(int argc, char *const argv[])
171 {
172         int i, err = 1;
173
174         /* Save factory defaults */
175         for (i = 0; i < MAX_FWENV_ADDR; i++)
176                 if (fwenv_addr[i] != -1) {
177                         ulong fwenv_end = fwenv_addr[i] + 4;
178
179                         flash_sect_roundb(&fwenv_end);
180                         flash_sect_protect(0, fwenv_addr[i], fwenv_end);
181                         if (flash_write
182                             ((char *)smac, fwenv_addr[i], sizeof(smac)))
183                                 printf("%s: %s [%d]\n", __func__, mystrerr, i);
184                         else
185                                 err = 0;
186                         flash_sect_protect(1, fwenv_addr[i], fwenv_end);
187                 }
188         if (err)
189                 return -2;
190
191         return err;
192 }
193
194 static int read_nor_arc_info(void)
195 {
196         int i;
197
198         for (i = 0; i < MAX_FWENV_ADDR; i++)
199                 if (fwenv_addr[i] != -1) {
200                         memcpy(smac, (void *)fwenv_addr[i], sizeof(smac));
201                         return (i + 1);
202                 }
203
204         return 0;
205 }
206 #endif
207
208 int set_arc_product(int argc, char *const argv[])
209 {
210         if (argc != 5)
211                 return -1;
212
213         /* Check serial number */
214         if (strlen(argv[1]) != MAX_SERIAL_SIZE)
215                 return -1;
216
217         /* Check HWaddrs */
218         if (ishwaddr(argv[2]) || ishwaddr(argv[3]) || ishwaddr(argv[4]))
219                 return -1;
220
221         strcpy(smac[0], argv[1]);
222         strcpy(smac[1], argv[2]);
223         strcpy(smac[2], argv[3]);
224         strcpy(smac[3], argv[4]);
225
226 #if (FWENV_TYPE == FWENV_NOR_FLASH)
227         return set_nor_arc_product(argc, argv);
228 #endif
229 #if (FWENV_TYPE == FWENV_SPI_FLASH)
230         return set_spi_arc_product(argc, argv);
231 #endif
232 #if (FWENV_TYPE == FWENV_MMC)
233         return set_mmc_arc_product(argc, argv);
234 #endif
235         return -2;
236 }
237
238 static int read_arc_info(void)
239 {
240 #if (FWENV_TYPE == FWENV_NOR_FLASH)
241         return read_nor_arc_info();
242 #endif
243 #if (FWENV_TYPE == FWENV_SPI_FLASH)
244         return read_spi_arc_info();
245 #endif
246 #if (FWENV_TYPE == FWENV_MMC)
247         return read_mmc_arc_info();
248 #endif
249         return 0;
250 }
251
252 static int do_get_arc_info(void)
253 {
254         int l = read_arc_info();
255         char *oldserial = env_get("SERIAL");
256         char *oldversion = env_get("VERSION");
257
258         if (oldversion != NULL)
259                 if (strcmp(oldversion, U_BOOT_VERSION) != 0)
260                         oldversion = NULL;
261
262         if (l == 0) {
263                 printf("%s: failed to read factory info\n", __func__);
264                 return -2;
265         }
266
267         printf("\rSERIAL:  ");
268         if (smac[0][0] == EMPY_CHAR) {
269                 printf("<not found>\n");
270         } else {
271                 printf("%s\n", smac[0]);
272                 env_set("SERIAL", smac[0]);
273         }
274
275         if (strcmp(smac[1], "00:00:00:00:00:00") == 0) {
276                 env_set("ethaddr", NULL);
277                 env_set("eth1addr", NULL);
278                 env_set("eth2addr", NULL);
279                 goto done;
280         }
281
282         printf("HWADDR0: ");
283         if (smac[1][0] == EMPY_CHAR) {
284                 printf("<not found>\n");
285         } else {
286                 char *ret = env_get("ethaddr");
287
288                 if (ret == NULL) {
289                         env_set("ethaddr", smac[1]);
290                         printf("%s\n", smac[1]);
291                 } else if (strcmp(ret, __stringify(CONFIG_ETHADDR)) == 0) {
292                         env_set("ethaddr", smac[1]);
293                         printf("%s (factory)\n", smac[1]);
294                 } else {
295                         printf("%s\n", ret);
296                 }
297         }
298
299         if (strcmp(smac[2], "00:00:00:00:00:00") == 0) {
300                 env_set("eth1addr", NULL);
301                 env_set("eth2addr", NULL);
302                 goto done;
303         }
304
305         printf("HWADDR1: ");
306         if (smac[2][0] == EMPY_CHAR) {
307                 printf("<not found>\n");
308         } else {
309                 char *ret = env_get("eth1addr");
310
311                 if (ret == NULL) {
312                         env_set("ethaddr", smac[2]);
313                         printf("%s\n", smac[2]);
314                 } else if (strcmp(ret, __stringify(CONFIG_ETH1ADDR)) == 0) {
315                         env_set("eth1addr", smac[2]);
316                         printf("%s (factory)\n", smac[2]);
317                 } else {
318                         printf("%s\n", ret);
319                 }
320         }
321
322         if (strcmp(smac[3], "00:00:00:00:00:00") == 0) {
323                 env_set("eth2addr", NULL);
324                 goto done;
325         }
326
327         printf("HWADDR2: ");
328         if (smac[3][0] == EMPY_CHAR) {
329                 printf("<not found>\n");
330         } else {
331                 char *ret = env_get("eth2addr");
332
333                 if (ret == NULL) {
334                         env_set("ethaddr", smac[3]);
335                         printf("%s\n", smac[3]);
336                 } else if (strcmp(ret, __stringify(CONFIG_ETH2ADDR)) == 0) {
337                         env_set("eth2addr", smac[3]);
338                         printf("%s (factory)\n", smac[3]);
339                 } else {
340                         printf("%s\n", ret);
341                 }
342         }
343 done:
344         if (oldserial == NULL || oldversion == NULL) {
345                 if (oldversion == NULL)
346                         env_set("VERSION", U_BOOT_VERSION);
347                 env_save();
348         }
349
350         return 0;
351 }
352
353 static int init_fwenv(void)
354 {
355         int i, ret = -1;
356
357         fwenv_addr[0] = FWENV_ADDR1;
358         fwenv_addr[1] = FWENV_ADDR2;
359         fwenv_addr[2] = FWENV_ADDR3;
360         fwenv_addr[3] = FWENV_ADDR4;
361
362         for (i = 0; i < MAX_FWENV_ADDR; i++)
363                 if (fwenv_addr[i] != -1)
364                         ret = 0;
365         if (ret)
366                 printf("%s: No firmfare info storage address is defined\n",
367                        __func__);
368         return ret;
369 }
370
371 void get_arc_info(void)
372 {
373         if (!init_fwenv())
374                 do_get_arc_info();
375 }
376
377 static int do_arc_cmd(cmd_tbl_t * cmdtp, int flag, int argc, char *const argv[])
378 {
379         const char *cmd;
380         int ret = -1;
381
382         cmd = argv[1];
383         --argc;
384         ++argv;
385
386         if (init_fwenv())
387                 return ret;
388
389         if (strcmp(cmd, "product") == 0)
390                 ret = set_arc_product(argc, argv);
391         else if (strcmp(cmd, "info") == 0)
392                 ret = do_get_arc_info();
393
394         if (ret == -1)
395                 return CMD_RET_USAGE;
396
397         return ret;
398 }
399
400 U_BOOT_CMD(arc, 6, 1, do_arc_cmd,
401            "Arcturus product command sub-system",
402            "product serial hwaddr0 hwaddr1 hwaddr2    - save Arcturus factory env\n"
403            "info                                      - show Arcturus factory env\n\n");