Add files via upload

This commit is contained in:
OusmBlueNinja 2024-10-12 22:01:35 -05:00 committed by GitHub
commit e82fb49c04
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
66 changed files with 2792 additions and 0 deletions

51
EYOSx86-main/Makefile Normal file
View File

@ -0,0 +1,51 @@
# Define paths and files
IMAGE_SIZE_MB := 10
DISK_IMAGE := dist/x86_64/filesystem.img
KERNEL_BIN := dist/x86_64/kernel.bin
ISO_FILE := dist/x86_64/kernel.iso
ISO_DIR := targets/x86_64/iso
# List of object files
kernel_source_files := $(shell find src/impl/kernel -name *.c)
kernel_object_files := $(patsubst src/impl/kernel/%.c, build/kernel/%.o, $(kernel_source_files))
x86_64_c_source_files := $(shell find src/impl/x86_64 -name *.c)
x86_64_c_object_files := $(patsubst src/impl/x86_64/%.c, build/x86_64/%.o, $(x86_64_c_source_files))
x86_64_cpp_source_files := $(shell find src/impl/x86_64 -name *.cpp)
x86_64_cpp_object_files := $(patsubst src/impl/x86_64/%.cpp, build/x86_64/%.o, $(x86_64_cpp_source_files))
x86_64_asm_source_files := $(shell find src/impl/x86_64 -name *.asm)
x86_64_asm_object_files := $(patsubst src/impl/x86_64/%.asm, build/x86_64/%.o, $(x86_64_asm_source_files))
x86_64_object_files := $(x86_64_c_object_files) $(x86_64_cpp_object_files) $(x86_64_asm_object_files)
# Rule to compile C files for the kernel
$(kernel_object_files): build/kernel/%.o : src/impl/kernel/%.c
mkdir -p $(dir $@) && \
x86_64-elf-gcc -c -I src/intf -ffreestanding $(patsubst build/kernel/%.o, src/impl/kernel/%.c, $@) -o $@
# Rule to compile C files for x86_64
$(x86_64_c_object_files): build/x86_64/%.o : src/impl/x86_64/%.c
mkdir -p $(dir $@) && \
x86_64-elf-gcc -c -I src/intf -ffreestanding $(patsubst build/x86_64/%.o, src/impl/x86_64/%.c, $@) -o $@
# Rule to compile C++ files for x86_64
$(x86_64_cpp_object_files): build/x86_64/%.o : src/impl/x86_64/%.cpp
mkdir -p $(dir $@) && \
x86_64-elf-g++ -c -I src/intf -ffreestanding $(patsubst build/x86_64/%.o, src/impl/x86_64/%.cpp, $@) -o $@
# Rule to assemble ASM files for x86_64
$(x86_64_asm_object_files): build/x86_64/%.o : src/impl/x86_64/%.asm
mkdir -p $(dir $@) && \
nasm -f elf64 $(patsubst build/x86_64/%.o, src/impl/x86_64/%.asm, $@) -o $@
.PHONY: build-x86_64
build-x86_64: $(kernel_object_files) $(x86_64_object_files)
mkdir -p dist/x86_64 targets/x86_64/iso && \
x86_64-elf-ld -n -o $(KERNEL_BIN) -T targets/x86_64/linker.ld $(kernel_object_files) $(x86_64_object_files) && \
cp $(KERNEL_BIN) $(ISO_DIR)/boot/kernel.bin && \
dd if=/dev/zero of=$(DISK_IMAGE) bs=1M count=$(IMAGE_SIZE_MB) && \
mkfs.vfat -F 16 $(DISK_IMAGE) && \
mcopy -i $(DISK_IMAGE) filesystem/hello/hello.txt ::/ && \
grub-mkrescue -o $(ISO_FILE) $(ISO_DIR)

60
EYOSx86-main/README.md Normal file
View File

@ -0,0 +1,60 @@
# Write Your Own 64-bit Operating System Kernel From Scratch
This respository holds all the source code for [this YouTube tutorial series](https://www.youtube.com/playlist?list=PLZQftyCk7_SeZRitx5MjBKzTtvk0pHMtp).
You can find the revision for a specific episode on [this page](https://github.com/davidcallanan/yt-os-series/tags).
You can find pre-built ISO files for this kernel at [this repository](https://github.com/davidcallanan/os-series-isos).
Considering supporting this work via [my Patreon page](http://patreon.com/codepulse).
## Prerequisites
- A text editor such as [VS Code](https://code.visualstudio.com/).
- [Docker](https://www.docker.com/) for creating our build-environment.
- [Qemu](https://www.qemu.org/) for emulating our operating system.
- Remember to add Qemu to the path so that you can access it from your command-line. ([Windows instructions here](https://dev.to/whaleshark271/using-qemu-on-windows-10-home-edition-4062))
## Setup
Build an image for our build-environment:
- `docker build buildenv -t myos-buildenv`
## Build
Enter build environment:
- Linux or MacOS: `docker run --rm -it -v "$(pwd)":/root/env myos-buildenv`
- Windows (CMD): `docker run --rm -it -v "%cd%":/root/env myos-buildenv`
- Windows (PowerShell): `docker run --rm -it -v "${pwd}:/root/env" myos-buildenv`
- Please use the linux command if you are using `WSL`, `msys2` or `git bash`
- NOTE: If you are having trouble with an unshared drive, ensure your docker daemon has access to the drive you're development environment is in. For Docker Desktop, this is in "Settings > Shared Drives" or "Settings > Resources > File Sharing".
Build for x86 (other architectures may come in the future):
- `make build-x86_64`
- If you are using Qemu, please close it before running this command to prevent errors.
To leave the build environment, enter `exit`.
## Emulate
You can emulate your operating system using [Qemu](https://www.qemu.org/): (Don't forget to [add qemu to your path](https://dev.to/whaleshark271/using-qemu-on-windows-10-home-edition-4062#:~:text=2.-,Add%20Qemu%20path%20to%20environment%20variables%20settings,-Copy%20the%20Qemu)!)
- `qemu-system-x86_64 -cdrom dist/x86_64/kernel.iso`
- Note: Close the emulator when finished, so as to not block writing to `kernel.iso` for future builds.
If the above command fails, try one of the following:
- Windows: [`qemu-system-x86_64 -cdrom dist/x86_64/kernel.iso -L "C:\Program Files\qemu"`](https://stackoverflow.com/questions/66266448/qemu-could-not-load-pc-bios-bios-256k-bin)
- Linux: [`qemu-system-x86_64 -cdrom dist/x86_64/kernel.iso -L /usr/share/qemu/`](https://unix.stackexchange.com/questions/134893/cannot-start-kvm-vm-because-missing-bios)
- Alternatively, install a custom BIOS binary file and link it to Qemu using the `-L` option.
Alternatively, you should be able to load the operating system on a USB drive and boot into it when you turn on your computer. (I haven't actually tested this yet.)
## Cleanup
Remove the build-evironment image:
- `docker rmi myos-buildenv -f`

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,14 @@
FROM randomdude/gcc-cross-x86_64-elf
RUN apt-get update
RUN apt-get upgrade -y
RUN apt-get install -y nasm
RUN apt-get install -y xorriso
RUN apt-get install -y grub-pc-bin
RUN apt-get install -y grub-common
RUN apt-get install -y dosfstools
RUN apt-get install -y mtools
VOLUME /root/env
WORKDIR /root/env

BIN
EYOSx86-main/dist/x86_64/filesystem.img vendored Normal file

Binary file not shown.

BIN
EYOSx86-main/dist/x86_64/kernel.bin vendored Normal file

Binary file not shown.

BIN
EYOSx86-main/dist/x86_64/kernel.iso vendored Normal file

Binary file not shown.

View File

@ -0,0 +1 @@
Hello, World!

View File

@ -0,0 +1,288 @@
#include "print.h"
#include "keydriver.h"
#include "stdint.h"
#include "stdopt.h"
#include "strings.h"
#include "io.h"
#include "vga.h"
#include "idt.h"
#include "memory.h"
#include "window.h"
#include "fs.h"
#include "fat12.h"
#define COMMAND_BUFFER_SIZE 256 // Increase buffer size to handle longer commands
#define BACKSPACE_KEY 8
#define HISTORY_SIZE 10
#define COMMAND_BUFFER_SIZE 256
#define BUFFER_SIZE 4096
extern void kpanic(int error_code);
void shutdown_system() {
__asm__ (
"movl $1, %eax\n" // syscall number for sys_reboot (1 in this case)
"movl $0, %ebx\n" // reboot flags
"movl $0, %ecx\n" // no additional arguments
"movl $0, %edx\n" // no additional arguments
"int $0x80\n" // interrupt to invoke syscall
);
}
char commandHistory[HISTORY_SIZE][COMMAND_BUFFER_SIZE];
int currentHistoryIndex = 0;
int historyCount = 0;
void add_to_history(const char* command) {
if (historyCount < HISTORY_SIZE) {
historyCount++;
} else {
for (int i = 1; i < HISTORY_SIZE; i++) {
strcpy(commandHistory[i - 1], commandHistory[i]);
}
}
strcpy(commandHistory[historyCount - 1], command);
currentHistoryIndex = historyCount;
}
const char* get_previous_command() {
if (currentHistoryIndex > 0) {
currentHistoryIndex--;
return commandHistory[currentHistoryIndex];
}
return NULL;
}
const char* get_next_command() {
if (currentHistoryIndex < historyCount - 1) {
currentHistoryIndex++;
return commandHistory[currentHistoryIndex];
}
return NULL;
}
const void clear()
{
print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK); // Set text color
move_print_cursor(0, 0);
move_cursor(0, 0);
print_clear();
print_setup_prompt();
}
void halt(){
print_str("[ WARN ] HALT\n");
while (1) {}
}
void commandHandler(char* command) {
printf("\n");
if (strcmp(command, "cls") == 0) {
clear();
} else if (strcmp(command, "knp") == 0) {
kpanic(1);
} else if (int_strncmp(command, "echo ", 5) == 0) {
char* message = command + 5; // Skip the "echo " part
print_str("\n");
print_str(message);
print_str("\n");
} else if (int_strncmp(command, "cwin", 4) == 0) {
// Define window properties
Window myWindow;
int x = 8; // X position of the window
int y = 4; // Y position of the window
int width = 30; // Width of the window
int height = 10; // Height of the window
uint8_t borderColor = PRINT_COLOR_RED; // Border color
uint8_t backgroundColor = PRINT_COLOR_BLUE; // Background color
// Create and display the window
create_window(&myWindow, x, y, width, height, borderColor, backgroundColor, "Main Window");
// Print text inside the window
print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLUE); // Set text color
print_text_in_window(&myWindow, 2, 2, "Window Manager is a ");
print_text_in_window(&myWindow, 2, 3, "Work in progress, Sorry :("); // Print text inside the window
print_text_in_window(&myWindow, 2, 4, "do [ cls ] to clear"); // Print text inside the window
} else if (int_strncmp(command, "exit", 4) == 0) {
printf("Driver Call [ shutdown_system(); ] \n");
shutdown_system();
} else if (int_strncmp(command, "panic_test", 10) == 0) {
int _y = 1/0;
printf("Output %d\n", _y);
} else if (int_strncmp(command, "test", 4) == 0) {
//// Test custom malloc and free
//void* block1 = malloc(32);
//void* block2 = malloc(64);
//void* block3 = malloc(128);
//
//// List used blocks
//list_used_blocks();
//
//// Free a block and check again
//free(block2);
//printf("\nAfter freeing block2:\n");
//list_used_blocks();
//
//void* block4 = malloc(64);
//
//list_used_blocks();
create_game();
} else if (int_strncmp(command, "split", 5) == 0) {
printf("Kernel Call [ split_string(); ]\n");
// Check the length of the command string and use it properly
char** new_command = split_string(command, ",", strlen(command));
//char** new_command = {{NULL, NULL, NULL, NULL}};
if (new_command) {
// Add a loop to print all the elements in the new_command array for debugging
for (int i = 0; new_command[i] != NULL; i++) {
printf("new_command[%d]: %s\n", i, new_command[i]);
}
//halt(); // Debug halt
// Ensure that new_command[1] exists before accessing it
if (new_command[1] != NULL) {
printf("%s\n", new_command[1]);
} else {
printf("Error: new_command[1] is NULL\n");
}
} else {
printf("Error: split_string returned NULL\n");
}
} else {
printf("Unknown command: %s\n", command);
}
}
void print_setup_prompt() {
move_cursor(0, 0);
print_set_color(PRINT_COLOR_LIGHT_RED, PRINT_COLOR_BLACK);
print_str("-------------------- ");
print_set_color(PRINT_COLOR_GREEN, PRINT_COLOR_BLACK);
print_str("EYOS");
print_set_color(PRINT_COLOR_LIGHT_RED, PRINT_COLOR_BLACK);
print_str(" --------------------\n");
print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK);
print_str("V 1.5.01\n");
}
void kernel_main() {
init_keyboard_driver();
idt_install();
print_str("[ WARN ] Skipping File System Initialization...\n[ INFO ] Do [ fsinit ] to initalize the filesystem\n");
if (fat12_init() == 0) {
printf("Filesystem mounted\n");
fat12_read_root_directory();
fat12_dir_entry_t entry;
if (fat12_find_file("HELLOTXT", &entry)) {
printf("File found: HELLO.TXT\n");
}
}
print_setup_prompt();
print_str(" > ");
// Main loop
char key;
bool keydown = false;
char commandBuffer[COMMAND_BUFFER_SIZE];
size_t commandLength = 0; // To track the length of the current command
while (1) {
key = read_key();
if (key != 0) {
if (!keydown) {
CursorPosition pos = get_print_cursor_pos();
move_cursor(pos.x,pos.y);
if (key == 10) { // Enter key
commandBuffer[commandLength] = '\0'; // Null-terminate the command
commandHandler(commandBuffer);
// Reset command buffer for the next input
commandLength = 0;
print_str(" > ");
} else if (key == BACKSPACE_KEY) { // Backspace key
if (commandLength > 0) {
// Remove the last character from the buffer
commandLength--;
commandBuffer[commandLength] = '0'; // Null-terminate after removal
// Clear the character from the screen (overwrite with space)
// Move cursor back one position
offset_print_cursor(-1,0);
print_char(' '); // Overwrite the character
offset_print_cursor(-1,0); // Move cursor back one position(because its moved left one by the rpintf)
}
} else {
if (key >= 32 && key <= 126) { // Check if the key is a printable character
if (commandLength < COMMAND_BUFFER_SIZE - 1) {
commandBuffer[commandLength++] = key; // Append character to buffer
commandBuffer[commandLength] = '\0'; // Null-terminate the buffer
print_char(key); // Print key to the screen
}
}
}
keydown = true;
}
} else {
keydown = false;
}
// int x = 100/0;
}
kpanic(2);
}

View File

@ -0,0 +1,16 @@
section .multiboot_header
header_start:
; magic number
dd 0xe85250d6 ; multiboot2
; architecture
dd 0 ; protected mode i386
; header length
dd header_end - header_start
; checksum
dd 0x100000000 - (0xe85250d6 + 0 + (header_end - header_start))
; end tag
dw 0
dw 0
dd 8
header_end:

View File

@ -0,0 +1,139 @@
; isr.asm - ISR assembly stubs
global isr0, isr1, isr2, isr3, isr4, isr5, isr6, isr7, isr8, isr9, isr10, isr11, isr12, isr13, isr14, isr15
global isr16, isr17, isr18, isr19, isr20, isr21, isr22, isr23, isr24, isr25, isr26, isr27, isr28, isr29, isr30, isr31
extern isr_common_handler
section .text
; ISRs 0 to 13 (no error code pushed by CPU)
isr0:
cli
push 0 ; Push error code (none for isr0)
push 0 ; Push interrupt number
jmp isr_common_handler
isr1:
cli
push 0
push 1
jmp isr_common_handler
isr2:
cli
push 0
push 2
jmp isr_common_handler
isr3:
cli
push 0
push 3
jmp isr_common_handler
isr4:
cli
push 0
push 4
jmp isr_common_handler
isr5:
cli
push 0
push 5
jmp isr_common_handler
isr6:
cli
push 0
push 6
jmp isr_common_handler
isr7:
cli
push 0
push 7
jmp isr_common_handler
isr8:
cli
push 0
push 8
jmp isr_common_handler
isr9:
cli
push 0
push 9
jmp isr_common_handler
isr10:
cli
push 0
push 10
jmp isr_common_handler
isr11:
cli
push 0
push 11
jmp isr_common_handler
isr12:
cli
push 0
push 12
jmp isr_common_handler
isr13:
cli
push 0
push 13
jmp isr_common_handler
; ISR 14 (Page Fault) requires error code pushed by CPU
isr14:
cli
push 14 ; Push interrupt number
jmp isr_common_handler
; ISRs 15 to 31 (no error code pushed by CPU)
isr15:
cli
push 0
push 15
jmp isr_common_handler
isr16:
cli
push 0
push 16
jmp isr_common_handler
isr17:
cli
push 0
push 17
jmp isr_common_handler
isr18:
cli
push 0
push 18
jmp isr_common_handler
isr19:
cli
push 0
push 19
jmp isr_common_handler
isr20:
cli
push 0
push 20
jmp isr_common_handler

View File

@ -0,0 +1,157 @@
global start
extern long_mode_start
extern idtp
extern handle_keypress
; idt_load.asm
global idt_load
section .text
bits 32
start:
mov esp, stack_top
call check_multiboot
call check_cpuid
call check_long_mode
call setup_page_tables
call enable_paging
lgdt [gdt64.pointer]
jmp gdt64.code_segment:long_mode_start
hlt
; Load the IDT
idt_load:
lidt [idtp]
sti ; Enable interrupts
ret
check_multiboot:
cmp eax, 0x36d76289
jne .no_multiboot
ret
.no_multiboot:
mov al, 'M'
jmp error
check_cpuid:
pushfd
pop eax
mov ecx, eax
xor eax, 1 << 21
push eax
popfd
pushfd
pop eax
push ecx
popfd
cmp eax, ecx
je .no_cpuid
ret
.no_cpuid:
mov al, 'C'
jmp error
check_long_mode:
mov eax, 0x80000000
cpuid
cmp eax, 0x80000001
jb .no_long_mode
mov eax, 0x80000001
cpuid
test edx, 1 << 29
jz .no_long_mode
ret
.no_long_mode:
mov al, 'L'
jmp error
setup_page_tables:
mov eax, page_table_l3
or eax, 0b11 ; present, writable
mov [page_table_l4], eax
mov eax, page_table_l2
or eax, 0b11 ; present, writable
mov [page_table_l3], eax
mov ecx, 0 ; counter
.loop:
mov eax, 0x200000 ; 2MiB
mul ecx
or eax, 0b10000011 ; present, writable, huge page
mov [page_table_l2 + ecx * 8], eax
inc ecx ; increment counter
cmp ecx, 512 ; checks if the whole table is mapped
jne .loop ; if not, continue
ret
enable_paging:
; pass page table location to cpu
mov eax, page_table_l4
mov cr3, eax
; enable PAE
mov eax, cr4
or eax, 1 << 5
mov cr4, eax
; enable long mode
mov ecx, 0xC0000080
rdmsr
or eax, 1 << 8
wrmsr
; enable paging
mov eax, cr0
or eax, 1 << 31
mov cr0, eax
ret
error:
; print "ERR: X" where X is the error code
mov dword [0xb8000], 0x4f524f45
mov dword [0xb8004], 0x4f3a4f52
mov dword [0xb8008], 0x4f204f20
mov byte [0xb800a], al
hlt
section .bss
; Reserve space for the IDT pointer
idtp:
resb 6 ; 2 bytes for limit + 4 bytes for base address
align 4096
page_table_l4:
resb 4096
page_table_l3:
resb 4096
page_table_l2:
resb 4096
stack_bottom:
resb 4096 * 4
stack_top:
section .rodata
gdt64:
dq 0 ; zero entry
.code_segment: equ $ - gdt64
dq (1 << 43) | (1 << 44) | (1 << 47) | (1 << 53) ; code segment
.pointer:
dw $ - gdt64 - 1 ; length
dq gdt64 ; address

View File

@ -0,0 +1,16 @@
global long_mode_start
extern kernel_main
section .text
bits 64
long_mode_start:
; load null into all data segment registers
mov ax, 0
mov ss, ax
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
call kernel_main
hlt

View File

@ -0,0 +1,43 @@
// disk_io.c
#include "disk_io.h"
#include "print.h" // Assuming you have a function for kernel printing
#define SECTOR_SIZE 512
// Function to read sectors from disk
int disk_read(uint32_t lba, void *buffer, uint32_t size) {
// lba: logical block address
// buffer: where to store the read data
// size: number of bytes to read
if (size % SECTOR_SIZE != 0) {
printf("Read size must be a multiple of 512 bytes\n");
return -1;
}
for (uint32_t i = 0; i < size / SECTOR_SIZE; i++) {
// Placeholder for actual disk sector read. Replace with proper implementation
if (!bios_read_sector(lba + i, buffer + (i * SECTOR_SIZE))) {
printf("Error reading sector from disk\n");
return -1;
}
}
return 0;
}
// Placeholder function to simulate reading sectors from the disk
// Replace this with actual disk reading logic depending on the platform
int bios_read_sector(uint32_t lba, void *buffer) {
// Simulate disk sector read
// In an actual kernel, you'd use interrupts or other mechanisms to read from disk
// For now, just zero out the buffer to simulate
for (int i = 0; i < SECTOR_SIZE; i++) {
((uint8_t*)buffer)[i] = 0; // Fill buffer with zeros
}
return 1; // Success
}

View File

@ -0,0 +1,129 @@
// fat12.c
#include "fat12.h"
#include "disk_io.h"
#include "print.h"
#include "strings.h"
#include "fat12.h"
#include "disk_io.h" // Assuming this contains `disk_read` for sector-level disk access
#define SECTOR_SIZE 512
#define FAT12_CLUSTER_SIZE 1 // Usually 1 sector per cluster for FAT12
#define FAT12_EOC 0xFF8 // End of cluster chain marker in FAT12
// Function to convert a cluster number to an LBA (Logical Block Address)
static uint32_t cluster_to_lba(uint16_t cluster, const fat12_boot_sector_t *boot_sector) {
uint32_t first_data_sector = boot_sector->reserved_sectors +
(boot_sector->num_fats * boot_sector->fat_size_16) +
boot_sector->root_entry_count * 32 / SECTOR_SIZE;
return first_data_sector + (cluster - 2) * boot_sector->sectors_per_cluster;
}
// Function to read the FAT to find the next cluster
static uint16_t fat12_get_next_cluster(uint16_t cluster, const fat12_boot_sector_t *boot_sector) {
uint32_t fat_offset = cluster + (cluster / 2); // FAT12 uses 12-bit entries
uint16_t next_cluster;
uint8_t fat_entry[2];
// Read the FAT sector where the current cluster is stored
uint32_t fat_sector = boot_sector->reserved_sectors + fat_offset / SECTOR_SIZE;
uint32_t fat_offset_in_sector = fat_offset % SECTOR_SIZE;
disk_read(fat_sector, fat_entry, sizeof(fat_entry));
if (cluster & 1) {
next_cluster = ((fat_entry[1] << 4) | (fat_entry[0] >> 4)) & 0xFFF; // Odd cluster number
} else {
next_cluster = ((fat_entry[1] << 8) | fat_entry[0]) & 0xFFF; // Even cluster number
}
return next_cluster;
}
int fat12_read_file(fat12_dir_entry_t *entry, void *buffer) {
fat12_boot_sector_t boot_sector;
uint16_t current_cluster = entry->first_cluster_low;
uint32_t file_size = entry->file_size;
uint8_t *buf_ptr = (uint8_t *)buffer;
uint32_t bytes_read = 0;
// Load the boot sector (this would need to be done once in initialization, but for simplicity here)
disk_read(0, &boot_sector, sizeof(fat12_boot_sector_t));
// Read each cluster of the file
while (current_cluster < FAT12_EOC && bytes_read < file_size) {
// Calculate the LBA of the current cluster
uint32_t lba = cluster_to_lba(current_cluster, &boot_sector);
// Read the cluster (sector) into the buffer
disk_read(lba, buf_ptr, SECTOR_SIZE);
buf_ptr += SECTOR_SIZE;
bytes_read += SECTOR_SIZE;
// Get the next cluster in the FAT chain
current_cluster = fat12_get_next_cluster(current_cluster, &boot_sector);
}
// Ensure we dont read beyond the file size
if (bytes_read > file_size) {
bytes_read = file_size;
}
return bytes_read; // Return the number of bytes read
}
static fat12_boot_sector_t boot_sector;
static fat12_dir_entry_t root_directory[ROOT_DIR_ENTRIES];
// FAT12 Initialization (called during filesystem mount)
int fat12_init(void) {
// Read boot sector
if (disk_read(0, &boot_sector, sizeof(fat12_boot_sector_t)) != 0) {
printf("Failed to read boot sector\n");
return -1;
}
// Check for FAT12 signature
if (*(uint16_t *)((char *)&boot_sector + 510) != FAT12_SIGNATURE) {
printf("Invalid FAT12 filesystem\n");
return -1;
}
printf("FAT12 filesystem successfully mounted\n");
return 0;
}
// Reads the root directory
int fat12_read_root_directory(void) {
uint32_t root_dir_lba = (boot_sector.reserved_sectors + boot_sector.num_fats * boot_sector.fat_size_16) * boot_sector.bytes_per_sector;
if (disk_read(root_dir_lba, root_directory, sizeof(root_directory)) != 0) {
printf("Failed to read root directory\n");
return -1;
}
printf("Root directory loaded\n");
return 0;
}
// Find a file by name in the root directory
int fat12_find_file(const char *filename, fat12_dir_entry_t *entry) {
for (int i = 0; i < ROOT_DIR_ENTRIES; i++) {
if (strncmp(root_directory[i].filename, filename, 8) == 0) {
*entry = root_directory[i];
return 1;
}
}
printf("File not found\n");
return 0;
}

View File

@ -0,0 +1,31 @@
#include "fat12.h"
#include "disk_io.h"
#include "print.h"
void fs_mount() {
// Load FAT12 boot sector
fat12_boot_sector_t boot_sector;
disk_read(0, &boot_sector, sizeof(boot_sector));
// Initialize FAT12
fat12_init();
}
void fs_read_file(const char *filename) {
// Find file in FAT12 root directory and read its contents
fat12_dir_entry_t dir_entry;
fat12_find_file(filename, &dir_entry);
// Read file data
uint8_t buffer[dir_entry.file_size];
fat12_read_file(&dir_entry, buffer);
// Print or process the data
printf(buffer);
}

View File

@ -0,0 +1,196 @@
#include <stdint.h>
#include "idt.h"
#include "print.h"
#include "vga.h"
#define IDT_ENTRIES 256
// Declare the IDT and IDT pointer as external symbols
struct idt_entry_t idt[IDT_ENTRIES]; // Assuming 256 entries
struct idt_ptr_t idt_ptr;
// Declare ISRs implemented in assembly
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();
// Continue up to the required number of ISRs
// IDT entry setup for 64-bit mode
void setup_idt_entry(int index, void (*handler)(), uint16_t selector, uint8_t type_attr) {
uint64_t handler_addr = (uint64_t)handler;
idt[index].offset_low = handler_addr & 0xFFFF; // Lower 16 bits of handler function address
idt[index].selector = selector; // Segment selector (kernel code segment)
idt[index].ist = 0; // Interrupt Stack Table (IST)
idt[index].type_attr = type_attr; // Type and attributes (P, DPL, S, Type)
idt[index].offset_mid = (handler_addr >> 16) & 0xFFFF; // Middle 16 bits of handler address
idt[index].offset_high = (handler_addr >> 32) & 0xFFFFFFFF; // Higher 32 bits of handler address (for 64-bit)
idt[index].zero = 0; // Reserved (set to 0)
}
// Initialize the IDT
void init_idt() {
// Setup each IDT entry
setup_idt_entry(0, isr0, 0x08, 0x8E); // Divide-by-zero
setup_idt_entry(1, isr1, 0x08, 0x8E); // Debug
setup_idt_entry(2, isr2, 0x08, 0x8E); // Non-maskable interrupt
setup_idt_entry(3, isr3, 0x08, 0x8E); // Breakpoint
setup_idt_entry(4, isr4, 0x08, 0x8E); // Overflow
setup_idt_entry(5, isr5, 0x08, 0x8E); // Bound Range Exceeded
setup_idt_entry(6, isr6, 0x08, 0x8E); // Invalid Opcode
setup_idt_entry(7, isr7, 0x08, 0x8E); // Device Not Available
setup_idt_entry(8, isr8, 0x08, 0x8E); // Double Fault
setup_idt_entry(9, isr9, 0x08, 0x8E); // Coprocessor Segment Overrun
setup_idt_entry(10, isr10, 0x08, 0x8E); // Invalid TSS
setup_idt_entry(11, isr11, 0x08, 0x8E); // Segment Not Present
setup_idt_entry(12, isr12, 0x08, 0x8E); // Stack-Segment Fault
setup_idt_entry(13, isr13, 0x08, 0x8E); // General Protection Fault
setup_idt_entry(14, isr14, 0x08, 0x8E); // Page Fault
setup_idt_entry(15, isr15, 0x08, 0x8E); // Reserved
setup_idt_entry(16, isr16, 0x08, 0x8E); // x87 FPU Floating-Point Error
setup_idt_entry(17, isr17, 0x08, 0x8E); // Alignment Check
setup_idt_entry(18, isr18, 0x08, 0x8E); // Machine Check
setup_idt_entry(19, isr19, 0x08, 0x8E); // SIMD Floating-Point Exception
setup_idt_entry(20, isr20, 0x08, 0x8E); // Virtualization Exception
// Additional Reserved Entries as needed, or continue with ISR setup
// Load the IDT
// IDT pointer setup
idt_ptr.limit = sizeof(idt) - 1;
idt_ptr.base = (uint64_t)&idt;
// Load the IDT with the lidt instruction
__asm__ volatile ("lidt %0" : : "m"(idt_ptr));
}
void isr_common_handler(uint32_t isr_number) {
printf("Interrupt received: ");
printf("IDT: %d", isr_number); // To verify if the correct ISR is triggered
printf("\n");
kpanic(isr_number);
}
// Define kpanic to handle panic with BSOD and error messages
void kpanic(int error_code) {
// Set the background color to blue and text color to white
print_set_color(PRINT_COLOR_BLUE, PRINT_COLOR_BLUE);
move_print_cursor(0, 0);
// Fill the entire screen with the background color
for (int y = 0; y < 25; y++) { // Replace SCREEN_HEIGHT with the actual screen height
for (int x = 0; x < 80; x++) { // Replace SCREEN_WIDTH with the actual screen width
print_char(' '); // Print a space to fill the background
}
}
// Set the text color to white and background color to blue
print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLUE);
move_print_cursor(0, 0);
// Print the text in the top left corner
print_str(" _ \n");
print_str(" / )\n");
print_str(" _ / / \n");
print_str(" (_)( ( \n");
print_str(" | | \n");
print_str(" _ ( ( \n");
print_str(" (_) \\ \\ \n");
print_str(" \\_)\n");
print_str("\n\n\n");
print_str(" KERNEL PANIC\n\n");
print_str(" ");
switch (error_code) {
case ERROR_DIVIDE_BY_ZERO:
print_str("Error: Divide-by-Zero Exception\n");
break;
case ERROR_DEBUG:
print_str("Error: Debug Exception\n");
break;
case ERROR_NMI:
print_str("Error: Non-Maskable Interrupt\n");
break;
case ERROR_BREAKPOINT:
print_str("Error: Breakpoint Exception\n");
break;
case ERROR_OVERFLOW:
print_str("Error: Overflow Exception\n");
break;
case ERROR_BOUND:
print_str("Error: Bound Range Exceeded\n");
break;
case ERROR_INVALID_OP:
print_str("Error: Invalid Opcode\n");
break;
case ERROR_DEVICE_NOT_AVAIL:
print_str("Error: Device Not Available\n");
break;
case ERROR_DOUBLE_FAULT:
print_str("Error: Double Fault\n");
break;
case ERROR_COPROCESSOR_OVERRUN:
print_str("Error: Coprocessor Segment Overrun\n");
break;
case ERROR_INVALID_TSS:
print_str("Error: Invalid TSS\n");
break;
case ERROR_SEGMENT_NOT_PRESENT:
print_str("Error: Segment Not Present\n");
break;
case ERROR_STACK_SEGMENT:
print_str("Error: Stack-Segment Fault\n");
break;
case ERROR_GENERAL_PROTECTION:
print_str("Error: General Protection Fault\n");
break;
case ERROR_PAGE_FAULT:
print_str("Error: Page Fault\n");
break;
case FILESYSTEM_ERROR:
print_str("Error: Filesystem Error\n");
break;
default:
printf("Error: Unknown Exception '%d'\n", error_code);
break;
}
// Halt the system
while (1) {}
}
void idt_install() {
print_set_color(PRINT_COLOR_LIGHT_GRAY, PRINT_COLOR_BLACK);
print_str("[ init ] IDT\n");
init_idt();
printf("IDT Base: %p\n", (void*)idt_ptr.base); // For pointer
printf("IDT Limit: %x\n", idt_ptr.limit); // Assuming limit is small enough for %x
print_set_color(PRINT_COLOR_GREEN, PRINT_COLOR_BLACK);
print_str("[ OK ] IDT\n");
}

View File

@ -0,0 +1,15 @@
// io.c
#include "io.h"
#include "stdint.h"
void outb(uint16_t port, uint8_t value) {
asm volatile ("outb %0, %1" : : "a"(value), "Nd"(port));
}
uint8_t inb(uint16_t port) {
uint8_t value;
asm volatile ("inb %1, %0" : "=a"(value) : "Nd"(port));
return value;
}

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,152 @@
#include "keydriver.h"
#include "print.h" // Make sure you have a print function available
// Define the keyboard buffer and index
static char keyboard_buffer[KEYBOARD_BUFFER_SIZE];
static unsigned int buffer_index = 0;
static int shift_pressed = 0;
// Updated ASCII conversion table (scan code to ASCII)
const char ascii_table[128] =
{
0, 27, '1', '2', '3', '4', '5', '6', '7', '8', // 9
'9', '0', '-', '=', '\b', // Backspace
'\t', // Tab
'q', 'w', 'e', 'r', // 19
't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', // Enter key
0, // 29 - Control
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', // 39
'\'', '`', 0, // Left shift
'\\', 'z', 'x', 'c', 'v', 'b', 'n', // 49
'm', ',', '.', '/', 0, // Right shift
'*',
0, // Alt
' ', // Space bar
0, // Caps lock
0, // 59 - F1 key ... >
0, 0, 0, 0, 0, 0, 0, 0,
0, // < ... F10
0, // 69 - Num lock
0, // Scroll Lock
0, // Home key
0, // Up Arrow
0, // Page Up
'-',
0, // Left Arrow
0,
0, // Right Arrow
'+',
0, // 79 - End key
0, // Down Arrow
0, // Page Down
0, // Insert Key
0, // Delete Key
0, 0, 0,
0, // F11 Key
0, // F12 Key
0, // All other keys are undefined
};
// Uppercase ASCII conversion table (shift key pressed)
const char shift_ascii_table[128] =
{
0, 27, '!', '@', '#', '$', '%', '^', '&', '*', // 9
'(', ')', '_', '+', '\b', // Backspace
'\t', // Tab
'Q', 'W', 'E', 'R', // 19
'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n', // Enter key
0, // 29 - Control
'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', // 39
'"', '~', 0, // Left shift
'|', 'Z', 'X', 'C', 'V', 'B', 'N', // 49
'M', '<', '>', '?', 0, // Right shift
'*',
0, // Alt
' ', // Space
0, // Caps lock
0, // 59 - F1 key ... >
0, 0, 0, 0, 0, 0, 0, 0,
0, // < ... F10
0, // 69 - Num lock
0, // Scroll Lock
0, // Home key
0, // Up Arrow
0, // Page Up
'-',
0, // Left Arrow
0,
0, // Right Arrow
'+',
0, // 79 - End key
0, // Down Arrow
0, // Page Down
0, // Insert Key
0, // Delete Key
0, 0, 0,
0, // F11 Key
0, // F12 Key
0, // All other keys
};
// Initialize the keyboard driver
void init_keyboard_driver() {
print_set_color(PRINT_COLOR_LIGHT_GRAY, PRINT_COLOR_BLACK);
print_str("[ init ] KEYDRIVER\n");
buffer_index = 0;
shift_pressed = 0;
print_set_color(PRINT_COLOR_GREEN, PRINT_COLOR_BLACK);
print_str("[ OK ] KEYDRIVER\n");
}
// Read a single character from the keyboard
char read_key() {
char key = 0;
// Read a key from port 0x60
__asm__("inb $0x60, %0" : "=a"(key));
// Check for key release (scan codes 0x80 and above are typically releases)
if (key & 0x80) {
// Handle key release
key &= 0x7F; // Remove the high bit to get the original scan code
if (key == 0x2A || key == 0x36) { // Left or right shift
shift_pressed = 0;
}
return 0;
} else {
// Handle key press
if (key == 0x2A || key == 0x36) { // Left or right shift
shift_pressed = 1;
return 0;
}
// Convert scan code to ASCII
if (key < 128) {
if (shift_pressed) {
key = shift_ascii_table[(unsigned char)key];
} else {
key = ascii_table[(unsigned char)key];
}
}
// Store the key in the buffer if there's space
if (buffer_index < KEYBOARD_BUFFER_SIZE) {
keyboard_buffer[buffer_index++] = key;
}
return key;
}
}
// Get the current buffer index
unsigned int get_buffer_index() {
return buffer_index;
}
// Retrieve the contents of the keyboard buffer
const char* get_keyboard_buffer() {
return keyboard_buffer;
}

View File

@ -0,0 +1,116 @@
#include "memory.h"
#include "stdint.h"
#include "print.h"
#define MEMORY_POOL_SIZE 0xFFFFF // Define the size of the memory pool
static uint8_t memory_pool[MEMORY_POOL_SIZE]; // Static memory pool
static uint8_t* memory_pool_end = memory_pool; // Pointer to the end of allocated memory
// Block header to store size and free status
typedef struct block_header {
size_t size;
struct block_header* next; // For linking free blocks
int is_free;
} block_header_t;
#define HEADER_SIZE sizeof(block_header_t)
static block_header_t* free_list = NULL; // Head of the free list
// Custom malloc implementation with block headers
void* malloc(size_t size) {
size = (size + 3) & ~3; // Align size to 4 bytes
// First, check the free list for a suitable block
block_header_t* current = free_list;
block_header_t* prev = NULL;
while (current) {
if (current->is_free && current->size >= size) {
current->is_free = 0; // Mark as used
return (void*)((uint8_t*)current + HEADER_SIZE); // Return memory after header
}
prev = current;
current = current->next;
}
// No suitable block found in free list, allocate new memory from pool
if ((memory_pool_end + size + HEADER_SIZE) > (memory_pool + MEMORY_POOL_SIZE)) {
printf("Failed to allocate memory! Requested: %u bytes\n", size);
return NULL;
}
block_header_t* header = (block_header_t*)memory_pool_end;
header->size = size;
header->is_free = 0;
header->next = NULL;
memory_pool_end += size + HEADER_SIZE;
return (void*)((uint8_t*)header + HEADER_SIZE);
}
// Custom free implementation to add block back to the free list
void free(void* ptr) {
if (!ptr) {
return;
}
// Get the block header before the allocated memory
block_header_t* header = (block_header_t*)((uint8_t*)ptr - HEADER_SIZE);
header->is_free = 1;
// Add the block to the free list
header->next = free_list;
free_list = header;
}
void list_used_blocks() {
uint8_t* current_ptr = memory_pool;
printf("Listing all used blocks:\n");
// Traverse the memory pool and print each block's information
while (current_ptr < memory_pool_end) {
block_header_t* header = (block_header_t*)current_ptr;
if (!header->is_free) {
printf("Used block at %p | Size: %u bytes\n", (void*)(current_ptr + HEADER_SIZE), header->size);
}
current_ptr += HEADER_SIZE + header->size;
}
printf("End of used blocks.\n");
}
void* memcpy(void* dst, const void* src, uint16_t num) {
uint8_t* d = (uint8_t*)dst;
const uint8_t* s = (const uint8_t*)src;
while (num--) {
*d++ = *s++;
}
return dst;
}
void* memset(void* ptr, int value, uint16_t num) {
uint8_t* p = (uint8_t*)ptr;
while (num--) {
*p++ = (uint8_t)value;
}
return ptr;
}
int memcmp(const void* ptr1, const void* ptr2, uint16_t num) {
const uint8_t* p1 = (const uint8_t*)ptr1;
const uint8_t* p2 = (const uint8_t*)ptr2;
while (num--) {
if (*p1 != *p2) {
return *p1 - *p2;
}
p1++;
p2++;
}
return 0;
}

View File

@ -0,0 +1,343 @@
#include <stdarg.h>
#include "print.h"
#include "vga.h"
const static size_t NUM_COLS = 80;
const static size_t NUM_ROWS = 25;
struct Char {
uint8_t character;
uint8_t color;
};
struct Char* buffer = (struct Char*) 0xb8000;
size_t col = 0;
size_t row = 0;
uint8_t color = PRINT_COLOR_WHITE | PRINT_COLOR_BLACK << 4;
void clear_row(size_t row) {
struct Char empty = (struct Char) {
character: ' ',
color: color,
};
for (size_t col = 0; col < NUM_COLS; col++) {
buffer[col + NUM_COLS * row] = empty;
}
}
void print_clear() {
for (size_t i = 0; i < NUM_ROWS; i++) {
clear_row(i);
}
}
//void print_newline() {
// col = 0;
//
// if (row < NUM_ROWS - 1) {
// row++;
// return;
// }
//
// for (size_t row = 1; row < NUM_ROWS; row++) {
// for (size_t col = 0; col < NUM_COLS; col++) {
// struct Char character = buffer[col + NUM_COLS * row];
// buffer[col + NUM_COLS * (row - 1)] = character;
// }
// }
//
// clear_row(NUM_COLS - 1);
//}
void print_newline() {
row++;
col = 0;
// Check for scrolling
if (row >= NUM_ROWS) {
row = NUM_ROWS - 1;
// Scroll the screen up
// Copy lines up
// Clear the last line
}
}
CursorPosition get_print_cursor_pos() {
CursorPosition pos;
pos.x = col; // Use col for x
pos.y = row; // Use row for y
return pos;
}
void print_hex(unsigned int num) {
char buffer[9]; // Buffer to hold the hexadecimal string representation
int i = 0;
// Handle zero case
if (num == 0) {
print_char('0');
return;
}
// Convert integer to hexadecimal in reverse order
while (num > 0) {
int digit = num % 16;
if (digit < 10) {
buffer[i++] = digit + '0';
} else {
buffer[i++] = (digit - 10) + 'A';
}
num /= 16;
}
// Print the hexadecimal number in correct order
for (int j = i - 1; j >= 0; j--) {
print_char(buffer[j]);
}
}
void move_print_cursor(int x, int y) {
col = x;
row = y;
set_cursor_position(col, row); // Move cursor to new position
}
void offset_print_cursor(int x, int y) {
col += x;
row += y;
set_cursor_position(col, row);
}
// Function to print a single character
void print_char(char character) {
if (character == '\n') {
print_newline();
return;
}
// Handle wrapping
if (col >= NUM_COLS) {
print_newline();
}
// Update the buffer
buffer[col + NUM_COLS * row] = (struct Char) {
.character = (uint8_t) character,
.color = color,
};
col++;
}
// Function to print a string
void print_str(char* str) {
size_t i = 0;
while (str[i] != '\0') {
print_char(str[i]);
i++;
}
}
void print_set_color(uint8_t foreground, uint8_t background) {
color = foreground + (background << 4);
}
void print_int(int num) {
// Handle negative numbers
if (num < 0) {
print_char('-');
num = -num;
}
// Convert number to string
char buffer[11]; // Buffer to hold integer string representation
int i = 0;
if (num == 0) {
buffer[i++] = '0';
} else {
while (num > 0) {
buffer[i++] = (num % 10) + '0';
num /= 10;
}
}
// Print the integer in correct order
for (int j = i - 1; j >= 0; j--) {
print_char(buffer[j]);
}
}
#include <stdarg.h>
#include "print.h"
void print_formatted(const char* format, va_list args) {
while (*format) {
if (*format == '%') {
format++;
switch (*format) {
case 's': {
char* str = va_arg(args, char*);
print_str(str);
break;
}
case 'x': {
unsigned int num = va_arg(args, unsigned int);
print_hex(num);
break;
}
case 'd': {
int num = va_arg(args, int);
print_int(num);
break;
}
case 'c': {
char ch = (char) va_arg(args, int); // Promoted to int
print_char(ch);
break;
}
case 'u': {
unsigned int num = va_arg(args, unsigned int);
print_uint(num); // Custom function for unsigned int
break;
}
case 'p': {
void* ptr = va_arg(args, void*);
print_pointer(ptr); // Custom function for pointers
break;
}
case 'f': {
double num = va_arg(args, double);
print_float(num); // Custom function for floating-point numbers
break;
}
default:
print_char('%');
print_char(*format);
break;
}
} else {
print_char(*format);
}
format++;
}
}
void print_uint(unsigned int num) {
// Convert to string and print (implementation required)
char buffer[11]; // Enough for 32-bit unsigned int
int i = 0;
if (num == 0) {
print_char('0');
return;
}
while (num > 0) {
buffer[i++] = '0' + (num % 10);
num /= 10;
}
while (i > 0) {
print_char(buffer[--i]);
}
}
void print_pointer(void* ptr) {
unsigned long num = (unsigned long) ptr;
print_str("0x");
print_hex(num); // Assuming print_hex handles long
}
void print_float(double num) {
// Simple implementation of floating-point printing
int int_part = (int)num;
int frac_part = (int)((num - int_part) * 1000000); // Six decimal places
print_int(int_part);
print_char('.');
// Ensure fractional part is always printed with six digits
for (int i = 0; i < 6; i++) {
print_char('0' + (frac_part % 10));
frac_part /= 10;
}
}
void sscanf(const char *str, const char *format, char *filename, char *content) {
const char *p = str;
char *f = filename;
char *c = content;
while (*format) {
if (*format == '%') {
format++;
if (*format == 's') {
// Copy the first string
while (*p && *p != ' ' && (f - filename) < MAX_STRING_LENGTH - 1) {
*f++ = *p++;
}
*f = '\0';
// Skip any whitespace
while (*p == ' ') p++;
// Copy the second string
while (*p && (c - content) < MAX_STRING_LENGTH - 1) {
*c++ = *p++;
}
*c = '\0';
}
}
format++;
}
}
int my_sscanf(const char *input, const char *format, char *output) {
const char *in_ptr = input;
const char *fmt_ptr = format;
char *out_ptr = output;
int match_count = 0;
// Skip any leading whitespace in the input
while (*in_ptr && (*in_ptr == ' ' || *in_ptr == '\t')) {
in_ptr++;
}
// Process the format string
while (*fmt_ptr) {
if (*fmt_ptr == '%' && *(fmt_ptr + 1) == 's') {
// Found a string specifier
fmt_ptr += 2; // Skip %s
// Copy input string to output until whitespace or end of input
while (*in_ptr && *in_ptr != ' ' && *in_ptr != '\t' && *in_ptr != '\n') {
*out_ptr++ = *in_ptr++;
}
*out_ptr = '\0'; // Null-terminate the output string
match_count++;
} else {
// Match literal characters in format string
if (*fmt_ptr == *in_ptr) {
fmt_ptr++;
in_ptr++;
} else {
// Literal character mismatch
return match_count;
}
}
}
return match_count;
}
void printf(const char* format, ...) {
va_list args;
va_start(args, format);
print_formatted(format, args);
va_end(args);
}

View File

@ -0,0 +1,80 @@
#include "vector.h"
// Initial capacity for a new vector
#define VECTOR_INITIAL_CAPACITY 4
// Create a new vector
vector* vector_create() {
vector* v = (vector*)malloc(sizeof(vector));
if (!v) return NULL; // Return NULL if allocation fails
v->capacity = VECTOR_INITIAL_CAPACITY;
v->size = 0;
v->items = (void**)malloc(sizeof(void*) * v->capacity);
if (!v->items) {
free(v); // Free the vector if item allocation fails
return NULL;
}
return v;
}
// Destroy the vector and free allocated memory
void vector_destroy(vector* v) {
if (v) {
free(v->items);
free(v);
}
}
// Push an item to the back of the vector
int vector_push_back(vector* v, void* item) {
// Resize the vector if it's full
if (v->size == v->capacity) {
if (vector_resize(v, v->capacity * 2) != 0) {
return -1; // Return -1 on failure to resize
}
}
v->items[v->size++] = item; // Add the new item
return 0; // Success
}
// Get the item at a specific index
void* vector_get(vector* v, size_t index) {
if (index >= v->size) return NULL; // Return NULL if index is out of bounds
return v->items[index];
}
// Set an item at a specific index
int vector_set(vector* v, size_t index, void* item) {
if (index >= v->size) return -1; // Return -1 if index is out of bounds
v->items[index] = item;
return 0; // Success
}
// Get the size of the vector
size_t vector_size(vector* v) {
return v->size;
}
// Resize the vector's internal array
int vector_resize(vector* v, size_t new_capacity) {
// Allocate new memory for the resized array
void** new_items = (void**)malloc(sizeof(void*) * new_capacity);
if (!new_items) return -1; // Return -1 on failure
// Copy the old items into the new array
for (size_t i = 0; i < v->size; i++) {
new_items[i] = v->items[i];
}
// Free the old memory
free(v->items);
// Update the vector's internal state
v->items = new_items;
v->capacity = new_capacity;
return 0; // Success
}

View File

@ -0,0 +1,29 @@
#include "vga.h"
#include "stdint.h"
#include "io.h"
#define VGA_PORT_INDEX 0x3D4
#define VGA_PORT_DATA 0x3D5
void move_cursor(int x, int y) {
uint16_t position = y * 80 + x; // Assuming 80 columns
outb(0x3D4, 0x0E); // VGA register for high byte
outb(0x3D5, (position >> 8) & 0xFF);
outb(0x3D4, 0x0F); // VGA register for low byte
outb(0x3D5, position & 0xFF);
}
void set_cursor_position(int x, int y) {
uint16_t position = y * 80 + x; // 80 columns in VGA text mode
outb(VGA_PORT_INDEX, 0x0E);
outb(VGA_PORT_DATA, (position >> 8) & 0xFF);
outb(VGA_PORT_INDEX, 0x0F);
outb(VGA_PORT_DATA, position & 0xFF);
}

View File

@ -0,0 +1,185 @@
#include "game.h"
#include "print.h"
#include "keydriver.h"
#include "strings.h"
#include "stdint.h"
// Define constants for the game
#define ROOM_COUNT 5
#define INVENTORY_SIZE 5
// Global variable to hold the game state
static GameState game_state;
// Room descriptions and connected rooms
typedef struct {
const char* description;
int north;
int south;
int east;
int west;
} Room;
static const Room rooms[ROOM_COUNT] = {
{ "You are in a dark forest. There are paths to the north and east.", 1, -1, 2, -1 },
{ "You are on a beach. There is a cave to the west.", -1, 0, -1, 3 },
{ "You are inside a cave. Its damp and dark.", -1, -1, -1, 0 },
{ "You are in a small village. There's a shop to the north and a forest to the east.", 4, -1, -1, -1 },
{ "You are in a shop filled with various items. The village is to the south.", -1, 3, -1, -1 }
};
// Player's inventory
static const char* inventory[INVENTORY_SIZE];
static int inventory_count = 0;
// Command buffer
static char commandBuffer[MAX_COMMAND_LENGTH];
static size_t commandLength = 0;
bool keydown = false;
// Function to handle user input commands
void handle_command(const char* command) {
game_clear();
if (strcmp(command, "look") == 0) {
printf(rooms[game_state.current_room].description);
printf("\n");
} else if (strcmp(command, "north") == 0) {
if (rooms[game_state.current_room].north != -1) {
game_state.current_room = rooms[game_state.current_room].north;
printf("You walk north.\n");
printf("%s\n", rooms[game_state.current_room].description);
} else {
printf("You can't go that way.\n");
}
} else if (strcmp(command, "south") == 0) {
if (rooms[game_state.current_room].south != -1) {
game_state.current_room = rooms[game_state.current_room].south;
printf("You walk south.\n");
printf("%s\n", rooms[game_state.current_room].description);
} else {
printf("You can't go that way.\n");
}
} else if (strcmp(command, "east") == 0) {
if (rooms[game_state.current_room].east != -1) {
game_state.current_room = rooms[game_state.current_room].east;
printf("You walk east.\n");
printf("%s\n", rooms[game_state.current_room].description);
} else {
printf("You can't go that way.\n");
}
} else if (strcmp(command, "west") == 0) {
if (rooms[game_state.current_room].west != -1) {
game_state.current_room = rooms[game_state.current_room].west;
printf("You walk west.\n");
printf("%s\n", rooms[game_state.current_room].description);
} else {
printf("You can't go that way.\n");
}
} else if (strcmp(command, "inventory") == 0) {
printf("You are carrying:\n");
for (int i = 0; i < inventory_count; ++i) {
printf("- %s\n", inventory[i]);
}
if (inventory_count == 0) {
printf("Nothing.\n");
}
} else if (strcmp(command, "take key") == 0) {
if (game_state.current_room == 1) {
if (inventory_count < INVENTORY_SIZE) {
inventory[inventory_count++] = "key";
printf("You picked up a key.\n");
} else {
printf("Your inventory is full.\n");
}
} else {
printf("There is no key here.\n");
}
} else if (strcmp(command, "use key") == 0) {
bool has_key = false;
for (int i = 0; i < inventory_count; ++i) {
if (strcmp(inventory[i], "key") == 0) {
has_key = true;
break;
}
}
if (has_key && game_state.current_room == 2) {
printf("You unlock the door in the cave and find a treasure!\n");
game_state.game_active = false; // End the game
} else {
printf("You can't use the key here.\n");
}
} else if (strcmp(command, "quit") == 0) {
printf("You quit the game.\n");
game_state.game_active = false;
} else {
printf("Unknown command.\n");
}
}
// Function to print the prompt for the player
void print_prompt() {
printf(" > ");
}
const void game_clear()
{
print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK); // Set text color
move_print_cursor(0, 0);
move_cursor(0, 0);
print_clear();
}
// Function to initialize and run the game
void create_game() {
// Initialize the game state
game_state.current_room = 0;
game_state.game_active = true;
printf("Welcome to the text adventure game!\n");
printf("Type 'look' to see where you are, 'north', 'south', 'east', 'west' to move, or 'quit' to exit.\n");
printf("You can 'take key' or 'use key' in the appropriate places.\n");
print_prompt();
// Main game loop
while (game_state.game_active) {
char key = read_key(); // Get key input
if (key != 0) {
if (!keydown) {
if (key == 10) { // Enter key
printf("\n");
commandBuffer[commandLength] = '\0'; // Null-terminate the command
handle_command(commandBuffer); // Process the command
commandLength = 0; // Reset command buffer
if (game_state.game_active) {
print_prompt(); // Print prompt for the next command
}
} else if (key == 8) { // Backspace key
if (commandLength > 0) {
commandLength--;
offset_print_cursor(-1, 0);
print_char(' '); // Overwrite the character
offset_print_cursor(-1, 0);
}
} else if (key >= 32 && key <= 126) { // Printable characters
if (commandLength < MAX_COMMAND_LENGTH - 1) {
commandBuffer[commandLength++] = key;
print_char(key); // Display the key on the screen
}
}
keydown = true;
}
} else {
keydown = false;
}
}
printf("Thanks for playing!\n");
}

View File

@ -0,0 +1,127 @@
#include <stdint.h>
#include "strings.h"
#include "memory.h"
void prepend(uint8_t* array, uint8_t c) {
// Ensure that size is within bounds and there's space to prepend
int size = sizeof(array);
// Shift all elements to the right
for (int i = size; i > 0; i--) {
array[i] = array[i - 1];
}
// Insert the new character at the beginning
array[0] = c;
}
void append(uint8_t* array, uint8_t c) {
// Ensure that size is within bounds and there's space to append
int size = sizeof(array);
// Insert the new character at the end
array[size] = c;
}
void append_first(uint8_t* array, uint8_t c) {
// Shift all elements to the right
int size = sizeof(array);
for (int i = size - 1; i > 0; i--) {
array[i] = array[i - 1];
}
// Insert the new character at the beginning
array[0] = c;
}
void append_last(uint8_t* array, uint8_t c) {
int size = sizeof(array);
// Shift all elements to the left
for (int i = 0; i < size - 1; i++) {
array[i] = array[i + 1];
}
// Insert the new character at the end
array[0] = c;
}
char** split_string(const char* str, char delimiter) {
if (str == NULL) {
return NULL;
}
// Count the number of tokens
int* num_tokens = 1;
for (const char* p = str; *p; ++p) {
if (*p == delimiter) {
(*num_tokens)++;
}
}
printf("Tokens: %d", num_tokens);
// Allocate memory for the array of char*
char** tokens = (char**)malloc((*num_tokens + 1) * sizeof(char*)); // +1 for NULL terminator
if (tokens == NULL) {
return NULL;
}
// Allocate memory for each token and split the string
size_t start = 0;
size_t end = 0;
int index = 0;
while (str[end] != '\0') {
if (str[end] == delimiter) {
size_t length = end - start;
tokens[index] = (char*)malloc((length + 1) * sizeof(char)); // +1 for null terminator
if (tokens[index] == NULL) {
// Free previously allocated memory in case of failure
for (int i = 0; i < index; i++) {
free(tokens[i]);
}
free(tokens);
return NULL;
}
strncpy(tokens[index], &str[start], length);
tokens[index][length] = '\0';
index++;
start = end + 1;
}
end++;
}
// Add the last token
size_t length = end - start;
tokens[index] = (char*)malloc((length + 1) * sizeof(char)); // +1 for null terminator
if (tokens[index] == NULL) {
// Free previously allocated memory in case of failure
for (int i = 0; i < index; i++) {
free(tokens[i]);
}
free(tokens);
return NULL;
}
strncpy(tokens[index], &str[start], length);
tokens[index][length] = '\0';
tokens[index + 1] = NULL; // Null-terminate the array
return tokens;
}
// Function to free the memory allocated for the array of strings
void free_split_strings(char** tokens, int num_tokens) {
if (tokens == NULL) {
return;
}
for (int i = 0; i < num_tokens; i++) {
free(tokens[i]);
}
free(tokens);
}

View File

@ -0,0 +1,92 @@
#include "strings.h"
#include "stdint.h"
int int_strncmp(const char* s1, const char* s2, size_t n) {
while (n > 0) {
if (*s1 != *s2) {
return (uint8_t)*s1 - (uint8_t)*s2;
}
if (*s1 == '\0') {
return 0; // End of both strings
}
s1++;
s2++;
n--;
}
return 0; // First n characters are equal
}
int strcmp(const char *str1, const char *str2) {
while (*str1 && (*str1 == *str2)) {
str1++;
str2++;
}
return *(unsigned char *)str1 - *(unsigned char *)str2;
}
void strcpy(char *dest, const char *src) {
while (*src) {
*dest = *src;
dest++;
src++;
}
*dest = '\0'; // Ensure the destination string is null-terminated
}
size_t strlen(const char *str) {
const char *s = str;
while (*s) {
s++;
}
return s - str;
}
char *strncpy(char *dest, const char *src, size_t n) {
char *d = dest;
while (n && (*d++ = *src++)) {
n--;
}
if (n) {
while (--n) {
*d++ = '\0';
}
}
return dest;
}
char* strrchr(const char* str, char ch) {
char* result = NULL;
while (*str) {
if (*str == ch) {
result = (char*)str;
}
str++;
}
return result;
}
// In strings.c
int strncmp(const char *s1, const char *s2, size_t n) {
while (n && *s1 && (*s1 == *s2)) {
++s1;
++s2;
--n;
}
if (n == 0) {
return 0;
} else {
return (*(unsigned char *)s1 - *(unsigned char *)s2);
}
}

View File

@ -0,0 +1,85 @@
#include "window.h"
#include "print.h"
// Define the screen dimensions
#define SCREEN_WIDTH 80
#define SCREEN_HEIGHT 25
// Function to draw the border of the window
static void draw_border(const Window* win) {
// Set the color for the border
print_set_color(win->border_color, win->border_color);
// Draw top border
for (int i = 0; i < win->size_x; ++i) {
move_print_cursor(win->x + i, win->y);
print_char('#');
}
// Draw bottom border
for (int i = 0; i < win->size_x; ++i) {
move_print_cursor(win->x + i, win->y + win->size_y - 1);
print_char('#');
}
// Draw left and right borders
for (int i = 1; i < win->size_y - 1; ++i) {
move_print_cursor(win->x, win->y + i);
print_char('#');
move_print_cursor(win->x + win->size_x - 1, win->y + i);
print_char('#');
}
// Draw title
if (win->title[0] != '\0') {
print_set_color(win->border_color, win->background_color);
move_print_cursor(win->x + 1, win->y);
print_str(win->title);
}
}
// Function to draw the background of the window
static void draw_background(const Window* win) {
// Set the color for the background
print_set_color(win->background_color, win->background_color);
for (int i = 1; i < win->size_y - 1; ++i) {
for (int j = 1; j < win->size_x - 1; ++j) {
move_print_cursor(win->x + j, win->y + i);
print_char(' '); // Background character
}
}
}
// Function to create a simple window with border, background, and title
void create_window(Window* win, int x, int y, int size_x, int size_y, uint8_t border_color, uint8_t background_color, const char* title) {
win->x = x;
win->y = y;
win->size_x = size_x;
win->size_y = size_y;
win->border_color = border_color;
win->background_color = background_color;
// Copy title to window struct
for (int i = 0; i < WINDOW_TITLE_MAX_LENGTH - 1 && title[i] != '\0'; ++i) {
win->title[i] = title[i];
}
win->title[WINDOW_TITLE_MAX_LENGTH - 1] = '\0'; // Ensure null-termination
// Draw the window
draw_background(win);
draw_border(win);
}
// Function to print text inside the window
void print_text_in_window(const Window* win, int x, int y, const char* text) {
// Set the color for the text
print_set_color(PRINT_COLOR_WHITE, win->background_color);
for (int i = 0; text[i] != '\0'; ++i) {
if (x + i < win->size_x - 1 && y < win->size_y - 1) {
move_print_cursor(win->x + x + i, win->y + y);
print_char(text[i]);
}
}
}

View File

@ -0,0 +1,17 @@
// disk_io.h
#ifndef DISK_IO_H
#define DISK_IO_H
#include <stdint.h>
// Read sectors from the disk
int disk_read(uint32_t lba, void *buffer, uint32_t size);
// Optional: Write sectors to the disk (not implemented)
int disk_write(uint32_t lba, const void *buffer, uint32_t size);
int bios_read_sector(uint32_t lba, void *buffer);
#endif // DISK_IO_H

View File

@ -0,0 +1,58 @@
#ifndef FAT12_H
#define FAT12_H
#include <stdint.h>
#define FAT12_SIGNATURE 0xAA55
#define ROOT_DIR_ENTRIES 224
typedef struct {
uint8_t jmp_boot[3]; // Jump instruction
char oem_name[8]; // OEM Name
uint16_t bytes_per_sector;
uint8_t sectors_per_cluster;
uint16_t reserved_sectors;
uint8_t num_fats;
uint16_t root_entry_count;
uint16_t total_sectors_16;
uint8_t media;
uint16_t fat_size_16;
uint16_t sectors_per_track;
uint16_t num_heads;
uint32_t hidden_sectors;
uint32_t total_sectors_32;
uint8_t boot_signature;
uint32_t volume_id;
char volume_label[11];
char fs_type[8];
} __attribute__((packed)) fat12_boot_sector_t;
typedef struct {
char filename[8];
char extension[3];
uint8_t attributes;
uint8_t reserved;
uint8_t creation_time_tenths;
uint16_t creation_time;
uint16_t creation_date;
uint16_t last_access_date;
uint16_t first_cluster_high;
uint16_t last_mod_time;
uint16_t last_mod_date;
uint16_t first_cluster_low;
uint32_t file_size;
} __attribute__((packed)) fat12_dir_entry_t;
// FAT12 Filesystem initialization
int fat12_init(void);
// Read the root directory
int fat12_read_root_directory(void);
// Find a file in the root directory
int fat12_find_file(const char *filename, fat12_dir_entry_t *entry);
// Read a file (to be implemented)
int fat12_read_file(fat12_dir_entry_t *entry, void *buffer);
#endif // FAT12_H

View File

@ -0,0 +1,47 @@
#ifndef FS_H
#define FS_H
#include <stdint.h>
#include "fat12.h"
#include "disk_io.h"
#include "print.h"
#define BLOCK_SIZE 4096
#define MAX_FILE_NAME 255
#define MAX_FILES 128
// Declarations for block operations
void write_block(uint32_t block_index, const void *data, uint32_t size);
void read_block(uint32_t block_index, void *buffer, uint32_t size);
// Structure of the superblock
typedef struct {
uint32_t total_blocks;
uint32_t free_blocks;
uint32_t total_inodes;
uint32_t free_inodes;
} Superblock;
// Structure of an inode
typedef struct {
char name[MAX_FILE_NAME];
uint32_t size;
uint32_t data_block_start;
uint32_t permissions;
} Inode;
// Structure of a directory entry
typedef struct {
char name[MAX_FILE_NAME];
uint32_t inode_index;
} DirectoryEntry;
// Filesystem operations
void fs_init();
int fs_create_file(const char *name, uint32_t size);
int fs_write_file(const char *name, const void *data, uint32_t size);
int fs_read_file(const char *name, void *buffer, uint32_t size);
int fs_delete_file(const char *name);
void list_files();
#endif // FS_H

View File

@ -0,0 +1,25 @@
#ifndef GAME_H
#define GAME_H
#include "stdint.h"
// Define the maximum length of a command
#define MAX_COMMAND_LENGTH 128
// Game state structure
typedef struct {
int current_room;
bool game_active;
} GameState;
// Function to initialize and run the game
void create_game();
// Function to handle the command input by the player
void handle_command(const char* command);
// Function to print the current prompt
void print_prompt();
#endif

View File

@ -0,0 +1,46 @@
#ifndef IDT_H
#define IDT_H
#include <stdint.h>
struct idt_entry_t {
uint16_t offset_low; // Lower 16 bits of ISR address
uint16_t selector; // Kernel segment selector
uint8_t ist; // Interrupt Stack Table (for 64-bit)
uint8_t type_attr; // Type and attributes (P, DPL, S, Type)
uint16_t offset_mid; // Middle 16 bits of ISR address
uint32_t offset_high; // Upper 32 bits of ISR address (for 64-bit)
uint32_t zero; // Reserved
} __attribute__((packed));
struct idt_ptr_t {
uint16_t limit; // Size of the IDT (bytes - 1)
uint64_t base; // Base address of the IDT
} __attribute__((packed));
#define ERROR_DIVIDE_BY_ZERO 0
#define ERROR_DEBUG 1
#define ERROR_NMI 2
#define ERROR_BREAKPOINT 3
#define ERROR_OVERFLOW 4
#define ERROR_BOUND 5
#define ERROR_INVALID_OP 6
#define ERROR_DEVICE_NOT_AVAIL 7
#define ERROR_DOUBLE_FAULT 8
#define ERROR_COPROCESSOR_OVERRUN 9
#define ERROR_INVALID_TSS 10
#define ERROR_SEGMENT_NOT_PRESENT 11
#define ERROR_STACK_SEGMENT 12
#define ERROR_GENERAL_PROTECTION 13
#define ERROR_PAGE_FAULT 14
#define FILESYSTEM_ERROR 15 // Assuming this relates to your filesystem
#define ERROR_RESERVED 16 // Not implemented error
// Function prototypes
void setup_idt_entry(int index, void (*handler)(), uint16_t selector, uint8_t type_attr);
void init_idt();
#endif

View File

@ -0,0 +1,11 @@
// io.h
#ifndef IO_H
#define IO_H
#include "stdint.h"
void outb(uint16_t port, uint8_t value);
uint8_t inb(uint16_t port);
#endif // IO_H

View File

@ -0,0 +1,18 @@
#ifndef KEYDRIVER_H
#define KEYDRIVER_H
#define KEYBOARD_BUFFER_SIZE 128
// Initializes the keyboard driver
void init_keyboard_driver();
// Reads a single character from the keyboard and stores it in the buffer
char read_key();
// Gets the current index of the buffer
unsigned int get_buffer_index();
// Retrieves the contents of the keyboard buffer
const char* get_keyboard_buffer();
#endif // KEYDRIVER_H

View File

@ -0,0 +1,9 @@
#pragma once
#include "stdint.h"
void* memcpy(void* dst, const void* src, uint16_t num);
void* memset(void* ptr, int value, uint16_t num);
int memcmp(const void* ptr1, const void* ptr2, uint16_t num);
void* malloc(size_t size);
void free(void* ptr);

View File

@ -0,0 +1,41 @@
#pragma once
#include <stdint.h>
#include <stddef.h>
#define MAX_STRING_LENGTH 100
typedef struct {
int x;
int y;
} CursorPosition;
enum {
PRINT_COLOR_BLACK = 0,
PRINT_COLOR_BLUE = 1,
PRINT_COLOR_GREEN = 2,
PRINT_COLOR_CYAN = 3,
PRINT_COLOR_RED = 4,
PRINT_COLOR_MAGENTA = 5,
PRINT_COLOR_BROWN = 6,
PRINT_COLOR_LIGHT_GRAY = 7,
PRINT_COLOR_DARK_GRAY = 8,
PRINT_COLOR_LIGHT_BLUE = 9,
PRINT_COLOR_LIGHT_GREEN = 10,
PRINT_COLOR_LIGHT_CYAN = 11,
PRINT_COLOR_LIGHT_RED = 12,
PRINT_COLOR_PINK = 13,
PRINT_COLOR_YELLOW = 14,
PRINT_COLOR_WHITE = 15,
};
void sscanf(const char *str, const char *format, char *filename, char *content);
int my_sscanf(const char *input, const char *format, char *output);
void print_clear();
void print_char(char character);
void print_str(char* string);
void printf(const char* format, ...);
void print_set_color(uint8_t foreground, uint8_t background);
void move_print_cursor(int x, int y);
void offset_print_cursor(int x, int y);
void print_hex(unsigned int num);
CursorPosition get_print_cursor_pos();

View File

@ -0,0 +1,23 @@
#pragma once
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef signed short int16_t;
typedef unsigned short 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 uint32_t size_t; // Adjust size based on your platform; 32-bit or 64-bit
typedef uint8_t bool;
#define false 0
#define true 1
#define NULL ((void*)0)
#define min(a,b) ((a) < (b) ? (a) : (b))
#define max(a,b) ((a) > (b) ? (a) : (b))
// Define size_t as an unsigned integer type for sizes and indices

View File

@ -0,0 +1,49 @@
#ifndef BUFFER_OPS_H
#define BUFFER_OPS_H
#include <stdint.h>
/**
* @brief Inserts a character at the beginning of the array.
* Shifts all elements to the right and removes the last element if the array is full.
*
* @param array Pointer to the array.
* @param c Character to prepend.
*/
void prepend(uint8_t* array, uint8_t c);
/**
* @brief Inserts a character at the end of the array.
* Shifts all elements to the left and removes the first element if the array is full.
*
* @param array Pointer to the array.
* @param c Character to append.
*/
void append(uint8_t* array, uint8_t c);
/**
* @brief Inserts a character at the beginning of the array.
* Shifts all elements to the right. Note that this function assumes there is space
* at the beginning of the array.
*
* @param array Pointer to the array.
* @param c Character to insert at the beginning.
*/
void append_first(uint8_t* array, uint8_t c);
/**
* @brief Inserts a character at the end of the array.
* Shifts all elements to the left. Note that this function assumes there is space
* at the end of the array.
*
* @param array Pointer to the array.
* @param c Character to insert at the end.
*/
void append_last(uint8_t* array, uint8_t c);
char** split_string(const char* str, char delimiter, int* num_tokens);
void free_split_strings(char** tokens, int num_tokens);
#endif // BUFFER_OPS_H

View File

@ -0,0 +1,12 @@
#include <stdint.h>
#include <stddef.h>
int strcmp(const char *str1, const char *str2);
size_t strlen(const char *str);
char *strncpy(char *dest, const char *src, size_t n);
int int_strncmp(const char* s1, const char* s2, size_t n);
void strcpy(char *dest, const char *src);
char* strrchr(const char* str, char ch);
int strncmp(const char *s1, const char *s2, size_t n);

View File

@ -0,0 +1,22 @@
#ifndef VECTOR_H
#define VECTOR_H
#include <stddef.h>
// Define the vector structure
typedef struct {
void** items; // Pointer to the array of items
size_t capacity; // Maximum number of items the vector can hold
size_t size; // Current number of items in the vector
} vector;
// Function prototypes
vector* vector_create();
void vector_destroy(vector* v);
int vector_push_back(vector* v, void* item);
void* vector_get(vector* v, size_t index);
int vector_set(vector* v, size_t index, void* item);
size_t vector_size(vector* v);
int vector_resize(vector* v, size_t new_capacity);
#endif

View File

@ -0,0 +1,6 @@
#include "stdint.h"
#include "io.h"
void set_cursor_position(int x, int y);
void move_cursor(int x, int y);

View File

@ -0,0 +1,19 @@
#pragma once
#include <stdint.h>
#define WINDOW_TITLE_MAX_LENGTH 20
typedef struct {
int x;
int y;
int size_x;
int size_y;
uint8_t border_color;
uint8_t background_color;
char title[WINDOW_TITLE_MAX_LENGTH];
} Window;
// Function to create and draw a simple window
void create_window(Window* win, int x, int y, int size_x, int size_y, uint8_t border_color, uint8_t background_color, const char* title);
void print_text_in_window(const Window* win, int x, int y, const char* text);

View File

@ -0,0 +1,7 @@
set timeout=0
set default=0
menuentry "my os" {
multiboot2 /boot/kernel.bin
boot
}

Binary file not shown.

View File

@ -0,0 +1,16 @@
ENTRY(start)
SECTIONS
{
. = 1M;
.boot :
{
KEEP(*(.multiboot_header))
}
.text :
{
*(.text)
}
}