| /* See COPYRIGHT for copyright information. */ | 
 |  | 
 | #ifdef CONFIG_BSD_ON_CORE0 | 
 | #error "Yeah, it's not possible to build ROS with BSD on Core 0, sorry......" | 
 | #else | 
 |  | 
 | #include <arch/arch.h> | 
 | #include <arch/console.h> | 
 | #include <multiboot.h> | 
 | #include <stab.h> | 
 | #include <smp.h> | 
 |  | 
 | #include <time.h> | 
 | #include <atomic.h> | 
 | #include <stdio.h> | 
 | #include <string.h> | 
 | #include <assert.h> | 
 | #include <monitor.h> | 
 | #include <pmap.h> | 
 | #include <process.h> | 
 | #include <trap.h> | 
 | #include <syscall.h> | 
 | #include <kclock.h> | 
 | #include <manager.h> | 
 | #include <testing.h> | 
 | #include <kmalloc.h> | 
 | #include <hashtable.h> | 
 | #include <radix.h> | 
 | #include <mm.h> | 
 | #include <frontend.h> | 
 |  | 
 | #include <arch/init.h> | 
 | #include <bitmask.h> | 
 | #include <slab.h> | 
 | #include <kfs.h> | 
 | #include <vfs.h> | 
 | #include <devfs.h> | 
 | #include <blockdev.h> | 
 | #include <ext2fs.h> | 
 | #include <kthread.h> | 
 | #include <console.h> | 
 | #include <linker_func.h> | 
 | #include <ip.h> | 
 | #include <acpi.h> | 
 | #include <coreboot_tables.h> | 
 | #include <ros/ttrace.h> | 
 |  | 
 | int booting = 1; | 
 | struct sysinfo_t sysinfo; | 
 | static void run_linker_funcs(void); | 
 | static int run_init_script(void); | 
 |  | 
 | void kernel_init(multiboot_info_t *mboot_info) | 
 | { | 
 | 	extern char edata[], end[]; | 
 |  | 
 | 	memset(edata, 0, end - edata); | 
 | 	/* mboot_info is a physical address.  while some arches currently have the | 
 | 	 * lower memory mapped, everyone should have it mapped at kernbase by now. | 
 | 	 * also, it might be in 'free' memory, so once we start dynamically using | 
 | 	 * memory, we may clobber it. */ | 
 | 	multiboot_kaddr = (struct multiboot_info*)((physaddr_t)mboot_info | 
 |                                                + KERNBASE); | 
 | 	cons_init(); | 
 | 	print_cpuinfo(); | 
 |  | 
 | 	cache_init();					// Determine systems's cache properties | 
 | 	pmem_init(multiboot_kaddr); | 
 | 	ttrace_init();                  // Setup timed tracer, depends on pmem | 
 | 	kmem_cache_init();              // Sets up slab allocator | 
 | 	kmalloc_init(); | 
 | 	hashtable_init(); | 
 | 	radix_init(); | 
 | 	cache_color_alloc_init();       // Inits data structs | 
 | 	colored_page_alloc_init();      // Allocates colors for agnostic processes | 
 | 	acpiinit(); | 
 | 	kthread_init();					/* might need to tweak when this happens */ | 
 | 	vmr_init(); | 
 | 	file_init(); | 
 | 	page_check(); | 
 | 	idt_init(); | 
 | 	kernel_msg_init(); | 
 | 	timer_init(); | 
 | 	vfs_init(); | 
 | 	devfs_init(); | 
 | 	train_timing(); | 
 | 	kb_buf_init(&cons_buf); | 
 | 	arch_init(); | 
 | 	block_init(); | 
 | 	ttrace_cleanup(); // Must be called after arch_init() | 
 | 	enable_irq(); | 
 | 	run_linker_funcs(); | 
 | 	/* reset/init devtab after linker funcs 3 and 4.  these run NIC and medium | 
 | 	 * pre-inits, which need to happen before devether. */ | 
 | 	devtabreset(); | 
 | 	devtabinit(); | 
 |  | 
 | #ifdef CONFIG_EXT2FS | 
 | 	mount_fs(&ext2_fs_type, "/dev/ramdisk", "/mnt", 0); | 
 | #endif /* CONFIG_EXT2FS */ | 
 | #ifdef CONFIG_ETH_AUDIO | 
 | 	eth_audio_init(); | 
 | #endif /* CONFIG_ETH_AUDIO */ | 
 | 	get_coreboot_info(&sysinfo); | 
 | 	booting = 0; | 
 |  | 
 | #ifdef CONFIG_RUN_INIT_SCRIPT | 
 | 	if (run_init_script()) { | 
 | 		printk("Configured to run init script, but no script specified!\n"); | 
 | 		manager(); | 
 | 	} | 
 | #else | 
 | 	manager(); | 
 | #endif | 
 | } | 
 |  | 
 | #ifdef CONFIG_RUN_INIT_SCRIPT | 
 | static int run_init_script(void) | 
 | { | 
 | 	/* If we have an init script path specified */ | 
 | 	if (strlen(CONFIG_INIT_SCRIPT_PATH_AND_ARGS) != 0) { | 
 | 		int vargs = 0; | 
 | 		char *sptr = &CONFIG_INIT_SCRIPT_PATH_AND_ARGS[0]; | 
 |  | 
 | 		/* Figure out how many arguments there are, by finding the spaces */ | 
 | 		/* TODO: consider rewriting this stuff with parsecmd */ | 
 | 		while (*sptr != '\0') { | 
 | 			if (*(sptr++) != ' ') { | 
 | 				vargs++; | 
 | 				while ((*sptr != ' ') && (*sptr != '\0')) | 
 | 					sptr++; | 
 | 			} | 
 | 		} | 
 |  | 
 | 		/* Initialize l_argv with its first three arguments, but allocate space | 
 | 		 * for all arguments as calculated above */ | 
 | 		int static_args = 3; | 
 | 		int total_args = vargs + static_args; | 
 | 		char *l_argv[total_args]; | 
 | 		l_argv[0] = ""; | 
 | 		l_argv[1] = "busybox"; | 
 | 		l_argv[2] = "ash"; | 
 |  | 
 | 		/* Initialize l_argv with the rest of the arguments */ | 
 | 		int i = static_args; | 
 | 		sptr = &CONFIG_INIT_SCRIPT_PATH_AND_ARGS[0]; | 
 | 		while (*sptr != '\0') { | 
 | 			if (*sptr != ' ') { | 
 | 				l_argv[i++] = sptr; | 
 | 				while ((*sptr != ' ') && (*sptr != '\0')) | 
 | 					sptr++; | 
 | 				if (*sptr == '\0') | 
 | 					break; | 
 | 				*sptr = '\0'; | 
 | 			} | 
 | 			sptr++; | 
 | 		} | 
 |  | 
 | 		/* Run the script with its arguments */ | 
 | 		mon_bin_run(total_args, l_argv, NULL); | 
 | 	} | 
 | 	return -1; | 
 | } | 
 | #endif | 
 |  | 
 | /* | 
 |  * Panic is called on unresolvable fatal errors. | 
 |  * It prints "panic: mesg", and then enters the kernel monitor. | 
 |  */ | 
 | void _panic(const char *file, int line, const char *fmt,...) | 
 | { | 
 | 	va_list ap; | 
 | 	struct per_cpu_info *pcpui; | 
 | 	/* We're panicing, possibly in a place that can't handle the lock checker */ | 
 | 	pcpui = &per_cpu_info[core_id_early()]; | 
 | 	pcpui->__lock_checking_enabled--; | 
 | 	va_start(ap, fmt); | 
 | 	printk("kernel panic at %s:%d, from core %d: ", file, line, | 
 | 	       core_id_early()); | 
 | 	vcprintf(fmt, ap); | 
 | 	cprintf("\n"); | 
 | 	va_end(ap); | 
 |  | 
 | dead: | 
 | 	monitor(NULL); | 
 | 	/* We could consider turning the lock checker back on here, but things are | 
 | 	 * probably a mess anyways, and with it on we would probably lock up right | 
 | 	 * away when we idle. */ | 
 | 	//pcpui->__lock_checking_enabled++; | 
 | 	smp_idle(); | 
 | } | 
 |  | 
 | /* like panic, but don't */ | 
 | void _warn(const char *file, int line, const char *fmt,...) | 
 | { | 
 | 	va_list ap; | 
 |  | 
 | 	va_start(ap, fmt); | 
 | 	printk("kernel warning at %s:%d, from core %d: ", file, line, | 
 | 	       core_id_early()); | 
 | 	vcprintf(fmt, ap); | 
 | 	cprintf("\n"); | 
 | 	va_end(ap); | 
 | } | 
 |  | 
 | static void run_links(linker_func_t *linkstart, linker_func_t *linkend) | 
 | { | 
 | 	/* Unlike with devtab, our linker sections for the function pointers are | 
 | 	 * 8 byte aligned (4 on 32 bit) (done by the linker/compiler), so we don't | 
 | 	 * have to worry about that.  */ | 
 | 	printd("linkstart %p, linkend %p\n", linkstart, linkend); | 
 | 	for (int i = 0; &linkstart[i] < linkend; i++) { | 
 | 		printd("i %d, linkfunc %p\n", i, linkstart[i]); | 
 | 		linkstart[i](); | 
 | 	} | 
 | } | 
 |  | 
 | static void run_linker_funcs(void) | 
 | { | 
 | 	run_links(__linkerfunc1start, __linkerfunc1end); | 
 | 	run_links(__linkerfunc2start, __linkerfunc2end); | 
 | 	run_links(__linkerfunc3start, __linkerfunc3end); | 
 | 	run_links(__linkerfunc4start, __linkerfunc4end); | 
 | } | 
 |  | 
 | /* You need to reference PROVIDE symbols somewhere, or they won't be included. | 
 |  * Only really a problem for debugging. */ | 
 | void debug_linker_tables(void) | 
 | { | 
 | 	extern struct dev __devtabstart[]; | 
 | 	extern struct dev __devtabend[]; | 
 | 	printk("devtab %p %p\nlink1 %p %p\nlink2 %p %p\nlink3 %p %p\nlink4 %p %p\n", | 
 | 	       __devtabstart, | 
 | 	       __devtabend, | 
 | 		   __linkerfunc1start, | 
 | 		   __linkerfunc1end, | 
 | 		   __linkerfunc2start, | 
 | 		   __linkerfunc2end, | 
 | 		   __linkerfunc3start, | 
 | 		   __linkerfunc3end, | 
 | 		   __linkerfunc4start, | 
 | 		   __linkerfunc4end); | 
 | } | 
 |  | 
 | #endif //Everything For Free |