237 lines
6.6 KiB
C
237 lines
6.6 KiB
C
// kernel.h
|
|
// Author: Josh Holtrop
|
|
// Date: 08/16/04
|
|
// Modified: 03/19/05
|
|
// This is the main kernel initialization and boot-strapping file
|
|
|
|
#include "kernel.h"
|
|
#include "multiboot.h"
|
|
#include "module.h"
|
|
#include "lang/lang.h"
|
|
#include "functions.h"
|
|
#include "mm/mm.h"
|
|
#include "mm/vmm.h"
|
|
#include "lang/conv.h"
|
|
#include "devices.h"
|
|
#include "display/display.h"
|
|
#include "display/kout.h"
|
|
#include "sys/io.h"
|
|
#include "sys/pic.h"
|
|
#include "char/keyboard.h"
|
|
#include "block/ramdisk.h"
|
|
#include "fs/vfs.h"
|
|
#include "fs/ext2/ext2.h"
|
|
|
|
mb_info_t mb_info_block;
|
|
mb_mmap_t mb_mmap[MAX_MMAP];
|
|
u32_t mmap_entries;
|
|
mb_module_t mb_modules[MAX_MODULES];
|
|
mb_apm_t mb_apm_table;
|
|
mb_module_t *real_mode_module; // pointer to real mode module (if present)
|
|
real_mode_param_t rm_params;
|
|
char mb_cmdline[256];
|
|
int criticalCounter; // semaphore for if interrupts are disabled
|
|
u32_t timer; // number of IRQ 0's
|
|
|
|
extern u32_t mm_freepages;
|
|
|
|
/* This function runs in segmented memory - 0xC000_0000 is mapped to 0x0 but 0x0
|
|
itself is an invalid linear address. Therefore, the multiboot information addresses
|
|
must be manually adjusted by VIRT_OFFSET to become valid linear addresses. */
|
|
mb_module_t *k_mbsave(mb_info_t *mbinfo, unsigned int mb_magic)
|
|
{
|
|
real_mode_module = NULL;
|
|
if (mb_magic != MULTIBOOT_BOOTLOADER_MAGIC)
|
|
{
|
|
char *msg = "Bad multiboot magic identifier!";
|
|
char *dest = (char *) CONSOLE_MEMORY;
|
|
while (*msg)
|
|
{
|
|
*dest++ = *msg++;
|
|
*dest++ = 0x04; //red error message
|
|
}
|
|
for (;;) ;
|
|
}
|
|
mb_info_block = *mbinfo;
|
|
if (mb_info_block.flags & MB_BOOTLOADER_COMMAND_LINE)
|
|
{
|
|
mb_info_block.cmdline += VIRT_OFFSET;
|
|
memcpy(mb_cmdline, (void *)mb_info_block.cmdline, 256);
|
|
mb_cmdline[255] = 0;
|
|
}
|
|
if (mb_info_block.flags & MB_BOOTLOADER_MODS)
|
|
{
|
|
mb_info_block.mods_addr += VIRT_OFFSET;
|
|
int i;
|
|
for (i = 0; i < mb_info_block.mods_count && i < MAX_MODULES; i++)
|
|
{
|
|
mb_modules[i] = ((mb_module_t *)mb_info_block.mods_addr)[i];
|
|
mb_modules[i].mod_start += VIRT_OFFSET;
|
|
mb_modules[i].mod_end += VIRT_OFFSET;
|
|
hos_module_header_t *mod = (hos_module_header_t *)mb_modules[i].mod_start;
|
|
if (mod->mod_magic == 0x4D534F48 && mod->mod_type == MOD_REAL_MODE)
|
|
real_mode_module = &mb_modules[i];
|
|
}
|
|
}
|
|
if (mb_info_block.flags & MB_BOOTLOADER_MMAP)
|
|
{
|
|
mb_info_block.mmap_addr += (VIRT_OFFSET - 4); //-4 to get to size field, not base_addr_low field
|
|
mb_mmap_t *mmap = (mb_mmap_t *)mb_info_block.mmap_addr;
|
|
int i, sz = 0;
|
|
for (i = 0; sz < mb_info_block.mmap_length && i < MAX_MMAP; i++)
|
|
{
|
|
sz += mmap->size + 4;
|
|
mb_mmap[i] = *mmap;
|
|
mmap = (mb_mmap_t *)(((u32_t) mmap) + mmap->size + 4);
|
|
mmap_entries++;
|
|
}
|
|
}
|
|
if (mb_info_block.flags & MB_BOOTLOADER_APM)
|
|
{
|
|
mb_info_block.apm_table += VIRT_OFFSET;
|
|
mb_apm_table = *(mb_apm_t *)mb_info_block.apm_table;
|
|
}
|
|
return real_mode_module;
|
|
}
|
|
|
|
/* Main kernel initialization routine */
|
|
void k_init()
|
|
{
|
|
criticalCounter++;
|
|
pic_remap(0x20, 0x28);
|
|
pic_mask1(0); //unmask IRQ's 0-7
|
|
pic_mask2(0); //unmask IRQ's 8-15
|
|
timer_init(HOS_TIMER_FREQ);
|
|
mm_init();
|
|
vmm_init();
|
|
devices_init();
|
|
if (real_mode_module)
|
|
{
|
|
if (rm_params.vid_addr) // there is video memory to map in
|
|
{
|
|
u32_t vid_mem = rm_params.width * rm_params.height;
|
|
switch (rm_params.bpp)
|
|
{
|
|
case 15: case 16:
|
|
vid_mem <<= 1; break;
|
|
case 24:
|
|
vid_mem *= 3; break;
|
|
case 32:
|
|
vid_mem <<= 2; break;
|
|
}
|
|
// map in video memory so we can access the video card's LFB
|
|
vmm_mapn(LFB_MEMORY, (u32_t)rm_params.vid_addr, (vid_mem >> 12) + 1);
|
|
}
|
|
}
|
|
display_init(); // initialize display subsystem
|
|
display_activate(11); // activate kernel dump vconsole
|
|
kprintf("HOS v0.16 initializing...\n");
|
|
kprintf("Kernel load size: %d (0x%x) bytes (%d kb)\n", kernel_size(), kernel_size(), kernel_size() >> 10);
|
|
kprintf("Kernel memory size: %d (0x%x) bytes (%d kb)\n", kernel_size_used(), kernel_size_used(), kernel_size_used() >> 10);
|
|
|
|
k_check(vfs_init(), "vfs_init() failed!");
|
|
|
|
int i;
|
|
for (i = 0; i < mb_info_block.mods_count; i++)
|
|
{
|
|
kprintf("Loaded kernel module %d: 0x%x - 0x%x (%d bytes)\n", i, mb_modules[i].mod_start, mb_modules[i].mod_end, mb_modules[i].mod_end - mb_modules[i].mod_start);
|
|
if (((mb_modules[i].mod_end - mb_modules[i].mod_start) > 1024) &&
|
|
((ext2_super_block_t *)(mb_modules[i].mod_start + 1024))->s_magic == EXT2_MAGIC)
|
|
{
|
|
// we found an initrd
|
|
minor_t initrd_minor = ramdisk_register((void *)mb_modules[i].mod_start, mb_modules[i].mod_end - mb_modules[i].mod_start);
|
|
kprintf("initrd (%dkb) loaded\n", (mb_modules[i].mod_end - mb_modules[i].mod_start) >> 10);
|
|
k_check(vfs_mount(DEV(MAJOR_RAMDISK, initrd_minor), "ext2", "/"), "Kernel panic: Could not mount initrd to /!");
|
|
}
|
|
}
|
|
|
|
/* vfs_open_file_t *root = vfs_open_dir("////");
|
|
if (root)
|
|
{
|
|
vfs_dir_entry_t dentry;
|
|
vfs_stat_t fstat;
|
|
while (!vfs_read_dir(root, &dentry))
|
|
{
|
|
vfs_stat_inode(dentry.inode_number, &fstat);
|
|
kprintf("%d\t", fstat.inode);
|
|
putc(fstat.type == VFS_FT_DIR ? 'd' : fstat.type == VFS_FT_CHAR ? 'c' : fstat.type == VFS_FT_BLOCK ? 'b' : fstat.type == VFS_FT_SYMLINK ? 'l' : '-');
|
|
putc(fstat.permissions & VFS_PERMS_UR ? 'r' : '-');
|
|
putc(fstat.permissions & VFS_PERMS_UW ? 'w' : '-');
|
|
putc(fstat.permissions & VFS_PERMS_UX ? 'x' : '-');
|
|
|
|
putc(fstat.permissions & VFS_PERMS_GR ? 'r' : '-');
|
|
putc(fstat.permissions & VFS_PERMS_GW ? 'w' : '-');
|
|
putc(fstat.permissions & VFS_PERMS_GX ? 'x' : '-');
|
|
|
|
putc(fstat.permissions & VFS_PERMS_OR ? 'r' : '-');
|
|
putc(fstat.permissions & VFS_PERMS_OW ? 'w' : '-');
|
|
putc(fstat.permissions & VFS_PERMS_OX ? 'x' : '-');
|
|
|
|
kprintf(" %d\t%d\t%d\t%d\t%s", fstat.links, fstat.uid, fstat.gid, fstat.size, dentry.name);
|
|
if (fstat.type == VFS_FT_CHAR || fstat.type == VFS_FT_BLOCK)
|
|
kprintf("\t(%d, %d)", fstat.dev >> 8, fstat.dev & 0xFF);
|
|
if (fstat.type == VFS_FT_SYMLINK)
|
|
{
|
|
char *link = kmalloc(4096);
|
|
vfs_link_deref(dentry.inode_number, link);
|
|
kprintf(" -> %s", link);
|
|
kfree(link);
|
|
}
|
|
putc('\n');
|
|
}
|
|
vfs_close_dir(root);
|
|
}
|
|
else
|
|
kprintf("Error: Could not open directory\n");
|
|
*/
|
|
criticalCounter--;
|
|
}
|
|
|
|
void isr(u32_t num)
|
|
{
|
|
criticalCounter++;
|
|
switch (num)
|
|
{
|
|
case 0x20: // timer
|
|
(*(u16_t *)CONSOLE_MEMORY)++;
|
|
timer++;
|
|
pic_eoi();
|
|
break;
|
|
case 0x21: // keyboard
|
|
isr_keyboard();
|
|
pic_eoi();
|
|
break;
|
|
case 0x30:
|
|
kprintf("User interrupt requested\n");
|
|
break;
|
|
default:
|
|
kprintf("Unhandled interrupt #%d, CR2 = 0x%x!\n", num, read_cr2());
|
|
halt();
|
|
}
|
|
criticalCounter--;
|
|
}
|
|
|
|
|
|
void k_enter_critical() // functions for implementing "atomic actions"
|
|
{
|
|
disable_ints();
|
|
criticalCounter++;
|
|
}
|
|
|
|
void k_leave_critical()
|
|
{
|
|
criticalCounter--;
|
|
if (!criticalCounter)
|
|
enable_ints();
|
|
}
|
|
|
|
void k_check(int val, char *msg)
|
|
{
|
|
if (val)
|
|
{
|
|
kprintf("\e[31;1m%s\n", msg);
|
|
halt();
|
|
}
|
|
}
|
|
|