| /* See COPYRIGHT for copyright information. */ |
| |
| #ifdef __SHARC__ |
| #pragma nosharc |
| #endif |
| |
| #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> |
| |
| // zra: flag for Ivy |
| 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 (RO BND(__this, end) edata)[], (RO SNT 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); |
| 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(); |
| |
| printx_on = TRUE; |
| 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); |
| // zra: let's Ivy know we're done booting |
| 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 |