#include #include #include #include "vga.h" #include "serial.h" #include "console.h" #include "stdlib.h" #include "string.h" #include "stdio.h" #include "interrupts.h" #include "keyboard.h" #include "mouse.h" #include "pci.h" #include "setjmp.h" #include "kernel.h" static jmp_buf panic_jmp_buf; static void handle_keyboard_event( keyboard_event_t *event, void *context ); static void handle_mouse_event( mouse_event_t *event, void *context ); static bool terminate = false; // must be first entry in kernel.bin (0x8400) as stage 2 of // the boot loader expects the entry point to be here! void entry( void ) { serial_t serial; serial_init( &serial ); vga_t vga; vga_init( &vga ); vga_set_color( &vga, VGA_COLOR_LIGHT_GREY ); vga_set_background_color( &vga, VGA_COLOR_BLACK ); console_t console; console_init( &console ); console_add_vga_output( &console, &vga ); // TODO: breaks on real hardware, we need proper interrupt handling // and driver implementation as for the mouse and the keyboard console_add_serial_output( &console, &serial ); // initialize the early console of the kernel stdio_set_console( &console ); puts( "Started early kernel console" ); printf( "Kernel code and data is at 0x%X, kernel stack at 0x%X\n", 0x8400, 0x90000 ); puts( "Initializing interrupts" ); interrupt_t interrupt; interrupts_init( &interrupt ); puts( "Initializing PS/2 keyboard" ); keyboard_t keyboard; keyboard_init( &keyboard, &handle_keyboard_event, NULL ); interrupt_handler_t keyboard_interrupt_handler; interrupt_handler_init( &keyboard_interrupt_handler, IRQ_BASE + 0x01, &interrupt, keyboard_handle_interrupt, &keyboard ); interrupts_register_interrupt_handler( keyboard_interrupt_handler ); puts( "Initializing PS/2 mouse" ); mouse_t mouse; mouse_init( &mouse, &handle_mouse_event, (void *)&vga, vga.res_x, vga.res_y ); interrupt_handler_t mouse_interrupt_handler; interrupt_handler_init( &mouse_interrupt_handler, IRQ_BASE + 0x0C, &interrupt, mouse_handle_interrupt, &mouse ); interrupts_register_interrupt_handler( mouse_interrupt_handler ); // exit point in case of kernel panic, do this as soon as // possible if( setjmp( panic_jmp_buf ) > 0 ) { goto TERMINATE; } puts( "Enabling interrupt handing now.." ); interrupts_enable( ); puts( "Detecting devices via PCI.." ); pci_controller_t pci_controller; pci_controller_init( &pci_controller ); pci_controller_scan( &pci_controller ); puts( "Running.." ); // endless loop doing nothing, later we have to get events // here from queues and for instance print characters received // from the keyboard to stdout while( !terminate ) { // for now we are only interested in interrupts, // so we let the main thread sleep instead of // burning CPU.. kernel_halt( ); } TERMINATE: puts( "Deinitializing PS/2 mouse.." ); mouse_deinit( &mouse ); puts( "Deinitializing PS/2 keyboard.." ); keyboard_deinit( &keyboard ); puts( "Terminating" ); } void kernel_panic( const char *format, ... ) { (void)printf( "\n*** KERNEL PANIC ***\n" ); va_list args; va_start( args, format ); (void)vprintf( format, args ); va_end( args ); longjmp( panic_jmp_buf, 47 ); } static void handle_keyboard_event( keyboard_event_t *event, void *context ) { static int pos = 0; static char buf[80]; if( event->type == KEYBOARD_EVENT_TYPE_KEY_PRESSED ) { if( event->key == KEYBOARD_KEY_ASCII ) { if( event->ascii_key == '\n' ) { buf[pos] = '\0'; pos = 0; puts( "" ); if( strcmp( buf, "help" ) == 0 ) { puts( "quit - terminate os" ); puts( "mem - show memory usage" ); puts( "driver - show status of drivers" ); puts( "proc - show process status" ); } else if( strcmp( buf, "quit" ) == 0 ) { terminate = true; } else if( strcmp( buf, "mem" ) == 0 ) { // TODO: print memory usage } else if( strcmp( buf, "proc" ) == 0 ) { // TODO: print scheduler status } else if( strcmp( buf, "driver" ) == 0 ) { // TODO: print driver information } else { printf( "ERR: Unknown pre-boot command '%s'\n", buf ); } } else { printf( "%c", event->ascii_key ); buf[pos++] = event->ascii_key; } } } } static void handle_mouse_event( mouse_event_t *event, void *context ) { vga_t *vga = (vga_t *)context; switch( event->type ) { case MOUSE_EVENT_TYPE_BUTTON_UP: printf( "MOUSE UP %d AT X:%d, Y:%d\n", event->button, event->cursor_x, event->cursor_y ); break; case MOUSE_EVENT_TYPE_BUTTON_DOWN: printf( "MOUSE DOWN %d AT X:%d, Y:%d\n", event->button, event->cursor_x, event->cursor_y ); break; case MOUSE_EVENT_TYPE_MOVE: vga_inverse_colors_at( vga, event->old_cursor_x, event->old_cursor_y ); vga_inverse_colors_at( vga, event->cursor_x, event->cursor_y ); break; } }