2011-12-11 03:34:10 +04:00
|
|
|
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
|
|
|
*
|
|
|
|
* Syscall Tables
|
|
|
|
*
|
2011-03-30 06:08:56 +04:00
|
|
|
*/
|
|
|
|
#include <system.h>
|
2011-12-09 01:25:48 +04:00
|
|
|
#include <process.h>
|
2011-12-15 05:06:11 +04:00
|
|
|
#include <logging.h>
|
2012-01-25 04:40:25 +04:00
|
|
|
#include <fs.h>
|
|
|
|
#include <pipe.h>
|
2012-01-27 08:46:18 +04:00
|
|
|
#include <version.h>
|
2012-02-06 04:12:50 +04:00
|
|
|
#include <shm.h>
|
2011-03-30 06:08:56 +04:00
|
|
|
|
2011-04-25 06:09:36 +04:00
|
|
|
#define SPECIAL_CASE_STDIO
|
2011-04-12 01:45:15 +04:00
|
|
|
|
2012-10-15 06:53:16 +04:00
|
|
|
#define RESERVED 1
|
|
|
|
|
2011-04-12 01:45:15 +04:00
|
|
|
/*
|
|
|
|
* System calls themselves
|
|
|
|
*/
|
|
|
|
|
2011-04-18 02:44:29 +04:00
|
|
|
void validate(void * ptr) {
|
2011-12-09 01:25:48 +04:00
|
|
|
if (ptr && (uintptr_t)ptr < current_process->image.entry) {
|
2012-09-04 09:35:11 +04:00
|
|
|
debug_print(ERROR, "SEGFAULT: Invalid pointer passed to syscall. (0x%x < 0x%x)", (uintptr_t)ptr, current_process->image.entry);
|
2011-04-18 02:44:29 +04:00
|
|
|
HALT_AND_CATCH_FIRE("Segmentation fault", NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-04-12 01:45:15 +04:00
|
|
|
/*
|
2012-01-25 10:19:52 +04:00
|
|
|
* print something to the debug terminal (serial)
|
2011-04-12 01:45:15 +04:00
|
|
|
*/
|
2011-03-30 06:08:56 +04:00
|
|
|
static int print(char * s) {
|
2011-04-18 02:44:29 +04:00
|
|
|
validate((void *)s);
|
2012-11-29 11:05:19 +04:00
|
|
|
kprintf("%s", s);
|
2011-04-09 00:27:12 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-04-12 01:45:15 +04:00
|
|
|
/*
|
|
|
|
* Exit the current task.
|
|
|
|
* DOES NOT RETURN!
|
|
|
|
*/
|
2011-04-09 00:27:12 +04:00
|
|
|
static int exit(int retval) {
|
|
|
|
/* Deschedule the current task */
|
2011-04-09 01:26:34 +04:00
|
|
|
task_exit(retval);
|
2011-04-09 00:27:12 +04:00
|
|
|
while (1) { };
|
|
|
|
return retval;
|
2011-03-30 06:08:56 +04:00
|
|
|
}
|
|
|
|
|
2011-04-17 05:01:04 +04:00
|
|
|
static int read(int fd, char * ptr, int len) {
|
2012-02-17 00:31:40 +04:00
|
|
|
if (fd >= (int)current_process->fds->length || fd < 0) {
|
2011-04-17 05:01:04 +04:00
|
|
|
return -1;
|
|
|
|
}
|
2012-02-17 00:31:40 +04:00
|
|
|
if (current_process->fds->entries[fd] == NULL) {
|
2012-01-25 10:19:52 +04:00
|
|
|
return -1;
|
|
|
|
}
|
2011-04-18 02:44:29 +04:00
|
|
|
validate(ptr);
|
2012-02-17 00:31:40 +04:00
|
|
|
fs_node_t * node = current_process->fds->entries[fd];
|
2011-04-17 05:01:04 +04:00
|
|
|
uint32_t out = read_fs(node, node->offset, len, (uint8_t *)ptr);
|
|
|
|
node->offset += out;
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2012-01-27 05:12:10 +04:00
|
|
|
static int readdir(int fd, int index, struct dirent * entry) {
|
2012-02-17 00:31:40 +04:00
|
|
|
if (fd >= (int)current_process->fds->length || fd < 0) {
|
2012-01-27 05:12:10 +04:00
|
|
|
return -1;
|
|
|
|
}
|
2012-02-17 00:31:40 +04:00
|
|
|
if (current_process->fds->entries[fd] == NULL) {
|
2012-01-27 05:12:10 +04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
validate(entry);
|
2012-02-17 00:31:40 +04:00
|
|
|
fs_node_t * node = current_process->fds->entries[fd];
|
2012-01-27 05:12:10 +04:00
|
|
|
|
|
|
|
struct dirent * kentry = readdir_fs(node, (uint32_t)index);
|
|
|
|
if (!kentry) {
|
|
|
|
free(kentry);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(entry, kentry, sizeof(struct dirent));
|
|
|
|
free(kentry);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-04-17 05:01:04 +04:00
|
|
|
static int write(int fd, char * ptr, int len) {
|
2012-02-17 00:31:40 +04:00
|
|
|
if ((fd == 1 && !current_process->fds->entries[fd]) ||
|
|
|
|
(fd == 2 && !current_process->fds->entries[fd])) {
|
2012-02-13 02:45:23 +04:00
|
|
|
for (uint32_t i = 0; i < (uint32_t)len; ++i) {
|
2012-11-29 11:05:19 +04:00
|
|
|
kprintf("%c", ptr[i]);
|
2012-02-13 02:45:23 +04:00
|
|
|
}
|
2011-04-25 06:09:36 +04:00
|
|
|
return len;
|
|
|
|
}
|
2012-02-17 00:31:40 +04:00
|
|
|
if (fd >= (int)current_process->fds->length || fd < 0) {
|
2011-04-17 05:01:04 +04:00
|
|
|
return -1;
|
|
|
|
}
|
2012-02-17 00:31:40 +04:00
|
|
|
if (current_process->fds->entries[fd] == NULL) {
|
2012-01-25 10:19:52 +04:00
|
|
|
return -1;
|
|
|
|
}
|
2011-04-18 02:44:29 +04:00
|
|
|
validate(ptr);
|
2012-02-17 00:31:40 +04:00
|
|
|
fs_node_t * node = current_process->fds->entries[fd];
|
2011-04-17 05:01:04 +04:00
|
|
|
uint32_t out = write_fs(node, node->offset, len, (uint8_t *)ptr);
|
|
|
|
node->offset += out;
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2011-12-16 01:31:18 +04:00
|
|
|
static int wait(int child) {
|
|
|
|
if (child < 1) {
|
2012-09-04 09:35:11 +04:00
|
|
|
debug_print(WARNING, "Process %d requested group wait, which we can not do!", getpid());
|
2011-12-16 01:31:18 +04:00
|
|
|
return 0;
|
|
|
|
}
|
2011-12-09 01:25:48 +04:00
|
|
|
process_t * volatile child_task = process_from_pid(child);
|
2011-12-07 06:13:20 +04:00
|
|
|
/* If the child task doesn't exist, bail */
|
2012-01-25 10:19:52 +04:00
|
|
|
if (!child_task) {
|
2012-09-04 09:35:11 +04:00
|
|
|
debug_print(WARNING, "Tried to wait for non-existent process");
|
2012-03-11 01:03:59 +04:00
|
|
|
return -1;
|
2012-01-25 10:19:52 +04:00
|
|
|
}
|
2011-12-07 06:13:20 +04:00
|
|
|
while (child_task->finished == 0) {
|
2012-02-01 05:27:38 +04:00
|
|
|
/* Add us to the wait queue for this child */
|
|
|
|
sleep_on(child_task->wait_queue);
|
2011-12-07 06:13:20 +04:00
|
|
|
}
|
|
|
|
/* Grab the child's return value */
|
2011-12-16 03:21:28 +04:00
|
|
|
int ret = child_task->status;
|
2011-12-16 07:08:48 +04:00
|
|
|
delete_process(child_task);
|
2011-12-16 03:21:28 +04:00
|
|
|
return ret;
|
2011-12-07 06:13:20 +04:00
|
|
|
}
|
|
|
|
|
2011-04-17 05:01:04 +04:00
|
|
|
static int open(const char * file, int flags, int mode) {
|
2011-04-18 02:44:29 +04:00
|
|
|
validate((void *)file);
|
2011-12-09 01:25:48 +04:00
|
|
|
fs_node_t * node = kopen((char *)file, 0);
|
2012-02-06 02:04:41 +04:00
|
|
|
if (!node && (flags & 0x600)) {
|
2012-01-31 10:16:09 +04:00
|
|
|
/* Um, make one */
|
2012-02-06 02:04:41 +04:00
|
|
|
if (!create_file_fs((char *)file, 0777)) {
|
2012-09-04 09:35:11 +04:00
|
|
|
debug_print(NOTICE, "[creat] Creating file!");
|
2012-02-06 02:04:41 +04:00
|
|
|
node = kopen((char *)file, 0);
|
|
|
|
}
|
2012-01-31 10:16:09 +04:00
|
|
|
}
|
2011-04-17 05:01:04 +04:00
|
|
|
if (!node) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
node->offset = 0;
|
2012-05-17 04:51:37 +04:00
|
|
|
int fd = process_append_fd((process_t *)current_process, node);
|
2012-09-04 09:35:11 +04:00
|
|
|
debug_print(INFO, "[open] pid=%d %s -> %d", getpid(), file, fd);
|
2012-05-17 04:51:37 +04:00
|
|
|
return fd;
|
2011-04-17 05:01:04 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static int close(int fd) {
|
2012-02-17 00:31:40 +04:00
|
|
|
if (fd >= (int)current_process->fds->length || fd < 0) {
|
2011-04-17 05:01:04 +04:00
|
|
|
return -1;
|
|
|
|
}
|
2012-02-17 00:31:40 +04:00
|
|
|
close_fs(current_process->fds->entries[fd]);
|
2011-04-17 05:01:04 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-04-18 03:28:40 +04:00
|
|
|
static int sys_sbrk(int size) {
|
2011-12-09 01:25:48 +04:00
|
|
|
uintptr_t ret = current_process->image.heap;
|
2012-01-19 06:12:04 +04:00
|
|
|
uintptr_t i_ret = ret;
|
|
|
|
while (ret % 0x1000) {
|
|
|
|
ret++;
|
|
|
|
}
|
|
|
|
current_process->image.heap += (ret - i_ret) + size;
|
2011-12-09 01:25:48 +04:00
|
|
|
while (current_process->image.heap > current_process->image.heap_actual) {
|
|
|
|
current_process->image.heap_actual += 0x1000;
|
2012-01-19 06:12:04 +04:00
|
|
|
assert(current_process->image.heap_actual % 0x1000 == 0);
|
2011-12-09 01:25:48 +04:00
|
|
|
alloc_frame(get_page(current_process->image.heap_actual, 1, current_directory), 0, 1);
|
2011-04-18 03:28:40 +04:00
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-02-16 08:56:16 +04:00
|
|
|
static int sys_getpid() {
|
|
|
|
/* The user actually wants the pid of the originating thread (which can be us). */
|
2012-02-16 11:06:44 +04:00
|
|
|
if (current_process->group) {
|
|
|
|
return current_process->group;
|
|
|
|
} else {
|
|
|
|
/* We are the leader */
|
|
|
|
return current_process->id;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Actual getpid() */
|
|
|
|
static int gettid() {
|
|
|
|
return getpid();
|
2012-02-16 08:56:16 +04:00
|
|
|
}
|
|
|
|
|
2011-04-17 22:26:31 +04:00
|
|
|
static int execve(const char * filename, char *const argv[], char *const envp[]) {
|
2011-04-18 02:44:29 +04:00
|
|
|
validate((void *)argv);
|
|
|
|
validate((void *)filename);
|
|
|
|
validate((void *)envp);
|
2012-10-08 07:46:35 +04:00
|
|
|
int argc = 0, envc = 0;
|
|
|
|
while (argv[argc]) { ++argc; }
|
|
|
|
if (envp) {
|
|
|
|
while (envp[envc]) { ++envc; }
|
2011-04-17 22:26:31 +04:00
|
|
|
}
|
2012-09-04 09:35:11 +04:00
|
|
|
debug_print(INFO, "Allocating space for arguments...");
|
2012-10-08 07:46:35 +04:00
|
|
|
char ** argv_ = malloc(sizeof(char *) * argc);
|
|
|
|
for (int j = 0; j < argc; ++j) {
|
2011-04-18 02:44:29 +04:00
|
|
|
argv_[j] = malloc((strlen(argv[j]) + 1) * sizeof(char));
|
|
|
|
memcpy(argv_[j], argv[j], strlen(argv[j]) + 1);
|
|
|
|
}
|
2012-10-08 07:46:35 +04:00
|
|
|
char ** envp_;
|
|
|
|
if (envp && envc) {
|
|
|
|
envp_ = malloc(sizeof(char *) * (envc + 1));
|
|
|
|
for (int j = 0; j < envc; ++j) {
|
|
|
|
envp_[j] = malloc((strlen(envp[j]) + 1) * sizeof(char));
|
|
|
|
memcpy(envp_[j], envp[j], strlen(envp[j]) + 1);
|
|
|
|
}
|
|
|
|
envp_[envc] = 0;
|
|
|
|
} else {
|
|
|
|
envp_ = malloc(sizeof(char *));
|
|
|
|
envp_[0] = NULL;
|
|
|
|
}
|
2012-09-04 09:35:11 +04:00
|
|
|
debug_print(INFO,"Releasing all shmem regions...");
|
2012-02-09 02:00:51 +04:00
|
|
|
shm_release_all((process_t *)current_process);
|
|
|
|
|
2012-09-04 09:35:11 +04:00
|
|
|
debug_print(INFO,"Executing...");
|
2011-04-17 22:26:31 +04:00
|
|
|
/* Discard envp */
|
2012-10-08 07:46:35 +04:00
|
|
|
exec((char *)filename, argc, (char **)argv_, (char **)envp_);
|
2011-04-17 22:26:31 +04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2011-04-30 04:54:07 +04:00
|
|
|
static int getgraphicsaddress() {
|
2012-09-18 09:46:43 +04:00
|
|
|
return (int)lfb_get_address();
|
2011-04-30 04:54:07 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static int seek(int fd, int offset, int whence) {
|
2012-02-17 00:31:40 +04:00
|
|
|
if (fd >= (int)current_process->fds->length || fd < 0) {
|
2011-04-30 04:54:07 +04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (fd < 3) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (whence == 0) {
|
2012-02-17 00:31:40 +04:00
|
|
|
current_process->fds->entries[fd]->offset = offset;
|
2011-04-30 04:54:07 +04:00
|
|
|
} else if (whence == 1) {
|
2012-02-17 00:31:40 +04:00
|
|
|
current_process->fds->entries[fd]->offset += offset;
|
2011-04-30 04:54:07 +04:00
|
|
|
} else if (whence == 2) {
|
2012-02-17 00:31:40 +04:00
|
|
|
current_process->fds->entries[fd]->offset = current_process->fds->entries[fd]->length + offset;
|
2011-04-30 04:54:07 +04:00
|
|
|
}
|
2012-02-17 00:31:40 +04:00
|
|
|
return current_process->fds->entries[fd]->offset;
|
2011-04-30 04:54:07 +04:00
|
|
|
}
|
|
|
|
|
2012-01-27 13:12:29 +04:00
|
|
|
static int stat(int fd, uint32_t st) {
|
2012-02-17 00:31:40 +04:00
|
|
|
if (fd >= (int)current_process->fds->length || fd < 0) {
|
2012-01-27 13:12:29 +04:00
|
|
|
return -1;
|
|
|
|
}
|
2012-02-17 00:31:40 +04:00
|
|
|
fs_node_t * fn = current_process->fds->entries[fd];
|
2012-01-27 13:12:29 +04:00
|
|
|
struct stat * f = (struct stat *)st;
|
|
|
|
f->st_dev = 0;
|
|
|
|
f->st_ino = fn->inode;
|
|
|
|
|
|
|
|
uint32_t flags = 0;
|
|
|
|
if (fn->flags & FS_FILE) { flags |= _IFREG; }
|
|
|
|
if (fn->flags & FS_DIRECTORY) { flags |= _IFDIR; }
|
|
|
|
if (fn->flags & FS_CHARDEVICE) { flags |= _IFCHR; }
|
|
|
|
if (fn->flags & FS_BLOCKDEVICE) { flags |= _IFBLK; }
|
|
|
|
if (fn->flags & FS_PIPE) { flags |= _IFIFO; }
|
|
|
|
if (fn->flags & FS_SYMLINK) { flags |= _IFLNK; }
|
|
|
|
|
|
|
|
f->st_mode = fn->mask | flags;
|
|
|
|
f->st_nlink = 0;
|
|
|
|
f->st_uid = fn->uid;
|
|
|
|
f->st_gid = fn->gid;
|
|
|
|
f->st_rdev = 0;
|
|
|
|
f->st_size = fn->length;
|
|
|
|
|
2012-01-31 10:16:09 +04:00
|
|
|
if (fn->flags & FS_PIPE) {
|
|
|
|
/* Pipes have dynamic sizes */
|
|
|
|
f->st_size = pipe_size(fn);
|
|
|
|
}
|
|
|
|
|
2011-04-30 04:54:07 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-04-30 06:41:29 +04:00
|
|
|
static int setgraphicsoffset(int rows) {
|
|
|
|
bochs_set_y_offset(rows);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-12-16 23:16:20 +04:00
|
|
|
static int getgraphicswidth() {
|
2012-09-18 09:46:43 +04:00
|
|
|
return lfb_resolution_x;
|
2011-12-16 23:16:20 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static int getgraphicsheight() {
|
2012-09-18 09:46:43 +04:00
|
|
|
return lfb_resolution_y;
|
2011-12-16 23:16:20 +04:00
|
|
|
}
|
|
|
|
|
VESA mode switching support.
BIOS execution is provided through the `v8086` module, which provides
software emulation of an 8086 processor. It is not currently working
with some BIOSes and may (read: probably will be) replaced with another
emulator (x86emu comes to mind) at some point in the near future. In the
meantime, the default video mode for QEMU works with this and it's
enough to get us on real VESA instead of fake VBE. The `bochs` module
will be renamed in a future commit. Userspace programs have been
adjusted to work at bitrates other than 32 *POORLY*. If you write pixels
left-to-right, they should work fine. They only work with 24-bpp
otherwise, and then you need to be careful of what pixels you are
writing when, or you will overwrite things in other pixels.
You may pass a commandline argument like the following to set display
modes:
vid=vesa,1024,768
Or for stranger modes under QEMU or Bochs, use the bochs VBE
initializer:
vid=bochs,1280,720
Note that the address of the linear framebuffer is still found via
hackish probing instead of PCI or trusting the VBE information, so if
you have things in the wrong memory ranges (0xE0000000+), be prepared to
have them get read.
Once again, this entire commit is a massive hack. I am happy that it
worked, and I will continue to make it less hacky, but in the meantime,
this is what we've got.
Happy holidays.
2011-12-25 10:40:40 +04:00
|
|
|
static int getgraphicsdepth() {
|
2012-09-18 09:46:43 +04:00
|
|
|
return lfb_resolution_b;
|
VESA mode switching support.
BIOS execution is provided through the `v8086` module, which provides
software emulation of an 8086 processor. It is not currently working
with some BIOSes and may (read: probably will be) replaced with another
emulator (x86emu comes to mind) at some point in the near future. In the
meantime, the default video mode for QEMU works with this and it's
enough to get us on real VESA instead of fake VBE. The `bochs` module
will be renamed in a future commit. Userspace programs have been
adjusted to work at bitrates other than 32 *POORLY*. If you write pixels
left-to-right, they should work fine. They only work with 24-bpp
otherwise, and then you need to be careful of what pixels you are
writing when, or you will overwrite things in other pixels.
You may pass a commandline argument like the following to set display
modes:
vid=vesa,1024,768
Or for stranger modes under QEMU or Bochs, use the bochs VBE
initializer:
vid=bochs,1280,720
Note that the address of the linear framebuffer is still found via
hackish probing instead of PCI or trusting the VBE information, so if
you have things in the wrong memory ranges (0xE0000000+), be prepared to
have them get read.
Once again, this entire commit is a massive hack. I am happy that it
worked, and I will continue to make it less hacky, but in the meantime,
this is what we've got.
Happy holidays.
2011-12-25 10:40:40 +04:00
|
|
|
}
|
|
|
|
|
2012-01-25 04:40:25 +04:00
|
|
|
static int mkpipe() {
|
2012-01-25 10:19:52 +04:00
|
|
|
fs_node_t * node = make_pipe(4096 * 2);
|
2012-01-25 04:40:25 +04:00
|
|
|
return process_append_fd((process_t *)current_process, node);
|
|
|
|
}
|
|
|
|
|
2012-01-25 05:06:07 +04:00
|
|
|
static int dup2(int old, int new) {
|
|
|
|
process_move_fd((process_t *)current_process, old, new);
|
|
|
|
return new;
|
|
|
|
}
|
|
|
|
|
2012-01-27 08:46:18 +04:00
|
|
|
static int getuid() {
|
|
|
|
return current_process->user;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int setuid(user_t new_uid) {
|
2012-01-27 09:11:43 +04:00
|
|
|
if (current_process->user == USER_ROOT_UID) {
|
2012-01-27 08:46:18 +04:00
|
|
|
current_process->user = new_uid;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int kernel_name_XXX(char * buffer) {
|
|
|
|
char version_number[1024];
|
|
|
|
sprintf(version_number, __kernel_version_format,
|
|
|
|
__kernel_version_major,
|
|
|
|
__kernel_version_minor,
|
|
|
|
__kernel_version_lower,
|
|
|
|
__kernel_version_suffix);
|
|
|
|
return sprintf(buffer, "%s %s %s %s %s %s",
|
|
|
|
__kernel_name,
|
|
|
|
version_number,
|
|
|
|
__kernel_version_codename,
|
|
|
|
__kernel_build_date,
|
|
|
|
__kernel_build_time,
|
|
|
|
__kernel_arch);
|
|
|
|
}
|
|
|
|
|
2012-02-08 12:40:44 +04:00
|
|
|
static int send_signal(pid_t process, uint32_t signal) {
|
|
|
|
process_t * receiver = process_from_pid(process);
|
|
|
|
|
|
|
|
if (!receiver) {
|
|
|
|
/* Invalid pid */
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (receiver->user != current_process->user && current_process->user != USER_ROOT_UID) {
|
|
|
|
/* No way in hell. */
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2012-02-13 04:47:01 +04:00
|
|
|
if (signal > NUMSIGNALS) {
|
2012-02-08 12:40:44 +04:00
|
|
|
/* Invalid signal */
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (receiver->finished) {
|
|
|
|
/* Can't send signals to finished processes */
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Append signal to list */
|
|
|
|
signal_t * sig = malloc(sizeof(signal_t));
|
|
|
|
sig->handler = (uintptr_t)receiver->signals.functions[signal];
|
|
|
|
sig->signum = signal;
|
|
|
|
memset(&sig->registers_before, 0x00, sizeof(regs_t));
|
|
|
|
|
2012-12-01 06:26:47 +04:00
|
|
|
if (!process_is_ready(receiver)) {
|
2012-02-08 12:40:44 +04:00
|
|
|
make_process_ready(receiver);
|
|
|
|
}
|
|
|
|
|
|
|
|
list_insert(receiver->signal_queue, sig);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static uintptr_t sys_signal(uint32_t signum, uintptr_t handler) {
|
2012-02-13 04:47:01 +04:00
|
|
|
if (signum > NUMSIGNALS) {
|
2012-02-08 12:40:44 +04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
uintptr_t old = current_process->signals.functions[signum];
|
|
|
|
current_process->signals.functions[signum] = handler;
|
|
|
|
return old;
|
|
|
|
}
|
|
|
|
|
2012-02-06 00:16:59 +04:00
|
|
|
/*
|
|
|
|
static void inspect_memory (uintptr_t vaddr) {
|
|
|
|
// Please use this scary hack of a function as infrequently as possible.
|
|
|
|
shmem_debug_frame(vaddr);
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
2012-09-29 11:38:45 +04:00
|
|
|
extern void ext2_disk_sync();
|
|
|
|
|
2012-01-27 09:11:43 +04:00
|
|
|
static int reboot() {
|
2012-09-04 09:35:11 +04:00
|
|
|
debug_print(NOTICE, "[kernel] Reboot requested from process %d by user #%d", current_process->id, current_process->user);
|
2012-02-08 12:40:44 +04:00
|
|
|
if (current_process->user != USER_ROOT_UID) {
|
2012-01-27 09:11:43 +04:00
|
|
|
return -1;
|
|
|
|
} else {
|
2012-09-04 09:35:11 +04:00
|
|
|
debug_print(NOTICE, "[kernel] Good bye!");
|
2012-09-29 11:38:45 +04:00
|
|
|
ext2_disk_sync();
|
2012-01-27 09:11:43 +04:00
|
|
|
/* Goodbye, cruel world */
|
2012-09-29 11:38:45 +04:00
|
|
|
IRQ_OFF;
|
2012-01-27 09:11:43 +04:00
|
|
|
uint8_t out = 0x02;
|
|
|
|
while ((out & 0x02) != 0) {
|
|
|
|
out = inportb(0x64);
|
|
|
|
}
|
|
|
|
outportb(0x64, 0xFE); /* Reset */
|
|
|
|
STOP;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-01-27 23:10:58 +04:00
|
|
|
static int chdir(char * newdir) {
|
|
|
|
char * path = canonicalize_path(current_process->wd_name, newdir);
|
|
|
|
fs_node_t * chd = kopen(path, 0);
|
|
|
|
if (chd) {
|
|
|
|
if ((chd->flags & FS_DIRECTORY) == 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
free(current_process->wd_name);
|
|
|
|
current_process->wd_name = malloc(strlen(path) + 1);
|
|
|
|
memcpy(current_process->wd_name, path, strlen(path) + 1);
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static char * getcwd(char * buf, size_t size) {
|
|
|
|
if (!buf) return NULL;
|
|
|
|
validate((void *)buf);
|
|
|
|
memcpy(buf, current_process->wd_name, min(size, strlen(current_process->wd_name) + 1));
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
2012-01-30 22:10:53 +04:00
|
|
|
static char hostname[256];
|
|
|
|
static size_t hostname_len = 0;
|
|
|
|
|
|
|
|
static int sethostname(char * new_hostname) {
|
|
|
|
if (current_process->user == USER_ROOT_UID) {
|
|
|
|
size_t len = strlen(new_hostname) + 1;
|
|
|
|
if (len > 256) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
hostname_len = len;
|
|
|
|
memcpy(hostname, new_hostname, hostname_len);
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int gethostname(char * buffer) {
|
|
|
|
memcpy(buffer, hostname, hostname_len);
|
|
|
|
return hostname_len;
|
|
|
|
}
|
|
|
|
|
2012-02-03 02:16:29 +04:00
|
|
|
static int mousedevice() {
|
|
|
|
extern fs_node_t * mouse_pipe;
|
|
|
|
return process_append_fd((process_t *)current_process, mouse_pipe);
|
|
|
|
}
|
|
|
|
|
2012-11-29 11:05:19 +04:00
|
|
|
static int open_serial(int device) {
|
|
|
|
return process_append_fd((process_t *)current_process, serial_device_create(device));
|
|
|
|
}
|
|
|
|
|
2012-02-06 02:04:41 +04:00
|
|
|
extern int mkdir_fs(char *name, uint16_t permission);
|
|
|
|
|
|
|
|
static int sys_mkdir(char * path, uint32_t mode) {
|
|
|
|
return mkdir_fs(path, 0777);
|
|
|
|
}
|
|
|
|
|
2012-02-09 06:59:34 +04:00
|
|
|
/**
|
|
|
|
* share_fd: Make a file descriptor available to another process.
|
|
|
|
*/
|
|
|
|
static uintptr_t share_fd(int fd, int pid) {
|
2012-02-17 00:31:40 +04:00
|
|
|
if (fd >= (int)current_process->fds->length || fd < 0) {
|
2012-02-09 06:59:34 +04:00
|
|
|
return 0;
|
|
|
|
}
|
2012-02-17 00:31:40 +04:00
|
|
|
fs_node_t * fn = current_process->fds->entries[fd];
|
2012-02-09 06:59:34 +04:00
|
|
|
fn->shared_with = pid;
|
|
|
|
return (uintptr_t)fn;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* get_fd: Retreive a file descriptor (by key == pointer to fs_node_t) from
|
|
|
|
* another proces.
|
|
|
|
*/
|
|
|
|
static int get_fd(uintptr_t fn) {
|
2012-02-13 04:47:01 +04:00
|
|
|
fs_node_t * node = (fs_node_t *)fn;
|
2012-02-17 00:31:40 +04:00
|
|
|
if (node->shared_with == current_process->id || node->shared_with == current_process->group) {
|
2012-02-09 06:59:34 +04:00
|
|
|
return process_append_fd((process_t *)current_process, node);
|
|
|
|
} else {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-02 07:13:52 +04:00
|
|
|
/*
|
|
|
|
* Yield the rest of the quantum;
|
|
|
|
* useful for busy waiting and other such things
|
|
|
|
*/
|
|
|
|
static int yield() {
|
|
|
|
switch_task(1);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2012-05-17 04:51:37 +04:00
|
|
|
/*
|
|
|
|
* System Function
|
|
|
|
*/
|
2012-09-04 09:35:11 +04:00
|
|
|
static int system_function(int fn, char ** args) {
|
2012-05-17 04:51:37 +04:00
|
|
|
/* System Functions are special debugging system calls */
|
|
|
|
if (current_process->user == USER_ROOT_UID) {
|
|
|
|
switch (fn) {
|
|
|
|
case 1:
|
|
|
|
/* Print memory information */
|
|
|
|
/* Future: /proc/meminfo */
|
|
|
|
kprintf("Memory used: %d\n", memory_use());
|
|
|
|
kprintf("Memory available: %d\n", memory_total());
|
|
|
|
return 0;
|
|
|
|
case 2:
|
|
|
|
/* Print process tree */
|
|
|
|
/* Future: /proc in general */
|
|
|
|
debug_print_process_tree();
|
|
|
|
return 0;
|
2012-05-31 15:52:47 +04:00
|
|
|
case 3:
|
|
|
|
ext2_disk_sync();
|
|
|
|
return 0;
|
2012-09-04 09:35:11 +04:00
|
|
|
case 4:
|
|
|
|
/* Request kernel output to file descriptor in arg0*/
|
|
|
|
kprintf("Setting output to file object in process %d's fd=%d!\n", getpid(), (int)args);
|
|
|
|
kprint_to_file = current_process->fds->entries[(int)args];
|
|
|
|
break;
|
2012-05-17 04:51:37 +04:00
|
|
|
default:
|
2012-09-04 09:35:11 +04:00
|
|
|
kprintf("Bad system function %d\n", fn);
|
2012-05-17 04:51:37 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1; /* Bad system function or access failure */
|
|
|
|
}
|
|
|
|
|
2011-04-12 01:45:15 +04:00
|
|
|
/*
|
|
|
|
* System Call Internals
|
|
|
|
*/
|
2011-03-30 06:08:56 +04:00
|
|
|
static void syscall_handler(struct regs * r);
|
2011-03-30 10:22:31 +04:00
|
|
|
static uintptr_t syscalls[] = {
|
2011-03-30 06:08:56 +04:00
|
|
|
/* System Call Table */
|
2012-07-07 08:16:19 +04:00
|
|
|
(uintptr_t)&exit, /* 0 */
|
2011-04-17 05:01:04 +04:00
|
|
|
(uintptr_t)&print,
|
|
|
|
(uintptr_t)&open,
|
|
|
|
(uintptr_t)&read,
|
2012-07-07 08:16:19 +04:00
|
|
|
(uintptr_t)&write, /* 4 */
|
2011-04-17 22:26:31 +04:00
|
|
|
(uintptr_t)&close,
|
|
|
|
(uintptr_t)&gettimeofday,
|
|
|
|
(uintptr_t)&execve,
|
2012-07-07 08:16:19 +04:00
|
|
|
(uintptr_t)&fork, /* 8 */
|
2012-02-16 08:56:16 +04:00
|
|
|
(uintptr_t)&sys_getpid,
|
2011-04-18 03:28:40 +04:00
|
|
|
(uintptr_t)&sys_sbrk,
|
2011-04-30 04:54:07 +04:00
|
|
|
(uintptr_t)&getgraphicsaddress,
|
2012-10-15 06:53:16 +04:00
|
|
|
(uintptr_t)RESERVED, /* 12 */
|
|
|
|
(uintptr_t)RESERVED,
|
2011-04-30 04:54:07 +04:00
|
|
|
(uintptr_t)&seek,
|
|
|
|
(uintptr_t)&stat,
|
2012-07-07 08:16:19 +04:00
|
|
|
(uintptr_t)&setgraphicsoffset, /* 16 */
|
2011-12-07 06:13:20 +04:00
|
|
|
(uintptr_t)&wait,
|
2011-12-16 23:16:20 +04:00
|
|
|
(uintptr_t)&getgraphicswidth,
|
|
|
|
(uintptr_t)&getgraphicsheight,
|
2012-07-07 08:16:19 +04:00
|
|
|
(uintptr_t)&getgraphicsdepth, /* 20 */
|
2012-01-25 04:40:25 +04:00
|
|
|
(uintptr_t)&mkpipe,
|
2012-01-25 05:06:07 +04:00
|
|
|
(uintptr_t)&dup2,
|
2012-01-27 08:46:18 +04:00
|
|
|
(uintptr_t)&getuid,
|
2012-07-07 08:16:19 +04:00
|
|
|
(uintptr_t)&setuid, /* 24 */
|
2012-01-27 08:46:18 +04:00
|
|
|
(uintptr_t)&kernel_name_XXX,
|
2012-01-27 09:11:43 +04:00
|
|
|
(uintptr_t)&reboot,
|
2012-01-27 05:12:10 +04:00
|
|
|
(uintptr_t)&readdir,
|
2012-07-07 08:16:19 +04:00
|
|
|
(uintptr_t)&chdir, /* 28 */
|
2012-01-27 23:10:58 +04:00
|
|
|
(uintptr_t)&getcwd,
|
2012-01-29 03:06:07 +04:00
|
|
|
(uintptr_t)&clone,
|
2012-01-30 22:10:53 +04:00
|
|
|
(uintptr_t)&sethostname,
|
2012-07-07 08:16:19 +04:00
|
|
|
(uintptr_t)&gethostname, /* 32 */
|
2012-02-03 02:16:29 +04:00
|
|
|
(uintptr_t)&mousedevice,
|
2012-02-06 02:04:41 +04:00
|
|
|
(uintptr_t)&sys_mkdir,
|
2012-02-06 00:16:59 +04:00
|
|
|
(uintptr_t)&shm_obtain,
|
2012-07-07 08:16:19 +04:00
|
|
|
(uintptr_t)&shm_release, /* 36 */
|
2012-02-08 12:40:44 +04:00
|
|
|
(uintptr_t)&send_signal,
|
|
|
|
(uintptr_t)&sys_signal,
|
2012-02-09 06:59:34 +04:00
|
|
|
(uintptr_t)&share_fd,
|
2012-07-07 08:16:19 +04:00
|
|
|
(uintptr_t)&get_fd, /* 40 */
|
2012-02-16 11:06:44 +04:00
|
|
|
(uintptr_t)&gettid,
|
2012-03-02 07:13:52 +04:00
|
|
|
(uintptr_t)&yield,
|
2012-05-17 04:51:37 +04:00
|
|
|
(uintptr_t)&system_function,
|
2012-11-29 11:05:19 +04:00
|
|
|
(uintptr_t)&open_serial, /* 44 */
|
2012-01-25 04:40:25 +04:00
|
|
|
0
|
2011-03-30 06:08:56 +04:00
|
|
|
};
|
2012-01-25 04:40:25 +04:00
|
|
|
uint32_t num_syscalls;
|
2011-03-30 06:08:56 +04:00
|
|
|
|
|
|
|
void
|
|
|
|
syscalls_install() {
|
2011-12-27 05:23:58 +04:00
|
|
|
blog("Initializing syscall table...");
|
2012-01-25 04:40:25 +04:00
|
|
|
for (num_syscalls = 0; syscalls[num_syscalls] != 0; ++num_syscalls);
|
2011-12-15 05:06:11 +04:00
|
|
|
LOG(INFO, "Initializing syscall table with %d functions", num_syscalls);
|
2011-03-30 06:08:56 +04:00
|
|
|
isrs_install_handler(0x7F, &syscall_handler);
|
2011-12-27 05:23:58 +04:00
|
|
|
bfinish(0);
|
2011-03-30 06:08:56 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
syscall_handler(
|
|
|
|
struct regs * r
|
|
|
|
) {
|
|
|
|
if (r->eax >= num_syscalls) {
|
|
|
|
return;
|
|
|
|
}
|
2012-10-15 06:53:16 +04:00
|
|
|
|
2011-03-30 10:22:31 +04:00
|
|
|
uintptr_t location = syscalls[r->eax];
|
2011-03-30 06:08:56 +04:00
|
|
|
|
2012-10-15 06:53:16 +04:00
|
|
|
if (location == 1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-01-29 03:06:07 +04:00
|
|
|
/* Update the syscall registers for this process */
|
|
|
|
current_process->syscall_registers = r;
|
2011-12-16 01:31:18 +04:00
|
|
|
|
2011-03-30 06:08:56 +04:00
|
|
|
uint32_t ret;
|
2011-10-31 10:17:26 +04:00
|
|
|
asm volatile (
|
2011-03-30 06:08:56 +04:00
|
|
|
"push %1\n"
|
|
|
|
"push %2\n"
|
|
|
|
"push %3\n"
|
|
|
|
"push %4\n"
|
|
|
|
"push %5\n"
|
|
|
|
"call *%6\n"
|
|
|
|
"pop %%ebx\n"
|
|
|
|
"pop %%ebx\n"
|
|
|
|
"pop %%ebx\n"
|
|
|
|
"pop %%ebx\n"
|
|
|
|
"pop %%ebx\n"
|
|
|
|
: "=a" (ret) : "r" (r->edi), "r" (r->esi), "r" (r->edx), "r" (r->ecx), "r" (r->ebx), "r" (location));
|
2012-01-29 03:06:07 +04:00
|
|
|
|
|
|
|
/* The syscall handler may have moved the register pointer
|
|
|
|
* (ie, by creating a new stack)
|
|
|
|
* Update the pointer */
|
|
|
|
r = current_process->syscall_registers;
|
2011-03-30 06:08:56 +04:00
|
|
|
r->eax = ret;
|
|
|
|
}
|