Record networking and DMA development progress
Add the current OS source tree, build scripts, system image layout, and development notes covering DMA page allocation, e1000 bring-up, net API dispatch, and DHCP work in progress.
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
.section .text
|
||||
.global _start
|
||||
.type _start, @function
|
||||
_start:
|
||||
cli
|
||||
cld
|
||||
lea kernel_stack_top(%rip), %rsp
|
||||
andq $-16, %rsp
|
||||
call kernel_main
|
||||
.hang:
|
||||
cli
|
||||
hlt
|
||||
jmp .hang
|
||||
|
||||
.section .bss
|
||||
.align 16
|
||||
.global kernel_stack
|
||||
.global kernel_stack_top
|
||||
kernel_stack:
|
||||
.skip 16384
|
||||
kernel_stack_top:
|
||||
Binary file not shown.
@@ -0,0 +1,5 @@
|
||||
void arch_halt_forever(void) {
|
||||
for (;;) {
|
||||
__asm__ volatile ("cli; hlt");
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,222 @@
|
||||
#include <utsm/idt.h>
|
||||
#include <utsm/log.h>
|
||||
#include <utsm/types.h>
|
||||
|
||||
/* IDT gate descriptor (64-bit) */
|
||||
typedef struct __attribute__((packed)) {
|
||||
u16 offset_low;
|
||||
u16 selector;
|
||||
u8 ist;
|
||||
u8 type_attr;
|
||||
u16 offset_mid;
|
||||
u32 offset_high;
|
||||
u32 reserved;
|
||||
} idt_entry;
|
||||
|
||||
/* IDT register */
|
||||
typedef struct __attribute__((packed)) {
|
||||
u16 limit;
|
||||
u64 base;
|
||||
} idt_ptr;
|
||||
|
||||
#define IDT_ENTRIES 256
|
||||
static idt_entry g_idt[IDT_ENTRIES] __attribute__((aligned(16)));
|
||||
|
||||
#define PIC1_CMD 0x20
|
||||
#define PIC1_DATA 0x21
|
||||
#define PIC2_CMD 0xA0
|
||||
#define PIC2_DATA 0xA1
|
||||
#define ICW1_ICW4 0x01
|
||||
#define ICW1_INIT 0x10
|
||||
|
||||
/* assembly stub declarations */
|
||||
extern void isr_stub_0(void);
|
||||
extern void isr_stub_1(void);
|
||||
extern void isr_stub_2(void);
|
||||
extern void isr_stub_3(void);
|
||||
extern void isr_stub_4(void);
|
||||
extern void isr_stub_5(void);
|
||||
extern void isr_stub_6(void);
|
||||
extern void isr_stub_7(void);
|
||||
extern void isr_stub_8(void);
|
||||
extern void isr_stub_9(void);
|
||||
extern void isr_stub_10(void);
|
||||
extern void isr_stub_11(void);
|
||||
extern void isr_stub_12(void);
|
||||
extern void isr_stub_13(void);
|
||||
extern void isr_stub_14(void);
|
||||
extern void isr_stub_15(void);
|
||||
extern void isr_stub_16(void);
|
||||
extern void isr_stub_17(void);
|
||||
extern void isr_stub_18(void);
|
||||
extern void isr_stub_19(void);
|
||||
extern void isr_stub_20(void);
|
||||
extern void isr_stub_21(void);
|
||||
extern void isr_stub_22(void);
|
||||
extern void isr_stub_23(void);
|
||||
extern void isr_stub_24(void);
|
||||
extern void isr_stub_25(void);
|
||||
extern void isr_stub_26(void);
|
||||
extern void isr_stub_27(void);
|
||||
extern void isr_stub_28(void);
|
||||
extern void isr_stub_29(void);
|
||||
extern void isr_stub_30(void);
|
||||
extern void isr_stub_31(void);
|
||||
extern void isr_stub_32(void);
|
||||
extern void isr_stub_33(void);
|
||||
extern void isr_stub_34(void);
|
||||
extern void isr_stub_35(void);
|
||||
extern void isr_stub_36(void);
|
||||
extern void isr_stub_37(void);
|
||||
extern void isr_stub_38(void);
|
||||
extern void isr_stub_39(void);
|
||||
extern void isr_stub_40(void);
|
||||
extern void isr_stub_41(void);
|
||||
extern void isr_stub_42(void);
|
||||
extern void isr_stub_43(void);
|
||||
extern void isr_stub_44(void);
|
||||
extern void isr_stub_45(void);
|
||||
extern void isr_stub_46(void);
|
||||
extern void isr_stub_47(void);
|
||||
|
||||
static void *g_isr_table[] = {
|
||||
isr_stub_0, isr_stub_1, isr_stub_2, isr_stub_3,
|
||||
isr_stub_4, isr_stub_5, isr_stub_6, isr_stub_7,
|
||||
isr_stub_8, isr_stub_9, isr_stub_10, isr_stub_11,
|
||||
isr_stub_12, isr_stub_13, isr_stub_14, isr_stub_15,
|
||||
isr_stub_16, isr_stub_17, isr_stub_18, isr_stub_19,
|
||||
isr_stub_20, isr_stub_21, isr_stub_22, isr_stub_23,
|
||||
isr_stub_24, isr_stub_25, isr_stub_26, isr_stub_27,
|
||||
isr_stub_28, isr_stub_29, isr_stub_30, isr_stub_31,
|
||||
isr_stub_32, isr_stub_33, isr_stub_34, isr_stub_35,
|
||||
isr_stub_36, isr_stub_37, isr_stub_38, isr_stub_39,
|
||||
isr_stub_40, isr_stub_41, isr_stub_42, isr_stub_43,
|
||||
isr_stub_44, isr_stub_45, isr_stub_46, isr_stub_47,
|
||||
};
|
||||
|
||||
static void outb(u16 port, u8 value) {
|
||||
__asm__ volatile ("outb %0, %1" :: "a"(value), "Nd"(port));
|
||||
}
|
||||
|
||||
static u8 inb(u16 port) {
|
||||
u8 value;
|
||||
__asm__ volatile ("inb %1, %0" : "=a"(value) : "Nd"(port));
|
||||
return value;
|
||||
}
|
||||
|
||||
static void io_wait(void) {
|
||||
outb(0x80, 0);
|
||||
}
|
||||
|
||||
static void pic_remap(void) {
|
||||
/* save masks */
|
||||
u8 m1 = inb(PIC1_DATA);
|
||||
u8 m2 = inb(PIC2_DATA);
|
||||
|
||||
/* ICW1: start init + ICW4 */
|
||||
outb(PIC1_CMD, ICW1_INIT | ICW1_ICW4);
|
||||
io_wait();
|
||||
outb(PIC2_CMD, ICW1_INIT | ICW1_ICW4);
|
||||
io_wait();
|
||||
|
||||
/* ICW2: vector offsets */
|
||||
outb(PIC1_DATA, 0x20); /* master: vectors 0x20-0x27 */
|
||||
io_wait();
|
||||
outb(PIC2_DATA, 0x28); /* slave: vectors 0x28-0x2F */
|
||||
io_wait();
|
||||
|
||||
/* ICW3: master/slave wiring */
|
||||
outb(PIC1_DATA, 0x04); /* master: IRQ2 → slave */
|
||||
io_wait();
|
||||
outb(PIC2_DATA, 0x02); /* slave: cascade identity */
|
||||
io_wait();
|
||||
|
||||
/* ICW4: 8086 mode */
|
||||
outb(PIC1_DATA, 0x01);
|
||||
io_wait();
|
||||
outb(PIC2_DATA, 0x01);
|
||||
io_wait();
|
||||
|
||||
/* restore masks: mask all except IRQ1 (keyboard) */
|
||||
outb(PIC1_DATA, 0xFD); /* 1111_1101: enable IRQ0 (timer) and IRQ1 (kb) */
|
||||
outb(PIC2_DATA, 0xFF); /* mask all slave */
|
||||
}
|
||||
|
||||
static void idt_set_entry(u8 vector, void *handler, u8 ist, u8 type) {
|
||||
u64 addr = (u64)handler;
|
||||
g_idt[vector].offset_low = (u16)(addr & 0xffff);
|
||||
g_idt[vector].selector = 0x08; /* kernel code segment (from GDT) */
|
||||
g_idt[vector].ist = ist;
|
||||
g_idt[vector].type_attr = type;
|
||||
g_idt[vector].offset_mid = (u16)((addr >> 16) & 0xffff);
|
||||
g_idt[vector].offset_high = (u32)(addr >> 32);
|
||||
g_idt[vector].reserved = 0;
|
||||
}
|
||||
|
||||
void idt_init(void) {
|
||||
log_info("[IDT] init begin");
|
||||
|
||||
for (u16 i = 0; i < 48; i++) {
|
||||
idt_set_entry((u8)i, g_isr_table[i], 0, 0x8E); /* present, ring0, 64-bit interrupt gate */
|
||||
}
|
||||
/* fill unused entries with null */
|
||||
for (u16 i = 48; i < IDT_ENTRIES; i++) {
|
||||
idt_set_entry((u8)i, 0, 0, 0);
|
||||
}
|
||||
|
||||
idt_ptr idtr;
|
||||
idtr.limit = (u16)(sizeof(g_idt) - 1);
|
||||
idtr.base = (u64)&g_idt;
|
||||
|
||||
__asm__ volatile ("lidt %0" :: "m"(idtr));
|
||||
|
||||
pic_remap();
|
||||
log_info("[IDT] PIC remapped (master=0x20 slave=0x28)");
|
||||
|
||||
__asm__ volatile ("sti");
|
||||
log_info("[IDT] interrupts enabled");
|
||||
log_info("[IDT] init ok");
|
||||
}
|
||||
|
||||
/* IRQ handler table */
|
||||
static irq_handler_t g_irq_handlers[16];
|
||||
|
||||
int irq_register(u8 irq, irq_handler_t handler) {
|
||||
if (irq >= 16) return -1;
|
||||
g_irq_handlers[irq] = handler;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Stack frame pushed by isr_common in idt.S */
|
||||
typedef struct {
|
||||
u64 r11, r10, r9, r8, rax, rcx, rdx, rsi, rdi;
|
||||
u64 vector;
|
||||
u64 error_code;
|
||||
u64 rip, cs, rflags;
|
||||
} isr_frame;
|
||||
|
||||
void idt_handler(isr_frame *frame) {
|
||||
if (frame->vector < 32) {
|
||||
log_error("[IDT] exception");
|
||||
log_hex64("[IDT] vector=", frame->vector);
|
||||
log_hex64("[IDT] err=", frame->error_code);
|
||||
log_hex64("[IDT] rip=", frame->rip);
|
||||
for (;;) { __asm__ volatile ("cli; hlt"); }
|
||||
}
|
||||
|
||||
if (frame->vector >= 32 && frame->vector <= 47) {
|
||||
u8 irq = (u8)(frame->vector - 0x20);
|
||||
|
||||
/* call registered handler */
|
||||
if (irq < 16 && g_irq_handlers[irq]) {
|
||||
int suppress_eoi = g_irq_handlers[irq](irq);
|
||||
if (suppress_eoi) return;
|
||||
}
|
||||
|
||||
/* send EOI */
|
||||
if (frame->vector >= 0x28) {
|
||||
outb(PIC2_CMD, 0x20);
|
||||
}
|
||||
outb(PIC1_CMD, 0x20);
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,62 @@
|
||||
/* IDT assembly stubs — SAS-R0 interrupt vectors */
|
||||
.section .text
|
||||
|
||||
.macro isr_no_err n
|
||||
.global isr_stub_\n
|
||||
.type isr_stub_\n, @function
|
||||
isr_stub_\n:
|
||||
pushq $0
|
||||
pushq $\n
|
||||
jmp isr_common
|
||||
.endm
|
||||
|
||||
.macro isr_err n
|
||||
.global isr_stub_\n
|
||||
.type isr_stub_\n, @function
|
||||
isr_stub_\n:
|
||||
pushq $\n
|
||||
jmp isr_common
|
||||
.endm
|
||||
|
||||
/* Exceptions 0-31 */
|
||||
isr_no_err 0; isr_no_err 1; isr_no_err 2; isr_no_err 3
|
||||
isr_no_err 4; isr_no_err 5; isr_no_err 6; isr_no_err 7
|
||||
isr_err 8; isr_no_err 9; isr_err 10; isr_err 11
|
||||
isr_err 12; isr_err 13; isr_err 14; isr_no_err 15
|
||||
isr_no_err 16; isr_err 17; isr_no_err 18; isr_no_err 19
|
||||
isr_no_err 20; isr_no_err 21; isr_no_err 22; isr_no_err 23
|
||||
isr_no_err 24; isr_no_err 25; isr_no_err 26; isr_no_err 27
|
||||
isr_no_err 28; isr_no_err 29; isr_err 30; isr_no_err 31
|
||||
|
||||
/* IRQ 32-47 */
|
||||
isr_no_err 32; isr_no_err 33; isr_no_err 34; isr_no_err 35
|
||||
isr_no_err 36; isr_no_err 37; isr_no_err 38; isr_no_err 39
|
||||
isr_no_err 40; isr_no_err 41; isr_no_err 42; isr_no_err 43
|
||||
isr_no_err 44; isr_no_err 45; isr_no_err 46; isr_no_err 47
|
||||
|
||||
/* Common ISR */
|
||||
isr_common:
|
||||
pushq %rdi
|
||||
pushq %rsi
|
||||
pushq %rdx
|
||||
pushq %rcx
|
||||
pushq %rax
|
||||
pushq %r8
|
||||
pushq %r9
|
||||
pushq %r10
|
||||
pushq %r11
|
||||
|
||||
movq %rsp, %rdi
|
||||
call idt_handler
|
||||
|
||||
popq %r11
|
||||
popq %r10
|
||||
popq %r9
|
||||
popq %r8
|
||||
popq %rax
|
||||
popq %rcx
|
||||
popq %rdx
|
||||
popq %rsi
|
||||
popq %rdi
|
||||
addq $16, %rsp
|
||||
iretq
|
||||
Binary file not shown.
@@ -0,0 +1,15 @@
|
||||
#include <utsm/types.h>
|
||||
|
||||
void outb(u16 port, u8 value) {
|
||||
__asm__ volatile ("outb %0, %1" : : "a"(value), "Nd"(port));
|
||||
}
|
||||
|
||||
u8 inb(u16 port) {
|
||||
u8 value;
|
||||
__asm__ volatile ("inb %1, %0" : "=a"(value) : "Nd"(port));
|
||||
return value;
|
||||
}
|
||||
|
||||
void io_wait(void) {
|
||||
outb(0x80, 0);
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,154 @@
|
||||
#ifndef UTSM_LIMINE_H
|
||||
#define UTSM_LIMINE_H
|
||||
|
||||
#include <utsm/types.h>
|
||||
|
||||
#define LIMINE_COMMON_MAGIC 0xc7b1dd30df4c8b88ULL, 0x0a82e883a194f07bULL
|
||||
|
||||
struct limine_hhdm_response {
|
||||
u64 revision;
|
||||
u64 offset;
|
||||
};
|
||||
|
||||
struct limine_hhdm_request {
|
||||
u64 id[4];
|
||||
u64 revision;
|
||||
struct limine_hhdm_response *response;
|
||||
};
|
||||
|
||||
struct limine_kernel_address_response {
|
||||
u64 revision;
|
||||
u64 physical_base;
|
||||
u64 virtual_base;
|
||||
};
|
||||
|
||||
struct limine_kernel_address_request {
|
||||
u64 id[4];
|
||||
u64 revision;
|
||||
struct limine_kernel_address_response *response;
|
||||
};
|
||||
|
||||
#define LIMINE_KERNEL_ADDRESS_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x71ba76863cc55f63ULL, 0xb2644a48c516a487ULL }
|
||||
|
||||
struct limine_file {
|
||||
u64 revision;
|
||||
void *address;
|
||||
u64 size;
|
||||
char *path;
|
||||
char *cmdline;
|
||||
u32 media_type;
|
||||
u32 unused;
|
||||
u32 tftp_ip;
|
||||
u32 tftp_port;
|
||||
u32 partition_index;
|
||||
u32 mbr_disk_id;
|
||||
u8 gpt_disk_uuid[16];
|
||||
u8 gpt_part_uuid[16];
|
||||
u8 part_uuid[16];
|
||||
};
|
||||
|
||||
struct limine_module_response {
|
||||
u64 revision;
|
||||
u64 module_count;
|
||||
struct limine_file **modules;
|
||||
};
|
||||
|
||||
struct limine_module_request {
|
||||
u64 id[4];
|
||||
u64 revision;
|
||||
struct limine_module_response *response;
|
||||
};
|
||||
|
||||
#define LIMINE_MODULE_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x3e7e279702be32afULL, 0xca1c4f3bd1280ceeULL }
|
||||
|
||||
struct limine_rsdp_response {
|
||||
u64 revision;
|
||||
void *address;
|
||||
};
|
||||
|
||||
struct limine_rsdp_request {
|
||||
u64 id[4];
|
||||
u64 revision;
|
||||
struct limine_rsdp_response *response;
|
||||
};
|
||||
|
||||
#define LIMINE_RSDP_REQUEST_ID { LIMINE_COMMON_MAGIC, 0xc5e77b6b397e7b43ULL, 0x27637845accdcf3cULL }
|
||||
|
||||
struct limine_framebuffer {
|
||||
void *address;
|
||||
u64 width;
|
||||
u64 height;
|
||||
u64 pitch;
|
||||
u16 bpp;
|
||||
u8 memory_model;
|
||||
u8 red_mask_size;
|
||||
u8 red_mask_shift;
|
||||
u8 green_mask_size;
|
||||
u8 green_mask_shift;
|
||||
u8 blue_mask_size;
|
||||
u8 blue_mask_shift;
|
||||
u8 unused[7];
|
||||
u64 edid_size;
|
||||
void *edid;
|
||||
u64 mode_count;
|
||||
struct limine_video_mode **modes;
|
||||
};
|
||||
|
||||
struct limine_video_mode {
|
||||
u64 pitch;
|
||||
u64 width;
|
||||
u64 height;
|
||||
u16 bpp;
|
||||
u8 memory_model;
|
||||
u8 red_mask_size;
|
||||
u8 red_mask_shift;
|
||||
u8 green_mask_size;
|
||||
u8 green_mask_shift;
|
||||
u8 blue_mask_size;
|
||||
u8 blue_mask_shift;
|
||||
};
|
||||
|
||||
struct limine_framebuffer_response {
|
||||
u64 revision;
|
||||
u64 framebuffer_count;
|
||||
struct limine_framebuffer **framebuffers;
|
||||
};
|
||||
|
||||
struct limine_framebuffer_request {
|
||||
u64 id[4];
|
||||
u64 revision;
|
||||
struct limine_framebuffer_response *response;
|
||||
};
|
||||
|
||||
#define LIMINE_FRAMEBUFFER_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x9d5827dcd881dd75ULL, 0xa3148604f6fab11bULL }
|
||||
|
||||
#define LIMINE_MEMMAP_USABLE 0
|
||||
#define LIMINE_MEMMAP_RESERVED 1
|
||||
#define LIMINE_MEMMAP_ACPI_RECLAIMABLE 2
|
||||
#define LIMINE_MEMMAP_ACPI_NVS 3
|
||||
#define LIMINE_MEMMAP_BAD_MEMORY 4
|
||||
#define LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE 5
|
||||
#define LIMINE_MEMMAP_KERNEL_AND_MODULES 6
|
||||
#define LIMINE_MEMMAP_FRAMEBUFFER 7
|
||||
|
||||
struct limine_memmap_entry {
|
||||
u64 base;
|
||||
u64 length;
|
||||
u64 type;
|
||||
};
|
||||
|
||||
struct limine_memmap_response {
|
||||
u64 revision;
|
||||
u64 entry_count;
|
||||
struct limine_memmap_entry **entries;
|
||||
};
|
||||
|
||||
struct limine_memmap_request {
|
||||
u64 id[4];
|
||||
u64 revision;
|
||||
struct limine_memmap_response *response;
|
||||
};
|
||||
|
||||
#define LIMINE_MEMMAP_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x67cf3d9d378a806fULL, 0xe304acdfc50c3c62ULL }
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,45 @@
|
||||
#include <utsm/types.h>
|
||||
|
||||
void outb(u16 port, u8 value);
|
||||
u8 inb(u16 port);
|
||||
|
||||
#define COM1 0x3F8
|
||||
|
||||
static int serial_ready(void) {
|
||||
return (inb(COM1 + 5) & 0x20) != 0;
|
||||
}
|
||||
|
||||
static int serial_wait_ready(void) {
|
||||
for (u64 spin = 0; spin < 1000000ULL; spin++) {
|
||||
if (serial_ready()) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void serial_init(void) {
|
||||
outb(COM1 + 1, 0x00);
|
||||
outb(COM1 + 3, 0x80);
|
||||
outb(COM1 + 0, 0x03);
|
||||
outb(COM1 + 1, 0x00);
|
||||
outb(COM1 + 3, 0x03);
|
||||
outb(COM1 + 2, 0xC7);
|
||||
outb(COM1 + 4, 0x0B);
|
||||
}
|
||||
|
||||
void serial_putc(char c) {
|
||||
if (c == '\n') {
|
||||
serial_putc('\r');
|
||||
}
|
||||
if (!serial_wait_ready()) {
|
||||
return;
|
||||
}
|
||||
outb(COM1, (u8)c);
|
||||
}
|
||||
|
||||
void serial_write(const char *s) {
|
||||
while (*s) {
|
||||
serial_putc(*s++);
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Reference in New Issue
Block a user