diff --git a/bootloader/linker.ld b/bootloader/linker.ld index 15e5ab9..e422078 100644 --- a/bootloader/linker.ld +++ b/bootloader/linker.ld @@ -14,4 +14,14 @@ SECTIONS { *(.bss*) *(COMMON) } + + .stack (NOLOAD) : { + . = ALIGN(4); + . = . + 0x1000; + } + + .heap (NOLOAD) : { + . = ALIGN(4); + . = . + 0x10000; + } } diff --git a/kernel/cpu.c b/kernel/cpu.c index 1098dd3..96aa335 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -2,6 +2,7 @@ #include "serial.h" #include "terminal.h" #include "utils.h" +#include "print.h" void cpuid(uint32_t function, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) { asm volatile ( diff --git a/kernel/fs.c b/kernel/fat12.c similarity index 51% rename from kernel/fs.c rename to kernel/fat12.c index 2496839..1335974 100644 --- a/kernel/fs.c +++ b/kernel/fat12.c @@ -1,5 +1,5 @@ -#include "fs.h" +#include "fat12.h" -void fs_init() { +void fat12_init() { // Filesystem initialization code } diff --git a/kernel/fat12.h b/kernel/fat12.h new file mode 100644 index 0000000..e10dac0 --- /dev/null +++ b/kernel/fat12.h @@ -0,0 +1,47 @@ +#ifndef FAT12_H +#define FAT12_H + +#include /* Include standard integer types */ +#include /* Include standard I/O library */ +#include /* Include standard library */ + +#define FAT12_SECTOR_SIZE 512 /* Sector size for FAT12 */ +#define FAT12_MAX_FILES 128 /* Maximum number of files in root directory */ +#define FAT12_ROOT_DIR_SECTORS 1 /* Number of sectors for root directory */ + +typedef struct { + uint8_t jump[3]; /* Jump instruction for boot */ + char oem[8]; /* OEM name */ + uint16_t bytes_per_sector; /* Bytes per sector */ + uint8_t sectors_per_cluster; /* Sectors per cluster */ + uint16_t reserved_sectors; /* Reserved sectors count */ + uint8_t num_fats; /* Number of FATs */ + uint16_t max_root_dir_entries; /* Max entries in root directory */ + uint16_t total_sectors; /* Total sectors */ + uint8_t media_descriptor; /* Media descriptor */ + uint16_t fat_size; /* Size of each FAT */ + uint16_t sectors_per_track; /* Sectors per track */ + uint16_t num_heads; /* Number of heads */ + uint32_t hidden_sectors; /* Hidden sectors count */ + uint32_t total_sectors_large; /* Total sectors for large disks */ +} __attribute__((packed)) FAT12_BootSector; /* Packed structure for boot sector */ + +typedef struct { + char name[11]; /* File name (8.3 format) */ + uint8_t attr; /* File attributes */ + uint16_t reserved; /* Reserved */ + uint16_t time; /* Time of last write */ + uint16_t date; /* Date of last write */ + uint16_t start_cluster; /* Starting cluster number */ + uint32_t file_size; /* File size in bytes */ +} __attribute__((packed)) FAT12_DirEntry; /* Directory entry structure */ + +void initialize_fat12(const char *disk_image); /* Function to initialize FAT12 */ +void read_fat12(const char *disk_image); /* Function to read FAT12 */ +void write_fat12(const char *disk_image); /* Function to write FAT12 */ +void list_files(const char *disk_image); /* Function to list files in root directory */ +void read_file(const char *disk_image, const char *filename); /* Function to read a file */ +void write_file(const char *disk_image, const char *filename, const uint8_t *data, size_t size); /* Function to write a file */ + +#endif +/* FAT12_H */ diff --git a/kernel/fs.h b/kernel/fs.h deleted file mode 100644 index 7eb878c..0000000 --- a/kernel/fs.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef FS_H -#define FS_H - -void fs_init(); - -#endif // FS_H diff --git a/kernel/kmalloc.c b/kernel/kmalloc.c index 6e54aa2..7ccc46e 100644 --- a/kernel/kmalloc.c +++ b/kernel/kmalloc.c @@ -1,6 +1,8 @@ #include "kmalloc.h" #include "terminal.h" // Optional: for debug output +#define HEAP_END 0xC0100000 + static uint32_t current_heap = 0; // Initialize the allocator with a starting heap address @@ -32,7 +34,18 @@ void* kmalloc_aligned(size_t size, uint32_t alignment) { current_heap = (current_heap + alignment) & ~(alignment - 1); } + if (current_heap + size > HEAP_END) { + terminal_write("kmalloc_aligned: Out of memory!\n"); + return 0; + } + void* addr = (void*)current_heap; current_heap += size; return addr; } + +void kfree(void* ptr) { + // In a bump allocator, we cannot free individual blocks. + // We can reset the allocator to the initial state. + current_heap = 0; // Reset the heap pointer +} diff --git a/kernel/malloc.c b/kernel/malloc.c index dd11d8e..96f739f 100644 --- a/kernel/malloc.c +++ b/kernel/malloc.c @@ -55,7 +55,15 @@ void mark_as_free(void *ptr) { block->next = block->next->next; } - // TODO: Implement coalescing with previous block + // Coalesce with previous block if it's free + struct memory_block *prev = free_blocks; + while (prev && prev->next != block) { + prev = prev->next; + } + if (prev && prev->is_free) { + prev->size += block->size + sizeof(struct memory_block); + prev->next = block->next; + } } void *malloc(size_t size) @@ -94,4 +102,4 @@ void free(void *ptr) // Mark the block as free mark_as_free(block); -} \ No newline at end of file +} diff --git a/kernel/print.c b/kernel/print.c index 2ab9055..d5a829f 100644 --- a/kernel/print.c +++ b/kernel/print.c @@ -1,6 +1,84 @@ #include +#include +#include "print.h" -void print_string(const char *str) -{ - printf("%s", str); +void my_putchar(char ch) { + // Write a single character to standard output + // In a freestanding environment, you might need to implement this differently + // For now, we will use the standard putchar for demonstration + // Replace this with your own implementation if needed + putchar(ch); +} + +void print_string(const char *str) { + // Simple implementation to print a string + while (*str) { + my_putchar(*str++); + } +} + +void my_printf(const char *format, ...) { + va_list args; + va_start(args, format); + + while (*format) { + if (*format == '%') { + format++; // Move to the next character after '%' + switch (*format) { + case 's': { // String + char *str = va_arg(args, char *); + print_string(str); + break; + } + case 'd': { // Integer + int num = va_arg(args, int); + char buffer[20]; // Buffer to hold the string representation + snprintf(buffer, sizeof(buffer), "%d", num); + print_string(buffer); + break; + } + case 'c': { // Character + char ch = (char)va_arg(args, int); // Promote char to int + my_putchar(ch); + break; + } + default: + my_putchar('%'); // Print the '%' if no valid format specifier + my_putchar(*format); + break; + } + } else { + my_putchar(*format); + } + format++; + } + + va_end(args); +} + + +void print_hex(unsigned int num) { + // Buffer to hold the hexadecimal representation + char buffer[9]; // 8 hex digits + null terminator + buffer[8] = '\0'; // Null-terminate the string + + for (int i = 7; i >= 0; i--) { + int digit = num & 0xF; // Get the last 4 bits + buffer[i] = (digit < 10) ? (digit + '0') : (digit - 10 + 'A'); // Convert to hex character + num >>= 4; // Shift right by 4 bits + } + + // Print the buffer, skipping leading zeros + int leading_zero = 1; + for (int i = 0; i < 8; i++) { + if (buffer[i] != '0') { + leading_zero = 0; // Found a non-zero digit + } + if (!leading_zero) { + my_putchar(buffer[i]); + } + } + if (leading_zero) { + my_putchar('0'); // If all were zeros, print a single '0' + } } \ No newline at end of file diff --git a/kernel/print.h b/kernel/print.h index 66454fb..61c08ae 100644 --- a/kernel/print.h +++ b/kernel/print.h @@ -2,5 +2,8 @@ #define PRINT_H void print_string(const char *str); +void my_printf(const char *format, ...); +void print_hex(unsigned int num); +void my_putchar(char ch); #endif diff --git a/kernel/shell.c b/kernel/shell.c index ee445f1..43b261c 100644 --- a/kernel/shell.c +++ b/kernel/shell.c @@ -1,16 +1,18 @@ #include "shell.h" #include "keyboard.h" #include "terminal.h" +#include "print.h" #include #include +#include "string_utils.h" void execute(char *input) { - if (strcmp(input, "help") == 0) { - printf("Available commands: help, clear, exit\n"); - } else if (strcmp(input, "clear") == 0) { + if (my_strcmp(input, "help") == 0) { + my_printf("Available commands: help, clear, exit\n"); + } else if (my_strcmp(input, "clear") == 0) { terminal_clear(); } else { - printf("Unknown command: %s\n", input); + my_printf("Unknown command: %s\n", input); } } @@ -22,7 +24,7 @@ void shell_loop() while (1) { - printf("> "); + my_printf("> "); index = 0; while (1) @@ -32,7 +34,7 @@ void shell_loop() if (c == '\n' || c == '\r') // Enter key { input[index] = '\0'; - printf("\n"); + my_printf("\n"); break; } else if (c == '\b' || c == 127) // Backspace @@ -40,7 +42,7 @@ void shell_loop() if (index > 0) { index--; - printf("\b \b"); // Erase last char on screen + my_printf("\b \b"); // Erase last char on screen } } else @@ -52,7 +54,7 @@ void shell_loop() } } - if (strcmp(input, "exit") == 0) + if (my_strcmp(input, "exit") == 0) break; execute(input); diff --git a/kernel/string_utils.c b/kernel/string_utils.c new file mode 100644 index 0000000..63e181c --- /dev/null +++ b/kernel/string_utils.c @@ -0,0 +1,80 @@ +#include "string_utils.h" +#include +#include + +size_t my_strlen(const char *str) { + const char *s = str; + while (*s) s++; + return s - str; +} + +// Forward declaration of my_itoa +static size_t my_itoa(int value, char *str, size_t size); + +int my_vsnprintf(char *str, size_t size, const char *format, ...) { + va_list args; + va_start(args, format); + size_t written = 0; // Change to size_t + + for (const char *p = format; *p != '\0' && written < size - 1; p++) { + if (*p == '%') { + p++; + if (*p == 's') { + const char *s = va_arg(args, const char *); + while (*s && written < size - 1) { + str[written++] = *s++; + } + } else if (*p == 'd') { + // Handle integer formatting + written += my_itoa(va_arg(args, int), str + written, size - written); + } else { + // Handle other formats as needed + str[written++] = *p; // Just copy the character + } + } else { + str[written++] = *p; + } + } + str[written] = '\0'; // Null-terminate the string + va_end(args); + return written; +} + +static size_t my_itoa(int value, char *str, size_t size) { + size_t written = 0; // Change to size_t + if (value < 0) { + if (written < size - 1) { + str[written++] = '-'; + } + value = -value; + } + // Convert integer to string + int temp = value; + int digits = 0; + do { + digits++; + temp /= 10; + } while (temp); + + if (written + digits >= size) { + digits = size - written - 1; // Prevent overflow + } + + str += written + digits; // Move pointer to the end + *str-- = '\0'; // Null-terminate the string + + do { + *str-- = (value % 10) + '0'; + value /= 10; + } while (value && str >= str - digits); + + return written + digits; // Return total written characters +} + +int my_strcmp(const char *str1, const char *str2) { + while (*str1 && (*str1 == *str2)) { + str1++; + str2++; + } + return *(unsigned char *)str1 - *(unsigned char *)str2; +} \ No newline at end of file diff --git a/kernel/string_utils.h b/kernel/string_utils.h new file mode 100644 index 0000000..799b9f3 --- /dev/null +++ b/kernel/string_utils.h @@ -0,0 +1,11 @@ +#ifndef STRING_UTILS_H +#define STRING_UTILS_H + +#include +#include // Include for va_list and related macros + +size_t my_strlen(const char *str); // Renamed to avoid conflict +int my_vsnprintf(char *str, size_t size, const char *format, ...); // Renamed to avoid conflict +int my_strcmp(const char *str1, const char *str2); + +#endif // STRING_UTILS_H diff --git a/kernel/syscalls.c b/kernel/syscalls.c index c86abf8..cba2c8e 100644 --- a/kernel/syscalls.c +++ b/kernel/syscalls.c @@ -21,8 +21,7 @@ void syscall_handler(int code, va_list args) { } } -void syscall(int code, ...) -{ +void syscall(int code, ...) { va_list args; va_start(args, code); syscall_handler(code, args); diff --git a/kernel/syscalls.h b/kernel/syscalls.h index cdec5a3..a954455 100644 --- a/kernel/syscalls.h +++ b/kernel/syscalls.h @@ -1,6 +1,7 @@ #ifndef SYSCALLS_H #define SYSCALLS_H +#include // Syscall numbers typedef enum { SYSCALL_INIT = 0, @@ -9,8 +10,7 @@ typedef enum { } syscall_code_t; // Syscall dispatcher -void syscall_handler(); - +void syscall_handler(int code, va_list args); // Syscall interface void syscall(int code, ...); diff --git a/kernel/vga.c b/kernel/vga.c index bb8a1c2..0f21c62 100644 --- a/kernel/vga.c +++ b/kernel/vga.c @@ -1,9 +1,9 @@ #include "vga.h" #include #include -#include // Include for vsnprintf -#include // Include for strlen -#include // Include for va_list, va_start, etc. +#include +#include +#include "string_utils.h" void outb(uint16_t port, uint8_t value) { __asm__ volatile("outb %0, %1" : : "a"(value), "Nd"(port)); @@ -130,11 +130,11 @@ void vga_printf(const char* format, ...) { char buffer[256]; // Buffer to store the formatted string va_list args; va_start(args, format); - vsnprintf(buffer, sizeof(buffer), format, args); + my_vsnprintf(buffer, sizeof(buffer), format, args); // Use my_vsnprintf instead of vsnprintf va_end(args); // Now you can use the buffer with vga_write_string - vga_write_string(buffer, strlen(buffer)); + vga_write_string(buffer, my_strlen(buffer)); // Use my_strlen instead of strlen } void vga_init(void) {