📄 main.c
字号:
/* * Setup the root and CWD directories of the process. The root of * this process will correspond to the "global" root of the whole * system since all the future processes will duplicate it ! */ retval = sos_fs_new_opened_file(proc_init, rootfs->root, SOS_FS_OPEN_READ | SOS_FS_OPEN_WRITE, & init_root); if (SOS_OK != retval) { sos_process_unref(proc_init); return -SOS_ENOENT; } /* Duplicate the root file to set the current working directory of the init process */ retval = sos_fs_duplicate_opened_file(init_root, proc_init, & init_cwd); if (SOS_OK != retval) { sos_fs_close(init_root); sos_process_unref(proc_init); return -SOS_ENOENT; } /* Now update the process ! */ if ( ( SOS_OK != sos_process_chroot(proc_init, init_root, & unused_of) ) || ( SOS_OK != sos_process_chdir(proc_init, init_cwd, & unused_of) ) ) { sos_fs_close(init_root); sos_fs_close(init_cwd); sos_process_chroot(proc_init, NULL, & unused_of); sos_process_chdir(proc_init, NULL, & unused_of); sos_process_unref(proc_init); return -SOS_ENOENT; } /* Map the 'init' program in user space */ start_uaddr = sos_binfmt_elf32_map(as_init, "init"); if (0 == start_uaddr) { sos_process_unref(proc_init); return -SOS_ENOENT; } /* Allocate the user stack */ ustack = (SOS_PAGING_TOP_USER_ADDRESS - SOS_DEFAULT_USER_STACK_SIZE) + 1; retval = sos_dev_zero_map(as_init, &ustack, SOS_DEFAULT_USER_STACK_SIZE, SOS_VM_MAP_PROT_READ | SOS_VM_MAP_PROT_WRITE, /* PRIVATE */ 0); if (SOS_OK != retval) { sos_process_unref(proc_init); return -SOS_ENOMEM; } /* Now create the user thread */ new_thr = sos_create_user_thread(NULL, proc_init, start_uaddr, 0, 0, ustack + SOS_DEFAULT_USER_STACK_SIZE - 4, SOS_SCHED_PRIO_TS_LOWEST); if (! new_thr) { sos_process_unref(proc_init); return -SOS_ENOMEM; } sos_process_unref(proc_init); return SOS_OK;}/* ====================================================================== * The C entry point of our operating system */void sos_main(unsigned long magic, unsigned long arg){ unsigned i; sos_paddr_t sos_kernel_core_base_paddr, sos_kernel_core_top_paddr; struct sos_time tick_resolution; struct sos_fs_manager_instance * rootfs; /* Size of RAM above 1MB. Might be undefined ! */ unsigned long int upper_mem = 0; /* Setup bochs and console, and clear the console */ sos_bochs_setup(); sos_x86_videomem_setup(); sos_x86_videomem_cls(SOS_X86_VIDEO_BG_BLUE); /* Greetings from SOS */ if (magic == MULTIBOOT_BOOTLOADER_MAGIC) { /* Grub sends us a structure, called multiboot_info_t with a lot of precious informations about the system, see the multiboot documentation for more information. */ multiboot_info_t *mbi = (multiboot_info_t *) arg; /* Multiboot says: "The value returned for upper memory is maximally the address of the first upper memory hole minus 1 megabyte.". It also adds: "It is not guaranteed to be this value." aka "YMMV" ;) */ upper_mem = mbi->mem_upper; sos_x86_videomem_printf(1, 0, SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE, "Welcome From GRUB to %s%c RAM is %dMB (upper mem = 0x%x kB)", "SOS article 8", ',', (unsigned)(upper_mem >> 10) + 1, (unsigned)upper_mem); } else if (magic == 0x42244224) { /* Loaded with SOS bootsect */ upper_mem = arg; sos_x86_videomem_printf(1, 0, SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE, "Welcome to %s%c RAM is %dMB (upper mem = 0x%x kB)", "SOS article 8", ',', (unsigned)(upper_mem >> 10) + 1, (unsigned)upper_mem); } else /* Not loaded with grub, not from an enhanced bootsect */ sos_x86_videomem_printf(1, 0, SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE, "Welcome to SOS article 8"); sos_bochs_putstring("Message in a bochs: This is SOS article 8.\n"); /* Setup CPU segmentation and IRQ subsystem */ sos_gdt_subsystem_setup(); sos_idt_subsystem_setup(); /* Setup SOS IRQs and exceptions subsystem */ sos_exception_subsystem_setup(); sos_irq_subsystem_setup(); /* Configure the timer so as to raise the IRQ0 at a 100Hz rate */ sos_i8254_set_frequency(100); /* Setup the kernel time subsystem to get prepared to take the timer ticks into account */ tick_resolution = (struct sos_time) { .sec=0, .nanosec=10000000UL }; sos_time_subsysem_setup(& tick_resolution); /* We need to know the RAM size */ if (upper_mem == 0) { sos_x86_videomem_putstring(20, 0, SOS_X86_VIDEO_FG_LTRED | SOS_X86_VIDEO_BG_BLUE | SOS_X86_VIDEO_FG_BLINKING, "I don't know RAM size ! Load me with Grub..."); /* STOP ! */ for (;;) continue; } /* * Some interrupt handlers */ /* Binding some HW interrupts and exceptions to software routines */ sos_irq_set_routine(SOS_IRQ_TIMER, clk_it); /* * Setup physical memory management */ SOS_ASSERT_FATAL(SOS_OK == sos_physmem_subsystem_setup((upper_mem<<10) + (1<<20), &sos_kernel_core_base_paddr, &sos_kernel_core_top_paddr)); /* * Switch to paged-memory mode */ /* Disabling interrupts should seem more correct, but it's not really necessary at this stage */ SOS_ASSERT_FATAL(SOS_OK == sos_paging_subsystem_setup(sos_kernel_core_base_paddr, sos_kernel_core_top_paddr)); /* Bind the page fault exception */ sos_exception_set_routine(SOS_EXCEPT_PAGE_FAULT, pgflt_ex); /* * Setup kernel virtual memory allocator */ if (sos_kmem_vmm_subsystem_setup(sos_kernel_core_base_paddr, sos_kernel_core_top_paddr, bootstrap_stack_bottom, bootstrap_stack_bottom + bootstrap_stack_size)) sos_bochs_printf("Could not setup the Kernel virtual space allocator\n"); if (sos_kmalloc_subsystem_setup()) sos_bochs_printf("Could not setup the Kmalloc subsystem\n"); /* * Initialize the MMU context subsystem */ sos_mm_context_subsystem_setup(); /* * Initialize the CPU context subsystem */ sos_cpu_context_subsystem_setup(); /* * Bind the syscall handler to its software interrupt handler */ sos_swintr_subsystem_setup(); /* * Initialize the Kernel thread and scheduler subsystems */ /* Initialize kernel thread subsystem */ sos_thread_subsystem_setup(bootstrap_stack_bottom, bootstrap_stack_size); /* Initialize the scheduler */ sos_sched_subsystem_setup(); /* Declare the IDLE thread */ SOS_ASSERT_FATAL(sos_create_kernel_thread("idle", idle_thread, NULL, SOS_SCHED_PRIO_TS_LOWEST) != NULL); /* Prepare the stats subsystem */ sos_load_subsystem_setup(); /* Declare a thread that prints some stats */ SOS_ASSERT_FATAL(sos_create_kernel_thread("stat_thread", stat_thread, NULL, SOS_SCHED_PRIO_TS_LOWEST) != NULL); /* * Initialise user address space management subsystem */ sos_umem_vmm_subsystem_setup(); sos_dev_zero_subsystem_setup(); /* * Initialize process stuff */ sos_process_subsystem_setup(); /* Enabling the HW interrupts here, this will make the timer HW interrupt call the scheduler */ asm volatile ("sti\n"); SOS_ASSERT_FATAL(SOS_OK == sos_fs_virtfs_subsystem_setup()); SOS_ASSERT_FATAL(SOS_OK == sos_fs_subsystem_setup(NULL, "virtfs", NULL, & rootfs)); /* Start the 'init' process, which in turns launches the other programs */ start_init(rootfs); /* * We can safely exit from this function now, for there is already * an idle Kernel thread ready to make the CPU busy working... * * However, we must EXPLICITELY call sos_thread_exit() because a * simple "return" will return nowhere ! Actually this first thread * was initialized by the Grub bootstrap stage, at a time when the * word "thread" did not exist. This means that the stack was not * setup in order for a return here to call sos_thread_exit() * automagically. Hence we must call it manually. This is the ONLY * kernel thread where we must do this manually. */ sos_bochs_printf("Bye from primary thread !\n"); sos_thread_exit(); SOS_FATAL_ERROR("No trespassing !");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -