diff --git a/Kernel/.vscode/c_cpp_properties.json b/Kernel/.vscode/c_cpp_properties.json
index 8d3c3fd6..fb685623 100644
--- a/Kernel/.vscode/c_cpp_properties.json
+++ b/Kernel/.vscode/c_cpp_properties.json
@@ -137,6 +137,33 @@
"-nostdinc++"
]
},
+ {
+ "name": "Fennix Arm (Linux, GCC, debug)",
+ "includePath": [
+ "${workspaceFolder}/include",
+ "${workspaceFolder}/include/**",
+ "${workspaceFolder}/include_std",
+ "${workspaceFolder}/include_std/**",
+ "${workspaceFolder}/arch/aarch64/include"
+ ],
+ "forcedInclude": [
+ "${workspaceFolder}/.vscode/preinclude.h"
+ ],
+ "defines": [
+ "DEBUG=\"1\""
+ ],
+ "compilerPath": "${workspaceFolder}/../tools/cross/bin/arm-fennix-gcc",
+ "cStandard": "c17",
+ "cppStandard": "c++20",
+ "intelliSenseMode": "linux-gcc-arm",
+ "configurationProvider": "ms-vscode.makefile-tools",
+ "compilerArgs": [
+ // VSCode flags
+ "-ffreestanding",
+ "-nostdinc",
+ "-nostdinc++"
+ ]
+ },
{
"name": "Fennix Aarch64 (Linux, GCC, debug)",
"includePath": [
diff --git a/Kernel/Makefile b/Kernel/Makefile
index 65130491..76f49399 100644
--- a/Kernel/Makefile
+++ b/Kernel/Makefile
@@ -53,6 +53,10 @@ LDFLAGS += -Tarch/amd64/linker.ld
else ifeq ($(OSARCH), i386)
CFLAGS += -march=pentium -m32 -mno-red-zone
LDFLAGS += -Tarch/i386/linker.ld
+else ifeq ($(OSARCH), arm)
+CFLAGS += -march=armv7-a -mfloat-abi=hard -mfpu=vfpv3-d16
+LDFLAGS += -Tarch/arm/linker.ld
+WARNCFLAG += -w
else ifeq ($(OSARCH), aarch64)
CFLAGS += -march=armv9.4-a -mtune=cortex-a72 -mlittle-endian -mcmodel=large
LDFLAGS += -Tarch/aarch64/linker.ld
@@ -67,6 +71,9 @@ ifeq ($(DEBUG), 1)
ifeq ($(OSARCH), amd64)
CFLAGS += -fverbose-asm
endif # amd64
+ifeq ($(OSARCH), arm)
+ CFLAGS += -fstack-check -fverbose-asm
+endif # arm
ifeq ($(OSARCH), aarch64)
CFLAGS += -fstack-check -fverbose-asm
endif # aarch64
@@ -119,6 +126,8 @@ ifeq ($(OSARCH), amd64)
$(__CONF_OBJCOPY) -O elf64-x86-64 -I binary $< $@
else ifeq ($(OSARCH), i386)
$(__CONF_OBJCOPY) -O elf32-i386 -I binary $< $@
+else ifeq ($(OSARCH), arm)
+ $(__CONF_OBJCOPY) -O elf32-littlearm -I binary $< $@
else ifeq ($(OSARCH), aarch64)
$(__CONF_OBJCOPY) -O elf64-littleaarch64 -I binary $< $@
endif
@@ -129,6 +138,8 @@ ifeq ($(OSARCH), amd64)
$(__CONF_OBJCOPY) -O elf64-x86-64 -I binary $< $@
else ifeq ($(OSARCH), i386)
$(__CONF_OBJCOPY) -O elf32-i386 -I binary $< $@
+else ifeq ($(OSARCH), arm)
+ $(__CONF_OBJCOPY) -O elf32-littlearm -I binary $< $@
else ifeq ($(OSARCH), aarch64)
$(__CONF_OBJCOPY) -O elf64-littlearch64 -I binary $< $@
endif
diff --git a/Kernel/arch/arm/aeabi.c b/Kernel/arch/arm/aeabi.c
new file mode 100644
index 00000000..c6410f19
--- /dev/null
+++ b/Kernel/arch/arm/aeabi.c
@@ -0,0 +1,40 @@
+/*
+ This file is part of Fennix Kernel.
+
+ Fennix Kernel is free software: you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ Fennix Kernel is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Fennix Kernel. If not, see .
+*/
+
+unsigned __aeabi_uidiv(unsigned a, unsigned b) { return a / b; }
+unsigned __aeabi_idiv(unsigned a, unsigned b) { return a / b; }
+unsigned __aeabi_l2d(unsigned a) { return a; }
+unsigned __aeabi_d2lz(unsigned a) { return a; }
+
+unsigned __aeabi_ldivmod(unsigned a, unsigned b, unsigned *r) { *r = a % b; return a / b; }
+
+unsigned __aeabi_uldivmod(unsigned a, unsigned b, unsigned *r) { *r = a % b; return a / b; }
+
+unsigned __aeabi_uidivmod(unsigned a, unsigned b, unsigned *r) { *r = a % b; return a / b; }
+
+
+unsigned __aeabi_idivmod(unsigned a, unsigned b, unsigned *r) { *r = a % b; return a / b; }
+
+
+unsigned __aeabi_unwind_cpp_pr1(void) { return 0; }
+unsigned __aeabi_atexit(void) { return 0; }
+unsigned __cxa_end_cleanup(void) { return 0; }
+unsigned __aeabi_unwind_cpp_pr0(void) { return 0; }
+
+
+
+
diff --git a/Kernel/arch/arm/bootstrap/boot.S b/Kernel/arch/arm/bootstrap/boot.S
new file mode 100644
index 00000000..956b21f1
--- /dev/null
+++ b/Kernel/arch/arm/bootstrap/boot.S
@@ -0,0 +1,18 @@
+/* Based on this tutorial:
+ https://github.com/s-matyukevich/raspberry-pi-os */
+
+.section ".text.boot", "a"
+
+.extern _bss_start
+.extern _bss_end
+
+.global _start
+_start:
+ b CPU_Loop
+
+Halt:
+ wfe
+ b Halt
+
+CPU_Loop:
+ b CPU_Loop
diff --git a/Kernel/arch/arm/core/panic/ui.cpp b/Kernel/arch/arm/core/panic/ui.cpp
new file mode 100644
index 00000000..eeae5743
--- /dev/null
+++ b/Kernel/arch/arm/core/panic/ui.cpp
@@ -0,0 +1,46 @@
+/*
+ This file is part of Fennix Kernel.
+
+ Fennix Kernel is free software: you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ Fennix Kernel is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Fennix Kernel. If not, see .
+*/
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#if defined(__amd64__)
+#include "../../arch/amd64/cpu/gdt.hpp"
+#include "../arch/amd64/cpu/apic.hpp"
+#elif defined(__i386__)
+#include "../../arch/i386/cpu/gdt.hpp"
+#include "../arch/i386/cpu/apic.hpp"
+#elif defined(__aarch64__)
+#endif
+
+#include "../../../../kernel.h"
+
+extern void ExPrint(const char *Format, ...);
+
+arch nsa void DisplayDetailsScreen(CPU::ExceptionFrame *Frame)
+{
+ ExPrint("\nException Frame:\n");
+}
diff --git a/Kernel/arch/arm/cpu/smp.cpp b/Kernel/arch/arm/cpu/smp.cpp
new file mode 100644
index 00000000..7f6454dc
--- /dev/null
+++ b/Kernel/arch/arm/cpu/smp.cpp
@@ -0,0 +1,59 @@
+/*
+ This file is part of Fennix Kernel.
+
+ Fennix Kernel is free software: you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ Fennix Kernel is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Fennix Kernel. If not, see .
+*/
+
+#include
+
+#include
+#include
+#include
+
+#include "../../../kernel.h"
+
+volatile bool CPUEnabled = false;
+
+#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
+static __aligned(0x1000) CPUData CPUs[MAX_CPU] = {0};
+
+CPUData *GetCPU(uint64_t id) { return &CPUs[id]; }
+
+CPUData *GetCurrentCPU()
+{
+ uint64_t ret = 0;
+
+ if (!CPUs[ret].IsActive)
+ {
+ error("CPU %d is not active!", ret);
+ return &CPUs[0];
+ }
+
+ if (CPUs[ret].Checksum != CPU_DATA_CHECKSUM)
+ {
+ error("CPU %d data is corrupted!", ret);
+ return &CPUs[0];
+ }
+ return &CPUs[ret];
+}
+
+namespace SMP
+{
+ int CPUCores = 0;
+
+ void Initialize(void *madt)
+ {
+ fixme("SMP::Initialize() is not implemented!");
+ }
+}
diff --git a/Kernel/arch/arm/entry.cpp b/Kernel/arch/arm/entry.cpp
new file mode 100644
index 00000000..d0ec97cd
--- /dev/null
+++ b/Kernel/arch/arm/entry.cpp
@@ -0,0 +1,27 @@
+/*
+ This file is part of Fennix Kernel.
+
+ Fennix Kernel is free software: you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ Fennix Kernel is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Fennix Kernel. If not, see .
+*/
+
+#include
+
+#include
+#include
+
+EXTERNC void arm64Entry(uint64_t dtb_ptr32, uint64_t x1, uint64_t x2, uint64_t x3)
+{
+ trace("Hello, World!");
+ CPU::Halt(true);
+}
diff --git a/Kernel/arch/arm/include/.gitkeep b/Kernel/arch/arm/include/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/Kernel/arch/arm/linker.ld b/Kernel/arch/arm/linker.ld
new file mode 100644
index 00000000..23fb294a
--- /dev/null
+++ b/Kernel/arch/arm/linker.ld
@@ -0,0 +1,89 @@
+/*
+ This file is part of Fennix Kernel.
+
+ Fennix Kernel is free software: you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ Fennix Kernel is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Fennix Kernel. If not, see .
+*/
+
+ENTRY(_start)
+
+SECTIONS
+{
+ _bootstrap_start = .;
+ .text.boot :
+ {
+ *(.text.boot)
+ . += CONSTANT(MAXPAGESIZE);
+ _bss_start = .;
+ *(.text.bss)
+ _bss_end = .;
+ }
+ _bootstrap_end = .;
+
+ _kernel_start = .;
+ _kernel_text_start = .;
+ .text :
+ {
+ KEEP(*(.text.boot))
+ *(.text .text.*)
+ }
+ . = ALIGN(4096);
+ _kernel_text_end = .;
+
+ _kernel_data_start = .;
+ .data :
+ {
+ *(.data .data.*)
+ }
+ . = ALIGN(4096);
+ _kernel_data_end = .;
+
+ _kernel_rodata_start = .;
+ .rodata :
+ {
+ *(.rodata .rodata.*)
+ }
+ . = ALIGN(4096);
+
+ .init_array :
+ {
+ PROVIDE_HIDDEN(__init_array_start = .);
+ KEEP(*(.init_array .ctors))
+ KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
+ PROVIDE_HIDDEN (__init_array_end = .);
+ }
+
+ .fini_array :
+ {
+ PROVIDE_HIDDEN(__fini_array_start = .);
+ KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
+ KEEP(*(.fini_array .dtors))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+ }
+ _kernel_rodata_end = .;
+
+ _kernel_bss_start = .;
+ .bss :
+ {
+ *(.bss .bss.*)
+ }
+ . = ALIGN(4096);
+ _kernel_bss_end = .;
+ _kernel_end = .;
+ _bss_size = _kernel_end - _kernel_rodata_end;
+
+ /DISCARD/ :
+ {
+ *(.comment*)
+ }
+}
diff --git a/Kernel/arch/arm/madt.cpp b/Kernel/arch/arm/madt.cpp
new file mode 100644
index 00000000..eaf2b011
--- /dev/null
+++ b/Kernel/arch/arm/madt.cpp
@@ -0,0 +1,97 @@
+/*
+ This file is part of Fennix Kernel.
+
+ Fennix Kernel is free software: you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ Fennix Kernel is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Fennix Kernel. If not, see .
+*/
+
+#include "acpi.hpp"
+
+#include
+#include
+
+#include "../../kernel.h"
+
+namespace ACPI
+{
+ MADT::MADT(ACPI::MADTHeader *madt)
+ {
+ trace("Initializing MADT");
+ if (!madt)
+ {
+ error("MADT is NULL");
+ return;
+ }
+
+ CPUCores = 0;
+ LAPICAddress = (LAPIC *)(uintptr_t)madt->LocalControllerAddress;
+ for (uint8_t *ptr = (uint8_t *)(madt->Entries);
+ (uintptr_t)(ptr) < (uintptr_t)(madt) + madt->Header.Length;
+ ptr += *(ptr + 1))
+ {
+ switch (*(ptr))
+ {
+ case 0:
+ {
+ if (ptr[4] & 1)
+ {
+ lapic.push_back((LocalAPIC *)ptr);
+ KPrint("Local APIC %d (APIC %d) found.", lapic.back()->ACPIProcessorId, lapic.back()->APICId);
+ CPUCores++;
+ }
+ break;
+ }
+ case 1:
+ {
+ ioapic.push_back((MADTIOApic *)ptr);
+ KPrint("I/O APIC %d (Address %#lx) found.", ioapic.back()->APICID, ioapic.back()->Address);
+ Memory::Virtual(KernelPageTable).Map((void *)(uintptr_t)ioapic.back()->Address, (void *)(uintptr_t)ioapic.back()->Address, Memory::PTFlag::RW | Memory::PTFlag::PCD); // Make sure that the address is mapped.
+ break;
+ }
+ case 2:
+ {
+ iso.push_back((MADTIso *)ptr);
+ KPrint("ISO (IRQ:%#lx, BUS:%#lx, GSI:%#lx, %s/%s) found.",
+ iso.back()->IRQSource, iso.back()->BuSSource, iso.back()->GSI,
+ iso.back()->Flags & 0x00000004 ? "Active High" : "Active Low",
+ iso.back()->Flags & 0x00000100 ? "Edge Triggered" : "Level Triggered");
+ break;
+ }
+ case 4:
+ {
+ nmi.push_back((MADTNmi *)ptr);
+ KPrint("NMI %#lx (lint:%#lx) found.", nmi.back()->processor, nmi.back()->lint);
+ break;
+ }
+ case 5:
+ {
+ LAPICAddress = (LAPIC *)ptr;
+ KPrint("APIC found at %#lx", LAPICAddress);
+ break;
+ }
+ default:
+ {
+ KPrint("Unknown MADT entry %#lx", *(ptr));
+ break;
+ }
+ }
+ Memory::Virtual(KernelPageTable).Map((void *)LAPICAddress, (void *)LAPICAddress, Memory::PTFlag::RW | Memory::PTFlag::PCD); // I should map more than one page?
+ }
+ CPUCores--; // We start at 0 (BSP) and end at 11 (APs), so we have 12 cores.
+ KPrint("Total CPU cores: %d", CPUCores + 1);
+ }
+
+ MADT::~MADT()
+ {
+ }
+}
diff --git a/Kernel/arch/arm/memory/vmm.cpp b/Kernel/arch/arm/memory/vmm.cpp
new file mode 100644
index 00000000..185a082f
--- /dev/null
+++ b/Kernel/arch/arm/memory/vmm.cpp
@@ -0,0 +1,69 @@
+/*
+ This file is part of Fennix Kernel.
+
+ Fennix Kernel is free software: you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ Fennix Kernel is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Fennix Kernel. If not, see .
+*/
+
+#include
+
+#include
+#include
+
+namespace Memory
+{
+ bool Virtual::Check(void *VirtualAddress, PTFlag Flag, MapType Type)
+ {
+#warning "arm not implemented"
+ return 0;
+ }
+
+ void *Virtual::GetPhysical(void *VirtualAddress)
+ {
+#warning "arm not implemented"
+ return nullptr;
+ }
+
+ Virtual::MapType Virtual::GetMapType(void *VirtualAddress)
+ {
+#warning "arm not implemented"
+ return MapType::NoMapType;
+ }
+
+ PageDirectoryEntry *Virtual::GetPDE(void *VirtualAddress, MapType Type)
+ {
+#warning "arm not implemented"
+ return nullptr;
+ }
+
+ PageTableEntry *Virtual::GetPTE(void *VirtualAddress, MapType Type)
+ {
+#warning "arm not implemented"
+ return nullptr;
+ }
+
+ void Virtual::Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags, MapType Type)
+ {
+#warning "arm not implemented"
+ }
+
+ void Virtual::Unmap(void *VirtualAddress, MapType Type)
+ {
+#warning "arm not implemented"
+ }
+
+ void Virtual::Remap(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags, MapType Type)
+ {
+#warning "arm not implemented"
+ }
+}
diff --git a/Kernel/arch/arm/syscalls.cpp b/Kernel/arch/arm/syscalls.cpp
new file mode 100644
index 00000000..e3fe63d7
--- /dev/null
+++ b/Kernel/arch/arm/syscalls.cpp
@@ -0,0 +1,30 @@
+/*
+ This file is part of Fennix Kernel.
+
+ Fennix Kernel is free software: you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ Fennix Kernel is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Fennix Kernel. If not, see .
+*/
+
+#include
+
+#include
+
+extern "C" __used __no_stack_protector void SystemCallHandlerStub()
+{
+}
+
+extern "C" uint64_t SystemCallsHandler(SyscallsFrame *regs);
+
+void InitializeSystemCalls()
+{
+}
diff --git a/Kernel/arch/arm/tasking/signal.cpp b/Kernel/arch/arm/tasking/signal.cpp
new file mode 100644
index 00000000..619bd798
--- /dev/null
+++ b/Kernel/arch/arm/tasking/signal.cpp
@@ -0,0 +1,38 @@
+/*
+ This file is part of Fennix Kernel.
+
+ Fennix Kernel is free software: you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ Fennix Kernel is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Fennix Kernel. If not, see .
+*/
+
+#include
+#include
+#include
+#include
+
+/* subsystem/linux/syscall.cpp */
+extern int ConvertSignalToLinux(signal_t sig);
+
+namespace Tasking
+{
+ bool Signal::HandleSignal(CPU::SchedulerFrame *tf, void *thread)
+ {
+#warning "arm not implemented"
+ return false;
+ }
+
+ void Signal::RestoreHandleSignal(SyscallsFrame *sf, void *thread)
+ {
+#warning "arm not implemented"
+ }
+}
diff --git a/Kernel/arch/arm/tasking/signal_trampoline.s b/Kernel/arch/arm/tasking/signal_trampoline.s
new file mode 100644
index 00000000..c23e2f51
--- /dev/null
+++ b/Kernel/arch/arm/tasking/signal_trampoline.s
@@ -0,0 +1,28 @@
+/*
+ This file is part of Fennix Kernel.
+
+ Fennix Kernel is free software: you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ Fennix Kernel is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Fennix Kernel. If not, see .
+*/
+
+.global _sig_native_trampoline_start
+_sig_native_trampoline_start:
+
+.global _sig_native_trampoline_end
+_sig_native_trampoline_end:
+
+.global _sig_linux_trampoline_start
+_sig_linux_trampoline_start:
+
+.global _sig_linux_trampoline_end
+_sig_linux_trampoline_end:
diff --git a/Kernel/core/memory/heap_allocators/rpmalloc/rpmalloc.c b/Kernel/core/memory/heap_allocators/rpmalloc/rpmalloc.c
index e155c96f..064b7c2f 100644
--- a/Kernel/core/memory/heap_allocators/rpmalloc/rpmalloc.c
+++ b/Kernel/core/memory/heap_allocators/rpmalloc/rpmalloc.c
@@ -551,9 +551,9 @@ struct heap_t
};
/* Keep in sync with heap_t inside rpmalloc_compat.cpp */
-#ifndef __i386__
+#if !defined(__i386__) && !defined(__arm__)
static_assert(sizeof(heap_t) == 56408, "heap_t size mismatch");
-#endif // __i386__
+#endif // __i386__ || __arm__
// Size class for defining a block size bucket
struct size_class_t
@@ -3105,7 +3105,11 @@ rpcalloc(size_t num, size_t size)
{
size_t total;
#if ENABLE_VALIDATE_ARGS
+#ifdef __arm__
+ int err = __builtin_umull_overflow(num, size, (unsigned long *)&total);
+#else
int err = __builtin_umull_overflow(num, size, &total);
+#endif
assert(!err && (total < MAX_ALLOC_SIZE));
#else
total = num * size;
@@ -3150,7 +3154,11 @@ rpaligned_calloc(size_t alignment, size_t num, size_t size)
{
size_t total;
#if ENABLE_VALIDATE_ARGS
+#ifdef __arm__
+ int err = __builtin_umull_overflow(num, size, (unsigned long *)&total);
+#else
int err = __builtin_umull_overflow(num, size, &total);
+#endif
assert(!err && (total < MAX_ALLOC_SIZE));
#else
total = num * size;
diff --git a/Kernel/core/memory/reserve_essentials.cpp b/Kernel/core/memory/reserve_essentials.cpp
index 2c9b5b00..b1253b8e 100644
--- a/Kernel/core/memory/reserve_essentials.cpp
+++ b/Kernel/core/memory/reserve_essentials.cpp
@@ -93,7 +93,7 @@ namespace Memory
#if defined(__amd64__) || defined(__aarch64__)
Elf64_Xword SymbolSize = 0;
Elf64_Xword StringSize = 0;
-#elif defined(__i386__)
+#elif defined(__i386__) || defined(__arm__)
Elf32_Word SymbolSize = 0;
Elf32_Word StringSize = 0;
#endif
diff --git a/Kernel/core/panic/ui.cpp b/Kernel/core/panic/ui.cpp
index c9c81e82..c9cf6a13 100644
--- a/Kernel/core/panic/ui.cpp
+++ b/Kernel/core/panic/ui.cpp
@@ -304,12 +304,19 @@ nsa void DisplayMainScreen(CPU::ExceptionFrame *Frame)
"stub",
"stub",
#warning "aarch64 not implemented"
+#elif defined(__arm__)
+ "stub",
+ "stub",
+#warning "arm not implemented"
#endif
#if defined(__amd64__) || defined(__i386__)
Frame->InterruptNumber);
#elif defined(__aarch64__)
0);
#warning "aarch64 not implemented"
+#elif defined(__arm__)
+ 0);
+#warning "arm not implemented"
#endif
#if defined(__amd64__) || defined(__i386__)
ExPrint("Cause: %s\n", x86Exceptions[Frame->InterruptNumber].Cause);
@@ -320,6 +327,8 @@ nsa void DisplayMainScreen(CPU::ExceptionFrame *Frame)
Frame->rip);
#elif defined(__i386__)
Frame->eip);
+#elif defined(__arm__)
+0);
#elif defined(__aarch64__)
0);
#warning "aarch64 not implemented"
diff --git a/Kernel/core/symbols.cpp b/Kernel/core/symbols.cpp
index 4af12849..8fb4d39a 100644
--- a/Kernel/core/symbols.cpp
+++ b/Kernel/core/symbols.cpp
@@ -104,7 +104,7 @@ namespace SymbolResolver
#if defined(__amd64__) || defined(__aarch64__)
Elf64_Xword SymbolSize = 0;
// Elf64_Xword StringSize = 0;
-#elif defined(__i386__)
+#elif defined(__i386__) || defined(__arm__)
Elf32_Word SymbolSize = 0;
// Elf32_Word StringSize = 0;
#endif
@@ -220,7 +220,7 @@ namespace SymbolResolver
#if defined(__amd64__) || defined(__aarch64__)
Elf64_Ehdr *Header = (Elf64_Ehdr *)ImageAddress;
-#elif defined(__i386__)
+#elif defined(__i386__) || defined(__arm__)
Elf32_Ehdr *Header = (Elf32_Ehdr *)ImageAddress;
#endif
if (Header->e_ident[0] != 0x7F &&
diff --git a/Kernel/include/abi.h b/Kernel/include/abi.h
index 36fecc1c..2895af08 100644
--- a/Kernel/include/abi.h
+++ b/Kernel/include/abi.h
@@ -80,9 +80,11 @@ typedef struct
#if defined(__amd64__)
typedef Elf64_auxv_t Elf_auxv_t;
#elif defined(__i386__)
-typedef Elf64_auxv_t Elf_auxv_t;
+typedef Elf32_auxv_t Elf_auxv_t;
#elif defined(__aarch64__)
typedef Elf64_auxv_t Elf_auxv_t;
+#elif defined(__arm__)
+typedef Elf32_auxv_t Elf_auxv_t;
#endif
typedef struct
diff --git a/Kernel/include/convert.h b/Kernel/include/convert.h
index b78891c4..9a8f71e2 100644
--- a/Kernel/include/convert.h
+++ b/Kernel/include/convert.h
@@ -90,8 +90,8 @@ extern "C"
long unsigned strlen_sse4_1(const char s[]);
long unsigned strlen_sse4_2(const char s[]);
- long unsigned strlen(const char s[]);
- int strncmp(const char *s1, const char *s2, unsigned long n);
+ size_t strlen(const char s[]);
+ int strncmp(const char *s1, const char *s2, size_t n);
char *strcat_unsafe(char *destination, const char *source);
char *strcpy_unsafe(char *destination, const char *source);
char *strncpy(char *destination, const char *source, unsigned long num);
diff --git a/Kernel/include/cpu.hpp b/Kernel/include/cpu.hpp
index 0f53d505..38d699df 100644
--- a/Kernel/include/cpu.hpp
+++ b/Kernel/include/cpu.hpp
@@ -1072,6 +1072,72 @@ namespace CPU
}
}
+ namespace arm
+ {
+ struct TrapFrame
+ {
+ uint32_t R0; /* Register R0 (argument / scratch) */
+ uint32_t R1; /* Register R1 (argument / scratch) */
+ uint32_t R2; /* Register R2 (argument / scratch) */
+ uint32_t R3; /* Register R3 (argument / scratch) */
+ uint32_t R4; /* Register R4 (callee-saved) */
+ uint32_t R5; /* Register R5 (callee-saved) */
+ uint32_t R6; /* Register R6 (callee-saved) */
+ uint32_t R7; /* Register R7 (callee-saved) */
+ uint32_t R8; /* Register R8 (callee-saved) */
+ uint32_t R9; /* Register R9 (platform-specific) */
+ uint32_t R10; /* Register R10 (callee-saved) */
+ uint32_t FP; /* Frame Pointer (R11) */
+ uint32_t IP; /* Intra-Procedure Scratch (R12) */
+ uint32_t SP; /* Stack Pointer (R13) */
+ uint32_t LR; /* Link Register (R14) */
+ uint32_t PC; /* Program Counter (R15) */
+ uint32_t CPSR; /* Current Program Status Register */
+ };
+
+ struct SchedulerFrame
+ {
+ uint32_t R0; /* Register R0 (argument / scratch) */
+ uint32_t R1; /* Register R1 (argument / scratch) */
+ uint32_t R2; /* Register R2 (argument / scratch) */
+ uint32_t R3; /* Register R3 (argument / scratch) */
+ uint32_t R4; /* Register R4 (callee-saved) */
+ uint32_t R5; /* Register R5 (callee-saved) */
+ uint32_t R6; /* Register R6 (callee-saved) */
+ uint32_t R7; /* Register R7 (callee-saved) */
+ uint32_t R8; /* Register R8 (callee-saved) */
+ uint32_t R9; /* Register R9 (platform-specific) */
+ uint32_t R10; /* Register R10 (callee-saved) */
+ uint32_t FP; /* Frame Pointer (R11) */
+ uint32_t IP; /* Intra-Procedure Scratch (R12) */
+ uint32_t SP; /* Stack Pointer (R13) */
+ uint32_t LR; /* Link Register (R14) */
+ uint32_t PC; /* Program Counter (R15) */
+ uint32_t CPSR; /* Current Program Status Register */
+ };
+
+ struct ExceptionFrame
+ {
+ uint32_t R0; /* Register R0 (argument / scratch) */
+ uint32_t R1; /* Register R1 (argument / scratch) */
+ uint32_t R2; /* Register R2 (argument / scratch) */
+ uint32_t R3; /* Register R3 (argument / scratch) */
+ uint32_t R4; /* Register R4 (callee-saved) */
+ uint32_t R5; /* Register R5 (callee-saved) */
+ uint32_t R6; /* Register R6 (callee-saved) */
+ uint32_t R7; /* Register R7 (callee-saved) */
+ uint32_t R8; /* Register R8 (callee-saved) */
+ uint32_t R9; /* Register R9 (platform-specific) */
+ uint32_t R10; /* Register R10 (callee-saved) */
+ uint32_t FP; /* Frame Pointer (R11) */
+ uint32_t IP; /* Intra-Procedure Scratch (R12) */
+ uint32_t SP; /* Stack Pointer (R13) */
+ uint32_t LR; /* Link Register (R14) */
+ uint32_t PC; /* Program Counter (R15) */
+ uint32_t CPSR; /* Current Program Status Register */
+ };
+ }
+
namespace aarch64
{
struct TrapFrame
@@ -1123,6 +1189,15 @@ namespace CPU
typedef x32::TrapFrame TrapFrame;
typedef x32::SchedulerFrame SchedulerFrame;
typedef x32::ExceptionFrame ExceptionFrame;
+#elif defined(__arm__)
+ /**
+ * CPU trap frame for the current architecture
+ *
+ * @note This is for arm
+ */
+ typedef arm::TrapFrame TrapFrame;
+ typedef arm::SchedulerFrame SchedulerFrame;
+ typedef arm::ExceptionFrame ExceptionFrame;
#elif defined(__aarch64__)
/**
* CPU trap frame for the current architecture
diff --git a/Kernel/include/elf.h b/Kernel/include/elf.h
index d3de007f..b63f9dda 100644
--- a/Kernel/include/elf.h
+++ b/Kernel/include/elf.h
@@ -962,7 +962,7 @@ typedef Elf64_Rel Elf_Rel;
typedef Elf64_Sym Elf_Sym;
typedef Elf64_Dyn Elf_Dyn;
typedef Elf64_Rela Elf_Rela;
-#elif defined(__i386__)
+#elif defined(__i386__) || defined(__arm__)
typedef Elf32_Addr Elf_Addr;
typedef Elf32_Half Elf_Half;
typedef Elf32_Off Elf_Off;
diff --git a/Kernel/include/memory/macro.hpp b/Kernel/include/memory/macro.hpp
index e75beb83..3bd33600 100644
--- a/Kernel/include/memory/macro.hpp
+++ b/Kernel/include/memory/macro.hpp
@@ -59,7 +59,7 @@
#define USER_STACK_END 0xFFFFEFFF00000000 /* 256 MiB */
#define USER_STACK_BASE 0xFFFFEFFFFFFF0000
-#elif defined(__i386__)
+#elif defined(__i386__) || defined(__arm__)
#define KERNEL_VMA_OFFSET 0xC0000000
#define USER_ALLOC_BASE 0x80000000
diff --git a/Kernel/include/syscalls.hpp b/Kernel/include/syscalls.hpp
index f0cd1d3b..45fcd777 100644
--- a/Kernel/include/syscalls.hpp
+++ b/Kernel/include/syscalls.hpp
@@ -67,6 +67,14 @@ typedef struct SyscallsFrame
uint64_t ExceptionSyndromeRegister;
uint64_t FaultAddressRegister;
uint64_t SavedProgramStatusRegister;
+#elif defined(__arm__)
+ uint32_t ReturnAddress; /* r0 */
+ uint32_t x[14];
+ uint32_t StackPointer;
+ uint32_t ExceptionLinkRegister;
+ uint32_t ExceptionSyndromeRegister;
+ uint32_t FaultAddressRegister;
+ uint32_t SavedProgramStatusRegister;
#endif
uintptr_t ReturnValue() const
diff --git a/Kernel/include/task.hpp b/Kernel/include/task.hpp
index 07b5545a..105b0a1e 100644
--- a/Kernel/include/task.hpp
+++ b/Kernel/include/task.hpp
@@ -553,6 +553,8 @@ namespace Tasking
return x64;
#elif defined(__i386__)
return x32;
+#elif defined(__arm__)
+ return ARM32;
#elif defined(__aarch64__)
return ARM64;
#endif
diff --git a/Kernel/include/types.h b/Kernel/include/types.h
index 5b782c42..9714a7db 100644
--- a/Kernel/include/types.h
+++ b/Kernel/include/types.h
@@ -171,7 +171,7 @@ typedef uint32_t uid_t;
typedef uint32_t gid_t;
typedef int64_t clock_t;
typedef int32_t pid_t;
-#elif defined(__i386__)
+#elif defined(__i386__) || defined(__arm__)
typedef int32_t off_t;
typedef long long off64_t;
typedef uint32_t mode_t;
diff --git a/Kernel/include_std/float.h b/Kernel/include_std/float.h
index 369b7161..ee779857 100644
--- a/Kernel/include_std/float.h
+++ b/Kernel/include_std/float.h
@@ -27,6 +27,10 @@
#define DBL_MANT_DIG 24
#define DBL_MAX_10_EXP 38
#define DBL_MAX 3.4028234663852886e+38
+#elif __arm__
+#define DBL_MANT_DIG __DBL_MANT_DIG__
+#define DBL_MAX_10_EXP __DBL_MAX_10_EXP__
+#define DBL_MAX __DBL_MAX__
#elif __aarch64__
#define DBL_MANT_DIG __DBL_MANT_DIG__
#define DBL_MAX_10_EXP __DBL_MAX_10_EXP__
diff --git a/Kernel/include_std/functional b/Kernel/include_std/functional
index 97ac2bbf..e58d5588 100644
--- a/Kernel/include_std/functional
+++ b/Kernel/include_std/functional
@@ -45,6 +45,10 @@ namespace std
static_assert(sizeof(uintptr_t) == sizeof(uint32_t));
const uint32_t FNV_OFFSET_BASIS = 2166136261u;
const uint32_t FNV_PRIME = 16777619u;
+#elif defined(__arm__)
+ static_assert(sizeof(uintptr_t) == sizeof(uint32_t));
+ const uint32_t FNV_OFFSET_BASIS = 2166136261u;
+ const uint32_t FNV_PRIME = 16777619u;
#elif defined(__aarch64__)
static_assert(sizeof(uintptr_t) == sizeof(uint64_t));
const uint64_t FNV_OFFSET_BASIS = 14695981039346656037ull;
diff --git a/Kernel/include_std/new b/Kernel/include_std/new
index 7d90a8c9..ec7f2fdd 100644
--- a/Kernel/include_std/new
+++ b/Kernel/include_std/new
@@ -79,13 +79,13 @@ namespace std
[[nodiscard]] void *operator new(std::size_t count);
[[nodiscard]] void *operator new[](std::size_t count);
-// [[nodiscard]] void *operator new(std::size_t count, std::align_val_t al);
-// [[nodiscard]] void *operator new[](std::size_t count, std::align_val_t al);
+[[nodiscard]] void *operator new(std::size_t count, std::align_val_t al);
+[[nodiscard]] void *operator new[](std::size_t count, std::align_val_t al);
-// [[nodiscard]] void *operator new(std::size_t count, const std::nothrow_t &tag) noexcept;
-// [[nodiscard]] void *operator new[](std::size_t count, const std::nothrow_t &tag) noexcept;
-// [[nodiscard]] void *operator new(std::size_t count, std::align_val_t al, const std::nothrow_t &) noexcept;
-// [[nodiscard]] void *operator new[](std::size_t count, std::align_val_t al, const std::nothrow_t &) noexcept;
+[[nodiscard]] void *operator new(std::size_t count, const std::nothrow_t &tag) noexcept;
+[[nodiscard]] void *operator new[](std::size_t count, const std::nothrow_t &tag) noexcept;
+[[nodiscard]] void *operator new(std::size_t count, std::align_val_t al, const std::nothrow_t &) noexcept;
+[[nodiscard]] void *operator new[](std::size_t count, std::align_val_t al, const std::nothrow_t &) noexcept;
[[nodiscard]] void *operator new(std::size_t count, void *ptr) noexcept;
[[nodiscard]] void *operator new[](std::size_t count, void *ptr) noexcept;
diff --git a/Kernel/library/convert.cpp b/Kernel/library/convert.cpp
index 0810e8b6..c75fba0b 100644
--- a/Kernel/library/convert.cpp
+++ b/Kernel/library/convert.cpp
@@ -62,7 +62,7 @@ EXTERNC int strncmp(const char *s1, const char *s2, size_t n)
return 0;
}
-EXTERNC long unsigned strlen(const char s[])
+EXTERNC size_t strlen(const char s[])
{
if (Config.SIMD)
{
diff --git a/Kernel/library/kexcept/cxxabi.cpp b/Kernel/library/kexcept/cxxabi.cpp
index 0f9b17f7..40d544d5 100644
--- a/Kernel/library/kexcept/cxxabi.cpp
+++ b/Kernel/library/kexcept/cxxabi.cpp
@@ -192,7 +192,9 @@ extern "C" __noreturn void __cxa_throw(void *thrown_object,
Exception->terminateHandler = &terminate_header_stub;
Exception->unwindHeader.exception_cleanup = &exception_cleanup_stub;
INIT_EXCEPTION_CLASS(&Exception->unwindHeader.exception_class);
+#ifndef __arm__
Exception->adjustedPtr = thrown_object;
+#endif
_Unwind_RaiseException(&Exception->unwindHeader);
__cxa_begin_catch(&Exception->unwindHeader);
diff --git a/Kernel/library/md5.c b/Kernel/library/md5.c
index 45606595..466683de 100644
--- a/Kernel/library/md5.c
+++ b/Kernel/library/md5.c
@@ -134,7 +134,7 @@ void md5Finalize(MD5Context *ctx)
(uint32_t)(ctx->input[(j * 4)]);
}
input[14] = (uint32_t)(ctx->size * 8);
-#ifdef __i386__
+#if defined(__i386__) || defined(__arm__)
input[15] = (uint32_t)((uint64_t)(((uint64_t)ctx->size >> 32) | ((uint64_t)ctx->size << 32)) >> 32);
#else
input[15] = (uint32_t)((ctx->size * 8) >> 32);
diff --git a/Kernel/library/std/new.cpp b/Kernel/library/std/new.cpp
index 4859ed05..aa3f97e9 100644
--- a/Kernel/library/std/new.cpp
+++ b/Kernel/library/std/new.cpp
@@ -42,8 +42,37 @@ void *operator new[](std::size_t count)
throw std::bad_alloc{};
}
-// void *operator new(std::size_t count, std::align_val_t al)
-// void *operator new[](std::size_t count, std::align_val_t al)
+void *operator new(std::size_t count, std::align_val_t al)
+{
+ if (count == 0)
+ ++count;
+
+ std::size_t alignment = static_cast(al);
+ void *ptr = kmalloc(count + alignment - 1 + sizeof(void *));
+ if (!ptr)
+ throw std::bad_alloc{};
+
+ void *aligned_ptr = reinterpret_cast(
+ (reinterpret_cast(ptr) + sizeof(void *) + alignment - 1) & ~(alignment - 1));
+ reinterpret_cast(aligned_ptr)[-1] = ptr;
+ return aligned_ptr;
+}
+
+void *operator new[](std::size_t count, std::align_val_t al)
+{
+ if (count == 0)
+ ++count;
+
+ std::size_t alignment = static_cast(al);
+ void *ptr = kmalloc(count + alignment - 1 + sizeof(void *));
+ if (!ptr)
+ throw std::bad_alloc{};
+
+ void *aligned_ptr = reinterpret_cast(
+ (reinterpret_cast(ptr) + sizeof(void *) + alignment - 1) & ~(alignment - 1));
+ reinterpret_cast(aligned_ptr)[-1] = ptr;
+ return aligned_ptr;
+}
// void *operator new(std::size_t count, const std::nothrow_t &tag)
// void *operator new[](std::size_t count, const std::nothrow_t &tag)
@@ -62,8 +91,24 @@ void operator delete(void *ptr) noexcept { kfree(ptr); }
void operator delete[](void *ptr) noexcept { kfree(ptr); }
-// void operator delete(void *ptr, std::align_val_t al) noexcept
-// void operator delete[](void *ptr, std::align_val_t al) noexcept
+void operator delete(void *ptr, std::align_val_t al) noexcept
+{
+ if (!ptr)
+ return;
+
+ void *original_ptr = reinterpret_cast(ptr)[-1];
+ kfree(original_ptr);
+}
+
+void operator delete[](void *ptr, std::align_val_t al) noexcept
+{
+ if (!ptr)
+ return;
+
+ void *original_ptr = reinterpret_cast(ptr)[-1];
+ kfree(original_ptr);
+}
+
void operator delete(void *ptr, std::size_t) noexcept { kfree(ptr); }
void operator delete[](void *ptr, std::size_t sz) noexcept { kfree(ptr); }
diff --git a/Kernel/subsystem/linux/include/defs.hpp b/Kernel/subsystem/linux/include/defs.hpp
index a70e4914..4ef82edd 100644
--- a/Kernel/subsystem/linux/include/defs.hpp
+++ b/Kernel/subsystem/linux/include/defs.hpp
@@ -334,6 +334,24 @@ struct linux_kstat
__kernel_ulong_t st_ctime_nsec;
#undef __unused
__kernel_long_t __unused[3];
+#elif defined(__arm__)
+ __kernel_ulong_t st_dev;
+ __kernel_ulong_t st_ino;
+ __kernel_ulong_t st_nlink;
+ unsigned int st_mode;
+ unsigned int st_uid;
+ unsigned int st_gid;
+ unsigned int __pad0;
+ __kernel_ulong_t st_rdev;
+ __kernel_long_t st_size;
+ __kernel_long_t st_blksize;
+ __kernel_long_t st_blocks;
+ __kernel_ulong_t st_atime;
+ __kernel_ulong_t st_atime_nsec;
+ __kernel_ulong_t st_mtime;
+ __kernel_ulong_t st_mtime_nsec;
+ __kernel_ulong_t st_ctime;
+ __kernel_ulong_t st_ctime_nsec;
#else
#error "Unsupported architecture"
#endif
@@ -371,7 +389,7 @@ struct __old_kernel_stat
unsigned short st_uid;
unsigned short st_gid;
unsigned short st_rdev;
-#ifdef __i386__
+#if defined(__i386__) || defined(__arm__)
unsigned long st_size;
unsigned long st_atime;
unsigned long st_mtime;
diff --git a/Makefile b/Makefile
index 8508f6c0..97088452 100644
--- a/Makefile
+++ b/Makefile
@@ -66,6 +66,15 @@ QEMUFLAGS += -M q35 \
-device intel-hda \
-device ich9-intel-hda \
-acpitable file=tools/acpi/SSDT1.dat
+else ifeq ($(OSARCH), arm)
+QEMUFLAGS += -M raspi2b \
+ -monitor pty \
+ -cpu cortex-a15 \
+ -serial file:serial.log \
+ -serial file:COM2.dmp \
+ -serial file:COM3.dmp \
+ -serial stdio \
+ -kernel $(OSNAME).img
else ifeq ($(OSARCH), aarch64)
QEMUFLAGS += -M raspi3b \
-monitor pty \
@@ -160,7 +169,7 @@ ifeq ($(BOOTLOADER), grub)
cp tools/grub.cfg iso_tmp_data/boot/grub/
grub-mkrescue -o $(OSNAME).iso iso_tmp_data
endif
-ifeq ($(OSARCH), aarch64)
+ifneq ($(filter aarch64 arm,$(OSARCH)),)
$(__CONF_OBJCOPY) Kernel/fennix.elf -O binary $(OSNAME).img
endif
@@ -179,6 +188,10 @@ ifeq ($(OSARCH), i386)
QEMU_SMP = -smp $(shell nproc)
endif
+ifeq ($(OSARCH), arm)
+QEMU_SMP = -smp 4
+endif
+
ifeq ($(OSARCH), aarch64)
QEMU_SMP = -smp 4
endif
@@ -189,6 +202,9 @@ QEMUMEMORY = -m 4G
else ifeq ($(OSARCH), i386)
QEMUHWACCELERATION = -machine q35 -enable-kvm
QEMUMEMORY = -m 4G
+else ifeq ($(OSARCH), arm)
+QEMUHWACCELERATION =
+QEMUMEMORY = -m 1G
else ifeq ($(OSARCH), aarch64)
QEMUHWACCELERATION =
QEMUMEMORY = -m 1G
diff --git a/Userspace/.vscode/c_cpp_properties.json b/Userspace/.vscode/c_cpp_properties.json
index 4c598532..a6c44b52 100644
--- a/Userspace/.vscode/c_cpp_properties.json
+++ b/Userspace/.vscode/c_cpp_properties.json
@@ -82,6 +82,27 @@
"-nostdinc++"
]
},
+ {
+ "name": "Fennix Arm (Linux, GCC, debug)",
+ "includePath": [
+ "${workspaceFolder}/libc/include/**",
+ "${workspaceFolder}/libs/include/**"
+ ],
+ "defines": [
+ "__debug_vscode__",
+ "DEBUG=\"1\""
+ ],
+ "compilerPath": "${workspaceFolder}/../tools/cross/bin/arm-fennix-gcc",
+ "cStandard": "c17",
+ "cppStandard": "c++20",
+ "intelliSenseMode": "linux-gcc-arm",
+ "configurationProvider": "ms-vscode.makefile-tools",
+ "compilerArgs": [
+ "-ffreestanding",
+ "-nostdinc",
+ "-nostdinc++"
+ ]
+ },
{
"name": "Fennix Aarch64 (Linux, GCC, debug)",
"includePath": [
diff --git a/Userspace/libc/include/stdio.h b/Userspace/libc/include/stdio.h
index ae09002c..50ec245d 100644
--- a/Userspace/libc/include/stdio.h
+++ b/Userspace/libc/include/stdio.h
@@ -50,7 +50,7 @@ extern "C"
#define P_tmpdir "/tmp/"
typedef long fpos_t;
- typedef unsigned long size_t;
+ typedef __SIZE_TYPE__ size_t;
struct _IO_FILE
{
diff --git a/Userspace/libc/include/stdlib.h b/Userspace/libc/include/stdlib.h
index a543744e..5191a601 100644
--- a/Userspace/libc/include/stdlib.h
+++ b/Userspace/libc/include/stdlib.h
@@ -46,7 +46,7 @@ extern "C"
long rem;
} ldiv_t;
- typedef unsigned long size_t;
+ typedef __SIZE_TYPE__ size_t;
// typedef __WCHAR_TYPE__ wchar_t;
long a64l(const char *);
diff --git a/Userspace/libc/include/sys/types.h b/Userspace/libc/include/sys/types.h
index 61ebc2b3..0fa16811 100644
--- a/Userspace/libc/include/sys/types.h
+++ b/Userspace/libc/include/sys/types.h
@@ -108,7 +108,7 @@ extern "C"
char __data;
} pthread_barrier_t;
- typedef unsigned long size_t;
+ typedef __SIZE_TYPE__ size_t;
typedef long ssize_t;
typedef long suseconds_t;
diff --git a/Userspace/libc/interpreter/elf.h b/Userspace/libc/interpreter/elf.h
index 5b0319b6..b4e4c4b8 100644
--- a/Userspace/libc/interpreter/elf.h
+++ b/Userspace/libc/interpreter/elf.h
@@ -189,6 +189,15 @@ enum RelocationTypes
R_AARCH64_RELATIVE = 1027,
R_AARCH64_TLS_DTPMOD64 = 1028,
+ R_ARM_NONE = 0,
+ R_ARM_COPY = 1024,
+ R_ARM_GLOB_DAT = 1025,
+ R_ARM_JUMP_SLOT = 1026,
+ R_ARM_RELATIVE = 1027,
+ R_ARM_TLS_DTPMOD32 = 1028,
+ R_ARM_TLS_DTPOFF32 = 1029,
+ R_ARM_TLS_TPOFF32 = 1030,
+
#if defined(__x86_64__)
R_NONE = R_X86_64_NONE,
R_COPY = R_X86_64_COPY,
@@ -216,6 +225,15 @@ enum RelocationTypes
R_DTPMOD64 = R_AARCH64_TLS_DTPMOD64,
R_DTPOFF64 = R_AARCH64_NONE,
R_TPOFF64 = R_AARCH64_NONE,
+#elif defined(__arm__)
+ R_NONE = R_ARM_NONE,
+ R_COPY = R_ARM_COPY,
+ R_GLOB_DAT = R_ARM_GLOB_DAT,
+ R_JMP_SLOT = R_ARM_JUMP_SLOT,
+ R_RELATIVE = R_ARM_RELATIVE,
+ R_DTPMOD64 = R_ARM_TLS_DTPMOD32,
+ R_DTPOFF64 = R_ARM_TLS_DTPOFF32,
+ R_TPOFF64 = R_ARM_TLS_TPOFF32,
#endif
};
@@ -1002,7 +1020,7 @@ typedef Elf64_Rela Elf_Rela;
#define ELF_ST_BIND(info) ELF64_ST_BIND(info)
#define ELF_ST_TYPE(info) ELF64_ST_TYPE(info)
#define ELF_ST_INFO(bind, type) ELF64_ST_INFO(bind, type)
-#elif defined(__i386__)
+#elif defined(__i386__) || defined(__arm__)
typedef Elf32_Addr Elf_Addr;
typedef Elf32_Half Elf_Half;
typedef Elf32_Off Elf_Off;
diff --git a/Userspace/libc/interpreter/start.c b/Userspace/libc/interpreter/start.c
index 1bfc3c02..0a99e591 100644
--- a/Userspace/libc/interpreter/start.c
+++ b/Userspace/libc/interpreter/start.c
@@ -128,6 +128,8 @@ __attribute__((naked, used, no_stack_protector)) void _start()
"call _exit\n"); /* Call _exit */
#elif defined(__i386__)
#warning "i386 _start not implemented"
+#elif defined(__arm__)
+#warning "arm _start not implemented"
#elif defined(__aarch64__)
#warning "aarch64 _start not implemented"
#else
diff --git a/Userspace/libc/runtime/Scrt1.c b/Userspace/libc/runtime/Scrt1.c
index 2e962f64..99cf28df 100644
--- a/Userspace/libc/runtime/Scrt1.c
+++ b/Userspace/libc/runtime/Scrt1.c
@@ -68,6 +68,8 @@ __attribute__((naked, used, no_stack_protector, section(".text"))) void _start()
"call _exit\n");
#elif defined(__i386__)
#warning "i386 _start not implemented"
+#elif defined(__arm__)
+#warning "arm _start not implemented"
#elif defined(__aarch64__)
#warning "aarch64 _start not implemented"
#else
diff --git a/Userspace/libc/runtime/crt1.c b/Userspace/libc/runtime/crt1.c
index 2e962f64..99cf28df 100644
--- a/Userspace/libc/runtime/crt1.c
+++ b/Userspace/libc/runtime/crt1.c
@@ -68,6 +68,8 @@ __attribute__((naked, used, no_stack_protector, section(".text"))) void _start()
"call _exit\n");
#elif defined(__i386__)
#warning "i386 _start not implemented"
+#elif defined(__arm__)
+#warning "arm _start not implemented"
#elif defined(__aarch64__)
#warning "aarch64 _start not implemented"
#else
diff --git a/Userspace/libc/src/softfloat.c b/Userspace/libc/src/softfloat.c
index a321b308..b36d7902 100644
--- a/Userspace/libc/src/softfloat.c
+++ b/Userspace/libc/src/softfloat.c
@@ -19,3 +19,176 @@ double __trunctfdf2(long double a)
{
return (double)a;
}
+
+int __aeabi_dcmple(long double a, long double b)
+{
+ return a <= b;
+}
+
+long long __aeabi_d2lz(double a)
+{
+ return (long long)a;
+}
+
+int __aeabi_dcmplt(long double a, long double b)
+{
+ return a < b;
+}
+
+typedef union
+{
+ double d;
+ struct
+ {
+ __UINT64_TYPE__ mantissa : 52;
+ __UINT64_TYPE__ exponent : 11;
+ __UINT64_TYPE__ sign : 1;
+ } parts;
+} aeabi_double_t;
+
+aeabi_double_t __aeabi_ddiv(aeabi_double_t a, aeabi_double_t b)
+{
+ aeabi_double_t result;
+ result.d = a.d / b.d;
+ return result;
+}
+
+aeabi_double_t __aeabi_dmul(aeabi_double_t a, aeabi_double_t b)
+{
+ aeabi_double_t result;
+ result.d = a.d * b.d;
+ return result;
+}
+
+aeabi_double_t __aeabi_dadd(aeabi_double_t a, aeabi_double_t b)
+{
+ aeabi_double_t result;
+ result.d = a.d + b.d;
+ return result;
+}
+
+int __aeabi_dcmpgt(aeabi_double_t a, aeabi_double_t b)
+{
+ return a.d > b.d;
+}
+
+int __aeabi_dcmpge(aeabi_double_t a, aeabi_double_t b)
+{
+ return a.d >= b.d;
+}
+
+aeabi_double_t __aeabi_dsub(aeabi_double_t a, aeabi_double_t b)
+{
+ aeabi_double_t result;
+ result.d = a.d - b.d;
+ return result;
+}
+
+aeabi_double_t __aeabi_i2d(int a)
+{
+ aeabi_double_t result;
+ result.d = (double)a;
+ return result;
+}
+
+aeabi_double_t __aeabi_l2d(long long a)
+{
+ aeabi_double_t result;
+ result.d = (double)a;
+ return result;
+}
+
+int __aeabi_dcmpeq(aeabi_double_t a, aeabi_double_t b)
+{
+ return a.d == b.d;
+}
+
+int __aeabi_d2iz(aeabi_double_t a)
+{
+ return (int)a.d;
+}
+
+struct ldivmod_result
+{
+ long quot;
+ long rem;
+};
+
+struct ldivmod_result __aeabi_ldivmod(long numerator, long denominator)
+{
+ struct ldivmod_result result;
+ result.quot = numerator / denominator;
+ result.rem = numerator % denominator;
+ return result;
+}
+
+signed __aeabi_idiv(signed numerator, signed denominator)
+{
+ return numerator / denominator;
+}
+
+signed __aeabi_idivmod(signed numerator, signed denominator)
+{
+ signed quotient = numerator / denominator;
+ signed remainder = numerator % denominator;
+ return (quotient << 16) | remainder;
+}
+
+unsigned __aeabi_uidiv(unsigned numerator, unsigned denominator)
+{
+ return numerator / denominator;
+}
+
+unsigned __aeabi_uidivmod(unsigned numerator, unsigned denominator)
+{
+ unsigned quotient = numerator / denominator;
+ unsigned remainder = numerator % denominator;
+ return (quotient << 16) | remainder;
+}
+
+__UINT64_TYPE__ __udivmoddi4(__UINT64_TYPE__ numerator, __UINT64_TYPE__ denominator, __UINT64_TYPE__ *remainder)
+{
+ __UINT64_TYPE__ quotient = 0;
+ __UINT64_TYPE__ bit = 1;
+
+ if (denominator == 0)
+ {
+ *remainder = numerator;
+ return ~0ULL;
+ }
+
+ while (denominator < numerator && (denominator & (1ULL << 63)) == 0)
+ {
+ denominator <<= 1;
+ bit <<= 1;
+ }
+
+ while (bit)
+ {
+ if (numerator >= denominator)
+ {
+ numerator -= denominator;
+ quotient |= bit;
+ }
+ denominator >>= 1;
+ bit >>= 1;
+ }
+
+ if (remainder)
+ *remainder = numerator;
+
+ return quotient;
+}
+
+struct udivmod_result
+{
+ __UINT64_TYPE__ quot;
+ __UINT64_TYPE__ rem;
+};
+
+struct udivmod_result __aeabi_uldivmod(__UINT64_TYPE__ numerator, __UINT64_TYPE__ denominator)
+{
+ struct udivmod_result result;
+ result.quot = __udivmoddi4(numerator, denominator, &result.rem);
+ return result;
+}