Compare commits

..
38 Commits
Author SHA1 Message Date
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
90 changed files with 1825 additions and 429 deletions
+1
View File
@@ -41,6 +41,7 @@ set(KERNEL_SOURCES
kernel/FS/USTARModule.cpp
kernel/FS/VirtualFileSystem.cpp
kernel/GDT.cpp
kernel/Graphics/BGA.cpp
kernel/IDT.cpp
kernel/Input/InputDevice.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_controllers();
void initialize_embedded_controller_gpes();
BAN::Optional<GAS> find_gpe_block(size_t index);
bool enable_gpe(uint8_t gpe);
@@ -14,7 +14,7 @@ namespace Kernel::ACPI
class EmbeddedController
{
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();
BAN::ErrorOr<uint8_t> read_byte(uint8_t offset);
@@ -22,21 +22,21 @@ namespace Kernel::ACPI
const AML::Scope& scope() const { return m_scope; }
static void handle_gpe_trampoline(void*);
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_command_port(command_port)
, m_data_port(data_port)
, m_has_gpe(has_gpe)
{ }
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);
void write_one(uint16_t port, uint8_t value);
static void handle_gpe_wrapper(void*);
void handle_gpe();
BAN::ErrorOr<void> call_query_method(uint8_t notification);
@@ -57,7 +57,6 @@ namespace Kernel::ACPI
const AML::Scope m_scope;
const uint16_t m_command_port;
const uint16_t m_data_port;
const bool m_has_gpe;
Mutex m_mutex;
ThreadBlocker m_thread_blocker;
@@ -6,15 +6,22 @@
namespace Kernel
{
class BGAController;
class FramebufferDevice : public CharacterDevice
{
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::RefPtr<FramebufferDevice> boot_framebuffer();
~FramebufferDevice();
uint32_t width() const { return m_width; }
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;
void set_pixel(uint32_t x, uint32_t y, uint32_t rgb);
@@ -50,14 +57,16 @@ namespace Kernel
private:
const BAN::String m_name;
vaddr_t m_video_memory_vaddr { 0 };
const paddr_t m_video_memory_paddr;
const uint32_t m_width;
const uint32_t m_height;
const uint32_t m_pitch;
const uint8_t m_bpp;
vaddr_t m_video_memory_vaddr { 0 };
paddr_t m_video_memory_paddr { 0 };
uint32_t m_width { 0 };
uint32_t m_height { 0 };
uint32_t m_pitch { 0 };
uint8_t m_bpp { 0 };
BAN::UniqPtr<VirtualRange> m_video_buffer;
BAN::RefPtr<BGAController> m_bga_controller;
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 };
};
template<typename Lock>
class SpinLockGuardAsMutex;
template<typename Lock>
class SpinLockGuard
{
@@ -85,7 +82,6 @@ namespace Kernel
private:
Lock& m_lock;
InterruptState m_state;
friend class SpinLockGuardAsMutex<Lock>;
};
}
+2 -3
View File
@@ -22,7 +22,6 @@ namespace Kernel
class GDT;
class IDT;
class Scheduler;
class SchedulerThreadNode;
class Thread;
#if ARCH(x86_64) || ARCH(i686)
@@ -54,8 +53,8 @@ namespace Kernel
union
{
TLBEntry flush_tlb;
SchedulerThreadNode* new_thread;
SchedulerThreadNode* unblock_thread;
Thread* new_thread;
Thread* unblock_thread;
bool dummy;
};
};
+2 -6
View File
@@ -41,9 +41,8 @@ namespace Kernel
void on_timer_interrupt();
void on_yield(YieldRegisters*);
static BAN::ErrorOr<void> bind_thread_to_processor(Thread*, ProcessorID);
// if thread is already bound, this will never fail
BAN::ErrorOr<void> add_thread(Thread*);
static void bind_thread_to_processor(Thread*, ProcessorID);
void add_thread(Thread*);
void block_current_thread(ThreadBlocker* thread_blocker, uint64_t wake_time_ns, BaseMutex* mutex);
void unblock_thread(Thread*);
@@ -68,9 +67,6 @@ namespace Kernel
class ProcessorID find_least_loaded_processor() const;
void add_thread(SchedulerThreadNode*);
void unblock_thread(SchedulerThreadNode*);
private:
SchedulerQueue m_run_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 is_vtty() const { return false; }
protected:
TTY(termios termios, mode_t mode, uid_t uid, gid_t gid);
@@ -100,9 +102,9 @@ namespace Kernel
termios m_termios;
protected:
Mutex m_mutex;
Mutex m_input_mutex;
Mutex m_write_lock;
RecursiveSpinLock m_write_lock;
ThreadBlocker m_write_blocker;
};
@@ -21,6 +21,9 @@ namespace Kernel
void clear() override;
bool is_vtty() const override { return true; }
BAN::ErrorOr<void> set_terminal_driver(BAN::RefPtr<TerminalDriver>);
protected:
BAN::StringView name() const override { return m_name; }
bool putchar_impl(uint8_t ch) override;
+2 -1
View File
@@ -7,6 +7,7 @@
#include <kernel/InterruptStack.h>
#include <kernel/Lock/Mutex.h>
#include <kernel/Memory/VirtualRange.h>
#include <kernel/SchedulerThreadNode.h>
#include <LibELF/AuxiliaryVector.h>
@@ -192,7 +193,7 @@ namespace Kernel
vaddr_t m_fsbase { 0 };
vaddr_t m_gsbase { 0 };
SchedulerThreadNode* m_scheduler_node { nullptr };
SchedulerThreadNode m_scheduler_node;
YieldRegisters m_yield_registers { };
+1
View File
@@ -30,6 +30,7 @@ namespace Kernel
Hub = 0x09,
BillboardDeviceClass = 0x11,
DiagnosticDevice = 0xDC,
WirelessController = 0xE0,
Miscellaneous = 0xEF,
VendorSpecific = 0xFF,
};
+78 -69
View File
@@ -784,26 +784,6 @@ acpi_release_global_lock:
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));
if (crs_obj == nullptr)
{
@@ -857,7 +837,7 @@ acpi_release_global_lock:
const auto data_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 {};
}
@@ -877,6 +857,33 @@ acpi_release_global_lock:
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)
{
if (m_gpe_methods[gpe].method)
@@ -996,57 +1003,27 @@ acpi_release_global_lock:
// 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;
if (auto ret = InterruptController::get().reserve_irq(irq); ret.is_error())
dwarnln("Could not enable ACPI interrupt: {}", ret.error());
else
{
auto hex_sv_to_int =
[](BAN::StringView sv) -> BAN::Optional<uint32_t>
const auto hex_sv_to_int = [](BAN::StringView sv) -> BAN::Optional<uint32_t> {
uint32_t ret = 0;
for (char c : sv)
{
uint32_t ret = 0;
for (char c : sv)
{
ret <<= 4;
if (c >= '0' && c <= '9')
ret += c - '0';
else if (c >= 'A' && c <= 'F')
ret += c - 'A' + 10;
else if (c >= 'a' && c <= 'f')
ret += c - 'a' + 10;
else
return {};
}
return ret;
};
ret <<= 4;
if (c >= '0' && c <= '9')
ret += c - '0';
else if (c >= 'A' && c <= 'F')
ret += c - 'A' + 10;
else if (c >= 'a' && c <= 'f')
ret += c - 'a' + 10;
else
return {};
}
return ret;
};
auto [gpe_scope, gpe_obj] = TRY(m_namespace->find_named_object({}, TRY(AML::NameString::from_string("\\_GPE"))));
if (gpe_obj && gpe_obj->node.is_scope())
@@ -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())
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())
dwarnln("Failed to create ACPI thread, power button will not work: {}", ret.error());
else
{
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())
{
+33 -2
View File
@@ -494,8 +494,23 @@ namespace Kernel::ACPI::AML
return TRY(embedded_controller->read_byte(offset));
}
case GAS::AddressSpaceID::SMBus:
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::IPMI:
case GAS::AddressSpaceID::GeneralPurposeIO:
@@ -581,8 +596,24 @@ namespace Kernel::ACPI::AML
TRY(embedded_controller->write_byte(offset, value));
return {};
}
case GAS::AddressSpaceID::SMBus:
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::IPMI:
case GAS::AddressSpaceID::GeneralPurposeIO:
+21 -37
View File
@@ -30,28 +30,18 @@ namespace Kernel::ACPI
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)
return BAN::Error::from_errno(ENOMEM);
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);
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;
}
@@ -95,26 +85,25 @@ namespace Kernel::ACPI
uint8_t EmbeddedController::read_one(uint16_t port)
{
wait_status_bit(STS_OBF, 1);
wait_status_bit(STS_OBF, true);
return IO::inb(port);
}
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);
}
void EmbeddedController::wait_status_bit(uint8_t bit, uint8_t value)
void EmbeddedController::wait_status_bit(uint8_t mask, bool set)
{
// FIXME: timeouts
const uint8_t mask = 1 << bit;
const uint8_t comp = value ? mask : 0;
const uint8_t comp = set ? mask : 0;
while ((IO::inb(m_command_port) & mask) != comp)
continue;
}
void EmbeddedController::handle_gpe_wrapper(void* embedded_controller)
void EmbeddedController::handle_gpe_trampoline(void* embedded_controller)
{
static_cast<EmbeddedController*>(embedded_controller)->handle_gpe();
}
@@ -217,7 +206,7 @@ namespace Kernel::ACPI
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();
if (command == nullptr)
@@ -226,27 +215,22 @@ namespace Kernel::ACPI
continue;
}
// TODO: use burst mode
m_mutex.unlock();
if (command)
{
// TODO: use burst mode
write_one(m_command_port, command->command);
if (command->data1.has_value())
write_one(m_data_port, command->data1.value());
if (command->data2.has_value())
write_one(m_data_port, command->data2.value());
if (command->response)
*command->response = read_one(m_data_port);
m_mutex.lock();
command->done = true;
m_thread_blocker.unblock();
m_mutex.unlock();
}
write_one(m_command_port, command->command);
if (command->data1.has_value())
write_one(m_data_port, command->data1.value());
if (command->data2.has_value())
write_one(m_data_port, command->data2.value());
if (command->response)
*command->response = read_one(m_data_port);
m_mutex.lock();
command->done = true;
m_thread_blocker.unblock();
}
}
@@ -343,6 +343,7 @@ namespace Kernel
using HDAudio::AFGWidget;
case AFGWidget::Type::OutputConverter:
case AFGWidget::Type::Mixer:
case AFGWidget::Type::Selector:
case AFGWidget::Type::PinComplex:
break;
default:
@@ -439,6 +440,9 @@ namespace Kernel
}
break;
case AFGWidget::Type::Selector:
break;
case AFGWidget::Type::PinComplex:
// enable output and H-Phn
TRY(m_controller->send_command({
@@ -525,6 +529,7 @@ namespace Kernel
case AFGWidget::Type::OutputConverter:
case AFGWidget::Type::Mixer:
case AFGWidget::Type::Selector:
break;
case AFGWidget::Type::PinComplex:
+69 -11
View File
@@ -2,6 +2,7 @@
#include <kernel/Device/DeviceNumbers.h>
#include <kernel/Device/FramebufferDevice.h>
#include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/Graphics/BGA.h>
#include <kernel/Memory/Heap.h>
#include <kernel/Terminal/FramebufferTerminal.h>
@@ -26,19 +27,14 @@ namespace Kernel
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 (g_boot_info.framebuffer.bpp != 24 && g_boot_info.framebuffer.bpp != 32)
if (bpp != 24 && bpp != 32)
return BAN::Error::from_errno(ENOTSUP);
auto* device_ptr = new FramebufferDevice(
0660, 0, 900,
makedev(DeviceNumber::Framebuffer, get_framebuffer_device_index()),
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
paddr, width, height, pitch, bpp
);
if (device_ptr == nullptr)
return BAN::Error::from_errno(ENOMEM);
@@ -49,6 +45,33 @@ namespace Kernel
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)
: CharacterDevice(mode, uid, gid)
, m_name(MUST(BAN::String::formatted("fb{}", minor(rdev))))
@@ -65,16 +88,20 @@ namespace Kernel
{
if (m_video_memory_vaddr == 0)
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);
}
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);
if (m_video_memory_vaddr == 0)
return BAN::Error::from_errno(ENOMEM);
PageTable::kernel().map_range_at(
m_video_memory_paddr & PAGE_ADDR_MASK,
m_video_memory_vaddr,
@@ -86,7 +113,7 @@ namespace Kernel
m_video_buffer = TRY(VirtualRange::create_to_vaddr_range(
PageTable::kernel(),
{ 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,
false
));
@@ -94,6 +121,37 @@ namespace Kernel
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)
{
// Reading from negative offset will fill buffer with framebuffer info
+3 -3
View File
@@ -63,7 +63,7 @@ namespace Kernel
}
}, s_instance
));
MUST(Processor::scheduler().add_thread(updater_thread));
Processor::scheduler().add_thread(updater_thread);
auto* disk_cache_drop_thread = MUST(Thread::create_kernel(
[](void* _devfs)
@@ -93,7 +93,7 @@ namespace Kernel
}
}, 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(
[](void* _devfs)
@@ -129,7 +129,7 @@ namespace Kernel
}
}, s_instance
));
MUST(Processor::scheduler().add_thread(disk_sync_thread));
Processor::scheduler().add_thread(disk_sync_thread);
}
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()
{
auto* thread = TRY(Thread::create_kernel(tty_keyboard_thread, nullptr));
ASSERT(thread);
TRY(Processor::scheduler().add_thread(thread));
Processor::scheduler().add_thread(thread);
return {};
}
+9 -2
View File
@@ -319,11 +319,18 @@ namespace Kernel::Input
if (crs_obj == nullptr)
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;
result.type = type;
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())
{
switch (data->type)
@@ -551,7 +558,7 @@ namespace Kernel::Input
static_cast<PS2DeviceInitInfo*>(info)->controller->device_initialize_task(info);
}, &info
));
TRY(Processor::scheduler().add_thread(init_thread));
Processor::scheduler().add_thread(init_thread);
while (!info.thread_started)
Processor::pause();
@@ -87,6 +87,9 @@ namespace Kernel
return BAN::Error::from_errno(ENOENT);
}
if (size == 0)
return BAN::Error::from_errno(EINVAL);
const auto& process = Process::current();
const uid_t uid = process.credentials().euid();
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) {
static_cast<E1000*>(e1000_ptr)->receive_thread();
}, this));
if (auto ret = Processor::scheduler().add_thread(thread); ret.is_error())
{
delete thread;
return ret.release_error();
}
Processor::scheduler().add_thread(thread);
m_thread_is_dead = false;
return {};
+2 -5
View File
@@ -25,11 +25,8 @@ namespace Kernel
auto* thread = TRY(Thread::create_kernel([](void* loopback_ptr) {
static_cast<LoopbackInterface*>(loopback_ptr)->receive_thread();
}, loopback_ptr));
if (auto ret = Processor::scheduler().add_thread(thread); ret.is_error())
{
delete thread;
return ret.release_error();
}
Processor::scheduler().add_thread(thread);
loopback->m_thread_is_dead = false;
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) {
static_cast<RTL8169*>(rtl8169_ptr)->receive_thread();
}, this));
if (auto ret = Processor::scheduler().add_thread(thread); ret.is_error())
{
delete thread;
return ret.release_error();
}
Processor::scheduler().add_thread(thread);
m_rx_thread_is_dead = false;
return {};
+1 -1
View File
@@ -45,7 +45,7 @@ namespace Kernel
reinterpret_cast<TCPSocket*>(socket_ptr)->process_task();
}, 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
socket->ref();
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)
{
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);
if (address_len > static_cast<socklen_t>(sizeof(sockaddr_un)))
address_len = sizeof(sockaddr_un);
@@ -30,13 +30,12 @@ namespace Kernel
if (sockaddr_un.sun_family != AF_UNIX)
return BAN::Error::from_errno(EINVAL);
size_t length = 0;
while (length < sizeof(sockaddr_un::sun_path) && sockaddr_un.sun_path[length])
length++;
if (length >= sizeof(sockaddr_un::sun_path))
return BAN::Error::from_errno(ENAMETOOLONG);
return BAN::StringView { sockaddr_un.sun_path, length };
auto sun_path = BAN::StringView { sockaddr_un.sun_path, address_len - sizeof(sa_family_t) };
if (const auto null_idx = sun_path.find('\0'); null_idx.has_value())
sun_path = sun_path.substring(0, null_idx.value());
if (sun_path.empty())
return BAN::Error::from_errno(EINVAL);
return sun_path;
}
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)
{
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
auto parent_file = sun_path.front() == '/'
? TRY(Process::current().root_file().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)
return BAN::Error::from_errno(EADDRINUSE);
+19 -5
View File
@@ -3,6 +3,7 @@
#include <kernel/ACPI/ACPI.h>
#include <kernel/APIC.h>
#include <kernel/Audio/Controller.h>
#include <kernel/Graphics/BGA.h>
#include <kernel/IDT.h>
#include <kernel/IO.h>
#include <kernel/Memory/PageTable.h>
@@ -258,6 +259,13 @@ namespace Kernel::PCI
for_each_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())
{
case 0x01:
@@ -912,10 +920,10 @@ namespace Kernel::PCI
}
// 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));
uint8_t offset = 0x10 + bar_num * 4;
const uint8_t offset = 0x10 + bar_num * 4;
uint64_t addr = device.read_dword(offset);
@@ -924,6 +932,13 @@ namespace Kernel::PCI
size = ~size + 1;
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
BarType type = BarType::INVALID;
if (addr & 1)
@@ -956,8 +971,7 @@ namespace Kernel::PCI
TRY(region->initialize());
// 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);
device.write_word(PCI_REG_COMMAND, command | ((type == BarType::IO) ? PCI_CMD_IO_SPACE : PCI_CMD_MEM_SPACE));
#if DEBUG_PCI
dprintln("created BAR region for PCI {2H}:{2H}.{2H}",
@@ -997,7 +1011,7 @@ namespace Kernel::PCI
if (m_type == BarType::IO)
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);
if (m_vaddr == 0)
return BAN::Error::from_errno(ENOMEM);
+8 -21
View File
@@ -237,9 +237,8 @@ namespace Kernel
#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(Processor::scheduler().bind_thread_to_processor(thread, Processor::current_id()));
{
SpinLockGuard _(s_process_lock);
@@ -247,7 +246,7 @@ namespace Kernel
}
MUST(process->m_threads.push_back(thread));
MUST(Processor::scheduler().add_thread(thread));
Processor::scheduler().add_thread(thread);
process_deleter.disable();
thread_deleter.disable();
@@ -877,9 +876,8 @@ namespace Kernel
Thread* thread = TRY(Thread::current().clone(forked, sp, ip));
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(Processor::scheduler().bind_thread_to_processor(thread, Processor::current_id()));
{
SpinLockGuard _(s_process_lock);
@@ -905,7 +903,7 @@ namespace Kernel
ASSERT(this == &Process::current());
MUST(forked->m_threads.push_back(thread));
MUST(Processor::scheduler().add_thread(thread));
Processor::scheduler().add_thread(thread);
process_deleter.disable();
thread_deleter.disable();
@@ -1072,14 +1070,6 @@ namespace Kernel
#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);
@@ -1103,7 +1093,9 @@ namespace Kernel
m_threads.front()->m_process = nullptr;
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;
for (size_t i = 0; i < sizeof(m_signal_handlers) / sizeof(*m_signal_handlers); i++)
@@ -3580,12 +3572,7 @@ namespace Kernel
LockGuard _1(m_process_lock);
TRY(m_threads.push_back(thread));
if (auto ret = Processor::scheduler().add_thread(thread); ret.is_error())
{
m_threads.pop_back();
delete thread;
return ret.release_error();
}
Processor::scheduler().add_thread(thread);
return thread->tid();
}
+68 -84
View File
@@ -33,9 +33,6 @@ namespace Kernel
static SpinLock s_processor_info_time_lock;
static BAN::Array<ProcessorInfo, 0xFF> s_processor_infos;
static BAN::Atomic<size_t> s_next_processor_index { 0 };
BAN::ErrorOr<Scheduler*> Scheduler::create()
{
auto* scheduler = new Scheduler();
@@ -151,7 +148,6 @@ namespace Kernel
if (&PageTable::current() != &PageTable::kernel())
PageTable::kernel().load();
delete m_current->thread;
delete m_current;
m_thread_count--;
break;
case Thread::State::Executing:
@@ -185,7 +181,6 @@ namespace Kernel
if (&PageTable::current() != &PageTable::kernel())
PageTable::kernel().load();
delete m_current->thread;
delete m_current;
m_thread_count--;
}
@@ -236,7 +231,7 @@ namespace Kernel
const uint64_t current_ns = SystemTimer::get().ns_since_boot();
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()
@@ -300,60 +295,6 @@ namespace Kernel
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 least_loaded_id = Processor::current_id();
@@ -535,7 +476,7 @@ namespace Kernel
thread_info.node->processor_id = least_loaded_id;
Processor::send_smp_message(least_loaded_id, {
.type = Processor::SMPMessage::Type::NewThread,
.new_thread = thread_info.node
.new_thread = thread_info.node->thread
});
thread_info = {
@@ -563,41 +504,52 @@ namespace Kernel
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);
new_node->processor_id = processor_id;
thread->m_scheduler_node = new_node;
return {};
ASSERT(thread->m_scheduler_node.processor_id == PROCESSOR_NONE);
thread->m_scheduler_node.processor_id = processor_id;
}
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 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 (node->processor_id == Processor::current_id())
add_thread(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::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
{
Processor::send_smp_message(node->processor_id, {
.type = Processor::SMPMessage::Type::NewThread,
.new_thread = node
});
m_block_list.push(&thread->m_scheduler_node);
if (m_block_list.front() == &thread->m_scheduler_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)
@@ -605,7 +557,7 @@ namespace Kernel
if (SystemTimer::get().ns_since_boot() >= wake_time_ns)
return;
auto state = Processor::get_interrupt_state();
const auto state = Processor::get_interrupt_state();
Processor::set_interrupt_state(InterruptState::Disabled);
ASSERT(m_current->processor_id == Processor::current_id());
@@ -639,7 +591,39 @@ namespace Kernel
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()
+1 -1
View File
@@ -146,7 +146,7 @@ namespace Kernel
auto slave = m_slave.lock();
if (!slave)
return BAN::Error::from_errno(EIO);
LockGuard _(slave->m_mutex);
LockGuard _(slave->m_input_mutex);
for (size_t i = 0; i < buffer.size(); i++)
slave->handle_input_byte(buffer[i]);
return buffer.size();
+17 -16
View File
@@ -6,6 +6,7 @@
#include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/FS/VirtualFileSystem.h>
#include <kernel/Input/InputDevice.h>
#include <kernel/Lock/BlockableSpinLock.h>
#include <kernel/Lock/LockGuard.h>
#include <kernel/Process.h>
#include <kernel/Terminal/TTY.h>
@@ -81,7 +82,6 @@ namespace Kernel
BAN::RefPtr<TTY> TTY::current()
{
ASSERT(s_tty);
return s_tty;
}
@@ -220,7 +220,7 @@ namespace Kernel
if (ansi_c_str == nullptr)
return;
LockGuard _(m_mutex);
LockGuard _(m_input_mutex);
while (*ansi_c_str)
handle_input_byte(*ansi_c_str++);
after_write();
@@ -269,7 +269,7 @@ namespace Kernel
bool should_flush = false;
bool force_echo = false;
LockGuard _(m_mutex);
LockGuard _(m_input_mutex);
if (!(termios.c_lflag & ICANON))
should_flush = true;
@@ -377,7 +377,8 @@ namespace Kernel
const auto termios = get_termios();
LockGuard _(m_write_lock);
SpinLockGuard _(m_write_lock);
if (termios.c_oflag & OPOST)
{
if ((termios.c_oflag & ONLCR) && ch == NL)
@@ -385,14 +386,16 @@ namespace Kernel
if ((termios.c_oflag & OCRNL) && ch == CR)
return putchar_impl(NL);
}
return putchar_impl(ch);
}
BAN::ErrorOr<size_t> TTY::read_impl(off_t, BAN::ByteSpan buffer)
{
LockGuard _(m_mutex);
LockGuard _(m_input_mutex);
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())
{
@@ -424,13 +427,14 @@ namespace Kernel
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())
{
if (master_has_closed())
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;
@@ -447,15 +451,12 @@ namespace Kernel
void TTY::putchar_current(uint8_t ch)
{
ASSERT(s_tty);
auto tty = s_tty;
ASSERT(tty);
while (!s_tty->m_write_lock.try_lock())
Processor::pause();
s_tty->putchar(ch);
s_tty->after_write();
s_tty->m_write_lock.unlock();
SpinLockGuard _(tty->m_write_lock);
tty->putchar(ch);
tty->after_write();
}
bool TTY::is_initialized()
+49 -47
View File
@@ -50,17 +50,48 @@ namespace Kernel
, m_foreground(driver->palette()[15])
, m_background(driver->palette()[0])
{
m_width = m_terminal_driver->width();
m_height = m_terminal_driver->height();
update_winsize(m_width, m_height);
MUST(set_terminal_driver(driver));
}
m_buffer = new Cell[m_width * m_height];
ASSERT(m_buffer);
BAN::ErrorOr<void> VirtualTTY::set_terminal_driver(BAN::RefPtr<TerminalDriver> terminal_driver)
{
const uint32_t new_width = terminal_driver->width();
const uint32_t new_height = terminal_driver->height();
SpinLockGuard _(m_write_lock);
if (m_width != new_width || m_height != new_height)
{
Cell* new_buffer = new Cell[new_width * new_height];
ASSERT(new_buffer);
for (uint32_t i = 0; i < new_width * m_height; i++)
new_buffer[i] = { .foreground = m_foreground, .background = m_background, .codepoint = ' ' };
for (uint32_t y = 0; y < BAN::Math::min<uint32_t>(m_height, new_height); y++)
for (uint32_t x = 0; x < BAN::Math::min<uint32_t>(m_width, new_width); x++)
new_buffer[y * new_width + x] = m_buffer[y * m_width + x];
delete[] m_buffer;
m_buffer = new_buffer;
m_width = new_width;
m_height = new_height;
}
m_terminal_driver = terminal_driver;
for (uint32_t y = 0; y < m_height; y++)
for (uint32_t x = 0; x < m_width; x++)
render_from_buffer(x, y);
update_winsize(new_width, new_height);
return {};
}
void VirtualTTY::clear()
{
LockGuard _(m_write_lock);
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);
@@ -70,46 +101,14 @@ namespace Kernel
{
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)
{
Cell* new_buffer = new Cell[new_width * new_height];
ASSERT(new_buffer);
for (uint32_t i = 0; i < new_width * m_height; i++)
new_buffer[i] = { .foreground = m_foreground, .background = m_background, .codepoint = ' ' };
for (uint32_t y = 0; y < BAN::Math::min<uint32_t>(m_height, new_height); y++)
for (uint32_t x = 0; x < BAN::Math::min<uint32_t>(m_width, new_width); x++)
new_buffer[y * new_width + x] = m_buffer[y * m_width + x];
delete[] m_buffer;
m_buffer = new_buffer;
m_width = new_width;
m_height = new_height;
}
for (uint32_t y = 0; y < m_height; y++)
for (uint32_t x = 0; x < m_width; x++)
render_from_buffer(x, y);
}
update_winsize(m_width, m_height);
TRY(m_terminal_driver->set_font(BAN::move(font)));
MUST(set_terminal_driver(m_terminal_driver));
return {};
}
void VirtualTTY::reset_ansi()
{
ASSERT(m_write_lock.is_locked_by_current_thread());
ASSERT(m_write_lock.current_processor_has_lock());
m_ansi_state = {
.nums = { -1, -1, -1, -1, -1 },
.index = 0,
@@ -120,7 +119,7 @@ namespace Kernel
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();
@@ -203,7 +202,8 @@ namespace Kernel
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)
{
case '0' ... '9':
@@ -445,7 +445,7 @@ namespace Kernel
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);
const auto& cell = m_buffer[y * m_width + x];
m_terminal_driver->putchar_at(cell.codepoint, x, y, cell.foreground, cell.background);
@@ -453,7 +453,7 @@ namespace Kernel
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);
auto& cell = m_buffer[y * m_width + x];
cell.codepoint = codepoint;
@@ -464,6 +464,8 @@ namespace Kernel
void VirtualTTY::scroll_if_needed()
{
ASSERT(m_write_lock.current_processor_has_lock());
while (m_row >= m_height)
{
memmove(m_buffer, m_buffer + m_width, m_width * (m_height - 1) * sizeof(Cell));
@@ -487,7 +489,7 @@ namespace Kernel
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)
{
@@ -533,7 +535,7 @@ namespace Kernel
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;
+1
View File
@@ -240,6 +240,7 @@ namespace Kernel
Thread::Thread(pid_t tid, Process* process)
: m_tid(tid), m_process(process)
, m_scheduler_node(this)
{
if (!s_default_sse_storage_initialized)
initialize_default_sse_storage();
+1 -1
View File
@@ -37,7 +37,7 @@ namespace Kernel
node->block_chain_prev = nullptr;
node->block_chain_next = nullptr;
Processor::scheduler().unblock_thread(node);
Processor::scheduler().unblock_thread(node->thread);
node = next;
}
+3
View File
@@ -134,6 +134,9 @@ namespace Kernel
case USB::DeviceBaseClass::DiagnosticDevice:
dprintln_if(DEBUG_USB, "Found DiagnosticDevice device");
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:
dprintln_if(DEBUG_USB, "Found Miscellaneous device");
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));
TRY(Processor::scheduler().add_thread(m_port_updater));
Processor::scheduler().add_thread(m_port_updater);
return {};
}
+1 -1
View File
@@ -149,7 +149,7 @@ namespace Kernel
continue;
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 {};
}
+49 -20
View File
@@ -68,6 +68,8 @@ static bool should_disable_serial(BAN::StringView full_command_line)
extern bool g_disable_debug;
static ParsedCommandLine cmdline;
static bool s_has_early_console { false };
static void parse_command_line()
{
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())
dprintln("failed to initialize terminal driver: {}", ret.error());
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)
InterruptController::get().initialize_multiprocessor();
@@ -171,18 +190,6 @@ extern "C" void kernel_main(uint32_t boot_magic, uint32_t boot_info)
MUST(SharedMemoryObjectManager::initialize());
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();
dprintln("RNG initialized");
@@ -196,7 +203,7 @@ extern "C" void kernel_main(uint32_t boot_magic, uint32_t boot_info)
MUST(Processor::scheduler().initialize());
auto* init_thread = MUST(Thread::create_kernel(init2, nullptr));
MUST(Processor::scheduler().add_thread(init_thread));
Processor::scheduler().add_thread(init_thread);
Processor::yield();
ASSERT_NOT_REACHED();
@@ -213,10 +220,6 @@ static void init2(void*)
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
// ACPI might require PCI access during its namespace initialization
PCI::PCIManager::initialize();
@@ -256,6 +259,32 @@ static void init2(void*)
PCI::PCIManager::get().initialize_devices(cmdline.disable_usb);
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);
dprintln("VFS initialized");
@@ -266,9 +295,9 @@ static void init2(void*)
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();
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()
+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)
+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
}
+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"
'--enable-cross-compile'
'--enable-shared'
'--disable-static'
'--disable-doc'
'--enable-gpl'
'--enable-version3'
'--enable-openssl'
)
configure() {
./configure "${CONFIGURE_OPTIONS[@]}"
./configure "${CONFIGURE_OPTIONS[@]}" || exit 1
}
+9
View File
@@ -26,3 +26,12 @@ build() {
install() {
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
}
+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',
+30
View File
@@ -0,0 +1,30 @@
#!/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'
)
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() {
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"
}
+8 -3
View File
@@ -34,10 +34,15 @@ post_install() {
export HARFBUZZ_CIRCULAR=1
for circular in freetype cairo; do
pushd "$BANAN_PORT_DIR/$circular" >/dev/null || exit 1
pushd "$BANAN_PORT_DIR/freetype" >/dev/null || exit 1
rm -f .compile_hash
./build.sh || exit 1
popd >/dev/null
if grep -q cairo "$BANAN_PORT_DIR/.installed_ports"; then
pushd "$BANAN_PORT_DIR/cairo" >/dev/null || exit 1
rm -f .compile_hash
./build.sh || exit 1
popd >/dev/null
done
fi
}
+35 -2
View File
@@ -54,6 +54,8 @@ MAKE_INSTALL_TARGETS=('install')
CONFIG_SUB=()
REVISION=1
clean() {
find . -mindepth 1 -maxdepth 1 -not -name 'patches' -not -name 'build.sh' -exec rm -rf {} +
}
@@ -111,12 +113,16 @@ post_install() {
install() {
for target in "${MAKE_INSTALL_TARGETS[@]}"; do
make $target "DESTDIR=$BANAN_SYSROOT" || exit 1
make $target "DESTDIR=$DESTDIR" || exit 1
done
}
source $1
if [ -z $DESCRIPTION ]; then
DESCRIPTION="TODO description for $NAME"
fi
if [ -z $NAME ] || [ -z $VERSION ] || [ -z $DOWNLOAD_URL ]; then
echo "Port does not set needed environment variables" >&2
exit 1
@@ -255,6 +261,33 @@ fi
DESTDIR="$BANAN_SYSROOT"
pre_install
install
grep -qsxF "$NAME-$VERSION" "$installed_file" || echo "$NAME-$VERSION" >> "$installed_file"
post_install
find "$BANAN_SYSROOT/usr/lib" -name '*.la' -delete
grep -qsxF "$NAME-$VERSION" "$installed_file" || echo "$NAME-$VERSION" >> "$installed_file"
if (( $PACKAGE )); then
PACKAGE_DIR="$BANAN_PORT_DIR/package"
version="$VERSION"
if [[ "$version" = 'git' ]]; then
version=0.0
fi
package_dir="${PACKAGE_DIR}/${NAME}-${version}_${REVISION}-${BANAN_ARCH}"
mkdir "$package_dir" &>/dev/null || exit 0
dependencies=''
for dep in "${DEPENDENCIES[@]}"; do
dependencies+="$dep>=0 "
done
echo $dependencies > "$package_dir.deps"
DESTDIR="$package_dir"
pre_install
install
post_install
mkdir -p "$PACKAGE_DIR/repo"
cd "$PACKAGE_DIR/repo"
xbps-create -A $BANAN_ARCH -n "$NAME-${version}_$REVISION" -s "$DESCRIPTION" -D "$dependencies" "$package_dir"
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
}
+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'
)
@@ -0,0 +1,31 @@
diff -ruN libcroco-0.6.13/configure libcroco-0.6.13-banan_os/configure
--- libcroco-0.6.13/configure 2019-04-06 20:28:06.000000000 +0300
+++ libcroco-0.6.13-banan_os/configure 2026-08-24 18:29:35.868215552 +0300
@@ -5609,6 +5609,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
;;
@@ -10822,6 +10826,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"
+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>
+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"
+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' '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
}
+1 -1
View File
@@ -20,5 +20,5 @@ build() {
install() {
DESTDIR="$DESTDIR" cmake --install build || exit 1
ln -s sdl2-compat.pc "$DESTDIR"/usr/lib/pkgconfig/sdl2.pc || exit 1
ln -sf sdl2-compat.pc "$DESTDIR"/usr/lib/pkgconfig/sdl2.pc || exit 1
}
+4 -2
View File
@@ -1,12 +1,14 @@
#!/bin/bash ../install.sh
NAME='shared-mime-info'
VERSION='2.4'
DOWNLOAD_URL="https://gitlab.freedesktop.org/xdg/shared-mime-info/-/archive/$VERSION/shared-mime-info-$VERSION.tar.gz#531291d0387eb94e16e775d7e73788d06d2b2fdd8cd2ac6b6b15287593b6a2de"
VERSION='2.5.1'
DOWNLOAD_URL="https://gitlab.freedesktop.org/xdg/shared-mime-info/-/archive/$VERSION/shared-mime-info-$VERSION.tar.gz#ea248ea157b7fa0165f4fe282c84919fa84c3f175553642f229c8f1ab7539128"
DEPENDENCIES=('glib' 'libxml2')
CONFIGURE_OPTIONS=(
'-Dprefix=/usr'
'-Dbuildtype=release'
'-Dbuild-spec=false'
'-Dbuild-tools=false'
'-Dbuild-tests=false'
'-Dbuild-translations=false'
'-Dupdate-mimedb=true'
+6 -14
View File
@@ -23,25 +23,17 @@ namespace LibAudio
return result;
}
BAN::ErrorOr<Audio> Audio::load(BAN::StringView path)
BAN::ErrorOr<Audio> Audio::create(BAN::UniqPtr<AudioStream>&& audio_stream)
{
Audio result(TRY(AudioStream::load(path)));
TRY(result.initialize(256 * 1024));
Audio result(BAN::move(audio_stream));
TRY(result.initialize(result.m_audio_stream->channels() * result.m_audio_stream->sample_rate()));
return result;
}
BAN::ErrorOr<Audio> Audio::random(uint32_t samples)
BAN::ErrorOr<Audio> Audio::load(BAN::StringView path)
{
Audio result;
TRY(result.initialize(samples));
result.m_audio_buffer->sample_rate = 48000;
result.m_audio_buffer->channels = 1;
for (size_t i = 0; i < samples - 1; i++)
result.m_audio_buffer->samples[i] = (rand() - RAND_MAX / 2) / (RAND_MAX / 2.0);
result.m_audio_buffer->head = samples - 1;
Audio result(TRY(AudioStream::load(path)));
TRY(result.initialize(result.m_audio_stream->channels() * result.m_audio_stream->sample_rate()));
return result;
}
@@ -0,0 +1,36 @@
#include <LibAudio/AudioStreams/SineWaveAudioStream.h>
#include <BAN/Math.h>
namespace LibAudio
{
BAN::ErrorOr<BAN::UniqPtr<AudioStream>> SineWaveAudioStream::create(uint32_t channels, uint32_t sample_rate, float frequency)
{
auto* stream_ptr = new SineWaveAudioStream(channels, sample_rate, frequency);
if (stream_ptr == nullptr)
return BAN::Error::from_errno(ENOMEM);
return BAN::UniqPtr<AudioStream>::adopt(stream_ptr);
}
SineWaveAudioStream::SineWaveAudioStream(uint32_t channels, uint32_t sample_rate, float frequency)
: m_channels(channels)
, m_sample_rate(sample_rate)
, m_frequency(frequency)
, m_phase_inc(2.0f * BAN::numbers::pi_v<float> * m_frequency / m_sample_rate)
{ }
float SineWaveAudioStream::get_sample()
{
if (m_sample_idx++ % m_channels == 0)
{
m_phase += m_phase_inc;
if (m_phase >= 2.0f * BAN::numbers::pi_v<float>)
m_phase -= 2.0f * BAN::numbers::pi_v<float>;
m_sample = BAN::Math::sin(m_phase);
}
return m_sample;
}
}
@@ -2,6 +2,7 @@ set(LIBAUDIO_SOURCES
Audio.cpp
AudioStream.cpp
AudioStreams/WAVAudioStream.cpp
AudioStreams/SineWaveAudioStream.cpp
)
add_library(libaudio ${LIBAUDIO_SOURCES})
@@ -30,8 +30,8 @@ namespace LibAudio
public:
static BAN::ErrorOr<Audio> create(uint32_t channels, uint32_t sample_rate, uint32_t sample_frames);
static BAN::ErrorOr<Audio> create(BAN::UniqPtr<AudioStream>&&);
static BAN::ErrorOr<Audio> load(BAN::StringView path);
static BAN::ErrorOr<Audio> random(uint32_t samples);
~Audio() { clear(); }
Audio(Audio&& other) { *this = BAN::move(other); }
@@ -0,0 +1,35 @@
#pragma once
#include <LibAudio/AudioStream.h>
#include <BAN/Limits.h>
namespace LibAudio
{
class SineWaveAudioStream : public AudioStream
{
public:
static BAN::ErrorOr<BAN::UniqPtr<AudioStream>> create(uint32_t channels, uint32_t sample_rate, float frequency);
uint32_t channels() const override { return m_channels; }
uint32_t sample_rate() const override { return m_sample_rate; }
uint32_t samples_remaining() const override { return BAN::numeric_limits<uint32_t>::max(); }
float get_sample() override;
private:
SineWaveAudioStream(uint32_t channels, uint32_t sample_rate, float frequency);
private:
const uint32_t m_channels;
const uint32_t m_sample_rate;
const float m_frequency;
const float m_phase_inc;
uint32_t m_sample_idx { 0 };
float m_sample { 0 };
float m_phase { 0 };
};
}
+1
View File
@@ -49,6 +49,7 @@ set(LIBC_SOURCES
sys/futex.cpp
sys/ioctl.cpp
sys/mman.cpp
sys/random.cpp
sys/resource.cpp
sys/select.cpp
sys/shm.cpp
@@ -15,6 +15,25 @@ struct framebuffer_info_t
uint32_t height;
};
struct fb_fix_info
{
uint32_t xpanstep;
uint32_t ypanstep;
uint32_t pitch;
uint64_t mem_start;
uint32_t mem_size;
};
struct fb_var_info
{
uint32_t xres;
uint32_t yres;
uint32_t xres_virt;
uint32_t yres_virt;
uint32_t xoff;
uint32_t yoff;
uint32_t bpp;
};
__END_DECLS
#endif
@@ -0,0 +1,19 @@
#ifndef _SYS_RANDOM_H
#define _SYS_RANDOM_H 1
#include <sys/cdefs.h>
__BEGIN_DECLS
#define __need_size_t
#define __need_ssize_t
#include <sys/types.h>
#define GRND_RANDOM 0x01
#define GRND_NONBLOCK 0x02
ssize_t getrandom(void* buf, size_t size, unsigned int flags);
__END_DECLS
#endif
+37
View File
@@ -0,0 +1,37 @@
#include <fcntl.h>
#include <sys/random.h>
ssize_t getrandom(void* buf, size_t size, unsigned int flags)
{
const unsigned int valid_flags = GRND_RANDOM | GRND_NONBLOCK;
if ((flags & valid_flags) != flags)
{
errno = EINVAL;
return -1;
}
const char* path = (flags & GRND_RANDOM) ? "/dev/random" : "/dev/urandom";
int oflag = O_RDONLY;
if (flags & GRND_NONBLOCK)
oflag |= O_NONBLOCK;
int fd = open(path, oflag);
if (fd == -1)
return -1;
uint8_t* ubuf = static_cast<uint8_t*>(buf);
size_t total_read = 0;
while (total_read < size)
{
const ssize_t nread = read(fd, ubuf + total_read, size - total_read);
if (nread <= 0)
break;
total_read += nread;
}
close(fd);
return total_read;
}
+12 -17
View File
@@ -47,30 +47,25 @@ int clock_gettime(clockid_t clock_id, struct timespec* tp)
} while (seq1 != seq2 || (seq1 & 1));
};
read_tsc_info:
if (g_shared_page->features & Kernel::API::SPF_RDTSCP)
{
uint32_t cpu;
curr_tsc = __builtin_ia32_rdtscp(&cpu);
read_tsc_info(g_shared_page->cpus[cpu].gettime_local);
do {
uint32_t cpu;
curr_tsc = __builtin_ia32_rdtscp(&cpu);
read_tsc_info(g_shared_page->cpus[cpu].gettime_local);
} while (curr_tsc < last_tsc);
}
else for (;;)
else
{
uint16_t cpu1, cpu2;
asm volatile("lsl %1, %0" : "=r"(cpu1) : "r"(g_shared_page->gdt_cpu_offset));
curr_tsc = __builtin_ia32_rdtsc();
asm volatile("lsl %1, %0" : "=r"(cpu2) : "r"(g_shared_page->gdt_cpu_offset));
if (cpu1 != cpu2)
continue;
read_tsc_info(g_shared_page->cpus[cpu1].gettime_local);
break;
do {
asm volatile("lsl %1, %0" : "=r"(cpu1) : "r"(g_shared_page->gdt_cpu_offset));
read_tsc_info(g_shared_page->cpus[cpu1].gettime_local);
curr_tsc = __builtin_ia32_rdtsc();
asm volatile("lsl %1, %0" : "=r"(cpu2) : "r"(g_shared_page->gdt_cpu_offset));
} while (cpu1 != cpu2);
}
// NOTE: as we read TSC before getting the calibration, it is possible
// for the calibration to get updated in between.
if (curr_tsc < last_tsc)
goto read_tsc_info;
uint64_t clock_ns = curr_tsc - last_tsc;
if (shift >= 0)
clock_ns <<= shift;
+30 -8
View File
@@ -1,4 +1,5 @@
#include <LibAudio/Audio.h>
#include <LibAudio/AudioStreams/SineWaveAudioStream.h>
#include <stdio.h>
#include <unistd.h>
@@ -7,18 +8,39 @@ int main(int argc, char** argv)
{
if (argc != 2)
{
fprintf(stderr, "usage: %s FILE\n", argv[0]);
fprintf(stderr, "usage: %s FREQ|FILE\n", argv[0]);
return 1;
}
auto audio_or_error = LibAudio::Audio::load(argv[1]);
if (audio_or_error.is_error())
{
fprintf(stderr, "failed to load %s: %s\n", argv[1], audio_or_error.error().get_message());
return 1;
}
auto audio = [argv]() -> LibAudio::Audio {
char* endp;
float freq = strtof(argv[1], &endp);
auto audio = audio_or_error.release_value();
if (*endp != '\0')
{
auto audio_or_error = LibAudio::Audio::load(argv[1]);
if (!audio_or_error.is_error())
return audio_or_error.release_value();
fprintf(stderr, "failed to load %s: %s\n", argv[1], audio_or_error.error().get_message());
exit(1);
}
auto sine_stream = LibAudio::SineWaveAudioStream::create(2, 48000, freq);
if (sine_stream.is_error())
{
fprintf(stderr, "failed to create sine wave stream: %s\n", sine_stream.error().get_message());
exit(1);
}
auto audio_or_error = LibAudio::Audio::create(sine_stream.release_value());
if (audio_or_error.is_error())
{
fprintf(stderr, "failed to create sine wave stream: %s\n", audio_or_error.error().get_message());
exit(1);
}
return audio_or_error.release_value();
}();
if (auto ret = audio.start(); ret.is_error())
{
+68 -2
View File
@@ -2,6 +2,7 @@
#include <BAN/Optional.h>
#include <BAN/Vector.h>
#include <dirent.h>
#include <fcntl.h>
#include <grp.h>
#include <pwd.h>
@@ -9,8 +10,70 @@
#include <stdlib.h>
#include <string.h>
#include <sys/banan-os.h>
#include <sys/random.h>
#include <termios.h>
static void generate_machine_id()
{
int fd = open("/etc/machine-id", O_WRONLY | O_CREAT | O_EXCL, 0444);
if (fd == -1)
return;
uint8_t machine_id[16];
if (getrandom(machine_id, sizeof(machine_id), 0) < static_cast<ssize_t>(sizeof(machine_id)))
{
unlinkat(fd, nullptr, 0);
close(fd);
return;
}
for (size_t i = 0; i < sizeof(machine_id); i++)
dprintf(fd, "%02x", machine_id[i]);
dprintf(fd, "\n");
close(fd);
}
static void run_init_scripts()
{
DIR* dirp = opendir("/etc/init.d");
if (dirp == nullptr)
return;
dirent* dirent;
while ((dirent = readdir(dirp)))
{
if (dirent->d_type != DT_REG)
continue;
char script_path[PATH_MAX];
sprintf(script_path, "/etc/init.d/%s", dirent->d_name);
const pid_t pid = fork();
if (pid == -1)
continue;
if (pid == 0)
{
execl(script_path, script_path, nullptr);
exit(1);
}
int status;
while (waitpid(pid, &status, 0) == -1 && errno == EINTR)
continue;
if (WIFSIGNALED(status))
dwarnln("'{}' was killed by signal {}", script_path, strsignal(WTERMSIG(status)));
else if (const int exit_code = WEXITSTATUS(status))
dwarnln("'{}' exited with {}", script_path, exit_code);
else
dprintln("'{}' succeeded", script_path);
}
closedir(dirp);
}
int main(int argc, char** argv)
{
ASSERT(argc == 2);
@@ -29,6 +92,11 @@ int main(int argc, char** argv)
perror("load_keymap");
setenv("TERM", "ansi", 1);
setenv("PATH", "/bin:/usr/bin", 1);
generate_machine_id();
run_init_scripts();
if (fork() == 0)
{
@@ -114,8 +182,6 @@ int main(int argc, char** argv)
if (setuid(pwd->pw_uid) == -1)
perror("setuid");
setenv("PATH", "/bin:/usr/bin", 0);
setenv("HOME", pwd->pw_dir, 1);
chdir(pwd->pw_dir);