reboot is done

This commit is contained in:
0x35c 2024-09-11 16:46:39 +02:00
parent 52951c96d5
commit e7a8d39ad7
3 changed files with 91 additions and 15 deletions

View File

@ -2,17 +2,18 @@
#include "gdt.h" #include "gdt.h"
#include "kprintf.h" #include "kprintf.h"
#include "string.h"
extern void set_gdt(uint32_t gdt_ptr); extern void set_gdt(uint32_t gdt_ptr);
uint8_t gdt_entries[GDT_SIZE * 8]; uint8_t gdt_entries[GDT_SIZE * 8];
struct gdt_descriptor *gdtr = (struct gdt_descriptor *)GDT_ADDRESS; struct gdt_descriptor *gdtr = (struct gdt_descriptor *)GDT_ADDRESS;
static void set_gdt_entry_value(uint8_t *target, uint32_t base, uint32_t limit, uint8_t access, uint8_t granularity) static void set_gdt_entry_value(uint8_t *target, uint32_t base, uint32_t limit,
uint8_t access, uint8_t granularity)
{ {
if (limit > 0xFFFFF) { if (limit > 0xFFFFF) {
kprintf(KERN_ERR, "GDT cannot encode limits larger than 0xFFFFF"); kprintf(KERN_ERR,
"GDT cannot encode limits larger than 0xFFFFF");
} }
// Encode the limit // Encode the limit
@ -33,20 +34,62 @@ static void set_gdt_entry_value(uint8_t *target, uint32_t base, uint32_t limit,
target[6] |= (granularity << 4); target[6] |= (granularity << 4);
} }
void initGdt() void initGdt(void)
{ {
gdtr->size = 8 * GDT_SIZE - 1; gdtr->size = 8 * GDT_SIZE - 1;
gdtr->base = (uint32_t)&gdt_entries; gdtr->base = (uint32_t)&gdt_entries;
set_gdt_entry_value(gdt_entries + 0x00, 0, 0, 0, 0); // Null segment set_gdt_entry_value(gdt_entries + 0x00, 0, 0, 0, 0); // Null segment
set_gdt_entry_value(gdt_entries + 0x08, 0, 0xFFFFF, GDT_ACCESS_P_VALID | GDT_ACCESS_DPL_KERNEL_MODE | GDT_ACCESS_S_CODE_OR_DATA | GDT_ACCESS_E_EXECUTABLE | GDT_ACCESS_DC_NOT_CONFORM | GDT_ACCESS_RW_READABLE_FOR_CODE_WRITABLE_FOR_DATA | GDT_ACCESS_A_ACCESSED, GDT_FLAG_32BIT_MODE | GDT_FLAG_PAGE_MODE); // Kernel code set_gdt_entry_value(
set_gdt_entry_value(gdt_entries + 0x10, 0, 0xFFFFF, GDT_ACCESS_P_VALID | GDT_ACCESS_DPL_KERNEL_MODE | GDT_ACCESS_S_CODE_OR_DATA | GDT_ACCESS_E_NOT_EXECUTABLE | GDT_ACCESS_DC_NOT_CONFORM | GDT_ACCESS_RW_READABLE_FOR_CODE_WRITABLE_FOR_DATA | GDT_ACCESS_A_ACCESSED, GDT_FLAG_32BIT_MODE | GDT_FLAG_PAGE_MODE); // Kernel data gdt_entries + 0x08, 0, 0xFFFFF,
set_gdt_entry_value(gdt_entries + 0x18, 0, 0x0, GDT_ACCESS_P_VALID | GDT_ACCESS_DPL_KERNEL_MODE | GDT_ACCESS_S_CODE_OR_DATA | GDT_ACCESS_E_NOT_EXECUTABLE | GDT_ACCESS_DC_CONFORM |GDT_ACCESS_RW_READABLE_FOR_CODE_WRITABLE_FOR_DATA | GDT_ACCESS_A_ACCESSED, GDT_FLAG_32BIT_MODE | GDT_FLAG_PAGE_MODE); // Kernel stack GDT_ACCESS_P_VALID | GDT_ACCESS_DPL_KERNEL_MODE |
GDT_ACCESS_S_CODE_OR_DATA | GDT_ACCESS_E_EXECUTABLE |
GDT_ACCESS_DC_NOT_CONFORM |
GDT_ACCESS_RW_READABLE_FOR_CODE_WRITABLE_FOR_DATA |
GDT_ACCESS_A_ACCESSED,
GDT_FLAG_32BIT_MODE | GDT_FLAG_PAGE_MODE); // Kernel code
set_gdt_entry_value(
gdt_entries + 0x10, 0, 0xFFFFF,
GDT_ACCESS_P_VALID | GDT_ACCESS_DPL_KERNEL_MODE |
GDT_ACCESS_S_CODE_OR_DATA | GDT_ACCESS_E_NOT_EXECUTABLE |
GDT_ACCESS_DC_NOT_CONFORM |
GDT_ACCESS_RW_READABLE_FOR_CODE_WRITABLE_FOR_DATA |
GDT_ACCESS_A_ACCESSED,
GDT_FLAG_32BIT_MODE | GDT_FLAG_PAGE_MODE); // Kernel data
set_gdt_entry_value(
gdt_entries + 0x18, 0, 0x0,
GDT_ACCESS_P_VALID | GDT_ACCESS_DPL_KERNEL_MODE |
GDT_ACCESS_S_CODE_OR_DATA | GDT_ACCESS_E_NOT_EXECUTABLE |
GDT_ACCESS_DC_CONFORM |
GDT_ACCESS_RW_READABLE_FOR_CODE_WRITABLE_FOR_DATA |
GDT_ACCESS_A_ACCESSED,
GDT_FLAG_32BIT_MODE | GDT_FLAG_PAGE_MODE); // Kernel stack
set_gdt_entry_value(gdt_entries + 0x20, 0, 0xFFFFF, GDT_ACCESS_P_VALID | GDT_ACCESS_DPL_USER_MODE | GDT_ACCESS_S_CODE_OR_DATA | GDT_ACCESS_E_EXECUTABLE | GDT_ACCESS_DC_CONFORM | GDT_ACCESS_RW_READABLE_FOR_CODE_WRITABLE_FOR_DATA | GDT_ACCESS_A_ACCESSED, GDT_FLAG_32BIT_MODE | GDT_FLAG_PAGE_MODE); // User code set_gdt_entry_value(
set_gdt_entry_value(gdt_entries + 0x28, 0, 0xFFFFF, GDT_ACCESS_P_VALID | GDT_ACCESS_DPL_USER_MODE | GDT_ACCESS_S_CODE_OR_DATA | GDT_ACCESS_E_NOT_EXECUTABLE | GDT_ACCESS_DC_NOT_CONFORM | GDT_ACCESS_RW_READABLE_FOR_CODE_WRITABLE_FOR_DATA | GDT_ACCESS_A_ACCESSED, GDT_FLAG_32BIT_MODE | GDT_FLAG_PAGE_MODE); // User data gdt_entries + 0x20, 0, 0xFFFFF,
set_gdt_entry_value(gdt_entries + 0x30, 0, 0xFFFFF, GDT_ACCESS_P_VALID | GDT_ACCESS_DPL_USER_MODE | GDT_ACCESS_S_CODE_OR_DATA | GDT_ACCESS_E_NOT_EXECUTABLE | GDT_ACCESS_DC_CONFORM | GDT_ACCESS_RW_READABLE_FOR_CODE_WRITABLE_FOR_DATA | GDT_ACCESS_A_ACCESSED, GDT_FLAG_32BIT_MODE | GDT_FLAG_PAGE_MODE); // User stack GDT_ACCESS_P_VALID | GDT_ACCESS_DPL_USER_MODE |
GDT_ACCESS_S_CODE_OR_DATA | GDT_ACCESS_E_EXECUTABLE |
GDT_ACCESS_DC_CONFORM |
GDT_ACCESS_RW_READABLE_FOR_CODE_WRITABLE_FOR_DATA |
GDT_ACCESS_A_ACCESSED,
GDT_FLAG_32BIT_MODE | GDT_FLAG_PAGE_MODE); // User code
set_gdt_entry_value(
gdt_entries + 0x28, 0, 0xFFFFF,
GDT_ACCESS_P_VALID | GDT_ACCESS_DPL_USER_MODE |
GDT_ACCESS_S_CODE_OR_DATA | GDT_ACCESS_E_NOT_EXECUTABLE |
GDT_ACCESS_DC_NOT_CONFORM |
GDT_ACCESS_RW_READABLE_FOR_CODE_WRITABLE_FOR_DATA |
GDT_ACCESS_A_ACCESSED,
GDT_FLAG_32BIT_MODE | GDT_FLAG_PAGE_MODE); // User data
set_gdt_entry_value(
gdt_entries + 0x30, 0, 0xFFFFF,
GDT_ACCESS_P_VALID | GDT_ACCESS_DPL_USER_MODE |
GDT_ACCESS_S_CODE_OR_DATA | GDT_ACCESS_E_NOT_EXECUTABLE |
GDT_ACCESS_DC_CONFORM |
GDT_ACCESS_RW_READABLE_FOR_CODE_WRITABLE_FOR_DATA |
GDT_ACCESS_A_ACCESSED,
GDT_FLAG_32BIT_MODE | GDT_FLAG_PAGE_MODE); // User stack
set_gdt(((uint32_t)gdtr)); set_gdt(((uint32_t)gdtr));
} }

View File

@ -85,7 +85,8 @@ void shell_init(void)
"poweroff, echo, color, merdella\n"); "poweroff, echo, color, merdella\n");
break; break;
case REBOOT: case REBOOT:
kprintf(0, "rebooting\n"); kprintf(0, "rebooting...\n");
reboot();
break; break;
case POWEROFF: case POWEROFF:
kprintf(0, "powering off\n"); kprintf(0, "powering off\n");

View File

@ -0,0 +1,32 @@
#include "sys/io.h"
#include <stdint.h>
#define KBD_INTERFACE 0x64
/* keyboard interface bits */
#define KBD_BIT_KDATA 0 /* keyboard data */
#define KBD_BIT_UDATA 1 /* user data */
#define KBD_IO 0x60 /* keyboard IO port */
#define KBD_RESET 0xFE /* reset CPU command */
#define bit(n) (1 << (n)) /* Set bit n to 1 */
/* Check if bit n in flags is set */
#define check_flag(flags, n) ((flags) & bit(n))
void reboot(void)
{
uint8_t tmp;
asm volatile("cli"); /* disable all interrupts */
do {
tmp = inb(KBD_INTERFACE); /* empty user data */
if (check_flag(tmp, KBD_BIT_KDATA))
inb(KBD_IO); /* empty keyboard data */
} while (check_flag(tmp, KBD_BIT_UDATA));
outb(KBD_INTERFACE, KBD_RESET); /* pulse CPU reset line */
loop:
asm volatile("hlt"); /* if that didn't work, halt the CPU */
goto loop; /* if a NMI is received, halt again */
}