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-04-12 01:45:15 +04:00
|
|
|
#include <syscall.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>
|
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
|
|
|
|
|
|
|
/*
|
|
|
|
* 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) {
|
|
|
|
kprintf("SEGFAULT: Invalid pointer passed to syscall. (0x%x < 0x%x)\n", (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-01-25 10:19:52 +04:00
|
|
|
serial_string(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) {
|
2011-12-09 01:25:48 +04:00
|
|
|
if (fd >= (int)current_process->fds.length || fd < 0) {
|
2011-04-17 05:01:04 +04:00
|
|
|
return -1;
|
|
|
|
}
|
2012-01-25 10:19:52 +04:00
|
|
|
if (current_process->fds.entries[fd] == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
2011-04-18 02:44:29 +04:00
|
|
|
validate(ptr);
|
2011-12-09 01:25:48 +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) {
|
|
|
|
if (fd >= (int)current_process->fds.length || fd < 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (current_process->fds.entries[fd] == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
validate(entry);
|
|
|
|
fs_node_t * node = current_process->fds.entries[fd];
|
|
|
|
|
|
|
|
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-01-25 10:19:52 +04:00
|
|
|
if ((fd == 1 && !current_process->fds.entries[fd]) ||
|
|
|
|
(fd == 2 && !current_process->fds.entries[fd])) {
|
|
|
|
serial_string(ptr);
|
2011-04-25 06:09:36 +04:00
|
|
|
return len;
|
|
|
|
}
|
2011-12-09 01:25:48 +04:00
|
|
|
if (fd >= (int)current_process->fds.length || fd < 0) {
|
2011-04-17 05:01:04 +04:00
|
|
|
return -1;
|
|
|
|
}
|
2012-01-25 10:19:52 +04:00
|
|
|
if (current_process->fds.entries[fd] == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
2011-04-18 02:44:29 +04:00
|
|
|
validate(ptr);
|
2011-12-09 01:25:48 +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-01-31 10:16:09 +04:00
|
|
|
kprintf("[debug] Process %d requested group wait, which we can not do!\n", 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) {
|
|
|
|
kprintf("Tried to wait for non-existent process\n");
|
|
|
|
}
|
2011-12-07 06:13:20 +04:00
|
|
|
/* Wait until it finishes (this is stupidly memory intensive,
|
|
|
|
* but we haven't actually implemented wait() yet, so there's
|
|
|
|
* not all that much we can do right now. */
|
|
|
|
while (child_task->finished == 0) {
|
|
|
|
if (child_task->finished != 0) break;
|
|
|
|
switch_task();
|
|
|
|
}
|
|
|
|
/* 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) {
|
2012-01-31 10:16:09 +04:00
|
|
|
kprintf("[debug] open(%s, 0x%x, 0x%x)\n", file, flags, 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-01-31 10:16:09 +04:00
|
|
|
if (!node && (mode & 0x600)) {
|
|
|
|
/* Um, make one */
|
|
|
|
}
|
2011-04-17 05:01:04 +04:00
|
|
|
if (!node) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
node->offset = 0;
|
2011-12-09 01:25:48 +04:00
|
|
|
return process_append_fd((process_t *)current_process, node);
|
2011-04-17 05:01:04 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static int close(int fd) {
|
2012-01-27 05:12:10 +04:00
|
|
|
if (fd >= (int)current_process->fds.length || fd < 0) {
|
2011-04-17 05:01:04 +04:00
|
|
|
return -1;
|
|
|
|
}
|
2011-12-09 01:25:48 +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;
|
|
|
|
}
|
|
|
|
|
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);
|
2011-04-17 22:26:31 +04:00
|
|
|
int i = 0;
|
|
|
|
while (argv[i]) {
|
|
|
|
++i;
|
|
|
|
}
|
2011-04-18 02:44:29 +04:00
|
|
|
char ** argv_ = malloc(sizeof(char *) * i);
|
|
|
|
for (int j = 0; j < i; ++j) {
|
|
|
|
argv_[j] = malloc((strlen(argv[j]) + 1) * sizeof(char));
|
|
|
|
memcpy(argv_[j], argv[j], strlen(argv[j]) + 1);
|
|
|
|
}
|
2011-04-17 22:26:31 +04:00
|
|
|
/* Discard envp */
|
2011-04-18 02:44:29 +04:00
|
|
|
exec((char *)filename, i, (char **)argv_);
|
2011-04-17 22:26:31 +04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2011-04-30 04:54:07 +04:00
|
|
|
static int getgraphicsaddress() {
|
|
|
|
return (int)bochs_get_address();
|
|
|
|
}
|
|
|
|
|
|
|
|
static volatile char kbd_last = 0;
|
|
|
|
|
|
|
|
static void kbd_direct_handler(char ch) {
|
|
|
|
kbd_last = ch;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int kbd_mode(int mode) {
|
|
|
|
if (mode == 0) {
|
2011-04-30 12:40:36 +04:00
|
|
|
if (keyboard_direct_handler) {
|
|
|
|
keyboard_direct_handler = NULL;
|
2011-04-30 04:54:07 +04:00
|
|
|
}
|
|
|
|
} else {
|
2011-04-30 12:40:36 +04:00
|
|
|
keyboard_direct_handler = kbd_direct_handler;
|
2011-04-30 04:54:07 +04:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int kbd_get() {
|
2011-04-30 12:40:36 +04:00
|
|
|
/* If we're requesting keyboard input, we better damn well be getting it */
|
2012-01-11 05:54:05 +04:00
|
|
|
IRQ_RES;
|
2011-04-30 04:54:07 +04:00
|
|
|
char x = kbd_last;
|
|
|
|
kbd_last = 0;
|
|
|
|
return (int)x;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int seek(int fd, int offset, int whence) {
|
2011-12-09 01:25:48 +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) {
|
2011-12-09 01:25:48 +04:00
|
|
|
current_process->fds.entries[fd]->offset = offset;
|
2011-04-30 04:54:07 +04:00
|
|
|
} else if (whence == 1) {
|
2011-12-09 01:25:48 +04:00
|
|
|
current_process->fds.entries[fd]->offset += offset;
|
2011-04-30 04:54:07 +04:00
|
|
|
} else if (whence == 2) {
|
2011-12-09 01:25:48 +04:00
|
|
|
current_process->fds.entries[fd]->offset = current_process->fds.entries[fd]->length + offset;
|
2011-04-30 04:54:07 +04:00
|
|
|
}
|
2011-12-09 01:25:48 +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) {
|
|
|
|
if (fd >= (int)current_process->fds.length || fd < 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
fs_node_t * fn = current_process->fds.entries[fd];
|
|
|
|
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() {
|
|
|
|
return bochs_resolution_x;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int getgraphicsheight() {
|
|
|
|
return bochs_resolution_y;
|
|
|
|
}
|
|
|
|
|
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() {
|
|
|
|
return bochs_resolution_b;
|
|
|
|
}
|
|
|
|
|
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-01-27 09:11:43 +04:00
|
|
|
static int reboot() {
|
|
|
|
kprintf("[kernel] Reboot requested from process %d by user #%d\n", current_process->id, current_process->user);
|
|
|
|
kprintf("[kernel] Good bye!\n");
|
|
|
|
if (current_process->user != 0) {
|
|
|
|
return -1;
|
|
|
|
} else {
|
|
|
|
/* Goodbye, cruel world */
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
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 */
|
2011-12-07 06:13:20 +04:00
|
|
|
(uintptr_t)&exit, /* 0 */
|
2011-04-17 05:01:04 +04:00
|
|
|
(uintptr_t)&print,
|
|
|
|
(uintptr_t)&open,
|
|
|
|
(uintptr_t)&read,
|
2011-12-07 06:13:20 +04:00
|
|
|
(uintptr_t)&write, /* 4 */
|
2011-04-17 22:26:31 +04:00
|
|
|
(uintptr_t)&close,
|
|
|
|
(uintptr_t)&gettimeofday,
|
|
|
|
(uintptr_t)&execve,
|
2012-01-29 03:06:07 +04:00
|
|
|
(uintptr_t)&fork, /* 8 */
|
2011-04-18 02:44:29 +04:00
|
|
|
(uintptr_t)&getpid,
|
2011-04-18 03:28:40 +04:00
|
|
|
(uintptr_t)&sys_sbrk,
|
2011-04-30 04:54:07 +04:00
|
|
|
(uintptr_t)&getgraphicsaddress,
|
2011-12-07 06:13:20 +04:00
|
|
|
(uintptr_t)&kbd_mode, /* 12 */
|
2011-04-30 04:54:07 +04:00
|
|
|
(uintptr_t)&kbd_get,
|
|
|
|
(uintptr_t)&seek,
|
|
|
|
(uintptr_t)&stat,
|
2011-12-07 06:13:20 +04:00
|
|
|
(uintptr_t)&setgraphicsoffset, /* 16 */
|
|
|
|
(uintptr_t)&wait,
|
2011-12-16 23:16:20 +04:00
|
|
|
(uintptr_t)&getgraphicswidth,
|
|
|
|
(uintptr_t)&getgraphicsheight,
|
2012-01-25 04:40:25 +04:00
|
|
|
(uintptr_t)&getgraphicsdepth, /* 20 */
|
|
|
|
(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,
|
|
|
|
(uintptr_t)&setuid, /* 24 */
|
|
|
|
(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-01-27 23:10:58 +04:00
|
|
|
(uintptr_t)&chdir, /* 28 */
|
|
|
|
(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,
|
|
|
|
(uintptr_t)&gethostname, /* 32 */
|
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;
|
|
|
|
}
|
2011-03-30 10:22:31 +04:00
|
|
|
uintptr_t location = syscalls[r->eax];
|
2011-03-30 06:08:56 +04:00
|
|
|
|
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;
|
|
|
|
}
|