TGT=i686
SOURCES= \
- $(TGT)/entry.o \
- $(TGT)/utils.o \
- module/biosvga/module.o module/serial/module.o module/console.o \
+ $(TGT)/entry.o $(TGT)/utils.o $(TGT)/gdt.o $(TGT)/idt.o $(TGT)/timer.o \
+ module/biosvga/module.o \
+ module/console.o \
+ common/stdc/putc.o common/stdc/puts.o common/stdc/vsprintf.o common/stdc/printf.o common/stdc/strcatlen.o common/stdc/dumphex.o \
common/stdc/memmove.o common/stdc/strlen.o common/stdc/memcmp.o common/stdc/memset.o common/stdc/memcpy.o \
common/kernel_main.o
RL=$(TGTNAM)-ranlib
CFLAGS=-ffreestanding -std=gnu11
-CPPFLAGS=-Iinclude -I$(TGT)/include
+CPPFLAGS=-Iinclude -Iinclude/stdc -I$(TGT)/include
LDFLAGS=-T$(LDSC)
ASFLAGS=
LIBS=
#include <module.h>
#include <module_console.h>
+#include <stdio.h>
+
int kernel_main(struct multiboot *mboot_ptr)
{
console_init();
- kprintf("1%c%% %s %X\n", 'c', "whoop", 0xDEADBEEF);
+ printf("1%c%% %s %X\n", 'c', "whoop", 0xDEADBEEF);
console_deinit();
while(1) {
- uint64_t clock = kclock();
- kprintf("%X%X\r", ((uint32_t*)&clock)[1], ((uint32_t*)&clock)[0]);
+ uint64_t ticks = clock();
+ printf("%X%X\r", ((uint32_t*)&ticks)[1], ((uint32_t*)&ticks)[0]);
asm("hlt");
}
--- /dev/null
+#include <string.h>
+#include <stdint.h>
+
+int dumphex(char* buf, const char* index, unsigned int num) {
+ uint8_t *num_8 = (uint8_t *)#
+ char *obuf = buf;
+ for (int i = 3; i >= 0; i--) {
+ uint8_t high = (num_8[i] >> 4) & 0xf;
+ uint8_t low = num_8[i] & 0xf;
+
+ *buf = (index)[high]; buf++;
+ *buf = (index)[low]; buf++;
+ }
+
+ return buf - obuf;
+}
+
#include <string.h>
int memcmp(const void* aptr, const void* bptr, size_t size) {
- const unsigned char* a = (const unsigned char*) aptr;
- const unsigned char* b = (const unsigned char*) bptr;
- for (size_t i = 0; i < size; i++) {
- if (a[i] < b[i])
- return -1;
- else if (b[i] < a[i])
- return 1;
- }
- return 0;
+ const unsigned char* a = (const unsigned char*) aptr;
+ const unsigned char* b = (const unsigned char*) bptr;
+ for (size_t i = 0; i < size; i++) {
+ if (a[i] < b[i])
+ return -1;
+ else if (b[i] < a[i])
+ return 1;
+ }
+ return 0;
}
#include <string.h>
void* memcpy(void* restrict dstptr, const void* restrict srcptr, size_t size) {
- unsigned char* dst = (unsigned char*) dstptr;
- const unsigned char* src = (const unsigned char*) srcptr;
- for (size_t i = 0; i < size; i++)
- dst[i] = src[i];
- return dstptr;
+ unsigned char* dst = (unsigned char*) dstptr;
+ const unsigned char* src = (const unsigned char*) srcptr;
+ for (size_t i = 0; i < size; i++)
+ dst[i] = src[i];
+ return dstptr;
}
#include <string.h>
void* memmove(void* dstptr, const void* srcptr, size_t size) {
- unsigned char* dst = (unsigned char*) dstptr;
- const unsigned char* src = (const unsigned char*) srcptr;
- if (dst < src) {
- for (size_t i = 0; i < size; i++)
- dst[i] = src[i];
- } else {
- for (size_t i = size; i != 0; i--)
- dst[i-1] = src[i-1];
- }
- return dstptr;
+ unsigned char* dst = (unsigned char*) dstptr;
+ const unsigned char* src = (const unsigned char*) srcptr;
+
+ if (dst < src) {
+ for (size_t i = 0; i < size; i++)
+ dst[i] = src[i];
+ } else {
+ for (size_t i = size; i != 0; i--)
+ dst[i-1] = src[i-1];
+ }
+
+ return dstptr;
}
#include <string.h>
void* memset(void* bufptr, int value, size_t size) {
- unsigned char* buf = (unsigned char*) bufptr;
- for (size_t i = 0; i < size; i++)
- buf[i] = (unsigned char) value;
- return bufptr;
+ unsigned char* buf = (unsigned char*) bufptr;
+ for (size_t i = 0; i < size; i++)
+ buf[i] = (unsigned char) value;
+ return bufptr;
}
--- /dev/null
+#include <stdio.h>
+
+void printf(const char* fmt, ...) {
+ char buf[4096];
+ va_list ap;
+ va_start(ap, fmt);
+
+ vsprintf(buf, fmt, ap);
+
+ va_end(ap);
+
+ puts(buf);
+}
+
--- /dev/null
+#include <stdio.h>
+
+void putc(char c) {
+ put_handler(c);
+}
--- /dev/null
+#include <stdio.h>
+
+void puts(char* str) {
+ while(*str != 0) {
+ putc(*str);
+ ++str;
+ }
+}
+
--- /dev/null
+#include <string.h>
+
+int strcatlen(char* a, char* b) {
+ char* o = b;
+ while(*b != 0) {
+ *a = *b;
+ a++;
+ b++;
+ }
+ return b - o;
+}
#include <string.h>
size_t strlen(const char* str) {
- size_t len = 0;
- while (str[len])
- len++;
- return len;
+ size_t len = 0;
+ while (str[len])
+ len++;
+ return len;
}
--- /dev/null
+#include <stdio.h>
+
+void vsprintf(char *buffer, const char* fmt_con, va_list ap) {
+ char* fmt = (char*)fmt_con;
+ char* buf = buffer;
+ while(*fmt != 0) {
+ if (*fmt == '%') {
+ // Format string.
+ ++fmt;
+ switch (*fmt) {
+ case 'c':
+ *buf = (char)va_arg(ap, int);
+ buf++;
+ fmt++;
+ break;
+ case '%':
+ *buf = '%';
+ buf++;
+ fmt++;
+ break;
+ case 's':
+ buf += strcatlen(buf, va_arg(ap, char*));
+ fmt++;
+ break;
+ case 'x':
+ buf += dumphex(buf, "0123456789abcdef", va_arg(ap, unsigned int));
+ ++fmt;
+ break;
+ case 'X':
+ buf += dumphex(buf, "0123456789ABCDEF", va_arg(ap, unsigned int));
+ ++fmt;
+ break;
+ case 'd':
+ case 'u':
+ default:
+ ++fmt;
+ break;
+ }
+ } else {
+ *buf = *fmt;
+ ++buf;
+ ++fmt;
+ }
+ }
+
+ *buf = 0;
+}
--- /dev/null
+#include <stdint.h>
+#include <stddef.h>
+
+#include <stdc/string.h>
+
+// Lets us access our ASM functions from our C code.
+extern void gdt_flush(uint32_t);
+
+// This structure contains the value of one GDT entry.
+// We use the attribute 'packed' to tell GCC not to change
+// any of the alignment in the structure.
+struct gdt_entry_struct
+{
+ uint16_t limit_low; // The lower 16 bits of the limit.
+ uint16_t base_low; // The lower 16 bits of the base.
+ uint8_t base_middle; // The next 8 bits of the base.
+ uint8_t access; // Access flags, determine what ring this segment can be used in.
+ uint8_t granularity;
+ uint8_t base_high; // The last 8 bits of the base.
+} __attribute__((packed));
+typedef struct gdt_entry_struct gdt_entry_t;
+
+struct gdt_ptr_struct
+{
+ uint16_t limit; // The upper 16 bits of all selector limits.
+ uint32_t base; // The address of the first gdt_entry_t struct.
+}
+ __attribute__((packed));
+typedef struct gdt_ptr_struct gdt_ptr_t;
+
+gdt_entry_t gdt_entries[5];
+gdt_ptr_t gdt_ptr;
+
+// Set the value of one GDT entry.
+void gdt_set_gate(int32_t num, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran)
+{
+ gdt_entries[num].base_low = (base & 0xFFFF);
+ gdt_entries[num].base_middle = (base >> 16) & 0xFF;
+ gdt_entries[num].base_high = (base >> 24) & 0xFF;
+
+ gdt_entries[num].limit_low = (limit & 0xFFFF);
+ gdt_entries[num].granularity = (limit >> 16) & 0x0F;
+
+ gdt_entries[num].granularity |= gran & 0xF0;
+ gdt_entries[num].access = access;
+}
+
+void init_gdt()
+{
+ gdt_ptr.limit = (sizeof(gdt_entry_t) * 5) - 1;
+ gdt_ptr.base = (uint32_t)&gdt_entries;
+
+ gdt_set_gate(0, 0, 0, 0, 0); // Null segment
+ gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); // Code segment
+ gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); // Data segment
+ gdt_set_gate(3, 0, 0xFFFFFFFF, 0xFA, 0xCF); // User mode code segment
+ gdt_set_gate(4, 0, 0xFFFFFFFF, 0xF2, 0xCF); // User mode data segment
+
+ gdt_flush((uint32_t)&gdt_ptr);
+}
--- /dev/null
+#include <stdint.h>
+#include <stddef.h>
+
+#include <stdc/string.h>
+
+// A struct describing an interrupt gate.
+struct idt_entry_struct
+{
+ uint16_t base_lo; // The lower 16 bits of the address to jump to when this interrupt fires.
+ uint16_t sel; // Kernel segment selector.
+ uint8_t always0; // This must always be zero.
+ uint8_t flags; // More flags. See documentation.
+ uint16_t base_hi; // The upper 16 bits of the address to jump to.
+} __attribute__((packed));
+typedef struct idt_entry_struct idt_entry_t;
+
+// A struct describing a pointer to an array of interrupt handlers.
+// This is in a format suitable for giving to 'lidt'.
+struct idt_ptr_struct
+{
+ uint16_t limit;
+ uint32_t base; // The address of the first element in our idt_entry_t array.
+} __attribute__((packed));
+typedef struct idt_ptr_struct idt_ptr_t;
+
+idt_entry_t idt_entries[256];
+idt_ptr_t idt_ptr;
+
+void idt_set_gate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags)
+{
+ idt_entries[num].base_lo = base & 0xFFFF;
+ idt_entries[num].base_hi = (base >> 16) & 0xFFFF;
+
+ idt_entries[num].sel = sel;
+ idt_entries[num].always0 = 0;
+ // We must uncomment the OR below when we get to using user-mode.
+ // It sets the interrupt gate's privilege level to 3.
+ idt_entries[num].flags = flags /* | 0x60 */;
+}
+
+struct interrupt_frame
+{
+ uint32_t ds; // Data segment selector
+ uint32_t edi, esi, ebp, reserve, ebx, edx, ecx, eax; // Pushed by pusha.
+ uint32_t int_no, err_code; // Interrupt number and error code (if applicable)
+ uint32_t eip, cs, eflags, esp, ss; // Pushed by the processor automatically.
+};
+
+void isr_handler(struct interrupt_frame* esp) {
+}
+
+int ticks_lock = 0;
+uint64_t ticks = 0;
+
+uint64_t clock() {
+ return ticks;
+}
+
+char table[255] = {
+ 0, 0, '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, '+', ' ',
+};
+
+uint32_t timer_lock;
+
+void irq_handler(struct interrupt_frame* esp) {
+ char c_kb = 0;
+
+ if (esp->int_no >= 7) {
+ outb(0xA0, 0x20);
+ }
+
+ outb(0x20, 0x20);
+
+ switch(esp->int_no) {
+ case 0:
+ ++ticks;
+ break;
+ case 1:
+ c_kb = inb(0x60);
+ putc(table[c_kb]);
+ break;
+ default:
+ break;
+ }
+}
+
+extern void isr_0();
+extern void isr_1();
+extern void isr_2();
+extern void isr_3();
+extern void isr_4();
+extern void isr_5();
+extern void isr_6();
+extern void isr_7();
+extern void isr_8();
+extern void isr_9();
+extern void isr_10();
+extern void isr_11();
+extern void isr_12();
+extern void isr_13();
+extern void isr_14();
+extern void isr_15();
+extern void isr_16();
+extern void isr_17();
+extern void isr_18();
+extern void isr_19();
+extern void isr_20();
+extern void isr_21();
+extern void isr_22();
+extern void isr_23();
+extern void isr_24();
+extern void isr_25();
+extern void isr_26();
+extern void isr_27();
+extern void isr_28();
+extern void isr_29();
+extern void isr_30();
+extern void isr_31();
+
+extern void irq_0();
+extern void irq_1();
+extern void irq_2();
+extern void irq_3();
+extern void irq_4();
+extern void irq_5();
+extern void irq_6();
+extern void irq_7();
+extern void irq_8();
+extern void irq_9();
+extern void irq_10();
+extern void irq_11();
+extern void irq_12();
+extern void irq_13();
+extern void irq_14();
+extern void irq_15();
+
+#define ISR_CALL(N) \
+ idt_set_gate( N , (uint32_t) isr_##N , 0x08, 0x8E )
+
+#define IRQ_CALL(N) \
+ idt_set_gate( 32 + N , (uint32_t) irq_##N , 0x08, 0x8E )
+
+void init_idt()
+{
+ idt_ptr.limit = sizeof(idt_entry_t) * 256 - 1;
+ idt_ptr.base = (uint32_t)&idt_entries;
+
+ memset(&idt_entries, 0, sizeof(idt_entry_t)*256);
+
+ ISR_CALL(0);
+ ISR_CALL(1);
+ ISR_CALL(2);
+ ISR_CALL(3);
+ ISR_CALL(4);
+ ISR_CALL(5);
+ ISR_CALL(6);
+ ISR_CALL(7);
+ ISR_CALL(8);
+ ISR_CALL(9);
+ ISR_CALL(10);
+ ISR_CALL(11);
+ ISR_CALL(12);
+ ISR_CALL(13);
+ ISR_CALL(14);
+ ISR_CALL(15);
+ ISR_CALL(16);
+ ISR_CALL(17);
+ ISR_CALL(18);
+ ISR_CALL(19);
+ ISR_CALL(20);
+ ISR_CALL(21);
+ ISR_CALL(22);
+ ISR_CALL(23);
+ ISR_CALL(24);
+ ISR_CALL(25);
+ ISR_CALL(26);
+ ISR_CALL(27);
+ ISR_CALL(28);
+ ISR_CALL(29);
+ ISR_CALL(30);
+ ISR_CALL(31);
+
+ outb(0x20, 0x11);
+ outb(0xA0, 0x11);
+
+ outb(0x21, 0x20);
+ outb(0xA1, 0x28);
+
+ outb(0x21, 0x04);
+ outb(0xA1, 0x02);
+
+ outb(0x21, 0x01);
+ outb(0xA1, 0x01);
+
+ outb(0x21, 0x0);
+ outb(0xA1, 0x0);
+
+ IRQ_CALL(0);
+ IRQ_CALL(1);
+ IRQ_CALL(2);
+ IRQ_CALL(3);
+ IRQ_CALL(4);
+ IRQ_CALL(5);
+ IRQ_CALL(6);
+ IRQ_CALL(7);
+ IRQ_CALL(8);
+ IRQ_CALL(9);
+ IRQ_CALL(10);
+ IRQ_CALL(11);
+ IRQ_CALL(12);
+ IRQ_CALL(13);
+ IRQ_CALL(14);
+ IRQ_CALL(15);
+
+ idt_flush((uint32_t)&idt_ptr);
+
+ asm volatile ("sti");
+}
--- /dev/null
+#include <stdint.h>
+#include <stddef.h>
+
+#include <stdc/string.h>
+
+int set_pitdiv(int freq) {
+ uint32_t div = 1193180 / freq;
+ outb(0x43, 0x36);
+
+ // Divisor has to be sent byte-wise, so split here into upper/lower bytes.
+ uint8_t l = (uint8_t)(div & 0xFF);
+ uint8_t h = (uint8_t)( (div >> 8) & 0xFF );
+
+ // Send the frequency divisor.
+ outb(0x40, l);
+ outb(0x40, h);
+}
return ret;
}
-
-// Lets us access our ASM functions from our C code.
-extern void gdt_flush(uint32_t);
-
-// This structure contains the value of one GDT entry.
-// We use the attribute 'packed' to tell GCC not to change
-// any of the alignment in the structure.
-struct gdt_entry_struct
-{
- uint16_t limit_low; // The lower 16 bits of the limit.
- uint16_t base_low; // The lower 16 bits of the base.
- uint8_t base_middle; // The next 8 bits of the base.
- uint8_t access; // Access flags, determine what ring this segment can be used in.
- uint8_t granularity;
- uint8_t base_high; // The last 8 bits of the base.
-} __attribute__((packed));
-typedef struct gdt_entry_struct gdt_entry_t;
-
-struct gdt_ptr_struct
-{
- uint16_t limit; // The upper 16 bits of all selector limits.
- uint32_t base; // The address of the first gdt_entry_t struct.
-}
- __attribute__((packed));
-typedef struct gdt_ptr_struct gdt_ptr_t;
-
-gdt_entry_t gdt_entries[5];
-gdt_ptr_t gdt_ptr;
-
-// Set the value of one GDT entry.
-static void gdt_set_gate(int32_t num, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran)
-{
- gdt_entries[num].base_low = (base & 0xFFFF);
- gdt_entries[num].base_middle = (base >> 16) & 0xFF;
- gdt_entries[num].base_high = (base >> 24) & 0xFF;
-
- gdt_entries[num].limit_low = (limit & 0xFFFF);
- gdt_entries[num].granularity = (limit >> 16) & 0x0F;
-
- gdt_entries[num].granularity |= gran & 0xF0;
- gdt_entries[num].access = access;
-}
-
-static void init_gdt()
-{
- gdt_ptr.limit = (sizeof(gdt_entry_t) * 5) - 1;
- gdt_ptr.base = (uint32_t)&gdt_entries;
-
- gdt_set_gate(0, 0, 0, 0, 0); // Null segment
- gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); // Code segment
- gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); // Data segment
- gdt_set_gate(3, 0, 0xFFFFFFFF, 0xFA, 0xCF); // User mode code segment
- gdt_set_gate(4, 0, 0xFFFFFFFF, 0xF2, 0xCF); // User mode data segment
-
- gdt_flush((uint32_t)&gdt_ptr);
-}
-
-// A struct describing an interrupt gate.
-struct idt_entry_struct
-{
- uint16_t base_lo; // The lower 16 bits of the address to jump to when this interrupt fires.
- uint16_t sel; // Kernel segment selector.
- uint8_t always0; // This must always be zero.
- uint8_t flags; // More flags. See documentation.
- uint16_t base_hi; // The upper 16 bits of the address to jump to.
-} __attribute__((packed));
-typedef struct idt_entry_struct idt_entry_t;
-
-// A struct describing a pointer to an array of interrupt handlers.
-// This is in a format suitable for giving to 'lidt'.
-struct idt_ptr_struct
-{
- uint16_t limit;
- uint32_t base; // The address of the first element in our idt_entry_t array.
-} __attribute__((packed));
-typedef struct idt_ptr_struct idt_ptr_t;
-
-idt_entry_t idt_entries[256];
-idt_ptr_t idt_ptr;
-
-static void idt_set_gate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags)
-{
- idt_entries[num].base_lo = base & 0xFFFF;
- idt_entries[num].base_hi = (base >> 16) & 0xFFFF;
-
- idt_entries[num].sel = sel;
- idt_entries[num].always0 = 0;
- // We must uncomment the OR below when we get to using user-mode.
- // It sets the interrupt gate's privilege level to 3.
- idt_entries[num].flags = flags /* | 0x60 */;
-}
-
-struct interrupt_frame
-{
- uint32_t ds; // Data segment selector
- uint32_t edi, esi, ebp, reserve, ebx, edx, ecx, eax; // Pushed by pusha.
- uint32_t int_no, err_code; // Interrupt number and error code (if applicable)
- uint32_t eip, cs, eflags, esp, ss; // Pushed by the processor automatically.
-};
-
-char *strs_isr[] = {
- "divide by zero",
- "debug exception",
- "non maskable interrupt",
- "breakpoint",
- "into detected overflow",
- "out of bounds exception",
- "invalid opcode exception",
- "no coprocessor exception",
- "double fault",
- "coprocessor segment overrun",
- "bad tss",
- "segment not present",
- "stack fault",
- "general protection fault",
- "page fault",
- "unknown interrupt",
- "coprocessor fault",
- "alignment check exception",
- "machine check exception"
-};
-
-void isr_handler(struct interrupt_frame* esp) {
- kprintf("int %x: ", esp->int_no);
- if (esp->int_no <= 18) {
- kprintf("%s\n", strs_isr[esp->int_no]);
- } else {
- kprintf("reserved\n");
- }
-}
-
-uint64_t ticks = 0;
-
-uint64_t kclock() {
- return ticks;
-}
-
-char *irq_strs[] = {
- "PIT",
- "Keyboard",
- "Cascade",
- "COM2",
- "COM1",
- "LPT1",
- "CMOS rtc",
- "Peripheral 1",
- "Peripheral 2",
- "Peripheral 3",
- "PS/2 Mouse",
- "FPU/Coprocessor",
- "ATA0",
- "ATA1",
-};
-
-void irq_handler(struct interrupt_frame* esp) {
- char c_kb;
-
- if (esp->int_no >= 7) {
- outb(0xA0, 0x20);
- }
-
- outb(0x20, 0x20);
-
- switch(esp->int_no) {
- case 0:
- ++ticks;
- break;
- case 1:
- c_kb = inb(0x60);
- kputc(c_kb);
- break;
- default:
- break;
- }
-}
-
-extern void isr_0();
-extern void isr_1();
-extern void isr_2();
-extern void isr_3();
-extern void isr_4();
-extern void isr_5();
-extern void isr_6();
-extern void isr_7();
-extern void isr_8();
-extern void isr_9();
-extern void isr_10();
-extern void isr_11();
-extern void isr_12();
-extern void isr_13();
-extern void isr_14();
-extern void isr_15();
-extern void isr_16();
-extern void isr_17();
-extern void isr_18();
-extern void isr_19();
-extern void isr_20();
-extern void isr_21();
-extern void isr_22();
-extern void isr_23();
-extern void isr_24();
-extern void isr_25();
-extern void isr_26();
-extern void isr_27();
-extern void isr_28();
-extern void isr_29();
-extern void isr_30();
-extern void isr_31();
-
-extern void irq_0();
-extern void irq_1();
-extern void irq_2();
-extern void irq_3();
-extern void irq_4();
-extern void irq_5();
-extern void irq_6();
-extern void irq_7();
-extern void irq_8();
-extern void irq_9();
-extern void irq_10();
-extern void irq_11();
-extern void irq_12();
-extern void irq_13();
-extern void irq_14();
-extern void irq_15();
-
-#define ISR_CALL(N) \
- idt_set_gate( N , (uint32_t) isr_##N , 0x08, 0x8E )
-
-#define IRQ_CALL(N) \
- idt_set_gate( 32 + N , (uint32_t) irq_##N , 0x08, 0x8E )
-
-static void init_idt()
-{
- idt_ptr.limit = sizeof(idt_entry_t) * 256 - 1;
- idt_ptr.base = (uint32_t)&idt_entries;
-
- memset(&idt_entries, 0, sizeof(idt_entry_t)*256);
-
- ISR_CALL(0);
- ISR_CALL(1);
- ISR_CALL(2);
- ISR_CALL(3);
- ISR_CALL(4);
- ISR_CALL(5);
- ISR_CALL(6);
- ISR_CALL(7);
- ISR_CALL(8);
- ISR_CALL(9);
- ISR_CALL(10);
- ISR_CALL(11);
- ISR_CALL(12);
- ISR_CALL(13);
- ISR_CALL(14);
- ISR_CALL(15);
- ISR_CALL(16);
- ISR_CALL(17);
- ISR_CALL(18);
- ISR_CALL(19);
- ISR_CALL(20);
- ISR_CALL(21);
- ISR_CALL(22);
- ISR_CALL(23);
- ISR_CALL(24);
- ISR_CALL(25);
- ISR_CALL(26);
- ISR_CALL(27);
- ISR_CALL(28);
- ISR_CALL(29);
- ISR_CALL(30);
- ISR_CALL(31);
-
- outb(0x20, 0x11);
- outb(0xA0, 0x11);
-
- outb(0x21, 0x20);
- outb(0xA1, 0x28);
-
- outb(0x21, 0x04);
- outb(0xA1, 0x02);
-
- outb(0x21, 0x01);
- outb(0xA1, 0x01);
-
- outb(0x21, 0x0);
- outb(0xA1, 0x0);
-
- IRQ_CALL(0);
- IRQ_CALL(1);
- IRQ_CALL(2);
- IRQ_CALL(3);
- IRQ_CALL(4);
- IRQ_CALL(5);
- IRQ_CALL(6);
- IRQ_CALL(7);
- IRQ_CALL(8);
- IRQ_CALL(9);
- IRQ_CALL(10);
- IRQ_CALL(11);
- IRQ_CALL(12);
- IRQ_CALL(13);
- IRQ_CALL(14);
- IRQ_CALL(15);
-
- idt_flush((uint32_t)&idt_ptr);
-
- asm volatile ("sti");
-}
-
-int set_pitdiv(int freq) {
- uint32_t div = 1193180 / freq;
- outb(0x43, 0x36);
-
- // Divisor has to be sent byte-wise, so split here into upper/lower bytes.
- uint8_t l = (uint8_t)(div & 0xFF);
- uint8_t h = (uint8_t)( (div >> 8) & 0xFF );
-
- // Send the frequency divisor.
- outb(0x40, l);
- outb(0x40, h);
-}
+void init_gdt();
+void init_idt();
+int set_pitdiv(int freq);
void i686_init() {
init_gdt();
#include <stdarg.h>
-typedef void (*console_put_f) (char, char, char, uint16_t, uint16_t);
-typedef void (*console_get_f) (char*, char*, char*, uint16_t, uint16_t);
-typedef void (*console_cursor_f) (uint16_t, uint16_t);
-typedef uint16_t (*console_width_f) ();
-typedef uint16_t (*console_height_f) ();
-typedef void (*console_refresh_f)();
-typedef int (*console_tty_f) ();
+typedef void (*module_out_f) (char);
-struct console_module {
- console_put_f put;
- console_get_f get;
- console_cursor_f cursor;
- console_width_f width;
- console_height_f height;
- console_refresh_f refresh;
- console_tty_f tty;
+struct output {
+ module_out_f out;
};
-void console_register_module(struct console_module*);
-void console_unregister_module(struct console_module*);
+void console_reg(struct output*);
+void console_unreg(struct output*);
void console_init();
void console_deinit();
-
-void kputc(char);
-void kwrite(char*);
-void kvsprintf(char *buffer, const char* fmt_con, va_list ap);
-void kprintf(const char* fmt, ...);
-
--- /dev/null
+#ifndef _STRING_H
+#define _STRING_H 1
+
+#include <sys/cdefs.h>
+#include <stddef.h>
+#include <stdarg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int dumphex (char* buf, const char* index, unsigned int num);
+void putc (char c);
+void puts (char* str);
+void vsprintf (char *buffer, const char* fmt_con, va_list ap);
+void printf (const char* fmt_con, ...);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
extern "C" {
#endif
-int memcmp(const void*, const void*, size_t);
-void* memcpy(void* __restrict, const void* __restrict, size_t);
-void* memmove(void*, const void*, size_t);
-void* memset(void*, int, size_t);
-size_t strlen(const char*);
+int memcmp (const void*, const void*, size_t);
+void* memcpy (void* __restrict, const void* __restrict, size_t);
+void* memmove (void*, const void*, size_t);
+void* memset (void*, int, size_t);
+size_t strlen (const char*);
+int strcatlen (char*, char*);
#ifdef __cplusplus
}
#include <stdint.h>
+#include <string.h>
#include <module.h>
#include <module_console.h>
-uint16_t *video_mem = (uint16_t*)0xC00B8000;
-
-void biosvga_put(char c, char color_fg, char color_bg, uint16_t x, uint16_t y) {
- uint8_t attr = (color_bg << 4) | (color_fg & 0xF);
- uint16_t write = (attr << 8) | c;
+#define WIDTH 80
+#define HEIGHT 25
- video_mem[y * 80 + x] = write;
-}
+int x, y;
-void biosvga_get(char* c, char* color_fg, char* color_bg, uint16_t x, uint16_t y) {
- uint16_t write = video_mem[y * 80 + x];
- *c = (char)(write & 0xFF);
- *color_bg = (write << 12) & 0xF;
- *color_fg = (write << 8) & 0xF;
-}
+uint16_t *video_mem = (uint16_t*)0xC00B8000;
-void biosvga_cursor(uint16_t x, uint16_t y) {
+void cursor(uint16_t x, uint16_t y) {
uint16_t loc = y * 80 + x;
outb(0x3D4, 14);
outb(0x3D5, loc >> 8);
outb(0x3D5, loc);
}
-uint16_t biosvga_width() {
- return 80;
-}
+void biosvga_wb(char c) {
+ uint8_t color_bg = 0;
+ uint8_t color_fg = 0xF;
+ uint8_t attr = (color_bg << 4) | (color_fg & 0xF);
+ uint16_t write = (attr << 8) | c;
-uint16_t biosvga_height() {
- return 25;
-}
+ switch(c) {
+ case '\n':
+ y++;
+ case '\r':
+ x = 0;
+ break;
+ case '\b':
+ if (x) --x;
+ break;
+ case '\t':
+ x += 4 - (x % 4);
+ break;
+ case ' ' ... '~':
+ video_mem[y * 80 + x] = write;
+ ++x;
+ break;
+ }
-void biosvga_refresh() {
+ if (x >= WIDTH) {
+ x = 0;
+ ++y;
+ }
-}
+ if (y >= HEIGHT) {
+ memcpy(video_mem, &video_mem[80], (HEIGHT - 1) * 80 * sizeof(uint16_t));
+ --y;
+ memset(&video_mem[y * 80], 0, 160);
+ }
-int biosvga_tty() {
- return 1;
+ cursor(x, y);
}
-struct console_module biosvga_module = {
- .put = biosvga_put,
- .get = biosvga_get,
- .tty = biosvga_tty,
- .cursor = biosvga_cursor,
- .width = biosvga_width,
- .height = biosvga_height,
- .refresh = biosvga_refresh
+struct output biosvga_module = {
+ .out = biosvga_wb
};
void biosvga_init() {
- console_register_module(&biosvga_module);
+ x = y = 0;
+ console_reg(&biosvga_module);
}
void biosvga_deinit() {
- console_unregister_module(&biosvga_module);
+ console_unreg(&biosvga_module);
// Stub.
}
#include <module.h>
#include <module_console.h>
-struct console_module *active;
-struct console_module *reg[2];
-uint16_t x, y, tab_w;
+struct output *active;
-void biosvga_init();
-void biosvga_deinit();
-
-void console_mark_active(int idx) {
- active = reg[idx];
-}
-
-void console_register_module(struct console_module* module) {
- reg[1] = reg[0];
- reg[0] = module;
-}
-
-void console_unregister_module(struct console_module* module) {
- if (reg[0] == module)
- reg[0] = reg[1];
- if (reg[1] == module)
- reg[1] = NULL;
+void put_handler(char c) {
+ active->out(c);
}
-// TODO - Should this be part of the backend? Scrolling is slow.
-void scroll() {
- if (active->tty() == 0)
- return;
-
- if (y >= active->height()) {
- for(int cy = 1; cy <= active->height(); cy++) {
- for(int cx = 0; cx <= active->width(); cx++) {
- char c = 0;
- uint8_t fg = 0, bg = 0;
- active->get(&c, &fg, &bg, cx, cy);
- active->put(c, 0xf, 0, cx, cy-1);
- }
- }
- --y;
- for(int cx = 0; cx < active->width(); cx++) {
- active->put(' ', 0xf, 0, cx, y);
- }
- }
+void console_reg(struct output* out) {
+ active = out;
}
-// TODO - Should this be part of the backend? Scrolling is slow.
-void clear() {
- if (active->tty() == 0)
- return;
-
- x = y = 0;
- for(int cy = 0; cy < active->height(); cy++) {
- for(int cx = 0; cx < active->width(); cx++) {
- active->put(' ', 0xf, 0x0, cx, cy);
- }
- }
-}
-
-void kputc(char c) {
- switch(c) {
- case '\t':
- x += tab_w - (x % tab_w);
- break;
- case '\b':
- --x;
- break;
- case '\n':
- ++y;
- case '\r':
- x = 0;
- break;
- case ' ' ... '~':
- active->put(c, 0xf, 0x0, x, y);
- default:
- x += 1;
- break;
- }
-
- if (x > active->width()) {
- x = 0;
- ++y;
- }
-
- scroll();
- if (active->tty() == 1)
- active->cursor(x, y);
-}
-
-void kwrite(char* str) {
- while(*str != 0) {
- kputc(*str);
- ++str;
- }
-}
-
-int strcatlen(char* a, char* b) {
- char* o = b;
- while(*b != 0) {
- *a = *b;
- a++;
- b++;
- }
- return b - o;
-}
-
-int dumphex(char* buf, const char* index, unsigned int num) {
- uint8_t *num_8 = (uint8_t *)#
- char *obuf = buf;
- for (int i = 3; i >= 0; i--) {
- uint8_t high = (num_8[i] >> 4) & 0xf;
- uint8_t low = num_8[i] & 0xf;
-
- *buf = (index)[high]; buf++;
- *buf = (index)[low]; buf++;
- }
-
- return buf - obuf;
-}
-
-void kvsprintf(char *buffer, const char* fmt_con, va_list ap) {
- char* fmt = (char*)fmt_con;
- char* buf = buffer;
- while(*fmt != 0) {
- if (*fmt == '%') {
- // Format string.
- ++fmt;
- switch (*fmt) {
- case 'c':
- *buf = (char)va_arg(ap, int);
- buf++;
- fmt++;
- break;
- case '%':
- *buf = '%';
- buf++;
- fmt++;
- break;
- case 's':
- buf += strcatlen(buf, va_arg(ap, char*));
- fmt++;
- break;
- case 'x':
- buf += dumphex(buf, "0123456789abcdef", va_arg(ap, unsigned int));
- ++fmt;
- break;
- case 'X':
- buf += dumphex(buf, "0123456789ABCDEF", va_arg(ap, unsigned int));
- ++fmt;
- break;
- case 'd':
- case 'u':
- default:
- ++fmt;
- break;
- }
- } else {
- *buf = *fmt;
- ++buf;
- ++fmt;
- }
- }
-
- *buf = 0;
-}
-
-char buf[4096];
-
-void kprintf(const char* fmt, ...) {
- va_list ap;
- va_start(ap, fmt);
-
- kvsprintf(buf, fmt, ap);
-
- va_end(ap);
-
- kwrite(buf);
-}
-
-void defer_kprintf(const char* fmt, ...) {
- va_list ap;
- va_start(ap, fmt);
-
- kvsprintf(buf, fmt, ap);
-
- va_end(ap);
-}
-
-void flush_defer_kprintf() {
- kwrite(buf);
+void console_unreg(struct output* out) {
+ active = out;
}
void console_init() {
- x = y = 0;
- tab_w = 4;
-
// Temporary
- serial_init();
biosvga_init();
-
- console_mark_active(0);
-
- clear();
}
void console_deinit() {
// Temporary
biosvga_deinit();
- serial_deinit();
}
return inb(PORT + 5) & 0x20;
}
-void serial_put(char c, char color_fg, char color_bg, uint16_t x, uint16_t y) {
+void serial_wb(char c) {
while (is_transmit_empty() == 0);
outb(PORT, c);
}
-void serial_get(char* c, char* color_fg, char* color_bg, uint16_t x, uint16_t y) {
+char serial_rb(void) {
}
-int serial_tty() {
- return 0;
-}
-
-struct console_module serial_module = {
- .put = serial_put,
- .get = serial_get,
- .tty = serial_tty
+struct port_module serial_module = {
+ .write = serial_wb,
+ .read = serial_rb,
};
void serial_init() {
outb(PORT + 3, 0x03); // 8 bits, no parity, one stop bit
outb(PORT + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
outb(PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
-
- console_register_module(&serial_module);
}
void serial_deinit() {
- console_unregister_module(&serial_module);
- // Stub.
}