|
|
1.1.1.2 root 1: /*
2: * linux/init/main.c
3: *
1.1.1.10! root 4: * Copyright (C) 1991, 1992 Linus Torvalds
1.1.1.2 root 5: */
6:
1.1.1.7 root 7: #include <stdarg.h>
1.1 root 8: #include <time.h>
9:
1.1.1.7 root 10: #include <asm/system.h>
11: #include <asm/io.h>
12:
1.1.1.10! root 13: #include <linux/types.h>
1.1.1.9 root 14: #include <linux/fcntl.h>
1.1.1.7 root 15: #include <linux/config.h>
16: #include <linux/sched.h>
17: #include <linux/tty.h>
18: #include <linux/head.h>
19: #include <linux/unistd.h>
20:
1.1 root 21: /*
22: * we need this inline - forking from kernel space will result
23: * in NO COPY ON WRITE (!!!), until an execve is executed. This
24: * is no problem, but for the stack. This is handled by not letting
25: * main() use the stack at all after fork(). Thus, no function
26: * calls - which means inline code for fork too, as otherwise we
27: * would use the stack upon exit from 'fork()'.
28: *
29: * Actually only pause and fork are needed inline, so that there
30: * won't be any messing with the stack from main(), but we define
31: * some others too.
32: */
33: static inline _syscall0(int,fork)
34: static inline _syscall0(int,pause)
1.1.1.2 root 35: static inline _syscall1(int,setup,void *,BIOS)
1.1 root 36: static inline _syscall0(int,sync)
1.1.1.7 root 37: static inline _syscall0(pid_t,setsid)
38: static inline _syscall3(int,write,int,fd,const char *,buf,off_t,count)
39: static inline _syscall1(int,dup,int,fd)
40: static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp)
1.1.1.9 root 41: static inline _syscall3(int,open,const char *,file,int,flag,int,mode)
1.1.1.7 root 42: static inline _syscall1(int,close,int,fd)
43: static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
1.1 root 44:
1.1.1.7 root 45: static inline pid_t wait(int * wait_stat)
46: {
47: return waitpid(-1,wait_stat,0);
48: }
1.1.1.4 root 49:
1.1 root 50: static char printbuf[1024];
51:
52: extern int vsprintf();
53: extern void init(void);
1.1.1.10! root 54: extern void init_IRQ(void);
1.1.1.9 root 55: extern long blk_dev_init(long,long);
56: extern long chr_dev_init(long,long);
1.1 root 57: extern void hd_init(void);
1.1.1.2 root 58: extern void floppy_init(void);
1.1.1.7 root 59: extern void sock_init(void);
1.1.1.3 root 60: extern long rd_init(long mem_start, int length);
1.1 root 61: extern long kernel_mktime(struct tm * tm);
1.1.1.4 root 62:
1.1.1.7 root 63: #ifdef CONFIG_SCSI
64: extern void scsi_dev_init(void);
65: #endif
66:
1.1.1.4 root 67: static int sprintf(char * str, const char *fmt, ...)
68: {
69: va_list args;
70: int i;
71:
72: va_start(args, fmt);
73: i = vsprintf(str, fmt, args);
74: va_end(args);
75: return i;
76: }
1.1 root 77:
78: /*
1.1.1.2 root 79: * This is set up by the setup-routine at boot-time
80: */
81: #define EXT_MEM_K (*(unsigned short *)0x90002)
82: #define DRIVE_INFO (*(struct drive_info *)0x90080)
1.1.1.10! root 83: #define SCREEN_INFO (*(struct screen_info *)0x90000)
1.1.1.2 root 84: #define ORIG_ROOT_DEV (*(unsigned short *)0x901FC)
85:
86: /*
1.1 root 87: * Yeah, yeah, it's ugly, but I cannot find how to do this correctly
88: * and this seems to work. I anybody has more info on the real-time
89: * clock I'd be interested. Most of this was trial and error, and some
90: * bios-listing reading. Urghh.
91: */
92:
93: #define CMOS_READ(addr) ({ \
94: outb_p(0x80|addr,0x70); \
95: inb_p(0x71); \
96: })
97:
98: #define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
99:
100: static void time_init(void)
101: {
102: struct tm time;
103:
104: do {
105: time.tm_sec = CMOS_READ(0);
106: time.tm_min = CMOS_READ(2);
107: time.tm_hour = CMOS_READ(4);
108: time.tm_mday = CMOS_READ(7);
1.1.1.2 root 109: time.tm_mon = CMOS_READ(8);
1.1 root 110: time.tm_year = CMOS_READ(9);
111: } while (time.tm_sec != CMOS_READ(0));
112: BCD_TO_BIN(time.tm_sec);
113: BCD_TO_BIN(time.tm_min);
114: BCD_TO_BIN(time.tm_hour);
115: BCD_TO_BIN(time.tm_mday);
116: BCD_TO_BIN(time.tm_mon);
117: BCD_TO_BIN(time.tm_year);
1.1.1.2 root 118: time.tm_mon--;
1.1 root 119: startup_time = kernel_mktime(&time);
120: }
121:
1.1.1.10! root 122: static unsigned long memory_start = 0;
! 123: static unsigned long memory_end = 0;
! 124:
1.1.1.4 root 125: static char term[32];
126:
1.1.1.5 root 127: static char * argv_init[] = { "/bin/init", NULL };
128: static char * envp_init[] = { "HOME=/", NULL, NULL };
129:
1.1.1.4 root 130: static char * argv_rc[] = { "/bin/sh", NULL };
131: static char * envp_rc[] = { "HOME=/", NULL ,NULL };
132:
133: static char * argv[] = { "-/bin/sh",NULL };
134: static char * envp[] = { "HOME=/usr/root", NULL, NULL };
1.1.1.2 root 135:
136: struct drive_info { char dummy[32]; } drive_info;
1.1.1.10! root 137: struct screen_info screen_info;
1.1.1.2 root 138:
1.1.1.5 root 139: void start_kernel(void)
140: {
1.1 root 141: /*
142: * Interrupts are still disabled. Do necessary setups, then
143: * enable them
144: */
1.1.1.2 root 145: ROOT_DEV = ORIG_ROOT_DEV;
1.1.1.10! root 146: drive_info = DRIVE_INFO;
! 147: screen_info = SCREEN_INFO;
! 148: sprintf(term, "TERM=con%dx%d", ORIG_VIDEO_COLS, ORIG_VIDEO_LINES);
1.1.1.4 root 149: envp[1] = term;
150: envp_rc[1] = term;
1.1.1.5 root 151: envp_init[1] = term;
1.1.1.2 root 152: memory_end = (1<<20) + (EXT_MEM_K<<10);
153: memory_end &= 0xfffff000;
154: if (memory_end > 16*1024*1024)
155: memory_end = 16*1024*1024;
1.1.1.10! root 156: memory_start = 1024*1024;
1.1 root 157: trap_init();
1.1.1.10! root 158: init_IRQ();
1.1.1.7 root 159: sched_init();
1.1.1.10! root 160: memory_start = chr_dev_init(memory_start,memory_end);
! 161: memory_start = blk_dev_init(memory_start,memory_end);
! 162: memory_start = mem_init(memory_start,memory_end);
! 163: buffer_init();
1.1.1.2 root 164: time_init();
1.1.1.7 root 165: printk("Linux version " UTS_RELEASE " " __DATE__ " " __TIME__ "\n");
1.1 root 166: hd_init();
1.1.1.2 root 167: floppy_init();
1.1.1.7 root 168: sock_init();
1.1 root 169: sti();
1.1.1.7 root 170: #ifdef CONFIG_SCSI
171: scsi_dev_init();
172: #endif
1.1 root 173: move_to_user_mode();
174: if (!fork()) { /* we count on this going ok */
175: init();
176: }
177: /*
1.1.1.10! root 178: * task[0] is meant to be used as an "idle" task: it may not sleep, but
! 179: * it might do some general things like count free pages or it could be
! 180: * used to implement a reasonable LRU algorithm for the paging routines:
! 181: * anything that can be useful, but shouldn't take time from the real
! 182: * processes.
! 183: *
! 184: * Right now task[0] just does a infinite loop in user mode.
1.1 root 185: */
1.1.1.4 root 186: for(;;)
1.1.1.10! root 187: /* nothing */ ;
1.1 root 188: }
189:
190: static int printf(const char *fmt, ...)
191: {
192: va_list args;
193: int i;
194:
195: va_start(args, fmt);
196: write(1,printbuf,i=vsprintf(printbuf, fmt, args));
197: va_end(args);
198: return i;
199: }
200:
201: void init(void)
202: {
1.1.1.3 root 203: int pid,i;
1.1 root 204:
1.1.1.2 root 205: setup((void *) &drive_info);
1.1.1.4 root 206: (void) open("/dev/tty1",O_RDWR,0);
1.1 root 207: (void) dup(0);
208: (void) dup(0);
1.1.1.10! root 209: printf("%d buffers = %d bytes buffer space\n\r",nr_buffers,
! 210: nr_buffers*BLOCK_SIZE);
! 211: printf("Free mem: %d bytes\n\r",memory_end-memory_start);
1.1.1.5 root 212:
1.1.1.6 root 213: execve("/etc/init",argv_init,envp_init);
1.1.1.5 root 214: execve("/bin/init",argv_init,envp_init);
215: /* if this fails, fall through to original stuff */
216:
1.1.1.3 root 217: if (!(pid=fork())) {
218: close(0);
219: if (open("/etc/rc",O_RDONLY,0))
220: _exit(1);
221: execve("/bin/sh",argv_rc,envp_rc);
222: _exit(2);
223: }
224: if (pid>0)
225: while (pid != wait(&i))
226: /* nothing */;
227: while (1) {
228: if ((pid=fork())<0) {
229: printf("Fork failed in init\r\n");
230: continue;
231: }
232: if (!pid) {
233: close(0);close(1);close(2);
234: setsid();
1.1.1.4 root 235: (void) open("/dev/tty1",O_RDWR,0);
1.1.1.3 root 236: (void) dup(0);
237: (void) dup(0);
238: _exit(execve("/bin/sh",argv,envp));
239: }
240: while (1)
241: if (pid == wait(&i))
242: break;
243: printf("\n\rchild %d died with code %04x\n\r",pid,i);
244: sync();
1.1 root 245: }
246: _exit(0); /* NOTE! _exit, not exit() */
247: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.