| 1 |
/* ============================================================================ |
| 2 |
* Pactor64 Kernel Main — x86-64 |
| 3 |
* Core kernel: I/O, printf, CPU detection, init sequence |
| 4 |
* ============================================================================ */ |
| 5 |
|
| 6 |
#include "types.h" |
| 7 |
|
| 8 |
/* === GCC builtins for va_list (no libc) === */ |
| 9 |
typedef __builtin_va_list va_list; |
| 10 |
#define va_start(ap, last) __builtin_va_start(ap, last) |
| 11 |
#define va_end(ap) __builtin_va_end(ap) |
| 12 |
#define va_arg(ap, type) __builtin_va_arg(ap, type) |
| 13 |
|
| 14 |
/* === Port I/O === */ |
| 15 |
void outb(uint16_t port, uint8_t val) { |
| 16 |
__asm__ volatile ("outb %0, %1" : : "a"(val), "Nd"(port)); |
| 17 |
} |
| 18 |
uint8_t inb(uint16_t port) { |
| 19 |
uint8_t val; |
| 20 |
__asm__ volatile ("inb %1, %0" : "=a"(val) : "Nd"(port)); |
| 21 |
return val; |
| 22 |
} |
| 23 |
|
| 24 |
/* === String utilities === */ |
| 25 |
size_t kstrlen(const char *s) { size_t n=0; while(s[n]) n++; return n; } |
| 26 |
int kstrcmp(const char *a, const char *b) { while(*a&&*a==*b){a++;b++;} return (uint8_t)*a-(uint8_t)*b; } |
| 27 |
int kstrncmp(const char *a, const char *b, size_t n) { for(size_t i=0;i<n;i++){if(a[i]!=b[i])return(uint8_t)a[i]-(uint8_t)b[i];if(!a[i])return 0;}return 0; } |
| 28 |
void *kmemset(void *d, int c, size_t n) { uint8_t *p=d; while(n--) *p++=(uint8_t)c; return d; } |
| 29 |
void *kmemcpy(void *d, const void *s, size_t n) { uint8_t *dp=d; const uint8_t *sp=s; while(n--) *dp++=*sp++; return d; } |
| 30 |
|
| 31 |
/* === Serial I/O (COM1) === */ |
| 32 |
#define COM1 0x3F8 |
| 33 |
|
| 34 |
void serial_init(void) { |
| 35 |
outb(COM1+1, 0x00); |
| 36 |
outb(COM1+3, 0x80); |
| 37 |
outb(COM1+0, 0x03); |
| 38 |
outb(COM1+1, 0x00); |
| 39 |
outb(COM1+3, 0x03); |
| 40 |
outb(COM1+2, 0xC7); |
| 41 |
outb(COM1+4, 0x0B); |
| 42 |
} |
| 43 |
|
| 44 |
void serial_putc(char c) { |
| 45 |
while (!(inb(COM1+5) & 0x20)) {} |
| 46 |
outb(COM1, c); |
| 47 |
} |
| 48 |
|
| 49 |
void serial_puts(const char *s) { while(*s) serial_putc(*s++); } |
| 50 |
|
| 51 |
int serial_poll(void) { return inb(COM1+5) & 0x01; } |
| 52 |
int serial_getc(void) { return serial_poll() ? inb(COM1) : -1; } |
| 53 |
|
| 54 |
/* === Number printing === */ |
| 55 |
void kprint_hex(uint64_t val) { |
| 56 |
serial_puts("0x"); |
| 57 |
for (int i = 60; i >= 0; i -= 4) { |
| 58 |
int n = (val >> i) & 0xF; |
| 59 |
serial_putc(n < 10 ? '0'+n : 'A'+n-10); |
| 60 |
} |
| 61 |
} |
| 62 |
|
| 63 |
void kprint_dec(uint64_t val) { |
| 64 |
if (!val) { serial_putc('0'); return; } |
| 65 |
char buf[21]; int i = 0; |
| 66 |
while (val) { buf[i++] = '0'+(val%10); val /= 10; } |
| 67 |
while (i > 0) serial_putc(buf[--i]); |
| 68 |
} |
| 69 |
|
| 70 |
/* === kprintf === */ |
| 71 |
void kprintf(const char *fmt, ...) { |
| 72 |
va_list ap; |
| 73 |
va_start(ap, fmt); |
| 74 |
for (int i = 0; fmt[i]; i++) { |
| 75 |
if (fmt[i] == '%' && fmt[i+1]) { |
| 76 |
i++; |
| 77 |
switch (fmt[i]) { |
| 78 |
case 'd': kprint_dec(va_arg(ap, uint64_t)); break; |
| 79 |
case 'x': kprint_hex(va_arg(ap, uint64_t)); break; |
| 80 |
case 's': { const char *s = va_arg(ap, const char*); |
| 81 |
serial_puts(s ? s : "(null)"); break; } |
| 82 |
case 'c': serial_putc((char)va_arg(ap, int)); break; |
| 83 |
case '%': serial_putc('%'); break; |
| 84 |
default: serial_putc('%'); serial_putc(fmt[i]); break; |
| 85 |
} |
| 86 |
} else serial_putc(fmt[i]); |
| 87 |
} |
| 88 |
va_end(ap); |
| 89 |
} |
| 90 |
|
| 91 |
/* === Assembly functions === */ |
| 92 |
extern void idt_init(void); |
| 93 |
extern void pic_remap(int offset1, int offset2); |
| 94 |
|
| 95 |
/* === Module init functions === */ |
| 96 |
extern void timer_init(uint32_t hz); |
| 97 |
extern void keyboard_init(void); |
| 98 |
extern void pmm_init(uint64_t mb2_info); |
| 99 |
extern void heap_init(void); |
| 100 |
extern void vga_init(void); |
| 101 |
extern void vga_clear(void); |
| 102 |
extern void vga_puts(const char *s); |
| 103 |
extern void ata_init(void); |
| 104 |
extern void syscall_init(void); |
| 105 |
extern void shell_init(void); |
| 106 |
|
| 107 |
extern void shell_run(void); |
| 108 |
|
| 109 |
extern uint64_t kernel_end; |
| 110 |
|
| 111 |
/* === Timer tick counter (from isr.asm) === */ |
| 112 |
extern volatile uint64_t timer_ticks; |
| 113 |
|
| 114 |
/* === CPU Detection === */ |
| 115 |
static void detect_cpu(void) { |
| 116 |
uint32_t eax, ebx, ecx, edx; |
| 117 |
char vendor[13] = {0}; |
| 118 |
__asm__ volatile ("cpuid":"=a"(eax),"=b"(ebx),"=c"(ecx),"=d"(edx):"a"(0)); |
| 119 |
*(uint32_t*)&vendor[0]=ebx; *(uint32_t*)&vendor[4]=edx; *(uint32_t*)&vendor[8]=ecx; |
| 120 |
kprintf(" CPU Vendor: %s\n", vendor); |
| 121 |
__asm__ volatile ("cpuid":"=a"(eax),"=d"(edx):"a"(1)); |
| 122 |
kprintf(" Family/Model: %d/%d Stepping %d\n", (eax>>8)&0xF, (eax>>4)&0xF, eax&0xF); |
| 123 |
kprintf(" Features: "); |
| 124 |
if(edx&(1<<4)) kprintf("TSC "); |
| 125 |
if(edx&(1<<8)) kprintf("CX8 "); |
| 126 |
if(edx&(1<<23)) kprintf("MMX "); |
| 127 |
if(edx&(1<<25)) kprintf("SSE "); |
| 128 |
if(edx&(1<<26)) kprintf("SSE2 "); |
| 129 |
__asm__ volatile ("cpuid":"=a"(eax),"=d"(edx):"a"(0x80000001)); |
| 130 |
if(edx&(1<<29)) kprintf("LM "); |
| 131 |
kprintf("\n"); |
| 132 |
} |
| 133 |
|
| 134 |
static void dump_registers(void) { |
| 135 |
uint64_t rsp, cr0, cr3, cr4; |
| 136 |
__asm__ volatile ("mov %%rsp,%0":"=r"(rsp)); |
| 137 |
__asm__ volatile ("mov %%cr0,%0":"=r"(cr0)); |
| 138 |
__asm__ volatile ("mov %%cr3,%0":"=r"(cr3)); |
| 139 |
__asm__ volatile ("mov %%cr4,%0":"=r"(cr4)); |
| 140 |
kprintf(" RSP: %x\n", rsp); |
| 141 |
kprintf(" CR0: %x (PE=%d PG=%d)\n", cr0, cr0&1, (cr0>>31)&1); |
| 142 |
kprintf(" CR3 (PML4): %x\n", cr3); |
| 143 |
kprintf(" CR4: %x (PAE=%d)\n", cr4, (cr4>>5)&1); |
| 144 |
} |
| 145 |
|
| 146 |
/* === Exception Handler === */ |
| 147 |
void exception_handler(uint64_t int_num, uint64_t err_code, uint64_t rip) { |
| 148 |
kprintf("\n*** EXCEPTION %d at RIP %x err=%x ***\n", int_num, rip, err_code); |
| 149 |
for (;;) __asm__ volatile ("cli; hlt"); |
| 150 |
} |
| 151 |
|
| 152 |
/* === Kernel Main === */ |
| 153 |
void kernel_main_64(uint64_t mb2_info, uint64_t mb2_magic) { |
| 154 |
serial_init(); |
| 155 |
|
| 156 |
kprintf("\n========================================\n"); |
| 157 |
kprintf(" Pactor64 — x86-64 Kernel\n"); |
| 158 |
kprintf(" Built from NT source code analysis\n"); |
| 159 |
kprintf("========================================\n\n"); |
| 160 |
|
| 161 |
if (mb2_magic == 0x36D76289) kprintf(" [OK] Multiboot2 verified\n"); |
| 162 |
else kprintf(" [WARN] Multiboot magic: %x\n", mb2_magic); |
| 163 |
|
| 164 |
detect_cpu(); |
| 165 |
dump_registers(); |
| 166 |
|
| 167 |
/* PIC + IDT */ |
| 168 |
pic_remap(0x20, 0x28); |
| 169 |
kprintf(" [OK] PIC remapped (IRQs 0x20-0x2F)\n"); |
| 170 |
idt_init(); |
| 171 |
kprintf(" [OK] IDT initialized (256 vectors, 64-bit)\n"); |
| 172 |
|
| 173 |
/* Enable interrupts */ |
| 174 |
__asm__ volatile ("sti"); |
| 175 |
kprintf(" [OK] Interrupts enabled\n"); |
| 176 |
|
| 177 |
/* Timer */ |
| 178 |
timer_init(100); |
| 179 |
kprintf(" [OK] PIT timer at 100 Hz\n"); |
| 180 |
|
| 181 |
/* Keyboard */ |
| 182 |
keyboard_init(); |
| 183 |
kprintf(" [OK] PS/2 keyboard initialized\n"); |
| 184 |
|
| 185 |
/* Physical memory */ |
| 186 |
pmm_init(mb2_info); |
| 187 |
|
| 188 |
/* Heap */ |
| 189 |
heap_init(); |
| 190 |
syscall_init(); |
| 191 |
kprintf(" [OK] SYSCALL interface (STAR/LSTAR MSRs)\n"); |
| 192 |
|
| 193 |
/* VGA */ |
| 194 |
vga_init(); |
| 195 |
vga_clear(); |
| 196 |
vga_puts("Pactor64 VGA active.\n"); |
| 197 |
kprintf(" [OK] VGA text mode (80x25)\n"); |
| 198 |
|
| 199 |
/* ATA */ |
| 200 |
ata_init(); |
| 201 |
|
| 202 |
kprintf("\n Kernel at 0x100000, end at %x\n", (uint64_t)&kernel_end); |
| 203 |
kprintf(" PML4 at "); |
| 204 |
uint64_t cr3; __asm__ volatile ("mov %%cr3,%0":"=r"(cr3)); |
| 205 |
kprint_hex(cr3); |
| 206 |
kprintf("\n\n"); |
| 207 |
|
| 208 |
/* Shell */ |
| 209 |
shell_init(); |
| 210 |
|
| 211 |
shell_run(); |
| 212 |
|
| 213 |
kprintf("\n System halted.\n"); |
| 214 |
for (;;) __asm__ volatile ("cli; hlt"); |
| 215 |
} |
| 216 |
|