diff --git a/kernel/include/gdt.h b/kernel/include/gdt.h new file mode 100644 index 0000000..750f9ef --- /dev/null +++ b/kernel/include/gdt.h @@ -0,0 +1,122 @@ +#ifndef _GDT_H +#define _GDT_H + +#include + +/* + * Entries: + * 0 Null desc. + * 1 Kernel code desc. + * 2 Kernel data desc. + * 3 SYSENTER + * 4 SYSEXIT + * 5 User code desc. + * 6 User data desc. + * 7 Task State Segment + */ +#define GDT_ENTRIES 8 +#define GDT_KERNEL_CODE 0x28 +#define GDT_KERNEL_DATA 0x30 +#define GDT_USER_CODE 0x50 +#define GDT_USER_DATA 0x48 +#define GDT_TSS 0x50 + +/* + * Segment selector explanation (why kcode is 0x08?) + * + * Each segment selector must be 16 bits. These bits + * have the following layout: (example is 0x08) + * 0000000000001 0 00 (lsb) + * | | '- Privilege level + * | '--- Table indicator + * '------ Index in table + * + * Bits 0-1 are the privilege level. x86 has four, + * where 00 is the highest and 11 is the lowest. Only + * these two are widely used. 00 being kernel space & + * 11 being userspace. Bit 3 is the table indicator. + * 0 means the GDT and 1 means the LDT. This will most + * likely be 0. Bits 4-15 are the index. This is just + * which descriptor in the table is used. + * + * SO, for the kernel code segment: + * Privilege is 00 for kernel space, table indicator + * s 0 for the GDT and the index is one, because it + * is the second entry in our GDT (after null desc.) + */ +#define SEGMENT_SEL(_priv, _tab, _i)\ + (uint16_t)(((_i) << 3) | ((_tab) << 2) | (_priv)) + +struct gdt_entry { + uint16_t limit; + uint16_t baseLow; + uint8_t baseMid; + uint8_t access; + uint8_t granulatiry; + uint8_t baseHigh; +} __packed; + +struct gdt_pointer { + uint16_t limit; + uint32_t base; +} __packed; + +struct tss_entry { + uint16_t length; + uint16_t baseLow; + uint8_t baseMid; + uint8_t flags1; + uint8_t flags2; + uint8_t baseHigh; +} __packed; + +struct tss_pointer { + uint16_t link; + uint16_t __reserved0; + uint32_t esp0; + uint16_t ss0; + uint16_t __reserved1; + uint32_t esp1; + uint16_t ss1; + uint16_t __reserved2; + uint32_t esp2; + uint16_t ss2; + uint16_t __reserved3; + uint32_t cr3; + uint32_t eip; + uint32_t eflags; + uint32_t eax; + uint32_t ecx; + uint32_t edx; + uint32_t ebx; + uint32_t esp; + uint32_t ebs; + uint32_t ebp; + uint32_t esi; + uint32_t edi; + uint16_t es; + uint16_t __reserved4; + uint16_t cs; + uint16_t __reserved5; + uint16_t ss; + uint16_t __reserved6; + uint16_t ds; + uint16_t __reserved7; + uint16_t fs; + uint16_t __reserved8; + uint16_t gs; + uint16_t __reserved9; + uint16_t ldtr; + uint32_t __reserved10; + uint16_t iopb; + uint32_t ssp; +} __packed; + +struct gdt_entries { + struct gdt_entry descriptors[GDT_ENTRIES - 1]; // Subtract one for TSS + struct tss_entry tss; +}; + +int gdt_init(void); + +#endif diff --git a/kernel/include/kernel.h b/kernel/include/kernel.h index 703b0f3..021a2c5 100644 --- a/kernel/include/kernel.h +++ b/kernel/include/kernel.h @@ -77,14 +77,14 @@ extern uint32_t __kernel_start, __kernel_end; /* * Logging and errors */ -// TODO -#define printk(_s) NULL -#define pr_dbg(_s) NULL -#define pr_wrn(_s) NULL -#define pr_err(_s) NULL -#define panic(_s) NULL -#define BUG() NULL -#define WARN() NULL +#include +#define printk debugf +#define pr_dbg(_s) printk("[debug] %s\n", (_s)) +#define pr_wrn(_s) printk("[warning] %s\n", (_s)) +#define pr_err(_s) printk("[error] %s\n", (_s)) +#define panic(_s) printk("[panic] %s\n", (_s)) +#define BUG() panic("BUG()") +#define WARN() pr_wrn("WARN()") #define BUG_ON(_e) ((_e) ? BUG() : NULL) #define WARN_ON(_e) ((_e) ? WARN() : NULL) diff --git a/kernel/include/string.h b/kernel/include/string.h new file mode 100644 index 0000000..3567b19 --- /dev/null +++ b/kernel/include/string.h @@ -0,0 +1,24 @@ +#ifndef _STRING_H +#define _STRING_H + +#include + +// Memory functions +void* memchr(const void* ptr, uint8_t val, size_t len); +int memcmp(const void* ptr1, const void* ptr2, size_t len); +void* memcpy(void* dst, const void* src, size_t len); +void* memmov(void* dst, const void* src, size_t len); +void* memset(void* dst, uint8_t val, size_t len); + +// String functions +char* strbrk(char* str, const char* accept); +char* strcat(char* dst, const char* src); +char* strchr(const char* str, char c); +int strcmp(const char* str1, const char* str2); +char* strcpy(char* dst, const char* src); +size_t strlen(const char* str); +size_t strspn(const char* str, const char* accept); +char* strstr(const char* str1, const char* str2); +char* strtok(char* str, const char* delim); + +#endif diff --git a/kernel/src/gdt.c b/kernel/src/gdt.c new file mode 100644 index 0000000..2f3b339 --- /dev/null +++ b/kernel/src/gdt.c @@ -0,0 +1,102 @@ +#include +#include +#include + +static struct gdt_entries gdt; +static struct gdt_pointer gdtp; +static struct tss_pointer tss; +struct tss_pointer* tssp = &tss; + +void gdt_loadTss(struct tss_pointer* ptr) { + size_t addr = (size_t)ptr; + + gdt.tss.baseLow = (uint16_t)addr; + gdt.tss.baseMid = (uint8_t)(addr >> 16); + gdt.tss.flags1 = 0x89; + gdt.tss.flags2 = 0; + gdt.tss.baseHigh = (uint8_t)(addr >> 24); + + __asm__ volatile ("ltr %0" : : "rm"(SEGMENT_SEL(0, 0, 7))); +} + +void gdt_reload(void) { + __asm__ volatile ( + "cli\n" + "lgdt (%0)\n" + "ljmp $0x08, $1f\n" + "1:\n" + "movw $0x10, %%ax\n" + "movw %%ax, %%ds\n" + "movw %%ax, %%es\n" + "movw %%ax, %%fs\n" + "movw %%ax, %%gs\n" + "movw %%ax, %%ss\n" + : + : "m" (gdtp) + : "memory", "rax" + ); +} + +int gdt_init(void) { + // Null descriptor (0) + gdt.descriptors[0].limit = 0; + gdt.descriptors[0].baseLow = 0; + gdt.descriptors[0].baseMid = 0; + gdt.descriptors[0].access = 0; + gdt.descriptors[0].granulatiry = 0; + gdt.descriptors[0].baseHigh = 0; + + // Kernel code (8) + gdt.descriptors[1].limit = 0xffff; + gdt.descriptors[1].baseLow = 0; + gdt.descriptors[1].baseMid = 0; + gdt.descriptors[1].access = 0x9a; + gdt.descriptors[1].granulatiry = 0xcf; + gdt.descriptors[1].baseHigh = 0; + + // Kernel data (16) + gdt.descriptors[2].limit = 0xffff; + gdt.descriptors[2].baseLow = 0; + gdt.descriptors[2].baseMid = 0; + gdt.descriptors[2].access = 0x90; + gdt.descriptors[2].granulatiry = 0xcf; + gdt.descriptors[2].baseHigh = 0; + + // SYSENTER/SYSEXIT + gdt.descriptors[3] = (struct gdt_entry){ 0 }; // (24) + gdt.descriptors[4] = (struct gdt_entry){ 0 }; // (32) + + // User code (40) + gdt.descriptors[5].limit = 0; + gdt.descriptors[5].baseLow = 0; + gdt.descriptors[5].baseMid = 0; + gdt.descriptors[5].access = 0xfa; + gdt.descriptors[5].granulatiry = 0x20; + gdt.descriptors[5].baseHigh = 0; + + // User data (48) + gdt.descriptors[6].limit = 0; + gdt.descriptors[6].baseLow = 0; + gdt.descriptors[6].baseMid = 0; + gdt.descriptors[6].access = 0xf2; + gdt.descriptors[6].granulatiry = 0; + gdt.descriptors[6].baseHigh = 0; + + // TSS (56) + gdt.tss.length = 104; + gdt.tss.baseLow = 0; + gdt.tss.baseMid = 0; + gdt.tss.flags1 = 0x89; + gdt.tss.flags2 = 0; + gdt.tss.baseHigh = 0; + + gdtp.limit = sizeof(struct gdt_entries) - 1; + gdtp.base = (uint32_t)&gdt; + + gdt_reload(); + + memset(tssp, 0, sizeof(struct tss_pointer)); + gdt_loadTss(tssp); + return 0; +} + diff --git a/kernel/src/kernel.c b/kernel/src/kernel.c index 7d7953f..e7a815d 100644 --- a/kernel/src/kernel.c +++ b/kernel/src/kernel.c @@ -1,9 +1,10 @@ #include #include #include +#include #include -/* TODO: Commented out stuff */ +// TODO: Commented out stuff __noreturn void kmain(void* ptr, uint32_t magic) { @@ -23,9 +24,10 @@ void kmain(void* ptr, uint32_t magic) { // pmm_init(); // vmm_init(); - // gdt_init(); + gdt_init(); // isr_init(); // pag_init(); + while (1); debugf("Basic initialization complete!\n"); diff --git a/kernel/src/string.c b/kernel/src/string.c new file mode 100644 index 0000000..2c1127a --- /dev/null +++ b/kernel/src/string.c @@ -0,0 +1,104 @@ +#include +#include + +void* memchr(const void* ptr, uint8_t val, size_t len) { + const uint8_t* p = ptr; + while (len--) if (*p++ == val) return (void*)(p - 1); + return NULL; +} + +int memcmp(const void* ptr1, const void* ptr2, size_t len) { + const uint8_t* p1 = ptr1; + const uint8_t* p2 = ptr2; + while (len--) if (*p1++ != *p2++) return p1[-1] - p2[-1]; + return 0; +} + +void* memcpy(void* dst, const void* src, size_t len) { + uint8_t* d = dst; + const uint8_t* s = src; + while (len--) *d++ = *s++; + return dst; +} + +void* memmov(void* dst, const void* src, size_t len) { + uint8_t* d = dst; + const uint8_t* s = src; + if (d < s) while (len--) *d++ = *s++; + else while (len--) d[len] = s[len]; + return dst; +} + +void* memset(void* dst, uint8_t val, size_t len) { + uint8_t* d = dst; + while (len--) *d++ = val; + return dst; +} + +char* strbrk(char* str, const char* accept) { + while (*str) { + if (strchr(accept, *str)) return (char*)str; + str++; + } + return NULL; +} + +char* strcat(char* dst, const char* src) { + char* d = dst; + while (*d) d++; + while ((*d++ = *src++)); + return dst; +} + +char* strchr(const char* str, char c) { + while (*str) if (*str++ == c) return (char*)(str - 1); + return NULL; +} + +int strcmp(const char* str1, const char* str2) { + while (*str1 && (*str1 == *str2)) str1++, str2++; + return (int)(*(uint8_t*)str1 - *(uint8_t*)str2); +} + +char* strcpy(char* dst, const char* src) { + char* d = dst; + while ((*d++ = *src++)); + return dst; +} + +size_t strlen(const char* str) { + const char* s = str; + while (*s++); + return s - str; +} + +size_t strspn(const char* str, const char* accept) { + const char* s = str; + while (*s && strchr(accept, *s)) s++; + return s - str; +} + +char* strstr(const char* str1, const char* str2) { + if (!*str2) return (char*)str1; + for (; *str1; str1++) { + const char* s1 = str1; + const char* s2 = str2; + while (*s1 && *s2 && (*s1 == *s2)) s1++, s2++; + if (!*s2) return (char*)str1; + } + return NULL; +} + +char* strtok(char* str, const char* delim) { + static char* next; + if (!str) str = next; + if (!str) return NULL; + str += strspn(str, delim); + if (!*str) return (next = NULL); + char* tok = str; + str = strbrk(str, delim); + if (str) *str++ = '\0'; + next = str; + return tok; +} +