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