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