Compare commits
9 Commits
ccaa159a73
...
969e07f0a2
Author | SHA1 | Date |
---|---|---|
|
969e07f0a2 | |
|
26da057ac4 | |
|
d1e187570e | |
|
d4191c0d94 | |
|
c2957d8761 | |
|
891ced4da2 | |
|
8f8d6bddc0 | |
|
d2d12d5281 | |
|
0ba278041b |
|
@ -32,9 +32,11 @@ set(KERNEL_SOURCES
|
||||||
kernel/FS/TmpFS/FileSystem.cpp
|
kernel/FS/TmpFS/FileSystem.cpp
|
||||||
kernel/FS/TmpFS/Inode.cpp
|
kernel/FS/TmpFS/Inode.cpp
|
||||||
kernel/FS/VirtualFileSystem.cpp
|
kernel/FS/VirtualFileSystem.cpp
|
||||||
kernel/Input/PS2Controller.cpp
|
kernel/Input/PS2/Controller.cpp
|
||||||
kernel/Input/PS2Keyboard.cpp
|
kernel/Input/PS2/Device.cpp
|
||||||
kernel/Input/PS2Keymap.cpp
|
kernel/Input/PS2/Keyboard.cpp
|
||||||
|
kernel/Input/PS2/Keymap.cpp
|
||||||
|
kernel/Input/PS2/Mouse.cpp
|
||||||
kernel/InterruptController.cpp
|
kernel/InterruptController.cpp
|
||||||
kernel/kernel.cpp
|
kernel/kernel.cpp
|
||||||
kernel/Memory/DMARegion.cpp
|
kernel/Memory/DMARegion.cpp
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace Kernel::Input
|
||||||
|
{
|
||||||
|
|
||||||
|
enum class MouseButton
|
||||||
|
{
|
||||||
|
Left, Right, Middle, Extra1, Extra2
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MouseButtonEvent
|
||||||
|
{
|
||||||
|
MouseButton button;
|
||||||
|
bool pressed;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MouseMoveEvent
|
||||||
|
{
|
||||||
|
int32_t rel_x;
|
||||||
|
int32_t rel_y;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MouseScrollEvent
|
||||||
|
{
|
||||||
|
int32_t scroll;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class MouseEventType
|
||||||
|
{
|
||||||
|
MouseButtonEvent,
|
||||||
|
MouseMoveEvent,
|
||||||
|
MouseScrollEvent,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MouseEvent
|
||||||
|
{
|
||||||
|
MouseEventType type;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
MouseButtonEvent button_event;
|
||||||
|
MouseMoveEvent move_event;
|
||||||
|
MouseScrollEvent scroll_event;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -55,6 +55,7 @@ namespace Kernel::Input::PS2
|
||||||
TEST_CONTROLLER_PASS = 0x55,
|
TEST_CONTROLLER_PASS = 0x55,
|
||||||
SELF_TEST_PASS = 0xAA,
|
SELF_TEST_PASS = 0xAA,
|
||||||
ACK = 0xFA,
|
ACK = 0xFA,
|
||||||
|
RESEND = 0xFE,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum DeviceCommand : uint8_t
|
enum DeviceCommand : uint8_t
|
||||||
|
@ -74,9 +75,6 @@ namespace Kernel::Input::PS2
|
||||||
enum KBResponse : uint8_t
|
enum KBResponse : uint8_t
|
||||||
{
|
{
|
||||||
KEY_ERROR_OR_BUFFER_OVERRUN1 = 0x00,
|
KEY_ERROR_OR_BUFFER_OVERRUN1 = 0x00,
|
||||||
SELF_TEST_PASSED = 0xAA,
|
|
||||||
ECHO_RESPONSE = 0xEE,
|
|
||||||
RESEND = 0xFE,
|
|
||||||
KEY_ERROR_OR_BUFFER_OVERRUN2 = 0xFF,
|
KEY_ERROR_OR_BUFFER_OVERRUN2 = 0xFF,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,24 +1,13 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <BAN/CircularQueue.h>
|
||||||
#include <kernel/Device/Device.h>
|
#include <kernel/Device/Device.h>
|
||||||
#include <kernel/InterruptController.h>
|
#include <kernel/InterruptController.h>
|
||||||
|
|
||||||
namespace Kernel::Input
|
namespace Kernel::Input
|
||||||
{
|
{
|
||||||
|
|
||||||
class PS2Device : public CharacterDevice, public Interruptable
|
class PS2Device;
|
||||||
{
|
|
||||||
public:
|
|
||||||
PS2Device();
|
|
||||||
virtual ~PS2Device() {}
|
|
||||||
|
|
||||||
virtual void send_initialize() = 0;
|
|
||||||
|
|
||||||
virtual BAN::StringView name() const override { return m_name; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
const BAN::String m_name;
|
|
||||||
};
|
|
||||||
|
|
||||||
class PS2Controller
|
class PS2Controller
|
||||||
{
|
{
|
|
@ -0,0 +1,45 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <kernel/Input/PS2/Controller.h>
|
||||||
|
|
||||||
|
namespace Kernel::Input
|
||||||
|
{
|
||||||
|
|
||||||
|
class PS2Device : public CharacterDevice, public Interruptable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PS2Device(PS2Controller&);
|
||||||
|
virtual ~PS2Device() {}
|
||||||
|
|
||||||
|
virtual void send_initialize() = 0;
|
||||||
|
|
||||||
|
bool append_command_queue(uint8_t command);
|
||||||
|
bool append_command_queue(uint8_t command, uint8_t data);
|
||||||
|
virtual void handle_irq() final override;
|
||||||
|
|
||||||
|
virtual void handle_byte(uint8_t) = 0;
|
||||||
|
virtual void handle_device_command_response(uint8_t) = 0;
|
||||||
|
|
||||||
|
virtual BAN::StringView name() const final override { return m_name; }
|
||||||
|
virtual dev_t rdev() const final override { return m_rdev; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void update();
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum class State
|
||||||
|
{
|
||||||
|
Normal,
|
||||||
|
WaitingAck,
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
const BAN::String m_name;
|
||||||
|
const dev_t m_rdev;
|
||||||
|
|
||||||
|
PS2Controller& m_controller;
|
||||||
|
State m_state = State::Normal;
|
||||||
|
BAN::CircularQueue<uint8_t, 10> m_command_queue;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -1,9 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <BAN/CircularQueue.h>
|
|
||||||
#include <kernel/Input/KeyEvent.h>
|
#include <kernel/Input/KeyEvent.h>
|
||||||
#include <kernel/Input/PS2Controller.h>
|
#include <kernel/Input/PS2/Device.h>
|
||||||
#include <kernel/Input/PS2Keymap.h>
|
#include <kernel/Input/PS2/Keymap.h>
|
||||||
#include <kernel/Semaphore.h>
|
#include <kernel/Semaphore.h>
|
||||||
|
|
||||||
namespace Kernel::Input
|
namespace Kernel::Input
|
||||||
|
@ -15,59 +14,36 @@ namespace Kernel::Input
|
||||||
enum Command : uint8_t
|
enum Command : uint8_t
|
||||||
{
|
{
|
||||||
SET_LEDS = 0xED,
|
SET_LEDS = 0xED,
|
||||||
SCANCODE = 0xF0,
|
SCANCODE = 0xF0
|
||||||
ENABLE_SCANNING = 0xF4,
|
|
||||||
DISABLE_SCANNING = 0xF5,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class State
|
|
||||||
{
|
|
||||||
Normal,
|
|
||||||
WaitingAck,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<PS2Keyboard*> create(PS2Controller&);
|
static BAN::ErrorOr<PS2Keyboard*> create(PS2Controller&);
|
||||||
virtual void send_initialize() override;
|
virtual void send_initialize() override;
|
||||||
|
|
||||||
virtual void handle_irq() override;
|
virtual void handle_byte(uint8_t) final override;
|
||||||
virtual void update() override;
|
virtual void handle_device_command_response(uint8_t) final override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PS2Keyboard(PS2Controller& controller);
|
PS2Keyboard(PS2Controller& controller);
|
||||||
|
|
||||||
void append_command_queue(uint8_t);
|
|
||||||
void append_command_queue(uint8_t, uint8_t);
|
|
||||||
|
|
||||||
void buffer_has_key();
|
|
||||||
|
|
||||||
void update_leds();
|
void update_leds();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PS2Controller& m_controller;
|
|
||||||
uint8_t m_byte_buffer[10];
|
uint8_t m_byte_buffer[10];
|
||||||
uint8_t m_byte_index { 0 };
|
uint8_t m_byte_index { 0 };
|
||||||
|
|
||||||
uint8_t m_modifiers { 0 };
|
uint8_t m_modifiers { 0 };
|
||||||
|
|
||||||
BAN::CircularQueue<KeyEvent, 10> m_event_queue;
|
BAN::CircularQueue<KeyEvent, 10> m_event_queue;
|
||||||
BAN::CircularQueue<uint8_t, 10> m_command_queue;
|
|
||||||
|
|
||||||
PS2Keymap m_keymap;
|
PS2Keymap m_keymap;
|
||||||
|
|
||||||
State m_state { State::Normal };
|
|
||||||
|
|
||||||
Semaphore m_semaphore;
|
Semaphore m_semaphore;
|
||||||
|
|
||||||
public:
|
|
||||||
virtual dev_t rdev() const override { return m_rdev; }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
||||||
virtual bool has_data_impl() const override;
|
virtual bool has_data_impl() const override;
|
||||||
|
|
||||||
private:
|
|
||||||
const dev_t m_rdev;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <kernel/Input/MouseEvent.h>
|
||||||
|
#include <kernel/Input/PS2/Device.h>
|
||||||
|
#include <kernel/Semaphore.h>
|
||||||
|
|
||||||
|
namespace Kernel::Input
|
||||||
|
{
|
||||||
|
|
||||||
|
class PS2Mouse final : public PS2Device
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
enum Command : uint8_t
|
||||||
|
{
|
||||||
|
SET_SAMPLE_RATE = 0xF3
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
static BAN::ErrorOr<PS2Mouse*> create(PS2Controller&);
|
||||||
|
virtual void send_initialize() override;
|
||||||
|
|
||||||
|
virtual void handle_byte(uint8_t) final override;
|
||||||
|
virtual void handle_device_command_response(uint8_t) final override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
PS2Mouse(PS2Controller& controller);
|
||||||
|
|
||||||
|
void initialize_extensions(uint8_t);
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8_t m_byte_buffer[10];
|
||||||
|
uint8_t m_byte_index { 0 };
|
||||||
|
|
||||||
|
bool m_enabled { false };
|
||||||
|
uint8_t m_mouse_id { 0x00 };
|
||||||
|
uint8_t m_button_mask { 0x00 };
|
||||||
|
|
||||||
|
BAN::CircularQueue<MouseEvent, 25> m_event_queue;
|
||||||
|
|
||||||
|
Semaphore m_semaphore;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
||||||
|
virtual bool has_data_impl() const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -68,7 +68,7 @@ namespace Kernel
|
||||||
BAN::ErrorOr<long> sys_settermios(const ::termios*);
|
BAN::ErrorOr<long> sys_settermios(const ::termios*);
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_fork(uintptr_t rsp, uintptr_t rip);
|
BAN::ErrorOr<long> sys_fork(uintptr_t rsp, uintptr_t rip);
|
||||||
BAN::ErrorOr<long> sys_exec(BAN::StringView path, const char* const* argv, const char* const* envp);
|
BAN::ErrorOr<long> sys_exec(const char* path, const char* const* argv, const char* const* envp);
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_wait(pid_t pid, int* stat_loc, int options);
|
BAN::ErrorOr<long> sys_wait(pid_t pid, int* stat_loc, int options);
|
||||||
BAN::ErrorOr<long> sys_sleep(int seconds);
|
BAN::ErrorOr<long> sys_sleep(int seconds);
|
||||||
|
@ -175,8 +175,8 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::String> absolute_path_of(BAN::StringView) const;
|
BAN::ErrorOr<BAN::String> absolute_path_of(BAN::StringView) const;
|
||||||
|
|
||||||
void validate_string_access(const char*);
|
BAN::ErrorOr<void> validate_string_access(const char*);
|
||||||
void validate_pointer_access(const void*, size_t);
|
BAN::ErrorOr<void> validate_pointer_access(const void*, size_t);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct ExitStatus
|
struct ExitStatus
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace Kernel
|
||||||
BAN::Vector<uint8_t> superblock_buffer;
|
BAN::Vector<uint8_t> superblock_buffer;
|
||||||
TRY(superblock_buffer.resize(sector_count * sector_size));
|
TRY(superblock_buffer.resize(sector_count * sector_size));
|
||||||
|
|
||||||
TRY(m_block_device->read_blocks(lba, sector_count, superblock_buffer.span()));
|
TRY(m_block_device->read_blocks(lba, sector_count, BAN::ByteSpan(superblock_buffer.span())));
|
||||||
|
|
||||||
memcpy(&m_superblock, superblock_buffer.data(), sizeof(Ext2::Superblock));
|
memcpy(&m_superblock, superblock_buffer.data(), sizeof(Ext2::Superblock));
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,10 @@
|
||||||
#include <kernel/ACPI.h>
|
#include <kernel/ACPI.h>
|
||||||
#include <kernel/FS/DevFS/FileSystem.h>
|
#include <kernel/FS/DevFS/FileSystem.h>
|
||||||
#include <kernel/IDT.h>
|
#include <kernel/IDT.h>
|
||||||
#include <kernel/Input/PS2Config.h>
|
#include <kernel/Input/PS2/Config.h>
|
||||||
#include <kernel/Input/PS2Controller.h>
|
#include <kernel/Input/PS2/Controller.h>
|
||||||
#include <kernel/Input/PS2Keyboard.h>
|
#include <kernel/Input/PS2/Keyboard.h>
|
||||||
|
#include <kernel/Input/PS2/Mouse.h>
|
||||||
#include <kernel/InterruptController.h>
|
#include <kernel/InterruptController.h>
|
||||||
#include <kernel/IO.h>
|
#include <kernel/IO.h>
|
||||||
#include <kernel/Timer/Timer.h>
|
#include <kernel/Timer/Timer.h>
|
||||||
|
@ -68,11 +69,6 @@ namespace Kernel::Input
|
||||||
|
|
||||||
static PS2Controller* s_instance = nullptr;
|
static PS2Controller* s_instance = nullptr;
|
||||||
|
|
||||||
PS2Device::PS2Device()
|
|
||||||
: CharacterDevice(0440, 0, 901)
|
|
||||||
, m_name(BAN::String::formatted("input{}", DevFileSystem::get().get_next_input_device()))
|
|
||||||
{ }
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> PS2Controller::initialize()
|
BAN::ErrorOr<void> PS2Controller::initialize()
|
||||||
{
|
{
|
||||||
ASSERT(s_instance == nullptr);
|
ASSERT(s_instance == nullptr);
|
||||||
|
@ -218,10 +214,9 @@ namespace Kernel::Input
|
||||||
|
|
||||||
// Standard PS/2 Mouse
|
// Standard PS/2 Mouse
|
||||||
if (index == 1 && (bytes[0] == 0x00))
|
if (index == 1 && (bytes[0] == 0x00))
|
||||||
return BAN::Error::from_error_code(ErrorCode::PS2_UnsupportedDevice);
|
m_devices[device] = TRY(PS2Mouse::create(*this));
|
||||||
|
|
||||||
// MF2 Keyboard
|
// MF2 Keyboard
|
||||||
if (index == 2 && (bytes[0] == 0xAB && bytes[1] == 0x83))
|
else if (index == 2 && (bytes[0] == 0xAB && bytes[1] == 0x83))
|
||||||
m_devices[device] = TRY(PS2Keyboard::create(*this));
|
m_devices[device] = TRY(PS2Keyboard::create(*this));
|
||||||
|
|
||||||
if (m_devices[device])
|
if (m_devices[device])
|
|
@ -0,0 +1,88 @@
|
||||||
|
#include <kernel/FS/DevFS/FileSystem.h>
|
||||||
|
#include <kernel/Input/PS2/Config.h>
|
||||||
|
#include <kernel/Input/PS2/Device.h>
|
||||||
|
#include <kernel/IO.h>
|
||||||
|
|
||||||
|
#include <sys/sysmacros.h>
|
||||||
|
|
||||||
|
namespace Kernel::Input
|
||||||
|
{
|
||||||
|
|
||||||
|
PS2Device::PS2Device(PS2Controller& controller)
|
||||||
|
: CharacterDevice(0440, 0, 901)
|
||||||
|
, m_name(BAN::String::formatted("input{}", DevFileSystem::get().get_next_input_device()))
|
||||||
|
, m_rdev(makedev(DevFileSystem::get().get_next_dev(), 0))
|
||||||
|
, m_controller(controller)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
bool PS2Device::append_command_queue(uint8_t command)
|
||||||
|
{
|
||||||
|
if (m_command_queue.size() + 1 >= m_command_queue.capacity())
|
||||||
|
{
|
||||||
|
dprintln("PS/2 command queue full");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_command_queue.push(command);
|
||||||
|
update();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PS2Device::append_command_queue(uint8_t command, uint8_t data)
|
||||||
|
{
|
||||||
|
if (m_command_queue.size() + 2 >= m_command_queue.capacity())
|
||||||
|
{
|
||||||
|
dprintln("PS/2 command queue full");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_command_queue.push(command);
|
||||||
|
m_command_queue.push(data);
|
||||||
|
update();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PS2Device::handle_irq()
|
||||||
|
{
|
||||||
|
uint8_t byte = IO::inb(PS2::IOPort::DATA);
|
||||||
|
|
||||||
|
// NOTE: This implementation does not allow using commands
|
||||||
|
// that respond with more bytes than ACK
|
||||||
|
switch (m_state)
|
||||||
|
{
|
||||||
|
case State::WaitingAck:
|
||||||
|
{
|
||||||
|
switch (byte)
|
||||||
|
{
|
||||||
|
case PS2::Response::ACK:
|
||||||
|
m_command_queue.pop();
|
||||||
|
m_state = State::Normal;
|
||||||
|
break;
|
||||||
|
case PS2::Response::RESEND:
|
||||||
|
m_state = State::Normal;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
handle_device_command_response(byte);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case State::Normal:
|
||||||
|
{
|
||||||
|
handle_byte(byte);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PS2Device::update()
|
||||||
|
{
|
||||||
|
if (m_state == State::WaitingAck)
|
||||||
|
return;
|
||||||
|
if (m_command_queue.empty())
|
||||||
|
return;
|
||||||
|
m_state = State::WaitingAck;
|
||||||
|
m_controller.send_byte(this, m_command_queue.front());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,12 +1,8 @@
|
||||||
#include <BAN/ScopeGuard.h>
|
#include <BAN/ScopeGuard.h>
|
||||||
#include <kernel/CriticalScope.h>
|
#include <kernel/CriticalScope.h>
|
||||||
#include <kernel/FS/DevFS/FileSystem.h>
|
#include <kernel/FS/DevFS/FileSystem.h>
|
||||||
#include <kernel/Input/PS2Config.h>
|
#include <kernel/Input/PS2/Config.h>
|
||||||
#include <kernel/Input/PS2Keyboard.h>
|
#include <kernel/Input/PS2/Keyboard.h>
|
||||||
#include <kernel/IO.h>
|
|
||||||
#include <kernel/Timer/Timer.h>
|
|
||||||
|
|
||||||
#include <sys/sysmacros.h>
|
|
||||||
|
|
||||||
#define SET_MASK(byte, mask, on_off) ((on_off) ? ((byte) | (mask)) : ((byte) & ~(mask)))
|
#define SET_MASK(byte, mask, on_off) ((on_off) ? ((byte) | (mask)) : ((byte) & ~(mask)))
|
||||||
#define TOGGLE_MASK(byte, mask) ((byte) ^ (mask))
|
#define TOGGLE_MASK(byte, mask) ((byte) ^ (mask))
|
||||||
|
@ -23,89 +19,36 @@ namespace Kernel::Input
|
||||||
}
|
}
|
||||||
|
|
||||||
PS2Keyboard::PS2Keyboard(PS2Controller& controller)
|
PS2Keyboard::PS2Keyboard(PS2Controller& controller)
|
||||||
: m_controller(controller)
|
: PS2Device(controller)
|
||||||
, m_rdev(makedev(DevFileSystem::get().get_next_dev(), 0))
|
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
void PS2Keyboard::handle_irq()
|
|
||||||
{
|
|
||||||
uint8_t byte = IO::inb(PS2::IOPort::DATA);
|
|
||||||
|
|
||||||
// NOTE: This implementation does not allow using commands
|
|
||||||
// that respond with more bytes than ACK
|
|
||||||
switch (m_state)
|
|
||||||
{
|
|
||||||
case State::WaitingAck:
|
|
||||||
{
|
|
||||||
switch (byte)
|
|
||||||
{
|
|
||||||
case PS2::Response::ACK:
|
|
||||||
m_command_queue.pop();
|
|
||||||
m_state = State::Normal;
|
|
||||||
break;
|
|
||||||
case PS2::KBResponse::RESEND:
|
|
||||||
m_state = State::Normal;
|
|
||||||
break;
|
|
||||||
case PS2::KBResponse::KEY_ERROR_OR_BUFFER_OVERRUN1:
|
|
||||||
case PS2::KBResponse::KEY_ERROR_OR_BUFFER_OVERRUN2:
|
|
||||||
dwarnln("Key detection error or internal buffer overrun");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
dwarnln("Unhandeled byte {2H}", byte);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case State::Normal:
|
|
||||||
{
|
|
||||||
m_byte_buffer[m_byte_index++] = byte;
|
|
||||||
if (byte != 0xE0 && byte != 0xF0)
|
|
||||||
buffer_has_key();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PS2Keyboard::send_initialize()
|
void PS2Keyboard::send_initialize()
|
||||||
{
|
{
|
||||||
append_command_queue(Command::SET_LEDS, 0x00);
|
append_command_queue(Command::SET_LEDS, 0x00);
|
||||||
append_command_queue(Command::SCANCODE, PS2::KBScancode::SET_SCANCODE_SET2);
|
append_command_queue(Command::SCANCODE, PS2::KBScancode::SET_SCANCODE_SET2);
|
||||||
append_command_queue(Command::ENABLE_SCANNING);
|
append_command_queue(PS2::DeviceCommand::ENABLE_SCANNING);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PS2Keyboard::update()
|
void PS2Keyboard::handle_device_command_response(uint8_t byte)
|
||||||
{
|
{
|
||||||
if (m_state == State::WaitingAck)
|
switch (byte)
|
||||||
return;
|
|
||||||
if (m_command_queue.empty())
|
|
||||||
return;
|
|
||||||
m_state = State::WaitingAck;
|
|
||||||
m_controller.send_byte(this, m_command_queue.front());
|
|
||||||
}
|
|
||||||
|
|
||||||
void PS2Keyboard::append_command_queue(uint8_t byte)
|
|
||||||
{
|
|
||||||
if (m_command_queue.full())
|
|
||||||
{
|
{
|
||||||
dwarnln("PS/2 command queue full");
|
case PS2::KBResponse::KEY_ERROR_OR_BUFFER_OVERRUN1:
|
||||||
return;
|
case PS2::KBResponse::KEY_ERROR_OR_BUFFER_OVERRUN2:
|
||||||
|
dwarnln("Key detection error or internal buffer overrun");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dwarnln("Unhandeled byte {2H}", byte);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
m_command_queue.push(byte);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PS2Keyboard::append_command_queue(uint8_t byte1, uint8_t byte2)
|
void PS2Keyboard::handle_byte(uint8_t byte)
|
||||||
{
|
{
|
||||||
if (m_command_queue.size() + 2 > m_command_queue.capacity())
|
m_byte_buffer[m_byte_index++] = byte;
|
||||||
{
|
if (byte == 0xE0 || byte == 0xF0)
|
||||||
dwarnln("PS/2 command queue full");
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
m_command_queue.push(byte1);
|
|
||||||
m_command_queue.push(byte2);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PS2Keyboard::buffer_has_key()
|
|
||||||
{
|
|
||||||
uint32_t scancode = 0;
|
uint32_t scancode = 0;
|
||||||
bool extended = false;
|
bool extended = false;
|
||||||
bool released = false;
|
bool released = false;
|
||||||
|
@ -185,12 +128,6 @@ namespace Kernel::Input
|
||||||
event.modifier = m_modifiers | (released ? (uint8_t)Input::KeyEvent::Modifier::Released : 0);
|
event.modifier = m_modifiers | (released ? (uint8_t)Input::KeyEvent::Modifier::Released : 0);
|
||||||
event.key = key;
|
event.key = key;
|
||||||
|
|
||||||
if (event.pressed() && event.key == Input::Key::F11)
|
|
||||||
{
|
|
||||||
auto time = SystemTimer::get().time_since_boot();
|
|
||||||
dprintln("{}.{9} s", time.tv_sec, time.tv_nsec);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_event_queue.full())
|
if (m_event_queue.full())
|
||||||
{
|
{
|
||||||
dwarnln("PS/2 event queue full");
|
dwarnln("PS/2 event queue full");
|
|
@ -1,4 +1,4 @@
|
||||||
#include <kernel/Input/PS2Keymap.h>
|
#include <kernel/Input/PS2/Keymap.h>
|
||||||
|
|
||||||
namespace Kernel::Input
|
namespace Kernel::Input
|
||||||
{
|
{
|
|
@ -0,0 +1,210 @@
|
||||||
|
#include <BAN/ScopeGuard.h>
|
||||||
|
#include <kernel/CriticalScope.h>
|
||||||
|
#include <kernel/FS/DevFS/FileSystem.h>
|
||||||
|
#include <kernel/Input/PS2/Config.h>
|
||||||
|
#include <kernel/Input/PS2/Mouse.h>
|
||||||
|
|
||||||
|
#define SET_MASK(byte, mask, on_off) ((on_off) ? ((byte) | (mask)) : ((byte) & ~(mask)))
|
||||||
|
#define TOGGLE_MASK(byte, mask) ((byte) ^ (mask))
|
||||||
|
|
||||||
|
namespace Kernel::Input
|
||||||
|
{
|
||||||
|
|
||||||
|
BAN::ErrorOr<PS2Mouse*> PS2Mouse::create(PS2Controller& controller)
|
||||||
|
{
|
||||||
|
PS2Mouse* mouse = new PS2Mouse(controller);
|
||||||
|
if (mouse == nullptr)
|
||||||
|
return BAN::Error::from_errno(ENOMEM);
|
||||||
|
return mouse;
|
||||||
|
}
|
||||||
|
|
||||||
|
PS2Mouse::PS2Mouse(PS2Controller& controller)
|
||||||
|
: PS2Device(controller)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
void PS2Mouse::send_initialize()
|
||||||
|
{
|
||||||
|
// Query extensions
|
||||||
|
append_command_queue(Command::SET_SAMPLE_RATE, 200);
|
||||||
|
append_command_queue(Command::SET_SAMPLE_RATE, 100);
|
||||||
|
append_command_queue(Command::SET_SAMPLE_RATE, 80);
|
||||||
|
append_command_queue(PS2::DeviceCommand::IDENTIFY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PS2Mouse::initialize_extensions(uint8_t byte)
|
||||||
|
{
|
||||||
|
ASSERT(!m_enabled);
|
||||||
|
|
||||||
|
switch (byte)
|
||||||
|
{
|
||||||
|
case 0x00:
|
||||||
|
m_mouse_id = 0x00;
|
||||||
|
m_enabled = true;
|
||||||
|
break;
|
||||||
|
case 0x03:
|
||||||
|
if (m_mouse_id == 0x03)
|
||||||
|
m_enabled = true;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_mouse_id = 0x03;
|
||||||
|
append_command_queue(Command::SET_SAMPLE_RATE, 200);
|
||||||
|
append_command_queue(Command::SET_SAMPLE_RATE, 200);
|
||||||
|
append_command_queue(Command::SET_SAMPLE_RATE, 80);
|
||||||
|
append_command_queue(PS2::DeviceCommand::IDENTIFY);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x04:
|
||||||
|
m_mouse_id = 0x04;
|
||||||
|
m_enabled = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dprintln("PS/2 Mouse: unknown id {2H}", byte);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_enabled)
|
||||||
|
{
|
||||||
|
append_command_queue(Command::SET_SAMPLE_RATE, 100);
|
||||||
|
append_command_queue(PS2::DeviceCommand::ENABLE_SCANNING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PS2Mouse::handle_device_command_response(uint8_t byte)
|
||||||
|
{
|
||||||
|
switch (byte)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
dwarnln("Unhandeled byte {2H}", byte);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PS2Mouse::handle_byte(uint8_t byte)
|
||||||
|
{
|
||||||
|
if (!m_enabled)
|
||||||
|
return initialize_extensions(byte);
|
||||||
|
|
||||||
|
m_byte_buffer[m_byte_index++] = byte;
|
||||||
|
if (!(m_byte_buffer[0] & 0x08))
|
||||||
|
{
|
||||||
|
dprintln("PS/2 mouse: corrupted package");
|
||||||
|
m_byte_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int packet_size = (m_mouse_id == 0x00) ? 3 : 4;
|
||||||
|
if (m_byte_index < packet_size)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint8_t new_button_mask = m_byte_buffer[0] & 0b111;
|
||||||
|
int32_t rel_x = m_byte_buffer[1] - ((m_byte_buffer[0] << 4) & 0x100);
|
||||||
|
int32_t rel_y = m_byte_buffer[2] - ((m_byte_buffer[0] << 3) & 0x100);
|
||||||
|
int32_t rel_z = 0;
|
||||||
|
|
||||||
|
if (m_mouse_id == 0x03)
|
||||||
|
{
|
||||||
|
rel_z = (int8_t)m_byte_buffer[3];
|
||||||
|
}
|
||||||
|
else if (m_mouse_id == 0x04)
|
||||||
|
{
|
||||||
|
new_button_mask |= (m_byte_buffer[3] >> 1) & 0b11000;
|
||||||
|
|
||||||
|
// sign extend z value
|
||||||
|
if (m_byte_buffer[3] & 0x08)
|
||||||
|
m_byte_buffer[3] |= 0xF0;
|
||||||
|
rel_z = (int8_t)m_byte_buffer[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
m_byte_index = 0;
|
||||||
|
|
||||||
|
// Max 7 events, one for each (5) button, one for movement, one for scroll
|
||||||
|
BAN::Array<MouseEvent, 7> events;
|
||||||
|
int event_count = 0;
|
||||||
|
|
||||||
|
auto button_index_to_button =
|
||||||
|
[](int index) -> MouseButton
|
||||||
|
{
|
||||||
|
if (index == 0)
|
||||||
|
return MouseButton::Left;
|
||||||
|
if (index == 1)
|
||||||
|
return MouseButton::Right;
|
||||||
|
if (index == 2)
|
||||||
|
return MouseButton::Middle;
|
||||||
|
if (index == 3)
|
||||||
|
return MouseButton::Extra1;
|
||||||
|
if (index == 4)
|
||||||
|
return MouseButton::Extra2;
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
};
|
||||||
|
|
||||||
|
if (new_button_mask != m_button_mask)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 5; i++)
|
||||||
|
{
|
||||||
|
if ((new_button_mask & (1 << i)) == (m_button_mask & (1 << i)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto& event = events[event_count++];
|
||||||
|
event.type = MouseEventType::MouseButtonEvent;
|
||||||
|
event.button_event.button = button_index_to_button(i);
|
||||||
|
event.button_event.pressed = !!(new_button_mask & (1 << i));
|
||||||
|
}
|
||||||
|
|
||||||
|
m_button_mask = new_button_mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rel_x || rel_y)
|
||||||
|
{
|
||||||
|
auto& event = events[event_count++];
|
||||||
|
event.type = MouseEventType::MouseMoveEvent;
|
||||||
|
event.move_event.rel_x = rel_x;
|
||||||
|
event.move_event.rel_y = rel_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rel_z)
|
||||||
|
{
|
||||||
|
auto& event = events[event_count++];
|
||||||
|
event.type = MouseEventType::MouseScrollEvent;
|
||||||
|
event.scroll_event.scroll = rel_z;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < event_count; i++)
|
||||||
|
{
|
||||||
|
if (m_event_queue.full())
|
||||||
|
{
|
||||||
|
dwarnln("PS/2 event queue full");
|
||||||
|
m_event_queue.pop();
|
||||||
|
}
|
||||||
|
m_event_queue.push(events[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_semaphore.unblock();
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<size_t> PS2Mouse::read_impl(off_t, BAN::ByteSpan buffer)
|
||||||
|
{
|
||||||
|
if (buffer.size() < sizeof(MouseEvent))
|
||||||
|
return BAN::Error::from_errno(ENOBUFS);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (m_event_queue.empty())
|
||||||
|
m_semaphore.block();
|
||||||
|
|
||||||
|
CriticalScope _;
|
||||||
|
if (m_event_queue.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
buffer.as<MouseEvent>() = m_event_queue.front();
|
||||||
|
m_event_queue.pop();
|
||||||
|
|
||||||
|
return sizeof(MouseEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PS2Mouse::has_data_impl() const
|
||||||
|
{
|
||||||
|
CriticalScope _;
|
||||||
|
return !m_event_queue.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -347,7 +347,7 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
validate_pointer_access(termios, sizeof(::termios));
|
TRY(validate_pointer_access(termios, sizeof(::termios)));
|
||||||
|
|
||||||
if (!m_controlling_terminal)
|
if (!m_controlling_terminal)
|
||||||
return BAN::Error::from_errno(ENOTTY);
|
return BAN::Error::from_errno(ENOTTY);
|
||||||
|
@ -366,7 +366,7 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
validate_pointer_access(termios, sizeof(::termios));
|
TRY(validate_pointer_access(termios, sizeof(::termios)));
|
||||||
|
|
||||||
if (!m_controlling_terminal)
|
if (!m_controlling_terminal)
|
||||||
return BAN::Error::from_errno(ENOTTY);
|
return BAN::Error::from_errno(ENOTTY);
|
||||||
|
@ -439,25 +439,28 @@ namespace Kernel
|
||||||
return forked->pid();
|
return forked->pid();
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_exec(BAN::StringView path, const char* const* argv, const char* const* envp)
|
BAN::ErrorOr<long> Process::sys_exec(const char* path, const char* const* argv, const char* const* envp)
|
||||||
{
|
{
|
||||||
// NOTE: We scope everything for automatic deletion
|
// NOTE: We scope everything for automatic deletion
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
|
TRY(validate_string_access(path));
|
||||||
|
auto loadable_elf = TRY(load_elf_for_exec(m_credentials, path, m_working_directory, page_table()));
|
||||||
|
|
||||||
BAN::Vector<BAN::String> str_argv;
|
BAN::Vector<BAN::String> str_argv;
|
||||||
for (int i = 0; argv && argv[i]; i++)
|
for (int i = 0; argv && argv[i]; i++)
|
||||||
{
|
{
|
||||||
validate_pointer_access(argv + i, sizeof(char*));
|
TRY(validate_pointer_access(argv + i, sizeof(char*)));
|
||||||
validate_string_access(argv[i]);
|
TRY(validate_string_access(argv[i]));
|
||||||
TRY(str_argv.emplace_back(argv[i]));
|
TRY(str_argv.emplace_back(argv[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::Vector<BAN::String> str_envp;
|
BAN::Vector<BAN::String> str_envp;
|
||||||
for (int i = 0; envp && envp[i]; i++)
|
for (int i = 0; envp && envp[i]; i++)
|
||||||
{
|
{
|
||||||
validate_pointer_access(envp + 1, sizeof(char*));
|
TRY(validate_pointer_access(envp + 1, sizeof(char*)));
|
||||||
validate_string_access(envp[i]);
|
TRY(validate_string_access(envp[i]));
|
||||||
TRY(str_envp.emplace_back(envp[i]));
|
TRY(str_envp.emplace_back(envp[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -467,13 +470,14 @@ namespace Kernel
|
||||||
m_open_file_descriptors.close_cloexec();
|
m_open_file_descriptors.close_cloexec();
|
||||||
|
|
||||||
m_mapped_regions.clear();
|
m_mapped_regions.clear();
|
||||||
m_loadable_elf.clear();
|
|
||||||
|
|
||||||
m_loadable_elf = TRY(load_elf_for_exec(m_credentials, executable_path, m_working_directory, page_table()));
|
m_loadable_elf = BAN::move(loadable_elf);
|
||||||
if (!m_loadable_elf->is_address_space_free())
|
if (!m_loadable_elf->is_address_space_free())
|
||||||
{
|
{
|
||||||
dprintln("ELF has unloadable address space");
|
dprintln("ELF has unloadable address space");
|
||||||
MUST(sys_kill(pid(), SIGKILL));
|
MUST(sys_kill(pid(), SIGKILL));
|
||||||
|
// NOTE: signal will only execute after return from syscall
|
||||||
|
return BAN::Error::from_errno(EINTR);
|
||||||
}
|
}
|
||||||
m_loadable_elf->reserve_address_space();
|
m_loadable_elf->reserve_address_space();
|
||||||
m_loadable_elf->update_suid_sgid(m_credentials);
|
m_loadable_elf->update_suid_sgid(m_credentials);
|
||||||
|
@ -568,7 +572,7 @@ namespace Kernel
|
||||||
|
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
validate_pointer_access(stat_loc, sizeof(int));
|
TRY(validate_pointer_access(stat_loc, sizeof(int)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: support options
|
// FIXME: support options
|
||||||
|
@ -618,9 +622,9 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
validate_pointer_access(rqtp, sizeof(timespec));
|
TRY(validate_pointer_access(rqtp, sizeof(timespec)));
|
||||||
if (rmtp)
|
if (rmtp)
|
||||||
validate_pointer_access(rmtp, sizeof(timespec));
|
TRY(validate_pointer_access(rmtp, sizeof(timespec)));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t sleep_ms = rqtp->tv_sec * 1000 + BAN::Math::div_round_up<uint64_t>(rqtp->tv_nsec, 1'000'000);
|
uint64_t sleep_ms = rqtp->tv_sec * 1000 + BAN::Math::div_round_up<uint64_t>(rqtp->tv_nsec, 1'000'000);
|
||||||
|
@ -744,7 +748,7 @@ namespace Kernel
|
||||||
BAN::ErrorOr<long> Process::sys_open(const char* path, int flags, mode_t mode)
|
BAN::ErrorOr<long> Process::sys_open(const char* path, int flags, mode_t mode)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
validate_string_access(path);
|
TRY(validate_string_access(path));
|
||||||
return open_file(path, flags, mode);
|
return open_file(path, flags, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -752,7 +756,7 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
validate_string_access(path);
|
TRY(validate_string_access(path));
|
||||||
|
|
||||||
// FIXME: handle O_SEARCH in fd
|
// FIXME: handle O_SEARCH in fd
|
||||||
|
|
||||||
|
@ -774,21 +778,21 @@ namespace Kernel
|
||||||
BAN::ErrorOr<long> Process::sys_read(int fd, void* buffer, size_t count)
|
BAN::ErrorOr<long> Process::sys_read(int fd, void* buffer, size_t count)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
validate_pointer_access(buffer, count);
|
TRY(validate_pointer_access(buffer, count));
|
||||||
return TRY(m_open_file_descriptors.read(fd, BAN::ByteSpan((uint8_t*)buffer, count)));
|
return TRY(m_open_file_descriptors.read(fd, BAN::ByteSpan((uint8_t*)buffer, count)));
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_write(int fd, const void* buffer, size_t count)
|
BAN::ErrorOr<long> Process::sys_write(int fd, const void* buffer, size_t count)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
validate_pointer_access(buffer, count);
|
TRY(validate_pointer_access(buffer, count));
|
||||||
return TRY(m_open_file_descriptors.write(fd, BAN::ByteSpan((uint8_t*)buffer, count)));
|
return TRY(m_open_file_descriptors.write(fd, BAN::ByteSpan((uint8_t*)buffer, count)));
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_create(const char* path, mode_t mode)
|
BAN::ErrorOr<long> Process::sys_create(const char* path, mode_t mode)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
validate_string_access(path);
|
TRY(validate_string_access(path));
|
||||||
TRY(create_file_or_dir(path, mode));
|
TRY(create_file_or_dir(path, mode));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -796,7 +800,7 @@ namespace Kernel
|
||||||
BAN::ErrorOr<long> Process::sys_create_dir(const char* path, mode_t mode)
|
BAN::ErrorOr<long> Process::sys_create_dir(const char* path, mode_t mode)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
validate_string_access(path);
|
TRY(validate_string_access(path));
|
||||||
BAN::StringView path_sv(path);
|
BAN::StringView path_sv(path);
|
||||||
if (!path_sv.empty() && path_sv.back() == '/')
|
if (!path_sv.empty() && path_sv.back() == '/')
|
||||||
path_sv = path_sv.substring(0, path_sv.size() - 1);
|
path_sv = path_sv.substring(0, path_sv.size() - 1);
|
||||||
|
@ -807,7 +811,7 @@ namespace Kernel
|
||||||
BAN::ErrorOr<long> Process::sys_unlink(const char* path)
|
BAN::ErrorOr<long> Process::sys_unlink(const char* path)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
validate_string_access(path);
|
TRY(validate_string_access(path));
|
||||||
|
|
||||||
auto absolute_path = TRY(absolute_path_of(path));
|
auto absolute_path = TRY(absolute_path_of(path));
|
||||||
|
|
||||||
|
@ -840,8 +844,8 @@ namespace Kernel
|
||||||
BAN::ErrorOr<long> Process::sys_readlink(const char* path, char* buffer, size_t bufsize)
|
BAN::ErrorOr<long> Process::sys_readlink(const char* path, char* buffer, size_t bufsize)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
validate_string_access(path);
|
TRY(validate_string_access(path));
|
||||||
validate_pointer_access(buffer, bufsize);
|
TRY(validate_pointer_access(buffer, bufsize));
|
||||||
|
|
||||||
auto absolute_path = TRY(absolute_path_of(path));
|
auto absolute_path = TRY(absolute_path_of(path));
|
||||||
|
|
||||||
|
@ -851,8 +855,8 @@ namespace Kernel
|
||||||
BAN::ErrorOr<long> Process::sys_readlinkat(int fd, const char* path, char* buffer, size_t bufsize)
|
BAN::ErrorOr<long> Process::sys_readlinkat(int fd, const char* path, char* buffer, size_t bufsize)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
validate_string_access(path);
|
TRY(validate_string_access(path));
|
||||||
validate_pointer_access(buffer, bufsize);
|
TRY(validate_pointer_access(buffer, bufsize));
|
||||||
|
|
||||||
// FIXME: handle O_SEARCH in fd
|
// FIXME: handle O_SEARCH in fd
|
||||||
auto parent_path = TRY(m_open_file_descriptors.path_of(fd));
|
auto parent_path = TRY(m_open_file_descriptors.path_of(fd));
|
||||||
|
@ -868,7 +872,7 @@ namespace Kernel
|
||||||
BAN::ErrorOr<long> Process::sys_pread(int fd, void* buffer, size_t count, off_t offset)
|
BAN::ErrorOr<long> Process::sys_pread(int fd, void* buffer, size_t count, off_t offset)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
validate_pointer_access(buffer, count);
|
TRY(validate_pointer_access(buffer, count));
|
||||||
auto inode = TRY(m_open_file_descriptors.inode_of(fd));
|
auto inode = TRY(m_open_file_descriptors.inode_of(fd));
|
||||||
return TRY(inode->read(offset, { (uint8_t*)buffer, count }));
|
return TRY(inode->read(offset, { (uint8_t*)buffer, count }));
|
||||||
}
|
}
|
||||||
|
@ -879,7 +883,7 @@ namespace Kernel
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
validate_string_access(path);
|
TRY(validate_string_access(path));
|
||||||
|
|
||||||
auto absolute_path = TRY(absolute_path_of(path));
|
auto absolute_path = TRY(absolute_path_of(path));
|
||||||
auto file = TRY(VirtualFileSystem::get().file_from_absolute_path(m_credentials, absolute_path, O_WRONLY));
|
auto file = TRY(VirtualFileSystem::get().file_from_absolute_path(m_credentials, absolute_path, O_WRONLY));
|
||||||
|
@ -891,7 +895,7 @@ namespace Kernel
|
||||||
BAN::ErrorOr<long> Process::sys_chown(const char* path, uid_t uid, gid_t gid)
|
BAN::ErrorOr<long> Process::sys_chown(const char* path, uid_t uid, gid_t gid)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
validate_string_access(path);
|
TRY(validate_string_access(path));
|
||||||
|
|
||||||
auto absolute_path = TRY(absolute_path_of(path));
|
auto absolute_path = TRY(absolute_path_of(path));
|
||||||
auto file = TRY(VirtualFileSystem::get().file_from_absolute_path(m_credentials, absolute_path, O_WRONLY));
|
auto file = TRY(VirtualFileSystem::get().file_from_absolute_path(m_credentials, absolute_path, O_WRONLY));
|
||||||
|
@ -903,7 +907,7 @@ namespace Kernel
|
||||||
BAN::ErrorOr<long> Process::sys_pipe(int fildes[2])
|
BAN::ErrorOr<long> Process::sys_pipe(int fildes[2])
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
validate_pointer_access(fildes, sizeof(int) * 2);
|
TRY(validate_pointer_access(fildes, sizeof(int) * 2));
|
||||||
TRY(m_open_file_descriptors.pipe(fildes));
|
TRY(m_open_file_descriptors.pipe(fildes));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -954,7 +958,7 @@ namespace Kernel
|
||||||
BAN::ErrorOr<long> Process::sys_fstat(int fd, struct stat* buf)
|
BAN::ErrorOr<long> Process::sys_fstat(int fd, struct stat* buf)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
validate_pointer_access(buf, sizeof(struct stat));
|
TRY(validate_pointer_access(buf, sizeof(struct stat)));
|
||||||
TRY(m_open_file_descriptors.fstat(fd, buf));
|
TRY(m_open_file_descriptors.fstat(fd, buf));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -962,7 +966,7 @@ namespace Kernel
|
||||||
BAN::ErrorOr<long> Process::sys_fstatat(int fd, const char* path, struct stat* buf, int flag)
|
BAN::ErrorOr<long> Process::sys_fstatat(int fd, const char* path, struct stat* buf, int flag)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
validate_pointer_access(buf, sizeof(struct stat));
|
TRY(validate_pointer_access(buf, sizeof(struct stat)));
|
||||||
TRY(m_open_file_descriptors.fstatat(fd, path, buf, flag));
|
TRY(m_open_file_descriptors.fstatat(fd, path, buf, flag));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -970,7 +974,7 @@ namespace Kernel
|
||||||
BAN::ErrorOr<long> Process::sys_stat(const char* path, struct stat* buf, int flag)
|
BAN::ErrorOr<long> Process::sys_stat(const char* path, struct stat* buf, int flag)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
validate_pointer_access(buf, sizeof(struct stat));
|
TRY(validate_pointer_access(buf, sizeof(struct stat)));
|
||||||
TRY(m_open_file_descriptors.stat(TRY(absolute_path_of(path)), buf, flag));
|
TRY(m_open_file_descriptors.stat(TRY(absolute_path_of(path)), buf, flag));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1023,7 +1027,7 @@ namespace Kernel
|
||||||
BAN::ErrorOr<long> Process::sys_read_dir_entries(int fd, DirectoryEntryList* list, size_t list_size)
|
BAN::ErrorOr<long> Process::sys_read_dir_entries(int fd, DirectoryEntryList* list, size_t list_size)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
validate_pointer_access(list, list_size);
|
TRY(validate_pointer_access(list, list_size));
|
||||||
TRY(m_open_file_descriptors.read_dir_entries(fd, list, list_size));
|
TRY(m_open_file_descriptors.read_dir_entries(fd, list, list_size));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1034,7 +1038,7 @@ namespace Kernel
|
||||||
|
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
validate_string_access(path);
|
TRY(validate_string_access(path));
|
||||||
absolute_path = TRY(absolute_path_of(path));
|
absolute_path = TRY(absolute_path_of(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1052,7 +1056,7 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
validate_pointer_access(buffer, size);
|
TRY(validate_pointer_access(buffer, size));
|
||||||
|
|
||||||
if (size < m_working_directory.size() + 1)
|
if (size < m_working_directory.size() + 1)
|
||||||
return BAN::Error::from_errno(ERANGE);
|
return BAN::Error::from_errno(ERANGE);
|
||||||
|
@ -1067,7 +1071,7 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
validate_pointer_access(args, sizeof(sys_mmap_t));
|
TRY(validate_pointer_access(args, sizeof(sys_mmap_t)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args->prot != PROT_NONE && args->prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
|
if (args->prot != PROT_NONE && args->prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
|
||||||
|
@ -1208,7 +1212,7 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
validate_string_access(buffer);
|
TRY(validate_string_access(buffer));
|
||||||
|
|
||||||
auto& tty = m_controlling_terminal;
|
auto& tty = m_controlling_terminal;
|
||||||
|
|
||||||
|
@ -1228,7 +1232,7 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
validate_pointer_access(tp, sizeof(timespec));
|
TRY(validate_pointer_access(tp, sizeof(timespec)));
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (clock_id)
|
switch (clock_id)
|
||||||
|
@ -1256,7 +1260,7 @@ namespace Kernel
|
||||||
|
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
validate_pointer_access((void*)handler, sizeof(handler));
|
TRY(validate_pointer_access((void*)handler, sizeof(handler)));
|
||||||
}
|
}
|
||||||
|
|
||||||
CriticalScope _;
|
CriticalScope _;
|
||||||
|
@ -1641,14 +1645,14 @@ namespace Kernel
|
||||||
return absolute_path;
|
return absolute_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Process::validate_string_access(const char* str)
|
BAN::ErrorOr<void> Process::validate_string_access(const char* str)
|
||||||
{
|
{
|
||||||
// NOTE: we will page fault here, if str is not actually mapped
|
// NOTE: we will page fault here, if str is not actually mapped
|
||||||
// outcome is still the same; SIGSEGV
|
// outcome is still the same; SIGSEGV
|
||||||
validate_pointer_access(str, strlen(str) + 1);
|
return validate_pointer_access(str, strlen(str) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Process::validate_pointer_access(const void* ptr, size_t size)
|
BAN::ErrorOr<void> Process::validate_pointer_access(const void* ptr, size_t size)
|
||||||
{
|
{
|
||||||
ASSERT(&Process::current() == this);
|
ASSERT(&Process::current() == this);
|
||||||
auto& thread = Thread::current();
|
auto& thread = Thread::current();
|
||||||
|
@ -1664,24 +1668,25 @@ namespace Kernel
|
||||||
goto unauthorized_access;
|
goto unauthorized_access;
|
||||||
|
|
||||||
if (vaddr == 0)
|
if (vaddr == 0)
|
||||||
return;
|
return {};
|
||||||
|
|
||||||
if (vaddr >= thread.stack_base() && vaddr + size <= thread.stack_base() + thread.stack_size())
|
if (vaddr >= thread.stack_base() && vaddr + size <= thread.stack_base() + thread.stack_size())
|
||||||
return;
|
return {};
|
||||||
|
|
||||||
// FIXME: should we allow cross mapping access?
|
// FIXME: should we allow cross mapping access?
|
||||||
for (auto& mapped_region : m_mapped_regions)
|
for (auto& mapped_region : m_mapped_regions)
|
||||||
mapped_region->contains_fully(vaddr, size);
|
mapped_region->contains_fully(vaddr, size);
|
||||||
return;
|
return {};
|
||||||
|
|
||||||
// FIXME: elf should contain full range [vaddr, vaddr + size)
|
// FIXME: elf should contain full range [vaddr, vaddr + size)
|
||||||
if (m_loadable_elf->contains(vaddr))
|
if (m_loadable_elf->contains(vaddr))
|
||||||
return;
|
return {};
|
||||||
|
|
||||||
unauthorized_access:
|
unauthorized_access:
|
||||||
dwarnln("process {}, thread {} attempted to make an invalid pointer access", pid(), Thread::current().tid());
|
dwarnln("process {}, thread {} attempted to make an invalid pointer access", pid(), Thread::current().tid());
|
||||||
Debug::dump_stack_trace();
|
Debug::dump_stack_trace();
|
||||||
MUST(sys_kill(pid(), SIGSEGV));
|
MUST(sys_kill(pid(), SIGSEGV));
|
||||||
|
return BAN::Error::from_errno(EINTR);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -8,7 +8,7 @@
|
||||||
#include <kernel/FS/VirtualFileSystem.h>
|
#include <kernel/FS/VirtualFileSystem.h>
|
||||||
#include <kernel/GDT.h>
|
#include <kernel/GDT.h>
|
||||||
#include <kernel/IDT.h>
|
#include <kernel/IDT.h>
|
||||||
#include <kernel/Input/PS2Controller.h>
|
#include <kernel/Input/PS2/Controller.h>
|
||||||
#include <kernel/InterruptController.h>
|
#include <kernel/InterruptController.h>
|
||||||
#include <kernel/kprint.h>
|
#include <kernel/kprint.h>
|
||||||
#include <kernel/Memory/Heap.h>
|
#include <kernel/Memory/Heap.h>
|
||||||
|
|
Loading…
Reference in New Issue