xref: /openbmc/u-boot/arch/nds32/lib/bootm.c (revision ea818dbb)
1 /*
2  * Copyright (C) 2011 Andes Technology Corporation
3  * Shawn Lin, Andes Technology Corporation <nobuhiro@andestech.com>
4  * Macpaul Lin, Andes Technology Corporation <macpaul@andestech.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307	 USA
19  *
20  */
21 
22 #include <common.h>
23 #include <command.h>
24 #include <image.h>
25 #include <u-boot/zlib.h>
26 #include <asm/byteorder.h>
27 
28 DECLARE_GLOBAL_DATA_PTR;
29 
30 #if defined(CONFIG_SETUP_MEMORY_TAGS) || \
31 	defined(CONFIG_CMDLINE_TAG) || \
32 	defined(CONFIG_INITRD_TAG) || \
33 	defined(CONFIG_SERIAL_TAG) || \
34 	defined(CONFIG_REVISION_TAG)
35 static void setup_start_tag(bd_t *bd);
36 
37 # ifdef CONFIG_SETUP_MEMORY_TAGS
38 static void setup_memory_tags(bd_t *bd);
39 # endif
40 static void setup_commandline_tag(bd_t *bd, char *commandline);
41 
42 # ifdef CONFIG_INITRD_TAG
43 static void setup_initrd_tag(bd_t *bd, ulong initrd_start, ulong initrd_end);
44 # endif
45 static void setup_end_tag(bd_t *bd);
46 
47 static struct tag *params;
48 #endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */
49 
50 int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
51 {
52 	bd_t	*bd = gd->bd;
53 	char	*s;
54 	int	machid = bd->bi_arch_number;
55 	void	(*theKernel)(int zero, int arch, uint params);
56 
57 #ifdef CONFIG_CMDLINE_TAG
58 	char *commandline = getenv("bootargs");
59 #endif
60 
61 	/*
62 	 * allow the PREP bootm subcommand, it is required for bootm to work
63 	 */
64 	if (flag & BOOTM_STATE_OS_PREP)
65 		return 0;
66 
67 	if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
68 		return 1;
69 
70 	theKernel = (void (*)(int, int, uint))images->ep;
71 
72 	s = getenv("machid");
73 	if (s) {
74 		machid = simple_strtoul(s, NULL, 16);
75 		printf("Using machid 0x%x from environment\n", machid);
76 	}
77 
78 	bootstage_mark(BOOTSTAGE_ID_RUN_OS);
79 
80 	debug("## Transferring control to Linux (at address %08lx) ...\n",
81 	       (ulong)theKernel);
82 
83 #if defined(CONFIG_SETUP_MEMORY_TAGS) || \
84 	defined(CONFIG_CMDLINE_TAG) || \
85 	defined(CONFIG_INITRD_TAG) || \
86 	defined(CONFIG_SERIAL_TAG) || \
87 	defined(CONFIG_REVISION_TAG)
88 	setup_start_tag(bd);
89 #ifdef CONFIG_SERIAL_TAG
90 	setup_serial_tag(&params);
91 #endif
92 #ifdef CONFIG_REVISION_TAG
93 	setup_revision_tag(&params);
94 #endif
95 #ifdef CONFIG_SETUP_MEMORY_TAGS
96 	setup_memory_tags(bd);
97 #endif
98 #ifdef CONFIG_CMDLINE_TAG
99 	setup_commandline_tag(bd, commandline);
100 #endif
101 #ifdef CONFIG_INITRD_TAG
102 	if (images->rd_start && images->rd_end)
103 		setup_initrd_tag(bd, images->rd_start, images->rd_end);
104 #endif
105 	setup_end_tag(bd);
106 #endif
107 
108 	/* we assume that the kernel is in place */
109 	printf("\nStarting kernel ...\n\n");
110 
111 #ifdef CONFIG_USB_DEVICE
112 	{
113 		extern void udc_disconnect(void);
114 		udc_disconnect();
115 	}
116 #endif
117 
118 	cleanup_before_linux();
119 
120 	theKernel(0, machid, bd->bi_boot_params);
121 	/* does not return */
122 
123 	return 1;
124 }
125 
126 
127 #if defined(CONFIG_SETUP_MEMORY_TAGS) || \
128 	defined(CONFIG_CMDLINE_TAG) || \
129 	defined(CONFIG_INITRD_TAG) || \
130 	defined(CONFIG_SERIAL_TAG) || \
131 	defined(CONFIG_REVISION_TAG)
132 static void setup_start_tag(bd_t *bd)
133 {
134 	params = (struct tag *)bd->bi_boot_params;
135 
136 	params->hdr.tag = ATAG_CORE;
137 	params->hdr.size = tag_size(tag_core);
138 
139 	params->u.core.flags = 0;
140 	params->u.core.pagesize = 0;
141 	params->u.core.rootdev = 0;
142 
143 	params = tag_next(params);
144 }
145 
146 
147 #ifdef CONFIG_SETUP_MEMORY_TAGS
148 static void setup_memory_tags(bd_t *bd)
149 {
150 	int i;
151 
152 	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
153 		params->hdr.tag = ATAG_MEM;
154 		params->hdr.size = tag_size(tag_mem32);
155 
156 		params->u.mem.start = bd->bi_dram[i].start;
157 		params->u.mem.size = bd->bi_dram[i].size;
158 
159 		params = tag_next(params);
160 	}
161 }
162 #endif /* CONFIG_SETUP_MEMORY_TAGS */
163 
164 
165 static void setup_commandline_tag(bd_t *bd, char *commandline)
166 {
167 	char *p;
168 
169 	if (!commandline)
170 		return;
171 
172 	/* eat leading white space */
173 	for (p = commandline; *p == ' '; p++)
174 		;
175 
176 	/* skip non-existent command lines so the kernel will still
177 	 * use its default command line.
178 	 */
179 	if (*p == '\0')
180 		return;
181 
182 	params->hdr.tag = ATAG_CMDLINE;
183 	params->hdr.size =
184 		(sizeof(struct tag_header) + strlen(p) + 1 + 4) >> 2;
185 
186 	strcpy(params->u.cmdline.cmdline, p)
187 		;
188 
189 	params = tag_next(params);
190 }
191 
192 
193 #ifdef CONFIG_INITRD_TAG
194 static void setup_initrd_tag(bd_t *bd, ulong initrd_start, ulong initrd_end)
195 {
196 	/* an ATAG_INITRD node tells the kernel where the compressed
197 	 * ramdisk can be found. ATAG_RDIMG is a better name, actually.
198 	 */
199 	params->hdr.tag = ATAG_INITRD2;
200 	params->hdr.size = tag_size(tag_initrd);
201 
202 	params->u.initrd.start = initrd_start;
203 	params->u.initrd.size = initrd_end - initrd_start;
204 
205 	params = tag_next(params);
206 }
207 #endif /* CONFIG_INITRD_TAG */
208 
209 #ifdef CONFIG_SERIAL_TAG
210 void setup_serial_tag(struct tag **tmp)
211 {
212 	struct tag *params = *tmp;
213 	struct tag_serialnr serialnr;
214 	void get_board_serial(struct tag_serialnr *serialnr);
215 
216 	get_board_serial(&serialnr);
217 	params->hdr.tag = ATAG_SERIAL;
218 	params->hdr.size = tag_size(tag_serialnr);
219 	params->u.serialnr.low = serialnr.low;
220 	params->u.serialnr.high = serialnr.high;
221 	params = tag_next(params);
222 	*tmp = params;
223 }
224 #endif
225 
226 #ifdef CONFIG_REVISION_TAG
227 void setup_revision_tag(struct tag **in_params)
228 {
229 	u32 rev = 0;
230 	u32 get_board_rev(void);
231 
232 	rev = get_board_rev();
233 	params->hdr.tag = ATAG_REVISION;
234 	params->hdr.size = tag_size(tag_revision);
235 	params->u.revision.rev = rev;
236 	params = tag_next(params);
237 }
238 #endif  /* CONFIG_REVISION_TAG */
239 
240 
241 static void setup_end_tag(bd_t *bd)
242 {
243 	params->hdr.tag = ATAG_NONE;
244 	params->hdr.size = 0;
245 }
246 
247 #endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */
248