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
|
@ -10,7 +10,7 @@ set djgpp_path=C:\DJGPP\bin
|
|||||||
rem Compile loader
|
rem Compile loader
|
||||||
%nasm_path%\nasm.exe -f aout -o %loader_name%.o %loader_name%.asm
|
%nasm_path%\nasm.exe -f aout -o %loader_name%.o %loader_name%.asm
|
||||||
rem Compile main Kernel
|
rem Compile main Kernel
|
||||||
%djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -finline-functions -nostdinc -fno-builtin -I./include -c -o main.o main.c
|
%djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -finline-functions -nostdinc -fno-builtin -I./include -c -o main.o main.c
|
||||||
rem OTHER GCC/NASM SOURCES GO HERE
|
rem OTHER GCC/NASM SOURCES GO HERE
|
||||||
|
|
||||||
@echo on
|
@echo on
|
||||||
@ -19,4 +19,5 @@ rem OTHER GCC/NASM SOURCES GO HERE
|
|||||||
@echo Done!
|
@echo Done!
|
||||||
|
|
||||||
@pause
|
@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>
|
#include <system.h>
|
||||||
|
|
||||||
#ifndef __CONSOLE_H
|
#ifndef __CONIO_H
|
||||||
#define __CONSOLE_H
|
#define __CONIO_H
|
||||||
#define _ATTRIB 0x0F
|
#define _ATTRIB 0x0F
|
||||||
|
|
||||||
byte default_background, default_foreground;
|
byte default_background, default_foreground;
|
||||||
|
|
||||||
|
char hex[] = "0123456789ABCDEF";
|
||||||
|
|
||||||
|
|
||||||
// Change cursor position
|
// Change cursor position
|
||||||
void text_mode_cursor(int x, int y)
|
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;
|
cursor_x = 0;
|
||||||
if (++cursor_y >=25) {
|
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
|
// Put character on screen in the current cursor position; different font colors
|
||||||
void putc_font(char c, byte back, byte fore)
|
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)] = c;
|
||||||
TextVideoRam[2*(cursor_y*current_mode_width+cursor_x)+1] = fore|(back<<4);
|
TextVideoRam[2*(cursor_y*current_mode_width+cursor_x)+1] = fore|(back<<4);
|
||||||
cursor_x++;
|
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
|
// Put character on screen in the current cursor position; default font colors
|
||||||
void putc(char c)
|
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;
|
TextVideoRam[2*(cursor_y*current_mode_width+cursor_x)] = c;
|
||||||
cursor_x++;
|
cursor_x++;
|
||||||
}
|
}
|
||||||
@ -125,9 +135,8 @@ void puts_font(char *str, byte back, byte fore)
|
|||||||
putc_font(str[i], back, 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];
|
char nr[9];
|
||||||
int i;
|
int i;
|
||||||
for (i = 7; i >= 0; i--) {
|
for (i = 7; i >= 0; i--) {
|
||||||
@ -135,7 +144,18 @@ void put_hex(int x, int y, unsigned int alpha)
|
|||||||
alpha /= 16;
|
alpha /= 16;
|
||||||
}
|
}
|
||||||
nr[8] = 0;
|
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)
|
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
|
* Interrupt Controller (PICs - also called the 8259's) in
|
||||||
* order to make IRQ0 to 15 be remapped to IDT entries 32 to
|
* order to make IRQ0 to 15 be remapped to IDT entries 32 to
|
||||||
* 47 */
|
* 47 */
|
||||||
void irq_remap(void)
|
void irq_remap(int pic1, int pic2)
|
||||||
{
|
{
|
||||||
|
// Send ICW1
|
||||||
outportb(0x20, 0x11);
|
outportb(0x20, 0x11);
|
||||||
outportb(0xA0, 0x11);
|
outportb(0xA0, 0x11);
|
||||||
outportb(0x21, 0x20);
|
|
||||||
outportb(0xA1, 0x28);
|
// send ICW2
|
||||||
outportb(0x21, 0x04);
|
outportb(0x21, pic1); // remap pics
|
||||||
outportb(0xA1, 0x02);
|
outportb(0xA1, pic2);
|
||||||
|
|
||||||
|
// send ICW3
|
||||||
|
outportb(0x21, 4);
|
||||||
|
outportb(0xA1, 2);
|
||||||
|
|
||||||
|
// Send ICW4
|
||||||
outportb(0x21, 0x01);
|
outportb(0x21, 0x01);
|
||||||
outportb(0xA1, 0x01);
|
outportb(0xA1, 0x01);
|
||||||
outportb(0x21, 0x0);
|
|
||||||
outportb(0xA1, 0x0);
|
outportb(0x21, 0x00);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We first remap the interrupt controllers, and then we install
|
/* 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 */
|
* is just like installing the exception handlers */
|
||||||
void irq_install()
|
void irq_install()
|
||||||
{
|
{
|
||||||
irq_remap();
|
irq_remap(32,40);
|
||||||
|
|
||||||
idt_set_gate(32, (unsigned)irq0, 0x08, 0x8E);
|
idt_set_gate(32, (unsigned)irq0, 0x08, 0x8E);
|
||||||
idt_set_gate(33, (unsigned)irq1, 0x08, 0x8E);
|
idt_set_gate(33, (unsigned)irq1, 0x08, 0x8E);
|
@ -1,5 +1,4 @@
|
|||||||
#include <system.h>
|
#include <system.h>
|
||||||
#include <console.h>
|
|
||||||
|
|
||||||
extern void isr0();
|
extern void isr0();
|
||||||
extern void isr1();
|
extern void isr1();
|
||||||
@ -132,30 +131,30 @@ void fault_handler(regs *r)
|
|||||||
puts (" Blue Screen Of Death\n");
|
puts (" Blue Screen Of Death\n");
|
||||||
int i; for (i = 79; i>=0; i--) putc('=');
|
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 (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, 4, "gs", 0x01, 0x0B); put_hex_pos(15, 4, r->gs);
|
||||||
puts_pos_font (10, 5, "fs", 0x01, 0x0B); put_hex(15, 5, r->fs);
|
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(15, 6, r->es);
|
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(15, 7, r->ds);
|
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, 4, "edi", 0x01, 0x0B); put_hex_pos(45, 4, r->edi);
|
||||||
puts_pos_font (40, 5, "esi", 0x01, 0x0B); put_hex(45, 5, r->esi);
|
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(45, 6, r->ebp);
|
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(45, 7, r->esp);
|
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, 9, "eax", 0x01, 0x0B); put_hex_pos(15, 9, r->eax);
|
||||||
puts_pos_font (10, 10, "ebx", 0x01, 0x0B); put_hex(15, 10, r->ebx);
|
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(45, 9, r->ecx);
|
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(45, 10, r->edx);
|
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, 12, "int_no", 0x01, 0x0B); put_hex_pos(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, 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, 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, 17, "eip", 0x01, 0x0B); put_hex_pos(17, 17, r->eip);
|
||||||
puts_pos_font (10, 18, "cs", 0x01, 0x0B); put_hex(17, 18, r->cs);
|
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(17, 19, r->eflags);
|
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(17, 20, r->useresp);
|
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(17, 21, r->ss);
|
puts_pos_font (10, 21, "ss", 0x01, 0x0B); put_hex_pos(17, 21, r->ss);
|
||||||
|
|
||||||
puts_pos_font (29, 24, "!!! System Halted !!!", 0x01, 0x0C);
|
puts_pos_font (29, 24, "!!! System Halted !!!", 0x01, 0x0C);
|
||||||
for (;;);
|
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--;
|
||||||
|
}
|
@ -442,8 +442,37 @@ irq_common_stub:
|
|||||||
add esp, 8
|
add esp, 8
|
||||||
iret
|
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
|
SECTION .bss
|
||||||
resb 8192 ; This reserves 8KBytes of memory here
|
resb 8192 ; This reserves 8KBytes of memory here
|
||||||
_sys_stack:
|
_sys_stack:
|
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