Compare commits

..

164 Commits

Author SHA1 Message Date
3996f71316 Initialize devices before storedev_init() 2025-10-08 19:34:15 +02:00
ed704e2cef dev Utility for working with devices 2025-10-08 19:32:57 +02:00
0ac80c76b0 devctl commands for getting device info 2025-10-08 19:32:37 +02:00
3830af45c8 tb Reset any colors after running an app 2025-10-08 19:04:03 +02:00
49cebd277c back to old default colors 2025-10-08 19:03:30 +02:00
a1ec132d09 PS2KB fix mapping KB_HOME 2025-10-06 23:07:34 +02:00
00b779fb91 ulib dlinklist, string_memmove() 2025-10-05 22:44:59 +02:00
a513909189 tb Fix handling CTRL+S 2025-10-05 20:05:09 +02:00
cdfb1e39c0 Move serial driver code to kernel/dev 2025-10-05 19:50:42 +02:00
e9838d530f Rearchitecture PS2KB driver using event buffers 2025-10-05 19:48:15 +02:00
247ef1bbd1 Add fbdev for getting framebuffer information 2025-10-05 15:56:16 +02:00
933083ffeb HAL clean up, remove uACPI 2025-10-05 00:13:38 +02:00
70d6931e3b Use shared macros for dev function IDs 2025-10-04 21:34:48 +02:00
acbf051dbc New rewritten serial driver + dev interface 2025-10-04 21:31:45 +02:00
0117080b61 Remove bcast pipes 2025-10-04 14:43:24 +02:00
ef9393e694 fs Add tree subcommand 2025-10-04 12:02:03 +02:00
082cb66c7e fs Fix off-by-one error - parse up to argslen()-2 args 2025-10-04 01:41:55 +02:00
b624214433 fs Add mkd subcommand for creating directories 2025-10-04 01:38:59 +02:00
26517e8e28 ioctl() IOCTL_MKDIR command, vfs_mkdir() 2025-10-04 01:38:41 +02:00
b72f3ee00d fix schedrelease() syscall 2025-10-04 01:12:03 +02:00
071f414f07 legal Add licenses for used code and libraries 2025-10-03 23:57:15 +02:00
04a4b1395c Store devices as a hashtable 2025-10-03 23:47:58 +02:00
18d646ff8b Rewrite the kernel hashtable struct 2025-10-03 23:22:22 +02:00
20b4545cae Fix minor warnings 2025-10-03 22:41:38 +02:00
fc47ff581e littlefs_fetchdirent() fix missing return statement 2025-10-03 22:34:32 +02:00
08793178f1 share Make errors.h assembler friendly too 2025-10-03 22:32:50 +02:00
3c1c63e970 share Make headers assembler friendly 2025-10-03 22:31:22 +02:00
57ba9ff126 Store device structs in a dynamic list 2025-10-03 22:25:16 +02:00
c0178a1405 fs mkf subcommand 2025-10-03 22:05:28 +02:00
dc8df7fade fs Fetch cleanup 2025-10-03 20:03:03 +02:00
c30d2d2ea6 Remove conversions between VfsStat struct and IoctlStat struct 2025-10-03 19:55:14 +02:00
443cf0e4ff Fetching directory entries 2025-10-03 19:50:10 +02:00
de20efa0f3 vfs Rewrite IOCTL_STAT so that it doesnt require an already open handle 2025-10-03 01:00:09 +02:00
2cfd3ee2fa ioctl() IOCTL_STAT use path instead of already open io handle 2025-10-02 23:57:38 +02:00
c345e2284e pctl Remove unnecessary header files 2025-10-02 22:33:08 +02:00
bc2b115cb3 fs Fetch file contents 2025-10-02 22:29:20 +02:00
91d648ade4 Remove % prefix for builtin commands 2025-10-01 22:50:27 +02:00
0232849994 tb Allow empty lines 2025-10-01 22:30:34 +02:00
73effcd52a tb Implement a string stack 2025-10-01 21:26:22 +02:00
62cf07afc7 ulib uprintf to pipe not termdev, ulib Add stringbuffer and linearlist, tb Capture subshell output 2025-10-01 20:08:44 +02:00
0e4a35eb86 ipcpipe Add pipe ownership guards 2025-10-01 19:57:09 +02:00
fa8a774115 tb Hex/byte escapes 2025-09-29 23:18:27 +02:00
39981fdbbf tb String escaping 2025-09-29 23:12:19 +02:00
10711f7fb3 tb Fix string tokenization bug (bad classification) 2025-09-29 22:58:40 +02:00
0fb63b4695 pctl Add kill command 2025-09-29 21:43:28 +02:00
46e52c8d48 tb %PID builtin command 2025-09-29 21:37:48 +02:00
4e8afae5fb all procs are user procs 2025-09-29 21:32:07 +02:00
20a89502c0 Remove kernel procs 2025-09-29 21:27:46 +02:00
8db585f581 new terminal theme 2025-09-28 23:51:17 +02:00
e03e950879 tb Fix alias expansion 2025-09-28 23:27:04 +02:00
2b93d6d184 tb input from ps2kb 2025-09-28 23:26:07 +02:00
d7562b98c1 Rewrite PS2KB using the new devctl interface 2025-09-28 23:25:43 +02:00
f5f44da5f6 tb finally works 2025-09-28 22:37:03 +02:00
1fd6c4e221 Get rid of writefmt functions 2025-09-28 20:10:41 +02:00
96ce9233ff umalloc fixes 2025-09-28 19:55:37 +02:00
c07a2c957b umalloc small bug fixes 2025-09-27 22:58:22 +02:00
8d081bedb0 Ditch dlmalloc in favour of custom umalloc 2025-09-27 22:32:38 +02:00
3b1bb9d531 WIP 2 2025-09-27 15:16:26 +02:00
5af7c5276a kernel Use canonical addresses for proc mmap base and stack top 2025-09-22 16:19:16 +02:00
5c7fb3e1cf Request process arguments differently, mmap-style dlmalloc port, new linklist utils 2025-09-21 22:51:38 +02:00
397379bca3 Rework requesting process arguments 2025-09-21 22:50:39 +02:00
475f77d30f Rewrite LL_* (link list) macros 2025-09-21 18:32:22 +02:00
d5c2df7365 ulib dlmalloc Add page-aligned increment 2025-09-21 13:26:33 +02:00
83a28bd25b Clean up HAL VMM 2025-09-21 13:26:05 +02:00
3f2c35f4cb Fix dlmalloc pointer port _last ptr alignment 2025-09-20 20:48:08 +02:00
8a9687c007 ulib Make syscall() safe (add "cc" to clobbers) 2025-09-20 20:22:53 +02:00
d50bdd0051 Use custom GCC toolchain 2025-09-20 20:07:39 +02:00
0c65bd9891 Rewrite ps2kbproc, rbuf (kernel ring buffer) and pipe read/write, Change to -O0 in kernel code 2025-09-20 16:50:40 +02:00
222e846881 tb Allow the user to kill current process in interactive mode (Ctrl+S) 2025-09-20 12:41:54 +02:00
a24b1fc677 diagdummy Simple dummy app for diagnostics and debugging 2025-09-20 12:25:02 +02:00
a8005917eb ulib Add quit() utility 2025-09-20 12:20:26 +02:00
97bc0aa05b tb Use % for builtin cmd prefix 2025-09-20 11:38:54 +02:00
6cd4c73438 tb Allow for only one consequent alias expansion 2025-09-20 11:13:48 +02:00
9694d1a5a0 Use unified header file ulib.h 2025-09-20 10:54:31 +02:00
e245ecca3c ulib Remove machine/limits.h std/limits.h std/stdlib.h 2025-09-20 10:47:04 +02:00
3f0231be3f tb Don't schedrelease() when reading in-pipe 2025-09-20 10:38:36 +02:00
a1b3d4efa4 TODO figure out why schedrelease() messes with terminal proc's ring buffer 2025-09-20 01:19:20 +02:00
8269e097d6 spinlock only restore RFLAGS IF flag 2025-09-20 00:55:18 +02:00
dcc68154b2 Make syscalls accept their interrupt frame, remove useless intr_eoi() param 2025-09-20 00:28:28 +02:00
81dc694a23 schedrelease() don't schedule if current interrupt frame is NULL 2025-09-19 23:48:30 +02:00
5b6408b06b tb fix call to schedrelease() 2025-09-19 23:47:55 +02:00
b7ad1e0633 tb Spin efficiently with new schedrelease() syscall 2025-09-19 23:41:24 +02:00
1b5701a659 schedrelease() syscall for more efficient spinning 2025-09-19 23:38:08 +02:00
e01d8d5e1a pctl ls List procs by PID 2025-09-19 23:06:37 +02:00
44b5aa305c ulib Add ARG_INT type to argument parser 2025-09-19 23:06:08 +02:00
c94ef4d990 pctl List procs by name 2025-09-19 22:50:34 +02:00
2c0d50a401 pctl Display memory usage and process state 2025-09-19 22:38:39 +02:00
1af0d1f5bc Use uint8_t for keyboard chars 2025-09-19 21:00:33 +02:00
504bdbd4ba pctl More compact output of ls subcmd 2025-09-19 20:45:49 +02:00
c364dca5e5 Change terminal font and colors 2025-09-19 20:40:17 +02:00
8d0f80f821 tb Clear screen shortcut 2025-09-19 20:07:17 +02:00
4cedfda19b Fix some keyboard keypressed still being missed 2025-09-19 20:03:36 +02:00
40b7dcedf8 tb Command aliases, preloading scripts 2025-09-19 19:55:35 +02:00
24a90b24e8 tb Handle keyboard inside of the shell interactive mode 2025-09-19 19:09:54 +02:00
d7153bf0b6 pctl display bad subcommand 2025-09-19 18:24:48 +02:00
ad56890ee9 Adopt pipe handle inheritance 2025-09-19 18:12:36 +02:00
2d7ceb4b43 Make subprocess inherit parent's pipe handles 2025-09-18 23:31:16 +02:00
4c17f26915 add PCTL_DELETE for removing pipes 2025-09-18 22:43:24 +02:00
024a5b2e21 ps2kb intr fix missed key presses by sending early EOI 2025-09-18 11:45:56 +02:00
9e9d2c5190 pctl format output as a table 2025-09-18 11:22:09 +02:00
e5e707eb54 tb running cmds in interactive mode 2025-09-18 00:57:24 +02:00
b3894f1600 Return an error code when a pipe is already present in a slot 2025-09-18 00:54:53 +02:00
b0e543177b PS2KB driver fix right shift key 2025-09-18 00:48:31 +02:00
ba1c0eedbd tb implement command logging 2025-09-17 22:07:58 +02:00
ac1cc172f7 ulib parse boolean arguments 2025-09-17 22:07:42 +02:00
6a8af7727e PCTL ignore build artifacts 2025-09-17 21:49:04 +02:00
91e65bb35a Resolve hisenbugs regarding GCC and -Os 2025-09-17 21:48:16 +02:00
0a5523f234 WIP 2025-09-15 22:35:15 +02:00
ce63020b34 ulib dlmalloc, more eco friendly sbrk() 2025-09-15 00:33:46 +02:00
40ccb7d476 TB print hello world 2025-09-14 23:31:14 +02:00
062e98d714 Fix poor VMM locking leading to subtle race conditions 2025-09-14 23:11:24 +02:00
69e23a9ca3 ioctl() IOCTL_STAT command 2025-09-14 19:30:20 +02:00
26ff717b50 Fix dlmalloc horror bug - mman_map overwrites application code 2025-09-14 19:07:00 +02:00
e6891b39cc Parsing commandline arguments 2025-09-13 15:43:31 +02:00
dc3d80d707 Handle process arguments 2025-09-10 23:25:03 +02:00
2f9f4d9397 Userspace dlmalloc port, supporting syscalls mman_map()/mman_unmap() 2025-09-10 21:52:01 +02:00
91c493c818 processctl() PCTL_SPAWN cmd, scheduler embryo state, redirected pipes 2025-09-10 01:11:22 +02:00
c4c26e0e19 Fix ps2 keyboard handling 2025-09-09 21:43:05 +02:00
3b42abc027 Temporary mountpoint (temp) 2025-09-09 19:38:39 +02:00
71be9c5fb3 Use uprintf instead of debugprint 2025-09-09 18:21:55 +02:00
4ade9ad1a0 Move all syscalls into one file 2025-09-09 18:18:55 +02:00
ac195acd2f Rework the ioctl() syscall, clean up arguments 2025-09-09 18:12:33 +02:00
1029db6342 Rename event pipes to broadcast pipes 2025-09-09 17:52:19 +02:00
ab224eda8e Add special event pipes, rework ps2kb process 2025-09-08 22:12:50 +02:00
94dd38d010 Set bitmap block size to page size 2025-09-07 22:56:00 +02:00
a9ac962051 Move dlmalloc outside of kernel tree 2025-09-07 22:48:05 +02:00
e71361dcca Nice userspace wrappers for ps2kb driver 2025-09-07 22:24:34 +02:00
659f98910d Terminal lock 2025-09-07 22:23:41 +02:00
80a788617e Serial comm kernel process 2025-09-07 21:44:46 +02:00
9644ad0b4e Handle ps2 keyboard via special process 2025-09-07 20:53:36 +02:00
4f3053bc8e Handle ps2 keyboard, no APIC for now 2025-09-07 14:25:23 +02:00
0cbf308d95 Implement a kernel process 2025-09-06 17:13:52 +02:00
b04ebd9c71 Add ANSI escape sequences library to ulib 2025-09-06 14:55:09 +02:00
97bfa178d1 Printf in userspace 2025-09-06 12:14:54 +02:00
cd0e262e56 Simple IPC with pipes 2025-09-06 11:47:01 +02:00
643d692259 Remove PID_SELF_MAGIC constant 2025-09-06 09:50:04 +02:00
3b18f56376 Fix holding spinlocks for too long 2025-09-06 09:35:31 +02:00
b89882e1cf VFS object auto cleanup 2025-09-06 09:31:05 +02:00
c31c00e8cd Nice wrappers around ioctl() syscall 2025-09-05 23:00:57 +02:00
d399922de6 rm libulib.a 2025-09-05 21:12:13 +02:00
fb5e88a175 Simple file IO with the ioctl syscall 2025-09-05 19:56:27 +02:00
f42c4b7e44 Rework shared headers 2025-09-05 17:08:40 +02:00
708c53c64d Move to new processctl syscall, share common kernel and ulib headers 2025-09-05 15:44:57 +02:00
ca92a0e6a8 Remove VFS object reference counting 2025-09-05 15:10:25 +02:00
90266f044b C userspace programs 2025-09-04 23:20:30 +02:00
afa4d383e0 Redesign the VFS 2025-09-03 17:32:08 +02:00
8a12f23b69 Implement syscalls, hello world from userspace 2025-09-02 23:51:14 +02:00
920de10025 Move vmm fully into hal 2025-09-02 07:51:02 +02:00
0fb3a1ca75 Fix makefiles after source grabber changes 2025-09-02 07:42:15 +02:00
ddca5f687e Fix kernel makefile formatting 2025-09-02 00:13:28 +02:00
4e3c386942 Clean up makefiles with a source grabber function 2025-09-02 00:10:07 +02:00
2015e0e0aa Hello user process 2025-09-01 23:22:47 +02:00
13ab117b1b Timed waiting with hal_wait() 2025-08-31 00:21:17 +02:00
73f27f730b Clean up Makefile, move stuff into separate scripts 2025-08-30 23:52:53 +02:00
0273330cf4 Kernel processes / multitasking 2025-08-30 23:47:25 +02:00
60a530b900 hal x86_64 vmm minor fixes in mapping/unmapping 2025-08-30 13:41:47 +02:00
7a52f2f051 Rework x86_64 paging and vmm 2025-08-30 00:31:20 +02:00
8cf1bde879 Make spinlock disable interrupts 2025-08-22 12:42:04 +02:00
182c6e2956 Implement PIT interrupts 2025-08-22 12:37:48 +02:00
9d8849a425 Init IOAPIC nad LAPICs 2025-08-21 00:47:58 +02:00
3f6df79885 Implement interrupts 2025-08-19 22:51:33 +02:00
92ccd189e7 Integrate uACPI 2025-08-17 18:37:57 +02:00
069870cd0d Use latest limine 2025-08-16 21:42:38 +02:00
54354e4f54 Clean up bootinfo 2025-08-16 21:35:03 +02:00
237 changed files with 17582 additions and 9108 deletions

1
.gdbinit Normal file
View File

@ -0,0 +1 @@
target remote :1234

1
.gitignore vendored
View File

@ -1,5 +1,4 @@
/limine /limine
/iso_root /iso_root
/base_root
*.iso *.iso
*.img *.img

View File

@ -1,49 +1,47 @@
.PHONY: all clean prepare cleanall iso base .PHONY: clean prepare cleanall iso base kernel user test
all: ARCH ?= x86_64
make -C kernel all
kernel:
make -C kernel ARCH=$(ARCH) ROOT=$(PWD) all
user:
make -C user ARCH=$(ARCH) ROOT=$(PWD) all
ulib:
make -C ulib ARCH=$(ARCH) ROOT=$(PWD) all
prepare: prepare:
if [ ! -d limine ]; then \ if [ ! -d limine ]; then \
mkdir limine; \ git clone https://github.com/limine-bootloader/limine.git --branch=v9.x-binary --depth=1; \
cd limine; \ cd limine; \
git init; \
git remote add origin https://github.com/limine-bootloader/limine.git; \
git fetch origin 9246bb78f446962aae5b0a291db4be32f9866ba6; \
git reset --hard FETCH_HEAD; \
make; \ make; \
fi fi
if [ ! -d toolchain/binutils-gdb ]; then \
cd toolchain; \
git clone git://sourceware.org/git/binutils-gdb.git --depth=1; \
$(PWD)/scripts/build-binutils-gdb.sh; \
cd ..; \
fi
if [ ! -d toolchain/gcc ]; then \
cd toolchain; \
git clone https://gcc.gnu.org/git/gcc.git --depth=1; \
$(PWD)/scripts/build-gcc.sh; \
cd ..; \
fi
cleanall: cleanall:
make clean make clean
rm -rf limine rm -rf limine
rm -rf littlefs-fuse
clean: clean:
make -C kernel clean make -C kernel ARCH=$(ARCH) ROOT=$(PWD) clean
make -C user ARCH=$(ARCH) ROOT=$(PWD) clean
make -C ulib ARCH=$(ARCH) ROOT=$(PWD) clean
rm -f mop2.iso base.img rm -f mop2.iso base.img
base: base:
@rm -f base.img ./scripts/mkbaseimg.sh
@rm -rf base_root
@mkdir -p base_root
mklittlefs -c base_root -b 4096 -s $$((1<<20)) base.img
iso: iso:
@rm -rf iso_root ./scripts/mkiso.sh
@mkdir -p iso_root/boot
@cp -v kernel/mop2 iso_root/boot
@cp -v base.img iso_root
@mkdir -p iso_root/boot/limine
@cp -v limine.conf limine/limine-bios.sys limine/limine-bios-cd.bin \
limine/limine-uefi-cd.bin iso_root/boot/limine
@mkdir -p iso_root/EFI/BOOT
@cp -v limine/BOOTX64.EFI iso_root/EFI/BOOT
@cp -v limine/BOOTIA32.EFI iso_root/EFI/BOOT
@xorriso -as mkisofs -R -r -J -b boot/limine/limine-bios-cd.bin \
-no-emul-boot -boot-load-size 4 -boot-info-table -hfsplus \
-apm-block-size 2048 --efi-boot boot/limine/limine-uefi-cd.bin \
-efi-boot-part --efi-boot-image --protective-msdos-label \
iso_root -o mop2.iso
@./limine/limine bios-install mop2.iso

3
base/bin/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*
!.gitignore
!.gitkeep

0
base/bin/.gitkeep Normal file
View File

3
base/scripts/init.tb Normal file
View File

@ -0,0 +1,3 @@
print 'this is an init script!'
base:/bin/pctl ls
base:/bin/tb -m interactive -preload base:/scripts/rc.tb

4
base/scripts/rc.tb Normal file
View File

@ -0,0 +1,4 @@
mkalias pctl base:/bin/pctl
mkalias tb base:/bin/tb
mkalias fs base:/bin/fs
mkalias dev base:/bin/dev

View File

@ -1,3 +0,0 @@
#!/bin/sh
make -B && make base && make iso

6292
dlmalloc/malloc.c Normal file

File diff suppressed because it is too large Load Diff

12
dlmalloc/malloc.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef MALLOC_MALLOC_H_
#define MALLOC_MALLOC_H_
#include <stddef.h>
void *dlmalloc(size_t);
void dlfree(void *);
void *dlcalloc(size_t, size_t);
void *dlrealloc(void *, size_t);
void *dlrealloc_in_place(void *, size_t);
#endif // MALLOC_MALLOC_H_

View File

@ -1,19 +1,23 @@
include $(ROOT)/mk/grabsrc.mk
.PHONY: all clean .PHONY: all clean
ARCH ?= x86_64
PUTCHAR_ ?= fb PUTCHAR_ ?= fb
CFLAGS := -ffreestanding -Wall -Wextra -g -fcommon -nostdinc CFLAGS := -ffreestanding -Wall -Wextra -g -fcommon -nostdinc
CFLAGS += -I. \ CFLAGS += -I. \
-I../limine \ -I$(ROOT)/limine \
-I./std/include \ -I$(ROOT)/std/include \
-I./std \
-I./flanterm/src \ -I./flanterm/src \
-I$(ROOT)/share \
-DPRINTF_INCLUDE_CONFIG_H=1 \ -DPRINTF_INCLUDE_CONFIG_H=1 \
-DLFS_NO_ASSERT \ -DLFS_NO_ASSERT \
-DLFS_NO_DEBUG \ -DLFS_NO_DEBUG \
-DLFS_NO_WARN \ -DLFS_NO_WARN \
-DLFS_NO_ERROR -DLFS_NO_ERROR \
-DUACPI_BAREBONES_MODE
ifeq ($(PUTCHAR_),fb) ifeq ($(PUTCHAR_),fb)
CFLAGS += -DPUTCHAR_=PUTCHAR_FB CFLAGS += -DPUTCHAR_=PUTCHAR_FB
@ -24,36 +28,42 @@ endif
include arch/$(ARCH)/$(ARCH).mk include arch/$(ARCH)/$(ARCH).mk
include extconf/extra.mk include extconf/extra.mk
LDFLAGS := -nostdlib -static -T arch/$(ARCH)/link.ld $(shell $(CC) -print-libgcc-file-name) LDFLAGS += -nostdlib -static -T arch/$(ARCH)/link.ld $(shell $(CC) -print-libgcc-file-name)
SRCFILES := $(wildcard *.c) \ SRCFILES :=
$(wildcard printf/*.c) \
$(wildcard bitmap/*.c) \ SRCFILES += $(call GRABSRC, \
$(wildcard pmm/*.c) \ . \
$(wildcard bootinfo/*.c) \ printf \
$(wildcard spinlock/*.c) \ bitmap \
$(wildcard term/*.c) \ pmm \
$(wildcard vmm/*.c) \ bootinfo \
$(wildcard dlmalloc/*.c) \ spinlock \
$(wildcard vfs/*.c) \ term \
$(wildcard storedev/*.c) \ dlmalloc \
$(wildcard util/*.c) \ vfs \
$(wildcard fs/kvfs/*.c) \ storedev \
$(wildcard fs/littlefs/*.c) \ util \
$(wildcard fs/portlfs/*.c) \ fs/kvfs \
$(wildcard baseimg/*.c) \ fs/littlefs \
$(wildcard hal/*.c) \ fs/portlfs \
$(wildcard hal/$(ARCH)/*.c) \ baseimg \
$(wildcard hal/$(ARCH)/*.S) \ proc \
$(wildcard paging/$(ARCH)/*.c) \ hal \
$(wildcard paging/*.c) \ hal/$(ARCH) \
$(wildcard *.S) \ std \
$(wildcard std/*.c) \ flanterm/src \
$(wildcard flanterm/src/*.c) \ flanterm/src/flanterm_backends \
$(wildcard flanterm/src/flanterm_backends/*.c) syscall \
CFILES := $(filter %.c,$(SRCFILES)) path \
ASFILES := $(filter %.S,$(SRCFILES)) rbuf \
OBJ := $(patsubst %.c,%.o,$(CFILES)) $(patsubst %.S,%.o,$(ASFILES)) ipc/pipe \
dev \
)
CFILES := $(call GET_CFILES, $(SRCFILES))
ASFILES := $(call GET_ASFILES, $(SRCFILES))
OBJ := $(call GET_OBJ, $(SRCFILES))
%.o: %.c %.o: %.c
$(CC) $(CFLAGS) -c $< -o $@ $(CC) $(CFLAGS) -c $< -o $@

View File

@ -1,5 +1,4 @@
CC := x86_64-elf-gcc include $(ROOT)/mk/arch/toolchain-x86_64.mk
LD := x86_64-elf-ld
CFLAGS += -m64 \ CFLAGS += -m64 \
-fPIE \ -fPIE \
@ -12,7 +11,7 @@ CFLAGS += -m64 \
-mno-red-zone \ -mno-red-zone \
-fno-stack-protector \ -fno-stack-protector \
-fno-stack-check \ -fno-stack-check \
-fno-lto -O0 \
LDFLAGS += -m elf_x86_64 \ LDFLAGS += -m elf_x86_64 \
-pie \ -pie \

6
kernel/atomic.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef ATOMIC_H_
#define ATOMIC_H_
#define ATOMIC(X) _Atomic(X)
#endif // ATOMIC_H_

View File

@ -32,7 +32,7 @@ void baseimg_init(void) {
hal_hang(); hal_hang();
} else { } else {
LOG("baseimg", "base.img found\n"); LOG("baseimg", "base.img found\n");
LOG("baseimg", "addr = %p, size = %lld\n", baseimg->address, baseimg->size); LOG("baseimg", "addr = %p, size = %lu\n", baseimg->address, baseimg->size);
for (size_t i = 0; i < 30; i++) { for (size_t i = 0; i < 30; i++) {
kprintf("%02X ", ((uint8_t *)(baseimg->address))[i]); kprintf("%02X ", ((uint8_t *)(baseimg->address))[i]);
if (i > 0 && (i + 1) % 10 == 0) { if (i > 0 && (i + 1) % 10 == 0) {

View File

@ -2,8 +2,8 @@
#include <stddef.h> #include <stddef.h>
#include <stdbool.h> #include <stdbool.h>
#include "bitmap.h" #include "bitmap.h"
#include "util/util.h"
#define DIV_ROUNDUP(num, div) ((num + div - 1) / div) #include "kprintf.h"
void *bitmap_toptr(BitMap *bm, size_t block) { void *bitmap_toptr(BitMap *bm, size_t block) {
uint8_t *ptr = (uint8_t *)(bm->mem_start + (block * BITMAP_BLOCK_SIZE)); uint8_t *ptr = (uint8_t *)(bm->mem_start + (block * BITMAP_BLOCK_SIZE));
@ -17,12 +17,12 @@ size_t bitmap_toblock(BitMap *bm, void *ptr) {
size_t bitmap_toblock_roundup(BitMap *bm, void *ptr) { size_t bitmap_toblock_roundup(BitMap *bm, void *ptr) {
uint8_t *p = ptr; uint8_t *p = ptr;
return (size_t)DIV_ROUNDUP((size_t)(p - bm->mem_start), BITMAP_BLOCK_SIZE); return (size_t)_DIV_ROUNDUP((size_t)(p - bm->mem_start), BITMAP_BLOCK_SIZE);
} }
size_t bitmap_calcsize(size_t total) { size_t bitmap_calcsize(size_t total) {
size_t nblocks = DIV_ROUNDUP(total, BITMAP_BLOCK_SIZE); size_t nblocks = _DIV_ROUNDUP(total, BITMAP_BLOCK_SIZE);
size_t nbytes = DIV_ROUNDUP(nblocks, 8); size_t nbytes = _DIV_ROUNDUP(nblocks, 8);
return nbytes; return nbytes;
} }
@ -59,7 +59,7 @@ void bitmap_markregion(BitMap *bm, void *baseptr, size_t size, bool is_used) {
if (is_used) { if (is_used) {
base = bitmap_toblock(bm, baseptr); base = bitmap_toblock(bm, baseptr);
size1 = DIV_ROUNDUP(size, BITMAP_BLOCK_SIZE); size1 = _DIV_ROUNDUP(size, BITMAP_BLOCK_SIZE);
} else { } else {
base = bitmap_toblock(bm, baseptr); base = bitmap_toblock(bm, baseptr);
size1 = size / BITMAP_BLOCK_SIZE; size1 = size / BITMAP_BLOCK_SIZE;
@ -105,13 +105,3 @@ void *bitmap_alloc(BitMap *bm, size_t blocks) {
void bitmap_free(BitMap *bm, void *base, size_t blocks) { void bitmap_free(BitMap *bm, void *base, size_t blocks) {
bitmap_markregion(bm, base, BITMAP_BLOCK_SIZE * blocks, 0); bitmap_markregion(bm, base, BITMAP_BLOCK_SIZE * blocks, 0);
} }
size_t bitmap_allocpageframe(BitMap *bm) {
size_t pickedreg = bitmap_freeregion(bm, 1);
bitmap_markblocks(bm, pickedreg, 1, 1);
return (bm->mem_start + (pickedreg * BITMAP_BLOCK_SIZE));
}
void bitmap_freepageframe(BitMap *bm, void *addr) {
bitmap_markregion(bm, addr, BITMAP_BLOCK_SIZE * 1, 0);
}

View File

@ -5,6 +5,8 @@
#include <stddef.h> #include <stddef.h>
#include <stdbool.h> #include <stdbool.h>
#include "hal/hal.h"
typedef struct { typedef struct {
uint8_t *map; uint8_t *map;
size_t nblocks; size_t nblocks;
@ -12,11 +14,10 @@ typedef struct {
size_t alloc_blocks; size_t alloc_blocks;
size_t last_deep_frag; size_t last_deep_frag;
uintptr_t mem_start; uintptr_t mem_start;
bool init;
} BitMap; } BitMap;
#define BITMAP_BLOCKS_PER_BYTE 8 #define BITMAP_BLOCKS_PER_BYTE 8
#define BITMAP_BLOCK_SIZE 0x1000 #define BITMAP_BLOCK_SIZE HAL_PAGE_SIZE
#define BITMAP_INVALID_BLOCK ((size_t)-1) #define BITMAP_INVALID_BLOCK ((size_t)-1)
void *bitmap_toptr(BitMap *bm, size_t block); void *bitmap_toptr(BitMap *bm, size_t block);
@ -30,7 +31,5 @@ void bitmap_markregion(BitMap *bm, void *baseptr, size_t size, bool is_used);
size_t bitmap_freeregion(BitMap *bm, size_t blocks); size_t bitmap_freeregion(BitMap *bm, size_t blocks);
void *bitmap_alloc(BitMap *bm, size_t blocks); void *bitmap_alloc(BitMap *bm, size_t blocks);
void bitmap_free(BitMap *bm, void *base, size_t blocks); void bitmap_free(BitMap *bm, void *base, size_t blocks);
size_t bitmap_allocpageframe(BitMap *bm);
void bitmap_freepageframe(BitMap *bm, void *addr);
#endif // BITMAP_BITMAP_H_ #endif // BITMAP_BITMAP_H_

View File

@ -6,68 +6,46 @@
BootInfo BOOT_INFO; BootInfo BOOT_INFO;
static volatile struct limine_paging_mode_request PAGING_REQ = { #define DEFINE_REQ(partname, partid) \
static volatile struct limine_##partname##_request partname##_req = \
{ .id = LIMINE_##partid##_REQUEST, .revision = 0 }
static volatile struct limine_paging_mode_request paging_req = {
.id = LIMINE_PAGING_MODE_REQUEST, .id = LIMINE_PAGING_MODE_REQUEST,
.revision = 0, .revision = 0,
#if defined(__x86_64__)
.mode = LIMINE_PAGING_MODE_X86_64_4LVL, .mode = LIMINE_PAGING_MODE_X86_64_4LVL,
#else
# error "Paging mode is unknown for this architecture"
#endif
}; };
static volatile struct limine_kernel_address_request KERN_ADDR_REQ = { DEFINE_REQ(kernel_address, KERNEL_ADDRESS);
.id = LIMINE_KERNEL_ADDRESS_REQUEST, .revision = 0, DEFINE_REQ(hhdm, HHDM);
}; DEFINE_REQ(memmap, MEMMAP);
DEFINE_REQ(smp, SMP);
static volatile struct limine_hhdm_request HHDM_REQ = { DEFINE_REQ(rsdp, RSDP);
.id = LIMINE_HHDM_REQUEST, .revision = 0, DEFINE_REQ(framebuffer, FRAMEBUFFER);
}; DEFINE_REQ(module, MODULE);
static volatile struct limine_memmap_request MEMMAP_REQ = {
.id = LIMINE_MEMMAP_REQUEST, .revision = 0,
};
static volatile struct limine_smp_request SMP_REQ = {
.id = LIMINE_SMP_REQUEST, .revision = 0,
};
static volatile struct limine_rsdp_request RSDP_REQ = {
.id = LIMINE_RSDP_REQUEST, .revision = 0,
};
static volatile struct limine_framebuffer_request FB_REQ = {
.id = LIMINE_FRAMEBUFFER_REQUEST, .revision = 0,
};
static volatile struct limine_module_request MODULE_REQ = {
.id = LIMINE_MODULE_REQUEST, .revision = 0,
};
void bootinfo_init(void) { void bootinfo_init(void) {
if (FB_REQ.response == NULL || FB_REQ.response->framebuffer_count < 1) { if (framebuffer_req.response == NULL || framebuffer_req.response->framebuffer_count < 1) {
hal_hang(); hal_hang();
} }
BOOT_INFO.fb = FB_REQ.response->framebuffers[0]; BOOT_INFO.fb = framebuffer_req.response->framebuffers[0];
struct limine_module_response *modulesres= MODULE_REQ.response; struct limine_module_response *modulesres= module_req.response;
BOOT_INFO.modules = modulesres; BOOT_INFO.modules = modulesres;
struct limine_paging_mode_response *pagingres = PAGING_REQ.response; struct limine_paging_mode_response *pagingres = paging_req.response;
#if defined(__x86_64__)
if (pagingres->mode != LIMINE_PAGING_MODE_X86_64_4LVL) { if (pagingres->mode != LIMINE_PAGING_MODE_X86_64_4LVL) {
#endif
hal_hang(); hal_hang();
} }
struct limine_hhdm_response *hhdmres = HHDM_REQ.response; struct limine_hhdm_response *hhdmres = hhdm_req.response;
BOOT_INFO.hhdm_off = hhdmres->offset; BOOT_INFO.hhdm_off = hhdmres->offset;
struct limine_kernel_address_response *kernaddrres = KERN_ADDR_REQ.response; struct limine_kernel_address_response *kernaddrres = kernel_address_req.response;
BOOT_INFO.kern_virtbase = kernaddrres->virtual_base; BOOT_INFO.kern_virtbase = kernaddrres->virtual_base;
BOOT_INFO.kern_physbase = kernaddrres->physical_base; BOOT_INFO.kern_physbase = kernaddrres->physical_base;
struct limine_memmap_response *memmapres = MEMMAP_REQ.response; struct limine_memmap_response *memmapres = memmap_req.response;
BOOT_INFO.memmap_entries = memmapres->entries; BOOT_INFO.memmap_entries = memmapres->entries;
BOOT_INFO.memmap_entrycount = memmapres->entry_count; BOOT_INFO.memmap_entrycount = memmapres->entry_count;
@ -79,7 +57,7 @@ void bootinfo_init(void) {
} }
} }
struct limine_smp_response *smpres = SMP_REQ.response; struct limine_smp_response *smpres = smp_req.response;
BOOT_INFO.smp = smpres; BOOT_INFO.smp = smpres;
BOOT_INFO.smp_bspindex = (uint64_t)(-1); BOOT_INFO.smp_bspindex = (uint64_t)(-1);
@ -93,6 +71,6 @@ void bootinfo_init(void) {
hal_hang(); hal_hang();
} }
struct limine_rsdp_response *rsdpres = RSDP_REQ.response; struct limine_rsdp_response *rsdpres = rsdp_req.response;
BOOT_INFO.rsdp = (size_t)rsdpres->address - BOOT_INFO.hhdm_off; BOOT_INFO.rsdp = (size_t)rsdpres->address - BOOT_INFO.hhdm_off;
} }

View File

@ -23,6 +23,7 @@ typedef struct {
uint64_t smp_bspindex; uint64_t smp_bspindex;
LIMINE_PTR(struct limine_framebuffer *) fb; LIMINE_PTR(struct limine_framebuffer *) fb;
LIMINE_PTR(struct limine_module_response *) modules; LIMINE_PTR(struct limine_module_response *) modules;
LIMINE_PTR(struct limine_executable_file_response *) exec;
} BootInfo; } BootInfo;
extern BootInfo BOOT_INFO; extern BootInfo BOOT_INFO;

View File

@ -2,5 +2,8 @@
#define COMPILER_ATTR_H_ #define COMPILER_ATTR_H_
#define PACKED __attribute__((packed)) #define PACKED __attribute__((packed))
#define ALIGNED(x) __attribute__((aligned((x))))
#define NORETURN __attribute__((noreturn))
#define UNUSED __attribute__((unused))
#endif // COMPILER_ATTR_H_ #endif // COMPILER_ATTR_H_

View File

@ -0,0 +1,6 @@
#ifndef COMPILER_BUILTINS_H_
#define COMPILER_BUILTINS_H_
#define unreachable() __builtin_unreachable()
#endif // COMPILER_BUILTINS_H_

22
kernel/dev/dev.c Normal file
View File

@ -0,0 +1,22 @@
#include <stdint.h>
#include <stddef.h>
#include "spinlock/spinlock.h"
#include "dev.h"
#include "hshtb.h"
#include "hal/hal.h"
#include "termdev.h"
#include "ps2kbdev.h"
#include "serialdev.h"
#include "fbdev.h"
DevTable DEVTABLE;
void dev_init(void) {
hal_memset(&DEVTABLE, 0, sizeof(DEVTABLE));
spinlock_init(&DEVTABLE.spinlock);
termdev_init();
ps2kbdev_init();
serialdev_init();
fbdev_init();
}

28
kernel/dev/dev.h Normal file
View File

@ -0,0 +1,28 @@
#ifndef DEV_DEV_H_
#define DEV_DEV_H_
#include <stdint.h>
#include "spinlock/spinlock.h"
#define DEV_FNS_MAX 32
typedef int32_t (*DevFn)(uint8_t *buffer, size_t len, void *extra);
typedef struct {
int _hshtbstate;
char ident[0x100];
DevFn fns[DEV_FNS_MAX];
SpinLock spinlock;
} Dev;
typedef struct {
SpinLock spinlock;
Dev devs[0x100];
} DevTable;
extern DevTable DEVTABLE;
void dev_init(void);
#endif // DEV_DEV_H_

29
kernel/dev/fbdev.c Normal file
View File

@ -0,0 +1,29 @@
#include <stdint.h>
#include <stddef.h>
#include "fbdev.h"
#include "dev.h"
#include "sysdefs/devctl.h"
#include "hshtb.h"
#include "spinlock/spinlock.h"
#include "util/util.h"
#include "hal/hal.h"
#include "bootinfo/bootinfo.h"
#include "errors.h"
int32_t fbdev_getinfo(uint8_t *buffer, size_t len, void *extra) {
FbDevGetInfo info = {
.w = BOOT_INFO.fb->width,
.h = BOOT_INFO.fb->height,
.margin = 20,
.fontw = 8,
.fonth = 16,
};
hal_memcpy(buffer, &info, sizeof(info));
return E_OK;
}
void fbdev_init(void) {
Dev *fbdev;
HSHTB_ALLOC(DEVTABLE.devs, ident, "fbdev", fbdev);
fbdev->fns[DEV_FBDEV_GETINFO] = &fbdev_getinfo;
}

7
kernel/dev/fbdev.h Normal file
View File

@ -0,0 +1,7 @@
#ifndef DEV_FBDEV_H_
#define DEV_FBDEV_H_
int32_t fbdev_getinfo(uint8_t *buffer, size_t len, void *extra);
void fbdev_init(void);
#endif // DEV_FBDEV_H_

259
kernel/dev/ps2kbdev.c Normal file
View File

@ -0,0 +1,259 @@
#include <stdint.h>
#include <stddef.h>
#include "kprintf.h"
#include "hal/hal.h"
#include "ps2kbdev.h"
#include "dev.h"
#include "errors.h"
#include "dlmalloc/malloc.h"
#include "util/util.h"
#include "hshtb.h"
#include "sysdefs/devctl.h"
#include "proc/proc.h"
#define KB_CTL_STATUS 0x64
#define KB_DATA_IN_BUF 0x01
#define KB_DATA 0x60
#define KB_SHIFT (1<<0)
#define KB_CTL (1<<1)
#define KB_ALT (1<<2)
#define KB_CAPSLOCK (1<<3)
#define KB_NUMLOCK (1<<4)
#define KB_SCRLLOCK (1<<5)
#define KB_E0ESC (1<<6)
#define KB_HOME 0xe0
#define KB_END 0xe1
#define KB_UP 0xe2
#define KB_DOWN 0xe3
#define KB_LEFT 0xe4
#define KB_RIGHT 0xe5
#define KB_PAGEUP 0xe6
#define KB_PAGEDN 0xe7
#define KB_INSERT 0xe8
#define KB_DELETE 0xe9
#define C(x) ((x)-'@')
static uint8_t shiftcode[0x100] = {
[0x1d] KB_CTL,
[0x2a] KB_SHIFT,
[0x36] KB_SHIFT,
[0x38] KB_ALT,
[0x9d] KB_CTL,
[0xb8] KB_ALT,
};
static uint8_t togglecode[0x100] = {
[0x3a] KB_CAPSLOCK,
[0x45] KB_NUMLOCK,
[0x46] KB_SCRLLOCK,
};
static uint8_t normalmap[0x100] = {
0x0, 0x1b, '1', '2', '3', '4', '5', '6',
'7', '8', '9', '0', '-', '=', '\b', '\t',
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
'o', 'p', '[', ']', '\n', 0x0, 'a', 's',
'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
'\'', '`', 0x0, '\\', 'z', 'x', 'c', 'v',
'b', 'n', 'm', ',', '.', '/', 0x0, '*',
0x0, ' ', 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, '7',
'8', '9', '-', '4', '5', '6', '+', '1',
'2', '3', '0', '.', 0x0, 0x0, 0x0, 0x0,
[0x9c] '\n',
[0xb5] '/',
[0xc8] KB_UP, [0xd0] KB_DOWN,
[0xc9] KB_PAGEUP, [0xd1] KB_PAGEDN,
[0xcb] KB_LEFT, [0xcd] KB_RIGHT,
[0x97] KB_HOME, [0xcf] KB_END,
[0xd2] KB_INSERT, [0xd3] KB_DELETE,
[0xc7] KB_HOME,
};
static uint8_t shiftmap[256] = {
0x0, 033,'!', '@', '#', '$', '%', '^',
'&', '*', '(', ')', '_', '+', '\b', '\t',
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
'O', 'P', '{', '}', '\n', 0x0, 'A', 'S',
'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
'"', '~', 0x0, '|', 'Z', 'X', 'C', 'V',
'B', 'N', 'M', '<', '>', '?', 0x0, '*',
0x0, ' ', 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, '7',
'8', '9', '-', '4', '5', '6', '+', '1',
'2', '3', '0', '.', 0x0, 0x0, 0x0, 0x0,
[0x9C] '\n',
[0xB5] '/',
[0xc8] KB_UP, [0xd0] KB_DOWN,
[0xc9] KB_PAGEUP, [0xd1] KB_PAGEDN,
[0xcb] KB_LEFT, [0xcd] KB_RIGHT,
[0x97] KB_HOME, [0xcf] KB_END,
[0xd2] KB_INSERT, [0xd3] KB_DELETE,
[0xc7] KB_HOME,
};
static uint8_t ctlmap[256] =
{
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
C('Q'), C('W'), C('E'), C('R'), C('T'), C('Y'), C('U'), C('I'),
C('O'), C('P'), 0x0, 0x0, '\r', 0x0, C('A'), C('S'),
C('D'), C('F'), C('G'), C('H'), C('J'), C('K'), C('L'), 0x0,
0x0, 0x0, 0x0, C('\\'), C('Z'), C('X'), C('C'), C('V'),
C('B'), C('N'), C('M'), 0x0, 0x0, C('/'), 0x0, 0x0,
[0x9C] '\r',
[0xB5] C('/'),
[0xc8] KB_UP, [0xd0] KB_DOWN,
[0xc9] KB_PAGEUP, [0xd1] KB_PAGEDN,
[0xcb] KB_LEFT, [0xcd] KB_RIGHT,
[0x97] KB_HOME, [0xcf] KB_END,
[0xd2] KB_INSERT, [0xd3] KB_DELETE,
[0xc7] KB_HOME,
};
int32_t ps2kb_intr(void) {
static uint8_t shift;
static uint8_t *charcode[4] = { normalmap, shiftmap, ctlmap, ctlmap };
uint32_t st, data, c;
st = io_in8(KB_CTL_STATUS);
if (!(st & KB_DATA_IN_BUF)) {
return -1;
}
data = io_in8(KB_DATA);
if (data == 0xe0) {
shift |= KB_E0ESC;
return 0;
} else if (data & 0x80) {
data = (shift & KB_E0ESC ? data : data & 0x7F);
shift &= ~(shiftcode[data] | KB_E0ESC);
return 0;
} else if (shift & KB_E0ESC) {
data |= 0x80;
shift &= ~KB_E0ESC;
}
shift |= shiftcode[data];
shift ^= togglecode[data];
c = charcode[shift & (KB_CTL | KB_SHIFT)][data];
if (shift & KB_CAPSLOCK) {
if ('a' <= c && c <= 'z') {
c += 'A' - 'a';
} else if ('A' <= c && c <= 'Z') {
c += 'a' - 'A';
}
}
return c;
}
typedef struct Ps2kbEvConsumer {
struct Ps2kbEvConsumer *next;
Proc *proc;
RBuf rbuf;
} Ps2kbEvConsumer;
struct {
SpinLock spinlock;
Ps2kbEvConsumer *list;
} PS2KB_CONSUMERS = {0};
int32_t ps2kbdev_readch(uint8_t *buffer, size_t len, void *extra) {
uint64_t pid = (uint64_t)buffer;
Proc *consproc = NULL;
spinlock_acquire(&PROCS.spinlock);
Proc *proc, *proctmp;
LL_FOREACH_SAFE(PROCS.procs, proc, proctmp) {
if (proc->pid == pid) {
consproc = proc;
}
}
spinlock_release(&PROCS.spinlock);
if (consproc == NULL) {
return E_INVALIDOPER;
}
uint8_t b;
int32_t r = -1;
spinlock_acquire(&PS2KB_CONSUMERS.spinlock);
Ps2kbEvConsumer *cons, *constmp;
LL_FOREACH_SAFE(PS2KB_CONSUMERS.list, cons, constmp) {
if (cons->proc == consproc) {
r = rbuf_pop(&cons->rbuf, &b);
break;
}
}
spinlock_release(&PS2KB_CONSUMERS.spinlock);
if (r == 0) {
return b;
} else {
return E_NOTYET;
}
}
#define CONSUMER_RBUF_MAX 0x400
int32_t ps2kbdev_attchcons(uint8_t *buffer, size_t len, void *extra) {
uint64_t pid = (uint64_t)buffer;
spinlock_acquire(&PROCS.spinlock);
Proc *proc, *proctmp;
LL_FOREACH_SAFE(PROCS.procs, proc, proctmp) {
if (proc->pid == pid) {
Ps2kbEvConsumer *cons = dlmalloc(sizeof(*cons));
cons->proc = proc;
uint8_t *buf = dlmalloc(CONSUMER_RBUF_MAX);
rbuf_init(&cons->rbuf, buf, CONSUMER_RBUF_MAX);
spinlock_acquire(&PS2KB_CONSUMERS.spinlock);
LL_APPEND(PS2KB_CONSUMERS.list, cons);
spinlock_release(&PS2KB_CONSUMERS.spinlock);
break;
}
}
spinlock_release(&PROCS.spinlock);
return E_OK;
}
void ps2kbdev_intr(void) {
int32_t c = ps2kb_intr();
if (c >= 0) {
uint8_t b = c;
spinlock_acquire(&PS2KB_CONSUMERS.spinlock);
Ps2kbEvConsumer *cons, *constmp;
LL_FOREACH_SAFE(PS2KB_CONSUMERS.list, cons, constmp) {
bool found = false;
spinlock_acquire(&PROCS.spinlock);
Proc *proc, *proctmp;
LL_FOREACH_SAFE(PROCS.procs, proc, proctmp) {
if (proc == cons->proc) {
found = true;
}
}
if (!found) {
LL_REMOVE(PS2KB_CONSUMERS.list, cons);
}
spinlock_release(&PROCS.spinlock);
rbuf_push(&cons->rbuf, b);
}
spinlock_release(&PS2KB_CONSUMERS.spinlock);
}
}
void ps2kbdev_init(void) {
intr_attchhandler(&ps2kbdev_intr, INTR_IRQBASE+1);
Dev *ps2kbdev;
HSHTB_ALLOC(DEVTABLE.devs, ident, "ps2kbdev", ps2kbdev);
spinlock_init(&ps2kbdev->spinlock);
spinlock_init(&PS2KB_CONSUMERS.spinlock);
ps2kbdev->fns[DEV_PS2KBDEV_READCH] = &ps2kbdev_readch;
ps2kbdev->fns[DEV_PS2KBDEV_ATTCHCONS] = &ps2kbdev_attchcons;
}

10
kernel/dev/ps2kbdev.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef DEV_PS2KBDEV_H_
#define DEV_PS2KBDEV_H_
#include <stdint.h>
#include <stddef.h>
#include "dev.h"
void ps2kbdev_init(void);
#endif // DEV_PS2KBDEV_H_

81
kernel/dev/serialdev.c Normal file
View File

@ -0,0 +1,81 @@
#include <stdint.h>
#include <stddef.h>
#include "dev.h"
#include "serialdev.h"
#include "errors.h"
#include "util/util.h"
#include "hshtb.h"
#include "sysdefs/devctl.h"
#include "kprintf.h"
#include "hal/hal.h"
// https://wiki.osdev.org/Serial_Ports
#define PORT 0x3f8
void serial_init(void) {
io_out8(PORT+1, 0x00);
io_out8(PORT+3, 0x80);
io_out8(PORT+0, 0x03);
io_out8(PORT+1, 0x00);
io_out8(PORT+3, 0x03);
io_out8(PORT+2, 0xC7);
io_out8(PORT+4, 0x0B);
io_out8(PORT+4, 0x1E);
io_out8(PORT+0, 0xAE);
if (io_in8(PORT+0) != 0xAE) {
ERR("serial", "serial is faulty!\n");
return;
}
io_out8(PORT+4, 0x0F);
}
int serial_recvready(void) {
return io_in8(PORT+5) & 1;
}
uint8_t serial_recvb(void) {
return io_in8(PORT);
}
int serial_sendready(void) {
return io_in8(PORT+5) & 0x20;
}
void serial_sendb(uint8_t b) {
io_out8(PORT, b);
}
int32_t serialdev_sendb(uint8_t *buffer, size_t len, void *extra) {
(void)len; (void)extra;
serial_sendb(buffer[0]);
return E_OK;
}
int32_t serialdev_sendready(uint8_t *buffer, size_t len, void *extra) {
(void)buffer; (void)len; (void) extra;
return serial_sendready();
}
int32_t serialdev_recvb(uint8_t *buffer, size_t len, void *extra) {
(void)buffer; (void)len; (void)extra;
return serial_recvb();
}
int32_t serialdev_recvready(uint8_t *buffer, size_t len, void *extra) {
(void)buffer; (void)len; (void)extra;
return serial_recvready();
}
void serialdev_init(void) {
Dev *serialdev = NULL;
HSHTB_ALLOC(DEVTABLE.devs, ident, "serialdev", serialdev);
serialdev->fns[DEV_SERIALDEV_SENDB] = &serialdev_sendb;
serialdev->fns[DEV_SERIALDEV_SENDREADY] = &serialdev_sendready;
serialdev->fns[DEV_SERIALDEV_RECVB] = &serialdev_recvb;
serialdev->fns[DEV_SERIALDEV_RECVREADY] = &serialdev_recvready;
spinlock_init(&serialdev->spinlock);
serial_init();
}

10
kernel/dev/serialdev.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef DEV_SERIALDEV_H_
#define DEV_SERIALDEV_H_
int32_t serialdev_sendb(uint8_t *buffer, size_t len, void *extra);
int32_t serialdev_sendready(uint8_t *buffer, size_t len, void *extra);
int32_t serialdev_recvb(uint8_t *buffer, size_t len, void *extra);
int32_t serialdev_recvready(uint8_t *buffer, size_t len, void *extra);
void serialdev_init(void);
#endif // DEV_SERIALDEV_H_

22
kernel/dev/termdev.c Normal file
View File

@ -0,0 +1,22 @@
#include <stdint.h>
#include <stddef.h>
#include "kprintf.h"
#include "hal/hal.h"
#include "termdev.h"
#include "dev.h"
#include "errors.h"
#include "util/util.h"
#include "hshtb.h"
#include "sysdefs/devctl.h"
int32_t termdev_putch(uint8_t *buffer, size_t len, void *extra) {
kprintf("%.*s", (int)len, (char *)buffer);
return E_OK;
}
void termdev_init(void) {
Dev *termdev = NULL;
HSHTB_ALLOC(DEVTABLE.devs, ident, "termdev", termdev);
termdev->fns[DEV_TERMDEV_PUTCH] = &termdev_putch;
spinlock_init(&termdev->spinlock);
}

11
kernel/dev/termdev.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef DEV_TERMDEV_H_
#define DEV_TERMDEV_H_
#include <stdint.h>
#include <stddef.h>
#include "dev.h"
int32_t termdev_putch(uint8_t *buffer, size_t len, void *extra);
void termdev_init(void);
#endif // DEV_TERMDEV_H_

View File

@ -0,0 +1,73 @@
// Config
#include <stddef.h>
#include "hal/hal.h"
#include "spinlock/spinlock.h"
#include "kprintf.h"
#include "bitmap/bitmap.h"
#include "util/util.h"
#include "pmm/pmm.h"
#include "malloc.h"
#include "bootinfo/bootinfo.h"
#define USE_DL_PREFIX 1
#define LACKS_SYS_TYPES_H 1
#define NO_MALLOC_STATS 1
#define LACKS_ERRNO_H 1
#define LACKS_TIME_H 1
#define LACKS_STDLIB_H 1
#define LACKS_SYS_MMAN_H 1
#define LACKS_FCNTL_H 1
#define LACKS_UNISTD_H 1
#define LACKS_SYS_PARAM_H 1
#define LACKS_STRINGS_H 1
#define LACKS_SCHED_H 1
#define HAVE_MMAP 0
#define ABORT \
do { \
ERR("dlmalloc", "Aborting..."); \
hal_hang(); \
} while(0)
#define MALLOC_FAILURE_ACTION
#define HAVE_MORECORE 1
#define USE_LOCKS 2
#define malloc_getpagesize 0x1000
#define EINVAL 0xdeadbeef
#define ENOMEM 0xb16b00b5
#define MORECORE_CONTIGUOUS 0
#define MLOCK_T SpinLock
int ACQUIRE_LOCK(SpinLock *sl) {
spinlock_acquire(sl);
return 0;
}
int RELEASE_LOCK(SpinLock *sl) {
spinlock_release(sl);
return 0;
}
int INITIAL_LOCK(SpinLock *sl) {
spinlock_init(sl);
return 0;
}
static MLOCK_T malloc_global_mutex = { 0 };
void *_last = 0;
void *sbrk(long inc) {
if (inc < 0) {
return 0;
}
if (!inc) {
return _last;
}
uint64_t blocks = _DIV_ROUNDUP(inc, BITMAP_BLOCK_SIZE);
uint8_t *virt = VIRT(pmm_alloc(blocks));
hal_memset(virt, 0, blocks * BITMAP_BLOCK_SIZE);
_last = (void *)(virt + inc);
return virt;
}

File diff suppressed because it is too large Load Diff

1
kernel/dlmalloc/malloc.c Symbolic link
View File

@ -0,0 +1 @@
../../dlmalloc/malloc.c

View File

@ -1,13 +0,0 @@
#ifndef MALLOC_MALLOC_H_
#define MALLOC_MALLOC_H_
#include <stddef.h>
void *dlmalloc(size_t);
void dlfree(void *);
void *dlcalloc(size_t, size_t);
void *dlrealloc(void *, size_t);
void *dlrealloc_in_place(void *, size_t);
void dlmalloc_check(void);
#endif // MALLOC_MALLOC_H_

1
kernel/dlmalloc/malloc.h Symbolic link
View File

@ -0,0 +1 @@
../../dlmalloc/malloc.h

355
kernel/elf.h Normal file
View File

@ -0,0 +1,355 @@
#ifndef ELF_H_
#define ELF_H_
#include <stdint.h>
#define ELFCLASS64 2
#define ELFDATA2LSB 1
#define ELFOSABI_SYSV 0
#define EM_X86_64 62
#define SHT_NULL 0
#define SHT_PROGBITS 1
#define SHT_SYMTAB 2
#define SHT_STRTAB 3
#define SHT_RELA 4
#define SHT_HASH 5
#define SHT_DYNAMIC 6
#define SHT_NOBITS 8
#define SHT_DYNSYM 11
#define SHF_WRITE 1
#define SHF_ALLOC 2
#define SHF_EXECINSTR 4
typedef uint64_t Elf64_Addr;
typedef uint64_t Elf64_Off;
typedef uint16_t Elf64_Half;
typedef uint32_t Elf64_Word;
typedef int32_t Elf64_Sword;
typedef uint64_t Elf64_Xword;
typedef int64_t Elf64_Sxword;
typedef uint32_t Elf32_Addr;
typedef uint32_t Elf32_Off;
typedef uint16_t Elf32_Half;
typedef uint32_t Elf32_Word;
typedef int32_t Elf32_Sword;
typedef uint64_t Elf32_Xword;
typedef int64_t Elf32_Sxword;
#define EI_NIDENT (16)
typedef struct {
unsigned char e_ident[EI_NIDENT]; /* ELF identification */
Elf32_Half e_type; /* Object file type */
Elf32_Half e_machine; /* Machine type */
Elf32_Word e_version; /* Object file version */
Elf32_Addr e_entry; /* Entry point address */
Elf32_Off e_phoff; /* Program header offset */
Elf32_Off e_shoff; /* Section header offset */
Elf32_Word e_flags; /* Processor-specific flags */
Elf32_Half e_ehsize; /* ELF header size */
Elf32_Half e_phentsize; /* Size of program header entry */
Elf32_Half e_phnum; /* Number of program header entries */
Elf32_Half e_shentsize; /* Size of section header entry */
Elf32_Half e_shnum; /* Number of section header entries */
Elf32_Half e_shstrndx; /* Section name string table index */
} Elf32_Ehdr;
typedef struct {
unsigned char e_ident[EI_NIDENT]; /* ELF identification */
Elf64_Half e_type; /* Object file type */
Elf64_Half e_machine; /* Machine type */
Elf64_Word e_version; /* Object file version */
Elf64_Addr e_entry; /* Entry point address */
Elf64_Off e_phoff; /* Program header offset */
Elf64_Off e_shoff; /* Section header offset */
Elf64_Word e_flags; /* Processor-specific flags */
Elf64_Half e_ehsize; /* ELF header size */
Elf64_Half e_phentsize; /* Size of program header entry */
Elf64_Half e_phnum; /* Number of program header entries */
Elf64_Half e_shentsize; /* Size of section header entry */
Elf64_Half e_shnum; /* Number of section header entries */
Elf64_Half e_shstrndx; /* Section name string table index */
} Elf64_Ehdr;
enum {
ET_NONE = 0,
ET_REL = 1,
ET_EXEC = 2,
ET_DYN = 3,
ET_CORE = 4,
};
enum { SHN_UNDEF = 0, SHN_ABS = 0xFFF1 };
typedef struct {
Elf64_Word st_name;
unsigned char st_info;
unsigned char st_other;
Elf64_Half st_shndx;
Elf64_Addr st_value;
Elf64_Xword st_size;
} Elf64_Sym;
enum { STB_GLOBAL = 1, STB_WEAK = 2, STB_GNU_UNIQUE = 10 };
enum { STT_OBJECT = 1, STT_FUNC = 2, STT_TLS = 6 };
enum {
R_X86_64_NONE = 0,
R_X86_64_64 = 1,
R_X86_64_COPY = 5,
R_X86_64_GLOB_DAT = 6,
R_X86_64_JUMP_SLOT = 7,
R_X86_64_RELATIVE = 8,
R_X86_64_DTPMOD64 = 16,
R_X86_64_DTPOFF64 = 17,
R_X86_64_TPOFF64 = 18,
};
enum {
R_AARCH64_ABS64 = 257,
R_AARCH64_COPY = 1024,
R_AARCH64_GLOB_DAT = 1025,
R_AARCH64_JUMP_SLOT = 1026,
R_AARCH64_RELATIVE = 1027,
R_AARCH64_TLS_TPREL = 1030,
R_AARCH64_TLSDESC = 1031
};
typedef struct {
Elf64_Addr r_offset;
uint64_t r_info;
} Elf64_Rel;
typedef struct {
Elf64_Addr r_offset;
Elf64_Xword r_info;
Elf64_Sxword r_addend;
} Elf64_Rela;
static inline Elf64_Xword ELF64_R_SYM(Elf64_Xword info) { return info >> 32; }
static inline Elf64_Xword ELF64_R_TYPE(Elf64_Xword info) {
return info & 0xFFFFFFFF;
}
enum {
PT_LOAD = 1,
PT_DYNAMIC = 2,
PT_INTERP = 3,
PT_NOTE = 4,
PT_PHDR = 6,
PT_TLS = 7,
PT_GNU_EH_FRAME = 0x6474E550,
PT_GNU_STACK = 0x6474E551,
PT_GNU_RELRO = 0x6474E552,
PT_GNU_PROPERTY = 0x6474E553,
};
enum { PF_X = 1, PF_W = 2, PF_R = 4 };
typedef struct {
Elf64_Word p_type; /* Type of segment */
Elf64_Word p_flags; /* Segment attributes */
Elf64_Off p_offset; /* Offset in file */
Elf64_Addr p_vaddr; /* Virtual address in memory */
Elf64_Addr p_paddr; /* Reserved */
Elf64_Xword p_filesz; /* Size of segment in file */
Elf64_Xword p_memsz; /* Size of segment in memory */
Elf64_Xword p_align; /* Alignment of segment */
} Elf64_Phdr;
enum {
DT_NULL = 0,
DT_NEEDED = 1,
DT_PLTRELSZ = 2,
DT_PLTGOT = 3,
DT_HASH = 4,
DT_STRTAB = 5,
DT_SYMTAB = 6,
DT_RELA = 7,
DT_RELASZ = 8,
DT_RELAENT = 9,
DT_STRSZ = 10,
DT_SYMENT = 11,
DT_INIT = 12,
DT_FINI = 13,
DT_SONAME = 14,
DT_RPATH = 15,
DT_SYMBOLIC = 16,
DT_REL = 17,
DT_BIND_NOW = 24,
DT_INIT_ARRAY = 25,
DT_FINI_ARRAY = 26,
DT_INIT_ARRAYSZ = 27,
DT_FINI_ARRAYSZ = 28,
DT_RUNPATH = 29,
DT_PLTREL = 20,
DT_DEBUG = 21,
DT_JMPREL = 23,
DT_FLAGS = 30,
DT_GNU_HASH = 0x6ffffef5,
DT_TLSDESC_PLT = 0x6ffffef6,
DT_TLSDESC_GOT = 0x6ffffef7,
DT_VERSYM = 0x6ffffff0,
DT_RELACOUNT = 0x6ffffff9,
DT_FLAGS_1 = 0x6ffffffb,
DT_VERDEF = 0x6ffffffc,
DT_VERDEFNUM = 0x6ffffffd,
DT_VERNEED = 0x6ffffffe,
DT_VERNEEDNUM = 0x6fffffff
};
enum {
// For DT_FLAGS.
DF_SYMBOLIC = 0x02,
DF_STATIC_TLS = 0x10,
// For DT_FLAGS_1.
DF_1_NOW = 0x00000001
};
typedef struct {
Elf32_Sword d_tag;
union {
Elf32_Word d_val;
Elf32_Addr d_ptr;
} d_un;
} Elf32_Dyn;
typedef struct {
Elf64_Sxword d_tag;
union {
Elf64_Xword d_val;
Elf64_Addr d_ptr;
} d_un;
} Elf64_Dyn;
typedef struct {
Elf32_Word sh_name;
Elf32_Word sh_type;
Elf32_Word sh_flags;
Elf32_Addr sh_addr;
Elf32_Off sh_offset;
Elf32_Word sh_size;
Elf32_Word sh_link;
Elf32_Word sh_info;
Elf32_Word sh_addralign;
Elf32_Word sh_entsize;
} Elf32_Shdr;
typedef struct {
Elf64_Word sh_name;
Elf64_Word sh_type;
Elf64_Xword sh_flags;
Elf64_Addr sh_addr;
Elf64_Off sh_offset;
Elf64_Xword sh_size;
Elf64_Word sh_link;
Elf64_Word sh_info;
Elf64_Xword sh_addralign;
Elf64_Xword sh_entsize;
} Elf64_Shdr;
typedef struct {
Elf32_Word n_namesz;
Elf32_Word n_descsz;
Elf32_Word n_type;
} Elf32_Nhdr;
typedef struct {
Elf64_Word n_namesz;
Elf64_Word n_descsz;
Elf64_Word n_type;
} Elf64_Nhdr;
/* ST_TYPE (subfield of st_info) values (symbol type) */
#define STT_NOTYPE 0
#define STT_OBJECT 1
#define STT_FUNC 2
#define STT_SECTION 3
#define STT_FILE 4
/* ST_BIND (subfield of st_info) values (symbol binding) */
#define STB_LOCAL 0
#define STB_GLOBAL 1
#define STB_WEAK 2
/* sh_type (section type) values */
#define SHT_NULL 0
#define SHT_PROGBITS 1
#define SHT_SYMTAB 2
#define SHT_STRTAB 3
#define SHT_RELA 4
#define SHT_NOBITS 8
#define SHT_REL 9
#define SHT_INIT_ARRAY 14
#define SHT_FINI_ARRAY 15
#define SHT_SYMTAB_SHNDX 18
/* special section indices */
#define SHN_UNDEF 0
#define SHN_LORESERVE 0xff00
#define SHN_COMMON 0xfff2
#define SHN_XINDEX 0xffff
#define SHN_HIRESERVE 0xff00
/* values for e_machine */
#define EM_NONE 0
#define EM_SPARC 2
#define EM_386 3
#define EM_PPC 20
#define EM_PPC64 21
#define EM_X86_64 62
/* e_indent constants */
#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'
#define EI_CLASS 4
#define ELFCLASSNONE 0
#define ELFCLASS32 1
#define ELFCLASS64 2
#define ELFCLASSNUM 3
#define EI_DATA 5
#define ELFDATANONE 0
#define ELFDATA2LSB 1
#define ELFDATA2MSB 2
#define ELFDATANUM 3
#define AT_NULL 0
#define AT_IGNORE 1
#define AT_EXECFD 2
#define AT_PHDR 3
#define AT_PHENT 4
#define AT_PHNUM 5
#define AT_PAGESZ 6
#define AT_BASE 7
#define AT_FLAGS 8
#define AT_ENTRY 9
#define AT_NOTELF 10
#define AT_UID 11
#define AT_EUID 12
#define AT_GID 13
#define AT_EGID 14
typedef struct {
uint64_t entry;
uint64_t phdr;
uint64_t phent;
uint64_t phnum;
} ElfAuxval;
#endif // ELF_H_

View File

@ -1,13 +0,0 @@
#ifndef ERRORS_H_
#define ERRORS_H_
#define E_OK 0
#define E_NOMEMORY -1
#define E_UNKNOWN_FSTYPE -2
#define E_NOENTRY -3
#define E_OUTOFBOUNDS -4
#define E_UNKNOWN_SDTYPE -5
#define E_TODO -6
#define E_GENERIC_ERROR -7
#endif // ERRORS_H_

345
kernel/fm-t-437.f16.h Normal file
View File

@ -0,0 +1,345 @@
unsigned char FM_T_437_F16[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0x81, 0xa5, 0xa5, 0x81, 0x81,
0x81, 0xbd, 0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x7e, 0xff, 0xff,
0xdb, 0xdb, 0xff, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00,
0x00, 0x22, 0x22, 0x77, 0x7f, 0x7f, 0x7f, 0x7f, 0x3e, 0x3e, 0x1c, 0x1c,
0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x1c, 0x1c, 0x3e, 0x3e, 0x7f, 0x7f,
0x3e, 0x3e, 0x1c, 0x1c, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x1c, 0x1c,
0x1c, 0x08, 0x6b, 0x7f, 0x7f, 0x6b, 0x08, 0x1c, 0x3e, 0x00, 0x00, 0x00,
0x00, 0x08, 0x08, 0x1c, 0x3e, 0x7f, 0x7f, 0x7f, 0x7f, 0x2a, 0x08, 0x1c,
0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x7e, 0x7e, 0x7e,
0x7e, 0x7e, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0xff, 0xff, 0xe7, 0xc3,
0xc3, 0x81, 0x81, 0x81, 0x81, 0x81, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff,
0x00, 0x00, 0x18, 0x24, 0x24, 0x42, 0x42, 0x42, 0x42, 0x42, 0x24, 0x24,
0x18, 0x00, 0x00, 0x00, 0xff, 0xff, 0xe7, 0xdb, 0xdb, 0xbd, 0xbd, 0xbd,
0xbd, 0xbd, 0xdb, 0xdb, 0xe7, 0xff, 0xff, 0xff, 0x00, 0x0f, 0x03, 0x05,
0x05, 0x08, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x00, 0x00,
0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x08, 0x08, 0x3e,
0x08, 0x08, 0x00, 0x00, 0x00, 0x08, 0x0c, 0x0a, 0x0a, 0x09, 0x09, 0x09,
0x08, 0x08, 0x38, 0x78, 0x78, 0x30, 0x00, 0x00, 0x00, 0x3f, 0x21, 0x3f,
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x23, 0x67, 0xe7, 0xe2, 0x40, 0x00,
0x00, 0x49, 0x49, 0x2a, 0x36, 0x14, 0x22, 0xe3, 0x22, 0x14, 0x36, 0x2a,
0x49, 0x49, 0x00, 0x00, 0x00, 0x00, 0x40, 0x60, 0x70, 0x78, 0x7c, 0x7e,
0x7c, 0x78, 0x70, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06,
0x0e, 0x1e, 0x3e, 0x7e, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00,
0x00, 0x08, 0x1c, 0x2a, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x2a,
0x1c, 0x08, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
0x22, 0x22, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x00, 0x3f, 0x49, 0x49,
0x49, 0x49, 0x39, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0x00,
0x00, 0x3c, 0x42, 0x42, 0x40, 0x20, 0x58, 0x44, 0x22, 0x1a, 0x04, 0x02,
0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x08, 0x1c, 0x2a,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x2a, 0x1c, 0x08, 0x3e, 0x00, 0x00,
0x00, 0x08, 0x1c, 0x2a, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x2a, 0x1c, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x04, 0x02, 0x7f, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x7f, 0x20, 0x10, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40,
0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x24, 0x42, 0xff, 0x42, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x1c, 0x1c, 0x3e, 0x3e, 0x7f, 0x7f,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x3e, 0x3e,
0x1c, 0x1c, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
0x08, 0x08, 0x00, 0x00, 0x00, 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x24, 0x24,
0x7e, 0x24, 0x24, 0x24, 0x24, 0x24, 0x7e, 0x24, 0x24, 0x24, 0x00, 0x00,
0x00, 0x08, 0x1e, 0x2b, 0x28, 0x28, 0x28, 0x1c, 0x0a, 0x0a, 0x0a, 0x6a,
0x3c, 0x08, 0x00, 0x00, 0x00, 0x00, 0x32, 0x52, 0x54, 0x64, 0x08, 0x08,
0x10, 0x10, 0x26, 0x2a, 0x4a, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44,
0x44, 0x44, 0x28, 0x18, 0x24, 0x45, 0x42, 0x42, 0x42, 0x3d, 0x00, 0x00,
0x00, 0x00, 0x04, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0x08, 0x08, 0x04, 0x00, 0x00, 0x00, 0x20, 0x10, 0x10,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x00, 0x00,
0x00, 0x00, 0x08, 0x49, 0x2a, 0x1c, 0x1c, 0x7f, 0x1c, 0x1c, 0x2a, 0x49,
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x3e,
0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x08, 0x08, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 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, 0x02, 0x02,
0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x80, 0x80, 0x00, 0x00,
0x00, 0x18, 0x24, 0x24, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x24,
0x24, 0x18, 0x00, 0x00, 0x00, 0x08, 0x18, 0x28, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42,
0x42, 0x02, 0x04, 0x08, 0x10, 0x20, 0x20, 0x40, 0x40, 0x7e, 0x00, 0x00,
0x00, 0x3c, 0x42, 0x42, 0x02, 0x02, 0x02, 0x1c, 0x02, 0x02, 0x02, 0x42,
0x42, 0x3c, 0x00, 0x00, 0x00, 0x04, 0x0c, 0x0c, 0x14, 0x14, 0x24, 0x24,
0x44, 0x44, 0x44, 0x7e, 0x04, 0x04, 0x00, 0x00, 0x00, 0x7e, 0x40, 0x40,
0x40, 0x40, 0x7c, 0x02, 0x02, 0x02, 0x02, 0x42, 0x42, 0x3c, 0x00, 0x00,
0x00, 0x3c, 0x42, 0x42, 0x40, 0x40, 0x7c, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x3c, 0x00, 0x00, 0x00, 0x7e, 0x42, 0x42, 0x42, 0x04, 0x04, 0x04,
0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42,
0x42, 0x42, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00,
0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x42,
0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
0x18, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x08, 0x10, 0x20, 0x00, 0x00,
0x00, 0x00, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x20, 0x10, 0x08, 0x04,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00,
0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x20,
0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x00, 0x00, 0x00,
0x00, 0x3c, 0x42, 0x42, 0x42, 0x02, 0x04, 0x08, 0x08, 0x08, 0x00, 0x00,
0x08, 0x08, 0x00, 0x00, 0x00, 0x1e, 0x22, 0x41, 0x49, 0x55, 0x55, 0x55,
0x55, 0x55, 0x57, 0x4b, 0x20, 0x1f, 0x00, 0x00, 0x00, 0x18, 0x24, 0x42,
0x42, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00,
0x00, 0x7c, 0x22, 0x22, 0x22, 0x22, 0x22, 0x3c, 0x22, 0x22, 0x22, 0x22,
0x22, 0x7c, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x42, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x42, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x78, 0x24, 0x22,
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x78, 0x00, 0x00,
0x00, 0x7e, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x40,
0x40, 0x7e, 0x00, 0x00, 0x00, 0x7e, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7c,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x42,
0x40, 0x40, 0x40, 0x40, 0x4e, 0x42, 0x42, 0x42, 0x22, 0x1c, 0x00, 0x00,
0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x1c, 0x00, 0x00, 0x00, 0x0e, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00,
0x00, 0x42, 0x42, 0x44, 0x44, 0x48, 0x50, 0x50, 0x68, 0x48, 0x44, 0x44,
0x42, 0x42, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x41, 0x63, 0x63,
0x55, 0x55, 0x49, 0x49, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x00, 0x00,
0x00, 0x42, 0x42, 0x62, 0x62, 0x52, 0x52, 0x4a, 0x4a, 0x46, 0x46, 0x42,
0x42, 0x42, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x78, 0x44, 0x42,
0x42, 0x42, 0x44, 0x78, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00,
0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x52, 0x4a, 0x44,
0x44, 0x3a, 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x7c,
0x48, 0x48, 0x44, 0x44, 0x42, 0x42, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42,
0x40, 0x40, 0x40, 0x3c, 0x02, 0x02, 0x02, 0x42, 0x42, 0x3c, 0x00, 0x00,
0x00, 0x7f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x22, 0x22, 0x22, 0x14, 0x1c, 0x08, 0x00, 0x00,
0x00, 0x41, 0x41, 0x41, 0x41, 0x49, 0x49, 0x49, 0x49, 0x55, 0x55, 0x55,
0x22, 0x22, 0x00, 0x00, 0x00, 0x41, 0x41, 0x22, 0x36, 0x14, 0x08, 0x08,
0x08, 0x14, 0x36, 0x22, 0x41, 0x41, 0x00, 0x00, 0x00, 0x41, 0x41, 0x22,
0x22, 0x14, 0x14, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
0x00, 0x7e, 0x02, 0x02, 0x04, 0x04, 0x08, 0x18, 0x10, 0x20, 0x20, 0x40,
0x40, 0x7e, 0x00, 0x00, 0x00, 0x1c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0x10, 0x10, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
0x40, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x02, 0x02, 0x00, 0x00,
0x00, 0x1c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x1c, 0x00, 0x00, 0x00, 0x08, 0x14, 0x22, 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, 0x7e, 0x00, 0x00,
0x00, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x04,
0x3c, 0x44, 0x44, 0x44, 0x48, 0x36, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40,
0x40, 0x5c, 0x62, 0x42, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x40, 0x40, 0x40, 0x40,
0x42, 0x3c, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x3a, 0x46, 0x42,
0x42, 0x42, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3c, 0x42, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00,
0x00, 0x0c, 0x12, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x46, 0x42,
0x42, 0x42, 0x42, 0x46, 0x3a, 0x02, 0x02, 0x3c, 0x00, 0x40, 0x40, 0x40,
0x40, 0x5c, 0x62, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00,
0x00, 0x08, 0x08, 0x00, 0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x0c, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x24, 0x18, 0x00, 0x40, 0x40, 0x40,
0x40, 0x42, 0x44, 0x48, 0x50, 0x60, 0x50, 0x48, 0x44, 0x42, 0x00, 0x00,
0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x6d, 0x49,
0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x5c, 0x62, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x62, 0x42,
0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x42, 0x46, 0x3a, 0x02, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x32, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40,
0x40, 0x3c, 0x02, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
0x10, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x12, 0x0c, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x46, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x41,
0x41, 0x22, 0x22, 0x14, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x36, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x66, 0x24, 0x18, 0x24, 0x66,
0x42, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x46, 0x3a, 0x02, 0x02, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7e, 0x02, 0x04, 0x04, 0x18, 0x20, 0x20, 0x40, 0x7e, 0x00, 0x00,
0x00, 0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x08, 0x08, 0x08, 0x08,
0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x10,
0x10, 0x10, 0x10, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x00, 0x00,
0x00, 0x32, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x28,
0x44, 0x82, 0x82, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x42,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x42, 0x22, 0x1c, 0x08, 0x38,
0x00, 0x42, 0x42, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x46, 0x3a, 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x00, 0x3c, 0x42, 0x42,
0x42, 0x7e, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x10, 0x28, 0x44,
0x00, 0x38, 0x44, 0x04, 0x3c, 0x44, 0x44, 0x44, 0x48, 0x36, 0x00, 0x00,
0x00, 0x44, 0x44, 0x00, 0x00, 0x38, 0x44, 0x04, 0x3c, 0x44, 0x44, 0x44,
0x48, 0x36, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x00, 0x38, 0x44, 0x04,
0x3c, 0x44, 0x44, 0x44, 0x48, 0x36, 0x00, 0x00, 0x00, 0x18, 0x24, 0x18,
0x00, 0x38, 0x44, 0x04, 0x3c, 0x44, 0x44, 0x44, 0x48, 0x36, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x40, 0x40, 0x40, 0x40,
0x42, 0x3c, 0x08, 0x38, 0x00, 0x18, 0x24, 0x42, 0x00, 0x3c, 0x42, 0x42,
0x42, 0x7e, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x42, 0x42, 0x00,
0x00, 0x3c, 0x42, 0x42, 0x42, 0x7e, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00,
0x00, 0x20, 0x10, 0x08, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x7e, 0x40, 0x40,
0x42, 0x3c, 0x00, 0x00, 0x00, 0x42, 0x42, 0x00, 0x00, 0x18, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x1c, 0x00, 0x00, 0x00, 0x08, 0x14, 0x22,
0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1c, 0x00, 0x00,
0x00, 0x20, 0x10, 0x08, 0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x1c, 0x00, 0x00, 0x00, 0x42, 0x42, 0x18, 0x24, 0x42, 0x42, 0x42,
0x7e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x18, 0x24, 0x18,
0x24, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00,
0x04, 0x08, 0x7e, 0x40, 0x40, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x40, 0x40,
0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x49, 0x09,
0x39, 0x4f, 0x48, 0x48, 0x49, 0x36, 0x00, 0x00, 0x00, 0x1f, 0x28, 0x48,
0x48, 0x48, 0x48, 0x7f, 0x48, 0x48, 0x48, 0x48, 0x48, 0x4f, 0x00, 0x00,
0x00, 0x18, 0x24, 0x42, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x3c, 0x00, 0x00, 0x00, 0x42, 0x42, 0x00, 0x00, 0x3c, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00,
0x00, 0x18, 0x24, 0x42, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x46, 0x3a, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x00, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00, 0x00, 0x42, 0x42, 0x00,
0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x46, 0x3a, 0x02, 0x02, 0x3c,
0x42, 0x42, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x3c, 0x00, 0x00, 0x42, 0x42, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
0x08, 0x3e, 0x49, 0x48, 0x48, 0x48, 0x48, 0x49, 0x3e, 0x08, 0x08, 0x00,
0x00, 0x0c, 0x12, 0x10, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x08, 0x38, 0x49,
0x49, 0x36, 0x00, 0x00, 0x00, 0x41, 0x41, 0x22, 0x22, 0x14, 0x7f, 0x08,
0x08, 0x7f, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x78, 0x44, 0x42,
0x42, 0x44, 0x78, 0x40, 0x44, 0x5f, 0x44, 0x44, 0x45, 0x42, 0x00, 0x00,
0x00, 0x06, 0x09, 0x09, 0x08, 0x08, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x48,
0x48, 0x30, 0x00, 0x00, 0x00, 0x08, 0x10, 0x20, 0x00, 0x38, 0x44, 0x04,
0x3c, 0x44, 0x44, 0x44, 0x48, 0x36, 0x00, 0x00, 0x00, 0x04, 0x08, 0x10,
0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1c, 0x00, 0x00,
0x00, 0x04, 0x08, 0x10, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x3c, 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x00, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x46, 0x3a, 0x00, 0x00, 0x00, 0x32, 0x4c, 0x00,
0x00, 0x5c, 0x62, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00,
0x32, 0x4c, 0x00, 0x42, 0x62, 0x62, 0x52, 0x52, 0x4a, 0x4a, 0x46, 0x46,
0x42, 0x42, 0x00, 0x00, 0x00, 0x38, 0x48, 0x48, 0x34, 0x00, 0x7c, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x48, 0x48,
0x30, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x20, 0x40, 0x42, 0x42,
0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e,
0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7e, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x10, 0x30, 0x10, 0x10, 0x11, 0x3a, 0x04, 0x08, 0x16, 0x29, 0x42,
0x04, 0x08, 0x0f, 0x00, 0x00, 0x10, 0x30, 0x10, 0x10, 0x11, 0x3a, 0x04,
0x08, 0x12, 0x26, 0x4a, 0x1f, 0x02, 0x02, 0x00, 0x00, 0x00, 0x08, 0x08,
0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x24, 0x48, 0x24, 0x12, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x24, 0x12,
0x24, 0x48, 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, 0xee, 0xbb, 0xee, 0xbb, 0xee, 0xbb, 0xee, 0xbb,
0xee, 0xbb, 0xee, 0xbb, 0xee, 0xbb, 0xee, 0xbb, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xf8, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xf8, 0x08,
0xf8, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x24, 0x24, 0x24, 0x24,
0x24, 0x24, 0x24, 0x24, 0xe4, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x24, 0x24, 0x24,
0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x08,
0xf8, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x24, 0x24, 0x24, 0x24,
0x24, 0x24, 0xe4, 0x04, 0xe4, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x04,
0xe4, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
0x24, 0x24, 0xe4, 0x04, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0xfc, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xf8, 0x08,
0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xf8, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x0f, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
0x27, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
0x24, 0x24, 0x27, 0x20, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x20, 0x27, 0x24, 0x24, 0x24,
0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0xe7, 0x00,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0x00, 0xe7, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x27, 0x20, 0x27, 0x24, 0x24, 0x24,
0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x24, 0x24, 0x24,
0x24, 0x24, 0xe7, 0x00, 0xe7, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0x00, 0xff, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x24, 0x24, 0x24,
0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x0f, 0x08, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x08, 0x0f, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3f, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
0x24, 0x24, 0x24, 0x24, 0xff, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xff, 0x08, 0xff, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x32, 0x4a, 0x4a, 0x44, 0x44, 0x44, 0x44, 0x4a, 0x32, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x48, 0x44, 0x42, 0x42,
0x42, 0x4c, 0x40, 0x40, 0x00, 0x7e, 0x42, 0x42, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7f, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00,
0x00, 0x7f, 0x40, 0x40, 0x20, 0x10, 0x08, 0x04, 0x08, 0x10, 0x20, 0x40,
0x40, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x48, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5d, 0x40, 0x40,
0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x4e, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x00, 0x00, 0x00, 0x7f, 0x08, 0x08, 0x1c, 0x22, 0x41, 0x41,
0x41, 0x22, 0x1c, 0x08, 0x08, 0x7f, 0x00, 0x00, 0x00, 0x18, 0x24, 0x24,
0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x24, 0x24, 0x18, 0x00, 0x00,
0x00, 0x00, 0x18, 0x24, 0x24, 0x42, 0x42, 0x42, 0x42, 0x42, 0x24, 0x24,
0x24, 0x66, 0x00, 0x00, 0x00, 0x0e, 0x11, 0x08, 0x04, 0x1c, 0x22, 0x42,
0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x36, 0x49, 0x49, 0x49, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x02, 0x02, 0x04, 0x3c, 0x4a, 0x4a, 0x52, 0x52, 0x3c, 0x20,
0x40, 0x40, 0x00, 0x00, 0x00, 0x0e, 0x10, 0x20, 0x20, 0x40, 0x40, 0x7c,
0x40, 0x40, 0x20, 0x20, 0x10, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x3e,
0x08, 0x08, 0x08, 0x08, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, 0x7e, 0x00, 0x00,
0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x40, 0x20, 0x10, 0x08, 0x04,
0x00, 0x7e, 0x00, 0x00, 0x00, 0x06, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x48, 0x48, 0x48, 0x30, 0x00,
0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x4c, 0x00,
0x32, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x48, 0x48,
0x48, 0x30, 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, 0x08, 0x08,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x28, 0x68, 0x28, 0x18, 0x18, 0x08, 0x00, 0x00,
0x00, 0x58, 0x64, 0x44, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x04, 0x18, 0x20, 0x3c, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};
unsigned int FM_T_437_F16_len = 4096;

View File

@ -1,107 +0,0 @@
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include "spinlock/spinlock.h"
#include "errors.h"
#include "hal/hal.h"
#include "hshtb.h"
#include "kprintf.h"
#include "vfs/vfs.h"
#include "dlmalloc/malloc.h"
#include "util/util.h"
int32_t kvfs_read(struct VfsMountPoint *vmp, const char *key, uint8_t *const buffer, size_t n, size_t off) {
KvfsNode *node = NULL;
spinlock_acquire(&vmp->spinlock);
HSHTB_GET(&vmp->fs.kvfs, nodes, (char *)key, key_, node);
spinlock_release(&vmp->spinlock);
if (node == NULL) {
return E_NOENTRY;
}
spinlock_acquire(&node->spinlock);
vmp->backingsd->read(vmp->backingsd, buffer, n, off);
spinlock_release(&node->spinlock);
return E_OK;
}
int32_t kvfs_write(struct VfsMountPoint *vmp, const char *key, const uint8_t *const buffer, size_t n, size_t off) {
KvfsNode *node = NULL;
spinlock_acquire(&vmp->spinlock);
HSHTB_GET(&vmp->fs.kvfs, nodes, (char *)key, key_, node);
spinlock_release(&vmp->spinlock);
if (node == NULL) {
return E_NOENTRY;
}
spinlock_acquire(&node->spinlock);
vmp->backingsd->write(vmp->backingsd, buffer, n, off);
spinlock_release(&node->spinlock);
return E_OK;
}
int32_t kvfs_remove(struct VfsMountPoint *vmp, const char *key) {
KvfsNode *node = NULL;
spinlock_acquire(&vmp->spinlock);
HSHTB_GET(&vmp->fs.kvfs, nodes, (char *)key, key_, node);
spinlock_release(&vmp->spinlock);
if (node == NULL) {
return E_NOENTRY;
}
spinlock_acquire(&node->spinlock);
hal_memset(node, 0, sizeof(*node));
spinlock_release(&node->spinlock);
return E_OK;
}
int32_t kvfs_cleanup(struct VfsMountPoint *vmp) {
int32_t err = vmp->backingsd->cleanup(vmp->backingsd);
if (err != E_OK) {
return err;
}
return E_OK;
}
int32_t kvfs_create(struct VfsMountPoint *vmp, const char *path, int32_t type) {
(void)type;
KvfsNode *node = NULL;
spinlock_acquire(&vmp->spinlock);
HSHTB_ALLOC(&vmp->fs.kvfs, nodes, (char *)path, key_, node);
spinlock_release(&vmp->spinlock);
if (node == NULL) {
return E_NOMEMORY;
}
return E_OK;
}
bool kvfs_check(void) {
int32_t ret;
ret = vfs_create("tmpvars", "hello", VFS_CREATE_FILE);
if (ret != E_OK) return false;
char *hello = "WAWAWAWA!!!";
ret = vfs_write("tmpvars", "hello", hello, hal_strlen(hello)+1, 0);
if (ret != E_OK) return false;
char buf[20];
ret = vfs_read("tmpvars", "hello", buf, sizeof(buf), 0);
if (ret != E_OK) return false;
vfs_remove("tmpvars", "hello");
if (ret != E_OK) return false;
ret = vfs_read("tmpvars", "hello", buf, sizeof(buf), 0);
if (ret != E_NOENTRY) return false;
return true;
}

View File

@ -1,30 +0,0 @@
#ifndef FS_KVFS_KVFS_H_
#define FS_KVFS_KVFS_H_
#include <stdint.h>
#include <stdbool.h>
struct VfsMountPoint;
#define KVFS_NODE_KEY_MAX 128
#define KVFS_NODES_MAX 256
#define KVFS_BUFFER_SIZE (1024 * 2)
typedef struct {
bool taken;
uint8_t key_[KVFS_NODE_KEY_MAX];
SpinLock spinlock;
} KvfsNode;
typedef struct {
KvfsNode nodes[KVFS_NODES_MAX];
} Kvfs;
int32_t kvfs_read(struct VfsMountPoint *vmp, const char *key, uint8_t *const buffer, size_t n, size_t off);
int32_t kvfs_write(struct VfsMountPoint *vmp, const char *key, const uint8_t *const buffer, size_t n, size_t off);
int32_t kvfs_remove(struct VfsMountPoint *vmp, const char *key);
int32_t kvfs_create(struct VfsMountPoint *vmp, const char *path, int32_t type);
int32_t kvfs_cleanup(struct VfsMountPoint *vmp);
bool kvfs_check(void);
#endif // FS_KVFS_KVFS_H_

View File

@ -5,96 +5,216 @@
#include "errors.h" #include "errors.h"
#include "kprintf.h" #include "kprintf.h"
#include "dlmalloc/malloc.h" #include "dlmalloc/malloc.h"
#include "hal/hal.h"
#define CHECK(err) \
do { \
int ok = (err); \
kprintf("ok = %d\n", ok); \
if (ok < 0) goto bad; \
} while(0)
int32_t littlefs_read(struct VfsMountPoint *vmp, const char *path, uint8_t *const buffer, size_t n, size_t off) {
spinlock_acquire(&vmp->spinlock);
LittleFs *fs = &vmp->fs.littlefs;
lfs_file_t file;
CHECK(lfs_file_open(&fs->instance, &file, path, LFS_O_RDONLY));
CHECK(lfs_file_seek(&fs->instance, &file, off, LFS_SEEK_SET));
CHECK(lfs_file_read(&fs->instance, &file, buffer + off, n));
CHECK(lfs_file_close(&fs->instance, &file));
spinlock_release(&vmp->spinlock);
return E_OK;
bad:
spinlock_release(&vmp->spinlock);
return E_GENERIC_ERROR;
}
int32_t littlefs_write(struct VfsMountPoint *vmp, const char *path, const uint8_t *const buffer, size_t n, size_t off) {
spinlock_acquire(&vmp->spinlock);
LittleFs *fs = &vmp->fs.littlefs;
lfs_file_t file;
CHECK(lfs_file_open(&fs->instance, &file, path, LFS_O_WRONLY));
CHECK(lfs_file_seek(&fs->instance, &file, off, LFS_SEEK_SET));
CHECK(lfs_file_write(&fs->instance, &file, buffer, n));
CHECK(lfs_file_close(&fs->instance, &file));
spinlock_release(&vmp->spinlock);
return E_OK;
bad:
spinlock_release(&vmp->spinlock);
return E_GENERIC_ERROR;
}
int32_t littlefs_remove(struct VfsMountPoint *vmp, const char *path) {
spinlock_acquire(&vmp->spinlock);
LittleFs *fs = &vmp->fs.littlefs;
CHECK(lfs_remove(&fs->instance, path));
spinlock_release(&vmp->spinlock);
return E_OK;
bad:
spinlock_release(&vmp->spinlock);
return E_GENERIC_ERROR;
}
int32_t littlefs_cleanup(struct VfsMountPoint *vmp) { int32_t littlefs_cleanup(struct VfsMountPoint *vmp) {
dlfree(vmp->fs.littlefs.instance.cfg); dlfree((void *)vmp->fs.littlefs.instance.cfg);
int32_t err = vmp->backingsd->cleanup(vmp->backingsd); int32_t err = vmp->backingsd->cleanup(vmp->backingsd);
if (err != E_OK) { if (err != E_OK) {
return err; return err;
} }
err = lfs_unmount(&vmp->fs.littlefs.instance); err = lfs_unmount(&vmp->fs.littlefs.instance);
if (err < 0) { return E_GENERIC_ERROR; } if (err < 0) { return E_BADIO; }
return E_OK; return E_OK;
} }
int32_t littlefs_create(struct VfsMountPoint *vmp, const char *path, int32_t type) { void littlefs_vobj_cleanup(struct VfsObj *vobj) {
if (vobj->extra != NULL) {
lfs_file_close(&vobj->vmp->fs.littlefs.instance, (lfs_file_t *)vobj->extra);
dlfree(vobj->extra);
}
dlfree(vobj);
}
int32_t littlefs_vobj_read(struct VfsObj *vobj, uint8_t *const buffer, size_t n, size_t off) {
if (!(vobj->flags & VFS_FLAG_READ)) {
return E_INVALIDOPER;
}
spinlock_acquire(&vobj->spinlock);
int ok = lfs_file_seek(&vobj->vmp->fs.littlefs.instance, (lfs_file_t *)vobj->extra, off, LFS_SEEK_SET);
if (ok < 0) {
spinlock_release(&vobj->spinlock);
return E_BADIO;
}
ok = lfs_file_read(&vobj->vmp->fs.littlefs.instance, (lfs_file_t *)vobj->extra, buffer, n);
if (ok < 0) {
spinlock_release(&vobj->spinlock);
return E_BADIO;
}
spinlock_release(&vobj->spinlock);
return E_OK;
}
int32_t littlefs_vobj_write(struct VfsObj *vobj, const uint8_t *const buffer, size_t n, size_t off) {
if (!(vobj->flags & VFS_FLAG_WRITE)) {
return E_INVALIDOPER;
}
spinlock_acquire(&vobj->spinlock);
int ok = lfs_file_seek(&vobj->vmp->fs.littlefs.instance, (lfs_file_t *)vobj->extra, off, LFS_SEEK_SET);
if (ok < 0) {
spinlock_release(&vobj->spinlock);
return E_BADIO;
}
ok = lfs_file_write(&vobj->vmp->fs.littlefs.instance, (lfs_file_t *)vobj->extra, buffer, n);
if (ok < 0) {
spinlock_release(&vobj->spinlock);
return E_BADIO;
}
spinlock_release(&vobj->spinlock);
return E_OK;
}
int32_t littlefs_stat(struct VfsMountPoint *vmp, const char *path, IoctlStat *statbuf) {
struct lfs_info info;
spinlock_acquire(&vmp->spinlock); spinlock_acquire(&vmp->spinlock);
LittleFs *fs = &vmp->fs.littlefs; int ok = lfs_stat(&vmp->fs.littlefs.instance, path, &info);
switch (type) { if (ok < 0) {
case VFS_CREATE_DIR: spinlock_release(&vmp->spinlock);
CHECK(lfs_mkdir(&fs->instance, path)); return E_BADIO;
break; }
case VFS_CREATE_FILE: {
lfs_file_t file; if (info.type == LFS_TYPE_REG) {
CHECK(lfs_file_open(&fs->instance, &file, path, LFS_O_CREAT | LFS_O_WRONLY)); statbuf->type = IOCTLSTAT_FILE;
CHECK(lfs_file_close(&fs->instance, &file)); statbuf->size = info.size;
} break; } else if (info.type == LFS_TYPE_DIR) {
statbuf->type = IOCTLSTAT_DIR;
statbuf->size = 0;
// TODO: find a better way than this... !!!
lfs_dir_t dir;
ok = lfs_dir_open(&vmp->fs.littlefs.instance, &dir, path);
if (ok < 0) {
spinlock_release(&vmp->spinlock);
return E_BADIO;
}
struct lfs_info info2;
while (lfs_dir_read(&vmp->fs.littlefs.instance, &dir, &info2) > 0) {
statbuf->size++;
}
lfs_dir_close(&vmp->fs.littlefs.instance, &dir);
} }
spinlock_release(&vmp->spinlock); spinlock_release(&vmp->spinlock);
return E_OK; return E_OK;
bad:
spinlock_release(&vmp->spinlock);
return E_GENERIC_ERROR;
} }
bool littlefs_check(void) { int32_t littlefs_mkdir(struct VfsMountPoint *vmp, const char *path) {
return true; spinlock_acquire(&vmp->spinlock);
int ok = lfs_mkdir(&vmp->fs.littlefs.instance, path);
spinlock_release(&vmp->spinlock);
if (ok < 0) {
return E_BADIO;
}
return E_OK;
}
struct VfsObj *littlefs_open(struct VfsMountPoint *vmp, const char *path, uint32_t flags) {
VfsObj *vobj = dlmalloc(sizeof(*vobj));
if (vobj == NULL) {
return NULL;
}
hal_memset(vobj, 0, sizeof(*vobj));
spinlock_init(&vobj->spinlock);
int lfs_flags = 0;
lfs_file_t *file = dlmalloc(sizeof(*file));
if (file == NULL) {
dlfree(vobj);
return NULL;
}
spinlock_acquire(&vmp->spinlock);
LittleFs *fs = &vmp->fs.littlefs;
if (flags & VFS_FLAG_MAKE) {
lfs_flags |= LFS_O_CREAT;
}
if (flags == VFS_FLAG_READ) {
lfs_flags |= LFS_O_RDONLY;
} else if (flags == VFS_FLAG_WRITE) {
lfs_flags |= LFS_O_WRONLY;
} else if ((flags & VFS_FLAG_READ) && (flags & VFS_FLAG_WRITE)) {
lfs_flags |= LFS_O_RDWR;
}
int ok = lfs_file_open(&fs->instance, file, path, lfs_flags);
if (ok < 0) {
dlfree(vobj);
dlfree(file);
spinlock_release(&vmp->spinlock);
return NULL;
}
vobj->flags = flags;
vobj->extra = file;
vobj->extrasize = sizeof(*file);
vobj->vmp = vmp;
vobj->cleanup = &littlefs_vobj_cleanup;
vobj->read = &littlefs_vobj_read;
vobj->write = &littlefs_vobj_write;
hal_strcpy(vobj->path, path);
spinlock_release(&vmp->spinlock);
return vobj;
}
int32_t littlefs_fetchdirent(struct VfsMountPoint *vmp, const char *path, IoctlDirent *direntbuf, size_t idx) {
size_t i = 0;
struct lfs_info statinfo;
int ok;
spinlock_acquire(&vmp->spinlock);
ok = lfs_stat(&vmp->fs.littlefs.instance, path, &statinfo);
if (ok < 0) {
spinlock_release(&vmp->spinlock);
return E_BADIO;
}
if (statinfo.type != LFS_TYPE_DIR) {
spinlock_release(&vmp->spinlock);
return E_BADIO;
}
lfs_dir_t dir;
ok = lfs_dir_open(&vmp->fs.littlefs.instance, &dir, path);
if (ok < 0) {
spinlock_release(&vmp->spinlock);
return E_BADIO;
}
struct lfs_info entinfo;
while (lfs_dir_read(&vmp->fs.littlefs.instance, &dir, &entinfo) > 0) {
if (i == idx) {
if (entinfo.type == LFS_TYPE_REG) {
direntbuf->stat.type = IOCTLSTAT_FILE;
direntbuf->stat.size = entinfo.size;
} else if (entinfo.type == LFS_TYPE_DIR) {
direntbuf->stat.type = IOCTLSTAT_DIR;
}
hal_memcpy(direntbuf->name, entinfo.name, sizeof(direntbuf->name));
break;
}
i++;
}
lfs_dir_close(&vmp->fs.littlefs.instance, &dir);
spinlock_release(&vmp->spinlock);
return E_OK;
} }
int portlfs_read(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size) { int portlfs_read(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size) {
@ -119,3 +239,4 @@ int portlfs_sync(const struct lfs_config *c) {
(void)c; (void)c;
return 0; return 0;
} }

View File

@ -4,21 +4,22 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "fs/littlefs/lfs.h" #include "fs/littlefs/lfs.h"
#include "sysdefs/ioctl.h"
#define LITTLEFS_BLOCK_SIZE 4096 #define LITTLEFS_BLOCK_SIZE 4096
struct VfsMountPoint; struct VfsMountPoint;
struct VfsObj;
typedef struct { typedef struct {
lfs_t instance; lfs_t instance;
} LittleFs; } LittleFs;
int32_t littlefs_read(struct VfsMountPoint *vmp, const char *path, uint8_t *const buffer, size_t n, size_t off);
int32_t littlefs_write(struct VfsMountPoint *vmp, const char *path, const uint8_t *const buffer, size_t n, size_t off);
int32_t littlefs_remove(struct VfsMountPoint *vmp, const char *path);
int32_t littlefs_create(struct VfsMountPoint *vmp, const char *path, int32_t type);
int32_t littlefs_cleanup(struct VfsMountPoint *vmp); int32_t littlefs_cleanup(struct VfsMountPoint *vmp);
bool littlefs_check(void); struct VfsObj *littlefs_open(struct VfsMountPoint *vmp, const char *path, uint32_t flags);
int32_t littlefs_stat(struct VfsMountPoint *vmp, const char *path, IoctlStat *statbuf);
int32_t littlefs_fetchdirent(struct VfsMountPoint *vmp, const char *path, IoctlDirent *direntbuf, size_t idx);
int32_t littlefs_mkdir(struct VfsMountPoint *vmp, const char *path);
int portlfs_read(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size); int portlfs_read(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size);
int portlfs_prog(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size); int portlfs_prog(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size);

View File

@ -18,9 +18,14 @@ size_t hal_strcspn(const char *s, const char *reject);
size_t hal_strspn(const char *s, const char *accept); size_t hal_strspn(const char *s, const char *accept);
char *hal_strcpy(char *dest, const char *src); char *hal_strcpy(char *dest, const char *src);
char *hal_strchr(const char *s, int c); char *hal_strchr(const char *s, int c);
void hal_wait(uint32_t ms);
#if defined(__x86_64__) #define HAL_PAGE_SIZE 0x1000
# define HAL_PAGE_SIZE 0x1000 #include "x86_64/vmm.h"
#endif #include "x86_64/switch.h"
#include "x86_64/paging.h"
#include "x86_64/intr.h"
#include "x86_64/io.h"
#include "x86_64/gdt.h"
#endif // KERNEL_HAL_HAL_H_ #endif // KERNEL_HAL_HAL_H_

View File

@ -2,8 +2,13 @@
#include <stddef.h> #include <stddef.h>
#include "compiler/attr.h" #include "compiler/attr.h"
#include "hal/hal.h" #include "hal/hal.h"
#include "gdt.h"
#define GDT_SIZE 5 #define GDT_PRESENT 0x80
#define GDT_TSS 0x89
#define KSTACK (1024*2*4096)
ALIGNED(16) static uint8_t kernelstack[KSTACK];
typedef struct { typedef struct {
uint16_t limitlow; uint16_t limitlow;
@ -25,70 +30,63 @@ typedef struct {
GdtEntry tsshigh; GdtEntry tsshigh;
} PACKED ExtendedGdt; } PACKED ExtendedGdt;
typedef struct { ALIGNED(16) Tss tss = {0};
uint32_t resv0; ALIGNED(16) static ExtendedGdt gdt = {0};
uint64_t rsp0;
uint64_t rsp1;
uint64_t rsp2;
uint64_t resv1;
uint64_t ist[7];
uint64_t resv2;
uint16_t resv3;
uint16_t iopb_off;
} PACKED Tss;
static Tss tss = {0}; void gdt_setentry(GdtEntry *ent, uint32_t base, uint32_t limit, uint8_t acc, uint8_t gran) {
static ExtendedGdt *curgdt = NULL; ent->baselow = base & 0xffff;
ent->basemid = (base >> 16) & 0xff;
#define KCODE 0x08 ent->basehigh = (base >> 24) & 0xff;
#define KDATA 0x10 ent->limitlow = limit & 0xffff;
#define UCODE 0x18 ent->gran = ((limit >> 16) & 0x0f) | (gran & 0xf0);
#define UDATA 0x20 ent->access = acc;
#define TSS 0x28
#define GDT_PRESENT 0x80
#define GDT_TSS 0x89
static uint64_t gdt_curretbase(void) {
GdtPtr gdtr;
asm volatile("sgdt %0" : "=m"(gdtr));
return gdtr.base;
}
void gdt_setentry(GdtEntry *entry, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran) {
entry->baselow = base & 0xffff;
entry->basemid = (base >> 16) & 0xff;
entry->basehigh = (base >> 24) & 0xff;
entry->limitlow = limit & 0xffff;
entry->gran = ((limit >> 16) & 0x0f) | (gran & 0xf0);
entry->access = access;
} }
void gdt_init(void) { void gdt_init(void) {
uint64_t base = gdt_curretbase();
curgdt = (ExtendedGdt *)base;
hal_memset(&tss, 0, sizeof(tss)); hal_memset(&tss, 0, sizeof(tss));
tss.iopb_off = sizeof(tss); tss.iopb_off = sizeof(tss);
tss.rsp0 = (uint64_t)(kernelstack + sizeof(kernelstack));
uint64_t tss_base = (uint64_t)&tss; uint64_t tss_base = (uint64_t)&tss;
uint32_t tss_limit = sizeof(tss) - 1; uint32_t tss_limit = sizeof(tss) - 1;
gdt_setentry(&curgdt->tsslow, tss_base & 0xFFFFFFFF, tss_limit, GDT_PRESENT | GDT_TSS, 0x0); gdt_setentry(&gdt.old[0], 0, 0, 0, 0);
gdt_setentry(&gdt.old[1], 0, 0xFFFFF, 0x9a, 0xA0);
gdt_setentry(&gdt.old[2], 0, 0xFFFFF, 0x92, 0xC0);
gdt_setentry(&gdt.old[3], 0, 0xFFFFF, 0xfa, 0xA0);
gdt_setentry(&gdt.old[4], 0, 0xFFFFF, 0xf2, 0xC0);
GdtEntry *tsshigh = &curgdt->tsshigh; gdt_setentry(&gdt.tsslow, tss_base & 0xFFFFFFFF, tss_limit, GDT_PRESENT | GDT_TSS, 0x0);
tsshigh->baselow = (tss_base >> 32) & 0xffff;
tsshigh->basemid = (tss_base >> 48) & 0xff; uint32_t tssbasehi = tss_base >> 32;
tsshigh->basehigh = (tss_base >> 56) & 0xff; gdt.tsshigh.limitlow = tssbasehi & 0xffff;
tsshigh->access = 0; gdt.tsshigh.baselow = (tssbasehi >> 16) & 0xffff;
tsshigh->gran = 0; gdt.tsshigh.basemid = 0;
tsshigh->limitlow = 0; gdt.tsshigh.basehigh = 0;
gdt.tsshigh.access = 0;
gdt.tsshigh.gran = 0;
GdtPtr gdtr; GdtPtr gdtr;
asm volatile("sgdt %0" : "=m"(gdtr)); gdtr.limit = sizeof(gdt) - 1;
gdtr.limit = sizeof(ExtendedGdt) - 1; gdtr.base = (uint64_t)&gdt;
asm volatile("lgdt %0" :: "m"(gdtr)); asm volatile("lgdt %0" :: "m"(gdtr));
asm volatile("ltr %0" :: "r"((uint16_t)0x28)); asm volatile(
"pushq %[kcode]\n"
"lea 1f(%%rip), %%rax\n"
"pushq %%rax\n"
"lretq\n"
"1:\n"
"movw %[kdata], %%ax\n"
"movw %%ax, %%ds\n"
"movw %%ax, %%es\n"
"movw %%ax, %%ss\n"
:
: [kcode] "i"(KCODE), [kdata] "i"(KDATA)
: "rax", "memory"
);
asm volatile("ltr %0" :: "r"((uint16_t)TSS));
} }

View File

@ -1,6 +1,26 @@
#ifndef HAL_GDT_H_ #ifndef HAL_GDT_H_
#define HAL_GDT_H_ #define HAL_GDT_H_
#define KCODE 0x08
#define KDATA 0x10
#define UCODE 0x18
#define UDATA 0x20
#define TSS 0x28
typedef struct {
uint32_t resv0;
uint64_t rsp0;
uint64_t rsp1;
uint64_t rsp2;
uint64_t resv1;
uint64_t ist[7];
uint64_t resv2;
uint16_t resv3;
uint16_t iopb_off;
} PACKED Tss;
ALIGNED(16) extern Tss tss;
void gdt_init(void); void gdt_init(void);
#endif // HAL_GDT_H_ #endif // HAL_GDT_H_

View File

@ -2,17 +2,17 @@
#include <stdbool.h> #include <stdbool.h>
#include "hal/hal.h" #include "hal/hal.h"
#include "kprintf.h" #include "kprintf.h"
#include "serial.h"
#include "gdt.h" #include "gdt.h"
#include "idt.h" #include "intr.h"
#include "pic.h"
#include "pit.h"
void hal_init(void) { void hal_init(void) {
if (!serial_init()) {
hal_hang(); // going further makes no sense
}
LOG("hal", "serial init\n");
gdt_init(); gdt_init();
idt_init(); intr_init();
pic_init();
pit_init();
hal_intr_disable();
} }
__attribute__((noreturn)) void hal_hang(void) { __attribute__((noreturn)) void hal_hang(void) {
@ -21,3 +21,7 @@ __attribute__((noreturn)) void hal_hang(void) {
} }
} }
void hal_wait(uint32_t ms) {
pit_wait(ms);
}

View File

@ -1,25 +0,0 @@
#include <stdint.h>
#include "idt.h"
#include "kprintf.h"
#define ENTRIES 256
static IdtGate idtgates[ENTRIES] = {0};
static Idt idt;
void idt_setgate(int i, uint64_t handler, uint8_t flags) {
idtgates[i].isrlow = (uint16_t)handler;
idtgates[i].kernelcs = 40;
idtgates[i].ist = 0;
idtgates[i].resv = 0;
idtgates[i].attrs = flags;
idtgates[i].isrmid = (uint16_t)(handler >> 16);
idtgates[i].isrhigh = (uint16_t)(handler >> 32);
}
void idt_init(void) {
idt.base = (uint64_t)&idtgates;
idt.limit = ENTRIES * sizeof(IdtGate) - 1;
asm volatile("lidt %0" :: "m"(idt) : "memory");
LOG("idt", "idt init\n");
}

View File

@ -1,24 +0,0 @@
#ifndef HAL_IDT_H_
#define HAL_IDT_H_
#include <stdint.h>
#include "compiler/attr.h"
typedef struct {
uint16_t isrlow;
uint16_t kernelcs;
uint8_t ist;
uint8_t attrs;
uint16_t isrmid;
uint32_t isrhigh;
uint32_t resv;
} PACKED IdtGate;
typedef struct {
uint16_t limit;
uint64_t base;
} PACKED Idt;
void idt_init(void);
#endif // HAL_IDT_H_

View File

@ -1,9 +0,0 @@
.global hal_intr_enable
hal_intr_enable:
sti
ret
.global hal_intr_disable
hal_intr_disable:
cli
ret

243
kernel/hal/x86_64/intr.c Normal file
View File

@ -0,0 +1,243 @@
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include "intr.h"
#include "io.h"
#include "gdt.h"
#include "hal/hal.h"
#include "kprintf.h"
#include "compiler/attr.h"
#include "pic.h"
#include "pit.h"
#include "proc/proc.h"
#include "syscall/syscall.h"
#include "errors.h"
#include "ipc/pipe/pipe.h"
#include "rbuf/rbuf.h"
#include "dlmalloc/malloc.h"
#include "util/util.h"
typedef struct IntrHandler {
struct IntrHandler *next;
void (*fn)(void);
int irq;
} IntrHandler;
IntrHandler *INTR_HANDLERS = NULL;
void intr_attchhandler(void (*fn)(void), int irq) {
IntrHandler *ih = dlmalloc(sizeof(*ih));
ih->fn = fn;
ih->irq = irq;
LL_APPEND(INTR_HANDLERS, ih);
}
typedef struct BackTraceFrame {
struct BackTraceFrame *rbp;
uint64_t rip;
} BackTraceFrame;
void backtrace(BackTraceFrame *bt) {
kprintf("Backtrace:\n");
for (size_t frame = 0; bt; frame++) {
kprintf(" %zu: 0x%lx\n", frame, bt->rip);
bt = bt->rbp;
}
}
void hal_intr_disable(void) {
asm volatile("cli");
}
void hal_intr_enable(void) {
asm volatile("sti");
}
typedef struct {
uint16_t intrlow;
uint16_t kernelcs;
uint8_t ist;
uint8_t attrs;
uint16_t intrmid;
uint32_t intrhigh;
uint32_t resv;
} PACKED IdtGate;
typedef struct {
uint16_t limit;
uint64_t base;
} PACKED Idt;
#define ENTRIES 256
ALIGNED(0x10) static IdtGate idtgates[ENTRIES] = {0};
static Idt idt = {0};
void idt_setentry(int i, uint64_t handler, uint8_t flags) {
idtgates[i].intrlow = handler & 0xffff;
idtgates[i].kernelcs = KCODE;
idtgates[i].ist = 0;
idtgates[i].attrs = flags;
idtgates[i].intrmid = (handler >> 16) & 0xFFFF;
idtgates[i].intrhigh = (handler >> 32) & 0xFFFFFFFF;
idtgates[i].resv = 0;
}
void idt_init(void) {
idt.base = (uint64_t)&idtgates;
idt.limit = ENTRIES * sizeof(IdtGate) - 1;
asm volatile("lidt %0" :: "m"(idt) : "memory");
LOG("hal", "idt init\n");
}
extern void *ISR_REDIRTABLE[];
static const char *exceptions[] = {
"#DE", "#DB", "NMI",
"#BP", "#OF", "#BR",
"#UD", "#NM", "#DF",
"CSO", "#TS", "#NP",
"#SS", "#GP", "#PF",
"RES", "#MF", "#AC",
"#MC", "#XM", "#VE",
"#CP",
};
void intr_init(void) {
#define MKINTR(N) \
extern void intr_vec##N(void); \
idt_setentry(N, (uint64_t)&intr_vec##N, 0x8E);
MKINTR(0);
MKINTR(1);
MKINTR(2);
MKINTR(4);
MKINTR(5);
MKINTR(6);
MKINTR(7);
MKINTR(8);
MKINTR(9);
MKINTR(10);
MKINTR(11);
MKINTR(12);
MKINTR(13);
MKINTR(14);
MKINTR(15);
MKINTR(16);
MKINTR(17);
MKINTR(18);
MKINTR(19);
MKINTR(20);
MKINTR(21);
MKINTR(22);
MKINTR(23);
MKINTR(24);
MKINTR(25);
MKINTR(26);
MKINTR(27);
MKINTR(28);
MKINTR(29);
MKINTR(30);
MKINTR(31);
MKINTR(32);
MKINTR(33);
MKINTR(34);
MKINTR(35);
MKINTR(36);
MKINTR(37);
MKINTR(38);
MKINTR(39);
MKINTR(40);
MKINTR(41);
MKINTR(42);
MKINTR(43);
MKINTR(44);
MKINTR(45);
MKINTR(46);
MKINTR(47);
extern void intr_vec128(void);
idt_setentry(0x80, (uint64_t)&intr_vec128, 0xEE);
idt_init();
}
void intr_dumpframe(IntrStackFrame *frame) {
uint64_t cr2;
asm volatile("mov %%cr2, %0" : "=r"(cr2));
uint64_t cr3;
asm volatile("mov %%cr3, %0" : "=r"(cr3));
uint64_t cr4;
asm volatile("mov %%cr4, %0" : "=r"(cr4));
kprintf("rax=%016lx rcx=%016lx rdx=%016lx\n"
"rsi=%016lx rdi=%016lx r8 =%016lx\n"
"r9 =%016lx r10=%016lx r11=%016lx\n"
"rip=%016lx rfl=%016lx rsp=%016lx\n"
"cs =%016lx ss =%016lx trp=%016lx\n"
"cr2=%016lx cr3=%016lx cr4=%016lx\n"
"\n\n",
frame->regs.rax, frame->regs.rcx, frame->regs.rdx,
frame->regs.rsi, frame->regs.rdi, frame->regs.r8,
frame->regs.r9, frame->regs.r10, frame->regs.r11,
frame->rip, frame->rflags, frame->rsp,
frame->cs, frame->ss, frame->trapnum,
cr2, cr3, cr4
);
}
void hal_syscalldispatch(IntrStackFrame *frame) {
uint64_t sysnum = frame->regs.rax;
if (sysnum < SYSCALLS_MAX) {
SyscallFn fn = SYSCALL_TABLE[sysnum];
if (fn == NULL) {
frame->regs.rax = E_BADSYSCALL;
return;
}
int32_t ret = fn(frame, frame->regs.rdi, frame->regs.rsi, frame->regs.rdx,
frame->regs.r10, frame->regs.r8, frame->regs.r9);
if (ret == E_DOSCHEDULING) {
proc_sched((void *)frame);
}
frame->regs.rax = *(uint64_t *)&ret;
}
}
void intr_eoi() {
io_out8(PIC2_CMD, PIC_EOI);
io_out8(PIC1_CMD, PIC_EOI);
}
void intr_handleintr(IntrStackFrame *frame) {
if (frame->trapnum <= 31) {
kprintf("ERROR %s, 0x%lX\n", exceptions[frame->trapnum], frame->errnum);
intr_dumpframe(frame);
backtrace((BackTraceFrame *)frame->regs.rbp);
if (hal_vmm_current_cr3() != KERNEL_CR3) {
kprintf("killed pid %ld %s\n", PROCS.current->pid, PROCS.current->name);
proc_killself();
proc_sched((void *)frame);
}
hal_hang();
} else if (frame->trapnum >= 32 && frame->trapnum <= 47) {
switch (frame->trapnum) {
case INTR_IRQBASE+0:
PIT_TICKS++;
intr_eoi();
proc_sched((void *)frame);
break;
default:
IntrHandler *ih, *ihtmp;
LL_FOREACH_SAFE(INTR_HANDLERS, ih, ihtmp) {
if (ih->irq == frame->trapnum) {
ih->fn();
}
}
intr_eoi();
break;
}
} else if (frame->trapnum == 0x80) {
hal_syscalldispatch(frame);
}
}

39
kernel/hal/x86_64/intr.h Normal file
View File

@ -0,0 +1,39 @@
#ifndef HAL_INTR_H_
#define HAL_INTR_H_
#define INTR_IRQBASE 0x20
#include "compiler/attr.h"
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 rbp;
uint64_t rdi;
uint64_t rsi;
uint64_t rdx;
uint64_t rcx;
uint64_t rax;
} PACKED SavedRegs;
typedef struct {
SavedRegs regs;
uint64_t trapnum;
uint64_t errnum;
uint64_t rip;
uint64_t cs;
uint64_t rflags;
uint64_t rsp;
uint64_t ss;
} PACKED IntrStackFrame;
void intr_attchhandler(void (*fn)(void), int irq);
void intr_init(void);
#endif // HAL_INTR_H_

221
kernel/hal/x86_64/intr0.S Normal file
View File

@ -0,0 +1,221 @@
#include "regs.S"
.extern intr_handleintr
.global intr_vec0
.global intr_vec1
.global intr_vec2
.global intr_vec3
.global intr_vec4
.global intr_vec5
.global intr_vec6
.global intr_vec7
.global intr_vec8
.global intr_vec9
.global intr_vec10
.global intr_vec11
.global intr_vec12
.global intr_vec13
.global intr_vec14
.global intr_vec15
.global intr_vec16
.global intr_vec17
.global intr_vec18
.global intr_vec19
.global intr_vec20
.global intr_vec21
.global intr_vec22
.global intr_vec23
.global intr_vec24
.global intr_vec25
.global intr_vec26
.global intr_vec27
.global intr_vec28
.global intr_vec29
.global intr_vec30
.global intr_vec31
.global intr_vec32
.global intr_vec33
.global intr_vec34
.global intr_vec35
.global intr_vec36
.global intr_vec37
.global intr_vec38
.global intr_vec39
.global intr_vec40
.global intr_vec41
.global intr_vec42
.global intr_vec43
.global intr_vec44
.global intr_vec45
.global intr_vec46
.global intr_vec47
.global intr_vec128
.macro _vecintr_errorcode_present_save num
pushq $\num
.endm
.macro _vecintr_plain_save num
pushq $0x0
pushq $\num
.endm
.macro _vecintr_bodygen
cli
_push_regs
cld
movq %rsp, %rdi
call intr_handleintr
_pop_regs
add $0x10, %rsp
iretq
.endm
intr_vec0:
_vecintr_plain_save 0
_vecintr_bodygen
intr_vec1:
_vecintr_plain_save 1
_vecintr_bodygen
intr_vec2:
_vecintr_plain_save 2
_vecintr_bodygen
intr_vec3:
_vecintr_plain_save 3
_vecintr_bodygen
intr_vec4:
_vecintr_plain_save 4
_vecintr_bodygen
intr_vec5:
_vecintr_plain_save 5
_vecintr_bodygen
intr_vec6:
_vecintr_plain_save 6
_vecintr_bodygen
intr_vec7:
_vecintr_plain_save 7
_vecintr_bodygen
intr_vec8:
_vecintr_errorcode_present_save 8
_vecintr_bodygen
intr_vec9:
_vecintr_plain_save 9
_vecintr_bodygen
intr_vec10:
_vecintr_errorcode_present_save 10
_vecintr_bodygen
intr_vec11:
_vecintr_errorcode_present_save 11
_vecintr_bodygen
intr_vec12:
_vecintr_errorcode_present_save 12
_vecintr_bodygen
intr_vec13:
_vecintr_errorcode_present_save 13
_vecintr_bodygen
intr_vec14:
_vecintr_errorcode_present_save 14
_vecintr_bodygen
intr_vec15:
_vecintr_plain_save 15
_vecintr_bodygen
intr_vec16:
_vecintr_plain_save 16
_vecintr_bodygen
intr_vec17:
_vecintr_errorcode_present_save 17
_vecintr_bodygen
intr_vec18:
_vecintr_plain_save 18
_vecintr_bodygen
intr_vec19:
_vecintr_plain_save 19
_vecintr_bodygen
intr_vec20:
_vecintr_plain_save 20
_vecintr_bodygen
intr_vec21:
_vecintr_errorcode_present_save 21
_vecintr_bodygen
intr_vec22:
_vecintr_plain_save 22
_vecintr_bodygen
intr_vec23:
_vecintr_plain_save 23
_vecintr_bodygen
intr_vec24:
_vecintr_plain_save 24
_vecintr_bodygen
intr_vec25:
_vecintr_plain_save 25
_vecintr_bodygen
intr_vec26:
_vecintr_plain_save 26
_vecintr_bodygen
intr_vec27:
_vecintr_plain_save 27
_vecintr_bodygen
intr_vec28:
_vecintr_plain_save 28
_vecintr_bodygen
intr_vec29:
_vecintr_errorcode_present_save 29
_vecintr_bodygen
intr_vec30:
_vecintr_errorcode_present_save 30
_vecintr_bodygen
intr_vec31:
_vecintr_plain_save 31
_vecintr_bodygen
intr_vec32:
_vecintr_plain_save 32
_vecintr_bodygen
intr_vec33:
_vecintr_plain_save 33
_vecintr_bodygen
intr_vec34:
_vecintr_plain_save 34
_vecintr_bodygen
intr_vec35:
_vecintr_plain_save 35
_vecintr_bodygen
intr_vec36:
_vecintr_plain_save 36
_vecintr_bodygen
intr_vec37:
_vecintr_plain_save 37
_vecintr_bodygen
intr_vec38:
_vecintr_plain_save 38
_vecintr_bodygen
intr_vec39:
_vecintr_plain_save 39
_vecintr_bodygen
intr_vec40:
_vecintr_plain_save 40
_vecintr_bodygen
intr_vec41:
_vecintr_plain_save 41
_vecintr_bodygen
intr_vec42:
_vecintr_plain_save 42
_vecintr_bodygen
intr_vec43:
_vecintr_plain_save 43
_vecintr_bodygen
intr_vec44:
_vecintr_plain_save 44
_vecintr_bodygen
intr_vec45:
_vecintr_plain_save 45
_vecintr_bodygen
intr_vec46:
_vecintr_plain_save 46
_vecintr_bodygen
intr_vec47:
_vecintr_plain_save 47
_vecintr_bodygen
intr_vec128:
_vecintr_plain_save 128
_vecintr_bodygen

View File

@ -1,13 +0,0 @@
.global io_outb
io_outb:
mov %di, %dx
mov %sil, %al
out %al, %dx
ret
.global io_inb
io_inb:
mov %di, %dx
in %dx, %al
movzx %al, %rax
ret

28
kernel/hal/x86_64/io.c Normal file
View File

@ -0,0 +1,28 @@
#include <stdint.h>
uint8_t io_in8(uint16_t port) {
uint8_t r;
asm volatile("inb %1, %0" : "=a"(r) : "dN"(port));
return r;
}
void io_out8(uint16_t port, uint8_t value) {
asm volatile("outb %1, %0" :: "dN"(port), "a"(value));
}
uint16_t io_in16(uint16_t port) {
uint16_t r;
asm volatile("in %%dx, %%ax" : "=a"(r) : "d"(port));
return r;
}
void io_out16(uint16_t port, uint16_t value) {
asm volatile("out %%ax, %%dx" :: "a"(value), "d"(port));
}
uint32_t io_in32(uint16_t port) {
uint32_t r;
asm volatile("inl %%dx, %%eax" : "=a"(r) : "d"(port));
return r;
}
void io_out32(uint16_t port, uint32_t value) {
asm volatile("outl %%eax, %%dx" :: "d"(port), "a"(value));
}

View File

@ -1,7 +1,15 @@
#ifndef HAL_IO_H_ #ifndef HAL_IO_H_
#define HAL_IO_H_ #define HAL_IO_H_
extern uint8_t io_inb(uint16_t port); #include <stdint.h>
extern void io_outb(uint16_t port, uint8_t value);
uint8_t io_in8(uint16_t port);
void io_out8(uint16_t port, uint8_t value);
uint16_t io_in16(uint16_t port);
void io_out16(uint16_t port, uint16_t value);
uint32_t io_in32(uint16_t port);
void io_out32(uint16_t port, uint32_t value);
#endif // HAL_IO_H_ #endif // HAL_IO_H_

View File

@ -0,0 +1,4 @@
.global hal_loadpd
hal_loadpd:
mov %rdi, %cr3
retq

View File

@ -0,0 +1,6 @@
#ifndef HAL_PAGING_H_
#define HAL_PAGING_H_
void hal_loadpd(PgTable *cr3);
#endif // HAL_PAGING_H_

22
kernel/hal/x86_64/pic.c Normal file
View File

@ -0,0 +1,22 @@
#include <stddef.h>
#include <stdint.h>
#include "pic.h"
#include "io.h"
#include "intr.h"
void pic_init(void) {
io_out8(PIC1_CMD, ICW1_INIT | ICW1_ICW4);
io_out8(PIC2_CMD, ICW1_INIT | ICW1_ICW4);
io_out8(PIC1_DATA, INTR_IRQBASE);
io_out8(PIC2_DATA, INTR_IRQBASE+8);
io_out8(PIC1_DATA, 2);
io_out8(PIC2_DATA, 2);
io_out8(PIC1_DATA, ICW4_8086);
io_out8(PIC2_DATA, ICW4_8086);
io_out8(PIC1_DATA, 0);
io_out8(PIC2_DATA, 0);
}

25
kernel/hal/x86_64/pic.h Normal file
View File

@ -0,0 +1,25 @@
#ifndef HAL_PIC_H_
#define HAL_PIC_H_
#define PIC1_CMD 0x0020
#define PIC1_DATA 0x0021
#define PIC2_CMD 0x00A0
#define PIC2_DATA 0x00A1
#define PIC_EOI 0x20
#define ICW1_ICW4 0x01
#define ICW1_SINGLE 0x02
#define ICW1_ADI 0x04
#define ICW1_LTIM 0x08
#define ICW1_INIT 0x10
#define ICW4_8086 0x01
#define ICW4_AUTO 0x02
#define ICW4_BUFSLAVE 0x04
#define ICW4_BUFMASTER 0x0C
#define ICW4_SFNM 0x10
void pic_init(void);
#endif // HAL_PIC_H_

40
kernel/hal/x86_64/pit.c Normal file
View File

@ -0,0 +1,40 @@
#include <stdint.h>
#include "pit.h"
#include "io.h"
#define PIT_COUNTER0 0x40
#define PIT_CMD 0x43
#define PIT_CMD_BINARY 0x00
#define PIT_CMD_BCD 0x01
#define PIT_CMD_MODE0 0x00
#define PIT_CMD_MODE1 0x02
#define PIT_CMD_MODE2 0x04
#define PIT_CMD_MODE3 0x06
#define PIT_CMD_MODE4 0x08
#define PIT_CMD_MODE5 0x0A
#define PIT_CMD_LATCH 0x00
#define PIT_CMD_RW_LOW 0x10
#define PIT_CMD_RW_HI 0x20
#define PIT_CMD_RW_BOTH 0x30
#define PIT_CMD_COUNTER0 0x00
#define PIT_CMD_COUNTER1 0x40
#define PIT_CMD_COUNTER2 0x80
#define PIT_CMD_READBACK 0xC0
#define PIT_FREQ 1193182
volatile uint32_t PIT_TICKS;
void pit_init(void) {
uint32_t hz = 1000;
uint32_t div = PIT_FREQ / hz;
io_out8(PIT_CMD, PIT_CMD_BINARY | PIT_CMD_MODE3 | PIT_CMD_RW_BOTH | PIT_CMD_COUNTER0);
io_out8(PIT_COUNTER0, div);
io_out8(PIT_COUNTER0, div >> 8);
}
void pit_wait(uint32_t ms) {
uint32_t now = PIT_TICKS;
++ms;
while (PIT_TICKS - now < ms);
}

11
kernel/hal/x86_64/pit.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef HAL_PIT_H_
#define HAL_PIT_H_
#include <stdint.h>
extern volatile uint32_t PIT_TICKS;
void pit_init(void);
void pit_wait(uint32_t ms);
#endif // HAL_PIT_H_

33
kernel/hal/x86_64/regs.S Normal file
View File

@ -0,0 +1,33 @@
.macro _push_regs
push %rax
push %rcx
push %rdx
push %rsi
push %rdi
push %rbp
push %r8
push %r9
push %r10
push %r11
push %r12
push %r13
push %r14
push %r15
.endm
.macro _pop_regs
pop %r15
pop %r14
pop %r13
pop %r12
pop %r11
pop %r10
pop %r9
pop %r8
pop %rbp
pop %rdi
pop %rsi
pop %rdx
pop %rcx
pop %rax
.endm

View File

@ -1,51 +0,0 @@
#include <stdint.h>
#include <stdbool.h>
#include "io.h"
#include "putchar.h"
#define SERIAL_PORT 0x3f8
static int serial_received(void) {
return io_inb(SERIAL_PORT + 5) & 1;
}
static uint8_t serial_read(void) {
while (serial_received() == 0);
return io_inb(SERIAL_PORT);
}
static int serial_trans_empty(void) {
return io_inb(SERIAL_PORT + 5) & 0x20;
}
static void serial_write(uint8_t value) {
while (!serial_trans_empty());
io_outb(SERIAL_PORT, value);
}
// REFERENCE: https://wiki.osdev.org/Serial_Ports
bool serial_init(void) {
io_outb(SERIAL_PORT + 1, 0x00);
io_outb(SERIAL_PORT + 3, 0x80);
io_outb(SERIAL_PORT + 0, 0x03);
io_outb(SERIAL_PORT + 1, 0x00);
io_outb(SERIAL_PORT + 3, 0x03);
io_outb(SERIAL_PORT + 2, 0xc7);
io_outb(SERIAL_PORT + 4, 0x0b);
io_outb(SERIAL_PORT + 4, 0x1e);
io_outb(SERIAL_PORT + 0, 0xae);
if (io_inb(SERIAL_PORT + 0) != 0xae) {
return false;
}
io_outb(SERIAL_PORT + 4, 0x0f);
return true;
}
#if PUTCHAR_ == PUTCHAR_SERIAL
// For printf library
void putchar_(char c) {
serial_write(c);
}
#endif

View File

@ -1,8 +0,0 @@
#ifndef HAL_SERIAL_H_
#define HAL_SERIAL_H_
#include <stdbool.h>
bool serial_init(void);
#endif // HAL_SERIAL_H_

View File

@ -0,0 +1,12 @@
#include "regs.S"
.global hal_switchproc
hal_switchproc:
testq %rsi, %rsi
je 1f
movq %rsi, %cr3
1:
mov %rdi, %rsp
_pop_regs
add $0x10, %rsp
iretq

View File

@ -0,0 +1,6 @@
#ifndef HAL_SWITCH_H_
#define HAL_SWITCH_H_
extern void hal_switchproc(void *newsp, PgTable *cr3);
#endif // HAL_SWITCH_H_

129
kernel/hal/x86_64/vmm.c Normal file
View File

@ -0,0 +1,129 @@
#include <stddef.h>
#include <stdint.h>
#include "vmm.h"
#include "hal/hal.h"
#include "bootinfo/bootinfo.h"
#include "pmm/pmm.h"
#include "paging.h"
#include "proc/proc.h"
#include "kprintf.h"
#include "spinlock/spinlock.h"
uint64_t KERNEL_CR3 = 0;
SpinLock spinlock;
uint64_t hal_vmm_current_cr3(void) {
uint64_t cr3;
asm volatile("mov %%cr3, %0" : "=r"(cr3));
return cr3;
}
PgIndex hal_vmm_pageindex(uint64_t vaddr) {
PgIndex ret;
ret.pml4 = (vaddr >> 39) & 0x1ff;
ret.pml3 = (vaddr >> 30) & 0x1ff;
ret.pml2 = (vaddr >> 21) & 0x1ff;
ret.pml1 = (vaddr >> 12) & 0x1ff;
return ret;
}
uint64_t *hal_vmm_nexttable(uint64_t *table, uint64_t ent, bool alloc) {
uint64_t entry = table[ent];
uint64_t phys;
if (entry & HAL_PG_PRESENT) {
phys = entry & ~0xFFFULL;
} else {
if (!alloc) {
return NULL;
}
uint8_t *newphys = pmm_alloc(1);
phys = (uint64_t)newphys;
hal_memset(VIRT(phys), 0, HAL_PAGE_SIZE);
table[ent] = phys | HAL_PG_USER | HAL_PG_RW | HAL_PG_PRESENT;
}
return (uint64_t *)((uint8_t *)VIRT(phys));
}
void hal_vmm_map_page(uint64_t cr3phys, uint64_t virtaddr, uint64_t physaddr, uint32_t flags) {
uint64_t *pml4 = (uint64_t *)VIRT(cr3phys);
PgIndex pi = hal_vmm_pageindex(virtaddr);
uint64_t *pml3 = hal_vmm_nexttable(pml4, pi.pml4, true);
uint64_t *pml2 = hal_vmm_nexttable(pml3, pi.pml3, true);
uint64_t *pml1 = hal_vmm_nexttable(pml2, pi.pml2, true);
uint64_t *pte = &pml1[pi.pml1];
*pte = (physaddr & ~0xFFFULL) | ((uint64_t)flags & 0x7ULL);
}
void hal_vmm_unmap_page(uint64_t cr3phys, uint64_t virtaddr, uint64_t physaddr) {
uint64_t *pml4 = (uint64_t *)VIRT(cr3phys);
PgIndex pi = hal_vmm_pageindex(virtaddr);
uint64_t *pml3 = hal_vmm_nexttable(pml4, pi.pml4, false);
uint64_t *pml2 = hal_vmm_nexttable(pml3, pi.pml3, false);
uint64_t *pml1 = hal_vmm_nexttable(pml2, pi.pml2, false);
uint64_t *pte = &pml1[pi.pml1];
*pte &= ~HAL_PG_PRESENT;
}
void hal_vmm_map_range(uint64_t cr3phys, void *virtstart, void *physstart, size_t size, uint32_t flags) {
if (size % HAL_PAGE_SIZE != 0 || (uint64_t)virtstart % HAL_PAGE_SIZE != 0 || (uint64_t)physstart % HAL_PAGE_SIZE != 0) {
return;
}
spinlock_acquire(&spinlock);
uint8_t *vaddr = (uint8_t *)virtstart;
uint8_t *paddr = (uint8_t *)physstart;
uint8_t *end = (uint8_t *)virtstart + size;
for (; vaddr < end; vaddr += HAL_PAGE_SIZE, paddr += HAL_PAGE_SIZE) {
hal_vmm_map_page(cr3phys, (uint64_t)vaddr, (uint64_t)paddr, flags);
}
spinlock_release(&spinlock);
}
void hal_vmm_unmap_range(uint64_t cr3phys, void *virtstart, void *physstart, size_t size) {
if (size % HAL_PAGE_SIZE != 0 || (uint64_t)virtstart % HAL_PAGE_SIZE != 0 || (uint64_t)physstart % HAL_PAGE_SIZE != 0) {
return;
}
spinlock_acquire(&spinlock);
uint8_t *vaddr = (uint8_t *)virtstart;
uint8_t *paddr = (uint8_t *)physstart;
uint8_t *end = vaddr + size;
for (; vaddr < end; vaddr += HAL_PAGE_SIZE, paddr += HAL_PAGE_SIZE) {
hal_vmm_unmap_page(cr3phys, (uint64_t)vaddr, (uint64_t)paddr);
}
spinlock_release(&spinlock);
}
void hal_vmm_map_kern(uint64_t targetcr3) {
uint64_t *kcr3 = (uint64_t *)VIRT(KERNEL_CR3);
uint64_t *cr3 = (uint64_t *)VIRT(targetcr3);
for (size_t i = 0; i < 512; i++) {
cr3[i] = kcr3[i];
}
}
uint64_t hal_vmm_userproc_pml4_phys(void) {
uint8_t *cr3phys = pmm_alloc(1);
uint64_t phys = (uint64_t)cr3phys;
hal_memset(VIRT(phys), 0, HAL_PAGE_SIZE);
uint64_t *kcr3 = (uint64_t *)VIRT(KERNEL_CR3);
uint64_t *pml4 = (uint64_t *)VIRT(phys);
for (size_t i = 256; i < 512; i++) {
pml4[i] = kcr3[i];
}
return phys;
}
void hal_vmm_init(void) {
spinlock_init(&spinlock);
KERNEL_CR3 = hal_vmm_current_cr3();
}

63
kernel/hal/x86_64/vmm.h Normal file
View File

@ -0,0 +1,63 @@
#ifndef HAL_VMM_H_
#define HAL_VMM_H_
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "compiler/attr.h"
#define VIRT(X) ((void *)(BOOT_INFO.hhdm_off + (uint64_t)(X)))
typedef struct VasRange {
struct VasRange *next;
uint8_t *virtstart;
uint8_t *physstart;
size_t size;
uint8_t pgflags;
} PACKED VasRange;
enum {
HAL_PG_PRESENT = 1<<0,
HAL_PG_RW = 1<<1,
HAL_PG_USER = 1<<2,
};
typedef struct {
uint16_t pml4;
uint16_t pml3;
uint16_t pml2;
uint16_t pml1;
} PACKED PgIndex;
typedef struct {
bool present: 1;
bool rw: 1;
bool user: 1;
bool writethrough: 1;
bool cachedisabled: 1;
bool accessed: 1;
bool dirty: 1;
bool hugepage: 1;
bool global: 1;
uint8_t avail: 3;
uint64_t addr: 40;
uint16_t osdef: 11;
bool nx: 1;
} PACKED Pte;
typedef struct {
Pte ents[512];
} PACKED PgTable;
extern uint64_t KERNEL_CR3;
void hal_vmm_init(void);
void hal_vmm_unmap_page(uint64_t cr3phys, uint64_t virtaddr, uint64_t physaddr);
void hal_vmm_map_page(uint64_t cr3phys, uint64_t virtaddr, uint64_t physaddr, uint32_t flags);
uint64_t hal_vmm_current_cr3(void);
void hal_vmm_map_range(uint64_t cr3phys, void *virtstart, void *physstart, size_t size, uint32_t flags);
void hal_vmm_unmap_range(uint64_t cr3phys, void *virtstart, void *physstart, size_t size);
uint64_t hal_vmm_userproc_pml4_phys();
#endif // HAL_VMM_H_

View File

@ -4,47 +4,85 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "hal/hal.h"
#include "util/util.h"
#define HSHTB_FNV32_BASE 0x811c9dc5 #define HSHTB_FNV32_OFF 0x811c9dc5u
#define HSHTB_FNV32_PRIME 0x01000193u
static inline uint32_t hshtb_fnv32(char *s, size_t len) { static inline uint32_t hshtb_fnv32(const void *data, size_t len) {
uint32_t h = HSHTB_FNV32_BASE; const unsigned char *p = (const unsigned char *)data;
uint32_t h = HSHTB_FNV32_OFF;
for (size_t i = 0; i < len; i++) { for (size_t i = 0; i < len; i++) {
h ^= s[i]; h ^= p[i];
h += (h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24); h *= HSHTB_FNV32_PRIME;
} }
return h >> 8; return h;
} }
#define HSHTB_ALLOC(tb, name, k, keyname, out) \ enum {
HSHTB_EMPTY = 0,
HSHTB_TAKEN = 1,
HSHTB_TOMB = 2,
};
#define __HSHTB_ARRAY_LEN(tb) \
((void)sizeof(struct { int _[!!(sizeof(tb) % sizeof((tb)[0]) == 0)]; }) , (sizeof(tb) / sizeof((tb)[0])))
#define HSHTB_ALLOC(tb, keyfield, k, out) \
do { \ do { \
size_t len = sizeof((tb)->name) / sizeof((tb)->name[0]); \ size_t __len = __HSHTB_ARRAY_LEN(tb); \
size_t idx = hshtb_fnv32(k, hal_strlen(k)) % len; \ uint32_t __h = hshtb_fnv32((k), hal_strlen((k))); \
size_t i = idx; \ size_t __idx = __h % __len; \
size_t __start = __idx; \
typeof(&(tb)[0]) __tomb = NULL; \
(out) = NULL; \
do { \ do { \
if (!(tb)->name[i].taken) { \ if ((tb)[__idx]._hshtbstate == HSHTB_EMPTY) { \
(out) = &((tb)->name[i]); \ typeof(&(tb)[0]) __slot = __tomb ? __tomb : &(tb)[__idx]; \
hal_memset((out), 0, sizeof(*(out))); \ hal_memset(__slot, 0, sizeof(*__slot)); \
(out)->taken = true; \ __slot->_hshtbstate = HSHTB_TAKEN; \
hal_memcpy((out)->keyname, k, hal_strlen(k)); \ hal_memcpy(__slot->keyfield, (k), MIN(sizeof(__slot->keyfield) - 1, hal_strlen((k)))); \
(out) = __slot; \
break; \ break; \
} \ } \
i = (i + 1) % len; \ if ((tb)[__idx]._hshtbstate == HSHTB_TAKEN && hal_strcmp((tb)[__idx].keyfield, (k)) == 0) { \
} while(i != idx); \ (out) = &(tb)[__idx]; \
break; \
} \
if ((tb)[__idx]._hshtbstate == HSHTB_TOMB && !__tomb) { \
__tomb = &(tb)[__idx]; \
} \
__idx = (__idx + 1) % __len; \
} while(__idx != __start); \
} while(0) } while(0)
#define HSHTB_GET(tb, name, k, keyname, out) \ #define HSHTB_GET(tb, keyfield, k, out) \
do { \ do { \
size_t len = sizeof((tb)->name) / sizeof((tb)->name[0]); \ size_t __len = __HSHTB_ARRAY_LEN(tb); \
size_t idx = hshtb_fnv32(k, hal_strlen(k)) % len; \ uint32_t __h = hshtb_fnv32((k), hal_strlen((k))); \
size_t i = idx; \ size_t __idx = __h % __len; \
size_t __start = __idx; \
(out) = NULL; \
do { \ do { \
if (hal_memcmp((tb)->name[i].keyname, k, hal_strlen(k)) == 0) { \ if ((tb)[__idx]._hshtbstate == HSHTB_EMPTY) { \
(out) = &((tb)->name[i]); \
break; \ break; \
} \ } \
i = (i + 1) % len; \ if ((tb)[__idx]._hshtbstate == HSHTB_TAKEN && hal_strcmp((tb)[__idx].keyfield, (k)) == 0) { \
} while(i != idx); \ (out) = &(tb)[__idx]; \
break; \
} \
__idx = (__idx + 1) % __len; \
} while(__idx != __start); \
} while(0)
#define HSHTB_DELETE(tb, keyfield, k) \
do { \
typeof(&(tb)[0]) __e; \
HSHTB_GET((tb), (keyfield), (k), __e); \
if (__e) { \
__e->_hshtbstate = HSHTB_TOMB; \
} \
} while(0) } while(0)
#endif // HSHTB_H_ #endif // HSHTB_H_

53
kernel/ipc/pipe/pipe.c Normal file
View File

@ -0,0 +1,53 @@
#include <stdint.h>
#include <stddef.h>
#include "rbuf/rbuf.h"
#include "spinlock/spinlock.h"
#include "hal/hal.h"
#include "dlmalloc/malloc.h"
#include "errors.h"
#include "pipe.h"
#include "kprintf.h"
int32_t ipc_pipeinit(IpcPipe *pipe, uint64_t pid) {
hal_memset(pipe, 0, sizeof(*pipe));
spinlock_init(&pipe->spinlock);
pipe->ownerpid = pid;
uint8_t *buf = dlmalloc(IPC_PIPE_MAX);
if (buf == NULL) {
return E_NOMEMORY;
}
rbuf_init(&pipe->rbuf, buf, IPC_PIPE_MAX);
return E_OK;
}
void ipc_pipefree(IpcPipe *pipe) {
if (pipe->rbuf.buffer != NULL) {
dlfree(pipe->rbuf.buffer);
}
}
int32_t ipc_pipewrite(IpcPipe *pipe, const uint8_t *const buffer, size_t n) {
size_t i = 0;
spinlock_acquire(&pipe->spinlock);
for (; i < n; i++) {
rbuf_push(&pipe->rbuf, buffer[i]);
}
spinlock_release(&pipe->spinlock);
return i;
}
int32_t ipc_piperead(IpcPipe *pipe, uint8_t *const buffer, size_t n) {
size_t i = 0;
spinlock_acquire(&pipe->spinlock);
while (i < n) {
if (rbuf_pop(&pipe->rbuf, &buffer[i]) < 0) {
break;
}
i++;
}
spinlock_release(&pipe->spinlock);
return i;
}

23
kernel/ipc/pipe/pipe.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef IPC_PIPE_PIPE_H_
#define IPC_PIPE_PIPE_H_
#include <stdint.h>
#include <stddef.h>
#include "rbuf/rbuf.h"
#include "spinlock/spinlock.h"
#define IPC_PIPE_MAX 0x1000
typedef struct IpcPipe {
struct IpcPipe *next;
RBuf rbuf;
SpinLock spinlock;
uint64_t ownerpid;
} IpcPipe;
int32_t ipc_pipeinit(IpcPipe *pipe, uint64_t pid);
void ipc_pipefree(IpcPipe *pipe);
int32_t ipc_pipewrite(IpcPipe *pipe, const uint8_t *const buffer, size_t n);
int32_t ipc_piperead(IpcPipe *pipe, uint8_t *const buffer, size_t n);
#endif // IPC_PIPE_PIPE_H_

View File

@ -5,11 +5,49 @@
#include "bootinfo/bootinfo.h" #include "bootinfo/bootinfo.h"
#include "pmm/pmm.h" #include "pmm/pmm.h"
#include "term/term.h" #include "term/term.h"
#include "paging/paging.h"
#include "dlmalloc/malloc.h" #include "dlmalloc/malloc.h"
#include "vfs/vfs.h" #include "vfs/vfs.h"
#include "baseimg/baseimg.h" #include "baseimg/baseimg.h"
#include "storedev/storedev.h" #include "storedev/storedev.h"
#include "util/util.h"
#include "proc/proc.h"
#include "dev/dev.h"
const char *human_size(uint64_t bytes, char *buf, size_t bufsize) {
static const char *units[] = { "B", "KiB", "MiB", "GiB", "TiB", "PiB" };
int unit = 0;
// Scale down until value fits nicely
uint64_t rem = 0;
while (bytes >= 1024 && unit < (int)(sizeof(units)/sizeof(units[0])) - 1) {
rem = bytes % 1024;
bytes /= 1024;
unit++;
}
if (unit == 0) {
// Just bytes
ksnprintf(buf, bufsize, "%llu %s", (unsigned long long)bytes, units[unit]);
} else {
// Show one decimal place without using floats
// Multiply remainder by 10 to get first decimal digit
uint64_t frac = (rem * 10 + 512) / 1024; // rounded
if (frac == 10) { // handle carry, e.g. 1023.9 -> 1024.0
bytes++;
frac = 0;
}
if (frac > 0) ksnprintf(buf, bufsize, "%llu.%llu %s", (unsigned long long)bytes, (unsigned long long)frac, units[unit]);
else ksnprintf(buf, bufsize, "%llu %s", (unsigned long long)bytes, units[unit]);
}
return buf;
}
void log_bootinfo(void) {
char buf[100];
LOG("kmain", "Memory total = %s\n", human_size(BOOT_INFO.memmap_total, buf, sizeof(buf)));
}
static volatile LIMINE_BASE_REVISION(2); static volatile LIMINE_BASE_REVISION(2);
@ -19,16 +57,16 @@ void kmain(void) {
} }
bootinfo_init(); bootinfo_init();
term_init(); term_init(BOOT_INFO.fb->address);
log_bootinfo();
hal_init(); hal_init();
pmm_init(); pmm_init();
paging_init(); hal_vmm_init();
dlmalloc_check(); dev_init();
storedev_init(); storedev_init();
baseimg_init(); baseimg_init();
vfs_init(); vfs_init();
proc_init();
kprintf(BANNER_TEXT "\n"); for(;;);
hal_hang();
} }

View File

@ -2,8 +2,16 @@
#define KPRINTF_H_ #define KPRINTF_H_
#include <printf/printf.h> #include <printf/printf.h>
#include "term/term.h"
#include "spinlock/spinlock.h"
#define kprintf(fmt, ...) \
do { \
spinlock_acquire(&TERM.spinlock); \
printf_(fmt, ##__VA_ARGS__); \
spinlock_release(&TERM.spinlock); \
} while(0)
#define kprintf printf_
#define ksprintf sprintf_ #define ksprintf sprintf_
#define kvsprintf vsprintf_ #define kvsprintf vsprintf_
#define ksnprintf snprintf_ #define ksnprintf snprintf_

View File

@ -1,10 +0,0 @@
#ifndef PAGING_PAGING_H_
#define PAGING_PAGING_H_
#include <stddef.h>
#include <stdint.h>
void paging_init(void);
size_t paging_virt2phys(size_t virtaddr);
#endif // PAGING_PAGING_H_

View File

@ -1,124 +0,0 @@
#include <stdint.h>
#include <stddef.h>
#include <limits.h>
#include "paging/paging.h"
#include "hal/hal.h"
#include "bootinfo/bootinfo.h"
#include "util/util.h"
#include "kprintf.h"
enum {
PF_PRESENT = 1<<0,
PF_READWRITE = 1<<1,
PF_USER = 1<<2,
PF_WRITETHROUGH = 1<<3,
PF_NOCACHE = 1<<4,
PF_ACCESS = 1<<5,
PF_DIRTY = 1<<6,
PF_PAGESIZE = 1<<7,
PF_ATTRTAB = 1<<7,
PF_GLOBAL = 1<<8,
PF_SHARED = 1<<9,
PF_CACHE_WC = PF_ATTRTAB | PF_WRITETHROUGH,
};
#define PGSHIFT_PML4E 39
#define PGSHIFT_PDPTE 30
#define PGSHIFT_PDE 21
#define PGSHIFT_PTE 12
#define PGMASK_ENTRY 0x1ff
#define PGMASK_OFFSET 0x3ff
#define BITS_TO_VIRT_ADDR(pml4_index, pdpte_index, pd_index, pt_index) \
(((uint64_t)pml4_index << PGSHIFT_PML4E) | \
((uint64_t)pdpte_index << PGSHIFT_PDPTE) | \
((uint64_t)pd_index << PGSHIFT_PDE) | ((uint64_t)pt_index << PGSHIFT_PTE))
// Workaround repeated characters
#define AMD64_MM_STRIPSX(a) ((uintptr_t)(a) & 0xFFFFFFFFFFFF)
#define AMD64_MM_ADDRSX(a) \
(((uintptr_t)(a) & (1ULL << 47)) ? (0xFFFFFF0000000000 | ((uintptr_t)(a))) \
: ((uintptr_t)(a)))
// Virtual address' macros
#define PML4E(a) (((a) >> PGSHIFT_PML4E) & PGMASK_ENTRY)
#define PDPTE(a) (((a) >> PGSHIFT_PDPTE) & PGMASK_ENTRY)
#define PDE(a) (((a) >> PGSHIFT_PDE) & PGMASK_ENTRY)
#define PTE(a) (((a) >> PGSHIFT_PTE) & PGMASK_ENTRY)
#define PTE_ADDR_MASK 0x000ffffffffff000
#define PTE_GET_ADDR(VALUE) ((VALUE) & PTE_ADDR_MASK)
#define PTE_GET_FLAGS(VALUE) ((VALUE) & ~PTE_ADDR_MASK)
#define PAGE_MASK(x) ((1 << (x)) - 1)
#define USER_STACK_PAGES 2048
#define PAGE_SIZE 0x1000
#define PAGE_SIZE_LARGE 0x200000
#define PAGE_SIZE_HUGE 0x40000000
#define P_PHYs_ADD(x) ((x) & ~0xfff)
uint64_t *global_page_dir = NULL;
void paging_init(void) {
uint64_t pdphys = 0;
asm volatile("movq %%cr3, %0" : "=r"(pdphys));
if (!pdphys) {
ERR("paging", "could not get default page dir\n");
hal_hang();
}
uint64_t pdvirt = pdphys + BOOT_INFO.hhdm_off;
global_page_dir = (uint64_t *)pdvirt;
LOG("paging", "global_page_dir = %p\n", global_page_dir);
}
size_t _paging_virt2phys(uint64_t *pgdir, size_t virtaddr) {
if (!pgdir) return 0;
if (virtaddr >= BOOT_INFO.hhdm_off
&& virtaddr <= (BOOT_INFO.hhdm_off + MAX(BOOT_INFO.memmap_total, UINT32_MAX))) {
return virtaddr - BOOT_INFO.hhdm_off;
}
size_t virtaddr_init = virtaddr;
virtaddr &= ~0xfff;
virtaddr = AMD64_MM_STRIPSX(virtaddr);
uint32_t pml4idx = PML4E(virtaddr);
uint32_t pdpidx = PDPTE(virtaddr);
uint32_t pdidx = PDE(virtaddr);
uint32_t ptidx = PTE(virtaddr);
if (!(pgdir[pml4idx] & PF_PRESENT)) {
return 0;
}
size_t *pdp = (size_t *)(PTE_GET_ADDR(pgdir[pml4idx]) + BOOT_INFO.hhdm_off);
if (!(pdp[pdpidx] & PF_PRESENT)) {
return 0;
}
size_t *pd = (size_t *)(PTE_GET_ADDR(pdp[pdpidx]) + BOOT_INFO.hhdm_off);
if (!(pd[pdidx] & PF_PRESENT)) {
return 0;
}
size_t *pt = (size_t *)(PTE_GET_ADDR(pd[pdidx]) + BOOT_INFO.hhdm_off);
if (pt[ptidx] & PF_PRESENT) {
return (size_t)(PTE_GET_ADDR(pt[ptidx]) + ((size_t)virtaddr_init & 0xfff));
}
return 0;
}
size_t paging_virt2phys(size_t virtaddr) {
return _paging_virt2phys(global_page_dir, virtaddr);
}

41
kernel/path/path.c Normal file
View File

@ -0,0 +1,41 @@
#include "path.h"
void path_parse(const char *in, char *mp, char *path) {
if (in == 0 || *in == 0) {
mp[0] = 0;
path[0] = 0;
return;
}
int i = 0, j = 0, colonfound = 0;
while (in[i]) {
if (in[i] == ':') {
if (colonfound) {
mp[0] = 0;
path[0] = 0;
return;
}
colonfound = 1;
mp[i] = 0;
i++;
continue;
}
if (!colonfound) {
mp[i] = in[i];
} else {
path[j++] = in[i];
}
i++;
}
if (!colonfound) {
mp[i] = 0;
path[0] = 0;
} else {
path[j] = 0;
}
}

6
kernel/path/path.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef PATH_PATH_H_
#define PATH_PATH_H_
void path_parse(const char *in, char *mp, char *path);
#endif // PATH_PATH_H_

View File

@ -6,6 +6,7 @@
#include "bootinfo/bootinfo.h" #include "bootinfo/bootinfo.h"
#include "spinlock/spinlock.h" #include "spinlock/spinlock.h"
#include "util/util.h" #include "util/util.h"
#include "hal/hal.h"
PhysMem PHYS_MEM; PhysMem PHYS_MEM;
@ -13,7 +14,6 @@ void pmm_init(void) {
spinlock_init(&PHYS_MEM.spinlock); spinlock_init(&PHYS_MEM.spinlock);
BitMap *bm = &PHYS_MEM.self; BitMap *bm = &PHYS_MEM.self;
bm->init = false;
bm->nblocks = _DIV_ROUNDUP(BOOT_INFO.memmap_total, BITMAP_BLOCK_SIZE); bm->nblocks = _DIV_ROUNDUP(BOOT_INFO.memmap_total, BITMAP_BLOCK_SIZE);
bm->nbytes = _DIV_ROUNDUP(bm->nblocks, 8); bm->nbytes = _DIV_ROUNDUP(bm->nblocks, 8);
@ -40,6 +40,9 @@ void pmm_init(void) {
hal_memset(bm->map, 0xff, bm->nbytes); hal_memset(bm->map, 0xff, bm->nbytes);
for (size_t i = 0; i < BOOT_INFO.memmap_entrycount; i++) { for (size_t i = 0; i < BOOT_INFO.memmap_entrycount; i++) {
struct limine_memmap_entry *entry = BOOT_INFO.memmap_entries[i]; struct limine_memmap_entry *entry = BOOT_INFO.memmap_entries[i];
if (entry == memmap_ent) {
continue;
}
// mark usable as 0 and unusable as 1 // mark usable as 0 and unusable as 1
bitmap_markregion(bm, (void *)entry->base, entry->length, entry->type != LIMINE_MEMMAP_USABLE); bitmap_markregion(bm, (void *)entry->base, entry->length, entry->type != LIMINE_MEMMAP_USABLE);
} }
@ -48,7 +51,6 @@ void pmm_init(void) {
bm->alloc_blocks = 0; bm->alloc_blocks = 0;
LOG("pmm", "phys bitmap init 0x%lx, size = 0x%lx\n", physbegin, bm->nbytes); LOG("pmm", "phys bitmap init 0x%lx, size = 0x%lx\n", physbegin, bm->nbytes);
bm->init = true;
} }
void *pmm_alloc(size_t pages) { void *pmm_alloc(size_t pages) {
@ -58,7 +60,7 @@ void *pmm_alloc(size_t pages) {
if (!phys) { if (!phys) {
ERR("pmm", "phys memory ran out\n"); ERR("pmm", "phys memory ran out\n");
hal_hang(); return NULL;
} }
return (void *)phys; return (void *)phys;
} }

File diff suppressed because it is too large Load Diff

1
kernel/printf/printf.c Symbolic link
View File

@ -0,0 +1 @@
../../share/printf/printf.c

View File

@ -1,236 +0,0 @@
/**
* @author (c) Eyal Rozenberg <eyalroz1@gmx.com>
* 2021-2023, Haifa, Palestine/Israel
* @author (c) Marco Paland (info@paland.com)
* 2014-2019, PALANDesign Hannover, Germany
*
* @note Others have made smaller contributions to this file: see the
* contributors page at https://github.com/eyalroz/printf/graphs/contributors
* or ask one of the authors.
*
* @brief Small stand-alone implementation of the printf family of functions
* (`(v)printf`, `(v)s(n)printf` etc., geared towards use on embedded systems
* with a very limited resources.
*
* @note the implementations are thread-safe; re-entrant; use no functions from
* the standard library; and do not dynamically allocate any memory.
*
* @license The MIT License (MIT)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef PRINTF_H_
#define PRINTF_H_
#ifdef __cplusplus
# include <cstdarg>
# include <cstddef>
extern "C" {
#else
# include <stdarg.h>
# include <stddef.h>
#endif
#ifdef __GNUC__
# if ((__GNUC__ == 4 && __GNUC_MINOR__>= 4) || __GNUC__ > 4)
# define ATTR_PRINTF(one_based_format_index, first_arg) \
__attribute__((format(gnu_printf, (one_based_format_index), (first_arg))))
# else
# define ATTR_PRINTF(one_based_format_index, first_arg) \
__attribute__((format(printf, (one_based_format_index), (first_arg))))
# endif
# define ATTR_VPRINTF(one_based_format_index) \
ATTR_PRINTF((one_based_format_index), 0)
#else
# define ATTR_PRINTF(one_based_format_index, first_arg)
# define ATTR_VPRINTF(one_based_format_index)
#endif
#ifndef PRINTF_ALIAS_STANDARD_FUNCTION_NAMES_SOFT
#define PRINTF_ALIAS_STANDARD_FUNCTION_NAMES_SOFT 0
#endif
#ifndef PRINTF_ALIAS_STANDARD_FUNCTION_NAMES_HARD
#define PRINTF_ALIAS_STANDARD_FUNCTION_NAMES_HARD 0
#endif
#if PRINTF_ALIAS_STANDARD_FUNCTION_NAMES_HARD
# define printf_ printf
# define sprintf_ sprintf
# define vsprintf_ vsprintf
# define snprintf_ snprintf
# define vsnprintf_ vsnprintf
# define vprintf_ vprintf
#endif
// If you want to include this implementation file directly rather than
// link against it, this will let you control the functions' visibility,
// e.g. make them static so as not to clash with other objects also
// using them.
#ifndef PRINTF_VISIBILITY
#define PRINTF_VISIBILITY
#endif
/**
* Prints/send a single character to some opaque output entity
*
* @note This function is not implemented by the library, only declared; you
* must provide an implementation if you wish to use the @ref printf / @ref
* vprintf function (and possibly for linking against the library, if your
* toolchain does not support discarding unused functions)
*
* @note The output could be as simple as a wrapper for the `write()` system
* call on a Unix-like * system, or even libc's @ref putchar , for replicating
* actual functionality of libc's @ref printf * function; but on an embedded
* system it may involve interaction with a special output device, like a UART,
* etc.
*
* @note in libc's @ref putchar, the parameter type is an int; this was intended
* to support the representation of either a proper character or EOF in a
* variable - but this is really not meaningful to pass into @ref putchar and is
* discouraged today. See further discussion in:
* @link https://stackoverflow.com/q/17452847/1593077
*
* @param c the single character to print
*/
PRINTF_VISIBILITY
void putchar_(char c);
/**
* An implementation of the C standard's printf/vprintf
*
* @note you must implement a @ref putchar_ function for using this function -
* it invokes @ref putchar_ * rather than directly performing any I/O (which
* insulates it from any dependence on the operating system * and external
* libraries).
*
* @param format A string specifying the format of the output, with %-marked
* specifiers of how to interpret additional arguments.
* @param arg Additional arguments to the function, one for each %-specifier in
* @p format
* @return The number of characters written into @p s, not counting the
* terminating null character
*/
///@{
PRINTF_VISIBILITY
int printf_(const char* format, ...) ATTR_PRINTF(1, 2);
PRINTF_VISIBILITY
int vprintf_(const char* format, va_list arg) ATTR_VPRINTF(1);
///@}
/**
* An implementation of the C standard's sprintf/vsprintf
*
* @note For security considerations (the potential for exceeding the buffer
* bounds), please consider using the size-constrained variant, @ref snprintf /
* @ref vsnprintf, instead.
*
* @param s An array in which to store the formatted string. It must be large
* enough to fit the formatted output!
* @param format A string specifying the format of the output, with %-marked
* specifiers of how to interpret additional arguments
* @param arg Additional arguments to the function, one for each specifier in
* @p format
* @return The number of characters written into @p s, not counting the
* terminating null character
*/
///@{
PRINTF_VISIBILITY
int sprintf_(char* s, const char* format, ...) ATTR_PRINTF(2, 3);
PRINTF_VISIBILITY
int vsprintf_(char* s, const char* format, va_list arg) ATTR_VPRINTF(2);
///@}
/**
* An implementation of the C standard's snprintf/vsnprintf
*
* @param s An array in which to store the formatted string. It must be large
* enough to fit either the entire formatted output, or at least @p n
* characters. Alternatively, it can be NULL, in which case nothing will
* be printed, and only the number of characters which _could_ have been
* printed is tallied and returned.
* @param n The maximum number of characters to write to the array, including
* a terminating null character
* @param format A string specifying the format of the output, with %-marked
* specifiers of how to interpret additional arguments.
* @param arg Additional arguments to the function, one for each specifier in
* @p format
* @return The number of characters that COULD have been written into @p s, not
* counting the terminating null character. A value equal or larger than
* @p n indicates truncation. Only when the returned value is non-negative
* and less than @p n, the null-terminated string has been fully and
* successfully printed.
*/
///@{
PRINTF_VISIBILITY
int snprintf_(char* s, size_t count, const char* format, ...) ATTR_PRINTF(3, 4);
PRINTF_VISIBILITY
int vsnprintf_(char* s, size_t count, const char* format, va_list arg) ATTR_VPRINTF(3);
///@}
/**
* printf/vprintf with user-specified output function
*
* An alternative to @ref printf_, in which the output function is specified
* dynamically (rather than @ref putchar_ being used)
*
* @param out An output function which takes one character and a type-erased
* additional parameters
* @param extra_arg The type-erased argument to pass to the output function @p
* out with each call
* @param format A string specifying the format of the output, with %-marked
* specifiers of how to interpret additional arguments.
* @param arg Additional arguments to the function, one for each specifier in
* @p format
* @return The number of characters for which the output f unction was invoked,
* not counting the terminating null character
*
*/
PRINTF_VISIBILITY
int fctprintf(void (*out)(char c, void* extra_arg), void* extra_arg, const char* format, ...) ATTR_PRINTF(3, 4);
PRINTF_VISIBILITY
int vfctprintf(void (*out)(char c, void* extra_arg), void* extra_arg, const char* format, va_list arg) ATTR_VPRINTF(3);
#ifdef __cplusplus
} // extern "C"
#endif
#if PRINTF_ALIAS_STANDARD_FUNCTION_NAMES_HARD
# undef printf_
# undef sprintf_
# undef vsprintf_
# undef snprintf_
# undef vsnprintf_
# undef vprintf_
#else
#if PRINTF_ALIAS_STANDARD_FUNCTION_NAMES_SOFT
# define printf printf_
# define sprintf sprintf_
# define vsprintf vsprintf_
# define snprintf snprintf_
# define vsnprintf vsnprintf_
# define vprintf vprintf_
#endif
#endif
#endif // PRINTF_H_

1
kernel/printf/printf.h Symbolic link
View File

@ -0,0 +1 @@
../../share/printf/printf.h

View File

@ -1,2 +0,0 @@
#define PRINTF_SUPPORT_DECIMAL_SPECIFIERS 0
#define PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS 0

View File

@ -0,0 +1 @@
../../share/printf/printf_config.h

260
kernel/proc/proc.c Normal file
View File

@ -0,0 +1,260 @@
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include "hal/hal.h"
#include "spinlock/spinlock.h"
#include "proc.h"
#include "dlmalloc/malloc.h"
#include "pmm/pmm.h"
#include "util/util.h"
#include "kprintf.h"
#include "elf.h"
#include "errors.h"
#include "vfs/vfs.h"
#include "bootinfo/bootinfo.h"
#include "ipc/pipe/pipe.h"
#include "sysdefs/processctl.h"
#include "sysdefs/ioctl.h"
#define PROC_REAPER_FREQ 30
uint64_t pids = 0;
uint64_t sched_ticks = 0;
Procs PROCS;
bool proc_checkelf(uint8_t *elf) {
if (elf[0] != 0x7f || elf[1] != 'E' || elf[2] != 'L' || elf[3] != 'F') {
return false;
}
return true;
}
ElfAuxval proc_load_elf_segs(Proc *proc, uint8_t *data) {
ElfAuxval aux = {0};
Elf64_Ehdr *elfhdr = (Elf64_Ehdr *)data;
aux.entry = elfhdr->e_entry;
aux.phnum = elfhdr->e_phnum;
aux.phent = elfhdr->e_phentsize;
for (uint64_t seg = 0; seg < elfhdr->e_phnum; seg++) {
Elf64_Phdr *phdr = (Elf64_Phdr *)(data + elfhdr->e_phoff + (elfhdr->e_phentsize * seg));
switch (phdr->p_type) {
case PT_PHDR: {
aux.phdr = (uint64_t)phdr->p_vaddr;
} break;
case PT_LOAD: {
uint64_t off = phdr->p_vaddr & (HAL_PAGE_SIZE - 1);
uint64_t blocks = (off + phdr->p_memsz + HAL_PAGE_SIZE - 1) / HAL_PAGE_SIZE;
uint8_t *physaddr = pmm_alloc(blocks);
uint8_t *virtaddr = (uint8_t *)(phdr->p_vaddr & ~(HAL_PAGE_SIZE - 1));
hal_memset(VIRT(physaddr), 0, blocks * HAL_PAGE_SIZE);
hal_memcpy(VIRT(physaddr) + off, (data + phdr->p_offset), phdr->p_filesz);
uint32_t pgflags = HAL_PG_USER | HAL_PG_PRESENT;
if (phdr->p_flags & PF_W) {
pgflags |= HAL_PG_RW;
}
hal_vmm_map_range(proc->platformdata.cr3, virtaddr, physaddr, blocks * HAL_PAGE_SIZE, pgflags);
VasRange *range = dlmalloc(sizeof(*range));
range->virtstart = virtaddr;
range->physstart = physaddr;
range->size = blocks * HAL_PAGE_SIZE;
range->pgflags = pgflags;
LL_APPEND(proc->vas, range);
} break;
}
}
return aux;
}
Proc *proc_spawnuser(char *mountpoint, char *path) {
IoctlStat stat;
if (vfs_stat(mountpoint, path, &stat) != E_OK) {
return NULL;
}
if (stat.type != IOCTLSTAT_FILE) {
return NULL;
}
VfsObj *vobj = vfs_open(mountpoint, path, VFS_FLAG_READ);
if (vobj == NULL) {
return NULL;
}
uint8_t *data = dlmalloc(stat.size);
if (data == NULL) {
vfs_close(vobj);
return NULL;
}
if (vobj->read(vobj, data, stat.size, 0) != E_OK) {
dlfree(data);
vfs_close(vobj);
return NULL;
}
vfs_close(vobj);
Proc *proc = dlmalloc(sizeof(*proc));
hal_memset(proc, 0, sizeof(*proc));
ksprintf(proc->name, "%s:%s", mountpoint, path);
hal_memset(&proc->platformdata.trapframe, 0, sizeof(proc->platformdata.trapframe));
proc->platformdata.cr3 = hal_vmm_userproc_pml4_phys();
uint8_t *kstackp = (uint8_t *)pmm_alloc(PROC_STACKBLOCKS) + PROC_STACKSIZE;
proc->platformdata.kstack = kstackp;
uint8_t *pstackp = (uint8_t *)pmm_alloc(PROC_STACKBLOCKS);
proc->platformdata.pstack = pstackp;
uint64_t virttop = PROC_USER_STACK_TOP;
uint64_t virtbase = virttop - PROC_STACKSIZE;
uint32_t flags = HAL_PG_RW | HAL_PG_PRESENT | HAL_PG_USER;
hal_vmm_map_range(proc->platformdata.cr3, (void *)virtbase, (void *)pstackp, PROC_STACKSIZE, flags);
VasRange *range = dlmalloc(sizeof(*range));
range->virtstart = (uint8_t *)virtbase;
range->physstart = (uint8_t *)pstackp;
range->size = PROC_STACKSIZE;
range->pgflags = flags;
LL_APPEND(proc->vas, range);
ElfAuxval aux = proc_load_elf_segs(proc, data);
dlfree(data);
proc->platformdata.trapframe.ss = 0x20 | 0x3;
proc->platformdata.trapframe.rsp = (uint64_t)virttop;
proc->platformdata.trapframe.rflags = 0x202;
proc->platformdata.trapframe.cs = 0x18 | 0x3;
proc->platformdata.trapframe.rip = aux.entry;
proc->state = PROC_EMBRYO;
proc->pid = pids++;
proc->mman_map_base = PROC_MMAN_MAP_BASE;
spinlock_init(&proc->pipes_spinlock);
spinlock_init(&proc->devs_spinlock);
proc->pipes[0] = dlmalloc(sizeof(IpcPipe));
ipc_pipeinit(proc->pipes[0], proc->pid);
proc->pipes[1] = dlmalloc(sizeof(IpcPipe));
ipc_pipeinit(proc->pipes[1], proc->pid);
return proc;
}
void proc_register(Proc *proc) {
spinlock_acquire(&PROCS.spinlock);
LL_APPEND(PROCS.procs, proc);
spinlock_release(&PROCS.spinlock);
}
Proc *proc_nextready(void) {
Proc *proc = PROCS.current->next;
for (;;) {
if (proc == NULL) {
proc = PROCS.procs;
}
if (proc->state == PROC_READY) {
return proc;
}
proc = proc->next;
}
}
void proc_reaper(void) {
spinlock_acquire(&PROCS.spinlock);
Proc *head, *tmp;
LL_FOREACH_SAFE(PROCS.procs, head, tmp) {
if (head->state != PROC_ZOMBIE) {
continue;
}
Proc *zombie = head;
LL_REMOVE(PROCS.procs, zombie);
for (size_t i = 0; i < zombie->vobjcnt; i++) {
if (zombie->vobjs[i] != NULL) {
vfs_close(zombie->vobjs[i]);
zombie->vobjs[i] = NULL;
}
}
for (size_t i = 0; i < PROC_PIPEHANDLES_MAX; i++) {
if (zombie->pipes[i] != NULL && zombie->pipes[i]->ownerpid == zombie->pid) {
dlfree(zombie->pipes[i]);
ipc_pipefree(zombie->pipes[i]);
zombie->pipes[i] = NULL;
}
}
pmm_free((uintptr_t)(zombie->platformdata.kstack - PROC_STACKSIZE), PROC_STACKBLOCKS);
pmm_free((uintptr_t)(zombie->platformdata.pstack - PROC_STACKSIZE), PROC_STACKBLOCKS);
VasRange *vas, *vastmp;
LL_FOREACH_SAFE(zombie->vas, vas, vastmp) {
hal_vmm_unmap_range(zombie->platformdata.cr3, vas->virtstart, vas->physstart, vas->size);
pmm_free((uintptr_t)vas->physstart, vas->size / HAL_PAGE_SIZE);
dlfree(vas);
}
pmm_free((uintptr_t)zombie->platformdata.cr3, 1);
ProcArg *arg, *argtmp;
LL_FOREACH_SAFE(zombie->procargs.list, arg, argtmp) {
dlfree(arg->string);
dlfree(arg);
}
dlfree(zombie);
}
spinlock_release(&PROCS.spinlock);
}
void proc_sched(void *cpustate) {
hal_intr_disable();
sched_ticks++;
IntrStackFrame *frame = cpustate;
PROCS.current->platformdata.trapframe = *frame;
PROCS.current = proc_nextready();
if (sched_ticks % PROC_REAPER_FREQ == 0) {
proc_reaper();
}
tss.rsp0 = (uint64_t)VIRT(PROCS.current->platformdata.kstack);
hal_switchproc(&PROCS.current->platformdata.trapframe, (void *)PROCS.current->platformdata.cr3);
}
void proc_kill(Proc *proc) {
proc->state = PROC_ZOMBIE;
}
void proc_killself(void) {
spinlock_acquire(&PROCS.spinlock);
Proc *proc = PROCS.current;
proc_kill(proc);
spinlock_release(&PROCS.spinlock);
}
void proc_init(void) {
spinlock_init(&PROCS.spinlock);
PROCS.procs = NULL;
Proc *init = proc_spawnuser("base", "/bin/init");
PROCS.current = init;
proc_register(init);
init->state = PROC_READY;
tss.rsp0 = (uint64_t)VIRT(PROCS.current->platformdata.kstack);
hal_switchproc(&PROCS.current->platformdata.trapframe, (void *)PROCS.current->platformdata.cr3);
}

103
kernel/proc/proc.h Normal file
View File

@ -0,0 +1,103 @@
#ifndef PROC_PROC_H_
#define PROC_PROC_H_
#include <stdint.h>
#include "hal/hal.h"
#include "spinlock/spinlock.h"
#include "bitmap/bitmap.h"
#include "vfs/vfs.h"
#include "ipc/pipe/pipe.h"
#include "sysdefs/processctl.h"
#include "dev/dev.h"
#define PROC_NAME_MAX 0x100
#define PROC_STACKBLOCKS (1024*2)
#define PROC_STACKSIZE (PROC_STACKBLOCKS * BITMAP_BLOCK_SIZE)
#define PROC_MAX 0x100 // max amount of processes
#define PROC_VFSHANDLES_MAX 0x80
#define PROC_PIPEHANDLES_MAX 0x20
#define PROC_DEVHANDLES_MAX 0x20
#define PROC_MMAN_MAP_BASE 0x0000100000000000ULL
#define PROC_USER_STACK_TOP 0x00007FFFFFFFF000ULL
typedef struct {
IntrStackFrame trapframe;
uint8_t *kstack;
uint8_t *pstack;
uint64_t cr3;
} ProcPlatformData;
enum {
PROC_EMBRYO = 0,
PROC_READY = 1,
PROC_ZOMBIE = 2,
PROC_WAITING = 3,
PROC_DIED = 4,
};
typedef struct ProcArg {
struct ProcArg *next;
char string[PROC_ARG_MAX];
} ProcArg;
typedef struct Proc {
struct Proc *next;
uint64_t pid;
char name[PROC_NAME_MAX];
ProcPlatformData platformdata;
uint8_t state;
VasRange *vas;
VfsObj *vobjs[PROC_VFSHANDLES_MAX];
uint64_t vobjcnt;
IpcPipe *pipes[PROC_PIPEHANDLES_MAX];
SpinLock pipes_spinlock;
Dev *devs[PROC_DEVHANDLES_MAX];
SpinLock devs_spinlock;
struct {
ProcArg *list;
size_t len;
} procargs;
uint64_t mman_map_base;
} Proc;
typedef struct {
SpinLock spinlock;
Proc *procs;
Proc *current;
} Procs;
extern Procs PROCS;
void proc_init(void);
void proc_register(Proc *proc);
Proc *proc_spawnuser(char *mountpoint, char *path);
void proc_sched(void *cpustate);
void proc_killself(void);
void proc_kill(Proc *proc);
#define PROC_DIE() \
do { \
proc_killself(); \
for(;;); \
} while(0)
#define PROC_ARG(proc, str) \
do { \
ProcArg *__arg = dlmalloc(sizeof(*__arg)); \
hal_strcpy(__arg->string, (str)); \
LL_APPEND((proc)->procargs.list, __arg); \
(proc)->procargs.len++; \
} while(0)
#endif // PROC_PROC_H_

34
kernel/rbuf/rbuf.c Normal file
View File

@ -0,0 +1,34 @@
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include "rbuf.h"
#include "kprintf.h"
#include "hal/hal.h"
void rbuf_init(RBuf *rbuf, uint8_t *buf, size_t bufsize) {
rbuf->buffer = buf;
rbuf->tail = 0;
rbuf->head = 0;
rbuf->cap = bufsize;
rbuf->count = 0;
}
int32_t rbuf_push(RBuf *rbuf, uint8_t data) {
if (rbuf->count == rbuf->cap) {
return -1;
}
rbuf->buffer[rbuf->head] = data;
rbuf->head = (rbuf->head + 1) % rbuf->cap;
rbuf->count++;
return 0;
}
int32_t rbuf_pop(RBuf *rbuf, uint8_t *data) {
if (rbuf->count == 0) {
return -1;
}
*data = rbuf->buffer[rbuf->tail];
rbuf->tail = (rbuf->tail + 1) % rbuf->cap;
rbuf->count--;
return 0;
}

21
kernel/rbuf/rbuf.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef RBUF_RBUF_H_
#define RBUF_RBUF_H_
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
typedef struct {
uint8_t *buffer;
size_t tail;
size_t head;
size_t cap;
size_t count;
bool full;
} RBuf;
int32_t rbuf_push(RBuf *rbuf, uint8_t data);
int32_t rbuf_pop(RBuf *rbuf, uint8_t *data);
void rbuf_init(RBuf *rbuf, uint8_t *buf, size_t bufsize);
#endif // RBUF_RBUF_H_

View File

@ -1,20 +1,75 @@
#include <stdatomic.h> #include <stdatomic.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include "spinlock.h" #include "spinlock.h"
#include "hal/hal.h"
#include "kprintf.h"
#define SPINLOCK_IRQ_DBG 1
#define SPINLOCK_HINT() asm volatile("pause")
struct {
atomic_uint64_t irq_flags;
atomic_int irq_nest;
} IRQ_CTX;
void spinlock_init(SpinLock *sl) { void spinlock_init(SpinLock *sl) {
atomic_store(&sl->lock, false); atomic_store(&sl->lock, false);
} }
uint64_t irqsave(void) {
uint64_t flags;
asm volatile("pushfq; cli; popq %0" : "=r"(flags) :: "memory", "cc");
return flags;
}
void irqrestore(uint64_t flags) {
if (flags & (1<<9)) {
asm volatile("sti" ::: "memory", "cc");
}
}
void irqsave_nested(void) {
if (atomic_load(&IRQ_CTX.irq_nest) == 0) {
atomic_store(&IRQ_CTX.irq_flags, irqsave());
}
atomic_inc(&IRQ_CTX.irq_nest);
#if SPINLOCK_IRQ_DBG
if (atomic_load(&IRQ_CTX.irq_nest) < 0) {
kprintf("IRQ_CTX.irq_nest underflow\n");
hal_hang();
}
#endif
}
void irqrestore_nested(void) {
#if SPINLOCK_IRQ_DBG
int irq_nest = atomic_load(&IRQ_CTX.irq_nest);
if (irq_nest <= 0) {
kprintf("spinlock: irqs restored too many times: %d\n", irq_nest);
hal_hang();
}
#endif
atomic_dec(&IRQ_CTX.irq_nest);
if (atomic_load(&IRQ_CTX.irq_nest) == 0) {
irqrestore(atomic_load(&IRQ_CTX.irq_flags));
}
}
void spinlock_acquire(SpinLock *sl) { void spinlock_acquire(SpinLock *sl) {
bool unlocked = false; irqsave_nested();
while (!atomic_compare_exchange_weak(&sl->lock, &unlocked, true)) {
unlocked = false; while (atomic_test_and_set_explicit(&sl->lock, memory_order_acquire)) {
SPINLOCK_HINT(); SPINLOCK_HINT();
} }
} }
void spinlock_release(SpinLock *sl) { void spinlock_release(SpinLock *sl) {
atomic_store(&sl->lock, false); atomic_clear_flag_explicit(&sl->lock, memory_order_release);
irqrestore_nested();
} }

View File

@ -3,16 +3,10 @@
#include <stdatomic.h> #include <stdatomic.h>
#include <stdint.h> #include <stdint.h>
#include "hal/hal.h"
typedef struct { atomic_bool lock; } SpinLock; typedef struct {
atomic_bool lock;
// Spin more efficiently - cpu dependant } SpinLock;
#if defined(__x86_64__)
# define SPINLOCK_HINT() asm volatile("pause")
#else
# define SPINLOCK_HINT()
#endif
void spinlock_init(SpinLock *sl); void spinlock_init(SpinLock *sl);
void spinlock_acquire(SpinLock *sl); void spinlock_acquire(SpinLock *sl);

View File

@ -1,22 +0,0 @@
#ifndef __FREESTND_C_HDRS_STDATOMIC_H
#define __FREESTND_C_HDRS_STDATOMIC_H
#define memory_order_relaxed __ATOMIC_RELAXED
#define memory_order_consume __ATOMIC_CONSUME
#define memory_order_acquire __ATOMIC_ACQUIRE
#define memory_order_release __ATOMIC_RELEASE
#define memory_order_acq_rel __ATOMIC_ACQ_REL
#define memory_order_seq_cst __ATOMIC_SEQ_CST
#define atomic_load_explicit __atomic_load_n
#define atomic_store_explicit __atomic_store_n
#define atomic_store(p, v) atomic_store_explicit(p, v, memory_order_relaxed)
#define atomic_load(p, v) atomic_load_explicit(p, v, memory_order_relaxed)
#define atomic_compare_exchange_weak(p, old, new) \
__atomic_compare_exchange_n(p, old, new, true, memory_order_relaxed, memory_order_relaxed)
#define atomic_bool volatile bool
#endif

View File

@ -5,12 +5,13 @@
#include <stddef.h> #include <stddef.h>
#include "spinlock/spinlock.h" #include "spinlock/spinlock.h"
#include "ramsd.h" #include "ramsd.h"
#include "compiler/attr.h"
enum { enum {
STOREDEV_RAMSD, STOREDEV_RAMSD,
}; };
static const char *storedev_strings[] = { UNUSED static const char *storedev_strings[] = {
"RAMSD", "RAMSD",
}; };

117
kernel/syscall/devctl.c Normal file
View File

@ -0,0 +1,117 @@
#include <stdint.h>
#include <stddef.h>
#include "kprintf.h"
#include "syscall.h"
#include "errors.h"
#include "spinlock/spinlock.h"
#include "proc/proc.h"
#include "sysdefs/devctl.h"
#include "util/util.h"
#include "hshtb.h"
#include "dev/dev.h"
int32_t SYSCALL5(sys_devctl, devh1, cmd1, buffer1, len1, extra1) {
uint64_t *devh = (uint64_t *)devh1;
uint64_t cmd = cmd1;
int32_t ret = E_OK;
spinlock_acquire(&PROCS.spinlock);
Proc *proc = PROCS.current;
spinlock_release(&PROCS.spinlock);
switch (cmd) {
case DEVCTL_GET_HANDLE: {
char *ident = (char *)buffer1;
if (ident == NULL) {
ret = E_INVALIDARGUMENT;
goto done;
}
spinlock_acquire(&DEVTABLE.spinlock);
Dev *founddev;
HSHTB_GET(DEVTABLE.devs, ident, ident, founddev);
spinlock_release(&DEVTABLE.spinlock);
if (founddev == NULL) {
ret = E_NOENTRY;
goto done;
}
bool found = false;
for (size_t i = 0; i < PROC_DEVHANDLES_MAX; i++) {
if (proc->devs[i] == NULL) {
found = true;
proc->devs[i] = founddev;
*devh = i;
break;
}
}
if (!found) {
ret = E_NOMEMORY;
goto done;
}
} break;
case DEVCTL_DEVLS_SZ: {
size_t n = 0;
spinlock_acquire(&DEVTABLE.spinlock);
for (size_t i = 0; i < LEN(DEVTABLE.devs); i++) {
if (DEVTABLE.devs[i]._hshtbstate == HSHTB_TAKEN) {
n++;
}
}
spinlock_release(&DEVTABLE.spinlock);
ret = n;
} break;
case DEVCTL_DEVLS_STAT: {
DevStat *devstat = (DevStat *)buffer1;
size_t idx = (size_t)len1;
if (devstat == NULL) {
ret = E_INVALIDARGUMENT;
goto done;
}
devstat->present = false;
spinlock_acquire(&DEVTABLE.spinlock);
for (size_t i = 0; i < LEN(DEVTABLE.devs); i++) {
if (i == idx && DEVTABLE.devs[i]._hshtbstate == HSHTB_TAKEN) {
Dev *dev = &DEVTABLE.devs[i];
hal_memcpy(devstat->name, dev->ident, sizeof(dev->ident));
for (size_t j = 0; j < DEV_FNS_MAX; j++) {
if (dev->fns[j] != NULL) {
devstat->nfns++;
}
}
devstat->present = true;
break;
}
}
spinlock_release(&DEVTABLE.spinlock);
} break;
default: {
if (devh == NULL) {
ret = E_INVALIDARGUMENT;
goto done;
}
if (cmd >= DEV_FNS_MAX) {
ret = E_INVALIDARGUMENT;
goto done;
}
Dev *dev = proc->devs[*devh];
if (dev == NULL) {
ret = E_NOENTRY;
goto done;
}
spinlock_acquire(&dev->spinlock);
ret = dev->fns[cmd]((uint8_t *)buffer1, (size_t)len1, (void *)extra1);
spinlock_release(&dev->spinlock);
} break;
}
done:
return ret;
}

10
kernel/syscall/devctl.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef SYSCALL_DEVCTL_H_
#define SYSCALL_DEVCTL_H_
#include <stdint.h>
#include "syscall.h"
#include "dev/dev.h"
int32_t SYSCALL5(sys_devctl, devh1, cmd1, buffer1, len1, extra1);
#endif // SYSCALL_DEVCTL_H_

205
kernel/syscall/ioctl.c Normal file
View File

@ -0,0 +1,205 @@
#include <stdint.h>
#include <stddef.h>
#include "syscall.h"
#include "sysdefs/ioctl.h"
#include "errors.h"
#include "path/path.h"
#include "vfs/vfs.h"
#include "kprintf.h"
#include "proc/proc.h"
#include "spinlock/spinlock.h"
#define IOCTL_MP_MAX 0xff
#define IOCTL_PATH_MAX VFS_PATH_MAX
int32_t SYSCALL5(sys_ioctl, ioh1, cmd1, arg1, arg2, arg3) {
uint64_t ioh = ioh1;
uint64_t cmd = cmd1;
int32_t ret = E_BADIO;
switch (cmd) {
case IOCTL_OPENF: {
const char *opath = (const char *)arg1;
uint64_t oflags = arg2;
if (opath == NULL) {
ret = E_INVALIDARGUMENT;
goto done;
}
char mp[IOCTL_MP_MAX];
char path[IOCTL_PATH_MAX];
path_parse(opath, mp, path);
VfsObj *vobj = vfs_open(mp, path, oflags);
if (vobj == NULL) {
ret = E_NOENTRY;
goto done;
}
spinlock_acquire(&PROCS.spinlock);
Proc *proc = PROCS.current;
spinlock_release(&PROCS.spinlock);
if (proc->vobjcnt < PROC_VFSHANDLES_MAX) {
proc->vobjs[proc->vobjcnt++] = vobj;
ret = proc->vobjcnt - 1;
} else {
ret = E_NOMEMORY;
}
} break;
case IOCTL_CLOSEF: {
if (ioh >= PROC_VFSHANDLES_MAX) {
ret = E_INVALIDARGUMENT;
goto done;
}
spinlock_acquire(&PROCS.spinlock);
Proc *proc = PROCS.current;
spinlock_release(&PROCS.spinlock);
VfsObj *vobj = proc->vobjs[ioh];
if (vobj == NULL) {
ret = E_INVALIDARGUMENT;
goto done;
}
size_t i = 0;
for (; i < PROC_VFSHANDLES_MAX; i++) {
if (proc->vobjs[i] == vobj) {
break;
}
}
vfs_close(vobj);
proc->vobjs[i] = NULL;
ret = E_OK;
} break;
case IOCTL_WRITE: {
const uint8_t *const buffer = (const uint8_t *const)arg1;
size_t len = (size_t)arg2;
size_t off = (size_t)arg3;
if (buffer == NULL) {
ret = E_INVALIDARGUMENT;
goto done;
}
if (ioh >= PROC_VFSHANDLES_MAX) {
ret = E_INVALIDARGUMENT;
goto done;
}
spinlock_acquire(&PROCS.spinlock);
Proc *proc = PROCS.current;
spinlock_release(&PROCS.spinlock);
VfsObj *vobj = proc->vobjs[ioh];
if (vobj == NULL) {
ret = E_INVALIDARGUMENT;
goto done;
}
ret = vobj->write(vobj, buffer, len, off);
} break;
case IOCTL_READ: {
uint8_t *const buffer = (uint8_t *const)arg1;
size_t len = (size_t)arg2;
size_t off = (size_t)arg3;
if (buffer == NULL) {
ret = E_INVALIDARGUMENT;
goto done;
}
if (ioh >= PROC_VFSHANDLES_MAX) {
ret = E_INVALIDARGUMENT;
goto done;
}
spinlock_acquire(&PROCS.spinlock);
Proc *proc = PROCS.current;
spinlock_release(&PROCS.spinlock);
VfsObj *vobj = proc->vobjs[ioh];
if (vobj == NULL) {
ret = E_INVALIDARGUMENT;
goto done;
}
ret = vobj->read(vobj, buffer, len, off);
} break;
case IOCTL_STAT: {
const char *opath = (const char *)arg2;
if (opath == NULL) {
ret = E_INVALIDARGUMENT;
goto done;
}
IoctlStat *iostat = (IoctlStat *)arg1;
if (iostat == NULL) {
ret = E_INVALIDARGUMENT;
goto done;
}
char mp[IOCTL_MP_MAX];
char path[IOCTL_PATH_MAX];
path_parse(opath, mp, path);
ret = vfs_stat(mp, path, iostat);
} break;
case IOCTL_FETCHDIRENT: {
const char *opath = (const char *)arg1;
if (opath == NULL) {
ret = E_INVALIDARGUMENT;
goto done;
}
IoctlDirent *direntbuf = (IoctlDirent *)arg2;
if (direntbuf == NULL) {
ret = E_INVALIDARGUMENT;
goto done;
}
size_t idx = (size_t)arg3;
char mp[IOCTL_MP_MAX];
char path[IOCTL_PATH_MAX];
path_parse(opath, mp, path);
ret = vfs_fetchdirent(mp, path, direntbuf, idx);
} break;
case IOCTL_MKDIR: {
const char *opath = (const char *)arg1;
if (opath == NULL) {
ret = E_INVALIDARGUMENT;
goto done;
}
size_t idx = (size_t)arg3;
char mp[IOCTL_MP_MAX];
char path[IOCTL_PATH_MAX];
path_parse(opath, mp, path);
ret = vfs_mkdir(mp, path);
} break;
default: {
ret = E_INVALIDARGUMENT;
goto done;
} break;
}
done:
return ret;
}

9
kernel/syscall/ioctl.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef SYSCALL_IOCTL_H_
#define SYSCALL_IOCTL_H_
#include <stdint.h>
#include "syscall.h"
int32_t SYSCALL5(sys_ioctl, ioh1, cmd1, arg1, arg2, arg3);
#endif // SYSCALL_IOCTL_H_

168
kernel/syscall/ipcpipe.c Normal file
View File

@ -0,0 +1,168 @@
#include <stddef.h>
#include <stdint.h>
#include "ipcpipe.h"
#include "ipc/pipe/pipe.h"
#include "sysdefs/ipcpipe.h"
#include "dlmalloc/malloc.h"
#include "proc/proc.h"
#include "spinlock/spinlock.h"
#include "errors.h"
#include "util/util.h"
#include "kprintf.h"
int32_t SYSCALL5(sys_ipcpipe, pid1, pipenum1, cmd1, buffer1, len1) {
uint64_t pid = pid1;
uint64_t pipenum = pipenum1;
uint64_t cmd = cmd1;
int32_t ret = E_OK;
if (pid == -1) {
pid = PROCS.current->pid;
}
spinlock_acquire(&PROCS.spinlock);
Proc *proc = NULL;
LL_FINDPROP(PROCS.procs, proc, pid, pid);
spinlock_release(&PROCS.spinlock);
if (proc == NULL) {
ret = E_INVALIDARGUMENT;
goto done;
}
switch (cmd) {
case IPCPIPE_MAKE: {
if (pipenum >= PROC_PIPEHANDLES_MAX) {
ret = E_NOMEMORY;
goto done;
}
IpcPipe *pipe = dlmalloc(sizeof(*pipe));
if (pipe == NULL) {
ret = E_NOMEMORY;
goto done;
}
if ((ret = ipc_pipeinit(pipe, proc->pid)) < 0) {
ret = E_NOMEMORY;
goto done;
}
spinlock_acquire(&proc->pipes_spinlock);
if (proc->pipes[pipenum] != NULL) {
spinlock_release(&proc->pipes_spinlock);
ipc_pipefree(pipe);
dlfree(pipe);
ret = E_RESOURCEAVAIL;
goto done;
}
proc->pipes[pipenum] = pipe;
spinlock_release(&proc->pipes_spinlock);
ret = E_OK;
} break;
case IPCPIPE_DELETE: {
if (pipenum >= PROC_PIPEHANDLES_MAX) {
ret = E_NOMEMORY;
goto done;
}
spinlock_acquire(&proc->pipes_spinlock);
if (proc->pipes[pipenum] != NULL && proc->pid == proc->pipes[pipenum]->ownerpid) {
ipc_pipefree(proc->pipes[pipenum]);
dlfree(proc->pipes[pipenum]);
}
proc->pipes[pipenum] = NULL;
spinlock_release(&proc->pipes_spinlock);
ret = E_OK;
} break;
case IPCPIPE_WRITE: {
if (pipenum >= PROC_PIPEHANDLES_MAX) {
ret = E_INVALIDARGUMENT;
goto done;
}
const uint8_t *const buffer = (const uint8_t *const)buffer1;
if (buffer == NULL) {
ret = E_INVALIDARGUMENT;
goto done;
}
spinlock_acquire(&proc->pipes_spinlock);
IpcPipe *pipe = proc->pipes[pipenum];
spinlock_release(&proc->pipes_spinlock);
if (pipe == NULL) {
ret = E_INVALIDARGUMENT;
goto done;
}
ret = ipc_pipewrite(pipe, buffer, len1);
} break;
case IPCPIPE_READ: {
if (pipenum >= PROC_PIPEHANDLES_MAX) {
ret = E_INVALIDARGUMENT;
goto done;
}
uint8_t *const buffer = (uint8_t *const)buffer1;
if (buffer == NULL) {
ret = E_INVALIDARGUMENT;
goto done;
}
spinlock_acquire(&proc->pipes_spinlock);
IpcPipe *pipe = proc->pipes[pipenum];
spinlock_release(&proc->pipes_spinlock);
if (pipe == NULL) {
ret = E_INVALIDARGUMENT;
goto done;
}
ret = ipc_piperead(pipe, buffer, len1);
} break;
case IPCPIPE_REPLACE: {
if (pipenum >= PROC_PIPEHANDLES_MAX) {
ret = E_NOMEMORY;
goto done;
}
uint64_t pid2 = buffer1;
uint64_t pipenum2 = len1;
spinlock_acquire(&PROCS.spinlock);
Proc *proc2 = NULL;
LL_FINDPROP(PROCS.procs, proc2, pid, pid2);
spinlock_release(&PROCS.spinlock);
if (proc2 == NULL) {
ret = E_INVALIDARGUMENT;
goto done;
}
if (pipenum2 >= PROC_PIPEHANDLES_MAX) {
ret = E_NOMEMORY;
goto done;
}
spinlock_acquire(&proc2->pipes_spinlock);
spinlock_acquire(&proc->pipes_spinlock);
if (proc->pipes[pipenum] != NULL && proc->pid == proc->pipes[pipenum]->ownerpid) {
ipc_pipefree(proc->pipes[pipenum]);
dlfree(proc->pipes[pipenum]);
}
proc->pipes[pipenum] = proc2->pipes[pipenum2];
spinlock_release(&proc->pipes_spinlock);
spinlock_release(&proc2->pipes_spinlock);
} break;
default: {
ret = E_INVALIDARGUMENT;
} break;
}
done:
return ret;
}

8
kernel/syscall/ipcpipe.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef SYSCALL_IPCPIPE_H_
#define SYSCALL_IPCPIPE_H_
#include "syscall.h"
int32_t SYSCALL5(sys_ipcpipe, pid1, pipenum1, cmd1, buffer1, len1);
#endif // SYSCALL_IPCPIPE_H_

Some files were not shown because too many files have changed in this diff Show More