瀏覽代碼

Kernel: Simplify VMWareBackdoor somewhat

- If there is no VMWare backdoor, don't allocate memory for it.
- Remove the "unsupported" state, instead just don't instantiate.
- Move the command-line parsing from init to the driver.
- Move mouse packet reception from PS2MouseDevice to VMWareBackdoor.
Andreas Kling 5 年之前
父節點
當前提交
5cc09b0245

+ 5 - 0
Kernel/CommandLine.cpp

@@ -61,6 +61,11 @@ CommandLine::CommandLine(const String& string)
     }
 }
 
+Optional<String> CommandLine::lookup(const String& key) const
+{
+    return m_params.get(key);
+}
+
 String CommandLine::get(const String& key) const
 {
     return m_params.get(key).value_or({});

+ 3 - 0
Kernel/CommandLine.h

@@ -27,17 +27,20 @@
 #pragma once
 
 #include <AK/HashMap.h>
+#include <AK/Optional.h>
 #include <AK/String.h>
 
 namespace Kernel {
 
 class CommandLine {
     AK_MAKE_ETERNAL;
+
 public:
     static void initialize(const String&);
 
     const String& string() const { return m_string; }
     String get(const String& key) const;
+    Optional<String> lookup(const String& key) const;
     bool contains(const String& key) const;
 
 private:

+ 8 - 67
Kernel/Devices/PS2MouseDevice.cpp

@@ -51,14 +51,6 @@ namespace Kernel {
 #define PS2MOUSE_RESEND 0xFE
 #define PS2MOUSE_RESET 0xFF
 
-#define PS2MOUSE_LEFT_CLICK 0x01
-#define PS2MOUSE_RIGHT_CLICK 0x02
-#define PS2MOUSE_MIDDLE_CLICK 0x04
-
-#define VMMOUSE_LEFT_CLICK 0x20
-#define VMMOUSE_RIGHT_CLICK 0x10
-#define VMMOUSE_MIDDLE_CLICK 0x08
-
 #define PS2MOUSE_INTELLIMOUSE_ID 0x03
 
 //#define PS2MOUSE_DEBUG
@@ -82,68 +74,17 @@ PS2MouseDevice& PS2MouseDevice::the()
     return *s_the;
 }
 
-void PS2MouseDevice::handle_vmmouse_absolute_pointer()
-{
-    VMWareCommand command;
-    command.bx = 0;
-    command.command = VMMOUSE_STATUS;
-    VMWareBackdoor::the().send(command);
-    if (command.ax == 0xFFFF0000) {
-#ifdef PS2MOUSE_DEBUG
-        dbg() << "Reset vmmouse.";
-#endif
-        VMWareBackdoor::the().disable_absolute_vmmouse();
-        VMWareBackdoor::the().enable_absolute_vmmouse();
-        return;
-    }
-    int words = command.ax & 0xFFFF;
-
-    if (!words || words % 4)
-        return;
-    command.size = 4;
-    command.command = VMMOUSE_DATA;
-    VMWareBackdoor::the().send(command);
-
-    int buttons = (command.ax & 0xFFFF);
-    int x = (command.bx);
-    int y = (command.cx);
-    int z = (command.dx);
-
-#ifdef PS2MOUSE_DEBUG
-    dbg() << "Absolute Mouse: Buttons " << String::format("%x", buttons);
-    dbg() << "Mouse: X " << x << ", Y " << y << ", Z " << z;
-#endif
-    MousePacket packet;
-    packet.x = x;
-    packet.y = y;
-    packet.z = z;
-    if (buttons & VMMOUSE_LEFT_CLICK) {
-        packet.buttons |= PS2MOUSE_LEFT_CLICK;
-    }
-    if (buttons & VMMOUSE_RIGHT_CLICK) {
-        packet.buttons |= PS2MOUSE_RIGHT_CLICK;
-    }
-    if (buttons & VMMOUSE_MIDDLE_CLICK) {
-        packet.buttons |= PS2MOUSE_MIDDLE_CLICK;
-    }
-    packet.is_relative = false;
-    m_queue.enqueue(packet);
-}
-
 void PS2MouseDevice::handle_irq(const RegisterState&)
 {
-
-    if (VMWareBackdoor::the().vmmouse_is_absolute()) {
-#ifdef PS2MOUSE_DEBUG
-        dbg() << "Handling PS2 vmmouse.";
-#endif
-        IO::in8(I8042_BUFFER);
-        handle_vmmouse_absolute_pointer();
-        return;
+    if (auto* backdoor = VMWareBackdoor::the()) {
+        if (backdoor->vmmouse_is_absolute()) {
+            IO::in8(I8042_BUFFER);
+            auto packet = backdoor->receive_mouse_packet();
+            if (packet.has_value())
+                m_queue.enqueue(packet.value());
+            return;
+        }
     }
-#ifdef PS2MOUSE_DEBUG
-    dbg() << "Handling classical PS2 mouse.";
-#endif
     for (;;) {
         u8 status = IO::in8(I8042_STATUS);
         if (!(((status & I8042_WHICH_BUFFER) == I8042_MOUSE_BUFFER) && (status & I8042_BUFFER_FULL)))

+ 79 - 49
Kernel/Devices/VMWareBackdoor.cpp

@@ -27,7 +27,9 @@
 #include <AK/Assertions.h>
 #include <AK/String.h>
 #include <Kernel/Arch/i386/CPU.h>
+#include <Kernel/CommandLine.h>
 #include <Kernel/Devices/VMWareBackdoor.h>
+#include <Kernel/MousePacket.h>
 #include <LibBareMetal/IO.h>
 
 namespace Kernel {
@@ -40,6 +42,9 @@ namespace Kernel {
 #define VMMOUSE_REQUEST_ABSOLUTE 0x53424152
 
 #define VMMOUSE_QEMU_VERSION 0x3442554a
+#define VMMOUSE_LEFT_CLICK 0x20
+#define VMMOUSE_RIGHT_CLICK 0x10
+#define VMMOUSE_MIDDLE_CLICK 0x08
 
 #define VMWARE_MAGIC 0x564D5868
 #define VMWARE_PORT 0x5658
@@ -77,34 +82,7 @@ inline void vmware_high_bandwidth_get(VMWareCommand& command)
 
 static VMWareBackdoor* s_vmware_backdoor;
 
-static bool is_initialized()
-{
-    return s_vmware_backdoor != nullptr;
-}
-
-void VMWareBackdoor::initialize()
-{
-    if (!is_initialized())
-        s_vmware_backdoor = new VMWareBackdoor;
-}
-
-VMWareBackdoor& VMWareBackdoor::the()
-{
-    ASSERT(s_vmware_backdoor != nullptr);
-    return *s_vmware_backdoor;
-}
-
-VMWareBackdoor::VMWareBackdoor()
-{
-    if (!detect_presence()) {
-        klog() << "VMWare Backdoor: Not supported!";
-        m_supported = false;
-        return;
-    }
-    klog() << "VMWare Backdoor: Supported.";
-    m_supported = true;
-}
-bool VMWareBackdoor::detect_presence()
+static bool detect_presence()
 {
     VMWareCommand command;
     command.bx = ~VMWARE_MAGIC;
@@ -115,15 +93,29 @@ bool VMWareBackdoor::detect_presence()
     return true;
 }
 
-bool VMWareBackdoor::supported()
+VMWareBackdoor* VMWareBackdoor::initialize()
+{
+    if (!detect_presence())
+        return nullptr;
+
+    s_vmware_backdoor = new VMWareBackdoor;
+    klog() << "VMWare backdoor opened.";
+    return s_vmware_backdoor;
+}
+
+VMWareBackdoor* VMWareBackdoor::the()
+{
+    return s_vmware_backdoor;
+}
+
+VMWareBackdoor::VMWareBackdoor()
 {
-    return m_supported;
+    if (kernel_command_line().lookup("vmmouse").value_or("on") == "on")
+        enable_absolute_vmmouse();
 }
 
 bool VMWareBackdoor::detect_vmmouse()
 {
-    if (!supported())
-        return false;
     VMWareCommand command;
     command.bx = VMMOUSE_READ_ID;
     command.command = VMMOUSE_COMMAND;
@@ -135,7 +127,7 @@ bool VMWareBackdoor::detect_vmmouse()
         return false;
     return true;
 }
-bool VMWareBackdoor::vmmouse_is_absolute()
+bool VMWareBackdoor::vmmouse_is_absolute() const
 {
     return m_vmmouse_absolute;
 }
@@ -143,9 +135,9 @@ bool VMWareBackdoor::vmmouse_is_absolute()
 void VMWareBackdoor::enable_absolute_vmmouse()
 {
     InterruptDisabler disabler;
-    if (!supported() || !detect_vmmouse())
+    if (!detect_vmmouse())
         return;
-    dbg() << "Enabling vmmouse, absolute mode";
+    klog() << "VMWareBackdoor: Enabling absolute mouse mode";
 
     VMWareCommand command;
 
@@ -153,7 +145,7 @@ void VMWareBackdoor::enable_absolute_vmmouse()
     command.command = VMMOUSE_STATUS;
     send(command);
     if (command.ax == 0xFFFF0000) {
-        klog() << "VMMouse retuned bad status.";
+        klog() << "VMWareBackdoor: VMMOUSE_STATUS got bad status";
         return;
     }
 
@@ -166,8 +158,6 @@ void VMWareBackdoor::enable_absolute_vmmouse()
 void VMWareBackdoor::disable_absolute_vmmouse()
 {
     InterruptDisabler disabler;
-    if (!supported())
-        return;
     VMWareCommand command;
     command.bx = VMMOUSE_REQUEST_RELATIVE;
     command.command = VMMOUSE_COMMAND;
@@ -177,32 +167,72 @@ void VMWareBackdoor::disable_absolute_vmmouse()
 
 void VMWareBackdoor::send_high_bandwidth(VMWareCommand& command)
 {
-    if (supported()) {
-        vmware_high_bandwidth_send(command);
+    vmware_high_bandwidth_send(command);
 #ifdef VMWAREBACKDOOR_DEBUG
-        dbg() << "VMWareBackdoor Command High bandwidth Send Results: EAX " << String::format("%x", command.ax) << " EBX " << String::format("%x", command.bx) << " ECX " << String::format("%x", command.cx) << " EDX " << String::format("%x", command.dx);
+    dbg() << "VMWareBackdoor Command High bandwidth Send Results: EAX " << String::format("%x", command.ax) << " EBX " << String::format("%x", command.bx) << " ECX " << String::format("%x", command.cx) << " EDX " << String::format("%x", command.dx);
 #endif
-    }
 }
 
 void VMWareBackdoor::get_high_bandwidth(VMWareCommand& command)
 {
-    if (supported()) {
-        vmware_high_bandwidth_get(command);
+    vmware_high_bandwidth_get(command);
 #ifdef VMWAREBACKDOOR_DEBUG
-        dbg() << "VMWareBackdoor Command High bandwidth Get Results: EAX " << String::format("%x", command.ax) << " EBX " << String::format("%x", command.bx) << " ECX " << String::format("%x", command.cx) << " EDX " << String::format("%x", command.dx);
+    dbg() << "VMWareBackdoor Command High bandwidth Get Results: EAX " << String::format("%x", command.ax) << " EBX " << String::format("%x", command.bx) << " ECX " << String::format("%x", command.cx) << " EDX " << String::format("%x", command.dx);
 #endif
-    }
 }
 
 void VMWareBackdoor::send(VMWareCommand& command)
 {
-    if (supported()) {
-        vmware_out(command);
+    vmware_out(command);
 #ifdef VMWAREBACKDOOR_DEBUG
-        dbg() << "VMWareBackdoor Command Send Results: EAX " << String::format("%x", command.ax) << " EBX " << String::format("%x", command.bx) << " ECX " << String::format("%x", command.cx) << " EDX " << String::format("%x", command.dx);
+    dbg() << "VMWareBackdoor Command Send Results: EAX " << String::format("%x", command.ax) << " EBX " << String::format("%x", command.bx) << " ECX " << String::format("%x", command.cx) << " EDX " << String::format("%x", command.dx);
 #endif
+}
+
+Optional<MousePacket> VMWareBackdoor::receive_mouse_packet()
+{
+    VMWareCommand command;
+    command.bx = 0;
+    command.command = VMMOUSE_STATUS;
+    send(command);
+    if (command.ax == 0xFFFF0000) {
+#ifdef PS2MOUSE_DEBUG
+        klog() << "PS2MouseDevice: Resetting VMWare mouse";
+#endif
+        disable_absolute_vmmouse();
+        enable_absolute_vmmouse();
+        return {};
     }
+    int words = command.ax & 0xFFFF;
+
+    if (!words || words % 4)
+        return {};
+    command.size = 4;
+    command.command = VMMOUSE_DATA;
+    send(command);
+
+    int buttons = (command.ax & 0xFFFF);
+    int x = (command.bx);
+    int y = (command.cx);
+    int z = (command.dx);
+
+#ifdef PS2MOUSE_DEBUG
+    dbg() << "Absolute Mouse: Buttons " << String::format("%x", buttons);
+    dbg() << "Mouse: X " << x << ", Y " << y << ", Z " << z;
+#endif
+    MousePacket packet;
+    packet.x = x;
+    packet.y = y;
+    packet.z = z;
+    if (buttons & VMMOUSE_LEFT_CLICK)
+        packet.buttons |= MousePacket::LeftButton;
+    if (buttons & VMMOUSE_RIGHT_CLICK)
+        packet.buttons |= MousePacket::RightButton;
+    if (buttons & VMMOUSE_MIDDLE_CLICK)
+        packet.buttons |= MousePacket::MiddleButton;
+
+    packet.is_relative = false;
+    return packet;
 }
 
 }

+ 8 - 6
Kernel/Devices/VMWareBackdoor.h

@@ -26,8 +26,10 @@
 
 #pragma once
 
+#include <AK/Optional.h>
 #include <AK/Types.h>
 #include <AK/kmalloc.h>
+#include <Kernel/MousePacket.h>
 
 namespace Kernel {
 
@@ -61,21 +63,21 @@ class VMWareBackdoor {
     AK_MAKE_ETERNAL;
 
 public:
-    static void initialize();
-    static VMWareBackdoor& the();
-    bool supported();
-    bool vmmouse_is_absolute();
+    static VMWareBackdoor* the();
+
+    static VMWareBackdoor* initialize();
+    bool vmmouse_is_absolute() const;
     void enable_absolute_vmmouse();
     void disable_absolute_vmmouse();
     void send(VMWareCommand& command);
 
+    Optional<MousePacket> receive_mouse_packet();
+
 private:
     void send_high_bandwidth(VMWareCommand& command);
     void get_high_bandwidth(VMWareCommand& command);
     VMWareBackdoor();
-    bool detect_presence();
     bool detect_vmmouse();
-    bool m_supported;
     bool m_vmmouse_absolute { false };
 };
 

+ 7 - 0
Kernel/MousePacket.h

@@ -32,6 +32,13 @@ struct MousePacket {
     int x { 0 };
     int y { 0 };
     int z { 0 };
+
+    enum Button {
+        LeftButton = 0x01,
+        RightButton = 0x02,
+        MiddleButton = 0x04,
+    };
+
     unsigned char buttons { 0 };
     bool is_relative { true };
 };

+ 3 - 22
Kernel/init.cpp

@@ -66,10 +66,10 @@
 #include <Kernel/RTC.h>
 #include <Kernel/Random.h>
 #include <Kernel/Scheduler.h>
-#include <Kernel/Tasks/FinalizerTask.h>
-#include <Kernel/Tasks/SyncTask.h>
 #include <Kernel/TTY/PTYMultiplexer.h>
 #include <Kernel/TTY/VirtualConsole.h>
+#include <Kernel/Tasks/FinalizerTask.h>
+#include <Kernel/Tasks/SyncTask.h>
 #include <Kernel/Time/TimeManagement.h>
 #include <Kernel/VM/MemoryManager.h>
 
@@ -86,7 +86,6 @@ namespace Kernel {
 [[noreturn]] static void init_stage2();
 static void setup_serial_debug();
 static void setup_acpi();
-static void setup_vmmouse();
 static void setup_pci();
 static void setup_interrupts();
 static void setup_time_management();
@@ -130,7 +129,6 @@ extern "C" [[noreturn]] void init()
     new VFS;
     new KeyboardDevice;
     new PS2MouseDevice;
-    setup_vmmouse();
     new Console;
 
     klog() << "Starting SerenityOS...";
@@ -198,6 +196,7 @@ void init_stage2()
     new RandomDevice;
     new PTYMultiplexer;
     new SB16;
+    VMWareBackdoor::initialize();
 
     bool dmi_unreliable = kernel_command_line().contains("dmi_unreliable");
     if (dmi_unreliable) {
@@ -390,24 +389,6 @@ void setup_acpi()
     hang();
 }
 
-void setup_vmmouse()
-{
-    VMWareBackdoor::initialize();
-    if (!kernel_command_line().contains("vmmouse")) {
-        VMWareBackdoor::the().enable_absolute_vmmouse();
-        return;
-    }
-    auto vmmouse = kernel_command_line().get("vmmouse");
-    if (vmmouse == "off")
-        return;
-    if (vmmouse == "on") {
-        VMWareBackdoor::the().enable_absolute_vmmouse();
-        return;
-    }
-    klog() << "vmmouse boot argmuent has an invalid value.";
-    hang();
-}
-
 void setup_pci()
 {
     if (!kernel_command_line().contains("pci_mmio")) {