Compare commits

..

No commits in common. "185757e2a7dcce05f14d65efab4da41e7e8b3199" and "3c1146f2c5a7eef2fe1a45be21bb68ad89170dd8" have entirely different histories.

121 changed files with 532 additions and 3416 deletions

5
.gitignore vendored
View File

@ -10,7 +10,4 @@ apps/bin/**
tests/**/bin/**
base/usr/include/**
base/usr/lib/**
**/*.a
ports/**/workdir/**
ports/ports.list
**/*.pkg.tar.xz
**/*.a

View File

@ -22,5 +22,4 @@ initrd-clean:
install:
@$(MAKE) -C kernel install
@$(MAKE) -C libs install
@$(MAKE) -C apps install
@tools/install-built-ports.sh
@$(MAKE) -C apps install

View File

@ -2,15 +2,16 @@
A simple kernel and userspace for the x86_64 platform, written mostly in C++.
## Features
Not so much at the moment.
- x86_64-compatible [kernel](kernel/).
- Keeps track of which [memory](kernel/src/memory/) is used and which memory is free, and can allocate memory for itself and [user programs](kernel/src/sys/mem.cpp).
- Can load files from a [virtual file system](kernel/src/fs/) supporting an initial ramdisk, device pseudo-filesystems... but no hard disks yet.
- Basic preemptive multitasking, round-robin [scheduler](kernel/src/thread/) that can switch between tasks.
- Can [load userspace ELF programs](kernel/src/sys/elf/) from the file system as user tasks.
- [System call](kernel/src/sys/) interface and simple [C Library](libs/libc/), aiming to be POSIX-compatible.
- Some very simple [example programs](apps/), written in C, that then can get loaded and executed by the kernel at userspace demand.
- Some very simple [example programs](apps/), written in C, that then can get loaded and executed by the kernel.
- UNIX-like [multitasking primitives](kernel/src/sys/exec.cpp), which allow user tasks to spawn other tasks.
- Very simple [command-line shell](apps/src/sh.c), allowing interactive use of the system.
## Setup
To build and run Luna, you will need to build a [GCC Cross-Compiler](https://wiki.osdev.org/Why_do_I_need_a_Cross_Compiler%3F) and cross-binutils for `x86_64-luna`. (Yes, Luna is advanced enough that it can use its own [OS-Specific Toolchain](https://wiki.osdev.org/OS_Specific_Toolchain), instead of a bare metal target like `x86_64-elf`. It is the first of my OS projects to be able to do so. The patches for Binutils and GCC are [binutils.patch](tools/binutils.patch) and [gcc.patch](tools/gcc.patch)).
@ -70,24 +71,5 @@ Prebuilt ISO images for every version can be found at [pub.cloudapio.eu](https:/
These images are built manually whenever I decide to make a new version, and thus don't reflect the latest changes on the `main` branch.
## Is there third-party software I can use on Luna?
Yes, actually! Check out the [ports](ports/) directory.
Right now, only [bc](https://github.com/gavinhoward/bc) is ported, because right now our C Library is quite primitive and doesn't support projects more complex than that.
And bc itself doesn't run very well... most notably, user input doesn't echo. But that's on our side. At least it runs!
You should also keep in mind that it is not possible to compile software written in any language other than C for Luna right now.
But feel free to try to port some program yourself and add it to the ports directory!
Port usage:
`ports/add-port.sh <port-name>` will build and add a port to the list of installed ports, and the built port will automatically get installed into the system root every time you run Luna.
`ports/remove-port.sh <port-name>` will remove the port from the list of installed ports, remove built files from the system root, as well as the build directory.
`ports/make-package.sh <port-name>` will compile the port and make a package archive from it, which may be used in the future with a package manager :)
## License
Luna is open-source and free software under the [BSD-2 License](LICENSE).

View File

@ -1,4 +1,4 @@
APPS := init sym sh crash uname uptime hello ps ls
APPS := init sym
APPS_DIR := $(LUNA_ROOT)/apps
APPS_SRC := $(APPS_DIR)/src
@ -6,7 +6,7 @@ APPS_BIN := $(APPS_DIR)/bin
REAL_APPS := $(patsubst %, $(APPS_BIN)/%, $(APPS))
CFLAGS := -Wall -Wextra -Werror -Os -fno-asynchronous-unwind-tables
CFLAGS := -Wall -Wextra -Werror -Os
$(APPS_BIN)/%: $(APPS_SRC)/%.c
@mkdir -p $(@D)

View File

@ -1,5 +0,0 @@
int main()
{
int* ptr = (int*)0xdeadbeef;
*ptr = 6;
}

View File

@ -1,6 +0,0 @@
#include <stdio.h>
int main()
{
puts("Hello, world!");
}

View File

@ -1,33 +1,40 @@
#include <errno.h>
#include <luna.h>
#include <setjmp.h>
#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
void show_motd()
int print_version()
{
FILE* fp = fopen("/etc/motd", "r");
char version[4096];
FILE* fp = fopen("/dev/version", "r");
if (!fp)
{
if (errno != ENOENT) { perror("fopen"); }
return;
perror("fopen");
return 1;
}
char buf[4096];
size_t nread = fread(buf, sizeof(buf) - 1, 1, fp);
size_t nread = fread(version, 4096, 1, fp);
if (ferror(fp))
{
perror("fread");
fclose(fp);
return;
return 1;
}
buf[nread] = 0;
puts(buf);
version[nread] = 0;
fclose(fp);
if (fclose(fp) < 0)
{
perror("fclose");
return 1;
}
putchar('\n');
printf("Your kernel version is %s\n\n", version);
return 0;
}
int main()
@ -38,11 +45,116 @@ int main()
return 1;
}
show_motd();
FILE* serial = fopen("/dev/serial", "r");
if (!serial)
{
perror("fopen");
return 1;
}
if (fputs("Hello from init!\n", serial) < 0)
{
perror("fputs");
return 1;
}
if (fclose(serial) < 0)
{
perror("fclose");
return 1;
}
msleep(200);
printf("Welcome to Luna!\n");
printf("Running as PID %ld\n\n", getpid());
sleep(1);
if (print_version()) return 1;
sleep(2);
const char* filename = "/sys/config";
printf("Opening %s for reading...\n", filename);
FILE* config = fopen(filename, "r");
if (!config)
{
perror("fopen");
return 1;
}
if (fseek(config, 0, SEEK_END) < 0)
{
perror("fseek");
return 1;
}
long offset = ftell(config);
if (offset < 0)
{
perror("ftell");
return 1;
}
printf("%s is %ld bytes long\n", filename, offset);
rewind(config);
char buf[4096];
size_t nread = fread(buf, sizeof(buf), 1, config);
if (ferror(config)) { perror("fread"); }
else
{
buf[nread] = 0;
printf("Read %zd bytes\n\n", nread);
printf("%s", buf);
}
if (fclose(config) < 0) { perror("fclose"); }
printf("\n\nGot random number %d\n\n", rand());
sleep(2);
printf("Press any key to restart.\n\n");
int stderr_fd = fileno(stderr);
int new_stderr_fd = dup(stderr_fd);
if (new_stderr_fd < 0)
{
perror("dup");
return 1;
}
FILE* new_stderr = fdopen(new_stderr_fd, "rw");
if (!new_stderr)
{
perror("fdopen");
return 1;
}
fprintf(new_stderr, "Bye!\n\n");
fclose(new_stderr);
const char* pathname = "/etc";
printf("Creating directory %s\n", pathname);
if (mkdir(pathname, 0) < 0)
{
perror("mkdir");
return 1;
}
printf("Success!!\n");
printf("Forking...\n");
pid_t child = fork();
if (child < 0)
{
perror("fork");
@ -50,19 +162,22 @@ int main()
}
if (child == 0)
{
execv("/bin/sh", NULL);
msleep(500);
printf("I am the child, who is my parent?\n");
execv("/bin/sym", NULL);
perror("execv");
return 1;
}
else { printf("Success!! Got PID %ld\n", child); }
pid_t result;
for (;;)
jmp_buf env;
int val = setjmp(env);
if (val == 0) { printf("Returning from setjmp!\n"); }
else
{
while ((result = wait(NULL)) == 0) // No child has exited yet
{
msleep(100);
}
if (result == child) { return 0; }
printf("Returning from longjmp! val=%d\n", val);
return 0;
}
longjmp(env, 3);
}

View File

@ -1,22 +0,0 @@
#include <dirent.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
DIR* dp = opendir("/bin");
if (!dp)
{
perror("opendir");
return 1;
}
do {
struct dirent* ent = readdir(dp);
if (!ent) break;
printf("%s\n", ent->d_name);
} while (1);
closedir(dp);
return 0;
}

View File

@ -1,44 +0,0 @@
#include <errno.h>
#include <luna/pstat.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
pid_t get_current_max_threads()
{
pid_t result = pstat(-1, NULL);
if (result < 0)
{
perror("pstat(-1)");
exit(1);
}
return result;
}
void display_process(struct pstat* pstatbuf)
{
printf("%ld %ld %s %s (%ld ms)\n", pstatbuf->pt_pid, pstatbuf->pt_ppid, pstatbuf->pt_name, pstatname(pstatbuf),
pstatbuf->pt_time);
}
int try_pstat(pid_t pid, struct pstat* pstatbuf)
{
pid_t result = pstat(pid, pstatbuf);
if (result < 0)
{
if (errno == ESRCH) return 0;
perror("pstat");
exit(1);
}
return 1;
}
int main()
{
struct pstat pst;
pid_t max = get_current_max_threads();
for (pid_t pid = 0; pid <= max; pid++)
{
if (try_pstat(pid, &pst)) { display_process(&pst); }
}
}

View File

@ -1,194 +0,0 @@
#include <assert.h>
#include <errno.h>
#include <luna.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
static int status = 0;
typedef struct
{
char* buffer;
size_t size;
size_t capacity;
} command;
void show_prompt()
{
if (WEXITSTATUS(status)) { printf("%d [%ld]> ", WEXITSTATUS(status), getpid()); }
else
printf("[%ld]> ", getpid());
}
int command_matches(command* cmd, const char* string)
{
if (cmd->size <= strlen(string)) // cmd->size includes null terminator
return 0;
return strncmp(cmd->buffer, string, strlen(string)) == 0;
}
int command_matches_exactly(command* cmd, const char* string)
{
if (cmd->size <= strlen(string)) // cmd->size includes null terminator
return 0;
if (cmd->size > (strlen(string) + 1)) return 0;
return strncmp(cmd->buffer, string, strlen(string)) == 0;
}
int command_match_builtins(command* cmd)
{
if (command_matches(cmd, "exit ")) { exit(atoi(cmd->buffer + 5)); }
if (command_matches_exactly(cmd, "exit")) { exit(0); }
if (command_matches_exactly(cmd, "pid"))
{
printf("pid %ld, ppid %ld\n", getpid(), getppid());
return 1;
}
return 0;
}
void command_expand(command* cmd, long new_capacity)
{
char* buffer = realloc(cmd->buffer, new_capacity);
if (!buffer)
{
perror("realloc");
exit(1);
}
cmd->buffer = buffer;
cmd->capacity = new_capacity;
}
void command_push(command* cmd, char c)
{
if (cmd->size == cmd->capacity) command_expand(cmd, cmd->capacity + 8);
cmd->buffer[cmd->size] = c;
cmd->size++;
}
void command_pop(command* cmd)
{
cmd->size--;
}
void command_init(command* cmd)
{
cmd->buffer = malloc(5);
cmd->capacity = 5;
cmd->size = 0;
}
void command_clear(command* cmd)
{
free(cmd->buffer);
return command_init(cmd);
}
void command_execute(command* cmd)
{
command_push(cmd, '\0');
if (command_match_builtins(cmd))
{
command_clear(cmd);
show_prompt();
return;
}
pid_t child = fork();
if (child < 0)
{
perror(cmd->buffer);
command_clear(cmd);
show_prompt();
return;
}
if (child == 0)
{
if (cmd->buffer[0] != '/' && access(cmd->buffer, F_OK) < 0) // FIXME: Race condition.
{
if (errno == ENOENT)
{ // Try in /bin
char* buf = malloc(cmd->size + 6);
strlcpy(buf, "/bin/", 6);
strncat(buf, cmd->buffer, cmd->size);
execv(buf, NULL);
}
}
else
execv(cmd->buffer, NULL);
perror(cmd->buffer);
exit(127);
}
pid_t result;
while ((result = waitpid(child, &status, 0)) == 0) { msleep(20); }
if (result < 0)
{
perror("waitpid");
command_clear(cmd);
show_prompt();
return;
}
int exit_status = WEXITSTATUS(status);
if (exit_status == -2 || exit_status == -3) printf("(PID %ld) Segmentation fault\n", result);
command_clear(cmd);
show_prompt();
}
void command_concat_char(command* cmd, char c)
{
if (c == '\b')
{
if (cmd->size != 0)
{
putchar(c);
command_pop(cmd);
}
}
else if (c == '\n')
{
putchar(c);
if (cmd->size == 0) show_prompt();
else
command_execute(cmd);
}
else
{
putchar(c);
command_push(cmd, c);
}
}
void command_concat(command* cmd, const char* str)
{
while (*str)
{
command_concat_char(cmd, *str);
str++;
}
}
int main()
{
show_prompt();
command shell_command;
command_init(&shell_command);
while (1)
{
int c = getchar();
if (c == EOF)
{
if (ferror(stdin))
{
perror("getchar");
return 1;
}
if (feof(stdin)) { return 0; }
assert(false); // we should never get here
}
command_concat_char(&shell_command, (char)c);
}
}

View File

@ -4,6 +4,8 @@
int main()
{
sleep(2);
FILE* syms = fopen("/sys/moon.sym", "r");
if (!syms)
{

View File

@ -1,18 +0,0 @@
#include <stdio.h>
int main()
{
FILE* fp = fopen("/dev/version", "r");
if (!fp)
{
perror("fopen");
return 1;
}
char buf[BUFSIZ];
fgets(buf, sizeof(buf), fp);
printf("%s\n", buf);
fclose(fp);
}

View File

@ -1,27 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE* fp = fopen("/dev/uptime", "r");
if (!fp)
{
perror("fopen");
return 1;
}
char buf[BUFSIZ];
fgets(buf, sizeof(buf), fp);
if (ferror(fp))
{
perror("fgets");
return 1;
}
long ms_uptime = atol(buf);
printf("up for %ld seconds\n", ms_uptime / 1000);
fclose(fp);
}

View File

@ -1,3 +0,0 @@
Welcome to Luna!
Tip of the day: Type 'help' to get started!

View File

@ -2,11 +2,8 @@
#define EPERM 1
#define ENOENT 2
#define ESRCH 3
#define EINTR 4
#define ENOEXEC 8
#define EBADF 9
#define EAGAIN 11
#define ENOMEM 12
#define EFAULT 14
#define EEXIST 17
@ -14,7 +11,6 @@
#define EISDIR 21
#define EINVAL 22
#define EMFILE 24
#define ENOTTY 25
#define ENOSPC 28
#define ENOSYS 38
#define ENOTSUP 95

View File

@ -24,15 +24,10 @@ struct Descriptor
m_is_open = false;
}
VFS::Node* node()
{
return m_node;
}
ssize_t read(size_t size, char* buffer);
ssize_t write(size_t size, const char* buffer);
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);
int seek(long offset);
long offset()
@ -45,16 +40,6 @@ struct Descriptor
return m_node->length;
}
bool able_to_block()
{
return m_able_to_block;
}
bool close_on_exec()
{
return m_close_on_exec;
}
Descriptor(const Descriptor& other);
Descriptor();
@ -64,8 +49,6 @@ struct Descriptor
bool m_is_open;
bool m_can_read;
bool m_can_write;
bool m_able_to_block;
bool m_close_on_exec;
VFS::Node* m_node;
uint64_t m_offset;
};

View File

@ -10,8 +10,6 @@ typedef long ssize_t;
#define VFS_MOUNTPOINT 0x1
#define NAME_MAX 64
namespace VFS
{
struct Node;
@ -20,23 +18,18 @@ namespace VFS
typedef ssize_t (*node_write)(Node*, size_t, size_t, const char*);
typedef Node* (*node_finddir)(Node*, const char*);
typedef int (*node_mkdir)(Node*, const char*);
typedef int (*node_block)(Node*);
typedef Node* (*node_readdir)(Node*, long);
struct Node
{
char name[NAME_MAX];
char name[64];
uint64_t inode;
uint64_t length;
int type;
int flags;
node_read read_func;
node_finddir find_func;
node_readdir readdir_func;
node_mkdir mkdir_func;
node_write write_func;
node_block block_func;
int tty = 0;
Node* link;
};
@ -45,8 +38,6 @@ namespace VFS
int mkdir(const char* path, const char* name);
int mkdir(const char* pathname);
int would_block(Node* node);
void mount_root(Node* root);
Node* resolve_path(const char* filename, Node* root = nullptr);
@ -59,6 +50,4 @@ namespace VFS
void unmount(Node* mountpoint);
Node* root();
Node* readdir(Node* dir, long offset);
}

View File

@ -6,5 +6,4 @@ namespace DeviceFS
VFS::Node* get();
VFS::Node* finddir(VFS::Node* node, const char* filename);
VFS::Node* readdir(VFS::Node* node, long offset);
}

View File

@ -1,13 +0,0 @@
#pragma once
#include "fs/VFS.h"
namespace KeyboardDevice
{
VFS::Node* create_new(const char* devname);
ssize_t read(VFS::Node* node, size_t offset, size_t size, char* buffer);
int would_block(VFS::Node* node);
void append(char c);
}

View File

@ -1,9 +0,0 @@
#pragma once
#include "fs/VFS.h"
namespace UptimeDevice
{
VFS::Node* create_new(const char* devname);
ssize_t read(VFS::Node* node, size_t offset, size_t size, char* buffer);
}

View File

@ -8,8 +8,4 @@ namespace KernelHeap
void free_virtual_page(uint64_t address);
void free_virtual_pages(uint64_t address, uint64_t count);
void clear();
void dump_usage();
}

View File

@ -1,6 +0,0 @@
#pragma once
// This should only be used for a keyboard TTY interface. Userspace should translate keyboard scancodes by themselves.
char translate_scancode(unsigned char scancode, bool* ignore);
bool scancode_filter_released(unsigned char* scancode);

View File

@ -17,7 +17,7 @@ char* strstr(char* haystack, const char* needle);
void* memcpy(void* dest, const void* src, size_t n);
void* memset(void* dest, int c, size_t n);
int memcmp(const void* a, const void* b, size_t n);
void* memmove(void* dest, const void* src, size_t n);
void* memmove(void* dest, void* src, size_t n);
char* strdup(const char* src);
char* strrchr(const char* str, int c);

View File

@ -7,7 +7,7 @@
#define SYS_sleep 2
#define SYS_write 3
#define SYS_paint 4
#define SYS_getprocid 5
#define SYS_getpid 5
#define SYS_mmap 6
#define SYS_munmap 7
#define SYS_open 8
@ -20,19 +20,12 @@
#define SYS_clock 15
#define SYS_mkdir 16
#define SYS_fork 17
#define SYS_waitpid 18
#define SYS_access 19
#define SYS_fstat 20
#define SYS_pstat 21
#define SYS_getdents 22
struct stat;
struct pstat;
struct luna_dirent;
namespace Syscall
{
void entry(Context* context);
char* strdup_from_user(const char* user_string);
}
void sys_exit(Context* context, int status);
@ -40,7 +33,7 @@ void sys_yield(Context* context);
void sys_sleep(Context* context, uint64_t ms);
void sys_write(Context* context, int fd, size_t size, const char* addr);
void sys_paint(Context* context, uint64_t x, uint64_t y, uint64_t w, uint64_t h, uint64_t col);
void sys_getprocid(Context* context, int field);
void sys_getpid(Context* context);
void sys_mmap(Context* context, void* address, size_t size, int prot);
void sys_munmap(Context* context, void* address, size_t size);
void sys_open(Context* context, const char* filename, int flags);
@ -52,9 +45,4 @@ void sys_fcntl(Context* context, int fd, int command, uintptr_t arg);
void sys_mprotect(Context* context, void* address, size_t size, int prot);
void sys_clock(Context* context);
void sys_mkdir(Context* context, const char* filename);
void sys_fork(Context* context);
void sys_waitpid(Context* context, long pid, int* wstatus, int options);
void sys_access(Context* context, const char* path, int amode);
void sys_fstat(Context* context, int fd, struct stat* buf);
void sys_pstat(Context* context, long pid, struct pstat* buf);
void sys_getdents(Context* context, int fd, struct luna_dirent* buf, size_t count);
void sys_fork(Context* context);

View File

@ -1,43 +0,0 @@
#pragma once
#ifndef MODULE
#define MODULE "mem"
#endif
#include "log/Log.h"
#include "memory/MemoryManager.h"
#include "memory/VMM.h"
#include "misc/utils.h"
char* strdup_from_user(const char* user_string);
// FIXME: Map the physical addresses into kernel address space. Right now, something overwrites KernelHeap and crashes
// it, so that's not really possible. But it should be done in the future.
template <typename T, unsigned long S = sizeof(T), typename V> T* user_address_to_typed_pointer(V address)
{
uint64_t phys = VMM::get_physical((uint64_t)address);
if (phys == (uint64_t)-1)
{
kinfoln("warning: user pointer is not mapped in its address space");
return nullptr;
}
// return (T*)MemoryManager::get_unaligned_mappings((void*)phys, Utilities::get_blocks_from_size(PAGE_SIZE, S),
// MAP_READ_WRITE);
return (T*)phys;
}
template <typename T, unsigned long S = sizeof(T)> void free_user_typed_pointer(T*)
{
// MemoryManager::release_unaligned_mappings(ptr, Utilities::get_blocks_from_size(PAGE_SIZE, S));
}
template <typename T> T* obtain_user_ref(T* user_ptr)
{
return user_address_to_typed_pointer<T>(user_ptr);
}
template <typename T> void release_user_ref(T* ptr)
{
return free_user_typed_pointer(ptr);
}

View File

@ -14,13 +14,10 @@ struct Task
Idle,
Running,
Sleeping,
Dying,
Blocking,
Exited
};
uint64_t id;
uint64_t ppid;
Context regs;
int64_t task_sleep = 0;
@ -68,15 +65,4 @@ struct Task
bool has_died();
char name[128];
struct
{
size_t size;
int fd;
char* buf;
} blocking_read_info;
void resume_read();
bool is_still_blocking();
};

View File

@ -1,23 +1,20 @@
#include "fs/FileDescriptor.h"
#include "std/errno.h"
#include "errno.h"
Descriptor::Descriptor() : m_is_open(false)
{
}
Descriptor::Descriptor(const Descriptor& other)
: m_is_open(other.m_is_open), m_can_read(other.m_can_read), m_can_write(other.m_can_write),
m_able_to_block(other.m_able_to_block), m_close_on_exec(other.m_close_on_exec), m_node(other.m_node),
: m_is_open(other.m_is_open), m_can_read(other.m_can_read), m_can_write(other.m_can_write), m_node(other.m_node),
m_offset(other.m_offset)
{
}
void Descriptor::open(VFS::Node* node, bool can_read, bool can_write, bool able_to_block, bool close_on_exec)
void Descriptor::open(VFS::Node* node, bool can_read, bool can_write)
{
m_can_read = can_read;
m_can_write = can_write;
m_able_to_block = able_to_block;
m_close_on_exec = close_on_exec;
m_node = node;
m_offset = 0;
m_is_open = true;
@ -39,7 +36,7 @@ ssize_t Descriptor::write(size_t size, const char* buffer)
int Descriptor::seek(long offset)
{
if (m_node->type == VFS_FILE && (uint64_t)offset > m_node->length)
if (m_node->type != VFS_DEVICE && (uint64_t)offset > m_node->length)
return -EINVAL; // FIXME: Support seeking beyond the current file's length.
m_offset = (uint64_t)offset;
return 0;
@ -52,7 +49,5 @@ const Descriptor& Descriptor::operator=(const Descriptor& other)
m_can_write = other.m_can_write;
m_offset = other.m_offset;
m_node = other.m_node;
m_able_to_block = other.m_able_to_block;
m_close_on_exec = other.m_close_on_exec;
return other;
}

View File

@ -1,21 +1,14 @@
#define MODULE "vfs"
#include "fs/VFS.h"
#include "errno.h"
#include "log/Log.h"
#include "std/errno.h"
#include "std/libgen.h"
#include "std/stdlib.h"
#include "std/string.h"
static VFS::Node* vfs_root;
int VFS::would_block(Node* node)
{
if (!node) { return 0; }
if (!node->block_func) { return 0; }
return node->block_func(node);
}
ssize_t VFS::read(Node* node, size_t offset, size_t length, char* buffer)
{
if (!node)
@ -111,7 +104,11 @@ VFS::Node* VFS::resolve_path(const char* filename, Node* root)
return 0;
}
Node* child = current_node->find_func(current_node, buffer);
if (!child) { return 0; }
if (!child)
{
kwarnln("Current node did not find our target node");
return 0;
}
if (child->flags & VFS_MOUNTPOINT)
{
if (!child->link)
@ -201,11 +198,4 @@ void VFS::unmount(Node* mountpoint)
if (!mountpoint) return;
if (!(mountpoint->flags & VFS_MOUNTPOINT)) return;
mountpoint->flags &= ~VFS_MOUNTPOINT;
}
VFS::Node* VFS::readdir(VFS::Node* dir, long offset)
{
if (!dir) return 0;
if (!dir->readdir_func) return 0;
return dir->readdir_func(dir, offset);
}

View File

@ -13,7 +13,6 @@ VFS::Node* ConsoleDevice::create_new(const char* devname)
dev->length = 0;
dev->type = VFS_DEVICE;
dev->flags = 0;
dev->tty = 1;
strncpy(dev->name, devname, sizeof(dev->name));
return dev;
}

View File

@ -1,9 +1,7 @@
#include "fs/devices/DeviceFS.h"
#include "fs/devices/Console.h"
#include "fs/devices/Keyboard.h"
#include "fs/devices/Random.h"
#include "fs/devices/Serial.h"
#include "fs/devices/Uptime.h"
#include "fs/devices/Version.h"
#include "std/stdlib.h"
#include "std/string.h"
@ -23,16 +21,12 @@ VFS::Node* DeviceFS::get()
devfs_root->inode = 0;
devfs_root->type = VFS_DIRECTORY;
devfs_root->find_func = DeviceFS::finddir;
devfs_root->readdir_func = DeviceFS::readdir;
strncpy(devfs_root->name, "dev", sizeof(devfs_root->name));
devfs_files[devfs_file_count++] = VersionDevice::create_new("version");
devfs_files[devfs_file_count++] = ConsoleDevice::create_new("console");
devfs_files[devfs_file_count++] = SerialDevice::create_new("serial");
devfs_files[devfs_file_count++] = RandomDevice::create_new("random");
devfs_files[devfs_file_count++] = KeyboardDevice::create_new("kbd");
devfs_files[devfs_file_count++] = UptimeDevice::create_new("uptime");
devfs_root->length = devfs_file_count;
return devfs_root;
}
@ -44,11 +38,4 @@ VFS::Node* DeviceFS::finddir(VFS::Node* node, const char* filename)
if (strncmp(devfs_files[i]->name, filename, sizeof(VFS::Node::name)) == 0) { return devfs_files[i]; }
}
return 0;
}
VFS::Node* DeviceFS::readdir(VFS::Node* node, long offset)
{
if (!node) return 0;
if (offset >= devfs_file_count) return 0;
return devfs_files[offset];
}

View File

@ -1,51 +0,0 @@
#define MODULE "kbd"
#include "fs/devices/Keyboard.h"
#include "config.h"
#include "log/Log.h"
#include "render/TextRenderer.h"
#include "std/stdio.h"
#include "std/stdlib.h"
#include "std/string.h"
char* kbd_buffer = nullptr;
uint64_t kbd_bufsize = 0;
int KeyboardDevice::would_block(VFS::Node*)
{
return kbd_bufsize == 0;
}
VFS::Node* KeyboardDevice::create_new(const char* devname)
{
VFS::Node* dev = new VFS::Node;
dev->read_func = KeyboardDevice::read;
dev->block_func = KeyboardDevice::would_block;
dev->inode = 0;
dev->length = 0;
dev->type = VFS_DEVICE;
dev->flags = 0;
dev->tty = 1;
strncpy(dev->name, devname, sizeof(dev->name));
return dev;
}
ssize_t KeyboardDevice::read(VFS::Node* node, size_t, size_t size, char* buffer)
{
if (!node) return -1;
if (!kbd_buffer) return 0;
if (size > kbd_bufsize) size = kbd_bufsize;
memcpy(buffer, kbd_buffer, size);
memmove(kbd_buffer, kbd_buffer + size, kbd_bufsize - size);
kbd_bufsize -= size;
kbd_buffer = (char*)krealloc(kbd_buffer, kbd_bufsize);
return (ssize_t)size;
}
void KeyboardDevice::append(char c)
{
kbd_bufsize++;
kbd_buffer = (char*)krealloc(
kbd_buffer, kbd_bufsize); // FIXME: We should probably not be calling realloc every time a key is pressed.
kbd_buffer[kbd_bufsize - 1] = c;
}

View File

@ -1,24 +0,0 @@
#include "fs/devices/Uptime.h"
#include "std/stdio.h"
#include "std/stdlib.h"
#include "std/string.h"
#include "thread/PIT.h"
VFS::Node* UptimeDevice::create_new(const char* devname)
{
VFS::Node* dev = new VFS::Node;
dev->read_func = UptimeDevice::read;
dev->inode = 0;
dev->length = 0;
dev->type = VFS_DEVICE;
dev->flags = 0;
strncpy(dev->name, devname, sizeof(dev->name));
return dev;
}
ssize_t UptimeDevice::read(VFS::Node* node, size_t, size_t size, char* buffer)
{
if (!node) return -1;
snprintf(buffer, size + 1, "%ld", PIT::ms_since_boot); // FIXME: Support offseting this read
return (ssize_t)size;
}

View File

@ -1,9 +1,9 @@
#define MODULE "gdt"
#include "gdt/GDT.h"
#include "kassert.h"
#include "log/Log.h"
#include "memory/MemoryManager.h"
#include "std/assert.h"
#include "std/string.h"
#include <stdint.h>

View File

@ -6,6 +6,7 @@
#include "init/InitRD.h"
#include "interrupts/Interrupts.h"
#include "io/Serial.h"
#include "kassert.h"
#include "log/Log.h"
#include "memory/MemoryManager.h"
#include "memory/PMM.h"
@ -15,7 +16,6 @@
#include "rand/Mersenne.h"
#include "render/Framebuffer.h"
#include "render/TextRenderer.h"
#include "std/assert.h"
#include "std/string.h"
extern BOOTBOOT bootboot;

View File

@ -2,12 +2,12 @@
#include "init/InitRD.h"
#include "bootboot.h"
#include "errno.h"
#include "fs/VFS.h"
#include "io/Serial.h"
#include "log/Log.h"
#include "memory/MemoryManager.h"
#include "misc/utils.h"
#include "std/errno.h"
#include "std/stdlib.h"
#include "std/string.h"
@ -116,8 +116,8 @@ void InitRD::for_each(void (*callback)(File& f))
}
}
#define INITRD_MAX_FILES_IN_DIR 16
#define INITRD_MAX_FILES 64
#define INITRD_MAX_FILES_IN_DIR 8
#define INITRD_MAX_FILES 32
namespace InitRD
{
@ -154,13 +154,13 @@ void initrd_for_each_dir(void (*callback)(InitRD::Directory& f))
}
}
static InitRD::File files[INITRD_MAX_FILES];
static InitRD::File files[32];
static uint32_t total_files = 0;
static InitRD::Directory dirs[INITRD_MAX_FILES];
static InitRD::Directory dirs[32];
static uint32_t total_dirs = 0;
static VFS::Node nodes[INITRD_MAX_FILES + (INITRD_MAX_FILES - 1)]; // One of the dirs is the initrd_root
static VFS::Node nodes[63]; // One of the dirs is the initrd_root
static uint32_t total_nodes = 0;
ssize_t initrd_read(VFS::Node* node, size_t offset, size_t length, char* buffer)
@ -186,15 +186,6 @@ VFS::Node* initrd_scan_dir(VFS::Node* node, const char* filename)
return 0;
}
VFS::Node* initrd_read_dir(VFS::Node* node, long offset)
{
if (!node) return 0;
if (node->inode >= total_dirs) return 0;
InitRD::Directory dir = dirs[node->inode];
if (offset >= dir.entries) return 0;
return dir.files[offset];
}
int initrd_mkdir(VFS::Node* node, const char* name) // FIXME: Return proper error numbers.
{
if (total_dirs >= 32)
@ -231,7 +222,6 @@ int initrd_mkdir(VFS::Node* node, const char* name) // FIXME: Return proper erro
dir.entries = 0;
dirs[total_dirs++] = dir; // FIXME: Right now this isn't of worry, but there is a possibility for a TOCTOU bug here.
// Should use a spinlock or something.
node->length++;
parent.files[parent.entries++] = &new_node;
return 0;
}
@ -280,13 +270,10 @@ static bool initrd_register_dir(InitRD::Directory& dir, uint64_t inode)
node.length = 0;
node.type = VFS_DIRECTORY;
node.mkdir_func = initrd_mkdir;
node.readdir_func = initrd_read_dir;
node.length = 0;
strncpy(node.name, buffer, sizeof(node.name));
strncpy(dir.name, buffer, sizeof(dir.name));
parent.files[parent.entries++] = &node;
current_node->length++;
kfree(buffer);
return true;
@ -345,7 +332,6 @@ static bool initrd_register_file(InitRD::File& f, uint64_t inode)
strncpy(f.name, buffer, sizeof(f.name));
parent.files[parent.entries++] = &node;
current_node->length++;
kfree(buffer);
return true;
}
@ -359,20 +345,12 @@ static bool initrd_register_file(InitRD::File& f, uint64_t inode)
static void initrd_scan()
{
initrd_for_each_dir([](InitRD::Directory& dir) {
if (total_dirs >= 32)
{
kwarnln("Failed to register directory %s: Too many directories in initrd", dir.name);
return;
}
if (total_dirs >= 32) return;
uint64_t inode = total_dirs;
if (initrd_register_dir(dir, inode)) dirs[total_dirs++] = dir;
});
InitRD::for_each([](InitRD::File& f) {
if (total_files >= 32)
{
kwarnln("Failed to register file %s: Too many files in initrd", f.name);
return;
}
if (total_files >= 32) return;
uint64_t inode = total_files;
if (initrd_register_file(f, inode)) files[total_files++] = f;
});
@ -389,7 +367,6 @@ static void initrd_initialize_root()
strncpy(root.name, "initrd", sizeof(root.name));
initrd_root.find_func = initrd_scan_dir;
initrd_root.mkdir_func = initrd_mkdir;
initrd_root.readdir_func = initrd_read_dir;
}
void InitRD::init()
@ -398,10 +375,8 @@ void InitRD::init()
(void*)bootboot.initrd_ptr, Utilities::get_blocks_from_size(PAGE_SIZE, bootboot.initrd_size));
kdbgln("physical base at %lx, size %lx, mapped to %p", bootboot.initrd_ptr, bootboot.initrd_size, initrd_base);
kdbgln("total blocks: %ld", get_total_blocks());
void* leak = kmalloc(4); // leak some memory so that kmalloc doesn't continously allocate and free pages
initrd_initialize_root();
initrd_scan();
VFS::mount_root(&initrd_root);
initrd_initialized = true;
kfree(leak);
}

View File

@ -4,10 +4,10 @@
#include "interrupts/IRQ.h"
#include "interrupts/Interrupts.h"
#include "io/Serial.h"
#include "kassert.h"
#include "log/Log.h"
#include "misc/hang.h"
#include "panic/Panic.h"
#include "std/assert.h"
#include "std/stdio.h"
#include "sys/Syscall.h"
#include "thread/Scheduler.h"
@ -51,6 +51,8 @@ extern "C" void common_handler(Context* context)
StackTracer tracer(context->rbp);
tracer.trace_with_ip(context->rip);
hang(); // FIXME: Remove this when multiple address spaces are working.
Scheduler::task_misbehave(context, -3);
}
}

View File

@ -1,8 +1,8 @@
#define MODULE "idt"
#include "interrupts/IDT.h"
#include "kassert.h"
#include "log/Log.h"
#include "std/assert.h"
struct IDTEntry
{

View File

@ -1,11 +1,10 @@
#define MODULE "irq"
#include "interrupts/IRQ.h"
#include "fs/devices/Keyboard.h"
#include "io/IO.h"
#include "io/PIC.h"
#include "log/Log.h"
#include "misc/Scancodes.h"
#include "misc/reboot.h"
#include "rand/Init.h"
#include "std/stdio.h"
#include "thread/PIT.h"
@ -20,11 +19,10 @@ void IRQ::interrupt_handler(Context* context)
Scheduler::task_tick(context);
break;
case 1: {
unsigned char scancode = IO::inb(0x60);
bool ignore = false;
char key = translate_scancode(scancode, &ignore);
if (ignore) break;
KeyboardDevice::append(key);
[[maybe_unused]] volatile unsigned char scancode = IO::inb(0x60);
kdbgln("Keyboard key pressed/released, seconds since boot: %ld.%ld", PIT::ms_since_boot / 1000,
PIT::ms_since_boot % 1000);
reboot();
break;
}
default: kwarnln("Unhandled IRQ: %ld", context->irq_number); break;

View File

@ -2,7 +2,6 @@
#include "io/Serial.h"
#include "std/stdio.h"
#include "thread/PIT.h"
#include "thread/Scheduler.h"
#include <stdarg.h>
static int level_mask = 15;
@ -23,13 +22,7 @@ static void log_backend_serial(const char* function, LogLevel level, const char*
va_list ap;
va_copy(ap, origin);
Serial::reset_color();
if (Scheduler::current_task() && Scheduler::current_task()->id)
{
Task* current_task = Scheduler::current_task();
printf("[%ld.%ld] (%s %ld) %s: ", PIT::ms_since_boot / 1000, PIT::ms_since_boot % 1000, current_task->name,
current_task->id, function);
}
else { printf("[%ld.%ld] (kernel) %s: ", PIT::ms_since_boot / 1000, PIT::ms_since_boot % 1000, function); }
printf("[%ld.%ld] %s: ", PIT::ms_since_boot / 1000, PIT::ms_since_boot % 1000, function);
switch (level)
{
case LogLevel::WARN: Serial::set_color(Color::Yellow); break;

View File

@ -9,11 +9,11 @@
#include "interrupts/Install.h"
#include "interrupts/Interrupts.h"
#include "io/PIC.h"
#include "kassert.h"
#include "log/Log.h"
#include "memory/Memory.h"
#include "memory/MemoryMap.h"
#include "misc/hang.h"
#include "std/assert.h"
#include "std/stdlib.h"
#include "thread/PIT.h"
#include "thread/Scheduler.h"
@ -57,7 +57,7 @@ extern "C" void _start()
ASSERT(Scheduler::load_user_task("/bin/init") > 0);
#endif
Scheduler::add_kernel_task("[reaper]", []() {
Scheduler::add_kernel_task("[moon-reaper]", []() {
while (1)
{
sleep(400);

View File

@ -12,7 +12,6 @@ AddressSpace AddressSpace::create()
{
AddressSpace result;
result.m_pml4 = (PageTable*)PMM::request_page();
memset(result.m_pml4, 0, PAGE_SIZE);
VMM::install_kernel_page_directory_into_address_space(result);
return move(result);
}
@ -127,26 +126,16 @@ void AddressSpace::clear()
pages_freed++;
PMM::free_page(pdp);
}
memset(m_pml4, 0, PAGE_SIZE);
VMM::install_kernel_page_directory_into_address_space(*this);
kdbgln("Reclaimed %ld pages from address space!", pages_freed);
}
static PageTable* try_clone_page_table(PageTable* source)
{
PageTable* dst = (PageTable*)PMM::request_page();
if (PMM_DID_FAIL(dst)) { return 0; }
memcpy(dst, source, sizeof(PageTable));
return dst;
}
AddressSpace AddressSpace::clone() // FIXME: Add out-of-memory checks to this function.
{
AddressSpace result;
result.m_pml4 = try_clone_page_table(m_pml4);
result.m_pml4 = (PageTable*)PMM::request_page();
if (!result.m_pml4) return result;
memcpy(result.m_pml4, m_pml4, PAGE_SIZE);
for (int i = 0; i < 512; i++)
{
PageDirectoryEntry& pdp_pde = m_pml4->entries[i];
@ -154,22 +143,14 @@ AddressSpace AddressSpace::clone() // FIXME: Add out-of-memory checks to this fu
if (!pdp_pde.present) continue;
if (pdp_pde.larger_pages)
{
void* cloned = try_clone_page_table((PageTable*)pdp_pde.get_address());
if (!cloned)
{
cloned_pdp_pde.present = false;
continue;
}
void* cloned = PMM::request_page();
memcpy(cloned, (void*)pdp_pde.get_address(), PAGE_SIZE);
cloned_pdp_pde.set_address((uint64_t)cloned);
continue;
}
PageTable* pdp = (PageTable*)pdp_pde.get_address();
PageTable* cloned_pdp = try_clone_page_table(pdp);
if (!cloned_pdp)
{
cloned_pdp_pde.present = false;
continue;
}
PageTable* cloned_pdp = (PageTable*)PMM::request_page();
memcpy(cloned_pdp, pdp, PAGE_SIZE);
cloned_pdp_pde.set_address((uint64_t)cloned_pdp);
for (int j = 0; j < 511; j++) // skip the last page directory, it's the kernel one
{
@ -178,22 +159,14 @@ AddressSpace AddressSpace::clone() // FIXME: Add out-of-memory checks to this fu
if (!pd_pde.present) continue;
if (pd_pde.larger_pages)
{
void* cloned = try_clone_page_table((PageTable*)pd_pde.get_address());
if (!cloned)
{
cloned_pd_pde.present = false;
continue;
}
void* cloned = PMM::request_page();
memcpy(cloned, (void*)pd_pde.get_address(), PAGE_SIZE);
cloned_pd_pde.set_address((uint64_t)cloned);
continue;
}
PageTable* pd = (PageTable*)pd_pde.get_address();
PageTable* cloned_pd = try_clone_page_table(pd);
if (!cloned_pd)
{
cloned_pd_pde.present = false;
continue;
}
PageTable* cloned_pd = (PageTable*)PMM::request_page();
memcpy(cloned_pd, pd, PAGE_SIZE);
cloned_pd_pde.set_address((uint64_t)cloned_pd);
for (int k = 0; k < 512; k++)
{
@ -202,34 +175,22 @@ AddressSpace AddressSpace::clone() // FIXME: Add out-of-memory checks to this fu
if (!pt_pde.present) continue;
if (pt_pde.larger_pages)
{
void* cloned = try_clone_page_table((PageTable*)pt_pde.get_address());
if (!cloned)
{
cloned_pt_pde.present = false;
continue;
}
void* cloned = PMM::request_page();
memcpy(cloned, (void*)pt_pde.get_address(), PAGE_SIZE);
cloned_pt_pde.set_address((uint64_t)cloned);
continue;
}
PageTable* pt = (PageTable*)pt_pde.get_address();
PageTable* cloned_pt = try_clone_page_table(pt);
if (!cloned_pt)
{
cloned_pt_pde.present = false;
continue;
}
PageTable* cloned_pt = (PageTable*)PMM::request_page();
memcpy(cloned_pt, pt, PAGE_SIZE);
cloned_pt_pde.set_address((uint64_t)cloned_pt);
for (int l = 0; l < 512; l++)
{
PageDirectoryEntry& pde = pt->entries[l];
PageDirectoryEntry& cloned_pde = cloned_pt->entries[l];
if (!pde.present) continue;
void* cloned = try_clone_page_table((PageTable*)pde.get_address());
if (!cloned)
{
cloned_pde.present = false;
continue;
}
void* cloned = PMM::request_page();
memcpy(cloned, (void*)pde.get_address(), PAGE_SIZE);
cloned_pde.set_address((uint64_t)cloned);
continue;
}

View File

@ -2,8 +2,6 @@
#include "memory/KernelHeap.h"
#include "assert.h"
#include "log/Log.h"
#include "std/string.h"
#ifndef PAGE_SIZE
#define PAGE_SIZE 4096
@ -11,13 +9,10 @@
static uint8_t page_bitmap[2048];
static int64_t kheap_free = sizeof(page_bitmap) * 8 * PAGE_SIZE;
static int64_t kheap_used = 0;
#define ALLOC_BASE 0xfffffffff8000000
#define ALLOC_END 0xfffffffffc000000
// static uint64_t start_index = 0;
static uint64_t start_index = 0;
static bool bitmap_read(uint64_t index)
{
@ -32,28 +27,13 @@ static void bitmap_set(uint64_t index, bool value)
if (value) { page_bitmap[byteIndex] |= bitIndexer; }
}
void KernelHeap::clear()
{
memset(page_bitmap, 0, sizeof(page_bitmap));
kinfoln("page bitmap located at %p", (void*)page_bitmap);
}
uint64_t KernelHeap::request_virtual_page()
{
for (uint64_t index = 0; index < sizeof(page_bitmap) * 8; index++)
for (uint64_t index = start_index; index < sizeof(page_bitmap) * 8; index++)
{
if (bitmap_read(index)) continue;
bitmap_set(index, true);
// start_index = index + 1;
#ifdef KHEAP_DEBUG
kinfoln("allocating one page for caller %p, returning %lx", __builtin_return_address(0),
ALLOC_BASE + (index * PAGE_SIZE));
#endif
kheap_free -= PAGE_SIZE;
kheap_used += PAGE_SIZE;
#ifdef KHEAP_DEBUG
dump_usage();
#endif
start_index = index + 1;
return ALLOC_BASE + (index * PAGE_SIZE);
}
@ -64,7 +44,7 @@ uint64_t KernelHeap::request_virtual_pages(uint64_t count)
{
uint64_t contiguous = 0;
uint64_t contiguous_start = 0;
for (uint64_t index = 0; index < sizeof(page_bitmap) * 8; index++)
for (uint64_t index = start_index; index < sizeof(page_bitmap) * 8; index++)
{
if (bitmap_read(index))
{
@ -81,15 +61,6 @@ uint64_t KernelHeap::request_virtual_pages(uint64_t count)
if (contiguous == count)
{
for (uint64_t i = 0; i < count; i++) bitmap_set(contiguous_start + i, true);
#ifdef KHEAP_DEBUG
kinfoln("allocating %lu pages for caller %p, returning %lx", count, __builtin_return_address(0),
ALLOC_BASE + (contiguous_start * PAGE_SIZE));
#endif
kheap_free -= (count * PAGE_SIZE);
kheap_used += (count * PAGE_SIZE);
#ifdef KHEAP_DEBUG
dump_usage();
#endif
return ALLOC_BASE + (contiguous_start * PAGE_SIZE);
}
}
@ -102,15 +73,7 @@ void KernelHeap::free_virtual_page(uint64_t address)
if (address < ALLOC_BASE || address >= ALLOC_END) return;
uint64_t index = (address - ALLOC_BASE) / PAGE_SIZE;
bitmap_set(index, false);
#ifdef KHEAP_DEBUG
kinfoln("releasing one page for caller %p, %lx", __builtin_return_address(0), address);
#endif
kheap_free += PAGE_SIZE;
kheap_used -= PAGE_SIZE;
#ifdef KHEAP_DEBUG
dump_usage();
#endif
// if (start_index > index) start_index = index;
if (start_index > index) start_index = index;
}
void KernelHeap::free_virtual_pages(uint64_t address, uint64_t count)
@ -118,19 +81,5 @@ void KernelHeap::free_virtual_pages(uint64_t address, uint64_t count)
if (address < ALLOC_BASE || address >= ALLOC_END) return;
uint64_t index = (address - ALLOC_BASE) / PAGE_SIZE;
for (uint64_t i = 0; i < count; i++) { bitmap_set(index + i, false); }
#ifdef KHEAP_DEBUG
kinfoln("releasing %lu pages for caller %p, %lx", count, __builtin_return_address(0), address);
#endif
kheap_free += (count * PAGE_SIZE);
kheap_used -= (count * PAGE_SIZE);
#ifdef KHEAP_DEBUG
dump_usage();
#endif
// if (start_index > index) start_index = index;
}
void KernelHeap::dump_usage()
{
kinfoln("Used: %ld KB", kheap_used / 1024);
kinfoln("Free: %ld KB", kheap_free / 1024);
if (start_index > index) start_index = index;
}

View File

@ -3,15 +3,14 @@
#include "log/Log.h"
#endif
#include "kassert.h"
#include "memory/KernelHeap.h"
#include "memory/MemoryManager.h"
#include "memory/PMM.h"
#include "memory/VMM.h"
#include "std/assert.h"
void MemoryManager::init()
{
KernelHeap::clear();
PMM::init();
VMM::init();
PMM::map_bitmap_to_virtual();
@ -25,7 +24,6 @@ void* MemoryManager::get_mapping(void* physicalAddress, int flags)
#ifdef MM_DEBUG
kwarnln("No kernel heap space (virtual address space from -128M to -64M) left");
#endif
KernelHeap::dump_usage();
return 0;
}
VMM::map(virtualAddress, (uint64_t)physicalAddress, flags);
@ -41,7 +39,6 @@ void* MemoryManager::get_unaligned_mapping(void* physicalAddress, int flags)
#ifdef MM_DEBUG
kwarnln("No kernel heap space (virtual address space from -128M to -64M) left");
#endif
KernelHeap::dump_usage();
return 0;
}
VMM::map(virtualAddress, (uint64_t)physicalAddress - offset, flags);
@ -61,7 +58,6 @@ void* MemoryManager::get_unaligned_mappings(void* physicalAddress, uint64_t coun
"-64M)",
count);
#endif
KernelHeap::dump_usage();
return 0;
}
for (uint64_t i = 0; i < count; i++)
@ -101,7 +97,6 @@ void* MemoryManager::get_page(int flags)
#ifdef MM_DEBUG
kwarnln("No kernel heap space (virtual address space from -128M to -64M) left");
#endif
KernelHeap::dump_usage();
return 0;
}
return get_page_at(virtualAddress, flags);
@ -142,7 +137,6 @@ void* MemoryManager::get_pages(uint64_t count, int flags)
#ifdef MM_DEBUG
kwarnln("No kernel heap space (virtual address space from -128M to -64M) left");
#endif
KernelHeap::dump_usage();
return 0; // Out of virtual address in the kernel heap range (-128M to -64M). This should be difficult to
// achieve...
}
@ -169,6 +163,9 @@ void* MemoryManager::get_pages_at(uint64_t addr, uint64_t count, int flags)
return 0;
}
VMM::map(addr + (i * PAGE_SIZE), (uint64_t)physicalAddress, flags);
#ifdef MM_DEBUG
kdbgln("allocating virtual %lx, physical %p", addr + (i * PAGE_SIZE), physicalAddress);
#endif
}
return (void*)addr;
}
@ -186,6 +183,9 @@ void MemoryManager::release_pages(void* pages, uint64_t count)
uint64_t physicalAddress = VMM::get_physical((uint64_t)page);
ASSERT(physicalAddress != UINT64_MAX);
VMM::unmap((uint64_t)page);
#ifdef MM_DEBUG
kdbgln("releasing virtual %p, physical %lx", page, physicalAddress);
#endif
PMM::free_page((void*)physicalAddress);
}
KernelHeap::free_virtual_pages((uint64_t)pages, count);

View File

@ -2,11 +2,10 @@
#include "memory/PMM.h"
#include "bootboot.h"
#include "log/Log.h"
#include "kassert.h"
#include "memory/Memory.h"
#include "memory/MemoryManager.h"
#include "misc/utils.h"
#include "std/assert.h"
#include "std/string.h"
extern BOOTBOOT bootboot;
@ -131,11 +130,6 @@ void* PMM::request_pages(uint64_t count)
void PMM::free_page(void* address)
{
uint64_t index = (uint64_t)address / PAGE_SIZE;
if (index > (bitmap_size * 8))
{
kinfoln("attempt to free out-of-range address %p", address);
return;
}
if (!bitmap_read(index)) return;
bitmap_set(index, false);
used_mem -= PAGE_SIZE;

View File

@ -1,10 +1,10 @@
#define MODULE "vmm"
#include "memory/VMM.h"
#include "kassert.h"
#include "log/Log.h"
#include "memory/PMM.h"
#include "misc/utils.h"
#include "std/assert.h"
#include "std/string.h"
#include "utils/Addresses.h"
#include "utils/Registers.h"
@ -281,8 +281,7 @@ void VMM::install_kernel_page_directory_into_address_space(AddressSpace& space)
if (!space_last_pdp_pde.present)
{
space_last_pdp = (PageTable*)PMM::request_page(); // FIXME: Add out-of-memory checks.
memset(space_last_pdp, 0, PAGE_SIZE);
space_last_pdp = (PageTable*)PMM::request_page();
space_last_pdp_pde.present = true;
space_last_pdp_pde.read_write = true;

View File

@ -1,168 +0,0 @@
#include "misc/Scancodes.h"
#define SCANCODE_EXTENDED 0xE0
bool scancode_filter_released(unsigned char* scancode)
{
if (*scancode > 0x80)
{
*scancode -= 0x80;
return true;
}
return false;
}
static bool next_key_ignored = false; // FIXME: Do not ignore extended scancodes.
static bool left_shifted = false;
static bool right_shifted = false;
static bool capslock = false;
static bool should_shift()
{
if (capslock) return !(left_shifted || right_shifted);
return left_shifted || right_shifted;
}
#define SCANCODE_LEFT_SHIFT 0x2A
#define SCANCODE_RIGHT_SHIFT 0x36
#define SCANCODE_CAPS_LOCK 0x3A
#define SCANCODE_LEFT_CONTROL 0x1D
#define SCANCODE_TAB 0x0F
#define SCANCODE_LEFT_ALT 0x38
#define SCANCODE_F11 0x57
#define SCANCODE_F12 0x58
static bool should_ignore_key(char scancode)
{
return (scancode > 0x3A && scancode < 0x47) || scancode == SCANCODE_LEFT_CONTROL || scancode == SCANCODE_TAB ||
scancode == SCANCODE_LEFT_ALT || scancode == SCANCODE_F11 || scancode == SCANCODE_F12;
}
char keys_normal[] = {
'\0',
'\1', // escape
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b',
'\0', // tab
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n',
'\0', // left ctrl
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`',
'\0', // left shift
'\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/',
'\0', // right shift
'*', // keypad *
'\0', // left alt
' ',
'\0', // caps lock
'\0', // f1
'\0', // f2
'\0', // f3
'\0', // f4
'\0', // f5
'\0', // f6
'\0', // f7
'\0', // f8
'\0', // f9
'\0', // f10
'\0', // num lock
'\0', // scroll lock
'7', // keypad 7
'8', // keypad 8
'9', // keypad 9
'-', // keypad -
'4', // keypad 4
'5', // keypad 5
'6', // keypad 6
'+', // keypad +
'1', // keypad 1
'2', // keypad 2
'3', // keypad 3
'0', // keypad 0
'.', // keypad .
};
char keys_shifted[] = {
'\0',
'\1', // escape
'!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '\b',
'\0', // tab
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n',
'\0', // left ctrl
'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~',
'\0', // left shift
'|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?',
'\0', // right shift
'*', // keypad *
'\0', // left alt
' ',
'\0', // caps lock
'\0', // f1
'\0', // f2
'\0', // f3
'\0', // f4
'\0', // f5
'\0', // f6
'\0', // f7
'\0', // f8
'\0', // f9
'\0', // f10
'\0', // num lock
'\0', // scroll lock
'7', // keypad 7
'8', // keypad 8
'9', // keypad 9
'-', // keypad -
'4', // keypad 4
'5', // keypad 5
'6', // keypad 6
'+', // keypad +
'1', // keypad 1
'2', // keypad 2
'3', // keypad 3
'0', // keypad 0
'.', // keypad .
};
char translate_scancode(unsigned char scancode, bool* ignore)
{
if (next_key_ignored)
{
next_key_ignored = false;
*ignore = true;
return 0;
}
if (scancode == SCANCODE_EXTENDED)
{
next_key_ignored = true;
*ignore = true;
return 0;
}
bool released = scancode_filter_released(&scancode);
if (scancode == SCANCODE_CAPS_LOCK)
{
if (!released) { capslock = !capslock; }
*ignore = true;
return 0;
}
if (scancode == SCANCODE_LEFT_SHIFT)
{
left_shifted = !released;
*ignore = true;
return 0;
}
if (scancode == SCANCODE_RIGHT_SHIFT)
{
right_shifted = !released;
*ignore = true;
return 0;
}
if (released || should_ignore_key(scancode))
{
*ignore = true;
return 0;
}
*ignore = false;
if (should_shift()) { return keys_shifted[scancode]; }
return keys_normal[scancode];
}

View File

@ -8,7 +8,7 @@
#endif
#ifndef MOON_MINOR
#define MOON_MINOR 13
#define MOON_MINOR 12
#endif
#ifndef _MOON_SUFFIX

View File

@ -5,34 +5,12 @@
#include "interrupts/IDT.h"
#include "io/PIC.h"
#include "log/Log.h"
#include "memory/VMM.h"
#include "misc/MSR.h"
#include "render/Framebuffer.h"
#include "render/TextRenderer.h"
#include "std/stdio.h"
#include "thread/Scheduler.h"
#include "trace/StackTracer.h"
static bool g_is_in_panic = false;
static bool g_is_in_double_panic = false;
static void panic_prepare_keyboard_triple_fault()
{
PIC::enable_master(0b11111101); // enable keyboard only
PIC::enable_slave(0b11111111);
IDTR idtr;
idtr.limit = 0x0000;
idtr.offset = 0x0000;
asm volatile(
"lidt %0"
:
: "m"(
idtr)); // when an interrupt arrives, triple-fault (the only interrupt that should come is the keyboard one)
asm volatile("sti");
}
void dump_registers(Context* context)
{
kinfoln("-- Registers:");
@ -45,36 +23,8 @@ void dump_registers(Context* context)
kinfoln("ia32_efer: %lx", MSR::read_from(IA32_EFER_MSR));
}
void fatal_dump_registers(Context* context)
{
printf("-- Possibly Relevant Registers:\n");
printf("rbp: %lx, rsp: %lx, rip: %lx, cs: %lx, ss: %lx, rflags: %lx, cr2: %lx, error code: %lx\n", context->rbp,
context->rsp, context->rip, context->cs, context->ss, context->rflags, context->cr2, context->error_code);
}
[[noreturn]] void __panic_fatal_stub(Context* context)
{
if (context) fatal_dump_registers(context);
printf("-- No stack trace available\n");
KernelLog::enable_log_backend(Backend::Console);
KernelLog::toggle_log_backend(
Backend::Console); // disable console logging, as we can page fault while writing to the framebuffer.
Scheduler::current_task()->id = 0; // we're panicking, we don't even care anymore. This is so KernelLog shows
// (kernel) instead of (taskname: PID) in the log.
panic_prepare_keyboard_triple_fault();
printf("Press any key to restart.\n");
while (1) asm volatile("hlt");
}
[[noreturn]] void __panic_stub(Context* context)
{
VMM::switch_back_to_kernel_address_space();
VMM::apply_address_space();
if (context) dump_registers(context);
if (InitRD::is_initialized())
@ -96,7 +46,21 @@ void fatal_dump_registers(Context* context)
}
else { kinfoln("-- No stack trace available"); }
panic_prepare_keyboard_triple_fault();
PIC::enable_master(0b11111101); // enable keyboard only
PIC::enable_slave(0b11111111);
IDTR idtr;
idtr.limit = 0x0000;
idtr.offset = 0x0000;
asm volatile(
"lidt %0"
:
: "m"(
idtr)); // when an interrupt arrives, triple-fault (the only interrupt that should come is the keyboard one)
asm volatile("sti");
kinfoln("Press any key to restart.");
while (1) asm volatile("hlt");
}
@ -105,28 +69,10 @@ extern "C" [[noreturn]] bool __do_int_panic(Context* context, const char* file,
{
asm volatile("cli");
if (g_is_in_double_panic)
{
panic_prepare_keyboard_triple_fault();
while (1) asm volatile("hlt");
}
if (g_is_in_panic)
{
g_is_in_double_panic = true;
printf("Kernel panic while panicking (showing vital information only) at %s, line %d: %s\n", file, line,
message);
__panic_fatal_stub(context);
}
g_is_in_panic = true;
KernelLog::enable_log_backend(Backend::Console);
TextRenderer::reset();
framebuffer0.clear(Color::Black);
if (context->number >= 0x20 && context->number < 0x30) { PIC::send_eoi((uint8_t)(context->irq_number & 0xFF)); }
Task* task;
@ -143,28 +89,10 @@ extern "C" [[noreturn]] bool __do_panic(const char* file, int line, const char*
{
asm volatile("cli");
if (g_is_in_double_panic)
{
panic_prepare_keyboard_triple_fault();
while (1) asm volatile("hlt");
}
if (g_is_in_panic)
{
g_is_in_double_panic = true;
printf("Kernel panic while panicking (showing vital information only) at %s, line %d: %s\n", file, line,
message);
__panic_fatal_stub(nullptr);
}
g_is_in_panic = true;
KernelLog::enable_log_backend(Backend::Console);
TextRenderer::reset();
framebuffer0.clear(Color::Black);
Task* task;
if ((task = Scheduler::current_task()))
{

View File

@ -1,7 +1,7 @@
#define MODULE "rand"
#include "rand/Mersenne.h"
#include "std/assert.h"
#include "kassert.h"
#include <stddef.h>
typedef uint64_t word_t;

View File

@ -111,32 +111,34 @@ void* memcpy(void* dest, const void* src, size_t n)
return dest;
}
void* memset(void* buf, int c, size_t n)
void* memset(void* dest, int c, size_t n)
{
for (size_t i = 0; i < n; ++i) { *((char*)buf + i) = (char)c; }
return buf;
for (size_t i = 0; i < n; ++i) { *((char*)dest + i) = (char)c; }
return dest;
}
int memcmp(const void* a, const void* b, size_t n)
{
const char* _a = (const char*)a;
const char* _b = (const char*)b;
for (; n && _a == _b; n--, _a++, _b++)
;
if (!n) return 0;
const unsigned char* ap = (const unsigned char*)a;
const unsigned char* bp = (const unsigned char*)b;
while (--n && *ap == *bp)
{
ap++;
bp++;
}
return *ap - *bp;
if (*_a > *_b) return 1;
return -1;
}
void* memmove(void* dest, const void* src, size_t n)
void* memmove(void* dest, void* src, size_t n)
{
if (dest == src) return dest;
if (dest > src)
for (long i = n - 1; i >= 0; i++) { *((char*)dest + i) = *((const char*)src + i); }
{
for (long i = n - 1; i >= 0; i++) { *((char*)dest + i) = *((char*)src + i); }
}
else
for (long i = 0; i < (long)n; i++) { *((char*)dest + i) = *((const char*)src + i); }
{
for (long i = 0; i < (long)n; i++) { *((char*)dest + i) = *((char*)src + i); }
}
return dest;
}

View File

@ -1,7 +1,7 @@
#include "sys/Syscall.h"
#include "errno.h"
#include "io/Serial.h"
#include "memory/VMM.h"
#include "std/errno.h"
#include "std/string.h"
#include "thread/Scheduler.h"
@ -16,7 +16,7 @@ void Syscall::entry(Context* context)
case SYS_sleep: sys_sleep(context, context->rdi); break;
case SYS_write: sys_write(context, (int)context->rdi, context->rsi, (const char*)context->rdx); break;
case SYS_paint: sys_paint(context, context->rdi, context->rsi, context->rdx, context->r10, context->r8); break;
case SYS_getprocid: sys_getprocid(context, (int)context->rdi); break;
case SYS_getpid: sys_getpid(context); break;
case SYS_mmap: sys_mmap(context, (void*)context->rdi, context->rsi, (int)context->rdx); break;
case SYS_munmap: sys_munmap(context, (void*)context->rdi, context->rsi); break;
case SYS_open: sys_open(context, (const char*)context->rdi, (int)context->rsi); break;
@ -29,14 +29,14 @@ void Syscall::entry(Context* context)
case SYS_clock: sys_clock(context); break;
case SYS_mkdir: sys_mkdir(context, (const char*)context->rdi); break;
case SYS_fork: sys_fork(context); break;
case SYS_waitpid: sys_waitpid(context, (long)context->rdi, (int*)context->rsi, (int)context->rdx); break;
case SYS_access: sys_access(context, (const char*)context->rdi, (int)context->rsi); break;
case SYS_fstat: sys_fstat(context, (int)context->rdi, (struct stat*)context->rsi); break;
case SYS_pstat: sys_pstat(context, (long)context->rdi, (struct pstat*)context->rsi); break;
case SYS_getdents:
sys_getdents(context, (int)context->rdi, (struct luna_dirent*)context->rsi, (size_t)context->rdx);
break;
default: context->rax = -ENOSYS; break;
}
VMM::exit_syscall_context();
}
char* Syscall::strdup_from_user(const char* user_string) // FIXME: This function is a little hacky.
{
uint64_t phys = VMM::get_physical((uint64_t)user_string);
if (phys == (uint64_t)-1) { return nullptr; }
return strdup((const char*)phys);
}

View File

@ -1,10 +0,0 @@
#include "sys/UserMemory.h"
#include "std/string.h"
char* strdup_from_user(
const char* user_string) // FIXME: This function is a little hacky. Use the obtain_user_ref and similar functions.
{
uint64_t phys = VMM::get_physical((uint64_t)user_string);
if (phys == (uint64_t)-1) { return nullptr; }
return strdup((const char*)phys);
}

View File

@ -1,61 +0,0 @@
#define MODULE "dir"
#include "luna/dirent.h"
#include "fs/VFS.h"
#include "interrupts/Context.h"
#include "std/errno.h"
#include "std/string.h"
#include "sys/UserMemory.h"
#include "thread/Scheduler.h"
void sys_getdents(Context* context, int fd, struct luna_dirent* buf, size_t count)
{
if (fd < 0 || fd > TASK_MAX_FDS)
{
context->rax = -EBADF;
return;
}
Task* current_task = Scheduler::current_task();
if (!current_task->files[fd].is_open())
{
context->rax = -EBADF;
return;
}
Descriptor& dir = current_task->files[fd];
VFS::Node* node = dir.node();
if (node->type != VFS_DIRECTORY)
{
context->rax = -ENOTDIR;
return;
}
size_t nread = 0;
while (count)
{
VFS::Node* entry = VFS::readdir(node, dir.offset());
if (!entry)
{
context->rax = nread;
return;
}
auto* kdirent = obtain_user_ref(buf);
if (!kdirent)
{
context->rax = -EFAULT;
return;
}
kdirent->total = node->length;
kdirent->offset = dir.offset();
kdirent->inode = entry->inode;
strlcpy(kdirent->name, entry->name, sizeof(kdirent->name));
release_user_ref(kdirent);
dir.seek(dir.offset() + 1);
buf++;
nread++;
count--;
}
context->rax = nread;
}

View File

@ -1,15 +1,15 @@
#define MODULE "elf"
#include "sys/elf/ELFLoader.h"
#include "errno.h"
#include "fs/VFS.h"
#include "init/InitRD.h"
#include "kassert.h"
#include "log/Log.h"
#include "memory/Memory.h"
#include "memory/MemoryManager.h"
#include "memory/VMM.h"
#include "misc/utils.h"
#include "std/assert.h"
#include "std/errno.h"
#include "std/stdlib.h"
#include "std/string.h"
#include "sys/elf/ELF.h"

View File

@ -1,16 +1,15 @@
#define MODULE "exec"
#include "errno.h"
#include "interrupts/Interrupts.h"
#include "kassert.h"
#include "log/Log.h"
#include "memory/MemoryManager.h"
#include "memory/PMM.h"
#include "memory/VMM.h"
#include "std/assert.h"
#include "std/errno.h"
#include "std/stdlib.h"
#include "std/string.h"
#include "sys/Syscall.h"
#include "sys/UserMemory.h"
#include "sys/elf/ELFLoader.h"
#include "thread/Scheduler.h"
@ -42,8 +41,6 @@ void sys_fork(Context* context)
child->address_space = parent->address_space.clone();
child->ppid = parent->id;
child->regs.rax = 0;
context->rax = child->id;
@ -58,7 +55,7 @@ void sys_fork(Context* context)
void sys_exec(Context* context, const char* pathname)
{
char* kpathname = strdup_from_user(pathname);
char* kpathname = Syscall::strdup_from_user(pathname);
if (!kpathname)
{
context->rax = -EFAULT;
@ -123,12 +120,6 @@ void sys_exec(Context* context, const char* pathname)
Scheduler::reset_task(task, image);
for (int i = 0; i < TASK_MAX_FDS; i++)
{
Descriptor& file = task->files[i];
if (file.close_on_exec()) { file.close(); }
}
task->restore_context(context);
kfree(kpathname);

View File

@ -1,24 +0,0 @@
#include "std/errno.h"
#include "thread/Scheduler.h"
#define ID_PID 0
#define ID_PPID 1
void sys_getprocid(Context* context, int field)
{
if (field == ID_PID)
{
context->rax = Scheduler::current_task()->id;
return;
}
else if (field == ID_PPID)
{
context->rax = Scheduler::current_task()->ppid;
return;
}
else
{
context->rax = -EINVAL;
return;
}
}

View File

@ -1,12 +1,12 @@
#define MODULE "mem"
#include "errno.h"
#include "interrupts/Context.h"
#include "log/Log.h"
#include "memory/Memory.h"
#include "memory/MemoryManager.h"
#include "memory/VMM.h"
#include "misc/utils.h"
#include "std/errno.h"
#include "thread/Scheduler.h"
#include <stddef.h>

View File

@ -1,7 +1,7 @@
#include "bootboot.h"
#include "errno.h"
#include "interrupts/Context.h"
#include "render/Framebuffer.h"
#include "std/errno.h"
#include <stdint.h>
extern BOOTBOOT bootboot;

View File

@ -1,6 +1,3 @@
#include "memory/VMM.h"
#include "std/errno.h"
#include "sys/UserMemory.h"
#include "thread/Scheduler.h"
void sys_exit(Context* context, int status)
@ -21,4 +18,9 @@ void sys_sleep(Context* context, uint64_t ms)
task->task_sleep = ms;
task->state = task->Sleeping;
Scheduler::task_yield(context);
}
void sys_getpid(Context* context)
{
context->rax = Scheduler::current_task()->id;
}

View File

@ -1,44 +0,0 @@
#include "fs/VFS.h"
#include "interrupts/Context.h"
#include "std/errno.h"
#include "sys/UserMemory.h"
#include "thread/Scheduler.h"
typedef unsigned long off_t;
typedef unsigned short mode_t;
typedef unsigned long ino_t;
struct stat // FIXME: This struct is quite stubbed out.
{
ino_t st_ino;
mode_t st_mode;
off_t st_size;
};
void sys_fstat(Context* context, int fd, struct stat* buf)
{
Task* current_task = Scheduler::current_task();
if (fd < 0 || fd >= TASK_MAX_FDS)
{
context->rax = -EBADF;
return;
}
Descriptor& file = current_task->files[fd];
if (!file.is_open())
{
context->rax = -EBADF;
return;
}
struct stat* kstat = obtain_user_ref(buf);
if (!kstat)
{
context->rax = -EFAULT; // FIXME: The manual doesn't say fstat can return EFAULT, but it seems logical here...
return;
}
VFS::Node* node = file.node();
kstat->st_ino = node->inode;
kstat->st_mode = (mode_t)node->type;
kstat->st_size = node->length;
release_user_ref(kstat);
context->rax = 0;
}

View File

@ -1,29 +1,24 @@
#define MODULE "stdio"
#include "errno.h"
#include "interrupts/Context.h"
#include "io/Serial.h"
#include "log/Log.h"
#include "memory/VMM.h"
#include "render/TextRenderer.h"
#include "std/errno.h"
#include "std/stdlib.h"
#include "sys/Syscall.h"
#include "sys/UserMemory.h"
#include "thread/Scheduler.h"
#include "thread/Task.h"
#define OPEN_READ 1
#define OPEN_WRITE 2
#define OPEN_NONBLOCK 4
#define OPEN_CLOEXEC 8
#define OPEN_DIRECTORY 16
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#define FCNTL_DUPFD 0
#define FCNTL_ISTTY 1
#define FNCTL_DUPFD 0
void sys_fcntl(Context* context, int fd, int command, uintptr_t arg)
{
@ -39,7 +34,7 @@ void sys_fcntl(Context* context, int fd, int command, uintptr_t arg)
return;
}
Descriptor& file = current_task->files[fd];
if (command == FCNTL_DUPFD)
if (command == FNCTL_DUPFD)
{
if ((int)arg < 0 || (int)arg >= TASK_MAX_FDS)
{
@ -57,14 +52,6 @@ void sys_fcntl(Context* context, int fd, int command, uintptr_t arg)
kdbgln("fcntl(F_DUPFD): duplicated fd %d, result is %d", fd, dupfd);
return;
}
else if (command == FCNTL_ISTTY)
{
VFS::Node* node = file.node();
if (node->tty) { context->rax = 1; }
else
context->rax = -ENOTTY;
return;
}
else
{
context->rax = -EINVAL;
@ -158,17 +145,17 @@ void sys_open(Context* context, const char* filename, int flags)
return;
}
char* kfilename = strdup_from_user(filename);
if (!kfilename)
char* kernel_filename = Syscall::strdup_from_user(filename);
if (!kernel_filename)
{
context->rax = -EFAULT;
return;
}
VFS::Node* node = VFS::resolve_path(kfilename);
VFS::Node* node = VFS::resolve_path(kernel_filename);
if (!node)
{
kfree(kfilename);
kfree(kernel_filename);
context->rax = -ENOENT;
return;
}
@ -177,31 +164,19 @@ void sys_open(Context* context, const char* filename, int flags)
bool can_write = (flags & OPEN_WRITE) > 0;
if (!can_read && !can_write)
{
kfree(kfilename);
kfree(kernel_filename);
context->rax = -EINVAL;
return;
}
bool able_to_block = (flags & OPEN_NONBLOCK) == 0;
bool close_on_exec = (flags & OPEN_CLOEXEC) > 0;
bool only_directory = (flags & OPEN_DIRECTORY) > 0;
if (only_directory && node->type != VFS_DIRECTORY)
{
kfree(kfilename);
context->rax = -ENOTDIR;
return;
}
kdbgln("open(): opening %s %s, allocated file descriptor %d", kfilename,
kdbgln("open(): opening %s %s, allocated file descriptor %d", kernel_filename,
(can_read && can_write) ? "rw"
: can_read ? "r-"
: "-w",
fd);
kfree(kfilename);
current_task->files[fd].open(node, can_read, can_write, able_to_block, close_on_exec);
kfree(kernel_filename);
current_task->files[fd].open(node, can_read, can_write);
context->rax = fd;
return;
}
@ -224,22 +199,7 @@ void sys_read(Context* context, int fd, size_t size, char* buffer)
context->rax = -EBADF;
return;
}
if (VFS::would_block(current_task->files[fd].node()))
{
if (!current_task->files[fd].able_to_block())
{
context->rax = -EAGAIN;
return;
}
current_task->state = current_task->Blocking;
current_task->blocking_read_info.fd = fd;
current_task->blocking_read_info.buf = (char*)VMM::get_physical((uint64_t)buffer); // FIXME: Handle errors.
current_task->blocking_read_info.size = size;
return Scheduler::task_yield(context);
}
ssize_t result = current_task->files[fd].read(
size, (char*)VMM::get_physical((uint64_t)buffer)); // FIXME: Handle errors, and big buffers which may not be
// across continuous physical pages.
ssize_t result = current_task->files[fd].read(size, (char*)VMM::get_physical((uint64_t)buffer));
context->rax = (size_t)result;
return;
}
@ -265,7 +225,7 @@ void sys_close(Context* context, int fd)
void sys_mkdir(Context* context, const char* filename)
{
char* kfilename = strdup_from_user(filename);
char* kfilename = Syscall::strdup_from_user(filename);
if (!kfilename)
{
context->rax = -EFAULT;
@ -277,13 +237,4 @@ void sys_mkdir(Context* context, const char* filename)
kfree(kfilename);
context->rax = rc;
}
void sys_access(Context* context, const char* path, int) // FIXME: Use the amode argument.
{
char* kpath = strdup_from_user(path);
if (!VFS::exists(kpath)) { context->rax = -ENOENT; }
else
context->rax = 0;
kfree(kpath);
}

View File

@ -1,20 +1,18 @@
#define MODULE "sched"
#include "thread/Scheduler.h"
#include "errno.h"
#include "interrupts/Interrupts.h"
#include "kassert.h"
#include "log/Log.h"
#include "memory/MemoryManager.h"
#include "memory/PMM.h"
#include "memory/VMM.h"
#include "misc/hang.h"
#include "misc/reboot.h"
#include "misc/utils.h"
#include "panic/Panic.h"
#include "std/assert.h"
#include "std/errno.h"
#include "std/stdlib.h"
#include "std/string.h"
#include "sys/UserMemory.h"
#include "sys/elf/ELFLoader.h"
#include "thread/PIT.h"
#include "thread/Task.h"
@ -46,14 +44,6 @@ template <typename Callback> void sched_for_each_task(Callback callback)
} while (task != base_task);
}
template <typename Callback> void sched_for_each_child(Task* task, Callback callback)
{
sched_for_each_task([&](Task* child) {
if (child->ppid == task->id) { return callback(child); }
return true;
});
}
Task* Scheduler::find_by_pid(uint64_t pid)
{
Task* result = nullptr;
@ -101,8 +91,6 @@ void Scheduler::init()
idle_task.user_task = false;
idle_task.state = idle_task.Idle;
strlcpy(idle_task.name, "[cpu-idle]", sizeof(idle_task.name));
sched_current_task = &idle_task;
frequency = 1000 / PIT::frequency();
@ -114,7 +102,6 @@ void Scheduler::add_kernel_task(const char* taskname, void (*task)(void))
ASSERT(new_task);
new_task->user_task = false;
new_task->id = free_tid++;
new_task->ppid = 0;
new_task->regs.rip = (uint64_t)task;
new_task->allocated_stack =
(uint64_t)MemoryManager::get_pages(TASK_PAGES_IN_STACK); // 16 KB is enough for everyone, right?
@ -141,7 +128,6 @@ Task* Scheduler::create_user_task()
memset(&new_task->regs, 0, sizeof(Context));
new_task->user_task = true;
new_task->id = free_tid++;
new_task->ppid = 0;
new_task->task_sleep = 0;
new_task->task_time = 0;
new_task->cpu_time = 0;
@ -166,11 +152,9 @@ long Scheduler::load_user_task(const char* filename)
ASSERT(new_task);
memset(&new_task->regs, 0, sizeof(Context));
new_task->id = free_tid++;
new_task->ppid = 0;
if (!new_task->allocator.init())
{
delete new_task;
free_tid--;
Interrupts::pop();
return -ENOMEM;
}
@ -189,7 +173,6 @@ long Scheduler::load_user_task(const char* filename)
{
new_task->address_space.destroy();
delete new_task;
free_tid--;
ELFLoader::release_elf_image(image);
VMM::switch_back_to_kernel_address_space();
Interrupts::pop();
@ -262,47 +245,26 @@ void Scheduler::reap_task(Task* task)
Interrupts::pop();
}
for (int i = 0; i < TASK_MAX_FDS; i++) { exiting_task->files[i].close(); }
if (exiting_task->id == (free_tid - 1)) free_tid--; // If we are the last spawned thread, free our PID.
delete exiting_task;
}
void sched_common_exit(Context* context, int64_t status)
{
if (sched_current_task->id == 1) sched_current_task->state = sched_current_task->Exited;
else
sched_current_task->state = sched_current_task->Dying;
sched_current_task->exit_status = status;
if (sched_current_task->id != 1)
{
sched_for_each_child(sched_current_task, [](Task* child) {
if (child->state != child->Exited) child->ppid = 1;
return true;
});
}
else
{
#ifndef RUN_TEST_AS_INIT
reboot();
#else
hang();
#endif
}
Scheduler::task_yield(context);
}
void Scheduler::task_exit(Context* context, int64_t status)
{
ASSERT(Interrupts::is_in_handler());
kdbgln("exit: task %ld finished running, used %ld ms of cpu time", sched_current_task->id,
sched_current_task->cpu_time);
sched_common_exit(context, status);
sched_current_task->state = sched_current_task->Exited;
sched_current_task->exit_status = status;
task_yield(context);
}
void Scheduler::task_misbehave(Context* context, int64_t status)
{
ASSERT(Interrupts::is_in_handler());
kdbgln("exit: task %ld misbehaved, used %ld ms of cpu time", sched_current_task->id, sched_current_task->cpu_time);
sched_common_exit(context, status);
sched_current_task->state = sched_current_task->Exited;
sched_current_task->exit_status = status;
task_yield(context);
}
void Scheduler::reap_tasks()
@ -374,10 +336,10 @@ void Scheduler::task_tick(Context* context)
ASSERT(Interrupts::is_in_handler());
Interrupts::disable();
sched_decrement_sleep_times();
if (sched_current_task->id == 0) return task_yield(context);
sched_current_task->task_time -= frequency;
sched_current_task->cpu_time += frequency;
if (sched_current_task->id == 0) return task_yield(context);
if (sched_current_task->task_time <= 0)
if (sched_current_task->task_time < 0)
{
sched_current_task->task_time = 0;
task_yield(context);
@ -399,14 +361,6 @@ void Scheduler::task_yield(Context* context)
Task* original_task = sched_current_task;
do {
sched_current_task = sched_current_task->next_task;
if (sched_current_task->state == sched_current_task->Blocking)
{
if (!sched_current_task->is_still_blocking())
{
sched_current_task->resume_read();
sched_current_task->state = sched_current_task->Running;
}
}
if (sched_current_task->state == sched_current_task->Running)
{
if (sched_current_task->id != original_task->id || was_idle)
@ -459,104 +413,4 @@ void Scheduler::sleep(unsigned long ms)
Task* Scheduler::current_task()
{
return sched_current_task;
}
void sys_waitpid(Context* context, long pid, int* wstatus,
int) // FIXME: Use the value in options and block if WNOHANG has not been specified.
{
Task* child = nullptr;
if (pid == -1)
{
sched_for_each_child(sched_current_task, [&](Task* task) {
if (task->state == task->Dying)
{
child = task;
return false;
}
return true;
});
if (!child)
{
context->rax = 0; // No child has exited, let's return 0.
return;
}
}
else
{
child = Scheduler::find_by_pid(pid);
if (!child)
{
context->rax = -ESRCH;
return;
}
}
if (child->state != child->Dying) // FIXME: This should block if WNOHANG has not been specified.
{
context->rax = 0;
return;
}
if (wstatus)
{
int* kwstatus = obtain_user_ref(wstatus);
if (kwstatus)
{
*kwstatus = (int)(child->exit_status & 0xff);
release_user_ref(kwstatus);
}
else
{
kinfoln("wstatus ptr is invalid: %p", (void*)wstatus);
child->state = child->Exited;
context->rax = -EFAULT;
return;
}
}
child->state = child->Exited;
context->rax = (long)child->id;
}
struct pstat
{
long pt_pid;
long pt_ppid;
char pt_name[128];
int pt_state;
long pt_time;
};
void sys_pstat(Context* context, long pid, struct pstat* buf)
{
Task* task;
if (pid == -1) task = Scheduler::find_by_pid(free_tid - 1);
else if (pid == 0)
task = &idle_task;
else
task = Scheduler::find_by_pid(pid);
if (!task)
{
context->rax = -ESRCH;
return;
}
if (task->state == task->Exited) // we're just waiting for the reaper to reap it
{
context->rax = -ESRCH;
return;
}
if (buf)
{
struct pstat* kpstat = obtain_user_ref(buf);
if (!kpstat)
{
context->rax = -EFAULT;
return;
}
kpstat->pt_pid = task->id;
kpstat->pt_ppid = task->ppid;
kpstat->pt_state = (int)task->state;
kpstat->pt_time = (long)task->cpu_time;
strlcpy(kpstat->pt_name, task->name, sizeof(kpstat->pt_name));
release_user_ref(kpstat);
}
context->rax = task->id;
return;
}

View File

@ -1,7 +1,4 @@
#define MODULE "sched"
#include "thread/Task.h"
#include "log/Log.h"
#include "memory/VMM.h"
#include "std/string.h"
@ -68,18 +65,4 @@ void Task::switch_to_address_space()
bool Task::has_died()
{
return state == Exited;
}
void Task::resume_read()
{
VMM::switch_back_to_kernel_address_space();
VMM::apply_address_space();
VMM::switch_to_previous_user_address_space();
regs.rax = files[blocking_read_info.fd].read(blocking_read_info.size, blocking_read_info.buf);
VMM::apply_address_space();
}
bool Task::is_still_blocking()
{
return VFS::would_block(files[blocking_read_info.fd].node());
}

View File

@ -24,7 +24,7 @@ typedef struct stackframe
void StackTracer::trace()
{
stackframe* frame = (stackframe*)m_base_pointer;
while (frame && frame->instruction && Memory::is_kernel_address(frame->instruction))
while (frame && frame->instruction)
{
char symbol_name[512];
get_symbol_name(frame->instruction - sizeof(uintptr_t), symbol_name, sizeof(symbol_name));

View File

@ -5,7 +5,7 @@ LIBC_BIN := $(LIBC_DIR)/bin
DESTDIR ?= $(LUNA_BASE)/usr/lib
CFLAGS := -Os -nostdlib -fno-asynchronous-unwind-tables -fno-omit-frame-pointer -pedantic -Wall -Wextra -Werror -Wfloat-equal -Wdisabled-optimization -Wformat=2 -Winit-self -Wmissing-include-dirs -Wswitch-default -Wcast-qual -Wundef -Wcast-align -Wwrite-strings -Wlogical-op -Wredundant-decls -Wshadow -Wconversion
CFLAGS := -Os -nostdlib -fno-omit-frame-pointer -pedantic -Wall -Wextra -Werror -Wfloat-equal -Wdisabled-optimization -Wformat=2 -Winit-self -Wmissing-include-dirs -Wswitch-default -Wcast-qual -Wundef -Wcast-align -Wwrite-strings -Wlogical-op -Wredundant-decls -Wshadow -Wconversion
CXXFLAGS := -fno-rtti -fno-exceptions -Wsign-promo -Wstrict-null-sentinel -Wctor-dtor-privacy
ASMFLAGS := -felf64

View File

@ -6,8 +6,6 @@ extern _fini
extern initialize_libc
extern exit
extern __argv
global _start
_start:
; Set up end of the stack frame linked list.
@ -21,7 +19,7 @@ _start:
call _init
mov rdi, 0 ; argc = 0
mov rsi, __argv ; Dummy argv which is equal to {NULL}
mov rsi, 0 ; argv = 0
call main

View File

@ -1,7 +0,0 @@
#ifndef _BITS_GETPROCID_H
#define _BITS_GETPROCID_H
#define ID_PID 0
#define ID_PPID 1
#endif

View File

@ -5,6 +5,5 @@
#define __lc_align(n) __attribute__((aligned(n)))
#define __lc_deprecated(msg) __attribute__((deprecated(msg)))
#define __lc_unreachable __builtin_unreachable
#define __lc_used __attribute__((used))
#endif

View File

@ -1,55 +0,0 @@
#ifndef _DIRENT_H
#define _DIRENT_H
#include <luna/os-limits.h>
#include <sys/types.h>
struct dirent
{
ino_t d_ino;
off_t d_off;
unsigned short d_reclen;
unsigned char d_type;
char d_name[NAME_MAX];
};
typedef struct
{
int d_dirfd;
} DIR;
#ifdef __cplusplus
extern "C"
{
#endif
/* Opens the directory at path and returns a handle to it, or NULL on error. */
DIR* opendir(const char* path);
/* Returns a new directory handle associated with the file descriptor fd. */
DIR* fdopendir(int fd);
/* Closes the directory stream. */
int closedir(DIR* stream);
/* Reads an entry from the directory stream. The contents of the pointer returned may be overwritten by subsequent
* calls to readdir(). */
struct dirent* readdir(DIR* stream);
/* Returns the file descriptor associated with stream. */
int dirfd(DIR* stream);
/* Positions stream's offset at the start of the directory. */
void rewinddir(DIR* stream);
/* Returns the current offset position for stream. */
long telldir(DIR* stream);
/* Moves stream's read offset to offset, which should be the return value of a previous call to telldir(). */
void seekdir(DIR* stream, long offset);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -6,11 +6,8 @@ extern int errno;
#define EPERM 1 // Operation not permitted
#define ENOENT 2 // No such file or directory
#define ESRCH 3 // No such process
#define EINTR 4 // Interrupted system call. Not implemented.
#define ENOEXEC 8 // Exec format error
#define EBADF 9 // Bad file descriptor
#define EAGAIN 11 // Resource temporarily unavailable
#define ENOMEM 12 // Cannot allocate memory
#define EFAULT 14 // Bad address
#define EEXIST 17 // File exists
@ -18,10 +15,9 @@ extern int errno;
#define EISDIR 21 // Is a directory
#define EINVAL 22 // Invalid argument
#define EMFILE 24 // Too many open files
#define ENOTTY 25 // Inappropriate ioctl for device
#define ENOSPC 28 // No space left on device
#define EPIPE 32 // Broken pipe. Not implemented.
#define ENOSYS 38 // Function not implemented
#define ENOTSUP 95 // Operation not supported
#define ENOTSUP 95 // Operation not supported.
#endif

View File

@ -7,17 +7,9 @@
#define O_WRONLY 2
/* Open for reading and writing. */
#define O_RDWR 3
/* Open without blocking. */
#define O_NONBLOCK 4
/* Close the opened file descriptor on a call to execve(). */
#define O_CLOEXEC 8
/* Refuse to open the file if it is not a directory. */
#define O_DIRECTORY 16
/* Duplicate a file descriptor. */
#define F_DUPFD 0
/* Is a file descriptor a TTY? */
#define F_ISTTY 1
#ifdef __cplusplus
extern "C"

View File

@ -3,69 +3,61 @@
#include <stdint.h>
#define __PRI64_PREFIX "l"
#define PRId8 "d"
#define PRId16 "d"
#define PRId32 "d"
#define PRId64 __PRI64_PREFIX "d"
#define PRIdLEAST8 "d"
#define PRIdLEAST16 "d"
#define PRIdLEAST32 "d"
#define PRIdLEAST64 __PRI64_PREFIX "d"
#define PRIdFAST8 "d"
#define PRIdFAST16 "d"
#define PRIdFAST32 "d"
#define PRIdFAST64 __PRI64_PREFIX "d"
#define PRIdMAX __PRI64_PREFIX "d"
#define PRIdPTR __PRI64_PREFIX "d"
#define PRIi8 "d"
#define PRIi16 "d"
#define PRIi32 "d"
#define PRIi64 __PRI64_PREFIX "d"
#define PRIiLEAST8 "d"
#define PRIiLEAST16 "d"
#define PRIiLEAST32 "d"
#define PRIiLEAST64 __PRI64_PREFIX "d"
#define PRIiFAST8 "d"
#define PRIiFAST16 "d"
#define PRIiFAST32 "d"
#define PRIiFAST64 __PRI64_PREFIX "d"
#define PRIiMAX __PRI64_PREFIX "d"
#define PRIiPTR __PRI64_PREFIX "d"
#define PRIu8 "u"
#define PRIu16 "u"
#define PRIu32 "u"
#define PRIu64 __PRI64_PREFIX "u"
#define PRIuLEAST8 "u"
#define PRIuLEAST16 "u"
#define PRIuLEAST32 "u"
#define PRIuLEAST64 __PRI64_PREFIX "u"
#define PRIuFAST8 "u"
#define PRIuFAST16 "u"
#define PRIuFAST32 "u"
#define PRIuFAST64 __PRI64_PREFIX "u"
#define PRIuMAX __PRI64_PREFIX "u"
#define PRIuPTR __PRI64_PREFIX "u"
#define PRIx8 "x"
#define PRIx16 "x"
#define PRIx32 "x"
#define PRIx64 __PRI64_PREFIX "x"
#define PRIxLEAST8 "x"
#define PRIxLEAST16 "x"
#define PRIxLEAST32 "x"
#define PRIxLEAST64 __PRI64_PREFIX "x"
#define PRIxFAST8 "x"
#define PRIxFAST16 "x"
#define PRIxFAST32 "x"
#define PRIxFAST64 __PRI64_PREFIX "x"
#define PRIxMAX __PRI64_PREFIX "x"
#define PRIxPTR __PRI64_PREFIX "x"
#define PRIX8 PRIx8
#define PRIX16 PRIx16
#define PRIX32 PRIx32
#define PRIX64 PRIx64
#define PRIXMAX PRIxMAX
#define PRIXPTR PRIxPTR
#define PRId8 "%d"
#define PRId16 "%d"
#define PRId32 "%d"
#define PRId64 "%ld"
#define PRIdLEAST8 "%d"
#define PRIdLEAST16 "%d"
#define PRIdLEAST32 "%d"
#define PRIdLEAST64 "%ld"
#define PRIdFAST8 "%d"
#define PRIdFAST16 "%d"
#define PRIdFAST32 "%d"
#define PRIdFAST64 "%ld"
#define PRIdMAX "%ld"
#define PRIdPTR "%ld"
#define PRIi8 "%d"
#define PRIi16 "%d"
#define PRIi32 "%d"
#define PRIi64 "%ld"
#define PRIiLEAST8 "%d"
#define PRIiLEAST16 "%d"
#define PRIiLEAST32 "%d"
#define PRIiLEAST64 "%ld"
#define PRIiFAST8 "%d"
#define PRIiFAST16 "%d"
#define PRIiFAST32 "%d"
#define PRIiFAST64 "%ld"
#define PRIiMAX "%ld"
#define PRIiPTR "%ld"
#define PRIu8 "%u"
#define PRIu16 "%u"
#define PRIu32 "%u"
#define PRIu64 "%lu"
#define PRIuLEAST8 "%u"
#define PRIuLEAST16 "%u"
#define PRIuLEAST32 "%u"
#define PRIuLEAST64 "%lu"
#define PRIuFAST8 "%u"
#define PRIuFAST16 "%u"
#define PRIuFAST32 "%u"
#define PRIuFAST64 "%lu"
#define PRIuMAX "%lu"
#define PRIuPTR "%lu"
#define PRIx8 "%x"
#define PRIx16 "%x"
#define PRIx32 "%x"
#define PRIx64 "%lx"
#define PRIxLEAST8 "%x"
#define PRIxLEAST16 "%x"
#define PRIxLEAST32 "%x"
#define PRIxLEAST64 "%lx"
#define PRIxFAST8 "%x"
#define PRIxFAST16 "%x"
#define PRIxFAST32 "%x"
#define PRIxFAST64 "%lx"
#define PRIxMAX "%lx"
#define PRIxPTR "%lx"
#endif

View File

@ -1,7 +1,6 @@
#ifndef _LUNA_H
#define _LUNA_H
#include <bits/getprocid.h>
#include <bits/macros.h>
#include <sys/types.h>
@ -10,9 +9,6 @@ extern "C"
{
#endif
/* Returns a numeric identifier associated with the current process, depending on field. */
long getprocid(int field);
/* Sleeps for ms milliseconds. */
unsigned int msleep(unsigned int ms);

View File

@ -1,27 +0,0 @@
#ifndef _LUNA_DIRENT_H
#define _LUNA_DIRENT_H
#include <luna/os-limits.h>
#include <sys/types.h>
struct luna_dirent
{
ino_t inode;
char name[NAME_MAX];
size_t total;
off_t offset;
};
#ifdef __cplusplus
extern "C"
{
#endif
/* Retrieve directory entries from the kernel. This is the raw interface, use readdir() instead. */
ssize_t getdents(int fd, struct luna_dirent* buf, size_t count);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -4,8 +4,6 @@
#define OPEN_MAX 32
#define ATEXIT_MAX 32
#define NAME_MAX 64
#define PAGESIZE 4096
#define PAGE_SIZE 4096

View File

@ -1,36 +0,0 @@
#ifndef _LUNA_PSTAT_H
#define _LUNA_PSTAT_H
#include <sys/types.h>
struct pstat
{
pid_t pt_pid;
pid_t pt_ppid;
char pt_name[128];
int pt_state;
long pt_time;
};
#define PT_IDLE 0
#define PT_RUNNING 1
#define PT_SLEEPING 2
#define PT_ZOMBIE 3
#define PT_WAITING 4
#ifdef __cplusplus
extern "C"
{
#endif
/* Returns information about the process with PID pid in buf, if buf is non-null. Luna-specific. */
pid_t pstat(pid_t pid, struct pstat* buf);
/* Returns a string representation of the process state in buf. */
const char* pstatname(struct pstat* buf);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,21 +1,42 @@
#ifndef _LUNA_SYSCALL_H
#define _LUNA_SYSCALL_H
#define SYS_exit 0
#define SYS_yield 1
#define SYS_sleep 2
#define SYS_write 3
#define SYS_paint 4
#define SYS_getpid 5
#define SYS_mmap 6
#define SYS_munmap 7
#define SYS_open 8
#define SYS_read 9
#define SYS_close 10
#define SYS_seek 11
#define SYS_exec 12
#define SYS_fcntl 13
#define SYS_mprotect 14
#define SYS_clock 15
#define SYS_mkdir 16
#define SYS_fork 17
#ifndef __want_syscalls
#ifdef __cplusplus
extern "C"
{
#endif
long __luna_syscall0(long sys_num);
long __luna_syscall1(long sys_num, unsigned long arg0);
long __luna_syscall2(long sys_num, unsigned long arg0, unsigned long arg1);
long __luna_syscall3(long sys_num, unsigned long arg0, unsigned long arg1, unsigned long arg2);
long __luna_syscall4(long sys_num, unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3);
long __luna_syscall5(long sys_num, unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3,
unsigned long arg4);
long int __luna_syscall0(long int sys_num);
long int __luna_syscall1(long int sys_num, unsigned long int arg0);
long int __luna_syscall2(long int sys_num, unsigned long int arg0, unsigned long int arg1);
long int __luna_syscall3(long int sys_num, unsigned long int arg0, unsigned long int arg1, unsigned long int arg2);
long int __luna_syscall4(long int sys_num, unsigned long int arg0, unsigned long int arg1, unsigned long int arg2,
unsigned long int arg3);
long int __luna_syscall5(long int sys_num, unsigned long int arg0, unsigned long int arg1, unsigned long int arg2,
unsigned long int arg3, unsigned long int arg4);
#ifdef __cplusplus
}
#endif
#endif
#endif

View File

@ -1,8 +0,0 @@
#ifndef _LUNA_VFS_H
#define _LUNA_VFS_H
#define __VFS_FILE 0x0
#define __VFS_DIRECTORY 0x1
#define __VFS_DEVICE 0x2
#endif

View File

@ -1,9 +1,7 @@
#ifndef _SIGNAL_H
#define _SIGNAL_H
typedef int sig_atomic_t; // On the x86, writes to aligned 32-bit and 64-bit integers are always atomic. (Or that's what
// I understood)
#define SIGINT 1 // Not implemented.
typedef int sig_atomic_t; // FIXME: Implement signals (I'm trying to build bc, this header is only to satisfy it) and
// use a proper atomic integer type.
#endif

View File

@ -3,39 +3,27 @@
#include <stdarg.h>
#include <stddef.h>
#include <sys/types.h>
#include <bits/seek.h>
#define FOPEN_MAX 32
#define BUFSIZ 32
#define FILENAME_MAX 1024 // Dummy value, we don't have a limit for filenames right now.
typedef struct
{
int f_fd;
int f_eof;
int f_err;
char* f_buf;
long f_bufsize;
long f_bufoff;
long f_bufrsize;
} FILE;
extern FILE* stderr;
extern FILE* stdout;
extern FILE* stdin;
#define stdin stdin
#define stdout stdout
#define stderr stderr
#define EOF -1
#define _IONBF 0
#define _IOLBF 1
#define _IOFBF 2
typedef off_t fpos_t;
typedef struct
{
long f_offset;
} fpos_t;
#ifdef __cplusplus
extern "C"
@ -54,9 +42,6 @@ extern "C"
/* Returns a new file associated with the file descriptor fd. */
FILE* fdopen(int fd, const char* mode);
/* Opens the file specified by pathname and points the file handle stream to it. */
FILE* freopen(const char* pathname, const char* mode, FILE* stream);
/* Returns the file descriptor associated with the file stream. */
int fileno(FILE* stream);
@ -69,18 +54,12 @@ extern "C"
/* Moves stream's read/write offset by offset, depending on whence. */
int fseek(FILE* stream, long offset, int whence);
/* Moves stream's read/write offset by offset, depending on whence. */
int fseeko(FILE* stream, off_t offset, int whence);
/* Moves stream's read/write offset to the offset stored in the pos structure. */
int fsetpos(FILE* stream, const fpos_t* pos);
/* Returns the current offset for stream. */
long ftell(FILE* stream);
/* Returns the current offset for stream. */
off_t ftello(FILE* stream);
/* Stores the current offset for stream in the pos structure. */
int fgetpos(FILE* stream, fpos_t* pos);
@ -90,20 +69,6 @@ extern "C"
/* Writes nmemb items of size size from buf into the file stream. */
size_t fwrite(const void* buf, size_t size, size_t nmemb, FILE* stream);
/* Reads a line from stream into buf. */
char* fgets(char* buf, int size, FILE* stream);
/* Retrieves a character from stream. */
int fgetc(FILE* stream);
/* Retrieves a character from stream. */
int getc(FILE* stream);
int ungetc(int, FILE*); // Not implemented.
/* Retrieves a character from standard input. */
int getchar();
/* Returns nonzero if the error flag in stream was set. */
int ferror(FILE* stream);
@ -113,8 +78,7 @@ extern "C"
/* Clears the error and end-of-file flags from stream. */
void clearerr(FILE* stream);
void setbuf(FILE*, char*); // Not implemented.
int setvbuf(FILE*, char*, int, size_t); // Not implemented.
void setbuf(FILE*, char*); // Not implemented.
/* Writes formatted output according to the string format to the file stream. */
int vfprintf(FILE* stream, const char* format, va_list ap);
@ -139,8 +103,6 @@ extern "C"
/* Writes at most max bytes of formatted output according to the string format to the string str. */
int vsnprintf(char* str, size_t max, const char* format, va_list ap);
int sscanf(const char*, const char*, ...); // Not implemented.
/* Writes the string str followed by a trailing newline to stdout. */
int puts(const char* str);
@ -160,8 +122,6 @@ extern "C"
* of the last error encountered during a call to a system or library function. */
void perror(const char* str);
int remove(const char* pathname); // Not implemented.
#ifdef __cplusplus
}
#endif

View File

@ -2,32 +2,8 @@
#define _STDLIB_H
#include <bits/macros.h>
#include <limits.h>
#include <stddef.h>
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1
#define RAND_MAX INT_MAX
typedef struct
{
int quot;
int rem;
} div_t;
typedef struct
{
long quot;
long rem;
} ldiv_t;
typedef struct
{
long long quot;
long long rem;
} lldiv_t;
#ifdef __cplusplus
extern "C"
{
@ -54,12 +30,6 @@ extern "C"
/* Returns an integer (of type long long) parsed from the string str. */
long long atoll(const char* str);
/* Returns an integer (of type unsigned long) parsed from the string str. */
unsigned long strtoul(const char* str, char** endptr, int base);
/* Returns an integer (of type long) parsed from the string str. */
long strtol(const char* str, char** endptr, int base);
/* Not implemented. */
char* getenv(const char*);
@ -86,26 +56,6 @@ extern "C"
/* Seeds the random number generator with the specified seed. */
void srand(unsigned int seed);
/* Returns the absolute value of an integer. */
int abs(int val);
/* Returns the absolute value of an integer. */
long labs(long val);
/* Returns the absolute value of an integer. */
long long llabs(long long val);
/* Returns the result of dividing a by b. */
div_t div(int a, int b);
/* Returns the result of dividing a by b. */
ldiv_t ldiv(long a, long b);
/* Returns the result of dividing a by b. */
lldiv_t lldiv(long long a, long long b);
void qsort(void*, size_t, size_t, int (*)(const void*, const void*)); // Not implemented.
#ifdef __cplusplus
}
#endif

View File

@ -27,10 +27,6 @@ extern "C"
/* Returns a heap-allocated copy of the string str. Should be freed when it is not used anymore. */
char* strdup(const char* str);
/* Returns a heap-allocated copy of the string str, copying at maximum max bytes. Should be freed when it is not
* used anymore. */
char* strndup(const char* str, size_t max);
/* Returns the length of the string str. */
size_t strlen(const char* str);
@ -49,37 +45,24 @@ extern "C"
/* Returns a pointer to the last occurrence of the character c in str, or NULL if it is not found. */
char* strrchr(const char* str, int c);
/* Returns a pointer to the first occurrence of the character c in str, or a pointer to the terminating null byte of
* str if it is not found. */
char* strchrnul(const char* str, int c);
/* Concatenates at most max bytes of the string src into dest. */
char* strncat(char* dest, const char* src, size_t max);
/* Returns the length of the initial segment of str which consists entirely of bytes not in reject. */
size_t strcspn(const char* str, const char* reject);
/* Returns the length of the initial segment of str which consists entirely of bytes in accept. */
size_t strspn(const char* str, const char* accept);
/* Returns a pointer to the first occurrence of any character of b in a. */
char* strpbrk(const char* a, const char* b);
/* Compares strings a and b. You might prefer to use the safer strncmp function. */
int strcmp(const char* a, const char* b);
/* Compares at most max bytes of the strings a and b. */
int strncmp(const char* a, const char* b, size_t max);
/* Compares a and b based on the current locale. */
int strcoll(const char* a, const char* b);
/* Searches for the needle string in the haystack string. */
char* strstr(const char* haystack, const char* needle);
/* Returns the error string associated with the error number err. */
char* strerror(int err);
/* Clears n bytes of buf. */
void* bzero(void* buf, size_t n);
/* Copies the string src into dest. This function is unsafe, use strlcpy instead. */
__lc_deprecated("strcpy is unsafe and should not be used; use strlcpy instead") char* strcpy(char* dest,
const char* src);

View File

@ -1,27 +0,0 @@
#ifndef _STRINGS_H
#define _STRINGS_H
#include <stddef.h>
#ifdef __cplusplus
extern "C"
{
#endif
/* Clears n bytes of buf. */
void bzero(void* buf, size_t n);
/* Copies n bytes of src into dest. */
void bcopy(void* dest, const void* src, size_t n);
/* Compares strings a and b while treating uppercase and lowercase characters as the same. */
int strcasecmp(const char* a, const char* b);
/* Compares at most max bytes of strings a and b while treating uppercase and lowercase characters as the same. */
int strncasecmp(const char* a, const char* b, size_t max);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -13,10 +13,6 @@
#define PAGE_SIZE 4096
#define MAP_PRIVATE 0
#define MAP_SHARED 1
#define MAP_ANONYMOUS 2
#ifdef __cplusplus
extern "C"
{
@ -30,7 +26,7 @@ extern "C"
* address space. */
int munmap(void* addr, size_t size);
/* Changes the permissions of size bytes of memory at addr zaccording to the prot argument. */
/* Protects size bytes of memory according to the prot argument. */
int mprotect(void* addr, size_t size, int prot);
#ifdef __cplusplus

View File

@ -1,19 +1,8 @@
#ifndef _SYS_STAT_H
#define _SYS_STAT_H
#include <luna/vfs.h>
#include <sys/types.h>
struct stat // FIXME: This struct is quite stubbed out.
{
ino_t st_ino;
mode_t st_mode;
off_t st_size;
};
#define S_ISDIR(mode) (((mode)&0xf) == __VFS_DIRECTORY)
#define S_ISREG(mode) (((mode)&0xf) == __VFS_FILE)
#ifdef __cplusplus
extern "C"
{
@ -22,9 +11,6 @@ extern "C"
/* Creates a new directory at the path pathname. FIXME: For now, mode is ignored. */
int mkdir(const char* pathname, mode_t mode);
/* Returns information about the file pointed to by fd in buf. */
int fstat(int fd, struct stat* buf);
#ifdef __cplusplus
}
#endif

View File

@ -1,28 +1,9 @@
#ifndef _SYS_SYSCALL_H
#define _SYS_SYSCALL_H
#define SYS_exit 0
#define SYS_yield 1
#define SYS_sleep 2
#define SYS_write 3
#define SYS_paint 4
#define SYS_getprocid 5
#define SYS_mmap 6
#define SYS_munmap 7
#define SYS_open 8
#define SYS_read 9
#define SYS_close 10
#define SYS_seek 11
#define SYS_exec 12
#define SYS_fcntl 13
#define SYS_mprotect 14
#define SYS_clock 15
#define SYS_mkdir 16
#define SYS_fork 17
#define SYS_waitpid 18
#define SYS_access 19
#define SYS_fstat 20
#define SYS_pstat 21
#define SYS_getdents 22
#define __want_syscalls
#include <luna/syscall.h>
#undef __want_syscalls
#undef _LUNA_SYSCALL_H
#endif

View File

@ -16,7 +16,4 @@ typedef long int off_t;
/* The type of a file's mode. */
typedef unsigned short mode_t;
/* The type of a filesystem inode. */
typedef unsigned long ino_t;
#endif

View File

@ -1,27 +0,0 @@
#ifndef _SYS_WAIT_H
#define _SYS_WAIT_H
#include <sys/types.h>
/* Has the child process exited by calling exit() or _exit()? */
#define WIFEXITED(status) ((status) || 1)
/* What was the child's exit status? */
#define WEXITSTATUS(status) (char)((status)&0xff)
#ifdef __cplusplus
extern "C"
{
#endif
/* Waits for the child process to finish running. */
pid_t waitpid(pid_t pid, int* wstatus, int options);
/* Waits for any child process to finish running. */
pid_t wait(int* wstatus);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,27 +1,9 @@
#ifndef _TIME_H
#define _TIME_H
#include <stddef.h>
typedef long int clock_t;
typedef long int time_t;
struct tm
{
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;
long tm_gmtoff;
const char* tm_zone;
};
#define CLOCKS_PER_SEC 1000
#ifdef __cplusplus
@ -33,13 +15,6 @@ extern "C"
* get the value in seconds. */
clock_t clock(void);
/* FIXME: For now, is an alias for clock(), but in seconds. */
time_t time(time_t* tloc);
struct tm* localtime(const time_t* timep); // Not implemented.
struct tm* gmtime(const time_t* timep); // Not implemented.
size_t strftime(char* str, size_t max, const char* format, const struct tm* time); // Not implemented.
#ifdef __cplusplus
}
#endif

View File

@ -6,14 +6,8 @@
#include <luna/os-limits.h>
#include <sys/types.h>
#define STDIN_FILENO 0 // The standard input stream.
#define STDOUT_FILENO 1 // The standard output stream.
#define STDERR_FILENO 2 // The standard error stream.
#define F_OK 0 // Check for a file's existence.
#define R_OK 1 // Check whether a file is readable.
#define W_OK 2 // Check whether a file is writable.
#define X_OK 4 // Check whether a file is executable.
#define STDOUT_FILENO 0
#define STDERR_FILENO 1
#ifdef __cplusplus
extern "C"
@ -33,12 +27,9 @@ extern "C"
* the parent. */
pid_t fork(void);
/* Returns the current process' process ID. */
/* Returns the current process's process ID. */
pid_t getpid(void);
/* Returns the current process' parent's process ID. */
pid_t getppid(void);
/* Terminates the program with the status code status. */
__lc_noreturn void _exit(int status);
@ -63,12 +54,6 @@ extern "C"
/* Returns a copy of the file descriptor fd. */
int dup(int fd);
/* Checks if the current program can access the file or directory at path. */
int access(const char* path, int amode);
/* Checks if the file descriptor fd refers to a terminal. */
int isatty(int fd);
#ifdef __cplusplus
}
#endif

View File

@ -1,73 +0,0 @@
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <luna/dirent.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
extern "C"
{
DIR* opendir(const char* path)
{
int fd = open(path, O_RDONLY | O_DIRECTORY);
if (fd < 0) return NULL;
return fdopendir(fd);
}
DIR* fdopendir(int fd)
{
if (fd < 0) return NULL;
DIR* result = (DIR*)malloc(sizeof(DIR));
if (!result) return NULL;
result->d_dirfd = fd;
return result;
}
int closedir(DIR* stream)
{
int status = close(stream->d_dirfd);
if (status < 0)
{
int savederr = errno;
free(stream);
errno = savederr; // free might reset errno. We don't want that.
}
else { free(stream); }
return status;
}
struct dirent* readdir(DIR* stream)
{
static struct dirent result;
struct luna_dirent ent;
ssize_t nread = getdents(stream->d_dirfd, &ent, 1); // FIXME: Use a buffer to avoid too many system calls.
if (nread <= 0) return NULL; // Either EOF or error.
result.d_ino = ent.inode;
result.d_reclen = sizeof(result);
result.d_off = ent.offset;
result.d_type = 0;
strlcpy(result.d_name, ent.name, NAME_MAX);
return &result;
}
int dirfd(DIR* stream)
{
return stream->d_dirfd;
}
void rewinddir(DIR* stream)
{
lseek(stream->d_dirfd, 0, SEEK_SET);
}
long telldir(DIR* stream)
{
return lseek(stream->d_dirfd, 0, SEEK_CUR);
}
void seekdir(DIR* stream, long offset)
{
lseek(stream->d_dirfd, offset, SEEK_SET);
}
}

View File

@ -7,35 +7,11 @@
FILE* stderr;
FILE* stdout;
FILE* stdin;
void file_read_buf(FILE* stream)
{
if (!stream->f_buf)
{
stream->f_buf = (char*)malloc(BUFSIZ); // FIXME: Handle errors.
stream->f_bufrsize = BUFSIZ;
}
stream->f_bufoff = 0;
ssize_t nread = read(stream->f_fd, stream->f_buf, stream->f_bufrsize);
if (nread < 0)
{
stream->f_err = 1;
return;
}
if (nread == 0)
{
stream->f_eof = 1;
return;
}
stream->f_bufsize = nread;
}
extern "C"
{
int fclose(FILE* stream)
{
if (stream->f_buf) free(stream->f_buf);
int status = close(stream->f_fd);
if (status < 0)
{
@ -70,23 +46,6 @@ extern "C"
}
FILE* stream = (FILE*)malloc(sizeof(FILE));
if (!stream) { return 0; }
stream->f_fd = fd;
clearerr(stream);
stream->f_buf = 0;
stream->f_bufoff = 0;
stream->f_bufsize = 0;
return stream;
}
FILE* freopen(const char* pathname, const char*,
FILE* stream) // FIXME: If pathname is NULL, open the original file with the new mode.
{
int fd = open(pathname, O_RDWR); // FIXME: Use the mode string.
if (fd < 0) { return 0; }
fflush(stream); // To make it future-proof.
fclose(stream);
stream->f_fd = fd;
clearerr(stream);
return stream;
@ -99,9 +58,7 @@ extern "C"
size_t fread(void* buf, size_t size, size_t nmemb, FILE* stream)
{
ssize_t status =
read(stream->f_fd, buf,
size * nmemb); // FIXME: This function should use file_read_buf() to not conflict with fgets().
ssize_t status = read(stream->f_fd, buf, size * nmemb);
if (status < 0)
{
stream->f_err = 1;
@ -111,79 +68,6 @@ extern "C"
return (size_t)status;
}
char* fgets(char* buf, int size, FILE* stream)
{
char* s = buf;
int original_size = size;
while (size > 1)
{
if (stream->f_bufoff < stream->f_bufsize)
{
*buf = *(stream->f_buf + stream->f_bufoff);
stream->f_bufoff++;
if (*buf == '\n')
{
buf++;
break;
}
buf++;
size--;
}
else
{
file_read_buf(stream);
if (ferror(stream)) return NULL;
if (feof(stream)) break;
}
}
if (size == original_size && feof(stream)) return NULL; // EOF while reading the first character
*buf = 0;
return s;
}
int fgetc(FILE* stream)
{
char result;
read:
if (stream->f_bufoff < stream->f_bufsize)
{
result = *(stream->f_buf + stream->f_bufoff);
stream->f_bufoff++;
}
else
{
file_read_buf(stream);
if (ferror(stream)) return EOF;
if (feof(stream)) return EOF;
goto read;
}
return (int)result;
}
int getc(FILE* stream)
{
return fgetc(stream);
}
int getchar()
{
return fgetc(stdin);
}
int ungetc(int c, FILE* stream)
{
if (stream->f_bufoff > 0)
{
stream->f_bufoff--;
stream->f_buf[stream->f_bufoff] = (char)c;
return c;
}
else
{
return EOF; // FIXME: Handle this case properly.
}
}
int ferror(FILE* stream)
{
return stream->f_err;
@ -206,14 +90,9 @@ extern "C"
return 0;
}
int fseeko(FILE* stream, off_t offset, int whence)
{
return fseek(stream, offset, whence);
}
int fsetpos(FILE* stream, const fpos_t* pos)
{
return fseek(stream, *pos, SEEK_SET);
return fseek(stream, pos->f_offset, SEEK_SET);
}
long ftell(FILE* stream)
@ -223,16 +102,11 @@ extern "C"
// maybe? We'd have to update this value in fread() and fwrite() as well...
}
off_t ftello(FILE* stream)
{
return ftell(stream);
}
int fgetpos(FILE* stream, fpos_t* pos)
{
long result = ftell(stream);
if (result < 0) { return -1; }
*pos = result;
pos->f_offset = result;
return 0;
}
@ -258,9 +132,4 @@ extern "C"
{
NOT_IMPLEMENTED("setbuf");
}
int setvbuf(FILE*, char*, int, size_t)
{
NOT_IMPLEMENTED("setvbuf");
}
}

View File

@ -4,13 +4,10 @@
#include <stdlib.h>
#include <unistd.h>
__lc_used const char* __argv[] = {NULL}; // For now.
static void terminate_libc()
{
fclose(stdout);
fclose(stderr);
fclose(stdin);
}
static void initialize_random()
@ -55,7 +52,6 @@ static void check_for_file(int fd, FILE** target_stream, const char* path, const
extern "C" void initialize_libc()
{
check_for_file(STDIN_FILENO, &stdin, "/dev/kbd", "r");
check_for_file(STDOUT_FILENO, &stdout, "/dev/console", "rw");
check_for_file(STDERR_FILENO, &stderr, "/dev/console", "rw");

View File

@ -7,11 +7,6 @@
extern "C"
{
long getprocid(int field)
{
return syscall(SYS_getprocid, field);
}
unsigned int msleep(unsigned int ms)
{
return (unsigned int)syscall(SYS_sleep, ms);

View File

@ -1,11 +0,0 @@
#include <luna/dirent.h>
#include <sys/syscall.h>
#include <unistd.h>
extern "C"
{
ssize_t getdents(int fd, struct luna_dirent* buf, size_t count)
{
return syscall(SYS_getdents, fd, buf, count);
}
}

View File

@ -1,24 +0,0 @@
#include <luna/pstat.h>
#include <sys/syscall.h>
#include <unistd.h>
extern "C"
{
pid_t pstat(pid_t pid, struct pstat* buf)
{
return syscall(SYS_pstat, pid, buf);
}
const char* pstatname(struct pstat* buf)
{
switch (buf->pt_state)
{
case PT_IDLE: return "Idle";
case PT_RUNNING: return "Running";
case PT_SLEEPING: return "Sleeping";
case PT_WAITING: return "Waiting";
case PT_ZOMBIE: return "Zombie";
default: return "Unknown";
}
}
}

View File

@ -1,50 +0,0 @@
global __luna_syscall0
__luna_syscall0:
mov rax, rdi
int 0x42
ret
global __luna_syscall1
__luna_syscall1:
mov rax, rdi
mov rdi, rsi
int 0x42
ret
global __luna_syscall2
__luna_syscall2:
mov rax, rdi
mov rdi, rsi
mov rsi, rdx
int 0x42
ret
global __luna_syscall3
__luna_syscall3:
mov rax, rdi
mov rdi, rsi
mov rsi, rdx
mov rdx, rcx
int 0x42
ret
global __luna_syscall4
__luna_syscall4:
mov rax, rdi
mov rdi, rsi
mov rsi, rdx
mov rdx, rcx
mov r10, r8
int 0x42
ret
global __luna_syscall5
__luna_syscall5:
mov rax, rdi
mov rdi, rsi
mov rsi, rdx
mov rdx, rcx
mov r10, r8
mov r8, r9
int 0x42
ret

View File

@ -0,0 +1,48 @@
#include <luna/syscall.h>
long int __luna_syscall0(long int sys_num)
{
long int result;
asm volatile("int $0x42" : "=a"(result) : "a"(sys_num));
return result;
}
long int __luna_syscall1(long int sys_num, unsigned long int arg0)
{
long int result;
asm volatile("int $0x42" : "=a"(result) : "a"(sys_num), "D"(arg0));
return result;
}
long int __luna_syscall2(long int sys_num, unsigned long int arg0, unsigned long int arg1)
{
long int result;
asm volatile("int $0x42" : "=a"(result) : "a"(sys_num), "D"(arg0), "S"(arg1));
return result;
}
long int __luna_syscall3(long int sys_num, unsigned long int arg0, unsigned long int arg1, unsigned long int arg2)
{
long int result;
asm volatile("int $0x42" : "=a"(result) : "a"(sys_num), "D"(arg0), "S"(arg1), "d"(arg2));
return result;
}
long int __luna_syscall4(long int sys_num, unsigned long int arg0, unsigned long int arg1, unsigned long int arg2,
unsigned long int arg3)
{
long int result;
register unsigned long int value0 asm("r10") = arg3;
asm volatile("int $0x42" : "=a"(result) : "a"(sys_num), "D"(arg0), "S"(arg1), "d"(arg2), "r"(value0));
return result;
}
long int __luna_syscall5(long int sys_num, unsigned long int arg0, unsigned long int arg1, unsigned long int arg2,
unsigned long int arg3, unsigned long int arg4)
{
long int result;
register unsigned long int value0 asm("r10") = arg3;
register unsigned long int value1 asm("r8") = arg4;
asm volatile("int $0x42" : "=a"(result) : "a"(sys_num), "D"(arg0), "S"(arg1), "d"(arg2), "r"(value0), "r"(value1));
return result;
}

View File

@ -15,14 +15,12 @@ extern "C"
if (putchar('\n') < 0) return -1;
return nwritten + 1;
}
int fputs(const char* s, FILE* stream)
{
int result = (int)fwrite(s, strlen(s), 1, stream);
if (ferror(stream)) return -1;
return result;
}
int fputc(int c, FILE* stream)
{
char chr = (char)c;
@ -30,17 +28,14 @@ extern "C"
if (ferror(stream)) { return -1; }
return c;
}
int putc(int c, FILE* stream)
{
return fputc(c, stream);
}
int putchar(int c)
{
return fputc(c, stdout);
}
void perror(const char* s)
{
int savederr =
@ -48,14 +43,4 @@ extern "C"
if (s && *s) { fprintf(stderr, "%s: ", s); }
fprintf(stderr, "%s\n", strerror(savederr));
}
int remove(const char*)
{
NOT_IMPLEMENTED("remove");
}
int sscanf(const char*, const char*, ...)
{
NOT_IMPLEMENTED("sscanf");
}
}

Some files were not shown because too many files have changed in this diff Show More