blob: 02fe72ed7faa2f418ad85bf7eabc2ea906c74b90 [file] [log] [blame]
Troy Kisky0ca618c2012-08-15 10:31:20 +00001/*
2 * Copyright (C) 2012 Boundary Devices Inc.
3 *
4 * See file CREDITS for list of people who contributed to this
5 * project.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20 * MA 02111-1307 USA
21 */
22#include <common.h>
23#include <asm/errno.h>
24#include <asm/io.h>
25#include <asm/imx-common/boot_mode.h>
26#include <malloc.h>
27
28static const struct boot_mode *modes[2];
29
30static const struct boot_mode *search_modes(char *arg)
31{
32 int i;
33
34 for (i = 0; i < ARRAY_SIZE(modes); i++) {
35 const struct boot_mode *p = modes[i];
36 if (p) {
37 while (p->name) {
38 if (!strcmp(p->name, arg))
39 return p;
40 p++;
41 }
42 }
43 }
44 return NULL;
45}
46
47static int create_usage(char *dest)
48{
49 int i;
50 int size = 0;
51
52 for (i = 0; i < ARRAY_SIZE(modes); i++) {
53 const struct boot_mode *p = modes[i];
54 if (p) {
55 while (p->name) {
56 int len = strlen(p->name);
57 if (dest) {
58 memcpy(dest, p->name, len);
59 dest += len;
60 *dest++ = '|';
61 }
62 size += len + 1;
63 p++;
64 }
65 }
66 }
67 if (dest)
68 memcpy(dest - 1, " [noreset]", 11); /* include trailing 0 */
69 size += 10;
70 return size;
71}
72
73static int do_boot_mode(cmd_tbl_t *cmdtp, int flag, int argc,
74 char * const argv[])
75{
76 const struct boot_mode *p;
77 int reset_requested = 1;
78
79 if (argc < 2)
80 return CMD_RET_USAGE;
81 p = search_modes(argv[1]);
82 if (!p)
83 return CMD_RET_USAGE;
84 if (argc == 3) {
85 if (strcmp(argv[2], "noreset"))
86 return CMD_RET_USAGE;
87 reset_requested = 0;
88 }
89
90 boot_mode_apply(p->cfg_val);
91 if (reset_requested && p->cfg_val)
92 do_reset(NULL, 0, 0, NULL);
93 return 0;
94}
95
96U_BOOT_CMD(
97 bmode, 3, 0, do_boot_mode,
98 NULL,
99 "");
100
101void add_board_boot_modes(const struct boot_mode *p)
102{
103 int size;
104 char *dest;
105
106 if (__u_boot_cmd_bmode.usage) {
107 free(__u_boot_cmd_bmode.usage);
108 __u_boot_cmd_bmode.usage = NULL;
109 }
110
111 modes[0] = p;
112 modes[1] = soc_boot_modes;
113 size = create_usage(NULL);
114 dest = malloc(size);
115 if (dest) {
116 create_usage(dest);
117 __u_boot_cmd_bmode.usage = dest;
118 }
119}