Skip to content

Commit

Permalink
更新鼠标
Browse files Browse the repository at this point in the history
  • Loading branch information
copi143 committed Feb 1, 2025
1 parent 361b7dd commit 8b83334
Show file tree
Hide file tree
Showing 10 changed files with 164 additions and 61 deletions.
1 change: 1 addition & 0 deletions include/kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ extern "C" {
#include "kernel/vbe.h"
#include "kernel/vdisk.h"
#include "kernel/virtio.h"
#include "kernel/vmtools.h"
#include "kernel/vsound.h"
#ifdef __cplusplus
}
Expand Down
2 changes: 1 addition & 1 deletion include/kernel/pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ struct pci_config_space_public {
u8 MaxLatency;
};

void init_pci(void *adder_Base);
void pci_init();
void pci_classcode_print(const struct pci_config_space_public *pci_config_space_puclic);
int pci_get_device(int vendor_id, int device_id, int subsystem_id, u8 *bus, u8 *slot, u8 *func);
u32 read_bar_n(u8 bus, u8 device, u8 function, u8 bar_n);
Expand Down
14 changes: 14 additions & 0 deletions include/kernel/ps2.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,17 @@ int getch();
extern struct MOUSE_DEC mdec;

void mouse_ready(struct MOUSE_DEC *mdec);

typedef struct PointerEvent {
usize device_id; // 设备 ID 不可用默认为 0
usize pointer_id; // 指针 ID 不可用默认为 0
u32 buttons; // 指针的按钮按下状态,每一位代表一个按钮
u32 x; // 指针指向的 x 位置
u32 y; // 指针指向的 y 位置
float xratio; // 指针指向的 x 位置的比例
float yratio; // 指针指向的 y 位置的比例
u32 width; // 指针接触范围的宽度
u32 height; // 指针接触范围的高度
f32 pressure; // 压力 (0 - 1) 不可用默认为 0.5
f32 twist; // 指针设备的朝向 (0 - 2 * PI) 不可用默认为 0
} PointerEvent;
36 changes: 36 additions & 0 deletions include/kernel/vmtools.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#pragma once
#include <define.h>

#define vmware_send(cmd, arg) \
({ \
const u32 _cmd_ = (cmd); \
const u32 _arg_ = (arg); \
struct { \
u32 eax, ebx, ecx, edx, esi, edi; \
} _564D5868_ = {0x564D5868, _arg_, _cmd_, 0x5658, 0, 0}; \
asm volatile("in %%dx, %%eax\n\t" \
: "+a"(_564D5868_.eax), "+b"(_564D5868_.ebx), "+c"(_564D5868_.ecx), \
"+d"(_564D5868_.edx), "+S"(_564D5868_.esi), "+D"(_564D5868_.edi)); \
_564D5868_; \
})

#define vm_is_vmware (vmware_send(0x0A, 0).ebx == 0x564D5868)

enum hypervisor_id {
HYPERVISOR_UNKNOWN,
HYPERVISOR_KVM,
HYPERVISOR_KVM_HV,
HYPERVISOR_QEMU,
HYPERVISOR_VMWARE,
HYPERVISOR_VBOX,
HYPERVISOR_HYPERV,
};

extern enum hypervisor_id hypervisor_id;

// 注意非 vmwware 的虚拟机也有可能提供 vmware backdoor
extern bool vmware_backdoor_available;

void detect_hypervisor();

void vmtools_init();
8 changes: 5 additions & 3 deletions src/kernel/drivers/general/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,12 @@ void pci_config(u32 bus, u32 f, u32 equipment, u32 adder) {

// TODO 重构循环体到新函数

void init_pci(void *addr_base) {
pci_addr_base = addr_base;
void pci_init() {
pci_addr_base = page_alloc(1 * 1024 * 1024);
kassert(pci_addr_base != null, "Out of memory");

u32 i, bus, equipment, func, addr, *i1;
u8 *pci_dat = (void *)addr_base, *pci_dat1;
u8 *pci_dat = (void *)pci_addr_base, *pci_dat1;
for (bus = 0; bus < 256; bus++) { //查询总线
for (equipment = 0; equipment < 32; equipment++) { //查询设备
for (func = 0; func < 8; func++) { //查询功能
Expand Down
87 changes: 87 additions & 0 deletions src/kernel/drivers/general/vmtools.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#include <kernel.h>

bool vmware_backdoor_available = false;

enum hypervisor_id hypervisor_id = HYPERVISOR_UNKNOWN;

static void detect_hypervisor_id() {
static const struct {
const void *key;
enum hypervisor_id value;
} hypervisor_ids[] = {
{"KVMKVMKVM\0\0\0", HYPERVISOR_KVM },
{"Linux KVM Hv", HYPERVISOR_KVM_HV},
{"TCGTCGTCGTCG", HYPERVISOR_QEMU },
{"VMwareVMware", HYPERVISOR_VMWARE},
{"VBoxVBoxVBox", HYPERVISOR_VBOX },
{"Microsoft Hv", HYPERVISOR_HYPERV},
};
for (usize i = 0; i < lengthof(hypervisor_ids); i++) {
if (memeq(cpuids.hypervisor_id, hypervisor_ids[i].key, 12)) {
hypervisor_id = hypervisor_ids[i].value;
return;
}
}
}

void detect_hypervisor() {
detect_hypervisor_id();
vmware_backdoor_available = vm_is_vmware;
}

static inthandler_f inthandler2c;

static void *ps2_mouse_handler = null;

static void vmware_mouse_init() {
// 取消鼠标捕获
vmware_send(41, 0x45414552);
vmware_send(40, 0);
vmware_send(39, 1);
vmware_send(41, 0x53424152);
ps2_mouse_handler = inthandler_set(0x2c, inthandler2c);
}

static void vmware_mouse_deinit() {
vmware_send(41, 0xF5);
inthandler_set(0x2c, ps2_mouse_handler);
}

void vmtools_init() {
if (vmware_backdoor_available) {
vmware_mouse_init(); //
}
}

static PointerEvent event;

static FASTCALL void inthandler2c(i32 id, regs32 *regs) {
asm_in8(PORT_KEYDAT);

val status = vmware_send(40, 0);

if (status.eax == 0xFFFF0000) {
klogw("VMware mouse data error");
vmware_mouse_deinit();
vmware_mouse_init();
return;
}

if ((status.eax & 0xFFFF) < 4) return;

val data = vmware_send(39, 4);

val flags = (data.eax & 0xFFFF0000) >> 16; /* Not important */
val buttons = data.eax & 0xFFFF; /* 0x10 = Right, 0x20 = Left, 0x08 = Middle */
val x = data.ebx; /* Both X and Y are scaled from 0 to 0xFFFF */
val y = data.ecx; /* You should map these somewhere to the actual resolution. */
val z = (i8)data.edx; /* Z is a single signed byte indicating scroll direction. */
klogd("mouse x: %d, y: %d, z: %d", x, y, z);

event.buttons = 0;
if (buttons & 0x20) event.buttons |= MASK(0);
if (buttons & 0x08) event.buttons |= MASK(1);
if (buttons & 0x10) event.buttons |= MASK(2);
event.xratio = (f32)x / 0xFFFF;
event.yratio = (f32)y / 0xFFFF;
}
2 changes: 1 addition & 1 deletion src/kernel/drivers/input/keyboard.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ static inthandler_f inthandler21;
// 初始化键盘控制电路
void keyboard_init() {
inthandler_set(0x21, inthandler21);
irq_enable(1);
ps2_wait();
asm_out8(PORT_KEYCMD, KEYCMD_WRITE_MODE);
ps2_wait();
asm_out8(PORT_KEYDAT, KBC_MODE);
irq_enable(1);
}

int getch() {
Expand Down
7 changes: 5 additions & 2 deletions src/kernel/drivers/input/mouse.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ static void mouse_reset() {

void mouse_init() {
inthandler_set(0x2c, inthandler2c);
irq_enable(12);
ps2_wait();
asm_out8(PORT_KEYCMD, KEYCMD_SENDTO_MOUSE);
ps2_wait();
Expand All @@ -52,7 +53,7 @@ void mouse_init() {
mouse_write(0xf3);
mouse_write(80);
mouse_write(0xf2);
klogd("mouseId=%d\n", mouse_read());
klogd("mouseId=%d", mouse_read());
/* 顺利的话,键盘控制器会返回ACK(0xfa) */
}

Expand All @@ -66,6 +67,8 @@ void mouse_ready(struct MOUSE_DEC *mdec) {
mdec->sleep = 0;
}

void update_mouse() {}

int mouse_decode(struct MOUSE_DEC *mdec, u8 dat) {
if (mdec->phase == 1) {
if (dat == 0xfa) { // ACK
Expand Down Expand Up @@ -109,5 +112,5 @@ int mouse_decode(struct MOUSE_DEC *mdec, u8 dat) {
static FASTCALL void inthandler2c(i32 id, regs32 *regs) {
byte data = asm_in8(PORT_KEYDAT);

klogd("mouse data=%02x\n", data);
klogd("mouse data=%02x", data);
}
66 changes: 13 additions & 53 deletions src/kernel/init/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,8 @@ void abort() {
}
}

#define vmware_send(cmd, arg) \
({ \
__SIZE_TYPE__ eax = 0x564D5868; \
__SIZE_TYPE__ ebx = (arg); \
__SIZE_TYPE__ ecx = (cmd); \
__SIZE_TYPE__ edx = 0x5658; \
asm volatile("in %%dx, %%eax\n\t" : "+a"(eax), "+b"(ebx), "+c"(ecx), "+d"(edx)); \
ebx; \
})

#define vm_is_vmware() \
({ \
__SIZE_TYPE__ eax = 0x564D5868; \
__SIZE_TYPE__ ebx = 0; \
__SIZE_TYPE__ ecx = 0x0A; \
__SIZE_TYPE__ edx = 0x5658; \
asm volatile("in %%dx, %%eax\n\t" : "+a"(eax), "+b"(ebx), "+c"(ecx), "+d"(edx)); \
ebx == 0x564D5868; \
})

void serial_init();

bool vmware_backdoor_available = false;

void sysinit() {
klogi("kernel is starting");

Expand Down Expand Up @@ -67,39 +45,19 @@ void sysinit() {

//+ ========== vm ==========

if (memeq(cpuids.hypervisor_id, "KVMKVMKVM", 9)) {
klogi("You are running on KVM."); //
}

if (memeq(cpuids.hypervisor_id, "Linux KVM Hv", 12)) {
klogi("You are running on KVM (Hyper-V emulation)."); //
}

if (memeq(cpuids.hypervisor_id, "TCGTCGTCGTCG", 12)) {
klogi("You are running on QEMU."); //
}

if (memeq(cpuids.hypervisor_id, "VMwareVMware", 12)) {
klogi("You are running on VMware."); //
}
detect_hypervisor();

if (memeq(cpuids.hypervisor_id, "VBoxVBoxVBox", 12)) {
klogi("You are running on VBox."); //
switch (hypervisor_id) {
case HYPERVISOR_KVM: klogi("You are running on KVM."); break;
case HYPERVISOR_KVM_HV: klogi("You are running on KVM (Hyper-V emulation)."); break;
case HYPERVISOR_QEMU: klogi("You are running on QEMU."); break;
case HYPERVISOR_VMWARE: klogi("You are running on VMware."); break;
case HYPERVISOR_VBOX: klogi("You are running on VBox."); break;
case HYPERVISOR_HYPERV: klogi("You are running on Hyper-V."); break;
default: break;
}

if (memeq(cpuids.hypervisor_id, "Microsoft Hv", 9)) {
klogi("You are running on Hyper-V."); //
}

if (vm_is_vmware()) {
klogi("VMware Backdoor available."); //
}

// 取消鼠标捕获
vmware_send(41, 0x45414552);
vmware_send(40, 0);
vmware_send(39, 1);
vmware_send(41, 0x53424152);
if (vmware_backdoor_available) klogi("VMware Backdoor available.");

//+ ========== VT-x / AMD-V ==========

Expand Down Expand Up @@ -132,7 +90,7 @@ void sysinit() {
init_tty();
screen_clear();

init_pci(page_alloc(1 * 1024 * 1024));
pci_init();

virtio_init();
virtio_gpu_init();
Expand All @@ -158,4 +116,6 @@ void sysinit() {

keyboard_init();
mouse_init();

vmtools_init();
}
2 changes: 1 addition & 1 deletion src/loader/driver/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ void pci_config(u32 bus, u32 f, u32 equipment, u32 adder) {
// cmd = cmd | 0x01;
asm_out32(PCI_COMMAND_PORT, cmd);
}
void init_pci(u32 adder_Base) {
void pci_init(u32 adder_Base) {
u32 i, BUS, Equipment, F, ADDER, *i1;
u8 *PCI_DATA = (u8 *)adder_Base, *PCI_DATA1;
for (BUS = 0; BUS < 256; BUS++) { // 查询总线
Expand Down

0 comments on commit 8b83334

Please sign in to comment.