root/init/main.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. _syscall0
  2. sprintf
  3. time_init
  4. start_kernel
  5. printf
  6. init

   1 /*
   2  *  linux/init/main.c
   3  *
   4  *  Copyright (C) 1991, 1992  Linus Torvalds
   5  */
   6 
   7 #include <stdarg.h>
   8 
   9 #include <asm/system.h>
  10 #include <asm/io.h>
  11 
  12 #include <linux/mktime.h>
  13 #include <linux/types.h>
  14 #include <linux/fcntl.h>
  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 
  21 extern unsigned long * prof_buffer;
  22 extern unsigned long prof_len;
  23 extern int end;
  24 extern char *linux_banner;
  25 
  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  */
  38 static inline _syscall0(int,idle)
     /* [previous][next][first][last][top][bottom][index][help] */
  39 static inline _syscall0(int,fork)
  40 static inline _syscall0(int,pause)
  41 static inline _syscall1(int,setup,void *,BIOS)
  42 static inline _syscall0(int,sync)
  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)
  47 static inline _syscall3(int,open,const char *,file,int,flag,int,mode)
  48 static inline _syscall1(int,close,int,fd)
  49 static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
  50 
  51 static inline pid_t wait(int * wait_stat)
  52 {
  53         return waitpid(-1,wait_stat,0);
  54 }
  55 
  56 static char printbuf[1024];
  57 
  58 extern int vsprintf();
  59 extern void init(void);
  60 extern void init_IRQ(void);
  61 extern long blk_dev_init(long,long);
  62 extern long chr_dev_init(long,long);
  63 extern void floppy_init(void);
  64 extern void sock_init(void);
  65 extern long rd_init(long mem_start, int length);
  66 extern long kernel_mktime(struct mktime * time);
  67 
  68 #ifdef CONFIG_SCSI
  69 extern void scsi_dev_init(void);
  70 #endif
  71 
  72 static int sprintf(char * str, const char *fmt, ...)
     /* [previous][next][first][last][top][bottom][index][help] */
  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 }
  82 
  83 /*
  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)
  88 #define SCREEN_INFO (*(struct screen_info *)0x90000)
  89 #define ORIG_ROOT_DEV (*(unsigned short *)0x901FC)
  90 #define AUX_DEVICE_INFO (*(unsigned char *)0x901FF)
  91 
  92 /*
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
 107 {
 108         struct mktime time;
 109 
 110         do {
 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--;
 125         startup_time = kernel_mktime(&time);
 126 }
 127 
 128 static unsigned long memory_start = 0; /* After mem_init, stores the */
 129                                        /* amount of free user memory */
 130 static unsigned long memory_end = 0;
 131 static unsigned long low_memory_start = 0;
 132 
 133 static char term[32];
 134 
 135 static char * argv_init[] = { "/bin/init", NULL };
 136 static char * envp_init[] = { "HOME=/", NULL, NULL };
 137 
 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 };
 143 
 144 struct drive_info { char dummy[32]; } drive_info;
 145 struct screen_info screen_info;
 146 
 147 unsigned char aux_device_present;
 148 
 149 void start_kernel(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 150 {
 151 /*
 152  * Interrupts are still disabled. Do necessary setups, then
 153  * enable them
 154  */
 155         ROOT_DEV = ORIG_ROOT_DEV;
 156         drive_info = DRIVE_INFO;
 157         screen_info = SCREEN_INFO;
 158         aux_device_present = AUX_DEVICE_INFO;
 159         sprintf(term, "TERM=con%dx%d", ORIG_VIDEO_COLS, ORIG_VIDEO_LINES);
 160         envp[1] = term; 
 161         envp_rc[1] = term;
 162         envp_init[1] = term;
 163         memory_end = (1<<20) + (EXT_MEM_K<<10);
 164         memory_end &= 0xfffff000;
 165         if (memory_end > 16*1024*1024)
 166                 memory_end = 16*1024*1024;
 167         memory_start = 1024*1024;
 168         low_memory_start = (unsigned long) &end;
 169         low_memory_start += 0xfff;
 170         low_memory_start &= 0xfffff000;
 171         trap_init();
 172         init_IRQ();
 173         sched_init();
 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
 180         memory_start = chr_dev_init(memory_start,memory_end);
 181         memory_start = blk_dev_init(memory_start,memory_end);
 182         mem_init(low_memory_start,memory_start,memory_end);
 183         buffer_init();
 184         time_init();
 185         floppy_init();
 186         sock_init();
 187         sti();
 188 #ifdef CONFIG_SCSI
 189         scsi_dev_init();
 190 #endif
 191         sti();
 192         move_to_user_mode();
 193         if (!fork())            /* we count on this going ok */
 194                 init();
 195 /*
 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  *
 202  * Right now task[0] just does a infinite idle loop.
 203  */
 204         for(;;)
 205                 idle();
 206 }
 207 
 208 static int printf(const char *fmt, ...)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 220 {
 221         int pid,i;
 222 
 223         setup((void *) &drive_info);
 224         (void) open("/dev/tty1",O_RDWR,0);
 225         (void) dup(0);
 226         (void) dup(0);
 227 
 228         printf(linux_banner);
 229         execve("/etc/init",argv_init,envp_init);
 230         execve("/bin/init",argv_init,envp_init);
 231         /* if this fails, fall through to original stuff */
 232 
 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();
 251                         (void) open("/dev/tty1",O_RDWR,0);
 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();
 261         }
 262         _exit(0);       /* NOTE! _exit, not exit() */
 263 }

/* [previous][next][first][last][top][bottom][index][help] */