Compare commits
No commits in common. "185757e2a7dcce05f14d65efab4da41e7e8b3199" and "3c1146f2c5a7eef2fe1a45be21bb68ad89170dd8" have entirely different histories.
185757e2a7
...
3c1146f2c5
3
.gitignore
vendored
3
.gitignore
vendored
@ -11,6 +11,3 @@ tests/**/bin/**
|
|||||||
base/usr/include/**
|
base/usr/include/**
|
||||||
base/usr/lib/**
|
base/usr/lib/**
|
||||||
**/*.a
|
**/*.a
|
||||||
ports/**/workdir/**
|
|
||||||
ports/ports.list
|
|
||||||
**/*.pkg.tar.xz
|
|
1
Makefile
1
Makefile
@ -23,4 +23,3 @@ install:
|
|||||||
@$(MAKE) -C kernel install
|
@$(MAKE) -C kernel install
|
||||||
@$(MAKE) -C libs install
|
@$(MAKE) -C libs install
|
||||||
@$(MAKE) -C apps install
|
@$(MAKE) -C apps install
|
||||||
@tools/install-built-ports.sh
|
|
24
README.md
24
README.md
@ -2,15 +2,16 @@
|
|||||||
A simple kernel and userspace for the x86_64 platform, written mostly in C++.
|
A simple kernel and userspace for the x86_64 platform, written mostly in C++.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
Not so much at the moment.
|
||||||
|
|
||||||
- x86_64-compatible [kernel](kernel/).
|
- 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).
|
- 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.
|
- 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.
|
- 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.
|
- 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.
|
- [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.
|
- 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
|
## 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)).
|
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.
|
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
|
## License
|
||||||
Luna is open-source and free software under the [BSD-2 License](LICENSE).
|
Luna is open-source and free software under the [BSD-2 License](LICENSE).
|
@ -1,4 +1,4 @@
|
|||||||
APPS := init sym sh crash uname uptime hello ps ls
|
APPS := init sym
|
||||||
|
|
||||||
APPS_DIR := $(LUNA_ROOT)/apps
|
APPS_DIR := $(LUNA_ROOT)/apps
|
||||||
APPS_SRC := $(APPS_DIR)/src
|
APPS_SRC := $(APPS_DIR)/src
|
||||||
@ -6,7 +6,7 @@ APPS_BIN := $(APPS_DIR)/bin
|
|||||||
|
|
||||||
REAL_APPS := $(patsubst %, $(APPS_BIN)/%, $(APPS))
|
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
|
$(APPS_BIN)/%: $(APPS_SRC)/%.c
|
||||||
@mkdir -p $(@D)
|
@mkdir -p $(@D)
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
int main()
|
|
||||||
{
|
|
||||||
int* ptr = (int*)0xdeadbeef;
|
|
||||||
*ptr = 6;
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
puts("Hello, world!");
|
|
||||||
}
|
|
167
apps/src/init.c
167
apps/src/init.c
@ -1,33 +1,40 @@
|
|||||||
#include <errno.h>
|
|
||||||
#include <luna.h>
|
#include <luna.h>
|
||||||
|
#include <setjmp.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/wait.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <unistd.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 (!fp)
|
||||||
{
|
{
|
||||||
if (errno != ENOENT) { perror("fopen"); }
|
perror("fopen");
|
||||||
return;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
char buf[4096];
|
size_t nread = fread(version, 4096, 1, fp);
|
||||||
size_t nread = fread(buf, sizeof(buf) - 1, 1, fp);
|
|
||||||
if (ferror(fp))
|
if (ferror(fp))
|
||||||
{
|
{
|
||||||
perror("fread");
|
perror("fread");
|
||||||
fclose(fp);
|
return 1;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
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()
|
int main()
|
||||||
@ -38,11 +45,116 @@ int main()
|
|||||||
return 1;
|
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();
|
pid_t child = fork();
|
||||||
|
|
||||||
if (child < 0)
|
if (child < 0)
|
||||||
{
|
{
|
||||||
perror("fork");
|
perror("fork");
|
||||||
@ -50,19 +162,22 @@ int main()
|
|||||||
}
|
}
|
||||||
if (child == 0)
|
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");
|
perror("execv");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
else { printf("Success!! Got PID %ld\n", child); }
|
||||||
|
|
||||||
pid_t result;
|
jmp_buf env;
|
||||||
|
int val = setjmp(env);
|
||||||
|
if (val == 0) { printf("Returning from setjmp!\n"); }
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Returning from longjmp! val=%d\n", val);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
for (;;)
|
longjmp(env, 3);
|
||||||
{
|
|
||||||
while ((result = wait(NULL)) == 0) // No child has exited yet
|
|
||||||
{
|
|
||||||
msleep(100);
|
|
||||||
}
|
|
||||||
if (result == child) { return 0; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
|
||||||
}
|
|
@ -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); }
|
|
||||||
}
|
|
||||||
}
|
|
194
apps/src/sh.c
194
apps/src/sh.c
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
|
sleep(2);
|
||||||
|
|
||||||
FILE* syms = fopen("/sys/moon.sym", "r");
|
FILE* syms = fopen("/sys/moon.sym", "r");
|
||||||
if (!syms)
|
if (!syms)
|
||||||
{
|
{
|
||||||
|
@ -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);
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
Welcome to Luna!
|
|
||||||
|
|
||||||
Tip of the day: Type 'help' to get started!
|
|
@ -2,11 +2,8 @@
|
|||||||
|
|
||||||
#define EPERM 1
|
#define EPERM 1
|
||||||
#define ENOENT 2
|
#define ENOENT 2
|
||||||
#define ESRCH 3
|
|
||||||
#define EINTR 4
|
|
||||||
#define ENOEXEC 8
|
#define ENOEXEC 8
|
||||||
#define EBADF 9
|
#define EBADF 9
|
||||||
#define EAGAIN 11
|
|
||||||
#define ENOMEM 12
|
#define ENOMEM 12
|
||||||
#define EFAULT 14
|
#define EFAULT 14
|
||||||
#define EEXIST 17
|
#define EEXIST 17
|
||||||
@ -14,7 +11,6 @@
|
|||||||
#define EISDIR 21
|
#define EISDIR 21
|
||||||
#define EINVAL 22
|
#define EINVAL 22
|
||||||
#define EMFILE 24
|
#define EMFILE 24
|
||||||
#define ENOTTY 25
|
|
||||||
#define ENOSPC 28
|
#define ENOSPC 28
|
||||||
#define ENOSYS 38
|
#define ENOSYS 38
|
||||||
#define ENOTSUP 95
|
#define ENOTSUP 95
|
@ -24,15 +24,10 @@ struct Descriptor
|
|||||||
m_is_open = false;
|
m_is_open = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
VFS::Node* node()
|
|
||||||
{
|
|
||||||
return m_node;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t read(size_t size, char* buffer);
|
ssize_t read(size_t size, char* buffer);
|
||||||
ssize_t write(size_t size, const 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);
|
int seek(long offset);
|
||||||
long offset()
|
long offset()
|
||||||
@ -45,16 +40,6 @@ struct Descriptor
|
|||||||
return m_node->length;
|
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(const Descriptor& other);
|
||||||
Descriptor();
|
Descriptor();
|
||||||
|
|
||||||
@ -64,8 +49,6 @@ struct Descriptor
|
|||||||
bool m_is_open;
|
bool m_is_open;
|
||||||
bool m_can_read;
|
bool m_can_read;
|
||||||
bool m_can_write;
|
bool m_can_write;
|
||||||
bool m_able_to_block;
|
|
||||||
bool m_close_on_exec;
|
|
||||||
VFS::Node* m_node;
|
VFS::Node* m_node;
|
||||||
uint64_t m_offset;
|
uint64_t m_offset;
|
||||||
};
|
};
|
@ -10,8 +10,6 @@ typedef long ssize_t;
|
|||||||
|
|
||||||
#define VFS_MOUNTPOINT 0x1
|
#define VFS_MOUNTPOINT 0x1
|
||||||
|
|
||||||
#define NAME_MAX 64
|
|
||||||
|
|
||||||
namespace VFS
|
namespace VFS
|
||||||
{
|
{
|
||||||
struct Node;
|
struct Node;
|
||||||
@ -20,23 +18,18 @@ namespace VFS
|
|||||||
typedef ssize_t (*node_write)(Node*, size_t, size_t, const char*);
|
typedef ssize_t (*node_write)(Node*, size_t, size_t, const char*);
|
||||||
typedef Node* (*node_finddir)(Node*, const char*);
|
typedef Node* (*node_finddir)(Node*, const char*);
|
||||||
typedef int (*node_mkdir)(Node*, const char*);
|
typedef int (*node_mkdir)(Node*, const char*);
|
||||||
typedef int (*node_block)(Node*);
|
|
||||||
typedef Node* (*node_readdir)(Node*, long);
|
|
||||||
|
|
||||||
struct Node
|
struct Node
|
||||||
{
|
{
|
||||||
char name[NAME_MAX];
|
char name[64];
|
||||||
uint64_t inode;
|
uint64_t inode;
|
||||||
uint64_t length;
|
uint64_t length;
|
||||||
int type;
|
int type;
|
||||||
int flags;
|
int flags;
|
||||||
node_read read_func;
|
node_read read_func;
|
||||||
node_finddir find_func;
|
node_finddir find_func;
|
||||||
node_readdir readdir_func;
|
|
||||||
node_mkdir mkdir_func;
|
node_mkdir mkdir_func;
|
||||||
node_write write_func;
|
node_write write_func;
|
||||||
node_block block_func;
|
|
||||||
int tty = 0;
|
|
||||||
Node* link;
|
Node* link;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -45,8 +38,6 @@ namespace VFS
|
|||||||
int mkdir(const char* path, const char* name);
|
int mkdir(const char* path, const char* name);
|
||||||
int mkdir(const char* pathname);
|
int mkdir(const char* pathname);
|
||||||
|
|
||||||
int would_block(Node* node);
|
|
||||||
|
|
||||||
void mount_root(Node* root);
|
void mount_root(Node* root);
|
||||||
|
|
||||||
Node* resolve_path(const char* filename, Node* root = nullptr);
|
Node* resolve_path(const char* filename, Node* root = nullptr);
|
||||||
@ -59,6 +50,4 @@ namespace VFS
|
|||||||
void unmount(Node* mountpoint);
|
void unmount(Node* mountpoint);
|
||||||
|
|
||||||
Node* root();
|
Node* root();
|
||||||
|
|
||||||
Node* readdir(Node* dir, long offset);
|
|
||||||
}
|
}
|
@ -6,5 +6,4 @@ namespace DeviceFS
|
|||||||
VFS::Node* get();
|
VFS::Node* get();
|
||||||
|
|
||||||
VFS::Node* finddir(VFS::Node* node, const char* filename);
|
VFS::Node* finddir(VFS::Node* node, const char* filename);
|
||||||
VFS::Node* readdir(VFS::Node* node, long offset);
|
|
||||||
}
|
}
|
@ -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);
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
@ -8,8 +8,4 @@ namespace KernelHeap
|
|||||||
|
|
||||||
void free_virtual_page(uint64_t address);
|
void free_virtual_page(uint64_t address);
|
||||||
void free_virtual_pages(uint64_t address, uint64_t count);
|
void free_virtual_pages(uint64_t address, uint64_t count);
|
||||||
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
void dump_usage();
|
|
||||||
}
|
}
|
@ -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);
|
|
@ -17,7 +17,7 @@ char* strstr(char* haystack, const char* needle);
|
|||||||
void* memcpy(void* dest, const void* src, size_t n);
|
void* memcpy(void* dest, const void* src, size_t n);
|
||||||
void* memset(void* dest, int c, size_t n);
|
void* memset(void* dest, int c, size_t n);
|
||||||
int memcmp(const void* a, const void* b, 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* strdup(const char* src);
|
||||||
char* strrchr(const char* str, int c);
|
char* strrchr(const char* str, int c);
|
@ -7,7 +7,7 @@
|
|||||||
#define SYS_sleep 2
|
#define SYS_sleep 2
|
||||||
#define SYS_write 3
|
#define SYS_write 3
|
||||||
#define SYS_paint 4
|
#define SYS_paint 4
|
||||||
#define SYS_getprocid 5
|
#define SYS_getpid 5
|
||||||
#define SYS_mmap 6
|
#define SYS_mmap 6
|
||||||
#define SYS_munmap 7
|
#define SYS_munmap 7
|
||||||
#define SYS_open 8
|
#define SYS_open 8
|
||||||
@ -20,19 +20,12 @@
|
|||||||
#define SYS_clock 15
|
#define SYS_clock 15
|
||||||
#define SYS_mkdir 16
|
#define SYS_mkdir 16
|
||||||
#define SYS_fork 17
|
#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
|
namespace Syscall
|
||||||
{
|
{
|
||||||
void entry(Context* context);
|
void entry(Context* context);
|
||||||
|
|
||||||
|
char* strdup_from_user(const char* user_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sys_exit(Context* context, int status);
|
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_sleep(Context* context, uint64_t ms);
|
||||||
void sys_write(Context* context, int fd, size_t size, const char* addr);
|
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_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_mmap(Context* context, void* address, size_t size, int prot);
|
||||||
void sys_munmap(Context* context, void* address, size_t size);
|
void sys_munmap(Context* context, void* address, size_t size);
|
||||||
void sys_open(Context* context, const char* filename, int flags);
|
void sys_open(Context* context, const char* filename, int flags);
|
||||||
@ -53,8 +46,3 @@ void sys_mprotect(Context* context, void* address, size_t size, int prot);
|
|||||||
void sys_clock(Context* context);
|
void sys_clock(Context* context);
|
||||||
void sys_mkdir(Context* context, const char* filename);
|
void sys_mkdir(Context* context, const char* filename);
|
||||||
void sys_fork(Context* context);
|
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);
|
|
@ -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);
|
|
||||||
}
|
|
@ -14,13 +14,10 @@ struct Task
|
|||||||
Idle,
|
Idle,
|
||||||
Running,
|
Running,
|
||||||
Sleeping,
|
Sleeping,
|
||||||
Dying,
|
|
||||||
Blocking,
|
|
||||||
Exited
|
Exited
|
||||||
};
|
};
|
||||||
|
|
||||||
uint64_t id;
|
uint64_t id;
|
||||||
uint64_t ppid;
|
|
||||||
Context regs;
|
Context regs;
|
||||||
|
|
||||||
int64_t task_sleep = 0;
|
int64_t task_sleep = 0;
|
||||||
@ -68,15 +65,4 @@ struct Task
|
|||||||
bool has_died();
|
bool has_died();
|
||||||
|
|
||||||
char name[128];
|
char name[128];
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
size_t size;
|
|
||||||
int fd;
|
|
||||||
char* buf;
|
|
||||||
} blocking_read_info;
|
|
||||||
|
|
||||||
void resume_read();
|
|
||||||
|
|
||||||
bool is_still_blocking();
|
|
||||||
};
|
};
|
@ -1,23 +1,20 @@
|
|||||||
#include "fs/FileDescriptor.h"
|
#include "fs/FileDescriptor.h"
|
||||||
#include "std/errno.h"
|
#include "errno.h"
|
||||||
|
|
||||||
Descriptor::Descriptor() : m_is_open(false)
|
Descriptor::Descriptor() : m_is_open(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Descriptor::Descriptor(const Descriptor& other)
|
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_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_able_to_block(other.m_able_to_block), m_close_on_exec(other.m_close_on_exec), m_node(other.m_node),
|
|
||||||
m_offset(other.m_offset)
|
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_read = can_read;
|
||||||
m_can_write = can_write;
|
m_can_write = can_write;
|
||||||
m_able_to_block = able_to_block;
|
|
||||||
m_close_on_exec = close_on_exec;
|
|
||||||
m_node = node;
|
m_node = node;
|
||||||
m_offset = 0;
|
m_offset = 0;
|
||||||
m_is_open = true;
|
m_is_open = true;
|
||||||
@ -39,7 +36,7 @@ ssize_t Descriptor::write(size_t size, const char* buffer)
|
|||||||
|
|
||||||
int Descriptor::seek(long offset)
|
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.
|
return -EINVAL; // FIXME: Support seeking beyond the current file's length.
|
||||||
m_offset = (uint64_t)offset;
|
m_offset = (uint64_t)offset;
|
||||||
return 0;
|
return 0;
|
||||||
@ -52,7 +49,5 @@ const Descriptor& Descriptor::operator=(const Descriptor& other)
|
|||||||
m_can_write = other.m_can_write;
|
m_can_write = other.m_can_write;
|
||||||
m_offset = other.m_offset;
|
m_offset = other.m_offset;
|
||||||
m_node = other.m_node;
|
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;
|
return other;
|
||||||
}
|
}
|
@ -1,21 +1,14 @@
|
|||||||
#define MODULE "vfs"
|
#define MODULE "vfs"
|
||||||
|
|
||||||
#include "fs/VFS.h"
|
#include "fs/VFS.h"
|
||||||
|
#include "errno.h"
|
||||||
#include "log/Log.h"
|
#include "log/Log.h"
|
||||||
#include "std/errno.h"
|
|
||||||
#include "std/libgen.h"
|
#include "std/libgen.h"
|
||||||
#include "std/stdlib.h"
|
#include "std/stdlib.h"
|
||||||
#include "std/string.h"
|
#include "std/string.h"
|
||||||
|
|
||||||
static VFS::Node* vfs_root;
|
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)
|
ssize_t VFS::read(Node* node, size_t offset, size_t length, char* buffer)
|
||||||
{
|
{
|
||||||
if (!node)
|
if (!node)
|
||||||
@ -111,7 +104,11 @@ VFS::Node* VFS::resolve_path(const char* filename, Node* root)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
Node* child = current_node->find_func(current_node, buffer);
|
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->flags & VFS_MOUNTPOINT)
|
||||||
{
|
{
|
||||||
if (!child->link)
|
if (!child->link)
|
||||||
@ -202,10 +199,3 @@ void VFS::unmount(Node* mountpoint)
|
|||||||
if (!(mountpoint->flags & VFS_MOUNTPOINT)) return;
|
if (!(mountpoint->flags & VFS_MOUNTPOINT)) return;
|
||||||
mountpoint->flags &= ~VFS_MOUNTPOINT;
|
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);
|
|
||||||
}
|
|
@ -13,7 +13,6 @@ VFS::Node* ConsoleDevice::create_new(const char* devname)
|
|||||||
dev->length = 0;
|
dev->length = 0;
|
||||||
dev->type = VFS_DEVICE;
|
dev->type = VFS_DEVICE;
|
||||||
dev->flags = 0;
|
dev->flags = 0;
|
||||||
dev->tty = 1;
|
|
||||||
strncpy(dev->name, devname, sizeof(dev->name));
|
strncpy(dev->name, devname, sizeof(dev->name));
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
#include "fs/devices/DeviceFS.h"
|
#include "fs/devices/DeviceFS.h"
|
||||||
#include "fs/devices/Console.h"
|
#include "fs/devices/Console.h"
|
||||||
#include "fs/devices/Keyboard.h"
|
|
||||||
#include "fs/devices/Random.h"
|
#include "fs/devices/Random.h"
|
||||||
#include "fs/devices/Serial.h"
|
#include "fs/devices/Serial.h"
|
||||||
#include "fs/devices/Uptime.h"
|
|
||||||
#include "fs/devices/Version.h"
|
#include "fs/devices/Version.h"
|
||||||
#include "std/stdlib.h"
|
#include "std/stdlib.h"
|
||||||
#include "std/string.h"
|
#include "std/string.h"
|
||||||
@ -23,16 +21,12 @@ VFS::Node* DeviceFS::get()
|
|||||||
devfs_root->inode = 0;
|
devfs_root->inode = 0;
|
||||||
devfs_root->type = VFS_DIRECTORY;
|
devfs_root->type = VFS_DIRECTORY;
|
||||||
devfs_root->find_func = DeviceFS::finddir;
|
devfs_root->find_func = DeviceFS::finddir;
|
||||||
devfs_root->readdir_func = DeviceFS::readdir;
|
|
||||||
strncpy(devfs_root->name, "dev", sizeof(devfs_root->name));
|
strncpy(devfs_root->name, "dev", sizeof(devfs_root->name));
|
||||||
|
|
||||||
devfs_files[devfs_file_count++] = VersionDevice::create_new("version");
|
devfs_files[devfs_file_count++] = VersionDevice::create_new("version");
|
||||||
devfs_files[devfs_file_count++] = ConsoleDevice::create_new("console");
|
devfs_files[devfs_file_count++] = ConsoleDevice::create_new("console");
|
||||||
devfs_files[devfs_file_count++] = SerialDevice::create_new("serial");
|
devfs_files[devfs_file_count++] = SerialDevice::create_new("serial");
|
||||||
devfs_files[devfs_file_count++] = RandomDevice::create_new("random");
|
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;
|
return devfs_root;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,10 +39,3 @@ VFS::Node* DeviceFS::finddir(VFS::Node* node, const char* filename)
|
|||||||
}
|
}
|
||||||
return 0;
|
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];
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
@ -1,9 +1,9 @@
|
|||||||
#define MODULE "gdt"
|
#define MODULE "gdt"
|
||||||
|
|
||||||
#include "gdt/GDT.h"
|
#include "gdt/GDT.h"
|
||||||
|
#include "kassert.h"
|
||||||
#include "log/Log.h"
|
#include "log/Log.h"
|
||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
#include "std/assert.h"
|
|
||||||
#include "std/string.h"
|
#include "std/string.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "init/InitRD.h"
|
#include "init/InitRD.h"
|
||||||
#include "interrupts/Interrupts.h"
|
#include "interrupts/Interrupts.h"
|
||||||
#include "io/Serial.h"
|
#include "io/Serial.h"
|
||||||
|
#include "kassert.h"
|
||||||
#include "log/Log.h"
|
#include "log/Log.h"
|
||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
#include "memory/PMM.h"
|
#include "memory/PMM.h"
|
||||||
@ -15,7 +16,6 @@
|
|||||||
#include "rand/Mersenne.h"
|
#include "rand/Mersenne.h"
|
||||||
#include "render/Framebuffer.h"
|
#include "render/Framebuffer.h"
|
||||||
#include "render/TextRenderer.h"
|
#include "render/TextRenderer.h"
|
||||||
#include "std/assert.h"
|
|
||||||
#include "std/string.h"
|
#include "std/string.h"
|
||||||
|
|
||||||
extern BOOTBOOT bootboot;
|
extern BOOTBOOT bootboot;
|
||||||
|
@ -2,12 +2,12 @@
|
|||||||
|
|
||||||
#include "init/InitRD.h"
|
#include "init/InitRD.h"
|
||||||
#include "bootboot.h"
|
#include "bootboot.h"
|
||||||
|
#include "errno.h"
|
||||||
#include "fs/VFS.h"
|
#include "fs/VFS.h"
|
||||||
#include "io/Serial.h"
|
#include "io/Serial.h"
|
||||||
#include "log/Log.h"
|
#include "log/Log.h"
|
||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
#include "misc/utils.h"
|
#include "misc/utils.h"
|
||||||
#include "std/errno.h"
|
|
||||||
#include "std/stdlib.h"
|
#include "std/stdlib.h"
|
||||||
#include "std/string.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_IN_DIR 8
|
||||||
#define INITRD_MAX_FILES 64
|
#define INITRD_MAX_FILES 32
|
||||||
|
|
||||||
namespace InitRD
|
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 uint32_t total_files = 0;
|
||||||
|
|
||||||
static InitRD::Directory dirs[INITRD_MAX_FILES];
|
static InitRD::Directory dirs[32];
|
||||||
static uint32_t total_dirs = 0;
|
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;
|
static uint32_t total_nodes = 0;
|
||||||
|
|
||||||
ssize_t initrd_read(VFS::Node* node, size_t offset, size_t length, char* buffer)
|
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;
|
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.
|
int initrd_mkdir(VFS::Node* node, const char* name) // FIXME: Return proper error numbers.
|
||||||
{
|
{
|
||||||
if (total_dirs >= 32)
|
if (total_dirs >= 32)
|
||||||
@ -231,7 +222,6 @@ int initrd_mkdir(VFS::Node* node, const char* name) // FIXME: Return proper erro
|
|||||||
dir.entries = 0;
|
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.
|
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.
|
// Should use a spinlock or something.
|
||||||
node->length++;
|
|
||||||
parent.files[parent.entries++] = &new_node;
|
parent.files[parent.entries++] = &new_node;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -280,13 +270,10 @@ static bool initrd_register_dir(InitRD::Directory& dir, uint64_t inode)
|
|||||||
node.length = 0;
|
node.length = 0;
|
||||||
node.type = VFS_DIRECTORY;
|
node.type = VFS_DIRECTORY;
|
||||||
node.mkdir_func = initrd_mkdir;
|
node.mkdir_func = initrd_mkdir;
|
||||||
node.readdir_func = initrd_read_dir;
|
|
||||||
node.length = 0;
|
|
||||||
strncpy(node.name, buffer, sizeof(node.name));
|
strncpy(node.name, buffer, sizeof(node.name));
|
||||||
strncpy(dir.name, buffer, sizeof(dir.name));
|
strncpy(dir.name, buffer, sizeof(dir.name));
|
||||||
|
|
||||||
parent.files[parent.entries++] = &node;
|
parent.files[parent.entries++] = &node;
|
||||||
current_node->length++;
|
|
||||||
|
|
||||||
kfree(buffer);
|
kfree(buffer);
|
||||||
return true;
|
return true;
|
||||||
@ -345,7 +332,6 @@ static bool initrd_register_file(InitRD::File& f, uint64_t inode)
|
|||||||
strncpy(f.name, buffer, sizeof(f.name));
|
strncpy(f.name, buffer, sizeof(f.name));
|
||||||
|
|
||||||
parent.files[parent.entries++] = &node;
|
parent.files[parent.entries++] = &node;
|
||||||
current_node->length++;
|
|
||||||
kfree(buffer);
|
kfree(buffer);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -359,20 +345,12 @@ static bool initrd_register_file(InitRD::File& f, uint64_t inode)
|
|||||||
static void initrd_scan()
|
static void initrd_scan()
|
||||||
{
|
{
|
||||||
initrd_for_each_dir([](InitRD::Directory& dir) {
|
initrd_for_each_dir([](InitRD::Directory& dir) {
|
||||||
if (total_dirs >= 32)
|
if (total_dirs >= 32) return;
|
||||||
{
|
|
||||||
kwarnln("Failed to register directory %s: Too many directories in initrd", dir.name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
uint64_t inode = total_dirs;
|
uint64_t inode = total_dirs;
|
||||||
if (initrd_register_dir(dir, inode)) dirs[total_dirs++] = dir;
|
if (initrd_register_dir(dir, inode)) dirs[total_dirs++] = dir;
|
||||||
});
|
});
|
||||||
InitRD::for_each([](InitRD::File& f) {
|
InitRD::for_each([](InitRD::File& f) {
|
||||||
if (total_files >= 32)
|
if (total_files >= 32) return;
|
||||||
{
|
|
||||||
kwarnln("Failed to register file %s: Too many files in initrd", f.name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
uint64_t inode = total_files;
|
uint64_t inode = total_files;
|
||||||
if (initrd_register_file(f, inode)) files[total_files++] = f;
|
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));
|
strncpy(root.name, "initrd", sizeof(root.name));
|
||||||
initrd_root.find_func = initrd_scan_dir;
|
initrd_root.find_func = initrd_scan_dir;
|
||||||
initrd_root.mkdir_func = initrd_mkdir;
|
initrd_root.mkdir_func = initrd_mkdir;
|
||||||
initrd_root.readdir_func = initrd_read_dir;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitRD::init()
|
void InitRD::init()
|
||||||
@ -398,10 +375,8 @@ void InitRD::init()
|
|||||||
(void*)bootboot.initrd_ptr, Utilities::get_blocks_from_size(PAGE_SIZE, bootboot.initrd_size));
|
(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("physical base at %lx, size %lx, mapped to %p", bootboot.initrd_ptr, bootboot.initrd_size, initrd_base);
|
||||||
kdbgln("total blocks: %ld", get_total_blocks());
|
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_initialize_root();
|
||||||
initrd_scan();
|
initrd_scan();
|
||||||
VFS::mount_root(&initrd_root);
|
VFS::mount_root(&initrd_root);
|
||||||
initrd_initialized = true;
|
initrd_initialized = true;
|
||||||
kfree(leak);
|
|
||||||
}
|
}
|
@ -4,10 +4,10 @@
|
|||||||
#include "interrupts/IRQ.h"
|
#include "interrupts/IRQ.h"
|
||||||
#include "interrupts/Interrupts.h"
|
#include "interrupts/Interrupts.h"
|
||||||
#include "io/Serial.h"
|
#include "io/Serial.h"
|
||||||
|
#include "kassert.h"
|
||||||
#include "log/Log.h"
|
#include "log/Log.h"
|
||||||
#include "misc/hang.h"
|
#include "misc/hang.h"
|
||||||
#include "panic/Panic.h"
|
#include "panic/Panic.h"
|
||||||
#include "std/assert.h"
|
|
||||||
#include "std/stdio.h"
|
#include "std/stdio.h"
|
||||||
#include "sys/Syscall.h"
|
#include "sys/Syscall.h"
|
||||||
#include "thread/Scheduler.h"
|
#include "thread/Scheduler.h"
|
||||||
@ -51,6 +51,8 @@ extern "C" void common_handler(Context* context)
|
|||||||
StackTracer tracer(context->rbp);
|
StackTracer tracer(context->rbp);
|
||||||
tracer.trace_with_ip(context->rip);
|
tracer.trace_with_ip(context->rip);
|
||||||
|
|
||||||
|
hang(); // FIXME: Remove this when multiple address spaces are working.
|
||||||
|
|
||||||
Scheduler::task_misbehave(context, -3);
|
Scheduler::task_misbehave(context, -3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#define MODULE "idt"
|
#define MODULE "idt"
|
||||||
|
|
||||||
#include "interrupts/IDT.h"
|
#include "interrupts/IDT.h"
|
||||||
|
#include "kassert.h"
|
||||||
#include "log/Log.h"
|
#include "log/Log.h"
|
||||||
#include "std/assert.h"
|
|
||||||
|
|
||||||
struct IDTEntry
|
struct IDTEntry
|
||||||
{
|
{
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
#define MODULE "irq"
|
#define MODULE "irq"
|
||||||
|
|
||||||
#include "interrupts/IRQ.h"
|
#include "interrupts/IRQ.h"
|
||||||
#include "fs/devices/Keyboard.h"
|
|
||||||
#include "io/IO.h"
|
#include "io/IO.h"
|
||||||
#include "io/PIC.h"
|
#include "io/PIC.h"
|
||||||
#include "log/Log.h"
|
#include "log/Log.h"
|
||||||
#include "misc/Scancodes.h"
|
#include "misc/reboot.h"
|
||||||
#include "rand/Init.h"
|
#include "rand/Init.h"
|
||||||
#include "std/stdio.h"
|
#include "std/stdio.h"
|
||||||
#include "thread/PIT.h"
|
#include "thread/PIT.h"
|
||||||
@ -20,11 +19,10 @@ void IRQ::interrupt_handler(Context* context)
|
|||||||
Scheduler::task_tick(context);
|
Scheduler::task_tick(context);
|
||||||
break;
|
break;
|
||||||
case 1: {
|
case 1: {
|
||||||
unsigned char scancode = IO::inb(0x60);
|
[[maybe_unused]] volatile unsigned char scancode = IO::inb(0x60);
|
||||||
bool ignore = false;
|
kdbgln("Keyboard key pressed/released, seconds since boot: %ld.%ld", PIT::ms_since_boot / 1000,
|
||||||
char key = translate_scancode(scancode, &ignore);
|
PIT::ms_since_boot % 1000);
|
||||||
if (ignore) break;
|
reboot();
|
||||||
KeyboardDevice::append(key);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: kwarnln("Unhandled IRQ: %ld", context->irq_number); break;
|
default: kwarnln("Unhandled IRQ: %ld", context->irq_number); break;
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
#include "io/Serial.h"
|
#include "io/Serial.h"
|
||||||
#include "std/stdio.h"
|
#include "std/stdio.h"
|
||||||
#include "thread/PIT.h"
|
#include "thread/PIT.h"
|
||||||
#include "thread/Scheduler.h"
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
static int level_mask = 15;
|
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_list ap;
|
||||||
va_copy(ap, origin);
|
va_copy(ap, origin);
|
||||||
Serial::reset_color();
|
Serial::reset_color();
|
||||||
if (Scheduler::current_task() && Scheduler::current_task()->id)
|
printf("[%ld.%ld] %s: ", PIT::ms_since_boot / 1000, PIT::ms_since_boot % 1000, function);
|
||||||
{
|
|
||||||
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); }
|
|
||||||
switch (level)
|
switch (level)
|
||||||
{
|
{
|
||||||
case LogLevel::WARN: Serial::set_color(Color::Yellow); break;
|
case LogLevel::WARN: Serial::set_color(Color::Yellow); break;
|
||||||
|
@ -9,11 +9,11 @@
|
|||||||
#include "interrupts/Install.h"
|
#include "interrupts/Install.h"
|
||||||
#include "interrupts/Interrupts.h"
|
#include "interrupts/Interrupts.h"
|
||||||
#include "io/PIC.h"
|
#include "io/PIC.h"
|
||||||
|
#include "kassert.h"
|
||||||
#include "log/Log.h"
|
#include "log/Log.h"
|
||||||
#include "memory/Memory.h"
|
#include "memory/Memory.h"
|
||||||
#include "memory/MemoryMap.h"
|
#include "memory/MemoryMap.h"
|
||||||
#include "misc/hang.h"
|
#include "misc/hang.h"
|
||||||
#include "std/assert.h"
|
|
||||||
#include "std/stdlib.h"
|
#include "std/stdlib.h"
|
||||||
#include "thread/PIT.h"
|
#include "thread/PIT.h"
|
||||||
#include "thread/Scheduler.h"
|
#include "thread/Scheduler.h"
|
||||||
@ -57,7 +57,7 @@ extern "C" void _start()
|
|||||||
ASSERT(Scheduler::load_user_task("/bin/init") > 0);
|
ASSERT(Scheduler::load_user_task("/bin/init") > 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Scheduler::add_kernel_task("[reaper]", []() {
|
Scheduler::add_kernel_task("[moon-reaper]", []() {
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
sleep(400);
|
sleep(400);
|
||||||
|
@ -12,7 +12,6 @@ AddressSpace AddressSpace::create()
|
|||||||
{
|
{
|
||||||
AddressSpace result;
|
AddressSpace result;
|
||||||
result.m_pml4 = (PageTable*)PMM::request_page();
|
result.m_pml4 = (PageTable*)PMM::request_page();
|
||||||
memset(result.m_pml4, 0, PAGE_SIZE);
|
|
||||||
VMM::install_kernel_page_directory_into_address_space(result);
|
VMM::install_kernel_page_directory_into_address_space(result);
|
||||||
return move(result);
|
return move(result);
|
||||||
}
|
}
|
||||||
@ -127,26 +126,16 @@ void AddressSpace::clear()
|
|||||||
pages_freed++;
|
pages_freed++;
|
||||||
PMM::free_page(pdp);
|
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);
|
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 AddressSpace::clone() // FIXME: Add out-of-memory checks to this function.
|
||||||
{
|
{
|
||||||
AddressSpace result;
|
AddressSpace result;
|
||||||
result.m_pml4 = try_clone_page_table(m_pml4);
|
result.m_pml4 = (PageTable*)PMM::request_page();
|
||||||
if (!result.m_pml4) return result;
|
if (!result.m_pml4) return result;
|
||||||
|
memcpy(result.m_pml4, m_pml4, PAGE_SIZE);
|
||||||
for (int i = 0; i < 512; i++)
|
for (int i = 0; i < 512; i++)
|
||||||
{
|
{
|
||||||
PageDirectoryEntry& pdp_pde = m_pml4->entries[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.present) continue;
|
||||||
if (pdp_pde.larger_pages)
|
if (pdp_pde.larger_pages)
|
||||||
{
|
{
|
||||||
void* cloned = try_clone_page_table((PageTable*)pdp_pde.get_address());
|
void* cloned = PMM::request_page();
|
||||||
if (!cloned)
|
memcpy(cloned, (void*)pdp_pde.get_address(), PAGE_SIZE);
|
||||||
{
|
|
||||||
cloned_pdp_pde.present = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
cloned_pdp_pde.set_address((uint64_t)cloned);
|
cloned_pdp_pde.set_address((uint64_t)cloned);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
PageTable* pdp = (PageTable*)pdp_pde.get_address();
|
PageTable* pdp = (PageTable*)pdp_pde.get_address();
|
||||||
PageTable* cloned_pdp = try_clone_page_table(pdp);
|
PageTable* cloned_pdp = (PageTable*)PMM::request_page();
|
||||||
if (!cloned_pdp)
|
memcpy(cloned_pdp, pdp, PAGE_SIZE);
|
||||||
{
|
|
||||||
cloned_pdp_pde.present = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
cloned_pdp_pde.set_address((uint64_t)cloned_pdp);
|
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
|
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.present) continue;
|
||||||
if (pd_pde.larger_pages)
|
if (pd_pde.larger_pages)
|
||||||
{
|
{
|
||||||
void* cloned = try_clone_page_table((PageTable*)pd_pde.get_address());
|
void* cloned = PMM::request_page();
|
||||||
if (!cloned)
|
memcpy(cloned, (void*)pd_pde.get_address(), PAGE_SIZE);
|
||||||
{
|
|
||||||
cloned_pd_pde.present = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
cloned_pd_pde.set_address((uint64_t)cloned);
|
cloned_pd_pde.set_address((uint64_t)cloned);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
PageTable* pd = (PageTable*)pd_pde.get_address();
|
PageTable* pd = (PageTable*)pd_pde.get_address();
|
||||||
PageTable* cloned_pd = try_clone_page_table(pd);
|
PageTable* cloned_pd = (PageTable*)PMM::request_page();
|
||||||
if (!cloned_pd)
|
memcpy(cloned_pd, pd, PAGE_SIZE);
|
||||||
{
|
|
||||||
cloned_pd_pde.present = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
cloned_pd_pde.set_address((uint64_t)cloned_pd);
|
cloned_pd_pde.set_address((uint64_t)cloned_pd);
|
||||||
for (int k = 0; k < 512; k++)
|
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.present) continue;
|
||||||
if (pt_pde.larger_pages)
|
if (pt_pde.larger_pages)
|
||||||
{
|
{
|
||||||
void* cloned = try_clone_page_table((PageTable*)pt_pde.get_address());
|
void* cloned = PMM::request_page();
|
||||||
if (!cloned)
|
memcpy(cloned, (void*)pt_pde.get_address(), PAGE_SIZE);
|
||||||
{
|
|
||||||
cloned_pt_pde.present = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
cloned_pt_pde.set_address((uint64_t)cloned);
|
cloned_pt_pde.set_address((uint64_t)cloned);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
PageTable* pt = (PageTable*)pt_pde.get_address();
|
PageTable* pt = (PageTable*)pt_pde.get_address();
|
||||||
PageTable* cloned_pt = try_clone_page_table(pt);
|
PageTable* cloned_pt = (PageTable*)PMM::request_page();
|
||||||
if (!cloned_pt)
|
memcpy(cloned_pt, pt, PAGE_SIZE);
|
||||||
{
|
|
||||||
cloned_pt_pde.present = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
cloned_pt_pde.set_address((uint64_t)cloned_pt);
|
cloned_pt_pde.set_address((uint64_t)cloned_pt);
|
||||||
for (int l = 0; l < 512; l++)
|
for (int l = 0; l < 512; l++)
|
||||||
{
|
{
|
||||||
PageDirectoryEntry& pde = pt->entries[l];
|
PageDirectoryEntry& pde = pt->entries[l];
|
||||||
PageDirectoryEntry& cloned_pde = cloned_pt->entries[l];
|
PageDirectoryEntry& cloned_pde = cloned_pt->entries[l];
|
||||||
if (!pde.present) continue;
|
if (!pde.present) continue;
|
||||||
void* cloned = try_clone_page_table((PageTable*)pde.get_address());
|
void* cloned = PMM::request_page();
|
||||||
if (!cloned)
|
memcpy(cloned, (void*)pde.get_address(), PAGE_SIZE);
|
||||||
{
|
|
||||||
cloned_pde.present = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
cloned_pde.set_address((uint64_t)cloned);
|
cloned_pde.set_address((uint64_t)cloned);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
|
|
||||||
#include "memory/KernelHeap.h"
|
#include "memory/KernelHeap.h"
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
#include "log/Log.h"
|
|
||||||
#include "std/string.h"
|
|
||||||
|
|
||||||
#ifndef PAGE_SIZE
|
#ifndef PAGE_SIZE
|
||||||
#define PAGE_SIZE 4096
|
#define PAGE_SIZE 4096
|
||||||
@ -11,13 +9,10 @@
|
|||||||
|
|
||||||
static uint8_t page_bitmap[2048];
|
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_BASE 0xfffffffff8000000
|
||||||
#define ALLOC_END 0xfffffffffc000000
|
#define ALLOC_END 0xfffffffffc000000
|
||||||
|
|
||||||
// static uint64_t start_index = 0;
|
static uint64_t start_index = 0;
|
||||||
|
|
||||||
static bool bitmap_read(uint64_t index)
|
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; }
|
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()
|
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;
|
if (bitmap_read(index)) continue;
|
||||||
bitmap_set(index, true);
|
bitmap_set(index, true);
|
||||||
// start_index = index + 1;
|
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
|
|
||||||
return ALLOC_BASE + (index * PAGE_SIZE);
|
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 = 0;
|
||||||
uint64_t contiguous_start = 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))
|
if (bitmap_read(index))
|
||||||
{
|
{
|
||||||
@ -81,15 +61,6 @@ uint64_t KernelHeap::request_virtual_pages(uint64_t count)
|
|||||||
if (contiguous == count)
|
if (contiguous == count)
|
||||||
{
|
{
|
||||||
for (uint64_t i = 0; i < count; i++) bitmap_set(contiguous_start + i, true);
|
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);
|
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;
|
if (address < ALLOC_BASE || address >= ALLOC_END) return;
|
||||||
uint64_t index = (address - ALLOC_BASE) / PAGE_SIZE;
|
uint64_t index = (address - ALLOC_BASE) / PAGE_SIZE;
|
||||||
bitmap_set(index, false);
|
bitmap_set(index, false);
|
||||||
#ifdef KHEAP_DEBUG
|
if (start_index > index) start_index = index;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void KernelHeap::free_virtual_pages(uint64_t address, uint64_t count)
|
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;
|
if (address < ALLOC_BASE || address >= ALLOC_END) return;
|
||||||
uint64_t index = (address - ALLOC_BASE) / PAGE_SIZE;
|
uint64_t index = (address - ALLOC_BASE) / PAGE_SIZE;
|
||||||
for (uint64_t i = 0; i < count; i++) { bitmap_set(index + i, false); }
|
for (uint64_t i = 0; i < count; i++) { bitmap_set(index + i, false); }
|
||||||
#ifdef KHEAP_DEBUG
|
if (start_index > index) start_index = index;
|
||||||
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);
|
|
||||||
}
|
}
|
@ -3,15 +3,14 @@
|
|||||||
#include "log/Log.h"
|
#include "log/Log.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "kassert.h"
|
||||||
#include "memory/KernelHeap.h"
|
#include "memory/KernelHeap.h"
|
||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
#include "memory/PMM.h"
|
#include "memory/PMM.h"
|
||||||
#include "memory/VMM.h"
|
#include "memory/VMM.h"
|
||||||
#include "std/assert.h"
|
|
||||||
|
|
||||||
void MemoryManager::init()
|
void MemoryManager::init()
|
||||||
{
|
{
|
||||||
KernelHeap::clear();
|
|
||||||
PMM::init();
|
PMM::init();
|
||||||
VMM::init();
|
VMM::init();
|
||||||
PMM::map_bitmap_to_virtual();
|
PMM::map_bitmap_to_virtual();
|
||||||
@ -25,7 +24,6 @@ void* MemoryManager::get_mapping(void* physicalAddress, int flags)
|
|||||||
#ifdef MM_DEBUG
|
#ifdef MM_DEBUG
|
||||||
kwarnln("No kernel heap space (virtual address space from -128M to -64M) left");
|
kwarnln("No kernel heap space (virtual address space from -128M to -64M) left");
|
||||||
#endif
|
#endif
|
||||||
KernelHeap::dump_usage();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
VMM::map(virtualAddress, (uint64_t)physicalAddress, flags);
|
VMM::map(virtualAddress, (uint64_t)physicalAddress, flags);
|
||||||
@ -41,7 +39,6 @@ void* MemoryManager::get_unaligned_mapping(void* physicalAddress, int flags)
|
|||||||
#ifdef MM_DEBUG
|
#ifdef MM_DEBUG
|
||||||
kwarnln("No kernel heap space (virtual address space from -128M to -64M) left");
|
kwarnln("No kernel heap space (virtual address space from -128M to -64M) left");
|
||||||
#endif
|
#endif
|
||||||
KernelHeap::dump_usage();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
VMM::map(virtualAddress, (uint64_t)physicalAddress - offset, flags);
|
VMM::map(virtualAddress, (uint64_t)physicalAddress - offset, flags);
|
||||||
@ -61,7 +58,6 @@ void* MemoryManager::get_unaligned_mappings(void* physicalAddress, uint64_t coun
|
|||||||
"-64M)",
|
"-64M)",
|
||||||
count);
|
count);
|
||||||
#endif
|
#endif
|
||||||
KernelHeap::dump_usage();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
for (uint64_t i = 0; i < count; i++)
|
for (uint64_t i = 0; i < count; i++)
|
||||||
@ -101,7 +97,6 @@ void* MemoryManager::get_page(int flags)
|
|||||||
#ifdef MM_DEBUG
|
#ifdef MM_DEBUG
|
||||||
kwarnln("No kernel heap space (virtual address space from -128M to -64M) left");
|
kwarnln("No kernel heap space (virtual address space from -128M to -64M) left");
|
||||||
#endif
|
#endif
|
||||||
KernelHeap::dump_usage();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return get_page_at(virtualAddress, flags);
|
return get_page_at(virtualAddress, flags);
|
||||||
@ -142,7 +137,6 @@ void* MemoryManager::get_pages(uint64_t count, int flags)
|
|||||||
#ifdef MM_DEBUG
|
#ifdef MM_DEBUG
|
||||||
kwarnln("No kernel heap space (virtual address space from -128M to -64M) left");
|
kwarnln("No kernel heap space (virtual address space from -128M to -64M) left");
|
||||||
#endif
|
#endif
|
||||||
KernelHeap::dump_usage();
|
|
||||||
return 0; // Out of virtual address in the kernel heap range (-128M to -64M). This should be difficult to
|
return 0; // Out of virtual address in the kernel heap range (-128M to -64M). This should be difficult to
|
||||||
// achieve...
|
// achieve...
|
||||||
}
|
}
|
||||||
@ -169,6 +163,9 @@ void* MemoryManager::get_pages_at(uint64_t addr, uint64_t count, int flags)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
VMM::map(addr + (i * PAGE_SIZE), (uint64_t)physicalAddress, flags);
|
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;
|
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);
|
uint64_t physicalAddress = VMM::get_physical((uint64_t)page);
|
||||||
ASSERT(physicalAddress != UINT64_MAX);
|
ASSERT(physicalAddress != UINT64_MAX);
|
||||||
VMM::unmap((uint64_t)page);
|
VMM::unmap((uint64_t)page);
|
||||||
|
#ifdef MM_DEBUG
|
||||||
|
kdbgln("releasing virtual %p, physical %lx", page, physicalAddress);
|
||||||
|
#endif
|
||||||
PMM::free_page((void*)physicalAddress);
|
PMM::free_page((void*)physicalAddress);
|
||||||
}
|
}
|
||||||
KernelHeap::free_virtual_pages((uint64_t)pages, count);
|
KernelHeap::free_virtual_pages((uint64_t)pages, count);
|
||||||
|
@ -2,11 +2,10 @@
|
|||||||
|
|
||||||
#include "memory/PMM.h"
|
#include "memory/PMM.h"
|
||||||
#include "bootboot.h"
|
#include "bootboot.h"
|
||||||
#include "log/Log.h"
|
#include "kassert.h"
|
||||||
#include "memory/Memory.h"
|
#include "memory/Memory.h"
|
||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
#include "misc/utils.h"
|
#include "misc/utils.h"
|
||||||
#include "std/assert.h"
|
|
||||||
#include "std/string.h"
|
#include "std/string.h"
|
||||||
|
|
||||||
extern BOOTBOOT bootboot;
|
extern BOOTBOOT bootboot;
|
||||||
@ -131,11 +130,6 @@ void* PMM::request_pages(uint64_t count)
|
|||||||
void PMM::free_page(void* address)
|
void PMM::free_page(void* address)
|
||||||
{
|
{
|
||||||
uint64_t index = (uint64_t)address / PAGE_SIZE;
|
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;
|
if (!bitmap_read(index)) return;
|
||||||
bitmap_set(index, false);
|
bitmap_set(index, false);
|
||||||
used_mem -= PAGE_SIZE;
|
used_mem -= PAGE_SIZE;
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
#define MODULE "vmm"
|
#define MODULE "vmm"
|
||||||
|
|
||||||
#include "memory/VMM.h"
|
#include "memory/VMM.h"
|
||||||
|
#include "kassert.h"
|
||||||
#include "log/Log.h"
|
#include "log/Log.h"
|
||||||
#include "memory/PMM.h"
|
#include "memory/PMM.h"
|
||||||
#include "misc/utils.h"
|
#include "misc/utils.h"
|
||||||
#include "std/assert.h"
|
|
||||||
#include "std/string.h"
|
#include "std/string.h"
|
||||||
#include "utils/Addresses.h"
|
#include "utils/Addresses.h"
|
||||||
#include "utils/Registers.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)
|
if (!space_last_pdp_pde.present)
|
||||||
{
|
{
|
||||||
space_last_pdp = (PageTable*)PMM::request_page(); // FIXME: Add out-of-memory checks.
|
space_last_pdp = (PageTable*)PMM::request_page();
|
||||||
memset(space_last_pdp, 0, PAGE_SIZE);
|
|
||||||
|
|
||||||
space_last_pdp_pde.present = true;
|
space_last_pdp_pde.present = true;
|
||||||
space_last_pdp_pde.read_write = true;
|
space_last_pdp_pde.read_write = true;
|
||||||
|
@ -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];
|
|
||||||
}
|
|
@ -8,7 +8,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MOON_MINOR
|
#ifndef MOON_MINOR
|
||||||
#define MOON_MINOR 13
|
#define MOON_MINOR 12
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef _MOON_SUFFIX
|
#ifndef _MOON_SUFFIX
|
||||||
|
@ -5,34 +5,12 @@
|
|||||||
#include "interrupts/IDT.h"
|
#include "interrupts/IDT.h"
|
||||||
#include "io/PIC.h"
|
#include "io/PIC.h"
|
||||||
#include "log/Log.h"
|
#include "log/Log.h"
|
||||||
#include "memory/VMM.h"
|
|
||||||
#include "misc/MSR.h"
|
#include "misc/MSR.h"
|
||||||
#include "render/Framebuffer.h"
|
|
||||||
#include "render/TextRenderer.h"
|
#include "render/TextRenderer.h"
|
||||||
#include "std/stdio.h"
|
#include "std/stdio.h"
|
||||||
#include "thread/Scheduler.h"
|
#include "thread/Scheduler.h"
|
||||||
#include "trace/StackTracer.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)
|
void dump_registers(Context* context)
|
||||||
{
|
{
|
||||||
kinfoln("-- Registers:");
|
kinfoln("-- Registers:");
|
||||||
@ -45,36 +23,8 @@ void dump_registers(Context* context)
|
|||||||
kinfoln("ia32_efer: %lx", MSR::read_from(IA32_EFER_MSR));
|
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)
|
[[noreturn]] void __panic_stub(Context* context)
|
||||||
{
|
{
|
||||||
VMM::switch_back_to_kernel_address_space();
|
|
||||||
VMM::apply_address_space();
|
|
||||||
if (context) dump_registers(context);
|
if (context) dump_registers(context);
|
||||||
|
|
||||||
if (InitRD::is_initialized())
|
if (InitRD::is_initialized())
|
||||||
@ -96,7 +46,21 @@ void fatal_dump_registers(Context* context)
|
|||||||
}
|
}
|
||||||
else { kinfoln("-- No stack trace available"); }
|
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");
|
while (1) asm volatile("hlt");
|
||||||
}
|
}
|
||||||
@ -105,28 +69,10 @@ extern "C" [[noreturn]] bool __do_int_panic(Context* context, const char* file,
|
|||||||
{
|
{
|
||||||
asm volatile("cli");
|
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);
|
KernelLog::enable_log_backend(Backend::Console);
|
||||||
|
|
||||||
TextRenderer::reset();
|
TextRenderer::reset();
|
||||||
|
|
||||||
framebuffer0.clear(Color::Black);
|
|
||||||
|
|
||||||
if (context->number >= 0x20 && context->number < 0x30) { PIC::send_eoi((uint8_t)(context->irq_number & 0xFF)); }
|
if (context->number >= 0x20 && context->number < 0x30) { PIC::send_eoi((uint8_t)(context->irq_number & 0xFF)); }
|
||||||
|
|
||||||
Task* task;
|
Task* task;
|
||||||
@ -143,28 +89,10 @@ extern "C" [[noreturn]] bool __do_panic(const char* file, int line, const char*
|
|||||||
{
|
{
|
||||||
asm volatile("cli");
|
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);
|
KernelLog::enable_log_backend(Backend::Console);
|
||||||
|
|
||||||
TextRenderer::reset();
|
TextRenderer::reset();
|
||||||
|
|
||||||
framebuffer0.clear(Color::Black);
|
|
||||||
|
|
||||||
Task* task;
|
Task* task;
|
||||||
if ((task = Scheduler::current_task()))
|
if ((task = Scheduler::current_task()))
|
||||||
{
|
{
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#define MODULE "rand"
|
#define MODULE "rand"
|
||||||
|
|
||||||
#include "rand/Mersenne.h"
|
#include "rand/Mersenne.h"
|
||||||
#include "std/assert.h"
|
#include "kassert.h"
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
typedef uint64_t word_t;
|
typedef uint64_t word_t;
|
||||||
|
@ -111,32 +111,34 @@ void* memcpy(void* dest, const void* src, size_t n)
|
|||||||
return dest;
|
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; }
|
for (size_t i = 0; i < n; ++i) { *((char*)dest + i) = (char)c; }
|
||||||
return buf;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
int memcmp(const void* a, const void* b, size_t n)
|
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;
|
if (!n) return 0;
|
||||||
const unsigned char* ap = (const unsigned char*)a;
|
if (*_a > *_b) return 1;
|
||||||
const unsigned char* bp = (const unsigned char*)b;
|
return -1;
|
||||||
while (--n && *ap == *bp)
|
|
||||||
{
|
|
||||||
ap++;
|
|
||||||
bp++;
|
|
||||||
}
|
|
||||||
return *ap - *bp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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) return dest;
|
||||||
if (dest > src)
|
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
|
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;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include "sys/Syscall.h"
|
#include "sys/Syscall.h"
|
||||||
|
#include "errno.h"
|
||||||
#include "io/Serial.h"
|
#include "io/Serial.h"
|
||||||
#include "memory/VMM.h"
|
#include "memory/VMM.h"
|
||||||
#include "std/errno.h"
|
|
||||||
#include "std/string.h"
|
#include "std/string.h"
|
||||||
#include "thread/Scheduler.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_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_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_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_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_munmap: sys_munmap(context, (void*)context->rdi, context->rsi); break;
|
||||||
case SYS_open: sys_open(context, (const char*)context->rdi, (int)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_clock: sys_clock(context); break;
|
||||||
case SYS_mkdir: sys_mkdir(context, (const char*)context->rdi); break;
|
case SYS_mkdir: sys_mkdir(context, (const char*)context->rdi); break;
|
||||||
case SYS_fork: sys_fork(context); 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;
|
default: context->rax = -ENOSYS; break;
|
||||||
}
|
}
|
||||||
VMM::exit_syscall_context();
|
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);
|
||||||
|
}
|
@ -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);
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
@ -1,15 +1,15 @@
|
|||||||
#define MODULE "elf"
|
#define MODULE "elf"
|
||||||
|
|
||||||
#include "sys/elf/ELFLoader.h"
|
#include "sys/elf/ELFLoader.h"
|
||||||
|
#include "errno.h"
|
||||||
#include "fs/VFS.h"
|
#include "fs/VFS.h"
|
||||||
#include "init/InitRD.h"
|
#include "init/InitRD.h"
|
||||||
|
#include "kassert.h"
|
||||||
#include "log/Log.h"
|
#include "log/Log.h"
|
||||||
#include "memory/Memory.h"
|
#include "memory/Memory.h"
|
||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
#include "memory/VMM.h"
|
#include "memory/VMM.h"
|
||||||
#include "misc/utils.h"
|
#include "misc/utils.h"
|
||||||
#include "std/assert.h"
|
|
||||||
#include "std/errno.h"
|
|
||||||
#include "std/stdlib.h"
|
#include "std/stdlib.h"
|
||||||
#include "std/string.h"
|
#include "std/string.h"
|
||||||
#include "sys/elf/ELF.h"
|
#include "sys/elf/ELF.h"
|
||||||
|
@ -1,16 +1,15 @@
|
|||||||
#define MODULE "exec"
|
#define MODULE "exec"
|
||||||
|
|
||||||
|
#include "errno.h"
|
||||||
#include "interrupts/Interrupts.h"
|
#include "interrupts/Interrupts.h"
|
||||||
|
#include "kassert.h"
|
||||||
#include "log/Log.h"
|
#include "log/Log.h"
|
||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
#include "memory/PMM.h"
|
#include "memory/PMM.h"
|
||||||
#include "memory/VMM.h"
|
#include "memory/VMM.h"
|
||||||
#include "std/assert.h"
|
|
||||||
#include "std/errno.h"
|
|
||||||
#include "std/stdlib.h"
|
#include "std/stdlib.h"
|
||||||
#include "std/string.h"
|
#include "std/string.h"
|
||||||
#include "sys/Syscall.h"
|
#include "sys/Syscall.h"
|
||||||
#include "sys/UserMemory.h"
|
|
||||||
#include "sys/elf/ELFLoader.h"
|
#include "sys/elf/ELFLoader.h"
|
||||||
#include "thread/Scheduler.h"
|
#include "thread/Scheduler.h"
|
||||||
|
|
||||||
@ -42,8 +41,6 @@ void sys_fork(Context* context)
|
|||||||
|
|
||||||
child->address_space = parent->address_space.clone();
|
child->address_space = parent->address_space.clone();
|
||||||
|
|
||||||
child->ppid = parent->id;
|
|
||||||
|
|
||||||
child->regs.rax = 0;
|
child->regs.rax = 0;
|
||||||
context->rax = child->id;
|
context->rax = child->id;
|
||||||
|
|
||||||
@ -58,7 +55,7 @@ void sys_fork(Context* context)
|
|||||||
|
|
||||||
void sys_exec(Context* context, const char* pathname)
|
void sys_exec(Context* context, const char* pathname)
|
||||||
{
|
{
|
||||||
char* kpathname = strdup_from_user(pathname);
|
char* kpathname = Syscall::strdup_from_user(pathname);
|
||||||
if (!kpathname)
|
if (!kpathname)
|
||||||
{
|
{
|
||||||
context->rax = -EFAULT;
|
context->rax = -EFAULT;
|
||||||
@ -123,12 +120,6 @@ void sys_exec(Context* context, const char* pathname)
|
|||||||
|
|
||||||
Scheduler::reset_task(task, image);
|
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);
|
task->restore_context(context);
|
||||||
|
|
||||||
kfree(kpathname);
|
kfree(kpathname);
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,12 +1,12 @@
|
|||||||
#define MODULE "mem"
|
#define MODULE "mem"
|
||||||
|
|
||||||
|
#include "errno.h"
|
||||||
#include "interrupts/Context.h"
|
#include "interrupts/Context.h"
|
||||||
#include "log/Log.h"
|
#include "log/Log.h"
|
||||||
#include "memory/Memory.h"
|
#include "memory/Memory.h"
|
||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
#include "memory/VMM.h"
|
#include "memory/VMM.h"
|
||||||
#include "misc/utils.h"
|
#include "misc/utils.h"
|
||||||
#include "std/errno.h"
|
|
||||||
#include "thread/Scheduler.h"
|
#include "thread/Scheduler.h"
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include "bootboot.h"
|
#include "bootboot.h"
|
||||||
|
#include "errno.h"
|
||||||
#include "interrupts/Context.h"
|
#include "interrupts/Context.h"
|
||||||
#include "render/Framebuffer.h"
|
#include "render/Framebuffer.h"
|
||||||
#include "std/errno.h"
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
extern BOOTBOOT bootboot;
|
extern BOOTBOOT bootboot;
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
#include "memory/VMM.h"
|
|
||||||
#include "std/errno.h"
|
|
||||||
#include "sys/UserMemory.h"
|
|
||||||
#include "thread/Scheduler.h"
|
#include "thread/Scheduler.h"
|
||||||
|
|
||||||
void sys_exit(Context* context, int status)
|
void sys_exit(Context* context, int status)
|
||||||
@ -22,3 +19,8 @@ void sys_sleep(Context* context, uint64_t ms)
|
|||||||
task->state = task->Sleeping;
|
task->state = task->Sleeping;
|
||||||
Scheduler::task_yield(context);
|
Scheduler::task_yield(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sys_getpid(Context* context)
|
||||||
|
{
|
||||||
|
context->rax = Scheduler::current_task()->id;
|
||||||
|
}
|
@ -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;
|
|
||||||
}
|
|
@ -1,29 +1,24 @@
|
|||||||
#define MODULE "stdio"
|
#define MODULE "stdio"
|
||||||
|
|
||||||
|
#include "errno.h"
|
||||||
#include "interrupts/Context.h"
|
#include "interrupts/Context.h"
|
||||||
#include "io/Serial.h"
|
#include "io/Serial.h"
|
||||||
#include "log/Log.h"
|
#include "log/Log.h"
|
||||||
#include "memory/VMM.h"
|
#include "memory/VMM.h"
|
||||||
#include "render/TextRenderer.h"
|
#include "render/TextRenderer.h"
|
||||||
#include "std/errno.h"
|
|
||||||
#include "std/stdlib.h"
|
#include "std/stdlib.h"
|
||||||
#include "sys/Syscall.h"
|
#include "sys/Syscall.h"
|
||||||
#include "sys/UserMemory.h"
|
|
||||||
#include "thread/Scheduler.h"
|
#include "thread/Scheduler.h"
|
||||||
#include "thread/Task.h"
|
#include "thread/Task.h"
|
||||||
|
|
||||||
#define OPEN_READ 1
|
#define OPEN_READ 1
|
||||||
#define OPEN_WRITE 2
|
#define OPEN_WRITE 2
|
||||||
#define OPEN_NONBLOCK 4
|
|
||||||
#define OPEN_CLOEXEC 8
|
|
||||||
#define OPEN_DIRECTORY 16
|
|
||||||
|
|
||||||
#define SEEK_SET 0
|
#define SEEK_SET 0
|
||||||
#define SEEK_CUR 1
|
#define SEEK_CUR 1
|
||||||
#define SEEK_END 2
|
#define SEEK_END 2
|
||||||
|
|
||||||
#define FCNTL_DUPFD 0
|
#define FNCTL_DUPFD 0
|
||||||
#define FCNTL_ISTTY 1
|
|
||||||
|
|
||||||
void sys_fcntl(Context* context, int fd, int command, uintptr_t arg)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
Descriptor& file = current_task->files[fd];
|
Descriptor& file = current_task->files[fd];
|
||||||
if (command == FCNTL_DUPFD)
|
if (command == FNCTL_DUPFD)
|
||||||
{
|
{
|
||||||
if ((int)arg < 0 || (int)arg >= TASK_MAX_FDS)
|
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);
|
kdbgln("fcntl(F_DUPFD): duplicated fd %d, result is %d", fd, dupfd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (command == FCNTL_ISTTY)
|
|
||||||
{
|
|
||||||
VFS::Node* node = file.node();
|
|
||||||
if (node->tty) { context->rax = 1; }
|
|
||||||
else
|
|
||||||
context->rax = -ENOTTY;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
context->rax = -EINVAL;
|
context->rax = -EINVAL;
|
||||||
@ -158,17 +145,17 @@ void sys_open(Context* context, const char* filename, int flags)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* kfilename = strdup_from_user(filename);
|
char* kernel_filename = Syscall::strdup_from_user(filename);
|
||||||
if (!kfilename)
|
if (!kernel_filename)
|
||||||
{
|
{
|
||||||
context->rax = -EFAULT;
|
context->rax = -EFAULT;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
VFS::Node* node = VFS::resolve_path(kfilename);
|
VFS::Node* node = VFS::resolve_path(kernel_filename);
|
||||||
if (!node)
|
if (!node)
|
||||||
{
|
{
|
||||||
kfree(kfilename);
|
kfree(kernel_filename);
|
||||||
context->rax = -ENOENT;
|
context->rax = -ENOENT;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -177,31 +164,19 @@ void sys_open(Context* context, const char* filename, int flags)
|
|||||||
bool can_write = (flags & OPEN_WRITE) > 0;
|
bool can_write = (flags & OPEN_WRITE) > 0;
|
||||||
if (!can_read && !can_write)
|
if (!can_read && !can_write)
|
||||||
{
|
{
|
||||||
kfree(kfilename);
|
kfree(kernel_filename);
|
||||||
context->rax = -EINVAL;
|
context->rax = -EINVAL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool able_to_block = (flags & OPEN_NONBLOCK) == 0;
|
kdbgln("open(): opening %s %s, allocated file descriptor %d", kernel_filename,
|
||||||
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,
|
|
||||||
(can_read && can_write) ? "rw"
|
(can_read && can_write) ? "rw"
|
||||||
: can_read ? "r-"
|
: can_read ? "r-"
|
||||||
: "-w",
|
: "-w",
|
||||||
fd);
|
fd);
|
||||||
|
|
||||||
kfree(kfilename);
|
kfree(kernel_filename);
|
||||||
current_task->files[fd].open(node, can_read, can_write, able_to_block, close_on_exec);
|
current_task->files[fd].open(node, can_read, can_write);
|
||||||
context->rax = fd;
|
context->rax = fd;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -224,22 +199,7 @@ void sys_read(Context* context, int fd, size_t size, char* buffer)
|
|||||||
context->rax = -EBADF;
|
context->rax = -EBADF;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (VFS::would_block(current_task->files[fd].node()))
|
ssize_t result = current_task->files[fd].read(size, (char*)VMM::get_physical((uint64_t)buffer));
|
||||||
{
|
|
||||||
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.
|
|
||||||
context->rax = (size_t)result;
|
context->rax = (size_t)result;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -265,7 +225,7 @@ void sys_close(Context* context, int fd)
|
|||||||
|
|
||||||
void sys_mkdir(Context* context, const char* filename)
|
void sys_mkdir(Context* context, const char* filename)
|
||||||
{
|
{
|
||||||
char* kfilename = strdup_from_user(filename);
|
char* kfilename = Syscall::strdup_from_user(filename);
|
||||||
if (!kfilename)
|
if (!kfilename)
|
||||||
{
|
{
|
||||||
context->rax = -EFAULT;
|
context->rax = -EFAULT;
|
||||||
@ -278,12 +238,3 @@ void sys_mkdir(Context* context, const char* filename)
|
|||||||
|
|
||||||
context->rax = rc;
|
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);
|
|
||||||
}
|
|
@ -1,20 +1,18 @@
|
|||||||
#define MODULE "sched"
|
#define MODULE "sched"
|
||||||
|
|
||||||
#include "thread/Scheduler.h"
|
#include "thread/Scheduler.h"
|
||||||
|
#include "errno.h"
|
||||||
#include "interrupts/Interrupts.h"
|
#include "interrupts/Interrupts.h"
|
||||||
|
#include "kassert.h"
|
||||||
#include "log/Log.h"
|
#include "log/Log.h"
|
||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
#include "memory/PMM.h"
|
#include "memory/PMM.h"
|
||||||
#include "memory/VMM.h"
|
#include "memory/VMM.h"
|
||||||
#include "misc/hang.h"
|
#include "misc/hang.h"
|
||||||
#include "misc/reboot.h"
|
|
||||||
#include "misc/utils.h"
|
#include "misc/utils.h"
|
||||||
#include "panic/Panic.h"
|
#include "panic/Panic.h"
|
||||||
#include "std/assert.h"
|
|
||||||
#include "std/errno.h"
|
|
||||||
#include "std/stdlib.h"
|
#include "std/stdlib.h"
|
||||||
#include "std/string.h"
|
#include "std/string.h"
|
||||||
#include "sys/UserMemory.h"
|
|
||||||
#include "sys/elf/ELFLoader.h"
|
#include "sys/elf/ELFLoader.h"
|
||||||
#include "thread/PIT.h"
|
#include "thread/PIT.h"
|
||||||
#include "thread/Task.h"
|
#include "thread/Task.h"
|
||||||
@ -46,14 +44,6 @@ template <typename Callback> void sched_for_each_task(Callback callback)
|
|||||||
} while (task != base_task);
|
} 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* Scheduler::find_by_pid(uint64_t pid)
|
||||||
{
|
{
|
||||||
Task* result = nullptr;
|
Task* result = nullptr;
|
||||||
@ -101,8 +91,6 @@ void Scheduler::init()
|
|||||||
idle_task.user_task = false;
|
idle_task.user_task = false;
|
||||||
idle_task.state = idle_task.Idle;
|
idle_task.state = idle_task.Idle;
|
||||||
|
|
||||||
strlcpy(idle_task.name, "[cpu-idle]", sizeof(idle_task.name));
|
|
||||||
|
|
||||||
sched_current_task = &idle_task;
|
sched_current_task = &idle_task;
|
||||||
|
|
||||||
frequency = 1000 / PIT::frequency();
|
frequency = 1000 / PIT::frequency();
|
||||||
@ -114,7 +102,6 @@ void Scheduler::add_kernel_task(const char* taskname, void (*task)(void))
|
|||||||
ASSERT(new_task);
|
ASSERT(new_task);
|
||||||
new_task->user_task = false;
|
new_task->user_task = false;
|
||||||
new_task->id = free_tid++;
|
new_task->id = free_tid++;
|
||||||
new_task->ppid = 0;
|
|
||||||
new_task->regs.rip = (uint64_t)task;
|
new_task->regs.rip = (uint64_t)task;
|
||||||
new_task->allocated_stack =
|
new_task->allocated_stack =
|
||||||
(uint64_t)MemoryManager::get_pages(TASK_PAGES_IN_STACK); // 16 KB is enough for everyone, right?
|
(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));
|
memset(&new_task->regs, 0, sizeof(Context));
|
||||||
new_task->user_task = true;
|
new_task->user_task = true;
|
||||||
new_task->id = free_tid++;
|
new_task->id = free_tid++;
|
||||||
new_task->ppid = 0;
|
|
||||||
new_task->task_sleep = 0;
|
new_task->task_sleep = 0;
|
||||||
new_task->task_time = 0;
|
new_task->task_time = 0;
|
||||||
new_task->cpu_time = 0;
|
new_task->cpu_time = 0;
|
||||||
@ -166,11 +152,9 @@ long Scheduler::load_user_task(const char* filename)
|
|||||||
ASSERT(new_task);
|
ASSERT(new_task);
|
||||||
memset(&new_task->regs, 0, sizeof(Context));
|
memset(&new_task->regs, 0, sizeof(Context));
|
||||||
new_task->id = free_tid++;
|
new_task->id = free_tid++;
|
||||||
new_task->ppid = 0;
|
|
||||||
if (!new_task->allocator.init())
|
if (!new_task->allocator.init())
|
||||||
{
|
{
|
||||||
delete new_task;
|
delete new_task;
|
||||||
free_tid--;
|
|
||||||
Interrupts::pop();
|
Interrupts::pop();
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
@ -189,7 +173,6 @@ long Scheduler::load_user_task(const char* filename)
|
|||||||
{
|
{
|
||||||
new_task->address_space.destroy();
|
new_task->address_space.destroy();
|
||||||
delete new_task;
|
delete new_task;
|
||||||
free_tid--;
|
|
||||||
ELFLoader::release_elf_image(image);
|
ELFLoader::release_elf_image(image);
|
||||||
VMM::switch_back_to_kernel_address_space();
|
VMM::switch_back_to_kernel_address_space();
|
||||||
Interrupts::pop();
|
Interrupts::pop();
|
||||||
@ -262,47 +245,26 @@ void Scheduler::reap_task(Task* task)
|
|||||||
Interrupts::pop();
|
Interrupts::pop();
|
||||||
}
|
}
|
||||||
for (int i = 0; i < TASK_MAX_FDS; i++) { exiting_task->files[i].close(); }
|
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;
|
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)
|
void Scheduler::task_exit(Context* context, int64_t status)
|
||||||
{
|
{
|
||||||
ASSERT(Interrupts::is_in_handler());
|
ASSERT(Interrupts::is_in_handler());
|
||||||
kdbgln("exit: task %ld finished running, used %ld ms of cpu time", sched_current_task->id,
|
kdbgln("exit: task %ld finished running, used %ld ms of cpu time", sched_current_task->id,
|
||||||
sched_current_task->cpu_time);
|
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)
|
void Scheduler::task_misbehave(Context* context, int64_t status)
|
||||||
{
|
{
|
||||||
ASSERT(Interrupts::is_in_handler());
|
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);
|
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()
|
void Scheduler::reap_tasks()
|
||||||
@ -374,10 +336,10 @@ void Scheduler::task_tick(Context* context)
|
|||||||
ASSERT(Interrupts::is_in_handler());
|
ASSERT(Interrupts::is_in_handler());
|
||||||
Interrupts::disable();
|
Interrupts::disable();
|
||||||
sched_decrement_sleep_times();
|
sched_decrement_sleep_times();
|
||||||
|
if (sched_current_task->id == 0) return task_yield(context);
|
||||||
sched_current_task->task_time -= frequency;
|
sched_current_task->task_time -= frequency;
|
||||||
sched_current_task->cpu_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;
|
sched_current_task->task_time = 0;
|
||||||
task_yield(context);
|
task_yield(context);
|
||||||
@ -399,14 +361,6 @@ void Scheduler::task_yield(Context* context)
|
|||||||
Task* original_task = sched_current_task;
|
Task* original_task = sched_current_task;
|
||||||
do {
|
do {
|
||||||
sched_current_task = sched_current_task->next_task;
|
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->state == sched_current_task->Running)
|
||||||
{
|
{
|
||||||
if (sched_current_task->id != original_task->id || was_idle)
|
if (sched_current_task->id != original_task->id || was_idle)
|
||||||
@ -460,103 +414,3 @@ Task* Scheduler::current_task()
|
|||||||
{
|
{
|
||||||
return sched_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;
|
|
||||||
}
|
|
@ -1,7 +1,4 @@
|
|||||||
#define MODULE "sched"
|
|
||||||
|
|
||||||
#include "thread/Task.h"
|
#include "thread/Task.h"
|
||||||
#include "log/Log.h"
|
|
||||||
#include "memory/VMM.h"
|
#include "memory/VMM.h"
|
||||||
#include "std/string.h"
|
#include "std/string.h"
|
||||||
|
|
||||||
@ -69,17 +66,3 @@ bool Task::has_died()
|
|||||||
{
|
{
|
||||||
return state == Exited;
|
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());
|
|
||||||
}
|
|
@ -24,7 +24,7 @@ typedef struct stackframe
|
|||||||
void StackTracer::trace()
|
void StackTracer::trace()
|
||||||
{
|
{
|
||||||
stackframe* frame = (stackframe*)m_base_pointer;
|
stackframe* frame = (stackframe*)m_base_pointer;
|
||||||
while (frame && frame->instruction && Memory::is_kernel_address(frame->instruction))
|
while (frame && frame->instruction)
|
||||||
{
|
{
|
||||||
char symbol_name[512];
|
char symbol_name[512];
|
||||||
get_symbol_name(frame->instruction - sizeof(uintptr_t), symbol_name, sizeof(symbol_name));
|
get_symbol_name(frame->instruction - sizeof(uintptr_t), symbol_name, sizeof(symbol_name));
|
||||||
|
@ -5,7 +5,7 @@ LIBC_BIN := $(LIBC_DIR)/bin
|
|||||||
|
|
||||||
DESTDIR ?= $(LUNA_BASE)/usr/lib
|
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
|
CXXFLAGS := -fno-rtti -fno-exceptions -Wsign-promo -Wstrict-null-sentinel -Wctor-dtor-privacy
|
||||||
ASMFLAGS := -felf64
|
ASMFLAGS := -felf64
|
||||||
|
|
||||||
|
@ -6,8 +6,6 @@ extern _fini
|
|||||||
extern initialize_libc
|
extern initialize_libc
|
||||||
extern exit
|
extern exit
|
||||||
|
|
||||||
extern __argv
|
|
||||||
|
|
||||||
global _start
|
global _start
|
||||||
_start:
|
_start:
|
||||||
; Set up end of the stack frame linked list.
|
; Set up end of the stack frame linked list.
|
||||||
@ -21,7 +19,7 @@ _start:
|
|||||||
call _init
|
call _init
|
||||||
|
|
||||||
mov rdi, 0 ; argc = 0
|
mov rdi, 0 ; argc = 0
|
||||||
mov rsi, __argv ; Dummy argv which is equal to {NULL}
|
mov rsi, 0 ; argv = 0
|
||||||
|
|
||||||
call main
|
call main
|
||||||
|
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
#ifndef _BITS_GETPROCID_H
|
|
||||||
#define _BITS_GETPROCID_H
|
|
||||||
|
|
||||||
#define ID_PID 0
|
|
||||||
#define ID_PPID 1
|
|
||||||
|
|
||||||
#endif
|
|
@ -5,6 +5,5 @@
|
|||||||
#define __lc_align(n) __attribute__((aligned(n)))
|
#define __lc_align(n) __attribute__((aligned(n)))
|
||||||
#define __lc_deprecated(msg) __attribute__((deprecated(msg)))
|
#define __lc_deprecated(msg) __attribute__((deprecated(msg)))
|
||||||
#define __lc_unreachable __builtin_unreachable
|
#define __lc_unreachable __builtin_unreachable
|
||||||
#define __lc_used __attribute__((used))
|
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -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
|
|
@ -6,11 +6,8 @@ extern int errno;
|
|||||||
|
|
||||||
#define EPERM 1 // Operation not permitted
|
#define EPERM 1 // Operation not permitted
|
||||||
#define ENOENT 2 // No such file or directory
|
#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 ENOEXEC 8 // Exec format error
|
||||||
#define EBADF 9 // Bad file descriptor
|
#define EBADF 9 // Bad file descriptor
|
||||||
#define EAGAIN 11 // Resource temporarily unavailable
|
|
||||||
#define ENOMEM 12 // Cannot allocate memory
|
#define ENOMEM 12 // Cannot allocate memory
|
||||||
#define EFAULT 14 // Bad address
|
#define EFAULT 14 // Bad address
|
||||||
#define EEXIST 17 // File exists
|
#define EEXIST 17 // File exists
|
||||||
@ -18,10 +15,9 @@ extern int errno;
|
|||||||
#define EISDIR 21 // Is a directory
|
#define EISDIR 21 // Is a directory
|
||||||
#define EINVAL 22 // Invalid argument
|
#define EINVAL 22 // Invalid argument
|
||||||
#define EMFILE 24 // Too many open files
|
#define EMFILE 24 // Too many open files
|
||||||
#define ENOTTY 25 // Inappropriate ioctl for device
|
|
||||||
#define ENOSPC 28 // No space left on device
|
#define ENOSPC 28 // No space left on device
|
||||||
#define EPIPE 32 // Broken pipe. Not implemented.
|
#define EPIPE 32 // Broken pipe. Not implemented.
|
||||||
#define ENOSYS 38 // Function not implemented
|
#define ENOSYS 38 // Function not implemented
|
||||||
#define ENOTSUP 95 // Operation not supported
|
#define ENOTSUP 95 // Operation not supported.
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -7,17 +7,9 @@
|
|||||||
#define O_WRONLY 2
|
#define O_WRONLY 2
|
||||||
/* Open for reading and writing. */
|
/* Open for reading and writing. */
|
||||||
#define O_RDWR 3
|
#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. */
|
/* Duplicate a file descriptor. */
|
||||||
#define F_DUPFD 0
|
#define F_DUPFD 0
|
||||||
/* Is a file descriptor a TTY? */
|
|
||||||
#define F_ISTTY 1
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C"
|
extern "C"
|
||||||
|
@ -3,69 +3,61 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#define __PRI64_PREFIX "l"
|
#define PRId8 "%d"
|
||||||
|
#define PRId16 "%d"
|
||||||
#define PRId8 "d"
|
#define PRId32 "%d"
|
||||||
#define PRId16 "d"
|
#define PRId64 "%ld"
|
||||||
#define PRId32 "d"
|
#define PRIdLEAST8 "%d"
|
||||||
#define PRId64 __PRI64_PREFIX "d"
|
#define PRIdLEAST16 "%d"
|
||||||
#define PRIdLEAST8 "d"
|
#define PRIdLEAST32 "%d"
|
||||||
#define PRIdLEAST16 "d"
|
#define PRIdLEAST64 "%ld"
|
||||||
#define PRIdLEAST32 "d"
|
#define PRIdFAST8 "%d"
|
||||||
#define PRIdLEAST64 __PRI64_PREFIX "d"
|
#define PRIdFAST16 "%d"
|
||||||
#define PRIdFAST8 "d"
|
#define PRIdFAST32 "%d"
|
||||||
#define PRIdFAST16 "d"
|
#define PRIdFAST64 "%ld"
|
||||||
#define PRIdFAST32 "d"
|
#define PRIdMAX "%ld"
|
||||||
#define PRIdFAST64 __PRI64_PREFIX "d"
|
#define PRIdPTR "%ld"
|
||||||
#define PRIdMAX __PRI64_PREFIX "d"
|
#define PRIi8 "%d"
|
||||||
#define PRIdPTR __PRI64_PREFIX "d"
|
#define PRIi16 "%d"
|
||||||
#define PRIi8 "d"
|
#define PRIi32 "%d"
|
||||||
#define PRIi16 "d"
|
#define PRIi64 "%ld"
|
||||||
#define PRIi32 "d"
|
#define PRIiLEAST8 "%d"
|
||||||
#define PRIi64 __PRI64_PREFIX "d"
|
#define PRIiLEAST16 "%d"
|
||||||
#define PRIiLEAST8 "d"
|
#define PRIiLEAST32 "%d"
|
||||||
#define PRIiLEAST16 "d"
|
#define PRIiLEAST64 "%ld"
|
||||||
#define PRIiLEAST32 "d"
|
#define PRIiFAST8 "%d"
|
||||||
#define PRIiLEAST64 __PRI64_PREFIX "d"
|
#define PRIiFAST16 "%d"
|
||||||
#define PRIiFAST8 "d"
|
#define PRIiFAST32 "%d"
|
||||||
#define PRIiFAST16 "d"
|
#define PRIiFAST64 "%ld"
|
||||||
#define PRIiFAST32 "d"
|
#define PRIiMAX "%ld"
|
||||||
#define PRIiFAST64 __PRI64_PREFIX "d"
|
#define PRIiPTR "%ld"
|
||||||
#define PRIiMAX __PRI64_PREFIX "d"
|
#define PRIu8 "%u"
|
||||||
#define PRIiPTR __PRI64_PREFIX "d"
|
#define PRIu16 "%u"
|
||||||
#define PRIu8 "u"
|
#define PRIu32 "%u"
|
||||||
#define PRIu16 "u"
|
#define PRIu64 "%lu"
|
||||||
#define PRIu32 "u"
|
#define PRIuLEAST8 "%u"
|
||||||
#define PRIu64 __PRI64_PREFIX "u"
|
#define PRIuLEAST16 "%u"
|
||||||
#define PRIuLEAST8 "u"
|
#define PRIuLEAST32 "%u"
|
||||||
#define PRIuLEAST16 "u"
|
#define PRIuLEAST64 "%lu"
|
||||||
#define PRIuLEAST32 "u"
|
#define PRIuFAST8 "%u"
|
||||||
#define PRIuLEAST64 __PRI64_PREFIX "u"
|
#define PRIuFAST16 "%u"
|
||||||
#define PRIuFAST8 "u"
|
#define PRIuFAST32 "%u"
|
||||||
#define PRIuFAST16 "u"
|
#define PRIuFAST64 "%lu"
|
||||||
#define PRIuFAST32 "u"
|
#define PRIuMAX "%lu"
|
||||||
#define PRIuFAST64 __PRI64_PREFIX "u"
|
#define PRIuPTR "%lu"
|
||||||
#define PRIuMAX __PRI64_PREFIX "u"
|
#define PRIx8 "%x"
|
||||||
#define PRIuPTR __PRI64_PREFIX "u"
|
#define PRIx16 "%x"
|
||||||
#define PRIx8 "x"
|
#define PRIx32 "%x"
|
||||||
#define PRIx16 "x"
|
#define PRIx64 "%lx"
|
||||||
#define PRIx32 "x"
|
#define PRIxLEAST8 "%x"
|
||||||
#define PRIx64 __PRI64_PREFIX "x"
|
#define PRIxLEAST16 "%x"
|
||||||
#define PRIxLEAST8 "x"
|
#define PRIxLEAST32 "%x"
|
||||||
#define PRIxLEAST16 "x"
|
#define PRIxLEAST64 "%lx"
|
||||||
#define PRIxLEAST32 "x"
|
#define PRIxFAST8 "%x"
|
||||||
#define PRIxLEAST64 __PRI64_PREFIX "x"
|
#define PRIxFAST16 "%x"
|
||||||
#define PRIxFAST8 "x"
|
#define PRIxFAST32 "%x"
|
||||||
#define PRIxFAST16 "x"
|
#define PRIxFAST64 "%lx"
|
||||||
#define PRIxFAST32 "x"
|
#define PRIxMAX "%lx"
|
||||||
#define PRIxFAST64 __PRI64_PREFIX "x"
|
#define PRIxPTR "%lx"
|
||||||
#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
|
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -1,7 +1,6 @@
|
|||||||
#ifndef _LUNA_H
|
#ifndef _LUNA_H
|
||||||
#define _LUNA_H
|
#define _LUNA_H
|
||||||
|
|
||||||
#include <bits/getprocid.h>
|
|
||||||
#include <bits/macros.h>
|
#include <bits/macros.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
@ -10,9 +9,6 @@ extern "C"
|
|||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Returns a numeric identifier associated with the current process, depending on field. */
|
|
||||||
long getprocid(int field);
|
|
||||||
|
|
||||||
/* Sleeps for ms milliseconds. */
|
/* Sleeps for ms milliseconds. */
|
||||||
unsigned int msleep(unsigned int ms);
|
unsigned int msleep(unsigned int ms);
|
||||||
|
|
||||||
|
@ -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
|
|
@ -4,8 +4,6 @@
|
|||||||
#define OPEN_MAX 32
|
#define OPEN_MAX 32
|
||||||
#define ATEXIT_MAX 32
|
#define ATEXIT_MAX 32
|
||||||
|
|
||||||
#define NAME_MAX 64
|
|
||||||
|
|
||||||
#define PAGESIZE 4096
|
#define PAGESIZE 4096
|
||||||
#define PAGE_SIZE 4096
|
#define PAGE_SIZE 4096
|
||||||
|
|
||||||
|
@ -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
|
|
@ -1,21 +1,42 @@
|
|||||||
#ifndef _LUNA_SYSCALL_H
|
#ifndef _LUNA_SYSCALL_H
|
||||||
#define _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
|
#ifdef __cplusplus
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
long __luna_syscall0(long sys_num);
|
long int __luna_syscall0(long int sys_num);
|
||||||
long __luna_syscall1(long sys_num, unsigned long arg0);
|
long int __luna_syscall1(long int sys_num, unsigned long int arg0);
|
||||||
long __luna_syscall2(long sys_num, unsigned long arg0, unsigned long arg1);
|
long int __luna_syscall2(long int sys_num, unsigned long int arg0, unsigned long int arg1);
|
||||||
long __luna_syscall3(long sys_num, unsigned long arg0, unsigned long arg1, unsigned long arg2);
|
long int __luna_syscall3(long int sys_num, unsigned long int arg0, unsigned long int arg1, unsigned long int arg2);
|
||||||
long __luna_syscall4(long sys_num, unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3);
|
long int __luna_syscall4(long int sys_num, unsigned long int arg0, unsigned long int arg1, unsigned long int arg2,
|
||||||
long __luna_syscall5(long sys_num, unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3,
|
unsigned long int arg3);
|
||||||
unsigned long arg4);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
@ -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
|
|
@ -1,9 +1,7 @@
|
|||||||
#ifndef _SIGNAL_H
|
#ifndef _SIGNAL_H
|
||||||
#define _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
|
typedef int sig_atomic_t; // FIXME: Implement signals (I'm trying to build bc, this header is only to satisfy it) and
|
||||||
// I understood)
|
// use a proper atomic integer type.
|
||||||
|
|
||||||
#define SIGINT 1 // Not implemented.
|
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -3,39 +3,27 @@
|
|||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <bits/seek.h>
|
#include <bits/seek.h>
|
||||||
|
|
||||||
#define FOPEN_MAX 32
|
#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
|
typedef struct
|
||||||
{
|
{
|
||||||
int f_fd;
|
int f_fd;
|
||||||
int f_eof;
|
int f_eof;
|
||||||
int f_err;
|
int f_err;
|
||||||
char* f_buf;
|
|
||||||
long f_bufsize;
|
|
||||||
long f_bufoff;
|
|
||||||
long f_bufrsize;
|
|
||||||
} FILE;
|
} FILE;
|
||||||
|
|
||||||
extern FILE* stderr;
|
extern FILE* stderr;
|
||||||
extern FILE* stdout;
|
extern FILE* stdout;
|
||||||
extern FILE* stdin;
|
|
||||||
#define stdin stdin
|
|
||||||
#define stdout stdout
|
#define stdout stdout
|
||||||
#define stderr stderr
|
#define stderr stderr
|
||||||
|
|
||||||
#define EOF -1
|
typedef struct
|
||||||
|
{
|
||||||
#define _IONBF 0
|
long f_offset;
|
||||||
#define _IOLBF 1
|
} fpos_t;
|
||||||
#define _IOFBF 2
|
|
||||||
|
|
||||||
typedef off_t fpos_t;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C"
|
extern "C"
|
||||||
@ -54,9 +42,6 @@ extern "C"
|
|||||||
/* Returns a new file associated with the file descriptor fd. */
|
/* Returns a new file associated with the file descriptor fd. */
|
||||||
FILE* fdopen(int fd, const char* mode);
|
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. */
|
/* Returns the file descriptor associated with the file stream. */
|
||||||
int fileno(FILE* stream);
|
int fileno(FILE* stream);
|
||||||
|
|
||||||
@ -69,18 +54,12 @@ extern "C"
|
|||||||
/* Moves stream's read/write offset by offset, depending on whence. */
|
/* Moves stream's read/write offset by offset, depending on whence. */
|
||||||
int fseek(FILE* stream, long offset, int 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. */
|
/* Moves stream's read/write offset to the offset stored in the pos structure. */
|
||||||
int fsetpos(FILE* stream, const fpos_t* pos);
|
int fsetpos(FILE* stream, const fpos_t* pos);
|
||||||
|
|
||||||
/* Returns the current offset for stream. */
|
/* Returns the current offset for stream. */
|
||||||
long ftell(FILE* 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. */
|
/* Stores the current offset for stream in the pos structure. */
|
||||||
int fgetpos(FILE* stream, fpos_t* pos);
|
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. */
|
/* 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);
|
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. */
|
/* Returns nonzero if the error flag in stream was set. */
|
||||||
int ferror(FILE* stream);
|
int ferror(FILE* stream);
|
||||||
|
|
||||||
@ -114,7 +79,6 @@ extern "C"
|
|||||||
void clearerr(FILE* stream);
|
void clearerr(FILE* stream);
|
||||||
|
|
||||||
void setbuf(FILE*, char*); // Not implemented.
|
void setbuf(FILE*, char*); // Not implemented.
|
||||||
int setvbuf(FILE*, char*, int, size_t); // Not implemented.
|
|
||||||
|
|
||||||
/* Writes formatted output according to the string format to the file stream. */
|
/* Writes formatted output according to the string format to the file stream. */
|
||||||
int vfprintf(FILE* stream, const char* format, va_list ap);
|
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. */
|
/* 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 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. */
|
/* Writes the string str followed by a trailing newline to stdout. */
|
||||||
int puts(const char* str);
|
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. */
|
* of the last error encountered during a call to a system or library function. */
|
||||||
void perror(const char* str);
|
void perror(const char* str);
|
||||||
|
|
||||||
int remove(const char* pathname); // Not implemented.
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -2,32 +2,8 @@
|
|||||||
#define _STDLIB_H
|
#define _STDLIB_H
|
||||||
|
|
||||||
#include <bits/macros.h>
|
#include <bits/macros.h>
|
||||||
#include <limits.h>
|
|
||||||
#include <stddef.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
|
#ifdef __cplusplus
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
@ -54,12 +30,6 @@ extern "C"
|
|||||||
/* Returns an integer (of type long long) parsed from the string str. */
|
/* Returns an integer (of type long long) parsed from the string str. */
|
||||||
long long atoll(const char* 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. */
|
/* Not implemented. */
|
||||||
char* getenv(const char*);
|
char* getenv(const char*);
|
||||||
|
|
||||||
@ -86,26 +56,6 @@ extern "C"
|
|||||||
/* Seeds the random number generator with the specified seed. */
|
/* Seeds the random number generator with the specified seed. */
|
||||||
void srand(unsigned int 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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -27,10 +27,6 @@ extern "C"
|
|||||||
/* Returns a heap-allocated copy of the string str. Should be freed when it is not used anymore. */
|
/* Returns a heap-allocated copy of the string str. Should be freed when it is not used anymore. */
|
||||||
char* strdup(const char* str);
|
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. */
|
/* Returns the length of the string str. */
|
||||||
size_t strlen(const char* 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. */
|
/* 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);
|
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. */
|
/* Concatenates at most max bytes of the string src into dest. */
|
||||||
char* strncat(char* dest, const char* src, size_t max);
|
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. */
|
/* Compares strings a and b. You might prefer to use the safer strncmp function. */
|
||||||
int strcmp(const char* a, const char* b);
|
int strcmp(const char* a, const char* b);
|
||||||
|
|
||||||
/* Compares at most max bytes of the strings a and b. */
|
/* Compares at most max bytes of the strings a and b. */
|
||||||
int strncmp(const char* a, const char* b, size_t max);
|
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. */
|
/* Searches for the needle string in the haystack string. */
|
||||||
char* strstr(const char* haystack, const char* needle);
|
char* strstr(const char* haystack, const char* needle);
|
||||||
|
|
||||||
/* Returns the error string associated with the error number err. */
|
/* Returns the error string associated with the error number err. */
|
||||||
char* strerror(int 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. */
|
/* 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,
|
__lc_deprecated("strcpy is unsafe and should not be used; use strlcpy instead") char* strcpy(char* dest,
|
||||||
const char* src);
|
const char* src);
|
||||||
|
@ -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
|
|
@ -13,10 +13,6 @@
|
|||||||
|
|
||||||
#define PAGE_SIZE 4096
|
#define PAGE_SIZE 4096
|
||||||
|
|
||||||
#define MAP_PRIVATE 0
|
|
||||||
#define MAP_SHARED 1
|
|
||||||
#define MAP_ANONYMOUS 2
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
@ -30,7 +26,7 @@ extern "C"
|
|||||||
* address space. */
|
* address space. */
|
||||||
int munmap(void* addr, size_t size);
|
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);
|
int mprotect(void* addr, size_t size, int prot);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -1,19 +1,8 @@
|
|||||||
#ifndef _SYS_STAT_H
|
#ifndef _SYS_STAT_H
|
||||||
#define _SYS_STAT_H
|
#define _SYS_STAT_H
|
||||||
|
|
||||||
#include <luna/vfs.h>
|
|
||||||
#include <sys/types.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
|
#ifdef __cplusplus
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
@ -22,9 +11,6 @@ extern "C"
|
|||||||
/* Creates a new directory at the path pathname. FIXME: For now, mode is ignored. */
|
/* Creates a new directory at the path pathname. FIXME: For now, mode is ignored. */
|
||||||
int mkdir(const char* pathname, mode_t mode);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,28 +1,9 @@
|
|||||||
#ifndef _SYS_SYSCALL_H
|
#ifndef _SYS_SYSCALL_H
|
||||||
#define _SYS_SYSCALL_H
|
#define _SYS_SYSCALL_H
|
||||||
|
|
||||||
#define SYS_exit 0
|
#define __want_syscalls
|
||||||
#define SYS_yield 1
|
#include <luna/syscall.h>
|
||||||
#define SYS_sleep 2
|
#undef __want_syscalls
|
||||||
#define SYS_write 3
|
#undef _LUNA_SYSCALL_H
|
||||||
#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
|
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -16,7 +16,4 @@ typedef long int off_t;
|
|||||||
/* The type of a file's mode. */
|
/* The type of a file's mode. */
|
||||||
typedef unsigned short mode_t;
|
typedef unsigned short mode_t;
|
||||||
|
|
||||||
/* The type of a filesystem inode. */
|
|
||||||
typedef unsigned long ino_t;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -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
|
|
@ -1,27 +1,9 @@
|
|||||||
#ifndef _TIME_H
|
#ifndef _TIME_H
|
||||||
#define _TIME_H
|
#define _TIME_H
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
typedef long int clock_t;
|
typedef long int clock_t;
|
||||||
typedef long int time_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
|
#define CLOCKS_PER_SEC 1000
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@ -33,13 +15,6 @@ extern "C"
|
|||||||
* get the value in seconds. */
|
* get the value in seconds. */
|
||||||
clock_t clock(void);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -6,14 +6,8 @@
|
|||||||
#include <luna/os-limits.h>
|
#include <luna/os-limits.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#define STDIN_FILENO 0 // The standard input stream.
|
#define STDOUT_FILENO 0
|
||||||
#define STDOUT_FILENO 1 // The standard output stream.
|
#define STDERR_FILENO 1
|
||||||
#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.
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C"
|
extern "C"
|
||||||
@ -33,12 +27,9 @@ extern "C"
|
|||||||
* the parent. */
|
* the parent. */
|
||||||
pid_t fork(void);
|
pid_t fork(void);
|
||||||
|
|
||||||
/* Returns the current process' process ID. */
|
/* Returns the current process's process ID. */
|
||||||
pid_t getpid(void);
|
pid_t getpid(void);
|
||||||
|
|
||||||
/* Returns the current process' parent's process ID. */
|
|
||||||
pid_t getppid(void);
|
|
||||||
|
|
||||||
/* Terminates the program with the status code status. */
|
/* Terminates the program with the status code status. */
|
||||||
__lc_noreturn void _exit(int status);
|
__lc_noreturn void _exit(int status);
|
||||||
|
|
||||||
@ -63,12 +54,6 @@ extern "C"
|
|||||||
/* Returns a copy of the file descriptor fd. */
|
/* Returns a copy of the file descriptor fd. */
|
||||||
int dup(int 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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -7,35 +7,11 @@
|
|||||||
|
|
||||||
FILE* stderr;
|
FILE* stderr;
|
||||||
FILE* stdout;
|
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"
|
extern "C"
|
||||||
{
|
{
|
||||||
int fclose(FILE* stream)
|
int fclose(FILE* stream)
|
||||||
{
|
{
|
||||||
if (stream->f_buf) free(stream->f_buf);
|
|
||||||
int status = close(stream->f_fd);
|
int status = close(stream->f_fd);
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
{
|
{
|
||||||
@ -70,23 +46,6 @@ extern "C"
|
|||||||
}
|
}
|
||||||
FILE* stream = (FILE*)malloc(sizeof(FILE));
|
FILE* stream = (FILE*)malloc(sizeof(FILE));
|
||||||
if (!stream) { return 0; }
|
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;
|
stream->f_fd = fd;
|
||||||
clearerr(stream);
|
clearerr(stream);
|
||||||
return stream;
|
return stream;
|
||||||
@ -99,9 +58,7 @@ extern "C"
|
|||||||
|
|
||||||
size_t fread(void* buf, size_t size, size_t nmemb, FILE* stream)
|
size_t fread(void* buf, size_t size, size_t nmemb, FILE* stream)
|
||||||
{
|
{
|
||||||
ssize_t status =
|
ssize_t status = read(stream->f_fd, buf, size * nmemb);
|
||||||
read(stream->f_fd, buf,
|
|
||||||
size * nmemb); // FIXME: This function should use file_read_buf() to not conflict with fgets().
|
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
{
|
{
|
||||||
stream->f_err = 1;
|
stream->f_err = 1;
|
||||||
@ -111,79 +68,6 @@ extern "C"
|
|||||||
return (size_t)status;
|
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)
|
int ferror(FILE* stream)
|
||||||
{
|
{
|
||||||
return stream->f_err;
|
return stream->f_err;
|
||||||
@ -206,14 +90,9 @@ extern "C"
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fseeko(FILE* stream, off_t offset, int whence)
|
|
||||||
{
|
|
||||||
return fseek(stream, offset, whence);
|
|
||||||
}
|
|
||||||
|
|
||||||
int fsetpos(FILE* stream, const fpos_t* pos)
|
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)
|
long ftell(FILE* stream)
|
||||||
@ -223,16 +102,11 @@ extern "C"
|
|||||||
// maybe? We'd have to update this value in fread() and fwrite() as well...
|
// 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)
|
int fgetpos(FILE* stream, fpos_t* pos)
|
||||||
{
|
{
|
||||||
long result = ftell(stream);
|
long result = ftell(stream);
|
||||||
if (result < 0) { return -1; }
|
if (result < 0) { return -1; }
|
||||||
*pos = result;
|
pos->f_offset = result;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,9 +132,4 @@ extern "C"
|
|||||||
{
|
{
|
||||||
NOT_IMPLEMENTED("setbuf");
|
NOT_IMPLEMENTED("setbuf");
|
||||||
}
|
}
|
||||||
|
|
||||||
int setvbuf(FILE*, char*, int, size_t)
|
|
||||||
{
|
|
||||||
NOT_IMPLEMENTED("setvbuf");
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -4,13 +4,10 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
__lc_used const char* __argv[] = {NULL}; // For now.
|
|
||||||
|
|
||||||
static void terminate_libc()
|
static void terminate_libc()
|
||||||
{
|
{
|
||||||
fclose(stdout);
|
fclose(stdout);
|
||||||
fclose(stderr);
|
fclose(stderr);
|
||||||
fclose(stdin);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void initialize_random()
|
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()
|
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(STDOUT_FILENO, &stdout, "/dev/console", "rw");
|
||||||
check_for_file(STDERR_FILENO, &stderr, "/dev/console", "rw");
|
check_for_file(STDERR_FILENO, &stderr, "/dev/console", "rw");
|
||||||
|
|
||||||
|
@ -7,11 +7,6 @@
|
|||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
long getprocid(int field)
|
|
||||||
{
|
|
||||||
return syscall(SYS_getprocid, field);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int msleep(unsigned int ms)
|
unsigned int msleep(unsigned int ms)
|
||||||
{
|
{
|
||||||
return (unsigned int)syscall(SYS_sleep, ms);
|
return (unsigned int)syscall(SYS_sleep, ms);
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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
|
|
48
libs/libc/src/luna/syscall.c
Normal file
48
libs/libc/src/luna/syscall.c
Normal 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;
|
||||||
|
}
|
@ -15,14 +15,12 @@ extern "C"
|
|||||||
if (putchar('\n') < 0) return -1;
|
if (putchar('\n') < 0) return -1;
|
||||||
return nwritten + 1;
|
return nwritten + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fputs(const char* s, FILE* stream)
|
int fputs(const char* s, FILE* stream)
|
||||||
{
|
{
|
||||||
int result = (int)fwrite(s, strlen(s), 1, stream);
|
int result = (int)fwrite(s, strlen(s), 1, stream);
|
||||||
if (ferror(stream)) return -1;
|
if (ferror(stream)) return -1;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fputc(int c, FILE* stream)
|
int fputc(int c, FILE* stream)
|
||||||
{
|
{
|
||||||
char chr = (char)c;
|
char chr = (char)c;
|
||||||
@ -30,17 +28,14 @@ extern "C"
|
|||||||
if (ferror(stream)) { return -1; }
|
if (ferror(stream)) { return -1; }
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
int putc(int c, FILE* stream)
|
int putc(int c, FILE* stream)
|
||||||
{
|
{
|
||||||
return fputc(c, stream);
|
return fputc(c, stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
int putchar(int c)
|
int putchar(int c)
|
||||||
{
|
{
|
||||||
return fputc(c, stdout);
|
return fputc(c, stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void perror(const char* s)
|
void perror(const char* s)
|
||||||
{
|
{
|
||||||
int savederr =
|
int savederr =
|
||||||
@ -48,14 +43,4 @@ extern "C"
|
|||||||
if (s && *s) { fprintf(stderr, "%s: ", s); }
|
if (s && *s) { fprintf(stderr, "%s: ", s); }
|
||||||
fprintf(stderr, "%s\n", strerror(savederr));
|
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
Loading…
Reference in New Issue
Block a user