xref: /freebsd/sys/kern/init_main.c (revision 0c43d89a0d8e976ca494d4837f4c1f3734d2c300)
1 /*
2  * Copyright (c) 1982, 1986, 1989, 1991, 1992, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  * (c) UNIX System Laboratories, Inc.
5  * All or some portions of this file are derived from material licensed
6  * to the University of California by American Telephone and Telegraph
7  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8  * the permission of UNIX System Laboratories, Inc.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by the University of
21  *	California, Berkeley and its contributors.
22  * 4. 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  * $Id: init_main.c,v 1.5 1994/08/18 22:34:57 wollman Exp $
40  */
41 
42 #include <sys/param.h>
43 #include <sys/filedesc.h>
44 #include <sys/errno.h>
45 #include <sys/exec.h>
46 #include <sys/kernel.h>
47 #include <sys/mount.h>
48 #include <sys/map.h>
49 #include <sys/proc.h>
50 #include <sys/resourcevar.h>
51 #include <sys/signalvar.h>
52 #include <sys/systm.h>
53 #include <sys/vnode.h>
54 #include <sys/sysent.h>
55 #include <sys/conf.h>
56 #include <sys/buf.h>
57 #include <sys/clist.h>
58 #include <sys/device.h>
59 #include <sys/protosw.h>
60 #include <sys/reboot.h>
61 #include <sys/user.h>
62 
63 #include <ufs/ufs/quota.h>
64 
65 #include <machine/cpu.h>
66 
67 #include <vm/vm.h>
68 
69 #ifdef HPFPLIB
70 char	copyright[] =
71 "Copyright (c) 1982, 1986, 1989, 1991, 1993\n\tThe Regents of the University of California.\nCopyright (c) 1992 Hewlett-Packard Company\nCopyright (c) 1992 Motorola Inc.\nAll rights reserved.\n\n";
72 #else
73 char	copyright[] =
74 "Copyright (c) 1982, 1986, 1989, 1991, 1993\n\tThe Regents of the University of California.  All rights reserved.\n\n";
75 #endif
76 
77 /* Components of the first process -- never freed. */
78 struct	session session0;
79 struct	pgrp pgrp0;
80 struct	proc proc0;
81 struct	pcred cred0;
82 struct	filedesc0 filedesc0;
83 struct	plimit limit0;
84 struct	vmspace vmspace0;
85 struct	proc *curproc = &proc0;
86 struct	proc *initproc, *pageproc, *updateproc;
87 
88 int	cmask = CMASK;
89 extern	struct user *proc0paddr;
90 
91 struct	vnode *rootvp, *swapdev_vp;
92 int	boothowto;
93 struct	timeval boottime;
94 struct	timeval runtime;
95 
96 static void start_init __P((struct proc *p, void *framep));
97 
98 #if __GNUC__ >= 2
99 void __main() {}
100 #endif
101 
102 /*
103  * This table is filled in by the linker with functions that need to be
104  * called to initialize various pseudo-devices and whatnot.
105  */
106 typedef void (*pseudo_func_t)(void);
107 extern const struct linker_set pseudo_set;
108 static const pseudo_func_t *pseudos =
109 	(const pseudo_func_t *)&pseudo_set.ls_items[0];
110 
111 /*
112  * System startup; initialize the world, create process 0, mount root
113  * filesystem, and fork to create init and pagedaemon.  Most of the
114  * hard work is done in the lower-level initialization routines including
115  * startup(), which does memory initialization and autoconfiguration.
116  */
117 void
118 main(framep)
119 	void *framep;
120 {
121 	register struct proc *p;
122 	register struct filedesc0 *fdp;
123 	register struct pdevinit *pdev;
124 	register int i;
125 	int s, rval[2];
126 	extern int (*mountroot) __P((void));
127 	extern struct pdevinit pdevinit[];
128 	extern void roundrobin __P((void *));
129 	extern void schedcpu __P((void *));
130 	extern struct sysentvec aout_sysvec;
131 
132 	/*
133 	 * Initialize the current process pointer (curproc) before
134 	 * any possible traps/probes to simplify trap processing.
135 	 */
136 	p = &proc0;
137 	curproc = p;
138 	/*
139 	 * Attempt to find console and initialize
140 	 * in case of early panic or other messages.
141 	 */
142 	consinit();
143 	printf(copyright);
144 
145 	vm_mem_init();
146 	kmeminit();
147 	cpu_startup();
148 
149 	/*
150 	 * Create process 0 (the swapper).
151 	 */
152 	allproc = (volatile struct proc *)p;
153 	p->p_prev = (struct proc **)&allproc;
154 	p->p_pgrp = &pgrp0;
155 	pgrphash[0] = &pgrp0;
156 	pgrp0.pg_mem = p;
157 	pgrp0.pg_session = &session0;
158 	session0.s_count = 1;
159 	session0.s_leader = p;
160 
161 	p->p_sysent = &aout_sysvec;
162 
163 	p->p_flag = P_INMEM | P_SYSTEM;
164 	p->p_stat = SRUN;
165 	p->p_nice = NZERO;
166 	bcopy("swapper", p->p_comm, sizeof ("swapper"));
167 
168 	/* Create credentials. */
169 	cred0.p_refcnt = 1;
170 	p->p_cred = &cred0;
171 	p->p_ucred = crget();
172 	p->p_ucred->cr_ngroups = 1;	/* group 0 */
173 
174 	/* Create the file descriptor table. */
175 	fdp = &filedesc0;
176 	p->p_fd = &fdp->fd_fd;
177 	fdp->fd_fd.fd_refcnt = 1;
178 	fdp->fd_fd.fd_cmask = cmask;
179 	fdp->fd_fd.fd_ofiles = fdp->fd_dfiles;
180 	fdp->fd_fd.fd_ofileflags = fdp->fd_dfileflags;
181 	fdp->fd_fd.fd_nfiles = NDFILE;
182 
183 	/* Create the limits structures. */
184 	p->p_limit = &limit0;
185 	for (i = 0; i < sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]); i++)
186 		limit0.pl_rlimit[i].rlim_cur =
187 		    limit0.pl_rlimit[i].rlim_max = RLIM_INFINITY;
188 	limit0.pl_rlimit[RLIMIT_NOFILE].rlim_cur = NOFILE;
189 	limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur = MAXUPRC;
190 	i = ptoa(cnt.v_free_count);
191 	limit0.pl_rlimit[RLIMIT_RSS].rlim_max = i;
192 	limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_max = i;
193 	limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = i / 3;
194 	limit0.p_refcnt = 1;
195 
196 	/* Allocate a prototype map so we have something to fork. */
197 	p->p_vmspace = &vmspace0;
198 	vmspace0.vm_refcnt = 1;
199 	pmap_pinit(&vmspace0.vm_pmap);
200 	vm_map_init(&vmspace0.vm_map, round_page(VM_MIN_ADDRESS),
201 	    trunc_page(VM_MAX_ADDRESS), TRUE);
202 	vmspace0.vm_map.pmap = &vmspace0.vm_pmap;
203 	p->p_addr = proc0paddr;				/* XXX */
204 
205 	/*
206 	 * We continue to place resource usage info and signal
207 	 * actions in the user struct so they're pageable.
208 	 */
209 	p->p_stats = &p->p_addr->u_stats;
210 	p->p_sigacts = &p->p_addr->u_sigacts;
211 
212 	/*
213 	 * Initialize per uid information structure and charge
214 	 * root for one process.
215 	 */
216 	usrinfoinit();
217 	(void)chgproccnt(0, 1);
218 
219 	rqinit();
220 
221 	/* Configure virtual memory system, set vm rlimits. */
222 	vm_init_limits(p);
223 
224 	/* Initialize the file systems. */
225 	vfsinit();
226 
227 	/* Start real time and statistics clocks. */
228 	initclocks();
229 
230 	/* Initialize mbuf's. */
231 	mbinit();
232 
233 	/* Initialize clists. */
234 	clist_init();
235 
236 	/*
237 	 * Attach pseudo-devices.
238 	 */
239 	while(*pseudos) {
240 		(**pseudos++)();
241 	}
242 
243 	/*
244 	 * Initialize protocols.  Block reception of incoming packets
245 	 * until everything is ready.
246 	 */
247 	s = splimp();
248 	ifinit();
249 	domaininit();
250 	splx(s);
251 
252 #ifdef GPROF
253 	/* Initialize kernel profiling. */
254 	kmstartup();
255 #endif
256 
257 	/* Kick off timeout driven events by calling first time. */
258 	roundrobin(NULL);
259 	schedcpu(NULL);
260 
261 	/* Mount the root file system. */
262 	if ((*mountroot)())
263 		panic("cannot mount root");
264 
265 	/* Get the vnode for '/'.  Set fdp->fd_fd.fd_cdir to reference it. */
266 	if (VFS_ROOT(mountlist.tqh_first, &rootvnode))
267 		panic("cannot find root vnode");
268 	fdp->fd_fd.fd_cdir = rootvnode;
269 	VREF(fdp->fd_fd.fd_cdir);
270 	VOP_UNLOCK(rootvnode);
271 	fdp->fd_fd.fd_rdir = NULL;
272 	swapinit();
273 
274 	/*
275 	 * Now can look at time, having had a chance to verify the time
276 	 * from the file system.  Reset p->p_rtime as it may have been
277 	 * munched in mi_switch() after the time got set.
278 	 */
279 	p->p_stats->p_start = runtime = mono_time = boottime = time;
280 	p->p_rtime.tv_sec = p->p_rtime.tv_usec = 0;
281 
282 	/* Initialize signal state for process 0. */
283 	siginit(p);
284 
285 	/* Create process 1 (init(8)). */
286 	if (fork(p, NULL, rval))
287 		panic("fork init");
288 	if (rval[1]) {
289 		start_init(curproc, framep);
290 		return;
291 	}
292 
293 	/* Create process 2 (the pageout daemon). */
294 	if (fork(p, NULL, rval))
295 		panic("fork pager");
296 	if (rval[1]) {
297 		/*
298 		 * Now in process 2.
299 		 */
300 		p = curproc;
301 		pageproc = p;
302 		p->p_flag |= P_INMEM | P_SYSTEM;	/* XXX */
303 		bcopy("pagedaemon", curproc->p_comm, sizeof ("pagedaemon"));
304 		vm_pageout();
305 		/* NOTREACHED */
306 	}
307 
308 	/*
309 	 * Start update daemon (process 3).
310 	 */
311 	if (fork(p, (void *) NULL, rval))
312 		panic("failed fork update daemon");
313 	if (rval[1]) {
314 		p = curproc;
315 		updateproc = p;
316 		p->p_flag |= P_INMEM | P_SYSTEM;
317 		bcopy("update", p->p_comm, sizeof("update"));
318 		vfs_update();
319 		/*NOTREACHED*/
320 	}
321 
322 	/* The scheduler is an infinite loop. */
323 	scheduler();
324 	/* NOTREACHED */
325 }
326 
327 /*
328  * List of paths to try when searching for "init".
329  */
330 static char *initpaths[] = {
331 	"/sbin/init",
332 	"/sbin/oinit",
333 	"/sbin/init.bak",
334 	NULL,
335 };
336 
337 /*
338  * Start the initial user process; try exec'ing each pathname in "initpaths".
339  * The program is invoked with one argument containing the boot flags.
340  */
341 static void
342 start_init(p, framep)
343 	struct proc *p;
344 	void *framep;
345 {
346 	vm_offset_t addr;
347 	struct execve_args args;
348 	int options, i, retval[2], error;
349 	char **pathp, *path, *ucp, **uap, *arg0, *arg1;
350 
351 	initproc = p;
352 
353 	/*
354 	 * We need to set the system call frame as if we were entered through
355 	 * a syscall() so that when we call execve() below, it will be able
356 	 * to set the entry point (see setregs) when it tries to exec.  The
357 	 * startup code in "locore.s" has allocated space for the frame and
358 	 * passed a pointer to that space as main's argument.
359 	 */
360 	cpu_set_init_frame(p, framep);
361 
362 	/*
363 	 * Need just enough stack to hold the faked-up "execve()" arguments.
364 	 */
365 	addr = trunc_page(VM_MAXUSER_ADDRESS - PAGE_SIZE);
366 	if (vm_allocate(&p->p_vmspace->vm_map, &addr, PAGE_SIZE, FALSE) != 0)
367 		panic("init: couldn't allocate argument space");
368 	p->p_vmspace->vm_maxsaddr = (caddr_t)addr;
369 	p->p_vmspace->vm_ssize = 1;
370 
371 	for (pathp = &initpaths[0]; (path = *pathp) != NULL; pathp++) {
372 		/*
373 		 * Move out the boot flag argument.
374 		 */
375 		options = 0;
376 		ucp = (char *)USRSTACK;
377 		(void)subyte(--ucp, 0);		/* trailing zero */
378 		if (boothowto & RB_SINGLE) {
379 			(void)subyte(--ucp, 's');
380 			options = 1;
381 		}
382 #ifdef notyet
383                 if (boothowto & RB_FASTBOOT) {
384 			(void)subyte(--ucp, 'f');
385 			options = 1;
386 		}
387 #endif
388 		if (options == 0)
389 			(void)subyte(--ucp, '-');
390 		(void)subyte(--ucp, '-');		/* leading hyphen */
391 		arg1 = ucp;
392 
393 		/*
394 		 * Move out the file name (also arg 0).
395 		 */
396 		for (i = strlen(path) + 1; i >= 0; i--)
397 			(void)subyte(--ucp, path[i]);
398 		arg0 = ucp;
399 
400 		/*
401 		 * Move out the arg pointers.
402 		 */
403 		uap = (char **)((int)ucp & ~(NBPW-1));
404 		(void)suword((caddr_t)--uap, 0);	/* terminator */
405 		(void)suword((caddr_t)--uap, (int)arg1);
406 		(void)suword((caddr_t)--uap, (int)arg0);
407 
408 		/*
409 		 * Point at the arguments.
410 		 */
411 		args.fname = arg0;
412 		args.argv = uap;
413 		args.envv = NULL;
414 
415 		/*
416 		 * Now try to exec the program.  If can't for any reason
417 		 * other than it doesn't exist, complain.
418 		 */
419 		if ((error = execve(p, &args, &retval)) == 0)
420 			return;
421 		if (error != ENOENT)
422 			printf("exec %s: error %d\n", path, error);
423 	}
424 	printf("init: not found\n");
425 	panic("no init");
426 }
427