Move to GitHub for flexing

This commit is contained in:
Simponic 2021-03-01 15:17:24 -07:00
parent 09d1dcf3b1
commit c0c846cc15
16 changed files with 397 additions and 28 deletions

BIN
boot.o

Binary file not shown.

BIN
gdt.o

Binary file not shown.

View File

@ -14,4 +14,8 @@ struct GDT_ptr {
uint32_t base; uint32_t base;
} __attribute((packed)); } __attribute((packed));
uint8_t gdt_entries[8 * 3]; // (8 bytes per entry) * (num entries)
void encodeGDT(uint8_t* gdtEntry, struct GDT source);
void initializeGDT();
#endif //GDT_H #endif //GDT_H

56
include/idt.h Normal file
View File

@ -0,0 +1,56 @@
#ifndef IDT_H
#define IDT_H
#include "types.h"
struct IDT {
uint32_t base;
uint16_t selector;
uint8_t flags;
} __attribute__((packed));
struct IDT_ptr {
uint16_t limit;
uint32_t base;
} __attribute__((packed));
uint8_t idt_entries[8 * 256]; // 8 bytes per entry * 256 entries
struct IDT createIDT(uint32_t base, uint16_t selector, uint8_t flags);
void encodeIDT(uint8_t* idtEntry, struct IDT source);
void initializeIDT();
extern void isr0 ();
extern void isr1 ();
extern void isr2 ();
extern void isr3 ();
extern void isr4 ();
extern void isr5 ();
extern void isr6 ();
extern void isr7 ();
extern void isr8 ();
extern void isr9 ();
extern void isr10();
extern void isr11();
extern void isr12();
extern void isr13();
extern void isr14();
extern void isr15();
extern void isr16();
extern void isr17();
extern void isr18();
extern void isr19();
extern void isr20();
extern void isr21();
extern void isr22();
extern void isr23();
extern void isr24();
extern void isr25();
extern void isr26();
extern void isr27();
extern void isr28();
extern void isr29();
extern void isr30();
extern void isr31();
#endif // IDT_H

13
include/isr.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef ISR_H
#define ISR_H
#include "types.h"
struct registers{
uint32_t ds;
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;
uint32_t int_no, err_code;
uint32_t eip, cs, eflags, useresp, ss;
} __attribute__((packed));
#endif // ISR_H

11
include/port.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef PORT_H
#define PORT_H
#include "types.h"
uint8_t port_byte_in (uint8_t port);
void port_byte_out(uint8_t port, uint8_t data);
uint16_t port_word_in (uint16_t port);
void port_word_out(uint16_t port, uint16_t data);
#endif // PORT_H

View File

@ -11,9 +11,14 @@ typedef struct TextOutput {
uint16_t* vid_mem; uint16_t* vid_mem;
}__attribute__((packed)) TextOutput; }__attribute__((packed)) TextOutput;
TextOutput monitor;
TextOutput createOutput(const int max_row, const int max_column, uint16_t* vid_mem); TextOutput createOutput(const int max_row, const int max_column, uint16_t* vid_mem);
void scrollText(TextOutput* textOutput); void scrollText(TextOutput* textOutput);
void putChar(uint8_t character, uint8_t background, uint8_t foreground, TextOutput* textOutput); void putChar(uint8_t character, uint8_t background, uint8_t foreground, TextOutput* textOutput);
void print(char* string, uint8_t background, uint8_t foreground, TextOutput* textOutput); void print(char* string, uint8_t background, uint8_t foreground, TextOutput* textOutput);
char* itoa(int value, char* buffer, int base);
void printToMonitor(char* string);
void printIntToMonitor(int num, int base);
#endif // PRINT_H #endif // PRINT_H

View File

@ -3,7 +3,7 @@ CXX = i386-elf-gcc
CFLAGS = -std=gnu99 -ffreestanding -O2 -Wall -Wextra -nostdlib -Iinclude CFLAGS = -std=gnu99 -ffreestanding -O2 -Wall -Wextra -nostdlib -Iinclude
ASM = nasm ASM = nasm
OBJECTS = gdt.o boot.o print.o kernel.o OBJECTS = boot.o gdt.o isr.o idt.o port.o print.o kernel.o
%.o : src/%.c %.o : src/%.c
$(CXX) $(CFLAGS) -o $@ -c $< $(CXX) $(CFLAGS) -o $@ -c $<

BIN
print.o

Binary file not shown.

View File

@ -38,19 +38,100 @@ stack_top:
; Declare _start as a function symbol with the given symbol size. ; Declare _start as a function symbol with the given symbol size.
section .text section .text
global _gdt_flush ; Allows the C code to link to this global reloadSegments ; Flush GDT
extern _gp ; Says that '_gp' is in another file reloadSegments:
_gdt_flush: ; Reload CS register containing code selector:
lgdt [_gp] ; Load the GDT with our '_gp' which is a special pointer JMP 0x08:reload_CS ; 0x08 points at the new code selector
mov ax, 0x10 ; 0x10 is the offset in the GDT to our data segment reload_CS:
; Reload data segment registers:
MOV AX, 0x10 ; 0x10 points at the new data selector
MOV DS, AX
MOV ES, AX
MOV FS, AX
MOV GS, AX
MOV SS, AX
RET
%macro ISR_NOERRCODE 1 ; define a macro, taking one parameter
[GLOBAL isr%1] ; %1 accesses the first parameter.
isr%1:
cli
push byte 0
push byte %1
jmp isr_common_stub
%endmacro
%macro ISR_ERRCODE 1
[GLOBAL isr%1]
isr%1:
cli
push byte %1
jmp isr_common_stub
%endmacro
ISR_NOERRCODE 0
ISR_NOERRCODE 1
ISR_NOERRCODE 2
ISR_NOERRCODE 3
ISR_NOERRCODE 4
ISR_NOERRCODE 5
ISR_NOERRCODE 6
ISR_NOERRCODE 7
ISR_NOERRCODE 8
ISR_NOERRCODE 9
ISR_NOERRCODE 10
ISR_NOERRCODE 11
ISR_NOERRCODE 12
ISR_NOERRCODE 13
ISR_NOERRCODE 14
ISR_NOERRCODE 15
ISR_NOERRCODE 16
ISR_NOERRCODE 17
ISR_NOERRCODE 18
ISR_NOERRCODE 19
ISR_NOERRCODE 20
ISR_NOERRCODE 21
ISR_NOERRCODE 22
ISR_NOERRCODE 23
ISR_NOERRCODE 24
ISR_NOERRCODE 25
ISR_NOERRCODE 26
ISR_NOERRCODE 27
ISR_NOERRCODE 28
ISR_NOERRCODE 29
ISR_NOERRCODE 30
ISR_NOERRCODE 31
[EXTERN isr_handler]
; This is our common ISR stub. It saves the processor state, sets
; up for kernel mode segments, calls the C-level fault handler,
; and finally restores the stack frame.
isr_common_stub:
pusha ; Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax
mov ax, ds ; Lower 16-bits of eax = ds.
push eax ; save the data segment descriptor
mov ax, 0x10 ; load the kernel data segment descriptor
mov ds, ax mov ds, ax
mov es, ax mov es, ax
mov fs, ax mov fs, ax
mov gs, ax mov gs, ax
mov ss, ax
jmp 0x08:flush2 ; 0x08 is the offset to our code segment: Far jump! call isr_handler
flush2:
ret ; Returns back to the C code! pop eax ; reload the original data segment descriptor
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
popa ; Pops edi,esi,ebp...
add esp, 8 ; Cleans up the pushed error code and pushed ISR number
sti
iret ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP
global _start:function (_start.end - _start) global _start:function (_start.end - _start)
_start: _start:
@ -70,6 +151,7 @@ _start:
; in assembly as languages such as C cannot function without a stack. ; in assembly as languages such as C cannot function without a stack.
mov esp, stack_top mov esp, stack_top
; This is a good place to initialize crucial processor state before the ; This is a good place to initialize crucial processor state before the
; high-level kernel is entered. It's best to minimize the early ; high-level kernel is entered. It's best to minimize the early
; environment where crucial features are offline. Note that the ; environment where crucial features are offline. Note that the

View File

@ -1,5 +1,7 @@
#include "gdt.h" #include "gdt.h"
extern void reloadSegments();
void encodeGDT(uint8_t* gdtEntry, struct GDT source) { void encodeGDT(uint8_t* gdtEntry, struct GDT source) {
if ((source.limit > 65536) && ((source.limit & 0xFFF) == 0xFFF)) { if ((source.limit > 65536) && ((source.limit & 0xFFF) == 0xFFF)) {
// Set the GDT to use paging // Set the GDT to use paging
@ -34,3 +36,32 @@ void encodeGDT(uint8_t* gdtEntry, struct GDT source) {
// where most of the ideas for this function are taken from shamelessly // where most of the ideas for this function are taken from shamelessly
gdtEntry[5] = source.type; gdtEntry[5] = source.type;
} }
void initializeGDT() {
struct GDT nullEntry;
nullEntry.limit = 0;
nullEntry.base = 0;
nullEntry.type = 0;
struct GDT codeSection;
codeSection.limit = 0xFFFFFFFF;
codeSection.base = 0;
codeSection.type = 0x9A;
struct GDT dataSection;
dataSection.limit = 0xFFFFFFFF;
dataSection.base = 0;
dataSection.type = 0x92;
encodeGDT(gdt_entries , nullEntry );
encodeGDT(gdt_entries + 8 , codeSection);
encodeGDT(gdt_entries + 16, dataSection);
struct GDT_ptr gdt_ptr;
gdt_ptr.limit = 8*3;
gdt_ptr.base = (uint32_t)(&gdt_entries);
asm("lgdt (%0)" : :"r" ((uint8_t*)(&gdt_ptr)));
reloadSegments();
}

67
src/idt.c Normal file
View File

@ -0,0 +1,67 @@
#include "idt.h"
struct IDT createIDT(uint32_t base, uint16_t selector, uint8_t flags) {
struct IDT result;
result.base = base;
result.selector = selector;
result.flags = flags;
return result;
}
void encodeIDT(uint8_t* idtEntry, struct IDT source) {
// Low base bytes
idtEntry[0] = source.base & 0xFF;
idtEntry[1] = (source.base >> 8) & 0xFF;
// Selector bytes
idtEntry[2] = source.selector & 0xFF;
idtEntry[3] = (source.selector >> 8) & 0xFF;
idtEntry[4] = 0; // Null byte
idtEntry[5] = source.flags; // Flag bytes
// High base bytes
idtEntry[6] = (source.base >> 16) & 0xFF;
idtEntry[7] = (source.base >> 24) & 0xFF;
}
void initializeIDT() {
struct IDT_ptr idt_ptr;
idt_ptr.limit = 8*256 - 1;
idt_ptr.base = (uint32_t)&idt_entries;
for (int i = 0; i < 256*8; i++)
idt_entries[i] = 0; // Just to be safe, set IDT to all 0
encodeIDT(&idt_entries[0] , createIDT((uint32_t)isr0 , 0x08, 0x8E));
encodeIDT(&idt_entries[1*8 - 1] , createIDT((uint32_t)isr1 , 0x08, 0x8E));
encodeIDT(&idt_entries[2*8 - 1] , createIDT((uint32_t)isr2 , 0x08, 0x8E));
encodeIDT(&idt_entries[3*8 - 1] , createIDT((uint32_t)isr3 , 0x08, 0x8E));
encodeIDT(&idt_entries[4*8 - 1] , createIDT((uint32_t)isr4 , 0x08, 0x8E));
encodeIDT(&idt_entries[5*8 - 1] , createIDT((uint32_t)isr5 , 0x08, 0x8E));
encodeIDT(&idt_entries[6*8 - 1] , createIDT((uint32_t)isr6 , 0x08, 0x8E));
encodeIDT(&idt_entries[7*8 - 1] , createIDT((uint32_t)isr7 , 0x08, 0x8E));
encodeIDT(&idt_entries[8*8 - 1] , createIDT((uint32_t)isr8 , 0x08, 0x8E));
encodeIDT(&idt_entries[9*8 - 1] , createIDT((uint32_t)isr9 , 0x08, 0x8E));
encodeIDT(&idt_entries[10*8 - 1], createIDT((uint32_t)isr10, 0x08, 0x8E));
encodeIDT(&idt_entries[11*8 - 1], createIDT((uint32_t)isr11, 0x08, 0x8E));
encodeIDT(&idt_entries[12*8 - 1], createIDT((uint32_t)isr12, 0x08, 0x8E));
encodeIDT(&idt_entries[13*8 - 1], createIDT((uint32_t)isr13, 0x08, 0x8E));
encodeIDT(&idt_entries[14*8 - 1], createIDT((uint32_t)isr14, 0x08, 0x8E));
encodeIDT(&idt_entries[15*8 - 1], createIDT((uint32_t)isr15, 0x08, 0x8E));
encodeIDT(&idt_entries[16*8 - 1], createIDT((uint32_t)isr16, 0x08, 0x8E));
encodeIDT(&idt_entries[17*8 - 1], createIDT((uint32_t)isr17, 0x08, 0x8E));
encodeIDT(&idt_entries[18*8 - 1], createIDT((uint32_t)isr18, 0x08, 0x8E));
encodeIDT(&idt_entries[19*8 - 1], createIDT((uint32_t)isr19, 0x08, 0x8E));
encodeIDT(&idt_entries[20*8 - 1], createIDT((uint32_t)isr20, 0x08, 0x8E));
encodeIDT(&idt_entries[21*8 - 1], createIDT((uint32_t)isr21, 0x08, 0x8E));
encodeIDT(&idt_entries[22*8 - 1], createIDT((uint32_t)isr22, 0x08, 0x8E));
encodeIDT(&idt_entries[23*8 - 1], createIDT((uint32_t)isr23, 0x08, 0x8E));
encodeIDT(&idt_entries[24*8 - 1], createIDT((uint32_t)isr24, 0x08, 0x8E));
encodeIDT(&idt_entries[25*8 - 1], createIDT((uint32_t)isr25, 0x08, 0x8E));
encodeIDT(&idt_entries[26*8 - 1], createIDT((uint32_t)isr26, 0x08, 0x8E));
encodeIDT(&idt_entries[27*8 - 1], createIDT((uint32_t)isr27, 0x08, 0x8E));
encodeIDT(&idt_entries[28*8 - 1], createIDT((uint32_t)isr28, 0x08, 0x8E));
encodeIDT(&idt_entries[29*8 - 1], createIDT((uint32_t)isr29, 0x08, 0x8E));
encodeIDT(&idt_entries[30*8 - 1], createIDT((uint32_t)isr30, 0x08, 0x8E));
encodeIDT(&idt_entries[31*8 - 1], createIDT((uint32_t)isr31, 0x08, 0x8E));
asm("lidt (%0)" : :"r" ((uint8_t*)(&idt_ptr)));
}

8
src/isr.c Normal file
View File

@ -0,0 +1,8 @@
#include "isr.h"
#include "print.h"
void isr_handler(struct registers regs) {
printToMonitor("recieved interrupt: \n");
printIntToMonitor(regs.int_no, 10);
printToMonitor("\n");
}

View File

@ -1,22 +1,21 @@
#include "gdt.h" #include "gdt.h"
#include "idt.h"
#include "isr.h"
#include "types.h" #include "types.h"
#include "print.h" #include "print.h"
#include "port.h"
// inline function to swap two numbers
#define FOREGROUND 0x0 #define FOREGROUND 0x0
#define BACKGROUND 0xF #define BACKGROUND 0xF
void PrintWithScreenFill(char* string, TextOutput* output_stream) {
// Print a string and fill the screen
print(string, BACKGROUND, FOREGROUND, output_stream);
int row = output_stream->terminal_row;
while (output_stream->terminal_row < output_stream->max_row) {
putChar('\n', BACKGROUND, FOREGROUND, output_stream);
}
output_stream->terminal_row = row;
}
void kernel_main(void) { void kernel_main(void) {
TextOutput output_stream = createOutput(25,80,(uint16_t*)0xB8000); initializeGDT();
PrintWithScreenFill("Hello, Logan World!\n", &output_stream); initializeIDT();
printToMonitor("Hello\n");
printIntToMonitor(10, 10);
asm ("int $0x3");
asm ("int $0x4");
} }

21
src/port.c Normal file
View File

@ -0,0 +1,21 @@
#include "port.h"
uint8_t port_byte_in (uint8_t port) {
uint8_t result;
__asm__("in %%dx, %%al" : "=a" (result) : "d" (port));
return result;
}
void port_byte_out(uint8_t port, uint8_t data) {
__asm__("out %%al, %%dx" : :"a" (data), "d" (port));
}
uint16_t port_word_in (uint16_t port) {
uint16_t result;
__asm__("in %%dx, %%ax" : "=a" (result) : "d" (port));
return result;
}
void port_word_out (uint16_t port, uint16_t data) {
__asm__("out %%ax, %%dx" : :"a" (data), "d" (port));
}

View File

@ -1,5 +1,8 @@
#include "print.h" #include "print.h"
#define FOREGROUND 0x0
#define BACKGROUND 0xF
TextOutput createOutput(const int max_row, const int max_column, uint16_t* vid_mem) { TextOutput createOutput(const int max_row, const int max_column, uint16_t* vid_mem) {
// Create a new TextOutput interface // Create a new TextOutput interface
TextOutput output; TextOutput output;
@ -66,8 +69,77 @@ void putChar(uint8_t character, uint8_t background, uint8_t foreground,
void print(char* string, uint8_t background, uint8_t foreground, TextOutput* textOutput) { void print(char* string, uint8_t background, uint8_t foreground, TextOutput* textOutput) {
// Print a string // Print a string
for (string; *string; string++) { while (*string) {
putChar(*string, background, foreground, textOutput); putChar(*string, background, foreground, textOutput);
string++;
} }
} }
void PrintWithScreenFill(char* string, TextOutput* output_stream) {
// Print a string and fill the screen
print(string, BACKGROUND, FOREGROUND, output_stream);
int row = output_stream->terminal_row;
while (output_stream->terminal_row < output_stream->max_row) {
putChar('\n', BACKGROUND, FOREGROUND, output_stream);
}
output_stream->terminal_row = row;
}
inline void swap(char *x, char *y) {
char t = *x; *x = *y; *y = t;
}
int abs(int value) {
return (value < 0 ? -value : value);
}
// function to reverse buffer[i..j]
char* reverse(char *buffer, int i, int j)
{
while (i < j)
swap(&buffer[i++], &buffer[j--]);
return buffer;
}
// Iterative function to implement itoa() function in C
char* itoa(int value, char* buffer, int base)
{
if (base < 2 || base > 32)
return buffer;
int n = abs(value);
int i = 0;
while (n)
{
int r = n % base;
if (r >= 10)
buffer[i++] = 65 + (r - 10);
else
buffer[i++] = 48 + r;
n = n / base;
}
if (i == 0)
buffer[i++] = '0';
if (value < 0 && base == 10)
buffer[i++] = '-';
buffer[i] = '\0';
return reverse(buffer, 0, i - 1);
}
int haveFilledScreen = 0;
void printToMonitor(char* string) {
if (!haveFilledScreen) {
monitor = createOutput(25, 80, (uint16_t*)(0xB8000));
PrintWithScreenFill(string, &monitor);
haveFilledScreen = 1;
}
else
print(string, BACKGROUND, FOREGROUND, &monitor);
}
void printIntToMonitor(int num, int base) {
char* buffer;
printToMonitor(itoa(num, buffer, base));
}