reboot is done
This commit is contained in:
parent
52951c96d5
commit
e7a8d39ad7
@ -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));
|
||||||
}
|
}
|
||||||
|
@ -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");
|
||||||
|
@ -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 */
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user