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);
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);
int seek(long offset);

View File

@ -24,6 +24,7 @@ namespace VFS
typedef int (*node_block)(Node*);
typedef Node* (*node_readdir)(Node*, long);
typedef uintptr_t (*node_mmap)(Node*, uintptr_t, size_t, int, off_t);
typedef long (*node_ioctl)(Node*, int, uintptr_t);
struct Node
{
@ -47,6 +48,7 @@ namespace VFS
node_write write_func;
node_block block_func;
node_mmap mmap_func;
node_ioctl ioctl_func;
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);
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_setgid 25
#define SYS_umask 26
#define SYS_ioctl 27
struct stat;
struct pstat;
@ -68,3 +69,4 @@ void sys_dup2(Context* context, int fd, int fd2);
void sys_setuid(Context* context, int new_uid, int new_euid);
void sys_setgid(Context* context, int new_gid, int new_egid);
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);
}
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)
{
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;
dev->write_func = FramebufferDevice::write;
dev->mmap_func = FramebufferDevice::mmap;
dev->ioctl_func = FramebufferDevice::ioctl;
dev->inode = 0;
dev->length = 0;
dev->type = VFS_DEVICE;
@ -57,3 +58,17 @@ ssize_t FramebufferDevice::write(VFS::Node* node, size_t offset, size_t size, co
memcpy(fb + offset, buffer, 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_setgid: sys_setgid(context, (int)context->rdi, (int)context->rsi); 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;
}
VMM::exit_syscall_context();

View File

@ -358,12 +358,7 @@ void sys_dup2(Context* context, int fd, int fd2)
context->rax = -err;
return;
}
if (!file1->is_open())
{
context->rax = -EBADF;
return;
}
Descriptor* file2 = Scheduler::current_task()->descriptor_from_fd(fd2, err);
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.
if (!file2)
{
context->rax = -err;
@ -381,3 +376,16 @@ void sys_umask(Context* context, mode_t cmask)
context->rax = current_task->umask;
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_setgid 25
#define SYS_umask 26
#define SYS_ioctl 27
#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_write:
case SYS_read:
case SYS_ioctl:
case SYS_mprotect:
case SYS_waitpid: {
arg arg0 = va_arg(ap, arg);