Line data Source code
1 : /* $OpenBSD: init_main.c,v 1.281 2018/09/10 16:18:34 sashan Exp $ */
2 : /* $NetBSD: init_main.c,v 1.84.4.1 1996/06/02 09:08:06 mrg Exp $ */
3 :
4 : /*
5 : * Copyright (c) 1995 Christopher G. Demetriou. All rights reserved.
6 : * Copyright (c) 1982, 1986, 1989, 1991, 1992, 1993
7 : * The Regents of the University of California. All rights reserved.
8 : * (c) UNIX System Laboratories, Inc.
9 : * All or some portions of this file are derived from material licensed
10 : * to the University of California by American Telephone and Telegraph
11 : * Co. or Unix System Laboratories, Inc. and are reproduced herein with
12 : * the permission of UNIX System Laboratories, Inc.
13 : *
14 : * Redistribution and use in source and binary forms, with or without
15 : * modification, are permitted provided that the following conditions
16 : * are met:
17 : * 1. Redistributions of source code must retain the above copyright
18 : * notice, this list of conditions and the following disclaimer.
19 : * 2. Redistributions in binary form must reproduce the above copyright
20 : * notice, this list of conditions and the following disclaimer in the
21 : * documentation and/or other materials provided with the distribution.
22 : * 3. Neither the name of the University nor the names of its contributors
23 : * may be used to endorse or promote products derived from this software
24 : * without specific prior written permission.
25 : *
26 : * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 : * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 : * SUCH DAMAGE.
37 : *
38 : * @(#)init_main.c 8.9 (Berkeley) 1/21/94
39 : */
40 :
41 : #include <sys/param.h>
42 : #include <sys/filedesc.h>
43 : #include <sys/file.h>
44 : #include <sys/errno.h>
45 : #include <sys/exec.h>
46 : #include <sys/kernel.h>
47 : #include <sys/kthread.h>
48 : #include <sys/mount.h>
49 : #include <sys/proc.h>
50 : #include <sys/resourcevar.h>
51 : #include <sys/signalvar.h>
52 : #include <sys/systm.h>
53 : #include <sys/namei.h>
54 : #include <sys/vnode.h>
55 : #include <sys/tty.h>
56 : #include <sys/conf.h>
57 : #include <sys/buf.h>
58 : #include <sys/device.h>
59 : #include <sys/socketvar.h>
60 : #include <sys/lockf.h>
61 : #include <sys/protosw.h>
62 : #include <sys/reboot.h>
63 : #include <sys/user.h>
64 : #ifdef SYSVSHM
65 : #include <sys/shm.h>
66 : #endif
67 : #ifdef SYSVSEM
68 : #include <sys/sem.h>
69 : #endif
70 : #ifdef SYSVMSG
71 : #include <sys/msg.h>
72 : #endif
73 : #include <sys/domain.h>
74 : #include <sys/msgbuf.h>
75 : #include <sys/mbuf.h>
76 : #include <sys/pipe.h>
77 : #include <sys/task.h>
78 : #include <sys/witness.h>
79 :
80 : #include <sys/syscall.h>
81 : #include <sys/syscallargs.h>
82 :
83 : #include <uvm/uvm_extern.h>
84 :
85 : #include <dev/rndvar.h>
86 :
87 : #include <ufs/ufs/quota.h>
88 :
89 : #include <net/if.h>
90 : #include <net/rtable.h>
91 : #include <net/netisr.h>
92 :
93 : #if defined(CRYPTO)
94 : #include <crypto/cryptodev.h>
95 : #include <crypto/cryptosoft.h>
96 : #endif
97 :
98 : #if defined(NFSSERVER) || defined(NFSCLIENT)
99 : extern void nfs_init(void);
100 : #endif
101 :
102 : #include "mpath.h"
103 : #include "vscsi.h"
104 : #include "softraid.h"
105 :
106 : const char copyright[] =
107 : "Copyright (c) 1982, 1986, 1989, 1991, 1993\n"
108 : "\tThe Regents of the University of California. All rights reserved.\n"
109 : "Copyright (c) 1995-2018 OpenBSD. All rights reserved. https://www.OpenBSD.org\n";
110 :
111 : /* Components of the first process -- never freed. */
112 : struct session session0;
113 : struct pgrp pgrp0;
114 : struct proc proc0;
115 : struct process process0;
116 : struct plimit limit0;
117 : struct vmspace vmspace0;
118 : struct sigacts sigacts0;
119 : struct process *initprocess;
120 : struct proc *reaperproc;
121 :
122 : extern struct user *proc0paddr;
123 :
124 : struct vnode *rootvp, *swapdev_vp;
125 : int boothowto;
126 : struct timespec boottime;
127 : int db_active = 0;
128 : int ncpus = 1;
129 : int ncpusfound = 1; /* number of cpus we find */
130 : volatile int start_init_exec; /* semaphore for start_init() */
131 :
132 : #if !defined(NO_PROPOLICE)
133 : long __guard_local __attribute__((section(".openbsd.randomdata")));
134 : #endif
135 :
136 : /* XXX return int so gcc -Werror won't complain */
137 : int main(void *);
138 : void check_console(struct proc *);
139 : void start_init(void *);
140 : void crypto_init(void);
141 : void db_ctf_init(void);
142 : void prof_init(void);
143 : void init_exec(void);
144 : void kqueue_init(void);
145 : void futex_init(void);
146 : void taskq_init(void);
147 : void timeout_proc_init(void);
148 : void pool_gc_pages(void *);
149 : void percpu_init(void);
150 :
151 : extern char sigcode[], esigcode[], sigcoderet[];
152 : #ifdef SYSCALL_DEBUG
153 : extern char *syscallnames[];
154 : #endif
155 :
156 : struct emul emul_native = {
157 : "native",
158 : NULL,
159 : SYS_syscall,
160 : SYS_MAXSYSCALL,
161 : sysent,
162 : #ifdef SYSCALL_DEBUG
163 : syscallnames,
164 : #else
165 : NULL,
166 : #endif
167 : 0,
168 : copyargs,
169 : setregs,
170 : NULL, /* fixup */
171 : NULL, /* coredump */
172 : sigcode,
173 : esigcode,
174 : sigcoderet
175 : };
176 :
177 : #ifdef DIAGNOSTIC
178 : int pdevinit_done = 0;
179 : #endif
180 :
181 : /*
182 : * System startup; initialize the world, create process 0, mount root
183 : * filesystem, and fork to create init and pagedaemon. Most of the
184 : * hard work is done in the lower-level initialization routines including
185 : * startup(), which does memory initialization and autoconfiguration.
186 : */
187 : /* XXX return int, so gcc -Werror won't complain */
188 : int
189 0 : main(void *framep)
190 : {
191 : struct proc *p;
192 : struct process *pr;
193 : struct pdevinit *pdev;
194 : quad_t lim;
195 : int i;
196 : extern struct pdevinit pdevinit[];
197 : extern void disk_init(void);
198 :
199 : /*
200 : * Initialize the current process pointer (curproc) before
201 : * any possible traps/probes to simplify trap processing.
202 : */
203 0 : curproc = p = &proc0;
204 0 : p->p_cpu = curcpu();
205 :
206 : /*
207 : * Initialize timeouts.
208 : */
209 0 : timeout_startup();
210 :
211 : /*
212 : * Attempt to find console and initialize
213 : * in case of early panic or other messages.
214 : */
215 0 : config_init(); /* init autoconfiguration data structures */
216 0 : consinit();
217 :
218 0 : printf("%s\n", copyright);
219 :
220 : WITNESS_INITIALIZE();
221 :
222 0 : KERNEL_LOCK_INIT();
223 0 : SCHED_LOCK_INIT();
224 :
225 0 : uvm_init();
226 0 : disk_init(); /* must come before autoconfiguration */
227 0 : tty_init(); /* initialise tty's */
228 0 : cpu_startup();
229 :
230 0 : random_start(); /* Start the flow */
231 :
232 : /*
233 : * Initialize mbuf's. Do this now because we might attempt to
234 : * allocate mbufs or mbuf clusters during autoconfiguration.
235 : */
236 0 : mbinit();
237 :
238 : /* Initialize sockets. */
239 0 : soinit();
240 :
241 : /* Initialize SRP subsystem. */
242 0 : srp_startup();
243 :
244 : /*
245 : * Initialize process and pgrp structures.
246 : */
247 0 : procinit();
248 :
249 : /* Initialize file locking. */
250 0 : lf_init();
251 :
252 : /*
253 : * Initialize filedescriptors.
254 : */
255 0 : filedesc_init();
256 :
257 : /*
258 : * Initialize pipes.
259 : */
260 0 : pipe_init();
261 :
262 : /*
263 : * Initialize kqueues.
264 : */
265 0 : kqueue_init();
266 :
267 : /*
268 : * Initialize futexes.
269 : */
270 0 : futex_init();
271 :
272 : /* Create credentials. */
273 0 : p->p_ucred = crget();
274 0 : p->p_ucred->cr_ngroups = 1; /* group 0 */
275 :
276 : /*
277 : * Create process 0 (the swapper).
278 : */
279 : pr = &process0;
280 0 : process_initialize(pr, p);
281 :
282 0 : LIST_INSERT_HEAD(&allprocess, pr, ps_list);
283 0 : LIST_INSERT_HEAD(PIDHASH(0), pr, ps_hash);
284 0 : atomic_setbits_int(&pr->ps_flags, PS_SYSTEM);
285 :
286 : /* Set the default routing table/domain. */
287 0 : process0.ps_rtableid = 0;
288 :
289 0 : LIST_INSERT_HEAD(&allproc, p, p_list);
290 0 : pr->ps_pgrp = &pgrp0;
291 0 : LIST_INSERT_HEAD(TIDHASH(0), p, p_hash);
292 0 : LIST_INSERT_HEAD(PGRPHASH(0), &pgrp0, pg_hash);
293 0 : LIST_INIT(&pgrp0.pg_members);
294 0 : LIST_INSERT_HEAD(&pgrp0.pg_members, pr, ps_pglist);
295 :
296 0 : pgrp0.pg_session = &session0;
297 0 : session0.s_count = 1;
298 0 : session0.s_leader = pr;
299 :
300 0 : atomic_setbits_int(&p->p_flag, P_SYSTEM);
301 0 : p->p_stat = SONPROC;
302 0 : pr->ps_nice = NZERO;
303 0 : pr->ps_emul = &emul_native;
304 0 : strlcpy(pr->ps_comm, "swapper", sizeof(pr->ps_comm));
305 :
306 : /* Init timeouts. */
307 0 : timeout_set(&p->p_sleep_to, endtsleep, p);
308 :
309 : /* Initialize signal state for process 0. */
310 0 : signal_init();
311 0 : pr->ps_sigacts = &sigacts0;
312 0 : siginit(pr);
313 :
314 : /* Create the file descriptor table. */
315 0 : p->p_fd = pr->ps_fd = fdinit();
316 :
317 : /* Create the limits structures. */
318 0 : pr->ps_limit = &limit0;
319 0 : for (i = 0; i < nitems(p->p_rlimit); i++)
320 0 : limit0.pl_rlimit[i].rlim_cur =
321 0 : limit0.pl_rlimit[i].rlim_max = RLIM_INFINITY;
322 0 : limit0.pl_rlimit[RLIMIT_NOFILE].rlim_cur = NOFILE;
323 0 : limit0.pl_rlimit[RLIMIT_NOFILE].rlim_max = MIN(NOFILE_MAX,
324 : (maxfiles - NOFILE > NOFILE) ? maxfiles - NOFILE : NOFILE);
325 0 : limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur = MAXUPRC;
326 0 : lim = ptoa(uvmexp.free);
327 0 : limit0.pl_rlimit[RLIMIT_RSS].rlim_max = lim;
328 0 : limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_max = lim;
329 0 : limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = lim / 3;
330 0 : limit0.p_refcnt = 1;
331 :
332 : /* Allocate a prototype map so we have something to fork. */
333 0 : uvmspace_init(&vmspace0, pmap_kernel(), round_page(VM_MIN_ADDRESS),
334 : trunc_page(VM_MAX_ADDRESS), TRUE, TRUE);
335 0 : p->p_vmspace = pr->ps_vmspace = &vmspace0;
336 :
337 0 : p->p_addr = proc0paddr; /* XXX */
338 :
339 : /*
340 : * Charge root for one process.
341 : */
342 0 : (void)chgproccnt(0, 1);
343 :
344 : /* Initialize run queues */
345 0 : sched_init_runqueues();
346 0 : sleep_queue_init();
347 0 : sched_init_cpu(curcpu());
348 0 : p->p_cpu->ci_randseed = (arc4random() & 0x7fffffff) + 1;
349 :
350 : /* Initialize timeouts in process context. */
351 0 : timeout_proc_init();
352 :
353 : /* Initialize task queues */
354 0 : taskq_init();
355 :
356 : /* Initialize the interface/address trees */
357 0 : ifinit();
358 :
359 : /* Lock the kernel on behalf of proc0. */
360 0 : KERNEL_LOCK();
361 :
362 : #if NMPATH > 0
363 : /* Attach mpath before hardware */
364 0 : config_rootfound("mpath", NULL);
365 : #endif
366 :
367 : /* Configure the devices */
368 0 : cpu_configure();
369 :
370 : /* Configure virtual memory system, set vm rlimits. */
371 0 : uvm_init_limits(p);
372 :
373 : /* Per CPU memory allocation */
374 0 : percpu_init();
375 :
376 : /* Initialize the file systems. */
377 : #if defined(NFSSERVER) || defined(NFSCLIENT)
378 0 : nfs_init(); /* initialize server/shared data */
379 : #endif
380 0 : vfsinit();
381 :
382 : /* Start real time and statistics clocks. */
383 0 : initclocks();
384 :
385 : #ifdef SYSVSHM
386 : /* Initialize System V style shared memory. */
387 0 : shminit();
388 : #endif
389 :
390 : #ifdef SYSVSEM
391 : /* Initialize System V style semaphores. */
392 0 : seminit();
393 : #endif
394 :
395 : #ifdef SYSVMSG
396 : /* Initialize System V style message queues. */
397 0 : msginit();
398 : #endif
399 :
400 : /* Create default routing table before attaching lo0. */
401 0 : rtable_init();
402 :
403 : /* Attach pseudo-devices. */
404 0 : for (pdev = pdevinit; pdev->pdev_attach != NULL; pdev++)
405 0 : if (pdev->pdev_count > 0)
406 0 : (*pdev->pdev_attach)(pdev->pdev_count);
407 : #ifdef DIAGNOSTIC
408 0 : pdevinit_done = 1;
409 : #endif
410 :
411 : #ifdef CRYPTO
412 0 : crypto_init();
413 0 : swcr_init();
414 : #endif /* CRYPTO */
415 :
416 : /*
417 : * Initialize protocols.
418 : */
419 0 : domaininit();
420 :
421 0 : initconsbuf();
422 :
423 : #if defined(GPROF) || defined(DDBPROF)
424 : /* Initialize kernel profiling. */
425 : prof_init();
426 : #endif
427 :
428 0 : mbcpuinit(); /* enable per cpu mbuf data */
429 :
430 : /* init exec and emul */
431 0 : init_exec();
432 :
433 : /* Start the scheduler */
434 0 : scheduler_start();
435 :
436 : /*
437 : * Create process 1 (init(8)). We do this now, as Unix has
438 : * historically had init be process 1, and changing this would
439 : * probably upset a lot of people.
440 : *
441 : * Note that process 1 won't immediately exec init(8), but will
442 : * wait for us to inform it that the root file system has been
443 : * mounted.
444 : */
445 : {
446 0 : struct proc *initproc;
447 :
448 0 : if (fork1(p, FORK_FORK, start_init, NULL, NULL, &initproc))
449 0 : panic("fork init");
450 0 : initprocess = initproc->p_p;
451 0 : }
452 :
453 0 : randompid = 1;
454 :
455 : /*
456 : * Create any kernel threads whose creation was deferred because
457 : * initprocess had not yet been created.
458 : */
459 0 : kthread_run_deferred_queue();
460 :
461 : /*
462 : * Now that device driver threads have been created, wait for
463 : * them to finish any deferred autoconfiguration. Note we don't
464 : * need to lock this semaphore, since we haven't booted any
465 : * secondary processors, yet.
466 : */
467 0 : while (config_pending)
468 0 : (void) tsleep((void *)&config_pending, PWAIT, "cfpend", 0);
469 :
470 0 : dostartuphooks();
471 :
472 : #if NVSCSI > 0
473 0 : config_rootfound("vscsi", NULL);
474 : #endif
475 : #if NSOFTRAID > 0
476 0 : config_rootfound("softraid", NULL);
477 : #endif
478 :
479 : /* Configure root/swap devices */
480 0 : diskconf();
481 :
482 : #ifdef DDB
483 : /* Make debug symbols available in ddb. */
484 0 : db_ctf_init();
485 : #endif
486 :
487 0 : if (mountroot == NULL || ((*mountroot)() != 0))
488 0 : panic("cannot mount root");
489 :
490 0 : TAILQ_FIRST(&mountlist)->mnt_flag |= MNT_ROOTFS;
491 :
492 : /* Get the vnode for '/'. Set p->p_fd->fd_cdir to reference it. */
493 0 : if (VFS_ROOT(TAILQ_FIRST(&mountlist), &rootvnode))
494 0 : panic("cannot find root vnode");
495 0 : p->p_fd->fd_cdir = rootvnode;
496 0 : vref(p->p_fd->fd_cdir);
497 0 : VOP_UNLOCK(rootvnode);
498 0 : p->p_fd->fd_rdir = NULL;
499 :
500 : /*
501 : * Now that root is mounted, we can fixup initprocess's CWD
502 : * info. All other processes are kthreads, which merely
503 : * share proc0's CWD info.
504 : */
505 0 : initprocess->ps_fd->fd_cdir = rootvnode;
506 0 : vref(initprocess->ps_fd->fd_cdir);
507 0 : initprocess->ps_fd->fd_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 0 : nanotime(&boottime);
515 0 : LIST_FOREACH(pr, &allprocess, ps_list) {
516 0 : pr->ps_start = boottime;
517 0 : TAILQ_FOREACH(p, &pr->ps_threads, p_thr_link) {
518 0 : nanouptime(&p->p_cpu->ci_schedstate.spc_runtime);
519 0 : timespecclear(&p->p_rtime);
520 : }
521 : }
522 :
523 0 : uvm_swap_init();
524 :
525 : /* Create the pageout daemon kernel thread. */
526 0 : if (kthread_create(uvm_pageout, NULL, NULL, "pagedaemon"))
527 0 : panic("fork pagedaemon");
528 :
529 : /* Create the reaper daemon kernel thread. */
530 0 : if (kthread_create(reaper, NULL, &reaperproc, "reaper"))
531 0 : panic("fork reaper");
532 :
533 : /* Create the cleaner daemon kernel thread. */
534 0 : if (kthread_create(buf_daemon, NULL, &cleanerproc, "cleaner"))
535 0 : panic("fork cleaner");
536 :
537 : /* Create the update daemon kernel thread. */
538 0 : if (kthread_create(syncer_thread, NULL, &syncerproc, "update"))
539 0 : panic("fork update");
540 :
541 : /* Create the aiodone daemon kernel thread. */
542 0 : if (kthread_create(uvm_aiodone_daemon, NULL, NULL, "aiodoned"))
543 0 : panic("fork aiodoned");
544 :
545 : #if !defined(__hppa__)
546 : /* Create the page zeroing kernel thread. */
547 0 : if (kthread_create(uvm_pagezero_thread, NULL, NULL, "zerothread"))
548 0 : panic("fork zerothread");
549 : #endif
550 :
551 : #if defined(MULTIPROCESSOR)
552 : /* Boot the secondary processors. */
553 0 : cpu_boot_secondary_processors();
554 : #endif
555 :
556 0 : config_process_deferred_mountroot();
557 :
558 : /*
559 : * Okay, now we can let init(8) exec! It's off to userland!
560 : */
561 0 : start_init_exec = 1;
562 0 : wakeup((void *)&start_init_exec);
563 :
564 : /*
565 : * Start the idle pool page garbage collector
566 : */
567 : #if !(defined(__m88k__) && defined(MULTIPROCESSOR)) /* XXX */
568 0 : pool_gc_pages(NULL);
569 : #endif
570 :
571 0 : start_periodic_resettodr();
572 :
573 : /*
574 : * proc0: nothing to do, back to sleep
575 : */
576 0 : while (1)
577 0 : tsleep(&proc0, PVM, "scheduler", 0);
578 : /* NOTREACHED */
579 : }
580 :
581 : /*
582 : * List of paths to try when searching for "init".
583 : */
584 : static char *initpaths[] = {
585 : "/sbin/init",
586 : "/sbin/oinit",
587 : "/sbin/init.bak",
588 : NULL,
589 : };
590 :
591 : void
592 0 : check_console(struct proc *p)
593 : {
594 0 : struct nameidata nd;
595 : int error;
596 :
597 0 : NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, "/dev/console", p);
598 0 : error = namei(&nd);
599 0 : if (error) {
600 0 : if (error == ENOENT)
601 0 : printf("warning: /dev/console does not exist\n");
602 : else
603 0 : printf("warning: /dev/console error %d\n", error);
604 : } else
605 0 : vrele(nd.ni_vp);
606 0 : }
607 :
608 : /*
609 : * Start the initial user process; try exec'ing each pathname in "initpaths".
610 : * The program is invoked with one argument containing the boot flags.
611 : */
612 : void
613 0 : start_init(void *arg)
614 : {
615 0 : struct proc *p = arg;
616 0 : vaddr_t addr;
617 0 : struct sys_execve_args /* {
618 : syscallarg(const char *) path;
619 : syscallarg(char *const *) argp;
620 : syscallarg(char *const *) envp;
621 : } */ args;
622 : int options, error;
623 0 : long i;
624 0 : register_t retval[2];
625 0 : char flags[4], *flagsp;
626 0 : char **pathp, *path, *ucp, **uap, *arg0, *arg1 = NULL;
627 :
628 : /*
629 : * Now in process 1.
630 : */
631 :
632 : /*
633 : * Wait for main() to tell us that it's safe to exec.
634 : */
635 0 : while (start_init_exec == 0)
636 0 : (void) tsleep((void *)&start_init_exec, PWAIT, "initexec", 0);
637 :
638 0 : check_console(p);
639 :
640 : /* process 0 ignores SIGCHLD, but we can't */
641 0 : p->p_p->ps_sigacts->ps_flags = 0;
642 :
643 : /*
644 : * Need just enough stack to hold the faked-up "execve()" arguments.
645 : */
646 : #ifdef MACHINE_STACK_GROWS_UP
647 : addr = USRSTACK;
648 : #else
649 0 : addr = USRSTACK - PAGE_SIZE;
650 : #endif
651 0 : p->p_vmspace->vm_maxsaddr = (caddr_t)addr;
652 0 : p->p_vmspace->vm_minsaddr = (caddr_t)(addr + PAGE_SIZE);
653 0 : if (uvm_map(&p->p_vmspace->vm_map, &addr, PAGE_SIZE,
654 : NULL, UVM_UNKNOWN_OFFSET, 0,
655 : UVM_MAPFLAG(PROT_READ | PROT_WRITE, PROT_MASK, MAP_INHERIT_COPY,
656 : MADV_NORMAL, UVM_FLAG_FIXED|UVM_FLAG_OVERLAY|UVM_FLAG_COPYONW|UVM_FLAG_STACK)))
657 0 : panic("init: couldn't allocate argument space");
658 :
659 0 : for (pathp = &initpaths[0]; (path = *pathp) != NULL; pathp++) {
660 : #ifdef MACHINE_STACK_GROWS_UP
661 : ucp = (char *)addr;
662 : #else
663 0 : ucp = (char *)(addr + PAGE_SIZE);
664 : #endif
665 : /*
666 : * Construct the boot flag argument.
667 : */
668 0 : flagsp = flags;
669 0 : *flagsp++ = '-';
670 : options = 0;
671 :
672 0 : if (boothowto & RB_SINGLE) {
673 0 : *flagsp++ = 's';
674 : options = 1;
675 0 : }
676 : #ifdef notyet
677 : if (boothowto & RB_FASTBOOT) {
678 : *flagsp++ = 'f';
679 : options = 1;
680 : }
681 : #endif
682 :
683 : /*
684 : * Move out the flags (arg 1), if necessary.
685 : */
686 0 : if (options != 0) {
687 0 : *flagsp++ = '\0';
688 0 : i = flagsp - flags;
689 : #ifdef DEBUG
690 : printf("init: copying out flags `%s' %ld\n", flags, i);
691 : #endif
692 : #ifdef MACHINE_STACK_GROWS_UP
693 : arg1 = ucp;
694 : (void)copyout((caddr_t)flags, (caddr_t)ucp, i);
695 : ucp += i;
696 : #else
697 0 : (void)copyout((caddr_t)flags, (caddr_t)(ucp -= i), i);
698 0 : arg1 = ucp;
699 : #endif
700 0 : }
701 :
702 : /*
703 : * Move out the file name (also arg 0).
704 : */
705 0 : i = strlen(path) + 1;
706 : #ifdef DEBUG
707 : printf("init: copying out path `%s' %ld\n", path, i);
708 : #endif
709 : #ifdef MACHINE_STACK_GROWS_UP
710 : arg0 = ucp;
711 : (void)copyout((caddr_t)path, (caddr_t)ucp, i);
712 : ucp += i;
713 : ucp = (caddr_t)ALIGN((u_long)ucp);
714 : uap = (char **)ucp + 3;
715 : #else
716 0 : (void)copyout((caddr_t)path, (caddr_t)(ucp -= i), i);
717 0 : arg0 = ucp;
718 0 : uap = (char **)((u_long)ucp & ~ALIGNBYTES);
719 : #endif
720 :
721 : /*
722 : * Move out the arg pointers.
723 : */
724 0 : i = 0;
725 0 : copyout(&i, (caddr_t)--uap, sizeof(register_t)); /* terminator */
726 0 : if (options != 0)
727 0 : copyout(&arg1, (caddr_t)--uap, sizeof(register_t));
728 0 : copyout(&arg0, (caddr_t)--uap, sizeof(register_t));
729 :
730 : /*
731 : * Point at the arguments.
732 : */
733 0 : SCARG(&args, path) = arg0;
734 0 : SCARG(&args, argp) = uap;
735 0 : SCARG(&args, envp) = NULL;
736 :
737 : /*
738 : * Now try to exec the program. If can't for any reason
739 : * other than it doesn't exist, complain.
740 : */
741 0 : if ((error = sys_execve(p, &args, retval)) == 0) {
742 0 : KERNEL_UNLOCK();
743 : return;
744 : }
745 0 : if (error != ENOENT)
746 0 : printf("exec %s: error %d\n", path, error);
747 : }
748 0 : printf("init: not found\n");
749 0 : panic("no init");
750 0 : }
|