This commit is contained in:
Tiberiu Chibici 2021-09-14 18:30:00 +03:00
parent c90c6dc692
commit 7cb940e485
48 changed files with 2621 additions and 507 deletions

View File

@ -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

37
init.c
View File

@ -1,37 +0,0 @@
#include <system.h>
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();
}

Binary file not shown.

25
kernel/clock/cmos.h Normal file
View File

@ -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");
}
}

76
kernel/clock/pictimer.c Normal file
View File

@ -0,0 +1,76 @@
#include <system.h>
#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();
}
}

143
kernel/clock/time.c Normal file
View File

@ -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

View File

@ -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

View File

@ -1,11 +1,13 @@
#include <system.h>
#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)

View File

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

85
kernel/include/system.h Normal file
View File

@ -0,0 +1,85 @@
#ifndef __SYSTEM_H
#define __SYSTEM_H
#include <sys/declarat.h>
#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

BIN
kernel/kernel.bin Normal file

Binary file not shown.

8
kernel/kernel/epilogue.c Normal file
View File

@ -0,0 +1,8 @@
void reboot()
{
unsigned char good = 0x02;
while ((good & 0x02) != 0)
good = inportb(0x64);
outportb(0x64, 0xFE);
__asm__ __volatile__ ("hlt");
}

View File

@ -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);

View File

@ -1,5 +1,4 @@
#include <system.h>
#include <console.h>
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 (;;);

4
kernel/kernel/memory.c Normal file
View File

@ -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);

61
kernel/kernel/prologue.c Normal file
View File

@ -0,0 +1,61 @@
#include <system.h>
#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);
}

View File

@ -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

60
kernel/keyboard/keyb.c Normal file
View File

@ -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);*/
}

179
kernel/keyboard/keyus.c Normal file
View File

@ -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<<offset;
kb_newdata = scancode;
}
else kb_array[pos] &= 0xFF - (1<<offset);
}
byte kb_get_key(byte scancode)
{
byte pos = scancode/8;
byte offset = scancode%8;
return (kb_array[pos]&(1<<offset));
}
void kb_handler(regs *r) {
byte scancode = inportb(0x60);
switch (scancode) {
case 0x00: // Error 0x00
case 0xFC: // Diagnostics failed (MF kb)
case 0xFD: // Diagnostics failed (AT kb)
case 0xFF: kb_waitin(); outportb(0x60, 0xF4); // Error 0xFF
break;
case 0xAA: // BAT test successful.
case 0xFA: // ACKnowledge
case 0xFE: // Last command invalid or parity error
case 0xEE: break; // Echo response
// Gray or break
case 0xE0: kb_prefix |= 1; break;
case 0xE1: kb_prefix |= 4; break;
case 0xF0: kb_prefix |= 2; break;
// Alt, ctrl...
case 0x11: if ((kb_prefix&1) == 0) { // Left alt
if ((kb_prefix&2) == 0) kb_modifier_status |= 1<<2;
else kb_modifier_status &= 0xFF - (1<<2);
}
else { // Right alt
if ((kb_prefix&2) == 0) kb_modifier_status |= 1<<3;
else kb_modifier_status &= 0xFF - (1<<3);
}
kb_prefix = 0; break;
case 0x12: if ((kb_prefix&1) == 0) { // Left shift
if ((kb_prefix&2) == 0) kb_modifier_status |= 1<<0;
else kb_modifier_status &= 0xFF - (1<<0);
}
else { // Fake shift
if ((kb_prefix&2) == 0) kb_modifier_status |= 1<<6;
else kb_modifier_status &= 0xFF - (1<<6);
}
kb_prefix = 0; break;
//TO ADD BELOW: pause/break byte1
case 0x14: if (kb_prefix&4) {
if ((kb_prefix&2) == 0) kb_set_key (0, 1);
else kb_set_key (0, 0);
kb_prefix |= 8; break;
}
else if ((kb_prefix&1) == 0) { // Left ctrl
if ((kb_prefix&2) == 0) kb_modifier_status |= 1<<4;
else kb_modifier_status &= 0xFF - (1<<4);
}
else { // Right ctrl
if ((kb_prefix&2) == 0) kb_modifier_status |= 1<<5;
else kb_modifier_status &= 0xFF - (1<<5);
}
kb_prefix = 0; break;
case 0x59: // Right shift
if ((kb_prefix&2) == 0) kb_modifier_status |= 1<<1;
else kb_modifier_status &= 0xFF - (1<<1);
kb_prefix = 0; break;
// LEDs
case 0x58: if ((kb_prefix&2) == 0) {
kb_lights_status ^= 4; kb_set_LEDs(kb_lights_status);
} kb_prefix = 0; break; // Caps
//TO ADD BELOW: pause/break byte2
case 0x77:
if ((kb_prefix&4) && (kb_prefix&8)) kb_prefix=0;
else if ((kb_prefix&2) == 0) {
kb_lights_status ^= 2; kb_set_LEDs(kb_lights_status);
} kb_prefix = 0; break; // Num
case 0x7E: if ((kb_prefix&2) == 0) {
kb_lights_status ^= 1; kb_set_LEDs(kb_lights_status);
} kb_prefix = 0; break; // Scroll
case 0x83: scancode = 0x02; // Put F7 under the 0x80 (128bit) barrier
default:
// Remap gray keys
if (kb_prefix&1) switch (scancode) {
case 0x7C: scancode=0x08; break; // PrintScreen
case 0x4A: scancode=0x6A; break; // Numpad /
case 0x5A: scancode=0x59; break; // Numpad Enter
case 0x69: scancode=0x5E; break; // End
case 0x6B: scancode=0x5F; break; // Left
case 0x6C: scancode=0x60; break; // Home
case 0x70: scancode=0x61; break; // Insert
case 0x71: scancode=0x62; break; // Delete
case 0x72: scancode=0x63; break; // Down
case 0x74: scancode=0x64; break; // Right
case 0x75: scancode=0x65; break; // Up
case 0x7A: scancode=0x67; break; // PageDown
case 0x7D: scancode=0x68; break; // PageUp
}
if ((kb_prefix&2) == 0) kb_set_key(scancode, 1);
else kb_set_key(scancode, 0);
kb_prefix = 0; break;
}
// Alt+ctrl+del = reset
if (scancode==0x62) {
int ok=0;
if ((kb_modifier_status&4) || (kb_modifier_status&8)) ok++;
if ((kb_modifier_status&16) || (kb_modifier_status&32)) ok++;
if (ok==2) reboot();
}
outportb(0x20, 0x20);
}
kb_key kb_getkey()
{
kb_key ret;
kb_newdata = 0xFF;
while (kb_newdata==0xFF); // wait for keypress
ret.scancode = kb_newdata; // Send scancode for non-chars
ret.status = kb_modifier_status; // Shift, ctrl... state
ret.lights = kb_lights_status; // Num, caps.... state
if ((ret.status & 1) || (ret.status & 2)) // Shift is on
ret.character = kbdus_map_shift[ret.scancode];
else ret.character = kbdus_map[ret.scancode]; // Shift is off
return ret; // And send it.
}

137
kernel/keyboard/keyus.h Normal file
View File

@ -0,0 +1,137 @@
void kb_set_LEDs(byte status);
void kb_set_repeat(byte rate, byte delay);
void kb_set_scancodeset(byte set);
char kbdus_map[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\t', '`', 0,
0, 0, 0, 0, 0, 'q', '1', 0, 0, 0, 'z', 's', 'a', 'w', '2', 0,
0, 'c', 'x', 'd', 'e', '4', '3', 0, 0, ' ', 'v', 'f', 't', 'r', '5', 0,
0, 'n', 'b', 'h', 'g', 'y', '6', 0, 0, 0, 'm', 'j', 'u', '7', '8', 0,
0, ',', 'k', 'i', 'o', '0', '9', 0, 0, '.', '/', '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
};
char kbdus_map_shift[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\t', '~', 0,
0, 0, 0, 0, 0, 'Q', '!', 0, 0, 0, 'Z', 'S', 'A', 'W', '@', 0,
0, 'C', 'X', 'D', 'E', '$', '#', 0, 0, ' ', 'V', 'F', 'T', 'R', '%', 0,
0, 'N', 'B', 'H', 'G', 'Y', '^', 0, 0, 0, 'M', 'J', 'U', '&', '*', 0,
0, '<', 'K', 'I', 'O', ')', '(', 0, 0, '>', '?', '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--;
}

View File

@ -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:

BIN
kernel/loader.o Normal file

Binary file not shown.

18
kernel/main.c Normal file
View File

@ -0,0 +1,18 @@
#include <system.h>
#include <conio.h>
#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;
}

BIN
kernel/main.o Normal file

Binary file not shown.

122
kernel/shell/apps.h Normal file
View File

@ -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;
}
}

81
kernel/shell/shell.c Normal file
View File

@ -0,0 +1,81 @@
#include <conio.h>
#include "apps.h"
void get_str(char *str, int len)
{
kb_key alpha;
int i;
for (i = 0; i<len-1 ; i++) {
text_mode_cursor(cursor_x, cursor_y);
alpha = kb_getkey();
switch (alpha.character) {
case 0x00: --i; break; // Ignore null characters
case 0x7F: --i; break;
case '\b': // Backspace
if (i>0) { // 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<apps_count; i++);
switch (i) {
case 0: puts("You must enter a command!\n"); break;
case 1: reboot();
case 2: apps_osver(); break;
case 3: apps_date(); break;
case 4: apps_place(); break;
case 5: apps_clrscr(); break;
case 6: apps_memory(params, (const char**)param); break;
default: puts("Invalid function: "); puts(param[0]);
putc('\n');
break;
}
}
}

209
keyus.c
View File

@ -1,209 +0,0 @@
unsigned char kbdus[128] =
{
0, 27, '1', '2', '3', '4', '5', '6', '7', '8', /* 9 */
'9', '0', '-', '=', '\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 */
};
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);
}

BIN
loader.o

Binary file not shown.

65
main.c
View File

@ -1,65 +0,0 @@
#include <system.h>
#include <console.h>
#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;
}

BIN
main.o

Binary file not shown.

BIN
stage1/MAKE.PIF Normal file

Binary file not shown.

314
stage1/bootload.asm Normal file
View File

@ -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

BIN
stage1/bootload.bin Normal file

Binary file not shown.

18
stage1/make.bat Normal file
View File

@ -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 <f.tmp
del f.tmp

15
stage2/MAKE.BAT Normal file
View File

@ -0,0 +1,15 @@
@echo off
set nasm_path=C:\nasm
set djgpp_path=C:\DJGPP\bin
set drive=A
@echo on
%nasm_path%\nasm.exe -f bin stage2.asm -o stage2.cta
@echo off
@echo.
@echo Press any key to copy to %drive%:, or CTRL+C to stop.
@pause >nul
@echo off
copy stage2.cta A:\stage2.cta

103
stage2/a20.inc Normal file
View File

@ -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

17
stage2/common.inc Normal file
View File

@ -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

243
stage2/fat12.inc Normal file
View File

@ -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__

117
stage2/floppy16.inc Normal file
View File

@ -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__

68
stage2/gdt.inc Normal file
View File

@ -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__

158
stage2/stage2.asm Normal file
View File

@ -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

BIN
stage2/stage2.cta Normal file

Binary file not shown.

298
stage2/stdio.inc Normal file
View File

@ -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__

52
timer.c
View File

@ -1,52 +0,0 @@
#include<system.h>
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);
}
}