209 lines
6.8 KiB
C
209 lines
6.8 KiB
C
/* kernel.c - the C part of the kernel
|
|
* vim:ts=4 noexpandtab
|
|
*/
|
|
|
|
#include "multiboot.h"
|
|
#include "x86_desc.h"
|
|
#include "lib/lib.h"
|
|
#include "devices/i8259.h"
|
|
#include "lib/debug.h"
|
|
#include "tests.h"
|
|
|
|
#include "devices/pci.h"
|
|
#include "devices/acpi.h"
|
|
#include "devices/cpuid.h"
|
|
#include "devices/keyboard.h"
|
|
#include "devices/rtc.h"
|
|
#include "devices/serial.h"
|
|
#include "devices/tux.h"
|
|
#include "devices/sb16.h"
|
|
#include "devices/speaker.h"
|
|
#include "devices/pit.h"
|
|
#include "devices/qemu_vga.h"
|
|
#include "devices/cmos.h"
|
|
#include "devices/rng.h"
|
|
#include "devices/mouse.h"
|
|
|
|
#include "data/uiuc.h"
|
|
#include "data/vga_fonts.h"
|
|
|
|
#include "paging.h"
|
|
#include "fs/ece391fs.h"
|
|
#include "interrupts/sys_calls.h"
|
|
#include "interrupts/multiprocessing.h"
|
|
|
|
#include "lib/status_bar.h"
|
|
|
|
#define RUN_TESTS
|
|
|
|
/* Macros. */
|
|
/* Check if the bit BIT in FLAGS is set. */
|
|
#define CHECK_FLAG(flags, bit) ((flags) & (1 << (bit)))
|
|
|
|
/* Check if MAGIC is valid and print the Multiboot information structure
|
|
pointed by ADDR. */
|
|
void entry(unsigned long magic, unsigned long addr) {
|
|
|
|
multiboot_info_t *mbi;
|
|
|
|
// Init the PIC
|
|
i8259_init();
|
|
|
|
/* Clear the screen. */
|
|
clear();
|
|
|
|
/* Am I booted by a Multiboot-compliant boot loader? */
|
|
if (magic != MULTIBOOT_BOOTLOADER_MAGIC) {
|
|
printf("Invalid magic number: 0x%#x\n", (unsigned)magic);
|
|
return;
|
|
}
|
|
|
|
/* Set MBI to the address of the Multiboot information structure. */
|
|
mbi = (multiboot_info_t *) addr;
|
|
|
|
/* Print out the flags. */
|
|
printf("flags = 0x%#x\n", (unsigned)mbi->flags);
|
|
|
|
/* Are mem_* valid? */
|
|
if (CHECK_FLAG(mbi->flags, 0))
|
|
printf("mem_lower = %uKB, mem_upper = %uKB\n", (unsigned)mbi->mem_lower, (unsigned)mbi->mem_upper);
|
|
|
|
/* Is boot_device valid? */
|
|
if (CHECK_FLAG(mbi->flags, 1))
|
|
printf("boot_device = 0x%#x\n", (unsigned)mbi->boot_device);
|
|
|
|
/* Is the command line passed? */
|
|
if (CHECK_FLAG(mbi->flags, 2))
|
|
printf("cmdline = %s\n", (char *)mbi->cmdline);
|
|
|
|
if (CHECK_FLAG(mbi->flags, 3)) {
|
|
int mod_count = 0;
|
|
// int i;
|
|
module_t* mod = (module_t*)mbi->mods_addr;
|
|
ece391fs_init((uint32_t) mod->mod_start, (uint32_t) mod->mod_end);
|
|
while (mod_count < mbi->mods_count) {
|
|
printf("Module %d loaded at address: 0x%#x - 0x%#x\n", mod_count,
|
|
(unsigned int)mod->mod_start, (unsigned int)mod->mod_end);
|
|
// printf("First few bytes of module:\n");
|
|
// for (i = 0; i < 16; i++) {
|
|
// printf("0x%x ", *((char*)(mod->mod_start+i)));
|
|
// }
|
|
// printf("\n");
|
|
mod_count++;
|
|
mod++;
|
|
}
|
|
}
|
|
|
|
/* Bits 4 and 5 are mutually exclusive! */
|
|
if (CHECK_FLAG(mbi->flags, 4) && CHECK_FLAG(mbi->flags, 5)) {
|
|
printf("Both bits 4 and 5 are set.\n");
|
|
return;
|
|
}
|
|
|
|
/* Is the section header table of ELF valid? */
|
|
if (CHECK_FLAG(mbi->flags, 5)) {
|
|
elf_section_header_table_t *elf_sec = &(mbi->elf_sec);
|
|
printf("elf_sec: num = %u, size = 0x%#x, addr = 0x%#x, shndx = 0x%#x\n",
|
|
(unsigned)elf_sec->num, (unsigned)elf_sec->size,
|
|
(unsigned)elf_sec->addr, (unsigned)elf_sec->shndx);
|
|
}
|
|
|
|
/* Are mmap_* valid? */
|
|
if (CHECK_FLAG(mbi->flags, 6)) {
|
|
memory_map_t *mmap;
|
|
printf("mmap_addr = 0x%#x, mmap_length = 0x%x\n",
|
|
(unsigned)mbi->mmap_addr, (unsigned)mbi->mmap_length);
|
|
for (mmap = (memory_map_t *)mbi->mmap_addr;
|
|
(unsigned long)mmap < mbi->mmap_addr + mbi->mmap_length;
|
|
mmap = (memory_map_t *)((unsigned long)mmap + mmap->size + sizeof (mmap->size)))
|
|
printf(" size = 0x%x, base_addr = 0x%#x%#x\n type = 0x%x, length = 0x%#x%#x\n",
|
|
(unsigned)mmap->size,
|
|
(unsigned)mmap->base_addr_high,
|
|
(unsigned)mmap->base_addr_low,
|
|
(unsigned)mmap->type,
|
|
(unsigned)mmap->length_high,
|
|
(unsigned)mmap->length_low);
|
|
}
|
|
|
|
/* Construct an LDT entry in the GDT */
|
|
{
|
|
seg_desc_t the_ldt_desc;
|
|
the_ldt_desc.granularity = 0x0;
|
|
the_ldt_desc.opsize = 0x1;
|
|
the_ldt_desc.reserved = 0x0;
|
|
the_ldt_desc.avail = 0x0;
|
|
the_ldt_desc.present = 0x1;
|
|
the_ldt_desc.dpl = 0x0;
|
|
the_ldt_desc.sys = 0x0;
|
|
the_ldt_desc.type = 0x2;
|
|
|
|
SET_LDT_PARAMS(the_ldt_desc, &ldt, ldt_size);
|
|
ldt_desc_ptr = the_ldt_desc;
|
|
lldt(KERNEL_LDT);
|
|
}
|
|
|
|
/* Construct a TSS entry in the GDT */
|
|
{
|
|
seg_desc_t the_tss_desc;
|
|
the_tss_desc.granularity = 0x0;
|
|
the_tss_desc.opsize = 0x0;
|
|
the_tss_desc.reserved = 0x0;
|
|
the_tss_desc.avail = 0x0;
|
|
the_tss_desc.seg_lim_19_16 = TSS_SIZE & 0x000F0000;
|
|
the_tss_desc.present = 0x1;
|
|
the_tss_desc.dpl = 0x0;
|
|
the_tss_desc.sys = 0x0;
|
|
the_tss_desc.type = 0x9;
|
|
the_tss_desc.seg_lim_15_00 = TSS_SIZE & 0x0000FFFF;
|
|
|
|
SET_TSS_PARAMS(the_tss_desc, &tss, tss_size);
|
|
|
|
tss_desc_ptr = the_tss_desc;
|
|
|
|
tss.ldt_segment_selector = KERNEL_LDT;
|
|
tss.ss0 = KERNEL_DS;
|
|
tss.esp0 = 0x800000;
|
|
ltr(KERNEL_TSS);
|
|
}
|
|
|
|
/* Initialize devices, memory, filesystem, enable device interrupts on the
|
|
* PIC, any other initialization stuff... */
|
|
// All other devices are auto initialized when used
|
|
acpi_init(); // Find the ACPI tables, so we can leave space for them when paging
|
|
cpuid_init(); // No need of querying every time
|
|
keyboard_init(); // Required for user input
|
|
mouse_init(); // Mouse support
|
|
pci_init(); // Required for QEMU VGA
|
|
rng_init(); // Seed the RNG
|
|
// QEMU VGA initializes before paging, video memory redirected according to whether
|
|
// QEMU VGA is enabled
|
|
qemu_vga_init(QEMU_VGA_DEFAULT_WIDTH, QEMU_VGA_DEFAULT_HEIGHT, QEMU_VGA_DEFAULT_BPP);
|
|
|
|
init_paging();
|
|
process_init(); // Initialize multiprocessing structures
|
|
rtc_init(); // Initialize RTC virtualization
|
|
|
|
// Show build info on status bar
|
|
char build_ver[] = "nullOS by Team NULL, build " __DATE__ " " __TIME__;
|
|
status_bar_update_message(build_ver, strlen(build_ver), ATTR_YELLOW_ON_BLACK);
|
|
|
|
// #ifdef RUN_TESTS
|
|
// /* Run tests */
|
|
// sti();
|
|
// launch_tests();
|
|
// cli();
|
|
// #endif
|
|
|
|
pit_init(); // PIT initializes after multiprocessing, as it does process switching
|
|
// otherwise system will triple fault
|
|
|
|
/* Enable interrupts */
|
|
/* Do not enable the following until after you have set up your
|
|
* IDT correctly otherwise QEMU will triple fault and simple close
|
|
* without showing you any output */
|
|
sti();
|
|
|
|
/* Spin (nicely, so we don't chew up cycles) */
|
|
infinite_loop();
|
|
}
|