diff --git a/.clang-format b/.clang-format
index 2896996..0308bab 100644
--- a/.clang-format
+++ b/.clang-format
@@ -1,4 +1,4 @@
-ColumnLimit: 100
+Language: Cpp
IndentWidth: 4
UseTab: ForIndentation
TabWidth: 4
@@ -6,25 +6,24 @@ SpacesBeforeTrailingComments: 1
NamespaceIndentation: None
AlignConsecutiveAssignments: false
AllowAllParametersOfDeclarationOnNextLine: true
-AllowShortBlocksOnASingleLine: true
+AllowShortBlocksOnASingleLine: Empty
AllowShortFunctionsOnASingleLine: Inline
AllowShortCaseLabelsOnASingleLine: true
-AllowShortIfStatementsOnASingleLine: true
+AllowShortIfStatementsOnASingleLine: WithoutElse
AllowShortLoopsOnASingleLine: true
BreakBeforeBinaryOperators: None
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
-DerivePointerAlignment: true
IndentCaseLabels: true
KeepEmptyLinesAtTheStartOfBlocks: false
PointerAlignment: Right
ContinuationIndentWidth: 4
-SpacesInParentheses: false
+SpacesInParens: Never
SpacesInSquareBrackets: false
SpacesInAngles: false
-SpaceInEmptyParentheses: true
IndentPPDirectives: None
IncludeBlocks: Preserve
Cpp11BracedListStyle: false
-Standard: Cpp11
\ No newline at end of file
+Standard: Cpp11
+ReflowComments: false
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index afb7f5e..7447d04 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,6 @@
+# Code editor files
+.vscode
+
# Prerequisites
*.d
diff --git a/Makefile b/Makefile
index 2b74d95..0a7b820 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@ SRCS := $(shell find kernel/ -name "*.c" -o -name "*.s")
OBJS := $(patsubst %.c, %.o, $(patsubst %.s, %.o, $(SRCS)))
$(shell mkdir -p $(dir $(OBJS)))
-CFLAGS = -m64 -Wall -Werror -std=gnu2x -Ikernel/include -ffreestanding -O0 -fno-stack-protector
+CFLAGS = -m64 -Wall -Werror -std=gnu2x -Ikernel/include -Ikernel/arch/include -ffreestanding -O0 -fno-stack-protector -Wno-format
ASFLAGS = -64
.PHONY: all run test clean format
@@ -23,7 +23,7 @@ kernel/kernel.elf: $(OBJS)
%.o: %.c
gcc $(CFLAGS) -c -o $@ $<
-%.o: %.s
+%.o: %.s %.S
as $(ASFLAGS) -o $@ $<
serial.log: cis-os.iso
diff --git a/kernel/arch/amd64/cpu/control.c b/kernel/arch/amd64/cpu/control.c
new file mode 100644
index 0000000..f0f38e2
--- /dev/null
+++ b/kernel/arch/amd64/cpu/control.c
@@ -0,0 +1,68 @@
+// NOTE: This file contains code derived from or inspired by:
+// AstriX ("The AstriX Operating System") at https://codeberg.org/AstriX/AstriX.
+// Copyright (c) 2023-2025 NotYourFox, sigsegv
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+// This program 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.
+
+// This program 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 this program. If not, see .
+
+#include "arch/cpu/control.h"
+#include "kreflock.h"
+#include "kstdlib.h"
+
+static inline void __cpu_enable_interrupt() {
+ asm volatile("sti");
+}
+
+static inline void __cpu_disable_interrupt() {
+ asm volatile("cli");
+}
+
+static reflock_t lock =
+ NEW_REFLOCK(__cpu_disable_interrupt, __cpu_enable_interrupt, false, true);
+
+bool cpu_interrupt_lock_acquired() {
+ if (unlikely(!reflock_validate(&lock))) {
+ reflock_make(&lock);
+ }
+
+ return reflock_is_locked(&lock);
+}
+
+void cpu_interrupt_lock_acquire() {
+ if (unlikely(!reflock_validate(&lock))) {
+ reflock_make(&lock);
+ }
+
+ reflock_acquire(&lock);
+}
+
+void cpu_interrupt_lock_release() {
+ if (unlikely(!reflock_validate(&lock))) {
+ reflock_make(&lock);
+ }
+
+ reflock_release(&lock);
+}
+
+void cpu_interrupt_lock_force_release() {
+ if (unlikely(!reflock_validate(&lock))) {
+ reflock_make(&lock);
+ }
+
+ reflock_force_unlock(&lock);
+}
+
+void cpu_halt() {
+ asm("hlt");
+}
\ No newline at end of file
diff --git a/kernel/arch/amd64/cpu/regs.S b/kernel/arch/amd64/cpu/regs.S
new file mode 100644
index 0000000..3bae2cc
--- /dev/null
+++ b/kernel/arch/amd64/cpu/regs.S
@@ -0,0 +1,24 @@
+#define __ASSEMBLY__
+
+#include "arch/cpu/tables.h"
+
+.code64
+
+.global __asm_update_regs
+
+get_flags:
+ pushfd
+ movq (%rsp), %rax
+ popfd
+
+ ret
+
+get_rip:
+ movq (%rsp), %rax
+ ret
+
+// TODO because I'm not familiar with x86-64 conventions
+__asm_update_regs:
+ ret
+
+#undef __ASSEMBLY__
\ No newline at end of file
diff --git a/kernel/arch/amd64/cpu/regs.c b/kernel/arch/amd64/cpu/regs.c
new file mode 100644
index 0000000..0b8742f
--- /dev/null
+++ b/kernel/arch/amd64/cpu/regs.c
@@ -0,0 +1,11 @@
+#include "amd64/cpu/regs.h"
+#include "arch/cpu/strace.h"
+#include "kstring.h"
+
+extern void __asm_update_regs(asm_regs_t *regs);
+
+// work in progress
+void update_asm_regs(asm_regs_t *state) {
+ memset(state, 0x00, sizeof(asm_regs_t));
+ return;
+}
\ No newline at end of file
diff --git a/kernel/arch/amd64/cpu/state.c b/kernel/arch/amd64/cpu/state.c
new file mode 100644
index 0000000..2e50fc0
--- /dev/null
+++ b/kernel/arch/amd64/cpu/state.c
@@ -0,0 +1,48 @@
+#include "amd64/cpu/regs.h"
+#include "khal.h"
+
+void cpu_state_print() {
+ asm_regs_t current_state;
+
+ serial_printf(
+ "The following register dump is a stub and a work-in-progress.\n");
+
+ update_asm_regs(¤t_state);
+ serial_printf("Registers:\n");
+ serial_printf("\tRAX: 0x%x RBX: 0x%x RCX: 0x%x RDX: 0x%x\n",
+ current_state.eax, current_state.ebx, current_state.ecx,
+ current_state.edx);
+ serial_printf("\tRBP: 0x%x RSP: 0x%x RSI: 0x%x RDI: 0x%x\n",
+ current_state.ebp, current_state.esp, current_state.esi,
+ current_state.edi);
+ serial_printf("\tCS: 0x%x DS: 0x%x ES: 0x%x FS: 0x%x\n",
+ current_state.cs, current_state.ds, current_state.es,
+ current_state.fs);
+ serial_printf("\tGS: 0x%x SS: 0x%x\n", current_state.gs,
+ current_state.ss);
+ serial_printf("\tCR0: 0x%x CR2: 0x%x CR3: 0x%x CR4: 0x%x\n",
+ current_state.cr0, current_state.cr2, current_state.cr3,
+ current_state.cr4);
+
+ serial_printf("\tDR0: 0x%x DR1: 0x%x DR2: 0x%x DR3: 0x%x\n",
+ current_state.dr0, current_state.dr1, current_state.dr2,
+ current_state.dr3);
+ serial_printf("\tDR6: 0x%x DR7: 0x%x\n", current_state.dr6,
+ current_state.dr7);
+ serial_printf("\tGDTR: base=0x%x, limit=0x%x\n\tLDTR: base=0x%x, "
+ "limit=0x%x\n\tIDTR: base=0x%x, limit=0x%x\n",
+ current_state.gdtr.base, current_state.gdtr.limit,
+ current_state.ldtr.base, current_state.ldtr.limit,
+ current_state.idtr.base, current_state.idtr.limit);
+
+ // TODO: symbol names
+ serial_printf("\tRIP: 0x%x", current_state.rip);
+
+ // serial_printf("\tCode: ");
+ // for (int i = 0; i < 16; i++) {
+ // serial_printf("%x ", *(uint8_t *)(current_state.rip + i));
+ // }
+ // serial_printf("\n");
+
+ serial_printf("\n");
+}
diff --git a/kernel/arch/amd64/cpu/strace.c b/kernel/arch/amd64/cpu/strace.c
new file mode 100644
index 0000000..ee419d2
--- /dev/null
+++ b/kernel/arch/amd64/cpu/strace.c
@@ -0,0 +1,19 @@
+#include "arch/cpu/strace.h"
+#include
+
+struct stackframe *strace_get() {
+ struct stackframe *res;
+ asm("movq %%rbp, %0" : "=r"(res));
+ return res;
+}
+
+uint64_t strace_get_framep(int sf_offset) {
+ struct stackframe *stack = strace_get();
+
+ // skip get_x86_stack_trace(), 0 points to this function
+ for (int i = 0; stack && i < sf_offset + 1; i++) {
+ stack = stack->sp;
+ }
+
+ return stack->pc;
+}
\ No newline at end of file
diff --git a/kernel/arch/amd64/idt.c b/kernel/arch/amd64/idt.c
index 8748efe..ecef2de 100644
--- a/kernel/arch/amd64/idt.c
+++ b/kernel/arch/amd64/idt.c
@@ -1,10 +1,11 @@
-#include
+#include "kstdint.h"
// From https://wiki.osdev.org/Interrupt_Descriptor_Table#Structure_on_x86-64
struct idt_64 {
- uint16_t offset_1; // offset bits 0..15
- uint16_t selector; // a code segment selector in GDT or LDT
- uint8_t ist; // bits 0..2 holds Interrupt Stack Table offset, rest of bits zero.
+ uint16_t offset_1; // offset bits 0..15
+ uint16_t selector; // a code segment selector in GDT or LDT
+ uint8_t
+ ist; // bits 0..2 holds Interrupt Stack Table offset, rest of bits zero.
uint8_t type_attributes; // gate type, dpl, and p fields
uint16_t offset_2; // offset bits 16..31
uint32_t offset_3; // offset bits 32..63
diff --git a/kernel/arch/amd64/paging.c b/kernel/arch/amd64/paging.c
index 2ca544d..f36bb88 100644
--- a/kernel/arch/amd64/paging.c
+++ b/kernel/arch/amd64/paging.c
@@ -1,7 +1,7 @@
-#include
+#include "kstdint.h"
uint64_t paging_main[3][512] __attribute__((aligned(4096))) = { 0 };
-int paging_init( ) {
+int paging_init() {
return -1;
}
\ No newline at end of file
diff --git a/kernel/arch/amd64/serial.c b/kernel/arch/amd64/serial.c
index d22c49a..6e9a6cc 100644
--- a/kernel/arch/amd64/serial.c
+++ b/kernel/arch/amd64/serial.c
@@ -1,14 +1,13 @@
-#include
-#include
+#include "kasm.h"
+#include "kstdint.h"
void serial_write_byte(uint8_t byte) {
// Wait until the transmit holding register is empty
- while ((inb(0x3f8 + 5) & 0x20) == 0)
- ;
+ while ((inb(0x3f8 + 5) & 0x20) == 0);
outb(0x3f8, byte);
}
-int serial_init( ) {
+int serial_init() {
// Disable all interrupts
outb(0x3f8 + 1, 0x00);
@@ -19,7 +18,8 @@ int serial_init( ) {
outb(0x3f8, 0x0C); // Low byte of divisor
outb(0x3f8 + 1, 0x00); // High byte of divisor (0 for divisor < 256)
- // Disable DLAB and set communication parameters: 8n1 (8 bits, no parity, 1 stop bit)
+ // Disable DLAB and set communication parameters: 8n1 (8 bits, no parity, 1
+ // stop bit)
outb(0x3f8 + 3, 0x03);
// Enable FIFOs
diff --git a/kernel/arch/include/amd64/cpu/regs.h b/kernel/arch/include/amd64/cpu/regs.h
new file mode 100644
index 0000000..0166359
--- /dev/null
+++ b/kernel/arch/include/amd64/cpu/regs.h
@@ -0,0 +1,97 @@
+#ifndef __ARCH_CPU_REGS
+#define __ARCH_CPU_REGS
+
+#include "amd64/cpu/tables.h"
+
+#include
+
+typedef struct {
+ uint32_t eflags;
+
+ union {
+ struct {
+ uint8_t ah;
+ uint8_t al;
+ };
+ uint16_t ax;
+ uint32_t eax;
+ uint64_t rax;
+ };
+ union {
+ struct {
+ uint8_t bh;
+ uint8_t bl;
+ };
+ uint16_t bx;
+ uint32_t ebx;
+ uint64_t rbx;
+ };
+ union {
+ struct {
+ uint8_t ch;
+ uint8_t cl;
+ };
+ uint16_t cx;
+ uint32_t ecx;
+ uint64_t rcx;
+ };
+ union {
+ struct {
+ uint8_t dh;
+ uint8_t dl;
+ };
+ uint16_t dx;
+ uint32_t edx;
+ uint64_t rdx;
+ };
+
+ union {
+ uint16_t bp;
+ uint32_t ebp;
+ uint64_t rbp;
+ };
+ union {
+ uint16_t sp;
+ uint32_t esp;
+ uint64_t rsp;
+ };
+ union {
+ uint16_t si;
+ uint32_t esi;
+ uint64_t rsi;
+ };
+ union {
+ uint16_t di;
+ uint32_t edi;
+ uint64_t rdi;
+ };
+
+ uint64_t rip;
+
+ uint16_t cs;
+ uint16_t ds;
+ uint16_t es;
+ uint16_t fs;
+ uint16_t gs;
+ uint16_t ss;
+
+ uint32_t cr0;
+ uint32_t cr2;
+ uint32_t cr3;
+ uint32_t cr4;
+
+ uint32_t dr0;
+ uint32_t dr1;
+ uint32_t dr2;
+ uint32_t dr3;
+ uint32_t dr6;
+ uint32_t dr7;
+
+ struct desc_table gdtr;
+ struct desc_table ldtr;
+ struct desc_table idtr;
+} __attribute__((packed)) asm_regs_t;
+
+extern void update_asm_regs(asm_regs_t *state);
+
+#endif
diff --git a/kernel/arch/include/amd64/cpu/tables.h b/kernel/arch/include/amd64/cpu/tables.h
new file mode 100644
index 0000000..b9a0537
--- /dev/null
+++ b/kernel/arch/include/amd64/cpu/tables.h
@@ -0,0 +1,15 @@
+#ifndef __ARCH_CPU_TABLES
+#define __ARCH_CPU_TABLES
+
+#define DESC_TABLE_SIZE 6
+
+#ifndef __ASSEMBLY__
+#include
+
+struct desc_table {
+ uint16_t limit;
+ uint32_t base;
+} __attribute__((packed));
+#endif
+
+#endif
\ No newline at end of file
diff --git a/kernel/cpio.c b/kernel/cpio.c
index f967fe6..c270444 100644
--- a/kernel/cpio.c
+++ b/kernel/cpio.c
@@ -1,4 +1,4 @@
-#include
+#include "kstdint.h"
// We need memory manager and kernel lib first
#if 0
diff --git a/kernel/include/3rd/multiboot2.h b/kernel/include/3rd/multiboot2.h
index 9ea887b..ce4901f 100644
--- a/kernel/include/3rd/multiboot2.h
+++ b/kernel/include/3rd/multiboot2.h
@@ -14,70 +14,71 @@
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY
- * DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
- * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
*/
#ifndef MULTIBOOT_HEADER
#define MULTIBOOT_HEADER 1
/* How many bytes from the start of the file we search for the header. */
-#define MULTIBOOT_SEARCH 32768
-#define MULTIBOOT_HEADER_ALIGN 8
+#define MULTIBOOT_SEARCH 32768
+#define MULTIBOOT_HEADER_ALIGN 8
/* The magic field should contain this. */
-#define MULTIBOOT2_HEADER_MAGIC 0xe85250d6
+#define MULTIBOOT2_HEADER_MAGIC 0xe85250d6
/* This should be in %eax. */
-#define MULTIBOOT2_BOOTLOADER_MAGIC 0x36d76289
+#define MULTIBOOT2_BOOTLOADER_MAGIC 0x36d76289
/* Alignment of multiboot modules. */
-#define MULTIBOOT_MOD_ALIGN 0x00001000
+#define MULTIBOOT_MOD_ALIGN 0x00001000
/* Alignment of the multiboot info structure. */
-#define MULTIBOOT_INFO_ALIGN 0x00000008
+#define MULTIBOOT_INFO_ALIGN 0x00000008
/* Flags set in the ’flags’ member of the multiboot header. */
-#define MULTIBOOT_TAG_ALIGN 8
-#define MULTIBOOT_TAG_TYPE_END 0
-#define MULTIBOOT_TAG_TYPE_CMDLINE 1
-#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME 2
-#define MULTIBOOT_TAG_TYPE_MODULE 3
-#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO 4
-#define MULTIBOOT_TAG_TYPE_BOOTDEV 5
-#define MULTIBOOT_TAG_TYPE_MMAP 6
-#define MULTIBOOT_TAG_TYPE_VBE 7
-#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8
-#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS 9
-#define MULTIBOOT_TAG_TYPE_APM 10
-#define MULTIBOOT_TAG_TYPE_EFI32 11
-#define MULTIBOOT_TAG_TYPE_EFI64 12
-#define MULTIBOOT_TAG_TYPE_SMBIOS 13
-#define MULTIBOOT_TAG_TYPE_ACPI_OLD 14
-#define MULTIBOOT_TAG_TYPE_ACPI_NEW 15
-#define MULTIBOOT_TAG_TYPE_NETWORK 16
-#define MULTIBOOT_TAG_TYPE_EFI_MMAP 17
-#define MULTIBOOT_TAG_TYPE_EFI_BS 18
-#define MULTIBOOT_TAG_TYPE_EFI32_IH 19
-#define MULTIBOOT_TAG_TYPE_EFI64_IH 20
-#define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR 21
-
-#define MULTIBOOT_HEADER_TAG_END 0
-#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1
-#define MULTIBOOT_HEADER_TAG_ADDRESS 2
-#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS 3
-#define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS 4
-#define MULTIBOOT_HEADER_TAG_FRAMEBUFFER 5
-#define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6
-#define MULTIBOOT_HEADER_TAG_EFI_BS 7
-#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32 8
-#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 9
-#define MULTIBOOT_HEADER_TAG_RELOCATABLE 10
-
-#define MULTIBOOT_ARCHITECTURE_I386 0
-#define MULTIBOOT_ARCHITECTURE_MIPS32 4
+#define MULTIBOOT_TAG_ALIGN 8
+#define MULTIBOOT_TAG_TYPE_END 0
+#define MULTIBOOT_TAG_TYPE_CMDLINE 1
+#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME 2
+#define MULTIBOOT_TAG_TYPE_MODULE 3
+#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO 4
+#define MULTIBOOT_TAG_TYPE_BOOTDEV 5
+#define MULTIBOOT_TAG_TYPE_MMAP 6
+#define MULTIBOOT_TAG_TYPE_VBE 7
+#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8
+#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS 9
+#define MULTIBOOT_TAG_TYPE_APM 10
+#define MULTIBOOT_TAG_TYPE_EFI32 11
+#define MULTIBOOT_TAG_TYPE_EFI64 12
+#define MULTIBOOT_TAG_TYPE_SMBIOS 13
+#define MULTIBOOT_TAG_TYPE_ACPI_OLD 14
+#define MULTIBOOT_TAG_TYPE_ACPI_NEW 15
+#define MULTIBOOT_TAG_TYPE_NETWORK 16
+#define MULTIBOOT_TAG_TYPE_EFI_MMAP 17
+#define MULTIBOOT_TAG_TYPE_EFI_BS 18
+#define MULTIBOOT_TAG_TYPE_EFI32_IH 19
+#define MULTIBOOT_TAG_TYPE_EFI64_IH 20
+#define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR 21
+
+#define MULTIBOOT_HEADER_TAG_END 0
+#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1
+#define MULTIBOOT_HEADER_TAG_ADDRESS 2
+#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS 3
+#define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS 4
+#define MULTIBOOT_HEADER_TAG_FRAMEBUFFER 5
+#define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6
+#define MULTIBOOT_HEADER_TAG_EFI_BS 7
+#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32 8
+#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 9
+#define MULTIBOOT_HEADER_TAG_RELOCATABLE 10
+
+#define MULTIBOOT_ARCHITECTURE_I386 0
+#define MULTIBOOT_ARCHITECTURE_MIPS32 4
#define MULTIBOOT_HEADER_TAG_OPTIONAL 1
#define MULTIBOOT_LOAD_PREFERENCE_NONE 0
@@ -89,327 +90,290 @@
#ifndef ASM_FILE
-typedef unsigned char multiboot_uint8_t;
-typedef unsigned short multiboot_uint16_t;
-typedef unsigned int multiboot_uint32_t;
-typedef unsigned long long multiboot_uint64_t;
-
-struct multiboot_header
-{
- /* Must be MULTIBOOT_MAGIC - see above. */
- multiboot_uint32_t magic;
-
- /* ISA */
- multiboot_uint32_t architecture;
-
- /* Total header length. */
- multiboot_uint32_t header_length;
-
- /* The above fields plus this one must equal 0 mod 2^32. */
- multiboot_uint32_t checksum;
-};
-
-struct multiboot_header_tag
-{
- multiboot_uint16_t type;
- multiboot_uint16_t flags;
- multiboot_uint32_t size;
-};
-
-struct multiboot_header_tag_information_request
-{
- multiboot_uint16_t type;
- multiboot_uint16_t flags;
- multiboot_uint32_t size;
- multiboot_uint32_t requests[0];
-};
-
-struct multiboot_header_tag_address
-{
- multiboot_uint16_t type;
- multiboot_uint16_t flags;
- multiboot_uint32_t size;
- multiboot_uint32_t header_addr;
- multiboot_uint32_t load_addr;
- multiboot_uint32_t load_end_addr;
- multiboot_uint32_t bss_end_addr;
-};
-
-struct multiboot_header_tag_entry_address
-{
- multiboot_uint16_t type;
- multiboot_uint16_t flags;
- multiboot_uint32_t size;
- multiboot_uint32_t entry_addr;
-};
-
-struct multiboot_header_tag_console_flags
-{
- multiboot_uint16_t type;
- multiboot_uint16_t flags;
- multiboot_uint32_t size;
- multiboot_uint32_t console_flags;
-};
-
-struct multiboot_header_tag_framebuffer
-{
- multiboot_uint16_t type;
- multiboot_uint16_t flags;
- multiboot_uint32_t size;
- multiboot_uint32_t width;
- multiboot_uint32_t height;
- multiboot_uint32_t depth;
-};
-
-struct multiboot_header_tag_module_align
-{
- multiboot_uint16_t type;
- multiboot_uint16_t flags;
- multiboot_uint32_t size;
-};
-
-struct multiboot_header_tag_relocatable
-{
- multiboot_uint16_t type;
- multiboot_uint16_t flags;
- multiboot_uint32_t size;
- multiboot_uint32_t min_addr;
- multiboot_uint32_t max_addr;
- multiboot_uint32_t align;
- multiboot_uint32_t preference;
-};
-
-struct multiboot_color
-{
- multiboot_uint8_t red;
- multiboot_uint8_t green;
- multiboot_uint8_t blue;
-};
-
-struct multiboot_mmap_entry
-{
- multiboot_uint64_t addr;
- multiboot_uint64_t len;
-#define MULTIBOOT_MEMORY_AVAILABLE 1
-#define MULTIBOOT_MEMORY_RESERVED 2
-#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3
-#define MULTIBOOT_MEMORY_NVS 4
-#define MULTIBOOT_MEMORY_BADRAM 5
- multiboot_uint32_t type;
- multiboot_uint32_t zero;
+typedef unsigned char multiboot_uint8_t;
+typedef unsigned short multiboot_uint16_t;
+typedef unsigned int multiboot_uint32_t;
+typedef unsigned long long multiboot_uint64_t;
+
+struct multiboot_header {
+ /* Must be MULTIBOOT_MAGIC - see above. */
+ multiboot_uint32_t magic;
+
+ /* ISA */
+ multiboot_uint32_t architecture;
+
+ /* Total header length. */
+ multiboot_uint32_t header_length;
+
+ /* The above fields plus this one must equal 0 mod 2^32. */
+ multiboot_uint32_t checksum;
+};
+
+struct multiboot_header_tag {
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+};
+
+struct multiboot_header_tag_information_request {
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+ multiboot_uint32_t requests[0];
+};
+
+struct multiboot_header_tag_address {
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+ multiboot_uint32_t header_addr;
+ multiboot_uint32_t load_addr;
+ multiboot_uint32_t load_end_addr;
+ multiboot_uint32_t bss_end_addr;
+};
+
+struct multiboot_header_tag_entry_address {
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+ multiboot_uint32_t entry_addr;
+};
+
+struct multiboot_header_tag_console_flags {
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+ multiboot_uint32_t console_flags;
+};
+
+struct multiboot_header_tag_framebuffer {
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+ multiboot_uint32_t width;
+ multiboot_uint32_t height;
+ multiboot_uint32_t depth;
+};
+
+struct multiboot_header_tag_module_align {
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+};
+
+struct multiboot_header_tag_relocatable {
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+ multiboot_uint32_t min_addr;
+ multiboot_uint32_t max_addr;
+ multiboot_uint32_t align;
+ multiboot_uint32_t preference;
+};
+
+struct multiboot_color {
+ multiboot_uint8_t red;
+ multiboot_uint8_t green;
+ multiboot_uint8_t blue;
+};
+
+struct multiboot_mmap_entry {
+ multiboot_uint64_t addr;
+ multiboot_uint64_t len;
+#define MULTIBOOT_MEMORY_AVAILABLE 1
+#define MULTIBOOT_MEMORY_RESERVED 2
+#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3
+#define MULTIBOOT_MEMORY_NVS 4
+#define MULTIBOOT_MEMORY_BADRAM 5
+ multiboot_uint32_t type;
+ multiboot_uint32_t zero;
};
typedef struct multiboot_mmap_entry multiboot_memory_map_t;
-struct multiboot_tag
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
+struct multiboot_tag {
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
};
-struct multiboot_tag_string
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
- char string[0];
+struct multiboot_tag_string {
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ char string[0];
};
-struct multiboot_tag_module
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
- multiboot_uint32_t mod_start;
- multiboot_uint32_t mod_end;
- char cmdline[0];
+struct multiboot_tag_module {
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t mod_start;
+ multiboot_uint32_t mod_end;
+ char cmdline[0];
};
-struct multiboot_tag_basic_meminfo
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
- multiboot_uint32_t mem_lower;
- multiboot_uint32_t mem_upper;
+struct multiboot_tag_basic_meminfo {
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t mem_lower;
+ multiboot_uint32_t mem_upper;
};
-struct multiboot_tag_bootdev
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
- multiboot_uint32_t biosdev;
- multiboot_uint32_t slice;
- multiboot_uint32_t part;
+struct multiboot_tag_bootdev {
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t biosdev;
+ multiboot_uint32_t slice;
+ multiboot_uint32_t part;
};
-struct multiboot_tag_mmap
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
- multiboot_uint32_t entry_size;
- multiboot_uint32_t entry_version;
- struct multiboot_mmap_entry entries[0];
+struct multiboot_tag_mmap {
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t entry_size;
+ multiboot_uint32_t entry_version;
+ struct multiboot_mmap_entry entries[0];
};
-struct multiboot_vbe_info_block
-{
- multiboot_uint8_t external_specification[512];
+struct multiboot_vbe_info_block {
+ multiboot_uint8_t external_specification[512];
};
-struct multiboot_vbe_mode_info_block
-{
- multiboot_uint8_t external_specification[256];
+struct multiboot_vbe_mode_info_block {
+ multiboot_uint8_t external_specification[256];
};
-struct multiboot_tag_vbe
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
+struct multiboot_tag_vbe {
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
- multiboot_uint16_t vbe_mode;
- multiboot_uint16_t vbe_interface_seg;
- multiboot_uint16_t vbe_interface_off;
- multiboot_uint16_t vbe_interface_len;
+ multiboot_uint16_t vbe_mode;
+ multiboot_uint16_t vbe_interface_seg;
+ multiboot_uint16_t vbe_interface_off;
+ multiboot_uint16_t vbe_interface_len;
- struct multiboot_vbe_info_block vbe_control_info;
- struct multiboot_vbe_mode_info_block vbe_mode_info;
+ struct multiboot_vbe_info_block vbe_control_info;
+ struct multiboot_vbe_mode_info_block vbe_mode_info;
};
-struct multiboot_tag_framebuffer_common
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
+struct multiboot_tag_framebuffer_common {
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
- multiboot_uint64_t framebuffer_addr;
- multiboot_uint32_t framebuffer_pitch;
- multiboot_uint32_t framebuffer_width;
- multiboot_uint32_t framebuffer_height;
- multiboot_uint8_t framebuffer_bpp;
+ multiboot_uint64_t framebuffer_addr;
+ multiboot_uint32_t framebuffer_pitch;
+ multiboot_uint32_t framebuffer_width;
+ multiboot_uint32_t framebuffer_height;
+ multiboot_uint8_t framebuffer_bpp;
#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
-#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1
-#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2
- multiboot_uint8_t framebuffer_type;
- multiboot_uint16_t reserved;
-};
-
-struct multiboot_tag_framebuffer
-{
- struct multiboot_tag_framebuffer_common common;
-
- union
- {
- struct
- {
- multiboot_uint16_t framebuffer_palette_num_colors;
- struct multiboot_color framebuffer_palette[0];
- };
- struct
- {
- multiboot_uint8_t framebuffer_red_field_position;
- multiboot_uint8_t framebuffer_red_mask_size;
- multiboot_uint8_t framebuffer_green_field_position;
- multiboot_uint8_t framebuffer_green_mask_size;
- multiboot_uint8_t framebuffer_blue_field_position;
- multiboot_uint8_t framebuffer_blue_mask_size;
- };
- };
-};
-
-struct multiboot_tag_elf_sections
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
- multiboot_uint32_t num;
- multiboot_uint32_t entsize;
- multiboot_uint32_t shndx;
- char sections[0];
-};
-
-struct multiboot_tag_apm
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
- multiboot_uint16_t version;
- multiboot_uint16_t cseg;
- multiboot_uint32_t offset;
- multiboot_uint16_t cseg_16;
- multiboot_uint16_t dseg;
- multiboot_uint16_t flags;
- multiboot_uint16_t cseg_len;
- multiboot_uint16_t cseg_16_len;
- multiboot_uint16_t dseg_len;
-};
-
-struct multiboot_tag_efi32
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
- multiboot_uint32_t pointer;
-};
-
-struct multiboot_tag_efi64
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
- multiboot_uint64_t pointer;
-};
-
-struct multiboot_tag_smbios
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
- multiboot_uint8_t major;
- multiboot_uint8_t minor;
- multiboot_uint8_t reserved[6];
- multiboot_uint8_t tables[0];
-};
-
-struct multiboot_tag_old_acpi
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
- multiboot_uint8_t rsdp[0];
-};
-
-struct multiboot_tag_new_acpi
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
- multiboot_uint8_t rsdp[0];
-};
-
-struct multiboot_tag_network
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
- multiboot_uint8_t dhcpack[0];
-};
-
-struct multiboot_tag_efi_mmap
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
- multiboot_uint32_t descr_size;
- multiboot_uint32_t descr_vers;
- multiboot_uint8_t efi_mmap[0];
-};
-
-struct multiboot_tag_efi32_ih
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
- multiboot_uint32_t pointer;
-};
-
-struct multiboot_tag_efi64_ih
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
- multiboot_uint64_t pointer;
-};
-
-struct multiboot_tag_load_base_addr
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
- multiboot_uint32_t load_base_addr;
+#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1
+#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2
+ multiboot_uint8_t framebuffer_type;
+ multiboot_uint16_t reserved;
+};
+
+struct multiboot_tag_framebuffer {
+ struct multiboot_tag_framebuffer_common common;
+
+ union {
+ struct {
+ multiboot_uint16_t framebuffer_palette_num_colors;
+ struct multiboot_color framebuffer_palette[0];
+ };
+ struct {
+ multiboot_uint8_t framebuffer_red_field_position;
+ multiboot_uint8_t framebuffer_red_mask_size;
+ multiboot_uint8_t framebuffer_green_field_position;
+ multiboot_uint8_t framebuffer_green_mask_size;
+ multiboot_uint8_t framebuffer_blue_field_position;
+ multiboot_uint8_t framebuffer_blue_mask_size;
+ };
+ };
+};
+
+struct multiboot_tag_elf_sections {
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t num;
+ multiboot_uint32_t entsize;
+ multiboot_uint32_t shndx;
+ char sections[0];
+};
+
+struct multiboot_tag_apm {
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint16_t version;
+ multiboot_uint16_t cseg;
+ multiboot_uint32_t offset;
+ multiboot_uint16_t cseg_16;
+ multiboot_uint16_t dseg;
+ multiboot_uint16_t flags;
+ multiboot_uint16_t cseg_len;
+ multiboot_uint16_t cseg_16_len;
+ multiboot_uint16_t dseg_len;
+};
+
+struct multiboot_tag_efi32 {
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t pointer;
+};
+
+struct multiboot_tag_efi64 {
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint64_t pointer;
+};
+
+struct multiboot_tag_smbios {
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint8_t major;
+ multiboot_uint8_t minor;
+ multiboot_uint8_t reserved[6];
+ multiboot_uint8_t tables[0];
+};
+
+struct multiboot_tag_old_acpi {
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint8_t rsdp[0];
+};
+
+struct multiboot_tag_new_acpi {
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint8_t rsdp[0];
+};
+
+struct multiboot_tag_network {
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint8_t dhcpack[0];
+};
+
+struct multiboot_tag_efi_mmap {
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t descr_size;
+ multiboot_uint32_t descr_vers;
+ multiboot_uint8_t efi_mmap[0];
+};
+
+struct multiboot_tag_efi32_ih {
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t pointer;
+};
+
+struct multiboot_tag_efi64_ih {
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint64_t pointer;
+};
+
+struct multiboot_tag_load_base_addr {
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t load_base_addr;
};
#endif /* ! ASM_FILE */
diff --git a/kernel/include/arch/cpu/control.h b/kernel/include/arch/cpu/control.h
new file mode 100644
index 0000000..a9d0ec7
--- /dev/null
+++ b/kernel/include/arch/cpu/control.h
@@ -0,0 +1,13 @@
+#ifndef __ARCH_CPU_CONTROL
+#define __ARCH_CPU_CONTROL
+
+#include
+
+extern bool cpu_interrupt_lock_acquired();
+extern void cpu_interrupt_lock_acquire();
+extern void cpu_interrupt_lock_release();
+extern void cpu_interrupt_lock_force_release();
+
+void cpu_halt();
+
+#endif
\ No newline at end of file
diff --git a/kernel/include/arch/cpu/state.h b/kernel/include/arch/cpu/state.h
new file mode 100644
index 0000000..fff6a10
--- /dev/null
+++ b/kernel/include/arch/cpu/state.h
@@ -0,0 +1,6 @@
+#ifndef __K_SYS_CPU_STATE
+#define __K_SYS_CPU_STATE
+
+extern void cpu_state_print();
+
+#endif
\ No newline at end of file
diff --git a/kernel/include/arch/cpu/strace.h b/kernel/include/arch/cpu/strace.h
new file mode 100644
index 0000000..2d3c60d
--- /dev/null
+++ b/kernel/include/arch/cpu/strace.h
@@ -0,0 +1,14 @@
+#ifndef __ARCH_CPU_STRACE
+#define __ARCH_CPU_STRACE
+
+#include
+
+struct stackframe {
+ struct stackframe *sp;
+ uint64_t pc;
+};
+
+extern struct stackframe *strace_get();
+extern uint64_t strace_get_framep(int sf_offset);
+
+#endif
\ No newline at end of file
diff --git a/kernel/include/kasm.h b/kernel/include/kasm.h
index 0dba1b8..85dbd01 100644
--- a/kernel/include/kasm.h
+++ b/kernel/include/kasm.h
@@ -1,7 +1,7 @@
#ifndef __K_ASM
#define __K_ASM
-#include
+#include "kstdint.h"
#if defined(__x86_64__)
static inline void outb(uint16_t port, uint8_t val) {
@@ -35,21 +35,21 @@ static inline unsigned int inl(uint16_t port) {
}
// https://wiki.osdev.org/Inline_Assembly/Examples
-static inline void io_wait( ) {
+static inline void io_wait() {
outb(0x80, 0);
}
-static inline void lidt(void* base, uint16_t size) {
+static inline void lidt(void *base, uint16_t size) {
// This function works in 32 and 64bit mode
struct {
uint16_t length;
- void* base;
+ void *base;
} __attribute__((packed)) IDTR = { size, base };
asm("lidt %0" : : "m"(IDTR)); // let the compiler choose an addressing mode
}
-static inline uint64_t rdtsc( ) {
+static inline uint64_t rdtsc() {
uint32_t low, high;
asm volatile("rdtsc" : "=a"(low), "=d"(high));
return ((uint64_t)high << 32) | low;
diff --git a/kernel/include/khal.h b/kernel/include/khal.h
index ac45d20..4539746 100644
--- a/kernel/include/khal.h
+++ b/kernel/include/khal.h
@@ -1,16 +1,17 @@
#ifndef __K_HAL
#define __K_HAL
-#include
-#include
+#include "kasm.h"
+#include "kstdint.h"
#if defined(__x86_64__)
extern uint64_t paging_main[3][512] __attribute__((aligned(4096)));
void serial_write_byte(uint8_t byte);
-int serial_init( );
-void serial_printf(const char *fmt, ...) ;
+int serial_init();
+void __attribute__((format(printf, 1, 2)))
+serial_printf(const char *restrict fmt, ...);
#else
#error "Only AMD64 is supported"
diff --git a/kernel/include/kopsize.h b/kernel/include/kopsize.h
new file mode 100644
index 0000000..aeea8f7
--- /dev/null
+++ b/kernel/include/kopsize.h
@@ -0,0 +1,11 @@
+#ifndef __K_OPSIZE
+#define __K_OPSIZE
+
+typedef enum {
+ OPSIZE_BYTE = 1,
+ OPSIZE_WORD = 2,
+ OPSIZE_DWORD = 4,
+ OPSIZE_QWORD = 8
+} opsize_t;
+
+#endif
\ No newline at end of file
diff --git a/kernel/include/kreflock.h b/kernel/include/kreflock.h
new file mode 100644
index 0000000..b1fd26f
--- /dev/null
+++ b/kernel/include/kreflock.h
@@ -0,0 +1,55 @@
+// NOTE: This file contains code derived from or inspired by:
+// AstriX ("The AstriX Operating System") at https://codeberg.org/AstriX/AstriX.
+// Copyright (c) 2023-2025 NotYourFox, sigsegv
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+// This program 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.
+
+// This program 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 this program. If not, see .
+
+#ifndef __K_REFLOCK
+#define __K_REFLOCK
+
+#include
+#include
+#include
+
+typedef struct {
+ void (*on_lock)();
+ void (*on_unlock)();
+
+ const bool strict; // if strict, panic if released empty lock
+ const bool allow_force_unlock;
+
+ uint8_t data[12];
+} reflock_t;
+
+#define NEW_REFLOCK(_on_lock, _on_unlock, _strict, _allow_force) \
+ { \
+ _on_lock, _on_unlock, _strict, _allow_force, { \
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 \
+ } \
+ }
+
+void reflock_make(reflock_t *lock);
+bool reflock_validate_magic(reflock_t *lock);
+
+static inline bool reflock_validate(reflock_t *lock) {
+ return reflock_validate_magic(lock);
+}
+
+void reflock_acquire(reflock_t *lock);
+void reflock_release(reflock_t *lock);
+bool reflock_is_locked(reflock_t *lock);
+void reflock_force_unlock(reflock_t *lock);
+
+#endif
\ No newline at end of file
diff --git a/kernel/include/kstdint.h b/kernel/include/kstdint.h
index dff5238..33afcfe 100644
--- a/kernel/include/kstdint.h
+++ b/kernel/include/kstdint.h
@@ -1,16 +1,20 @@
#ifndef __K_STDINT
#define __K_STDINT
-typedef char int8_t;
-typedef short int16_t;
-typedef int int32_t;
-typedef long long int64_t;
+#include
-typedef unsigned char uint8_t;
-typedef unsigned short uint16_t;
-typedef unsigned int uint32_t;
-typedef unsigned long long uint64_t;
+// deprecate this, #include from OS instead
-typedef uint64_t uintptr_t;
+// typedef char int8_t;
+// typedef short int16_t;
+// typedef int int32_t;
+// typedef long long int64_t;
+
+// typedef unsigned char uint8_t;
+// typedef unsigned short uint16_t;
+// typedef unsigned int uint32_t;
+// typedef unsigned long long uint64_t;
+
+// typedef uint64_t uintptr_t;
#endif
\ No newline at end of file
diff --git a/kernel/include/kstdlib.h b/kernel/include/kstdlib.h
index 38a4be6..d1f270b 100644
--- a/kernel/include/kstdlib.h
+++ b/kernel/include/kstdlib.h
@@ -1,6 +1,9 @@
#ifndef __K_STDLIB
#define __K_STDLIB
+#define unlikely(x) __builtin_expect(x, 0)
+#define likely(x) __builtin_expect(x, 1)
+
#define IGNORE_UNUSED(x) ((void)x)
#endif
\ No newline at end of file
diff --git a/kernel/include/kstring.h b/kernel/include/kstring.h
index 399f653..203a0a0 100644
--- a/kernel/include/kstring.h
+++ b/kernel/include/kstring.h
@@ -1,11 +1,49 @@
#ifndef __K_STRING
#define __K_STRING
-#include
+#include "kopsize.h"
+#include
+#include
-int strcmp(const char *s1, const char *s2);
-char *strcpy(char *dst, const char *src);
-char *strcat(char *dst, const char *src);
-int strlen(const char *s);
+#define string_equal(s1, s2) !strcmp(s1, s2)
+#define string_equal_n(s1, s2, n) !strncmp(s1, s2, n)
+#define string_for_each(_s, _i) for (size_t _i = 0; _i < strlen(_s); _i++)
+
+void memset(void *ptr, char c, size_t size);
+void memcpy(void *dest, const void *src, size_t size);
+void xmemcpy(void *dest, const void *src, size_t size, opsize_t opsize);
+int memcmp(const void *ptr1, const void *ptr2, size_t count);
+
+#define _tolower(c) ((c) | 0x20)
+
+size_t __attribute__((pure)) strlen(const char *s);
+
+char *strcpy(char *dest, const char *src);
+char *strncpy(char *dest, const char *src, size_t n);
+
+int __attribute__((pure)) strncmp(const char *s1, const char *s2, size_t n);
+int __attribute__((pure)) strcmp(const char *s1, const char *s2);
+
+char *strchr(char *s, char c);
+char *strchr_r(char *s, char c);
+char *strstr(char *str, const char *sub);
+
+char *strltrim(char *str);
+char *strrtrim(char *str);
+char *strtrim(char *str);
+
+bool isdigit(char c);
+bool isalphac(char c);
+bool islowerc(char c);
+bool isupperc(char c);
+bool isalnumc(char c);
+
+bool isnumeric(const char *s);
+bool isalpha(const char *s);
+bool isalnum(const char *s);
+
+char tolowerc(char c);
+char *tolower(char *s);
+char *toupper(char *s);
#endif
diff --git a/kernel/include/sys/panic.h b/kernel/include/sys/panic.h
new file mode 100644
index 0000000..7fc8245
--- /dev/null
+++ b/kernel/include/sys/panic.h
@@ -0,0 +1,4 @@
+#include
+
+void __attribute__((noreturn)) panic_int(uint8_t int_no, const char *msg);
+void __attribute__((noreturn)) panic(const char *msg);
\ No newline at end of file
diff --git a/kernel/kernel.c b/kernel/kernel.c
index 56cd91b..4402c7a 100644
--- a/kernel/kernel.c
+++ b/kernel/kernel.c
@@ -1,13 +1,15 @@
-#include
-#include
-#include
+#include "khal.h"
+#include "kstdint.h"
+#include "kstring.h"
+#include "sys/panic.h"
int multiboot2_init(uint64_t *addr, uint32_t magic);
-void kernel_main64(uint64_t *multiboot2, uint32_t magic, void *esp, uint64_t base) {
- serial_init( );
+void kernel_main64(uint64_t *multiboot2, uint32_t magic, void *esp,
+ uint64_t base) {
+ serial_init();
serial_printf(":D\n");
-
+
int status = multiboot2_init(multiboot2, magic);
if (status) {
@@ -15,18 +17,8 @@ void kernel_main64(uint64_t *multiboot2, uint32_t magic, void *esp, uint64_t bas
} else {
serial_printf("[ERR]\n");
}
- char *str1 = "ABCF";
- char *str2 = "ABCD";
- char buf[7] = "";
- auto cmp_value = strcmp(str1, str2);
-
- serial_printf("[LOG] STR1 AND STR2 CMP %d\n", cmp_value);
- serial_printf("[LOG] STR1 LEN %d\n", strlen(str1));
- strcpy((char*)&buf, str1);
- serial_printf("[LOG] STRCPY RESULT: %s\n", buf);
- serial_printf("[LOG] STRCPY RESULT LEN %d\n", strlen(buf));
- strcat((char*)&buf, "CAT");
- serial_printf("[LOG] STRCAT RESULT: %s\n", buf);
- serial_printf("[LOG] STRCAT RESULT LEN %d\n", strlen(buf));
+
+ panic("AAAAAAAAAAAAAAAaa");
+
for (;;) {}
}
diff --git a/kernel/klibc/kstring.c b/kernel/klibc/kstring.c
deleted file mode 100644
index 397969b..0000000
--- a/kernel/klibc/kstring.c
+++ /dev/null
@@ -1,42 +0,0 @@
-#include
-#include
-
-int strcmp(const char *s1, const char *s2)
-{
- for (int i = 0;; i++)
- {
- if (s1[i] > s2[i])
- {
- return 1;
- }
- else if (s1[i] < s2[i])
- {
- return -1; // INT сломан, тут он возращает maxValue.
- }
- if (s1[i] == '\0' || s2[i] == '\0')
- {
- return 0;
- }
- }
-}
-
-char *strcpy(char *dst, const char *src)
-{
- char *buf = dst;
- while ((*dst++ = *src++) != '\0'); // Задаем по байту в dst из src, пока результатом этого не станет NUL
- return buf;
-}
-
-int strlen(const char *s)
-{
- int i;
- for (i = 0; s[i] != '\0'; i++); // Добавляем к i, пока не встретим NUL
- return i;
-}
-
-char *strcat(char *dst, const char *src)
-{
- char *buf = dst;
- strcpy(dst+strlen(dst), src); // Копируем строку в цель со смешением в длинну dst
- return buf;
-}
diff --git a/kernel/klibc/printf.c b/kernel/klibc/printf.c
index 7b2885d..f239ce9 100644
--- a/kernel/klibc/printf.c
+++ b/kernel/klibc/printf.c
@@ -1,80 +1,68 @@
+#include "khal.h"
+#include "kstdint.h"
#include
-#include
-#include
static char *itoa(uint64_t value, char *buf, uint8_t base) {
- char *ptr = buf;
- uint64_t temp = value;
- do {
- uint64_t digit = temp % base;
- if (digit < 10)
- *ptr = '0' + digit;
- else
- *ptr = 'A' + (digit - 10);
- ptr++;
- temp /= base;
- } while (temp);
- *ptr = '\0';
- // Reverse the string
- char *start = buf;
- char *end = ptr - 1;
- while (start < end) {
- char tmp = *start;
- *start = *end;
- *end = tmp;
- start++;
- end--;
- }
- return buf;
+ char *ptr = buf;
+ uint64_t temp = value;
+ do {
+ uint64_t digit = temp % base;
+ if (digit < 10)
+ *ptr = '0' + digit;
+ else
+ *ptr = 'A' + (digit - 10);
+ ptr++;
+ temp /= base;
+ } while (temp);
+ *ptr = '\0';
+ // Reverse the string
+ char *start = buf;
+ char *end = ptr - 1;
+ while (start < end) {
+ char tmp = *start;
+ *start = *end;
+ *end = tmp;
+ start++;
+ end--;
+ }
+ return buf;
}
-void serial_printf(const char *fmt, ...) {
- char buf[32];
- va_list args;
- va_start(args, fmt);
- while (*fmt) {
- if (*fmt == '%') {
- fmt++;
- switch (*fmt) {
- case 's':
- {
- char *str = va_arg(args, char *);
- while (*str)
- serial_write_byte(*str++);
- }
- break;
- case 'd':
- {
- int64_t num = va_arg(args, int64_t);
- itoa(num, buf, 10);
- serial_printf("%s", buf);
- }
- break;
- case 'u':
- {
- uint64_t num = va_arg(args, uint64_t);
- itoa(num, buf, 10);
- serial_printf("%s", buf);
- }
- break;
- case 'x':
- {
- uint64_t num = va_arg(args, uint64_t);
- itoa(num, buf, 16);
- serial_printf("%s", buf);
- }
- break;
- case 'c':
- serial_write_byte(va_arg(args, int));
- break;
- default:
- serial_write_byte(*fmt);
- break;
- }
- fmt++;
- } else {
- serial_write_byte(*fmt++);
- }
- }
- va_end(args);
+// TODO: normalize
+void __attribute__((format(printf, 1, 2))) serial_printf(const char *fmt, ...) {
+ char buf[32];
+ va_list args;
+ va_start(args, fmt);
+ while (*fmt) {
+ if (*fmt == '%') {
+ fmt++;
+ switch (*fmt) {
+ case 's': {
+ char *str = va_arg(args, char *);
+ while (*str) serial_write_byte(*str++);
+ } break;
+ case 'd': {
+ int64_t num = va_arg(args, int64_t);
+ itoa(num, buf, 10);
+ serial_printf("%s", buf);
+ } break;
+ case 'u': {
+ uint64_t num = va_arg(args, uint64_t);
+ itoa(num, buf, 10);
+ serial_printf("%s", buf);
+ } break;
+ case 'x': {
+ uint64_t num = va_arg(args, uint64_t);
+ itoa(num, buf, 16);
+ serial_printf("%s", buf);
+ } break;
+ case 'c': serial_write_byte(va_arg(args, int)); break;
+ default: serial_write_byte(*fmt); break;
+ }
+ fmt++;
+ } else {
+ serial_write_byte(*fmt++);
+ }
+ }
+ va_end(args);
}
diff --git a/kernel/klibc/reflock.c b/kernel/klibc/reflock.c
new file mode 100644
index 0000000..a637b04
--- /dev/null
+++ b/kernel/klibc/reflock.c
@@ -0,0 +1,97 @@
+// NOTE: This file contains code derived from or inspired by:
+// AstriX ("The AstriX Operating System") at https://codeberg.org/AstriX/AstriX.
+// Copyright (c) 2023-2025 NotYourFox, sigsegv
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+// This program 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.
+
+// This program 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 this program. If not, see .
+
+#include "kreflock.h"
+#include "kstring.h"
+#include "sys/panic.h"
+#include
+#include
+
+struct reflock_private {
+ struct {
+ char *magic;
+ volatile int refcount;
+ } data;
+};
+
+#define REFLOCK_MAGIC "r3f10ck"
+
+static inline struct reflock_private *reflock_get_private_ptr(reflock_t *lock) {
+ return (struct reflock_private *)(&lock->data);
+}
+
+void reflock_make(reflock_t *lock) {
+ struct reflock_private *private = reflock_get_private_ptr(lock);
+ private->data.magic = REFLOCK_MAGIC;
+ private->data.refcount = 0;
+}
+
+bool reflock_validate_magic(reflock_t *lock) {
+ struct reflock_private *private = reflock_get_private_ptr(lock);
+ return !strcmp(private->data.magic, REFLOCK_MAGIC);
+}
+
+void reflock_acquire(reflock_t *lock) {
+ struct reflock_private *private = reflock_get_private_ptr(lock);
+
+ if (!reflock_validate_magic(lock)) {
+ panic("broken reflock (invalid magic)");
+ }
+
+ if (!private->data.refcount && lock->on_lock) {
+ lock->on_lock();
+ }
+
+ private->data.refcount++;
+}
+
+void reflock_release(reflock_t *lock) {
+ struct reflock_private *private = reflock_get_private_ptr(lock);
+
+ if (!reflock_validate_magic(lock)) {
+ panic("broken reflock (invalid magic field)");
+ }
+
+ if (!private->data.refcount) {
+ if (lock->strict) {
+ panic("Attempted to release empty strict reflock");
+ }
+
+ return;
+ }
+
+ if (!--private->data.refcount && lock->on_unlock) {
+ lock->on_unlock();
+ }
+}
+
+bool reflock_is_locked(reflock_t *lock) {
+ return reflock_get_private_ptr(lock)->data.refcount > 0 &&
+ reflock_validate_magic(lock);
+}
+
+void reflock_force_unlock(reflock_t *lock) {
+ struct reflock_private *private = reflock_get_private_ptr(lock);
+
+ if (!lock->allow_force_unlock) {
+ panic("Attempted disallowed force-unlock of a reflock");
+ }
+
+ private->data.refcount = 0;
+ lock->on_unlock();
+}
diff --git a/kernel/klibc/string.c b/kernel/klibc/string.c
new file mode 100644
index 0000000..99a6971
--- /dev/null
+++ b/kernel/klibc/string.c
@@ -0,0 +1,294 @@
+// NOTE: This file contains code derived from or inspired by AstriX ("The AstriX
+// Operating System") at https://codeberg.org/AstriX/AstriX. Copyright (c)
+// 2023-2025 NotYourFox, sigsegv SPDX-License-Identifier: GPL-3.0-or-later
+
+// If this project is made accessible to the general public, it is required to
+// obey the terms of GNU General Public License version 3 (or later) for as long
+// as this notice applies.
+// If you suspect any form of license violation or copyright infringement,
+// please reach out to AstriX team at .
+
+// This program 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.
+
+// This program 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 this program. If not, see .
+
+#include "kstring.h"
+#include
+#include
+
+void memset(void *ptr, char c, size_t size) {
+ for (size_t i = 0; i < size; i++) {
+ *(char *)(ptr + i) = c;
+ }
+}
+
+void xmemcpy(void *dest, const void *src, size_t size, opsize_t opsize) {
+ size_t d0, d1, d2;
+
+ switch (opsize) {
+ case OPSIZE_BYTE:
+ asm volatile("rep movsb"
+ : "=&c"(d0), "=&D"(d1), "=&S"(d2)
+ : "0"(size), "1"(dest), "2"(src)
+ : "memory");
+ break;
+ case OPSIZE_WORD:
+ asm volatile("rep movsw"
+ : "=&c"(d0), "=&D"(d1), "=&S"(d2)
+ : "0"(size), "1"(dest), "2"(src)
+ : "memory");
+ break;
+ case OPSIZE_DWORD:
+ asm volatile("rep movsd"
+ : "=&c"(d0), "=&D"(d1), "=&S"(d2)
+ : "0"(size), "1"(dest), "2"(src)
+ : "memory");
+ break;
+ case OPSIZE_QWORD:
+ asm volatile("rep movsd"
+ : "=&c"(d0), "=&D"(d1), "=&S"(d2)
+ : "0"(size), "1"(dest), "2"(src)
+ : "memory");
+ break;
+ default:
+ asm volatile("rep movsb"
+ : "=&c"(d0), "=&D"(d1), "=&S"(d2)
+ : "0"(size * opsize), "1"(dest), "2"(src)
+ : "memory");
+ break;
+ }
+}
+
+void memcpy(void *dest, const void *src, size_t size) {
+ xmemcpy(dest, src, size, OPSIZE_BYTE);
+}
+
+int memcmp(const void *ptr1, const void *ptr2, size_t count) {
+ register const unsigned char *p1 = ptr1;
+ register const unsigned char *p2 = ptr2;
+
+ while (count-- > 0) {
+ if (*p1++ != *p2++) {
+ return p1[-1] < p2[-1] ? -1 : 1;
+ }
+ }
+
+ return 0;
+}
+
+size_t __attribute__((pure)) strlen(const char *s) {
+ int i;
+ for (i = 0; s[i] != '\0'; i++);
+ return i;
+}
+
+char *strcat(char *dst, const char *src) {
+ char *buf = dst;
+ strcpy(dst + strlen(dst), src);
+ return buf;
+}
+
+char *strcpy(char *dest, const char *src) {
+ memcpy(dest, src, strlen(src) + 1);
+ return dest;
+}
+
+char *strncpy(char *dest, const char *src, size_t n) {
+ size_t total = n > strlen(src) ? strlen(src) : n;
+ memcpy(dest, src, total);
+ dest[total] = 0x00;
+
+ return dest;
+}
+
+int strncmp(const char *s1, const char *s2, size_t n) {
+ if (n > strlen(s1) || n > strlen(s2)) {
+ return strlen(s1) > strlen(s2) ? 1 : -1;
+ }
+
+ return memcmp(s1, s2, n);
+}
+
+int strcmp(const char *s1, const char *s2) {
+ if (strlen(s1) != strlen(s2)) {
+ return strlen(s1) > strlen(s2) ? 1 : -1;
+ }
+
+ return strncmp(s1, s2, strlen(s1));
+}
+
+char *strltrim(char *str) {
+ while (*str == ' ' || *str == '\t') {
+ str++;
+ }
+
+ return str;
+}
+
+char *strrtrim(char *str) {
+ char *ptr = str + strlen(str) - 1;
+ while (*ptr == ' ' || *ptr == '\t') {
+ *ptr++ = 0x00;
+ }
+
+ return str;
+}
+
+char *strtrim(char *str) {
+ str = strltrim(str);
+ return strrtrim(str);
+}
+
+bool isupperc(char c) {
+ return (c >= 'A' && c <= 'Z');
+}
+
+bool isupper(const char *s) {
+ string_for_each(s, i) {
+ if (!isupperc(s[i])) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool islowerc(char c) {
+ return (c >= 'a' && c <= 'z');
+}
+
+// note: returns false for non-alpha string
+bool islower(const char *s) {
+ string_for_each(s, i) {
+ if (!islowerc(s[i])) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool isdigit(char c) {
+ return c >= '0' && c <= '9';
+}
+
+bool isnumeric(const char *s) {
+ string_for_each(s, i) {
+ if (!isdigit(s[i])) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool isalphac(char c) {
+ return isupperc(c) || islowerc(c);
+}
+
+bool isalpha(const char *s) {
+ string_for_each(s, i) {
+ if (!isalphac(s[i])) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool isalnumc(char c) {
+ return isalphac(c) || isdigit(c);
+}
+
+bool isalnum(const char *s) {
+ string_for_each(s, i) {
+ if (!isalphac(s[i]) && !isdigit(s[i])) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+char toupperc(char c) {
+ if (!isalnumc(c)) {
+ return c;
+ }
+
+ return c & ~0x20;
+}
+
+char tolowerc(char c) {
+ if (!isalnumc(c)) {
+ return c;
+ }
+
+ return _tolower(c);
+}
+
+// NOTE: MODIFIES STRING IN-PLACE
+
+char *toupper(char *s) {
+ // note: 'a' > 'A'
+ string_for_each(s, i) {
+ if (isupperc(s[i]) || !isalphac(s[i])) {
+ continue;
+ }
+
+ s[i] = toupperc(s[i]);
+ }
+
+ return s;
+}
+
+char *tolower(char *s) {
+ // note: 'a' > 'A'
+ string_for_each(s, i) {
+ if (islowerc(s[i]) || !isalphac(s[i])) {
+ continue;
+ }
+
+ s[i] = tolowerc(s[i]);
+ }
+
+ return s;
+}
+
+char *strchr(char *s, char c) {
+ for (size_t i = 0; i < strlen(s); i++) {
+ if (s[i] == c) {
+ return s + i;
+ }
+ }
+
+ return NULL;
+}
+
+char *strchr_r(char *s, char c) {
+ for (int i = strlen(s) - 1; i >= 0; i--) {
+ if (s[i] == c) {
+ return s + i;
+ }
+ }
+
+ return NULL;
+}
+
+char *strstr(char *str, const char *sub) {
+ for (size_t i = 0; i < strlen(str); i++) {
+ if (!strncmp(str + i, sub, strlen(sub))) {
+ return str + i;
+ }
+ }
+
+ return NULL;
+}
\ No newline at end of file
diff --git a/kernel/multiboot2.c b/kernel/multiboot2.c
index ac2d7dc..6c72110 100644
--- a/kernel/multiboot2.c
+++ b/kernel/multiboot2.c
@@ -1,7 +1,7 @@
+#include "khal.h"
+#include "kstdint.h"
+#include "kstdlib.h"
#include <3rd/multiboot2.h>
-#include
-#include
-#include
#define CHECK_FLAG(flags, bit) ((flags) & (1 << (bit)))
@@ -12,90 +12,93 @@ void handle_basic_meminfo_tag(struct multiboot_tag *tag);
void handle_mmap_tag(struct multiboot_tag *tag);
int multiboot2_init(uint64_t *addr, uint32_t magic) {
- struct multiboot_tag *tag;
- uint64_t mbi_addr = (uint64_t)addr;
-
- if (magic != MULTIBOOT2_BOOTLOADER_MAGIC) {
- serial_printf("Invalid magic number: 0x%x\n", (unsigned)magic);
- return -1;
- }
-
- if (mbi_addr & 7) {
- serial_printf("Unaligned mbi: 0x%x\n", mbi_addr);
- return -2;
- }
-
- uint64_t size = *addr;
- serial_printf("Announced mbi size 0x%x\n", size);
-
- tag = (struct multiboot_tag *)(mbi_addr + sizeof(uint64_t));
-
- while (tag->type != MULTIBOOT_TAG_TYPE_END) {
- if ((uintptr_t)tag % MULTIBOOT_TAG_ALIGN != 0) {
- serial_printf("Tag at 0x%x is not aligned correctly\n", (uintptr_t)tag);
- break;
- }
-
- switch (tag->type) {
- case MULTIBOOT_TAG_TYPE_CMDLINE:
- handle_cmdline_tag(tag);
- break;
- case MULTIBOOT_TAG_TYPE_MODULE:
- handle_module_tag(tag);
- break;
- case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO:
- handle_basic_meminfo_tag(tag);
- break;
- case MULTIBOOT_TAG_TYPE_MMAP:
- handle_mmap_tag(tag);
- break;
- case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR:
- handle_basic_load_base_addr(tag);
- break;
- default:
- serial_printf("Tag at 0x%x | %d\n", (uintptr_t)tag, tag->type);
- break;
- }
-
- // Move to the next tag
- tag = (struct multiboot_tag *)((uintptr_t)tag) + ((tag->size + 7) & ~7);
- }
-
- return 1;
+ struct multiboot_tag *tag;
+ uint64_t mbi_addr = (uint64_t)addr;
+
+ if (magic != MULTIBOOT2_BOOTLOADER_MAGIC) {
+ serial_printf("Invalid magic number: 0x%x\n", (unsigned)magic);
+ return -1;
+ }
+
+ if (mbi_addr & 7) {
+ serial_printf("Unaligned mbi: 0x%x\n", mbi_addr);
+ return -2;
+ }
+
+ uint64_t size = *addr;
+ serial_printf("Announced mbi size 0x%x\n", size);
+
+ tag = (struct multiboot_tag *)(mbi_addr + sizeof(uint64_t));
+
+ while (tag->type != MULTIBOOT_TAG_TYPE_END) {
+ if ((uintptr_t)tag % MULTIBOOT_TAG_ALIGN != 0) {
+ serial_printf("Tag at 0x%x is not aligned correctly\n",
+ (uintptr_t)tag);
+ break;
+ }
+
+ switch (tag->type) {
+ case MULTIBOOT_TAG_TYPE_CMDLINE: handle_cmdline_tag(tag); break;
+ case MULTIBOOT_TAG_TYPE_MODULE: handle_module_tag(tag); break;
+ case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO:
+ handle_basic_meminfo_tag(tag);
+ break;
+ case MULTIBOOT_TAG_TYPE_MMAP: handle_mmap_tag(tag); break;
+ case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR:
+ handle_basic_load_base_addr(tag);
+ break;
+ default:
+ serial_printf("Tag at 0x%x | %d\n", (uintptr_t)tag, tag->type);
+ break;
+ }
+
+ // Move to the next tag
+ tag = (struct multiboot_tag *)((uintptr_t)tag) + ((tag->size + 7) & ~7);
+ }
+
+ return 1;
}
void handle_cmdline_tag(struct multiboot_tag *tag) {
- struct multiboot_tag_string *cmdline = (struct multiboot_tag_string *)tag;
- serial_printf("Command line: %s\n", cmdline->string);
+ struct multiboot_tag_string *cmdline = (struct multiboot_tag_string *)tag;
+ serial_printf("Command line: %s\n", cmdline->string);
}
void handle_module_tag(struct multiboot_tag *tag) {
- struct multiboot_tag_module *module = (struct multiboot_tag_module *)tag;
- serial_printf("Module at 0x%x - 0x%x\n", module->mod_start, module->mod_end);
- serial_printf("Module cmdline: %s\n", module->cmdline);
+ struct multiboot_tag_module *module = (struct multiboot_tag_module *)tag;
+ serial_printf("Module at 0x%x - 0x%x\n", module->mod_start,
+ module->mod_end);
+ serial_printf("Module cmdline: %s\n", module->cmdline);
}
void handle_basic_meminfo_tag(struct multiboot_tag *tag) {
- struct multiboot_tag_basic_meminfo *meminfo = (struct multiboot_tag_basic_meminfo *)tag;
- serial_printf("Memory lower: %u KB\n", meminfo->mem_lower);
- serial_printf("Memory upper: %u KB\n", meminfo->mem_upper);
+ struct multiboot_tag_basic_meminfo *meminfo =
+ (struct multiboot_tag_basic_meminfo *)tag;
+ serial_printf("Memory lower: %u KB\n", meminfo->mem_lower);
+ serial_printf("Memory upper: %u KB\n", meminfo->mem_upper);
}
void handle_basic_load_base_addr(struct multiboot_tag *tag) {
- struct multiboot_tag_load_base_addr *base_addr = (struct multiboot_tag_load_base_addr *)tag;
- serial_printf("load_base_size: %u\n", base_addr->size);
- serial_printf("load_base_addr: 0x%x\n", base_addr->load_base_addr);
+ struct multiboot_tag_load_base_addr *base_addr =
+ (struct multiboot_tag_load_base_addr *)tag;
+ serial_printf("load_base_size: %u\n", base_addr->size);
+ serial_printf("load_base_addr: 0x%x\n", base_addr->load_base_addr);
}
void handle_mmap_tag(struct multiboot_tag *tag) {
- struct multiboot_tag_mmap *mmap = (struct multiboot_tag_mmap *)tag;
- struct multiboot_mmap_entry *entry;
- uint64_t entry_size = mmap->entry_size;
- uint64_t entry_count = (mmap->size - sizeof(struct multiboot_tag_mmap)) / entry_size;
-
- serial_printf("Memory map:\n");
- for (uint64_t i = 0; i < entry_count; i++) {
- entry = (struct multiboot_mmap_entry *)((uintptr_t)mmap + sizeof(struct multiboot_tag_mmap) + i * entry_size);
- serial_printf(" 0x%x - 0x%x: type %u\n", entry->addr, entry->addr + entry->len, entry->type);
- }
+ struct multiboot_tag_mmap *mmap = (struct multiboot_tag_mmap *)tag;
+ struct multiboot_mmap_entry *entry;
+ uint64_t entry_size = mmap->entry_size;
+ uint64_t entry_count =
+ (mmap->size - sizeof(struct multiboot_tag_mmap)) / entry_size;
+
+ serial_printf("Memory map:\n");
+ for (uint64_t i = 0; i < entry_count; i++) {
+ entry =
+ (struct multiboot_mmap_entry *)((uintptr_t)mmap +
+ sizeof(struct multiboot_tag_mmap) +
+ i * entry_size);
+ serial_printf(" 0x%x - 0x%x: type %u\n", entry->addr,
+ entry->addr + entry->len, entry->type);
+ }
}
\ No newline at end of file
diff --git a/kernel/sys/panic.c b/kernel/sys/panic.c
new file mode 100644
index 0000000..b264a68
--- /dev/null
+++ b/kernel/sys/panic.c
@@ -0,0 +1,21 @@
+#include "arch/cpu/control.h"
+#include "arch/cpu/state.h"
+#include "khal.h"
+#include
+
+// TODO: make printf-like
+
+void __attribute__((noreturn)) panic_int(uint8_t int_no, const char *msg) {
+ serial_printf("\n\rKernel panic (in interrupt) [INT=0x%02X] - %s\n", int_no,
+ msg);
+ cpu_state_print();
+
+ for (;;) cpu_halt();
+}
+
+void __attribute__((noreturn)) panic(const char *msg) {
+ serial_printf("\n\rKernel panic - %s\n", msg);
+ cpu_state_print();
+
+ for (;;) cpu_halt();
+}
\ No newline at end of file
diff --git a/scripts/clang-format.sh b/scripts/clang-format.sh
new file mode 100755
index 0000000..edc4e19
--- /dev/null
+++ b/scripts/clang-format.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+pwd=$(pwd)
+SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
+
+cd $SCRIPT_DIR/..
+
+clang-format --style=file --dump-config
+find ./ -iname '*.h' -o -iname '*.c' | xargs clang-format -i --style=file --verbose
+
+cd $pwd