Compare commits

..
53 Commits
Author SHA1 Message Date
Bananymous 95de7ad674 BuildSystem: Fix xbps port packaging 2026-08-26 00:39:06 +03:00
Bananymous 4495b81769 Kernel: Fix framebuffer bounds checks
running yes and pressing ctrl+c paniced the kernel :nekocatwoah:
2026-08-25 23:53:07 +03:00
Bananymous 999b1a073e Kernel: Add hack to not kernel panic when running vim 2026-08-25 23:52:49 +03:00
Bananymous 1433657697 4000th COMMIT: Add a package manager, xbps
Now you don't have to wait painstakingly long for ports to compile!
2026-08-25 23:51:27 +03:00
Bananymous 59077f0f72 Kernel: Allow pinning multiple memory regions
One port allocated memory page by page and did a big write on the final
multi-region buffer. Now we allow this!
2026-08-25 15:33:56 +03:00
Bananymous 645150039a BuildSystem: Add script to package all ports 2026-08-25 15:32:54 +03:00
Bananymous 8a5557f4ae BuildSystem: Cleanup port install script with packaging 2026-08-25 15:32:54 +03:00
Bananymous b20a1640b2 ports: Fix packaging of bunch of ports 2026-08-25 15:32:54 +03:00
Bananymous aca9f459ed ports: Fix compilation of bunch of ports 2026-08-25 15:32:54 +03:00
Bananymous ef469ab043 ports: Update python 3.13.3->3.14.7 2026-08-25 15:32:54 +03:00
Bananymous d2f4137894 ports: Add missing libXxf86vm port 2026-08-25 15:32:54 +03:00
Bananymous 94b2105cd6 LibC: Add duplocale stub 2026-08-25 15:32:54 +03:00
Bananymous 1d618ea39d ports: Remove circular harfbuzz/freetype/cairo dependency
I don't even know why I was rebuilding cairo and freetype can be just
configured with dynamic harfbuzz
2026-08-25 15:32:54 +03:00
Bananymous c6694f6a28 ports: Create files in /etc/profile.d instead of modifying shellrc 2026-08-25 03:52:52 +03:00
Bananymous 631fec7c4d init/Shell: init now spawns a login shell which sources /etc/profile 2026-08-25 03:52:52 +03:00
Bananymous 68c741d54d BuildSystem: Allow packaging ports into xbps packages
if you build a package, you can build a port with
`PACKAGE=1 ./build.sh`
2026-08-25 03:52:52 +03:00
Bananymous f9487b63b0 ports: Add gimp port 2026-08-24 21:53:03 +03:00
Bananymous 1a3dc080e6 ports: Add poppler port 2026-08-24 21:53:03 +03:00
Bananymous 1a227504e2 ports: Add AppStream port 2026-08-24 21:53:03 +03:00
Bananymous 69d8927c12 ports: Add libfyaml port 2026-08-24 21:53:03 +03:00
Bananymous 9b5fd077d2 ports: Add mypaint port 2026-08-24 21:53:03 +03:00
Bananymous 889415b22a ports: Add gexiv2 port 2026-08-24 21:53:00 +03:00
Bananymous da94e21dbe ports: Add gegl port 2026-08-24 21:53:00 +03:00
Bananymous 501783e9ae ports: Add babl port 2026-08-24 21:53:00 +03:00
Bananymous f1f2f2aa25 ports: Add lcms2 port 2026-08-24 21:53:00 +03:00
Bananymous f2d08a85a5 porst: Add json-glib port 2026-08-24 21:52:55 +03:00
Bananymous 44189938d7 ports: Add glib-networking port 2026-08-24 21:01:41 +03:00
Bananymous c6536260c3 ports: Add librsvg port
We use version 2.40.21 as that is the last version that does not need a
rust toolchain
2026-08-24 20:58:21 +03:00
Bananymous d22ff2cbc4 ports: Add libcroco port 2026-08-24 20:58:09 +03:00
Bananymous 48d8902e98 ports/glib: Add init script to compile schemas 2026-08-24 20:57:27 +03:00
Bananymous b4349511f4 ports/gdk-pixbuf: Add init script to update pixbuf loader cache
If the loader cache is not updated, pixbuf fails to load anything :)
2026-08-24 20:56:25 +03:00
Bananymous b42b16add7 ports/sdl2-compat: Use -f when linking pc files 2026-08-24 20:55:30 +03:00
Bananymous 8fd18eef4d ports/harfbuzz: Don't compile cairo if its not compiled 2026-08-24 20:54:12 +03:00
Bananymous 1e7afa11d7 ports/ffmpeg: Don't compile static libraries 2026-08-24 20:53:11 +03:00
Bananymous 1cfcd76588 init: Run all scripts from /etc/init.d at startup 2026-08-24 20:37:45 +03:00
Bananymous 179f76114b init: Generate /etc/machine-id if it doesn't exist 2026-08-24 19:18:31 +03:00
Bananymous 65e559596b LibC: Add sys/random.h with getrandom 2026-08-24 19:16:37 +03:00
Bananymous 98c11ee33b Kernel: Support non-null-terminated paths in sockaddr_un 2026-08-24 17:37:34 +03:00
Bananymous 2f4fec9ab9 ports: Update shared-mime-info 2.4->2.5.1
2.4 failed to build spec on my machine and did not support disabling it
2026-08-24 03:55:19 +03:00
Bananymous a38e29c59d audio: Passing number to audio now generates a sinwave at that freq 2026-08-24 01:44:37 +03:00
Bananymous c6a435ed36 LibAudio: Allow generating sine waves 2026-08-24 01:44:04 +03:00
Bananymous 2e22ebf0b5 LibC: Cleanup TSC clock_gettime control flow 2026-08-24 01:37:05 +03:00
Bananymous cd6269d406 Kernel: Add very simple BGA driver
Only thing this is currently helpful is qemu when booting with -kernel
flag as that does not provide framebuffer info in multiboot headers
2026-08-24 01:35:06 +03:00
Bananymous 9a9a4fe8c0 Kernel: Don't allow creating zero sized shm objects 2026-08-23 15:51:01 +03:00
Bananymous f163dacce5 Kernel: Safely fail allocating zero sized BAR regions
Our device discovery thinks vmware's audio device is AC97 and allocating
one of the BARs leads to zero sized allocation -> panic from page table
as it tries to allocate 0 pages. Now we gracefully handle these regions
and fail to allocate the BAR
2026-08-23 15:44:12 +03:00
Bananymous 7e7ca3d929 Kernel: Add support for iHDA Selectors
Again this has not been tested as I don't have any hardware with
Selector on an usable output path. My T61 does have Selectors but they
are not used for the internal speakers. The T61 does have mixers though
so they seem to be working fine!
2026-08-23 15:20:41 +03:00
Bananymous c00f37b930 Kernel: Evaluate and validate PS/2 _CRS
Don't assume it is a buffer. On bochs it is a method :D
2026-08-23 15:08:01 +03:00
Bananymous ace5edfda2 Kernel: "Recognize" USB wireless controllers
Apparently USB device descriptor is allowed to have class
WirelessController if and only if it is a bluetooth controller(?) :D Now
we print ENOTSUP instead of EINVAL when encountering these
2026-08-23 14:21:42 +03:00
Bananymous 17813f3fcf Kernel: Store SchedulerThreadNode directly in Thread
Having the pointer indirection was weird and forced allocations when
adding/binding a new thread :P
2026-08-23 14:21:27 +03:00
Bananymous cce6e417df Kernel: Remove obsolete SpinLockGuardAsMutex declaration 2026-08-23 14:21:27 +03:00
Bananymous 8eb572d038 Kernel: Add reads/write to System CMOS to AML 2026-08-23 14:21:27 +03:00
Bananymous cee65bd68e Kernel: Fix ACPI Embedded Controllers
I was polling the wrong bit in read/write which lead to dead locks on
machines that used embedded controllers :D

Also EC GPEs are now only initialized AFTER the ACPI post initialization
is done. This fixes some issues where _GPE body was not fully available
yet
2026-08-23 14:21:27 +03:00
Bananymous 74d7a48c4b Kernel: Make TTY write lock a spinlock
I don't really like this but its needed with the current architecture to
allow printing while interrupts are disabled. I was hitting a dead lock
on few real machines
2026-08-23 14:21:27 +03:00
139 changed files with 2353 additions and 706 deletions
+22 -10
View File
@@ -9,7 +9,7 @@ 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) 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. ![screenshot from qemu running banan-os](assets/banan-os.png)
### Features ### Features
@@ -18,6 +18,8 @@ If you want to try out DOOM, you should first enter the GUI environment using th
- [x] SMP (multiprocessing) - [x] SMP (multiprocessing)
- [x] Linear framebuffer (VESA and GOP) - [x] Linear framebuffer (VESA and GOP)
- [x] Network stack - [x] Network stack
- [x] USB stack
- [x] Audio support
- [x] ELF executable loading - [x] ELF executable loading
- [x] AML interpreter (partial) - [x] AML interpreter (partial)
- [x] Basic graphical environment - [x] Basic graphical environment
@@ -27,16 +29,14 @@ If you want to try out DOOM, you should first enter the GUI environment using th
- [ ] Some nice apps - [ ] Some nice apps
- [x] ELF dynamic linking - [x] ELF dynamic linking
- [x] copy-on-write memory - [x] copy-on-write memory
- [x] file mappings
- [ ] anonymous mappings
#### Drivers #### Drivers
- [x] NVMe disks - [x] NVMe disks
- [x] ATA (IDE, SATA) disks - [x] ATA (IDE, SATA) disks
- [x] E1000 and E1000E NICs - [x] E1000 and E1000E NICs
- [x] RTL8111/8168/8211/8411 NICs - [x] RTL8111/8168/8211/8411 NICs
- [x] PS2 keyboard (all scancode sets) - [x] AC97 and iHDA audio cards
- [x] PS2 mouse - [x] PS2 keyboard and mouse
- [x] USB - [x] USB
- [x] xHCI - [x] xHCI
- [ ] EHCI - [ ] EHCI
@@ -46,7 +46,8 @@ If you want to try out DOOM, you should first enter the GUI environment using th
- [x] Mouse - [x] Mouse
- [x] Mass storage - [x] Mass storage
- [x] Hubs - [x] Hubs
- [ ] ... - [ ] Network
- [ ] Audio
- [ ] virtio devices (network, storage) - [ ] virtio devices (network, storage)
#### Network #### Network
@@ -54,7 +55,7 @@ If you want to try out DOOM, you should first enter the GUI environment using th
- [x] ICMP - [x] ICMP
- [x] IPv4 - [x] IPv4
- [x] UDP - [x] UDP
- [x] TCP (partial and buggy) - [x] TCP
- [x] Unix domain sockets - [x] Unix domain sockets
- [ ] SSL - [ ] SSL
@@ -65,7 +66,6 @@ If you want to try out DOOM, you should first enter the GUI environment using th
- [x] Dev - [x] Dev
- [x] Ram - [x] Ram
- [x] Proc - [x] Proc
- [ ] Sys
- [ ] 9P - [ ] 9P
#### Bootloader support #### Bootloader support
@@ -73,8 +73,6 @@ If you want to try out DOOM, you should first enter the GUI environment using th
- [x] Custom BIOS bootloader - [x] Custom BIOS bootloader
- [ ] Custom UEFI bootloader - [ ] Custom UEFI bootloader
![screenshot from qemu running banan-os](assets/banan-os.png)
## Code structure ## Code structure
Each major component and library has its own subdirectory (kernel, userspace, libc, ...). Each directory contains directory *include*, which has **all** of the header files of the component. Every header is included by its absolute path. Each major component and library has its own subdirectory (kernel, userspace, libc, ...). Each directory contains directory *include*, which has **all** of the header files of the component. Every header is included by its absolute path.
@@ -125,8 +123,22 @@ If you have corrupted your disk image or want to create new one, you can either
./bos image-full ./bos image-full
``` ```
To test on real hardware, I have a script to generate a compressed ISO. The ISO can be copied directly to an USB drive with for example `dd`. The file is created at build/banan-os.iso and can be generated with
```sh
./bos iso
```
I have also created shell completion script for zsh. You can either copy the file in _script/shell-completion/zsh/\_bos_ to _/usr/share/zsh/site-functions/_ or add the _script/shell-completion/zsh_ to your fpath in _.zshrc_. I have also created shell completion script for zsh. You can either copy the file in _script/shell-completion/zsh/\_bos_ to _/usr/share/zsh/site-functions/_ or add the _script/shell-completion/zsh_ to your fpath in _.zshrc_.
### Package Manager
banan-os uses xbps as its package manager for ports. All upstream ports are packaged into xbps packages hosted on a [repository on my server](https://packages.bananymous.com/banan-os). You can manage sysroot's xbps packages with `./bos` wrapper. You can use `xbps-install`, `xbps-remove` and `xbps-query` with repository and sysroot set to the correct values. For example to install xbps that can be used inside banan-os you can use
```sh
./bos xbps-install -S xbps
```
For xbps usage see [their documentation](https://docs.voidlinux.org/xbps/index.html).
## Contributing ## Contributing
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:[email protected]), [discord](https://discord.gg/ehjGySwYdK)). 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:[email protected]), [discord](https://discord.gg/ehjGySwYdK)).
+1
View File
@@ -41,6 +41,7 @@ set(KERNEL_SOURCES
kernel/FS/USTARModule.cpp kernel/FS/USTARModule.cpp
kernel/FS/VirtualFileSystem.cpp kernel/FS/VirtualFileSystem.cpp
kernel/GDT.cpp kernel/GDT.cpp
kernel/Graphics/BGA.cpp
kernel/IDT.cpp kernel/IDT.cpp
kernel/Input/InputDevice.cpp kernel/Input/InputDevice.cpp
kernel/Input/PS2/Controller.cpp kernel/Input/PS2/Controller.cpp
+1
View File
@@ -54,6 +54,7 @@ namespace Kernel::ACPI
BAN::ErrorOr<void> initialize_embedded_controller(const AML::Scope& embedded_controller); BAN::ErrorOr<void> initialize_embedded_controller(const AML::Scope& embedded_controller);
BAN::ErrorOr<void> initialize_embedded_controllers(); BAN::ErrorOr<void> initialize_embedded_controllers();
void initialize_embedded_controller_gpes();
BAN::Optional<GAS> find_gpe_block(size_t index); BAN::Optional<GAS> find_gpe_block(size_t index);
bool enable_gpe(uint8_t gpe); bool enable_gpe(uint8_t gpe);
@@ -14,7 +14,7 @@ namespace Kernel::ACPI
class EmbeddedController class EmbeddedController
{ {
public: public:
static BAN::ErrorOr<BAN::UniqPtr<EmbeddedController>> create(AML::Scope&& scope, uint16_t command_port, uint16_t data_port, BAN::Optional<uint8_t> gpe); static BAN::ErrorOr<BAN::UniqPtr<EmbeddedController>> create(AML::Scope&& scope, uint16_t command_port, uint16_t data_port);
~EmbeddedController(); ~EmbeddedController();
BAN::ErrorOr<uint8_t> read_byte(uint8_t offset); BAN::ErrorOr<uint8_t> read_byte(uint8_t offset);
@@ -22,21 +22,21 @@ namespace Kernel::ACPI
const AML::Scope& scope() const { return m_scope; } const AML::Scope& scope() const { return m_scope; }
static void handle_gpe_trampoline(void*);
private: private:
EmbeddedController(AML::Scope&& scope, uint16_t command_port, uint16_t data_port, bool has_gpe) EmbeddedController(AML::Scope&& scope, uint16_t command_port, uint16_t data_port)
: m_scope(BAN::move(scope)) : m_scope(BAN::move(scope))
, m_command_port(command_port) , m_command_port(command_port)
, m_data_port(data_port) , m_data_port(data_port)
, m_has_gpe(has_gpe)
{ } { }
private: private:
void wait_status_bit(uint8_t bit, uint8_t value); void wait_status_bit(uint8_t mask, bool set);
uint8_t read_one(uint16_t port); uint8_t read_one(uint16_t port);
void write_one(uint16_t port, uint8_t value); void write_one(uint16_t port, uint8_t value);
static void handle_gpe_wrapper(void*);
void handle_gpe(); void handle_gpe();
BAN::ErrorOr<void> call_query_method(uint8_t notification); BAN::ErrorOr<void> call_query_method(uint8_t notification);
@@ -57,7 +57,6 @@ namespace Kernel::ACPI
const AML::Scope m_scope; const AML::Scope m_scope;
const uint16_t m_command_port; const uint16_t m_command_port;
const uint16_t m_data_port; const uint16_t m_data_port;
const bool m_has_gpe;
Mutex m_mutex; Mutex m_mutex;
ThreadBlocker m_thread_blocker; ThreadBlocker m_thread_blocker;
@@ -6,15 +6,22 @@
namespace Kernel namespace Kernel
{ {
class BGAController;
class FramebufferDevice : public CharacterDevice class FramebufferDevice : public CharacterDevice
{ {
public: public:
static BAN::ErrorOr<BAN::RefPtr<FramebufferDevice>> create(paddr_t paddr, uint32_t width, uint32_t height, uint32_t pitch, uint8_t bpp);
static BAN::ErrorOr<BAN::RefPtr<FramebufferDevice>> create(BAN::RefPtr<BGAController>);
static BAN::ErrorOr<BAN::RefPtr<FramebufferDevice>> create_from_boot_framebuffer(); static BAN::ErrorOr<BAN::RefPtr<FramebufferDevice>> create_from_boot_framebuffer();
static BAN::RefPtr<FramebufferDevice> boot_framebuffer(); static BAN::RefPtr<FramebufferDevice> boot_framebuffer();
~FramebufferDevice(); ~FramebufferDevice();
uint32_t width() const { return m_width; } uint32_t width() const { return m_width; }
uint32_t height() const { return m_height; } uint32_t height() const { return m_height; }
uint8_t bpp() const { return m_bpp; }
BAN::ErrorOr<void> set_bga_controller(BAN::RefPtr<BGAController>);
uint32_t get_pixel(uint32_t x, uint32_t y) const; uint32_t get_pixel(uint32_t x, uint32_t y) const;
void set_pixel(uint32_t x, uint32_t y, uint32_t rgb); void set_pixel(uint32_t x, uint32_t y, uint32_t rgb);
@@ -51,13 +58,15 @@ namespace Kernel
const BAN::String m_name; const BAN::String m_name;
vaddr_t m_video_memory_vaddr { 0 }; vaddr_t m_video_memory_vaddr { 0 };
const paddr_t m_video_memory_paddr; paddr_t m_video_memory_paddr { 0 };
const uint32_t m_width;
const uint32_t m_height; uint32_t m_width { 0 };
const uint32_t m_pitch; uint32_t m_height { 0 };
const uint8_t m_bpp; uint32_t m_pitch { 0 };
uint8_t m_bpp { 0 };
BAN::UniqPtr<VirtualRange> m_video_buffer; BAN::UniqPtr<VirtualRange> m_video_buffer;
BAN::RefPtr<BGAController> m_bga_controller;
friend class FramebufferMemoryRegion; friend class FramebufferMemoryRegion;
}; };
+37
View File
@@ -0,0 +1,37 @@
#pragma once
#include <BAN/RefPtr.h>
#include <kernel/Lock/SpinLock.h>
#include <kernel/PCI.h>
#include <sys/framebuffer.h>
namespace Kernel
{
class BGAController : public BAN::RefCounted<BGAController>
{
public:
static BAN::ErrorOr<BAN::RefPtr<BGAController>> create(PCI::Device&);
fb_fix_info get_fb_fix_info() const;
fb_var_info get_fb_var_info() const;
BAN::ErrorOr<void> set_fb_var_info(const fb_var_info&);
private:
BGAController(PCI::Device&);
BAN::ErrorOr<void> initialize();
void write_reg(uint16_t reg, uint16_t value);
uint16_t read_reg(uint16_t reg);
private:
mutable RecursiveSpinLock m_lock;
PCI::Device& m_pci_device;
BAN::UniqPtr<PCI::BarRegion> m_lfb_bar;
fb_fix_info m_fix_info {};
fb_var_info m_var_info {};
};
}
-4
View File
@@ -61,9 +61,6 @@ namespace Kernel
uint32_t m_lock_depth { 0 }; uint32_t m_lock_depth { 0 };
}; };
template<typename Lock>
class SpinLockGuardAsMutex;
template<typename Lock> template<typename Lock>
class SpinLockGuard class SpinLockGuard
{ {
@@ -85,7 +82,6 @@ namespace Kernel
private: private:
Lock& m_lock; Lock& m_lock;
InterruptState m_state; InterruptState m_state;
friend class SpinLockGuardAsMutex<Lock>;
}; };
} }
+1 -1
View File
@@ -286,7 +286,7 @@ namespace Kernel
BAN::ErrorOr<FileParent> find_parent_file(int fd, const char* path, int flags) const; BAN::ErrorOr<FileParent> find_parent_file(int fd, const char* path, int flags) const;
BAN::ErrorOr<VirtualFileSystem::File> find_relative_parent(int fd, const char* path) const; BAN::ErrorOr<VirtualFileSystem::File> find_relative_parent(int fd, const char* path) const;
BAN::ErrorOr<MemoryRegion*> validate_and_pin_pointer_access(const void*, size_t, bool needs_write); BAN::ErrorOr<void> validate_and_pin_pointer_access(const void*, size_t, bool needs_write, BAN::Vector<MemoryRegion*>&);
uint64_t signal_pending_mask() const uint64_t signal_pending_mask() const
{ {
+2 -3
View File
@@ -22,7 +22,6 @@ namespace Kernel
class GDT; class GDT;
class IDT; class IDT;
class Scheduler; class Scheduler;
class SchedulerThreadNode;
class Thread; class Thread;
#if ARCH(x86_64) || ARCH(i686) #if ARCH(x86_64) || ARCH(i686)
@@ -54,8 +53,8 @@ namespace Kernel
union union
{ {
TLBEntry flush_tlb; TLBEntry flush_tlb;
SchedulerThreadNode* new_thread; Thread* new_thread;
SchedulerThreadNode* unblock_thread; Thread* unblock_thread;
bool dummy; bool dummy;
}; };
}; };
+2 -6
View File
@@ -41,9 +41,8 @@ namespace Kernel
void on_timer_interrupt(); void on_timer_interrupt();
void on_yield(YieldRegisters*); void on_yield(YieldRegisters*);
static BAN::ErrorOr<void> bind_thread_to_processor(Thread*, ProcessorID); static void bind_thread_to_processor(Thread*, ProcessorID);
// if thread is already bound, this will never fail void add_thread(Thread*);
BAN::ErrorOr<void> add_thread(Thread*);
void block_current_thread(ThreadBlocker* thread_blocker, uint64_t wake_time_ns, BaseMutex* mutex); void block_current_thread(ThreadBlocker* thread_blocker, uint64_t wake_time_ns, BaseMutex* mutex);
void unblock_thread(Thread*); void unblock_thread(Thread*);
@@ -68,9 +67,6 @@ namespace Kernel
class ProcessorID find_least_loaded_processor() const; class ProcessorID find_least_loaded_processor() const;
void add_thread(SchedulerThreadNode*);
void unblock_thread(SchedulerThreadNode*);
private: private:
SchedulerQueue m_run_list; SchedulerQueue m_run_list;
SchedulerHeap m_block_list; SchedulerHeap m_block_list;
+4 -2
View File
@@ -53,6 +53,8 @@ namespace Kernel
virtual bool master_has_closed() const { return false; } virtual bool master_has_closed() const { return false; }
virtual bool is_vtty() const { return false; }
protected: protected:
TTY(termios termios, mode_t mode, uid_t uid, gid_t gid); TTY(termios termios, mode_t mode, uid_t uid, gid_t gid);
@@ -100,9 +102,9 @@ namespace Kernel
termios m_termios; termios m_termios;
protected: protected:
Mutex m_mutex; Mutex m_input_mutex;
Mutex m_write_lock; RecursiveSpinLock m_write_lock;
ThreadBlocker m_write_blocker; ThreadBlocker m_write_blocker;
}; };
@@ -21,6 +21,9 @@ namespace Kernel
void clear() override; void clear() override;
bool is_vtty() const override { return true; }
BAN::ErrorOr<void> set_terminal_driver(BAN::RefPtr<TerminalDriver>);
protected: protected:
BAN::StringView name() const override { return m_name; } BAN::StringView name() const override { return m_name; }
bool putchar_impl(uint8_t ch) override; bool putchar_impl(uint8_t ch) override;
+2 -1
View File
@@ -7,6 +7,7 @@
#include <kernel/InterruptStack.h> #include <kernel/InterruptStack.h>
#include <kernel/Lock/Mutex.h> #include <kernel/Lock/Mutex.h>
#include <kernel/Memory/VirtualRange.h> #include <kernel/Memory/VirtualRange.h>
#include <kernel/SchedulerThreadNode.h>
#include <LibELF/AuxiliaryVector.h> #include <LibELF/AuxiliaryVector.h>
@@ -192,7 +193,7 @@ namespace Kernel
vaddr_t m_fsbase { 0 }; vaddr_t m_fsbase { 0 };
vaddr_t m_gsbase { 0 }; vaddr_t m_gsbase { 0 };
SchedulerThreadNode* m_scheduler_node { nullptr }; SchedulerThreadNode m_scheduler_node;
YieldRegisters m_yield_registers { }; YieldRegisters m_yield_registers { };
+1
View File
@@ -30,6 +30,7 @@ namespace Kernel
Hub = 0x09, Hub = 0x09,
BillboardDeviceClass = 0x11, BillboardDeviceClass = 0x11,
DiagnosticDevice = 0xDC, DiagnosticDevice = 0xDC,
WirelessController = 0xE0,
Miscellaneous = 0xEF, Miscellaneous = 0xEF,
VendorSpecific = 0xFF, VendorSpecific = 0xFF,
}; };
+64 -55
View File
@@ -784,26 +784,6 @@ acpi_release_global_lock:
BAN::ErrorOr<void> ACPI::initialize_embedded_controller(const AML::Scope& embedded_controller) BAN::ErrorOr<void> ACPI::initialize_embedded_controller(const AML::Scope& embedded_controller)
{ {
BAN::Optional<uint8_t> gpe_int;
do {
auto [gpe_path, gpe_obj] = TRY(m_namespace->find_named_object(embedded_controller, TRY(AML::NameString::from_string("_GPE"_sv)), true));
if (gpe_obj == nullptr)
{
dwarnln("EC {} does not have _GPE", embedded_controller);
break;
}
auto gpe = TRY(AML::evaluate_node(gpe_path, gpe_obj->node));
if (gpe.type == AML::Node::Type::Package)
{
dwarnln("TODO: EC {} has package _GPE");
break;
}
gpe_int = TRY(AML::convert_node(BAN::move(gpe), AML::ConvInteger, -1)).as.integer.value;
} while (false);
auto [crs_path, crs_obj] = TRY(m_namespace->find_named_object(embedded_controller, TRY(AML::NameString::from_string("_CRS"_sv)), true)); auto [crs_path, crs_obj] = TRY(m_namespace->find_named_object(embedded_controller, TRY(AML::NameString::from_string("_CRS"_sv)), true));
if (crs_obj == nullptr) if (crs_obj == nullptr)
{ {
@@ -857,7 +837,7 @@ acpi_release_global_lock:
const auto data_port = TRY(extract_io_port(crs_buffer)); const auto data_port = TRY(extract_io_port(crs_buffer));
const auto command_port = TRY(extract_io_port(crs_buffer)); const auto command_port = TRY(extract_io_port(crs_buffer));
TRY(m_embedded_controllers.push_back(TRY(EmbeddedController::create(TRY(embedded_controller.copy()), command_port, data_port, gpe_int)))); TRY(m_embedded_controllers.push_back(TRY(EmbeddedController::create(TRY(embedded_controller.copy()), command_port, data_port))));
return {}; return {};
} }
@@ -877,6 +857,33 @@ acpi_release_global_lock:
return {}; return {};
} }
void ACPI::initialize_embedded_controller_gpes()
{
const auto initialize_gpe = [this](EmbeddedController& embedded_controller) -> BAN::ErrorOr<void> {
auto [gpe_path, gpe_obj] = TRY(m_namespace->find_named_object(embedded_controller.scope(), TRY(AML::NameString::from_string("_GPE"_sv)), true));
if (gpe_obj == nullptr)
{
dprintln("EC {} does not have _GPE", embedded_controller.scope());
return {};
}
auto gpe = TRY(AML::evaluate_node(gpe_path, gpe_obj->node));
if (gpe.type == AML::Node::Type::Package)
{
dwarnln("TODO: EC {} has package _GPE");
return {};
}
const auto gpe_int = TRY(AML::convert_node(BAN::move(gpe), AML::ConvInteger, -1)).as.integer.value;
TRY(register_gpe_handler(gpe_int, &EmbeddedController::handle_gpe_trampoline, &embedded_controller));
return {};
};
for (auto& embedded_controller : m_embedded_controllers)
(void)initialize_gpe(*embedded_controller);
}
BAN::ErrorOr<void> ACPI::register_gpe_handler(uint8_t gpe, void (*callback)(void*), void* argument) BAN::ErrorOr<void> ACPI::register_gpe_handler(uint8_t gpe, void (*callback)(void*), void* argument)
{ {
if (m_gpe_methods[gpe].method) if (m_gpe_methods[gpe].method)
@@ -996,42 +1003,12 @@ acpi_release_global_lock:
// FIXME: add support for GPE blocks inside the ACPI namespace // FIXME: add support for GPE blocks inside the ACPI namespace
} }
if (auto ret = initialize_embedded_controllers(); ret.is_error())
dwarnln("Failed to initialize Embedded Controllers: {}", ret.error());
if (auto ret = m_namespace->post_load_initialize(); ret.is_error())
dwarnln("Failed to initialize ACPI namespace: {}", ret.error());
auto [pic_path, pic_obj] = TRY(m_namespace->find_named_object({}, TRY(AML::NameString::from_string("\\_PIC"_sv))));
if (pic_obj && pic_obj->node.type == AML::Node::Type::Method)
{
auto& pic_node = pic_obj->node;
if (pic_node.as.method.arg_count != 1)
{
dwarnln("Method \\_PIC has {} arguments, expected 1", pic_node.as.method.arg_count);
return BAN::Error::from_errno(EINVAL);
}
AML::Reference arg_ref;
arg_ref.node.type = AML::Node::Type::Integer;
arg_ref.node.as.integer.value = InterruptController::get().is_using_apic() ? 1 : 0;
arg_ref.ref_count = 2;
BAN::Array<AML::Reference*, 7> arguments(nullptr);
arguments[0] = &arg_ref; // method call should not delete argument
TRY(AML::method_call(pic_path, pic_node, BAN::move(arguments)));
}
dprintln("Evaluated \\_PIC({})", InterruptController::get().is_using_apic() ? 1 : 0);
uint8_t irq = fadt().sci_int; uint8_t irq = fadt().sci_int;
if (auto ret = InterruptController::get().reserve_irq(irq); ret.is_error()) if (auto ret = InterruptController::get().reserve_irq(irq); ret.is_error())
dwarnln("Could not enable ACPI interrupt: {}", ret.error()); dwarnln("Could not enable ACPI interrupt: {}", ret.error());
else else
{ {
auto hex_sv_to_int = const auto hex_sv_to_int = [](BAN::StringView sv) -> BAN::Optional<uint32_t> {
[](BAN::StringView sv) -> BAN::Optional<uint32_t>
{
uint32_t ret = 0; uint32_t ret = 0;
for (char c : sv) for (char c : sv)
{ {
@@ -1092,11 +1069,43 @@ acpi_release_global_lock:
if (auto thread_or_error = Thread::create_kernel([](void*) { get().acpi_event_task(); }, nullptr); thread_or_error.is_error()) if (auto thread_or_error = Thread::create_kernel([](void*) { get().acpi_event_task(); }, nullptr); thread_or_error.is_error())
dwarnln("Failed to create ACPI thread, power button will not work: {}", thread_or_error.error()); dwarnln("Failed to create ACPI thread, power button will not work: {}", thread_or_error.error());
else if (auto ret = Processor::scheduler().add_thread(thread_or_error.value()); ret.is_error()) else
dwarnln("Failed to create ACPI thread, power button will not work: {}", ret.error()); {
Processor::scheduler().add_thread(thread_or_error.value());
dprintln("Initialized ACPI interrupts");
}
} }
dprintln("Initialized ACPI interrupts"); if (auto ret = initialize_embedded_controllers(); ret.is_error())
dwarnln("Failed to initialize Embedded Controllers: {}", ret.error());
if (auto ret = m_namespace->post_load_initialize(); ret.is_error())
dwarnln("Failed to initialize ACPI namespace: {}", ret.error());
// NOTE: We cannot initialize EC GPEs before the post init is done, but post init does need ECs initialized
initialize_embedded_controller_gpes();
auto [pic_path, pic_obj] = TRY(m_namespace->find_named_object({}, TRY(AML::NameString::from_string("\\_PIC"_sv))));
if (pic_obj && pic_obj->node.type == AML::Node::Type::Method)
{
auto& pic_node = pic_obj->node;
if (pic_node.as.method.arg_count != 1)
{
dwarnln("Method \\_PIC has {} arguments, expected 1", pic_node.as.method.arg_count);
return BAN::Error::from_errno(EINVAL);
}
AML::Reference arg_ref;
arg_ref.node.type = AML::Node::Type::Integer;
arg_ref.node.as.integer.value = InterruptController::get().is_using_apic() ? 1 : 0;
arg_ref.ref_count = 2;
BAN::Array<AML::Reference*, 7> arguments(nullptr);
arguments[0] = &arg_ref; // method call should not delete argument
TRY(AML::method_call(pic_path, pic_node, BAN::move(arguments)));
dprintln("Evaluated \\_PIC({})", InterruptController::get().is_using_apic() ? 1 : 0);
}
if (InterruptController::get().is_using_apic()) if (InterruptController::get().is_using_apic())
{ {
+33 -2
View File
@@ -494,8 +494,23 @@ namespace Kernel::ACPI::AML
return TRY(embedded_controller->read_byte(offset)); return TRY(embedded_controller->read_byte(offset));
} }
case GAS::AddressSpaceID::SMBus:
case GAS::AddressSpaceID::SystemCMOS: case GAS::AddressSpaceID::SystemCMOS:
if (byte_offset >= 64)
{
dwarnln("CMOS read from offset 0x{H}", byte_offset);
return BAN::Error::from_errno(ENOTSUP);
}
switch (access_size)
{
case 1:
IO::outb(0x70, offset);
return IO::inb(0x71);
default:
dwarnln("{} byte read from CMOS offset {2H}", access_size, byte_offset);
return BAN::Error::from_errno(EINVAL);
}
ASSERT_NOT_REACHED();
case GAS::AddressSpaceID::SMBus:
case GAS::AddressSpaceID::PCIBarTarget: case GAS::AddressSpaceID::PCIBarTarget:
case GAS::AddressSpaceID::IPMI: case GAS::AddressSpaceID::IPMI:
case GAS::AddressSpaceID::GeneralPurposeIO: case GAS::AddressSpaceID::GeneralPurposeIO:
@@ -581,8 +596,24 @@ namespace Kernel::ACPI::AML
TRY(embedded_controller->write_byte(offset, value)); TRY(embedded_controller->write_byte(offset, value));
return {}; return {};
} }
case GAS::AddressSpaceID::SMBus:
case GAS::AddressSpaceID::SystemCMOS: case GAS::AddressSpaceID::SystemCMOS:
if (byte_offset >= 64)
{
dwarnln("CMOS write to offset 0x{H}", byte_offset);
return BAN::Error::from_errno(ENOTSUP);
}
switch (access_size)
{
case 1:
IO::outb(0x70, offset);
IO::outb(0x71, value);
break;
default:
dwarnln("{} byte write to CMOS offset {2H}", access_size, byte_offset);
return BAN::Error::from_errno(EINVAL);
}
return {};
case GAS::AddressSpaceID::SMBus:
case GAS::AddressSpaceID::PCIBarTarget: case GAS::AddressSpaceID::PCIBarTarget:
case GAS::AddressSpaceID::IPMI: case GAS::AddressSpaceID::IPMI:
case GAS::AddressSpaceID::GeneralPurposeIO: case GAS::AddressSpaceID::GeneralPurposeIO:
+12 -28
View File
@@ -30,28 +30,18 @@ namespace Kernel::ACPI
CMD_QUERY = 0x84, CMD_QUERY = 0x84,
}; };
BAN::ErrorOr<BAN::UniqPtr<EmbeddedController>> EmbeddedController::create(AML::Scope&& scope, uint16_t command_port, uint16_t data_port, BAN::Optional<uint8_t> gpe) BAN::ErrorOr<BAN::UniqPtr<EmbeddedController>> EmbeddedController::create(AML::Scope&& scope, uint16_t command_port, uint16_t data_port)
{ {
auto* embedded_controller_ptr = new EmbeddedController(BAN::move(scope), command_port, data_port, gpe.has_value()); auto* embedded_controller_ptr = new EmbeddedController(BAN::move(scope), command_port, data_port);
if (embedded_controller_ptr == nullptr) if (embedded_controller_ptr == nullptr)
return BAN::Error::from_errno(ENOMEM); return BAN::Error::from_errno(ENOMEM);
auto* thread = TRY(Thread::create_kernel([](void* ec) { static_cast<EmbeddedController*>(ec)->thread_task(); }, embedded_controller_ptr)); auto* thread = TRY(Thread::create_kernel([](void* ec) { static_cast<EmbeddedController*>(ec)->thread_task(); }, embedded_controller_ptr));
TRY(Processor::scheduler().add_thread(thread)); Processor::scheduler().add_thread(thread);
auto embedded_controller = BAN::UniqPtr<EmbeddedController>::adopt(embedded_controller_ptr); auto embedded_controller = BAN::UniqPtr<EmbeddedController>::adopt(embedded_controller_ptr);
embedded_controller->m_thread = thread; embedded_controller->m_thread = thread;
if (gpe.has_value())
TRY(ACPI::get().register_gpe_handler(gpe.value(), &handle_gpe_wrapper, embedded_controller.ptr()));
else
{
// FIXME: Restructure EC such that SCI_EVT can be polled.
// Simple solution would be spawning another thread,
// but that feels too hacky.
dwarnln("TODO: SCI_EVT polling without GPE");
}
return embedded_controller; return embedded_controller;
} }
@@ -95,26 +85,25 @@ namespace Kernel::ACPI
uint8_t EmbeddedController::read_one(uint16_t port) uint8_t EmbeddedController::read_one(uint16_t port)
{ {
wait_status_bit(STS_OBF, 1); wait_status_bit(STS_OBF, true);
return IO::inb(port); return IO::inb(port);
} }
void EmbeddedController::write_one(uint16_t port, uint8_t value) void EmbeddedController::write_one(uint16_t port, uint8_t value)
{ {
wait_status_bit(STS_IBF, 0); wait_status_bit(STS_IBF, false);
IO::outb(port, value); IO::outb(port, value);
} }
void EmbeddedController::wait_status_bit(uint8_t bit, uint8_t value) void EmbeddedController::wait_status_bit(uint8_t mask, bool set)
{ {
// FIXME: timeouts // FIXME: timeouts
const uint8_t mask = 1 << bit; const uint8_t comp = set ? mask : 0;
const uint8_t comp = value ? mask : 0;
while ((IO::inb(m_command_port) & mask) != comp) while ((IO::inb(m_command_port) & mask) != comp)
continue; continue;
} }
void EmbeddedController::handle_gpe_wrapper(void* embedded_controller) void EmbeddedController::handle_gpe_trampoline(void* embedded_controller)
{ {
static_cast<EmbeddedController*>(embedded_controller)->handle_gpe(); static_cast<EmbeddedController*>(embedded_controller)->handle_gpe();
} }
@@ -217,7 +206,7 @@ namespace Kernel::ACPI
for (;;) for (;;)
{ {
Command* const command = m_queued_command.has_value() ? m_queued_command.value() : nullptr; auto* const command = m_queued_command.value_or(nullptr);
m_queued_command.clear(); m_queued_command.clear();
if (command == nullptr) if (command == nullptr)
@@ -226,12 +215,10 @@ namespace Kernel::ACPI
continue; continue;
} }
m_mutex.unlock();
if (command)
{
// TODO: use burst mode // TODO: use burst mode
m_mutex.unlock();
write_one(m_command_port, command->command); write_one(m_command_port, command->command);
if (command->data1.has_value()) if (command->data1.has_value())
write_one(m_data_port, command->data1.value()); write_one(m_data_port, command->data1.value());
@@ -241,12 +228,9 @@ namespace Kernel::ACPI
*command->response = read_one(m_data_port); *command->response = read_one(m_data_port);
m_mutex.lock(); m_mutex.lock();
command->done = true; command->done = true;
m_thread_blocker.unblock(); m_thread_blocker.unblock();
m_mutex.unlock();
}
m_mutex.lock();
} }
} }
@@ -343,6 +343,7 @@ namespace Kernel
using HDAudio::AFGWidget; using HDAudio::AFGWidget;
case AFGWidget::Type::OutputConverter: case AFGWidget::Type::OutputConverter:
case AFGWidget::Type::Mixer: case AFGWidget::Type::Mixer:
case AFGWidget::Type::Selector:
case AFGWidget::Type::PinComplex: case AFGWidget::Type::PinComplex:
break; break;
default: default:
@@ -439,6 +440,9 @@ namespace Kernel
} }
break; break;
case AFGWidget::Type::Selector:
break;
case AFGWidget::Type::PinComplex: case AFGWidget::Type::PinComplex:
// enable output and H-Phn // enable output and H-Phn
TRY(m_controller->send_command({ TRY(m_controller->send_command({
@@ -525,6 +529,7 @@ namespace Kernel
case AFGWidget::Type::OutputConverter: case AFGWidget::Type::OutputConverter:
case AFGWidget::Type::Mixer: case AFGWidget::Type::Mixer:
case AFGWidget::Type::Selector:
break; break;
case AFGWidget::Type::PinComplex: case AFGWidget::Type::PinComplex:
+69 -11
View File
@@ -2,6 +2,7 @@
#include <kernel/Device/DeviceNumbers.h> #include <kernel/Device/DeviceNumbers.h>
#include <kernel/Device/FramebufferDevice.h> #include <kernel/Device/FramebufferDevice.h>
#include <kernel/FS/DevFS/FileSystem.h> #include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/Graphics/BGA.h>
#include <kernel/Memory/Heap.h> #include <kernel/Memory/Heap.h>
#include <kernel/Terminal/FramebufferTerminal.h> #include <kernel/Terminal/FramebufferTerminal.h>
@@ -26,19 +27,14 @@ namespace Kernel
return s_boot_framebuffer; return s_boot_framebuffer;
} }
BAN::ErrorOr<BAN::RefPtr<FramebufferDevice>> FramebufferDevice::create_from_boot_framebuffer() BAN::ErrorOr<BAN::RefPtr<FramebufferDevice>> FramebufferDevice::create(paddr_t paddr, uint32_t width, uint32_t height, uint32_t pitch, uint8_t bpp)
{ {
ASSERT(g_boot_info.framebuffer.type == FramebufferInfo::Type::RGB); if (bpp != 24 && bpp != 32)
if (g_boot_info.framebuffer.bpp != 24 && g_boot_info.framebuffer.bpp != 32)
return BAN::Error::from_errno(ENOTSUP); return BAN::Error::from_errno(ENOTSUP);
auto* device_ptr = new FramebufferDevice( auto* device_ptr = new FramebufferDevice(
0660, 0, 900, 0660, 0, 900,
makedev(DeviceNumber::Framebuffer, get_framebuffer_device_index()), makedev(DeviceNumber::Framebuffer, get_framebuffer_device_index()),
g_boot_info.framebuffer.address, paddr, width, height, pitch, bpp
g_boot_info.framebuffer.width,
g_boot_info.framebuffer.height,
g_boot_info.framebuffer.pitch,
g_boot_info.framebuffer.bpp
); );
if (device_ptr == nullptr) if (device_ptr == nullptr)
return BAN::Error::from_errno(ENOMEM); return BAN::Error::from_errno(ENOMEM);
@@ -49,6 +45,33 @@ namespace Kernel
return device; return device;
} }
BAN::ErrorOr<BAN::RefPtr<FramebufferDevice>> FramebufferDevice::create(BAN::RefPtr<BGAController> bga_controller)
{
const auto fix_info = bga_controller->get_fb_fix_info();
const auto var_info = bga_controller->get_fb_var_info();
auto controller = TRY(create(
fix_info.mem_start,
var_info.xres,
var_info.yres,
fix_info.pitch,
var_info.bpp
));
controller->m_bga_controller = bga_controller;
return controller;
}
BAN::ErrorOr<BAN::RefPtr<FramebufferDevice>> FramebufferDevice::create_from_boot_framebuffer()
{
s_boot_framebuffer = TRY(create(
g_boot_info.framebuffer.address,
g_boot_info.framebuffer.width,
g_boot_info.framebuffer.height,
g_boot_info.framebuffer.pitch,
g_boot_info.framebuffer.bpp
));
return s_boot_framebuffer;
}
FramebufferDevice::FramebufferDevice(mode_t mode, uid_t uid, gid_t gid, dev_t rdev, paddr_t paddr, uint32_t width, uint32_t height, uint32_t pitch, uint8_t bpp) FramebufferDevice::FramebufferDevice(mode_t mode, uid_t uid, gid_t gid, dev_t rdev, paddr_t paddr, uint32_t width, uint32_t height, uint32_t pitch, uint8_t bpp)
: CharacterDevice(mode, uid, gid) : CharacterDevice(mode, uid, gid)
, m_name(MUST(BAN::String::formatted("fb{}", minor(rdev)))) , m_name(MUST(BAN::String::formatted("fb{}", minor(rdev))))
@@ -65,16 +88,20 @@ namespace Kernel
{ {
if (m_video_memory_vaddr == 0) if (m_video_memory_vaddr == 0)
return; return;
size_t video_memory_pages = range_page_count(m_video_memory_paddr, m_height * m_pitch); const size_t video_memory_bytes = m_bga_controller ? m_bga_controller->get_fb_fix_info().mem_size : m_height * m_pitch;
const size_t video_memory_pages = range_page_count(m_video_memory_paddr, video_memory_bytes);
PageTable::kernel().unmap_range(m_video_memory_vaddr, video_memory_pages * PAGE_SIZE); PageTable::kernel().unmap_range(m_video_memory_vaddr, video_memory_pages * PAGE_SIZE);
} }
BAN::ErrorOr<void> FramebufferDevice::initialize() BAN::ErrorOr<void> FramebufferDevice::initialize()
{ {
size_t video_memory_pages = range_page_count(m_video_memory_paddr, m_height * m_pitch); const size_t video_memory_bytes = m_bga_controller ? m_bga_controller->get_fb_fix_info().mem_size : m_height * m_pitch;
const size_t video_memory_pages = range_page_count(m_video_memory_paddr, video_memory_bytes);
m_video_memory_vaddr = PageTable::kernel().reserve_free_contiguous_pages(video_memory_pages, KERNEL_OFFSET); m_video_memory_vaddr = PageTable::kernel().reserve_free_contiguous_pages(video_memory_pages, KERNEL_OFFSET);
if (m_video_memory_vaddr == 0) if (m_video_memory_vaddr == 0)
return BAN::Error::from_errno(ENOMEM); return BAN::Error::from_errno(ENOMEM);
PageTable::kernel().map_range_at( PageTable::kernel().map_range_at(
m_video_memory_paddr & PAGE_ADDR_MASK, m_video_memory_paddr & PAGE_ADDR_MASK,
m_video_memory_vaddr, m_video_memory_vaddr,
@@ -86,7 +113,7 @@ namespace Kernel
m_video_buffer = TRY(VirtualRange::create_to_vaddr_range( m_video_buffer = TRY(VirtualRange::create_to_vaddr_range(
PageTable::kernel(), PageTable::kernel(),
{ KERNEL_OFFSET, UINTPTR_MAX }, { KERNEL_OFFSET, UINTPTR_MAX },
BAN::Math::div_round_up<size_t>(m_width * m_height * (BANAN_FB_BPP / 8), PAGE_SIZE) * PAGE_SIZE, video_memory_pages * PAGE_SIZE,
PageTable::Flags::ReadWrite | PageTable::Flags::Present, PageTable::Flags::ReadWrite | PageTable::Flags::Present,
false false
)); ));
@@ -94,6 +121,37 @@ namespace Kernel
return {}; return {};
} }
BAN::ErrorOr<void> FramebufferDevice::set_bga_controller(BAN::RefPtr<BGAController> bga_controller)
{
ASSERT(!m_bga_controller);
if (auto var_info = bga_controller->get_fb_var_info(); var_info.bpp != 32)
{
var_info.bpp = 32;
TRY(bga_controller->set_fb_var_info(var_info));
}
const auto fix_info = bga_controller->get_fb_fix_info();
const auto var_info = bga_controller->get_fb_var_info();
ASSERT(m_video_memory_vaddr);
PageTable::kernel().unmap_range(m_video_memory_vaddr, m_height * m_pitch);
m_video_memory_vaddr = 0;
m_video_memory_paddr = fix_info.mem_start;
m_width = var_info.xres;
m_height = var_info.yres;
m_pitch = fix_info.pitch;
m_bpp = var_info.bpp;
m_bga_controller = bga_controller;
TRY(initialize());
return {};
}
BAN::ErrorOr<size_t> FramebufferDevice::read_impl(off_t offset, BAN::ByteSpan buffer) BAN::ErrorOr<size_t> FramebufferDevice::read_impl(off_t offset, BAN::ByteSpan buffer)
{ {
// Reading from negative offset will fill buffer with framebuffer info // Reading from negative offset will fill buffer with framebuffer info
+3 -3
View File
@@ -63,7 +63,7 @@ namespace Kernel
} }
}, s_instance }, s_instance
)); ));
MUST(Processor::scheduler().add_thread(updater_thread)); Processor::scheduler().add_thread(updater_thread);
auto* disk_cache_drop_thread = MUST(Thread::create_kernel( auto* disk_cache_drop_thread = MUST(Thread::create_kernel(
[](void* _devfs) [](void* _devfs)
@@ -93,7 +93,7 @@ namespace Kernel
} }
}, s_instance }, s_instance
)); ));
MUST(Processor::scheduler().add_thread(disk_cache_drop_thread)); Processor::scheduler().add_thread(disk_cache_drop_thread);
auto* disk_sync_thread = MUST(Thread::create_kernel( auto* disk_sync_thread = MUST(Thread::create_kernel(
[](void* _devfs) [](void* _devfs)
@@ -129,7 +129,7 @@ namespace Kernel
} }
}, s_instance }, s_instance
)); ));
MUST(Processor::scheduler().add_thread(disk_sync_thread)); Processor::scheduler().add_thread(disk_sync_thread);
} }
void DevFileSystem::initiate_disk_cache_drop() void DevFileSystem::initiate_disk_cache_drop()
+242
View File
@@ -0,0 +1,242 @@
#include <kernel/Device/FramebufferDevice.h>
#include <kernel/Graphics/BGA.h>
#include <kernel/IO.h>
#include <kernel/Terminal/FramebufferTerminal.h>
#include <kernel/Terminal/VirtualTTY.h>
namespace Kernel
{
enum BGA_IO_PORT : uint16_t
{
BGA_IO_PORT_INDEX = 0x1CE,
BGA_IO_PORT_DATA = 0x1CF,
};
enum BGA_REG : uint16_t
{
BGA_REG_ID = 0,
BGA_REG_XRES = 1,
BGA_REG_YRES = 2,
BGA_REG_BPP = 3,
BGA_REG_ENABLE = 4,
BGA_REG_BANK = 5,
BGA_REG_XRES_VIRT = 6,
BGA_REG_YRES_VIRT = 7,
BGA_REG_XOFF = 8,
BGA_REG_YOFF = 9,
};
enum BGA_ID : uint16_t
{
BGA_ID_0 = 0xB0C0,
BGA_ID_1 = 0xB0C1,
BGA_ID_2 = 0xB0C2,
BGA_ID_3 = 0xB0C3,
BGA_ID_4 = 0xB0C4,
BGA_ID_5 = 0xB0C5,
};
enum BGA_ENABLE : uint16_t
{
BGA_ENABLE_ENABLE = 0x01,
BGA_ENABLE_LFB_ENABLE = 0x40,
BGA_ENABLE_NOCLEARMEM = 0x80,
};
BAN::ErrorOr<BAN::RefPtr<BGAController>> BGAController::create(PCI::Device& pci_device)
{
auto* bga_controller_ptr = new BGAController(pci_device);
if (bga_controller_ptr == nullptr)
return BAN::Error::from_errno(ENOMEM);
auto bga_controller = BAN::RefPtr<BGAController>::adopt(bga_controller_ptr);
TRY(bga_controller->initialize());
return bga_controller;
}
BGAController::BGAController(PCI::Device& pci_device)
: m_pci_device(pci_device)
{ }
BAN::ErrorOr<void> BGAController::initialize()
{
auto boot_framebuffer = FramebufferDevice::boot_framebuffer();
m_lfb_bar = TRY(m_pci_device.allocate_bar_region(0));
if (m_lfb_bar->type() != PCI::BarType::MEM)
{
dwarnln("BGA LFB is not memory bar");
return BAN::Error::from_errno(EINVAL);
}
m_fix_info = {
.xpanstep = 1,
.ypanstep = 1,
.pitch = 0,
.mem_start = static_cast<uint64_t>(m_lfb_bar->paddr()),
.mem_size = static_cast<uint32_t>(m_lfb_bar->size()),
};
const auto ready_to_use_flags = BGA_ENABLE_LFB_ENABLE | BGA_ENABLE_ENABLE;
if ((read_reg(BGA_REG_ENABLE) & ready_to_use_flags) == ready_to_use_flags)
{
m_var_info = {
.xres = read_reg(BGA_REG_XRES),
.yres = read_reg(BGA_REG_YRES),
.xres_virt = read_reg(BGA_REG_XRES_VIRT),
.yres_virt = read_reg(BGA_REG_XRES_VIRT),
.xoff = read_reg(BGA_REG_XOFF),
.yoff = read_reg(BGA_REG_YOFF),
.bpp = read_reg(BGA_REG_BPP),
};
m_fix_info.pitch = m_var_info.xres_virt * m_var_info.bpp / 8;
}
else
{
const uint32_t xres = boot_framebuffer ? boot_framebuffer->width() : 1280;
const uint32_t yres = boot_framebuffer ? boot_framebuffer->height() : 800;
const uint32_t bpp = boot_framebuffer ? boot_framebuffer->bpp() : 32;
TRY(set_fb_var_info({
.xres = xres,
.yres = yres,
.xres_virt = xres,
.yres_virt = yres * 2,
.xoff = 0,
.yoff = 0,
.bpp = bpp,
}));
}
if (boot_framebuffer)
{
// FIXME: check that this is actually the boot framebuffer
TRY(boot_framebuffer->set_bga_controller(this));
}
else
{
auto framebuffer_device = TRY(FramebufferDevice::create(this));
auto fb_terminal_driver = TRY(FramebufferTerminalDriver::create(framebuffer_device));
// FIXME: query vtty instead of checking the current tty
if (auto tty = TTY::current(); tty && tty->is_vtty())
TRY(static_cast<VirtualTTY*>(tty.ptr())->set_terminal_driver(fb_terminal_driver));
else
TRY(VirtualTTY::create(fb_terminal_driver));
}
return {};
}
BAN::ErrorOr<void> BGAController::set_fb_var_info(const fb_var_info& var_info)
{
const auto validate_u16 = [](auto value) -> BAN::ErrorOr<void> {
if (value > BAN::numeric_limits<uint16_t>::max())
return BAN::Error::from_errno(EINVAL);
return {};
};
TRY(validate_u16(var_info.xres));
TRY(validate_u16(var_info.xres));
TRY(validate_u16(var_info.xres_virt));
TRY(validate_u16(var_info.yres_virt));
TRY(validate_u16(var_info.xoff));
TRY(validate_u16(var_info.yoff));
TRY(validate_u16(var_info.bpp));
if (var_info.xres + var_info.xoff > var_info.xres_virt)
return BAN::Error::from_errno(EINVAL);
if (var_info.yres + var_info.yoff > var_info.yres_virt)
return BAN::Error::from_errno(EINVAL);
if (static_cast<uint64_t>(var_info.xres_virt) * var_info.yres_virt * var_info.bpp / 8 > m_lfb_bar->size())
return BAN::Error::from_errno(EINVAL);
SpinLockGuard _(m_lock);
const bool needs_reconf =
(m_var_info.xres != var_info.xres) ||
(m_var_info.yres != var_info.yres) ||
(m_var_info.xres_virt != var_info.xres_virt) ||
(m_var_info.yres_virt != var_info.yres_virt) ||
(m_var_info.bpp != var_info.bpp);
if (!needs_reconf)
{
write_reg(BGA_REG_XOFF, var_info.xoff);
write_reg(BGA_REG_YOFF, var_info.yoff);
m_var_info.xoff = var_info.xoff;
m_var_info.yoff = var_info.yoff;
return {};
}
const auto old_enable = read_reg(BGA_REG_ENABLE);
write_reg(BGA_REG_ENABLE, 0);
write_reg(BGA_REG_BPP, var_info.bpp);
write_reg(BGA_REG_XRES, var_info.xres);
write_reg(BGA_REG_YRES, var_info.yres);
write_reg(BGA_REG_XRES_VIRT, var_info.xres_virt);
write_reg(BGA_REG_YRES_VIRT, var_info.yres_virt);
const bool valid_config =
read_reg(BGA_REG_BPP) == var_info.bpp &&
read_reg(BGA_REG_XRES) == var_info.xres &&
read_reg(BGA_REG_YRES) == var_info.yres &&
read_reg(BGA_REG_XRES_VIRT) == var_info.xres_virt;
if (!valid_config)
{
write_reg(BGA_REG_BPP, m_var_info.bpp);
write_reg(BGA_REG_XRES, m_var_info.xres);
write_reg(BGA_REG_YRES, m_var_info.yres);
write_reg(BGA_REG_XRES_VIRT, m_var_info.xres_virt);
write_reg(BGA_REG_YRES_VIRT, m_var_info.yres_virt);
write_reg(BGA_REG_ENABLE, BGA_ENABLE_NOCLEARMEM | old_enable);
return BAN::Error::from_errno(EINVAL);
}
write_reg(BGA_REG_ENABLE, BGA_ENABLE_LFB_ENABLE | BGA_ENABLE_ENABLE);
// NOTE: At least qemu only sets virtual yres on enable and it will be
// maximum that fits within vram. Our initial bounds check should
// make sure this always succeeds
ASSERT(read_reg(BGA_REG_YRES_VIRT) >= var_info.yres_virt);
write_reg(BGA_REG_XOFF, var_info.xoff);
write_reg(BGA_REG_YOFF, var_info.yoff);
m_var_info = var_info;
m_fix_info.pitch = m_var_info.xres_virt * m_var_info.bpp / 8;
return {};
}
void BGAController::write_reg(uint16_t reg, uint16_t value)
{
SpinLockGuard _(m_lock);
IO::outw(BGA_IO_PORT_INDEX, reg);
IO::outw(BGA_IO_PORT_DATA, value);
}
uint16_t BGAController::read_reg(uint16_t reg)
{
SpinLockGuard _(m_lock);
IO::outw(BGA_IO_PORT_INDEX, reg);
return IO::inw(BGA_IO_PORT_DATA);
}
fb_fix_info BGAController::get_fb_fix_info() const
{
SpinLockGuard _(m_lock);
return m_fix_info;
}
fb_var_info BGAController::get_fb_var_info() const
{
SpinLockGuard _(m_lock);
return m_var_info;
}
}
+1 -2
View File
@@ -307,8 +307,7 @@ namespace Kernel
BAN::ErrorOr<void> KeyboardDevice::initialize_tty_thread() BAN::ErrorOr<void> KeyboardDevice::initialize_tty_thread()
{ {
auto* thread = TRY(Thread::create_kernel(tty_keyboard_thread, nullptr)); auto* thread = TRY(Thread::create_kernel(tty_keyboard_thread, nullptr));
ASSERT(thread); Processor::scheduler().add_thread(thread);
TRY(Processor::scheduler().add_thread(thread));
return {}; return {};
} }
+9 -2
View File
@@ -319,11 +319,18 @@ namespace Kernel::Input
if (crs_obj == nullptr) if (crs_obj == nullptr)
return PS2ResourceSetting {}; return PS2ResourceSetting {};
const auto crs = TRY(ACPI::AML::evaluate_node(crs_path, crs_obj->node));
if (crs.type != ACPI::AML::Node::Type::Buffer)
{
dwarnln("PS/2 _CRS is not a buffer, but {}", crs);
return BAN::Error::from_errno(EINVAL);
}
PS2ResourceSetting result; PS2ResourceSetting result;
result.type = type; result.type = type;
BAN::Optional<ACPI::ResourceData> data; BAN::Optional<ACPI::ResourceData> data;
ACPI::ResourceParser parser({ crs_obj->node.as.str_buf->bytes, static_cast<size_t>(crs_obj->node.as.str_buf->size) }); ACPI::ResourceParser parser({ crs.as.str_buf->bytes, static_cast<size_t>(crs.as.str_buf->size) });
while ((data = parser.get_next()).has_value()) while ((data = parser.get_next()).has_value())
{ {
switch (data->type) switch (data->type)
@@ -551,7 +558,7 @@ namespace Kernel::Input
static_cast<PS2DeviceInitInfo*>(info)->controller->device_initialize_task(info); static_cast<PS2DeviceInitInfo*>(info)->controller->device_initialize_task(info);
}, &info }, &info
)); ));
TRY(Processor::scheduler().add_thread(init_thread)); Processor::scheduler().add_thread(init_thread);
while (!info.thread_started) while (!info.thread_started)
Processor::pause(); Processor::pause();
@@ -87,6 +87,9 @@ namespace Kernel
return BAN::Error::from_errno(ENOENT); return BAN::Error::from_errno(ENOENT);
} }
if (size == 0)
return BAN::Error::from_errno(EINVAL);
const auto& process = Process::current(); const auto& process = Process::current();
const uid_t uid = process.credentials().euid(); const uid_t uid = process.credentials().euid();
const gid_t gid = process.credentials().egid(); const gid_t gid = process.credentials().egid();
+2 -5
View File
@@ -95,11 +95,8 @@ namespace Kernel
auto* thread = TRY(Thread::create_kernel([](void* e1000_ptr) { auto* thread = TRY(Thread::create_kernel([](void* e1000_ptr) {
static_cast<E1000*>(e1000_ptr)->receive_thread(); static_cast<E1000*>(e1000_ptr)->receive_thread();
}, this)); }, this));
if (auto ret = Processor::scheduler().add_thread(thread); ret.is_error())
{ Processor::scheduler().add_thread(thread);
delete thread;
return ret.release_error();
}
m_thread_is_dead = false; m_thread_is_dead = false;
return {}; return {};
+2 -5
View File
@@ -25,11 +25,8 @@ namespace Kernel
auto* thread = TRY(Thread::create_kernel([](void* loopback_ptr) { auto* thread = TRY(Thread::create_kernel([](void* loopback_ptr) {
static_cast<LoopbackInterface*>(loopback_ptr)->receive_thread(); static_cast<LoopbackInterface*>(loopback_ptr)->receive_thread();
}, loopback_ptr)); }, loopback_ptr));
if (auto ret = Processor::scheduler().add_thread(thread); ret.is_error())
{ Processor::scheduler().add_thread(thread);
delete thread;
return ret.release_error();
}
loopback->m_thread_is_dead = false; loopback->m_thread_is_dead = false;
loopback->set_ipv4_address({ 127, 0, 0, 1 }); loopback->set_ipv4_address({ 127, 0, 0, 1 });
+2 -5
View File
@@ -75,11 +75,8 @@ namespace Kernel
auto* thread = TRY(Thread::create_kernel([](void* rtl8169_ptr) { auto* thread = TRY(Thread::create_kernel([](void* rtl8169_ptr) {
static_cast<RTL8169*>(rtl8169_ptr)->receive_thread(); static_cast<RTL8169*>(rtl8169_ptr)->receive_thread();
}, this)); }, this));
if (auto ret = Processor::scheduler().add_thread(thread); ret.is_error())
{ Processor::scheduler().add_thread(thread);
delete thread;
return ret.release_error();
}
m_rx_thread_is_dead = false; m_rx_thread_is_dead = false;
return {}; return {};
+1 -1
View File
@@ -45,7 +45,7 @@ namespace Kernel
reinterpret_cast<TCPSocket*>(socket_ptr)->process_task(); reinterpret_cast<TCPSocket*>(socket_ptr)->process_task();
}, socket.ptr() }, socket.ptr()
)); ));
TRY(Processor::scheduler().add_thread(socket->m_thread)); Processor::scheduler().add_thread(socket->m_thread);
// hack to keep socket alive until its process starts // hack to keep socket alive until its process starts
socket->ref(); socket->ref();
return socket; return socket;
+11 -11
View File
@@ -21,7 +21,7 @@ namespace Kernel
static BAN::ErrorOr<BAN::StringView> validate_sockaddr_un(const sockaddr* address, socklen_t address_len) static BAN::ErrorOr<BAN::StringView> validate_sockaddr_un(const sockaddr* address, socklen_t address_len)
{ {
if (address_len < static_cast<socklen_t>(sizeof(sa_family_t))) if (address_len <= static_cast<socklen_t>(sizeof(sa_family_t)))
return BAN::Error::from_errno(EINVAL); return BAN::Error::from_errno(EINVAL);
if (address_len > static_cast<socklen_t>(sizeof(sockaddr_un))) if (address_len > static_cast<socklen_t>(sizeof(sockaddr_un)))
address_len = sizeof(sockaddr_un); address_len = sizeof(sockaddr_un);
@@ -30,13 +30,12 @@ namespace Kernel
if (sockaddr_un.sun_family != AF_UNIX) if (sockaddr_un.sun_family != AF_UNIX)
return BAN::Error::from_errno(EINVAL); return BAN::Error::from_errno(EINVAL);
size_t length = 0; auto sun_path = BAN::StringView { sockaddr_un.sun_path, address_len - sizeof(sa_family_t) };
while (length < sizeof(sockaddr_un::sun_path) && sockaddr_un.sun_path[length]) if (const auto null_idx = sun_path.find('\0'); null_idx.has_value())
length++; sun_path = sun_path.substring(0, null_idx.value());
if (length >= sizeof(sockaddr_un::sun_path)) if (sun_path.empty())
return BAN::Error::from_errno(ENAMETOOLONG); return BAN::Error::from_errno(EINVAL);
return sun_path;
return BAN::StringView { sockaddr_un.sun_path, length };
} }
BAN::ErrorOr<BAN::RefPtr<UnixDomainSocket>> UnixDomainSocket::create(Socket::Type socket_type, const Socket::Info& info) BAN::ErrorOr<BAN::RefPtr<UnixDomainSocket>> UnixDomainSocket::create(Socket::Type socket_type, const Socket::Info& info)
@@ -264,14 +263,15 @@ namespace Kernel
BAN::ErrorOr<void> UnixDomainSocket::bind_impl(const sockaddr* address, socklen_t address_len) BAN::ErrorOr<void> UnixDomainSocket::bind_impl(const sockaddr* address, socklen_t address_len)
{ {
const auto sun_path = TRY(validate_sockaddr_un(address, address_len)); const auto sun_path = TRY(validate_sockaddr_un(address, address_len));
if (sun_path.empty())
return BAN::Error::from_errno(EINVAL); BAN::String sun_path_nul;
TRY(sun_path_nul.append(sun_path));
// FIXME: This feels sketchy // FIXME: This feels sketchy
auto parent_file = sun_path.front() == '/' auto parent_file = sun_path.front() == '/'
? TRY(Process::current().root_file().clone()) ? TRY(Process::current().root_file().clone())
: TRY(Process::current().working_directory().clone()); : TRY(Process::current().working_directory().clone());
if (auto ret = Process::current().create_file(AT_FDCWD, sun_path.data(), 0755 | Inode::Mode::IFSOCK); ret.is_error()) if (auto ret = Process::current().create_file(AT_FDCWD, sun_path_nul.data(), 0755 | Inode::Mode::IFSOCK); ret.is_error())
{ {
if (ret.error().get_error_code() == EEXIST) if (ret.error().get_error_code() == EEXIST)
return BAN::Error::from_errno(EADDRINUSE); return BAN::Error::from_errno(EADDRINUSE);
+19 -5
View File
@@ -3,6 +3,7 @@
#include <kernel/ACPI/ACPI.h> #include <kernel/ACPI/ACPI.h>
#include <kernel/APIC.h> #include <kernel/APIC.h>
#include <kernel/Audio/Controller.h> #include <kernel/Audio/Controller.h>
#include <kernel/Graphics/BGA.h>
#include <kernel/IDT.h> #include <kernel/IDT.h>
#include <kernel/IO.h> #include <kernel/IO.h>
#include <kernel/Memory/PageTable.h> #include <kernel/Memory/PageTable.h>
@@ -258,6 +259,13 @@ namespace Kernel::PCI
for_each_device( for_each_device(
[&](PCI::Device& pci_device) [&](PCI::Device& pci_device)
{ {
if (pci_device.vendor_id() == 0x1234 && pci_device.device_id() == 0x1111)
{
if (auto ret = BGAController::create(pci_device); ret.is_error())
dprintln("BGA: {}", ret.error());
return;
}
switch (pci_device.class_code()) switch (pci_device.class_code())
{ {
case 0x01: case 0x01:
@@ -912,10 +920,10 @@ namespace Kernel::PCI
} }
// disable io/mem space while reading bar // disable io/mem space while reading bar
uint16_t command = device.read_word(PCI_REG_COMMAND); const uint16_t command = device.read_word(PCI_REG_COMMAND);
device.write_word(PCI_REG_COMMAND, command & ~(PCI_CMD_IO_SPACE | PCI_CMD_MEM_SPACE)); device.write_word(PCI_REG_COMMAND, command & ~(PCI_CMD_IO_SPACE | PCI_CMD_MEM_SPACE));
uint8_t offset = 0x10 + bar_num * 4; const uint8_t offset = 0x10 + bar_num * 4;
uint64_t addr = device.read_dword(offset); uint64_t addr = device.read_dword(offset);
@@ -924,6 +932,13 @@ namespace Kernel::PCI
size = ~size + 1; size = ~size + 1;
device.write_dword(offset, addr); device.write_dword(offset, addr);
if (size == 0)
{
device.write_word(PCI_REG_COMMAND, command);
dwarnln("BAR{} has size 0", bar_num);
return BAN::Error::from_errno(EINVAL);
}
// determine bar type // determine bar type
BarType type = BarType::INVALID; BarType type = BarType::INVALID;
if (addr & 1) if (addr & 1)
@@ -956,8 +971,7 @@ namespace Kernel::PCI
TRY(region->initialize()); TRY(region->initialize());
// restore old command register and enable correct IO/MEM space // restore old command register and enable correct IO/MEM space
command |= (type == BarType::IO) ? PCI_CMD_IO_SPACE : PCI_CMD_MEM_SPACE; device.write_word(PCI_REG_COMMAND, command | ((type == BarType::IO) ? PCI_CMD_IO_SPACE : PCI_CMD_MEM_SPACE));
device.write_word(PCI_REG_COMMAND, command);
#if DEBUG_PCI #if DEBUG_PCI
dprintln("created BAR region for PCI {2H}:{2H}.{2H}", dprintln("created BAR region for PCI {2H}:{2H}.{2H}",
@@ -997,7 +1011,7 @@ namespace Kernel::PCI
if (m_type == BarType::IO) if (m_type == BarType::IO)
return {}; return {};
size_t needed_pages = BAN::Math::div_round_up<size_t>(m_size, PAGE_SIZE); const size_t needed_pages = BAN::Math::div_round_up<size_t>(m_size, PAGE_SIZE);
m_vaddr = PageTable::kernel().reserve_free_contiguous_pages(needed_pages, KERNEL_OFFSET); m_vaddr = PageTable::kernel().reserve_free_contiguous_pages(needed_pages, KERNEL_OFFSET);
if (m_vaddr == 0) if (m_vaddr == 0)
return BAN::Error::from_errno(ENOMEM); return BAN::Error::from_errno(ENOMEM);
+96 -111
View File
@@ -237,9 +237,8 @@ namespace Kernel
#endif #endif
} }
// NOTE: make sure the last two `MUST`s don't fail // NOTE: make sure the last `MUST` doesn't fail
TRY(process->m_threads.reserve(1)); TRY(process->m_threads.reserve(1));
TRY(Processor::scheduler().bind_thread_to_processor(thread, Processor::current_id()));
{ {
SpinLockGuard _(s_process_lock); SpinLockGuard _(s_process_lock);
@@ -247,7 +246,7 @@ namespace Kernel
} }
MUST(process->m_threads.push_back(thread)); MUST(process->m_threads.push_back(thread));
MUST(Processor::scheduler().add_thread(thread)); Processor::scheduler().add_thread(thread);
process_deleter.disable(); process_deleter.disable();
thread_deleter.disable(); thread_deleter.disable();
@@ -877,9 +876,8 @@ namespace Kernel
Thread* thread = TRY(Thread::current().clone(forked, sp, ip)); Thread* thread = TRY(Thread::current().clone(forked, sp, ip));
BAN::ScopeGuard thread_deleter([thread] { delete thread; }); BAN::ScopeGuard thread_deleter([thread] { delete thread; });
// NOTE: make sure the last two `MUST`s don't fail // NOTE: make sure the last `MUST` doesn't fail
TRY(forked->m_threads.reserve(1)); TRY(forked->m_threads.reserve(1));
TRY(Processor::scheduler().bind_thread_to_processor(thread, Processor::current_id()));
{ {
SpinLockGuard _(s_process_lock); SpinLockGuard _(s_process_lock);
@@ -905,7 +903,7 @@ namespace Kernel
ASSERT(this == &Process::current()); ASSERT(this == &Process::current());
MUST(forked->m_threads.push_back(thread)); MUST(forked->m_threads.push_back(thread));
MUST(Processor::scheduler().add_thread(thread)); Processor::scheduler().add_thread(thread);
process_deleter.disable(); process_deleter.disable();
thread_deleter.disable(); thread_deleter.disable();
@@ -1072,14 +1070,6 @@ namespace Kernel
#endif #endif
} }
// NOTE: bind new thread to this processor so it wont be rescheduled before end of this function
// and so that adding the thread to the scheduler cannot fail
if (auto ret = Scheduler::bind_thread_to_processor(new_thread, Processor::current_id()); ret.is_error())
{
Processor::set_interrupt_state(InterruptState::Enabled);
delete new_thread;
return ret.release_error();
}
RWLockWRGuard wr_guard(m_memory_region_lock); RWLockWRGuard wr_guard(m_memory_region_lock);
@@ -1103,7 +1093,9 @@ namespace Kernel
m_threads.front()->m_process = nullptr; m_threads.front()->m_process = nullptr;
m_threads.front()->give_keep_alive_page_table(BAN::move(m_page_table)); m_threads.front()->give_keep_alive_page_table(BAN::move(m_page_table));
MUST(Processor::scheduler().add_thread(new_thread)); // NOTE: bind new thread to this processor so it wont be rescheduled before end of this function
Scheduler::bind_thread_to_processor(new_thread, Processor::current_id());
Processor::scheduler().add_thread(new_thread);
m_threads.front() = new_thread; m_threads.front() = new_thread;
for (size_t i = 0; i < sizeof(m_signal_handlers) / sizeof(*m_signal_handlers); i++) for (size_t i = 0; i < sizeof(m_signal_handlers) / sizeof(*m_signal_handlers); i++)
@@ -1270,18 +1262,12 @@ namespace Kernel
return BAN::Error::from_errno(EINVAL); return BAN::Error::from_errno(EINVAL);
} }
MemoryRegion* value_region = nullptr; BAN::Vector<MemoryRegion*> regions;
MemoryRegion* ovalue_region = nullptr; BAN::ScopeGuard _([&] { for (auto* region : regions) region->unpin(); });
BAN::ScopeGuard _([&] {
if (value_region)
value_region->unpin();
if (ovalue_region)
ovalue_region->unpin();
});
value_region = TRY(validate_and_pin_pointer_access(value, sizeof(itimerval), false)); TRY(validate_and_pin_pointer_access(value, sizeof(itimerval), false, regions));
if (ovalue != nullptr) if (ovalue != nullptr)
ovalue_region = TRY(validate_and_pin_pointer_access(ovalue, sizeof(itimerval), true)); TRY(validate_and_pin_pointer_access(ovalue, sizeof(itimerval), true, regions));
{ {
SpinLockGuard _(s_process_lock); SpinLockGuard _(s_process_lock);
@@ -1475,8 +1461,10 @@ namespace Kernel
return 0; return 0;
} }
auto* buffer_region = TRY(validate_and_pin_pointer_access(buffer, count, true)); BAN::Vector<MemoryRegion*> regions;
BAN::ScopeGuard _([buffer_region] { buffer_region->unpin(); }); BAN::ScopeGuard _([&] { for (auto* region : regions) region->unpin(); });
TRY(validate_and_pin_pointer_access(buffer, count, true, regions));
return TRY(m_open_file_descriptors.read(fd, BAN::ByteSpan(static_cast<uint8_t*>(buffer), count))); return TRY(m_open_file_descriptors.read(fd, BAN::ByteSpan(static_cast<uint8_t*>(buffer), count)));
} }
@@ -1488,8 +1476,10 @@ namespace Kernel
return 0; return 0;
} }
auto* buffer_region = TRY(validate_and_pin_pointer_access(buffer, count, false)); BAN::Vector<MemoryRegion*> regions;
BAN::ScopeGuard _([buffer_region] { buffer_region->unpin(); }); BAN::ScopeGuard _([&] { for (auto* region : regions) region->unpin(); });
TRY(validate_and_pin_pointer_access(buffer, count, false, regions));
return TRY(m_open_file_descriptors.write(fd, BAN::ConstByteSpan(static_cast<const uint8_t*>(buffer), count))); return TRY(m_open_file_descriptors.write(fd, BAN::ConstByteSpan(static_cast<const uint8_t*>(buffer), count)));
} }
@@ -1679,8 +1669,9 @@ namespace Kernel
{ {
auto inode = TRY(m_open_file_descriptors.inode_of(fd)); auto inode = TRY(m_open_file_descriptors.inode_of(fd));
auto* buffer_region = TRY(validate_and_pin_pointer_access(buffer, count, true)); BAN::Vector<MemoryRegion*> regions;
BAN::ScopeGuard _([buffer_region] { buffer_region->unpin(); }); BAN::ScopeGuard _([&] { for (auto* region : regions) region->unpin(); });
TRY(validate_and_pin_pointer_access(buffer, count, true, regions));
return TRY(inode->read(offset, { reinterpret_cast<uint8_t*>(buffer), count })); return TRY(inode->read(offset, { reinterpret_cast<uint8_t*>(buffer), count }));
} }
@@ -1689,8 +1680,9 @@ namespace Kernel
{ {
auto inode = TRY(m_open_file_descriptors.inode_of(fd)); auto inode = TRY(m_open_file_descriptors.inode_of(fd));
auto* buffer_region = TRY(validate_and_pin_pointer_access(buffer, count, false)); BAN::Vector<MemoryRegion*> regions;
BAN::ScopeGuard _([buffer_region] { buffer_region->unpin(); }); BAN::ScopeGuard _([&] { for (auto* region : regions) region->unpin(); });
TRY(validate_and_pin_pointer_access(buffer, count, false, regions));
return TRY(inode->write(offset, { reinterpret_cast<const uint8_t*>(buffer), count })); } return TRY(inode->write(offset, { reinterpret_cast<const uint8_t*>(buffer), count })); }
@@ -1710,11 +1702,8 @@ namespace Kernel
{ {
LockGuard _(m_process_lock); LockGuard _(m_process_lock);
if (!m_credentials.is_superuser() && inode->uid() != m_credentials.euid()) if (!m_credentials.is_superuser() && inode->uid() != m_credentials.euid())
{
dwarnln("cannot chmod uid {} vs {}", inode->uid(), m_credentials.euid());
return BAN::Error::from_errno(EPERM); return BAN::Error::from_errno(EPERM);
} }
}
TRY(inode->chmod(mode & ~S_IFMASK)); TRY(inode->chmod(mode & ~S_IFMASK));
@@ -1885,8 +1874,9 @@ namespace Kernel
if (!inode->mode().ifsock()) if (!inode->mode().ifsock())
return BAN::Error::from_errno(ENOTSOCK); return BAN::Error::from_errno(ENOTSOCK);
auto* buffer = TRY(validate_and_pin_pointer_access(user_option_value, option_len, true)); BAN::Vector<MemoryRegion*> regions;
BAN::ScopeGuard _([buffer] { buffer->unpin(); }); BAN::ScopeGuard _([&] { for (auto* region : regions) region->unpin(); });
TRY(validate_and_pin_pointer_access(user_option_value, option_len, true, regions));
TRY(inode->getsockopt(level, option_name, user_option_value, &option_len)); TRY(inode->getsockopt(level, option_name, user_option_value, &option_len));
TRY(write_to_user(user_option_len, &option_len, sizeof(socklen_t))); TRY(write_to_user(user_option_len, &option_len, sizeof(socklen_t)));
@@ -1903,8 +1893,9 @@ namespace Kernel
if (!inode->mode().ifsock()) if (!inode->mode().ifsock())
return BAN::Error::from_errno(ENOTSOCK); return BAN::Error::from_errno(ENOTSOCK);
auto* buffer = TRY(validate_and_pin_pointer_access(user_option_value, option_len, false)); BAN::Vector<MemoryRegion*> regions;
BAN::ScopeGuard _([buffer] { buffer->unpin(); }); BAN::ScopeGuard _([&] { for (auto* region : regions) region->unpin(); });
TRY(validate_and_pin_pointer_access(user_option_value, option_len, false, regions));
TRY(inode->setsockopt(level, option_name, user_option_value, option_len)); TRY(inode->setsockopt(level, option_name, user_option_value, option_len));
@@ -1918,20 +1909,13 @@ namespace Kernel
if (flags & ~(SOCK_NONBLOCK | SOCK_CLOEXEC)) if (flags & ~(SOCK_NONBLOCK | SOCK_CLOEXEC))
return BAN::Error::from_errno(EINVAL); return BAN::Error::from_errno(EINVAL);
MemoryRegion* address_region1 = nullptr; BAN::Vector<MemoryRegion*> regions;
MemoryRegion* address_region2 = nullptr; BAN::ScopeGuard _([&] { for (auto* region : regions) region->unpin(); });
BAN::ScopeGuard _([&] {
if (address_region1)
address_region1->unpin();
if (address_region2)
address_region2->unpin();
});
if (address_len) if (address_len)
{ {
address_region1 = TRY(validate_and_pin_pointer_access(address_len, sizeof(address_len), true)); TRY(validate_and_pin_pointer_access(address_len, sizeof(address_len), true, regions));
address_region2 = TRY(validate_and_pin_pointer_access(address, *address_len, true)); TRY(validate_and_pin_pointer_access(address, *address_len, true, regions));
} }
auto inode = TRY(m_open_file_descriptors.inode_of(socket)); auto inode = TRY(m_open_file_descriptors.inode_of(socket));
@@ -1998,23 +1982,17 @@ namespace Kernel
TRY(read_from_user(user_message, &message, sizeof(msghdr))); TRY(read_from_user(user_message, &message, sizeof(msghdr)));
BAN::Vector<MemoryRegion*> regions; BAN::Vector<MemoryRegion*> regions;
TRY(regions.reserve(!!message.msg_name + !!message.msg_control + !!message.msg_iov)); BAN::ScopeGuard _([&] { for (auto* region : regions) region->unpin(); });
BAN::ScopeGuard _([&regions] {
for (auto* region : regions)
region->unpin();
});
if (message.msg_name) if (message.msg_name)
TRY(regions.push_back(TRY(validate_and_pin_pointer_access(message.msg_name, message.msg_namelen, true)))); TRY(validate_and_pin_pointer_access(message.msg_name, message.msg_namelen, true, regions));
if (message.msg_control) if (message.msg_control)
TRY(regions.push_back(TRY(validate_and_pin_pointer_access(message.msg_control, message.msg_controllen, true)))); TRY(validate_and_pin_pointer_access(message.msg_control, message.msg_controllen, true, regions));
if (message.msg_iov) if (message.msg_iov)
{ {
TRY(regions.push_back(TRY(validate_and_pin_pointer_access(message.msg_iov, message.msg_iovlen * sizeof(iovec), true)))); TRY(validate_and_pin_pointer_access(message.msg_iov, message.msg_iovlen * sizeof(iovec), true, regions));
TRY(regions.reserve(regions.size() + message.msg_iovlen));
for (int i = 0; i < message.msg_iovlen; i++) for (int i = 0; i < message.msg_iovlen; i++)
TRY(regions.push_back(TRY(validate_and_pin_pointer_access(message.msg_iov[i].iov_base, message.msg_iov[i].iov_len, true)))); TRY(validate_and_pin_pointer_access(message.msg_iov[i].iov_base, message.msg_iov[i].iov_len, true, regions));
} }
const auto ret = TRY(m_open_file_descriptors.recvmsg(socket, message, flags)); const auto ret = TRY(m_open_file_descriptors.recvmsg(socket, message, flags));
@@ -2030,23 +2008,18 @@ namespace Kernel
TRY(read_from_user(user_message, &message, sizeof(msghdr))); TRY(read_from_user(user_message, &message, sizeof(msghdr)));
BAN::Vector<MemoryRegion*> regions; BAN::Vector<MemoryRegion*> regions;
TRY(regions.reserve(!!message.msg_name + !!message.msg_control + !!message.msg_iov)); BAN::ScopeGuard _([&regions] { for (auto* region : regions) region->unpin(); });
BAN::ScopeGuard _([&regions] {
for (auto* region : regions)
region->unpin();
});
if (message.msg_name) if (message.msg_name)
TRY(regions.push_back(TRY(validate_and_pin_pointer_access(message.msg_name, message.msg_namelen, false)))); TRY(validate_and_pin_pointer_access(message.msg_name, message.msg_namelen, false, regions));
if (message.msg_control) if (message.msg_control)
TRY(regions.push_back(TRY(validate_and_pin_pointer_access(message.msg_control, message.msg_controllen, false)))); TRY(validate_and_pin_pointer_access(message.msg_control, message.msg_controllen, false, regions));
if (message.msg_iov) if (message.msg_iov)
{ {
TRY(regions.push_back(TRY(validate_and_pin_pointer_access(message.msg_iov, message.msg_iovlen * sizeof(iovec), false)))); TRY(validate_and_pin_pointer_access(message.msg_iov, message.msg_iovlen * sizeof(iovec), false, regions));
TRY(regions.reserve(regions.size() + message.msg_iovlen)); TRY(regions.reserve(regions.size() + message.msg_iovlen));
for (int i = 0; i < message.msg_iovlen; i++) for (int i = 0; i < message.msg_iovlen; i++)
TRY(regions.push_back(TRY(validate_and_pin_pointer_access(message.msg_iov[i].iov_base, message.msg_iov[i].iov_len, false)))); TRY(validate_and_pin_pointer_access(message.msg_iov[i].iov_base, message.msg_iov[i].iov_len, false, regions));
} }
return TRY(m_open_file_descriptors.sendmsg(socket, message, flags)); return TRY(m_open_file_descriptors.sendmsg(socket, message, flags));
@@ -2181,8 +2154,9 @@ namespace Kernel
BAN::ErrorOr<long> Process::sys_ppoll(pollfd* fds, nfds_t nfds, const timespec* user_timeout, const sigset_t* user_sigmask) BAN::ErrorOr<long> Process::sys_ppoll(pollfd* fds, nfds_t nfds, const timespec* user_timeout, const sigset_t* user_sigmask)
{ {
auto* fds_region = TRY(validate_and_pin_pointer_access(fds, nfds * sizeof(pollfd), true)); BAN::Vector<MemoryRegion*> regions;
BAN::ScopeGuard _([fds_region] { fds_region->unpin(); }); BAN::ScopeGuard _([&] { for (auto* region : regions) region->unpin(); });
TRY(validate_and_pin_pointer_access(fds, nfds * sizeof(pollfd), true, regions));
const auto old_sigmask = Thread::current().m_signal_block_mask; const auto old_sigmask = Thread::current().m_signal_block_mask;
if (user_sigmask != nullptr) if (user_sigmask != nullptr)
@@ -2364,8 +2338,9 @@ namespace Kernel
timeout.tv_nsec; timeout.tv_nsec;
} }
auto* events_region = TRY(validate_and_pin_pointer_access(events, maxevents * sizeof(epoll_event), true)); BAN::Vector<MemoryRegion*> regions;
BAN::ScopeGuard _([events_region] { events_region->unpin(); }); BAN::ScopeGuard _([&] { for (auto* region : regions) region->unpin(); });
TRY(validate_and_pin_pointer_access(events, maxevents * sizeof(epoll_event), true, regions));
const auto old_sigmask = Thread::current().m_signal_block_mask; const auto old_sigmask = Thread::current().m_signal_block_mask;
if (user_sigmask) if (user_sigmask)
@@ -2578,8 +2553,10 @@ namespace Kernel
if (BAN::Math::will_multiplication_overflow(list_len, sizeof(struct dirent))) if (BAN::Math::will_multiplication_overflow(list_len, sizeof(struct dirent)))
return BAN::Error::from_errno(EOVERFLOW); return BAN::Error::from_errno(EOVERFLOW);
auto* list_region = TRY(validate_and_pin_pointer_access(list, list_len * sizeof(struct dirent), true)); BAN::Vector<MemoryRegion*> regions;
BAN::ScopeGuard _([list_region] { list_region->unpin(); }); BAN::ScopeGuard _([&] { for (auto* region : regions) region->unpin(); });
TRY(validate_and_pin_pointer_access(list, list_len * sizeof(struct dirent), true, regions));
return TRY(m_open_file_descriptors.read_dir_entries(fd, list, list_len)); return TRY(m_open_file_descriptors.read_dir_entries(fd, list, list_len));
} }
@@ -3416,8 +3393,9 @@ namespace Kernel
const bool is_private = (op & FUTEX_PRIVATE); const bool is_private = (op & FUTEX_PRIVATE);
op &= ~(FUTEX_PRIVATE | FUTEX_REALTIME); op &= ~(FUTEX_PRIVATE | FUTEX_REALTIME);
auto* buffer_region = TRY(validate_and_pin_pointer_access(addr, sizeof(uint32_t), false)); BAN::Vector<MemoryRegion*> regions;
BAN::ScopeGuard pin_guard([buffer_region] { buffer_region->unpin(); }); BAN::ScopeGuard _0([&] { for (auto* region : regions) region->unpin(); });
TRY(validate_and_pin_pointer_access(addr, sizeof(uint32_t), false, regions));
const paddr_t paddr = m_page_table->physical_address_of(vaddr & PAGE_ADDR_MASK) | (vaddr & ~PAGE_ADDR_MASK); const paddr_t paddr = m_page_table->physical_address_of(vaddr & PAGE_ADDR_MASK) | (vaddr & ~PAGE_ADDR_MASK);
ASSERT(paddr != 0); ASSERT(paddr != 0);
@@ -3478,7 +3456,7 @@ namespace Kernel
} }
} }
LockGuard _(futex->mutex); LockGuard _1(futex->mutex);
switch (op) switch (op)
{ {
@@ -3561,8 +3539,9 @@ namespace Kernel
if (stack_vaddr % PAGE_SIZE || stack_size % PAGE_SIZE) if (stack_vaddr % PAGE_SIZE || stack_size % PAGE_SIZE)
return BAN::Error::from_errno(EINVAL); return BAN::Error::from_errno(EINVAL);
auto* memory_region = TRY(validate_and_pin_pointer_access(stack_base, stack_size, true)); BAN::Vector<MemoryRegion*> regions;
BAN::ScopeGuard _0([memory_region] { if (memory_region) memory_region->unpin(); }); BAN::ScopeGuard _0([&] { for (auto* region : regions) region->unpin(); });
TRY(validate_and_pin_pointer_access(stack_base, stack_size, true, regions));
const vaddr_t initial_stack_pointer = stack_vaddr + stack_size - sizeof(void*); const vaddr_t initial_stack_pointer = stack_vaddr + stack_size - sizeof(void*);
*reinterpret_cast<void**>(initial_stack_pointer) = arg; *reinterpret_cast<void**>(initial_stack_pointer) = arg;
@@ -3580,12 +3559,7 @@ namespace Kernel
LockGuard _1(m_process_lock); LockGuard _1(m_process_lock);
TRY(m_threads.push_back(thread)); TRY(m_threads.push_back(thread));
if (auto ret = Processor::scheduler().add_thread(thread); ret.is_error()) Processor::scheduler().add_thread(thread);
{
m_threads.pop_back();
delete thread;
return ret.release_error();
}
return thread->tid(); return thread->tid();
} }
@@ -4035,13 +4009,14 @@ namespace Kernel
if (BAN::Math::will_multiplication_overflow(count, sizeof(gid_t))) if (BAN::Math::will_multiplication_overflow(count, sizeof(gid_t)))
return BAN::Error::from_errno(EOVERFLOW); return BAN::Error::from_errno(EOVERFLOW);
LockGuard _(m_process_lock); LockGuard _0(m_process_lock);
if (!m_credentials.is_superuser()) if (!m_credentials.is_superuser())
return BAN::Error::from_errno(EPERM); return BAN::Error::from_errno(EPERM);
auto* region = TRY(validate_and_pin_pointer_access(groups, count * sizeof(gid_t), false)); BAN::Vector<MemoryRegion*> regions;
BAN::ScopeGuard pin_guard([region] { region->unpin(); }); BAN::ScopeGuard _1([&] { for (auto* region : regions) region->unpin(); });
TRY(validate_and_pin_pointer_access(groups, count * sizeof(gid_t), false, regions));
TRY(m_credentials.set_groups({ groups, count })); TRY(m_credentials.set_groups({ groups, count }));
@@ -4106,26 +4081,23 @@ namespace Kernel
return region->allocate_page_containing(address, wants_write); return region->allocate_page_containing(address, wants_write);
} }
BAN::ErrorOr<MemoryRegion*> Process::validate_and_pin_pointer_access(const void* ptr, size_t size, bool needs_write) BAN::ErrorOr<void> Process::validate_and_pin_pointer_access(const void* ptr, size_t size, bool needs_write, BAN::Vector<MemoryRegion*>& regions)
{ {
// TODO: allow pinning multiple regions? vaddr_t vaddr = reinterpret_cast<vaddr_t>(ptr);
const vaddr_t user_vaddr = reinterpret_cast<vaddr_t>(ptr);
{ {
RWLockRDGuard _(m_memory_region_lock); RWLockRDGuard _(m_memory_region_lock);
const size_t first_index = find_mapped_region(user_vaddr); const size_t first_index = find_mapped_region(vaddr);
for (size_t i = first_index; i < m_mapped_regions.size(); i++) for (size_t i = first_index; i < m_mapped_regions.size(); i++)
{ {
auto& region = m_mapped_regions[i]; const auto& region = m_mapped_regions[i];
if (user_vaddr >= region->vaddr() + region->size()) if (vaddr < region->vaddr())
break; break;
if (!region->contains_fully(user_vaddr, size))
continue;
const size_t page_count = range_page_count(user_vaddr, size); const vaddr_t min_vaddr_end = BAN::Math::min(vaddr + size, region->vaddr() + region->size());
const vaddr_t page_base = user_vaddr & PAGE_ADDR_MASK; const size_t page_count = range_page_count(vaddr, min_vaddr_end - vaddr);
const vaddr_t page_base = vaddr & PAGE_ADDR_MASK;
for (size_t p = 0; p < page_count; p++) for (size_t p = 0; p < page_count; p++)
{ {
const auto flags = PageTable::UserSupervisor | (needs_write ? PageTable::ReadWrite : 0) | PageTable::Present; const auto flags = PageTable::UserSupervisor | (needs_write ? PageTable::ReadWrite : 0) | PageTable::Present;
@@ -4133,8 +4105,15 @@ namespace Kernel
goto validate_and_pin_pointer_access_with_allocation; goto validate_and_pin_pointer_access_with_allocation;
} }
TRY(regions.push_back(region.ptr()));
region->pin(); region->pin();
return region.ptr();
if (region->contains(vaddr + size - 1))
return {};
const vaddr_t next_vaddr = region->vaddr() + region->size();
size -= next_vaddr - vaddr;
vaddr = next_vaddr;
} }
return BAN::Error::from_errno(EFAULT); return BAN::Error::from_errno(EFAULT);
@@ -4143,17 +4122,16 @@ namespace Kernel
validate_and_pin_pointer_access_with_allocation: validate_and_pin_pointer_access_with_allocation:
RWLockWRGuard _(m_memory_region_lock); RWLockWRGuard _(m_memory_region_lock);
const size_t first_index = find_mapped_region(user_vaddr); const size_t first_index = find_mapped_region(vaddr);
for (size_t i = first_index; i < m_mapped_regions.size(); i++) for (size_t i = first_index; i < m_mapped_regions.size(); i++)
{ {
auto& region = m_mapped_regions[i]; auto& region = m_mapped_regions[i];
if (user_vaddr >= region->vaddr() + region->size()) if (vaddr < region->vaddr())
break; break;
if (!region->contains_fully(user_vaddr, size))
continue;
const size_t page_count = range_page_count(user_vaddr, size); const vaddr_t min_vaddr_end = BAN::Math::min(vaddr + size, region->vaddr() + region->size());
const vaddr_t page_base = user_vaddr & PAGE_ADDR_MASK; const size_t page_count = range_page_count(vaddr, min_vaddr_end - vaddr);
const vaddr_t page_base = vaddr & PAGE_ADDR_MASK;
for (size_t p = 0; p < page_count; p++) for (size_t p = 0; p < page_count; p++)
{ {
const auto flags = PageTable::UserSupervisor | (needs_write ? PageTable::ReadWrite : 0) | PageTable::Present; const auto flags = PageTable::UserSupervisor | (needs_write ? PageTable::ReadWrite : 0) | PageTable::Present;
@@ -4163,8 +4141,15 @@ namespace Kernel
return BAN::Error::from_errno(EFAULT); return BAN::Error::from_errno(EFAULT);
} }
TRY(regions.push_back(region.ptr()));
region->pin(); region->pin();
return region.ptr();
if (region->contains(vaddr + size - 1))
return {};
const vaddr_t next_vaddr = region->vaddr() + region->size();
size -= next_vaddr - vaddr;
vaddr = next_vaddr;
} }
return BAN::Error::from_errno(EFAULT); return BAN::Error::from_errno(EFAULT);
+68 -84
View File
@@ -33,9 +33,6 @@ namespace Kernel
static SpinLock s_processor_info_time_lock; static SpinLock s_processor_info_time_lock;
static BAN::Array<ProcessorInfo, 0xFF> s_processor_infos; static BAN::Array<ProcessorInfo, 0xFF> s_processor_infos;
static BAN::Atomic<size_t> s_next_processor_index { 0 };
BAN::ErrorOr<Scheduler*> Scheduler::create() BAN::ErrorOr<Scheduler*> Scheduler::create()
{ {
auto* scheduler = new Scheduler(); auto* scheduler = new Scheduler();
@@ -151,7 +148,6 @@ namespace Kernel
if (&PageTable::current() != &PageTable::kernel()) if (&PageTable::current() != &PageTable::kernel())
PageTable::kernel().load(); PageTable::kernel().load();
delete m_current->thread; delete m_current->thread;
delete m_current;
m_thread_count--; m_thread_count--;
break; break;
case Thread::State::Executing: case Thread::State::Executing:
@@ -185,7 +181,6 @@ namespace Kernel
if (&PageTable::current() != &PageTable::kernel()) if (&PageTable::current() != &PageTable::kernel())
PageTable::kernel().load(); PageTable::kernel().load();
delete m_current->thread; delete m_current->thread;
delete m_current;
m_thread_count--; m_thread_count--;
} }
@@ -236,7 +231,7 @@ namespace Kernel
const uint64_t current_ns = SystemTimer::get().ns_since_boot(); const uint64_t current_ns = SystemTimer::get().ns_since_boot();
while (!m_block_list.empty() && current_ns >= m_block_list.front()->wake_time_ns) while (!m_block_list.empty() && current_ns >= m_block_list.front()->wake_time_ns)
unblock_thread(m_block_list.front()); unblock_thread(m_block_list.front()->thread);
} }
void Scheduler::update_wake_up_deadline() void Scheduler::update_wake_up_deadline()
@@ -300,60 +295,6 @@ namespace Kernel
update_wake_up_deadline(); update_wake_up_deadline();
} }
void Scheduler::unblock_thread(SchedulerThreadNode* node)
{
auto state = Processor::get_interrupt_state();
Processor::set_interrupt_state(InterruptState::Disabled);
if (node->processor_id == Processor::current_id())
{
if (!node->blocked)
return;
ASSERT(node != m_current);
Processor::set_disable_smp_messages(true);
m_block_list.pop(node);
if (auto* blocker = node->blocker.load())
blocker->remove_thread_from_block_queue(node);
node->blocked = false;
m_run_list.push(node);
update_most_loaded_node_list(node, &m_run_list);
Processor::set_disable_smp_messages(false);
}
else
{
Processor::send_smp_message(node->processor_id, {
.type = Processor::SMPMessage::Type::UnblockThread,
.unblock_thread = node
});
}
Processor::set_interrupt_state(state);
}
void Scheduler::add_thread(SchedulerThreadNode* node)
{
auto state = Processor::get_interrupt_state();
Processor::set_interrupt_state(InterruptState::Disabled);
ASSERT(node->processor_id == Processor::current_id());
if (!node->blocked)
m_run_list.push(node);
else
{
m_block_list.push(node);
if (m_block_list.front() == node)
update_wake_up_deadline();
}
if (auto* thread = node->thread; thread->is_userspace() && thread->has_process())
thread->update_processor_index_address();
m_thread_count++;
Processor::set_interrupt_state(state);
}
ProcessorID Scheduler::find_least_loaded_processor() const ProcessorID Scheduler::find_least_loaded_processor() const
{ {
ProcessorID least_loaded_id = Processor::current_id(); ProcessorID least_loaded_id = Processor::current_id();
@@ -535,7 +476,7 @@ namespace Kernel
thread_info.node->processor_id = least_loaded_id; thread_info.node->processor_id = least_loaded_id;
Processor::send_smp_message(least_loaded_id, { Processor::send_smp_message(least_loaded_id, {
.type = Processor::SMPMessage::Type::NewThread, .type = Processor::SMPMessage::Type::NewThread,
.new_thread = thread_info.node .new_thread = thread_info.node->thread
}); });
thread_info = { thread_info = {
@@ -563,41 +504,52 @@ namespace Kernel
m_last_load_balance_ns += s_load_balance_interval_ns; m_last_load_balance_ns += s_load_balance_interval_ns;
} }
BAN::ErrorOr<void> Scheduler::bind_thread_to_processor(Thread* thread, ProcessorID processor_id) void Scheduler::bind_thread_to_processor(Thread* thread, ProcessorID processor_id)
{ {
ASSERT(thread->m_scheduler_node == nullptr);
auto* new_node = new SchedulerThreadNode(thread);
if (new_node == nullptr)
return BAN::Error::from_errno(ENOMEM);
ASSERT(processor_id != PROCESSOR_NONE); ASSERT(processor_id != PROCESSOR_NONE);
new_node->processor_id = processor_id; ASSERT(thread->m_scheduler_node.processor_id == PROCESSOR_NONE);
thread->m_scheduler_node = new_node; thread->m_scheduler_node.processor_id = processor_id;
return {};
} }
BAN::ErrorOr<void> Scheduler::add_thread(Thread* thread) void Scheduler::add_thread(Thread* thread)
{ {
if (thread->m_scheduler_node == nullptr) ASSERT(thread);
if (thread->m_scheduler_node.processor_id == PROCESSOR_NONE)
{ {
static BAN::Atomic<size_t> s_next_processor_index { 0 };
const size_t processor_index = s_next_processor_index++ % Processor::count(); const size_t processor_index = s_next_processor_index++ % Processor::count();
const auto processor_id = Processor::id_from_index(processor_index); const auto processor_id = Processor::id_from_index(processor_index);
TRY(bind_thread_to_processor(thread, processor_id)); bind_thread_to_processor(thread, processor_id);
} }
auto* node = thread->m_scheduler_node; if (const auto proc_id = thread->m_scheduler_node.processor_id; proc_id != Processor::current_id())
if (node->processor_id == Processor::current_id()) {
add_thread(node); Processor::send_smp_message(proc_id, {
.type = Processor::SMPMessage::Type::NewThread,
.new_thread = thread
});
return;
}
const auto state = Processor::get_interrupt_state();
Processor::set_interrupt_state(InterruptState::Disabled);
if (!thread->m_scheduler_node.blocked)
m_run_list.push(&thread->m_scheduler_node);
else else
{ {
Processor::send_smp_message(node->processor_id, { m_block_list.push(&thread->m_scheduler_node);
.type = Processor::SMPMessage::Type::NewThread, if (m_block_list.front() == &thread->m_scheduler_node)
.new_thread = node update_wake_up_deadline();
});
} }
return {}; if (thread->is_userspace() && thread->has_process())
thread->update_processor_index_address();
m_thread_count++;
Processor::set_interrupt_state(state);
} }
void Scheduler::block_current_thread(ThreadBlocker* blocker, uint64_t wake_time_ns, BaseMutex* mutex) void Scheduler::block_current_thread(ThreadBlocker* blocker, uint64_t wake_time_ns, BaseMutex* mutex)
@@ -605,7 +557,7 @@ namespace Kernel
if (SystemTimer::get().ns_since_boot() >= wake_time_ns) if (SystemTimer::get().ns_since_boot() >= wake_time_ns)
return; return;
auto state = Processor::get_interrupt_state(); const auto state = Processor::get_interrupt_state();
Processor::set_interrupt_state(InterruptState::Disabled); Processor::set_interrupt_state(InterruptState::Disabled);
ASSERT(m_current->processor_id == Processor::current_id()); ASSERT(m_current->processor_id == Processor::current_id());
@@ -639,7 +591,39 @@ namespace Kernel
void Scheduler::unblock_thread(Thread* thread) void Scheduler::unblock_thread(Thread* thread)
{ {
unblock_thread(thread->m_scheduler_node); if (const auto proc_id = thread->m_scheduler_node.processor_id; proc_id != Processor::current_id())
{
Processor::send_smp_message(proc_id, {
.type = Processor::SMPMessage::Type::UnblockThread,
.unblock_thread = thread
});
return;
}
const auto state = Processor::get_interrupt_state();
Processor::set_interrupt_state(InterruptState::Disabled);
if (!thread->m_scheduler_node.blocked)
{
Processor::set_interrupt_state(state);
return;
}
ASSERT(&thread->m_scheduler_node != m_current);
Processor::set_disable_smp_messages(true);
m_block_list.pop(&thread->m_scheduler_node);
if (auto* blocker = thread->m_scheduler_node.blocker.load())
blocker->remove_thread_from_block_queue(&thread->m_scheduler_node);
thread->m_scheduler_node.blocked = false;
m_run_list.push(&thread->m_scheduler_node);
update_most_loaded_node_list(&thread->m_scheduler_node, &m_run_list);
Processor::set_disable_smp_messages(false);
Processor::set_interrupt_state(state);
} }
Thread& Scheduler::current_thread() Thread& Scheduler::current_thread()
@@ -102,10 +102,9 @@ namespace Kernel
void FramebufferTerminalDriver::show_cursor(bool use_data) void FramebufferTerminalDriver::show_cursor(bool use_data)
{ {
// NOTE: cursor is allowed to be on width as scrolling only if (m_cursor_x == width() || m_cursor_y == height())
// happens after character gets printed to next line
if (m_cursor_x == width())
return; return;
ASSERT(m_cursor_x < width() && m_cursor_y < height());
if (!use_data) if (!use_data)
read_cursor(); read_cursor();
+1 -1
View File
@@ -146,7 +146,7 @@ namespace Kernel
auto slave = m_slave.lock(); auto slave = m_slave.lock();
if (!slave) if (!slave)
return BAN::Error::from_errno(EIO); return BAN::Error::from_errno(EIO);
LockGuard _(slave->m_mutex); LockGuard _(slave->m_input_mutex);
for (size_t i = 0; i < buffer.size(); i++) for (size_t i = 0; i < buffer.size(); i++)
slave->handle_input_byte(buffer[i]); slave->handle_input_byte(buffer[i]);
return buffer.size(); return buffer.size();
+17 -16
View File
@@ -6,6 +6,7 @@
#include <kernel/FS/DevFS/FileSystem.h> #include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/FS/VirtualFileSystem.h> #include <kernel/FS/VirtualFileSystem.h>
#include <kernel/Input/InputDevice.h> #include <kernel/Input/InputDevice.h>
#include <kernel/Lock/BlockableSpinLock.h>
#include <kernel/Lock/LockGuard.h> #include <kernel/Lock/LockGuard.h>
#include <kernel/Process.h> #include <kernel/Process.h>
#include <kernel/Terminal/TTY.h> #include <kernel/Terminal/TTY.h>
@@ -81,7 +82,6 @@ namespace Kernel
BAN::RefPtr<TTY> TTY::current() BAN::RefPtr<TTY> TTY::current()
{ {
ASSERT(s_tty);
return s_tty; return s_tty;
} }
@@ -220,7 +220,7 @@ namespace Kernel
if (ansi_c_str == nullptr) if (ansi_c_str == nullptr)
return; return;
LockGuard _(m_mutex); LockGuard _(m_input_mutex);
while (*ansi_c_str) while (*ansi_c_str)
handle_input_byte(*ansi_c_str++); handle_input_byte(*ansi_c_str++);
after_write(); after_write();
@@ -269,7 +269,7 @@ namespace Kernel
bool should_flush = false; bool should_flush = false;
bool force_echo = false; bool force_echo = false;
LockGuard _(m_mutex); LockGuard _(m_input_mutex);
if (!(termios.c_lflag & ICANON)) if (!(termios.c_lflag & ICANON))
should_flush = true; should_flush = true;
@@ -377,7 +377,8 @@ namespace Kernel
const auto termios = get_termios(); const auto termios = get_termios();
LockGuard _(m_write_lock); SpinLockGuard _(m_write_lock);
if (termios.c_oflag & OPOST) if (termios.c_oflag & OPOST)
{ {
if ((termios.c_oflag & ONLCR) && ch == NL) if ((termios.c_oflag & ONLCR) && ch == NL)
@@ -385,14 +386,16 @@ namespace Kernel
if ((termios.c_oflag & OCRNL) && ch == CR) if ((termios.c_oflag & OCRNL) && ch == CR)
return putchar_impl(NL); return putchar_impl(NL);
} }
return putchar_impl(ch); return putchar_impl(ch);
} }
BAN::ErrorOr<size_t> TTY::read_impl(off_t, BAN::ByteSpan buffer) BAN::ErrorOr<size_t> TTY::read_impl(off_t, BAN::ByteSpan buffer)
{ {
LockGuard _(m_mutex); LockGuard _(m_input_mutex);
while (!m_output.flush) while (!m_output.flush)
TRY(Thread::current().block_or_eintr_indefinite(m_output.thread_blocker, &m_mutex)); TRY(Thread::current().block_or_eintr_indefinite(m_output.thread_blocker, &m_input_mutex));
if (m_output.buffer->empty()) if (m_output.buffer->empty())
{ {
@@ -424,13 +427,14 @@ namespace Kernel
BAN::ErrorOr<size_t> TTY::write_impl(off_t, BAN::ConstByteSpan buffer) BAN::ErrorOr<size_t> TTY::write_impl(off_t, BAN::ConstByteSpan buffer)
{ {
LockGuard write_guard(m_write_lock); SpinLockGuard _(m_write_lock);
while (!can_write()) while (!can_write())
{ {
if (master_has_closed()) if (master_has_closed())
return BAN::Error::from_errno(EIO); return BAN::Error::from_errno(EIO);
TRY(Thread::current().block_or_eintr_indefinite(m_write_blocker, &m_write_lock)); BlockableSpinLock block(m_write_lock);
TRY(Thread::current().block_or_eintr_indefinite(m_write_blocker, &block));
} }
size_t written = 0; size_t written = 0;
@@ -447,15 +451,12 @@ namespace Kernel
void TTY::putchar_current(uint8_t ch) void TTY::putchar_current(uint8_t ch)
{ {
ASSERT(s_tty); auto tty = s_tty;
ASSERT(tty);
while (!s_tty->m_write_lock.try_lock()) SpinLockGuard _(tty->m_write_lock);
Processor::pause(); tty->putchar(ch);
tty->after_write();
s_tty->putchar(ch);
s_tty->after_write();
s_tty->m_write_lock.unlock();
} }
bool TTY::is_initialized() bool TTY::is_initialized()
+39 -32
View File
@@ -50,34 +50,15 @@ namespace Kernel
, m_foreground(driver->palette()[15]) , m_foreground(driver->palette()[15])
, m_background(driver->palette()[0]) , m_background(driver->palette()[0])
{ {
m_width = m_terminal_driver->width(); MUST(set_terminal_driver(driver));
m_height = m_terminal_driver->height();
update_winsize(m_width, m_height);
m_buffer = new Cell[m_width * m_height];
ASSERT(m_buffer);
} }
void VirtualTTY::clear() BAN::ErrorOr<void> VirtualTTY::set_terminal_driver(BAN::RefPtr<TerminalDriver> terminal_driver)
{ {
LockGuard _(m_write_lock); const uint32_t new_width = terminal_driver->width();
for (uint32_t i = 0; i < m_width * m_height; i++) const uint32_t new_height = terminal_driver->height();
m_buffer[i] = { .foreground = m_foreground, .background = m_background, .codepoint = ' ' };
m_terminal_driver->clear(m_background);
}
BAN::ErrorOr<void> VirtualTTY::set_font(LibFont::Font&& font) SpinLockGuard _(m_write_lock);
{
if (!m_terminal_driver->has_font())
return BAN::Error::from_errno(EINVAL);
{
LockGuard _(m_write_lock);
TRY(m_terminal_driver->set_font(BAN::move(font)));
uint32_t new_width = m_terminal_driver->width();
uint32_t new_height = m_terminal_driver->height();
if (m_width != new_width || m_height != new_height) if (m_width != new_width || m_height != new_height)
{ {
@@ -97,19 +78,37 @@ namespace Kernel
m_height = new_height; m_height = new_height;
} }
m_terminal_driver = terminal_driver;
for (uint32_t y = 0; y < m_height; y++) for (uint32_t y = 0; y < m_height; y++)
for (uint32_t x = 0; x < m_width; x++) for (uint32_t x = 0; x < m_width; x++)
render_from_buffer(x, y); render_from_buffer(x, y);
update_winsize(new_width, new_height);
return {};
} }
update_winsize(m_width, m_height); void VirtualTTY::clear()
{
SpinLockGuard _(m_write_lock);
for (uint32_t i = 0; i < m_width * m_height; i++)
m_buffer[i] = { .foreground = m_foreground, .background = m_background, .codepoint = ' ' };
m_terminal_driver->clear(m_background);
}
BAN::ErrorOr<void> VirtualTTY::set_font(LibFont::Font&& font)
{
if (!m_terminal_driver->has_font())
return BAN::Error::from_errno(EINVAL);
TRY(m_terminal_driver->set_font(BAN::move(font)));
MUST(set_terminal_driver(m_terminal_driver));
return {}; return {};
} }
void VirtualTTY::reset_ansi() void VirtualTTY::reset_ansi()
{ {
ASSERT(m_write_lock.is_locked_by_current_thread()); ASSERT(m_write_lock.current_processor_has_lock());
m_ansi_state = { m_ansi_state = {
.nums = { -1, -1, -1, -1, -1 }, .nums = { -1, -1, -1, -1, -1 },
.index = 0, .index = 0,
@@ -120,7 +119,7 @@ namespace Kernel
void VirtualTTY::handle_ansi_csi_color(uint8_t value) void VirtualTTY::handle_ansi_csi_color(uint8_t value)
{ {
ASSERT(m_write_lock.is_locked_by_current_thread()); ASSERT(m_write_lock.current_processor_has_lock());
auto& palette = m_terminal_driver->palette(); auto& palette = m_terminal_driver->palette();
@@ -203,7 +202,8 @@ namespace Kernel
void VirtualTTY::handle_ansi_csi(uint8_t ch) void VirtualTTY::handle_ansi_csi(uint8_t ch)
{ {
ASSERT(m_write_lock.is_locked_by_current_thread()); ASSERT(m_write_lock.current_processor_has_lock());
switch (ch) switch (ch)
{ {
case '0' ... '9': case '0' ... '9':
@@ -427,10 +427,15 @@ namespace Kernel
case 'n': case 'n':
if (m_ansi_state.nums[0] == 6) if (m_ansi_state.nums[0] == 6)
{ {
// NOTE: this is very hacky but should be fine as long
// as kernel doesn't use this
while (!m_input_mutex.try_lock())
Processor::pause();
BAN::Formatter::print( BAN::Formatter::print(
[this](char ch) { handle_input_byte(ch); }, [this](char ch) { handle_input_byte(ch); },
"\e[{};{}R", m_row + 1, m_column + 1 "\e[{};{}R", m_row + 1, m_column + 1
); );
m_input_mutex.unlock();
return reset_ansi(); return reset_ansi();
}; };
reset_ansi(); reset_ansi();
@@ -445,7 +450,7 @@ namespace Kernel
void VirtualTTY::render_from_buffer(uint32_t x, uint32_t y) void VirtualTTY::render_from_buffer(uint32_t x, uint32_t y)
{ {
ASSERT(m_write_lock.is_locked_by_current_thread()); ASSERT(m_write_lock.current_processor_has_lock());
ASSERT(x < m_width && y < m_height); ASSERT(x < m_width && y < m_height);
const auto& cell = m_buffer[y * m_width + x]; const auto& cell = m_buffer[y * m_width + x];
m_terminal_driver->putchar_at(cell.codepoint, x, y, cell.foreground, cell.background); m_terminal_driver->putchar_at(cell.codepoint, x, y, cell.foreground, cell.background);
@@ -453,7 +458,7 @@ namespace Kernel
void VirtualTTY::putchar_at(uint32_t codepoint, uint32_t x, uint32_t y) void VirtualTTY::putchar_at(uint32_t codepoint, uint32_t x, uint32_t y)
{ {
ASSERT(m_write_lock.is_locked_by_current_thread()); ASSERT(m_write_lock.current_processor_has_lock());
ASSERT(x < m_width && y < m_height); ASSERT(x < m_width && y < m_height);
auto& cell = m_buffer[y * m_width + x]; auto& cell = m_buffer[y * m_width + x];
cell.codepoint = codepoint; cell.codepoint = codepoint;
@@ -464,6 +469,8 @@ namespace Kernel
void VirtualTTY::scroll_if_needed() void VirtualTTY::scroll_if_needed()
{ {
ASSERT(m_write_lock.current_processor_has_lock());
while (m_row >= m_height) while (m_row >= m_height)
{ {
memmove(m_buffer, m_buffer + m_width, m_width * (m_height - 1) * sizeof(Cell)); memmove(m_buffer, m_buffer + m_width, m_width * (m_height - 1) * sizeof(Cell));
@@ -487,7 +494,7 @@ namespace Kernel
void VirtualTTY::putcodepoint(uint32_t codepoint) void VirtualTTY::putcodepoint(uint32_t codepoint)
{ {
ASSERT(m_write_lock.is_locked_by_current_thread()); ASSERT(m_write_lock.current_processor_has_lock());
switch (codepoint) switch (codepoint)
{ {
@@ -533,7 +540,7 @@ namespace Kernel
bool VirtualTTY::putchar_impl(uint8_t ch) bool VirtualTTY::putchar_impl(uint8_t ch)
{ {
ASSERT(m_write_lock.is_locked_by_current_thread()); ASSERT(m_write_lock.current_processor_has_lock());
uint32_t codepoint = ch; uint32_t codepoint = ch;
+1
View File
@@ -240,6 +240,7 @@ namespace Kernel
Thread::Thread(pid_t tid, Process* process) Thread::Thread(pid_t tid, Process* process)
: m_tid(tid), m_process(process) : m_tid(tid), m_process(process)
, m_scheduler_node(this)
{ {
if (!s_default_sse_storage_initialized) if (!s_default_sse_storage_initialized)
initialize_default_sse_storage(); initialize_default_sse_storage();
+1 -1
View File
@@ -37,7 +37,7 @@ namespace Kernel
node->block_chain_prev = nullptr; node->block_chain_prev = nullptr;
node->block_chain_next = nullptr; node->block_chain_next = nullptr;
Processor::scheduler().unblock_thread(node); Processor::scheduler().unblock_thread(node->thread);
node = next; node = next;
} }
+3
View File
@@ -134,6 +134,9 @@ namespace Kernel
case USB::DeviceBaseClass::DiagnosticDevice: case USB::DeviceBaseClass::DiagnosticDevice:
dprintln_if(DEBUG_USB, "Found DiagnosticDevice device"); dprintln_if(DEBUG_USB, "Found DiagnosticDevice device");
return BAN::Error::from_errno(ENOTSUP); return BAN::Error::from_errno(ENOTSUP);
case USB::DeviceBaseClass::WirelessController:
dprintln_if(DEBUG_USB, "Found WirelessController device");
return BAN::Error::from_errno(ENOTSUP);
case USB::DeviceBaseClass::Miscellaneous: case USB::DeviceBaseClass::Miscellaneous:
dprintln_if(DEBUG_USB, "Found Miscellaneous device"); dprintln_if(DEBUG_USB, "Found Miscellaneous device");
return BAN::Error::from_errno(ENOTSUP); return BAN::Error::from_errno(ENOTSUP);
+1 -1
View File
@@ -218,7 +218,7 @@ namespace Kernel
} }
m_port_updater = TRY(Thread::create_kernel([](void* data) { reinterpret_cast<USBHubDriver*>(data)->port_updater_task(); }, this)); m_port_updater = TRY(Thread::create_kernel([](void* data) { reinterpret_cast<USBHubDriver*>(data)->port_updater_task(); }, this));
TRY(Processor::scheduler().add_thread(m_port_updater)); Processor::scheduler().add_thread(m_port_updater);
return {}; return {};
} }
+1 -1
View File
@@ -149,7 +149,7 @@ namespace Kernel
continue; continue;
m_port_updater = TRY(Thread::create_kernel([](void* data) { reinterpret_cast<XHCIController*>(data)->port_updater_task(); }, this)); m_port_updater = TRY(Thread::create_kernel([](void* data) { reinterpret_cast<XHCIController*>(data)->port_updater_task(); }, this));
TRY(Processor::scheduler().add_thread(m_port_updater)); Processor::scheduler().add_thread(m_port_updater);
return {}; return {};
} }
+49 -20
View File
@@ -68,6 +68,8 @@ static bool should_disable_serial(BAN::StringView full_command_line)
extern bool g_disable_debug; extern bool g_disable_debug;
static ParsedCommandLine cmdline; static ParsedCommandLine cmdline;
static bool s_has_early_console { false };
static void parse_command_line() static void parse_command_line()
{ {
auto full_command_line = Kernel::g_boot_info.command_line.sv(); auto full_command_line = Kernel::g_boot_info.command_line.sv();
@@ -160,7 +162,24 @@ extern "C" void kernel_main(uint32_t boot_magic, uint32_t boot_info)
if (auto ret = TerminalDriver::initialize_from_boot_info(); ret.is_error()) if (auto ret = TerminalDriver::initialize_from_boot_info(); ret.is_error())
dprintln("failed to initialize terminal driver: {}", ret.error()); dprintln("failed to initialize terminal driver: {}", ret.error());
else else
dprintln("terminal driver initialized"); {
MUST(VirtualTTY::create(g_terminal_driver));
dprintln("Virtual TTY initialized");
}
if (Serial::has_devices())
{
Serial::initialize_devices();
dprintln("Serial devices initialized");
}
if (auto ret = DevFileSystem::get().root_inode()->find_inode(cmdline.console); !ret.is_error())
{
auto console = ret.release_value();
ASSERT(console->is_tty());
static_cast<Kernel::TTY*>(console.ptr())->set_as_current();
s_has_early_console = true;
}
if (!cmdline.disable_smp) if (!cmdline.disable_smp)
InterruptController::get().initialize_multiprocessor(); InterruptController::get().initialize_multiprocessor();
@@ -171,18 +190,6 @@ extern "C" void kernel_main(uint32_t boot_magic, uint32_t boot_info)
MUST(SharedMemoryObjectManager::initialize()); MUST(SharedMemoryObjectManager::initialize());
dprintln("Shared memory object system initialized"); dprintln("Shared memory object system initialized");
if (Serial::has_devices())
{
Serial::initialize_devices();
dprintln("Serial devices initialized");
}
if (g_terminal_driver)
{
auto vtty = MUST(VirtualTTY::create(g_terminal_driver));
dprintln("Virtual TTY initialized");
}
Random::initialize(); Random::initialize();
dprintln("RNG initialized"); dprintln("RNG initialized");
@@ -196,7 +203,7 @@ extern "C" void kernel_main(uint32_t boot_magic, uint32_t boot_info)
MUST(Processor::scheduler().initialize()); MUST(Processor::scheduler().initialize());
auto* init_thread = MUST(Thread::create_kernel(init2, nullptr)); auto* init_thread = MUST(Thread::create_kernel(init2, nullptr));
MUST(Processor::scheduler().add_thread(init_thread)); Processor::scheduler().add_thread(init_thread);
Processor::yield(); Processor::yield();
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
@@ -213,10 +220,6 @@ static void init2(void*)
ProcFileSystem::get().post_scheduler_initialize(); ProcFileSystem::get().post_scheduler_initialize();
auto console = MUST(DevFileSystem::get().root_inode()->find_inode(cmdline.console));
ASSERT(console->is_tty());
static_cast<Kernel::TTY*>(console.ptr())->set_as_current();
// This only initializes PCIManager by enumerating available devices and choosing PCIe/legacy // This only initializes PCIManager by enumerating available devices and choosing PCIe/legacy
// ACPI might require PCI access during its namespace initialization // ACPI might require PCI access during its namespace initialization
PCI::PCIManager::initialize(); PCI::PCIManager::initialize();
@@ -256,6 +259,32 @@ static void init2(void*)
PCI::PCIManager::get().initialize_devices(cmdline.disable_usb); PCI::PCIManager::get().initialize_devices(cmdline.disable_usb);
dprintln("PCI devices initialized"); dprintln("PCI devices initialized");
if (!s_has_early_console)
{
auto console_or_error = DevFileSystem::get().root_inode()->find_inode(cmdline.console);
if (!console_or_error.is_error())
{
auto console = console_or_error.release_value();
ASSERT(console->is_tty());
static_cast<TTY*>(console.ptr())->set_as_current();
}
else
{
BAN::RefPtr<TTY> tty;
DevFileSystem::get().for_each_inode([&](BAN::RefPtr<Inode> inode) -> BAN::Iteration {
if (!inode->is_tty())
return BAN::Iteration::Continue;
tty = static_cast<TTY*>(inode.ptr());
return BAN::Iteration::Break;
});
ASSERT(tty);
dwarnln("Could not find /dev/{}, falling back to /dev/{}", cmdline.console, tty->name());
tty->set_as_current();
}
}
VirtualFileSystem::initialize(cmdline.root); VirtualFileSystem::initialize(cmdline.root);
dprintln("VFS initialized"); dprintln("VFS initialized");
@@ -266,9 +295,9 @@ static void init2(void*)
Banos::initialize_initial_drivers(); Banos::initialize_initial_drivers();
auto console_path = MUST(BAN::String::formatted("/dev/{}", cmdline.console)); auto console_path = MUST(BAN::String::formatted("/dev/{}", TTY::current()->name()));
auto console_path_sv = console_path.sv(); auto console_path_sv = console_path.sv();
MUST(Process::create_userspace({ 0, 0, 0, 0 }, "/usr/bin/init"_sv, BAN::Span<BAN::StringView>(&console_path_sv, 1))); MUST(Process::create_userspace({ 0, 0, 0, 0 }, "/usr/bin/init"_sv, { &console_path_sv, 1 }));
} }
extern "C" void ap_main() extern "C" void ap_main()
+31
View File
@@ -0,0 +1,31 @@
#!/bin/bash ../install.sh
NAME='AppStream'
VERSION='1.1.2'
DOWNLOAD_URL="https://www.freedesktop.org/software/appstream/releases/AppStream-$VERSION.tar.xz#46b4257100e25a6468ceed7b3ab82441f47b119da3398d30aea6d7b91174b586"
DEPENDENCIES=('glib' 'curl' 'libxml2' 'libfyaml')
CONFIGURE_OPTIONS=(
'-Dprefix=/usr'
'-Dbuildtype=release'
'-Dbash-completion=false'
'-Dgir=false'
'-Dman=false'
'-Dstemming=false'
'-Dsystemd=false'
)
configure() {
meson setup \
--reconfigure \
--cross-file "$MESON_CROSS_FILE" \
"${CONFIGURE_OPTIONS[@]}" \
build || exit 1
}
build() {
meson compile -C build || exit 1
}
install() {
meson install --destdir="$DESTDIR" -C build || exit 1
}
@@ -0,0 +1,12 @@
diff -ruN AppStream-1.1.2/data/meson.build AppStream-1.1.2-banan_os/data/meson.build
--- AppStream-1.1.2/data/meson.build 2026-01-28 22:15:58.000000000 +0200
+++ AppStream-1.1.2-banan_os/data/meson.build 2026-03-25 04:09:17.550968139 +0200
@@ -9,8 +9,6 @@
# Do not rely on an exe wrapper for rel-info, use the system one in that case
if meson.is_cross_build()
- dependency('appstream', version: '>=' + as_version, native: true,
- not_found_message: 'Native appstream required for cross-building')
ascli_exe = find_program('appstreamcli', native: true)
endif
@@ -0,0 +1,12 @@
diff -ruN AppStream-1.1.2/src/as-system-info.c AppStream-1.1.2-banan_os/src/as-system-info.c
--- AppStream-1.1.2/src/as-system-info.c 2026-01-28 22:15:58.000000000 +0200
+++ AppStream-1.1.2-banan_os/src/as-system-info.c 2026-03-25 04:08:32.249321186 +0200
@@ -513,7 +513,7 @@
return 0;
}
return hbi.memory_size / MB_IN_BYTES;
-#elif defined(__sun)
+#elif defined(__sun) || defined(__banan_os__)
long physpages = sysconf (_SC_PHYS_PAGES);
long pagesize = sysconf (_SC_PAGESIZE);
if (physpages > 0 && pagesize > 0)
+1
View File
@@ -19,5 +19,6 @@ build() {
} }
install() { install() {
mkdir -p "$DESTDIR/usr/bin"
cp -v bin/gcc/$specseek_arch/specseek_$specseek_arch "$DESTDIR/usr/bin/specseek" || exit 1 cp -v bin/gcc/$specseek_arch/specseek_$specseek_arch "$DESTDIR/usr/bin/specseek" || exit 1
} }
+35
View File
@@ -0,0 +1,35 @@
#!/bin/bash ../install.sh
NAME='babl'
VERSION='0.1.124'
DOWNLOAD_URL="https://download.gimp.org/pub/babl/0.1/babl-$VERSION.tar.xz#1b0d544ab6f409f2b1b5f677226272d1e8c6d373f2f453ee870bfc7e5dd4f1b1"
DEPENDENCIES=('lcms2')
CONFIGURE_OPTIONS=(
'-Dprefix=/usr'
'-Dbuildtype=release'
'-Dwith-docs=false'
'-Denable-gir=false'
'-Denable-vapi=false'
'-Dgi-docgen=disabled'
'-Denable-avx2=false'
)
configure() {
meson setup \
--reconfigure \
--cross-file "$MESON_CROSS_FILE" \
"${CONFIGURE_OPTIONS[@]}" \
build || exit 1
}
post_configure() {
grep -q '<alloca.h>' build/config.h || echo '#include <alloca.h>' >> build/config.h
}
build() {
meson compile -C build || exit 1
}
install() {
meson install --destdir="$DESTDIR" -C build || exit 1
}
+2 -2
View File
@@ -16,7 +16,7 @@ CONFIGURE_OPTIONS=(
) )
post_install() { post_install() {
if [ ! -L $DESTDIR/usr/bin/sh ]; then if [ ! -L "$DESTDIR/usr/bin/sh" ]; then
ln -s bash $DESTDIR/usr/bin/sh ln -sv "bash $DESTDIR/usr/bin/sh"
fi fi
} }
+4 -2
View File
@@ -17,9 +17,11 @@ configure() {
} }
build() { build() {
./b2 --user-config=user-config.jam toolset=gcc target-os=banan_os || exit 1 ./b2 --user-config=user-config.jam \
toolset=gcc target-os=banan_os || exit 1
} }
install() { install() {
./b2 --user-config=user-config.jam toolset=gcc target-os=banan_os install || exit 1 ./b2 --user-config=user-config.jam --prefix="$DESTDIR/usr" \
toolset=gcc target-os=banan_os install || exit 1
} }
+2 -1
View File
@@ -22,7 +22,8 @@ install() {
mkdir -p "$DESTDIR/usr/include" mkdir -p "$DESTDIR/usr/include"
cp -v bzlib.h "$DESTDIR/usr/include/" || exit 1 cp -v bzlib.h "$DESTDIR/usr/include/" || exit 1
cat > $DESTDIR/usr/lib/pkgconfig/bzip2.pc << EOF mkdir -p "$DESTDIR/usr/lib/pkgconfig"
cat > "$DESTDIR/usr/lib/pkgconfig/bzip2.pc" << EOF
prefix=/usr prefix=/usr
exec_prefix=\${prefix} exec_prefix=\${prefix}
bindir=\${exec_prefix}/bin bindir=\${exec_prefix}/bin
+1 -1
View File
@@ -11,7 +11,7 @@ configure() {
build() { build() {
if [ ! -f ../doom1.wad ]; then if [ ! -f ../doom1.wad ]; then
wget https://distro.ibiblio.org/slitaz/sources/packages/d/doom1.wad -O ../doom1.wad || exit 1 wget 'https://bananymous.com/files/doom1.wad' -O ../doom1.wad || exit 1
fi fi
make -C doomgeneric -f Makefile.sdl CC="$CC" SDL_PATH="$BANAN_SYSROOT/usr/bin/" || exit 1 make -C doomgeneric -f Makefile.sdl CC="$CC" SDL_PATH="$BANAN_SYSROOT/usr/bin/" || exit 1
+26
View File
@@ -0,0 +1,26 @@
#!/bin/bash ../install.sh
NAME='exiv2'
VERSION='0.28.8'
DOWNLOAD_URL="https://github.com/Exiv2/exiv2/archive/refs/tags/v$VERSION.tar.gz#ea51b0609f58a9afa063b60daa1539948b62247721e154f4fff0ad3aec9f9756"
DEPENDENCIES=('zlib' 'expat')
configure() {
cmake --fresh -B build -S . -G Ninja \
--toolchain="$BANAN_TOOLCHAIN_DIR/Toolchain.txt" \
-DCMAKE_INSTALL_PREFIX=/usr \
-DCMAKE_BUILD_TYPE=Release \
-DEXIV2_ENABLE_NLS=OFF \
-DEXIV2_ENABLE_BROTLI=OFF \
-DEXIV2_ENABLE_INIH=OFF \
-DBUILD_WITH_STACK_PROTECTOR=OFF \
|| exit 1
}
build() {
cmake --build build || exit 1
}
install() {
DESTDIR="$DESTDIR" cmake --install build || exit 1
}
+3 -1
View File
@@ -12,11 +12,13 @@ CONFIGURE_OPTIONS=(
"--cxx=$CXX" "--cxx=$CXX"
'--enable-cross-compile' '--enable-cross-compile'
'--enable-shared' '--enable-shared'
'--disable-static'
'--disable-doc'
'--enable-gpl' '--enable-gpl'
'--enable-version3' '--enable-version3'
'--enable-openssl' '--enable-openssl'
) )
configure() { configure() {
./configure "${CONFIGURE_OPTIONS[@]}" ./configure "${CONFIGURE_OPTIONS[@]}" || exit 1
} }
+1 -1
View File
@@ -3,7 +3,7 @@
NAME='fontconfig' NAME='fontconfig'
VERSION='2.17.1' VERSION='2.17.1'
DOWNLOAD_URL="https://gitlab.freedesktop.org/fontconfig/fontconfig/-/archive/$VERSION/fontconfig-$VERSION.tar.gz#82e73b26adad651b236e5f5d4b3074daf8ff0910188808496326bd3449e5261d" DOWNLOAD_URL="https://gitlab.freedesktop.org/fontconfig/fontconfig/-/archive/$VERSION/fontconfig-$VERSION.tar.gz#82e73b26adad651b236e5f5d4b3074daf8ff0910188808496326bd3449e5261d"
DEPENDENCIES=('harfbuzz' 'freetype' 'expat' 'libiconv' 'dejavu-fonts-ttf') DEPENDENCIES=('freetype' 'expat' 'libiconv' 'dejavu-fonts-ttf')
CONFIGURE_OPTIONS=( CONFIGURE_OPTIONS=(
'-Dprefix=/usr' '-Dprefix=/usr'
'-Dbuildtype=release' '-Dbuildtype=release'
+20 -2
View File
@@ -5,6 +5,24 @@ VERSION='2.14.3'
DOWNLOAD_URL="https://download.savannah.gnu.org/releases/freetype/freetype-$VERSION.tar.xz#36bc4f1cc413335368ee656c42afca65c5a3987e8768cc28cf11ba775e785a5f" DOWNLOAD_URL="https://download.savannah.gnu.org/releases/freetype/freetype-$VERSION.tar.xz#36bc4f1cc413335368ee656c42afca65c5a3987e8768cc28cf11ba775e785a5f"
DEPENDENCIES=('zlib' 'libpng') DEPENDENCIES=('zlib' 'libpng')
CONFIGURE_OPTIONS=( CONFIGURE_OPTIONS=(
'--disable-static' '-Dprefix=/usr'
'lt_cv_deplibs_check_method=pass_all' '-Dbuildtype=release'
'-Dharfbuzz=dynamic'
'-Dc_link_args=-lgcc_s' # something is messed up with my toolchain
) )
configure() {
meson setup \
--reconfigure \
--cross-file "$MESON_CROSS_FILE" \
"${CONFIGURE_OPTIONS[@]}" \
build || exit 1
}
build() {
meson compile -C build || exit 1
}
install() {
meson install --destdir="$DESTDIR" -C build || exit 1
}
+9
View File
@@ -26,3 +26,12 @@ build() {
install() { install() {
meson install --destdir="$DESTDIR" -C build || exit 1 meson install --destdir="$DESTDIR" -C build || exit 1
} }
post_install() {
mkdir -p "$DESTDIR/etc/init.d"
cat > "$DESTDIR/etc/init.d/gdk-pixbuf-update-loaders" << EOF
#!/bin/Shell
exec gdk-pixbuf-query-loaders --update-cache
EOF
chmod +x "$DESTDIR/etc/init.d/gdk-pixbuf-update-loaders"
}
+26
View File
@@ -0,0 +1,26 @@
#!/bin/bash ../install.sh
NAME='gegl'
VERSION='0.4.70'
DOWNLOAD_URL="https://download.gimp.org/gegl/0.4/gegl-$VERSION.tar.xz#47f50d9c3aecd375deb48c11ebfead52d162e4fc162a4b3d44618277f1faec02"
DEPENDENCIES=('json-glib' 'babl' 'libjpeg-turbo' 'libpng')
CONFIGURE_OPTIONS=(
'-Dprefix=/usr'
'-Dbuildtype=release'
)
configure() {
meson setup \
--reconfigure \
--cross-file "$MESON_CROSS_FILE" \
"${CONFIGURE_OPTIONS[@]}" \
build || exit 1
}
build() {
meson compile -C build || exit 1
}
install() {
meson install --destdir="$DESTDIR" -C build || exit 1
}
+9
View File
@@ -0,0 +1,9 @@
#!/bin/bash
REVISION=1
source 'build.sh'
[[ "$VERSION" == 'git' ]] && VERSION=0.0
echo "${NAME}-${VERSION//[_-]/.}_${REVISION}.${BANAN_ARCH}"
+31
View File
@@ -0,0 +1,31 @@
#!/bin/bash ../install.sh
NAME='gexiv2'
VERSION='0.14.6' # gimp requires 0.14.x
DOWNLOAD_URL="https://github.com/GNOME/gexiv2/archive/refs/tags/gexiv2-$VERSION.tar.gz#9083050df329b630f71f6f71aafc193c26e46548854ae21037d0a679ef62ae50"
TAR_CONTENT="gexiv2-gexiv2-$VERSION"
DEPENDENCIES=('exiv2' 'glib')
CONFIGURE_OPTIONS=(
'-Dprefix=/usr'
'-Dbuildtype=release'
'-Dintrospection=false'
'-Dvapi=false'
'-Dpython3=false'
'-Dtests=false'
)
configure() {
meson setup \
--reconfigure \
--cross-file "$MESON_CROSS_FILE" \
"${CONFIGURE_OPTIONS[@]}" \
build || exit 1
}
build() {
meson compile -C build || exit 1
}
install() {
meson install --destdir="$DESTDIR" -C build || exit 1
}
+33
View File
@@ -0,0 +1,33 @@
#!/bin/bash ../install.sh
NAME='gimp'
VERSION='3.2.4'
DOWNLOAD_URL="https://download.gimp.org/gimp/v3.2/gimp-$VERSION.tar.xz#7312bc53e9c6d2d0056ca7b93f1c6b98707946dd934f714c21b8746ecb601588"
DEPENDENCIES=('gtk3' 'gegl' 'gexiv2' 'glib-networking' 'librsvg' 'lcms2' 'libmypaint' 'mypaint-brushes' 'AppStream' 'libarchive' 'libXmu' 'poppler')
CONFIGURE_OPTIONS=(
'-Dprefix=/usr'
'-Dbuildtype=release'
'-Dshmem-type=sysv'
'-Dgi-docgen=disabled'
)
pre_configure() {
# allow native pkgconfig lookup
unset PKG_CONFIG_DIR PKG_CONFIG_SYSROOT_DIR PKG_CONFIG_LIBDIR PKG_CONFIG_PATH
}
configure() {
meson setup \
--reconfigure \
--cross-file "$MESON_CROSS_FILE" \
"${CONFIGURE_OPTIONS[@]}" \
_build || exit 1
}
build() {
meson compile -C _build || exit 1
}
install() {
meson install --destdir="$DESTDIR" -C _build || exit 1
}
@@ -0,0 +1,21 @@
diff -ruN gimp-3.2.4/meson.build gimp-3.2.4-banan_os/meson.build
--- gimp-3.2.4/meson.build 2026-04-17 11:37:38.000000000 +0300
+++ gimp-3.2.4-banan_os/meson.build 2026-08-24 21:47:23.319981280 +0300
@@ -573,7 +573,7 @@
pangoft2 = dependency('pangoft2', version: '>='+pango_minver)
endif
-if cc.run('''
+if meson.can_run_host_binaries() and cc.run('''
#include <pango/pango.h>
#include <string.h>
#include <stdlib.h>
@@ -1580,7 +1580,7 @@
endif
if shmem_choice == 'sysv'
- check_ip_rmid_deferred_release = cc.run('''
+ check_ip_rmid_deferred_release = host_os.contains('banan_os') or cc.run('''
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
@@ -0,0 +1,13 @@
diff -ruN gimp-3.2.4/libgimp/gimpplugin.c gimp-3.2.4-banan_os/libgimp/gimpplugin.c
--- gimp-3.2.4/libgimp/gimpplugin.c 2026-04-17 11:37:38.000000000 +0300
+++ gimp-3.2.4-banan_os/libgimp/gimpplugin.c 2026-08-24 21:47:23.319160010 +0300
@@ -24,6 +24,9 @@
#include <errno.h>
#include <libintl.h>
#include <string.h>
+#ifdef __banan_os__
+#include <sys/select.h>
+#endif
#include "gimp.h"
@@ -0,0 +1,32 @@
diff -ruN gimp-3.2.4/meson.build gimp-3.2.4-banan_os/meson.build
--- gimp-3.2.4/meson.build 2026-04-17 11:37:38.000000000 +0300
+++ gimp-3.2.4-banan_os/meson.build 2026-08-24 21:47:23.319981280 +0300
@@ -486,7 +486,7 @@
# minimum requirement.
add_project_arguments('-DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_76', language: 'c')
-gi = dependency('gobject-introspection-1.0')
+gi = dependency('gobject-introspection-1.0', required: false)
gobject = dependency('gobject-2.0', version: '>='+glib_minver)
gmodule = dependency('gmodule-no-export-2.0')
diff -ruN gimp-3.2.4/plug-ins/meson.build gimp-3.2.4-banan_os/plug-ins/meson.build
--- gimp-3.2.4/plug-ins/meson.build 2026-04-17 11:37:38.000000000 +0300
+++ gimp-3.2.4-banan_os/plug-ins/meson.build 2026-08-24 21:47:23.320319594 +0300
@@ -35,10 +35,15 @@
{ 'name': 'pagecurl', },
{ 'name': 'print', },
{ 'name': 'screenshot', },
- { 'name': 'script-fu', },
{ 'name': 'selection-to-path', }
]
+if gi.found()
+ comples_plugins_list += {
+ 'name': 'script-fu',
+ }
+endif
+
if openexr.found()
complex_plugins_list += {
'name': 'file-exr',
+31
View File
@@ -0,0 +1,31 @@
#!/bin/bash ../install.sh
NAME='glib-networking'
VERSION='2.80.1'
DOWNLOAD_URL="https://download.gnome.org/sources/glib-networking/${VERSION%.*}/glib-networking-$VERSION.tar.xz#b80e2874157cd55071f1b6710fa0b911d5ac5de106a9ee2a4c9c7bee61782f8e"
DEPENDENCIES=('glib' 'openssl')
CONFIGURE_OPTIONS=(
'-Dprefix=/usr'
'-Dbuildtype=release'
'-Dlibproxy=disabled'
'-Dgnome_proxy=disabled'
'-Dgnutls=disabled'
'-Dopenssl=enabled'
'-Dc_link_args=-lgcc_s' # something is messed up with my toolchain
)
configure() {
meson setup \
--reconfigure \
--cross-file "$MESON_CROSS_FILE" \
"${CONFIGURE_OPTIONS[@]}" \
build || exit 1
}
build() {
meson compile -C build || exit 1
}
install() {
meson install --destdir="$DESTDIR" -C build || exit 1
}
@@ -0,0 +1,13 @@
diff -ruN glib-networking-2.80.1/meson.build glib-networking-2.80.1-banan_os/meson.build
--- glib-networking-2.80.1/meson.build 2025-01-08 23:51:06.000000000 +0200
+++ glib-networking-2.80.1-banan_os/meson.build 2026-08-24 21:00:58.043148228 +0300
@@ -63,8 +63,7 @@
gobject_dep = dependency('gobject-2.0')
gmodule_dep = dependency('gmodule-2.0')
-gio_module_dir = gio_dep.get_variable('giomoduledir',
- pkgconfig_define: ['libdir', join_paths(prefix, libdir)])
+gio_module_dir = join_paths(prefix, libdir, 'gio', 'modules')
assert(gio_module_dir != '', 'GIO_MODULE_DIR is missing from gio-2.0.pc')
# *** Checks for LibProxy ***
+9
View File
@@ -25,3 +25,12 @@ build() {
install() { install() {
meson install --destdir="$DESTDIR" -C build || exit 1 meson install --destdir="$DESTDIR" -C build || exit 1
} }
post_install() {
mkdir -p "$DESTDIR/etc/init.d"
cat > "$DESTDIR/etc/init.d/glib-compile-schemas" << EOF
#!/bin/Shell
exec glib-compile-schemas /usr/share/glib-2.0/schemas
EOF
chmod +x "$DESTDIR/etc/init.d/glib-compile-schemas"
}
+2 -1
View File
@@ -1,8 +1,9 @@
#!/bin/bash ../install.sh #!/bin/bash ../install.sh
NAME='gtk' NAME='gtk3'
VERSION='3.24.49' VERSION='3.24.49'
DOWNLOAD_URL="https://gitlab.gnome.org/GNOME/gtk/-/archive/$VERSION/gtk-$VERSION.tar.gz#a2958d82986c81794e953a3762335fa7c78948706d23cced421f7245ca544cbc" DOWNLOAD_URL="https://gitlab.gnome.org/GNOME/gtk/-/archive/$VERSION/gtk-$VERSION.tar.gz#a2958d82986c81794e953a3762335fa7c78948706d23cced421f7245ca544cbc"
TAR_CONTENT="gtk-$VERSION"
DEPENDENCIES=('glib' 'gdk-pixbuf' 'pango' 'libatk' 'libepoxy' 'libXrandr' 'libXcursor' 'libXinerama') DEPENDENCIES=('glib' 'gdk-pixbuf' 'pango' 'libatk' 'libepoxy' 'libXrandr' 'libXcursor' 'libXinerama')
CONFIGURE_OPTIONS=( CONFIGURE_OPTIONS=(
'-Dprefix=/usr' '-Dprefix=/usr'
+2 -17
View File
@@ -1,8 +1,8 @@
#!/bin/bash ../install.sh #!/bin/bash ../install.sh
NAME='harfbuzz' NAME='harfbuzz'
VERSION='12.2.0' VERSION='14.3.1'
DOWNLOAD_URL="https://github.com/harfbuzz/harfbuzz/releases/download/$VERSION/harfbuzz-$VERSION.tar.xz#ecb603aa426a8b24665718667bda64a84c1504db7454ee4cadbd362eea64e545" DOWNLOAD_URL="https://github.com/harfbuzz/harfbuzz/releases/download/$VERSION/harfbuzz-$VERSION.tar.xz#9dae9538aae2ffdf70cec31f2c27bf68e2aaeeae3112688467697d5faf6194f7"
DEPENDENCIES=('glib' 'freetype' 'icu') DEPENDENCIES=('glib' 'freetype' 'icu')
CONFIGURE_OPTIONS=( CONFIGURE_OPTIONS=(
'-Dprefix=/usr' '-Dprefix=/usr'
@@ -26,18 +26,3 @@ build() {
install() { install() {
meson install --destdir="$DESTDIR" -C build || exit 1 meson install --destdir="$DESTDIR" -C build || exit 1
} }
post_install() {
if [ -n "$HARFBUZZ_CIRCULAR" ]; then
return
fi
export HARFBUZZ_CIRCULAR=1
for circular in freetype cairo; do
pushd "$BANAN_PORT_DIR/$circular" >/dev/null || exit 1
rm -f .compile_hash
./build.sh || exit 1
popd >/dev/null
done
}
+55 -4
View File
@@ -15,8 +15,12 @@ installed_file="$BANAN_PORT_DIR/.installed_ports"
if [ -z $DONT_REMOVE_INSTALLED ]; then if [ -z $DONT_REMOVE_INSTALLED ]; then
export DONT_REMOVE_INSTALLED=1 export DONT_REMOVE_INSTALLED=1
rm -f "$installed_file" rm -f "$installed_file"
rm -rf "$BANAN_SYSROOT/var/db/xbps"
fi fi
PACKAGE_ROOT="$BANAN_PORT_DIR/package"
PACKAGE_REPO="$PACKAGE_ROOT/repo"
export PATH="$BANAN_TOOLCHAIN_PREFIX/bin:$PATH" export PATH="$BANAN_TOOLCHAIN_PREFIX/bin:$PATH"
export PKG_CONFIG_DIR='' export PKG_CONFIG_DIR=''
@@ -54,6 +58,8 @@ MAKE_INSTALL_TARGETS=('install')
CONFIG_SUB=() CONFIG_SUB=()
REVISION=1
clean() { clean() {
find . -mindepth 1 -maxdepth 1 -not -name 'patches' -not -name 'build.sh' -exec rm -rf {} + find . -mindepth 1 -maxdepth 1 -not -name 'patches' -not -name 'build.sh' -exec rm -rf {} +
} }
@@ -111,11 +117,15 @@ post_install() {
install() { install() {
for target in "${MAKE_INSTALL_TARGETS[@]}"; do for target in "${MAKE_INSTALL_TARGETS[@]}"; do
make $target "DESTDIR=$BANAN_SYSROOT" || exit 1 make $target "DESTDIR=$DESTDIR" || exit 1
done done
} }
source $1 source "$1"
if [ -z $DESCRIPTION ]; then
DESCRIPTION="TODO description for $NAME"
fi
if [ -z $NAME ] || [ -z $VERSION ] || [ -z $DOWNLOAD_URL ]; then if [ -z $NAME ] || [ -z $VERSION ] || [ -z $DOWNLOAD_URL ]; then
echo "Port does not set needed environment variables" >&2 echo "Port does not set needed environment variables" >&2
@@ -148,7 +158,16 @@ for dependency in "${DEPENDENCIES[@]}"; do
pushd "../$dependency" >/dev/null pushd "../$dependency" >/dev/null
pwd pwd
if ! ./build.sh; then
version_string="$(../get-version-string.sh)"
if [ -f "$PACKAGE_REPO/$version_string.xbps" ]; then
run_xbps xbps-install \
-r "$BANAN_SYSROOT" \
-R "$PACKAGE_REPO" \
-y "$dependency" \
|| exit 1
echo "${version_string%%_*}" >> "$installed_file"
elif ! ./build.sh; then
echo "Failed to install dependency '$dependency' of port '$NAME'" echo "Failed to install dependency '$dependency' of port '$NAME'"
exit 1 exit 1
fi fi
@@ -255,6 +274,38 @@ fi
DESTDIR="$BANAN_SYSROOT" DESTDIR="$BANAN_SYSROOT"
pre_install pre_install
install install
grep -qsxF "$NAME-$VERSION" "$installed_file" || echo "$NAME-$VERSION" >> "$installed_file"
post_install post_install
find "$BANAN_SYSROOT/usr/lib" -name '*.la' -delete find "$BANAN_SYSROOT/usr/lib" -name '*.la' -delete
rm -f "$BANAN_SYSROOT/usr/share/info/dir"
grep -qsxF "$NAME-$VERSION" "$installed_file" || echo "$NAME-$VERSION" >> "$installed_file"
if (( $PACKAGE )); then
mkdir -p "$PACKAGE_ROOT"
version_string=$(cd .. && ../get-version-string.sh)
package_dir="$PACKAGE_ROOT/$version_string"
rm -rf "$package_dir"
mkdir "$package_dir"
dependencies=''
for dep in "${DEPENDENCIES[@]}"; do
dependencies+="$dep>=0 "
done
DESTDIR="$package_dir"
pre_install
install
post_install
find "$DESTDIR/usr/lib" -name '*.la' -delete
rm -f "$DESTDIR/usr/share/info/dir"
mkdir -p "$PACKAGE_REPO"
cd "$PACKAGE_REPO"
run_xbps xbps-create -A "$BANAN_ARCH" -n "${version_string%.*}" -s "$DESCRIPTION" -D "$dependencies" "$package_dir"
run_xbps xbps-rindex -af "$version_string.xbps"
fi
+23
View File
@@ -0,0 +1,23 @@
#!/bin/bash ../install.sh
NAME='json-c'
VERSION='0.18-20240915'
DOWNLOAD_URL="https://github.com/json-c/json-c/archive/refs/tags/json-c-$VERSION.tar.gz#3112c1f25d39eca661fe3fc663431e130cc6e2f900c081738317fba49d29e298"
TAR_CONTENT="json-c-json-c-$VERSION"
configure() {
cmake --fresh -B build -S . -G Ninja \
--toolchain="$BANAN_TOOLCHAIN_DIR/Toolchain.txt" \
-DCMAKE_INSTALL_PREFIX=/usr \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_STATIC_LIBS=OFF \
|| exit 1
}
build() {
cmake --build build || exit 1
}
install() {
DESTDIR="$DESTDIR" cmake --install build || exit 1
}
@@ -0,0 +1,12 @@
diff -ruN json-c-0.18-20240915/CMakeLists.txt json-c-0.18-20240915-banan_os/CMakeLists.txt
--- json-c-0.18-20240915/CMakeLists.txt 2024-09-15 19:22:45.000000000 +0300
+++ json-c-0.18-20240915-banan_os/CMakeLists.txt 2026-03-25 02:59:13.104155305 +0200
@@ -571,7 +571,7 @@
set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_LIBDIR}/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files")
install(FILES ${PROJECT_BINARY_DIR}/json-c.pc DESTINATION "${INSTALL_PKGCONFIG_DIR}")
-install(FILES ${JSON_C_PUBLIC_HEADERS} DESTINATION ${CMAKE_INSTALL_FULL_INCLUDEDIR}/json-c)
+install(FILES ${JSON_C_PUBLIC_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/json-c)
if (CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND BUILD_TESTING AND
(NOT MSVC OR NOT (MSVC_VERSION LESS 1800)) # Tests need at least VS2013
+29
View File
@@ -0,0 +1,29 @@
#!/bin/bash ../install.sh
NAME='json-glib'
VERSION='1.10.8'
DOWNLOAD_URL="https://github.com/GNOME/json-glib/archive/refs/tags/$VERSION.tar.gz#7a114bdac0b2611a7207e981c37fa9b1e70d9cb642470cd9e967b135428cec52"
DEPENDENCIES=('glib' 'json-c')
CONFIGURE_OPTIONS=(
'-Dprefix=/usr'
'-Dbuildtype=release'
'-Dintrospection=disabled'
'-Dnls=disabled'
'-Dtests=false'
)
configure() {
meson setup \
--reconfigure \
--cross-file "$MESON_CROSS_FILE" \
"${CONFIGURE_OPTIONS[@]}" \
build || exit 1
}
build() {
meson compile -C build || exit 1
}
install() {
meson install --destdir="$DESTDIR" -C build || exit 1
}
+28
View File
@@ -0,0 +1,28 @@
#!/bin/bash ../install.sh
NAME='lcms2'
VERSION='2.18'
DOWNLOAD_URL="https://github.com/mm2/Little-CMS/archive/refs/tags/lcms$VERSION.tar.gz#4f52a4459a93ac02b88e49b04dc0679e52fc92d36d3b722e5a1a44dbe8118236"
TAR_CONTENT="Little-CMS-lcms$VERSION"
DEPENDENCIES=('libtiff' 'libjpeg-turbo')
CONFIGURE_OPTIONS=(
'-Dprefix=/usr'
'-Dbuildtype=release'
'-Dtests=disabled'
)
configure() {
meson setup \
--reconfigure \
--cross-file "$MESON_CROSS_FILE" \
"${CONFIGURE_OPTIONS[@]}" \
build || exit 1
}
build() {
meson compile -C build || exit 1
}
install() {
meson install --destdir="$DESTDIR" -C build || exit 1
}
+1 -1
View File
@@ -4,7 +4,7 @@ NAME='libXdamage'
VERSION='1.1.7' VERSION='1.1.7'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libXdamage-$VERSION.tar.xz#127067f521d3ee467b97bcb145aeba1078e2454d448e8748eb984d5b397bde24" DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libXdamage-$VERSION.tar.xz#127067f521d3ee467b97bcb145aeba1078e2454d448e8748eb984d5b397bde24"
CONFIG_SUB=('config.sub') CONFIG_SUB=('config.sub')
DEPENDENCIES=('libX11') # FIXME: check deps DEPENDENCIES=('libX11' 'libXfixes')
CONFIGURE_OPTIONS=( CONFIGURE_OPTIONS=(
'--enable-shared=yes' '--enable-shared=yes'
'--enable-static=no' '--enable-static=no'
+11
View File
@@ -0,0 +1,11 @@
#!/bin/bash ../install.sh
NAME='libXxf86vm'
VERSION='1.1.7'
DOWNLOAD_URL="https://xorg.freedesktop.org/archive/individual/lib/libXxf86vm-$VERSION.tar.xz#ae50c0f669e0af5a67cc4cd0f54f21d64a64d2660af883e80e95d3fe51b945d8"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('libX11' 'libXext')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)
@@ -0,0 +1,31 @@
diff -ruN libXxf86vm-1.1.7/configure libXxf86vm-1.1.7-banan_os/configure
--- libXxf86vm-1.1.7/configure 2026-01-26 03:22:56.000000000 +0200
+++ libXxf86vm-1.1.7-banan_os/configure 2026-07-05 09:42:42.300455316 +0300
@@ -6162,6 +6162,10 @@
lt_cv_deplibs_check_method=pass_all
;;
+banan_os*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
beos*)
lt_cv_deplibs_check_method=pass_all
;;
@@ -11696,6 +11700,16 @@
;;
esac
;;
+
+banan_os*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker="$host_os DynamicLoader.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
beos*)
library_names_spec='$libname$shared_ext'
+11
View File
@@ -0,0 +1,11 @@
#!/bin/bash ../install.sh
NAME='libcroco'
VERSION='0.6.13'
DOWNLOAD_URL="https://download.gnome.org/sources/libcroco/${VERSION%.*}/libcroco-$VERSION.tar.xz#767ec234ae7aa684695b3a735548224888132e063f92db585759b422570621d4"
DEPENDENCIES=('glib' 'libxml2')
CONFIG_SUB=('config.sub')
CONFIGURE_OPTIONS=(
'--disable-static'
'--enable-shared'
)
@@ -1,7 +1,7 @@
diff -ruN freetype-2.14.3/builds/unix/configure freetype-2.14.3-banan_os/builds/unix/configure diff -ruN libcroco-0.6.13/configure libcroco-0.6.13-banan_os/configure
--- freetype-2.14.3/builds/unix/configure 2026-03-22 17:10:53.000000000 +0200 --- libcroco-0.6.13/configure 2019-04-06 20:28:06.000000000 +0300
+++ freetype-2.14.3-banan_os/builds/unix/configure 2026-07-05 13:40:58.479544155 +0300 +++ libcroco-0.6.13-banan_os/configure 2026-08-24 18:29:35.868215552 +0300
@@ -5417,6 +5417,10 @@ @@ -5609,6 +5609,10 @@
lt_cv_deplibs_check_method=pass_all lt_cv_deplibs_check_method=pass_all
;; ;;
@@ -12,7 +12,7 @@ diff -ruN freetype-2.14.3/builds/unix/configure freetype-2.14.3-banan_os/builds/
beos*) beos*)
lt_cv_deplibs_check_method=pass_all lt_cv_deplibs_check_method=pass_all
;; ;;
@@ -11327,6 +11331,16 @@ @@ -10822,6 +10826,16 @@
esac esac
;; ;;
+21
View File
@@ -0,0 +1,21 @@
#!/bin/bash ../install.sh
NAME='libfyaml'
VERSION='0.9.6'
DOWNLOAD_URL="https://github.com/pantoniou/libfyaml/releases/download/v$VERSION/libfyaml-$VERSION.tar.gz#a59cc3331e2eb903ec36933ad52a45888041cac31e44f553a00511131242c483"
configure() {
cmake --fresh -B build -S . -G Ninja \
--toolchain="$BANAN_TOOLCHAIN_DIR/Toolchain.txt" \
-DCMAKE_INSTALL_PREFIX=/usr \
-DCMAKE_BUILD_TYPE=Release \
|| exit 1
}
build() {
cmake --build build || exit 1
}
install() {
DESTDIR="$DESTDIR" cmake --install build || exit 1
}
@@ -0,0 +1,39 @@
diff -ruN libfyaml-0.9.6/CMakeLists.txt libfyaml-0.9.6-banan_os/CMakeLists.txt
--- libfyaml-0.9.6/CMakeLists.txt 2026-03-15 15:48:50.000000000 +0200
+++ libfyaml-0.9.6-banan_os/CMakeLists.txt 2026-03-25 03:53:58.967967134 +0200
@@ -1271,8 +1271,8 @@
endif()
add_executable(fy-tool ${FY_TOOL_SOURCES})
-target_include_directories(fy-tool PRIVATE ${FY_TOOL_INCLUDE_DIRS})
-target_compile_definitions(fy-tool PRIVATE ${COMMON_C_DEFINITIONS})
+target_include_directories(fy-tool PRIVATE ${FY_TOOL_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR})
+target_compile_definitions(fy-tool PRIVATE ${COMMON_C_DEFINITIONS} HAVE_CONFIG_H)
target_link_libraries(fy-tool PRIVATE fyaml)
@@ -1340,9 +1340,10 @@
src/internal/fy-thread.c
${GETOPT_SOURCES}
)
-target_include_directories(fy-thread PRIVATE ${INTERNAL_TOOL_INCLUDES})
+target_include_directories(fy-thread PRIVATE ${INTERNAL_TOOL_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR})
target_compile_definitions(fy-thread PRIVATE
${COMMON_C_DEFINITIONS}
+ HAVE_CONFIG_H
FY_STATIC)
if(NOT MSVC)
if(APPLE)
@@ -1373,10 +1374,12 @@
)
target_include_directories(fy-b3sum PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src/blake3
+ ${CMAKE_CURRENT_BINARY_DIR}
${INTERNAL_TOOL_INCLUDES}
)
target_compile_definitions(fy-b3sum PRIVATE
${COMMON_C_DEFINITIONS}
+ HAVE_CONFIG_H
FY_STATIC)
if(NOT MSVC)
if(APPLE)
@@ -0,0 +1,12 @@
diff -ruN libfyaml-0.9.6/include/libfyaml/libfyaml-endian.h libfyaml-0.9.6-banan_os/include/libfyaml/libfyaml-endian.h
--- libfyaml-0.9.6/include/libfyaml/libfyaml-endian.h 2026-03-15 15:48:50.000000000 +0200
+++ libfyaml-0.9.6-banan_os/include/libfyaml/libfyaml-endian.h 2026-03-25 03:35:29.164450940 +0200
@@ -42,7 +42,7 @@
extern "C" {
#endif
-#if defined(__linux__) || defined(__CYGWIN__) || defined(__OpenBSD__) || defined(__GNU__) || defined(__EMSCRIPTEN__)
+#if defined(__linux__) || defined(__CYGWIN__) || defined(__OpenBSD__) || defined(__GNU__) || defined(__EMSCRIPTEN__) || defined(__banan_os__)
# include <endian.h>
#elif defined(__APPLE__)
# include <libkern/OSByteOrder.h>
@@ -0,0 +1,17 @@
diff -ruN libfyaml-0.9.6/src/util/fy-utils.c libfyaml-0.9.6-banan_os/src/util/fy-utils.c
--- libfyaml-0.9.6/src/util/fy-utils.c 2026-03-15 15:48:50.000000000 +0200
+++ libfyaml-0.9.6-banan_os/src/util/fy-utils.c 2026-03-25 03:41:24.070062486 +0200
@@ -434,7 +434,13 @@
newt = t;
+#ifdef __banan_os__
+ newt.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
+ newt.c_oflag &= ~(OPOST);
+ newt.c_lflag &= ~(ECHO | ECHONL | ISIG | ICANON | IEXTEN);
+#else
cfmakeraw(&newt);
+#endif
ret = tcsetattr(fd, TCSANOW, &newt);
if (ret != 0)
+12
View File
@@ -0,0 +1,12 @@
#!/bin/bash ../install.sh
NAME='libmypaint'
VERSION='1.6.1'
DOWNLOAD_URL="https://github.com/mypaint/libmypaint/releases/download/v$VERSION/libmypaint-$VERSION.tar.xz#741754f293f6b7668f941506da07cd7725629a793108bb31633fb6c3eae5315f"
DEPENDENCIES=('glib' 'json-c')
CONFIG_SUB=('config.sub')
CONFIGURE_OPTIONS=(
'--disable-introspection'
'--disable-i18n'
'--disable-nls'
)
@@ -0,0 +1,31 @@
diff -ruN libmypaint-1.6.1/configure libmypaint-1.6.1-banan_os/configure
--- libmypaint-1.6.1/configure 2020-05-11 19:38:35.000000000 +0300
+++ libmypaint-1.6.1-banan_os/configure 2026-03-25 03:05:53.901886496 +0200
@@ -5608,6 +5608,10 @@
lt_cv_deplibs_check_method=pass_all
;;
+banan_os*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
beos*)
lt_cv_deplibs_check_method=pass_all
;;
@@ -11347,6 +11351,16 @@
esac
;;
+banan_os*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker="$host_os DynamicLoader.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
beos*)
library_names_spec='$libname$shared_ext'
dynamic_linker="$host_os ld.so"
+15
View File
@@ -0,0 +1,15 @@
#!/bin/bash ../install.sh
NAME='librsvg' # last pre-rust version
VERSION='2.40.21'
DOWNLOAD_URL="https://download.gnome.org/sources/librsvg/${VERSION%.*}/librsvg-$VERSION.tar.xz#f7628905f1cada84e87e2b14883ed57d8094dca3281d5bcb24ece4279e9a92ba"
DEPENDENCIES=('gdk-pixbuf' 'glib' 'libxml2' 'libcroco' 'cairo' 'pango')
CONFIG_SUB=('config.sub')
CONFIGURE_OPTIONS=(
'--disable-static'
'--enable-shared'
'--enable-pixbuf-loader'
'--disable-introspection'
'--disable-installed-tests'
'--disable-always-build-tests'
)
@@ -0,0 +1,31 @@
diff -ruN librsvg-2.40.21/configure librsvg-2.40.21-banan_os/configure
--- librsvg-2.40.21/configure 2020-02-26 19:45:16.000000000 +0200
+++ librsvg-2.40.21-banan_os/configure 2026-08-24 18:34:52.949804530 +0300
@@ -6802,6 +6802,10 @@
lt_cv_deplibs_check_method=pass_all
;;
+banan_os*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
beos*)
lt_cv_deplibs_check_method=pass_all
;;
@@ -12275,6 +12279,16 @@
esac
;;
+banan_os*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker="$host_os DynamicLoader.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
beos*)
library_names_spec='$libname$shared_ext'
dynamic_linker="$host_os ld.so"
@@ -0,0 +1,13 @@
diff -ruN librsvg-2.40.21/configure librsvg-2.40.21-banan_os/configure
--- librsvg-2.40.21/configure 2020-02-26 19:45:16.000000000 +0200
+++ librsvg-2.40.21-banan_os/configure 2026-08-24 19:52:43.388200018 +0300
@@ -14745,6 +14745,9 @@
gdk_pixbuf_binarydir="`$PKG_CONFIG --variable=gdk_pixbuf_binarydir gdk-pixbuf-2.0`"
gdk_pixbuf_moduledir=`$PKG_CONFIG --variable gdk_pixbuf_moduledir gdk-pixbuf-2.0`
gdk_pixbuf_cache_file=`$PKG_CONFIG --variable gdk_pixbuf_cache_file gdk-pixbuf-2.0`
+ gdk_pixbuf_binarydir="${gdk_pixbuf_binarydir#$PKG_CONFIG_SYSROOT_DIR}"
+ gdk_pixbuf_moduledir="${gdk_pixbuf_moduledir#$PKG_CONFIG_SYSROOT_DIR}"
+ gdk_pixbuf_cache_file="${gdk_pixbuf_cache_file#$PKG_CONFIG_SYSROOT_DIR}"
fi
@@ -0,0 +1,24 @@
diff -ruN librsvg-2.40.21/rsvg-css.c librsvg-2.40.21-banan_os/rsvg-css.c
--- librsvg-2.40.21/rsvg-css.c 2018-10-02 01:50:22.000000000 +0300
+++ librsvg-2.40.21-banan_os/rsvg-css.c 2026-08-24 18:45:05.745087552 +0300
@@ -839,7 +839,7 @@
}
static void
-rsvg_xml_noerror (void *data, xmlErrorPtr error)
+rsvg_xml_noerror (void *data, const xmlError* error)
{
}
diff -ruN librsvg-2.40.21/rsvg-private.h librsvg-2.40.21-banan_os/rsvg-private.h
--- librsvg-2.40.21/rsvg-private.h 2020-02-26 19:40:25.000000000 +0200
+++ librsvg-2.40.21-banan_os/rsvg-private.h 2026-08-24 18:45:12.583727389 +0300
@@ -31,7 +31,7 @@
#include "rsvg.h"
-#include <libxml/SAX.h>
+#include <libxml/tree.h>
#include <libxml/xmlmemory.h>
#include <pango/pango.h>
#include <glib.h>
+3 -3
View File
@@ -1,4 +1,4 @@
#!/bin/bash #!/bin/bash ../install.sh
export MESA_VARIANT='glx' MESA_VARIANT='glx'
exec ../mesa/build.sh source ../mesa/build.sh
+5
View File
@@ -0,0 +1,5 @@
#!/bin/bash ../install.sh
NAME='mypaint-brushes'
VERSION='2.0.2'
DOWNLOAD_URL="https://github.com/mypaint/mypaint-brushes/releases/download/v$VERSION/mypaint-brushes-$VERSION.tar.xz#7984a74edef94571d872d0629b224abaa956a36f632f5c5516b33d22e49eb566"
+1
View File
@@ -7,6 +7,7 @@ DEPENDENCIES=('ncurses')
CONFIG_SUB=('config.sub') CONFIG_SUB=('config.sub')
CONFIGURE_OPTIONS=( CONFIGURE_OPTIONS=(
'ac_cv_header_glob_h=no' 'ac_cv_header_glob_h=no'
'CFLAGS=-Dpthread_self=pthread_self'
) )
pre_configure() { pre_configure() {
+10 -6
View File
@@ -6,7 +6,7 @@ DOWNLOAD_URL="https://ftpmirror.gnu.org/gnu/ncurses/ncurses-$VERSION.tar.gz#355b
CONFIG_SUB=('config.sub') CONFIG_SUB=('config.sub')
CONFIGURE_OPTIONS=( CONFIGURE_OPTIONS=(
"--with-pkg-config='$PKG_CONFIG'" "--with-pkg-config='$PKG_CONFIG'"
"--with-pkg-config-libdir=/usr/lib/pkgconfig" '--with-pkg-config-libdir=/usr/lib/pkgconfig'
'--enable-pc-files' '--enable-pc-files'
'--enable-sigwinch' '--enable-sigwinch'
'--with-shared' '--with-shared'
@@ -16,13 +16,17 @@ CONFIGURE_OPTIONS=(
CFLAGS='-std=c17' CFLAGS='-std=c17'
) )
pre_configure() {
unset TERMINFO TERMINFO_DIRS
}
post_install() { post_install() {
for lib in ncurses ncurses++ form panel menu; do for lib in ncurses form panel menu; do
ln -sv ${lib}w.pc "$DESTDIR/usr/lib/pkgconfig/$lib.pc" ln -svf ${lib}w.pc "$DESTDIR/usr/lib/pkgconfig/$lib.pc"
done done
ln -sv libncursesw.so "$DESTDIR/usr/lib/libncurses.so" ln -svf libncursesw.so "$DESTDIR/usr/lib/libncurses.so"
shellrc="$BANAN_SYSROOT/home/user/.shellrc" mkdir -p "$DESTDIR/etc/profile.d"
grep -q 'export NCURSES_NO_UTF8_ACS=' "$shellrc" || echo 'export NCURSES_NO_UTF8_ACS=1' >> "$shellrc" echo 'export NCURSES_NO_UTF8_ACS=1' > "$DESTDIR/etc/profile.d/ncurses.sh"
} }
+1 -1
View File
@@ -10,5 +10,5 @@ configure() {
install() { install() {
mkdir -p "$DESTDIR/usr/bin" mkdir -p "$DESTDIR/usr/bin"
cp src/nyancat "$DESTDIR/usr/bin/" cp -v src/nyancat "$DESTDIR/usr/bin/" || exit 1
} }
+1 -1
View File
@@ -20,7 +20,7 @@ post_install() {
openssl rehash "$BANAN_SYSROOT/etc/cacert/extracted" openssl rehash "$BANAN_SYSROOT/etc/cacert/extracted"
find "$BANAN_SYSROOT/etc/cacert/extracted" -type l -print0 | find "$BANAN_SYSROOT/etc/cacert/extracted" -type l -print0 |
while IFS= read -r -d '' link; do while IFS= read -r -d '' link; do
ln -s "../../cacert/extracted/$(readlink "$link")" "$DESTDIR/etc/ssl/certs/${link##*/}" ln -sf "../../cacert/extracted/$(readlink "$link")" "$DESTDIR/etc/ssl/certs/${link##*/}"
rm "$link" rm "$link"
done done
} }
+33
View File
@@ -0,0 +1,33 @@
#!/bin/bash
if [[ -z $BANAN_ROOT_DIR ]]; then
export BANAN_ROOT_DIR="$(realpath $(dirname $(realpath "$0"))/..)"
fi
source "$BANAN_ROOT_DIR/script/config.sh"
package_standalone() {
pushd "$BANAN_PORT_DIR/$1" >/dev/null
local version_string="$(../get-version-string.sh)"
if [ ! -f "$BANAN_PORT_DIR/package/repo/${version_string}.xbps" ]; then
local dependency
for dependency in $(source build.sh; echo ${DEPENDENCIES[*]}); do
package_standalone "$dependency"
done
find "$BANAN_SYSROOT/usr/lib" \( -type f -o -type l \) -delete
PACKAGE=1 ./build.sh || echo "$port_name" >> ../failed-ports
fi
popd >/dev/null
}
cd "$BANAN_PORT_DIR"
for build_script in */build.sh; do
port_name="${build_script%/*}"
[[ "$port_name" == 'llvm' ]] && continue
package_standalone "$port_name"
done
+1 -1
View File
@@ -3,7 +3,7 @@
NAME='pango' NAME='pango'
VERSION='1.57.0' VERSION='1.57.0'
DOWNLOAD_URL="https://gitlab.gnome.org/GNOME/pango/-/archive/$VERSION/pango-$VERSION.tar.gz#1b2e2f683dfb5adec3faf17087ade8c648f10a5d3d0e17e421e0ac1a39e6740e" DOWNLOAD_URL="https://gitlab.gnome.org/GNOME/pango/-/archive/$VERSION/pango-$VERSION.tar.gz#1b2e2f683dfb5adec3faf17087ade8c648f10a5d3d0e17e421e0ac1a39e6740e"
DEPENDENCIES=('glib' 'fontconfig' 'cairo' 'fribidi' 'libXft') DEPENDENCIES=('glib' 'harfbuzz' 'fontconfig' 'cairo' 'fribidi' 'libXft')
CONFIGURE_OPTIONS=( CONFIGURE_OPTIONS=(
'-Dprefix=/usr' '-Dprefix=/usr'
'-Dbuildtype=release' '-Dbuildtype=release'
+21
View File
@@ -0,0 +1,21 @@
#!/bin/bash ../install.sh
NAME='poppler-data'
VERSION='0.4.12'
DOWNLOAD_URL="https://poppler.freedesktop.org/poppler-data-$VERSION.tar.gz#c835b640a40ce357e1b83666aabd95edffa24ddddd49b8daff63adb851cdab74"
configure() {
cmake --fresh -B build -S . -G Ninja \
--toolchain="$BANAN_TOOLCHAIN_DIR/Toolchain.txt" \
-DCMAKE_INSTALL_PREFIX='/usr' \
-DCMAKE_BUILD_TYPE=Release \
|| exit 1
}
build() {
cmake --build build ||exit 1
}
install() {
DESTDIR="$DESTDIR" cmake --install build ||exit 1
}
+28
View File
@@ -0,0 +1,28 @@
#!/bin/bash ../install.sh
NAME='poppler'
VERSION='26.03.0'
DOWNLOAD_URL="https://poppler.freedesktop.org/poppler-$VERSION.tar.xz#8b3c5e2a9f2ab4c3ec5029f28af1b433c6b71f0d1e7b3997aa561cf1c0ca4ebe"
DEPENDENCIES=('gtk3' 'cairo' 'boost' 'curl' 'lcms2' 'libtiff' 'poppler-data')
configure() {
cmake --fresh -B build -S . -G Ninja \
--toolchain="$BANAN_TOOLCHAIN_DIR/Toolchain.txt" \
-DCMAKE_INSTALL_PREFIX=/usr \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_SHARED_LIBS=ON \
-DENABLE_NSS3=OFF \
-DENABLE_GPGME=OFF \
-DENABLE_QT5=OFF \
-DENABLE_QT6=OFF \
-DENABLE_LIBOPENJPEG=none \
|| exit 1
}
build() {
cmake --build build ||exit 1
}
install() {
DESTDIR="$DESTDIR" cmake --install build ||exit 1
}
+8 -11
View File
@@ -1,25 +1,22 @@
#!/bin/bash ../install.sh #!/bin/bash ../install.sh
NAME='python' NAME='python'
VERSION='3.13.3' VERSION='3.14.7'
DOWNLOAD_URL="https://www.python.org/ftp/python/$VERSION/Python-$VERSION.tar.xz#40f868bcbdeb8149a3149580bb9bfd407b3321cd48f0be631af955ac92c0e041" DOWNLOAD_URL="https://www.python.org/ftp/python/$VERSION/Python-$VERSION.tar.xz#3b48dac8fb59f62eaa67ac83c1eb12bda1b7a08406dd286e252c11a66be27f81"
TAR_CONTENT="Python-$VERSION" TAR_CONTENT="Python-$VERSION"
DEPENDENCIES=('ncurses' 'zlib' 'openssl') DEPENDENCIES=('ncurses' 'openssl' 'libffi' 'zlib' 'zstd' 'bzip2')
CONFIG_SUB=('config.sub') CONFIG_SUB=('config.sub')
CONFIGURE_OPTIONS=( CONFIGURE_OPTIONS=(
"--build=$(uname -m)-pc-linux-gnu" "--build=$(uname -m)-pc-linux-gnu"
"--with-build-python=python3.13" '--with-build-python=python3.14'
'--without-ensurepip'
'--disable-ipv6' '--disable-ipv6'
'--disable-test-modules'
'--enable-shared' '--enable-shared'
'--disable-test-modules'
'ac_cv_file__dev_ptmx=no' 'ac_cv_file__dev_ptmx=no'
'ac_cv_file__dev_ptc=no' 'ac_cv_file__dev_ptc=no'
) )
pre_configure() { post_install() {
if ! command -v python3.13 &>/dev/null ; then mkdir -p "$DESTDIR/usr/bin"
echo "You need to have python3.13 installed on your host machine" >&2 ln -svf python3 "$DESTDIR/usr/bin/python" || exit 1
exit 1
fi
} }
@@ -1,7 +1,7 @@
diff -ruN Python-3.13.3/configure Python-3.13.3-banan_os/configure diff -ru python-3.14.7/configure python-3.14.7-banan_os/configure
--- Python-3.13.3/configure 2025-04-08 16:54:08.000000000 +0300 --- python-3.14.7/configure 2026-08-05 13:29:49.000000000 +0300
+++ Python-3.13.3-banan_os/configure 2025-04-19 04:25:20.860260051 +0300 +++ python-3.14.7-banan_os/configure 2026-08-25 12:39:57.212768646 +0300
@@ -4052,6 +4052,9 @@ @@ -4112,6 +4112,9 @@
*-*-linux*) *-*-linux*)
ac_sys_system=Linux ac_sys_system=Linux
;; ;;
@@ -11,7 +11,7 @@ diff -ruN Python-3.13.3/configure Python-3.13.3-banan_os/configure
*-*-cygwin*) *-*-cygwin*)
ac_sys_system=Cygwin ac_sys_system=Cygwin
;; ;;
@@ -4500,6 +4503,9 @@ @@ -4591,6 +4594,9 @@
_host_ident=$host_cpu _host_ident=$host_cpu
esac esac
;; ;;
@@ -21,7 +21,7 @@ diff -ruN Python-3.13.3/configure Python-3.13.3-banan_os/configure
*-*-cygwin*) *-*-cygwin*)
_host_ident= _host_ident=
;; ;;
@@ -7603,6 +7609,11 @@ @@ -7751,6 +7757,11 @@
PY3LIBRARY=libpython3.so PY3LIBRARY=libpython3.so
fi fi
;; ;;
@@ -33,7 +33,7 @@ diff -ruN Python-3.13.3/configure Python-3.13.3-banan_os/configure
hp*|HP*) hp*|HP*)
case `uname -m` in case `uname -m` in
ia64) ia64)
@@ -12983,7 +12994,7 @@ @@ -13750,7 +13761,7 @@
Emscripten*|WASI*) Emscripten*|WASI*)
LDSHARED='$(CC) -shared' LDSHARED='$(CC) -shared'
LDCXXSHARED='$(CXX) -shared';; LDCXXSHARED='$(CXX) -shared';;
@@ -42,19 +42,12 @@ diff -ruN Python-3.13.3/configure Python-3.13.3-banan_os/configure
LDSHARED='$(CC) -shared' LDSHARED='$(CC) -shared'
LDCXXSHARED='$(CXX) -shared';; LDCXXSHARED='$(CXX) -shared';;
FreeBSD*) FreeBSD*)
@@ -13069,6 +13080,7 @@ @@ -13835,7 +13846,7 @@
then CCSHARED="-fPIC";
else CCSHARED="+z"; else CCSHARED="+z";
fi;; fi;;
Linux*|GNU*) CCSHARED="-fPIC";; - Linux*|GNU*) CCSHARED="-fPIC";;
+ banan_os*) CCSHARED="-fPIC";; + Linux*|GNU*|banan_os*) CCSHARED="-fPIC";;
Emscripten*|WASI*) Emscripten*|WASI*)
if test "x$enable_wasm_dynamic_linking" = xyes if test "x$enable_wasm_dynamic_linking" = xyes
then : then :
@@ -23609,6 +23621,7 @@
case $ac_sys_system in
Darwin) ;;
+banan_os) ;;
*) LIBM=-lm
esac
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for --with-libm=STRING" >&5

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