The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/init_main.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: init_main.c,v 1.235 2004/03/28 22:43:56 matt Exp $     */
    2 
    3 /*
    4  * Copyright (c) 1982, 1986, 1989, 1991, 1992, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  * (c) UNIX System Laboratories, Inc.
    7  * All or some portions of this file are derived from material licensed
    8  * to the University of California by American Telephone and Telegraph
    9  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
   10  * the permission of UNIX System Laboratories, Inc.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. Neither the name of the University nor the names of its contributors
   21  *    may be used to endorse or promote products derived from this software
   22  *    without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34  * SUCH DAMAGE.
   35  *
   36  *      @(#)init_main.c 8.16 (Berkeley) 5/14/95
   37  */
   38 
   39 /*
   40  * Copyright (c) 1995 Christopher G. Demetriou.  All rights reserved.
   41  *
   42  * Redistribution and use in source and binary forms, with or without
   43  * modification, are permitted provided that the following conditions
   44  * are met:
   45  * 1. Redistributions of source code must retain the above copyright
   46  *    notice, this list of conditions and the following disclaimer.
   47  * 2. Redistributions in binary form must reproduce the above copyright
   48  *    notice, this list of conditions and the following disclaimer in the
   49  *    documentation and/or other materials provided with the distribution.
   50  * 3. All advertising materials mentioning features or use of this software
   51  *    must display the following acknowledgement:
   52  *      This product includes software developed by the University of
   53  *      California, Berkeley and its contributors.
   54  * 4. Neither the name of the University nor the names of its contributors
   55  *    may be used to endorse or promote products derived from this software
   56  *    without specific prior written permission.
   57  *
   58  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   59  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   60  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   61  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   62  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   63  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   64  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   65  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   66  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   67  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   68  * SUCH DAMAGE.
   69  *
   70  *      @(#)init_main.c 8.16 (Berkeley) 5/14/95
   71  */
   72 
   73 #include <sys/cdefs.h>
   74 __KERNEL_RCSID(0, "$NetBSD: init_main.c,v 1.235 2004/03/28 22:43:56 matt Exp $");
   75 
   76 #include "fs_nfs.h"
   77 #include "opt_nfsserver.h"
   78 #include "opt_ipsec.h"
   79 #include "opt_sysv.h"
   80 #include "opt_maxuprc.h"
   81 #include "opt_multiprocessor.h"
   82 #include "opt_pipe.h"
   83 #include "opt_syscall_debug.h"
   84 #include "opt_systrace.h"
   85 #include "opt_posix.h"
   86 #include "opt_kcont.h"
   87 
   88 #include "opencrypto.h"
   89 #include "rnd.h"
   90 
   91 #include <sys/param.h>
   92 #include <sys/acct.h>
   93 #include <sys/filedesc.h>
   94 #include <sys/file.h>
   95 #include <sys/errno.h>
   96 #include <sys/callout.h>
   97 #include <sys/kernel.h>
   98 #include <sys/kcont.h>
   99 #include <sys/mount.h>
  100 #include <sys/proc.h>
  101 #include <sys/kthread.h>
  102 #include <sys/resourcevar.h>
  103 #include <sys/signalvar.h>
  104 #include <sys/systm.h>
  105 #include <sys/vnode.h>
  106 #include <sys/tty.h>
  107 #include <sys/conf.h>
  108 #include <sys/disklabel.h>
  109 #include <sys/buf.h>
  110 #include <sys/device.h>
  111 #include <sys/disk.h>
  112 #include <sys/exec.h>
  113 #include <sys/socketvar.h>
  114 #include <sys/protosw.h>
  115 #include <sys/reboot.h>
  116 #include <sys/user.h>
  117 #include <sys/sysctl.h>
  118 #include <sys/event.h>
  119 #include <sys/mbuf.h>
  120 #ifdef FAST_IPSEC
  121 #include <netipsec/ipsec.h>
  122 #endif
  123 #ifdef SYSVSHM
  124 #include <sys/shm.h>
  125 #endif
  126 #ifdef SYSVSEM
  127 #include <sys/sem.h>
  128 #endif
  129 #ifdef SYSVMSG
  130 #include <sys/msg.h>
  131 #endif
  132 #ifdef P1003_1B_SEMAPHORE
  133 #include <sys/ksem.h>
  134 #endif
  135 #ifdef SYSTRACE
  136 #include <sys/systrace.h>
  137 #endif
  138 #include <sys/domain.h>
  139 #include <sys/namei.h>
  140 #if NOPENCRYPTO > 0
  141 #include <opencrypto/cryptodev.h>       /* XXX really the framework */
  142 #endif
  143 #if NRND > 0
  144 #include <sys/rnd.h>
  145 #endif
  146 #ifndef PIPE_SOCKETPAIR
  147 #include <sys/pipe.h>
  148 #endif
  149 #ifdef LKM
  150 #include <sys/lkm.h>
  151 #endif
  152 
  153 #include <sys/syscall.h>
  154 #include <sys/sa.h>
  155 #include <sys/syscallargs.h>
  156 
  157 #include <ufs/ufs/quota.h>
  158 
  159 #include <miscfs/genfs/genfs.h>
  160 #include <miscfs/syncfs/syncfs.h>
  161 
  162 #include <machine/cpu.h>
  163 
  164 #include <uvm/uvm.h>
  165 
  166 #include <dev/cons.h>
  167 
  168 #include <net/if.h>
  169 #include <net/raw_cb.h>
  170 
  171 /* Components of the first process -- never freed. */
  172 struct  session session0;
  173 struct  pgrp pgrp0;
  174 struct  proc proc0;
  175 struct  lwp lwp0;
  176 struct  pcred cred0;
  177 struct  filedesc0 filedesc0;
  178 struct  cwdinfo cwdi0;
  179 struct  plimit limit0;
  180 struct  pstats pstat0;
  181 struct  vmspace vmspace0;
  182 struct  sigacts sigacts0;
  183 #ifndef curlwp
  184 struct  lwp *curlwp = &lwp0;
  185 #endif
  186 struct  proc *initproc;
  187 
  188 int     nofile = NOFILE;
  189 int     maxuprc = MAXUPRC;
  190 int     cmask = CMASK;
  191 extern  struct user *proc0paddr;
  192 
  193 struct  vnode *rootvp, *swapdev_vp;
  194 int     boothowto;
  195 int     cold = 1;                       /* still working on startup */
  196 struct  timeval boottime;
  197 
  198 __volatile int start_init_exec;         /* semaphore for start_init() */
  199 
  200 static void check_console(struct proc *p);
  201 static void start_init(void *);
  202 void main(void);
  203 
  204 extern const struct emul emul_netbsd;   /* defined in kern_exec.c */
  205 
  206 /*
  207  * System startup; initialize the world, create process 0, mount root
  208  * filesystem, and fork to create init and pagedaemon.  Most of the
  209  * hard work is done in the lower-level initialization routines including
  210  * startup(), which does memory initialization and autoconfiguration.
  211  */
  212 void
  213 main(void)
  214 {
  215         struct lwp *l;
  216         struct proc *p;
  217         struct pdevinit *pdev;
  218         int s, error;
  219         u_int i;
  220         rlim_t lim;
  221         extern struct pdevinit pdevinit[];
  222         extern void schedcpu(void *);
  223 #if defined(NFSSERVER) || defined(NFS)
  224         extern void nfs_init(void);
  225 #endif
  226 #ifdef NVNODE_IMPLICIT
  227         int usevnodes;
  228 #endif
  229 
  230         /*
  231          * Initialize the current LWP pointer (curlwp) before
  232          * any possible traps/probes to simplify trap processing.
  233          */
  234         l = &lwp0;
  235         curlwp = l;
  236         l->l_cpu = curcpu();
  237         l->l_proc = &proc0;
  238         l->l_lid = 1;
  239 
  240         /*
  241          * Attempt to find console and initialize
  242          * in case of early panic or other messages.
  243          */
  244         consinit();
  245         printf("%s", copyright);
  246 
  247         KERNEL_LOCK_INIT();
  248 
  249         uvm_init();
  250 
  251         /* Do machine-dependent initialization. */
  252         cpu_startup();
  253 
  254         /* Initialize callouts. */
  255         callout_startup();
  256 
  257         /* Initialize the buffer cache */
  258         bufinit();
  259 
  260         /*
  261          * Initialize mbuf's.  Do this now because we might attempt to
  262          * allocate mbufs or mbuf clusters during autoconfiguration.
  263          */
  264         mbinit();
  265 
  266         /* Initialize kqueues. */
  267         kqueue_init();
  268 
  269         /* Initialize sockets. */
  270         soinit();
  271 
  272 #ifdef KCONT
  273         /* Initialize kcont. */
  274         kcont_init();
  275 #endif
  276 
  277         /*
  278          * The following things must be done before autoconfiguration.
  279          */
  280         evcnt_init();           /* initialize event counters */
  281         disk_init();            /* initialize disk list */
  282         tty_init();             /* initialize tty list */
  283 #if NRND > 0
  284         rnd_init();             /* initialize RNG */
  285 #endif
  286 #if NOPENCRYPTO > 0
  287         /* Initialize crypto subsystem before configuring crypto hardware. */
  288         (void)crypto_init();
  289 #endif
  290         /* Initialize the sysctl subsystem. */
  291         sysctl_init();
  292 
  293         /*
  294          * Initialize process and pgrp structures.
  295          */
  296         procinit();
  297 
  298 #ifdef LKM
  299         /* Initialize the LKM system. */
  300         lkm_init();
  301 #endif
  302 
  303         /*
  304          * Create process 0 (the swapper).
  305          */
  306         p = &proc0;
  307         proc0_insert(p, l, &pgrp0, &session0);
  308 
  309         /*
  310          * Set P_NOCLDWAIT so that kernel threads are reparented to
  311          * init(8) when they exit.  init(8) can easily wait them out
  312          * for us.
  313          */
  314         p->p_flag = P_SYSTEM | P_NOCLDWAIT;
  315         p->p_stat = SACTIVE;
  316         p->p_nice = NZERO;
  317         p->p_emul = &emul_netbsd;
  318 #ifdef __HAVE_SYSCALL_INTERN
  319         (*p->p_emul->e_syscall_intern)(p);
  320 #endif
  321         strncpy(p->p_comm, "swapper", MAXCOMLEN);
  322 
  323         l->l_flag = L_INMEM;
  324         l->l_stat = LSONPROC;
  325         p->p_nrlwps = 1;
  326 
  327         callout_init(&l->l_tsleep_ch);
  328 
  329         /* Create credentials. */
  330         cred0.p_refcnt = 1;
  331         p->p_cred = &cred0;
  332         p->p_ucred = crget();
  333         p->p_ucred->cr_ngroups = 1;     /* group 0 */
  334 
  335         /* Create the file descriptor table. */
  336         finit();
  337         p->p_fd = &filedesc0.fd_fd;
  338         fdinit1(&filedesc0);
  339 
  340         /* Create the CWD info. */
  341         p->p_cwdi = &cwdi0;
  342         cwdi0.cwdi_cmask = cmask;
  343         cwdi0.cwdi_refcnt = 1;
  344 
  345         /* Create the limits structures. */
  346         p->p_limit = &limit0;
  347         for (i = 0; i < sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]); i++)
  348                 limit0.pl_rlimit[i].rlim_cur =
  349                     limit0.pl_rlimit[i].rlim_max = RLIM_INFINITY;
  350 
  351         limit0.pl_rlimit[RLIMIT_NOFILE].rlim_max = maxfiles;
  352         limit0.pl_rlimit[RLIMIT_NOFILE].rlim_cur =
  353             maxfiles < nofile ? maxfiles : nofile;
  354 
  355         limit0.pl_rlimit[RLIMIT_NPROC].rlim_max = maxproc;
  356         limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur =
  357             maxproc < maxuprc ? maxproc : maxuprc;
  358 
  359         lim = ptoa(uvmexp.free);
  360         limit0.pl_rlimit[RLIMIT_RSS].rlim_max = lim;
  361         limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_max = lim;
  362         limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = lim / 3;
  363         limit0.pl_corename = defcorename;
  364         limit0.p_refcnt = 1;
  365 
  366         /*
  367          * Initialize proc0's vmspace, which uses the kernel pmap.
  368          * All kernel processes (which never have user space mappings)
  369          * share proc0's vmspace, and thus, the kernel pmap.
  370          */
  371         uvmspace_init(&vmspace0, pmap_kernel(), round_page(VM_MIN_ADDRESS),
  372             trunc_page(VM_MAX_ADDRESS));
  373         p->p_vmspace = &vmspace0;
  374 
  375         l->l_addr = proc0paddr;                         /* XXX */
  376 
  377         p->p_stats = &pstat0;
  378 
  379         /*
  380          * Charge root for one process.
  381          */
  382         (void)chgproccnt(0, 1);
  383 
  384         rqinit();
  385 
  386         /* Configure virtual memory system, set vm rlimits. */
  387         uvm_init_limits(p);
  388 
  389         /* Initialize the file systems. */
  390 #if defined(NFSSERVER) || defined(NFS)
  391         nfs_init();                     /* initialize server/shared data */
  392 #endif
  393 #ifdef NVNODE_IMPLICIT
  394         /*
  395          * If maximum number of vnodes in namei vnode cache is not explicitly
  396          * defined in kernel config, adjust the number such as we use roughly
  397          * 1.0% of memory for vnode cache (but not less than NVNODE vnodes).
  398          */
  399         usevnodes = (ptoa((unsigned)physmem) / 100) / sizeof(struct vnode);
  400         if (usevnodes > desiredvnodes)
  401                 desiredvnodes = usevnodes;
  402 #endif
  403         vfsinit();
  404 
  405         /* Configure the system hardware.  This will enable interrupts. */
  406         configure();
  407 
  408         ubc_init();             /* must be after autoconfig */
  409 
  410         /* Lock the kernel on behalf of proc0. */
  411         KERNEL_PROC_LOCK(l);
  412 
  413 #ifdef SYSVSHM
  414         /* Initialize System V style shared memory. */
  415         shminit();
  416 #endif
  417 
  418 #ifdef SYSVSEM
  419         /* Initialize System V style semaphores. */
  420         seminit();
  421 #endif
  422 
  423 #ifdef SYSVMSG
  424         /* Initialize System V style message queues. */
  425         msginit();
  426 #endif
  427 
  428 #ifdef P1003_1B_SEMAPHORE
  429         /* Initialize posix semaphores */
  430         ksem_init();
  431 #endif
  432         /* Attach pseudo-devices. */
  433         for (pdev = pdevinit; pdev->pdev_attach != NULL; pdev++)
  434                 (*pdev->pdev_attach)(pdev->pdev_count);
  435 
  436 #ifdef  FAST_IPSEC
  437         /* Attach network crypto subsystem */
  438         ipsec_attach();
  439 #endif
  440 
  441         /*
  442          * Initialize protocols.  Block reception of incoming packets
  443          * until everything is ready.
  444          */
  445         s = splnet();
  446         ifinit();
  447         domaininit();
  448         if_attachdomain();
  449         splx(s);
  450 
  451 #ifdef GPROF
  452         /* Initialize kernel profiling. */
  453         kmstartup();
  454 #endif
  455 
  456         /* Initialize system accouting. */
  457         acct_init();
  458 
  459 #ifdef SYSTRACE
  460         systrace_init();
  461 #endif
  462         /*
  463          * Initialize signal-related data structures, and signal state
  464          * for proc0.
  465          */
  466         signal_init();
  467         p->p_sigacts = &sigacts0;
  468         siginit(p);
  469 
  470         /* Kick off timeout driven events by calling first time. */
  471         schedcpu(NULL);
  472 
  473         /*
  474          * Create process 1 (init(8)).  We do this now, as Unix has
  475          * historically had init be process 1, and changing this would
  476          * probably upset a lot of people.
  477          *
  478          * Note that process 1 won't immediately exec init(8), but will
  479          * wait for us to inform it that the root file system has been
  480          * mounted.
  481          */
  482         if (fork1(l, 0, SIGCHLD, NULL, 0, start_init, NULL, NULL, &initproc))
  483                 panic("fork init");
  484 
  485         /*
  486          * Create any kernel threads who's creation was deferred because
  487          * initproc had not yet been created.
  488          */
  489         kthread_run_deferred_queue();
  490 
  491         /*
  492          * Now that device driver threads have been created, wait for
  493          * them to finish any deferred autoconfiguration.  Note we don't
  494          * need to lock this semaphore, since we haven't booted any
  495          * secondary processors, yet.
  496          */
  497         while (config_pending)
  498                 (void) tsleep((void *)&config_pending, PWAIT, "cfpend", 0);
  499 
  500         /*
  501          * Finalize configuration now that all real devices have been
  502          * found.  This needs to be done before the root device is
  503          * selected, since finalization may create the root device.
  504          */
  505         config_finalize();
  506 
  507         /*
  508          * Now that autoconfiguration has completed, we can determine
  509          * the root and dump devices.
  510          */
  511         cpu_rootconf();
  512         cpu_dumpconf();
  513 
  514         /* Mount the root file system. */
  515         do {
  516                 domountroothook();
  517                 if ((error = vfs_mountroot())) {
  518                         printf("cannot mount root, error = %d\n", error);
  519                         boothowto |= RB_ASKNAME;
  520                         setroot(root_device,
  521                             (rootdev != NODEV) ? DISKPART(rootdev) : 0);
  522                 }
  523         } while (error != 0);
  524         mountroothook_destroy();
  525 
  526         CIRCLEQ_FIRST(&mountlist)->mnt_flag |= MNT_ROOTFS;
  527         CIRCLEQ_FIRST(&mountlist)->mnt_op->vfs_refcount++;
  528 
  529         /*
  530          * Get the vnode for '/'.  Set filedesc0.fd_fd.fd_cdir to
  531          * reference it.
  532          */
  533         if (VFS_ROOT(CIRCLEQ_FIRST(&mountlist), &rootvnode))
  534                 panic("cannot find root vnode");
  535         cwdi0.cwdi_cdir = rootvnode;
  536         VREF(cwdi0.cwdi_cdir);
  537         VOP_UNLOCK(rootvnode, 0);
  538         cwdi0.cwdi_rdir = NULL;
  539 
  540         /*
  541          * Now that root is mounted, we can fixup initproc's CWD
  542          * info.  All other processes are kthreads, which merely
  543          * share proc0's CWD info.
  544          */
  545         initproc->p_cwdi->cwdi_cdir = rootvnode;
  546         VREF(initproc->p_cwdi->cwdi_cdir);
  547         initproc->p_cwdi->cwdi_rdir = NULL;
  548 
  549         /*
  550          * Now can look at time, having had a chance to verify the time
  551          * from the file system.  Reset p->p_rtime as it may have been
  552          * munched in mi_switch() after the time got set.
  553          */
  554         proclist_lock_read();
  555         s = splsched();
  556         LIST_FOREACH(p, &allproc, p_list) {
  557                 p->p_stats->p_start = mono_time = boottime = time;
  558                 LIST_FOREACH(l, &p->p_lwps, l_sibling) {
  559                         if (l->l_cpu != NULL)
  560                                 l->l_cpu->ci_schedstate.spc_runtime = time;
  561                 }
  562                 p->p_rtime.tv_sec = p->p_rtime.tv_usec = 0;
  563         }
  564         splx(s);
  565         proclist_unlock_read();
  566 
  567         /* Create the pageout daemon kernel thread. */
  568         uvm_swap_init();
  569         if (kthread_create1(uvm_pageout, NULL, NULL, "pagedaemon"))
  570                 panic("fork pagedaemon");
  571 
  572         /* Create the filesystem syncer kernel thread. */
  573         if (kthread_create1(sched_sync, NULL, NULL, "ioflush"))
  574                 panic("fork syncer");
  575 
  576         /* Create the aiodone daemon kernel thread. */
  577         if (kthread_create1(uvm_aiodone_daemon, NULL, &uvm.aiodoned_proc,
  578             "aiodoned"))
  579                 panic("fork aiodoned");
  580 
  581 #if defined(MULTIPROCESSOR)
  582         /* Boot the secondary processors. */
  583         cpu_boot_secondary_processors();
  584 #endif
  585 
  586         /* Initialize exec structures */
  587         exec_init(1);
  588 
  589 #ifndef PIPE_SOCKETPAIR
  590         /* Initialize pipe structures */
  591         pipe_init();
  592 #endif
  593 
  594         /*
  595          * Okay, now we can let init(8) exec!  It's off to userland!
  596          */
  597         start_init_exec = 1;
  598         wakeup((void *)&start_init_exec);
  599 
  600         /* The scheduler is an infinite loop. */
  601         uvm_scheduler();
  602         /* NOTREACHED */
  603 }
  604 
  605 static void
  606 check_console(struct proc *p)
  607 {
  608         struct nameidata nd;
  609         int error;
  610 
  611         NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, "/dev/console", p);
  612         error = namei(&nd);
  613         if (error == 0)
  614                 vrele(nd.ni_vp);
  615         else if (error == ENOENT)
  616                 printf("warning: no /dev/console\n");
  617         else
  618                 printf("warning: lookup /dev/console: error %d\n", error);
  619 }
  620 
  621 /*
  622  * List of paths to try when searching for "init".
  623  */
  624 static const char *initpaths[] = {
  625         "/sbin/init",
  626         "/sbin/oinit",
  627         "/sbin/init.bak",
  628         NULL,
  629 };
  630 
  631 /*
  632  * Start the initial user process; try exec'ing each pathname in "initpaths".
  633  * The program is invoked with one argument containing the boot flags.
  634  */
  635 static void
  636 start_init(void *arg)
  637 {
  638         struct lwp *l = arg;
  639         struct proc *p = l->l_proc;
  640         vaddr_t addr;
  641         struct sys_execve_args /* {
  642                 syscallarg(const char *) path;
  643                 syscallarg(char * const *) argp;
  644                 syscallarg(char * const *) envp;
  645         } */ args;
  646         int options, i, error;
  647         register_t retval[2];
  648         char flags[4], *flagsp;
  649         const char *path, *slash;
  650         char *ucp, **uap, *arg0, *arg1 = NULL;
  651         char ipath[129];
  652         int ipx, len;
  653 
  654         /*
  655          * Now in process 1.
  656          */
  657         strncpy(p->p_comm, "init", MAXCOMLEN);
  658 
  659         /*
  660          * Wait for main() to tell us that it's safe to exec.
  661          */
  662         while (start_init_exec == 0)
  663                 (void) tsleep((void *)&start_init_exec, PWAIT, "initexec", 0);
  664 
  665         /*
  666          * This is not the right way to do this.  We really should
  667          * hand-craft a descriptor onto /dev/console to hand to init,
  668          * but that's a _lot_ more work, and the benefit from this easy
  669          * hack makes up for the "good is the enemy of the best" effect.
  670          */
  671         check_console(p);
  672 
  673         /*
  674          * Need just enough stack to hold the faked-up "execve()" arguments.
  675          */
  676         addr = (vaddr_t)STACK_ALLOC(USRSTACK, PAGE_SIZE);
  677         if (uvm_map(&p->p_vmspace->vm_map, &addr, PAGE_SIZE,
  678                     NULL, UVM_UNKNOWN_OFFSET, 0,
  679                     UVM_MAPFLAG(UVM_PROT_ALL, UVM_PROT_ALL, UVM_INH_COPY,
  680                     UVM_ADV_NORMAL,
  681                     UVM_FLAG_FIXED|UVM_FLAG_OVERLAY|UVM_FLAG_COPYONW)) != 0)
  682                 panic("init: couldn't allocate argument space");
  683         p->p_vmspace->vm_maxsaddr = (caddr_t)STACK_MAX(addr, PAGE_SIZE);
  684 
  685         ipx = 0;
  686         while (1) {
  687                 if (boothowto & RB_ASKNAME) {
  688                         printf("init path");
  689                         if (initpaths[ipx])
  690                                 printf(" (default %s)", initpaths[ipx]);
  691                         printf(": ");
  692                         len = cngetsn(ipath, sizeof(ipath)-1);
  693                         if (len == 0) {
  694                                 if (initpaths[ipx])
  695                                         path = initpaths[ipx++];
  696                                 else
  697                                         continue;
  698                         } else {
  699                                 ipath[len] = '\0';
  700                                 path = ipath;
  701                         }
  702                 } else {
  703                         if ((path = initpaths[ipx++]) == NULL)
  704                                 break;
  705                 }
  706 
  707                 ucp = (char *)USRSTACK;
  708 
  709                 /*
  710                  * Construct the boot flag argument.
  711                  */
  712                 flagsp = flags;
  713                 *flagsp++ = '-';
  714                 options = 0;
  715 
  716                 if (boothowto & RB_SINGLE) {
  717                         *flagsp++ = 's';
  718                         options = 1;
  719                 }
  720 #ifdef notyet
  721                 if (boothowto & RB_FASTBOOT) {
  722                         *flagsp++ = 'f';
  723                         options = 1;
  724                 }
  725 #endif
  726 
  727                 /*
  728                  * Move out the flags (arg 1), if necessary.
  729                  */
  730                 if (options != 0) {
  731                         *flagsp++ = '\0';
  732                         i = flagsp - flags;
  733 #ifdef DEBUG
  734                         printf("init: copying out flags `%s' %d\n", flags, i);
  735 #endif
  736                         arg1 = STACK_ALLOC(ucp, i);
  737                         ucp = STACK_MAX(arg1, i);
  738                         (void)copyout((caddr_t)flags, arg1, i);
  739                 }
  740 
  741                 /*
  742                  * Move out the file name (also arg 0).
  743                  */
  744                 i = strlen(path) + 1;
  745 #ifdef DEBUG
  746                 printf("init: copying out path `%s' %d\n", path, i);
  747 #else
  748                 if (boothowto & RB_ASKNAME || path != initpaths[0])
  749                         printf("init: trying %s\n", path);
  750 #endif
  751                 arg0 = STACK_ALLOC(ucp, i);
  752                 ucp = STACK_MAX(arg0, i);
  753                 (void)copyout((caddr_t)path, arg0, i);
  754 
  755                 /*
  756                  * Move out the arg pointers.
  757                  */
  758                 ucp = (caddr_t)STACK_ALIGN(ucp, ALIGNBYTES);
  759                 uap = (char **)STACK_ALLOC(ucp, sizeof(char *) * 3);
  760                 SCARG(&args, path) = arg0;
  761                 SCARG(&args, argp) = uap;
  762                 SCARG(&args, envp) = NULL;
  763                 slash = strrchr(path, '/');
  764                 if (slash)
  765                         (void)suword((caddr_t)uap++,
  766                             (long)arg0 + (slash + 1 - path));
  767                 else
  768                         (void)suword((caddr_t)uap++, (long)arg0);
  769                 if (options != 0)
  770                         (void)suword((caddr_t)uap++, (long)arg1);
  771                 (void)suword((caddr_t)uap++, 0);        /* terminator */
  772 
  773                 /*
  774                  * Now try to exec the program.  If can't for any reason
  775                  * other than it doesn't exist, complain.
  776                  */
  777                 error = sys_execve(LIST_FIRST(&p->p_lwps), &args, retval);
  778                 if (error == 0 || error == EJUSTRETURN) {
  779                         KERNEL_PROC_UNLOCK(l);
  780                         return;
  781                 }
  782                 printf("exec %s: error %d\n", path, error);
  783         }
  784         printf("init: not found\n");
  785         panic("no init");
  786 }

Cache object: c1986f83f6a9f389214e05b50bdd6782


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.