]>
git.ipfire.org Git - people/ms/u-boot.git/blob - arch/arm/lib/bootm.c
3 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
4 * Marius Groeger <mgroeger@sysgo.de>
6 * Copyright (C) 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include <u-boot/zlib.h>
28 #include <asm/byteorder.h>
31 #include <fdt_support.h>
33 DECLARE_GLOBAL_DATA_PTR
;
35 #if defined (CONFIG_SETUP_MEMORY_TAGS) || \
36 defined (CONFIG_CMDLINE_TAG) || \
37 defined (CONFIG_INITRD_TAG) || \
38 defined (CONFIG_SERIAL_TAG) || \
39 defined (CONFIG_REVISION_TAG)
40 static void setup_start_tag (bd_t
*bd
);
42 # ifdef CONFIG_SETUP_MEMORY_TAGS
43 static void setup_memory_tags (bd_t
*bd
);
45 static void setup_commandline_tag (bd_t
*bd
, char *commandline
);
47 # ifdef CONFIG_INITRD_TAG
48 static void setup_initrd_tag (bd_t
*bd
, ulong initrd_start
,
51 static void setup_end_tag (bd_t
*bd
);
53 static struct tag
*params
;
54 #endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */
56 static ulong
get_sp(void);
57 #if defined(CONFIG_OF_LIBFDT)
58 static int bootm_linux_fdt(int machid
, bootm_headers_t
*images
);
61 void arch_lmb_reserve(struct lmb
*lmb
)
66 * Booting a (Linux) kernel image
68 * Allocate space for command line and board info - the
69 * address should be as high as possible within the reach of
70 * the kernel (see CONFIG_SYS_BOOTMAPSZ settings), but in unused
71 * memory, which means far enough below the current stack
75 debug("## Current stack ends at 0x%08lx ", sp
);
77 /* adjust sp by 1K to be safe */
80 gd
->bd
->bi_dram
[0].start
+ gd
->bd
->bi_dram
[0].size
- sp
);
83 static void announce_and_cleanup(void)
85 printf("\nStarting kernel ...\n\n");
87 #ifdef CONFIG_USB_DEVICE
89 extern void udc_disconnect(void);
93 cleanup_before_linux();
96 int do_bootm_linux(int flag
, int argc
, char *argv
[], bootm_headers_t
*images
)
100 int machid
= bd
->bi_arch_number
;
101 void (*kernel_entry
)(int zero
, int arch
, uint params
);
103 #ifdef CONFIG_CMDLINE_TAG
104 char *commandline
= getenv ("bootargs");
107 if ((flag
!= 0) && (flag
!= BOOTM_STATE_OS_GO
))
110 s
= getenv ("machid");
112 machid
= simple_strtoul (s
, NULL
, 16);
113 printf ("Using machid 0x%x from environment\n", machid
);
116 show_boot_progress (15);
118 #ifdef CONFIG_OF_LIBFDT
120 return bootm_linux_fdt(machid
, images
);
123 kernel_entry
= (void (*)(int, int, uint
))images
->ep
;
125 debug ("## Transferring control to Linux (at address %08lx) ...\n",
126 (ulong
) kernel_entry
);
128 #if defined (CONFIG_SETUP_MEMORY_TAGS) || \
129 defined (CONFIG_CMDLINE_TAG) || \
130 defined (CONFIG_INITRD_TAG) || \
131 defined (CONFIG_SERIAL_TAG) || \
132 defined (CONFIG_REVISION_TAG)
133 setup_start_tag (bd
);
134 #ifdef CONFIG_SERIAL_TAG
135 setup_serial_tag (¶ms
);
137 #ifdef CONFIG_REVISION_TAG
138 setup_revision_tag (¶ms
);
140 #ifdef CONFIG_SETUP_MEMORY_TAGS
141 setup_memory_tags (bd
);
143 #ifdef CONFIG_CMDLINE_TAG
144 setup_commandline_tag (bd
, commandline
);
146 #ifdef CONFIG_INITRD_TAG
147 if (images
->rd_start
&& images
->rd_end
)
148 setup_initrd_tag (bd
, images
->rd_start
, images
->rd_end
);
153 announce_and_cleanup();
155 kernel_entry(0, machid
, bd
->bi_boot_params
);
156 /* does not return */
161 #if defined(CONFIG_OF_LIBFDT)
162 static int fixup_memory_node(void *blob
)
166 u64 start
[CONFIG_NR_DRAM_BANKS
];
167 u64 size
[CONFIG_NR_DRAM_BANKS
];
169 for (bank
= 0; bank
< CONFIG_NR_DRAM_BANKS
; bank
++) {
170 start
[bank
] = bd
->bi_dram
[bank
].start
;
171 size
[bank
] = bd
->bi_dram
[bank
].size
;
174 return fdt_fixup_memory_banks(blob
, start
, size
, CONFIG_NR_DRAM_BANKS
);
177 static int bootm_linux_fdt(int machid
, bootm_headers_t
*images
)
182 void (*kernel_entry
)(int zero
, int dt_machid
, void *dtblob
);
183 ulong bootmap_base
= getenv_bootm_low();
184 ulong of_size
= images
->ft_len
;
185 char **of_flat_tree
= &images
->ft_addr
;
186 ulong
*initrd_start
= &images
->initrd_start
;
187 ulong
*initrd_end
= &images
->initrd_end
;
188 struct lmb
*lmb
= &images
->lmb
;
191 kernel_entry
= (void (*)(int, int, void *))images
->ep
;
193 rd_len
= images
->rd_end
- images
->rd_start
;
194 ret
= boot_ramdisk_high(lmb
, images
->rd_start
, rd_len
,
195 initrd_start
, initrd_end
);
199 ret
= boot_relocate_fdt(lmb
, bootmap_base
, of_flat_tree
, &of_size
);
203 debug("## Transferring control to Linux (at address %08lx) ...\n",
204 (ulong
) kernel_entry
);
206 fdt_chosen(*of_flat_tree
, 1);
208 fixup_memory_node(*of_flat_tree
);
210 fdt_initrd(*of_flat_tree
, *initrd_start
, *initrd_end
, 1);
212 announce_and_cleanup();
214 kernel_entry(0, machid
, *of_flat_tree
);
215 /* does not return */
221 #if defined (CONFIG_SETUP_MEMORY_TAGS) || \
222 defined (CONFIG_CMDLINE_TAG) || \
223 defined (CONFIG_INITRD_TAG) || \
224 defined (CONFIG_SERIAL_TAG) || \
225 defined (CONFIG_REVISION_TAG)
226 static void setup_start_tag (bd_t
*bd
)
228 params
= (struct tag
*) bd
->bi_boot_params
;
230 params
->hdr
.tag
= ATAG_CORE
;
231 params
->hdr
.size
= tag_size (tag_core
);
233 params
->u
.core
.flags
= 0;
234 params
->u
.core
.pagesize
= 0;
235 params
->u
.core
.rootdev
= 0;
237 params
= tag_next (params
);
241 #ifdef CONFIG_SETUP_MEMORY_TAGS
242 static void setup_memory_tags (bd_t
*bd
)
246 for (i
= 0; i
< CONFIG_NR_DRAM_BANKS
; i
++) {
247 params
->hdr
.tag
= ATAG_MEM
;
248 params
->hdr
.size
= tag_size (tag_mem32
);
250 params
->u
.mem
.start
= bd
->bi_dram
[i
].start
;
251 params
->u
.mem
.size
= bd
->bi_dram
[i
].size
;
253 params
= tag_next (params
);
256 #endif /* CONFIG_SETUP_MEMORY_TAGS */
259 static void setup_commandline_tag (bd_t
*bd
, char *commandline
)
266 /* eat leading white space */
267 for (p
= commandline
; *p
== ' '; p
++);
269 /* skip non-existent command lines so the kernel will still
270 * use its default command line.
275 params
->hdr
.tag
= ATAG_CMDLINE
;
277 (sizeof (struct tag_header
) + strlen (p
) + 1 + 4) >> 2;
279 strcpy (params
->u
.cmdline
.cmdline
, p
);
281 params
= tag_next (params
);
285 #ifdef CONFIG_INITRD_TAG
286 static void setup_initrd_tag (bd_t
*bd
, ulong initrd_start
, ulong initrd_end
)
288 /* an ATAG_INITRD node tells the kernel where the compressed
289 * ramdisk can be found. ATAG_RDIMG is a better name, actually.
291 params
->hdr
.tag
= ATAG_INITRD2
;
292 params
->hdr
.size
= tag_size (tag_initrd
);
294 params
->u
.initrd
.start
= initrd_start
;
295 params
->u
.initrd
.size
= initrd_end
- initrd_start
;
297 params
= tag_next (params
);
299 #endif /* CONFIG_INITRD_TAG */
301 #ifdef CONFIG_SERIAL_TAG
302 void setup_serial_tag (struct tag
**tmp
)
304 struct tag
*params
= *tmp
;
305 struct tag_serialnr serialnr
;
306 void get_board_serial(struct tag_serialnr
*serialnr
);
308 get_board_serial(&serialnr
);
309 params
->hdr
.tag
= ATAG_SERIAL
;
310 params
->hdr
.size
= tag_size (tag_serialnr
);
311 params
->u
.serialnr
.low
= serialnr
.low
;
312 params
->u
.serialnr
.high
= serialnr
.high
;
313 params
= tag_next (params
);
318 #ifdef CONFIG_REVISION_TAG
319 void setup_revision_tag(struct tag
**in_params
)
322 u32
get_board_rev(void);
324 rev
= get_board_rev();
325 params
->hdr
.tag
= ATAG_REVISION
;
326 params
->hdr
.size
= tag_size (tag_revision
);
327 params
->u
.revision
.rev
= rev
;
328 params
= tag_next (params
);
330 #endif /* CONFIG_REVISION_TAG */
333 static void setup_end_tag (bd_t
*bd
)
335 params
->hdr
.tag
= ATAG_NONE
;
336 params
->hdr
.size
= 0;
339 static ulong
get_sp(void)
343 asm("mov %0, sp" : "=r"(ret
) : );
347 #endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */