CTAOS v2
This commit is contained in:
parent
c90c6dc692
commit
7cb940e485
104
include/system.h
104
include/system.h
@ -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
37
init.c
@ -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();
|
||||
|
||||
|
||||
}
|
BIN
kernel.bin
BIN
kernel.bin
Binary file not shown.
25
kernel/clock/cmos.h
Normal file
25
kernel/clock/cmos.h
Normal 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
76
kernel/clock/pictimer.c
Normal 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
143
kernel/clock/time.c
Normal 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
|
@ -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
|
@ -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)
|
40
kernel/include/sys/declarat.h
Normal file
40
kernel/include/sys/declarat.h
Normal 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
85
kernel/include/system.h
Normal 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
BIN
kernel/kernel.bin
Normal file
Binary file not shown.
8
kernel/kernel/epilogue.c
Normal file
8
kernel/kernel/epilogue.c
Normal file
@ -0,0 +1,8 @@
|
||||
void reboot()
|
||||
{
|
||||
unsigned char good = 0x02;
|
||||
while ((good & 0x02) != 0)
|
||||
good = inportb(0x64);
|
||||
outportb(0x64, 0xFE);
|
||||
__asm__ __volatile__ ("hlt");
|
||||
}
|
@ -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);
|
@ -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
4
kernel/kernel/memory.c
Normal 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
61
kernel/kernel/prologue.c
Normal 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);
|
||||
}
|
135
kernel/keyboard/key_list.txt
Normal file
135
kernel/keyboard/key_list.txt
Normal 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
60
kernel/keyboard/keyb.c
Normal 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
179
kernel/keyboard/keyus.c
Normal 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
137
kernel/keyboard/keyus.h
Normal 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--;
|
||||
}
|
@ -443,6 +443,35 @@ irq_common_stub:
|
||||
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
|
BIN
kernel/loader.o
Normal file
BIN
kernel/loader.o
Normal file
Binary file not shown.
18
kernel/main.c
Normal file
18
kernel/main.c
Normal 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
BIN
kernel/main.o
Normal file
Binary file not shown.
122
kernel/shell/apps.h
Normal file
122
kernel/shell/apps.h
Normal 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
81
kernel/shell/shell.c
Normal 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
209
keyus.c
@ -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);
|
||||
}
|
65
main.c
65
main.c
@ -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
stage1/MAKE.PIF
Normal file
BIN
stage1/MAKE.PIF
Normal file
Binary file not shown.
314
stage1/bootload.asm
Normal file
314
stage1/bootload.asm
Normal 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
BIN
stage1/bootload.bin
Normal file
Binary file not shown.
18
stage1/make.bat
Normal file
18
stage1/make.bat
Normal 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
15
stage2/MAKE.BAT
Normal 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
103
stage2/a20.inc
Normal 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
17
stage2/common.inc
Normal 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
243
stage2/fat12.inc
Normal 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
117
stage2/floppy16.inc
Normal 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
68
stage2/gdt.inc
Normal 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
158
stage2/stage2.asm
Normal 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
BIN
stage2/stage2.cta
Normal file
Binary file not shown.
298
stage2/stdio.inc
Normal file
298
stage2/stdio.inc
Normal 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
52
timer.c
@ -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);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user