Compare commits
38
Commits
315d8895a7
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
68c741d54d | ||
|
|
f9487b63b0 | ||
|
|
1a3dc080e6 | ||
|
|
1a227504e2 | ||
|
|
69d8927c12 | ||
|
|
9b5fd077d2 | ||
|
|
889415b22a | ||
|
|
da94e21dbe | ||
|
|
501783e9ae | ||
|
|
f1f2f2aa25 | ||
|
|
f2d08a85a5 | ||
|
|
44189938d7 | ||
|
|
c6536260c3 | ||
|
|
d22ff2cbc4 | ||
|
|
48d8902e98 | ||
|
|
b4349511f4 | ||
|
|
b42b16add7 | ||
|
|
8fd18eef4d | ||
|
|
1e7afa11d7 | ||
|
|
1cfcd76588 | ||
|
|
179f76114b | ||
|
|
65e559596b | ||
|
|
98c11ee33b | ||
|
|
2f4fec9ab9 | ||
|
|
a38e29c59d | ||
|
|
c6a435ed36 | ||
|
|
2e22ebf0b5 | ||
|
|
cd6269d406 | ||
|
|
9a9a4fe8c0 | ||
|
|
f163dacce5 | ||
|
|
7e7ca3d929 | ||
|
|
c00f37b930 | ||
|
|
ace5edfda2 | ||
|
|
17813f3fcf | ||
|
|
cce6e417df | ||
|
|
8eb572d038 | ||
|
|
cee65bd68e | ||
|
|
74d7a48c4b |
@@ -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
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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 {};
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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>;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 { };
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ namespace Kernel
|
||||
Hub = 0x09,
|
||||
BillboardDeviceClass = 0x11,
|
||||
DiagnosticDevice = 0xDC,
|
||||
WirelessController = 0xE0,
|
||||
Miscellaneous = 0xEF,
|
||||
VendorSpecific = 0xFF,
|
||||
};
|
||||
|
||||
+78
-69
@@ -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())
|
||||
{
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 {};
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 {};
|
||||
|
||||
@@ -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 });
|
||||
|
||||
@@ -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 {};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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()
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {};
|
||||
}
|
||||
|
||||
@@ -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
@@ -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()
|
||||
|
||||
Executable
+31
@@ -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)
|
||||
Executable
+35
@@ -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
|
||||
}
|
||||
Executable
+26
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
Executable
+26
@@ -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
|
||||
}
|
||||
Executable
+31
@@ -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
|
||||
}
|
||||
Executable
+33
@@ -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',
|
||||
Executable
+30
@@ -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 ***
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
Executable
+23
@@ -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
|
||||
Executable
+29
@@ -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
|
||||
}
|
||||
Executable
+28
@@ -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
|
||||
}
|
||||
Executable
+11
@@ -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"
|
||||
Executable
+21
@@ -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)
|
||||
Executable
+12
@@ -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"
|
||||
Executable
+15
@@ -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>
|
||||
Executable
+5
@@ -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"
|
||||
Executable
+21
@@ -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
|
||||
}
|
||||
Executable
+28
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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 };
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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())
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user