Fix driver implementation

This commit is contained in:
EnderIce2
2024-07-07 03:15:17 +03:00
parent f85935f8f3
commit 4ecf37c44e
64 changed files with 2893 additions and 2863 deletions

View File

@ -1,83 +1,22 @@
# Config file
# Config files
include ../../../Makefile.conf
FILENAME = example.drv
CC = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
CPP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)g++
LD = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)ld
AS = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)as
OBJDUMP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)objdump
include ../../config.mk
S_SOURCES = $(shell find ./ -type f -name '*.S')
C_SOURCES = $(shell find ./ -type f -name '*.c')
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp')
HEADERS = $(sort $(dir $(wildcard ../../include/*)))
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(ASM_SOURCES:.asm=.o) $(S_SOURCES:.S=.o) $(PSF_SOURCES:.psf=.o) $(BMP_SOURCES:.bmp=.o)
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(S_SOURCES:.S=.o)
STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CPP_SOURCES:.cpp=.su)
INCLUDE_DIR = ../../include
LIBS := ../../out/dcrt0.o -L../../out -ldriver
LDFLAGS := \
-fPIC -fPIE -pie \
-Wl,--no-dynamic-linker,-ztext,--no-warn-rwx-segment \
-nostdlib -nodefaultlibs -nolibc \
-zmax-page-size=0x1000 \
-Wl,-Map file.map -shared -fvisibility=hidden
WARNCFLAG = -Wall -Wextra
CFLAGS := -I$(INCLUDE_DIR) -fvisibility=hidden
ifeq ($(OSARCH), amd64)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 \
-march=x86-64 -pipe -ffunction-sections \
-msoft-float -fno-builtin
else ifeq ($(OSARCH), i386)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 -ffunction-sections \
-march=i386 -pipe -msoft-float -fno-builtin
else ifeq ($(OSARCH), aarch64)
CFLAGS += -pipe -fno-builtin -fPIC
endif
ifeq ($(DEBUG), 1)
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fstack-usage
ifeq ($(OSARCH), amd64)
CFLAGS += -fverbose-asm
endif
ifneq ($(OSARCH), aarch64)
CFLAGS += -fstack-check
endif
LDFLAGS += -ggdb3 -O0
endif
FILENAME = example.drv
build: $(FILENAME)
mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ)
$(info Linking $@)
$(CC) $(LDFLAGS) $(OBJ) $(LIBS) -o $@
%.o: %.c $(HEADERS)
$(info Compiling $<)
$(CC) $(CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
%.o: %.cpp $(HEADERS)
$(info Compiling $<)
$(CPP) $(CFLAGS) $(WARNCFLAG) -std=c++20 -fno-exceptions -fno-rtti -c $< -o $@
%.o: %.S
$(info Compiling $<)
$(AS) -o $@ $<
$(CC) $(DRIVER_LDFLAGS) $(OBJ) ../../out/dcrt0.o -L../../out -lkernel -o $@
clean:
rm -f file.map $(OBJ) $(STACK_USAGE_OBJ)

View File

@ -20,16 +20,15 @@
int DriverEntry()
{
/** This is the main function of the driver.
* This function is called when the driver is loaded.
* This function should be used to initialize the PCI device
* and allocate resources.
*/
/* Print a message to the screen */
KPrint("Hello World from Example Driver!");
/* Print a message to the kernel terminal */
KernelPrint("Hello World from Example Driver!");
/* Print a message to the kernel log */
Log("Hello World from Example Driver!");
KernelLog("Hello World from Example Driver!");
/* Print a message only if DEBUG is set */
DebugLog("Hello World from Example Driver!");
@ -52,7 +51,7 @@ int DriverPanic()
{
/** This function is called when the kernel panics.
* This function should be used to stop the driver from
* receiving interrupts or anything else that is not
* sending interrupts or anything else that is not
* safe to do when the kernel panics.
*/
@ -63,13 +62,14 @@ int DriverProbe()
{
/** This is the first function that is called when the
* driver is loaded.
* We can use this function to test if the driver is
* compatible with the hardware.
* Like if we have a specific PCI device or if we have
* a specific CPU feature.
*
* This function is to test if the driver is compatible
* with the hardware.
* Example: Like if there is a PCI device that the driver
* is for, or a CPU feature that etc.
*
* Return 0 if the driver is compatible with the hardware.
* Otherwise, we return a value from the errno.h header.
* Otherwise, return a value that is not 0.
*
* Note: In this function you cannot use variables that
* have constructors or destructors. Before DriverEntry,
@ -80,8 +80,18 @@ int DriverProbe()
return 0;
}
/** DriverInfo() is a macro that is used to define the
* driver's information.
*
* The parameters are:
* - Name: Lowercase name
* - Description: A short description
* - Author: The author
* - Version: The version
* - License: The license
*/
DriverInfo("example",
"Example Driver",
"EnderIce2",
"0.1",
0, 0, 1,
"GPLv3");

View File

@ -1,83 +1,22 @@
# Config file
# Config files
include ../../../Makefile.conf
FILENAME = vmware.drv
CC = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
CPP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)g++
LD = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)ld
AS = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)as
OBJDUMP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)objdump
include ../../config.mk
S_SOURCES = $(shell find ./ -type f -name '*.S')
C_SOURCES = $(shell find ./ -type f -name '*.c')
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp')
HEADERS = $(sort $(dir $(wildcard ../../include/*)))
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(ASM_SOURCES:.asm=.o) $(S_SOURCES:.S=.o) $(PSF_SOURCES:.psf=.o) $(BMP_SOURCES:.bmp=.o)
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(S_SOURCES:.S=.o)
STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CPP_SOURCES:.cpp=.su)
INCLUDE_DIR = ../../include
LIBS := ../../out/dcrt0.o -L../../out -ldriver
LDFLAGS := \
-fPIC -fPIE -pie \
-Wl,--no-dynamic-linker,-ztext,--no-warn-rwx-segment \
-nostdlib -nodefaultlibs -nolibc \
-zmax-page-size=0x1000 \
-Wl,-Map file.map -shared -fvisibility=hidden
WARNCFLAG = -Wall -Wextra
CFLAGS := -I$(INCLUDE_DIR) -fvisibility=hidden
ifeq ($(OSARCH), amd64)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 \
-march=x86-64 -pipe -ffunction-sections \
-msoft-float -fno-builtin
else ifeq ($(OSARCH), i386)
CFLAGS += -fPIC -fPIE -pie -mno-80387 -mno-mmx -mno-3dnow \
-mno-red-zone -mno-sse -mno-sse2 -ffunction-sections \
-march=i386 -pipe -msoft-float -fno-builtin
else ifeq ($(OSARCH), aarch64)
CFLAGS += -pipe -fno-builtin -fPIC
endif
ifeq ($(DEBUG), 1)
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fstack-usage
ifeq ($(OSARCH), amd64)
CFLAGS += -fverbose-asm
endif
ifneq ($(OSARCH), aarch64)
CFLAGS += -fstack-check
endif
LDFLAGS += -ggdb3 -O0
endif
FILENAME = vmware.drv
build: $(FILENAME)
mv $(FILENAME) ../../out/$(FILENAME)
$(FILENAME): $(OBJ)
$(info Linking $@)
$(CC) $(LDFLAGS) $(OBJ) $(LIBS) -o $@
%.o: %.c $(HEADERS)
$(info Compiling $<)
$(CC) $(CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
%.o: %.cpp $(HEADERS)
$(info Compiling $<)
$(CPP) $(CFLAGS) $(WARNCFLAG) -std=c++20 -fno-exceptions -fno-rtti -c $< -o $@
%.o: %.S
$(info Compiling $<)
$(AS) -o $@ $<
$(CC) $(DRIVER_LDFLAGS) $(OBJ) ../../out/dcrt0.o -L../../out -lkernel -o $@
clean:
rm -f file.map $(OBJ) $(STACK_USAGE_OBJ)

View File

@ -17,11 +17,11 @@
#include <driver.h>
#include <errno.h>
#include <fs.h>
#include <input.h>
#include <regs.h>
#include <base.h>
#include <aip.h>
#include <vm.h>
#include <io.h>
enum RPCMessages
@ -170,7 +170,7 @@ typedef struct
"r"(bp) : "memory", "cc")
/* TODO:
- use vmcall or vmmcall instead of out or in if available
- use vmcall or vmmcall instead of "out" and "in" if available
*/
typedef struct
@ -183,6 +183,102 @@ typedef struct
dev_t MouseDevID = -1;
int __strcmp(const char *l, const char *r)
{
for (; *l == *r && *l; l++, r++)
;
return *(unsigned char *)l - *(unsigned char *)r;
}
void __cpuid(uint32_t Function,
uint32_t *eax, uint32_t *ebx,
uint32_t *ecx, uint32_t *edx)
{
asmv("cpuid"
: "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
: "a"(Function));
}
bool __CheckHypervisorBit()
{
uint32_t eax, ebx, ecx, edx;
__cpuid(0x1, &eax, &ebx, &ecx, &edx);
if (!(ecx & (1 << 31)))
return false; /* Hypervisor not detected */
return true;
}
bool __VMwareBackdoorHypervisors()
{
const char hv[13] = {0};
uint32_t eax, ebx, ecx, edx;
__cpuid(0x40000000, &eax, &ebx, &ecx, &edx);
*(uint32_t *)hv = ebx;
*(uint32_t *)(hv + 4) = ecx;
*(uint32_t *)(hv + 8) = edx;
if (__strcmp(hv, "VMwareVMware") != 0 &&
__strcmp(hv, "KVMKVMKVM") != 0 &&
__strcmp(hv, "TCGTCGTCGTCG") != 0)
{
return false;
}
return true;
}
bool IsVMwareBackdoorAvailable()
{
if (!__CheckHypervisorBit())
return false;
if (!__VMwareBackdoorHypervisors())
return false;
struct
{
union
{
uint32_t ax;
uint32_t magic;
};
union
{
uint32_t bx;
size_t size;
};
union
{
uint32_t cx;
uint16_t command;
};
union
{
uint32_t dx;
uint16_t port;
};
uint32_t si;
uint32_t di;
} cmd;
cmd.si = cmd.di = 0;
cmd.bx = ~0x564D5868;
cmd.command = 0xA;
cmd.magic = 0x564D5868;
cmd.port = 0x5658;
asmv("in %%dx, %0"
: "+a"(cmd.ax), "+b"(cmd.bx),
"+c"(cmd.cx), "+d"(cmd.dx),
"+S"(cmd.si), "+D"(cmd.di));
if (cmd.bx != 0x564D5868 ||
cmd.ax == 0xFFFFFFFF)
return false;
return true;
}
static int OpenMessageChannel(ToolboxContext *ctx, uint32_t Protocol)
{
uintptr_t ax, bx, cx, dx, si = 0, di = 0;
@ -194,7 +290,7 @@ static int OpenMessageChannel(ToolboxContext *ctx, uint32_t Protocol)
if ((HighWord(cx) & STATUS_SUCCESS) == 0)
{
Log("Failed to open message channel %#lx", Protocol);
KernelLog("Failed to open message channel %#lx", Protocol);
return -EINVAL;
}
@ -343,8 +439,8 @@ static int MessageSend(ToolboxContext *ctx,
if ((HighWord(cx) & STATUS_SUCCESS) == 0)
{
Log("Failed to send message size for \"%s\": %d",
Message, cx);
KernelLog("Failed to send message size for \"%s\": %d",
Message, cx);
return -EINVAL;
}
@ -363,14 +459,14 @@ static int MessageSend(ToolboxContext *ctx,
}
else if ((status & STATUS_CPT) == 0)
{
Log("Checkpoint occurred for message \"%s\"", Message);
KernelLog("Checkpoint occurred for message \"%s\"", Message);
continue;
}
else
break;
}
Log("Failed to send message \"%s\": %#lx", Message, bx);
KernelLog("Failed to send message \"%s\": %#lx", Message, bx);
return -EINVAL;
}
@ -401,12 +497,12 @@ static int MessageReceive(ToolboxContext *ctx,
if ((HighWord(cx) & STATUS_SUCCESS) == 0)
{
Log("Failed to receive message size: %d", cx);
KernelLog("Failed to receive message size: %d", cx);
return -EINVAL;
}
else if ((HighWord(cx) & STATUS_DORECV) == 0)
{
// Log("No message to receive");
DebugLog("No message to receive");
return -EAGAIN;
}
@ -427,11 +523,11 @@ static int MessageReceive(ToolboxContext *ctx,
{
if ((HighWord(bx) & STATUS_CPT) == 0)
{
Log("Checkpoint occurred for message payload");
KernelLog("Checkpoint occurred for message payload");
continue;
}
Log("Failed to receive message payload: %d", HighWord(bx));
KernelLog("Failed to receive message payload: %d", HighWord(bx));
FreeMemory(ReplyBuf, ReplyBufPages);
return -EINVAL;
}
@ -451,11 +547,11 @@ static int MessageReceive(ToolboxContext *ctx,
{
if ((HighWord(cx) & STATUS_CPT) == 0)
{
Log("Retrying message receive");
KernelLog("Retrying message receive");
continue;
}
Log("Failed to receive message status: %d", HighWord(cx));
KernelLog("Failed to receive message status: %d", HighWord(cx));
FreeMemory(ReplyBuf, ReplyBufPages);
return -EINVAL;
}
@ -465,7 +561,7 @@ static int MessageReceive(ToolboxContext *ctx,
if (ReplyBuf == NULL)
{
Log("Failed to receive message");
KernelLog("Failed to receive message");
return -EINVAL;
}
@ -481,14 +577,14 @@ static int SendRPCI(ToolboxContext *, const char *Request)
int status = OpenMessageChannel(&rpci_ctx, MESSAGE_RPCI);
if (status < 0)
{
Log("Failed to open RPCI channel: %d", status);
KernelLog("Failed to open RPCI channel: %d", status);
return status;
}
status = MessageSend(&rpci_ctx, Request);
if (status < 0)
{
Log("Failed to send RPCI request: %d", status);
KernelLog("Failed to send RPCI request: %d", status);
return status;
}
@ -524,7 +620,7 @@ static int DisplayGetSize(ToolboxContext *ctx)
}
else if (status < 0)
{
Log("Failed to receive message");
KernelLog("Failed to receive message");
return 1;
}
@ -579,7 +675,7 @@ void DisplayScaleThread()
while (true)
{
if (DisplayGetSize(tb_ctx) != 0)
Log("Failed to scale display");
KernelLog("Failed to scale display");
Sleep(1000);
}
}
@ -627,6 +723,7 @@ void Relative()
CommandSend(&cmd);
}
InputReport ir = {0};
void InterruptHandler(TrapFrame *)
{
uint8_t Data = inb(0x60);
@ -639,7 +736,7 @@ void InterruptHandler(TrapFrame *)
if (cmd.ax == 0xFFFF0000)
{
Log("VMware mouse is not connected?");
KernelLog("VMware mouse is not connected?");
Relative();
Absolute();
return;
@ -654,17 +751,6 @@ void InterruptHandler(TrapFrame *)
int Buttons = (cmd.ax & 0xFFFF);
MouseReport mr = {
.LeftButton = Buttons & 0x20,
.RightButton = Buttons & 0x10,
.MiddleButton = Buttons & 0x08,
.Button4 = 0x0,
.Button5 = 0x0,
.X = 0,
.Y = 0,
.Z = (int8_t)cmd.dx,
};
/**
* How should I handle this?
* (cmd.[bx,cx] * Width) / 0xFFFF
@ -672,9 +758,44 @@ void InterruptHandler(TrapFrame *)
*/
uintptr_t AbsoluteX = cmd.bx;
uintptr_t AbsoluteY = cmd.cx;
ReportAbsoluteMouseEvent(MouseDevID, mr, AbsoluteX, AbsoluteY);
ir.Type = INPUT_TYPE_MOUSE;
ir.Device = MouseDevID;
ir.Mouse.X = AbsoluteX;
ir.Mouse.Y = AbsoluteY;
ir.Mouse.Z = (int8_t)cmd.dx;
ir.Mouse.Absolute = 1;
ir.Mouse.LeftButton = Buttons & 0x20;
ir.Mouse.RightButton = Buttons & 0x10;
ir.Mouse.MiddleButton = Buttons & 0x08;
// ir.Mouse.Button4 = 0x0;
// ir.Mouse.Button5 = 0x0;
// ir.Mouse.Button6 = 0x0;
// ir.Mouse.Button7 = 0x0;
// ir.Mouse.Button8 = 0x0;
ReportInputEvent(&ir);
}
int __fs_Ioctl(struct Inode *, unsigned long Request, void *)
{
switch (Request)
{
case 0x1:
Relative();
break;
case 0x2:
Absolute();
break;
default:
return -EINVAL;
}
return 0;
}
const struct InodeOperations MouseOps = {
.Ioctl = __fs_Ioctl,
};
bool ToolboxSupported = false;
int DriverEntry()
{
@ -711,7 +832,8 @@ int DriverEntry()
* override its interrupt handler.
*/
OverrideInterruptHandler(12, InterruptHandler);
MouseDevID = RegisterInputDevice(ddt_Mouse);
MouseDevID = RegisterDevice(INPUT_TYPE_MOUSE, &MouseOps);
return 0;
}
@ -721,7 +843,8 @@ int DriverFinal()
PS2WriteData(PS2_MOUSE_CMD_DISABLE_DATA_REPORTING);
Relative();
UnregisterInputDevice(MouseDevID, ddt_Mouse);
UnregisterDevice(MouseDevID);
if (ToolboxSupported)
{
@ -751,5 +874,5 @@ int DriverProbe()
DriverInfo("vmware",
"VMware Tools Driver",
"EnderIce2",
"0.1",
0, 0, 1,
"GPLv3");