[Stage1] Complete IDT implementation
[Stage1] Add IRQ remapping [Stage1] Handle IRQ0 gracefully [Stage1] Add error output functions
This commit is contained in:
parent
17a18e4f91
commit
dad4ff6a34
13 changed files with 261 additions and 89 deletions
|
|
@ -52,6 +52,11 @@ int main(int argc, char** argv) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (kernel == NULL) {
|
||||||
|
fprintf(stderr, "Failed to open kernel file\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
LFFileHandle image_handle = libhost_create_handle(image);
|
LFFileHandle image_handle = libhost_create_handle(image);
|
||||||
|
|
||||||
LFControlBlock fat;
|
LFControlBlock fat;
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,11 @@ os_bool libfat_write_fat_cluster(LFControlBlock* fat, os_u32 cluster_id, os_u32
|
||||||
fat->handle.seek(second_fat_cluster_offset, LIBFAT_SEEK_ORIGIN, fat->handle.user_data);
|
fat->handle.seek(second_fat_cluster_offset, LIBFAT_SEEK_ORIGIN, fat->handle.user_data);
|
||||||
fat->handle.write(sizeof(os_u32), (void*)&cluster_value, fat->handle.user_data);
|
fat->handle.write(sizeof(os_u32), (void*)&cluster_value, fat->handle.user_data);
|
||||||
|
|
||||||
|
if (fat->first_loaded_cluster <= cluster_id && (fat->first_loaded_cluster + fat->loaded_fat_cluster_amount) > cluster_id) {
|
||||||
|
os_u32 cluster_offset = cluster_id - fat->first_loaded_cluster;
|
||||||
|
fat->loaded_fat_segment[cluster_offset] = cluster_value;
|
||||||
|
}
|
||||||
|
|
||||||
return OS_TRUE;
|
return OS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -113,7 +118,7 @@ os_u32 libfat_write_cluster(LFControlBlock* fat, os_u32 cluster, void* buffer, o
|
||||||
os_u32 cluster_size = fat->header.base.bytes_per_sector * fat->header.base.sectors_per_cluster;
|
os_u32 cluster_size = fat->header.base.bytes_per_sector * fat->header.base.sectors_per_cluster;
|
||||||
os_u32 data_offset = (fat->header.base.reserved_sectors + (fat->header.sectors_per_fat_32 * fat->header.base.number_of_fats)) * fat->header.base.bytes_per_sector;
|
os_u32 data_offset = (fat->header.base.reserved_sectors + (fat->header.sectors_per_fat_32 * fat->header.base.number_of_fats)) * fat->header.base.bytes_per_sector;
|
||||||
|
|
||||||
if (offset_in_cluster + buffer_size >= cluster_size) {
|
if (offset_in_cluster + buffer_size > cluster_size) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -596,7 +601,7 @@ os_u32 libfat_write(LFFile* f, void* buffer, os_u32 buffer_size) {
|
||||||
f->in_cluster_position = 0;
|
f->in_cluster_position = 0;
|
||||||
os_u32 next = libfat_read_cluster(f->fat, f->current_cluster);
|
os_u32 next = libfat_read_cluster(f->fat, f->current_cluster);
|
||||||
if (next >= FAT_LAST_CLUSTER_32_2) {
|
if (next >= FAT_LAST_CLUSTER_32_2) {
|
||||||
next = libfat_add_cluster_to_chain(f->fat, next);
|
next = libfat_add_cluster_to_chain(f->fat, f->current_cluster);
|
||||||
}
|
}
|
||||||
f->current_cluster = next;
|
f->current_cluster = next;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
add_executable(stage1 stage1.c screen.c include/interrupts.h interrupts.c interrupt_utils.asm)
|
add_executable(stage1 stage1.c screen.c include/interrupts.h interrupts.c interrupt_utils.asm include/io.h io.asm include/pic_8259.h pic_8259.c)
|
||||||
target_compile_options(stage1 PUBLIC "$<$<COMPILE_LANGUAGE:C>:-ffreestanding>")
|
target_compile_options(stage1 PUBLIC "$<$<COMPILE_LANGUAGE:C>:-ffreestanding>")
|
||||||
set_target_properties(stage1 PROPERTIES LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld)
|
set_target_properties(stage1 PROPERTIES LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld)
|
||||||
target_link_options(stage1 PRIVATE -T${CMAKE_CURRENT_SOURCE_DIR}/linker.ld)
|
target_link_options(stage1 PRIVATE -T${CMAKE_CURRENT_SOURCE_DIR}/linker.ld)
|
||||||
|
|
|
||||||
|
|
@ -1,43 +1,9 @@
|
||||||
#ifndef OS3_INTERRUPTS_H
|
#ifndef OS3_INTERRUPTS_H
|
||||||
#define OS3_INTERRUPTS_H
|
#define OS3_INTERRUPTS_H
|
||||||
|
|
||||||
#include "datatypes.h"
|
extern void setup_interrupts();
|
||||||
#include "packing.h"
|
|
||||||
#include "screen.h"
|
|
||||||
|
|
||||||
OS_PACK_START
|
// Defined in interrupt_utils.asm
|
||||||
typedef struct __idt_attributes {
|
extern void enable_interrupts();
|
||||||
os_u8 gate_type: 4;
|
|
||||||
os_u8 empty : 1;
|
|
||||||
os_u8 dpl : 2;
|
|
||||||
os_u8 present: 1;
|
|
||||||
} OS_PACK_MID idt_attributes;
|
|
||||||
OS_PACK_END
|
|
||||||
|
|
||||||
#define IDT_GATE_TYPE_TASK 0x5
|
|
||||||
#define IDT_GATE_TYPE_INTERRUPT_16 0x6
|
|
||||||
#define IDT_GATE_TYPE_TRAP_16 0x7
|
|
||||||
#define IDT_GATE_TYPE_INTERRUPT_32 0xE
|
|
||||||
#define IDT_GATE_TYPE_TRAP_32 0xF
|
|
||||||
|
|
||||||
OS_PACK_START
|
|
||||||
typedef struct __idt_entry {
|
|
||||||
os_u16 isr_low;
|
|
||||||
os_u16 kernel_gdt_code_segment;
|
|
||||||
os_u8 reserved;
|
|
||||||
//idt_attributes attributes;
|
|
||||||
os_u8 attributes;
|
|
||||||
os_u16 isr_high;
|
|
||||||
} OS_PACK_MID idt_entry;
|
|
||||||
OS_PACK_END
|
|
||||||
|
|
||||||
OS_PACK_START
|
|
||||||
typedef struct __idt_ptr {
|
|
||||||
os_u16 limit;
|
|
||||||
os_u32 base;
|
|
||||||
} OS_PACK_MID idt_ptr;
|
|
||||||
OS_PACK_END
|
|
||||||
|
|
||||||
extern void fill_idt();
|
|
||||||
|
|
||||||
#endif //OS3_INTERRUPTS_H
|
#endif //OS3_INTERRUPTS_H
|
||||||
|
|
|
||||||
18
stage1/include/io.h
Normal file
18
stage1/include/io.h
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
//
|
||||||
|
// Created by John Stefanelli on 18/01/23.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OS3_IO_H
|
||||||
|
#define OS3_IO_H
|
||||||
|
|
||||||
|
#include "datatypes.h"
|
||||||
|
|
||||||
|
extern void outb(os_u16 port, os_u8 data);
|
||||||
|
extern void outw(os_u16 port, os_u16 data);
|
||||||
|
extern void outd(os_u16 port, os_u32 data);
|
||||||
|
|
||||||
|
extern os_u8 inb(os_u16 port);
|
||||||
|
extern os_u16 inw(os_u16 port);
|
||||||
|
extern os_u32 ind(os_u16 port);
|
||||||
|
|
||||||
|
#endif //OS3_IO_H
|
||||||
13
stage1/include/pic_8259.h
Normal file
13
stage1/include/pic_8259.h
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
//
|
||||||
|
// Created by John Stefanelli on 18/01/23.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OS3_PIC_8259_H
|
||||||
|
#define OS3_PIC_8259_H
|
||||||
|
|
||||||
|
#include "datatypes.h"
|
||||||
|
|
||||||
|
extern void pic_sendEOI(os_u8 irq);
|
||||||
|
extern void setup_pic();
|
||||||
|
|
||||||
|
#endif //OS3_PIC_8259_H
|
||||||
|
|
@ -3,8 +3,11 @@
|
||||||
|
|
||||||
#include "datatypes.h"
|
#include "datatypes.h"
|
||||||
|
|
||||||
extern void write_string(const char*, int);
|
extern void screen_write_string(const char* str, int length);
|
||||||
extern void clear_screen();
|
extern void screen_write_error(const char* str, int length);
|
||||||
extern void write_number(os_u32 number);
|
extern void screen_clear();
|
||||||
|
extern void screen_write_number(os_u32 number);
|
||||||
|
extern void screen_write_number_error(os_u32 number);
|
||||||
|
extern void screen_set_pos(int x, int y);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -1,10 +1,14 @@
|
||||||
; list of 256 void* to call when the corresponding interrupt is received
|
; list of 256 void* to call when the corresponding interrupt is received
|
||||||
extern interrupt_service_list, generic_exception
|
extern interrupt_service_list
|
||||||
|
; IDTR structure
|
||||||
|
extern main_idt_ptr
|
||||||
|
|
||||||
%macro interrupt_service_routine 1
|
%macro interrupt_service_routine 1
|
||||||
isr_stub_%+%1:
|
isr_stub_%+%1:
|
||||||
;CALL interrupt_service_list + (%1*4)
|
MOV EAX, i ; load interrupt number
|
||||||
CALL generic_exception
|
PUSH EAX ; push parameter "interrupt number"
|
||||||
|
CALL [interrupt_service_list + (%1*4)] ; call interrupt subroutine
|
||||||
|
ADD ESP, 4 ; clear parameters
|
||||||
IRET
|
IRET
|
||||||
%endmacro
|
%endmacro
|
||||||
|
|
||||||
|
|
@ -24,11 +28,11 @@ interrupt_service_table:
|
||||||
%assign i i+1
|
%assign i i+1
|
||||||
%endrep
|
%endrep
|
||||||
|
|
||||||
; void load_idt(void* idt_ptr)
|
; void load_idt()
|
||||||
global load_idt
|
global load_idt
|
||||||
load_idt:
|
load_idt:
|
||||||
LIDT [ESP+4] ; load idt with SP+4
|
LIDT [main_idt_ptr] ; load idt with SP+4
|
||||||
RET ; return
|
RET ; return
|
||||||
|
|
||||||
; void enable_interrupts()
|
; void enable_interrupts()
|
||||||
global enable_interrupts
|
global enable_interrupts
|
||||||
|
|
|
||||||
|
|
@ -1,56 +1,91 @@
|
||||||
#include "include/interrupts.h"
|
#include "include/interrupts.h"
|
||||||
|
#include "datatypes.h"
|
||||||
|
#include "packing.h"
|
||||||
|
#include "include/screen.h"
|
||||||
|
#include "include/pic_8259.h"
|
||||||
|
|
||||||
#define EFFECTIVE_INTERRUPT_AMOUNT 32
|
OS_PACK_START
|
||||||
|
typedef struct __idt_attributes {
|
||||||
|
os_u8 gate_type: 4;
|
||||||
|
os_u8 empty : 1;
|
||||||
|
os_u8 dpl : 2;
|
||||||
|
os_u8 present: 1;
|
||||||
|
} OS_PACK_MID idt_attributes;
|
||||||
|
OS_PACK_END
|
||||||
|
|
||||||
|
#define IDT_GATE_TYPE_TASK 0x5
|
||||||
|
#define IDT_GATE_TYPE_INTERRUPT_16 0x6
|
||||||
|
#define IDT_GATE_TYPE_TRAP_16 0x7
|
||||||
|
#define IDT_GATE_TYPE_INTERRUPT_32 0xE
|
||||||
|
#define IDT_GATE_TYPE_TRAP_32 0xF
|
||||||
|
|
||||||
|
OS_PACK_START
|
||||||
|
typedef struct __idt_entry {
|
||||||
|
os_u16 isr_low;
|
||||||
|
os_u16 kernel_gdt_code_segment;
|
||||||
|
os_u8 reserved;
|
||||||
|
idt_attributes attributes;
|
||||||
|
//os_u8 attributes;
|
||||||
|
os_u16 isr_high;
|
||||||
|
} OS_PACK_MID idt_entry;
|
||||||
|
OS_PACK_END
|
||||||
|
|
||||||
|
OS_PACK_START
|
||||||
|
typedef struct __idt_ptr {
|
||||||
|
os_u16 limit;
|
||||||
|
os_u32 base;
|
||||||
|
} OS_PACK_MID idt_ptr;
|
||||||
|
OS_PACK_END
|
||||||
|
|
||||||
|
|
||||||
|
#define EFFECTIVE_INTERRUPT_AMOUNT 256
|
||||||
|
|
||||||
__attribute__((aligned(0x10)))
|
__attribute__((aligned(0x10)))
|
||||||
idt_entry main_idt[EFFECTIVE_INTERRUPT_AMOUNT];
|
idt_entry main_idt[EFFECTIVE_INTERRUPT_AMOUNT];
|
||||||
idt_ptr main_idt_ptr;
|
idt_ptr main_idt_ptr;
|
||||||
volatile void* interrupt_service_list[EFFECTIVE_INTERRUPT_AMOUNT];
|
volatile void* interrupt_service_list[EFFECTIVE_INTERRUPT_AMOUNT];
|
||||||
|
|
||||||
void generic_exception() {
|
void generic_exception(os_u32 interrupt_id) {
|
||||||
//clear_screen();
|
//screen_clear();
|
||||||
write_string("Exception received: ", 0);
|
screen_set_pos(0, 0);
|
||||||
write_number(0);
|
screen_write_error("Exception received: ", 0);
|
||||||
write_string("\n", 0);
|
screen_write_number_error(interrupt_id);
|
||||||
__asm__("cli; hlt;");
|
screen_write_string("\n", 0);
|
||||||
while(1) {
|
while(1) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handle_irq0(os_u32) {
|
||||||
|
pic_sendEOI(0);
|
||||||
|
}
|
||||||
|
|
||||||
/* The following is defined in interrupt_utils.asm */
|
/* The following is defined in interrupt_utils.asm */
|
||||||
extern void* interrupt_service_table[];
|
extern void* interrupt_service_table[];
|
||||||
extern void load_idt(void* idtr_ptr);
|
extern void load_idt();
|
||||||
extern void enable_interrupts();
|
|
||||||
/* --- */
|
/* --- */
|
||||||
|
|
||||||
void fill_idt() {
|
void setup_interrupts() {
|
||||||
|
|
||||||
main_idt_ptr.base = (os_u32) &main_idt[0];
|
main_idt_ptr.base = (os_u32) &main_idt[0];
|
||||||
main_idt_ptr.limit = ((os_u16) (sizeof(idt_entry) * EFFECTIVE_INTERRUPT_AMOUNT)) - 1;
|
main_idt_ptr.limit = ((os_u16) (sizeof(idt_entry) * EFFECTIVE_INTERRUPT_AMOUNT)) - 1;
|
||||||
os_u32 val = (os_u32) interrupt_service_table[0];
|
|
||||||
write_string("ISR address: ", 0);
|
|
||||||
write_number(val);
|
|
||||||
write_string("\n", 1);
|
|
||||||
for (int i = 0; i < EFFECTIVE_INTERRUPT_AMOUNT; i++) {
|
for (int i = 0; i < EFFECTIVE_INTERRUPT_AMOUNT; i++) {
|
||||||
|
|
||||||
//os_u32 val = (os_u32) interrupt_service_table[0];
|
os_u32 val = (os_u32) interrupt_service_table[i];
|
||||||
os_u32 val = (os_u32) &generic_exception;
|
//os_u32 val = (os_u32) &generic_exception;
|
||||||
main_idt[i].isr_low = (os_u16)(val & 0xFFFF);
|
main_idt[i].isr_low = (os_u16)(val & 0xFFFF);
|
||||||
main_idt[i].isr_high = (os_u16)(val >> 16);
|
main_idt[i].isr_high = (os_u16)(val >> 16);
|
||||||
main_idt[i].kernel_gdt_code_segment = 0x08;
|
main_idt[i].kernel_gdt_code_segment = 0x08;
|
||||||
main_idt[i].reserved = 0;
|
main_idt[i].reserved = 0;
|
||||||
/*
|
|
||||||
main_idt[i].attributes.present = 1;
|
main_idt[i].attributes.present = 1;
|
||||||
main_idt[i].attributes.gate_type = IDT_GATE_TYPE_INTERRUPT_32;
|
main_idt[i].attributes.gate_type = IDT_GATE_TYPE_INTERRUPT_32;
|
||||||
main_idt[i].attributes.empty = 0;
|
main_idt[i].attributes.empty = 0;
|
||||||
main_idt[i].attributes.dpl = i == 0x49 ? 3 : 0;
|
main_idt[i].attributes.dpl = i == 0x49 ? 3 : 0;
|
||||||
*/
|
|
||||||
main_idt[i].attributes = 0x8e;
|
|
||||||
|
|
||||||
interrupt_service_list[i] = (void*)&generic_exception;
|
interrupt_service_list[i] = (void*)&generic_exception;
|
||||||
}
|
}
|
||||||
|
interrupt_service_list[32] = (void*)&handle_irq0;
|
||||||
|
|
||||||
load_idt((void*)&main_idt_ptr);
|
load_idt();
|
||||||
enable_interrupts();
|
|
||||||
}
|
}
|
||||||
50
stage1/io.asm
Normal file
50
stage1/io.asm
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
|
||||||
|
section .text
|
||||||
|
|
||||||
|
; void outb(os_u16 port, os_u8 data);
|
||||||
|
global outb
|
||||||
|
outb:
|
||||||
|
MOV EDX, [ESP + 4] ; load parameter 'port'
|
||||||
|
MOV EAX, [ESP + 8] ; load parameter 'data'
|
||||||
|
OUT DX, AL ; output byte in AL to port in DX
|
||||||
|
RET ; return
|
||||||
|
|
||||||
|
; void outw(os_u16 port, os_u16 data)
|
||||||
|
global outw
|
||||||
|
outw:
|
||||||
|
MOV EDX, [ESP + 4] ; load parameter 'port'
|
||||||
|
MOV EAX, [ESP + 8] ; load parameter 'data'
|
||||||
|
OUT DX, AX ; output word in AX to port in DX
|
||||||
|
RET ; return
|
||||||
|
|
||||||
|
; void outd(os_u16 port, os_u32 data)
|
||||||
|
global outd
|
||||||
|
outd:
|
||||||
|
MOV EDX, [ESP + 4] ; load parameter 'port'
|
||||||
|
MOV EAX, [ESP + 8] ; load parameter 'data'
|
||||||
|
OUT DX, EAX ; output double word in EAX to port in DX
|
||||||
|
RET ; return
|
||||||
|
|
||||||
|
; os_u8 inb(os_u16 port)
|
||||||
|
global inb
|
||||||
|
inb:
|
||||||
|
MOV EDX, [ESP + 4] ; load parameter 'port'
|
||||||
|
XOR EAX, EAX ; reset EAX
|
||||||
|
IN AL, DX ; read byte from port 'DX'
|
||||||
|
RET ; return
|
||||||
|
|
||||||
|
; os_u16 inw(os_u16 port)
|
||||||
|
global inw
|
||||||
|
inw:
|
||||||
|
MOV EDX, [ESP + 4] ; load parameter 'port'
|
||||||
|
XOR EAX, EAX ; reset EAX
|
||||||
|
IN AX, DX ; read word from port 'DX'
|
||||||
|
RET ; return
|
||||||
|
|
||||||
|
; os_u32 ind(os_u16 port)
|
||||||
|
global ind
|
||||||
|
ind:
|
||||||
|
MOV EDX, [ESP + 4] ; load parameter 'port'
|
||||||
|
XOR EAX, EAX ; reset EAX
|
||||||
|
IN EAX, DX ; read double word from port 'DX'
|
||||||
|
RET ; return
|
||||||
50
stage1/pic_8259.c
Normal file
50
stage1/pic_8259.c
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
#include "include/pic_8259.h"
|
||||||
|
#include "include/io.h"
|
||||||
|
|
||||||
|
#define PIC0 0x20
|
||||||
|
#define PIC1 0xA0
|
||||||
|
#define PIC0_COMMAND (PIC0)
|
||||||
|
#define PIC0_DATA (PIC0 + 1)
|
||||||
|
#define PIC1_COMMAND (PIC1)
|
||||||
|
#define PIC1_DATA (PIC1 + 1)
|
||||||
|
|
||||||
|
#define PIC_EOI 0x20 //PIC end-of-interrupt command
|
||||||
|
|
||||||
|
#define ICW1_ICW4 0x01 /* ICW4 (not) needed */
|
||||||
|
#define ICW1_SINGLE 0x02 /* Single (cascade) mode */
|
||||||
|
#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */
|
||||||
|
#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */
|
||||||
|
#define ICW1_INIT 0x10 /* Initialization - required! */
|
||||||
|
|
||||||
|
#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */
|
||||||
|
#define ICW4_AUTO 0x02 /* Auto (normal) EOI */
|
||||||
|
#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */
|
||||||
|
#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */
|
||||||
|
#define ICW4_SFNM 0x10 /* Special fully nested (not) */
|
||||||
|
|
||||||
|
void pic_sendEOI(os_u8 irq) {
|
||||||
|
if (irq >= 8) {
|
||||||
|
outb(PIC1_COMMAND, PIC_EOI);
|
||||||
|
}
|
||||||
|
|
||||||
|
outb(PIC0_COMMAND, PIC_EOI);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup_pic() {
|
||||||
|
os_u8 a1, a2;
|
||||||
|
|
||||||
|
a1 = inb(PIC0_DATA); // save current interrupt masks
|
||||||
|
a2 = inb(PIC1_DATA);
|
||||||
|
|
||||||
|
outb(PIC0_COMMAND, ICW1_INIT | ICW1_ICW4); //Start init sequence in cascade mode
|
||||||
|
outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4);
|
||||||
|
outb(PIC0_DATA, 0x20); // 0x20: Offset of IRQ 0
|
||||||
|
outb(PIC1_DATA, 0x28); // 0x28: Offset of IRQ 8
|
||||||
|
outb(PIC0_DATA, 4); //Master PIC should handle cascade at IRQ 2
|
||||||
|
outb(PIC1_DATA, 2); //Salve PIC should handle cascade identity '2'
|
||||||
|
outb(PIC0_DATA, ICW4_8086); //Set master to 8086 mode
|
||||||
|
outb(PIC1_DATA, ICW4_8086); //Set slave to 8086 mode
|
||||||
|
|
||||||
|
outb(PIC0_DATA, a1); //restore interrupt masks
|
||||||
|
outb(PIC1_DATA, a2);
|
||||||
|
}
|
||||||
|
|
@ -1,18 +1,17 @@
|
||||||
#include "include/screen.h"
|
|
||||||
#include "../os3_common/datatypes.h"
|
#include "../os3_common/datatypes.h"
|
||||||
#include "../os3_common/packing.h"
|
#include "../os3_common/packing.h"
|
||||||
|
#include "include/screen.h"
|
||||||
|
|
||||||
int x = 0;
|
int x = 0;
|
||||||
int y = 0;
|
int y = 0;
|
||||||
|
|
||||||
void write_character(char c) {
|
void write_character(char c, os_u8 color) {
|
||||||
os_u16 color_byte = 0x0A;
|
|
||||||
os_u16* vram = (os_u16*) 0xB8000;
|
os_u16* vram = (os_u16*) 0xB8000;
|
||||||
os_u16* cursor_pos = vram + ((y * 80) + x);
|
os_u16* cursor_pos = vram + ((y * 80) + x);
|
||||||
*cursor_pos = c | (color_byte << 8);
|
*cursor_pos = c | (color << 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_string(const char* str, int max_len) {
|
void screen_write(const char* str, int max_len, os_u8 color) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
do {
|
do {
|
||||||
char c = *str;
|
char c = *str;
|
||||||
|
|
@ -22,7 +21,7 @@ void write_string(const char* str, int max_len) {
|
||||||
|
|
||||||
if (c == '\n') {
|
if (c == '\n') {
|
||||||
if (y == 24) {
|
if (y == 24) {
|
||||||
clear_screen();
|
screen_clear();
|
||||||
}
|
}
|
||||||
y = (y + 1) % 25;
|
y = (y + 1) % 25;
|
||||||
x = 0;
|
x = 0;
|
||||||
|
|
@ -30,11 +29,11 @@ void write_string(const char* str, int max_len) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
write_character(c);
|
write_character(c, color);
|
||||||
x++;
|
x++;
|
||||||
if (x >= 80) {
|
if (x >= 80) {
|
||||||
if (y == 24) {
|
if (y == 24) {
|
||||||
clear_screen();
|
screen_clear();
|
||||||
}
|
}
|
||||||
y = (y + 1) % 25;
|
y = (y + 1) % 25;
|
||||||
x = 0;
|
x = 0;
|
||||||
|
|
@ -44,7 +43,15 @@ void write_string(const char* str, int max_len) {
|
||||||
} while(i < max_len || max_len == 0);
|
} while(i < max_len || max_len == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear_screen() {
|
void screen_write_string(const char* str, int length) {
|
||||||
|
screen_write(str, length, 0x0A);
|
||||||
|
}
|
||||||
|
|
||||||
|
void screen_write_error(const char* str, int length) {
|
||||||
|
screen_write(str, length, 0x0C);
|
||||||
|
}
|
||||||
|
|
||||||
|
void screen_clear() {
|
||||||
os_u16* ptr = (os_u16*) 0xB8000;
|
os_u16* ptr = (os_u16*) 0xB8000;
|
||||||
for (int y = 0; y < 25; y++) {
|
for (int y = 0; y < 25; y++) {
|
||||||
for (int x = 0; x < 80; x++) {
|
for (int x = 0; x < 80; x++) {
|
||||||
|
|
@ -56,7 +63,7 @@ void clear_screen() {
|
||||||
y = 0;
|
y = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_number(os_u32 number) {
|
void screen_write_number_impl(os_u32 number, os_u8 color) {
|
||||||
char buffer[32];
|
char buffer[32];
|
||||||
char buffer_2[32];
|
char buffer_2[32];
|
||||||
|
|
||||||
|
|
@ -79,5 +86,18 @@ void write_number(os_u32 number) {
|
||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
|
|
||||||
write_string(buffer_2, 0);
|
screen_write(buffer_2, 0, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void screen_write_number(os_u32 number) {
|
||||||
|
screen_write_number_impl(number, 0x0A);
|
||||||
|
}
|
||||||
|
|
||||||
|
void screen_write_number_error(os_u32 number) {
|
||||||
|
screen_write_number_impl(number, 0x0C);
|
||||||
|
}
|
||||||
|
|
||||||
|
void screen_set_pos(int nx, int ny) {
|
||||||
|
x = nx;
|
||||||
|
y = ny;
|
||||||
}
|
}
|
||||||
|
|
@ -2,17 +2,20 @@
|
||||||
#include "../os3_common/packing.h"
|
#include "../os3_common/packing.h"
|
||||||
#include "include/screen.h"
|
#include "include/screen.h"
|
||||||
#include "include/interrupts.h"
|
#include "include/interrupts.h"
|
||||||
|
#include "include/pic_8259.h"
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
clear_screen();
|
screen_clear();
|
||||||
write_string("OS3 Booted into stage 1!\n", 0);
|
screen_write_string("OS3 Booted into stage 1!\n", 0);
|
||||||
write_string("Looking for stage 2....\n", 0);
|
screen_write_string("Looking for stage 2....\n", 0);
|
||||||
fill_idt();
|
setup_interrupts();
|
||||||
os_u32 i = 0;
|
|
||||||
|
setup_pic();
|
||||||
|
|
||||||
|
enable_interrupts();
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
write_number(i++);
|
}
|
||||||
write_string("\n", 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue