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