1 #define__LIBRARY__ 2 #include <unistd.h>
3 #include <time.h>
4
5 /* 6 * we need this inline - forking from kernel space will result 7 * in NO COPY ON WRITE (!!!), until an execve is executed. This 8 * is no problem, but for the stack. This is handled by not letting 9 * main() use the stack at all after fork(). Thus, no function 10 * calls - which means inline code for fork too, as otherwise we 11 * would use the stack upon exit from 'fork()'. 12 * 13 * Actually only pause and fork are needed inline, so that there 14 * won't be any messing with the stack from main(), but we define 15 * some others too. 16 */ 17 staticinline_syscall0(int,fork)
18 staticinline_syscall0(int,pause)
19 staticinline_syscall0(int,setup)
20 staticinline_syscall0(int,sync)
21
22 #include <linux/tty.h>
23 #include <linux/sched.h>
24 #include <linux/head.h>
25 #include <asm/system.h>
26 #include <asm/io.h>
27
28 #include <stddef.h>
29 #include <stdarg.h>
30 #include <unistd.h>
31 #include <fcntl.h>
32 #include <sys/types.h>
33
34 #include <linux/fs.h>
35
36 staticcharprintbuf[1024];
37
38 externintvsprintf();
39 externvoidinit(void);
40 externvoidhd_init(void);
41 externlongkernel_mktime(structtm * tm);
42 externlongstartup_time;
43
44 /* 45 * Yeah, yeah, it's ugly, but I cannot find how to do this correctly 46 * and this seems to work. I anybody has more info on the real-time 47 * clock I'd be interested. Most of this was trial and error, and some 48 * bios-listing reading. Urghh. 49 */ 50
51 #defineCMOS_READ(addr) ({ \
52 outb_p(0x80|addr,0x70); \
53 inb_p(0x71); \
54 })
55
56 #defineBCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
57
58 staticvoidtime_init(void)
/* */ 59 { 60 structtmtime;
61
62 do{ 63 time.tm_sec = CMOS_READ(0);
64 time.tm_min = CMOS_READ(2);
65 time.tm_hour = CMOS_READ(4);
66 time.tm_mday = CMOS_READ(7);
67 time.tm_mon = CMOS_READ(8)-1;
68 time.tm_year = CMOS_READ(9);
69 }while (time.tm_sec != CMOS_READ(0));
70 BCD_TO_BIN(time.tm_sec);
71 BCD_TO_BIN(time.tm_min);
72 BCD_TO_BIN(time.tm_hour);
73 BCD_TO_BIN(time.tm_mday);
74 BCD_TO_BIN(time.tm_mon);
75 BCD_TO_BIN(time.tm_year);
76 startup_time = kernel_mktime(&time);
77 } 78
79 void main(void) /* This really IS void, no error here. *//* */ 80 {/* The startup routine assumes (well, ...) this */ 81 /* 82 * Interrupts are still disabled. Do necessary setups, then 83 * enable them 84 */ 85 time_init();
86 tty_init();
87 trap_init();
88 sched_init();
89 buffer_init();
90 hd_init();
91 sti();
92 move_to_user_mode();
93 if (!fork()) {/* we count on this going ok */ 94 init();
95 } 96 /* 97 * NOTE!! For any other task 'pause()' would mean we have to get a 98 * signal to awaken, but task0 is the sole exception (see 'schedule()') 99 * as task 0 gets activated at every idle moment (when no other tasks 100 * can run). For task0 'pause()' just means we go check if some other 101 * task can run, and if not we return here. 102 */ 103 for(;;) pause();
104 } 105
106 staticintprintf(constchar *fmt, ...)
/* */ 107 { 108 va_listargs;
109 inti;
110
111 va_start(args, fmt);
112 write(1,printbuf,i=vsprintf(printbuf, fmt, args));
113 va_end(args);
114 returni;
115 } 116
117 staticchar * argv[] = { "-",NULL};
118 staticchar * envp[] = { "HOME=/usr/root", NULL};
119
120 voidinit(void)
/* */ 121 { 122 inti,j;
123
124 setup();
125 if (!fork())
126 _exit(execve("/bin/update",NULL,NULL));
127 (void) open("/dev/tty0",O_RDWR,0);
128 (void) dup(0);
129 (void) dup(0);
130 printf("%d buffers = %d bytes buffer space\n\r",NR_BUFFERS,
131 NR_BUFFERS*BLOCK_SIZE);
132 printf(" Ok.\n\r");
133 if ((i=fork())<0)
134 printf("Fork failed in init\r\n");
135 elseif (!i) { 136 close(0);close(1);close(2);
137 setsid();
138 (void) open("/dev/tty0",O_RDWR,0);
139 (void) dup(0);
140 (void) dup(0);
141 _exit(execve("/bin/sh",argv,envp));
142 } 143 j=wait(&i);
144 printf("child %d died with code %04x\n",j,i);
145 sync();
146 _exit(0); /* NOTE! _exit, not exit() */ 147 }