Forum

Notifications
Clear all

C++ 64-Bit AMD64 Architecture Custom Operating System

1 Posts
1 Users
0 Reactions
6 Views
 josh
(@josh)
Member Admin
Joined: 2 months ago
Posts: 510
Topic starter  
# 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.

   
Quote
Share: