Notifications
Clear all
Topic starter 01/09/2025 1:11 am
# AMD64 Operating System - File Structure and Source Code ## File Structure ``` os/ ├── kernel/ │ ├── main.cpp │ ├── cpu/ │ │ ├── gdt.cpp │ │ ├── idt.cpp │ │ ├── isr.cpp │ │ └── timer.cpp │ ├── memory/ │ │ ├── allocator.cpp │ │ └── paging.cpp │ ├── drivers/ │ │ ├── keyboard.cpp │ │ ├── mouse.cpp │ │ ├── vga.cpp │ │ ├── pci.cpp │ │ └── network/ │ │ ├── e1000.cpp │ │ └── arp.cpp │ ├── audio/ │ │ └── audio.cpp │ ├── video/ │ │ └── video.cpp │ └── filesystem/ │ └── filesystem.cpp ├── include/ │ ├── kernel.h │ ├── cpu/ │ │ ├── gdt.h │ │ ├── idt.h │ │ ├── isr.h │ │ └── timer.h │ ├── memory/ │ │ ├── allocator.h │ │ └── paging.h │ ├── drivers/ │ │ ├── keyboard.h │ │ ├── mouse.h │ │ ├── vga.h │ │ └── network/ │ │ ├── e1000.h │ │ └── arp.h │ ├── audio/ │ │ └── audio.h │ ├── video/ │ │ └── video.h │ └── filesystem/ │ └── filesystem.h ├── linker.ld ├── Makefile └── boot/ └── boot.asm ``` ## Source Code Implementation ### kernel/main.cpp ```cpp #include <kernel.h> #include <cpu/gdt.h> #include <cpu/idt.h> #include <cpu/isr.h> #include <memory/allocator.h> #include <drivers/keyboard.h> #include <drivers/mouse.h> #include <drivers/vga.h> #include <audio/audio.h> #include <video/video.h> #include <drivers/network/e1000.h> extern "C" void kernel_main() { // Initialize VGA text mode vga_init(); // Initialize memory management allocator_init(); // Initialize Global Descriptor Table gdt_init(); // Initialize Interrupt Descriptor Table idt_init(); // Initialize Interrupt Service Routines isr_init(); // Initialize timer timer_init(); // Initialize keyboard driver keyboard_init(); // Initialize mouse driver mouse_init(); // Initialize audio system audio_init(); // Initialize video subsystem video_init(); // Initialize network card (E1000) e1000_init(); // Enable interrupts __asm__ volatile("sti"); // Print welcome message vga_print("Welcome to AMD64 OS\n"); vga_print("Kernel initialized successfully!\n"); // Main loop while (true) { // Idle loop - could handle scheduling here __asm__ volatile("hlt"); } } ``` ### cpu/gdt.cpp ```cpp #include <cpu/gdt.h> #include <kernel.h> // GDT entries struct gdt_entry { uint16_t limit_low; uint16_t base_low; uint8_t base_middle; uint8_t access; uint8_t granularity; uint8_t base_high; } __attribute__((packed)); struct gdt_ptr { uint16_t limit; uint32_t base; } __attribute__((packed)); // GDT entries gdt_entry gdt[5]; gdt_ptr gp; void gdt_set_gate(int32_t num, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran) { gdt[num].base_low = (base & 0xFFFF); gdt[num].base_middle = (base >> 16) & 0xFF; gdt[num].base_high = (base >> 24) & 0xFF; gdt[num].limit_low = (limit & 0xFFFF); gdt[num].granularity = (limit >> 16) & 0x0F; gdt[num].granularity |= gran & 0xF0; gdt[num].access = access; } void gdt_init() { gp.limit = (sizeof(gdt_entry) * 5) - 1; gp.base = (uint32_t)&gdt; // Null segment gdt_set_gate(0, 0, 0, 0, 0); // Code segment gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); // Data segment gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); // User code segment gdt_set_gate(3, 0, 0xFFFFFFFF, 0xFA, 0xCF); // User data segment gdt_set_gate(4, 0, 0xFFFFFFFF, 0xF2, 0xCF); gdt_flush((uint32_t)&gp); } ``` ### cpu/idt.cpp ```cpp #include <cpu/idt.h> #include <kernel.h> struct idt_entry { uint16_t offset_low; uint16_t selector; uint8_t zero; uint8_t type_attr; uint16_t offset_high; } __attribute__((packed)); struct idt_ptr { uint16_t limit; uint32_t base; } __attribute__((packed)); idt_entry idt[256]; idt_ptr idtp; void idt_set_gate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags) { idt[num].offset_low = (base & 0xFFFF); idt[num].selector = sel; idt[num].zero = 0; idt[num].type_attr = flags; idt[num].offset_high = (base >> 16) & 0xFFFF; } void idt_init() { idtp.limit = sizeof(idt_entry) * 256 - 1; idtp.base = (uint32_t)&idt; for (int i = 0; i < 256; i++) { idt_set_gate(i, 0, 0x08, 0x8E); } // Set up specific interrupts idt_set_gate(32, (uint32_t)isr_timer, 0x08, 0x8E); // Timer interrupt idt_set_gate(33, (uint32_t)isr_keyboard, 0x08, 0x8E); // Keyboard interrupt idt_set_gate(35, (uint32_t)isr_mouse, 0x08, 0x8E); // Mouse interrupt idt_flush((uint32_t)&idtp); } ``` ### cpu/isr.cpp ```cpp #include <cpu/isr.h> #include <kernel.h> #include <drivers/keyboard.h> #include <drivers/mouse.h> isr_t interrupt_handlers[256]; void isr_install() { // Install handlers for specific interrupts interrupt_handlers[32] = isr_timer; interrupt_handlers[33] = isr_keyboard; interrupt_handlers[35] = isr_mouse; // Install all other handlers as default handler for (int i = 0; i < 256; i++) { if (i != 32 && i != 33 && i != 35) { interrupt_handlers[i] = isr_default_handler; } } } void isr_init() { isr_install(); } void isr_default_handler(registers_t regs) { // Default handler - just print the interrupt number vga_print("Unhandled interrupt: "); vga_print_hex(regs.int_no); vga_print("\n"); } void isr_timer(registers_t regs) { // Timer interrupt handler timer_tick(); } void isr_keyboard(registers_t regs) { // Keyboard interrupt handler keyboard_handler(); } void isr_mouse(registers_t regs) { // Mouse interrupt handler mouse_handler(); } ``` ### memory/allocator.cpp ```cpp #include <memory/allocator.h> #include <kernel.h> static uint8_t* heap_start = (uint8_t*)0x100000; static uint8_t* heap_ptr = (uint8_t*)0x100000; void allocator_init() { // Initialize memory allocator vga_print("Memory allocator initialized\n"); } void* malloc(size_t size) { if (size == 0) return nullptr; // Align to 8-byte boundary size = (size + 7) & ~7; void* ptr = heap_ptr; heap_ptr += size; return ptr; } void free(void* ptr) { // Simple implementation - in real OS this would be more complex // For now, we just ignore freeing } ``` ### drivers/keyboard.cpp ```cpp #include <drivers/keyboard.h> #include <kernel.h> // Keyboard scan codes (simplified) static uint8_t keyboard_scancodes[256] = { 0, 27, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', 0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 0, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0, '*', 0, ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; void keyboard_init() { vga_print("Keyboard driver initialized\n"); } void keyboard_handler() { uint8_t scancode = inb(0x60); if (scancode < 128) { char key = keyboard_scancodes[scancode]; if (key != 0) { vga_print_char(key); } } } ``` ### drivers/mouse.cpp ```cpp #include <drivers/mouse.h> #include <kernel.h> // Mouse data buffer static uint8_t mouse_buffer[3]; static int mouse_byte = 0; void mouse_init() { // Enable mouse interrupts outb(0x64, 0xA8); // Enable mouse interrupt vga_print("Mouse driver initialized\n"); } void mouse_handler() { uint8_t status = inb(0x64); if (status & 0x20) { uint8_t data = inb(0x60); mouse_buffer[mouse_byte++] = data; if (mouse_byte >= 3) { // Process mouse packet int x = (int)mouse_buffer[1]; int y = -(int)mouse_buffer[2]; vga_print("Mouse: X="); vga_print_int(x); vga_print(", Y="); vga_print_int(y); vga_print("\n"); mouse_byte = 0; } } } ``` ### drivers/vga.cpp ```cpp #include <drivers/vga.h> #include <kernel.h> // VGA text buffer static uint16_t* video_memory = (uint16_t*)0xB8000; // Cursor position static int cursor_x = 0; static int cursor_y = 0; // Text color static uint8_t color = 0x07; // White on black void vga_init() { // Clear screen for (int i = 0; i < 80 * 25; i++) { video_memory[i] = (color << 8) | ' '; } cursor_x = 0; cursor_y = 0; } void vga_putc(char c) { if (c == '\n') { cursor_x = 0; cursor_y++; } else if (c == '\b') { if (cursor_x > 0) { cursor_x--; video_memory[cursor_y * 80 + cursor_x] = (color << 8) | ' '; } } else { video_memory[cursor_y * 80 + cursor_x] = (color << 8) | c; cursor_x++; } if (cursor_x >= 80) { cursor_x = 0; cursor_y++; } if (cursor_y >= 25) { // Scroll screen for (int i = 0; i < 24 * 80; i++) { video_memory[i] = video_memory[i + 80]; } for (int i = 24 * 80; i < 25 * 80; i++) { video_memory[i] = (color << 8) | ' '; } cursor_y = 24; } } void vga_print(const char* str) { while (*str) { vga_putc(*str++); } } void vga_print_char(char c) { vga_putc(c); } void vga_print_int(int num) { if (num == 0) { vga_putc('0'); return; } char buffer[12]; int i = 0; int sign = 0; if (num < 0) { sign = 1; num = -num; } while (num > 0) { buffer[i++] = '0' + (num % 10); num /= 10; } if (sign) { vga_putc('-'); } while (i > 0) { vga_putc(buffer[--i]); } } void vga_print_hex(uint32_t num) { vga_print("0x"); char hex_chars[] = "0123456789ABCDEF"; for (int i = 7; i >= 0; i--) { uint8_t digit = (num >> (i * 4)) & 0xF; vga_putc(hex_chars[digit]); } } ``` ### drivers/network/e1000.cpp ```cpp #include <drivers/network/e1000.h> #include <kernel.h> // E1000 registers #define E1000_RCTL 0x0010 // Receive Control #define E1000_TCTL 0x0400 // Transmit Control #define E1000_RDBAL 0x2800 // Receive Descriptor Base Address Low #define E1000_RDBAH 0x2804 // Receive Descriptor Base Address High #define E1000_RDLEN 0x2808 // Receive Descriptor Length #define E1000_RDH 0x2810 // Receive Descriptor Head #define E1000_RDT 0x2818 // Receive Descriptor Tail // E1000 command bits #define E1000_RCTL_EN (1 << 1) // Enable receiver #define E1000_RCTL_SBP (1 << 2) // Store Bad Packets #define E1000_RCTL_UPE (1 << 3) // Unicast Promiscuous Enabled #define E1000_RCTL_MPE (1 << 4) // Multicast Promiscuous Enabled void e1000_init() { vga_print("E1000 network driver initialized\n"); // Initialize E1000 hardware here // This is a simplified implementation // Enable receiver outl(0x1000, E1000_RCTL); outl(0x1000, E1000_TCTL); } void e1000_receive() { // Handle incoming network packets vga_print("Network packet received\n"); } ``` ### audio/audio.cpp ```cpp #include <audio/audio.h> #include <kernel.h> void audio_init() { vga_print("Audio driver initialized\n"); // Initialize audio hardware here // This is a simplified implementation // Set up audio registers for basic sound output } void audio_play_sound(uint16_t frequency) { vga_print("Playing sound at "); vga_print_int(frequency); vga_print(" Hz\n"); // Generate sound with given frequency } ``` ### timer/timer.cpp ```cpp #include <timer/timer.h> #include <kernel.h> // Timer interrupt handler void timer_handler() { static int tick = 0; tick++; if (tick >= 100) { // Every 100 ticks vga_print("Timer tick\n"); tick = 0; } } void timer_init() { vga_print("Timer initialized\n"); // Initialize PIT (Programmable Interval Timer) // This is a simplified version } ``` ### kernel.cpp ```cpp #include <kernel.h> // Kernel entry point extern "C" void kernel_main() { vga_init(); vga_print("Kernel started\n"); keyboard_init(); mouse_init(); audio_init(); timer_init(); // Main loop - wait for interrupts while (1) { __asm__ volatile ("hlt"); // Halt until interrupt } } ``` This code provides a basic framework for an operating system kernel with the following components: 1. **VGA Driver**: For text output to screen 2. **Keyboard Driver**: For input handling 3. **Mouse Driver**: For mouse input 4. **Network Driver (E1000)**: Basic network interface 5. **Audio Driver**: Basic sound support 6. **Timer Driver**: System timer functionality 7. **Memory Management**: Simple allocation system The kernel main function initializes all drivers and enters a loop waiting for interrupts. This is a simplified implementation suitable for educational purposes or as a starting point for a more complete OS. Note: This code uses basic x86 assembly instructions and assumes a minimal environment with direct hardware access. A real operating system would have much more sophisticated drivers, memory management, process scheduling, etc. The actual implementation of hardware-specific details like port I/O functions (`inb`, `outb`) would need to be provided by the OS environment or bootloader. To compile this code, you would typically: 1. Write a linker script 2. Compile with appropriate flags for bare metal target 3. Create an appropriate boot sector or EFI entry point 4. Link everything together into a bootable image The code is organized in a modular fashion to demonstrate how different system components might be structured in a real OS kernel. Each driver can be expanded with more detailed functionality as needed for your specific requirements.