Compare commits
157 Commits
8da890e388
...
master
Author | SHA1 | Date | |
---|---|---|---|
a513909189 | |||
cdfb1e39c0 | |||
e9838d530f | |||
247ef1bbd1 | |||
933083ffeb | |||
70d6931e3b | |||
acbf051dbc | |||
0117080b61 | |||
ef9393e694 | |||
082cb66c7e | |||
b624214433 | |||
26517e8e28 | |||
b72f3ee00d | |||
071f414f07 | |||
04a4b1395c | |||
18d646ff8b | |||
20b4545cae | |||
fc47ff581e | |||
08793178f1 | |||
3c1c63e970 | |||
57ba9ff126 | |||
c0178a1405 | |||
dc8df7fade | |||
c30d2d2ea6 | |||
443cf0e4ff | |||
de20efa0f3 | |||
2cfd3ee2fa | |||
c345e2284e | |||
bc2b115cb3 | |||
91d648ade4 | |||
0232849994 | |||
73effcd52a | |||
62cf07afc7 | |||
0e4a35eb86 | |||
fa8a774115 | |||
39981fdbbf | |||
10711f7fb3 | |||
0fb63b4695 | |||
46e52c8d48 | |||
4e8afae5fb | |||
20a89502c0 | |||
8db585f581 | |||
e03e950879 | |||
2b93d6d184 | |||
d7562b98c1 | |||
f5f44da5f6 | |||
1fd6c4e221 | |||
96ce9233ff | |||
c07a2c957b | |||
8d081bedb0 | |||
3b1bb9d531 | |||
5af7c5276a | |||
5c7fb3e1cf | |||
397379bca3 | |||
475f77d30f | |||
d5c2df7365 | |||
83a28bd25b | |||
3f2c35f4cb | |||
8a9687c007 | |||
d50bdd0051 | |||
0c65bd9891 | |||
222e846881 | |||
a24b1fc677 | |||
a8005917eb | |||
97bc0aa05b | |||
6cd4c73438 | |||
9694d1a5a0 | |||
e245ecca3c | |||
3f0231be3f | |||
a1b3d4efa4 | |||
8269e097d6 | |||
dcc68154b2 | |||
81dc694a23 | |||
5b6408b06b | |||
b7ad1e0633 | |||
1b5701a659 | |||
e01d8d5e1a | |||
44b5aa305c | |||
c94ef4d990 | |||
2c0d50a401 | |||
1af0d1f5bc | |||
504bdbd4ba | |||
c364dca5e5 | |||
8d0f80f821 | |||
4cedfda19b | |||
40b7dcedf8 | |||
24a90b24e8 | |||
d7153bf0b6 | |||
ad56890ee9 | |||
2d7ceb4b43 | |||
4c17f26915 | |||
024a5b2e21 | |||
9e9d2c5190 | |||
e5e707eb54 | |||
b3894f1600 | |||
b0e543177b | |||
ba1c0eedbd | |||
ac1cc172f7 | |||
6a8af7727e | |||
91e65bb35a | |||
0a5523f234 | |||
ce63020b34 | |||
40ccb7d476 | |||
062e98d714 | |||
69e23a9ca3 | |||
26ff717b50 | |||
e6891b39cc | |||
dc3d80d707 | |||
2f9f4d9397 | |||
91c493c818 | |||
c4c26e0e19 | |||
3b42abc027 | |||
71be9c5fb3 | |||
4ade9ad1a0 | |||
ac195acd2f | |||
1029db6342 | |||
ab224eda8e | |||
94dd38d010 | |||
a9ac962051 | |||
e71361dcca | |||
659f98910d | |||
80a788617e | |||
9644ad0b4e | |||
4f3053bc8e | |||
0cbf308d95 | |||
b04ebd9c71 | |||
97bfa178d1 | |||
cd0e262e56 | |||
643d692259 | |||
3b18f56376 | |||
b89882e1cf | |||
c31c00e8cd | |||
d399922de6 | |||
fb5e88a175 | |||
f42c4b7e44 | |||
708c53c64d | |||
ca92a0e6a8 | |||
90266f044b | |||
afa4d383e0 | |||
8a12f23b69 | |||
920de10025 | |||
0fb3a1ca75 | |||
ddca5f687e | |||
4e3c386942 | |||
2015e0e0aa | |||
13ab117b1b | |||
73f27f730b | |||
0273330cf4 | |||
60a530b900 | |||
7a52f2f051 | |||
8cf1bde879 | |||
182c6e2956 | |||
9d8849a425 | |||
3f6df79885 | |||
92ccd189e7 | |||
069870cd0d | |||
54354e4f54 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,5 +1,4 @@
|
||||
/limine
|
||||
/iso_root
|
||||
/base_root
|
||||
*.iso
|
||||
*.img
|
||||
|
60
Makefile
60
Makefile
@ -1,49 +1,47 @@
|
||||
.PHONY: all clean prepare cleanall iso base
|
||||
.PHONY: clean prepare cleanall iso base kernel user test
|
||||
|
||||
all:
|
||||
make -C kernel all
|
||||
ARCH ?= x86_64
|
||||
|
||||
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:
|
||||
if [ ! -d limine ]; then \
|
||||
mkdir limine; \
|
||||
git clone https://github.com/limine-bootloader/limine.git --branch=v9.x-binary --depth=1; \
|
||||
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; \
|
||||
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:
|
||||
make clean
|
||||
rm -rf limine
|
||||
rm -rf littlefs-fuse
|
||||
|
||||
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
|
||||
|
||||
base:
|
||||
@rm -f base.img
|
||||
@rm -rf base_root
|
||||
@mkdir -p base_root
|
||||
mklittlefs -c base_root -b 4096 -s $$((1<<20)) base.img
|
||||
./scripts/mkbaseimg.sh
|
||||
|
||||
iso:
|
||||
@rm -rf iso_root
|
||||
@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
|
||||
|
||||
./scripts/mkiso.sh
|
||||
|
3
base/bin/.gitignore
vendored
Normal file
3
base/bin/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
*
|
||||
!.gitignore
|
||||
!.gitkeep
|
0
base/bin/.gitkeep
Normal file
0
base/bin/.gitkeep
Normal file
3
base/scripts/init.tb
Normal file
3
base/scripts/init.tb
Normal 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
|
3
base/scripts/rc.tb
Normal file
3
base/scripts/rc.tb
Normal file
@ -0,0 +1,3 @@
|
||||
mkalias pctl base:/bin/pctl
|
||||
mkalias tb base:/bin/tb
|
||||
mkalias fs base:/bin/fs
|
6292
dlmalloc/malloc.c
Normal file
6292
dlmalloc/malloc.c
Normal file
File diff suppressed because it is too large
Load Diff
12
dlmalloc/malloc.h
Normal file
12
dlmalloc/malloc.h
Normal 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_
|
@ -1,19 +1,23 @@
|
||||
include $(ROOT)/mk/grabsrc.mk
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
ARCH ?= x86_64
|
||||
PUTCHAR_ ?= fb
|
||||
|
||||
CFLAGS := -ffreestanding -Wall -Wextra -g -fcommon -nostdinc
|
||||
|
||||
CFLAGS += -I. \
|
||||
-I../limine \
|
||||
-I./std/include \
|
||||
-I./flanterm/src \
|
||||
-DPRINTF_INCLUDE_CONFIG_H=1 \
|
||||
-DLFS_NO_ASSERT \
|
||||
-DLFS_NO_DEBUG \
|
||||
-DLFS_NO_WARN \
|
||||
-DLFS_NO_ERROR
|
||||
-I$(ROOT)/limine \
|
||||
-I$(ROOT)/std/include \
|
||||
-I./std \
|
||||
-I./flanterm/src \
|
||||
-I$(ROOT)/share \
|
||||
-DPRINTF_INCLUDE_CONFIG_H=1 \
|
||||
-DLFS_NO_ASSERT \
|
||||
-DLFS_NO_DEBUG \
|
||||
-DLFS_NO_WARN \
|
||||
-DLFS_NO_ERROR \
|
||||
-DUACPI_BAREBONES_MODE
|
||||
|
||||
ifeq ($(PUTCHAR_),fb)
|
||||
CFLAGS += -DPUTCHAR_=PUTCHAR_FB
|
||||
@ -24,36 +28,42 @@ endif
|
||||
include arch/$(ARCH)/$(ARCH).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) \
|
||||
$(wildcard printf/*.c) \
|
||||
$(wildcard bitmap/*.c) \
|
||||
$(wildcard pmm/*.c) \
|
||||
$(wildcard bootinfo/*.c) \
|
||||
$(wildcard spinlock/*.c) \
|
||||
$(wildcard term/*.c) \
|
||||
$(wildcard vmm/*.c) \
|
||||
$(wildcard dlmalloc/*.c) \
|
||||
$(wildcard vfs/*.c) \
|
||||
$(wildcard storedev/*.c) \
|
||||
$(wildcard util/*.c) \
|
||||
$(wildcard fs/kvfs/*.c) \
|
||||
$(wildcard fs/littlefs/*.c) \
|
||||
$(wildcard fs/portlfs/*.c) \
|
||||
$(wildcard baseimg/*.c) \
|
||||
$(wildcard hal/*.c) \
|
||||
$(wildcard hal/$(ARCH)/*.c) \
|
||||
$(wildcard hal/$(ARCH)/*.S) \
|
||||
$(wildcard paging/$(ARCH)/*.c) \
|
||||
$(wildcard paging/*.c) \
|
||||
$(wildcard *.S) \
|
||||
$(wildcard std/*.c) \
|
||||
$(wildcard flanterm/src/*.c) \
|
||||
$(wildcard flanterm/src/flanterm_backends/*.c)
|
||||
CFILES := $(filter %.c,$(SRCFILES))
|
||||
ASFILES := $(filter %.S,$(SRCFILES))
|
||||
OBJ := $(patsubst %.c,%.o,$(CFILES)) $(patsubst %.S,%.o,$(ASFILES))
|
||||
SRCFILES :=
|
||||
|
||||
SRCFILES += $(call GRABSRC, \
|
||||
. \
|
||||
printf \
|
||||
bitmap \
|
||||
pmm \
|
||||
bootinfo \
|
||||
spinlock \
|
||||
term \
|
||||
dlmalloc \
|
||||
vfs \
|
||||
storedev \
|
||||
util \
|
||||
fs/kvfs \
|
||||
fs/littlefs \
|
||||
fs/portlfs \
|
||||
baseimg \
|
||||
proc \
|
||||
hal \
|
||||
hal/$(ARCH) \
|
||||
std \
|
||||
flanterm/src \
|
||||
flanterm/src/flanterm_backends \
|
||||
syscall \
|
||||
path \
|
||||
rbuf \
|
||||
ipc/pipe \
|
||||
dev \
|
||||
)
|
||||
|
||||
CFILES := $(call GET_CFILES, $(SRCFILES))
|
||||
ASFILES := $(call GET_ASFILES, $(SRCFILES))
|
||||
OBJ := $(call GET_OBJ, $(SRCFILES))
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
@ -1,5 +1,4 @@
|
||||
CC := x86_64-elf-gcc
|
||||
LD := x86_64-elf-ld
|
||||
include $(ROOT)/mk/arch/toolchain-x86_64.mk
|
||||
|
||||
CFLAGS += -m64 \
|
||||
-fPIE \
|
||||
@ -12,7 +11,7 @@ CFLAGS += -m64 \
|
||||
-mno-red-zone \
|
||||
-fno-stack-protector \
|
||||
-fno-stack-check \
|
||||
-fno-lto
|
||||
-Os \
|
||||
|
||||
LDFLAGS += -m elf_x86_64 \
|
||||
-pie \
|
||||
|
6
kernel/atomic.h
Normal file
6
kernel/atomic.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef ATOMIC_H_
|
||||
#define ATOMIC_H_
|
||||
|
||||
#define ATOMIC(X) _Atomic(X)
|
||||
|
||||
#endif // ATOMIC_H_
|
@ -32,7 +32,7 @@ void baseimg_init(void) {
|
||||
hal_hang();
|
||||
} else {
|
||||
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++) {
|
||||
kprintf("%02X ", ((uint8_t *)(baseimg->address))[i]);
|
||||
if (i > 0 && (i + 1) % 10 == 0) {
|
||||
|
@ -2,8 +2,8 @@
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include "bitmap.h"
|
||||
|
||||
#define DIV_ROUNDUP(num, div) ((num + div - 1) / div)
|
||||
#include "util/util.h"
|
||||
#include "kprintf.h"
|
||||
|
||||
void *bitmap_toptr(BitMap *bm, size_t block) {
|
||||
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) {
|
||||
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 nblocks = DIV_ROUNDUP(total, BITMAP_BLOCK_SIZE);
|
||||
size_t nbytes = DIV_ROUNDUP(nblocks, 8);
|
||||
size_t nblocks = _DIV_ROUNDUP(total, BITMAP_BLOCK_SIZE);
|
||||
size_t nbytes = _DIV_ROUNDUP(nblocks, 8);
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
@ -59,7 +59,7 @@ void bitmap_markregion(BitMap *bm, void *baseptr, size_t size, bool is_used) {
|
||||
|
||||
if (is_used) {
|
||||
base = bitmap_toblock(bm, baseptr);
|
||||
size1 = DIV_ROUNDUP(size, BITMAP_BLOCK_SIZE);
|
||||
size1 = _DIV_ROUNDUP(size, BITMAP_BLOCK_SIZE);
|
||||
} else {
|
||||
base = bitmap_toblock(bm, baseptr);
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "hal/hal.h"
|
||||
|
||||
typedef struct {
|
||||
uint8_t *map;
|
||||
size_t nblocks;
|
||||
@ -12,11 +14,10 @@ typedef struct {
|
||||
size_t alloc_blocks;
|
||||
size_t last_deep_frag;
|
||||
uintptr_t mem_start;
|
||||
bool init;
|
||||
} BitMap;
|
||||
|
||||
#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)
|
||||
|
||||
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);
|
||||
void *bitmap_alloc(BitMap *bm, 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_
|
||||
|
@ -6,68 +6,46 @@
|
||||
|
||||
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,
|
||||
.revision = 0,
|
||||
#if defined(__x86_64__)
|
||||
.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 = {
|
||||
.id = LIMINE_KERNEL_ADDRESS_REQUEST, .revision = 0,
|
||||
};
|
||||
|
||||
static volatile struct limine_hhdm_request HHDM_REQ = {
|
||||
.id = LIMINE_HHDM_REQUEST, .revision = 0,
|
||||
};
|
||||
|
||||
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,
|
||||
};
|
||||
DEFINE_REQ(kernel_address, KERNEL_ADDRESS);
|
||||
DEFINE_REQ(hhdm, HHDM);
|
||||
DEFINE_REQ(memmap, MEMMAP);
|
||||
DEFINE_REQ(smp, SMP);
|
||||
DEFINE_REQ(rsdp, RSDP);
|
||||
DEFINE_REQ(framebuffer, FRAMEBUFFER);
|
||||
DEFINE_REQ(module, MODULE);
|
||||
|
||||
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();
|
||||
}
|
||||
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;
|
||||
|
||||
struct limine_paging_mode_response *pagingres = PAGING_REQ.response;
|
||||
#if defined(__x86_64__)
|
||||
struct limine_paging_mode_response *pagingres = paging_req.response;
|
||||
if (pagingres->mode != LIMINE_PAGING_MODE_X86_64_4LVL) {
|
||||
#endif
|
||||
hal_hang();
|
||||
}
|
||||
|
||||
struct limine_hhdm_response *hhdmres = HHDM_REQ.response;
|
||||
struct limine_hhdm_response *hhdmres = hhdm_req.response;
|
||||
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_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_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_bspindex = (uint64_t)(-1);
|
||||
@ -93,6 +71,6 @@ void bootinfo_init(void) {
|
||||
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;
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ typedef struct {
|
||||
uint64_t smp_bspindex;
|
||||
LIMINE_PTR(struct limine_framebuffer *) fb;
|
||||
LIMINE_PTR(struct limine_module_response *) modules;
|
||||
LIMINE_PTR(struct limine_executable_file_response *) exec;
|
||||
} BootInfo;
|
||||
|
||||
extern BootInfo BOOT_INFO;
|
||||
|
@ -1,6 +1,9 @@
|
||||
#ifndef 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_
|
||||
|
6
kernel/compiler/builtins.h
Normal file
6
kernel/compiler/builtins.h
Normal 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
22
kernel/dev/dev.c
Normal 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
28
kernel/dev/dev.h
Normal 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
29
kernel/dev/fbdev.c
Normal 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
7
kernel/dev/fbdev.h
Normal 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_
|
256
kernel/dev/ps2kbdev.c
Normal file
256
kernel/dev/ps2kbdev.c
Normal file
@ -0,0 +1,256 @@
|
||||
#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,
|
||||
};
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
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
10
kernel/dev/ps2kbdev.h
Normal 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
81
kernel/dev/serialdev.c
Normal 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
10
kernel/dev/serialdev.h
Normal 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
22
kernel/dev/termdev.c
Normal 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
11
kernel/dev/termdev.h
Normal 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_
|
73
kernel/dlmalloc/dlmalloc_port.inc
Normal file
73
kernel/dlmalloc/dlmalloc_port.inc
Normal 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
1
kernel/dlmalloc/malloc.c
Symbolic link
@ -0,0 +1 @@
|
||||
../../dlmalloc/malloc.c
|
@ -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
1
kernel/dlmalloc/malloc.h
Symbolic link
@ -0,0 +1 @@
|
||||
../../dlmalloc/malloc.h
|
355
kernel/elf.h
Normal file
355
kernel/elf.h
Normal 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_
|
@ -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
345
kernel/fm-t-437.f16.h
Normal 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;
|
@ -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;
|
||||
}
|
||||
|
@ -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_
|
@ -5,96 +5,216 @@
|
||||
#include "errors.h"
|
||||
#include "kprintf.h"
|
||||
#include "dlmalloc/malloc.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;
|
||||
}
|
||||
#include "hal/hal.h"
|
||||
|
||||
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);
|
||||
if (err != E_OK) {
|
||||
return err;
|
||||
}
|
||||
err = lfs_unmount(&vmp->fs.littlefs.instance);
|
||||
if (err < 0) { return E_GENERIC_ERROR; }
|
||||
if (err < 0) { return E_BADIO; }
|
||||
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);
|
||||
|
||||
LittleFs *fs = &vmp->fs.littlefs;
|
||||
switch (type) {
|
||||
case VFS_CREATE_DIR:
|
||||
CHECK(lfs_mkdir(&fs->instance, path));
|
||||
break;
|
||||
case VFS_CREATE_FILE: {
|
||||
lfs_file_t file;
|
||||
CHECK(lfs_file_open(&fs->instance, &file, path, LFS_O_CREAT | LFS_O_WRONLY));
|
||||
CHECK(lfs_file_close(&fs->instance, &file));
|
||||
} break;
|
||||
int ok = lfs_stat(&vmp->fs.littlefs.instance, path, &info);
|
||||
if (ok < 0) {
|
||||
spinlock_release(&vmp->spinlock);
|
||||
return E_BADIO;
|
||||
}
|
||||
|
||||
if (info.type == LFS_TYPE_REG) {
|
||||
statbuf->type = IOCTLSTAT_FILE;
|
||||
statbuf->size = info.size;
|
||||
} 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);
|
||||
return E_OK;
|
||||
bad:
|
||||
spinlock_release(&vmp->spinlock);
|
||||
return E_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
bool littlefs_check(void) {
|
||||
return true;
|
||||
int32_t littlefs_mkdir(struct VfsMountPoint *vmp, const char *path) {
|
||||
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) {
|
||||
@ -119,3 +239,4 @@ int portlfs_sync(const struct lfs_config *c) {
|
||||
(void)c;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -4,21 +4,22 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "fs/littlefs/lfs.h"
|
||||
#include "sysdefs/ioctl.h"
|
||||
|
||||
#define LITTLEFS_BLOCK_SIZE 4096
|
||||
|
||||
struct VfsMountPoint;
|
||||
struct VfsObj;
|
||||
|
||||
typedef struct {
|
||||
lfs_t instance;
|
||||
} 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);
|
||||
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_prog(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size);
|
||||
|
@ -18,9 +18,14 @@ size_t hal_strcspn(const char *s, const char *reject);
|
||||
size_t hal_strspn(const char *s, const char *accept);
|
||||
char *hal_strcpy(char *dest, const char *src);
|
||||
char *hal_strchr(const char *s, int c);
|
||||
void hal_wait(uint32_t ms);
|
||||
|
||||
#if defined(__x86_64__)
|
||||
# define HAL_PAGE_SIZE 0x1000
|
||||
#endif
|
||||
#define HAL_PAGE_SIZE 0x1000
|
||||
#include "x86_64/vmm.h"
|
||||
#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_
|
||||
|
@ -2,8 +2,13 @@
|
||||
#include <stddef.h>
|
||||
#include "compiler/attr.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 {
|
||||
uint16_t limitlow;
|
||||
@ -25,70 +30,63 @@ typedef struct {
|
||||
GdtEntry tsshigh;
|
||||
} PACKED ExtendedGdt;
|
||||
|
||||
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) Tss tss = {0};
|
||||
ALIGNED(16) static ExtendedGdt gdt = {0};
|
||||
|
||||
static Tss tss = {0};
|
||||
static ExtendedGdt *curgdt = NULL;
|
||||
|
||||
#define KCODE 0x08
|
||||
#define KDATA 0x10
|
||||
#define UCODE 0x18
|
||||
#define UDATA 0x20
|
||||
#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_setentry(GdtEntry *ent, uint32_t base, uint32_t limit, uint8_t acc, uint8_t gran) {
|
||||
ent->baselow = base & 0xffff;
|
||||
ent->basemid = (base >> 16) & 0xff;
|
||||
ent->basehigh = (base >> 24) & 0xff;
|
||||
ent->limitlow = limit & 0xffff;
|
||||
ent->gran = ((limit >> 16) & 0x0f) | (gran & 0xf0);
|
||||
ent->access = acc;
|
||||
}
|
||||
|
||||
void gdt_init(void) {
|
||||
uint64_t base = gdt_curretbase();
|
||||
curgdt = (ExtendedGdt *)base;
|
||||
|
||||
hal_memset(&tss, 0, sizeof(tss));
|
||||
tss.iopb_off = sizeof(tss);
|
||||
|
||||
tss.rsp0 = (uint64_t)(kernelstack + sizeof(kernelstack));
|
||||
|
||||
uint64_t tss_base = (uint64_t)&tss;
|
||||
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;
|
||||
tsshigh->baselow = (tss_base >> 32) & 0xffff;
|
||||
tsshigh->basemid = (tss_base >> 48) & 0xff;
|
||||
tsshigh->basehigh = (tss_base >> 56) & 0xff;
|
||||
tsshigh->access = 0;
|
||||
tsshigh->gran = 0;
|
||||
tsshigh->limitlow = 0;
|
||||
gdt_setentry(&gdt.tsslow, tss_base & 0xFFFFFFFF, tss_limit, GDT_PRESENT | GDT_TSS, 0x0);
|
||||
|
||||
uint32_t tssbasehi = tss_base >> 32;
|
||||
gdt.tsshigh.limitlow = tssbasehi & 0xffff;
|
||||
gdt.tsshigh.baselow = (tssbasehi >> 16) & 0xffff;
|
||||
gdt.tsshigh.basemid = 0;
|
||||
gdt.tsshigh.basehigh = 0;
|
||||
gdt.tsshigh.access = 0;
|
||||
gdt.tsshigh.gran = 0;
|
||||
|
||||
GdtPtr gdtr;
|
||||
asm volatile("sgdt %0" : "=m"(gdtr));
|
||||
gdtr.limit = sizeof(ExtendedGdt) - 1;
|
||||
gdtr.limit = sizeof(gdt) - 1;
|
||||
gdtr.base = (uint64_t)&gdt;
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,26 @@
|
||||
#ifndef 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);
|
||||
|
||||
#endif // HAL_GDT_H_
|
||||
|
@ -2,17 +2,17 @@
|
||||
#include <stdbool.h>
|
||||
#include "hal/hal.h"
|
||||
#include "kprintf.h"
|
||||
#include "serial.h"
|
||||
#include "gdt.h"
|
||||
#include "idt.h"
|
||||
#include "intr.h"
|
||||
#include "pic.h"
|
||||
#include "pit.h"
|
||||
|
||||
void hal_init(void) {
|
||||
if (!serial_init()) {
|
||||
hal_hang(); // going further makes no sense
|
||||
}
|
||||
LOG("hal", "serial init\n");
|
||||
gdt_init();
|
||||
idt_init();
|
||||
intr_init();
|
||||
pic_init();
|
||||
pit_init();
|
||||
hal_intr_disable();
|
||||
}
|
||||
|
||||
__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);
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
}
|
@ -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_
|
@ -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
243
kernel/hal/x86_64/intr.c
Normal 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
39
kernel/hal/x86_64/intr.h
Normal 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
221
kernel/hal/x86_64/intr0.S
Normal 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
|
@ -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
28
kernel/hal/x86_64/io.c
Normal 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));
|
||||
}
|
@ -1,7 +1,15 @@
|
||||
#ifndef HAL_IO_H_
|
||||
#define HAL_IO_H_
|
||||
|
||||
extern uint8_t io_inb(uint16_t port);
|
||||
extern void io_outb(uint16_t port, uint8_t value);
|
||||
#include <stdint.h>
|
||||
|
||||
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_
|
||||
|
4
kernel/hal/x86_64/paging.S
Normal file
4
kernel/hal/x86_64/paging.S
Normal file
@ -0,0 +1,4 @@
|
||||
.global hal_loadpd
|
||||
hal_loadpd:
|
||||
mov %rdi, %cr3
|
||||
retq
|
6
kernel/hal/x86_64/paging.h
Normal file
6
kernel/hal/x86_64/paging.h
Normal 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
22
kernel/hal/x86_64/pic.c
Normal 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
25
kernel/hal/x86_64/pic.h
Normal 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
40
kernel/hal/x86_64/pit.c
Normal 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
11
kernel/hal/x86_64/pit.h
Normal 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
33
kernel/hal/x86_64/regs.S
Normal 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
|
@ -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
|
@ -1,8 +0,0 @@
|
||||
#ifndef HAL_SERIAL_H_
|
||||
#define HAL_SERIAL_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
bool serial_init(void);
|
||||
|
||||
#endif // HAL_SERIAL_H_
|
12
kernel/hal/x86_64/switch.S
Normal file
12
kernel/hal/x86_64/switch.S
Normal 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
|
6
kernel/hal/x86_64/switch.h
Normal file
6
kernel/hal/x86_64/switch.h
Normal 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
129
kernel/hal/x86_64/vmm.c
Normal 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
63
kernel/hal/x86_64/vmm.h
Normal 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_
|
@ -4,47 +4,85 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.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) {
|
||||
uint32_t h = HSHTB_FNV32_BASE;
|
||||
static inline uint32_t hshtb_fnv32(const void *data, size_t len) {
|
||||
const unsigned char *p = (const unsigned char *)data;
|
||||
uint32_t h = HSHTB_FNV32_OFF;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
h ^= s[i];
|
||||
h += (h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24);
|
||||
h ^= p[i];
|
||||
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 { \
|
||||
size_t len = sizeof((tb)->name) / sizeof((tb)->name[0]); \
|
||||
size_t idx = hshtb_fnv32(k, hal_strlen(k)) % len; \
|
||||
size_t i = idx; \
|
||||
size_t __len = __HSHTB_ARRAY_LEN(tb); \
|
||||
uint32_t __h = hshtb_fnv32((k), hal_strlen((k))); \
|
||||
size_t __idx = __h % __len; \
|
||||
size_t __start = __idx; \
|
||||
typeof(&(tb)[0]) __tomb = NULL; \
|
||||
(out) = NULL; \
|
||||
do { \
|
||||
if (!(tb)->name[i].taken) { \
|
||||
(out) = &((tb)->name[i]); \
|
||||
hal_memset((out), 0, sizeof(*(out))); \
|
||||
(out)->taken = true; \
|
||||
hal_memcpy((out)->keyname, k, hal_strlen(k)); \
|
||||
if ((tb)[__idx]._hshtbstate == HSHTB_EMPTY) { \
|
||||
typeof(&(tb)[0]) __slot = __tomb ? __tomb : &(tb)[__idx]; \
|
||||
hal_memset(__slot, 0, sizeof(*__slot)); \
|
||||
__slot->_hshtbstate = HSHTB_TAKEN; \
|
||||
hal_memcpy(__slot->keyfield, (k), MIN(sizeof(__slot->keyfield) - 1, hal_strlen((k)))); \
|
||||
(out) = __slot; \
|
||||
break; \
|
||||
} \
|
||||
i = (i + 1) % len; \
|
||||
} while(i != idx); \
|
||||
if ((tb)[__idx]._hshtbstate == HSHTB_TAKEN && hal_strcmp((tb)[__idx].keyfield, (k)) == 0) { \
|
||||
(out) = &(tb)[__idx]; \
|
||||
break; \
|
||||
} \
|
||||
if ((tb)[__idx]._hshtbstate == HSHTB_TOMB && !__tomb) { \
|
||||
__tomb = &(tb)[__idx]; \
|
||||
} \
|
||||
__idx = (__idx + 1) % __len; \
|
||||
} while(__idx != __start); \
|
||||
} while(0)
|
||||
|
||||
#define HSHTB_GET(tb, name, k, keyname, out) \
|
||||
#define HSHTB_GET(tb, keyfield, k, out) \
|
||||
do { \
|
||||
size_t len = sizeof((tb)->name) / sizeof((tb)->name[0]); \
|
||||
size_t idx = hshtb_fnv32(k, hal_strlen(k)) % len; \
|
||||
size_t i = idx; \
|
||||
size_t __len = __HSHTB_ARRAY_LEN(tb); \
|
||||
uint32_t __h = hshtb_fnv32((k), hal_strlen((k))); \
|
||||
size_t __idx = __h % __len; \
|
||||
size_t __start = __idx; \
|
||||
(out) = NULL; \
|
||||
do { \
|
||||
if (hal_memcmp((tb)->name[i].keyname, k, hal_strlen(k)) == 0) { \
|
||||
(out) = &((tb)->name[i]); \
|
||||
if ((tb)[__idx]._hshtbstate == HSHTB_EMPTY) { \
|
||||
break; \
|
||||
} \
|
||||
i = (i + 1) % len; \
|
||||
} while(i != idx); \
|
||||
if ((tb)[__idx]._hshtbstate == HSHTB_TAKEN && hal_strcmp((tb)[__idx].keyfield, (k)) == 0) { \
|
||||
(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)
|
||||
|
||||
#endif // HSHTB_H_
|
||||
|
53
kernel/ipc/pipe/pipe.c
Normal file
53
kernel/ipc/pipe/pipe.c
Normal 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
23
kernel/ipc/pipe/pipe.h
Normal 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_
|
@ -5,11 +5,49 @@
|
||||
#include "bootinfo/bootinfo.h"
|
||||
#include "pmm/pmm.h"
|
||||
#include "term/term.h"
|
||||
#include "paging/paging.h"
|
||||
#include "dlmalloc/malloc.h"
|
||||
#include "vfs/vfs.h"
|
||||
#include "baseimg/baseimg.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);
|
||||
|
||||
@ -19,16 +57,16 @@ void kmain(void) {
|
||||
}
|
||||
|
||||
bootinfo_init();
|
||||
term_init();
|
||||
term_init(BOOT_INFO.fb->address);
|
||||
log_bootinfo();
|
||||
hal_init();
|
||||
pmm_init();
|
||||
paging_init();
|
||||
dlmalloc_check();
|
||||
hal_vmm_init();
|
||||
storedev_init();
|
||||
baseimg_init();
|
||||
vfs_init();
|
||||
dev_init();
|
||||
proc_init();
|
||||
|
||||
kprintf(BANNER_TEXT "\n");
|
||||
|
||||
hal_hang();
|
||||
for(;;);
|
||||
}
|
||||
|
@ -2,8 +2,16 @@
|
||||
#define KPRINTF_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 kvsprintf vsprintf_
|
||||
#define ksnprintf snprintf_
|
||||
|
@ -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_
|
@ -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
41
kernel/path/path.c
Normal 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
6
kernel/path/path.h
Normal 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_
|
@ -6,6 +6,7 @@
|
||||
#include "bootinfo/bootinfo.h"
|
||||
#include "spinlock/spinlock.h"
|
||||
#include "util/util.h"
|
||||
#include "hal/hal.h"
|
||||
|
||||
PhysMem PHYS_MEM;
|
||||
|
||||
@ -13,7 +14,6 @@ void pmm_init(void) {
|
||||
spinlock_init(&PHYS_MEM.spinlock);
|
||||
|
||||
BitMap *bm = &PHYS_MEM.self;
|
||||
bm->init = false;
|
||||
|
||||
bm->nblocks = _DIV_ROUNDUP(BOOT_INFO.memmap_total, BITMAP_BLOCK_SIZE);
|
||||
bm->nbytes = _DIV_ROUNDUP(bm->nblocks, 8);
|
||||
@ -40,6 +40,9 @@ void pmm_init(void) {
|
||||
hal_memset(bm->map, 0xff, bm->nbytes);
|
||||
for (size_t i = 0; i < BOOT_INFO.memmap_entrycount; i++) {
|
||||
struct limine_memmap_entry *entry = BOOT_INFO.memmap_entries[i];
|
||||
if (entry == memmap_ent) {
|
||||
continue;
|
||||
}
|
||||
// mark usable as 0 and unusable as 1
|
||||
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;
|
||||
|
||||
LOG("pmm", "phys bitmap init 0x%lx, size = 0x%lx\n", physbegin, bm->nbytes);
|
||||
bm->init = true;
|
||||
}
|
||||
|
||||
void *pmm_alloc(size_t pages) {
|
||||
@ -58,7 +60,7 @@ void *pmm_alloc(size_t pages) {
|
||||
|
||||
if (!phys) {
|
||||
ERR("pmm", "phys memory ran out\n");
|
||||
hal_hang();
|
||||
return NULL;
|
||||
}
|
||||
return (void *)phys;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
1
kernel/printf/printf.c
Symbolic link
1
kernel/printf/printf.c
Symbolic link
@ -0,0 +1 @@
|
||||
../../share/printf/printf.c
|
@ -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
1
kernel/printf/printf.h
Symbolic link
@ -0,0 +1 @@
|
||||
../../share/printf/printf.h
|
@ -1,2 +0,0 @@
|
||||
#define PRINTF_SUPPORT_DECIMAL_SPECIFIERS 0
|
||||
#define PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS 0
|
1
kernel/printf/printf_config.h
Symbolic link
1
kernel/printf/printf_config.h
Symbolic link
@ -0,0 +1 @@
|
||||
../../share/printf/printf_config.h
|
260
kernel/proc/proc.c
Normal file
260
kernel/proc/proc.c
Normal 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
103
kernel/proc/proc.h
Normal 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
34
kernel/rbuf/rbuf.c
Normal 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
21
kernel/rbuf/rbuf.h
Normal 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_
|
@ -1,20 +1,75 @@
|
||||
#include <stdatomic.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.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) {
|
||||
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) {
|
||||
bool unlocked = false;
|
||||
while (!atomic_compare_exchange_weak(&sl->lock, &unlocked, true)) {
|
||||
unlocked = false;
|
||||
irqsave_nested();
|
||||
|
||||
while (atomic_test_and_set_explicit(&sl->lock, memory_order_acquire)) {
|
||||
SPINLOCK_HINT();
|
||||
}
|
||||
}
|
||||
|
||||
void spinlock_release(SpinLock *sl) {
|
||||
atomic_store(&sl->lock, false);
|
||||
atomic_clear_flag_explicit(&sl->lock, memory_order_release);
|
||||
|
||||
irqrestore_nested();
|
||||
}
|
||||
|
||||
|
@ -3,16 +3,10 @@
|
||||
|
||||
#include <stdatomic.h>
|
||||
#include <stdint.h>
|
||||
#include "hal/hal.h"
|
||||
|
||||
typedef struct { atomic_bool lock; } SpinLock;
|
||||
|
||||
// Spin more efficiently - cpu dependant
|
||||
#if defined(__x86_64__)
|
||||
# define SPINLOCK_HINT() asm volatile("pause")
|
||||
#else
|
||||
# define SPINLOCK_HINT()
|
||||
#endif
|
||||
typedef struct {
|
||||
atomic_bool lock;
|
||||
} SpinLock;
|
||||
|
||||
void spinlock_init(SpinLock *sl);
|
||||
void spinlock_acquire(SpinLock *sl);
|
||||
|
@ -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
|
@ -5,12 +5,13 @@
|
||||
#include <stddef.h>
|
||||
#include "spinlock/spinlock.h"
|
||||
#include "ramsd.h"
|
||||
#include "compiler/attr.h"
|
||||
|
||||
enum {
|
||||
STOREDEV_RAMSD,
|
||||
};
|
||||
|
||||
static const char *storedev_strings[] = {
|
||||
UNUSED static const char *storedev_strings[] = {
|
||||
"RAMSD",
|
||||
};
|
||||
|
||||
|
79
kernel/syscall/devctl.c
Normal file
79
kernel/syscall/devctl.c
Normal file
@ -0,0 +1,79 @@
|
||||
#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;
|
||||
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
10
kernel/syscall/devctl.h
Normal 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
205
kernel/syscall/ioctl.c
Normal 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
9
kernel/syscall/ioctl.h
Normal 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
168
kernel/syscall/ipcpipe.c
Normal 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
8
kernel/syscall/ipcpipe.h
Normal 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
Reference in New Issue
Block a user