Kernel, libc: Add ioctl()

Right now, only the framebuffer supports this system call, to query its dimensions.
This commit is contained in:
apio 2022-11-02 20:59:42 +01:00
parent feab66c0d3
commit 249c79f8a3
12 changed files with 87 additions and 7 deletions

View File

@ -34,6 +34,8 @@ struct Descriptor
uintptr_t mmap(uintptr_t addr, size_t size, int prot, off_t offset); uintptr_t mmap(uintptr_t addr, size_t size, int prot, off_t offset);
long ioctl(int cmd, uintptr_t arg);
void open(VFS::Node* node, bool can_read, bool can_write, bool able_to_block, bool close_on_exec); void open(VFS::Node* node, bool can_read, bool can_write, bool able_to_block, bool close_on_exec);
int seek(long offset); int seek(long offset);

View File

@ -24,6 +24,7 @@ namespace VFS
typedef int (*node_block)(Node*); typedef int (*node_block)(Node*);
typedef Node* (*node_readdir)(Node*, long); typedef Node* (*node_readdir)(Node*, long);
typedef uintptr_t (*node_mmap)(Node*, uintptr_t, size_t, int, off_t); typedef uintptr_t (*node_mmap)(Node*, uintptr_t, size_t, int, off_t);
typedef long (*node_ioctl)(Node*, int, uintptr_t);
struct Node struct Node
{ {
@ -47,6 +48,7 @@ namespace VFS
node_write write_func; node_write write_func;
node_block block_func; node_block block_func;
node_mmap mmap_func; node_mmap mmap_func;
node_ioctl ioctl_func;
Node* link; Node* link;
}; };

View File

@ -8,4 +8,6 @@ namespace FramebufferDevice
ssize_t write(VFS::Node* node, size_t offset, size_t size, const char* buffer); ssize_t write(VFS::Node* node, size_t offset, size_t size, const char* buffer);
uintptr_t mmap(VFS::Node* node, uintptr_t addr, size_t size, int prot, off_t offset); uintptr_t mmap(VFS::Node* node, uintptr_t addr, size_t size, int prot, off_t offset);
long ioctl(VFS::Node* node, int cmd, uintptr_t arg);
} }

View File

@ -30,6 +30,7 @@
#define SYS_setuid 24 #define SYS_setuid 24
#define SYS_setgid 25 #define SYS_setgid 25
#define SYS_umask 26 #define SYS_umask 26
#define SYS_ioctl 27
struct stat; struct stat;
struct pstat; struct pstat;
@ -67,4 +68,5 @@ void sys_stat(Context* context, const char* path, struct stat* buf);
void sys_dup2(Context* context, int fd, int fd2); void sys_dup2(Context* context, int fd, int fd2);
void sys_setuid(Context* context, int new_uid, int new_euid); void sys_setuid(Context* context, int new_uid, int new_euid);
void sys_setgid(Context* context, int new_gid, int new_egid); void sys_setgid(Context* context, int new_gid, int new_egid);
void sys_umask(Context* context, mode_t cmask); void sys_umask(Context* context, mode_t cmask);
void sys_ioctl(Context* context, int fd, int request, uintptr_t arg);

View File

@ -45,6 +45,12 @@ uintptr_t Descriptor::mmap(uintptr_t addr, size_t size, int prot, off_t offset)
return m_node->mmap_func(m_node, addr, size, prot, offset); return m_node->mmap_func(m_node, addr, size, prot, offset);
} }
long Descriptor::ioctl(int cmd, uintptr_t arg)
{
if(!m_node->ioctl_func) return MAP_FAIL(ENOTSUP);
return m_node->ioctl_func(m_node, cmd, arg);
}
int Descriptor::seek(long offset) int Descriptor::seek(long offset)
{ {
if (m_node->type == VFS_FILE && (uint64_t)offset > m_node->length) if (m_node->type == VFS_FILE && (uint64_t)offset > m_node->length)

View File

@ -20,6 +20,7 @@ VFS::Node* FramebufferDevice::create_new(const char* devname)
VFS::Node* dev = new VFS::Node; VFS::Node* dev = new VFS::Node;
dev->write_func = FramebufferDevice::write; dev->write_func = FramebufferDevice::write;
dev->mmap_func = FramebufferDevice::mmap; dev->mmap_func = FramebufferDevice::mmap;
dev->ioctl_func = FramebufferDevice::ioctl;
dev->inode = 0; dev->inode = 0;
dev->length = 0; dev->length = 0;
dev->type = VFS_DEVICE; dev->type = VFS_DEVICE;
@ -56,4 +57,18 @@ ssize_t FramebufferDevice::write(VFS::Node* node, size_t offset, size_t size, co
} }
memcpy(fb + offset, buffer, size); memcpy(fb + offset, buffer, size);
return (ssize_t)size; return (ssize_t)size;
}
#define FB_GET_WIDTH 0
#define FB_GET_HEIGHT 1
long FramebufferDevice::ioctl(VFS::Node* node, int cmd, uintptr_t)
{
if (!node) return -1;
switch(cmd)
{
case FB_GET_WIDTH: return (long)bootboot.fb_width;
case FB_GET_HEIGHT: return (long)bootboot.fb_height;
default: return -EINVAL;
}
} }

View File

@ -40,6 +40,7 @@ void Syscall::entry(Context* context)
case SYS_setuid: sys_setuid(context, (int)context->rdi, (int)context->rsi); break; case SYS_setuid: sys_setuid(context, (int)context->rdi, (int)context->rsi); break;
case SYS_setgid: sys_setgid(context, (int)context->rdi, (int)context->rsi); break; case SYS_setgid: sys_setgid(context, (int)context->rdi, (int)context->rsi); break;
case SYS_umask: sys_umask(context, (mode_t)context->rdi); break; case SYS_umask: sys_umask(context, (mode_t)context->rdi); break;
case SYS_ioctl: sys_ioctl(context, (int)context->rdi, (int)context->rsi, (uintptr_t)context->rdx); break;
default: context->rax = -ENOSYS; break; default: context->rax = -ENOSYS; break;
} }
VMM::exit_syscall_context(); VMM::exit_syscall_context();

View File

@ -358,12 +358,7 @@ void sys_dup2(Context* context, int fd, int fd2)
context->rax = -err; context->rax = -err;
return; return;
} }
if (!file1->is_open()) Descriptor* file2 = Scheduler::current_task()->descriptor_from_fd(fd2, err); // FIXME: This will return EBADF if fd2 is not open, but we want to replace it with fd1 if it is not open.
{
context->rax = -EBADF;
return;
}
Descriptor* file2 = Scheduler::current_task()->descriptor_from_fd(fd2, err);
if (!file2) if (!file2)
{ {
context->rax = -err; context->rax = -err;
@ -380,4 +375,17 @@ void sys_umask(Context* context, mode_t cmask)
Task* current_task = Scheduler::current_task(); Task* current_task = Scheduler::current_task();
context->rax = current_task->umask; context->rax = current_task->umask;
current_task->umask = cmask; current_task->umask = cmask;
}
void sys_ioctl(Context* context, int fd, int cmd, uintptr_t arg)
{
int err;
Descriptor* file = Scheduler::current_task()->descriptor_from_fd(fd, err);
if (!file)
{
context->rax = -err;
return;
}
kinfoln("ioctl(): fd %d, cmd %d, arg %lu", fd, cmd, arg);
context->rax = file->ioctl(cmd, arg);
} }

View File

@ -0,0 +1,23 @@
#ifndef _SYS_IOCTL_H
#define _SYS_IOCTL_H
#include <sys/types.h>
/* Get the width of a framebuffer device. */
#define FB_GET_WIDTH 0
/* Get the height of a framebuffer device. */
#define FB_GET_HEIGHT 1
#ifdef __cplusplus
extern "C"
{
#endif
/* Perform an arbitrary operation on an open file descriptor. Many operations are device-specific. */
int ioctl(int fd, int cmd, ...);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -28,5 +28,6 @@
#define SYS_setuid 24 #define SYS_setuid 24
#define SYS_setgid 25 #define SYS_setgid 25
#define SYS_umask 26 #define SYS_umask 26
#define SYS_ioctl 27
#endif #endif

View File

@ -0,0 +1,17 @@
#include <luna/syscall.h>
#include <sys/ioctl.h>
#include <sys/syscall.h>
#include <stdarg.h>
#include <stdint.h>
extern "C"
{
int ioctl(int fd, int cmd, ...)
{
va_list ap;
va_start(ap, cmd);
long result = __lc_fast_syscall3(SYS_ioctl, fd, cmd, va_arg(ap, uintptr_t));
va_end(ap);
return (int)result;
}
}

View File

@ -41,6 +41,7 @@ extern "C" long syscall(long number, ...)
case SYS_seek: case SYS_seek:
case SYS_write: case SYS_write:
case SYS_read: case SYS_read:
case SYS_ioctl:
case SYS_mprotect: case SYS_mprotect:
case SYS_waitpid: { case SYS_waitpid: {
arg arg0 = va_arg(ap, arg); arg arg0 = va_arg(ap, arg);