main.c 14.9 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/*
 *  linux/init/main.c
 *
 *  Copyright (C) 1991, 1992  Linus Torvalds
 *
 *  GK 2/5/95  -  Changed to support mounting root fs via NFS
 *  Added initrd & change_root: Werner Almesberger & Hans Lermen, Feb '96
 *  Moan early if gcc is old, avoiding bogus kernels - Paul Gortmaker, May '96
 *  Simplified starting of init:  Michael A. Griffith <grif@acm.org> 
 */

#define __KERNEL_SYSCALLS__

#include <linux/config.h>
Andrew Morton's avatar
Andrew Morton committed
15
#include <linux/types.h>
16
#include <linux/module.h>
Linus Torvalds's avatar
Linus Torvalds committed
17 18
#include <linux/proc_fs.h>
#include <linux/devfs_fs_kernel.h>
19
#include <linux/kernel.h>
Andrew Morton's avatar
Andrew Morton committed
20
#include <linux/syscalls.h>
Linus Torvalds's avatar
Linus Torvalds committed
21 22 23 24 25 26 27
#include <linux/string.h>
#include <linux/ctype.h>
#include <linux/delay.h>
#include <linux/utsname.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/smp_lock.h>
Christoph Hellwig's avatar
Christoph Hellwig committed
28
#include <linux/initrd.h>
Linus Torvalds's avatar
Linus Torvalds committed
29 30
#include <linux/hdreg.h>
#include <linux/bootmem.h>
Linus Torvalds's avatar
Linus Torvalds committed
31
#include <linux/tty.h>
32
#include <linux/gfp.h>
Rusty Russell's avatar
Rusty Russell committed
33
#include <linux/percpu.h>
Andrew Morton's avatar
Andrew Morton committed
34
#include <linux/kernel_stat.h>
35
#include <linux/security.h>
Ingo Molnar's avatar
Ingo Molnar committed
36
#include <linux/workqueue.h>
John Levon's avatar
John Levon committed
37
#include <linux/profile.h>
38
#include <linux/rcupdate.h>
39
#include <linux/moduleparam.h>
40
#include <linux/kallsyms.h>
41
#include <linux/writeback.h>
42
#include <linux/cpu.h>
Andrew Morton's avatar
Andrew Morton committed
43
#include <linux/efi.h>
44
#include <linux/unistd.h>
Linus Torvalds's avatar
Linus Torvalds committed
45 46 47 48

#include <asm/io.h>
#include <asm/bugs.h>

49 50 51 52 53 54 55 56 57 58
/*
 * This is one of the first .c files built. Error out early
 * if we have compiler trouble..
 */
#if __GNUC__ == 2 && __GNUC_MINOR__ == 96
#ifdef CONFIG_FRAME_POINTER
#error This compiler cannot compile correctly with frame pointers enabled
#endif
#endif

Linus Torvalds's avatar
Linus Torvalds committed
59
#ifdef CONFIG_X86_LOCAL_APIC
Linus Torvalds's avatar
Linus Torvalds committed
60 61 62 63 64 65 66 67 68
#include <asm/smp.h>
#endif

/*
 * Versions of gcc older than that listed below may actually compile
 * and link okay, but the end product can have subtle run time bugs.
 * To avoid associated bogus bug reports, we flatly refuse to compile
 * with a gcc that is known to be too old from the very beginning.
 */
69
#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 95)
Linus Torvalds's avatar
Linus Torvalds committed
70 71 72 73 74 75 76 77 78 79 80 81 82 83
#error Sorry, your GCC is too old. It builds incorrect kernels.
#endif

extern char *linux_banner;

static int init(void *);

extern void init_IRQ(void);
extern void sock_init(void);
extern void fork_init(unsigned long);
extern void mca_init(void);
extern void sbus_init(void);
extern void sysctl_init(void);
extern void signals_init(void);
84
extern void buffer_init(void);
85
extern void pidhash_init(void);
86
extern void pidmap_init(void);
87
extern void pte_chain_init(void);
88
extern void radix_tree_init(void);
Linus Torvalds's avatar
Linus Torvalds committed
89
extern void free_initmem(void);
90
extern void populate_rootfs(void);
91
extern void driver_init(void);
92
extern void prepare_namespace(void);
Linus Torvalds's avatar
Linus Torvalds committed
93 94 95 96 97

#ifdef CONFIG_TC
extern void tc_init(void);
#endif

98
int system_state;	/* SYSTEM_BOOTING/RUNNING/SHUTDOWN */
99

Linus Torvalds's avatar
Linus Torvalds committed
100 101 102 103 104 105 106
/*
 * Boot command-line arguments
 */
#define MAX_INIT_ARGS 8
#define MAX_INIT_ENVS 8

extern void time_init(void);
107
/* Default late time init is NULL. archs can override this later. */
Andrew Morton's avatar
Andrew Morton committed
108
void (*late_time_init)(void);
Linus Torvalds's avatar
Linus Torvalds committed
109 110
extern void softirq_init(void);

111
static char *execute_command;
Linus Torvalds's avatar
Linus Torvalds committed
112

113
/* Setup configured maximum number of CPUs to activate */
Dave Jones's avatar
Dave Jones committed
114
static unsigned int max_cpus = NR_CPUS;
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141

/*
 * Setup routine for controlling SMP activation
 *
 * Command-line option of "nosmp" or "maxcpus=0" will disable SMP
 * activation entirely (the MPS table probe still happens, though).
 *
 * Command-line option of "maxcpus=<NUM>", where <NUM> is an integer
 * greater than 0, limits the maximum number of CPUs activated in
 * SMP mode to <NUM>.
 */
static int __init nosmp(char *str)
{
	max_cpus = 0;
	return 1;
}

__setup("nosmp", nosmp);

static int __init maxcpus(char *str)
{
	get_option(&str, &max_cpus);
	return 1;
}

__setup("maxcpus=", maxcpus);

Linus Torvalds's avatar
Linus Torvalds committed
142
static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, };
Linus Torvalds's avatar
Linus Torvalds committed
143
char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, };
144
static const char *panic_later, *panic_param;
Linus Torvalds's avatar
Linus Torvalds committed
145 146 147

__setup("profile=", profile_setup);

148
static int __init obsolete_checksetup(char *line)
Linus Torvalds's avatar
Linus Torvalds committed
149
{
150 151
	struct obs_kernel_param *p;
	extern struct obs_kernel_param __setup_start, __setup_end;
Linus Torvalds's avatar
Linus Torvalds committed
152 153 154 155

	p = &__setup_start;
	do {
		int n = strlen(p->str);
156 157 158 159 160
		if (!strncmp(line, p->str, n)) {
			if (!p->setup_func) {
				printk(KERN_WARNING "Parameter %s is obsolete, ignored\n", p->str);
				return 1;
			} else if (p->setup_func(line + n))
Linus Torvalds's avatar
Linus Torvalds committed
161 162 163 164 165 166 167 168 169 170 171
				return 1;
		}
		p++;
	} while (p < &__setup_end);
	return 0;
}

/* this should be approx 2 Bo*oMips to start (note initial shift), and will
   still work even if initially too large, it will just take slightly longer */
unsigned long loops_per_jiffy = (1<<12);

172 173 174 175
#ifndef __ia64__
EXPORT_SYMBOL(loops_per_jiffy);
#endif

Linus Torvalds's avatar
Linus Torvalds committed
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
/* This is the number of bits of precision for the loops_per_jiffy.  Each
   bit takes on average 1.5/HZ seconds.  This (like the original) is a little
   better than 1% */
#define LPS_PREC 8

void __init calibrate_delay(void)
{
	unsigned long ticks, loopbit;
	int lps_precision = LPS_PREC;

	loops_per_jiffy = (1<<12);

	printk("Calibrating delay loop... ");
	while (loops_per_jiffy <<= 1) {
		/* wait for "start of" clock tick */
		ticks = jiffies;
		while (ticks == jiffies)
			/* nothing */;
		/* Go .. */
		ticks = jiffies;
		__delay(loops_per_jiffy);
		ticks = jiffies - ticks;
		if (ticks)
			break;
	}

/* Do a binary approximation to get loops_per_jiffy set to equal one clock
   (up to lps_precision bits) */
	loops_per_jiffy >>= 1;
	loopbit = loops_per_jiffy;
	while ( lps_precision-- && (loopbit >>= 1) ) {
		loops_per_jiffy |= loopbit;
		ticks = jiffies;
		while (ticks == jiffies);
		ticks = jiffies;
		__delay(loops_per_jiffy);
		if (jiffies != ticks)	/* longer than 1 tick */
			loops_per_jiffy &= ~loopbit;
	}

/* Round the value and print it */	
	printk("%lu.%02lu BogoMIPS\n",
		loops_per_jiffy/(500000/HZ),
		(loops_per_jiffy/(5000/HZ)) % 100);
}

static int __init debug_kernel(char *str)
{
	if (*str)
		return 0;
	console_loglevel = 10;
	return 1;
}

static int __init quiet_kernel(char *str)
{
	if (*str)
		return 0;
	console_loglevel = 4;
	return 1;
}

__setup("debug", debug_kernel);
__setup("quiet", quiet_kernel);

241 242 243
/* Unknown boot options get handed to init, unless they look like
   failed parameters */
static int __init unknown_bootoption(char *param, char *val)
Linus Torvalds's avatar
Linus Torvalds committed
244
{
245 246 247
	/* Change NUL term back to "=", to make "param" the whole string. */
	if (val)
		val[-1] = '=';
Linus Torvalds's avatar
Linus Torvalds committed
248

249 250 251 252 253 254 255 256 257 258 259
	/* Handle obsolete-style parameters */
	if (obsolete_checksetup(param))
		return 0;

	/* Preemptive maintenance for "why didn't my mispelled command
           line work?" */
	if (strchr(param, '.') && (!val || strchr(param, '.') < val)) {
		printk(KERN_ERR "Unknown boot option `%s': ignoring\n", param);
		return 0;
	}

260 261 262
	if (panic_later)
		return 0;

263 264 265 266
	if (val) {
		/* Environment option */
		unsigned int i;
		for (i = 0; envp_init[i]; i++) {
267 268 269 270
			if (i == MAX_INIT_ENVS) {
				panic_later = "Too many boot env vars at `%s'";
				panic_param = param;
			}
Linus Torvalds's avatar
Linus Torvalds committed
271
		}
272 273 274 275 276
		envp_init[i] = param;
	} else {
		/* Command line option */
		unsigned int i;
		for (i = 0; argv_init[i]; i++) {
277 278 279 280
			if (i == MAX_INIT_ARGS) {
				panic_later = "Too many boot init vars at `%s'";
				panic_param = param;
			}
Linus Torvalds's avatar
Linus Torvalds committed
281
		}
282
		argv_init[i] = param;
Linus Torvalds's avatar
Linus Torvalds committed
283
	}
284
	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
285 286
}

287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
static int __init init_setup(char *str)
{
	unsigned int i;

	execute_command = str;
	/* In case LILO is going to boot us with default command line,
	 * it prepends "auto" before the whole cmdline which makes
	 * the shell think it should execute a script with such name.
	 * So we ignore all arguments entered _before_ init=... [MJ]
	 */
	for (i = 1; i < MAX_INIT_ARGS; i++)
		argv_init[i] = NULL;
	return 1;
}
__setup("init=", init_setup);

Linus Torvalds's avatar
Linus Torvalds committed
303 304 305 306 307
extern void setup_arch(char **);
extern void cpu_idle(void);

#ifndef CONFIG_SMP

Linus Torvalds's avatar
Linus Torvalds committed
308
#ifdef CONFIG_X86_LOCAL_APIC
Linus Torvalds's avatar
Linus Torvalds committed
309 310
static void __init smp_init(void)
{
Linus Torvalds's avatar
Linus Torvalds committed
311
	APIC_init_uniprocessor();
Linus Torvalds's avatar
Linus Torvalds committed
312 313 314 315 316
}
#else
#define smp_init()	do { } while (0)
#endif

317
static inline void setup_per_cpu_areas(void) { }
318
static inline void smp_prepare_cpus(unsigned int maxcpus) { }
319

Linus Torvalds's avatar
Linus Torvalds committed
320 321
#else

Rusty Russell's avatar
Rusty Russell committed
322
#ifdef __GENERIC_PER_CPU
Rusty Russell's avatar
Rusty Russell committed
323 324
unsigned long __per_cpu_offset[NR_CPUS];

325 326
EXPORT_SYMBOL(__per_cpu_offset);

Rusty Russell's avatar
Rusty Russell committed
327 328 329 330 331 332 333 334 335
static void __init setup_per_cpu_areas(void)
{
	unsigned long size, i;
	char *ptr;
	/* Created by linker magic */
	extern char __per_cpu_start[], __per_cpu_end[];

	/* Copy section for each CPU (we discard the original) */
	size = ALIGN(__per_cpu_end - __per_cpu_start, SMP_CACHE_BYTES);
336 337 338 339
#ifdef CONFIG_MODULES
	if (size < PERCPU_ENOUGH_ROOM)
		size = PERCPU_ENOUGH_ROOM;
#endif
Linus Torvalds's avatar
Linus Torvalds committed
340

Rusty Russell's avatar
Rusty Russell committed
341 342 343 344
	ptr = alloc_bootmem(size * NR_CPUS);

	for (i = 0; i < NR_CPUS; i++, ptr += size) {
		__per_cpu_offset[i] = ptr - __per_cpu_start;
345
		memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
Rusty Russell's avatar
Rusty Russell committed
346 347
	}
}
Rusty Russell's avatar
Rusty Russell committed
348
#endif /* !__GENERIC_PER_CPU */
Rusty Russell's avatar
Rusty Russell committed
349

Linus Torvalds's avatar
Linus Torvalds committed
350 351 352
/* Called by boot processor to activate the rest. */
static void __init smp_init(void)
{
353
	unsigned int i;
354
	unsigned j = 1;
355 356 357 358 359 360 361

	/* FIXME: This should be done in userspace --RR */
	for (i = 0; i < NR_CPUS; i++) {
		if (num_online_cpus() >= max_cpus)
			break;
		if (cpu_possible(i) && !cpu_online(i)) {
			cpu_up(i);
362
			j++;
363 364 365 366
		}
	}

	/* Any cleanup work */
367
	printk("Brought up %u CPUs\n", j);
368 369
	smp_cpus_done(max_cpus);
#if 0
Linus Torvalds's avatar
Linus Torvalds committed
370
	/* Get other processors into their bootup holding patterns. */
Linus Torvalds's avatar
Linus Torvalds committed
371

Linus Torvalds's avatar
Linus Torvalds committed
372 373
	smp_threads_ready=1;
	smp_commence();
374
#endif
Linus Torvalds's avatar
Linus Torvalds committed
375
}
Linus Torvalds's avatar
Linus Torvalds committed
376 377 378

#endif

Linus Torvalds's avatar
Linus Torvalds committed
379 380 381 382 383
/*
 * We need to finalize in a non-__init function or else race conditions
 * between the root thread and the init thread may cause start_kernel to
 * be reaped by free_initmem before the root thread has proceeded to
 * cpu_idle.
384 385
 *
 * gcc-3.4 accidentally inlines this function, so use noinline.
Linus Torvalds's avatar
Linus Torvalds committed
386 387
 */

388
static void noinline rest_init(void)
Linus Torvalds's avatar
Linus Torvalds committed
389
{
390
	kernel_thread(init, NULL, CLONE_FS | CLONE_SIGHAND);
Linus Torvalds's avatar
Linus Torvalds committed
391 392 393 394
	unlock_kernel();
 	cpu_idle();
} 

Linus Torvalds's avatar
Linus Torvalds committed
395 396 397
/*
 *	Activate the first processor.
 */
Linus Torvalds's avatar
Linus Torvalds committed
398

Linus Torvalds's avatar
Linus Torvalds committed
399 400 401 402
asmlinkage void __init start_kernel(void)
{
	char * command_line;
	extern char saved_command_line[];
403
	extern struct kernel_param __start___param[], __stop___param[];
Linus Torvalds's avatar
Linus Torvalds committed
404 405 406 407
/*
 * Interrupts are still disabled. Do necessary setups, then
 * enable them
 */
408
	lock_kernel();
409
	page_address_init();
Linus Torvalds's avatar
Linus Torvalds committed
410 411
	printk(linux_banner);
	setup_arch(&command_line);
Rusty Russell's avatar
Rusty Russell committed
412
	setup_per_cpu_areas();
413 414 415 416 417 418 419

	/*
	 * Mark the boot cpu "online" so that it can call console drivers in
	 * printk() and can access its per-cpu storage.
	 */
	smp_prepare_boot_cpu();

Andrew Morton's avatar
Andrew Morton committed
420
	build_all_zonelists();
421
	page_alloc_init();
Linus Torvalds's avatar
Linus Torvalds committed
422
	printk("Kernel command line: %s\n", saved_command_line);
423 424
	parse_args("Booting kernel", command_line, __start___param,
		   __stop___param - __start___param,
425
		   &unknown_bootoption);
426
	sort_main_extable();
Linus Torvalds's avatar
Linus Torvalds committed
427
	trap_init();
428
	rcu_init();
Linus Torvalds's avatar
Linus Torvalds committed
429
	init_IRQ();
430
	pidhash_init();
Linus Torvalds's avatar
Linus Torvalds committed
431 432
	sched_init();
	softirq_init();
Linus Torvalds's avatar
Linus Torvalds committed
433
	time_init();
Linus Torvalds's avatar
Linus Torvalds committed
434 435 436 437 438 439 440

	/*
	 * HACK ALERT! This is early. We're enabling the console before
	 * we've done PCI setups etc, and console_init() must be aware of
	 * this. But we do want output early, in case something goes wrong.
	 */
	console_init();
441 442
	if (panic_later)
		panic(panic_later, panic_param);
John Levon's avatar
John Levon committed
443
	profile_init();
444
	local_irq_enable();
Linus Torvalds's avatar
Linus Torvalds committed
445 446 447 448 449 450 451 452 453
#ifdef CONFIG_BLK_DEV_INITRD
	if (initrd_start && !initrd_below_start_ok &&
			initrd_start < min_low_pfn << PAGE_SHIFT) {
		printk(KERN_CRIT "initrd overwritten (0x%08lx < 0x%08lx) - "
		    "disabling it.\n",initrd_start,min_low_pfn << PAGE_SHIFT);
		initrd_start = 0;
	}
#endif
	mem_init();
454
	kmem_cache_init();
455 456 457
	if (late_time_init)
		late_time_init();
	calibrate_delay();
458
	pidmap_init();
Linus Torvalds's avatar
Linus Torvalds committed
459
	pgtable_cache_init();
460
	pte_chain_init();
Andrew Morton's avatar
Andrew Morton committed
461 462 463 464
#ifdef CONFIG_X86
	if (efi_enabled)
		efi_enter_virtual_mode();
#endif
465
	fork_init(num_physpages);
Linus Torvalds's avatar
Linus Torvalds committed
466
	proc_caches_init();
467
	buffer_init();
468
	unnamed_dev_init();
469
	security_scaffolding_startup();
470
	vfs_caches_init(num_physpages);
471
	radix_tree_init();
Linus Torvalds's avatar
Linus Torvalds committed
472
	signals_init();
473 474
	/* rootfs populating might need page-writeback */
	page_writeback_init();
Linus Torvalds's avatar
Linus Torvalds committed
475 476
#ifdef CONFIG_PROC_FS
	proc_root_init();
Linus Torvalds's avatar
Linus Torvalds committed
477 478 479 480 481 482 483 484 485
#endif
	check_bugs();
	printk("POSIX conformance testing by UNIFIX\n");

	/* 
	 *	We count on the initial thread going ok 
	 *	Like idlers init is an unlocked kernel thread, which will
	 *	make syscalls (and thus be locked).
	 */
486
	init_idle(current, smp_processor_id());
Linus Torvalds's avatar
Linus Torvalds committed
487 488

	/* Do the rest non-__init'ed, we're now alive */
Linus Torvalds's avatar
Linus Torvalds committed
489
	rest_init();
Linus Torvalds's avatar
Linus Torvalds committed
490 491
}

492
static int __initdata initcall_debug;
Andrew Morton's avatar
Andrew Morton committed
493 494 495 496 497 498 499 500

static int __init initcall_debug_setup(char *str)
{
	initcall_debug = 1;
	return 1;
}
__setup("initcall_debug", initcall_debug_setup);

Linus Torvalds's avatar
Linus Torvalds committed
501 502
struct task_struct *child_reaper = &init_task;

503 504
extern initcall_t __initcall_start, __initcall_end;

Linus Torvalds's avatar
Linus Torvalds committed
505 506 507
static void __init do_initcalls(void)
{
	initcall_t *call;
Andrew Morton's avatar
Andrew Morton committed
508 509 510 511 512
	int count = preempt_count();

	for (call = &__initcall_start; call < &__initcall_end; call++) {
		char *msg;

513 514 515 516 517
		if (initcall_debug) {
			printk(KERN_DEBUG "Calling initcall 0x%p", *call);
			print_symbol(": %s()", (unsigned long) *call);
			printk("\n");
		}
Linus Torvalds's avatar
Linus Torvalds committed
518 519

		(*call)();
Andrew Morton's avatar
Andrew Morton committed
520 521 522 523 524 525 526 527 528 529 530 531 532 533 534

		msg = NULL;
		if (preempt_count() != count) {
			msg = "preemption imbalance";
			preempt_count() = count;
		}
		if (irqs_disabled()) {
			msg = "disabled interrupts";
			local_irq_enable();
		}
		if (msg) {
			printk("error in initcall at 0x%p: "
				"returned with %s\n", *call, msg);
		}
	}
Linus Torvalds's avatar
Linus Torvalds committed
535 536

	/* Make sure there is no pending stuff from the initcall sequence */
Ingo Molnar's avatar
Ingo Molnar committed
537
	flush_scheduled_work();
Linus Torvalds's avatar
Linus Torvalds committed
538 539 540 541 542 543 544 545 546 547 548
}

/*
 * Ok, the machine is now initialized. None of the devices
 * have been touched yet, but the CPU subsystem is up and
 * running, and memory and process management works.
 *
 * Now we can finally start doing some real work..
 */
static void __init do_basic_setup(void)
{
549 550
	driver_init();

Linus Torvalds's avatar
Linus Torvalds committed
551 552 553 554 555 556 557
#ifdef CONFIG_SYSCTL
	sysctl_init();
#endif

	/* Networking initialization needs a process context */ 
	sock_init();

Ingo Molnar's avatar
Ingo Molnar committed
558
	init_workqueues();
Linus Torvalds's avatar
Linus Torvalds committed
559
	do_initcalls();
Linus Torvalds's avatar
Linus Torvalds committed
560 561
}

562 563 564
static void do_pre_smp_initcalls(void)
{
	extern int spawn_ksoftirqd(void);
565 566
#ifdef CONFIG_SMP
	extern int migration_init(void);
567 568

	migration_init();
569
#endif
570
	node_nr_running_init();
571 572 573
	spawn_ksoftirqd();
}

574 575 576 577 578 579
static void run_init_process(char *init_filename)
{
	argv_init[0] = init_filename;
	execve(init_filename, argv_init, envp_init);
}

Linus Torvalds's avatar
Linus Torvalds committed
580 581 582
static int init(void * unused)
{
	lock_kernel();
583 584 585 586 587 588 589 590 591 592
	/*
	 * Tell the world that we're going to be the grim
	 * reaper of innocent orphaned children.
	 *
	 * We don't want people to have to make incorrect
	 * assumptions about where in the task array this
	 * can be found.
	 */
	child_reaper = current;

593 594
	/* Sets up cpus_possible() */
	smp_prepare_cpus(max_cpus);
595 596 597

	do_pre_smp_initcalls();

598
	smp_init();
Linus Torvalds's avatar
Linus Torvalds committed
599

600 601 602 603
	/*
	 * Do this before initcalls, because some drivers want to access
	 * firmware files.
	 */
604
	populate_rootfs();
605 606 607

	do_basic_setup();

608 609 610 611 612 613 614 615
	/*
	 * check if there is an early userspace init.  If yes, let it do all
	 * the work
	 */
	if (sys_access("/init", 0) == 0)
		execute_command = "/init";
	else
		prepare_namespace();
Linus Torvalds's avatar
Linus Torvalds committed
616

Linus Torvalds's avatar
Linus Torvalds committed
617 618 619 620 621 622 623
	/*
	 * Ok, we have completed the initial bootup, and
	 * we're essentially up and running. Get rid of the
	 * initmem segments and start the user-mode stuff..
	 */
	free_initmem();
	unlock_kernel();
624
	system_state = SYSTEM_RUNNING;
Linus Torvalds's avatar
Linus Torvalds committed
625

626
	if (sys_open("/dev/console", O_RDWR, 0) < 0)
Linus Torvalds's avatar
Linus Torvalds committed
627 628
		printk("Warning: unable to open an initial console.\n");

629 630
	(void) sys_dup(0);
	(void) sys_dup(0);
Linus Torvalds's avatar
Linus Torvalds committed
631 632 633 634 635 636 637 638 639
	
	/*
	 * We try each of these until one succeeds.
	 *
	 * The Bourne shell can be used instead of init if we are 
	 * trying to recover a really broken machine.
	 */

	if (execute_command)
640 641 642 643 644 645 646
		run_init_process(execute_command);

	run_init_process("/sbin/init");
	run_init_process("/etc/init");
	run_init_process("/bin/init");
	run_init_process("/bin/sh");

Linus Torvalds's avatar
Linus Torvalds committed
647 648
	panic("No init found.  Try passing init= option to kernel.");
}