Compare commits
7 Commits
9f5fb547f7
...
985d45ddfb
Author | SHA1 | Date | |
---|---|---|---|
985d45ddfb | |||
d2856d8812 | |||
29dad5651d | |||
1d51935d43 | |||
fc0779a2f9 | |||
fe47e0d5cb | |||
f8ed74fda5 |
@ -1,4 +1,5 @@
|
||||
#include "Log.h"
|
||||
#include "arch/CPU.h"
|
||||
#include "arch/Serial.h"
|
||||
#include "arch/Timer.h"
|
||||
#include "video/TextConsole.h"
|
||||
@ -112,4 +113,16 @@ bool log_serial_enabled()
|
||||
bool log_text_console_enabled()
|
||||
{
|
||||
return g_text_console_enabled;
|
||||
}
|
||||
|
||||
static bool g_check_already_failed = false;
|
||||
|
||||
_noreturn bool __check_failed(const char* file, const char* line, const char* func, const char* expr)
|
||||
{
|
||||
if (!g_check_already_failed)
|
||||
{ // Avoid endlessly failing when trying to report a failed check.
|
||||
g_check_already_failed = true;
|
||||
kerrorln("ERROR: Check failed at %s:%s, in %s: %s", file, line, func, expr);
|
||||
}
|
||||
CPU::efficient_halt();
|
||||
}
|
@ -34,16 +34,4 @@ namespace Serial
|
||||
va_end(ap);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
static bool g_check_already_failed = false;
|
||||
|
||||
_noreturn bool __check_failed(const char* file, const char* line, const char* func, const char* expr)
|
||||
{
|
||||
if (!g_check_already_failed)
|
||||
{ // Avoid endlessly failing when trying to report a failed check.
|
||||
g_check_already_failed = true;
|
||||
Serial::printf("ERROR: Check failed at %s:%s, in %s: %s\n", file, line, func, expr);
|
||||
}
|
||||
CPU::efficient_halt();
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
#include "arch/Timer.h"
|
||||
#include "Log.h"
|
||||
#include "arch/Serial.h"
|
||||
#include "boot/bootboot.h"
|
||||
#include <Result.h>
|
||||
@ -46,8 +47,7 @@ static u64 bootloader_time_to_unix(u8 boottime[8])
|
||||
int second = bcd_number_to_decimal(boottime[6]);
|
||||
// "The last byte can store 1/100th second precision, but in lack of support on most platforms, it is 0x00".
|
||||
// Therefore, let's not rely on it.
|
||||
Serial::printf("Current time: %.2d/%.2d/%d %.2d:%.2d:%.2d UTC\n", day, month, year, hour, minute, second)
|
||||
.release_value();
|
||||
kinfoln("Current time: %.2d/%.2d/%d %.2d:%.2d:%.2d UTC", day, month, year, hour, minute, second).release_value();
|
||||
return broken_down_to_unix(year - 1900, make_yday(year, month) + (day - 1), hour, minute, second);
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,10 @@
|
||||
#include "arch/x86_64/CPU.h"
|
||||
#include "Log.h"
|
||||
#include "arch/Serial.h"
|
||||
#include "arch/Timer.h"
|
||||
#include "arch/x86_64/IO.h"
|
||||
#include <String.h>
|
||||
#include <SystemError.h>
|
||||
#include <Types.h>
|
||||
#include <cpuid.h>
|
||||
|
||||
@ -274,7 +276,7 @@ static void setup_idt()
|
||||
// Interrupt handling
|
||||
|
||||
#define FIXME_UNHANDLED_INTERRUPT(name) \
|
||||
Serial::println("FIXME(interrupt): " name); \
|
||||
kerrorln("FIXME(interrupt): %s", name); \
|
||||
CPU::efficient_halt();
|
||||
|
||||
extern "C" void handle_x86_exception([[maybe_unused]] Registers* regs)
|
||||
@ -314,20 +316,20 @@ extern "C" void arch_interrupt_entry(Registers* regs)
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial::println("IRQ catched! Halting.");
|
||||
kwarnln("IRQ catched! Halting.");
|
||||
CPU::efficient_halt();
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" [[noreturn]] void arch_double_fault()
|
||||
{
|
||||
Serial::println("ERROR: Catched double fault");
|
||||
kerrorln("ERROR: Catched double fault");
|
||||
CPU::efficient_halt();
|
||||
}
|
||||
|
||||
extern "C" [[noreturn]] void arch_machine_check()
|
||||
{
|
||||
Serial::println("ERROR: Machine check failed");
|
||||
kerrorln("ERROR: Machine check failed");
|
||||
CPU::efficient_halt();
|
||||
}
|
||||
|
||||
@ -347,11 +349,11 @@ namespace CPU
|
||||
static char brand_string[49];
|
||||
|
||||
u32 buf[4];
|
||||
if (!__get_cpuid(0x80000002, &buf[0], &buf[1], &buf[2], &buf[3])) return err;
|
||||
if (!__get_cpuid(0x80000002, &buf[0], &buf[1], &buf[2], &buf[3])) return err(ENOTSUP);
|
||||
memcpy(brand_string, buf, 16);
|
||||
if (!__get_cpuid(0x80000003, &buf[0], &buf[1], &buf[2], &buf[3])) return err;
|
||||
if (!__get_cpuid(0x80000003, &buf[0], &buf[1], &buf[2], &buf[3])) return err(ENOTSUP);
|
||||
memcpy(&brand_string[16], buf, 16);
|
||||
if (!__get_cpuid(0x80000004, &buf[0], &buf[1], &buf[2], &buf[3])) return err;
|
||||
if (!__get_cpuid(0x80000004, &buf[0], &buf[1], &buf[2], &buf[3])) return err(ENOTSUP);
|
||||
memcpy(&brand_string[32], buf, 16);
|
||||
|
||||
brand_string[48] = 0; // null-terminate it :)
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "arch/MMU.h"
|
||||
#include "memory/MemoryManager.h"
|
||||
#include <String.h>
|
||||
#include <SystemError.h>
|
||||
|
||||
#define PAGE_SIZE 4096
|
||||
|
||||
@ -161,12 +162,12 @@ namespace MMU
|
||||
Result<PageTableEntry*> find_entry(u64 virt)
|
||||
{
|
||||
auto& l4 = l4_entry(virt);
|
||||
if (!l4.present) return err;
|
||||
if (!l4.present) return err(EFAULT);
|
||||
auto& l3 = l3_entry(virt);
|
||||
if (!l3.present) return err;
|
||||
if (!l3.present) return err(EFAULT);
|
||||
if (l3.larger_pages) return &l3;
|
||||
auto& l2 = l2_entry(virt);
|
||||
if (!l2.present) return err;
|
||||
if (!l2.present) return err(EFAULT);
|
||||
if (l2.larger_pages) return &l2;
|
||||
return &l1_entry(virt);
|
||||
}
|
||||
@ -174,16 +175,16 @@ namespace MMU
|
||||
Result<PageTableEntry*> apply_cascading_flags(u64 virt, int flags)
|
||||
{
|
||||
auto& l4 = l4_entry(virt);
|
||||
if (!l4.present) return err;
|
||||
if (!l4.present) return err(EFAULT);
|
||||
if (flags & Flags::ReadWrite) l4.read_write = true;
|
||||
if (flags & Flags::User) l4.user = true;
|
||||
auto& l3 = l3_entry(virt);
|
||||
if (!l3.present) return err;
|
||||
if (!l3.present) return err(EFAULT);
|
||||
if (l3.larger_pages) return &l3;
|
||||
if (flags & Flags::ReadWrite) l3.read_write = true;
|
||||
if (flags & Flags::User) l3.user = true;
|
||||
auto& l2 = l2_entry(virt);
|
||||
if (!l2.present) return err;
|
||||
if (!l2.present) return err(EFAULT);
|
||||
if (l2.larger_pages) return &l2;
|
||||
if (flags & Flags::ReadWrite) l2.read_write = true;
|
||||
if (flags & Flags::User) l2.user = true;
|
||||
@ -217,7 +218,7 @@ namespace MMU
|
||||
if (flags & Flags::ReadWrite) l3.read_write = true;
|
||||
if (flags & Flags::User) l3.user = true;
|
||||
|
||||
if (l3.larger_pages) return err; // FIXME: Replacing larger pages is not supported ATM
|
||||
if (l3.larger_pages) return err(EFIXME); // FIXME: Replacing larger pages is not supported ATM
|
||||
|
||||
auto& l2 = l2_entry(virt);
|
||||
if (!l2.present)
|
||||
@ -231,10 +232,10 @@ namespace MMU
|
||||
if (flags & Flags::ReadWrite) l2.read_write = true;
|
||||
if (flags & Flags::User) l2.user = true;
|
||||
|
||||
if (l2.larger_pages) return err; // FIXME: Replacing larger pages is not supported ATM
|
||||
if (l2.larger_pages) return err(EFIXME); // FIXME: Replacing larger pages is not supported ATM
|
||||
|
||||
auto& l1 = l1_entry(virt);
|
||||
if (l1.present) return err; // Please explicitly unmap the page before mapping it again.
|
||||
if (l1.present) return err(EEXIST); // Please explicitly unmap the page before mapping it again.
|
||||
l1.ignore0 = l1.ignore1 = false;
|
||||
l1.present = true;
|
||||
l1.read_write = (flags & Flags::ReadWrite);
|
||||
@ -249,7 +250,7 @@ namespace MMU
|
||||
Result<void> remap(u64 virt, int flags)
|
||||
{
|
||||
auto& l1 = *TRY(apply_cascading_flags(virt, flags));
|
||||
if (!l1.present) return err;
|
||||
if (!l1.present) return err(EFAULT);
|
||||
l1.read_write = (flags & Flags::ReadWrite);
|
||||
l1.user = (flags & Flags::User);
|
||||
l1.write_through = (flags & Flags::WriteThrough);
|
||||
@ -261,7 +262,7 @@ namespace MMU
|
||||
Result<u64> unmap(u64 virt)
|
||||
{
|
||||
auto& l1 = *TRY(find_entry(virt));
|
||||
if (!l1.present) return err;
|
||||
if (!l1.present) return err(EFAULT);
|
||||
u64 address = l1.get_address();
|
||||
memset(&l1, 0, sizeof(l1));
|
||||
flush_page(virt);
|
||||
@ -271,14 +272,14 @@ namespace MMU
|
||||
Result<u64> get_physical(u64 virt)
|
||||
{
|
||||
auto& l1 = *TRY(find_entry(virt));
|
||||
if (!l1.present) return err;
|
||||
if (!l1.present) return err(EFAULT);
|
||||
return l1.get_address();
|
||||
}
|
||||
|
||||
Result<int> get_flags(u64 virt)
|
||||
{
|
||||
auto& l1 = *TRY(find_entry(virt));
|
||||
if (!l1.present) return err;
|
||||
if (!l1.present) return err(EFAULT);
|
||||
return arch_flags_to_mmu(l1);
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@ void Init::check_magic()
|
||||
{
|
||||
if (memcmp(bootboot.magic, BOOTBOOT_MAGIC, 4))
|
||||
{
|
||||
Serial::println("ERROR: Invalid magic value from bootloader");
|
||||
kerrorln("ERROR: Invalid magic value from bootloader");
|
||||
for (;;)
|
||||
;
|
||||
}
|
||||
|
@ -11,67 +11,28 @@
|
||||
|
||||
Result<void> init()
|
||||
{
|
||||
Serial::println("Hello, world!");
|
||||
kinfoln("Hello, world!");
|
||||
|
||||
Serial::printf("Current platform: %s\n", CPU::platform_string());
|
||||
kinfoln("Current platform: %s", CPU::platform_string());
|
||||
|
||||
Serial::println(TRY(CPU::identify()));
|
||||
|
||||
const u64 address = 0xfffffffff8000000;
|
||||
|
||||
Serial::printf("Mapping address 0x%lx\n", address);
|
||||
|
||||
TRY(MemoryManager::alloc_at(address, 1, MMU::ReadWrite));
|
||||
|
||||
TRY(MMU::remap(address, MMU::ReadWrite | MMU::User));
|
||||
|
||||
int flags = TRY(MMU::get_flags(address));
|
||||
|
||||
if (flags & MMU::ReadWrite) Serial::println("Mapping is now writable");
|
||||
if (flags & MMU::User) Serial::println("Mapping is now user accessible");
|
||||
|
||||
u64 old = TRY(MMU::unmap(address));
|
||||
|
||||
Serial::printf("Unmapped page, was pointing to %#lx\n", old);
|
||||
|
||||
TextConsole::set_foreground(0xff000055);
|
||||
TextConsole::set_background(0xff88ff00);
|
||||
|
||||
TextConsole::printf("Hello from Moon for the %s architecture!\n", CPU::platform_string());
|
||||
kinfoln("Current processor: %s", TRY(CPU::identify()));
|
||||
|
||||
Timer::init();
|
||||
|
||||
kinfoln("Hello, world!");
|
||||
kwarnln("THIS IS A WARNING");
|
||||
kerrorln("ERROR: Please do something.");
|
||||
|
||||
CPU::platform_finish_init();
|
||||
|
||||
CPU::enable_interrupts();
|
||||
|
||||
usize start = 0;
|
||||
|
||||
int* mem = TRY(make<int>());
|
||||
*(volatile int*)mem = 6;
|
||||
Serial::printf("Read %d from memory\n", *mem);
|
||||
|
||||
TRY(destroy(mem));
|
||||
|
||||
char buffer[64];
|
||||
to_dynamic_unit(MemoryManager::total(), buffer, sizeof(buffer));
|
||||
kinfoln("Total memory: %s", buffer);
|
||||
to_dynamic_unit(MemoryManager::free(), buffer, sizeof(buffer));
|
||||
kinfoln("Free memory: %s", buffer);
|
||||
kinfoln("Free memory: %s", buffer);
|
||||
to_dynamic_unit(MemoryManager::used(), buffer, sizeof(buffer));
|
||||
kinfoln("Used memory: %s", buffer);
|
||||
kinfoln("Used memory: %s", buffer);
|
||||
to_dynamic_unit(MemoryManager::reserved(), buffer, sizeof(buffer));
|
||||
kinfoln("Reserved memory: %s", buffer);
|
||||
|
||||
while (1)
|
||||
{
|
||||
while ((Timer::ticks_ms() - start) < 100) { CPU::wait_for_interrupt(); }
|
||||
start = Timer::ticks_ms();
|
||||
kdbgln("%8zu milliseconds have passed!", start);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -80,6 +41,6 @@ extern "C" [[noreturn]] void _start()
|
||||
Init::check_magic();
|
||||
Init::early_init();
|
||||
auto rc = init();
|
||||
rc.release_value();
|
||||
if (rc.has_error()) kerrorln("Runtime error: %s", rc.error_string());
|
||||
CPU::efficient_halt();
|
||||
}
|
@ -1,9 +1,11 @@
|
||||
#include "memory/Heap.h"
|
||||
#include "Log.h"
|
||||
#include "arch/MMU.h"
|
||||
#include "arch/Serial.h"
|
||||
#include "memory/MemoryManager.h"
|
||||
#include <Alignment.h>
|
||||
#include <String.h>
|
||||
#include <SystemError.h>
|
||||
|
||||
static constexpr int BLOCK_USED = 1 << 0;
|
||||
static constexpr int BLOCK_START_MEM = 1 << 1;
|
||||
@ -97,7 +99,7 @@ static Result<HeapBlock*> split(HeapBlock* block, usize size)
|
||||
usize old_size =
|
||||
block->full_size; // Save the old value of this variable since we are going to use it after modifying it
|
||||
|
||||
if (available < (size + sizeof(HeapBlock))) return err;
|
||||
if (available < (size + sizeof(HeapBlock))) return err(0); // This error is not propagated.
|
||||
|
||||
usize offset = get_fair_offset_to_split_at(block, size + sizeof(HeapBlock));
|
||||
block->full_size = offset; // shrink the old block to fit this offset
|
||||
@ -239,18 +241,18 @@ Result<void> kfree(void* ptr)
|
||||
{
|
||||
if (block->magic == BLOCK_DEAD)
|
||||
{
|
||||
Serial::printf("ERROR: Attempt to free memory at %p, which was already freed\n", ptr);
|
||||
kerrorln("ERROR: Attempt to free memory at %p, which was already freed", ptr);
|
||||
}
|
||||
else
|
||||
Serial::printf("ERROR: Attempt to free memory at %p, which wasn't allocated with kmalloc\n", ptr);
|
||||
kerrorln("ERROR: Attempt to free memory at %p, which wasn't allocated with kmalloc", ptr);
|
||||
|
||||
return err;
|
||||
return err(EFAULT);
|
||||
}
|
||||
|
||||
if (is_block_free(block))
|
||||
{
|
||||
Serial::printf("ERROR: Attempt to free memory at %p, which was already freed\n", ptr);
|
||||
return err;
|
||||
kerrorln("ERROR: Attempt to free memory at %p, which was already freed", ptr);
|
||||
return err(EFAULT);
|
||||
}
|
||||
else
|
||||
block->status &= ~BLOCK_USED;
|
||||
@ -295,20 +297,20 @@ Result<void*> krealloc(void* ptr, usize size)
|
||||
{
|
||||
if (block->magic == BLOCK_DEAD)
|
||||
{
|
||||
Serial::printf("ERROR: Attempt to realloc memory at %p, which was already freed\n", ptr);
|
||||
kerrorln("ERROR: Attempt to realloc memory at %p, which was already freed", ptr);
|
||||
}
|
||||
else
|
||||
Serial::printf("ERROR: Attempt to realloc memory at %p, which wasn't allocated with kmalloc\n", ptr);
|
||||
kerrorln("ERROR: Attempt to realloc memory at %p, which wasn't allocated with kmalloc", ptr);
|
||||
|
||||
return err;
|
||||
return err(EFAULT);
|
||||
}
|
||||
|
||||
size = align_up(size, 16UL);
|
||||
|
||||
if (is_block_free(block))
|
||||
{
|
||||
Serial::printf("ERROR: Attempt to realloc memory at %p, which was already freed\n", ptr);
|
||||
return err;
|
||||
kerrorln("ERROR: Attempt to realloc memory at %p, which was already freed", ptr);
|
||||
return err(EFAULT);
|
||||
}
|
||||
|
||||
if (block->full_size >= size)
|
||||
@ -335,10 +337,10 @@ Result<void*> kcalloc(usize nmemb, usize size)
|
||||
|
||||
void dump_heap_usage()
|
||||
{
|
||||
Serial::println("-- Dumping usage stats for kernel heap:");
|
||||
kdbgln("-- Dumping usage stats for kernel heap:");
|
||||
if (!heap_start)
|
||||
{
|
||||
Serial::println("- Heap is not currently being used");
|
||||
kdbgln("- Heap is not currently being used");
|
||||
return;
|
||||
}
|
||||
usize alloc_total = 0;
|
||||
@ -348,19 +350,18 @@ void dump_heap_usage()
|
||||
{
|
||||
if (is_block_free(block))
|
||||
{
|
||||
Serial::printf("- Available block, of size %zu\n", block->full_size);
|
||||
kdbgln("- Available block, of size %zu", block->full_size);
|
||||
alloc_total += block->full_size + sizeof(HeapBlock);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial::printf("- Used block, of size %zu, of which %zu bytes are being used\n", block->full_size,
|
||||
block->req_size);
|
||||
kdbgln("- Used block, of size %zu, of which %zu bytes are being used", block->full_size, block->req_size);
|
||||
alloc_total += block->full_size + sizeof(HeapBlock);
|
||||
alloc_used += block->req_size;
|
||||
}
|
||||
block = block->next;
|
||||
}
|
||||
|
||||
Serial::printf("-- Total memory allocated for heap: %zu bytes\n", alloc_total);
|
||||
Serial::printf("-- Heap memory in use by the kernel: %zu bytes\n", alloc_used);
|
||||
kdbgln("-- Total memory allocated for heap: %zu bytes", alloc_total);
|
||||
kdbgln("-- Heap memory in use by the kernel: %zu bytes", alloc_used);
|
||||
}
|
@ -1,9 +1,10 @@
|
||||
#include "memory/MemoryManager.h"
|
||||
#include "Log.h"
|
||||
#include "arch/MMU.h"
|
||||
#include "arch/Serial.h"
|
||||
#include "boot/bootboot.h"
|
||||
#include <Alignment.h>
|
||||
#include <String.h>
|
||||
#include <SystemError.h>
|
||||
#include <Types.h>
|
||||
|
||||
extern BOOTBOOT bootboot;
|
||||
@ -87,7 +88,7 @@ namespace MemoryManager
|
||||
page_virtual_bitmap_addr = page_bitmap_addr; // we'll map this to virtual memory as soon as the MMU is ready
|
||||
if ((total_mem / ARCH_PAGE_SIZE / 8) >= biggest_memory_block_size)
|
||||
{
|
||||
Serial::println("ERROR: No single memory block is enough to hold the page bitmap");
|
||||
kerrorln("ERROR: No single memory block is enough to hold the page bitmap");
|
||||
for (;;)
|
||||
;
|
||||
}
|
||||
@ -143,14 +144,14 @@ namespace MemoryManager
|
||||
return index * ARCH_PAGE_SIZE;
|
||||
}
|
||||
|
||||
return err; // FIXME: ENOMEM.
|
||||
return err(ENOMEM);
|
||||
}
|
||||
|
||||
Result<void> free_frame(u64 frame)
|
||||
{
|
||||
const u64 index = frame / ARCH_PAGE_SIZE;
|
||||
if (index > (page_bitmap_size * 8)) return err;
|
||||
if (!page_bitmap_read(index)) return err;
|
||||
if (index > (page_bitmap_size * 8)) return err(EFAULT);
|
||||
if (!page_bitmap_read(index)) return err(EFAULT);
|
||||
page_bitmap_set(index, false);
|
||||
used_mem -= ARCH_PAGE_SIZE;
|
||||
free_mem += ARCH_PAGE_SIZE;
|
||||
@ -272,4 +273,9 @@ namespace MemoryManager
|
||||
{
|
||||
return reserved_mem;
|
||||
}
|
||||
|
||||
u64 total()
|
||||
{
|
||||
return free_mem + used_mem + reserved_mem;
|
||||
}
|
||||
}
|
@ -30,4 +30,5 @@ namespace MemoryManager
|
||||
u64 free();
|
||||
u64 used();
|
||||
u64 reserved();
|
||||
u64 total();
|
||||
}
|
@ -3,6 +3,7 @@ set(FREESTANDING_SOURCES
|
||||
NumberParsing.cpp
|
||||
String.cpp
|
||||
Units.cpp
|
||||
SystemError.cpp
|
||||
)
|
||||
|
||||
set(SOURCES
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <Check.h>
|
||||
#include <Move.h>
|
||||
#include <PlacementNew.h>
|
||||
#include <SystemError.h>
|
||||
#include <Types.h>
|
||||
|
||||
struct Error
|
||||
@ -92,6 +93,12 @@ template <typename T> class Result
|
||||
return {m_error};
|
||||
}
|
||||
|
||||
const char* error_string()
|
||||
{
|
||||
check(has_error());
|
||||
return ::error_string(m_error);
|
||||
}
|
||||
|
||||
T value()
|
||||
{
|
||||
check(has_value());
|
||||
@ -224,6 +231,12 @@ template <> class Result<void>
|
||||
return {m_error};
|
||||
}
|
||||
|
||||
const char* error_string()
|
||||
{
|
||||
check(has_error());
|
||||
return ::error_string(m_error);
|
||||
}
|
||||
|
||||
void value()
|
||||
{
|
||||
check(has_value());
|
||||
@ -242,7 +255,7 @@ template <> class Result<void>
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
#define err Error{0}
|
||||
#define err(x) Error{x}
|
||||
// clang-format on
|
||||
|
||||
#define TRY(expr) \
|
||||
|
60
luna/SystemError.cpp
Normal file
60
luna/SystemError.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
#include <SystemError.h>
|
||||
|
||||
const char* error_string(int error)
|
||||
{
|
||||
switch (error)
|
||||
{
|
||||
case 0: return "Success (not an error)";
|
||||
case EPERM: return "Operation not permitted";
|
||||
case ENOENT: return "No such file or directory";
|
||||
case ESRCH: return "No such process";
|
||||
case EINTR: return "Interrupted system call";
|
||||
case EIO: return "Input/output error";
|
||||
case ENXIO: return "No such device or address";
|
||||
case E2BIG: return "Argument list too long";
|
||||
case ENOEXEC: return "Exec format error";
|
||||
case EBADF: return "Bad file descriptor";
|
||||
case ECHILD: return "No child processes";
|
||||
case EAGAIN: return "Resource temporarily unavailable";
|
||||
case ENOMEM: return "Cannot allocate memory";
|
||||
case EACCES: return "Permission denied";
|
||||
case EFAULT: return "Bad address";
|
||||
case EBUSY: return "Device or resource busy";
|
||||
case EEXIST: return "File exists";
|
||||
case EXDEV: return "Invalid cross-device link";
|
||||
case ENODEV: return "No such device";
|
||||
case ENOTDIR: return "Not a directory";
|
||||
case EISDIR: return "Is a directory";
|
||||
case EINVAL: return "Invalid argument";
|
||||
case ENFILE: return "Too many open files in system";
|
||||
case EMFILE: return "Too many open files";
|
||||
case ENOTTY: return "Inappropriate ioctl for device";
|
||||
case EFBIG: return "File too large";
|
||||
case ENOSPC: return "No space left on device";
|
||||
case ESPIPE: return "Illegal seek";
|
||||
case EROFS: return "Read-only file system";
|
||||
case EMLINK: return "Too many links";
|
||||
case EPIPE: return "Broken pipe";
|
||||
case EDOM: return "Numerical argument out of domain";
|
||||
case ERANGE: return "Numerical result out of range";
|
||||
case EDEADLK: return "Resource deadlock avoided";
|
||||
case ENAMETOOLONG: return "File name too long";
|
||||
case ENOLCK: return "No locks available";
|
||||
case ENOSYS: return "Function not implemented";
|
||||
case ENOTEMPTY: return "Directory not empty";
|
||||
case ELOOP: return "Too many levels of symbolic links";
|
||||
case ENOMSG: return "No message of desired type";
|
||||
case EOVERFLOW: return "Value too large for defined data type";
|
||||
case EILSEQ: return "Invalid or incomplete multibyte or wide character";
|
||||
case ENOTSOCK: return "Socket operation on non-socket";
|
||||
case ENOTSUP: return "Operation not supported";
|
||||
case EADDRINUSE: return "Address already in use";
|
||||
case ENETRESET: return "Network dropped connection on reset";
|
||||
case ECONNRESET: return "Connection reset by peer";
|
||||
case EISCONN: return "Transport endpoint is already connected";
|
||||
case ETIMEDOUT: return "Connection timed out";
|
||||
case EALREADY: return "Operation already in progress";
|
||||
case EFIXME: return "Functionality not yet implemented";
|
||||
default: return "Unknown error";
|
||||
}
|
||||
}
|
58
luna/SystemError.h
Normal file
58
luna/SystemError.h
Normal file
@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#define EPERM 1 // Operation not permitted
|
||||
#define ENOENT 2 // No such file or directory
|
||||
#define ESRCH 3 // No such process
|
||||
#define EINTR 4 // Interrupted system call
|
||||
#define EIO 5 // Input/output error
|
||||
#define ENXIO 6 // No such device or address
|
||||
#define E2BIG 7 // Argument list too long
|
||||
#define ENOEXEC 8 // Exec format error
|
||||
#define EBADF 9 // Bad file descriptor
|
||||
#define ECHILD 10 // No child processes
|
||||
#define EAGAIN 11 // Resource temporarily unavailable
|
||||
#define EWOULDBLOCK 11 // Resource temporarily unavailable
|
||||
#define ENOMEM 12 // Cannot allocate memory
|
||||
#define EACCES 13 // Permission denied
|
||||
#define EFAULT 14 // Bad address
|
||||
#define EBUSY 16 // Device or resource busy
|
||||
#define EEXIST 17 // File exists
|
||||
#define EXDEV 18 // Invalid cross-device link
|
||||
#define ENODEV 19 // No such device
|
||||
#define ENOTDIR 20 // Not a directory
|
||||
#define EISDIR 21 // Is a directory
|
||||
#define EINVAL 22 // Invalid argument
|
||||
#define ENFILE 23 // Too many open files in system
|
||||
#define EMFILE 24 // Too many open files
|
||||
#define ENOTTY 25 // Inappropriate ioctl for device
|
||||
#define EFBIG 27 // File too large
|
||||
#define ENOSPC 28 // No space left on device
|
||||
#define ESPIPE 29 // Illegal seek
|
||||
#define EROFS 30 // Read-only file system
|
||||
#define EMLINK 31 // Too many links
|
||||
#define EPIPE 32 // Broken pipe
|
||||
#define EDOM 33 // Numerical argument out of domain
|
||||
#define ERANGE 34 // Numerical result out of range
|
||||
#define EDEADLK 35 // Resource deadlock avoided
|
||||
#define ENAMETOOLONG 36 // File name too long
|
||||
#define ENOLCK 37 // No locks available
|
||||
#define ENOSYS 38 // Function not implemented
|
||||
#define ENOTEMPTY 39 // Directory not empty
|
||||
#define ELOOP 40 // Too many levels of symbolic links
|
||||
#define ENOMSG 42 // No message of desired type
|
||||
#define EOVERFLOW 75 // Value too large for defined data type
|
||||
#define EILSEQ 84 // Invalid or incomplete multibyte or wide character
|
||||
#define ENOTSOCK 88 // Socket operation on non-socket
|
||||
#define ENOTSUP 95 // Operation not supported
|
||||
#define EOPNOTSUPP 95 // Operation not supported
|
||||
#define EADDRINUSE 98 // Address already in use
|
||||
#define ENETRESET 102 // Network dropped connection on reset
|
||||
#define ECONNRESET 104 // Connection reset by peer
|
||||
#define EISCONN 106 // Transport endpoint is already connected
|
||||
#define ETIMEDOUT 110 // Connection timed out
|
||||
#define EALREADY 114 // Operation already in progress
|
||||
|
||||
// This one is Luna-specific.
|
||||
#define EFIXME 342 // Functionality not yet implemented
|
||||
|
||||
const char* error_string(int error);
|
@ -1,15 +1,14 @@
|
||||
#include <Format.h>
|
||||
#include <Units.h>
|
||||
#include <limits.h>
|
||||
|
||||
Result<usize> to_dynamic_unit(usize value, char* buffer, size_t max)
|
||||
{
|
||||
if (value < 1024) { return string_format(buffer, max, "%u bytes", value); }
|
||||
|
||||
const char* unit_prefixes = "KMGTPE";
|
||||
for (int i = 40; i >= 0 && value > (0xfffccccccccccccUL >> i); i -= 10)
|
||||
while (value > (1024 * 1024))
|
||||
{
|
||||
value >>= 10;
|
||||
value /= 1024;
|
||||
unit_prefixes++;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user