📄 main.c
字号:
void calibrate_delay(void){ int ticks; int loopbit; int lps_precision = LPS_PREC; loops_per_sec = (1<<12); printk("Calibrating delay loop.. "); while (loops_per_sec <<= 1) { /* wait for "start of" clock tick */ ticks = jiffies; while (ticks == jiffies) /* nothing */; /* Go .. */ ticks = jiffies; __delay(loops_per_sec); ticks = jiffies - ticks; if (ticks) break; }/* Do a binary approximation to get loops_per_second set to equal one clock (up to lps_precision bits) */ loops_per_sec >>= 1; loopbit = loops_per_sec; while ( lps_precision-- && (loopbit >>= 1) ) { loops_per_sec |= loopbit; ticks = jiffies; while (ticks == jiffies); ticks = jiffies; __delay(loops_per_sec); if (jiffies != ticks) /* longer than 1 tick */ loops_per_sec &= ~loopbit; }/* finally, adjust loops per second in terms of seconds instead of clocks */ loops_per_sec *= HZ;/* Round the value and print it */ printk("ok - %lu.%02lu BogoMIPS\n", (loops_per_sec+2500)/500000, ((loops_per_sec+2500)/5000) % 100);#if defined(__SMP__) && defined(__i386__) smp_loops_per_tick = loops_per_sec / 400;#endif}static void parse_root_dev(char * line){ int base = 0; static struct dev_name_struct { const char *name; const int num; } devices[] = { { "nfs", 0x00ff }, { "loop", 0x0700 }, { "hda", 0x0300 }, { "hdb", 0x0340 }, { "hdc", 0x1600 }, { "hdd", 0x1640 }, { "hde", 0x2100 }, { "hdf", 0x2140 }, { "hdg", 0x2200 }, { "hdh", 0x2240 }, { "sda", 0x0800 }, { "sdb", 0x0810 }, { "sdc", 0x0820 }, { "sdd", 0x0830 }, { "sde", 0x0840 }, { "sdf", 0x0850 }, { "sdg", 0x0860 }, { "sdh", 0x0870 }, { "sdi", 0x0880 }, { "sdj", 0x0890 }, { "sdk", 0x08a0 }, { "sdl", 0x08b0 }, { "sdm", 0x08c0 }, { "sdn", 0x08d0 }, { "sdo", 0x08e0 }, { "sdp", 0x08f0 }, { "fd", 0x0200 }, { "xda", 0x0d00 }, { "xdb", 0x0d40 }, { "ram", 0x0100 }, { "scd", 0x0b00 }, { "mcd", 0x1700 }, { "cdu535", 0x1800 }, { "aztcd", 0x1d00 }, { "cm206cd", 0x2000 }, { "gscd", 0x1000 }, { "sbpcd", 0x1900 }, { "sonycd", 0x1800 },#ifdef CONFIG_PARIDE_PD { "pda", 0x2d00 }, { "pdb", 0x2d10 }, { "pdc", 0x2d20 }, { "pdd", 0x2d30 },#endif#ifdef CONFIG_PARIDE_PCD { "pcd", 0x2e00 },#endif#ifdef CONFIG_PARIDE_PF { "pf", 0x2f00 },#endif { NULL, 0 } }; if (strncmp(line,"/dev/",5) == 0) { struct dev_name_struct *dev = devices; line += 5; do { int len = strlen(dev->name); if (strncmp(line,dev->name,len) == 0) { line += len; base = dev->num; break; } dev++; } while (dev->name); } ROOT_DEV = to_kdev_t(base + simple_strtoul(line,NULL,base?10:16));}/* * This is a simple kernel command line parsing function: it parses * the command line, and fills in the arguments/environment to init * as appropriate. Any cmd-line option is taken to be an environment * variable if it contains the character '='. * * * This routine also checks for options meant for the kernel. * These options are not given to init - they are for internal kernel use only. */static void parse_options(char *line){ char *next; int args, envs; if (!*line) return; args = 0; envs = 1; /* TERM is set to 'linux' by default */ next = line; while ((line = next) != NULL) { if ((next = strchr(line,' ')) != NULL) *next++ = 0; /* * check for kernel options first.. */ if (!strncmp(line,"root=",5)) { parse_root_dev(line+5); continue; }#ifdef CONFIG_ROOT_NFS if (!strncmp(line, "nfsroot=", 8)) { int n; line += 8; ROOT_DEV = MKDEV(UNNAMED_MAJOR, 255); if (line[0] == '/' || line[0] == ',' || (line[0] >= '0' && line[0] <= '9')) { strncpy(nfs_root_name, line, sizeof(nfs_root_name)); nfs_root_name[sizeof(nfs_root_name)-1] = '\0'; continue; } n = strlen(line) + strlen(NFS_ROOT); if (n >= sizeof(nfs_root_name)) line[sizeof(nfs_root_name) - strlen(NFS_ROOT) - 1] = '\0'; sprintf(nfs_root_name, NFS_ROOT, line); continue; } if (!strncmp(line, "nfsaddrs=", 9)) { line += 9; strncpy(nfs_root_addrs, line, sizeof(nfs_root_addrs)); nfs_root_addrs[sizeof(nfs_root_addrs)-1] = '\0'; continue; }#endif if (!strcmp(line,"ro")) { root_mountflags |= MS_RDONLY; continue; } if (!strcmp(line,"rw")) { root_mountflags &= ~MS_RDONLY; continue; } if (!strcmp(line,"debug")) { console_loglevel = 10; continue; } if (!strncmp(line,"init=",5)) { line += 5; execute_command = line; continue; } if (checksetup(line)) continue; /* * Then check if it's an environment variable or * an option. */ if (strchr(line,'=')) { if (envs >= MAX_INIT_ENVS) break; envp_init[++envs] = line; } else { if (args >= MAX_INIT_ARGS) break; argv_init[++args] = line; } } argv_init[args+1] = NULL; envp_init[envs+1] = NULL;}extern void setup_arch(char **, unsigned long *, unsigned long *);extern void arch_syms_export(void);#ifndef __SMP__/* * Uniprocessor idle thread */ int cpu_idle(void *unused){ for(;;) idle();}#else/* * Multiprocessor idle thread is in arch/... */ extern int cpu_idle(void * unused);/* * Activate a secondary processor. */ asmlinkage void start_secondary(void){ trap_init(); init_IRQ(); smp_callin(); cpu_idle(NULL);}/* * Called by CPU#0 to activate the rest. */ static void smp_init(void){ int i, j; smp_boot_cpus(); /* * Create the slave init tasks as sharing pid 0. * * This should only happen if we have virtual CPU numbers * higher than 0. */ for (i=1; i<smp_num_cpus; i++) { struct task_struct *n, *p; j = cpu_logical_map[i]; /* * We use kernel_thread for the idlers which are * unlocked tasks running in kernel space. */ kernel_thread(cpu_idle, NULL, CLONE_PID); /* * Don't assume linear processor numbering */ current_set[j]=task[i]; current_set[j]->processor=j; cli(); n = task[i]->next_run; p = task[i]->prev_run; nr_running--; n->prev_run = p; p->next_run = n; task[i]->next_run = task[i]->prev_run = task[i]; sti(); }} /* * The autoprobe routines assume CPU#0 on the i386 * so we don't actually set the game in motion until * they are finished. */ static void smp_begin(void){ smp_threads_ready=1; smp_commence();} #endif/* * Activate the first processor. */ asmlinkage void start_kernel(void){ char * command_line;/* * This little check will move. */#ifdef __SMP__ static int first_cpu=1; if(!first_cpu) start_secondary(); first_cpu=0; #endif /* * Interrupts are still disabled. Do necessary setups, then * enable them */ setup_arch(&command_line, &memory_start, &memory_end); memory_start = paging_init(memory_start,memory_end); trap_init(); init_IRQ(); sched_init(); time_init(); parse_options(command_line);#ifdef CONFIG_MODULES init_modules();#endif#ifdef CONFIG_PROFILE if (!prof_shift)#ifdef CONFIG_PROFILE_SHIFT prof_shift = CONFIG_PROFILE_SHIFT;#else prof_shift = 2;#endif#endif if (prof_shift) { prof_buffer = (unsigned int *) memory_start; /* only text is profiled */ prof_len = (unsigned long) &_etext - (unsigned long) &_stext; prof_len >>= prof_shift; memory_start += prof_len * sizeof(unsigned int); memset(prof_buffer, 0, prof_len * sizeof(unsigned int)); } memory_start = console_init(memory_start,memory_end);#ifdef CONFIG_PCI memory_start = pci_init(memory_start,memory_end);#endif memory_start = kmalloc_init(memory_start,memory_end); sti(); calibrate_delay(); memory_start = inode_init(memory_start,memory_end); memory_start = file_table_init(memory_start,memory_end); memory_start = name_cache_init(memory_start,memory_end);#ifdef CONFIG_BLK_DEV_INITRD if (initrd_start && initrd_start < memory_start) { printk(KERN_CRIT "initrd overwritten (0x%08lx < 0x%08lx) - " "disabling it.\n",initrd_start,memory_start); initrd_start = 0; }#endif mem_init(memory_start,memory_end); buffer_init(); sock_init();#if defined(CONFIG_SYSVIPC) || defined(CONFIG_KERNELD) ipc_init();#endif dquot_init(); arch_syms_export(); sti(); check_bugs();#if defined(CONFIG_MTRR) && defined(__SMP__) init_mtrr_config();#endif printk(linux_banner);#ifdef __SMP__ smp_init();#endif sysctl_init(); /* * We count on the initial thread going ok * Like idlers init is an unlocked kernel thread, which will * make syscalls (and thus be locked). */ kernel_thread(init, NULL, 0);/* * task[0] is meant to be used as an "idle" task: it may not sleep, but * it might do some general things like count free pages or it could be * used to implement a reasonable LRU algorithm for the paging routines: * anything that can be useful, but shouldn't take time from the real * processes. * * Right now task[0] just does a infinite idle loop. */ cpu_idle(NULL);}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 int do_rc(void * rc){ close(0); if (open(rc,O_RDONLY,0)) return -1; return execve("/bin/sh", argv_rc, envp_rc);}static int do_shell(void * shell){ close(0);close(1);close(2); setsid(); (void) open("/dev/tty1",O_RDWR,0); (void) dup(0); (void) dup(0); return execve(shell, argv, envp);}#ifdef CONFIG_BLK_DEV_INITRDstatic int do_linuxrc(void * shell){ static char *argv[] = { "linuxrc", NULL, }; close(0);close(1);close(2); setsid(); (void) open("/dev/tty1",O_RDWR,0); (void) dup(0); (void) dup(0); return execve(shell, argv, envp_init);}static void no_initrd(char *s,int *ints){ mount_initrd = 0;}#endifstatic int init(void * unused){ int pid,i;#ifdef CONFIG_BLK_DEV_INITRD int real_root_mountflags;#endif /* Launch bdflush from here, instead of the old syscall way. */ kernel_thread(bdflush, NULL, 0); /* Start the background pageout daemon. */ kswapd_setup(); kernel_thread(kswapd, NULL, 0);#ifdef CONFIG_BLK_DEV_INITRD real_root_dev = ROOT_DEV; real_root_mountflags = root_mountflags; if (initrd_start && mount_initrd) root_mountflags &= ~MS_RDONLY; else mount_initrd =0;#endif setup();#ifdef __SMP__ /* * With the devices probed and setup we can * now enter SMP mode. */ smp_begin();#endif #ifdef CONFIG_UMSDOS_FS { /* When mounting a umsdos fs as root, we detect the pseudo_root (/linux) and initialise it here. pseudo_root is defined in fs/umsdos/inode.c */ extern struct inode *pseudo_root; if (pseudo_root != NULL){ current->fs->root = pseudo_root; current->fs->pwd = pseudo_root; } } #endif#ifdef CONFIG_BLK_DEV_INITRD root_mountflags = real_root_mountflags; if (mount_initrd && ROOT_DEV != real_root_dev && ROOT_DEV == MKDEV(RAMDISK_MAJOR,0)) { int error; pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD); if (pid>0) while (pid != wait(&i)); if (real_root_dev != MKDEV(RAMDISK_MAJOR, 0)) { error = change_root(real_root_dev,"/initrd"); if (error) printk(KERN_ERR "Change root to /initrd: " "error %d\n",error); } }#endif /* * This keeps serial console MUCH cleaner, but does assume * the console driver checks there really is a video device * attached (Sparc effectively does). */ if ((open("/dev/tty1",O_RDWR,0) < 0) && (open("/dev/ttyS0",O_RDWR,0) < 0)) printk("Unable to open an initial console.\n"); (void) dup(0); (void) dup(0); if (!execute_command) { execve("/etc/init",argv_init,envp_init); execve("/bin/init",argv_init,envp_init); execve("/sbin/init",argv_init,envp_init); /* if this fails, fall through to original stuff */ pid = kernel_thread(do_rc, "/etc/rc", SIGCHLD); if (pid>0) while (pid != wait(&i)) /* nothing */; } while (1) { pid = kernel_thread(do_shell, execute_command ? execute_command : "/bin/sh", SIGCHLD); if (pid < 0) { printf("Fork failed in init\n\r"); continue; } while (1) if (pid == wait(&i)) break; printf("\n\rchild %d died with code %04x\n\r",pid,i); sync(); } return -1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -