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;
} __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

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;
}__attribute__((packed)) TextOutput;
TextOutput monitor;
TextOutput createOutput(const int max_row, const int max_column, uint16_t* vid_mem);
void scrollText(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);
char* itoa(int value, char* buffer, int base);
void printToMonitor(char* string);
void printIntToMonitor(int num, int base);
#endif // PRINT_H

View File

@ -3,7 +3,7 @@ CXX = i386-elf-gcc
CFLAGS = -std=gnu99 -ffreestanding -O2 -Wall -Wextra -nostdlib -Iinclude
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
$(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.
section .text
global _gdt_flush ; Allows the C code to link to this
extern _gp ; Says that '_gp' is in another file
_gdt_flush:
lgdt [_gp] ; Load the GDT with our '_gp' which is a special pointer
mov ax, 0x10 ; 0x10 is the offset in the GDT to our data segment
global reloadSegments ; Flush GDT
reloadSegments:
; Reload CS register containing code selector:
JMP 0x08:reload_CS ; 0x08 points at the new code selector
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 es, ax
mov fs, ax
mov gs, ax
mov ss, ax
jmp 0x08:flush2 ; 0x08 is the offset to our code segment: Far jump!
flush2:
ret ; Returns back to the C code!
call isr_handler
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)
_start:
@ -70,6 +151,7 @@ _start:
; in assembly as languages such as C cannot function without a stack.
mov esp, stack_top
; This is a good place to initialize crucial processor state before the
; high-level kernel is entered. It's best to minimize the early
; environment where crucial features are offline. Note that the

View File

@ -1,5 +1,7 @@
#include "gdt.h"
extern void reloadSegments();
void encodeGDT(uint8_t* gdtEntry, struct GDT source) {
if ((source.limit > 65536) && ((source.limit & 0xFFF) == 0xFFF)) {
// 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
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 "idt.h"
#include "isr.h"
#include "types.h"
#include "print.h"
#include "port.h"
// inline function to swap two numbers
#define FOREGROUND 0x0
#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) {
TextOutput output_stream = createOutput(25,80,(uint16_t*)0xB8000);
PrintWithScreenFill("Hello, Logan World!\n", &output_stream);
initializeGDT();
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"
#define FOREGROUND 0x0
#define BACKGROUND 0xF
TextOutput createOutput(const int max_row, const int max_column, uint16_t* vid_mem) {
// Create a new TextOutput interface
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) {
// Print a string
for (string; *string; string++) {
while (*string) {
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));
}