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