Compare commits

..

No commits in common. "b8ca749a6c41610ebc20b21b917771f4a952c3d0" and "da41784183fe38f7ac07cf1d09ddf1a1da5c5194" have entirely different histories.

570 changed files with 20293 additions and 18809 deletions

View File

@ -9,6 +9,4 @@ AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: Always
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: 'true'
PointerAlignment: Left
Cpp11BracedListStyle: 'false'
SpaceBeforeCpp11BracedList: 'true'
PointerAlignment: Left

View File

@ -1,25 +0,0 @@
kind: pipeline
type: docker
name: test
platform:
arch: arm64
os: linux
steps:
- name: build
image: ubuntu
commands:
- apt update
- apt install build-essential cmake ninja-build wget nasm -y
- wget https://pub.cloudapio.eu/luna/toolchains/ci-toolchain-arm64.tar.gz --quiet
- tar xf ci-toolchain-arm64.tar.gz
- rm ci-toolchain-arm64.tar.gz
- tools/rebuild-iso.sh
trigger:
branch:
- main
event:
- push
- pull_request

View File

@ -1,4 +1,4 @@
file kernel/moon
file kernel/bin/moon.elf
break _start
target remote :1234
continue

15
.gitignore vendored
View File

@ -1,8 +1,15 @@
Luna.iso
toolchain/
build/
.vscode/
**/*.o
initrd/boot/moon
env-local.sh
kernel/bin/moon
initrd/sys/moon.sym
initrd/bin/**
initrd/tests/**
base/
apps/bin/**
tests/**/bin/**
base/usr/**
**/*.a
ports/**/workdir/**
ports/ports.list
**/*.pkg.tar.xz

View File

@ -1,19 +0,0 @@
{
"configurations": [
{
"name": "Luna",
"compilerPath": "${workspaceFolder}/toolchain/x86_64-luna/bin/x86_64-luna-gcc",
"cStandard": "c17",
"cppStandard": "c++20",
"intelliSenseMode": "gcc-x64",
"configurationProvider": "ms-vscode.cmake-tools",
"includePath": [
"${default}",
"${workspaceFolder}/base/usr/include",
"${workspaceFolder}/libc/include",
"${workspaceFolder}/libluna/include"
]
}
],
"version": 4
}

17
.vscode/settings.json vendored
View File

@ -1,17 +0,0 @@
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "xaver.clang-format",
"files.exclude": {
"toolchain/build/**": true,
"toolchain/tarballs/**": true,
},
"search.exclude": {
"toolchain/build/**": true,
"toolchain/tarballs/**": true,
},
"editor.tabSize": 4,
"files.trimFinalNewlines": true,
"files.insertFinalNewline": true,
"git.inputValidationLength": 72,
"git.inputValidationSubjectLength": 72
}

View File

@ -1,50 +0,0 @@
cmake_minimum_required(VERSION 3.8..3.22)
set(CMAKE_C_COMPILER_WORKS 1)
set(CMAKE_CXX_COMPILER_WORKS 1)
set(CMAKE_CROSSCOMPILING true)
project(Luna LANGUAGES C CXX ASM ASM_NASM VERSION 0.1.0)
set(LUNA_ROOT ${CMAKE_CURRENT_LIST_DIR})
set(LUNA_BASE ${CMAKE_CURRENT_LIST_DIR}/base)
set(LUNA_ARCH $ENV{LUNA_ARCH})
if(NOT DEFINED LUNA_ARCH)
set(LUNA_ARCH "x86_64")
endif()
set(CMAKE_C_COMPILER ${LUNA_ARCH}-luna-gcc)
set(CMAKE_CXX_COMPILER ${LUNA_ARCH}-luna-g++)
set(CMAKE_ASM_COMPILER ${LUNA_ARCH}-luna-gcc)
set(CMAKE_ASM_NASM_OBJECT_FORMAT elf64)
set(CMAKE_ASM_NASM_LINK_EXECUTABLE "${LUNA_ARCH}-luna-ld <FLAGS> <CMAKE_ASM_NASM_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
set(CMAKE_FIND_ROOT_PATH ${LUNA_ROOT}/toolchain/${LUNA_ARCH}-luna)
message(STATUS "Configuring Luna for ${LUNA_ARCH}")
set(COMMON_FLAGS -Wall -Wextra -Werror -Wvla
-Wdisabled-optimization -Wformat=2 -Winit-self
-Wmissing-include-dirs -Wswitch-default -Wcast-qual
-Wundef -Wcast-align -Wwrite-strings -Wlogical-op
-Wredundant-decls -Wshadow -Wconversion
-fno-asynchronous-unwind-tables -fno-omit-frame-pointer
-std=c++20 -fno-rtti -fno-exceptions)
if(LUNA_NO_OPTIMIZATIONS)
set(COMMON_FLAGS ${COMMON_FLAGS} -ggdb)
else()
set(COMMON_FLAGS ${COMMON_FLAGS} -Os)
endif()
add_subdirectory(libluna)
add_subdirectory(libos)
add_subdirectory(libc)
add_subdirectory(kernel)
add_subdirectory(apps)
add_subdirectory(tests)

View File

@ -1,6 +1,6 @@
BSD 2-Clause License
Copyright (c) 2022-2023, apio.
Copyright (c) 2022, apio.
All rights reserved.
Redistribution and use in source and binary forms, with or without
@ -22,4 +22,4 @@ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

26
Makefile Normal file
View File

@ -0,0 +1,26 @@
CC := x86_64-luna-gcc
CXX := x86_64-luna-g++
ASM := nasm
AR := x86_64-luna-ar
LD := x86_64-luna-ld
build:
+@tools/sync-libc.sh
+@tools/buildstep.sh kernel build
+@tools/buildstep.sh libs build
+@tools/buildstep.sh apps build
clean: initrd-clean
+@tools/buildstep.sh kernel clean
+@tools/buildstep.sh libs clean
+@tools/buildstep.sh apps clean
initrd-clean:
rm -f $(LUNA_ROOT)/initrd/boot/moon $(LUNA_ROOT)/Luna.iso
rm -rf $(LUNA_ROOT)/initrd/bin
install:
+@tools/buildstep.sh kernel install
+@tools/buildstep.sh libs install
+@tools/buildstep.sh apps install
+@tools/install-built-ports.sh

View File

@ -1,25 +1,23 @@
# Luna
A very basic POSIX operating system for desktop computers, written mostly in C++ and C. [![Build Status](https://drone.cloudapio.eu/api/badges/apio/Luna/status.svg)](https://drone.cloudapio.eu/apio/Luna)
## Another UNIX clone?
[Yes, another UNIX clone](https://wiki.osdev.org/User:Sortie/Yes_Another_Unix_Clone).
A simple kernel and userspace for the x86_64 platform, written mostly in C++ and C.
## Features
- x86_64-compatible lightweight [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).
- Can read, write and execute files from a [virtual file system](kernel/src/fs/) supporting an initial ramdisk, device pseudo-filesystems... but no hard disks yet.
- Preemptive multitasking, with a round-robin [scheduler](kernel/src/thread/) that can switch between tasks.
- [Virtual file system](kernel/src/fs/) with a simple but working [tmpfs](kernel/src/fs/tmpfs/) populated from the initial ramdisk.
- Can [load ELF programs](kernel/src/ELF.cpp) from the file system as userspace tasks.
- [System call](kernel/src/sys/) interface and [C Library](libc/), aiming to be mostly POSIX-compatible.
- Designed to be [portable](kernel/src/arch), no need to be restricted to x86_64.
- Fully [UTF-8 aware](libluna/include/luna/Utf8.h), **everywhere**.
- [Thread](libluna/include/luna/Atomic.h) [safety](kernel/src/thread/Spinlock.h) (supposedly).
- Environment-agnostic [utility library](libluna/), which can be used in both kernel and userspace.
- Return-oriented [error propagation](libluna/include/luna/Result.h), inspired by Rust and SerenityOS.
- Build system uses [CMake](CMakeLists.txt).
- Can [load ELF programs](kernel/src/sys/elf/) from the file system as userspace tasks.
- [System call](kernel/src/sys/) interface and [C Library](libs/libc/), aiming to be mostly POSIX-compatible.
- UNIX-like [multitasking primitives](kernel/src/sys/exec.cpp), which allow user tasks to spawn other tasks.
- Some simple [userspace programs](apps/src/), written in C.
- Simple [command-line shell](apps/src/sh.c), allowing for interactive use of the system.
- Basic multi-user system with [a password file](initrd/etc/passwd) and utilities for [logging in](apps/src/session.c) and [switching users](apps/src/su.c).
## Notes
- The default user is named 'selene' and you can log into it with the password 'moon'.
## 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) 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)).
You should start by installing the [required dependencies](https://wiki.osdev.org/GCC_Cross_Compiler#Installing_Dependencies).
@ -30,6 +28,8 @@ This script will check whether you have the required versions of the toolchain a
Please beware that building GCC and Binutils can take some time, depending on your machine.
## Building
Yes, there is a Makefile sitting on the top level of the repository. It's tempting. But do not use it directly, since it depends on environment variables set by the build scripts.
There are a variety of scripts for building Luna.
`tools/build.sh` will build the kernel, libc and binaries.
@ -42,11 +42,13 @@ There are a variety of scripts for building Luna.
`tools/build-iso.sh` will build, install, and make an ISO disk image named Luna.iso.
`tools/build-debug.sh` will rebuild the kernel with debug symbols and optimizations disabled, install, and make an ISO image. This script should only be used when you are going to be running the system with a debugger (such as GDB).
`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`.
In most cases, you should just use `build-iso.sh`.
## Running
@ -54,12 +56,14 @@ You should have [QEMU](https://www.qemu.org/) installed.
You can choose between 3 run scripts:
`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/run.sh` is the one you should use in most cases. It will build (only files that have changed since last build), 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)
Beware that running with optimizations disabled may cause the kernel to behave differently, which is why I don't use it that often.
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`.
@ -76,7 +80,20 @@ These images do reflect the latest changes on the `main` branch, but are obvious
## Is there third-party software I can use on Luna?
Not right now, but hopefully we can start porting some software soon! (After the VFS and fork/exec are done, of course. So, in a long time.)
Yes, actually! Check out the [ports](ports/) directory.
Right now, there are very few ports, because our C Library is a bit primitive and doesn't support complex projects.
You should also keep in mind that it is not possible to compile software written in any language other than C/C++ (and C++ was added recently, its standard library doesn't work very well) for Luna right now.
But feel free to try to port some program yourself and add it to the ports directory!
Port usage:
`ports/add-port.sh <port-name>` will build and add a port to the list of installed ports, and the built port will automatically get installed into the system root every time you run Luna.
`ports/remove-port.sh <port-name>` will remove the port from the list of installed ports, remove built files from the system root, as well as the build directory.
`ports/make-package.sh <port-name>` will compile the port and make a package archive from it, which may be used in the future with a package manager :)
## License
Luna is open-source and free software under the [BSD-2 License](LICENSE).
Luna is open-source and free software under the [BSD-2 License](LICENSE).

View File

@ -1,27 +0,0 @@
function(luna_app SOURCE_FILE APP_NAME SETUID)
add_executable(${APP_NAME} ${SOURCE_FILE})
target_compile_options(${APP_NAME} PRIVATE -Os ${COMMON_FLAGS} -Wno-write-strings)
add_dependencies(${APP_NAME} libc)
target_include_directories(${APP_NAME} PRIVATE ${LUNA_BASE}/usr/include)
target_link_libraries(${APP_NAME} PRIVATE os)
if(${SETUID})
install(TARGETS ${APP_NAME} DESTINATION ${LUNA_ROOT}/initrd/bin PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE SETUID)
else()
install(TARGETS ${APP_NAME} DESTINATION ${LUNA_ROOT}/initrd/bin)
endif()
endfunction()
luna_app(init.cpp init OFF)
luna_app(env.cpp env OFF)
luna_app(su.cpp su ON)
luna_app(sh.cpp sh OFF)
luna_app(cat.cpp cat OFF)
luna_app(date.cpp date OFF)
luna_app(edit.cpp edit OFF)
luna_app(ls.cpp ls OFF)
luna_app(chown.cpp chown OFF)
luna_app(chmod.cpp chmod OFF)
luna_app(mkdir.cpp mkdir OFF)
luna_app(rm.cpp rm OFF)
luna_app(stat.cpp stat OFF)
luna_app(uname.cpp uname OFF)

33
apps/Makefile Normal file
View File

@ -0,0 +1,33 @@
C_APPS := init sh uname uptime hello ps ls args cat stat su session date mkdir screen
CXX_APPS := hello-cpp
APPS_DIR := $(LUNA_ROOT)/apps
APPS_SRC := $(APPS_DIR)/src
APPS_BIN := $(APPS_DIR)/bin
C_APPS_PATH := $(patsubst %, $(APPS_BIN)/%, $(C_APPS))
CXX_APPS_PATH := $(patsubst %, $(APPS_BIN)/%, $(CXX_APPS))
CFLAGS := -Wall -Wextra -Werror -Os -fno-asynchronous-unwind-tables -ffunction-sections -fdata-sections -Wl,--gc-sections
CXXFLAGS := -fno-exceptions
$(APPS_BIN)/%: $(APPS_SRC)/%.c
@mkdir -p $(@D)
@$(CC) $(CFLAGS) -o $@ $^
@echo " CC $^"
$(APPS_BIN)/%: $(APPS_SRC)/%.cpp
@mkdir -p $(@D)
@$(CXX) $(CFLAGS) $(CXXFLAGS) -o $@ $^
@echo " CXX $^"
build: $(C_APPS_PATH) $(CXX_APPS_PATH)
install: $(C_APPS_PATH) $(CXX_APPS_PATH)
@mkdir -p $(LUNA_ROOT)/initrd/bin
@cp $(C_APPS_PATH) $(CXX_APPS_PATH) $(LUNA_ROOT)/initrd/bin
@echo " INSTALL $(C_APPS_PATH) $(CXX_APPS_PATH)"
@chmod a+s $(LUNA_ROOT)/initrd/bin/su
clean:
rm -f $(APPS_BIN)/*

View File

@ -1,42 +0,0 @@
#include <luna/String.h>
#include <os/ArgumentParser.h>
#include <os/File.h>
using os::File;
static Result<void> do_cat(StringView path)
{
SharedPtr<File> f;
auto out = File::standard_output();
if (path == "-") f = File::standard_input();
else
f = TRY(File::open(path, File::ReadOnly));
auto buf = TRY(Buffer::create_sized(4096));
while (1)
{
TRY(f->read(buf, 4096));
if (buf.is_empty()) break;
out->write(buf);
}
return {};
}
Result<int> luna_main(int argc, char** argv)
{
StringView filename;
os::ArgumentParser parser;
parser.add_description("Concatenate files to standard output."_sv);
parser.add_positional_argument(filename, "file"_sv, "-"_sv);
Vector<StringView> extra_files = TRY(parser.parse(argc, argv));
TRY(do_cat(filename));
for (auto file : extra_files) TRY(do_cat(file));
return 0;
}

View File

@ -1,24 +0,0 @@
#include <os/ArgumentParser.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char** argv)
{
StringView mode_string;
StringView path;
os::ArgumentParser parser;
parser.add_description("Change the permissions of a file."_sv);
parser.add_positional_argument(mode_string, "mode"_sv, true);
parser.add_positional_argument(path, "path"_sv, true);
parser.parse(argc, argv);
mode_t mode = (mode_t)strtoul(mode_string.chars(), NULL, 8);
if (chmod(path.chars(), mode) < 0)
{
perror("chmod");
return 1;
}
}

View File

@ -1,78 +0,0 @@
#include <luna/String.h>
#include <os/ArgumentParser.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
Result<int> luna_main(int argc, char** argv)
{
StringView user_and_group;
StringView path;
os::ArgumentParser parser;
parser.add_description("Change the owner and group of a file."_sv);
parser.add_positional_argument(user_and_group, "owner"_sv, true);
parser.add_positional_argument(path, "path"_sv, true);
parser.parse(argc, argv);
u32 uid = -1;
Option<u32> gid = -1;
auto names = TRY(user_and_group.split_once(':'));
if (names.size() > 1)
{
auto& group = names[1];
if (group.is_empty()) { gid = {}; }
else
{
auto rc = group.view().to_uint();
if (rc.has_value()) { gid = (u32)rc.value(); }
else
{
fprintf(stderr, "FIXME: read entry from group file to determine GID for group %s\n", group.chars());
return 1;
}
}
}
if (names.size() > 0)
{
auto& owner = names[0];
if (!owner.is_empty())
{
auto rc = owner.view().to_uint();
if (rc.has_value()) { uid = (u32)rc.value(); }
else
{
struct passwd* pw = getpwnam(owner.chars());
if (!pw)
{
fprintf(stderr, "%s: unknown user %s!\n", argv[0], owner.chars());
return 1;
}
uid = pw->pw_uid;
}
if (!gid.has_value())
{
struct passwd* pw = getpwuid(uid);
if (!pw)
{
fprintf(stderr, "%s: unknown user id %u!\n", argv[0], uid);
return 1;
}
gid = pw->pw_gid;
}
}
}
if (chown(path.chars(), uid, gid.value_or(-1)) < 0)
{
perror("chown");
return 1;
}
return 0;
}

View File

@ -1,23 +0,0 @@
#include <os/ArgumentParser.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(int argc, char** argv)
{
StringView date;
os::ArgumentParser parser;
parser.add_description("Display the current (or another) date and time."_sv);
parser.add_value_argument(date, 'd', "date"_sv, true,
"the UNIX timestamp to display instead of the current time"_sv);
parser.parse(argc, argv);
time_t now;
if (date.is_empty()) { now = time(NULL); }
else { now = strtol(date.chars(), nullptr, 10); }
fputs(ctime(&now), stdout);
}

View File

@ -1,28 +0,0 @@
#include <luna/String.h>
#include <os/ArgumentParser.h>
#include <os/File.h>
using os::File;
Result<int> luna_main(int argc, char** argv)
{
StringView pathname;
os::ArgumentParser parser;
parser.add_description("Edit a file using basic line-based shell editing."_sv);
parser.add_positional_argument(pathname, "path"_sv, true);
parser.parse(argc, argv);
auto file = TRY(File::open_or_create(pathname, File::WriteOnly));
auto input = File::standard_input();
while (1)
{
String line = TRY(input->read_line());
if (line.is_empty()) break;
TRY(file->write(line.view()));
}
return 0;
}

View File

@ -1,9 +0,0 @@
#include <stdio.h>
extern char** environ;
int main()
{
char** env = environ;
while (*env) { puts(*(env++)); }
}

View File

@ -1,262 +0,0 @@
#include <luna/PathParser.h>
#include <luna/String.h>
#include <luna/Vector.h>
#include <os/File.h>
#include <os/Process.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/sysmacros.h>
#include <sys/wait.h>
#include <unistd.h>
FILE* g_init_log;
#define xmknod(path, mode, maj, min) \
if (mknod(path, mode, makedev(maj, min)) < 0) exit(255);
// Too early for console logs (/dev/console is created here!), so we have to resort to exiting with a weird exit code in
// case of failure.
static void populate_devfs()
{
if (mkdir("/dev", 0755) < 0 && errno != EEXIST) exit(255);
xmknod("/dev/console", 0666, 1, 0);
xmknod("/dev/null", 0666, 2, 0);
xmknod("/dev/zero", 0666, 2, 1);
xmknod("/dev/fb0", 0222, 3, 0);
}
struct Service
{
String name;
String command;
bool restart { false };
String environment;
Option<pid_t> pid {};
};
Vector<Service> g_services;
static Result<void> service_child(const Service& service)
{
auto args = TRY(service.command.split(" \n"));
if (service.environment.is_empty()) { TRY(os::Process::exec(args[0].view(), args.slice(), false)); }
else
{
auto env = TRY(service.environment.split(",\n"));
TRY(os::Process::exec(args[0].view(), args.slice(), env.slice(), false));
}
return {};
}
static Result<void> try_start_service(Service& service)
{
pid_t pid = TRY(os::Process::fork());
if (pid == 0)
{
auto rc = service_child(service);
if (rc.has_error())
{
fprintf(g_init_log, "[child %d] failed to start service %s due to error: %s\n", getpid(),
service.name.chars(), rc.error_string());
}
fclose(g_init_log);
exit(127);
}
fprintf(g_init_log, "[init] created new child process %d for service %s\n", pid, service.name.chars());
service.pid = pid;
return {};
}
static void start_service(Service& service)
{
auto rc = try_start_service(service);
if (rc.has_error())
{
fprintf(g_init_log, "[init] failed to start service %s due to error: %s\n", service.name.chars(),
rc.error_string());
}
}
static Result<void> load_service(StringView path)
{
fprintf(g_init_log, "[init] reading service file: %s\n", path.chars());
auto file = TRY(os::File::open(path, os::File::ReadOnly));
Service service;
while (true)
{
auto line = TRY(file->read_line());
if (line.is_empty()) break;
line.trim("\n");
if (line.is_empty()) continue;
auto parts = TRY(line.split_once('='));
if (parts.size() < 2 || parts[0].is_empty() || parts[1].is_empty())
{
fprintf(g_init_log, "[init] file contains invalid line, aborting: '%s'\n", line.chars());
return {};
}
if (parts[0].view() == "Name")
{
service.name = move(parts[1]);
continue;
}
if (parts[0].view() == "Command")
{
service.command = move(parts[1]);
continue;
}
if (parts[0].view() == "Restart")
{
if (parts[1].view() == "true" || parts[1].view().to_uint().value_or(0) == 1)
{
service.restart = true;
continue;
}
service.restart = false;
continue;
}
if (parts[0].view() == "Environment")
{
service.environment = move(parts[1]);
continue;
}
fprintf(g_init_log, "[init] skipping unknown entry name %s\n", parts[0].chars());
}
if (service.name.is_empty())
{
fprintf(g_init_log, "[init] service file is missing 'Name' entry, aborting!\n");
return {};
}
if (service.command.is_empty())
{
fprintf(g_init_log, "[init] service file is missing 'Command' entry, aborting!\n");
return {};
}
fprintf(g_init_log, "[init] loaded service %s into memory\n", service.name.chars());
TRY(g_services.try_append(move(service)));
return {};
}
static Result<void> load_services()
{
DIR* dp = opendir("/etc/init");
if (!dp)
{
fprintf(g_init_log, "[init] cannot open service directory: %s\n", strerror(errno));
return {};
}
dirent* ent;
while ((ent = readdir(dp)))
{
if ("."_sv == ent->d_name || ".."_sv == ent->d_name) continue;
auto service_path = TRY(PathParser::join("/etc/init"_sv, ent->d_name));
TRY(load_service(service_path.view()));
}
closedir(dp);
return {};
}
static Result<void> start_services()
{
TRY(load_services());
for (auto& service : g_services)
{
fprintf(g_init_log, "[init] starting service %s\n", service.name.chars());
start_service(service);
}
return {};
}
static Result<void> set_hostname()
{
auto file = TRY(os::File::open("/etc/hostname", os::File::ReadOnly));
auto hostname = TRY(file->read_line());
hostname.trim("\n");
if (sethostname(hostname.chars(), hostname.length()) < 0) return {};
fprintf(g_init_log, "[init] successfully set system hostname to '%s'\n", hostname.chars());
return {};
}
int main()
{
if (getpid() != 1)
{
fprintf(stderr, "error: init not running as PID 1.\n");
return 1;
}
populate_devfs();
// Before this point, we don't even have an stdin, stdout and stderr. Set it up now so that child processes (and us)
// can print stuff.
stdin = fopen("/dev/console", "r");
stdout = fopen("/dev/console", "w");
stderr = fopen("/dev/console", "w");
g_init_log = fopen("/init.log", "w+");
fcntl(fileno(g_init_log), F_SETFD, FD_CLOEXEC);
set_hostname();
start_services();
while (1)
{
int status;
pid_t child = wait(&status);
for (auto& service : g_services)
{
if (service.pid.has_value() && service.pid.value() == child)
{
fprintf(g_init_log, "[init] service %s exited with status %d\n", service.name.chars(),
WEXITSTATUS(status));
if (service.restart)
{
fprintf(g_init_log, "[init] restarting service %s\n", service.name.chars());
start_service(service);
}
break;
}
}
}
}

View File

@ -1,42 +0,0 @@
#include <os/ArgumentParser.h>
#include <dirent.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
Result<int> luna_main(int argc, char** argv)
{
StringView pathname;
bool show_all { false };
bool show_almost_all { false };
os::ArgumentParser parser;
parser.add_description("List files contained in a directory (defaults to '.', the current directory)"_sv);
parser.add_positional_argument(pathname, "directory"_sv, "."_sv);
parser.add_switch_argument(show_all, 'a', "all"_sv, "also list hidden files (whose filename begins with a dot)"_sv);
parser.add_switch_argument(show_almost_all, 'A', "almost-all"_sv, "list all files except '.' and '..'"_sv);
parser.parse(argc, argv);
DIR* dp = opendir(pathname.chars());
if (!dp)
{
perror("opendir");
return 1;
}
int first_ent = 1;
do {
struct dirent* ent = readdir(dp);
if (!ent) break;
if (show_almost_all && (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))) continue;
if (!show_all && !show_almost_all && *ent->d_name == '.') continue;
printf(first_ent ? "%s" : " %s", ent->d_name);
first_ent = 0;
} while (1);
putchar('\n');
closedir(dp);
return 0;
}

View File

@ -1,51 +0,0 @@
#include <luna/NumberParsing.h>
#include <luna/PathParser.h>
#include <os/ArgumentParser.h>
#include <os/FileSystem.h>
Result<void> mkdir_recursively(StringView path, mode_t mode)
{
begin:
auto rc = os::FileSystem::create_directory(path, mode);
if (!rc.has_error()) return {};
if (rc.error() == EEXIST) return {};
if (rc.error() == ENOENT)
{
PathParser parser = TRY(PathParser::create(path.chars()));
auto parent = TRY(parser.dirname());
TRY(mkdir_recursively(parent.view(), mode));
goto begin;
}
return rc.release_error();
}
Result<int> luna_main(int argc, char** argv)
{
StringView path;
StringView mode_string;
bool recursive;
os::ArgumentParser parser;
parser.add_description("Create directories."_sv);
parser.add_positional_argument(path, "path"_sv, true);
parser.add_positional_argument(mode_string, "mode"_sv, "755"_sv);
parser.add_switch_argument(recursive, 'p', "parents"_sv,
"if parent directories do not exist, create them as well"_sv);
parser.parse(argc, argv);
mode_t mode = (mode_t)parse_unsigned_integer(mode_string.chars(), nullptr, 8);
if (recursive)
{
TRY(mkdir_recursively(path, mode));
return 0;
}
TRY(os::FileSystem::create_directory(path, mode));
return 0;
}

View File

@ -1,21 +0,0 @@
#include <os/ArgumentParser.h>
#include <os/FileSystem.h>
Result<int> luna_main(int argc, char** argv)
{
StringView path;
bool recursive;
os::ArgumentParser parser;
parser.add_description("Remove a path from the file system."_sv);
parser.add_positional_argument(path, "path"_sv, true);
parser.add_switch_argument(recursive, 'r', "recursive"_sv,
"remove a directory recursively (by default, rm removes only empty directories)"_sv);
parser.parse(argc, argv);
if (!recursive) TRY(os::FileSystem::remove(path));
else
TRY(os::FileSystem::remove_tree(path));
return 0;
}

View File

@ -1,118 +0,0 @@
#include <luna/String.h>
#include <luna/Vector.h>
#include <os/ArgumentParser.h>
#include <os/File.h>
#include <os/FileSystem.h>
#include <os/Process.h>
#include <errno.h>
#include <pwd.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/utsname.h>
#include <sys/wait.h>
#include <unistd.h>
using os::File;
static Result<Vector<String>> split_command_into_args(StringView cmd)
{
return cmd.split(" \n"_sv);
}
static Result<void> execute_command(StringView command)
{
auto args = TRY(split_command_into_args(command));
if (args.size() < 1) exit(0);
return os::Process::exec(args[0].view(), args.slice());
}
struct utsname g_sysinfo;
const char* hostname = "";
const char* username = "";
char prompt_end = '$';
Result<int> luna_main(int argc, char** argv)
{
StringView path;
StringView command;
bool interactive { false };
SharedPtr<File> input_file;
os::ArgumentParser parser;
parser.add_description("The Luna system's command shell."_sv);
parser.add_positional_argument(path, "path"_sv, "-"_sv);
parser.add_value_argument(command, 'c', "command"_sv, true, "execute a single command and then exit"_sv);
parser.parse(argc, argv);
if (!command.is_empty()) TRY(execute_command(command));
if (path == "-")
{
input_file = File::standard_input();
interactive = true;
}
else
{
input_file = TRY(File::open(path, File::ReadOnly));
input_file->set_close_on_exec();
}
if (interactive)
{
// Set up everything to form a prompt.
uname(&g_sysinfo);
hostname = g_sysinfo.nodename;
if (getuid() == 0) prompt_end = '#';
struct passwd* pw = getpwuid(getuid());
if (pw) { username = pw->pw_name; }
}
while (1)
{
if (interactive)
{
auto cwd = TRY(os::FileSystem::working_directory());
printf("%s@%s:%s%c ", username, hostname, cwd.chars(), prompt_end);
}
auto cmd = TRY(input_file->read_line());
if (cmd.is_empty()) break;
if (strspn(cmd.chars(), " \n") == cmd.length()) continue;
if (!strncmp(cmd.chars(), "cd", 2))
{
auto args = TRY(split_command_into_args(cmd.view()));
check(args[0].view() == "cd");
if (args.size() == 1)
{
auto home = TRY(os::FileSystem::home_directory());
TRY(os::FileSystem::change_directory(home.view()));
continue;
}
TRY(os::FileSystem::change_directory(args[1].view()));
continue;
}
pid_t child = TRY(os::Process::fork());
if (child == 0) { TRY(execute_command(cmd.view())); }
if (waitpid(child, NULL, 0) < 0)
{
perror("waitpid");
return 1;
}
}
return 0;
}

7
apps/src/args.c Normal file
View File

@ -0,0 +1,7 @@
#include <stdio.h>
#include <unistd.h>
int main(int argc, char** argv)
{
for (int i = 0; i < argc; i++) puts(argv[i]);
}

45
apps/src/cat.c Normal file
View File

@ -0,0 +1,45 @@
#define _GNU_SOURCE // for program_invocation_name
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void cat(FILE* stream)
{
char buf[BUFSIZ];
do {
fgets(buf, BUFSIZ, stream);
if (ferror(stream))
{
perror(program_invocation_name);
exit(EXIT_FAILURE);
}
fputs(buf, stdout);
} while (!feof(stream));
}
int main(int argc, char** argv)
{
if (argc == 1) cat(stdin);
else
{
for (int i = 1; i < argc; i++)
{
if (strcmp(argv[i], "-") == 0) cat(stdin);
else if (strcmp(argv[i], "-n") == 0 || strcmp(argv[i], "--newline") == 0)
putchar('\n');
else
{
FILE* stream = fopen(argv[i], "r");
if (!stream)
{
perror(program_invocation_name);
return EXIT_FAILURE;
}
cat(stream);
fclose(stream);
}
}
}
}

9
apps/src/date.c Normal file
View File

@ -0,0 +1,9 @@
#include <stdio.h>
#include <time.h>
int main()
{
time_t date = time(NULL);
fputs(ctime(&date), stdout);
}

6
apps/src/hello-cpp.cpp Normal file
View File

@ -0,0 +1,6 @@
#include <cstdio>
int main()
{
printf("Well hello world!\n");
}

6
apps/src/hello.c Normal file
View File

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

77
apps/src/init.c Normal file
View File

@ -0,0 +1,77 @@
#include <errno.h>
#include <fcntl.h>
#include <luna.h>
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
void show_motd()
{
int fd = open("/etc/motd", O_RDONLY | O_CLOEXEC);
if (fd < 0)
{
if (errno != ENOENT) { perror("open"); }
return;
}
FILE* fp = fdopen(fd, "r");
if (!fp)
{
perror("fopen");
return;
}
char buf[4096];
size_t nread = fread(buf, 1, sizeof(buf) - 1, fp);
if (ferror(fp))
{
perror("fread");
fclose(fp);
return;
}
buf[nread] = 0;
puts(buf);
fclose(fp);
putchar('\n');
}
int main()
{
if (getpid() != 1)
{
fprintf(stderr, "init must be started as PID 1\n");
return 1;
}
if (getuid() != 0)
{
fprintf(stderr, "init must be started as root\n");
return 1;
}
show_motd();
pid_t child = fork();
if (child < 0)
{
perror("fork");
return 1;
}
if (child == 0)
{
char* argv[] = {"/bin/session", NULL};
execv(argv[0], argv);
perror("execv");
return 1;
}
pid_t result;
for (;;)
{
result = wait(NULL);
if (result == child) return 0;
}
}

31
apps/src/ls.c Normal file
View File

@ -0,0 +1,31 @@
#include <dirent.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc, char** argv)
{
const char* pathname;
if (argc == 1) pathname = "/";
else
pathname = argv[1];
DIR* dp = opendir(pathname);
if (!dp)
{
perror("opendir");
return 1;
}
bool first_ent = true;
do {
struct dirent* ent = readdir(dp);
if (!ent) break;
printf(first_ent ? "%s" : " %s", ent->d_name);
first_ent = false;
} while (1);
printf("\n");
closedir(dp);
return 0;
}

17
apps/src/mkdir.c Normal file
View File

@ -0,0 +1,17 @@
#include <stdio.h>
#include <sys/stat.h>
int main(int argc, char** argv)
{
if (argc == 1)
{
fprintf(stderr, "Usage: %s [directory]", argv[0]);
return 1;
}
if (mkdir(argv[1], 0755) < 0)
{
perror("mkdir");
return 1;
}
}

48
apps/src/ps.c Normal file
View File

@ -0,0 +1,48 @@
#include <errno.h>
#include <luna/pstat.h>
#include <pwd.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)
{
struct passwd* pwd = getpwuid(pstatbuf->pt_uid);
if (!pwd && errno) perror("getpwuid");
printf("%s %ld %ld %s %s (%ld ms)\n", pwd ? pwd->pw_name : "???", 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); }
}
endpwent();
}

32
apps/src/screen.c Normal file
View File

@ -0,0 +1,32 @@
#include <fcntl.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <unistd.h>
int main()
{
int fd = open("/dev/fb0", O_WRONLY | O_CLOEXEC);
if (fd < 0)
{
perror("open");
return 1;
}
int fb_width = ioctl(fd, FB_GET_WIDTH);
if (fb_width < 0)
{
perror("ioctl(FB_GET_WIDTH)");
return 1;
}
int fb_height = ioctl(fd, FB_GET_HEIGHT);
if (fb_height < 0)
{
perror("ioctl(FB_GET_HEIGHT)");
return 1;
}
printf("Your screen is %dx%d\n", fb_width, fb_height);
close(fd);
}

145
apps/src/session.c Normal file
View File

@ -0,0 +1,145 @@
#include <errno.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
static char* echoing_fgets(char* buf, size_t size, FILE* stream)
{
char* s = buf;
memset(buf, 0, size);
size_t oldsize = size;
while (size)
{
int c = fgetc(stream);
if (c == EOF)
{
if (ferror(stream)) return NULL;
if (feof(stream))
{
if (s != buf) return s;
else
return NULL;
};
}
if ((char)c == '\b')
{
if (size != oldsize)
{
buf--;
size++;
putchar('\b');
}
}
else
{
size--;
*buf = (char)c;
buf++;
putchar((char)c);
if ((char)c == '\n') return s;
}
*buf = 0;
}
return s;
}
static void strip_newline(char* str)
{
size_t len = strlen(str);
if (str[len - 1] == '\n') str[len - 1] = 0;
}
static char* collect_password()
{
static char buf[BUFSIZ];
printf("Password: ");
fgets(buf, BUFSIZ, stdin);
strip_newline(buf);
putchar('\n');
char* copy = strdup(
buf); // The password only stays in a caller-controlled heap-allocated buffer, where it can be freed at will.
memset(buf, 0, BUFSIZ);
return copy;
}
static void login_as(struct passwd* user)
{
pid_t child = fork();
if (child < 0)
{
perror("fork");
return;
}
if (child == 0)
{
setgid(user->pw_gid);
setuid(user->pw_uid);
char* argv[] = {user->pw_shell, NULL};
execv(argv[0], argv);
perror("execv");
exit(EXIT_FAILURE);
}
wait(NULL);
}
static int login()
{
printf("Username: ");
char username[BUFSIZ];
echoing_fgets(username, BUFSIZ, stdin);
strip_newline(username);
if (strcmp("exit", username) == 0) return 1;
struct passwd* user = getpwnam(username);
if (!user)
{
if (errno) perror("getpwnam");
else
printf("Unknown user %s\n", username);
return 0;
}
char* password = collect_password();
putchar('\n');
if (strcmp(user->pw_passwd, password) == 0)
{
free(password);
login_as(user);
puts("logout\n");
}
else
{
free(password);
puts("Invalid password.\n");
}
return 0;
}
int main(int argc, char** argv)
{
(void)argc;
if (getuid() != 0)
{
fprintf(stderr,
"%s must be run as root.\nYou are probably looking for the 'su' command, which lets you switch users "
"once logged in.\n",
argv[0]);
return EXIT_FAILURE;
}
for (;;)
{
if (login()) break;
}
endpwent();
return EXIT_SUCCESS;
}

359
apps/src/sh.c Normal file
View File

@ -0,0 +1,359 @@
#include <assert.h>
#include <errno.h>
#include <luna.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
static int status = 0;
static char* username = NULL;
typedef struct
{
char* buffer;
size_t size;
size_t capacity;
int interactive;
} command_t;
char** split_command_into_argv(const char* cmd)
{
size_t argc = 1;
char* ptr = strdup(cmd);
char* endptr;
char** arr = calloc(sizeof(char*), argc);
for (;;)
{
endptr = strchr(ptr, ' ');
arr[argc - 1] = ptr;
if (endptr == NULL) break;
*endptr = 0;
ptr = endptr + 1;
if (*ptr)
{
argc++;
arr = realloc(arr, sizeof(char*) * argc);
}
else
break;
}
argc++;
arr = realloc(arr, sizeof(char*) * argc);
arr[argc - 1] = NULL;
return arr;
}
char* shell_concat_path(const char* dirname, const char* basename)
{
char* buf = malloc(strlen(basename) + strlen(dirname) + 6);
strlcpy(buf, dirname, strlen(dirname) + 1);
strncat(buf, basename, strlen(basename));
return buf;
}
void shell_execvp(char* pathname, char* const argv[])
{
char* new_path;
if (access(pathname, F_OK) == 0)
{
execv(pathname, argv);
return;
}
if (pathname[0] == '/') return; // We do not want to lookup absolute paths
new_path = shell_concat_path("/bin/", pathname);
if (access(new_path, F_OK) == 0)
{
execv(new_path, argv);
return;
}
free(new_path);
new_path = shell_concat_path("/usr/bin/", pathname);
execv(new_path, argv);
int saved = errno;
free(new_path);
errno = saved;
}
void show_prompt()
{
if (WEXITSTATUS(status)) { printf("%d [%s]> ", WEXITSTATUS(status), username); }
else
printf("[%s]> ", username);
}
int command_matches(command_t* 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_t* 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_t* cmd)
{
if (command_matches(cmd, "exit ")) { exit(atoi(cmd->buffer + 5)); }
if (command_matches_exactly(cmd, "exit")) { exit(0); }
if (command_matches_exactly(cmd, "id"))
{
printf("pid %ld, ppid %ld, uid %d (%s), gid %d\n", getpid(), getppid(), getuid(), username, getgid());
return 1;
}
if (command_matches_exactly(cmd, "clear"))
{
fputs("\033@", stdout); // clear screen. for now, escape sequences in luna are non-standard.
return 1;
}
return 0;
}
void command_expand(command_t* 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_t* 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_t* cmd)
{
cmd->size--;
}
void command_init(command_t* cmd)
{
cmd->buffer = malloc(5);
cmd->capacity = 5;
cmd->size = 0;
}
void command_clear(command_t* cmd)
{
free(cmd->buffer);
return command_init(cmd);
}
void process_execute_command(const char* command)
{
char** argv = split_command_into_argv(command);
shell_execvp(argv[0], argv);
perror(argv[0]);
exit(127);
}
void command_execute(command_t* cmd)
{
command_push(cmd, '\0');
if (command_match_builtins(cmd))
{
command_clear(cmd);
if (cmd->interactive) show_prompt();
return;
}
pid_t child = fork();
if (child < 0)
{
perror("fork");
command_clear(cmd);
if (cmd->interactive) show_prompt();
return;
}
if (child == 0) process_execute_command(cmd->buffer);
pid_t result = waitpid(child, &status, 0);
if (result < 0)
{
perror("waitpid");
command_clear(cmd);
if (cmd->interactive) show_prompt();
return;
}
int exit_status = WEXITSTATUS(status);
if (exit_status == -2 || exit_status == -3) printf("(PID %ld) Segmentation fault\n", result);
if (exit_status == -1) printf("(PID %ld) Aborted\n", result);
command_clear(cmd);
if (cmd->interactive) show_prompt();
}
void command_concat_char(command_t* cmd, char c)
{
if (c == '\b')
{
if (cmd->size != 0)
{
if (cmd->interactive) putchar(c);
command_pop(cmd);
}
}
else if (c == '\n')
{
if (cmd->interactive) putchar(c);
if (cmd->size == 0)
{
status = 0;
if (cmd->interactive) show_prompt();
}
else
command_execute(cmd);
}
else
{
if (cmd->interactive) putchar(c);
command_push(cmd, c);
}
}
void command_concat(command_t* cmd, const char* str)
{
while (*str)
{
command_concat_char(cmd, *str);
str++;
}
}
void shell_interactive()
{
show_prompt();
command_t shell_command;
command_init(&shell_command);
shell_command.interactive = 1;
while (1)
{
int c = getchar();
if (c == EOF)
{
if (ferror(stdin))
{
perror("getchar");
exit(EXIT_FAILURE);
}
if (feof(stdin)) exit(EXIT_SUCCESS);
assert(false); // we should never get here
}
command_concat_char(&shell_command, (char)c);
}
}
void shell_read_from_file(const char* pathname)
{
FILE* fp = fopen(pathname, "r");
if (!fp)
{
perror("sh");
exit(EXIT_FAILURE);
}
command_t file_command;
command_init(&file_command);
file_command.interactive = 0;
char buffer[BUFSIZ];
while (fgets(buffer, BUFSIZ, fp))
{
command_concat(&file_command, buffer);
if (feof(fp)) break;
}
if (file_command.size > 0) // last line of file, does not end with newline
{
command_execute(&file_command);
}
fclose(fp);
}
void shell_execute_command(const char* command)
{
command_t cmd;
cmd.buffer = strdup(command);
cmd.size = strlen(command) + 1;
if (command_match_builtins(&cmd)) return;
command_clear(&cmd);
process_execute_command(command);
}
void fetch_username()
{
struct passwd* user = getpwuid(getuid());
if (!user)
{
perror("getpwuid");
exit(EXIT_FAILURE);
}
username = user->pw_name;
endpwent();
}
int main(int argc, char** argv)
{
fetch_username();
if (argc == 1) shell_interactive();
else if (argc == 2)
{
if (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version"))
{
puts("Luna sh version 0.1"); // FIXME: Store the version somewhere, or use the kernel's version.
return 0;
}
if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
{
printf("To use interactively: %s\n", argv[0]);
printf("To run a script: %s [script-name]\n", argv[0]);
printf("To get help: %s --help\n", argv[0]);
printf("To show the version: %s --version\n", argv[0]);
printf("To run a command: %s -c [command]\n", argv[0]);
return 0;
}
if (!strcmp(argv[1], "-c") || !strcmp(argv[1], "--command"))
{
fprintf(stderr, "Usage: %s %s [command]\n", argv[0], argv[1]);
fprintf(stderr, "Use the --help flag for more help.\n");
return 1;
}
shell_read_from_file(argv[1]);
}
else if (argc == 3)
{
if (!strcmp(argv[1], "-c") || !strcmp(argv[1], "--command")) shell_execute_command(argv[2]);
else
{
fprintf(stderr, "%s: too many arguments\n", argv[0]);
fprintf(stderr, "Use the --help flag for more help.\n");
return 1;
}
}
else
{
fprintf(stderr, "%s: too many arguments\n", argv[0]);
fprintf(stderr, "Use the --help flag for more help.\n");
return 1;
}
}

66
apps/src/stat.c Normal file
View File

@ -0,0 +1,66 @@
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <time.h>
const char* mode_to_string(mode_t mode)
{
static char mode_string[12];
char mode_set[12] = {'s', 'g', 'r', 'w', 'x', 'r', 'w', 'x', 'r', 'w', 'x', 0};
mode_t mode_val[12] = {S_ISUID, S_ISGID, S_IRUSR, S_IWUSR, S_IXUSR, S_IRGRP,
S_IWGRP, S_IXGRP, S_IROTH, S_IWOTH, S_IXOTH, S_IFMT};
for (int i = 0; i < 12; i++)
{
if (mode & mode_val[i]) mode_string[i] = mode_set[i];
else
mode_string[i] = '-';
}
return mode_string;
}
int main(int argc, char** argv)
{
if (argc == 1)
{
fprintf(stderr, "Usage: stat [file]\n");
return EXIT_FAILURE;
}
struct stat st;
if (stat(argv[1], &st) < 0)
{
perror("stat");
return EXIT_FAILURE;
}
printf("Type: ");
switch (st.st_mode & S_IFMT)
{
case S_IFREG: puts("Regular file"); break;
case S_IFDIR: puts("Directory"); break;
case S_IFCHR: puts("Character device"); break;
default: puts("Unknown"); break;
}
struct passwd* own = getpwuid(st.st_uid);
printf("Length: %ld\n", st.st_size);
printf("Inode: %ld\n", st.st_ino);
if (!own) printf("Owned by: UID %d\n", st.st_uid);
else
printf("Owned by: %s\n", own->pw_name);
printf("Mode: %s\n", mode_to_string(st.st_mode));
printf("Accessed on: %s", ctime(&st.st_atime));
printf("Modified on: %s", ctime(&st.st_mtime));
printf("Changed on: %s", ctime(&st.st_ctime));
endpwent();
return EXIT_SUCCESS;
}

88
apps/src/su.c Normal file
View File

@ -0,0 +1,88 @@
#include <errno.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
void run_program(char** argv)
{
execv(argv[0], argv);
perror("execv");
exit(EXIT_FAILURE);
}
void strip_newline(char* str)
{
size_t len = strlen(str);
if (str[len - 1] == '\n') str[len - 1] = 0;
}
static const char* collect_password()
{
static char buf[BUFSIZ];
printf("Password: ");
fgets(buf, BUFSIZ, stdin);
strip_newline(buf);
putchar('\n');
return buf;
}
int main(int argc, char** argv)
{
const char* username;
if (argc == 1) username = "root";
else
username = argv[1];
if (geteuid() != 0)
{
fprintf(stderr, "%s must be setuid root", argv[0]);
return EXIT_FAILURE;
}
struct passwd* user = getpwnam(username);
endpwent();
if (!user)
{
if (errno) perror("getpwnam");
else
fprintf(stderr, "Unknown user %s\n", username);
return EXIT_FAILURE;
}
if (getuid() != geteuid()) // we were started from a non-root user
{
const char* pw = collect_password();
if (strcmp(pw, user->pw_passwd) != 0)
{
fprintf(stderr, "Invalid password\n");
return EXIT_FAILURE;
}
}
if (setgid(user->pw_gid) < 0)
{
perror("setgid");
return EXIT_FAILURE;
}
if (setuid(user->pw_uid) < 0)
{
perror("setuid");
return EXIT_FAILURE;
}
char* default_argv[] = {user->pw_shell, NULL};
if (argc < 3) run_program(default_argv);
else
run_program(argv + 2);
}

18
apps/src/uname.c Normal file
View File

@ -0,0 +1,18 @@
#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);
}

38
apps/src/uptime.c Normal file
View File

@ -0,0 +1,38 @@
#include <stdio.h>
#include <time.h>
#define VALUE_SINGULAR_AT_ONE(v) v, v == 1 ? "" : "s"
int main()
{
struct timespec tp;
clock_gettime(CLOCK_MONOTONIC, &tp); // On Luna, CLOCK_MONOTONIC starts at boot.
struct tm* time = gmtime(
&tp.tv_sec); // just splitting the value into seconds, minutes, hours, days... not the best way to do it but ok.
time->tm_year -= 70;
if (time->tm_year)
{
printf("up for %d year%s, %d day%s, %d hour%s, %d minute%s, %d second%s\n",
VALUE_SINGULAR_AT_ONE(time->tm_year), VALUE_SINGULAR_AT_ONE(time->tm_yday),
VALUE_SINGULAR_AT_ONE(time->tm_hour), VALUE_SINGULAR_AT_ONE(time->tm_min),
VALUE_SINGULAR_AT_ONE(time->tm_sec));
}
else if (time->tm_yday)
{
printf("up for %d day%s, %d hour%s, %d minute%s, %d second%s\n", VALUE_SINGULAR_AT_ONE(time->tm_yday),
VALUE_SINGULAR_AT_ONE(time->tm_hour), VALUE_SINGULAR_AT_ONE(time->tm_min),
VALUE_SINGULAR_AT_ONE(time->tm_sec));
}
else if (time->tm_hour)
{
printf("up for %d hour%s, %d minute%s, %d second%s\n", VALUE_SINGULAR_AT_ONE(time->tm_hour),
VALUE_SINGULAR_AT_ONE(time->tm_min), VALUE_SINGULAR_AT_ONE(time->tm_sec));
}
else if (time->tm_min)
printf("up for %d minute%s, %d second%s\n", VALUE_SINGULAR_AT_ONE(time->tm_min),
VALUE_SINGULAR_AT_ONE(time->tm_sec));
else
printf("up for %d second%s\n", VALUE_SINGULAR_AT_ONE(time->tm_sec));
}

View File

@ -1,38 +0,0 @@
#include <os/ArgumentParser.h>
#include <stdio.h>
#include <sys/stat.h>
static const char* file_type(mode_t mode)
{
switch (mode & S_IFMT)
{
case S_IFREG: return "regular file";
case S_IFDIR: return "directory";
case S_IFCHR: return "character special device";
default: return "unknown file type";
}
}
Result<int> luna_main(int argc, char** argv)
{
StringView path;
os::ArgumentParser parser;
parser.add_description("Display file status.");
parser.add_positional_argument(path, "path", true);
parser.parse(argc, argv);
struct stat st;
if (stat(path.chars(), &st) < 0)
{
perror("stat");
return 1;
}
printf(" File: %s\n", path.chars());
printf(" Size: %zu (%s)\n", st.st_size, file_type(st.st_mode));
printf("Inode: %lu Links: %lu\n", st.st_ino, st.st_nlink);
printf(" Mode: %#o UID: %u GID: %u\n", st.st_mode & ~S_IFMT, st.st_uid, st.st_gid);
return 0;
}

View File

@ -1,98 +0,0 @@
#include <bits/termios.h>
#include <os/ArgumentParser.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <unistd.h>
static struct termios orig;
void restore_terminal()
{
ioctl(fileno(stdin), TCSETS, &orig);
}
char* getpass()
{
fputs("Password: ", stdout);
if (ioctl(fileno(stdin), TCGETS, &orig) < 0)
{
perror("ioctl(TCGETS)");
return nullptr;
}
atexit(restore_terminal);
struct termios tc = orig;
tc.c_lflag &= ~ECHO;
if (ioctl(fileno(stdin), TCSETS, &tc) < 0)
{
perror("ioctl(TCSETS)");
return nullptr;
}
static char buf[1024];
char* rc = fgets(buf, sizeof(buf), stdin);
restore_terminal();
putchar('\n');
if (!rc)
{
perror("fgets");
return nullptr;
}
char* newline = strrchr(rc, '\n');
if (newline) *newline = 0;
return buf;
}
Result<int> luna_main(int argc, char** argv)
{
StringView name;
if (geteuid() != 0)
{
fprintf(stderr, "su must be setuid root!\n");
return 1;
}
os::ArgumentParser parser;
parser.add_description("Switch to a different user (by default, root)."_sv);
parser.add_positional_argument(name, "name"_sv, "root"_sv);
parser.parse(argc, argv);
struct passwd* entry = getpwnam(name.chars());
if (!entry)
{
fprintf(stderr, "su: user %s not found!\n", name.chars());
return 1;
}
if (getuid() != geteuid() && *entry->pw_passwd)
{
char* pass = getpass();
if (!pass) return 1;
if (strcmp(pass, entry->pw_passwd))
{
fprintf(stderr, "Wrong password!\n");
return 1;
}
memset(pass, 0, strlen(pass));
}
setgid(entry->pw_gid);
setuid(entry->pw_uid);
chdir(entry->pw_dir);
execl(entry->pw_shell, entry->pw_shell, NULL);
return 1;
}

View File

@ -1,59 +0,0 @@
#include <os/ArgumentParser.h>
#include <stdio.h>
#include <sys/utsname.h>
#define OPERATING_SYSTEM "Luna"
void print_sequenced(const char* string)
{
static bool first { true };
if (!first) { putchar(' '); }
first = false;
fputs(string, stdout);
}
Result<int> luna_main(int argc, char** argv)
{
bool all { false };
bool kernel_name { false };
bool node_name { false };
bool kernel_release { false };
bool kernel_version { false };
bool machine { false };
bool operating_system { false };
os::ArgumentParser parser;
parser.add_description("Print system information. If given no options, defaults to -s."_sv);
parser.add_switch_argument(all, 'a', "all"_sv, "print all information"_sv);
parser.add_switch_argument(kernel_name, 's', "kernel-name"_sv, "print the kernel name"_sv);
parser.add_switch_argument(node_name, 'n', "nodename"_sv, "print the network hostname"_sv);
parser.add_switch_argument(kernel_release, 'r', "kernel-release"_sv, "print the kernel release"_sv);
parser.add_switch_argument(kernel_version, 'v', "kernel-version"_sv, "print the kernel version"_sv);
parser.add_switch_argument(machine, 'm', "machine"_sv, "print the machine name"_sv);
parser.add_switch_argument(operating_system, 'o', "operating-system"_sv, "print the operating system"_sv);
parser.parse(argc, argv);
// If no options are given, default is -s.
if (!all && !kernel_name && !node_name && !kernel_release && !kernel_version && !machine && !operating_system)
kernel_name = true;
if (all) kernel_name = node_name = kernel_release = kernel_version = machine = operating_system = true;
struct utsname info;
if (uname(&info) < 0)
{
perror("uname");
return 1;
}
if (kernel_name) print_sequenced(info.sysname);
if (node_name) print_sequenced(info.nodename);
if (kernel_release) print_sequenced(info.release);
if (kernel_version) print_sequenced(info.version);
if (machine) print_sequenced(info.machine);
if (operating_system) print_sequenced(OPERATING_SYSTEM);
putchar('\n');
return 0;
}

View File

@ -1 +0,0 @@
lunar

View File

@ -1,4 +0,0 @@
Name=shell
Command=/bin/sh
Restart=true
Environment=PATH=/bin:/sbin

View File

@ -1 +1,3 @@
Hello, world!
Welcome to Luna!
Tip of the day: Log in as user 'selene' and password 'moon' :)

View File

@ -1,2 +1,2 @@
root:toor:0:0:Administrator:/:/bin/sh
selene:moon:1000:1000:User:/home/selene:/bin/sh
root:secure:0:0:Administrator:/:/bin/sh
selene:moon:1:1:Default User:/:/bin/sh

View File

@ -1,2 +1,3 @@
screen=1024x768
kernel=boot/moon
kernel=boot/moon
verbose=1

View File

@ -1,110 +0,0 @@
# The Moon kernel for Luna.
file(GLOB_RECURSE HEADERS src/*.h)
set(SOURCES
${HEADERS}
src/main.cpp
src/Log.cpp
src/cxxabi.cpp
src/video/Framebuffer.cpp
src/video/TextConsole.cpp
src/memory/MemoryManager.cpp
src/memory/Heap.cpp
src/memory/KernelVM.cpp
src/memory/UserVM.cpp
src/memory/MemoryMap.cpp
src/boot/Init.cpp
src/arch/Serial.cpp
src/arch/Timer.cpp
src/arch/PCI.cpp
src/thread/Thread.cpp
src/thread/ThreadImage.cpp
src/thread/Scheduler.cpp
src/sys/Syscall.cpp
src/sys/exit.cpp
src/sys/clock_gettime.cpp
src/sys/mmap.cpp
src/sys/usleep.cpp
src/sys/open.cpp
src/sys/exec.cpp
src/sys/file.cpp
src/sys/id.cpp
src/sys/mkdir.cpp
src/sys/mknod.cpp
src/sys/waitpid.cpp
src/sys/getdents.cpp
src/sys/stat.cpp
src/sys/chdir.cpp
src/sys/link.cpp
src/sys/uname.cpp
src/fs/VFS.cpp
src/fs/tmpfs/FileSystem.cpp
src/fs/devices/DeviceRegistry.cpp
src/fs/devices/NullDevice.cpp
src/fs/devices/ZeroDevice.cpp
src/fs/devices/ConsoleDevice.cpp
src/fs/devices/FramebufferDevice.cpp
src/InitRD.cpp
src/ELF.cpp
)
if("${LUNA_ARCH}" MATCHES "x86_64")
set(SOURCES
${SOURCES}
src/arch/x86_64/IO.cpp
src/arch/x86_64/Serial.cpp
src/arch/x86_64/MMU.cpp
src/arch/x86_64/CPU.cpp
src/arch/x86_64/Timer.cpp
src/arch/x86_64/Thread.cpp
src/arch/x86_64/PCI.cpp
src/arch/x86_64/Keyboard.cpp
src/arch/x86_64/init/GDT.cpp
src/arch/x86_64/init/IDT.cpp
src/arch/x86_64/init/PIC.cpp
)
endif()
add_executable(moon ${SOURCES})
if("${LUNA_ARCH}" MATCHES "x86_64")
set(ASM_SOURCES
src/arch/x86_64/CPU.asm
src/arch/x86_64/Entry.asm
)
add_library(moon-asm STATIC ${ASM_SOURCES})
target_link_libraries(moon moon-asm)
endif()
target_link_libraries(moon luna-freestanding)
target_compile_definitions(moon PRIVATE IN_MOON)
target_compile_options(moon PRIVATE ${COMMON_FLAGS})
target_compile_options(moon PRIVATE -nostdlib -mcmodel=kernel -ffreestanding)
if("${LUNA_ARCH}" MATCHES "x86_64")
target_compile_options(moon PRIVATE -mno-red-zone)
target_compile_options(moon PRIVATE -mno-80387 -mno-mmx -mno-sse -mno-sse2)
target_link_options(moon PRIVATE -mno-red-zone)
endif()
if(MOON_DEBUG)
include(debug.cmake)
endif()
target_link_options(moon PRIVATE -lgcc -Wl,--build-id=none -z max-page-size=0x1000 -mcmodel=kernel)
set_target_properties(moon PROPERTIES CXX_STANDARD 20)
target_include_directories(moon PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src)
target_include_directories(moon PRIVATE ${LUNA_BASE}/usr/include)
configure_file(src/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/gen/config.h @ONLY)
target_include_directories(moon PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/gen)
target_link_options(moon PRIVATE LINKER:-T ${CMAKE_CURRENT_LIST_DIR}/moon.ld -nostdlib -nodefaultlibs)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/moon" DESTINATION ${LUNA_ROOT}/initrd/boot)

85
kernel/Makefile Normal file
View File

@ -0,0 +1,85 @@
MOON_DIR := $(realpath $(dir $(abspath $(lastword $(MAKEFILE_LIST)))))
MOON_SRC := $(MOON_DIR)/src
MOON_OBJ := $(MOON_DIR)/lib
MOON_BIN := $(MOON_DIR)/bin
CFLAGS ?= -Os
CFLAGS := ${CFLAGS} -pedantic -Wall -Wextra -Werror -Wvla -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 -ffreestanding -fstack-protector-strong -fno-omit-frame-pointer -mno-red-zone -mno-mmx -mno-sse -mno-sse2 -fshort-wchar -mcmodel=kernel -I$(MOON_DIR)/include -isystem $(MOON_DIR)/include/std
CXXFLAGS := -fno-rtti -fno-exceptions -Wsign-promo -Wstrict-null-sentinel -Wctor-dtor-privacy
ASMFLAGS := -felf64
LDFLAGS := -T$(MOON_DIR)/moon.ld -nostdlib -lgcc -Wl,--build-id=none -z max-page-size=0x1000 -mno-red-zone -mcmodel=kernel
ifneq ($(MOON_BUILD_STABLE), 1)
CFLAGS := ${CFLAGS} -D_MOON_SUFFIX=-$(shell git rev-parse --short HEAD)
endif
ifeq ($(MOON_BUILD_DEBUG), 1)
CFLAGS := -ggdb -fsanitize=undefined ${CFLAGS}
endif
rwildcard=$(foreach d,$(wildcard $(1:=/*)),$(call rwildcard,$d,$2) $(filter $(subst *,%,$2),$d))
CXX_SRC = $(call rwildcard,$(MOON_SRC),*.cpp)
C_SRC = $(call rwildcard,$(MOON_SRC),*.c)
NASM_SRC = $(call rwildcard,$(MOON_SRC),*.asm)
OBJS = $(patsubst $(MOON_SRC)/%.cpp, $(MOON_OBJ)/%.cpp.o, $(CXX_SRC))
OBJS += $(patsubst $(MOON_SRC)/%.c, $(MOON_OBJ)/%.c.o, $(C_SRC))
OBJS += $(patsubst $(MOON_SRC)/%.asm, $(MOON_OBJ)/%.asm.o, $(NASM_SRC))
default: $(MOON_BIN)/moon
$(MOON_OBJ)/main.cpp.o: $(MOON_SRC)/main.cpp
@mkdir -p $(@D)
@$(CXX) $(CFLAGS) -fno-stack-protector $(CXXFLAGS) -o $@ -c $^
@echo " CXX $^"
$(MOON_OBJ)/misc/config.cpp.o: $(MOON_SRC)/misc/config.cpp FORCE
@mkdir -p $(@D)
@$(CXX) $(CFLAGS) $(CXXFLAGS) -o $@ -c $(MOON_SRC)/misc/config.cpp
@echo " CXX $^"
$(MOON_OBJ)/init/Init.cpp.o: $(MOON_SRC)/init/Init.cpp
@mkdir -p $(@D)
@$(CXX) $(CFLAGS) -fno-stack-protector $(CXXFLAGS) -o $@ -c $^
@echo " CXX $^"
$(MOON_OBJ)/%.cpp.o: $(MOON_SRC)/%.cpp
@mkdir -p $(@D)
@$(CXX) $(CFLAGS) $(CXXFLAGS) -o $@ -c $^
@echo " CXX $^"
$(MOON_OBJ)/memory/liballoc/liballoc.c.o: $(MOON_SRC)/memory/liballoc/liballoc.c
@mkdir -p $(@D)
@$(CC) $(CFLAGS) -fno-sanitize=undefined -o $@ -c $^
@echo " CC $^"
$(MOON_OBJ)/%.c.o: $(MOON_SRC)/%.c
@mkdir -p $(@D)
@$(CC) $(CFLAGS) -o $@ -c $^
@echo " CC $^"
$(MOON_OBJ)/%.asm.o: $(MOON_SRC)/%.asm
@mkdir -p $(@D)
@$(ASM) $(ASMFLAGS) -o $@ $^
@echo " ASM $^"
build: $(OBJS)
@mkdir -p $(MOON_BIN)
@$(CC) $(OBJS) $(LDFLAGS) -o $(MOON_BIN)/moon
@echo " CCLD $(MOON_BIN)/moon"
clean:
rm -rf $(MOON_OBJ)/*
rm -rf $(MOON_BIN)/*
install: $(MOON_BIN)/moon
@mkdir -p $(LUNA_ROOT)/initrd/boot
@cp $^ $(LUNA_ROOT)/initrd/boot/moon
@echo " INSTALL $^"
@$(LUNA_ROOT)/tools/generate-symbols.sh
@$(STRIP) $(LUNA_ROOT)/initrd/boot/moon
@echo " STRIP $(LUNA_ROOT)/initrd/boot/moon"
.PHONY: build clean install FORCE
FORCE:

View File

@ -1,6 +0,0 @@
target_compile_definitions(moon PRIVATE LOCKED_VALUE_DEBUG)
target_compile_definitions(moon PRIVATE DEBUG_MODE)
target_compile_definitions(moon PRIVATE ELF_DEBUG)
target_compile_definitions(moon PRIVATE MMU_DEBUG)
target_compile_definitions(moon PRIVATE MMAP_DEBUG)
target_compile_options(moon PRIVATE -fsanitize=undefined)

View File

@ -0,0 +1,93 @@
#pragma once
#include "acpi/SDT.h"
namespace ACPI
{
enum AddressSpace
{
SystemMemory = 0,
SystemIO = 1,
PCI = 2,
EmbeddedController = 3,
SystemManagementBus = 4,
SystemCMOS = 5,
PCIBarTarget = 6,
IPMI = 7,
GeneralPurposeIO = 8,
GenericSerialBus = 9,
PlatformCommunicationChannel = 10
};
struct GenericAddressStructure
{
uint8_t AddressSpace;
uint8_t BitWidth;
uint8_t BitOffset;
uint8_t AccessSize;
uint64_t Address;
};
struct FADT
{
SDTHeader header;
uint32_t FirmwareCtrl;
uint32_t Dsdt;
uint8_t Reserved;
uint8_t PreferredPowerManagementProfile;
uint16_t SCI_Interrupt;
uint32_t SMI_CommandPort;
uint8_t AcpiEnable;
uint8_t AcpiDisable;
uint8_t S4BIOS_REQ;
uint8_t PSTATE_Control;
uint32_t PM1aEventBlock;
uint32_t PM1bEventBlock;
uint32_t PM1aControlBlock;
uint32_t PM1bControlBlock;
uint32_t PM2ControlBlock;
uint32_t PMTimerBlock;
uint32_t GPE0Block;
uint32_t GPE1Block;
uint8_t PM1EventLength;
uint8_t PM1ControlLength;
uint8_t PM2ControlLength;
uint8_t PMTimerLength;
uint8_t GPE0Length;
uint8_t GPE1Length;
uint8_t GPE1Base;
uint8_t CStateControl;
uint16_t WorstC2Latency;
uint16_t WorstC3Latency;
uint16_t FlushSize;
uint16_t FlushStride;
uint8_t DutyOffset;
uint8_t DutyWidth;
uint8_t DayAlarm;
uint8_t MonthAlarm;
uint8_t Century;
uint16_t BootArchitectureFlags;
uint8_t Reserved2;
uint32_t Flags;
GenericAddressStructure ResetReg;
uint8_t ResetValue;
uint8_t Reserved3[3];
uint64_t X_FirmwareControl;
uint64_t X_Dsdt;
GenericAddressStructure X_PM1aEventBlock;
GenericAddressStructure X_PM1bEventBlock;
GenericAddressStructure X_PM1aControlBlock;
GenericAddressStructure X_PM1bControlBlock;
GenericAddressStructure X_PM2ControlBlock;
GenericAddressStructure X_PMTimerBlock;
GenericAddressStructure X_GPE0Block;
GenericAddressStructure X_GPE1Block;
};
}

View File

@ -0,0 +1,25 @@
#pragma once
#include "acpi/SDT.h"
namespace ACPI
{
struct XSDT
{
SDTHeader header;
uint64_t other_sdt[1];
};
struct RSDT
{
SDTHeader header;
uint32_t other_sdt[1];
};
SDTHeader* get_rsdt_or_xsdt();
bool validate_rsdt_or_xsdt(SDTHeader* root_sdt);
bool is_xsdt();
void* find_table(SDTHeader* root_sdt, const char* signature);
}

20
kernel/include/acpi/SDT.h Normal file
View File

@ -0,0 +1,20 @@
#pragma once
#include <stdint.h>
namespace ACPI
{
struct SDTHeader
{
char Signature[4];
uint32_t Length;
uint8_t Revision;
uint8_t Checksum;
char OEMID[6];
char OEMTableID[8];
uint32_t OEMRevision;
uint32_t CreatorID;
uint32_t CreatorRevision;
};
bool validate_sdt_header(SDTHeader* header);
}

View File

@ -1,5 +1,5 @@
/*
* boot/bootboot.h
* bootboot.h
* https://gitlab.com/bztsrc/bootboot
*
* Copyright (C) 2017 - 2021 bzt (bztsrc@gitlab)

7
kernel/include/config.h Normal file
View File

@ -0,0 +1,7 @@
#pragma once
int __moon_version_major();
int __moon_version_minor();
const char* __moon_version_suffix();
const char* moon_version();

14
kernel/include/cpu/CPU.h Normal file
View File

@ -0,0 +1,14 @@
#pragma once
#include "cpu/Features.h"
#include <stdint.h>
namespace CPU
{
const char* get_vendor_string();
const char* get_brand_string();
void log_cpu_information();
uint64_t get_feature_bitmask();
uint64_t get_initial_apic_id();
bool has_feature(CPU::Features);
bool has_nx();
}

View File

@ -0,0 +1,72 @@
#pragma once
namespace CPU
{
enum class Features
{
FPU,
VME,
DE,
PSE,
TSC,
MSR,
PAE,
MCE,
CX8,
APIC,
UNUSED1,
SEP,
MTRR,
PGE,
MCA,
CMOV,
PAT,
PSE36,
PSN,
CLFLUSH,
UNUSED2,
DS,
ACPI,
MMX,
FXSR,
SSE,
SSE2,
SS,
HTT,
TM,
IA64,
PBE,
SSE3,
PCLMUL,
DTES64,
MONITOR,
DS_CPL,
VMX,
SMX,
EST,
TM2,
SSSE3,
CID,
SDBG,
FMA,
CX16,
XTPR,
PDCM,
UNUSED3,
PCID,
DCA,
SSE4_1,
SSE4_2,
X2APIC,
MOVBE,
POPCNT,
TSC_2,
AES,
XSAVE,
OSXSAVE,
AVX,
F16C,
RDRAND,
HYPERVISOR,
};
}

260
kernel/include/font.h Normal file
View File

@ -0,0 +1,260 @@
#pragma once
unsigned char font[] = {
0x00, 0x00, 0x00, 0x00, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 0 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1 */
0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, /* 2 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 3 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 4 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 6 */
0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 7 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 10 */
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 11 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 12 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 13 */
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 14 */
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 15 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 16 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 17 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 18 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 19 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 20 */
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 21 */
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xf8, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 22 */
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 23 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 24 */
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 25 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 26 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 27 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 28 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 29 */
0x00, 0x00, 0x00, 0x1c, 0x22, 0x20, 0x20, 0xf8, 0x20, 0x20, 0x72, 0x8c, 0x00, 0x00, 0x00, 0x00, /* 30 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 31 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 32 */
0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* 33 */
0x00, 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 34 */
0x00, 0x00, 0x00, 0x24, 0x24, 0x7e, 0x24, 0x24, 0x24, 0x7e, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, /* 35 */
0x00, 0x00, 0x08, 0x08, 0x1e, 0x20, 0x20, 0x1c, 0x02, 0x02, 0x3c, 0x08, 0x08, 0x00, 0x00, 0x00, /* 36 */
0x00, 0x00, 0x00, 0x30, 0x49, 0x4a, 0x34, 0x08, 0x16, 0x29, 0x49, 0x06, 0x00, 0x00, 0x00, 0x00, /* 37 */
0x00, 0x00, 0x30, 0x48, 0x48, 0x48, 0x30, 0x31, 0x49, 0x46, 0x46, 0x39, 0x00, 0x00, 0x00, 0x00, /* 38 */
0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 39 */
0x00, 0x00, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x04, 0x00, 0x00, /* 40 */
0x00, 0x00, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x00, 0x00, /* 41 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x18, 0x7e, 0x18, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 42 */
0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x7f, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, /* 43 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x08, 0x08, 0x10, 0x00, /* 44 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 45 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, /* 46 */
0x00, 0x00, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x00, 0x00, /* 47 */
0x00, 0x00, 0x00, 0x3c, 0x42, 0x46, 0x4a, 0x52, 0x62, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 48 */
0x00, 0x00, 0x00, 0x08, 0x18, 0x28, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 49 */
0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x02, 0x04, 0x08, 0x10, 0x20, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 50 */
0x00, 0x00, 0x00, 0x7e, 0x04, 0x08, 0x1c, 0x02, 0x02, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 51 */
0x00, 0x00, 0x00, 0x04, 0x0c, 0x14, 0x24, 0x44, 0x7e, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, /* 52 */
0x00, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x7c, 0x02, 0x02, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 53 */
0x00, 0x00, 0x00, 0x1c, 0x20, 0x40, 0x40, 0x7c, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 54 */
0x00, 0x00, 0x00, 0x7e, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* 55 */
0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x3c, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 56 */
0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x04, 0x38, 0x00, 0x00, 0x00, 0x00, /* 57 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, /* 58 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x08, 0x08, 0x10, 0x00, /* 59 */
0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x40, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, /* 60 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 61 */
0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, /* 62 */
0x00, 0x00, 0x3c, 0x42, 0x02, 0x04, 0x08, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* 63 */
0x00, 0x00, 0x1c, 0x22, 0x41, 0x4f, 0x51, 0x51, 0x51, 0x53, 0x4d, 0x40, 0x20, 0x1f, 0x00, 0x00, /* 64 */
0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 65 */
0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x7c, 0x42, 0x42, 0x42, 0x7c, 0x00, 0x00, 0x00, 0x00, /* 66 */
0x00, 0x00, 0x00, 0x1e, 0x20, 0x40, 0x40, 0x40, 0x40, 0x40, 0x20, 0x1e, 0x00, 0x00, 0x00, 0x00, /* 67 */
0x00, 0x00, 0x00, 0x78, 0x44, 0x42, 0x42, 0x42, 0x42, 0x42, 0x44, 0x78, 0x00, 0x00, 0x00, 0x00, /* 68 */
0x00, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 69 */
0x00, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, /* 70 */
0x00, 0x00, 0x00, 0x1e, 0x20, 0x40, 0x40, 0x46, 0x42, 0x42, 0x22, 0x1e, 0x00, 0x00, 0x00, 0x00, /* 71 */
0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 72 */
0x00, 0x00, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 73 */
0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 74 */
0x00, 0x00, 0x00, 0x42, 0x44, 0x48, 0x50, 0x60, 0x50, 0x48, 0x44, 0x42, 0x00, 0x00, 0x00, 0x00, /* 75 */
0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 76 */
0x00, 0x00, 0x00, 0x41, 0x63, 0x55, 0x49, 0x49, 0x41, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, /* 77 */
0x00, 0x00, 0x00, 0x42, 0x62, 0x52, 0x4a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 78 */
0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 79 */
0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x7c, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, /* 80 */
0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x04, 0x02, 0x00, 0x00, /* 81 */
0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x7c, 0x48, 0x44, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 82 */
0x00, 0x00, 0x00, 0x3e, 0x40, 0x40, 0x20, 0x18, 0x04, 0x02, 0x02, 0x7c, 0x00, 0x00, 0x00, 0x00, /* 83 */
0x00, 0x00, 0x00, 0x7f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 84 */
0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 85 */
0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x24, 0x24, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, /* 86 */
0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x41, 0x49, 0x49, 0x49, 0x55, 0x63, 0x00, 0x00, 0x00, 0x00, /* 87 */
0x00, 0x00, 0x00, 0x41, 0x41, 0x22, 0x14, 0x08, 0x14, 0x22, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, /* 88 */
0x00, 0x00, 0x00, 0x41, 0x41, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 89 */
0x00, 0x00, 0x00, 0x7e, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 90 */
0x00, 0x00, 0x1e, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1e, 0x00, 0x00, /* 91 */
0x00, 0x00, 0x40, 0x40, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x00, 0x00, /* 92 */
0x00, 0x00, 0x78, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x78, 0x00, 0x00, /* 93 */
0x00, 0x00, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 94 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, /* 95 */
0x00, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 96 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 97 */
0x00, 0x00, 0x40, 0x40, 0x40, 0x7c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x7c, 0x00, 0x00, 0x00, 0x00, /* 98 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 99 */
0x00, 0x00, 0x02, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 100 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 101 */
0x00, 0x00, 0x0e, 0x10, 0x10, 0x7e, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* 102 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x3c, 0x00, /* 103 */
0x00, 0x00, 0x40, 0x40, 0x40, 0x7c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 104 */
0x00, 0x00, 0x08, 0x08, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 105 */
0x00, 0x00, 0x04, 0x04, 0x00, 0x1c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x38, 0x00, /* 106 */
0x00, 0x00, 0x40, 0x40, 0x40, 0x44, 0x48, 0x50, 0x70, 0x48, 0x44, 0x42, 0x00, 0x00, 0x00, 0x00, /* 107 */
0x00, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 108 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x00, 0x00, 0x00, 0x00, /* 109 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 110 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 111 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x7c, 0x40, 0x40, 0x40, 0x00, /* 112 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x02, 0x00, /* 113 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, /* 114 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x40, 0x20, 0x18, 0x04, 0x02, 0x7c, 0x00, 0x00, 0x00, 0x00, /* 115 */
0x00, 0x00, 0x00, 0x10, 0x10, 0x7e, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0e, 0x00, 0x00, 0x00, 0x00, /* 116 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 117 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x24, 0x24, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, /* 118 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x49, 0x49, 0x55, 0x63, 0x00, 0x00, 0x00, 0x00, /* 119 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x22, 0x14, 0x08, 0x14, 0x22, 0x41, 0x00, 0x00, 0x00, 0x00, /* 120 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x3c, 0x00, /* 121 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x04, 0x08, 0x10, 0x20, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 122 */
0x00, 0x0e, 0x10, 0x10, 0x10, 0x10, 0x10, 0xe0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0e, 0x00, 0x00, /* 123 */
0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, /* 124 */
0x00, 0x70, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x08, 0x08, 0x08, 0x08, 0x08, 0x70, 0x00, 0x00, /* 125 */
0x00, 0x00, 0x31, 0x49, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 126 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 127 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 128 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 129 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 130 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 131 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 132 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 133 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 134 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 135 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 136 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 137 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 138 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 139 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 140 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 141 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 142 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 143 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 144 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 145 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 146 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 147 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 148 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 149 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 150 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 151 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 152 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 153 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 154 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 155 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 156 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 157 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 158 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 159 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 160 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, /* 161 */
0x00, 0x00, 0x08, 0x08, 0x1c, 0x22, 0x40, 0x40, 0x40, 0x22, 0x1c, 0x08, 0x08, 0x00, 0x00, 0x00, /* 162 */
0x00, 0x00, 0x00, 0x1c, 0x22, 0x20, 0x20, 0xf8, 0x20, 0x20, 0x72, 0x8c, 0x00, 0x00, 0x00, 0x00, /* 163 */
0x00, 0x00, 0x00, 0x00, 0x42, 0x3c, 0x24, 0x24, 0x24, 0x3c, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, /* 164 */
0x00, 0x00, 0x00, 0x41, 0x22, 0x14, 0x08, 0x3e, 0x08, 0x3e, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 165 */
0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, /* 166 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 167 */
0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 168 */
0x00, 0x00, 0x00, 0x1c, 0x22, 0x41, 0x4d, 0x51, 0x51, 0x4d, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, /* 169 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 170 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x12, 0x24, 0x48, 0x24, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00, /* 171 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 172 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 173 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 174 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 175 */
0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 176 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 177 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 178 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 179 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 180 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 181 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 182 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 183 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x30, 0x00, /* 184 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 185 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 186 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x24, 0x12, 0x09, 0x12, 0x24, 0x48, 0x00, 0x00, 0x00, 0x00, /* 187 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 188 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 189 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 190 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x10, 0x20, 0x40, 0x42, 0x3c, 0x00, /* 191 */
0x20, 0x10, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 192 */
0x04, 0x08, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 193 */
0x18, 0x24, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 194 */
0x32, 0x4c, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 195 */
0x24, 0x24, 0x00, 0x18, 0x18, 0x24, 0x24, 0x24, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 196 */
0x18, 0x24, 0x24, 0x18, 0x18, 0x24, 0x24, 0x24, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 197 */
0x00, 0x00, 0x00, 0x0f, 0x14, 0x14, 0x24, 0x27, 0x3c, 0x44, 0x44, 0x47, 0x00, 0x00, 0x00, 0x00, /* 198 */
0x00, 0x00, 0x00, 0x1e, 0x20, 0x40, 0x40, 0x40, 0x40, 0x40, 0x20, 0x1e, 0x08, 0x08, 0x30, 0x00, /* 199 */
0x20, 0x10, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 200 */
0x04, 0x08, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 201 */
0x18, 0x24, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 202 */
0x24, 0x24, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, /* 203 */
0x10, 0x08, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 204 */
0x04, 0x08, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 205 */
0x18, 0x24, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 206 */
0x22, 0x22, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 207 */
0x00, 0x00, 0x00, 0x3c, 0x22, 0x21, 0x21, 0x79, 0x21, 0x21, 0x22, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 208 */
0x32, 0x4c, 0x00, 0x42, 0x62, 0x52, 0x4a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 209 */
0x10, 0x08, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 210 */
0x04, 0x08, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 211 */
0x18, 0x24, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 212 */
0x32, 0x4c, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 213 */
0x24, 0x24, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 214 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x14, 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, /* 215 */
0x00, 0x00, 0x02, 0x3c, 0x42, 0x46, 0x4a, 0x52, 0x62, 0x42, 0x42, 0x3c, 0x40, 0x00, 0x00, 0x00, /* 216 */
0x20, 0x10, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 217 */
0x04, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 218 */
0x18, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 219 */
0x24, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 220 */
0x04, 0x08, 0x00, 0x41, 0x41, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 221 */
0x00, 0x00, 0x00, 0x40, 0x40, 0x7c, 0x42, 0x42, 0x42, 0x7c, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, /* 222 */
0x00, 0x00, 0x00, 0x3c, 0x42, 0x44, 0x4c, 0x42, 0x42, 0x42, 0x44, 0x58, 0x00, 0x00, 0x00, 0x00, /* 223 */
0x00, 0x00, 0x20, 0x10, 0x00, 0x3c, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 224 */
0x00, 0x00, 0x04, 0x08, 0x00, 0x3c, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 225 */
0x00, 0x18, 0x24, 0x00, 0x00, 0x3c, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 226 */
0x00, 0x32, 0x4c, 0x00, 0x00, 0x3c, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 227 */
0x00, 0x00, 0x24, 0x24, 0x00, 0x3c, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 228 */
0x18, 0x24, 0x24, 0x18, 0x00, 0x3c, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 229 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x09, 0x39, 0x4f, 0x48, 0x48, 0x37, 0x00, 0x00, 0x00, 0x00, /* 230 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x40, 0x40, 0x42, 0x3c, 0x08, 0x08, 0x30, 0x00, /* 231 */
0x00, 0x00, 0x20, 0x10, 0x00, 0x3c, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 232 */
0x00, 0x00, 0x04, 0x08, 0x00, 0x3c, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 233 */
0x00, 0x18, 0x24, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 234 */
0x00, 0x00, 0x24, 0x24, 0x00, 0x3c, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 235 */
0x00, 0x00, 0x10, 0x08, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 236 */
0x00, 0x00, 0x04, 0x08, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 237 */
0x00, 0x18, 0x24, 0x00, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 238 */
0x00, 0x00, 0x24, 0x24, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 239 */
0x00, 0x09, 0x06, 0x1a, 0x01, 0x1d, 0x23, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, /* 240 */
0x00, 0x32, 0x4c, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* 241 */
0x00, 0x00, 0x10, 0x08, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 242 */
0x00, 0x00, 0x04, 0x08, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 243 */
0x00, 0x18, 0x24, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 244 */
0x00, 0x32, 0x4c, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 245 */
0x00, 0x00, 0x24, 0x24, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, /* 246 */
0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, /* 247 */
0x00, 0x00, 0x00, 0x00, 0x02, 0x3c, 0x46, 0x4a, 0x52, 0x62, 0x42, 0x3c, 0x40, 0x00, 0x00, 0x00, /* 248 */
0x00, 0x00, 0x20, 0x10, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 249 */
0x00, 0x00, 0x04, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 250 */
0x00, 0x18, 0x24, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 251 */
0x00, 0x00, 0x24, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, /* 252 */
0x00, 0x00, 0x04, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x3c, 0x00, /* 253 */
0x00, 0x00, 0x40, 0x40, 0x40, 0x5c, 0x62, 0x41, 0x41, 0x41, 0x62, 0x5c, 0x40, 0x40, 0x40, 0x00, /* 254 */
0x00, 0x00, 0x24, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x3c, 0x00,
/* 255 */};

View File

@ -0,0 +1,83 @@
#pragma once
#include "fs/VFS.h"
#include <stdint.h>
struct Descriptor
{
bool is_open()
{
return m_is_open;
}
bool can_read()
{
return m_can_read && m_is_open;
}
bool can_write()
{
return m_can_write && m_is_open;
}
void close()
{
m_is_open = false;
}
VFS::Node* node()
{
return m_node;
}
ssize_t read(size_t size, char* buffer);
ssize_t write(size_t size, const char* buffer);
ssize_t user_read(size_t size, char* buffer);
ssize_t user_write(size_t size, const char* buffer);
uintptr_t mmap(uintptr_t addr, size_t size, int prot, off_t offset);
long ioctl(int cmd, uintptr_t arg);
void open(VFS::Node* node, bool can_read, bool can_write, bool able_to_block, bool close_on_exec);
int seek(long offset);
long offset()
{
return (long)m_offset;
}
unsigned long length()
{
return m_node->length;
}
bool able_to_block()
{
return m_able_to_block;
}
bool close_on_exec()
{
return m_close_on_exec;
}
void set_close_on_exec(bool value)
{
m_close_on_exec = value;
}
Descriptor(const Descriptor& other);
Descriptor();
const Descriptor& operator=(const Descriptor& other);
private:
bool m_is_open;
bool m_can_read;
bool m_can_write;
bool m_able_to_block;
bool m_close_on_exec;
VFS::Node* m_node;
uint64_t m_offset;
};

View File

@ -0,0 +1,54 @@
#pragma once
#include <stdint.h>
#include <sys/types.h>
#define TAR_MAGIC "ustar"
#define TAR_BLOCKSIZE 512
namespace InitRD
{
struct TarHeader
{ /* byte offset */
char name[100]; /* 0 */
char mode[8]; /* 100 */
char uid[8]; /* 108 */
char gid[8]; /* 116 */
char size[12]; /* 124 */
char mtime[12]; /* 136 */
char chksum[8]; /* 148 */
char typeflag; /* 156 */
char linkname[100]; /* 157 */
char magic[6]; /* 257 */
char version[2]; /* 263 */
char uname[32]; /* 265 */
char gname[32]; /* 297 */
char devmajor[8]; /* 329 */
char devminor[8]; /* 337 */
char prefix[155]; /* 345 */
/* 500 */
} __attribute__((packed));
struct File
{
char name[100];
uint64_t size;
uint64_t size_in_blocks;
void* addr;
mode_t mode;
};
uint64_t get_total_blocks();
File get_file(TarHeader* header);
void free_file(File& file);
TarHeader* get_block(uint64_t block_index);
bool is_valid_header(TarHeader* header);
uint64_t get_file_physical_address(File& file);
File open(const char* filename);
void for_each(void (*callback)(File& file));
bool is_initialized();
void init();
}

86
kernel/include/fs/VFS.h Normal file
View File

@ -0,0 +1,86 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
#include <sys/types.h>
typedef long ssize_t;
#define VFS_FILE 0x0
#define VFS_DIRECTORY 0x1
#define VFS_DEVICE 0x2
#define VFS_MOUNTPOINT 0x1
#define NAME_MAX 64
namespace VFS
{
struct Node;
typedef ssize_t (*node_read)(Node*, size_t, size_t, char*);
typedef ssize_t (*node_write)(Node*, size_t, size_t, const char*);
typedef Node* (*node_finddir)(Node*, const char*);
typedef int (*node_mkdir)(Node*, const char*, mode_t);
typedef int (*node_block)(Node*);
typedef Node* (*node_readdir)(Node*, long);
typedef uintptr_t (*node_mmap)(Node*, uintptr_t, size_t, int, off_t);
typedef long (*node_ioctl)(Node*, int, uintptr_t);
struct Node
{
char name[NAME_MAX];
int type;
int flags;
int tty = 0;
int uid;
int gid;
mode_t mode;
uint64_t impl;
uint64_t atime;
uint64_t ctime;
uint64_t mtime;
uint64_t inode;
uint64_t length;
node_read read_func;
node_finddir find_func;
node_readdir readdir_func;
node_mkdir mkdir_func;
node_write write_func;
node_block block_func;
node_mmap mmap_func;
node_ioctl ioctl_func;
Node* link;
};
ssize_t read(Node* node, size_t offset, size_t length, char* buffer);
ssize_t write(Node* node, size_t offset, size_t length, const char* buffer);
int mkdir(const char* path, const char* name);
int mkdir(const char* pathname);
int do_mkdir(const char* path, const char* name, int uid, int gid, mode_t mode);
int do_mkdir(const char* pathname, int uid, int gid, mode_t mode);
int would_block(Node* node);
void mount_root(Node* root);
Node* resolve_path(const char* filename, Node* root = nullptr);
bool exists(const char* pathname);
void mount(Node* mountpoint, Node* mounted);
void mount(const char* pathname, Node* mounted);
void unmount(Node* mountpoint);
Node* root();
Node* readdir(Node* dir, long offset);
bool can_execute(Node* node, int uid, int gid);
bool can_read(Node* node, int uid, int gid);
bool can_write(Node* node, int uid, int gid);
bool is_setuid(Node* node);
bool is_setgid(Node* node);
}

View File

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

View File

@ -0,0 +1,10 @@
#pragma once
#include "fs/VFS.h"
namespace DeviceFS
{
VFS::Node* get();
VFS::Node* finddir(VFS::Node* node, const char* filename);
VFS::Node* readdir(VFS::Node* node, long offset);
}

View File

@ -0,0 +1,13 @@
#pragma once
#include "fs/VFS.h"
namespace FramebufferDevice
{
VFS::Node* create_new(const char* devname);
ssize_t write(VFS::Node* node, size_t offset, size_t size, const char* buffer);
uintptr_t mmap(VFS::Node* node, uintptr_t addr, size_t size, int prot, off_t offset);
long ioctl(VFS::Node* node, int cmd, uintptr_t arg);
}

View File

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

View File

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

View File

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

View File

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

View File

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

6
kernel/include/gdt/GDT.h Normal file
View File

@ -0,0 +1,6 @@
#pragma once
namespace GDT
{
void load();
}

View File

@ -2,6 +2,8 @@
namespace Init
{
void early_init();
void check_magic();
}
void disable_smp();
void early_init();
void finish_kernel_boot();
}

View File

@ -0,0 +1,14 @@
#pragma once
#include <stdint.h>
struct Context
{
uint64_t cr2, ds;
uint64_t r15, r14, r13, r12, r11, r10, r9, r8, rsi, rdi, rbp, rdx, rcx, rbx, rax;
uint64_t number;
union {
uint64_t error_code;
uint64_t irq_number;
};
uint64_t rip, cs, rflags, rsp, ss;
};

View File

@ -0,0 +1,18 @@
#pragma once
#include <stdint.h>
#define IDT_TA_InterruptGate 0b10001110
#define IDT_TA_InterruptGateUser 0b11101110
#define IDT_TA_TrapGate 0b10001111
struct IDTR
{
uint16_t limit;
uint64_t offset;
} __attribute__((packed));
namespace IDT
{
void add_handler(short interrupt_number, void* handler, uint8_t type_attr);
void load();
}

View File

@ -0,0 +1,7 @@
#pragma once
#include "Context.h"
namespace IRQ
{
void interrupt_handler(Context* context);
}

View File

@ -0,0 +1,7 @@
#pragma once
#include <stdint.h>
namespace Interrupts
{
void install();
}

View File

@ -0,0 +1,17 @@
#pragma once
#include "interrupts/Context.h"
namespace Interrupts
{
void enable();
void disable();
bool is_in_handler();
void return_from_handler(Context* context);
bool are_enabled();
bool were_enabled();
void push_and_disable();
void push_and_enable();
void pop();
}

13
kernel/include/io/IO.h Normal file
View File

@ -0,0 +1,13 @@
#pragma once
#include <stdint.h>
namespace IO
{
uint8_t inb(uint16_t);
void outb(uint16_t, uint8_t);
uint16_t inw(uint16_t);
void outw(uint16_t, uint16_t);
uint32_t inl(uint16_t);
void outl(uint16_t, uint32_t);
void delay();
}

98
kernel/include/io/PCI.h Normal file
View File

@ -0,0 +1,98 @@
#pragma once
#include <stdint.h>
#define PCI_VENDOR_FIELD 0x0
#define PCI_DEVICE_FIELD 0x2
#define PCI_SUBCLASS_FIELD 0xa
#define PCI_CLASS_FIELD 0xb
#define PCI_REVISION_ID_FIELD 0x8
#define PCI_PROG_IF_FIELD 0x9
#define PCI_HEADER_TYPE_FIELD 0xe
#define PCI_SECONDARY_BUS_NUMBER_FIELD 0x19
#define PCI_BAR0_FIELD 0x10
#define PCI_BAR1_FIELD 0x14
#define PCI_BAR2_FIELD 0x18
#define PCI_BAR3_FIELD 0x1C
#define PCI_BAR4_FIELD 0x20
#define PCI_BAR5_FIELD 0x24
namespace PCI
{
struct DeviceID
{
uint16_t vendor;
uint16_t device;
};
struct DeviceType
{
uint8_t dev_class;
uint8_t dev_subclass;
uint8_t prog_if;
uint8_t revision;
};
struct Device
{
void write8(int32_t offset, uint8_t value);
void write16(int32_t offset, uint16_t value);
void write32(int32_t offset, uint32_t value);
uint8_t read8(int32_t offset);
uint16_t read16(int32_t offset);
uint32_t read32(int32_t offset);
uint32_t getBAR0();
uint32_t getBAR1();
uint32_t getBAR2();
uint32_t getBAR3();
uint32_t getBAR4();
uint32_t getBAR5();
uint8_t bus()
{
return m_bus;
}
uint8_t slot()
{
return m_slot;
}
uint8_t function()
{
return m_function;
}
DeviceID id()
{
return m_id;
}
DeviceType type()
{
return m_type;
}
Device(DeviceID id, DeviceType type, uint8_t bus, uint8_t slot, uint8_t function);
Device(uint8_t bus, uint8_t slot, uint8_t function);
Device(const Device& other);
private:
DeviceID m_id;
DeviceType m_type;
uint8_t m_bus;
uint8_t m_slot;
uint8_t m_function;
};
uint32_t raw_address(uint32_t bus, uint32_t slot, uint32_t function, int32_t offset);
void raw_write8(uint32_t bus, uint32_t slot, uint32_t function, int32_t offset, uint8_t value);
void raw_write16(uint32_t bus, uint32_t slot, uint32_t function, int32_t offset, uint16_t value);
void raw_write32(uint32_t bus, uint32_t slot, uint32_t function, int32_t offset, uint32_t value);
uint8_t raw_read8(uint32_t bus, uint32_t slot, uint32_t function, int32_t offset);
uint16_t raw_read16(uint32_t bus, uint32_t slot, uint32_t function, int32_t offset);
uint32_t raw_read32(uint32_t bus, uint32_t slot, uint32_t function, int32_t offset);
DeviceID get_device_id(uint32_t bus, uint32_t slot, uint32_t function);
DeviceType get_device_type(uint32_t bus, uint32_t slot, uint32_t function);
void scan(void (*callback)(PCI::Device&));
}

12
kernel/include/io/PIC.h Normal file
View File

@ -0,0 +1,12 @@
#pragma once
#include <stdint.h>
namespace PIC
{
void remap();
void end_slave();
void end_master();
void enable_master(uint8_t mask);
void enable_slave(uint8_t mask);
void send_eoi(unsigned char irq);
}

View File

@ -0,0 +1,13 @@
#pragma once
#include "render/Color.h"
#include <stddef.h>
namespace Serial
{
void wait();
void write(const char* string, size_t size);
void print(const char* string);
void println(const char* string);
void set_color(Color& color);
void reset_color();
}

41
kernel/include/log/Log.h Normal file
View File

@ -0,0 +1,41 @@
#pragma once
enum class LogLevel
{
DEBUG,
INFO,
WARN,
ERROR
};
enum class Backend
{
Serial,
Console
};
#define PRINTF_LIKE(n, m) __attribute__((format(printf, n, m)))
namespace KernelLog
{
void log(const char* function, LogLevel level, const char* message, ...) PRINTF_LIKE(3, 4);
void logln(const char* function, LogLevel level, const char* message, ...) PRINTF_LIKE(3, 4);
void toggle_log_level(LogLevel level);
void toggle_log_backend(Backend backend);
void enable_log_backend(Backend backend);
}
#ifndef MODULE
#define kcommonlog(function, level, ...) KernelLog::function(__FUNCTION__, level, __VA_ARGS__)
#else
#define kcommonlog(function, level, ...) KernelLog::function(MODULE, level, __VA_ARGS__)
#endif
#define kdbg(...) kcommonlog(log, LogLevel::DEBUG, __VA_ARGS__)
#define kdbgln(...) kcommonlog(logln, LogLevel::DEBUG, __VA_ARGS__)
#define kinfo(...) kcommonlog(log, LogLevel::INFO, __VA_ARGS__)
#define kinfoln(...) kcommonlog(logln, LogLevel::INFO, __VA_ARGS__)
#define kwarn(...) kcommonlog(log, LogLevel::WARN, __VA_ARGS__)
#define kwarnln(...) kcommonlog(logln, LogLevel::WARN, __VA_ARGS__)
#define kerror(...) kcommonlog(log, LogLevel::ERROR, __VA_ARGS__)
#define kerrorln(...) kcommonlog(logln, LogLevel::ERROR, __VA_ARGS__)

View File

@ -0,0 +1,21 @@
#pragma once
#include "memory/Paging.h"
struct AddressSpace
{
static AddressSpace create();
void destroy();
void clear();
AddressSpace clone();
PageTable* get_pml4()
{
return m_pml4;
}
private:
PageTable* m_pml4;
};

View File

@ -0,0 +1,15 @@
#pragma once
#include <stdint.h>
namespace KernelHeap
{ // Virtual memory allocator for the kernel, goes from -128MB to -64MB
uint64_t request_virtual_page();
uint64_t request_virtual_pages(uint64_t count);
void free_virtual_page(uint64_t address);
void free_virtual_pages(uint64_t address, uint64_t count);
void clear();
void dump_usage();
}

View File

@ -0,0 +1,11 @@
#pragma once
#include <stdint.h>
namespace Memory
{
uint64_t get_system();
uint64_t get_usable();
bool is_user_address(uintptr_t address);
bool is_kernel_address(uintptr_t address);
}

View File

@ -0,0 +1,40 @@
#pragma once
#include <stdint.h>
#ifndef PAGE_SIZE
#define PAGE_SIZE 4096
#endif
#define MAP_READ_WRITE 1 << 0
#define MAP_USER 1 << 1
#define MAP_EXEC 1 << 2
#define MAP_AS_OWNED_BY_TASK 1 << 3
namespace MemoryManager
{
void init();
void protect_kernel_sections();
void* get_mapping(void* physicalAddress, int flags = MAP_READ_WRITE);
void release_mapping(void* mapping);
void* get_unaligned_mapping(void* physicalAddress, int flags = MAP_READ_WRITE);
void* get_unaligned_mappings(void* physicalAddress, uint64_t count, int flags = MAP_READ_WRITE);
void release_unaligned_mapping(void* mapping);
void release_unaligned_mappings(void* mapping, uint64_t count);
void* get_page(int flags = MAP_READ_WRITE);
void* get_pages(uint64_t count, int flags = MAP_READ_WRITE);
void* get_page_at(uint64_t addr, int flags = MAP_READ_WRITE);
void* get_pages_at(uint64_t addr, uint64_t count, int flags = MAP_READ_WRITE);
void release_page(void* page);
void release_pages(void* pages, uint64_t count);
void protect(void* page, uint64_t count, int flags);
void map_several_pages(uint64_t physicalAddress, uint64_t virtualAddress, uint64_t count,
int flags = MAP_READ_WRITE);
}

View File

@ -0,0 +1,6 @@
#pragma once
namespace Memory
{
void walk_memory_map();
}

View File

@ -0,0 +1,27 @@
#pragma once
#include <stdint.h>
#define PMM_FAILED (void*)-1
#define PMM_DID_FAIL(addr) (void*)addr == PMM_FAILED
namespace PMM
{
void init();
void* request_page();
void* request_pages(uint64_t count);
void free_page(void* address);
void free_pages(void* address, uint64_t count);
void lock_page(void* address);
void lock_pages(void* address, uint64_t count);
uint64_t get_free();
uint64_t get_used();
uint64_t get_reserved();
uint64_t get_bitmap_size();
void map_bitmap_to_virtual();
};

View File

@ -0,0 +1,34 @@
#pragma once
#include <stdint.h>
#ifndef PAGE_SIZE
#define PAGE_SIZE 4096
#endif
struct PageDirectoryEntry
{
bool present : 1;
bool read_write : 1;
bool user : 1;
bool write_through : 1;
bool cache_disabled : 1;
bool accessed : 1;
bool ignore0 : 1;
bool larger_pages : 1;
bool ignore1 : 1;
uint8_t available : 3;
uint64_t address : 48;
bool owned_by_task : 1; // Part of the available for OS use bits.
uint8_t available2 : 2;
bool no_execute : 1;
void set_address(uint64_t addr);
uint64_t get_address();
} __attribute__((packed));
struct PageTable
{
PageDirectoryEntry entries[512];
} __attribute__((aligned(PAGE_SIZE)));
static_assert(sizeof(PageDirectoryEntry) == 8UL);

View File

@ -0,0 +1,27 @@
#pragma once
#include <stdint.h>
struct UserHeap
{
bool init();
uint64_t request_virtual_page();
uint64_t request_virtual_pages(uint64_t count);
void free_virtual_page(uint64_t address);
void free_virtual_pages(uint64_t address, uint64_t count);
void free();
bool inherit(UserHeap& other);
private:
uint8_t* bitmap = nullptr;
uint64_t bitmap_size = 0;
uint64_t start_index = 0;
bool bitmap_read(uint64_t index);
void bitmap_set(uint64_t index, bool value);
bool try_expand();
bool try_expand_size(uint64_t size);
};

View File

@ -0,0 +1,48 @@
#pragma once
#include "memory/AddressSpace.h"
#include "memory/Paging.h"
enum Flags
{
ReadWrite = 1 << 0,
User = 1 << 1,
Execute = 1 << 2,
OwnedByTask = 1 << 3,
};
namespace VMM
{
void init(); // Fetch page table from cr3
void switch_to_user_address_space(AddressSpace& space);
void switch_to_previous_user_address_space();
void switch_back_to_kernel_address_space();
void enter_syscall_context();
void exit_syscall_context();
void apply_address_space();
bool is_using_kernel_address_space();
void map(uint64_t vaddr, uint64_t paddr, int flags);
void remap(uint64_t vaddr, int flags);
void unmap(uint64_t vaddr);
uint64_t get_physical(uint64_t vaddr);
uint64_t get_flags(uint64_t vaddr);
PageDirectoryEntry* find_pde(PageTable* root, uint64_t vaddr);
PageDirectoryEntry* create_pde_if_not_exists(PageTable* root, uint64_t vaddr);
void propagate_read_write(PageTable* root, uint64_t vaddr);
void propagate_no_execute(PageTable* root, uint64_t vaddr);
void propagate_user(PageTable* root, uint64_t vaddr);
void flush_tlb(uint64_t addr);
void flush_tlb_full();
void decompose_vaddr(uint64_t vaddr, uint64_t& page_index, uint64_t& pt_index, uint64_t& pd_index,
uint64_t& pdp_index);
uint64_t recompose_vaddr(uint64_t page_index, uint64_t pt_index, uint64_t pd_index, uint64_t pdp_index);
void install_kernel_page_directory_into_address_space(AddressSpace& space);
};

View File

@ -0,0 +1,75 @@
#ifndef _LIBALLOC_H
#define _LIBALLOC_H
#include <stddef.h>
/** \defgroup ALLOCHOOKS liballoc hooks
*
* These are the OS specific functions which need to
* be implemented on any platform that the library
* is expected to work on.
*/
/** @{ */
// If we are told to not define our own size_t, then we skip the define.
//#define _HAVE_UINTPTR_T
// typedef unsigned long uintptr_t;
// This lets you prefix malloc and friends
#define PREFIX(func) k##func
#ifdef __cplusplus
extern "C"
{
#endif
#ifndef __skip_bindings
/** This function is supposed to lock the memory data structures. It
* could be as simple as disabling interrupts or acquiring a spinlock.
* It's up to you to decide.
*
* \return 0 if the lock was acquired successfully. Anything else is
* failure.
*/
extern int liballoc_lock();
/** This function unlocks what was previously locked by the liballoc_lock
* function. If it disabled interrupts, it enables interrupts. If it
* had acquiried a spinlock, it releases the spinlock. etc.
*
* \return 0 if the lock was successfully released.
*/
extern int liballoc_unlock();
/** This is the hook into the local system which allocates pages. It
* accepts an integer parameter which is the number of pages
* required. The page size was set up in the liballoc_init function.
*
* \return NULL if the pages were not allocated.
* \return A pointer to the allocated memory.
*/
extern void* liballoc_alloc(size_t);
/** This frees previously allocated memory. The void* parameter passed
* to the function is the exact same value returned from a previous
* liballoc_alloc call.
*
* The integer value is the number of pages to free.
*
* \return 0 if the memory was successfully freed.
*/
extern int liballoc_free(void*, size_t);
#endif
extern void* PREFIX(malloc)(size_t); ///< The standard function.
extern void* PREFIX(realloc)(void*, size_t); ///< The standard function.
extern void* PREFIX(calloc)(size_t, size_t); ///< The standard function.
extern void PREFIX(free)(void*); ///< The standard function.
#ifdef __cplusplus
}
#endif
/** @} */
#endif

21
kernel/include/misc/MSR.h Normal file
View File

@ -0,0 +1,21 @@
#pragma once
#include <stdint.h>
#define IA32_EFER_MSR 0xC0000080
struct MSR
{
void write(uint64_t value);
uint64_t read();
MSR(uint32_t msr_num);
static void write_to(uint32_t msr_num, uint64_t value);
static uint64_t read_from(uint32_t msr_num);
static void with_value_of(uint32_t msr_num, void (*callback)(uint64_t&));
void with_value(void (*callback)(uint64_t&));
private:
uint32_t m_msr_num;
};

View File

@ -0,0 +1,4 @@
#pragma once
#include "io/PCI.h"
const char* pci_type_name(PCI::DeviceType type);

View File

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

View File

@ -0,0 +1,4 @@
#pragma once
[[noreturn]] void hang();
void halt();

View File

@ -0,0 +1,3 @@
#pragma once
[[noreturn]] void reboot();

View File

@ -0,0 +1,3 @@
#pragma once
[[noreturn]] void shutdown();

View File

@ -0,0 +1,10 @@
#pragma once
#include <stdint.h>
namespace Utilities
{
inline uint64_t get_blocks_from_size(uint64_t blocksize, uint64_t size)
{
return (size + (blocksize - 1)) / blocksize;
}
}

View File

@ -0,0 +1,15 @@
#pragma once
#include "interrupts/Context.h"
#ifdef __cplusplus
extern "C"
{
#endif
[[noreturn]] bool __do_int_panic(Context* context, const char* file, int line, const char* message);
[[noreturn]] bool __do_panic(const char* file, int line, const char* message);
#ifdef __cplusplus
}
#endif
#define panic(message) __do_panic(__FILE__, __LINE__, message)
#define int_panic(context, message) __do_int_panic(context, __FILE__, __LINE__, message)

View File

@ -0,0 +1,7 @@
#pragma once
namespace Mersenne
{
void init();
void reseed();
}

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