1 /*
2 * linux/init/main.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 #define __LIBRARY__
8 #include <unistd.h>
9 #include <time.h>
10
11 /*
12 * we need this inline - forking from kernel space will result
13 * in NO COPY ON WRITE (!!!), until an execve is executed. This
14 * is no problem, but for the stack. This is handled by not letting
15 * main() use the stack at all after fork(). Thus, no function
16 * calls - which means inline code for fork too, as otherwise we
17 * would use the stack upon exit from 'fork()'.
18 *
19 * Actually only pause and fork are needed inline, so that there
20 * won't be any messing with the stack from main(), but we define
21 * some others too.
22 */
23 static inline _syscall0(int,fork)
24 static inline _syscall0(int,pause)
25 static inline _syscall1(int,setup,void *,BIOS)
26 static inline _syscall0(int,sync)
27
28 #include <linux/tty.h>
29 #include <linux/sched.h>
30 #include <linux/head.h>
31 #include <asm/system.h>
32 #include <asm/io.h>
33
34 #include <stddef.h>
35 #include <stdarg.h>
36 #include <unistd.h>
37 #include <fcntl.h>
38 #include <sys/types.h>
39
40 #include <linux/fs.h>
41
42 static char printbuf[1024];
43
44 extern int vsprintf();
45 extern void init(void);
46 extern void blk_dev_init(void);
47 extern void chr_dev_init(void);
48 extern void hd_init(void);
49 extern void floppy_init(void);
50 extern void mem_init(long start, long end);
51 extern long rd_init(long mem_start, int length);
52 extern long kernel_mktime(struct tm * tm);
53 extern long startup_time;
54
55 /*
56 * This is set up by the setup-routine at boot-time
57 */
58 #define EXT_MEM_K (*(unsigned short *)0x90002)
59 #define DRIVE_INFO (*(struct drive_info *)0x90080)
60 #define ORIG_ROOT_DEV (*(unsigned short *)0x901FC)
61
62 /*
63 * Yeah, yeah, it's ugly, but I cannot find how to do this correctly
64 * and this seems to work. I anybody has more info on the real-time
65 * clock I'd be interested. Most of this was trial and error, and some
66 * bios-listing reading. Urghh.
67 */
68
69 #define CMOS_READ(addr) ({ \
70 outb_p(0x80|addr,0x70); \
71 inb_p(0x71); \
72 })
73
74 #define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
75
76 static void time_init(void)
77 {
78 struct tm time;
79
80 do {
81 time.tm_sec = CMOS_READ(0);
82 time.tm_min = CMOS_READ(2);
83 time.tm_hour = CMOS_READ(4);
84 time.tm_mday = CMOS_READ(7);
85 time.tm_mon = CMOS_READ(8);
86 time.tm_year = CMOS_READ(9);
87 } while (time.tm_sec != CMOS_READ(0));
88 BCD_TO_BIN(time.tm_sec);
89 BCD_TO_BIN(time.tm_min);
90 BCD_TO_BIN(time.tm_hour);
91 BCD_TO_BIN(time.tm_mday);
92 BCD_TO_BIN(time.tm_mon);
93 BCD_TO_BIN(time.tm_year);
94 time.tm_mon--;
95 startup_time = kernel_mktime(&time);
96 }
97
98 static long memory_end = 0;
99 static long buffer_memory_end = 0;
100 static long main_memory_start = 0;
101
102 struct drive_info { char dummy[32]; } drive_info;
103
104 void main(void) /* This really IS void, no error here. */
105 { /* The startup routine assumes (well, ...) this */
106 /*
107 * Interrupts are still disabled. Do necessary setups, then
108 * enable them
109 */
110 ROOT_DEV = ORIG_ROOT_DEV;
111 drive_info = DRIVE_INFO;
112 memory_end = (1<<20) + (EXT_MEM_K<<10);
113 memory_end &= 0xfffff000;
114 if (memory_end > 16*1024*1024)
115 memory_end = 16*1024*1024;
116 if (memory_end > 12*1024*1024)
117 buffer_memory_end = 4*1024*1024;
118 else if (memory_end > 6*1024*1024)
119 buffer_memory_end = 2*1024*1024;
120 else
121 buffer_memory_end = 1*1024*1024;
122 main_memory_start = buffer_memory_end;
123 #ifdef RAMDISK
124 main_memory_start += rd_init(main_memory_start, RAMDISK*1024);
125 #endif
126 mem_init(main_memory_start,memory_end);
127 trap_init();
128 blk_dev_init();
129 chr_dev_init();
130 tty_init();
131 time_init();
132 sched_init();
133 buffer_init(buffer_memory_end);
134 hd_init();
135 floppy_init();
136 sti();
137 move_to_user_mode();
138 if (!fork()) { /* we count on this going ok */
139 init();
140 }
141 /*
142 * NOTE!! For any other task 'pause()' would mean we have to get a
143 * signal to awaken, but task0 is the sole exception (see 'schedule()')
144 * as task 0 gets activated at every idle moment (when no other tasks
145 * can run). For task0 'pause()' just means we go check if some other
146 * task can run, and if not we return here.
147 */
148 for(;;) pause();
149 }
150
151 static int printf(const char *fmt, ...)
152 {
153 va_list args;
154 int i;
155
156 va_start(args, fmt);
157 write(1,printbuf,i=vsprintf(printbuf, fmt, args));
158 va_end(args);
159 return i;
160 }
161
162 static char * argv_rc[] = { "/bin/sh", NULL };
163 static char * envp_rc[] = { "HOME=/", NULL };
164
165 static char * argv[] = { "-/bin/sh",NULL };
166 static char * envp[] = { "HOME=/usr/root", NULL };
167
168 void init(void)
169 {
170 int pid,i;
171
172 setup((void *) &drive_info);
173 (void) open("/dev/tty0",O_RDWR,0);
174 (void) dup(0);
175 (void) dup(0);
176 printf("%d buffers = %d bytes buffer space\n\r",NR_BUFFERS,
177 NR_BUFFERS*BLOCK_SIZE);
178 printf("Free mem: %d bytes\n\r",memory_end-main_memory_start);
179 if (!(pid=fork())) {
180 close(0);
181 if (open("/etc/rc",O_RDONLY,0))
182 _exit(1);
183 execve("/bin/sh",argv_rc,envp_rc);
184 _exit(2);
185 }
186 if (pid>0)
187 while (pid != wait(&i))
188 /* nothing */;
189 while (1) {
190 if ((pid=fork())<0) {
191 printf("Fork failed in init\r\n");
192 continue;
193 }
194 if (!pid) {
195 close(0);close(1);close(2);
196 setsid();
197 (void) open("/dev/tty0",O_RDWR,0);
198 (void) dup(0);
199 (void) dup(0);
200 _exit(execve("/bin/sh",argv,envp));
201 }
202 while (1)
203 if (pid == wait(&i))
204 break;
205 printf("\n\rchild %d died with code %04x\n\r",pid,i);
206 sync();
207 }
208 _exit(0); /* NOTE! _exit, not exit() */
209 }
210
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.