diff --git a/include/system.h b/include/system.h deleted file mode 100644 index 87af581..0000000 --- a/include/system.h +++ /dev/null @@ -1,104 +0,0 @@ -#ifndef __SYSTEM_H -#define __SYSTEM_H - -// Data type declarations -typedef unsigned char byte; -typedef unsigned short word; -typedef unsigned int dword; - -/* This defines what the stack looks like after an ISR was running */ -typedef struct -{ - unsigned int gs, fs, es, ds; /* pushed the segs last */ - unsigned int edi, esi, ebp, esp, ebx, edx, ecx, eax; /* pushed by 'pusha' */ - unsigned int int_no, err_code; /* our 'push byte #' and ecodes do this */ - unsigned int eip, cs, eflags, useresp, ss; /* pushed by the processor automatically */ -} regs; - - -byte *TextVideoRam; -int cursor_x, cursor_y; -int current_mode_width; -int current_mode_height; - -// System functions declaration -void system_init(); -void *memcpy(void *dest, const void *src, int count); -void *memset(void *dest, char val, int count); -unsigned short *memsetw(unsigned short *dest, unsigned short val, int count); -int strlen (const char *str); -byte inportb (word _port); -byte inb (word _port); -void outportb (word _port, byte _data); -void outb (word _port, byte _data) ; - -// GDT, IDT, ISRs, IRQ functions declarations -void gdt_set_gate(int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char gran); -void gdt_install(); - -void idt_set_gate(unsigned char num, unsigned long base, unsigned short sel, unsigned char flags); -void idt_install(); - -void isrs_install(); - -void irq_install_handler(int irq, void (*handler)(regs *r)); -void irq_uninstall_handler(int irq); -void irq_install(); - - -// Initialize system - - -void *memcpy(void *dest, const void *src, int count) -{ - const char *sp = (const char *)src; - char *dp = (char *)dest; - for(; count != 0; count--) *dp++ = *sp++; - return dest; -} - -void *memset(void *dest, char val, int count) -{ - char *temp = (char *)dest; - for( ; count != 0; count--) *temp++ = val; - return dest; -} - -unsigned short *memsetw(unsigned short *dest, unsigned short val, int count) -{ - unsigned short *temp = (unsigned short *)dest; - for( ; count != 0; count--) *temp++ = val; - return dest; -} - - -// strlen -- Get lenght of str -int strlen (const char *str) -{ - int i; - for (i = 0; str[i]!=0; i++) {} - return i; -} - - -byte inportb (word _port) { - byte rv; - __asm__ __volatile__ ("inb %1, %0" : "=a" (rv) : "dN" (_port)); - return rv; -} -byte inb (word _port) { - byte rv; - __asm__ __volatile__ ("inb %1, %0" : "=a" (rv) : "dN" (_port)); - return rv; -} - - -void outportb (word _port, byte _data) { - __asm__ __volatile__ ("outb %1, %0" : : "dN" (_port), "a" (_data)); -} -void outb (word _port, byte _data) { - __asm__ __volatile__ ("outb %1, %0" : : "dN" (_port), "a" (_data)); -} - - -#endif \ No newline at end of file diff --git a/init.c b/init.c deleted file mode 100644 index 9dcd6ef..0000000 --- a/init.c +++ /dev/null @@ -1,37 +0,0 @@ -#include - - -void system_init() -{ - // Detect if color/monochrome screen - char c = (*(volatile unsigned short*)0x410)&0x30; - if (c==0x30) TextVideoRam = (byte *)0xb0000; - else TextVideoRam = (byte *)0xb8000; - - // Reset cursor, use 80x25 text video mode - current_mode_width = 80; - current_mode_height = 25; - cursor_x = cursor_y = 0; - - // Install GDT, IDT, ISRs and IRQs; Enable interrupts - gdt_install(); - idt_install(); - isrs_install(); - irq_install(); - __asm__ __volatile__ ("sti"); - - // Install PIT timer - timer_ticks = 0; - irq_install_handler(0, timer_handler); - timer_phase (100); - - // Install keyboard - kb_modifier_status = 0; - kb_lights_status = 0xFF; kb_update_LED(); - kb_lights_status = 0; kb_update_LED(); - irq_install_handler(1, kb_handler); - - // mouse_driver(); - - -} \ No newline at end of file diff --git a/kernel.bin b/kernel.bin deleted file mode 100644 index cb04e41..0000000 Binary files a/kernel.bin and /dev/null differ diff --git a/kernel/clock/cmos.h b/kernel/clock/cmos.h new file mode 100644 index 0000000..a8dba18 --- /dev/null +++ b/kernel/clock/cmos.h @@ -0,0 +1,25 @@ +volatile static byte cmos_data[128]; + +void cmos_write () +{ + byte i; + for (i = 0; i < 128; i++) { + //asm volatile ("cli"); + outportb(0x70, i); + iowait(); + outportb(0x71, cmos_data[i]); + //asm volatile ("sti"); + } +} + +void cmos_read () +{ + byte i; + for (i = 0; i < 128; i++) { + //asm volatile ("cli"); + outportb(0x70, i); + iowait(); + cmos_data[i] = inportb(0x71); + //asm volatile ("sti"); + } +} \ No newline at end of file diff --git a/kernel/clock/pictimer.c b/kernel/clock/pictimer.c new file mode 100644 index 0000000..9846d4a --- /dev/null +++ b/kernel/clock/pictimer.c @@ -0,0 +1,76 @@ +#include +#include "time.c" +int timer_ticks = 0; +int timer_hz; + +void timer_phase(int hz) +{ + int divisor = 1193180/hz; // Calculate the divisor + outportb(0x43, 0x36); // Set our command byte 0x36 + outportb(0x40, divisor&0xFF); // Set low byte + outportb(0x40, divisor>>8); // Set high byte + timer_hz = hz; +} + +void clock_show (int uptime_secs) +{ + int i; + for (i=0;i<80;i++) putc_pos_font (i, 0, ' ', 0x02, 0x0F); + puts_pos_font (64, 0, "Uptime:", 0x02, 0x0E); + + unsigned int uptime; + + uptime = uptime_secs%60; // Seconds + uptime += 100* ((uptime_secs/60)%60); // Minutes + uptime += 10000*(uptime_secs/3600); // Hours + + for (i=79;i>71;i--) { + if (i==77 || i==74) { + if (uptime_secs%2==0) putc_pos_font(i, 0, ':', 0x02, 0x0F); + else putc_pos_font(i, 0, ' ', 0x02, 0x0F); + } + else { + putc_pos_font(i, 0, (uptime%10)+'0', 0x02, 0x0F); + uptime/=10; + } + } + + // PRINT CURRENT TIME + uptime = clock.seconds; // Seconds + uptime += 100* clock.minutes; // Minutes + uptime += 10000*clock.hours; // Hours + + for (i=9;i>1;i--) { + if (i==7 || i==4) { + if (uptime_secs%2==0) putc_pos_font(i, 0, ':', 0x02, 0x0F); + else putc_pos_font(i, 0, ' ', 0x02, 0x0F); + } + else { + putc_pos_font(i,0, (uptime%10)+'0', 0x02, 0x0F); + uptime/=10; + } + } + if (clock.am_pm==0) puts_pos_font(10, 0, "am", 0x02, 0x0F); + else puts_pos_font(10, 0, "pm", 0x02, 0x0F); + + // PRINT DATE + putc_pos_font(32, 0, (clock.day/10)+'0', 0x02, 0x0E); + putc_pos_font(33, 0, (clock.day%10)+'0', 0x02, 0x0E); + puts_pos_font(35, 0, (char*)clock_months[clock.month], 0x02, 0x0F); + putc_pos_font(35+strlen(clock_months[clock.month])+1, 0, (clock.century/10)+'0', 0x02, 0x0E); + putc_pos_font(35+strlen(clock_months[clock.month])+2, 0, (clock.century%10)+'0', 0x02, 0x0E); + putc_pos_font(35+strlen(clock_months[clock.month])+3, 0, (clock.year/10)+'0', 0x02, 0x0E); + putc_pos_font(35+strlen(clock_months[clock.month])+4, 0, (clock.year%10)+'0', 0x02, 0x0E); + +} + + +void timer_handler(regs *r) +{ + timer_ticks++; + + if (timer_ticks % timer_hz == 0) { + clock_show (timer_ticks / timer_hz); + clock_inc(); + } +} \ No newline at end of file diff --git a/kernel/clock/time.c b/kernel/clock/time.c new file mode 100644 index 0000000..5b0e3a2 --- /dev/null +++ b/kernel/clock/time.c @@ -0,0 +1,143 @@ +#ifndef __TIME_C +#define __TIME_C + +#include "cmos.h" + +static const char* clock_months[] = {0, + "January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December"}; +static const char* clock_weekdays[] = {0, + "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; + +byte clock_months_len[] = { + 0, + 31, // January + 28, // February + 31, // March + 30, // April + 31, // May + 30, // June + 31, // July + 31, // August + 30, // September + 31, // October + 30, // November + 31 // December +}; + +typedef struct { + byte seconds; + byte minutes; + byte hours; + byte weekday; + byte day; + byte month; + byte year; + byte century; + byte am_pm; + +} TIME; +volatile static TIME clock; + +void RTC_get_time() +{ + cmos_read(); + + if ((cmos_data[0x0b]&4)==0) // BCD = true; + { + clock.seconds = (cmos_data[0x00]%16) + 10*(cmos_data[0x00]/16); + clock.minutes = (cmos_data[0x02]%16) + 10*(cmos_data[0x02]/16); + if ((cmos_data[0x0b]&2)==0) { // AM/PM + if (cmos_data[0x04]&80) { // pm + clock.hours = ((cmos_data[0x04]-0x80)%16) + 10*((cmos_data[0x04]-0x80)/16); + clock.am_pm = 1; + } + else { // am + clock.hours = (cmos_data[0x04]%16) + 10*(cmos_data[0x04]/16); + clock.am_pm = 0; + } + } + else { // 24 hours + clock.hours = (cmos_data[0x04]%16) + 10*(cmos_data[0x04]/16); + if (clock.hours > 12) { + clock.am_pm = 1; + clock.hours -= 12; + } + else clock.am_pm = 0; + } + + clock.weekday = (cmos_data[0x06]%16) + 10*(cmos_data[0x06]/16); + clock.day = (cmos_data[0x07]%16) + 10*(cmos_data[0x07]/16); + clock.month = (cmos_data[0x08]%16) + 10*(cmos_data[0x08]/16); + clock.year = (cmos_data[0x09]%16) + 10*(cmos_data[0x09]/16); + clock.century = (cmos_data[0x32]%16) + 10*(cmos_data[0x32]/16); + } + + else {//BCD = false; + clock.seconds = cmos_data[0x00]; + clock.minutes = cmos_data[0x02]; + if ((cmos_data[0x0b]&2)==0) { // AM/PM + if (cmos_data[0x04]&80) { // pm + clock.hours = cmos_data[0x04]-0x80; + clock.am_pm = 1; + } + else { // am + clock.hours = cmos_data[0x04]; + clock.am_pm = 0; + } + } + else { // 24 hours + clock.hours = cmos_data[0x02]; + if (clock.hours > 12) { + clock.am_pm = 1; + clock.hours -= 12; + } + else clock.am_pm = 0; + } + clock.weekday = cmos_data[0x06]; + clock.day = cmos_data[0x07]; + clock.month = cmos_data[0x08]; + clock.year = cmos_data[0x09]; + clock.century = cmos_data[0x32]; + } + // Leap years + if (clock.year % 4 == 0) clock_months_len[2]=29; + +} + +void clock_inc() +{ + // New minute + if (++clock.seconds > 59) { + clock.seconds = 0; + // New hour + if (++clock.minutes > 59) { + clock.minutes = 0; + clock.hours++; + if (clock.hours == 12 && clock.am_pm == 1) { // 11:59pm -> 0:00am + clock.hours = 0; clock.am_pm = 0; + // New day + clock.weekday = 1+(clock.weekday%7); + // New month + if (++clock.day > clock_months_len[clock.month]) { + clock.day = 1; + // New year + if (++clock.month>12) { + clock.month = 1; + // New century + if (++clock.year > 99) { + clock.year = 0; + clock.century++; + } + } + } + } + else if (clock.hours == 12 && clock.am_pm == 0) // 11:59am -> 12:00pm + clock.am_pm = 1; + else if (clock.hours == 13 && clock.am_pm == 1) // 12:59pm -> 1:59pm + clock.hours = 1; + } + } +} + +#endif \ No newline at end of file diff --git a/compile.bat b/kernel/compile.bat similarity index 89% rename from compile.bat rename to kernel/compile.bat index 8b34431..dcc17a1 100644 --- a/compile.bat +++ b/kernel/compile.bat @@ -10,7 +10,7 @@ set djgpp_path=C:\DJGPP\bin rem Compile loader %nasm_path%\nasm.exe -f aout -o %loader_name%.o %loader_name%.asm rem Compile main Kernel -%djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -finline-functions -nostdinc -fno-builtin -I./include -c -o main.o main.c +%djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -finline-functions -nostdinc -fno-builtin -I./include -c -o main.o main.c rem OTHER GCC/NASM SOURCES GO HERE @echo on @@ -19,4 +19,5 @@ rem OTHER GCC/NASM SOURCES GO HERE @echo Done! @pause -copy C:\CTAOS\KERNEL.BIN C:\SHARE +copy KERNEL.BIN C:\SHARE +copy KERNEL.BIN A:\KERNEL.CTA \ No newline at end of file diff --git a/console.o b/kernel/console.o similarity index 100% rename from console.o rename to kernel/console.o diff --git a/include/console.h b/kernel/include/conio.h similarity index 83% rename from include/console.h rename to kernel/include/conio.h index 4630fe8..b2718b1 100644 --- a/include/console.h +++ b/kernel/include/conio.h @@ -1,11 +1,13 @@ #include -#ifndef __CONSOLE_H -#define __CONSOLE_H +#ifndef __CONIO_H +#define __CONIO_H #define _ATTRIB 0x0F byte default_background, default_foreground; +char hex[] = "0123456789ABCDEF"; + // Change cursor position void text_mode_cursor(int x, int y) @@ -55,7 +57,15 @@ void scroll(int n) } -void _endl() +void prev_line() +{ + cursor_x = 79; + if (--cursor_y < 0) { + cursor_y = 0; cursor_x=0; + } +} + +void next_line() { cursor_x = 0; if (++cursor_y >=25) { @@ -78,9 +88,9 @@ void putc_pos(int x, int y, char c) // Put character on screen in the current cursor position; different font colors void putc_font(char c, byte back, byte fore) { - if (cursor_x > current_mode_width) _endl(); + if (cursor_x >= current_mode_width) next_line(); - if (c == '\n') {_endl(); return;}; + if (c == '\n') {next_line(); return;}; TextVideoRam[2*(cursor_y*current_mode_width+cursor_x)] = c; TextVideoRam[2*(cursor_y*current_mode_width+cursor_x)+1] = fore|(back<<4); cursor_x++; @@ -88,9 +98,9 @@ void putc_font(char c, byte back, byte fore) // Put character on screen in the current cursor position; default font colors void putc(char c) { - if (cursor_x > current_mode_width) _endl(); + if (cursor_x >= current_mode_width) next_line(); - if (c == '\n') {_endl(); return;}; + if (c == '\n') {next_line(); return;}; TextVideoRam[2*(cursor_y*current_mode_width+cursor_x)] = c; cursor_x++; } @@ -125,9 +135,8 @@ void puts_font(char *str, byte back, byte fore) putc_font(str[i], back, fore); } -void put_hex(int x, int y, unsigned int alpha) +void put_hex(unsigned int alpha) { - char hex[] = "0123456789ABCDEF"; char nr[9]; int i; for (i = 7; i >= 0; i--) { @@ -135,7 +144,18 @@ void put_hex(int x, int y, unsigned int alpha) alpha /= 16; } nr[8] = 0; - puts_pos(x, y, nr); + puts(nr); +} +void put_hex_pos(int x, int y, unsigned int alpha) +{ + char nr[9]; + int i; + for (i = 7; i >= 0; i--) { + nr[i] = hex[alpha%16]; + alpha /= 16; + } + nr[8] = 0; + puts_pos(x,y,nr); } void put_bin (int x, int y, byte xz) diff --git a/kernel/include/sys/declarat.h b/kernel/include/sys/declarat.h new file mode 100644 index 0000000..28fa675 --- /dev/null +++ b/kernel/include/sys/declarat.h @@ -0,0 +1,40 @@ +// Data type declarations +typedef unsigned char byte; +typedef unsigned short word; +typedef unsigned int dword; + +/* This defines what the stack looks like after an ISR was running */ +typedef struct +{ + unsigned int gs, fs, es, ds; /* pushed the segs last */ + unsigned int edi, esi, ebp, esp, ebx, edx, ecx, eax; /* pushed by 'pusha' */ + unsigned int int_no, err_code; /* our 'push byte #' and ecodes do this */ + unsigned int eip, cs, eflags, useresp, ss; /* pushed by the processor automatically */ +} regs; + + +// Functions +void system_init(); +void *memcpy(void *dest, const void *src, int count); +void *memset(void *dest, char val, int count); +unsigned short *memsetw(unsigned short *dest, unsigned short val, int count); +int strlen (const char *str); +byte inportb (word _port); +byte inb (word _port); +void outportb (word _port, byte _data); +void outb (word _port, byte _data) ; + +void gdt_set_gate(int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char gran); +void gdt_install(); + +void idt_set_gate(unsigned char num, unsigned long base, unsigned short sel, unsigned char flags); +void idt_install(); + +void isrs_install(); + +void irq_install_handler(int irq, void (*handler)(regs *r)); +void irq_uninstall_handler(int irq); +void irq_install(); +void kb_handler(regs *r); +void reboot(); +void kb_waitin(); \ No newline at end of file diff --git a/kernel/include/system.h b/kernel/include/system.h new file mode 100644 index 0000000..9ba8159 --- /dev/null +++ b/kernel/include/system.h @@ -0,0 +1,85 @@ +#ifndef __SYSTEM_H +#define __SYSTEM_H +#include + +#define true 1 +#define false 0 + +byte *TextVideoRam; +volatile static int cursor_x, cursor_y; +int current_mode_width; +int current_mode_height; + +void *memcpy(void *dest, const void *src, int count) +{ + const char *sp = (const char *)src; + char *dp = (char *)dest; + for(; count != 0; count--) *dp++ = *sp++; + return dest; +} + +void *memset(void *dest, char val, int count) +{ + char *temp = (char *)dest; + for( ; count != 0; count--) *temp++ = val; + return dest; +} + +unsigned short *memsetw(unsigned short *dest, unsigned short val, int count) +{ + unsigned short *temp = (unsigned short *)dest; + for( ; count != 0; count--) *temp++ = val; + return dest; +} + + +// strlen -- Get lenght of str +int strlen (const char *str) +{ + int i; + for (i = 0; *str!=0; str++) i++; + return i; +} + +int strcmp(const char *pStr1, const char *pStr2) +{ + char c1, c2; + int v; + + do { + c1 = *pStr1++; + c2 = *pStr2++; + /* the casts are necessary when pStr1 is shorter & char is signed */ + v = (unsigned int)c1 - (unsigned int)c2; + } while ((v == 0) && (c1 != '\0')); + + return v; +} + + + +byte inportb (word _port) { + byte rv; + __asm__ __volatile__ ("inb %1, %0" : "=a" (rv) : "dN" (_port)); + return rv; +} +byte inb (word _port) { + byte rv; + __asm__ __volatile__ ("inb %1, %0" : "=a" (rv) : "dN" (_port)); + return rv; +} + +static inline void iowait() { + asm volatile ("outb %al, $0x80"); +} + + +void outportb (word _port, byte _data) { + __asm__ __volatile__ ("outb %1, %0" : : "dN" (_port), "a" (_data)); +} +void outb (word _port, byte _data) { + __asm__ __volatile__ ("outb %1, %0" : : "dN" (_port), "a" (_data)); +} + + +#endif \ No newline at end of file diff --git a/kernel/kernel.bin b/kernel/kernel.bin new file mode 100644 index 0000000..a50d6ed Binary files /dev/null and b/kernel/kernel.bin differ diff --git a/kernel/kernel/epilogue.c b/kernel/kernel/epilogue.c new file mode 100644 index 0000000..8c7c267 --- /dev/null +++ b/kernel/kernel/epilogue.c @@ -0,0 +1,8 @@ +void reboot() +{ + unsigned char good = 0x02; + while ((good & 0x02) != 0) + good = inportb(0x64); + outportb(0x64, 0xFE); + __asm__ __volatile__ ("hlt"); +} \ No newline at end of file diff --git a/gdt.c b/kernel/kernel/gdt.c similarity index 100% rename from gdt.c rename to kernel/kernel/gdt.c diff --git a/idt.c b/kernel/kernel/idt.c similarity index 100% rename from idt.c rename to kernel/kernel/idt.c diff --git a/irq.c b/kernel/kernel/irq.c similarity index 92% rename from irq.c rename to kernel/kernel/irq.c index 4c1e861..e86a83e 100644 --- a/irq.c +++ b/kernel/kernel/irq.c @@ -48,18 +48,25 @@ void irq_uninstall_handler (int irq) * Interrupt Controller (PICs - also called the 8259's) in * order to make IRQ0 to 15 be remapped to IDT entries 32 to * 47 */ -void irq_remap(void) +void irq_remap(int pic1, int pic2) { + // Send ICW1 outportb(0x20, 0x11); outportb(0xA0, 0x11); - outportb(0x21, 0x20); - outportb(0xA1, 0x28); - outportb(0x21, 0x04); - outportb(0xA1, 0x02); + + // send ICW2 + outportb(0x21, pic1); // remap pics + outportb(0xA1, pic2); + + // send ICW3 + outportb(0x21, 4); + outportb(0xA1, 2); + + // Send ICW4 outportb(0x21, 0x01); outportb(0xA1, 0x01); - outportb(0x21, 0x0); - outportb(0xA1, 0x0); + + outportb(0x21, 0x00); } /* We first remap the interrupt controllers, and then we install @@ -67,7 +74,7 @@ void irq_remap(void) * is just like installing the exception handlers */ void irq_install() { - irq_remap(); + irq_remap(32,40); idt_set_gate(32, (unsigned)irq0, 0x08, 0x8E); idt_set_gate(33, (unsigned)irq1, 0x08, 0x8E); diff --git a/isrs.c b/kernel/kernel/isrs.c similarity index 77% rename from isrs.c rename to kernel/kernel/isrs.c index cf975eb..fa1ef02 100644 --- a/isrs.c +++ b/kernel/kernel/isrs.c @@ -1,5 +1,4 @@ #include -#include extern void isr0(); extern void isr1(); @@ -132,30 +131,30 @@ void fault_handler(regs *r) puts (" Blue Screen Of Death\n"); int i; for (i = 79; i>=0; i--) putc('='); puts_pos_font (15, 2, "A fatal error has occured, CTA OS has been halted.", 0x01, 0x0C); - puts_pos_font (10, 4, "gs", 0x01, 0x0B); put_hex(15, 4, r->gs); - puts_pos_font (10, 5, "fs", 0x01, 0x0B); put_hex(15, 5, r->fs); - puts_pos_font (10, 6, "es", 0x01, 0x0B); put_hex(15, 6, r->es); - puts_pos_font (10, 7, "ds", 0x01, 0x0B); put_hex(15, 7, r->ds); + puts_pos_font (10, 4, "gs", 0x01, 0x0B); put_hex_pos(15, 4, r->gs); + puts_pos_font (10, 5, "fs", 0x01, 0x0B); put_hex_pos(15, 5, r->fs); + puts_pos_font (10, 6, "es", 0x01, 0x0B); put_hex_pos(15, 6, r->es); + puts_pos_font (10, 7, "ds", 0x01, 0x0B); put_hex_pos(15, 7, r->ds); - puts_pos_font (40, 4, "edi", 0x01, 0x0B); put_hex(45, 4, r->edi); - puts_pos_font (40, 5, "esi", 0x01, 0x0B); put_hex(45, 5, r->esi); - puts_pos_font (40, 6, "ebp", 0x01, 0x0B); put_hex(45, 6, r->ebp); - puts_pos_font (40, 7, "esp", 0x01, 0x0B); put_hex(45, 7, r->esp); + puts_pos_font (40, 4, "edi", 0x01, 0x0B); put_hex_pos(45, 4, r->edi); + puts_pos_font (40, 5, "esi", 0x01, 0x0B); put_hex_pos(45, 5, r->esi); + puts_pos_font (40, 6, "ebp", 0x01, 0x0B); put_hex_pos(45, 6, r->ebp); + puts_pos_font (40, 7, "esp", 0x01, 0x0B); put_hex_pos(45, 7, r->esp); - puts_pos_font (10, 9, "eax", 0x01, 0x0B); put_hex(15, 9, r->eax); - puts_pos_font (10, 10, "ebx", 0x01, 0x0B); put_hex(15, 10, r->ebx); - puts_pos_font (40, 9, "ecx", 0x01, 0x0B); put_hex(45, 9, r->ecx); - puts_pos_font (40, 10, "edx", 0x01, 0x0B); put_hex(45, 10, r->edx); + puts_pos_font (10, 9, "eax", 0x01, 0x0B); put_hex_pos(15, 9, r->eax); + puts_pos_font (10, 10, "ebx", 0x01, 0x0B); put_hex_pos(15, 10, r->ebx); + puts_pos_font (40, 9, "ecx", 0x01, 0x0B); put_hex_pos(45, 9, r->ecx); + puts_pos_font (40, 10, "edx", 0x01, 0x0B); put_hex_pos(45, 10, r->edx); - puts_pos_font (10, 12, "int_no", 0x01, 0x0B); put_hex(17, 12, r->int_no); - puts_pos_font (10, 14, "Error code:", 0x01, 0x0B); put_hex(24, 14, r->err_code); + puts_pos_font (10, 12, "int_no", 0x01, 0x0B); put_hex_pos(17, 12, r->int_no); + puts_pos_font (10, 14, "Error code:", 0x01, 0x0B); put_hex_pos(24, 14, r->err_code); puts_pos_font (10, 15, "Error msg: ", 0x01, 0x0B); puts_pos(24, 15, exception_messages[r->int_no]); - puts_pos_font (10, 17, "eip", 0x01, 0x0B); put_hex(17, 17, r->eip); - puts_pos_font (10, 18, "cs", 0x01, 0x0B); put_hex(17, 18, r->cs); - puts_pos_font (10, 19, "eflags", 0x01, 0x0B); put_hex(17, 19, r->eflags); - puts_pos_font (10, 20, "useresp", 0x01, 0x0B); put_hex(17, 20, r->useresp); - puts_pos_font (10, 21, "ss", 0x01, 0x0B); put_hex(17, 21, r->ss); + puts_pos_font (10, 17, "eip", 0x01, 0x0B); put_hex_pos(17, 17, r->eip); + puts_pos_font (10, 18, "cs", 0x01, 0x0B); put_hex_pos(17, 18, r->cs); + puts_pos_font (10, 19, "eflags", 0x01, 0x0B); put_hex_pos(17, 19, r->eflags); + puts_pos_font (10, 20, "useresp", 0x01, 0x0B); put_hex_pos(17, 20, r->useresp); + puts_pos_font (10, 21, "ss", 0x01, 0x0B); put_hex_pos(17, 21, r->ss); puts_pos_font (29, 24, "!!! System Halted !!!", 0x01, 0x0C); for (;;); diff --git a/kernel/kernel/memory.c b/kernel/kernel/memory.c new file mode 100644 index 0000000..b5d21e7 --- /dev/null +++ b/kernel/kernel/memory.c @@ -0,0 +1,4 @@ +extern unsigned long* read_cr0(); +extern unsigned long* read_cr3(); +extern void write_cr0(unsigned long* alpha); +extern void write_cr3(unsigned long* alpha); \ No newline at end of file diff --git a/kernel/kernel/prologue.c b/kernel/kernel/prologue.c new file mode 100644 index 0000000..f0eb980 --- /dev/null +++ b/kernel/kernel/prologue.c @@ -0,0 +1,61 @@ +#include +#include "gdt.c" +#include "idt.c" +#include "isrs.c" +#include "irq.c" + +void system_init() +{ + // Detect if color/monochrome screen + char c = (*(volatile unsigned short*)0x410)&0x30; + if (c==0x30) TextVideoRam = (byte *)0xb0000; + else TextVideoRam = (byte *)0xb8000; + + // Reset cursor, use 80x25 text video mode + current_mode_width = 80; + current_mode_height = 25; + cursor_x = cursor_y = 0; + + // Install GDT, IDT, ISRs and IRQs; Enable interrupts + gdt_install(); + idt_install(); + isrs_install(); + irq_install(); + RTC_get_time(); + __asm__ __volatile__ ("sti"); + + // Install PIT timer + timer_ticks = 0; + timer_phase (100); + irq_install_handler(0, timer_handler); + + // Install keyboard (part 1): install IRQ1 and start BAT test + kb_modifier_status = 0; + irq_install_handler(1, kb_handler); + kb_waitin(); outportb(0x60, 0xFF); // Reset kb + + + // other drivers come here!!; + + + + // Install keyboard (part 2): BAT test results & set repeat rates + byte temp; + do temp = inportb(0x60); + while (temp!=0xAA && temp!=0xFC); + // KB failed BAT TEST + if (temp == 0xFC) puts_font("\nKeyboard error: failed BAT test.", 0x07, 0x0C); + kb_set_repeat(1, 11); + + // Install keyboard (part 3): set scancode set 2 + kb_set_scancodeset(2); // Set new scancode set + + kb_waitin(); outportb(0x64, 0x20); // Get "Command byte" + do { temp = inportb(0x60); + } while (temp==0xFA || temp==0xAA); + + temp &= 0xFF - (1<<6); // Set bit6 to 0: disable conversion + kb_waitin(); outportb(0x64, 0x60); // Function to write cmd byte + kb_waitin(); outportb(0x60, temp); // Send it + memset(kb_array, 0, 16); +} \ No newline at end of file diff --git a/kernel/keyboard/key_list.txt b/kernel/keyboard/key_list.txt new file mode 100644 index 0000000..5ff143e --- /dev/null +++ b/kernel/keyboard/key_list.txt @@ -0,0 +1,135 @@ +*0x00 Pause/Break +0x01 F9 +0x02 F7 +0x03 F5 +0x04 F3 +0x05 F1 +0x06 F2 +0x07 F12 +0x08 Print Screen +0x09 F10 +0x0A F8 +0x0B F6 +0x0C F4 +0x0D Tab +0x0E `~ +0x0F + +0x10 +0x11 +0x12 +0x13 +0x14 +0x15 Q +0x16 1! +0x17 +0x18 +0x19 +0x1A Z +0x1B S +0x1C A +0x1D W +0x1E 2@ +0x1F LeftWin + +0x20 +0x21 C +0x22 X +0x23 D +0x24 E +0x25 4$ +0x26 3# +0x27 RightWin +0x28 +0x29 Space +0x2A V +0x2B F +0x2C T +0x2D R +0x2E 5% +0x2F Menu + +0x30 +0x31 N +0x32 B +0x33 H +0x34 G +0x35 Y +0x36 6^ +0x37 +0x38 +0x39 +0x3A M +0x3B J +0x3C U +0x3D 7& +0x3E 8* +0x3F + +0x40 +0x41 ,< +0x42 K +0x43 I +0x44 O +0x45 0) +0x46 9( +0x47 +0x48 +0x49 .> +0x4A /? +0x4B L +0x4C ;: +0x4D P +0x4E -_ +0x4F + +0x50 +0x51 +0x52 '" +0x53 +0x54 [{ +0x55 =+ +0x56 +0x57 +0x58 +0x59 Numpad Enter +0x5A Enter +0x5B ]} +0x5C +0x5D \| +0x5E End +0x5F Left + +0x60 Home +0x61 Insert +0x62 Delete +0x63 Down +0x64 Right +0x65 Up +0x66 Backspace +0x67 PageDown +0x68 PageUp +0x69 Numpad 1 (end) +0x6A Numpad / +0x6B Numpad 4 (left) +0x6C Numpad 7 (Home) +0x6D +0x6E +0x6F + +0x70 Numpad 0 (insert) +0x71 Numpad . (del) +0x72 Numpad 2 (down) +0x73 Numpad 5 +0x74 Numpad 6 (right) +0x75 Numpad 8 (up) +0x76 Esc +0x77 +0x78 F11 +0x79 Numpad + +0x7A Numpad 3 (pgdwn) +0x7B Numpad - +0x7C Numpad * +0x7D Numpad 9 (pgup) +0x7E +0x7F \ No newline at end of file diff --git a/kernel/keyboard/keyb.c b/kernel/keyboard/keyb.c new file mode 100644 index 0000000..3ab763c --- /dev/null +++ b/kernel/keyboard/keyb.c @@ -0,0 +1,60 @@ + + +void kb_test() +{ + byte temp=0, secs=0; + + puts("\nTHIS WILL TEST FEW COMMANDS OF THE PS/2 KEYBOARD.\n"); + + + puts("\nEcho... "); + while ((inportb(0x64)&2)!=0); + outportb(0x60, 0xEE); +/* while ((inportb(0x64)&1)!=0); + temp = inportb(0x60); + putc_font('[', 0x07, 0x02); + putc_font(hex[temp/16], 0x07, 0x02); + putc_font(hex[temp%16], 0x07, 0x02); + putc_font(']', 0x07, 0x02);*/ + + + puts("\nSet LEDs - SCROLL on... "); + while ((inportb(0x64)&2)!=0); + outportb(0x60, 0xED); +/* while ((inportb(0x64)&2)!=0); + outportb(0x60, 1); + while ((inportb(0x64)&1)!=0); + temp = inportb(0x60);*/ + putc_font('[', 0x07, 0x02); + putc_font(hex[temp/16], 0x07, 0x02); + putc_font(hex[temp%16], 0x07, 0x02); + putc_font(']', 0x07, 0x02); + + + puts("\nGet current scancode set... "); + while ((inportb(0x64)&2)!=0); + outportb(0x60, 0xF0); + while ((inportb(0x64)&2)!=0); + outportb(0x60, 0); + +/* while ((inportb(0x64)&1)!=0); + temp = inportb(0x60); + putc_font('[', 0x07, 0x02); + putc_font(hex[temp/16], 0x07, 0x02); + putc_font(hex[temp%16], 0x07, 0x02); + putc_font(']', 0x07, 0x02);*/ + + + puts("\nTurning on 2 leds (don't know which ones :P)... "); + while ((inportb(0x64)&2)!=0); + outportb(0x60, 0xED); + while ((inportb(0x64)&2)!=0); + outportb(0x60, (byte)1|2); + /* while ((inportb(0x64)&1)!=0); + temp = inportb(0x60); + putc_font('[', 0x07, 0x02); + putc_font(hex[temp/16], 0x07, 0x02); + putc_font(hex[temp%16], 0x07, 0x02); + putc_font(']', 0x07, 0x02);*/ + +} \ No newline at end of file diff --git a/kernel/keyboard/keyus.c b/kernel/keyboard/keyus.c new file mode 100644 index 0000000..392a4ff --- /dev/null +++ b/kernel/keyboard/keyus.c @@ -0,0 +1,179 @@ +#include "keyus.h" + +// kb_key_return 4-byte structure +typedef struct { + byte status; + byte lights; + byte scancode; + byte character; +} kb_key; + +byte kb_array[16]; +volatile static byte kb_newdata; + +/*********DEBUG**************/ +void kb_print_binary(int x, int y, byte what) +{ + char arr[9]; int i; + for (i = 7; i>=0; i--, what/=2) + arr[i] = (what%2) + '0'; + + arr[8] = 0; + + puts_pos(x,y,arr); + +} +/*********DEBUG**************/ + +void kb_set_key(byte scancode, byte val) +{ + byte pos = scancode/8; + byte offset = scancode%8; + + if (val) { + kb_array[pos] |= 1<', '?', 'L', ':', 'P', '_', 0, + 0, 0, '\"', 0, '{', '+', 0, 0, 0, '\n', '\n', '}', 0, '|', 0, 0, + 0, 0, 0x7F, 0, 0, 0, '\b', 0, 0, '1', '/', '4', '7', 0, 0, 0, + '0', '.', '2', '5', '6', '8', 0, 0, 0, '+', '3', '-', '*', '9', 0, 0 + }; +/* kb_modifier_status: + BIT | Description + ----+----------------------------------- + 0 | Left Shift + 1 | Right Shift + 2 | Left Alt + 3 | Right Alt + 4 | Left CTRL + 5 | Right CTRL + 6 | Fake Shift */ +byte kb_modifier_status; + +/* kb_modifier_status: + BIT | Description + ----+----------------------------------- + 0 | Gray + 1 | Break code + 2 | 0xE1 (pause/break) + 3 | Recieved first byte from pause/break */ +byte kb_prefix; + +/* kb_lights_status + BIT | Description + ----+----------------------------------- + 0 | SCROLLOCK + 1 | NUMLOCK + 2 | CAPSLOCK */ +byte kb_lights_status; +byte kb_scancode_set; + + +/*************************************** + * Set repeat rate/delay * + *************************************** + Values for inter-character delay (bits 4-0) + (characters per second; default is 10.9) + | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 + ----+----+----+----+----+----+----+----+---- + 0 |30.0|26.7|24.0|21.8|20.0|18.5|17.1|16.0 + 8 |15.0|13.3|12.0|10.9|10.0|9.2 |8.6 |8.0 + 16 |7.5 |6.7 |6.0 |5.5 |5.0 |4.6 |4.3 |4.0 + 24 |3.7 |3.3 |3.0 |2.7 |2.5 |2.3 |2.1 |2.0 + + Values for delay: + (miliseconds; default is 500) + 0 | 1 | 2 | 3 + -----+-----+-----+----- + 250 | 500 | 750 | 1000 + + ***************************************/ +void kb_set_repeat(byte rate, byte delay) +{ + if (rate>3 || delay>31) return; + + byte out = rate<<5 | delay; + while ((inportb(0x64)&2) != 0); + outportb(0x60, 0xF3); + while ((inportb(0x64)&2) != 0); + outportb(0x60, out); +} + + +/*************************************** + * Set keyboard LEDs * + *************************************** + +-----------+-------+-------+--------+ + | Bits 7-3 | Bit 2 | Bit 1 | Bit 0 | + | 0 | Caps | Num | Scroll | + |(reserved) | lock | lock | lock | + +-----------+-------+-------+--------+ + ***************************************/ +void kb_set_LEDs(byte status) +{ + while ((inportb (0x64)&2)!=0); + outportb (0x60, 0xED); + + while ((inportb (0x64)&2)!=0); + outportb (0x60, status); +} + +/*************************************** + * Set scancode set * + *************************************** + 0 Get current scancode set + 1 Set to scancode set 1 + 2 Set to scancode set 2 + 3 Set to scancode set 3 + ***************************************/ +void kb_set_scancodeset(byte set) +{ + //If ask for current scancode, tell kb handler what to expect + if (set==0) kb_scancode_set = 4; + + while ((inportb (0x64)&2)!=0); + outportb (0x60, 0xF0); + + while ((inportb (0x64)&2)!=0); + outportb (0x60, set); +} + + +void kb_waitin() +{ + int fail_safe=200000; + while ((inportb(0x64)&2)!=0 && fail_safe>0) fail_safe--; +} + +void kb_waitout() +{ + int fail_safe=200000; + while ((inportb(0x64)&1)==0 && fail_safe>0) fail_safe--; +} \ No newline at end of file diff --git a/link.ld b/kernel/link.ld similarity index 100% rename from link.ld rename to kernel/link.ld diff --git a/loader.asm b/kernel/loader.asm similarity index 95% rename from loader.asm rename to kernel/loader.asm index c5488fc..eba57f1 100644 --- a/loader.asm +++ b/kernel/loader.asm @@ -442,8 +442,37 @@ irq_common_stub: add esp, 8 iret + +[global _read_cr0] +_read_cr0: + mov eax, cr0 + retn + +[global _write_cr0] +_write_cr0: + push ebp + mov ebp, esp + mov eax, [ebp+8] + mov cr0, eax + pop ebp + retn +[global _read_cr3] +_read_cr3: + mov eax, cr3 + retn +[global _write_cr3] +_write_cr3: + push ebp + mov ebp, esp + mov eax, [ebp+8] + mov cr3, eax + pop ebp + retn + + + SECTION .bss resb 8192 ; This reserves 8KBytes of memory here _sys_stack: \ No newline at end of file diff --git a/kernel/loader.o b/kernel/loader.o new file mode 100644 index 0000000..9e620cd Binary files /dev/null and b/kernel/loader.o differ diff --git a/kernel/main.c b/kernel/main.c new file mode 100644 index 0000000..623bb3c --- /dev/null +++ b/kernel/main.c @@ -0,0 +1,18 @@ +#include +#include +#include "clock/pictimer.c" +#include "keyboard/keyus.c" +#include "kernel/prologue.c" +#include "kernel/epilogue.c" +#include "shell/shell.c" + +int main() +{ + system_init(); + + shell(); + + // do nothing + for(;;); + return 0; +} \ No newline at end of file diff --git a/kernel/main.o b/kernel/main.o new file mode 100644 index 0000000..c776921 Binary files /dev/null and b/kernel/main.o differ diff --git a/kernel/shell/apps.h b/kernel/shell/apps.h new file mode 100644 index 0000000..cf2adb5 --- /dev/null +++ b/kernel/shell/apps.h @@ -0,0 +1,122 @@ +const char *apps_lst[] = { + "", + "reboot", + "osver", + "date", + "place", + "cls", + "memory" + }; +int apps_count = 7; + +void apps_osver() +{ + puts("CTA OS v0.1"); + puts("\n(c) CTA 2010.\n"); +} + +void apps_date() +{ + puts("Today is "); + puts((char*)clock_weekdays[clock.weekday]); + puts(", "); putc((clock.day/10)+'0'); + putc((clock.day%10)+'0'); + puts(" "); puts((char*)clock_months[clock.month]); + puts(" "); putc((clock.century/10)+'0'); + putc((clock.century%10)+'0'); + putc((clock.year/10)+'0'); + putc((clock.year%10)+'0'); + putc('\n'); +} + +void apps_place() +{ + puts("On your desk, if you didn't notice... \n"); +} + +void apps_clrscr() +{ + clrscr(); +} + +void apps_memory(const int pn, const char* param[]) +{ + if (pn<3) { + puts ("Correct syntax: memory [start_address] [end_address] (in hex)\n"); + return; + } + + byte *start, *end; + byte l1 = strlen(param[1]), l2 = strlen(param[2]); + unsigned int a; + int i; byte *count; + + a = 0; + for(i = 0; i < l1; i++) { + switch (param[1][i]) { + case 'a': + case 'A': a = a*16 + 10; break; + case 'b': + case 'B': a = a*16 + 11; break; + case 'c': + case 'C': a = a*16 + 12; break; + case 'd': + case 'D': a = a*16 + 13; break; + case 'e': + case 'E': a = a*16 + 14; break; + case 'f': + case 'F': a = a*16 + 15; break; + + default: if (!(param[1][i]>='0' && param[1][i]<='9')) { + puts ((char*)param[1]); puts(" is not a valid hex address.\n"); + return; + } + a = a*16 + (param[1][i] - '0'); + break; + } + } + start = (byte *)a; + + a = 0; + for(i = 0; i < l2; i++) { + switch (param[2][i]) { + case 'a': + case 'A': a = a*16 + 10; break; + case 'b': + case 'B': a = a*16 + 11; break; + case 'c': + case 'C': a = a*16 + 12; break; + case 'd': + case 'D': a = a*16 + 13; break; + case 'e': + case 'E': a = a*16 + 14; break; + case 'f': + case 'F': a = a*16 + 15; break; + + default: if (!(param[2][i]>='0' && param[2][i]<='9')) { + puts ((char*)param[2]); puts(" is not a valid hex address.\n"); + return; + } + a = a*16 + (param[2][i] - '0'); + break; + } + } + end = (byte *)a; + + while (start <= end) { + put_hex ((unsigned int) start); puts(": "); + + for (count = start; count < start+16; count++) { + putc(hex[*count/16]); putc(hex[*count%16]); + putc(' '); + } + puts(" "); + for (count = start; count < start+16; count++) + putc(*count); + + putc('\n'); + start+=16; + } + + +} \ No newline at end of file diff --git a/kernel/shell/shell.c b/kernel/shell/shell.c new file mode 100644 index 0000000..9f6220d --- /dev/null +++ b/kernel/shell/shell.c @@ -0,0 +1,81 @@ +#include +#include "apps.h" + +void get_str(char *str, int len) +{ + kb_key alpha; + + int i; + for (i = 0; i0) { // Only backspace our string + if (--cursor_x < 0) { // Begin of row - 1 = End of previous row + cursor_x = 79; cursor_y--; + } + putc_pos(cursor_x, cursor_y, 0); + str[--i] = 0; + } + i--; break; + + case '\n': str[i]=0; putc('\n'); return; + + default: putc(alpha.character); + str[i] = alpha.character; + str[i+1] = 0; + break; + } + } +} + + +void shell() +{ + char str[256]; + char* param[16]; + int i, len, params=0; + + set_default_colors (0x07, 0x04); + clrscr(); + + + + for (;;) { + puts("\n] "); + get_str(str, 256); + + len = strlen(str); + + // Ignore spaces in front of command + i=0; params = 0; + while (str[i] == ' ') i++; + param[params] = str+i; params++; i++; // Parameter 0 = app itself + + + for (; i < len && params<16; i++) { + if (str[i] == ' ') str[i]=0; + + if (str[i] != 0 && str[i-1]==0) { + param[params] = str+i; params++; + } + } + + for (i = 0; strcmp(apps_lst[i], param[0])!=0 && i */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, /* < ... F10 */ - 0, /* 69 - Num lock*/ - 0, /* Scroll Lock */ - 0, /* Home key */ - 0, /* Up Arrow */ - 0, /* Page Up */ - '-', - 0, /* Left Arrow */ - 0, - 0, /* Right Arrow */ - '+', - 0, /* 79 - End key*/ - 0, /* Down Arrow */ - 0, /* Page Down */ - 0, /* Insert Key */ - 0, /* Delete Key */ - 0, 0, 0, - 0, /* F11 Key */ - 0, /* F12 Key */ - 0, /* All other keys are undefined */ -}; - -unsigned char kbdus_shift[128] = -{ - 0, 27, '!', '@', '#', '$', '%', '^', '&', '*', /* 9 */ - '(', ')', '_', '+', '\b', /* Backspace */ - '\t', /* Tab */ - 'Q', 'W', 'E', 'R', /* 19 */ - 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n', /* Enter key */ - 0, /* 29 - Control */ - 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', /* 39 */ - '\"', '~', 0, /* Left shift */ - '|', 'Z', 'X', 'C', 'V', 'B', 'N', /* 49 */ - 'M', '<', '>', '?', 0, /* Right shift */ - '*', - 0, /* Alt */ - ' ', /* Space bar */ - 0, /* Caps lock */ - 0, /* 59 - F1 key ... > */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, /* < ... F10 */ - 0, /* 69 - Num lock*/ - 0, /* Scroll Lock */ - 0, /* Home key */ - 0, /* Up Arrow */ - 0, /* Page Up */ - '-', - 0, /* Left Arrow */ - 0, - 0, /* Right Arrow */ - '+', - 0, /* 79 - End key*/ - 0, /* Down Arrow */ - 0, /* Page Down */ - 0, /* Insert Key */ - 0, /* Delete Key */ - 0, 0, 0, - 0, /* F11 Key */ - 0, /* F12 Key */ - 0, /* All other keys are undefined */ -}; - - - -/* kb_modifier_status: - BIT | Description - ----+----------------------------------- - 0 | Left Shift - 1 | Right Shift - 2 | Left Alt - 3 | Right Alt - 4 | Left CTRL - 5 | Right CTRL - 6 | Fake Shift - 7 | Special */ -unsigned char kb_modifier_status; - -/* kb_lights_status - BIT | Description - ----+----------------------------------- - 0 | SCROLLOCK - 1 | NUMLOCK - 2 | CAPSLOCK */ -unsigned char kb_lights_status; - -void kb_update_LED() -{ - while ((inportb (0x64)&2)!=0); - outportb (0x60, 0xED); - - while ((inportb (0x64)&2)!=0); - outportb (0x60, kb_lights_status); -} - -/* kb_toggle_LED - Toggle NUM/CAPS/SCROLL LOCK LEDs. 0 to ignore. If all 0, reset; */ -void kb_toggle_LED(int NUM, int CAPS, int SCROLL) -{ - if (NUM) kb_lights_status ^= 1<<1; - if (CAPS) kb_lights_status ^= 1<<2; - if (SCROLL) kb_lights_status ^= 1; - if ((!NUM) && (!CAPS) && (!SCROLL)) kb_lights_status = 0; - kb_update_LED(); -} - -byte prev, scancode; -void kb_handler(regs *r) { - scancode = inportb(0x60); - - puts_pos(0, 0, "Key Pressed ");put_hex(30, 0, scancode); - - switch (scancode) { - // Special - case 0x0E: kb_modifier_status |= 1<<7; - break; - - // Left Shift or fake shift make - case 0x2A: if (kb_modifier_status && 128) kb_modifier_status |= 1<<6; - else kb_modifier_status |= 1; - break; - - // Left Shift or fake shift release - case 0xAA: if (kb_modifier_status && 128) kb_modifier_status &= (1<<6) ^0xFF; - else kb_modifier_status &= 1 ^0xFF; - break; - - // Right Shift make - case 0x36: kb_modifier_status |= 1<<1; - break; - - // Right shift release - case 0xB6: kb_modifier_status &= (1<<1) ^0xFF; - break; - - // Left Alt or Right Alt make - case 0x38: if (kb_modifier_status && 128) kb_modifier_status |= 1<<3; - else kb_modifier_status |= 1<<2; - break; - - // Left Alt or Right Alt release - case 0xB8: if (kb_modifier_status && 128) kb_modifier_status &= (1<<3) ^0xFF; - else kb_modifier_status &= (1<<2) ^0xFF; - break; - - // Left Ctrl or Right Ctrl make - case 0x1D: if (kb_modifier_status && 128) kb_modifier_status |= 1<<5; - else kb_modifier_status |= 1<<4; - break; - - // Left Ctrl or Right Ctrl release - case 0x9D: if (kb_modifier_status && 128) kb_modifier_status &= (1<<5) ^0xFF; - else kb_modifier_status &= (1<<5) ^0xFF; - break; - - // Caps, Num and Scroll (in this order) - case 0x3A: kb_toggle_LED (0,1,0); break; - case 0x45: kb_toggle_LED (1,0,0); break; - case 0x46: kb_toggle_LED (0,0,1); break; - - default: if (scancode & 0x80) break; - if (scancode != prev) kb_modifier_status &= (1<<7) ^0xFF; - if ((kb_modifier_status && 1) || (kb_modifier_status && 2)) - putc_pos(50, 0, kbdus_shift[scancode]); - else putc_pos (50, 0, kbdus[scancode]); - break; - } - - outportb(0x20, 0x20); -} - - -char kb_getch() -{ - regs *r = 0; - do { - prev = scancode; kb_handler(r); } - while (prev == scancode || prev+0x80 == scancode); - - - if ((kb_modifier_status && 1) || (kb_modifier_status && 2)) - return kbdus_shift[scancode]; - - return kbdus[scancode]; -} - -void kb_get_status() -{ - byte a = inportb(0x64); - puts_pos(0, 8, "KeyBrd Status: "); - put_bin(0, 9, a); -} \ No newline at end of file diff --git a/loader.o b/loader.o deleted file mode 100644 index 2730558..0000000 Binary files a/loader.o and /dev/null differ diff --git a/main.c b/main.c deleted file mode 100644 index 84c99d2..0000000 --- a/main.c +++ /dev/null @@ -1,65 +0,0 @@ -#include -#include -#include "gdt.c" -#include "idt.c" -#include "isrs.c" -#include "irq.c" -#include "timer.c" -#include "keyus.c" -#include "init.c" - - -/*void put_line_scroll(int line, char c) -{ - int i = 0; - while (TextVideoRam[2*(80*line+i)] != 0 && i<=80) ++i; - if (i>78) { - memcpy(TextVideoRam + (2*80*line), TextVideoRam + (2*80*line) + 2, (i+1)*2); - } - putc_pos(i, line, c); -}*/ - - -int main() -{ - system_init(); - set_default_colors (0x07, 0x04); - clrscr(); - - int i; - for (i=0;i<80;i++) putc_pos_font (i, 0, ' ', 0x02, 0x0F); - puts_pos_font (60, 0, "Uptime:", 0x02, 0x0E); cursor_y++; - - // Do other stuff - puts ("Testing puts...\nAnd this shoudl be new line\n"); - puts_font ("And this should be colored in another color ", 0x02, 0x0F); - puts ("<- colored font should be right about heree"); - - puts_pos (0, 23, "This text should be starting in position (0, 23)"); - puts_pos_font (0, 23, "THIS", 0x00, 0x09); - - puts_pos (5, 20, "<- The cursor should be blinking right here"); - putc_pos_font (3, 20, 0, 0x04, 0x0F); - text_mode_cursor(3, 20); - - - while (1) { - kb_get_status(); - - put_bin(60, 15, kb_modifier_status); - puts_pos_font (60, 16, "LShift", 0x07, 0x08 - (kb_modifier_status&1)*0x06); - puts_pos_font (60, 17, "RShift", 0x07, 0x08 - (kb_modifier_status&2)*0x06); - puts_pos_font (60, 18, "LAlt", 0x07, 0x08 - (kb_modifier_status&4)*0x06); - puts_pos_font (60, 19, "RAlt", 0x07, 0x08 - (kb_modifier_status&8)*0x06); - puts_pos_font (60, 20, "LCtrl", 0x07, 0x08 - (kb_modifier_status&16)*0x06); - puts_pos_font (60, 21, "RCtrl", 0x07, 0x08 - (kb_modifier_status&32)*0x06); - puts_pos_font (60, 22, "FakeShift", 0x07, 0x08 - (kb_modifier_status&64)*0x06); - puts_pos_font (60, 23, "Special", 0x07, 0x08 - (kb_modifier_status&128)*0x06); - - putc (kb_getch()); - } - - // do nothing - for(;;); - return 0; -} \ No newline at end of file diff --git a/main.o b/main.o deleted file mode 100644 index 5f8a70a..0000000 Binary files a/main.o and /dev/null differ diff --git a/stage1/MAKE.PIF b/stage1/MAKE.PIF new file mode 100644 index 0000000..e4ad688 Binary files /dev/null and b/stage1/MAKE.PIF differ diff --git a/stage1/bootload.asm b/stage1/bootload.asm new file mode 100644 index 0000000..9769325 --- /dev/null +++ b/stage1/bootload.asm @@ -0,0 +1,314 @@ + +;********************************************* +; Boot1.asm +; - A Simple Bootloader +; +; Operating Systems Development Series +;********************************************* + +bits 16 ; we are in 16 bit real mode + +org 0 ; we will set regisers later + +start: jmp main ; jump to start of bootloader + +;********************************************* +; BIOS Parameter Block +;********************************************* + +; BPB Begins 3 bytes from start. We do a far jump, which is 3 bytes in size. +; If you use a short jump, add a "nop" after it to offset the 3rd byte. + +bpbOEM db "CTA OS " ; OEM identifier (Cannot exceed 8 bytes!) +bpbBytesPerSector: DW 512 +bpbSectorsPerCluster: DB 1 +bpbReservedSectors: DW 1 +bpbNumberOfFATs: DB 2 +bpbRootEntries: DW 224 +bpbTotalSectors: DW 2880 +bpbMedia: DB 0xf8 ;; 0xF1 +bpbSectorsPerFAT: DW 9 +bpbSectorsPerTrack: DW 18 +bpbHeadsPerCylinder: DW 2 +bpbHiddenSectors: DD 0 +bpbTotalSectorsBig: DD 0 +bsDriveNumber: DB 0 +bsUnused: DB 0 +bsExtBootSignature: DB 0x29 +bsSerialNumber: DD 0xa0a1a2a3 +bsVolumeLabel: DB "CTA FLOPPY " +bsFileSystem: DB "FAT12 " + +;************************************************; +; Prints a string +; DS=>SI: 0 terminated string +;************************************************; +Print: + lodsb ; load next byte from string from SI to AL + or al, al ; Does AL=0? + jz PrintDone ; Yep, null terminator found-bail out + mov ah, 0eh ; Nope-Print the character + int 10h + jmp Print ; Repeat until null terminator found + PrintDone: + ret ; we are done, so return + +;************************************************; +; Reads a series of sectors +; CX=>Number of sectors to read +; AX=>Starting sector +; ES:BX=>Buffer to read to +;************************************************; + +ReadSectors: + .MAIN: + mov di, 0x0005 ; five retries for error + .SECTORLOOP: + push ax + push bx + push cx + call LBACHS ; convert starting sector to CHS + mov ah, 0x02 ; BIOS read sector + mov al, 0x01 ; read one sector + mov ch, BYTE [absoluteTrack] ; track + mov cl, BYTE [absoluteSector] ; sector + mov dh, BYTE [absoluteHead] ; head + mov dl, BYTE [bsDriveNumber] ; drive + int 0x13 ; invoke BIOS + jnc .SUCCESS ; test for read error + xor ax, ax ; BIOS reset disk + int 0x13 ; invoke BIOS + dec di ; decrement error counter + pop cx + pop bx + pop ax + jnz .SECTORLOOP ; attempt to read again + int 0x18 + .SUCCESS: + mov si, msgProgress + call Print + pop cx + pop bx + pop ax + add bx, WORD [bpbBytesPerSector] ; queue next buffer + inc ax ; queue next sector + loop .MAIN ; read next sector + ret + +;************************************************; +; Convert CHS to LBA +; LBA = (cluster - 2) * sectors per cluster +;************************************************; + +ClusterLBA: + sub ax, 0x0002 ; zero base cluster number + xor cx, cx + mov cl, BYTE [bpbSectorsPerCluster] ; convert byte to word + mul cx + add ax, WORD [datasector] ; base data sector + ret + +;************************************************; +; Convert LBA to CHS +; AX=>LBA Address to convert +; +; absolute sector = (logical sector / sectors per track) + 1 +; absolute head = (logical sector / sectors per track) MOD number of heads +; absolute track = logical sector / (sectors per track * number of heads) +; +;************************************************; + +LBACHS: + xor dx, dx ; prepare dx:ax for operation + div WORD [bpbSectorsPerTrack] ; calculate + inc dl ; adjust for sector 0 + mov BYTE [absoluteSector], dl + xor dx, dx ; prepare dx:ax for operation + div WORD [bpbHeadsPerCylinder] ; calculate + mov BYTE [absoluteHead], dl + mov BYTE [absoluteTrack], al + ret + +;********************************************* +; Bootloader Entry Point +;********************************************* + +main: + + ;---------------------------------------------------- + ; code located at 0000:7C00, adjust segment registers + ;---------------------------------------------------- + + cli ; disable interrupts + mov ax, 0x07C0 ; setup registers to point to our segment + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + + ;---------------------------------------------------- + ; create stack + ;---------------------------------------------------- + + mov ax, 0x0000 ; set the stack + mov ss, ax + mov sp, 0xFFFF + sti ; restore interrupts + + ;---------------------------------------------------- + ; Display loading message + ;---------------------------------------------------- + + mov si, msgLoading + call Print + + ;---------------------------------------------------- + ; Load root directory table + ;---------------------------------------------------- + + LOAD_ROOT: + + ; compute size of root directory and store in "cx" + + xor cx, cx + xor dx, dx + mov ax, 0x0020 ; 32 byte directory entry + mul WORD [bpbRootEntries] ; total size of directory + div WORD [bpbBytesPerSector] ; sectors used by directory + xchg ax, cx + + ; compute location of root directory and store in "ax" + + mov al, BYTE [bpbNumberOfFATs] ; number of FATs + mul WORD [bpbSectorsPerFAT] ; sectors used by FATs + add ax, WORD [bpbReservedSectors] ; adjust for bootsector + mov WORD [datasector], ax ; base of root directory + add WORD [datasector], cx + + ; read root directory into memory (7C00:0200) + + mov bx, 0x0200 ; copy root dir above bootcode + call ReadSectors + + ;---------------------------------------------------- + ; Find stage 2 + ;---------------------------------------------------- + + ; browse root directory for binary image + mov cx, WORD [bpbRootEntries] ; load loop counter + mov di, 0x0200 ; locate first root entry + .LOOP: + push cx + mov cx, 0x000B ; eleven character name + mov si, ImageName ; image name to find + push di + rep cmpsb ; test for entry match + pop di + je LOAD_FAT + pop cx + add di, 0x0020 ; queue next directory entry + loop .LOOP + jmp FAILURE + + ;---------------------------------------------------- + ; Load FAT + ;---------------------------------------------------- + + LOAD_FAT: + + ; save starting cluster of boot image + + mov dx, WORD [di + 0x001A] + mov WORD [cluster], dx ; file's first cluster + + ; compute size of FAT and store in "cx" + + xor ax, ax + mov al, BYTE [bpbNumberOfFATs] ; number of FATs + mul WORD [bpbSectorsPerFAT] ; sectors used by FATs + mov cx, ax + + ; compute location of FAT and store in "ax" + + mov ax, WORD [bpbReservedSectors] ; adjust for bootsector + + ; read FAT into memory (7C00:0200) + + mov bx, 0x0200 ; copy FAT above bootcode + call ReadSectors + + ; read image file into memory (0050:0000) + + mov ax, 0x0050 + mov es, ax ; destination for image + mov bx, 0x0000 ; destination for image + push bx + + ;---------------------------------------------------- + ; Load Stage 2 + ;---------------------------------------------------- + + LOAD_IMAGE: + + mov ax, WORD [cluster] ; cluster to read + pop bx ; buffer to read into + call ClusterLBA ; convert cluster to LBA + xor cx, cx + mov cl, BYTE [bpbSectorsPerCluster] ; sectors to read + call ReadSectors + push bx + + ; compute next cluster + + mov ax, WORD [cluster] ; identify current cluster + mov cx, ax ; copy current cluster + mov dx, ax ; copy current cluster + shr dx, 0x0001 ; divide by two + add cx, dx ; sum for (3/2) + mov bx, 0x0200 ; location of FAT in memory + add bx, cx ; index into FAT + mov dx, WORD [bx] ; read two bytes from FAT + test ax, 0x0001 + jnz .ODD_CLUSTER + + .EVEN_CLUSTER: + + and dx, 0000111111111111b ; take low twelve bits + jmp .DONE + + .ODD_CLUSTER: + + shr dx, 0x0004 ; take high twelve bits + + .DONE: + + mov WORD [cluster], dx ; store new cluster + cmp dx, 0x0FF0 ; test for end of file + jb LOAD_IMAGE + + DONE: + push WORD 0x0050 + push WORD 0x0000 + retf + + FAILURE: + + mov si, msgFailure + call Print + mov ah, 0x00 + int 0x16 ; await keypress + int 0x19 ; warm boot computer + + absoluteSector db 0x00 + absoluteHead db 0x00 + absoluteTrack db 0x00 + + datasector dw 0x0000 + cluster dw 0x0000 + ImageName db "STAGE2 CTA" + msgLoading db 0x0D, "CTA OS v0.1", 0x0A, 0x0D, "(c) CTA 2010", 0x0A, 0x0D, "Loading", 0x00 + msgProgress db ".", 0x00 + msgFailure db 0x0D, 0x0A, "Error: Could not find stage2.bin. Press any key to reboot.", 0x0A, 0x00 + + TIMES 510-($-$$) db 0 + DW 0xAA55 diff --git a/stage1/bootload.bin b/stage1/bootload.bin new file mode 100644 index 0000000..a1ea468 Binary files /dev/null and b/stage1/bootload.bin differ diff --git a/stage1/make.bat b/stage1/make.bat new file mode 100644 index 0000000..05cd83b --- /dev/null +++ b/stage1/make.bat @@ -0,0 +1,18 @@ +@echo off +set nasm_path=C:\nasm +set djgpp_path=C:\DJGPP\bin +set drive=0 + +@echo on +%nasm_path%\nasm.exe -f bin bootload.asm -o bootload.bin + +@echo. +@echo Press any key to copy to (fd%drive%), or CTRL+C to stop. +@pause >nul + +@echo off +@echo w 100 %drive% 0 1 >f.tmp +@echo q>>f.tmp + +debug bootload.bin nul + +@echo off +copy stage2.cta A:\stage2.cta \ No newline at end of file diff --git a/stage2/a20.inc b/stage2/a20.inc new file mode 100644 index 0000000..f50e445 --- /dev/null +++ b/stage2/a20.inc @@ -0,0 +1,103 @@ + +;******************************************** +; Enable A20 address line +; +; OS Development Series +;******************************************** + +%ifndef __A20_INC_67343546FDCC56AAB872_INCLUDED__ +%define __A20_INC_67343546FDCC56AAB872_INCLUDED__ + +bits 16 + +;---------------------------------------------- +; Enables a20 line through keyboard controller +;---------------------------------------------- + +EnableA20_KKbrd: + + cli + push ax + mov al, 0xdd ; send enable a20 address line command to controller + out 0x64, al + pop ax + ret + +;-------------------------------------------- +; Enables a20 line through output port +;-------------------------------------------- + +EnableA20_KKbrd_Out: + + cli + pusha + + call wait_input + mov al,0xAD + out 0x64,al ; disable keyboard + call wait_input + + mov al,0xD0 + out 0x64,al ; tell controller to read output port + call wait_output + + in al,0x60 + push eax ; get output port data and store it + call wait_input + + mov al,0xD1 + out 0x64,al ; tell controller to write output port + call wait_input + + pop eax + or al,2 ; set bit 1 (enable a20) + out 0x60,al ; write out data back to the output port + + call wait_input + mov al,0xAE ; enable keyboard + out 0x64,al + + call wait_input + popa + sti + ret + + ; wait for input buffer to be clear + +wait_input: + in al,0x64 + test al,2 + jnz wait_input + ret + + ; wait for output buffer to be clear + +wait_output: + in al,0x64 + test al,1 + jz wait_output + ret + +;-------------------------------------- +; Enables a20 line through bios +;-------------------------------------- + +EnableA20_Bios: + pusha + mov ax, 0x2401 + int 0x15 + popa + ret + +;------------------------------------------------- +; Enables a20 line through system control port A +;------------------------------------------------- + +EnableA20_SysControlA: + push ax + mov al, 2 + out 0x92, al + pop ax + ret + +%endif diff --git a/stage2/common.inc b/stage2/common.inc new file mode 100644 index 0000000..38bfda0 --- /dev/null +++ b/stage2/common.inc @@ -0,0 +1,17 @@ + +%ifndef _COMMON_INC_INCLUDED +%define _COMMON_INC_INCLUDED + +; where the kernel is to be loaded to in protected mode +%define IMAGE_PMODE_BASE 0x100000 + +; where the kernel is to be loaded to in real mode +%define IMAGE_RMODE_BASE 0x3000 + +; kernel name (Must be 11 bytes) +ImageName db "KERNEL CTA" + +; size of kernel image in bytes +ImageSize db 0 + +%endif diff --git a/stage2/fat12.inc b/stage2/fat12.inc new file mode 100644 index 0000000..f2a120b --- /dev/null +++ b/stage2/fat12.inc @@ -0,0 +1,243 @@ + +;******************************************************* +; +; Fat12.inc +; FAT12 filesystem for 3-1/2 floppies +; +; OS Development Series +;******************************************************* + +%ifndef __FAT12_INC_67343546FDCC56AAB872_INCLUDED__ +%define __FAT12_INC_67343546FDCC56AAB872_INCLUDED__ + +bits 16 + +%include "Floppy16.inc" ; the erm.. floppy driver + +%define ROOT_OFFSET 0x2e00 +%define FAT_SEG 0x2c0 +%define ROOT_SEG 0x2e0 + +;******************************************* +; LoadRoot () +; - Load Root Directory Table to 0x7e00 +;******************************************* + +LoadRoot: + + pusha ; store registers + push es + + ; compute size of root directory and store in "cx" + + xor cx, cx ; clear registers + xor dx, dx + mov ax, 32 ; 32 byte directory entry + mul WORD [bpbRootEntries] ; total size of directory + div WORD [bpbBytesPerSector] ; sectors used by directory + xchg ax, cx ; move into AX + + ; compute location of root directory and store in "ax" + + mov al, BYTE [bpbNumberOfFATs] ; number of FATs + mul WORD [bpbSectorsPerFAT] ; sectors used by FATs + add ax, WORD [bpbReservedSectors] + mov WORD [datasector], ax ; base of root directory + add WORD [datasector], cx + + ; read root directory into 0x7e00 + + push word ROOT_SEG + pop es + mov bx, 0 ; copy root dir + call ReadSectors ; read in directory table + pop es + popa ; restore registers and return + ret + +;******************************************* +; LoadFAT () +; - Loads FAT table to 0x7c00 +; +; Parm/ ES:DI => Root Directory Table +;******************************************* + +LoadFAT: + + pusha ; store registers + push es + + ; compute size of FAT and store in "cx" + + xor ax, ax + mov al, BYTE [bpbNumberOfFATs] ; number of FATs + mul WORD [bpbSectorsPerFAT] ; sectors used by FATs + mov cx, ax + + ; compute location of FAT and store in "ax" + + mov ax, WORD [bpbReservedSectors] + + ; read FAT into memory (Overwrite our bootloader at 0x7c00) + + push word FAT_SEG + pop es + xor bx, bx + call ReadSectors + pop es + popa ; restore registers and return + ret + +;******************************************* +; FindFile () +; - Search for filename in root table +; +; parm/ DS:SI => File name +; ret/ AX => File index number in directory table. -1 if error +;******************************************* + +FindFile: + + push cx ; store registers + push dx + push bx + mov bx, si ; copy filename for later + + ; browse root directory for binary image + + mov cx, WORD [bpbRootEntries] ; load loop counter + mov di, ROOT_OFFSET ; locate first root entry at 1 MB mark + cld ; clear direction flag + +.LOOP: + push cx + mov cx, 11 ; eleven character name. Image name is in SI + mov si, bx ; image name is in BX + push di + rep cmpsb ; test for entry match + pop di + je .Found + pop cx + add di, 32 ; queue next directory entry + loop .LOOP + +.NotFound: + pop bx ; restore registers and return + pop dx + pop cx + mov ax, -1 ; set error code + ret + +.Found: + pop ax ; return value into AX contains entry of file + pop bx ; restore registers and return + pop dx + pop cx + ret + +;******************************************* +; LoadFile () +; - Load file +; parm/ ES:SI => File to load +; parm/ EBX:BP => Buffer to load file to +; ret/ AX => -1 on error, 0 on success +; ret/ CX => number of sectors read +;******************************************* + +LoadFile: + + xor ecx, ecx ; size of file in sectors + push ecx + +.FIND_FILE: + + push bx ; BX=>BP points to buffer to write to; store it for later + push bp + call FindFile ; find our file. ES:SI contains our filename + cmp ax, -1 + jne .LOAD_IMAGE_PRE + pop bp + pop bx + pop ecx + mov ax, -1 + ret + +.LOAD_IMAGE_PRE: + + sub edi, ROOT_OFFSET + sub eax, ROOT_OFFSET + + ; get starting cluster + + push word ROOT_SEG ;root segment loc + pop es + mov dx, WORD [es:di + 0x001A]; DI points to file entry in root directory table. Refrence the table... + mov WORD [cluster], dx ; file's first cluster + pop bx ; get location to write to so we dont screw up the stack + pop es + push bx ; store location for later again + push es + call LoadFAT + +.LOAD_IMAGE: + + ; load the cluster + + mov ax, WORD [cluster] ; cluster to read + pop es ; bx:bp=es:bx + pop bx + call ClusterLBA + xor cx, cx + mov cl, BYTE [bpbSectorsPerCluster] + call ReadSectors + pop ecx + inc ecx ; add one more sector to counter + push ecx + push bx + push es + mov ax, FAT_SEG ;start reading from fat + mov es, ax + xor bx, bx + + ; get next cluster + + mov ax, WORD [cluster] ; identify current cluster + mov cx, ax ; copy current cluster + mov dx, ax + shr dx, 0x0001 ; divide by two + add cx, dx ; sum for (3/2) + + mov bx, 0 ;location of fat in memory + add bx, cx + mov dx, WORD [es:bx] + test ax, 0x0001 ; test for odd or even cluster + jnz .ODD_CLUSTER + +.EVEN_CLUSTER: + + and dx, 0000111111111111b ; take low 12 bits + jmp .DONE + +.ODD_CLUSTER: + + shr dx, 0x0004 ; take high 12 bits + +.DONE: + + mov WORD [cluster], dx + cmp dx, 0x0ff0 ; test for end of file marker + jb .LOAD_IMAGE + +.SUCCESS: + pop es + pop bx + pop ecx + xor ax, ax + ret + +%endif ;__FAT12_INC_67343546FDCC56AAB872_INCLUDED__ + + + + + diff --git a/stage2/floppy16.inc b/stage2/floppy16.inc new file mode 100644 index 0000000..5893a6a --- /dev/null +++ b/stage2/floppy16.inc @@ -0,0 +1,117 @@ + +;******************************************************* +; +; Floppy16.inc +; Floppy drive interface routines +; +; OS Development Series +;******************************************************* + +%ifndef __FLOPPY16_INC_67343546FDCC56AAB872_INCLUDED__ +%define __FLOPPY16_INC_67343546FDCC56AAB872_INCLUDED__ + +bits 16 + +bpbOEM db "My OS " +bpbBytesPerSector: DW 512 +bpbSectorsPerCluster: DB 1 +bpbReservedSectors: DW 1 +bpbNumberOfFATs: DB 2 +bpbRootEntries: DW 224 +bpbTotalSectors: DW 2880 +bpbMedia: DB 0xf0 ;; 0xF1 +bpbSectorsPerFAT: DW 9 +bpbSectorsPerTrack: DW 18 +bpbHeadsPerCylinder: DW 2 +bpbHiddenSectors: DD 0 +bpbTotalSectorsBig: DD 0 +bsDriveNumber: DB 0 +bsUnused: DB 0 +bsExtBootSignature: DB 0x29 +bsSerialNumber: DD 0xa0a1a2a3 +bsVolumeLabel: DB "MOS FLOPPY " +bsFileSystem: DB "FAT12 " + +datasector dw 0x0000 +cluster dw 0x0000 + +absoluteSector db 0x00 +absoluteHead db 0x00 +absoluteTrack db 0x00 + +;************************************************; +; Convert CHS to LBA +; LBA = (cluster - 2) * sectors per cluster +;************************************************; + +ClusterLBA: + sub ax, 0x0002 ; zero base cluster number + xor cx, cx + mov cl, BYTE [bpbSectorsPerCluster] ; convert byte to word + mul cx + add ax, WORD [datasector] ; base data sector + ret + +;************************************************; +; Convert LBA to CHS +; AX=>LBA Address to convert +; +; absolute sector = (logical sector / sectors per track) + 1 +; absolute head = (logical sector / sectors per track) MOD number of heads +; absolute track = logical sector / (sectors per track * number of heads) +; +;************************************************; + +LBACHS: + xor dx, dx ; prepare dx:ax for operation + div WORD [bpbSectorsPerTrack] ; calculate + inc dl ; adjust for sector 0 + mov BYTE [absoluteSector], dl + xor dx, dx ; prepare dx:ax for operation + div WORD [bpbHeadsPerCylinder] ; calculate + mov BYTE [absoluteHead], dl + mov BYTE [absoluteTrack], al + ret + + +;************************************************; +; Reads a series of sectors +; CX=>Number of sectors to read +; AX=>Starting sector +; ES:EBX=>Buffer to read to +;************************************************; + +ReadSectors: + .MAIN: + mov di, 0x0005 ; five retries for error + .SECTORLOOP: + push ax + push bx + push cx + call LBACHS ; convert starting sector to CHS + mov ah, 0x02 ; BIOS read sector + mov al, 0x01 ; read one sector + mov ch, BYTE [absoluteTrack] ; track + mov cl, BYTE [absoluteSector] ; sector + mov dh, BYTE [absoluteHead] ; head + mov dl, BYTE [bsDriveNumber] ; drive + int 0x13 ; invoke BIOS + jnc .SUCCESS ; test for read error + xor ax, ax ; BIOS reset disk + int 0x13 ; invoke BIOS + dec di ; decrement error counter + pop cx + pop bx + pop ax + jnz .SECTORLOOP ; attempt to read again + int 0x18 + .SUCCESS: + pop cx + pop bx + pop ax + add bx, WORD [bpbBytesPerSector] ; queue next buffer + inc ax ; queue next sector + loop .MAIN ; read next sector + ret + +%endif ;__FLOPPY16_INC_67343546FDCC56AAB872_INCLUDED__ diff --git a/stage2/gdt.inc b/stage2/gdt.inc new file mode 100644 index 0000000..952d66f --- /dev/null +++ b/stage2/gdt.inc @@ -0,0 +1,68 @@ + + +;************************************************* +; Gdt.inc +; -GDT Routines +; +; OS Development Series +;************************************************* + +%ifndef __GDT_INC_67343546FDCC56AAB872_INCLUDED__ +%define __GDT_INC_67343546FDCC56AAB872_INCLUDED__ + +bits 16 + +;******************************************* +; InstallGDT() +; - Install our GDT +;******************************************* + +InstallGDT: + + cli ; clear interrupts + pusha ; save registers + lgdt [toc] ; load GDT into GDTR + sti ; enable interrupts + popa ; restore registers + ret ; All done! + +;******************************************* +; Global Descriptor Table (GDT) +;******************************************* + +gdt_data: + dd 0 ; null descriptor + dd 0 + +; gdt code: ; code descriptor + dw 0FFFFh ; limit low + dw 0 ; base low + db 0 ; base middle + db 10011010b ; access + db 11001111b ; granularity + db 0 ; base high + +; gdt data: ; data descriptor + dw 0FFFFh ; limit low (Same as code)10:56 AM 7/8/2007 + dw 0 ; base low + db 0 ; base middle + db 10010010b ; access + db 11001111b ; granularity + db 0 ; base high + +end_of_gdt: +toc: + dw end_of_gdt - gdt_data - 1 ; limit (Size of GDT) + dd gdt_data ; base of GDT + +; give the descriptor offsets names + +%define NULL_DESC 0 +%define CODE_DESC 0x8 +%define DATA_DESC 0x10 + +%endif ;__GDT_INC_67343546FDCC56AAB872_INCLUDED__ + + + + diff --git a/stage2/stage2.asm b/stage2/stage2.asm new file mode 100644 index 0000000..1ead0de --- /dev/null +++ b/stage2/stage2.asm @@ -0,0 +1,158 @@ + +;******************************************************* +; +; Stage2.asm +; Stage2 Bootloader +; +; OS Development Series +;******************************************************* + +bits 16 + +; Remember the memory map-- 0x500 through 0x7bff is unused above the BIOS data area. +; We are loaded at 0x500 (0x50:0) + +org 0x500 + +jmp main ; go to start + +;******************************************************* +; Preprocessor directives +;******************************************************* + +%include "stdio.inc" ; basic i/o routines +%include "Gdt.inc" ; Gdt routines +%include "A20.inc" ; A20 enabling +%include "Fat12.inc" ; FAT12 driver. Kinda :) +%include "common.inc" + +;******************************************************* +; Data Section +;******************************************************* + +msgFailure db 0x0A, 0x0D, "FATAL ERROR: MISSING OR CORRUPT KERNEL.CTA", 0x0A, 0x0D, "Press any key to reboot...", 0x0D, 0x0A, 0x00 + +;******************************************************* +; STAGE 2 ENTRY POINT +; +; -Store BIOS information +; -Load Kernel +; -Install GDT; go into protected mode (pmode) +; -Jump to Stage 3 +;******************************************************* + +main: + + ;-------------------------------; + ; Setup segments and stack ; + ;-------------------------------; + + cli ; clear interrupts + xor ax, ax ; null segments + mov ds, ax + mov es, ax + mov ax, 0x0 ; stack begins at 0x9000-0xffff + mov ss, ax + mov sp, 0xFFFF + sti ; enable interrupts + + ;-------------------------------; + ; Install our GDT ; + ;-------------------------------; + + call InstallGDT ; install our GDT + + ;-------------------------------; + ; Enable A20 ; + ;-------------------------------; + + call EnableA20_KKbrd_Out + + ;-------------------------------; + ; Initialize filesystem ; + ;-------------------------------; + + call LoadRoot ; Load root directory table + + ;-------------------------------; + ; Load Kernel ; + ;-------------------------------; + + mov ebx, 0 ; BX:BP points to buffer to load to + mov bp, IMAGE_RMODE_BASE + mov si, ImageName ; our file to load + call LoadFile ; load our file + mov dword [ImageSize], ecx ; save size of kernel + cmp ax, 0 ; Test for success + je EnterStage3 ; yep--onto Stage 3! + mov si, msgFailure ; Nope--print error + call Puts16 + mov ah, 0 + int 0x16 ; await keypress + int 0x19 ; warm boot computer + cli ; If we get here, something really went wong + hlt + + ;-------------------------------; + ; Go into pmode ; + ;-------------------------------; + +EnterStage3: + + cli ; clear interrupts + mov eax, cr0 ; set bit 0 in cr0--enter pmode + or eax, 1 + mov cr0, eax + + jmp CODE_DESC:Stage3 ; far jump to fix CS. Remember that the code selector is 0x8! + + ; Note: Do NOT re-enable interrupts! Doing so will triple fault! + ; We will fix this in Stage 3. + +;****************************************************** +; ENTRY POINT FOR STAGE 3 +;****************************************************** + +bits 32 + +Stage3: + + ;-------------------------------; + ; Set registers ; + ;-------------------------------; + + mov ax, DATA_DESC ; set data segments to data selector (0x10) + mov ds, ax + mov ss, ax + mov es, ax + mov esp, 90000h ; stack begins from 90000h + + ;-------------------------------; + ; Copy kernel to 1MB ; + ;-------------------------------; + +CopyImage: + mov eax, dword [ImageSize] + movzx ebx, word [bpbBytesPerSector] + mul ebx + mov ebx, 4 + div ebx + cld + mov esi, IMAGE_RMODE_BASE + mov edi, IMAGE_PMODE_BASE + mov ecx, eax + rep movsd ; copy image to its protected mode address + + ;---------------------------------------; + ; Execute Kernel ; + ;---------------------------------------; + + jmp CODE_DESC:IMAGE_PMODE_BASE; jump to our kernel! Note: This assumes Kernel's entry point is at 1 MB + + ;---------------------------------------; + ; Stop execution ; + ;---------------------------------------; + + cli + hlt + diff --git a/stage2/stage2.cta b/stage2/stage2.cta new file mode 100644 index 0000000..128a53c Binary files /dev/null and b/stage2/stage2.cta differ diff --git a/stage2/stdio.inc b/stage2/stdio.inc new file mode 100644 index 0000000..b1aa7d4 --- /dev/null +++ b/stage2/stdio.inc @@ -0,0 +1,298 @@ + +;************************************************* +; stdio.inc +; -Input/Output routines +; +; OS Development Series +;************************************************* + +%ifndef __STDIO_INC_67343546FDCC56AAB872_INCLUDED__ +%define __STDIO_INC_67343546FDCC56AAB872_INCLUDED__ + + +;========================================================== +; +; 16 Bit Real Mode Routines +;========================================================== + + +;************************************************; +; Puts16 () +; -Prints a null terminated string +; DS=>SI: 0 terminated string +;************************************************; + +bits 16 + +Puts16: + pusha ; save registers +.Loop1: + lodsb ; load next byte from string from SI to AL + or al, al ; Does AL=0? + jz Puts16Done ; Yep, null terminator found-bail out + mov ah, 0eh ; Nope-Print the character + int 10h ; invoke BIOS + jmp .Loop1 ; Repeat until null terminator found +Puts16Done: + popa ; restore registers + ret ; we are done, so return + + +;========================================================== +; +; 32 Bit Protected Mode Routines +;========================================================== + +bits 32 + +%define VIDMEM 0xB8000 ; video memory +%define COLS 80 ; width and height of screen +%define LINES 25 +%define CHAR_ATTRIB 63 ; character attribute (White text on light blue background) + +_CurX db 0 ; current x/y location +_CurY db 0 + +;**************************************************; +; Putch32 () +; - Prints a character to screen +; BL => Character to print +;**************************************************; + +Putch32: + + pusha ; save registers + mov edi, VIDMEM ; get pointer to video memory + + ;-------------------------------; + ; Get current position ; + ;-------------------------------; + + xor eax, eax ; clear eax + + ;-------------------------------- + ; Remember: currentPos = x + y * COLS! x and y are in _CurX and _CurY. + ; Because there are two bytes per character, COLS=number of characters in a line. + ; We have to multiply this by 2 to get number of bytes per line. This is the screen width, + ; so multiply screen with * _CurY to get current line + ;-------------------------------- + + mov ecx, COLS*2 ; Mode 7 has 2 bytes per char, so its COLS*2 bytes per line + mov al, byte [_CurY] ; get y pos + mul ecx ; multiply y*COLS + push eax ; save eax--the multiplication + + ;-------------------------------- + ; Now y * screen width is in eax. Now, just add _CurX. But, again remember that _CurX is relative + ; to the current character count, not byte count. Because there are two bytes per character, we + ; have to multiply _CurX by 2 first, then add it to our screen width * y. + ;-------------------------------- + + mov al, byte [_CurX] ; multiply _CurX by 2 because it is 2 bytes per char + mov cl, 2 + mul cl + pop ecx ; pop y*COLS result + add eax, ecx + + ;------------------------------- + ; Now eax contains the offset address to draw the character at, so just add it to the base address + ; of video memory (Stored in edi) + ;------------------------------- + + xor ecx, ecx + add edi, eax ; add it to the base address + + ;-------------------------------; + ; Watch for new line ; + ;-------------------------------; + + cmp bl, 0x0A ; is it a newline character? + je .Row ; yep--go to next row + + ;-------------------------------; + ; Print a character ; + ;-------------------------------; + + mov dl, bl ; Get character + mov dh, CHAR_ATTRIB ; the character attribute + mov word [edi], dx ; write to video display + + ;-------------------------------; + ; Update next position ; + ;-------------------------------; + + inc byte [_CurX] ; go to next character +; cmp byte [_CurX], COLS ; are we at the end of the line? +; je .Row ; yep-go to next row + jmp .done ; nope, bail out + + ;-------------------------------; + ; Go to next row ; + ;-------------------------------; + +.Row: + mov byte [_CurX], 0 ; go back to col 0 + inc byte [_CurY] ; go to next row + + ;-------------------------------; + ; Restore registers & return ; + ;-------------------------------; + +.done: + popa ; restore registers and return + ret + +;**************************************************; +; Puts32 () +; - Prints a null terminated string +; parm\ EBX = address of string to print +;**************************************************; + +Puts32: + + ;-------------------------------; + ; Store registers ; + ;-------------------------------; + + pusha ; save registers + push ebx ; copy the string address + pop edi + +.loop: + + ;-------------------------------; + ; Get character ; + ;-------------------------------; + + mov bl, byte [edi] ; get next character + cmp bl, 0 ; is it 0 (Null terminator)? + je .done ; yep-bail out + + ;-------------------------------; + ; Print the character ; + ;-------------------------------; + + call Putch32 ; Nope-print it out + + ;-------------------------------; + ; Go to next character ; + ;-------------------------------; + + inc edi ; go to next character + jmp .loop + +.done: + + ;-------------------------------; + ; Update hardware cursor ; + ;-------------------------------; + + ; Its more efficiant to update the cursor after displaying + ; the complete string because direct VGA is slow + + mov bh, byte [_CurY] ; get current position + mov bl, byte [_CurX] + call MovCur ; update cursor + + popa ; restore registers, and return + ret + +;**************************************************; +; MoveCur () +; - Update hardware cursor +; parm/ bh = Y pos +; parm/ bl = x pos +;**************************************************; + +bits 32 + +MovCur: + + pusha ; save registers (aren't you getting tired of this comment?) + + ;-------------------------------; + ; Get current position ; + ;-------------------------------; + + ; Here, _CurX and _CurY are relitave to the current position on screen, not in memory. + ; That is, we don't need to worry about the byte alignment we do when displaying characters, + ; so just follow the forumla: location = _CurX + _CurY * COLS + + xor eax, eax + mov ecx, COLS + mov al, bh ; get y pos + mul ecx ; multiply y*COLS + add al, bl ; Now add x + mov ebx, eax + + ;--------------------------------------; + ; Set low byte index to VGA register ; + ;--------------------------------------; + + mov al, 0x0f + mov dx, 0x03D4 + out dx, al + + mov al, bl + mov dx, 0x03D5 + out dx, al ; low byte + + ;---------------------------------------; + ; Set high byte index to VGA register ; + ;---------------------------------------; + + xor eax, eax + + mov al, 0x0e + mov dx, 0x03D4 + out dx, al + + mov al, bh + mov dx, 0x03D5 + out dx, al ; high byte + + popa + ret + +;**************************************************; +; ClrScr32 () +; - Clears screen +;**************************************************; + +bits 32 + +ClrScr32: + + pusha + cld + mov edi, VIDMEM + mov cx, 2000 + mov ah, CHAR_ATTRIB + mov al, ' ' + rep stosw + + mov byte [_CurX], 0 + mov byte [_CurY], 0 + popa + ret + +;**************************************************; +; GotoXY () +; - Set current X/Y location +; parm\ AL=X position +; parm\ AH=Y position +;**************************************************; + +bits 32 + +GotoXY: + pusha + mov [_CurX], al ; just set the current position + mov [_CurY], ah + popa + ret + + + + +%endif ;__STDIO_INC_67343546FDCC56AAB872_INCLUDED__ diff --git a/timer.c b/timer.c deleted file mode 100644 index 3e09c41..0000000 --- a/timer.c +++ /dev/null @@ -1,52 +0,0 @@ -#include -int timer_ticks = 0; -int timer_hz; - -void timer_phase(int hz) -{ - int divisor = 1193180/hz; // Calculate the divisor - outportb(0x43, 0x36); // Set our command byte 0x36 - outportb(0x40, divisor&0xFF); // Set low byte - outportb(0x40, divisor>>8); // Set high byte - timer_hz = hz; -} - -void timer_clock (int x, int y, int secs) -{ - int s, m, h; - char arr[9] = {0,0,0,0,0,0,0,0,0}; - - s = secs%60; - m = (secs/60)%60; - h = secs/3600; - - arr[0] = (h/10)%10 + '0'; if (arr[0]=='0') arr[0] = ' '; - arr[1] = h%10 + '0'; - - arr[3] = (m/10) + '0'; - arr[4] = m%10 + '0'; - - arr[6] = s/10 + '0'; - arr[7] = s%10 + '0'; - - if (secs%2 == 0) { - arr[2] = ' '; - arr[5] = ' '; - } - else { - arr[2] = ':'; - arr[5] = ':'; - } - - puts_pos(x, y, arr); -} - - -void timer_handler(regs *r) -{ - timer_ticks++; - - if (timer_ticks % timer_hz) { - timer_clock (70, 0, timer_ticks / timer_hz); - } -} \ No newline at end of file