xref: /openbmc/u-boot/arch/arm/mach-imx/cmd_bmode.c (revision fabbeb33)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2012 Boundary Devices Inc.
4  */
5 #include <common.h>
6 #include <linux/errno.h>
7 #include <asm/io.h>
8 #include <asm/mach-imx/boot_mode.h>
9 #include <malloc.h>
10 #include <command.h>
11 
12 static const struct boot_mode *modes[2];
13 
14 static const struct boot_mode *search_modes(char *arg)
15 {
16 	int i;
17 
18 	for (i = 0; i < ARRAY_SIZE(modes); i++) {
19 		const struct boot_mode *p = modes[i];
20 		if (p) {
21 			while (p->name) {
22 				if (!strcmp(p->name, arg))
23 					return p;
24 				p++;
25 			}
26 		}
27 	}
28 	return NULL;
29 }
30 
31 static int create_usage(char *dest)
32 {
33 	int i;
34 	int size = 0;
35 
36 	for (i = 0; i < ARRAY_SIZE(modes); i++) {
37 		const struct boot_mode *p = modes[i];
38 		if (p) {
39 			while (p->name) {
40 				int len = strlen(p->name);
41 				if (dest) {
42 					memcpy(dest, p->name, len);
43 					dest += len;
44 					*dest++ = '|';
45 				}
46 				size += len + 1;
47 				p++;
48 			}
49 		}
50 	}
51 	if (dest)
52 		memcpy(dest - 1, " [noreset]", 11);	/* include trailing 0 */
53 	size += 10;
54 	return size;
55 }
56 
57 static int do_boot_mode(cmd_tbl_t *cmdtp, int flag, int argc,
58 		char * const argv[])
59 {
60 	const struct boot_mode *p;
61 	int reset_requested = 1;
62 
63 	if (argc < 2)
64 		return CMD_RET_USAGE;
65 	p = search_modes(argv[1]);
66 	if (!p)
67 		return CMD_RET_USAGE;
68 	if (argc == 3) {
69 		if (strcmp(argv[2], "noreset"))
70 			return CMD_RET_USAGE;
71 		reset_requested = 0;
72 	}
73 
74 	boot_mode_apply(p->cfg_val);
75 	if (reset_requested && p->cfg_val)
76 		do_reset(NULL, 0, 0, NULL);
77 	return 0;
78 }
79 
80 U_BOOT_CMD(
81 	bmode, 3, 0, do_boot_mode,
82 	NULL,
83 	"");
84 
85 void add_board_boot_modes(const struct boot_mode *p)
86 {
87 	int size;
88 	char *dest;
89 
90 	cmd_tbl_t *entry = ll_entry_get(cmd_tbl_t, bmode, cmd);
91 
92 	if (entry->usage) {
93 		free(entry->usage);
94 		entry->usage = NULL;
95 	}
96 
97 	modes[0] = p;
98 	modes[1] = soc_boot_modes;
99 	size = create_usage(NULL);
100 	dest = malloc(size);
101 	if (dest) {
102 		create_usage(dest);
103 		entry->usage = dest;
104 	}
105 }
106