Add ctaos-early: first hobby kernels 2009-2010 (source snapshots and help pages)
This commit is contained in:
1 parent
7df26cb1a9
commit
d30ec5b5e9
47 files changed
+3491
No files matched your search
@@ -34,3 +34,23 @@ into the kernel (2011).
|
|||||||
- `ctaos/` (Nov 2010 - Mar 2011): NetBeans project shell for an earlier,
|
- `ctaos/` (Nov 2010 - Mar 2011): NetBeans project shell for an earlier,
|
||||||
tutorial-based kernel (kernel.c, interrupt, PIT, GDT/IDT/IRQ/PIC sources).
|
tutorial-based kernel (kernel.c, interrupt, PIT, GDT/IDT/IRQ/PIC sources).
|
||||||
Only the project files survive, the sources are not included.
|
Only the project files survive, the sources are not included.
|
||||||
|
|
||||||
|
## Earlier hobby kernels
|
||||||
|
|
||||||
|
- `ctaos-early/` (Oct 2009 - Nov 2010): the first hobby-OS attempts, the
|
||||||
|
predecessor of luxOS. A GRUB (stage1/stage2 on a floppy image) booted kernel
|
||||||
|
that starts as plain C and moves to C++ with a text console and keyboard
|
||||||
|
driver. Source only; floppy/disk images, GRUB stages and compiled output
|
||||||
|
were left out. Each folder is one snapshot, oldest first:
|
||||||
|
- `2009-10-25-ctaos/`: first kernel, C (`kernel.c`), loader and linker script.
|
||||||
|
- `2009-10-28-ctaos++/`: moved to C++ (`kernel.cpp`, `console.h`, `startup.h`).
|
||||||
|
- `2009-10-30-ctaos++/`: adds `keyboard.h`; changed `kernel.cpp` and `startup.h`.
|
||||||
|
- `2009-10-31-tctaos/`: separate test copy (`TCTAOS~1`, original name lost) with a
|
||||||
|
smaller kernel and different loader.
|
||||||
|
- `2010-11-ctaos++/`: last version (`CTAOS_~1`, probably `ctaos++`): bigger
|
||||||
|
`console.h`, `keyboard.h`, `system.h`, floppy driver header, and a script
|
||||||
|
that builds a bootable GRUB hard disk image for qemu.
|
||||||
|
- `help/`: the hand-written pages of the OS guide (index, bootloader, kernel,
|
||||||
|
`conio.h` reference), 2010. The files with a `.HT~` extension are 8.3-mangled
|
||||||
|
names (probably `.html~` backups); the CKEditor copy that came with them is not included.
|
||||||
|
The Nov 2010 - Mar 2011 NetBeans project shell is in `ctaos/` above.
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
cd /home/tiberiu/Desktop/ctaos
|
||||||
|
echo "Compiling..."
|
||||||
|
echo "gcc -o kernel.o -c kernel.c -Wall -Wextra -nostdlib -nostartfiles -nodefaultlibs"
|
||||||
|
gcc -o kernel.o -c kernel.c -Wall -Wextra -nostdlib -nodefaultlibs
|
||||||
|
echo ""
|
||||||
|
echo "nasm -f elf -o loader.o loader.s"
|
||||||
|
nasm -f elf -o loader.o loader.s
|
||||||
|
echo ""
|
||||||
|
echo "ld -T linker.ld -o kernel.bin loader.o kernel.o"
|
||||||
|
ld -T linker.ld -o kernel.bin loader.o kernel.o
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
echo "Making floppy image..."
|
||||||
|
echo "dd if=/dev/zero of=pad bs=1 count=750"
|
||||||
|
dd if=/dev/zero of=pad bs=1 count=750
|
||||||
|
echo "dd if=/dev/zero of=pad2 bs=1 count=(userspecified)"
|
||||||
|
dd if=/dev/zero of=pad2 bs=1 count=1358807
|
||||||
|
cat stage1 stage2 pad kernel.bin pad2 > floppy.img
|
||||||
|
echo "cat stage1 stage2 pad kernel.bin pad2 > floppy.img"
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
unsigned char *videoram = (unsigned char*) 0xb8000;
|
||||||
|
|
||||||
|
void ctamain();
|
||||||
|
void cout(char string[]);
|
||||||
|
void cout_style (char string[], unsigned char style);
|
||||||
|
void cls();
|
||||||
|
|
||||||
|
void kmain (void* mdb, unsigned int magic)
|
||||||
|
{
|
||||||
|
if (magic != 0x2BADB002)
|
||||||
|
{
|
||||||
|
cout ("Magic error. System halted!");
|
||||||
|
}
|
||||||
|
|
||||||
|
char* boot_loader_name = (char*) ((long*)mdb)[16];
|
||||||
|
|
||||||
|
ctamain();
|
||||||
|
}
|
||||||
|
|
||||||
|
void cls()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i <= 80*25; i++)
|
||||||
|
{
|
||||||
|
videoram[i*2] = 0;
|
||||||
|
videoram[i*2+1] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cout (char string[])
|
||||||
|
{
|
||||||
|
int offset=0, i;
|
||||||
|
while (videoram[offset*2]!=0) offset++;
|
||||||
|
|
||||||
|
for (i=0; string[i]!=0; i++, offset++) {
|
||||||
|
if (string[i] == '\n')
|
||||||
|
do { videoram[offset*2] = ' ';
|
||||||
|
offset++;
|
||||||
|
} while (offset%80 != 0);
|
||||||
|
|
||||||
|
else {
|
||||||
|
videoram[offset*2] = string[i];
|
||||||
|
videoram[offset*2+1] = 0x07;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cout_style (char string[], unsigned char style)
|
||||||
|
{
|
||||||
|
int offset=0, i;
|
||||||
|
while (videoram[offset*2]!=0) offset++;
|
||||||
|
|
||||||
|
for (i=0; string[i]!=0; i++, offset++) {
|
||||||
|
if (string[i] == '\n')
|
||||||
|
do { videoram[offset*2] = ' ';
|
||||||
|
videoram[offset*2+1] = style;
|
||||||
|
offset++;
|
||||||
|
} while (offset-%80 != 0);
|
||||||
|
|
||||||
|
else {
|
||||||
|
videoram[offset*2] = string[i];
|
||||||
|
videoram[offset*2+1] = style;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ctamain()
|
||||||
|
{
|
||||||
|
cls();
|
||||||
|
cout("Hello, world!!!\n");
|
||||||
|
cout("Welcome to CTA OS 1.0\n");
|
||||||
|
cout_style("MUHAHAHAHAHAHAHAHAHSfdHAHAHA\n", 0x1F);
|
||||||
|
cout("Good bye now.");
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
ENTRY (loader)
|
||||||
|
|
||||||
|
SECTIONS {
|
||||||
|
. = 0x00100000;
|
||||||
|
|
||||||
|
.text :{
|
||||||
|
*(.text)
|
||||||
|
}
|
||||||
|
|
||||||
|
.rodata ALIGN (0x1000) : {
|
||||||
|
*(.rodata)
|
||||||
|
}
|
||||||
|
|
||||||
|
.data ALIGN (0x1000) : {
|
||||||
|
*(.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
.bss : {
|
||||||
|
sbss = .;
|
||||||
|
*(COMMON)
|
||||||
|
*(.bss)
|
||||||
|
ebss = .;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
global loader
|
||||||
|
extern kmain
|
||||||
|
|
||||||
|
MODULEALIGN equ 1<<0
|
||||||
|
MEMINFO equ 1<<1
|
||||||
|
FLAGS equ MODULEALIGN | MEMINFO
|
||||||
|
MAGIC equ 0x1BADB002
|
||||||
|
CHECKSUM equ -(MAGIC+FLAGS)
|
||||||
|
|
||||||
|
section .text
|
||||||
|
align 4
|
||||||
|
MultiBootHeader:
|
||||||
|
dd MAGIC
|
||||||
|
dd FLAGS
|
||||||
|
dd CHECKSUM
|
||||||
|
|
||||||
|
STACKSIZE equ 0x4000
|
||||||
|
|
||||||
|
loader:
|
||||||
|
mov esp, stack+STACKSIZE
|
||||||
|
push eax
|
||||||
|
push ebx
|
||||||
|
|
||||||
|
call kmain
|
||||||
|
|
||||||
|
cli
|
||||||
|
hang:
|
||||||
|
hlt
|
||||||
|
jmp hang
|
||||||
|
|
||||||
|
section .bss
|
||||||
|
align 4
|
||||||
|
stack:
|
||||||
|
resb STACKSIZE
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
cd /home/tiberiu/Desktop/ctaos++
|
||||||
|
echo ""
|
||||||
|
echo "Compiling..."
|
||||||
|
echo "gcc -o kernel.o -c kernel.cpp -Wall -Wextra -nostdlib -nostartfiles -nodefaultlibs"
|
||||||
|
gcc -o kernel.o -c kernel.cpp -Wall -Wextra -nostdlib -nostartfiles -nodefaultlibs -fno-exceptions
|
||||||
|
echo ""
|
||||||
|
echo "nasm -f elf -o loader.o loader.s"
|
||||||
|
nasm -f elf -o loader.o loader.s
|
||||||
|
echo ""
|
||||||
|
echo "ld -T linker.ld -o kernel.bin loader.o kernel.o"
|
||||||
|
ld -T linker.ld -o kernel.bin loader.o kernel.o
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
cd /home/tiberiu/Desktop/ctaos++
|
||||||
|
echo ""
|
||||||
|
echo "Making floppy image..."
|
||||||
|
echo ""
|
||||||
|
echo "dd if=/dev/zero of=pad bs=1 count=750"
|
||||||
|
dd if=/dev/zero of=pad bs=1 count=750
|
||||||
|
echo ""
|
||||||
|
echo "dd if=/dev/zero of=pad2 bs=1 count=(userspecified)"
|
||||||
|
dd if=/dev/zero of=pad2 bs=1 count=1358451
|
||||||
|
echo ""
|
||||||
|
echo "cat stage1 stage2 pad kernel.bin pad2 > floppy.img"
|
||||||
|
cat stage1 stage2 pad kernel.bin pad2 > floppy.img
|
||||||
|
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
unsigned char *videoram = (unsigned char*) 0xb8000;
|
||||||
|
static __inline__ void outb(unsigned short port, unsigned char val);
|
||||||
|
static __inline__ unsigned char inb(unsigned short port);
|
||||||
|
static __inline__ void io_wait(void);
|
||||||
|
|
||||||
|
// update cursor position
|
||||||
|
void cupdate_cursor (int x, int y)
|
||||||
|
{
|
||||||
|
unsigned short position = (y * 80) + x;
|
||||||
|
|
||||||
|
// unsigned char word1, word2;
|
||||||
|
unsigned short word;
|
||||||
|
|
||||||
|
/* word1 = inb (0x463);
|
||||||
|
word2 = inb (0x464);*/
|
||||||
|
|
||||||
|
word = (256 * inb (0x463)) + 256*inb (0x464);
|
||||||
|
|
||||||
|
outb(word, 0x0F);
|
||||||
|
outb(word+1, (unsigned char)(position&0xFF));
|
||||||
|
|
||||||
|
outb(word, 0x0E);
|
||||||
|
outb(word+1, (unsigned char )((position>>8)&0xFF));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the screen
|
||||||
|
void cls()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i <= 80*25; i++)
|
||||||
|
{
|
||||||
|
videoram[i*2] = 0;
|
||||||
|
videoram[i*2+1] = 0;
|
||||||
|
}
|
||||||
|
cursor.x = 0;
|
||||||
|
cursor.y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Place a character on the screen
|
||||||
|
void cputchar (int x, int y, char c, unsigned char style)
|
||||||
|
{
|
||||||
|
videoram[2*(y*80+x)] = c;
|
||||||
|
videoram[2*(y*80+x)+1] = style;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a character in a specified position
|
||||||
|
char cgetchar (int x, int y)
|
||||||
|
{
|
||||||
|
return videoram[2*(y*80+x)];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a style in specified position
|
||||||
|
unsigned char cgetstyle (int x, int y)
|
||||||
|
{
|
||||||
|
return videoram[2*(y*80+x)+1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scroll n lines
|
||||||
|
void scroll (int n)
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
cursor.y -= n;
|
||||||
|
for (y = 0; y < 25-n; y++)
|
||||||
|
for (x = 0; x < 80; x++)
|
||||||
|
cputchar (x, y, cgetchar(x, y+n), cgetstyle(x, y+n));
|
||||||
|
|
||||||
|
while (y<25) {
|
||||||
|
for (x = 0; x < 80; x++)
|
||||||
|
cputchar (x, y, 0, 0);
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Display a string of text on the screen
|
||||||
|
void cout (const char string[])
|
||||||
|
{
|
||||||
|
for (int i=0; string[i]!=0; i++) {
|
||||||
|
// scroll if necesary
|
||||||
|
if (cursor.y >= 25) scroll(1);
|
||||||
|
|
||||||
|
// end of line character behavior
|
||||||
|
if (string[i] == '\n') {
|
||||||
|
cursor.y++;
|
||||||
|
cursor.x = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// display text
|
||||||
|
else {
|
||||||
|
cputchar (cursor.x, cursor.y, string[i], 0x07);
|
||||||
|
if (++cursor.x >= 80) {
|
||||||
|
cursor.x = 0;
|
||||||
|
cursor.y++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cupdate_cursor (cursor.x, cursor.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cout_style (const char string[], unsigned char style)
|
||||||
|
{
|
||||||
|
for (int i=0; string[i]!=0; i++) {
|
||||||
|
// scroll if necesary
|
||||||
|
if (cursor.y >= 25) scroll(1);
|
||||||
|
|
||||||
|
// end of line character behavior
|
||||||
|
if (string[i] == '\n') {
|
||||||
|
cursor.y++;
|
||||||
|
cursor.x = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// display text
|
||||||
|
else {
|
||||||
|
cputchar (cursor.x, cursor.y, string[i], style);
|
||||||
|
if (++cursor.x >= 80) {
|
||||||
|
cursor.x = 0;
|
||||||
|
cursor.y++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cupdate_cursor (cursor.x, cursor.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
extern "C" int number();
|
||||||
|
|
||||||
|
|
||||||
|
struct point {int x,y;} cursor;
|
||||||
|
|
||||||
|
#include "console.h"
|
||||||
|
#include "startup.h"
|
||||||
|
|
||||||
|
void ctamain()
|
||||||
|
{
|
||||||
|
int no = number();
|
||||||
|
char whatever[] = " is a number.\n";
|
||||||
|
unsigned char c, temp = 2;
|
||||||
|
|
||||||
|
whatever[0] = '0' + (char) (no/10);
|
||||||
|
whatever[1] = '0' + (char) (no%10);
|
||||||
|
|
||||||
|
cls();
|
||||||
|
cout("Hello, world!!!\n");
|
||||||
|
cout("Welcome to CTA OS 1.0\n");
|
||||||
|
cout_style("MUHAHAHAHAHAHAHAHAHSfdHAHAHA\n", 0x1F);
|
||||||
|
cout(whatever);
|
||||||
|
cout("Testing keyboard input:\n");
|
||||||
|
|
||||||
|
do { c = (char) KeyboardIsr();
|
||||||
|
temp = c;
|
||||||
|
do { c = KeyboardIsr(); } while (c == temp);
|
||||||
|
cout ("This is another line...\n");
|
||||||
|
} while (1);
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
ENTRY (loader)
|
||||||
|
|
||||||
|
SECTIONS {
|
||||||
|
. = 0x00100000;
|
||||||
|
|
||||||
|
.text :{
|
||||||
|
*(.text)
|
||||||
|
}
|
||||||
|
|
||||||
|
.rodata ALIGN (0x1000) : {
|
||||||
|
*(.rodata)
|
||||||
|
}
|
||||||
|
|
||||||
|
.data ALIGN (0x1000) : {
|
||||||
|
start_ctors = .;
|
||||||
|
*(.ctor*)
|
||||||
|
end_ctors = .;
|
||||||
|
start_dtors = .;
|
||||||
|
*(.dtor*)
|
||||||
|
end_dtors = .;
|
||||||
|
*(.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
.bss : {
|
||||||
|
sbss = .;
|
||||||
|
*(COMMON)
|
||||||
|
*(.bss)
|
||||||
|
ebss = .;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
global loader
|
||||||
|
global number
|
||||||
|
extern _main
|
||||||
|
extern start_ctors, end_ctors, start_dtors, end_dtors
|
||||||
|
|
||||||
|
MODULEALIGN equ 1<<0
|
||||||
|
MEMINFO equ 1<<1
|
||||||
|
FLAGS equ MODULEALIGN | MEMINFO
|
||||||
|
MAGIC equ 0x1BADB002
|
||||||
|
CHECKSUM equ -(MAGIC+FLAGS)
|
||||||
|
|
||||||
|
section .text
|
||||||
|
align 4
|
||||||
|
MultiBootHeader:
|
||||||
|
dd MAGIC
|
||||||
|
dd FLAGS
|
||||||
|
dd CHECKSUM
|
||||||
|
|
||||||
|
STACKSIZE equ 0x4000
|
||||||
|
|
||||||
|
; Loader
|
||||||
|
loader:
|
||||||
|
mov esp, stack+STACKSIZE
|
||||||
|
push eax
|
||||||
|
push ebx
|
||||||
|
|
||||||
|
static_ctors_loop:
|
||||||
|
mov ebx, start_ctors
|
||||||
|
jmp .test
|
||||||
|
.body:
|
||||||
|
call [ebx]
|
||||||
|
add ebx, 4
|
||||||
|
.test:
|
||||||
|
cmp ebx, end_ctors
|
||||||
|
jb .body
|
||||||
|
|
||||||
|
call _main
|
||||||
|
|
||||||
|
static_dtors_loop:
|
||||||
|
mov ebx, start_dtors
|
||||||
|
jmp .test
|
||||||
|
.body:
|
||||||
|
call [ebx]
|
||||||
|
add ebx, 4
|
||||||
|
.test:
|
||||||
|
cmp ebx, end_dtors
|
||||||
|
jb .body
|
||||||
|
|
||||||
|
hang:
|
||||||
|
hlt
|
||||||
|
jmp hang
|
||||||
|
|
||||||
|
; Number function, returns 12
|
||||||
|
number:
|
||||||
|
mov eax, 12
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
section .bss
|
||||||
|
align 4
|
||||||
|
stack:
|
||||||
|
resb STACKSIZE
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
#define PIC1 0x20 /* IO base address for master PIC */
|
||||||
|
#define PIC2 0xA0 /* IO base address for slave PIC */
|
||||||
|
#define PIC1_COMMAND PIC1
|
||||||
|
#define PIC1_DATA (PIC1+1)
|
||||||
|
#define PIC2_COMMAND PIC2
|
||||||
|
#define PIC2_DATA (PIC2+1)
|
||||||
|
#define NULL 0
|
||||||
|
|
||||||
|
extern "C" void _main (struct multiboot_data* mbd, unsigned int magic);
|
||||||
|
void ctamain();
|
||||||
|
|
||||||
|
typedef unsigned char byte;
|
||||||
|
|
||||||
|
// Entrance point
|
||||||
|
void _main (struct multiboot_data* mdb, unsigned int magic)
|
||||||
|
{
|
||||||
|
if (magic != 0x2BADB002)
|
||||||
|
{
|
||||||
|
cout ("Magic error. System halted!");
|
||||||
|
}
|
||||||
|
|
||||||
|
char* boot_loader_name = (char*) ((long*)mdb)[16];
|
||||||
|
|
||||||
|
ctamain();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// sends a byte (or word or dword) on a I/O location
|
||||||
|
static __inline__ void outb(unsigned short port, unsigned char val)
|
||||||
|
{
|
||||||
|
asm volatile("outb %0,%1"::"a"(val), "Nd" (port));
|
||||||
|
}
|
||||||
|
|
||||||
|
// receives a byte (or word or dword) from an I/O location
|
||||||
|
static __inline__ unsigned char inb(unsigned short port)
|
||||||
|
{
|
||||||
|
unsigned char ret;
|
||||||
|
asm volatile ("inb %1,%0":"=a"(ret):"Nd"(port));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forces the CPU to wait for an I/O operation to complete
|
||||||
|
static __inline__ void io_wait(void)
|
||||||
|
{
|
||||||
|
asm volatile("outb %%al, $0x80" : : "a"(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keyboard input
|
||||||
|
byte KeyboardIsr()
|
||||||
|
{
|
||||||
|
byte new_scan_code = inb(0x60);
|
||||||
|
/* Do something with the scancode.
|
||||||
|
* Remember you only get '''one''' byte of the scancode each time the ISR is invoked.
|
||||||
|
* (Though most of the times the scancode is only one byte.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Acknowledge the IRQ, pretty much tells the PIC that we can accept >=priority IRQs now. */
|
||||||
|
outb(0x20,0x20);
|
||||||
|
|
||||||
|
return new_scan_code;
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
cd /home/tiberiu/Desktop/ctaos++
|
||||||
|
echo ""
|
||||||
|
echo "Compiling..."
|
||||||
|
echo "gcc -o kernel.o -c kernel.cpp -Wall -Wextra -nostdlib -nostartfiles -nodefaultlibs"
|
||||||
|
gcc -o kernel.o -c kernel.cpp -Wall -Wextra -nostdlib -nostartfiles -nodefaultlibs -fno-exceptions
|
||||||
|
echo ""
|
||||||
|
echo "nasm -f elf -o loader.o loader.s"
|
||||||
|
nasm -f elf -o loader.o loader.s
|
||||||
|
echo ""
|
||||||
|
echo "ld -T linker.ld -o kernel.bin loader.o kernel.o"
|
||||||
|
ld -T linker.ld -o kernel.bin loader.o kernel.o
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
cd /home/tiberiu/Desktop/ctaos++
|
||||||
|
echo ""
|
||||||
|
echo "Making floppy image..."
|
||||||
|
echo ""
|
||||||
|
echo "dd if=/dev/zero of=pad bs=1 count=750"
|
||||||
|
dd if=/dev/zero of=pad bs=1 count=750
|
||||||
|
echo ""
|
||||||
|
echo "dd if=/dev/zero of=pad2 bs=1 count=(userspecified)"
|
||||||
|
dd if=/dev/zero of=pad2 bs=1 count=1358451
|
||||||
|
echo ""
|
||||||
|
echo "cat stage1 stage2 pad kernel.bin pad2 > floppy.img"
|
||||||
|
cat stage1 stage2 pad kernel.bin pad2 > floppy.img
|
||||||
|
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
unsigned char *videoram = (unsigned char*) 0xb8000;
|
||||||
|
static __inline__ void outb(unsigned short port, unsigned char val);
|
||||||
|
static __inline__ unsigned char inb(unsigned short port);
|
||||||
|
static __inline__ void io_wait(void);
|
||||||
|
|
||||||
|
// update cursor position
|
||||||
|
void cupdate_cursor (int x, int y)
|
||||||
|
{
|
||||||
|
unsigned short position = (y * 80) + x;
|
||||||
|
|
||||||
|
// unsigned char word1, word2;
|
||||||
|
unsigned short word;
|
||||||
|
|
||||||
|
/* word1 = inb (0x463);
|
||||||
|
word2 = inb (0x464);*/
|
||||||
|
|
||||||
|
word = (256 * inb (0x463)) + 256*inb (0x464);
|
||||||
|
|
||||||
|
outb(word, 0x0F);
|
||||||
|
outb(word+1, (unsigned char)(position&0xFF));
|
||||||
|
|
||||||
|
outb(word, 0x0E);
|
||||||
|
outb(word+1, (unsigned char )((position>>8)&0xFF));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the screen
|
||||||
|
void cls()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i <= 80*25; i++)
|
||||||
|
{
|
||||||
|
videoram[i*2] = 0;
|
||||||
|
videoram[i*2+1] = 0;
|
||||||
|
}
|
||||||
|
cursor.x = 0;
|
||||||
|
cursor.y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Place a character on the screen
|
||||||
|
void cputchar (int x, int y, char c, unsigned char style)
|
||||||
|
{
|
||||||
|
videoram[2*(y*80+x)] = c;
|
||||||
|
videoram[2*(y*80+x)+1] = style;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a character in a specified position
|
||||||
|
char cgetchar (int x, int y)
|
||||||
|
{
|
||||||
|
return videoram[2*(y*80+x)];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a style in specified position
|
||||||
|
unsigned char cgetstyle (int x, int y)
|
||||||
|
{
|
||||||
|
return videoram[2*(y*80+x)+1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scroll n lines
|
||||||
|
void scroll (int n)
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
cursor.y -= n;
|
||||||
|
for (y = 0; y < 25-n; y++)
|
||||||
|
for (x = 0; x < 80; x++)
|
||||||
|
cputchar (x, y, cgetchar(x, y+n), cgetstyle(x, y+n));
|
||||||
|
|
||||||
|
while (y<25) {
|
||||||
|
for (x = 0; x < 80; x++)
|
||||||
|
cputchar (x, y, 0, 0);
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Display a string of text on the screen
|
||||||
|
void cout (const char string[])
|
||||||
|
{
|
||||||
|
for (int i=0; string[i]!=0; i++) {
|
||||||
|
// scroll if necesary
|
||||||
|
if (cursor.y >= 25) scroll(1);
|
||||||
|
|
||||||
|
// end of line character behavior
|
||||||
|
if (string[i] == '\n') {
|
||||||
|
cursor.y++;
|
||||||
|
cursor.x = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// display text
|
||||||
|
else {
|
||||||
|
cputchar (cursor.x, cursor.y, string[i], 0x07);
|
||||||
|
if (++cursor.x >= 80) {
|
||||||
|
cursor.x = 0;
|
||||||
|
cursor.y++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cupdate_cursor (cursor.x, cursor.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cout_style (const char string[], unsigned char style)
|
||||||
|
{
|
||||||
|
for (int i=0; string[i]!=0; i++) {
|
||||||
|
// scroll if necesary
|
||||||
|
if (cursor.y >= 25) scroll(1);
|
||||||
|
|
||||||
|
// end of line character behavior
|
||||||
|
if (string[i] == '\n') {
|
||||||
|
cursor.y++;
|
||||||
|
cursor.x = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// display text
|
||||||
|
else {
|
||||||
|
cputchar (cursor.x, cursor.y, string[i], style);
|
||||||
|
if (++cursor.x >= 80) {
|
||||||
|
cursor.x = 0;
|
||||||
|
cursor.y++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cupdate_cursor (cursor.x, cursor.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
extern "C" int number();
|
||||||
|
|
||||||
|
|
||||||
|
struct point {int x,y;} cursor;
|
||||||
|
|
||||||
|
#include "console.h"
|
||||||
|
#include "startup.h"
|
||||||
|
#include "keyboard.h"
|
||||||
|
|
||||||
|
void ctamain()
|
||||||
|
{
|
||||||
|
int no = number();
|
||||||
|
char whatever[] = " is a number.\n";
|
||||||
|
unsigned char c, temp = 2;
|
||||||
|
|
||||||
|
whatever[0] = '0' + (char) (no/10);
|
||||||
|
whatever[1] = '0' + (char) (no%10);
|
||||||
|
|
||||||
|
cls();
|
||||||
|
cout("Hello, world!!!\n");
|
||||||
|
cout("Welcome to CTA OS 1.0\n");
|
||||||
|
cout_style("MUHAHAHAHAHAHAHAHAHSfdHAHAHA\n", 0x1F);
|
||||||
|
cout(whatever);
|
||||||
|
cout("Testing keyboard input:\n");
|
||||||
|
|
||||||
|
do { c = (char) KeyboardIsr();
|
||||||
|
temp = c;
|
||||||
|
do { c = KeyboardIsr(); } while (c == temp);
|
||||||
|
cout ("This is another line...\n");
|
||||||
|
} while (1);
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
#define SCROLL_LOCK 1
|
||||||
|
#define NUM_LOCK 2
|
||||||
|
#define CAPS_LOCK 4
|
||||||
|
|
||||||
|
#define _KEY_ESCAPE 1
|
||||||
|
#define _KEY_BACKSPACE 14
|
||||||
|
#define _KEY_TAB 15
|
||||||
|
#define _KEY_ENTER 28
|
||||||
|
#define _KEY_RETURN 28
|
||||||
|
#define _KEY_LEFT_CTRL 29
|
||||||
|
#define _KEY_LEFT_SHIFT 42
|
||||||
|
#define _KEY_RIGHT_SHIFT 54
|
||||||
|
#define _KEY_LEFT_ALT 56
|
||||||
|
#define _KEY_SPACEBAR 57
|
||||||
|
#define _KEY_CAPSLOCK 58
|
||||||
|
#define _KEY_NUMLOCK 69
|
||||||
|
#define _KEY_SCROLLLOCK 70
|
||||||
|
#define _KEY_F1 59
|
||||||
|
#define _KEY_F2 60
|
||||||
|
#define _KEY_F3 61
|
||||||
|
#define _KEY_F4 62
|
||||||
|
#define _KEY_F5 63
|
||||||
|
#define _KEY_F6 64
|
||||||
|
#define _KEY_F7 65
|
||||||
|
#define _KEY_F8 66
|
||||||
|
#define _KEY_F9 67
|
||||||
|
#define _KEY_F10 68
|
||||||
|
#define _KEY_F11 87
|
||||||
|
#define _KEY_F12 88
|
||||||
|
|
||||||
|
byte _ON_SHIFT, _ON_CTRL, _ON_CAPS, _ON_ALT, _ON_NUM;
|
||||||
|
|
||||||
|
// Update keyboard LEDs
|
||||||
|
void KeyboardLED (uint8_t status) {
|
||||||
|
uint8_t tmp;
|
||||||
|
|
||||||
|
while ((inb (0x64)&2)!=0) {}
|
||||||
|
outb (0x60, 0xED);
|
||||||
|
|
||||||
|
while ((inb (0x64)&2)!=0) {}
|
||||||
|
outb (0x60, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char KeyboardChar (byte scancode)
|
||||||
|
{
|
||||||
|
unsigned char row1_h[] = "!@#$%^&*()_+";
|
||||||
|
unsigned char row1_l[] = "1234567890-=";
|
||||||
|
|
||||||
|
unsigned char row2_h [] = "QWERTYUIOP{}";
|
||||||
|
unsigned char row2_l [] = "qwertyuiop[]";
|
||||||
|
|
||||||
|
unsigned char row3_h [] = "ASDFGHJKL:\"~";
|
||||||
|
unsigned char row3_l [] = "asdfghjkl;'`";
|
||||||
|
|
||||||
|
unsigned char row4_h [] = "ZXCVBNM<>?";
|
||||||
|
unsigned char row4_l [] = "zxcvbnm,./";
|
||||||
|
|
||||||
|
unsigned char numpad [] = "789-456+1230.";
|
||||||
|
|
||||||
|
unsigned char spacebar = " ";
|
||||||
|
unsigned char numpad_asterisk = "*";
|
||||||
|
|
||||||
|
if (scancode > 1 && scancode < 14 && _ON_SHIFT) return row1_h[scancode-2];
|
||||||
|
if (scancode > 1 && scancode < 14 && !_ON_SHIFT)return row1_l[scancode-2];
|
||||||
|
|
||||||
|
if (scancode > 15 && scancode < 28 && _ON_SHIFT) return row2_h[scancode-16];
|
||||||
|
if (scancode > 15 && scancode < 28 && !_ON_SHIFT) return row2_l[scancode-16];
|
||||||
|
|
||||||
|
if (scancode > 29 && scancode < 42 && _ON_SHIFT) return row3_h[scancode-30];
|
||||||
|
if (scancode > 29 && scancode < 42 && !_ON_SHIFT) return row3_l[scancode-30];
|
||||||
|
|
||||||
|
if (scancode > 43 && scancode < 54 && _ON_SHIFT) return row4_h[scancode-44];
|
||||||
|
if (scancode > 43 && scancode < 54 && !_ON_SHIFT) return row4_l[scancode-44];
|
||||||
|
|
||||||
|
if (scancode > 70 && scancode < 87 && _ON_NUM) return numpad[scancode-71];
|
||||||
|
|
||||||
|
if (scancode == 57) return spacebar;
|
||||||
|
if (scancode == 55) return numpad_asterisk;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keyboard input
|
||||||
|
byte KeyboardIsr()
|
||||||
|
{
|
||||||
|
byte new_scan_code = inb(0x60);
|
||||||
|
/* Do something with the scancode.
|
||||||
|
* Remember you only get '''one''' byte of the scancode each time the ISR is invoked.
|
||||||
|
* (Though most of the times the scancode is only one byte.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Acknowledge the IRQ, pretty much tells the PIC that we can accept >=priority IRQs now. */
|
||||||
|
outb(0x20,0x20);
|
||||||
|
|
||||||
|
return new_scan_code;
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
ENTRY (loader)
|
||||||
|
|
||||||
|
SECTIONS {
|
||||||
|
. = 0x00100000;
|
||||||
|
|
||||||
|
.text :{
|
||||||
|
*(.text)
|
||||||
|
}
|
||||||
|
|
||||||
|
.rodata ALIGN (0x1000) : {
|
||||||
|
*(.rodata)
|
||||||
|
}
|
||||||
|
|
||||||
|
.data ALIGN (0x1000) : {
|
||||||
|
start_ctors = .;
|
||||||
|
*(.ctor*)
|
||||||
|
end_ctors = .;
|
||||||
|
start_dtors = .;
|
||||||
|
*(.dtor*)
|
||||||
|
end_dtors = .;
|
||||||
|
*(.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
.bss : {
|
||||||
|
sbss = .;
|
||||||
|
*(COMMON)
|
||||||
|
*(.bss)
|
||||||
|
ebss = .;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
global loader
|
||||||
|
global number
|
||||||
|
extern _main
|
||||||
|
extern start_ctors, end_ctors, start_dtors, end_dtors
|
||||||
|
|
||||||
|
MODULEALIGN equ 1<<0
|
||||||
|
MEMINFO equ 1<<1
|
||||||
|
FLAGS equ MODULEALIGN | MEMINFO
|
||||||
|
MAGIC equ 0x1BADB002
|
||||||
|
CHECKSUM equ -(MAGIC+FLAGS)
|
||||||
|
|
||||||
|
section .text
|
||||||
|
align 4
|
||||||
|
MultiBootHeader:
|
||||||
|
dd MAGIC
|
||||||
|
dd FLAGS
|
||||||
|
dd CHECKSUM
|
||||||
|
|
||||||
|
STACKSIZE equ 0x4000
|
||||||
|
|
||||||
|
; Loader
|
||||||
|
loader:
|
||||||
|
mov esp, stack+STACKSIZE
|
||||||
|
push eax
|
||||||
|
push ebx
|
||||||
|
|
||||||
|
static_ctors_loop:
|
||||||
|
mov ebx, start_ctors
|
||||||
|
jmp .test
|
||||||
|
.body:
|
||||||
|
call [ebx]
|
||||||
|
add ebx, 4
|
||||||
|
.test:
|
||||||
|
cmp ebx, end_ctors
|
||||||
|
jb .body
|
||||||
|
|
||||||
|
call _main
|
||||||
|
|
||||||
|
static_dtors_loop:
|
||||||
|
mov ebx, start_dtors
|
||||||
|
jmp .test
|
||||||
|
.body:
|
||||||
|
call [ebx]
|
||||||
|
add ebx, 4
|
||||||
|
.test:
|
||||||
|
cmp ebx, end_dtors
|
||||||
|
jb .body
|
||||||
|
|
||||||
|
hang:
|
||||||
|
hlt
|
||||||
|
jmp hang
|
||||||
|
|
||||||
|
; Number function, returns 12
|
||||||
|
number:
|
||||||
|
mov eax, 12
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
section .bss
|
||||||
|
align 4
|
||||||
|
stack:
|
||||||
|
resb STACKSIZE
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
#define PIC1 0x20 /* IO base address for master PIC */
|
||||||
|
#define PIC2 0xA0 /* IO base address for slave PIC */
|
||||||
|
#define PIC1_COMMAND PIC1
|
||||||
|
#define PIC1_DATA (PIC1+1)
|
||||||
|
#define PIC2_COMMAND PIC2
|
||||||
|
#define PIC2_DATA (PIC2+1)
|
||||||
|
#define NULL 0
|
||||||
|
#define true 1
|
||||||
|
#define false 0
|
||||||
|
|
||||||
|
extern "C" void _main (struct multiboot_data* mbd, unsigned int magic);
|
||||||
|
void ctamain();
|
||||||
|
|
||||||
|
typedef unsigned char byte;
|
||||||
|
|
||||||
|
// Entrance point
|
||||||
|
void _main (struct multiboot_data* mdb, unsigned int magic)
|
||||||
|
{
|
||||||
|
if (magic != 0x2BADB002)
|
||||||
|
{
|
||||||
|
cout ("Magic error. System halted!");
|
||||||
|
}
|
||||||
|
|
||||||
|
char* boot_loader_name = (char*) ((long*)mdb)[16];
|
||||||
|
|
||||||
|
ctamain();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// sends a byte (or word or dword) on a I/O location
|
||||||
|
static __inline__ void outb(unsigned short port, unsigned char val)
|
||||||
|
{
|
||||||
|
asm volatile("outb %0,%1"::"a"(val), "Nd" (port));
|
||||||
|
}
|
||||||
|
|
||||||
|
// receives a byte (or word or dword) from an I/O location
|
||||||
|
static __inline__ unsigned char inb(unsigned short port)
|
||||||
|
{
|
||||||
|
unsigned char ret;
|
||||||
|
asm volatile ("inb %1,%0":"=a"(ret):"Nd"(port));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forces the CPU to wait for an I/O operation to complete
|
||||||
|
static __inline__ void io_wait(void)
|
||||||
|
{
|
||||||
|
asm volatile("outb %%al, $0x80" : : "a"(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keyboard input
|
||||||
|
byte KeyboardIsr()
|
||||||
|
{
|
||||||
|
byte new_scan_code = inb(0x60);
|
||||||
|
/* Do something with the scancode.
|
||||||
|
* Remember you only get '''one''' byte of the scancode each time the ISR is invoked.
|
||||||
|
* (Though most of the times the scancode is only one byte.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Acknowledge the IRQ, pretty much tells the PIC that we can accept >=priority IRQs now. */
|
||||||
|
outb(0x20,0x20);
|
||||||
|
|
||||||
|
return new_scan_code;
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
echo ""
|
||||||
|
echo "GCC compiling... "
|
||||||
|
gcc -o kernel.o -c kernel.cpp -Wall -Wextra -nostdlib -nostartfiles -nodefaultlibs -fno-exceptions
|
||||||
|
echo ""
|
||||||
|
echo "NASM compiling... "
|
||||||
|
nasm -f elf -o loader.o loader.s
|
||||||
|
echo ""
|
||||||
|
echo "Linking... "
|
||||||
|
ld -T linker.ld -o kernel.bin kernel.o loader.o
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
cd /home/tiberiu/Desktop/tctaos++
|
||||||
|
echo ""
|
||||||
|
echo "Making floppy image..."
|
||||||
|
echo ""
|
||||||
|
echo "dd if=/dev/zero of=pad bs=1 count=750"
|
||||||
|
dd if=/dev/zero of=pad bs=1 count=750
|
||||||
|
echo ""
|
||||||
|
echo "dd if=/dev/zero of=pad bs=1 count=1358454"
|
||||||
|
dd if=/dev/zero of=pad2 bs=1 count=1358454
|
||||||
|
echo ""
|
||||||
|
echo "cat stage1 stage2 pad kernel.bin > floppy.img"
|
||||||
|
cat stage1 stage2 pad kernel.bin pad2 > floppy.img
|
||||||
|
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
extern "C" void _main (struct multiboot_data* mbd, unsigned int magic);
|
||||||
|
|
||||||
|
unsigned char *videoram = (unsigned char *) 0xb8000;
|
||||||
|
|
||||||
|
void ctamain();
|
||||||
|
void putchar(int x, int y, char c, unsigned char style);
|
||||||
|
void cls();
|
||||||
|
|
||||||
|
void _main (struct multiboot_data* mbd, unsigned int magic)
|
||||||
|
{
|
||||||
|
if (magic != 0x2BADB002)
|
||||||
|
{ //Error behaviour
|
||||||
|
}
|
||||||
|
|
||||||
|
char* boot_loader_name = (char*) ((long*)mbd)[16];
|
||||||
|
|
||||||
|
ctamain();
|
||||||
|
}
|
||||||
|
|
||||||
|
void putchar(int x, int y, char c, unsigned char style)
|
||||||
|
{
|
||||||
|
videoram[2*((80*y)+x)] = c;
|
||||||
|
videoram[2*((80*y)+x)+1] = style;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cls()
|
||||||
|
{
|
||||||
|
for (int x = 0; x < 80; x ++)
|
||||||
|
for (int y = 0; y < 25; y++)
|
||||||
|
putchar (x, y, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cout(int x, int y, char str[])
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
while (str[i] != 0) {
|
||||||
|
putchar (i+x, y, str[i], 0x07);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ctamain()
|
||||||
|
{
|
||||||
|
cls();
|
||||||
|
cout (0, 0, "Hello world!");
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
ENTRY (loader)
|
||||||
|
|
||||||
|
SECTIONS {
|
||||||
|
. = 0x00100000;
|
||||||
|
|
||||||
|
.text :{
|
||||||
|
*(.text)
|
||||||
|
}
|
||||||
|
|
||||||
|
.rodata ALIGN (0x1000) : {
|
||||||
|
*(.rodata)
|
||||||
|
}
|
||||||
|
|
||||||
|
.data ALIGN (0x1000) : {
|
||||||
|
start_ctors = .;
|
||||||
|
*(.ctor*)
|
||||||
|
end_ctors = .;
|
||||||
|
start_dtors = .;
|
||||||
|
*(.dtor*)
|
||||||
|
end_dtors = .;
|
||||||
|
*(.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
.bss : {
|
||||||
|
sbss = .;
|
||||||
|
*(COMMON)
|
||||||
|
*(.bss)
|
||||||
|
ebss = .;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
global loader
|
||||||
|
extern _main
|
||||||
|
extern start_ctors, end_ctors, start_dtors, end_dtors
|
||||||
|
|
||||||
|
MODULEALIGN equ 1<<0
|
||||||
|
MEMINFO equ 1<<1
|
||||||
|
FLAGS equ MODULEALIGN | MEMINFO
|
||||||
|
MAGIC equ 0x1BADB002
|
||||||
|
CHECKSUM equ -(MAGIC+FLAGS)
|
||||||
|
|
||||||
|
section .text
|
||||||
|
align 4
|
||||||
|
MultiBootHeader:
|
||||||
|
dd MAGIC
|
||||||
|
dd FLAGS
|
||||||
|
dd CHECKSUM
|
||||||
|
|
||||||
|
STACKSIZE equ 0x4000
|
||||||
|
|
||||||
|
; Loader
|
||||||
|
loader:
|
||||||
|
mov esp, stack+STACKSIZE
|
||||||
|
push eax
|
||||||
|
push ebx
|
||||||
|
|
||||||
|
static_ctors_loop:
|
||||||
|
mov ebx, start_ctors
|
||||||
|
jmp .test
|
||||||
|
.body:
|
||||||
|
call [ebx]
|
||||||
|
add ebx, 4
|
||||||
|
.test:
|
||||||
|
cmp ebx, end_ctors
|
||||||
|
jb .body
|
||||||
|
|
||||||
|
call _main
|
||||||
|
|
||||||
|
static_dtors_loop:
|
||||||
|
mov ebx, start_dtors
|
||||||
|
jmp .test
|
||||||
|
.body:
|
||||||
|
call [ebx]
|
||||||
|
add ebx, 4
|
||||||
|
.test:
|
||||||
|
cmp ebx, end_dtors
|
||||||
|
jb .body
|
||||||
|
|
||||||
|
hang:
|
||||||
|
hlt
|
||||||
|
jmp hang
|
||||||
|
|
||||||
|
|
||||||
|
section .bss
|
||||||
|
align 4
|
||||||
|
stack:
|
||||||
|
resb STACKSIZE
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
cd /home/tiberiu/Desktop/ctaos++
|
||||||
|
echo ""
|
||||||
|
echo "Compiling..."
|
||||||
|
echo "gcc -o kernel.o -c kernel.cpp -Wall -Wextra -nostdlib -nostartfiles -nodefaultlibs"
|
||||||
|
gcc -o kernel.o -c kernel.cpp -Wall -Wextra -nostdlib -nostartfiles -nodefaultlibs -fno-exceptions
|
||||||
|
echo ""
|
||||||
|
echo "nasm -f elf -o loader.o loader.s"
|
||||||
|
nasm -f elf -o loader.o loader.s
|
||||||
|
echo ""
|
||||||
|
echo "ld -T linker.ld -o kernel.bin loader.o kernel.o"
|
||||||
|
ld -T linker.ld -o kernel.bin loader.o kernel.o
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
cd /home/tiberiu/Desktop/ctaos++
|
||||||
|
echo ""
|
||||||
|
echo "Making floppy image..."
|
||||||
|
echo ""
|
||||||
|
echo "dd if=/dev/zero of=pad bs=1 count=750"
|
||||||
|
dd if=/dev/zero of=pad bs=1 count=750
|
||||||
|
echo ""
|
||||||
|
echo "dd if=/dev/zero of=pad2 bs=1 count=(userspecified)"
|
||||||
|
dd if=/dev/zero of=pad2 bs=1 count=1358451
|
||||||
|
echo ""
|
||||||
|
echo "cat stage1 stage2 pad kernel.bin pad2 > floppy.img"
|
||||||
|
cat stage1 stage2 pad kernel.bin pad2 > floppy.img
|
||||||
|
|
||||||
@@ -0,0 +1,192 @@
|
|||||||
|
unsigned char *videoram = (unsigned char*) 0xb8000; // Video memory
|
||||||
|
struct unsigned_point {unsigned int x,y;} cursor; // Cursor position in a point structure
|
||||||
|
char hex[] = "0123456789ABCDEF"; // Hex chars
|
||||||
|
|
||||||
|
void cDetectVideo();
|
||||||
|
void cendl();
|
||||||
|
void cFillStyle(byte style);
|
||||||
|
char cgetchar (int x, int y);
|
||||||
|
unsigned char cgetstyle (int x, int y);
|
||||||
|
void cls();
|
||||||
|
void cout (const char string[]);
|
||||||
|
void cout_hex (int no);
|
||||||
|
void cout_hex (short no);
|
||||||
|
void cout_hex (unsigned short no);
|
||||||
|
void cout_hex (char no);
|
||||||
|
void cout_style (const char string[], unsigned char style);
|
||||||
|
void cputchar (int x, int y, char c, unsigned char style);
|
||||||
|
void cscroll (int n);
|
||||||
|
void cUpdateCursor ();
|
||||||
|
|
||||||
|
void cDetectVideo()
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
c = (*(volatile unsigned short*)0x410)&0x30;
|
||||||
|
|
||||||
|
//c can be 0x00 or 0x20 for colour, 0x30 for mono.
|
||||||
|
if (c==0x30) {
|
||||||
|
video_mode_colors = 0;
|
||||||
|
videoram = (unsigned char*) 0xb0000;
|
||||||
|
}
|
||||||
|
else video_mode_colors = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// update cursor position
|
||||||
|
void cUpdateCursor (int x, int y)
|
||||||
|
{
|
||||||
|
unsigned position = (y * 80) + x;
|
||||||
|
unsigned short address = 0x3D4;
|
||||||
|
|
||||||
|
outb(address, 0x0E);
|
||||||
|
outb(address+1, (position >> 8) & 0xFF);
|
||||||
|
|
||||||
|
outb(address, 0x0F);
|
||||||
|
outb(address+1, position & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the screen
|
||||||
|
void cls()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i <= 80*25; i++)
|
||||||
|
{
|
||||||
|
videoram[i*2] = 0;
|
||||||
|
videoram[i*2+1] = 0;
|
||||||
|
}
|
||||||
|
cursor.x = 0;
|
||||||
|
cursor.y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Fill the screen with a style
|
||||||
|
void cFillStyle(byte style)
|
||||||
|
{
|
||||||
|
for (int i = 0; i <= 80*25; i++)
|
||||||
|
videoram[i*2+1] = style;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Place a character on the screen
|
||||||
|
void cputchar (int x, int y, char c, unsigned char style)
|
||||||
|
{
|
||||||
|
videoram[2*(y*80+x)] = c;
|
||||||
|
videoram[2*(y*80+x)+1] = style;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a character in a specified position
|
||||||
|
char cgetchar (int x, int y)
|
||||||
|
{
|
||||||
|
return videoram[2*(y*80+x)];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a style in specified position
|
||||||
|
unsigned char cgetstyle (int x, int y)
|
||||||
|
{
|
||||||
|
return videoram[2*(y*80+x)+1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scroll n lines
|
||||||
|
void cscroll (int n)
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
cursor.y -= n;
|
||||||
|
for (y = 0; y < 25-n; y++)
|
||||||
|
for (x = 0; x < 80; x++)
|
||||||
|
cputchar (x, y, cgetchar(x, y+n), cgetstyle(x, y+n));
|
||||||
|
|
||||||
|
while (y<25) {
|
||||||
|
for (x = 0; x < 80; x++)
|
||||||
|
cputchar (x, y, 0, 0);
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cendl()
|
||||||
|
{
|
||||||
|
cursor.y++; cursor.x = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display a string of text on the screen
|
||||||
|
void cout (const char string[])
|
||||||
|
{
|
||||||
|
for (int i=0; string[i]!=0; i++) {
|
||||||
|
// scroll if necesary
|
||||||
|
if (cursor.y >= 25) cscroll(1);
|
||||||
|
|
||||||
|
// end of line character behavior
|
||||||
|
if (string[i] == '\n')
|
||||||
|
cendl();
|
||||||
|
|
||||||
|
// display text
|
||||||
|
else {
|
||||||
|
cputchar (cursor.x, cursor.y, string[i], 0x07);
|
||||||
|
if (++cursor.x >= 80) cendl();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cout_hex (char no)
|
||||||
|
{
|
||||||
|
char str[] = "0x ";
|
||||||
|
str[3] = hex[no%16];
|
||||||
|
str[2] = hex[no/16];
|
||||||
|
cout (str);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cout_hex (short no)
|
||||||
|
{
|
||||||
|
char str[] = "0x ";
|
||||||
|
str[5] = hex[no%16];
|
||||||
|
str[4] = hex[(no/16)%16];
|
||||||
|
str[3] = hex[(no/256)%16];
|
||||||
|
str[2] = hex[no/(256*16)];
|
||||||
|
cout (str);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cout_hex (unsigned short no)
|
||||||
|
{
|
||||||
|
char str[] = "0x ";
|
||||||
|
str[5] = hex[no%16];
|
||||||
|
str[4] = hex[(no/16)%16];
|
||||||
|
str[3] = hex[(no/256)%16];
|
||||||
|
str[2] = hex[no/(256*16)];
|
||||||
|
cout (str);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void cout_hex (int no)
|
||||||
|
{
|
||||||
|
char str[] = "0x ";
|
||||||
|
str[9] = hex[no%16];
|
||||||
|
str[8] = hex[(no/16)%16];
|
||||||
|
str[7] = hex[(no/(16*16))%16];
|
||||||
|
str[6] = hex[(no/(16*16*16))%16];
|
||||||
|
str[5] = hex[(no/(16*16*16*16))%16];
|
||||||
|
str[4] = hex[(no/(16*16*16*16*16))%16];
|
||||||
|
str[3] = hex[(no/(16*16*16*16*16*16))%16];
|
||||||
|
str[2] = hex[no/(16*16*16*16*16*16*16)];
|
||||||
|
cout (str);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cout_style (const char string[], unsigned char style)
|
||||||
|
{
|
||||||
|
for (int i=0; string[i]!=0; i++) {
|
||||||
|
// scroll if necesary
|
||||||
|
if (cursor.y >= 25) cscroll(1);
|
||||||
|
|
||||||
|
// end of line character behavior
|
||||||
|
if (string[i] == '\n') {
|
||||||
|
do cputchar (cursor.x, cursor.y, ' ', style);
|
||||||
|
while (++cursor.x < 80);
|
||||||
|
cendl();
|
||||||
|
}
|
||||||
|
|
||||||
|
// display text
|
||||||
|
else {
|
||||||
|
cputchar (cursor.x, cursor.y, string[i], style);
|
||||||
|
if (++cursor.x >= 80) cendl();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
#include "floppy.h"
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
#ifndef __FLOPPY_CONTROLLER
|
||||||
|
#define __FLOPPY_CONTROLLER
|
||||||
|
|
||||||
|
#define FLOPPYDigitalOutputRegister 0x3F2
|
||||||
|
#define FLOPPYMainStatusRegister 0x3F4
|
||||||
|
|
||||||
|
/********************************************************************************
|
||||||
|
Byte to binary and binary to byte functions
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
void byte_to_binary (unsigned char byt, bool array[])
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
while (++i < 8) {
|
||||||
|
array[i] = byt%2;
|
||||||
|
byt /= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
byte binary_to_byte (bool array[])
|
||||||
|
{
|
||||||
|
byte ret;
|
||||||
|
ret = array[0];
|
||||||
|
ret += 2 * (byte)array[1];
|
||||||
|
ret += 4 * (byte)array[2];
|
||||||
|
ret += 8 * (byte)array[3];
|
||||||
|
ret += 16 * (byte)array[4];
|
||||||
|
ret += 32 * (byte)array[5];
|
||||||
|
ret += 64 * (byte)array[6];
|
||||||
|
ret += 128 * (byte)array[7];
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/********************************************************************************
|
||||||
|
Floppy functions
|
||||||
|
********************************************************************************/
|
||||||
|
byte floppy_motor(char drive, bool state)
|
||||||
|
{
|
||||||
|
byte status;
|
||||||
|
bool array[8];
|
||||||
|
|
||||||
|
status = inb (FLOPPYDigitalOutputRegister);
|
||||||
|
byte_to_binary (status, array);
|
||||||
|
|
||||||
|
if (drive == 'A') array[4] = state;
|
||||||
|
if (drive == 'B') array[5] = state;
|
||||||
|
if (drive == 'C') array[6] = state;
|
||||||
|
if (drive == 'D') array[7] = state;
|
||||||
|
|
||||||
|
|
||||||
|
status = binary_to_byte (array);
|
||||||
|
outb (FLOPPYDigitalOutputRegister, status);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
byte floppy_DMA(bool state)
|
||||||
|
{
|
||||||
|
byte status;
|
||||||
|
bool array[8];
|
||||||
|
|
||||||
|
status = inb (FLOPPYDigitalOutputRegister);
|
||||||
|
byte_to_binary (status, array);
|
||||||
|
|
||||||
|
array[3] = state;
|
||||||
|
|
||||||
|
status = binary_to_byte (array);
|
||||||
|
outb (FLOPPYDigitalOutputRegister, status);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void floppy_reset()
|
||||||
|
{
|
||||||
|
outb (FLOPPYDigitalOutputRegister, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte floppy_select (char drive)
|
||||||
|
{
|
||||||
|
byte status;
|
||||||
|
bool array[8];
|
||||||
|
|
||||||
|
status = inb (FLOPPYDigitalOutputRegister);
|
||||||
|
byte_to_binary (status, array);
|
||||||
|
|
||||||
|
array[0] = (drive - 'A')%2;
|
||||||
|
array[1] = (drive >= 'C');
|
||||||
|
|
||||||
|
status = binary_to_byte (array);
|
||||||
|
outb (FLOPPYDigitalOutputRegister, status);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool floppy_ready()
|
||||||
|
{
|
||||||
|
byte status;
|
||||||
|
bool array[8];
|
||||||
|
|
||||||
|
status = inb (FLOPPYMainStatusRegister);
|
||||||
|
byte_to_binary (status, array);
|
||||||
|
|
||||||
|
if (array[7] && !array[4]) return true;
|
||||||
|
else return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
#include "system.h"
|
||||||
|
#include "console.h"
|
||||||
|
#include "keyboard.h"
|
||||||
|
#include "drivers/drivers.h"
|
||||||
|
|
||||||
|
void ctamain()
|
||||||
|
{
|
||||||
|
//cls();
|
||||||
|
char k;
|
||||||
|
cout_style("Welcome to CTA OS 1.0\n", 0x2A);
|
||||||
|
|
||||||
|
floppy_motor('A', 0);
|
||||||
|
cout_style("Now you can eject your floppy :D\n", 0x1F);
|
||||||
|
|
||||||
|
cout("Testing keyboard input:\n");
|
||||||
|
|
||||||
|
do { do { k = KeyboardUpdate(); }
|
||||||
|
while (k == -1);
|
||||||
|
|
||||||
|
if (k<0) k*=-1;
|
||||||
|
|
||||||
|
cputchar(60, 20, k, 0x2F);
|
||||||
|
cputchar(60, 21, hex[k/16], 0x1F);
|
||||||
|
cputchar(61, 21, hex[k%16], 0x1F);
|
||||||
|
|
||||||
|
for (int i = 0; i < 0x80; i++)
|
||||||
|
{
|
||||||
|
cputchar(i, 10, keyboard[i]+'0', 0x0F);
|
||||||
|
cputchar(i, 12, keyboard_special[i]+'0', 0x0F);
|
||||||
|
}
|
||||||
|
cursor.x = 0; cursor.y = 14;
|
||||||
|
cout ("Special: "); cputchar (15, 14, keyb_specialON+'0', 0x03);
|
||||||
|
|
||||||
|
cursor.x = 0; cursor.y = 16;
|
||||||
|
cout ("LShift: "); cputchar (15, 16, keyb_LSHIFT+'0', 0x03);
|
||||||
|
cursor.x = 40; cursor.y = 16;
|
||||||
|
cout ("RShift: "); cputchar (55, 16, keyb_RSHIFT+'0', 0x03);
|
||||||
|
|
||||||
|
cursor.x = 0; cursor.y = 17;
|
||||||
|
cout ("LAlt: "); cputchar (15, 17, keyb_LALT+'0', 0x03);
|
||||||
|
cursor.x = 40; cursor.y = 17;
|
||||||
|
cout ("RAlt: "); cputchar (55, 17, keyb_RALT+'0', 0x03);
|
||||||
|
|
||||||
|
cursor.x = 0; cursor.y = 18;
|
||||||
|
cout ("LCTRL: "); cputchar (15, 18, keyb_LCTRL+'0', 0x03);
|
||||||
|
cursor.x = 40; cursor.y = 18;
|
||||||
|
cout ("RCTRL: "); cputchar (55, 18, keyb_RCTRL+'0', 0x03);
|
||||||
|
|
||||||
|
cursor.x = 0; cursor.y = 21;
|
||||||
|
cout ("STATUS: ");
|
||||||
|
for (int i = 0; i < 0x60; i++) {
|
||||||
|
if (keyboard[i] && !keyboard_special[i]) {
|
||||||
|
cout(keys_list[i]);
|
||||||
|
cout (" \n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keyboard[1]) {
|
||||||
|
cout("Rebooting system...");
|
||||||
|
SystemReboot();
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (1);
|
||||||
|
}
|
||||||
@@ -0,0 +1,169 @@
|
|||||||
|
#ifndef __STANDARD_US_KEYBOARD
|
||||||
|
#define __STANDARD_US_KEYBOARD
|
||||||
|
#define SCROLL_LOCK 1
|
||||||
|
#define NUM_LOCK 2
|
||||||
|
#define CAPS_LOCK 4
|
||||||
|
|
||||||
|
unsigned char keyboard[0x60]; // All keys pressed/released list
|
||||||
|
unsigned char keyboard_special[128]; // All special keys pressed/released list
|
||||||
|
bool keyb_specialON; // Other special keys
|
||||||
|
bool keyb_LSHIFT, keyb_RSHIFT, keyb_FAKESHIFT,
|
||||||
|
keyb_LALT, keyb_RALT,
|
||||||
|
keyb_LCTRL, keyb_RCTRL;
|
||||||
|
|
||||||
|
bool keyb_NUMLOCK, keyb_SCROLLLOCK, keyb_CAPSLOCK;
|
||||||
|
unsigned char keyb_pause; // Pause/break key
|
||||||
|
byte prev;
|
||||||
|
|
||||||
|
char keys_list[0x60][0x1F] = { "ERROR", "Escape", "1 !", "2 @", "3 #",
|
||||||
|
"4 $", "5 %", "6 ^", "7 &", "8 *", "9 (", "0 )", "- _",
|
||||||
|
"= +", "Backspace", "Tab", "q Q", "w W", "e E", "r R", "t T", "y Y",
|
||||||
|
"u U", "i I", "o O", "p P", "[ {", "] }" ,"Enter", "LCtrl", "a A", "s S",
|
||||||
|
"d D", "f F", "g G", "h H", "j J", "k K", "l L", "; :", "' \"", "` ~",
|
||||||
|
"LShift", "\\ |", "z Z", "x X", "c C", "v V", "b B", "n N", "m M", ", <",
|
||||||
|
". >", "/ ?", "RShift", "Keypad-*/PrtScn", "LAlt", "Space bar",
|
||||||
|
"CapsLock", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8",
|
||||||
|
"F9", "F10", "NumLock", "ScrollLock", "Keypad-7/Home",
|
||||||
|
"Keypad-8/Up", "Keypad-9/PgUp", "Keypad--", "Keypad-4/Left",
|
||||||
|
"Keypad-5", "Keypad-6/Right", "Keypad-+", "Keypad-1/End",
|
||||||
|
"Keypad-2/Down", "Keypad-3/PgDn", "Keypad-0/Ins", "Keypad-./Del",
|
||||||
|
"Alt-SysRq", " ", "BLANK", "F11", "F12" };
|
||||||
|
|
||||||
|
|
||||||
|
// Update keyboard LEDs
|
||||||
|
void KeyboardLED (uint8_t status) {
|
||||||
|
while ((inb (0x64)&2)!=0) {}
|
||||||
|
outb (0x60, 0xED);
|
||||||
|
|
||||||
|
while ((inb (0x64)&2)!=0) {}
|
||||||
|
outb (0x60, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
byte KeyboardGetInput()
|
||||||
|
{ byte scan = inb(0x60);
|
||||||
|
outb (0x20, 0x20);
|
||||||
|
return scan;
|
||||||
|
}
|
||||||
|
|
||||||
|
char scancode_to_ASCII(byte scancode, bool shift)
|
||||||
|
{
|
||||||
|
// Ignore break code
|
||||||
|
if (scancode >= 0x80) scancode-=0x80;
|
||||||
|
|
||||||
|
|
||||||
|
if (scancode == 0x01) return 0x00; // Escape
|
||||||
|
else if (scancode >= 0x02 && scancode <= 0x0D) { // First row on the keyboard
|
||||||
|
unsigned char str0[] = "1234567890-=";
|
||||||
|
unsigned char str1[] = "!@#$%^&*()_+";
|
||||||
|
if (shift) return str1[scancode-0x02];
|
||||||
|
else return str0[scancode-0x02];
|
||||||
|
}
|
||||||
|
else if (scancode == 0x0E) return 0x08; // Backspace
|
||||||
|
else if (scancode == 0x0F) return 0x09; // Tab
|
||||||
|
else if (scancode >= 0x10 && scancode <= 0x1b) { // Second row on the keyboard
|
||||||
|
unsigned char str0[] = "qwertyuiop[]";
|
||||||
|
unsigned char str1[] = "QWERTYUIOP{}";
|
||||||
|
if (shift) return str1[scancode-0x10];
|
||||||
|
else return str0[scancode-0x10];
|
||||||
|
}
|
||||||
|
else if (scancode == 0x1C) return 0x0D; // Enter (Carrige return)
|
||||||
|
else if (scancode >= 0x1E && scancode <= 0x29) { // Third row on the keyboard
|
||||||
|
unsigned char str0[] = "asdfghjkl;'`";
|
||||||
|
unsigned char str1[] = "ASDFGHJKL:\"~";
|
||||||
|
if (shift) return str1[scancode-0x1E];
|
||||||
|
else return str0[scancode-0x1E];
|
||||||
|
}
|
||||||
|
else if (scancode == 0x2B) { // | key
|
||||||
|
unsigned char str0[] = "\\|";
|
||||||
|
return str0[shift];
|
||||||
|
}
|
||||||
|
else if (scancode >= 0x2C && scancode <= 0x35) { // Forth row on the keyboard
|
||||||
|
unsigned char str0[] = "zxcvbnm,./";
|
||||||
|
unsigned char str1[] = "ZXCVBNM<>?";
|
||||||
|
if (shift) return str1[scancode-0x2C];
|
||||||
|
else return str0[scancode-0x2C];
|
||||||
|
}
|
||||||
|
else if (scancode == 0x37) return '*';
|
||||||
|
else if (scancode == 0x39) return ' ';
|
||||||
|
else if (scancode >= 0x47 && scancode <= 0x53) { // Numpad keys
|
||||||
|
unsigned char str0[] = "789-456+1230.";
|
||||||
|
return str0[scancode-0x47];
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keyboard input
|
||||||
|
byte KeyboardUpdate()
|
||||||
|
{
|
||||||
|
byte new_scan_code = KeyboardGetInput();
|
||||||
|
|
||||||
|
if (new_scan_code == prev) return -1; // 1: Nothing new
|
||||||
|
switch (new_scan_code) {
|
||||||
|
case 0x00: return -2; break; // 2: Keyboard error
|
||||||
|
case 0xFF: return -2; break;
|
||||||
|
case 0xAA: return -3; break; // 3: BAT (Basic Assurance Test) OK
|
||||||
|
case 0xFA: return -4; break; // 4: Acknowledge from kbd
|
||||||
|
case 0xFC: return -5; break; // 5: BAT error or Mouse transmit error
|
||||||
|
case 0xFD: return -6; break; // 6: Internal failure
|
||||||
|
case 0xFE: return -7; break; // 7: Keyboard fails to ack, please resend
|
||||||
|
|
||||||
|
case 0xE1: keyb_specialON = true; return 0; break;
|
||||||
|
case 0xE0: keyb_specialON = true; return 0; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keyb_specialON) {
|
||||||
|
// FAKE SHIFT
|
||||||
|
if (new_scan_code == 0x2A) keyb_FAKESHIFT = true;
|
||||||
|
else if (new_scan_code == 0xAA) keyb_FAKESHIFT = false;
|
||||||
|
// Right Alt
|
||||||
|
else if (new_scan_code == 0x38) keyb_RALT = true;
|
||||||
|
else if (new_scan_code == 0x38+0x80) keyb_RALT = false;
|
||||||
|
// Right Control
|
||||||
|
else if (new_scan_code == 0x1D) keyb_RCTRL = true;
|
||||||
|
else if (new_scan_code == 0x1D+0x80) keyb_RCTRL = false;
|
||||||
|
|
||||||
|
else if (new_scan_code < 0x80) keyboard_special[new_scan_code] = true;
|
||||||
|
else keyboard_special[new_scan_code-0x80] = false;
|
||||||
|
|
||||||
|
keyb_specialON = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
// Left Shift
|
||||||
|
if (new_scan_code == 0x2A) keyb_LSHIFT = true;
|
||||||
|
else if (new_scan_code == 0xAA) keyb_LSHIFT = false;
|
||||||
|
// Right Shift
|
||||||
|
else if (new_scan_code == 0x36) keyb_RSHIFT = true;
|
||||||
|
else if (new_scan_code == 0x36+0x80) keyb_RSHIFT = false;
|
||||||
|
// Left Alt
|
||||||
|
else if (new_scan_code == 0x38) keyb_LALT = true;
|
||||||
|
else if (new_scan_code == 0x38+0x80) keyb_LALT = false;
|
||||||
|
// Left Control
|
||||||
|
else if (new_scan_code == 0x1D) keyb_LCTRL = true;
|
||||||
|
else if (new_scan_code == 0x1D+0x80) keyb_LCTRL = false;
|
||||||
|
|
||||||
|
else if (new_scan_code < 0x80) keyboard[new_scan_code] = true;
|
||||||
|
else keyboard[new_scan_code - 0x80] = false;
|
||||||
|
|
||||||
|
if (new_scan_code == 0x45) {
|
||||||
|
keyb_NUMLOCK = 1-keyb_NUMLOCK;
|
||||||
|
KeyboardLED((keyb_NUMLOCK*2) | (keyb_SCROLLLOCK*1) | (keyb_CAPSLOCK*4));
|
||||||
|
}
|
||||||
|
if (new_scan_code == 0x46) {
|
||||||
|
keyb_SCROLLLOCK = 1-keyb_SCROLLLOCK;
|
||||||
|
KeyboardLED((keyb_NUMLOCK*2) | (keyb_SCROLLLOCK*1) | (keyb_CAPSLOCK*4));
|
||||||
|
}
|
||||||
|
if (new_scan_code == 0x3A) {
|
||||||
|
keyb_CAPSLOCK = 1-keyb_CAPSLOCK;
|
||||||
|
KeyboardLED((keyb_NUMLOCK*2) | (keyb_SCROLLLOCK*1) | (keyb_CAPSLOCK*4));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prev = new_scan_code;
|
||||||
|
|
||||||
|
return scancode_to_ASCII(new_scan_code, keyb_RSHIFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
ENTRY (loader)
|
||||||
|
|
||||||
|
SECTIONS {
|
||||||
|
. = 0x00100000;
|
||||||
|
|
||||||
|
.text :{
|
||||||
|
*(.text)
|
||||||
|
}
|
||||||
|
|
||||||
|
.rodata ALIGN (0x1000) : {
|
||||||
|
*(.rodata)
|
||||||
|
}
|
||||||
|
|
||||||
|
.data ALIGN (0x1000) : {
|
||||||
|
start_ctors = .;
|
||||||
|
*(.ctor*)
|
||||||
|
end_ctors = .;
|
||||||
|
start_dtors = .;
|
||||||
|
*(.dtor*)
|
||||||
|
end_dtors = .;
|
||||||
|
*(.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
.bss : {
|
||||||
|
sbss = .;
|
||||||
|
*(COMMON)
|
||||||
|
*(.bss)
|
||||||
|
ebss = .;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
global loader
|
||||||
|
global number
|
||||||
|
extern _main
|
||||||
|
extern start_ctors, end_ctors, start_dtors, end_dtors
|
||||||
|
|
||||||
|
MODULEALIGN equ 1<<0
|
||||||
|
MEMINFO equ 1<<1
|
||||||
|
FLAGS equ MODULEALIGN | MEMINFO
|
||||||
|
MAGIC equ 0x1BADB002
|
||||||
|
CHECKSUM equ -(MAGIC+FLAGS)
|
||||||
|
|
||||||
|
section .text
|
||||||
|
align 4
|
||||||
|
MultiBootHeader:
|
||||||
|
dd MAGIC
|
||||||
|
dd FLAGS
|
||||||
|
dd CHECKSUM
|
||||||
|
|
||||||
|
STACKSIZE equ 0x4000
|
||||||
|
|
||||||
|
; Loader
|
||||||
|
loader:
|
||||||
|
mov esp, stack+STACKSIZE
|
||||||
|
push eax
|
||||||
|
push ebx
|
||||||
|
|
||||||
|
static_ctors_loop:
|
||||||
|
mov ebx, start_ctors
|
||||||
|
jmp .test
|
||||||
|
.body:
|
||||||
|
call [ebx]
|
||||||
|
add ebx, 4
|
||||||
|
.test:
|
||||||
|
cmp ebx, end_ctors
|
||||||
|
jb .body
|
||||||
|
|
||||||
|
call _main
|
||||||
|
|
||||||
|
static_dtors_loop:
|
||||||
|
mov ebx, start_dtors
|
||||||
|
jmp .test
|
||||||
|
.body:
|
||||||
|
call [ebx]
|
||||||
|
add ebx, 4
|
||||||
|
.test:
|
||||||
|
cmp ebx, end_dtors
|
||||||
|
jb .body
|
||||||
|
|
||||||
|
hang:
|
||||||
|
hlt
|
||||||
|
jmp hang
|
||||||
|
|
||||||
|
; Number function, returns 12
|
||||||
|
number:
|
||||||
|
mov eax, 12
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
section .bss
|
||||||
|
align 4
|
||||||
|
stack:
|
||||||
|
resb STACKSIZE
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# This script can be used to quickly test MultiBoot-compliant
|
||||||
|
# kernels. The kernel filename is required to be kernel.bin.
|
||||||
|
# Also, this script requires the file 'stage1' and 'stage2'
|
||||||
|
# from GRUB to be in the current directory.
|
||||||
|
|
||||||
|
|
||||||
|
# config params here
|
||||||
|
image_size=$((4*1024*1024)) # 4 megabytes
|
||||||
|
qemu_cmdline="qemu -hda harddisk.img"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
stage1_size=`stat -c %s stage1` || echo "file 'stage1' required" # steal these from GRUB
|
||||||
|
stage2_size=`stat -c %s stage2` || echo "file 'stage2' required"
|
||||||
|
kernel_size=`stat -c %s kernel.bin` || echo "file 'kernel.bin' required"
|
||||||
|
|
||||||
|
kernel_begin_block=$(((stage1_size+stage2_size+511)/512))
|
||||||
|
|
||||||
|
padding_size=$((kernel_begin_block*512 - stage1_size - stage2_size))
|
||||||
|
padding2_size=$((image_size - kernel_begin_block*512 - kernel_size))
|
||||||
|
|
||||||
|
|
||||||
|
dd if=/dev/zero of=padding.tmp count=1 bs=$padding_size 2>/dev/null
|
||||||
|
dd if=/dev/zero of=padding2.tmp count=1 bs=$padding2_size 2>/dev/null
|
||||||
|
|
||||||
|
cat stage1 stage2 padding.tmp kernel.bin padding2.tmp > harddisk.img
|
||||||
|
|
||||||
|
rm padding.tmp padding2.tmp
|
||||||
|
|
||||||
|
|
||||||
|
( stty cbreak ; stty -echo ; python -c "`cat <<EOF
|
||||||
|
import sys, time
|
||||||
|
|
||||||
|
s="kernel ${kernel_begin_block}+$(((kernel_size+511) / 512))\nboot\n"
|
||||||
|
|
||||||
|
translate={
|
||||||
|
"\n": "ret",
|
||||||
|
"+": "kp_add",
|
||||||
|
" ": "spc"
|
||||||
|
}
|
||||||
|
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
try:
|
||||||
|
for c in s:
|
||||||
|
if c in translate:
|
||||||
|
c = translate[c]
|
||||||
|
sys.stdout.write("sendkey "+c+"\n")
|
||||||
|
sys.stdout.flush()
|
||||||
|
time.sleep(0.05)
|
||||||
|
except IOError:
|
||||||
|
pass
|
||||||
|
EOF`" ; cat ; ) | $qemu_cmdline -monitor stdio
|
||||||
|
|
||||||
|
stty echo
|
||||||
|
|
||||||
|
echo
|
||||||
@@ -0,0 +1,165 @@
|
|||||||
|
#ifndef __SYSTEM_H
|
||||||
|
#define __SYSTEM_H
|
||||||
|
|
||||||
|
// #define PIC1 0x20 /* IO base address for master PIC */
|
||||||
|
// #define PIC2 0xA0 /* IO base address for slave PIC */
|
||||||
|
// #define PIC1_COMMAND PIC1
|
||||||
|
// #define PIC1_DATA (PIC1+1)
|
||||||
|
// #define PIC2_COMMAND PIC2
|
||||||
|
// #define PIC2_DATA (PIC2+1)
|
||||||
|
#define NULL 0
|
||||||
|
#define true 1
|
||||||
|
#define false 0
|
||||||
|
#define inportb inb
|
||||||
|
#define outportb outb
|
||||||
|
|
||||||
|
extern "C" void _main (struct multiboot_data* mbd, unsigned int magic);
|
||||||
|
void ctamain();
|
||||||
|
void cout (const char string[]);
|
||||||
|
void cls();
|
||||||
|
void cDetectVideo();
|
||||||
|
char video_mode_colors;
|
||||||
|
|
||||||
|
typedef signed char int8_t;
|
||||||
|
typedef unsigned char uint8_t;
|
||||||
|
typedef signed int int16_t;
|
||||||
|
typedef unsigned int uint16_t;
|
||||||
|
typedef signed long int int32_t;
|
||||||
|
typedef unsigned long int uint32_t;
|
||||||
|
typedef signed long long int int64_t;
|
||||||
|
typedef unsigned long long int uint64_t;
|
||||||
|
typedef unsigned char byte;
|
||||||
|
typedef unsigned short word;
|
||||||
|
typedef unsigned int dword;
|
||||||
|
|
||||||
|
// Entrance point
|
||||||
|
void _main (struct multiboot_data* mdb, unsigned int magic)
|
||||||
|
{
|
||||||
|
if (magic != 0x2BADB002)
|
||||||
|
{
|
||||||
|
cout ("Magic error. System halted!");
|
||||||
|
}
|
||||||
|
|
||||||
|
char* boot_loader_name = (char*) ((long*)mdb)[16];
|
||||||
|
|
||||||
|
// Detect color/monochrome monitor and clear screen
|
||||||
|
cDetectVideo(); cls();
|
||||||
|
|
||||||
|
// Launch main function
|
||||||
|
ctamain();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// sends a byte (or word or dword) on a I/O location
|
||||||
|
static __inline__ void outb(unsigned short port, unsigned char val)
|
||||||
|
{
|
||||||
|
asm volatile("outb %0,%1"::"a"(val), "Nd" (port));
|
||||||
|
}
|
||||||
|
static __inline__ void outw(unsigned short port, unsigned short val)
|
||||||
|
{
|
||||||
|
asm volatile("outw %0,%1"::"a"(val), "Nd" (port));
|
||||||
|
}
|
||||||
|
static __inline__ void outd(unsigned short port, unsigned int val)
|
||||||
|
{
|
||||||
|
asm volatile("outd %0,%1"::"a"(val), "Nd" (port));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// receives a byte (or word or dword) from an I/O location
|
||||||
|
static __inline__ unsigned char inb(unsigned short port)
|
||||||
|
{
|
||||||
|
unsigned char ret;
|
||||||
|
asm volatile ("inb %1,%0":"=a"(ret):"Nd"(port));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
static __inline__ unsigned short inw(unsigned short port)
|
||||||
|
{
|
||||||
|
unsigned short ret;
|
||||||
|
asm volatile ("inw %1,%0":"=a"(ret):"Nd"(port));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
static __inline__ unsigned int ind(unsigned short port)
|
||||||
|
{
|
||||||
|
unsigned int ret;
|
||||||
|
asm volatile ("ind %1,%0":"=a"(ret):"Nd"(port));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forces the CPU to wait for an I/O operation to complete
|
||||||
|
static __inline__ void io_wait(void)
|
||||||
|
{
|
||||||
|
asm volatile("outb %%al, $0x80" : : "a"(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char *memcpy (unsigned char *dest, const unsigned char *src, int count)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
dest[i] = src[i];
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char *memset (unsigned char *dest, unsigned char val, int count)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
dest[i] = val;
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char *memsetw (unsigned char *dest, unsigned short val, int count)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
dest[i] = val;
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
int strlen (const char *str)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
for (ret = 0; str[ret] != NULL; ret++) {}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef unsigned char uchar;
|
||||||
|
typedef uchar byte;
|
||||||
|
|
||||||
|
|
||||||
|
/* keyboard interface IO port: data and control
|
||||||
|
READ: status port
|
||||||
|
WRITE: control register */
|
||||||
|
#define KBRD_INTRFC 0x64
|
||||||
|
|
||||||
|
/* keyboard interface bits */
|
||||||
|
#define KBRD_BIT_KDATA 0 /* keyboard data is in buffer (output buffer is empty) (bit 0) */
|
||||||
|
#define KBRD_BIT_UDATA 1 /* user data is in buffer (command buffer is empty) (bit 1) */
|
||||||
|
|
||||||
|
#define KBRD_IO 0x60 /* keyboard IO port */
|
||||||
|
#define KBRD_RESET 0xFE /* reset CPU command */
|
||||||
|
|
||||||
|
#define bit(n) (1<<(n)) /* Set bit n to 1 */
|
||||||
|
|
||||||
|
/* Check if bit n in flags is set */
|
||||||
|
#define check_flag(flags, n) ((flags) & bit(n))
|
||||||
|
|
||||||
|
void SystemReboot()
|
||||||
|
{
|
||||||
|
byte temp;
|
||||||
|
|
||||||
|
asm volatile ("CLI"); /* disable all interrupts */
|
||||||
|
|
||||||
|
/* Clear all keyboard buffers (output and command buffers) */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
temp = inb(KBRD_INTRFC); /* empty user data */
|
||||||
|
if (check_flag(temp, KBRD_BIT_KDATA) != 0)
|
||||||
|
inb(KBRD_IO); /* empty keyboard data */
|
||||||
|
} while (check_flag(temp, KBRD_BIT_UDATA) != 0);
|
||||||
|
|
||||||
|
outb(KBRD_INTRFC, KBRD_RESET); /* pulse CPU reset line */
|
||||||
|
asm volatile ("HLT"); /* if that didn't work, halt the CPU */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,26 @@
|
|||||||
|
<html>
|
||||||
|
<header><title> CTA 32bit Operating System guide </title></header>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
</style>
|
||||||
|
<style type="text/css">
|
||||||
|
</style>
|
||||||
|
<style type="text/css">
|
||||||
|
</style>
|
||||||
|
<style type="text/css">
|
||||||
|
</style>
|
||||||
|
<h1>
|
||||||
|
<span style="font-size: 72px;"><span style="color: rgb(51, 102, 204);">c</span><span style="color: rgb(255, 140, 0);">t</span><span style="color: rgb(102, 204, 51);">a</span><span style="color: rgb(169, 169, 169);"><sup>os</sup></span></span></h1>
|
||||||
|
|
||||||
|
<ul style="list-style-type: square;">
|
||||||
|
<span style="font-family:georgia,serif">
|
||||||
|
<li>
|
||||||
|
<span style="font-size: 14px;"><a href = "pages\bootload.html">CTA Bootloader </a></span></li>
|
||||||
|
<li>
|
||||||
|
<span style="font-size: 14px;"><a href = "pages\kernel.html">CTA Kernel </a></span></li>
|
||||||
|
</span>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
Filelist:
|
||||||
|
=========
|
||||||
|
|
||||||
|
clock/pictimer.c 76
|
||||||
|
clock/cmos.h 25
|
||||||
|
clock/time.c 143
|
||||||
|
|
||||||
|
include/console.h 153
|
||||||
|
include/system.h 111
|
||||||
|
|
||||||
|
kernel/gdt.c 78
|
||||||
|
kernel/idt.c 63
|
||||||
|
kernel/init.c 60
|
||||||
|
kernel/irq.c 126
|
||||||
|
kernel/isrs.c 164
|
||||||
|
kernel/memory.c 4
|
||||||
|
|
||||||
|
keyboard/keyus.c 293
|
||||||
|
keyboard/keyus.h 117
|
||||||
|
|
||||||
|
loader.asm 478
|
||||||
|
main.c 63
|
||||||
|
link.ld 25
|
||||||
|
compile.bat 23
|
||||||
|
|
||||||
|
Total lines of code:
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<a:clrMap xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" bg1="lt1" tx1="dk1" bg2="lt2" tx2="dk2" accent1="accent1" accent2="accent2" accent3="accent3" accent4="accent4" accent5="accent5" accent6="accent6" hlink="hlink" folHlink="folHlink"/>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<xml xmlns:o="urn:schemas-microsoft-com:office:office">
|
||||||
|
<o:MainFile HRef="../index.html"/>
|
||||||
|
<o:File HRef="item0006.xml"/>
|
||||||
|
<o:File HRef="props0007.xml"/>
|
||||||
|
<o:File HRef="themedata.thmx"/>
|
||||||
|
<o:File HRef="colorschememapping.xml"/>
|
||||||
|
<o:File HRef="filelist.xml"/>
|
||||||
|
</xml>
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
<b:Sources SelectedStyle="\APA.XSL" StyleName="APA" xmlns:b="http://schemas.openxmlformats.org/officeDocument/2006/bibliography" xmlns="http://schemas.openxmlformats.org/officeDocument/2006/bibliography"></b:Sources>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<ds:datastoreItem ds:itemID="{B6A49BB7-8D0F-4E82-BF18-360FF3A4C301}" xmlns:ds="http://schemas.openxmlformats.org/officeDocument/2006/customXml"><ds:schemaRefs><ds:schemaRef ds:uri="http://schemas.openxmlformats.org/officeDocument/2006/bibliography"/></ds:schemaRefs></ds:datastoreItem>
|
||||||
Binary file not shown.
@@ -0,0 +1,30 @@
|
|||||||
|
<html><head>
|
||||||
|
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title> CTA 32bit Operating System guide ## THE KERNEL</title></head><body><header></header>
|
||||||
|
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
</style>
|
||||||
|
<style type="text/css">
|
||||||
|
</style>
|
||||||
|
<style type="text/css">
|
||||||
|
</style>
|
||||||
|
<style type="text/css">
|
||||||
|
</style>
|
||||||
|
<h1>
|
||||||
|
<span style="font-size: 72px;"><span style="color: rgb(51, 102, 204);">c</span><span
|
||||||
|
style="color: rgb(255, 140, 0);">t</span><span style="color: rgb(102,
|
||||||
|
204, 51);">a</span><span style="color: rgb(169, 169, 169);"><sup>os</sup></span></span></h1>
|
||||||
|
|
||||||
|
<ul style="list-style-type: square;">
|
||||||
|
<span style="font-family: georgia,serif;">
|
||||||
|
<li>
|
||||||
|
<span style="font-size: 14px;"><a
|
||||||
|
href="file:///C:/ctaos/help/pages/pages/bootload.html">CTA Bootloader </a></span></li>
|
||||||
|
<li>
|
||||||
|
<span style="font-size: 14px;"><a
|
||||||
|
href="file:///C:/ctaos/help/pages/pages/kernel.html">CTA Kernel </a></span></li>
|
||||||
|
</span>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</body></html>
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
<html><head>
|
||||||
|
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title> CTA 32bit Operating System guide ## THE BOOTLOADER </title></head><body><header></header>
|
||||||
|
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
</style>
|
||||||
|
<style type="text/css">
|
||||||
|
</style>
|
||||||
|
<style type="text/css">
|
||||||
|
</style>
|
||||||
|
<style type="text/css">
|
||||||
|
</style>
|
||||||
|
<h1>
|
||||||
|
<span style="font-size: 72px;"><span style="color: rgb(51, 102, 204);">c</span><span
|
||||||
|
style="color: rgb(255, 140, 0);">t</span><span style="color: rgb(102,
|
||||||
|
204, 51);">a</span><span style="color: rgb(169, 169, 169);"><sup>os</sup></span></span></h1>
|
||||||
|
|
||||||
|
<ul style="list-style-type: square;">
|
||||||
|
<span style="font-family: georgia,serif;">
|
||||||
|
<li>
|
||||||
|
<span style="font-size: 14px;"><a
|
||||||
|
href="file:///C:/ctaos/help/pages/pages/bootload.html">CTA Bootloader </a></span></li>
|
||||||
|
<li>
|
||||||
|
<span style="font-size: 14px;"><a
|
||||||
|
href="file:///C:/ctaos/help/pages/pages/kernel.html">CTA Kernel </a></span></li>
|
||||||
|
</span>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</body></html>
|
||||||
Reference in new issue
Block a user