linux-old/init/main.c
<<
>>
Prefs
   1/*
   2 *  linux/init/main.c
   3 *
   4 *  Copyright (C) 1991, 1992  Linus Torvalds
   5 *
   6 *  GK 2/5/95  -  Changed to support mounting root fs via NFS
   7 *  Added initrd & change_root: Werner Almesberger & Hans Lermen, Feb '96
   8 *  Moan early if gcc is old, avoiding bogus kernels - Paul Gortmaker, May '96
   9 *  Simplified starting of init:  Michael A. Griffith <grif@acm.org> 
  10 */
  11
  12#define __KERNEL_SYSCALLS__
  13
  14#include <linux/config.h>
  15#include <linux/proc_fs.h>
  16#include <linux/devfs_fs_kernel.h>
  17#include <linux/unistd.h>
  18#include <linux/string.h>
  19#include <linux/ctype.h>
  20#include <linux/delay.h>
  21#include <linux/utsname.h>
  22#include <linux/ioport.h>
  23#include <linux/init.h>
  24#include <linux/smp_lock.h>
  25#include <linux/blk.h>
  26#include <linux/hdreg.h>
  27#include <linux/iobuf.h>
  28#include <linux/bootmem.h>
  29#include <linux/tty.h>
  30
  31#include <asm/io.h>
  32#include <asm/bugs.h>
  33
  34#if defined(CONFIG_ARCH_S390)
  35#include <asm/s390mach.h>
  36#include <asm/ccwcache.h>
  37#endif
  38
  39#ifdef CONFIG_PCI
  40#include <linux/pci.h>
  41#endif
  42
  43#ifdef CONFIG_DIO
  44#include <linux/dio.h>
  45#endif
  46
  47#ifdef CONFIG_ZORRO
  48#include <linux/zorro.h>
  49#endif
  50
  51#ifdef CONFIG_MTRR
  52#  include <asm/mtrr.h>
  53#endif
  54
  55#ifdef CONFIG_NUBUS
  56#include <linux/nubus.h>
  57#endif
  58
  59#ifdef CONFIG_ISAPNP
  60#include <linux/isapnp.h>
  61#endif
  62
  63#ifdef CONFIG_IRDA
  64extern int irda_proto_init(void);
  65extern int irda_device_init(void);
  66#endif
  67
  68#ifdef CONFIG_X86_LOCAL_APIC
  69#include <asm/smp.h>
  70#endif
  71
  72/*
  73 * Versions of gcc older than that listed below may actually compile
  74 * and link okay, but the end product can have subtle run time bugs.
  75 * To avoid associated bogus bug reports, we flatly refuse to compile
  76 * with a gcc that is known to be too old from the very beginning.
  77 */
  78#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 91)
  79#error Sorry, your GCC is too old. It builds incorrect kernels.
  80#endif
  81
  82extern char _stext, _etext;
  83extern char *linux_banner;
  84
  85static int init(void *);
  86
  87extern void init_IRQ(void);
  88extern void init_modules(void);
  89extern void sock_init(void);
  90extern void fork_init(unsigned long);
  91extern void mca_init(void);
  92extern void sbus_init(void);
  93extern void ppc_init(void);
  94extern void sysctl_init(void);
  95extern void signals_init(void);
  96extern int init_pcmcia_ds(void);
  97
  98extern void free_initmem(void);
  99
 100#ifdef CONFIG_TC
 101extern void tc_init(void);
 102#endif
 103
 104extern void ecard_init(void);
 105
 106#if defined(CONFIG_SYSVIPC)
 107extern void ipc_init(void);
 108#endif
 109#ifdef CONFIG_PERFMON
 110extern void perfmon_init(void);
 111#endif
 112
 113/*
 114 * Boot command-line arguments
 115 */
 116#define MAX_INIT_ARGS 8
 117#define MAX_INIT_ENVS 8
 118
 119extern void time_init(void);
 120extern void softirq_init(void);
 121
 122int rows, cols;
 123
 124#ifdef CONFIG_BLK_DEV_INITRD
 125unsigned int real_root_dev;     /* do_proc_dointvec cannot handle kdev_t */
 126#endif
 127
 128int root_mountflags = MS_RDONLY;
 129char *execute_command;
 130char root_device_name[64];
 131
 132
 133static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, };
 134static char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, };
 135
 136static int __init profile_setup(char *str)
 137{
 138    int par;
 139    if (get_option(&str,&par)) prof_shift = par;
 140        return 1;
 141}
 142
 143__setup("profile=", profile_setup);
 144
 145
 146static struct dev_name_struct {
 147        const char *name;
 148        const int num;
 149} root_dev_names[] __initdata = {
 150        { "nfs",     0x00ff },
 151        { "hda",     0x0300 },
 152        { "hdb",     0x0340 },
 153        { "loop",    0x0700 },
 154        { "hdc",     0x1600 },
 155        { "hdd",     0x1640 },
 156        { "hde",     0x2100 },
 157        { "hdf",     0x2140 },
 158        { "hdg",     0x2200 },
 159        { "hdh",     0x2240 },
 160        { "hdi",     0x3800 },
 161        { "hdj",     0x3840 },
 162        { "hdk",     0x3900 },
 163        { "hdl",     0x3940 },
 164        { "hdm",     0x5800 },
 165        { "hdn",     0x5840 },
 166        { "hdo",     0x5900 },
 167        { "hdp",     0x5940 },
 168        { "hdq",     0x5A00 },
 169        { "hdr",     0x5A40 },
 170        { "hds",     0x5B00 },
 171        { "hdt",     0x5B40 },
 172        { "sda",     0x0800 },
 173        { "sdb",     0x0810 },
 174        { "sdc",     0x0820 },
 175        { "sdd",     0x0830 },
 176        { "sde",     0x0840 },
 177        { "sdf",     0x0850 },
 178        { "sdg",     0x0860 },
 179        { "sdh",     0x0870 },
 180        { "sdi",     0x0880 },
 181        { "sdj",     0x0890 },
 182        { "sdk",     0x08a0 },
 183        { "sdl",     0x08b0 },
 184        { "sdm",     0x08c0 },
 185        { "sdn",     0x08d0 },
 186        { "sdo",     0x08e0 },
 187        { "sdp",     0x08f0 },
 188        { "ada",     0x1c00 },
 189        { "adb",     0x1c10 },
 190        { "adc",     0x1c20 },
 191        { "add",     0x1c30 },
 192        { "ade",     0x1c40 },
 193        { "fd",      0x0200 },
 194        { "md",      0x0900 },       
 195        { "xda",     0x0d00 },
 196        { "xdb",     0x0d40 },
 197        { "ram",     0x0100 },
 198        { "scd",     0x0b00 },
 199        { "mcd",     0x1700 },
 200        { "cdu535",  0x1800 },
 201        { "sonycd",  0x1800 },
 202        { "aztcd",   0x1d00 },
 203        { "cm206cd", 0x2000 },
 204        { "gscd",    0x1000 },
 205        { "sbpcd",   0x1900 },
 206        { "eda",     0x2400 },
 207        { "edb",     0x2440 },
 208        { "pda",        0x2d00 },
 209        { "pdb",        0x2d10 },
 210        { "pdc",        0x2d20 },
 211        { "pdd",        0x2d30 },
 212        { "pcd",        0x2e00 },
 213        { "pf",         0x2f00 },
 214        { "apblock", APBLOCK_MAJOR << 8},
 215        { "ddv", DDV_MAJOR << 8},
 216        { "jsfd",    JSFD_MAJOR << 8},
 217#if defined(CONFIG_ARCH_S390)
 218        { "dasda", (DASD_MAJOR << MINORBITS) },
 219        { "dasdb", (DASD_MAJOR << MINORBITS) + (1 << 2) },
 220        { "dasdc", (DASD_MAJOR << MINORBITS) + (2 << 2) },
 221        { "dasdd", (DASD_MAJOR << MINORBITS) + (3 << 2) },
 222        { "dasde", (DASD_MAJOR << MINORBITS) + (4 << 2) },
 223        { "dasdf", (DASD_MAJOR << MINORBITS) + (5 << 2) },
 224        { "dasdg", (DASD_MAJOR << MINORBITS) + (6 << 2) },
 225        { "dasdh", (DASD_MAJOR << MINORBITS) + (7 << 2) },
 226#endif
 227#if defined(CONFIG_BLK_CPQ_DA) || defined(CONFIG_BLK_CPQ_DA_MODULE)
 228        { "ida/c0d0p",0x4800 },
 229        { "ida/c0d1p",0x4810 },
 230        { "ida/c0d2p",0x4820 },
 231        { "ida/c0d3p",0x4830 },
 232        { "ida/c0d4p",0x4840 },
 233        { "ida/c0d5p",0x4850 },
 234        { "ida/c0d6p",0x4860 },
 235        { "ida/c0d7p",0x4870 },
 236        { "ida/c0d8p",0x4880 },
 237        { "ida/c0d9p",0x4890 },
 238        { "ida/c0d10p",0x48A0 },
 239        { "ida/c0d11p",0x48B0 },
 240        { "ida/c0d12p",0x48C0 },
 241        { "ida/c0d13p",0x48D0 },
 242        { "ida/c0d14p",0x48E0 },
 243        { "ida/c0d15p",0x48F0 },
 244#endif
 245#if defined(CONFIG_BLK_CPQ_CISS_DA) || defined(CONFIG_BLK_CPQ_CISS_DA_MODULE)
 246        { "cciss/c0d0p",0x6800 },
 247        { "cciss/c0d1p",0x6810 },
 248        { "cciss/c0d2p",0x6820 },
 249        { "cciss/c0d3p",0x6830 },
 250        { "cciss/c0d4p",0x6840 },
 251        { "cciss/c0d5p",0x6850 },
 252        { "cciss/c0d6p",0x6860 },
 253        { "cciss/c0d7p",0x6870 },
 254        { "cciss/c0d8p",0x6880 },
 255        { "cciss/c0d9p",0x6890 },
 256        { "cciss/c0d10p",0x68A0 },
 257        { "cciss/c0d11p",0x68B0 },
 258        { "cciss/c0d12p",0x68C0 },
 259        { "cciss/c0d13p",0x68D0 },
 260        { "cciss/c0d14p",0x68E0 },
 261        { "cciss/c0d15p",0x68F0 },
 262#endif
 263        { "nftla", 0x5d00 },
 264        { "nftlb", 0x5d10 },
 265        { "nftlc", 0x5d20 },
 266        { "nftld", 0x5d30 },
 267        { "ftla", 0x2c00 },
 268        { "ftlb", 0x2c08 },
 269        { "ftlc", 0x2c10 },
 270        { "ftld", 0x2c18 },
 271        { "mtdblock", 0x1f00 },
 272        { NULL, 0 }
 273};
 274
 275kdev_t __init name_to_kdev_t(char *line)
 276{
 277        int base = 0;
 278
 279        if (strncmp(line,"/dev/",5) == 0) {
 280                struct dev_name_struct *dev = root_dev_names;
 281                line += 5;
 282                do {
 283                        int len = strlen(dev->name);
 284                        if (strncmp(line,dev->name,len) == 0) {
 285                                line += len;
 286                                base = dev->num;
 287                                break;
 288                        }
 289                        dev++;
 290                } while (dev->name);
 291        }
 292        return to_kdev_t(base + simple_strtoul(line,NULL,base?10:16));
 293}
 294
 295static int __init root_dev_setup(char *line)
 296{
 297        int i;
 298        char ch;
 299
 300        ROOT_DEV = name_to_kdev_t(line);
 301        memset (root_device_name, 0, sizeof root_device_name);
 302        if (strncmp (line, "/dev/", 5) == 0) line += 5;
 303        for (i = 0; i < sizeof root_device_name - 1; ++i)
 304        {
 305            ch = line[i];
 306            if ( isspace (ch) || (ch == ',') || (ch == '\0') ) break;
 307            root_device_name[i] = ch;
 308        }
 309        return 1;
 310}
 311
 312__setup("root=", root_dev_setup);
 313
 314static int __init checksetup(char *line)
 315{
 316        struct kernel_param *p;
 317
 318        p = &__setup_start;
 319        do {
 320                int n = strlen(p->str);
 321                if (!strncmp(line,p->str,n)) {
 322                        if (p->setup_func(line+n))
 323                                return 1;
 324                }
 325                p++;
 326        } while (p < &__setup_end);
 327        return 0;
 328}
 329
 330/* this should be approx 2 Bo*oMips to start (note initial shift), and will
 331   still work even if initially too large, it will just take slightly longer */
 332unsigned long loops_per_jiffy = (1<<12);
 333
 334/* This is the number of bits of precision for the loops_per_jiffy.  Each
 335   bit takes on average 1.5/HZ seconds.  This (like the original) is a little
 336   better than 1% */
 337#define LPS_PREC 8
 338
 339void __init calibrate_delay(void)
 340{
 341        unsigned long ticks, loopbit;
 342        int lps_precision = LPS_PREC;
 343
 344        loops_per_jiffy = (1<<12);
 345
 346        printk("Calibrating delay loop... ");
 347        while (loops_per_jiffy <<= 1) {
 348                /* wait for "start of" clock tick */
 349                ticks = jiffies;
 350                while (ticks == jiffies)
 351                        /* nothing */;
 352                /* Go .. */
 353                ticks = jiffies;
 354                __delay(loops_per_jiffy);
 355                ticks = jiffies - ticks;
 356                if (ticks)
 357                        break;
 358        }
 359
 360/* Do a binary approximation to get loops_per_jiffy set to equal one clock
 361   (up to lps_precision bits) */
 362        loops_per_jiffy >>= 1;
 363        loopbit = loops_per_jiffy;
 364        while ( lps_precision-- && (loopbit >>= 1) ) {
 365                loops_per_jiffy |= loopbit;
 366                ticks = jiffies;
 367                while (ticks == jiffies);
 368                ticks = jiffies;
 369                __delay(loops_per_jiffy);
 370                if (jiffies != ticks)   /* longer than 1 tick */
 371                        loops_per_jiffy &= ~loopbit;
 372        }
 373
 374/* Round the value and print it */      
 375        printk("%lu.%02lu BogoMIPS\n",
 376                loops_per_jiffy/(500000/HZ),
 377                (loops_per_jiffy/(5000/HZ)) % 100);
 378}
 379
 380static int __init readonly(char *str)
 381{
 382        if (*str)
 383                return 0;
 384        root_mountflags |= MS_RDONLY;
 385        return 1;
 386}
 387
 388static int __init readwrite(char *str)
 389{
 390        if (*str)
 391                return 0;
 392        root_mountflags &= ~MS_RDONLY;
 393        return 1;
 394}
 395
 396static int __init debug_kernel(char *str)
 397{
 398        if (*str)
 399                return 0;
 400        console_loglevel = 10;
 401        return 1;
 402}
 403
 404static int __init quiet_kernel(char *str)
 405{
 406        if (*str)
 407                return 0;
 408        console_loglevel = 4;
 409        return 1;
 410}
 411
 412__setup("ro", readonly);
 413__setup("rw", readwrite);
 414__setup("debug", debug_kernel);
 415__setup("quiet", quiet_kernel);
 416
 417/*
 418 * This is a simple kernel command line parsing function: it parses
 419 * the command line, and fills in the arguments/environment to init
 420 * as appropriate. Any cmd-line option is taken to be an environment
 421 * variable if it contains the character '='.
 422 *
 423 * This routine also checks for options meant for the kernel.
 424 * These options are not given to init - they are for internal kernel use only.
 425 */
 426static void __init parse_options(char *line)
 427{
 428        char *next,*quote;
 429        int args, envs;
 430
 431        if (!*line)
 432                return;
 433        args = 0;
 434        envs = 1;       /* TERM is set to 'linux' by default */
 435        next = line;
 436        while ((line = next) != NULL) {
 437                quote = strchr(line,'"');
 438                next = strchr(line, ' ');
 439                while (next != NULL && quote != NULL && quote < next) {
 440                        /* we found a left quote before the next blank
 441                         * now we have to find the matching right quote
 442                         */
 443                        next = strchr(quote+1, '"');
 444                        if (next != NULL) {
 445                                quote = strchr(next+1, '"');
 446                                next = strchr(next+1, ' ');
 447                        }
 448                }
 449                if (next != NULL)
 450                        *next++ = 0;
 451                if (!strncmp(line,"init=",5)) {
 452                        line += 5;
 453                        execute_command = line;
 454                        /* In case LILO is going to boot us with default command line,
 455                         * it prepends "auto" before the whole cmdline which makes
 456                         * the shell think it should execute a script with such name.
 457                         * So we ignore all arguments entered _before_ init=... [MJ]
 458                         */
 459                        args = 0;
 460                        continue;
 461                }
 462                if (checksetup(line))
 463                        continue;
 464                
 465                /*
 466                 * Then check if it's an environment variable or
 467                 * an option.
 468                 */
 469                if (strchr(line,'=')) {
 470                        if (envs >= MAX_INIT_ENVS)
 471                                break;
 472                        envp_init[++envs] = line;
 473                } else {
 474                        if (args >= MAX_INIT_ARGS)
 475                                break;
 476                        if (*line)
 477                                argv_init[++args] = line;
 478                }
 479        }
 480        argv_init[args+1] = NULL;
 481        envp_init[envs+1] = NULL;
 482}
 483
 484
 485extern void setup_arch(char **);
 486extern void cpu_idle(void);
 487
 488unsigned long wait_init_idle;
 489
 490#ifndef CONFIG_SMP
 491
 492#ifdef CONFIG_X86_LOCAL_APIC
 493static void __init smp_init(void)
 494{
 495        APIC_init_uniprocessor();
 496}
 497#else
 498#define smp_init()      do { } while (0)
 499#endif
 500
 501#else
 502
 503
 504/* Called by boot processor to activate the rest. */
 505static void __init smp_init(void)
 506{
 507        /* Get other processors into their bootup holding patterns. */
 508        smp_boot_cpus();
 509        wait_init_idle = cpu_online_map;
 510        clear_bit(current->processor, &wait_init_idle); /* Don't wait on me! */
 511
 512        smp_threads_ready=1;
 513        smp_commence();
 514
 515        /* Wait for the other cpus to set up their idle processes */
 516        printk("Waiting on wait_init_idle (map = 0x%lx)\n", wait_init_idle);
 517        while (wait_init_idle) {
 518                cpu_relax();
 519                barrier();
 520        }
 521        printk("All processors have done init_idle\n");
 522}
 523
 524#endif
 525
 526/*
 527 * We need to finalize in a non-__init function or else race conditions
 528 * between the root thread and the init thread may cause start_kernel to
 529 * be reaped by free_initmem before the root thread has proceeded to
 530 * cpu_idle.
 531 */
 532
 533static void rest_init(void)
 534{
 535        kernel_thread(init, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL);
 536        unlock_kernel();
 537        current->need_resched = 1;
 538        cpu_idle();
 539} 
 540
 541/*
 542 *      Activate the first processor.
 543 */
 544
 545asmlinkage void __init start_kernel(void)
 546{
 547        char * command_line;
 548        unsigned long mempages;
 549        extern char saved_command_line[];
 550/*
 551 * Interrupts are still disabled. Do necessary setups, then
 552 * enable them
 553 */
 554        lock_kernel();
 555        printk(linux_banner);
 556        setup_arch(&command_line);
 557        printk("Kernel command line: %s\n", saved_command_line);
 558        parse_options(command_line);
 559        trap_init();
 560        init_IRQ();
 561        sched_init();
 562        softirq_init();
 563        time_init();
 564
 565        /*
 566         * HACK ALERT! This is early. We're enabling the console before
 567         * we've done PCI setups etc, and console_init() must be aware of
 568         * this. But we do want output early, in case something goes wrong.
 569         */
 570        console_init();
 571#ifdef CONFIG_MODULES
 572        init_modules();
 573#endif
 574        if (prof_shift) {
 575                unsigned int size;
 576                /* only text is profiled */
 577                prof_len = (unsigned long) &_etext - (unsigned long) &_stext;
 578                prof_len >>= prof_shift;
 579                
 580                size = prof_len * sizeof(unsigned int) + PAGE_SIZE-1;
 581                prof_buffer = (unsigned int *) alloc_bootmem(size);
 582        }
 583
 584        kmem_cache_init();
 585        sti();
 586        calibrate_delay();
 587#ifdef CONFIG_BLK_DEV_INITRD
 588        if (initrd_start && !initrd_below_start_ok &&
 589                        initrd_start < min_low_pfn << PAGE_SHIFT) {
 590                printk(KERN_CRIT "initrd overwritten (0x%08lx < 0x%08lx) - "
 591                    "disabling it.\n",initrd_start,min_low_pfn << PAGE_SHIFT);
 592                initrd_start = 0;
 593        }
 594#endif
 595        mem_init();
 596        kmem_cache_sizes_init();
 597        pgtable_cache_init();
 598
 599#ifdef CONFIG_PERFMON
 600        perfmon_init();
 601#endif
 602        mempages = num_physpages;
 603
 604        fork_init(mempages);
 605        proc_caches_init();
 606        vfs_caches_init(mempages);
 607        buffer_init(mempages);
 608        page_cache_init(mempages);
 609#if defined(CONFIG_ARCH_S390)
 610        ccwcache_init();
 611#endif
 612        signals_init();
 613#ifdef CONFIG_PROC_FS
 614        proc_root_init();
 615#endif
 616#if defined(CONFIG_SYSVIPC)
 617        ipc_init();
 618#endif
 619        check_bugs();
 620        printk("POSIX conformance testing by UNIFIX\n");
 621
 622        /* 
 623         *      We count on the initial thread going ok 
 624         *      Like idlers init is an unlocked kernel thread, which will
 625         *      make syscalls (and thus be locked).
 626         */
 627        smp_init();
 628        rest_init();
 629}
 630
 631#ifdef CONFIG_BLK_DEV_INITRD
 632static int do_linuxrc(void * shell)
 633{
 634        static char *argv[] = { "linuxrc", NULL, };
 635
 636        close(0);close(1);close(2);
 637        setsid();
 638        (void) open("/dev/console",O_RDWR,0);
 639        (void) dup(0);
 640        (void) dup(0);
 641        return execve(shell, argv, envp_init);
 642}
 643
 644#endif
 645
 646struct task_struct *child_reaper = &init_task;
 647
 648static void __init do_initcalls(void)
 649{
 650        initcall_t *call;
 651
 652        call = &__initcall_start;
 653        do {
 654                (*call)();
 655                call++;
 656        } while (call < &__initcall_end);
 657
 658        /* Make sure there is no pending stuff from the initcall sequence */
 659        flush_scheduled_tasks();
 660}
 661
 662/*
 663 * Ok, the machine is now initialized. None of the devices
 664 * have been touched yet, but the CPU subsystem is up and
 665 * running, and memory and process management works.
 666 *
 667 * Now we can finally start doing some real work..
 668 */
 669static void __init do_basic_setup(void)
 670{
 671
 672        /*
 673         * Tell the world that we're going to be the grim
 674         * reaper of innocent orphaned children.
 675         *
 676         * We don't want people to have to make incorrect
 677         * assumptions about where in the task array this
 678         * can be found.
 679         */
 680        child_reaper = current;
 681
 682#if defined(CONFIG_MTRR)        /* Do this after SMP initialization */
 683/*
 684 * We should probably create some architecture-dependent "fixup after
 685 * everything is up" style function where this would belong better
 686 * than in init/main.c..
 687 */
 688        mtrr_init();
 689#endif
 690
 691#ifdef CONFIG_SYSCTL
 692        sysctl_init();
 693#endif
 694
 695        /*
 696         * Ok, at this point all CPU's should be initialized, so
 697         * we can start looking into devices..
 698         */
 699#if defined(CONFIG_ARCH_S390)
 700        s390_init_machine_check();
 701#endif
 702
 703#ifdef CONFIG_PCI
 704        pci_init();
 705#endif
 706#ifdef CONFIG_SBUS
 707        sbus_init();
 708#endif
 709#if defined(CONFIG_PPC)
 710        ppc_init();
 711#endif
 712#ifdef CONFIG_MCA
 713        mca_init();
 714#endif
 715#ifdef CONFIG_ARCH_ACORN
 716        ecard_init();
 717#endif
 718#ifdef CONFIG_ZORRO
 719        zorro_init();
 720#endif
 721#ifdef CONFIG_DIO
 722        dio_init();
 723#endif
 724#ifdef CONFIG_NUBUS
 725        nubus_init();
 726#endif
 727#ifdef CONFIG_ISAPNP
 728        isapnp_init();
 729#endif
 730#ifdef CONFIG_TC
 731        tc_init();
 732#endif
 733
 734        /* Networking initialization needs a process context */ 
 735        sock_init();
 736
 737        start_context_thread();
 738        do_initcalls();
 739
 740#ifdef CONFIG_IRDA
 741        irda_proto_init();
 742        irda_device_init(); /* Must be done after protocol initialization */
 743#endif
 744#ifdef CONFIG_PCMCIA
 745        init_pcmcia_ds();               /* Do this last */
 746#endif
 747}
 748
 749extern void rd_load(void);
 750extern void initrd_load(void);
 751
 752/*
 753 * Prepare the namespace - decide what/where to mount, load ramdisks, etc.
 754 */
 755static void prepare_namespace(void)
 756{
 757#ifdef CONFIG_BLK_DEV_INITRD
 758        int real_root_mountflags = root_mountflags;
 759        if (!initrd_start)
 760                mount_initrd = 0;
 761        if (mount_initrd)
 762                root_mountflags &= ~MS_RDONLY;
 763        real_root_dev = ROOT_DEV;
 764#endif
 765
 766#ifdef CONFIG_BLK_DEV_RAM
 767#ifdef CONFIG_BLK_DEV_INITRD
 768        if (mount_initrd)
 769                initrd_load();
 770        else
 771#endif
 772        rd_load();
 773#endif
 774
 775        /* Mount the root filesystem.. */
 776        mount_root();
 777
 778        mount_devfs_fs ();
 779
 780#ifdef CONFIG_BLK_DEV_INITRD
 781        root_mountflags = real_root_mountflags;
 782        if (mount_initrd && ROOT_DEV != real_root_dev
 783            && MAJOR(ROOT_DEV) == RAMDISK_MAJOR && MINOR(ROOT_DEV) == 0) {
 784                int error;
 785                int i, pid;
 786
 787                pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD);
 788                if (pid > 0) {
 789                        while (pid != wait(&i)) {
 790                                current->policy |= SCHED_YIELD;
 791                                schedule();
 792                        }
 793                }
 794                if (MAJOR(real_root_dev) != RAMDISK_MAJOR
 795                     || MINOR(real_root_dev) != 0) {
 796                        error = change_root(real_root_dev,"/initrd");
 797                        if (error)
 798                                printk(KERN_ERR "Change root to /initrd: "
 799                                    "error %d\n",error);
 800                }
 801        }
 802#endif
 803}
 804
 805static int init(void * unused)
 806{
 807        lock_kernel();
 808        do_basic_setup();
 809
 810        prepare_namespace();
 811
 812        /*
 813         * Ok, we have completed the initial bootup, and
 814         * we're essentially up and running. Get rid of the
 815         * initmem segments and start the user-mode stuff..
 816         */
 817        free_initmem();
 818        unlock_kernel();
 819
 820        if (open("/dev/console", O_RDWR, 0) < 0)
 821                printk("Warning: unable to open an initial console.\n");
 822
 823        (void) dup(0);
 824        (void) dup(0);
 825        
 826        /*
 827         * We try each of these until one succeeds.
 828         *
 829         * The Bourne shell can be used instead of init if we are 
 830         * trying to recover a really broken machine.
 831         */
 832
 833        if (execute_command)
 834                execve(execute_command,argv_init,envp_init);
 835        execve("/sbin/init",argv_init,envp_init);
 836        execve("/etc/init",argv_init,envp_init);
 837        execve("/bin/init",argv_init,envp_init);
 838        execve("/bin/sh",argv_init,envp_init);
 839        panic("No init found.  Try passing init= option to kernel.");
 840}
 841
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.