1
2
3
4
5
6
7
8
9
10
11
12#define __KERNEL_SYSCALLS__
13
14#include <linux/config.h>
15#include <linux/proc_fs.h>
16#include <linux/devfs_fs_kernel.h>
17#include <linux/unistd.h>
18#include <linux/string.h>
19#include <linux/ctype.h>
20#include <linux/delay.h>
21#include <linux/utsname.h>
22#include <linux/ioport.h>
23#include <linux/init.h>
24#include <linux/smp_lock.h>
25#include <linux/blk.h>
26#include <linux/hdreg.h>
27#include <linux/iobuf.h>
28#include <linux/bootmem.h>
29#include <linux/tty.h>
30
31#include <asm/io.h>
32#include <asm/bugs.h>
33
34#if defined(CONFIG_ARCH_S390)
35#include <asm/s390mach.h>
36#include <asm/ccwcache.h>
37#endif
38
39#ifdef CONFIG_PCI
40#include <linux/pci.h>
41#endif
42
43#ifdef CONFIG_DIO
44#include <linux/dio.h>
45#endif
46
47#ifdef CONFIG_ZORRO
48#include <linux/zorro.h>
49#endif
50
51#ifdef CONFIG_MTRR
52# include <asm/mtrr.h>
53#endif
54
55#ifdef CONFIG_NUBUS
56#include <linux/nubus.h>
57#endif
58
59#ifdef CONFIG_ISAPNP
60#include <linux/isapnp.h>
61#endif
62
63#ifdef CONFIG_IRDA
64extern int irda_proto_init(void);
65extern int irda_device_init(void);
66#endif
67
68#ifdef CONFIG_X86_LOCAL_APIC
69#include <asm/smp.h>
70#endif
71
72
73
74
75
76
77
78#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 91)
79#error Sorry, your GCC is too old. It builds incorrect kernels.
80#endif
81
82extern char _stext, _etext;
83extern char *linux_banner;
84
85static int init(void *);
86
87extern void init_IRQ(void);
88extern void init_modules(void);
89extern void sock_init(void);
90extern void fork_init(unsigned long);
91extern void mca_init(void);
92extern void sbus_init(void);
93extern void ppc_init(void);
94extern void sysctl_init(void);
95extern void signals_init(void);
96extern int init_pcmcia_ds(void);
97
98extern void free_initmem(void);
99
100#ifdef CONFIG_TC
101extern void tc_init(void);
102#endif
103
104extern void ecard_init(void);
105
106#if defined(CONFIG_SYSVIPC)
107extern void ipc_init(void);
108#endif
109#ifdef CONFIG_PERFMON
110extern void perfmon_init(void);
111#endif
112
113
114
115
116#define MAX_INIT_ARGS 8
117#define MAX_INIT_ENVS 8
118
119extern void time_init(void);
120extern void softirq_init(void);
121
122int rows, cols;
123
124#ifdef CONFIG_BLK_DEV_INITRD
125unsigned int real_root_dev;
126#endif
127
128int root_mountflags = MS_RDONLY;
129char *execute_command;
130char root_device_name[64];
131
132
133static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, };
134static char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, };
135
136static int __init profile_setup(char *str)
137{
138 int par;
139 if (get_option(&str,&par)) prof_shift = par;
140 return 1;
141}
142
143__setup("profile=", profile_setup);
144
145
146static struct dev_name_struct {
147 const char *name;
148 const int num;
149} root_dev_names[] __initdata = {
150 { "nfs", 0x00ff },
151 { "hda", 0x0300 },
152 { "hdb", 0x0340 },
153 { "loop", 0x0700 },
154 { "hdc", 0x1600 },
155 { "hdd", 0x1640 },
156 { "hde", 0x2100 },
157 { "hdf", 0x2140 },
158 { "hdg", 0x2200 },
159 { "hdh", 0x2240 },
160 { "hdi", 0x3800 },
161 { "hdj", 0x3840 },
162 { "hdk", 0x3900 },
163 { "hdl", 0x3940 },
164 { "hdm", 0x5800 },
165 { "hdn", 0x5840 },
166 { "hdo", 0x5900 },
167 { "hdp", 0x5940 },
168 { "hdq", 0x5A00 },
169 { "hdr", 0x5A40 },
170 { "hds", 0x5B00 },
171 { "hdt", 0x5B40 },
172 { "sda", 0x0800 },
173 { "sdb", 0x0810 },
174 { "sdc", 0x0820 },
175 { "sdd", 0x0830 },
176 { "sde", 0x0840 },
177 { "sdf", 0x0850 },
178 { "sdg", 0x0860 },
179 { "sdh", 0x0870 },
180 { "sdi", 0x0880 },
181 { "sdj", 0x0890 },
182 { "sdk", 0x08a0 },
183 { "sdl", 0x08b0 },
184 { "sdm", 0x08c0 },
185 { "sdn", 0x08d0 },
186 { "sdo", 0x08e0 },
187 { "sdp", 0x08f0 },
188 { "ada", 0x1c00 },
189 { "adb", 0x1c10 },
190 { "adc", 0x1c20 },
191 { "add", 0x1c30 },
192 { "ade", 0x1c40 },
193 { "fd", 0x0200 },
194 { "md", 0x0900 },
195 { "xda", 0x0d00 },
196 { "xdb", 0x0d40 },
197 { "ram", 0x0100 },
198 { "scd", 0x0b00 },
199 { "mcd", 0x1700 },
200 { "cdu535", 0x1800 },
201 { "sonycd", 0x1800 },
202 { "aztcd", 0x1d00 },
203 { "cm206cd", 0x2000 },
204 { "gscd", 0x1000 },
205 { "sbpcd", 0x1900 },
206 { "eda", 0x2400 },
207 { "edb", 0x2440 },
208 { "pda", 0x2d00 },
209 { "pdb", 0x2d10 },
210 { "pdc", 0x2d20 },
211 { "pdd", 0x2d30 },
212 { "pcd", 0x2e00 },
213 { "pf", 0x2f00 },
214 { "apblock", APBLOCK_MAJOR << 8},
215 { "ddv", DDV_MAJOR << 8},
216 { "jsfd", JSFD_MAJOR << 8},
217#if defined(CONFIG_ARCH_S390)
218 { "dasda", (DASD_MAJOR << MINORBITS) },
219 { "dasdb", (DASD_MAJOR << MINORBITS) + (1 << 2) },
220 { "dasdc", (DASD_MAJOR << MINORBITS) + (2 << 2) },
221 { "dasdd", (DASD_MAJOR << MINORBITS) + (3 << 2) },
222 { "dasde", (DASD_MAJOR << MINORBITS) + (4 << 2) },
223 { "dasdf", (DASD_MAJOR << MINORBITS) + (5 << 2) },
224 { "dasdg", (DASD_MAJOR << MINORBITS) + (6 << 2) },
225 { "dasdh", (DASD_MAJOR << MINORBITS) + (7 << 2) },
226#endif
227#if defined(CONFIG_BLK_CPQ_DA) || defined(CONFIG_BLK_CPQ_DA_MODULE)
228 { "ida/c0d0p",0x4800 },
229 { "ida/c0d1p",0x4810 },
230 { "ida/c0d2p",0x4820 },
231 { "ida/c0d3p",0x4830 },
232 { "ida/c0d4p",0x4840 },
233 { "ida/c0d5p",0x4850 },
234 { "ida/c0d6p",0x4860 },
235 { "ida/c0d7p",0x4870 },
236 { "ida/c0d8p",0x4880 },
237 { "ida/c0d9p",0x4890 },
238 { "ida/c0d10p",0x48A0 },
239 { "ida/c0d11p",0x48B0 },
240 { "ida/c0d12p",0x48C0 },
241 { "ida/c0d13p",0x48D0 },
242 { "ida/c0d14p",0x48E0 },
243 { "ida/c0d15p",0x48F0 },
244#endif
245#if defined(CONFIG_BLK_CPQ_CISS_DA) || defined(CONFIG_BLK_CPQ_CISS_DA_MODULE)
246 { "cciss/c0d0p",0x6800 },
247 { "cciss/c0d1p",0x6810 },
248 { "cciss/c0d2p",0x6820 },
249 { "cciss/c0d3p",0x6830 },
250 { "cciss/c0d4p",0x6840 },
251 { "cciss/c0d5p",0x6850 },
252 { "cciss/c0d6p",0x6860 },
253 { "cciss/c0d7p",0x6870 },
254 { "cciss/c0d8p",0x6880 },
255 { "cciss/c0d9p",0x6890 },
256 { "cciss/c0d10p",0x68A0 },
257 { "cciss/c0d11p",0x68B0 },
258 { "cciss/c0d12p",0x68C0 },
259 { "cciss/c0d13p",0x68D0 },
260 { "cciss/c0d14p",0x68E0 },
261 { "cciss/c0d15p",0x68F0 },
262#endif
263 { "nftla", 0x5d00 },
264 { "nftlb", 0x5d10 },
265 { "nftlc", 0x5d20 },
266 { "nftld", 0x5d30 },
267 { "ftla", 0x2c00 },
268 { "ftlb", 0x2c08 },
269 { "ftlc", 0x2c10 },
270 { "ftld", 0x2c18 },
271 { "mtdblock", 0x1f00 },
272 { NULL, 0 }
273};
274
275kdev_t __init name_to_kdev_t(char *line)
276{
277 int base = 0;
278
279 if (strncmp(line,"/dev/",5) == 0) {
280 struct dev_name_struct *dev = root_dev_names;
281 line += 5;
282 do {
283 int len = strlen(dev->name);
284 if (strncmp(line,dev->name,len) == 0) {
285 line += len;
286 base = dev->num;
287 break;
288 }
289 dev++;
290 } while (dev->name);
291 }
292 return to_kdev_t(base + simple_strtoul(line,NULL,base?10:16));
293}
294
295static int __init root_dev_setup(char *line)
296{
297 int i;
298 char ch;
299
300 ROOT_DEV = name_to_kdev_t(line);
301 memset (root_device_name, 0, sizeof root_device_name);
302 if (strncmp (line, "/dev/", 5) == 0) line += 5;
303 for (i = 0; i < sizeof root_device_name - 1; ++i)
304 {
305 ch = line[i];
306 if ( isspace (ch) || (ch == ',') || (ch == '\0') ) break;
307 root_device_name[i] = ch;
308 }
309 return 1;
310}
311
312__setup("root=", root_dev_setup);
313
314static int __init checksetup(char *line)
315{
316 struct kernel_param *p;
317
318 p = &__setup_start;
319 do {
320 int n = strlen(p->str);
321 if (!strncmp(line,p->str,n)) {
322 if (p->setup_func(line+n))
323 return 1;
324 }
325 p++;
326 } while (p < &__setup_end);
327 return 0;
328}
329
330
331
332unsigned long loops_per_jiffy = (1<<12);
333
334
335
336
337#define LPS_PREC 8
338
339void __init calibrate_delay(void)
340{
341 unsigned long ticks, loopbit;
342 int lps_precision = LPS_PREC;
343
344 loops_per_jiffy = (1<<12);
345
346 printk("Calibrating delay loop... ");
347 while (loops_per_jiffy <<= 1) {
348
349 ticks = jiffies;
350 while (ticks == jiffies)
351 ;
352
353 ticks = jiffies;
354 __delay(loops_per_jiffy);
355 ticks = jiffies - ticks;
356 if (ticks)
357 break;
358 }
359
360
361
362 loops_per_jiffy >>= 1;
363 loopbit = loops_per_jiffy;
364 while ( lps_precision-- && (loopbit >>= 1) ) {
365 loops_per_jiffy |= loopbit;
366 ticks = jiffies;
367 while (ticks == jiffies);
368 ticks = jiffies;
369 __delay(loops_per_jiffy);
370 if (jiffies != ticks)
371 loops_per_jiffy &= ~loopbit;
372 }
373
374
375 printk("%lu.%02lu BogoMIPS\n",
376 loops_per_jiffy/(500000/HZ),
377 (loops_per_jiffy/(5000/HZ)) % 100);
378}
379
380static int __init readonly(char *str)
381{
382 if (*str)
383 return 0;
384 root_mountflags |= MS_RDONLY;
385 return 1;
386}
387
388static int __init readwrite(char *str)
389{
390 if (*str)
391 return 0;
392 root_mountflags &= ~MS_RDONLY;
393 return 1;
394}
395
396static int __init debug_kernel(char *str)
397{
398 if (*str)
399 return 0;
400 console_loglevel = 10;
401 return 1;
402}
403
404static int __init quiet_kernel(char *str)
405{
406 if (*str)
407 return 0;
408 console_loglevel = 4;
409 return 1;
410}
411
412__setup("ro", readonly);
413__setup("rw", readwrite);
414__setup("debug", debug_kernel);
415__setup("quiet", quiet_kernel);
416
417
418
419
420
421
422
423
424
425
426static void __init parse_options(char *line)
427{
428 char *next,*quote;
429 int args, envs;
430
431 if (!*line)
432 return;
433 args = 0;
434 envs = 1;
435 next = line;
436 while ((line = next) != NULL) {
437 quote = strchr(line,'"');
438 next = strchr(line, ' ');
439 while (next != NULL && quote != NULL && quote < next) {
440
441
442
443 next = strchr(quote+1, '"');
444 if (next != NULL) {
445 quote = strchr(next+1, '"');
446 next = strchr(next+1, ' ');
447 }
448 }
449 if (next != NULL)
450 *next++ = 0;
451 if (!strncmp(line,"init=",5)) {
452 line += 5;
453 execute_command = line;
454
455
456
457
458
459 args = 0;
460 continue;
461 }
462 if (checksetup(line))
463 continue;
464
465
466
467
468
469 if (strchr(line,'=')) {
470 if (envs >= MAX_INIT_ENVS)
471 break;
472 envp_init[++envs] = line;
473 } else {
474 if (args >= MAX_INIT_ARGS)
475 break;
476 if (*line)
477 argv_init[++args] = line;
478 }
479 }
480 argv_init[args+1] = NULL;
481 envp_init[envs+1] = NULL;
482}
483
484
485extern void setup_arch(char **);
486extern void cpu_idle(void);
487
488unsigned long wait_init_idle;
489
490#ifndef CONFIG_SMP
491
492#ifdef CONFIG_X86_LOCAL_APIC
493static void __init smp_init(void)
494{
495 APIC_init_uniprocessor();
496}
497#else
498#define smp_init() do { } while (0)
499#endif
500
501#else
502
503
504
505static void __init smp_init(void)
506{
507
508 smp_boot_cpus();
509 wait_init_idle = cpu_online_map;
510 clear_bit(current->processor, &wait_init_idle);
511
512 smp_threads_ready=1;
513 smp_commence();
514
515
516 printk("Waiting on wait_init_idle (map = 0x%lx)\n", wait_init_idle);
517 while (wait_init_idle) {
518 cpu_relax();
519 barrier();
520 }
521 printk("All processors have done init_idle\n");
522}
523
524#endif
525
526
527
528
529
530
531
532
533static void rest_init(void)
534{
535 kernel_thread(init, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL);
536 unlock_kernel();
537 current->need_resched = 1;
538 cpu_idle();
539}
540
541
542
543
544
545asmlinkage void __init start_kernel(void)
546{
547 char * command_line;
548 unsigned long mempages;
549 extern char saved_command_line[];
550
551
552
553
554 lock_kernel();
555 printk(linux_banner);
556 setup_arch(&command_line);
557 printk("Kernel command line: %s\n", saved_command_line);
558 parse_options(command_line);
559 trap_init();
560 init_IRQ();
561 sched_init();
562 softirq_init();
563 time_init();
564
565
566
567
568
569
570 console_init();
571#ifdef CONFIG_MODULES
572 init_modules();
573#endif
574 if (prof_shift) {
575 unsigned int size;
576
577 prof_len = (unsigned long) &_etext - (unsigned long) &_stext;
578 prof_len >>= prof_shift;
579
580 size = prof_len * sizeof(unsigned int) + PAGE_SIZE-1;
581 prof_buffer = (unsigned int *) alloc_bootmem(size);
582 }
583
584 kmem_cache_init();
585 sti();
586 calibrate_delay();
587#ifdef CONFIG_BLK_DEV_INITRD
588 if (initrd_start && !initrd_below_start_ok &&
589 initrd_start < min_low_pfn << PAGE_SHIFT) {
590 printk(KERN_CRIT "initrd overwritten (0x%08lx < 0x%08lx) - "
591 "disabling it.\n",initrd_start,min_low_pfn << PAGE_SHIFT);
592 initrd_start = 0;
593 }
594#endif
595 mem_init();
596 kmem_cache_sizes_init();
597 pgtable_cache_init();
598
599#ifdef CONFIG_PERFMON
600 perfmon_init();
601#endif
602 mempages = num_physpages;
603
604 fork_init(mempages);
605 proc_caches_init();
606 vfs_caches_init(mempages);
607 buffer_init(mempages);
608 page_cache_init(mempages);
609#if defined(CONFIG_ARCH_S390)
610 ccwcache_init();
611#endif
612 signals_init();
613#ifdef CONFIG_PROC_FS
614 proc_root_init();
615#endif
616#if defined(CONFIG_SYSVIPC)
617 ipc_init();
618#endif
619 check_bugs();
620 printk("POSIX conformance testing by UNIFIX\n");
621
622
623
624
625
626
627 smp_init();
628 rest_init();
629}
630
631#ifdef CONFIG_BLK_DEV_INITRD
632static int do_linuxrc(void * shell)
633{
634 static char *argv[] = { "linuxrc", NULL, };
635
636 close(0);close(1);close(2);
637 setsid();
638 (void) open("/dev/console",O_RDWR,0);
639 (void) dup(0);
640 (void) dup(0);
641 return execve(shell, argv, envp_init);
642}
643
644#endif
645
646struct task_struct *child_reaper = &init_task;
647
648static void __init do_initcalls(void)
649{
650 initcall_t *call;
651
652 call = &__initcall_start;
653 do {
654 (*call)();
655 call++;
656 } while (call < &__initcall_end);
657
658
659 flush_scheduled_tasks();
660}
661
662
663
664
665
666
667
668
669static void __init do_basic_setup(void)
670{
671
672
673
674
675
676
677
678
679
680 child_reaper = current;
681
682#if defined(CONFIG_MTRR)
683
684
685
686
687
688 mtrr_init();
689#endif
690
691#ifdef CONFIG_SYSCTL
692 sysctl_init();
693#endif
694
695
696
697
698
699#if defined(CONFIG_ARCH_S390)
700 s390_init_machine_check();
701#endif
702
703#ifdef CONFIG_PCI
704 pci_init();
705#endif
706#ifdef CONFIG_SBUS
707 sbus_init();
708#endif
709#if defined(CONFIG_PPC)
710 ppc_init();
711#endif
712#ifdef CONFIG_MCA
713 mca_init();
714#endif
715#ifdef CONFIG_ARCH_ACORN
716 ecard_init();
717#endif
718#ifdef CONFIG_ZORRO
719 zorro_init();
720#endif
721#ifdef CONFIG_DIO
722 dio_init();
723#endif
724#ifdef CONFIG_NUBUS
725 nubus_init();
726#endif
727#ifdef CONFIG_ISAPNP
728 isapnp_init();
729#endif
730#ifdef CONFIG_TC
731 tc_init();
732#endif
733
734
735 sock_init();
736
737 start_context_thread();
738 do_initcalls();
739
740#ifdef CONFIG_IRDA
741 irda_proto_init();
742 irda_device_init();
743#endif
744#ifdef CONFIG_PCMCIA
745 init_pcmcia_ds();
746#endif
747}
748
749extern void rd_load(void);
750extern void initrd_load(void);
751
752
753
754
755static void prepare_namespace(void)
756{
757#ifdef CONFIG_BLK_DEV_INITRD
758 int real_root_mountflags = root_mountflags;
759 if (!initrd_start)
760 mount_initrd = 0;
761 if (mount_initrd)
762 root_mountflags &= ~MS_RDONLY;
763 real_root_dev = ROOT_DEV;
764#endif
765
766#ifdef CONFIG_BLK_DEV_RAM
767#ifdef CONFIG_BLK_DEV_INITRD
768 if (mount_initrd)
769 initrd_load();
770 else
771#endif
772 rd_load();
773#endif
774
775
776 mount_root();
777
778 mount_devfs_fs ();
779
780#ifdef CONFIG_BLK_DEV_INITRD
781 root_mountflags = real_root_mountflags;
782 if (mount_initrd && ROOT_DEV != real_root_dev
783 && MAJOR(ROOT_DEV) == RAMDISK_MAJOR && MINOR(ROOT_DEV) == 0) {
784 int error;
785 int i, pid;
786
787 pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD);
788 if (pid > 0) {
789 while (pid != wait(&i)) {
790 current->policy |= SCHED_YIELD;
791 schedule();
792 }
793 }
794 if (MAJOR(real_root_dev) != RAMDISK_MAJOR
795 || MINOR(real_root_dev) != 0) {
796 error = change_root(real_root_dev,"/initrd");
797 if (error)
798 printk(KERN_ERR "Change root to /initrd: "
799 "error %d\n",error);
800 }
801 }
802#endif
803}
804
805static int init(void * unused)
806{
807 lock_kernel();
808 do_basic_setup();
809
810 prepare_namespace();
811
812
813
814
815
816
817 free_initmem();
818 unlock_kernel();
819
820 if (open("/dev/console", O_RDWR, 0) < 0)
821 printk("Warning: unable to open an initial console.\n");
822
823 (void) dup(0);
824 (void) dup(0);
825
826
827
828
829
830
831
832
833 if (execute_command)
834 execve(execute_command,argv_init,envp_init);
835 execve("/sbin/init",argv_init,envp_init);
836 execve("/etc/init",argv_init,envp_init);
837 execve("/bin/init",argv_init,envp_init);
838 execve("/bin/sh",argv_init,envp_init);
839 panic("No init found. Try passing init= option to kernel.");
840}
841