125 lines
3.1 KiB
C
125 lines
3.1 KiB
C
#include "user/utsname.h"
|
|
#include "user/reboot.h"
|
|
#include "user/errno.h"
|
|
#include "user/time.h"
|
|
#include "sys/sys_sys.h"
|
|
#include "sys/block/blk.h"
|
|
#include "fs/node.h"
|
|
#include "sys/string.h"
|
|
#include "sys/assert.h"
|
|
#include "sys/thread.h"
|
|
#include "fs/vfs.h"
|
|
#include "sys/sched.h"
|
|
#include "sys/debug.h"
|
|
|
|
int sys_mount(const char *dev_name, const char *dir_name, const char *type, unsigned long flags, void *data) {
|
|
struct process *proc = thread_self->proc;
|
|
struct vnode *dev_node;
|
|
void *dev;
|
|
int res;
|
|
_assert(dir_name);
|
|
|
|
if (proc->ioctx.uid != 0) {
|
|
// Only root can do that
|
|
return -EACCES;
|
|
}
|
|
|
|
if (dev_name) {
|
|
if ((res = vfs_find(&proc->ioctx, proc->ioctx.cwd_vnode, dev_name, 0, &dev_node)) != 0) {
|
|
return res;
|
|
}
|
|
|
|
// Check that it's a block device:
|
|
if (dev_node->type != VN_BLK) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
dev = dev_node->dev;
|
|
} else {
|
|
dev = NULL;
|
|
}
|
|
|
|
return vfs_mount(&proc->ioctx, dir_name, dev, type, (uint32_t) flags, data);
|
|
}
|
|
|
|
int sys_umount(const char *dir_name) {
|
|
return vfs_umount(&thread_self->proc->ioctx, dir_name);
|
|
}
|
|
|
|
int sys_nanosleep(const struct timespec *req, struct timespec *rem) {
|
|
struct thread *thr = thread_self;
|
|
_assert(thr);
|
|
uint64_t deadline = req->tv_sec * 1000000000ULL + req->tv_nsec + system_time;
|
|
uint64_t int_time;
|
|
int ret = thread_sleep(thr, deadline, &int_time);
|
|
if (rem) {
|
|
if (ret) {
|
|
_assert(deadline > int_time);
|
|
uint64_t rem_time = deadline - int_time;
|
|
rem->tv_sec = rem_time / 1000000000ULL;
|
|
rem->tv_nsec = rem_time % 1000000000ULL;
|
|
} else {
|
|
rem->tv_sec = 0;
|
|
rem->tv_nsec = 0;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int sys_gettimeofday(struct timeval *tv, struct timezone *tz) {
|
|
if (tz) {
|
|
tz->tz_dsttime = 0;
|
|
tz->tz_minuteswest = 0;
|
|
}
|
|
|
|
uint64_t secs = system_time / 1000000000ULL + system_boot_time;
|
|
// System time is in nanos
|
|
tv->tv_usec = (system_time / 1000) % 1000000;
|
|
tv->tv_sec = secs;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sys_uname(struct utsname *name) {
|
|
if (!name) {
|
|
return -EFAULT;
|
|
}
|
|
|
|
strcpy(name->sysname, "yggdrasil");
|
|
// XXX: Hostname is not present in the kernel yet
|
|
strcpy(name->nodename, "nyan");
|
|
// XXX: No release numbers yet, only git version
|
|
strcpy(name->release, "X.Y");
|
|
strcpy(name->version, KERNEL_VERSION_STR);
|
|
// It's the only platform I'm developing the kernel for
|
|
strcpy(name->machine, "x86_64");
|
|
strcpy(name->domainname, "localhost");
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sys_reboot(int magic1, int magic2, unsigned int cmd, void *arg) {
|
|
if (thread_self->proc->ioctx.uid != 0) {
|
|
return -EACCES;
|
|
}
|
|
|
|
if (magic1 != (int) YGG_REBOOT_MAGIC1 || magic2 != (int) YGG_REBOOT_MAGIC2) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
switch (cmd) {
|
|
case YGG_REBOOT_RESTART:
|
|
case YGG_REBOOT_POWER_OFF:
|
|
case YGG_REBOOT_HALT:
|
|
sched_reboot(cmd);
|
|
return 0;
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
int sys_sync(void) {
|
|
blk_sync_all();
|
|
return 0;
|
|
}
|