Compare commits

..

No commits in common. "e145690db8dbfcf84b948841b4bb244be9eb7468" and "8bf1aac961ad110503be184576b75b05d36381dc" have entirely different histories.

94 changed files with 500 additions and 1520 deletions

View File

@ -1,4 +0,0 @@
file initrd/boot/moon.elf
break _start
target remote :1234
continue

View File

@ -38,8 +38,6 @@ 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.
@ -56,7 +54,7 @@ You can choose between 3 run scripts:
`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)
`tools/debug.sh` will rebuild the kernel with debug symbols and optimizations disabled, install, make an ISO image, and run Luna in QEMU with a port open for GDB to connect to. (run `gdb initrd/boot/moon.elf`, `break _start`, `target remote :1234`, and then `debug.sh` for an optimal debugging experience)
Beware that running without hardware virtualization/with optimizations disabled may cause the kernel to behave differently, which is why I don't use it that often.

View File

@ -1,4 +1,4 @@
APPS := init
APPS := init fib leap art memeater
APPS_DIR := $(LUNA_ROOT)/apps
APPS_SRC := $(APPS_DIR)/src
@ -6,12 +6,11 @@ APPS_BIN := $(APPS_DIR)/bin
REAL_APPS := $(patsubst %, $(APPS_BIN)/%, $(APPS))
CFLAGS := -Wall -Wextra -Werror -Os
CFLAGS := -Wall -Wextra -Werror
$(APPS_BIN)/%: $(APPS_SRC)/%.c
@mkdir -p $(@D)
$(CC) $(CFLAGS) -o $@ $^
$(STRIP) $@
build: $(REAL_APPS)

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

@ -0,0 +1,18 @@
#include <stdio.h>
#include <sys/syscall.h>
#include <unistd.h>
int main()
{
sleep(1);
syscall(SYS_paint, 0, 0, 400, 300, 0x000000FF);
sleep(1);
printf("Hello, colorful world!\n");
sleep(1);
printf("Press any key to restart.");
}

34
apps/src/fib.c Normal file
View File

@ -0,0 +1,34 @@
#include <luna.h>
#include <stdio.h>
#include <unistd.h>
void fib_next(unsigned long int* a, unsigned long int* b)
{
unsigned long int _a = *a;
unsigned long int _b = *b;
*a = *b;
*b = _a + _b;
}
int main()
{
unsigned long int fib_a = 1;
unsigned long int fib_b = 1;
printf("Calculating the 50 first Fibonacci numbers...\n");
sleep(2);
printf("%lu\n", fib_a);
msleep(500);
for (int i = 0; i < 49; i++)
{
printf("%lu\n", fib_b);
fib_next(&fib_a, &fib_b);
msleep(500);
}
printf("\nDone, press any key to restart.\n");
}

View File

@ -1,4 +1,3 @@
#include <errno.h>
#include <luna.h>
#include <stdio.h>
#include <stdlib.h>
@ -6,39 +5,6 @@
#include <sys/syscall.h>
#include <unistd.h>
typedef long ssize_t;
int print_version()
{
char version[4096];
FILE* verfile = fopen("/dev/version", "r");
if (!verfile)
{
perror("fopen");
return 1;
}
size_t nread = fread(version, 4096, 1, verfile);
if (ferror(verfile))
{
perror("fread");
return 1;
}
version[nread] = 0;
if (fclose(verfile) < 0)
{
perror("fclose");
return 1;
}
printf("Your kernel version is %s\n\n", version);
return 0;
}
int main()
{
if (gettid() == 0) // why are we the idle task?
@ -52,37 +18,21 @@ int main()
sleep(1);
if (print_version()) return 1;
char version[40];
syscall(SYS_getversion, version, sizeof(version));
printf("Your kernel version is %s\n\n", version);
sleep(2);
const char* filename = "/sys/config";
printf("Opening %s for reading...\n", filename);
FILE* config = fopen(filename, "r");
if (!config)
{
perror("fopen");
return 1;
char* variable = malloc(200);
*variable = 3;
printf("Allocated variable at address %lx\n", (unsigned long int)variable);
free(variable);
}
char buf[4096];
size_t nread = fread(buf, sizeof(buf), 1, config);
if (ferror(config)) { perror("fread"); }
else
{
buf[nread] = 0;
printf("Read %zd bytes\n\n", nread);
printf("%s", buf);
}
if (fclose(config) < 0) { perror("fclose"); }
printf("\n\nPress any key to restart.\n");
printf("Press any key to restart.\n");
return 0;
}

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

@ -0,0 +1,38 @@
#include <luna.h>
#include <stdio.h>
#include <sys/syscall.h>
#include <unistd.h>
unsigned long random_year() // Return a year from 1000 to 2500.
{
unsigned long result = syscall(SYS_rand);
return (result % 1500) + 1000;
}
int is_leap(unsigned long year)
{
return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
}
int main()
{
printf("Welcome to the Luna Leap Year Program!\n\n");
sleep(1);
printf("Choosing a random year between 1000 and 2500... ");
msleep(500);
unsigned long year = random_year();
printf("%lu!\n\n", year);
sleep(1);
printf("%lu is %s\n", year, is_leap(year) ? "a leap year!" : "not a leap year :(");
msleep(500);
printf("Press any key to restart.\n");
}

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

@ -0,0 +1,17 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define CHUNK 4194304 // 4 MB
int main()
{
printf("Welcome to memeater! This little program is designed to eat up all the memory on your system.\n");
sleep(1);
void* allocated = malloc(CHUNK);
do {
printf("Allocating 4 MB of memory... %lx\n", (unsigned long)allocated);
sleep(1);
} while ((allocated = malloc(CHUNK)));
printf("Out of memory.\n");
}

View File

@ -6,7 +6,7 @@ MOON_BIN := $(MOON_DIR)/bin
CFLAGS := -pedantic -Wall -Wextra -Werror -Wfloat-equal -Wdisabled-optimization -Wformat=2 -Winit-self -Wmissing-include-dirs -Wswitch-default -Wcast-qual -Wundef -Wcast-align -Wwrite-strings -Wlogical-op -Wredundant-decls -Wshadow -Wconversion -Os -ffreestanding -fstack-protector-all -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
LDFLAGS := -T$(MOON_DIR)/moon.ld -nostdlib -lgcc -Wl,--build-id=none -z max-page-size=0x1000
ifneq ($(MOON_BUILD_STABLE), 1)
CFLAGS := ${CFLAGS} -D_MOON_SUFFIX=-$(shell git rev-parse --short HEAD)
@ -54,7 +54,7 @@ $(MOON_OBJ)/%.asm.o: $(MOON_SRC)/%.asm
build: $(OBJS)
@mkdir -p $(@D)
$(CC) $(OBJS) $(LDFLAGS) -o $(MOON_BIN)/moon.elf
$(CC) $(OBJS) $(CFLAGS) $(LDFLAGS) -o $(MOON_BIN)/moon.elf
clean:
rm -rf $(MOON_OBJ)/*
@ -64,7 +64,6 @@ install: $(MOON_BIN)/moon.elf
@mkdir -p $(@D)
cp $^ $(LUNA_ROOT)/initrd/boot/moon.elf
$(LUNA_ROOT)/tools/generate-symbols.sh
$(STRIP) $(LUNA_ROOT)/initrd/boot/moon.elf
.PHONY: build clean install FORCE
FORCE:

View File

@ -1,10 +0,0 @@
#pragma once
#define EPERM 1
#define ENOENT 2
#define EBADF 9
#define ENOMEM 12
#define EISDIR 21
#define EINVAL 22
#define EMFILE 24
#define ENOSYS 38

View File

@ -1,41 +0,0 @@
#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;
}
ssize_t read(size_t size, char* buffer);
ssize_t write(size_t size, const char* buffer);
void open(VFS::Node* node, bool can_read, bool can_write);
Descriptor(const Descriptor& other);
Descriptor();
private:
bool m_is_open;
bool m_can_read;
bool m_can_write;
VFS::Node* m_node;
uint64_t m_offset;
};

View File

@ -1,49 +0,0 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
typedef long ssize_t;
#define VFS_FILE 0x0
#define VFS_DIRECTORY 0x1
#define VFS_MOUNTPOINT 0x1
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*);
struct Node
{
char name[64];
uint64_t inode;
uint64_t length;
int type;
int flags;
node_read read_func;
node_finddir find_func;
node_mkdir mkdir_func;
node_write write_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); // FIXME: Support deducing this via a single path.
void mount_root(Node* root);
Node* resolve_path(const char* filename, Node* root = nullptr);
void mount(Node* mountpoint, Node* mounted);
void mount(const char* pathname, Node* mounted);
void unmount(Node* mountpoint);
Node* root();
}

View File

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

View File

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

View File

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

View File

@ -0,0 +1,34 @@
#pragma once
#include <stdint.h>
namespace Ext2
{
struct Superblock
{
uint32_t fs_inodes; // Total number of inodes in file system
uint32_t fs_blocks; // Total number of blocks in file system
uint32_t su_blocks; // Number of blocks reserved for superuser
uint32_t free_blocks; // Total number of unallocated blocks
uint32_t free_inodes; // Total number of unallocated inodes
uint32_t superblock_number; // Block number of the block containing the superblock
uint32_t block_size; // log2(block size) - 10
uint32_t frag_size; // log2(fragment size) - 10
uint32_t num_blocks; // Number of blocks in each block group
uint32_t num_frag; // Number of fragments in each block group
uint32_t num_inodes; // Number of inodes in each block group
uint32_t mount_time; // Last mount time (in POSIX time)
uint32_t write_time; // Last written time (in POSIX time)
uint16_t fsck_mounts; // Number of times the volume has been mounted since its last consistency check
uint16_t fsck_mounts_allowed; // Number of mounts allowed before a consistency check must be done
uint16_t signature; // Ext2 signature (0xef53)
uint16_t fs_state; // File system state
uint16_t error_action; // What to do when an error is detected
uint16_t version_minor; // Minor portion of version
uint32_t fsck_time; // POSIX time of last consistency check
uint32_t fsck_interval; // Interval (in POSIX time) between forced consistency checks
uint32_t os_id; // Operating system ID from which the filesystem on this volume was created
uint32_t version_major; // Major portion of version
uint16_t su_uid; // User ID that can use reserved blocks (superuser)
uint16_t su_gid; // Group ID that can use reserved blocks
};
}

View File

@ -1,10 +1,6 @@
#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

View File

@ -1,10 +1,6 @@
#pragma once
#include <stdint.h>
#ifndef PAGE_SIZE
#define PAGE_SIZE 4096
#endif
namespace Paging
{
struct PageDirectoryEntry

View File

@ -8,27 +8,23 @@
#define SYS_write 3
#define SYS_paint 4
#define SYS_rand 5
#define SYS_gettid 6
#define SYS_mmap 7
#define SYS_munmap 8
#define SYS_open 9
#define SYS_read 10
#define SYS_close 11
#define SYS_getversion 6
#define SYS_gettid 7
#define SYS_mmap 8
#define SYS_munmap 9
namespace Syscall
{
void entry(Context* context);
}
void sys_exit(Context* context, int status);
void sys_exit(Context* context);
void sys_yield(Context* context);
void sys_sleep(Context* context, uint64_t ms);
void sys_write(Context* context, int fd, size_t size, const char* addr);
void sys_write(Context* context, const char* addr, size_t size);
void sys_paint(Context* context, uint64_t x, uint64_t y, uint64_t w, uint64_t h, uint64_t col);
void sys_rand(Context* context);
void sys_getversion(Context* context, char* buffer, size_t max);
void sys_gettid(Context* context);
void sys_mmap(Context* context, void* address, size_t size, int flags);
void sys_munmap(Context* context, void* address, size_t size);
void sys_open(Context* context, const char* filename, int flags);
void sys_read(Context* context, int fd, size_t size, char* buffer);
void sys_close(Context* context, int fd);
void sys_munmap(Context* context, void* address, size_t size);

View File

@ -5,5 +5,5 @@
namespace ELFLoader
{
ELFImage* load_elf_from_address(uintptr_t addr);
ELFImage* load_elf_from_filesystem(const char* filename);
ELFImage* load_elf_from_initrd(const char* filename);
}

View File

@ -5,15 +5,15 @@ namespace Scheduler
{
void init();
void yield();
void exit(int status);
void exit();
void sleep(unsigned long ms);
void add_kernel_task(void (*task)(void));
void add_user_task(void* task);
void load_user_task(const char* filename);
void task_exit(Context* context, int64_t status);
void task_misbehave(Context* context, int64_t status);
void task_exit(Context* context);
void task_misbehave(Context* context);
Task* current_task();

View File

@ -1,10 +1,7 @@
#pragma once
#include "fs/FileDescriptor.h"
#include "interrupts/Context.h"
#include "sys/elf/Image.h"
#define TASK_MAX_FDS 8
struct Task
{
enum TaskState
@ -19,9 +16,6 @@ struct Task
Context regs;
int64_t task_sleep = 0;
int64_t exit_status;
int64_t task_time = 0;
Task* next_task = nullptr;
@ -39,8 +33,6 @@ struct Task
bool is_user_task();
ELFImage* image = nullptr;
Descriptor files[TASK_MAX_FDS];
};
void set_context_from_task(Task& task, Context* ctx);

View File

@ -4,7 +4,6 @@
#include "bootboot.h"
#include "log/Log.h"
#include "memory/MemoryManager.h"
#include "misc/utils.h"
#include "std/stdio.h"
#include "std/string.h"
@ -12,27 +11,24 @@ extern BOOTBOOT bootboot;
ACPI::SDTHeader* ACPI::get_rsdt_or_xsdt()
{
static SDTHeader* cache = nullptr;
if (cache) return cache;
static void* cache = nullptr;
if (cache) return (SDTHeader*)cache;
kdbgln("First time accessing the RSDT/XSDT, mapping it into memory");
void* physical = (void*)bootboot.arch.x86_64.acpi_ptr;
kdbgln("RSDT/XSDT physical address: %p", physical);
SDTHeader* rsdt = (SDTHeader*)MemoryManager::get_unaligned_mapping(physical);
uint64_t offset = (uint64_t)physical % PAGE_SIZE;
uint64_t rsdt_pages = Utilities::get_blocks_from_size(PAGE_SIZE, (offset + rsdt->Length));
if (rsdt_pages > 1)
uint64_t offset = (uint64_t)physical % 4096;
kdbgln("RSDT/XSDT physical address: %lx", (uint64_t)physical);
cache = MemoryManager::get_unaligned_mapping(physical);
uint64_t numPages = 1;
while ((offset + ((SDTHeader*)cache)->Length) > (numPages * 4096))
{
MemoryManager::release_unaligned_mapping(rsdt);
rsdt = (SDTHeader*)MemoryManager::get_unaligned_mappings(cache, rsdt_pages);
kwarnln("RSDT/XSDT extends beyond the mapped page, mapping one more page");
MemoryManager::release_unaligned_mappings(cache, numPages);
numPages++;
cache = MemoryManager::get_unaligned_mappings(cache, numPages);
}
kdbgln("Mapped RSDT/XSDT to virtual address %p, uses %ld pages", (void*)rsdt, rsdt_pages);
cache = rsdt;
return rsdt;
kdbgln("Mapped RSDT/XSDT to virtual address %lx, uses %ld pages", (uint64_t)cache, numPages);
SDTHeader* result = (SDTHeader*)cache;
return result;
}
bool ACPI::validate_rsdt_or_xsdt(ACPI::SDTHeader* root_sdt)
@ -58,8 +54,8 @@ void* ACPI::find_table(ACPI::SDTHeader* root_sdt, const char* signature)
{
bool isXSDT = is_xsdt();
uint64_t entries = (root_sdt->Length - sizeof(SDTHeader)) / (isXSDT ? 8 : 4);
kdbgln("Searching for table %s in the %s at %p (table contains %ld entries)", signature, isXSDT ? "XSDT" : "RSDT",
(void*)root_sdt, entries);
kdbgln("Searching for table %s in the %s at %lx (table contains %ld entries)", signature, isXSDT ? "XSDT" : "RSDT",
(uint64_t)root_sdt, entries);
for (uint64_t i = 0; i < entries; i++)
{
@ -81,9 +77,9 @@ void* ACPI::find_table(ACPI::SDTHeader* root_sdt, const char* signature)
kwarnln("Entry %ld in the %s points to null", i, isXSDT ? "XSDT" : "RSDT");
continue;
}
kdbgln("Physical address of entry: %p", (void*)h);
kdbgln("Physical address of entry: %lx", (uint64_t)h);
SDTHeader* realHeader = (SDTHeader*)MemoryManager::get_unaligned_mapping(h);
kdbgln("Mapped entry to virtual address %p", (void*)realHeader);
kdbgln("Mapped entry to virtual address %lx", (uint64_t)realHeader);
if (!validate_sdt_header(realHeader))
{
kwarnln("Header of entry %ld is not valid, skipping this entry", i);

View File

@ -1,34 +0,0 @@
#include "fs/FileDescriptor.h"
Descriptor::Descriptor() : m_is_open(false)
{
}
Descriptor::Descriptor(const Descriptor& other)
: m_is_open(other.m_is_open), m_can_read(other.m_can_read), m_can_write(other.m_can_write), m_node(other.m_node),
m_offset(other.m_offset)
{
}
void Descriptor::open(VFS::Node* node, bool can_read, bool can_write)
{
m_can_read = can_read;
m_can_write = can_write;
m_node = node;
m_offset = 0;
m_is_open = true;
}
ssize_t Descriptor::read(size_t size, char* buffer)
{
ssize_t result = VFS::read(m_node, m_offset, size, buffer);
m_offset += result;
return result;
}
ssize_t Descriptor::write(size_t size, const char* buffer)
{
ssize_t result = VFS::write(m_node, m_offset, size, buffer);
m_offset += result;
return result;
}

View File

@ -1,162 +0,0 @@
#define MODULE "vfs"
#include "fs/VFS.h"
#include "errno.h"
#include "log/Log.h"
#include "std/stdlib.h"
#include "std/string.h"
static VFS::Node* vfs_root;
ssize_t VFS::read(Node* node, size_t offset, size_t length, char* buffer)
{
if (!node)
{
kwarnln("read() failed: trying to read from nullptr");
return -1;
}
if (node->type == VFS_DIRECTORY)
{
kwarnln("read() failed: is a directory");
return -EISDIR;
}
if (!node->read_func)
{
kwarnln("read() failed: the chosen node doesn't support reading");
return -1;
}
return node->read_func(node, offset, length, buffer);
}
ssize_t VFS::write(Node* node, size_t offset, size_t length, const char* buffer)
{
if (!node)
{
kwarnln("write() failed: trying to write to nullptr");
return -1;
}
if (node->type == VFS_DIRECTORY)
{
kwarnln("write() failed: is a directory");
return -EISDIR;
}
if (!node->write_func)
{
kwarnln("write() failed: the chosen node doesn't support writing");
return -1;
}
return node->write_func(node, offset, length, buffer);
}
void VFS::mount_root(Node* root)
{
if (!root)
{
kwarnln("mount_root() failed: attempted to mount nullptr");
return;
}
if (vfs_root)
{
kwarnln("mount_root() failed: root filesystem already mounted");
return;
}
kinfoln("mounting node '%s' as vfs root", root->name);
vfs_root = root;
}
VFS::Node* VFS::root()
{
return vfs_root;
}
VFS::Node* VFS::resolve_path(const char* filename, Node* root)
{
if (!root) root = vfs_root;
if (strlen(filename) == 0) return 0;
if (*filename == '/') // Absolute path.
{
filename++;
root = vfs_root;
}
Node* current_node = root;
while (true)
{
while (*filename == '/') { filename++; }
if (*filename == 0) { return current_node; }
size_t path_section_size = 0;
while (filename[path_section_size] && filename[path_section_size] != '/') { path_section_size++; }
if (strncmp(filename, ".", path_section_size) != 0) // The current path section is not '.'
{
char* buffer = (char*)kmalloc(path_section_size + 1);
memcpy(buffer, filename, path_section_size);
buffer[path_section_size] = 0;
if (!current_node->find_func)
{
kwarnln("Current node has no way to find child nodes");
return 0;
}
Node* child = current_node->find_func(current_node, buffer);
if (!child)
{
kwarnln("Current node did not find our target node");
return 0;
}
if (child->flags & VFS_MOUNTPOINT)
{
if (!child->link)
{
kwarnln("Current node's link is null");
return 0;
}
child = child->link;
}
current_node = child;
kfree(buffer);
}
filename += path_section_size;
}
}
int VFS::mkdir(const char* path, const char* name)
{
Node* node = resolve_path(path, vfs_root);
if (!node)
{
kwarnln("Attempting to mkdir in %s, which does not exist", path);
return -1;
}
if (!node->mkdir_func)
{
kwarnln("Chosen node does not support mkdir()");
return -1;
}
return node->mkdir_func(node, name);
}
void VFS::mount(Node* mountpoint, Node* mounted)
{
if (!mountpoint || !mounted) return;
if (mountpoint->flags & VFS_MOUNTPOINT || mounted->flags & VFS_MOUNTPOINT) return;
mountpoint->link = mounted;
mountpoint->flags |= VFS_MOUNTPOINT;
}
void VFS::mount(const char* pathname, Node* mounted)
{
return mount(resolve_path(pathname), mounted);
}
void VFS::unmount(Node* mountpoint)
{
if (!mountpoint) return;
if (!(mountpoint->flags & VFS_MOUNTPOINT)) return;
mountpoint->flags &= ~VFS_MOUNTPOINT;
}

View File

@ -1,25 +0,0 @@
#include "fs/devices/Console.h"
#include "config.h"
#include "render/TextRenderer.h"
#include "std/stdio.h"
#include "std/stdlib.h"
#include "std/string.h"
VFS::Node* ConsoleDevice::create_new()
{
VFS::Node* dev = new VFS::Node;
dev->write_func = ConsoleDevice::write;
dev->inode = 0;
dev->length = 0;
dev->type = VFS_FILE;
dev->flags = 0;
strncpy(dev->name, "console", sizeof(dev->name));
return dev;
}
ssize_t ConsoleDevice::write(VFS::Node* node, size_t, size_t size, const char* buffer)
{
if (!node) return -1;
TextRenderer::write(buffer, size);
return (ssize_t)size;
}

View File

@ -1,37 +0,0 @@
#include "fs/devices/DeviceFS.h"
#include "fs/devices/Console.h"
#include "fs/devices/Version.h"
#include "std/stdlib.h"
#include "std/string.h"
#define DEVFS_MAX_FILES 32
VFS::Node* devfs_root = nullptr;
VFS::Node* devfs_files[DEVFS_MAX_FILES];
int devfs_file_count = 0;
VFS::Node* DeviceFS::get()
{
if (devfs_root) return devfs_root;
devfs_root = new VFS::Node;
devfs_root->length = 0;
devfs_root->inode = 0;
devfs_root->type = VFS_DIRECTORY;
devfs_root->find_func = DeviceFS::finddir;
strncpy(devfs_root->name, "dev", sizeof(devfs_root->name));
devfs_files[devfs_file_count++] = VersionDevice::create_new();
devfs_files[devfs_file_count++] = ConsoleDevice::create_new();
return devfs_root;
}
VFS::Node* DeviceFS::finddir(VFS::Node* node, const char* filename)
{
if (!node) return 0;
for (int i = 0; i < devfs_file_count; i++)
{
if (strncmp(devfs_files[i]->name, filename, sizeof(VFS::Node::name)) == 0) { return devfs_files[i]; }
}
return 0;
}

View File

@ -1,26 +0,0 @@
#include "fs/devices/Version.h"
#include "config.h"
#include "std/stdio.h"
#include "std/stdlib.h"
#include "std/string.h"
VFS::Node* VersionDevice::create_new()
{
VFS::Node* dev = new VFS::Node;
dev->read_func = VersionDevice::read;
dev->inode = 0;
dev->length = strlen(moon_version()) + 5;
dev->type = VFS_FILE;
dev->flags = 0;
strncpy(dev->name, "version", sizeof(dev->name));
return dev;
}
ssize_t VersionDevice::read(VFS::Node* node, size_t offset, size_t size, char* buffer)
{
if (!node) return -1;
if (offset > node->length) return -1;
if (offset + size > node->length) { size = node->length - offset; }
snprintf(buffer, size + 1, "moon %s", moon_version()); // FIXME: Support offseting this read
return (ssize_t)size;
}

View File

@ -84,8 +84,7 @@ void GDT::load()
gdtr.offset = (uint64_t)&internal_gdt;
gdtr.size = sizeof(InternalGDT);
memset(&main_tss, 0, sizeof(TSS));
main_tss.rsp[0] =
(uint64_t)MemoryManager::get_pages(4) + (PAGE_SIZE * 4) - 8; // allocate 16KB for the syscall stack
main_tss.rsp[0] = (uint64_t)MemoryManager::get_pages(4) + (4096 * 4) - 8; // allocate 16KB for the syscall stack
main_tss.iomap_base = sizeof(TSS);
set_base(&internal_gdt.tss, (uint64_t)&main_tss & 0xffffffff);
internal_gdt.tss2.base_high = (uint32_t)(((uint64_t)&main_tss >> 32) & 0xffffffff);

View File

@ -2,21 +2,18 @@
#include "init/InitRD.h"
#include "bootboot.h"
#include "fs/VFS.h"
#include "io/Serial.h"
#include "log/Log.h"
#include "memory/MemoryManager.h"
#include "misc/utils.h"
#include "std/stdlib.h"
#include "std/string.h"
#include <string.h>
extern BOOTBOOT bootboot;
static void* initrd_base;
static bool initrd_initialized = false;
static VFS::Node initrd_root;
bool InitRD::is_initialized()
{
return initrd_initialized;
@ -115,267 +112,10 @@ void InitRD::for_each(void (*callback)(File& f))
}
}
#define INITRD_MAX_FILES_IN_DIR 8
#define INITRD_MAX_FILES 32
namespace InitRD
{
struct Directory
{
char name[64];
int entries = 0;
VFS::Node* files[INITRD_MAX_FILES_IN_DIR];
};
}
void initrd_for_each_dir(void (*callback)(InitRD::Directory& f))
{
uint64_t block = 0;
uint64_t total_blocks = InitRD::get_total_blocks();
while (block < total_blocks)
{
InitRD::TarHeader* hdr = (InitRD::TarHeader*)InitRD::get_block(block);
if (!InitRD::is_valid_header(hdr))
{
block++;
continue;
}
if (hdr->typeflag == 53)
{
InitRD::Directory dir;
strncpy(dir.name, hdr->name, sizeof(dir.name));
callback(dir);
block++;
continue;
}
auto f = get_file(hdr);
block += get_file_size_in_blocks(f) + 1;
}
}
static InitRD::File files[32];
static uint32_t total_files = 0;
static InitRD::Directory dirs[32];
static uint32_t total_dirs = 0;
static VFS::Node nodes[63]; // One of the dirs is the initrd_root
static uint32_t total_nodes = 0;
ssize_t initrd_read(VFS::Node* node, size_t offset, size_t length, char* buffer)
{
if (!node) return -1;
if (node->inode >= total_files) return -1;
InitRD::File& file = files[node->inode];
if (offset > file.size) return -1;
if (offset + length > file.size) { length = file.size - offset; }
memcpy(buffer, (void*)((uintptr_t)file.addr + offset), length);
return length;
}
VFS::Node* initrd_scan_dir(VFS::Node* node, const char* filename)
{
if (!node) return 0;
if (node->inode >= total_dirs) return 0;
InitRD::Directory dir = dirs[node->inode];
for (int i = 0; i < dir.entries; i++)
{
if (strncmp(dir.files[i]->name, filename, sizeof(VFS::Node::name)) == 0) { return dir.files[i]; }
}
return 0;
}
int initrd_mkdir(VFS::Node* node, const char* name) // FIXME: Return proper error numbers.
{
if (total_dirs >= 32)
{
kwarnln("mkdir() failed: too many directories");
return -1;
}
if (node->inode > total_dirs)
{
kwarnln("mkdir() failed: invalid node");
return -1;
}
if (!(node->type & VFS_DIRECTORY))
{
kwarnln("mkdir() failed: not a directory");
return -1;
}
InitRD::Directory& parent = dirs[node->inode];
if (parent.entries == INITRD_MAX_FILES_IN_DIR)
{
kwarnln("mkdir() failed: parent is null");
return -1;
}
uint64_t inode = total_dirs;
VFS::Node& new_node = nodes[total_nodes++];
new_node.inode = inode;
new_node.find_func = initrd_scan_dir;
new_node.mkdir_func = initrd_mkdir;
new_node.length = 0;
new_node.type = VFS_DIRECTORY;
strncpy(new_node.name, name, sizeof(new_node.name));
InitRD::Directory dir;
strncpy(dir.name, name, sizeof(dir.name));
dir.entries = 0;
dirs[total_dirs++] = dir; // FIXME: Right now this isn't of worry, but there is a possibility for a TOCTOU bug here.
// Should use a spinlock or something.
parent.files[parent.entries++] = &new_node;
return 0;
}
static bool initrd_register_dir(InitRD::Directory& dir, uint64_t inode)
{
const char* filename = dir.name;
VFS::Node* current_node = &initrd_root;
while (true)
{
while (*filename == '/') { filename++; }
if (*filename == 0) { return false; }
size_t path_section_size = 0;
while (filename[path_section_size] && filename[path_section_size] != '/') { path_section_size++; }
if (filename[path_section_size]) // We are in a '/'
{
char* buffer = (char*)kmalloc(path_section_size + 1);
memcpy(buffer, filename, path_section_size);
buffer[path_section_size] = 0;
if (!current_node->find_func) { return false; }
VFS::Node* child = current_node->find_func(current_node, buffer);
if (!child) { return false; }
current_node = child;
kfree(buffer);
}
else
{
if (strncmp(filename, ".", path_section_size) != 0) // The current path section is not '.'
{
if (strncmp(filename, "..", path_section_size) == 0) { return false; }
if (!current_node->find_func) { return false; }
InitRD::Directory& parent = dirs[current_node->inode];
if (parent.entries == INITRD_MAX_FILES_IN_DIR) { return false; }
char* buffer = (char*)kmalloc(path_section_size + 1);
memcpy(buffer, filename, path_section_size);
buffer[path_section_size] = 0;
VFS::Node& node = nodes[total_nodes++];
node.inode = inode;
node.find_func = initrd_scan_dir;
node.length = 0;
node.type = VFS_DIRECTORY;
node.mkdir_func = initrd_mkdir;
strncpy(node.name, buffer, sizeof(node.name));
strncpy(dir.name, buffer, sizeof(dir.name));
parent.files[parent.entries++] = &node;
kfree(buffer);
return true;
}
else { return false; }
}
filename += path_section_size;
}
}
static bool initrd_register_file(InitRD::File& f, uint64_t inode)
{
const char* filename = f.name;
VFS::Node* current_node = &initrd_root;
while (true)
{
while (*filename == '/') { filename++; }
if (*filename == 0) { return false; }
size_t path_section_size = 0;
while (filename[path_section_size] && filename[path_section_size] != '/') { path_section_size++; }
if (filename[path_section_size]) // We are in a '/'
{
char* buffer = (char*)kmalloc(path_section_size + 1);
memcpy(buffer, filename, path_section_size);
buffer[path_section_size] = 0;
if (!current_node->find_func) { return false; }
VFS::Node* child = current_node->find_func(current_node, buffer);
if (!child) { return false; }
current_node = child;
kfree(buffer);
}
else
{
if (strncmp(filename, ".", path_section_size) != 0) // The current path section is not '.'
{
if (strncmp(filename, "..", path_section_size) == 0) { return false; }
if (!current_node->find_func) { return false; }
InitRD::Directory& parent = dirs[current_node->inode];
if (parent.entries == INITRD_MAX_FILES_IN_DIR) { return false; }
char* buffer = (char*)kmalloc(path_section_size + 1);
memcpy(buffer, filename, path_section_size);
buffer[path_section_size] = 0;
VFS::Node& node = nodes[total_nodes++];
node.inode = inode;
node.read_func = initrd_read;
node.length = f.size;
node.type = VFS_FILE;
strncpy(node.name, buffer, sizeof(node.name));
strncpy(f.name, buffer, sizeof(f.name));
parent.files[parent.entries++] = &node;
kfree(buffer);
return true;
}
else { return false; }
}
filename += path_section_size;
}
}
static void initrd_scan()
{
initrd_for_each_dir([](InitRD::Directory& dir) {
if (total_dirs >= 32) return;
uint64_t inode = total_dirs;
if (initrd_register_dir(dir, inode)) dirs[total_dirs++] = dir;
});
InitRD::for_each([](InitRD::File& f) {
if (total_files >= 32) return;
uint64_t inode = total_files;
if (initrd_register_file(f, inode)) files[total_files++] = f;
});
}
static void initrd_initialize_root()
{
initrd_root.length = 0;
initrd_root.inode = 0;
initrd_root.type |= VFS_DIRECTORY;
InitRD::Directory& root = dirs[0];
total_dirs++;
strncpy(initrd_root.name, "initrd", sizeof(initrd_root.name));
strncpy(root.name, "initrd", sizeof(root.name));
initrd_root.find_func = initrd_scan_dir;
initrd_root.mkdir_func = initrd_mkdir;
}
void InitRD::init()
{
initrd_base = MemoryManager::get_unaligned_mappings(
(void*)bootboot.initrd_ptr, Utilities::get_blocks_from_size(PAGE_SIZE, bootboot.initrd_size));
kdbgln("physical base at %lx, size %lx, mapped to %p", bootboot.initrd_ptr, bootboot.initrd_size, initrd_base);
kdbgln("total blocks: %ld", get_total_blocks());
initrd_initialize_root();
initrd_scan();
VFS::mount_root(&initrd_root);
initrd_base = MemoryManager::get_unaligned_mappings((void*)bootboot.initrd_ptr, bootboot.initrd_size / 4096 + 1);
kdbgln("physical base at %lx, size %lx, mapped to %lx", bootboot.initrd_ptr, bootboot.initrd_size,
(uint64_t)initrd_base);
initrd_initialized = true;
}

View File

@ -34,7 +34,7 @@ extern "C" void common_handler(Context* context)
StackTracer tracer(context->rbp);
tracer.trace_with_ip(context->rip);
Scheduler::task_misbehave(context, -2);
Scheduler::task_misbehave(context);
}
}
if (context->number == 14)
@ -51,7 +51,7 @@ extern "C" void common_handler(Context* context)
StackTracer tracer(context->rbp);
tracer.trace_with_ip(context->rip);
Scheduler::task_misbehave(context, -3);
Scheduler::task_misbehave(context);
}
}
if (context->number == 8) { int_panic(context, "Double fault, halting"); }

View File

@ -4,8 +4,6 @@
#include "assert.h"
#include "config.h"
#include "cpu/CPU.h"
#include "fs/VFS.h"
#include "fs/devices/DeviceFS.h"
#include "gdt/GDT.h"
#include "init/Init.h"
#include "init/InitRD.h"
@ -34,6 +32,8 @@
#include "thread/PIT.h"
#include "thread/Scheduler.h"
extern "C" void _userspace();
extern "C" void _start()
{
Init::check_magic();
@ -70,6 +70,52 @@ extern "C" void _start()
kinfoln("Prepared scheduler");
/*Scheduler::add_kernel_task([]() {
int64_t x = 0;
int64_t y = 0;
int64_t xvel = 10;
int64_t yvel = 10;
while (1)
{
sleep(2);
uint32_t color = (uint32_t)Mersenne::get();
x += xvel;
y += yvel;
if ((x + 10) >= framebuffer0.width())
{
xvel = -xvel;
x = (framebuffer0.width() - 10);
}
if ((y + 10) >= framebuffer0.height())
{
yvel = -yvel;
y = (framebuffer0.height() - 10);
}
if (xvel < 0 && (x - 10) < 0)
{
xvel = -xvel;
x = 0;
}
if (yvel < 0 && (y - 10) < 0)
{
yvel = -yvel;
y = 0;
}
framebuffer0.paint_rect(x, y, 10, 10, Color::from_integer(color));
}
});*/
/*Scheduler::add_kernel_task([]() {
while (1)
{
sleep(100);
uint32_t color = (uint32_t)Mersenne::get();
framebuffer0.paint_rect(Mersenne::get() % (framebuffer0.width() - 256),
Mersenne::get() % (framebuffer0.height() - 256), Mersenne::get() % 255,
Mersenne::get() % 255, Color::from_integer(color));
}
});*/
Scheduler::add_kernel_task([]() {
while (1)
{
@ -78,16 +124,38 @@ extern "C" void _start()
}
});
Scheduler::load_user_task("/bin/init");
uint64_t demo = Mersenne::get() % 5;
switch (demo)
{
case 0:
kinfoln("Loading demo: example init program");
Scheduler::load_user_task("bin/init");
break;
case 1:
kinfoln("Loading demo: first 50 fibonacci numbers");
Scheduler::load_user_task("bin/fib");
break;
case 2:
kinfoln("Loading demo: leap year calculator");
Scheduler::load_user_task("bin/leap");
break;
case 3:
kinfoln("Loading demo: painting program");
Scheduler::load_user_task("bin/art");
break;
case 4:
kinfoln("Loading demo: memory eating program");
Scheduler::load_user_task("bin/memeater");
break;
default: break;
}
kinfoln("Prepared scheduler tasks");
ASSERT(VFS::mkdir("/", "dev") == 0);
VFS::mount("/dev", DeviceFS::get());
Init::finish_kernel_boot();
Interrupts::enable(); // Task switching commences here
Interrupts::enable();
kinfoln("Interrupts enabled");
@ -95,5 +163,5 @@ extern "C" void _start()
kinfoln("Found PCI device %x:%x, %s", dev.id().vendor, dev.id().device, pci_type_name(dev.type()));
});
Scheduler::exit(0);
Scheduler::exit();
}

View File

@ -1,10 +1,6 @@
#include "memory/KernelHeap.h"
#include "assert.h"
#ifndef PAGE_SIZE
#define PAGE_SIZE 4096
#endif
static uint8_t page_bitmap[2048];
#define ALLOC_BASE 0xfffffffff8000000
@ -32,7 +28,7 @@ uint64_t KernelHeap::request_virtual_page()
if (bitmap_read(index)) continue;
bitmap_set(index, true);
start_index = index + 1;
return ALLOC_BASE + (index * PAGE_SIZE);
return ALLOC_BASE + (index * 4096);
}
return 0;
@ -59,7 +55,7 @@ uint64_t KernelHeap::request_virtual_pages(uint64_t count)
if (contiguous == count)
{
for (uint64_t i = 0; i < count; i++) bitmap_set(contiguous_start + i, true);
return ALLOC_BASE + (contiguous_start * PAGE_SIZE);
return ALLOC_BASE + (contiguous_start * 4096);
}
}
@ -69,7 +65,7 @@ uint64_t KernelHeap::request_virtual_pages(uint64_t count)
void KernelHeap::free_virtual_page(uint64_t address)
{
ASSERT(address >= ALLOC_BASE && address < ALLOC_END);
uint64_t index = (address - ALLOC_BASE) / PAGE_SIZE;
uint64_t index = (address - ALLOC_BASE) / 4096;
bitmap_set(index, false);
if (start_index > index) start_index = index;
}
@ -77,7 +73,7 @@ void KernelHeap::free_virtual_page(uint64_t address)
void KernelHeap::free_virtual_pages(uint64_t address, uint64_t count)
{
ASSERT(address >= ALLOC_BASE && address < ALLOC_END);
uint64_t index = (address - ALLOC_BASE) / PAGE_SIZE;
uint64_t index = (address - ALLOC_BASE) / 4096;
for (uint64_t i = 0; i < count; i++) { bitmap_set(index + i, false); }
if (start_index > index) start_index = index;
}

View File

@ -32,7 +32,7 @@ void* MemoryManager::get_mapping(void* physicalAddress, int flags)
void* MemoryManager::get_unaligned_mapping(void* physicalAddress, int flags)
{
uint64_t offset = (uint64_t)physicalAddress % PAGE_SIZE;
uint64_t offset = (uint64_t)physicalAddress % 4096;
uint64_t virtualAddress = KernelHeap::request_virtual_page();
if (!virtualAddress)
{
@ -49,7 +49,7 @@ void* MemoryManager::get_unaligned_mappings(void* physicalAddress, uint64_t coun
{
if (!count) return 0;
if (count == 1) return get_unaligned_mapping(physicalAddress, flags);
uint64_t offset = (uint64_t)physicalAddress % PAGE_SIZE;
uint64_t offset = (uint64_t)physicalAddress % 4096;
uint64_t virtualAddress = KernelHeap::request_virtual_pages(count);
if (!virtualAddress)
{
@ -62,14 +62,14 @@ void* MemoryManager::get_unaligned_mappings(void* physicalAddress, uint64_t coun
}
for (uint64_t i = 0; i < count; i++)
{
kernelVMM.map(virtualAddress + (i * PAGE_SIZE), ((uint64_t)physicalAddress - offset) + (i * PAGE_SIZE), flags);
kernelVMM.map(virtualAddress + (i * 4096), ((uint64_t)physicalAddress - offset) + (i * 4096), flags);
}
return (void*)(virtualAddress + offset);
}
void MemoryManager::release_unaligned_mapping(void* mapping)
{
uint64_t offset = (uint64_t)mapping % PAGE_SIZE;
uint64_t offset = (uint64_t)mapping % 4096;
kernelVMM.unmap((uint64_t)mapping - offset);
KernelHeap::free_virtual_page((uint64_t)mapping - offset);
}
@ -78,9 +78,9 @@ void MemoryManager::release_unaligned_mappings(void* mapping, uint64_t count)
{
if (!count) return;
if (count == 1) return release_unaligned_mapping(mapping);
uint64_t offset = (uint64_t)mapping % PAGE_SIZE;
uint64_t offset = (uint64_t)mapping % 4096;
KernelHeap::free_virtual_pages((uint64_t)mapping - offset, count);
for (uint64_t i = 0; i < count; i++) { kernelVMM.unmap(((uint64_t)mapping - offset) + (i * PAGE_SIZE)); }
for (uint64_t i = 0; i < count; i++) { kernelVMM.unmap(((uint64_t)mapping - offset) + (i * 4096)); }
}
void MemoryManager::release_mapping(void* mapping)
@ -148,7 +148,7 @@ void* MemoryManager::get_pages_at(uint64_t addr, uint64_t count, int flags)
if (!count) return 0;
if (count == 1) return get_page_at(addr, flags);
#ifdef MM_DEBUG
kdbgln("allocating several pages (%ld), at address %lx", count, addr);
kdbgln("allocating several pages (%ld), at address %ld", count, addr);
#endif
for (uint64_t i = 0; i < count; i++)
{
@ -162,9 +162,9 @@ void* MemoryManager::get_pages_at(uint64_t addr, uint64_t count, int flags)
#endif
return 0;
}
kernelVMM.map(addr + (i * PAGE_SIZE), (uint64_t)physicalAddress, flags);
kernelVMM.map(addr + (i * 4096), (uint64_t)physicalAddress, flags);
#ifdef MM_DEBUG
kdbgln("allocating virtual %lx, physical %p", virtualAddress + (i * PAGE_SIZE), physicalAddress);
kdbgln("allocating virtual %lx, physical %lx", virtualAddress + (i * 4096), (uint64_t)physicalAddress);
#endif
}
return (void*)addr;
@ -179,12 +179,12 @@ void MemoryManager::release_pages(void* pages, uint64_t count)
#endif
for (uint64_t i = 0; i < count; i++)
{
void* page = (void*)((uint64_t)pages + (i * PAGE_SIZE));
void* page = (void*)((uint64_t)pages + (i * 4096));
uint64_t physicalAddress = kernelVMM.getPhysical((uint64_t)page);
ASSERT(physicalAddress != UINT64_MAX);
kernelVMM.unmap((uint64_t)page);
#ifdef MM_DEBUG
kdbgln("releasing virtual %p, physical %lx", page, physicalAddress);
kdbgln("releasing virtual %lx, physical %lx", (uint64_t)page, physicalAddress);
#endif
PMM::free_page((void*)physicalAddress);
}

View File

@ -48,25 +48,26 @@ void PMM::init()
}
bitmap_addr = (char*)biggest_chunk;
virtual_bitmap_addr = bitmap_addr;
ASSERT((total_mem / PAGE_SIZE / 8) < biggest_chunk_size);
bitmap_size = total_mem / PAGE_SIZE / 8 + 1;
virtual_bitmap_addr =
bitmap_addr; // FIXME: map this to a virtual address (ideally in the kernel heap between -128M and -64M)
ASSERT((total_mem / 4096 / 8) < biggest_chunk_size);
bitmap_size = total_mem / 4096 / 8 + 1;
memset(bitmap_addr, 0xFF, bitmap_size);
ptr = &bootboot.mmap;
for (uint64_t i = 0; i < mmap_entries; i++)
{
uint64_t index = MMapEnt_Ptr(ptr) / PAGE_SIZE;
uint64_t index = MMapEnt_Ptr(ptr) / 4096;
if (!MMapEnt_IsFree(ptr)) { reserved_mem += MMapEnt_Size(ptr); }
else
{
free_mem += MMapEnt_Size(ptr);
for (uint64_t j = 0; j < (MMapEnt_Size(ptr) / PAGE_SIZE); j++) { bitmap_set(index + j, false); }
for (uint64_t j = 0; j < (MMapEnt_Size(ptr) / 4096); j++) { bitmap_set(index + j, false); }
}
ptr++;
}
lock_pages(bitmap_addr, bitmap_size / PAGE_SIZE + 1);
lock_pages(bitmap_addr, bitmap_size / 4096 + 1);
}
static bool bitmap_read(uint64_t index)
@ -89,9 +90,9 @@ void* PMM::request_page()
if (bitmap_read(index)) continue;
bitmap_set(index, true);
start_index = index + 1;
free_mem -= PAGE_SIZE;
used_mem += PAGE_SIZE;
return (void*)(index * PAGE_SIZE);
free_mem -= 4096;
used_mem += 4096;
return (void*)(index * 4096);
}
return PMM_FAILED;
@ -118,9 +119,9 @@ void* PMM::request_pages(uint64_t count)
if (contiguous == count)
{
for (uint64_t i = 0; i < count; i++) bitmap_set(contiguous_start + i, true);
free_mem -= (count * PAGE_SIZE);
used_mem += (count * PAGE_SIZE);
return (void*)(contiguous_start * PAGE_SIZE);
free_mem -= (count * 4096);
used_mem += (count * 4096);
return (void*)(contiguous_start * 4096);
}
}
@ -129,11 +130,11 @@ void* PMM::request_pages(uint64_t count)
void PMM::free_page(void* address)
{
uint64_t index = (uint64_t)address / PAGE_SIZE;
uint64_t index = (uint64_t)address / 4096;
if (!bitmap_read(index)) return;
bitmap_set(index, false);
used_mem -= PAGE_SIZE;
free_mem += PAGE_SIZE;
used_mem -= 4096;
free_mem += 4096;
if (start_index > index) start_index = index;
}
@ -144,11 +145,11 @@ void PMM::free_pages(void* address, uint64_t count)
void PMM::lock_page(void* address)
{
uint64_t index = ((uint64_t)address) / PAGE_SIZE;
uint64_t index = ((uint64_t)address) / 4096;
if (bitmap_read(index)) return;
bitmap_set(index, true);
used_mem += PAGE_SIZE;
free_mem -= PAGE_SIZE;
used_mem += 4096;
free_mem -= 4096;
}
void PMM::lock_pages(void* address, uint64_t count)
@ -178,6 +179,6 @@ uint64_t PMM::get_bitmap_size()
void PMM::map_bitmap_to_virtual()
{
virtual_bitmap_addr = (char*)MemoryManager::get_unaligned_mappings(
bitmap_addr, Utilities::get_blocks_from_size(PAGE_SIZE, bitmap_size));
virtual_bitmap_addr =
(char*)MemoryManager::get_unaligned_mappings(bitmap_addr, Utilities::get_blocks_from_size(4096, bitmap_size));
}

View File

@ -8,7 +8,7 @@
#endif
#ifndef MOON_MINOR
#define MOON_MINOR 10
#define MOON_MINOR 9
#endif
#ifndef _MOON_SUFFIX

View File

@ -29,9 +29,8 @@ void TextRenderer::reset()
#pragma GCC push_options
#pragma GCC optimize("O0")
static void putchar_at_offset(
char c, [[maybe_unused]] uint32_t cx, [[maybe_unused]] uint32_t cy, [[maybe_unused]] Color& fg,
[[maybe_unused]] Color& bg) // FIXME: Rewrite this function to actually work with foreground and background colors.
static void putchar_at_offset(char c, [[maybe_unused]] uint32_t cx, [[maybe_unused]] uint32_t cy,
[[maybe_unused]] Color& fg, [[maybe_unused]] Color& bg)
{
uint8_t* glyph = &font[c * 16];
for (uint32_t y = 0; y < FONT_HEIGHT; y++)

View File

@ -159,15 +159,6 @@ static int internal_printf(const char* format, PutString put_string_callback, ss
}
break;
}
case 'p': {
char result[25];
ultoa(va_arg(ap, uint64_t), result, 16);
if (buffer_insert_index + strlen(result) > 1024) flush_buffer();
memcpy(buffer + buffer_insert_index, result, strlen(result));
buffer_insert_index += strlen(result);
if (buffer_insert_index == 1024) flush_buffer();
break;
}
case 's': {
const char* str = va_arg(ap, const char*);
while (strlen(str) > 1024)

View File

@ -1,5 +1,4 @@
#include "sys/Syscall.h"
#include "errno.h"
#include "io/Serial.h"
#include "thread/Scheduler.h"
@ -8,18 +7,24 @@ void Syscall::entry(Context* context)
asm volatile("cli");
switch (context->rax)
{
case SYS_exit: sys_exit(context, (int)context->rdi); break;
case SYS_yield: sys_yield(context); break;
case SYS_sleep: sys_sleep(context, context->rdi); break;
case SYS_write: sys_write(context, (int)context->rdi, context->rsi, (const char*)context->rdx); break;
case SYS_exit: // sys_exit
sys_exit(context);
break;
case SYS_yield: // sys_yield
sys_yield(context);
break;
case SYS_sleep: // sys_sleep
sys_sleep(context, context->rdi);
break;
case SYS_write: // sys_write
sys_write(context, (const char*)context->rdi, context->rsi);
break;
case SYS_paint: sys_paint(context, context->rdi, context->rsi, context->rdx, context->r10, context->r8); break;
case SYS_rand: sys_rand(context); break;
case SYS_getversion: sys_getversion(context, (char*)context->rdi, context->rsi); break;
case SYS_gettid: sys_gettid(context); break;
case SYS_mmap: sys_mmap(context, (void*)context->rdi, context->rsi, (int)context->rdx); break;
case SYS_munmap: sys_munmap(context, (void*)context->rdi, context->rsi); break;
case SYS_open: sys_open(context, (const char*)context->rdi, (int)context->rsi); break;
case SYS_read: sys_read(context, (int)context->rdi, context->rsi, (char*)context->rdx); break;
case SYS_close: sys_close(context, (int)context->rdi); break;
default: context->rax = -ENOSYS; break;
default: context->rax = -1; break;
}
}

View File

@ -1,7 +1,6 @@
#define MODULE "elf"
#include "sys/elf/ELFLoader.h"
#include "fs/VFS.h"
#include "init/InitRD.h"
#include "log/Log.h"
#include "memory/MemoryManager.h"
@ -20,37 +19,16 @@ static const char* format_permissions(uint32_t flags)
return perms;
}
ELFImage* ELFLoader::load_elf_from_filesystem(const char* filename)
ELFImage* ELFLoader::load_elf_from_initrd(const char* filename)
{
VFS::Node* node = VFS::resolve_path(filename);
if (!node)
InitRD::File elf_file = InitRD::open(filename);
if (!elf_file.addr)
{
kwarnln("Failed to open file %s for loading", filename);
return 0;
}
if (node->type == VFS_DIRECTORY)
{
kwarnln("Failed to load %s: is a directory", filename);
return 0;
}
void* file = kmalloc(node->length);
if (VFS::read(node, 0, node->length, (char*)file) < 0)
{
kwarnln("Failed to read ELF image from file");
kfree(file);
return 0;
}
ELFImage* result =
load_elf_from_address((uintptr_t)file); // FIXME: Read headers and sections as we go along the file, to avoid
// loading the entire file at once into memory.
kfree(file);
return result;
return load_elf_from_address((uintptr_t)elf_file.addr);
}
ELFImage* ELFLoader::load_elf_from_address(uintptr_t addr)

View File

@ -1,89 +1,80 @@
#define MODULE "mem"
#include "errno.h"
#include "interrupts/Context.h"
#include "log/Log.h"
#include "memory/MemoryManager.h"
#include "memory/VMM.h"
#include <stddef.h>
#define MAP_FAIL(errno) 0xffffffffffffff00 | (unsigned char)(errno)
void sys_mmap(Context* context, void* address, size_t size, int flags)
{
if (size < PAGE_SIZE)
if (size < 4096)
{
kdbgln("sys_mmap: size too small");
context->rax = MAP_FAIL(EINVAL);
context->rax = 0;
return;
}
int real_flags = MAP_USER;
if (flags & MAP_READ_WRITE) real_flags |= MAP_READ_WRITE;
if (address)
{
kdbgln("sys_mmap: %ld pages at address %p, %s", size / PAGE_SIZE, address,
kdbgln("sys_mmap: %ld pages at address %lx, %s", size / 4096, (uint64_t)address,
real_flags & MAP_READ_WRITE ? "rw" : "ro");
if (kernelVMM.getPhysical((uint64_t)address) != (uint64_t)-1) // Address is already used.
{
kdbgln("attempt to mmap an already mapped address");
context->rax = MAP_FAIL(ENOMEM);
context->rax = 0;
return;
}
uint64_t offset = (uint64_t)address % PAGE_SIZE;
void* result = MemoryManager::get_pages_at((uint64_t)address - offset, size / PAGE_SIZE, real_flags);
uint64_t offset = (uint64_t)address % 4096;
void* result = MemoryManager::get_pages_at((uint64_t)address - offset, size / 4096, real_flags);
if (result)
{
kdbgln("mmap succeeded: %p", result);
kdbgln("mmap succeeded: %lx", (uint64_t)result);
context->rax = (uint64_t)result;
return;
}
else
{
kdbgln("mmap failed");
context->rax = MAP_FAIL(ENOMEM);
context->rax = 0;
return;
}
}
kdbgln("sys_mmap: %ld pages at any address, %s", size / PAGE_SIZE, real_flags & MAP_READ_WRITE ? "rw" : "ro");
void* result = MemoryManager::get_pages(size / PAGE_SIZE, real_flags);
kdbgln("sys_mmap: %ld pages at any address, %s", size / 4096, real_flags & MAP_READ_WRITE ? "rw" : "ro");
void* result = MemoryManager::get_pages(size / 4096, real_flags);
if (result)
{
kdbgln("mmap succeeded: %p", result);
kdbgln("mmap succeeded: %lx", (uint64_t)result);
context->rax = (uint64_t)result;
return;
}
else
{
kdbgln("mmap failed");
context->rax = MAP_FAIL(ENOMEM);
context->rax = 0;
return;
}
}
void sys_munmap(Context* context, void* address, size_t size)
{
kdbgln("sys_munmap: attempting to unmap %p", address);
if (size < PAGE_SIZE)
{
kdbgln("munmap failed: size is too small");
context->rax = -EINVAL;
return;
}
kdbgln("sys_munmap: attempting to unmap %lx", (uint64_t)address);
if (!address)
{
kdbgln("munmap failed: attempted to unmap page 0");
context->rax = -EINVAL;
context->rax = -1;
return;
}
uint64_t flags = kernelVMM.getFlags((uint64_t)address);
if (!(flags & MAP_USER))
{
kdbgln("munmap failed: attempted to unmap a kernel page");
context->rax = -EINVAL;
context->rax = -1;
return;
}
uint64_t offset = (uint64_t)address % PAGE_SIZE;
MemoryManager::release_pages((void*)((uint64_t)address - offset), size / PAGE_SIZE);
uint64_t offset = (uint64_t)address % 4096;
MemoryManager::release_pages((void*)((uint64_t)address - offset), size / 4096);
kdbgln("munmap succeeded");
context->rax = 0;
return;

View File

@ -1,5 +1,4 @@
#include "bootboot.h"
#include "errno.h"
#include "interrupts/Context.h"
#include "render/Framebuffer.h"
#include <stdint.h>
@ -10,12 +9,12 @@ void sys_paint(Context* context, uint64_t x, uint64_t y, uint64_t w, uint64_t h,
{
if ((x + w) > bootboot.fb_width)
{
context->rax = -EINVAL;
context->rax = -1;
return;
}
if ((y + h) > bootboot.fb_height)
{
context->rax = -EINVAL;
context->rax = -1;
return;
}

View File

@ -1,8 +1,8 @@
#include "thread/Scheduler.h"
void sys_exit(Context* context, int status)
void sys_exit(Context* context)
{
Scheduler::task_exit(context, status);
Scheduler::task_exit(context);
}
void sys_yield(Context* context)

View File

@ -1,140 +1,9 @@
#define MODULE "stdio"
#include "errno.h"
#include "interrupts/Context.h"
#include "io/Serial.h"
#include "log/Log.h"
#include "render/TextRenderer.h"
#include "thread/Scheduler.h"
#include "thread/Task.h"
#define OPEN_READ 1
#define OPEN_WRITE 2
#define STDIO_FAIL(function, error) kwarnln("%s failed with %s", #function, #error)
void sys_write(Context* context, int fd, size_t size, const char* addr)
void sys_write(Context* context, const char* addr, size_t size)
{
if (!addr)
{
STDIO_FAIL(write, EINVAL);
context->rax = -EINVAL; // FIXME: This should probably return EFAULT.
return;
}
if (fd >= TASK_MAX_FDS || fd < 0)
{
kwarnln("file descriptor %d is outside the valid range", fd);
STDIO_FAIL(write, EBADF);
context->rax = -EBADF;
return;
}
Task* current_task = Scheduler::current_task();
if (!current_task->files[fd].is_open())
{
kwarnln("file descriptor %d is not open", fd);
STDIO_FAIL(write, EBADF);
context->rax = -EBADF;
return;
}
if (!current_task->files[fd].can_write())
{
kwarnln("file descriptor %d is not open for writing", fd);
STDIO_FAIL(write, EBADF);
context->rax = -EBADF;
return;
}
ssize_t result = current_task->files[fd].write(size, addr);
context->rax = (size_t)result;
return;
}
void sys_open(Context* context, const char* filename, int flags)
{
Task* current_task = Scheduler::current_task();
int fd;
for (fd = 0; fd < TASK_MAX_FDS; fd++)
{
if (!current_task->files[fd].is_open()) break;
}
if (fd == TASK_MAX_FDS)
{
STDIO_FAIL(open, EMFILE);
context->rax = -EMFILE;
return;
}
VFS::Node* node = VFS::resolve_path(filename);
if (!node)
{
STDIO_FAIL(open, ENOENT);
context->rax = -ENOENT;
return;
}
bool can_read = (flags & OPEN_READ) > 0;
bool can_write = (flags & OPEN_WRITE) > 0;
if (!can_read && !can_write)
{
STDIO_FAIL(open, EINVAL);
context->rax = -EINVAL;
return;
}
kdbgln("open(): opening %s %s, allocated file descriptor %d", filename,
(can_read && can_write) ? "rw"
: can_read ? "r-"
: "-w",
fd);
current_task->files[fd].open(node, can_read, can_write);
context->rax = fd;
return;
}
void sys_read(Context* context, int fd, size_t size, char* buffer)
{
if (!buffer)
{
STDIO_FAIL(read, EINVAL);
context->rax = -EINVAL; // FIXME: This should probably return EFAULT.
return;
}
if (fd >= TASK_MAX_FDS || fd < 0)
{
STDIO_FAIL(read, EBADF);
context->rax = -EBADF;
return;
}
Task* current_task = Scheduler::current_task();
if (!current_task->files[fd].is_open() || !current_task->files[fd].can_read())
{
STDIO_FAIL(read, EBADF);
context->rax = -EBADF;
return;
}
ssize_t result = current_task->files[fd].read(size, buffer);
context->rax = (size_t)result;
return;
}
void sys_close(Context* context, int fd)
{
if (fd >= TASK_MAX_FDS || fd < 0)
{
STDIO_FAIL(close, EBADF);
context->rax = -EBADF;
return;
}
Task* current_task = Scheduler::current_task();
if (!current_task->files[fd].is_open())
{
STDIO_FAIL(close, EBADF);
context->rax = -EBADF;
return;
}
kdbgln("close(): releasing file descriptor %d", fd);
current_task->files[fd].close();
context->rax = 0;
return;
context->rax = size;
TextRenderer::write(addr, size);
}

View File

@ -0,0 +1,8 @@
#include "config.h"
#include "interrupts/Context.h"
#include "std/stdio.h"
void sys_getversion(Context* context, char* buffer, size_t max)
{
context->rax = snprintf(buffer, max, "moon %s", moon_version());
}

View File

@ -64,7 +64,7 @@ void Scheduler::add_kernel_task(void (*task)(void))
new_task->regs.rip = (uint64_t)task;
new_task->allocated_stack =
(uint64_t)MemoryManager::get_pages(TASK_PAGES_IN_STACK); // 16 KB is enough for everyone, right?
new_task->regs.rsp = new_task->allocated_stack + (PAGE_SIZE * TASK_PAGES_IN_STACK) - sizeof(uintptr_t);
new_task->regs.rsp = new_task->allocated_stack + (4096 * TASK_PAGES_IN_STACK) - sizeof(uintptr_t);
new_task->regs.cs = 0x08;
new_task->regs.ss = 0x10;
new_task->regs.ds = 0x10;
@ -92,7 +92,7 @@ void Scheduler::add_user_task(void* task)
new_task->regs.rip = (uint64_t)task;
new_task->allocated_stack = (uint64_t)MemoryManager::get_pages(
TASK_PAGES_IN_STACK, MAP_READ_WRITE | MAP_USER); // 16 KB is enough for everyone, right?
new_task->regs.rsp = new_task->allocated_stack + (PAGE_SIZE * TASK_PAGES_IN_STACK) - sizeof(uintptr_t);
new_task->regs.rsp = new_task->allocated_stack + (4096 * TASK_PAGES_IN_STACK) - sizeof(uintptr_t);
new_task->regs.cs = 0x18 | 0x03;
new_task->regs.ss = 0x20 | 0x03;
new_task->regs.ds = 0x20 | 0x03;
@ -117,18 +117,23 @@ void Scheduler::load_user_task(const char* filename)
Task* new_task = new Task;
ASSERT(new_task);
new_task->id = free_tid++;
ELFImage* image = ELFLoader::load_elf_from_filesystem(filename);
ELFImage* image = ELFLoader::load_elf_from_initrd(filename);
if (!image)
{
kerrorln("Failed to load %s from initrd", filename);
delete new_task;
return;
}
new_task->regs.rip = image->entry;
new_task->image = image;
if (!new_task->regs.rip)
{
kwarnln("Failed to load user task %s", filename);
delete new_task;
return;
}
new_task->allocated_stack = (uint64_t)MemoryManager::get_pages(
TASK_PAGES_IN_STACK, MAP_READ_WRITE | MAP_USER); // 16 KB is enough for everyone, right?
new_task->regs.rsp = new_task->allocated_stack + (PAGE_SIZE * TASK_PAGES_IN_STACK) - sizeof(uintptr_t);
new_task->regs.rsp = new_task->allocated_stack + (4096 * TASK_PAGES_IN_STACK) - sizeof(uintptr_t);
new_task->regs.cs = 0x18 | 0x03;
new_task->regs.ss = 0x20 | 0x03;
new_task->regs.ds = 0x20 | 0x03;
@ -153,7 +158,7 @@ void Scheduler::reap_task(Task* task)
task_num--;
Task* exiting_task = task;
ASSERT(task->id != 0); // WHY IN THE WORLD WOULD WE BE REAPING THE IDLE TASK?
kinfoln("reaping task %ld, exited with code %ld", exiting_task->id, exiting_task->exit_status);
kinfoln("reaping task %ld", exiting_task->id);
if (exiting_task->allocated_stack)
MemoryManager::release_pages((void*)exiting_task->allocated_stack, TASK_PAGES_IN_STACK);
if (exiting_task->image)
@ -168,22 +173,20 @@ void Scheduler::reap_task(Task* task)
delete exiting_task;
}
void Scheduler::task_exit(Context* context, int64_t status)
void Scheduler::task_exit(Context* context)
{
ASSERT(Interrupts::is_in_handler());
kdbgln("exit: task %ld finished running, used %ld ms of cpu time", sched_current_task->id,
sched_current_task->cpu_time);
sched_current_task->state = sched_current_task->Exited;
sched_current_task->exit_status = status;
task_yield(context);
}
void Scheduler::task_misbehave(Context* context, int64_t status)
void Scheduler::task_misbehave(Context* context)
{
ASSERT(Interrupts::is_in_handler());
kdbgln("exit: task %ld misbehaved, used %ld ms of cpu time", sched_current_task->id, sched_current_task->cpu_time);
sched_current_task->state = sched_current_task->Exited;
sched_current_task->exit_status = status;
task_yield(context);
}
@ -313,9 +316,9 @@ void Scheduler::yield()
asm volatile("int $0x42" : : "a"(1));
}
void Scheduler::exit(int status)
void Scheduler::exit()
{
asm volatile("int $0x42" : : "a"(0), "D"(status));
asm volatile("int $0x42" : : "a"(0));
}
void Scheduler::sleep(unsigned long ms)

View File

@ -21,7 +21,7 @@ typedef struct stackframe
void StackTracer::trace()
{
stackframe* frame = (stackframe*)m_base_pointer;
while (frame)
while (Memory::is_kernel_address((uintptr_t)frame))
{
char symbol_name[512];
get_symbol_name(frame->instruction, symbol_name);
@ -32,6 +32,11 @@ void StackTracer::trace()
void StackTracer::trace_with_ip(uintptr_t ip)
{
if (!Memory::is_kernel_address(ip))
{
printf("(user stack)");
return;
}
char symbol_name[512];
get_symbol_name(ip, symbol_name);
printf("%lx: %s\n", ip, symbol_name);

View File

@ -3,7 +3,6 @@ section .text
extern _init
extern main
extern _fini
extern initialize_libc
extern exit
global _start
@ -14,8 +13,6 @@ _start:
push rbp ; rbp=0
mov rbp, rsp
call initialize_libc
call _init
mov rdi, 0 ; argc = 0

View File

@ -1,28 +0,0 @@
#ifndef _BITS_ERROR_H
#define _BITS_ERROR_H
#include <errno.h>
#define _RETURN_WITH_ERRNO(rc, type) \
do { \
if (rc < 0) \
{ \
errno = (int)(-rc); \
return -1; \
} \
errno = 0; \
return (type)rc; \
} while (0)
#define _RETURN_WITH_MEMORY_ERRNO(rc, type) \
do { \
if ((unsigned long int)rc > 0xffffffffffffff00) \
{ \
errno = (int)((rc)&0xff); \
return (type)-1; \
} \
errno = 0; \
return (type)rc; \
} while (0)
#endif

View File

@ -1,5 +1,5 @@
#ifndef _BITS_LIBALLOC_H
#define _BITS_LIBALLOC_H
#ifndef _LIBALLOC_H
#define _LIBALLOC_H
#include <stddef.h>

View File

@ -1,5 +1,5 @@
#ifndef _BITS_MACROS_H
#define _BITS_MACROS_H
#ifndef __MACROS_H
#define __MACROS_H
#define noreturn __attribute__((noreturn))
#define align(n) __attribute__((aligned(n)))

View File

@ -1,15 +0,0 @@
#ifndef _ERRNO_H
#define _ERRNO_H
extern int errno;
#define EPERM 1
#define ENOENT 2
#define EBADF 9
#define ENOMEM 12
#define EISDIR 21
#define EINVAL 22
#define EMFILE 24
#define ENOSYS 38
#endif

View File

@ -1,19 +0,0 @@
#ifndef _FCNTL_H
#define _FCNTL_H
#define O_RDONLY 1
#define O_WRONLY 2
#define O_RDWR 3
#ifdef __cplusplus
extern "C"
{
#endif
int open(const char*, int);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -7,12 +7,10 @@
#define SYS_write 3
#define SYS_paint 4
#define SYS_rand 5
#define SYS_gettid 6
#define SYS_mmap 7
#define SYS_munmap 8
#define SYS_open 9
#define SYS_read 10
#define SYS_close 11
#define SYS_getversion 6
#define SYS_gettid 7
#define SYS_mmap 8
#define SYS_munmap 9
#ifndef __want_syscalls
#ifdef __cplusplus

View File

@ -8,20 +8,16 @@
typedef struct
{
int f_fd;
int f_eof;
int f_err;
int unused;
} FILE;
extern FILE* __stderr;
extern FILE* __stdout;
#define stderr __stderr
#define stdout __stdout
#ifdef __cplusplus
extern "C"
{
#endif
extern FILE* stderr;
#define stderr stderr
int fclose(FILE*);
int fflush(FILE*);
FILE* fopen(const char*, const char*);
@ -30,9 +26,6 @@ extern "C"
int fseek(FILE*, long, int);
long ftell(FILE*);
size_t fwrite(const void*, size_t, size_t, FILE*);
int ferror(FILE*);
int feof(FILE*);
void clearerr(FILE*);
void setbuf(FILE*, char*);
int vfprintf(FILE*, const char*, va_list);
int printf(const char*, ...);
@ -42,7 +35,6 @@ extern "C"
int vsprintf(char*, const char*, va_list);
int vsnprintf(char*, size_t, const char*, va_list);
int puts(const char*);
void perror(const char*);
#ifdef __cplusplus
}

View File

@ -23,8 +23,6 @@ extern "C"
deprecated("strcat is unsafe and should not be used; use strncat instead") char* strcat(char*, const char*);
char* strncat(char*, const char*, size_t);
char* strerror(int);
#ifdef __cplusplus
}
#endif

View File

@ -1,26 +0,0 @@
#ifndef _SYS_MMAN_H
#define _SYS_MMAN_H
#include <stddef.h>
typedef unsigned long off_t;
#define MAP_FAILED (void*)-1
#define PROT_READ_WRITE 1
#define PAGE_SIZE 4096
#ifdef __cplusplus
extern "C"
{
#endif
void* mmap(void*, size_t, int, int, int, off_t);
int munmap(void* addr, size_t len);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,8 +1,4 @@
#ifndef _SYS_TYPES_H
#define _SYS_TYPES_H
typedef long int pid_t;
typedef unsigned long int size_t;
typedef long int ssize_t;
#endif

View File

@ -1,13 +1,10 @@
#ifndef _UNISTD_H
#define _UNISTD_H
#include <sys/types.h>
#ifdef __cplusplus
extern "C"
{
#endif
int execv(const char*, char* const[]);
int execve(const char*, char* const[], char* const[]);
int execvp(const char*, char* const[]);
@ -15,12 +12,7 @@ extern "C"
long syscall(long, ...);
unsigned int sleep(unsigned int);
ssize_t read(int, void*, size_t);
ssize_t write(int, const void*, size_t);
int close(int);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,5 +1,6 @@
#include <stddef.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <unistd.h>
int liballoc_lock()
{
@ -13,12 +14,14 @@ int liballoc_unlock()
void* liballoc_alloc(size_t size)
{
void* result = mmap(NULL, size * PAGE_SIZE, PROT_READ_WRITE, 0, 0, 0);
if (result == MAP_FAILED) return 0;
unsigned long int result = (unsigned long int)syscall(SYS_mmap, NULL, size * 4096, 1);
return (void*)result;
}
int liballoc_free(void* address, size_t size)
{
return munmap(address, size * PAGE_SIZE);
int result = (int)syscall(SYS_munmap, address, size * 4096);
if (result < 0) return 1;
else
return 0;
}

View File

@ -1,3 +0,0 @@
#include <errno.h>
int errno;

View File

@ -1,11 +0,0 @@
#include <fcntl.h>
#include <sys/syscall.h>
#include <unistd.h>
extern "C"
{
int open(const char* pathname, int flags)
{
return (int)syscall(SYS_open, pathname, flags);
}
}

View File

@ -1,96 +0,0 @@
#include <errno.h>
#include <fcntl.h>
#include <luna.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
FILE* __stderr;
FILE* __stdout;
extern "C"
{
int fclose(FILE* stream)
{
int status = close(stream->f_fd);
if (status < 0)
{
int savederr = errno;
free(stream); // We do not want to leak memory. man fclose(3) says that whether fclose() fails or not, any
// further operation on the stream results in undefined behavior. So we are free to free the
// stream.
errno = savederr; // free might reset errno. We don't want that.
}
else { free(stream); }
return status;
}
int fflush(FILE*)
{
return 0; // FIXME: Implement buffered IO.
}
FILE* fopen(const char* pathname, const char*)
{
int fd = open(pathname, O_RDWR); // FIXME: Use the mode string.
if (fd < 0) { return 0; }
FILE* stream = (FILE*)malloc(sizeof(FILE));
stream->f_fd = fd;
clearerr(stream);
return stream;
}
size_t fread(void* buf, size_t size, size_t nmemb, FILE* stream)
{
ssize_t status = read(stream->f_fd, buf, size * nmemb);
if (status < 0)
{
stream->f_err = 1;
return 0;
}
if (status == 0) stream->f_eof = 1;
return (size_t)status;
}
int ferror(FILE* stream)
{
return stream->f_err;
}
int feof(FILE* stream)
{
return stream->f_eof;
}
void clearerr(FILE* stream)
{
stream->f_err = stream->f_eof = 0;
}
int fseek(FILE*, long, int)
{
NOT_IMPLEMENTED("fseek");
}
long ftell(FILE*)
{
NOT_IMPLEMENTED("ftell");
}
size_t fwrite(const void* buf, size_t size, size_t nmemb, FILE* stream)
{
ssize_t status = write(stream->f_fd, buf, size * nmemb);
if (status < 0)
{
stream->f_err = 1;
return 0;
}
if (status == 0) stream->f_eof = 1;
return (size_t)status;
}
void setbuf(FILE*, char*)
{
NOT_IMPLEMENTED("setbuf");
}
}

View File

@ -1,14 +0,0 @@
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
extern "C" void initialize_libc()
{
__stderr = fopen("/dev/console", "rw");
if (!stderr) exit(errno);
__stdout = fopen("/dev/console", "rw");
if (!stdout) exit(errno);
clearerr(__stderr);
clearerr(__stdout);
}

View File

@ -1,6 +1,4 @@
#include <luna.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/syscall.h>
#include <unistd.h>
@ -21,7 +19,8 @@ extern "C"
noreturn void __luna_abort(const char* message)
{
fwrite(message, strlen(message), 1, stdout);
abort();
syscall(SYS_write, message, strlen(message));
syscall(SYS_exit);
__builtin_unreachable();
}
}

View File

@ -1,4 +1,3 @@
#include <errno.h>
#include <luna.h>
#include <stdarg.h>
#include <stddef.h>
@ -243,30 +242,6 @@ static int internal_printf(const char* format, PutString put_string_callback, ss
}
break;
}
case 'p': {
char result[25];
__unsignedtoa<unsigned long>(va_arg(ap, uint64_t), result, 16);
if (buffer_insert_index + strlen(result) > 1024) flush_buffer();
memcpy(buffer + buffer_insert_index, result, strlen(result));
buffer_insert_index += strlen(result);
if (buffer_insert_index == 1024) flush_buffer();
break;
}
case 'm': {
const char* str = strerror(errno);
while (strlen(str) > 1024)
{
flush_buffer();
memcpy(buffer, str, 1024);
str += 1024;
buffer_insert_index = 1024;
}
if (buffer_insert_index + strlen(str) > 1024) flush_buffer();
memcpy(buffer + buffer_insert_index, str, strlen(str));
buffer_insert_index += strlen(str);
if (buffer_insert_index == 1024) flush_buffer();
break;
}
case 's': {
const char* str = va_arg(ap, const char*);
while (strlen(str) > 1024)
@ -306,7 +281,8 @@ extern "C"
{
int vprintf(const char* format, va_list ap)
{
return vfprintf(stdout, format, ap);
return internal_printf(
format, [](const char* s) { syscall(SYS_write, s, strlen(s)); }, -1, ap);
}
int vsprintf(char* str, const char* format, va_list ap)
@ -328,46 +304,4 @@ extern "C"
},
max == 0 ? 0 : max - 1, ap);
}
int snprintf(char* str, size_t max, const char* format, ...)
{
va_list ap;
va_start(ap, format);
int written = vsnprintf(str, max, format, ap);
va_end(ap);
return written;
}
int sprintf(char* str, const char* format, ...)
{
va_list ap;
va_start(ap, format);
int written = vsprintf(str, format, ap);
va_end(ap);
return written;
}
int printf(const char* format, ...)
{
va_list ap;
va_start(ap, format);
int written = vfprintf(stdout, format, ap);
va_end(ap);
return written;
}
int fprintf(FILE* stream, const char* format, ...)
{
va_list ap;
va_start(ap, format);
int written = vfprintf(stream, format, ap);
va_end(ap);
return written;
}
int vfprintf(FILE* stream, const char* format, va_list ap)
{
return internal_printf(
format, [&](const char* s) { fwrite(s, strlen(s), 1, stream); }, -1, ap);
}
}

View File

@ -1,4 +1,3 @@
#include <errno.h>
#include <luna.h>
#include <stdio.h>
#include <stdlib.h>
@ -8,18 +7,74 @@
extern "C"
{
int fclose(FILE*)
{
NOT_IMPLEMENTED("fclose");
}
int fflush(FILE*)
{
NOT_IMPLEMENTED("fflush");
}
FILE* fopen(const char*, const char*)
{
NOT_IMPLEMENTED("fopen");
}
int fprintf(FILE*, const char*, ...)
{
NOT_IMPLEMENTED("fprintf");
}
size_t fread(void*, size_t, size_t, FILE*)
{
NOT_IMPLEMENTED("fread");
}
int fseek(FILE*, long, int)
{
NOT_IMPLEMENTED("fseek");
}
long ftell(FILE*)
{
NOT_IMPLEMENTED("ftell");
}
size_t fwrite(const void*, size_t, size_t, FILE*)
{
NOT_IMPLEMENTED("fwrite");
}
void setbuf(FILE*, char*)
{
NOT_IMPLEMENTED("setbuf");
}
int vfprintf(FILE*, const char*, va_list)
{
NOT_IMPLEMENTED("vfprintf");
}
int puts(const char* s)
{
long nwritten = fwrite(s, strlen(s), 1, stdout);
if (nwritten < 0) return -1;
nwritten += fwrite("\n", 1, 1, stdout);
long nwritten = syscall(SYS_write, s, strlen(s));
nwritten += syscall(SYS_write, "\n", 1);
return (int)nwritten;
}
void perror(const char* s)
int snprintf(char* str, size_t max, const char* format, ...)
{
int savederr =
errno; // This was necessary before, but even more now since we clear errno on successful syscalls now.
if (s && *s) { fprintf(stderr, "%s: ", s); }
fprintf(stderr, "%s\n", strerror(savederr));
va_list ap;
va_start(ap, format);
int written = vsnprintf(str, max, format, ap);
va_end(ap);
return written;
}
int sprintf(char* str, const char* format, ...)
{
va_list ap;
va_start(ap, format);
int written = vsprintf(str, format, ap);
va_end(ap);
return written;
}
int printf(const char* format, ...)
{
va_list ap;
va_start(ap, format);
int written = vprintf(format, ap);
va_end(ap);
return written;
}
}

View File

@ -15,9 +15,9 @@ extern "C"
exit(-1);
}
noreturn void exit(int status)
noreturn void exit(int)
{
syscall(SYS_exit, status);
syscall(SYS_exit);
__builtin_unreachable();
}

View File

@ -1,4 +1,3 @@
#include <errno.h>
#include <luna.h>
#include <string.h>
@ -61,11 +60,9 @@ extern "C"
return dest;
}
char* strchr(const char* str, int chr)
char* strchr(const char*, int)
{
while (*str && *str != (char)chr) str++;
if (*str) return const_cast<char*>(str);
return NULL;
NOT_IMPLEMENTED("strchr");
}
void* memclr(void* start, size_t count)
@ -111,26 +108,4 @@ extern "C"
// we return "m_start" + the amount of bytes that were transfered
return (void*)(((size_t)start) + i);
}
#pragma GCC push_options
#pragma GCC diagnostic ignored "-Wwrite-strings"
char* strerror(int errnum)
{
switch (errnum)
{
case EPERM: return "Operation not permitted";
case EINVAL: return "Invalid argument";
case ENOMEM: return "Out of memory";
case ENOSYS: return "Function not implemented";
case ENOENT: return "No such file or directory";
case EBADF: return "Bad file descriptor";
case EMFILE: return "Too many open files";
case EISDIR: return "Is a directory";
case 0: return "Success";
default: return (char*)(unsigned long int)errnum;
}
}
#pragma GCC pop_options
}

View File

@ -1,17 +0,0 @@
#include <sys/mman.h>
#include <sys/syscall.h>
#include <unistd.h>
extern "C"
{
// FIXME: Implement a POSIX-compliant mmap.
void* mmap(void* addr, size_t len, int prot, int, int, off_t)
{
return (void*)syscall(SYS_mmap, addr, len, prot);
}
int munmap(void* addr, size_t len)
{
return (int)syscall(SYS_munmap, addr, len);
}
}

View File

@ -1,4 +1,3 @@
#include <bits/error.h>
#include <luna.h>
#include <luna/syscall.h>
#include <stdarg.h>
@ -31,21 +30,19 @@ extern "C"
va_start(ap, number);
switch (number)
{
case SYS_exit:
case SYS_yield:
case SYS_gettid:
case SYS_rand: result = __luna_syscall0(number); break;
case SYS_exit:
case SYS_close:
case SYS_sleep: result = __luna_syscall1(number, va_arg(ap, arg)); break;
case SYS_write:
case SYS_munmap:
case SYS_open: {
case SYS_getversion: {
arg arg0 = va_arg(ap, arg);
arg arg1 = va_arg(ap, arg);
result = __luna_syscall2(number, arg0, arg1);
break;
}
case SYS_write:
case SYS_read:
case SYS_mmap: {
arg arg0 = va_arg(ap, arg);
arg arg1 = va_arg(ap, arg);
@ -62,30 +59,14 @@ extern "C"
result = __luna_syscall5(number, arg0, arg1, arg2, arg3, arg4);
break;
}
default: result = -ENOSYS; break;
default: result = -1; break;
}
va_end(ap);
if (number == SYS_mmap) { _RETURN_WITH_MEMORY_ERRNO(result, long int); }
else { _RETURN_WITH_ERRNO(result, long); }
return result;
}
unsigned int sleep(unsigned int seconds)
{
return msleep(seconds * 1000);
}
ssize_t read(int fd, void* buf, size_t count)
{
return syscall(SYS_read, fd, count, buf); // yes, our read() syscall is in the wrong order.
}
ssize_t write(int fd, const void* buf, size_t count)
{
return syscall(SYS_write, fd, count, buf); // yes, our write() syscall is in the wrong order.
}
int close(int fd)
{
return (int)syscall(SYS_close, fd);
}
}

View File

@ -1,6 +0,0 @@
#!/usr/bin/env bash
set -e
source $(dirname $0)/env.sh
MOON_BUILD_DEBUG=1 tools/rebuild-iso.sh

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/sh
set -e
source $(dirname $0)/env.sh

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/sh
set -e
source $(dirname $0)/env.sh

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/sh
set -e
source $(dirname $0)/env.sh

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/sh
set -e
source $(dirname $0)/env.sh

View File

@ -1,6 +1,8 @@
#!/usr/bin/env bash
#!/bin/sh
set -e
source $(dirname $0)/env.sh
qemu-system-x86_64 -cdrom Luna.iso -smp 1 -m 256M -serial stdio -d int,cpu_reset -s $@
MOON_BUILD_DEBUG=1 tools/rebuild-iso.sh
qemu-system-x86_64 -cdrom Luna.iso -smp 1 -m 256M -serial stdio -d int,cpu_reset -s -no-reboot $@

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/sh
export LUNA_ROOT=$(realpath $(dirname $0)/..)
export LUNA_BASE=$LUNA_ROOT/base
export PATH=$LUNA_ROOT/toolchain/x86-64-luna/bin:$LUNA_ROOT/toolchain/dist:$PATH
@ -7,5 +7,4 @@ export CC=x86_64-luna-gcc
export CXX=x86_64-luna-g++
export LD=x86_64-luna-ld
export AR=x86_64-luna-ar
export ASM=nasm
export STRIP=x86_64-luna-strip
export ASM=nasm

View File

@ -1,6 +0,0 @@
#!/usr/bin/env bash
set -e
source $(dirname $0)/env.sh
gdb -x .gdbconf

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/sh
set -e

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/sh
set -e
source $(dirname $0)/env.sh

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/sh
set -e
source $(dirname $0)/env.sh

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/sh
set -e
source $(dirname $0)/env.sh

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/sh
set -e
source $(dirname $0)/env.sh

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/sh
set -e
source $(dirname $0)/env.sh

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/sh
set -e
source $(dirname $0)/env.sh

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/sh
set -e
source $(dirname $0)/setup-env.sh

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/sh
source $(dirname $0)/env.sh
export LUNA_GCC_VERSION_REQUIRED=12.2.0

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/sh
set -e
source $(dirname $0)/setup-env.sh

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/sh
set -e
source $(dirname $0)/env.sh

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/sh
set -e
if ! $(dirname $0)/test-binutils.sh

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/sh
set -e
source $(dirname $0)/env.sh

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/sh
set -e
source $(dirname $0)/setup-env.sh

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/sh
set -e
source $(dirname $0)/setup-env.sh