352 lines
9.3 KiB
C
352 lines
9.3 KiB
C
/*
|
|
* Copyright (c) 1986 Regents of the University of California.
|
|
* All rights reserved. The Berkeley software License Agreement
|
|
* specifies the terms and conditions for redistribution.
|
|
*/
|
|
#include <sys/param.h>
|
|
#include <sys/user.h>
|
|
#include <sys/fs.h>
|
|
#include <sys/mount.h>
|
|
#include <sys/map.h>
|
|
#include <sys/proc.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/inode.h>
|
|
#include <sys/conf.h>
|
|
#include <sys/buf.h>
|
|
#include <sys/fcntl.h>
|
|
#include <sys/vm.h>
|
|
#include <sys/clist.h>
|
|
#include <sys/reboot.h>
|
|
#include <sys/systm.h>
|
|
#include <sys/kernel.h>
|
|
#include <sys/namei.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/kconfig.h>
|
|
#include <sys/rdisk.h>
|
|
|
|
u_int swapstart, nswap; /* start and size of swap space */
|
|
size_t physmem; /* total amount of physical memory */
|
|
int boothowto; /* reboot flags, from boot */
|
|
|
|
/*
|
|
* Initialize hash links for buffers.
|
|
*/
|
|
static void
|
|
bhinit()
|
|
{
|
|
register int i;
|
|
register struct bufhd *bp;
|
|
|
|
for (bp = bufhash, i = 0; i < BUFHSZ; i++, bp++)
|
|
bp->b_forw = bp->b_back = (struct buf *)bp;
|
|
}
|
|
|
|
/*
|
|
* Initialize the buffer I/O system by freeing
|
|
* all buffers and setting all device buffer lists to empty.
|
|
*/
|
|
static void
|
|
binit()
|
|
{
|
|
register struct buf *bp;
|
|
register int i;
|
|
caddr_t paddr;
|
|
|
|
for (bp = bfreelist; bp < &bfreelist[BQUEUES]; bp++)
|
|
bp->b_forw = bp->b_back = bp->av_forw = bp->av_back = bp;
|
|
paddr = bufdata;
|
|
for (i = 0; i < NBUF; i++, paddr += MAXBSIZE) {
|
|
bp = &buf[i];
|
|
bp->b_dev = NODEV;
|
|
bp->b_bcount = 0;
|
|
bp->b_addr = paddr;
|
|
binshash(bp, &bfreelist[BQ_AGE]);
|
|
bp->b_flags = B_BUSY|B_INVAL;
|
|
brelse(bp);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Initialize clist by freeing all character blocks, then count
|
|
* number of character devices. (Once-only routine)
|
|
*/
|
|
static void
|
|
cinit()
|
|
{
|
|
register int ccp;
|
|
register struct cblock *cp;
|
|
|
|
ccp = (int)cfree;
|
|
ccp = (ccp + CROUND) & ~CROUND;
|
|
for (cp = (struct cblock *)ccp; cp <= &cfree[NCLIST - 1]; cp++) {
|
|
cp->c_next = cfreelist;
|
|
cfreelist = cp;
|
|
cfreecount += CBSIZE;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Initialization code.
|
|
* Called from cold start routine as
|
|
* soon as a stack and segmentation
|
|
* have been established.
|
|
* Functions:
|
|
* clear and free user core
|
|
* turn on clock
|
|
* hand craft 0th process
|
|
* call all initialization routines
|
|
* fork - process 0 to schedule
|
|
* - process 1 execute bootstrap
|
|
*/
|
|
int
|
|
main()
|
|
{
|
|
register struct proc *p;
|
|
register int i;
|
|
register struct fs *fs = NULL;
|
|
char inbuf[4];
|
|
char inch;
|
|
int s __attribute__((unused));
|
|
|
|
startup();
|
|
printf ("\n%s", version);
|
|
kconfig();
|
|
cnidentify();
|
|
|
|
/*
|
|
* Set up system process 0 (swapper).
|
|
*/
|
|
p = &proc[0];
|
|
p->p_addr = (size_t) &u;
|
|
p->p_stat = SRUN;
|
|
p->p_flag |= SLOAD | SSYS;
|
|
p->p_nice = NZERO;
|
|
|
|
u.u_procp = p; /* init user structure */
|
|
u.u_cmask = CMASK;
|
|
u.u_lastfile = -1;
|
|
for (i = 1; i < NGROUPS; i++)
|
|
u.u_groups[i] = NOGROUP;
|
|
for (i = 0; i < sizeof(u.u_rlimit)/sizeof(u.u_rlimit[0]); i++)
|
|
u.u_rlimit[i].rlim_cur = u.u_rlimit[i].rlim_max =
|
|
RLIM_INFINITY;
|
|
|
|
/* Initialize signal state for process 0 */
|
|
siginit (p);
|
|
|
|
/*
|
|
* Initialize tables, protocols, and set up well-known inodes.
|
|
*/
|
|
#ifdef LOG_ENABLED
|
|
loginit();
|
|
#endif
|
|
coutinit();
|
|
cinit();
|
|
pqinit();
|
|
ihinit();
|
|
bhinit();
|
|
binit();
|
|
nchinit();
|
|
clkstart();
|
|
|
|
/* Attach services. */
|
|
struct conf_service *svc;
|
|
for (svc = conf_service_init; svc->svc_attach != NULL; svc++)
|
|
(*svc->svc_attach)();
|
|
|
|
s = spl0();
|
|
rdisk_init();
|
|
|
|
if (rootdev == NODEV)
|
|
rootdev = get_boot_device();
|
|
if (swapdev == NODEV)
|
|
swapdev = get_swap_device();
|
|
pipedev = rootdev;
|
|
|
|
/* Mount a root filesystem. */
|
|
for (;;) {
|
|
if(rootdev!=-1)
|
|
{
|
|
fs = mountfs (rootdev, (boothowto & RB_RDONLY) ? MNT_RDONLY : 0,
|
|
(struct inode*) 0);
|
|
}
|
|
if (fs)
|
|
break;
|
|
printf ("No root filesystem available!\n");
|
|
// rdisk_list_partitions(RDISK_FS);
|
|
retry:
|
|
printf ("Please enter device to boot from (press ? to list): ");
|
|
inch=0;
|
|
inbuf[0] = inbuf[1] = inbuf[2] = inbuf[3] = 0;
|
|
while((inch=cngetc()) != '\r')
|
|
{
|
|
switch(inch)
|
|
{
|
|
case '?':
|
|
printf("?\n");
|
|
rdisk_list_partitions(RDISK_FS);
|
|
printf ("Please enter device to boot from (press ? to list): ");
|
|
break;
|
|
default:
|
|
printf("%c",inch);
|
|
inbuf[0] = inbuf[1];
|
|
inbuf[1] = inbuf[2];
|
|
inbuf[2] = inbuf[3];
|
|
inbuf[3] = inch;
|
|
break;
|
|
}
|
|
}
|
|
|
|
inch = 0;
|
|
if(inbuf[0]=='r' && inbuf[1]=='d')
|
|
{
|
|
if(inbuf[2]>='0' && inbuf[2] < '0'+rdisk_num_disks())
|
|
{
|
|
if(inbuf[3]>='a' && inbuf[3]<='d')
|
|
{
|
|
rootdev=makedev(inbuf[2]-'0',inbuf[3]-'a'+1);
|
|
inch = 1;
|
|
}
|
|
}
|
|
} else if(inbuf[1]=='r' && inbuf[2]=='d') {
|
|
if(inbuf[3]>='0' && inbuf[3] < '0'+rdisk_num_disks())
|
|
{
|
|
rootdev=makedev(inbuf[3]-'0',0);
|
|
inch = 1;
|
|
}
|
|
} else if(inbuf[3] == 0) {
|
|
inch = 1;
|
|
}
|
|
if(inch==0)
|
|
{
|
|
printf("\nUnknown device.\n\n");
|
|
goto retry;
|
|
}
|
|
printf ("\n\n");
|
|
}
|
|
printf ("phys mem = %u kbytes\n", physmem / 1024);
|
|
printf ("user mem = %u kbytes\n", MAXMEM / 1024);
|
|
if(minor(rootdev)==0)
|
|
{
|
|
printf ("root dev = rd%d (%d,%d)\n",
|
|
major(rootdev),
|
|
major(rootdev), minor(rootdev)
|
|
);
|
|
} else {
|
|
printf ("root dev = rd%d%c (%d,%d)\n",
|
|
major(rootdev), 'a'+minor(rootdev)-1,
|
|
major(rootdev), minor(rootdev)
|
|
);
|
|
}
|
|
|
|
printf ("root size = %u kbytes\n", fs->fs_fsize * DEV_BSIZE / 1024);
|
|
mount[0].m_inodp = (struct inode*) 1; /* XXX */
|
|
mount_updname (fs, "/", "root", 1, 4);
|
|
time.tv_sec = fs->fs_time;
|
|
boottime = time;
|
|
|
|
/* Find a swap file. */
|
|
swapstart = 1;
|
|
while(swapdev == -1)
|
|
{
|
|
printf("Please enter swap device (press ? to list): ");
|
|
inbuf[0] = inbuf[1] = inbuf[2] = inbuf[3] = 0;
|
|
while((inch = cngetc())!='\r')
|
|
{
|
|
switch(inch)
|
|
{
|
|
case '?':
|
|
printf("?\n");
|
|
rdisk_list_partitions(RDISK_SWAP);
|
|
printf("Please enter swap device (press ? to list): ");
|
|
break;
|
|
default:
|
|
printf("%c",inch);
|
|
inbuf[0] = inbuf[1];
|
|
inbuf[1] = inbuf[2];
|
|
inbuf[2] = inbuf[3];
|
|
inbuf[3] = inch;
|
|
break;
|
|
}
|
|
}
|
|
inch = 0;
|
|
if(inbuf[0]=='r' && inbuf[1]=='d')
|
|
{
|
|
if(inbuf[2]>='0' && inbuf[2] < '0'+rdisk_num_disks())
|
|
{
|
|
if(inbuf[3]>='a' && inbuf[3]<='d')
|
|
{
|
|
swapdev=makedev(inbuf[2]-'0',inbuf[3]-'a'+1);
|
|
inch = 1;
|
|
}
|
|
}
|
|
} else if(inbuf[1]=='r' && inbuf[2]=='d') {
|
|
if(inbuf[3]>='0' && inbuf[3] < '0'+rdisk_num_disks())
|
|
{
|
|
swapdev=makedev(inbuf[3]-'0',0);
|
|
inch = 1;
|
|
}
|
|
}
|
|
|
|
if(minor(swapdev)!=0)
|
|
{
|
|
if(partition_type(swapdev)!=RDISK_SWAP)
|
|
{
|
|
printf("\nNot a swap partition!\n\n");
|
|
swapdev=-1;
|
|
}
|
|
}
|
|
}
|
|
nswap = rdsize(swapdev);
|
|
|
|
if(minor(swapdev)==0)
|
|
{
|
|
printf ("swap dev = rd%d (%d,%d)\n",
|
|
major(swapdev),
|
|
major(swapdev), minor(swapdev)
|
|
);
|
|
} else {
|
|
printf ("swap dev = rd%d%c (%d,%d)\n",
|
|
major(swapdev), 'a'+minor(swapdev)-1,
|
|
major(swapdev), minor(swapdev)
|
|
);
|
|
}
|
|
(*bdevsw[major(swapdev)].d_open)(swapdev, FREAD|FWRITE, S_IFBLK);
|
|
printf ("swap size = %u kbytes\n", nswap * DEV_BSIZE / 1024);
|
|
if (nswap <= 0)
|
|
panic ("zero swap size"); /* don't want to panic, but what ? */
|
|
mfree (swapmap, nswap, swapstart);
|
|
|
|
/* Kick off timeout driven events by calling first time. */
|
|
schedcpu (0);
|
|
|
|
/* Set up the root file system. */
|
|
rootdir = iget (rootdev, &mount[0].m_filsys, (ino_t) ROOTINO);
|
|
iunlock (rootdir);
|
|
u.u_cdir = iget (rootdev, &mount[0].m_filsys, (ino_t) ROOTINO);
|
|
iunlock (u.u_cdir);
|
|
u.u_rdir = NULL;
|
|
|
|
/*
|
|
* Make init process.
|
|
*/
|
|
if (newproc (0) == 0) {
|
|
/* Parent process with pid 0: swapper.
|
|
* No return from sched. */
|
|
sched();
|
|
}
|
|
/* Child process with pid 1: init. */
|
|
s = splhigh();
|
|
p = u.u_procp;
|
|
p->p_dsize = icodeend - icode;
|
|
p->p_daddr = USER_DATA_START;
|
|
p->p_ssize = 1024; /* one kbyte of stack */
|
|
p->p_saddr = USER_DATA_END - 1024;
|
|
bcopy ((caddr_t) icode, (caddr_t) USER_DATA_START, icodeend - icode);
|
|
/*
|
|
* return goes to location 0 of user init code
|
|
* just copied out.
|
|
*/
|
|
return 0;
|
|
}
|