# Define _ LIBRARY __# include
# Include time. h>/** we need this inline-forking from kernel space will result * in no copy on write (!!!), Until an execve is executed. this * is no problem, but for the stack. this is handled by not letting * main () use the stack at all after fork (). thus, no function * CILS-which means inline code for fork too, as otherwise we * wocould use the stack upon exit from 'fork ()'. ** Actually only pause and fork are needed inline, so that there * won't be any messing with the stack from main (), but we define * some others too. */static inline _ syscall0 (int, fork) static inline _ syscall0 (int, pause) static inline _ syscall0 (int, setup) static inline _ syscall0 (int, sync) # include
# Include
# Include
# Include system. h> # include
# Include
# Include
# Include
# Include
# Include
Static char printbuf [1024]; extern int vsprintf (); extern void init (void); extern void hd_init (void); extern long kernel_mktime (struct tm * tm ); extern long startup_time;/** Yeah, yeah, it's uugly, but I cannot find how to do this correctly * and this seems to work. I anybody has more info on the real-time * clock I 'd be interested. most of this was trial and error, and some * bios-listing reading. urgh H. */# define CMOS_READ (addr) ({// disable NMI (unshielded interrupt) outb_p (0x80 | addr, 0x70);/inb_p (0x71 ); /}) # define BCD_TO_BIN (val) = (val) & 15) + (val)> 4) * 10) // Binary-encoded decimal representation of static void time_init (void) {struct tm time; do {time. tm_sec = CMOS_READ (0); time. tm_min = CMOS_READ (2); time. tm_hour = CMOS_READ (4); time. tm_mday = CMOS_READ (7); time. tm_mon = CMOS_READ (8)-1; time. tm_year = CMOS_READ (9);} while (time. tm_sec! = CMOS_READ (0); // The time Structure BCD_TO_BIN (time. tm_sec); BCD_TO_BIN (time. tm_min); BCD_TO_BIN (time. tm_hour); BCD_TO_BIN (time. tm_mday); BCD_TO_BIN (time. tm_mon); BCD_TO_BIN (time. tm_year); startup_time = kernel_mktime (& time);} void main (void)/* This really IS void, no error here. */{/* The startup routine assumes (well ,...) this * // ** Interrupts are still disabled. do necessary setups, then * enable them */Time_init (); tty_init (); trap_init (); sched_init (); buffer_init (); hd_init (); sti (); move_to_user_mode (); // transfer to user mode if (! Fork () {/* we count on this going OK */init () ;}/ ** NOTE !! For any other task 'pause () 'wocould mean we have to get a * signal to awaken, but task0 is the sole exception (see 'schedule ()') * as task 0 gets activated at every idle moment (when no other tasks * can run ). for task0 'pause () 'just means we go check if some other * task can run, and if not we return here. */for (;) pause (); // pause task0 and run other processes cyclically, there is actually only one 0 task} static int printf (const char * fmt ,...) {Va_list args; int I; va_start (args, fmt); write (1, printbuf, I = vsprintf (printbuf, fmt, args); va_end (args); return I ;} static char * argv [] = {"-", NULL}; static char * envp [] = {"HOME =/usr/root", NULL}; void init (void) {int I, j; setup (); // read the hard disk information, store the information in start_buffer-> B _data, save the partition information, and register the root super block if (! Fork () _ exit (execve ("/bin/update", NULL, NULL); (void) open ("/dev/tty0", O_RDWR, 0 ); (void) dup (0); // copy a tty0 (void) dup (0 ); // copy another tty0printf ("% d buffers = % d bytes buffer space/n/r", NR_BUFFERS, NR_BUFFERS * BLOCK_SIZE); printf ("OK. /n/r "); if (I = fork () // copy the current process printf (" Fork failed in init/r/n "); else if (! I) {// if close (0); close (1); close (2); // close the three opened tty0 files setsid (); (void) open ("/dev/tty0", O_RDWR, 0); (void) dup (0); (void) dup (0 ); _ exit (execve ("/bin/sh", argv, envp); // execute shell} j = wait (& I ); printf ("child % d died with code % 04x/n", j, I); sync (); _ exit (0);/* NOTE! _ Exit, not exit ()*/}