15 Commits

Author SHA1 Message Date
23cb50a73f Create ata.h
implement the base ata pio mode driver so that the filesystems like fat16, fat32 work. This is the header for that. It will need a iso9660 driver for cdrom etc optical media
2026-01-18 17:44:18 -08:00
b6c158957e Merge pull request #95 from shoshta73/qol
[misc] add editorconfig, clangd config and clang-format config
2026-01-18 16:46:05 -08:00
Borna Šoštarić
a7b0d1152f add rules for formatting consecutives 2026-01-18 10:54:18 +01:00
Borna Šoštarić
e38f1aa2ee add .clang-format 2026-01-18 10:40:34 +01:00
Borna Šoštarić
78d5e9a7ab added editorconfig file 2026-01-18 10:18:23 +01:00
Borna Šoštarić
daead5ee57 add clangd config file 2026-01-18 10:15:38 +01:00
Borna Šoštarić
4fb81d2e57 add compile_commands.json genereation 2026-01-18 10:10:39 +01:00
19f7c7b213 Merge pull request #93 from vmttmv/fix/91-header-cleanup
Remove types.c/.h, use klibc headers, amend stdbool.h, reimplement cpuid()
2026-01-13 07:40:03 -08:00
bc9d84a93e Merge branch 'main' into fix/91-header-cleanup 2026-01-13 07:39:46 -08:00
9066ceaddb Merge pull request #94 from vmttmv/fix/92-paging
Fix PDE/PTE definitions, header cleanup
2026-01-13 07:29:27 -08:00
vmttmv
3b67e81ed0 Fix PDE/PTE definitions, header cleanup
- Fixes PDE/PTE definitions in kernel/paging.h
- removes memset declaration from kernel/utils.h, uses klibc string.h as
needed
2026-01-12 04:02:15 +02:00
vmttmv
841892398a Remove types.c/.h, use klibc headers, amend stdbool.h, reimplement cpuid() 2026-01-12 02:43:37 +02:00
86608ef48c Merge pull request #90 from gbowne1/gbowne1-patch-2
Fix extern declaration for disk_read_sector function
2026-01-10 21:31:34 -08:00
c0e7ab6be0 Fix k_memcmp return logic and add disk_read_sector
Refactor k_memcmp to return correct difference and add disk_read_sector function.
2026-01-08 21:10:35 -08:00
f78bc27f35 Fix extern declaration for disk_read_sector function 2026-01-08 21:03:10 -08:00
18 changed files with 156 additions and 128 deletions

24
.clang-format Normal file
View File

@@ -0,0 +1,24 @@
BasedOnStyle: Google
IndentWidth: 4
TabWidth: 4
UseTab: Never
ColumnLimit: 80
DerivePointerAlignment: false
PointerAlignment: Right
ReferenceAlignment: Right
AlignConsecutiveMacros: Consecutive
AlignTrailingComments:
Kind: Always
OverEmptyLines: 0
IncludeBlocks: Regroup
IncludeCategories:
# Std headers
- Regex: '<[[:alnum:]_.]+>'
Priority: 2
# Other headers
- Regex: '.*'
Priority: 1

6
.clangd Normal file
View File

@@ -0,0 +1,6 @@
CompileFlags:
CompilationDatabase: build
Diagnostics:
UnusedIncludes: Strict
MissingIncludes: Strict

12
.editorconfig Normal file
View File

@@ -0,0 +1,12 @@
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[Makefile]
indent_style = tab
indent_size = 8
tab_width = 8

View File

@@ -18,9 +18,9 @@ KERNEL_OBJ += $(patsubst kernel/%.asm, $(BUILD_DIR)/asm_%.o, $(KERNEL_ASM_SRC))
KLIBC_SRC = $(wildcard klibc/src/*.c) KLIBC_SRC = $(wildcard klibc/src/*.c)
KLIBC_OBJ = $(patsubst klibc/src/%.c, $(BUILD_DIR)/klibc/%.o, $(KLIBC_SRC)) KLIBC_OBJ = $(patsubst klibc/src/%.c, $(BUILD_DIR)/klibc/%.o, $(KLIBC_SRC))
.PHONY: all stage1 stage2 kernel compile-commands $(BUILD_DIR)/compile_commands.json run gdb clean clean-cross clean-all
all: $(DISK_IMG) all: $(DISK_IMG)
.PHONY: stage1 stage2 kernel run gdb clean
stage1: $(BUILD_DIR) stage1: $(BUILD_DIR)
$(AS) $(ASFLAGS) -o $(BUILD_DIR)/$@.o bootloader/$@.asm $(AS) $(ASFLAGS) -o $(BUILD_DIR)/$@.o bootloader/$@.asm
$(LD) -Ttext=0x7c00 -melf_i386 -o $(BUILD_DIR)/$@.elf $(BUILD_DIR)/$@.o $(LD) -Ttext=0x7c00 -melf_i386 -o $(BUILD_DIR)/$@.elf $(BUILD_DIR)/$@.o
@@ -57,6 +57,10 @@ $(BUILD_DIR):
mkdir -p $@ mkdir -p $@
mkdir -p $(BUILD_DIR)/klibc mkdir -p $(BUILD_DIR)/klibc
compile-commands: $(BUILD_DIR)/compile_commands.json
$(BUILD_DIR)/compile_commands.json: $(BUILD_DIR)
bear --output $@ -- make -B
run: run:
qemu-system-i386 -s -S $(DISK_IMG) qemu-system-i386 -s -S $(DISK_IMG)

43
kernel/ata.h Normal file
View File

@@ -0,0 +1,43 @@
#ifndef ATA_H
#define ATA_H
#include <stdint.h>
#include <stdbool.h>
/* ATA I/O ports */
#define ATA_PRIMARY_IO 0x1F0
#define ATA_PRIMARY_CTRL 0x3F6
/* ATA registers */
#define ATA_REG_DATA 0x00
#define ATA_REG_ERROR 0x01
#define ATA_REG_FEATURES 0x01
#define ATA_REG_SECCOUNT0 0x02
#define ATA_REG_LBA0 0x03
#define ATA_REG_LBA1 0x04
#define ATA_REG_LBA2 0x05
#define ATA_REG_HDDEVSEL 0x06
#define ATA_REG_COMMAND 0x07
#define ATA_REG_STATUS 0x07
/* ATA commands */
#define ATA_CMD_READ_PIO 0x20
#define ATA_CMD_WRITE_PIO 0x30
#define ATA_CMD_IDENTIFY 0xEC
/* Status flags */
#define ATA_SR_BSY 0x80
#define ATA_SR_DRDY 0x40
#define ATA_SR_DRQ 0x08
#define ATA_SR_ERR 0x01
/* Drive select */
#define ATA_MASTER 0x00
#define ATA_SLAVE 0x10
/* Public API */
bool ata_init(void);
bool ata_read_sector(uint32_t lba, uint8_t* buffer);
bool ata_write_sector(uint32_t lba, const uint8_t* buffer);
#endif

View File

@@ -3,6 +3,14 @@
#include "terminal.h" #include "terminal.h"
#include "utils.h" #include "utils.h"
void cpuid(uint32_t leaf, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) {
__asm__(
"cpuid"
: "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
: "a"(leaf)
);
}
// Helper to print a labeled decimal value // Helper to print a labeled decimal value
void print_val(const char* label, uint32_t val) { void print_val(const char* label, uint32_t val) {
char buf[12]; char buf[12];

View File

@@ -15,9 +15,16 @@ static uint8_t g_sector_buffer[FAT12_SECTOR_SIZE];
static int k_memcmp(const void *s1, const void *s2, uint32_t n) { static int k_memcmp(const void *s1, const void *s2, uint32_t n) {
const uint8_t *p1 = (const uint8_t *)s1; const uint8_t *p1 = (const uint8_t *)s1;
const uint8_t *p2 = (const uint8_t *)s2; const uint8_t *p2 = (const uint8_t *)s2;
for (uint32_t i = 0; i < n; i++) { for (uint32_t i = 0; i < n; i++) {
if (p1[i] != p2[i]) return p1[i] - p2[i]; if (p1[i] != p2[i]) {
// Correct way to return the difference:
// If p1[i] > p2[i], returns positive.
// If p1[i] < p2[i], returns negative.
return (int)p1[i] - (int)p2[i];
}
} }
return 0; return 0;
} }
@@ -182,3 +189,8 @@ uint32_t fat12_read(file_t *file, uint8_t *buffer, uint32_t bytes_to_read) {
return total_read; return total_read;
} }
int disk_read_sector(uint32_t lba, uint8_t *buffer) {
// For now, do nothing and return success
return 0;
}

View File

@@ -58,7 +58,7 @@ typedef struct {
// You must implement this in your disk driver (e.g., floppy.c) // You must implement this in your disk driver (e.g., floppy.c)
// Returns 0 on success, non-zero on error. // Returns 0 on success, non-zero on error.
extern int disk_read_sector(uint32_t lba, uint8_t *buffer); int disk_read_sector(uint32_t lba, uint8_t *buffer);
void fat12_init(); void fat12_init();
file_t fat12_open(const char *filename); file_t fat12_open(const char *filename);

View File

@@ -1,7 +1,7 @@
#ifndef IRQ_H #ifndef IRQ_H
#define IRQ_H #define IRQ_H
#include "types.h" #include <stdint.h>
void irq_remap(void); void irq_remap(void);
void irq_install(void); void irq_install(void);

View File

@@ -1,3 +1,4 @@
#include <stdbool.h>
#include "terminal.h" #include "terminal.h"
#include "serial.h" #include "serial.h"
#include "isr.h" #include "isr.h"

View File

@@ -1,21 +1,17 @@
#include "paging.h"
#include "io.h"
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <string.h>
#include "io.h"
#include "paging.h"
page_directory_entry_t *page_directory = (page_directory_entry_t *)0x200000; page_directory_entry_t *page_directory = (page_directory_entry_t *)0x200000;
page_table_entry_t *page_table = (page_table_entry_t *)0x201000; page_table_entry_t *page_table = (page_table_entry_t *)0x201000;
page_table_entry_t *heap_page_table = (page_table_entry_t *)0x202000;
// Helper function to set up the page directory entry // Helper function to set up the page directory entry
void set_page_directory(page_directory_entry_t *dir) { void set_page_directory(page_directory_entry_t *dir) {
for (int i = 0; i < PAGE_DIRECTORY_SIZE; i++) { // Set first PDE
dir[i].present = 0;
}
dir[0].present = 1; dir[0].present = 1;
dir[0].rw = 1; dir[0].rw = 1;
dir[0].user = 0; dir[0].addr = (uint32_t)page_table >> 12;
dir[0].frame = (uint32_t)page_table >> 12;
} }
// Helper function to set up the page table entry // Helper function to set up the page table entry
@@ -23,12 +19,8 @@ void set_page_table(page_table_entry_t *table) {
for (int i = 0; i < PAGE_TABLE_SIZE; i++) { for (int i = 0; i < PAGE_TABLE_SIZE; i++) {
// Set up page table entries with identity mapping // Set up page table entries with identity mapping
table[i].present = 1; table[i].present = 1;
table[i].rw = 1; // Read/Write table[i].rw = 1; // Read/Write
table[i].user = 0; // Kernel mode table[i].addr = i; // Identity mapping
table[i].write_through = 0;
table[i].cache_disabled = 0;
table[i].accessed = 0;
table[i].frame = i; // Identity mapping
} }
} }
@@ -47,26 +39,13 @@ void enable_paging() {
// Initialize paging: set up the page directory and enable paging // Initialize paging: set up the page directory and enable paging
void paging_init() { void paging_init() {
// Zero out the tables
memset(page_directory, 0x00, PAGE_DIRECTORY_SIZE * sizeof *page_directory);
memset(page_table, 0x00, PAGE_TABLE_SIZE * sizeof *page_table);
// Set up identity-mapped page directory + table // Set up identity-mapped page directory + table
set_page_directory(page_directory); set_page_directory(page_directory);
set_page_table(page_table); set_page_table(page_table);
// === Set up heap mapping at 0xC0100000 ===
for (int i = 0; i < PAGE_TABLE_SIZE; i++) {
heap_page_table[i].present = 1;
heap_page_table[i].rw = 1;
heap_page_table[i].user = 0;
heap_page_table[i].write_through = 0;
heap_page_table[i].cache_disabled = 0;
heap_page_table[i].accessed = 0;
heap_page_table[i].frame = (256 + i); // Start physical heap at 1MB (256*4KB = 1MB)
}
// Index 772 = 0xC0100000 / 4MB
page_directory[772].present = 1;
page_directory[772].rw = 1;
page_directory[772].user = 0;
page_directory[772].frame = (uint32_t)heap_page_table >> 12;
enable_paging(); enable_paging();
} }

View File

@@ -10,31 +10,31 @@
// Page Directory and Page Table structure // Page Directory and Page Table structure
typedef struct { typedef struct {
uint32_t present : 1; // Present bit (1: page is present in memory) uint32_t present : 1; // Present bit (1: page is present in memory)
uint32_t rw : 1; // Read-Write bit (1: page is read-write) uint32_t rw : 1; // Read-Write bit (1: page is read-write)
uint32_t user : 1; // User-supervisor bit (1: user mode access) uint32_t user : 1; // User-supervisor bit (1: user mode access)
uint32_t write_through : 1; // Write-through cache uint32_t write_through : 1; // Write-through cache
uint32_t cache_disabled : 1; // Cache disabled uint32_t cache_disabled : 1; // Cache disabled
uint32_t accessed : 1; // Accessed bit uint32_t accessed : 1; // Accessed bit
uint32_t reserved : 1; // Reserved bit uint32_t dirty : 1; // Dirty bit
uint32_t page_size : 1; // Page size (0: 4KB, 1: 4MB) uint32_t attribute : 1; // Page size (0: 4KB, 1: 4MB)
uint32_t global : 1; // Global page (can be used across different processes) uint32_t global : 1; // Global page (can be used across different processes)
uint32_t available : 3; // Available bits for the system uint32_t reserved : 3; // Unused
uint32_t frame : 20; // Frame address (physical address) uint32_t addr : 20; // Page frame address (physical address)
} __attribute__((packed)) page_table_entry_t; } __attribute__((packed)) page_table_entry_t;
// Define page directory entry // Define page directory entry
typedef struct { typedef struct {
uint32_t present : 1; uint32_t present : 1; // Present bit (1: PTE is present in memory)
uint32_t rw : 1; uint32_t rw : 1; // Read-Write bit (1: pages are read-write)
uint32_t user : 1; uint32_t user : 1; // User-supervisor bit (1: user mode access)
uint32_t write_through : 1; uint32_t write_through : 1; // Write-through cache
uint32_t cache_disabled : 1; uint32_t cache_disabled : 1; // Cache disabled
uint32_t accessed : 1; uint32_t accessed : 1; // Accessed bit
uint32_t reserved : 1; uint32_t available : 1; // Unused
uint32_t zero : 5; // Must be zero for page directory uint32_t page_size : 1; // Page size (0: 4KB, 1: 4MB)
uint32_t reserved_2 : 7; // Reserved bits uint32_t available_2 : 4; // Unused
uint32_t frame : 20; // Frame address of the page table uint32_t addr : 20; // Page table address
} __attribute__((packed)) page_directory_entry_t; } __attribute__((packed)) page_directory_entry_t;
extern page_directory_entry_t *page_directory; extern page_directory_entry_t *page_directory;

View File

@@ -1,7 +1,7 @@
#ifndef PRINT_H #ifndef PRINT_H
#define PRINT_H #define PRINT_H
#include "types.h" #include <stdint.h>
void print_string(const char *str); void print_string(const char *str);
void my_printf(const char *format, ...); void my_printf(const char *format, ...);

View File

@@ -1,9 +1,8 @@
#include <stdbool.h>
#include <string.h>
#include "malloc.h" #include "malloc.h"
#include "print.h" #include "print.h"
#include "threading.h" #include "threading.h"
#include "types.h"
#include "utils.h"
#include <stdint.h>
#define MAX_THREADS 16 // Maximum number of threads #define MAX_THREADS 16 // Maximum number of threads
#define THREAD_STACK_SIZE 8192 // Stack size for each thread #define THREAD_STACK_SIZE 8192 // Stack size for each thread

View File

@@ -1 +0,0 @@
#include "types.h"

View File

@@ -1,61 +0,0 @@
#ifndef TYPES_H
#define TYPES_H
// ----------------------------
// Fixed-width integer types
// ----------------------------
typedef unsigned char uint8_t;
typedef signed char int8_t;
typedef unsigned short uint16_t;
typedef signed short int16_t;
typedef unsigned int uint32_t;
typedef signed int int32_t;
typedef unsigned long long uint64_t;
typedef signed long long int64_t;
// ----------------------------
// Boolean & NULL definitions
// ----------------------------
#ifndef __cplusplus
typedef enum { false = 0, true = 1 } bool;
#endif
#ifndef NULL
#define NULL ((void*)0)
#endif
// ----------------------------
// OS subsystem types
// ----------------------------
typedef int32_t ssize_t;
typedef uint32_t phys_addr_t; // Physical address
typedef uint32_t virt_addr_t; // Virtual address
typedef uint32_t pid_t; // Process ID
typedef uint32_t tid_t; // Thread ID
// ----------------------------
// Bitfield & utility macros
// ----------------------------
#define BIT(n) (1U << (n))
#define BITS(m, n) (((1U << ((n) - (m) + 1)) - 1) << (m))
// Align value to next multiple of alignment
#define ALIGN_UP(val, align) (((val) + ((align)-1)) & ~((align)-1))
#define ALIGN_DOWN(val, align) ((val) & ~((align)-1))
// ----------------------------
// Attributes for structures
// ----------------------------
#define PACKED __attribute__((packed))
#define ALIGN(x) __attribute__((aligned(x)))
// ----------------------------
// Likely/unlikely branch hints
// (for future optimization use)
// ----------------------------
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#endif // TYPES_H

View File

@@ -3,14 +3,10 @@
#include <stddef.h> #include <stddef.h>
#include "types.h"
// Convert integer to string (base is typically 10, 16, etc.) // Convert integer to string (base is typically 10, 16, etc.)
char* itoa(int value, char* str, int base); char* itoa(int value, char* str, int base);
// Convert unsigned integer to string (base is typically 10, 16, etc.) // Convert unsigned integer to string (base is typically 10, 16, etc.)
char* utoa(unsigned int value, char* str, int base); char* utoa(unsigned int value, char* str, int base);
void *memset(void *dest, int value, size_t len);
#endif // UTILS_H #endif // UTILS_H

View File

@@ -1,6 +1,12 @@
#ifndef CLASSICOS_KLIBC_STDBOOL_H #ifndef CLASSICOS_KLIBC_STDBOOL_H
#define CLASSICOS_KLIBC_STDBOOL_H #define CLASSICOS_KLIBC_STDBOOL_H
typedef enum { false = 0, true = 1 } bool; #ifndef __cplusplus
#define bool _Bool
#define true 1
#define false 0
#endif
#define __bool_true_false_are_defined 1
#endif // CLASSICOS_KLIBC_STDBOOL_H #endif // CLASSICOS_KLIBC_STDBOOL_H