Compare commits

...

1743 Commits

Author SHA1 Message Date
f77aa65dc5 Kernel: Cleanup accessing userspace memory
Instead of doing page validiation and loading manually we just do simple
memcpy and handle the possible page faults
2026-04-02 16:36:33 +03:00
9589b5984d Kernel: Move USERSPACE_END to lower half
This allows calculating distance to USERSPACE_END from lower half
address
2026-04-02 16:34:47 +03:00
32806a5af3 LibC: Allow "t" in stdio mode 2026-04-02 15:44:50 +03:00
876fbe3d7c LibC: Fix sem_{,timed}wait 2026-04-02 15:43:34 +03:00
c1b8f5e475 LibC: Add and cleanup network definitions 2026-04-02 15:42:00 +03:00
cf31ea9cbe LibC: Add _SC_PHYS_PAGES and _SC_AVPHYS_PAGES 2026-04-02 15:41:26 +03:00
7e6b8c93b4 LibC: Implement strsep 2026-04-02 15:40:23 +03:00
dd2bbe4588 LibC: Implement sched_getcpu 2026-04-02 15:39:36 +03:00
e01e35713b LibC: Allow including assert.h multiple times
Some shit seems to depend on this
2026-04-02 15:38:06 +03:00
82d5d9ba58 LibC: Write memchr, memcmp and strlen with sse 2026-04-02 15:35:03 +03:00
d168492462 WindowServer: bind volume up/down to volume control 2026-04-02 15:24:02 +03:00
6f2e8320a9 TaskBar: Show current volume level 2026-04-02 15:22:42 +03:00
bf4831f468 AudioServer: Add support for volume control 2026-04-02 15:21:38 +03:00
5647cf24d2 Kernel: Implement volume control to audio drivers 2026-04-02 15:14:27 +03:00
85f61aded5 BAN: Use builtins for math overflow 2026-04-02 14:49:12 +03:00
21639071c2 kill: Allow killing with process name 2026-04-02 05:02:05 +03:00
68506a789a Kernel: Add support for volume control keys 2026-04-02 05:02:05 +03:00
d9ca25b796 LibC: Add FNM_CASEFOLD and FNM_IGNORECASE
These are part of POSIX issue 8
2026-03-25 04:27:00 +02:00
e9c81477d7 BAN/LibC: Implement remainder
This is basically just fmod but with fprem1 instead of fprem
2026-03-25 01:06:45 +02:00
5c20d5e291 Kernel: HDAudio hide unusable pins and cleanup path finding 2026-03-24 01:16:47 +02:00
f89d690716 Kernel: HDAudio only probe codecs in STATESTS
This removes unnecessary probing that lead to timeouts. Also cap codec
address at 14 instead of 15. My test laptop was duplicating codec 0 at
address 15 leading to duplicate devices.
2026-03-24 00:49:47 +02:00
c563efcd1c AudioServer: Query pins of the asked device and not the current one 2026-03-23 22:57:49 +02:00
dedeebbfbe Kernel: Use ByteRingBuffer with audio buffers 2026-03-23 22:12:40 +02:00
35e2a70de0 AudioServer: Handle client data before disconnecting clients 2026-03-23 20:41:13 +02:00
81d5c86a7a WindowServer: Automatically launch xbanan if installed 2026-03-23 19:39:08 +02:00
db6644bae9 BuildSystem: Set glib-compile- binaries in meson cross file 2026-03-23 19:34:00 +02:00
14f1c1a358 LibC: Implement vsyslog 2026-03-23 19:13:38 +02:00
5be9bc64a2 ports/libxml2: Configure with -shared-libgcc
otherwise it doesn't seem to find libiconv due to __divdc3
2026-03-23 19:09:33 +02:00
64d3a5c8b7 ports: Update zlib 1.3.1->1.3.2
1.3.1 is no longer available at zlib.net
2026-03-23 18:54:57 +02:00
ccb4d13a82 Kernel: Compile EventFD file 2026-03-23 18:25:18 +02:00
cbe835a2c8 DynamicLoader: Add missing strlen definition 2026-03-23 18:23:31 +02:00
6a77754adf LibC: Don't link against libstdc++
This prevented building the toolchain
2026-03-23 18:22:42 +02:00
7d7d5ba734 LibC: Compile eventfd file 2026-03-23 18:22:04 +02:00
684fa1c4b0 ports: Add pixman port
This fixes cairo dependencies
2026-03-23 17:58:39 +02:00
a98d851fde ports: Add gtk3 port 2026-03-23 17:58:39 +02:00
9c3e2dab40 ports: Add pango port 2026-03-23 17:58:39 +02:00
eddb68f2fa ports/mesa: Build with x support 2026-03-23 17:55:57 +02:00
791091174a ports/cairo: Build with x support 2026-03-23 17:50:35 +02:00
dd9280c6ea ports/expat: Add support for shared libraries 2026-03-23 17:48:19 +02:00
a4d83f9fdb ports: Add xbanan port
This allows running x apps on top of my own GUI interface!
2026-03-23 17:47:11 +02:00
f42c5c4a5b ports: Add a lot of x library ports + xeyes/xclock 2026-03-23 17:45:59 +02:00
186fa4f1a1 ports: Update git 2.52.0->2.53.0 2026-03-23 17:35:08 +02:00
09292bb87e BAN: Cleanup math code and add SSE sqrt
We should prefer SSE instructions when they are easily available. For
other functions x87 is just simpler. It's hard to write faster and close
to as accurate approximations with SSE.

This does not use xmmintrin.h as clangd does not like that file and
starts throwing errors in every file that includes this :)
2026-03-22 22:07:48 +02:00
d18a0de879 Kernel: Fix mprotext for partial regions
if mprotected are did not contain the start of the region, mprotect
would exit early
2026-03-17 23:33:05 +02:00
cdc45935b5 Kernel: Don't allow chdir into non-directories 2026-03-17 22:57:17 +02:00
43e18148a6 LibC: Define SSP things 2026-03-17 20:30:25 +02:00
b0db645248 LibC: Add basic elf.h 2026-03-17 20:25:38 +02:00
07712758a7 BAN: Add default constructor to ipv4address 2026-03-17 20:24:48 +02:00
c1a424a635 Kernel: Implement linux's eventfd 2026-03-17 20:24:06 +02:00
a49588dbc7 DynamicLoader: Fix library lookup for already loaded files 2026-03-17 20:05:05 +02:00
1f22b9b982 DynamicLinker: Implement RTLD_NOLOAD 2026-03-17 20:04:48 +02:00
1d07d8e08e LibC/DynamicLoader: Add support for dynamically loaded TLS
Previously I failed to dlopen if any of the objects contained TLS
section
2026-03-17 20:01:51 +02:00
05b2424fca LibC: Implement more proper random number generator 2026-03-17 19:53:43 +02:00
07201c711e LibC: set endp in string to float conversion error 2026-03-17 19:50:12 +02:00
8fac88c9a6 LibC: Add sincos{,f,l} 2026-03-17 19:42:53 +02:00
c9aafa78ec DynamicLoader: Fix RO section mprotect arguments 2026-03-05 17:57:03 +02:00
e1c337a483 LibC: Fix compile and link flags
We were linking with -nostdlib and manually linked against libgcc. This
does not link with crtbegin and crtend which provides __dso_handle
preventing use of some global C++ constructors inside libc.

Now we just don't link against libc fixing this issue
2026-03-05 16:25:06 +02:00
acebe68dfa DynamicLoader: Fix copy relocation and TLS initialization 2026-03-04 23:04:19 +02:00
eeef945c25 Kernel: Make tty use the new byte ring buffer 2026-02-28 14:53:15 +02:00
a602753bda Kernel: Add front/back/pop_back to ByteRingBuffer 2026-02-28 14:51:35 +02:00
812ae77cd7 Kernel: Make TCP sockets use the new ring buffer
Also fix race condition that sometimes prevented window updates not
being sent after zero window effectively hanging the whole socket
2026-02-28 14:22:08 +02:00
8b8af1a9d9 Kernel: Rewrite pipes using the new ring buffer 2026-02-28 14:20:52 +02:00
493b5cb9b1 Kernel: Implement byte ring buffer
This maps the ring twice right next to each other so we don't have to
care about wrapping around when doing memcpy or accessing the data
2026-02-28 14:18:23 +02:00
1ecd7cc2fe Kernel: Allow protocol specific socket options
I had forgot to remove this condition on the syscall
2026-02-27 19:20:22 +02:00
5c38832456 Kernel: use wake_with_waketime in epoll
We already have the wake time so there is no reason to calculate the
timeout
2026-02-27 19:14:35 +02:00
d16f07a547 Kernel: Print thread id when writing to /dev/debug 2026-02-27 19:12:35 +02:00
54acb05131 Kernel: Don't print "./" prefix with debug functions 2026-02-27 19:10:51 +02:00
9ddf19f605 Kernel: Optimize networking code
Remove buffering from network layer and rework loopback interface.
loopback now has a separate recieve thread to allow concurrent sends and
prevent deadlocks
2026-02-27 19:08:08 +02:00
ff378e4538 Kernel: Cleanup and optimize TCP
We now only send enough data to fill other ends window, not past that.
Previous logic had a but that allowed sending too much data leading to
retransmissions.

When the target sends zero window and later updates window size,
immediately retransmit non-acknowledged bytes.

Don't validate packets through listeing socket twice. The actual socket
will already verify the checksum so the listening socket does not have
to.
2026-02-24 16:20:23 +02:00
2ea0a24795 Kernel: Fix TCP SYN option propagation
Listening socket now forwards TCP options to the newly created socket
2026-02-23 23:00:47 +02:00
acf28d8170 Kernel: Use ring buffers for TCP windows
This speeds up TCP networkign a ton as it doesnt have to do unnecessary
memmoves for each send/receive
2026-02-23 21:10:13 +02:00
666a7bb826 Kernel: Rework TCP window size reporting
We now report actually available window size when sending packets. If
the available window size grows significantly we send an ACK to reflect
this to the remote.
2026-02-23 21:10:13 +02:00
1ac20251cf Kernel: Fix TCP stack crash on retransmission 2026-02-23 17:48:16 +02:00
a318a19fe2 LibGUI/WindowServer: Add fullscreen events
When window's fullscreen state changes we now generate events!
2026-02-23 16:06:48 +02:00
f4a7aec167 LibGUI/WindowServer: Add support for custom cursor origin 2026-02-23 16:06:48 +02:00
9445332499 Kernel: Remove unnecessary interface lookup
This prevented connecting to local sockets listening on INADDR_ANY
2026-02-23 16:06:48 +02:00
8edd63d115 Kernel: Cleanup {set,get}sockopt debug prints 2026-02-23 16:06:48 +02:00
304ace1172 LibInput: Export keyboard layout keymaps 2026-02-23 16:06:48 +02:00
a5cdf0640f BAN: Add value_type to String{,View} 2026-02-23 16:06:48 +02:00
1fc2e43881 BAN: Add support for string format padding 2026-02-23 16:06:48 +02:00
0964c9f928 BAN: Remove unnecessary assert from span 2026-02-23 16:06:48 +02:00
8b1e820869 BAN: Add reallocator support to Vector 2026-02-21 04:03:11 +02:00
9edc6966db BAN: Add reallocator definition
for the moment this does not exist in kernel, kmalloc rewrite soon™️
2026-02-21 04:03:11 +02:00
12207dcb77 BAN: Add is_trivially_copyable trait 2026-02-21 04:03:11 +02:00
2255e36810 LibDEFLATE: Add GZip support
This allows compressing and decompressing with data using GZip headers
and footers
2026-02-21 04:03:11 +02:00
5abddd448e LibC: Fix typo/bug in fnmatch
* would stop matching at '0' instead of end of string
2026-02-19 22:12:59 +02:00
f022a1b08f Shell: Fix crash when executing semicolon
This fixes #4
2026-02-13 17:52:54 +02:00
b3bbfaeff0 LibC: Fix posix_spawnattr_t definition 2026-02-10 01:22:25 +02:00
679a3d4209 LibGUI: Add Texture::clear{,_rect} 2026-02-08 19:45:01 +02:00
a0211d88e7 Kernel: Don't include TCP header in MSS 2026-02-08 19:44:30 +02:00
e216fc7798 Kernel: Fix port allocation endianness 2026-02-08 19:43:08 +02:00
c648ea12f2 Kernel: Cleanup and fix UNIX sockets
EPOLLOUT is now sent to the correct socket and buffer is now a ring
buffer to avoid unnecessary memmove on every packet
2026-02-08 19:38:28 +02:00
2e59373a1e Kernel: Fix non blocking sockets blocking :D 2026-02-08 19:33:28 +02:00
a51a81b6cd Kernel: Move {set,get}sockopt to sockets
Sockets can now actually implement socket options :D
2026-02-08 19:27:16 +02:00
9809f87010 LibC: Fix {read,write}v return value for partial actions 2026-02-08 18:45:29 +02:00
8794122c2d BAN: Variant allow copy/move from empty 2026-02-07 18:54:31 +02:00
8fb2270ecf DynamicLoader: map RO sections actually read only
I was mapping everything RW as i did not have mprotect when I
implemented the dynamic loader.
2026-02-04 23:21:06 +02:00
c304133224 LibC: Indicate regex support in unistd.h 2026-01-25 01:47:30 +02:00
7843d3de62 LibC: Support attrs and file actions in posix spawn
Apparently GCC wants to use posix_spawn now that it is available, this
patch adds support for the missing fields. POSIX Issue 8 did add some
fields that are not supported here
2026-01-25 01:45:47 +02:00
aef536fff3 Kernel: Fix SharedMemoryObject cloning on deleted keys 2026-01-25 01:42:17 +02:00
d472e1ac0e Kernel: Remove obsolete FIXMEs and null pointer checks 2026-01-24 22:42:18 +02:00
120c08fb75 Kernel: Implement fcntl based locks 2026-01-24 22:38:34 +02:00
ba6229b92d Kernel: Fix TCP accept bind address
I was accidentally binding the new socket to the target address instead
of the listening socket's address
2026-01-24 00:33:05 +02:00
3d2362cb5f ports/xash3d-fwgs: Don't apply vorbis patch
I removed the pathes a while ago
2026-01-21 19:20:02 +02:00
a08b9b82a6 Kernel: Fix yield stack pointer value
Stack pointer was pointing to value of return address on return instead
of past it. This did not affect anything as ig Processor::yield() didn't
use stack after calling the trampoline
2026-01-19 00:47:00 +02:00
5d62fa3f10 Kernel: Clenup stacktrace printing on exception
Start from current ip and bp. This removes kernel call stack to debug
printing function from the stack trace
2026-01-16 16:31:35 +02:00
d3df00f0ba Kernel: Make Processor structure default to zero
This moves processor info to bss instead of having it in data section
2026-01-16 16:24:47 +02:00
34e84f8b07 Kernel: Reduce the number of TLB invalidations
Invalidations are not done if mapping or unmapping previously unmapped
page. TLB invalidate IPIs are now ignored if they don't affect the
currently mapped address space
2026-01-16 16:22:29 +02:00
1143dc3cae Kernel: Rework syscall memory validation and locking
Process's memory regions are now behind an rwlock instead of using the
full process lock. This allows most pointer validations to not block as
write operations to memory regions are rare.

Thread's userspace stack is now part of process's memory regions. This
simplifies code that explicitly looped over threads to see if the
accessed address was inside a thread's stack.

Only drawback of this is that MemoryRegions don't support guard pages,
so userspace stackoverflow will be handeled as cleanly as it was prior
to this.

This patch also fixes some unnecessary locking of the process lock and
moves locking to the internal helper functions instead of asserting that
the lock is held. Also we now make sure loaded ELF regions are in sorted
order as we previously expected.
2026-01-16 16:09:38 +02:00
0299d4d44e Kernel/LibC: remove SYS_TERMID
This syscall is not needed. /dev/tty is already a symlink to the
controlling terminal. Also this syscall did not handle pseudo terminals
2026-01-16 15:57:36 +02:00
1d07151743 ports/xash-fwgs: Cleanup patches
Remove patches that are no longer needed and cleanup the general support
patch
2026-01-13 20:51:58 +02:00
a83fa6f4c6 Kernel: Optimize futexes
Eeach futex object now has its own mutex to prevent unnecessary locking
of the process/global futex lock. This basically removes sys_futex from
profiles when running software with llvmpipe
2026-01-13 19:18:52 +02:00
c30fc9d60f LibGUI: Rewrite using epoll
select is slow :^)
2026-01-12 23:53:11 +02:00
311a68160c Kernel: Don't delete futex objects after they are not used anymore
Hashmap insertions and deletions made futex very slow to use. When
running SuperTuxKart, ~15% of cpu time was spent doing these.

Never freeing objects is not great either but at least the performance
is usable now :)
2026-01-12 23:52:04 +02:00
343aef31c3 AudioServer: Rewrite using epoll
select is slow :^)
2026-01-12 23:46:51 +02:00
3ac8f7e14f WindowServer: Rewrite using epoll
Looking at profiles, select is a very slow syscall as it has to allocate
a temporary epoll instance
2026-01-12 23:46:03 +02:00
0cef66d155 Kernel: Fix epoll reporting multiple of the same event 2026-01-12 23:45:17 +02:00
9ffbb9fbf0 LibC: Fix clock_gettime return value 2026-01-11 22:44:03 +02:00
c9a8f5b456 Kernel: Fix ext2 fileystem super block backups
Check if rev >= 1 sets sparse superblock feature instead of assuming it
is set
2026-01-11 19:55:10 +02:00
4e3831e380 Kernel: ACHI use ext commands for LBAs >=24 bits
AFAICS non extended commands are supposed to support 27 bit LBAs but
qemu seems to ignore bits 27:24. Maybe I'm just doing something wrong
but this seems to fix this.

This fixes using big disks :D ATM using using disks >= 8 GiB (with 512
byte LBAs) returned wrong data on reads, failing the boot :D
2026-01-11 15:15:58 +02:00
cae2b3bd14 Kernel: Cleanup ext2 indirect block lookup
If we are not allocating and the block is null, add a fast path to
delete it. This also prevents possibly blocking filesystem block wrapper
allocation
2026-01-11 04:00:04 +02:00
5637b8602b Kernel: Fix setting ext2 symbolic link target
If a link was >= 60 bytes but got shrinked to 60 bytes, reading it would
rebort garbage and unlinking it would leak blocks
2026-01-11 03:58:48 +02:00
4af9699b22 Kernel: Only save/load sse state when it is used
There is no need to save and load sse state on every interrupt. Instead
we can use CR0.TS to make threads trigger an interrupt when they use sse
instructions. This can be used to only save and load sse state when
needed.

Processor now keeps track of its current "sse thread" and the scheduler
either enabled or disabled sse based on which thread it is starting up.
When a thread dies, it checks if it was the current sse thread to avoid
use after free bugs. When load balancing, processor has to save the
thread's sse state before sending it to a new processor (if it was the
current sse thread). This ensures thread's sse state will be correct
when the new processor ends up loading it.
2026-01-11 03:06:39 +02:00
35c97e2ff8 Kernel: optimize yielding
Doing a yield no longer raises a software interrupt. Instead it just
saves all the callee saved registers, ip, sp and return value. Because
yield is only called in the kernel, it can just restore registers and
jump to the target address. There is never a need to use iret :)
2026-01-11 01:31:09 +02:00
83e5cb81e8 ports: Cleanup projects using cmake
There is no need to use $BANAN_CMAKE because our own toolchain directory
is added to path.
2026-01-10 19:32:48 +02:00
7a49a0d986 BuildSystem: Install meson as part of the toolchain
Debian based distros have meson 0.6x in their repositories. These cause
some obscure error messages when building meson based ports.
2026-01-10 19:32:48 +02:00
78cd054d59 BuildSystem: Write my own disk image perm updater
If user's bash does not have bultin stat, updating image perms was
terribly slow. This patch adds a simple c program that does the job
without exec overhead
2026-01-10 17:57:21 +02:00
d33a8eac9c ports/mesa: Download prebuilt llvm instead of building it
compiling llvm takes too long :D
2026-01-10 16:40:12 +02:00
9355ab1656 ports: Add cairo port
This is needed by harfbuzz
2026-01-10 16:21:12 +02:00
1f87bfbf2e ports/SuperTuxKart: Don't disable configure :D 2026-01-10 16:00:24 +02:00
e06429da87 ports: Add SuperTuxKart port 2026-01-10 13:35:07 +02:00
26058763df ports: Add harfbuzz port 2026-01-10 13:32:20 +02:00
1f03d23dae Kernel: Fix load balancing
My code to find least loaded processor used processor index instead of
processor id to index the array. Most of the time this lead to wrong
processor returned as the least loaded, leaving some processors
basically idle.
2026-01-10 01:46:08 +02:00
2eea074473 Kernel: Remove unnecessary page table loads
loading a page table is slow as it invalidates the whole tlb
2026-01-10 01:13:48 +02:00
ed82a18e2a Kernel: Fix deadlock in ext2 filesystem
If multiple threads were waiting for more block buffers without anyone
releasing them, they ended up in a deadlock.

Now we store 6 blocks for 8 threads. If a thread already has a block
buffer, it will not have to wait for a new one. Only if there are more
than 8 threads using blocks, will it block until there are free slots
for a thread available.
2026-01-10 00:30:30 +02:00
2961a49dc7 Kernel: Optimize futexes
Add support for processor local futexes. These work the exact same way
as global ones, but only lock a process specific lock and use a process
specific hash map.

Also reduce the time futex lock is held. There was no need to hold the
global lock while validating addresses in the process' address space.
2026-01-09 22:27:59 +02:00
5c9151d3e9 LibC: Add stubs for {init,set}state
Some port wanted these as it detected we had {,s}random
2026-01-09 22:08:32 +02:00
90deb9fb43 BAN: Make debug output thread safe
Now file lock is only acquired once per message, not once per character
2026-01-09 20:30:35 +02:00
12489a4c6b Kernel: Fix 32 bit target compile and runtime
Apparently I have to reload stack in the fork trampoline. Not sure why
or why not on x86_64. Also sse builtins did not compile
2026-01-09 17:06:57 +02:00
74f70ae4bd Kernel/LibC: Use builtin functions over inline asm
Getting flags and saving/restoring sse state and reading TSC can be done
using compiler builtins
2026-01-09 15:39:19 +02:00
a9ceab0415 Kernel: Use syscall/sysret for syscalls in x86_64 2026-01-09 15:18:58 +02:00
94bd74d0bb BuildSystem: Update qemu script
Default to intel-hda instead of ac97 for audio

If we are accelerating with kvm, use host cpu and disable migratable to
allow invariant TSC
2026-01-08 17:16:20 +02:00
b2d8199480 ports/openal-soft: Add SDL2 as a dependency 2026-01-08 17:13:59 +02:00
e60f3711f8 ports: Update openssl 3.3.1->3.6.0 2026-01-08 17:13:59 +02:00
6ec9e4f7b8 ports: Update freetype 2.13.3->2.14.1 2026-01-08 17:13:59 +02:00
9eb3834ae5 Kernel: Add syscall-less clock_gettime
If the processor has invariant TSC it can be used to measure time. We
keep track of the last nanosecond and TSC values and offset them based
on the current TSC. This allows getting current time in userspace.

The implementation maps a single RO page to every processes' address
space. The page contains the TSC info which gets updated every 100 ms.
If the processor does not have invariant TSC, this page will not
indicate the capability for TSC based timing.

There was the problem about how does a processor know which cpu it is
running without doing syscall. TSC counters may or may not be
synchronized between cores, so we need a separate TSC info for each
processor. I ended up adding sequence of bytes 0..255 at the start of
the shared page. When a scheduler gets a new thread, it updates the
threads gs/fs segment to point to the byte corresponding to the current
cpu.

This TSC based timing is also used in kernel. With 64 bit HPET this
probably does not bring much of a benefit, but on PIT or 32 bit HPET
this removes the need to aquire a spinlock to get the current time.

This change does force the userspace to not use gs/fs themselves and
they are both now reserved. Other one is used for TLS (this can be
technically used if user does not call libc code) and the other for
the current processor index (cannot be used as kernel unconditionally
resets it after each load balance).

I was looking at how many times timer's current time was polled
(userspace and kernel combined). When idling in window manager, it was
around 8k times/s. When running doom it peaked at over 1 million times
per second when loading and settled at ~30k times/s.
2026-01-08 17:13:59 +02:00
ee57cf3e9a Kernel: Expose usb device's device descriptor
This is used by the joystick detection code but i forgot to commit this
:D
2026-01-08 13:46:11 +02:00
fea5d1d82b BAN: Fix wrong include in heap 2026-01-07 22:12:20 +02:00
c84a30d4dd ports/SDL2: Update to new joystick interface 2026-01-07 19:07:42 +02:00
24d91eee90 Kernel/LibInput: Rework Joystick handling
Joystick axis and buttons are now named to standard values, this allows
interfacing multiple different controllers (only DS3 is supported)

Add ioctl calls for userspace to set joystick player leds and rumble

Only use DS3 code paths when we detect that the attached device is
actually an DS3 controller

update test-joystick program to the new interface and add support to
control rumble and player leds
2026-01-07 19:01:07 +02:00
a5318448f5 userspace: Add audioctl utility to configure audio server 2026-01-06 22:26:11 +02:00
b7c40eeb57 AudioServer: Handle multiple audio devices with multiple pins
This makes audio server configurable during runtime!
2026-01-06 22:26:11 +02:00
e7c9be1875 AudioServer: Increase send buffer size and hardcode volume to 20% 2026-01-06 22:26:11 +02:00
8f1b314802 Kernel: Add ioctls to select audio device's output pin 2026-01-06 22:26:11 +02:00
da6794c8ce Kernel: Implement HD audio driver
This is very basic and does not support a lot of stuff (like changing
the output pin :D)
2026-01-06 22:26:10 +02:00
e926beba5a test-mouse: Fix mouse fd cleanup
I was creating a local variable shadowing the global one. This prevented
cleanup to close it. (this is not really necessary as the program dies
anyway)
2026-01-06 21:58:56 +02:00
3ad053cf6d image: Add option to change resize algoritm
Also benchmark timing is now done cpu clock, not monotonic one
2026-01-06 21:58:56 +02:00
bc11469a0b mkdir: Fix mkdir error handling 2026-01-06 21:58:56 +02:00
a00695bdac LibC: Add stubs that I have locally
I'm not sure if these are used by anything but I would assume so as I
have added them :D

functions added:
- getprotobyname
- open_memstream
- munlock
- lockf
- nice
- crypt
- getsid
- wcstoul
2026-01-06 21:58:56 +02:00
89959b800c LibC: Implement random and srandom 2026-01-06 21:58:56 +02:00
3e19c3b62e LibC: Fix timeradd and timersub overflow/underflow 2026-01-06 21:58:56 +02:00
d970debb4d LibC: Define MAXPATHLEN in sys/param.h
This file is not POSIX, but some software seems to rely on it
2026-01-06 21:58:56 +02:00
d0ba52073f LibC: Add stubs for shm_* functions 2026-01-06 21:58:56 +02:00
943e3b6f51 LibC: Define IN_CLASS* macros
These are not POSIX but some software seems to rely on them
2026-01-06 21:58:56 +02:00
25d43682aa LibC: Bump FOPEN_MAX 16->64 2026-01-06 21:58:56 +02:00
ad16de59f8 Kernel: Implement basic F_{GET,SET}LK{,W}
At the moment these lock the whole file which is not what is supposed to
happen. Some port was trying to use these and this seems to work for
that. This may cause deadlocks but that should be easy enough to find
the reason because of the debug warnings
2026-01-06 21:58:56 +02:00
8634bbb792 Kernel: Don't save/restore sse or reschedule on spurious interrupts
I think these should be just fully ignored :D
2026-01-06 21:58:56 +02:00
60ec5d30fd init: Start Clipboard server on startup
I had forgotten to commit this when I added the clipboard server :D
2026-01-06 21:58:56 +02:00
7667fe6ca5 LibC: Implement sem_timedwait 2026-01-06 21:58:56 +02:00
4b5a8196c3 Kernel: Fix bitmap byte index calculation in PMM
No idea how I had not crashed here earlier, but running on real hw with
a bit initrd ended up crashing :D
2026-01-04 01:16:43 +02:00
706c0816dd Kernel: Move smp_initialized flag after schedulers are initialized
Before this real hardware failed to boot with smp enabled. Allocating
the idle thread does a page mapping which ends up broadcasting TLB
shootdown to other processes. This ends up failing somewhere halting the
processors never allowing them to initialize their scheduler
2026-01-03 23:39:07 +02:00
a8aa89362d ports/SDL2: Add support for game controllers
SuperTux and tuxracer now work with controller support!
2026-01-03 20:42:42 +02:00
7964698ae5 userspace: Add simple joystick test app 2026-01-03 20:42:42 +02:00
65664b0d65 Kernel: Add support for DualShock 3 controllers
This driver accepts any HID joystick devices but button and axis
mappings will only work on a PS3 controller
2026-01-03 20:07:08 +02:00
08bfa0971e Kernel: Rework storage device and disk cache locking
Syncing the disk cache no longer blocks the underlying storage device
and the disk cache itself during sync
2026-01-02 18:06:56 +02:00
912c5ea0bf Kernel: Implement basic RWLock 2026-01-02 17:50:22 +02:00
6cdf5a5a7f Kernel: Make AHCI controller thread safe 2026-01-02 17:50:22 +02:00
50ba743faf Terminal: Cleanup CSI handling and add =c,>c,c,E,F 2026-01-02 17:13:46 +02:00
e26aac3067 Kernel: Decrease the number of syncs done by ext2 inodes
Each allocated inode used to call sync(). Each sync reads and writes
a block from the filesystem. Doing a 1 MiB write ended up syncing around
257 times
2026-01-01 23:54:09 +02:00
941e8aa5d5 Kernel: Optimize ext2 filesystem
block lookup can now also allocate blocks so there is no need to do
multiple lookups of the block did not exist
2026-01-01 23:15:35 +02:00
33b6536e6b Kernel: Make disk cache entry lookup O(log n)
I have absolutely no idea why i was doing a linear lookup here :D
2026-01-01 20:40:38 +02:00
9fbd9288b2 Kernel: Fix symlink deletion from tmpfs
Small symlinks store their target in inline storage of data block
indices. Freeing blocks did not account for this and tried to interpret
the link target as block inidices to delete
2026-01-01 20:40:38 +02:00
bef1a56007 ports: Update git 2.48.1->2.52.0
also remove curl link hack as updating curl port fixed the issue
2026-01-01 20:40:38 +02:00
bc71ff5e81 ports: Update curl 8.11.1->8.17.0
This fixes broken DT_NEEDED dependencies in curl!
2026-01-01 20:40:38 +02:00
bd50444d06 ports: Update ca-certificates 2024-07-02 -> 2025-12-02 2025-12-31 19:28:55 +02:00
2efd6f92b2 rm: add -f and -i options
rm *should* now be posix compatible
2025-12-31 19:28:55 +02:00
7fdfad4088 Kernel: Mount /tmp with sticky bit set 2025-12-31 19:28:55 +02:00
31a1968798 Kernel: Cleanup scheduling while idling
If there are no threads in the run queue and we are idle, attempt to
wake up threads from the sleep queue
2025-12-31 19:28:55 +02:00
b0bd4ad546 Kernel: Fix dup2 return value
We returned the wrong fd number :D
2025-12-31 19:28:55 +02:00
dc454b9a6a Kernel: Fix SA_RESETHAND handling order
if SA_RESETHAND was set, alt stack would not get used
2025-12-31 19:28:55 +02:00
f06e5d33e7 Kernel: Rework socket binding to an address
Sockets are no longer bound to an interface, but an ipv4 address. This
allows servers at 0.0.0.0 talk to multiple different interfaces
2025-12-31 19:28:55 +02:00
efdbd1576f ports/SDL2: disable static lib and enable semaphores
Also add libiconv as a dep so SDL_iconv_string etc works
2025-12-28 15:30:02 +02:00
0421fbdc25 LibC: Implement sem_getvalue 2025-12-28 15:29:37 +02:00
bd426199f8 Kernel: Remove unused (and broken) code from signal trampoline 2025-12-28 03:53:38 +02:00
8e00b3d110 ports: Add ffmpeg port
This allows basic video and audio playback on banan-os!
2025-12-28 00:12:03 +02:00
6fbf1469aa LibC: define static_assert in assert.h
This is needed from C11 until C23
2025-12-28 00:12:03 +02:00
280d3fd919 LibC: Fix assert.h include guard 2025-12-28 00:12:03 +02:00
40ce95b87f LibC: Add definition for TCP_MAXSEG
This is not implemented yet
2025-12-27 23:37:03 +02:00
e7d644b874 AudioServer: Fix rounding the number of samples when resampling
If client tried to play a single sample at lower frequency as the
kenrel, audio server would never play it leading to the client hanging

This makes calculations round the number of samples always up to fix
this
2025-12-18 16:05:28 +02:00
c64159d5c3 AudioServer: Fix resampling math
This caused resampled audio to freeze the whole audio system after few
minutes of playing (like doom)
2025-12-18 14:59:55 +02:00
e2ccc3026f BAN: Remove unnecessary c++ header inclusion 2025-12-16 16:44:42 +02:00
2af6066ee3 LibC: Fix sysconf(_SC_OPEN_MAX) 2025-12-16 05:20:18 +02:00
fc16b5331c LibC: Fix backtrace compilation
Also dump backtrace on SIGABRT
2025-12-16 05:20:00 +02:00
b2723a0c5f aoc2025: Implement day12 solution 2025-12-15 19:06:17 +02:00
01042a24f0 aoc2025: Implement day11 solution 2025-12-15 17:57:45 +02:00
f9643b3881 aoc2025: Implement day10 solution 2025-12-15 14:42:03 +02:00
d2d18bea5d aoc2025: Implement day9 solution 2025-12-13 03:09:15 +02:00
87e595b83e aoc2025: Implement day8 solution 2025-12-12 22:37:03 +02:00
08031b1227 aoc2025: Implement day7 solution 2025-12-12 21:15:22 +02:00
9a87c1f734 aoc2025: Implement day6 solution 2025-12-12 20:17:12 +02:00
edeb667ead aoc2025: Implement day5 solution 2025-12-12 06:30:03 +02:00
db2aa495b8 aoc2025: Implement day4 solution 2025-12-12 06:08:00 +02:00
ddfb591094 aoc2025: Implement day3 solution 2025-12-12 04:34:40 +02:00
e8f1ba3722 aoc2025: Implement day2 solution 2025-12-12 02:49:33 +02:00
19c4f34ccb aoc2025: Implement day1 solution 2025-12-12 02:49:10 +02:00
5d9e9c021a aoc2025: Prepare programming environment 2025-12-12 02:48:40 +02:00
6a924db68c Kernel: Implement FIONREAD for tty and pty 2025-11-24 18:15:10 +02:00
9d0990e5e8 Kernel: Implement /proc/<n>/fd 2025-11-24 00:19:51 +02:00
3207f5d61f Kernel: Fix possible page fault on file lookup 2025-11-23 19:49:07 +02:00
c72b351bba LibC: Implement glob{,free} 2025-11-23 05:33:44 +02:00
1f9b296ae7 cp: Add -r/--recursive flag 2025-11-23 02:25:05 +02:00
e3e2e7b4df userspace: Implement mv utility 2025-11-23 02:24:52 +02:00
4ec8f4a4bf Kernel/LibC: Implement rename{,at} 2025-11-22 23:55:10 +02:00
05d59a05df Kernel: Remove obsolete kprint
This hasn't been in use in 3 years :)
2025-11-22 06:21:50 +02:00
11ccbe6506 ports/SDL2: Add clipboard support 2025-11-22 01:24:06 +02:00
673711a246 ports/mesa: Require llvm
I dont't really even want to suppot softpipe as that is so slow
2025-11-22 00:40:14 +02:00
fff5139d80 Kernel: Add /proc/<n>/cwd
Also update /proc/<n>/* permissions to match what linux does :D
2025-11-18 05:40:36 +02:00
812e70c626 ports: Add zsh port 2025-11-18 05:40:36 +02:00
db7ffcf9d5 Kernel/Terminal: Add support for bracketed paste mode
This gets rid of annoying warnings when running some programs like bash
2025-11-18 05:40:36 +02:00
8f6cb9c057 Terminal: Add selection and clipboard support
text can now be copied with ctrl+shift+c and pasted with ctrl+shift+v
2025-11-18 05:40:36 +02:00
291f298d19 userspace: Implement LibClipboard and ClipboardServer
programs can now connect to the clipboard server using libclipboard and
get and set the clipboard of the current user
2025-11-18 05:40:36 +02:00
d60f12d3b8 Kernel: Add support for SCM_CREDENTIALS and fix recvmsg
recvmsg was broken when receiving into more than a single iovec
2025-11-18 05:40:36 +02:00
b8a2573bb4 userspace: Implement ImageViewer utility
This supports viewing images and doing basic zooming and panning
2025-11-17 20:58:12 +02:00
7ce8e610f5 stat: Fix handling of symlinks 2025-11-17 05:26:07 +02:00
839b9c8f07 Kernel: Check parent's sticky bit in unlink 2025-11-17 05:26:07 +02:00
db20801521 Shell: Add exec builtin 2025-11-17 05:26:07 +02:00
160a9278c9 LibC: Fix RTLD_* definitions 2025-11-17 05:26:07 +02:00
ee507de154 LibC: Implement posix regex
This is an almost complete implementation, it does not support
alternations or collating elements and it is restricted to the ASCII
character set
2025-11-17 05:26:07 +02:00
dc0fa49de2 ports/tuxracer: Add sound support and fix compiling 2025-11-17 05:26:07 +02:00
b678541427 ports: Add SDL_mixer port 2025-11-17 05:26:07 +02:00
6c4cd0d8cb ports: Add libmikmod port 2025-11-17 05:26:07 +02:00
c096d3cd42 ports/sdl12-compat: Define that banan-os has alloca.h 2025-11-17 05:26:07 +02:00
dcdab4df21 ports/sdl12-compat: Remove unnecessary patch
This is not needed as our SDL2 library is in the expected form
2025-11-17 05:26:07 +02:00
9803209ba1 WindowServer: Make clients nonblock
Also dont allow freezed windows to "steal" focus and lock up the window
server :D
2025-11-17 05:26:07 +02:00
f166cb09ec Kernel: Fail xHCI initialization if page size != 4096
Also zero out scratchapd buffers as the spec says
2025-11-17 05:26:07 +02:00
2dd8b76289 BuildSystem: Automatically delete libtool files
Half of the ports had a manual post_install step to delete libtool files
this is now done automatically and there is no need for it!

Libtool files have to be deleted as libtool doesn't work while
cross-compiling (at least out of the box)
2025-11-17 05:26:07 +02:00
2bf7c67767 LibC: Add backtrace signal handlers for SIG{FPE,ILL,BUS,SEGV}
This allows programs to dump better backtraces on crashes compared to
what kernel can as libc can resolve symbols and libraries' dynamic bases
2025-11-17 05:26:07 +02:00
dd636ffcb2 Kernel: Add support for SA_SIGINFO 2025-11-17 05:26:07 +02:00
a44c45ff9e LibC: Cleanup signal.h
Make sa_handler and sa_sigaction be part of an union

Add definitions of SIGIO TRAP_BRKPT TRAP_TRACE
2025-11-17 05:26:07 +02:00
dc2a455395 Kernel: Optimize processes' memory management
Memory regions are now stored in a sorted array. This allows O(nlogn)
lookup for address validation instead of the old linear lookup.

Now inserting new regions is also O(nlogn) instead of the old constant
time, but lookups are **much** more frequent
2025-11-17 05:26:07 +02:00
c700d9f714 Kernel: Implement connect for UDP socket 2025-11-17 05:26:07 +02:00
59cfc339b0 Kernel: Ignore MSG_NOSIGNAL and invalid flags 2025-11-17 05:26:07 +02:00
e06c07ca89 ports: Update binutils 2.44->2.45
Now we don't have to keep patches for both versions around :D
2025-11-17 05:26:07 +02:00
6facd54a7e LibC: Add ru_maxrss to struct rusage
This is not required by posix but some ports use it
2025-11-17 05:26:07 +02:00
6f8d850726 BuildSystem: Cleanup port building script
All dependencies are now installed only ones. If a port depends on for
examle zlib and one of its other dependencies depends on zlib, zlib will
now get installe only once.

Accept .tgz archives as the main download file
2025-11-17 05:26:07 +02:00
f3beee9874 Kernel: Cleanup userspace pointer validation 2025-11-17 02:33:00 +02:00
35e063bdaf Kernel: Dump r8-r15 on x86_64 exceptions 2025-11-17 02:33:00 +02:00
09175d1799 Kernel: Fix 32 bit target
Rewrite some assembly and add some required casts
2025-11-17 02:33:00 +02:00
46f9a9053f DynamicLoader: Use canonical path for the main executable 2025-11-13 04:20:53 +02:00
bb86520094 Kernel: Set message flags in UDP and TCP recvmsg 2025-11-13 04:20:53 +02:00
c1e2c660bf LibC: Define caddr_t
This is used by some ports
2025-11-13 04:20:53 +02:00
89c0ff1a9d Kernel/LibC: Replace SYS_{GET,SET}_TLS with SYS_{SET,GET}_{FS,GS}BASE
This allows userspace to use both registers
2025-11-13 04:20:53 +02:00
7a68ce7e94 DynamicLoader: Fix testing for possible base address
Replace MAP_FIXED with MAP_FIXED_NOREPLACE and only attempt to map
program headers with PT_LOAD
2025-11-13 04:20:53 +02:00
9537922acc Kernel: Implement proper memory region splitting
Memory regions are now splitted when they get munmapped, mprotected, or
mmapped with MAP_FIXED. This is used by couple of ports, and without
this we were just leaking up memory or straight up crashing programs.
2025-11-13 04:20:53 +02:00
a39aa73e21 Kernel: Allow munmap on non-page aligned address 2025-11-12 00:06:36 +02:00
f1d12c330e Kernel/LibC: Implement MMAP_FIXED_NOREPLACE
This is a handy thing from linux

Also fix MMAP_FIXED validation and error reporting
2025-11-12 00:06:36 +02:00
82c8eeb4be ports/openssh: Update to 10.2p1 and enable fd passing 2025-11-12 00:06:36 +02:00
3a951f4830 LibC: Define IN_LOOPBACKNET
some ports expect this to exist
2025-11-12 00:06:36 +02:00
998ea25fb9 LibC: Add netinet/in_systm.h compatibility header 2025-11-12 00:06:36 +02:00
7b580b8f56 Kernel: Implement fd passing with SCM_RIGTHS 2025-11-12 00:06:36 +02:00
641ccfdd47 LibC: Add BSD compatibility defines S_I{READ,WRITE,EXEC}
These just map to S_I{R,W,X}USR respectively
2025-11-10 01:40:33 +02:00
4288f70d04 LibC: Make poll and epoll macros match with each other
This was an assertion in one of my ports and I couldn't be bothered to
write a patch for it :D
2025-11-10 01:40:33 +02:00
95fda5dfb7 LibC: Add definitions for IPPROTO_ICMPV6 and IP_TOS 2025-11-10 01:40:33 +02:00
1903c5e0c6 Kernel: Use user given address hint in mmap if possible 2025-11-10 01:40:33 +02:00
362501a097 LibC: Make x86_64 crt0 PIE compatible
Instead of pushing addresses of functions directly, use rip relative
addressing
2025-11-10 01:40:33 +02:00
72982e3c2b Kernel/LibC: Take fcntl extra field as uintptr_t
This allows passing pointers to fcntl
2025-11-10 01:40:33 +02:00
04d24bce70 Kernel/LibC: Implement {recv,send}msg as syscalls
This also removes the now old recvfrom and sendto syscalls. These are
now implemented as wrappers around recvmsg and sendmsg.

Also replace unnecessary spinlocks from unix socket with mutexes
2025-11-10 01:40:33 +02:00
2f38306c6b LibC: Implement simple posix_spawn{,p}
This does not support file_actions or attributes
2025-11-10 01:40:33 +02:00
4b36e5197d LibC: Implement execvpe
This is not part of posix but it seems handy
2025-11-09 16:12:29 +02:00
b755cf3e42 LibC: Add sockatmark stub 2025-11-07 14:57:00 +02:00
3acad7c911 LibC: Add ifreq.ifr_{flags,mtu} and fix defines
compatibility defines for ifr_{netmask,gwaddr,hwaddr} were wrong
2025-11-07 14:55:30 +02:00
f3319016c4 LibC: Implement if_{,free}nameindex 2025-11-07 14:54:53 +02:00
4e14f7d483 LibC: Implement {,l,ll}{abs,div} 2025-11-06 23:20:35 +02:00
979059c804 Kernel: Implement ext2 symlinks with >= 60 byte target 2025-11-06 17:21:36 +02:00
bdf4423512 ports/freetype: Add missing dependencies 2025-11-04 23:06:13 +02:00
c6ef4b5840 userspace: Implement kill utility 2025-11-04 19:19:46 +02:00
acd792d8b4 userspace: Implement pwd utility 2025-11-04 18:46:13 +02:00
fc730679ed userspace: Implement uname utility 2025-11-04 18:45:20 +02:00
00e5749e20 ports: Add SuperTux port 2025-11-02 22:47:02 +02:00
7b4d349574 ports: Add glm port 2025-11-02 22:47:02 +02:00
dc0cccfb6c ports: Add physfs port 2025-11-02 22:47:02 +02:00
fdc1daefb6 ports: Add libvorbis port 2025-11-02 22:47:02 +02:00
c9159b81c8 ports: Add libogg port 2025-11-02 22:47:02 +02:00
9233049356 ports: Add openal-soft port 2025-11-02 22:47:02 +02:00
bd9015e474 ports: Add libsndfile port 2025-11-02 22:47:02 +02:00
3a79540d2d ports: Add SDL2_image port 2025-11-02 22:47:02 +02:00
9e500dc387 ports: Add boost port 2025-11-02 22:47:02 +02:00
e05a735589 DynamicLoader: Honour STB_LOCAL binding 2025-11-02 22:47:02 +02:00
0be18c4a53 DynamicLoader: Make everything thread safe
This is kinda dumb implementation, but it works. We grap a global lock
on functions :)
2025-11-02 22:47:02 +02:00
e258fde25a LibC: Implement unnamed semaphores 2025-11-02 21:11:16 +02:00
7367672570 Kernel: Default initialize flock as unlocked
This caused unlocked flock's to hang on lock
2025-11-02 21:10:13 +02:00
b822d42889 LibC: Define ESHUTDOWN
This is not used but some ports expect it to exist
2025-11-02 21:09:48 +02:00
10084ff1bb LibC: Define FIONBIO
This doesn't do anything but some ports expect it to exist
2025-11-02 21:07:26 +02:00
c3c69ac727 LibC: Update _POSIX_* definitions and extern environ
environ is externed by other operating systems so some ports expect it
to be there
2025-10-30 16:49:12 +02:00
0cfda6f6a7 LibC: Add posix_fadvise as no-op 2025-10-30 16:34:03 +02:00
dc51ce9e92 LibC: Implement readdir_r and fix memory leak 2025-10-30 16:33:17 +02:00
aa0de2b00e LibC: Fix stack_t::ss_sp type from void** -> void* 2025-10-30 15:43:25 +02:00
5f61581e1d Kernel: Show QR code with panic logs on kernel panic
This makes debugging on real hardware easier!
2025-10-28 05:50:19 +02:00
f519cb2cc0 Kernel: Expose boot framebuffer device 2025-10-28 05:50:19 +02:00
37aef630d2 BAN: Fix Array and Vector span constness 2025-10-28 05:50:19 +02:00
d93fcff5db userspace: Add LibQR
This library can be used to generate QR codes
2025-10-28 05:50:19 +02:00
4952a82af5 LibImage: Use LibDEFLATE instead of builtin DEFLATE decompressor 2025-10-28 05:50:19 +02:00
fecda6a034 userspace: Add LibDEFLATE
This can be used to compress and decompress DEFLATE data either in raw
or zlib format
2025-10-28 05:50:19 +02:00
9f0addbd8b BAN: Implement simple priority queue
This is just a wrapper around BAN::Vector and heap functions
2025-10-26 00:32:00 +03:00
7f8ea6b8e0 BAN: Move heap functions to Heap.h
This also adds push_heap and pop_heap, similar to what C++ standard
library provides
2025-10-26 00:31:06 +03:00
9d3ea6fed7 BAN: Use new it_value_type_t in sorting functions 2025-10-26 00:30:51 +03:00
703b3eda56 BAN: Add it_value_type_t
This is a template that resolves into T for pointers to T and T::value_type otherwise. It allows using the underlaying type of an iterator or pointer for range based algorithms
2025-10-26 00:22:35 +03:00
84006e1e77 BuildSystem: Don't set symlink mode
Only call chmod if the file is not a symlink. Older versions of chmod
(shipped with ubuntu) don't support the -h flag.
2025-10-02 17:05:20 +03:00
73fb085a41 LibC: Add inet_pton for IPv4 addresses 2025-10-02 16:19:49 +03:00
c89780178f LibC: Add sys/polls.h as wrapper for poll.h
some ports require this
2025-10-02 16:02:07 +03:00
2ac3976924 ports/libiconv: Fix download url
remove /pub/ part of url as mirrors don't seem to accept it
2025-10-02 15:54:55 +03:00
ac9dbd24e4 ports/vim: Fix compilation on new toolchain 2025-09-30 16:15:05 +03:00
3af9830a2e ports/tuxraces: Cleanup cflag passing 2025-09-30 16:14:40 +03:00
da6b8eb2ab BuildSystem: Use ftpmirror.gnu.org for downloads
ftp.gnu.org is really slow :(
2025-09-30 16:13:38 +03:00
da39e98adf Kernel: Make F11 drop disk cache
This can be useful to detect memory leaks or something
2025-08-31 00:36:59 +03:00
791a541381 Kernel: Implement process stopping and continuing 2025-08-31 00:34:52 +03:00
56684e753b Kernel: Fix PS/2 legacy controller detection
This was wrong for devices without FADT or pre revision 3 FADT
2025-08-29 21:07:33 +03:00
c7298edf65 Kernel: Clone executable path on fork
Before this forked processes had empty executables
2025-08-29 01:41:18 +03:00
30215963b2 Kernel: Fix /proc/<pid>/exe permissions 2025-08-29 01:40:56 +03:00
f15f88ebd6 TaskBar: Don't leak fds when reading battery info 2025-08-28 15:57:10 +03:00
391fc0c4c2 Kernel: Don't crash if Ext2 filesystem doing too many fileops
I had a hardlimit of 10 block buffers and if they ran out, the kernel
would crash. this patchs increases the number of buffers to 16 and
removes the crash condition when they run out :D
2025-08-28 15:55:40 +03:00
948ef2c820 Kernel: Fix race condition when destroying threads 2025-08-28 15:55:40 +03:00
c1b6b6b76a Kernel: Fix string validation in unlink syscall 2025-08-28 15:55:40 +03:00
a8bb07052e Kernel: Rewrite SMP message code
Remove locks and map smp buffer as uncached
2025-08-28 15:55:40 +03:00
6976a2dae7 Kernel: Add hardlink support to USTAR
Also handle file types L and K for long file names and link names
2025-08-28 15:55:40 +03:00
51cd951b4c Kernel: Add hardlink support to tmpfs 2025-08-28 15:55:40 +03:00
16a5a234c1 Kernel: Cleanup hardlink creation 2025-08-28 15:55:40 +03:00
f994210927 LibC: Fix sigsetjmp (again)
I was using a wrong register for signal mask storage...
2025-08-28 15:55:40 +03:00
aaa8760d09 Kernel: Don't wait for ps2 timeout when flushing buffer
This speeds up boot time by a second :dd:
2025-08-28 15:55:40 +03:00
cea19ecc31 Kernel: Fix possible crash during exec 2025-08-28 15:55:40 +03:00
706cfeb443 Kernel: Allow file backed mapping be larger than inode size
This is only allowed if the mapping does **not** exceed a page boundary.
Some port was doing an exactly two-page-mapping on a file that was one
and a half page long
2025-08-28 15:55:40 +03:00
d9c91589f0 Kernel: Don't limit /tmp max size 2025-08-28 15:55:40 +03:00
9854691265 LibC: Don't leak fds on rename 2025-08-28 15:55:40 +03:00
32afa33a06 LibC: Make sure FILE's buffer does not get overflown 2025-08-28 15:55:40 +03:00
c6946d0145 LibC: Use pthread_mutex on FILE instead of atomics 2025-08-28 15:55:40 +03:00
abbe7b79d6 Kernel: Add /proc/<pid>/exe 2025-08-28 15:55:40 +03:00
e4abe75043 Kernel: Add /proc/self 2025-08-28 15:55:40 +03:00
b904503691 ports: Update GCC 15.1.0->15.2.0 2025-08-28 15:55:40 +03:00
2db42dfb2e BuildSystem: Don't download config.sub every hour
There isn't really any need to :D
2025-08-25 22:16:23 +03:00
10bd24e585 Kernel: Fix signal delivery without an alternate stack
I had only tested that sigaltstack worked, so I didn't notice my normal
signals broke :D
2025-08-25 22:16:23 +03:00
f926e599fa Kernel: Zero initialize Processors
This moves processor array to .bss reducing data size by 8192 bytes :)

This needed GCC updated to 15.2.0 because of an internal compiler error
I found :)
2025-08-25 18:29:14 +03:00
e7b518ba67 BuildSystem: binutils 2.44->2.45, gcc 15.1.0->15.2.0 2025-08-25 18:25:36 +03:00
a4698f0bde Kernel: Fix IOAPIC max redirection entry fetching
Also max redirection entry is an index, not count so comparisons should
check for equality :)
2025-08-25 17:15:55 +03:00
9a6eae69ba Kernel: Replace all occurances of BSB with BSP 2025-08-25 17:11:32 +03:00
0ff365c7f0 ports: Add qemu port 2025-08-21 03:11:16 +03:00
214e7a5672 ports: Add glib port 2025-08-21 03:11:16 +03:00
24b69a6dea ports: Add libffi port 2025-08-21 03:11:16 +03:00
699235147c ports: Add pcre2 port 2025-08-21 03:11:16 +03:00
72ad413a61 ports/SDL2: Handle window focus events 2025-08-21 03:11:16 +03:00
f11bb082e4 WindowServer/LibGUI: Add window focus events 2025-08-21 03:11:16 +03:00
2f3fd6867d Kernel: Add VERY HACKY MAP_FIXED fix
This definitely will break stuff but I don't think anything depends on
this (except maybe dynamic loader)

This WILL get fixed soon (I hope :D)
2025-08-21 03:11:16 +03:00
350ae90bb6 Kernel: Make all futexes shared
Some stuff tries to use shared futexes so make them all shared. Private
futexes would be faster as they are process specific but supporting both
would need some reworks
2025-08-21 02:56:17 +03:00
fb61cab70d LibC: Rewrite pthread_mutex using a futex 2025-08-21 02:52:49 +03:00
1d6c08478d LibC: Fix sigsetjmp
the call from C sigsetjmp messed up rbp, now sigsetjmp is also written
in assembly.

I did not test the 32 bit code, just ported the tested 64 bit version
over :D
2025-08-21 02:52:49 +03:00
0dfe0b7023 Kernel/LibC: Implement sigaltstack 2025-08-21 02:52:49 +03:00
def236b7cd Kernel/LibC: Implement sigwait 2025-08-20 20:16:19 +03:00
247743ef9c Kernel/LibC: Implement sigsuspend 2025-08-20 20:14:54 +03:00
49122cf729 Kernel: Allow adding signals to thread that are blocked 2025-08-20 18:35:18 +03:00
84f579be81 ports: Add nano port 2025-08-19 17:00:14 +03:00
3d5f23a1b2 LibC: Implement wctomb 2025-08-19 16:44:18 +03:00
8b26b6604d LibC: Make mbstate_t into int
This is not used, but makes more sense than an empty struct
2025-08-19 16:29:46 +03:00
f88e55ffa8 ports: Add nyancat port 2025-08-19 16:23:30 +03:00
34bdcb12e5 Kernel: Fix termios and enter key handling
Enter key now produces expected \r which gets converted to \n by default
by the ICRNL input flag.

Also input flags are now handled always, not just when ICANON is set.
I don't know why I though ICANON should disable input handling
2025-08-19 16:23:30 +03:00
95b353dae5 LibInput: Fix numpad keycode generation
I had made this function with broken PS/2 scancode set 3, so it seemed
like it worked
2025-08-19 16:23:30 +03:00
6560f229b1 Kernel: Fix PS/2 scancode set 3 numpad keys 2025-08-19 16:23:30 +03:00
8c9ab2d68c WindowServer: Fix crash when window closes while being "button window" 2025-08-19 16:23:30 +03:00
8496726ab1 Terminal: Ignore some control characters 2025-08-19 16:23:30 +03:00
32d7f429f8 Kernel: Fix default ignored signals
SIGWINCH and SIGCANCEL ended up interrupting functions even when they
were marked as SIG_DFL. Now resizing the userspace terminal emulator
does not get interrupted!
2025-08-19 16:23:30 +03:00
0f52f49188 Terminal: Remove unused code 2025-08-19 16:23:30 +03:00
b334259a07 AudioServer: Don't allow client to fully halt audio 2025-08-19 16:23:30 +03:00
74af4e9150 ports/SDL2_mixer: Add MIDI support 2025-08-19 16:23:30 +03:00
8b7790ded2 Kernel: Fix userspace pointer checks
Some syscalls were unconditionally validating optional paramenters which
were allowed to be null pointers
2025-08-19 16:23:30 +03:00
3e97a82af0 Kernel: Allow getgroups with size
This can be used to query the number of groups
2025-08-19 16:23:30 +03:00
0066b20413 Kernel: Fix spinlock leaks with unix sockets 2025-08-19 16:23:30 +03:00
9d6656451a LibC: Make time_t signed integer
Some port like python3 assumes this is the case
2025-08-19 16:23:30 +03:00
32f980e259 Kernel: Fix ACPI namespace lookup for multi segment names 2025-08-19 16:23:30 +03:00
ca9361abc1 DynamicLoader: Add support for dladdr 2025-08-19 16:23:30 +03:00
36cb3d56fe LibC: Define Dl_info_t and add stub for dladdr 2025-08-19 16:23:30 +03:00
0bece8a54c Kernel: Add missing ACPI resource header 2025-08-19 16:23:30 +03:00
70bbdbd8f5 LibC: Cleanup syslog output
add ": " after the identification and formatted output. syslog does not
require trailing newline so add it in case it is missing.
2025-08-16 22:56:03 +03:00
df8365f0c7 ports/openssh: Configure with --disable-fd-passing
I though this wasn't needed because of my patch, but I didn't actually
test the code
2025-08-16 22:55:53 +03:00
974aae2ebe ports: Add openssh port 2025-08-16 22:32:37 +03:00
ceca93c8b1 LibC: Cleanup memmove and memcpy for x86_64 2025-08-16 14:05:21 +03:00
b6793cc6f2 Kernel: Add AML ConcatResOp 2025-08-15 18:54:17 +03:00
809d07546a Kernel: Remove minimum timeout of 100 ms from epoll
This is not actually needed and was just temporary code to make sure i
notified the epoll everywhere
2025-08-15 18:28:11 +03:00
804cbeb1a7 Kernel: Increment kmalloc storage size to 64 MiB
I really don't want to do this, but rewriting kmalloc to be dynamic
would require me to rewrite 32 bit paging and I really don't want to.
2025-08-15 17:02:15 +03:00
c07188a60e Kernel: Look for PS/2 devices in the ACPI namespace
This allows finding the PS/2 controller on newer machines that don't
have the 8042 bit set in FADT.
2025-08-15 17:02:15 +03:00
3804d4332b Kernel: Make _SEG, _BBN and _ADR lookup absolute 2025-08-15 17:02:15 +03:00
064aaef6c3 Kernel: Don't fail on creating reserved opregion 2025-08-15 17:02:15 +03:00
ce262a5d2d Kernel: Allow ReturnOp in global scope 2025-08-15 17:02:15 +03:00
d128f4d70b Kernel: Fix AML CreateField debug print 2025-08-15 17:02:15 +03:00
46d1ada708 Kernel: Allow AML package->package conversion 2025-08-15 17:02:15 +03:00
2819e5f647 Kernel: Make _STA and _INI lookup absolute 2025-08-15 17:02:15 +03:00
c2017a5181 Kernel: Allow looking up devices with multiple eisa ids
Also match against _CIDs in addition to _HID
2025-08-15 17:02:15 +03:00
58ad839136 Kernel: Add support for ACPI Embedded Controllers 2025-08-15 17:02:15 +03:00
8ed5a71c45 Kernel: Register IDT handlers from a vector
This drops code size by a lot :D
2025-08-13 18:27:46 +03:00
57050a83ba ports/timidity: Fix compilation
Precalculating newton coefficients does not work as the buildsystem
tries to run a banan-os binary. This patch enables coefficient
calculation code for the runtime!
2025-08-13 12:20:21 +03:00
6ed0e84421 LibC: Fix mktime argument updating 2025-08-11 19:00:23 +03:00
9b09d2b47a LibC: Update struct tm to be POSIX issue 8 compliant 2025-08-11 18:59:20 +03:00
1a6c5deb4b LibC: Add {AF,PF}_LOCAL as aliases to {AF,PF}_UNIX 2025-08-11 18:48:24 +03:00
45a73b00de LibC: Make glob_t a typedef 2025-08-11 18:47:55 +03:00
59fff26a5f LibC: Remove our iconv.h header and add libiconv port
If I ever end up writing my own iconv, i will drop the port :D
2025-08-11 18:46:15 +03:00
fde4d4662e LibC: Implement getopt_long{,_only}
Few ports attempt to use this so lets add them :D
2025-08-11 18:36:46 +03:00
c9355ad94a BuildSystem: Fix file permission bits on image creation
If a file had setuid/setgid/sticky bits set, they were not copied to the
sysroot
2025-08-11 14:48:57 +03:00
bad3b8b3e2 ports/binutils: Fix compilation when zstd is installed
binutils uses pkg-config to find zstd for the host when building. If our
zstd port is installed, it finds it instead and ends up including our
own sysroot which is incompatible with host's.

unsetting pkg-config related variables fixes this and allows binutils to
build fine even when zstd is installed. We can now make it a dependency.
2025-08-11 14:07:37 +03:00
0b81bb9b10 ports/quake2: Use SDL2 instead of our own frontend 2025-08-11 14:07:37 +03:00
f61c78efd5 ports/tinygb: Use SDL2 instead of our own frontend 2025-08-11 14:07:37 +03:00
6b2307ab22 ports/doom: Use SDL2 instead of our own frontend
This allows doom to play sounds!
2025-08-11 14:07:37 +03:00
9ccb381c31 ports: Add SDL2_mixer port
This allows some ports to use audio :D

I did not port any audio libraries so loading sounds probably doesn't
work :D
2025-08-11 14:07:37 +03:00
71133236f8 ports: Add timidity port 2025-08-11 14:07:37 +03:00
e5786fe435 init: Start AudioServer on boot 2025-08-11 14:07:37 +03:00
ef6ee78fd1 Kernel/LibC: Implement chroot 2025-08-11 14:07:37 +03:00
695262624d Kernel: Fix potential UB in AML OpRegion initialization 2025-08-11 03:45:38 +03:00
c96c264801 LibC: Implement fnmatch 2025-08-10 19:57:31 +03:00
af0bca74e4 Kernel/LibC: Implement {get,set,init}groups
This allows dropping /etc/group parsing from the kernel :D
2025-08-10 19:57:31 +03:00
f41e254e35 Kernel: Fix dead lock on process exit 2025-08-10 19:57:31 +03:00
7e472a9c1d Kernel: Fix USB FS device default max packet size
Apparently this is a common non spec compliant issue on many
controllers/devices.

thanks @sasdallas
2025-08-10 19:57:31 +03:00
ee3f10313a BuildSystem: Flip USB_ARGS and DISK_ARGS in qemu.sh
This allows attaching usb disk :D
2025-08-10 19:57:31 +03:00
5b587d199e Kernel/LibC: Implement FIONREAD for tcp and udp sockets 2025-08-10 19:57:31 +03:00
009b073892 LibC: Add IN6_IS_ADDR_* and IN_MULTICAST macros
These are assumed to exist by some ports
2025-08-10 19:57:31 +03:00
92e962430b LibC: Make sockaddr and sockaddr_in compatible with other systems
sockaddr:
make sa_data is 14 bytes on all systems

sockaddr_in:
add sin_zero
2025-08-10 19:57:31 +03:00
3aa20a3a32 Kernel: Fix ACPI _GPE calling
This adds patch adds support for extended GPEs and the second GPE
register block.
2025-08-07 19:35:13 +03:00
de7c3d3d29 Kernel: Don't try to create . in USTAR
Our build system adds . entry to the tar archive and it should be
handled as an no-op
2025-08-07 19:35:13 +03:00
3f89df338e IDT: Remove stack OOB check
This makes debugging easier when you can see the actual register values
and what is mapped and where
2025-08-07 19:35:13 +03:00
c7f89c9b77 ports: Update SDL2 2.30.11 -> 2.32.8 2025-08-07 16:43:05 +03:00
a107e463e8 ports/SDL2: Add audio support 2025-08-07 16:43:05 +03:00
7a5cfe1728 LibAudio/AudioServer: Add support for playing real time audio 2025-08-07 16:43:05 +03:00
7ad3f967db Kernel: Don't stop audio processing after each entry in AC97 2025-08-07 16:43:05 +03:00
d1c814cf9d Kernel: Optimize consecutive absolute mouse move events
This is a hack to make window server usable without kvm :D
2025-08-07 16:43:05 +03:00
72f85dce2b Kernel: Make userspace stack on-demand allocated
Also bump the hardlimit of stack size from 512 KiB->32 MiB. This still
feels quite low but is much better than before :D
2025-08-07 16:43:05 +03:00
f5bbcc017c Kernel: Only send one smp message when reserving a range
This was causing some kernel panic because processors ran out of smp
message storage when reserving large areas.

Also most of the time there is no need to actually send the SMP message.
If process is mapping something to just its own address space, there is
no need for a TLB shootdown. Maybe this should be only limited to kernel
memory and threads across the same process. I'm not sure what the best
approach here and it is better to send too many invalidations that too
few!
2025-08-07 16:43:05 +03:00
2980173c8e ports: Fix config.sub downloading 2025-08-07 16:28:09 +03:00
a84c348045 LibC: Add shm_{open,unlink} stubs
These are needed for our llvm port
2025-08-07 16:28:09 +03:00
d845ecc811 LibC: Add wcstok, wcstol and swprintf stubs
These are needed for our python3 port
2025-08-07 16:28:09 +03:00
064d9009a2 LibC: Add clock_getres stub
This is needed for our python3 port
2025-08-07 02:50:24 +03:00
b6aa5bdfab LibC: Implement if_indextoname and if_nametoindex
These are needed for our cmake port
2025-08-07 02:50:24 +03:00
a3bdf0456e LibC: Add getpriority stub
This is needed for our cmake port
2025-08-07 02:50:24 +03:00
e3ecf05866 LibC: Add stubs for {get,free}ifaddrs
These are needed for our libuv port
2025-08-07 02:50:24 +03:00
6240374dd1 LibC: Add semaphore stubs
These are needed for our bochs port
2025-08-07 02:50:24 +03:00
e17ee831a7 LibC: Add times stub
This is needed for our openssl port
2025-08-07 02:50:24 +03:00
aef9bd6357 LibC: Add mk{nod,fifo}{,at} stubs
These are needed for our tcl port
2025-08-07 02:50:24 +03:00
8857227a35 LibC: Add getservbyname stub
This is needed by our tcl port
2025-08-07 02:50:24 +03:00
937250c681 userspace: Add dummy libdl
This allows ports to link against without needing to patch it out
2025-08-07 02:50:24 +03:00
66d3a1d025 ls: Output in columns 2025-08-07 02:50:24 +03:00
647fedfa19 Kernel: Add missing multiboot.h 2025-08-05 17:12:26 +03:00
c593d3ed75 LibC: Add missing libintl.h 2025-08-05 17:10:43 +03:00
bd885a01e5 ports/expat: Remove libtool file 2025-08-05 03:47:52 +03:00
628825fdff ports: Don't set CMAKE_TOOLCHAIN_FILE environment variable
This doesn't allow llvm to build native tablegen
2025-08-05 03:47:16 +03:00
46dd411273 LibC: fflush stdout when reading from stdin
This is the *intended behaviour* per ISO C specification
2025-08-05 03:32:59 +03:00
2e2ee11452 LibC: Add more reasonable values to stack size constants 2025-08-05 03:32:59 +03:00
ce0df333b3 LibC: Make sa_data in sock_addr zero sized 2025-08-05 03:32:59 +03:00
8bbda78272 ports/xash3d-fwgs: Don't disable opengl and patch output
Manually link against libxash.so. My current dlopen does not support
loading ELF files that contain TLS
2025-08-05 03:32:59 +03:00
945509fc93 ports/mesa: Use llvm pipe instead of softpipe if llvm is compiled 2025-08-05 03:32:59 +03:00
b586917930 ports: Add llvm port
This can be compiled before mesa to make mesa use llvmpipe instead of
softpipe. llvmpipe is at least 10x faster :D
2025-08-05 03:09:24 +03:00
45ad6082bc DynamicLoader: Support dlopen(NULL, ...) 2025-08-05 03:09:24 +03:00
f27823babe Kernel: Move stacks to the top of userspace address space 2025-08-05 03:09:24 +03:00
95cfac471a Kernel: Rename loopback adapter lo0 -> lo 2025-08-05 03:09:24 +03:00
f7c1084c3e Kernel: Expose boot command line in /proc/cmdline 2025-08-05 03:09:24 +03:00
cf96bb6cc3 Kernel: Add support for multiboot
I don't know why I did it but it works now :D
2025-08-05 03:09:24 +03:00
f1369c8fd6 Kernel/LibC: Implement mprotect
There may be some race conditions with this but i think this is good
enough to start with
2025-08-05 03:09:24 +03:00
eb7922ab88 LibC: Implement pthread_cond_* using a futex 2025-08-05 03:09:24 +03:00
dfdfb7cdaf Kernel: check all threads in validate_pointer_access 2025-08-05 03:09:24 +03:00
1cc0fb9c01 Kernel: Reschedule if idle after IPI
This allows starting thread execution right after thread is received
from load balancing
2025-08-05 03:09:24 +03:00
a51b589bc9 Kernel: Allow any signal flags and support SA_RESETHAND 2025-08-05 03:09:24 +03:00
5940e912b3 Kernel/LibC: Implement simple futex 2025-08-05 03:09:24 +03:00
658a001d91 LibC: Make pthread_barrier safe
It used to deadlock and it was not safe if more threads than the target
were attempting to wait on it.
2025-08-05 03:09:24 +03:00
57c9f5a8a8 LibC: lock mutex when pthread_cond_timedwait times out 2025-08-05 03:09:24 +03:00
fa7b58057c LibC: Add MAP_ANON as synonym for MAP_ANONYMOUS
This is part of POSIX issue 8 and some things only check MAP_ANON
2025-08-05 03:09:24 +03:00
0e0f5295cf LibC: Make {,__cxa_}atexit thread safe 2025-08-05 03:09:24 +03:00
284c9e5f61 Kernel: Don't kill process if stack pointer is OOB
This can be valid if process is using green threads or for some other
reason using its own stack
2025-08-05 03:09:24 +03:00
927fbda1e8 Kernel: Make on-demand paging thread safe 2025-08-05 03:09:24 +03:00
d25a5034db LibC: Update thread id on fork 2025-08-05 03:09:24 +03:00
f197d39aaf LibC: Don't allow pthread_join to return EINTR 2025-08-05 03:09:24 +03:00
4a95343936 LibC: Make _get_uthread a macro
This allows nice inlining :)
2025-08-05 03:09:24 +03:00
4e705a91af LibC: Fix pthread keys
I had misunderstood how these are supposed to work :D
2025-08-05 03:09:24 +03:00
82b351469b DynamicLoader: Setup thread id when initializing TLS
This allows pre-libc code use pthread functions

(__cxa_guard_release calls pthread_cond_broadcast)
2025-08-05 03:09:24 +03:00
ea91bdcce7 WindowServer: Make relative mouse no-op with absolute mouse 2025-08-05 03:09:24 +03:00
256c9daefd ports/SDL2: Optimize rendering and fix cursor
Remove the unnecessary framebuffer layer, we can just use the window's
own framebuffer.

Set default cursor on mouse initialization, this fixes cursor hiding in
tuxracer

defined SetRelativeMouseMode instead of SetMouseCapture. This is what
the behaviour was :D
2025-08-05 03:09:24 +03:00
af0a46e79c LibGUI/WindowServer: Rename mouse capture -> mouse relative
My terminology was incorrect and this is more correct
2025-08-05 03:09:24 +03:00
4519c48284 WindowServer: Fix custom cursors
Custom cursor is now only set if the cursor is in the client area
instead of anyehere in the window. This makes hidden cursor visible
when it is on top of the title bar!
2025-08-05 03:09:24 +03:00
8ea32c7650 WindowServer: Fix relative mouse vertical flip 2025-08-05 03:09:24 +03:00
5972d40ced ports: Update zstd 1.5.6 -> 1.5.7
Also build using cmake because we can :)
2025-08-05 03:09:24 +03:00
f35a6b3922 BuildSystem: Fix meson toolchain file
sed to replace SYSROOT did not work because paths contain /

also add cmake to allow cmake based library detection
2025-08-05 03:09:24 +03:00
21009c37b4 BuildSystem: Remove unnecessary variables from cmake toolchain 2025-08-05 03:09:24 +03:00
11a2d15003 BuildSystem: Optimize disk image creation
disk image is now created with rsync so there is no need for copying the
whole sysroot twice.
2025-08-05 03:09:24 +03:00
d8a695a88d Kernel: Don't fail ustar unpack when creation fails 2025-08-05 03:09:24 +03:00
f82390424b ports: Add cmake port 2025-08-05 03:09:24 +03:00
08ed405a5b ports: Add libuv port 2025-08-05 03:09:24 +03:00
8c598a6902 LibC: Include stdint.h instead of inttypes.h in network headers 2025-08-05 03:09:24 +03:00
8e9c40caa4 LibC: Pump OPEN_MAX to 128
cmake seems to use around 70 when checking compiler. That seems quite a
lot but could be "normal"
2025-07-31 22:47:40 +03:00
8c29036fbf Kernel: Fix EAGAIN on hungup pipe 2025-07-31 22:47:40 +03:00
b46337d376 BuildSystem: Add banan-os cmake platform 2025-07-31 22:47:40 +03:00
56d701492b ports/ncurses: Add c++ bindings 2025-07-31 22:47:40 +03:00
07e4e764a0 LibC: Implement mbtowc 2025-07-31 22:47:40 +03:00
66fe2f2e50 LibC: Fix readv and writev 2025-07-31 22:47:40 +03:00
fda0ced72e LibC: Implement getpw{nam,uid}_r 2025-07-31 22:47:40 +03:00
654e8bb7f6 LibC: Implement getgr{gid,nam}_r 2025-07-31 22:47:40 +03:00
80ffde5e1e LibC: Implement aligned_malloc
This is part of POSIX issue 8
2025-07-31 22:47:40 +03:00
52309e0754 LibC: Add in6addr_{any,loopback} definitions 2025-07-31 22:47:40 +03:00
31e411f8f1 LibC: Implement recvmsg and sendmsg
These just wrap recvfrom and sendto so ancillary data is not supported
2025-07-31 22:47:40 +03:00
de45b760b5 LibC: Implement alphasort and scandir 2025-07-31 22:47:40 +03:00
ff29e9c4d6 LibC: Implement {,f}pathconf
This just return minimum values specified by posix
2025-07-31 22:47:40 +03:00
cc04bd0f06 LibC/Kernel: Implement ttyname_r 2025-07-31 22:47:40 +03:00
e72e1e4e43 LibC: Add _SC_NPROCESSORS_{CONF,ONLN) 2025-07-31 22:47:40 +03:00
987cc3c237 3000th COMMIT: ports: Add halflife port 2025-07-31 22:47:34 +03:00
935f69e011 ports: Add freetype port 2025-07-31 22:47:29 +03:00
9f0c2fb6e2 ports: Apply only patches ending in .patch 2025-07-31 22:47:29 +03:00
9b18bda9c8 Kernel: Make epoll always check for HUP and ERR 2025-07-31 22:47:29 +03:00
7831c74e8c DynamicLoader: Add support for LD_LIBRARY_PATH
Also fix a bug with dlopen with TLS
2025-07-31 22:47:29 +03:00
c1978f9133 Shell: Implement redirections
This works well enough. At the moment redirections can appear anywhere
in the command **after** environment variables and possible alias
command. This means commands like `>foo echo hello` are not supported.
I don't think this is big enough problem for now (99% time redirections
are given after arguments) that i would rewrite the environment and
alias parsing.
2025-07-22 16:54:06 +03:00
05affda20c ports: Add python3 port 2025-07-22 14:11:09 +03:00
e2eb555ca0 LibC: Add dummy libintl support
This doesn't really do anything but allows some ports to use it :D
2025-07-22 13:26:53 +03:00
418c3c9cfa ports: Remove unneeded libtool files after install 2025-07-22 10:32:52 +03:00
bc66e181a5 ports: Update to new config.sub syntax
There is no longer need to manually patch config.sub files!
2025-07-22 10:31:56 +03:00
6971f76bd3 ports: Add support for downloading upstream config.sub
banan-os is now in the upstream config.sub. This means no more
config.sub patches!
2025-07-22 10:13:41 +03:00
1e65f02ff7 Terminal: Handle bell and warn on unimplemented control characters 2025-07-21 14:28:09 +03:00
4efaf65d3f BuildSystem: Use usb-tablet instead of usb-mouse
This allows sharing mouse between host and guest!
2025-07-19 18:02:07 +03:00
aa0249fadb WindowServer: Support absolute position mouse 2025-07-19 18:01:23 +03:00
2c65590134 Kernel: Add support for absolute position mouse 2025-07-19 18:00:39 +03:00
a0d1a9ad67 Kernel: Fix PIT::prescheduler_sleep_ns
I don't even know what I was doing here :D
2025-07-19 01:25:46 +03:00
5df6270e32 Kernel: Clobber flags in rdrand 2025-07-18 19:36:37 +03:00
7af6e1cd34 Kernel: Ignore HID main item tag 0
This for some reason exists in vmware's usb devices
2025-07-18 19:11:12 +03:00
cceb066284 Kernel: Don't use IST on 32 bit target
This only exists in 64 bit
2025-07-18 19:10:48 +03:00
7a054787ca Kernel: Don't print error if root is empty
This is used when loading filesystem from initrd
2025-07-18 19:09:43 +03:00
d27891c79f Kernel: Fix correct IOAPIC lookup based on gsi 2025-07-18 19:09:20 +03:00
5874fd640e Kernel: Fix TmpFS for 32 bit target
There was a problem when sizeof(size_t) != sizeof(PageInfo)
2025-07-18 19:07:32 +03:00
11ae220dbe LibImage: Optimize image resizing algorithms 2025-07-18 18:20:37 +03:00
22542a3a71 BuildSystem: Enable sse and sse2 for all programs and libraries
This is default on x86_64 but not on the 32 bit target. banan-os
already requires the CPU to support SSE even on 32 bit platforms.
2025-07-18 18:20:37 +03:00
e16fb6a8e9 Kernel: Don't validate allowed null pointers on syscalls 2025-07-17 22:14:04 +03:00
d941e6d70b General: Update README features and environment variables 2025-07-17 21:45:48 +03:00
b65068dc7d BuildSystem: Add support for building initrd image
This is nice for testing when there isn't xhci controller available or
my usb stack fails :)
2025-07-17 21:45:48 +03:00
d5301508ec Kernel: Increase kernel thread stack size
HACK HACK HACK

This is just to make banan-os boot on one razer laptop where AML
triggers a stack overflow :)
2025-07-17 21:21:14 +03:00
793cca423b Kernel: Fix system timer disabling
I was actually not disabling system timer (HPET, PIT) when using lapic
timers for scheduling. This made BSB get too many timer interrupts :D
2025-07-16 20:02:04 +03:00
3960687f9d Kernel: Parse PCIConfig opregion address on read/write
I was testing on some hardware and _ADR does not have to exist in the
namespace when opregion is parsed :)
2025-07-16 15:34:36 +03:00
3ec7aad432 Kernel: Increase PS/2 timeout and detect more keyboards
I was testing on a old T61
2025-07-16 15:29:27 +03:00
84f1ad4f26 ports: Fix doom compilation with the new toolchain 2025-07-15 16:12:03 +03:00
6b9dbf625d userspace: Add audio utility to play audio files 2025-07-15 16:12:03 +03:00
3aea2c007d Userspace: Add simple AudioServer and LibAudio 2025-07-15 16:12:03 +03:00
85d195212a BuildSystem: Update qemu script and add ac97 2025-07-15 14:17:49 +03:00
8a663cb94f Kernel: Implement basic AC97 driver 2025-07-15 14:17:49 +03:00
674e194a91 Kernel: Don't fail PCI interrupt allocation with PCIe and no PCI 2025-07-15 14:17:49 +03:00
c57f0abb56 BuildSystem: Order source list alphabetically 2025-07-15 14:17:49 +03:00
163fdcd582 LibC: Fix exec family function path resolution 2025-07-15 14:17:49 +03:00
3be17c6117 BAN: Add clear and access by index to CircularQueue 2025-07-10 17:24:40 +03:00
995dfa1455 Kernel: Fix AML PCIConfig OpRegion accesses
Apparently I'm not supposted to calculate device/function from the
offset, but parse them from the acpi namespace :)

This allows PCI PIN interrupt routing actually work
2025-07-04 13:21:02 +03:00
544c8dbc13 Kernel: Optimize AML interpreter stack usage
There is a very hacky no-inline hack that I am not proud of but it drops
the stack usage of few functions A LOT.

Previously Virtual Box could not boot with our 8 page stack, but these
changes allow it to boot on 5!
2025-07-03 00:49:23 +03:00
8da4f80453 Kernel: Add custom stack to double fault handler
This prevents triple faults!
2025-07-02 23:14:52 +03:00
6084aae603 Kernel: Add guard pages to kernel and userspace stacks 2025-07-02 23:12:36 +03:00
e1319a06f2 Kernel: Remove accidentally commited debug prints 2025-07-02 23:09:57 +03:00
51fd7a607d Kernel: Fix IDE controller waiting
We did not correctly wait until controller is ready to receive data on
write command. Also remove possible kernel panic if controller sends
unexpected interrupts
2025-07-02 22:04:41 +03:00
8aff315c7b LibC: fflush file in setvbuf before updating the buffer 2025-07-02 01:54:03 +03:00
8e0d79f301 ports: Fix make compilation with new toolchain 2025-07-02 01:54:03 +03:00
8a0269d29e Kernel: Remove kernel processes
Kernel can just use raw threads, pretty muchs the only thing that
process provides is syscalls which kernel threads of course don't
need.

Also this makes init process have pid 1 :D
2025-07-02 01:54:03 +03:00
892e16dfb1 Kernel: Increase PS2 timeout to 300 ms, load PS2 in separate thread
PS/2 seems to hit command timeout sometimes on slow emulation so
increase the timeouts.

Also move PS/2 device initialization to a different thread because
device indentification waits for timeouts.
2025-07-02 00:17:42 +03:00
92e4078287 Kernel: Rewrite ThreadBlocker
This gets rid of a very old bug where kernel panics when thread is being
woken up and unblocked at the same time on different cores. This
required adding a new lock to SchedulerQueue::Node and adding a cap to
how many threads a threadblocker can simultaneously block. I don't think
I ever block more than five threads on the same ThreadBlocker so this
should be fine.
2025-07-02 00:17:42 +03:00
41e1819072 Kernel: Align argv and envp to pointer boundary
This bug was found with ubsan
2025-07-02 00:17:42 +03:00
fb7e9719a1 Kernel: Add fast fill method to framebuffer device
This makes `clear` much faster when running without kvm!
2025-07-02 00:17:42 +03:00
c2d09b64ca Kernel: Drop 24 bpp support from double buffer
I don't even know why this was supported, I am not planning on making
the fb anything other than 32 bpp
2025-07-02 00:17:42 +03:00
1b2aa6c2da Kernel: Fix unaligned access in AML
Found with ubsan
2025-07-02 00:17:42 +03:00
a5b4cee298 Kernel: Load USTAR from a boot module if loading root partition fails
This allows banan-os to boot on hardware where we don't have working
storage driver or the storage driver fails (pretty common with my usb
mass storage drivers...)
2025-07-02 00:17:42 +03:00
17f1ac10e3 Kernel: Don't ignore modules passed with multiboot2 2025-07-02 00:17:42 +03:00
c67198032f Kernel: Rewrite TmpFS block and inode allocation
This makes creating files and appending to then A LOT faster. Some code
I tested took 40 seconds in the previous implementation and less than a
second on the new one!

This code is really sketcy, I hope I'll never have to touch it again :)
2025-07-02 00:17:42 +03:00
107b092982 Kernel: Allow arbitrary sized tmpfs files
The 2 block limit started to get annoying :D
2025-07-02 00:17:42 +03:00
bac06e45a4 Kernel: Fix TmpSymlinkInode target getting/setting 2025-07-02 00:17:42 +03:00
0e8a68831c Kernel: Fix TmpInode chmod not preserving file type 2025-07-02 00:17:42 +03:00
5912abd541 Kernel: Add error reporting for readonly mounted filesystems 2025-07-02 00:17:42 +03:00
13d33995cb Kernel: Make sure PageTable::fast_page gets passed page aligned addr 2025-06-30 01:48:47 +03:00
c8c05f62b4 Kernel: Remove unused FileSystem::dev 2025-06-29 00:29:03 +03:00
944b045885 Toolchain: Set CMAKE_STAGING_PREFIX in toolchain file 2025-06-28 23:34:11 +03:00
19897ffa26 userspace: Compile test utility :D 2025-06-28 22:40:00 +03:00
42a10b21c7 userspace: Implement true and false utilities 2025-06-28 22:39:19 +03:00
5df0e25c1f userspace: Implement chown utility 2025-06-28 21:32:59 +03:00
ebf2b16d09 Kernel: Implement chown to ext2 and tmpfs 2025-06-28 21:28:54 +03:00
f2eaab6e43 ports: Add tuxracer port
THIS IS SUPER SLOW
2025-06-28 20:54:45 +03:00
a847823411 ports: Add tcl port 2025-06-28 20:54:45 +03:00
fe9a8b542a ports: Add bochs port
THIS IS SUPER SLOW
2025-06-28 20:54:45 +03:00
cd101b6844 ports: Add sdl12-compat port 2025-06-28 20:54:45 +03:00
69229102c4 ports: Add SDL2 port 2025-06-28 20:52:33 +03:00
4bc3630d19 ports: Add glu port 2025-06-28 20:52:20 +03:00
ab00686ac9 ports: Add mesa port 2025-06-28 20:51:29 +03:00
c3004a038f ports: Add bash port 2025-06-28 20:48:13 +03:00
9cf9d8847b ports: Add lua port 2025-06-28 20:48:13 +03:00
0a3c10566b ports: vim update to 9.1 2025-06-28 20:48:13 +03:00
c94243e107 ports: Update some ports to new syntax 2025-06-28 20:48:13 +03:00
505388b9fa ports: Add pre_install and post_install to install.sh 2025-06-28 20:25:35 +03:00
7314cf708c Kernel: Only restart certain syscalls with SA_RESTART
SA_RESTART is not supposted to restart every function.
2025-06-28 20:25:35 +03:00
3e6a4f2b16 LibC: Add getgroups stub 2025-06-28 20:25:35 +03:00
c7c3dd7662 init/ports: Fix environment variables in init/ncurses
init no longer sets NCURSES_NO_UTF8_ACS
ncurses no longer sets TERM
2025-06-28 20:25:35 +03:00
e4f025edd6 LibC: Implement deprecated bcmp, bcopy, bzero 2025-06-28 20:25:35 +03:00
96f3efbf86 LibC: Fix enviroment variable allocation 2025-06-28 20:25:35 +03:00
2b2130ff42 toolchain/ports: Use strip install targets
I just found that these exist. This is much cleaner than manually
stripping the executables!
2025-06-28 20:25:35 +03:00
463ce05da0 ports: Allow specifying custom make targets 2025-06-28 20:25:35 +03:00
fa4095ba95 ports: Add pre_configure to build system
We have post_configure, so why not this :)
2025-06-28 20:25:35 +03:00
db571b4859 Kernel: Allow relockign mutex even when holding a spinlock
Only reason mutex locking is now allowed with spinlocks is to prevent
yield.

Also try_lock can be now safely used while holding a spinlock
2025-06-28 19:40:54 +03:00
e8491b34b8 Kernel/LibC: Rework TIOC{G,S}WINSZ more linux like
Userspace can freely set terminal size, kernel just updates it when for
example new font is loaded. Also SIGWINCH is now sent by kernel instead
of userspace.
2025-06-28 19:40:54 +03:00
521457eb92 DynamicLoader: Add support for calling destructors
After all libraries are initialized, their destructors are registered
using atexit
2025-06-28 16:55:13 +03:00
f26a445ce6 LibC: Make malloc actually allign to s_malloc_default_align boundary 2025-06-28 16:55:13 +03:00
f73bb242f3 Kernel: Save fpu state and flags in signal handler
This was causing some weird crashes :D
2025-06-28 16:55:13 +03:00
9e895e5286 Kernel: Use fxsave64 and fxrstor64 on 64 bit target 2025-06-28 16:55:13 +03:00
5b0e5512a8 Kernel: Don't block in send until full message is sent
Only block until some data was sent. This allows select + send to be
actually non blocking if used correctly.

Also fixes a bug with non blocking sockets that could not send the full
message is one try.
2025-06-28 16:55:13 +03:00
850b3284ac Terminal: Fix screen clearing when scrolling 2025-06-28 16:55:13 +03:00
05a727979a Kernel: Make sse initialization thread safe 2025-06-28 16:55:13 +03:00
d68c88c3f9 LibC: Implement rewinddir 2025-06-28 16:55:13 +03:00
5f07d53034 WindowServer: Send mod key to clients
Also roll back accidental mod key update from super->alt
2025-06-28 16:55:13 +03:00
fe62ce4bae Kernel: Fix spurious wakeup from SYS_SLEEP 2025-06-28 16:55:13 +03:00
fb09aa4d06 LibInput: Correctly resize keyboard layout maps 0xFF->0x100 2025-06-28 16:55:13 +03:00
4d080b30ab LibInput: Pass raw scancode in KeyEvent 2025-06-28 16:55:13 +03:00
2d314e72fe LibGUI: Implement basic message box 2025-06-28 16:55:13 +03:00
cf07b747fe LibGUI/WindowServer: Implement per-window custom cursors 2025-06-28 16:55:13 +03:00
273e9bbc92 LibGUI/WindowServer: Implement per-window cursor hiding 2025-06-28 16:55:13 +03:00
7dcf1797e9 WindowServer: Cleanup packet callback calling 2025-06-28 16:55:13 +03:00
7aa24b6157 LibGUI: Implement serialization for BAN::Vector 2025-06-28 16:55:13 +03:00
d73a667437 LibGUI: Implement very bad widget system :D 2025-06-28 16:55:13 +03:00
4695fa061d Kernel: Don't panic if UNIX socket is already bound but deleted 2025-06-28 16:55:13 +03:00
7bf7bfbe13 Texture: Add invisible color when copying textures
This should probably support proper alpha blending but I'm lazy :)
2025-06-28 16:55:13 +03:00
397219c22e LibC: Implement very hacky dlopen/dlsym/dclose
If ELF loading fails, this will just crash the program :D

And there is no support for RTLD_LOCAL
2025-06-28 16:55:13 +03:00
83c0ef3514 Kernel: Implement CLOCK_{PROCESS,THREAD}_CPUTIME_ID 2025-06-28 16:55:13 +03:00
4fa40de557 WindowServer: Fix crash when moving mouse out of bounds 2025-06-28 16:55:13 +03:00
bc06926702 LibC: Implement gethostbyaddr 2025-06-28 16:55:13 +03:00
9de27110e2 LibC: Add alloca.h 2025-06-28 16:55:13 +03:00
93e5d09a63 Kernel/LibC: Implement flock 2025-06-28 16:55:13 +03:00
0cbc39698c WindowServer: Ignore SIGPIPE so we don't crash unexpectedly 2025-06-28 16:55:13 +03:00
83069e433f LibGUI/WindowServer: Implement window showing/hiding 2025-06-28 16:55:13 +03:00
bbb490b24f LibGUI: Implement set_max_size
I already support set_min_size so why not this :)
2025-06-28 16:55:13 +03:00
85f200bd86 LibC: Add sched_get_priority_{min,max}
I don't support priority scheduling so these are just no-ops
2025-06-28 16:55:13 +03:00
0f2c02fb04 LibC: Add stubs for pthread_{get,set}schedparam 2025-06-28 16:55:13 +03:00
6d3d41abe2 Kernel: Fix possible division by zero in scheduler 2025-06-28 16:55:13 +03:00
6fa7fe26dc ports: Add support for meson build systems 2025-06-28 16:55:13 +03:00
fe804c123d ports: Add expat port 2025-06-28 16:55:13 +03:00
dba32fb95d ports: Add SONAME to zlib's dynamic library 2025-06-28 16:55:13 +03:00
7dc187fdb1 ports: Update gcc 12.2.0->15.1.0
Also enable threading :)
2025-06-28 16:55:13 +03:00
ee5a627952 ports: Update mpfr 4.2.1->4.2.2 2025-06-28 16:53:06 +03:00
3b83561309 ports: Fix gmp port to compile with gcc 15.1.0 2025-06-28 16:53:06 +03:00
6fb0b5203a ports: Update binutils 2.39->2.44 2025-06-28 16:53:06 +03:00
4677d7a1c6 LibC: Update RAND_MAX INT32_MAX -> INT_MAX 2025-06-19 19:06:24 +03:00
3283359ac8 Kernel: Cleanup ANSI DSR 2025-06-19 19:05:49 +03:00
fff16f6b8c Kernel: don't directly access user memory in mmap 2025-06-19 19:04:20 +03:00
a347ceba74 Kernel: Cleanup sys_wait sleep/signal handling 2025-06-19 19:03:42 +03:00
05836fab4c Kernel: Allow accessing fd's inode without having read/search access
I have no idea what the point of this was. VFS is already verifying
read and search access
2025-06-19 19:02:28 +03:00
15e84f28ed LibC: Include strings.h in string.h 2025-06-19 19:01:45 +03:00
32c35a822b BuildSystem: binutils1.39->1.44, gcc12.2.0->15.1.0 2025-06-19 19:00:50 +03:00
9c86e5e54d Kernel: Add ANSI SGR 39 and 49
Also debug log unimplemented ANSI SRGs, this makes finding missing
commonly used ANSI SGR codes more easy
2025-06-18 20:34:55 +03:00
87f348b48e LibC: Fix my ugly and hacked posix_memalign 2025-06-18 14:17:17 +03:00
ff289b25b6 LibC: Implement {,v}asprintf
These were added in POSIX issue 8
2025-06-17 13:56:30 +03:00
a9f58e96d2 LibC: Add endian.h
This is part of POSIX issue 2024 and some software depends on it
2025-06-17 13:15:42 +03:00
c61ded8a1e toolchain: Update gcc patch to add pthread driver
This makes gcc recognize -pthread argument
2025-06-17 12:49:59 +03:00
7651ca747d LibC: Allow searching null char with wcschr 2025-06-16 15:09:55 +03:00
7ff7a4aa87 LibC: Fix locale handling in wcrtomb and mbrtowc 2025-06-16 15:09:39 +03:00
cdcd226b1a LibC: Fix mbstowcs and add wcstombs 2025-06-16 15:08:49 +03:00
f9451915b9 LibC: Use pause in pthread spinlock locking 2025-06-16 15:07:58 +03:00
5e4e174d61 tests: Add tls test 2025-06-16 15:07:26 +03:00
4a00cb7d55 DynamicLoader: Add few more TLS relocations 2025-06-16 15:06:48 +03:00
b97c123764 BAN: Make WeakPtr::lock const
There is no reason why it would not be :)

Also this prevented upstream from compiling
2025-06-11 16:53:43 +03:00
69bdff6b7e ports: Add links port
We now have graphical browser on banan-os :O
2025-06-11 16:02:00 +03:00
8574fcf6e1 ports: Add libwebp port 2025-06-11 16:01:47 +03:00
f4f424bf04 ports: Add libtiff port 2025-06-11 16:01:47 +03:00
ac745bfa3d ports: Add libjpeg port 2025-06-11 16:01:47 +03:00
aa691f236e ports: Add libpng port 2025-06-11 16:01:47 +03:00
a0a9d49d81 ports: Update toolchain triple and add post_configure
post_configure is called after default configure. This can be used for
port specific customization when using default configure function
2025-06-11 16:01:47 +03:00
125f8b591d Kernel: Don't crash if socket tries to reconnect
:D
2025-06-11 01:54:41 +03:00
c97b60e7e5 LibGUI: Remove parameters I had forgot in function declarations 2025-06-11 01:53:31 +03:00
8a73414e3e LibGUI: Add support for clip area to texture 2025-06-11 01:53:31 +03:00
ac22e006a4 Shell: Don't get stuck on broken state when failing to build command 2025-06-10 11:03:02 +03:00
30d5d85d1d userspace: Add test utility 2025-06-08 23:56:39 +03:00
6f74f3c386 BAN: Allow constexpr construction of StringView 2025-06-07 18:29:32 +03:00
515918329c ports: Add SpecSeek port 2025-06-06 17:41:59 +03:00
8ea0a67280 Terminal: Add support for tabs 2025-06-06 16:41:06 +03:00
5ad7d7edb1 DynamicLoader: Fix TLS on 32 bit platform
There were two problems with my previous implementation
- TLS was not allocated if nothing used it. There is a fallback
  initialization in _init_libc, but this was not enough if one of the
  init functions tried to access errno.
- __tls_get_addr was not resolved. If __tls_get_addr was called through
  a plt entry, everything would just break :(
2025-06-06 16:27:07 +03:00
00c6820825 LibC: Make {open,sys,close}log use their own FILE instead of stddbg 2025-06-06 11:59:15 +03:00
6beaafcf11 LibC: Define std{in,out,err,dbg} with their actual names 2025-06-06 11:56:39 +03:00
e92f039a17 Kernel: Fix tcp sending with already sent unacknowledged bytes 2025-06-06 11:55:44 +03:00
ef76ffa1c1 Kernel: Remove unnecessary hack
This is no longer needed as thread unlocks its spinlock before calling
Process::exit() on terminating signal
2025-06-06 11:13:55 +03:00
652eb2346c Kernel: Fix syscall interrupt disabling
If thread had a terminating signal, syscall leaving would try to lock
process's mutex while not having interrupts enabled
2025-06-06 11:12:48 +03:00
66726090ec Kenrel: Fix TCP connection closing
If TCP socket was connected with connect() instead of accept() it would
never send FIN to other end when it was closed.
2025-06-06 11:10:29 +03:00
b668173cba Kernel: Fix pseudo terminal writability 2025-06-06 11:09:50 +03:00
a7e20d6e85 LibC: Fix getnameinfo port endianness 2025-06-06 06:52:56 +03:00
c6ded82406 Kernel: Fix a deadlock when thread is executing terminating signal 2025-06-06 06:52:27 +03:00
a76c6faffc Kernel: Fix a deadlock when process is exiting 2025-06-06 06:52:02 +03:00
81ff71a97f Kernel: Track the number of recursive spinlocks a thread is holding 2025-06-06 06:51:15 +03:00
56db0efe58 Kernel: Add missing file for race condition fixes :) 2025-06-06 04:03:37 +03:00
5eefd98e1b Kernel: Add debugging macro to dump syscalls that take a long time 2025-06-06 04:00:57 +03:00
eecdad50a6 Kernel: Fix most of mutex + block race conditions
All block functions now take an optional mutex parameter that is
atomically unlocked instead of having the user unlock it before hand.
This prevents a ton of race conditions everywhere in the code!
2025-06-06 03:59:22 +03:00
96d5ed9cc7 Kernel: Fix E1000 driver interrupts
I have no idea why, but E1000 seems to be missing interrupts frequently
when clearing ICR only at the end of the interrupt handler
2025-06-06 03:45:35 +03:00
73090ecb37 Kernel: TTY set EPOLLOUT 2025-06-05 22:04:51 +03:00
8812704601 Kernel: Make sure IPv4 and ARP packets are not missed
This is a really hacky solution but will do until i get atomic
unblocking with respect to locks
2025-06-05 22:03:15 +03:00
0f189d410e Kernel: Fix unix socket recv from
If connection on unix socket was closed and other end tries to recvfrom,
the thread would enter a fucked up state where it held the socket's
spinlock when returning to userspace.
2025-06-05 22:02:53 +03:00
cfeabc4580 Kernel/Terminal: Fix ANSI SGR 8 bit color parsing 2025-06-05 20:43:57 +03:00
49f203d61d Terminal: Add ANSI CSI P and ANSI SGR 22 2025-06-05 02:41:48 +03:00
a912a4dc67 LibGUI: Remove fill_color from texture copy API
Nothing was using this and it just overcomplicated everything
2025-06-05 02:40:51 +03:00
f79db874bf Kernel: Fix ANSI CSI 1J
I was accidentally clearing the whole screen when I needed to clear from
cursor to the end of the screen
2025-06-05 02:38:57 +03:00
8de19aff3c Kernel/Terminal: Fix 24 bit ANSI SGR color parsing 2025-06-05 02:38:07 +03:00
bf41b448d6 Kernel: Fix TCP sending
- Fix race condition when adding packet to send buffer before other end
  has acknowledged it
- Allow sending multiple packets before receiving ACK for previous ones
2025-06-04 22:21:35 +03:00
448632cf11 Kernel: Add fast path to pselect and ppoll
If events are available right away, don't create epoll object to wait
on. Also fix pselect return value to the number of bits set. Previously
return value could've been greater than that if epoll return EPOLLERR or
EPOLLHUP for events that were not listened to
2025-06-04 17:51:22 +03:00
11174bfa14 BuildSystem: Rename toolchain -> x86_64-pc-banan_os 2025-06-03 23:02:10 +03:00
84b1f3990c LibC: Fix getnameinfo
How was i doing everything so wrong :D
2025-06-03 16:36:39 +03:00
943069b2a3 Kernel: Socket EPIPE and send SIGPIPE on write after hang up 2025-06-03 10:24:44 +03:00
e305698e6b Kernel: Fix epoll EPOLLHUP and EPOLLERR reporting 2025-06-03 10:23:53 +03:00
4c0b7d44b4 Kernel: Enable ECHOE and ECHOK, support VKILL, fix VEOF 2025-06-02 16:26:53 +03:00
775c77c0fa Shell: Get default backspace key from c_cc[VERASE] 2025-06-02 15:55:20 +03:00
fb466b5af7 Kernel: use termios c_cc values instead of hardcoded characters 2025-06-02 15:54:11 +03:00
e473118ec8 userspace: Add nologin "shell" 2025-06-02 12:26:16 +03:00
755d41ca4e LibC: Add pw_passwd and pw_gecos to passwd structure
This information is available in /etc/passwd either way so why not
expose it to the user. Practically all UNIX-likes have these either way
2025-06-02 12:23:06 +03:00
bbff9f89b0 BuildSystem: Don't invoke ninja directly, but use cmake --build 2025-06-02 11:45:06 +03:00
fdcb38ac1f Shell: Accept '\r' as enter
This happens with some terminals and i don't want to bother with fixing
my termios :D
2025-06-02 11:42:06 +03:00
fac742c038 test-sort: Add qsort test 2025-06-02 11:41:34 +03:00
5a6b43fc90 LibC: Remove debug printing from getnameinfo 2025-06-02 11:39:18 +03:00
317f413746 LibC: Implement very hacky posix_memalign
I did not even test this and i know the code is super hacky. I could not
bother with writing proper code for this xD
2025-06-02 11:39:18 +03:00
895909b7fa LibC: Add CMSG_* definitions to sys/socket.h 2025-06-02 11:39:18 +03:00
2ee8b6c8b4 LibC: Add more definitions to netinet/in.h
These are non-standard but a lot of UNIX-likes have them networking
software attempts to use them
2025-06-02 11:39:18 +03:00
022bb69782 LibC: Implement inet_aton
This is not POSIX but IMO it makes sense to have the counter part to
inet_ntoa
2025-06-02 11:39:18 +03:00
be6da3e0db BuildSystem: Compile gcc with threading support 2025-06-02 11:39:18 +03:00
1f07e02298 BuildSystem: Fix cmake toolchain file processor 2025-06-02 11:39:18 +03:00
7a645b8555 Kernel: Add SMP message StackTrace
This event is sent when user presses ctrl+{F1-F12} and it will dump the
corresponding processor's stack trace. This is really helpful for
detecting deadlocks in the system
2025-06-02 11:39:18 +03:00
c5b0d0235f Kenrel: Allow Processor::send_smp_message to send event to current CPU 2025-06-02 11:39:18 +03:00
b7948551ff userspace: Add empty libm and libpthread
These making porting stuff easier. I could not find a way to tell CMake
that the system does not have threads library
2025-06-02 11:39:18 +03:00
e109b5cff6 Kernel: Remove unnecessary locks from Pipe
Inode already locks its own mutex when read/write is called there is no
need to explicitly lock them in read_impl/write_impl
2025-06-02 11:39:18 +03:00
9883fb7bf6 Kernel: Rewrite epoll notifying system
This removes the need to lock epoll's mutex when notifying epoll. This
prevents a ton of deadlocks when epoll is notified from an interrupt
handler or otherwise with interrupts disabled
2025-06-02 11:39:18 +03:00
e9f8471a28 BAN: Return UTF::invalid from byte_length instead of 0 2025-06-02 11:39:18 +03:00
4656b11256 LibC: actually use ATEXIT_MAX for atexit limit 2025-06-02 10:43:49 +03:00
f2ccab2df7 ports/openssl: Fix openssl
New unistd.h definitions (or something) makes openssl think recvmsg is
available, disable it manually.
2025-06-01 19:51:33 +03:00
b2e3aefa72 Kernel: Don't crash when terminating process with signal 2025-06-01 16:59:02 +03:00
2b48933f29 LibC: Implement all functions from complex.h 2025-06-01 13:48:03 +03:00
4ac6cbe70e LibC: Add some missing wchar.h functions
isw* functions are just wrappers to is*
tow* functions are just wrappers to to*
2025-06-01 13:48:03 +03:00
cc07c3df94 LibC: Add basic strxfrm{,_l} 2025-06-01 13:48:03 +03:00
31bcad2535 LibC: Implement truncate 2025-06-01 13:48:03 +03:00
b75970958e Kernel/LibC: Implement unlinkat 2025-06-01 13:48:03 +03:00
91756c057e LibC: Add all of the missing POSIX definitions in unistd.h and limits.h 2025-06-01 13:48:03 +03:00
df7f245cf8 LibC: Implement pthread_atfork
Again this code is not tested but *feels* right :D
2025-06-01 13:48:03 +03:00
dbdefa0f4a LibC: Implement pthread cancelation
This code is not tested at all but it looks correct xD
2025-06-01 13:48:03 +03:00
56fdf6002c Kernel/LibC: Implement pthread_kill 2025-06-01 13:48:03 +03:00
c957f1ddca LibC: Cleanup pthread code and add some pthread_attr functions
errno, pthread cleanup and pthread id are now stored in uthread. This
allows using these without TLS
2025-06-01 13:48:03 +03:00
423386a052 LibC: Add memory.h that just includes string.h
There are a lot of ports trying to include memory.h. This is not posix
but glibc just includes string.h. I think this is just to privide mem*
functionss...?
2025-06-01 13:48:03 +03:00
1c882ea361 DynamicLoader: Don't print TODOs on PT_GNU_ headers
These should be either handled by kernel or just used as optimizations.
There is no requirement to handle them in dynamic loader
2025-06-01 13:48:03 +03:00
b1065fa01d Kernel/LibC: Add ppoll syscall and fix poll
poll is now using its own syscall instead of wrapping aroung pselect.
This adds less overhead on top of poll and adds support for POLLHUP
2025-06-01 13:48:03 +03:00
8ff9c030bf Kernel: Add better termios support
I'm not sure if this is correct but at least it's better than before :)
2025-06-01 13:48:03 +03:00
9b875fb930 Kernel: Make epoll work with different fds pointing to same inode 2025-06-01 13:48:03 +03:00
857bac4b78 Kernel: Disable unused interrupt methods in PCI devices 2025-06-01 13:48:03 +03:00
30074c290d Kernel: Add more descriptive names to sockets types 2025-06-01 13:48:03 +03:00
60d1c26114 Kernel: Fix race condition in FileBackedRegion creation 2025-06-01 13:48:03 +03:00
692ba43182 Kernel: Fix spinlock bugs found by the new spinlock security 2025-06-01 13:48:03 +03:00
6542a037df Kernel: Make spinlocks more safe
Kernel now makes sure thread is not holding any spinlocks when it tries
to lock a mutex or yield. Spinlocks are supposed to be only used for
short times without the possibility of yielding
2025-06-01 13:48:03 +03:00
9f4b451501 Kernel: Fix epoll deadlock
If epoll_wait and epoll_notify were called at the same time, there was a
possible deadlock when epoll was confirming the event from the inode
2025-06-01 13:48:03 +03:00
1bd454b8fd Kernel/LibC: Implement utime* family functions
This patch adds *working*
 - utime
 - utimes
 - utimensat
 - futimens
2025-06-01 13:48:03 +03:00
8392472bac ports: Add git port
This commit is pushed from banan-os :D
2025-05-29 00:31:40 +00:00
cd5b351ce4 Kernel: Fix fchmodat mode handling
Ignore file type bits instead of returning EINVAL if they are set
2025-05-29 03:24:31 +03:00
50024fbf8b ports/vim: Set EDITOR=vim in .shellrc 2025-05-29 01:20:30 +03:00
4d4fb3b6ec Kernel: Cleanup and fix pipe
pipe now sends SIGPIPE and returns EPIPE when writing and no readers are
open
2025-05-29 01:02:22 +03:00
37dea8aee7 userspace: Implement basic less program
This is very simple and only supports couple of flags and scrolling
2025-05-29 01:00:28 +03:00
69c4940b27 LibC: Fix signal return value
signal was returning `func` when it should've returned the old handler
2025-05-29 00:58:30 +03:00
7691b019e2 LibC: Fix printf %c modifier for null byte 2025-05-28 03:10:01 +03:00
f55d6b11c5 LibC: Implement mblen 2025-05-28 03:10:01 +03:00
f52877abb4 LibC: Implement readv and writev 2025-05-28 03:10:01 +03:00
ee7c9b6731 LibC: Add simple getnameinfo
This doesn't actually do any name resolution but just formats input to
string.
2025-05-28 03:10:01 +03:00
4721344518 LibC: Don't fail getaddrinfo if node is null 2025-05-28 03:10:01 +03:00
e0d986dcd7 LibC: Add missing u_char and u_short types 2025-05-28 03:10:01 +03:00
c7be3dcd5b LibC: Add timer{add,sub,clear,isset,cmp}
These are not POSIX but used by used by some ports
2025-05-28 03:10:01 +03:00
89c9bfd052 Kernel/LibC: Implement socketpair for UNIX sockets 2025-05-28 03:10:01 +03:00
12b93567f7 Kernel/LibC: Implement getpeername 2025-05-28 03:10:01 +03:00
2f37776614 Kernel: Notify epoll on new TCP connections 2025-05-28 03:10:01 +03:00
f778bca3f2 Kernel: Remove accidentally commited debug code :) 2025-05-28 03:10:01 +03:00
a945d19750 Kernel: Partially fix PCI PIN interrupt routing
Don't fail early if the first device is not the one we are looking for
2025-05-28 03:10:01 +03:00
7f04b2c96c Kernel: Fix E1000 interrupt handling
E1000 does not support MSI-X and thus does not generate RxQ0 interrupts.
2025-05-28 03:10:01 +03:00
8aa4e4ff1e LibC: Implement clearenv
This is GNU extension but seems nice to have :D
2025-05-28 03:10:01 +03:00
7eade002a7 LibC: Fix mktime
yday calculation was off so results were always off for march-december
2025-05-28 03:10:01 +03:00
a8f8d27f4e LibC: Implement basic tzset()
I still don't have timezone support so this just sets values to UTC
2025-05-28 03:10:01 +03:00
356935bd4f LibC: Fix strtou{,l,ll} for negative values
Also set endp if base is invalid
2025-05-28 03:10:01 +03:00
bce3dd045f LibC: Fix strncat return value 2025-05-28 03:10:01 +03:00
79a2b84c81 Kernel: Fix process exit when there are multiple threads 2025-05-28 03:10:01 +03:00
44b762f916 Kernel/LibC: Implement pwrite and make pread non-locking 2025-05-28 03:10:01 +03:00
5d80c880c8 LibC: Fix FILE buffering once again :D 2025-05-28 03:10:01 +03:00
b907263f35 LibC: Implement basic tmpfile 2025-05-28 03:10:01 +03:00
0f0accf82c LibC: Don't use false in pthread initializers 2025-05-28 03:10:01 +03:00
ddcf414107 LibC: Fix netinet/in.h and arpa/inet.h definitions 2025-05-28 03:10:01 +03:00
6be3b1d7f2 commit from banan-os :D 2025-05-27 23:57:43 +00:00
0e0d7016b3 Kernel: Rename has_hangup -> has_hungup 2025-05-17 12:39:23 +03:00
553c76ab0f Kernel: Add locking to inode's epoll list
This was prone to crashing :)
2025-05-17 12:36:36 +03:00
b90cfa8e5c test-window: poll events instead of sleeping 2025-05-13 10:19:13 +03:00
e7f0cd0c4b stat: Fix return value when one of stats fails 2025-05-13 10:19:13 +03:00
0661b339a0 test-tcp: Fix name resolution
Comparison was the wrong way around so hostname lookup always failed.
2025-05-13 10:19:13 +03:00
d1bb72f6fb Kernel: Don't allow CPU load printing underflow 2025-05-13 10:19:13 +03:00
1bcd1edbf5 Kernel/LibC: Implement basic epoll
This implementation is on top of inodes instead of fds as linux does it.
If I start finding ports/software that relies on epoll allowing
duplicate inodes, I will do what linux does.

I'm probably missing multiple epoll_notify's which may cause hangs but
the system seems to work fine :dd:
2025-05-13 10:18:05 +03:00
143a00626b Kernel: Fix fork cmdline copying and copy environ 2025-05-13 10:16:21 +03:00
0eb981f51c Kernel: Fix Random.h includes 2025-05-13 10:16:21 +03:00
6cc01349f7 Kernel: Fix unblocking recv through read 2025-05-13 10:16:21 +03:00
a7bd4acd46 Kernel: Remove static variables from virtual tty 2025-05-13 10:16:21 +03:00
8e0a56b49a Kernel: Implement loopback network interface 2025-05-13 10:16:21 +03:00
a8844ddd28 WindowServer: Send mouse release to same window as mouse press 2025-05-13 10:16:21 +03:00
c18fefd5f3 BuildSystem: Cleanup cmake library linking 2025-05-07 18:42:37 +03:00
3040940e35 ports/tcc: Fix 32 bit build and add version name
tcc was using "Linux" for machine name in version string if it was not
explicitly specified.
2025-05-07 18:33:39 +03:00
df3d2d57c3 ports/quake2: Update to new LibGUI interface 2025-05-07 17:23:15 +03:00
92d26f2216 ports/doom: Update to new LibGUI interface 2025-05-07 17:21:29 +03:00
0380c68f89 ports/tinygb: Update to new LibGUI interface 2025-05-07 17:21:29 +03:00
2a6dc6a7b7 LibGUI: Add missing Texture files 2025-05-07 17:21:29 +03:00
40617f0d5c WindowServer: Make mod+d open program launcher 2025-05-06 00:42:15 +03:00
09745a7835 userspace: Implement program launcher
This is kinda useless as I only have Terminal and test-window
implemented. Also the code is really messy as I don't have GUI widgets.
2025-05-06 00:41:22 +03:00
57f6f50939 Terminal: Implement dumb font bolding
This is just drawing character twice at one pixel offset
2025-05-05 23:09:53 +03:00
f959905adf LibGUI: Rework window rendering
Abstract drawing surface to Texture. All windows now contain a texture
matching its size.
2025-05-05 23:08:01 +03:00
f78c7e7926 LibGUI: Add API to block until window events are available 2025-05-05 22:33:00 +03:00
96496da0ab Kernel: Allow USB mouse to send extra2 button events 2025-05-05 22:32:26 +03:00
2dc4733ac1 test: improve pthread test 2025-05-05 19:21:47 +03:00
f14774d034 libc: fix tmpnam when no name is found 2025-05-05 19:17:16 +03:00
c08c63f420 libc: reorder destructor and fflush in exit 2025-05-05 19:16:52 +03:00
eb79c6c47c mkdir: Add -p option 2025-05-05 19:16:29 +03:00
bf1cbb4cde Terminal: Update terminal size and send SIGWINCH on resize 2025-05-05 19:09:21 +03:00
592675022e Kernel: Allow tcgetpgrp on pseudo terminal masters 2025-05-05 19:09:01 +03:00
b2e10d7e6e Kernel: Remove unnecessary locks 2025-05-05 19:08:57 +03:00
0689954433 Terminal: Set minimum size to 8x2 cells 2025-05-05 18:20:22 +03:00
5c37f198cb WindowServer/LibGUI: Allow windows to set minimum size 2025-05-05 18:19:59 +03:00
3b02a9d4fe WindowServer: Resize from closest corner 2025-05-05 18:19:19 +03:00
c9057aa498 WindowServer: Cleanup code and resize on fullscreen 2025-05-05 16:42:15 +03:00
2b0d198b05 Terminal: Allow resizing of the terminal 2025-05-05 03:15:30 +03:00
7798145c74 WindowServer: Implement window resizing
windows can now set resizable attribute which allows window server to
resize them
2025-05-05 03:14:50 +03:00
fcfadd7c74 LibGUI: Add background color for windows
This is used when resizing a window to fill the empty space
2025-05-05 03:12:31 +03:00
c0181820a9 ports/tinygb: Set title like sdl frontend does 2025-05-05 01:10:41 +03:00
76d4e6bd18 LibGUI: Add support for changing window title 2025-05-05 01:10:05 +03:00
ccb81de85d snake: Use box drawing characters
This makes it look much better.

Also fix bug with apples generating on top of snake's tail
2025-05-05 00:30:58 +03:00
82f4975f45 LibC: Save callee saved registers on setjmp 2025-05-04 13:54:35 +03:00
d457e6ad6a LibC: Fix printf e/E modifier for negative exponents 2025-05-04 13:42:17 +03:00
abf7c8e68a LibC: Implement difftime 2025-05-04 13:42:17 +03:00
1a38d0c31e LibC: Add g/G modifiers to printf 2025-05-04 13:42:17 +03:00
9ff9d679e9 Kernel: Fix text mode cursor
Apparently text mode renders cursor in the *foreground* color. My
current clear function used the same color for foreground and background
making the cursor effectively invisible.

Also cursor hiding is now done by moving the cursor off bounds (0, height)
some website I read said this to be valid even on VGA compatible cards
without disable bit.

http://www.osdever.net/FreeVGA/vga/textcur.htm
2025-04-25 02:31:33 +03:00
9f3f8f950a Kernel: Add better panic message for failed shutdown
ACPI shutdown does not work on the web emulator and running `poweroff`
crashes on `ASSERT_NOT_REACHED()`.
2025-04-25 01:52:33 +03:00
006a196e4a LibC: optimize strpbrk, str{,c}spn, strtok{,_r}
These matches are now detected with bitmasks instead of looping over the
second string
2025-04-24 01:39:49 +03:00
418678466c Kernel: Fix text mode palette
ANSI and text mode color indices are not in the same order
2025-04-23 23:07:47 +03:00
9f4cb5c4dd Kernel: Make pseudo terminals not overwrite old data
If pseudo terminal buffer was filled, old implementation would overwrite
old data. This is bad if producer is capable of producing more data than
consumer can handle.
2025-04-23 22:03:53 +03:00
73f9de6635 Terminal: Add support for ANSI SGR 8bit and 24bit 2025-04-23 22:03:53 +03:00
12b9c82086 Terminal: Don't wrap cursor right after x == cols
This prevents scrolling when bottom right scroll is written to
2025-04-23 22:03:53 +03:00
a8edb8870e Kernel: Add support for 8bit and 24bit ANSI SGR 2025-04-23 22:03:53 +03:00
dabc3c6cc4 Kernel: Don't wrap cursor immediatly at cols()
This prevents unwanted scrolling when writing to bottom right cell
2025-04-23 22:03:53 +03:00
cc7c1ad30d Kernel: Add per terminal palette for TerminalDriver
This allows better color approximation on text mode and in future will
allow user to possibly change the palette
2025-04-23 18:44:37 +03:00
4d840a8d9a BAN: Make Array more constexpr 2025-04-23 18:40:20 +03:00
95a80bfe81 ports: Add tinygb port
This is awesome!
2025-04-23 13:19:28 +03:00
53e9eab0cd ports/tcc: Fix building on 32 bit 2025-04-23 08:43:27 +03:00
35b3c3c98c Kernel: Fix scheduler load balancing
I was not updating the current queue of the thread which lead to blocked
threads think they were in run queue
2025-04-23 08:09:51 +03:00
20e17a28cf Kernel: Fix \b handling
Don't clear the character, only move cursor backwards
2025-04-23 06:33:11 +03:00
28bf2d6374 Kernel/Terminal: Add support for ANSI DSR 2025-04-23 06:14:56 +03:00
8a00b53050 Kernel/Terminal: Fix ANSI SGR m for multiple values 2025-04-23 05:29:22 +03:00
8834241417 LibC: Fix scanf %n modifier
Old code was always returning off by one
2025-04-22 09:55:38 +03:00
96740d6be4 LibC: Make inet_addr spec compliant
I was not doing any error checking, basically i validated anything that
started with atleast a single digit.
2025-04-22 09:40:46 +03:00
b853d29992 Kernel: Fix unix domain socket close detection 2025-04-22 08:36:44 +03:00
33a0f562d3 resolver: Add support for CNAME
Also rework resolver's send format and convert test-tcp and nslookup to
use getaddrinfo
2025-04-22 08:36:44 +03:00
f8e3ae0525 Kernel: Fix deadlock caused by multithreading
This allows multiple threads to concurrently call the most common
blocking syscalls:
- read
- write
- accept
- connect
- sendto
- recv
- pselect

This prevents a dead lock when for example process is waiting on a pipe,
but unable to write to it since process is locked.

This is the beginning of starting to remove processes own lock from
syscall and locking only necessary parts.
2025-04-22 04:51:53 +03:00
c790bad667 Kernel: Make OpenFileDescriptorSet thread safe
Also this allows concurrent calling of read/write/send/recv
2025-04-22 04:31:18 +03:00
d54489bbcb Kernel: Implement MemoryRegion pinning
This allows process to pin a MemoryRegion into users memory space for
syscall duration without allowing user to munmap the region.
2025-04-22 04:30:07 +03:00
808c97020a Kernel/LibC: Implement SA_RESTART
I have been thinking how to do this for a long time but I finally
figured out a semi-clean way
2025-04-22 02:42:44 +03:00
34e680d792 ports/ncurses: Set some needed environment variables
ncurses depends on these being set to function properly
2025-04-22 01:56:34 +03:00
32d543943b ports: Add lynx port
I have had this for a while but apparently never commited :D
2025-04-22 01:44:49 +03:00
2632507980 ports/ca-certificates: Add symlink to /etc/ssl/cert.pem
Some ports try to use this file
2025-04-22 01:44:02 +03:00
f467a9a309 resolver: Resolve hostname to loopback address
We don't currently support loopback adapters, but some ports were trying
to resolve it.
2025-04-22 00:48:26 +03:00
5c9710c78b LibC: Implement strcoll_l 2025-04-22 00:48:26 +03:00
107b31a0b5 Kernel: Fix E1000{,E} driver for older qemu versions
This patch adds clearing of *Interrupt Cause Registers*, which allows
older qemu versions to send new interrupts. Apparently this is not
needed on newer releases.
2025-04-22 00:31:13 +03:00
028c7a822f LibC: Don't define SCHAR_MAX in locale.c 2025-04-21 22:21:40 +03:00
18f5f98e62 General: Mark USB hubs done in README 2025-04-21 22:13:31 +03:00
543bb3cc4b LibC: Rework malloc locking add proper realloc 2025-04-21 20:29:28 +03:00
1c44d24b76 Kernel: Fix TCP closing state machine 2025-04-21 20:02:32 +03:00
5305f962c0 ports/openssl: Make openssl port threaded 2025-04-21 19:59:57 +03:00
b774f147da LibC: Implement dummy pthread_attr_{get,set}detachstate
detached threads are not yet supported, but this allows implementation
to make sure threads are joinable.
2025-04-21 19:58:01 +03:00
2a5921b9c9 LibC: Implement pthread_barrier
This is not fully working but should be fine for most cases
2025-04-21 19:53:38 +03:00
60cb392e97 LibC: Implement pthread_barrier
This is yet another bad sched_yield implementation :D
2025-04-21 19:52:14 +03:00
d012c538c3 LibC: Add PTHREAD_SPIN_INITIALIZER
This is not posix, but current implementation allows adding this
2025-04-21 19:47:00 +03:00
1c88d0d7f7 LibC: Implement pthread_rwlock
This uses the same dumb sched_yield instead of actually blocking :D
2025-04-21 18:48:47 +03:00
773b8de8ba LibC: Refactor pthread type definitions 2025-04-21 14:38:40 +03:00
5d8dd090a9 LibC: Implement pthread_once 2025-04-21 14:17:17 +03:00
2cbfe70a28 DynamicLoader: Don't leak fds 2025-04-20 18:18:32 +03:00
16dbfbb267 LibC: Make limits.h *_MAX usable in #if comparisons 2025-04-20 17:15:20 +03:00
99fc7817c6 Kernel: Cleanup stack alignment assembly 2025-04-20 16:55:18 +03:00
265b4c2b22 LibC: Implement thread_equal 2025-04-20 03:27:16 +03:00
db9db2cc40 LibC: Implement basic pthread mutexes
This implementation is just calling sched_yield if it could not get
mutex. This is not optimal as it does not allow the CPU to idle, but it
works for now :)

Also I did not test this code at all, but it feels correct :D
2025-04-20 03:27:16 +03:00
3642eabac0 LibC: Use BAN::atomic_* functions in pthread spinlock
This allows us not to reinterpret_cast pthread_spin_t to
BAN::Atomic<pthread_spin_t> which is much better :)
2025-04-20 03:11:41 +03:00
98e05fd179 BAN: Implement atomic functions for normal integers 2025-04-20 03:11:41 +03:00
1ccff9478f LibC: Don't define __tls_get_addr if TLS is disabled
This makes linking fail if something tries to use TLS :)
2025-04-20 03:11:41 +03:00
85f9b585f5 LibC: Don't yield on pthread_spin_lock
Thats kinda the whole point of spinlocks :D
2025-04-20 03:11:41 +03:00
01626b4c9f LibC: Add stub for pthread_detach 2025-04-20 03:11:41 +03:00
a85841ca76 LibC: Add stub for pthread_attr_setstacksize 2025-04-20 03:11:41 +03:00
fe6c4cd0b5 LibC: Implement POSIX TLD area (pthread_key*) 2025-04-20 03:11:41 +03:00
f1585d09e1 LibC: Add more integer size definintions to limits.h 2025-04-19 21:50:26 +03:00
252784ff5b Kernel: Preserve kernel command line on fork 2025-04-19 21:29:52 +03:00
6f9dc2a9b8 Kernel/LibC: Implement fchdir, cleanup chdir and getcwd 2025-04-19 21:28:31 +03:00
7edfae8583 Shell: Cleanup export builtin 2025-04-19 21:23:26 +03:00
28275d86ea LibC/Shell: set PWD env in Shell, not libc
I have no idea why I was doing it in the libc
2025-04-19 21:16:11 +03:00
2d19b5074e LibC: Implement some missing wchar functions 2025-04-19 20:56:41 +03:00
e62cc17797 LibC: Use nl_langinfo for strings in strftime 2025-04-19 20:03:56 +03:00
407eed212a LibC: Implement nl_langinfo
All values are from POSIX locale except CODESET which can be "UTF-8"
depending on the current locale
2025-04-19 20:02:01 +03:00
12d47858c1 LibC: Fix overflow error in fread and fwrite 2025-04-19 18:42:12 +03:00
3d34e6e6d9 ports: ncurses add support for shared libraries 2025-04-19 05:55:16 +03:00
dc188e601a LibC: Add definition for LOG_UPTO 2025-04-19 02:48:21 +03:00
8a2df23260 LibC: Define RLIM_NLIMITS 2025-04-19 02:34:56 +03:00
46079a8612 LibC: Implement no-op posix_madvice
Also add non-posix prefixed definitions
2025-04-19 02:07:45 +03:00
201d752850 Kernel: Allow pipe to write partial data
This allows potential blocking
2025-04-19 00:39:42 +03:00
63b3d9875d Kernel: Fix Thread::block_with_eintr* functions
I was using wrong block function, `block_with_timeout` instead of
`block_with_wake_time`. This caused functions to block way too long and
caused a lot of hangs.
2025-04-19 00:39:42 +03:00
8cd2d772b0 Shell: Print error if execv fails 2025-04-19 00:39:42 +03:00
2ff3f88b4d LibC: Add support for shebangs
I implemented shebangs in userspace as I don't really see the benefit of
doing it in kernel space. Only benefit I can think of is executing non
readable scripts but I don't really see the benefit in that.
2025-04-19 00:39:42 +03:00
ab4dd6a268 LibC: Add ARG_MAX constant 2025-04-19 00:39:42 +03:00
0094efc7f4 LibC: Fix execl* memory leak on error 2025-04-18 20:54:53 +03:00
d73a270fb1 Shell: Save and restore stdin flags after child returns
If child makes stdin nonblocking, Shell now restores it back to "normal"
flags
2025-04-18 18:26:09 +03:00
d9647868cc Terminal: Fix ANSI SGR color invert 2025-04-18 17:32:24 +03:00
85505b0482 Kernel: Fix ANSI SGR color invert 2025-04-18 17:31:46 +03:00
703c1a485c Kernel: Fix Ext2 bug for big files
My ext2 implementation was reading wrong blocks for very big block
indices.
2025-04-18 04:17:31 +03:00
9258c73484 Kernel: Optimize VTTY cursor rendering
cursor is now only updated once after all consecutive `putchar`s are
handled.
2025-04-18 03:55:56 +03:00
6858546ce9 Kernel: Fix rendering bugs with framebuffer cursor 2025-04-18 03:54:17 +03:00
7c6966a9c4 Kernel: Add support for text mode terminal
This probably won't be used at all but it was so simple and made me do
really nice refactorings so i decided to add it :)
2025-04-18 02:45:06 +03:00
40d1d20cd6 Kernel: Move cursor handling from TTY -> TerminalDriver 2025-04-18 02:43:41 +03:00
c0942d78cb Kernel: Fix TTY ANSI ? handling 2025-04-18 02:42:49 +03:00
cef8779bf7 Kernel: Improve error handling when setting TTY font 2025-04-18 02:42:24 +03:00
d6667844de Kernel: Fix fcntl F_SETFL and masking 2025-04-18 02:37:44 +03:00
4cdf218145 Kernel: Don't allow opening file with path "" 2025-04-18 02:37:16 +03:00
994713d04c Kernel: Implement FramebufferDevice::get_pixel() 2025-04-18 02:35:28 +03:00
554b13ac50 Kernel: Restructure terminal initialization
This is still very ugly and will be rewritten in the future :D
2025-04-18 01:19:59 +03:00
439fb57d88 Kernel: Fix ANSI CSI @ and b for VirtualTTY 2025-04-17 23:24:17 +03:00
4409d0f03f Terminal: Implement ANSI CSI A, B, b, d, @ 2025-04-17 23:16:22 +03:00
ebd00b1eb2 Terminal: Implement ANSI SGR 10, 39, 49 2025-04-17 23:15:44 +03:00
3ca0ef1583 LibGUI: Add copy_rect API
This allows moving parts of window around
2025-04-17 23:14:46 +03:00
88abbd90dc LibC: Fix strncat
strncat was using strncpy internally which nullpadded dest until n bytes
were written.

also there was no terminating null byte added if src was shorter than n
bytes
2025-04-17 23:12:40 +03:00
bdbde25784 LibC: Rewrite environ handling
environ is only allocated on heap when you insert new variables.

environment variables are only `free`'d if they are `malloc`'d by libc
2025-04-16 21:08:01 +03:00
ee9e941a56 LibC: Implement getitimer 2025-04-15 23:35:25 +03:00
ac90800c3c Kernel/LibC/DynamicLoader: Implement thread local storage
For some reason this does not work on 32 bit version, so it is disabled
on that platform. I'll have to look into it later to find the bug :)
2025-04-15 23:33:39 +03:00
08f5833ca8 Kernel/LibC: Implement pthread_attr_init 2025-04-15 23:31:17 +03:00
4bcd3ed86f Kernel: Start working on TLS, add SYS_{SET,GET}_TLS 2025-04-15 23:31:17 +03:00
254fd80088 DynamicLoader: Cleanup and prepare for TLS 2025-04-15 23:31:17 +03:00
d7e6df1e44 LibELF: Add definitions for ELF TLS values 2025-04-15 23:31:17 +03:00
a933fabb86 Kernel: Define constant USERSPACE_END
This should be used for userspace generic allocations. Currently I used
KERNEL_OFFSET, but I want to limit userspace to the actual lower half of
the address space
2025-04-15 23:31:17 +03:00
36baf7b0af Kernel/LibC/DynamicLoader: Update process start ABI
We now use SysV abi for process startup
2025-04-15 23:05:52 +03:00
e6026cb0b8 DynamicLoader: Handle circular dependencies 2025-04-15 23:05:52 +03:00
cc2b4967ea LibC: Make malloc thread safe with pthread_spinlock 2025-04-15 23:05:52 +03:00
cf59f89bfb LibC: Rework constructor/destructor calling
constructors are now called in _init_libc instead of crt0

destructors are now registered with atexit() instead of called manually
2025-04-15 23:05:52 +03:00
066ed7e4a1 LibC: merge atexit and __cxa_atexit into common function 2025-04-15 23:05:52 +03:00
4f49d60e4a DynamicLoader/LibC: lazy malloc environ
This allows DynamicLoader to just set the value of global environ symbol
without libc needing to malloc it at startup
2025-04-15 23:05:52 +03:00
3721dadd72 LibC: Make stdio and malloc initialization constructors 2025-04-15 22:01:57 +03:00
5539d5eed0 LibC: Implement pthread_cleanup_{pop,push} 2025-04-15 21:48:38 +03:00
64002626b9 LibC: Add h_addr definition for hostent backwards compatibility 2025-04-15 21:39:50 +03:00
4b1c20fa36 Kernel: Make SYS_{,P}READ work with count == 0 2025-04-15 21:36:00 +03:00
b418683337 LibELF: Add definition and values for auxiliary vectors 2025-04-15 21:31:02 +03:00
00015285ab Kernel: Add vaddr->paddr getter to VirtualRange 2025-04-15 21:25:15 +03:00
0f936fc163 Kernel: Cleanup 32 bit interrupt stack alignment 2025-04-15 21:21:23 +03:00
15045cc486 Kernel: Make nonblocking sockets unblocking :) 2025-04-05 18:42:02 +03:00
c9132d984b Kernel: Fix TCP window scaling 2025-04-05 18:40:23 +03:00
a0123e7c2d Kernel: save and load sse context in more spaces 2025-04-02 12:58:39 +03:00
be786be67d Kernel/LibC: Implement pthread_join 2025-04-02 12:58:39 +03:00
e85b18e206 LibC: Fix pthread stack alignment 2025-04-02 12:58:39 +03:00
f32f62dfc1 LibC: Implement pthread_spin_* functions 2025-04-02 12:58:39 +03:00
28392050bf LibC: Make pthread_t pid_t 2025-04-02 12:58:39 +03:00
b9cc6063ff LibC: Implement stdio FILE locking 2025-04-02 12:58:39 +03:00
9066e62a97 Kernel/LibC: Implement sched_yield 2025-04-02 12:58:39 +03:00
5549696c3a Kernel/LibC: Implement pthread_self 2025-04-02 02:39:29 +03:00
691c9fe8e0 LibC: Fix bsearch
bsearch had unsigned integer underflow which was UB and returned false
positives
2025-04-02 00:03:50 +03:00
04463675c0 LibC: Lock file during gets 2025-04-01 23:26:13 +03:00
b9da6a4a5d LibC: Implement getdelim and getline 2025-04-01 23:26:13 +03:00
9fb161c320 Kernel: Move thread stacks 1 MiB back 2025-04-01 23:26:13 +03:00
2ba25b4c28 LibC: Add non standard types/values used by ports 2025-04-01 23:26:13 +03:00
c1618e2b5d Kernel/LibC: Add basic support for pthread_{create,exit} 2025-04-01 23:26:13 +03:00
788f5429e1 LibC: Implement spec compliant abort() 2025-04-01 23:09:30 +03:00
36026d4ec6 Kernel: Cleanup TCP and add basic window scaling support 2025-04-01 23:09:30 +03:00
96767f5ca8 Kernel: Implement PCI interrupt routing
This does not really work but I have no idea what I'm doing wrong
2025-04-01 23:09:30 +03:00
76bad31dd5 Kernel: Reorder locking with VirtualRange 2025-04-01 23:09:30 +03:00
2e3b917192 Kernel: Cleanup PS2 mouse button event generation 2025-04-01 23:09:30 +03:00
95f262b3e6 Kernel: Print process pid through /dev/debug 2025-04-01 23:09:30 +03:00
aebacb6b6a Kernel: Bypass PS2 detection if scancode set is forced 2025-04-01 23:09:30 +03:00
27613da5ea Kernel: Route PCI Interrupt Link Device interrupts 2025-04-01 23:09:30 +03:00
28ac6c2267 Kernel: Implement AML FindSet{Left,Right}Bit 2025-04-01 23:09:30 +03:00
1c1fc65c7c Kernel: Add API to reserve GSI instead of irq
This also fixes a bug with IOAPIC gsi_base != 0
2025-04-01 23:09:30 +03:00
ba74b352bd Kernel: Make BufferField actually access the buffer and not copy 2025-04-01 23:09:30 +03:00
0474ac4262 Kernel: Expose ACPI resolve_package_element to outside 2025-04-01 23:09:30 +03:00
aba49cc93f Kernel: Add API to get ACPI reference paths 2025-04-01 23:09:30 +03:00
b3b5b40163 Kernel: Add _OS an _REV to ACPI namespace 2025-04-01 23:09:30 +03:00
0e085b30cc Kernel: ACPI add easier API for calling methods with arguments 2025-04-01 23:09:30 +03:00
35149b6960 Kernel: Add helper functions to create AML String and Buffer 2025-04-01 23:09:30 +03:00
3800d5420e Kernel: Collect created AML nodes in add_{named,alias}...
This makes it harder to miss adding scoped objects. Before I was not
deleting all types of nodes on method return
2025-04-01 23:09:25 +03:00
b145c1ab64 Kernel: Add easier api for evaluating ACPI nodes 2025-04-01 23:09:20 +03:00
b8a3439219 Kernel: Add getter for ACPI namespace 2025-04-01 23:09:15 +03:00
1a153b835c BAN: Nullterminate encoded UTF8 data 2025-04-01 22:39:56 +03:00
73c292c4e9 BAN: Fix negative floating point value printing 2025-04-01 22:39:21 +03:00
d8bb0b53f8 LibImage: Fix PNG palette decoding
I was only loading third of the palette to wrong indices :D
2025-02-12 10:09:03 +02:00
83c66901f8 Kernel: Fix reboot when ACPI is disabled
If ACPI was disabled ACPI::reset() would page fault when accessing
namespace instead of checking wheter namespace is initialized :D
2025-02-11 21:53:20 +02:00
088f77a226 Kernel: Add super basic support for USB keyboard LEDs
This is very hacky but it seems to mostly work. Also for some reason
this fixed my Razer Mamba mouse????
2025-02-11 02:18:50 +02:00
4dd6c85df2 Kernel: Fix USB keyboard Scroll lock
I was using 8 bit modifier and ScrollLock bit does not fit this. Also I
was not generating ScrollLock keypresses
2025-02-11 02:16:38 +02:00
d0452a3510 Kernel: Fix xHCI controller destruction
Port updater task was not actually able to exit without a kernel panic.
This patch makes controller wait until port updater exits itself :D
2025-02-10 22:58:57 +02:00
11310e7615 Kernel: Don't manually clear xHCI interrupt flag if using MSI 2025-02-10 22:58:14 +02:00
22b32a0fe5 Kernel: Expose PCI interrupt mechanism from PCIDevice 2025-02-10 22:57:25 +02:00
ad143c184f Kernel: Add basic support for USB hubs
This is still buggy and some hubs lead to usb transaction errors. I'll
have to debug this but this shouldn't prevent any already working device
from working
2025-02-10 22:56:25 +02:00
803a4cd163 Kernel: Don't enable ACPI devices when ACPI is disabled
This really didn't make any sense. There are no ACPI device to be
initialized when AML is not parsed :D
2025-02-07 21:35:25 +02:00
267fdf9fa1 Kernel: Remove storage devices after unplugging them 2025-02-07 18:04:54 +02:00
26d2a4420e Kernel: Don't limit xHCI TRB transfer length to max packet size
This made no sense and just used a ton of TRBs.

This patch also fixes some incorrectly set flags in data/status stage
TRBs.
2025-02-06 23:18:14 +02:00
c623ad7da0 Kernel: Use correct USB endpoint field to determine interval
I was using the wrong endpoint descriptor field which caused intervals
to be messed up.
2025-02-06 23:18:14 +02:00
7de689055c Kernel: Pass xHCI device information in structs
This makes code more readable and extendable
2025-02-06 23:18:14 +02:00
63b15a8855 Kernel: Rename USB initialize_endpoint -> configure_endpoint
This makes more sense as the USB command is CONFIGURE_ENDPOINT

Also configure_endpoint can be called multiple times on the same
endpoint. There was no reason to limit this to only one call.
2025-02-06 22:10:00 +02:00
a2a7302964 Kernel: Make sure USB class driver is deinitialized before xhci device 2025-02-06 22:00:26 +02:00
6a5367dbe3 Kernel: Don't initialize USB alternate interfaces 2025-02-06 21:43:15 +02:00
6768a18475 Kernel: Don't parse xHCI custom slot_types
xHCI spec mandates that slot_type for USB protocol is 0.
2025-02-06 21:41:44 +02:00
242ed4a3c2 Kernel: Remove support for custom xHCI speed_ids
This gets really weird with hubs and I don't think even linux handles
them.
2025-02-06 21:38:30 +02:00
f9b70d1b5b Kernel: Don't enter infinite loop on unexpected serial behaviour 2025-02-06 20:59:17 +02:00
faa5252191 Kernel: Fix TTY ANSI CSI m and prevent crash :) 2025-02-06 20:58:03 +02:00
4212f48d7a bootloader: Cleanup memcpy and memset
There isn't really any reason to do 32 bit moves
2025-02-06 20:56:35 +02:00
b30a79c7fe Kernel: Temporary hack to "fix" munmap
My current munmap implementation does not support partial unmaps and
GCC relies on this behaviour. This patch removes unmapping if the
address and len does not fully contain the mmap region.
2025-02-01 22:25:22 +02:00
22374ac8f7 ports: Add make port 2025-01-28 22:50:11 +02:00
17014bb8de LibC: Fix strndup
I did not null terminate short strndup copies :D
2025-01-28 22:40:06 +02:00
d1c3d3d5aa Kernel: Fix ANSI CSI L
With my new memcpy implementation this crashed. I have no idea how this
was not crashing before :D
2025-01-28 18:41:53 +02:00
7fedd94cc5 ln: Don't require link target to exist for symlinks 2025-01-28 17:46:36 +02:00
48eca3d031 LibC: Make libc usable with tcc
tcc does not provide its own stdint.h but defines everything in
stddef.h. Also tcc does not support [[noreturn]] attribute syntax.
2025-01-28 17:27:41 +02:00
21d3cf91a0 LibC: Implement some missing signal.h functions 2025-01-28 17:27:41 +02:00
5938cc4086 Kernel: Support pselect sigmask 2025-01-28 17:17:59 +02:00
7c57d736c6 Kernel/LibC: Fix dirent functions
dirent functions used to fail if a directory contained more than 128
files :D
2025-01-28 17:15:11 +02:00
cbe3f2a4ac BuildSystem: Cleanup and fix cmake files
I now set library SONAME so i don't have to build them in build root.

Creating font now makes sure the install directory exists. This allows
building using make files.

LibC now links agains ligcc
2025-01-28 17:11:21 +02:00
7a10e0e347 Kernel: Fix TmpFS inode linking
TmpFS now looks for empty entries in directories instead of always
appending files to the end of directories. This makes kernel not crash
after process pid 126 is created :D
2025-01-28 17:06:35 +02:00
efb577769e ports: Add nasm port 2025-01-25 23:10:04 +02:00
8c569ac7bf 2500th COMMIT: ports: Add gcc port
I've had this laying around locally for a while. binutils was not
working so I didn't feel like this was worth pushing. My new stdio FILE
buffering rewrite fixed binutils and now gcc actually works!
2025-01-25 18:40:16 +02:00
a84fb57e32 ports: Add binutils port 2025-01-25 18:40:16 +02:00
7314d2b577 ports: Add mpc port
This will be used by gcc
2025-01-25 18:40:16 +02:00
ba83ede0d1 ports: Add mpfr port
This will be used by gcc
2025-01-25 18:40:08 +02:00
42500ce043 ports: Add gmp port
This will be used by gcc
2025-01-25 18:40:04 +02:00
caa8c1da90 LibC: Add stub implementations for set{rlimit,priority} 2025-01-25 18:15:50 +02:00
cbcb9f9044 Kernel: Warn on unsupport clock_gettime clock_ids 2025-01-25 17:31:17 +02:00
60bffb5f49 LibC: Implement clock in terms of clock_gettime
This allows clock to "just work" after I update clock_gettime to support
CLOCK_PROCESS_CPUTIME_ID.
2025-01-24 19:58:44 +02:00
2a16a67aed Kernel: Ignore SA_RESTART flag on sigaction
This is a big hack but a lot of ports set this flag. This seems really
annoying to implement properly
2025-01-24 19:34:22 +02:00
c6cd185cb5 DynamicLoader: Fix copy relocations
Weak symbols are now actually resolved to the same strong symbol between
shared objects and copy relocations now work!
2025-01-24 19:23:33 +02:00
58cdcf754c ports: Update curl port
This patch updates curl to version 8.11.1 and adds support for dynamic
libraries
2025-01-24 19:23:33 +02:00
d969f5df7b ports: Add zstd port 2025-01-24 19:23:33 +02:00
b6455e0661 LibC: Implement stub for clock 2025-01-24 19:23:33 +02:00
15021b442c LibC: Fix memchr and memcmp assembly implementations
These functions did not work with size 0 :D
2025-01-23 21:55:26 +02:00
ee078fc638 Kernel: Fix fd status/descriptor flag handling
I was not sharing status and offset on fork and I was sharing descriptor
flags on dup/dup2
2025-01-17 20:12:04 +02:00
9893c90e74 Kernel: Remove SYS_DUP and implement it using fcntl F_DUPFD 2025-01-17 19:29:47 +02:00
82978da5e3 Kernel: Cleanup AML code 2025-01-17 16:20:00 +02:00
80ce9d546a Kernel: Don't error out on SYS_WAIT with W{CONTINUED,UNTRACED}
As I don't support stopping and continuing processes these flags are
effecively no-ops
2025-01-17 16:14:52 +02:00
34775633b2 Kernel: Clear DF on every interrupt handler
I was missing this and it lead to UB with my new mem* functions that
were implemented with `rep`
2025-01-17 16:11:13 +02:00
03b5c8e76e Kernel: Fix disk caching when readonly is specified 2025-01-16 16:16:38 +02:00
766b8cd62e LibC: Fix stdio FILE operations
Mixing read/write/ungetc was broken. This mostly fixes everything. There
might still be some problems that have to be fixed
2025-01-16 14:57:58 +02:00
609067cefa Kernel: Cleanup internal CPUID functions declarations 2025-01-14 22:57:44 +02:00
9d497ad311 Kernel: Cleanup interrupt stub definitions 2025-01-14 22:55:06 +02:00
72059a9441 LibC: Redefine SEEK_* macros to match common systems
some ports written in assembly seem to depend on this
2025-01-14 22:52:13 +02:00
ebecbb69ec LibC: Implement some mem* and str* functions in assembly
This made them a lot faster on modern cpus with optimized rep stos and
rep movs
2025-01-14 22:50:46 +02:00
b129bab81a Kernel: Make mem* and str* functions weak symbols 2025-01-14 19:08:03 +02:00
14c70c5cc8 LibC: Make mem* and str* functions weak symbols
This allows adding architecture dependent implementations while still
providing an general implementation
2025-01-14 18:36:54 +02:00
d62a67502e LibC: Remove global -fno-tree-loop-distribute-patterns flag
This is only really needed for string.cpp where mem* and str* functions
are defined
2025-01-14 18:35:33 +02:00
4b2c303873 LibC: Add weak_alias header that defines a weak_alias macro 2025-01-14 18:33:57 +02:00
d189f00f38 Kernel: Null terminate tmpfs directory entries 2025-01-12 16:03:09 +02:00
a5cf92b2ff Kernel: Use uint64_t instead of size_t for AML node conversion
This allows 32 bit to compile again :)
2024-12-30 06:27:49 +02:00
8c45249c06 LibC: Remove stdint.h as toolchain provides one
I have no idea why i even had this written, it was just containing
compiler macros
2024-12-30 06:26:17 +02:00
55c8a15983 aoc2024: Implement day25 solution
This was a nice AOC season. First time I fully completed it! I may still
optimize my solutions as some of them are a bit slow...
2024-12-25 18:13:57 +02:00
3607e2e759 aoc2024: Implement day24 solution
This is kinda weird and specific to my input but it works xD
2024-12-25 18:13:20 +02:00
d035068982 aoc2024: Implement day23 solution
I'm not proud of my implementation to last 2 days, but they work in a
reasonable time. I might optimize them later...

Problem is largely with my hash structures. Preallocating a lot of
elements before running day22 makes it run in less than half of the
current time.
2024-12-23 21:20:47 +02:00
af8156f310 aoc2024: Implement day22 solution 2024-12-23 01:47:27 +02:00
47b995a2a3 aoc2024: Implement day21 solution 2024-12-22 21:39:28 +02:00
6f8f99f42c Terminal: Set terminal size with TIOCSWINSZ when starting
This actually fixes the very broken vim port
2024-12-21 03:23:21 +02:00
69137cddab Kernel: Implement TIOCSWINSZ for pseudo terminals
I have no idea how I had forgotten this
2024-12-21 03:22:48 +02:00
9caa3030ea aoc2024: Implement day20 solution 2024-12-20 21:31:10 +02:00
3e9826acf5 aoc2024: Implement day19 solution 2024-12-19 12:57:28 +02:00
d7b4f54983 Kernel: Check Control Method Battery _STA bit 4
This bit indicates wheter the battery is actually present.
2024-12-19 02:35:09 +02:00
00b0dcd306 Kernel: Reorder ACPI initialization method calls 2024-12-19 02:35:09 +02:00
53c356a940 Kernel: Implement AML MatchOp 2024-12-18 19:26:19 +02:00
a7f3351c0e TaskBar: Prevent possible division by zero
If battery reports its full capacity as zero, battery percentage
calculation did a division by zero crashing the TaskBar :)
2024-12-18 18:36:26 +02:00
3a6cdfff45 Kernel: Fix ACPI namespace initialization
Now _REG, _STA, _INI are called in the order my laptop expects them to
be called. This was kinda weird because what uACPI was doing did not
work.

\_SB_.PCI0.LPC0.EC0_.BAT0._STA required \_SB_.PCI0.LPC0.EC0_._REG to be
called
\_SB_.PCI0.LPC0.EC0_._REG required \_SB_.PCI0._STA to be called

Now I call all the _REG methods of a device after calling _STA/_INI and
after performing the whole _STA/_INI sequence i call rest of missing
_REG functions
2024-12-18 18:30:45 +02:00
c26e347e91 Kernel: Fix AML FieldUnit conversion and NameString construction 2024-12-18 18:29:04 +02:00
1b94957b07 Kernel: Copy AML NameString base when moving it :) 2024-12-18 18:28:16 +02:00
2e39668605 aoc2024: Implement day18 solution 2024-12-18 14:06:32 +02:00
0642c569b4 TaskBar: Show battery percentage if available 2024-12-18 14:06:32 +02:00
4e364bd2f6 Kernel: Add support for ACPI Control Method Batteries
The implementation is kinda weird but it exposes some battery
information to userspace!
2024-12-18 14:06:32 +02:00
b9fe564d78 Kernel: Check for GCC when ignoring Wmaybe-uninitialized 2024-12-18 01:45:36 +02:00
437fa45ca2 Kernel: Add helper to find ACPI devices with EISA id 2024-12-18 01:45:00 +02:00
85e215650c Kernel: Implement AML ToStringOp 2024-12-18 01:44:33 +02:00
7eb186dad4 Kernel: Add to_sv() helper for AML String 2024-12-18 01:43:46 +02:00
2259614640 Kernel: Remove unused function from ACPI namespace 2024-12-18 01:43:04 +02:00
a584e1a4ec aoc2024: Implement day17 solution 2024-12-17 23:30:37 +02:00
869f4011a1 Kernel: Replace the old AML interpreter by a new, better one
The old AML interpreter was trash and did not follow value/reference
semantics at all. It was also super slow, one of my machines taking over
7 seconds to parse ACPI namespace and call _INI and _STA.
2024-12-17 03:36:33 +02:00
463bb72d24 aoc2024: Implement day16 solution 2024-12-16 17:23:08 +02:00
8b312a47e6 BAN: Allow MUST and TRY to contain commas 2024-12-16 17:22:40 +02:00
46d4e32510 Kenrel: Validate inode open mode on read/write syscalls 2024-12-15 20:49:12 +02:00
1815a913c3 Kernel: Remove unnecessary hash map lookups 2024-12-15 20:47:40 +02:00
a7e06715ba aoc2024: Implement day15 solution 2024-12-15 20:45:57 +02:00
a89fd95864 aoc2024: Implement day14 solution 2024-12-14 23:52:22 +02:00
9ba9469bb1 aoc2024: Optimize day12
There is actually no need for hash maps
2024-12-14 03:58:11 +02:00
4dbf173ed4 aoc2024: Implement day13 solution 2024-12-14 03:17:55 +02:00
8936cca9cf aoc2024: Implement day12 solution 2024-12-12 17:03:31 +02:00
1c704680a8 aoc2024: Implement day11 solution
Finally we got a problem where trivial solution does not work
2024-12-11 09:05:52 +02:00
3e36834751 aoc2024: Implement day10 solution 2024-12-10 17:26:39 +02:00
581caff638 BuildSystem: Install base sysroot only once
Base sysroot is not only installed when creating the syroot directory
for the first time. To get it installed again, you have to either delete
the old sysroot diretory or run clean target

This makes it so its actually possible to edit files specified in the
base sysroot without random hacks.
2024-12-10 16:44:59 +02:00
8b612ba547 aoc2024: Implement day9 solution
part2 is kinda unoptimized, it should not use expanded input, but I did
not feel like rewriting my parsing code :)
2024-12-09 16:20:21 +02:00
90820f24a4 BAN: Make HashMap::{insert,emplace}{,_or_assign} return an iterator
This reduces the number of lookups done into the hash map :)
2024-12-09 03:37:13 +02:00
12a37500b0 Kernel: Fix triple-fault in vitual tty
This was happening when printing non-utf8 data while having virtual tty
as the debug console.
2024-12-09 03:35:51 +02:00
3ae6ffdb01 ports/tcc: Create usr/include/sys/ucontext.h
This file does not have to contain anything, tcc just requires that it
exists.
2024-12-08 20:42:04 +02:00
c4e76b391e aoc2024: Implement day8 solution
I did not feel like optimizing this one, so its a O(n^2) looking over
every cell in the grid. Performs way faster than my optimized day6
solution tho :DD
2024-12-08 16:14:39 +02:00
cf9ba737f0 aoc2024: Implement day7 solution 2024-12-07 07:34:21 +02:00
2d0690ae2d Kernel: Cleanup most of syscalls dealing with files 2024-12-07 05:33:04 +02:00
71a2d0971f Kernel: Remove unnecessary reverse from VFS file search 2024-12-07 01:41:23 +02:00
3bf57e0748 Kernel: Add . and .. entries to /proc/<pid> directories
This allows to run `cd ..` in one of these directories
2024-12-07 01:37:40 +02:00
fbc0319cb6 aoc2024: Implement day6 solution 2024-12-07 01:08:08 +02:00
e8bc3c2d80 General: Add intructions to run doom to README 2024-12-06 20:25:09 +02:00
fe192e07fb General: Update README feature list 2024-12-05 19:49:38 +02:00
51b6329c86 Kernel: Make backspace \b and delete 0x7F
This is what `vim` seems to expect and imo makes way more sense.
2024-12-05 17:34:37 +02:00
72d9e4c1e7 Kernel: Remove accidental debug prints from fcntl syscall 2024-12-05 17:34:32 +02:00
cb7d5c9d09 userspace: Implement dirname utility 2024-12-05 08:30:30 +02:00
097ab82529 userspace: Implement basename utility 2024-12-05 08:30:06 +02:00
ccb603d77f aoc2024: Implement day5 solution 2024-12-05 08:16:34 +02:00
d7b02db832 aoc2024: Implement day4 solution 2024-12-05 08:16:12 +02:00
56cc5da9fb userspace: Implement ln utility 2024-12-05 08:14:45 +02:00
1903079f96 LibC: Fix popen to return correct return value instead of -1 2024-12-05 06:47:10 +02:00
b6d0950ee9 LibC: Fix strftime implementation
This implementation now passes every musl-libc test :)
2024-12-05 06:46:31 +02:00
c1a32a4041 LibC: Implement mktime 2024-12-05 06:43:35 +02:00
8fa443879c ports: Add working tcc port!
You can actually now compile programs within banan-os!!
2024-12-04 21:23:09 +02:00
3a465cb94f DynamicLoader: Don't write to pltgot if it does not exist
This makes `tcc` compile runnable executables
2024-12-04 21:11:43 +02:00
49133dce48 Kernel: Make pipe check data every 100ms
This prevents dead lock if read-end does not detect data before blocking
why write-end already notified.
2024-12-03 21:54:27 +02:00
3b7b6beca5 ports: Allow using banan-os cmake toolchain file for ports 2024-12-03 20:29:38 +02:00
0dd81328ff ports: Unconditionally compile banan-os before building ports
This allows ports to use any banan-os library cleanly. Ninja is fast on
when everything is already compiled, so it doesn't add too much
overhead.
2024-12-03 20:29:38 +02:00
a668593e6b ports: Don't update ports on every build
This makes using ports much less painful :)
2024-12-03 20:29:38 +02:00
3a5a22511a aoc2024: Implement day3 solution 2024-12-03 20:29:38 +02:00
86859267f0 ports/curl: remove libcurl.la file and use /dev/urandom 2024-12-03 20:29:38 +02:00
88c9f6d233 LibC: Make environ a weak alias
If user program defines its own global `environ` variable it will still
work :)
2024-12-03 20:29:38 +02:00
176693dd5a LibC: Implement wcscmp and wcsncmp 2024-12-03 16:21:54 +02:00
62bee04fc0 LibC: Implement dummy utime that just checks file existance 2024-12-03 16:21:18 +02:00
0a5aacfd87 Kernel: Allow open with O_CREAT bypass file permission checks
call to open(path, O_CREAT|O_EXCL|O_RDWR, 0444) should open file as
read-write although file is created as read-only on filesystem.
2024-12-03 16:17:34 +02:00
2dec3a6c95 Kernel: Add some sanity checks for existanse of threads 2024-12-03 16:16:50 +02:00
fcc2814199 Kernel: Remove process from alarm list after it dies 2024-12-03 16:16:08 +02:00
bc93d238dd LibC: Fix fread argument order in gethostname 2024-12-03 16:15:16 +02:00
79e2c5d48c LibC: Make FILE* reading buffered
There was no reason to perform a syscall for every byte read
2024-12-03 16:13:48 +02:00
0fab7ad63b Kernel: Fix SYS_FCNTL command handling :)
I had misunderstood how these work
2024-12-03 16:12:26 +02:00
e6a2f55a59 Kernel: Closing file backed mmap wont expand the file size 2024-12-03 16:12:26 +02:00
67e9ca56ac Kernel: Create /dev/urandom -> /dev/random symlink
Most software uses urandom instead of random so this allows it work
normally.
2024-12-03 16:12:26 +02:00
713daf6cd3 Kernel/LibC: Add support for creating hardlinks 2024-12-03 16:12:26 +02:00
12abe81c6d ports/openssl: Add support for shared libraries 2024-12-03 01:46:59 +02:00
fbcf10c86d LibC: Implement closelog and make syslog print to stddbg 2024-12-03 01:45:54 +02:00
415b20f884 LibC: Remove errno EEXISTS
I don't know why I had added this. It doesn't seem to be a thing on
either POSIX or linux. This was literally equivalent to EXIST
2024-12-02 20:13:38 +02:00
d58ca5f37a Kernel/LibC: Implement symlink{,at} 2024-12-02 20:13:38 +02:00
11b6ee423e LibC: Define timezone structure 2024-12-02 20:13:37 +02:00
a10ca47657 Kernel/LibC: Implement {,f}statvfs 2024-12-02 20:13:37 +02:00
ad1f175a39 Kernel/LibC: Implement getppid 2024-12-02 20:13:37 +02:00
fd3246113a LibC: Implement missing execlp and cleanup exec code 2024-12-02 20:13:37 +02:00
b8013c883c LibC: Implement getpass 2024-12-02 20:13:37 +02:00
ffcc4fd03a init: Make tty owned by logged in user 2024-12-02 20:13:37 +02:00
9d97964998 LibC: Fix getpwend gid field :) 2024-12-02 20:13:37 +02:00
f0e54cdd51 LibC: Implement {asctime,ctime,gmtime,localtime}_r
Old non _r prefixed functions are now just wrappers around these new
functions :)
2024-12-02 20:13:37 +02:00
0360fd1efe LibC: Implement mk{,d,s}temp 2024-12-02 20:13:37 +02:00
4508e099ff LibC: Implement getpagesize 2024-12-02 20:13:37 +02:00
6ed1435aeb Kernel/LibC: Implement tcgetpgrp 2024-12-02 20:13:37 +02:00
6346e288ad LibC: Implement getrlimit 2024-12-02 20:13:37 +02:00
d2b503910f userspace: fix aoc2023 and aoc2024 linking
This patch makes aoc projects not link against system libc but the cmake
libc target. This allows compilation before libc is installed
2024-12-02 20:13:37 +02:00
747c3b2a4b Kernel/LibC: Implement fsync 2024-12-02 20:13:37 +02:00
cccb4e6d5e LibC: Implement basename and dirname 2024-12-02 20:13:37 +02:00
f4c6afbdae LibC: Add definitions to LibC that are used by some ports 2024-12-02 20:13:37 +02:00
d1ef380e6b LibC: Add missing definitions for ifreq members 2024-12-02 20:13:37 +02:00
c02de2580d Kernel: Add support for SIOCGIFNAME ioctl 2024-12-02 20:13:37 +02:00
a231f8587e aoc2024: Implement day2 solution 2024-12-02 20:13:37 +02:00
4149748766 Kernel: Add missing include in ACPI headers 2024-12-01 21:32:34 +02:00
783627c315 LibC: Fix time.h sigevent defition 2024-12-01 21:31:27 +02:00
1ff6aa1748 aoc2024: cleanup day1 solution 2024-12-01 07:58:40 +02:00
6662dc4a8d aoc2024: fix full runner search path for solutions 2024-12-01 07:58:40 +02:00
d6b170e274 aoc2024: implement day1 solution 2024-12-01 07:41:25 +02:00
11cac7a646 aoc2024: prepare programming environment 2024-12-01 07:41:25 +02:00
9c2fcd745c ports/doom: Fix patch calling exit() to actually do what it says 2024-12-01 02:28:50 +02:00
04f49a6819 LibC: Implement {,v}dprintf 2024-11-27 21:33:10 +02:00
d465ea2a67 LibC: Fix headers :) 2024-11-27 21:32:10 +02:00
1f5073d0ac ports/doom: Allow doomgeneric to write directly to window framebuffer
This prevents an unnecessary `malloc` of the framebuffer and a copy
every frame.
2024-11-27 13:39:21 +02:00
8dbbbc1a1a Kernel: Add command line option readonly
This prevents calls to write_sectors_impl and all dirty pages are always
kept in RAM.
2024-11-27 13:31:55 +02:00
f985673dc3 LibGUI: Add API to retrieve Window's underlying framebuffer 2024-11-27 13:29:42 +02:00
a6fc3cf7a6 Kernel: Clear AHCI pending interrupts
I have no idea why I did not have this in. All devices were just
constatly spamming interrupts like crazy :D
2024-11-26 01:39:11 +02:00
1941885cfd Kernel: Disable USB Mass Storage writing until I get it fixed
This prevented real hw from running for over 10-20 seconds. When first
disk sync happens after 10 secods, USB storage would enter faulty state
and not allow any io operations.

I have no idea what the problem is. If I don't send Reset command to the
USB device writing seems to work fine. I also don't think its part of
the Reset process either as reading works just fine.
2024-11-26 01:01:25 +02:00
88a86a9927 Kernel: Fix Thread destruction after sys_exit
This had undefined behaviour as Thread's (Processes's) PageTable was
destroyed before Thread had the change to destroy its own stacks that
lived on the PageTable.
2024-11-26 00:59:34 +02:00
48e030bca3 Kernel: Make PageTable non-copyable and non-movable
Also PageTable destructor now verifies that is has allocated something
instead of assuming paddr of 0.
2024-11-26 00:58:35 +02:00
6f118c1be1 BAN: Make HashMap key move constructible
This allows using non-copyable types as keys
2024-11-26 00:57:11 +02:00
7316eb87b8 BAN: Add requires expression for BAN::Formatter
This allows seeing syntax errors before compilation :)
2024-11-26 00:55:58 +02:00
5376236ab6 BAN: Make ErrorOr non-copyable
This makes avoiding accidentals copies easier :)
2024-11-26 00:55:12 +02:00
0af80d48ee BAN: Mark ByteSpan::slice as [[nodiscard]] 2024-11-26 00:54:35 +02:00
793c0368f2 Kernel: Refactor USB mass storage code
Also increment command timeout to 10 seconds so commands don't timeout
when they are not supposted to :)
2024-11-23 01:24:32 +02:00
076001462e Kernel: Implement AML ConcatOp 2024-11-22 22:23:07 +02:00
d2e1d8ec13 Kernel: Implement AML NotOp 2024-11-22 22:22:44 +02:00
30ceaa6bef Kernel: Implement AML ToHexStringOp 2024-11-22 22:22:27 +02:00
0247d47a3d Kernel: Make USBMassStorage send_scsi_command templated
This allows passing ConstByteSpan when data will not be modified
2024-11-22 22:21:19 +02:00
480368c878 Kernel: Cleanup and fix xHCI interrupt handling
Always clear EventHandlerBusy bit and remove unnecessary nesting
2024-11-22 22:19:53 +02:00
c1d8790623 Kernel: Don't allow sending commands to halted xHCI 2024-11-22 22:19:29 +02:00
fb1ffec5bb Kernel: Remove unused mutex from xHCI
This was preventing multiple xHCI controllers to do parallel device
initialization
2024-11-22 22:18:38 +02:00
1bdabe693f Kernel: Preserve RsvdP bits in xHCI controller initialization 2024-11-22 22:18:09 +02:00
ce09f35275 Kernel: Fix PCI 64 bit MSI msg_data offset 2024-11-22 22:17:25 +02:00
40c13043b3 Kernel: Add support for scratchpad buffers in xHCI 2024-11-22 22:16:57 +02:00
e620068416 Kernel: Allow USB devices to handle STALL conditions 2024-11-22 22:15:22 +02:00
8e624ca85a Kernel: Don't panic if uninitialized AHCI device gets an interrupt 2024-11-21 20:41:13 +02:00
c7afd46016 Kernel: Don't log spurious interrupts
Some PCs seem to be spamming a lot of int 7
2024-11-21 20:40:29 +02:00
3573656244 Kernel: Make PARTUUID matching case insensitive
Case sensitivity made it super annoying to work with :)
2024-11-21 20:39:27 +02:00
1de6de975a Kernel: Rename cmdline UUID= to PARTUUID=
This makes more sense and behaves more like existing software.
2024-11-21 20:38:50 +02:00
15c55b8c7d BuildSystem: Don't hardcode partition UUID
That was dumb :D I can just read the UUID parted assigned...
2024-11-21 20:37:42 +02:00
865061b492 Kernel: Temporary fix to make tmpfs more stable
whole TmpFS will have to be rewritten at some point :)
2024-11-21 18:13:26 +02:00
39313e1737 BuildSystem: Add option to boot using IDE or USB drives 2024-11-21 18:09:35 +02:00
70880636f4 Kernel: Implement basic USB Mass Storage support
I finally decided to do this :D
2024-11-21 18:08:37 +02:00
96a5ba0ed3 BuildSystem: Make root partition UUID fixed
This allows specifying root as UUID which makes booting nicer experience
on real hardware
2024-11-21 17:59:38 +02:00
8054f6c618 Kernel: Wait 10 seconds to find root device
If root device is initialized asynchronously it may not be ready when
main initialization thread is finished. This patch adds searching for
root device every 500 ms for 10 seconds.
2024-11-21 17:56:58 +02:00
658ea68d04 Kernel: Check max packet size for all USB devices
Spec says that this has to be done. Most cases can be probably skipped
as I used to do, but this is less error prone and adds practically no
overhead
2024-11-21 13:46:42 +02:00
5750f87396 Kernel: Fix unaligned access in xHCI controller initialization 2024-11-21 13:46:09 +02:00
1253e2a458 Kernel: Add support for bulk endpoints and update endpoint API
USB device now sets its own data buffers for IN/OUT endpoints. This
allows more customization and parallelism as data buffer does not have
to be shared.
2024-11-21 13:44:21 +02:00
857b3e92f8 Kernel: Support initializing USB 3 devices 2024-11-21 13:40:16 +02:00
8bf14d542e Kernel: Move SCSI device rdev allocation out of ATA code 2024-11-21 13:36:59 +02:00
31d2a39540 BAN: Add default constructors for BAN::{Little,Big}Endian 2024-11-21 13:34:12 +02:00
97718b4046 Kernel: Don't launch init process twice
I had accidentrally left the old init process launch in when replacing
it with the new one.
2024-11-19 20:43:38 +02:00
c07fd265f0 Kernel: Add support for ATA CHS addressing and cleanup code
I thought that I had an PC without LBA support so I implement support
for CHS. Turns out that my ATA device detection was broken and was no
device on that port and initialize data was just garbage.

Now that I added CHS, I guess I should just keep it in :)

Both ATA read and write are now combined into a single function to avoid
code duplication.
2024-11-19 20:39:32 +02:00
1de50a2a94 Kernel: Improve ATA device initialization
This does better detection of empty ports and fixes floating bus
read-value from 0x00 to 0xFF.
2024-11-19 00:25:42 +02:00
627ca432cc Kernel: Make PS/2 controller not hang if device keeps sending resend 2024-11-19 00:18:48 +02:00
f8ef11b4d2 BAN: Make PlacementNew.h only include <new> if it exists
Otherwise it will define the functions itself. This allows compiling
toolchain as stdlibc++ depends on BAN.
2024-11-19 00:16:44 +02:00
71563034a7 Kernel: Remove accidentally left debug prints 2024-11-18 03:45:07 +02:00
aaff5a65e1 Kernel/init: /dev/tty is now custom symlink to controlling terminal
kernel now passes the name of default console to init process so init
knows which file to open as stdio. before /dev/tty was referencing the
system wide current terminal which was inherited from cmdline. This
doesn't work anymore as we have pseudo terminals implemented that can
chage the current terminal during runtime :D
2024-11-17 22:38:52 +02:00
458a362f98 Kernel: Allow kernel to pass arguments to init process 2024-11-17 22:38:02 +02:00
36d07065fb WindowServer: Optimize msync calls to synchronize less bytes
This *probably* makes framebuffer much faster :D Window server does not
have to do page aligned and page sized syncs which used way too many
pixels.
2024-11-17 20:15:28 +02:00
f206e72447 Kernel: Don't require msync addresses to be page aligned
Inodes implementing msync can require page aligned addresses, but are
also allowed to not :) This reduces sizes of framebuffer msyncs!
2024-11-17 20:15:28 +02:00
58e45fb394 Kernel: Print process name on exceptions if it is available 2024-11-17 20:15:28 +02:00
411f32c766 WindowServer: Make select timeout more precise to hit target FPS
Previously window server was only running at around 40 FPS while
targetting 60. This makes the select timeout properly sleep so that
target FPS is reached!
2024-11-17 20:15:28 +02:00
e1b82e4e43 WindowServer: Don't allow focusing unfocusable windows after closing 2024-11-17 20:15:28 +02:00
df613775b6 WindowServer: Alpha blend background image in fullscreen mode 2024-11-17 20:15:28 +02:00
5e8fdc997a Kernel: Prevent userspace from overwriting CPU load memory 2024-11-17 20:15:28 +02:00
51bfe4252d ports/doom: download doom1.wad to common directory between archs 2024-11-15 20:50:40 +02:00
c96aee5740 WindowServer: Make mod+f toggle focused window fullscreen state 2024-11-15 20:45:56 +02:00
1c08849667 WindowServer: Draw cursor in fullscreen mode 2024-11-15 20:45:01 +02:00
73349e5e75 WindowServer: don't set window location to (0,0) when fullscreening 2024-11-15 20:43:41 +02:00
74ae411b69 WindowServer: Skip invalidation on other windows in fullscreen mode 2024-11-15 20:42:07 +02:00
d458592fb1 WindowServer: Don't focus unfocusable windows on window creation 2024-11-15 20:41:42 +02:00
627c89a62d LibGUI: Actually set window attributes when creating a window 2024-11-14 23:33:12 +02:00
0228cd4f31 Kernel: Increase userspace stack size and decrease kernel stack
Quake II needs a lot of stack, it was overflowing my 256 KiB stack so
this patch doubles that, so Quake II can run!

Also every thread had 256 KiB kernel stack. This is unnecessarily large
and now dropped to 32 KiB.
2024-11-14 21:03:04 +02:00
a859558840 LibGUI: Window Creation takes attributes as an argument
This reduces windows showing/moving once they are opened and setting
their attributes.
2024-11-14 20:57:34 +02:00
04eee2ea75 ports: Add quake2 port (+two years of banan-os!)
This patch adds software rendered quake2 port. I was supposted to push
this as two days ago as two years of banan-os, but I was too sick to do
any programming.
2024-11-14 12:47:30 +02:00
bda2c663da WindowServer: Implement fullscreen windows
If window size does not match framebuffer size, window data will be
scaled to framebuffer using nearest sampling for best performance.
2024-11-13 19:10:15 +02:00
5e041e6e5a WindowServer: Make all terminating signals exit cleanly
This allows window server to restore input handling to TTY if window
server crashes on page fault or some other unexpected exception.
2024-11-13 17:32:13 +02:00
d19264eea8 WindowServer: Implement partial window resizing
This patch adds support for client side resizing, so clients can request
the server to resize their windows. WindowServer will respond with
resize event when and if the resizing is complete.
2024-11-13 17:30:12 +02:00
64c52012df Kernel: Fix MemoryRegion overlap comparison
This made some calls to `munmap` unmap extra regions.
2024-11-13 17:26:42 +02:00
7542e55cb2 LibC: Add option to debug userspace malloc family calls 2024-11-10 14:03:25 +02:00
6bd51ac345 LibGUI: Client window now exits if it loses connection from server
This can be prevented by installing callback for socket errors.
2024-11-10 14:02:23 +02:00
cf21eb4b39 TaskBar: Cleanup TaskBar string generation 2024-11-08 02:57:35 +02:00
da8170c5b6 LibGUI: Add support for focusable windows and mouse capturing
These are essential parts of a window server! This allows making TaskBar
non-focusable.
2024-11-08 02:55:10 +02:00
12bc7480e0 LibC: Implement _Exit
This just calls _exit as POSIX says they can be equivalent
2024-11-08 02:52:12 +02:00
92862fdf39 LibC: Implement nan{,f,l} as functions
One port was using function pointers to these functions so macros don't
work.
2024-11-08 02:49:21 +02:00
4417268ecc BAN: only include <new> in PlacementNew.h
I was getting annoying multiple definitions for placement new and my
build system requires that c++ libraries are compiled. I guess this is
the easiest and cleanest solution
2024-11-08 02:48:07 +02:00
346853ee55 BAN: Implement sincos to math
This function calculates both sin and cos fast (hopefully)
2024-11-04 17:42:01 +02:00
a82f00cb70 BAN: Fix HashMap::{insert,emplace}_or_assign to actually assing value
I seemed to completely forgotten to do the assignment itself :D
2024-11-04 15:42:04 +02:00
1838ea5c30 Kernel: Fix pseudo terminal leaks 2024-11-04 15:35:07 +02:00
a356d90445 LibC: Fix libc compilation for 32 bit target 2024-11-04 10:51:31 +02:00
a3f41fd4d9 Kernel: Cleanup disk cache
Add missing include and cleanup code calling automatic disk sync.
2024-11-03 20:28:15 +02:00
f4be37700f Kernel/userspace: rework floating point math
SSE is now unconditionally enabled any where and most of math.h is now
actually implemented. using __builtin_<func> lead to many hangs where
the builtin function would just call itself.
2024-11-03 20:28:15 +02:00
ed19bb11fe Kernel: Cleanup thread default sse initialization 2024-11-03 20:22:28 +02:00
07275ecb5f BAN: Implement floating point constants in Numbers.h 2024-11-03 20:19:45 +02:00
2464fccadd LibC: Fix *scanf consuming extra characters 2024-10-19 12:43:23 +03:00
5fde2cf91a TaskBar: Ignore window close events and exit on connection close
This prevents user from killing the task bar with keyboard shortcuts
2024-10-18 17:19:05 +03:00
d57e797147 WindowServer: Don't kill window on key event, instead send close event
This allows notifying the client about window close and let client
handle it as it wants
2024-10-18 17:17:58 +03:00
988f7b0561 ports: Fix doom port to use the new GUI events 2024-10-18 03:45:15 +03:00
e99a271465 Userspace: Implement basic task bar
This bar only shows current time but its something to work on later!
2024-10-18 03:36:03 +03:00
d266c7f93b LibGUI: Implement attributes for windows
Windows can now change whether they have title bar, rounded corners,
alpha channel and whether they are movable. Also windows can also change
their own position
2024-10-18 03:32:12 +03:00
d7e5c56e94 userspace: Use SOCK_STREAM instead of SOCK_SEQPACKET for WindowServer
This makes more sense if we have longer packages
2024-10-17 01:44:48 +03:00
ddd3b4c093 BAN: Implement is_pod type traits 2024-10-17 01:35:42 +03:00
3a6fc4c197 BAN: Add proper error messages for MUST() in userspace 2024-10-17 01:32:55 +03:00
91381546d5 Shell: Don't crash if history file does not exist :D 2024-10-16 00:41:28 +03:00
41e2b898ab Shell: Implement history file for persistent history storage 2024-10-16 00:21:58 +03:00
6e981d1222 Shell: Add support for inline environment variables
e.g. `foo=$(echo lol) Shell -c 'echo $foo'` will now print lol!
2024-10-15 23:45:08 +03:00
8317bb13ca Shell: Cleanup code by defining argument types as nested types 2024-10-15 23:44:06 +03:00
c40f244dff Shell: remove env builtin and add type
other shells don't seem to implement as a builtin, so i won't either
2024-10-15 23:42:01 +03:00
a6aa048be0 userspace: Implement env as an executable 2024-10-15 23:42:01 +03:00
8fd0162393 Kernel: Rewrite x86_64 page tables to use HHDM instead of kmalloc
This allows page tables to not crash the kernel once kmalloc runs out of
its (limited) static memory.
2024-10-14 11:40:30 +03:00
f0b18da881 Kernel: Add kmalloc helper APIs 2024-10-14 11:39:04 +03:00
5f63ea8f8a Kernel: Add CPUID check for 1 GiB page support 2024-10-14 11:38:03 +03:00
2b43569927 Kernel: Use enums in boot info instead of magic values 2024-10-14 11:36:51 +03:00
4ba33175cf Kernel: Don't leak memory when preparing fast page
For some reason I was allocating memory for page table entry...
2024-10-14 11:34:48 +03:00
3edc1af560 Kernel: Don't map main bios area in page table initialization
This is only needed for RSDP lookup so it can be done with fast pages
2024-10-14 11:32:54 +03:00
55fbd09e45 Kernel: Rewrite physical memory allocation with PageTable::fast_pages 2024-10-14 11:32:54 +03:00
6a46a25f48 image: Add benchmark flag to measure performance of image operations 2024-10-13 22:05:13 +03:00
88b8ca5b29 LibC: Fix some string functions
I was not casting some required values to char or handling length of
zero
2024-10-13 22:04:08 +03:00
fdddb556ae LibC: Implement system() more properly
Old implementation did not ignore and block needed signals
2024-10-13 22:03:15 +03:00
d36b64e0c8 LibImage: name color to u32 function to to_argb from to_rgba
This is the actual format that it returns
2024-10-13 22:01:46 +03:00
8adc97980a Shell: rewrite the whole shell to use tokens instead of raw strings
tab completion is still running with raw strings and that has to be
fixed in the future.
2024-10-13 22:00:16 +03:00
dab6e5a60f BAN: Cleanup HashMap implementation and add {insert,emplace}_or_assign 2024-10-13 22:00:16 +03:00
0b05e9827b BAN: Use memmove instead of memcpy on overlapping data
I was accidentally using memcpy where memmove was needed
2024-10-13 22:00:16 +03:00
1c1a76d6d7 BAN: Member function pointers now use references instead of pointers
This seems cleaner as class pointer cannot be null anymore
2024-10-13 22:00:16 +03:00
df4f37d68d BAN: only define placement new operators for banan-os targets
This allows building and using BAN library outside of banan-os!
2024-10-10 21:55:25 +03:00
44629ba5dd BAN: Allow userspace to use string literals with BAN::Error 2024-10-10 21:54:52 +03:00
2da6776451 BAN: Update {Byte}Span API with better constness
const BAN::Span<int> is now allowed to modify its underlying data, but
the container itself is const.

BAN::Span<const int> can be used for spans over constant data.
2024-10-10 21:53:23 +03:00
a68f411024 BAN: Add requires clauses for Container::emplace{,_back} functions
This allows syntax highlighters to report errors!
2024-10-10 21:51:44 +03:00
166550fbba Kernel: Ext2 check if file exists before creating it 2024-10-07 18:21:05 +03:00
3e68981b0b userspace: Remove start-gui from shell builtins and make it an alias
This makes way more sense :D
2024-10-07 18:01:33 +03:00
6fd76e8d1e Shell: Rewrite alias parsing to allow chained commands
You can now have "chained" commands in alias
e.g. `alias foo='echo hello && ls`
2024-10-07 18:01:33 +03:00
dfcd15e7c4 Shell: Implement background processes with & 2024-10-07 18:01:33 +03:00
5fa359c28d ls: Print file name in quotes if it contains spaces 2024-10-07 18:01:32 +03:00
5bcfc9dd50 Shell: Always print prompt to new line
This is only done on non banan-os targets if terminal is detected to
support cursor position querying
2024-10-07 18:01:32 +03:00
f67cad326a Shell: Don't crash when there are no tab completions available :D 2024-10-07 14:26:07 +03:00
9775e83374 Shell: Fix tab space escaping in tab completion 2024-10-07 04:19:36 +03:00
264d1798dc Shell: Clenup code and fix some bugs
Don't list tab completion multiple times, allow `clear` to work even
when ANSI CSI 3K is not supported, reset buffer index when cancelling
command with ctrl+c
2024-10-07 04:10:25 +03:00
1824988b9a Shell: Add support for simple aliases
Aliases do not support chained commands with pipes, &&, ... but this is
a good start.
2024-10-07 04:09:38 +03:00
c54d9b3f60 Shell: Implement simple tab completion for commands and files 2024-10-07 01:44:44 +03:00
f432d3fcf8 BAN: Cleanup Optional casting for value getters 2024-10-07 01:44:44 +03:00
4f7828bab9 Shell: Allow escaping spaces in commands 2024-10-07 01:44:44 +03:00
ae073a336d Shell: Move builtin commands to a hash map
This allows accessing builtin commands outside of `execute_builtin`
2024-10-07 01:44:44 +03:00
6f90974896 BAN: Fix StringView::starts_with
I have no idea what i had been thinking when writing this code :D
2024-10-06 06:23:25 +03:00
4f3c05851c Shell: Expand ~ to home if its at the start of non quoted argument 2024-10-06 01:38:43 +03:00
4b13055125 Shell: Make builtin exit command read exit value from argument
Shell used to unconditionally return with exit code of 0
2024-10-06 01:24:34 +03:00
d542cd811d Shell: Add support for &&, || and ; 2024-10-06 01:24:24 +03:00
f75cebac7e Shell: Mark all functions as static 2024-10-05 19:11:58 +03:00
e302b6b635 Shell: Use sigaction instead of signal
This allows ctrl-c to work on linux :D
2024-10-05 19:07:59 +03:00
f709e88994 Shell: Cleanup argument handling and exiting 2024-10-04 17:54:01 +03:00
ab9a6d583b Userspace: Set SHELL environment variable in init instead of shell 2024-10-04 17:24:37 +03:00
26d6bf338e Shell: Ignore SIGTTOU and set pgroup from parent instead of child
This allows using the shell in linux!
2024-10-04 17:23:31 +03:00
b6e040dfc2 Kernel/Shell: Fix backspace and delete key byte sequences 2024-10-04 04:14:47 +03:00
f5802ca3e5 General: Update screenshot in README 2024-09-30 18:28:16 +03:00
7223e581a2 WindowServer: Fix 32 bit compilation with -Werror
There was a always false statement on 32 bit that the compliler was
warning about.
2024-09-27 15:33:25 +03:00
2d11ce9669 Kernel: Fix interrupt system
I had not understood how MSIs work and I was unnecessarily routing them
through IOAPIC. This is not necessary and should not be done :D

Also MSIs were reserving interrupts that IOAPIC was capable of
generating. Now IOAPIC and MSIs use different set of interrupts so
IOAPIC can use more interrupts if needed.
2024-09-27 15:31:31 +03:00
e4982a1a5c LibC: Fix printf with alternate format and zero values 2024-09-26 15:25:16 +03:00
cea6dedccc Userspace: Compile programs and libraries with -Wall -Wextra -Werror 2024-09-26 15:20:07 +03:00
e6ed5a388d BuildSystem: Export compile commands for clangd 2024-09-26 15:14:54 +03:00
b89fc3fe87 Kernel: Implement ANSI SGR 7 to invert colors
This allows vim's visual selection to show up
2024-09-26 15:08:11 +03:00
57ae74f908 Terminal: Implement more ANSI escape handling
This patch adds L and M codes for inserting and deleting lines and SGR 7
for inverting colors
2024-09-26 15:07:08 +03:00
1a6804b4b4 Terminal: Make Terminal::handle_csi() return invalidated rectangle
When I updated Terminal to only do a single invalidation after all of
input text was printed, I forgot to change handle_csi
2024-09-26 15:05:11 +03:00
82e6a3582d LibGUI: cleanup Window::shift_vertical and add copy_horizontal_slice 2024-09-26 15:00:14 +03:00
11a4e4faa2 LibImage: Add Adam7 support for PNG decoder 2024-09-26 11:47:34 +03:00
50a3533322 LibInput: Add value for ESC in key_to_utf8_ansi
This allows exiting vim when using this function for key mappings :D
2024-09-24 18:08:34 +03:00
4e9f39384a LibC: Initialize libc only once
This was breaking stuff with dynamic loader initializing libc and main
executable reinitializing it later :D
2024-09-24 17:56:12 +03:00
39802b56c1 Kernel: Allow SYS_EXEC to fail at any point
This patch builds new executable image to another pml4 structure and
only after everything is validated will current context be replaced.
This allows exec to fail "late" where previously it would panic the
kernel or kill the process. This allows graceful handling of exec
failures in userspace!
2024-09-24 16:29:38 +03:00
ebb87ccdde Kernel: Add asserts for overflow checks with ms -> ns conversions 2024-09-24 16:28:44 +03:00
f0e55938c1 Kernel: Allow initial binding of threads to specific processor 2024-09-24 16:27:40 +03:00
348d04f7f5 Kernel: Implement static Process::kill()
This allows killing processes even when there does not exist a current
thread.
2024-09-24 13:16:43 +03:00
1b0086217c Terminal: Do scrolling in putchar if necessary
I overlooked that handling *newline* scrolls would be enough. You can
definitely scroll more if printing a lot of text which wraps to the next
line.
2024-09-23 15:00:47 +03:00
d395cf38b7 Kernel: Binding to port 0 will always find unused port 2024-09-22 17:30:01 +03:00
57aec2a733 Kernel: Validate pointer's when printing stack trace
There was an kernel panic if stack trace contained uncanonical
addresses.
2024-09-22 17:16:01 +03:00
ae89237453 Kernel: Disable warning when calling syscall
This warning is only generated when compiling with UBSAN and I don't see
how the value would even be uninitialzed.
2024-09-22 17:15:07 +03:00
60d5257678 Kenrel: Add __builtin_unreachable support for UBSAN 2024-09-22 17:14:36 +03:00
d59463d11b Kernel: Fix TTY reading one keyevent after disabling input handling 2024-09-22 17:13:10 +03:00
1280528e4e BuildSystem: Use -O2 for all libraries
I don't know why I had not specified optimization level for libraries.
Only LibImage was using explicit -O3. LibImage doesn't need O3 anymore
as O2 seems to be around the same speed.
2024-09-20 20:04:49 +03:00
23d6205659 Kernel: Move DEBUG_* macros to centralized Debug.h
This makes toggling debug info much easier
2024-09-20 11:00:07 +03:00
bc0acc6f44 Kernel: Validate network packet sizes before casting
This caused a lot of crashes on invalid packets :D
2024-09-20 10:46:59 +03:00
b8622f2b4b Kernel: Implement simple RTL8169 driver
This allows me to use internet when running banan-os on my hardware!
2024-09-19 22:58:03 +03:00
7f0c39fe91 Kernel: Don't crash the kernel if packet is smaller than ethernet hdr 2024-09-19 22:51:55 +03:00
a489be0e05 Kernel: Allow parallel LAPIC timer initialization with HPET
HPET supports reading LAPIC counter without locks, so it can be done in
parallel. This makes booting much faster. Previously initializing every
timer took 100 ms, so 16 CPUs took total of 1.6 seconds. This allows
doing it all in 100 ms.
2024-09-19 14:41:59 +03:00
8e08046519 Kernel: Add asserts about having locked TTY's write lock
This for some reason fixes booting on real hardware? :D
2024-09-18 00:56:48 +03:00
999eb53364 Kernel: Release debug lock if its locked during kernel panic
Also kernel panic now prints if it had lock
2024-09-18 00:56:02 +03:00
f7e549e412 Toolchain: Run strip after installing toolchain
This drops installed toolchain size to around fifth :D
2024-09-17 22:30:40 +03:00
fbb99de728 ls: Show symlink target with -l 2024-09-17 19:12:34 +03:00
0620ed3d4f Kernel: Fix file open permissions for some syscalls 2024-09-17 19:11:48 +03:00
b779b3cf2d Kernel: Move file finding code to a helper 2024-09-17 18:52:52 +03:00
a6b973003b WindowServer: chmod the correct file 2024-09-17 18:35:27 +03:00
e431e90b20 Kernel/LibC: Implement all chown family function with fchownat 2024-09-17 18:35:01 +03:00
4aa466b948 Kernel/LibC: Implement all chmod family functions using fchmodat 2024-09-17 17:19:26 +03:00
04ae53b6df Shell: Add back accidentally deleted cd and time builtins 2024-09-17 16:38:45 +03:00
3666525d24 Kernel/LibC: Implement readlink in terms of readlinkat 2024-09-17 16:38:15 +03:00
f1a4bbce53 Kernel/LibC: Implement all stat family functions with fstatat
This patch gets rid of 2 unnecessary syscalls!
2024-09-17 16:38:01 +03:00
708a720d9d Kernel: Remove SYS_OPEN
This can be done with SYS_OPENAT with fd set to AT_FDCWD
2024-09-17 16:16:47 +03:00
7177da7d62 LibC: Implement dummy get_rusage
One port seems to use this function. This dummy just reports no used CPU
time for current process nor children
2024-09-17 15:59:22 +03:00
5e4aa75e03 Kernel: Perform access checks when creating a file or a directory
Also SYS_CREATE_DIR now uses correct relative path. It used to always
create files relative to root. And as no permission checks were tested,
file creation succeeded to root as long as path did not contain '/' :D
2024-09-17 15:57:07 +03:00
d88ee5c9ee Kernel/LibC: Implement creat with open
This allows getting rid of unnecessary SYS_CREATE. Directory creation
still has its own syscall, but I could combine it with SYS_OPEN also.
2024-09-17 15:55:53 +03:00
d4ea720239 Kernel: Don't crash the kernel if ext2 encounters disk error
This will most likely result in a corrupted filesystem, but crashing the
kernel is too much :D
2024-09-17 15:54:33 +03:00
97ee370ffe Kernel: Allow listing files even if one of directories blocks are empty 2024-09-17 15:53:14 +03:00
a084f83f4c Kernel: Rework kernel-side ELF loading
ELFs are now loaded as MemoryRegions so they don't need special handling
anywhere. This also allows file backed COW optimizations to work. This
was not the case before.

This patch removes now obsolete LoadableELF and unused ELF files from
LibElf.
2024-09-15 23:57:34 +03:00
54732edff4 Kernel: Fix bugs in memory regions
MemoryRegion::initialize() required size to be page aligned, this is not
necessary.

MemoryBackedRegion::copy_data_to_region() required user-write
permissions for underlying data. This did not matter as memory backed
regions dont support COW memory, but it could lead to bugs later on.
2024-09-15 23:18:05 +03:00
1a24d1839f LibInput: KeyEvent to ansi string now handles delete key
This allows Terminal emulator to also handle delete key.

The value of `\0x7F` may be wrong as qemu's serial console seems to be
sending `\e[3~`
2024-09-15 03:13:21 +03:00
c3040a04a3 Terminal: Optimize printing a lot
Terminal used to run `yes` at around 400 lines per second

This patch pumps that to over 100'000 lines per second!

There are 2 optimizations done:
  1. only invalidate window once after rendering is done
  2. if printing more than `rows()` newlines skip prior data
2024-09-15 03:12:26 +03:00
7feb4c4ebd Kernel: VFS::file_from_absolute_path now used root_file() API 2024-09-15 02:38:25 +03:00
2911d1f018 Kernel: Cleanup and fix pseudo terminals 2024-09-15 02:38:07 +03:00
d68ad893f0 Kernel/Shell: Add support for delete key 2024-09-14 22:45:48 +03:00
4ca147699d Shell: use printf and putchar instead of fprintf and fputc 2024-09-14 22:37:09 +03:00
abed41b8fa Shell: Remove builtin tests
Test should be programs in /bin instead
2024-09-14 22:28:33 +03:00
2604a55f80 Shell: Make ctrl+c start a new command 2024-09-14 22:27:32 +03:00
39667de662 Kernel: Fix sizeof check for sys_tc{set,get}attr 2024-09-14 21:17:03 +03:00
8956835d95 Kernel: Make sys_.*at use VFS relative path finding 2024-09-14 21:15:58 +03:00
ea4ec2eafc Kernel: Make OpenFileDescrptor store VFS::File instead of inode+path 2024-09-14 20:10:21 +03:00
3a352078de Kernel: Make VirtualFileSystem::File non copyable 2024-09-14 20:09:28 +03:00
6060b39548 Kernel: Implement relative file searching in VFS 2024-09-14 19:44:20 +03:00
dce2436b2c BAN: Implement Vector::reverse() 2024-09-14 19:44:20 +03:00
2b52ea4c6f Kernel: Make Inode::can_access const 2024-09-14 19:39:41 +03:00
b41738b47b Kernel: Fix ACPI name formatting functions 2024-09-14 19:39:13 +03:00
57e76a65a4 Kernel: Null terminate ext2 directory entries
This fixes a weird bug with `ls /bin`
2024-09-12 23:55:34 +03:00
7f25ddc229 userspace: Add missing alpha channels 2024-09-12 20:53:45 +03:00
163961df4f ports/doom: Add alpha channel for framebuffer access 2024-09-12 20:16:17 +03:00
97da386ed6 WindowServer: Make focused window bounce by pressing F2
This was an awesome idea by [@Dcraftbg](https://github.com/Dcraftbg)
2024-09-12 20:09:23 +03:00
c706829a91 WindowServer: Make corner-radius a variable in config file! 2024-09-12 20:07:30 +03:00
6cd246a38e WindowServer: Add support for rounded corners and transparency 2024-09-12 19:35:44 +03:00
43e88c0ae0 Terminal: Add alpha channel to colors
This doesn't do anything yet, but will when I add transparency support
for WindowServer
2024-09-12 19:34:25 +03:00
bf01b935bd WindowServer: Start Terminal with Super+Enter
this allows doing something in GUI after Terminal is closed

also WindowServer is now stopped with Super+Shift+E
2024-09-11 22:18:08 +03:00
98c011e6a6 WindowServer: Open all fds as CLOEXEC
This will allow forking the window server cleanly :D
2024-09-11 22:17:31 +03:00
86dcb5c471 init: Don't leak pwent fd to child processes 2024-09-11 22:11:05 +03:00
467ac6c365 Kernel/LibC: Implement SOCK_CLOEXEC and SOCK_NONBLOCK
This removes the need for fcntl after creating a socket :)
2024-09-11 21:59:11 +03:00
c77ad5fb34 Kernel: Implement copy-on-write memory for file backed mmaps 2024-09-11 19:33:50 +03:00
4006a04817 DynamicLoader: Don't do file backed mapping over file bounds 2024-09-11 19:30:35 +03:00
4189a1c729 LibC: Make _init and _fini weak symbols
These seem to be missing sometimes when making shared executables
2024-09-11 14:39:07 +03:00
a07cbabcb3 LibC: Define function sizes for setjmp and longjmp
dynamic linking was complaining about these not existing
2024-09-10 16:21:20 +03:00
64a3893f6f Kernel: Add command line option to disable AML parsing
This can be handy if my broken AML parser crashes or hangs while parsing
AML :D
2024-09-10 16:20:24 +03:00
eabe759ebf Kernel: Don't require APs that are not started to start :D 2024-09-10 16:19:43 +03:00
a4838386e6 Kernel: Remove unnecessary branch from uncanonicalizing addresses 2024-09-10 16:19:16 +03:00
c65613901f Kernel: Fix AML aliases and package elements 2024-09-10 16:18:42 +03:00
19d16620a6 DynamicLoader: Don't do file backed mapping for filesz == 0 2024-09-05 14:50:05 +03:00
4e15b9cdfa Ports: Add explicit -libgcc-shared for ports on 32 bit 2024-09-05 14:49:23 +03:00
de35cec2e1 Kernel: Allow private file mappings past file end
This is just to make memory mapping ELF files easier :D
2024-09-05 14:48:42 +03:00
e8bcebfb8e DynamicLoader: Use file backed mmap when possible 2024-09-05 13:59:39 +03:00
2f241e1b61 Kernel: Implement FileBackedRegion::clone 2024-09-05 13:59:09 +03:00
6affef76b1 test-shared: Add more shared tests 2024-09-05 12:59:48 +03:00
32ba4d07e2 Userspace: Remove unnecessary mov instruction from crt0 2024-09-05 12:59:05 +03:00
ddaaf89c87 BuildSystem: Make default libc a shared library 2024-09-05 12:58:35 +03:00
9aed8dbe6b Toolchain: Build crtbeginS.o crtendS.o and shared libgcc 2024-09-05 12:58:21 +03:00
aa7e92b275 Userspace: Write a dynamic loader
This allows running executing dynamically linked executables!
2024-09-05 12:58:21 +03:00
f30947336a BuildSystem: Cleanup cmake files 2024-09-05 12:52:25 +03:00
0bb44d7b75 LibC: Fix errno to work with shared libraries 2024-09-04 21:16:04 +03:00
1138ec77ca Kernel: Fix MemoryBackedRegion cloning for non page aligned size 2024-09-04 21:14:26 +03:00
c4dadd27ac BAN: Fix refenrece -> reference typo 2024-09-03 16:39:21 +03:00
04c715d314 BuildSystem: Build all libraries in root build directory
I could not figure out how to use cmake's rpath to build libraries with
DT_NEEDED only containing the library name, not a relative path.
2024-09-02 21:31:08 +03:00
35743cc8e6 LibC: Compile both static and shared version of LibC
libc target is now set as an alias for libc-static
2024-09-02 21:28:02 +03:00
5f92807fdd userspace: Allow building without SSE
I had added changes that had broken compilation without sse support
2024-09-02 21:25:00 +03:00
700c3444f5 LibELF: Add more values and macros for interpreting fields 2024-09-02 20:40:38 +03:00
ddf1babfe1 Kernel: Cleanup constructor calls 2024-08-31 02:23:08 +03:00
2ae2ede0b2 LibELF: Add value definitions for DT_ 2024-08-30 15:35:01 +03:00
ef5af384e7 Kernel: Print userspace invalid pointer access address 2024-08-30 15:34:37 +03:00
a134d16070 Kernel: Fix MemoryRegion test for contains_fully 2024-08-30 15:33:58 +03:00
827eec6af0 Kernel: Make .rodata read-only and add -orphan-handling=error
I don't really know why .rodata was marked writable :D
2024-08-30 15:33:02 +03:00
8da2f12ba6 Kernel: Only load program headers of interpreter if its present
I was loading program headers of both executable and interpreter but
that is incorrect. The interpreter will itself load the program headers
of the executable.
2024-08-28 21:19:37 +03:00
50ab391133 test-globals: print something when calling main
This shows that constructors and destructors are called in correct order
2024-08-28 17:09:07 +03:00
991647bc8f Userspace: Add shared library test
I will use this while testing my dynamic loader
2024-08-28 17:08:37 +03:00
57300687ff LibC: Cleanup and fix missing LibC headers 2024-08-28 17:07:58 +03:00
d559339f5f LibC: Compile shared libc as well as static 2024-08-28 17:07:15 +03:00
2bf65ef512 Kernel: Invoke ELF interpreter instead if it is specified 2024-08-28 17:06:32 +03:00
d20752c318 Kernel: Make OpenFileDescritorSet::open take rvalue
This gets rid of some implicit allocations from copy constructors
2024-08-28 16:36:10 +03:00
5f66ef34dd Kernel: map userspace arguments after the entry point
This allows cleaner memory layout for processes that are not loaded to
default location
2024-08-27 22:46:08 +03:00
da0b4cd40e Kernel: Allow MAP_FIXED in mmap 2024-08-27 22:45:49 +03:00
68f9dc1f8a Toolchain: Add support for building shared libraries 2024-08-27 17:36:09 +03:00
5121d0d934 Kernel: Allow loading PIEs
This is initial work towards implementing dynamic loader and shared
library support.
2024-08-27 17:32:22 +03:00
2c520391eb Kernel/LibC: Add support for init_array and fini_array 2024-08-27 00:47:03 +03:00
7c4b9218f2 Kernel: VirtualTTY now resets ansi state before printing anything 2024-08-25 17:56:06 +03:00
72f8138ca1 Kernel: Disable scheduler load balancing until I get it fixed
Scheduler keeps crashing all the time when running on multiple cores.
This patch disabled the load balancer, which seems to get rid of most
scheduler crashes.
2024-08-25 15:37:17 +03:00
991ae4383a Kernel/LibC: Implement fchmod 2024-08-25 15:07:42 +03:00
2ce7205c80 Kernel: Add command line option to disable debug printing
The whole system can crash when debug output and tty output are done at
the same time. This patch is just a hack to prevent the crash :D
2024-08-25 15:02:15 +03:00
bec3e8654f Shell: Implement escaping quotes in quoted strings 2024-08-24 17:13:50 +03:00
14fdcb892d Ports: Make curl port use openssl
Curl now works with https!
2024-08-22 15:10:41 +03:00
d6d062841d Ports: Add openssl port 2024-08-22 15:10:41 +03:00
06d0985bba Ports: Add zlib port 2024-08-22 15:10:41 +03:00
9ea969be1f Ports: Add port that downloads and install cacert to system 2024-08-22 15:10:41 +03:00
500f774b7f LibC: Add a lot of stub implementations for different libc functions
some ports want to link against these, but they are not ever called
based on simple testing

This patch adds stubs for
- openlog
- syslog
- getrusage
- mlock
- mprotect
- getpeername
- shutdown
- tzset
- mktime
2024-08-22 15:10:41 +03:00
ca8832c0e1 LibC: Implement getaddrinfo and freeaddrinfo, add stub for getnameinfo 2024-08-22 15:10:41 +03:00
1cbba113fd LibC: Add and cleanup some networking structures and definitions 2024-08-22 15:10:41 +03:00
45b4b33a3d LibC: Add definitions for some integer sizes to limits.h 2024-08-22 15:10:41 +03:00
c453a8e2dc LibC: Implement poll() using select 2024-08-22 15:10:41 +03:00
e59772a58d General: Cleanup build scripts 2024-08-22 15:10:41 +03:00
fb35f06cf5 Kernel: Add better support for bootloaders loading the kernel
Before I assumed that bootloaders loaded the kernel at physical address
0, but this patch kinda allows loading to different addresses. This
still doesn't fully work as kernel bootstrap paging relies on kernel
being loaded at 0
2024-08-22 14:48:21 +03:00
abc788c756 Kernel: Improve output message when dumping all syscalls 2024-08-22 14:48:21 +03:00
63b616dc2e Kernel: Hack non-blocking support for sockets
This is not thread safe and can still block if two programs refering to
the same socket try to read data at the same time
2024-08-22 14:48:14 +03:00
72f3fe0b12 LibC: Add empty files sys/param.h and sys/file.h
For some reason some ports include these files even when they detect
that they are not available
2024-08-22 14:47:59 +03:00
cba12efeb1 Kernel: Ignore optional_actions in SYS_TCSETATTR
Currently all terminals are syncronous, so the actions don't do anything
2024-08-22 14:47:54 +03:00
37cd4ed504 Kernel: Add support for CSI @, b, d to VirtualTerminal 2024-08-22 14:04:45 +03:00
869bba4dad Kernel: Add check for panic in timer interrupt handler
Previously processors would not get notified about kernel panic if they
were idling
2024-08-22 14:03:03 +03:00
23194d1f53 Kernel: Implement basic random device to /dev/random 2024-08-22 14:02:26 +03:00
969563c06a Kernel: Don't load AP init code to 0xF000, but relocate it later
This cleans up the kernel executable as bootloaders don't have to
load AP init code straight to 0xF000, but it will be moved there once
kernel is doing the AP initialization.
2024-08-21 13:37:50 +03:00
066e8e1cc2 Kernel: Remove unnecessary debug logging from VFS initialization 2024-08-18 20:51:10 +03:00
5cd7b40165 Kernel: Make BananBootloader info struct header compatible with C 2024-08-18 20:51:10 +03:00
c7b134ba4b Kernel: Fix NVMe controller namespace numbering
namespace numbers were incrementing globally instead of per controller.
This led to two single namespace controllers creating nvme0n1 and
nvme1n2
2024-08-18 20:51:10 +03:00
ff62c262fe Kernel: Fix PS/2 scancode set 2 keycodes for the bottom row keys 2024-08-18 20:51:10 +03:00
42e2c15e0c Kernel: Add ps2=<scancode set> command line argument
This allows forcing specific scancode set on broken PS/2 emulations
2024-08-18 20:51:10 +03:00
40c6989374 Kernel: Implement AML ObjectTypeOp 2024-08-18 20:51:10 +03:00
71dc373610 Kernel: "Fix" AML _OSI string to return true for windows strings
This is the way its supposed to be done as other code paths are
untested...
2024-08-18 20:51:10 +03:00
0fa16cf982 Kernel: Fix and add some AML to_underlying functions 2024-08-18 20:44:51 +03:00
8902032b42 BuildSystem: Cleanup kernel cmake file 2024-08-18 20:44:12 +03:00
368f5e9799 Kernel: Add command lineoption nousb that will disable usb controller 2024-08-16 22:09:24 +03:00
46b34817d2 snake: Remove random goto statements when regenerating apple's position 2024-08-16 17:36:37 +03:00
b1fe24bb57 Kernel: Hack AML integers to work better
Something is trying to store into a constant integers. Just by copying
not returning any integers as constants fixes it xD
2024-08-16 13:04:52 +03:00
490a28ee7a Kernel/AML: General cleanup and compliance improvements 2024-08-15 23:14:13 +03:00
75884ca6b8 Kernel/AML: Allow calling method through named objects 2024-08-15 23:13:32 +03:00
d729d7f570 Kernel: Implement AML storing to Buffer 2024-08-15 23:12:52 +03:00
6408bb2efa Kernel: Add AML API for getting underlying value of nodes 2024-08-15 23:11:59 +03:00
d8dabab4fb Kernel: Implement AML CopyObjectOp 2024-08-15 20:55:55 +03:00
4dc107f77a Kernel: Fix AML Register/Reference accesses 2024-08-15 20:55:18 +03:00
eaf06d239c Kernel: Cleanup and fix AML Method calls 2024-08-15 20:54:55 +03:00
d9b3a4bf77 Kernel: Add more conversions for AML Integer, Register, String 2024-08-15 20:51:04 +03:00
cf970d5914 Kernel: Add better conversion for AML Alias, Name and Reference 2024-08-15 20:48:35 +03:00
1cfe3dd4da Kernel: Implement AML BreakOp and ContinueOp 2024-08-15 19:08:00 +03:00
51d1e47bfe Kernel: Fix AML CreateFieldOp to take bit index instead of byte index 2024-08-15 19:05:58 +03:00
e0a447bfaf Kernel: Add _GL to ACPI root namespace 2024-08-15 02:28:22 +03:00
3f5ee6f414 Kernel: Rewrite the AML conversion API
This doesn't currently make the interpreter any better, but it will make
further implementation easier to be spec (or hardware...) compliant
2024-08-15 02:25:45 +03:00
44d5c8c4b4 Kernel: Implement AML To{Buffer,Integer,String}Op 2024-08-14 20:28:32 +03:00
17b7e9e772 Kernel: Allow all named objects to fail cleanly if name exists 2024-08-14 20:28:00 +03:00
8a2a444f33 BAN: Make formatting functions inline 2024-08-14 20:26:55 +03:00
957df08932 Kernel: root command line option can be specified as an UUID
Format is the same as in linux
root=UUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX

This makes it easier to boot when computer has multiple disks installed
2024-08-14 13:23:27 +03:00
fd018b32d0 BAN: Implement GUID::to_string 2024-08-14 13:23:27 +03:00
e000c7d818 BAN: Use static_cast instead of C-style cast in RefPtr deletion 2024-08-14 13:23:27 +03:00
bb40069773 Kernel: Add nice debug prints for device addition/removal 2024-08-14 13:23:27 +03:00
37d5b60f5c Kernel: Implement AML {Event,Reset,Signal,Wait}Op 2024-08-14 11:59:34 +03:00
37e6cd6500 General: Update README contribution information 2024-08-14 10:34:41 +03:00
feadea0e91 Kernel: Fix AML unaligned integer reads and buffer shifts over 32 2024-08-13 23:44:17 +03:00
f71a29b6c4 Kernel: Implement AliasOp for AML interpreter 2024-08-13 22:42:37 +03:00
ec4cfdee23 Kernel: Fix and cleanup a lot of AML code
Node now have APIs to convert them to buffer, integer and string. This
allows possibility to handle methods that need explicitly use one of the
overloads instead of integer.

This patch also adds handling of DebugOp. This is used quite heavily in
uACPIs test suite.
2024-08-13 22:42:37 +03:00
dd79db6383 Kernel: AML implement CreateFieldOp 2024-08-13 18:52:48 +03:00
723e458bd7 Kernel/Terminal: Update terminal color themes and fix TTY bright/dark 2024-08-12 21:15:55 +03:00
25a47f0df3 LibC: Implement ungetc()
I didn't really test this, but I think this implementation does what it
needs to :)
2024-08-12 19:14:55 +03:00
39be57424c Kernel: Fix SYS_SEEK with SEEK_END
I was subtracting the offset from file end when I should have added it.
2024-08-12 19:13:27 +03:00
45ffa1b79c General: Update README feature list
README did not contain anything about GUI or USB which I have had for
maybe a month now :D
2024-08-12 15:14:04 +03:00
f37e1c2229 Kernel: Map .rodata as read only instead of read-write 2024-08-12 14:28:52 +03:00
1bd7b86e60 Terminal: Implement cursor blinking
This looks much nicer than the old static cursor
2024-08-12 14:24:17 +03:00
18e7cf2069 Terminal: Add cursor rendering
Cursor is now shown at the current position. It can be hidden (or shown)
with the ansi `\033[?25h` or `\033[?25l`
2024-08-12 00:50:06 +03:00
60b4d90608 LibGUI: Add Window::get_pixel()
This is fine as its not reading from video memory
2024-08-12 00:49:35 +03:00
5197000124 LibC: Fix qsort for types bigger than 64 bytes 2024-08-11 18:00:05 +03:00
71d4060993 Ports: Update port building instructions 2024-08-11 17:58:10 +03:00
34c6ad7277 Base: Add sample png image and make it the default GUI background 2024-08-11 01:16:23 +03:00
9e79ef2a91 Terminal: Use pseudo terminal instead of pipes
Terminal can now send signals from keyboard (ctrl+c) to programs running
in the terminal!
2024-08-11 01:02:59 +03:00
4d1b32f770 Kernel: open does not need TTY_INIT to set the controlling terminal 2024-08-11 01:02:59 +03:00
a5a097fa4a Kernel/LibC: Add initial pseudo terminal support
This patch implements posix_openpt() and ptsname()

grantpt() and unlockpt() are left in LibC as stubs, as posix_openpt
currently does all of the needed work.
2024-08-11 01:02:59 +03:00
ad645f31d0 Kernel/LibC: Add setsid() 2024-08-11 00:58:12 +03:00
f08d429851 Terminal: Add utf8 parsing for input
This patch adds possibility to render multibyte utf8 codepoints!
2024-08-11 00:54:51 +03:00
bac3219a01 Kernel: Fix Pipe::can_read_impl()
The logic was inversed, which made all select calls report incorrectly
for pipes. This made terminal emulator just freeze.
2024-08-10 18:18:25 +03:00
09a527fb12 Kernel: Fix scheduler thread counter
I was actually never incrementing the counter :D
2024-08-10 18:18:25 +03:00
58a3a480b9 Ports: Update the port system once again! 2024-08-10 18:18:25 +03:00
a12bfe4639 LibC: Don't crash when calling tcflush() 2024-08-09 17:03:21 +03:00
6cda639869 LibC: Add stubs for tmpfile, mktemp and fchmod 2024-08-09 17:02:49 +03:00
2797fe116f LibC: Add stubs for some functions in {dlfcn,ftw,utime,wchar}.h 2024-08-09 17:01:41 +03:00
e768cd53fb LibC: Add definition for SIGWINCH
This is actually not yet sent, but programs can install signal handlers
for it!
2024-08-09 17:00:13 +03:00
83e2ad40d6 LibC: Implement gai_strerror and add stubs for {get,free}addrinfo 2024-08-09 16:59:49 +03:00
7ebd0699e3 LibC: Add _PC* definitions to unistd.h
These are not used for anything yet
2024-08-09 16:58:58 +03:00
46b1d4d194 LibC: Remove cxx abi stuff from libc
These will cause multiple definitions when linking with libstdc++
2024-08-09 16:58:11 +03:00
f60e265397 LibC: Add ldexp to math.cpp 2024-08-09 16:57:16 +03:00
2e642327ea LibC: Implement localeconv() 2024-08-09 16:56:48 +03:00
a87ce41030 LibC: rename fd_set internal variable
binutils seems to need access to the internal type and uses this name
for lookup.
2024-08-09 16:55:52 +03:00
0c8cae4cc3 LibC: Move ioctl to <sys/ioctl.h>
Some ports seem to be assuming that ioctl exists there and not in
stropts.h
2024-08-09 16:54:30 +03:00
ed325b4a45 Kernel: Fix typo in userspace address validation 2024-08-09 16:52:57 +03:00
1c67b5e812 Kernel: Fix wait syscall to report status of exited children 2024-08-09 16:52:35 +03:00
b6c964c444 Kernel: Rewrite pipes
Pipes have now a fixed size buffer and pipe clone and close is working
again.
2024-08-09 16:50:19 +03:00
6fedf06150 LibC: Implement {sig,_,}{longjmp,setjmp} 2024-08-09 15:58:56 +03:00
91d513a672 2000th COMMIT: userspace: Implement basic fetch program bananfetch
This patch adds a obligatory fetch program to banan-os!

This program (`bananfetch`) fetches some basic information about the
operating system and the hardware its running on!
2024-08-09 15:58:56 +03:00
44f0ec601f Kernel: Expose /proc/meminfo and fix /proc/<pid>/meminfo
Thread was unconditionally calling <stack>->size() without validating
that the stack actually exists
2024-08-09 15:58:56 +03:00
2a659a9d03 BuildSystem: Fix enable sse definition
__enable_sse was never actually defined for any targets. This also adds
__arch definition for libc (so `utsname` works).
2024-08-09 15:52:42 +03:00
7e7c3a1bb3 Kernel: VirtualTTY now handles dark colors
I have seemingly forgot to add these before
2024-08-09 15:52:42 +03:00
3b23458ecc LibC: Start work on locales
This patch adds 2 locales, POSIX locale and UTF8 locale.

functions `mbstowcs()` and `strcoll()` use locales to do convertions and
comparison respectively.
2024-08-09 15:52:42 +03:00
7afdfb150f LibC: Rewrite sigprocmask in terms of pthread_sigmask
Also don't fail SYS_SIGPROCMASK if how is invalid and set is NULL.
2024-08-07 17:01:35 +03:00
2ca7886f88 Ports: remove architecture from .compile_hash files
This is was over complicating things and there can be only one banan-os
build at a given time.
2024-08-07 16:34:28 +03:00
5aca6c7c1f Ports: Fix bugs in the port system
Fix some bugs and add pkg-config for the port system. Also ncurses is
now downloaded from the gnu mirror in the hope that it works better
2024-08-07 01:57:44 +03:00
fe94d6cf89 LibC: Implement dummy rename() so vim can save files
vim calls rename when saving a file. This patch adds dummy
implementation that only works for regular files and does a copy instead
of proper rename.
2024-08-05 20:16:05 +03:00
0a7c316ffb Kernel: Fix race condition when blocking threads
If thread was blocked, but had not reached block queue, you might
already get an unblock request which would fail on an assertion.

If blocked thread was load balanced to another processor and unblocked
simultaneously, there was a race condition.
2024-08-05 20:14:13 +03:00
e72424e01a Kernel: Implement ANSI CSI M and fix ANSI CSI L
There are not maybe not correct, but work much better than the old ones
2024-08-05 15:53:01 +03:00
dbba9128a4 Ports: Add ncurses and vim port!
vim is kind of buggy because my virtual tty {insert,delete} line ansi
codes don't really work.
2024-08-05 15:20:18 +03:00
352c1ddc16 BuildSystem: Rewrite port compilation system
Now ports define some environment variables, and call a unified bash
script that handles configuration, recompilation and installation.

If a port uses non-configure buildsystem, port script can also specify
custom build and install step.
2024-08-05 15:20:18 +03:00
4d96ae56ac LibC: Add stubs for ungetc(), tcflush() and symlink() 2024-08-05 01:48:24 +03:00
adadb10b15 LibC: Fix strsignal() and implement psignal() 2024-08-05 00:59:03 +03:00
a749b9806e LibC: Add definition for h_errno
Nothing uses this yet, but linking will succeed
2024-08-05 00:58:06 +03:00
615d9d4abe LibC: Add INADDR_LOOPBACK
Some port was using this. Loopback addresses are not supported, but they
will be 127.0.0.1.
2024-08-05 00:56:42 +03:00
aa03274093 LibC: Remove O_DIRECTORY from opendir()
opendir() did not work on symlinks after with this flag...
2024-08-05 00:55:03 +03:00
e7a06979ec LibC: Implement usleep()
This is not a POSIX function, but some ports seem to be using it either
way
2024-08-05 00:54:17 +03:00
3651306f57 LibC: Implement strto{u,i}max() 2024-08-05 00:53:27 +03:00
5dce4e6aea LibC: Implement strftime()
I did not test this at all, this might very well be broken
2024-08-05 00:49:44 +03:00
1d9041f2aa LibC: make opendir() fail if path is not a directory 2024-08-01 22:57:46 +03:00
a578527012 Kernel/LibC: Implement ioctl(TIOCGWINSZ)
This allows ncurses to get the window size!
2024-08-01 22:56:26 +03:00
af78a2d080 Kernel: Implement ANSI CSI L for TTY
vim seems to be using this, so I decided its needed
2024-08-01 22:08:46 +03:00
840000d02b Kernel: Make sure null signal is not send with kill() 2024-08-01 21:41:54 +03:00
9ea4c777ad Kernel: TTY now handles ESC key presses
This allows exiting vim :D
2024-08-01 21:41:11 +03:00
a33b63d066 Kernel/LibC: Implement alarm() and setitimer()
This makes vim able to start!
2024-08-01 21:09:56 +03:00
da3b30cd94 Kernel: Add macro to dump all syscalls and their return values 2024-08-01 18:21:49 +03:00
4599e1dec5 Kernel: Make schedler not crash when unblocking active thread
This was happening when sending signals to processes that were currently
running.
2024-08-01 18:21:49 +03:00
6de350ce9d Kernel/LibC: Cleanup, fix and implement a lot of signal code
This patch implements sigsets and some of their usages
2024-08-01 17:01:18 +03:00
838d31fa41 Kernel: Implement more POSIX compliant open() and openat() syscalls 2024-08-01 15:35:02 +03:00
401b460d75 LibC: Implement setbuf() and setvbuf() 2024-08-01 01:30:00 +03:00
c440204fa5 LibC: Implement dummy strcoll() 2024-07-31 23:58:10 +03:00
adf50dffd8 LibC: Implement uname() 2024-07-31 23:54:26 +03:00
20d38ed28c LibC/Shell: Implement gethostname() and shell uses it for hostname 2024-07-31 23:53:55 +03:00
edc30cd71d LibC: Compile without exceptions
This allows libc to not require __gxx_personality_v0. I can maybe add
C++ back to libc... :D I don't know why I did not research earlier what
this symbols was used for
2024-07-31 23:33:41 +03:00
10ce03a1e7 LibC: Implement ctime() and asctime() 2024-07-31 23:26:10 +03:00
5fca5c774a LibC: Implement umask() 2024-07-31 23:26:10 +03:00
fc6c39e670 LibC: Implement gettimeofday() 2024-07-31 23:26:06 +03:00
7c3b6307d9 Kernel: Cleanup USB initialization code 2024-07-31 23:23:44 +03:00
e52dac3b25 LibC: Implement tmpnam()
This implementation is not really spec compliant as rand() does not
guarantee TMP_MAX different outputs + seeding
2024-07-30 12:02:30 +03:00
62db9a8ef3 LibC: Implement C++ static guards 2024-07-30 12:02:05 +03:00
f0be4f86a6 LibC/Kernel: Implement access 2024-07-30 11:51:07 +03:00
e5bb843059 LibC/Kernel: Implement ttyname 2024-07-30 11:41:18 +03:00
ca774dfeb5 LibC: Implement setlocale() for C locale 2024-07-30 11:33:02 +03:00
681d8327f5 LibC/Kernel: Cleanup termios code
This is still not correct, but much better than it used to be
2024-07-30 11:10:43 +03:00
9bc02c81f8 Kernel: Map DMA and PCI MMIO as uncached 2024-07-30 11:10:08 +03:00
bb1738db8c Kernel: Make thread unblocking O(1)
This is still bit broken. VirtualBox seems to freeze sometimes, but I
could not recreate this on qemu (with and without kvm) or real hardware.
2024-07-24 00:31:01 +03:00
9548c592a3 Kernel: Always print basic info about xHCI controller
Its nice to see that the controller is getting initalized
2024-07-23 09:09:08 +03:00
cda0276d39 Kernel: Force PCI irq line usage when not using APIC
afaik PIC does not support MSI
2024-07-23 09:08:00 +03:00
539afb329a Kernel: All processors use LAPIC timer when running with APIC
This makes scheduler preemption much cleaner as bsb does not have to
send smp messages to notify other processes about timer interrupt.

Also PIT percision is now "full" 0.8 us instead of 1 ms that I was using
before.
2024-07-23 02:28:52 +03:00
3e0150f847 Kernel: Pressing F1 now toggles rendering of CPU loads to the terminal
This can be nice for seeing the performance and problems on the load
balancing algorithm.
2024-07-22 00:43:13 +03:00
f8261c60c0 Kernel: Rewrite the whole scheduler and re-architecture SMP handling
Change Semaphore -> ThreadBlocker
  This was not a semaphore, I just named it one because I didn't know
  what semaphore was. I have meant to change this sooner, but it was in
  no way urgent :D

Implement SMP events. Processors can now be sent SMP events through
IPIs. SMP events can be sent either to a single processor or broadcasted
to every processor.

PageTable::{map_page,map_range,unmap_page,unmap_range}() now send SMP
event to invalidate TLB caches for the changed pages.

Scheduler no longer uses a global run queue. Each processor has its own
scheduler that keeps track of the load on the processor. Once every
second schedulers do load balancing. Schedulers have no access to other
processors' schedulers, they just see approximate loads. If scheduler
decides that it has too much load, it will send a thread to another
processor through a SMP event.

Schedulers are currently run using the timer interrupt on BSB. This
should be not the case, and each processor should use its LAPIC timer
for interrupts. There is no reason to broadcast SMP event to all
processors when BSB gets timer interrupt.

Old scheduler only achieved 20% idle load on qemu. That was probably a
very inefficient implementation. This new scheduler seems to average
around 1% idle load. This is much closer to what I would expect. On my
own laptop idle load seems to be only around 0.5% on each processor.
2024-07-22 00:33:50 +03:00
9f90eeab05 Kernel: Fix stack pointer OOB check
i686 does not push the stack pointer on interrupt when no CPL change
happens.
2024-07-22 00:27:08 +03:00
1ee37cb671 Kernel: Make sure stack is aligned on interrupts for i686 target
I just realized that only x86_64 aligns stack pointer when interrupt is
triggered.
2024-07-22 00:10:42 +03:00
8fe798de6d Kernel: Make PIT counter atomic with spinlock 2024-07-21 18:56:41 +03:00
e00efca170 Userspace: Pprogram template and loadfont mark install as optional 2024-07-21 17:41:40 +03:00
86b6714777 Kernel: Add command line option to boot without smp 2024-07-21 17:40:57 +03:00
77b5e6d44a Kernel: Make ATABus use BAN::Atomic<> instead of gcc builtin atomics 2024-07-21 17:39:26 +03:00
ffe73165f9 Kernel: Fix PCI typo serail -> serial 2024-07-21 17:36:29 +03:00
96c7e9e29d Kernel: Cleanup VirtualRange code
Virtual range does not need to look into the page table for mapped
physcial pages. It can (and should) just keep track of them itself.
2024-07-21 17:35:07 +03:00
02051ed60f Kernel: Move keyboard kernel panic to the general input device
This will allow command to work without requiring it per keyboard driver
2024-07-21 17:33:38 +03:00
f49689caac Kernel: Implement API for sending IPIs for only one processor
Also move the spin wait to check for pending IPI sends to the start of
ipi sending function. There is no need to wait for IPI send succeeding
right after it. It is enough to make sure there are not multiple IPIs
being sent at the same time.
2024-07-21 17:30:59 +03:00
819c130366 BAN: If format string is started with space, numbers are padded with it 2024-07-19 21:39:31 +03:00
974b9b992d Kernel: Fix process exiting infinite loop
If process was exiting and had a process waiting for it and that waiting
process got interrupted, the exiting process could never exit.
2024-07-18 21:40:44 +03:00
3ab1214012 LibC: Fix _toupper and _tolower definitions
They were using C++ global namespace, which of course does not exist for
C targets.
2024-07-18 01:10:51 +03:00
4b917390ac Kernel: Fix sse state saving
This was broken when I added SMP support. This patch makes sse kind of
dumb as it is saved and restored on every interrupt, but now it at least
works properly... I'll have to look into how sse can get optimized
nicely with SMP. Simple way would be pinning each thread to a specific
processor and doing pretty much what I had before, but sse thread saved
in processor rather than static global.
2024-07-16 23:15:11 +03:00
7a0fb9a57f Kernel: Fix TTY scroll clearing first and/or last characters from line 2024-07-16 22:49:49 +03:00
58fcd2b2fe Kernel: Fix multi-interface USB device initialization 2024-07-16 22:29:18 +03:00
bdcf058e52 README: update discord link 2024-07-16 21:10:32 +03:00
61f0043cd8 resolver: Fix infinite debug printing loop, if client disconnects 2024-07-16 15:05:07 +03:00
dd7bfba8d5 ports: Compile with multiple jobs and fix curl install query 2024-07-16 15:04:46 +03:00
5b8fdbc82d LibC: Don't expose math.h in stdlib.h 2024-07-16 12:47:38 +03:00
6a1c677cbc Ports: Update doom port gitignore 2024-07-16 11:54:57 +03:00
e30952efee Kernel: Implement key repeating for USB keyboard
USB keyboards don't send repeating keys automatically, so it has to be
emulated in software.
2024-07-16 11:54:57 +03:00
fd8dc03ae9 BAN: Default initialize optional storage
This removes maybe uninitialized warning when using default initialized
optionals.
2024-07-16 11:19:16 +03:00
1337758660 Kernel: Make USB HID interfaces configure all endpoints 2024-07-16 00:23:26 +03:00
339e8a7910 Kernel: Fix USB keyboard state updating with variable reports 2024-07-16 00:03:00 +03:00
a60b460701 Kernel: Update USB HID code to support multiple top-level collections
This allows me to use my laptops own keyboard!
2024-07-16 00:01:53 +03:00
a5cb4057f9 Kernel: Implement unified input files for device hot-plugging support
/dev/keyboard and /dev/mouse can be read for events from any attached
keyboard or mouse respectively. This makes device hot-plugging support
pretty much automatic for TTY, GUI, and whatever takes input.
2024-07-15 22:11:15 +03:00
9d7f97ccd5 Kernel: Implement DevFileSystem::remove_device
This function cleanly removes the devices from the whole filesystem.

USB devices are now removed from the filesystem as soon as they are
destroyed.
2024-07-15 22:10:42 +03:00
0578d41500 Kernel: Implement WriteCombining memory
This makes framebuffer much faster on real hardware
2024-07-15 22:09:09 +03:00
42c3fa24f0 Kernel: Add support for HID Report ID and parsing all collections
Only the first top-level collection is used for the device, but that
seems to generally be what keyboard and mouse use for input.
2024-07-15 15:51:07 +03:00
60b396fee5 Kernel: Add mouse move and scroll event merging back
This makes mouse work much faster when reading can't keep up with the
amount of events.
2024-07-15 15:45:20 +03:00
4cd9252ff6 Kernel: Fix USB code
Fix USB Keyboard scan code table for bottom row of keyboard

Support multiple interfaces on a single USB device

Add usb mouse to default qemu settings
2024-07-15 11:48:48 +03:00
75875d3a8f Kernel: Set interval and average trb length on configure endpoint
Real controllers seem to require this while spec 4.8.2.4 says that they
should be left as zero.
2024-07-15 11:46:28 +03:00
86e9d92ecb Kernel: Take ownership of xHCI controller from bios 2024-07-14 03:31:35 +03:00
baa4e6475a Kernel: Implement basic USB Mouse
This has the same problem I described in previous commit for keyboard
2024-07-14 02:11:32 +03:00
ac5c77ee2c Kernel: Implement USB Keyboard
This is kinda hacky, as I had disable the PS/2 initialization so that
usb keyboard gets /dev/keyboard0. I should add device hot plugging
support for TTY and GUI...
2024-07-14 02:09:18 +03:00
1efc6a1385 Kernel: Implement simple USB HID driver
This should be easily expandable to add HID devices
2024-07-14 02:04:48 +03:00
442ea8a692 BAN: Remove Optional emplace constructor
This was kind breaking some initializations. Emplacing is still possible
through Optional::emplace
2024-07-14 01:53:50 +03:00
749be67df3 Kernel: Fix cxxabi for function static variable guards 2024-07-14 01:53:50 +03:00
a97a574718 Kernel: Rewrite the whole input system
PS/2 code is now kind of messed up, but it works. Keyboards and mice are
now an abstract class that is automatically exposed to userspace. This
will make adding USB input much nicer.
2024-07-14 01:53:50 +03:00
110a45bee6 BAN: Implement Variant::has_value() and Variant::operator bool() 2024-07-12 20:37:56 +03:00
f120da3aca Kernel: USB device now sets the current configuration 2024-07-12 11:26:06 +03:00
240684bc1f Kernel: Refactor some xHCI code and add new definitions 2024-07-12 11:25:24 +03:00
62003d96f3 BAN: Implement Optional::value_or
This will return value specified in the argument if optional is not
storing any value.
2024-07-12 11:22:10 +03:00
e905634343 Kernel: Fix bugs and cleanup USB and xHCI code and API 2024-07-11 14:10:55 +03:00
14dce1abac Kernel: Start work on USB stack
Current code can enumerate all xHCI devices and detect their type based
on the class code on device or interface descriptors.
2024-07-10 12:06:00 +03:00
8ddab05ed3 BuildSystem: Cleanup userspace directory layout
userspace programs are now in userspace/programs
userspace tests are now in userspace/tests

This makes listing userspace projects much cleaner. Libraries were
already separated to their own directory, so other programs should also.
2024-07-03 09:18:02 +03:00
5dc441c4af Kernel/userspace: Implement KD_LOADFONT and loadfont program 2024-07-03 09:02:49 +03:00
940fb0d1fd Base: Add /var/www with dummy index.html 2024-07-02 21:34:32 +03:00
f18c33563d Kernel: Fix PCI MSI-X allocation 2024-06-30 20:36:43 +03:00
10e8a54b2e General: Add more missing features to README 2024-06-29 22:13:33 +03:00
f792976d6d BuildSystem: Don't fill mount dir if mounting fails 2024-06-29 22:12:36 +03:00
08cbd009ac Kernel: PCI don't report multi function bit with header_type() 2024-06-29 22:11:55 +03:00
3d4219bfee Kernel: Don't panic if nvme initialization fails 2024-06-29 22:07:55 +03:00
d58a569660 WindowServer: Limit msync to 60 Hz and only sync necessary pages
This speeds up GUI a lot. I can now run GUI on real hardware at almost
60 Hz.
2024-06-29 19:00:58 +03:00
fd3cf5d2b1 BuildSystem: Allow running qemu without kvm
If you set QEMU_ACCEL to empty string, build system won't try to look
for kvm support.
2024-06-29 19:00:10 +03:00
1a844426c3 Kernel: Add fast path for framembuffer sync if bpp == 32 2024-06-28 23:34:11 +03:00
42237a3bc8 Kernel: Implement fast scrolling for TTY 2024-06-28 23:15:03 +03:00
010c2c934b BAN: Write RefPtr and WeakPtr to be thread safe 2024-06-28 22:00:29 +03:00
48a76426e7 BAN: Add more APIs for Atomic and make compare_exchage take a reference 2024-06-28 21:47:47 +03:00
0c645ba867 LibGUI: Window now uses double buffering
This allows data in shared memory object be always up to date. With this
change window server can update lazily, and not necessarily on all
invalidate calls
2024-06-27 00:39:59 +03:00
f538dd5276 test-tcp: Fix printing of "connection reset" when tcp connection closed 2024-06-27 00:39:22 +03:00
31568fc5a1 Kernel: Rewrite Sockets to not be TmpInodes
TmpInodes just caused issues because TmpFS kept them alive. There was
really no reason for sockets to even be stored inside a TmpFS...
2024-06-27 00:35:19 +03:00
44c7fde2f7 BAN: Fix Function requires clause argument forwariding 2024-06-27 00:33:50 +03:00
cb07142832 Kernel: ACPI allow more calling or \_S5
Spec says that \_Sx must have 4 fields, but virtual box seems to only
have the two defined once. This patch allows shutodown on virtual box
2024-06-25 23:25:10 +03:00
60a05412c9 Kernel: ACPI implement SizeOf 2024-06-25 23:24:51 +03:00
0179f5ea09 Kernel: ACPI add \_OS string 2024-06-25 23:24:19 +03:00
f671ed7e3f Kernel: ACPI implement integer stores to registers as copies
Before storing const integer and then modifying the register it would
error.
2024-06-25 23:23:52 +03:00
2fccff5a35 Kernel: Implement ACPI IndexOp into Strings 2024-06-25 23:23:00 +03:00
cd41d5f6dd ports: DOOM install now downloads and installs doom1.wad 2024-06-25 19:57:15 +03:00
66905fcc08 http-server: Make http-server actually usable
http-server now implements basic static content from a specified
directory.
2024-06-25 19:36:10 +03:00
af4b138094 Kernel/LibC: Implement realpath
realpath is implemented as a syscall. This is not really required but it
was the easiest way to get it working as there is already path
canonicalization at kernel level.
2024-06-25 19:32:40 +03:00
3c57e05a65 BAN: Implement hash for StringView 2024-06-25 19:28:45 +03:00
25099b4c98 Kernel: Don't validate O_SEARCH for non-directories 2024-06-25 19:27:55 +03:00
1ac7629459 BAN: Implement StringView::rfind() 2024-06-25 11:04:03 +03:00
95681a7a05 LibImage: Cleanup bicubic calculations 2024-06-25 11:04:03 +03:00
d7b8458a56 Kernel: Fix TCP sending
TCP send was effectively always waiting for connection to close and then
return a value of 0.
2024-06-25 11:04:03 +03:00
67dfe0bcf3 BAN: Allow String::formatted to fail 2024-06-25 11:04:03 +03:00
b1869bced4 BAN: Implement StringView::starts_with() 2024-06-25 11:04:03 +03:00
61aa1ea11f sudo: Fix installation permissions
I had accudentally removed SETUID bit from sudo. This required to
elevate the permissions.
2024-06-24 15:00:08 +03:00
20aa7c79d1 BuildSystem: Fix crt file installation
crt files should be installed always before userpace programs are
linked.
2024-06-22 17:30:00 +03:00
22548a3f4a BuildSystem: Fix crt file installation
crt files for userspace are now a dependency of libc, which means that
everytime libc gets installed, crt files will also install.

This fixes the problem when building libc
2024-06-21 17:10:58 +03:00
9e1b5cbaab BuildSystem: Cleanup CMake code to allow libc only installation
There was no way to just install libc which is required for stdlibc++
2024-06-21 01:45:14 +03:00
1488ec5a03 Userspace: Implement the most basic http server
This server just responds with static http "hello world" to every
incoming request
2024-06-20 13:29:01 +03:00
4f0457a268 Kernel: Rewrite a lot of TCP code and implement TCP server sockets
TCP stack is now implemented much closer to spec
2024-06-20 13:26:50 +03:00
30fdc2198f BAN: Add exchage() to Atomic<T> 2024-06-20 13:24:42 +03:00
bce16cdd6e Kernel: Fix how socket closing works
Sockets are now closed only when they are not referenced any more. This
allows child process to close socket and still keep it open for the
parent.
2024-06-19 10:39:44 +03:00
d5daa46ab8 General: Add default .vscode directory
The .vscode contains 2 C++ profiles that use my custom toolchain and
correct library include paths. One configuration is for kernel and other
for userspace
2024-06-19 10:16:20 +03:00
ad6d95ba52 BuildSystem: Rework the whole cmake build system
Now files are installed using the install() command instead of manually
copying files to their destinations. This allows automatic recompilation
of headers that did not work previously
2024-06-19 09:40:03 +03:00
318ce5dec8 All: Fix a lot of compiler warnings from header files
While reworking build system, header files started to report warnings.
2024-06-18 23:02:10 +03:00
526d4369ce Ports: Don't throw error if _installed_ does not exist
This was annoying and I got multiple people reporting it as a possible
bug.
2024-06-18 13:16:33 +03:00
c69919738b BuildSystem: Move all userpace libraries under the userspace directory
As the number of libraries is increasing, root directory starts to
expand. This adds better organization for libraries
2024-06-18 13:14:35 +03:00
1b5a01a6c9 LibImage: Add support for PNG images
I have not tested images with less than 8 bits per color or images with
indexed color as gimp could not export those. There is currently no
support for interlaced images.
2024-06-18 02:37:46 +03:00
f233715b70 BAN: Add d{print,want,error}ln_if macros for userspace 2024-06-18 02:35:45 +03:00
a58ac18fa0 BAN: Add move constructors to ByteSpan 2024-06-18 01:52:02 +03:00
f1e366d36f Kernel: Free keyboard mutex while waiting for data to read
This was making select hang if one thread was trying to read from
keyboard.
2024-06-17 23:04:37 +03:00
301dcd78cc LibImage: Compile with -O3
This makes image resizing with cubic interpolation around 10x faster
2024-06-17 23:03:52 +03:00
65c6d62a15 LibImage: Start work on PNG decoding
This patch adds PNG decoder that currently only inflates the PNG's zlib
deflate stream
2024-06-17 22:58:59 +03:00
aaf7a249c6 image: Add nicer error message if image could not be parsed 2024-06-17 22:58:59 +03:00
0bc8d49684 LibImage: Add image format probing
Instead of determining the image type in Image.cpp call image probing
functions for each supported image type
2024-06-17 22:14:43 +03:00
17ecbca204 BAN: Add network_endian_to_host 2024-06-17 22:14:43 +03:00
78928b7eb4 Ports: Add curl port! 2024-06-17 21:40:13 +03:00
5236e1ef0d LibC: Add dummy functions for rename() and strftime()
I don't really want to implement them right now, but they are required
to exist for some ports.
2024-06-17 21:02:37 +03:00
be7ed8e74a Kernel/LibC: Implement {get,set}sockopt()
These are pretty much dummy functions in the kernel side. Only case that
is handled is SOL_SOCKET with SO_ERROR. This is hard coded to return no
error. Network stack is currently synchronous, so all errors are already
reported through synchronous network functions.
2024-06-17 20:56:48 +03:00
78bcb85679 LibC: Implement gethostbyname()
This is not a POSIX function, but curl seems to depend on it. It is
even deprecated on linux...
2024-06-17 20:55:50 +03:00
b98bb9eb27 LibC: Add HOST_NAME_MAX definition 2024-06-17 20:55:17 +03:00
cad55a4da5 Kernel/LibC: Implement getsockname for ipv4 sockets 2024-06-17 20:54:45 +03:00
511fc870a1 BAN: Mark RefPtr and WeakPtr operator bool() as explicit 2024-06-17 20:19:36 +03:00
dafd2fecf7 LibC: Implement gmtime() and localtime()
localtime() just returns gmtime() as there is no timezone support
2024-06-17 16:51:41 +03:00
9c5cca784e LibC: Implement bsearch() 2024-06-17 16:51:24 +03:00
1138165308 LibC: Define PF_* macros on sys/socket.h 2024-06-17 16:50:03 +03:00
d7eb321d58 LibC: Make assert() macro a void expression 2024-06-17 16:49:26 +03:00
15f8c7014f BAN: Add line endings to d{warn,error}ln 2024-06-17 16:48:56 +03:00
dd64e2060e WindowServer: Add support for background images
WindowServer now looks in _$HOME/.config/WindowServer.conf_ for a
configuration file that can specify a background image.

Also add default background image /usr/share/images/sample.ppm to the
base sysroot provided in the git repo.
2024-06-16 00:28:09 +03:00
14d4551476 LibImage: Add rgba getter for Image::Color
Actually the format is 0xAARRGGBB which is what my framebuffer uses.
2024-06-16 00:23:02 +03:00
e6549b0fe8 LibImage: Implement (bi)cubic interpolation
This is kind of slow but yields much nicer results compared to
(bi)linear interpolation. I should probably add gamma correction...
2024-06-15 23:05:10 +03:00
157e05f57c image: Implement --scale argument to scale image to framebuffer
Also fix bug where red and blue channels were flipped
2024-06-15 17:24:01 +03:00
96efd1e8b9 LibImage: Implement image resize using nearest or bilinear filters 2024-06-15 17:23:24 +03:00
672ce40618 LibImage: Move userspace image parsing to its own library
The image utility now uses this tool instead of parsing images on its
own.
2024-06-14 11:05:54 +03:00
05e9d76c77 BAN: Implement will_{addition,multiplication}_overflow 2024-06-14 11:04:29 +03:00
ea7fc7f6c4 Kernel: Implement read-only FAT12/16/32 driver with long name support
You can now mount FAT filesystems! This code might not work perfectly
but my quick testing seemed to work on all (FAT12/16/32) variants.
2024-06-14 01:04:12 +03:00
6b1d5d28be Kernel: VFS root now has to be block device instead of partition 2024-06-14 00:19:12 +03:00
a9b0bfa740 LibC: Make ino_t always 64 bit 2024-06-14 00:18:21 +03:00
cc6b80a55b BAN: Optimize Vector copy assignment to reduce allocations
If vector contains enough elements, it will now replace old elements
instead of clearing and reallocating
2024-06-14 00:17:28 +03:00
6707989cd5 BAN: Implement same_as and add requires for BAN::Function with lambda
BAN::Function(lambda) now requires that the object is callable and
returns the correct type. This allows overloads with different
callback formats.
2024-06-14 00:15:48 +03:00
766439db6d Kernel: Start work on adding support for new filesystems
Old code tried to create ext2 filesystem from all devices.
2024-06-11 10:50:26 +03:00
d4903caafa Kernel: Combine consecutive mouse move and scroll events
This makes mouse work much smoother when running without kvm.
2024-06-11 00:07:31 +03:00
caa0111c79 BAN: Implement back() for CircularQueue 2024-06-11 00:05:11 +03:00
ffacff67cf LibFont: Move PSF code to separate file 2024-06-10 16:10:05 +03:00
f43a7fdfb4 Ports/doom: Doom now runs inside a window 2024-06-10 16:10:05 +03:00
7bb1a3906d BuildSystem: Run kvm-ok to determine kvm access 2024-06-10 16:10:05 +03:00
530c259e71 Kernel: Close unix domain socket when it gets destoyed
Inode closing is something that needs a complete rework. Currently all
sockets are closed when close() is called, which leads to connection
closing if you fork()/exec() with socket being marked as CLOEXEC.

Inodes should probably only be closed once they are not referenced
anywhere.
2024-06-03 18:06:01 +03:00
843a6851c4 Userspace: Start work on a terminal emulator
Terminal is still missing some ANSI codes, cursor and pseudo terminal
support.

Shell's builtin start-gui now launches a Terminal instead of test
windows.
2024-06-03 18:04:33 +03:00
234051d6bc Shell: Optimize drawing characters at the end of a command 2024-06-03 18:03:19 +03:00
981c0eb8bc Shell: Only set terminal properties if STDIN is a TTY 2024-06-03 18:02:49 +03:00
1066855532 LibGUI: Mark Window's server fd as CLOEXEC and expose it through API 2024-06-03 18:01:34 +03:00
f2d6518311 LibGUI: Add new drawing APIs to LibGUI::Window 2024-06-03 18:00:50 +03:00
765ccfa18c Kernel: Deliver SIGCHLD on process exit and ignore it properly 2024-06-03 17:58:24 +03:00
201aee3119 LibInput: Implement key_to_utf8_ansi
This function outputs utf8 encoding of a key event or ansi code for
everything it is applicable (arrows, ctrl+..., ...)
2024-06-03 17:52:43 +03:00
65f299038d BAN: Implement traits {true,false}_type with integral_constant 2024-06-03 17:51:44 +03:00
bd1290706a Kernel: Implement SharedMemoryObject cloning 2024-06-03 03:41:00 +03:00
939cbf46e4 BAN: Implement BAN::UTF8::to_codepoint() for single byte types 2024-06-03 03:39:57 +03:00
aec5a09caf Kernel/LibC: Implement SYS_ISATTY and isatty() 2024-06-03 03:36:25 +03:00
6346d1b6c7 Shell: Add builtin command for starting window server and test windows 2024-06-02 17:27:40 +03:00
05ee242b80 WindowServer: Add window title to title bar and send close events 2024-06-02 17:27:09 +03:00
64be3f05a3 LibGUI: Add 10 second timeout for connecting to WindowServer 2024-06-02 17:25:17 +03:00
cfdce9be61 BAN: Mark RefPtr and WeakPtr helper destructors virtual
Also fix a bug in WeakPtr::lock() which would assert false if the
underlying weak link was not initialized
2024-06-02 16:50:26 +03:00
446220494e Kernel: Unix domain sockets close can now be detected
When a unix domain socket is closed and it has a connection to another
socket, it will make the other socket readable and recv will return 0.

This allows detection of socket closing
2024-06-02 16:48:55 +03:00
f12ffa92a0 LibFont: Font::get_glyph() now returns nullptr if glyph does not exist
This allows getting glyphs with a single hash lookup
2024-05-31 13:05:07 +03:00
b2a4797d16 BAN: Fix dwarnln and derrorln stop color 2024-05-31 13:04:36 +03:00
8bfacb0091 Kernel: Implement deletion of SMO objects 2024-05-31 13:04:23 +03:00
0501f3bd99 Kernel: Move font code to its own library LibFont 2024-05-31 10:47:05 +03:00
ae3ae6fd0e WindowServer: Fix partial invalidation over cursor 2024-05-31 03:20:21 +03:00
011a5f57e1 WindowServer: Add title bars and clean up code 2024-05-31 03:02:58 +03:00
84b3289a2a Kernel: Move Scheduler::yield() lock check after interrupts disabled
I have no idea why this solves a bug where current processor has
scheduler lock at the beginning of yield.
2024-05-31 02:56:39 +03:00
b760892de2 Kernel: Make pselect use nanosecods instead of milliseconds 2024-05-31 02:56:17 +03:00
6840a8983c Kernel: Make sure MSB is not set on SMO keys 2024-05-29 20:01:12 +03:00
a1b3490764 Kernel: Improve random number generation for unsigned types 2024-05-29 20:00:47 +03:00
076f1efecb Kernel: Fix 32 bit fast page locking
I forgot to change this when changing the lock type. 32 bit boots again
fine :D
2024-05-29 19:44:39 +03:00
b23511edb1 LibC: Don't use BAN inside pwd.cpp
This made pwd.cpp require libstdc++ which meant that getlogin() also
needed libstdc++. This made build process of libstdc++ require itself
which is of course not possible.
2024-05-29 19:12:15 +03:00
53e572f072 Kernel: Fix s_fast_page_lock type on 32 bit target 2024-05-29 18:04:23 +03:00
c2b6ba0d5a Userspace: Start work on GUI and WindowServer
Current implementation can create custom windows and each window has
its own framebuffer. When window wants to write its framebuffer to the
screen it will send a message to the WindowServer using unix sockets.
2024-05-29 16:00:54 +03:00
d4d530e6c8 Kernel: Implement basic shared memory objects
These can allocate memory that can be shared between processes using
a global key. There is currenly no safety checks meaning anyone can
map any shared memory object just by trying to map every possible key.
2024-05-29 15:58:46 +03:00
99270e96a9 Kernel: Lock debug lock while printing fault details
This allows multiprocessor to dump clean output on concurrent faults
2024-05-29 15:49:24 +03:00
4bf7a08c80 Kernel: Allow SYS_PSELECT to work with timeout of zero 2024-05-29 15:32:18 +03:00
3823de6552 Kernel: Add templated get function for Random 2024-05-29 15:32:00 +03:00
30592b27ce BAN: Add comparison operators for RefPtr 2024-05-29 13:50:03 +03:00
8bc6c2eb20 Kernel: Move KeyEvent/MouseEvent from kernel to LibInput 2024-05-28 23:30:08 +03:00
87d52e5ebe Kernel: Fix timer early wake message
When printing early return message, current time was read twice. This
could lead to early return check failing, but when printing and reading
the time again subtraction overflow would happen.
2024-05-28 16:04:18 +03:00
598a09c13d Kernel: Allow select to work on any type of inode 2024-05-28 16:03:54 +03:00
54db4ab215 BAN: Increase BAN::Function storage size to 8 pointers 2024-05-28 16:01:41 +03:00
5b5ccba247 LibC: Define PATH_MAX in limits.h 2024-05-28 01:08:25 +03:00
18e2559b1e Kernel/LibC: Add SYS_TRUNCATE 2024-05-28 01:08:04 +03:00
f5987b68ff BAN: Mark some class methods as constexpr 2024-05-28 01:07:29 +03:00
a1ab44d39f Kernel: Optimize disk reads to read multiple sectors at once
Old StorageDevice::read_sectors() read each sector separately if the
underlying disk had a disk cache. This patch allows multiple sectors to
be read even if the disk cache exists and contains some of the sectors.

Only sectors that could not be found from the disk cache are actually
read from the disk. This optimization is not done for writing, which
still will write each sector separately, if disk cache has no memory to
store new sectors. It would feel kind of unnecessary optimization as you
have greater problems if disk cache cannot allocate a single page.
2024-05-27 15:52:34 +03:00
8b1514e575 Kernel: Make all storage devices readable and writable
I only had a {read,write}_impl defined for ATABaseDevice. This patch
moves that implmentation to general storage device.
2024-05-27 13:41:55 +03:00
1290 changed files with 94319 additions and 28201 deletions

13
.clangd Normal file
View File

@@ -0,0 +1,13 @@
Diagnostics:
Suppress: target_unsupported_type
CompileFlags:
Remove: [
-fstrict-volatile-bitfields,
-fno-tree-loop-distribute-patterns
]
Add: [
-D__banan_os__,
-D__arch__=x86_64,
-D__x86_64__
]

1
.gitignore vendored
View File

@@ -3,3 +3,4 @@
build/
base/
script/fakeroot-context
tools/update-image-perms

38
.vscode/c_cpp_properties.json vendored Normal file
View File

@@ -0,0 +1,38 @@
{
"configurations": [
{
"name": "banan-os",
"includePath": [
"${workspaceFolder}/BAN/include",
"${workspaceFolder}/kernel/include",
"${workspaceFolder}/userspace/libraries/*/include"
],
"defines": [
"__arch=x86_64",
"__enable_sse=1"
],
"compilerPath": "${workspaceFolder}/toolchain/local/bin/x86_64-banan_os-gcc",
"cStandard": "c17",
"cppStandard": "gnu++20",
"intelliSenseMode": "linux-gcc-x64"
},
{
"name": "banan-os-kernel",
"includePath": [
"${workspaceFolder}/BAN/include",
"${workspaceFolder}/kernel/include",
"${workspaceFolder}/userspace/libraries/*/include"
],
"defines": [
"__arch=x86_64",
"__is_kernel",
"__enable_sse=1"
],
"compilerPath": "${workspaceFolder}/toolchain/local/bin/x86_64-banan_os-gcc",
"cStandard": "c17",
"cppStandard": "gnu++20",
"intelliSenseMode": "linux-gcc-x64"
}
],
"version": 4
}

10
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,10 @@
{
"cmake.configureOnOpen": false,
"editor.tabSize": 4,
"editor.insertSpaces": false,
"editor.detectIndentation": false,
"clangd.arguments": [
"--compile-commands-dir=${workspaceFolder}/build",
"-header-insertion=never"
]
}

View File

@@ -1,7 +1,3 @@
cmake_minimum_required(VERSION 3.26)
project(BAN CXX)
set(BAN_SOURCES
BAN/Assert.cpp
BAN/New.cpp
@@ -9,16 +5,14 @@ set(BAN_SOURCES
BAN/Time.cpp
)
add_custom_target(ban-headers
COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different ${CMAKE_CURRENT_SOURCE_DIR}/include/ ${BANAN_INCLUDE}/
DEPENDS sysroot
)
add_library(ban ${BAN_SOURCES})
add_dependencies(ban headers libc-install)
target_link_options(ban PRIVATE -nolibc)
banan_link_library(ban libc)
add_custom_target(ban-install
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_BINARY_DIR}/libban.a ${BANAN_LIB}/
DEPENDS ban
BYPRODUCTS ${BANAN_LIB}/libban.a
)
set_target_properties(ban PROPERTIES OUTPUT_NAME libban)
# set SONAME as cmake doesn't set it for some reason??
set_target_properties(ban PROPERTIES LINK_FLAGS "-Wl,-soname,libban.so")
banan_install_headers(ban)
install(TARGETS ban OPTIONAL)

View File

@@ -18,78 +18,78 @@ namespace BAN
using const_iterator = ConstIteratorSimple<T, Array>;
public:
Array() = default;
Array(const T&);
constexpr Array() = default;
constexpr Array(const T&);
iterator begin() { return iterator(m_data); }
iterator end() { return iterator(m_data + size()); }
const_iterator begin() const { return const_iterator(m_data); }
const_iterator end() const { return const_iterator(m_data + size()); }
const T& operator[](size_type) const;
T& operator[](size_type);
constexpr const T& operator[](size_type) const;
constexpr T& operator[](size_type);
const T& back() const;
T& back();
const T& front() const;
T& front();
constexpr const T& back() const;
constexpr T& back();
constexpr const T& front() const;
constexpr T& front();
Span<T> span() { return Span(m_data, size()); }
const Span<T> span() const { return Span(m_data, size()); }
Span<const T> span() const { return Span(m_data, size()); }
constexpr size_type size() const;
const T* data() const { return m_data; }
T* data() { return m_data; }
constexpr const T* data() const { return m_data; }
constexpr T* data() { return m_data; }
private:
T m_data[S] {};
};
template<typename T, size_t S>
Array<T, S>::Array(const T& value)
constexpr Array<T, S>::Array(const T& value)
{
for (size_type i = 0; i < S; i++)
m_data[i] = value;
}
template<typename T, size_t S>
const T& Array<T, S>::operator[](size_type index) const
constexpr const T& Array<T, S>::operator[](size_type index) const
{
ASSERT(index < S);
return m_data[index];
}
template<typename T, size_t S>
T& Array<T, S>::operator[](size_type index)
constexpr T& Array<T, S>::operator[](size_type index)
{
ASSERT(index < S);
return m_data[index];
}
template<typename T, size_t S>
const T& Array<T, S>::back() const
constexpr const T& Array<T, S>::back() const
{
ASSERT(S != 0);
return m_data[S - 1];
}
template<typename T, size_t S>
T& Array<T, S>::back()
constexpr T& Array<T, S>::back()
{
ASSERT(S != 0);
return m_data[S - 1];
}
template<typename T, size_t S>
const T& Array<T, S>::front() const
constexpr const T& Array<T, S>::front() const
{
ASSERT(S != 0);
return m_data[0];
}
template<typename T, size_t S>
T& Array<T, S>::front()
constexpr T& Array<T, S>::front()
{
ASSERT(S != 0);
return m_data[0];

View File

@@ -1,5 +1,7 @@
#pragma once
#include <BAN/Traits.h>
namespace BAN
{
@@ -13,8 +15,36 @@ namespace BAN
memory_order_seq_cst = __ATOMIC_SEQ_CST,
};
template<typename T, MemoryOrder MEM_ORDER = MemoryOrder::memory_order_seq_cst>
requires requires { __atomic_always_lock_free(sizeof(T), 0); }
template<typename T> concept atomic_c = is_integral_v<T> || is_pointer_v<T>;
template<typename T> concept atomic_lockfree_c = (is_integral_v<T> || is_pointer_v<T>) && __atomic_always_lock_free(sizeof(T), 0);
template<atomic_lockfree_c T, atomic_c U>
inline void atomic_store(T& obj, U value, MemoryOrder mem_order = MemoryOrder::memory_order_seq_cst) { __atomic_store_n(&obj, value, mem_order); }
template<atomic_lockfree_c T>
inline T atomic_load(T& obj, MemoryOrder mem_order = MemoryOrder::memory_order_seq_cst) { return __atomic_load_n(&obj, mem_order); }
template<atomic_lockfree_c T, atomic_c U>
inline T atomic_exchange(T& obj, U value, MemoryOrder mem_order = MemoryOrder::memory_order_seq_cst) { return __atomic_exchange_n(&obj, value, mem_order); }
template<atomic_lockfree_c T, atomic_lockfree_c U, atomic_c V>
inline bool atomic_compare_exchange(T& obj, U& expected, V value, MemoryOrder mem_order = MemoryOrder::memory_order_seq_cst) { return __atomic_compare_exchange_n(&obj, &expected, value, false, mem_order, mem_order); }
#define DECL_ATOMIC_INLINE template<atomic_lockfree_c T, atomic_c U> inline
DECL_ATOMIC_INLINE T atomic_add_fetch (T& obj, U value, MemoryOrder mem_order = MemoryOrder::memory_order_seq_cst) { return __atomic_add_fetch (&obj, value, mem_order); }
DECL_ATOMIC_INLINE T atomic_sub_fetch (T& obj, U value, MemoryOrder mem_order = MemoryOrder::memory_order_seq_cst) { return __atomic_sub_fetch (&obj, value, mem_order); }
DECL_ATOMIC_INLINE T atomic_and_fetch (T& obj, U value, MemoryOrder mem_order = MemoryOrder::memory_order_seq_cst) { return __atomic_and_fetch (&obj, value, mem_order); }
DECL_ATOMIC_INLINE T atomic_xor_fetch (T& obj, U value, MemoryOrder mem_order = MemoryOrder::memory_order_seq_cst) { return __atomic_xor_fetch (&obj, value, mem_order); }
DECL_ATOMIC_INLINE T atomic_or_fetch (T& obj, U value, MemoryOrder mem_order = MemoryOrder::memory_order_seq_cst) { return __atomic_or_fetch (&obj, value, mem_order); }
DECL_ATOMIC_INLINE T atomic_nand_fetch(T& obj, U value, MemoryOrder mem_order = MemoryOrder::memory_order_seq_cst) { return __atomic_nand_fetch(&obj, value, mem_order); }
DECL_ATOMIC_INLINE T atomic_fetch_add (T& obj, U value, MemoryOrder mem_order = MemoryOrder::memory_order_seq_cst) { return __atomic_fetch_add (&obj, value, mem_order); }
DECL_ATOMIC_INLINE T atomic_fetch_sub (T& obj, U value, MemoryOrder mem_order = MemoryOrder::memory_order_seq_cst) { return __atomic_fetch_sub (&obj, value, mem_order); }
DECL_ATOMIC_INLINE T atomic_fetch_and (T& obj, U value, MemoryOrder mem_order = MemoryOrder::memory_order_seq_cst) { return __atomic_fetch_and (&obj, value, mem_order); }
DECL_ATOMIC_INLINE T atomic_fetch_xor (T& obj, U value, MemoryOrder mem_order = MemoryOrder::memory_order_seq_cst) { return __atomic_fetch_xor (&obj, value, mem_order); }
DECL_ATOMIC_INLINE T atomic_fetch_or (T& obj, U value, MemoryOrder mem_order = MemoryOrder::memory_order_seq_cst) { return __atomic_fetch_or (&obj, value, mem_order); }
DECL_ATOMIC_INLINE T atomic_fetch_nand(T& obj, U value, MemoryOrder mem_order = MemoryOrder::memory_order_seq_cst) { return __atomic_fetch_nand(&obj, value, mem_order); }
#undef DECL_ATOMIC_INLINE
template<atomic_lockfree_c T, MemoryOrder MEM_ORDER = MemoryOrder::memory_order_seq_cst>
class Atomic
{
Atomic(const Atomic&) = delete;
@@ -26,26 +56,41 @@ namespace BAN
constexpr Atomic() : m_value(0) {}
constexpr Atomic(T val) : m_value(val) {}
inline T load(MemoryOrder mem_order = MEM_ORDER) const volatile { return __atomic_load_n(&m_value, mem_order); }
inline void store(T val, MemoryOrder mem_order = MEM_ORDER) volatile { __atomic_store_n(&m_value, val, mem_order); }
inline T load(MemoryOrder mem_order = MEM_ORDER) const volatile { return atomic_load(m_value, mem_order); }
inline void store(T val, MemoryOrder mem_order = MEM_ORDER) volatile { atomic_store(m_value, val, mem_order); }
inline T operator=(T val) volatile { store(val); return val; }
inline operator T() const volatile { return load(); }
inline T operator+=(T val) volatile { return __atomic_add_fetch(&m_value, val, MEM_ORDER); }
inline T operator-=(T val) volatile { return __atomic_sub_fetch(&m_value, val, MEM_ORDER); }
inline T operator&=(T val) volatile { return __atomic_and_fetch(&m_value, val, MEM_ORDER); }
inline T operator^=(T val) volatile { return __atomic_xor_fetch(&m_value, val, MEM_ORDER); }
inline T operator|=(T val) volatile { return __atomic_or_fetch(&m_value, val, MEM_ORDER); }
inline T operator+=(T val) volatile { return atomic_add_fetch(m_value, val, MEM_ORDER); }
inline T operator-=(T val) volatile { return atomic_sub_fetch(m_value, val, MEM_ORDER); }
inline T operator&=(T val) volatile { return atomic_and_fetch(m_value, val, MEM_ORDER); }
inline T operator^=(T val) volatile { return atomic_xor_fetch(m_value, val, MEM_ORDER); }
inline T operator|=(T val) volatile { return atomic_or_fetch(m_value, val, MEM_ORDER); }
inline T operator--() volatile { return __atomic_sub_fetch(&m_value, 1, MEM_ORDER); }
inline T operator++() volatile { return __atomic_add_fetch(&m_value, 1, MEM_ORDER); }
inline T operator--() volatile { return atomic_sub_fetch(m_value, 1, MEM_ORDER); }
inline T operator++() volatile { return atomic_add_fetch(m_value, 1, MEM_ORDER); }
inline T operator--(int) volatile { return __atomic_fetch_sub(&m_value, 1, MEM_ORDER); }
inline T operator++(int) volatile { return __atomic_fetch_add(&m_value, 1, MEM_ORDER); }
inline T operator--(int) volatile { return atomic_fetch_sub(m_value, 1, MEM_ORDER); }
inline T operator++(int) volatile { return atomic_fetch_add(m_value, 1, MEM_ORDER); }
inline bool compare_exchange(T expected, T desired, MemoryOrder mem_order = MEM_ORDER) volatile { return __atomic_compare_exchange_n(&m_value, &expected, desired, false, mem_order, mem_order); }
inline bool compare_exchange(T& expected, T desired, MemoryOrder mem_order = MEM_ORDER) volatile { return atomic_compare_exchange(m_value, expected, desired, mem_order); }
inline T exchange(T desired, MemoryOrder mem_order = MEM_ORDER) volatile { return atomic_exchange(m_value, desired, mem_order); };
inline T add_fetch (T val, MemoryOrder mem_order = MEM_ORDER) volatile { return atomic_add_fetch (m_value, val, mem_order); }
inline T sub_fetch (T val, MemoryOrder mem_order = MEM_ORDER) volatile { return atomic_sub_fetch (m_value, val, mem_order); }
inline T and_fetch (T val, MemoryOrder mem_order = MEM_ORDER) volatile { return atomic_and_fetch (m_value, val, mem_order); }
inline T xor_fetch (T val, MemoryOrder mem_order = MEM_ORDER) volatile { return atomic_xor_fetch (m_value, val, mem_order); }
inline T or_fetch (T val, MemoryOrder mem_order = MEM_ORDER) volatile { return atomic_or_fetch (m_value, val, mem_order); }
inline T nand_fetch(T val, MemoryOrder mem_order = MEM_ORDER) volatile { return atomic_nand_fetch(m_value, val, mem_order); }
inline T fetch_add (T val, MemoryOrder mem_order = MEM_ORDER) volatile { return atomic_fetch_add (m_value, val, mem_order); }
inline T fetch_sub (T val, MemoryOrder mem_order = MEM_ORDER) volatile { return atomic_fetch_sub (m_value, val, mem_order); }
inline T fetch_and (T val, MemoryOrder mem_order = MEM_ORDER) volatile { return atomic_fetch_and (m_value, val, mem_order); }
inline T fetch_xor (T val, MemoryOrder mem_order = MEM_ORDER) volatile { return atomic_fetch_xor (m_value, val, mem_order); }
inline T fetch_or (T val, MemoryOrder mem_order = MEM_ORDER) volatile { return atomic_fetch_or (m_value, val, mem_order); }
inline T fetch_nand(T val, MemoryOrder mem_order = MEM_ORDER) volatile { return atomic_fetch_nand(m_value, val, mem_order); }
private:
T m_value;

View File

@@ -21,60 +21,56 @@ namespace BAN
, m_size(size)
{ }
ByteSpanGeneral(ByteSpanGeneral& other)
template<bool SRC_CONST>
ByteSpanGeneral(const ByteSpanGeneral<SRC_CONST>& other) requires(CONST || !SRC_CONST)
: m_data(other.data())
, m_size(other.size())
{ }
template<bool C2>
ByteSpanGeneral(const ByteSpanGeneral<C2>& other) requires(CONST)
template<bool SRC_CONST>
ByteSpanGeneral(ByteSpanGeneral<SRC_CONST>&& other) requires(CONST || !SRC_CONST)
: m_data(other.data())
, m_size(other.size())
{ }
ByteSpanGeneral(Span<uint8_t> other)
: m_data(other.data())
, m_size(other.size())
{ }
ByteSpanGeneral(const Span<const uint8_t>& other) requires(CONST)
: m_data(other.data())
, m_size(other.size())
{ }
{
other.clear();
}
ByteSpanGeneral& operator=(ByteSpanGeneral other)
template<typename T>
ByteSpanGeneral(const Span<T>& other) requires(is_same_v<T, uint8_t> || (is_same_v<T, const uint8_t> && CONST))
: m_data(other.data())
, m_size(other.size())
{ }
template<typename T>
ByteSpanGeneral(Span<T>&& other) requires(is_same_v<T, uint8_t> || (is_same_v<T, const uint8_t> && CONST))
: m_data(other.data())
, m_size(other.size())
{
other.clear();
}
template<bool SRC_CONST>
ByteSpanGeneral& operator=(const ByteSpanGeneral<SRC_CONST>& other) requires(CONST || !SRC_CONST)
{
m_data = other.data();
m_size = other.size();
return *this;
}
template<bool C2>
ByteSpanGeneral& operator=(const ByteSpanGeneral<C2>& other) requires(CONST)
{
m_data = other.data();
m_size = other.size();
return *this;
}
ByteSpanGeneral& operator=(Span<uint8_t> other)
{
m_data = other.data();
m_size = other.size();
return *this;
}
ByteSpanGeneral& operator=(const Span<const uint8_t>& other) requires(CONST)
template<bool SRC_CONST>
ByteSpanGeneral& operator=(ByteSpanGeneral<SRC_CONST>&& other) requires(CONST || !SRC_CONST)
{
m_data = other.data();
m_size = other.size();
other.clear();
return *this;
}
template<typename S>
requires(CONST || !is_const_v<S>)
static ByteSpanGeneral from(S& value)
static ByteSpanGeneral from(S& value) requires(CONST || !is_const_v<S>)
{
return ByteSpanGeneral(reinterpret_cast<value_type*>(&value), sizeof(S));
}
template<typename S>
requires(!CONST && !is_const_v<S>)
S& as()
S& as() const requires(!CONST || is_const_v<S>)
{
ASSERT(m_data);
ASSERT(m_size >= sizeof(S));
@@ -82,30 +78,13 @@ namespace BAN
}
template<typename S>
requires(is_const_v<S>)
S& as() const
{
ASSERT(m_data);
ASSERT(m_size >= sizeof(S));
return *reinterpret_cast<S*>(m_data);
}
template<typename S>
requires(!CONST && !is_const_v<S>)
Span<S> as_span()
Span<S> as_span() const requires(!CONST || is_const_v<S>)
{
ASSERT(m_data);
return Span<S>(reinterpret_cast<S*>(m_data), m_size / sizeof(S));
}
template<typename S>
const Span<S> as_span() const
{
ASSERT(m_data);
return Span<S>(reinterpret_cast<S*>(m_data), m_size / sizeof(S));
}
ByteSpanGeneral slice(size_type offset, size_type length = size_type(-1))
[[nodiscard]] ByteSpanGeneral slice(size_type offset, size_type length = size_type(-1)) const
{
ASSERT(m_data);
ASSERT(m_size >= offset);
@@ -115,25 +94,28 @@ namespace BAN
return ByteSpanGeneral(m_data + offset, length);
}
value_type& operator[](size_type offset)
{
ASSERT(offset < m_size);
return m_data[offset];
}
const value_type& operator[](size_type offset) const
value_type& operator[](size_type offset) const
{
ASSERT(offset < m_size);
return m_data[offset];
}
value_type* data() { return m_data; }
const value_type* data() const { return m_data; }
value_type* data() const { return m_data; }
bool empty() const { return m_size == 0; }
size_type size() const { return m_size; }
void clear()
{
m_data = nullptr;
m_size = 0;
}
private:
value_type* m_data { nullptr };
size_type m_size { 0 };
friend class ByteSpanGeneral<!CONST>;
};
using ByteSpan = ByteSpanGeneral<false>;

View File

@@ -24,13 +24,21 @@ namespace BAN
void push(const T&);
void push(T&&);
template<typename... Args>
void emplace(Args&&... args);
void emplace(Args&&... args) requires is_constructible_v<T, Args...>;
void pop();
const T& front() const;
T& front();
const T& back() const;
T& back();
const T& operator[](size_t index) const;
T& operator[](size_t index);
void clear();
size_type size() const { return m_size; }
bool empty() const { return size() == 0; }
bool full() const { return size() == capacity(); }
@@ -50,8 +58,7 @@ namespace BAN
template<typename T, size_t S>
CircularQueue<T, S>::~CircularQueue()
{
for (size_type i = 0; i < m_size; i++)
element_at((m_first + i) % capacity())->~T();
clear();
}
template<typename T, size_t S>
@@ -68,7 +75,7 @@ namespace BAN
template<typename T, size_t S>
template<typename... Args>
void CircularQueue<T, S>::emplace(Args&&... args)
void CircularQueue<T, S>::emplace(Args&&... args) requires is_constructible_v<T, Args...>
{
ASSERT(!full());
new (element_at(((m_first + m_size) % capacity()))) T(BAN::forward<Args>(args)...);
@@ -98,6 +105,42 @@ namespace BAN
return *element_at(m_first);
}
template<typename T, size_t S>
const T& CircularQueue<T, S>::back() const
{
ASSERT(!empty());
return *element_at((m_first + m_size - 1) % capacity());
}
template<typename T, size_t S>
T& CircularQueue<T, S>::back()
{
ASSERT(!empty());
return *element_at((m_first + m_size - 1) % capacity());
}
template<typename T, size_t S>
const T& CircularQueue<T, S>::operator[](size_t index) const
{
ASSERT(index < m_size);
return *element_at((m_first + index) % capacity());
}
template<typename T, size_t S>
T& CircularQueue<T, S>::operator[](size_t index)
{
ASSERT(index < m_size);
return *element_at((m_first + index) % capacity());
}
template<typename T, size_t S>
void CircularQueue<T, S>::clear()
{
for (size_type i = 0; i < m_size; i++)
element_at((m_first + i) % capacity())->~T();
m_size = 0;
}
template<typename T, size_t S>
const T* CircularQueue<T, S>::element_at(size_type index) const
{

View File

@@ -9,27 +9,53 @@
#include <BAN/Formatter.h>
#include <stdio.h>
#define __debug_putchar [](int c) { putc(c, stddbg); }
#define __debug_putchar [](int c) { putc_unlocked(c, stddbg); }
#define dprintln(...) \
do { \
flockfile(stddbg); \
BAN::Formatter::print(__debug_putchar, __VA_ARGS__); \
BAN::Formatter::print(__debug_putchar,"\r\n"); \
BAN::Formatter::print(__debug_putchar,"\n"); \
fflush(stddbg); \
funlockfile(stddbg); \
} while (false)
#define dwarnln(...) \
do { \
flockfile(stddbg); \
BAN::Formatter::print(__debug_putchar, "\e[33m"); \
dprintln(__VA_ARGS__); \
BAN::Formatter::print(__debug_putchar, "\e[m"); \
BAN::Formatter::print(__debug_putchar, __VA_ARGS__); \
BAN::Formatter::print(__debug_putchar, "\e[m\n"); \
fflush(stddbg); \
funlockfile(stddbg); \
} while(false)
#define derrorln(...) \
do { \
flockfile(stddbg); \
BAN::Formatter::print(__debug_putchar, "\e[31m"); \
BAN::Formatter::print(__debug_putchar, __VA_ARGS__); \
BAN::Formatter::print(__debug_putchar, "\e[m\n"); \
fflush(stddbg); \
funlockfile(stddbg); \
} while(false)
#define dprintln_if(cond, ...) \
do { \
if constexpr(cond) \
dprintln(__VA_ARGS__); \
BAN::Formatter::print(__debug_putchar, "\e[m"); \
} while(false)
#define dwarnln_if(cond, ...) \
do { \
if constexpr(cond) \
dwarnln(__VA_ARGS__); \
} while(false)
#define derrorln_if(cond, ...) \
do { \
if constexpr(cond) \
derrorln(__VA_ARGS__); \
} while(false)
#endif

View File

@@ -70,15 +70,19 @@ namespace BAN
template<integral T>
struct LittleEndian
{
constexpr LittleEndian()
: raw(0)
{ }
constexpr LittleEndian(T value)
{
raw = host_to_little_endian(value);
}
: raw(host_to_little_endian(value))
{ }
constexpr operator T() const
{
return host_to_little_endian(raw);
}
private:
T raw;
};
@@ -86,15 +90,19 @@ namespace BAN
template<integral T>
struct BigEndian
{
constexpr BigEndian()
: raw(0)
{ }
constexpr BigEndian(T value)
{
raw = host_to_big_endian(value);
}
: raw(host_to_big_endian(value))
{ }
constexpr operator T() const
{
return host_to_big_endian(raw);
}
private:
T raw;
};
@@ -108,4 +116,10 @@ namespace BAN
return host_to_big_endian(value);
}
template<integral T>
constexpr T network_endian_to_host(T value)
{
return big_endian_to_host(value);
}
}

View File

@@ -1,6 +1,7 @@
#pragma once
#include <BAN/Formatter.h>
#include <BAN/NoCopyMove.h>
#include <BAN/Variant.h>
#include <errno.h>
@@ -9,16 +10,16 @@
#ifdef __is_kernel
#include <kernel/Panic.h>
#include <kernel/Errors.h>
#define MUST(expr) ({ auto&& e = expr; if (e.is_error()) Kernel::panic("{}", e.error()); e.release_value(); })
#define MUST_REF(expr) *({ auto&& e = expr; if (e.is_error()) Kernel::panic("{}", e.error()); &e.release_value(); })
#define MUST(...) ({ auto&& e = (__VA_ARGS__); if (e.is_error()) Kernel::panic("{}", e.error()); e.release_value(); })
#define MUST_REF(...) *({ auto&& e = (__VA_ARGS__); if (e.is_error()) Kernel::panic("{}", e.error()); &e.release_value(); })
#else
#include <assert.h>
#define MUST(expr) ({ auto&& e = expr; assert(!e.is_error()); e.release_value(); })
#define MUST_REF(expr) *({ auto&& e = expr; assert(!e.is_error()); &e.release_value(); })
#include <BAN/Debug.h>
#define MUST(...) ({ auto&& e = (__VA_ARGS__); if (e.is_error()) { derrorln("MUST(" #__VA_ARGS__ "): {}", e.error()); __builtin_trap(); } e.release_value(); })
#define MUST_REF(...) *({ auto&& e = (__VA_ARGS__); if (e.is_error()) { derrorln("MUST(" #__VA_ARGS__ "): {}", e.error()); __builtin_trap(); } &e.release_value(); })
#endif
#define TRY(expr) ({ auto&& e = expr; if (e.is_error()) return e.release_error(); e.release_value(); })
#define TRY_REF(expr) *({ auto&& e = expr; if (e.is_error()) return e.release_error(); &e.release_value(); })
#define TRY(...) ({ auto&& e = (__VA_ARGS__); if (e.is_error()) return e.release_error(); e.release_value(); })
#define TRY_REF(...) *({ auto&& e = (__VA_ARGS__); if (e.is_error()) return e.release_error(); &e.release_value(); })
namespace BAN
{
@@ -36,7 +37,14 @@ namespace BAN
{
return Error((uint64_t)error | kernel_error_mask);
}
#else
template<size_t N>
consteval static Error from_literal(const char (&message)[N])
{
return Error(message);
}
#endif
static Error from_errno(int error)
{
return Error(error);
@@ -54,12 +62,15 @@ namespace BAN
}
#endif
uint64_t get_error_code() const { return m_error_code; }
constexpr uint64_t get_error_code() const { return m_error_code; }
const char* get_message() const
{
#ifdef __is_kernel
if (m_error_code & kernel_error_mask)
return Kernel::error_string(kernel_error());
#else
if (m_message)
return m_message;
#endif
if (auto* desc = strerrordesc_np(m_error_code))
return desc;
@@ -67,16 +78,27 @@ namespace BAN
}
private:
Error(uint64_t error)
constexpr Error(uint64_t error)
: m_error_code(error)
{}
uint64_t m_error_code;
#ifndef __is_kernel
constexpr Error(const char* message)
: m_message(message)
{}
#endif
uint64_t m_error_code { 0 };
#ifndef __is_kernel
const char* m_message { nullptr };
#endif
};
template<typename T>
class [[nodiscard]] ErrorOr
{
BAN_NON_COPYABLE(ErrorOr);
public:
ErrorOr(const T& value)
: m_data(value)
@@ -90,6 +112,14 @@ namespace BAN
ErrorOr(Error&& error)
: m_data(move(error))
{}
ErrorOr(ErrorOr&& other)
: m_data(move(other.m_data))
{}
ErrorOr& operator=(ErrorOr&& other)
{
m_data = move(other.m_data);
return *this;
}
bool is_error() const { return m_data.template has<Error>(); }
const Error& error() const { return m_data.template get<Error>(); }

View File

@@ -10,22 +10,19 @@ namespace BAN::Formatter
struct ValueFormat;
template<typename F>
static void print(F putc, const char* format);
template<typename F, typename Arg, typename... Args>
static void print(F putc, const char* format, Arg&& arg, Args&&... args);
template<typename F, typename... Args>
static void println(F putc, const char* format, Args&&... args);
concept PrintableArguments = requires(F putc, Args&&... args, const ValueFormat& format)
{
(print_argument(putc, BAN::forward<Args>(args), format), ...);
};
template<typename F, typename T>
static void print_argument(F putc, T value, const ValueFormat& format);
inline void print_argument(F putc, T value, const ValueFormat& format);
namespace detail
{
template<typename F, typename T>
static size_t parse_format_and_print_argument(F putc, const char* format, T&& arg);
inline size_t parse_format_and_print_argument(F putc, const char* format, T&& arg);
}
/*
@@ -39,11 +36,12 @@ namespace BAN::Formatter
int base = 10;
int percision = 3;
int fill = 0;
char fill_char = '0';
bool upper = false;
};
template<typename F>
void print(F putc, const char* format)
inline void print(F putc, const char* format)
{
while (*format)
{
@@ -52,8 +50,8 @@ namespace BAN::Formatter
}
}
template<typename F, typename Arg, typename... Args>
void print(F putc, const char* format, Arg&& arg, Args&&... args)
template<typename F, typename Arg, typename... Args> requires PrintableArguments<F, Arg, Args...>
inline void print(F putc, const char* format, Arg&& arg, Args&&... args)
{
while (*format && *format != '{')
{
@@ -71,7 +69,7 @@ namespace BAN::Formatter
}
template<typename F, typename... Args>
void println(F putc, const char* format, Args&&... args)
inline void println(F putc, const char* format, Args&&... args)
{
print(putc, format, args...);
putc('\n');
@@ -81,7 +79,7 @@ namespace BAN::Formatter
{
template<typename F, typename Arg>
size_t parse_format_and_print_argument(F putc, const char* format, Arg&& argument)
inline size_t parse_format_and_print_argument(F putc, const char* format, Arg&& argument)
{
ValueFormat value_format;
@@ -94,6 +92,12 @@ namespace BAN::Formatter
if (!format[i] || format[i] == '}')
break;
if (format[i] == ' ')
{
value_format.fill_char = ' ';
i++;
}
if ('0' <= format[i] && format[i] <= '9')
{
int fill = 0;
@@ -143,7 +147,7 @@ namespace BAN::Formatter
return i + 1;
}
static char value_to_base_char(uint8_t value, int base, bool upper)
inline char value_to_base_char(uint8_t value, int base, bool upper)
{
if (base <= 10)
return value + '0';
@@ -157,11 +161,12 @@ namespace BAN::Formatter
}
template<typename F, typename T>
void print_integer(F putc, T value, const ValueFormat& format)
inline void print_integer(F putc, T value, const ValueFormat& format)
{
if (value == 0)
{
for (int i = 0; i < format.fill || i < 1; i++)
for (int i = 0; i < format.fill - 1; i++)
putc(format.fill_char);
putc('0');
return;
}
@@ -188,7 +193,7 @@ namespace BAN::Formatter
}
while (ptr >= buffer + sizeof(buffer) - format.fill)
*(--ptr) = '0';
*(--ptr) = format.fill_char;
if (sign)
*(--ptr) = '-';
@@ -197,12 +202,16 @@ namespace BAN::Formatter
}
template<typename F, typename T>
void print_floating(F putc, T value, const ValueFormat& format)
inline void print_floating(F putc, T value, const ValueFormat& format)
{
if (value < 0)
{
putc('-');
return print_floating(putc, -value, format);
}
int64_t int_part = (int64_t)value;
T frac_part = value - (T)int_part;
if (frac_part < 0)
frac_part = -frac_part;
print_integer(putc, int_part, format);
@@ -220,7 +229,7 @@ namespace BAN::Formatter
}
template<typename F>
void print_pointer(F putc, void* ptr, const ValueFormat& format)
inline void print_pointer(F putc, void* ptr, const ValueFormat& format)
{
uintptr_t value = (uintptr_t)ptr;
print(putc, "0x");
@@ -236,13 +245,13 @@ namespace BAN::Formatter
*/
template<typename F, integral T> void print_argument(F putc, T value, const ValueFormat& format) { detail::print_integer(putc, value, format); }
template<typename F, floating_point T> void print_argument(F putc, T value, const ValueFormat& format) { detail::print_floating(putc, value, format); }
template<typename F, pointer T> void print_argument(F putc, T value, const ValueFormat& format) { detail::print_pointer(putc, (void*)value, format); }
template<typename F, integral T> inline void print_argument(F putc, T value, const ValueFormat& format) { detail::print_integer(putc, value, format); }
template<typename F, floating_point T> inline void print_argument(F putc, T value, const ValueFormat& format) { detail::print_floating(putc, value, format); }
template<typename F, pointer T> inline void print_argument(F putc, T value, const ValueFormat& format) { detail::print_pointer(putc, (void*)value, format); }
template<typename F> void print_argument(F putc, char value, const ValueFormat&) { putc(value); }
template<typename F> void print_argument(F putc, bool value, const ValueFormat&) { print(putc, value ? "true" : "false"); }
template<typename F> void print_argument(F putc, const char* value, const ValueFormat&) { print(putc, value); }
template<typename F> void print_argument(F putc, char* value, const ValueFormat&) { print(putc, value); }
template<typename F> inline void print_argument(F putc, char value, const ValueFormat&) { putc(value); }
template<typename F> inline void print_argument(F putc, bool value, const ValueFormat&) { print(putc, value ? "true" : "false"); }
template<typename F> inline void print_argument(F putc, const char* value, const ValueFormat&) { print(putc, value); }
template<typename F> inline void print_argument(F putc, char* value, const ValueFormat&) { print(putc, value); }
}

View File

@@ -20,19 +20,19 @@ namespace BAN
new (m_storage) CallablePointer(function);
}
template<typename Own>
Function(Ret(Own::*function)(Args...), Own* owner)
Function(Ret(Own::*function)(Args...), Own& owner)
{
static_assert(sizeof(CallableMember<Own>) <= m_size);
new (m_storage) CallableMember<Own>(function, owner);
}
template<typename Own>
Function(Ret(Own::*function)(Args...) const, const Own* owner)
Function(Ret(Own::*function)(Args...) const, const Own& owner)
{
static_assert(sizeof(CallableMemberConst<Own>) <= m_size);
new (m_storage) CallableMemberConst<Own>(function, owner);
}
template<typename Lambda>
Function(Lambda lambda)
Function(Lambda lambda) requires requires(Lambda lamda, Args&&... args) { { lambda(forward<Args>(args)...) } -> BAN::same_as<Ret>; }
{
static_assert(sizeof(CallableLambda<Lambda>) <= m_size);
new (m_storage) CallableLambda<Lambda>(lambda);
@@ -91,36 +91,36 @@ namespace BAN
template<typename Own>
struct CallableMember : public CallableBase
{
CallableMember(Ret(Own::*function)(Args...), Own* owner)
CallableMember(Ret(Own::*function)(Args...), Own& owner)
: m_owner(owner)
, m_function(function)
{ }
virtual Ret call(Args... args) const override
{
return (m_owner->*m_function)(forward<Args>(args)...);
return (m_owner.*m_function)(forward<Args>(args)...);
}
private:
Own* m_owner = nullptr;
Own& m_owner;
Ret(Own::*m_function)(Args...) = nullptr;
};
template<typename Own>
struct CallableMemberConst : public CallableBase
{
CallableMemberConst(Ret(Own::*function)(Args...) const, const Own* owner)
CallableMemberConst(Ret(Own::*function)(Args...) const, const Own& owner)
: m_owner(owner)
, m_function(function)
{ }
virtual Ret call(Args... args) const override
{
return (m_owner->*m_function)(forward<Args>(args)...);
return (m_owner.*m_function)(forward<Args>(args)...);
}
private:
const Own* m_owner = nullptr;
const Own& m_owner;
Ret(Own::*m_function)(Args...) const = nullptr;
};
@@ -141,7 +141,7 @@ namespace BAN
};
private:
static constexpr size_t m_size = sizeof(void*) * 5;
static constexpr size_t m_size = sizeof(void*) * 8;
alignas(CallableBase) uint8_t m_storage[m_size] { 0 };
};

View File

@@ -1,7 +1,7 @@
#pragma once
#include <BAN/Optional.h>
#include <BAN/StringView.h>
#include <BAN/String.h>
#include <string.h>
@@ -19,6 +19,54 @@ namespace BAN
{
return memcmp(this, &other, sizeof(GUID)) == 0;
}
BAN::ErrorOr<BAN::String> to_string() const
{
char buffer[37];
char* ptr = buffer;
const auto append_hex_nibble =
[&ptr](uint8_t nibble)
{
if (nibble < 10)
*ptr++ = '0' + nibble;
else
*ptr++ = 'A' + nibble - 10;
};
const auto append_hex_byte =
[&append_hex_nibble](uint8_t byte)
{
append_hex_nibble(byte >> 4);
append_hex_nibble(byte & 0xF);
};
append_hex_byte((component1 >> 24) & 0xFF);
append_hex_byte((component1 >> 16) & 0xFF);
append_hex_byte((component1 >> 8) & 0xFF);
append_hex_byte((component1 >> 0) & 0xFF);
*ptr++ = '-';
append_hex_byte((component2 >> 8) & 0xFF);
append_hex_byte((component2 >> 0) & 0xFF);
*ptr++ = '-';
append_hex_byte((component3 >> 8) & 0xFF);
append_hex_byte((component3 >> 0) & 0xFF);
*ptr++ = '-';
append_hex_byte(component45[0]);
append_hex_byte(component45[1]);
*ptr++ = '-';
append_hex_byte(component45[2]);
append_hex_byte(component45[3]);
append_hex_byte(component45[4]);
append_hex_byte(component45[5]);
append_hex_byte(component45[6]);
append_hex_byte(component45[7]);
*ptr = '\0';
BAN::String guid;
TRY(guid.append(buffer));
return BAN::move(guid);
}
};
static_assert(sizeof(GUID) == 16);

View File

@@ -14,11 +14,17 @@ namespace BAN
struct Entry
{
template<typename... Args>
Entry(const Key& key, Args&&... args)
Entry(const Key& key, Args&&... args) requires is_constructible_v<T, Args...>
: key(key)
, value(forward<Args>(args)...)
{}
template<typename... Args>
Entry(Key&& key, Args&&... args) requires is_constructible_v<T, Args...>
: key(BAN::move(key))
, value(forward<Args>(args)...)
{}
Key key;
T value;
};
@@ -39,10 +45,27 @@ namespace BAN
HashMap<Key, T, HASH>& operator=(const HashMap<Key, T, HASH>&);
HashMap<Key, T, HASH>& operator=(HashMap<Key, T, HASH>&&);
ErrorOr<void> insert(const Key&, const T&);
ErrorOr<void> insert(const Key&, T&&);
ErrorOr<iterator> insert(const Key& key, const T& value) { return emplace(key, value); }
ErrorOr<iterator> insert(const Key& key, T&& value) { return emplace(key, move(value)); }
ErrorOr<iterator> insert(Key&& key, const T& value) { return emplace(move(key), value); }
ErrorOr<iterator> insert(Key&& key, T&& value) { return emplace(move(key), move(value)); }
ErrorOr<iterator> insert_or_assign(const Key& key, const T& value) { return emplace_or_assign(key, value); }
ErrorOr<iterator> insert_or_assign(const Key& key, T&& value) { return emplace_or_assign(key, move(value)); }
ErrorOr<iterator> insert_or_assign(Key&& key, const T& value) { return emplace_or_assign(move(key), value); }
ErrorOr<iterator> insert_or_assign(Key&& key, T&& value) { return emplace_or_assign(move(key), move(value)); }
template<typename... Args>
ErrorOr<void> emplace(const Key&, Args&&...);
ErrorOr<iterator> emplace(const Key& key, Args&&... args) requires is_constructible_v<T, Args...>
{ return emplace(Key(key), forward<Args>(args)...); }
template<typename... Args>
ErrorOr<iterator> emplace(Key&&, Args&&...) requires is_constructible_v<T, Args...>;
template<typename... Args>
ErrorOr<iterator> emplace_or_assign(const Key& key, Args&&... args) requires is_constructible_v<T, Args...>
{ return emplace_or_assign(Key(key), forward<Args>(args)...); }
template<typename... Args>
ErrorOr<iterator> emplace_or_assign(Key&&, Args&&...) requires is_constructible_v<T, Args...>;
iterator begin() { return iterator(m_buckets.end(), m_buckets.begin()); }
iterator end() { return iterator(m_buckets.end(), m_buckets.end()); }
@@ -117,27 +140,36 @@ namespace BAN
}
template<typename Key, typename T, typename HASH>
ErrorOr<void> HashMap<Key, T, HASH>::insert(const Key& key, const T& value)
template<typename... Args>
ErrorOr<typename HashMap<Key, T, HASH>::iterator> HashMap<Key, T, HASH>::emplace(Key&& key, Args&&... args) requires is_constructible_v<T, Args...>
{
return insert(key, move(T(value)));
}
ASSERT(!contains(key));
TRY(rebucket(m_size + 1));
template<typename Key, typename T, typename HASH>
ErrorOr<void> HashMap<Key, T, HASH>::insert(const Key& key, T&& value)
{
return emplace(key, move(value));
auto bucket_it = get_bucket_iterator(key);
TRY(bucket_it->emplace_back(move(key), forward<Args>(args)...));
m_size++;
return iterator(m_buckets.end(), bucket_it, prev(bucket_it->end(), 1));
}
template<typename Key, typename T, typename HASH>
template<typename... Args>
ErrorOr<void> HashMap<Key, T, HASH>::emplace(const Key& key, Args&&... args)
ErrorOr<typename HashMap<Key, T, HASH>::iterator> HashMap<Key, T, HASH>::emplace_or_assign(Key&& key, Args&&... args) requires is_constructible_v<T, Args...>
{
ASSERT(!contains(key));
TRY(rebucket(m_size + 1));
auto& bucket = get_bucket(key);
TRY(bucket.emplace_back(key, forward<Args>(args)...));
m_size++;
return {};
if (empty())
return emplace(move(key), forward<Args>(args)...);
auto bucket_it = get_bucket_iterator(key);
for (auto entry_it = bucket_it->begin(); entry_it != bucket_it->end(); entry_it++)
{
if (entry_it->key != key)
continue;
entry_it->value = T(forward<Args>(args)...);
return iterator(m_buckets.end(), bucket_it, entry_it);
}
return emplace(move(key), forward<Args>(args)...);
}
template<typename Key, typename T, typename HASH>
@@ -177,7 +209,7 @@ namespace BAN
for (Entry& entry : bucket)
if (entry.key == key)
return entry.value;
ASSERT(false);
ASSERT_NOT_REACHED();
}
template<typename Key, typename T, typename HASH>
@@ -188,7 +220,7 @@ namespace BAN
for (const Entry& entry : bucket)
if (entry.key == key)
return entry.value;
ASSERT(false);
ASSERT_NOT_REACHED();
}
template<typename Key, typename T, typename HASH>

89
BAN/include/BAN/Heap.h Normal file
View File

@@ -0,0 +1,89 @@
#pragma once
#include <BAN/Iterators.h>
#include <BAN/Swap.h>
#include <BAN/Traits.h>
namespace BAN
{
namespace detail
{
template<typename It, typename Comp>
void heapify_up(It begin, size_t index, Comp comp)
{
size_t parent = (index - 1) / 2;
while (parent < index)
{
if (comp(*(begin + index), *(begin + parent)))
break;
swap(*(begin + parent), *(begin + index));
index = parent;
parent = (index - 1) / 2;
}
}
template<typename It, typename Comp>
void heapify_down(It begin, size_t index, size_t len, Comp comp)
{
for (;;)
{
const size_t lchild = 2 * index + 1;
const size_t rchild = 2 * index + 2;
size_t child = 0;
if (lchild < len && !comp(*(begin + lchild), *(begin + index)))
{
if (rchild < len && !comp(*(begin + rchild), *(begin + lchild)))
child = rchild;
else
child = lchild;
}
else if (rchild < len && !comp(*(begin + rchild), *(begin + index)))
child = rchild;
else
break;
swap(*(begin + child), *(begin + index));
index = child;
}
}
}
template<typename It, typename Comp = less<it_value_type_t<It>>>
void make_heap(It begin, It end, Comp comp = {})
{
const size_t len = distance(begin, end);
if (len <= 1)
return;
size_t index = (len - 2) / 2;
while (index < len)
detail::heapify_down(begin, index--, len, comp);
}
template<typename It, typename Comp = less<it_value_type_t<It>>>
void push_heap(It begin, It end, Comp comp = {})
{
const size_t len = distance(begin, end);
detail::heapify_up(begin, len - 1, comp);
}
template<typename It, typename Comp = less<it_value_type_t<It>>>
void pop_heap(It begin, It end, Comp comp = {})
{
const size_t len = distance(begin, end);
swap(*begin, *(begin + len - 1));
detail::heapify_down(begin, 0, len - 1, comp);
}
template<typename It, typename Comp = less<it_value_type_t<It>>>
void sort_heap(It begin, It end, Comp comp = {})
{
while (begin != end)
pop_heap(begin, end--, comp);
}
}

View File

@@ -9,6 +9,10 @@ namespace BAN
struct IPv4Address
{
constexpr IPv4Address()
: IPv4Address(0)
{ }
constexpr IPv4Address(uint32_t u32_address)
{
raw = u32_address;

View File

@@ -9,7 +9,7 @@ namespace BAN
{
template<typename It>
It next(It it, size_t count)
constexpr It next(It it, size_t count)
{
for (size_t i = 0; i < count; i++)
++it;
@@ -18,13 +18,13 @@ namespace BAN
template<typename It>
requires requires(It it, size_t n) { requires is_same_v<decltype(it + n), It>; }
It next(It it, size_t count)
constexpr It next(It it, size_t count)
{
return it + count;
}
template<typename It>
It prev(It it, size_t count)
constexpr It prev(It it, size_t count)
{
for (size_t i = 0; i < count; i++)
--it;
@@ -33,13 +33,13 @@ namespace BAN
template<typename It>
requires requires(It it, size_t n) { requires is_same_v<decltype(it - n), It>; }
It prev(It it, size_t count)
constexpr It prev(It it, size_t count)
{
return it - count;
}
template<typename It>
size_t distance(It it1, It it2)
constexpr size_t distance(It it1, It it2)
{
size_t dist = 0;
while (it1 != it2)
@@ -52,7 +52,7 @@ namespace BAN
template<typename It>
requires requires(It it1, It it2) { requires is_integral_v<decltype(it2 - it1)>; }
size_t distance(It it1, It it2)
constexpr size_t distance(It it1, It it2)
{
return it2 - it1;
}
@@ -64,109 +64,109 @@ namespace BAN
using value_type = T;
public:
IteratorSimpleGeneral() = default;
constexpr IteratorSimpleGeneral() = default;
template<bool CONST2, typename = enable_if_t<CONST2 == CONST || CONST>>
IteratorSimpleGeneral(const IteratorSimpleGeneral<T, Container, CONST2>& other)
constexpr IteratorSimpleGeneral(const IteratorSimpleGeneral<T, Container, CONST2>& other)
: m_pointer(other.m_pointer)
, m_valid(other.m_valid)
{
}
const T& operator*() const
constexpr const T& operator*() const
{
ASSERT(m_pointer);
return *m_pointer;
}
template<bool CONST2 = CONST>
enable_if_t<!CONST2, T&> operator*()
constexpr enable_if_t<!CONST2, T&> operator*()
{
ASSERT(*this);
ASSERT(m_pointer);
return *m_pointer;
}
const T* operator->() const
constexpr const T* operator->() const
{
ASSERT(*this);
ASSERT(m_pointer);
return m_pointer;
}
template<bool CONST2 = CONST>
enable_if_t<!CONST2, T*> operator->()
constexpr enable_if_t<!CONST2, T*> operator->()
{
ASSERT(*this);
ASSERT(m_pointer);
return m_pointer;
}
IteratorSimpleGeneral& operator++()
constexpr IteratorSimpleGeneral& operator++()
{
ASSERT(*this);
ASSERT(m_pointer);
++m_pointer;
return *this;
}
IteratorSimpleGeneral operator++(int)
constexpr IteratorSimpleGeneral operator++(int)
{
auto temp = *this;
++(*this);
return temp;
}
IteratorSimpleGeneral& operator--()
constexpr IteratorSimpleGeneral& operator--()
{
ASSERT(*this);
ASSERT(m_pointer);
--m_pointer;
return *this;
}
IteratorSimpleGeneral operator--(int)
constexpr IteratorSimpleGeneral operator--(int)
{
auto temp = *this;
--(*this);
return temp;
}
size_t operator-(const IteratorSimpleGeneral& other) const
constexpr size_t operator-(const IteratorSimpleGeneral& other) const
{
ASSERT(*this && other);
return m_pointer - other.m_pointer;
}
IteratorSimpleGeneral operator+(size_t offset) const
constexpr IteratorSimpleGeneral operator+(size_t offset) const
{
return IteratorSimpleGeneral(m_pointer + offset);
}
IteratorSimpleGeneral operator-(size_t offset) const
constexpr IteratorSimpleGeneral operator-(size_t offset) const
{
return IteratorSimpleGeneral(m_pointer - offset);
}
bool operator<(const IteratorSimpleGeneral& other) const
constexpr bool operator<(const IteratorSimpleGeneral& other) const
{
ASSERT(*this);
return m_pointer < other.m_pointer;
}
bool operator==(const IteratorSimpleGeneral& other) const
constexpr bool operator==(const IteratorSimpleGeneral& other) const
{
ASSERT(*this);
return m_pointer == other.m_pointer;
}
bool operator!=(const IteratorSimpleGeneral& other) const
constexpr bool operator!=(const IteratorSimpleGeneral& other) const
{
ASSERT(*this);
return !(*this == other);
}
explicit operator bool() const
constexpr explicit operator bool() const
{
return m_valid;
}
private:
IteratorSimpleGeneral(maybe_const_t<CONST, T>* pointer)
constexpr IteratorSimpleGeneral(maybe_const_t<CONST, T>* pointer)
: m_pointer(pointer)
, m_valid(true)
{
@@ -193,16 +193,16 @@ namespace BAN
using value_type = T;
public:
IteratorDoubleGeneral() = default;
constexpr IteratorDoubleGeneral() = default;
template<bool CONST2, typename = enable_if_t<CONST2 == CONST || CONST>>
IteratorDoubleGeneral(const IteratorDoubleGeneral<T, OuterContainer, InnerContainer, Container, CONST2>& other)
constexpr IteratorDoubleGeneral(const IteratorDoubleGeneral<T, OuterContainer, InnerContainer, Container, CONST2>& other)
: m_outer_end(other.m_outer_end)
, m_outer_current(other.m_outer_current)
, m_inner_current(other.m_inner_current)
{
}
const T& operator*() const
constexpr const T& operator*() const
{
ASSERT(*this);
ASSERT(m_outer_current != m_outer_end);
@@ -210,7 +210,7 @@ namespace BAN
return m_inner_current.operator*();
}
template<bool CONST2 = CONST>
enable_if_t<!CONST2, T&> operator*()
constexpr enable_if_t<!CONST2, T&> operator*()
{
ASSERT(*this);
ASSERT(m_outer_current != m_outer_end);
@@ -218,7 +218,7 @@ namespace BAN
return m_inner_current.operator*();
}
const T* operator->() const
constexpr const T* operator->() const
{
ASSERT(*this);
ASSERT(m_outer_current != m_outer_end);
@@ -226,7 +226,7 @@ namespace BAN
return m_inner_current.operator->();
}
template<bool CONST2 = CONST>
enable_if_t<!CONST2, T*> operator->()
constexpr enable_if_t<!CONST2, T*> operator->()
{
ASSERT(*this);
ASSERT(m_outer_current != m_outer_end);
@@ -234,7 +234,7 @@ namespace BAN
return m_inner_current.operator->();
}
IteratorDoubleGeneral& operator++()
constexpr IteratorDoubleGeneral& operator++()
{
ASSERT(*this);
ASSERT(m_outer_current != m_outer_end);
@@ -243,14 +243,14 @@ namespace BAN
find_valid_or_end();
return *this;
}
IteratorDoubleGeneral operator++(int)
constexpr IteratorDoubleGeneral operator++(int)
{
auto temp = *this;
++(*this);
return temp;
}
bool operator==(const IteratorDoubleGeneral& other) const
constexpr bool operator==(const IteratorDoubleGeneral& other) const
{
ASSERT(*this && other);
if (m_outer_end != other.m_outer_end)
@@ -262,18 +262,18 @@ namespace BAN
ASSERT(m_inner_current && other.m_inner_current);
return m_inner_current == other.m_inner_current;
}
bool operator!=(const IteratorDoubleGeneral& other) const
constexpr bool operator!=(const IteratorDoubleGeneral& other) const
{
return !(*this == other);
}
explicit operator bool() const
constexpr explicit operator bool() const
{
return !!m_outer_current;
}
private:
IteratorDoubleGeneral(const OuterIterator& outer_end, const OuterIterator& outer_current)
constexpr IteratorDoubleGeneral(const OuterIterator& outer_end, const OuterIterator& outer_current)
: m_outer_end(outer_end)
, m_outer_current(outer_current)
{
@@ -284,7 +284,7 @@ namespace BAN
}
}
IteratorDoubleGeneral(const OuterIterator& outer_end, const OuterIterator& outer_current, const InnerIterator& inner_current)
constexpr IteratorDoubleGeneral(const OuterIterator& outer_end, const OuterIterator& outer_current, const InnerIterator& inner_current)
: m_outer_end(outer_end)
, m_outer_current(outer_current)
, m_inner_current(inner_current)
@@ -292,7 +292,7 @@ namespace BAN
find_valid_or_end();
}
void find_valid_or_end()
constexpr void find_valid_or_end()
{
while (m_inner_current == m_outer_current->end())
{
@@ -303,8 +303,8 @@ namespace BAN
}
}
OuterIterator outer_current() { return m_outer_current; }
InnerIterator inner_current() { return m_inner_current; }
constexpr OuterIterator outer_current() { return m_outer_current; }
constexpr InnerIterator inner_current() { return m_inner_current; }
private:
OuterIterator m_outer_end;

View File

@@ -34,9 +34,9 @@ namespace BAN
ErrorOr<void> insert(iterator, const T&);
ErrorOr<void> insert(iterator, T&&);
template<typename... Args>
ErrorOr<void> emplace_back(Args&&...);
ErrorOr<void> emplace_back(Args&&...) requires is_constructible_v<T, Args...>;
template<typename... Args>
ErrorOr<void> emplace(iterator, Args&&...);
ErrorOr<void> emplace(iterator, Args&&...) requires is_constructible_v<T, Args...>;
void pop_back();
iterator remove(iterator);
@@ -196,14 +196,14 @@ namespace BAN
template<typename T>
template<typename... Args>
ErrorOr<void> LinkedList<T>::emplace_back(Args&&... args)
ErrorOr<void> LinkedList<T>::emplace_back(Args&&... args) requires is_constructible_v<T, Args...>
{
return emplace(end(), forward<Args>(args)...);
}
template<typename T>
template<typename... Args>
ErrorOr<void> LinkedList<T>::emplace(iterator iter, Args&&... args)
ErrorOr<void> LinkedList<T>::emplace(iterator iter, Args&&... args) requires is_constructible_v<T, Args...>
{
Node* new_node = TRY(allocate_node(forward<Args>(args)...));
insert_node(iter, new_node);

View File

@@ -1,17 +1,18 @@
#pragma once
#include <BAN/Limits.h>
#include <BAN/Numbers.h>
#include <BAN/Traits.h>
#include <stddef.h>
#include <stdint.h>
#include <float.h>
namespace BAN::Math
{
template<typename T>
inline constexpr T abs(T val)
inline constexpr T abs(T x)
{
return val < 0 ? -val : val;
return x < 0 ? -x : x;
}
template<typename T>
@@ -35,12 +36,11 @@ namespace BAN::Math
template<integral T>
inline constexpr T gcd(T a, T b)
{
T t;
while (b)
{
t = b;
T temp = b;
b = a % b;
a = t;
a = temp;
}
return a;
}
@@ -58,65 +58,408 @@ namespace BAN::Math
}
template<integral T>
inline constexpr bool is_power_of_two(T value)
inline constexpr bool is_power_of_two(T x)
{
if (value == 0)
if (x == 0)
return false;
return (value & (value - 1)) == 0;
return (x & (x - 1)) == 0;
}
template<integral T>
__attribute__((always_inline))
inline constexpr bool will_multiplication_overflow(T a, T b)
{
T dummy;
return __builtin_mul_overflow(a, b, &dummy);
}
template<integral T>
__attribute__((always_inline))
inline constexpr bool will_addition_overflow(T a, T b)
{
T dummy;
return __builtin_add_overflow(a, b, &dummy);
}
template<typename T>
requires is_same_v<T, unsigned int> || is_same_v<T, unsigned long> || is_same_v<T, unsigned long long>
inline constexpr T ilog2(T value)
inline constexpr T ilog2(T x)
{
if constexpr(is_same_v<T, unsigned int>)
return sizeof(T) * 8 - __builtin_clz(value) - 1;
return sizeof(T) * 8 - __builtin_clz(x) - 1;
if constexpr(is_same_v<T, unsigned long>)
return sizeof(T) * 8 - __builtin_clzl(value) - 1;
return sizeof(T) * 8 - __builtin_clzll(value) - 1;
return sizeof(T) * 8 - __builtin_clzl(x) - 1;
return sizeof(T) * 8 - __builtin_clzll(x) - 1;
}
// This is ugly but my clangd does not like including
// intrinsic headers at all
#if !defined(__SSE__) || !defined(__SSE2__)
#pragma GCC push_options
#ifndef __SSE__
#pragma GCC target("sse")
#endif
#ifndef __SSE2__
#pragma GCC target("sse2")
#endif
#define BAN_MATH_POP_OPTIONS
#endif
template<floating_point T>
inline constexpr T floor(T x)
{
if constexpr(is_same_v<T, float>)
return __builtin_floorf(x);
if constexpr(is_same_v<T, double>)
return __builtin_floor(x);
if constexpr(is_same_v<T, long double>)
return __builtin_floorl(x);
}
template<floating_point T>
inline constexpr T log2(T value)
inline constexpr T ceil(T x)
{
T result;
asm volatile("fyl2x" : "=t"(result) : "0"(value), "u"((T)1.0) : "st(1)");
return result;
if constexpr(is_same_v<T, float>)
return __builtin_ceilf(x);
if constexpr(is_same_v<T, double>)
return __builtin_ceil(x);
if constexpr(is_same_v<T, long double>)
return __builtin_ceill(x);
}
template<floating_point T>
inline constexpr T log10(T value)
inline constexpr T round(T x)
{
constexpr T INV_LOG_2_10 = 0.3010299956639811952137388947244930267681898814621085413104274611;
T result;
asm volatile("fyl2x" : "=t"(result) : "0"(value), "u"(INV_LOG_2_10) : "st(1)");
return result;
if (x == (T)0.0)
return x;
if (x > (T)0.0)
return floor<T>(x + (T)0.5);
return ceil<T>(x - (T)0.5);
}
template<floating_point T>
inline constexpr T log(T value, T base)
inline constexpr T trunc(T x)
{
return log2(value) / log2(base);
if constexpr(is_same_v<T, float>)
return __builtin_truncf(x);
if constexpr(is_same_v<T, double>)
return __builtin_trunc(x);
if constexpr(is_same_v<T, long double>)
return __builtin_truncl(x);
}
template<floating_point T>
inline constexpr T pow(T base, T exp)
inline constexpr T rint(T x)
{
T result;
asm volatile(
"fyl2x;"
asm("frndint" : "+t"(x));
return x;
}
template<floating_point T>
inline constexpr T fmod(T a, T b)
{
asm(
"1:"
"fprem;"
"fnstsw %%ax;"
"testb $4, %%ah;"
"jne 1b;"
: "+t"(a)
: "u"(b)
: "ax", "cc"
);
return a;
}
template<floating_point T>
inline constexpr T remainder(T a, T b)
{
asm(
"1:"
"fprem1;"
"fnstsw %%ax;"
"testb $4, %%ah;"
"jne 1b;"
: "+t"(a)
: "u"(b)
: "ax", "cc"
);
return a;
}
template<floating_point T>
static T modf(T x, T* iptr)
{
const T frac = BAN::Math::fmod<T>(x, (T)1.0);
*iptr = x - frac;
return frac;
}
template<floating_point T>
inline constexpr T frexp(T num, int* exp)
{
if (num == (T)0.0)
{
*exp = 0;
return (T)0.0;
}
T e;
asm("fxtract" : "+t"(num), "=u"(e));
*exp = (int)e + 1;
return num / (T)2.0;
}
template<floating_point T>
inline constexpr T copysign(T x, T y)
{
if ((x < (T)0.0) != (y < (T)0.0))
x = -x;
return x;
}
namespace detail
{
template<floating_point T>
inline constexpr T fyl2x(T x, T y)
{
asm("fyl2x" : "+t"(x) : "u"(y) : "st(1)");
return x;
}
}
template<floating_point T>
inline constexpr T log(T x)
{
return detail::fyl2x<T>(x, numbers::ln2_v<T>);
}
template<floating_point T>
inline constexpr T log2(T x)
{
return detail::fyl2x<T>(x, 1.0);
}
template<floating_point T>
inline constexpr T log10(T x)
{
return detail::fyl2x<T>(x, numbers::lg2_v<T>);
}
template<floating_point T>
inline constexpr T logb(T x)
{
static_assert(FLT_RADIX == 2);
return log2<T>(x);
}
template<floating_point T>
inline constexpr T exp2(T x)
{
if (abs(x) <= (T)1.0)
{
asm("f2xm1" : "+t"(x));
return x + (T)1.0;
}
asm(
"fld1;"
"fld %%st(1);"
"fprem;"
"f2xm1;"
"faddp;"
"fscale;"
"fxch %%st(1);"
"fstp %%st;"
: "=t"(result)
: "0"(base), "u"(exp)
"fstp %%st(1);"
: "+t"(x)
);
return result;
return x;
}
template<floating_point T>
inline constexpr T exp(T x)
{
return exp2<T>(x * numbers::log2e_v<T>);
}
template<floating_point T>
inline constexpr T pow(T x, T y)
{
if (x == (T)0.0)
return (T)0.0;
return exp2<T>(y * log2<T>(x));
}
template<floating_point T>
inline constexpr T scalbn(T x, int n)
{
asm("fscale" : "+t"(x) : "u"(static_cast<T>(n)));
return x;
}
template<floating_point T>
inline constexpr T ldexp(T x, int y)
{
const bool exp_sign = y < 0;
if (exp_sign)
y = -y;
T exp = (T)1.0;
T mult = (T)2.0;
while (y)
{
if (y & 1)
exp *= mult;
mult *= mult;
y >>= 1;
}
if (exp_sign)
exp = (T)1.0 / exp;
return x * exp;
}
template<floating_point T>
inline constexpr T sqrt(T x)
{
if constexpr(BAN::is_same_v<T, float>)
{
using v4sf = float __attribute__((vector_size(16)));
return __builtin_ia32_sqrtss((v4sf) { x, 0.0f, 0.0f, 0.0f })[0];
}
else if constexpr(BAN::is_same_v<T, double>)
{
using v2df = double __attribute__((vector_size(16)));
return __builtin_ia32_sqrtsd((v2df) { x, 0.0 })[0];
}
else if constexpr(BAN::is_same_v<T, long double>)
{
asm("fsqrt" : "+t"(x));
return x;
}
}
template<floating_point T>
inline constexpr T cbrt(T value)
{
return pow<T>(value, (T)1.0 / (T)3.0);
}
template<floating_point T>
inline constexpr T sin(T x)
{
asm("fsin" : "+t"(x));
return x;
}
template<floating_point T>
inline constexpr T cos(T x)
{
asm("fcos" : "+t"(x));
return x;
}
template<floating_point T>
inline constexpr void sincos(T x, T& sin, T& cos)
{
asm("fsincos" : "=t"(cos), "=u"(sin) : "0"(x));
}
template<floating_point T>
inline constexpr T tan(T x)
{
T one, ret;
asm("fptan" : "=t"(one), "=u"(ret) : "0"(x));
return ret;
}
template<floating_point T>
inline constexpr T atan2(T y, T x)
{
asm("fpatan" : "+t"(x) : "u"(y) : "st(1)");
return x;
}
template<floating_point T>
inline constexpr T atan(T x)
{
return atan2<T>(x, (T)1.0);
}
template<floating_point T>
inline constexpr T asin(T x)
{
if (x == (T)0.0)
return (T)0.0;
if (x == (T)1.0)
return +numbers::pi_v<T> / (T)2.0;
if (x == (T)-1.0)
return -numbers::pi_v<T> / (T)2.0;
return (T)2.0 * atan<T>(x / ((T)1.0 + sqrt<T>((T)1.0 - x * x)));
}
template<floating_point T>
inline constexpr T acos(T x)
{
if (x == (T)0.0)
return numbers::pi_v<T> / (T)2.0;
if (x == (T)1.0)
return (T)0.0;
if (x == (T)-1.0)
return numbers::pi_v<T>;
return (T)2.0 * atan<T>(sqrt<T>((T)1.0 - x * x) / ((T)1.0 + x));
}
template<floating_point T>
inline constexpr T sinh(T x)
{
return (exp<T>(x) - exp<T>(-x)) / (T)2.0;
}
template<floating_point T>
inline constexpr T cosh(T x)
{
return (exp<T>(x) + exp<T>(-x)) / (T)2.0;
}
template<floating_point T>
inline constexpr T tanh(T x)
{
const T exp_px = exp<T>(+x);
const T exp_nx = exp<T>(-x);
return (exp_px - exp_nx) / (exp_px + exp_nx);
}
template<floating_point T>
inline constexpr T asinh(T x)
{
return log<T>(x + sqrt<T>(x * x + (T)1.0));
}
template<floating_point T>
inline constexpr T acosh(T x)
{
return log<T>(x + sqrt<T>(x * x - (T)1.0));
}
template<floating_point T>
inline constexpr T atanh(T x)
{
return (T)0.5 * log<T>(((T)1.0 + x) / ((T)1.0 - x));
}
template<floating_point T>
inline constexpr T hypot(T x, T y)
{
return sqrt<T>(x * x + y * y);
}
#ifdef BAN_MATH_POP_OPTIONS
#undef BAN_MATH_POP_OPTIONS
#pragma GCC pop_options
#endif
}

View File

@@ -9,10 +9,12 @@
namespace BAN
{
#if defined(__is_kernel)
static constexpr void*(&allocator)(size_t) = kmalloc;
static constexpr void(&deallocator)(void*) = kfree;
static constexpr void*(*allocator)(size_t) = kmalloc;
static constexpr void*(*reallocator)(void*, size_t) = nullptr;
static constexpr void(*deallocator)(void*) = kfree;
#else
static constexpr void*(&allocator)(size_t) = malloc;
static constexpr void(&deallocator)(void*) = free;
static constexpr void*(*allocator)(size_t) = malloc;
static constexpr void*(*reallocator)(void*, size_t) = realloc;
static constexpr void(*deallocator)(void*) = free;
#endif
}

28
BAN/include/BAN/Numbers.h Normal file
View File

@@ -0,0 +1,28 @@
#pragma once
#include <BAN/Traits.h>
namespace BAN::numbers
{
template<floating_point T> inline constexpr T e_v = 2.71828182845904523536;
template<floating_point T> inline constexpr T log2e_v = 1.44269504088896340736;
template<floating_point T> inline constexpr T lge_v = 0.43429448190325182765;
template<floating_point T> inline constexpr T lg2_v = 0.30102999566398119521;
template<floating_point T> inline constexpr T ln2_v = 0.69314718055994530942;
template<floating_point T> inline constexpr T ln10_v = 2.30258509299404568402;
template<floating_point T> inline constexpr T pi_v = 3.14159265358979323846;
template<floating_point T> inline constexpr T sqrt2_v = 1.41421356237309504880;
template<floating_point T> inline constexpr T sqrt3_v = 1.73205080756887729353;
inline constexpr double e = e_v<double>;
inline constexpr double log2e = log2e_v<double>;
inline constexpr double lge = lge_v<double>;
inline constexpr double lg2 = lge_v<double>;
inline constexpr double ln2 = ln2_v<double>;
inline constexpr double ln10 = ln10_v<double>;
inline constexpr double pi = pi_v<double>;
inline constexpr double sqrt2 = sqrt2_v<double>;
inline constexpr double sqrt3 = sqrt3_v<double>;
}

View File

@@ -13,48 +13,48 @@ namespace BAN
class Optional
{
public:
Optional();
Optional(Optional&&);
Optional(const Optional&);
Optional(const T&);
Optional(T&&);
template<typename... Args>
Optional(Args&&...);
constexpr Optional();
constexpr Optional(Optional&&);
constexpr Optional(const Optional&);
constexpr Optional(const T&);
constexpr Optional(T&&);
~Optional();
Optional& operator=(Optional&&);
Optional& operator=(const Optional&);
constexpr Optional& operator=(Optional&&);
constexpr Optional& operator=(const Optional&);
template<typename... Args>
Optional& emplace(Args&&...);
constexpr Optional& emplace(Args&&...) requires is_constructible_v<T, Args...>;
T* operator->();
const T* operator->() const;
constexpr T* operator->();
constexpr const T* operator->() const;
T& operator*();
const T& operator*() const;
constexpr T& operator*();
constexpr const T& operator*() const;
bool has_value() const;
constexpr bool has_value() const;
T release_value();
T& value();
const T& value() const;
constexpr T release_value();
constexpr T& value();
constexpr const T& value() const;
constexpr T& value_or(T&);
constexpr const T& value_or(const T&) const;
void clear();
constexpr void clear();
private:
alignas(T) uint8_t m_storage[sizeof(T)];
alignas(T) uint8_t m_storage[sizeof(T)] {};
bool m_has_value { false };
};
template<typename T>
Optional<T>::Optional()
constexpr Optional<T>::Optional()
: m_has_value(false)
{}
template<typename T>
Optional<T>::Optional(Optional<T>&& other)
constexpr Optional<T>::Optional(Optional<T>&& other)
: m_has_value(other.has_value())
{
if (other.has_value())
@@ -62,7 +62,7 @@ namespace BAN
}
template<typename T>
Optional<T>::Optional(const Optional<T>& other)
constexpr Optional<T>::Optional(const Optional<T>& other)
: m_has_value(other.has_value())
{
if (other.has_value())
@@ -70,27 +70,19 @@ namespace BAN
}
template<typename T>
Optional<T>::Optional(const T& value)
constexpr Optional<T>::Optional(const T& value)
: m_has_value(true)
{
new (m_storage) T(value);
}
template<typename T>
Optional<T>::Optional(T&& value)
constexpr Optional<T>::Optional(T&& value)
: m_has_value(true)
{
new (m_storage) T(move(value));
}
template<typename T>
template<typename... Args>
Optional<T>::Optional(Args&&... args)
: m_has_value(true)
{
new (m_storage) T(forward<Args>(args)...);
}
template<typename T>
Optional<T>::~Optional()
{
@@ -98,7 +90,7 @@ namespace BAN
}
template<typename T>
Optional<T>& Optional<T>::operator=(Optional&& other)
constexpr Optional<T>& Optional<T>::operator=(Optional&& other)
{
clear();
m_has_value = other.has_value();
@@ -108,18 +100,18 @@ namespace BAN
}
template<typename T>
Optional<T>& Optional<T>::operator=(const Optional& other)
constexpr Optional<T>& Optional<T>::operator=(const Optional& other)
{
clear();
m_has_value = other.has_value();
if (other.has_value)
if (other.has_value())
new (m_storage) T(other.value());
return *this;
}
template<typename T>
template<typename... Args>
Optional<T>& Optional<T>::emplace(Args&&... args)
constexpr Optional<T>& Optional<T>::emplace(Args&&... args) requires is_constructible_v<T, Args...>
{
clear();
m_has_value = true;
@@ -128,41 +120,41 @@ namespace BAN
}
template<typename T>
T* Optional<T>::operator->()
constexpr T* Optional<T>::operator->()
{
ASSERT(has_value());
return &value();
}
template<typename T>
const T* Optional<T>::operator->() const
constexpr const T* Optional<T>::operator->() const
{
ASSERT(has_value());
return &value();
}
template<typename T>
T& Optional<T>::operator*()
constexpr T& Optional<T>::operator*()
{
ASSERT(has_value());
return value();
}
template<typename T>
const T& Optional<T>::operator*() const
constexpr const T& Optional<T>::operator*() const
{
ASSERT(has_value());
return value();
}
template<typename T>
bool Optional<T>::has_value() const
constexpr bool Optional<T>::has_value() const
{
return m_has_value;
}
template<typename T>
T Optional<T>::release_value()
constexpr T Optional<T>::release_value()
{
ASSERT(has_value());
T released_value = move(value());
@@ -172,21 +164,37 @@ namespace BAN
}
template<typename T>
T& Optional<T>::value()
constexpr T& Optional<T>::value()
{
ASSERT(has_value());
return (T&)m_storage;
return *reinterpret_cast<T*>(&m_storage);
}
template<typename T>
const T& Optional<T>::value() const
constexpr const T& Optional<T>::value() const
{
ASSERT(has_value());
return (const T&)m_storage;
return *reinterpret_cast<const T*>(&m_storage);
}
template<typename T>
void Optional<T>::clear()
constexpr T& Optional<T>::value_or(T& empty)
{
if (!has_value())
return empty;
return value();
}
template<typename T>
constexpr const T& Optional<T>::value_or(const T& empty) const
{
if (!has_value())
return empty;
return value();
}
template<typename T>
constexpr void Optional<T>::clear()
{
if (m_has_value)
value().~T();

View File

@@ -1,6 +1,10 @@
#pragma once
#if __has_include(<new>)
#include <new>
#else
#include <stddef.h>
inline void* operator new(size_t, void* addr) { return addr; }
inline void* operator new[](size_t, void* addr) { return addr; }
#endif

View File

@@ -0,0 +1,64 @@
#pragma once
#include "BAN/Errors.h"
#include <BAN/Vector.h>
#include <BAN/Heap.h>
namespace BAN
{
template<typename T, typename Comp = less<T>>
class PriorityQueue
{
public:
PriorityQueue() = default;
PriorityQueue(Comp comp)
: m_comp(comp)
{ }
ErrorOr<void> push(const T& value)
{
TRY(m_data.push_back(value));
push_heap(m_data.begin(), m_data.end());
return {};
}
ErrorOr<void> push(T&& value)
{
TRY(m_data.push_back(move(value)));
push_heap(m_data.begin(), m_data.end());
return {};
}
template<typename... Args>
ErrorOr<void> emplace(Args&&... args) requires is_constructible_v<T, Args...>
{
TRY(m_data.emplace_back(forward<Args>(args)...));
push_heap(m_data.begin(), m_data.end());
return {};
}
void pop()
{
pop_heap(m_data.begin(), m_data.end());
m_data.pop_back();
}
BAN::ErrorOr<void> reserve(Vector<T>::size_type size)
{
return m_data.reserve(size);
}
T& top() { return m_data.front(); }
const T& top() const { return m_data.front(); }
bool empty() const { return m_data.empty(); }
Vector<T>::size_type size() const { return m_data.size(); }
Vector<T>::size_type capacity() const { return m_data.capacity(); }
private:
Comp m_comp;
Vector<T> m_data;
};
}

View File

@@ -31,7 +31,7 @@ namespace BAN
ErrorOr<void> push(T&&);
ErrorOr<void> push(const T&);
template<typename... Args>
ErrorOr<void> emplace(Args&&...);
ErrorOr<void> emplace(Args&&...) requires is_constructible_v<T, Args...>;
ErrorOr<void> reserve(size_type);
ErrorOr<void> shrink_to_fit();
@@ -131,7 +131,7 @@ namespace BAN
template<typename T>
template<typename... Args>
ErrorOr<void> Queue<T>::emplace(Args&&... args)
ErrorOr<void> Queue<T>::emplace(Args&&... args) requires is_constructible_v<T, Args...>
{
TRY(ensure_capacity(m_size + 1));
new (m_data + m_size) T(forward<Args>(args)...);

View File

@@ -1,5 +1,6 @@
#pragma once
#include <BAN/Atomic.h>
#include <BAN/Errors.h>
#include <BAN/Move.h>
#include <BAN/NoCopyMove.h>
@@ -22,24 +23,36 @@ namespace BAN
void ref() const
{
ASSERT(m_ref_count > 0);
m_ref_count++;
uint32_t old = m_ref_count.fetch_add(1, MemoryOrder::memory_order_relaxed);
ASSERT(old > 0);
}
bool try_ref() const
{
uint32_t expected = m_ref_count.load(MemoryOrder::memory_order_relaxed);
for (;;)
{
if (expected == 0)
return false;
if (m_ref_count.compare_exchange(expected, expected + 1, MemoryOrder::memory_order_acquire))
return true;
}
}
void unref() const
{
ASSERT(m_ref_count > 0);
m_ref_count--;
if (m_ref_count == 0)
delete (const T*)this;
uint32_t old = m_ref_count.fetch_sub(1);
ASSERT(old > 0);
if (old == 1)
delete static_cast<const T*>(this);
}
protected:
RefCounted() = default;
~RefCounted() { ASSERT(m_ref_count == 0); }
virtual ~RefCounted() { ASSERT(m_ref_count == 0); }
private:
mutable uint32_t m_ref_count = 1;
mutable Atomic<uint32_t> m_ref_count = 1;
};
template<typename T>
@@ -63,8 +76,9 @@ namespace BAN
return ptr;
}
// NOTE: don't use is_constructible_v<T, Args...> as RefPtr<T> is allowed with friends
template<typename... Args>
static ErrorOr<RefPtr> create(Args&&... args)
static ErrorOr<RefPtr> create(Args&&... args) requires requires(Args&&... args) { T(forward<Args>(args)...); }
{
T* pointer = new T(forward<Args>(args)...);
if (pointer == nullptr)
@@ -124,8 +138,11 @@ namespace BAN
T* operator->() { return ptr(); }
const T* operator->() const { return ptr(); }
bool operator==(RefPtr other) const { return m_pointer == other.m_pointer; }
bool operator!=(RefPtr other) const { return m_pointer != other.m_pointer; }
bool empty() const { return m_pointer == nullptr; }
operator bool() const { return m_pointer; }
explicit operator bool() const { return m_pointer; }
void clear()
{

View File

@@ -1,5 +1,6 @@
#pragma once
#include <BAN/Heap.h>
#include <BAN/Math.h>
#include <BAN/Swap.h>
#include <BAN/Traits.h>
@@ -8,7 +9,7 @@
namespace BAN::sort
{
template<typename It, typename Comp = less<typename It::value_type>>
template<typename It, typename Comp = less<it_value_type_t<It>>>
void exchange_sort(It begin, It end, Comp comp = {})
{
for (It lhs = begin; lhs != end; ++lhs)
@@ -42,7 +43,7 @@ namespace BAN::sort
}
template<typename It, typename Comp = less<typename It::value_type>>
template<typename It, typename Comp = less<it_value_type_t<It>>>
void quick_sort(It begin, It end, Comp comp = {})
{
if (distance(begin, end) <= 1)
@@ -52,14 +53,14 @@ namespace BAN::sort
quick_sort(++mid, end, comp);
}
template<typename It, typename Comp = less<typename It::value_type>>
template<typename It, typename Comp = less<it_value_type_t<It>>>
void insertion_sort(It begin, It end, Comp comp = {})
{
if (distance(begin, end) <= 1)
return;
for (It it1 = next(begin, 1); it1 != end; ++it1)
{
typename It::value_type x = move(*it1);
auto x = move(*it1);
It it2 = it1;
for (; it2 != begin && comp(x, *prev(it2, 1)); --it2)
*it2 = move(*prev(it2, 1));
@@ -67,83 +68,7 @@ namespace BAN::sort
}
}
namespace detail
{
template<typename It, typename Comp>
void push_heap(It begin, size_t hole_index, size_t top_index, typename It::value_type value, Comp comp)
{
size_t parent = (hole_index - 1) / 2;
while (hole_index > top_index && comp(*next(begin, parent), value))
{
*next(begin, hole_index) = move(*next(begin, parent));
hole_index = parent;
parent = (hole_index - 1) / 2;
}
*next(begin, hole_index) = move(value);
}
template<typename It, typename Comp>
void adjust_heap(It begin, size_t hole_index, size_t len, typename It::value_type value, Comp comp)
{
const size_t top_index = hole_index;
size_t child = hole_index;
while (child < (len - 1) / 2)
{
child = 2 * (child + 1);
if (comp(*next(begin, child), *next(begin, child - 1)))
child--;
*next(begin, hole_index) = move(*next(begin, child));
hole_index = child;
}
if (len % 2 == 0 && child == (len - 2) / 2)
{
child = 2 * (child + 1);
*next(begin, hole_index) = move(*next(begin, child - 1));
hole_index = child - 1;
}
push_heap(begin, hole_index, top_index, move(value), comp);
}
}
template<typename It, typename Comp = less<typename It::value_type>>
void make_heap(It begin, It end, Comp comp = {})
{
const size_t len = distance(begin, end);
if (len <= 1)
return;
size_t parent = (len - 2) / 2;
while (true)
{
detail::adjust_heap(begin, parent, len, move(*next(begin, parent)), comp);
if (parent == 0)
break;
parent--;
}
}
template<typename It, typename Comp = less<typename It::value_type>>
void sort_heap(It begin, It end, Comp comp = {})
{
const size_t len = distance(begin, end);
if (len <= 1)
return;
size_t last = len;
while (last > 1)
{
last--;
typename It::value_type x = move(*next(begin, last));
*next(begin, last) = move(*begin);
detail::adjust_heap(begin, 0, last, move(x), comp);
}
}
template<typename It, typename Comp = less<typename It::value_type>>
template<typename It, typename Comp = less<it_value_type_t<It>>>
void heap_sort(It begin, It end, Comp comp = {})
{
make_heap(begin, end, comp);
@@ -167,7 +92,7 @@ namespace BAN::sort
}
template<typename It, typename Comp = less<typename It::value_type>>
template<typename It, typename Comp = less<it_value_type_t<It>>>
void intro_sort(It begin, It end, Comp comp = {})
{
const size_t len = distance(begin, end);
@@ -190,10 +115,10 @@ namespace BAN::sort
}
template<typename It, size_t radix = 256>
requires is_unsigned_v<typename It::value_type> && (radix > 0 && (radix & (radix - 1)) == 0)
requires is_unsigned_v<it_value_type_t<It>> && (radix > 0 && (radix & (radix - 1)) == 0)
BAN::ErrorOr<void> radix_sort(It begin, It end)
{
using value_type = typename It::value_type;
using value_type = it_value_type_t<It>;
const size_t len = distance(begin, end);
if (len <= 1)
@@ -231,7 +156,7 @@ namespace BAN::sort
return {};
}
template<typename It, typename Comp = less<typename It::value_type>>
template<typename It, typename Comp = less<it_value_type_t<It>>>
void sort(It begin, It end, Comp comp = {})
{
return intro_sort(begin, end, comp);

View File

@@ -14,116 +14,75 @@ namespace BAN
public:
using value_type = T;
using size_type = size_t;
using iterator = IteratorSimple<T, Span>;
using const_iterator = ConstIteratorSimple<T, Span>;
using iterator = IteratorSimple<value_type, Span>;
using const_iterator = ConstIteratorSimple<value_type, Span>;
private:
template<typename S>
static inline constexpr bool can_init_from_v = is_same_v<value_type, const S> || is_same_v<value_type, S>;
public:
Span() = default;
Span(T*, size_type);
Span(Span<T>&);
Span(value_type* data, size_type size)
: m_data(data)
, m_size(size)
{ }
template<typename S>
requires(is_same_v<T, const S>)
Span(const Span<S>&);
Span(const Span<S>& other) requires can_init_from_v<S>
: m_data(other.m_data)
, m_size(other.m_size)
{ }
template<typename S>
Span(Span<S>&& other) requires can_init_from_v<S>
: m_data(other.m_data)
, m_size(other.m_size)
{
other.clear();
}
template<typename S>
Span& operator=(const Span<S>& other) requires can_init_from_v<S>
{
m_data = other.m_data;
m_size = other.m_size;
return *this;
}
template<typename S>
Span& operator=(Span<S>&& other) requires can_init_from_v<S>
{
m_data = other.m_data;
m_size = other.m_size;
return *this;
}
iterator begin() { return iterator(m_data); }
iterator end() { return iterator(m_data + m_size); }
const_iterator begin() const { return const_iterator(m_data); }
const_iterator end() const { return const_iterator(m_data + m_size); }
T& operator[](size_type);
const T& operator[](size_type) const;
T* data();
const T* data() const;
bool empty() const;
size_type size() const;
void clear();
Span slice(size_type, size_type = ~size_type(0));
Span<const T> as_const() const { return Span<const T>(m_data, m_size); }
private:
T* m_data = nullptr;
size_type m_size = 0;
};
template<typename T>
Span<T>::Span(T* data, size_type size)
: m_data(data)
, m_size(size)
value_type& operator[](size_type index) const
{
}
template<typename T>
Span<T>::Span(Span& other)
: m_data(other.data())
, m_size(other.size())
{
}
template<typename T>
template<typename S>
requires(is_same_v<T, const S>)
Span<T>::Span(const Span<S>& other)
: m_data(other.data())
, m_size(other.size())
{
}
template<typename T>
T& Span<T>::operator[](size_type index)
{
ASSERT(m_data);
ASSERT(index < m_size);
return m_data[index];
}
template<typename T>
const T& Span<T>::operator[](size_type index) const
{
ASSERT(m_data);
ASSERT(index < m_size);
return m_data[index];
}
template<typename T>
T* Span<T>::data()
value_type* data() const
{
return m_data;
}
template<typename T>
const T* Span<T>::data() const
{
return m_data;
}
bool empty() const { return m_size == 0; }
size_type size() const { return m_size; }
template<typename T>
bool Span<T>::empty() const
{
return m_size == 0;
}
template<typename T>
typename Span<T>::size_type Span<T>::size() const
{
return m_size;
}
template<typename T>
void Span<T>::clear()
void clear()
{
m_data = nullptr;
m_size = 0;
}
template<typename T>
Span<T> Span<T>::slice(size_type start, size_type length)
Span slice(size_type start, size_type length = ~size_type(0)) const
{
ASSERT(m_data);
ASSERT(start <= m_size);
if (length == ~size_type(0))
length = m_size - start;
@@ -131,4 +90,13 @@ namespace BAN
return Span(m_data + start, length);
}
Span<const value_type> as_const() const { return *this; }
private:
value_type* m_data = nullptr;
size_type m_size = 0;
friend class Span<const value_type>;
};
}

View File

@@ -14,6 +14,7 @@ namespace BAN
{
public:
using size_type = size_t;
using value_type = char;
using iterator = IteratorSimple<char, String>;
using const_iterator = ConstIteratorSimple<char, String>;
static constexpr size_type sso_capacity = 15;
@@ -26,10 +27,15 @@ namespace BAN
~String() { clear(); }
template<typename... Args>
static String formatted(const char* format, const Args&... args)
static BAN::ErrorOr<String> formatted(const char* format, Args&&... args)
{
size_type length = 0;
BAN::Formatter::print([&](char) { length++; }, format, BAN::forward<Args>(args)...);
String result;
BAN::Formatter::print([&](char c){ MUST(result.push_back(c)); }, format, args...);
TRY(result.reserve(length));
BAN::Formatter::print([&](char c){ MUST(result.push_back(c)); }, format, BAN::forward<Args>(args)...);
return result;
}
@@ -122,7 +128,7 @@ namespace BAN
void remove(size_type index)
{
ASSERT(index < m_size);
memcpy(data() + index, data() + index + 1, m_size - index);
memmove(data() + index, data() + index + 1, m_size - index);
m_size--;
data()[m_size] = '\0';
}
@@ -347,10 +353,9 @@ namespace BAN::Formatter
{
template<typename F>
void print_argument(F putc, const String& string, const ValueFormat&)
void print_argument(F putc, const String& string, const ValueFormat& format)
{
for (String::size_type i = 0; i < string.size(); i++)
putc(string[i]);
print_argument(putc, string.sv(), format);
}
}

View File

@@ -2,6 +2,7 @@
#include <BAN/Formatter.h>
#include <BAN/ForwardList.h>
#include <BAN/Hash.h>
#include <BAN/Iterators.h>
#include <BAN/Optional.h>
#include <BAN/Vector.h>
@@ -13,43 +14,49 @@ namespace BAN
{
public:
using size_type = size_t;
using value_type = char;
using const_iterator = ConstIteratorSimple<char, StringView>;
public:
StringView() {}
StringView(const String&);
StringView(const char* string, size_type len = -1)
constexpr StringView() {}
constexpr StringView(const char* string, size_type len = -1)
{
if (len == size_type(-1))
len = strlen(string);
for (len = 0; string[len];)
len++;
m_data = string;
m_size = len;
}
StringView(const String&);
const_iterator begin() const { return const_iterator(m_data); }
const_iterator end() const { return const_iterator(m_data + m_size); }
constexpr const_iterator begin() const { return const_iterator(m_data); }
constexpr const_iterator end() const { return const_iterator(m_data + m_size); }
char operator[](size_type index) const
constexpr char operator[](size_type index) const
{
ASSERT(index < m_size);
return m_data[index];
}
bool operator==(StringView other) const
constexpr bool operator==(StringView other) const
{
if (m_size != other.m_size)
return false;
return memcmp(m_data, other.m_data, m_size) == 0;
for (size_type i = 0; i < m_size; i++)
if (m_data[i] != other.m_data[i])
return false;
return true;
}
bool operator==(const char* other) const
constexpr bool operator==(const char* other) const
{
if (memcmp(m_data, other, m_size))
for (size_type i = 0; i < m_size; i++)
if (m_data[i] != other[i])
return false;
return other[m_size] == '\0';
}
StringView substring(size_type index, size_type len = -1) const
constexpr StringView substring(size_type index, size_type len = -1) const
{
ASSERT(index <= m_size);
if (len == size_type(-1))
@@ -133,13 +140,13 @@ namespace BAN
return result;
}
char back() const
constexpr char back() const
{
ASSERT(m_size > 0);
return m_data[m_size - 1];
}
char front() const
constexpr char front() const
{
ASSERT(m_size > 0);
return m_data[0];
@@ -161,7 +168,33 @@ namespace BAN
return {};
}
bool contains(char ch) const
BAN::Optional<size_type> rfind(char ch) const
{
for (size_type i = m_size; i > 0; i--)
if (m_data[i - 1] == ch)
return i - 1;
return {};
}
BAN::Optional<size_type> rfind(bool(*comp)(char)) const
{
for (size_type i = m_size; i > 0; i--)
if (comp(m_data[i - 1]))
return i - 1;
return {};
}
constexpr bool starts_with(BAN::StringView target) const
{
if (target.size() > m_size)
return false;
for (size_type i = 0; i < target.size(); i++)
if (m_data[i] != target[i])
return false;
return true;
}
constexpr bool contains(char ch) const
{
for (size_type i = 0; i < m_size; i++)
if (m_data[i] == ch)
@@ -169,7 +202,7 @@ namespace BAN
return false;
}
size_type count(char ch) const
constexpr size_type count(char ch) const
{
size_type result = 0;
for (size_type i = 0; i < m_size; i++)
@@ -178,27 +211,48 @@ namespace BAN
return result;
}
bool empty() const { return m_size == 0; }
size_type size() const { return m_size; }
const char* data() const { return m_data; }
constexpr bool empty() const { return m_size == 0; }
constexpr size_type size() const { return m_size; }
constexpr const char* data() const { return m_data; }
private:
const char* m_data = nullptr;
size_type m_size = 0;
};
template<>
struct hash<StringView>
{
hash_t operator()(StringView string) const
{
constexpr hash_t FNV_offset_basis = 0x811c9dc5;
constexpr hash_t FNV_prime = 0x01000193;
hash_t hash = FNV_offset_basis;
for (StringView::size_type i = 0; i < string.size(); i++)
{
hash *= FNV_prime;
hash ^= (uint8_t)string[i];
}
inline BAN::StringView operator""sv(const char* str, BAN::StringView::size_type len) { return BAN::StringView(str, len); }
return hash;
}
};
}
inline constexpr BAN::StringView operator""_sv(const char* str, BAN::StringView::size_type len) { return BAN::StringView(str, len); }
namespace BAN::Formatter
{
template<typename F>
void print_argument(F putc, const StringView& sv, const ValueFormat&)
void print_argument(F putc, const StringView& sv, const ValueFormat& format)
{
for (StringView::size_type i = 0; i < sv.size(); i++)
putc(sv[i]);
for (int i = sv.size(); i < format.fill; i++)
putc(' ');
}
}

View File

@@ -3,10 +3,10 @@
namespace BAN
{
template<typename T> struct remove_refenrece { using type = T; };
template<typename T> struct remove_refenrece<T&> { using type = T; };
template<typename T> struct remove_refenrece<T&&> { using type = T; };
template<typename T> using remove_reference_t = typename remove_refenrece<T>::type;
template<typename T> struct remove_reference { using type = T; };
template<typename T> struct remove_reference<T&> { using type = T; };
template<typename T> struct remove_reference<T&&> { using type = T; };
template<typename T> using remove_reference_t = typename remove_reference<T>::type;
template<typename T> struct remove_const { using type = T; };
template<typename T> struct remove_const<const T> { using type = T; };
@@ -34,12 +34,15 @@ namespace BAN
template<typename T1, typename T2> struct either_or<true, T1, T2> { using type = T1; };
template<bool B, typename T1, typename T2> using either_or_t = typename either_or<B, T1, T2>::type;
struct true_type { static constexpr bool value = true; };
struct false_type { static constexpr bool value = false; };
template<typename T, T V> struct integral_constant { static constexpr T value = V; };
template<typename T, T V > inline constexpr T integral_constant_v = integral_constant<T, V>::value;
using true_type = integral_constant<bool, true>;
using false_type = integral_constant<bool, false>;
template<typename T, typename S> struct is_same : false_type {};
template<typename T> struct is_same<T, T> : true_type {};
template<typename T, typename S> inline constexpr bool is_same_v = is_same<T, S>::value;
template<typename T, typename S> concept same_as = BAN::is_same_v<T, S>;
template<typename T> struct is_lvalue_reference : false_type {};
template<typename T> struct is_lvalue_reference<T&> : true_type {};
@@ -58,6 +61,9 @@ namespace BAN
template<typename T> struct is_move_constructible { static constexpr bool value = is_constructible_v<T, T&&>; };
template<typename T> inline constexpr bool is_move_constructible_v = is_move_constructible<T>::value;
template<typename T> struct is_trivially_copyable { static constexpr bool value = __is_trivially_copyable(T); };
template<typename T> inline constexpr bool is_trivially_copyable_v = is_trivially_copyable<T>::value;
template<typename T> struct is_integral { static constexpr bool value = requires (T t, T* p, void (*f)(T)) { reinterpret_cast<T>(t); f(0); p + t; }; };
template<typename T> inline constexpr bool is_integral_v = is_integral<T>::value;
template<typename T> concept integral = is_integral_v<T>;
@@ -87,8 +93,8 @@ namespace BAN
template<typename Base, typename Derived> struct is_base_of { static constexpr bool value = __is_base_of(Base, Derived); };
template<typename Base, typename Derived> inline constexpr bool is_base_of_v = is_base_of<Base, Derived>::value;
template<typename T, T V> struct integral_constant { static constexpr T value = V; };
template<typename T, T V > inline constexpr T integral_constant_v = integral_constant<T, V>::value;
template<typename T> struct is_pod { static constexpr bool value = __is_pod(T); };
template<typename T> inline constexpr bool is_pod_v = is_pod<T>::value;
namespace detail
{
@@ -136,6 +142,10 @@ namespace BAN
template<typename T> using make_signed_t = typename make_signed<T>::type;
#undef __BAN_TRAITS_MAKE_SIGNED_CV
template<typename T> struct it_value_type { using value_type = T::value_type; };
template<typename T> struct it_value_type<T*> { using value_type = T; };
template<typename T> using it_value_type_t = typename it_value_type<T>::value_type;
template<typename T> struct less { constexpr bool operator()(const T& lhs, const T& rhs) const { return lhs < rhs; } };
template<typename T> struct equal { constexpr bool operator()(const T& lhs, const T& rhs) const { return lhs == rhs; } };
template<typename T> struct greater { constexpr bool operator()(const T& lhs, const T& rhs) const { return lhs > rhs; } };

View File

@@ -18,23 +18,24 @@ namespace BAN::UTF8
return 3;
if ((first_byte & 0xF8) == 0xF0)
return 4;
return 0;
return UTF8::invalid;
}
constexpr uint32_t to_codepoint(uint8_t* bytes)
template<typename T> requires (sizeof(T) == 1)
constexpr uint32_t to_codepoint(const T* bytes)
{
uint32_t length = byte_length(bytes[0]);
for (uint32_t i = 1; i < length; i++)
if ((bytes[i] & 0xC0) != 0x80)
if (((uint8_t)bytes[i] & 0xC0) != 0x80)
return UTF8::invalid;
switch (length)
{
case 1: return ((bytes[0] & 0x80) != 0x00) ? UTF8::invalid : bytes[0];
case 2: return ((bytes[0] & 0xE0) != 0xC0) ? UTF8::invalid : ((bytes[0] & 0x1F) << 6) | (bytes[1] & 0x3F);
case 3: return ((bytes[0] & 0xF0) != 0xE0) ? UTF8::invalid : ((bytes[0] & 0x0F) << 12) | ((bytes[1] & 0x3F) << 6) | (bytes[2] & 0x3F);
case 4: return ((bytes[0] & 0xF8) != 0xF0) ? UTF8::invalid : ((bytes[0] & 0x07) << 18) | ((bytes[1] & 0x3F) << 12) | ((bytes[2] & 0x3F) << 6) | (bytes[3] & 0x3F);
case 1: return (((uint8_t)bytes[0] & 0x80) != 0x00) ? UTF8::invalid : (uint8_t)bytes[0];
case 2: return (((uint8_t)bytes[0] & 0xE0) != 0xC0) ? UTF8::invalid : (((uint8_t)bytes[0] & 0x1F) << 6) | ((uint8_t)bytes[1] & 0x3F);
case 3: return (((uint8_t)bytes[0] & 0xF0) != 0xE0) ? UTF8::invalid : (((uint8_t)bytes[0] & 0x0F) << 12) | (((uint8_t)bytes[1] & 0x3F) << 6) | ((uint8_t)bytes[2] & 0x3F);
case 4: return (((uint8_t)bytes[0] & 0xF8) != 0xF0) ? UTF8::invalid : (((uint8_t)bytes[0] & 0x07) << 18) | (((uint8_t)bytes[1] & 0x3F) << 12) | (((uint8_t)bytes[2] & 0x3F) << 6) | ((uint8_t)bytes[3] & 0x3F);
}
return UTF8::invalid;
@@ -75,6 +76,8 @@ namespace BAN::UTF8
}
}
*ptr = '\0';
return true;
}

View File

@@ -33,8 +33,9 @@ namespace BAN
return uniq;
}
// NOTE: don't use is_constructible_v<T, Args...> as UniqPtr<T> is allowed with friends
template<typename... Args>
static BAN::ErrorOr<UniqPtr> create(Args&&... args)
static BAN::ErrorOr<UniqPtr> create(Args&&... args) requires requires(Args&&... args) { T(forward<Args>(args)...); }
{
UniqPtr uniq;
uniq.m_pointer = new T(BAN::forward<Args>(args)...);

View File

@@ -126,6 +126,7 @@ namespace BAN
Variant(Variant&& other)
: m_index(other.m_index)
{
if (other.has_value())
detail::move_construct<Ts...>(other.m_index, other.m_storage, m_storage);
other.clear();
}
@@ -133,6 +134,7 @@ namespace BAN
Variant(const Variant& other)
: m_index(other.m_index)
{
if (other.has_value())
detail::copy_construct<Ts...>(other.m_index, other.m_storage, m_storage);
}
@@ -157,11 +159,12 @@ namespace BAN
Variant& operator=(Variant&& other)
{
if (m_index == other.m_index)
if (m_index == other.m_index && m_index != invalid_index())
detail::move_assign<Ts...>(m_index, other.m_storage, m_storage);
else
{
clear();
if (other.has_value())
detail::move_construct<Ts...>(other.m_index, other.m_storage, m_storage);
m_index = other.m_index;
}
@@ -171,11 +174,12 @@ namespace BAN
Variant& operator=(const Variant& other)
{
if (m_index == other.m_index)
if (m_index == other.m_index && m_index != invalid_index())
detail::copy_assign<Ts...>(m_index, other.m_storage, m_storage);
else
{
clear();
if (other.has_value())
detail::copy_construct<Ts...>(other.m_index, other.m_storage, m_storage);
m_index = other.m_index;
}
@@ -217,7 +221,7 @@ namespace BAN
}
template<typename T, typename... Args>
void emplace(Args&&... args) requires (can_have<T>())
void emplace(Args&&... args) requires (can_have<T>() && is_constructible_v<T, Args...>)
{
clear();
m_index = detail::index<T, Ts...>();
@@ -286,6 +290,16 @@ namespace BAN
return **reinterpret_cast<const remove_reference_t<T>**>(m_storage);
}
bool has_value() const
{
return m_index != invalid_index();
}
explicit operator bool() const
{
return has_value();
}
void clear()
{
if (m_index != invalid_index())

View File

@@ -7,6 +7,7 @@
#include <BAN/New.h>
#include <BAN/PlacementNew.h>
#include <BAN/Span.h>
#include <BAN/Swap.h>
namespace BAN
{
@@ -34,9 +35,9 @@ namespace BAN
ErrorOr<void> push_back(T&&);
ErrorOr<void> push_back(const T&);
template<typename... Args>
ErrorOr<void> emplace_back(Args&&...);
ErrorOr<void> emplace_back(Args&&...) requires is_constructible_v<T, Args...>;
template<typename... Args>
ErrorOr<void> emplace(size_type, Args&&...);
ErrorOr<void> emplace(size_type, Args&&...) requires is_constructible_v<T, Args...>;
ErrorOr<void> insert(size_type, T&&);
ErrorOr<void> insert(size_type, const T&);
@@ -55,7 +56,7 @@ namespace BAN
bool contains(const T&) const;
Span<T> span() { return Span(m_data, m_size); }
const Span<T> span() const { return Span(m_data, m_size); }
Span<const T> span() const { return Span(m_data, m_size); }
const T& operator[](size_type) const;
T& operator[](size_type);
@@ -65,6 +66,8 @@ namespace BAN
const T& front() const;
T& front();
void reverse();
ErrorOr<void> resize(size_type) requires is_default_constructible_v<T>;
ErrorOr<void> resize(size_type, const T&) requires is_copy_constructible_v<T>;
ErrorOr<void> reserve(size_type);
@@ -138,10 +141,13 @@ namespace BAN
template<typename T>
Vector<T>& Vector<T>::operator=(const Vector<T>& other)
{
clear();
MUST(ensure_capacity(other.size()));
for (size_type i = 0; i < other.size(); i++)
for (size_type i = 0; i < BAN::Math::min(size(), other.size()); i++)
m_data[i] = other.m_data[i];
for (size_type i = size(); i < other.size(); i++)
new (m_data + i) T(other[i]);
for (size_type i = other.size(); i < size(); i++)
m_data[i].~T();
m_size = other.m_size;
return *this;
}
@@ -163,7 +169,7 @@ namespace BAN
template<typename T>
template<typename... Args>
ErrorOr<void> Vector<T>::emplace_back(Args&&... args)
ErrorOr<void> Vector<T>::emplace_back(Args&&... args) requires is_constructible_v<T, Args...>
{
TRY(ensure_capacity(m_size + 1));
new (m_data + m_size) T(forward<Args>(args)...);
@@ -173,7 +179,7 @@ namespace BAN
template<typename T>
template<typename... Args>
ErrorOr<void> Vector<T>::emplace(size_type index, Args&&... args)
ErrorOr<void> Vector<T>::emplace(size_type index, Args&&... args) requires is_constructible_v<T, Args...>
{
ASSERT(index <= m_size);
TRY(ensure_capacity(m_size + 1));
@@ -298,6 +304,13 @@ namespace BAN
return m_data[0];
}
template<typename T>
void Vector<T>::reverse()
{
for (size_type i = 0; i < m_size / 2; i++)
BAN::swap(m_data[i], m_data[m_size - i - 1]);
}
template<typename T>
ErrorOr<void> Vector<T>::resize(size_type size) requires is_default_constructible_v<T>
{
@@ -368,10 +381,35 @@ namespace BAN
template<typename T>
ErrorOr<void> Vector<T>::ensure_capacity(size_type size)
{
static_assert(alignof(T) <= alignof(max_align_t), "over aligned types not supported");
if (m_capacity >= size)
return {};
size_type new_cap = BAN::Math::max<size_type>(size, m_capacity * 2);
T* new_data = (T*)BAN::allocator(new_cap * sizeof(T));
const size_type new_cap = BAN::Math::max<size_type>(size, m_capacity * 2);
if constexpr (BAN::is_trivially_copyable_v<T>)
{
if constexpr (BAN::reallocator)
{
auto* new_data = static_cast<T*>(BAN::reallocator(m_data, new_cap * sizeof(T)));
if (new_data == nullptr)
return Error::from_errno(ENOMEM);
m_data = new_data;
}
else
{
auto* new_data = static_cast<T*>(BAN::allocator(new_cap * sizeof(T)));
if (new_data == nullptr)
return Error::from_errno(ENOMEM);
memcpy(new_data, m_data, m_size * sizeof(T));
BAN::deallocator(m_data);
m_data = new_data;
}
}
else
{
auto* new_data = static_cast<T*>(BAN::allocator(new_cap * sizeof(T)));
if (new_data == nullptr)
return Error::from_errno(ENOMEM);
for (size_type i = 0; i < m_size; i++)
@@ -381,6 +419,8 @@ namespace BAN
}
BAN::deallocator(m_data);
m_data = new_data;
}
m_capacity = new_cap;
return {};
}

View File

@@ -2,6 +2,10 @@
#include <BAN/RefPtr.h>
#if __is_kernel
#include <kernel/Lock/SpinLock.h>
#endif
namespace BAN
{
@@ -11,22 +15,37 @@ namespace BAN
template<typename T>
class WeakPtr;
// FIXME: Write this without using locks...
template<typename T>
class WeakLink : public RefCounted<WeakLink<T>>
{
public:
RefPtr<T> lock() { ASSERT(m_ptr); return raw_ptr(); }
T* raw_ptr() { return m_ptr; }
RefPtr<T> try_lock() const
{
#if __is_kernel
Kernel::SpinLockGuard _(m_weak_lock);
#endif
if (m_ptr && m_ptr->try_ref())
return RefPtr<T>::adopt(m_ptr);
return nullptr;
}
bool valid() const { return m_ptr; }
void invalidate() { m_ptr = nullptr; }
void invalidate()
{
#if __is_kernel
Kernel::SpinLockGuard _(m_weak_lock);
#endif
m_ptr = nullptr;
}
private:
WeakLink(T* ptr) : m_ptr(ptr) {}
private:
T* m_ptr;
#if __is_kernel
mutable Kernel::SpinLock m_weak_lock;
#endif
friend class RefPtr<WeakLink<T>>;
};
@@ -34,7 +53,7 @@ namespace BAN
class Weakable
{
public:
~Weakable()
virtual ~Weakable()
{
if (m_link)
m_link->invalidate();
@@ -80,10 +99,10 @@ namespace BAN
return *this;
}
RefPtr<T> lock()
RefPtr<T> lock() const
{
if (m_link->valid())
return m_link->lock();
if (m_link)
return m_link->try_lock();
return nullptr;
}
@@ -91,7 +110,7 @@ namespace BAN
bool valid() const { return m_link && m_link->valid(); }
operator bool() const { return valid(); }
explicit operator bool() const { return valid(); }
private:
WeakPtr(const RefPtr<WeakLink<T>>& link)

View File

@@ -4,46 +4,51 @@ if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "banan-os")
message(FATAL_ERROR "CMAKE_SYSTEM_NAME is not banan-os")
endif ()
#add_compile_options(-mno-sse -mno-sse2)
add_compile_definitions(__enable_sse=1)
project(banan-os CXX C ASM)
set(BANAN_BASE_SYSROOT ${CMAKE_SOURCE_DIR}/base-sysroot.tar.gz)
set(BANAN_INCLUDE ${BANAN_SYSROOT}/usr/include)
set(BANAN_LIB ${BANAN_SYSROOT}/usr/lib)
set(BANAN_BIN ${BANAN_SYSROOT}/usr/bin)
set(BANAN_ETC ${BANAN_SYSROOT}/usr/etc)
set(BANAN_SHARE ${BANAN_SYSROOT}/usr/share)
set(BANAN_BOOT ${BANAN_SYSROOT}/boot)
set(CMAKE_INSTALL_BINDIR ${BANAN_BIN})
set(CMAKE_INSTALL_SBINDIR ${BANAN_BIN})
set(CMAKE_INSTALL_LIBDIR ${BANAN_LIB})
set(CMAKE_INSTALL_INCLUDEDIR ${BANAN_INCLUDE})
set(CMAKE_INSTALL_SYSCONF ${BANAN_ETC})
set(CMAKE_INSTALL_MESSAGE NEVER)
set(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY True)
set(CMAKE_STATIC_LIBRARY_PREFIX "")
set(CMAKE_SHARED_LIBRARY_PREFIX "")
set(BUILD_SHARED_LIBS True)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# include headers of ${library} to ${target}
function(banan_include_headers target library)
target_include_directories(${target} PUBLIC $<TARGET_PROPERTY:${library},SOURCE_DIR>/include)
endfunction()
# include headers and link ${library} to ${target}
function(banan_link_library target library)
target_link_libraries(${target} PUBLIC ${library})
banan_include_headers(${target} ${library})
endfunction()
# add install step for all header files of target
function(banan_install_headers target)
file(GLOB_RECURSE headers RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/include *.h)
foreach(header ${headers})
get_filename_component(subdirectory ${header} DIRECTORY)
install(FILES include/${header} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${subdirectory})
endforeach()
target_include_directories(${target} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
endfunction()
add_subdirectory(kernel)
add_subdirectory(bootloader)
add_subdirectory(BAN)
add_subdirectory(libc)
add_subdirectory(LibELF)
add_subdirectory(userspace)
add_custom_target(sysroot
COMMAND ${CMAKE_COMMAND} -E make_directory ${BANAN_SYSROOT}
COMMAND cd ${BANAN_SYSROOT} && tar xf ${BANAN_BASE_SYSROOT}
)
add_custom_target(headers
DEPENDS kernel-headers
DEPENDS ban-headers
DEPENDS libc-headers
DEPENDS libelf-headers
)
add_custom_target(install-sysroot
DEPENDS kernel-install
DEPENDS ban-install
DEPENDS libc-install
DEPENDS userspace-install
DEPENDS libelf-install
)
add_custom_target(package-sysroot
COMMAND cd ${BANAN_SYSROOT} && tar cf ${BANAN_SYSROOT_TAR} *
DEPENDS install-sysroot
)

View File

@@ -1,12 +0,0 @@
cmake_minimum_required(VERSION 3.26)
project(LibELF CXX)
add_custom_target(libelf-headers
COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different ${CMAKE_CURRENT_SOURCE_DIR}/include/ ${BANAN_INCLUDE}/
DEPENDS sysroot
)
add_custom_target(libelf-install
DEPENDS libelf-headers
)

View File

@@ -1,405 +0,0 @@
#include <BAN/ScopeGuard.h>
#include <LibELF/ELF.h>
#include <LibELF/Values.h>
#ifdef __is_kernel
#include <kernel/FS/VirtualFileSystem.h>
#include <kernel/Process.h>
#endif
#include <fcntl.h>
#define ELF_PRINT_HEADERS 0
#ifdef __is_kernel
extern uint8_t g_kernel_end[];
using namespace Kernel;
#endif
namespace LibELF
{
#ifdef __is_kernel
BAN::ErrorOr<BAN::UniqPtr<ELF>> ELF::load_from_file(BAN::RefPtr<Inode> inode)
{
BAN::Vector<uint8_t> buffer;
TRY(buffer.resize(inode->size()));
TRY(inode->read(0, buffer.data(), inode->size()));
ELF* elf_ptr = new ELF(BAN::move(buffer));
if (elf_ptr == nullptr)
return BAN::Error::from_errno(ENOMEM);
auto elf = BAN::UniqPtr<ELF>::adopt(elf_ptr);
TRY(elf->load());
return BAN::move(elf);
}
#else
BAN::ErrorOr<ELF*> ELF::load_from_file(BAN::StringView file_path)
{
ELF* elf = nullptr;
{
BAN::Vector<uint8_t> data;
int fd = TRY(Kernel::Process::current().open(file_path, O_RDONLY));
BAN::ScopeGuard _([fd] { MUST(Kernel::Process::current().close(fd)); });
struct stat st;
TRY(Kernel::Process::current().fstat(fd, &st));
TRY(data.resize(st.st_size));
TRY(Kernel::Process::current().read(fd, data.data(), data.size()));
elf = new ELF(BAN::move(data));
ASSERT(elf);
}
if (auto res = elf->load(); res.is_error())
{
delete elf;
return res.error();
}
return elf;
}
#endif
BAN::ErrorOr<void> ELF::load()
{
if (m_data.size() < EI_NIDENT)
{
dprintln("Too small ELF file");
return BAN::Error::from_errno(EINVAL);
}
if (m_data[EI_MAG0] != ELFMAG0 ||
m_data[EI_MAG1] != ELFMAG1 ||
m_data[EI_MAG2] != ELFMAG2 ||
m_data[EI_MAG3] != ELFMAG3)
{
dprintln("Invalid ELF header");
return BAN::Error::from_errno(EINVAL);
}
if (m_data[EI_DATA] != ELFDATA2LSB)
{
dprintln("Only little-endian is supported");
return BAN::Error::from_errno(EINVAL);
}
if (m_data[EI_VERSION] != EV_CURRENT)
{
dprintln("Invalid ELF version");
return BAN::Error::from_errno(EINVAL);
}
if (m_data[EI_CLASS] == ELFCLASS64)
{
if (m_data.size() <= sizeof(Elf64FileHeader))
{
dprintln("Too small ELF file");
return BAN::Error::from_errno(EINVAL);
}
auto& header = file_header64();
if (!parse_elf64_file_header(header))
return BAN::Error::from_errno(EINVAL);
for (size_t i = 0; i < header.e_phnum; i++)
{
auto& program_header = program_header64(i);
if (!parse_elf64_program_header(program_header))
return BAN::Error::from_errno(EINVAL);
}
for (size_t i = 1; i < header.e_shnum; i++)
{
auto& section_header = section_header64(i);
if (!parse_elf64_section_header(section_header))
return BAN::Error::from_errno(EINVAL);
}
}
else if (m_data[EI_CLASS] == ELFCLASS32)
{
if (m_data.size() <= sizeof(Elf32FileHeader))
{
dprintln("Too small ELF file");
return BAN::Error::from_errno(EINVAL);
}
auto& header = file_header32();
if (!parse_elf32_file_header(header))
return BAN::Error::from_errno(EINVAL);
for (size_t i = 0; i < header.e_phnum; i++)
{
auto& program_header = program_header32(i);
if (!parse_elf32_program_header(program_header))
return BAN::Error::from_errno(EINVAL);
}
for (size_t i = 1; i < header.e_shnum; i++)
{
auto& section_header = section_header32(i);
if (!parse_elf32_section_header(section_header))
return BAN::Error::from_errno(EINVAL);
}
}
return {};
}
bool ELF::is_x86_32() const { return m_data[EI_CLASS] == ELFCLASS32; }
bool ELF::is_x86_64() const { return m_data[EI_CLASS] == ELFCLASS64; }
/*
64 bit ELF
*/
const char* ELF::lookup_section_name64(uint32_t offset) const
{
return lookup_string64(file_header64().e_shstrndx, offset);
}
const char* ELF::lookup_string64(size_t table_index, uint32_t offset) const
{
if (table_index == SHN_UNDEF)
return nullptr;
auto& section_header = section_header64(table_index);
return (const char*)m_data.data() + section_header.sh_offset + offset;
}
bool ELF::parse_elf64_file_header(const Elf64FileHeader& header)
{
if (header.e_type != ET_EXEC)
{
dprintln("Only executable files are supported");
return false;
}
if (header.e_version != EV_CURRENT)
{
dprintln("Invalid ELF version");
return false;
}
return true;
}
bool ELF::parse_elf64_program_header(const Elf64ProgramHeader& header)
{
#if ELF_PRINT_HEADERS
dprintln("program header");
dprintln(" type {H}", header.p_type);
dprintln(" flags {H}", header.p_flags);
dprintln(" offset {H}", header.p_offset);
dprintln(" vaddr {H}", header.p_vaddr);
dprintln(" paddr {H}", header.p_paddr);
dprintln(" filesz {}", header.p_filesz);
dprintln(" memsz {}", header.p_memsz);
dprintln(" align {}", header.p_align);
#endif
(void)header;
return true;
}
bool ELF::parse_elf64_section_header(const Elf64SectionHeader& header)
{
#if ELF_PRINT_HEADERS
if (auto* name = lookup_section_name64(header.sh_name))
dprintln("{}", name);
switch (header.sh_type)
{
case SHT_NULL:
dprintln(" SHT_NULL");
break;
case SHT_PROGBITS:
dprintln(" SHT_PROGBITS");
break;
case SHT_SYMTAB:
for (size_t i = 1; i < header.sh_size / header.sh_entsize; i++)
{
auto& symbol = ((const Elf64Symbol*)(m_data.data() + header.sh_offset))[i];
if (auto* name = lookup_string64(header.sh_link, symbol.st_name))
dprintln(" {}", name);
}
break;
case SHT_STRTAB:
dprintln(" SHT_STRTAB");
break;
case SHT_RELA:
dprintln(" SHT_RELA");
break;
case SHT_NOBITS:
dprintln(" SHT_NOBITS");
break;
case SHT_REL:
dprintln(" SHT_REL");
break;
case SHT_SHLIB:
dprintln(" SHT_SHLIB");
break;
case SHT_DYNSYM:
dprintln(" SHT_DYNSYM");
break;
default:
ASSERT(false);
}
#endif
(void)header;
return true;
}
const Elf64FileHeader& ELF::file_header64() const
{
ASSERT(is_x86_64());
return *(const Elf64FileHeader*)m_data.data();
}
const Elf64ProgramHeader& ELF::program_header64(size_t index) const
{
ASSERT(is_x86_64());
const auto& file_header = file_header64();
ASSERT(index < file_header.e_phnum);
return *(const Elf64ProgramHeader*)(m_data.data() + file_header.e_phoff + file_header.e_phentsize * index);
}
const Elf64SectionHeader& ELF::section_header64(size_t index) const
{
ASSERT(is_x86_64());
const auto& file_header = file_header64();
ASSERT(index < file_header.e_shnum);
return *(const Elf64SectionHeader*)(m_data.data() + file_header.e_shoff + file_header.e_shentsize * index);
}
/*
32 bit ELF
*/
const char* ELF::lookup_section_name32(uint32_t offset) const
{
return lookup_string32(file_header32().e_shstrndx, offset);
}
const char* ELF::lookup_string32(size_t table_index, uint32_t offset) const
{
if (table_index == SHN_UNDEF)
return nullptr;
auto& section_header = section_header32(table_index);
return (const char*)m_data.data() + section_header.sh_offset + offset;
}
bool ELF::parse_elf32_file_header(const Elf32FileHeader& header)
{
if (header.e_type != ET_EXEC)
{
dprintln("Only executable files are supported");
return false;
}
if (header.e_version != EV_CURRENT)
{
dprintln("Invalid ELF version");
return false;
}
return true;
}
bool ELF::parse_elf32_program_header(const Elf32ProgramHeader& header)
{
#if ELF_PRINT_HEADERS
dprintln("program header");
dprintln(" type {H}", header.p_type);
dprintln(" flags {H}", header.p_flags);
dprintln(" offset {H}", header.p_offset);
dprintln(" vaddr {H}", header.p_vaddr);
dprintln(" paddr {H}", header.p_paddr);
dprintln(" filesz {}", header.p_filesz);
dprintln(" memsz {}", header.p_memsz);
dprintln(" align {}", header.p_align);
#endif
(void)header;
return true;
}
bool ELF::parse_elf32_section_header(const Elf32SectionHeader& header)
{
#if ELF_PRINT_HEADERS
if (auto* name = lookup_section_name32(header.sh_name))
dprintln("{}", name);
switch (header.sh_type)
{
case SHT_NULL:
dprintln(" SHT_NULL");
break;
case SHT_PROGBITS:
dprintln(" SHT_PROGBITS");
break;
case SHT_SYMTAB:
for (size_t i = 1; i < header.sh_size / header.sh_entsize; i++)
{
auto& symbol = ((const Elf32Symbol*)(m_data.data() + header.sh_offset))[i];
if (auto* name = lookup_string32(header.sh_link, symbol.st_name))
dprintln(" {}", name);
}
break;
case SHT_STRTAB:
dprintln(" SHT_STRTAB");
break;
case SHT_RELA:
dprintln(" SHT_RELA");
break;
case SHT_NOBITS:
dprintln(" SHT_NOBITS");
break;
case SHT_REL:
dprintln(" SHT_REL");
break;
case SHT_SHLIB:
dprintln(" SHT_SHLIB");
break;
case SHT_DYNSYM:
dprintln(" SHT_DYNSYM");
break;
default:
ASSERT(false);
}
#endif
(void)header;
return true;
}
const Elf32FileHeader& ELF::file_header32() const
{
ASSERT(is_x86_32());
return *(const Elf32FileHeader*)m_data.data();
}
const Elf32ProgramHeader& ELF::program_header32(size_t index) const
{
ASSERT(is_x86_32());
const auto& file_header = file_header32();
ASSERT(index < file_header.e_phnum);
return *(const Elf32ProgramHeader*)(m_data.data() + file_header.e_phoff + file_header.e_phentsize * index);
}
const Elf32SectionHeader& ELF::section_header32(size_t index) const
{
ASSERT(is_x86_32());
const auto& file_header = file_header32();
ASSERT(index < file_header.e_shnum);
return *(const Elf32SectionHeader*)(m_data.data() + file_header.e_shoff + file_header.e_shentsize * index);
}
}

View File

@@ -1,331 +0,0 @@
#include <BAN/ScopeGuard.h>
#include <kernel/Memory/Heap.h>
#include <kernel/Lock/LockGuard.h>
#include <LibELF/LoadableELF.h>
#include <LibELF/Values.h>
namespace LibELF
{
using namespace Kernel;
BAN::ErrorOr<BAN::UniqPtr<LoadableELF>> LoadableELF::load_from_inode(PageTable& page_table, BAN::RefPtr<Inode> inode)
{
auto* elf_ptr = new LoadableELF(page_table, inode);
if (elf_ptr == nullptr)
return BAN::Error::from_errno(ENOMEM);
auto elf = BAN::UniqPtr<LoadableELF>::adopt(elf_ptr);
TRY(elf->initialize());
return BAN::move(elf);
}
LoadableELF::LoadableELF(PageTable& page_table, BAN::RefPtr<Inode> inode)
: m_inode(inode)
, m_page_table(page_table)
{
}
LoadableELF::~LoadableELF()
{
if (!m_loaded)
return;
for (const auto& program_header : m_program_headers)
{
switch (program_header.p_type)
{
case PT_NULL:
continue;
case PT_LOAD:
{
vaddr_t start = program_header.p_vaddr & PAGE_ADDR_MASK;
size_t pages = range_page_count(program_header.p_vaddr, program_header.p_memsz);
for (size_t i = 0; i < pages; i++)
{
paddr_t paddr = m_page_table.physical_address_of(start + i * PAGE_SIZE);
if (paddr != 0)
Heap::get().release_page(paddr);
}
m_page_table.unmap_range(start, pages * PAGE_SIZE);
break;
}
default:
ASSERT_NOT_REACHED();
}
}
}
BAN::ErrorOr<void> LoadableELF::initialize()
{
if ((size_t)m_inode->size() < sizeof(ElfNativeFileHeader))
{
dprintln("Too small file");
return BAN::Error::from_errno(ENOEXEC);
}
size_t nread = TRY(m_inode->read(0, BAN::ByteSpan::from(m_file_header)));
ASSERT(nread == sizeof(m_file_header));
if (m_file_header.e_ident[EI_MAG0] != ELFMAG0 ||
m_file_header.e_ident[EI_MAG1] != ELFMAG1 ||
m_file_header.e_ident[EI_MAG2] != ELFMAG2 ||
m_file_header.e_ident[EI_MAG3] != ELFMAG3)
{
dprintln("Invalid magic in header");
return BAN::Error::from_errno(ENOEXEC);
}
if (m_file_header.e_ident[EI_DATA] != ELFDATA2LSB)
{
dprintln("Only little-endian is supported");
return BAN::Error::from_errno(ENOEXEC);
}
if (m_file_header.e_ident[EI_VERSION] != EV_CURRENT)
{
dprintln("Invalid version");
return BAN::Error::from_errno(ENOEXEC);
}
#if ARCH(i686)
if (m_file_header.e_ident[EI_CLASS] != ELFCLASS32)
#elif ARCH(x86_64)
if (m_file_header.e_ident[EI_CLASS] != ELFCLASS64)
#endif
{
dprintln("Not in native format");
return BAN::Error::from_errno(EINVAL);
}
if (m_file_header.e_type != ET_EXEC)
{
dprintln("Only executable files are supported");
return BAN::Error::from_errno(EINVAL);
}
if (m_file_header.e_version != EV_CURRENT)
{
dprintln("Unsupported version");
return BAN::Error::from_errno(EINVAL);
}
ASSERT(m_file_header.e_phentsize <= sizeof(ElfNativeProgramHeader));
TRY(m_program_headers.resize(m_file_header.e_phnum));
for (size_t i = 0; i < m_file_header.e_phnum; i++)
{
TRY(m_inode->read(m_file_header.e_phoff + m_file_header.e_phentsize * i, BAN::ByteSpan::from(m_program_headers[i])));
const auto& pheader = m_program_headers[i];
if (pheader.p_type != PT_NULL && pheader.p_type != PT_LOAD)
{
dprintln("Unsupported program header type {}", pheader.p_type);
return BAN::Error::from_errno(ENOTSUP);
}
if (pheader.p_memsz < pheader.p_filesz)
{
dprintln("Invalid program header");
return BAN::Error::from_errno(EINVAL);
}
m_virtual_page_count += BAN::Math::div_round_up<size_t>((pheader.p_vaddr % PAGE_SIZE) + pheader.p_memsz, PAGE_SIZE);
}
return {};
}
vaddr_t LoadableELF::entry_point() const
{
return m_file_header.e_entry;
}
bool LoadableELF::contains(vaddr_t address) const
{
for (const auto& program_header : m_program_headers)
{
switch (program_header.p_type)
{
case PT_NULL:
continue;
case PT_LOAD:
if (program_header.p_vaddr <= address && address < program_header.p_vaddr + program_header.p_memsz)
return true;
break;
default:
ASSERT_NOT_REACHED();
}
}
return false;
}
bool LoadableELF::is_address_space_free() const
{
for (const auto& program_header : m_program_headers)
{
switch (program_header.p_type)
{
case PT_NULL:
break;
case PT_LOAD:
{
vaddr_t page_vaddr = program_header.p_vaddr & PAGE_ADDR_MASK;
size_t pages = range_page_count(program_header.p_vaddr, program_header.p_memsz);
if (!m_page_table.is_range_free(page_vaddr, pages * PAGE_SIZE))
return false;
break;
}
default:
ASSERT_NOT_REACHED();
}
}
return true;
}
void LoadableELF::reserve_address_space()
{
for (const auto& program_header : m_program_headers)
{
switch (program_header.p_type)
{
case PT_NULL:
break;
case PT_LOAD:
{
vaddr_t page_vaddr = program_header.p_vaddr & PAGE_ADDR_MASK;
size_t pages = range_page_count(program_header.p_vaddr, program_header.p_memsz);
ASSERT(m_page_table.reserve_range(page_vaddr, pages * PAGE_SIZE));
break;
}
default:
ASSERT_NOT_REACHED();
}
}
m_loaded = true;
}
void LoadableELF::update_suid_sgid(Kernel::Credentials& credentials)
{
if (m_inode->mode().mode & +Inode::Mode::ISUID)
credentials.set_euid(m_inode->uid());
if (m_inode->mode().mode & +Inode::Mode::ISGID)
credentials.set_egid(m_inode->gid());
}
BAN::ErrorOr<void> LoadableELF::load_page_to_memory(vaddr_t address)
{
for (const auto& program_header : m_program_headers)
{
switch (program_header.p_type)
{
case PT_NULL:
break;
case PT_LOAD:
{
if (!(program_header.p_vaddr <= address && address < program_header.p_vaddr + program_header.p_memsz))
continue;
PageTable::flags_t flags = PageTable::Flags::UserSupervisor | PageTable::Flags::Present;
if (program_header.p_flags & LibELF::PF_W)
flags |= PageTable::Flags::ReadWrite;
if (program_header.p_flags & LibELF::PF_X)
flags |= PageTable::Flags::Execute;
vaddr_t vaddr = address & PAGE_ADDR_MASK;
paddr_t paddr = Heap::get().take_free_page();
if (paddr == 0)
return BAN::Error::from_errno(ENOMEM);
// Temporarily map page as RW so kernel can write to it
m_page_table.map_page_at(paddr, vaddr, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
m_physical_page_count++;
memset((void*)vaddr, 0x00, PAGE_SIZE);
if (vaddr / PAGE_SIZE < BAN::Math::div_round_up<size_t>(program_header.p_vaddr + program_header.p_filesz, PAGE_SIZE))
{
size_t vaddr_offset = 0;
if (vaddr < program_header.p_vaddr)
vaddr_offset = program_header.p_vaddr - vaddr;
size_t file_offset = 0;
if (vaddr > program_header.p_vaddr)
file_offset = vaddr - program_header.p_vaddr;
size_t bytes = BAN::Math::min<size_t>(PAGE_SIZE - vaddr_offset, program_header.p_filesz - file_offset);
TRY(m_inode->read(program_header.p_offset + file_offset, { (uint8_t*)vaddr + vaddr_offset, bytes }));
}
// Map page with the correct flags
m_page_table.map_page_at(paddr, vaddr, flags);
return {};
}
default:
ASSERT_NOT_REACHED();
}
}
ASSERT_NOT_REACHED();
}
BAN::ErrorOr<BAN::UniqPtr<LoadableELF>> LoadableELF::clone(Kernel::PageTable& new_page_table)
{
auto* elf_ptr = new LoadableELF(new_page_table, m_inode);
if (elf_ptr == nullptr)
return BAN::Error::from_errno(ENOMEM);
auto elf = BAN::UniqPtr<LoadableELF>::adopt(elf_ptr);
memcpy(&elf->m_file_header, &m_file_header, sizeof(ElfNativeFileHeader));
TRY(elf->m_program_headers.resize(m_program_headers.size()));
memcpy(elf->m_program_headers.data(), m_program_headers.data(), m_program_headers.size() * sizeof(ElfNativeProgramHeader));
elf->reserve_address_space();
for (const auto& program_header : m_program_headers)
{
switch (program_header.p_type)
{
case PT_NULL:
break;
case PT_LOAD:
{
if (!(program_header.p_flags & LibELF::PF_W))
continue;
PageTable::flags_t flags = PageTable::Flags::UserSupervisor | PageTable::Flags::Present;
if (program_header.p_flags & LibELF::PF_W)
flags |= PageTable::Flags::ReadWrite;
if (program_header.p_flags & LibELF::PF_X)
flags |= PageTable::Flags::Execute;
vaddr_t start = program_header.p_vaddr & PAGE_ADDR_MASK;
size_t pages = range_page_count(program_header.p_vaddr, program_header.p_memsz);
for (size_t i = 0; i < pages; i++)
{
if (m_page_table.physical_address_of(start + i * PAGE_SIZE) == 0)
continue;
paddr_t paddr = Heap::get().take_free_page();
if (paddr == 0)
return BAN::Error::from_errno(ENOMEM);
PageTable::with_fast_page(paddr, [&] {
memcpy(PageTable::fast_page_as_ptr(), (void*)(start + i * PAGE_SIZE), PAGE_SIZE);
});
new_page_table.map_page_at(paddr, start + i * PAGE_SIZE, flags);
elf->m_physical_page_count++;
}
break;
}
default:
ASSERT_NOT_REACHED();
}
}
return elf;
}
}

View File

@@ -1,89 +0,0 @@
#pragma once
#ifdef __is_kernel
#include <kernel/FS/Inode.h>
#include <kernel/Memory/VirtualRange.h>
#endif
#include <BAN/StringView.h>
#include <BAN/UniqPtr.h>
#include <BAN/Vector.h>
#include <kernel/Arch.h>
#include "Types.h"
namespace LibELF
{
class ELF
{
public:
#ifdef __is_kernel
static BAN::ErrorOr<BAN::UniqPtr<ELF>> load_from_file(BAN::RefPtr<Kernel::Inode>);
#else
static BAN::ErrorOr<BAN::UniqPtr<ELF>> load_from_file(BAN::StringView);
#endif
const Elf64FileHeader& file_header64() const;
const Elf64ProgramHeader& program_header64(size_t) const;
const Elf64SectionHeader& section_header64(size_t) const;
const char* lookup_section_name64(uint32_t) const;
const char* lookup_string64(size_t, uint32_t) const;
#if ARCH(x86_64)
const Elf64FileHeader& file_header_native() const { return file_header64(); }
const Elf64ProgramHeader& program_header_native(size_t index) const { return program_header64(index); }
const Elf64SectionHeader& section_header_native(size_t index) const { return section_header64(index); }
const char* lookup_section_name_native(uint32_t offset) const { return lookup_section_name64(offset); }
const char* lookup_string_native(size_t table_index, uint32_t offset) const { return lookup_string64(table_index, offset); }
bool is_native() const { return is_x86_64(); }
#endif
const Elf32FileHeader& file_header32() const;
const Elf32ProgramHeader& program_header32(size_t) const;
const Elf32SectionHeader& section_header32(size_t) const;
const char* lookup_section_name32(uint32_t) const;
const char* lookup_string32(size_t, uint32_t) const;
#if ARCH(i686)
const Elf32FileHeader& file_header_native() const { return file_header32(); }
const Elf32ProgramHeader& program_header_native(size_t index) const { return program_header32(index); }
const Elf32SectionHeader& section_header_native(size_t index) const { return section_header32(index); }
const char* lookup_section_name_native(uint32_t offset) const { return lookup_section_name32(offset); }
const char* lookup_string_native(size_t table_index, uint32_t offset) const { return lookup_string32(table_index, offset); }
bool is_native() const { return is_x86_32(); }
#endif
const uint8_t* data() const { return m_data.data(); }
bool is_x86_32() const;
bool is_x86_64() const;
private:
//#ifdef __is_kernel
// ELF(BAN::UniqPtr<Kernel::VirtualRange>&& storage, size_t size)
// : m_storage(BAN::move(storage))
// , m_data((const uint8_t*)m_storage->vaddr(), size)
// {}
//#else
ELF(BAN::Vector<uint8_t>&& data)
: m_data(BAN::move(data))
{}
//#endif
BAN::ErrorOr<void> load();
bool parse_elf64_file_header(const Elf64FileHeader&);
bool parse_elf64_program_header(const Elf64ProgramHeader&);
bool parse_elf64_section_header(const Elf64SectionHeader&);
bool parse_elf32_file_header(const Elf32FileHeader&);
bool parse_elf32_program_header(const Elf32ProgramHeader&);
bool parse_elf32_section_header(const Elf32SectionHeader&);
private:
//#ifdef __is_kernel
// BAN::UniqPtr<Kernel::VirtualRange> m_storage;
// BAN::Span<const uint8_t> m_data;
//#else
const BAN::Vector<uint8_t> m_data;
//#endif
};
}

View File

@@ -1,57 +0,0 @@
#pragma once
#ifndef __is_kernel
#error "This is kernel only header"
#endif
#include <BAN/UniqPtr.h>
#include <BAN/Vector.h>
#include <kernel/Credentials.h>
#include <kernel/FS/Inode.h>
#include <kernel/Memory/PageTable.h>
#include <LibELF/Types.h>
namespace LibELF
{
class LoadableELF
{
BAN_NON_COPYABLE(LoadableELF);
BAN_NON_MOVABLE(LoadableELF);
public:
static BAN::ErrorOr<BAN::UniqPtr<LoadableELF>> load_from_inode(Kernel::PageTable&, BAN::RefPtr<Kernel::Inode>);
~LoadableELF();
Kernel::vaddr_t entry_point() const;
bool contains(Kernel::vaddr_t address) const;
bool is_address_space_free() const;
void reserve_address_space();
void update_suid_sgid(Kernel::Credentials&);
BAN::ErrorOr<void> load_page_to_memory(Kernel::vaddr_t address);
BAN::ErrorOr<BAN::UniqPtr<LoadableELF>> clone(Kernel::PageTable&);
size_t virtual_page_count() const { return m_virtual_page_count; }
size_t physical_page_count() const { return m_physical_page_count; }
private:
LoadableELF(Kernel::PageTable&, BAN::RefPtr<Kernel::Inode>);
BAN::ErrorOr<void> initialize();
private:
BAN::RefPtr<Kernel::Inode> m_inode;
Kernel::PageTable& m_page_table;
ElfNativeFileHeader m_file_header;
BAN::Vector<ElfNativeProgramHeader> m_program_headers;
size_t m_virtual_page_count = 0;
size_t m_physical_page_count = 0;
bool m_loaded { false };
};
}

View File

@@ -1,140 +0,0 @@
#pragma once
namespace LibELF
{
enum ELF_Ident
{
ELFMAG0 = 0x7F,
ELFMAG1 = 'E',
ELFMAG2 = 'L',
ELFMAG3 = 'F',
ELFCLASSNONE = 0,
ELFCLASS32 = 1,
ELFCLASS64 = 2,
ELFDATANONE = 0,
ELFDATA2LSB = 1,
ELFDATA2MSB = 2,
};
enum ELF_EI
{
EI_MAG0 = 0,
EI_MAG1 = 1,
EI_MAG2 = 2,
EI_MAG3 = 3,
EI_CLASS = 4,
EI_DATA = 5,
EI_VERSION = 6,
EI_OSABI = 7,
EI_ABIVERSION = 8,
EI_NIDENT = 16,
};
enum ELF_ET
{
ET_NONE = 0,
ET_REL = 1,
ET_EXEC = 2,
ET_DYN = 3,
ET_CORE = 4,
ET_LOOS = 0xfe00,
ET_HIOS = 0xfeff,
ET_LOPROC = 0xff00,
ET_HIPROC = 0xffff,
};
enum ELF_EV
{
EV_NONE = 0,
EV_CURRENT = 1,
};
enum ELF_SHT
{
SHT_NULL = 0,
SHT_PROGBITS = 1,
SHT_SYMTAB = 2,
SHT_STRTAB = 3,
SHT_RELA = 4,
SHT_NOBITS = 8,
SHT_REL = 9,
SHT_SHLIB = 10,
SHT_DYNSYM = 11,
SHT_LOOS = 0x60000000,
SHT_HIOS = 0x6FFFFFFF,
SHT_LOPROC = 0x70000000,
SHT_HIPROC = 0x7FFFFFFF,
};
enum ELF_SHF
{
SHF_WRITE = 0x1,
SHF_ALLOC = 0x2,
SHF_EXECINSTR = 0x4,
SHF_MASKOS = 0x0F000000,
SHF_MASKPROC = 0xF0000000,
};
enum ELF_SHN
{
SHN_UNDEF = 0,
SHN_LOPROC = 0xFF00,
SHN_HIPROC = 0xFF1F,
SHN_LOOS = 0xFF20,
SHN_HIOS = 0xFF3F,
SHN_ABS = 0xFFF1,
SHN_COMMON = 0xFFF2,
};
enum ELF_STB
{
STB_LOCAL = 0,
STB_GLOBAL = 1,
STB_WEAK = 2,
STB_LOOS = 10,
STB_HIOS = 12,
STB_LOPROC = 13,
STB_HIPROC = 15,
};
enum ELF_STT
{
STT_NOTYPE = 0,
STT_OBJECT = 1,
STT_FUNC = 2,
STT_SECTION = 3,
STT_FILE = 4,
STT_LOOS = 10,
STT_HIOS = 12,
STT_LOPROC = 13,
STT_HIPROC = 15,
};
enum ELF_PT
{
PT_NULL = 0,
PT_LOAD = 1,
PT_DYNAMIC = 2,
PT_INTERP = 3,
PT_NOTE = 4,
PT_SHLIB = 5,
PT_PHDR = 6,
PT_LOOS = 0x60000000,
PT_HIOS = 0x6FFFFFFF,
PT_LOPROC = 0x70000000,
PT_HIPROC = 0x7FFFFFFF,
};
enum ELF_PF
{
PF_X = 0x1,
PF_W = 0x2,
PF_R = 0x4,
PF_MASKOS = 0x00FF0000,
PF_MASKPROC = 0xFF000000,
};
}

View File

@@ -9,6 +9,8 @@ This is my hobby operating system written in C++. Currently supports x86\_64 and
You can find a live demo [here](https://bananymous.com/banan-os)
If you want to try out DOOM, you should first enter the GUI environment using the `start-gui` command. Then you can run `doom` in the GUI terminal.
### Features
#### General
@@ -18,15 +20,34 @@ You can find a live demo [here](https://bananymous.com/banan-os)
- [x] Network stack
- [x] ELF executable loading
- [x] AML interpreter (partial)
- [ ] ELF dynamic linking
- [ ] Graphical desktop
- [x] Basic graphical environment
- [x] Terminal emulator
- [x] Status bar
- [x] Program launcher
- [ ] Some nice apps
- [x] ELF dynamic linking
- [x] copy-on-write memory
- [x] file mappings
- [ ] anonymous mappings
#### Drivers
- [x] NVMe disks
- [x] ATA (IDE, SATA) disks
- [x] E1000 and E1000E NICs
- [x] RTL8111/8168/8211/8411 NICs
- [x] PS2 keyboard (all scancode sets)
- [x] PS2 mouse
- [x] USB
- [x] xHCI
- [ ] EHCI
- [ ] OHCI
- [ ] UHCI
- [x] Keyboard
- [x] Mouse
- [x] Mass storage
- [x] Hubs
- [ ] ...
- [ ] virtio devices (network, storage)
#### Network
- [x] ARP
@@ -35,14 +56,17 @@ You can find a live demo [here](https://bananymous.com/banan-os)
- [x] UDP
- [x] TCP (partial and buggy)
- [x] Unix domain sockets
- [ ] SSL
#### Filesystems
- [x] Virtual filesystem
- [x] Ext2
- [x] FAT12/16/32
- [x] Dev
- [x] Ram
- [x] Proc
- [ ] Sys
- [ ] 9P
#### Bootloader support
- [x] GRUB
@@ -60,7 +84,7 @@ Each major component and library has its own subdirectory (kernel, userspace, li
### Needed packages
#### apt (tested on ubuntu 22.04)
```# apt install build-essential git ninja-build texinfo bison flex libgmp-dev libmpfr-dev libmpc-dev parted qemu-system-x86```
```# apt install build-essential git ninja-build texinfo bison flex libgmp-dev libmpfr-dev libmpc-dev parted qemu-system-x86 cpu-checker```
#### pacman
```# pacman -S --needed base-devel git wget cmake ninja parted qemu-system-x86```
@@ -94,6 +118,8 @@ To change the bootloader you can set environment variable BANAN\_BOOTLOADER; sup
To run with UEFI set environment variable BANAN\_UEFI\_BOOT=1. You will also have to set OVMF\_PATH to the correct OVMF (default */usr/share/ovmf/x64/OVMF.fd*).
To build an image with no physical root filesystem, but an initrd set environment variable BANAN\_INITRD=1. This can be used when testing on hardware with unsupported USB controller.
If you have corrupted your disk image or want to create new one, you can either manually delete *build/banan-os.img* and build system will automatically create you a new one or you can run the following command.
```sh
./bos image-full
@@ -103,13 +129,13 @@ I have also created shell completion script for zsh. You can either copy the fil
## Contributing
As the upstream is hosted on my server https://git.bananymous.com/Bananymous/banan-os, please contact me about account creation ([email](mailto:oskari.alaranta@bananymous.com), [discord](https://discord.gg/xMXKt9Wf)) and I will add a account for you. This is done to limit the people with access to the server.
As the upstream is hosted on my server https://git.bananymous.com/Bananymous/banan-os, merging contributions is not as trivial as it would be on GitHub. You can still send PRs in GitHub in which case I should be able to download the diff and apply it manually. If you want, I can also provide you an account to my git server. In this case please contact me ([email](mailto:oskari.alaranta@bananymous.com), [discord](https://discord.gg/ehjGySwYdK)).
As this is mostly a learning experience for me, I would appreciate if you first contacted me about adding new features (email, discord, issue, ...). Bug fixes are always welcome!
As this is mostly a learning experience for me, I would appreciate if you first contacted me about adding new features (email, discord, issue, ...). If you send a PR about something I was planning on doing myself and you didn't ask me, I will probably just close it. Bug fixes are always welcome!
Commit message should be formatted followingly
1. First line is of the form "_Subject: Description_", where _Subject_ tells the area touched (Kernel, Shell, BuildSystem, ...) and _Description_ is brief description of the change done. First line should fit fully in 70 characters.
1. First line is of the form "_Subject: Description_", where _Subject_ tells the area touched (Kernel, Shell, BuildSystem, ...) and _Description_ is brief description of the change done. First line should fit fully in 72 characters.
2. Body of the message should further describe the change and reasoning behind the change.
All commits should pass the pre-commit hook defined in _.pre-commit-config.yaml_. For instructions on how to setup pre-commit, please see https://pre-commit.com/#install.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 384 KiB

Binary file not shown.

View File

@@ -172,3 +172,5 @@ banan_boot_info:
.long framebuffer
boot_memory_map:
.long memory_map
boot_kernel_paddr:
.long 0

View File

@@ -84,4 +84,4 @@ command_line:
# 100 character command line
command_line_buffer:
.ascii "root=/dev/sda2"
.skip 100 - 28
.skip 100 - (. - command_line_buffer)

View File

@@ -306,20 +306,8 @@ memset32:
movw $GDT_DATA32, %dx
movw %dx, %es
movl %ecx, %edx
andl $3, %ecx
rep stosb %es:(%edi)
movl %edx, %ecx
shrl $2, %ecx
movb %al, %ah
movw %ax, %dx
shll $16, %eax
movw %dx, %ax
rep stosl %es:(%edi)
ljmpl $GDT_CODE16, $.memset32_pmode16
.code16
@@ -370,14 +358,8 @@ memcpy32:
movw %dx, %ds
movw %dx, %es
movl %ecx, %edx
andl $3, %ecx
rep movsb %ds:(%esi), %es:(%edi)
movl %edx, %ecx
shrl $2, %ecx
rep movsl %ds:(%esi), %es:(%edi)
ljmpl $GDT_CODE16, $.memcpy32_pmode16
.code16

View File

@@ -18,5 +18,5 @@ set(SOURCES
add_executable(banan_os-bootloader-installer ${SOURCES})
target_compile_options(banan_os-bootloader-installer PRIVATE -O2 -std=c++20)
target_compile_definitions(banan_os-bootloader-installer PRIVATE __arch=${BANAN_ARCH})
target_include_directories(banan_os-bootloader-installer PRIVATE ${CMAKE_SOURCE_DIR}/../../LibELF/include)
target_include_directories(banan_os-bootloader-installer PRIVATE ${CMAKE_SOURCE_DIR}/../../userspace/libraries/LibELF/include)
target_include_directories(banan_os-bootloader-installer PRIVATE ${CMAKE_SOURCE_DIR}/../../kernel/include)

View File

@@ -1,24 +1,16 @@
cmake_minimum_required(VERSION 3.26)
project(kernel CXX C ASM)
if("${BANAN_ARCH}" STREQUAL "x86_64")
set(ELF_FORMAT elf64-x86-64)
elseif("${BANAN_ARCH}" STREQUAL "i686")
set(ELF_FORMAT elf32-i386)
endif()
set(KERNEL_SOURCES
font/prefs.psf.o
kernel/ACPI/ACPI.cpp
kernel/ACPI/AML.cpp
kernel/ACPI/AML/Field.cpp
kernel/ACPI/AML/NamedObject.cpp
kernel/ACPI/AML/Namespace.cpp
kernel/ACPI/AML/Node.cpp
kernel/ACPI/AML/Package.cpp
kernel/ACPI/AML/Scope.cpp
kernel/ACPI/AML/OpRegion.cpp
kernel/ACPI/BatterySystem.cpp
kernel/ACPI/EmbeddedController.cpp
kernel/APIC.cpp
kernel/Audio/AC97/Controller.cpp
kernel/Audio/Controller.cpp
kernel/Audio/HDAudio/AudioFunctionGroup.cpp
kernel/Audio/HDAudio/Controller.cpp
kernel/BootInfo.cpp
kernel/CPUID.cpp
kernel/Credentials.cpp
@@ -27,23 +19,29 @@ set(KERNEL_SOURCES
kernel/Device/Device.cpp
kernel/Device/FramebufferDevice.cpp
kernel/Device/NullDevice.cpp
kernel/Device/RandomDevice.cpp
kernel/Device/ZeroDevice.cpp
kernel/ELF.cpp
kernel/Epoll.cpp
kernel/Errors.cpp
kernel/Font.cpp
kernel/FS/DevFS/FileSystem.cpp
kernel/FS/EventFD.cpp
kernel/FS/Ext2/FileSystem.cpp
kernel/FS/Ext2/Inode.cpp
kernel/FS/FAT/FileSystem.cpp
kernel/FS/FAT/Inode.cpp
kernel/FS/FileSystem.cpp
kernel/FS/Inode.cpp
kernel/FS/Pipe.cpp
kernel/FS/ProcFS/FileSystem.cpp
kernel/FS/ProcFS/Inode.cpp
kernel/FS/TmpFS/FileSystem.cpp
kernel/FS/TmpFS/Inode.cpp
kernel/FS/USTARModule.cpp
kernel/FS/VirtualFileSystem.cpp
kernel/GDT.cpp
kernel/IDT.cpp
kernel/Input/KeyboardLayout.cpp
kernel/Input/KeyEvent.cpp
kernel/Input/InputDevice.cpp
kernel/Input/PS2/Controller.cpp
kernel/Input/PS2/Device.cpp
kernel/Input/PS2/Keyboard.cpp
@@ -52,6 +50,8 @@ set(KERNEL_SOURCES
kernel/Interruptable.cpp
kernel/InterruptController.cpp
kernel/kernel.cpp
kernel/Lock/SpinLock.cpp
kernel/Memory/ByteRingBuffer.cpp
kernel/Memory/DMARegion.cpp
kernel/Memory/FileBackedRegion.cpp
kernel/Memory/Heap.cpp
@@ -59,14 +59,18 @@ set(KERNEL_SOURCES
kernel/Memory/MemoryBackedRegion.cpp
kernel/Memory/MemoryRegion.cpp
kernel/Memory/PhysicalRange.cpp
kernel/Memory/SharedMemoryObject.cpp
kernel/Memory/VirtualRange.cpp
kernel/Networking/ARPTable.cpp
kernel/Networking/E1000/E1000.cpp
kernel/Networking/E1000/E1000E.cpp
kernel/Networking/IPv4Layer.cpp
kernel/Networking/Loopback.cpp
kernel/Networking/NetworkInterface.cpp
kernel/Networking/NetworkLayer.cpp
kernel/Networking/NetworkManager.cpp
kernel/Networking/NetworkSocket.cpp
kernel/Networking/RTL8169/RTL8169.cpp
kernel/Networking/TCPSocket.cpp
kernel/Networking/UDPSocket.cpp
kernel/Networking/UNIX/Socket.cpp
@@ -78,7 +82,6 @@ set(KERNEL_SOURCES
kernel/Processor.cpp
kernel/Random.cpp
kernel/Scheduler.cpp
kernel/Semaphore.cpp
kernel/SSP.cpp
kernel/Storage/ATA/AHCI/Controller.cpp
kernel/Storage/ATA/AHCI/Device.cpp
@@ -90,21 +93,38 @@ set(KERNEL_SOURCES
kernel/Storage/NVMe/Namespace.cpp
kernel/Storage/NVMe/Queue.cpp
kernel/Storage/Partition.cpp
kernel/Storage/SCSI.cpp
kernel/Storage/StorageDevice.cpp
kernel/Syscall.cpp
kernel/Terminal/FramebufferTerminal.cpp
kernel/Terminal/PseudoTerminal.cpp
kernel/Terminal/Serial.cpp
kernel/Terminal/TerminalDriver.cpp
kernel/Terminal/TextModeTerminal.cpp
kernel/Terminal/TTY.cpp
kernel/Terminal/VirtualTTY.cpp
kernel/Thread.cpp
kernel/ThreadBlocker.cpp
kernel/Timer/HPET.cpp
kernel/Timer/PIT.cpp
kernel/Timer/RTC.cpp
kernel/Timer/Timer.cpp
kernel/USB/Controller.cpp
kernel/USB/Device.cpp
kernel/USB/HID/HIDDriver.cpp
kernel/USB/HID/Joystick.cpp
kernel/USB/HID/Keyboard.cpp
kernel/USB/HID/Mouse.cpp
kernel/USB/Hub/HubDriver.cpp
kernel/USB/MassStorage/MassStorageDriver.cpp
kernel/USB/MassStorage/SCSIDevice.cpp
kernel/USB/USBManager.cpp
kernel/USB/XHCI/Controller.cpp
kernel/USB/XHCI/Device.cpp
icxxabi.cpp
)
#set(ENABLE_KERNEL_UBSAN True)
set(ENABLE_KERNEL_UBSAN False)
if(ENABLE_KERNEL_UBSAN)
set(KERNEL_SOURCES ${KERNEL_SOURCES} ubsan.cpp)
@@ -119,6 +139,8 @@ if("${BANAN_ARCH}" STREQUAL "x86_64")
arch/x86_64/Signal.S
arch/x86_64/Syscall.S
arch/x86_64/Thread.S
arch/x86_64/User.S
arch/x86_64/Yield.S
)
elseif("${BANAN_ARCH}" STREQUAL "i686")
set(KERNEL_SOURCES
@@ -129,6 +151,8 @@ elseif("${BANAN_ARCH}" STREQUAL "i686")
arch/i686/Signal.S
arch/i686/Syscall.S
arch/i686/Thread.S
arch/i686/User.S
arch/i686/Yield.S
)
else()
message(FATAL_ERROR "unsupported architecure ${BANAN_ARCH}")
@@ -144,62 +168,84 @@ set(BAN_SOURCES
set(KLIBC_SOURCES
klibc/ctype.cpp
klibc/string.cpp
# Ehhh don't do this but for now libc uses the same stuff kernel can use
# This won't work after libc starts using sse implemetations tho
../userspace/libraries/LibC/arch/${BANAN_ARCH}/string.S
)
set(LIBELF_SOURCES
../LibELF/LibELF/LoadableELF.cpp
set(LIBDEFLATE_SOURCE
../userspace/libraries/LibDEFLATE/Compressor.cpp
../userspace/libraries/LibDEFLATE/Decompressor.cpp
../userspace/libraries/LibDEFLATE/HuffmanTree.cpp
)
set(LIBFONT_SOURCES
../userspace/libraries/LibFont/Font.cpp
../userspace/libraries/LibFont/PSF.cpp
)
set(LIBINPUT_SOURCE
../userspace/libraries/LibInput/KeyboardLayout.cpp
../userspace/libraries/LibInput/KeyEvent.cpp
)
set(LIBQR_SOURCE
../userspace/libraries/LibQR/QRCode.cpp
)
set(KERNEL_SOURCES
${KERNEL_SOURCES}
${LAI_SOURCES}
${BAN_SOURCES}
${KLIBC_SOURCES}
${LIBELF_SOURCES}
${LIBDEFLATE_SOURCE}
${LIBFONT_SOURCES}
${LIBINPUT_SOURCE}
${LIBQR_SOURCE}
)
add_executable(kernel ${KERNEL_SOURCES})
add_dependencies(kernel headers)
target_compile_definitions(kernel PUBLIC __is_kernel)
target_compile_definitions(kernel PUBLIC __arch=${BANAN_ARCH})
target_compile_definitions(kernel PRIVATE __is_kernel)
target_compile_definitions(kernel PRIVATE __arch=${BANAN_ARCH})
target_compile_definitions(kernel PRIVATE LIBDEFLATE_AVOID_STACK=1)
target_compile_options(kernel PUBLIC -O2 -g)
target_compile_options(kernel PUBLIC $<$<COMPILE_LANGUAGE:CXX>:-Wno-literal-suffix -fno-rtti -fno-exceptions>)
target_compile_options(kernel PUBLIC -fmacro-prefix-map=${CMAKE_CURRENT_SOURCE_DIR}=.)
target_compile_options(kernel PUBLIC -fstack-protector -ffreestanding -Wall -Wextra -Werror -Wstack-usage=1024 -fno-omit-frame-pointer -mgeneral-regs-only)
target_compile_options(kernel PRIVATE
-O2 -g
-fmacro-prefix-map=${CMAKE_CURRENT_SOURCE_DIR}=.
-fstack-protector
-ffreestanding
-fno-omit-frame-pointer
-fstrict-volatile-bitfields
-mgeneral-regs-only
-Wall -Wextra -Werror -Wstack-usage=1024
)
# This might not work with other toolchains
target_compile_options(kernel PUBLIC $<$<COMPILE_LANGUAGE:CXX>:-Wno-invalid-offsetof>)
# C++ specific
target_compile_options(kernel PRIVATE
-Wno-literal-suffix
-Wno-invalid-offsetof
-fno-rtti
-fno-exceptions
)
if(ENABLE_KERNEL_UBSAN)
target_compile_options(kernel PUBLIC -fsanitize=undefined)
target_compile_options(kernel PRIVATE -fsanitize=undefined)
endif()
if("${BANAN_ARCH}" STREQUAL "x86_64")
target_compile_options(kernel PUBLIC -mcmodel=kernel -mno-red-zone)
target_link_options(kernel PUBLIC LINKER:-z,max-page-size=4096)
target_link_options(kernel PUBLIC LINKER:-T,${CMAKE_CURRENT_SOURCE_DIR}/arch/x86_64/linker.ld)
target_compile_options(kernel PRIVATE -mcmodel=kernel -mno-red-zone)
target_link_options(kernel PRIVATE LINKER:-z,max-page-size=4096)
target_link_options(kernel PRIVATE LINKER:-T,${CMAKE_CURRENT_SOURCE_DIR}/arch/x86_64/linker.ld)
elseif("${BANAN_ARCH}" STREQUAL "i686")
target_link_options(kernel PUBLIC LINKER:-T,${CMAKE_CURRENT_SOURCE_DIR}/arch/i686/linker.ld)
target_link_options(kernel PRIVATE LINKER:-T,${CMAKE_CURRENT_SOURCE_DIR}/arch/i686/linker.ld)
endif()
target_link_options(kernel PUBLIC -ffreestanding -nostdlib)
target_link_options(kernel PRIVATE -ffreestanding -nostdlib -orphan-handling=error)
set_source_files_properties(${LAI_SOURCES} PROPERTIES COMPILE_FLAGS -Wno-stack-usage)
add_custom_target(kernel-headers
COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different ${CMAKE_CURRENT_SOURCE_DIR}/include/ ${BANAN_INCLUDE}/
DEPENDS sysroot
)
add_custom_target(kernel-install
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/kernel ${BANAN_BOOT}/banan-os.kernel
DEPENDS kernel
)
execute_process(COMMAND ${CMAKE_CXX_COMPILER} -print-file-name=crtbegin.o OUTPUT_VARIABLE CRTBEGIN OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND ${CMAKE_CXX_COMPILER} -print-file-name=crtend.o OUTPUT_VARIABLE CRTEND OUTPUT_STRIP_TRAILING_WHITESPACE)
get_target_property(KERNEL_COMPILE_OPTIONS kernel COMPILE_OPTIONS)
execute_process(COMMAND ${CMAKE_CXX_COMPILER} ${KERNEL_COMPILE_OPTIONS} -print-file-name=crtbegin.o OUTPUT_VARIABLE CRTBEGIN OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND ${CMAKE_CXX_COMPILER} ${KERNEL_COMPILE_OPTIONS} -print-file-name=crtend.o OUTPUT_VARIABLE CRTEND OUTPUT_STRIP_TRAILING_WHITESPACE)
add_custom_command(
TARGET kernel PRE_LINK
@@ -214,9 +260,27 @@ add_custom_command(
# COMMAND x86_64-banan_os-strip ${CMAKE_CURRENT_BINARY_DIR}/kernel
#)
banan_include_headers(kernel ban)
banan_include_headers(kernel libc)
banan_include_headers(kernel libdeflate)
banan_include_headers(kernel libelf)
banan_include_headers(kernel libfont)
banan_include_headers(kernel libinput)
banan_include_headers(kernel libqr)
banan_install_headers(kernel)
set_target_properties(kernel PROPERTIES OUTPUT_NAME banan-os.kernel)
install(TARGETS kernel DESTINATION ${BANAN_BOOT} OPTIONAL)
if("${BANAN_ARCH}" STREQUAL "x86_64")
set(ELF_FORMAT elf64-x86-64)
elseif("${BANAN_ARCH}" STREQUAL "i686")
set(ELF_FORMAT elf32-i386)
endif()
add_custom_command(
OUTPUT font/prefs.psf.o
COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && objcopy -O ${ELF_FORMAT} -B i386 -I binary font/prefs.psf ${CMAKE_CURRENT_BINARY_DIR}/font/prefs.psf.o
COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/font && objcopy -O ${ELF_FORMAT} -B i386 -I binary font/prefs.psf ${CMAKE_CURRENT_BINARY_DIR}/font/prefs.psf.o
)
set(CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_COMPILER} <CMAKE_CXX_LINK_FLAGS> <FLAGS> <LINK_FLAGS> -o <TARGET> ${CMAKE_CURRENT_BINARY_DIR}/crti.o ${CMAKE_CURRENT_BINARY_DIR}/crtbegin.o <OBJECTS> ${CMAKE_CURRENT_BINARY_DIR}/crtend.o ${CMAKE_CURRENT_BINARY_DIR}/crtn.o -lgcc ")

View File

@@ -1,3 +1,4 @@
#include <kernel/BootInfo.h>
#include <kernel/CPUID.h>
#include <kernel/Lock/SpinLock.h>
#include <kernel/Memory/kmalloc.h>
@@ -9,17 +10,21 @@ extern uint8_t g_kernel_end[];
extern uint8_t g_kernel_execute_start[];
extern uint8_t g_kernel_execute_end[];
extern uint8_t g_kernel_writable_start[];
extern uint8_t g_kernel_writable_end[];
extern uint8_t g_userspace_start[];
extern uint8_t g_userspace_end[];
namespace Kernel
{
RecursiveSpinLock PageTable::s_fast_page_lock;
SpinLock PageTable::s_fast_page_lock;
static PageTable* s_kernel = nullptr;
static bool s_has_nxe = false;
static bool s_has_pge = false;
static bool s_has_pat = false;
static paddr_t s_global_pdpte = 0;
@@ -32,8 +37,6 @@ namespace Kernel
result |= Flags::Execute;
if (entry & Flags::Reserved)
result |= Flags::Reserved;
if (entry & Flags::CacheDisable)
result |= Flags::CacheDisable;
if (entry & Flags::UserSupervisor)
result |= Flags::UserSupervisor;
if (entry & Flags::ReadWrite)
@@ -43,7 +46,7 @@ namespace Kernel
return result;
}
void PageTable::initialize()
void PageTable::initialize_pre_heap()
{
if (CPUID::has_nxe())
s_has_nxe = true;
@@ -51,6 +54,9 @@ namespace Kernel
if (CPUID::has_pge())
s_has_pge = true;
if (CPUID::has_pat())
s_has_pat = true;
ASSERT(s_kernel == nullptr);
s_kernel = new PageTable();
ASSERT(s_kernel);
@@ -59,6 +65,11 @@ namespace Kernel
s_kernel->initial_load();
}
void PageTable::initialize_post_heap()
{
// NOTE: this is no-op as our 32 bit target does not use hhdm
}
void PageTable::initial_load()
{
if (s_has_nxe)
@@ -82,6 +93,17 @@ namespace Kernel
);
}
if (s_has_pat)
{
asm volatile(
"movl $0x277, %%ecx;"
"rdmsr;"
"movw $0x0401, %%dx;"
"wrmsr;"
::: "eax", "ecx", "edx", "memory"
);
}
// enable write protect
asm volatile(
"movl %%cr0, %%eax;"
@@ -112,6 +134,18 @@ namespace Kernel
return (uint64_t*)page;
}
template<typename T>
static paddr_t V2P(const T vaddr)
{
return (vaddr_t)vaddr - KERNEL_OFFSET + g_boot_info.kernel_paddr;
}
template<typename T>
static vaddr_t P2V(const T paddr)
{
return (paddr_t)paddr - g_boot_info.kernel_paddr + KERNEL_OFFSET;
}
void PageTable::initialize_kernel()
{
ASSERT(s_global_pdpte == 0);
@@ -121,21 +155,13 @@ namespace Kernel
prepare_fast_page();
// Map main bios area below 1 MiB
map_range_at(
0x000E0000,
P2V(0x000E0000),
0x00100000 - 0x000E0000,
PageTable::Flags::Present
);
// Map (phys_kernel_start -> phys_kernel_end) to (virt_kernel_start -> virt_kernel_end)
ASSERT((vaddr_t)g_kernel_start % PAGE_SIZE == 0);
map_range_at(
V2P(g_kernel_start),
(vaddr_t)g_kernel_start,
g_kernel_end - g_kernel_start,
Flags::ReadWrite | Flags::Present
Flags::Present
);
// Map executable kernel memory as executable
@@ -146,6 +172,14 @@ namespace Kernel
Flags::Execute | Flags::Present
);
// Map writable kernel memory as writable
map_range_at(
V2P(g_kernel_writable_start),
(vaddr_t)g_kernel_writable_start,
g_kernel_writable_end - g_kernel_writable_start,
Flags::ReadWrite | Flags::Present
);
// Map userspace memory
map_range_at(
V2P(g_userspace_start),
@@ -159,7 +193,6 @@ namespace Kernel
{
constexpr uint64_t pdpte = (fast_page() >> 30) & 0x1FF;
constexpr uint64_t pde = (fast_page() >> 21) & 0x1FF;
constexpr uint64_t pte = (fast_page() >> 12) & 0x1FF;
uint64_t* pdpt = reinterpret_cast<uint64_t*>(P2V(m_highest_paging_struct));
ASSERT(pdpt[pdpte] & Flags::Present);
@@ -167,18 +200,15 @@ namespace Kernel
uint64_t* pd = reinterpret_cast<uint64_t*>(P2V(pdpt[pdpte]) & PAGE_ADDR_MASK);
ASSERT(!(pd[pde] & Flags::Present));
pd[pde] = V2P(allocate_zeroed_page_aligned_page()) | Flags::ReadWrite | Flags::Present;
uint64_t* pt = reinterpret_cast<uint64_t*>(P2V(pd[pde]) & PAGE_ADDR_MASK);
ASSERT(!(pt[pte] & Flags::Present));
pt[pte] = V2P(allocate_zeroed_page_aligned_page());
}
void PageTable::map_fast_page(paddr_t paddr)
{
ASSERT(s_kernel);
ASSERT(paddr);
ASSERT(paddr % PAGE_SIZE == 0);
SpinLockGuard _(s_fast_page_lock);
ASSERT(s_fast_page_lock.current_processor_has_lock());
constexpr uint64_t pdpte = (fast_page() >> 30) & 0x1FF;
constexpr uint64_t pde = (fast_page() >> 21) & 0x1FF;
@@ -191,14 +221,14 @@ namespace Kernel
ASSERT(!(pt[pte] & Flags::Present));
pt[pte] = paddr | Flags::ReadWrite | Flags::Present;
invalidate(fast_page());
asm volatile("invlpg (%0)" :: "r"(fast_page()) : "memory");
}
void PageTable::unmap_fast_page()
{
ASSERT(s_kernel);
SpinLockGuard _(s_fast_page_lock);
ASSERT(s_fast_page_lock.current_processor_has_lock());
constexpr uint64_t pdpte = (fast_page() >> 30) & 0x1FF;
constexpr uint64_t pde = (fast_page() >> 21) & 0x1FF;
@@ -211,7 +241,7 @@ namespace Kernel
ASSERT(pt[pte] & Flags::Present);
pt[pte] = 0;
invalidate(fast_page());
asm volatile("invlpg (%0)" :: "r"(fast_page()) : "memory");
}
BAN::ErrorOr<PageTable*> PageTable::create_userspace()
@@ -243,6 +273,9 @@ namespace Kernel
PageTable::~PageTable()
{
if (m_highest_paging_struct == 0)
return;
uint64_t* pdpt = reinterpret_cast<uint64_t*>(P2V(m_highest_paging_struct));
for (uint32_t pdpte = 0; pdpte < 3; pdpte++)
@@ -270,13 +303,25 @@ namespace Kernel
Processor::set_current_page_table(this);
}
void PageTable::invalidate(vaddr_t vaddr)
void PageTable::invalidate(vaddr_t vaddr, bool send_smp_message)
{
ASSERT(vaddr % PAGE_SIZE == 0);
asm volatile("invlpg (%0)" :: "r"(vaddr) : "memory");
if (send_smp_message)
{
Processor::broadcast_smp_message({
.type = Processor::SMPMessage::Type::FlushTLB,
.flush_tlb = {
.vaddr = vaddr,
.page_count = 1,
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
}
});
}
}
void PageTable::unmap_page(vaddr_t vaddr)
void PageTable::unmap_page(vaddr_t vaddr, bool send_smp_message)
{
ASSERT(vaddr);
ASSERT(vaddr % PAGE_SIZE == 0);
@@ -293,30 +338,41 @@ namespace Kernel
SpinLockGuard _(m_lock);
if (is_page_free(vaddr))
{
dwarnln("unmapping unmapped page {8H}", vaddr);
return;
}
Kernel::panic("trying to unmap unmapped page 0x{H}", vaddr);
uint64_t* pdpt = reinterpret_cast<uint64_t*>(P2V(m_highest_paging_struct));
uint64_t* pd = reinterpret_cast<uint64_t*>(P2V(pdpt[pdpte] & PAGE_ADDR_MASK));
uint64_t* pt = reinterpret_cast<uint64_t*>(P2V(pd[pde] & PAGE_ADDR_MASK));
const paddr_t old_paddr = pt[pte] & PAGE_ADDR_MASK;
pt[pte] = 0;
invalidate(vaddr);
if (old_paddr != 0)
invalidate(vaddr, send_smp_message);
}
void PageTable::unmap_range(vaddr_t vaddr, size_t size)
{
vaddr_t s_page = vaddr / PAGE_SIZE;
vaddr_t e_page = BAN::Math::div_round_up<vaddr_t>(vaddr + size, PAGE_SIZE);
ASSERT(vaddr % PAGE_SIZE == 0);
size_t page_count = range_page_count(vaddr, size);
SpinLockGuard _(m_lock);
for (vaddr_t page = s_page; page < e_page; page++)
unmap_page(page * PAGE_SIZE);
for (vaddr_t page = 0; page < page_count; page++)
unmap_page(vaddr + page * PAGE_SIZE, false);
Processor::broadcast_smp_message({
.type = Processor::SMPMessage::Type::FlushTLB,
.flush_tlb = {
.vaddr = vaddr,
.page_count = page_count,
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
}
});
}
void PageTable::map_page_at(paddr_t paddr, vaddr_t vaddr, flags_t flags)
void PageTable::map_page_at(paddr_t paddr, vaddr_t vaddr, flags_t flags, MemoryType memory_type, bool send_smp_message)
{
ASSERT(vaddr);
ASSERT(vaddr != fast_page());
@@ -338,8 +394,13 @@ namespace Kernel
extra_flags |= 1ull << 63;
if (flags & Flags::Reserved)
extra_flags |= Flags::Reserved;
if (flags & Flags::CacheDisable)
extra_flags |= Flags::CacheDisable;
if (memory_type == MemoryType::Uncached)
extra_flags |= (1ull << 4);
if (s_has_pat && memory_type == MemoryType::WriteCombining)
extra_flags |= (1ull << 7);
if (s_has_pat && memory_type == MemoryType::WriteThrough)
extra_flags |= (1ull << 7) | (1ull << 3);
// NOTE: we add present here, since it has to be available in higher level structures
flags_t uwr_flags = (flags & (Flags::UserSupervisor | Flags::ReadWrite)) | Flags::Present;
@@ -362,12 +423,16 @@ namespace Kernel
uwr_flags &= ~Flags::Present;
uint64_t* pt = reinterpret_cast<uint64_t*>(P2V(pd[pde] & PAGE_ADDR_MASK));
const paddr_t old_paddr = pt[pte] & PAGE_ADDR_MASK;
pt[pte] = paddr | uwr_flags | extra_flags;
invalidate(vaddr);
if (old_paddr != 0)
invalidate(vaddr, send_smp_message);
}
void PageTable::map_range_at(paddr_t paddr, vaddr_t vaddr, size_t size, flags_t flags)
void PageTable::map_range_at(paddr_t paddr, vaddr_t vaddr, size_t size, flags_t flags, MemoryType memory_type)
{
ASSERT(vaddr);
ASSERT(paddr % PAGE_SIZE == 0);
@@ -377,7 +442,16 @@ namespace Kernel
SpinLockGuard _(m_lock);
for (size_t page = 0; page < page_count; page++)
map_page_at(paddr + page * PAGE_SIZE, vaddr + page * PAGE_SIZE, flags);
map_page_at(paddr + page * PAGE_SIZE, vaddr + page * PAGE_SIZE, flags, memory_type, false);
Processor::broadcast_smp_message({
.type = Processor::SMPMessage::Type::FlushTLB,
.flush_tlb = {
.vaddr = vaddr,
.page_count = page_count,
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
}
});
}
uint64_t PageTable::get_page_data(vaddr_t vaddr) const
@@ -434,13 +508,13 @@ namespace Kernel
return true;
}
bool PageTable::reserve_page(vaddr_t vaddr, bool only_free)
bool PageTable::reserve_page(vaddr_t vaddr, bool only_free, bool send_smp_message)
{
SpinLockGuard _(m_lock);
ASSERT(vaddr % PAGE_SIZE == 0);
if (only_free && !is_page_free(vaddr))
return false;
map_page_at(0, vaddr, Flags::Reserved);
map_page_at(0, vaddr, Flags::Reserved, MemoryType::Normal, send_smp_message);
return true;
}
@@ -454,7 +528,15 @@ namespace Kernel
if (only_free && !is_range_free(vaddr, bytes))
return false;
for (size_t offset = 0; offset < bytes; offset += PAGE_SIZE)
reserve_page(vaddr + offset);
reserve_page(vaddr + offset, true, false);
Processor::broadcast_smp_message({
.type = Processor::SMPMessage::Type::FlushTLB,
.flush_tlb = {
.vaddr = vaddr,
.page_count = bytes / PAGE_SIZE,
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
}
});
return true;
}

View File

@@ -1,35 +1,73 @@
.section .userspace, "aw"
.section .userspace, "ax"
// stack contains
// return address
// return stack
// return rflags
// siginfo_t
// signal number
// signal handler
.global signal_trampoline
signal_trampoline:
pushl %esi // gregs
pushl %edi
pushl %edx
pushl %ecx
pushl %ebx
pushl %eax
pushl %ebp
movl %esp, %ebp
pusha
// FIXME: populate these
xorl %eax, %eax
pushl %eax // stack
pushl %eax
pushl %eax
pushl %eax // sigset
pushl %eax
pushl %eax // link
movl 40(%esp), %edi
movl 36(%esp), %eax
movl %esp, %edx // ucontext
leal 60(%esp), %esi // siginfo
movl 56(%esp), %edi // signal number
movl 52(%esp), %eax // handlers
// align stack to 16 bytes
movl %esp, %ebx
andl $0x0F, %ebx
subl %ebx, %esp
movl %esp, %ebp
andl $-16, %esp
subl $12, %esp
subl $512, %esp
fxsave (%esp)
subl $4, %esp
pushl %edx
pushl %esi
pushl %edi
call *%eax
addl $16, %esp
// restore stack
addl %ebx, %esp
popa
fxrstor (%esp)
addl $512, %esp
leave
addl $8, %esp
// restore stack
movl %ebp, %esp
addl $24, %esp
// restore registers
popl %ebp
popl %eax
popl %ebx
popl %ecx
popl %edx
popl %edi
popl %esi
// skip handler, number, siginfo_t
addl $44, %esp
// restore flags
popf
movl (%esp), %esp
ret

View File

@@ -1,12 +1,6 @@
// arguments in EAX, EBX, ECX, EDX, ESI, EDI
.global asm_syscall_handler
asm_syscall_handler:
# save segment registers
pushw %ds
pushw %es
pushw %fs
pushw %gs
# save general purpose registers
pushl %ebx
pushl %ecx
@@ -14,10 +8,14 @@ asm_syscall_handler:
pushl %edi
pushl %esi
pushl %ebp
cld
# align stack and push arguments
pushl %esp
addl $32, (%esp)
# align stack
movl %esp, %ebp
andl $-16, %esp
# push arguments
subl $8, %esp
pushl %edi
pushl %esi
pushl %edx
@@ -34,7 +32,17 @@ asm_syscall_handler:
movw %ax, %gs
call cpp_syscall_handler
addl $28, %esp
movl %ebp, %esp
# restore userspace segments
movw $(0x20 | 3), %bx
movw %bx, %ds
movw %bx, %es
movw $(0x30 | 3), %bx
movw %bx, %fs
movw $(0x38 | 3), %bx
movw %bx, %gs
# restore general purpose registers
popl %ebp
@@ -44,12 +52,6 @@ asm_syscall_handler:
popl %ecx
popl %ebx
# restore segment registers
popw %gs
popw %fs
popw %es
popw %ds
iret
.global sys_fork_trampoline

View File

@@ -31,38 +31,18 @@ start_kernel_thread:
subl $12, %esp
pushl %edi
call *%esi
addl $16, %esp
.global start_userspace_thread
start_userspace_thread:
call get_thread_start_sp
movl %eax, %esp
# STACK LAYOUT
# entry
# argc
# argv
# envp
# userspace stack
call get_userspace_thread_stack_top
movw $(0x20 | 3), %bx
movw %bx, %ds
movw %bx, %es
movw $(0x30 | 3), %bx
movw %bx, %fs
movw $(0x38 | 3), %bx
movw %bx, %gs
xorw %bx, %bx
popl %edx
popl %esi
popl %edi
popl %ecx
pushl $(0x20 | 3)
pushl %eax
pushl $0x202
pushl $(0x18 | 3)
pushl %ecx
iret

54
kernel/arch/i686/User.S Normal file
View File

@@ -0,0 +1,54 @@
# bool safe_user_memcpy(void*, const void*, size_t)
.global safe_user_memcpy
.global safe_user_memcpy_end
.global safe_user_memcpy_fault
safe_user_memcpy:
xorl %eax, %eax
xchgl 4(%esp), %edi
xchgl 8(%esp), %esi
movl 12(%esp), %ecx
movl %edi, %edx
rep movsb
movl 4(%esp), %edi
movl 8(%esp), %esi
incl %eax
safe_user_memcpy_fault:
ret
safe_user_memcpy_end:
# bool safe_user_strncpy(void*, const void*, size_t)
.global safe_user_strncpy
.global safe_user_strncpy_end
.global safe_user_strncpy_fault
safe_user_strncpy:
xchgl 4(%esp), %edi
xchgl 8(%esp), %esi
movl 12(%esp), %ecx
testl %ecx, %ecx
jz safe_user_strncpy_fault
.safe_user_strncpy_loop:
movb (%esi), %al
movb %al, (%edi)
testb %al, %al
jz .safe_user_strncpy_done
incl %edi
incl %esi
decl %ecx
jnz .safe_user_strncpy_loop
safe_user_strncpy_fault:
xorl %eax, %eax
jmp .safe_user_strncpy_return
.safe_user_strncpy_done:
movl $1, %eax
.safe_user_strncpy_return:
movl 4(%esp), %edi
movl 8(%esp), %esi
ret
safe_user_strncpy_end:

25
kernel/arch/i686/Yield.S Normal file
View File

@@ -0,0 +1,25 @@
.global asm_yield_trampoline
asm_yield_trampoline:
leal 4(%esp), %ecx
movl 4(%esp), %esp
pushl -4(%ecx)
pushl %ecx
pushl %eax
pushl %ebx
pushl %esi
pushl %edi
pushl %ebp
pushl %esp
call scheduler_on_yield
addl $4, %esp
popl %ebp
popl %edi
popl %esi
popl %ebx
popl %eax
movl 4(%esp), %ecx
movl 0(%esp), %esp
jmp *%ecx

View File

@@ -14,6 +14,23 @@
# multiboot2 header
.section .multiboot, "aw"
.align 8
multiboot_start:
.long 0x1BADB002
.long (1 << 2) # page align modules
.long -(0x1BADB002 + (1 << 2))
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long FB_WIDTH
.long FB_HEIGHT
.long FB_BPP
multiboot_end:
.align 8
multiboot2_start:
.long 0xE85250D6
.long 0
@@ -36,6 +53,12 @@ multiboot2_start:
.long 12
.long V2P(_start)
# page align modules
.align 8
.short 6
.short 0
.long 8
.align 8
.short 0
.short 0
@@ -53,10 +76,10 @@ bananboot_start:
bananboot_end:
.section .bss, "aw", @nobits
.align 4096
boot_stack_bottom:
.global g_boot_stack_top
g_boot_stack_bottom:
.skip 4096 * 4
boot_stack_top:
g_boot_stack_top:
.global g_kernel_cmdline
g_kernel_cmdline:
@@ -161,6 +184,13 @@ enable_sse:
movl %eax, %cr4
ret
enable_tsc:
# allow userspace to use RDTSC
movl %cr4, %ecx
andl $0xFFFFFFFB, %ecx
movl %ecx, %cr4
ret
initialize_paging:
# enable PAE
movl %cr4, %ecx
@@ -188,7 +218,7 @@ _start:
movl %ebx, V2P(bootloader_info)
# load boot stack
movl $V2P(boot_stack_top), %esp
movl $V2P(g_boot_stack_top), %esp
# load boot GDT
lgdt V2P(boot_gdtr)
@@ -203,10 +233,11 @@ gdt_flush:
# do processor initialization
call check_requirements
call enable_sse
call enable_tsc
call initialize_paging
# load higher half stack pointer
movl $boot_stack_top, %esp
movl $g_boot_stack_top, %esp
# jump to higher half
leal higher_half, %ecx
@@ -216,6 +247,13 @@ higher_half:
# call global constuctors
call _init
movl $g_init_array_start, %ebx
jmp 2f
1: call *(%ebx)
addl $4, %ebx
2: cmpl $g_init_array_end, %ebx
jne 1b
# call to the kernel itself (clear ebp for stacktrace)
xorl %ebp, %ebp
@@ -235,26 +273,31 @@ system_halt:
jmp 1b
#define AP_V2P(vaddr) ((vaddr) - ap_trampoline + 0xF000)
.section .ap_init, "ax"
.code16
.global ap_trampoline
ap_trampoline:
jmp 1f
.align 8
ap_stack_ptr:
.skip 4
1:
cli; cld
ljmpl $0x00, $ap_cs_clear
ap_cs_clear:
ap_stack_loaded:
.skip 1
1: cli; cld
ljmpl $0x00, $AP_V2P(ap_cs_clear)
ap_cs_clear:
# load ap gdt and enter protected mode
lgdt ap_gdtr
lgdt AP_V2P(ap_gdtr)
movl %cr0, %eax
orb $1, %al
movl %eax, %cr0
ljmpl $0x08, $ap_protected_mode
ljmpl $0x08, $AP_V2P(ap_protected_mode)
.code32
ap_protected_mode:
@@ -263,16 +306,16 @@ ap_protected_mode:
movw %ax, %ss
movw %ax, %es
movl ap_stack_ptr, %esp
movb $1, V2P(g_ap_stack_loaded)
movl AP_V2P(ap_stack_ptr), %esp
movb $1, AP_V2P(ap_stack_loaded)
call V2P(enable_sse)
call V2P(initialize_paging)
leal V2P(enable_sse), %ecx; call *%ecx
leal V2P(enable_tsc), %ecx; call *%ecx
leal V2P(initialize_paging), %ecx; call *%ecx
# load boot gdt and enter long mode
lgdt V2P(boot_gdtr)
ljmpl $0x08, $ap_flush_gdt
ljmpl $0x08, $AP_V2P(ap_flush_gdt)
ap_flush_gdt:
# move stack pointer to higher half

View File

@@ -1,23 +0,0 @@
.section .text
.global _start
_start:
# Set up end of the stack frame linked list.
movl $0, %ebp
pushl %ebp # rip=0
pushl %ebp # rbp=0
movl %esp, %ebp
# Prepare signals, memory allocation, stdio and such.
#call initialize_standard_library
# Run the global constructors.
call _init
# Run main
call main
# Terminate the process with the exit code.
movl %eax, %edi
call exit
.size _start, . - _start

View File

@@ -1,9 +1,9 @@
/* x86 crti.s */
/* i686 crti.s */
.section .init
.global _init
.type _init, @function
_init:
push %ebp
pushl %ebp
movl %esp, %ebp
/* gcc will nicely put the contents of crtbegin.o's .init section here. */
@@ -11,6 +11,6 @@ _init:
.global _fini
.type _fini, @function
_fini:
push %ebp
pushl %ebp
movl %esp, %ebp
/* gcc will nicely put the contents of crtbegin.o's .fini section here. */

View File

@@ -1,4 +1,4 @@
/* x86 crtn.s */
/* i686 crtn.s */
.section .init
/* gcc will nicely put the contents of crtend.o's .init section here. */
popl %ebp

View File

@@ -1,84 +1,119 @@
.macro push_userspace
pushw %gs
pushw %fs
pushw %es
pushw %ds
pushal
.endm
.macro maybe_load_kernel_segments, n
testb $3, \n(%esp)
jz 1f; jnp 1f
.macro load_kernel_segments
movw $0x10, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw $0x28, %ax
movw %ax, %gs
1:
.endm
.macro pop_userspace
popal
popw %ds
popw %es
popw %fs
popw %gs
.macro maybe_load_userspace_segments, n
testb $3, \n(%esp)
jz 1f; jnp 1f
movw $(0x20 | 3), %bx
movw %bx, %ds
movw %bx, %es
movw $(0x30 | 3), %bx
movw %bx, %fs
movw $(0x38 | 3), %bx
movw %bx, %gs
1:
.endm
isr_stub:
push_userspace
load_kernel_segments
pushal
maybe_load_kernel_segments 44
cld
movl %cr0, %eax; pushl %eax
movl %cr2, %eax; pushl %eax
movl %cr3, %eax; pushl %eax
movl %cr4, %eax; pushl %eax
movl %esp, %eax // register ptr
leal 64(%esp), %ebx // interrupt stack ptr
movl 60(%esp), %ecx // error code
movl 56(%esp), %edx // isr number
movl 48(%esp), %edi // isr number
movl 52(%esp), %esi // error code
leal 56(%esp), %edx // interrupt stack ptr
movl %esp, %ecx // register ptr
# stack frame for stack trace
leal 56(%esp), %eax
pushl (%eax)
pushl %ebp
movl %esp, %ebp
andl $-16, %esp
subl $12, %esp
pushl %eax
pushl %ebx
pushl %ecx
pushl %edx
pushl %esi
pushl %edi
call cpp_isr_handler
addl $44, %esp
pop_userspace
movl %ebp, %esp
addl $24, %esp
maybe_load_userspace_segments 44
popal
addl $8, %esp
iret
irq_stub:
push_userspace
load_kernel_segments
pushal
maybe_load_kernel_segments 44
cld
movl 40(%esp), %eax # interrupt number
movl 32(%esp), %edi # interrupt number
movl %esp, %ebp
andl $-16, %esp
subl $12, %esp
pushl %eax
pushl %edi
call cpp_irq_handler
addl $16, %esp
pop_userspace
movl %ebp, %esp
maybe_load_userspace_segments 44
popal
addl $8, %esp
iret
.global asm_yield_handler
asm_yield_handler:
# This can only be called from kernel, so no segment saving is needed
.global asm_ipi_handler
asm_ipi_handler:
pushal
maybe_load_kernel_segments 36
cld
movl %esp, %eax # interrupt registers ptr
leal 32(%esp), %ebx # interrupt stack ptr
movl %esp, %ebp
andl $-16, %esp
subl $4, %esp
pushl %eax
pushl %ebx
call cpp_yield_handler
addl $12, %esp
call cpp_ipi_handler
movl %ebp, %esp
maybe_load_userspace_segments 36
popal
iret
.global asm_timer_handler
asm_timer_handler:
pushal
maybe_load_kernel_segments 36
cld
movl %esp, %ebp
andl $-16, %esp
call cpp_timer_handler
movl %ebp, %esp
maybe_load_userspace_segments 36
popal
iret
@@ -138,36 +173,26 @@ isr 29
isr 30
isr 31
irq 0
irq 1
irq 2
irq 3
irq 4
irq 5
irq 6
irq 7
irq 8
irq 9
irq 10
irq 11
irq 12
irq 13
irq 14
irq 15
irq 16
irq 17
irq 18
irq 19
irq 20
irq 21
irq 22
irq 23
irq 24
irq 25
irq 26
irq 27
irq 28
irq 29
irq 30
irq 31
irq 32
.irp i, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, \
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, \
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, \
30, 31, 32, 33, 34, 35, 36, 37, 38, 39, \
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, \
50, 51, 52, 53, 54, 55, 56, 57, 58, 59, \
60, 61, 62, 63, 64, 65, 66, 67, 68, 69, \
70, 71, 72, 73, 74, 75, 76, 77, 78, 79, \
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, \
90, 91, 92, 93, 94, 95, 96, 97, 98, 99, \
100,101,102,103,104,105,106,107,108,109, \
110,111,112,113,114,115,116,117,118,119, \
120,121,122,123,124,125,126,127,128,129, \
130,131,132,133,134,135,136,137,138,139, \
140,141,142,143,144,145,146,147,148,149, \
150,151,152,153,154,155,156,157,158,159, \
160,161,162,163,164,165,166,167,168,169, \
170,171,172,173,174,175,176,177,178,179, \
180,181,182,183,184,185,186,187,188,189, \
190,191,192,193,194,195,196,197,198,199, \
200,201,202,203,204,205,206,207
irq \i
.endr

View File

@@ -4,13 +4,6 @@ KERNEL_OFFSET = 0xC0000000;
SECTIONS
{
. = 0xF000;
.ap_init ALIGN(4K) : AT(ADDR(.ap_init))
{
g_ap_init_addr = .;
*(.ap_init)
}
. = 0x00100000 + KERNEL_OFFSET;
g_kernel_start = .;
@@ -28,18 +21,31 @@ SECTIONS
g_userspace_end = .;
g_kernel_execute_end = .;
}
.ap_init ALIGN(4K) : AT(ADDR(.ap_init) - KERNEL_OFFSET)
{
g_ap_init_addr = .;
*(.ap_init)
}
.rodata ALIGN(4K) : AT(ADDR(.rodata) - KERNEL_OFFSET)
{
*(.rodata.*)
}
.init_array ALIGN(4K) : AT(ADDR(.init_array) - KERNEL_OFFSET)
{
g_init_array_start = .;
*(.init_array)
g_init_array_end = .;
}
.data ALIGN(4K) : AT(ADDR(.data) - KERNEL_OFFSET)
{
g_kernel_writable_start = .;
*(.data)
}
.bss ALIGN(4K) : AT(ADDR(.bss) - KERNEL_OFFSET)
{
*(COMMON)
*(.bss)
g_kernel_writable_end = .;
}
g_kernel_end = .;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,57 +1,84 @@
.section .userspace, "aw"
.section .userspace, "ax"
// stack contains
// return address
// return stack
// return rflags
// siginfo_t
// signal number
// signal handler
.global signal_trampoline
signal_trampoline:
pushq %rax
pushq %rbx
pushq %rcx
pushq %rdx
pushq %rbp
pushq %rdi
pushq %rsi
pushq %r8
pushq %r9
pushq %r10
pushq %r11
pushq %r12
pushq %r13
pushq %r15 // gregs
pushq %r14
pushq %r15
pushq %r13
pushq %r12
pushq %r11
pushq %r10
pushq %r9
pushq %r8
pushq %rsi
pushq %rdi
pushq %rdx
pushq %rcx
pushq %rbx
pushq %rax
pushq %rbp
movq 128(%rsp), %rdi
movq 120(%rsp), %rax
// FIXME: populate these
xorq %rax, %rax
pushq %rax // stack
pushq %rax
pushq %rax
pushq %rax // sigset
pushq %rax // link
movq %rsp, %rdx // ucontext
leaq 176(%rsp), %rsi // siginfo
movq 168(%rsp), %rdi // signal number
movq 160(%rsp), %rax // handler
// align stack to 16 bytes
movq %rsp, %rbx
andq $0x0F, %rbx
subq %rbx, %rsp
movq %rsp, %rbp
andq $-16, %rsp
subq $512, %rsp
fxsave64 (%rsp)
call *%rax
fxrstor64 (%rsp)
addq $512, %rsp
// restore stack
addq %rbx, %rsp
popq %r15
popq %r14
popq %r13
popq %r12
popq %r11
popq %r10
popq %r9
popq %r8
popq %rsi
popq %rdi
movq %rbp, %rsp
addq $40, %rsp
// restore registers
popq %rbp
popq %rdx
popq %rcx
popq %rbx
popq %rax
popq %rbx
popq %rcx
popq %rdx
popq %rdi
popq %rsi
popq %r8
popq %r9
popq %r10
popq %r11
popq %r12
popq %r13
popq %r14
popq %r15
addq $16, %rsp
// skip handler, number, siginfo_t
addq $72, %rsp
// return over red-zone
// restore flags
popfq
movq (%rsp), %rsp
// return over red-zone and siginfo_t
ret $128

View File

@@ -1,48 +1,26 @@
// arguments in RAX, RBX, RCX, RDX, RSI, RDI
// System V ABI: RDI, RSI, RDX, RCX, R8, R9
.global asm_syscall_handler
asm_syscall_handler:
pushq %rbx
pushq %rcx
pushq %rdx
pushq %rdi
pushq %rsi
pushq %rbp
pushq %r8
pushq %r9
pushq %r10
swapgs
movq %rsp, %rax
movq %gs:8, %rsp
pushq $(0x20 | 3)
pushq %rax
pushq %r11
pushq %r12
pushq %r13
pushq %r14
pushq %r15
pushq $(0x28 | 3)
pushq %rcx
subq $8, %rsp
movq %rsi, %r8
movq %rdi, %r9
movq %rax, %rdi
movq %rbx, %rsi
xchgq %rcx, %rdx
leaq 112(%rsp), %rbx
pushq %rbx
movq %r10, %rcx
call cpp_syscall_handler
addq $8, %rsp
popq %r15
popq %r14
popq %r13
popq %r12
popq %r11
popq %r10
popq %r9
popq %r8
popq %rbp
popq %rsi
popq %rdi
popq %rdx
popq %rcx
popq %rbx
iretq
movq 8(%rsp), %rcx
movq 24(%rsp), %r11
movq 32(%rsp), %rsp
swapgs
sysretq
.global sys_fork_trampoline
sys_fork_trampoline:
@@ -55,7 +33,7 @@ sys_fork_trampoline:
call read_ip
testq %rax, %rax
je .reload_stack
je .done
movq %rax, %rsi
movq %rsp, %rdi
@@ -69,9 +47,3 @@ sys_fork_trampoline:
popq %rbp
popq %rbx
ret
.reload_stack:
call get_thread_start_sp
movq %rax, %rsp
xorq %rax, %rax
jmp .done

View File

@@ -30,23 +30,6 @@ start_userspace_thread:
call get_thread_start_sp
movq %rax, %rsp
# STACK LAYOUT
# entry
# argc
# argv
# envp
# userspace stack
swapgs
call get_userspace_thread_stack_top
popq %rdx
popq %rsi
popq %rdi
popq %rcx
pushq $(0x20 | 3)
pushq %rax
pushq $0x202
pushq $(0x18 | 3)
pushq %rcx
iretq

87
kernel/arch/x86_64/User.S Normal file
View File

@@ -0,0 +1,87 @@
# bool safe_user_memcpy(void*, const void*, size_t)
.global safe_user_memcpy
.global safe_user_memcpy_end
.global safe_user_memcpy_fault
safe_user_memcpy:
xorq %rax, %rax
movq %rdx, %rcx
rep movsb
incq %rax
safe_user_memcpy_fault:
ret
safe_user_memcpy_end:
# bool safe_user_strncpy(void*, const void*, size_t)
.global safe_user_strncpy
.global safe_user_strncpy_end
.global safe_user_strncpy_fault
safe_user_strncpy:
movq %rdx, %rcx
testq %rcx, %rcx
jz safe_user_strncpy_fault
.safe_user_strncpy_align_loop:
testb $0x7, %sil
jz .safe_user_strncpy_align_done
movb (%rsi), %al
movb %al, (%rdi)
testb %al, %al
jz .safe_user_strncpy_done
incq %rdi
incq %rsi
decq %rcx
jnz .safe_user_strncpy_align_loop
jmp safe_user_strncpy_fault
.safe_user_strncpy_align_done:
movq $0x0101010101010101, %r8
movq $0x8080808080808080, %r9
.safe_user_strncpy_qword_loop:
cmpq $8, %rcx
jb .safe_user_strncpy_qword_done
movq (%rsi), %rax
movq %rax, %r10
movq %rax, %r11
# https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord
subq %r8, %r10
notq %r11
andq %r11, %r10
andq %r9, %r10
jnz .safe_user_strncpy_byte_loop
movq %rax, (%rdi)
addq $8, %rdi
addq $8, %rsi
subq $8, %rcx
jnz .safe_user_strncpy_qword_loop
jmp safe_user_strncpy_fault
.safe_user_strncpy_qword_done:
testq %rcx, %rcx
jz safe_user_strncpy_fault
.safe_user_strncpy_byte_loop:
movb (%rsi), %al
movb %al, (%rdi)
testb %al, %al
jz .safe_user_strncpy_done
incq %rdi
incq %rsi
decq %rcx
jnz .safe_user_strncpy_byte_loop
safe_user_strncpy_fault:
xorq %rax, %rax
ret
.safe_user_strncpy_done:
movb $1, %al
ret
safe_user_strncpy_end:

View File

@@ -0,0 +1,29 @@
.global asm_yield_trampoline
asm_yield_trampoline:
leaq 8(%rsp), %rcx
movq %rdi, %rsp
subq $8, %rsp
pushq -8(%rcx)
pushq %rcx
pushq %rax
pushq %rbx
pushq %rbp
pushq %r12
pushq %r13
pushq %r14
pushq %r15
movq %rsp, %rdi
call scheduler_on_yield
popq %r15
popq %r14
popq %r13
popq %r12
popq %rbp
popq %rbx
popq %rax
movq 8(%rsp), %rcx
movq 0(%rsp), %rsp
jmp *%rcx

View File

@@ -14,6 +14,23 @@
# multiboot2 header
.section .multiboot, "aw"
.align 8
multiboot_start:
.long 0x1BADB002
.long (1 << 2) # page align modules
.long -(0x1BADB002 + (1 << 2))
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long FB_WIDTH
.long FB_HEIGHT
.long FB_BPP
multiboot_end:
.align 8
multiboot2_start:
.long 0xE85250D6
.long 0
@@ -36,6 +53,12 @@ multiboot2_start:
.long 12
.long V2P(_start)
# page align modules
.align 8
.short 6
.short 0
.long 8
.align 8
.short 0
.short 0
@@ -53,9 +76,10 @@ bananboot_start:
bananboot_end:
.section .bss, "aw", @nobits
boot_stack_bottom:
.skip 4096 * 64
boot_stack_top:
.global g_boot_stack_top
g_boot_stack_bottom:
.skip 4096 * 4
g_boot_stack_top:
.global g_kernel_cmdline
g_kernel_cmdline:
@@ -108,9 +132,6 @@ g_ap_startup_done:
.global g_ap_running_count
g_ap_running_count:
.byte 0
.global g_ap_stack_loaded
g_ap_stack_loaded:
.byte 0
.section .text
@@ -158,6 +179,13 @@ enable_sse:
movl %eax, %cr4
ret
enable_tsc:
# allow userspace to use RDTSC
movl %cr4, %ecx
andl $0xFFFFFFFB, %ecx
movl %ecx, %cr4
ret
initialize_paging:
# enable PAE
movl %cr4, %ecx
@@ -190,11 +218,11 @@ _start:
movl %eax, V2P(bootloader_magic)
movl %ebx, V2P(bootloader_info)
movl $V2P(boot_stack_top), %esp
movl $V2P(g_boot_stack_top), %esp
call check_requirements
call enable_sse
call enable_tsc
call initialize_paging
# flush gdt and jump to 64 bit
@@ -220,6 +248,13 @@ higher_half:
# call global constuctors
call _init
movq $g_init_array_start, %rbx
jmp 2f
1: call *(%rbx)
addq $8, %rbx
2: cmpq $g_init_array_end, %rbx
jne 1b
# call to the kernel itself (clear rbp for stacktrace)
xorq %rbp, %rbp
@@ -237,26 +272,31 @@ system_halt:
jmp 1b
#define AP_V2P(vaddr) ((vaddr) - ap_trampoline + 0xF000)
.section .ap_init, "ax"
.code16
.global ap_trampoline
ap_trampoline:
jmp 1f
.align 8
ap_stack_ptr:
.skip 4
1:
cli; cld
ljmpl $0x00, $ap_cs_clear
ap_cs_clear:
ap_stack_loaded:
.skip 1
1: cli; cld
ljmpl $0x00, $AP_V2P(ap_cs_clear)
ap_cs_clear:
# load ap gdt and enter protected mode
lgdt ap_gdtr
lgdt AP_V2P(ap_gdtr)
movl %cr0, %eax
orb $1, %al
movl %eax, %cr0
ljmpl $0x08, $ap_protected_mode
ljmpl $0x08, $AP_V2P(ap_protected_mode)
.code32
ap_protected_mode:
@@ -265,16 +305,16 @@ ap_protected_mode:
movw %ax, %ss
movw %ax, %es
movl ap_stack_ptr, %esp
movb $1, V2P(g_ap_stack_loaded)
movl AP_V2P(ap_stack_ptr), %esp
movb $1, AP_V2P(ap_stack_loaded)
call V2P(enable_sse)
call V2P(initialize_paging)
leal V2P(enable_sse), %ecx; call *%ecx
leal V2P(enable_tsc), %ecx; call *%ecx
leal V2P(initialize_paging), %ecx; call *%ecx
# load boot gdt and enter long mode
lgdt V2P(boot_gdtr)
ljmpl $0x08, $ap_long_mode
ljmpl $0x08, $AP_V2P(ap_long_mode)
.code64
ap_long_mode:
@@ -282,22 +322,20 @@ ap_long_mode:
movl %esp, %esp
addq $KERNEL_OFFSET, %rsp
# jump to higher half
movabsq $ap_higher_half, %rcx
jmp *%rcx
ap_higher_half:
# clear rbp for stacktrace
xorq %rbp, %rbp
xorb %al, %al
1: pause
cmpb $0, g_ap_startup_done
cmpb %al, g_ap_startup_done
jz 1b
lock incb g_ap_running_count
call ap_main
jmp system_halt
# jump to ap_main in higher half
movabsq $ap_main, %rcx
call *%rcx
jmp V2P(system_halt)
ap_gdt:
.quad 0x0000000000000000 # null descriptor

View File

@@ -1,4 +1,12 @@
.macro pushaq
.macro swapgs_if_necessary, n
testb $3, \n(%rsp)
jz 1f; jnp 1f
swapgs
1:
.endm
.macro pushaq, n
swapgs_if_necessary \n
pushq %rax
pushq %rcx
pushq %rdx
@@ -16,7 +24,7 @@
pushq %r15
.endm
.macro popaq
.macro popaq, n
popq %r15
popq %r14
popq %r13
@@ -32,11 +40,12 @@
popq %rdx
popq %rcx
popq %rax
swapgs_if_necessary \n
.endm
isr_stub:
pushaq
pushaq 24
cld
movq %cr0, %rax; pushq %rax
movq %cr2, %rax; pushq %rax
movq %cr3, %rax; pushq %rax
@@ -49,25 +58,33 @@ isr_stub:
call cpp_isr_handler
addq $32, %rsp
popaq
popaq 24
addq $16, %rsp
iretq
irq_stub:
pushaq
pushaq 24
cld
movq 120(%rsp), %rdi # irq number
call cpp_irq_handler
popaq
popaq 24
addq $16, %rsp
iretq
.global asm_yield_handler
asm_yield_handler:
pushaq
leaq 120(%rsp), %rdi # interrupt stack ptr
movq %rsp, %rsi # interrupt register ptr
call cpp_yield_handler
popaq
.global asm_ipi_handler
asm_ipi_handler:
pushaq 8
cld
call cpp_ipi_handler
popaq 8
iretq
.global asm_timer_handler
asm_timer_handler:
pushaq 8
cld
call cpp_timer_handler
popaq 8
iretq
.macro isr n
@@ -126,36 +143,26 @@ isr 29
isr 30
isr 31
irq 0
irq 1
irq 2
irq 3
irq 4
irq 5
irq 6
irq 7
irq 8
irq 9
irq 10
irq 11
irq 12
irq 13
irq 14
irq 15
irq 16
irq 17
irq 18
irq 19
irq 20
irq 21
irq 22
irq 23
irq 24
irq 25
irq 26
irq 27
irq 28
irq 29
irq 30
irq 31
irq 32
.irp i, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, \
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, \
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, \
30, 31, 32, 33, 34, 35, 36, 37, 38, 39, \
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, \
50, 51, 52, 53, 54, 55, 56, 57, 58, 59, \
60, 61, 62, 63, 64, 65, 66, 67, 68, 69, \
70, 71, 72, 73, 74, 75, 76, 77, 78, 79, \
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, \
90, 91, 92, 93, 94, 95, 96, 97, 98, 99, \
100,101,102,103,104,105,106,107,108,109, \
110,111,112,113,114,115,116,117,118,119, \
120,121,122,123,124,125,126,127,128,129, \
130,131,132,133,134,135,136,137,138,139, \
140,141,142,143,144,145,146,147,148,149, \
150,151,152,153,154,155,156,157,158,159, \
160,161,162,163,164,165,166,167,168,169, \
170,171,172,173,174,175,176,177,178,179, \
180,181,182,183,184,185,186,187,188,189, \
190,191,192,193,194,195,196,197,198,199, \
200,201,202,203,204,205,206,207
irq \i
.endr

View File

@@ -4,13 +4,6 @@ KERNEL_OFFSET = 0xFFFFFFFF80000000;
SECTIONS
{
. = 0xF000;
.ap_init ALIGN(4K) : AT(ADDR(.ap_init))
{
g_ap_init_addr = .;
*(.ap_init)
}
. = 0x00100000 + KERNEL_OFFSET;
g_kernel_start = .;
@@ -28,18 +21,31 @@ SECTIONS
g_userspace_end = .;
g_kernel_execute_end = .;
}
.ap_init ALIGN(4K) : AT(ADDR(.ap_init) - KERNEL_OFFSET)
{
g_ap_init_addr = .;
*(.ap_init)
}
.rodata ALIGN(4K) : AT(ADDR(.rodata) - KERNEL_OFFSET)
{
*(.rodata.*)
}
.init_array ALIGN(4K) : AT(ADDR(.init_array) - KERNEL_OFFSET)
{
g_init_array_start = .;
*(.init_array)
g_init_array_end = .;
}
.data ALIGN(4K) : AT(ADDR(.data) - KERNEL_OFFSET)
{
g_kernel_writable_start = .;
*(.data)
}
.bss ALIGN(4K) : AT(ADDR(.bss) - KERNEL_OFFSET)
{
*(COMMON)
*(.bss)
g_kernel_writable_end = .;
}
g_kernel_end = .;
}

View File

@@ -42,20 +42,20 @@ namespace __cxxabiv1
{
using __guard = uint64_t;
int __cxa_guard_acquire (__guard* g)
extern "C" int __cxa_guard_acquire (__guard* g)
{
uint8_t* byte = reinterpret_cast<uint8_t*>(g);
uint8_t zero = 0;
return __atomic_compare_exchange_n(byte, &zero, 1, false, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);
}
void __cxa_guard_release (__guard* g)
extern "C" void __cxa_guard_release (__guard* g)
{
uint8_t* byte = reinterpret_cast<uint8_t*>(g);
__atomic_store_n(byte, 0, __ATOMIC_RELEASE);
}
void __cxa_guard_abort (__guard*)
extern "C" void __cxa_guard_abort (__guard*)
{
Kernel::panic("__cxa_guard_abort");
}

View File

@@ -1,10 +1,11 @@
#pragma once
#include <BAN/Vector.h>
#include <kernel/ACPI/AML/Method.h>
#include <kernel/ACPI/AML/Namespace.h>
#include <kernel/ACPI/EmbeddedController.h>
#include <kernel/ACPI/Headers.h>
#include <kernel/Memory/Types.h>
#include <kernel/ThreadBlocker.h>
namespace Kernel::ACPI
{
@@ -28,25 +29,38 @@ namespace Kernel::ACPI
// 2: SAPIC
BAN::ErrorOr<void> enter_acpi_mode(uint8_t mode);
// This function will power off the system
// This function will return only if there was an error
void poweroff();
BAN::ErrorOr<void> initialize_acpi_devices();
// This function will reset the system
// This function will return only if there was an error
void reset();
AML::Namespace* acpi_namespace() { return m_namespace; }
BAN::ErrorOr<void> poweroff();
BAN::ErrorOr<void> reset();
BAN::ErrorOr<void> register_gpe_handler(uint8_t gpe, void (*callback)(void*), void* argument);
void handle_irq() override;
BAN::Span<BAN::UniqPtr<EmbeddedController>> embedded_controllers() { return m_embedded_controllers.span(); }
private:
ACPI() = default;
BAN::ErrorOr<void> initialize_impl();
FADT& fadt() { return *m_fadt; }
bool prepare_sleep(uint8_t sleep_state);
BAN::ErrorOr<void> prepare_sleep(uint8_t sleep_state);
void acpi_event_task();
BAN::ErrorOr<void> load_aml_tables(BAN::StringView name, bool all);
BAN::ErrorOr<void> route_interrupt_link_device(const AML::Scope& device, uint64_t& routed_irq_mask);
BAN::ErrorOr<void> initialize_embedded_controller(const AML::Scope& embedded_controller);
BAN::ErrorOr<void> initialize_embedded_controllers();
BAN::Optional<GAS> find_gpe_block(size_t index);
bool enable_gpe(uint8_t gpe);
private:
paddr_t m_header_table_paddr = 0;
vaddr_t m_header_table_vaddr = 0;
@@ -63,11 +77,28 @@ namespace Kernel::ACPI
FADT* m_fadt { nullptr };
Semaphore m_event_semaphore;
BAN::Array<BAN::RefPtr<AML::Method>, 0xFF> m_gpe_methods;
ThreadBlocker m_event_thread_blocker;
BAN::Vector<BAN::UniqPtr<EmbeddedController>> m_embedded_controllers;
struct GPEHandler
{
bool has_callback { false };
union {
AML::Reference* method;
struct
{
void (*callback)(void*);
void* argument;
};
};
};
bool m_has_any_gpes { false };
AML::Scope m_gpe_scope;
BAN::Array<GPEHandler, 0xFF> m_gpe_methods;
bool m_hardware_reduced { false };
BAN::RefPtr<AML::Namespace> m_namespace;
AML::Namespace* m_namespace { nullptr };
};
}

View File

@@ -1,11 +0,0 @@
#pragma once
#include <kernel/ACPI/Headers.h>
#include <kernel/ACPI/AML/Namespace.h>
namespace Kernel::ACPI::AML
{
BAN::RefPtr<AML::Namespace> initialize_namespace();
}

View File

@@ -1,212 +0,0 @@
#pragma once
#include <kernel/ACPI/AML/Bytes.h>
#include <kernel/ACPI/AML/Integer.h>
#include <kernel/ACPI/AML/Node.h>
#include <kernel/ACPI/AML/ParseContext.h>
#include <kernel/ACPI/AML/Pkg.h>
namespace Kernel::ACPI::AML
{
struct Buffer : public AML::Node
{
BAN::Vector<uint8_t> buffer;
Buffer()
: AML::Node(Node::Type::Buffer)
{}
BAN::RefPtr<AML::Node> evaluate() override
{
return this;
}
static ParseResult parse(AML::ParseContext& context)
{
ASSERT(context.aml_data.size() >= 1);
ASSERT(static_cast<Byte>(context.aml_data[0]) == Byte::BufferOp);
context.aml_data = context.aml_data.slice(1);
auto buffer_pkg = AML::parse_pkg(context.aml_data);
if (!buffer_pkg.has_value())
return ParseResult::Failure;
auto buffer_context = context;
buffer_context.aml_data = buffer_pkg.value();
auto buffer_size_object = AML::parse_object(buffer_context);
if (!buffer_size_object.success())
return ParseResult::Failure;
auto buffer_size = buffer_size_object.node()->as_integer();
if (!buffer_size.has_value())
return ParseResult::Failure;
uint32_t actual_buffer_size = BAN::Math::max<uint32_t>(buffer_size.value(), buffer_context.aml_data.size());
auto buffer = MUST(BAN::RefPtr<Buffer>::create());
MUST(buffer->buffer.resize(actual_buffer_size, 0));
for (uint32_t i = 0; i < buffer_context.aml_data.size(); i++)
buffer->buffer[i] = buffer_context.aml_data[i];
#if AML_DEBUG_LEVEL >= 2
buffer->debug_print(0);
AML_DEBUG_PRINTLN("");
#endif
return ParseResult(buffer);
}
virtual void debug_print(int indent) const override
{
AML_DEBUG_PRINT_INDENT(indent);
AML_DEBUG_PRINT("Buffer ({} bytes)", buffer.size());
}
};
struct BufferField : AML::NamedObject
{
BAN::RefPtr<Buffer> buffer;
size_t field_bit_offset;
size_t field_bit_size;
BufferField(AML::NameSeg name, BAN::RefPtr<Buffer> buffer, size_t field_bit_offset, size_t field_bit_size)
: AML::NamedObject(Node::Type::BufferField, name)
, buffer(buffer)
, field_bit_offset(field_bit_offset)
, field_bit_size(field_bit_size)
{}
BAN::RefPtr<AML::Node> evaluate() override
{
ASSERT(buffer);
ASSERT(field_bit_offset + field_bit_size <= buffer->buffer.size() * 8);
uint64_t value = 0;
const size_t byte_offset = field_bit_offset / 8;
const size_t bit_offset = field_bit_offset % 8;
if (field_bit_size == 1)
{
value = (buffer->buffer[byte_offset] >> bit_offset) & 1;
}
else
{
ASSERT(bit_offset == 0);
for (size_t byte = 0; byte < field_bit_size / 8; byte++)
value |= buffer->buffer[byte_offset + byte] << byte;
}
return MUST(BAN::RefPtr<AML::Integer>::create(value));
}
bool store(BAN::RefPtr<AML::Node> node) override
{
ASSERT(buffer);
ASSERT(field_bit_offset + field_bit_size <= buffer->buffer.size() * 8);
auto value = node->as_integer();
if (!value.has_value())
return false;
const size_t byte_offset = field_bit_offset / 8;
const size_t bit_offset = field_bit_offset % 8;
if (field_bit_size == 1)
{
buffer->buffer[byte_offset] &= ~(1 << bit_offset);
buffer->buffer[byte_offset] |= (value.value() & 1) << bit_offset;
}
else
{
ASSERT(bit_offset == 0);
for (size_t byte = 0; byte < field_bit_size / 8; byte++)
buffer->buffer[byte_offset + byte] = (value.value() >> (byte * 8)) & 0xFF;
}
return true;
}
static ParseResult parse(AML::ParseContext& context)
{
ASSERT(context.aml_data.size() >= 1);
size_t field_bit_size = 0;
switch (static_cast<Byte>(context.aml_data[0]))
{
case AML::Byte::CreateBitFieldOp:
field_bit_size = 1;
break;
case AML::Byte::CreateByteFieldOp:
field_bit_size = 8;
break;
case AML::Byte::CreateWordFieldOp:
field_bit_size = 16;
break;
case AML::Byte::CreateDWordFieldOp:
field_bit_size = 32;
break;
case AML::Byte::CreateQWordFieldOp:
field_bit_size = 64;
break;
default:
ASSERT_NOT_REACHED();
}
context.aml_data = context.aml_data.slice(1);
auto buffer_result = AML::parse_object(context);
if (!buffer_result.success())
return ParseResult::Failure;
auto buffer_node = buffer_result.node() ? buffer_result.node()->evaluate() : nullptr;
if (!buffer_node || buffer_node->type != Node::Type::Buffer)
{
AML_ERROR("Buffer source does not evaluate to a Buffer");
return ParseResult::Failure;
}
auto buffer = static_cast<Buffer*>(buffer_node.ptr());
auto index_result = AML::parse_object(context);
if (!index_result.success())
return ParseResult::Failure;
auto index = index_result.node() ? index_result.node()->as_integer() : BAN::Optional<uint64_t>();
if (!index.has_value())
{
AML_ERROR("Failed to parse index for BufferField");
return ParseResult::Failure;
}
size_t field_bit_offset = index.value();
if (field_bit_size != 1)
field_bit_offset *= 8;
auto field_name = AML::NameString::parse(context.aml_data);
if (!field_name.has_value())
return ParseResult::Failure;
if (field_name->path.empty())
{
AML_ERROR("Empty field name for BufferField");
return ParseResult::Failure;
}
auto field = MUST(BAN::RefPtr<BufferField>::create(field_name->path.back(), buffer, field_bit_offset, field_bit_size));
if (!Namespace::root_namespace()->add_named_object(context, field_name.value(), field))
return ParseResult::Failure;
#if AML_DEBUG_LEVEL >= 2
field->debug_print(0);
AML_DEBUG_PRINTLN("");
#endif
return ParseResult::Success;
}
virtual void debug_print(int indent) const override
{
AML_DEBUG_PRINT_INDENT(indent);
AML_DEBUG_PRINT("BufferField {} at bit offset {} ({} bits) to { ", name, field_bit_offset, field_bit_size);
buffer->debug_print(0);
AML_DEBUG_PRINT(" }");
}
};
}

View File

@@ -145,19 +145,35 @@ namespace Kernel::ACPI::AML
DataRegionOp = 0x88,
};
static constexpr bool is_digit_char(uint8_t ch)
inline constexpr bool is_digit_char(uint8_t ch)
{
return '0' <= ch && ch <= '9';
}
static constexpr bool is_lead_name_char(uint8_t ch)
inline constexpr bool is_lead_name_char(uint8_t ch)
{
return ('A' <= ch && ch <= 'Z') || ch == '_';
}
static constexpr bool is_name_char(uint8_t ch)
inline constexpr bool is_name_char(uint8_t ch)
{
return is_lead_name_char(ch) || is_digit_char(ch);
}
inline constexpr bool is_name_string_start(uint8_t ch)
{
if (is_lead_name_char(ch))
return true;
switch (static_cast<AML::Byte>(ch))
{
case AML::Byte::RootChar:
case AML::Byte::ParentPrefixChar:
case AML::Byte::MultiNamePrefix:
case AML::Byte::DualNamePrefix:
return true;
default:
return false;
}
}
}

View File

@@ -1,57 +0,0 @@
#pragma once
#include <kernel/ACPI/AML/Method.h>
#include <kernel/ACPI/AML/ParseContext.h>
#include <kernel/ACPI/AML/Pkg.h>
#include <kernel/ACPI/AML/Scope.h>
namespace Kernel::ACPI::AML
{
struct Device : public AML::Scope
{
Device(NameSeg name)
: Scope(Node::Type::Device, name)
{}
static ParseResult parse(ParseContext& context)
{
ASSERT(context.aml_data.size() >= 2);
ASSERT(static_cast<AML::Byte>(context.aml_data[0]) == AML::Byte::ExtOpPrefix);
ASSERT(static_cast<AML::ExtOp>(context.aml_data[1]) == AML::ExtOp::DeviceOp);
context.aml_data = context.aml_data.slice(2);
auto device_pkg = AML::parse_pkg(context.aml_data);
if (!device_pkg.has_value())
return ParseResult::Failure;
auto name_string = AML::NameString::parse(device_pkg.value());
if (!name_string.has_value())
return ParseResult::Failure;
auto device = MUST(BAN::RefPtr<Device>::create(name_string->path.back()));
if (!Namespace::root_namespace()->add_named_object(context, name_string.value(), device))
return ParseResult::Failure;
return device->enter_context_and_parse_term_list(context, name_string.value(), device_pkg.value());
}
virtual void debug_print(int indent) const override
{
AML_DEBUG_PRINT_INDENT(indent);
AML_DEBUG_PRINT("Device ");
name.debug_print();
AML_DEBUG_PRINTLN(" {");
Namespace::root_namespace()->for_each_child(scope,
[&](const auto&, const auto& child)
{
child->debug_print(indent + 1);
AML_DEBUG_PRINTLN("");
}
);
AML_DEBUG_PRINT_INDENT(indent);
AML_DEBUG_PRINT("}");
}
};
}

View File

@@ -1,216 +0,0 @@
#pragma once
#include <kernel/ACPI/AML/Bytes.h>
#include <kernel/ACPI/AML/Integer.h>
#include <kernel/ACPI/AML/Node.h>
#include <kernel/ACPI/AML/ParseContext.h>
namespace Kernel::ACPI::AML
{
struct Expression
{
static ParseResult parse(ParseContext& context)
{
ASSERT(context.aml_data.size() >= 1);
switch (static_cast<Byte>(context.aml_data[0]))
{
// unary
case AML::Byte::IncrementOp:
case AML::Byte::DecrementOp:
{
auto opcode = (static_cast<AML::Byte>(context.aml_data[0]) == AML::Byte::IncrementOp) ? AML::Byte::AddOp : AML::Byte::SubtractOp;
context.aml_data = context.aml_data.slice(1);
auto source_result = AML::parse_object(context);
if (!source_result.success())
return ParseResult::Failure;
auto source_node = source_result.node() ? source_result.node()->evaluate() : BAN::RefPtr<AML::Node>();
if (!source_node || source_node->type != AML::Node::Type::Integer)
{
AML_ERROR("UnaryOp source not integer");
return ParseResult::Failure;
}
auto source_integer = static_cast<AML::Integer*>(source_node.ptr());
if (source_integer->constant)
{
AML_ERROR("UnaryOp source is constant");
return ParseResult::Failure;
}
source_integer->value += (opcode == AML::Byte::AddOp) ? 1 : -1;
return ParseResult(source_integer);
}
case AML::Byte::NotOp:
AML_TODO("NotOp", context.aml_data[0]);
return ParseResult::Failure;
case AML::Byte::LNotOp:
{
context.aml_data = context.aml_data.slice(1);
auto node_result = AML::parse_object(context);
if (!node_result.success())
return ParseResult::Failure;
auto value = node_result.node() ? node_result.node()->as_integer() : BAN::Optional<uint64_t>();
if (!value.has_value())
{
AML_ERROR("Logical NotOp source is not integer");
return ParseResult::Failure;
}
auto result = value.value() ? Integer::Constants::Zero : Integer::Constants::Ones;
return ParseResult(result);
}
case AML::Byte::AddOp:
case AML::Byte::AndOp:
case AML::Byte::ModOp:
case AML::Byte::MultiplyOp:
case AML::Byte::NandOp:
case AML::Byte::NorOp:
case AML::Byte::OrOp:
case AML::Byte::ShiftLeftOp:
case AML::Byte::ShiftRightOp:
case AML::Byte::SubtractOp:
case AML::Byte::XorOp:
return parse_binary_op(context);
case AML::Byte::LAndOp:
case AML::Byte::LEqualOp:
case AML::Byte::LGreaterOp:
case AML::Byte::LLessOp:
case AML::Byte::LOrOp:
return parse_logical_binary_op(context);
case AML::Byte::DivideOp:
AML_TODO("DivideOp");
return ParseResult::Failure;
default:
ASSERT_NOT_REACHED();
}
}
private:
static ParseResult parse_binary_op(ParseContext& context)
{
auto opcode = static_cast<AML::Byte>(context.aml_data[0]);
context.aml_data = context.aml_data.slice(1);
auto lhs_result = AML::parse_object(context);
if (!lhs_result.success())
return ParseResult::Failure;
auto lhs_value = lhs_result.node() ? lhs_result.node()->as_integer() : BAN::Optional<uint64_t>();
if (!lhs_value.has_value())
{
AML_ERROR("BinaryOP {2H} LHS not an integer", static_cast<uint8_t>(opcode));
if (lhs_result.node())
lhs_result.node()->debug_print(1);
AML_DEBUG_PRINTLN("");
return ParseResult::Failure;
}
auto rhs_result = AML::parse_object(context);
if (!rhs_result.success())
return ParseResult::Failure;
auto rhs_value = lhs_result.node() ? rhs_result.node()->as_integer() : BAN::Optional<uint64_t>();
if (!rhs_value.has_value())
{
AML_ERROR("BinaryOP {2H} RHS not an integer", static_cast<uint8_t>(opcode));
if (rhs_result.node())
rhs_result.node()->debug_print(1);
AML_DEBUG_PRINTLN("");
return ParseResult::Failure;
}
if (context.aml_data.size() < 1)
{
AML_ERROR("BinaryOP {2H} missing target", static_cast<uint8_t>(opcode));
return ParseResult::Failure;
}
BAN::RefPtr<AML::Node> target_node;
if (context.aml_data[0] == 0x00)
context.aml_data = context.aml_data.slice(1);
else
{
auto target_result = AML::parse_object(context);
if (!target_result.success())
return ParseResult::Failure;
target_node = target_result.node();
if (!target_node)
{
AML_ERROR("BinaryOP {2H} target invalid", static_cast<uint8_t>(opcode));
return ParseResult::Failure;
}
}
uint64_t (*func)(uint64_t, uint64_t) = nullptr;
switch (opcode)
{
case AML::Byte::AddOp: func = [](uint64_t a, uint64_t b) { return a + b; }; break;
case AML::Byte::AndOp: func = [](uint64_t a, uint64_t b) { return a & b; }; break;
case AML::Byte::ModOp: func = [](uint64_t a, uint64_t b) { return a % b; }; break;
case AML::Byte::MultiplyOp: func = [](uint64_t a, uint64_t b) { return a * b; }; break;
case AML::Byte::NandOp: func = [](uint64_t a, uint64_t b) { return ~(a & b); }; break;
case AML::Byte::NorOp: func = [](uint64_t a, uint64_t b) { return ~(a | b); }; break;
case AML::Byte::OrOp: func = [](uint64_t a, uint64_t b) { return a | b; }; break;
case AML::Byte::ShiftLeftOp: func = [](uint64_t a, uint64_t b) { return a << b; }; break;
case AML::Byte::ShiftRightOp: func = [](uint64_t a, uint64_t b) { return a >> b; }; break;
case AML::Byte::SubtractOp: func = [](uint64_t a, uint64_t b) { return a - b; }; break;
case AML::Byte::XorOp: func = [](uint64_t a, uint64_t b) { return a ^ b; }; break;
default:
ASSERT_NOT_REACHED();
}
uint64_t result = func(lhs_value.value(), rhs_value.value());
auto result_node = MUST(BAN::RefPtr<AML::Integer>::create(result));
if (target_node && !target_node->store(result_node))
{
AML_ERROR("BinaryOp {2H} failed to store result", static_cast<uint8_t>(opcode));
return ParseResult::Failure;
}
return ParseResult(result_node);
}
static ParseResult parse_logical_binary_op(ParseContext& context)
{
auto opcode = static_cast<AML::Byte>(context.aml_data[0]);
context.aml_data = context.aml_data.slice(1);
auto lhs_result = AML::parse_object(context);
if (!lhs_result.success())
return ParseResult::Failure;
auto lhs_value = lhs_result.node() ? lhs_result.node()->as_integer() : BAN::Optional<uint64_t>();
if (!lhs_value.has_value())
{
AML_TODO("Logical BinaryOP {2H} LHS not integer", static_cast<uint8_t>(opcode));
return ParseResult::Failure;
}
auto rhs_result = AML::parse_object(context);
if (!rhs_result.success())
return ParseResult::Failure;
auto rhs_value = rhs_result.node() ? rhs_result.node()->as_integer() : BAN::Optional<uint64_t>();
if (!rhs_value.has_value())
{
AML_TODO("Logical BinaryOP {2H} RHS not integer", static_cast<uint8_t>(opcode));
return ParseResult::Failure;
}
BAN::RefPtr<AML::Integer> (*func)(uint64_t, uint64_t) = nullptr;
switch (opcode)
{
case AML::Byte::LAndOp: func = [](uint64_t a, uint64_t b) { return a && b ? Integer::Constants::Ones : Integer::Constants::Zero; }; break;
case AML::Byte::LEqualOp: func = [](uint64_t a, uint64_t b) { return a == b ? Integer::Constants::Ones : Integer::Constants::Zero; }; break;
case AML::Byte::LGreaterOp: func = [](uint64_t a, uint64_t b) { return a > b ? Integer::Constants::Ones : Integer::Constants::Zero; }; break;
case AML::Byte::LLessOp: func = [](uint64_t a, uint64_t b) { return a < b ? Integer::Constants::Ones : Integer::Constants::Zero; }; break;
case AML::Byte::LOrOp: func = [](uint64_t a, uint64_t b) { return a || b ? Integer::Constants::Ones : Integer::Constants::Zero; }; break;
default:
ASSERT_NOT_REACHED();
}
return ParseResult(func(lhs_value.value(), rhs_value.value()));
}
};
}

View File

@@ -1,141 +0,0 @@
#pragma once
#include <kernel/ACPI/AML/NamedObject.h>
#include <kernel/ACPI/AML/ParseContext.h>
#include <kernel/ACPI/AML/Pkg.h>
#include <kernel/ACPI/AML/Region.h>
namespace Kernel::ACPI::AML
{
struct FieldRules
{
enum class AccessType
{
Any = 0,
Byte = 1,
Word = 2,
DWord = 3,
QWord = 4,
Buffer = 5,
};
AccessType access_type;
enum class LockRule
{
NoLock = 0,
Lock = 1,
};
LockRule lock_rule;
enum class UpdateRule
{
Preserve = 0,
WriteAsOnes = 1,
WriteAsZeros = 2,
};
UpdateRule update_rule;
enum class AccessAttrib
{
Normal = 0,
Bytes = 1,
RawBytes = 2,
RawProcessBytes = 3,
};
AccessAttrib access_attrib = AccessAttrib::Normal;
uint8_t access_length = 0;
};
struct FieldElement : public NamedObject
{
uint64_t bit_offset;
uint64_t bit_count;
FieldRules access_rules;
BAN::RefPtr<OpRegion> op_region;
FieldElement(NameSeg name, uint64_t bit_offset, uint64_t bit_count, FieldRules access_rules)
: NamedObject(Node::Type::FieldElement, name)
, bit_offset(bit_offset)
, bit_count(bit_count)
, access_rules(access_rules)
{}
BAN::RefPtr<Node> evaluate() override;
bool store(BAN::RefPtr<Node> source) override;
void debug_print(int indent) const override;
private:
BAN::Optional<uint64_t> evaluate_internal();
bool store_internal(uint64_t value);
friend struct IndexFieldElement;
friend struct BankFieldElement;
};
struct Field
{
static ParseResult parse(ParseContext& context);
};
struct IndexFieldElement : public NamedObject
{
uint64_t bit_offset;
uint64_t bit_count;
FieldRules access_rules;
BAN::RefPtr<FieldElement> index_element;
BAN::RefPtr<FieldElement> data_element;
IndexFieldElement(NameSeg name, uint64_t bit_offset, uint64_t bit_count, FieldRules access_rules)
: NamedObject(Node::Type::IndexFieldElement, name)
, bit_offset(bit_offset)
, bit_count(bit_count)
, access_rules(access_rules)
{}
BAN::RefPtr<Node> evaluate() override;
bool store(BAN::RefPtr<Node> source) override;
void debug_print(int indent) const override;
};
struct IndexField
{
static ParseResult parse(ParseContext& context);
};
struct BankFieldElement : public NamedObject
{
uint64_t bit_offset;
uint64_t bit_count;
FieldRules access_rules;
BAN::RefPtr<OpRegion> op_region;
BAN::RefPtr<FieldElement> bank_selector;
uint64_t bank_value;
BankFieldElement(NameSeg name, uint64_t bit_offset, uint64_t bit_count, FieldRules access_rules)
: NamedObject(Node::Type::BankFieldElement, name)
, bit_offset(bit_offset)
, bit_count(bit_count)
, access_rules(access_rules)
{}
BAN::RefPtr<Node> evaluate() override;
bool store(BAN::RefPtr<Node> source) override;
void debug_print(int indent) const override;
};
struct BankField
{
static ParseResult parse(ParseContext& context);
};
}

View File

@@ -1,64 +0,0 @@
#pragma once
#include <BAN/HashMap.h>
#include <kernel/ACPI/AML/Node.h>
#include <kernel/ACPI/AML/ParseContext.h>
#include <kernel/ACPI/AML/Pkg.h>
namespace Kernel::ACPI::AML
{
struct IfElse
{
static ParseResult parse(ParseContext& context)
{
ASSERT(context.aml_data.size() >= 1);
ASSERT(static_cast<Byte>(context.aml_data[0]) == Byte::IfOp);
context.aml_data = context.aml_data.slice(1);
auto if_pkg = AML::parse_pkg(context.aml_data);
if (!if_pkg.has_value())
return ParseResult::Failure;
auto outer_aml_data = context.aml_data;
context.aml_data = if_pkg.value();
auto predicate_result = AML::parse_object(context);
if (!predicate_result.success())
return ParseResult::Failure;
auto predicate = predicate_result.node() ? predicate_result.node()->as_integer() : BAN::Optional<uint64_t>();
if (!predicate.has_value())
{
AML_ERROR("If predicate is not an integer");
return ParseResult::Failure;
}
// Else
BAN::ConstByteSpan else_pkg;
if (outer_aml_data.size() >= 1 && static_cast<AML::Byte>(outer_aml_data[0]) == Byte::ElseOp)
{
outer_aml_data = outer_aml_data.slice(1);
auto else_pkg_result = AML::parse_pkg(outer_aml_data);
if (!else_pkg_result.has_value())
return ParseResult::Failure;
else_pkg = else_pkg_result.value();
}
if (!predicate.value())
context.aml_data = else_pkg;
while (context.aml_data.size() > 0)
{
auto object_result = AML::parse_object(context);
if (object_result.returned())
return ParseResult(ParseResult::Result::Returned, object_result.node());
if (!object_result.success())
return ParseResult::Failure;
}
context.aml_data = outer_aml_data;
return ParseResult::Success;
}
};
}

View File

@@ -1,106 +0,0 @@
#pragma once
#include <kernel/ACPI/AML/Buffer.h>
#include <kernel/ACPI/AML/Node.h>
#include <kernel/ACPI/AML/Package.h>
#include <kernel/ACPI/AML/ParseContext.h>
#include <kernel/ACPI/AML/Reference.h>
namespace Kernel::ACPI::AML
{
struct Index
{
static ParseResult parse(ParseContext& context)
{
ASSERT(context.aml_data.size() >= 1);
ASSERT(static_cast<Byte>(context.aml_data[0]) == Byte::IndexOp);
context.aml_data = context.aml_data.slice(1);
auto source_result = AML::parse_object(context);
if (!source_result.success())
return ParseResult::Failure;
auto source = source_result.node() ? source_result.node()->evaluate() : BAN::RefPtr<AML::Node>();
if (!source)
{
AML_ERROR("IndexOp source is null");
return ParseResult::Failure;
}
auto index_result = AML::parse_object(context);
if (!index_result.success())
return ParseResult::Failure;
auto index = index_result.node() ? index_result.node()->as_integer() : BAN::Optional<uint64_t>();
if (!index.has_value())
{
AML_ERROR("IndexOp index is not an integer");
return ParseResult::Failure;
}
BAN::RefPtr<AML::Reference> result;
switch (source->type)
{
case AML::Node::Type::Buffer:
{
auto buffer = static_cast<AML::Buffer*>(source.ptr());
if (index.value() >= buffer->buffer.size())
{
AML_ERROR("IndexOp index is out of buffer bounds");
return ParseResult::Failure;
}
auto buffer_field = MUST(BAN::RefPtr<BufferField>::create(NameSeg(""sv), buffer, index.value() * 8, 8));
result = MUST(BAN::RefPtr<AML::Reference>::create(buffer_field));
break;
}
case AML::Node::Type::Package:
{
auto package = static_cast<AML::Package*>(source.ptr());
if (index.value() >= package->elements.size())
{
AML_ERROR("IndexOp index is out of package bounds");
return ParseResult::Failure;
}
auto package_element = package->elements[index.value()];
result = MUST(BAN::RefPtr<AML::Reference>::create(package_element));
break;
}
case AML::Node::Type::String:
AML_TODO("IndexOp source String");
return ParseResult::Failure;
default:
AML_ERROR("IndexOp source is not a Buffer, Package, or String");
return ParseResult::Failure;
}
#if AML_DEBUG_LEVEL >= 2
AML_DEBUG_PRINT("Index {}, ", index.value());
source->debug_print(0);
AML_DEBUG_PRINTLN("");
#endif
if (context.aml_data.size() < 1)
return ParseResult::Failure;
if (context.aml_data[0] == 0x00)
context.aml_data = context.aml_data.slice(1);
else
{
auto destination_result = AML::parse_object(context);
if (!destination_result.success())
return ParseResult::Failure;
auto destination = destination_result.node();
if (!destination)
{
AML_ERROR("IndexOp failed to resolve destination");
return ParseResult::Failure;
}
if (!destination->store(result))
return ParseResult::Failure;
}
return ParseResult(result);
}
};
}

View File

@@ -1,131 +0,0 @@
#pragma once
#include <BAN/Endianness.h>
#include <BAN/Optional.h>
#include <BAN/String.h>
#include <BAN/Vector.h>
#include <kernel/ACPI/AML/Bytes.h>
#include <kernel/ACPI/AML/Node.h>
#include <kernel/ACPI/AML/Utils.h>
namespace Kernel::ACPI::AML
{
struct Integer : public Node
{
struct Constants
{
// Initialized in Namespace::create_root_namespace
static BAN::RefPtr<Integer> Zero;
static BAN::RefPtr<Integer> One;
static BAN::RefPtr<Integer> Ones;
};
const bool constant;
uint64_t value;
Integer(uint64_t value, bool constant = false)
: Node(Node::Type::Integer)
, value(value)
, constant(constant)
{}
BAN::RefPtr<AML::Node> evaluate() override
{
return this;
}
bool store(BAN::RefPtr<AML::Node> store_node) override
{
if (constant)
{
AML_ERROR("Cannot store to constant integer");
return false;
}
auto store_value = store_node->as_integer();
if (!store_value.has_value())
{
AML_ERROR("Cannot store non-integer to integer");
return false;
}
value = store_value.value();
return true;
}
static ParseResult parse(BAN::ConstByteSpan& aml_data)
{
switch (static_cast<AML::Byte>(aml_data[0]))
{
case AML::Byte::ZeroOp:
aml_data = aml_data.slice(1);
return ParseResult(Constants::Zero);
case AML::Byte::OneOp:
aml_data = aml_data.slice(1);
return ParseResult(Constants::One);
case AML::Byte::OnesOp:
aml_data = aml_data.slice(1);
return ParseResult(Constants::Ones);
case AML::Byte::BytePrefix:
{
if (aml_data.size() < 2)
return ParseResult::Failure;
uint8_t value = aml_data[1];
aml_data = aml_data.slice(2);
return ParseResult(MUST(BAN::RefPtr<Integer>::create(value)));
}
case AML::Byte::WordPrefix:
{
if (aml_data.size() < 3)
return ParseResult::Failure;
uint16_t value = BAN::little_endian_to_host<uint16_t>(
*reinterpret_cast<const uint16_t*>(&aml_data[1])
);
aml_data = aml_data.slice(3);
return ParseResult(MUST(BAN::RefPtr<Integer>::create(value)));
}
case AML::Byte::DWordPrefix:
{
if (aml_data.size() < 5)
return ParseResult::Failure;
uint32_t value = BAN::little_endian_to_host<uint32_t>(
*reinterpret_cast<const uint32_t*>(&aml_data[1])
);
aml_data = aml_data.slice(5);
return ParseResult(MUST(BAN::RefPtr<Integer>::create(value)));
}
case AML::Byte::QWordPrefix:
{
if (aml_data.size() < 9)
return ParseResult::Failure;
uint64_t value = BAN::little_endian_to_host<uint64_t>(
*reinterpret_cast<const uint64_t*>(&aml_data[1])
);
aml_data = aml_data.slice(9);
return ParseResult(MUST(BAN::RefPtr<Integer>::create(value)));
}
default:
ASSERT_NOT_REACHED();
}
}
void debug_print(int indent) const override
{
AML_DEBUG_PRINT_INDENT(indent);
if (!constant)
AML_DEBUG_PRINT("0x{H}", value);
else
{
AML_DEBUG_PRINT("Const ");
if (value == Constants::Zero->value)
AML_DEBUG_PRINT("Zero");
else if (value == Constants::One->value)
AML_DEBUG_PRINT("One");
else if (value == Constants::Ones->value)
AML_DEBUG_PRINT("Ones");
else
ASSERT_NOT_REACHED();
}
}
};
}

View File

@@ -1,175 +0,0 @@
#pragma once
#include <BAN/Function.h>
#include <kernel/ACPI/AML/Bytes.h>
#include <kernel/ACPI/AML/Namespace.h>
#include <kernel/ACPI/AML/ParseContext.h>
#include <kernel/ACPI/AML/Pkg.h>
#include <kernel/ACPI/AML/Scope.h>
namespace Kernel::ACPI::AML
{
struct Method : public AML::Scope
{
Kernel::Mutex mutex;
uint8_t arg_count;
bool serialized;
uint8_t sync_level;
BAN::Function<BAN::RefPtr<AML::Node>(ParseContext&)> override_function;
BAN::ConstByteSpan term_list;
Method(AML::NameSeg name, uint8_t arg_count, bool serialized, uint8_t sync_level)
: AML::Scope(Node::Type::Method, name)
, arg_count(arg_count)
, serialized(serialized)
, sync_level(sync_level)
{}
static ParseResult parse(AML::ParseContext& context)
{
ASSERT(context.aml_data.size() >= 1);
ASSERT(static_cast<Byte>(context.aml_data[0]) == Byte::MethodOp);
context.aml_data = context.aml_data.slice(1);
auto method_pkg = AML::parse_pkg(context.aml_data);
if (!method_pkg.has_value())
return ParseResult::Failure;
auto name_string = AML::NameString::parse(method_pkg.value());
if (!name_string.has_value())
return ParseResult::Failure;
if (method_pkg->size() < 1)
return ParseResult::Failure;
auto method_flags = method_pkg.value()[0];
method_pkg = method_pkg.value().slice(1);
auto method = MUST(BAN::RefPtr<Method>::create(
name_string.value().path.back(),
method_flags & 0x07,
(method_flags >> 3) & 0x01,
method_flags >> 4
));
if (!Namespace::root_namespace()->add_named_object(context, name_string.value(), method))
return ParseResult::Failure;
method->term_list = method_pkg.value();
#if AML_DEBUG_LEVEL >= 2
method->debug_print(0);
AML_DEBUG_PRINTLN("");
#endif
return ParseResult::Success;
}
BAN::Optional<BAN::RefPtr<AML::Node>> invoke(
BAN::RefPtr<AML::Node> arg0 = {},
BAN::RefPtr<AML::Node> arg1 = {},
BAN::RefPtr<AML::Node> arg2 = {},
BAN::RefPtr<AML::Node> arg3 = {},
BAN::RefPtr<AML::Node> arg4 = {},
BAN::RefPtr<AML::Node> arg5 = {},
BAN::RefPtr<AML::Node> arg6 = {}
)
{
BAN::Vector<uint8_t> sync_stack;
return invoke_with_sync_stack(sync_stack, arg0, arg1, arg2, arg3, arg4, arg5, arg6);
}
BAN::Optional<BAN::RefPtr<AML::Node>> invoke_with_sync_stack(
BAN::Vector<uint8_t>& current_sync_stack,
BAN::RefPtr<AML::Node> arg0 = {},
BAN::RefPtr<AML::Node> arg1 = {},
BAN::RefPtr<AML::Node> arg2 = {},
BAN::RefPtr<AML::Node> arg3 = {},
BAN::RefPtr<AML::Node> arg4 = {},
BAN::RefPtr<AML::Node> arg5 = {},
BAN::RefPtr<AML::Node> arg6 = {}
)
{
if (serialized && !current_sync_stack.empty() && sync_level < current_sync_stack.back())
{
AML_ERROR("Trying to evaluate method {} with lower sync level than current sync level", scope);
return {};
}
ParseContext context;
context.aml_data = term_list;
context.scope = scope;
context.method_args[0] = MUST(BAN::RefPtr<AML::Register>::create(arg0));
context.method_args[1] = MUST(BAN::RefPtr<AML::Register>::create(arg1));
context.method_args[2] = MUST(BAN::RefPtr<AML::Register>::create(arg2));
context.method_args[3] = MUST(BAN::RefPtr<AML::Register>::create(arg3));
context.method_args[4] = MUST(BAN::RefPtr<AML::Register>::create(arg4));
context.method_args[5] = MUST(BAN::RefPtr<AML::Register>::create(arg5));
context.method_args[6] = MUST(BAN::RefPtr<AML::Register>::create(arg6));
context.sync_stack = BAN::move(current_sync_stack);
for (auto& local : context.method_locals)
local = MUST(BAN::RefPtr<AML::Register>::create());
if (serialized)
{
mutex.lock();
MUST(context.sync_stack.push_back(sync_level));
}
#if AML_DEBUG_LEVEL >= 2
AML_DEBUG_PRINTLN("Evaluating {}", scope);
#endif
BAN::Optional<BAN::RefPtr<AML::Node>> return_value = BAN::RefPtr<AML::Node>();
if (override_function)
return_value = override_function(context);
else
{
while (context.aml_data.size() > 0)
{
auto parse_result = AML::parse_object(context);
if (parse_result.returned())
{
return_value = parse_result.node();
break;
}
if (!parse_result.success())
{
AML_ERROR("Method {} evaluate failed", scope);
return_value = {};
break;
}
}
}
while (!context.created_objects.empty())
{
Namespace::root_namespace()->remove_named_object(context.created_objects.back());
context.created_objects.pop_back();
}
if (serialized)
{
context.sync_stack.pop_back();
mutex.unlock();
}
current_sync_stack = BAN::move(context.sync_stack);
return return_value;
}
virtual void debug_print(int indent) const override
{
AML_DEBUG_PRINT_INDENT(indent);
AML_DEBUG_PRINT("Method ");
name.debug_print();
AML_DEBUG_PRINTLN("({} args, {}Serialized, 0x{H}) {", arg_count, serialized ? "" : "Not", sync_level);
AML_DEBUG_PRINT_INDENT(indent + 1);
AML_DEBUG_PRINTLN("TermList: {} bytes", term_list.size());
AML_DEBUG_PRINT_INDENT(indent);
AML_DEBUG_PRINT("}");
}
};
}

View File

@@ -1,166 +0,0 @@
#pragma once
#include <kernel/ACPI/AML/Bytes.h>
#include <kernel/ACPI/AML/Integer.h>
#include <kernel/ACPI/AML/NamedObject.h>
#include <kernel/ACPI/AML/ParseContext.h>
#include <kernel/Lock/Mutex.h>
#include <kernel/Timer/Timer.h>
namespace Kernel::ACPI::AML
{
struct Mutex : public AML::NamedObject
{
Kernel::Mutex mutex;
uint8_t sync_level;
Mutex(NameSeg name, uint8_t sync_level)
: NamedObject(Node::Type::Mutex, name)
, sync_level(sync_level)
{}
static ParseResult parse(ParseContext& context)
{
ASSERT(context.aml_data.size() >= 2);
ASSERT(static_cast<AML::Byte>(context.aml_data[0]) == AML::Byte::ExtOpPrefix);
switch (static_cast<AML::ExtOp>(context.aml_data[1]))
{
case AML::ExtOp::MutexOp:
return parse_mutex(context);
case AML::ExtOp::AcquireOp:
return parse_acquire(context);
case AML::ExtOp::ReleaseOp:
return parse_release(context);
default:
ASSERT_NOT_REACHED();
}
}
virtual void debug_print(int indent) const override
{
AML_DEBUG_PRINT_INDENT(indent);
AML_DEBUG_PRINT("Mutex ");
name.debug_print();
AML_DEBUG_PRINT(" (SyncLevel: {})", sync_level);
}
private:
static ParseResult parse_mutex(ParseContext& context)
{
ASSERT(context.aml_data.size() >= 2);
ASSERT(static_cast<AML::Byte>(context.aml_data[0]) == AML::Byte::ExtOpPrefix);
ASSERT(static_cast<AML::ExtOp>(context.aml_data[1]) == AML::ExtOp::MutexOp);
context.aml_data = context.aml_data.slice(2);
auto name = NameString::parse(context.aml_data);
if (!name.has_value())
return ParseResult::Failure;
if (context.aml_data.size() < 1)
return ParseResult::Failure;
auto sync_level = context.aml_data[0];
context.aml_data = context.aml_data.slice(1);
if (sync_level & 0xF0)
{
AML_ERROR("Invalid sync level {}", sync_level);
return ParseResult::Failure;
}
auto mutex = MUST(BAN::RefPtr<Mutex>::create(name->path.back(), sync_level));
if (!Namespace::root_namespace()->add_named_object(context, name.value(), mutex))
return ParseResult::Failure;
#if AML_DEBUG_LEVEL >= 2
mutex->debug_print(0);
AML_DEBUG_PRINTLN("");
#endif
return ParseResult::Success;
}
static ParseResult parse_acquire(ParseContext& context)
{
ASSERT(context.aml_data.size() >= 2);
ASSERT(static_cast<AML::Byte>(context.aml_data[0]) == AML::Byte::ExtOpPrefix);
ASSERT(static_cast<AML::ExtOp>(context.aml_data[1]) == AML::ExtOp::AcquireOp);
context.aml_data = context.aml_data.slice(2);
auto mutex_result = AML::parse_object(context);
if (!mutex_result.success() || !mutex_result.node() || mutex_result.node()->type != AML::Node::Type::Mutex)
{
AML_ERROR("Acquire does not name a valid mutex");
return ParseResult::Failure;
}
auto* mutex = static_cast<AML::Mutex*>(mutex_result.node().ptr());
if (mutex->sync_level < context.sync_level())
{
AML_ERROR("Trying to acquire mutex with lower sync level than current sync level");
return ParseResult::Failure;
}
if (context.aml_data.size() < 2)
{
AML_ERROR("Missing timeout value");
return ParseResult::Failure;
}
uint16_t timeout = context.aml_data[0] | (context.aml_data[1] << 8);
context.aml_data = context.aml_data.slice(2);
if (timeout >= 0xFFFF)
mutex->mutex.lock();
else
{
// FIXME: This is a very inefficient way to wait for a mutex
uint64_t wake_time = SystemTimer::get().ms_since_boot() + timeout;
while (!mutex->mutex.try_lock())
{
if (SystemTimer::get().ms_since_boot() >= wake_time)
return ParseResult(Integer::Constants::Ones);
SystemTimer::get().sleep(1);
}
}
MUST(context.sync_stack.push_back(mutex->sync_level));
return ParseResult(Integer::Constants::Zero);
}
static ParseResult parse_release(ParseContext& context)
{
ASSERT(context.aml_data.size() >= 2);
ASSERT(static_cast<AML::Byte>(context.aml_data[0]) == AML::Byte::ExtOpPrefix);
ASSERT(static_cast<AML::ExtOp>(context.aml_data[1]) == AML::ExtOp::ReleaseOp);
context.aml_data = context.aml_data.slice(2);
auto mutex_result = AML::parse_object(context);
if (!mutex_result.success() || !mutex_result.node() || mutex_result.node()->type != AML::Node::Type::Mutex)
{
AML_ERROR("Release does not name a valid mutex");
return ParseResult::Failure;
}
if (context.sync_stack.empty())
{
AML_ERROR("Trying to release mutex without having acquired it");
return ParseResult::Failure;
}
auto* mutex = static_cast<AML::Mutex*>(mutex_result.node().ptr());
if (mutex->sync_level != context.sync_level())
{
AML_ERROR("Trying to release mutex with different sync level than current sync level");
return ParseResult::Failure;
}
mutex->mutex.unlock();
context.sync_stack.pop_back();
return ParseResult::Success;
}
};
}

View File

@@ -1,42 +0,0 @@
#pragma once
#include <BAN/HashMap.h>
#include <kernel/ACPI/AML/Names.h>
namespace Kernel::ACPI::AML
{
struct NamedObject : public Node
{
BAN::RefPtr<NamedObject> parent;
NameSeg name;
NamedObject(Node::Type type, NameSeg name) : Node(type), name(name) {}
};
struct Name : public NamedObject
{
BAN::RefPtr<AML::Node> object;
Name(NameSeg name, BAN::RefPtr<AML::Node> object)
: NamedObject(Node::Type::Name, name), object(BAN::move(object))
{}
BAN::RefPtr<AML::Node> evaluate() override
{
ASSERT(object);
return object->evaluate();
}
bool store(BAN::RefPtr<AML::Node> node) override
{
ASSERT(object);
object = node;
return true;
}
static ParseResult parse(ParseContext& context);
virtual void debug_print(int indent) const override;
};
}

View File

@@ -1,241 +0,0 @@
#pragma once
#include <BAN/Optional.h>
#include <BAN/String.h>
#include <BAN/Vector.h>
#include <kernel/ACPI/AML/Bytes.h>
#include <kernel/ACPI/AML/Node.h>
#include <kernel/ACPI/AML/Utils.h>
namespace Kernel::ACPI::AML
{
struct NameSeg
{
union {
char chars[4];
uint32_t u32;
};
NameSeg() = default;
NameSeg(BAN::StringView name)
{
ASSERT(name.size() <= 4);
for (size_t i = 0; i < name.size(); i++)
chars[i] = static_cast<char>(name[i]);
for (size_t i = name.size(); i < 4; i++)
chars[i] = '_';
}
NameSeg(BAN::ConstByteSpan& aml_data)
{
ASSERT(aml_data.size() >= 4);
for (size_t i = 0; i < 4; i++)
chars[i] = static_cast<char>(aml_data[i]);
aml_data = aml_data.slice(4);
}
BAN::StringView sv() const
{
size_t len = 4;
while (len > 0 && chars[len - 1] == '_')
len--;
return BAN::StringView(chars, len);
}
static BAN::Optional<NameSeg> parse(BAN::ConstByteSpan& aml_data)
{
if (aml_data.size() < 4)
return {};
if (!is_lead_name_char(aml_data[0])
|| !is_name_char(aml_data[1])
|| !is_name_char(aml_data[2])
|| !is_name_char(aml_data[3]))
return {};
return NameSeg(aml_data);
}
constexpr bool operator==(const NameSeg& other) const
{
return u32 == other.u32;
}
void debug_print() const
{
size_t len = 4;
while (len > 0 && chars[len - 1] == '_')
len--;
for (size_t i = 0; i < len; i++)
AML_DEBUG_PUTC(chars[i]);
}
};
struct NameString
{
BAN::String prefix;
BAN::Vector<NameSeg> path;
NameString() = default;
NameString(BAN::StringView str)
{
if (!str.empty() && str.front() == '\\')
{
MUST(prefix.push_back('\\'));
str = str.substring(1);
}
else
{
while (str.size() > 0 && str.front() == '^')
{
MUST(prefix.push_back('^'));
str = str.substring(1);
}
}
while (!str.empty())
{
ASSERT(str[0] != '.');
size_t len = 1;
while (len < str.size() && str[len] != '.')
len++;
ASSERT(len <= 4);
MUST(path.push_back(NameSeg(str.substring(0, len))));
str = str.substring(len);
if (!str.empty())
{
ASSERT(str[0] == '.');
str = str.substring(1);
}
}
}
static bool can_parse(BAN::ConstByteSpan aml_data)
{
if (aml_data.size() == 0)
return false;
switch (static_cast<AML::Byte>(aml_data[0]))
{
case AML::Byte::RootChar:
case AML::Byte::ParentPrefixChar:
case AML::Byte::NullName:
case AML::Byte::DualNamePrefix:
case AML::Byte::MultiNamePrefix:
return true;
default:
return is_lead_name_char(aml_data[0]);
}
}
static BAN::Optional<NameString> parse(BAN::ConstByteSpan& aml_data)
{
if (aml_data.size() == 0)
return {};
NameString result;
if (static_cast<AML::Byte>(aml_data[0]) == AML::Byte::RootChar)
{
MUST(result.prefix.push_back('\\'));
aml_data = aml_data.slice(1);
}
else
{
while (aml_data.size() > 0 && static_cast<AML::Byte>(aml_data[0]) == AML::Byte::ParentPrefixChar)
{
MUST(result.prefix.push_back(aml_data[0]));
aml_data = aml_data.slice(1);
}
}
if (aml_data.size() == 0)
return {};
size_t name_count = 1;
switch (static_cast<AML::Byte>(aml_data[0]))
{
case AML::Byte::NullName:
name_count = 0;
aml_data = aml_data.slice(1);
break;
case AML::Byte::DualNamePrefix:
name_count = 2;
aml_data = aml_data.slice(1);
break;
case AML::Byte::MultiNamePrefix:
if (aml_data.size() < 2)
return {};
name_count = aml_data[1];
aml_data = aml_data.slice(2);
break;
default:
break;
}
for (size_t i = 0; i < name_count; i++)
{
auto name_seg = NameSeg::parse(aml_data);
if (!name_seg.has_value())
return {};
MUST(result.path.push_back(name_seg.release_value()));
}
return result;
}
void debug_print() const
{
for (size_t i = 0; i < prefix.size(); i++)
AML_DEBUG_PUTC(prefix[i]);
if (!path.empty())
path.front().debug_print();
for (size_t i = 1; i < path.size(); i++)
{
AML_DEBUG_PUTC('.');
path[i].debug_print();
}
}
};
}
namespace BAN
{
template<>
struct hash<Kernel::ACPI::AML::NameSeg>
{
constexpr hash_t operator()(Kernel::ACPI::AML::NameSeg name) const
{
return hash<uint32_t>()(name.u32);
}
};
template<typename F>
void Formatter::print_argument(F putc, const Kernel::ACPI::AML::NameSeg& name_seg, const ValueFormat&)
{
size_t len = 4;
while (len > 0 && name_seg.chars[len - 1] == '_')
len--;
for (size_t i = 0; i < len; i++)
putc(name_seg.chars[i]);
}
template<typename F>
void Formatter::print_argument(F putc, const Kernel::ACPI::AML::NameString& name_string, const ValueFormat&)
{
print_argument(putc, name_string.prefix, {});
if (!name_string.path.empty())
print_argument(putc, name_string.path.front(), {});
for (size_t i = 1; i < name_string.path.size(); i++)
{
putc('.');
print_argument(putc, name_string.path[i], {});
}
}
}

View File

@@ -1,63 +1,74 @@
#pragma once
#include <BAN/Bitcast.h>
#include <BAN/ByteSpan.h>
#include <BAN/Function.h>
#include <BAN/HashMap.h>
#include <kernel/ACPI/AML/Scope.h>
#include <kernel/ACPI/Headers.h>
#include <kernel/Lock/Mutex.h>
#include <BAN/HashSet.h>
#include <BAN/Iteration.h>
#include <kernel/ACPI/AML/Node.h>
namespace Kernel::ACPI::AML
{
struct Namespace : public AML::Scope
struct Namespace
{
static BAN::RefPtr<AML::Namespace> root_namespace();
BAN_NON_COPYABLE(Namespace);
BAN_NON_MOVABLE(Namespace);
public:
Namespace() = default;
~Namespace();
template<typename F>
static void for_each_child(const AML::NameString& scope, const F& callback)
static BAN::ErrorOr<void> prepare_root_namespace();
static Namespace& root_namespace();
BAN::ErrorOr<void> post_load_initialize();
BAN::ErrorOr<void> parse(BAN::ConstByteSpan);
BAN::ErrorOr<Node> evaluate(BAN::StringView path) { return evaluate(Scope {}, path); }
BAN::ErrorOr<Node> evaluate(const Scope& scope, BAN::StringView);
// returns empty scope if object already exited
BAN::ErrorOr<Scope> add_named_object(ParseContext& context, const NameString& name_string, Node&& node);
BAN::ErrorOr<Scope> add_alias(ParseContext& scope, const NameString& name_string, Reference* reference);
BAN::ErrorOr<void> remove_named_object(const Scope& absolute_path);
// node is nullptr if it is not found
struct FindResult
{
auto canonical_path = root_namespace()->resolve_path(scope, {}, FindMode::ForceAbsolute);
ASSERT(canonical_path.has_value());
for (auto& [path, child] : root_namespace()->m_objects)
{
if (path.size() < canonical_path->size() + 1)
continue;
if (canonical_path->size() != 1 && path[canonical_path->size()] != '.')
continue;
if (path.sv().substring(0, canonical_path->size()) != canonical_path->sv())
continue;
if (path.sv().substring(canonical_path->size() + 1).contains('.'))
continue;
callback(path, child);
}
}
Namespace(NameSeg name) : AML::Scope(Node::Type::Namespace, name) {}
static BAN::RefPtr<AML::Namespace> create_root_namespace();
bool parse(const SDTHeader& header);
void debug_print(int indent) const override;
enum class FindMode
{
Normal,
ForceAbsolute,
Scope path;
Reference* node { nullptr };
};
BAN::Optional<BAN::String> resolve_path(const AML::NameString& relative_base, const AML::NameString& relative_path, FindMode mode, bool check_existence = true) const;
BAN::ErrorOr<FindResult> find_named_object(const Scope& scope, const NameString& name_string, bool force_absolute = false);
// Find an object in the namespace. Returns nullptr if the object is not found.
BAN::RefPtr<NamedObject> find_object(const AML::NameString& relative_base, const AML::NameString& relative_path, FindMode mode);
BAN::ErrorOr<Scope> find_reference_scope(const Reference* reference);
// Add an object to the namespace. Returns false if the parent object could not be added.
bool add_named_object(ParseContext&, const AML::NameString& object_path, BAN::RefPtr<NamedObject> object);
BAN::ErrorOr<void> for_each_child(const Scope&, const BAN::Function<BAN::Iteration(BAN::StringView, Reference*)>&);
BAN::ErrorOr<void> for_each_child(const Scope&, const BAN::Function<BAN::Iteration(const Scope&, Reference*)>&);
// Remove an object from the namespace. Returns false if the object could not be removed.
bool remove_named_object(const AML::NameString& absolute_path);
BAN::ErrorOr<BAN::Vector<Scope>> find_device_with_eisa_id(BAN::StringView eisa_id);
BAN::ErrorOr<BAN::Vector<Scope>> find_device_with_eisa_id(BAN::Span<BAN::StringView> eisa_ids);
private:
BAN::HashMap<BAN::String, BAN::RefPtr<NamedObject>> m_objects;
mutable Mutex m_object_mutex;
BAN::ErrorOr<Scope> resolve_path(const Scope& scope, const NameString& name_string);
BAN::ErrorOr<void> initialize_scope(const Scope& scope);
BAN::ErrorOr<void> opregion_call_reg(const Scope& scope, const Node& opregion);
BAN::ErrorOr<uint64_t> evaluate_sta(const Scope& scope);
BAN::ErrorOr<void> evaluate_ini(const Scope& scope);
BAN::ErrorOr<void> initialize_op_regions();
private:
bool m_has_initialized_namespace { false };
BAN::HashMap<Scope, Reference*> m_named_objects;
BAN::HashMap<Scope, uint32_t> m_called_reg_bitmaps;
BAN::HashSet<Scope> m_aliases;
};
}

View File

@@ -1,95 +1,449 @@
#pragma once
#include <BAN/Array.h>
#include <BAN/ByteSpan.h>
#include <BAN/LinkedList.h>
#include <BAN/NoCopyMove.h>
#include <BAN/Optional.h>
#include <BAN/RefPtr.h>
#include <BAN/StringView.h>
#include <BAN/Vector.h>
#include <kernel/ACPI/AML/Utils.h>
#include <kernel/ACPI/AML/Scope.h>
#include <kernel/ACPI/Headers.h>
#include <kernel/Lock/Mutex.h>
#define AML_DUMP_FUNCTION_CALLS 0
#define AML_ENABLE_DEBUG 1
namespace Kernel::ACPI::AML
{
struct Node : public BAN::RefCounted<Node>
struct NameString
{
static uint64_t total_node_count;
BAN_NON_COPYABLE(NameString);
public:
NameString() = default;
NameString(NameString&& other)
: base(other.base)
, parts(BAN::move(other.parts))
{}
NameString& operator=(NameString&& other)
{
base = other.base;
parts = BAN::move(other.parts);
return *this;
}
static BAN::ErrorOr<NameString> from_string(BAN::StringView name);
BAN::ErrorOr<NameString> copy() const
{
NameString result;
result.base = this->base;
TRY(result.parts.resize(parts.size()));
for (size_t i = 0; i < parts.size(); i++)
result.parts[i] = parts[i];
return result;
}
static constexpr uint32_t base_root = -1;
uint32_t base { 0 };
BAN::Vector<uint32_t> parts;
};
template<typename T1, typename T2>
struct Pair
{
T1 elem1;
T2 elem2;
};
struct Node;
struct ParseContext;
struct Reference;
struct Mutex
{
Kernel::Mutex mutex;
uint8_t sync_level;
bool global_lock;
uint32_t ref_count;
};
struct Buffer
{
BAN::StringView as_sv() const
{
return BAN::StringView(reinterpret_cast<const char*>(bytes), size);
}
uint64_t size;
uint32_t ref_count;
uint8_t bytes[];
};
struct OpRegion
{
GAS::AddressSpaceID address_space;
uint64_t offset;
uint64_t length;
alignas(Scope) uint8_t scope_storage[sizeof(Scope)];
Scope& scope() { return *reinterpret_cast<Scope*>(scope_storage); }
const Scope& scope() const { return *reinterpret_cast<const Scope*>(scope_storage); }
};
struct FieldUnit
{
enum class Type {
Field,
IndexField,
BankField,
};
uint64_t offset;
uint64_t length;
uint8_t flags;
Type type;
union {
struct {
OpRegion opregion;
} field;
struct {
Reference* index;
Reference* data;
} index_field;
struct {
OpRegion opregion;
Reference* bank_selector;
uint64_t bank_value;
} bank_field;
} as;
};
struct Package
{
struct Element
{
struct Location {
NameString name;
Scope scope;
};
bool resolved { true };
union {
Node* node { nullptr };
Location* location;
} value;
};
uint64_t num_elements;
uint32_t ref_count;
Element elements[];
};
struct Node
{
BAN_NON_COPYABLE(Node);
public:
Node() = default;
~Node() { clear(); }
Node(Node&& other) { *this = BAN::move(other); }
Node& operator=(Node&&);
static BAN::ErrorOr<Node> create_string(BAN::StringView string)
{
const auto* u8_data = reinterpret_cast<const uint8_t*>(string.data());
auto result = TRY(create_buffer({ u8_data, string.size() }));
result.type = Node::Type::String;
return result;
}
static BAN::ErrorOr<Node> create_buffer(BAN::ConstByteSpan buffer)
{
Node node;
node.type = Node::Type::Buffer;
node.as.str_buf = static_cast<Buffer*>(kmalloc(sizeof(Buffer) + buffer.size()));
if (node.as.str_buf == nullptr)
return BAN::Error::from_errno(ENOMEM);
node.as.str_buf->ref_count = 1;
node.as.str_buf->size = buffer.size();
memcpy(node.as.str_buf->bytes, buffer.data(), buffer.size());
return node;
}
enum class Type
{
BankFieldElement,
Buffer,
BufferField,
Device,
FieldElement,
IndexFieldElement,
Uninitialized,
Debug,
Integer,
String,
Buffer,
Package,
BufferField,
OpRegion,
FieldUnit,
Event,
Device,
Processor,
PowerResource,
ThermalZone,
Method,
Mutex,
Name,
Namespace,
OpRegion,
Package,
PackageElement,
PowerResource,
Processor,
// FIXME: Index should not be its own type
// parsing index should return references
Index,
Reference,
Register,
String,
ThermalZone,
};
const Type type;
PredefinedScope,
Count
} type { Type::Uninitialized };
Node(Type type) : type(type) { total_node_count++; }
virtual ~Node() { total_node_count--; }
virtual bool is_scope() const { return false; }
[[nodiscard]] BAN::Optional<uint64_t> as_integer();
[[nodiscard]] virtual BAN::RefPtr<AML::Node> evaluate() { AML_TODO("evaluate, type {}", static_cast<uint8_t>(type)); return nullptr; }
[[nodiscard]] virtual bool store(BAN::RefPtr<AML::Node> source) { AML_TODO("store, type {}", static_cast<uint8_t>(type)); return false; }
virtual void debug_print(int indent) const = 0;
};
struct ParseContext;
struct ParseResult
inline bool is_scope() const
{
static ParseResult Failure;
static ParseResult Success;
enum class Result
switch (type)
{
Success,
Failure,
Returned,
};
ParseResult(Result success)
: m_result(success)
{}
ParseResult(Result success, BAN::RefPtr<Node> node)
: m_result(success)
, m_node(BAN::move(node))
{}
ParseResult(BAN::RefPtr<Node> node)
: m_result(Result::Success)
, m_node(BAN::move(node))
{
ASSERT(m_node);
case Type::Device:
case Type::Processor:
case Type::PowerResource:
case Type::ThermalZone:
case Type::PredefinedScope:
return true;
default:
return false;
}
ASSERT_NOT_REACHED();
}
bool success() const { return m_result == Result::Success; }
bool returned() const { return m_result == Result::Returned; }
BAN::RefPtr<Node> node()
union
{
ASSERT(m_node);
return m_node;
}
struct {
uint64_t value;
} integer;
Package* package;
Buffer* str_buf;
struct {
Buffer* buffer;
uint64_t bit_offset;
uint64_t bit_count;
} buffer_field;
OpRegion opregion;
FieldUnit field_unit;
struct {
uint32_t signal_count;
} event;
struct {
uint8_t storage[sizeof(Kernel::Mutex)];
const uint8_t* start;
size_t length;
uint8_t arg_count;
BAN::ErrorOr<Node> (*override_func)(const BAN::Array<Reference*, 7>&);
bool serialized;
Mutex* mutex;
} method;
Mutex* mutex;
struct {
Node::Type type;
union {
Buffer* str_buf;
Package* package;
} as;
uint64_t index;
} index;
Reference* reference;
} as;
private:
Result m_result = Result::Failure;
BAN::RefPtr<Node> m_node;
BAN::ErrorOr<Node> copy() const;
void clear();
};
ParseResult parse_object(ParseContext& context);
struct Reference
{
Node node {};
uint32_t ref_count { 1 };
};
struct ParseContext
{
Scope scope;
BAN::ConstByteSpan aml_data;
uint32_t call_depth { 0 };
BAN::Array<Reference*, 8> locals;
BAN::Array<Reference*, 7> args;
BAN::LinkedList<Scope> created_nodes;
~ParseContext();
BAN::ErrorOr<void> allocate_locals();
};
enum class ExecutionFlow
{
Normal,
Break,
Continue,
Return,
};
using ExecutionFlowResult = Pair<ExecutionFlow, BAN::Optional<Node>>;
enum Conversion : uint8_t
{
ConvInteger = 1,
ConvBuffer = 2,
ConvString = 4,
};
BAN::ErrorOr<Node> parse_node(ParseContext& context, bool return_ref = false);
BAN::ErrorOr<ExecutionFlowResult> parse_node_or_execution_flow(ParseContext& context);
BAN::ErrorOr<NameString> parse_name_string(BAN::ConstByteSpan& aml_data);
BAN::ErrorOr<BAN::ConstByteSpan> parse_pkg(BAN::ConstByteSpan& aml_data);
BAN::ErrorOr<Node> convert_node(Node&& source, uint8_t conversion, uint64_t max_length);
BAN::ErrorOr<Node> convert_node(Node&& source, const Node& target);
BAN::ErrorOr<Node> evaluate_node(const Scope& node_path, const Node& node);
// If method has no return, it will return <integer 0>
BAN::ErrorOr<Node> method_call(const Scope& scope, const Node& method, BAN::Array<Reference*, 7>&& args, uint32_t call_depth = 0);
BAN::ErrorOr<Node> method_call(const Scope& scope, const Node& method,
Node&& arg0 = {}, Node&& arg1 = {}, Node&& arg2 = {}, Node&& arg3 = {}, Node&& arg4 = {}, Node&& arg5 = {}, Node&& arg6 = {});
BAN::ErrorOr<void> resolve_package_element(Package::Element& element, bool error_if_not_exists);
}
namespace BAN::Formatter
{
template<typename F>
void print_argument(F putc, const Kernel::ACPI::AML::NameString& name_string, const ValueFormat&)
{
if (name_string.base == Kernel::ACPI::AML::NameString::base_root)
putc('\\');
else for (uint32_t i = 0; i < name_string.base; i++)
putc('^');
for (size_t i = 0; i < name_string.parts.size(); i++) {
if (i != 0)
putc('.');
const char* name_seg = reinterpret_cast<const char*>(&name_string.parts[i]);
putc(name_seg[0]); putc(name_seg[1]); putc(name_seg[2]); putc(name_seg[3]);
}
}
template<typename F>
void print_argument(F putc, const Kernel::ACPI::AML::Buffer& buffer, const ValueFormat&)
{
static constexpr size_t max_elements { 16 };
print(putc, "<buffer '");
if (buffer.size)
print(putc, "{2H}", buffer.bytes[0]);
for (size_t i = 1; i < buffer.size && i < max_elements; i++)
print(putc, " {2H}", buffer.bytes[i]);
if (buffer.size > max_elements)
print(putc, "...");
print(putc, "'>");
}
template<typename F>
void print_argument(F putc, const Kernel::ACPI::AML::Package& package, const ValueFormat&)
{
print(putc, "<package '{} elements'>", package.num_elements);
}
template<typename F>
void print_argument(F putc, const Kernel::ACPI::AML::Node& node, const ValueFormat&)
{
switch (node.type)
{
case Kernel::ACPI::AML::Node::Type::Uninitialized:
print(putc, "<uninitialized>");
break;
case Kernel::ACPI::AML::Node::Type::Debug:
print(putc, "<debug>");
break;
case Kernel::ACPI::AML::Node::Type::Integer:
print(putc, "<integer 0x{H}>", node.as.integer.value);
break;
case Kernel::ACPI::AML::Node::Type::String:
print(putc, "<string '{}'>", node.as.str_buf->as_sv());
break;
case Kernel::ACPI::AML::Node::Type::Package:
print(putc, "{}", *node.as.package);
break;
case Kernel::ACPI::AML::Node::Type::Buffer:
print(putc, "{}", *node.as.str_buf);
break;
case Kernel::ACPI::AML::Node::Type::BufferField:
print(putc, "<buffer field '{} bytes, offset 0x{H}, bit count {}'>",
node.as.buffer_field.buffer->size,
node.as.buffer_field.bit_offset,
node.as.buffer_field.bit_count
);
break;
case Kernel::ACPI::AML::Node::Type::OpRegion:
print(putc, "<opregion 'type {2H}, offset 0x{H}, length 0x{H}'>",
static_cast<uint8_t>(node.as.opregion.address_space),
node.as.opregion.offset,
node.as.opregion.length
);
break;
case Kernel::ACPI::AML::Node::Type::FieldUnit:
print(putc, "<field unit ({}), 'offset 0x{H}, length 0x{H}'>",
static_cast<uint8_t>(node.as.field_unit.type),
node.as.field_unit.offset,
node.as.field_unit.length
);
break;
case Kernel::ACPI::AML::Node::Type::Event:
print(putc, "<event '{} signals'>", node.as.event.signal_count);
break;
case Kernel::ACPI::AML::Node::Type::Device:
print(putc, "<device>");
break;
case Kernel::ACPI::AML::Node::Type::Processor:
print(putc, "<processor>");
break;
case Kernel::ACPI::AML::Node::Type::PowerResource:
print(putc, "<power resouce>");
break;
case Kernel::ACPI::AML::Node::Type::ThermalZone:
print(putc, "<thermal zone>");
break;
case Kernel::ACPI::AML::Node::Type::Method:
print(putc, "<method '{} bytes'>", node.as.method.length);
break;
case Kernel::ACPI::AML::Node::Type::Mutex:
print(putc, "<mutex>");
break;
case Kernel::ACPI::AML::Node::Type::Index:
switch (node.as.index.type)
{
case Kernel::ACPI::AML::Node::Type::String:
case Kernel::ACPI::AML::Node::Type::Buffer:
print(putc, "<index {}, {}>", *node.as.index.as.str_buf, node.as.index.index);
break;
case Kernel::ACPI::AML::Node::Type::Package:
print(putc, "<index {}, {}>", *node.as.index.as.package, node.as.index.index);
break;
default:
print(putc, "<index {}??, {}>", (uint32_t)node.as.index.type, node.as.index.index);
break;
}
break;
case Kernel::ACPI::AML::Node::Type::Reference:
print(putc, "<reference {}, {} refs>", node.as.reference->node, node.as.reference->ref_count);
break;
case Kernel::ACPI::AML::Node::Type::PredefinedScope:
print(putc, "<scope>");
break;
case Kernel::ACPI::AML::Node::Type::Count:
ASSERT_NOT_REACHED();
}
}
}

View File

@@ -1,66 +0,0 @@
#pragma once
#include <kernel/ACPI/AML/Device.h>
#include <kernel/ACPI/AML/ParseContext.h>
#include <kernel/ACPI/AML/Processor.h>
#include <kernel/ACPI/AML/ThermalZone.h>
namespace Kernel::ACPI::AML
{
struct Notify
{
static ParseResult parse(ParseContext& context)
{
ASSERT(context.aml_data.size() >= 1);
ASSERT(static_cast<Byte>(context.aml_data[0]) == Byte::NotifyOp);
context.aml_data = context.aml_data.slice(1);
auto object_result = AML::parse_object(context);
if (!object_result.success())
return ParseResult::Failure;
auto object = object_result.node();
if (!object)
{
AML_ERROR("Notify object is null");
return ParseResult::Failure;
}
auto value_result = AML::parse_object(context);
if (!value_result.success())
return ParseResult::Failure;
auto value = value_result.node() ? value_result.node()->as_integer() : BAN::Optional<uint64_t>();
if (!value.has_value())
{
AML_ERROR("Notify value is not an integer");
return ParseResult::Failure;
}
BAN::StringView object_type_sv;
BAN::StringView object_name_sv;
switch (object->type)
{
case AML::Node::Type::Device:
object_type_sv = "Device"sv;
object_name_sv = static_cast<AML::Device*>(object.ptr())->name.sv();
break;
case AML::Node::Type::Processor:
object_type_sv = "Processor"sv;
object_name_sv = static_cast<AML::Processor*>(object.ptr())->name.sv();
break;
case AML::Node::Type::ThermalZone:
object_type_sv = "ThermalZone"sv;
object_name_sv = static_cast<AML::ThermalZone*>(object.ptr())->name.sv();
break;
default:
object_type_sv = "Unknown"sv;
object_name_sv = "????"sv;
break;
}
AML_TODO("Notify: {} {}: {2H}", object_type_sv, object_name_sv, value.value());
return ParseResult::Success;
}
};
}

View File

@@ -0,0 +1,16 @@
#pragma once
#include <kernel/ACPI/AML/Node.h>
namespace Kernel::ACPI::AML
{
BAN::ErrorOr<void> parse_opregion_op(ParseContext& context);
BAN::ErrorOr<void> parse_field_op(ParseContext& context);
BAN::ErrorOr<void> parse_index_field_op(ParseContext& context);
BAN::ErrorOr<void> parse_bank_field_op(ParseContext& context);
BAN::ErrorOr<Node> convert_from_field_unit(const Node& node, uint8_t conversion, uint64_t max_length);
BAN::ErrorOr<void> store_to_field_unit(const Node& source, const Node& target);
}

View File

@@ -1,134 +0,0 @@
#pragma once
#include <kernel/ACPI/AML/Bytes.h>
#include <kernel/ACPI/AML/Node.h>
#include <kernel/ACPI/AML/ParseContext.h>
#include <kernel/ACPI/AML/Pkg.h>
namespace Kernel::ACPI::AML
{
struct PackageElement;
struct Package : public AML::Node
{
BAN::Vector<BAN::RefPtr<PackageElement>> elements;
AML::NameString scope;
Package(AML::NameString scope)
: Node(Node::Type::Package)
, elements(BAN::move(elements))
, scope(scope)
{}
BAN::RefPtr<AML::Node> evaluate() override
{
return this;
}
static ParseResult parse(AML::ParseContext& context);
virtual void debug_print(int indent) const override;
};
struct PackageElement : public AML::Node
{
BAN::RefPtr<AML::Package> parent;
BAN::RefPtr<AML::Node> element;
AML::NameString unresolved_name;
bool resolved = false;
bool initialized = false;
PackageElement(BAN::RefPtr<AML::Package> parent, BAN::RefPtr<AML::Node> element)
: Node(Node::Type::PackageElement)
, parent(parent)
, element(element)
{
ASSERT(element);
resolved = true;
initialized = true;
}
PackageElement(BAN::RefPtr<AML::Package> parent, AML::NameString unresolved_name)
: Node(Node::Type::PackageElement)
, parent(parent)
, unresolved_name(unresolved_name)
{
resolved = false;
initialized = true;
}
PackageElement(BAN::RefPtr<AML::Package> parent)
: Node(Node::Type::PackageElement)
, parent(parent)
, unresolved_name(unresolved_name)
{
resolved = false;
initialized = false;
}
BAN::RefPtr<AML::Node> evaluate() override
{
if (!initialized)
{
AML_ERROR("Trying to evaluate uninitialized PackageElement");
return {};
}
if (!resolved)
{
auto object = Namespace::root_namespace()->find_object(parent->scope, unresolved_name, Namespace::FindMode::Normal);
if (!object)
{
AML_ERROR("Failed to resolve reference {} in package {}", unresolved_name, parent->scope);
return {};
}
element = object;
resolved = true;
}
return element->evaluate();
}
static ParseResult parse(AML::ParseContext& context, BAN::RefPtr<AML::Package> package)
{
BAN::RefPtr<AML::PackageElement> element;
if (context.aml_data[0] != 0x00 && AML::NameString::can_parse(context.aml_data))
{
auto name = AML::NameString::parse(context.aml_data);
if (!name.has_value())
return ParseResult::Failure;
element = MUST(BAN::RefPtr<PackageElement>::create(package, name.value()));
}
else
{
auto element_result = AML::parse_object(context);
if (!element_result.success())
return ParseResult::Failure;
element = MUST(BAN::RefPtr<PackageElement>::create(package, element_result.node()));
}
return ParseResult(element);
}
virtual void debug_print(int indent) const override
{
AML_DEBUG_PRINT_INDENT(indent);
AML_DEBUG_PRINTLN("PackageElement {");
if (!initialized)
{
AML_DEBUG_PRINT_INDENT(indent + 1);
AML_DEBUG_PRINT("Uninitialized");
}
else if (!resolved)
{
AML_DEBUG_PRINT_INDENT(indent + 1);
AML_DEBUG_PRINT("Unresolved {}", unresolved_name);
}
else
{
element->debug_print(indent + 1);
}
AML_DEBUG_PRINTLN("");
AML_DEBUG_PRINT_INDENT(indent);
AML_DEBUG_PRINT("}");
}
};
}

View File

@@ -1,30 +0,0 @@
#pragma once
#include <BAN/Array.h>
#include <BAN/ByteSpan.h>
#include <BAN/LinkedList.h>
#include <kernel/ACPI/AML/NamedObject.h>
#include <kernel/ACPI/AML/Namespace.h>
#include <kernel/ACPI/AML/Register.h>
namespace Kernel::ACPI::AML
{
struct ParseContext
{
BAN::ConstByteSpan aml_data;
AML::NameString scope;
// Used for cleaning up on method exit
// NOTE: This uses linked list instead of vector because
// we don't really need large contiguous memory
BAN::LinkedList<AML::NameString> created_objects;
uint8_t sync_level() const { return !sync_stack.empty() ? sync_stack.back() : 0; }
BAN::Vector<uint8_t> sync_stack;
BAN::Array<BAN::RefPtr<Register>, 7> method_args;
BAN::Array<BAN::RefPtr<Register>, 8> method_locals;
};
}

View File

@@ -1,51 +0,0 @@
#pragma once
#include <BAN/ByteSpan.h>
#include <BAN/Optional.h>
namespace Kernel::ACPI::AML
{
static BAN::Optional<uint32_t> parse_pkg_length(BAN::ConstByteSpan aml_data)
{
if (aml_data.size() < 1)
return {};
uint8_t lead_byte = aml_data[0];
if ((lead_byte & 0xC0) && (lead_byte & 0x30))
return {};
uint32_t pkg_length = lead_byte & 0x3F;
uint8_t byte_count = (lead_byte >> 6) + 1;
if (aml_data.size() < byte_count)
return {};
for (uint8_t i = 1; i < byte_count; i++)
pkg_length |= aml_data[i] << (i * 8 - 4);
return pkg_length;
}
static void trim_pkg_length(BAN::ConstByteSpan& aml_data)
{
ASSERT(aml_data.size() >= 1);
uint8_t byte_count = (aml_data[0] >> 6) + 1;
aml_data = aml_data.slice(byte_count);
}
static BAN::Optional<BAN::ConstByteSpan> parse_pkg(BAN::ConstByteSpan& aml_data)
{
auto pkg_length = parse_pkg_length(aml_data);
if (!pkg_length.has_value())
return {};
auto result = aml_data.slice(0, pkg_length.value());
trim_pkg_length(result);
aml_data = aml_data.slice(pkg_length.value());
return result;
}
}

View File

@@ -1,68 +0,0 @@
#pragma once
#include <BAN/Endianness.h>
#include <kernel/ACPI/AML/Bytes.h>
#include <kernel/ACPI/AML/ParseContext.h>
#include <kernel/ACPI/AML/Pkg.h>
#include <kernel/ACPI/AML/Scope.h>
namespace Kernel::ACPI::AML
{
struct PowerResource : public AML::Scope
{
uint8_t system_level;
uint16_t resource_order;
PowerResource(NameSeg name, uint8_t system_level, uint16_t resource_order)
: Scope(Node::Type::PowerResource, name)
, system_level(system_level)
, resource_order(resource_order)
{}
static ParseResult parse(ParseContext& context)
{
ASSERT(context.aml_data.size() >= 2);
ASSERT(static_cast<AML::Byte>(context.aml_data[0]) == AML::Byte::ExtOpPrefix);
ASSERT(static_cast<AML::ExtOp>(context.aml_data[1]) == AML::ExtOp::PowerResOp);
context.aml_data = context.aml_data.slice(2);
auto opt_power_res_pkg = AML::parse_pkg(context.aml_data);
if (!opt_power_res_pkg.has_value())
return ParseResult::Failure;
auto power_res_pkg = opt_power_res_pkg.value();
auto name = NameString::parse(power_res_pkg);
if (!name.has_value())
return ParseResult::Failure;
if (power_res_pkg.size() < 1)
return ParseResult::Failure;
uint8_t system_level = power_res_pkg[0];
power_res_pkg = power_res_pkg.slice(1);
if (power_res_pkg.size() < 2)
return ParseResult::Failure;
uint16_t resource_order = BAN::little_endian_to_host<uint16_t>(*reinterpret_cast<const uint16_t*>(power_res_pkg.data()));
power_res_pkg = power_res_pkg.slice(2);
auto power_res = MUST(BAN::RefPtr<PowerResource>::create(name->path.back(), system_level, resource_order));
if (!Namespace::root_namespace()->add_named_object(context, name.value(), power_res))
return ParseResult::Failure;
#if AML_DEBUG_LEVEL >= 2
power_res->debug_print(0);
AML_DEBUG_PRINTLN("");
#endif
return power_res->enter_context_and_parse_term_list(context, name.value(), power_res_pkg);
}
virtual void debug_print(int indent) const override
{
AML_DEBUG_PRINT_INDENT(indent);
AML_DEBUG_PRINT("PowerResource {} (SystemLevel {}, ResourceOrder {})", name, system_level, resource_order);
}
};
}

View File

@@ -1,84 +0,0 @@
#pragma once
#include <BAN/Endianness.h>
#include <kernel/ACPI/AML/Bytes.h>
#include <kernel/ACPI/AML/ParseContext.h>
#include <kernel/ACPI/AML/Pkg.h>
#include <kernel/ACPI/AML/Scope.h>
namespace Kernel::ACPI::AML
{
struct Processor : public AML::Scope
{
uint8_t id;
uint32_t pblk_addr;
uint8_t pblk_len;
Processor(NameSeg name, uint8_t id, uint32_t pblk_addr, uint8_t pblk_len)
: Scope(Node::Type::Processor, name)
, id(id)
, pblk_addr(pblk_addr)
, pblk_len(pblk_len)
{}
static ParseResult parse(ParseContext& context)
{
ASSERT(context.aml_data.size() >= 2);
ASSERT(static_cast<AML::Byte>(context.aml_data[0]) == AML::Byte::ExtOpPrefix);
ASSERT(static_cast<AML::ExtOp>(context.aml_data[1]) == AML::ExtOp::ProcessorOp);
context.aml_data = context.aml_data.slice(2);
auto opt_processor_pkg = AML::parse_pkg(context.aml_data);
if (!opt_processor_pkg.has_value())
return ParseResult::Failure;
auto processor_pkg = opt_processor_pkg.value();
auto name = NameString::parse(processor_pkg);
if (!name.has_value())
return ParseResult::Failure;
if (processor_pkg.size() < 1)
return ParseResult::Failure;
uint8_t id = processor_pkg[0];
processor_pkg = processor_pkg.slice(1);
if (processor_pkg.size() < 4)
return ParseResult::Failure;
uint32_t pblk_addr = BAN::little_endian_to_host<uint32_t>(*reinterpret_cast<const uint32_t*>(processor_pkg.data()));
processor_pkg = processor_pkg.slice(4);
if (processor_pkg.size() < 1)
return ParseResult::Failure;
uint8_t pblk_len = processor_pkg[0];
processor_pkg = processor_pkg.slice(1);
auto processor = MUST(BAN::RefPtr<Processor>::create(name->path.back(), id, pblk_addr, pblk_len));
if (!Namespace::root_namespace()->add_named_object(context, name.value(), processor))
return ParseResult::Failure;
#if AML_DEBUG_LEVEL >= 2
processor->debug_print(0);
AML_DEBUG_PRINTLN("");
#endif
return processor->enter_context_and_parse_term_list(context, name.value(), processor_pkg);
}
virtual void debug_print(int indent) const override
{
AML_DEBUG_PRINT_INDENT(indent);
AML_DEBUG_PRINTLN("Processor {} (ID: {}, PBlkAddr: 0x{H}, PBlkLen: {}) {", name, id, pblk_addr, pblk_len);
Namespace::root_namespace()->for_each_child(scope,
[&](const auto&, const auto& child)
{
child->debug_print(indent + 1);
AML_DEBUG_PRINTLN("");
}
);
AML_DEBUG_PRINT_INDENT(indent);
AML_DEBUG_PRINT("}");
}
};
}

View File

@@ -1,155 +0,0 @@
#pragma once
#include <kernel/ACPI/AML/Bytes.h>
#include <kernel/ACPI/AML/Integer.h>
#include <kernel/ACPI/AML/Node.h>
#include <kernel/ACPI/AML/Names.h>
#include <kernel/ACPI/AML/String.h>
#include <kernel/ACPI/AML/ParseContext.h>
namespace Kernel::ACPI::AML
{
struct Reference : public AML::Node
{
BAN::RefPtr<AML::Node> node;
Reference(BAN::RefPtr<AML::Node> node)
: Node(AML::Node::Type::Reference)
, node(node)
{
ASSERT(node);
}
BAN::RefPtr<AML::Node> evaluate() override
{
return this;
}
static ParseResult parse(ParseContext& context)
{
ASSERT(context.aml_data.size() >= 1);
bool conditional = false;
switch (static_cast<AML::Byte>(context.aml_data[0]))
{
case AML::Byte::DerefOfOp:
return parse_dereference(context);
case AML::Byte::RefOfOp:
context.aml_data = context.aml_data.slice(1);
conditional = false;
break;
case AML::Byte::ExtOpPrefix:
ASSERT(static_cast<AML::ExtOp>(context.aml_data[1]) == AML::ExtOp::CondRefOfOp);
context.aml_data = context.aml_data.slice(2);
conditional = true;
break;
default:
ASSERT_NOT_REACHED();
}
BAN::RefPtr<AML::Node> object;
if (NameString::can_parse(context.aml_data))
{
auto name = NameString::parse(context.aml_data);
if (!name.has_value())
return ParseResult::Failure;
object = Namespace::root_namespace()->find_object(context.scope, name.value(), Namespace::FindMode::Normal);
}
else
{
auto parse_result = AML::parse_object(context);
if (!parse_result.success())
return ParseResult::Failure;
object = parse_result.node();
}
if (!conditional)
{
if (!object)
{
AML_ERROR("RefOf failed to resolve reference");
return ParseResult::Failure;
}
auto reference = MUST(BAN::RefPtr<Reference>::create(object));
#if AML_DEBUG_LEVEL >= 2
reference->debug_print(0);
AML_DEBUG_PRINTLN("");
#endif
return ParseResult(reference);
}
if (context.aml_data.size() >= 1 && context.aml_data[0] != 0x00)
{
auto target_result = AML::parse_object(context);
if (!target_result.success())
return ParseResult::Failure;
auto target_node = target_result.node();
if (!target_node)
{
AML_ERROR("CondRefOf failed to resolve target");
return ParseResult::Failure;
}
target_node->store(MUST(BAN::RefPtr<Reference>::create(object)));
}
#if AML_DEBUG_LEVEL >= 2
AML_DEBUG_PRINT("CondRefOf ");
if (object)
object->debug_print(0);
else
AML_DEBUG_PRINT("null");
AML_DEBUG_PRINTLN("");
#endif
auto return_value = object ? Integer::Constants::Ones : Integer::Constants::Zero;
return AML::ParseResult(return_value);
}
static ParseResult parse_dereference(ParseContext& context)
{
ASSERT(context.aml_data.size() >= 1);
ASSERT(static_cast<Byte>(context.aml_data[0]) == Byte::DerefOfOp);
context.aml_data = context.aml_data.slice(1);
if (context.aml_data.size() >= 1 && static_cast<AML::Byte>(context.aml_data[0]) == AML::Byte::StringPrefix)
{
auto string_result = AML::String::parse(context);
if (!string_result.success())
return ParseResult::Failure;
ASSERT(string_result.node());
auto string = static_cast<AML::String*>(string_result.node().ptr());
AML_TODO("DerefOf String ({})", string->string);
return ParseResult::Failure;
}
else
{
auto parse_result = AML::parse_object(context);
if (!parse_result.success())
return ParseResult::Failure;
auto object = parse_result.node();
if (!object || object->type != AML::Node::Type::Reference)
{
AML_TODO("DerefOf source is not a Reference, but a {}", object ? static_cast<uint8_t>(object->type) : 999);
return ParseResult::Failure;
}
#if AML_DEBUG_LEVEL >= 2
AML_DEBUG_PRINT("DerefOf ");
object->debug_print(0);
AML_DEBUG_PRINTLN("");
#endif
return ParseResult(static_cast<Reference*>(object.ptr())->node);
}
}
virtual void debug_print(int indent) const override
{
AML_DEBUG_PRINT_INDENT(indent);
AML_DEBUG_PRINTLN("Reference {");
node->debug_print(indent + 1);
AML_DEBUG_PRINT_INDENT(indent);
AML_DEBUG_PRINT("}");
}
};
}

View File

@@ -1,106 +0,0 @@
#pragma once
#include <kernel/ACPI/AML/NamedObject.h>
#include <kernel/ACPI/AML/Namespace.h>
#include <kernel/ACPI/AML/ParseContext.h>
namespace Kernel::ACPI::AML
{
struct OpRegion : public NamedObject
{
using RegionSpace = GAS::AddressSpaceID;
RegionSpace region_space;
uint64_t region_offset;
uint64_t region_length;
Kernel::Mutex mutex;
OpRegion(NameSeg name, RegionSpace region_space, uint64_t region_offset, uint64_t region_length)
: NamedObject(Node::Type::OpRegion, name)
, region_space(region_space)
, region_offset(region_offset)
, region_length(region_length)
{}
static ParseResult parse(AML::ParseContext& context)
{
ASSERT(context.aml_data.size() > 2);
ASSERT(static_cast<Byte>(context.aml_data[0]) == Byte::ExtOpPrefix);
ASSERT(static_cast<ExtOp>(context.aml_data[1]) == ExtOp::OpRegionOp);
context.aml_data = context.aml_data.slice(2);
auto name = NameString::parse(context.aml_data);
if (!name.has_value())
return ParseResult::Failure;
if (context.aml_data.size() < 1)
return ParseResult::Failure;
auto region_space = static_cast<RegionSpace>(context.aml_data[0]);
context.aml_data = context.aml_data.slice(1);
auto offset_result = AML::parse_object(context);
if (!offset_result.success())
return ParseResult::Failure;
auto offset = offset_result.node()->as_integer();
if (!offset.has_value())
{
AML_ERROR("OpRegion offset must be an integer");
return ParseResult::Failure;
}
auto length_result = AML::parse_object(context);
if (!length_result.success())
return ParseResult::Failure;
auto length = length_result.node()->as_integer();
if (!length.has_value())
{
AML_ERROR("OpRegion length must be an integer");
return ParseResult::Failure;
}
auto op_region = MUST(BAN::RefPtr<OpRegion>::create(
name->path.back(),
region_space,
offset.value(),
length.value()
));
if (!Namespace::root_namespace()->add_named_object(context, name.value(), op_region))
return ParseResult::Failure;
#if AML_DEBUG_LEVEL >= 2
op_region->debug_print(0);
AML_DEBUG_PRINTLN("");
#endif
return ParseResult::Success;
}
virtual void debug_print(int indent) const override
{
BAN::StringView region_space_name;
switch (region_space)
{
case RegionSpace::SystemMemory: region_space_name = "SystemMemory"sv; break;
case RegionSpace::SystemIO: region_space_name = "SystemIO"sv; break;
case RegionSpace::PCIConfig: region_space_name = "PCIConfig"sv; break;
case RegionSpace::EmbeddedController: region_space_name = "EmbeddedController"sv; break;
case RegionSpace::SMBus: region_space_name = "SMBus"sv; break;
case RegionSpace::SystemCMOS: region_space_name = "SystemCMOS"sv; break;
case RegionSpace::PCIBarTarget: region_space_name = "PCIBarTarget"sv; break;
case RegionSpace::IPMI: region_space_name = "IPMI"sv; break;
case RegionSpace::GeneralPurposeIO: region_space_name = "GeneralPurposeIO"sv; break;
case RegionSpace::GenericSerialBus: region_space_name = "GenericSerialBus"sv; break;
case RegionSpace::PlatformCommunicationChannel: region_space_name = "PlatformCommunicationChannel"sv; break;
default: region_space_name = "Unknown"sv; break;
}
AML_DEBUG_PRINT_INDENT(indent);
AML_DEBUG_PRINT("OperationRegion(");
name.debug_print();
AML_DEBUG_PRINT(", {}, 0x{H}, 0x{H})", region_space_name, region_offset, region_length);
}
};
}

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