home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / init / main.c next >
Encoding:
C/C++ Source or Header  |  1995-02-24  |  11.0 KB  |  480 lines

  1. /*
  2.  *  linux/init/main.c
  3.  *
  4.  *  Copyright (C) 1991, 1992  Linus Torvalds
  5.  */
  6.  
  7. #define __KERNEL_SYSCALLS__
  8. #include <stdarg.h>
  9.  
  10. #include <asm/system.h>
  11. #include <asm/io.h>
  12.  
  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. #include <linux/string.h>
  21. #include <linux/timer.h>
  22. #include <linux/fs.h>
  23. #include <linux/ctype.h>
  24. #include <linux/delay.h>
  25. #include <linux/utsname.h>
  26. #include <linux/ioport.h>
  27. #include <linux/hdreg.h>
  28. #include <linux/mm.h>
  29.  
  30. #include <asm/bugs.h>
  31.  
  32. extern unsigned long * prof_buffer;
  33. extern unsigned long prof_len;
  34. extern char etext, end;
  35. extern char *linux_banner;
  36.  
  37. static char printbuf[1024];
  38.  
  39. extern int console_loglevel;
  40.  
  41. extern void init(void);
  42. extern void init_IRQ(void);
  43. extern void init_modules(void);
  44. extern long console_init(long, long);
  45. extern long kmalloc_init(long,long);
  46. extern long blk_dev_init(long,long);
  47. extern long chr_dev_init(long,long);
  48. extern void sock_init(void);
  49. extern long rd_init(long mem_start, int length);
  50. unsigned long net_dev_init(unsigned long, unsigned long);
  51. extern long bios32_init(long, long);
  52.  
  53. extern void bmouse_setup(char *str, int *ints);
  54. extern void eth_setup(char *str, int *ints);
  55. extern void xd_setup(char *str, int *ints);
  56. extern void floppy_setup(char *str, int *ints);
  57. extern void mcd_setup(char *str, int *ints);
  58. extern void aztcd_setup(char *str, int *ints);
  59. extern void st_setup(char *str, int *ints);
  60. extern void st0x_setup(char *str, int *ints);
  61. extern void tmc8xx_setup(char *str, int *ints);
  62. extern void t128_setup(char *str, int *ints);
  63. extern void pas16_setup(char *str, int *ints);
  64. extern void generic_NCR5380_setup(char *str, int *intr);
  65. extern void aha152x_setup(char *str, int *ints);
  66. extern void aha1542_setup(char *str, int *ints);
  67. extern void aha274x_setup(char *str, int *ints);
  68. extern void buslogic_setup(char *str, int *ints);
  69. extern void scsi_luns_setup(char *str, int *ints);
  70. extern void sound_setup(char *str, int *ints);
  71. #ifdef CONFIG_SBPCD
  72. extern void sbpcd_setup(char *str, int *ints);
  73. #endif CONFIG_SBPCD
  74. #ifdef CONFIG_CDU31A
  75. extern void cdu31a_setup(char *str, int *ints);
  76. #endif CONFIG_CDU31A
  77. #ifdef CONFIG_CDU535
  78. extern void sonycd535_setup(char *str, int *ints);
  79. #endif CONFIG_CDU535
  80. void ramdisk_setup(char *str, int *ints);
  81.  
  82. #ifdef CONFIG_SYSVIPC
  83. extern void ipc_init(void);
  84. #endif
  85. #ifdef CONFIG_SCSI
  86. extern unsigned long scsi_dev_init(unsigned long, unsigned long);
  87. #endif
  88.  
  89. /*
  90.  * Boot command-line arguments
  91.  */
  92. #define MAX_INIT_ARGS 8
  93. #define MAX_INIT_ENVS 8
  94.  
  95. extern void time_init(void);
  96.  
  97. static unsigned long memory_start = 0;
  98. static unsigned long memory_end = 0;
  99.  
  100. static char term[21];
  101. int rows, cols;
  102.  
  103. int ramdisk_size;
  104. int root_mountflags = 0;
  105.  
  106. static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, };
  107. static char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", term, NULL, };
  108.  
  109. static char * argv_rc[] = { "/bin/sh", NULL };
  110. static char * envp_rc[] = { "HOME=/", term, NULL };
  111.  
  112. static char * argv[] = { "-/bin/sh",NULL };
  113. static char * envp[] = { "HOME=/usr/root", term, NULL };
  114.  
  115. char *get_options(char *str, int *ints)
  116. {
  117.     char *cur = str;
  118.     int i=1;
  119.  
  120.     while (cur && isdigit(*cur) && i <= 10) {
  121.         ints[i++] = simple_strtoul(cur,NULL,0);
  122.         if ((cur = strchr(cur,',')) != NULL)
  123.             cur++;
  124.     }
  125.     ints[0] = i-1;
  126.     return(cur);
  127. }
  128.  
  129. struct {
  130.     char *str;
  131.     void (*setup_func)(char *, int *);
  132. } bootsetups[] = {
  133.     { "reserve=", reserve_setup },
  134.     { "ramdisk=", ramdisk_setup },
  135. #ifdef CONFIG_BUGi386
  136.     { "no-hlt", no_halt },
  137.     { "no387", no_387 },
  138. #endif
  139. #ifdef CONFIG_INET
  140.     { "ether=", eth_setup },
  141. #endif
  142. #ifdef CONFIG_SCSI
  143.     { "max_scsi_luns=", scsi_luns_setup },
  144. #endif
  145. #ifdef CONFIG_BLK_DEV_IDE
  146.     { "hda=", hda_setup },
  147.     { "hdb=", hdb_setup },
  148.     { "hdc=", hdc_setup },
  149.     { "hdd=", hdd_setup },
  150.     { "hd=",  ide_setup },
  151. #elif defined(CONFIG_BLK_DEV_HD)
  152.     { "hd=", hd_setup },
  153. #endif
  154. #ifdef CONFIG_CHR_DEV_ST
  155.     { "st=", st_setup },
  156. #endif
  157. #ifdef CONFIG_BUSMOUSE
  158.     { "bmouse=", bmouse_setup },
  159. #endif
  160. #ifdef CONFIG_SCSI_SEAGATE
  161.     { "st0x=", st0x_setup },
  162.     { "tmc8xx=", tmc8xx_setup },
  163. #endif
  164. #ifdef CONFIG_SCSI_T128
  165.     { "t128=", t128_setup },
  166. #endif
  167. #ifdef CONFIG_SCSI_PAS16
  168.     { "pas16=", pas16_setup },
  169. #endif
  170. #ifdef CONFIG_SCSI_GENERIC_NCR5380
  171.     { "ncr5380=", generic_NCR5380_setup },
  172. #endif
  173. #ifdef CONFIG_SCSI_AHA152X
  174.     { "aha152x=", aha152x_setup},
  175. #endif
  176. #ifdef CONFIG_SCSI_AHA1542
  177.     { "aha1542=", aha1542_setup},
  178. #endif
  179. #ifdef CONFIG_SCSI_AHA274X
  180.     { "aha274x=", aha274x_setup},
  181. #endif
  182. #ifdef CONFIG_SCSI_BUSLOGIC
  183.     { "buslogic=", buslogic_setup},
  184. #endif
  185. #ifdef CONFIG_BLK_DEV_XD
  186.     { "xd=", xd_setup },
  187. #endif
  188. #ifdef CONFIG_BLK_DEV_FD
  189.     { "floppy=", floppy_setup },
  190. #endif
  191. #ifdef CONFIG_MCD
  192.     { "mcd=", mcd_setup },
  193. #endif
  194. #ifdef CONFIG_AZTCD
  195.     { "aztcd=", aztcd_setup },
  196. #endif
  197. #ifdef CONFIG_CDU535
  198.     { "sonycd535=", sonycd535_setup },
  199. #endif CONFIG_CDU535
  200. #ifdef CONFIG_SOUND
  201.     { "sound=", sound_setup },
  202. #endif
  203. #ifdef CONFIG_SBPCD
  204.     { "sbpcd=", sbpcd_setup },
  205. #endif CONFIG_SBPCD
  206. #ifdef CONFIG_CDU31A
  207.     { "cdu31a=", cdu31a_setup },
  208. #endif CONFIG_CDU31A
  209.     { 0, 0 }
  210. };
  211.  
  212. void ramdisk_setup(char *str, int *ints)
  213. {
  214.    if (ints[0] > 0 && ints[1] >= 0)
  215.       ramdisk_size = ints[1];
  216. }
  217.  
  218. static int checksetup(char *line)
  219. {
  220.     int i = 0;
  221.     int ints[11];
  222.  
  223.     while (bootsetups[i].str) {
  224.         int n = strlen(bootsetups[i].str);
  225.         if (!strncmp(line,bootsetups[i].str,n)) {
  226.             bootsetups[i].setup_func(get_options(line+n,ints), ints);
  227.             return 1;
  228.         }
  229.         i++;
  230.     }
  231.     return 0;
  232. }
  233.  
  234. unsigned long loops_per_sec = 1;
  235.  
  236. static void calibrate_delay(void)
  237. {
  238.     int ticks;
  239.  
  240.     printk("Calibrating delay loop.. ");
  241.     while (loops_per_sec <<= 1) {
  242.         /* wait for "start of" clock tick */
  243.         ticks = jiffies;
  244.         while (ticks == jiffies)
  245.             /* nothing */;
  246.         /* Go .. */
  247.         ticks = jiffies;
  248.         __delay(loops_per_sec);
  249.         ticks = jiffies - ticks;
  250.         if (ticks >= HZ) {
  251.             loops_per_sec = muldiv(loops_per_sec, HZ, ticks);
  252.             printk("ok - %lu.%02lu BogoMips\n",
  253.                 loops_per_sec/500000,
  254.                 (loops_per_sec/5000) % 100);
  255.             return;
  256.         }
  257.     }
  258.     printk("failed\n");
  259. }
  260.  
  261.  
  262. /*
  263.  * This is a simple kernel command line parsing function: it parses
  264.  * the command line, and fills in the arguments/environment to init
  265.  * as appropriate. Any cmd-line option is taken to be an environment
  266.  * variable if it contains the character '='.
  267.  *
  268.  *
  269.  * This routine also checks for options meant for the kernel.
  270.  * These options are not given to init - they are for internal kernel use only.
  271.  */
  272. static void parse_options(char *line)
  273. {
  274.     char *next;
  275.     char *devnames[] = { "hda", "hdb", "hdc", "hdd", "sda", "sdb", "sdc", "sdd", "sde", "fd", "xda", "xdb", NULL };
  276.     int devnums[]    = { 0x300, 0x340, 0x1600, 0x1640, 0x800, 0x810, 0x820, 0x830, 0x840, 0x200, 0xD00, 0xD40, 0};
  277.     int args, envs;
  278.  
  279.     if (!*line)
  280.         return;
  281.     args = 0;
  282.     envs = 1;    /* TERM is set to 'console' by default */
  283.     next = line;
  284.     while ((line = next) != NULL) {
  285.         if ((next = strchr(line,' ')) != NULL)
  286.             *next++ = 0;
  287.         /*
  288.          * check for kernel options first..
  289.          */
  290.         if (!strncmp(line,"root=",5)) {
  291.             int n;
  292.             line += 5;
  293.             if (strncmp(line,"/dev/",5)) {
  294.                 ROOT_DEV = simple_strtoul(line,NULL,16);
  295.                 continue;
  296.             }
  297.             line += 5;
  298.             for (n = 0 ; devnames[n] ; n++) {
  299.                 int len = strlen(devnames[n]);
  300.                 if (!strncmp(line,devnames[n],len)) {
  301.                     ROOT_DEV = devnums[n]+simple_strtoul(line+len,NULL,0);
  302.                     break;
  303.                 }
  304.             }
  305.             continue;
  306.         }
  307.         if (!strcmp(line,"ro")) {
  308.             root_mountflags |= MS_RDONLY;
  309.             continue;
  310.         }
  311.         if (!strcmp(line,"rw")) {
  312.             root_mountflags &= ~MS_RDONLY;
  313.             continue;
  314.         }
  315.         if (!strcmp(line,"debug")) {
  316.             console_loglevel = 10;
  317.             continue;
  318.         }
  319.         if (checksetup(line))
  320.             continue;
  321.         /*
  322.          * Then check if it's an environment variable or
  323.          * an option.
  324.          */
  325.         if (strchr(line,'=')) {
  326.             if (envs >= MAX_INIT_ENVS)
  327.                 break;
  328.             envp_init[++envs] = line;
  329.         } else {
  330.             if (args >= MAX_INIT_ARGS)
  331.                 break;
  332.             argv_init[++args] = line;
  333.         }
  334.     }
  335.     argv_init[args+1] = NULL;
  336.     envp_init[envs+1] = NULL;
  337. }
  338.  
  339. extern void check_bugs(void);
  340. extern void setup_arch(char **, unsigned long *, unsigned long *);
  341.  
  342. asmlinkage void start_kernel(void)
  343. {
  344.     char * command_line;
  345. /*
  346.  * Interrupts are still disabled. Do necessary setups, then
  347.  * enable them
  348.  */
  349.     setup_arch(&command_line, &memory_start, &memory_end);
  350.     memory_start = paging_init(memory_start,memory_end);
  351.     trap_init();
  352.     init_IRQ();
  353.     sched_init();
  354.     parse_options(command_line);
  355.     init_modules();
  356. #ifdef CONFIG_PROFILE
  357.     prof_buffer = (unsigned long *) memory_start;
  358.     /* only text is profiled */
  359.     prof_len = (unsigned long) &etext;
  360.     prof_len >>= CONFIG_PROFILE_SHIFT;
  361.     memory_start += prof_len * sizeof(unsigned long);
  362. #endif
  363.     memory_start = console_init(memory_start,memory_end);
  364.     memory_start = bios32_init(memory_start,memory_end);
  365.     memory_start = kmalloc_init(memory_start,memory_end);
  366.     sti();
  367.     calibrate_delay();
  368.     memory_start = chr_dev_init(memory_start,memory_end);
  369.     memory_start = blk_dev_init(memory_start,memory_end);
  370.     sti();
  371. #ifdef CONFIG_SCSI
  372.     memory_start = scsi_dev_init(memory_start,memory_end);
  373. #endif
  374. #ifdef CONFIG_INET
  375.     memory_start = net_dev_init(memory_start,memory_end);
  376. #endif
  377.     memory_start = inode_init(memory_start,memory_end);
  378.     memory_start = file_table_init(memory_start,memory_end);
  379.     memory_start = name_cache_init(memory_start,memory_end);
  380.     mem_init(memory_start,memory_end);
  381.     buffer_init();
  382.     time_init();
  383.     sock_init();
  384. #ifdef CONFIG_SYSVIPC
  385.     ipc_init();
  386. #endif
  387.     sti();
  388.     check_bugs();
  389.  
  390.     printk(linux_banner);
  391.  
  392.     if (!fork())        /* we count on this going ok */
  393.         init();
  394. /*
  395.  * task[0] is meant to be used as an "idle" task: it may not sleep, but
  396.  * it might do some general things like count free pages or it could be
  397.  * used to implement a reasonable LRU algorithm for the paging routines:
  398.  * anything that can be useful, but shouldn't take time from the real
  399.  * processes.
  400.  *
  401.  * Right now task[0] just does a infinite idle loop.
  402.  */
  403.     for(;;)
  404.         idle();
  405. }
  406.  
  407. static int printf(const char *fmt, ...)
  408. {
  409.     va_list args;
  410.     int i;
  411.  
  412.     va_start(args, fmt);
  413.     write(1,printbuf,i=vsprintf(printbuf, fmt, args));
  414.     va_end(args);
  415.     return i;
  416. }
  417.  
  418. void init(void)
  419. {
  420.     int pid,i;
  421.  
  422.     setup();
  423.     sprintf(term, "TERM=con%dx%d", ORIG_VIDEO_COLS, ORIG_VIDEO_LINES);
  424.  
  425.     #ifdef CONFIG_UMSDOS_FS
  426.     {
  427.         /*
  428.             When mounting a umsdos fs as root, we detect
  429.             the pseudo_root (/linux) and initialise it here.
  430.             pseudo_root is defined in fs/umsdos/inode.c
  431.         */
  432.         extern struct inode *pseudo_root;
  433.         if (pseudo_root != NULL){
  434.             current->fs->root = pseudo_root;
  435.             current->fs->pwd  = pseudo_root;
  436.         }
  437.     }
  438.     #endif
  439.  
  440.     (void) open("/dev/tty1",O_RDWR,0);
  441.     (void) dup(0);
  442.     (void) dup(0);
  443.  
  444.     execve("/etc/init",argv_init,envp_init);
  445.     execve("/bin/init",argv_init,envp_init);
  446.     execve("/sbin/init",argv_init,envp_init);
  447.     /* if this fails, fall through to original stuff */
  448.  
  449.     if (!(pid=fork())) {
  450.         close(0);
  451.         if (open("/etc/rc",O_RDONLY,0))
  452.             _exit(1);
  453.         execve("/bin/sh",argv_rc,envp_rc);
  454.         _exit(2);
  455.     }
  456.     if (pid>0)
  457.         while (pid != wait(&i))
  458.             /* nothing */;
  459.     while (1) {
  460.         if ((pid = fork()) < 0) {
  461.             printf("Fork failed in init\n\r");
  462.             continue;
  463.         }
  464.         if (!pid) {
  465.             close(0);close(1);close(2);
  466.             setsid();
  467.             (void) open("/dev/tty1",O_RDWR,0);
  468.             (void) dup(0);
  469.             (void) dup(0);
  470.             _exit(execve("/bin/sh",argv,envp));
  471.         }
  472.         while (1)
  473.             if (pid == wait(&i))
  474.                 break;
  475.         printf("\n\rchild %d died with code %04x\n\r",pid,i);
  476.         sync();
  477.     }
  478.     _exit(0);
  479. }
  480.