aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/setup.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/setup.c')
-rw-r--r--arch/mips/kernel/setup.c144
1 files changed, 86 insertions, 58 deletions
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index bcbd926e58f7..489b27320dfa 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -200,7 +200,12 @@ static inline void parse_cmdline_early(void)
200 } 200 }
201} 201}
202 202
203static inline int parse_rd_cmdline(unsigned long* rd_start, unsigned long* rd_end) 203/*
204 * Manage initrd
205 */
206#ifdef CONFIG_BLK_DEV_INITRD
207
208static int __init parse_rd_cmdline(unsigned long *rd_start, unsigned long *rd_end)
204{ 209{
205 /* 210 /*
206 * "rd_start=0xNNNNNNNN" defines the memory address of an initrd 211 * "rd_start=0xNNNNNNNN" defines the memory address of an initrd
@@ -263,49 +268,93 @@ static inline int parse_rd_cmdline(unsigned long* rd_start, unsigned long* rd_en
263 return 0; 268 return 0;
264} 269}
265 270
271static unsigned long __init init_initrd(void)
272{
273 unsigned long tmp, end;
274 u32 *initrd_header;
275
276 ROOT_DEV = Root_RAM0;
277
278 if (parse_rd_cmdline(&initrd_start, &initrd_end))
279 return initrd_end;
280 /*
281 * Board specific code should have set up initrd_start
282 * and initrd_end...
283 */
284 end = (unsigned long)&_end;
285 tmp = PAGE_ALIGN(end) - sizeof(u32) * 2;
286 if (tmp < end)
287 tmp += PAGE_SIZE;
288
289 initrd_header = (u32 *)tmp;
290 if (initrd_header[0] == 0x494E5244) {
291 initrd_start = (unsigned long)&initrd_header[2];
292 initrd_end = initrd_start + initrd_header[1];
293 }
294 return initrd_end;
295}
296
297static void __init finalize_initrd(void)
298{
299 unsigned long size = initrd_end - initrd_start;
300
301 if (size == 0) {
302 printk(KERN_INFO "Initrd not found or empty");
303 goto disable;
304 }
305 if (CPHYSADDR(initrd_end) > PFN_PHYS(max_low_pfn)) {
306 printk("Initrd extends beyond end of memory");
307 goto disable;
308 }
309
310 reserve_bootmem(CPHYSADDR(initrd_start), size);
311 initrd_below_start_ok = 1;
312
313 printk(KERN_INFO "Initial ramdisk at: 0x%lx (%lu bytes)\n",
314 initrd_start, size);
315 return;
316disable:
317 printk(" - disabling initrd\n");
318 initrd_start = 0;
319 initrd_end = 0;
320}
321
322#else /* !CONFIG_BLK_DEV_INITRD */
323
324#define init_initrd() 0
325#define finalize_initrd() do {} while (0)
326
327#endif
328
266/* 329/*
267 * Initialize the bootmem allocator. It also setup initrd related data 330 * Initialize the bootmem allocator. It also setup initrd related data
268 * if needed. 331 * if needed.
269 */ 332 */
333#ifdef CONFIG_SGI_IP27
334
270static void __init bootmem_init(void) 335static void __init bootmem_init(void)
271{ 336{
272 unsigned long reserved_end = (unsigned long)&_end; 337 init_initrd();
273#ifndef CONFIG_SGI_IP27 338 finalize_initrd();
339}
340
341#else /* !CONFIG_SGI_IP27 */
342
343static void __init bootmem_init(void)
344{
345 unsigned long reserved_end;
274 unsigned long highest = 0; 346 unsigned long highest = 0;
275 unsigned long mapstart = -1UL; 347 unsigned long mapstart = -1UL;
276 unsigned long bootmap_size; 348 unsigned long bootmap_size;
277 int i; 349 int i;
278#endif
279#ifdef CONFIG_BLK_DEV_INITRD
280 int initrd_reserve_bootmem = 0;
281
282 /* Board specific code should have set up initrd_start and initrd_end */
283 ROOT_DEV = Root_RAM0;
284 if (parse_rd_cmdline(&initrd_start, &initrd_end)) {
285 reserved_end = max(reserved_end, initrd_end);
286 initrd_reserve_bootmem = 1;
287 } else {
288 unsigned long tmp;
289 u32 *initrd_header;
290
291 tmp = PAGE_ALIGN(reserved_end) - sizeof(u32) * 2;
292 if (tmp < reserved_end)
293 tmp += PAGE_SIZE;
294 initrd_header = (u32 *)tmp;
295 if (initrd_header[0] == 0x494E5244) {
296 initrd_start = (unsigned long)&initrd_header[2];
297 initrd_end = initrd_start + initrd_header[1];
298 reserved_end = max(reserved_end, initrd_end);
299 initrd_reserve_bootmem = 1;
300 }
301 }
302#endif /* CONFIG_BLK_DEV_INITRD */
303 350
304#ifndef CONFIG_SGI_IP27
305 /* 351 /*
306 * reserved_end is now a pfn 352 * Init any data related to initrd. It's a nop if INITRD is
353 * not selected. Once that done we can determine the low bound
354 * of usable memory.
307 */ 355 */
308 reserved_end = PFN_UP(CPHYSADDR(reserved_end)); 356 reserved_end = init_initrd();
357 reserved_end = PFN_UP(CPHYSADDR(max(reserved_end, (unsigned long)&_end)));
309 358
310 /* 359 /*
311 * Find the highest page frame number we have available. 360 * Find the highest page frame number we have available.
@@ -388,35 +437,14 @@ static void __init bootmem_init(void)
388 */ 437 */
389 reserve_bootmem(PFN_PHYS(mapstart), bootmap_size); 438 reserve_bootmem(PFN_PHYS(mapstart), bootmap_size);
390 439
391#endif /* CONFIG_SGI_IP27 */ 440 /*
392 441 * Reserve initrd memory if needed.
393#ifdef CONFIG_BLK_DEV_INITRD 442 */
394 initrd_below_start_ok = 1; 443 finalize_initrd();
395 if (initrd_start) {
396 unsigned long initrd_size = ((unsigned char *)initrd_end) -
397 ((unsigned char *)initrd_start);
398 const int width = sizeof(long) * 2;
399
400 printk("Initial ramdisk at: 0x%p (%lu bytes)\n",
401 (void *)initrd_start, initrd_size);
402
403 if (CPHYSADDR(initrd_end) > PFN_PHYS(max_low_pfn)) {
404 printk("initrd extends beyond end of memory "
405 "(0x%0*Lx > 0x%0*Lx)\ndisabling initrd\n",
406 width,
407 (unsigned long long) CPHYSADDR(initrd_end),
408 width,
409 (unsigned long long) PFN_PHYS(max_low_pfn));
410 initrd_start = initrd_end = 0;
411 initrd_reserve_bootmem = 0;
412 }
413
414 if (initrd_reserve_bootmem)
415 reserve_bootmem(CPHYSADDR(initrd_start), initrd_size);
416 }
417#endif /* CONFIG_BLK_DEV_INITRD */
418} 444}
419 445
446#endif /* CONFIG_SGI_IP27 */
447
420/* 448/*
421 * arch_mem_init - initialize memory managment subsystem 449 * arch_mem_init - initialize memory managment subsystem
422 * 450 *