Compare commits
7 Commits
927aeb0872
...
f79f04361a
Author | SHA1 | Date | |
---|---|---|---|
f79f04361a | |||
6238fbf8fe | |||
d3c8dd45c7 | |||
4af4ad89a4 | |||
c5178d56bd | |||
f33b63d1fb | |||
d830acbbd4 |
|
@ -576,11 +576,7 @@ typedef struct __attribute__((aligned(64), packed)) {
|
||||||
} XSAVE_AREA;
|
} XSAVE_AREA;
|
||||||
|
|
||||||
|
|
||||||
static void* IRQ_Handlers[16] = {
|
static void* IRQ_Handlers[16];
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static const char* ExceptionStrings[] = {
|
static const char* ExceptionStrings[] = {
|
||||||
"Division by Zero",
|
"Division by Zero",
|
||||||
|
@ -642,6 +638,12 @@ size_t ReadCPUFrequency(size_t* PerformanceDest, uint8_t AvgOrDirect);
|
||||||
uint32_t ReadPort(uint16_t Port, int Length);
|
uint32_t ReadPort(uint16_t Port, int Length);
|
||||||
uint32_t WritePort(uint16_t Port, uint32_t Data, int Length);
|
uint32_t WritePort(uint16_t Port, uint32_t Data, int Length);
|
||||||
|
|
||||||
|
/* Serial functions */
|
||||||
|
void serial_write(const char chr);
|
||||||
|
void serial_print(const char* data);
|
||||||
|
void serial_printf(const char* format, ...);
|
||||||
|
void init_serial();
|
||||||
|
|
||||||
/* ==================== Registers ==================== */
|
/* ==================== Registers ==================== */
|
||||||
size_t ReadModelSpecificRegister(size_t MSR);
|
size_t ReadModelSpecificRegister(size_t MSR);
|
||||||
size_t WriteModelSpecificRegister(size_t MSR, size_t Data);
|
size_t WriteModelSpecificRegister(size_t MSR, size_t Data);
|
||||||
|
@ -686,7 +688,7 @@ void ScanCPUFeatures(size_t RAX, size_t RCX);
|
||||||
|
|
||||||
/* ==================== Interrupts ==================== */
|
/* ==================== Interrupts ==================== */
|
||||||
|
|
||||||
uint64_t time;
|
static uint64_t time;
|
||||||
|
|
||||||
void IRQ_Common(INTERRUPT_FRAME* Frame, size_t Interupt);
|
void IRQ_Common(INTERRUPT_FRAME* Frame, size_t Interupt);
|
||||||
void ISR_Common(INTERRUPT_FRAME* Frame, size_t Interrupt);
|
void ISR_Common(INTERRUPT_FRAME* Frame, size_t Interrupt);
|
||||||
|
|
|
@ -79,7 +79,8 @@ __attribute__((aligned(4096))) static size_t FirstPageTable[512] = {0};
|
||||||
void timer_wait(int ticks){
|
void timer_wait(int ticks){
|
||||||
uint64_t FinalTick = time + ticks;
|
uint64_t FinalTick = time + ticks;
|
||||||
|
|
||||||
while(time < FinalTick);
|
int i = 0;
|
||||||
|
while(i < ticks * 1000) { i++; };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -99,7 +100,15 @@ void PrepareSystem(FILELOADER_PARAMS* FLOP) {
|
||||||
InstallGDT();
|
InstallGDT();
|
||||||
InstallIDT();
|
InstallIDT();
|
||||||
|
|
||||||
beep();
|
// WARNING!
|
||||||
|
// W A R N I N G !
|
||||||
|
// This is L O U D!
|
||||||
|
// Turn your volume down!
|
||||||
|
// Seriously!
|
||||||
|
// LOWER!
|
||||||
|
// IT'S LOUD!
|
||||||
|
|
||||||
|
//beep();
|
||||||
|
|
||||||
if(SetIdentityMap(FLOP->RTServices) == NULL) {
|
if(SetIdentityMap(FLOP->RTServices) == NULL) {
|
||||||
Memory_Info.MemoryMap = FLOP->MemoryMap;
|
Memory_Info.MemoryMap = FLOP->MemoryMap;
|
||||||
|
@ -570,209 +579,6 @@ size_t ReadCPUFrequency(size_t* Perfs, uint8_t AverageOrDirect) {
|
||||||
return Frequency;
|
return Frequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ReadPort(uint16_t Port, int Length) {
|
|
||||||
uint32_t Data;
|
|
||||||
if(Length == 1) { // Read a byte
|
|
||||||
__asm__ __volatile__("inb %[address], %[value]" : : [value] "a" ((uint8_t) Data), [address] "d" (Port) :);
|
|
||||||
} else if (Length == 2) { // Read a word
|
|
||||||
__asm__ __volatile__("inw %[address], %[value]" : : [value] "a" ((uint16_t) Data), [address] "d" (Port) :);
|
|
||||||
} else if (Length == 4) { // Read a long (dword)
|
|
||||||
__asm__ __volatile__("inl %[address], %[value]" : : [value] "a" (Data), [address] "d" (Port) :);
|
|
||||||
} else {
|
|
||||||
printf("ReadPort: Invalid Read Length.\r\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
return Data;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t WritePort(uint16_t Port, uint32_t Data, int Length) {
|
|
||||||
if(Length == 1) { // Write a byte
|
|
||||||
__asm__ __volatile__("outb %[value], %[address]" : : [value] "a" ((uint8_t) Data), [address] "d" (Port) :);
|
|
||||||
} else if (Length == 2) { // Write a word
|
|
||||||
__asm__ __volatile__("outw %[value], %[address]" : : [value] "a" ((uint16_t) Data), [address] "d" (Port) :);
|
|
||||||
} else if (Length == 4) { // Write a long (dword)
|
|
||||||
__asm__ __volatile__("outl %[value], %[address]" : : [value] "a" (Data), [address] "d" (Port) :);
|
|
||||||
} else {
|
|
||||||
printf("WritePort: Invalid Write Length.\r\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
return Data;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ReadModelSpecificRegister(size_t MSR) {
|
|
||||||
size_t RegHigh = 0, RegLow = 0;
|
|
||||||
__asm__ __volatile__("rdmsr" : "=a" (RegLow), "=d" (RegHigh) : "c" (MSR) :);
|
|
||||||
return (RegHigh << 32 | RegLow);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t WriteModelSpecificRegister(size_t MSR, size_t Data) {
|
|
||||||
size_t DataLow = 0, DataHigh = 0;
|
|
||||||
|
|
||||||
DataLow = ((uint32_t* )&Data)[0];
|
|
||||||
DataHigh = ((uint32_t* )&Data)[1];
|
|
||||||
__asm__ __volatile__("wrmsr" : : "a" (DataLow), "c" (MSR), "d" (DataHigh) : );
|
|
||||||
return Data;
|
|
||||||
}
|
|
||||||
|
|
||||||
// VMXCSR - Vex-Encoded MXCSR. These are preferred when AVX is available.
|
|
||||||
uint32_t ReadVexMXCSR() {
|
|
||||||
uint32_t Data;
|
|
||||||
__asm__ __volatile__("vstmxcsr %[dest]" : [dest] "=m" (Data) : :);
|
|
||||||
return Data;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t WriteVexMXCSR(uint32_t Data) {
|
|
||||||
__asm__ __volatile__("vldmxcsr %[src]" : : [src] "m" (Data) :);
|
|
||||||
return Data;
|
|
||||||
}
|
|
||||||
|
|
||||||
// MXCSR - SSE Control Register.
|
|
||||||
uint32_t ReadMXCSR() {
|
|
||||||
uint32_t Data;
|
|
||||||
__asm__ __volatile__("stmxcsr %[dest]" : [dest] "=m" (Data) : :);
|
|
||||||
return Data;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t WriteMXCSR(uint32_t Data) {
|
|
||||||
__asm__ __volatile__("ldmxcsr %[src]" : : [src] "m" (Data) :);
|
|
||||||
return Data;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Control Register : CRX + RFLAGS. Specify 'f' for RFLAGS, X for CRX.
|
|
||||||
|
|
||||||
size_t ReadControlRegister(int CRX) {
|
|
||||||
size_t Data;
|
|
||||||
switch(CRX) {
|
|
||||||
case 0:
|
|
||||||
__asm__ __volatile__("mov %%cr0, %[dest]" : [dest] "=r" (Data) : :);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
__asm__ __volatile__("mov %%cr1, %[dest]" : [dest] "=r" (Data) : :);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
__asm__ __volatile__("mov %%cr2, %[dest]" : [dest] "=r" (Data) : :);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
__asm__ __volatile__("mov %%cr3, %[dest]" : [dest] "=r" (Data) : :);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
__asm__ __volatile__("mov %%cr4, %[dest]" : [dest] "=r" (Data) : :);
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
__asm__ __volatile__("mov %%cr8, %[dest]" : [dest] "=r" (Data) : :);
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
// Push flags and pop them into our buffer
|
|
||||||
__asm__ __volatile__("pushfq\n\t" "popq %[dest]" : [dest] "=r" (Data) : :);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Data;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t WriteControlRegister(int CRX, size_t Data) {
|
|
||||||
switch(CRX) {
|
|
||||||
case 0:
|
|
||||||
__asm__ __volatile__("mov %[dest], %%cr0" : : [dest] "r" (Data) :);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
__asm__ __volatile__("mov %[dest], %%cr1" : : [dest] "r" (Data) :);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
__asm__ __volatile__("mov %[dest], %%cr2" : : [dest] "r" (Data) :);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
__asm__ __volatile__("mov %[dest], %%cr3" : : [dest] "r" (Data) :);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
__asm__ __volatile__("mov %[dest], %%cr4" : : [dest] "r" (Data) :);
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
__asm__ __volatile__("mov %[dest], %%cr8" : : [dest] "r" (Data) :);
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
__asm__ __volatile__("pushq %[dest]\n\t" "popfq" : : [dest] "r" (Data) : "cc");
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Data;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// XCR = eXtended Control Register.
|
|
||||||
// XCR0 is used to enable AVX/SSE.
|
|
||||||
|
|
||||||
size_t ReadExtendedControlRegister(size_t XCRX) {
|
|
||||||
size_t RegHigh = 0, RegLow = 0;
|
|
||||||
|
|
||||||
__asm__ __volatile__("xgetbv" : "=a" (RegLow), "=d" (RegHigh) : "c" (XCRX) :);
|
|
||||||
return (RegHigh << 32 | RegLow);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t WriteExtendedControlRegister(size_t XCRX, size_t Data) {
|
|
||||||
__asm__ __volatile__("xsetbv" : : "a" ( ((uint32_t*)&Data)[0]), "c" (XCRX), "d" ( ((uint32_t*)&Data)[1] ) :);
|
|
||||||
return Data;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The following two functions are utility - for determining whether we're operating in Long Mode.
|
|
||||||
// TODO: Move into DescriptorTables.c
|
|
||||||
|
|
||||||
size_t ReadXCS() {
|
|
||||||
size_t Data = 0;
|
|
||||||
__asm__ __volatile__("mov %%cs, %[dest]" : [dest] "=r" (Data) : :);
|
|
||||||
return Data;
|
|
||||||
}
|
|
||||||
|
|
||||||
DESCRIPTOR_TABLE_POINTER FetchGDT() {
|
|
||||||
DESCRIPTOR_TABLE_POINTER GDTrData = {0};
|
|
||||||
|
|
||||||
__asm__ __volatile__("sgdt %[dest]" : [dest] "=m" (GDTrData) : :);
|
|
||||||
return GDTrData;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetGDT(DESCRIPTOR_TABLE_POINTER GDTrData) {
|
|
||||||
__asm__ __volatile__("lgdt %[src]" : : [src] "m" (GDTrData) :);
|
|
||||||
}
|
|
||||||
|
|
||||||
DESCRIPTOR_TABLE_POINTER FetchIDT() {
|
|
||||||
DESCRIPTOR_TABLE_POINTER IDTrData = {0};
|
|
||||||
__asm__ __volatile__("sidt %[dest]" : [dest] "=m" (IDTrData) : :);
|
|
||||||
return IDTrData;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetIDT(DESCRIPTOR_TABLE_POINTER IDTrData) {
|
|
||||||
__asm__ __volatile__("lidt %[src]" : : [src] "m" (IDTrData) :);
|
|
||||||
}
|
|
||||||
|
|
||||||
// LDT = Local Descriptor Table (= GDT entry for current segment)
|
|
||||||
|
|
||||||
uint16_t FetchLDT() {
|
|
||||||
uint16_t LDTrData = 0;
|
|
||||||
__asm__ __volatile__("sldt %[dest]" : [dest] "=m" (LDTrData) : :);
|
|
||||||
return LDTrData;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetLDT(uint16_t LDTrData) {
|
|
||||||
__asm__ __volatile__("lldt %[src]" : : [src] "m" (LDTrData) :);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TSR - Tast State Register
|
|
||||||
|
|
||||||
uint16_t FetchTSR() {
|
|
||||||
uint16_t TSRData = 0;
|
|
||||||
__asm__ __volatile__ ("str %[dest]" : [dest] "=m" (TSRData) : :);
|
|
||||||
return TSRData;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetTSR(uint16_t TSRData) {
|
|
||||||
__asm__ __volatile__("ltr %[src]" : : [src] "m" (TSRData) :);
|
|
||||||
}
|
|
||||||
|
|
||||||
void InstallGDT() {
|
void InstallGDT() {
|
||||||
DESCRIPTOR_TABLE_POINTER GDTData = {0};
|
DESCRIPTOR_TABLE_POINTER GDTData = {0};
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,8 @@ void SetupPrinting(EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE GPU) {
|
||||||
Print_Info.cursorPos = 0;
|
Print_Info.cursorPos = 0;
|
||||||
|
|
||||||
Print_Info.scrollMode = 0;
|
Print_Info.scrollMode = 0;
|
||||||
|
|
||||||
|
ClearScreen(GPU);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteScaledFormatString(EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE GPU,
|
void WriteScaledFormatString(EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE GPU,
|
||||||
|
|
|
@ -34,11 +34,13 @@
|
||||||
|
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
|
|
||||||
#ifdef __x86_64__
|
|
||||||
typedef unsigned long long int uword_t;
|
typedef unsigned long long int uword_t;
|
||||||
#else
|
|
||||||
typedef unsigned int uword_t;
|
|
||||||
#endif
|
static void* IRQ_Handlers[16] = {
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/* All of the ISR routines call this function for now.
|
/* All of the ISR routines call this function for now.
|
||||||
|
@ -48,11 +50,10 @@ typedef unsigned int uword_t;
|
||||||
void ISR_Common(INTERRUPT_FRAME* Frame, size_t Exception) {
|
void ISR_Common(INTERRUPT_FRAME* Frame, size_t Exception) {
|
||||||
/* Only the first 32 ISR/IRQs are reserved for exceptions by the CPU. We can handle up to 512 interrupts total, though. */
|
/* Only the first 32 ISR/IRQs are reserved for exceptions by the CPU. We can handle up to 512 interrupts total, though. */
|
||||||
if(Exception < 32) {
|
if(Exception < 32) {
|
||||||
/* exception_messages is an array of c-strings defined in kernel.h */
|
/* ExceptionStrings is an array of c-strings defined in kernel.h */
|
||||||
// TODO: Serial!
|
|
||||||
|
|
||||||
//serial_print(0x3F8, exception_messages[Exception]);
|
serial_print(ExceptionStrings[Exception]);
|
||||||
//serial_print(0x3F8, " Exception.\r\n");
|
serial_print(" Exception.\r\n");
|
||||||
printf("%s exception!", ExceptionStrings[Exception]);
|
printf("%s exception!", ExceptionStrings[Exception]);
|
||||||
panic();
|
panic();
|
||||||
}
|
}
|
||||||
|
@ -62,8 +63,8 @@ void ISR_Common(INTERRUPT_FRAME* Frame, size_t Exception) {
|
||||||
into what went wrong. In pure Curle style, though, we just ignore the error code. */
|
into what went wrong. In pure Curle style, though, we just ignore the error code. */
|
||||||
void ISR_Error_Common(EXCEPTION_FRAME* Frame, size_t Exception) {
|
void ISR_Error_Common(EXCEPTION_FRAME* Frame, size_t Exception) {
|
||||||
if(Exception < 32) {
|
if(Exception < 32) {
|
||||||
//serial_print(0x3F8, ExceptionStrings[Exception]);
|
serial_print(ExceptionStrings[Exception]);
|
||||||
//serial_printf(0x3F8, " Exception. Context given: %d\r\n", Frame->ErrorCode);
|
serial_printf(" Exception. Context given: %d\r\n", Frame->ErrorCode);
|
||||||
printf("%s exception. Context: %x", ExceptionStrings[Exception], Frame->ErrorCode);
|
printf("%s exception. Context: %x", ExceptionStrings[Exception], Frame->ErrorCode);
|
||||||
panic();
|
panic();
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,13 +20,17 @@
|
||||||
|
|
||||||
void gdb_end() {} /* GDB Debugging stump */
|
void gdb_end() {} /* GDB Debugging stump */
|
||||||
|
|
||||||
|
static size_t time = 0;
|
||||||
|
|
||||||
int kernel_main(FILELOADER_PARAMS* FLOP) {
|
int kernel_main(FILELOADER_PARAMS* FLOP) {
|
||||||
|
init_serial();
|
||||||
|
serial_printf("Kernel has been given control of the computer.\nStarting bootstrap init.\n");
|
||||||
/* The kernel is started in 64-bit Long Mode by Syncboot. */
|
/* The kernel is started in 64-bit Long Mode by Syncboot. */
|
||||||
/* Here, we start by drawing a splash, then loading a GDT and IDT into the placeholder UEFI gives us. */
|
|
||||||
|
/* PrepareSystem just initializes all hardware features and gets the system ready to execute every function.
|
||||||
|
/* Most of this is just preparing the interrupts system, but there is a bit of messing with AVX features, which are used extensively in drawing graphics. */
|
||||||
|
|
||||||
|
|
||||||
/* Not sure how well serial would work in UEFI. */
|
|
||||||
// TODO: look at this.
|
|
||||||
PrepareSystem(FLOP);
|
PrepareSystem(FLOP);
|
||||||
|
|
||||||
gdb_end(); /* The first important step. Waypoint it for gdb debugging. */
|
gdb_end(); /* The first important step. Waypoint it for gdb debugging. */
|
||||||
|
|
216
kernel/ports.c
Normal file
216
kernel/ports.c
Normal file
|
@ -0,0 +1,216 @@
|
||||||
|
|
||||||
|
/************************
|
||||||
|
*** Team Kitty, 2019 ***
|
||||||
|
*** Sync ***
|
||||||
|
***********************/
|
||||||
|
|
||||||
|
/* This file contains code required for directly communicating with hardware.
|
||||||
|
* This means ASM, most of the time. These are just wrapper functions that make ASM a little bit less daunting.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <kernel.h>
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t ReadPort(uint16_t Port, int Length) {
|
||||||
|
uint32_t Data;
|
||||||
|
if(Length == 1) { // Read a byte
|
||||||
|
__asm__ __volatile__("inb %[address], %[value]" : : [value] "a" ((uint8_t) Data), [address] "d" (Port) :);
|
||||||
|
} else if (Length == 2) { // Read a word
|
||||||
|
__asm__ __volatile__("inw %[address], %[value]" : : [value] "a" ((uint16_t) Data), [address] "d" (Port) :);
|
||||||
|
} else if (Length == 4) { // Read a long (dword)
|
||||||
|
__asm__ __volatile__("inl %[address], %[value]" : : [value] "a" (Data), [address] "d" (Port) :);
|
||||||
|
} else {
|
||||||
|
printf("ReadPort: Invalid Read Length.\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t WritePort(uint16_t Port, uint32_t Data, int Length) {
|
||||||
|
if(Length == 1) { // Write a byte
|
||||||
|
__asm__ __volatile__("outb %[value], %[address]" : : [value] "a" ((uint8_t) Data), [address] "d" (Port) :);
|
||||||
|
} else if (Length == 2) { // Write a word
|
||||||
|
__asm__ __volatile__("outw %[value], %[address]" : : [value] "a" ((uint16_t) Data), [address] "d" (Port) :);
|
||||||
|
} else if (Length == 4) { // Write a long (dword)
|
||||||
|
__asm__ __volatile__("outl %[value], %[address]" : : [value] "a" (Data), [address] "d" (Port) :);
|
||||||
|
} else {
|
||||||
|
printf("WritePort: Invalid Write Length.\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ReadModelSpecificRegister(size_t MSR) {
|
||||||
|
size_t RegHigh = 0, RegLow = 0;
|
||||||
|
__asm__ __volatile__("rdmsr" : "=a" (RegLow), "=d" (RegHigh) : "c" (MSR) :);
|
||||||
|
return (RegHigh << 32 | RegLow);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t WriteModelSpecificRegister(size_t MSR, size_t Data) {
|
||||||
|
size_t DataLow = 0, DataHigh = 0;
|
||||||
|
|
||||||
|
DataLow = ((uint32_t* )&Data)[0];
|
||||||
|
DataHigh = ((uint32_t* )&Data)[1];
|
||||||
|
__asm__ __volatile__("wrmsr" : : "a" (DataLow), "c" (MSR), "d" (DataHigh) : );
|
||||||
|
return Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// VMXCSR - Vex-Encoded MXCSR. These are preferred when AVX is available.
|
||||||
|
uint32_t ReadVexMXCSR() {
|
||||||
|
uint32_t Data;
|
||||||
|
__asm__ __volatile__("vstmxcsr %[dest]" : [dest] "=m" (Data) : :);
|
||||||
|
return Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t WriteVexMXCSR(uint32_t Data) {
|
||||||
|
__asm__ __volatile__("vldmxcsr %[src]" : : [src] "m" (Data) :);
|
||||||
|
return Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MXCSR - SSE Control Register.
|
||||||
|
uint32_t ReadMXCSR() {
|
||||||
|
uint32_t Data;
|
||||||
|
__asm__ __volatile__("stmxcsr %[dest]" : [dest] "=m" (Data) : :);
|
||||||
|
return Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t WriteMXCSR(uint32_t Data) {
|
||||||
|
__asm__ __volatile__("ldmxcsr %[src]" : : [src] "m" (Data) :);
|
||||||
|
return Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Control Register : CRX + RFLAGS. Specify 'f' for RFLAGS, X for CRX.
|
||||||
|
|
||||||
|
size_t ReadControlRegister(int CRX) {
|
||||||
|
size_t Data;
|
||||||
|
switch(CRX) {
|
||||||
|
case 0:
|
||||||
|
__asm__ __volatile__("mov %%cr0, %[dest]" : [dest] "=r" (Data) : :);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
__asm__ __volatile__("mov %%cr1, %[dest]" : [dest] "=r" (Data) : :);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
__asm__ __volatile__("mov %%cr2, %[dest]" : [dest] "=r" (Data) : :);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
__asm__ __volatile__("mov %%cr3, %[dest]" : [dest] "=r" (Data) : :);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
__asm__ __volatile__("mov %%cr4, %[dest]" : [dest] "=r" (Data) : :);
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
__asm__ __volatile__("mov %%cr8, %[dest]" : [dest] "=r" (Data) : :);
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
// Push flags and pop them into our buffer
|
||||||
|
__asm__ __volatile__("pushfq\n\t" "popq %[dest]" : [dest] "=r" (Data) : :);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t WriteControlRegister(int CRX, size_t Data) {
|
||||||
|
switch(CRX) {
|
||||||
|
case 0:
|
||||||
|
__asm__ __volatile__("mov %[dest], %%cr0" : : [dest] "r" (Data) :);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
__asm__ __volatile__("mov %[dest], %%cr1" : : [dest] "r" (Data) :);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
__asm__ __volatile__("mov %[dest], %%cr2" : : [dest] "r" (Data) :);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
__asm__ __volatile__("mov %[dest], %%cr3" : : [dest] "r" (Data) :);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
__asm__ __volatile__("mov %[dest], %%cr4" : : [dest] "r" (Data) :);
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
__asm__ __volatile__("mov %[dest], %%cr8" : : [dest] "r" (Data) :);
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
__asm__ __volatile__("pushq %[dest]\n\t" "popfq" : : [dest] "r" (Data) : "cc");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Data;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// XCR = eXtended Control Register.
|
||||||
|
// XCR0 is used to enable AVX/SSE.
|
||||||
|
|
||||||
|
size_t ReadExtendedControlRegister(size_t XCRX) {
|
||||||
|
size_t RegHigh = 0, RegLow = 0;
|
||||||
|
|
||||||
|
__asm__ __volatile__("xgetbv" : "=a" (RegLow), "=d" (RegHigh) : "c" (XCRX) :);
|
||||||
|
return (RegHigh << 32 | RegLow);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t WriteExtendedControlRegister(size_t XCRX, size_t Data) {
|
||||||
|
__asm__ __volatile__("xsetbv" : : "a" ( ((uint32_t*)&Data)[0]), "c" (XCRX), "d" ( ((uint32_t*)&Data)[1] ) :);
|
||||||
|
return Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The following two functions are utility - for determining whether we're operating in Long Mode.
|
||||||
|
// TODO: Move into DescriptorTables.c
|
||||||
|
|
||||||
|
size_t ReadXCS() {
|
||||||
|
size_t Data = 0;
|
||||||
|
__asm__ __volatile__("mov %%cs, %[dest]" : [dest] "=r" (Data) : :);
|
||||||
|
return Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
DESCRIPTOR_TABLE_POINTER FetchGDT() {
|
||||||
|
DESCRIPTOR_TABLE_POINTER GDTrData = {0};
|
||||||
|
|
||||||
|
__asm__ __volatile__("sgdt %[dest]" : [dest] "=m" (GDTrData) : :);
|
||||||
|
return GDTrData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetGDT(DESCRIPTOR_TABLE_POINTER GDTrData) {
|
||||||
|
__asm__ __volatile__("lgdt %[src]" : : [src] "m" (GDTrData) :);
|
||||||
|
}
|
||||||
|
|
||||||
|
DESCRIPTOR_TABLE_POINTER FetchIDT() {
|
||||||
|
DESCRIPTOR_TABLE_POINTER IDTrData = {0};
|
||||||
|
__asm__ __volatile__("sidt %[dest]" : [dest] "=m" (IDTrData) : :);
|
||||||
|
return IDTrData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetIDT(DESCRIPTOR_TABLE_POINTER IDTrData) {
|
||||||
|
__asm__ __volatile__("lidt %[src]" : : [src] "m" (IDTrData) :);
|
||||||
|
}
|
||||||
|
|
||||||
|
// LDT = Local Descriptor Table (= GDT entry for current segment)
|
||||||
|
|
||||||
|
uint16_t FetchLDT() {
|
||||||
|
uint16_t LDTrData = 0;
|
||||||
|
__asm__ __volatile__("sldt %[dest]" : [dest] "=m" (LDTrData) : :);
|
||||||
|
return LDTrData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetLDT(uint16_t LDTrData) {
|
||||||
|
__asm__ __volatile__("lldt %[src]" : : [src] "m" (LDTrData) :);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TSR - Tast State Register
|
||||||
|
|
||||||
|
uint16_t FetchTSR() {
|
||||||
|
uint16_t TSRData = 0;
|
||||||
|
__asm__ __volatile__ ("str %[dest]" : [dest] "=m" (TSRData) : :);
|
||||||
|
return TSRData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetTSR(uint16_t TSRData) {
|
||||||
|
__asm__ __volatile__("ltr %[src]" : : [src] "m" (TSRData) :);
|
||||||
|
}
|
|
@ -457,7 +457,7 @@ static void printchar(int Char, void* Args) {
|
||||||
case '\a': // Alert
|
case '\a': // Alert
|
||||||
// TODO: Audio alert.
|
// TODO: Audio alert.
|
||||||
break;
|
break;
|
||||||
case '\b': // Backspace
|
case '\b': // Back a space - NOT backspace, does not remove previous character.
|
||||||
if(Arg->cursorPos != 0) {
|
if(Arg->cursorPos != 0) {
|
||||||
Arg->cursorPos--;
|
Arg->cursorPos--;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,13 +35,13 @@
|
||||||
|
|
||||||
void serial_set_baud_rate(uint16_t com, uint16_t divisor) {
|
void serial_set_baud_rate(uint16_t com, uint16_t divisor) {
|
||||||
WritePort(SERIAL_LINE_COMMAND_PORT(com),
|
WritePort(SERIAL_LINE_COMMAND_PORT(com),
|
||||||
SERIAL_LINE_ENABLE_DLAB, 8);
|
SERIAL_LINE_ENABLE_DLAB, 1);
|
||||||
|
|
||||||
WritePort(SERIAL_DATA_PORT(com),
|
WritePort(SERIAL_DATA_PORT(com),
|
||||||
(divisor >> 8) & 0x00FF, 8);
|
(divisor >> 8) & 0x00FF, 1);
|
||||||
|
|
||||||
WritePort(SERIAL_DATA_PORT(com),
|
WritePort(SERIAL_DATA_PORT(com),
|
||||||
divisor & 0x00FF, 8);
|
divisor & 0x00FF, 1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ void serial_configure_line(uint16_t com) {
|
||||||
* Value: | 0 | 0 | 0 0 0 | 0 | 1 1 | = 0x03
|
* Value: | 0 | 0 | 0 0 0 | 0 | 1 1 | = 0x03
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WritePort(SERIAL_LINE_COMMAND_PORT(com), 0x0B, 8);
|
WritePort(SERIAL_LINE_COMMAND_PORT(com), 0x0B, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** serial_configure_buffers:
|
/** serial_configure_buffers:
|
||||||
|
@ -75,7 +75,7 @@ void serial_configure_buffers(uint16_t com) {
|
||||||
* Value: | 1 1 | 0 | 0 | 0 | 1 | 1 | 1 | = 0xC7
|
* Value: | 1 1 | 0 | 0 | 0 | 1 | 1 | 1 | = 0xC7
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WritePort(SERIAL_FIFO_COMMAND_PORT(com), 0xC7, 8);
|
WritePort(SERIAL_FIFO_COMMAND_PORT(com), 0xC7, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** serial_configure_modem
|
/** serial_configure_modem
|
||||||
|
@ -88,7 +88,7 @@ void serial_configure_modem(uint16_t com) {
|
||||||
* Value: | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | = 0x03
|
* Value: | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | = 0x03
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WritePort(SERIAL_MODEM_COMMAND_PORT(com), 0x3, 8);
|
WritePort(SERIAL_MODEM_COMMAND_PORT(com), 0x3, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** serial_check_tqueue:
|
/** serial_check_tqueue:
|
||||||
|
@ -100,7 +100,7 @@ void serial_configure_modem(uint16_t com) {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int serial_check_tqueue(uint16_t com) {
|
int serial_check_tqueue(uint16_t com) {
|
||||||
return ReadPort(SERIAL_LINE_STATUS_PORT(com), 8) & 0x20;
|
return ReadPort(SERIAL_LINE_STATUS_PORT(com), 1) & 0x20;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** serial_write:
|
/** serial_write:
|
||||||
|
@ -110,10 +110,11 @@ int serial_check_tqueue(uint16_t com) {
|
||||||
* @param data The character to write.
|
* @param data The character to write.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void serial_write(uint16_t com, const char chr) {
|
void serial_write(const char chr) {
|
||||||
|
uint16_t com = SERIAL_COM1_BASE;
|
||||||
//Hang until we have access to the COM port.
|
//Hang until we have access to the COM port.
|
||||||
while(serial_check_tqueue(com) == 0);
|
while(serial_check_tqueue(com) == 0);
|
||||||
WritePort(com, chr, 0);
|
WritePort(com, chr, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** serial_print:
|
/** serial_print:
|
||||||
|
@ -124,9 +125,9 @@ void serial_write(uint16_t com, const char chr) {
|
||||||
* @param data The string to write.
|
* @param data The string to write.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void serial_print(uint16_t com, const char* data) {
|
void serial_print(const char* data) {
|
||||||
for(size_t i = 0; i < strlen(data); i++) {
|
for(size_t i = 0; i < strlen(data); i++) {
|
||||||
serial_write(com, data[i]);
|
serial_write(data[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,7 +138,8 @@ void serial_print(uint16_t com, const char* data) {
|
||||||
* @param ... The substitutions.
|
* @param ... The substitutions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void serial_printf(uint16_t com, const char* format, ...) {
|
void serial_printf(const char* format, ...) {
|
||||||
|
uint16_t com = SERIAL_COM1_BASE;
|
||||||
uint32_t storage; //To hold temporary variables
|
uint32_t storage; //To hold temporary variables
|
||||||
char stringstore[10] = {0}; //To convert ints to strings.
|
char stringstore[10] = {0}; //To convert ints to strings.
|
||||||
va_list list;
|
va_list list;
|
||||||
|
@ -151,7 +153,7 @@ void serial_printf(uint16_t com, const char* format, ...) {
|
||||||
|
|
||||||
storage = va_arg(list, int);
|
storage = va_arg(list, int);
|
||||||
int_to_ascii(storage, stringstore);
|
int_to_ascii(storage, stringstore);
|
||||||
serial_print(com, stringstore);
|
serial_print(stringstore);
|
||||||
empty_string(stringstore);
|
empty_string(stringstore);
|
||||||
i += 2;
|
i += 2;
|
||||||
|
|
||||||
|
@ -159,21 +161,21 @@ void serial_printf(uint16_t com, const char* format, ...) {
|
||||||
|
|
||||||
storage = va_arg(list, int);
|
storage = va_arg(list, int);
|
||||||
int_to_hex(storage, stringstore);
|
int_to_hex(storage, stringstore);
|
||||||
serial_print(com, stringstore);
|
serial_print(stringstore);
|
||||||
empty_string(stringstore);
|
empty_string(stringstore);
|
||||||
i += 2;
|
i += 2;
|
||||||
|
|
||||||
} else if(format[i+1] == 's') {
|
} else if(format[i+1] == 's') {
|
||||||
|
|
||||||
serial_print(com, va_arg(list, char*));
|
serial_print(va_arg(list, char*));
|
||||||
i += 2;
|
i += 2;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
serial_print(com, "ERROR: Attempting to parse unknown format string.");
|
serial_print("ERROR: Attempting to parse unknown format string.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
serial_write(com, format[i]);
|
serial_write(format[i]);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -182,7 +184,7 @@ void serial_printf(uint16_t com, const char* format, ...) {
|
||||||
|
|
||||||
void init_serial() {
|
void init_serial() {
|
||||||
// Disable interrupts
|
// Disable interrupts
|
||||||
WritePort(SERIAL_COM1_BASE + 1, 0x00, 0);
|
WritePort(SERIAL_COM1_BASE + 1, 0x00, 1);
|
||||||
|
|
||||||
// Set baud rate divisor.
|
// Set baud rate divisor.
|
||||||
serial_set_baud_rate(SERIAL_COM1_BASE, 3);
|
serial_set_baud_rate(SERIAL_COM1_BASE, 3);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user