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.283 2006/11/26 16:22:36 elad 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.283 2006/11/26 16:22:36 elad Exp $");
   75 
   76 #include "opt_ipsec.h"
   77 #include "opt_kcont.h"
   78 #include "opt_multiprocessor.h"
   79 #include "opt_ntp.h"
   80 #include "opt_pipe.h"
   81 #include "opt_posix.h"
   82 #include "opt_syscall_debug.h"
   83 #include "opt_sysv.h"
   84 #include "opt_fileassoc.h"
   85 #include "opt_pax.h"
   86 
   87 #include "rnd.h"
   88 #include "veriexec.h"
   89 
   90 #include <sys/param.h>
   91 #include <sys/acct.h>
   92 #include <sys/filedesc.h>
   93 #include <sys/file.h>
   94 #include <sys/errno.h>
   95 #include <sys/callout.h>
   96 #include <sys/kernel.h>
   97 #include <sys/kcont.h>
   98 #include <sys/kmem.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/exec.h>
  112 #include <sys/socketvar.h>
  113 #include <sys/protosw.h>
  114 #include <sys/reboot.h>
  115 #include <sys/user.h>
  116 #include <sys/sysctl.h>
  117 #include <sys/event.h>
  118 #include <sys/mbuf.h>
  119 #ifdef FAST_IPSEC
  120 #include <netipsec/ipsec.h>
  121 #endif
  122 #ifdef SYSVSHM
  123 #include <sys/shm.h>
  124 #endif
  125 #ifdef SYSVSEM
  126 #include <sys/sem.h>
  127 #endif
  128 #ifdef SYSVMSG
  129 #include <sys/msg.h>
  130 #endif
  131 #ifdef P1003_1B_SEMAPHORE
  132 #include <sys/ksem.h>
  133 #endif
  134 #include <sys/domain.h>
  135 #include <sys/namei.h>
  136 #if NRND > 0
  137 #include <sys/rnd.h>
  138 #endif
  139 #ifndef PIPE_SOCKETPAIR
  140 #include <sys/pipe.h>
  141 #endif
  142 #ifdef LKM
  143 #include <sys/lkm.h>
  144 #endif
  145 #if NVERIEXEC > 0
  146 #include <sys/verified_exec.h>
  147 #endif /* NVERIEXEC > 0 */
  148 #include <sys/kauth.h>
  149 #include <net80211/ieee80211_netbsd.h>
  150 
  151 #include <sys/syscall.h>
  152 #include <sys/sa.h>
  153 #include <sys/syscallargs.h>
  154 
  155 #ifdef FILEASSOC
  156 #include <sys/fileassoc.h>
  157 #endif /* FILEASSOC */
  158 
  159 #if defined(PAX_MPROTECT) || defined(PAX_SEGVGUARD)
  160 #include <sys/pax.h>
  161 #endif /* PAX_MPROTECT || PAX_SEGVGUARD */
  162 #include <ufs/ufs/quota.h>
  163 
  164 #include <miscfs/genfs/genfs.h>
  165 #include <miscfs/syncfs/syncfs.h>
  166 
  167 #include <machine/cpu.h>
  168 
  169 #include <uvm/uvm.h>
  170 
  171 #include <dev/cons.h>
  172 
  173 #include <net/if.h>
  174 #include <net/raw_cb.h>
  175 
  176 #include <secmodel/secmodel.h>
  177 
  178 extern struct proc proc0;
  179 extern struct lwp lwp0;
  180 extern struct cwdinfo cwdi0;
  181 
  182 #ifndef curlwp
  183 struct  lwp *curlwp = &lwp0;
  184 #endif
  185 struct  proc *initproc;
  186 
  187 struct  vnode *rootvp, *swapdev_vp;
  188 int     boothowto;
  189 int     cold = 1;                       /* still working on startup */
  190 struct timeval boottime;                /* time at system startup - will only follow settime deltas */
  191 time_t  rootfstime;                     /* recorded root fs time, if known */
  192 
  193 volatile int start_init_exec;           /* semaphore for start_init() */
  194 
  195 static void check_console(struct lwp *l);
  196 static void start_init(void *);
  197 void main(void);
  198 
  199 #if defined(__SSP__) || defined(__SSP_ALL__)
  200 long __stack_chk_guard[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  201 void __stack_chk_fail(void);
  202 
  203 void
  204 __stack_chk_fail(void)
  205 {
  206         panic("stack overflow detected; terminated");
  207 }
  208 #endif
  209 
  210 /*
  211  * System startup; initialize the world, create process 0, mount root
  212  * filesystem, and fork to create init and pagedaemon.  Most of the
  213  * hard work is done in the lower-level initialization routines including
  214  * startup(), which does memory initialization and autoconfiguration.
  215  */
  216 void
  217 main(void)
  218 {
  219 #ifdef __HAVE_TIMECOUNTER
  220         struct timeval time;
  221 #endif
  222         struct lwp *l;
  223         struct proc *p;
  224         struct pdevinit *pdev;
  225         int s, error;
  226         extern struct pdevinit pdevinit[];
  227         extern void schedcpu(void *);
  228 #ifdef NVNODE_IMPLICIT
  229         int usevnodes;
  230 #endif
  231 
  232         /*
  233          * Initialize the current LWP pointer (curlwp) before
  234          * any possible traps/probes to simplify trap processing.
  235          */
  236         l = &lwp0;
  237         curlwp = l;
  238         l->l_cpu = curcpu();
  239         l->l_proc = &proc0;
  240         l->l_lid = 1;
  241 
  242         /*
  243          * Attempt to find console and initialize
  244          * in case of early panic or other messages.
  245          */
  246         consinit();
  247 
  248         KERNEL_LOCK_INIT();
  249 
  250         uvm_init();
  251 
  252         kmem_init();
  253 
  254         /* Do machine-dependent initialization. */
  255         cpu_startup();
  256 
  257         /* Initialize callouts. */
  258         callout_startup();
  259 
  260         /* Initialize the buffer cache */
  261         bufinit();
  262 
  263         /*
  264          * Initialize mbuf's.  Do this now because we might attempt to
  265          * allocate mbufs or mbuf clusters during autoconfiguration.
  266          */
  267         mbinit();
  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 #if NRND > 0
  282         rnd_init();             /* initialize RNG */
  283 #endif
  284         /* Initialize the sysctl subsystem. */
  285         sysctl_init();
  286 
  287         /* Initialize process and pgrp structures. */
  288         procinit();
  289         lwpinit();
  290 
  291         /* Initialize signal-related data structures. */
  292         signal_init();
  293 
  294         /* Create process 0 (the swapper). */
  295         proc0_init();
  296 
  297         /*
  298          * Charge root for one process.
  299          */
  300         (void)chgproccnt(0, 1);
  301 
  302         rqinit();
  303 
  304         /* Initialize the file systems. */
  305 #ifdef NVNODE_IMPLICIT
  306         /*
  307          * If maximum number of vnodes in namei vnode cache is not explicitly
  308          * defined in kernel config, adjust the number such as we use roughly
  309          * 1.0% of memory for vnode cache (but not less than NVNODE vnodes).
  310          */
  311         usevnodes = (ptoa((unsigned)physmem) / 100) / sizeof(struct vnode);
  312         if (usevnodes > desiredvnodes)
  313                 desiredvnodes = usevnodes;
  314 #endif
  315         vfsinit();
  316 
  317 
  318 #ifdef __HAVE_TIMECOUNTER
  319         inittimecounter();
  320         ntp_init();
  321 #endif /* __HAVE_TIMECOUNTER */
  322 
  323         /* Initialize kauth. */
  324         kauth_init();
  325 
  326         /* Configure the system hardware.  This will enable interrupts. */
  327         configure();
  328 
  329 #if defined(__SSP__) || defined(__SSP_ALL__)
  330         {
  331 #ifdef DIAGNOSTIC
  332                 printf("Initializing SSP:");
  333 #endif
  334                 /*
  335                  * We initialize ssp here carefully:
  336                  *      1. after we got some entropy
  337                  *      2. without calling a function
  338                  */
  339                 size_t i;
  340                 long guard[__arraycount(__stack_chk_guard)];
  341 
  342                 arc4randbytes(guard, sizeof(guard));
  343                 for (i = 0; i < __arraycount(guard); i++)
  344                         __stack_chk_guard[i] = guard[i];
  345 #ifdef DIAGNOSTIC
  346                 for (i = 0; i < __arraycount(guard); i++)
  347                         printf("%lx ", guard[i]);
  348                 printf("\n");
  349 #endif
  350         }
  351 #endif
  352         ubc_init();             /* must be after autoconfig */
  353 
  354         /* Lock the kernel on behalf of proc0. */
  355         KERNEL_PROC_LOCK(l);
  356 
  357 #ifdef SYSVSHM
  358         /* Initialize System V style shared memory. */
  359         shminit();
  360 #endif
  361 
  362 #ifdef SYSVSEM
  363         /* Initialize System V style semaphores. */
  364         seminit();
  365 #endif
  366 
  367 #ifdef SYSVMSG
  368         /* Initialize System V style message queues. */
  369         msginit();
  370 #endif
  371 
  372 #ifdef P1003_1B_SEMAPHORE
  373         /* Initialize posix semaphores */
  374         ksem_init();
  375 #endif
  376 
  377         /* Initialize default security model. */
  378         secmodel_start();
  379 
  380 #ifdef FILEASSOC
  381         fileassoc_init();
  382 #endif /* FILEASSOC */
  383 
  384 #if NVERIEXEC > 0
  385         /*
  386          * Initialise the Veriexec subsystem.
  387          */
  388         veriexec_init();
  389 #endif /* NVERIEXEC > 0 */
  390 
  391 #if defined(PAX_MPROTECT) || defined(PAX_SEGVGUARD)
  392         pax_init();
  393 #endif /* PAX_MPROTECT || PAX_SEGVGUARD */
  394 
  395         /* Attach pseudo-devices. */
  396         for (pdev = pdevinit; pdev->pdev_attach != NULL; pdev++)
  397                 (*pdev->pdev_attach)(pdev->pdev_count);
  398 
  399 #ifdef  FAST_IPSEC
  400         /* Attach network crypto subsystem */
  401         ipsec_attach();
  402 #endif
  403 
  404         /*
  405          * Initialize protocols.  Block reception of incoming packets
  406          * until everything is ready.
  407          */
  408         s = splnet();
  409         ifinit();
  410         domaininit();
  411         if_attachdomain();
  412         splx(s);
  413 
  414 #ifdef GPROF
  415         /* Initialize kernel profiling. */
  416         kmstartup();
  417 #endif
  418 
  419         /* Initialize system accouting. */
  420         acct_init();
  421 
  422         /* Kick off timeout driven events by calling first time. */
  423         schedcpu(NULL);
  424 
  425         /*
  426          * Create process 1 (init(8)).  We do this now, as Unix has
  427          * historically had init be process 1, and changing this would
  428          * probably upset a lot of people.
  429          *
  430          * Note that process 1 won't immediately exec init(8), but will
  431          * wait for us to inform it that the root file system has been
  432          * mounted.
  433          */
  434         if (fork1(l, 0, SIGCHLD, NULL, 0, start_init, NULL, NULL, &initproc))
  435                 panic("fork init");
  436 
  437         /*
  438          * Create any kernel threads who's creation was deferred because
  439          * initproc had not yet been created.
  440          */
  441         kthread_run_deferred_queue();
  442 
  443         /*
  444          * Now that device driver threads have been created, wait for
  445          * them to finish any deferred autoconfiguration.  Note we don't
  446          * need to lock this semaphore, since we haven't booted any
  447          * secondary processors, yet.
  448          */
  449         while (config_pending)
  450                 (void) tsleep(&config_pending, PWAIT, "cfpend", 0);
  451 
  452         /*
  453          * Finalize configuration now that all real devices have been
  454          * found.  This needs to be done before the root device is
  455          * selected, since finalization may create the root device.
  456          */
  457         config_finalize();
  458 
  459         /*
  460          * Now that autoconfiguration has completed, we can determine
  461          * the root and dump devices.
  462          */
  463         cpu_rootconf();
  464         cpu_dumpconf();
  465 
  466         /* Mount the root file system. */
  467         do {
  468                 domountroothook();
  469                 if ((error = vfs_mountroot())) {
  470                         printf("cannot mount root, error = %d\n", error);
  471                         boothowto |= RB_ASKNAME;
  472                         setroot(root_device,
  473                             (rootdev != NODEV) ? DISKPART(rootdev) : 0);
  474                 }
  475         } while (error != 0);
  476         mountroothook_destroy();
  477 
  478         /*
  479          * Initialise the time-of-day clock, passing the time recorded
  480          * in the root filesystem (if any) for use by systems that
  481          * don't have a non-volatile time-of-day device.
  482          */
  483         inittodr(rootfstime);
  484 
  485         CIRCLEQ_FIRST(&mountlist)->mnt_flag |= MNT_ROOTFS;
  486         CIRCLEQ_FIRST(&mountlist)->mnt_op->vfs_refcount++;
  487 
  488         /*
  489          * Get the vnode for '/'.  Set filedesc0.fd_fd.fd_cdir to
  490          * reference it.
  491          */
  492         error = VFS_ROOT(CIRCLEQ_FIRST(&mountlist), &rootvnode);
  493         if (error)
  494                 panic("cannot find root vnode, error=%d", error);
  495         cwdi0.cwdi_cdir = rootvnode;
  496         VREF(cwdi0.cwdi_cdir);
  497         VOP_UNLOCK(rootvnode, 0);
  498         cwdi0.cwdi_rdir = NULL;
  499 
  500         /*
  501          * Now that root is mounted, we can fixup initproc's CWD
  502          * info.  All other processes are kthreads, which merely
  503          * share proc0's CWD info.
  504          */
  505         initproc->p_cwdi->cwdi_cdir = rootvnode;
  506         VREF(initproc->p_cwdi->cwdi_cdir);
  507         initproc->p_cwdi->cwdi_rdir = NULL;
  508 
  509         /*
  510          * Now can look at time, having had a chance to verify the time
  511          * from the file system.  Reset p->p_rtime as it may have been
  512          * munched in mi_switch() after the time got set.
  513          */
  514         proclist_lock_read();
  515         s = splsched();
  516 #ifdef __HAVE_TIMECOUNTER
  517         getmicrotime(&time);
  518 #else
  519         mono_time = time;
  520 #endif
  521         boottime = time;
  522         LIST_FOREACH(p, &allproc, p_list) {
  523                 KASSERT((p->p_flag & P_MARKER) == 0);
  524                 p->p_stats->p_start = time;
  525                 LIST_FOREACH(l, &p->p_lwps, l_sibling) {
  526                         if (l->l_cpu != NULL)
  527                                 l->l_cpu->ci_schedstate.spc_runtime = time;
  528                 }
  529                 p->p_rtime.tv_sec = p->p_rtime.tv_usec = 0;
  530         }
  531         splx(s);
  532         proclist_unlock_read();
  533 
  534         /* Create the pageout daemon kernel thread. */
  535         uvm_swap_init();
  536         if (kthread_create1(uvm_pageout, NULL, NULL, "pagedaemon"))
  537                 panic("fork pagedaemon");
  538 
  539         /* Create the filesystem syncer kernel thread. */
  540         if (kthread_create1(sched_sync, NULL, NULL, "ioflush"))
  541                 panic("fork syncer");
  542 
  543         /* Create the aiodone daemon kernel thread. */
  544         if (kthread_create1(uvm_aiodone_daemon, NULL, &uvm.aiodoned_proc,
  545             "aiodoned"))
  546                 panic("fork aiodoned");
  547 
  548 #if defined(MULTIPROCESSOR)
  549         /* Boot the secondary processors. */
  550         cpu_boot_secondary_processors();
  551 #endif
  552 
  553         /* Initialize exec structures */
  554         exec_init(1);
  555 
  556         /*
  557          * Okay, now we can let init(8) exec!  It's off to userland!
  558          */
  559         start_init_exec = 1;
  560         wakeup(&start_init_exec);
  561 
  562         /* The scheduler is an infinite loop. */
  563         uvm_scheduler();
  564         /* NOTREACHED */
  565 }
  566 
  567 void
  568 setrootfstime(time_t t)
  569 {
  570         rootfstime = t;
  571 }
  572 
  573 static void
  574 check_console(struct lwp *l)
  575 {
  576         struct nameidata nd;
  577         int error;
  578 
  579         NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, "/dev/console", l);
  580         error = namei(&nd);
  581         if (error == 0)
  582                 vrele(nd.ni_vp);
  583         else if (error == ENOENT)
  584                 printf("warning: no /dev/console\n");
  585         else
  586                 printf("warning: lookup /dev/console: error %d\n", error);
  587 }
  588 
  589 /*
  590  * List of paths to try when searching for "init".
  591  */
  592 static const char *initpaths[] = {
  593         "/sbin/init",
  594         "/sbin/oinit",
  595         "/sbin/init.bak",
  596         NULL,
  597 };
  598 
  599 /*
  600  * Start the initial user process; try exec'ing each pathname in "initpaths".
  601  * The program is invoked with one argument containing the boot flags.
  602  */
  603 static void
  604 start_init(void *arg)
  605 {
  606         struct lwp *l = arg;
  607         struct proc *p = l->l_proc;
  608         vaddr_t addr;
  609         struct sys_execve_args /* {
  610                 syscallarg(const char *) path;
  611                 syscallarg(char * const *) argp;
  612                 syscallarg(char * const *) envp;
  613         } */ args;
  614         int options, i, error;
  615         register_t retval[2];
  616         char flags[4], *flagsp;
  617         const char *path, *slash;
  618         char *ucp, **uap, *arg0, *arg1 = NULL;
  619         char ipath[129];
  620         int ipx, len;
  621 
  622         /*
  623          * Now in process 1.
  624          */
  625         strncpy(p->p_comm, "init", MAXCOMLEN);
  626 
  627         /*
  628          * Wait for main() to tell us that it's safe to exec.
  629          */
  630         while (start_init_exec == 0)
  631                 (void) tsleep(&start_init_exec, PWAIT, "initexec", 0);
  632 
  633         /*
  634          * This is not the right way to do this.  We really should
  635          * hand-craft a descriptor onto /dev/console to hand to init,
  636          * but that's a _lot_ more work, and the benefit from this easy
  637          * hack makes up for the "good is the enemy of the best" effect.
  638          */
  639         check_console(l);
  640 
  641         /*
  642          * Need just enough stack to hold the faked-up "execve()" arguments.
  643          */
  644         addr = (vaddr_t)STACK_ALLOC(USRSTACK, PAGE_SIZE);
  645         if (uvm_map(&p->p_vmspace->vm_map, &addr, PAGE_SIZE,
  646                     NULL, UVM_UNKNOWN_OFFSET, 0,
  647                     UVM_MAPFLAG(UVM_PROT_ALL, UVM_PROT_ALL, UVM_INH_COPY,
  648                     UVM_ADV_NORMAL,
  649                     UVM_FLAG_FIXED|UVM_FLAG_OVERLAY|UVM_FLAG_COPYONW)) != 0)
  650                 panic("init: couldn't allocate argument space");
  651         p->p_vmspace->vm_maxsaddr = (caddr_t)STACK_MAX(addr, PAGE_SIZE);
  652 
  653         ipx = 0;
  654         while (1) {
  655                 if (boothowto & RB_ASKNAME) {
  656                         printf("init path");
  657                         if (initpaths[ipx])
  658                                 printf(" (default %s)", initpaths[ipx]);
  659                         printf(": ");
  660                         len = cngetsn(ipath, sizeof(ipath)-1);
  661                         if (len == 0) {
  662                                 if (initpaths[ipx])
  663                                         path = initpaths[ipx++];
  664                                 else
  665                                         continue;
  666                         } else {
  667                                 ipath[len] = '\0';
  668                                 path = ipath;
  669                         }
  670                 } else {
  671                         if ((path = initpaths[ipx++]) == NULL)
  672                                 break;
  673                 }
  674 
  675                 ucp = (char *)USRSTACK;
  676 
  677                 /*
  678                  * Construct the boot flag argument.
  679                  */
  680                 flagsp = flags;
  681                 *flagsp++ = '-';
  682                 options = 0;
  683 
  684                 if (boothowto & RB_SINGLE) {
  685                         *flagsp++ = 's';
  686                         options = 1;
  687                 }
  688 #ifdef notyet
  689                 if (boothowto & RB_FASTBOOT) {
  690                         *flagsp++ = 'f';
  691                         options = 1;
  692                 }
  693 #endif
  694 
  695                 /*
  696                  * Move out the flags (arg 1), if necessary.
  697                  */
  698                 if (options != 0) {
  699                         *flagsp++ = '\0';
  700                         i = flagsp - flags;
  701 #ifdef DEBUG
  702                         printf("init: copying out flags `%s' %d\n", flags, i);
  703 #endif
  704                         arg1 = STACK_ALLOC(ucp, i);
  705                         ucp = STACK_MAX(arg1, i);
  706                         (void)copyout((caddr_t)flags, arg1, i);
  707                 }
  708 
  709                 /*
  710                  * Move out the file name (also arg 0).
  711                  */
  712                 i = strlen(path) + 1;
  713 #ifdef DEBUG
  714                 printf("init: copying out path `%s' %d\n", path, i);
  715 #else
  716                 if (boothowto & RB_ASKNAME || path != initpaths[0])
  717                         printf("init: trying %s\n", path);
  718 #endif
  719                 arg0 = STACK_ALLOC(ucp, i);
  720                 ucp = STACK_MAX(arg0, i);
  721                 (void)copyout(path, arg0, i);
  722 
  723                 /*
  724                  * Move out the arg pointers.
  725                  */
  726                 ucp = (caddr_t)STACK_ALIGN(ucp, ALIGNBYTES);
  727                 uap = (char **)STACK_ALLOC(ucp, sizeof(char *) * 3);
  728                 SCARG(&args, path) = arg0;
  729                 SCARG(&args, argp) = uap;
  730                 SCARG(&args, envp) = NULL;
  731                 slash = strrchr(path, '/');
  732                 if (slash)
  733                         (void)suword((caddr_t)uap++,
  734                             (long)arg0 + (slash + 1 - path));
  735                 else
  736                         (void)suword((caddr_t)uap++, (long)arg0);
  737                 if (options != 0)
  738                         (void)suword((caddr_t)uap++, (long)arg1);
  739                 (void)suword((caddr_t)uap++, 0);        /* terminator */
  740 
  741                 /*
  742                  * Now try to exec the program.  If can't for any reason
  743                  * other than it doesn't exist, complain.
  744                  */
  745                 error = sys_execve(l, &args, retval);
  746                 if (error == 0 || error == EJUSTRETURN) {
  747                         KERNEL_PROC_UNLOCK(l);
  748                         return;
  749                 }
  750                 printf("exec %s: error %d\n", path, error);
  751         }
  752         printf("init: not found\n");
  753         panic("no init");
  754 }

Cache object: 4ce4fee73e8dbbe989121a7be329b1b3


[ 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.