Compare commits
No commits in common. "7328cfe7342ea229dc227c0771623381d69e9ee1" and "82411789e87a2dad2649ce4343ff5e278b3a31e8" have entirely different histories.
7328cfe734
...
82411789e8
38
README.md
38
README.md
@ -11,7 +11,6 @@ A very basic POSIX-based operating system for personal computers, written in C++
|
|||||||
- Can [load ELF programs](kernel/src/thread/ELF.cpp) from the file system as userspace tasks.
|
- Can [load ELF programs](kernel/src/thread/ELF.cpp) from the file system as userspace tasks.
|
||||||
- Boots from an [ext2](apps/preinit.cpp) root filesystem (a bit slow for now).
|
- Boots from an [ext2](apps/preinit.cpp) root filesystem (a bit slow for now).
|
||||||
- [System call](kernel/src/sys/) interface and [C Library](libc/), aiming to be mostly POSIX-compatible.
|
- [System call](kernel/src/sys/) interface and [C Library](libc/), aiming to be mostly POSIX-compatible.
|
||||||
- POSIX [signal](libc/src/signal.cpp) support.
|
|
||||||
- Designed to be [portable](kernel/src/arch), no need to be restricted to x86_64.
|
- Designed to be [portable](kernel/src/arch), no need to be restricted to x86_64.
|
||||||
- Designed around [UTF-8](libluna/include/luna/Utf8.h).
|
- Designed around [UTF-8](libluna/include/luna/Utf8.h).
|
||||||
- Environment-agnostic [utility library](libluna/), which can be used in both kernel and userspace.
|
- Environment-agnostic [utility library](libluna/), which can be used in both kernel and userspace.
|
||||||
@ -24,19 +23,46 @@ To build and run Luna, you will need to build a [GCC Cross-Compiler](https://wik
|
|||||||
|
|
||||||
You should start by installing the [required dependencies](https://wiki.osdev.org/GCC_Cross_Compiler#Installing_Dependencies).
|
You should start by installing the [required dependencies](https://wiki.osdev.org/GCC_Cross_Compiler#Installing_Dependencies).
|
||||||
|
|
||||||
Additionally, some extra Luna-specific dependencies you should install are: cmake, ninja, nasm and genext2fs.
|
|
||||||
|
|
||||||
Then, run `tools/setup.sh` to build the toolchain.
|
Then, run `tools/setup.sh` to build the toolchain.
|
||||||
|
|
||||||
|
This script will check whether you have the required versions of the toolchain already setup, and will skip building them if so. (This means that it is used by the build scripts to install the toolchain if it is missing before building, so you could skip running it manually.)
|
||||||
|
|
||||||
Please beware that building GCC and Binutils can take some time, depending on your machine.
|
Please beware that building GCC and Binutils can take some time, depending on your machine.
|
||||||
|
|
||||||
|
## Building
|
||||||
|
There are a variety of scripts for building Luna.
|
||||||
|
|
||||||
|
`tools/build.sh` will build the kernel, libc and binaries.
|
||||||
|
|
||||||
|
`tools/rebuild.sh` will do a full rebuild of the kernel, libc and binaries.
|
||||||
|
|
||||||
|
`tools/install.sh` will install those to the system root and initial ramdisk.
|
||||||
|
|
||||||
|
`tools/sync-libc.sh` will install the libc headers to the system root, build libc and install it.
|
||||||
|
|
||||||
|
`tools/build-iso.sh` will build, install, and make an ISO disk image named Luna.iso.
|
||||||
|
|
||||||
|
`tools/build-stable-iso.sh` does the same thing as build-iso.sh, but configures the kernel so that the version does not show the commit hash (used for stable versions).
|
||||||
|
|
||||||
|
`tools/rebuild-iso.sh` will do a clean rebuild, install, and make an ISO disk image.
|
||||||
|
|
||||||
|
In most cases, you should just use `run.sh`, but if you want to build without running, `build-iso.sh`.
|
||||||
|
|
||||||
## Running
|
## Running
|
||||||
|
|
||||||
You should have [QEMU](https://www.qemu.org/) installed.
|
You should have [QEMU](https://www.qemu.org/) installed.
|
||||||
|
|
||||||
`tools/run.sh` is the script you should use in most cases. It will build changed files, install, make an ISO image, and run Luna in QEMU.
|
You can choose between 3 run scripts:
|
||||||
|
|
||||||
If you have no toolchain set up, `run.sh` will build it automatically, which means that you don't necessarily have to run `setup.sh` since `run.sh` does it for you.
|
`tools/run.sh` is the one you should use in most cases. It will build changed files, install, make an ISO image, and run Luna in QEMU.
|
||||||
|
|
||||||
|
`tools/rebuild-and-run.sh` will rebuild, install, make an ISO, and run Luna in QEMU.
|
||||||
|
|
||||||
|
`tools/debug.sh` will run Luna in QEMU with a port open for GDB to connect to. (run `tools/build-debug.sh`, `tools/gdb.sh`, and then `tools/debug.sh` in a separate terminal for an optimal debugging experience)
|
||||||
|
|
||||||
|
Essentially, since `run.sh` builds the toolchain if it hasn't been built, builds Luna if it hasn't been built, and runs it, you could just checkout this repo, run `run.sh`, and you're done. No need for the other scripts. Those are included for more fine-grained control/building step-by-step.
|
||||||
|
|
||||||
|
You can pass any arguments you want to the run scripts, and those will be forwarded to QEMU. Example: `tools/run.sh -m 512M -net none -machine q35`.
|
||||||
|
|
||||||
## Prebuilt images
|
## Prebuilt images
|
||||||
|
|
||||||
@ -44,7 +70,7 @@ Prebuilt ISO images (numbered) for every version can be found at [pub.cloudapio.
|
|||||||
|
|
||||||
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.
|
||||||
|
|
||||||
Every hour, this server pulls the latest commits on `main` and builds an hourly ISO image. The ten most recent ones can be found in the [hourly](https://pub.cloudapio.eu/luna/hourly) directory, and [Luna-latest.iso](https://pub.cloudapio.eu/luna/Luna-latest.iso) should always be symlinked to the newest one.
|
Every hour, my server pulls the latest commits on `main` and builds an hourly ISO image. The ten most recent ones can be found in the [hourly](https://pub.cloudapio.eu/luna/hourly) directory, and [Luna-latest.iso](https://pub.cloudapio.eu/luna/Luna-latest.iso) should always be symlinked to the newest one.
|
||||||
|
|
||||||
These images do reflect the latest changes on the `main` branch, but are obviously less stable. Additionally, an hourly image will be skipped if building the latest commit of the project fails.
|
These images do reflect the latest changes on the `main` branch, but are obviously less stable. Additionally, an hourly image will be skipped if building the latest commit of the project fails.
|
||||||
|
|
||||||
|
@ -117,8 +117,6 @@ Result<u64> sys_execve(Registers* regs, SyscallArgs args)
|
|||||||
current->signal_handlers[i] = { .sa_handler = SIG_DFL, .sa_mask = 0, .sa_flags = 0 };
|
current->signal_handlers[i] = { .sa_handler = SIG_DFL, .sa_mask = 0, .sa_flags = 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
current->has_called_exec = true;
|
|
||||||
|
|
||||||
kinfoln("exec: thread %lu was replaced with %s", current->id, path.chars());
|
kinfoln("exec: thread %lu was replaced with %s", current->id, path.chars());
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -95,39 +95,6 @@ Result<u64> sys_setegid(Registers*, SyscallArgs args)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<u64> sys_setpgid(Registers*, SyscallArgs args)
|
|
||||||
{
|
|
||||||
pid_t pid = (pid_t)args[0];
|
|
||||||
pid_t pgid = (pid_t)args[1];
|
|
||||||
|
|
||||||
auto* current = Scheduler::current();
|
|
||||||
if (pid == 0) pid = (pid_t)current->id;
|
|
||||||
if (pgid == 0) pgid = (pid_t)current->id;
|
|
||||||
|
|
||||||
if (pgid < 0) return err(EINVAL);
|
|
||||||
|
|
||||||
auto* thread = TRY(Result<Thread*>::from_option(Scheduler::find_by_pid(pid), ESRCH));
|
|
||||||
if (thread != current && thread->parent != current) return err(ESRCH);
|
|
||||||
|
|
||||||
// FIXME: Weird session stuff, we don't have that currently.
|
|
||||||
|
|
||||||
if (thread->has_called_exec) return err(EPERM);
|
|
||||||
|
|
||||||
if (pgid != (pid_t)current->id)
|
|
||||||
{
|
|
||||||
bool pgid_exists = false;
|
|
||||||
Scheduler::for_each_in_process_group(pgid, [&pgid_exists](Thread*) {
|
|
||||||
pgid_exists = true;
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
if (!pgid_exists) return err(EPERM);
|
|
||||||
}
|
|
||||||
|
|
||||||
thread->pgid = (u64)pgid;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<u64> sys_fchmodat(Registers*, SyscallArgs args)
|
Result<u64> sys_fchmodat(Registers*, SyscallArgs args)
|
||||||
{
|
{
|
||||||
int dirfd = (int)args[0];
|
int dirfd = (int)args[0];
|
||||||
|
@ -45,19 +45,6 @@ namespace Scheduler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Callback> void for_each_in_process_group(pid_t group, Callback callback)
|
|
||||||
{
|
|
||||||
for (Thread* current = g_threads.first().value_or(nullptr); current;
|
|
||||||
current = g_threads.next(current).value_or(nullptr))
|
|
||||||
{
|
|
||||||
if (current->pgid == (u64)group)
|
|
||||||
{
|
|
||||||
bool should_continue = callback(current);
|
|
||||||
if (!should_continue) return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void dump_state();
|
void dump_state();
|
||||||
|
|
||||||
bool has_children(Thread* thread);
|
bool has_children(Thread* thread);
|
||||||
|
@ -57,7 +57,6 @@ struct Thread : public LinkedListNode<Thread>
|
|||||||
Registers regs;
|
Registers regs;
|
||||||
|
|
||||||
u64 id;
|
u64 id;
|
||||||
u64 pgid { 0 };
|
|
||||||
|
|
||||||
Credentials auth;
|
Credentials auth;
|
||||||
|
|
||||||
@ -83,14 +82,14 @@ struct Thread : public LinkedListNode<Thread>
|
|||||||
|
|
||||||
struct sigaction signal_handlers[NSIG];
|
struct sigaction signal_handlers[NSIG];
|
||||||
sigset_t signal_mask { 0 };
|
sigset_t signal_mask { 0 };
|
||||||
sigset_t pending_signals { 0 };
|
|
||||||
|
int pending_signals { 0 };
|
||||||
|
|
||||||
FPData fp_data;
|
FPData fp_data;
|
||||||
|
|
||||||
ThreadState state = ThreadState::Runnable;
|
ThreadState state = ThreadState::Runnable;
|
||||||
|
|
||||||
bool is_kernel { true };
|
bool is_kernel { true };
|
||||||
bool has_called_exec { false };
|
|
||||||
|
|
||||||
int status { 0 };
|
int status { 0 };
|
||||||
|
|
||||||
|
@ -3,8 +3,7 @@
|
|||||||
#ifndef _BITS_ATTRS_H
|
#ifndef _BITS_ATTRS_H
|
||||||
#define _BITS_ATTRS_H
|
#define _BITS_ATTRS_H
|
||||||
|
|
||||||
#if !defined(_STDLIB_H) && !defined(_UNISTD_H) && !defined(_STRING_H) && !defined(_ASSERT_H) && !defined(_SETJMP_H) && \
|
#if !defined(_STDLIB_H) && !defined(_STRING_H) && !defined(_ASSERT_H) && !defined(_SETJMP_H) && !defined(_SYS_TIME_H)
|
||||||
!defined(_SYS_TIME_H)
|
|
||||||
#error "Never include bits/attrs.h directly; use one of the standard library headers."
|
#error "Never include bits/attrs.h directly; use one of the standard library headers."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -49,20 +49,6 @@
|
|||||||
#define PRIuFAST64 __PRI64_PREFIX "u"
|
#define PRIuFAST64 __PRI64_PREFIX "u"
|
||||||
#define PRIuMAX __PRI64_PREFIX "u"
|
#define PRIuMAX __PRI64_PREFIX "u"
|
||||||
#define PRIuPTR __PRI64_PREFIX "u"
|
#define PRIuPTR __PRI64_PREFIX "u"
|
||||||
#define PRIo8 "o"
|
|
||||||
#define PRIo16 "o"
|
|
||||||
#define PRIo32 "o"
|
|
||||||
#define PRIo64 __PRI64_PREFIX "o"
|
|
||||||
#define PRIoLEAST8 "o"
|
|
||||||
#define PRIoLEAST16 "o"
|
|
||||||
#define PRIoLEAST32 "o"
|
|
||||||
#define PRIoLEAST64 __PRI64_PREFIX "o"
|
|
||||||
#define PRIoFAST8 "o"
|
|
||||||
#define PRIoFAST16 "o"
|
|
||||||
#define PRIoFAST32 "o"
|
|
||||||
#define PRIoFAST64 __PRI64_PREFIX "o"
|
|
||||||
#define PRIoMAX __PRI64_PREFIX "o"
|
|
||||||
#define PRIoPTR __PRI64_PREFIX "o"
|
|
||||||
#define PRIx8 "x"
|
#define PRIx8 "x"
|
||||||
#define PRIx16 "x"
|
#define PRIx16 "x"
|
||||||
#define PRIx32 "x"
|
#define PRIx32 "x"
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#include <bits/access.h>
|
#include <bits/access.h>
|
||||||
#include <bits/attrs.h>
|
|
||||||
#include <bits/seek.h>
|
#include <bits/seek.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@ -57,9 +56,6 @@ extern "C"
|
|||||||
/* Set the current process' effective group ID. */
|
/* Set the current process' effective group ID. */
|
||||||
int setegid(gid_t gid);
|
int setegid(gid_t gid);
|
||||||
|
|
||||||
/* Set the current process or a child process's process group. */
|
|
||||||
int setpgid(pid_t pid, pid_t pgid);
|
|
||||||
|
|
||||||
/* Change the owner and group of a file. */
|
/* Change the owner and group of a file. */
|
||||||
int chown(const char* path, uid_t uid, gid_t gid);
|
int chown(const char* path, uid_t uid, gid_t gid);
|
||||||
|
|
||||||
@ -90,9 +86,6 @@ extern "C"
|
|||||||
/* Call the operating system kernel for a specific service. */
|
/* Call the operating system kernel for a specific service. */
|
||||||
long syscall(long num, ...);
|
long syscall(long num, ...);
|
||||||
|
|
||||||
/* Exit the process immediately, without performing any cleanup actions. */
|
|
||||||
__noreturn void _exit(int status);
|
|
||||||
|
|
||||||
/* Sleep for X microseconds. */
|
/* Sleep for X microseconds. */
|
||||||
int usleep(useconds_t us);
|
int usleep(useconds_t us);
|
||||||
|
|
||||||
|
@ -144,12 +144,6 @@ extern "C"
|
|||||||
__errno_return(rc, int);
|
__errno_return(rc, int);
|
||||||
}
|
}
|
||||||
|
|
||||||
int setpgid(pid_t pid, pid_t pgid)
|
|
||||||
{
|
|
||||||
long rc = syscall(SYS_setpgid, pid, pgid);
|
|
||||||
__errno_return(rc, int);
|
|
||||||
}
|
|
||||||
|
|
||||||
int chown(const char* path, uid_t uid, gid_t gid)
|
int chown(const char* path, uid_t uid, gid_t gid)
|
||||||
{
|
{
|
||||||
long rc = syscall(SYS_fchownat, AT_FDCWD, path, uid, gid, 0);
|
long rc = syscall(SYS_fchownat, AT_FDCWD, path, uid, gid, 0);
|
||||||
@ -252,12 +246,6 @@ extern "C"
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
__noreturn void _exit(int status)
|
|
||||||
{
|
|
||||||
syscall(SYS_exit, status);
|
|
||||||
__builtin_unreachable();
|
|
||||||
}
|
|
||||||
|
|
||||||
int usleep(useconds_t us)
|
int usleep(useconds_t us)
|
||||||
{
|
{
|
||||||
long rc = syscall(SYS_usleep, us);
|
long rc = syscall(SYS_usleep, us);
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
_e(getgid) _e(getegid) _e(setuid) _e(setgid) _e(seteuid) _e(setegid) _e(fchmodat) _e(fchownat) _e(ioctl) \
|
_e(getgid) _e(getegid) _e(setuid) _e(setgid) _e(seteuid) _e(setegid) _e(fchmodat) _e(fchownat) _e(ioctl) \
|
||||||
_e(fstatat) _e(chdir) _e(getcwd) _e(unlinkat) _e(uname) _e(sethostname) _e(dup2) _e(pipe) _e(mount) \
|
_e(fstatat) _e(chdir) _e(getcwd) _e(unlinkat) _e(uname) _e(sethostname) _e(dup2) _e(pipe) _e(mount) \
|
||||||
_e(umount) _e(pstat) _e(getrusage) _e(symlinkat) _e(readlinkat) _e(umask) _e(linkat) _e(faccessat) \
|
_e(umount) _e(pstat) _e(getrusage) _e(symlinkat) _e(readlinkat) _e(umask) _e(linkat) _e(faccessat) \
|
||||||
_e(pivot_root) _e(sigreturn) _e(sigaction) _e(kill) _e(sigprocmask) _e(setpgid)
|
_e(pivot_root) _e(sigreturn) _e(sigaction) _e(kill) _e(sigprocmask)
|
||||||
|
|
||||||
enum Syscalls
|
enum Syscalls
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user