init_main.c revision 1.157 1 1.157 bouyer /* $NetBSD: init_main.c,v 1.157 1999/09/28 14:47:03 bouyer Exp $ */
2 1.61 mycroft
3 1.61 mycroft /*
4 1.76 cgd * Copyright (c) 1995 Christopher G. Demetriou. All rights reserved.
5 1.61 mycroft * Copyright (c) 1982, 1986, 1989, 1991, 1992, 1993
6 1.61 mycroft * The Regents of the University of California. All rights reserved.
7 1.61 mycroft * (c) UNIX System Laboratories, Inc.
8 1.61 mycroft * All or some portions of this file are derived from material licensed
9 1.61 mycroft * to the University of California by American Telephone and Telegraph
10 1.61 mycroft * Co. or Unix System Laboratories, Inc. and are reproduced herein with
11 1.61 mycroft * the permission of UNIX System Laboratories, Inc.
12 1.61 mycroft *
13 1.61 mycroft * Redistribution and use in source and binary forms, with or without
14 1.61 mycroft * modification, are permitted provided that the following conditions
15 1.61 mycroft * are met:
16 1.61 mycroft * 1. Redistributions of source code must retain the above copyright
17 1.61 mycroft * notice, this list of conditions and the following disclaimer.
18 1.61 mycroft * 2. Redistributions in binary form must reproduce the above copyright
19 1.61 mycroft * notice, this list of conditions and the following disclaimer in the
20 1.61 mycroft * documentation and/or other materials provided with the distribution.
21 1.61 mycroft * 3. All advertising materials mentioning features or use of this software
22 1.61 mycroft * must display the following acknowledgement:
23 1.61 mycroft * This product includes software developed by the University of
24 1.61 mycroft * California, Berkeley and its contributors.
25 1.61 mycroft * 4. Neither the name of the University nor the names of its contributors
26 1.61 mycroft * may be used to endorse or promote products derived from this software
27 1.61 mycroft * without specific prior written permission.
28 1.61 mycroft *
29 1.61 mycroft * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30 1.61 mycroft * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 1.61 mycroft * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 1.61 mycroft * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33 1.61 mycroft * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 1.61 mycroft * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35 1.61 mycroft * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 1.61 mycroft * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 1.61 mycroft * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38 1.61 mycroft * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 1.61 mycroft * SUCH DAMAGE.
40 1.61 mycroft *
41 1.118 fvdl * @(#)init_main.c 8.16 (Berkeley) 5/14/95
42 1.61 mycroft */
43 1.115 mrg
44 1.117 thorpej #include "fs_nfs.h"
45 1.123 thorpej #include "opt_nfsserver.h"
46 1.134 tron #include "opt_sysv.h"
47 1.61 mycroft
48 1.106 explorer #include "rnd.h"
49 1.106 explorer
50 1.61 mycroft #include <sys/param.h>
51 1.61 mycroft #include <sys/filedesc.h>
52 1.131 thorpej #include <sys/file.h>
53 1.61 mycroft #include <sys/errno.h>
54 1.61 mycroft #include <sys/exec.h>
55 1.61 mycroft #include <sys/kernel.h>
56 1.61 mycroft #include <sys/mount.h>
57 1.61 mycroft #include <sys/map.h>
58 1.61 mycroft #include <sys/proc.h>
59 1.136 thorpej #include <sys/kthread.h>
60 1.61 mycroft #include <sys/resourcevar.h>
61 1.61 mycroft #include <sys/signalvar.h>
62 1.61 mycroft #include <sys/systm.h>
63 1.61 mycroft #include <sys/vnode.h>
64 1.87 thorpej #include <sys/tty.h>
65 1.61 mycroft #include <sys/conf.h>
66 1.95 thorpej #include <sys/disklabel.h>
67 1.61 mycroft #include <sys/buf.h>
68 1.61 mycroft #include <sys/device.h>
69 1.128 thorpej #include <sys/socketvar.h>
70 1.61 mycroft #include <sys/protosw.h>
71 1.61 mycroft #include <sys/reboot.h>
72 1.61 mycroft #include <sys/user.h>
73 1.82 christos #ifdef SYSVSHM
74 1.82 christos #include <sys/shm.h>
75 1.82 christos #endif
76 1.82 christos #ifdef SYSVSEM
77 1.82 christos #include <sys/sem.h>
78 1.82 christos #endif
79 1.82 christos #ifdef SYSVMSG
80 1.82 christos #include <sys/msg.h>
81 1.82 christos #endif
82 1.82 christos #include <sys/domain.h>
83 1.82 christos #include <sys/mbuf.h>
84 1.94 mouse #include <sys/namei.h>
85 1.106 explorer #if NRND > 0
86 1.103 explorer #include <sys/rnd.h>
87 1.106 explorer #endif
88 1.61 mycroft
89 1.77 christos #include <sys/syscall.h>
90 1.68 cgd #include <sys/syscallargs.h>
91 1.68 cgd
92 1.61 mycroft #include <ufs/ufs/quota.h>
93 1.61 mycroft
94 1.61 mycroft #include <machine/cpu.h>
95 1.61 mycroft
96 1.61 mycroft #include <vm/vm.h>
97 1.81 christos #include <vm/vm_pageout.h>
98 1.81 christos
99 1.114 mrg #include <uvm/uvm.h>
100 1.114 mrg
101 1.81 christos #include <net/if.h>
102 1.81 christos #include <net/raw_cb.h>
103 1.61 mycroft
104 1.107 thorpej char copyright[] = "\
105 1.138 lukem Copyright (c) 1996, 1997, 1998, 1999
106 1.112 thorpej The NetBSD Foundation, Inc. All rights reserved.
107 1.107 thorpej Copyright (c) 1982, 1986, 1989, 1991, 1993
108 1.107 thorpej The Regents of the University of California. All rights reserved.
109 1.107 thorpej
110 1.107 thorpej ";
111 1.61 mycroft
112 1.61 mycroft /* Components of the first process -- never freed. */
113 1.61 mycroft struct session session0;
114 1.61 mycroft struct pgrp pgrp0;
115 1.61 mycroft struct proc proc0;
116 1.61 mycroft struct pcred cred0;
117 1.61 mycroft struct filedesc0 filedesc0;
118 1.148 thorpej struct cwdinfo cwdi0;
119 1.61 mycroft struct plimit limit0;
120 1.61 mycroft struct vmspace vmspace0;
121 1.149 thorpej struct sigacts sigacts0;
122 1.133 pk #ifndef curproc
123 1.61 mycroft struct proc *curproc = &proc0;
124 1.133 pk #endif
125 1.105 mycroft struct proc *initproc;
126 1.61 mycroft
127 1.61 mycroft int cmask = CMASK;
128 1.61 mycroft extern struct user *proc0paddr;
129 1.61 mycroft
130 1.61 mycroft struct vnode *rootvp, *swapdev_vp;
131 1.61 mycroft int boothowto;
132 1.156 thorpej int cold = 1; /* still working on startup */
133 1.61 mycroft struct timeval boottime;
134 1.61 mycroft struct timeval runtime;
135 1.61 mycroft
136 1.96 cgd static void check_console __P((struct proc *p));
137 1.135 thorpej static void start_init __P((void *));
138 1.135 thorpej static void start_pagedaemon __P((void *));
139 1.135 thorpej static void start_reaper __P((void *));
140 1.122 mycroft void main __P((void));
141 1.76 cgd
142 1.77 christos extern char sigcode[], esigcode[];
143 1.77 christos #ifdef SYSCALL_DEBUG
144 1.77 christos extern char *syscallnames[];
145 1.77 christos #endif
146 1.77 christos
147 1.77 christos struct emul emul_netbsd = {
148 1.77 christos "netbsd",
149 1.77 christos NULL,
150 1.77 christos sendsig,
151 1.77 christos SYS_syscall,
152 1.77 christos SYS_MAXSYSCALL,
153 1.77 christos sysent,
154 1.77 christos #ifdef SYSCALL_DEBUG
155 1.77 christos syscallnames,
156 1.77 christos #else
157 1.77 christos NULL,
158 1.77 christos #endif
159 1.77 christos 0,
160 1.77 christos copyargs,
161 1.77 christos setregs,
162 1.77 christos sigcode,
163 1.77 christos esigcode,
164 1.77 christos };
165 1.77 christos
166 1.61 mycroft /*
167 1.61 mycroft * System startup; initialize the world, create process 0, mount root
168 1.61 mycroft * filesystem, and fork to create init and pagedaemon. Most of the
169 1.61 mycroft * hard work is done in the lower-level initialization routines including
170 1.61 mycroft * startup(), which does memory initialization and autoconfiguration.
171 1.61 mycroft */
172 1.81 christos void
173 1.121 mycroft main()
174 1.61 mycroft {
175 1.144 thorpej struct proc *p;
176 1.111 thorpej struct pdevinit *pdev;
177 1.111 thorpej int i, s, error;
178 1.61 mycroft extern struct pdevinit pdevinit[];
179 1.61 mycroft extern void roundrobin __P((void *));
180 1.61 mycroft extern void schedcpu __P((void *));
181 1.80 thorpej extern void disk_init __P((void));
182 1.95 thorpej #if defined(NFSSERVER) || defined(NFS)
183 1.91 thorpej extern void nfs_init __P((void));
184 1.91 thorpej #endif
185 1.61 mycroft
186 1.61 mycroft /*
187 1.61 mycroft * Initialize the current process pointer (curproc) before
188 1.61 mycroft * any possible traps/probes to simplify trap processing.
189 1.61 mycroft */
190 1.61 mycroft p = &proc0;
191 1.61 mycroft curproc = p;
192 1.61 mycroft /*
193 1.61 mycroft * Attempt to find console and initialize
194 1.61 mycroft * in case of early panic or other messages.
195 1.61 mycroft */
196 1.61 mycroft consinit();
197 1.141 cjs printf("%s", copyright);
198 1.61 mycroft
199 1.114 mrg uvm_init();
200 1.127 thorpej
201 1.145 thorpej /* Do machine-dependent initialization. */
202 1.145 thorpej cpu_startup();
203 1.145 thorpej
204 1.127 thorpej /*
205 1.127 thorpej * Initialize mbuf's. Do this now because we might attempt to
206 1.127 thorpej * allocate mbufs or mbuf clusters during autoconfiguration.
207 1.127 thorpej */
208 1.127 thorpej mbinit();
209 1.128 thorpej
210 1.128 thorpej /* Initialize sockets. */
211 1.128 thorpej soinit();
212 1.127 thorpej
213 1.156 thorpej /*
214 1.156 thorpej * The following 3 things must be done before autoconfiguration.
215 1.156 thorpej */
216 1.156 thorpej disk_init(); /* initialize disk list */
217 1.156 thorpej tty_init(); /* initialize tty list */
218 1.106 explorer #if NRND > 0
219 1.156 thorpej rnd_init(); /* initialize RNG */
220 1.106 explorer #endif
221 1.61 mycroft
222 1.61 mycroft /*
223 1.63 mycroft * Initialize process and pgrp structures.
224 1.63 mycroft */
225 1.63 mycroft procinit();
226 1.63 mycroft
227 1.63 mycroft /*
228 1.61 mycroft * Create process 0 (the swapper).
229 1.61 mycroft */
230 1.154 thorpej s = proclist_lock_write();
231 1.63 mycroft LIST_INSERT_HEAD(&allproc, p, p_list);
232 1.154 thorpej proclist_unlock_write(s);
233 1.154 thorpej
234 1.61 mycroft p->p_pgrp = &pgrp0;
235 1.63 mycroft LIST_INSERT_HEAD(PGRPHASH(0), &pgrp0, pg_hash);
236 1.63 mycroft LIST_INIT(&pgrp0.pg_members);
237 1.63 mycroft LIST_INSERT_HEAD(&pgrp0.pg_members, p, p_pglist);
238 1.63 mycroft
239 1.61 mycroft pgrp0.pg_session = &session0;
240 1.61 mycroft session0.s_count = 1;
241 1.116 thorpej session0.s_sid = p->p_pid;
242 1.61 mycroft session0.s_leader = p;
243 1.61 mycroft
244 1.136 thorpej /*
245 1.136 thorpej * Set P_NOCLDWAIT so that kernel threads are reparented to
246 1.136 thorpej * init(8) when they exit. init(8) can easily wait them out
247 1.136 thorpej * for us.
248 1.136 thorpej */
249 1.136 thorpej p->p_flag = P_INMEM | P_SYSTEM | P_NOCLDWAIT;
250 1.61 mycroft p->p_stat = SRUN;
251 1.61 mycroft p->p_nice = NZERO;
252 1.77 christos p->p_emul = &emul_netbsd;
253 1.146 gwr strncpy(p->p_comm, "swapper", MAXCOMLEN);
254 1.61 mycroft
255 1.61 mycroft /* Create credentials. */
256 1.61 mycroft cred0.p_refcnt = 1;
257 1.61 mycroft p->p_cred = &cred0;
258 1.61 mycroft p->p_ucred = crget();
259 1.61 mycroft p->p_ucred->cr_ngroups = 1; /* group 0 */
260 1.61 mycroft
261 1.61 mycroft /* Create the file descriptor table. */
262 1.131 thorpej finit();
263 1.79 mycroft p->p_fd = &filedesc0.fd_fd;
264 1.109 thorpej fdinit1(&filedesc0);
265 1.61 mycroft
266 1.148 thorpej /* Create the CWD info. */
267 1.148 thorpej p->p_cwdi = &cwdi0;
268 1.148 thorpej cwdi0.cwdi_cmask = cmask;
269 1.148 thorpej cwdi0.cwdi_refcnt = 1;
270 1.148 thorpej
271 1.61 mycroft /* Create the limits structures. */
272 1.61 mycroft p->p_limit = &limit0;
273 1.61 mycroft for (i = 0; i < sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]); i++)
274 1.61 mycroft limit0.pl_rlimit[i].rlim_cur =
275 1.61 mycroft limit0.pl_rlimit[i].rlim_max = RLIM_INFINITY;
276 1.140 christos
277 1.140 christos limit0.pl_rlimit[RLIMIT_NOFILE].rlim_max = maxfiles;
278 1.140 christos limit0.pl_rlimit[RLIMIT_NOFILE].rlim_cur =
279 1.140 christos maxfiles < NOFILE ? maxfiles : NOFILE;
280 1.140 christos
281 1.140 christos limit0.pl_rlimit[RLIMIT_NPROC].rlim_max = maxproc;
282 1.140 christos limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur =
283 1.140 christos maxproc < MAXUPRC ? maxproc : MAXUPRC;
284 1.140 christos
285 1.114 mrg i = ptoa(uvmexp.free);
286 1.61 mycroft limit0.pl_rlimit[RLIMIT_RSS].rlim_max = i;
287 1.61 mycroft limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_max = i;
288 1.61 mycroft limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = i / 3;
289 1.157 bouyer limit0.pl_corename = defcorename;
290 1.61 mycroft limit0.p_refcnt = 1;
291 1.61 mycroft
292 1.120 thorpej /*
293 1.120 thorpej * Initialize proc0's vmspace, which uses the kernel pmap.
294 1.120 thorpej * All kernel processes (which never have user space mappings)
295 1.120 thorpej * share proc0's vmspace, and thus, the kernel pmap.
296 1.120 thorpej */
297 1.120 thorpej uvmspace_init(&vmspace0, pmap_kernel(), round_page(VM_MIN_ADDRESS),
298 1.120 thorpej trunc_page(VM_MAX_ADDRESS), TRUE);
299 1.120 thorpej p->p_vmspace = &vmspace0;
300 1.99 gwr
301 1.61 mycroft p->p_addr = proc0paddr; /* XXX */
302 1.61 mycroft
303 1.61 mycroft /*
304 1.149 thorpej * We continue to place resource usage info in the
305 1.149 thorpej * user struct so they're pageable.
306 1.61 mycroft */
307 1.61 mycroft p->p_stats = &p->p_addr->u_stats;
308 1.61 mycroft
309 1.61 mycroft /*
310 1.63 mycroft * Charge root for one process.
311 1.61 mycroft */
312 1.61 mycroft (void)chgproccnt(0, 1);
313 1.61 mycroft
314 1.61 mycroft rqinit();
315 1.61 mycroft
316 1.61 mycroft /* Configure virtual memory system, set vm rlimits. */
317 1.114 mrg uvm_init_limits(p);
318 1.61 mycroft
319 1.61 mycroft /* Initialize the file systems. */
320 1.95 thorpej #if defined(NFSSERVER) || defined(NFS)
321 1.91 thorpej nfs_init(); /* initialize server/shared data */
322 1.91 thorpej #endif
323 1.61 mycroft vfsinit();
324 1.61 mycroft
325 1.156 thorpej /* Configure the system hardware. This will enable interrupts. */
326 1.156 thorpej configure();
327 1.61 mycroft
328 1.61 mycroft #ifdef SYSVSHM
329 1.61 mycroft /* Initialize System V style shared memory. */
330 1.61 mycroft shminit();
331 1.61 mycroft #endif
332 1.61 mycroft
333 1.61 mycroft #ifdef SYSVSEM
334 1.61 mycroft /* Initialize System V style semaphores. */
335 1.61 mycroft seminit();
336 1.61 mycroft #endif
337 1.61 mycroft
338 1.61 mycroft #ifdef SYSVMSG
339 1.61 mycroft /* Initialize System V style message queues. */
340 1.61 mycroft msginit();
341 1.61 mycroft #endif
342 1.61 mycroft
343 1.61 mycroft /* Attach pseudo-devices. */
344 1.61 mycroft for (pdev = pdevinit; pdev->pdev_attach != NULL; pdev++)
345 1.61 mycroft (*pdev->pdev_attach)(pdev->pdev_count);
346 1.61 mycroft
347 1.61 mycroft /*
348 1.61 mycroft * Initialize protocols. Block reception of incoming packets
349 1.61 mycroft * until everything is ready.
350 1.61 mycroft */
351 1.61 mycroft s = splimp();
352 1.61 mycroft ifinit();
353 1.61 mycroft domaininit();
354 1.61 mycroft splx(s);
355 1.61 mycroft
356 1.61 mycroft #ifdef GPROF
357 1.61 mycroft /* Initialize kernel profiling. */
358 1.61 mycroft kmstartup();
359 1.61 mycroft #endif
360 1.61 mycroft
361 1.61 mycroft /* Kick off timeout driven events by calling first time. */
362 1.61 mycroft roundrobin(NULL);
363 1.61 mycroft schedcpu(NULL);
364 1.98 gwr
365 1.101 thorpej /* Determine the root and dump devices. */
366 1.98 gwr cpu_rootconf();
367 1.101 thorpej cpu_dumpconf();
368 1.61 mycroft
369 1.61 mycroft /* Mount the root file system. */
370 1.95 thorpej do {
371 1.95 thorpej domountroothook();
372 1.95 thorpej if ((error = vfs_mountroot())) {
373 1.97 thorpej printf("cannot mount root, error = %d\n", error);
374 1.95 thorpej boothowto |= RB_ASKNAME;
375 1.95 thorpej setroot(root_device,
376 1.152 thorpej (rootdev != NODEV) ? DISKPART(rootdev) : 0);
377 1.95 thorpej }
378 1.95 thorpej } while (error != 0);
379 1.95 thorpej mountroothook_destroy();
380 1.95 thorpej
381 1.74 mycroft mountlist.cqh_first->mnt_flag |= MNT_ROOTFS;
382 1.74 mycroft mountlist.cqh_first->mnt_op->vfs_refcount++;
383 1.61 mycroft
384 1.111 thorpej /*
385 1.111 thorpej * Get the vnode for '/'. Set filedesc0.fd_fd.fd_cdir to
386 1.111 thorpej * reference it.
387 1.111 thorpej */
388 1.74 mycroft if (VFS_ROOT(mountlist.cqh_first, &rootvnode))
389 1.61 mycroft panic("cannot find root vnode");
390 1.148 thorpej cwdi0.cwdi_cdir = rootvnode;
391 1.148 thorpej VREF(cwdi0.cwdi_cdir);
392 1.118 fvdl VOP_UNLOCK(rootvnode, 0);
393 1.148 thorpej cwdi0.cwdi_rdir = NULL;
394 1.114 mrg uvm_swap_init();
395 1.61 mycroft
396 1.61 mycroft /*
397 1.61 mycroft * Now can look at time, having had a chance to verify the time
398 1.61 mycroft * from the file system. Reset p->p_rtime as it may have been
399 1.61 mycroft * munched in mi_switch() after the time got set.
400 1.61 mycroft */
401 1.61 mycroft p->p_stats->p_start = runtime = mono_time = boottime = time;
402 1.61 mycroft p->p_rtime.tv_sec = p->p_rtime.tv_usec = 0;
403 1.61 mycroft
404 1.149 thorpej /*
405 1.149 thorpej * Initialize signal-related data structures, and signal state
406 1.149 thorpej * for proc0.
407 1.149 thorpej */
408 1.149 thorpej signal_init();
409 1.149 thorpej p->p_sigacts = &sigacts0;
410 1.61 mycroft siginit(p);
411 1.61 mycroft
412 1.61 mycroft /* Create process 1 (init(8)). */
413 1.151 thorpej if (fork1(p, 0, SIGCHLD, NULL, 0, NULL, &initproc))
414 1.61 mycroft panic("fork init");
415 1.144 thorpej cpu_set_kpc(initproc, start_init, initproc);
416 1.61 mycroft
417 1.135 thorpej /* Create process 2, the pageout daemon kernel thread. */
418 1.153 thorpej if (kthread_create1(start_pagedaemon, NULL, NULL, "pagedaemon"))
419 1.135 thorpej panic("fork pagedaemon");
420 1.61 mycroft
421 1.135 thorpej /* Create process 3, the process reaper kernel thread. */
422 1.153 thorpej if (kthread_create1(start_reaper, NULL, NULL, "reaper"))
423 1.132 thorpej panic("fork reaper");
424 1.137 thorpej
425 1.137 thorpej /* Create any other deferred kernel threads. */
426 1.137 thorpej kthread_run_deferred_queue();
427 1.132 thorpej
428 1.61 mycroft /* The scheduler is an infinite loop. */
429 1.114 mrg uvm_scheduler();
430 1.61 mycroft /* NOTREACHED */
431 1.61 mycroft }
432 1.61 mycroft
433 1.93 mouse static void
434 1.93 mouse check_console(p)
435 1.96 cgd struct proc *p;
436 1.93 mouse {
437 1.93 mouse struct nameidata nd;
438 1.93 mouse int error;
439 1.93 mouse
440 1.93 mouse NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, "/dev/console", p);
441 1.93 mouse error = namei(&nd);
442 1.96 cgd if (error == 0)
443 1.96 cgd vrele(nd.ni_vp);
444 1.96 cgd else if (error == ENOENT)
445 1.96 cgd printf("warning: no /dev/console\n");
446 1.93 mouse else
447 1.96 cgd printf("warning: lookup /dev/console: error %d\n", error);
448 1.93 mouse }
449 1.93 mouse
450 1.61 mycroft /*
451 1.61 mycroft * List of paths to try when searching for "init".
452 1.61 mycroft */
453 1.61 mycroft static char *initpaths[] = {
454 1.61 mycroft "/sbin/init",
455 1.61 mycroft "/sbin/oinit",
456 1.61 mycroft "/sbin/init.bak",
457 1.61 mycroft NULL,
458 1.61 mycroft };
459 1.61 mycroft
460 1.61 mycroft /*
461 1.61 mycroft * Start the initial user process; try exec'ing each pathname in "initpaths".
462 1.61 mycroft * The program is invoked with one argument containing the boot flags.
463 1.61 mycroft */
464 1.61 mycroft static void
465 1.135 thorpej start_init(arg)
466 1.135 thorpej void *arg;
467 1.61 mycroft {
468 1.135 thorpej struct proc *p = arg;
469 1.130 eeh vaddr_t addr;
470 1.78 mycroft struct sys_execve_args /* {
471 1.108 mycroft syscallarg(const char *) path;
472 1.92 cgd syscallarg(char * const *) argp;
473 1.92 cgd syscallarg(char * const *) envp;
474 1.68 cgd } */ args;
475 1.68 cgd int options, i, error;
476 1.68 cgd register_t retval[2];
477 1.66 mycroft char flags[4], *flagsp;
478 1.142 mycroft char **pathp, *path, *slash, *ucp, **uap, *arg0, *arg1 = NULL;
479 1.61 mycroft
480 1.76 cgd /*
481 1.76 cgd * Now in process 1.
482 1.76 cgd */
483 1.146 gwr strncpy(p->p_comm, "init", MAXCOMLEN);
484 1.93 mouse
485 1.93 mouse /*
486 1.93 mouse * This is not the right way to do this. We really should
487 1.93 mouse * hand-craft a descriptor onto /dev/console to hand to init,
488 1.93 mouse * but that's a _lot_ more work, and the benefit from this easy
489 1.93 mouse * hack makes up for the "good is the enemy of the best" effect.
490 1.93 mouse */
491 1.93 mouse check_console(p);
492 1.61 mycroft
493 1.61 mycroft /*
494 1.61 mycroft * Need just enough stack to hold the faked-up "execve()" arguments.
495 1.61 mycroft */
496 1.61 mycroft addr = USRSTACK - PAGE_SIZE;
497 1.114 mrg if (uvm_map(&p->p_vmspace->vm_map, &addr, PAGE_SIZE,
498 1.114 mrg NULL, UVM_UNKNOWN_OFFSET,
499 1.114 mrg UVM_MAPFLAG(UVM_PROT_ALL, UVM_PROT_ALL, UVM_INH_COPY,
500 1.114 mrg UVM_ADV_NORMAL,
501 1.114 mrg UVM_FLAG_FIXED|UVM_FLAG_OVERLAY|UVM_FLAG_COPYONW))
502 1.114 mrg != KERN_SUCCESS)
503 1.114 mrg panic("init: couldn't allocate argument space");
504 1.61 mycroft p->p_vmspace->vm_maxsaddr = (caddr_t)addr;
505 1.61 mycroft
506 1.61 mycroft for (pathp = &initpaths[0]; (path = *pathp) != NULL; pathp++) {
507 1.64 mycroft ucp = (char *)(addr + PAGE_SIZE);
508 1.64 mycroft
509 1.61 mycroft /*
510 1.64 mycroft * Construct the boot flag argument.
511 1.61 mycroft */
512 1.66 mycroft flagsp = flags;
513 1.66 mycroft *flagsp++ = '-';
514 1.61 mycroft options = 0;
515 1.66 mycroft
516 1.61 mycroft if (boothowto & RB_SINGLE) {
517 1.64 mycroft *flagsp++ = 's';
518 1.61 mycroft options = 1;
519 1.61 mycroft }
520 1.61 mycroft #ifdef notyet
521 1.61 mycroft if (boothowto & RB_FASTBOOT) {
522 1.64 mycroft *flagsp++ = 'f';
523 1.61 mycroft options = 1;
524 1.61 mycroft }
525 1.61 mycroft #endif
526 1.64 mycroft
527 1.64 mycroft /*
528 1.64 mycroft * Move out the flags (arg 1), if necessary.
529 1.64 mycroft */
530 1.64 mycroft if (options != 0) {
531 1.64 mycroft *flagsp++ = '\0';
532 1.64 mycroft i = flagsp - flags;
533 1.64 mycroft #ifdef DEBUG
534 1.90 christos printf("init: copying out flags `%s' %d\n", flags, i);
535 1.64 mycroft #endif
536 1.64 mycroft (void)copyout((caddr_t)flags, (caddr_t)(ucp -= i), i);
537 1.64 mycroft arg1 = ucp;
538 1.64 mycroft }
539 1.61 mycroft
540 1.61 mycroft /*
541 1.61 mycroft * Move out the file name (also arg 0).
542 1.61 mycroft */
543 1.64 mycroft i = strlen(path) + 1;
544 1.64 mycroft #ifdef DEBUG
545 1.90 christos printf("init: copying out path `%s' %d\n", path, i);
546 1.64 mycroft #endif
547 1.64 mycroft (void)copyout((caddr_t)path, (caddr_t)(ucp -= i), i);
548 1.61 mycroft arg0 = ucp;
549 1.61 mycroft
550 1.61 mycroft /*
551 1.61 mycroft * Move out the arg pointers.
552 1.61 mycroft */
553 1.73 cgd uap = (char **)((long)ucp & ~ALIGNBYTES);
554 1.61 mycroft (void)suword((caddr_t)--uap, 0); /* terminator */
555 1.64 mycroft if (options != 0)
556 1.64 mycroft (void)suword((caddr_t)--uap, (long)arg1);
557 1.142 mycroft slash = strrchr(path, '/');
558 1.142 mycroft if (slash)
559 1.142 mycroft (void)suword((caddr_t)--uap,
560 1.142 mycroft (long)arg0 + (slash + 1 - path));
561 1.142 mycroft else
562 1.142 mycroft (void)suword((caddr_t)--uap, (long)arg0);
563 1.61 mycroft
564 1.61 mycroft /*
565 1.61 mycroft * Point at the arguments.
566 1.61 mycroft */
567 1.68 cgd SCARG(&args, path) = arg0;
568 1.68 cgd SCARG(&args, argp) = uap;
569 1.68 cgd SCARG(&args, envp) = NULL;
570 1.61 mycroft
571 1.61 mycroft /*
572 1.61 mycroft * Now try to exec the program. If can't for any reason
573 1.61 mycroft * other than it doesn't exist, complain.
574 1.61 mycroft */
575 1.102 mycroft error = sys_execve(p, &args, retval);
576 1.102 mycroft if (error == 0 || error == EJUSTRETURN)
577 1.61 mycroft return;
578 1.61 mycroft if (error != ENOENT)
579 1.90 christos printf("exec %s: error %d\n", path, error);
580 1.61 mycroft }
581 1.90 christos printf("init: not found\n");
582 1.61 mycroft panic("no init");
583 1.76 cgd }
584 1.76 cgd
585 1.135 thorpej /* ARGSUSED */
586 1.76 cgd static void
587 1.135 thorpej start_pagedaemon(arg)
588 1.135 thorpej void *arg;
589 1.76 cgd {
590 1.76 cgd
591 1.114 mrg uvm_pageout();
592 1.132 thorpej /* NOTREACHED */
593 1.132 thorpej }
594 1.132 thorpej
595 1.135 thorpej /* ARGSUSED */
596 1.132 thorpej static void
597 1.135 thorpej start_reaper(arg)
598 1.135 thorpej void *arg;
599 1.132 thorpej {
600 1.132 thorpej
601 1.132 thorpej reaper();
602 1.76 cgd /* NOTREACHED */
603 1.61 mycroft }
604