Files

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();
}