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