kernel: Rewrite from scratch since the current thing is held by duct tape (lmao)
This commit is contained in:
parent
d017412af5
commit
a1e27c2730
117 changed files with 285 additions and 13622 deletions
6
kernel/.gitignore
vendored
Executable file → Normal file
6
kernel/.gitignore
vendored
Executable file → Normal file
|
@ -1,5 +1,5 @@
|
|||
/freestnd-c-hdrs
|
||||
/cc-runtime*
|
||||
/src/limine.h
|
||||
/compile_commands.json
|
||||
/.cache
|
||||
/src/deps
|
||||
/bin-*
|
||||
/obj-*
|
||||
|
|
45
kernel/GNUmakefile
Executable file → Normal file
45
kernel/GNUmakefile
Executable file → Normal file
|
@ -4,7 +4,7 @@ MAKEFLAGS += -rR
|
|||
|
||||
# This is the name that our final executable will have.
|
||||
# Change as needed.
|
||||
override OUTPUT := soaplin
|
||||
override OUTPUT := kernel
|
||||
|
||||
# Target architecture to build for. Default to x86_64.
|
||||
ARCH := x86_64
|
||||
|
@ -20,9 +20,6 @@ endif
|
|||
# User controllable C compiler command.
|
||||
CC := cc
|
||||
|
||||
# User controllable archiver command.
|
||||
AR := ar
|
||||
|
||||
# User controllable C flags.
|
||||
CFLAGS := -g -O2 -pipe
|
||||
|
||||
|
@ -39,7 +36,7 @@ LDFLAGS :=
|
|||
|
||||
# Ensure the dependencies have been obtained.
|
||||
ifneq ($(shell ( test '$(MAKECMDGOALS)' = clean || test '$(MAKECMDGOALS)' = distclean ); echo $$?),0)
|
||||
ifeq ($(shell ( ! test -d freestnd-c-hdrs || ! test -d cc-runtime || ! test -f src/limine.h ); echo $$?),0)
|
||||
ifeq ($(shell ( ! test -d src/deps/freestnd-c-hdrs || ! test -f src/deps/cc-runtime.c || ! test -f src/deps/limine.h || ! test -d src/deps/flanterm ); echo $$?),0)
|
||||
$(error Please run the ./get-deps script first)
|
||||
endif
|
||||
endif
|
||||
|
@ -58,14 +55,12 @@ override CFLAGS += \
|
|||
-fno-stack-check \
|
||||
-fno-PIC \
|
||||
-ffunction-sections \
|
||||
-fdata-sections \
|
||||
-fno-omit-frame-pointer \
|
||||
-fno-optimize-sibling-calls
|
||||
-fdata-sections
|
||||
|
||||
# Internal C preprocessor flags that should not be changed by the user.
|
||||
override CPPFLAGS := \
|
||||
-I src \
|
||||
-isystem freestnd-c-hdrs \
|
||||
-isystem src/deps/freestnd-c-hdrs \
|
||||
$(CPPFLAGS) \
|
||||
-DLIMINE_API_REVISION=3 \
|
||||
-MMD \
|
||||
|
@ -167,62 +162,52 @@ all: bin-$(ARCH)/$(OUTPUT)
|
|||
# Include header dependencies.
|
||||
-include $(HEADER_DEPS)
|
||||
|
||||
# Link rules for building the C compiler runtime.
|
||||
cc-runtime-$(ARCH)/cc-runtime.a: GNUmakefile cc-runtime/*
|
||||
@rm -rf cc-runtime-$(ARCH)
|
||||
@cp -r cc-runtime cc-runtime-$(ARCH)
|
||||
@$(MAKE) -C cc-runtime-$(ARCH) -f cc-runtime.mk \
|
||||
CC="$(CC)" \
|
||||
AR="$(AR)" \
|
||||
CFLAGS="$(CFLAGS)" \
|
||||
CPPFLAGS='-isystem ../freestnd-c-hdrs -DCC_RUNTIME_NO_FLOAT'
|
||||
@echo " C runtime built"
|
||||
|
||||
# Link rules for the final executable.
|
||||
bin-$(ARCH)/$(OUTPUT): GNUmakefile linker-$(ARCH).ld $(OBJ) cc-runtime-$(ARCH)/cc-runtime.a
|
||||
@mkdir -p "$$(dirname $@)"
|
||||
bin-$(ARCH)/$(OUTPUT): GNUmakefile linker-$(ARCH).ld $(OBJ)
|
||||
@echo " LD $@"
|
||||
@$(CC) $(CFLAGS) $(LDFLAGS) $(OBJ) cc-runtime-$(ARCH)/cc-runtime.a -o $@
|
||||
@mkdir -p "$$(dirname $@)"
|
||||
@$(CC) $(CFLAGS) $(LDFLAGS) $(OBJ) -o $@
|
||||
|
||||
# Compilation rules for *.c files.
|
||||
obj-$(ARCH)/%.c.o: src/%.c GNUmakefile
|
||||
@mkdir -p "$$(dirname $@)"
|
||||
@echo " CC $@"
|
||||
@mkdir -p "$$(dirname $@)"
|
||||
@$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
|
||||
|
||||
# Compilation rules for *.S files.
|
||||
obj-$(ARCH)/%.S.o: src/%.S GNUmakefile
|
||||
@echo " CC $@"
|
||||
@mkdir -p "$$(dirname $@)"
|
||||
@echo " AS $@"
|
||||
@$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
|
||||
|
||||
ifeq ($(ARCH),x86_64)
|
||||
# Compilation rules for *.asm (nasm) files.
|
||||
obj-$(ARCH)/%.asm.o: src/%.asm GNUmakefile
|
||||
@echo " NASM $@"
|
||||
@mkdir -p "$$(dirname $@)"
|
||||
@echo " NASM $@"
|
||||
@nasm $(NASMFLAGS) $< -o $@
|
||||
endif
|
||||
|
||||
# Remove object files and the final executable.
|
||||
.PHONY: clean
|
||||
clean:
|
||||
@rm -rf bin-$(ARCH) obj-$(ARCH) cc-runtime-$(ARCH)
|
||||
@echo " The kernel output files have been removed."
|
||||
@rm -rf bin-$(ARCH) obj-$(ARCH)
|
||||
|
||||
# Remove everything built and generated including downloaded dependencies.
|
||||
.PHONY: distclean
|
||||
distclean:
|
||||
@rm -rf bin-* obj-* freestnd-c-hdrs cc-runtime* src/limine.h
|
||||
@echo " The kernel output & downloaded files have been removed."
|
||||
@rm -rf bin-* obj-* src/deps
|
||||
|
||||
# Install the final built executable to its final on-root location.
|
||||
.PHONY: install
|
||||
install: all
|
||||
@install -d "$(DESTDIR)$(PREFIX)/share/$(OUTPUT)"
|
||||
@install -m 644 bin-$(ARCH)/$(OUTPUT) "$(DESTDIR)$(PREFIX)/share/$(OUTPUT)/$(OUTPUT)-$(ARCH)"
|
||||
@echo "A new copy of Soaplin has been installed to $(DESTDIR)$(PREFIX)/share/$(OUTPUT)."
|
||||
|
||||
# Try to undo whatever the "install" target did.
|
||||
.PHONY: uninstall
|
||||
uninstall:
|
||||
@rm -f "$(DESTDIR)$(PREFIX)/share/$(OUTPUT)/$(OUTPUT)-$(ARCH)"
|
||||
@-rmdir "$(DESTDIR)$(PREFIX)/share/$(OUTPUT)"
|
||||
@echo "The copy of Soaplin at $(DESTDIR)$(PREFIX)/share/$(OUTPUT) has been deleted."
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
#! /bin/sh
|
||||
|
||||
set -ex
|
||||
|
||||
srcdir="$(dirname "$0")"
|
||||
test -z "$srcdir" && srcdir=.
|
||||
|
||||
cd "$srcdir"
|
||||
|
||||
clone_repo_commit() {
|
||||
echo " DEPS Cloning $1 to $2 (commit: $3)"
|
||||
if test -d "$2/.git"; then
|
||||
git -C "$2" reset --hard
|
||||
git -C "$2" clean -fd
|
||||
git -C "$2" reset --hard > /dev/null 2>&1
|
||||
git -C "$2" clean -fd > /dev/null 2>&1
|
||||
if ! git -C "$2" checkout $3; then
|
||||
rm -rf "$2"
|
||||
fi
|
||||
|
@ -22,8 +21,8 @@ clone_repo_commit() {
|
|||
fi
|
||||
fi
|
||||
if ! test -d "$2"; then
|
||||
git clone $1 "$2"
|
||||
if ! git -C "$2" checkout $3; then
|
||||
git clone $1 "$2" > /dev/null 2>&1
|
||||
if ! git -C "$2" checkout $3 > /dev/null 2>&1; then
|
||||
rm -rf "$2"
|
||||
exit 1
|
||||
fi
|
||||
|
@ -32,27 +31,28 @@ clone_repo_commit() {
|
|||
|
||||
download_by_hash() {
|
||||
DOWNLOAD_COMMAND="curl -Lo"
|
||||
if ! command -v $DOWNLOAD_COMMAND >/dev/null 2>&1; then
|
||||
if ! command -v "${DOWNLOAD_COMMAND%% *}" >/dev/null 2>&1; then
|
||||
DOWNLOAD_COMMAND="wget -O"
|
||||
if ! command -v $DOWNLOAD_COMMAND >/dev/null 2>&1; then
|
||||
if ! command -v "${DOWNLOAD_COMMAND%% *}" >/dev/null 2>&1; then
|
||||
set +x
|
||||
echo "error: Neither curl nor wget found"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
SHA256_COMMAND="sha256sum"
|
||||
if ! command -v $SHA256_COMMAND >/dev/null 2>&1; then
|
||||
if ! command -v "${SHA256_COMMAND%% *}" >/dev/null 2>&1; then
|
||||
SHA256_COMMAND="sha256"
|
||||
if ! command -v $SHA256_COMMAND >/dev/null 2>&1; then
|
||||
if ! command -v "${SHA256_COMMAND%% *}" >/dev/null 2>&1; then
|
||||
set +x
|
||||
echo "error: Cannot find sha256(sum) command"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
echo " DEPS Downloading $1 to $2"
|
||||
if ! test -f "$2" || ! $SHA256_COMMAND "$2" | grep $3 >/dev/null 2>&1; then
|
||||
rm -f "$2"
|
||||
mkdir -p "$2" && rm -rf "$2"
|
||||
$DOWNLOAD_COMMAND "$2" $1
|
||||
$DOWNLOAD_COMMAND "$2" $1 > /dev/null 2>&1
|
||||
if ! $SHA256_COMMAND "$2" | grep $3 >/dev/null 2>&1; then
|
||||
set +x
|
||||
echo "error: Cannot download file '$2' by hash"
|
||||
|
@ -64,17 +64,29 @@ download_by_hash() {
|
|||
fi
|
||||
}
|
||||
|
||||
clone_repo_commit \
|
||||
https://github.com/osdev0/freestnd-c-hdrs-0bsd.git \
|
||||
freestnd-c-hdrs \
|
||||
a87c192f3eb66b0806740dc67325f9ad23fc2d0b
|
||||
mkdir src/deps
|
||||
|
||||
clone_repo_commit \
|
||||
https://github.com/osdev0/cc-runtime.git \
|
||||
cc-runtime \
|
||||
576a01179f3298a4795b92f42c088f9f8800b56b
|
||||
https://codeberg.org/mintsuki/flanterm \
|
||||
src/deps/flanterm \
|
||||
bdecdcb1b7dad05ab5249e2c3e4d2c27a661e864
|
||||
|
||||
clone_repo_commit \
|
||||
https://codeberg.org/osdev/freestnd-c-hdrs-0bsd.git \
|
||||
src/deps/freestnd-c-hdrs \
|
||||
a87c192f3eb66b0806740dc67325f9ad23fc2d0b
|
||||
|
||||
download_by_hash \
|
||||
https://codeberg.org/osdev/cc-runtime/raw/commit/d5425655388977fa12ff9b903e554a20b20c426e/cc-runtime.c \
|
||||
src/deps/cc-runtime.c \
|
||||
60bb1af4f6541077b736f19bf0f5a22b5dd8a2f3bed0d9d9d89846a33ef24b74
|
||||
|
||||
download_by_hash \
|
||||
https://github.com/limine-bootloader/limine/raw/4687a182be23939c2d9f15db970382dc353ed956/limine.h \
|
||||
src/limine.h \
|
||||
src/deps/limine.h \
|
||||
6879e626f34c1be25ac2f72bf43b083fc2b53887280bb0fcdaee790e258c6974
|
||||
|
||||
download_by_hash \
|
||||
https://github.com/charlesnicholson/nanoprintf/raw/49628bd79977478dbd7c9a1b5277c44e5d49b118/nanoprintf.h \
|
||||
src/deps/npf.h \
|
||||
ef496c71868b3942695f63e0215da9d25ebdfa21569c854950e8f91adb9e0bea
|
0
kernel/linker-aarch64.ld
Executable file → Normal file
0
kernel/linker-aarch64.ld
Executable file → Normal file
0
kernel/linker-loongarch64.ld
Executable file → Normal file
0
kernel/linker-loongarch64.ld
Executable file → Normal file
0
kernel/linker-riscv64.ld
Executable file → Normal file
0
kernel/linker-riscv64.ld
Executable file → Normal file
28
kernel/linker-x86_64.ld
Executable file → Normal file
28
kernel/linker-x86_64.ld
Executable file → Normal file
|
@ -23,45 +23,32 @@ SECTIONS
|
|||
/* that is the beginning of the region. */
|
||||
. = 0xffffffff80000000;
|
||||
|
||||
|
||||
.text : {
|
||||
text_start_ld = .;
|
||||
*(.text .text.*)
|
||||
text_end_ld = .;
|
||||
} :text
|
||||
|
||||
/* Move to the next memory page for .limine_requests */
|
||||
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
/* Define a section to contain the Limine requests and assign it to its own PHDR */
|
||||
.limine_requests : {
|
||||
reqs_start_ld = .;
|
||||
KEEP(*(.limine_requests_start))
|
||||
KEEP(*(.limine_requests))
|
||||
KEEP(*(.limine_requests_end))
|
||||
reqs_end_ld = .;
|
||||
} :limine_requests
|
||||
|
||||
/* Move to the next memory page for .text */
|
||||
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
.text : {
|
||||
*(.text .text.*)
|
||||
} :text
|
||||
|
||||
/* Move to the next memory page for .rodata */
|
||||
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
.rodata : {
|
||||
rodata_start_ld = .;
|
||||
*(.rodata .rodata.*)
|
||||
rodata_end_ld = .;
|
||||
} :rodata
|
||||
|
||||
/* Move to the next memory page for .data */
|
||||
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
.data : {
|
||||
data_start_ld = .;
|
||||
*(.data .data.*)
|
||||
|
||||
/* Exported kernel symbols */
|
||||
__start_ksyms = .;
|
||||
KEEP(*(.ksyms))
|
||||
__stop_ksyms = .;
|
||||
} :data
|
||||
|
||||
/* NOTE: .bss needs to be the last thing mapped to :data, otherwise lots of */
|
||||
|
@ -71,7 +58,6 @@ SECTIONS
|
|||
.bss : {
|
||||
*(.bss .bss.*)
|
||||
*(COMMON)
|
||||
data_end_ld = .;
|
||||
} :data
|
||||
|
||||
/* Discard .note.* and .eh_frame* since they may cause issues on some hosts. */
|
||||
|
|
11
kernel/src/arch/aarch64/cpu.c
Normal file
11
kernel/src/arch/aarch64/cpu.c
Normal file
|
@ -0,0 +1,11 @@
|
|||
#if defined (__aarch64__)
|
||||
|
||||
#include <arch/cpu.h>
|
||||
|
||||
void hcf() {
|
||||
for (;;) {
|
||||
asm ("wfi");
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,5 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#define ENSURE_X86_64 #ifdef __x86_64__
|
||||
|
||||
#define ENDENSURE
|
4
kernel/src/arch/cpu.h
Normal file
4
kernel/src/arch/cpu.h
Normal file
|
@ -0,0 +1,4 @@
|
|||
#pragma once
|
||||
|
||||
// Disable interrupts and halt the system.
|
||||
void hcf();
|
11
kernel/src/arch/la64/cpu.c
Normal file
11
kernel/src/arch/la64/cpu.c
Normal file
|
@ -0,0 +1,11 @@
|
|||
#if defined (__loongarch64)
|
||||
|
||||
#include <arch/cpu.h>
|
||||
|
||||
void hcf() {
|
||||
for (;;) {
|
||||
asm ("idle 0");
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
11
kernel/src/arch/riscv/cpu.c
Normal file
11
kernel/src/arch/riscv/cpu.c
Normal file
|
@ -0,0 +1,11 @@
|
|||
#if defined (__riscv)
|
||||
|
||||
#include <arch/cpu.h>
|
||||
|
||||
void hcf() {
|
||||
for (;;) {
|
||||
asm ("wfi");
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
12
kernel/src/arch/x86_64/cpu.c
Normal file
12
kernel/src/arch/x86_64/cpu.c
Normal file
|
@ -0,0 +1,12 @@
|
|||
#if defined (__x86_64__)
|
||||
|
||||
#include <arch/cpu.h>
|
||||
|
||||
void hcf() {
|
||||
asm ("cli");
|
||||
for (;;) {
|
||||
asm ("hlt");
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,647 +0,0 @@
|
|||
#ifndef __CPUID_H__
|
||||
#define __CPUID_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
//=================CPUID_VENDOR=================
|
||||
#define CPUID_VENDOR_INTEL "GenuineIntel"
|
||||
#define CPUID_VENDOR_AMD "AuthenticAMD"
|
||||
|
||||
//================CPUID_CPU_INFO================
|
||||
#define CPUID_CPU_INFO_EAX_STEPPING_MASK 0xF
|
||||
#define CPUID_CPU_INFO_EAX_MODEL_MASK 0xF << 4
|
||||
#define CPUID_CPU_INFO_EAX_FAMILY_MASK 0xF << 8
|
||||
#define CPUID_CPU_INFO_EAX_TYPE_MASK 0x3 << 12
|
||||
#define CPUID_CPU_INFO_EAX_EXT_MODEL_MASK 0xF << 16
|
||||
#define CPUID_CPU_INFO_EAX_EXT_FAMILY_MASK 0xFF << 20
|
||||
|
||||
#define CPUID_CPU_INFO_EBX_BRAND_INDEX 0xFF
|
||||
#define CPUID_CPU_INFO_EBX_CFLUSH_SIZE 0xFF << 8
|
||||
#define CPUID_CPU_INFO_EBX_MAX_LOGPROC 0xFF << 16
|
||||
#define CPUID_CPU_INFO_EBX_INIT_APIC_ID 0xFF << 25
|
||||
|
||||
#define CPUID_CPU_INFO_ECX_SSE3 1 << 0
|
||||
#define CPUID_CPU_INFO_ECX_PCLMULQDQ 1 << 1
|
||||
#define CPUID_CPU_INFO_ECX_DTES64 1 << 2
|
||||
#define CPUID_CPU_INFO_ECX_MONITOR 1 << 3
|
||||
#define CPUID_CPU_INFO_ECX_DS_CPL 1 << 4
|
||||
#define CPUID_CPU_INFO_ECX_VMX 1 << 5
|
||||
#define CPUID_CPU_INFO_ECX_SMX 1 << 6
|
||||
#define CPUID_CPU_INFO_ECX_EIST 1 << 7
|
||||
#define CPUID_CPU_INFO_ECX_TM2 1 << 8
|
||||
#define CPUID_CPU_INFO_ECX_SSSE3 1 << 9
|
||||
#define CPUID_CPU_INFO_ECX_CNXT_ID 1 << 10
|
||||
#define CPUID_CPU_INFO_ECX_SDBG 1 << 11
|
||||
#define CPUID_CPU_INFO_ECX_FMA 1 << 12
|
||||
#define CPUID_CPU_INFO_ECX_CMPXCHG16B 1 << 13
|
||||
#define CPUID_CPU_INFO_ECX_XTPR_UC 1 << 14
|
||||
#define CPUID_CPU_INFO_ECX_PDCM 1 << 15
|
||||
// bit 16 is reserved
|
||||
#define CPUID_CPU_INFO_ECX_PCID 1 << 17
|
||||
#define CPUID_CPU_INFO_ECX_DCA 1 << 18
|
||||
#define CPUID_CPU_INFO_ECX_SSE4_1 1 << 19
|
||||
#define CPUID_CPU_INFO_ECX_SSE4_2 1 << 20
|
||||
#define CPUID_CPU_INFO_ECX_X2APIC 1 << 21
|
||||
#define CPUID_CPU_INFO_ECX_MOVBE 1 << 22
|
||||
#define CPUID_CPU_INFO_ECX_POPCNT 1 << 23
|
||||
#define CPUID_CPU_INFO_ECX_TSC_DEADLINE 1 << 24
|
||||
#define CPUID_CPU_INFO_ECX_AESNI 1 << 25
|
||||
#define CPUID_CPU_INFO_ECX_XSAVE 1 << 26
|
||||
#define CPUID_CPU_INFO_ECX_OSXSAVE 1 << 27
|
||||
#define CPUID_CPU_INFO_ECX_AVX 1 << 28
|
||||
#define CPUID_CPU_INFO_ECX_F16C 1 << 29
|
||||
#define CPUID_CPU_INFO_ECX_RDRAND 1 << 30
|
||||
// bit 31 is unused
|
||||
|
||||
#define CPUID_CPU_INFO_EDX_FPU 1 << 0
|
||||
#define CPUID_CPU_INFO_EDX_VME 1 << 1
|
||||
#define CPUID_CPU_INFO_EDX_DE 1 << 2
|
||||
#define CPUID_CPU_INFO_EDX_PSE 1 << 3
|
||||
#define CPUID_CPU_INFO_EDX_TSC 1 << 4
|
||||
#define CPUID_CPU_INFO_EDX_MSR 1 << 5
|
||||
#define CPUID_CPU_INFO_EDX_PAE 1 << 6
|
||||
#define CPUID_CPU_INFO_EDX_MCE 1 << 7
|
||||
#define CPUID_CPU_INFO_EDX_CX8 1 << 8
|
||||
#define CPUID_CPU_INFO_EDX_APIC 1 << 9
|
||||
// bit 10 is reserved
|
||||
#define CPUID_CPU_INFO_EDX_SEP 1 << 11
|
||||
#define CPUID_CPU_INFO_EDX_MTRR 1 << 12
|
||||
#define CPUID_CPU_INFO_EDX_PGE 1 << 13
|
||||
#define CPUID_CPU_INFO_EDX_MCA 1 << 14
|
||||
#define CPUID_CPU_INFO_EDX_CMOV 1 << 15
|
||||
#define CPUID_CPU_INFO_EDX_PAT 1 << 16
|
||||
#define CPUID_CPU_INFO_EDX_PSE_36 1 << 17
|
||||
#define CPUID_CPU_INFO_EDX_PSN 1 << 18
|
||||
#define CPUID_CPU_INFO_EDX_CLFSH 1 << 19
|
||||
// bit 20 is reserved
|
||||
#define CPUID_CPU_INFO_EDX_DS 1 << 21
|
||||
#define CPUID_CPU_INFO_EDX_ACPI 1 << 22
|
||||
#define CPUID_CPU_INFO_EDX_MMX 1 << 23
|
||||
#define CPUID_CPU_INFO_EDX_FXSR 1 << 24
|
||||
#define CPUID_CPU_INFO_EDX_SSE 1 << 25
|
||||
#define CPUID_CPU_INFO_EDX_SSE2 1 << 26
|
||||
#define CPUID_CPU_INFO_EDX_SS 1 << 27
|
||||
#define CPUID_CPU_INFO_EDX_HTT 1 << 28
|
||||
#define CPUID_CPU_INFO_EDX_TM 1 << 29
|
||||
// bit 30 is reserved
|
||||
#define CPUID_CPU_INFO_EDX_PBE 1 << 31
|
||||
|
||||
//===============CPUID_CACHE_TLB===============
|
||||
// WARNING: I gave up and used ChatGPT for these
|
||||
#define CPUID_CACHE_TLB_DESC_NULL 0x00
|
||||
#define CPUID_CACHE_TLB_DESC_TLB_4_KBYTE_4WAY_32E 0x01
|
||||
#define CPUID_CACHE_TLB_DESC_TLB_4_MBYTE_FULLY_2E 0x02
|
||||
#define CPUID_CACHE_TLB_DESC_DTLB_4_KBYTE_4WAY_64E 0x03
|
||||
#define CPUID_CACHE_TLB_DESC_DTLB_4_MBYTE_4WAY_8E 0x04
|
||||
#define CPUID_CACHE_TLB_DESC_DTLB1_4_MBYTE_4WAY_32E 0x05
|
||||
#define CPUID_CACHE_TLB_DESC_L1_INST_8K_4WAY_32B 0x06
|
||||
#define CPUID_CACHE_TLB_DESC_L1_INST_16K_4WAY_32B 0x08
|
||||
#define CPUID_CACHE_TLB_DESC_L1_INST_32K_4WAY_64B 0x09
|
||||
#define CPUID_CACHE_TLB_DESC_L1_DATA_8K_2WAY_32B 0x0A
|
||||
#define CPUID_CACHE_TLB_DESC_TLB_4_MBYTE_4WAY_4E 0x0B
|
||||
#define CPUID_CACHE_TLB_DESC_L1_DATA_16K_4WAY_32B 0x0C
|
||||
#define CPUID_CACHE_TLB_DESC_L1_DATA_16K_4WAY_64B 0x0D
|
||||
#define CPUID_CACHE_TLB_DESC_L1_DATA_24K_6WAY_64B 0x0E
|
||||
#define CPUID_CACHE_TLB_DESC_L2_128K_2WAY_64B 0x1D
|
||||
#define CPUID_CACHE_TLB_DESC_L2_256K_8WAY_64B 0x21
|
||||
#define CPUID_CACHE_TLB_DESC_L3_512K_4WAY_64B_2LPS 0x22
|
||||
#define CPUID_CACHE_TLB_DESC_L3_1M_8WAY_64B_2LPS 0x23
|
||||
#define CPUID_CACHE_TLB_DESC_L2_1M_16WAY_64B 0x24
|
||||
#define CPUID_CACHE_TLB_DESC_L3_2M_8WAY_64B_2LPS 0x25
|
||||
#define CPUID_CACHE_TLB_DESC_L3_4M_8WAY_64B_2LPS 0x29
|
||||
#define CPUID_CACHE_TLB_DESC_L1_DATA_32K_8WAY_64B 0x2C
|
||||
#define CPUID_CACHE_TLB_DESC_L1_INST_32K_8WAY_64B 0x30
|
||||
#define CPUID_CACHE_TLB_DESC_NO_L2_OR_L3 0x40
|
||||
#define CPUID_CACHE_TLB_DESC_L2_128K_4WAY_32B 0x41
|
||||
#define CPUID_CACHE_TLB_DESC_L2_256K_4WAY_32B 0x42
|
||||
#define CPUID_CACHE_TLB_DESC_L2_512K_4WAY_32B 0x43
|
||||
#define CPUID_CACHE_TLB_DESC_L2_1M_4WAY_32B 0x44
|
||||
#define CPUID_CACHE_TLB_DESC_L2_2M_4WAY_32B 0x45
|
||||
#define CPUID_CACHE_TLB_DESC_L3_4M_4WAY_64B 0x46
|
||||
#define CPUID_CACHE_TLB_DESC_L3_8M_8WAY_64B 0x47
|
||||
#define CPUID_CACHE_TLB_DESC_L2_3M_12WAY_64B 0x48
|
||||
#define CPUID_CACHE_TLB_DESC_L3_4M_16WAY_64B 0x49
|
||||
#define CPUID_CACHE_TLB_DESC_L3_6M_12WAY_64B 0x4A
|
||||
#define CPUID_CACHE_TLB_DESC_L3_8M_16WAY_64B 0x4B
|
||||
#define CPUID_CACHE_TLB_DESC_L3_12M_12WAY_64B 0x4C
|
||||
#define CPUID_CACHE_TLB_DESC_L3_16M_16WAY_64B 0x4D
|
||||
#define CPUID_CACHE_TLB_DESC_L2_6M_24WAY_64B 0x4E
|
||||
#define CPUID_CACHE_TLB_DESC_TLB_INST_4K_32E 0x4F
|
||||
#define CPUID_CACHE_TLB_DESC_TLB_INST_4K_2M_4M_64E 0x50
|
||||
#define CPUID_CACHE_TLB_DESC_TLB_INST_4K_2M_4M_128E 0x51
|
||||
#define CPUID_CACHE_TLB_DESC_TLB_INST_4K_2M_4M_256E 0x52
|
||||
#define CPUID_CACHE_TLB_DESC_TLB_INST_2M_4M_FULLY_7E 0x55
|
||||
#define CPUID_CACHE_TLB_DESC_DTLB0_4M_4WAY_16E 0x56
|
||||
#define CPUID_CACHE_TLB_DESC_DTLB0_4K_4WAY_16E 0x57
|
||||
#define CPUID_CACHE_TLB_DESC_DTLB0_4K_FULLY_16E 0x59
|
||||
#define CPUID_CACHE_TLB_DESC_DTLB0_2M_4M_4WAY_32E 0x5A
|
||||
#define CPUID_CACHE_TLB_DESC_DTLB_4K_4M_64E 0x5B
|
||||
#define CPUID_CACHE_TLB_DESC_DTLB_4K_4M_128E 0x5C
|
||||
#define CPUID_CACHE_TLB_DESC_DTLB_4K_4M_256E 0x5D
|
||||
#define CPUID_CACHE_TLB_DESC_L1_DATA_16K_8WAY_64B 0x60
|
||||
#define CPUID_CACHE_TLB_DESC_TLB_INST_4K_FULLY_48E 0x61
|
||||
#define CPUID_CACHE_TLB_DESC_DTLB_2M_4M_32E_1G_4WAY_4E 0x63
|
||||
#define CPUID_CACHE_TLB_DESC_DTLB_4K_4WAY_512E 0x64
|
||||
#define CPUID_CACHE_TLB_DESC_L1_DATA_8K_4WAY_64B 0x66
|
||||
#define CPUID_CACHE_TLB_DESC_L1_DATA_16K_4WAY_64B_DUPLICATE 0x67 //????????????
|
||||
#define CPUID_CACHE_TLB_DESC_L1_DATA_32K_4WAY_64B 0x68
|
||||
#define CPUID_CACHE_TLB_DESC_UTLB_4K_8WAY_64E 0x6A
|
||||
#define CPUID_CACHE_TLB_DESC_DTLB_4K_8WAY_256E 0x6B
|
||||
#define CPUID_CACHE_TLB_DESC_DTLB_2M_4M_8WAY_128E 0x6C
|
||||
#define CPUID_CACHE_TLB_DESC_DTLB_1G_FULLY_16E 0x6D
|
||||
#define CPUID_CACHE_TLB_DESC_TRACE_12K_8WAY 0x70
|
||||
#define CPUID_CACHE_TLB_DESC_TRACE_16K_8WAY 0x71
|
||||
#define CPUID_CACHE_TLB_DESC_TRACE_32K_8WAY 0x72
|
||||
#define CPUID_CACHE_TLB_DESC_TLB_INST_2M_4M_FULLY_8E 0x76
|
||||
#define CPUID_CACHE_TLB_DESC_L2_1M_4WAY_64B 0x78
|
||||
#define CPUID_CACHE_TLB_DESC_L2_128K_8WAY_64B_2LPS 0x79
|
||||
#define CPUID_CACHE_TLB_DESC_L2_256K_8WAY_64B_2LPS 0x7A
|
||||
#define CPUID_CACHE_TLB_DESC_L2_512K_8WAY_64B_2LPS 0x7B
|
||||
#define CPUID_CACHE_TLB_DESC_L2_1M_8WAY_64B_2LPS 0x7C
|
||||
#define CPUID_CACHE_TLB_DESC_L2_2M_8WAY_64B 0x7D
|
||||
#define CPUID_CACHE_TLB_DESC_L2_512K_2WAY_64B 0x7F
|
||||
#define CPUID_CACHE_TLB_DESC_L2_512K_8WAY_64B 0x80
|
||||
#define CPUID_CACHE_TLB_DESC_L2_256K_8WAY_32B 0x82
|
||||
#define CPUID_CACHE_TLB_DESC_L2_512K_8WAY_32B 0x83
|
||||
#define CPUID_CACHE_TLB_DESC_L2_1M_8WAY_32B 0x84
|
||||
#define CPUID_CACHE_TLB_DESC_L2_2M_8WAY_32B 0x85
|
||||
#define CPUID_CACHE_TLB_DESC_L2_512K_4WAY_64B 0x86
|
||||
#define CPUID_CACHE_TLB_DESC_L2_1M_8WAY_64B 0x87
|
||||
#define CPUID_CACHE_TLB_DESC_DTLB_4K_FULLY_ASSOC_32E 0xA0
|
||||
#define CPUID_CACHE_TLB_DESC_TLB_INST_4K_4WAY_128E 0xB0
|
||||
#define CPUID_CACHE_TLB_DESC_TLB_INST_2M_4WAY_8E_4M_4WAY_4E 0xB1
|
||||
#define CPUID_CACHE_TLB_DESC_TLB_INST_4K_4WAY_64E 0xB2
|
||||
#define CPUID_CACHE_TLB_DESC_TLB_DATA_4K_4WAY_128E 0xB3
|
||||
#define CPUID_CACHE_TLB_DESC_TLB_DATA_4K_4WAY_256E 0xB4
|
||||
#define CPUID_CACHE_TLB_DESC_TLB_INST_4K_8WAY_64E 0xB5
|
||||
#define CPUID_CACHE_TLB_DESC_TLB_INST_4K_8WAY_128E 0xB6
|
||||
#define CPUID_CACHE_TLB_DESC_TLB_DATA_4K_4WAY_64E 0xBA
|
||||
#define CPUID_CACHE_TLB_DESC_TLB_DATA_4K_4M_4WAY_8E 0xC0
|
||||
#define CPUID_CACHE_TLB_DESC_STLB_2ND_LEVEL_4K_2M_8WAY_1024E 0xC1
|
||||
#define CPUID_CACHE_TLB_DESC_DTLB_4K_2M_4WAY_16E 0xC2
|
||||
#define CPUID_CACHE_TLB_DESC_STLB_2ND_LEVEL_4K_2M_6WAY_1536E_1GB_4WAY_16E 0xC3
|
||||
#define CPUID_CACHE_TLB_DESC_DTLB_2M_4M_4WAY_32E 0xC4
|
||||
#define CPUID_CACHE_TLB_DESC_STLB_2ND_LEVEL_4K_4WAY_512E 0xCA
|
||||
#define CPUID_CACHE_TLB_DESC_CACHE_3RD_LEVEL_512KB_4WAY_64B_LINE 0xD0
|
||||
#define CPUID_CACHE_TLB_DESC_CACHE_3RD_LEVEL_1MB_4WAY_64B_LINE 0xD1
|
||||
#define CPUID_CACHE_TLB_DESC_CACHE_3RD_LEVEL_2MB_4WAY_64B_LINE 0xD2
|
||||
#define CPUID_CACHE_TLB_DESC_CACHE_3RD_LEVEL_1MB_8WAY_64B_LINE 0xD6
|
||||
#define CPUID_CACHE_TLB_DESC_CACHE_3RD_LEVEL_2MB_8WAY_64B_LINE 0xD7
|
||||
#define CPUID_CACHE_TLB_DESC_CACHE_3RD_LEVEL_4MB_8WAY_64B_LINE 0xD8
|
||||
#define CPUID_CACHE_TLB_DESC_CACHE_3RD_LEVEL_1_5MB_12WAY_64B_LINE 0xDC
|
||||
#define CPUID_CACHE_TLB_DESC_CACHE_3RD_LEVEL_3MB_12WAY_64B_LINE 0xDD
|
||||
#define CPUID_CACHE_TLB_DESC_CACHE_3RD_LEVEL_6MB_12WAY_64B_LINE 0xDE
|
||||
#define CPUID_CACHE_TLB_DESC_CACHE_3RD_LEVEL_2MB_16WAY_64B_LINE 0xE2
|
||||
#define CPUID_CACHE_TLB_DESC_CACHE_3RD_LEVEL_4MB_16WAY_64B_LINE 0xE3
|
||||
#define CPUID_CACHE_TLB_DESC_CACHE_3RD_LEVEL_8MB_16WAY_64B_LINE 0xE4
|
||||
#define CPUID_CACHE_TLB_DESC_CACHE_3RD_LEVEL_12MB_24WAY_64B_LINE 0xEA
|
||||
#define CPUID_CACHE_TLB_DESC_CACHE_3RD_LEVEL_18MB_24WAY_64B_LINE 0xEB
|
||||
#define CPUID_CACHE_TLB_DESC_CACHE_3RD_LEVEL_24MB_24WAY_64B_LINE 0xEC
|
||||
#define CPUID_CACHE_TLB_DESC_PREFETCH_64_BYTE 0xF0
|
||||
#define CPUID_CACHE_TLB_DESC_PREFETCH_128_BYTE 0xF1
|
||||
#define CPUID_CACHE_TLB_DESC_NO_TLB_INFO_CPUID_LEAF_18H 0xFE
|
||||
#define CPUID_CACHE_TLB_DESC_NO_CACHE_INFO_CPUID_LEAF_4 0xFF
|
||||
|
||||
//=============CPUID_SERIAL_NUMBER=============
|
||||
#define CPUID_SERIAL_NUMBER_STITCH(ECX, EDX) (uint64_t)((EDX << 32) | ECX)
|
||||
|
||||
//=============CPUID_CACHE_PARAMS==============
|
||||
#define CPUID_CACHE_PARAMS_EAX_CACHE_TYPE 0xF
|
||||
#define CPUID_CACHE_PARAMS_EAX_CACHE_LEVEL 0x7 << 4
|
||||
#define CPUID_CACHE_PARAMS_EAX_IS_SELF_INIT 1 << 8
|
||||
#define CPUID_CACHE_PARAMS_EAX_IS_FULLY_ASSOCIATIVE 1 << 9
|
||||
// bits 10-13 are reserved
|
||||
#define CPUID_CACHE_PARAMS_EAX_MAX_PROC_SHARING 0xFFF << 14
|
||||
|
||||
#define CPUID_CACHE_PARAMS_EAX_CACHE_TYPE_NULL 0x0
|
||||
#define CPUID_CACHE_PARAMS_EAX_CACHE_TYPE_DATA 0x1
|
||||
#define CPUID_CACHE_PARAMS_EAX_CACHE_TYPE_INSTRUCTION 0x2
|
||||
#define CPUID_CACHE_PARAMS_EAX_CACHE_TYPE_UNIFIED 0x3
|
||||
|
||||
#define CPUID_CACHE_PARAMS_EBX_COHERENCY_LINE_SIZE 0xFFF
|
||||
#define CPUID_CACHE_PARAMS_EBX_PHYS_LINE_PARTITIONS 0x3FF << 12
|
||||
#define CPUID_CACHE_PARAMS_EBX_WAYS_OF_ASSOCIVITY 0x3FF
|
||||
|
||||
#define CPUID_CACHE_PARAMS_EDX_CACHE_INCLUSIVENESS 1
|
||||
#define CPUID_CACHE_PARAMS_EDX_COMPLEX_CACHE_INDEXING 1 << 1
|
||||
|
||||
//=============CPUID_MONITOR_MWAIT=============
|
||||
#define CPUID_MONITOR_MWAIT_ECX_ENUM_EXTENSIONS 1
|
||||
#define CPUID_MONITOR_MWAIT_ECX_BREAK_EVENTS 1 << 1
|
||||
|
||||
#define CPUID_MONITOR_MWAIT_EDX_C0_SUBC_STATES 0xF
|
||||
#define CPUID_MONITOR_MWAIT_EDX_C1_SUBC_STATES 0xF << 4
|
||||
#define CPUID_MONITOR_MWAIT_EDX_C2_SUBC_STATES 0xF << 8
|
||||
#define CPUID_MONITOR_MWAIT_EDX_C3_SUBC_STATES 0xF << 12
|
||||
#define CPUID_MONITOR_MWAIT_EDX_C4_SUBC_STATES 0xF << 16
|
||||
#define CPUID_MONITOR_MWAIT_EDX_C5_SUBC_STATES 0xF << 20
|
||||
#define CPUID_MONITOR_MWAIT_EDX_C6_SUBC_STATES 0xF << 24
|
||||
#define CPUID_MONITOR_MWAIT_EDX_C7_SUBC_STATES 0xF << 28
|
||||
|
||||
//===========CPUID_THERMAL_AND_POWER===========
|
||||
#define CPUID_THERMAL_AND_POWER_EAX_TEMP_SENSOR 1
|
||||
#define CPUID_THERMAL_AND_POWER_EAX_TURBO_BOOST 1 << 1
|
||||
#define CPUID_THERMAL_AND_POWER_EAX_ARAT 1 << 2
|
||||
// Bit 3 is reserved
|
||||
#define CPUID_THERMAL_AND_POWER_EAX_PLN 1 << 3
|
||||
#define CPUID_THERMAL_AND_POWER_EAX_ECMD 1 << 5
|
||||
#define CPUID_THERMAL_AND_POWER_EAX_PTM 1 << 6
|
||||
#define CPUID_THERMAL_AND_POWER_EAX_HWP 1 << 7
|
||||
#define CPUID_THERMAL_AND_POWER_EAX_HWP_NOTIFICATION 1 << 8
|
||||
#define CPUID_THERMAL_AND_POWER_EAX_HWP_ACT_WINDOW 1 << 9
|
||||
#define CPUID_THERMAL_AND_POWER_EAX_HWP_PERF_PREF 1 << 10
|
||||
#define CPUID_THERMAL_AND_POWER_EAX_HWP_PKG_LVL_REQ 1 << 11
|
||||
// Bit 12 is reserved
|
||||
#define CPUID_THERMAL_AND_POWER_EAX_HDC 1 << 13
|
||||
#define CPUID_THERMAL_AND_POWER_EAX_TURBO_BOOST_MAX 1 << 14
|
||||
#define CPUID_THERMAL_AND_POWER_EAX_HWP_CAPABILITIES 1 << 15
|
||||
#define CPUID_THERMAL_AND_POWER_EAX_HWP_PECI 1 << 16
|
||||
#define CPUID_THERMAL_AND_POWER_EAX_FLEXIBLE_HWP 1 << 17
|
||||
#define CPUID_THERMAL_AND_POWER_EAX_FAST_HWP_REQUEST 1 << 18
|
||||
#define CPUID_THERMAL_AND_POWER_EAX_HW_FEEDBACK 1 << 19
|
||||
#define CPUID_THERMAL_AND_POWER_EAX_IGNORE_HWP_IDLE 1 << 20
|
||||
// Bits 21 and 22 are reserved
|
||||
#define CPUID_THERMAL_AND_POWER_EAX_THREAD_DIRECTOR 1 << 23
|
||||
#define CPUID_THERMAL_AND_POWER_EAX_THERM_INTERRUPT 1 << 24
|
||||
|
||||
#define CPUID_THERMAL_AND_POWER_EBX_INT_TRESHOLD 0xf
|
||||
|
||||
#define CPUID_THERMAL_AND_POWER_ECX_HW_COORD_FEEDBACK 1
|
||||
#define CPUID_THERMAL_AND_POWER_ECX_ENERGY_PERF_BIAS 1 << 3
|
||||
#define CPUID_THERMAL_AND_POWER_ECX_TD_CLASSES 0xff << 8
|
||||
|
||||
#define CPUID_THERMAL_AND_POWER_EDX_PERF_REPORT 1
|
||||
#define CPUID_THERMAL_AND_POWER_EDX_EFFICIENCY_REPORT 1 << 1
|
||||
#define CPUID_THERMAL_AND_POWER_EDX_HW_FEEDBACK_SIZE 0xf << 8
|
||||
#define CPUID_THERMAL_AND_POWER_EDX_THIS_PROC_HW_FB 0xffff << 16
|
||||
|
||||
//===========CPUID_EXTENDED_FEATURES===========
|
||||
#define CPUID_EXTENDED_FEATURES_EBX_FSGSBASE 1
|
||||
#define CPUID_EXTENDED_FEATURES_EBX_TSC_ADJUST 1 << 1
|
||||
#define CPUID_EXTENDED_FEATURES_EBX_SGX 1 << 2
|
||||
#define CPUID_EXTENDED_FEATURES_EBX_BMI1 1 << 3
|
||||
#define CPUID_EXTENDED_FEATURES_EBX_HLE 1 << 4
|
||||
#define CPUID_EXTENDED_FEATURES_EBX_AVX2 1 << 5
|
||||
#define CPUID_EXTENDED_FEATURES_EBX_FDP_EXCPTN_ONLY 1 << 6
|
||||
#define CPUID_EXTENDED_FEATURES_EBX_SMEP 1 << 7
|
||||
#define CPUID_EXTENDED_FEATURES_EBX_BMI2 1 << 8
|
||||
#define CPUID_EXTENDED_FEATURES_EBX_ENHANCED_REP 1 << 9
|
||||
#define CPUID_EXTENDED_FEATURES_EBX_INVCIP 1 << 10
|
||||
#define CPUID_EXTENDED_FEATURES_EBX_RTM 1 << 11
|
||||
#define CPUID_EXTENDED_FEATURES_EBX_RDT_M 1 << 12
|
||||
#define CPUID_EXTENDED_FEATURES_EBX_NO_FPU_CS 1 << 13
|
||||
#define CPUID_EXTENDED_FEATURES_EBX_MPX 1 << 14
|
||||
#define CPUID_EXTENDED_FEATURES_EBX_RDT_A 1 << 15
|
||||
#define CPUID_EXTENDED_FEATURES_EBX_AVX512F 1 << 16
|
||||
#define CPUID_EXTENDED_FEATURES_EBX_AVX512DQ 1 << 17
|
||||
#define CPUID_EXTENDED_FEATURES_EBX_RDSEED 1 << 18
|
||||
#define CPUID_EXTENDED_FEATURES_EBX_ADX 1 << 19
|
||||
#define CPUID_EXTENDED_FEATURES_EBX_SMAP 1 << 20
|
||||
#define CPUID_EXTENDED_FEATURES_EBX_AVX512_IFMA 1 << 21
|
||||
// Bit 22 is reserved
|
||||
#define CPUID_EXTENDED_FEATURES_EBX_CLFLUSHOPT 1 << 23
|
||||
#define CPUID_EXTENDED_FEATURES_EBX_CLWB 1 << 24
|
||||
#define CPUID_EXTENDED_FEATURES_EBX_TRACE 1 << 25
|
||||
#define CPUID_EXTENDED_FEATURES_EBX_AVX512PF 1 << 26
|
||||
#define CPUID_EXTENDED_FEATURES_EBX_AVX512ER 1 << 27
|
||||
#define CPUID_EXTENDED_FEATURES_EBX_AVX512CD 1 << 28
|
||||
#define CPUID_EXTENDED_FEATURES_EBX_SHA 1 << 29
|
||||
#define CPUID_EXTENDED_FEATURES_EBX_AVX512BW 1 << 30
|
||||
#define CPUID_EXTENDED_FEATURES_EBX_AVX512VL 1 << 31
|
||||
|
||||
#define CPUID_EXTENDED_FEATURES_ECX_PREFETCHWT1 1
|
||||
#define CPUID_EXTENDED_FEATURES_ECX_AFX512_VBMI 1 << 1
|
||||
#define CPUID_EXTENDED_FEATURES_ECX_UMIP 1 << 2
|
||||
#define CPUID_EXTENDED_FEATURES_ECX_PKU 1 << 3
|
||||
#define CPUID_EXTENDED_FEATURES_ECX_OSPKE 1 << 4
|
||||
#define CPUID_EXTENDED_FEATURES_ECX_WAITPKG 1 << 5
|
||||
#define CPUID_EXTENDED_FEATURES_ECX_AVX512_VBMI2 1 << 6
|
||||
#define CPUID_EXTENDED_FEATURES_ECX_CET_SS 1 << 7
|
||||
#define CPUID_EXTENDED_FEATURES_ECX_GFNI 1 << 8
|
||||
#define CPUID_EXTENDED_FEATURES_ECX_VAES 1 << 9
|
||||
#define CPUID_EXTENDED_FEATURES_ECX_VPCLMULQDQ 1 << 10
|
||||
#define CPUID_EXTENDED_FEATURES_ECX_AVX512_VNNI 1 << 11
|
||||
#define CPUID_EXTENDED_FEATURES_ECX_AVX512_BITLANG 1 << 12
|
||||
#define CPUID_EXTENDED_FEATURES_ECX_TME_EN 1 << 13
|
||||
#define CPUID_EXTENDED_FEATURES_ECX_AVX512_VPOPVNZDQ 1 << 14
|
||||
// bit 15 is reserved
|
||||
#define CPUID_EXTENDED_FEATURES_ECX_LA57 1 << 16
|
||||
#define CPUID_EXTENDED_FEATURES_ECX_MAWAU_VAL 0x1F << 17
|
||||
#define CPUID_EXTENDED_FEATURES_ECX_RDPID 1 << 22
|
||||
#define CPUID_EXTENDED_FEATURES_ECX_KL 1 << 23
|
||||
#define CPUID_EXTENDED_FEATURES_ECX_BUS_LOCK_DETECT 1 << 24
|
||||
#define CPUID_EXTENDED_FEATURES_ECX_CLDEMOTE 1 << 25
|
||||
// bit 26 is reserved
|
||||
#define CPUID_EXTENDED_FEATURES_ECX_MOVDIRI 1 << 27
|
||||
#define CPUID_EXTENDED_FEATURES_ECX_MOVDIR64B 1 << 28
|
||||
#define CPUID_EXTENDED_FEATURES_ECX_ENQCMD 1 << 29
|
||||
#define CPUID_EXTENDED_FEATURES_ECX_SGX_LC 1 << 30
|
||||
#define CPUID_EXTENDED_FEATURES_ECX_PKS 1 << 31
|
||||
|
||||
// bit 0 is reserved
|
||||
#define CPUID_EXTENDED_FEATURES_EDX_SGX_KEYS 1 << 1
|
||||
#define CPUID_EXTENDED_FEATURES_EDX_AVX512_4VNNIW 1 << 2
|
||||
#define CPUID_EXTENDED_FEATURES_EDX_AVX512_4FMAPS 1 << 3
|
||||
#define CPUID_EXTENDED_FEATURES_EDX_FAST_REP_MOV 1 << 4
|
||||
#define CPUID_EXTENDED_FEATURES_EDX_UINTR 1 << 5
|
||||
// bits 6 and 7 are reserved
|
||||
#define CPUID_EXTENDED_FEATURES_EDX_AVX512_VPINTERSECT \
|
||||
1 << 8 // intel you son of a bitch
|
||||
#define CPUID_EXTENDED_FEATURES_EDX_SRBDS_CTRL 1 << 9
|
||||
#define CPUID_EXTENDED_FEATURES_EDX_MD_CLEAR 1 << 10
|
||||
#define CPUID_EXTENDED_FEATURES_EDX_RTM_ALWAYS_ABORT 1 << 11
|
||||
// bit 12 is reserved
|
||||
#define CPUID_EXTENDED_FEATURES_EDX_RTM_FORCE_ABORT 1 << 13
|
||||
#define CPUID_EXTENDED_FEATURES_EDX_SERIALIZE 1 << 14
|
||||
#define CPUID_EXTENDED_FEATURES_EDX_HYBRID 1 << 15
|
||||
#define CPUID_EXTENDED_FEATURES_EDX_TSXLDTRK 1 << 16
|
||||
// bit 17 is reserved
|
||||
#define CPUID_EXTENDED_FEATURES_EDX_PCONFIG 1 << 18
|
||||
#define CPUID_EXTENDED_FEATURES_EDX_ARCHITECTURAL_LBR 1 << 19
|
||||
#define CPUID_EXTENDED_FEATURES_EDX_CET_IBT 1 << 20
|
||||
// bit 21 is reserved
|
||||
#define CPUID_EXTENDED_FEATURES_EDX_AMX_BF16 1 << 22
|
||||
#define CPUID_EXTENDED_FEATURES_EDX_AVX512_FP16 1 << 23
|
||||
#define CPUID_EXTENDED_FEATURES_EDX_AMX_TILE 1 << 24
|
||||
#define CPUID_EXTENDED_FEATURES_EDX_AMX_INT8 1 << 25
|
||||
#define CPUID_EXTENDED_FEATURES_EDX_IBRS 1 << 26
|
||||
#define CPUID_EXTENDED_FEATURES_EDX_STIBP 1 << 27
|
||||
#define CPUID_EXTENDED_FEATURES_EDX_L1D_FLUSH 1 << 28
|
||||
#define CPUID_EXTENDED_FEATURES_EDX_ARCH_CAPABS_MSR 1 << 29
|
||||
#define CPUID_EXTENDED_FEATURES_EDX_CORE_CAPABS_MSR 1 << 30
|
||||
#define CPUID_EXTENDED_FEATURES_EDX_SSBD 1 << 31
|
||||
|
||||
//=========CPUID_EXTENDED_FEATURES_SL1=========
|
||||
// bits 0-3 are reserved
|
||||
#define CPUID_EXTENDED_FEATURES_SL1_EAX_AVX_VNNI 1 << 4
|
||||
#define CPUID_EXTENDED_FEATURES_SL1_EAX_AVX512_BF16 1 << 5
|
||||
// bits 6-9 are reserved
|
||||
#define CPUID_EXTENDED_FEATURES_SL1_EAX_0_REP_MOVSB 1 << 10
|
||||
#define CPUID_EXTENDED_FEATURES_SL1_EAX_FAST_STOSB 1 << 11
|
||||
#define CPUID_EXTENDED_FEATURES_SL1_EAX_FAST_CMPSB 1 << 12
|
||||
// bits 13-21 are reserved
|
||||
#define CPUID_EXTENDED_FEATURES_SL1_EAX_HRESET 1 << 22
|
||||
// bits 23-19 are reserved
|
||||
#define CPUID_EXTENDED_FEATURES_SL1_EAX_INVD_POSTPOST 1 << 30
|
||||
// bit 31 is reserved
|
||||
|
||||
#define CPUID_EXTENDED_FEATURES_SL1_EBX_PPIN 1
|
||||
|
||||
#define CPUID_EXTENDED_FEATURES_SL1_EDX_CET_SSS 1 << 18
|
||||
|
||||
//=========CPUID_EXTENDED_FEATURES_SL2=========
|
||||
#define CPUID_EXTENDED_FEATURES_SL2_EDX_PSFD 1
|
||||
#define CPUID_EXTENDED_FEATURES_SL2_EDX_IPRED_CTRL 1 << 1
|
||||
#define CPUID_EXTENDED_FEATURES_SL2_EDX_RRSBA_CTRL 1 << 2
|
||||
#define CPUID_EXTENDED_FEATURES_SL2_EDX_DDPD_U 1 << 3
|
||||
#define CPUID_EXTENDED_FEATURES_SL2_EDX_BHI_CTRL 1 << 4
|
||||
// The rest of the bits are reserved
|
||||
|
||||
enum leaves {
|
||||
/* @ Basic CPU info
|
||||
* @ Returned EAX: Highest basic CPUID leaf present
|
||||
* @ Returned EBX: First 4 letters of the vendor identifier string
|
||||
* @ Returned ECX: Third 4 letters of the vendor identifier string
|
||||
* @ Retruned EDX: Second 4 letters of the vendor identifier string
|
||||
*/
|
||||
CPUID_VENDOR = 0x00000000,
|
||||
/* @ CPU Version information
|
||||
* @ Returned EAX: Family,Model,Stepping
|
||||
* @ Returned EBX: Brand Index,CLFLUSH line size, Max number of logical
|
||||
* processors
|
||||
* @ Returned ECX: Featrue information
|
||||
* @ Retruned EDX: More feature information
|
||||
*/
|
||||
CPUID_CPU_INFO = 0x00000001,
|
||||
/* @ CPU Cache and TLB information
|
||||
* @ Returned EAX: 4 Cache, prefetch or TLB descriptors
|
||||
* @ Returned EBX: 4 Cache, prefetch or TLB descriptors
|
||||
* @ Returned ECX: 4 Cache, prefetch or TLB descriptors
|
||||
* @ Retruned EDX: 4 Cache, prefetch or TLB descriptors
|
||||
*/
|
||||
CPUID_CACHE_TLB = 0x00000002,
|
||||
/* @ CPU Serial Number !!! PENTIUM 3 ONLY !!!
|
||||
* @ Returned EAX: Reserved
|
||||
* @ Returned EBX: Reserved
|
||||
* @ Returned ECX: bits 0-31 of the serial number
|
||||
* @ Retruned EDX: bits 32-63 of the serial number
|
||||
*/
|
||||
CPUID_SERIAL_NUMBER = 0x00000003,
|
||||
/* @ CPU Deterministic cache parameters !!! Initial ECX = Cache level !!!
|
||||
* @ Returned EAX: Cache level,Is self init,Is fully associative,Maximum
|
||||
* number of addressable IDs for logical processors sharing this cache
|
||||
* @ Returned EBX: L, P and W
|
||||
* @ Returned ECX: S
|
||||
* @ Retruned EDX: Cache inclusiveness and Complex Cache indexing
|
||||
*/
|
||||
CPUID_CACHE_PARAMS = 0x00000004,
|
||||
/* @ MONITOR/MWAIT params
|
||||
* @ Returned EAX: Smallest monitor-line size
|
||||
* @ Returned EBX: Largest monitor-line size
|
||||
* @ Returned ECX: Enumeration of Monitor-Mwait extensions,Supports treating
|
||||
* interrupts as break-event for MWAIT
|
||||
* @ Retruned EDX: Number of sub C-states supported using MWAIT for each C
|
||||
* number thingy IDK
|
||||
*/
|
||||
CPUID_MONITOR_MWAIT = 0x00000005,
|
||||
/* @ Thermal and power managment
|
||||
* @ Returned EAX: Thermal and power info
|
||||
* @ Returned EBX: Thermal and power info
|
||||
* @ Returned ECX: Thermal and power info
|
||||
* @ Retruned EDX: Thermal and power info
|
||||
*/
|
||||
CPUID_THERMAL_AND_POWER = 0x00000006,
|
||||
/* @ Extended features
|
||||
* @ Returned EAX: Number of subleaves supported
|
||||
* @ Returned EBX: Features
|
||||
* @ Returned ECX: Features
|
||||
* @ Retruned EDX: Features
|
||||
*/
|
||||
CPUID_EXTENDED_FEATURES = 0x00000007,
|
||||
/* @ Direct Cache Access Information
|
||||
* @ Returned EAX: Value of the MSR "IA32_PLATFORM_DCA_CAP"
|
||||
* @ Returned EBX: Reserved
|
||||
* @ Returned ECX: Reserved
|
||||
* @ Retruned EDX: Reserved
|
||||
*/
|
||||
CPUID_CACHE_ACCESS_INFO = 0x00000009,
|
||||
CPUID_PERFORMANCE_MONITORING = 0x0000000A,
|
||||
CPUID_EXTENDENDED_TOPOLOGY = 0x0000000B,
|
||||
CPUID_EXTENDENDED_TOPOLOGY2 = 0x0000000D,
|
||||
CPUID_INTEL_RDT = 0x0000000F,
|
||||
CPUID_INTEL_RDT2 = 0x00000010,
|
||||
CPUID_INTEL_SGX = 0x00000012,
|
||||
CPUID_CPU_TRACE_ENUM = 0x00000014,
|
||||
CPUID_TSC = 0x00000015,
|
||||
CPUID_CPU_FREQ_INFO = 0x00000016,
|
||||
CPUID_SOC_VENDOR = 0x00000017,
|
||||
CPUID_DETERMINISTIC_ADRESS_TRANSLATION_PARAMS = 0x00000018,
|
||||
CPUID_KEY_LOCKER = 0x000000019,
|
||||
CPUID_NATIVE_MODEL_ID = 0x0000001A,
|
||||
CPUID_PCONFIG_INFO = 0x0000001B,
|
||||
CPUID_LAST_BRACH = 0x00000001C,
|
||||
CPUID_TILE_INFO = 0x00000001D,
|
||||
CPUID_TMUL_INFO = 0x00000001E,
|
||||
CPUID_V2_EXTENDED_TOPOLOGY = 0x00000001F,
|
||||
CPUID_V2_EXTENDED_TOPOLOGY2 = 0x000000020,
|
||||
// TODO: add the bitmasks for these Microsoft ones
|
||||
/* @ Hypervisor CPUID Leaf Range
|
||||
* @ Returned EAX: Highest hypervisor CPUID leaf present
|
||||
* @ Returned EBX: Largest monitor-line size
|
||||
* @ Returned ECX: Enumeration of Monitor-Mwait extensions,Supports treating
|
||||
* interrupts as break-event for MWAIT
|
||||
* @ Retruned EDX: Number of sub C-states supported using MWAIT for each C
|
||||
* number thingy IDK
|
||||
*/
|
||||
CPUID_HYPERV_IDENT = 0x40000000,
|
||||
/* @ Hypervisor Vendor-Neutral Interface Identification
|
||||
* @ Returned EAX: Hypervisor interface signature
|
||||
* @ Returned EBX: Reserved
|
||||
* @ Returned ECX: Reserved
|
||||
* @ Retruned EDX: Reserved
|
||||
*/
|
||||
CPUID_MS_HYPERV_INTERFCE_IDENT = 0x40000001,
|
||||
/* @ Hypervisor System Identity
|
||||
* @ Returned EAX: Build number
|
||||
* @ Returned EBX: Major and minor version
|
||||
* @ Returned ECX: Reserved
|
||||
* @ Retruned EDX: Reserved
|
||||
*/
|
||||
CPUID_MS_HYPERV_SYSTEM_IDENT = 0x40000002,
|
||||
/* @ Hypervisor Feature Identification
|
||||
* @ Returned EAX: bits 0-31 of HV_PARTITION_PRIVILEGE_MASK
|
||||
* @ Returned EBX: bits 31-63 of HV_PARTITION_PRIVILEGE_MASK
|
||||
* @ Returned ECX: Hyper-V features
|
||||
* @ Retruned EDX: Hyper-V features
|
||||
*/
|
||||
CPUID_MS_HYPERV_FEATURE_IDENT = 0x40000003,
|
||||
/* @ Implementation Recommendations
|
||||
* @ Returned EAX: Hyper-V feature recommendations
|
||||
* @ Returned EBX: Hyper-V feature recommendations
|
||||
* @ Returned ECX: Hyper-V feature recommendations
|
||||
* @ Retruned EDX: Reserved
|
||||
*/
|
||||
CPUID_MS_HYPERV_RECOMMENDATIONS = 0x40000004,
|
||||
/* @ Hypervisor Implementation Limits
|
||||
* @ Returned EAX: The maximum number of virtual processors supported
|
||||
* @ Returned EBX: The maximum number of logical processors supported
|
||||
* @ Returned ECX: The maximum number of physical interrupt vectors available
|
||||
* for interrupt remapping.
|
||||
* @ Retruned EDX: Reserved
|
||||
*/
|
||||
CPUID_MS_HYPERV_IMPL_LIMITS = 0x40000005,
|
||||
/* @ Implementation Hardware Features
|
||||
* @ Returned EAX: Hardware features
|
||||
* @ Returned EBX: Reserved
|
||||
* @ Returned ECX: Reserved
|
||||
* @ Retruned EDX: Reserved
|
||||
*/
|
||||
CPUID_MS_HYPERV_HARDWARE_FEATURES = 0x40000006,
|
||||
/* @ Nested Hypervisor Feature Identification
|
||||
* @ Returned EAX: Nested Hypervisor features
|
||||
* @ Returned EBX: Reserved
|
||||
* @ Returned ECX: Reserved
|
||||
* @ Retruned EDX: Nested Hypervisor features
|
||||
*/
|
||||
CPUID_MS_HYPERV_NESTED_FEATURES = 0x40000009,
|
||||
/* @ Nested Hypervisor Nested Virtualization Features
|
||||
* @ Returned EAX: Nested Hypervisor features
|
||||
* @ Returned EBX: Nested Hypervisor features
|
||||
* @ Returned ECX: Reserved
|
||||
* @ Retruned EDX: Reserved
|
||||
*/
|
||||
CPUID_MS_HYPERV_NESTED_OPTIMISATIONS = 0x4000000A,
|
||||
/* @ Extended processor signature
|
||||
* @ Returned EAX: Reserved
|
||||
* @ Returned EBX: Reserved
|
||||
* @ Returned ECX: Extended feature bits
|
||||
* @ Retruned EDX: Extended feature bits
|
||||
*/
|
||||
CPUID_EXTENDED_SIGNATURE = 0x800000001,
|
||||
/* @ Full CPU name
|
||||
* @ Returned EAX: First 4 characters of the full CPU name
|
||||
* @ Returned EBX: Second 4 characters of the full CPU name
|
||||
* @ Returned ECX: Third 4 characters of the full CPU name
|
||||
* @ Retruned EDX: Fourth 4 characters of the full CPU name
|
||||
*/
|
||||
CPUID_BRAND_STRING1 = 0x800000002,
|
||||
/* @ Full CPU name 2
|
||||
* @ Returned EAX: Fifth 4 characters of the full CPU name
|
||||
* @ Returned EBX: Sexth 4 characters of the full CPU name
|
||||
* @ Returned ECX: Seventh 4 characters of the full CPU name
|
||||
* @ Retruned EDX: Eightth 4 characters of the full CPU name
|
||||
*/
|
||||
CPUID_BRAND_STRING2 = 0x800000003,
|
||||
/* @ Full CPU name 3
|
||||
* @ Returned EAX: Nineth 4 characters of the full CPU name
|
||||
* @ Returned EBX: Tenth 4 characters of the full CPU name
|
||||
* @ Returned ECX: Eleventh 4 characters of the full CPU name
|
||||
* @ Retruned EDX: Twelveth 4 characters of the full CPU name
|
||||
*/
|
||||
CPUID_BRAND_STRING3 = 0x800000004,
|
||||
/* @ Cache line size and associativity
|
||||
* @ Returned EAX: Reserved
|
||||
* @ Returned EBX: Reserved
|
||||
* @ Returned ECX: Bits 0-7 = Cache line size in bytes, Bits 12-15 = L2
|
||||
* Associativity, Bits 16-31 = Cache size in 1K blocks
|
||||
* @ Retruned EDX: Reserved
|
||||
*/
|
||||
CPUID_MORE_CACHE = 0x800000006,
|
||||
/* @ Invariant TSC available
|
||||
* @ Returned EAX: Reserved
|
||||
* @ Returned EBX: Reserved
|
||||
* @ Returned ECX: Bit 8 = Invariant TSC available
|
||||
* @ Retruned EDX: Reserved
|
||||
*/
|
||||
CPUID_INVARIANT_TSC_AVAILABLE = 0x800000007,
|
||||
/* @ Physical adress size
|
||||
* @ Returned EAX: Bits 0-7 = Physical Adress bits, Bits 8-15 = Linear
|
||||
* Address bits
|
||||
* @ Returned EBX: Bit 9 = WBNOINVD available
|
||||
* @ Returned ECX: Reserved
|
||||
* @ Retruned EDX: Reserved
|
||||
*/
|
||||
CPUID_PHYS_ADDR_SIZE = 0x800000008,
|
||||
};
|
||||
|
||||
enum sub_leaves {
|
||||
/* @ Extended features available subleaf 1 !!! All fields return 0 is info not
|
||||
* available !!!
|
||||
* @ Returned EAX: Features
|
||||
* @ Returned EBX: PPIN
|
||||
* @ Returned ECX: Reserved
|
||||
* @ Retruned EDX: CET_SSS
|
||||
*/
|
||||
CPUID_EXTENDED_FEATURES_SL1 = 0x00000001,
|
||||
/* @ Extended features available subleaf 2 !!! All fields return 0 is info not
|
||||
* available !!!
|
||||
* @ Returned EAX: Reserved
|
||||
* @ Returned EBX: Reserved
|
||||
* @ Returned ECX: Reserved
|
||||
* @ Retruned EDX: Features
|
||||
*/
|
||||
CPUID_EXTENDED_FEATURES_SL2 = 0x00000002,
|
||||
CPUID_INTEL_RDT_CAPABILITY = 0x00000001,
|
||||
CPUID_INTEL_RDT2_ALLOCATION = 0x00000000,
|
||||
CPUID_INTEL_RDT2_RESID1 = 0x00000001,
|
||||
CPUID_INTEL_RDT2_RESID2 = 0x00000002,
|
||||
CPUID_INTEL_RDT2_RESID3 = 0x00000003,
|
||||
CPUID_INTEL_SGX_SL1 = 0x00000001,
|
||||
CPUID_INTEL_SGX_SL2 = 0x00000002,
|
||||
CPUID_CPU_TRACE_ENUM_SL = 0x00000001,
|
||||
CPUID_SOC_VENDOR_SL1 = 0x00000001,
|
||||
CPUID_SOC_VENDOR_SL2 = 0x00000002,
|
||||
CPUID_SOC_VENDOR_SL3 = 0x00000003,
|
||||
// NOTE: goes higher than 1
|
||||
CPUID_DETERMINISTIC_ADRESS_TRANSLATION_PARAMS_SL = 0x00000001,
|
||||
CPUID_TILE_INFO_PALETTE1 = 0x000000001,
|
||||
};
|
||||
|
||||
static inline void cpuid(int leaf, int subleaf, int *a, int *b, int *c,
|
||||
int *d) {
|
||||
__asm__ __volatile__("cpuid"
|
||||
: "=a"(*a), "=b"(*b), "=c"(*c), "=d"(*d)
|
||||
: "a"(leaf), "c"(subleaf));
|
||||
}
|
||||
|
||||
#endif // __CPUID_H__
|
|
@ -1,12 +0,0 @@
|
|||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void fpu_set_cw(const uint16_t cw) { asm volatile("fldcw %0" ::"m"(cw)); }
|
||||
|
||||
void fpu_activate() {
|
||||
size_t cr4;
|
||||
asm volatile("mov %%cr4, %0" : "=r"(cr4));
|
||||
cr4 |= 0x200;
|
||||
asm volatile("mov %0, %%cr4" ::"r"(cr4));
|
||||
fpu_set_cw(0x37F);
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void fpu_set_cw(const uint16_t cw);
|
||||
void fpu_activate();
|
|
@ -1,51 +0,0 @@
|
|||
// #include "sys/log.h"
|
||||
#include <arch/x86_64/gdt.h>
|
||||
#include <mm/memop.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/log.h>
|
||||
|
||||
gdt_table def_table = {{
|
||||
0x0000000000000000, // 0x00
|
||||
|
||||
0x00009a000000ffff, // 0x08 16 bit code
|
||||
0x000093000000ffff, // 0x10 16 bit data
|
||||
|
||||
0x00cf9a000000ffff, // 0x18 32 bit code
|
||||
0x00cf93000000ffff, // 0x20 32 bit data
|
||||
|
||||
0x00af9b000000ffff, // 0x28 64 bit code cs
|
||||
0x00af93000000ffff, // 0x30 64 bit data ss
|
||||
|
||||
0x00aff3000000ffff, // 0x38 user mode data ss
|
||||
0x00affb000000ffff, // 0x40 user mode code cs
|
||||
},
|
||||
{}};
|
||||
|
||||
tssr tss_list[256]; // One tssr per CPU
|
||||
|
||||
void gdt_init(char *kstack) {
|
||||
|
||||
// TODO: adapt for multiprocessor kernel
|
||||
memset(&tss_list[0], 0, sizeof(tssr));
|
||||
tss_list[0].rsp[0] = (uint64_t)kstack;
|
||||
tss_list[0].iopb = sizeof(tssr);
|
||||
uintptr_t tss = (uintptr_t)&tss_list[0];
|
||||
|
||||
def_table.tss_entry.length = sizeof(tss_entry);
|
||||
def_table.tss_entry.base = (uint16_t)(tss & 0xffff);
|
||||
def_table.tss_entry.base1 = (uint8_t)((tss >> 16) & 0xff);
|
||||
def_table.tss_entry.flags = 0x89;
|
||||
def_table.tss_entry.flags1 = 0;
|
||||
def_table.tss_entry.base2 = (uint8_t)((tss >> 24) & 0xff);
|
||||
def_table.tss_entry.base3 = (uint32_t)(tss >> 32);
|
||||
def_table.tss_entry.resv = 0;
|
||||
|
||||
gdtr gdt =
|
||||
(gdtr){.size = (sizeof(gdt_table)) - 1, .address = (uint64_t)&def_table};
|
||||
|
||||
__asm__ volatile("lgdt %0\n\t" : : "m"(gdt) : "memory");
|
||||
__asm__ volatile("ltr %0\n\t" : : "r"((uint16_t)0x48));
|
||||
|
||||
// logln(progress, "kinit stage 1", "GDT initialized\n");
|
||||
log("gdt - initialized.\n");
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
uint16_t length;
|
||||
uint16_t base;
|
||||
uint8_t base1;
|
||||
uint8_t flags;
|
||||
uint8_t flags1;
|
||||
uint8_t base2;
|
||||
uint32_t base3;
|
||||
uint32_t resv;
|
||||
} __attribute__((packed)) tss_entry;
|
||||
|
||||
typedef struct {
|
||||
uint64_t gdt_entries[9];
|
||||
tss_entry tss_entry;
|
||||
} __attribute__((packed)) gdt_table;
|
||||
|
||||
typedef struct {
|
||||
uint16_t size;
|
||||
uint64_t address;
|
||||
} __attribute__((packed)) gdtr;
|
||||
|
||||
typedef struct {
|
||||
uint32_t resv;
|
||||
uint64_t rsp[4];
|
||||
uint64_t resv1;
|
||||
uint64_t ist[7];
|
||||
uint64_t resv2;
|
||||
uint16_t resv3;
|
||||
uint16_t iopb;
|
||||
} __attribute__((packed)) tssr; // Per CPU
|
||||
|
||||
void gdt_init(char *kstack);
|
|
@ -1,335 +0,0 @@
|
|||
%macro pushall 0
|
||||
push rax
|
||||
push rcx
|
||||
push rdx
|
||||
push rbx
|
||||
push rbp
|
||||
push rsi
|
||||
push rdi
|
||||
push r8
|
||||
push r9
|
||||
push r10
|
||||
push r11
|
||||
push r12
|
||||
push r13
|
||||
push r14
|
||||
push r15
|
||||
%endmacro
|
||||
|
||||
%macro popall 0
|
||||
pop r15
|
||||
pop r14
|
||||
pop r13
|
||||
pop r12
|
||||
pop r11
|
||||
pop r10
|
||||
pop r9
|
||||
pop r8
|
||||
pop rdi
|
||||
pop rsi
|
||||
pop rbp
|
||||
pop rbx
|
||||
pop rdx
|
||||
pop rcx
|
||||
pop rax
|
||||
%endmacro
|
||||
|
||||
%macro isr_err_stub 1
|
||||
isr_stub_%+%1:
|
||||
|
||||
push %1
|
||||
pushall
|
||||
|
||||
mov rdi, rsp
|
||||
|
||||
call idt_int_handler
|
||||
|
||||
popall
|
||||
|
||||
add rsp, 16
|
||||
iretq
|
||||
%endmacro
|
||||
|
||||
%macro isr_no_err_stub 1
|
||||
isr_stub_%+%1:
|
||||
push 0
|
||||
push %1
|
||||
pushall
|
||||
|
||||
mov rdi, rsp
|
||||
|
||||
call idt_int_handler
|
||||
|
||||
popall
|
||||
|
||||
add rsp, 16
|
||||
iretq
|
||||
%endmacro
|
||||
|
||||
extern idt_int_handler
|
||||
isr_no_err_stub 0
|
||||
isr_no_err_stub 1
|
||||
isr_no_err_stub 2
|
||||
isr_no_err_stub 3
|
||||
isr_no_err_stub 4
|
||||
isr_no_err_stub 5
|
||||
isr_no_err_stub 6
|
||||
isr_no_err_stub 7
|
||||
isr_err_stub 8
|
||||
isr_no_err_stub 9
|
||||
isr_err_stub 10
|
||||
isr_err_stub 11
|
||||
isr_err_stub 12
|
||||
isr_err_stub 13
|
||||
isr_err_stub 14
|
||||
isr_no_err_stub 15
|
||||
isr_no_err_stub 16
|
||||
isr_err_stub 17
|
||||
isr_no_err_stub 18
|
||||
isr_no_err_stub 19
|
||||
isr_no_err_stub 20
|
||||
isr_no_err_stub 21
|
||||
isr_no_err_stub 22
|
||||
isr_no_err_stub 23
|
||||
isr_no_err_stub 24
|
||||
isr_no_err_stub 25
|
||||
isr_no_err_stub 26
|
||||
isr_no_err_stub 27
|
||||
isr_no_err_stub 28
|
||||
isr_no_err_stub 29
|
||||
isr_err_stub 30
|
||||
isr_no_err_stub 31
|
||||
|
||||
|
||||
isr_no_err_stub 32
|
||||
isr_no_err_stub 33
|
||||
isr_no_err_stub 34
|
||||
isr_no_err_stub 35
|
||||
isr_no_err_stub 36
|
||||
isr_no_err_stub 37
|
||||
isr_no_err_stub 38
|
||||
isr_no_err_stub 39
|
||||
isr_no_err_stub 40
|
||||
isr_no_err_stub 41
|
||||
isr_no_err_stub 42
|
||||
isr_no_err_stub 43
|
||||
isr_no_err_stub 44
|
||||
isr_no_err_stub 45
|
||||
isr_no_err_stub 46
|
||||
isr_no_err_stub 47
|
||||
isr_no_err_stub 48
|
||||
isr_no_err_stub 49
|
||||
isr_no_err_stub 50
|
||||
isr_no_err_stub 51
|
||||
isr_no_err_stub 52
|
||||
isr_no_err_stub 53
|
||||
isr_no_err_stub 54
|
||||
isr_no_err_stub 55
|
||||
isr_no_err_stub 56
|
||||
isr_no_err_stub 57
|
||||
isr_no_err_stub 58
|
||||
isr_no_err_stub 59
|
||||
isr_no_err_stub 60
|
||||
isr_no_err_stub 61
|
||||
isr_no_err_stub 62
|
||||
isr_no_err_stub 63
|
||||
isr_no_err_stub 64
|
||||
isr_no_err_stub 65
|
||||
isr_no_err_stub 66
|
||||
isr_no_err_stub 67
|
||||
isr_no_err_stub 68
|
||||
isr_no_err_stub 69
|
||||
isr_no_err_stub 70
|
||||
isr_no_err_stub 71
|
||||
isr_no_err_stub 72
|
||||
isr_no_err_stub 73
|
||||
isr_no_err_stub 74
|
||||
isr_no_err_stub 75
|
||||
isr_no_err_stub 76
|
||||
isr_no_err_stub 77
|
||||
isr_no_err_stub 78
|
||||
isr_no_err_stub 79
|
||||
isr_no_err_stub 80
|
||||
isr_no_err_stub 81
|
||||
isr_no_err_stub 82
|
||||
isr_no_err_stub 83
|
||||
isr_no_err_stub 84
|
||||
isr_no_err_stub 85
|
||||
isr_no_err_stub 86
|
||||
isr_no_err_stub 87
|
||||
isr_no_err_stub 88
|
||||
isr_no_err_stub 89
|
||||
isr_no_err_stub 90
|
||||
isr_no_err_stub 91
|
||||
isr_no_err_stub 92
|
||||
isr_no_err_stub 93
|
||||
isr_no_err_stub 94
|
||||
isr_no_err_stub 95
|
||||
isr_no_err_stub 96
|
||||
isr_no_err_stub 97
|
||||
isr_no_err_stub 98
|
||||
isr_no_err_stub 99
|
||||
isr_no_err_stub 100
|
||||
isr_no_err_stub 101
|
||||
isr_no_err_stub 102
|
||||
isr_no_err_stub 103
|
||||
isr_no_err_stub 104
|
||||
isr_no_err_stub 105
|
||||
isr_no_err_stub 106
|
||||
isr_no_err_stub 107
|
||||
isr_no_err_stub 108
|
||||
isr_no_err_stub 109
|
||||
isr_no_err_stub 110
|
||||
isr_no_err_stub 111
|
||||
isr_no_err_stub 112
|
||||
isr_no_err_stub 113
|
||||
isr_no_err_stub 114
|
||||
isr_no_err_stub 115
|
||||
isr_no_err_stub 116
|
||||
isr_no_err_stub 117
|
||||
isr_no_err_stub 118
|
||||
isr_no_err_stub 119
|
||||
isr_no_err_stub 120
|
||||
isr_no_err_stub 121
|
||||
isr_no_err_stub 122
|
||||
isr_no_err_stub 123
|
||||
isr_no_err_stub 124
|
||||
isr_no_err_stub 125
|
||||
isr_no_err_stub 126
|
||||
isr_no_err_stub 127
|
||||
isr_no_err_stub 128
|
||||
isr_no_err_stub 129
|
||||
isr_no_err_stub 130
|
||||
isr_no_err_stub 131
|
||||
isr_no_err_stub 132
|
||||
isr_no_err_stub 133
|
||||
isr_no_err_stub 134
|
||||
isr_no_err_stub 135
|
||||
isr_no_err_stub 136
|
||||
isr_no_err_stub 137
|
||||
isr_no_err_stub 138
|
||||
isr_no_err_stub 139
|
||||
isr_no_err_stub 140
|
||||
isr_no_err_stub 141
|
||||
isr_no_err_stub 142
|
||||
isr_no_err_stub 143
|
||||
isr_no_err_stub 144
|
||||
isr_no_err_stub 145
|
||||
isr_no_err_stub 146
|
||||
isr_no_err_stub 147
|
||||
isr_no_err_stub 148
|
||||
isr_no_err_stub 149
|
||||
isr_no_err_stub 150
|
||||
isr_no_err_stub 151
|
||||
isr_no_err_stub 152
|
||||
isr_no_err_stub 153
|
||||
isr_no_err_stub 154
|
||||
isr_no_err_stub 155
|
||||
isr_no_err_stub 156
|
||||
isr_no_err_stub 157
|
||||
isr_no_err_stub 158
|
||||
isr_no_err_stub 159
|
||||
isr_no_err_stub 160
|
||||
isr_no_err_stub 161
|
||||
isr_no_err_stub 162
|
||||
isr_no_err_stub 163
|
||||
isr_no_err_stub 164
|
||||
isr_no_err_stub 165
|
||||
isr_no_err_stub 166
|
||||
isr_no_err_stub 167
|
||||
isr_no_err_stub 168
|
||||
isr_no_err_stub 169
|
||||
isr_no_err_stub 170
|
||||
isr_no_err_stub 171
|
||||
isr_no_err_stub 172
|
||||
isr_no_err_stub 173
|
||||
isr_no_err_stub 174
|
||||
isr_no_err_stub 175
|
||||
isr_no_err_stub 176
|
||||
isr_no_err_stub 177
|
||||
isr_no_err_stub 178
|
||||
isr_no_err_stub 179
|
||||
isr_no_err_stub 180
|
||||
isr_no_err_stub 181
|
||||
isr_no_err_stub 182
|
||||
isr_no_err_stub 183
|
||||
isr_no_err_stub 184
|
||||
isr_no_err_stub 185
|
||||
isr_no_err_stub 186
|
||||
isr_no_err_stub 187
|
||||
isr_no_err_stub 188
|
||||
isr_no_err_stub 189
|
||||
isr_no_err_stub 190
|
||||
isr_no_err_stub 191
|
||||
isr_no_err_stub 192
|
||||
isr_no_err_stub 193
|
||||
isr_no_err_stub 194
|
||||
isr_no_err_stub 195
|
||||
isr_no_err_stub 196
|
||||
isr_no_err_stub 197
|
||||
isr_no_err_stub 198
|
||||
isr_no_err_stub 199
|
||||
isr_no_err_stub 200
|
||||
isr_no_err_stub 201
|
||||
isr_no_err_stub 202
|
||||
isr_no_err_stub 203
|
||||
isr_no_err_stub 204
|
||||
isr_no_err_stub 205
|
||||
isr_no_err_stub 206
|
||||
isr_no_err_stub 207
|
||||
isr_no_err_stub 208
|
||||
isr_no_err_stub 209
|
||||
isr_no_err_stub 210
|
||||
isr_no_err_stub 211
|
||||
isr_no_err_stub 212
|
||||
isr_no_err_stub 213
|
||||
isr_no_err_stub 214
|
||||
isr_no_err_stub 215
|
||||
isr_no_err_stub 216
|
||||
isr_no_err_stub 217
|
||||
isr_no_err_stub 218
|
||||
isr_no_err_stub 219
|
||||
isr_no_err_stub 220
|
||||
isr_no_err_stub 221
|
||||
isr_no_err_stub 222
|
||||
isr_no_err_stub 223
|
||||
isr_no_err_stub 224
|
||||
isr_no_err_stub 225
|
||||
isr_no_err_stub 226
|
||||
isr_no_err_stub 227
|
||||
isr_no_err_stub 228
|
||||
isr_no_err_stub 229
|
||||
isr_no_err_stub 230
|
||||
isr_no_err_stub 231
|
||||
isr_no_err_stub 232
|
||||
isr_no_err_stub 233
|
||||
isr_no_err_stub 234
|
||||
isr_no_err_stub 235
|
||||
isr_no_err_stub 236
|
||||
isr_no_err_stub 237
|
||||
isr_no_err_stub 238
|
||||
isr_no_err_stub 239
|
||||
isr_no_err_stub 240
|
||||
isr_no_err_stub 241
|
||||
isr_no_err_stub 242
|
||||
isr_no_err_stub 243
|
||||
isr_no_err_stub 244
|
||||
isr_no_err_stub 245
|
||||
isr_no_err_stub 246
|
||||
isr_no_err_stub 247
|
||||
isr_no_err_stub 248
|
||||
isr_no_err_stub 249
|
||||
isr_no_err_stub 250
|
||||
isr_no_err_stub 251
|
||||
isr_no_err_stub 252
|
||||
isr_no_err_stub 253
|
||||
isr_no_err_stub 254
|
||||
isr_no_err_stub 255
|
||||
|
||||
global isr_stub_table
|
||||
isr_stub_table:
|
||||
%assign i 0
|
||||
%rep 256
|
||||
dq isr_stub_%+i ; use DQ instead if targeting 64-bit
|
||||
%assign i i+1
|
||||
%endrep
|
|
@ -1,94 +0,0 @@
|
|||
// #include "sys/log.h"
|
||||
#include "arch/x86_64/smp.h"
|
||||
#include "dev/ioapic.h"
|
||||
#include "dev/lapic.h"
|
||||
#include "mm/vmm.h"
|
||||
#include "sys/errhnd/panic.h"
|
||||
#include <arch/x86_64/idt.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/log.h>
|
||||
#include <sched/sched.h>
|
||||
|
||||
__attribute__((aligned(0x10))) static idt_entry_t idt[256];
|
||||
|
||||
static idtr_t idtr;
|
||||
static int vectors[256];
|
||||
extern void *isr_stub_table[];
|
||||
idt_irq_handler_t irq_handler_table[256 - 32];
|
||||
|
||||
void idt_set_descriptor(uint8_t vector, void *isr, uint8_t flags) {
|
||||
idt_entry_t *descriptor = &idt[vector];
|
||||
|
||||
descriptor->isr_low = (uint64_t)isr & 0xFFFF;
|
||||
descriptor->kernel_cs = 0x28;
|
||||
descriptor->ist = 0;
|
||||
descriptor->attributes = flags;
|
||||
descriptor->isr_mid = ((uint64_t)isr >> 16) & 0xFFFF;
|
||||
descriptor->isr_high = ((uint64_t)isr >> 32) & 0xFFFFFFFF;
|
||||
descriptor->reserved = 0;
|
||||
}
|
||||
|
||||
void idt_register_irq(uint8_t vector, void *isr) {
|
||||
if (vector <= 14)
|
||||
ioapic_redirect_irq(bootstrap_lapic_id, vector + 32, vector, false);
|
||||
|
||||
irq_handler_table[vector] = isr;
|
||||
vectors[vector <= 14 ? vector + 32 : vector] = IDT_VT_IRQ;
|
||||
}
|
||||
|
||||
void idt_init() {
|
||||
idtr.base = (uintptr_t)&idt[0];
|
||||
idtr.limit = (uint16_t)sizeof(idt_entry_t) * 256 - 1;
|
||||
|
||||
for (uint16_t vector = 0; vector < 32; vector++) {
|
||||
idt_set_descriptor(vector, isr_stub_table[vector], 0x8E);
|
||||
vectors[vector] = IDT_VT_EXCEPTION;
|
||||
}
|
||||
|
||||
for (uint16_t vector = 32; vector < 256; vector++) {
|
||||
idt_set_descriptor(vector, isr_stub_table[vector], 0x8E);
|
||||
vectors[vector] = IDT_VT_UNDEFINED;
|
||||
}
|
||||
|
||||
// Do not use the legacy PIC.
|
||||
// pic_init();
|
||||
// pic_unmask_irq(1);
|
||||
// pic_unmask_irq(8);
|
||||
|
||||
__asm__ volatile("lidt %0" : : "m"(idtr)); // load the new IDT
|
||||
__asm__ volatile("sti"); // set the interrupt flag
|
||||
|
||||
log("idt - initialized\n");
|
||||
}
|
||||
|
||||
void idt_int_handler(registers_t *regs) {
|
||||
vmm_load_pagemap(vmm_kernel_pm);
|
||||
// log("kernel - Interrupt %d\n", regs->int_no);
|
||||
|
||||
if (regs->int_no < 32) {
|
||||
if (regs->cs == 0x43) {
|
||||
log("ints - Process \"%s\" (pid: %d) caused a CPU fault: %d (err: %d, IP: %p)\n",
|
||||
curr_proc->name, curr_proc->pid, regs->int_no, regs->err_code, regs->rip);
|
||||
|
||||
sched_exit(-144);
|
||||
return;
|
||||
//asm("cli");
|
||||
//while (1)
|
||||
// asm("hlt");
|
||||
}
|
||||
|
||||
panic_ctx("A CPU exception occured.", regs);
|
||||
}
|
||||
|
||||
int vec = regs->int_no;
|
||||
if (vec >= 32 && vec < 47)
|
||||
vec -= 32;
|
||||
|
||||
if (vectors[regs->int_no] == IDT_VT_IRQ) {
|
||||
idt_irq_handler_t i = irq_handler_table[vec];
|
||||
i(regs);
|
||||
}
|
||||
|
||||
lapic_eoi();
|
||||
// pic_ack(regs->int_no - 32);
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// VT = Vector type
|
||||
#define IDT_VT_UNDEFINED 0
|
||||
#define IDT_VT_EXCEPTION 1
|
||||
#define IDT_VT_IRQ 2
|
||||
|
||||
typedef struct {
|
||||
uint64_t r15;
|
||||
uint64_t r14;
|
||||
uint64_t r13;
|
||||
uint64_t r12;
|
||||
uint64_t r11;
|
||||
uint64_t r10;
|
||||
uint64_t r9;
|
||||
uint64_t r8;
|
||||
uint64_t rdi;
|
||||
uint64_t rsi;
|
||||
uint64_t rbp;
|
||||
uint64_t rbx;
|
||||
uint64_t rdx;
|
||||
uint64_t rcx;
|
||||
uint64_t rax;
|
||||
uint64_t int_no;
|
||||
uint64_t err_code;
|
||||
uint64_t rip;
|
||||
uint64_t cs;
|
||||
uint64_t rflags;
|
||||
uint64_t rsp;
|
||||
uint64_t ss;
|
||||
} __attribute__((packed)) registers_t;
|
||||
|
||||
typedef struct stackframe {
|
||||
struct stackframe *rbp;
|
||||
uint64_t rip;
|
||||
} stackframe_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t isr_low; // The lower 16 bits of the ISR's address
|
||||
uint16_t kernel_cs; // The GDT segment selector that the CPU will load into CS
|
||||
// before calling the ISR
|
||||
uint8_t ist; // The IST in the TSS that the CPU will load into RSP; set to
|
||||
// zero for now
|
||||
uint8_t attributes; // Type and attributes; see the IDT page
|
||||
uint16_t
|
||||
isr_mid; // The higher 16 bits of the lower 32 bits of the ISR's address
|
||||
uint32_t isr_high; // The higher 32 bits of the ISR's address
|
||||
uint32_t reserved; // Set to zero
|
||||
} __attribute__((packed)) idt_entry_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t limit;
|
||||
uint64_t base;
|
||||
} __attribute__((packed)) idtr_t;
|
||||
|
||||
typedef void (*idt_irq_handler_t)(registers_t *regs);
|
||||
|
||||
void idt_register_irq(uint8_t vector, void *isr);
|
||||
void idt_set_descriptor(uint8_t vector, void *isr, uint8_t flags);
|
||||
void idt_init(void);
|
|
@ -1,17 +0,0 @@
|
|||
// Copyright (C) 2024 Sipaa Projects
|
||||
// This code is part of the Soaplin kernel and is licensed under the terms of
|
||||
// the MIT License.
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint8_t inb(uint16_t port) {
|
||||
uint8_t ret;
|
||||
__asm__ volatile("inb %w1, %b0" : "=a"(ret) : "Nd"(port) : "memory");
|
||||
return ret;
|
||||
}
|
||||
|
||||
void outb(uint16_t port, uint8_t val) {
|
||||
__asm__ volatile("outb %b0, %w1" : : "a"(val), "Nd"(port) : "memory");
|
||||
}
|
||||
|
||||
void io_wait(void) { outb(0x80, 0); }
|
|
@ -1,19 +0,0 @@
|
|||
// Copyright (C) 2024 Sipaa Projects
|
||||
// This code is part of the Soaplin kernel and is licensed under the terms of
|
||||
// the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
uint8_t inb(uint16_t port);
|
||||
void outb(uint16_t port, uint8_t val);
|
||||
void io_wait(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -1,18 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define IA32_GS_MSR 0xC0000101
|
||||
#define IA32_GS_KERNEL_MSR 0xC0000102
|
||||
|
||||
static inline void wrmsr(uint64_t msr, uint64_t value) {
|
||||
uint32_t low = value & 0xFFFFFFFF;
|
||||
uint32_t high = value >> 32;
|
||||
asm volatile("wrmsr" : : "c"(msr), "a"(low), "d"(high));
|
||||
}
|
||||
|
||||
static inline uint64_t rdmsr(uint64_t msr) {
|
||||
uint32_t low, high;
|
||||
asm volatile("rdmsr" : "=a"(low), "=d"(high) : "c"(msr));
|
||||
return ((uint64_t)high << 32) | low;
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
#include "arch/x86_64/idt.h"
|
||||
#include "sched/sched.h"
|
||||
#include <arch/x86_64/idt.h>
|
||||
#include <arch/x86_64/pit.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/log.h>
|
||||
|
||||
uint32_t tick = 0;
|
||||
|
||||
void pit_handler(registers_t *regs) {
|
||||
// log("PIT");
|
||||
tick++;
|
||||
schedule(regs);
|
||||
}
|
||||
|
||||
void pit_init() {
|
||||
outb(0x43, 0x36);
|
||||
uint16_t div = (uint16_t)(1193180 / 1000);
|
||||
outb(0x40, (uint8_t)div);
|
||||
outb(0x40, (uint8_t)(div >> 8));
|
||||
}
|
||||
|
||||
void pit_enable() { idt_register_irq(0, pit_handler); }
|
||||
|
||||
void pit_sleep(uint32_t ms) {
|
||||
uint64_t start = tick;
|
||||
while (tick - start < ms) {
|
||||
__asm__ volatile("nop");
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
#ifndef PIT_H
|
||||
#define PIT_H
|
||||
|
||||
#include <arch/x86_64/io.h>
|
||||
#include <stdint.h>
|
||||
|
||||
extern uint32_t tick;
|
||||
|
||||
void pit_init();
|
||||
void pit_sleep(uint32_t ms);
|
||||
void pit_enable();
|
||||
|
||||
#endif
|
|
@ -1,43 +0,0 @@
|
|||
#include "rtc.h"
|
||||
#include "io.h"
|
||||
|
||||
char bcd;
|
||||
|
||||
unsigned char read_register(unsigned char reg) {
|
||||
__asm__ volatile("cli");
|
||||
outb(RTC_COMMAND, reg);
|
||||
return inb(RTC_DATA);
|
||||
__asm__ volatile("sti");
|
||||
}
|
||||
|
||||
void write_register(unsigned char reg, unsigned char value) {
|
||||
__asm__ volatile("cli");
|
||||
outb(RTC_COMMAND, reg);
|
||||
outb(RTC_DATA, value);
|
||||
__asm__ volatile("sti");
|
||||
}
|
||||
|
||||
unsigned char bcd2bin(unsigned char in_bcd) {
|
||||
return (bcd) ? ((in_bcd >> 4) * 10) + (in_bcd & 0x0F) : in_bcd;
|
||||
}
|
||||
|
||||
int rtc_init() {
|
||||
__asm__ volatile("cli");
|
||||
unsigned char status;
|
||||
status = read_register(RTC_STATUS);
|
||||
status |= 0x02; // 24 hour clock
|
||||
status |= 0x10; // update ended interrupts
|
||||
status &= ~0x20; // no alarm interrupts
|
||||
status &= ~0x40; // no periodic interrupt
|
||||
bcd = !(status & 0x04); // check if data type is BCD
|
||||
write_register(RTC_STATUS, status);
|
||||
|
||||
outb(0x70, 0x8B); // select register B, and disable NMI
|
||||
char prev = inb(0x71); // read the current value of register B
|
||||
outb(0x70,
|
||||
0x8B); // set the index again (a read will reset the index to register D)
|
||||
outb(0x71, prev | 0x40); // write the previous value ORed with 0x40. This
|
||||
// turns on bit 6 of register B
|
||||
__asm__ volatile("sti");
|
||||
return 0;
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
#ifndef __TIME_H
|
||||
#define __TIME_H
|
||||
|
||||
#define RTC_COMMAND 0x70
|
||||
#define RTC_DATA 0x71
|
||||
#define RTC_STATUS 0x0B
|
||||
|
||||
#define RTC_SECONDS 0x00
|
||||
#define RTC_MINUTES 0x02
|
||||
#define RTC_HOURS 0x04
|
||||
#define RTC_DAY_OF_WEEK 0x06
|
||||
#define RTC_DAY 0x07
|
||||
#define RTC_MONTH 0x08
|
||||
#define RTC_YEAR 0x09
|
||||
|
||||
int rtc_init();
|
||||
|
||||
#endif // __TIME_H__
|
|
@ -1,52 +0,0 @@
|
|||
#include "arch/x86_64/smp.h"
|
||||
#include "lib/spinlock.h"
|
||||
#include "limine.h"
|
||||
#include "sys/log.h"
|
||||
#include <stdint.h>
|
||||
|
||||
__attribute__((
|
||||
used, section(".limine_requests"))) static volatile struct limine_mp_request
|
||||
smp_request = {.id = LIMINE_MP_REQUEST, .revision = 0};
|
||||
|
||||
uint32_t bootstrap_lapic_id = 0;
|
||||
uint32_t smp_cpu_count = 0; // Number of processors
|
||||
spinlock_t smp_lock = {0};
|
||||
|
||||
uint32_t ctr = 0;
|
||||
|
||||
void smp_entry(struct limine_mp_info *smp_info) {
|
||||
// spinlock_acquire(&smp_lock);
|
||||
|
||||
log("smp - CPU %d started (LAPIC ID: %d)\n", smp_info->processor_id,
|
||||
smp_info->lapic_id);
|
||||
__atomic_fetch_add(&ctr, 1, __ATOMIC_SEQ_CST);
|
||||
|
||||
while (1)
|
||||
;
|
||||
;
|
||||
// spinlock_release(&smp_lock);
|
||||
}
|
||||
|
||||
void smp_init() {
|
||||
bootstrap_lapic_id = smp_request.response->bsp_lapic_id;
|
||||
smp_cpu_count = smp_request.response->cpu_count;
|
||||
|
||||
log("smp - detected %d CPUs\n", smp_cpu_count);
|
||||
|
||||
for (uint64_t i = 0; i < smp_cpu_count; i++) {
|
||||
if (smp_request.response->cpus[i]->lapic_id != bootstrap_lapic_id) {
|
||||
uint32_t old_ctr = __atomic_load_n(&ctr, __ATOMIC_SEQ_CST);
|
||||
|
||||
__atomic_store_n(&smp_request.response->cpus[i]->goto_address, smp_entry,
|
||||
__ATOMIC_SEQ_CST);
|
||||
|
||||
while (__atomic_load_n(&ctr, __ATOMIC_SEQ_CST) == old_ctr)
|
||||
;
|
||||
} else {
|
||||
log("smp - CPU %d is the bootstrap processor (LAPIC ID: %d)\n", i,
|
||||
smp_request.response->cpus[i]->lapic_id);
|
||||
}
|
||||
}
|
||||
|
||||
log("smp - initialized\n");
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern uint32_t bootstrap_lapic_id;
|
||||
|
||||
void smp_init();
|
|
@ -1,59 +0,0 @@
|
|||
#include <arch/x86_64/sse.h>
|
||||
#include <sys/log.h>
|
||||
#include <sys/printf.h>
|
||||
|
||||
int cpuid_check_bit(int reg, int bit) {
|
||||
int eax, ebx, ecx, edx;
|
||||
|
||||
// Minimal inline assembly to execute CPUID
|
||||
__asm__ volatile("cpuid" // Execute CPUID instruction
|
||||
: "=a"(eax), "=b"(ebx), "=c"(ecx),
|
||||
"=d"(edx) // Output registers
|
||||
: "a"(0x1) // Input: EAX = 0x1 (query feature flags)
|
||||
: // No clobbered registers
|
||||
);
|
||||
|
||||
// Check bit 25 of EDX (SSE support) in plain C
|
||||
if (reg == 0) {
|
||||
if (edx & (1 << bit)) {
|
||||
return 1; // SSE is supported
|
||||
} else {
|
||||
return 0; // SSE is not supported
|
||||
}
|
||||
} else if (reg == 1) {
|
||||
if (ecx & (1 << bit)) {
|
||||
return 1; // SSE is supported
|
||||
} else {
|
||||
return 0; // SSE is not supported
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sse_init() {
|
||||
int sse = cpuid_check_bit(0, 25);
|
||||
int sse2 = cpuid_check_bit(0, 26);
|
||||
int sse3 = cpuid_check_bit(1, 0);
|
||||
int ssse3 = cpuid_check_bit(1, 9);
|
||||
|
||||
if (sse)
|
||||
log("sse - sse is supported!\n");
|
||||
else
|
||||
log("sse - sse isn't supported!\n");
|
||||
|
||||
if (sse2)
|
||||
log("sse - sse2 is supported!\n");
|
||||
else
|
||||
log("sse - sse2 isn't supported!\n");
|
||||
|
||||
if (sse3)
|
||||
log("sse - sse3 is supported!\n");
|
||||
else
|
||||
log("sse - sse3 isn't supported!\n");
|
||||
|
||||
if (ssse3)
|
||||
log("sse - ssse3 is supported!\n");
|
||||
else
|
||||
log("sse - ssse3 isn't supported!\n");
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
int sse_is_supported();
|
||||
void sse_init();
|
|
@ -1,53 +0,0 @@
|
|||
bits 64
|
||||
|
||||
section .text
|
||||
global syscall_entry
|
||||
extern syscall_handle
|
||||
|
||||
syscall_entry:
|
||||
swapgs ; switch
|
||||
mov [gs:0], rsp
|
||||
mov rsp, [gs:8]
|
||||
|
||||
push 0
|
||||
push 0
|
||||
push rax
|
||||
push rcx
|
||||
push rdx
|
||||
push rbx
|
||||
push rbp
|
||||
push rsi
|
||||
push rdi
|
||||
push r8
|
||||
push r9
|
||||
push r10
|
||||
push r11
|
||||
push r12
|
||||
push r13
|
||||
push r14
|
||||
push r15
|
||||
|
||||
mov rdi, rsp
|
||||
call syscall_handle
|
||||
|
||||
pop r15
|
||||
pop r14
|
||||
pop r13
|
||||
pop r12
|
||||
pop r11
|
||||
pop r10
|
||||
pop r9
|
||||
pop r8
|
||||
pop rdi
|
||||
pop rsi
|
||||
pop rbp
|
||||
pop rbx
|
||||
pop rdx
|
||||
pop rcx
|
||||
pop rax
|
||||
add rsp, 16
|
||||
|
||||
mov [gs:8], rsp
|
||||
mov rsp, [gs:0]
|
||||
swapgs
|
||||
o64 sysret
|
|
@ -1,18 +0,0 @@
|
|||
#include <arch/x86_64/msr.h>
|
||||
#include <arch/x86_64/syscall.h>
|
||||
#include <stdint.h>
|
||||
|
||||
extern void syscall_entry();
|
||||
|
||||
void __x86_64_syscall_init() {
|
||||
uint64_t efer = rdmsr(IA32_EFER);
|
||||
efer |= (1 << 0);
|
||||
wrmsr(IA32_EFER, efer);
|
||||
uint64_t star = 0;
|
||||
star |= ((uint64_t)0x28 << 32); // kernel cs
|
||||
star |= ((uint64_t)0x30 << 48); // user cs base (SYSCALL adds 16 for CS=0x40, 24 for SS=0x38)
|
||||
wrmsr(IA32_STAR, star);
|
||||
wrmsr(IA32_LSTAR, (uint64_t)syscall_entry);
|
||||
wrmsr(IA32_CSTAR, 0x0);
|
||||
wrmsr(IA32_CSTAR + 1, 0x200);
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#define IA32_EFER 0xC0000080
|
||||
#define IA32_STAR 0xC0000081
|
||||
#define IA32_LSTAR 0xC0000082
|
||||
#define IA32_CSTAR 0xC0000083
|
||||
#define IA32_SFMASK 0xC0000084
|
30
kernel/src/boot/limine.c
Normal file
30
kernel/src/boot/limine.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
#include "deps/limine.h"
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <boot/limine.h>
|
||||
|
||||
__attribute__((used, section(".limine_requests")))
|
||||
static volatile LIMINE_BASE_REVISION(3);
|
||||
|
||||
__attribute__((used, section(".limine_requests")))
|
||||
static volatile struct limine_framebuffer_request framebuffer_request = {
|
||||
.id = LIMINE_FRAMEBUFFER_REQUEST,
|
||||
.revision = 0
|
||||
};
|
||||
|
||||
__attribute__((used, section(".limine_requests_start")))
|
||||
static volatile LIMINE_REQUESTS_START_MARKER;
|
||||
|
||||
__attribute__((used, section(".limine_requests_end")))
|
||||
static volatile LIMINE_REQUESTS_END_MARKER;
|
||||
|
||||
bool limine_ensure_baserev() { return LIMINE_BASE_REVISION_SUPPORTED; }
|
||||
|
||||
limine_fb_t *limine_get_fb(int id) {
|
||||
if (!framebuffer_request.response)
|
||||
return NULL;
|
||||
|
||||
if (id >= (int32_t)framebuffer_request.response->framebuffer_count) // Limine, WHY putting the FB count as a 64-bit integer??? I never seen someone with 0xFFFFFFFFFFFFFFFF screens
|
||||
return NULL;
|
||||
return framebuffer_request.response->framebuffers[id];
|
||||
}
|
12
kernel/src/boot/limine.h
Normal file
12
kernel/src/boot/limine.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include <deps/limine.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct limine_framebuffer limine_fb_t;
|
||||
|
||||
// Ensure that the used boot loader supports the kernel's LBP revision
|
||||
bool limine_ensure_baserev();
|
||||
|
||||
// Get a framebuffer
|
||||
limine_fb_t *limine_get_fb(int id);
|
|
@ -1,22 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// At Soaplin, we aren't doing module racism based on the license. (Ḭ̸̡̢̨̧̨̛͍͚̙̺̦̩͕̮̙̙̳̮͉̝̙̜͓̪͇̠̪̣̻̰͕̲̲̘̖̦͖͕͎̲̹͖̮̳̻̞̌͋̋̆͛̉͆ ̸̨͕͎̣̥͖͔̳̫̳͚̯̬̙̘͓̹̼̻̼̈̓̉ͅͅs̶̟͉̠̣̞͎͍̘̟̝̱̩̃͛̽͛̆͌̆̒̔̈́̎̿̐̈́͐̓̓͒͌̈̀̓͗̋̕͜͜͝͠͝͠ͅȩ̸̡̛͔̦̲̦̼̹̙̲͖͎̼̝̯̦̞̜͍̀̈́̈́͂̈́̍́̆̆̔͗́̆̀͑̀̔͆̄͐͐̆͠ę̸̨̢̢̧̛̛͕̱̯̲̦͕͖̦̝̯̮̤̫͙͔̲̬̯̗̗͈̬̳̙͙̼͉̩͚̼̮͚̖̰̗̤͓̘͂̾̒͋̀͂̏́̂̋̅̆̋̈̔̈́̀̔̈́̊̓͂͌̋̂́̍̀͒͊͊̓͌̃̚͘͜͝͠ ̸̧̡̧͍̼̹͇̞̘͇̯̞̣̝̲̳̦̟̱͇̥͈̟̝̹̳̫͕̜̬̥̯̬̟̤̖̹̙̩̰̈͗͆͌̊̽̾͝͝ͅy̵̡̡̢̞̭͔̰͔͔̖̥͕̙̳̯͍͉̦̦͓̥̞̝͖͕̰̼͖̲̮͚̲̜̰̱̘̯̤̌́̏̄̏́̈́̓ͅỡ̵̢̢̢̖̠͉̖̺̻̣̜̬̮͓̫͎͖͎̤̪̝̗̰͕͍͖̖̟͙͍̻̑͊̃̃̒̍̆̎̋̿͐̋̉̇̾͆̿̌̃̏̽̊̀͒̇̏̓̾̏̈́̓̿̏̚͠͝͝͝ͅu̸̧͕̟͉͉͖̰̝͕̞̪̖͙͙̅̒̅̂̑́,̶̢̡̡̧̛̲̬̞̘̻̗̩̫̗͓̪̬͚̗̖͕̰̣͙͍̯͇̩̭͎̖̝̬̻͖̟̩̙̩̝͓̤́̄̆̍̂̈̊̄͆̽̑̑̊̓̋͐̔̉̍͌̏̀̿͘͜͜͜ͅͅ ̴̢̛̛͈͚̳̣̮̬̲̲͈̮͓̭̗̈́̽̄͌̾̒́̔̌̐̽͋̓̄̉̆̑̃́̏̉̔̓̂̽̊͆̽̎̍̈͑́̌͑̍̕͘͘͝͠ͅL̵̙̯̦̬̱͍̣̹̱̝̓̒i̵̢̨̨̧̨̛̗̲͍͇̖̥̯͔̙̪̱͓̝̦̼̭̬̟̞̩̭͙̐̐͊̒͑̊͌̽̂̉͊̈́̌͒̆̐͐͒̉̀́̑́̅͛͐̕̕͝͝ͅͅņ̵̛͓̲͆̏̃̊̒̇̑̑̾̽͊̃͌̔́̌̈́̈́͛͆̒̀̿̎͒̑̃̈́̈́͂͐͂̕̚̕͘͜͠͠ư̸̧̯̤̲͚͖̯͖͈̠̽̏̈́̄̀͒̐̅̽̋̓̂̑̋̽͒̄̑̇̈́̆̈͛͆̿̈̉͆͗͊̎͂̇̽̋̅͊̀̚̚͝ś̶̛̗̥͇̖̠͓͆̀̅̓̓͆͆̐́̄͛̃͑̔̑̒͒͋͂̂́͋͂́͗̐͆̐̕͝͝͠)
|
||||
|
||||
typedef struct {
|
||||
const char* name;
|
||||
uint64_t addr;
|
||||
uint64_t size;
|
||||
} kernel_symbol_t;
|
||||
|
||||
#define EXPORT_SYMBOL(sym) \
|
||||
static const kernel_symbol_t __ksym_##sym \
|
||||
__attribute__((section(".ksyms"), used)) = { \
|
||||
.name = #sym, \
|
||||
.addr = (uint64_t)&sym, \
|
||||
.size = sizeof(sym) \
|
||||
}
|
||||
|
||||
extern const kernel_symbol_t __start_ksyms[];
|
||||
extern const kernel_symbol_t __stop_ksyms[];
|
|
@ -1,56 +0,0 @@
|
|||
#include "dbg/sym.h"
|
||||
#include "exec/elf.h"
|
||||
#include "limine.h"
|
||||
#include "sys/errhnd/panic.h"
|
||||
#include "sys/log.h"
|
||||
#include <lib/string.h>
|
||||
#include <mm/liballoc/liballoc.h>
|
||||
|
||||
static Elf64_Sym *__ksym_symtab;
|
||||
static char *__ksym_strtab;
|
||||
static int __ksym_symcount = 0;
|
||||
|
||||
__attribute__((used, section(".limine_requests"))) static volatile struct
|
||||
limine_executable_file_request exec_file_rq = {
|
||||
.id = LIMINE_EXECUTABLE_FILE_REQUEST, .revision = 3};
|
||||
|
||||
void ksym_init() {
|
||||
char *img = exec_file_rq.response->executable_file->address;
|
||||
Elf64_Ehdr *ehdr = (Elf64_Ehdr *)img;
|
||||
if (ehdr->e_ident[EI_MAG0] != ELFMAG0 || ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
|
||||
ehdr->e_ident[EI_MAG2] != ELFMAG2 || ehdr->e_ident[EI_MAG3] != ELFMAG3) {
|
||||
panic("kernel - how did i even boot? *starts galaxy brain meme*");
|
||||
}
|
||||
|
||||
Elf64_Shdr *shdr = (Elf64_Shdr *)(img + ehdr->e_shoff);
|
||||
const char *shstrtab = (char *)img + shdr[ehdr->e_shstrndx].sh_offset;
|
||||
|
||||
for (int j = 0; j < ehdr->e_shnum; j++) {
|
||||
if (shdr[j].sh_type == SHT_SYMTAB) {
|
||||
__ksym_symtab = (Elf64_Sym *)(img + shdr[j].sh_offset);
|
||||
__ksym_symcount = shdr[j].sh_size / shdr[j].sh_entsize;
|
||||
} else if (shdr[j].sh_type == SHT_STRTAB &&
|
||||
strcmp(shstrtab + shdr[j].sh_name, ".strtab") == 0) {
|
||||
__ksym_strtab = (char *)(img + shdr[j].sh_offset);
|
||||
}
|
||||
}
|
||||
|
||||
log("kernel - loaded %d symbols\n", __ksym_symcount);
|
||||
}
|
||||
|
||||
func *ksym_fromip(uint64_t ip) {
|
||||
for (int i = 0; i < __ksym_symcount; i++) {
|
||||
uint64_t value = __ksym_symtab[i].st_value;
|
||||
uint64_t size = __ksym_symtab[i].st_size;
|
||||
|
||||
if (value <= ip && ip < (value + size)) {
|
||||
func *f = malloc(sizeof(func));
|
||||
f->base = value;
|
||||
f->ip = ip;
|
||||
f->name = (__ksym_strtab + __ksym_symtab[i].st_name);
|
||||
return f;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "mm/vmm.h"
|
||||
|
||||
typedef struct func {
|
||||
uint64_t base;
|
||||
uint64_t ip;
|
||||
char *name;
|
||||
} func;
|
||||
|
||||
void ksym_init();
|
||||
func *ksym_fromip(uint64_t ip);
|
|
@ -1,113 +0,0 @@
|
|||
#include "sys/acpi/madt.h"
|
||||
#include <dev/ioapic.h>
|
||||
#include <mm/pmm.h>
|
||||
#include <sys/log.h>
|
||||
|
||||
void ioapic_init() {
|
||||
madt_ioapic *ioapic = acpi_madt_ioapic_list[0];
|
||||
|
||||
uint32_t val = ioapic_read(ioapic, IOAPIC_VER);
|
||||
uint32_t count = ((val >> 16) & 0xFF);
|
||||
|
||||
if ((ioapic_read(ioapic, 0) >> 24) != ioapic->apic_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i <= count; ++i) {
|
||||
ioapic_write(ioapic, IOAPIC_REDTBL + 2 * i, 0x00010000 | (32 + i));
|
||||
ioapic_write(ioapic, IOAPIC_REDTBL + 2 * i + 1, 0);
|
||||
}
|
||||
|
||||
log("ioapic - initialized\n");
|
||||
}
|
||||
|
||||
void ioapic_write(madt_ioapic *ioapic, uint8_t reg, uint32_t val) {
|
||||
*((volatile uint32_t *)(HIGHER_HALF(ioapic->apic_addr) + IOAPIC_REGSEL)) =
|
||||
reg;
|
||||
*((volatile uint32_t *)(HIGHER_HALF(ioapic->apic_addr) + IOAPIC_IOWIN)) = val;
|
||||
}
|
||||
|
||||
uint32_t ioapic_read(madt_ioapic *ioapic, uint8_t reg) {
|
||||
*((volatile uint32_t *)(HIGHER_HALF(ioapic->apic_addr) + IOAPIC_REGSEL)) =
|
||||
reg;
|
||||
return *(
|
||||
(volatile uint32_t *)(HIGHER_HALF(ioapic->apic_addr) + IOAPIC_IOWIN));
|
||||
}
|
||||
|
||||
void ioapic_set_entry(madt_ioapic *ioapic, uint8_t idx, uint64_t data) {
|
||||
ioapic_write(ioapic, (uint8_t)(IOAPIC_REDTBL + idx * 2), (uint32_t)data);
|
||||
ioapic_write(ioapic, (uint8_t)(IOAPIC_REDTBL + idx * 2 + 1),
|
||||
(uint32_t)(data >> 32));
|
||||
}
|
||||
|
||||
uint64_t ioapic_gsi_count(madt_ioapic *ioapic) {
|
||||
return (ioapic_read(ioapic, 1) & 0xff0000) >> 16;
|
||||
}
|
||||
|
||||
madt_ioapic *ioapic_get_gsi(uint32_t gsi) {
|
||||
for (uint64_t i = 0; i < acpi_madt_ioapic_length; i++) {
|
||||
madt_ioapic *ioapic = acpi_madt_ioapic_list[i];
|
||||
if (ioapic->gsi_base <= gsi &&
|
||||
ioapic->gsi_base + ioapic_gsi_count(ioapic) > gsi)
|
||||
return ioapic;
|
||||
}
|
||||
return (madt_ioapic *)0;
|
||||
}
|
||||
|
||||
void ioapic_redirect_gsi(uint32_t lapic_id, uint8_t vec, uint32_t gsi,
|
||||
uint16_t flags, bool mask) {
|
||||
madt_ioapic *ioapic = ioapic_get_gsi(gsi);
|
||||
|
||||
uint64_t redirect = vec;
|
||||
|
||||
if ((flags & (1 << 1)) != 0) {
|
||||
redirect |= (1 << 13);
|
||||
}
|
||||
|
||||
if ((flags & (1 << 3)) != 0) {
|
||||
redirect |= (1 << 15);
|
||||
}
|
||||
|
||||
if (mask)
|
||||
redirect |= (1 << 16);
|
||||
else
|
||||
redirect &= ~(1 << 16);
|
||||
|
||||
redirect |= (uint64_t)lapic_id << 56;
|
||||
|
||||
uint32_t redir_table = (gsi - ioapic->gsi_base) * 2 + 16;
|
||||
ioapic_write(ioapic, redir_table, (uint32_t)redirect);
|
||||
ioapic_write(ioapic, redir_table + 1, (uint32_t)(redirect >> 32));
|
||||
}
|
||||
|
||||
void ioapic_redirect_irq(uint32_t lapic_id, uint8_t vec, uint8_t irq,
|
||||
bool mask) {
|
||||
uint8_t idx = 0;
|
||||
madt_iso *iso = (madt_iso *)0;
|
||||
|
||||
while (idx < acpi_madt_iso_length) {
|
||||
iso = acpi_madt_iso_list[idx];
|
||||
if (iso->irq_src == irq) {
|
||||
ioapic_redirect_gsi(lapic_id, vec, iso->gsi, iso->flags, mask);
|
||||
return;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
|
||||
ioapic_redirect_gsi(lapic_id, vec, irq, 0, mask);
|
||||
}
|
||||
|
||||
uint32_t ioapic_get_redirect_irq(uint8_t irq) {
|
||||
uint8_t idx = 0;
|
||||
madt_iso *iso;
|
||||
|
||||
while (idx < acpi_madt_iso_length) {
|
||||
iso = acpi_madt_iso_list[idx];
|
||||
if (iso->irq_src == irq) {
|
||||
return iso->gsi;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
|
||||
return irq;
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <sys/acpi.h>
|
||||
#include <sys/acpi/madt.h>
|
||||
|
||||
#define IOAPIC_REGSEL 0x0
|
||||
#define IOAPIC_IOWIN 0x10
|
||||
|
||||
#define IOAPIC_ID 0x0
|
||||
#define IOAPIC_VER 0x01
|
||||
#define IOAPIC_ARB 0x02
|
||||
#define IOAPIC_REDTBL 0x10
|
||||
|
||||
void ioapic_write(madt_ioapic *ioapic, uint8_t reg, uint32_t val);
|
||||
uint32_t ioapic_read(madt_ioapic *ioapic, uint8_t reg);
|
||||
|
||||
void ioapic_redirect_irq(uint32_t lapic_id, uint8_t vec, uint8_t irq,
|
||||
bool mask);
|
||||
uint32_t ioapic_get_redirect_irq(uint8_t irq);
|
||||
|
||||
void ioapic_set_entry(madt_ioapic *ioapic, uint8_t idx, uint64_t data);
|
||||
|
||||
void ioapic_init();
|
|
@ -1,60 +0,0 @@
|
|||
#include "mm/pmm.h"
|
||||
#include <dev/lapic.h>
|
||||
#include <sys/log.h>
|
||||
|
||||
uint64_t apic_ticks = 0;
|
||||
|
||||
void lapic_init() {
|
||||
lapic_write(0xf0, 0x1ff);
|
||||
log("lapic - initialized\n");
|
||||
}
|
||||
|
||||
void lapic_stop_timer() {
|
||||
// We do this to avoid overlapping oneshots
|
||||
lapic_write(LAPIC_TIMER_INITCNT, 0);
|
||||
lapic_write(LAPIC_TIMER_LVT, LAPIC_TIMER_DISABLE);
|
||||
}
|
||||
|
||||
void lapic_oneshot(uint8_t vec, uint64_t ms) {
|
||||
lapic_stop_timer();
|
||||
lapic_write(LAPIC_TIMER_DIV, 0);
|
||||
lapic_write(LAPIC_TIMER_LVT, vec);
|
||||
lapic_write(LAPIC_TIMER_INITCNT, apic_ticks * ms);
|
||||
}
|
||||
|
||||
void lapic_calibrate_timer() {
|
||||
lapic_stop_timer();
|
||||
lapic_write(LAPIC_TIMER_DIV, 0);
|
||||
lapic_write(LAPIC_TIMER_LVT, (1 << 16) | 0xff);
|
||||
lapic_write(LAPIC_TIMER_INITCNT, 0xFFFFFFFF);
|
||||
// pit_sleep(1); // 1 ms
|
||||
lapic_write(LAPIC_TIMER_LVT, LAPIC_TIMER_DISABLE);
|
||||
uint32_t ticks = 0xFFFFFFFF - lapic_read(LAPIC_TIMER_CURCNT);
|
||||
apic_ticks = ticks;
|
||||
lapic_stop_timer();
|
||||
}
|
||||
|
||||
void lapic_write(uint32_t reg, uint32_t val) {
|
||||
*((volatile uint32_t *)(HIGHER_HALF(0xfee00000) + reg)) = val;
|
||||
}
|
||||
|
||||
uint32_t lapic_read(uint32_t reg) {
|
||||
return *((volatile uint32_t *)(HIGHER_HALF(0xfee00000) + reg));
|
||||
}
|
||||
|
||||
void lapic_eoi() { lapic_write((uint8_t)0xb0, 0x0); }
|
||||
|
||||
void lapic_ipi(uint32_t id, uint8_t dat) {
|
||||
lapic_write(LAPIC_ICRHI, id << LAPIC_ICDESTSHIFT);
|
||||
lapic_write(LAPIC_ICRLO, dat);
|
||||
}
|
||||
|
||||
void lapic_send_all_int(uint32_t id, uint32_t vec) {
|
||||
lapic_ipi(id, vec | LAPIC_ICRAIS);
|
||||
}
|
||||
|
||||
void lapic_send_others_int(uint32_t id, uint32_t vec) {
|
||||
lapic_ipi(id, vec | LAPIC_ICRAES);
|
||||
}
|
||||
|
||||
uint32_t lapic_get_id() { return lapic_read(0x0020) >> LAPIC_ICDESTSHIFT; }
|
|
@ -1,52 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <sys/acpi.h>
|
||||
#include <sys/acpi/madt.h>
|
||||
|
||||
#define LAPIC_PPR 0x00a0
|
||||
|
||||
#define LAPIC_ICRLO 0x0300
|
||||
#define LAPIC_ICRHI 0x0310
|
||||
|
||||
#define LAPIC_ICINI 0x0500
|
||||
#define LAPIC_ICSTR 0x0600
|
||||
|
||||
#define LAPIC_ICEDGE 0x0000
|
||||
|
||||
#define LAPIC_ICPEND 0x00001000
|
||||
#define LAPIC_ICPHYS 0x00000000
|
||||
#define LAPIC_ICASSR 0x00004000
|
||||
#define LAPIC_ICSHRTHND 0x00000000
|
||||
#define LAPIC_ICDESTSHIFT 24
|
||||
|
||||
#define LAPIC_ICRAIS 0x00080000
|
||||
#define LAPIC_ICRAES 0x000c0000
|
||||
|
||||
// Timer
|
||||
|
||||
#define LAPIC_TIMER_DIV 0x3E0
|
||||
#define LAPIC_TIMER_INITCNT 0x380
|
||||
#define LAPIC_TIMER_LVT 0x320
|
||||
#define LAPIC_TIMER_DISABLE 0x10000
|
||||
#define LAPIC_TIMER_CURCNT 0x390
|
||||
#define LAPIC_TIMER_PERIODIC 0x20000
|
||||
|
||||
void lapic_init();
|
||||
|
||||
void lapic_stop_timer();
|
||||
void lapic_oneshot(uint8_t vec, uint64_t ms);
|
||||
void lapic_calibrate_timer();
|
||||
|
||||
void lapic_write(uint32_t reg, uint32_t val);
|
||||
uint32_t lapic_read(uint32_t reg);
|
||||
|
||||
void lapic_eoi();
|
||||
|
||||
void lapic_ipi(uint32_t id, uint8_t dat);
|
||||
|
||||
void lapic_send_all_int(uint32_t id, uint32_t vec);
|
||||
void lapic_send_others_int(uint32_t id, uint32_t vec);
|
||||
|
||||
void lapic_init_cpu(uint32_t id);
|
||||
void lapic_start_cpu(uint32_t id, uint32_t vec);
|
||||
uint32_t lapic_get_id();
|
31
kernel/src/dev/tty.c
Normal file
31
kernel/src/dev/tty.c
Normal file
|
@ -0,0 +1,31 @@
|
|||
|
||||
#include <boot/limine.h>
|
||||
#include <deps/flanterm/backends/fb.h>
|
||||
#include <deps/flanterm/flanterm.h>
|
||||
#include <lib/string.h>
|
||||
|
||||
struct flanterm_context *tty0_ctx;
|
||||
|
||||
void tty_init() {
|
||||
limine_fb_t *fb0 = limine_get_fb(0);
|
||||
|
||||
tty0_ctx = flanterm_fb_init(
|
||||
NULL,
|
||||
NULL,
|
||||
fb0->address, fb0->width, fb0->height, fb0->pitch,
|
||||
fb0->red_mask_size, fb0->red_mask_shift,
|
||||
fb0->green_mask_size, fb0->green_mask_shift,
|
||||
fb0->blue_mask_size, fb0->blue_mask_shift,
|
||||
NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
NULL, 0, 0, 1,
|
||||
0, 0,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
void tty_write_raw(char *str) {
|
||||
flanterm_write(tty0_ctx, str, strlen(str));
|
||||
}
|
4
kernel/src/dev/tty.h
Normal file
4
kernel/src/dev/tty.h
Normal file
|
@ -0,0 +1,4 @@
|
|||
#pragma once
|
||||
|
||||
void tty_init();
|
||||
void tty_write_raw(char *str);
|
|
@ -1,135 +0,0 @@
|
|||
#include "exec/exec.h"
|
||||
#include "mm/memop.h"
|
||||
#include "mm/pmm.h"
|
||||
#include "mm/vmm.h"
|
||||
#include <exec/elf.h>
|
||||
#include <mm/liballoc/liballoc.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/log.h>
|
||||
|
||||
program_t *elf_load(char *data, int user) {
|
||||
Elf64_Ehdr *ehdr = (Elf64_Ehdr *)data;
|
||||
if (ehdr->e_ident[EI_MAG0] != ELFMAG0 || ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
|
||||
ehdr->e_ident[EI_MAG2] != ELFMAG2 || ehdr->e_ident[EI_MAG3] != ELFMAG3) {
|
||||
log("elf - loading failed: magic is incorrect\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
log("elf - e_ident[EI_DATA]: %d\n", ehdr->e_ident[EI_DATA]);
|
||||
log("elf - e_ident[EI_CLASS]: %d\n", ehdr->e_ident[EI_CLASS]);
|
||||
log("elf - e_ident[EI_OSABI]: %d\n", ehdr->e_ident[EI_OSABI]);
|
||||
log("elf - e_machine: %d\n", ehdr->e_machine);
|
||||
log("elf - e_entry: %p\n", ehdr->e_entry);
|
||||
log("elf - e_type: %p\n", ehdr->e_type);
|
||||
log("elf - e_phnum: %p\n", ehdr->e_phnum);
|
||||
|
||||
if (ehdr->e_ident[EI_CLASS] != ELFCLASS64 || ehdr->e_machine != EM_X86_64) {
|
||||
log("elf - loading failed: is the file built for amd64?\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ehdr->e_type != ET_EXEC) {
|
||||
log("elf - loading failed: ELF type isn't ET_EXEC\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// There's the interesing part
|
||||
elf_program_t *ret =
|
||||
malloc(sizeof(elf_program_t)); // Allocate memory for the program.
|
||||
|
||||
pagemap_t *pm = vmm_alloc_pm(); // Allocate a pagemap, so that we can map the
|
||||
// program inside.
|
||||
ret->program.pm = pm;
|
||||
ret->program.entry = ehdr->e_entry;
|
||||
ret->ehdr = ehdr;
|
||||
|
||||
Elf64_Phdr *phdr = (Elf64_Phdr *)((uint8_t *)data + ehdr->e_phoff);
|
||||
|
||||
for (uint16_t i = 0; i < ehdr->e_phnum; i++) {
|
||||
log("elf - ELF segment type: %d\n", phdr[i].p_type);
|
||||
|
||||
if (phdr[i].p_type == PT_INTERP) {
|
||||
log("elf - A PT_INTERP program header was found. This was meant to be a dynamically-linked program, which Soaplin doesn't supports.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (phdr[i].p_type != PT_LOAD)
|
||||
continue;
|
||||
|
||||
uint64_t vaddr_start = ALIGN_DOWN(phdr[i].p_vaddr, PMM_PAGE_SIZE);
|
||||
uint64_t vaddr_end =
|
||||
ALIGN_UP(phdr[i].p_vaddr + phdr[i].p_memsz, PMM_PAGE_SIZE);
|
||||
uint64_t offset = phdr[i].p_offset;
|
||||
|
||||
uint64_t flags = VMM_PRESENT;
|
||||
if (phdr[i].p_flags & PF_W)
|
||||
flags |= VMM_WRITABLE;
|
||||
if (phdr[i].p_flags & PF_X)
|
||||
flags &= ~VMM_NX;
|
||||
else
|
||||
flags |= VMM_NX;
|
||||
|
||||
if (user)
|
||||
flags |= VMM_USER;
|
||||
|
||||
log("elf - loading ELF program header %u: vaddr 0x%llx - 0x%llx, offset "
|
||||
"0x%llx, filesz 0x%llx, size 0x%llx, flags 0x%llx\n",
|
||||
i, vaddr_start, vaddr_end, offset, phdr[i].p_filesz, phdr[i].p_memsz,
|
||||
flags);
|
||||
|
||||
uint64_t page_offset = phdr[i].p_vaddr & (PMM_PAGE_SIZE - 1);
|
||||
|
||||
for (uint64_t vaddr = vaddr_start; vaddr < vaddr_end;
|
||||
vaddr += PMM_PAGE_SIZE) {
|
||||
uint64_t phys = (uint64_t)pmm_request_page();
|
||||
if (!phys) {
|
||||
log("elf - pmm page alloc failed. out of memory?\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (user) {
|
||||
log("elf - vmm_map_user(%p, %p, %p, %d)\n", pm, vaddr, phys, flags);
|
||||
vmm_map_user(pm, vaddr, phys, flags);
|
||||
} else {
|
||||
log("elf - vmm_map(%p, %p, %p, %d)\n", pm, vaddr, phys, flags);
|
||||
vmm_map(pm, vaddr, phys, flags);
|
||||
}
|
||||
log("elf - memset(%p, 0, 0x1000)\n", HIGHER_HALF(phys));
|
||||
memset((void *)HIGHER_HALF(phys), 0, PMM_PAGE_SIZE);
|
||||
|
||||
uint64_t file_page_offset = offset + (vaddr - vaddr_start);
|
||||
uint64_t file_data_end = offset + phdr[i].p_filesz;
|
||||
|
||||
if (file_page_offset < file_data_end) {
|
||||
uint64_t bytes_from_start = vaddr - vaddr_start;
|
||||
uint64_t page_data_offset = 0;
|
||||
|
||||
if (bytes_from_start == 0 && page_offset > 0) {
|
||||
page_data_offset = page_offset;
|
||||
}
|
||||
|
||||
uint64_t copy_offset = file_page_offset;
|
||||
uint64_t copy_size = PMM_PAGE_SIZE - page_data_offset;
|
||||
|
||||
if (copy_offset + copy_size > file_data_end) {
|
||||
copy_size = file_data_end - copy_offset;
|
||||
}
|
||||
|
||||
if (copy_size > 0) {
|
||||
void *dest = (void *)(HIGHER_HALF(phys) + page_data_offset);
|
||||
void *src = (uint8_t *)data + copy_offset;
|
||||
log("elf - memcpy(%p, %p, %d)\n", dest, src, copy_size);
|
||||
memcpy(dest, src, copy_size);
|
||||
|
||||
// log("elf - copied 0x%llx bytes from ELF file offset 0x%llx to vaddr
|
||||
// 0x%llx (phys 0x%llx)\n",
|
||||
// copy_size, copy_offset, vaddr + page_data_offset, phys +
|
||||
// page_data_offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log("elf - loaded ELF program in memory.\n");
|
||||
return (program_t *)ret;
|
||||
}
|
|
@ -1,153 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "exec/exec.h"
|
||||
#include <stdint.h>
|
||||
|
||||
// ELF magic.
|
||||
#define EI_MAG0 0
|
||||
#define ELFMAG0 0x7f
|
||||
|
||||
#define EI_MAG1 1
|
||||
#define ELFMAG1 'E'
|
||||
|
||||
#define EI_MAG2 2
|
||||
#define ELFMAG2 'L'
|
||||
|
||||
#define EI_MAG3 3
|
||||
#define ELFMAG3 'F'
|
||||
|
||||
// ELF class
|
||||
#define EI_CLASS 4
|
||||
#define ELFCLASSNONE 0
|
||||
#define ELFCLASS32 1
|
||||
#define ELFCLASS64 2
|
||||
|
||||
// Is processor-specific data little-endian or big-endian?
|
||||
#define EI_DATA 5
|
||||
#define ELFDATANONE 0
|
||||
#define ELFDATA2LSB 1
|
||||
#define ELFDATA2MSB 2
|
||||
|
||||
// ELF version
|
||||
#define EI_VERSION 6
|
||||
#define EV_NONE 0
|
||||
#define EV_CURRENT 1
|
||||
|
||||
// ELF ABI
|
||||
#define EI_OSABI 7
|
||||
#define ELFOSABI_NONE 0
|
||||
#define ELFOSABI_SYSV 0
|
||||
#define ELFOSABI_HPUX 1
|
||||
#define ELFOSABI_NETBSD 2
|
||||
#define ELFOSABI_LINUX 3
|
||||
#define ELFOSABI_SOLARIS 6
|
||||
#define ELFOSABI_IRIX 8
|
||||
#define ELFOSABI_FREEBSD 9
|
||||
#define ELFOSABI_TRU64 10
|
||||
#define ELFOSABI_ARM 97
|
||||
#define ELFOSABI_STANDALONE 255
|
||||
|
||||
// ABI version
|
||||
#define EI_ABIVERSION 8
|
||||
|
||||
// Unused bytes.
|
||||
#define EI_PAD 9
|
||||
|
||||
// Magic size.
|
||||
#define EI_NIDENT 16
|
||||
|
||||
// e_type
|
||||
#define ET_NONE 0
|
||||
#define ET_REL 1
|
||||
#define ET_EXEC 2
|
||||
#define ET_DYN 3
|
||||
#define ET_CORE 4
|
||||
|
||||
// e_machine (we only included machines supported by Soaplin.)
|
||||
#define EM_X86_64 62
|
||||
|
||||
typedef uint64_t Elf64_Addr;
|
||||
typedef uint64_t Elf64_Off;
|
||||
typedef uint16_t Elf64_Section;
|
||||
typedef uint16_t Elf64_Versym;
|
||||
typedef uint8_t Elf_Byte;
|
||||
typedef uint16_t Elf64_Half;
|
||||
typedef int32_t Elf64_Sword;
|
||||
typedef uint32_t Elf64_Word;
|
||||
typedef int64_t Elf64_Sxword;
|
||||
typedef uint64_t Elf64_Xword;
|
||||
|
||||
typedef struct {
|
||||
unsigned char e_ident[EI_NIDENT];
|
||||
uint16_t e_type;
|
||||
uint16_t e_machine;
|
||||
uint32_t e_version;
|
||||
Elf64_Addr e_entry;
|
||||
Elf64_Off e_phoff;
|
||||
Elf64_Off e_shoff;
|
||||
uint32_t e_flags;
|
||||
uint16_t e_ehsize;
|
||||
uint16_t e_phentsize;
|
||||
uint16_t e_phnum;
|
||||
uint16_t e_shentsize;
|
||||
uint16_t e_shnum;
|
||||
uint16_t e_shstrndx;
|
||||
} Elf64_Ehdr;
|
||||
|
||||
#define PT_NULL 0
|
||||
#define PT_LOAD 1
|
||||
#define PT_DYNAMIC 2
|
||||
#define PT_INTERP 3
|
||||
#define PT_NOTE 4
|
||||
#define PT_SHLIB 5
|
||||
|
||||
#define PF_X (1 << 0)
|
||||
#define PF_W (1 << 1)
|
||||
#define PF_R (1 << 2)
|
||||
|
||||
typedef struct {
|
||||
uint32_t p_type;
|
||||
uint32_t p_flags;
|
||||
Elf64_Off p_offset;
|
||||
Elf64_Addr p_vaddr;
|
||||
Elf64_Addr p_paddr;
|
||||
uint64_t p_filesz;
|
||||
uint64_t p_memsz;
|
||||
uint64_t p_align;
|
||||
} Elf64_Phdr;
|
||||
|
||||
typedef struct {
|
||||
program_t program;
|
||||
|
||||
Elf64_Ehdr *ehdr;
|
||||
} elf_program_t;
|
||||
|
||||
program_t *elf_load(char *data, int user);
|
||||
|
||||
// Those aren't used for loading, but used by
|
||||
// the kernel to resolve symbols from an instruction
|
||||
// pointer.
|
||||
#define SHT_SYMTAB 2
|
||||
#define SHT_STRTAB 3
|
||||
|
||||
typedef struct {
|
||||
uint32_t st_name;
|
||||
unsigned char st_info;
|
||||
unsigned char st_other;
|
||||
uint16_t st_shndx;
|
||||
Elf64_Addr st_value;
|
||||
uint64_t st_size;
|
||||
} Elf64_Sym;
|
||||
|
||||
typedef struct {
|
||||
uint32_t sh_name;
|
||||
uint32_t sh_type;
|
||||
uint64_t sh_flags;
|
||||
Elf64_Addr sh_addr;
|
||||
Elf64_Off sh_offset;
|
||||
uint64_t sh_size;
|
||||
uint32_t sh_link;
|
||||
uint32_t sh_info;
|
||||
uint64_t sh_addralign;
|
||||
uint64_t sh_entsize;
|
||||
} Elf64_Shdr;
|
|
@ -1,28 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* A program (or a script, if a shebang is found inside), literally.
|
||||
*/
|
||||
#include "mm/vmm.h"
|
||||
|
||||
#define EXEC_TYPE_ELF 0
|
||||
|
||||
typedef struct {
|
||||
// The path to the program/script that will be executed.
|
||||
char *path;
|
||||
|
||||
// The pagemap where the program's code is loaded.
|
||||
pagemap_t *pm;
|
||||
|
||||
// The path to the first instruction. This will be passed to the new process's
|
||||
// rip register.
|
||||
uint64_t entry;
|
||||
|
||||
// The program type. Used to get additional, unneeded information out of a
|
||||
// program
|
||||
int type;
|
||||
|
||||
// That is what Soaplin needs to know. Executable file loaders are encouraged
|
||||
// to extend this structure to include info such as the EHDR for the ELF
|
||||
// loader...
|
||||
} program_t;
|
|
@ -1,343 +0,0 @@
|
|||
unsigned char VGA8[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd,
|
||||
0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff,
|
||||
0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe,
|
||||
0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
|
||||
0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c,
|
||||
0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd,
|
||||
0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x1e, 0x0e,
|
||||
0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30,
|
||||
0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x63,
|
||||
0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8,
|
||||
0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0e,
|
||||
0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
|
||||
0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xdb,
|
||||
0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6,
|
||||
0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c,
|
||||
0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
|
||||
0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x28, 0x6c, 0xfe, 0x6c, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c,
|
||||
0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c,
|
||||
0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c,
|
||||
0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18,
|
||||
0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c,
|
||||
0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30,
|
||||
0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18,
|
||||
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e,
|
||||
0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xd6, 0xd6, 0xc6, 0xc6, 0x6c, 0x38,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6,
|
||||
0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe,
|
||||
0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0,
|
||||
0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18,
|
||||
0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6,
|
||||
0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
|
||||
0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00,
|
||||
0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
|
||||
0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xde, 0xde,
|
||||
0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38,
|
||||
0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0,
|
||||
0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x6c,
|
||||
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68,
|
||||
0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66,
|
||||
0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c,
|
||||
0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60,
|
||||
0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xee,
|
||||
0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
|
||||
0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66,
|
||||
0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c,
|
||||
0x0c, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c,
|
||||
0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6,
|
||||
0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
|
||||
0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6,
|
||||
0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x38,
|
||||
0x7c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66,
|
||||
0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xfe, 0xc6, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||
0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
|
||||
0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c,
|
||||
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
|
||||
0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c,
|
||||
0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x60,
|
||||
0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc,
|
||||
0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc,
|
||||
0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, 0x00, 0x00, 0xe0, 0x60,
|
||||
0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06,
|
||||
0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0xe0, 0x60,
|
||||
0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6,
|
||||
0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66,
|
||||
0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60,
|
||||
0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30,
|
||||
0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66,
|
||||
0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6,
|
||||
0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18,
|
||||
0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6,
|
||||
0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66,
|
||||
0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00,
|
||||
0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe,
|
||||
0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c,
|
||||
0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c,
|
||||
0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38,
|
||||
0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06,
|
||||
0x3c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe,
|
||||
0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00,
|
||||
0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66,
|
||||
0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6,
|
||||
0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00,
|
||||
0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
|
||||
0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x76, 0x36,
|
||||
0x7e, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x6c,
|
||||
0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6,
|
||||
0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18,
|
||||
0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc,
|
||||
0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00,
|
||||
0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00,
|
||||
0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
|
||||
0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x3c,
|
||||
0x66, 0x60, 0x60, 0x60, 0x66, 0x3c, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18,
|
||||
0x7e, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xcc, 0xcc,
|
||||
0xf8, 0xc4, 0xcc, 0xde, 0xcc, 0xcc, 0xcc, 0xc6, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0xd8, 0x70, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c,
|
||||
0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30,
|
||||
0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc,
|
||||
0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc,
|
||||
0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
|
||||
0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c,
|
||||
0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0,
|
||||
0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xdc, 0x86, 0x0c,
|
||||
0x18, 0x3e, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30,
|
||||
0x66, 0xce, 0x9e, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18,
|
||||
0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36,
|
||||
0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x44, 0x11, 0x44,
|
||||
0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44,
|
||||
0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
|
||||
0x55, 0xaa, 0x55, 0xaa, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77,
|
||||
0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36,
|
||||
0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36,
|
||||
0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36,
|
||||
0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||
0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6,
|
||||
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||
0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37,
|
||||
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||
0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36,
|
||||
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||
0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36,
|
||||
0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36,
|
||||
0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36,
|
||||
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
|
||||
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||
0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0,
|
||||
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
|
||||
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
|
||||
0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0,
|
||||
0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8,
|
||||
0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66,
|
||||
0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38,
|
||||
0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66,
|
||||
0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60,
|
||||
0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c,
|
||||
0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18,
|
||||
0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
|
||||
0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00,
|
||||
0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c,
|
||||
0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c,
|
||||
0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00};
|
|
@ -1,3 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
extern unsigned char VGA8[];
|
|
@ -1,101 +0,0 @@
|
|||
#include "fs/hellofs.h"
|
||||
#include "fs/vfs.h"
|
||||
#include <mm/liballoc/liballoc.h>
|
||||
#include <mm/memop.h>
|
||||
#include <lib/string.h>
|
||||
|
||||
static int hellofs_read(vnode_t *vn, void *buf, size_t off, size_t size) {
|
||||
if (!vn || !buf || size <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char *hello = "hello";
|
||||
const size_t hello_len = 5; // strlen("hello")
|
||||
char *cbuf = (char *)buf;
|
||||
size_t bytes_written = 0;
|
||||
|
||||
while (bytes_written < size) {
|
||||
size_t pos = off % hello_len; // Position within "hello"
|
||||
size_t remaining = hello_len - pos; // Remaining bytes in current "hello"
|
||||
size_t to_copy = (size - bytes_written < remaining) ?
|
||||
(size - bytes_written) : remaining;
|
||||
|
||||
memcpy(cbuf + bytes_written, hello + pos, to_copy);
|
||||
bytes_written += to_copy;
|
||||
off += to_copy;
|
||||
}
|
||||
|
||||
return bytes_written;
|
||||
}
|
||||
|
||||
vnode_ops_t hellofs_hello_ops = {
|
||||
.read = hellofs_read,
|
||||
.lookup = NULL,
|
||||
};
|
||||
|
||||
static int hellofs_lookup(vnode_t *vn, const char *name, vnode_t **out) {
|
||||
if (!vn || !name || !out) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strcmp(name, "hello") == 0) {
|
||||
*out = vfs_create_node("hello", VN_FILE);
|
||||
if (*out) {
|
||||
(*out)->ops = &hellofs_hello_ops;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
} else {
|
||||
*out = NULL; // Not found
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
vnode_ops_t hellofs_root_ops = {
|
||||
.read = NULL,
|
||||
.lookup = hellofs_lookup,
|
||||
};
|
||||
|
||||
static int hellofs_mount(fs_t *fs, vnode_t *mountpoint) {
|
||||
if (!fs || !mountpoint) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// mountpoint list isn't implemented.
|
||||
|
||||
/*mountpoint_t *mp = (mountpoint_t *)malloc(sizeof(mountpoint_t));
|
||||
if (!mp) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(mp, 0, sizeof(mountpoint_t));
|
||||
strncpy(mp->name, fs->name, sizeof(mp->name) - 1);
|
||||
mp->fs = fs;
|
||||
mp->mountpoint = mountpoint;*/
|
||||
|
||||
// Mounting is essentially just putting the file system's root directory operations
|
||||
// on the mountpoint vnode.
|
||||
mountpoint->ops = &hellofs_root_ops;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
fs_t *hellofs_init() {
|
||||
fs_t *fs = (fs_t *)malloc(sizeof(fs_t));
|
||||
if (!fs) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(fs, 0, sizeof(fs_t));
|
||||
strncpy(fs->name, "hellofs", sizeof(fs->name) - 1);
|
||||
|
||||
fs->mount = hellofs_mount;
|
||||
fs->root = vfs_create_node("/", VN_DIR);
|
||||
if (!fs->root) {
|
||||
free(fs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return fs;
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <fs/vfs.h>
|
||||
|
||||
fs_t *hellofs_init(void);
|
|
@ -1,112 +0,0 @@
|
|||
#include "fs/vfs.h"
|
||||
#include "lib/string.h"
|
||||
#include "mm/liballoc/liballoc.h"
|
||||
#include "mm/memop.h"
|
||||
#include "sys/errhnd/panic.h"
|
||||
|
||||
vnode_t *root = NULL;
|
||||
|
||||
void vfs_init() {
|
||||
root = vfs_create_node("/", VN_DIR);
|
||||
if (!root) {
|
||||
panic("vfs - failed to create root node");
|
||||
}
|
||||
root->parent = root; // Root's parent is itself
|
||||
}
|
||||
|
||||
// Not worth adding to the header, since it should only lookup
|
||||
// for files/directories in dir, without going deeper.
|
||||
int vfs_lookup(vnode_t *dir, const char *name, vnode_t **out) {
|
||||
if (!dir || !name)
|
||||
return -1;
|
||||
|
||||
if (dir->ops && dir->ops->lookup) {
|
||||
return dir->ops->lookup(dir, name, out);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int vfs_open(vnode_t *curdir, const char *path, vnode_t **out) {
|
||||
if (strcmp(path, ".") == 0) {
|
||||
*out = curdir;
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(path, "..") == 0) {
|
||||
*out = curdir->parent;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *path_copy = strdup(path);
|
||||
if (!path_copy) {
|
||||
*out = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
vnode_t *cur_node = path[0] == '/' ? root : curdir;
|
||||
char *token = strtok(path_copy, "/");
|
||||
|
||||
while (token) {
|
||||
vnode_t *next;
|
||||
vfs_lookup(cur_node, token, &next);
|
||||
if (!next) {
|
||||
free(path_copy);
|
||||
*out = NULL;
|
||||
return -1;
|
||||
}
|
||||
cur_node = next;
|
||||
token = strtok(NULL, "/");
|
||||
}
|
||||
|
||||
free(path_copy);
|
||||
*out = cur_node;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vfs_mount(char *path, fs_t *fs) {
|
||||
if (!fs || !path) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
vnode_t *mp;
|
||||
if (strcmp(path, "/") == 0) {
|
||||
mp = root;
|
||||
} else {
|
||||
vfs_open(root, path, &mp);
|
||||
}
|
||||
|
||||
if (fs->mount == NULL)
|
||||
return -1; // why allocating a fs without the capability to mount to a node? lmao
|
||||
|
||||
return fs->mount(fs, mp);
|
||||
}
|
||||
|
||||
int vfs_unmount(char *path) {
|
||||
(void)path;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int vfs_read(vnode_t *vn, void *buf, size_t off, size_t size) {
|
||||
if (!vn || !buf || off < 0 || size <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (vn->ops && vn->ops->read) {
|
||||
return vn->ops->read(vn, buf, off, size);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
vnode_t *vfs_create_node(char *name, vnode_type_t type) {
|
||||
vnode_t *node = (vnode_t *)malloc(sizeof(vnode_t));
|
||||
if (!node) {
|
||||
return NULL;
|
||||
}
|
||||
memset(node, 0, sizeof(vnode_t));
|
||||
strncpy(node->name, name, sizeof(node->name) - 1);
|
||||
node->type = type;
|
||||
node->ops = NULL;
|
||||
// node->parent = NULL;
|
||||
// node->child = NULL;
|
||||
// node->next = NULL;
|
||||
return node;
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct vnode;
|
||||
|
||||
#define VN_FILE 1
|
||||
#define VN_DIR 2
|
||||
|
||||
typedef uint32_t vnode_type_t;
|
||||
|
||||
typedef struct vnode_ops {
|
||||
int (*read)(struct vnode *vn, void *buf, size_t off, size_t size);
|
||||
int (*lookup)(struct vnode *vn, const char *name, struct vnode **out);
|
||||
} vnode_ops_t;
|
||||
|
||||
typedef struct vnode {
|
||||
char name[256];
|
||||
vnode_type_t type;
|
||||
uint32_t refcount;
|
||||
struct vnode* parent; // If this vnode exists, then it's parent too.
|
||||
// struct vnode* child;
|
||||
// struct vnode* next;
|
||||
|
||||
struct vnode_ops *ops;
|
||||
void *internal;
|
||||
} vnode_t;
|
||||
|
||||
typedef struct mountpoint {
|
||||
char name[32];
|
||||
struct fs *fs;
|
||||
vnode_t *mountpoint;
|
||||
} mountpoint_t;
|
||||
|
||||
typedef struct fs {
|
||||
char name[32];
|
||||
struct vnode *root;
|
||||
int (*mount)(struct fs *fs, struct vnode *mountpoint);
|
||||
} fs_t;
|
||||
|
||||
void vfs_init(void);
|
||||
int vfs_mount(char *path, fs_t *fs);
|
||||
int vfs_unmount(char *path);
|
||||
int vfs_open(vnode_t *curdir, const char *path, vnode_t **out);
|
||||
int vfs_read(vnode_t *vn, void *buf, size_t off, size_t size);
|
||||
vnode_t *vfs_create_node(char *name, vnode_type_t type);
|
|
@ -1,2 +0,0 @@
|
|||
# Soaplin vnodes
|
||||
...
|
|
@ -1,18 +0,0 @@
|
|||
#include <stdint.h>
|
||||
/*int __eqdf2(double a, double b) {
|
||||
union { double f; uint64_t i; } ua = { a }, ub = { b };
|
||||
return ua.i == ub.i;
|
||||
}
|
||||
int __ltdf2(double a, double b) {
|
||||
if (a < b) return -1;
|
||||
if (a > b) return 1;
|
||||
return 0;
|
||||
}
|
||||
double __truncxfdf2(double x) {
|
||||
return (double)x;
|
||||
}
|
||||
int __gtdf2(double a, double b) {
|
||||
if (a > b) return 1;
|
||||
if (a < b) return -1;
|
||||
return 0;
|
||||
}**/
|
|
@ -1,31 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct spinlock {
|
||||
volatile int locked;
|
||||
} spinlock_t;
|
||||
|
||||
static inline void spinlock_acquire(spinlock_t *lock) {
|
||||
// uint64_t timeout = 1000000; // Adjust this value based on your needs
|
||||
|
||||
for (;;) {
|
||||
if (__atomic_exchange_n(&lock->locked, 1, __ATOMIC_ACQUIRE) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (__atomic_load_n(&lock->locked, __ATOMIC_RELAXED)) {
|
||||
/**if (--timeout == 0) {
|
||||
// Force unlock after too many attempts
|
||||
__atomic_store_n(&lock->locked, 0, __ATOMIC_RELEASE);
|
||||
continue;
|
||||
}**/
|
||||
__asm__ volatile("pause" ::: "memory");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void spinlock_release(spinlock_t *lock) {
|
||||
__atomic_store_n(&lock->locked, 0, __ATOMIC_RELEASE);
|
||||
}
|
|
@ -1,134 +1,8 @@
|
|||
#include <lib/string.h>
|
||||
#include <mm/liballoc/liballoc.h>
|
||||
#include <mm/memop.h>
|
||||
#include <stddef.h>
|
||||
|
||||
static char *olds;
|
||||
|
||||
int strlen(const char *str) {
|
||||
int len = 0;
|
||||
while (str[len])
|
||||
len++;
|
||||
return len;
|
||||
}
|
||||
|
||||
int strcmp(const char *s1, const char *s2) {
|
||||
while (*s1 && *s1 == *s2) {
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
return *s1 - *s2;
|
||||
}
|
||||
|
||||
char *strcpy(char *dest, const char *src) {
|
||||
if (dest == NULL || src == NULL)
|
||||
return NULL;
|
||||
|
||||
char *temp = dest;
|
||||
while ((*dest++ = *src++) != '\0')
|
||||
;
|
||||
return temp;
|
||||
}
|
||||
|
||||
char *strchr(const char *s, int c) {
|
||||
while (*s++) {
|
||||
if (*s == c)
|
||||
return (char *)s;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *strrchr(const char *s, int c) {
|
||||
const char *p = NULL;
|
||||
|
||||
for (;;) {
|
||||
if (*s == (char)c)
|
||||
p = s;
|
||||
if (*s++ == '\0')
|
||||
return (char *)p;
|
||||
}
|
||||
}
|
||||
|
||||
int oct2bin(unsigned char *str, int size) {
|
||||
int n = 0;
|
||||
unsigned char *c = str;
|
||||
while (size-- > 0) {
|
||||
n *= 8;
|
||||
n += *c - '0';
|
||||
c++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
char *strdup(const char *str) {
|
||||
if (str == NULL)
|
||||
return NULL;
|
||||
|
||||
int len = strlen(str);
|
||||
char *dup = (char *)malloc(len + 1);
|
||||
if (dup == NULL)
|
||||
return NULL;
|
||||
|
||||
strcpy(dup, str);
|
||||
return dup;
|
||||
}
|
||||
|
||||
char *strncpy(char *dest, const char *src, size_t n) {
|
||||
size_t i;
|
||||
for (i = 0; i < n && src[i] != '\0'; i++)
|
||||
dest[i] = src[i];
|
||||
for (; i < n; i++)
|
||||
dest[i] = '\0';
|
||||
return dest;
|
||||
}
|
||||
|
||||
#define DICT_LEN 256
|
||||
|
||||
static int *create_delim_dict(char *delim) {
|
||||
int *d = (int *)malloc(sizeof(int) * DICT_LEN);
|
||||
memset((void *)d, 0, sizeof(int) * DICT_LEN);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < strlen(delim); i++) {
|
||||
d[delim[i]] = 1;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
char *strtok(char *str, char *delim) {
|
||||
|
||||
static char *last, *to_free;
|
||||
int *deli_dict = create_delim_dict(delim);
|
||||
|
||||
if (!deli_dict) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (str) {
|
||||
last = (char *)malloc(strlen(str) + 1);
|
||||
if (!last) {
|
||||
free(deli_dict);
|
||||
}
|
||||
to_free = last;
|
||||
strcpy(last, str);
|
||||
}
|
||||
|
||||
while (deli_dict[*last] && *last != '\0') {
|
||||
last++;
|
||||
}
|
||||
str = last;
|
||||
if (*last == '\0') {
|
||||
free(deli_dict);
|
||||
free(to_free);
|
||||
return NULL;
|
||||
}
|
||||
while (*last != '\0' && !deli_dict[*last]) {
|
||||
last++;
|
||||
}
|
||||
|
||||
*last = '\0';
|
||||
last++;
|
||||
|
||||
free(deli_dict);
|
||||
return str;
|
||||
}
|
||||
size_t strlen(char *str) {
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
return i;
|
||||
}
|
|
@ -1,12 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
int strlen(const char *str);
|
||||
int strcmp(const char *s1, const char *s2);
|
||||
char *strchr(const char *s, int c);
|
||||
char *strcpy(char *dest, const char *src);
|
||||
char *strrchr(const char *s, int c);
|
||||
int oct2bin(unsigned char *str, int size);
|
||||
char *strdup(const char *str);
|
||||
char *strncpy(char *dest, const char *src, size_t n);
|
||||
char *strtok(char *str, char *delim);
|
||||
size_t strlen(char *str);
|
|
@ -1,141 +1,15 @@
|
|||
#include "arch/x86_64/pit.h"
|
||||
#include "arch/x86_64/smp.h"
|
||||
#include "arch/x86_64/sse.h"
|
||||
#include "dbg/sym.h"
|
||||
#include "dev/ioapic.h"
|
||||
#include "dev/lapic.h"
|
||||
#include "exec/elf.h"
|
||||
#include "exec/exec.h"
|
||||
#include "fs/hellofs.h"
|
||||
#include "mm/liballoc/liballoc.h"
|
||||
#include "mm/pmm.h"
|
||||
#include "mm/vma.h"
|
||||
#include "mm/vmm.h"
|
||||
#include "sched/sched.h"
|
||||
#include "sys/acpi.h"
|
||||
#include "sys/acpi/madt.h"
|
||||
#include "sys/syscall.h"
|
||||
#include <arch/x86_64/fpu.h>
|
||||
#include <arch/x86_64/gdt.h>
|
||||
#include <arch/x86_64/idt.h>
|
||||
#include <font.h>
|
||||
#include <fs/vfs.h>
|
||||
#include <limine.h>
|
||||
#include <mm/memop.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/errhnd/panic.h>
|
||||
#include <sys/gfx/flanterm/backends/fb.h>
|
||||
#include <sys/gfx/flanterm/flanterm.h>
|
||||
#include <sys/log.h>
|
||||
#include <sys/printf.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <boot/limine.h>
|
||||
#include <dev/tty.h>
|
||||
|
||||
__attribute__((
|
||||
used, section(".limine_requests"))) static volatile LIMINE_BASE_REVISION(3);
|
||||
void kmain(void) {
|
||||
tty_init();
|
||||
|
||||
__attribute__((
|
||||
used,
|
||||
section(
|
||||
".limine_requests"))) static volatile struct limine_framebuffer_request
|
||||
framebuffer_request = {.id = LIMINE_FRAMEBUFFER_REQUEST, .revision = 0};
|
||||
tty_write_raw("Hello, World!\n");
|
||||
|
||||
__attribute__((
|
||||
used,
|
||||
section(".limine_requests"))) static volatile struct limine_module_request
|
||||
module_request = {.id = LIMINE_MODULE_REQUEST, .revision = 0};
|
||||
|
||||
__attribute__((used,
|
||||
section(".limine_requests_"
|
||||
"start"))) static volatile LIMINE_REQUESTS_START_MARKER;
|
||||
|
||||
__attribute__((
|
||||
used,
|
||||
section(
|
||||
".limine_requests_end"))) static volatile LIMINE_REQUESTS_END_MARKER;
|
||||
|
||||
struct limine_framebuffer *fb;
|
||||
struct flanterm_context *ft_ctx;
|
||||
|
||||
char kstack[8192];
|
||||
|
||||
void __kmain(void) {
|
||||
if (framebuffer_request.response != NULL) {
|
||||
|
||||
struct limine_framebuffer *framebuffer =
|
||||
framebuffer_request.response->framebuffers[0];
|
||||
fb = framebuffer;
|
||||
|
||||
ft_ctx = flanterm_fb_init(
|
||||
NULL, NULL, framebuffer->address, framebuffer->width,
|
||||
framebuffer->height, framebuffer->pitch, framebuffer->red_mask_size,
|
||||
framebuffer->red_mask_shift, framebuffer->green_mask_size,
|
||||
framebuffer->green_mask_shift, framebuffer->blue_mask_size,
|
||||
framebuffer->blue_mask_shift, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
VGA8, 8, 16, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
printf("\n Soaplin 0.7-sild is booting up your computer...\n\n");
|
||||
|
||||
gdt_init(&kstack[8192]);
|
||||
idt_init();
|
||||
pmm_init();
|
||||
vmm_init();
|
||||
|
||||
kernel_vma_context = vma_create_context(vmm_kernel_pm);
|
||||
if (!kernel_vma_context) {
|
||||
log("kernel - vma ctx creation failed. halting\n");
|
||||
asm("cli");
|
||||
while (1)
|
||||
asm("hlt");
|
||||
}
|
||||
|
||||
ksym_init();
|
||||
func *f = ksym_fromip((uint64_t)__kmain);
|
||||
if (f) {
|
||||
log("ksym: found %s at %p\n", f->name, f->ip);
|
||||
} else {
|
||||
log("ksym: not found\n");
|
||||
}
|
||||
|
||||
acpi_init();
|
||||
madt_init();
|
||||
ioapic_init();
|
||||
lapic_init();
|
||||
pit_init();
|
||||
smp_init();
|
||||
|
||||
vfs_init();
|
||||
fs_t *hellofs = hellofs_init();
|
||||
vfs_mount("/", hellofs);
|
||||
|
||||
vnode_t *vn;
|
||||
vfs_open(NULL, "/hello", &vn);
|
||||
if (vn) {
|
||||
char buf[100];
|
||||
vfs_read(vn, buf, 2, sizeof(buf));
|
||||
log("Read from /hello: %s\n", buf);
|
||||
} else {
|
||||
log("Failed to open /hello\n");
|
||||
}
|
||||
|
||||
syscall_init();
|
||||
sched_init();
|
||||
|
||||
// vfs_init();
|
||||
|
||||
// panic("No working initialization program found. (This is normal due to "
|
||||
// "Soaplin's current state, so please do not report this as a bug)");
|
||||
|
||||
program_t *p = elf_load(module_request.response->modules[0]->address, 1);
|
||||
|
||||
|
||||
sched_process *proc =
|
||||
sched_from_program(p);
|
||||
|
||||
log("kernel - Soaplin initialized sucessfully.\n");
|
||||
|
||||
pit_enable();
|
||||
while (1)
|
||||
;;
|
||||
// We're done, just hang...
|
||||
hcf();
|
||||
}
|
||||
|
|
|
@ -1,586 +0,0 @@
|
|||
// Copyright: Durand Miller <clutter@djm.co.za>
|
||||
#include <mm/liballoc/liballoc.h>
|
||||
|
||||
// very dirty way of disabling logging in liballoc
|
||||
#define log(...) (void)0
|
||||
|
||||
#define VERSION "1.1"
|
||||
#define ALIGNMENT 16ul
|
||||
|
||||
#define ALIGN_TYPE char
|
||||
#define ALIGN_INFO sizeof(ALIGN_TYPE) * 16
|
||||
|
||||
#define USE_CASE1
|
||||
#define USE_CASE2
|
||||
#define USE_CASE3
|
||||
#define USE_CASE4
|
||||
#define USE_CASE5
|
||||
|
||||
#define ALIGN(ptr) \
|
||||
if (ALIGNMENT > 1) { \
|
||||
uintptr_t diff; \
|
||||
ptr = (void *)((uintptr_t)ptr + ALIGN_INFO); \
|
||||
diff = (uintptr_t)ptr & (ALIGNMENT - 1); \
|
||||
if (diff != 0) { \
|
||||
diff = ALIGNMENT - diff; \
|
||||
ptr = (void *)((uintptr_t)ptr + diff); \
|
||||
} \
|
||||
*((ALIGN_TYPE *)((uintptr_t)ptr - ALIGN_INFO)) = diff + ALIGN_INFO; \
|
||||
}
|
||||
|
||||
#define UNALIGN(ptr) \
|
||||
if (ALIGNMENT > 1) { \
|
||||
uintptr_t diff = *((ALIGN_TYPE *)((uintptr_t)ptr - ALIGN_INFO)); \
|
||||
if (diff < (ALIGNMENT + ALIGN_INFO)) { \
|
||||
ptr = (void *)((uintptr_t)ptr - diff); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define LIBALLOC_MAGIC 0xc001c0de
|
||||
#define LIBALLOC_DEAD 0xdeaddead
|
||||
|
||||
struct liballoc_major {
|
||||
struct liballoc_major *prev;
|
||||
struct liballoc_major *next;
|
||||
unsigned int pages;
|
||||
unsigned int size;
|
||||
unsigned int usage;
|
||||
struct liballoc_minor *first;
|
||||
};
|
||||
|
||||
struct liballoc_minor {
|
||||
struct liballoc_minor *prev;
|
||||
struct liballoc_minor *next;
|
||||
struct liballoc_major *block;
|
||||
unsigned int magic;
|
||||
unsigned int size;
|
||||
unsigned int req_size;
|
||||
};
|
||||
|
||||
static struct liballoc_major *l_memRoot = NULL;
|
||||
static struct liballoc_major *l_bestBet = NULL;
|
||||
|
||||
static unsigned int l_pageSize = 4096;
|
||||
static unsigned int l_pageCount = 16;
|
||||
static unsigned long long l_allocated = 0;
|
||||
static unsigned long long l_inuse = 0;
|
||||
|
||||
static long long l_warningCount = 0;
|
||||
static long long l_errorCount = 0;
|
||||
static long long l_possibleOverruns = 0;
|
||||
|
||||
static void *liballoc_memset(void *s, int c, size_t n) {
|
||||
unsigned int i;
|
||||
for (i = 0; i < n; i++)
|
||||
((char *)s)[i] = c;
|
||||
|
||||
return s;
|
||||
}
|
||||
static void *liballoc_memcpy(void *s1, const void *s2, size_t n) {
|
||||
char *cdest;
|
||||
char *csrc;
|
||||
unsigned int *ldest = (unsigned int *)s1;
|
||||
unsigned int *lsrc = (unsigned int *)s2;
|
||||
|
||||
while (n >= sizeof(unsigned int)) {
|
||||
*ldest++ = *lsrc++;
|
||||
n -= sizeof(unsigned int);
|
||||
}
|
||||
|
||||
cdest = (char *)ldest;
|
||||
csrc = (char *)lsrc;
|
||||
|
||||
while (n > 0) {
|
||||
*cdest++ = *csrc++;
|
||||
n -= 1;
|
||||
}
|
||||
|
||||
return s1;
|
||||
}
|
||||
|
||||
#if _DEBUG
|
||||
void liballoc_dump() {
|
||||
#ifdef _DEBUG
|
||||
struct liballoc_major *maj = l_memRoot;
|
||||
struct liballoc_minor *min = NULL;
|
||||
#endif
|
||||
|
||||
info("------ Memory data ---------------");
|
||||
info("System memory allocated: %i bytes", l_allocated);
|
||||
info("Memory in used (malloc'ed): %i bytes", l_inuse);
|
||||
info("Warning count: %i", l_warningCount);
|
||||
info("Error count: %i", l_errorCount);
|
||||
info("Possible overruns: %i", l_possibleOverruns);
|
||||
|
||||
#ifdef _DEBUG
|
||||
while (maj != NULL) {
|
||||
info("%x: total = %i, used = %i", maj, maj->size, maj->usage);
|
||||
|
||||
min = maj->first;
|
||||
while (min != NULL) {
|
||||
info(" %x: %i bytes", min, min->size);
|
||||
min = min->next;
|
||||
}
|
||||
|
||||
maj = maj->next;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
void liballoc_dump() { return; }
|
||||
#endif
|
||||
|
||||
static struct liballoc_major *allocate_new_page(unsigned int size) {
|
||||
unsigned int st;
|
||||
struct liballoc_major *maj;
|
||||
|
||||
st = size + sizeof(struct liballoc_major);
|
||||
st += sizeof(struct liballoc_minor);
|
||||
|
||||
if ((st % l_pageSize) == 0)
|
||||
st = st / (l_pageSize);
|
||||
else
|
||||
st = st / (l_pageSize) + 1;
|
||||
|
||||
if (st < l_pageCount)
|
||||
st = l_pageCount;
|
||||
|
||||
maj = (struct liballoc_major *)liballoc_alloc(st);
|
||||
|
||||
if (maj == NULL) {
|
||||
l_warningCount += 1;
|
||||
log("liballoc - (warning) liballoc_alloc( %i ) return NULL", st);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
maj->prev = NULL;
|
||||
maj->next = NULL;
|
||||
maj->pages = st;
|
||||
maj->size = st * l_pageSize;
|
||||
maj->usage = sizeof(struct liballoc_major);
|
||||
maj->first = NULL;
|
||||
|
||||
l_allocated += maj->size;
|
||||
|
||||
log("liballoc - Resource allocated %x of %i pages (%i bytes) for %i size.",
|
||||
maj, st, maj->size, size);
|
||||
log("liballoc - Total memory usage = %i KB", (int)((l_allocated / (1024))));
|
||||
|
||||
return maj;
|
||||
}
|
||||
|
||||
void *PREFIX(malloc)(size_t req_size) {
|
||||
int startedBet = 0;
|
||||
unsigned long long bestSize = 0;
|
||||
void *p = NULL;
|
||||
uintptr_t diff;
|
||||
struct liballoc_major *maj;
|
||||
struct liballoc_minor *min;
|
||||
struct liballoc_minor *new_min;
|
||||
unsigned long size = req_size;
|
||||
|
||||
if (ALIGNMENT > 1) {
|
||||
size += ALIGNMENT + ALIGN_INFO;
|
||||
}
|
||||
|
||||
liballoc_lock();
|
||||
|
||||
if (size == 0) {
|
||||
l_warningCount += 1;
|
||||
log("liballoc - (warning) alloc( 0 ) called from %x",
|
||||
__builtin_return_address(0));
|
||||
|
||||
liballoc_unlock();
|
||||
return PREFIX(malloc)(1);
|
||||
}
|
||||
|
||||
if (l_memRoot == NULL) {
|
||||
log("liballoc - initialization of liballoc " VERSION "");
|
||||
l_memRoot = allocate_new_page(size);
|
||||
if (l_memRoot == NULL) {
|
||||
liballoc_unlock();
|
||||
log("liballoc - initial l_memRoot initialization failed", p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
log("liballoc - set up first memory major %x", l_memRoot);
|
||||
}
|
||||
|
||||
log("liballoc - %x PREFIX(malloc)( %i ): ", __builtin_return_address(0),
|
||||
size);
|
||||
|
||||
maj = l_memRoot;
|
||||
startedBet = 0;
|
||||
|
||||
if (l_bestBet != NULL) {
|
||||
bestSize = l_bestBet->size - l_bestBet->usage;
|
||||
|
||||
if (bestSize > (size + sizeof(struct liballoc_minor))) {
|
||||
maj = l_bestBet;
|
||||
startedBet = 1;
|
||||
}
|
||||
}
|
||||
|
||||
while (maj != NULL) {
|
||||
diff = maj->size - maj->usage;
|
||||
|
||||
if (bestSize < diff) {
|
||||
|
||||
l_bestBet = maj;
|
||||
bestSize = diff;
|
||||
}
|
||||
|
||||
#ifdef USE_CASE1
|
||||
|
||||
if (diff < (size + sizeof(struct liballoc_minor))) {
|
||||
log("liballoc - (warning) CASE 1: Insufficient space in block %x", maj);
|
||||
|
||||
if (maj->next != NULL) {
|
||||
maj = maj->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (startedBet == 1) {
|
||||
maj = l_memRoot;
|
||||
startedBet = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
maj->next = allocate_new_page(size);
|
||||
if (maj->next == NULL)
|
||||
break;
|
||||
maj->next->prev = maj;
|
||||
maj = maj->next;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_CASE2
|
||||
|
||||
if (maj->first == NULL) {
|
||||
maj->first = (struct liballoc_minor *)((uintptr_t)maj +
|
||||
sizeof(struct liballoc_major));
|
||||
|
||||
maj->first->magic = LIBALLOC_MAGIC;
|
||||
maj->first->prev = NULL;
|
||||
maj->first->next = NULL;
|
||||
maj->first->block = maj;
|
||||
maj->first->size = size;
|
||||
maj->first->req_size = req_size;
|
||||
maj->usage += size + sizeof(struct liballoc_minor);
|
||||
|
||||
l_inuse += size;
|
||||
|
||||
p = (void *)((uintptr_t)(maj->first) + sizeof(struct liballoc_minor));
|
||||
|
||||
ALIGN(p);
|
||||
|
||||
log("liballoc - (warning) CASE 2: returning %x", p);
|
||||
liballoc_unlock();
|
||||
return p;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_CASE3
|
||||
|
||||
diff = (uintptr_t)(maj->first);
|
||||
diff -= (uintptr_t)maj;
|
||||
diff -= sizeof(struct liballoc_major);
|
||||
|
||||
if (diff >= (size + sizeof(struct liballoc_minor))) {
|
||||
|
||||
maj->first->prev =
|
||||
(struct liballoc_minor *)((uintptr_t)maj +
|
||||
sizeof(struct liballoc_major));
|
||||
maj->first->prev->next = maj->first;
|
||||
maj->first = maj->first->prev;
|
||||
|
||||
maj->first->magic = LIBALLOC_MAGIC;
|
||||
maj->first->prev = NULL;
|
||||
maj->first->block = maj;
|
||||
maj->first->size = size;
|
||||
maj->first->req_size = req_size;
|
||||
maj->usage += size + sizeof(struct liballoc_minor);
|
||||
|
||||
l_inuse += size;
|
||||
|
||||
p = (void *)((uintptr_t)(maj->first) + sizeof(struct liballoc_minor));
|
||||
ALIGN(p);
|
||||
|
||||
log("liballoc - (warning) CASE 3: returning %x", p);
|
||||
liballoc_unlock();
|
||||
return p;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_CASE4
|
||||
|
||||
min = maj->first;
|
||||
|
||||
while (min != NULL) {
|
||||
|
||||
if (min->next == NULL) {
|
||||
|
||||
diff = (uintptr_t)(maj) + maj->size;
|
||||
diff -= (uintptr_t)min;
|
||||
diff -= sizeof(struct liballoc_minor);
|
||||
diff -= min->size;
|
||||
|
||||
if (diff >= (size + sizeof(struct liballoc_minor))) {
|
||||
|
||||
min->next = (struct liballoc_minor *)((uintptr_t)min +
|
||||
sizeof(struct liballoc_minor) +
|
||||
min->size);
|
||||
min->next->prev = min;
|
||||
min = min->next;
|
||||
min->next = NULL;
|
||||
min->magic = LIBALLOC_MAGIC;
|
||||
min->block = maj;
|
||||
min->size = size;
|
||||
min->req_size = req_size;
|
||||
maj->usage += size + sizeof(struct liballoc_minor);
|
||||
|
||||
l_inuse += size;
|
||||
|
||||
p = (void *)((uintptr_t)min + sizeof(struct liballoc_minor));
|
||||
ALIGN(p);
|
||||
|
||||
log("liballoc - (warning) CASE 4.1: returning %x", p);
|
||||
liballoc_unlock();
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
if (min->next != NULL) {
|
||||
|
||||
diff = (uintptr_t)(min->next);
|
||||
diff -= (uintptr_t)min;
|
||||
diff -= sizeof(struct liballoc_minor);
|
||||
diff -= min->size;
|
||||
|
||||
if (diff >= (size + sizeof(struct liballoc_minor))) {
|
||||
|
||||
new_min = (struct liballoc_minor *)((uintptr_t)min +
|
||||
sizeof(struct liballoc_minor) +
|
||||
min->size);
|
||||
|
||||
new_min->magic = LIBALLOC_MAGIC;
|
||||
new_min->next = min->next;
|
||||
new_min->prev = min;
|
||||
new_min->size = size;
|
||||
new_min->req_size = req_size;
|
||||
new_min->block = maj;
|
||||
min->next->prev = new_min;
|
||||
min->next = new_min;
|
||||
maj->usage += size + sizeof(struct liballoc_minor);
|
||||
|
||||
l_inuse += size;
|
||||
|
||||
p = (void *)((uintptr_t)new_min + sizeof(struct liballoc_minor));
|
||||
ALIGN(p);
|
||||
|
||||
log("liballoc - (warning) CASE 4.2: returning %x", p);
|
||||
liballoc_unlock();
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
min = min->next;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_CASE5
|
||||
|
||||
if (maj->next == NULL) {
|
||||
log("liballoc - (warning) CASE 5: block full");
|
||||
|
||||
if (startedBet == 1) {
|
||||
maj = l_memRoot;
|
||||
startedBet = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
maj->next = allocate_new_page(size);
|
||||
if (maj->next == NULL)
|
||||
break;
|
||||
maj->next->prev = maj;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
maj = maj->next;
|
||||
}
|
||||
|
||||
liballoc_unlock();
|
||||
|
||||
log("liballoc - (warning) All cases exhausted. No memory available.");
|
||||
log("liballoc - (warning) PREFIX(malloc)( %i ) returning NULL.", size);
|
||||
liballoc_dump();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void PREFIX(free)(void *ptr) {
|
||||
struct liballoc_minor *min;
|
||||
struct liballoc_major *maj;
|
||||
|
||||
if (ptr == NULL) {
|
||||
l_warningCount += 1;
|
||||
log("liballoc - (warning) PREFIX(free)( NULL ) called from %x",
|
||||
__builtin_return_address(0));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
UNALIGN(ptr);
|
||||
|
||||
liballoc_lock();
|
||||
|
||||
min =
|
||||
(struct liballoc_minor *)((uintptr_t)ptr - sizeof(struct liballoc_minor));
|
||||
|
||||
if (min->magic != LIBALLOC_MAGIC) {
|
||||
l_errorCount += 1;
|
||||
|
||||
if (((min->magic & 0xFFFFFF) == (LIBALLOC_MAGIC & 0xFFFFFF)) ||
|
||||
((min->magic & 0xFFFF) == (LIBALLOC_MAGIC & 0xFFFF)) ||
|
||||
((min->magic & 0xFF) == (LIBALLOC_MAGIC & 0xFF))) {
|
||||
l_possibleOverruns += 1;
|
||||
log("liballoc - (warning) Possible 1-3 byte overrun for magic %x != %x",
|
||||
min->magic, LIBALLOC_MAGIC);
|
||||
}
|
||||
|
||||
if (min->magic == LIBALLOC_DEAD) {
|
||||
log("liballoc - multiple PREFIX(free)() attempt on %x from %x.", ptr,
|
||||
__builtin_return_address(0));
|
||||
} else {
|
||||
log("liballoc - Bad PREFIX(free)( %x ) called from %x", ptr,
|
||||
__builtin_return_address(0));
|
||||
}
|
||||
|
||||
liballoc_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
log("liballoc - %x PREFIX(free)( %x ): ", __builtin_return_address(0), ptr);
|
||||
|
||||
maj = min->block;
|
||||
|
||||
l_inuse -= min->size;
|
||||
|
||||
maj->usage -= (min->size + sizeof(struct liballoc_minor));
|
||||
min->magic = LIBALLOC_DEAD;
|
||||
|
||||
if (min->next != NULL)
|
||||
min->next->prev = min->prev;
|
||||
if (min->prev != NULL)
|
||||
min->prev->next = min->next;
|
||||
|
||||
if (min->prev == NULL)
|
||||
maj->first = min->next;
|
||||
|
||||
if (maj->first == NULL) {
|
||||
if (l_memRoot == maj)
|
||||
l_memRoot = maj->next;
|
||||
if (l_bestBet == maj)
|
||||
l_bestBet = NULL;
|
||||
if (maj->prev != NULL)
|
||||
maj->prev->next = maj->next;
|
||||
if (maj->next != NULL)
|
||||
maj->next->prev = maj->prev;
|
||||
l_allocated -= maj->size;
|
||||
|
||||
liballoc_free(maj, maj->pages);
|
||||
} else {
|
||||
if (l_bestBet != NULL) {
|
||||
int bestSize = l_bestBet->size - l_bestBet->usage;
|
||||
int majSize = maj->size - maj->usage;
|
||||
|
||||
if (majSize > bestSize)
|
||||
l_bestBet = maj;
|
||||
}
|
||||
}
|
||||
|
||||
log("liballoc - (warning) OK");
|
||||
|
||||
liballoc_unlock();
|
||||
}
|
||||
|
||||
void *PREFIX(calloc)(size_t nobj, size_t size) {
|
||||
int real_size;
|
||||
void *p;
|
||||
|
||||
real_size = nobj * size;
|
||||
|
||||
p = PREFIX(malloc)(real_size);
|
||||
|
||||
liballoc_memset(p, 0, real_size);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void *PREFIX(realloc)(void *p, size_t size) {
|
||||
void *ptr;
|
||||
struct liballoc_minor *min;
|
||||
unsigned int real_size;
|
||||
|
||||
if (size == 0) {
|
||||
PREFIX(free)
|
||||
(p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (p == NULL)
|
||||
return PREFIX(malloc)(size);
|
||||
|
||||
ptr = p;
|
||||
UNALIGN(ptr);
|
||||
|
||||
liballoc_lock();
|
||||
|
||||
min =
|
||||
(struct liballoc_minor *)((uintptr_t)ptr - sizeof(struct liballoc_minor));
|
||||
|
||||
if (min->magic != LIBALLOC_MAGIC) {
|
||||
l_errorCount += 1;
|
||||
|
||||
if (((min->magic & 0xFFFFFF) == (LIBALLOC_MAGIC & 0xFFFFFF)) ||
|
||||
((min->magic & 0xFFFF) == (LIBALLOC_MAGIC & 0xFFFF)) ||
|
||||
((min->magic & 0xFF) == (LIBALLOC_MAGIC & 0xFF))) {
|
||||
l_possibleOverruns += 1;
|
||||
log("liballoc - Possible 1-3 byte overrun for magic %x != %x", min->magic,
|
||||
LIBALLOC_MAGIC);
|
||||
}
|
||||
|
||||
if (min->magic == LIBALLOC_DEAD) {
|
||||
log("liballoc - liballoc: multiple PREFIX(free)() attempt on %x from %x.",
|
||||
ptr, __builtin_return_address(0));
|
||||
} else {
|
||||
log("liballoc - liballoc: Bad PREFIX(free)( %x ) called from %x", ptr,
|
||||
__builtin_return_address(0));
|
||||
}
|
||||
|
||||
liballoc_unlock();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
real_size = min->req_size;
|
||||
|
||||
if (real_size >= size) {
|
||||
min->req_size = size;
|
||||
liballoc_unlock();
|
||||
return p;
|
||||
}
|
||||
|
||||
liballoc_unlock();
|
||||
|
||||
ptr = PREFIX(malloc)(size);
|
||||
liballoc_memcpy(ptr, p, real_size);
|
||||
PREFIX(free)
|
||||
(p);
|
||||
|
||||
return ptr;
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
// Copyright: Durand Miller <clutter@djm.co.za>
|
||||
#ifndef LIBALLOC_H
|
||||
#define LIBALLOC_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/log.h>
|
||||
|
||||
#define PREFIX(func) func
|
||||
|
||||
#ifdef _DEBUG
|
||||
void liballoc_dump();
|
||||
#endif // _DEBUG
|
||||
|
||||
extern int liballoc_lock();
|
||||
extern int liballoc_unlock();
|
||||
extern void *liballoc_alloc(size_t);
|
||||
extern int liballoc_free(void *, size_t);
|
||||
|
||||
extern void *PREFIX(malloc)(size_t);
|
||||
extern void *PREFIX(realloc)(void *, size_t);
|
||||
extern void *PREFIX(calloc)(size_t, size_t);
|
||||
extern void PREFIX(free)(void *);
|
||||
|
||||
#endif // LIBALLOC_H
|
|
@ -1,34 +0,0 @@
|
|||
#include "mm/liballoc/liballoc.h"
|
||||
#include "mm/vmm.h"
|
||||
#include <lib/spinlock.h>
|
||||
#include <mm/vma.h>
|
||||
#include <stddef.h>
|
||||
|
||||
extern vma_context_t *kernel_vma_context;
|
||||
|
||||
static spinlock_t liballoc_lock_var = {0};
|
||||
|
||||
int liballoc_lock() {
|
||||
spinlock_acquire(&liballoc_lock_var);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int liballoc_unlock() {
|
||||
spinlock_release(&liballoc_lock_var);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *liballoc_alloc(size_t pages) {
|
||||
return vma_alloc(kernel_vma_context, pages, VMM_PRESENT | VMM_WRITABLE);
|
||||
}
|
||||
|
||||
int liballoc_free(void *ptr, size_t pages) {
|
||||
(void)pages;
|
||||
vma_free(kernel_vma_context, ptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// void *malloc(size_t s) { return PREFIX(malloc)(s); }
|
||||
// void *realloc(void *v, size_t s) { return PREFIX(realloc)(v, s); }
|
||||
// void *calloc(size_t s1, size_t s) { return PREFIX(calloc)(s1, s); }
|
||||
// void free(void *v) { return PREFIX(free)(v); }
|
|
@ -1,58 +1,65 @@
|
|||
// Copyright (C) 2024 Sipaa Projects
|
||||
// This code is part of the Soaplin kernel and is licensed under the terms of
|
||||
// the MIT License.
|
||||
|
||||
#include "mm/pmm.h"
|
||||
#include <stddef.h>
|
||||
#include <mm/memop.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void *memcpy(void *dest, const void *src, size_t n) {
|
||||
uint8_t *pdest = (uint8_t *)dest;
|
||||
const uint8_t *psrc = (const uint8_t *)src;
|
||||
void *memcpy(void *restrict dest, const void *restrict src, size_t n) {
|
||||
#if defined(__x86_64__)
|
||||
long d0, d1, d2;
|
||||
asm volatile(
|
||||
"rep ; movsq\n\t movq %4,%%rcx\n\t""rep ; movsb\n\t": "=&c" (d0),
|
||||
"=&D" (d1),
|
||||
"=&S" (d2): "0" (n >> 3),
|
||||
"g" (n & 7),
|
||||
"1" (dest),
|
||||
"2" (src): "memory"
|
||||
);
|
||||
#else
|
||||
uint8_t *restrict pdest = (uint8_t *restrict)dest;
|
||||
const uint8_t *restrict psrc = (const uint8_t *restrict)src;
|
||||
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
pdest[i] = psrc[i];
|
||||
}
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
pdest[i] = psrc[i];
|
||||
}
|
||||
|
||||
return dest;
|
||||
return dest;
|
||||
#endif
|
||||
}
|
||||
|
||||
void *memset(void *s, int c, size_t n) {
|
||||
uint8_t *p = (uint8_t *)s;
|
||||
uint8_t *p = (uint8_t *)s;
|
||||
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
p[i] = (uint8_t)c;
|
||||
}
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
p[i] = (uint8_t)c;
|
||||
}
|
||||
|
||||
return s;
|
||||
return s;
|
||||
}
|
||||
|
||||
void *memmove(void *dest, const void *src, size_t n) {
|
||||
uint8_t *pdest = (uint8_t *)dest;
|
||||
const uint8_t *psrc = (const uint8_t *)src;
|
||||
uint8_t *pdest = (uint8_t *)dest;
|
||||
const uint8_t *psrc = (const uint8_t *)src;
|
||||
|
||||
if (src > dest) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
pdest[i] = psrc[i];
|
||||
if (src > dest) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
pdest[i] = psrc[i];
|
||||
}
|
||||
} else if (src < dest) {
|
||||
for (size_t i = n; i > 0; i--) {
|
||||
pdest[i-1] = psrc[i-1];
|
||||
}
|
||||
}
|
||||
} else if (src < dest) {
|
||||
for (size_t i = n; i > 0; i--) {
|
||||
pdest[i - 1] = psrc[i - 1];
|
||||
}
|
||||
}
|
||||
|
||||
return dest;
|
||||
return dest;
|
||||
}
|
||||
|
||||
int memcmp(const void *s1, const void *s2, size_t n) {
|
||||
const uint8_t *p1 = (const uint8_t *)s1;
|
||||
const uint8_t *p2 = (const uint8_t *)s2;
|
||||
const uint8_t *p1 = (const uint8_t *)s1;
|
||||
const uint8_t *p2 = (const uint8_t *)s2;
|
||||
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
if (p1[i] != p2[i]) {
|
||||
return p1[i] < p2[i] ? -1 : 1;
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
if (p1[i] != p2[i]) {
|
||||
return p1[i] < p2[i] ? -1 : 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
7
kernel/src/mm/memop.h
Executable file → Normal file
7
kernel/src/mm/memop.h
Executable file → Normal file
|
@ -1,13 +1,8 @@
|
|||
// Copyright (C) 2024 Sipaa Projects
|
||||
// This code is part of the Soaplin kernel and is licensed under the terms of
|
||||
// the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void *memcpy(void *dest, const void *src, size_t n);
|
||||
void *memcpy(void *restrict dest, const void *restrict src, size_t n);
|
||||
void *memset(void *s, int c, size_t n);
|
||||
void *memmove(void *dest, const void *src, size_t n);
|
||||
int memcmp(const void *s1, const void *s2, size_t n);
|
|
@ -1,97 +0,0 @@
|
|||
#include "limine.h"
|
||||
#include <mm/memop.h>
|
||||
#include <mm/pmm.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/log.h>
|
||||
|
||||
pmm_stack_t stack;
|
||||
struct limine_memmap_response *_memmap;
|
||||
|
||||
uint64_t hhdm_offset = 0x0;
|
||||
|
||||
__attribute__((
|
||||
used, section(".limine_requests"))) struct limine_memmap_request mm_req = {
|
||||
.id = LIMINE_MEMMAP_REQUEST, .revision = 3};
|
||||
|
||||
__attribute__((
|
||||
used, section(".limine_requests"))) struct limine_hhdm_request hhdm_req = {
|
||||
.id = LIMINE_HHDM_REQUEST, .revision = 3};
|
||||
|
||||
int pmm_init() {
|
||||
uint64_t free_pages = 0;
|
||||
hhdm_offset = hhdm_req.response->offset;
|
||||
|
||||
struct limine_memmap_response *memmap = mm_req.response;
|
||||
_memmap = memmap;
|
||||
|
||||
// DEBUG("mm", "----- PMM //INFO -----");
|
||||
int freemem = 0;
|
||||
for (uint64_t i = 0; i < memmap->entry_count; i++) {
|
||||
if (memmap->entries[i]->type == LIMINE_MEMMAP_USABLE) {
|
||||
// DEBUG("mm", " - USABLE ENTRY\t\t@ 0x%.16llx, size: 0x%.16llx",
|
||||
// memmap->entries[i]->base, memmap->entries[i]->length);
|
||||
free_pages += DIV_ROUND_UP(memmap->entries[i]->length, PMM_PAGE_SIZE);
|
||||
freemem += memmap->entries[i]->length;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t array_size = ALIGN_UP(free_pages * 8, PMM_PAGE_SIZE);
|
||||
|
||||
for (uint64_t i = 0; i < memmap->entry_count; i++) {
|
||||
struct limine_memmap_entry *entry = memmap->entries[i];
|
||||
if (entry->length >= array_size && entry->type == LIMINE_MEMMAP_USABLE) {
|
||||
stack.pages = (uintptr_t *)HIGHER_HALF(entry->base);
|
||||
entry->length -= array_size;
|
||||
entry->base += array_size;
|
||||
// DEBUG("mm", " - STACK START\t\t@ 0x%.16llx", stack.pages);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint64_t i = 0; i < memmap->entry_count; i++) {
|
||||
struct limine_memmap_entry *entry = memmap->entries[i];
|
||||
if (entry->type == LIMINE_MEMMAP_USABLE) {
|
||||
for (uint64_t j = 0; j < entry->length; j += PMM_PAGE_SIZE) {
|
||||
stack.pages[stack.idx++] = entry->base + j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stack.max = stack.idx;
|
||||
// DEBUG("mm", " - MAX INDEX:\t\t%d", stack.max);
|
||||
// DEBUG("mm", " - CURRENT INDEX:\t%d", stack.idx);
|
||||
// DEBUG("mm", "--------------------");
|
||||
|
||||
log("pmm - %dmb is available to us.\n", freemem / (1024 * 1024));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *pmm_request_page() {
|
||||
if (stack.idx == 0) {
|
||||
// ERROR("mm", "No more pages available.");
|
||||
log("pmm - out of memory.\n");
|
||||
asm("cli");
|
||||
while (1) {
|
||||
asm("hlt");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint64_t page_addr = stack.pages[--stack.idx];
|
||||
memset(HIGHER_HALF(page_addr), 0, PMM_PAGE_SIZE);
|
||||
return (void *)page_addr;
|
||||
}
|
||||
|
||||
void pmm_free_page(void *ptr) {
|
||||
if (ptr == NULL)
|
||||
return;
|
||||
|
||||
if (stack.idx >= stack.max) {
|
||||
// ERROR("mm", "Stack overflow attempt while freeing a page.");
|
||||
log("pmm - could not free the page: stack overflow.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
stack.pages[stack.idx++] = (uint64_t)ptr;
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
#ifndef PMM_H
|
||||
#define PMM_H
|
||||
|
||||
#include <stdint.h>
|
||||
#define PMM_PAGE_SIZE 4096
|
||||
|
||||
typedef struct pmm_stack {
|
||||
uintptr_t *pages;
|
||||
uint64_t idx;
|
||||
uint64_t max;
|
||||
} pmm_stack_t;
|
||||
|
||||
extern uint64_t hhdm_offset;
|
||||
|
||||
#define DIV_ROUND_UP(x, y) \
|
||||
(((uint64_t)(x) + ((uint64_t)(y) - 1)) / (uint64_t)(y))
|
||||
#define ALIGN_UP(x, y) (DIV_ROUND_UP(x, y) * (uint64_t)(y))
|
||||
#define ALIGN_DOWN(x, y) (((uint64_t)(x) / (uint64_t)(y)) * (uint64_t)(y))
|
||||
|
||||
#define HIGHER_HALF(ptr) ((void *)((uint64_t)ptr) + hhdm_offset)
|
||||
#define PHYSICAL(ptr) ((void *)((uint64_t)ptr) - hhdm_offset)
|
||||
|
||||
int pmm_init();
|
||||
void *pmm_request_page();
|
||||
void pmm_free_page(void *ptr);
|
||||
void pmm_dump();
|
||||
|
||||
#endif // PMM_H
|
|
@ -1,181 +0,0 @@
|
|||
// credit to kevin for writing the vma
|
||||
// go check his projects: https://github.com/kevinalavik
|
||||
|
||||
#include "mm/pmm.h"
|
||||
#include "mm/vmm.h"
|
||||
#include <mm/memop.h>
|
||||
#include <mm/vma.h>
|
||||
#include <sys/log.h>
|
||||
|
||||
vma_context_t *kernel_vma_context;
|
||||
|
||||
vma_context_t *vma_create_context(pagemap_t *pagemap) {
|
||||
log("vma - creating VMA context with pagemap: 0x%.16llx\n",
|
||||
(uint64_t)pagemap);
|
||||
|
||||
vma_context_t *ctx = (vma_context_t *)HIGHER_HALF(pmm_request_page());
|
||||
if (ctx == NULL) {
|
||||
log("vma - failed to allocate VMA context\n");
|
||||
return NULL;
|
||||
}
|
||||
log("vma - allocated VMA context at 0x%.16llx\n", (uint64_t)ctx);
|
||||
memset(ctx, 0, sizeof(vma_context_t));
|
||||
log("vma - zeroed out VMA context at 0x%.16llx\n", (uint64_t)ctx);
|
||||
|
||||
ctx->root = (vma_region_t *)HIGHER_HALF(pmm_request_page());
|
||||
if (ctx->root == NULL) {
|
||||
log("vma - failed to allocate root region\n");
|
||||
pmm_free_page((void *)PHYSICAL(ctx));
|
||||
return NULL;
|
||||
}
|
||||
log("vma - allocated root region at 0x%.16llx\n", (uint64_t)ctx->root);
|
||||
|
||||
ctx->pagemap = pagemap;
|
||||
ctx->root->start = PMM_PAGE_SIZE;
|
||||
ctx->root->size = 0;
|
||||
|
||||
log("vma - VMA context created at 0x%.16llx with root region at 0x%.16llx\n",
|
||||
(uint64_t)ctx, (uint64_t)ctx->root);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void vma_destroy_context(vma_context_t *ctx) {
|
||||
log("vma - destroying VMA context at 0x%.16llx\n", (uint64_t)ctx);
|
||||
|
||||
if (ctx->root == NULL || ctx->pagemap == NULL) {
|
||||
log("vma - invalid context or root passed to vma_destroy_context\n");
|
||||
return;
|
||||
}
|
||||
|
||||
vma_region_t *region = ctx->root;
|
||||
while (region != NULL) {
|
||||
log("vma - freeing region at 0x%.16llx\n", (uint64_t)region);
|
||||
vma_region_t *next = region->next;
|
||||
pmm_free_page((void *)PHYSICAL(region));
|
||||
region = next;
|
||||
}
|
||||
|
||||
pmm_free_page((void *)PHYSICAL(ctx));
|
||||
log("vma - destroyed VMA context at 0x%.16llx\n", (uint64_t)ctx);
|
||||
}
|
||||
|
||||
void *vma_alloc(vma_context_t *ctx, uint64_t size, uint64_t flags) {
|
||||
if (ctx == NULL || ctx->root == NULL || ctx->pagemap == NULL) {
|
||||
log("vma - invalid context or root passed to vma_alloc\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vma_region_t *region = ctx->root;
|
||||
vma_region_t *new_region;
|
||||
vma_region_t *last_region = ctx->root;
|
||||
|
||||
while (region != NULL) {
|
||||
if (region->next == NULL ||
|
||||
region->start + region->size < region->next->start) {
|
||||
new_region = (vma_region_t *)HIGHER_HALF(pmm_request_page());
|
||||
if (new_region == NULL) {
|
||||
log("vma - failed to allocate new VMA region\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(new_region, 0, sizeof(vma_region_t));
|
||||
new_region->size = size;
|
||||
new_region->flags = flags;
|
||||
new_region->start = region->start + region->size;
|
||||
new_region->next = region->next;
|
||||
new_region->prev = region;
|
||||
region->next = new_region;
|
||||
|
||||
for (uint64_t i = 0; i < size; i++) {
|
||||
uint64_t page = (uint64_t)pmm_request_page();
|
||||
if (page == 0) {
|
||||
log("vma - failed to allocate physical memory for VMA region\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vmm_map(ctx->pagemap, new_region->start + i * PMM_PAGE_SIZE, page,
|
||||
new_region->flags);
|
||||
}
|
||||
|
||||
return (void *)new_region->start;
|
||||
}
|
||||
region = region->next;
|
||||
}
|
||||
|
||||
new_region = (vma_region_t *)HIGHER_HALF(pmm_request_page());
|
||||
if (new_region == NULL) {
|
||||
log("vma - failed to allocate new VMA region\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(new_region, 0, sizeof(vma_region_t));
|
||||
|
||||
last_region->next = new_region;
|
||||
new_region->prev = last_region;
|
||||
new_region->start = last_region->start + last_region->size;
|
||||
new_region->size = size;
|
||||
new_region->flags = flags;
|
||||
new_region->next = NULL;
|
||||
|
||||
for (uint64_t i = 0; i < size; i++) {
|
||||
uint64_t page = (uint64_t)pmm_request_page();
|
||||
if (page == 0) {
|
||||
log("vma - failed to allocate physical memory for VMA region\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vmm_map(ctx->pagemap, new_region->start + i * PMM_PAGE_SIZE, page,
|
||||
new_region->flags);
|
||||
}
|
||||
|
||||
return (void *)new_region->start;
|
||||
}
|
||||
|
||||
void vma_free(vma_context_t *ctx, void *ptr) {
|
||||
if (ctx == NULL) {
|
||||
log("vma - invalid context passed to vma_free\n");
|
||||
return;
|
||||
}
|
||||
|
||||
vma_region_t *region = ctx->root;
|
||||
while (region != NULL) {
|
||||
if (region->start == (uint64_t)ptr) {
|
||||
log("vma - found region to free at 0x%.16llx\n", (uint64_t)region);
|
||||
break;
|
||||
}
|
||||
region = region->next;
|
||||
}
|
||||
|
||||
if (region == NULL) {
|
||||
log("vma - unable to find region to free at address 0x%.16llx\n",
|
||||
(uint64_t)ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
vma_region_t *prev = region->prev;
|
||||
vma_region_t *next = region->next;
|
||||
|
||||
for (uint64_t i = 0; i < region->size; i++) {
|
||||
uint64_t virt = region->start + i * PMM_PAGE_SIZE;
|
||||
uint64_t phys = virt_to_phys(vmm_kernel_pm, virt);
|
||||
|
||||
if (phys != 0) {
|
||||
pmm_free_page((void *)phys);
|
||||
vmm_unmap(ctx->pagemap, virt);
|
||||
}
|
||||
}
|
||||
|
||||
if (prev != NULL) {
|
||||
prev->next = next;
|
||||
}
|
||||
|
||||
if (next != NULL) {
|
||||
next->prev = prev;
|
||||
}
|
||||
|
||||
if (region == ctx->root) {
|
||||
ctx->root = next;
|
||||
}
|
||||
|
||||
pmm_free_page((void *)PHYSICAL(region));
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
// credit to kevin for writing the vma
|
||||
// go check his projects: https://github.com/kevinalavik
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <mm/pmm.h>
|
||||
#include <mm/vmm.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct vma_region {
|
||||
uint64_t start;
|
||||
uint64_t size;
|
||||
uint64_t flags;
|
||||
struct vma_region *next;
|
||||
struct vma_region *prev;
|
||||
} vma_region_t;
|
||||
|
||||
typedef struct vma_context {
|
||||
pagemap_t *pagemap;
|
||||
vma_region_t *root;
|
||||
} vma_context_t;
|
||||
|
||||
extern vma_context_t *kernel_vma_context;
|
||||
|
||||
vma_context_t *vma_create_context(pagemap_t *pagemap);
|
||||
void vma_destroy_context(vma_context_t *ctx);
|
||||
void *vma_alloc(vma_context_t *ctx, uint64_t size, uint64_t flags);
|
||||
void vma_free(vma_context_t *ctx, void *ptr);
|
||||
void vma_dump_context(vma_context_t *ctx);
|
|
@ -1,244 +0,0 @@
|
|||
#include "mm/vmm.h"
|
||||
#include "limine.h"
|
||||
#include "mm/memop.h"
|
||||
#include "mm/pmm.h"
|
||||
#include "sys/log.h"
|
||||
#include "vmm.h"
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
__attribute__((
|
||||
used,
|
||||
section(
|
||||
".limine_requests"))) static volatile struct limine_paging_mode_request
|
||||
pmrq = {.id = LIMINE_PAGING_MODE_REQUEST,
|
||||
.revision = 3,
|
||||
.mode = LIMINE_PAGING_MODE_X86_64_4LVL};
|
||||
|
||||
__attribute__((used, section(".limine_requests"))) volatile struct
|
||||
limine_executable_address_request karq = {
|
||||
.id = LIMINE_EXECUTABLE_ADDRESS_REQUEST,
|
||||
.revision = 0,
|
||||
};
|
||||
|
||||
pagemap_t *vmm_kernel_pm = NULL;
|
||||
pagemap_t *vmm_current_pm = NULL;
|
||||
int vmm_kernel_pm_exists = 0;
|
||||
|
||||
pagemap_t *vmm_alloc_pm() {
|
||||
pagemap_t *pm = (pagemap_t *)HIGHER_HALF((uint64_t)pmm_request_page());
|
||||
memset(pm, 0, PMM_PAGE_SIZE);
|
||||
|
||||
pm->toplevel = (uint64_t *)HIGHER_HALF((uint64_t)pmm_request_page());
|
||||
memset(pm->toplevel, 0, PMM_PAGE_SIZE);
|
||||
|
||||
if (vmm_kernel_pm_exists) {
|
||||
for (int i = 256; i < 512; i++) {
|
||||
pm->toplevel[i] = vmm_kernel_pm->toplevel[i];
|
||||
}
|
||||
}
|
||||
|
||||
return pm;
|
||||
}
|
||||
|
||||
void vmm_release_pm(pagemap_t *pm) {
|
||||
memset(pm->toplevel, 0, PMM_PAGE_SIZE);
|
||||
memset(pm, 0, PMM_PAGE_SIZE);
|
||||
pmm_free_page(pm->toplevel);
|
||||
pmm_free_page(pm);
|
||||
}
|
||||
|
||||
void vmm_sanity_check() {
|
||||
uint64_t *my_memory = HIGHER_HALF(pmm_request_page());
|
||||
*my_memory = 0x40;
|
||||
|
||||
pagemap_t *pm = vmm_alloc_pm();
|
||||
vmm_map(pm, 0x1000, (uint64_t)my_memory, VMM_PRESENT | VMM_WRITABLE);
|
||||
|
||||
uint64_t *my_ptr = (uint64_t *)0x1000;
|
||||
uint64_t ptr_val = 0;
|
||||
vmm_load_pagemap(pm);
|
||||
ptr_val = *my_ptr;
|
||||
vmm_load_pagemap(vmm_kernel_pm);
|
||||
|
||||
if (ptr_val != 0x40) {
|
||||
log("vmm - sanity check failed. system halted.\n");
|
||||
asm("cli");
|
||||
while (1)
|
||||
asm("hlt");
|
||||
}
|
||||
}
|
||||
|
||||
void vmm_init() {
|
||||
if (pmrq.response->mode != LIMINE_PAGING_MODE_X86_64_4LVL) {
|
||||
log("vmm - Soaplin only supports 4-level paging!\n");
|
||||
asm("cli; hlt;");
|
||||
}
|
||||
vmm_kernel_pm = vmm_alloc_pm();
|
||||
vmm_kernel_pm_exists = 1;
|
||||
|
||||
uint64_t kphysaddr = karq.response->physical_base;
|
||||
uint64_t kvirtaddr = karq.response->virtual_base;
|
||||
|
||||
uint64_t reqs_start = ALIGN_DOWN((uint64_t)reqs_start_ld, PMM_PAGE_SIZE);
|
||||
uint64_t reqs_end = ALIGN_UP((uint64_t)reqs_end_ld, PMM_PAGE_SIZE);
|
||||
uint64_t text_start = ALIGN_DOWN((uint64_t)text_start_ld, PMM_PAGE_SIZE);
|
||||
uint64_t text_end = ALIGN_UP((uint64_t)text_end_ld, PMM_PAGE_SIZE);
|
||||
uint64_t rodata_start = ALIGN_DOWN((uint64_t)rodata_start_ld, PMM_PAGE_SIZE);
|
||||
uint64_t rodata_end = ALIGN_UP((uint64_t)rodata_end_ld, PMM_PAGE_SIZE);
|
||||
uint64_t data_start = ALIGN_DOWN((uint64_t)data_start_ld, PMM_PAGE_SIZE);
|
||||
uint64_t data_end = ALIGN_UP((uint64_t)data_end_ld, PMM_PAGE_SIZE);
|
||||
|
||||
log("vmm - mapping .requests section...\n");
|
||||
for (uint64_t req = reqs_start; req < reqs_end; req += PMM_PAGE_SIZE) {
|
||||
vmm_map(vmm_kernel_pm, req, req - kvirtaddr + kphysaddr,
|
||||
VMM_PRESENT | VMM_WRITABLE);
|
||||
}
|
||||
|
||||
log("vmm - mapping .text section...\n");
|
||||
for (uint64_t text = text_start; text < text_end; text += PMM_PAGE_SIZE) {
|
||||
vmm_map(vmm_kernel_pm, text, text - kvirtaddr + kphysaddr, VMM_PRESENT);
|
||||
}
|
||||
|
||||
log("vmm - mapping .rodata section...\n");
|
||||
for (uint64_t roData = rodata_start; roData < rodata_end;
|
||||
roData += PMM_PAGE_SIZE)
|
||||
vmm_map(vmm_kernel_pm, roData, roData - kvirtaddr + kphysaddr,
|
||||
VMM_PRESENT | VMM_NX);
|
||||
|
||||
log("vmm - mapping .data section...\n");
|
||||
for (uint64_t data = data_start; data < data_end; data += PMM_PAGE_SIZE)
|
||||
vmm_map(vmm_kernel_pm, data, data - kvirtaddr + kphysaddr,
|
||||
VMM_PRESENT | VMM_WRITABLE | VMM_NX);
|
||||
|
||||
log("vmm - mapping address from 0x0 to 0x100000000...\n");
|
||||
for (uint64_t gb4 = 0; gb4 < 0x100000000; gb4 += PMM_PAGE_SIZE) {
|
||||
//vmm_map(vmm_kernel_pm, gb4, gb4, VMM_PRESENT | VMM_WRITABLE);
|
||||
vmm_map(vmm_kernel_pm, (uint64_t)HIGHER_HALF(gb4), gb4,
|
||||
VMM_PRESENT | VMM_WRITABLE);
|
||||
}
|
||||
|
||||
vmm_load_pagemap(vmm_kernel_pm);
|
||||
|
||||
//vmm_sanity_check();
|
||||
log("vmm - initialized!\n");
|
||||
}
|
||||
|
||||
void vmm_load_pagemap(pagemap_t *pm) {
|
||||
if (!pm)
|
||||
return;
|
||||
|
||||
if (!pm->toplevel)
|
||||
return;
|
||||
|
||||
vmm_current_pm = pm;
|
||||
__asm__ volatile("mov %0, %%cr3" : : "r"(PHYSICAL(pm->toplevel)) : "memory");
|
||||
}
|
||||
|
||||
static uint64_t *__vmm_get_next_lvl(uint64_t *level, uint64_t entry,
|
||||
uint64_t flags, bool alloc) {
|
||||
if (level[entry] & VMM_PRESENT)
|
||||
return HIGHER_HALF(PTE_GET_ADDR(level[entry]));
|
||||
if (alloc) {
|
||||
uint64_t *pml = (uint64_t *)HIGHER_HALF(pmm_request_page());
|
||||
memset(pml, 0, PMM_PAGE_SIZE);
|
||||
level[entry] = (uint64_t)PHYSICAL(pml) | flags;
|
||||
return pml;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint64_t vmm_get_flags(pagemap_t *pm, uint64_t vaddr) {
|
||||
uint64_t pml4_entry = (vaddr >> 39) & 0x1ff;
|
||||
uint64_t pml3_entry = (vaddr >> 30) & 0x1ff;
|
||||
uint64_t pml2_entry = (vaddr >> 21) & 0x1ff;
|
||||
uint64_t pml1_entry = (vaddr >> 12) & 0x1ff;
|
||||
|
||||
uint64_t *pml3 = __vmm_get_next_lvl(pm->toplevel, pml4_entry, 0, false);
|
||||
if (!pml3)
|
||||
return 0;
|
||||
uint64_t *pml2 = __vmm_get_next_lvl(pml3, pml3_entry, 0, false);
|
||||
if (!pml2)
|
||||
return 0;
|
||||
uint64_t *pml1 = __vmm_get_next_lvl(pml2, pml2_entry, 0, false);
|
||||
if (!pml1)
|
||||
return 0;
|
||||
|
||||
return pml1[pml1_entry] & 0x7000000000000FFF;
|
||||
}
|
||||
|
||||
uint64_t virt_to_phys(pagemap_t *pagemap, uint64_t virt) {
|
||||
uint64_t pml4_idx = (virt >> 39) & 0x1FF;
|
||||
uint64_t pml3_idx = (virt >> 30) & 0x1FF;
|
||||
uint64_t pml2_idx = (virt >> 21) & 0x1FF;
|
||||
uint64_t pml1_idx = (virt >> 12) & 0x1FF;
|
||||
|
||||
uint64_t *pml3 = __vmm_get_next_lvl(pagemap->toplevel, pml4_idx, 0, false);
|
||||
if (!pml3)
|
||||
return 0;
|
||||
uint64_t *pml2 = __vmm_get_next_lvl(pml3, pml3_idx, 0, false);
|
||||
if (!pml2)
|
||||
return 0;
|
||||
uint64_t *pml1 = __vmm_get_next_lvl(pml2, pml2_idx, 0, false);
|
||||
if (!pml1)
|
||||
return 0;
|
||||
|
||||
uint64_t phys_addr = pml1[pml1_idx] & 0x000FFFFFFFFFF000;
|
||||
|
||||
return phys_addr;
|
||||
}
|
||||
|
||||
void vmm_map(pagemap_t *pm, uint64_t vaddr, uint64_t paddr, uint64_t flags) {
|
||||
uint64_t pml4_entry = (vaddr >> 39) & 0x1ff;
|
||||
uint64_t pml3_entry = (vaddr >> 30) & 0x1ff;
|
||||
uint64_t pml2_entry = (vaddr >> 21) & 0x1ff;
|
||||
uint64_t pml1_entry = (vaddr >> 12) & 0x1ff;
|
||||
|
||||
uint64_t *pml3 = __vmm_get_next_lvl(pm->toplevel, pml4_entry,
|
||||
VMM_PRESENT | VMM_WRITABLE, true);
|
||||
uint64_t *pml2 =
|
||||
__vmm_get_next_lvl(pml3, pml3_entry, VMM_PRESENT | VMM_WRITABLE, true);
|
||||
uint64_t *pml1 =
|
||||
__vmm_get_next_lvl(pml2, pml2_entry, VMM_PRESENT | VMM_WRITABLE, true);
|
||||
|
||||
pml1[pml1_entry] = paddr | flags;
|
||||
}
|
||||
|
||||
void vmm_map_user(pagemap_t *pm, uint64_t vaddr, uint64_t paddr,
|
||||
uint64_t flags) {
|
||||
uint64_t pml4_entry = (vaddr >> 39) & 0x1ff;
|
||||
uint64_t pml3_entry = (vaddr >> 30) & 0x1ff;
|
||||
uint64_t pml2_entry = (vaddr >> 21) & 0x1ff;
|
||||
uint64_t pml1_entry = (vaddr >> 12) & 0x1ff;
|
||||
|
||||
uint64_t *pml3 =
|
||||
__vmm_get_next_lvl(pm->toplevel, pml4_entry, flags | VMM_WRITABLE,
|
||||
true); // PML3 / Page Directory Pointer Entry
|
||||
uint64_t *pml2 = __vmm_get_next_lvl(pml3, pml3_entry, flags | VMM_WRITABLE,
|
||||
true); // PML2 / Page Directory Entry
|
||||
uint64_t *pml1 = __vmm_get_next_lvl(pml2, pml2_entry, flags | VMM_WRITABLE,
|
||||
true); // PML1 / Page Table Entry
|
||||
|
||||
pml1[pml1_entry] = paddr | flags;
|
||||
}
|
||||
|
||||
void vmm_unmap(pagemap_t *pm, uint64_t vaddr) {
|
||||
uint64_t pml1_entry = (vaddr >> 12) & 0x1ff;
|
||||
uint64_t pml2_entry = (vaddr >> 21) & 0x1ff;
|
||||
uint64_t pml3_entry = (vaddr >> 30) & 0x1ff;
|
||||
uint64_t pml4_entry = (vaddr >> 39) & 0x1ff;
|
||||
|
||||
uint64_t *pml3 = __vmm_get_next_lvl(pm->toplevel, pml4_entry, 0, false);
|
||||
if (pml3 == NULL)
|
||||
return;
|
||||
uint64_t *pml2 = __vmm_get_next_lvl(pml3, pml3_entry, 0, false);
|
||||
if (pml2 == NULL)
|
||||
return;
|
||||
uint64_t *pml1 = __vmm_get_next_lvl(pml2, pml2_entry, 0, false);
|
||||
if (pml1 == NULL)
|
||||
return;
|
||||
|
||||
pml1[pml1_entry] = 0;
|
||||
|
||||
__asm__ volatile("invlpg (%0)" : : "b"(vaddr) : "memory");
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define PTE_ADDR_MASK 0x000ffffffffff000
|
||||
#define PTE_GET_ADDR(VALUE) ((VALUE) & PTE_ADDR_MASK)
|
||||
#define PTE_GET_FLAGS(VALUE) ((VALUE) & ~PTE_ADDR_MASK)
|
||||
|
||||
#define VMM_PRESENT (1 << 0)
|
||||
#define VMM_WRITABLE (1 << 1)
|
||||
#define VMM_USER (1 << 2)
|
||||
#define VMM_NX (1ULL << 63)
|
||||
|
||||
typedef char sym[];
|
||||
|
||||
extern sym reqs_start_ld;
|
||||
extern sym reqs_end_ld;
|
||||
|
||||
extern sym text_start_ld;
|
||||
extern sym text_end_ld;
|
||||
|
||||
extern sym rodata_start_ld;
|
||||
extern sym rodata_end_ld;
|
||||
|
||||
extern sym data_start_ld;
|
||||
extern sym data_end_ld;
|
||||
|
||||
typedef struct pagemap {
|
||||
uint64_t *toplevel;
|
||||
} pagemap_t;
|
||||
|
||||
extern pagemap_t *vmm_kernel_pm;
|
||||
extern pagemap_t *vmm_current_pm;
|
||||
|
||||
pagemap_t *vmm_alloc_pm();
|
||||
void vmm_init();
|
||||
void vmm_release_pm(pagemap_t *pm);
|
||||
void vmm_load_pagemap(pagemap_t *pm);
|
||||
uint64_t vmm_get_flags(pagemap_t *pm, uint64_t vaddr);
|
||||
uint64_t virt_to_phys(pagemap_t *pagemap, uint64_t virt);
|
||||
|
||||
// NOTE: for user mode, please use vmm_map_user instead.
|
||||
void vmm_map(pagemap_t *pm, uint64_t vaddr, uint64_t paddr, uint64_t flags);
|
||||
void vmm_map_user(pagemap_t *pm, uint64_t vaddr, uint64_t paddr,
|
||||
uint64_t flags);
|
||||
void vmm_unmap(pagemap_t *pm, uint64_t vaddr);
|
|
@ -1,10 +0,0 @@
|
|||
bits 64
|
||||
section .text
|
||||
global kmain
|
||||
extern __kmain
|
||||
extern kstack
|
||||
|
||||
kmain:
|
||||
mov rsp, kstack+0x2000 ; supposons 16 KiB de stack
|
||||
xor rbp, rbp ; Set %ebp to NULL
|
||||
call __kmain
|
|
@ -1,204 +0,0 @@
|
|||
#include "sched/sched.h"
|
||||
#include "arch/x86_64/idt.h"
|
||||
#include "arch/x86_64/msr.h"
|
||||
#include "mm/memop.h"
|
||||
#include "mm/pmm.h"
|
||||
#include "mm/vmm.h"
|
||||
#include "sys/errhnd/panic.h"
|
||||
#include "sys/log.h"
|
||||
#include <lib/string.h>
|
||||
#include <mm/liballoc/liballoc.h>
|
||||
#include <stddef.h>
|
||||
|
||||
sched_process *proc_list;
|
||||
sched_process *curr_proc;
|
||||
int current_pid = 0;
|
||||
int standby = 0;
|
||||
|
||||
void map_range_to_pagemap(pagemap_t *dest_pagemap, pagemap_t *src_pagemap,
|
||||
uint64_t start, uint64_t size, int user,
|
||||
uint64_t flags) {
|
||||
for (uint64_t offset = 0; offset < size; offset += PMM_PAGE_SIZE) {
|
||||
uint64_t phys = virt_to_phys(src_pagemap, start + offset);
|
||||
if (phys) {
|
||||
if (user)
|
||||
vmm_map_user(dest_pagemap, start + offset, phys, flags);
|
||||
else
|
||||
vmm_map(dest_pagemap, start + offset, phys, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void __sched_enter_standby() {
|
||||
standby = 1;
|
||||
log("sched - As there's nothing "
|
||||
"to schedule, the scheduler entered standby"
|
||||
"mode.\n");
|
||||
}
|
||||
|
||||
static void __sched_exit_standby() {
|
||||
standby = 0;
|
||||
log("sched - The scheduler exited standby mode.\n");
|
||||
}
|
||||
|
||||
void sched_init() {
|
||||
// TODO: It may be good to implement heap memory to save space.
|
||||
|
||||
// We must initialize the process list.
|
||||
// By default, sched_create will append to this list.
|
||||
proc_list = malloc(sizeof(sched_process));
|
||||
memcpy(proc_list->name, "System\0", 7);
|
||||
proc_list->pid = -1;
|
||||
proc_list->type = SCHED_EMPTY;
|
||||
proc_list->flags = SCHED_KERNEL_PROCESS;
|
||||
proc_list->pm = vmm_kernel_pm;
|
||||
|
||||
curr_proc = proc_list;
|
||||
__sched_enter_standby();
|
||||
}
|
||||
|
||||
sched_process *sched_create(char *name, uint64_t entry_point, pagemap_t *pm,
|
||||
uint32_t flags) {
|
||||
|
||||
sched_process *proc = malloc(sizeof(sched_process));
|
||||
memset(proc, 0, sizeof(sched_process));
|
||||
|
||||
memcpy(proc->name, name, strlen(name) > 128 ? 128 : strlen(name));
|
||||
proc->pid = current_pid;
|
||||
proc->type = SCHED_RUNNING;
|
||||
proc->flags = flags;
|
||||
|
||||
// We are about to setup the registers ourself.
|
||||
// If it's broken, it's a boom in the ass of your computer
|
||||
// (and a CPU exception)
|
||||
|
||||
proc->pm = pm;
|
||||
|
||||
uint64_t *stack_phys = pmm_request_page();
|
||||
uint64_t *kstack_phys = pmm_request_page();
|
||||
uint64_t *stack_virt = (uint64_t *)0x40000000;
|
||||
|
||||
proc->kernel_stack = HIGHER_HALF(kstack_phys) + PMM_PAGE_SIZE;
|
||||
if (flags == SCHED_KERNEL_PROCESS) {
|
||||
proc->stack_base = HIGHER_HALF(stack_phys);
|
||||
proc->stack_base_physical = stack_phys;
|
||||
proc->stack_end = proc->stack_base + PMM_PAGE_SIZE;
|
||||
} else if (flags == SCHED_USER_PROCESS) {
|
||||
vmm_map_user(proc->pm, (uint64_t)stack_virt, (uint64_t)stack_phys,
|
||||
VMM_PRESENT | VMM_WRITABLE | VMM_USER);
|
||||
proc->stack_base = stack_virt;
|
||||
proc->stack_base_physical = stack_phys;
|
||||
proc->stack_end = proc->stack_base + PMM_PAGE_SIZE;
|
||||
}
|
||||
proc->regs.rip = (uint64_t)entry_point;
|
||||
|
||||
if (flags == SCHED_KERNEL_PROCESS) {
|
||||
proc->regs.cs = 0x28; // Run in kernel mode
|
||||
proc->regs.ss = 0x30;
|
||||
} else if (flags == SCHED_USER_PROCESS) {
|
||||
proc->regs.cs = 0x40 | 3; // Run in user mode
|
||||
proc->regs.ss = 0x38 | 3;
|
||||
}
|
||||
proc->regs.rflags = 0x202; // Enable interrupts
|
||||
proc->regs.rsp = (uint64_t)proc->stack_end;
|
||||
proc->regs.rbp = 0;
|
||||
|
||||
proc->next = curr_proc->next;
|
||||
curr_proc->next = proc;
|
||||
|
||||
current_pid++;
|
||||
|
||||
if (flags == SCHED_USER_PROCESS)
|
||||
map_range_to_pagemap(pm, vmm_kernel_pm, 0x1000, 0x10000, 1,
|
||||
VMM_PRESENT | VMM_WRITABLE | VMM_USER);
|
||||
else
|
||||
map_range_to_pagemap(pm, vmm_kernel_pm, 0x1000, 0x10000, 0,
|
||||
VMM_PRESENT | VMM_WRITABLE);
|
||||
|
||||
if (standby) {
|
||||
__sched_exit_standby();
|
||||
}
|
||||
|
||||
log("sched - created process '%s' (pid: %d, rip: %p)\n", proc->name,
|
||||
proc->pid, proc->regs.rip);
|
||||
return proc;
|
||||
}
|
||||
|
||||
sched_process *sched_from_program(program_t *prog) {
|
||||
// D̶̡͖̼̪̩̽̃̿͐͐̀̑͐̑ǫ̴͚̘̩̗̠̣̗͇̳̀̅̈͌͆͆ ̸̢̢̯͎̳̟̑͋́N̷̹͛̋͗ö̴͇̼̖̝̼́̀̾̿̾̓̔̌t̵̯̘͇̙̬̤̫͚͓̠͔̭̚ͅ ̵͔̲͈̭͛̆̈Ú̷̱̈́͑́̇̀̈́̔͝͠s̴̢͇̳̯̬͔̦̗̯̜̀̓̎̆̅̈́̈́̑̾͆͌̆͝ê̴̛͎̪̩̙͕̖͖͍͓͐̊̈͋̆̂̌̍̂͘͘̚ ̵̢̢͖̦̬͔̻͇̠̺̂͒͌͌̈́̇̏͑͋̓̔̅̓͂͝S̴̡͇͎̠̯͙̖̲̮͓͋͊̐̋̑́͂͆̿C̵̤̲͉̫̜͓͇̙͇̪̥̈̂́̈́͋̃̿̕H̶̡͓̠̝͉͋͋̎̃E̶͉̬̞̖̮͚̙͗̔̋͆Ḑ̴̛͎̙̥̱̱͎͊͊͋̈́̆̎̓͑̚̚_̷͚̯̻̖͈̳̺̖̈͗́̽͠Ḱ̴̮͓̲̠̫͈̆̿͂͂̀̂͆̀́̔͝ͅḘ̷̡͔̘̒̒̐͆̍̀R̵̭̰̐́̾̈́̈́̋͗̎̉͐͝N̴̰͆̂͛̂̈́̄̊͌̓͆̕͘͠͠Ě̴̥͙̼̳̩̠͓͕̫͔̘̠̻̀͌̓͑́̓̂̋̌͘͜L̴̙͓̣̭̙͙͈̺̩̄̈͆͆͒͗͛̈́̎̉̈́͘͘͜͠_̵̭̱͇͍̩̬͌̿͂͊̐͘̕ͅP̵̡̪̹̀͂̀̋̇̓͘͜Ŕ̸̭͍̮̼̙͓͕̳̫̇̏͌͌̋͜͝Ǫ̵̛͎̭̱͈̫̮̘͉͔̪̟̺̥̉̈̈́̊́̕̕͠ͅC̵̡̡͕̱̠̝̭͓̗̜͇̼̳̲͓̑̽̔̑͠Ę̷̛̦̑̈̒̃̊̈́̓̚̚͜͠͝Ş̴̥͇̬̱̠̟͙̳̖̿͗̀͌͊̽̐͒̃͜S̴͉͖͉͎͎̱̝͔̙̜̭̍͑͊̒͆̃͗̂͌̽͑̓ͅ ̶̼̥̜͙͈̦̲̰̞̈́̑͆̂͝H̸̩̭̹̘̩̊͗̔̉̓̈́ȩ̷̩͍͚̮̰̭̘͍͇͈̺͇̻̓̀̅̊́̓̈́͗̇̔̓͛͜͝ṙ̶̡̩̜̜̭̝̪͔͙̟̣͉̆͗̉͜͠͝ͅę̷̡̦̘̰͖̲͉̤̼͈̺̺̦̯̿͌́͐̃̃͂̾́̊́.̶̡̧͈͍͈̟̠͙̘̤̝̪̽̊̈͐̕͜
|
||||
return sched_create("unknown program", prog->entry, prog->pm, SCHED_USER_PROCESS);
|
||||
}
|
||||
void sched_exit(int exit_code) {
|
||||
log("sched - Process %d exited with code %d!\n", curr_proc->pid, exit_code);
|
||||
curr_proc->type = SCHED_DIED;
|
||||
schedule(&curr_proc->regs);
|
||||
}
|
||||
|
||||
void schedule(registers_t *regs) {
|
||||
if (standby) {
|
||||
// log("sched - Sched is in standby.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (curr_proc->type != SCHED_DIED) {
|
||||
memcpy(&curr_proc->regs, regs, sizeof(registers_t));
|
||||
}
|
||||
|
||||
if (curr_proc->type == SCHED_DIED) {
|
||||
sched_process *prev_proc = proc_list;
|
||||
sched_process *next = curr_proc->next;
|
||||
if (next == NULL) {
|
||||
next = proc_list;
|
||||
}
|
||||
|
||||
if (proc_list == curr_proc) {
|
||||
goto kill_process;
|
||||
}
|
||||
|
||||
while (prev_proc->next != curr_proc) {
|
||||
prev_proc = prev_proc->next;
|
||||
}
|
||||
|
||||
kill_process:
|
||||
if (next == NULL) {
|
||||
next = proc_list;
|
||||
}
|
||||
|
||||
if (proc_list == curr_proc) {
|
||||
vmm_release_pm(curr_proc->pm);
|
||||
pmm_free_page(curr_proc->stack_base_physical);
|
||||
free(curr_proc);
|
||||
|
||||
__sched_enter_standby();
|
||||
return;
|
||||
}
|
||||
|
||||
prev_proc->next = next;
|
||||
|
||||
vmm_release_pm(curr_proc->pm);
|
||||
pmm_free_page(curr_proc->stack_base_physical);
|
||||
free(curr_proc);
|
||||
|
||||
curr_proc = next;
|
||||
} else {
|
||||
curr_proc = curr_proc->next;
|
||||
if (curr_proc == NULL)
|
||||
curr_proc = proc_list;
|
||||
}
|
||||
|
||||
if (curr_proc->type == SCHED_RUNNING) {
|
||||
memcpy(regs, &curr_proc->regs, sizeof(registers_t));
|
||||
} else if (curr_proc->type == SCHED_EMPTY) {
|
||||
memset(regs, 0, sizeof(registers_t));
|
||||
regs->cs = 0x28;
|
||||
regs->ss = 0x30;
|
||||
regs->rflags = 0x202;
|
||||
regs->rip = 0;
|
||||
} else {
|
||||
panic("sched - Tried to schedule a dead process.\n");
|
||||
}
|
||||
|
||||
wrmsr(IA32_GS_KERNEL_MSR, (uint64_t)curr_proc);
|
||||
// log("sched - proc %d\n", curr_proc->pid);
|
||||
vmm_load_pagemap(curr_proc->pm);
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "arch/x86_64/idt.h"
|
||||
#include "exec/exec.h"
|
||||
#include "mm/vmm.h"
|
||||
|
||||
#define SCHED_KERNEL_PROCESS 0 // A process that runs in kernel mode.
|
||||
#define SCHED_USER_PROCESS \
|
||||
1 // A process that runs in userspace. The code MUST be mapped directly after
|
||||
// creating the process.
|
||||
|
||||
typedef enum { SCHED_RUNNING, SCHED_DIED, SCHED_EMPTY } sched_proc_type;
|
||||
|
||||
typedef struct _sched_process {
|
||||
uint64_t *stack_base;
|
||||
uint64_t *kernel_stack; // Kernel-mode stack used for "syscall"
|
||||
|
||||
char name[128];
|
||||
int pid;
|
||||
int type;
|
||||
int flags;
|
||||
|
||||
registers_t regs;
|
||||
pagemap_t *pm;
|
||||
|
||||
uint64_t *stack_end;
|
||||
uint64_t *stack_base_physical;
|
||||
|
||||
struct _sched_process *next;
|
||||
} sched_process;
|
||||
|
||||
extern sched_process *curr_proc;
|
||||
extern sched_process *proc_list;
|
||||
|
||||
// The idle process is ditched in favor of standby mode,
|
||||
// which activates when there's nothing to run.
|
||||
// extern sched_process *idle_process;
|
||||
|
||||
void sched_init();
|
||||
sched_process *sched_create(char *name, uint64_t entry_point, pagemap_t *pm,
|
||||
uint32_t flags);
|
||||
|
||||
sched_process *sched_from_program(program_t *prog);
|
||||
|
||||
void sched_exit(int exit_code);
|
||||
void schedule(registers_t *regs);
|
|
@ -1,58 +0,0 @@
|
|||
#include "limine.h"
|
||||
#include "mm/pmm.h"
|
||||
#include "sys/log.h"
|
||||
#include <mm/memop.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/acpi.h>
|
||||
#include <sys/errhnd/panic.h>
|
||||
|
||||
__attribute__((
|
||||
used,
|
||||
section(".limine_requests"))) static volatile struct limine_rsdp_request
|
||||
rsdp_req = {.revision = 0, .id = LIMINE_RSDP_REQUEST};
|
||||
|
||||
static int __acpi_uses_xsdt = 0;
|
||||
static void *__acpi_rsdt_ptr;
|
||||
|
||||
void *acpi_find_table(const char *name) {
|
||||
if (!__acpi_uses_xsdt) {
|
||||
acpi_rsdt *rsdt = (acpi_rsdt *)__acpi_rsdt_ptr;
|
||||
uint32_t entries = (rsdt->sdt.len - sizeof(rsdt->sdt)) / 4;
|
||||
|
||||
for (uint32_t i = 0; i < entries; i++) {
|
||||
acpi_sdt *sdt = (acpi_sdt *)HIGHER_HALF(*((uint32_t *)rsdt->table + i));
|
||||
if (!memcmp(sdt->sign, name, 4))
|
||||
return (void *)sdt;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
acpi_xsdt *xsdt = (acpi_xsdt *)__acpi_rsdt_ptr;
|
||||
uint32_t entries = (xsdt->sdt.len - sizeof(xsdt->sdt)) / 8;
|
||||
|
||||
for (uint32_t i = 0; i < entries; i++) {
|
||||
acpi_sdt *sdt = (acpi_sdt *)HIGHER_HALF(*((uint64_t *)xsdt->table + i));
|
||||
if (!memcmp(sdt->sign, name, 4)) {
|
||||
return (void *)sdt;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void acpi_init() {
|
||||
acpi_rsdp *rsdp = (acpi_rsdp *)HIGHER_HALF(rsdp_req.response->address);
|
||||
|
||||
if (memcmp(rsdp->sign, "RSD PTR", 7))
|
||||
panic("acpi: Invalid RSDP signature!");
|
||||
|
||||
if (rsdp->revision != 0) {
|
||||
__acpi_uses_xsdt = 1;
|
||||
acpi_xsdp *xsdp = (acpi_xsdp *)rsdp;
|
||||
__acpi_rsdt_ptr = (void *)HIGHER_HALF(xsdp->xsdt_addr);
|
||||
return;
|
||||
}
|
||||
|
||||
__acpi_rsdt_ptr = (void *)HIGHER_HALF(rsdp->rsdt_addr);
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define ACPI_RSDP_SIGNATURE "RSD PTR "
|
||||
#define ACPI_RSDP_SIGNATURE_LEN 7
|
||||
|
||||
typedef struct {
|
||||
char sign[8];
|
||||
uint8_t checksum;
|
||||
char oem_id[6];
|
||||
uint8_t revision;
|
||||
uint32_t rsdt_addr;
|
||||
} __attribute__((packed)) acpi_rsdp;
|
||||
|
||||
typedef struct {
|
||||
char sign[8];
|
||||
uint8_t checksum;
|
||||
char oem_id[6];
|
||||
uint8_t revision;
|
||||
uint32_t resv;
|
||||
|
||||
uint32_t length;
|
||||
uint64_t xsdt_addr;
|
||||
uint8_t extended_checksum;
|
||||
uint8_t resv1[3];
|
||||
} __attribute__((packed)) acpi_xsdp;
|
||||
|
||||
typedef struct {
|
||||
char sign[4];
|
||||
uint32_t len;
|
||||
uint8_t revision;
|
||||
uint8_t checksum;
|
||||
char oem_id[6];
|
||||
char oem_table_id[8];
|
||||
uint32_t oem_revision;
|
||||
uint32_t creator_id;
|
||||
uint32_t creator_revision;
|
||||
} __attribute__((packed)) acpi_sdt;
|
||||
|
||||
typedef struct {
|
||||
acpi_sdt sdt;
|
||||
char table[];
|
||||
} acpi_rsdt;
|
||||
|
||||
typedef struct {
|
||||
acpi_sdt sdt;
|
||||
char table[];
|
||||
} acpi_xsdt;
|
||||
|
||||
void *acpi_find_table(const char *name);
|
||||
void acpi_init();
|
|
@ -1,42 +0,0 @@
|
|||
#include "sys/acpi.h"
|
||||
#include <stdint.h>
|
||||
#include <sys/acpi/madt.h>
|
||||
#include <sys/errhnd/panic.h>
|
||||
#include <sys/log.h>
|
||||
|
||||
madt_ioapic *acpi_madt_ioapic_list[256] = {0};
|
||||
madt_iso *acpi_madt_iso_list[256] = {0};
|
||||
|
||||
uint32_t acpi_madt_ioapic_length = 0;
|
||||
uint32_t acpi_madt_iso_length = 0;
|
||||
|
||||
uint64_t *acpi_lapic_addr = 0;
|
||||
|
||||
void madt_init() {
|
||||
void *addr = acpi_find_table("APIC");
|
||||
if (!addr)
|
||||
panic("madt: Failed to find MADT table!");
|
||||
|
||||
acpi_madt *madt = (acpi_madt *)addr;
|
||||
|
||||
uint64_t offset = 0;
|
||||
int i = 0;
|
||||
|
||||
while (1) {
|
||||
if (offset > madt->sdt.len - sizeof(acpi_madt))
|
||||
break;
|
||||
|
||||
madt_entry *entry = (madt_entry *)(madt->table + offset);
|
||||
|
||||
if (entry->type == 0)
|
||||
i++;
|
||||
else if (entry->type == 1)
|
||||
acpi_madt_ioapic_list[acpi_madt_ioapic_length++] = (madt_ioapic *)entry;
|
||||
else if (entry->type == 2)
|
||||
acpi_madt_iso_list[acpi_madt_iso_length++] = (madt_iso *)entry;
|
||||
else if (entry->type == 5)
|
||||
acpi_lapic_addr = (uint64_t *)((madt_lapic_addr *)entry)->phys_lapic;
|
||||
|
||||
offset += entry->length;
|
||||
}
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "sys/acpi.h"
|
||||
#include <stdint.h>
|
||||
typedef struct {
|
||||
acpi_sdt sdt;
|
||||
|
||||
uint32_t lapic_address;
|
||||
uint32_t flags;
|
||||
|
||||
char table[];
|
||||
} acpi_madt;
|
||||
|
||||
typedef struct {
|
||||
uint8_t type;
|
||||
uint8_t length;
|
||||
} madt_entry;
|
||||
|
||||
typedef struct {
|
||||
madt_entry un;
|
||||
uint8_t cpu_id;
|
||||
uint8_t apic_id;
|
||||
uint32_t flags;
|
||||
} madt_cpu_lapic;
|
||||
|
||||
typedef struct {
|
||||
madt_entry un;
|
||||
uint8_t apic_id;
|
||||
uint8_t reserved;
|
||||
uint32_t apic_addr;
|
||||
uint32_t gsi_base;
|
||||
} madt_ioapic;
|
||||
|
||||
typedef struct {
|
||||
madt_entry un;
|
||||
uint8_t bus_src;
|
||||
uint8_t irq_src;
|
||||
uint32_t gsi;
|
||||
uint16_t flags;
|
||||
} madt_iso;
|
||||
|
||||
typedef struct {
|
||||
madt_entry un;
|
||||
uint16_t reserved;
|
||||
uint64_t phys_lapic;
|
||||
} madt_lapic_addr;
|
||||
|
||||
extern madt_ioapic *acpi_madt_ioapic_list[256];
|
||||
extern madt_iso *acpi_madt_iso_list[256];
|
||||
|
||||
extern uint32_t acpi_madt_ioapic_length;
|
||||
extern uint32_t acpi_madt_iso_length;
|
||||
|
||||
extern uint64_t *acpi_lapic_addr;
|
||||
|
||||
void madt_init();
|
|
@ -1,208 +0,0 @@
|
|||
#include "sys/errhnd/panic.h"
|
||||
#include "arch/x86_64/idt.h"
|
||||
#include "lib/spinlock.h"
|
||||
#include <mm/memop.h>
|
||||
#include <sys/log.h>
|
||||
|
||||
#include "sched/sched.h"
|
||||
|
||||
static registers_t __panic_regdump;
|
||||
|
||||
static void __panic_dump_regs() {
|
||||
memset(&__panic_regdump, 0, sizeof(registers_t));
|
||||
|
||||
asm volatile(
|
||||
// Save general purpose registers
|
||||
"movq %%r15, %0\n\t"
|
||||
"movq %%r14, %1\n\t"
|
||||
"movq %%r13, %2\n\t"
|
||||
"movq %%r12, %3\n\t"
|
||||
"movq %%r11, %4\n\t"
|
||||
"movq %%r10, %5\n\t"
|
||||
"movq %%r9, %6\n\t"
|
||||
"movq %%r8, %7\n\t"
|
||||
"movq %%rdi, %8\n\t"
|
||||
"movq %%rsi, %9\n\t"
|
||||
"movq %%rbp, %10\n\t"
|
||||
"movq %%rbx, %11\n\t"
|
||||
"movq %%rdx, %12\n\t"
|
||||
"movq %%rcx, %13\n\t"
|
||||
"movq %%rax, %14\n\t"
|
||||
|
||||
// The rest of the registers (rip, cs, rflags, rsp, ss) would typically
|
||||
// be captured in the interrupt/exception handler context and passed in
|
||||
// We'll zero them out here since we don't have direct access
|
||||
: "=m"(__panic_regdump.r15), "=m"(__panic_regdump.r14),
|
||||
"=m"(__panic_regdump.r13), "=m"(__panic_regdump.r12),
|
||||
"=m"(__panic_regdump.r11), "=m"(__panic_regdump.r10),
|
||||
"=m"(__panic_regdump.r9), "=m"(__panic_regdump.r8),
|
||||
"=m"(__panic_regdump.rdi), "=m"(__panic_regdump.rsi),
|
||||
"=m"(__panic_regdump.rbp), "=m"(__panic_regdump.rbx),
|
||||
"=m"(__panic_regdump.rdx), "=m"(__panic_regdump.rcx),
|
||||
"=m"(__panic_regdump.rax)
|
||||
:
|
||||
: "memory");
|
||||
|
||||
// Zero out the registers we can't directly access in this context
|
||||
__panic_regdump.int_no = 0;
|
||||
__panic_regdump.err_code = 0;
|
||||
__panic_regdump.rip = 0;
|
||||
__panic_regdump.cs = 0;
|
||||
__panic_regdump.rflags = 0;
|
||||
__panic_regdump.rsp = 0;
|
||||
__panic_regdump.ss = 0;
|
||||
}
|
||||
|
||||
static void __panic_display_page_fault(registers_t *regs) {
|
||||
if (regs->int_no != 14) // 14 is the page fault interrupt number
|
||||
return;
|
||||
|
||||
uint64_t cr2;
|
||||
asm volatile("mov %%cr2, %0" : "=r"(cr2));
|
||||
|
||||
log("-- PAGE FAULT DETAILS --\n");
|
||||
log("This appears to be a page fault.\n");
|
||||
log("\n");
|
||||
log("Faulting Address (CR2): 0x%lx\n", cr2);
|
||||
log("Error Code: %d\n", regs->err_code);
|
||||
log("Flags:\n");
|
||||
if (!(regs->err_code & (1 << 0)))
|
||||
log(" - Page Not Present\n");
|
||||
else
|
||||
log(" - Protection Violation\n");
|
||||
|
||||
if (regs->err_code & (1 << 1))
|
||||
log(" - Write Access\n");
|
||||
else
|
||||
log(" - Read Access\n");
|
||||
|
||||
if (regs->err_code & (1 << 2))
|
||||
log(" - User-Mode Access\n");
|
||||
else
|
||||
log(" - Kernel-Mode Access\n");
|
||||
|
||||
if (regs->err_code & (1 << 3))
|
||||
log(" - Reserved Bits Set\n");
|
||||
|
||||
if (regs->err_code & (1 << 4))
|
||||
log(" - Instruction Fetch\n");
|
||||
log("\n");
|
||||
}
|
||||
|
||||
static void __panic_display_regs(registers_t *regs) {
|
||||
log("-- REGISTER DUMP --\n");
|
||||
log("RDI: %p, RSI: %p, RDX: %p, RCX: %p, R8: %p, R9: %p\n", regs->rdi,
|
||||
regs->rsi, regs->rdx, regs->rcx, regs->r8, regs->r9);
|
||||
log("RAX: %p, RBP: %p, RBX: %p, R10: %p, R11: %p, R12: %p\n", regs->rax,
|
||||
regs->rbp, regs->rbx, regs->r10, regs->r11, regs->r12);
|
||||
log("R13: %p, R14: %p, R15: %p\n", regs->r13, regs->r14, regs->r15);
|
||||
log("RIP: %p, CS: %x, SS: %x, RFLAGS: %d, INTERRUPT: %d, ERROR CODE: %d\n",
|
||||
regs->rip, regs->cs, regs->ss, regs->rflags, regs->int_no,
|
||||
regs->err_code);
|
||||
log("RSP: %p\n", regs->rsp);
|
||||
log("\n");
|
||||
|
||||
if (regs->int_no == 14) // If it's a page fault
|
||||
__panic_display_page_fault(regs);
|
||||
}
|
||||
|
||||
static void __panic_display_bt(registers_t *regs) {
|
||||
if (regs->cs == 0x43 || regs->cs == 0x3B) {
|
||||
log("The backtrace can't be dumped from a userspace process.\n");
|
||||
return; // Don't try to backtrace userspace
|
||||
}
|
||||
|
||||
log("-- BACKTRACE --\n");
|
||||
|
||||
// First print the current instruction pointer from the interrupt frame
|
||||
if (regs->rip) {
|
||||
log("* %p (current)\n", regs->rip);
|
||||
}
|
||||
|
||||
uint64_t *frame = (uint64_t*)regs->rbp;
|
||||
if (!frame || (uint64_t)frame < 0xffffffff80000000) {
|
||||
log("No further stack frames available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Frame format in x86_64:
|
||||
// [rbp] -> previous rbp
|
||||
// [rbp+8] -> return address
|
||||
int depth = 0;
|
||||
while (frame && depth < 16) { // Limit depth to avoid infinite loops
|
||||
// Validate both frame and return address pointers
|
||||
uint64_t *ret_addr_ptr = frame + 1;
|
||||
if ((uint64_t)ret_addr_ptr < 0xffffffff80000000) {
|
||||
break;
|
||||
}
|
||||
|
||||
uint64_t ret_addr = *ret_addr_ptr;
|
||||
if (ret_addr < 0xffffffff80000000 || ret_addr > 0xfffffffffffff000) {
|
||||
break;
|
||||
}
|
||||
|
||||
log("* %p\n", ret_addr);
|
||||
|
||||
uint64_t next_rbp = *frame;
|
||||
if (next_rbp < 0xffffffff80000000 || next_rbp > 0xfffffffffffff000) {
|
||||
break;
|
||||
}
|
||||
|
||||
frame = (uint64_t*)next_rbp;
|
||||
depth++;
|
||||
}
|
||||
log("\n");
|
||||
}
|
||||
|
||||
void __panic_display_ascii_art() {
|
||||
log(" _ __ _ ___ _ \n");
|
||||
log("| |/ /___ _ _ _ _ ___| | | _ \\__ _ _ _ (_)__ \n");
|
||||
log("| ' </ -_) '_| ' \\/ -_) | | _/ _` | ' \\| / _|_ _ _ \n");
|
||||
log("|_|\\_\\___|_| |_||_\\___|_| |_| \\__,_|_||_|_\\__(_|_|_)\n");
|
||||
log("\n");
|
||||
log("Due to an error that can't be recovered from, Soaplin was needed to "
|
||||
"halt the PC.\n");
|
||||
}
|
||||
|
||||
void panic(char *msg) {
|
||||
__panic_display_ascii_art();
|
||||
|
||||
log("\n");
|
||||
log("%s\n", msg);
|
||||
log("\n");
|
||||
|
||||
__panic_dump_regs();
|
||||
__panic_display_regs(&__panic_regdump);
|
||||
|
||||
log("System halted: Please restart your computer manually.\n");
|
||||
|
||||
asm("cli");
|
||||
for (;;)
|
||||
asm("hlt");
|
||||
}
|
||||
|
||||
void panic_ctx(char *msg, registers_t *regs) {
|
||||
__panic_display_ascii_art();
|
||||
|
||||
log("\n");
|
||||
log("%s\n", msg);
|
||||
log("\n");
|
||||
|
||||
if (curr_proc) {
|
||||
log("Current process: %s (PID: %d)\n", curr_proc->name, curr_proc->pid);
|
||||
log("\n");
|
||||
}
|
||||
|
||||
if (regs)
|
||||
__panic_display_regs(regs);
|
||||
else
|
||||
log("No register context provided.\n");
|
||||
|
||||
__panic_display_bt(regs);
|
||||
|
||||
log("System halted: Please restart your computer manually.\n");
|
||||
|
||||
asm("cli");
|
||||
for (;;)
|
||||
asm("hlt");
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "arch/x86_64/idt.h"
|
||||
|
||||
typedef struct __panic_backtrace {
|
||||
struct Idt_StackFrame* rbp;
|
||||
uint64_t rip;
|
||||
} __attribute__((packed)) panic_backtrace_t;
|
||||
|
||||
void panic(char *msg);
|
||||
void panic_ctx(char *msg, registers_t *regs);
|
2
kernel/src/sys/gfx/flanterm/.gitignore
vendored
2
kernel/src/sys/gfx/flanterm/.gitignore
vendored
|
@ -1,2 +0,0 @@
|
|||
*.d
|
||||
*.o
|
|
@ -1,22 +0,0 @@
|
|||
Copyright (C) 2022-2025 mintsuki and contributors.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -1,43 +0,0 @@
|
|||
# Flanterm
|
||||
|
||||
Flanterm is a fast and reasonably complete terminal emulator with support for
|
||||
multiple output backends. Included is a fast framebuffer backend.
|
||||
|
||||
### Quick usage
|
||||
|
||||
To quickly set up and use a framebuffer Flanterm instance, it is possible to
|
||||
use the `flanterm_fb_init()` function as such:
|
||||
```c
|
||||
#include <flanterm/flanterm.h>
|
||||
#include <flanterm/backends/fb.h>
|
||||
|
||||
struct flanterm_context *ft_ctx = flanterm_fb_init(
|
||||
NULL,
|
||||
NULL,
|
||||
framebuffer_ptr, width, height, pitch,
|
||||
red_mask_size, red_mask_shift,
|
||||
green_mask_size, green_mask_shift,
|
||||
blue_mask_size, blue_mask_shift,
|
||||
NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
NULL, 0, 0, 1,
|
||||
0, 0,
|
||||
0
|
||||
);
|
||||
```
|
||||
Where `framebuffer_ptr, width, height, pitch` and `{red,green,blue}_mask_{size,shift}`
|
||||
represent the corresponding info about the framebuffer to use for this given instance.
|
||||
|
||||
The meaning of the other arguments can be found in `backends/fb.h`.
|
||||
|
||||
To then print to the terminal instance, simply use the `flanterm_write()`
|
||||
function on the given instance. For example:
|
||||
```c
|
||||
#include <flanterm/flanterm.h>
|
||||
|
||||
const char msg[] = "Hello world\n";
|
||||
|
||||
flanterm_write(ft_ctx, msg, sizeof(msg));
|
||||
```
|
File diff suppressed because it is too large
Load diff
|
@ -1,69 +0,0 @@
|
|||
/* Copyright (C) 2022-2025 mintsuki and contributors.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FLANTERM_FB_H
|
||||
#define FLANTERM_FB_H 1
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "../flanterm.h"
|
||||
|
||||
#ifdef FLANTERM_IN_FLANTERM
|
||||
|
||||
#include "fb_private.h"
|
||||
|
||||
#endif
|
||||
|
||||
struct flanterm_context *flanterm_fb_init(
|
||||
/* If _malloc and _free are nulled, use the bump allocated instance (1 use
|
||||
only). */
|
||||
void *(*_malloc)(size_t size), void (*_free)(void *ptr, size_t size),
|
||||
uint32_t *framebuffer, size_t width, size_t height, size_t pitch,
|
||||
uint8_t red_mask_size, uint8_t red_mask_shift, uint8_t green_mask_size,
|
||||
uint8_t green_mask_shift, uint8_t blue_mask_size, uint8_t blue_mask_shift,
|
||||
uint32_t *canvas, /* If nulled, no canvas. */
|
||||
uint32_t *ansi_colours,
|
||||
uint32_t *ansi_bright_colours, /* If nulled, default. */
|
||||
uint32_t *default_bg, uint32_t *default_fg, /* If nulled, default. */
|
||||
uint32_t *default_bg_bright,
|
||||
uint32_t *default_fg_bright, /* If nulled, default. */
|
||||
/* If font is null, use default font and font_width and font_height ignored.
|
||||
*/
|
||||
void *font, size_t font_width, size_t font_height, size_t font_spacing,
|
||||
/* If scale_x and scale_y are 0, automatically scale font based on
|
||||
resolution. */
|
||||
size_t font_scale_x, size_t font_scale_y, size_t margin);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,122 +0,0 @@
|
|||
/* Copyright (C) 2022-2025 mintsuki and contributors.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FLANTERM_FB_PRIVATE_H
|
||||
#define FLANTERM_FB_PRIVATE_H 1
|
||||
|
||||
#ifndef FLANTERM_IN_FLANTERM
|
||||
#error "Do not use fb_private.h. Use interfaces defined in fb.h only."
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define FLANTERM_FB_FONT_GLYPHS 256
|
||||
|
||||
struct flanterm_fb_char {
|
||||
uint32_t c;
|
||||
uint32_t fg;
|
||||
uint32_t bg;
|
||||
};
|
||||
|
||||
struct flanterm_fb_queue_item {
|
||||
size_t x, y;
|
||||
struct flanterm_fb_char c;
|
||||
};
|
||||
|
||||
struct flanterm_fb_context {
|
||||
struct flanterm_context term;
|
||||
|
||||
void (*plot_char)(struct flanterm_context *ctx, struct flanterm_fb_char *c,
|
||||
size_t x, size_t y);
|
||||
|
||||
size_t font_width;
|
||||
size_t font_height;
|
||||
size_t glyph_width;
|
||||
size_t glyph_height;
|
||||
|
||||
size_t font_scale_x;
|
||||
size_t font_scale_y;
|
||||
|
||||
size_t offset_x, offset_y;
|
||||
|
||||
volatile uint32_t *framebuffer;
|
||||
size_t pitch;
|
||||
size_t width;
|
||||
size_t height;
|
||||
size_t bpp;
|
||||
|
||||
uint8_t red_mask_size, red_mask_shift;
|
||||
uint8_t green_mask_size, green_mask_shift;
|
||||
uint8_t blue_mask_size, blue_mask_shift;
|
||||
|
||||
size_t font_bits_size;
|
||||
uint8_t *font_bits;
|
||||
size_t font_bool_size;
|
||||
bool *font_bool;
|
||||
|
||||
uint32_t ansi_colours[8];
|
||||
uint32_t ansi_bright_colours[8];
|
||||
uint32_t default_fg, default_bg;
|
||||
uint32_t default_fg_bright, default_bg_bright;
|
||||
|
||||
size_t canvas_size;
|
||||
uint32_t *canvas;
|
||||
|
||||
size_t grid_size;
|
||||
size_t queue_size;
|
||||
size_t map_size;
|
||||
|
||||
struct flanterm_fb_char *grid;
|
||||
|
||||
struct flanterm_fb_queue_item *queue;
|
||||
size_t queue_i;
|
||||
|
||||
struct flanterm_fb_queue_item **map;
|
||||
|
||||
uint32_t text_fg;
|
||||
uint32_t text_bg;
|
||||
size_t cursor_x;
|
||||
size_t cursor_y;
|
||||
|
||||
uint32_t saved_state_text_fg;
|
||||
uint32_t saved_state_text_bg;
|
||||
size_t saved_state_cursor_x;
|
||||
size_t saved_state_cursor_y;
|
||||
|
||||
size_t old_cursor_x;
|
||||
size_t old_cursor_y;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load diff
|
@ -1,85 +0,0 @@
|
|||
/* Copyright (C) 2022-2025 mintsuki and contributors.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FLANTERM_H
|
||||
#define FLANTERM_H 1
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define FLANTERM_CB_DEC 10
|
||||
#define FLANTERM_CB_BELL 20
|
||||
#define FLANTERM_CB_PRIVATE_ID 30
|
||||
#define FLANTERM_CB_STATUS_REPORT 40
|
||||
#define FLANTERM_CB_POS_REPORT 50
|
||||
#define FLANTERM_CB_KBD_LEDS 60
|
||||
#define FLANTERM_CB_MODE 70
|
||||
#define FLANTERM_CB_LINUX 80
|
||||
|
||||
#define FLANTERM_OOB_OUTPUT_OCRNL (1 << 0)
|
||||
#define FLANTERM_OOB_OUTPUT_OFDEL (1 << 1)
|
||||
#define FLANTERM_OOB_OUTPUT_OFILL (1 << 2)
|
||||
#define FLANTERM_OOB_OUTPUT_OLCUC (1 << 3)
|
||||
#define FLANTERM_OOB_OUTPUT_ONLCR (1 << 4)
|
||||
#define FLANTERM_OOB_OUTPUT_ONLRET (1 << 5)
|
||||
#define FLANTERM_OOB_OUTPUT_ONOCR (1 << 6)
|
||||
#define FLANTERM_OOB_OUTPUT_OPOST (1 << 7)
|
||||
|
||||
#ifdef FLANTERM_IN_FLANTERM
|
||||
|
||||
#include "flanterm_private.h"
|
||||
|
||||
#else
|
||||
|
||||
struct flanterm_context;
|
||||
|
||||
#endif
|
||||
|
||||
void flanterm_write(struct flanterm_context *ctx, const char *buf,
|
||||
size_t count);
|
||||
void flanterm_flush(struct flanterm_context *ctx);
|
||||
void flanterm_full_refresh(struct flanterm_context *ctx);
|
||||
void flanterm_deinit(struct flanterm_context *ctx,
|
||||
void (*_free)(void *ptr, size_t size));
|
||||
|
||||
void flanterm_get_dimensions(struct flanterm_context *ctx, size_t *cols,
|
||||
size_t *rows);
|
||||
void flanterm_set_autoflush(struct flanterm_context *ctx, bool state);
|
||||
void flanterm_set_callback(struct flanterm_context *ctx,
|
||||
void (*callback)(struct flanterm_context *, uint64_t,
|
||||
uint64_t, uint64_t, uint64_t));
|
||||
uint64_t flanterm_get_oob_output(struct flanterm_context *ctx);
|
||||
void flanterm_set_oob_output(struct flanterm_context *ctx, uint64_t oob_output);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,125 +0,0 @@
|
|||
/* Copyright (C) 2022-2025 mintsuki and contributors.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FLANTERM_PRIVATE_H
|
||||
#define FLANTERM_PRIVATE_H 1
|
||||
|
||||
#ifndef FLANTERM_IN_FLANTERM
|
||||
#error \
|
||||
"Do not use flanterm_private.h. Use interfaces defined in flanterm.h only."
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define FLANTERM_MAX_ESC_VALUES 16
|
||||
|
||||
struct flanterm_context {
|
||||
/* internal use */
|
||||
|
||||
size_t tab_size;
|
||||
bool autoflush;
|
||||
bool cursor_enabled;
|
||||
bool scroll_enabled;
|
||||
bool control_sequence;
|
||||
bool escape;
|
||||
bool osc;
|
||||
bool osc_escape;
|
||||
bool rrr;
|
||||
bool discard_next;
|
||||
bool bold;
|
||||
bool bg_bold;
|
||||
bool reverse_video;
|
||||
bool dec_private;
|
||||
bool insert_mode;
|
||||
uint64_t code_point;
|
||||
size_t unicode_remaining;
|
||||
uint8_t g_select;
|
||||
uint8_t charsets[2];
|
||||
size_t current_charset;
|
||||
size_t escape_offset;
|
||||
size_t esc_values_i;
|
||||
size_t saved_cursor_x;
|
||||
size_t saved_cursor_y;
|
||||
size_t current_primary;
|
||||
size_t current_bg;
|
||||
size_t scroll_top_margin;
|
||||
size_t scroll_bottom_margin;
|
||||
uint32_t esc_values[FLANTERM_MAX_ESC_VALUES];
|
||||
uint64_t oob_output;
|
||||
bool saved_state_bold;
|
||||
bool saved_state_bg_bold;
|
||||
bool saved_state_reverse_video;
|
||||
size_t saved_state_current_charset;
|
||||
size_t saved_state_current_primary;
|
||||
size_t saved_state_current_bg;
|
||||
|
||||
/* to be set by backend */
|
||||
|
||||
size_t rows, cols;
|
||||
|
||||
void (*raw_putchar)(struct flanterm_context *, uint8_t c);
|
||||
void (*clear)(struct flanterm_context *, bool move);
|
||||
void (*set_cursor_pos)(struct flanterm_context *, size_t x, size_t y);
|
||||
void (*get_cursor_pos)(struct flanterm_context *, size_t *x, size_t *y);
|
||||
void (*set_text_fg)(struct flanterm_context *, size_t fg);
|
||||
void (*set_text_bg)(struct flanterm_context *, size_t bg);
|
||||
void (*set_text_fg_bright)(struct flanterm_context *, size_t fg);
|
||||
void (*set_text_bg_bright)(struct flanterm_context *, size_t bg);
|
||||
void (*set_text_fg_rgb)(struct flanterm_context *, uint32_t fg);
|
||||
void (*set_text_bg_rgb)(struct flanterm_context *, uint32_t bg);
|
||||
void (*set_text_fg_default)(struct flanterm_context *);
|
||||
void (*set_text_bg_default)(struct flanterm_context *);
|
||||
void (*set_text_fg_default_bright)(struct flanterm_context *);
|
||||
void (*set_text_bg_default_bright)(struct flanterm_context *);
|
||||
void (*move_character)(struct flanterm_context *, size_t new_x, size_t new_y,
|
||||
size_t old_x, size_t old_y);
|
||||
void (*scroll)(struct flanterm_context *);
|
||||
void (*revscroll)(struct flanterm_context *);
|
||||
void (*swap_palette)(struct flanterm_context *);
|
||||
void (*save_state)(struct flanterm_context *);
|
||||
void (*restore_state)(struct flanterm_context *);
|
||||
void (*double_buffer_flush)(struct flanterm_context *);
|
||||
void (*full_refresh)(struct flanterm_context *);
|
||||
void (*deinit)(struct flanterm_context *, void (*)(void *, size_t));
|
||||
|
||||
/* to be set by client */
|
||||
|
||||
void (*callback)(struct flanterm_context *, uint64_t, uint64_t, uint64_t,
|
||||
uint64_t);
|
||||
};
|
||||
|
||||
void flanterm_context_reinit(struct flanterm_context *ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,46 +0,0 @@
|
|||
#include "arch/x86_64/io.h"
|
||||
#include "sys/gfx/flanterm/flanterm.h"
|
||||
#include <lib/spinlock.h>
|
||||
#include <lib/string.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/printf.h>
|
||||
|
||||
extern struct flanterm_context *ft_ctx;
|
||||
|
||||
static spinlock_t log_lock = {0};
|
||||
|
||||
void log(char *format, ...) {
|
||||
// TODO: replace this call with a call to printf() when the RTC is
|
||||
// implemented.
|
||||
|
||||
// spinlock_acquire(&log_lock);
|
||||
|
||||
char *date = "1970-01-01 00:00:00 | ";
|
||||
if (ft_ctx)
|
||||
flanterm_write(ft_ctx, date, strlen(date));
|
||||
|
||||
char buf[2048];
|
||||
va_list l;
|
||||
va_start(l, format);
|
||||
npf_vsnprintf(buf, 2048, format, l);
|
||||
va_end(l);
|
||||
|
||||
if (ft_ctx)
|
||||
flanterm_write(ft_ctx, buf, strlen(buf));
|
||||
|
||||
for (int i = 0;; i++) {
|
||||
if (date[i] == '\0')
|
||||
break;
|
||||
|
||||
outb(0xE9, date[i]);
|
||||
}
|
||||
|
||||
for (int i = 0;; i++) {
|
||||
if (buf[i] == '\0')
|
||||
break;
|
||||
|
||||
outb(0xE9, buf[i]);
|
||||
}
|
||||
|
||||
// spinlock_release(&log_lock);
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
void log(char *format, ...);
|
|
@ -1,31 +0,0 @@
|
|||
// Copyright (C) 2024 Sipaa Projects
|
||||
// This code is part of the Soaplin kernel and is licensed under the terms of
|
||||
// the MIT License.
|
||||
#include "sys/gfx/flanterm/flanterm.h"
|
||||
#include <lib/string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#define NANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS 1
|
||||
#define NANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS 1
|
||||
#define NANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS 1
|
||||
#define NANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS 0
|
||||
#define NANOPRINTF_USE_BINARY_FORMAT_SPECIFIERS 1
|
||||
#define NANOPRINTF_USE_WRITEBACK_FORMAT_SPECIFIERS 0
|
||||
|
||||
// Compile nanoprintf in this translation unit.
|
||||
#define NANOPRINTF_IMPLEMENTATION
|
||||
#include <sys/printf.h>
|
||||
|
||||
extern struct flanterm_context *ft_ctx;
|
||||
|
||||
void printf(char *format, ...) {
|
||||
char buf[2048];
|
||||
va_list lst;
|
||||
va_start(lst, format);
|
||||
npf_vsnprintf(buf, 2048, format, lst);
|
||||
va_end(lst);
|
||||
|
||||
// rt_print(buf);
|
||||
if (ft_ctx)
|
||||
flanterm_write(ft_ctx, buf, strlen(buf));
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,64 +0,0 @@
|
|||
#include "sched/sched.h"
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/log.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
static syscall syscall_table[1024];
|
||||
|
||||
static int syscall_initialized = 0;
|
||||
|
||||
extern void __x86_64_syscall_init();
|
||||
|
||||
// Stub function for undefined syscalls.
|
||||
static uint64_t __syscall_undefined() { return 0; }
|
||||
|
||||
void syscall_handle(registers_t *regs) {
|
||||
if (regs->rax >= 1024) {
|
||||
log("syscall - syscall_handle was called with rax better than what Soaplin "
|
||||
"supports (1024). did you forget to set rax?\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (curr_proc == NULL || curr_proc->regs.cs != 0x43) {
|
||||
log("syscall - syscall_handle was called by the kernel. is this wanted?\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (syscall_table[regs->rax] == (syscall)__syscall_undefined) {
|
||||
log("syscall - syscall_handle was called with an undefined system call. "
|
||||
"(%d)\n",
|
||||
regs->rax);
|
||||
return;
|
||||
}
|
||||
|
||||
log("Hello!\n");
|
||||
|
||||
regs->rax = syscall_table[regs->rax](regs->rdi, regs->rsi, regs->rdx,
|
||||
regs->rcx, regs->r8, regs->r9);
|
||||
return;
|
||||
}
|
||||
|
||||
void syscall_register(int id, syscall handler) {
|
||||
if (syscall_table[id] != (syscall)__syscall_undefined) {
|
||||
log("syscall - warning: syscall_register has been called to try replacing "
|
||||
"an existing syscall.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
syscall_table[id] = handler;
|
||||
log("syscall - System call %d has been set to %p\n", id, handler);
|
||||
}
|
||||
|
||||
extern void syscall_write(int fd, const char *buf, size_t count);
|
||||
extern void syscall_exit(int exit_code);
|
||||
|
||||
void syscall_init() {
|
||||
for (int i = 0; i < 1024; i++)
|
||||
syscall_table[i] = (syscall)__syscall_undefined;
|
||||
|
||||
syscall_register(1, (syscall)syscall_write);
|
||||
syscall_register(60, (syscall)syscall_exit);
|
||||
|
||||
__x86_64_syscall_init();
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "arch/x86_64/idt.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/// A function that defines a system call.
|
||||
/// NOTE: Arguments are defined as uint64_t, but you can simply put your own
|
||||
/// type, and then cast your function to syscall.
|
||||
typedef uint64_t (*syscall)(uint64_t rdi, uint64_t rsi, uint64_t rdx,
|
||||
uint64_t rcx, uint64_t r8, uint64_t r9);
|
||||
|
||||
/// Registers a system call.
|
||||
/// NOTE: an existing system call cannot be replaced by another.
|
||||
void syscall_register(int id, syscall handler);
|
||||
|
||||
/// Called by the interupt handler, or the "syscall" instruction handler
|
||||
void syscall_handle(registers_t *);
|
||||
|
||||
/// Initialize the system calls.
|
||||
void syscall_init();
|
|
@ -1,11 +0,0 @@
|
|||
#include <stddef.h>
|
||||
#include <sys/printf.h>
|
||||
|
||||
int syscall_write(int fd, const char *buf, size_t count) {
|
||||
if (fd == 1) {
|
||||
printf("%s", buf); // Prevent the buffer from being formatted.
|
||||
return count;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
#include <sched/sched.h>
|
||||
|
||||
int syscall_exit(int exit_code) {
|
||||
sched_exit(exit_code);
|
||||
return 0;
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
typedef struct __uname {
|
||||
char sysname[128]; /* Operating system name */
|
||||
char nodename[128]; /* Name within communications network
|
||||
to which the node is attached, if any */
|
||||
char release[128]; /* Operating system release */
|
||||
char version[128]; /* Operating system version */
|
||||
char machine[128]; /* Hardware type identifier */
|
||||
#ifdef _GNU_SOURCE
|
||||
char domainname[]; /* NIS or YP domain name */
|
||||
#endif
|
||||
} uname_t;
|
Loading…
Add table
Add a link
Reference in a new issue