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.