Compare commits

..

No commits in common. "684fa1c4b01366b44cf15835237ef176e3722148" and "f022a1b08ffd73982eb24042c318f98b3cb982fb" have entirely different histories.

145 changed files with 952 additions and 3863 deletions

View File

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

View File

@ -6,19 +6,6 @@
#include <float.h>
// This is ugly but my clangd does not like including
// intrinsic headers at all
#if !defined(__SSE__) || !defined(__SSE2__)
#pragma GCC push_options
#ifndef __SSE__
#pragma GCC target("sse")
#endif
#ifndef __SSE2__
#pragma GCC target("sse2")
#endif
#define BAN_MATH_POP_OPTIONS
#endif
namespace BAN::Math
{
@ -180,7 +167,7 @@ namespace BAN::Math
template<floating_point T>
static T modf(T x, T* iptr)
{
const T frac = BAN::Math::fmod<T>(x, (T)1.0);
const T frac = BAN::Math::fmod<T>(x, 1);
*iptr = x - frac;
return frac;
}
@ -188,15 +175,15 @@ namespace BAN::Math
template<floating_point T>
inline constexpr T frexp(T num, int* exp)
{
if (num == (T)0.0)
if (num == 0.0)
{
*exp = 0;
return (T)0.0;
return 0.0;
}
T e;
asm("fxtract" : "+t"(num), "=u"(e));
*exp = (int)e + 1;
T _exp;
asm("fxtract" : "+t"(num), "=u"(_exp));
*exp = (int)_exp + 1;
return num / (T)2.0;
}
@ -264,7 +251,6 @@ namespace BAN::Math
"fstp %%st(1);"
: "+t"(x)
);
return x;
}
@ -277,9 +263,18 @@ namespace BAN::Math
template<floating_point T>
inline constexpr T pow(T x, T y)
{
if (x == (T)0.0)
return (T)0.0;
return exp2<T>(y * log2<T>(x));
asm(
"fyl2x;"
"fld1;"
"fld %%st(1);"
"fprem;"
"f2xm1;"
"faddp;"
"fscale;"
: "+t"(x), "+u"(y)
);
return x;
}
template<floating_point T>
@ -314,28 +309,17 @@ namespace BAN::Math
template<floating_point T>
inline constexpr T sqrt(T x)
{
if constexpr(BAN::is_same_v<T, float>)
{
using v4sf = float __attribute__((vector_size(16)));
return __builtin_ia32_sqrtss((v4sf) { x, 0.0f, 0.0f, 0.0f })[0];
}
else if constexpr(BAN::is_same_v<T, double>)
{
using v2df = double __attribute__((vector_size(16)));
return __builtin_ia32_sqrtsd((v2df) { x, 0.0 })[0];
}
else if constexpr(BAN::is_same_v<T, long double>)
{
asm("fsqrt" : "+t"(x));
return x;
}
}
template<floating_point T>
inline constexpr T cbrt(T value)
{
return pow<T>(value, (T)1.0 / (T)3.0);
if (value == 0.0)
return 0.0;
return pow<T>(value, 1.0 / 3.0);
}
template<floating_point T>
@ -362,21 +346,30 @@ namespace BAN::Math
inline constexpr T tan(T x)
{
T one, ret;
asm("fptan" : "=t"(one), "=u"(ret) : "0"(x));
asm(
"fptan"
: "=t"(one), "=u"(ret)
: "0"(x)
);
return ret;
}
template<floating_point T>
inline constexpr T atan2(T y, T x)
{
asm("fpatan" : "+t"(x) : "u"(y) : "st(1)");
asm(
"fpatan"
: "+t"(x)
: "u"(y)
: "st(1)"
);
return x;
}
template<floating_point T>
inline constexpr T atan(T x)
{
return atan2<T>(x, (T)1.0);
return atan2<T>(x, 1.0);
}
template<floating_point T>
@ -385,10 +378,10 @@ namespace BAN::Math
if (x == (T)0.0)
return (T)0.0;
if (x == (T)1.0)
return +numbers::pi_v<T> / (T)2.0;
return numbers::pi_v<T> / (T)2.0;
if (x == (T)-1.0)
return -numbers::pi_v<T> / (T)2.0;
return (T)2.0 * atan<T>(x / ((T)1.0 + sqrt<T>((T)1.0 - x * x)));
return (T)2.0 * atan<T>(x / (T(1.0) + sqrt<T>((T)1.0 - x * x)));
}
template<floating_point T>
@ -418,7 +411,7 @@ namespace BAN::Math
template<floating_point T>
inline constexpr T tanh(T x)
{
const T exp_px = exp<T>(+x);
const T exp_px = exp<T>(x);
const T exp_nx = exp<T>(-x);
return (exp_px - exp_nx) / (exp_px + exp_nx);
}
@ -448,8 +441,3 @@ namespace BAN::Math
}
}
#ifdef BAN_MATH_POP_OPTIONS
#undef BAN_MATH_POP_OPTIONS
#pragma GCC pop_options
#endif

View File

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

View File

@ -69,6 +69,7 @@ namespace BAN
value_type* data() const
{
ASSERT(m_data);
return m_data;
}
@ -83,6 +84,7 @@ namespace BAN
Span slice(size_type start, size_type length = ~size_type(0)) const
{
ASSERT(m_data);
ASSERT(start <= m_size);
if (length == ~size_type(0))
length = m_size - start;

View File

@ -14,7 +14,6 @@ namespace BAN
{
public:
using size_type = size_t;
using value_type = char;
using iterator = IteratorSimple<char, String>;
using const_iterator = ConstIteratorSimple<char, String>;
static constexpr size_type sso_capacity = 15;
@ -353,9 +352,10 @@ namespace BAN::Formatter
{
template<typename F>
void print_argument(F putc, const String& string, const ValueFormat& format)
void print_argument(F putc, const String& string, const ValueFormat&)
{
print_argument(putc, string.sv(), format);
for (String::size_type i = 0; i < string.size(); i++)
putc(string[i]);
}
}

View File

@ -14,7 +14,6 @@ namespace BAN
{
public:
using size_type = size_t;
using value_type = char;
using const_iterator = ConstIteratorSimple<char, StringView>;
public:
@ -247,12 +246,10 @@ namespace BAN::Formatter
{
template<typename F>
void print_argument(F putc, const StringView& sv, const ValueFormat& format)
void print_argument(F putc, const StringView& sv, const ValueFormat&)
{
for (StringView::size_type i = 0; i < sv.size(); i++)
putc(sv[i]);
for (int i = sv.size(); i < format.fill; i++)
putc(' ');
}
}

View File

@ -61,9 +61,6 @@ namespace BAN
template<typename T> struct is_move_constructible { static constexpr bool value = is_constructible_v<T, T&&>; };
template<typename T> inline constexpr bool is_move_constructible_v = is_move_constructible<T>::value;
template<typename T> struct is_trivially_copyable { static constexpr bool value = __is_trivially_copyable(T); };
template<typename T> inline constexpr bool is_trivially_copyable_v = is_trivially_copyable<T>::value;
template<typename T> struct is_integral { static constexpr bool value = requires (T t, T* p, void (*f)(T)) { reinterpret_cast<T>(t); f(0); p + t; }; };
template<typename T> inline constexpr bool is_integral_v = is_integral<T>::value;
template<typename T> concept integral = is_integral_v<T>;

View File

@ -381,35 +381,10 @@ namespace BAN
template<typename T>
ErrorOr<void> Vector<T>::ensure_capacity(size_type size)
{
static_assert(alignof(T) <= alignof(max_align_t), "over aligned types not supported");
if (m_capacity >= size)
return {};
const size_type new_cap = BAN::Math::max<size_type>(size, m_capacity * 2);
if constexpr (BAN::is_trivially_copyable_v<T>)
{
if constexpr (BAN::reallocator)
{
auto* new_data = static_cast<T*>(BAN::reallocator(m_data, new_cap * sizeof(T)));
if (new_data == nullptr)
return Error::from_errno(ENOMEM);
m_data = new_data;
}
else
{
auto* new_data = static_cast<T*>(BAN::allocator(new_cap * sizeof(T)));
if (new_data == nullptr)
return Error::from_errno(ENOMEM);
memcpy(new_data, m_data, m_size * sizeof(T));
BAN::deallocator(m_data);
m_data = new_data;
}
}
else
{
auto* new_data = static_cast<T*>(BAN::allocator(new_cap * sizeof(T)));
size_type new_cap = BAN::Math::max<size_type>(size, m_capacity * 2);
T* new_data = (T*)BAN::allocator(new_cap * sizeof(T));
if (new_data == nullptr)
return Error::from_errno(ENOMEM);
for (size_type i = 0; i < m_size; i++)
@ -419,8 +394,6 @@ namespace BAN
}
BAN::deallocator(m_data);
m_data = new_data;
}
m_capacity = new_cap;
return {};
}

View File

@ -50,7 +50,6 @@ set(KERNEL_SOURCES
kernel/InterruptController.cpp
kernel/kernel.cpp
kernel/Lock/SpinLock.cpp
kernel/Memory/ByteRingBuffer.cpp
kernel/Memory/DMARegion.cpp
kernel/Memory/FileBackedRegion.cpp
kernel/Memory/Heap.cpp

View File

@ -1,52 +0,0 @@
#pragma once
#include <kernel/FS/Inode.h>
namespace Kernel
{
class EventFD final : public Inode
{
public:
static BAN::ErrorOr<BAN::RefPtr<Inode>> create(uint64_t initval, bool semaphore);
ino_t ino() const override { return 0; }
Mode mode() const override { return { Mode::IFCHR | Mode::IRUSR | Mode::IWUSR }; }
nlink_t nlink() const override { return ref_count(); }
uid_t uid() const override { return 0; }
gid_t gid() const override { return 0; }
off_t size() const override { return 0; }
timespec atime() const override { return {}; }
timespec mtime() const override { return {}; }
timespec ctime() const override { return {}; }
blksize_t blksize() const override { return 8; }
blkcnt_t blocks() const override { return 0; }
dev_t dev() const override { return 0; }
dev_t rdev() const override { return 0; }
const FileSystem* filesystem() const override { return nullptr; }
protected:
BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
BAN::ErrorOr<void> fsync_impl() final override { return {}; }
bool can_read_impl() const override { return m_value > 0; }
bool can_write_impl() const override { return m_value < UINT64_MAX - 1; }
bool has_error_impl() const override { return false; }
bool has_hungup_impl() const override { return false; }
private:
EventFD(uint64_t initval, bool is_semaphore)
: m_is_semaphore(is_semaphore)
, m_value(initval)
{ }
private:
const bool m_is_semaphore;
uint64_t m_value;
ThreadBlocker m_thread_blocker;
};
}

View File

@ -2,7 +2,6 @@
#include <BAN/Array.h>
#include <kernel/FS/Inode.h>
#include <kernel/Memory/ByteRingBuffer.h>
#include <kernel/ThreadBlocker.h>
namespace Kernel
@ -39,7 +38,7 @@ namespace Kernel
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
virtual BAN::ErrorOr<void> fsync_impl() final override { return {}; }
virtual bool can_read_impl() const override { return !m_buffer->empty(); }
virtual bool can_read_impl() const override { return m_buffer_size > 0; }
virtual bool can_write_impl() const override { return true; }
virtual bool has_error_impl() const override { return m_reading_count == 0; }
virtual bool has_hungup_impl() const override { return m_writing_count == 0; }
@ -55,7 +54,9 @@ namespace Kernel
timespec m_ctime {};
ThreadBlocker m_thread_blocker;
BAN::UniqPtr<ByteRingBuffer> m_buffer;
BAN::Array<uint8_t, PAGE_SIZE> m_buffer;
BAN::Atomic<size_t> m_buffer_size { 0 };
size_t m_buffer_tail { 0 };
BAN::Atomic<uint32_t> m_writing_count { 1 };
BAN::Atomic<uint32_t> m_reading_count { 1 };

View File

@ -1,76 +0,0 @@
#pragma once
#include <BAN/ByteSpan.h>
#include <BAN/UniqPtr.h>
#include <BAN/Vector.h>
#include <kernel/Memory/Types.h>
namespace Kernel
{
class ByteRingBuffer
{
public:
static BAN::ErrorOr<BAN::UniqPtr<ByteRingBuffer>> create(size_t size);
~ByteRingBuffer();
void push(BAN::ConstByteSpan data)
{
ASSERT(data.size() + m_size <= m_capacity);
uint8_t* buffer_head = reinterpret_cast<uint8_t*>(m_vaddr) + (m_tail + m_size) % m_capacity;
memcpy(buffer_head, data.data(), data.size());
m_size += data.size();
}
void pop(size_t size)
{
ASSERT(size <= m_size);
m_tail = (m_tail + size) % m_capacity;
m_size -= size;
}
void pop_back(size_t size)
{
ASSERT(size <= m_size);
m_size -= size;
}
BAN::ConstByteSpan get_data() const
{
const uint8_t* base = reinterpret_cast<const uint8_t*>(m_vaddr);
return { base + m_tail, m_size };
}
uint8_t front() const
{
ASSERT(!empty());
return reinterpret_cast<const uint8_t*>(m_vaddr)[m_tail];
}
uint8_t back() const
{
ASSERT(!empty());
return reinterpret_cast<const uint8_t*>(m_vaddr)[m_tail + m_size];
}
bool empty() const { return m_size == 0; }
bool full() const { return m_size == m_capacity; }
size_t free() const { return m_capacity - m_size; }
size_t size() const { return m_size; }
size_t capacity() const { return m_capacity; }
private:
ByteRingBuffer(size_t capacity)
: m_capacity(capacity)
{ }
private:
size_t m_size { 0 };
size_t m_tail { 0 };
const size_t m_capacity;
vaddr_t m_vaddr { 0 };
};
}

View File

@ -31,18 +31,35 @@ namespace Kernel
public:
static BAN::ErrorOr<BAN::UniqPtr<ARPTable>> create();
~ARPTable();
BAN::ErrorOr<BAN::MACAddress> get_mac_from_ipv4(NetworkInterface&, BAN::IPv4Address);
BAN::ErrorOr<void> handle_arp_packet(NetworkInterface&, BAN::ConstByteSpan);
void add_arp_packet(NetworkInterface&, BAN::ConstByteSpan);
private:
ARPTable() = default;
ARPTable();
void packet_handle_task();
BAN::ErrorOr<void> handle_arp_packet(NetworkInterface&, const ARPPacket&);
private:
SpinLock m_arp_table_lock;
struct PendingArpPacket
{
NetworkInterface& interface;
ARPPacket packet;
};
private:
SpinLock m_table_lock;
SpinLock m_pending_lock;
BAN::HashMap<BAN::IPv4Address, BAN::MACAddress> m_arp_table;
Thread* m_thread { nullptr };
BAN::CircularQueue<PendingArpPacket, 128> m_pending_packets;
ThreadBlocker m_pending_thread_blocker;
friend class BAN::UniqPtr<ARPTable>;
};

View File

@ -23,14 +23,14 @@ namespace Kernel
static BAN::ErrorOr<BAN::RefPtr<E1000>> create(PCI::Device&);
~E1000();
BAN::MACAddress get_mac_address() const override { return m_mac_address; }
virtual BAN::MACAddress get_mac_address() const override { return m_mac_address; }
bool link_up() override { return m_link_up; }
int link_speed() override;
virtual bool link_up() override { return m_link_up; }
virtual int link_speed() override;
size_t payload_mtu() const override { return E1000_RX_BUFFER_SIZE - sizeof(EthernetHeader); }
virtual size_t payload_mtu() const override { return E1000_RX_BUFFER_SIZE - sizeof(EthernetHeader); }
void handle_irq() final override;
virtual void handle_irq() final override;
protected:
E1000(PCI::Device& pci_device)
@ -45,12 +45,12 @@ namespace Kernel
uint32_t read32(uint16_t reg);
void write32(uint16_t reg, uint32_t value);
BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan> payload) override;
virtual BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::ConstByteSpan) override;
bool can_read_impl() const override { return false; }
bool can_write_impl() const override { return false; }
bool has_error_impl() const override { return false; }
bool has_hungup_impl() const override { return false; }
virtual bool can_read_impl() const override { return false; }
virtual bool can_write_impl() const override { return false; }
virtual bool has_error_impl() const override { return false; }
virtual bool has_hungup_impl() const override { return false; }
private:
BAN::ErrorOr<void> read_mac_address();
@ -61,7 +61,7 @@ namespace Kernel
void enable_link();
BAN::ErrorOr<void> enable_interrupt();
void receive_thread();
void handle_receive();
protected:
PCI::Device& m_pci_device;
@ -75,10 +75,6 @@ namespace Kernel
BAN::UniqPtr<DMARegion> m_tx_descriptor_region;
SpinLock m_lock;
bool m_thread_should_die { false };
BAN::Atomic<bool> m_thread_is_dead { true };
ThreadBlocker m_thread_blocker;
BAN::MACAddress m_mac_address {};
bool m_link_up { false };

View File

@ -12,8 +12,8 @@ namespace Kernel
static BAN::ErrorOr<BAN::RefPtr<E1000E>> create(PCI::Device&);
protected:
void detect_eeprom() override;
uint32_t eeprom_read(uint8_t addr) override;
virtual void detect_eeprom() override;
virtual uint32_t eeprom_read(uint8_t addr) override;
private:
E1000E(PCI::Device& pci_device)

View File

@ -38,10 +38,11 @@ namespace Kernel
public:
static BAN::ErrorOr<BAN::UniqPtr<IPv4Layer>> create();
~IPv4Layer();
ARPTable& arp_table() { return *m_arp_table; }
BAN::ErrorOr<void> handle_ipv4_packet(NetworkInterface&, BAN::ConstByteSpan);
void add_ipv4_packet(NetworkInterface&, BAN::ConstByteSpan);
virtual void unbind_socket(uint16_t port) override;
virtual BAN::ErrorOr<void> bind_socket_with_target(BAN::RefPtr<NetworkSocket>, const sockaddr* target_address, socklen_t target_address_len) override;
@ -54,14 +55,34 @@ namespace Kernel
virtual size_t header_size() const override { return sizeof(IPv4Header); }
private:
IPv4Layer() = default;
IPv4Layer();
void add_ipv4_header(BAN::ByteSpan packet, BAN::IPv4Address src_ipv4, BAN::IPv4Address dst_ipv4, uint8_t protocol) const;
BAN::ErrorOr<in_port_t> find_free_port();
private:
BAN::UniqPtr<ARPTable> m_arp_table;
void packet_handle_task();
BAN::ErrorOr<void> handle_ipv4_packet(NetworkInterface&, BAN::ByteSpan);
private:
struct PendingIPv4Packet
{
NetworkInterface& interface;
};
private:
RecursiveSpinLock m_bound_socket_lock;
BAN::UniqPtr<ARPTable> m_arp_table;
Thread* m_thread { nullptr };
static constexpr size_t pending_packet_buffer_size = 128 * PAGE_SIZE;
BAN::UniqPtr<VirtualRange> m_pending_packet_buffer;
BAN::CircularQueue<PendingIPv4Packet, 128> m_pending_packets;
ThreadBlocker m_pending_thread_blocker;
SpinLock m_pending_lock;
size_t m_pending_total_size { 0 };
BAN::HashMap<int, BAN::WeakPtr<NetworkSocket>> m_bound_sockets;
friend class BAN::UniqPtr<IPv4Layer>;

View File

@ -9,7 +9,6 @@ namespace Kernel
{
public:
static constexpr size_t buffer_size = BAN::numeric_limits<uint16_t>::max() + 1;
static constexpr size_t buffer_count = 32;
public:
static BAN::ErrorOr<BAN::RefPtr<LoopbackInterface>> create();
@ -25,9 +24,8 @@ namespace Kernel
LoopbackInterface()
: NetworkInterface(Type::Loopback)
{}
~LoopbackInterface();
BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan> payload) override;
BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::ConstByteSpan) override;
bool can_read_impl() const override { return false; }
bool can_write_impl() const override { return false; }
@ -35,27 +33,8 @@ namespace Kernel
bool has_hungup_impl() const override { return false; }
private:
void receive_thread();
private:
struct Descriptor
{
uint8_t* addr;
uint32_t size;
uint8_t state;
};
private:
Mutex m_buffer_lock;
SpinLock m_buffer_lock;
BAN::UniqPtr<VirtualRange> m_buffer;
uint32_t m_buffer_tail { 0 };
uint32_t m_buffer_head { 0 };
Descriptor m_descriptors[buffer_count] {};
bool m_thread_should_die { false };
BAN::Atomic<bool> m_thread_is_dead { true };
ThreadBlocker m_thread_blocker;
};
}

View File

@ -60,11 +60,7 @@ namespace Kernel
virtual dev_t rdev() const override { return m_rdev; }
virtual BAN::StringView name() const override { return m_name; }
BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::ConstByteSpan payload)
{
return send_bytes(destination, protocol, { &payload, 1 });
}
virtual BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan> payload) = 0;
virtual BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::ConstByteSpan) = 0;
private:
const Type m_type;

View File

@ -11,7 +11,7 @@ namespace Kernel
BAN::IPv4Address src_ipv4 { 0 };
BAN::IPv4Address dst_ipv4 { 0 };
BAN::NetworkEndian<uint16_t> protocol { 0 };
BAN::NetworkEndian<uint16_t> length { 0 };
BAN::NetworkEndian<uint16_t> extra { 0 };
};
static_assert(sizeof(PseudoHeader) == 12);
@ -36,7 +36,6 @@ namespace Kernel
NetworkLayer() = default;
};
uint16_t calculate_internet_checksum(BAN::ConstByteSpan buffer);
uint16_t calculate_internet_checksum(BAN::Span<const BAN::ConstByteSpan> buffers);
uint16_t calculate_internet_checksum(BAN::ConstByteSpan packet, const PseudoHeader& pseudo_header);
}

View File

@ -32,7 +32,7 @@ namespace Kernel
BAN::ErrorOr<BAN::RefPtr<NetworkInterface>> interface(const sockaddr* target, socklen_t target_len);
virtual size_t protocol_header_size() const = 0;
virtual void get_protocol_header(BAN::ByteSpan header, BAN::ConstByteSpan payload, uint16_t dst_port, PseudoHeader) = 0;
virtual void add_protocol_header(BAN::ByteSpan packet, uint16_t dst_port, PseudoHeader) = 0;
virtual NetworkProtocol protocol() const = 0;
virtual void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len) = 0;

View File

@ -29,11 +29,9 @@ namespace Kernel
: NetworkInterface(Type::Ethernet)
, m_pci_device(pci_device)
{ }
~RTL8169();
BAN::ErrorOr<void> initialize();
virtual BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan>) override;
virtual BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::ConstByteSpan) override;
virtual bool can_read_impl() const override { return false; }
virtual bool can_write_impl() const override { return false; }
@ -49,7 +47,7 @@ namespace Kernel
void enable_link();
BAN::ErrorOr<void> enable_interrupt();
void receive_thread();
void handle_receive();
protected:
PCI::Device& m_pci_device;
@ -65,9 +63,6 @@ namespace Kernel
BAN::UniqPtr<DMARegion> m_tx_descriptor_region;
SpinLock m_lock;
bool m_thread_should_die { false };
BAN::Atomic<bool> m_thread_is_dead { true };
ThreadBlocker m_thread_blocker;
uint32_t m_rx_current { 0 };

View File

@ -4,7 +4,7 @@
#include <BAN/Endianness.h>
#include <BAN/Queue.h>
#include <kernel/Lock/Mutex.h>
#include <kernel/Memory/ByteRingBuffer.h>
#include <kernel/Memory/VirtualRange.h>
#include <kernel/Networking/NetworkInterface.h>
#include <kernel/Networking/NetworkSocket.h>
#include <kernel/Thread.h>
@ -50,30 +50,29 @@ namespace Kernel
static BAN::ErrorOr<BAN::RefPtr<TCPSocket>> create(NetworkLayer&, const Info&);
~TCPSocket();
NetworkProtocol protocol() const override { return NetworkProtocol::TCP; }
virtual NetworkProtocol protocol() const override { return NetworkProtocol::TCP; }
size_t protocol_header_size() const override { return sizeof(TCPHeader) + m_tcp_options_bytes; }
void get_protocol_header(BAN::ByteSpan header, BAN::ConstByteSpan payload, uint16_t dst_port, PseudoHeader) override;
virtual size_t protocol_header_size() const override { return sizeof(TCPHeader) + m_tcp_options_bytes; }
virtual void add_protocol_header(BAN::ByteSpan packet, uint16_t dst_port, PseudoHeader) override;
protected:
BAN::ErrorOr<long> accept_impl(sockaddr*, socklen_t*, int) override;
BAN::ErrorOr<void> connect_impl(const sockaddr*, socklen_t) override;
BAN::ErrorOr<void> listen_impl(int) override;
BAN::ErrorOr<void> bind_impl(const sockaddr*, socklen_t) override;
BAN::ErrorOr<size_t> recvmsg_impl(msghdr& message, int flags) override;
BAN::ErrorOr<size_t> sendmsg_impl(const msghdr& message, int flags) override;
BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) override;
BAN::ErrorOr<void> getsockopt_impl(int, int, void*, socklen_t*) override;
BAN::ErrorOr<void> setsockopt_impl(int, int, const void*, socklen_t) override;
virtual BAN::ErrorOr<long> accept_impl(sockaddr*, socklen_t*, int) override;
virtual BAN::ErrorOr<void> connect_impl(const sockaddr*, socklen_t) override;
virtual BAN::ErrorOr<void> listen_impl(int) override;
virtual BAN::ErrorOr<void> bind_impl(const sockaddr*, socklen_t) override;
virtual BAN::ErrorOr<size_t> recvmsg_impl(msghdr& message, int flags) override;
virtual BAN::ErrorOr<size_t> sendmsg_impl(const msghdr& message, int flags) override;
virtual BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) override;
virtual BAN::ErrorOr<void> getsockopt_impl(int, int, void*, socklen_t*) override;
BAN::ErrorOr<long> ioctl_impl(int, void*) override;
virtual BAN::ErrorOr<long> ioctl_impl(int, void*) override;
void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len) override;
virtual void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len) override;
bool can_read_impl() const override;
bool can_write_impl() const override;
bool has_error_impl() const override { return false; }
bool has_hungup_impl() const override;
virtual bool can_read_impl() const override;
virtual bool can_write_impl() const override;
virtual bool has_error_impl() const override { return false; }
virtual bool has_hungup_impl() const override;
private:
enum class State
@ -97,8 +96,9 @@ namespace Kernel
bool has_ghost_byte { false };
uint32_t data_size { 0 }; // number of bytes in this buffer
uint8_t scale_shift { 0 }; // window scale
BAN::UniqPtr<ByteRingBuffer> buffer;
BAN::UniqPtr<VirtualRange> buffer;
};
struct SendWindowInfo
@ -115,10 +115,10 @@ namespace Kernel
uint64_t last_send_ms { 0 }; // last send time, used for retransmission timeout
bool has_ghost_byte { false };
bool had_zero_window { false };
uint32_t data_size { 0 }; // number of bytes in this buffer
uint32_t sent_size { 0 }; // number of bytes in this buffer that have been sent
BAN::UniqPtr<ByteRingBuffer> buffer;
BAN::UniqPtr<VirtualRange> buffer;
};
struct ConnectionInfo
@ -132,8 +132,6 @@ namespace Kernel
{
ConnectionInfo target;
uint32_t target_start_seq;
uint16_t maximum_seqment_size;
uint8_t window_scale;
};
struct ListenKey
@ -168,17 +166,8 @@ namespace Kernel
State m_next_state { State::Closed };
uint8_t m_next_flags { 0 };
size_t m_last_sent_window_size { 0 };
Thread* m_thread { nullptr };
// TODO: actually support these
bool m_keep_alive { false };
bool m_no_delay { false };
bool m_should_send_zero_window { false };
bool m_should_send_window_update { false };
uint64_t m_time_wait_start_ms { 0 };
ThreadBlocker m_thread_blocker;

View File

@ -25,28 +25,27 @@ namespace Kernel
public:
static BAN::ErrorOr<BAN::RefPtr<UDPSocket>> create(NetworkLayer&, const Socket::Info&);
NetworkProtocol protocol() const override { return NetworkProtocol::UDP; }
virtual NetworkProtocol protocol() const override { return NetworkProtocol::UDP; }
size_t protocol_header_size() const override { return sizeof(UDPHeader); }
void get_protocol_header(BAN::ByteSpan header, BAN::ConstByteSpan payload, uint16_t dst_port, PseudoHeader) override;
virtual size_t protocol_header_size() const override { return sizeof(UDPHeader); }
virtual void add_protocol_header(BAN::ByteSpan packet, uint16_t dst_port, PseudoHeader) override;
protected:
void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len) override;
virtual void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len) override;
BAN::ErrorOr<void> connect_impl(const sockaddr*, socklen_t) override;
BAN::ErrorOr<void> bind_impl(const sockaddr* address, socklen_t address_len) override;
BAN::ErrorOr<size_t> recvmsg_impl(msghdr& message, int flags) override;
BAN::ErrorOr<size_t> sendmsg_impl(const msghdr& message, int flags) override;
BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) override { return BAN::Error::from_errno(ENOTCONN); }
BAN::ErrorOr<void> getsockopt_impl(int, int, void*, socklen_t*) override;
BAN::ErrorOr<void> setsockopt_impl(int, int, const void*, socklen_t) override;
virtual BAN::ErrorOr<void> connect_impl(const sockaddr*, socklen_t) override;
virtual BAN::ErrorOr<void> bind_impl(const sockaddr* address, socklen_t address_len) override;
virtual BAN::ErrorOr<size_t> recvmsg_impl(msghdr& message, int flags) override;
virtual BAN::ErrorOr<size_t> sendmsg_impl(const msghdr& message, int flags) override;
virtual BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) override { return BAN::Error::from_errno(ENOTCONN); }
virtual BAN::ErrorOr<void> getsockopt_impl(int, int, void*, socklen_t*) override;
BAN::ErrorOr<long> ioctl_impl(int, void*) override;
virtual BAN::ErrorOr<long> ioctl_impl(int, void*) override;
bool can_read_impl() const override { return !m_packets.empty(); }
bool can_write_impl() const override { return true; }
bool has_error_impl() const override { return false; }
bool has_hungup_impl() const override { return false; }
virtual bool can_read_impl() const override { return !m_packets.empty(); }
virtual bool can_write_impl() const override { return true; }
virtual bool has_error_impl() const override { return false; }
virtual bool has_hungup_impl() const override { return false; }
private:
UDPSocket(NetworkLayer&, const Socket::Info&);

View File

@ -147,8 +147,6 @@ namespace Kernel
BAN::ErrorOr<long> sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event* event);
BAN::ErrorOr<long> sys_epoll_pwait2(int epfd, struct epoll_event* events, int maxevents, const struct timespec* timeout, const sigset_t* sigmask);
BAN::ErrorOr<long> sys_eventfd(unsigned int initval_hi, int flags);
BAN::ErrorOr<long> sys_pipe(int fildes[2]);
BAN::ErrorOr<long> sys_dup2(int fildes, int fildes2);

View File

@ -3,7 +3,6 @@
#include <BAN/Array.h>
#include <kernel/Device/Device.h>
#include <kernel/Lock/SpinLock.h>
#include <kernel/Memory/ByteRingBuffer.h>
#include <kernel/Terminal/TerminalDriver.h>
#include <kernel/ThreadBlocker.h>
#include <LibInput/KeyEvent.h>
@ -103,7 +102,8 @@ namespace Kernel
struct Buffer
{
BAN::UniqPtr<ByteRingBuffer> buffer;
BAN::Array<uint8_t, 1024> buffer;
size_t bytes { 0 };
bool flush { false };
ThreadBlocker thread_blocker;
};

View File

@ -335,8 +335,6 @@ namespace Debug
void print_prefix(const char* file, int line)
{
if (file[0] == '.' && file[1] == '/')
file += 2;
auto ms_since_boot = Kernel::SystemTimer::is_initialized() ? Kernel::SystemTimer::get().ms_since_boot() : 0;
BAN::Formatter::print(Debug::putchar, "[{5}.{3}] {}:{}: ", ms_since_boot / 1000, ms_since_boot % 1000, file, line);
}

View File

@ -21,11 +21,10 @@ namespace Kernel
{
auto ms_since_boot = SystemTimer::get().ms_since_boot();
SpinLockGuard _(Debug::s_debug_lock);
BAN::Formatter::print(Debug::putchar, "[{5}.{3}] {}:{} {}: ",
BAN::Formatter::print(Debug::putchar, "[{5}.{3}] {} {}: ",
ms_since_boot / 1000,
ms_since_boot % 1000,
Kernel::Process::current().pid(),
Thread::current().tid(),
Kernel::Process::current().name()
);
for (size_t i = 0; i < buffer.size(); i++)

View File

@ -209,7 +209,7 @@ namespace Kernel
continue;
SpinLockGuardAsMutex smutex(guard);
TRY(Thread::current().block_or_eintr_or_waketime_ns(m_thread_blocker, waketime_ns, false, &smutex));
TRY(Thread::current().block_or_eintr_or_timeout_ns(m_thread_blocker, waketime_ns - current_ns, false, &smutex));
}
return event_count;

View File

@ -1,54 +0,0 @@
#include <kernel/FS/EventFD.h>
#include <sys/epoll.h>
namespace Kernel
{
BAN::ErrorOr<BAN::RefPtr<Inode>> EventFD::create(uint64_t initval, bool semaphore)
{
auto* eventfd_ptr = new EventFD(initval, semaphore);
if (eventfd_ptr == nullptr)
return BAN::Error::from_errno(ENOMEM);
return BAN::RefPtr<Inode>(BAN::RefPtr<EventFD>::adopt(eventfd_ptr));
}
BAN::ErrorOr<size_t> EventFD::read_impl(off_t, BAN::ByteSpan buffer)
{
if (buffer.size() < sizeof(uint64_t))
return BAN::Error::from_errno(EINVAL);
while (m_value == 0)
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker, &m_mutex));
const uint64_t read_value = m_is_semaphore ? 1 : m_value;
m_value -= read_value;
buffer.as<uint64_t>() = read_value;
epoll_notify(EPOLLOUT);
return sizeof(uint64_t);
}
BAN::ErrorOr<size_t> EventFD::write_impl(off_t, BAN::ConstByteSpan buffer)
{
if (buffer.size() < sizeof(uint64_t))
return BAN::Error::from_errno(EINVAL);
const uint64_t write_value = buffer.as<const uint64_t>();
if (write_value == UINT64_MAX)
return BAN::Error::from_errno(EINVAL);
while (m_value + write_value < m_value)
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker, &m_mutex));
m_value += write_value;
if (m_value > 0)
epoll_notify(EPOLLIN);
return sizeof(uint64_t);
}
}

View File

@ -9,16 +9,12 @@
namespace Kernel
{
static constexpr size_t s_pipe_buffer_size = 0x10000;
BAN::ErrorOr<BAN::RefPtr<Inode>> Pipe::create(const Credentials& credentials)
{
auto* pipe_ptr = new Pipe(credentials);
if (pipe_ptr == nullptr)
Pipe* pipe = new Pipe(credentials);
if (pipe == nullptr)
return BAN::Error::from_errno(ENOMEM);
auto pipe = BAN::RefPtr<Pipe>::adopt(pipe_ptr);
pipe->m_buffer = TRY(ByteRingBuffer::create(s_pipe_buffer_size));
return BAN::RefPtr<Inode>(pipe);
return BAN::RefPtr<Inode>::adopt(pipe);
}
Pipe::Pipe(const Credentials& credentials)
@ -73,16 +69,27 @@ namespace Kernel
BAN::ErrorOr<size_t> Pipe::read_impl(off_t, BAN::ByteSpan buffer)
{
while (m_buffer->empty())
while (m_buffer_size == 0)
{
if (m_writing_count == 0)
return 0;
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker, &m_mutex));
}
const size_t to_copy = BAN::Math::min<size_t>(buffer.size(), m_buffer->size());
memcpy(buffer.data(), m_buffer->get_data().data(), to_copy);
m_buffer->pop(to_copy);
const size_t to_copy = BAN::Math::min<size_t>(buffer.size(), m_buffer_size);
if (m_buffer_tail + to_copy <= m_buffer.size())
memcpy(buffer.data(), m_buffer.data() + m_buffer_tail, to_copy);
else
{
const size_t before_wrap = m_buffer.size() - m_buffer_tail;
const size_t after_wrap = to_copy - before_wrap;
memcpy(buffer.data(), m_buffer.data() + m_buffer_tail, before_wrap);
memcpy(buffer.data() + before_wrap, m_buffer.data(), after_wrap);
}
m_buffer_tail = (m_buffer_tail + to_copy) % m_buffer.size();
m_buffer_size -= to_copy;
m_atime = SystemTimer::get().real_time();
@ -95,7 +102,7 @@ namespace Kernel
BAN::ErrorOr<size_t> Pipe::write_impl(off_t, BAN::ConstByteSpan buffer)
{
while (m_buffer->full())
while (m_buffer_size >= m_buffer.size())
{
if (m_reading_count == 0)
{
@ -105,8 +112,20 @@ namespace Kernel
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker, &m_mutex));
}
const size_t to_copy = BAN::Math::min(buffer.size(), m_buffer->free());
m_buffer->push(buffer.slice(0, to_copy));
const size_t to_copy = BAN::Math::min(buffer.size(), m_buffer.size() - m_buffer_size);
const size_t buffer_head = (m_buffer_tail + m_buffer_size) % m_buffer.size();
if (buffer_head + to_copy <= m_buffer.size())
memcpy(m_buffer.data() + buffer_head, buffer.data(), to_copy);
else
{
const size_t before_wrap = m_buffer.size() - buffer_head;
const size_t after_wrap = to_copy - before_wrap;
memcpy(m_buffer.data() + buffer_head, buffer.data(), before_wrap);
memcpy(m_buffer.data(), buffer.data() + before_wrap, after_wrap);
}
m_buffer_size += to_copy;
timespec current_time = SystemTimer::get().real_time();
m_mtime = current_time;

View File

@ -1,49 +0,0 @@
#include <kernel/Memory/ByteRingBuffer.h>
#include <kernel/Memory/Heap.h>
#include <kernel/Memory/PageTable.h>
namespace Kernel
{
BAN::ErrorOr<BAN::UniqPtr<ByteRingBuffer>> ByteRingBuffer::create(size_t size)
{
ASSERT(size % PAGE_SIZE == 0);
const size_t page_count = size / PAGE_SIZE;
auto* buffer_ptr = new ByteRingBuffer(size);
if (buffer_ptr == nullptr)
return BAN::Error::from_errno(ENOMEM);
auto buffer = BAN::UniqPtr<ByteRingBuffer>::adopt(buffer_ptr);
buffer->m_vaddr = PageTable::kernel().reserve_free_contiguous_pages(page_count * 2, KERNEL_OFFSET);
if (buffer->m_vaddr == 0)
return BAN::Error::from_errno(ENOMEM);
for (size_t i = 0; i < page_count; i++)
{
const paddr_t paddr = Heap::get().take_free_page();
if (paddr == 0)
return BAN::Error::from_errno(ENOMEM);
PageTable::kernel().map_page_at(paddr, buffer->m_vaddr + i * PAGE_SIZE, PageTable::ReadWrite | PageTable::Present);
PageTable::kernel().map_page_at(paddr, buffer->m_vaddr + size + i * PAGE_SIZE, PageTable::ReadWrite | PageTable::Present);
}
return buffer;
}
ByteRingBuffer::~ByteRingBuffer()
{
if (m_vaddr == 0)
return;
for (size_t i = 0; i < m_capacity / PAGE_SIZE; i++)
{
const paddr_t paddr = PageTable::kernel().physical_address_of(m_vaddr + i * PAGE_SIZE);
if (paddr == 0)
break;
Heap::get().release_page(paddr);
}
PageTable::kernel().unmap_range(m_vaddr, m_capacity * 2);
}
}

View File

@ -17,7 +17,27 @@ namespace Kernel
BAN::ErrorOr<BAN::UniqPtr<ARPTable>> ARPTable::create()
{
return TRY(BAN::UniqPtr<ARPTable>::create());
auto arp_table = TRY(BAN::UniqPtr<ARPTable>::create());
arp_table->m_thread = TRY(Thread::create_kernel(
[](void* arp_table_ptr)
{
auto& arp_table = *reinterpret_cast<ARPTable*>(arp_table_ptr);
arp_table.packet_handle_task();
}, arp_table.ptr()
));
TRY(Processor::scheduler().add_thread(arp_table->m_thread));
return arp_table;
}
ARPTable::ARPTable()
{
}
ARPTable::~ARPTable()
{
if (m_thread)
m_thread->add_signal(SIGKILL, {});
m_thread = nullptr;
}
BAN::ErrorOr<BAN::MACAddress> ARPTable::get_mac_from_ipv4(NetworkInterface& interface, BAN::IPv4Address ipv4_address)
@ -44,7 +64,7 @@ namespace Kernel
ipv4_address = interface.get_gateway();
{
SpinLockGuard _(m_arp_table_lock);
SpinLockGuard _(m_table_lock);
auto it = m_arp_table.find(ipv4_address);
if (it != m_arp_table.end())
return it->value;
@ -67,7 +87,7 @@ namespace Kernel
while (SystemTimer::get().ms_since_boot() < timeout)
{
{
SpinLockGuard _(m_arp_table_lock);
SpinLockGuard _(m_table_lock);
auto it = m_arp_table.find(ipv4_address);
if (it != m_arp_table.end())
return it->value;
@ -78,16 +98,8 @@ namespace Kernel
return BAN::Error::from_errno(ETIMEDOUT);
}
BAN::ErrorOr<void> ARPTable::handle_arp_packet(NetworkInterface& interface, BAN::ConstByteSpan buffer)
BAN::ErrorOr<void> ARPTable::handle_arp_packet(NetworkInterface& interface, const ARPPacket& packet)
{
if (buffer.size() < sizeof(ARPPacket))
{
dwarnln_if(DEBUG_ARP, "Too small ARP packet");
return {};
}
const auto& packet = buffer.as<const ARPPacket>();
if (packet.ptype != EtherType::IPv4)
{
dprintln("Non IPv4 arp packet?");
@ -100,24 +112,23 @@ namespace Kernel
{
if (packet.tpa == interface.get_ipv4_address())
{
const ARPPacket arp_reply {
.htype = 0x0001,
.ptype = EtherType::IPv4,
.hlen = 0x06,
.plen = 0x04,
.oper = ARPOperation::Reply,
.sha = interface.get_mac_address(),
.spa = interface.get_ipv4_address(),
.tha = packet.sha,
.tpa = packet.spa,
};
ARPPacket arp_reply;
arp_reply.htype = 0x0001;
arp_reply.ptype = EtherType::IPv4;
arp_reply.hlen = 0x06;
arp_reply.plen = 0x04;
arp_reply.oper = ARPOperation::Reply;
arp_reply.sha = interface.get_mac_address();
arp_reply.spa = interface.get_ipv4_address();
arp_reply.tha = packet.sha;
arp_reply.tpa = packet.spa;
TRY(interface.send_bytes(packet.sha, EtherType::ARP, BAN::ConstByteSpan::from(arp_reply)));
}
break;
}
case ARPOperation::Reply:
{
SpinLockGuard _(m_arp_table_lock);
SpinLockGuard _(m_table_lock);
auto it = m_arp_table.find(packet.spa);
if (it != m_arp_table.end())
@ -143,4 +154,48 @@ namespace Kernel
return {};
}
void ARPTable::packet_handle_task()
{
for (;;)
{
PendingArpPacket pending = ({
SpinLockGuard guard(m_pending_lock);
while (m_pending_packets.empty())
{
SpinLockGuardAsMutex smutex(guard);
m_pending_thread_blocker.block_indefinite(&smutex);
}
auto packet = m_pending_packets.front();
m_pending_packets.pop();
packet;
});
if (auto ret = handle_arp_packet(pending.interface, pending.packet); ret.is_error())
dwarnln("{}", ret.error());
}
}
void ARPTable::add_arp_packet(NetworkInterface& interface, BAN::ConstByteSpan buffer)
{
if (buffer.size() < sizeof(ARPPacket))
{
dwarnln_if(DEBUG_ARP, "ARP packet too small");
return;
}
auto& arp_packet = buffer.as<const ARPPacket>();
SpinLockGuard _(m_pending_lock);
if (m_pending_packets.full())
{
dwarnln_if(DEBUG_ARP, "ARP packet queue full");
return;
}
m_pending_packets.push({ .interface = interface, .packet = arp_packet });
m_pending_thread_blocker.unblock();
}
}

View File

@ -1,7 +1,6 @@
#include <kernel/IDT.h>
#include <kernel/InterruptController.h>
#include <kernel/IO.h>
#include <kernel/Lock/SpinLockAsMutex.h>
#include <kernel/Memory/PageTable.h>
#include <kernel/MMIO.h>
#include <kernel/Networking/E1000/E1000.h>
@ -58,11 +57,6 @@ namespace Kernel
E1000::~E1000()
{
m_thread_should_die = true;
m_thread_blocker.unblock();
while (!m_thread_is_dead)
Processor::yield();
}
BAN::ErrorOr<void> E1000::initialize()
@ -90,16 +84,6 @@ namespace Kernel
dprintln(" link speed: {} Mbps", speed);
}
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();
}
m_thread_is_dead = false;
return {};
}
@ -275,8 +259,10 @@ namespace Kernel
return {};
}
BAN::ErrorOr<void> E1000::send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan> payload)
BAN::ErrorOr<void> E1000::send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::ConstByteSpan buffer)
{
ASSERT(buffer.size() + sizeof(EthernetHeader) <= E1000_TX_BUFFER_SIZE);
SpinLockGuard _(m_lock);
size_t tx_current = read32(REG_TDT) % E1000_TX_DESCRIPTOR_COUNT;
@ -288,38 +274,33 @@ namespace Kernel
ethernet_header.src_mac = get_mac_address();
ethernet_header.ether_type = protocol;
size_t packet_size = sizeof(EthernetHeader);
for (const auto& buffer : payload)
{
ASSERT(packet_size + buffer.size() < E1000_TX_BUFFER_SIZE);
memcpy(tx_buffer + packet_size, buffer.data(), buffer.size());
packet_size += buffer.size();
}
memcpy(tx_buffer + sizeof(EthernetHeader), buffer.data(), buffer.size());
auto& descriptor = reinterpret_cast<volatile e1000_tx_desc*>(m_tx_descriptor_region->vaddr())[tx_current];
descriptor.length = packet_size;
descriptor.length = sizeof(EthernetHeader) + buffer.size();
descriptor.status = 0;
descriptor.cmd = CMD_EOP | CMD_IFCS | CMD_RS;
// FIXME: there isnt really any reason to wait for transmission
write32(REG_TDT, (tx_current + 1) % E1000_TX_DESCRIPTOR_COUNT);
while (descriptor.status == 0)
continue;
dprintln_if(DEBUG_E1000, "sent {} bytes", packet_size);
dprintln_if(DEBUG_E1000, "sent {} bytes", sizeof(EthernetHeader) + buffer.size());
return {};
}
void E1000::receive_thread()
void E1000::handle_irq()
{
const uint32_t icr = read32(REG_ICR);
if (!(icr & (ICR_RxQ0 | ICR_RXT0)))
return;
write32(REG_ICR, icr);
SpinLockGuard _(m_lock);
while (!m_thread_should_die)
{
for (;;)
{
const uint32_t rx_current = (read32(REG_RDT0) + 1) % E1000_RX_DESCRIPTOR_COUNT;
for (;;) {
uint32_t rx_current = (read32(REG_RDT0) + 1) % E1000_RX_DESCRIPTOR_COUNT;
auto& descriptor = reinterpret_cast<volatile e1000_rx_desc*>(m_rx_descriptor_region->vaddr())[rx_current];
if (!(descriptor.status & 1))
@ -328,36 +309,14 @@ namespace Kernel
dprintln_if(DEBUG_E1000, "got {} bytes", (uint16_t)descriptor.length);
m_lock.unlock(InterruptState::Enabled);
NetworkManager::get().on_receive(*this, BAN::ConstByteSpan {
reinterpret_cast<const uint8_t*>(m_rx_buffer_region->vaddr() + rx_current * E1000_RX_BUFFER_SIZE),
descriptor.length
});
m_lock.lock();
descriptor.status = 0;
write32(REG_RDT0, rx_current);
}
SpinLockAsMutex smutex(m_lock, InterruptState::Enabled);
m_thread_blocker.block_indefinite(&smutex);
}
m_thread_is_dead = true;
}
void E1000::handle_irq()
{
const uint32_t icr = read32(REG_ICR);
write32(REG_ICR, icr);
if (icr & (ICR_RxQ0 | ICR_RXT0))
{
SpinLockGuard _(m_lock);
m_thread_blocker.unblock();
}
}
}

View File

@ -21,26 +21,50 @@ namespace Kernel
BAN::ErrorOr<BAN::UniqPtr<IPv4Layer>> IPv4Layer::create()
{
auto ipv4_manager = TRY(BAN::UniqPtr<IPv4Layer>::create());
ipv4_manager->m_thread = TRY(Thread::create_kernel(
[](void* ipv4_manager_ptr)
{
auto& ipv4_manager = *reinterpret_cast<IPv4Layer*>(ipv4_manager_ptr);
ipv4_manager.packet_handle_task();
}, ipv4_manager.ptr()
));
TRY(Processor::scheduler().add_thread(ipv4_manager->m_thread));
ipv4_manager->m_pending_packet_buffer = TRY(VirtualRange::create_to_vaddr_range(
PageTable::kernel(),
KERNEL_OFFSET,
~(uintptr_t)0,
pending_packet_buffer_size,
PageTable::Flags::ReadWrite | PageTable::Flags::Present,
true, false
));
ipv4_manager->m_arp_table = TRY(ARPTable::create());
return ipv4_manager;
}
static IPv4Header get_ipv4_header(size_t packet_size, BAN::IPv4Address src_ipv4, BAN::IPv4Address dst_ipv4, uint8_t protocol)
IPv4Layer::IPv4Layer()
{ }
IPv4Layer::~IPv4Layer()
{
IPv4Header header {
.version_IHL = 0x45,
.DSCP_ECN = 0x00,
.total_length = packet_size,
.identification = 1,
.flags_frament = 0x00,
.time_to_live = 0x40,
.protocol = protocol,
.checksum = 0,
.src_address = src_ipv4,
.dst_address = dst_ipv4,
};
header.checksum = calculate_internet_checksum(BAN::ConstByteSpan::from(header));
return header;
if (m_thread)
m_thread->add_signal(SIGKILL, {});
m_thread = nullptr;
}
void IPv4Layer::add_ipv4_header(BAN::ByteSpan packet, BAN::IPv4Address src_ipv4, BAN::IPv4Address dst_ipv4, uint8_t protocol) const
{
auto& header = packet.as<IPv4Header>();
header.version_IHL = 0x45;
header.DSCP_ECN = 0x00;
header.total_length = packet.size();
header.identification = 1;
header.flags_frament = 0x00;
header.time_to_live = 0x40;
header.protocol = protocol;
header.src_address = src_ipv4;
header.dst_address = dst_ipv4;
header.checksum = 0;
header.checksum = calculate_internet_checksum(BAN::ConstByteSpan::from(header), {});
}
void IPv4Layer::unbind_socket(uint16_t port)
@ -180,7 +204,7 @@ namespace Kernel
return {};
}
BAN::ErrorOr<size_t> IPv4Layer::sendto(NetworkSocket& socket, BAN::ConstByteSpan payload, const sockaddr* address, socklen_t address_len)
BAN::ErrorOr<size_t> IPv4Layer::sendto(NetworkSocket& socket, BAN::ConstByteSpan buffer, const sockaddr* address, socklen_t address_len)
{
if (address->sa_family != AF_INET)
return BAN::Error::from_errno(EINVAL);
@ -207,63 +231,46 @@ namespace Kernel
if (!receiver)
return BAN::Error::from_errno(EADDRNOTAVAIL);
TRY(socket.interface(receiver->address(), receiver->address_len()));
}
const auto ipv4_header = get_ipv4_header(
sizeof(IPv4Header) + socket.protocol_header_size() + payload.size(),
BAN::Vector<uint8_t> packet_buffer;
TRY(packet_buffer.resize(buffer.size() + sizeof(IPv4Header) + socket.protocol_header_size()));
auto packet = BAN::ByteSpan { packet_buffer.span() };
auto pseudo_header = PseudoHeader {
.src_ipv4 = interface->get_ipv4_address(),
.dst_ipv4 = dst_ipv4,
.protocol = socket.protocol()
};
memcpy(
packet.slice(sizeof(IPv4Header)).slice(socket.protocol_header_size()).data(),
buffer.data(),
buffer.size()
);
socket.add_protocol_header(
packet.slice(sizeof(IPv4Header)),
dst_port,
pseudo_header
);
add_ipv4_header(
packet,
interface->get_ipv4_address(),
dst_ipv4,
socket.protocol()
);
const auto pseudo_header = PseudoHeader {
.src_ipv4 = interface->get_ipv4_address(),
.dst_ipv4 = dst_ipv4,
.protocol = socket.protocol(),
.length = socket.protocol_header_size() + payload.size()
};
TRY(interface->send_bytes(dst_mac, EtherType::IPv4, packet));
uint8_t protocol_header_buffer[32];
ASSERT(socket.protocol_header_size() < sizeof(protocol_header_buffer));
auto protocol_header = BAN::ByteSpan::from(protocol_header_buffer).slice(0, socket.protocol_header_size());
socket.get_protocol_header(protocol_header, payload, dst_port, pseudo_header);
BAN::ConstByteSpan buffers[] {
BAN::ConstByteSpan::from(ipv4_header),
protocol_header,
payload,
};
TRY(interface->send_bytes(dst_mac, EtherType::IPv4, { buffers, sizeof(buffers) / sizeof(*buffers) }));
return payload.size();
return buffer.size();
}
BAN::ErrorOr<void> IPv4Layer::handle_ipv4_packet(NetworkInterface& interface, BAN::ConstByteSpan packet)
BAN::ErrorOr<void> IPv4Layer::handle_ipv4_packet(NetworkInterface& interface, BAN::ByteSpan packet)
{
if (packet.size() < sizeof(IPv4Header))
{
dwarnln_if(DEBUG_IPV4, "Too small IPv4 packet");
return {};
}
ASSERT(packet.size() >= sizeof(IPv4Header));
auto& ipv4_header = packet.as<const IPv4Header>();
if (calculate_internet_checksum(BAN::ConstByteSpan::from(ipv4_header)) != 0)
{
dwarnln_if(DEBUG_IPV4, "IPv4 packet checksum failed");
return {};
}
if (ipv4_header.total_length > packet.size() || ipv4_header.total_length > interface.payload_mtu() || ipv4_header.total_length < sizeof(IPv4Header))
{
if (ipv4_header.flags_frament & IPv4Flags::DF)
dwarnln_if(DEBUG_IPV4, "Invalid IPv4 packet");
else
dwarnln_if(DEBUG_IPV4, "IPv4 fragmentation not supported");
return {};
}
auto ipv4_data = packet.slice(0, ipv4_header.total_length).slice(sizeof(IPv4Header));
auto ipv4_data = packet.slice(sizeof(IPv4Header));
auto src_ipv4 = ipv4_header.src_address;
@ -286,33 +293,14 @@ namespace Kernel
{
auto dst_mac = TRY(m_arp_table->get_mac_from_ipv4(interface, src_ipv4));
auto send_ipv4_header = get_ipv4_header(
ipv4_data.size(),
interface.get_ipv4_address(),
src_ipv4,
NetworkProtocol::ICMP
);
auto& reply_icmp_header = ipv4_data.as<ICMPHeader>();
reply_icmp_header.type = ICMPType::EchoReply;
reply_icmp_header.checksum = 0;
reply_icmp_header.checksum = calculate_internet_checksum(ipv4_data, {});
ICMPHeader send_icmp_header {
.type = ICMPType::EchoReply,
.code = icmp_header.code,
.checksum = 0,
.rest = icmp_header.rest,
};
auto send_payload = ipv4_data.slice(sizeof(ICMPHeader));
const BAN::ConstByteSpan send_buffers[] {
BAN::ConstByteSpan::from(send_ipv4_header),
BAN::ConstByteSpan::from(send_icmp_header),
send_payload
};
auto send_buffers_span = BAN::Span { send_buffers, sizeof(send_buffers) / sizeof(*send_buffers) };
send_icmp_header.checksum = calculate_internet_checksum(send_buffers_span.slice(1));
TRY(interface.send_bytes(dst_mac, EtherType::IPv4, send_buffers_span));
add_ipv4_header(packet, interface.get_ipv4_address(), src_ipv4, NetworkProtocol::ICMP);
TRY(interface.send_bytes(dst_mac, EtherType::IPv4, packet));
break;
}
case ICMPType::DestinationUnreachable:
@ -394,4 +382,80 @@ namespace Kernel
return {};
}
void IPv4Layer::packet_handle_task()
{
for (;;)
{
PendingIPv4Packet pending = ({
SpinLockGuard guard(m_pending_lock);
while (m_pending_packets.empty())
{
SpinLockGuardAsMutex smutex(guard);
m_pending_thread_blocker.block_indefinite(&smutex);
}
auto packet = m_pending_packets.front();
m_pending_packets.pop();
packet;
});
uint8_t* buffer_start = reinterpret_cast<uint8_t*>(m_pending_packet_buffer->vaddr());
const size_t ipv4_packet_size = reinterpret_cast<const IPv4Header*>(buffer_start)->total_length;
if (auto ret = handle_ipv4_packet(pending.interface, BAN::ByteSpan(buffer_start, ipv4_packet_size)); ret.is_error())
dwarnln_if(DEBUG_IPV4, "{}", ret.error());
SpinLockGuard _(m_pending_lock);
m_pending_total_size -= ipv4_packet_size;
if (m_pending_total_size)
memmove(buffer_start, buffer_start + ipv4_packet_size, m_pending_total_size);
}
}
void IPv4Layer::add_ipv4_packet(NetworkInterface& interface, BAN::ConstByteSpan buffer)
{
if (buffer.size() < sizeof(IPv4Header))
{
dwarnln_if(DEBUG_IPV4, "IPv4 packet too small");
return;
}
SpinLockGuard _(m_pending_lock);
if (m_pending_packets.full())
{
dwarnln_if(DEBUG_IPV4, "IPv4 packet queue full");
return;
}
if (m_pending_total_size + buffer.size() > m_pending_packet_buffer->size())
{
dwarnln_if(DEBUG_IPV4, "IPv4 packet queue full");
return;
}
auto& ipv4_header = buffer.as<const IPv4Header>();
if (calculate_internet_checksum(BAN::ConstByteSpan::from(ipv4_header), {}) != 0)
{
dwarnln_if(DEBUG_IPV4, "Invalid IPv4 packet");
return;
}
if (ipv4_header.total_length > buffer.size() || ipv4_header.total_length > interface.payload_mtu())
{
if (ipv4_header.flags_frament & IPv4Flags::DF)
dwarnln_if(DEBUG_IPV4, "Invalid IPv4 packet");
else
dwarnln_if(DEBUG_IPV4, "IPv4 fragmentation not supported");
return;
}
uint8_t* buffer_start = reinterpret_cast<uint8_t*>(m_pending_packet_buffer->vaddr());
memcpy(buffer_start + m_pending_total_size, buffer.data(), ipv4_header.total_length);
m_pending_total_size += ipv4_header.total_length;
m_pending_packets.push({ .interface = interface });
m_pending_thread_blocker.unblock();
}
}

View File

@ -1,4 +1,3 @@
#include <kernel/Lock/LockGuard.h>
#include <kernel/Networking/Loopback.h>
#include <kernel/Networking/NetworkManager.h>
@ -11,121 +10,40 @@ namespace Kernel
if (loopback_ptr == nullptr)
return BAN::Error::from_errno(ENOMEM);
auto loopback = BAN::RefPtr<LoopbackInterface>::adopt(loopback_ptr);
loopback->m_buffer = TRY(VirtualRange::create_to_vaddr_range(
PageTable::kernel(),
KERNEL_OFFSET,
BAN::numeric_limits<vaddr_t>::max(),
buffer_size * buffer_count,
buffer_size,
PageTable::Flags::ReadWrite | PageTable::Flags::Present,
true, false
));
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();
}
loopback->m_thread_is_dead = false;
loopback->set_ipv4_address({ 127, 0, 0, 1 });
loopback->set_netmask({ 255, 0, 0, 0 });
for (size_t i = 0; i < buffer_count; i++)
{
loopback->m_descriptors[i] = {
.addr = reinterpret_cast<uint8_t*>(loopback->m_buffer->vaddr()) + i * buffer_size,
.size = 0,
.state = 0,
};
}
return loopback;
}
LoopbackInterface::~LoopbackInterface()
BAN::ErrorOr<void> LoopbackInterface::send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::ConstByteSpan buffer)
{
m_thread_should_die = true;
m_thread_blocker.unblock();
ASSERT(buffer.size() + sizeof(EthernetHeader) <= buffer_size);
while (!m_thread_is_dead)
Processor::yield();
}
SpinLockGuard _(m_buffer_lock);
BAN::ErrorOr<void> LoopbackInterface::send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan> payload)
{
auto& descriptor =
[&]() -> Descriptor&
{
LockGuard _(m_buffer_lock);
for (;;)
{
auto& descriptor = m_descriptors[m_buffer_head];
if (descriptor.state == 0)
{
m_buffer_head = (m_buffer_head + 1) % buffer_count;
descriptor.state = 1;
return descriptor;
}
m_thread_blocker.block_indefinite(&m_buffer_lock);
}
}();
uint8_t* buffer_vaddr = reinterpret_cast<uint8_t*>(m_buffer->vaddr());
auto& ethernet_header = *reinterpret_cast<EthernetHeader*>(descriptor.addr);
auto& ethernet_header = *reinterpret_cast<EthernetHeader*>(buffer_vaddr);
ethernet_header.dst_mac = destination;
ethernet_header.src_mac = get_mac_address();
ethernet_header.ether_type = protocol;
size_t packet_size = sizeof(EthernetHeader);
for (const auto& buffer : payload)
{
ASSERT(packet_size + buffer.size() <= buffer_size);
memcpy(descriptor.addr + packet_size, buffer.data(), buffer.size());
packet_size += buffer.size();
}
memcpy(buffer_vaddr + sizeof(EthernetHeader), buffer.data(), buffer.size());
LockGuard _(m_buffer_lock);
descriptor.size = packet_size;
descriptor.state = 2;
m_thread_blocker.unblock();
NetworkManager::get().on_receive(*this, BAN::ConstByteSpan {
buffer_vaddr,
buffer.size() + sizeof(EthernetHeader)
});
return {};
}
void LoopbackInterface::receive_thread()
{
LockGuard _(m_buffer_lock);
while (!m_thread_should_die)
{
for (;;)
{
auto& descriptor = m_descriptors[m_buffer_tail];
if (descriptor.state != 2)
break;
m_buffer_tail = (m_buffer_tail + 1) % buffer_count;
m_buffer_lock.unlock();
NetworkManager::get().on_receive(*this, {
descriptor.addr,
descriptor.size,
});
m_buffer_lock.lock();
descriptor.size = 0;
descriptor.state = 0;
m_thread_blocker.unblock();
}
m_thread_blocker.block_indefinite(&m_buffer_lock);
}
m_thread_is_dead = true;
}
}

View File

@ -3,28 +3,15 @@
namespace Kernel
{
uint16_t calculate_internet_checksum(BAN::ConstByteSpan buffer)
{
return calculate_internet_checksum({ &buffer, 1 });
}
uint16_t calculate_internet_checksum(BAN::Span<const BAN::ConstByteSpan> buffers)
uint16_t calculate_internet_checksum(BAN::ConstByteSpan packet, const PseudoHeader& pseudo_header)
{
uint32_t checksum = 0;
for (size_t i = 0; i < buffers.size(); i++)
{
auto buffer = buffers[i];
const uint16_t* buffer_u16 = reinterpret_cast<const uint16_t*>(buffer.data());
for (size_t j = 0; j < buffer.size() / 2; j++)
checksum += BAN::host_to_network_endian(buffer_u16[j]);
if (buffer.size() % 2 == 0)
continue;
ASSERT(i == buffers.size() - 1);
checksum += buffer[buffer.size() - 1] << 8;
}
for (size_t i = 0; i < sizeof(pseudo_header) / sizeof(uint16_t); i++)
checksum += BAN::host_to_network_endian(reinterpret_cast<const uint16_t*>(&pseudo_header)[i]);
for (size_t i = 0; i < packet.size() / sizeof(uint16_t); i++)
checksum += BAN::host_to_network_endian(reinterpret_cast<const uint16_t*>(packet.data())[i]);
if (packet.size() % 2)
checksum += (uint16_t)packet[packet.size() - 1] << 8;
while (checksum >> 16)
checksum = (checksum >> 16) + (checksum & 0xFFFF);
return ~(uint16_t)checksum;

View File

@ -154,18 +154,18 @@ namespace Kernel
return;
auto ethernet_header = packet.as<const EthernetHeader>();
auto packet_data = packet.slice(sizeof(EthernetHeader));
switch (ethernet_header.ether_type)
{
case EtherType::ARP:
if (auto ret = m_ipv4_layer->arp_table().handle_arp_packet(interface, packet_data); ret.is_error())
dwarnln("ARP: {}", ret.error());
{
m_ipv4_layer->arp_table().add_arp_packet(interface, packet.slice(sizeof(EthernetHeader)));
break;
}
case EtherType::IPv4:
if (auto ret = m_ipv4_layer->handle_ipv4_packet(interface, packet_data); ret.is_error())
dwarnln("IPv4; {}", ret.error());
{
m_ipv4_layer->add_ipv4_packet(interface, packet.slice(sizeof(EthernetHeader)));
break;
}
default:
dprintln_if(DEBUG_ETHERTYPE, "Unknown EtherType 0x{4H}", (uint16_t)ethernet_header.ether_type);
break;

View File

@ -7,9 +7,6 @@
namespace Kernel
{
// each buffer is 7440 bytes + padding = 8192
constexpr size_t s_buffer_size = 8192;
bool RTL8169::probe(PCI::Device& pci_device)
{
if (pci_device.vendor_id() != 0x10ec)
@ -71,28 +68,9 @@ namespace Kernel
// lock config registers
m_io_bar_region->write8(RTL8169_IO_9346CR, RTL8169_9346CR_MODE_NORMAL);
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();
}
m_thread_is_dead = false;
return {};
}
RTL8169::~RTL8169()
{
m_thread_should_die = true;
m_thread_blocker.unblock();
while (!m_thread_is_dead)
Processor::yield();
}
BAN::ErrorOr<void> RTL8169::reset()
{
m_io_bar_region->write8(RTL8169_IO_CR, RTL8169_CR_RST);
@ -107,12 +85,15 @@ namespace Kernel
BAN::ErrorOr<void> RTL8169::initialize_rx()
{
m_rx_buffer_region = TRY(DMARegion::create(m_rx_descriptor_count * s_buffer_size));
// each buffer is 7440 bytes + padding = 8192
constexpr size_t buffer_size = 2 * PAGE_SIZE;
m_rx_buffer_region = TRY(DMARegion::create(m_rx_descriptor_count * buffer_size));
m_rx_descriptor_region = TRY(DMARegion::create(m_rx_descriptor_count * sizeof(RTL8169Descriptor)));
for (size_t i = 0; i < m_rx_descriptor_count; i++)
{
const paddr_t rx_buffer_paddr = m_rx_buffer_region->paddr() + i * s_buffer_size;
const paddr_t rx_buffer_paddr = m_rx_buffer_region->paddr() + i * buffer_size;
uint32_t command = 0x1FF8 | RTL8169_DESC_CMD_OWN;
if (i == m_rx_descriptor_count - 1)
@ -139,17 +120,21 @@ namespace Kernel
// configure max rx packet size
m_io_bar_region->write16(RTL8169_IO_RMS, RTL8169_RMS_MAX);
return {};
}
BAN::ErrorOr<void> RTL8169::initialize_tx()
{
m_tx_buffer_region = TRY(DMARegion::create(m_tx_descriptor_count * s_buffer_size));
// each buffer is 7440 bytes + padding = 8192
constexpr size_t buffer_size = 2 * PAGE_SIZE;
m_tx_buffer_region = TRY(DMARegion::create(m_tx_descriptor_count * buffer_size));
m_tx_descriptor_region = TRY(DMARegion::create(m_tx_descriptor_count * sizeof(RTL8169Descriptor)));
for (size_t i = 0; i < m_tx_descriptor_count; i++)
{
const paddr_t tx_buffer_paddr = m_tx_buffer_region->paddr() + i * s_buffer_size;
const paddr_t tx_buffer_paddr = m_tx_buffer_region->paddr() + i * buffer_size;
uint32_t command = 0;
if (i == m_tx_descriptor_count - 1)
@ -209,8 +194,14 @@ namespace Kernel
return 0;
}
BAN::ErrorOr<void> RTL8169::send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan> payload)
BAN::ErrorOr<void> RTL8169::send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::ConstByteSpan buffer)
{
constexpr size_t buffer_size = 8192;
const uint16_t packet_size = sizeof(EthernetHeader) + buffer.size();
if (packet_size > buffer_size)
return BAN::Error::from_errno(EINVAL);
if (!link_up())
return BAN::Error::from_errno(EADDRNOTAVAIL);
@ -228,20 +219,14 @@ namespace Kernel
m_lock.unlock(state);
auto* tx_buffer = reinterpret_cast<uint8_t*>(m_tx_buffer_region->vaddr() + tx_current * s_buffer_size);
auto* tx_buffer = reinterpret_cast<uint8_t*>(m_tx_buffer_region->vaddr() + tx_current * buffer_size);
// write packet
auto& ethernet_header = *reinterpret_cast<EthernetHeader*>(tx_buffer);
ethernet_header.dst_mac = destination;
ethernet_header.src_mac = get_mac_address();
ethernet_header.ether_type = protocol;
size_t packet_size = sizeof(EthernetHeader);
for (const auto& buffer : payload)
{
memcpy(tx_buffer + packet_size, buffer.data(), buffer.size());
packet_size += buffer.size();
}
memcpy(tx_buffer + sizeof(EthernetHeader), buffer.data(), buffer.size());
// give packet ownership to NIC
uint32_t command = packet_size | RTL8169_DESC_CMD_OWN | RTL8169_DESC_CMD_LS | RTL8169_DESC_CMD_FS;
@ -255,50 +240,6 @@ namespace Kernel
return {};
}
void RTL8169::receive_thread()
{
SpinLockGuard _(m_lock);
while (!m_thread_should_die)
{
for (;;)
{
auto& descriptor = reinterpret_cast<volatile RTL8169Descriptor*>(m_rx_descriptor_region->vaddr())[m_rx_current];
if (descriptor.command & RTL8169_DESC_CMD_OWN)
break;
// packet buffer can only hold single packet, so we should not receive any multi-descriptor packets
ASSERT((descriptor.command & RTL8169_DESC_CMD_LS) && (descriptor.command & RTL8169_DESC_CMD_FS));
const uint16_t packet_length = descriptor.command & 0x3FFF;
if (packet_length > s_buffer_size)
dwarnln("Got {} bytes to {} byte buffer", packet_length, s_buffer_size);
else if (descriptor.command & (1u << 21))
; // descriptor has an error
else
{
m_lock.unlock(InterruptState::Enabled);
NetworkManager::get().on_receive(*this, BAN::ConstByteSpan {
reinterpret_cast<const uint8_t*>(m_rx_buffer_region->vaddr() + m_rx_current * s_buffer_size),
packet_length
});
m_lock.lock();
}
m_rx_current = (m_rx_current + 1) % m_rx_descriptor_count;
descriptor.command = descriptor.command | RTL8169_DESC_CMD_OWN;
}
SpinLockAsMutex smutex(m_lock, InterruptState::Enabled);
m_thread_blocker.block_indefinite(&smutex);
}
m_thread_is_dead = true;
}
void RTL8169::handle_irq()
{
const uint16_t interrupt_status = m_io_bar_region->read16(RTL8169_IO_ISR);
@ -310,7 +251,7 @@ namespace Kernel
dprintln("link status -> {}", m_link_up.load());
}
if (interrupt_status & (RTL8169_IR_TOK | RTL8169_IR_ROK))
if (interrupt_status & RTL8169_IR_TOK)
{
SpinLockGuard _(m_lock);
m_thread_blocker.unblock();
@ -325,6 +266,38 @@ namespace Kernel
if (interrupt_status & RTL8169_IR_FVOW)
dwarnln("Rx FIFO overflow");
// dont log TDU is sent after each sent packet
if (!(interrupt_status & RTL8169_IR_ROK))
return;
constexpr size_t buffer_size = 8192;
for (;;)
{
auto& descriptor = reinterpret_cast<volatile RTL8169Descriptor*>(m_rx_descriptor_region->vaddr())[m_rx_current];
if (descriptor.command & RTL8169_DESC_CMD_OWN)
break;
// packet buffer can only hold single packet, so we should not receive any multi-descriptor packets
ASSERT((descriptor.command & RTL8169_DESC_CMD_LS) && (descriptor.command & RTL8169_DESC_CMD_FS));
const uint16_t packet_length = descriptor.command & 0x3FFF;
if (packet_length > buffer_size)
dwarnln("Got {} bytes to {} byte buffer", packet_length, buffer_size);
else if (descriptor.command & (1u << 21))
; // descriptor has an error
else
{
NetworkManager::get().on_receive(*this, BAN::ConstByteSpan {
reinterpret_cast<const uint8_t*>(m_rx_buffer_region->vaddr() + m_rx_current * buffer_size),
packet_length
});
}
m_rx_current = (m_rx_current + 1) % m_rx_descriptor_count;
descriptor.command = descriptor.command | RTL8169_DESC_CMD_OWN;
}
}
}

View File

@ -7,7 +7,6 @@
#include <fcntl.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/epoll.h>
#include <sys/ioctl.h>
@ -25,19 +24,26 @@ namespace Kernel
static constexpr size_t s_recv_window_buffer_size = 16 * PAGE_SIZE;
static constexpr size_t s_send_window_buffer_size = 16 * PAGE_SIZE;
// allows upto 1 MiB windows
static constexpr uint8_t s_window_shift = 4;
// https://www.rfc-editor.org/rfc/rfc1122 4.2.2.6
static constexpr uint16_t s_default_mss = 536;
BAN::ErrorOr<BAN::RefPtr<TCPSocket>> TCPSocket::create(NetworkLayer& network_layer, const Info& info)
{
auto socket = TRY(BAN::RefPtr<TCPSocket>::create(network_layer, info));
socket->m_last_sent_window_size = s_recv_window_buffer_size;
socket->m_recv_window.buffer = TRY(ByteRingBuffer::create(s_recv_window_buffer_size));
socket->m_recv_window.scale_shift = s_window_shift;
socket->m_send_window.buffer = TRY(ByteRingBuffer::create(s_send_window_buffer_size));
socket->m_recv_window.buffer = TRY(VirtualRange::create_to_vaddr_range(
PageTable::kernel(),
KERNEL_OFFSET,
~(vaddr_t)0,
s_recv_window_buffer_size,
PageTable::Flags::ReadWrite | PageTable::Flags::Present,
true, false
));
socket->m_recv_window.scale_shift = PAGE_SIZE_SHIFT; // use PAGE_SIZE windows
socket->m_send_window.buffer = TRY(VirtualRange::create_to_vaddr_range(
PageTable::kernel(),
KERNEL_OFFSET,
~(vaddr_t)0,
s_send_window_buffer_size,
PageTable::Flags::ReadWrite | PageTable::Flags::Present,
true, false
));
socket->m_thread = TRY(Thread::create_kernel(
[](void* socket_ptr)
{
@ -94,13 +100,12 @@ namespace Kernel
return_inode->m_listen_parent = this;
return_inode->m_connection_info.emplace(connection.target);
return_inode->m_recv_window.start_seq = connection.target_start_seq;
return_inode->m_send_window.scale_shift = connection.window_scale;
return_inode->m_send_window.mss = connection.maximum_seqment_size;
return_inode->m_next_flags = SYN | ACK;
return_inode->m_next_state = State::SynReceived;
return_inode->m_mutex.unlock();
if (!return_inode->m_connection_info->has_window_scale)
return_inode->m_recv_window.scale_shift = 0;
return_inode->m_mutex.unlock();
TRY(m_listen_children.emplace(listen_key, return_inode));
@ -192,7 +197,8 @@ namespace Kernel
BAN::ErrorOr<size_t> TCPSocket::recvmsg_impl(msghdr& message, int flags)
{
if (flags & ~(MSG_PEEK))
flags &= (MSG_OOB | MSG_PEEK | MSG_WAITALL);
if (flags != 0)
{
dwarnln("TODO: recvmsg with flags 0x{H}", flags);
return BAN::Error::from_errno(ENOTSUP);
@ -200,14 +206,14 @@ namespace Kernel
if (CMSG_FIRSTHDR(&message))
{
dprintln_if(DEBUG_TCP, "ignoring recvmsg control message");
dwarnln("ignoring recvmsg control message");
message.msg_controllen = 0;
}
if (!m_has_connected)
return BAN::Error::from_errno(ENOTCONN);
while (m_recv_window.buffer->empty())
while (m_recv_window.data_size == 0)
{
if (m_state != State::Established)
return return_with_maybe_zero();
@ -217,34 +223,21 @@ namespace Kernel
message.msg_flags = 0;
size_t total_recv = 0;
for (int i = 0; i < message.msg_iovlen && total_recv < m_recv_window.buffer->size(); i++)
for (int i = 0; i < message.msg_iovlen; i++)
{
auto& iov = message.msg_iov[i];
auto* recv_buffer = reinterpret_cast<uint8_t*>(m_recv_window.buffer->vaddr());
const size_t nrecv = BAN::Math::min(iov.iov_len, m_recv_window.buffer->size() - total_recv);
memcpy(iov.iov_base, m_recv_window.buffer->get_data().data() + total_recv, nrecv);
const size_t nrecv = BAN::Math::min<size_t>(message.msg_iov[i].iov_len, m_recv_window.data_size);
memcpy(message.msg_iov[i].iov_base, recv_buffer, nrecv);
total_recv += nrecv;
}
m_recv_window.data_size -= nrecv;
m_recv_window.start_seq += nrecv;
if (m_recv_window.data_size == 0)
break;
if (!(flags & MSG_PEEK))
{
m_recv_window.buffer->pop(total_recv);
m_recv_window.start_seq += total_recv;
}
const size_t update_window_threshold = m_recv_window.buffer->capacity() / 8;
const bool should_update_window_size =
m_last_sent_window_size != m_recv_window.buffer->capacity() && (
(m_last_sent_window_size == 0) ||
(m_recv_window.buffer->empty()) ||
(m_last_sent_window_size + update_window_threshold <= m_recv_window.buffer->free())
);
if (should_update_window_size || m_should_send_zero_window)
{
m_should_send_window_update = true;
m_thread_blocker.unblock();
// TODO: use circular buffer to avoid this
memmove(recv_buffer, recv_buffer + nrecv, m_recv_window.data_size);
}
return total_recv;
@ -264,7 +257,7 @@ namespace Kernel
if (!m_has_connected)
return BAN::Error::from_errno(ENOTCONN);
while (m_send_window.buffer->full())
while (m_send_window.data_size == m_send_window.buffer->size())
{
if (m_state != State::Established)
return return_with_maybe_zero();
@ -274,14 +267,17 @@ namespace Kernel
}
size_t total_sent = 0;
for (int i = 0; i < message.msg_iovlen && !m_send_window.buffer->full(); i++)
for (int i = 0; i < message.msg_iovlen; i++)
{
const auto& iov = message.msg_iov[i];
auto* send_buffer = reinterpret_cast<uint8_t*>(m_send_window.buffer->vaddr());
const size_t nsend = BAN::Math::min(iov.iov_len, m_send_window.buffer->free());
m_send_window.buffer->push({ static_cast<const uint8_t*>(iov.iov_base), nsend });
const size_t nsend = BAN::Math::min<size_t>(message.msg_iov[i].iov_len, m_send_window.buffer->size() - m_send_window.data_size);
memcpy(send_buffer + m_send_window.data_size, message.msg_iov[i].iov_base, nsend);
total_sent += nsend;
m_send_window.data_size += nsend;
if (m_send_window.data_size == m_send_window.buffer->size())
break;
}
m_thread_blocker.unblock();
@ -302,16 +298,12 @@ namespace Kernel
BAN::ErrorOr<void> TCPSocket::getsockopt_impl(int level, int option, void* value, socklen_t* value_len)
{
int result;
if (level != SOL_SOCKET)
return BAN::Error::from_errno(EINVAL);
switch (level)
{
case SOL_SOCKET:
int result;
switch (option)
{
case SO_KEEPALIVE:
result = m_keep_alive;
break;
case SO_ERROR:
result = 0;
break;
@ -319,27 +311,10 @@ namespace Kernel
result = m_send_window.scaled_size();
break;
case SO_RCVBUF:
result = m_recv_window.buffer->capacity();
result = m_recv_window.buffer->size();
break;
default:
dwarnln("getsockopt(SOL_SOCKET, {})", option);
return BAN::Error::from_errno(ENOPROTOOPT);
}
break;
case IPPROTO_TCP:
switch (option)
{
case TCP_NODELAY:
result = m_no_delay;
break;
default:
dwarnln("getsockopt(IPPROTO_TCP, {})", option);
return BAN::Error::from_errno(ENOPROTOOPT);
}
break;
default:
dwarnln("getsockopt({}, {})", level, option);
return BAN::Error::from_errno(EINVAL);
return BAN::Error::from_errno(ENOTSUP);
}
const size_t len = BAN::Math::min<size_t>(sizeof(result), *value_len);
@ -349,50 +324,12 @@ namespace Kernel
return {};
}
BAN::ErrorOr<void> TCPSocket::setsockopt_impl(int level, int option, const void* value, socklen_t value_len)
{
switch (level)
{
case SOL_SOCKET:
switch (option)
{
case SO_KEEPALIVE:
if (value_len != sizeof(int))
return BAN::Error::from_errno(EINVAL);
m_keep_alive = *static_cast<const int*>(value);
break;
default:
dwarnln("setsockopt(SOL_SOCKET, {})", option);
return BAN::Error::from_errno(ENOPROTOOPT);
}
break;
case IPPROTO_TCP:
switch (option)
{
case TCP_NODELAY:
if (value_len != sizeof(int))
return BAN::Error::from_errno(EINVAL);
m_no_delay = *static_cast<const int*>(value);
break;
default:
dwarnln("setsockopt(IPPROTO_TCP, {})", option);
return BAN::Error::from_errno(ENOPROTOOPT);
}
break;
default:
dwarnln("setsockopt({}, {})", level, option);
return BAN::Error::from_errno(EINVAL);
}
return {};
}
BAN::ErrorOr<long> TCPSocket::ioctl_impl(int request, void* argument)
{
switch (request)
{
case FIONREAD:
*static_cast<int*>(argument) = m_recv_window.buffer->size();
*static_cast<int*>(argument) = m_recv_window.data_size;
return 0;
}
@ -405,14 +342,14 @@ namespace Kernel
return true;
if (m_state == State::Listen)
return !m_pending_connections.empty();
return !m_recv_window.buffer->empty();
return m_recv_window.data_size > 0;
}
bool TCPSocket::can_write_impl() const
{
if (m_state != State::Established)
return false;
return !m_send_window.buffer->full();
return m_send_window.data_size < m_send_window.buffer->size();
}
bool TCPSocket::has_hungup_impl() const
@ -485,7 +422,7 @@ namespace Kernel
if (header.options[i] == TCPOption::NOP)
continue;
if (header.options[i] == TCPOption::MaximumSeqmentSize)
result.maximum_seqment_size = BAN::network_endian_to_host(*reinterpret_cast<const uint16_t*>(&header.options[i + 2]));
result.maximum_seqment_size = BAN::host_to_network_endian(*reinterpret_cast<const uint16_t*>(&header.options[i + 2]));
if (header.options[i] == TCPOption::WindowScale)
result.window_scale = header.options[i + 2];
if (header.options[i + 1] == 0)
@ -496,28 +433,22 @@ namespace Kernel
return result;
}
void TCPSocket::get_protocol_header(BAN::ByteSpan header_buffer, BAN::ConstByteSpan payload, uint16_t dst_port, PseudoHeader pseudo_header)
void TCPSocket::add_protocol_header(BAN::ByteSpan packet, uint16_t dst_port, PseudoHeader pseudo_header)
{
ASSERT(m_next_flags);
ASSERT(m_mutex.locker() == Thread::current().tid());
ASSERT(header_buffer.size() == protocol_header_size());
m_last_sent_window_size = m_should_send_zero_window ? 0 : m_recv_window.buffer->free();
auto& header = header_buffer.as<TCPHeader>();
header = {
.src_port = bound_port(),
.dst_port = dst_port,
.seq_number = m_send_window.current_seq + m_send_window.has_ghost_byte,
.ack_number = m_recv_window.start_seq + m_recv_window.buffer->size() + m_recv_window.has_ghost_byte,
.data_offset = (sizeof(TCPHeader) + m_tcp_options_bytes) / sizeof(uint32_t),
.flags = m_next_flags,
.window_size = BAN::Math::min<size_t>(0xFFFF, m_last_sent_window_size >> m_recv_window.scale_shift),
.checksum = 0,
.urgent_pointer = 0,
};
memset(header.options, 0, m_tcp_options_bytes);
auto& header = packet.as<TCPHeader>();
memset(&header, 0, sizeof(TCPHeader));
memset(header.options, TCPOption::End, m_tcp_options_bytes);
header.src_port = bound_port();
header.dst_port = dst_port;
header.seq_number = m_send_window.current_seq + m_send_window.has_ghost_byte;
header.ack_number = m_recv_window.start_seq + m_recv_window.data_size + m_recv_window.has_ghost_byte;
header.data_offset = (sizeof(TCPHeader) + m_tcp_options_bytes) / sizeof(uint32_t);
header.window_size = BAN::Math::min<size_t>(0xFFFF, m_recv_window.buffer->size() >> m_recv_window.scale_shift);
header.flags = m_next_flags;
if (header.flags & FIN)
m_send_window.has_ghost_byte = true;
m_next_flags = 0;
@ -536,39 +467,24 @@ namespace Kernel
if (m_connection_info->has_window_scale)
add_tcp_header_option<4, TCPOption::WindowScale>(header, m_recv_window.scale_shift);
header.window_size = BAN::Math::min<size_t>(0xFFFF, m_recv_window.buffer->capacity());
header.window_size = BAN::Math::min<size_t>(0xFFFF, m_recv_window.buffer->size());
m_send_window.mss = 1440;
m_send_window.start_seq++;
m_send_window.current_seq = m_send_window.start_seq;
}
const BAN::ConstByteSpan buffers[] {
BAN::ConstByteSpan::from(pseudo_header),
header_buffer,
payload,
};
header.checksum = calculate_internet_checksum({ buffers, sizeof(buffers) / sizeof(*buffers) });
pseudo_header.extra = packet.size();
header.checksum = calculate_internet_checksum(packet, pseudo_header);
dprintln_if(DEBUG_TCP, "sending {} {8b}", (uint8_t)m_state, header.flags);
dprintln_if(DEBUG_TCP, " ack {}", (uint32_t)header.ack_number);
dprintln_if(DEBUG_TCP, " seq {}", (uint32_t)header.seq_number);
dprintln_if(DEBUG_TCP, " {}", (uint32_t)header.ack_number);
dprintln_if(DEBUG_TCP, " {}", (uint32_t)header.seq_number);
}
void TCPSocket::receive_packet(BAN::ConstByteSpan buffer, const sockaddr* sender, socklen_t sender_len)
{
if (m_state == State::Listen)
{
auto socket =
[&]() -> BAN::RefPtr<TCPSocket> {
LockGuard _(m_mutex);
if (auto it = m_listen_children.find(ListenKey(sender, sender_len)); it != m_listen_children.end())
return it->value;
return {};
}();
if (socket)
return socket->receive_packet(buffer, sender, sender_len);
}
(void)sender_len;
{
uint16_t checksum = 0;
@ -581,17 +497,14 @@ namespace Kernel
auto interface = interface_or_error.release_value();
auto& addr_in = *reinterpret_cast<const sockaddr_in*>(sender);
const PseudoHeader pseudo_header {
checksum = calculate_internet_checksum(buffer,
PseudoHeader {
.src_ipv4 = BAN::IPv4Address(addr_in.sin_addr.s_addr),
.dst_ipv4 = interface->get_ipv4_address(),
.protocol = NetworkProtocol::TCP,
.length = buffer.size(),
};
const BAN::ConstByteSpan buffers[] {
BAN::ConstByteSpan::from(pseudo_header),
buffer
};
checksum = calculate_internet_checksum({ buffers, sizeof(buffers) / sizeof(*buffers) });
.extra = buffer.size()
}
);
}
else
{
@ -611,14 +524,11 @@ namespace Kernel
const bool hungup_before = has_hungup_impl();
auto& header = buffer.as<const TCPHeader>();
dprintln_if(DEBUG_TCP, "receiving {} {8b}", (uint8_t)m_state, header.flags);
dprintln_if(DEBUG_TCP, " ack {}", (uint32_t)header.ack_number);
dprintln_if(DEBUG_TCP, " seq {}", (uint32_t)header.seq_number);
dprintln_if(DEBUG_TCP, " {}", (uint32_t)header.ack_number);
dprintln_if(DEBUG_TCP, " {}", (uint32_t)header.seq_number);
m_send_window.non_scaled_size = header.window_size;
if (m_send_window.scaled_size() == 0)
m_send_window.had_zero_window = true;
bool check_payload = false;
switch (m_state)
@ -637,7 +547,8 @@ namespace Kernel
}
auto options = parse_tcp_options(header);
m_send_window.mss = options.maximum_seqment_size.value_or(s_default_mss);
if (options.maximum_seqment_size.has_value())
m_send_window.mss = *options.maximum_seqment_size;
if (options.window_scale.has_value())
m_send_window.scale_shift = *options.window_scale;
else
@ -662,34 +573,44 @@ namespace Kernel
m_has_connected = true;
break;
case State::Listen:
if (header.flags != SYN)
dprintln_if(DEBUG_TCP, "Unexpected packet to listening socket");
else if (m_pending_connections.size() == m_pending_connections.capacity())
if (header.flags == SYN)
{
if (m_pending_connections.size() == m_pending_connections.capacity())
dprintln_if(DEBUG_TCP, "No storage to store pending connection");
else
{
const auto options = parse_tcp_options(header);
ConnectionInfo connection_info;
memcpy(&connection_info.address, sender, sender_len);
connection_info.address_len = sender_len;
connection_info.has_window_scale = options.window_scale.has_value();
connection_info.has_window_scale = parse_tcp_options(header).window_scale.has_value();
MUST(m_pending_connections.emplace(
connection_info,
header.seq_number + 1,
options.maximum_seqment_size.value_or(s_default_mss),
options.window_scale.value_or(0)
header.seq_number + 1
));
epoll_notify(EPOLLIN);
m_thread_blocker.unblock();
}
}
else
{
auto it = m_listen_children.find(ListenKey(sender, sender_len));
if (it == m_listen_children.end())
{
dprintln_if(DEBUG_TCP, "Unexpected packet to listening socket");
break;
}
auto socket = it->value;
m_mutex.unlock();
socket->receive_packet(buffer, sender, sender_len);
m_mutex.lock();
}
return;
case State::Established:
check_payload = true;
if (!(header.flags & FIN))
break;
if (m_recv_window.start_seq + m_recv_window.buffer->size() != header.seq_number)
if (m_recv_window.start_seq + m_recv_window.data_size != header.seq_number)
break;
m_next_flags = FIN | ACK;
m_next_state = State::LastAck;
@ -738,9 +659,7 @@ namespace Kernel
break;
}
const uint32_t expected_seq = m_recv_window.start_seq + m_recv_window.buffer->size() + m_recv_window.has_ghost_byte;
if (header.seq_number > expected_seq)
if (header.seq_number != m_recv_window.start_seq + m_recv_window.data_size + m_recv_window.has_ghost_byte)
dprintln_if(DEBUG_TCP, "Missing packets");
else if (check_payload)
{
@ -751,37 +670,28 @@ namespace Kernel
m_send_window.current_ack = header.ack_number;
auto payload = buffer.slice(header.data_offset * sizeof(uint32_t));
if (header.seq_number < expected_seq)
if (payload.size() > 0)
{
const uint32_t already_received_bytes = expected_seq - header.seq_number;
if (already_received_bytes <= payload.size())
payload = payload.slice(already_received_bytes);
if (m_recv_window.data_size + payload.size() > m_recv_window.buffer->size())
dprintln_if(DEBUG_TCP, "Cannot fit received bytes to window, waiting for retransmission");
else
payload = {};
}
const bool can_receive_new_data = (payload.size() > 0 && !m_recv_window.buffer->full());
if (can_receive_new_data)
{
const size_t nrecv = BAN::Math::min(payload.size(), m_recv_window.buffer->free());
m_recv_window.buffer->push(payload.slice(0, nrecv));
auto* buffer = reinterpret_cast<uint8_t*>(m_recv_window.buffer->vaddr());
memcpy(buffer + m_recv_window.data_size, payload.data(), payload.size());
m_recv_window.data_size += payload.size();
epoll_notify(EPOLLIN);
dprintln_if(DEBUG_TCP, "Received {} bytes", nrecv);
}
dprintln_if(DEBUG_TCP, "Received {} bytes", payload.size());
// make sure zero window is reported
if (m_last_sent_window_size > 0 && m_recv_window.buffer->full())
m_should_send_zero_window = true;
else if (can_receive_new_data)
if (m_next_flags == 0)
{
m_next_flags = ACK;
m_next_state = m_state;
}
}
}
}
if (!hungup_before && has_hungup_impl())
epoll_notify(EPOLLHUP);
@ -883,14 +793,21 @@ namespace Kernel
continue;
}
if (m_send_window.current_ack - m_send_window.has_ghost_byte > m_send_window.start_seq)
if (m_send_window.data_size > 0 && m_send_window.current_ack - m_send_window.has_ghost_byte > m_send_window.start_seq)
{
const uint32_t acknowledged_bytes = m_send_window.current_ack - m_send_window.start_seq - m_send_window.has_ghost_byte;
ASSERT(acknowledged_bytes <= m_send_window.buffer->size());
uint32_t acknowledged_bytes = m_send_window.current_ack - m_send_window.start_seq - m_send_window.has_ghost_byte;
ASSERT(acknowledged_bytes <= m_send_window.data_size);
m_send_window.data_size -= acknowledged_bytes;
m_send_window.start_seq += acknowledged_bytes;
if (m_send_window.data_size > 0)
{
auto* send_buffer = reinterpret_cast<uint8_t*>(m_send_window.buffer->vaddr());
memmove(send_buffer, send_buffer + acknowledged_bytes, m_send_window.data_size);
}
m_send_window.sent_size -= acknowledged_bytes;
m_send_window.buffer->pop(acknowledged_bytes);
epoll_notify(EPOLLOUT);
@ -899,32 +816,26 @@ namespace Kernel
continue;
}
const bool should_retransmit = m_send_window.had_zero_window || (m_send_window.sent_size > 0 && current_ms >= m_send_window.last_send_ms + retransmit_timeout_ms);
const bool should_retransmit = m_send_window.data_size > 0 && current_ms >= m_send_window.last_send_ms + retransmit_timeout_ms;
const bool can_send_new_data = (m_send_window.buffer->size() > m_send_window.sent_size && m_send_window.sent_size < m_send_window.scaled_size());
if (m_send_window.scaled_size() > 0 && (should_retransmit || can_send_new_data))
if (m_send_window.data_size > m_send_window.sent_size || should_retransmit)
{
m_send_window.had_zero_window = false;
ASSERT(m_connection_info.has_value());
auto* target_address = reinterpret_cast<const sockaddr*>(&m_connection_info->address);
auto target_address_len = m_connection_info->address_len;
const size_t send_offset = should_retransmit ? 0 : m_send_window.sent_size;
const uint32_t send_base = should_retransmit ? 0 : m_send_window.sent_size;
const size_t total_send = BAN::Math::min<size_t>(
m_send_window.buffer->size() - send_offset,
m_send_window.scaled_size() - send_offset
);
const uint32_t total_send = BAN::Math::min<uint32_t>(m_send_window.data_size - send_base, m_send_window.scaled_size());
m_send_window.current_seq = m_send_window.start_seq + send_offset;
m_send_window.current_seq = m_send_window.start_seq + m_send_window.sent_size;
for (size_t i = 0; i < total_send;)
auto* send_buffer = reinterpret_cast<const uint8_t*>(m_send_window.buffer->vaddr() + send_base);
for (uint32_t i = 0; i < total_send;)
{
const size_t to_send = BAN::Math::min<size_t>(total_send - i, m_send_window.mss);
const uint32_t to_send = BAN::Math::min(total_send - i, m_send_window.mss);
auto message = m_send_window.buffer->get_data().slice(send_offset + i, to_send);
auto message = BAN::ConstByteSpan(send_buffer + i, to_send);
m_next_flags = ACK;
if (auto ret = m_network_layer.sendto(*this, message, target_address, target_address_len); ret.is_error())
@ -935,10 +846,9 @@ namespace Kernel
dprintln_if(DEBUG_TCP, "Sent {} bytes", to_send);
i += to_send;
m_send_window.sent_size += to_send;
m_send_window.current_seq += to_send;
if (send_offset + i > m_send_window.sent_size)
m_send_window.sent_size = send_offset + i;
i += to_send;
}
m_send_window.last_send_ms = current_ms;
@ -946,30 +856,6 @@ namespace Kernel
continue;
}
if (m_last_sent_window_size == 0)
m_should_send_zero_window = false;
if (m_should_send_zero_window || m_should_send_window_update)
{
ASSERT(m_connection_info.has_value());
auto* target_address = reinterpret_cast<const sockaddr*>(&m_connection_info->address);
auto target_address_len = m_connection_info->address_len;
m_next_flags = ACK;
if (auto ret = m_network_layer.sendto(*this, {}, target_address, target_address_len); ret.is_error())
dwarnln("{}", ret.error());
m_should_send_zero_window = false;
m_should_send_window_update = false;
if (m_last_sent_window_size == 0 && !m_recv_window.buffer->full())
{
m_next_flags = ACK;
if (auto ret = m_network_layer.sendto(*this, {}, target_address, target_address_len); ret.is_error())
dwarnln("{}", ret.error());
}
}
m_thread_blocker.unblock();
m_thread_blocker.block_with_wake_time_ms(current_ms + retransmit_timeout_ms, &m_mutex);
}

View File

@ -35,26 +35,13 @@ namespace Kernel
m_address_len = 0;
}
void UDPSocket::get_protocol_header(BAN::ByteSpan header_buffer, BAN::ConstByteSpan payload, uint16_t dst_port, PseudoHeader pseudo_header)
void UDPSocket::add_protocol_header(BAN::ByteSpan packet, uint16_t dst_port, PseudoHeader)
{
ASSERT(header_buffer.size() == protocol_header_size());
auto& header = header_buffer.as<UDPHeader>();
header = {
.src_port = bound_port(),
.dst_port = dst_port,
.length = protocol_header_size() + payload.size(),
.checksum = 0,
};
const BAN::ConstByteSpan buffers[] {
BAN::ConstByteSpan::from(pseudo_header),
header_buffer,
payload,
};
header.checksum = calculate_internet_checksum({ buffers, sizeof(buffers) / sizeof(*buffers) });
if (header.checksum == 0)
header.checksum = 0xFFFF;
auto& header = packet.as<UDPHeader>();
header.src_port = bound_port();
header.dst_port = dst_port;
header.length = packet.size();
header.checksum = 0;
}
void UDPSocket::receive_packet(BAN::ConstByteSpan packet, const sockaddr* sender, socklen_t sender_len)
@ -225,11 +212,10 @@ namespace Kernel
BAN::ErrorOr<void> UDPSocket::getsockopt_impl(int level, int option, void* value, socklen_t* value_len)
{
int result;
if (level != SOL_SOCKET)
return BAN::Error::from_errno(EINVAL);
switch (level)
{
case SOL_SOCKET:
int result;
switch (option)
{
case SO_ERROR:
@ -242,16 +228,7 @@ namespace Kernel
result = m_packet_buffer->size();
break;
default:
dwarnln("getsockopt(SOLSOCKET, {})", option);
return BAN::Error::from_errno(ENOPROTOOPT);
}
break;
case IPPROTO_UDP:
dwarnln("getsockopt(IPPROTO_UDP, {})", option);
return BAN::Error::from_errno(ENOPROTOOPT);
default:
dwarnln("getsockopt({}, {})", level, option);
return BAN::Error::from_errno(EINVAL);
return BAN::Error::from_errno(ENOTSUP);
}
const size_t len = BAN::Math::min<size_t>(sizeof(result), *value_len);
@ -261,27 +238,6 @@ namespace Kernel
return {};
}
BAN::ErrorOr<void> UDPSocket::setsockopt_impl(int level, int option, const void* value, socklen_t value_len)
{
(void)value;
(void)value_len;
switch (level)
{
case SOL_SOCKET:
dwarnln("setsockopt(SOL_SOCKET, {})", option);
return BAN::Error::from_errno(ENOPROTOOPT);
case IPPROTO_UDP:
dwarnln("setsockopt(IPPROTO_UDP, {})", option);
return BAN::Error::from_errno(ENOPROTOOPT);
default:
dwarnln("setsockopt({}, {})", level, option);
return BAN::Error::from_errno(EINVAL);
}
return {};
}
BAN::ErrorOr<long> UDPSocket::ioctl_impl(int request, void* argument)
{
switch (request)

View File

@ -707,10 +707,7 @@ namespace Kernel
BAN::ErrorOr<void> UnixDomainSocket::getsockopt_impl(int level, int option, void* value, socklen_t* value_len)
{
if (level != SOL_SOCKET)
{
dwarnln("getsockopt({}, {})", level, option);
return BAN::Error::from_errno(EINVAL);
}
int result;
switch (option)
@ -739,10 +736,7 @@ namespace Kernel
BAN::ErrorOr<void> UnixDomainSocket::setsockopt_impl(int level, int option, const void* value, socklen_t value_len)
{
if (level != SOL_SOCKET)
{
dwarnln("setsockopt({}, {})", level, option);
return BAN::Error::from_errno(EINVAL);
}
switch (option)
{

View File

@ -5,7 +5,6 @@
#include <kernel/ELF.h>
#include <kernel/Epoll.h>
#include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/FS/EventFD.h>
#include <kernel/FS/ProcFS/FileSystem.h>
#include <kernel/FS/VirtualFileSystem.h>
#include <kernel/IDT.h>
@ -29,7 +28,6 @@
#include <pthread.h>
#include <stdio.h>
#include <sys/banan-os.h>
#include <sys/eventfd.h>
#include <sys/futex.h>
#include <sys/sysmacros.h>
#include <sys/wait.h>
@ -381,7 +379,7 @@ namespace Kernel
const auto [master_addr, master_size] = master_tls;
ASSERT(master_size % alignof(uthread) == 0);
const size_t tls_size = master_size + sizeof(uthread);
const size_t tls_size = master_size + PAGE_SIZE;
auto region = TRY(MemoryBackedRegion::create(
page_table,
@ -410,26 +408,28 @@ namespace Kernel
bytes_copied += to_copy;
}
auto uthread = TRY(BAN::UniqPtr<struct uthread>::create());
*uthread = {
const uthread uthread {
.self = reinterpret_cast<struct uthread*>(region->vaddr() + master_size),
.master_tls_addr = reinterpret_cast<void*>(master_addr),
.master_tls_size = master_size,
.master_tls_module_count = 1,
.dynamic_tls = nullptr,
.cleanup_stack = nullptr,
.id = 0,
.errno_ = 0,
.cancel_type = 0,
.cancel_state = 0,
.canceled = 0,
.dtv = { 0, region->vaddr() }
};
const uintptr_t dtv[2] { 1, region->vaddr() };
TRY(region->copy_data_to_region(
master_size,
reinterpret_cast<const uint8_t*>(uthread.ptr()),
sizeof(struct uthread)
reinterpret_cast<const uint8_t*>(&uthread),
sizeof(uthread)
));
TRY(region->copy_data_to_region(
master_size + sizeof(uthread),
reinterpret_cast<const uint8_t*>(&dtv),
sizeof(dtv)
));
TLSResult result;
@ -1658,6 +1658,12 @@ namespace Kernel
BAN::ErrorOr<long> Process::sys_getsockopt(int socket, int level, int option_name, void* user_option_value, socklen_t* user_option_len)
{
if (level != SOL_SOCKET)
{
dwarnln("{}: getsockopt level {}", name(), level);
return BAN::Error::from_errno(EINVAL);
}
socklen_t option_len;
TRY(read_from_user(user_option_len, &option_len, sizeof(socklen_t)));
@ -1679,6 +1685,12 @@ namespace Kernel
BAN::ErrorOr<long> Process::sys_setsockopt(int socket, int level, int option_name, const void* user_option_value, socklen_t option_len)
{
if (level != SOL_SOCKET)
{
dwarnln("{}: setsockopt level {}", name(), level);
return BAN::Error::from_errno(EINVAL);
}
if (option_len < 0)
return BAN::Error::from_errno(EINVAL);
@ -2162,27 +2174,6 @@ namespace Kernel
return TRY(static_cast<Epoll*>(epoll_inode.ptr())->wait(BAN::Span<epoll_event>(events, maxevents), waketime_ns));
}
BAN::ErrorOr<long> Process::sys_eventfd(unsigned int initval, int flags)
{
if (flags & ~(EFD_CLOEXEC | EFD_NONBLOCK | EFD_SEMAPHORE))
return BAN::Error::from_errno(EINVAL);
int oflags = 0;
if (flags & EFD_CLOEXEC)
oflags |= O_CLOEXEC;
if (flags & EFD_NONBLOCK)
oflags |= O_NONBLOCK;
const bool is_semaphore = !!(flags & EFD_SEMAPHORE);
return TRY(m_open_file_descriptors.open(
VirtualFileSystem::File {
TRY(EventFD::create(initval, is_semaphore)),
"<eventfd>"_sv
}, oflags
));
}
BAN::ErrorOr<long> Process::sys_pipe(int user_fildes[2])
{
int fildes[2];
@ -2380,8 +2371,6 @@ namespace Kernel
TRY(read_string_from_user(user_path, path, PATH_MAX));
auto new_cwd = TRY(find_file(AT_FDCWD, path, O_SEARCH));
if (!new_cwd.inode->mode().ifdir())
return BAN::Error::from_errno(ENOTDIR);
LockGuard _(m_process_lock);
m_working_directory = BAN::move(new_cwd);
@ -2665,9 +2654,6 @@ namespace Kernel
for (size_t j = 0; j < new_regions.size(); j++)
TRY(m_mapped_regions.insert(i + j + 1, BAN::move(new_regions[j])));
while (i + 1 < m_mapped_regions.size() && !m_mapped_regions[i + 1]->overlaps(vaddr, len))
i++;
continue;
}

View File

@ -73,9 +73,7 @@ namespace Kernel
: CharacterDevice(mode, uid, gid)
, m_termios(termios)
, m_rdev(next_tty_rdev())
{
m_output.buffer = MUST(ByteRingBuffer::create(PAGE_SIZE));
}
{ }
BAN::RefPtr<TTY> TTY::current()
{
@ -206,7 +204,7 @@ namespace Kernel
}
case FIONREAD:
{
*static_cast<int*>(argument) = m_output.flush ? m_output.buffer->size() : 0;
*static_cast<int*>(argument) = m_output.flush ? m_output.bytes : 0;
return 0;
}
case TIOCGWINSZ:
@ -234,13 +232,14 @@ namespace Kernel
return;
const char* ansi_c_str = LibInput::key_to_utf8_ansi(event.key, event.modifier);
if (ansi_c_str == nullptr)
return;
while (*ansi_c_str)
handle_input_byte(*ansi_c_str++);
if (ansi_c_str)
{
auto* ptr = reinterpret_cast<const uint8_t*>(ansi_c_str);
while (*ptr)
handle_input_byte(*ptr++);
after_write();
}
}
void TTY::handle_input_byte(uint8_t ch)
{
@ -288,7 +287,7 @@ namespace Kernel
if (ch == m_termios.c_cc[VKILL] && (m_termios.c_lflag & ECHOK))
{
while (!m_output.buffer->empty() && m_output.buffer->back() != '\n')
while (m_output.bytes > 0 && m_output.buffer[m_output.bytes - 1] != '\n')
do_backspace();
return;
}
@ -308,8 +307,12 @@ namespace Kernel
// TODO: terminal suspension with VSTOP/VSTART
if (should_append && !m_output.buffer->full())
m_output.buffer->push({ &ch, 1 });
if (should_append)
{
if (m_output.bytes >= m_output.buffer.size())
return;
m_output.buffer[m_output.bytes++] = ch;
}
if (should_append && (force_echo || (m_termios.c_lflag & ECHO)))
{
@ -347,22 +350,29 @@ namespace Kernel
void TTY::do_backspace()
{
if (m_output.buffer->empty())
return;
const bool is_caret_notation =
(m_output.buffer->back() < 32) ||
(m_output.buffer->back() == 127);
// handle multibyte UTF8
while ((m_output.buffer->back() & 0xC0) == 0x80)
m_output.buffer->pop_back(1);
ASSERT(!m_output.buffer->empty());
m_output.buffer->pop_back(1);
if (is_caret_notation)
if (m_output.bytes > 0)
{
uint8_t last = m_output.buffer[m_output.bytes - 1];
// Multibyte UTF8
if ((last & 0xC0) == 0x80)
{
// NOTE: this should be valid UTF8 since keyboard input already 'validates' it
while ((m_output.buffer[m_output.bytes - 1] & 0xC0) == 0x80)
{
ASSERT(m_output.bytes > 0);
m_output.bytes--;
}
ASSERT(m_output.bytes > 0);
m_output.bytes--;
putchar('\b');
putchar(' ');
putchar('\b');
}
// Caret notation
else if (last < 32 || last == 127)
{
m_output.bytes--;
putchar('\b');
putchar('\b');
putchar(' ');
@ -370,13 +380,16 @@ namespace Kernel
putchar('\b');
putchar('\b');
}
// Ascii
else
{
m_output.bytes--;
putchar('\b');
putchar(' ');
putchar('\b');
}
}
}
bool TTY::putchar(uint8_t ch)
{
@ -398,7 +411,7 @@ namespace Kernel
while (!m_output.flush)
TRY(Thread::current().block_or_eintr_indefinite(m_output.thread_blocker, &m_mutex));
if (m_output.buffer->empty())
if (m_output.bytes == 0)
{
if (master_has_closed())
return 0;
@ -406,19 +419,19 @@ namespace Kernel
return 0;
}
auto data = m_output.buffer->get_data();
const size_t max_to_copy = BAN::Math::min<size_t>(buffer.size(), data.size());
const size_t max_to_copy = BAN::Math::min<size_t>(buffer.size(), m_output.bytes);
size_t to_copy = max_to_copy;
if (m_termios.c_lflag & ICANON)
for (to_copy = 1; to_copy < max_to_copy; to_copy++)
if (data[to_copy - 1] == NL)
if (m_output.buffer[to_copy - 1] == NL)
break;
memcpy(buffer.data(), data.data(), to_copy);
m_output.buffer->pop(to_copy);
memcpy(buffer.data(), m_output.buffer.data(), to_copy);
if (m_output.buffer->empty())
memmove(m_output.buffer.data(), m_output.buffer.data() + to_copy, m_output.bytes - to_copy);
m_output.bytes -= to_copy;
if (m_output.bytes == 0)
m_output.flush = false;
m_output.thread_blocker.unblock();

View File

@ -3,7 +3,7 @@
NAME='cairo'
VERSION='1.18.4'
DOWNLOAD_URL="https://cairographics.org/releases/cairo-$VERSION.tar.xz#445ed8208a6e4823de1226a74ca319d3600e83f6369f99b14265006599c32ccb"
DEPENDENCIES=('libpng' 'pixman' 'fontconfig' 'glib' 'libX11' 'libXrender' 'libXext')
DEPENDENCIES=('libpng' 'pixman' 'fontconfig' 'glib')
CONFIGURE_OPTIONS=(
'-Dprefix=/usr'
'-Dtests=disabled'

View File

@ -1,29 +0,0 @@
#!/bin/bash ../install.sh
NAME='dbus'
VERSION='1.16.2'
DOWNLOAD_URL="https://dbus.freedesktop.org/releases/dbus/dbus-$VERSION.tar.xz#0ba2a1a4b16afe7bceb2c07e9ce99a8c2c3508e5dec290dbb643384bd6beb7e2"
DEPENDENCIES=('glib' 'expat')
CONFIGURE_OPTIONS=(
'-Dprefix=/usr'
'-Depoll=disabled' # linux only
'-Dintrusive_tests=false'
'-Dinstalled_tests=false'
'-Dmodular_tests=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="$BANAN_SYSROOT" -C build || exit 1
}

View File

@ -1,13 +0,0 @@
diff -ruN dbus-1.16.2/tools/dbus-print-message.c dbus-1.16.2-banan_os/tools/dbus-print-message.c
--- dbus-1.16.2/tools/dbus-print-message.c 2025-02-27 18:29:06.000000000 +0200
+++ dbus-1.16.2-banan_os/tools/dbus-print-message.c 2026-02-21 23:23:51.987302740 +0200
@@ -31,7 +31,9 @@
#include <sys/un.h>
#include <unistd.h>
#include <netinet/in.h>
+#ifndef __banan_os__
#include <netinet/ip.h>
+#endif
#include <arpa/inet.h>
#endif

View File

@ -1,48 +0,0 @@
diff -ruN expat-2.7.1/configure expat-2.7.1-banan_os/configure
--- expat-2.7.1/configure 2025-03-27 21:46:37.000000000 +0200
+++ expat-2.7.1-banan_os/configure 2025-08-10 00:50:27.773898797 +0300
@@ -6679,6 +6679,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
;;
@@ -12479,6 +12483,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"
@@ -18079,6 +18093,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"

View File

@ -1,47 +0,0 @@
#!/bin/bash ../install.sh
NAME='fontconfig'
VERSION='2.17.1'
DOWNLOAD_URL="https://gitlab.freedesktop.org/fontconfig/fontconfig/-/archive/$VERSION/fontconfig-$VERSION.tar.gz#82e73b26adad651b236e5f5d4b3074daf8ff0910188808496326bd3449e5261d"
DEPENDENCIES=('harfbuzz' 'freetype' 'expat' 'libiconv')
CONFIGURE_OPTIONS=(
'-Dprefix=/usr'
'-Dtests=disabled'
'-Dnls=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="$BANAN_SYSROOT" -C build || exit 1
}
post_install() {
pushd .. &>/dev/null
local font_name='dejavu-fonts-ttf-2.37'
if [ ! -f "$font_name.tar.bz2" ]; then
wget "http://sourceforge.net/projects/dejavu/files/dejavu/2.37/$font_name.tar.bz2" || exit 1
fi
if [ ! -d "$font_name" ]; then
tar xf "$font_name.tar.bz2" || exit 1
fi
mkdir -p "$BANAN_SYSROOT/usr/share/fonts/TTF" || exit 1
cp "$font_name/ttf/"* "$BANAN_SYSROOT/usr/share/fonts/TTF/" || exit 1
cp "$font_name/fontconfig/"* "$BANAN_SYSROOT/usr/share/fontconfig/conf.avail/" || exit 1
popd &>/dev/null
}

View File

@ -1,6 +0,0 @@
#!/bin/bash ../install.sh
NAME='fribidi'
VERSION='1.0.16'
DOWNLOAD_URL="https://github.com/fribidi/fribidi/releases/download/v$VERSION/fribidi-$VERSION.tar.xz#1b1cde5b235d40479e91be2f0e88a309e3214c8ab470ec8a2744d82a5a9ea05c"
CONFIG_SUB=('config.sub')

View File

@ -1,20 +0,0 @@
diff -ruN fribidi-1.0.16/configure fribidi-1.0.16-banan_os/configure
--- fribidi-1.0.16/configure 2024-09-25 21:04:21.000000000 +0300
+++ fribidi-1.0.16-banan_os/configure 2025-11-05 20:51:12.227775953 +0200
@@ -11536,6 +11536,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"

View File

@ -1,27 +0,0 @@
#!/bin/bash ../install.sh
NAME='gdk-pixbuf'
VERSION='2.44.4'
DOWNLOAD_URL="https://gitlab.gnome.org/GNOME/gdk-pixbuf/-/archive/$VERSION/gdk-pixbuf-$VERSION.tar.gz#6de2f77d992155b4121d20036e7e986dfe595a0e654381cdd0d7257f493c208a"
DEPENDENCIES=('glib' 'libpng' 'libjpeg' 'libtiff' 'shared-mime-info')
CONFIGURE_OPTIONS=(
'-Dprefix=/usr'
'-Dtests=false'
'-Dman=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="$BANAN_SYSROOT" -C build || exit 1
}

View File

@ -1,14 +1,13 @@
#!/bin/bash ../install.sh
NAME='git'
VERSION='2.53.0'
DOWNLOAD_URL="https://www.kernel.org/pub/software/scm/git/git-$VERSION.tar.xz#5818bd7d80b061bbbdfec8a433d609dc8818a05991f731ffc4a561e2ca18c653"
DEPENDENCIES=('zlib' 'openssl' 'curl' 'libiconv')
VERSION='2.52.0'
DOWNLOAD_URL="https://www.kernel.org/pub/software/scm/git/git-$VERSION.tar.xz#3cd8fee86f69a949cb610fee8cd9264e6873d07fa58411f6060b3d62729ed7c5"
DEPENDENCIES=('zlib' 'openssl' 'curl')
CONFIGURE_OPTIONS=(
'--with-curl'
'--with-openssl'
ac_cv_fread_reads_directories=no
ac_cv_iconv_omits_bom=no
ac_cv_lib_curl_curl_global_init=yes
ac_cv_snprintf_returns_bogus=no
ac_cv_lib_curl_curl_global_init=yes
)

View File

@ -1,30 +0,0 @@
#!/bin/bash ../install.sh
NAME='gtk'
VERSION='3.24.49'
DOWNLOAD_URL="https://gitlab.gnome.org/GNOME/gtk/-/archive/$VERSION/gtk-$VERSION.tar.gz#a2958d82986c81794e953a3762335fa7c78948706d23cced421f7245ca544cbc"
DEPENDENCIES=('glib' 'gdk-pixbuf' 'pango' 'libatk' 'libepoxy' 'libXrandr')
CONFIGURE_OPTIONS=(
'-Dprefix=/usr'
'-Dtests=false'
'-Dexamples=false'
'-Dintrospection=false'
'-Dx11_backend=true'
'-Dwayland_backend=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="$BANAN_SYSROOT" -C build || exit 1
}

View File

@ -1,45 +0,0 @@
#!/bin/bash ../install.sh
NAME='icu'
VERSION='78.1'
DOWNLOAD_URL="https://github.com/unicode-org/icu/releases/download/release-$VERSION/icu4c-$VERSION-sources.tgz#6217f58ca39b23127605cfc6c7e0d3475fe4b0d63157011383d716cb41617886"
TAR_CONTENT='icu'
_DEPENDENCIES=('ca-certificates' 'openssl' 'zlib' 'zstd')
CONFIG_SUB=('source/config.sub')
CONFIGURE_OPTIONS=(
"--with-cross-build=$BANAN_PORT_DIR/icu/icu-$VERSION-$BANAN_ARCH/source/build-host"
'--disable-tests'
'--disable-samples'
)
pre_configure() {
unset CC CXX LD AS AR
mkdir -p source/build-host || exit 1
pushd source/build-host || exit 1
../configure --disable-tests --disable-samples || exit 1
make -j$(proc) || exit 1
popd >/dev/null || exit 1
pushd source >/dev/null || exit 1
}
post_configure() {
popd >/dev/null || exit 1
}
pre_build() {
pushd source >/dev/null || exit 1
}
post_build() {
popd >/dev/null || exit 1
}
pre_install() {
pushd source >/dev/null || exit 1
}
post_install() {
popd >/dev/null || exit 1
}

View File

@ -1,95 +0,0 @@
diff -ruN icu-78.1/source/config/mh-banan_os icu-78.1-banan_os/source/config/mh-banan_os
--- icu-78.1/source/config/mh-banan_os 1970-01-01 02:00:00.000000000 +0200
+++ icu-78.1-banan_os/source/config/mh-banan_os 2025-11-06 23:07:11.542495330 +0200
@@ -0,0 +1,80 @@
+## -*-makefile-*-
+## Copyright (C) 2016 and later: Unicode, Inc. and others.
+## License & terms of use: http://www.unicode.org/copyright.html
+## haiku-specific setup
+## Copyright (c) 2010-2012, International Business Machines Corporation and
+## others. All Rights Reserved.
+##
+
+## Commands to generate dependency files
+GEN_DEPS.c= $(CC) -E -MM $(DEFS) $(CPPFLAGS)
+GEN_DEPS.cc= $(CXX) -E -MM $(DEFS) $(CPPFLAGS)
+
+## Flags for position independent code
+SHAREDLIBCFLAGS = -fPIC
+SHAREDLIBCXXFLAGS = -fPIC
+SHAREDLIBCPPFLAGS = -DPIC
+
+## Additional flags when building libraries and with threads
+LIBCPPFLAGS =
+THREADSCPPFLAGS =
+
+#
+CPPFLAGS += -DU_CHARSET_IS_UTF8=1
+
+## Compiler switch to embed a runtime search path
+LD_RPATH=
+LD_RPATH_PRE = -Wl,-rpath,
+
+## Compiler switch to embed a library name
+LD_SONAME = -Wl,-soname -Wl,$(notdir $(MIDDLE_SO_TARGET))
+
+## Shared object suffix
+SO = so
+## Non-shared intermediate object suffix
+STATIC_O = ao
+
+## Compilation rules
+%.$(STATIC_O): $(srcdir)/%.c
+ $(COMPILE.c) $(STATICCPPFLAGS) $(STATICCFLAGS) -o $@ $<
+%.o: $(srcdir)/%.c
+ $(COMPILE.c) $(DYNAMICCPPFLAGS) $(DYNAMICCFLAGS) -o $@ $<
+
+%.$(STATIC_O): $(srcdir)/%.cpp
+ $(COMPILE.cc) $(STATICCPPFLAGS) $(STATICCXXFLAGS) -o $@ $<
+%.o: $(srcdir)/%.cpp
+ $(COMPILE.cc) $(DYNAMICCPPFLAGS) $(DYNAMICCXXFLAGS) -o $@ $<
+
+
+## Dependency rules
+%.d: $(srcdir)/%.c
+ @echo "generating dependency information for $<"
+ @$(SHELL) -ec '$(GEN_DEPS.c) $< \
+ | sed '\''s%\($*\)\.o[ :]*%\1.o $@ : %g'\'' > $@; \
+ [ -s $@ ] || rm -f $@'
+
+%.d: $(srcdir)/%.cpp
+ @echo "generating dependency information for $<"
+ @$(SHELL) -ec '$(GEN_DEPS.cc) $< \
+ | sed '\''s%\($*\)\.o[ :]*%\1.o $@ : %g'\'' > $@; \
+ [ -s $@ ] || rm -f $@'
+
+## Versioned libraries rules
+
+%.$(SO).$(SO_TARGET_VERSION_MAJOR): %.$(SO).$(SO_TARGET_VERSION)
+ $(RM) $@ && ln -s ${<F} $@
+%.$(SO): %.$(SO).$(SO_TARGET_VERSION_MAJOR)
+ $(RM) $@ && ln -s ${*F}.$(SO).$(SO_TARGET_VERSION) $@
+
+## Bind internal references
+
+# LDflags that pkgdata will use
+BIR_LDFLAGS= -Wl,-Bsymbolic
+
+# Dependencies [i.e. map files] for the final library
+BIR_DEPS=
+
+# Use LIBRARY_PATH instead of LD_LIBRARY_PATH
+LDLIBRARYPATH_ENVVAR= LIBRARY_PATH
+
+## End haiku-specific setup
diff -ruN icu-78.1/source/configure icu-78.1-banan_os/source/configure
--- icu-78.1/source/configure 2025-10-30 19:37:19.000000000 +0200
+++ icu-78.1-banan_os/source/configure 2025-11-06 23:06:17.308923216 +0200
@@ -5829,6 +5829,7 @@
*-apple-darwin*) icu_cv_host_frag=mh-darwin ;;
*-*-beos) icu_cv_host_frag=mh-beos ;;
*-*-haiku) icu_cv_host_frag=mh-haiku ;;
+*-*-banan_os) icu_cv_host_frag=mh-banan_os ;;
*-*-irix*) icu_cv_host_frag=mh-irix ;;
*-dec-osf*) icu_cv_host_frag=mh-alpha-osf ;;
*-*-nto*) icu_cv_host_frag=mh-qnx ;;

View File

@ -1,11 +0,0 @@
--- icu/source/common/unicode/ptypes.h 2025-10-30 19:37:19.000000000 +0200
+++ icu-78.1-x86_64/source/common/unicode/ptypes.h 2025-11-06 23:12:15.984514832 +0200
@@ -56,7 +56,7 @@
// implementations (looking at you, Apple, spring 2024) actually do this, so
// ICU4C must detect and deal with that.
#if !defined(__cplusplus) && !defined(U_IN_DOXYGEN)
-# if U_HAVE_CHAR16_T
+# if ! U_HAVE_CHAR16_T
# include <uchar.h>
# else
typedef uint16_t char16_t;

View File

@ -1,11 +0,0 @@
#!/bin/bash ../install.sh
NAME='libICE'
VERSION='1.1.2'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libICE-$VERSION.tar.xz#974e4ed414225eb3c716985df9709f4da8d22a67a2890066bc6dfc89ad298625"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('xorgproto' 'xtrans')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)

View File

@ -1,31 +0,0 @@
diff -ruN libICE-1.1.2/configure libICE-1.1.2-banan_os/configure
--- libICE-1.1.2/configure 2024-12-13 23:40:33.000000000 +0200
+++ libICE-1.1.2-banan_os/configure 2025-11-16 23:38:24.456211241 +0200
@@ -6464,6 +6464,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
;;
@@ -11969,6 +11973,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"

View File

@ -1,11 +0,0 @@
#!/bin/bash ../install.sh
NAME='libSM'
VERSION='1.2.6'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libSM-$VERSION.tar.xz#be7c0abdb15cbfd29ac62573c1c82e877f9d4047ad15321e7ea97d1e43d835be"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('libICE')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)

View File

@ -1,31 +0,0 @@
diff -ruN libSM-1.2.6/configure libSM-1.2.6-banan_os/configure
--- libSM-1.2.6/configure 2025-03-09 03:46:18.000000000 +0200
+++ libSM-1.2.6-banan_os/configure 2025-11-16 23:36:16.733929290 +0200
@@ -6262,6 +6262,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
;;
@@ -11797,6 +11801,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"

View File

@ -1,11 +0,0 @@
#!/bin/bash ../install.sh
NAME='libX11'
VERSION='1.8.12'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libX11-$VERSION.tar.xz#fa026f9bb0124f4d6c808f9aef4057aad65e7b35d8ff43951cef0abe06bb9a9a"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('xorgproto' 'xtrans' 'libxcb')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)

View File

@ -1,31 +0,0 @@
diff -ruN libX11-1.8.12/configure libX11-1.8.12-banan_os/configure
--- libX11-1.8.12/configure 2025-03-09 01:53:09.000000000 +0200
+++ libX11-1.8.12-banan_os/configure 2025-11-13 20:07:46.592619585 +0200
@@ -6633,6 +6633,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
;;
@@ -12138,6 +12142,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"

View File

@ -1,11 +0,0 @@
#!/bin/bash ../install.sh
NAME='libXau'
VERSION='1.0.12'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libXau-$VERSION.tar.xz#74d0e4dfa3d39ad8939e99bda37f5967aba528211076828464d2777d477fc0fb"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('xorgproto')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)

View File

@ -1,31 +0,0 @@
diff -ruN libXau-1.0.12/configure libXau-1.0.12-banan_os/configure
--- libXau-1.0.12/configure 2024-12-14 03:33:02.000000000 +0200
+++ libXau-1.0.12-banan_os/configure 2025-11-13 20:00:35.574268731 +0200
@@ -6224,6 +6224,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
;;
@@ -12060,6 +12064,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"

View File

@ -1,11 +0,0 @@
#!/bin/bash ../install.sh
NAME='libXaw'
VERSION='1.0.16'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libXaw-$VERSION.tar.xz#731d572b54c708f81e197a6afa8016918e2e06dfd3025e066ca642a5b8c39c8f"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('libX11' 'libXext' 'libXt' 'libXmu' 'libXpm')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)

View File

@ -1,31 +0,0 @@
diff -ruN libXaw-1.0.16/configure libXaw-1.0.16-banan_os/configure
--- libXaw-1.0.16/configure 2024-03-10 19:39:54.000000000 +0200
+++ libXaw-1.0.16-banan_os/configure 2025-11-16 23:51:15.704550082 +0200
@@ -5977,6 +5977,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
;;
@@ -11343,6 +11347,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"

View File

@ -1,11 +0,0 @@
#!/bin/bash ../install.sh
NAME='libXdmcp'
VERSION='1.1.5'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libXdmcp-$VERSION.tar.xz#d8a5222828c3adab70adf69a5583f1d32eb5ece04304f7f8392b6a353aa2228c"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('xorgproto')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)

View File

@ -1,31 +0,0 @@
diff -ruN libXdmcp-1.1.5/configure libXdmcp-1.1.5-banan_os/configure
--- libXdmcp-1.1.5/configure 2024-03-02 23:37:19.000000000 +0200
+++ libXdmcp-1.1.5-banan_os/configure 2025-11-13 21:49:06.142805910 +0200
@@ -6247,6 +6247,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
;;
@@ -11960,6 +11964,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"

View File

@ -1,12 +0,0 @@
#!/bin/bash ../install.sh
NAME='libXext'
VERSION='1.3.6'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libXext-$VERSION.tar.xz#edb59fa23994e405fdc5b400afdf5820ae6160b94f35e3dc3da4457a16e89753"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('libX11')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
'--disable-malloc0returnsnull'
)

View File

@ -1,31 +0,0 @@
diff -ruN libXext-1.3.6/configure libXext-1.3.6-banan_os/configure
--- libXext-1.3.6/configure 2024-02-04 23:42:50.000000000 +0200
+++ libXext-1.3.6-banan_os/configure 2025-11-16 23:30:16.532954111 +0200
@@ -6282,6 +6282,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
;;
@@ -11663,6 +11667,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'

View File

@ -1,11 +0,0 @@
#!/bin/bash ../install.sh
NAME='libXfixes'
VERSION='6.0.2'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libXfixes-$VERSION.tar.xz#39f115d72d9c5f8111e4684164d3d68cc1fd21f9b27ff2401b08fddfc0f409ba"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('libX11')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)

View File

@ -1,31 +0,0 @@
diff -ruN libXfixes-6.0.2/configure libXfixes-6.0.2-banan_os/configure
--- libXfixes-6.0.2/configure 2025-09-02 02:25:56.000000000 +0300
+++ libXfixes-6.0.2-banan_os/configure 2025-11-16 23:59:00.284383978 +0200
@@ -6157,6 +6157,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
;;
@@ -11692,6 +11696,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"

View File

@ -1,11 +0,0 @@
#!/bin/bash ../install.sh
NAME='libXfont2'
VERSION='2.0.7'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libXfont2-$VERSION.tar.xz#8b7b82fdeba48769b69433e8e3fbb984a5f6bf368b0d5f47abeec49de3e58efb"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('freetype' 'xorgproto' 'xtrans' 'libfontenc')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)

View File

@ -1,31 +0,0 @@
diff -ruN libXfont2-2.0.7/configure libXfont2-2.0.7-banan_os/configure
--- libXfont2-2.0.7/configure 2024-08-02 02:38:54.000000000 +0300
+++ libXfont2-2.0.7-banan_os/configure 2025-11-13 20:21:21.333718050 +0200
@@ -6558,6 +6558,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
;;
@@ -11940,6 +11944,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"

View File

@ -1,11 +0,0 @@
#!/bin/bash ../install.sh
NAME='libXft'
VERSION='2.3.9'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libXft-$VERSION.tar.xz#60a25b78945ed6932635b3bb1899a517d31df7456e69867ffba27f89ff3976f5"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('libXrender' 'libX11' 'freetype' 'fontconfig')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)

View File

@ -1,31 +0,0 @@
diff -ruN libXft-2.3.9/configure libXft-2.3.9-banan_os/configure
--- libXft-2.3.9/configure 2025-04-20 18:10:46.000000000 +0300
+++ libXft-2.3.9-banan_os/configure 2025-11-17 01:42:42.971908492 +0200
@@ -5873,6 +5873,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
;;
@@ -11239,6 +11243,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"

View File

@ -1,12 +0,0 @@
#!/bin/bash ../install.sh
NAME='libXi'
VERSION='1.8.2'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libXi-$VERSION.tar.xz#d0e0555e53d6e2114eabfa44226ba162d2708501a25e18d99cfb35c094c6c104"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('libX11' 'libXext' 'libXfixes')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
'--disable-malloc0returnsnull'
)

View File

@ -1,31 +0,0 @@
diff -ruN libXi-1.8.2/configure libXi-1.8.2-banan_os/configure
--- libXi-1.8.2/configure 2024-09-05 04:19:46.000000000 +0300
+++ libXi-1.8.2-banan_os/configure 2025-11-16 23:54:14.061298859 +0200
@@ -6020,6 +6020,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
;;
@@ -11377,6 +11381,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"

View File

@ -1,11 +0,0 @@
#!/bin/bash ../install.sh
NAME='libXmu'
VERSION='1.2.1'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libXmu-$VERSION.tar.xz#fcb27793248a39e5fcc5b9c4aec40cc0734b3ca76aac3d7d1c264e7f7e14e8b2"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('libXt' 'libXext' 'libX11')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)

View File

@ -1,31 +0,0 @@
diff -ruN libXmu-1.2.1/configure libXmu-1.2.1-banan_os/configure
--- libXmu-1.2.1/configure 2024-04-16 23:02:25.000000000 +0300
+++ libXmu-1.2.1-banan_os/configure 2025-11-16 23:42:28.961754856 +0200
@@ -6165,6 +6165,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
;;
@@ -11492,6 +11496,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"

View File

@ -1,11 +0,0 @@
#!/bin/bash ../install.sh
NAME='libXpm'
VERSION='3.5.17'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libXpm-$VERSION.tar.xz#64b31f81019e7d388c822b0b28af8d51c4622b83f1f0cb6fa3fc95e271226e43"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('libX11')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)

View File

@ -1,31 +0,0 @@
diff -ruN libXpm-3.5.17/configure libXpm-3.5.17-banan_os/configure
--- libXpm-3.5.17/configure 2023-10-03 19:12:11.000000000 +0300
+++ libXpm-3.5.17-banan_os/configure 2025-11-16 23:46:08.171880860 +0200
@@ -5897,6 +5897,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
;;
@@ -11254,6 +11258,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"

View File

@ -1,11 +0,0 @@
#!/bin/bash ../install.sh
NAME='libXrandr'
VERSION='1.5.5'
DOWNLOAD_URL="https://xorg.freedesktop.org/archive/individual/lib/libXrandr-$VERSION.tar.xz#72b922c2e765434e9e9f0960148070bd4504b288263e2868a4ccce1b7cf2767a"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('libX11' 'libXext' 'libXrender')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)

View File

@ -1,31 +0,0 @@
diff -ruN libXrandr-1.5.5/configure libXrandr-1.5.5-banan_os/configure
--- libXrandr-1.5.5/configure 2026-01-26 02:25:38.000000000 +0200
+++ libXrandr-1.5.5-banan_os/configure 2026-02-21 23:34:03.906187857 +0200
@@ -6162,6 +6162,10 @@
lt_cv_deplibs_check_method=pass_all
;;
+banan_os*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
beos*)
lt_cv_deplibs_check_method=pass_all
;;
@@ -11697,6 +11701,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"

View File

@ -1,11 +0,0 @@
#!/bin/bash ../install.sh
NAME='libXrender'
VERSION='0.9.12'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libXrender-$VERSION.tar.xz#b832128da48b39c8d608224481743403ad1691bf4e554e4be9c174df171d1b97"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('libX11')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)

View File

@ -1,31 +0,0 @@
diff -ruN libXrender-0.9.12/configure libXrender-0.9.12-banan_os/configure
--- libXrender-0.9.12/configure 2024-12-13 23:07:57.000000000 +0200
+++ libXrender-0.9.12-banan_os/configure 2025-11-17 00:04:56.995318198 +0200
@@ -6035,6 +6035,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
;;
@@ -11570,6 +11574,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"

View File

@ -1,11 +0,0 @@
#!/bin/bash ../install.sh
NAME='libXt'
VERSION='1.3.1'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libXt-$VERSION.tar.xz#e0a774b33324f4d4c05b199ea45050f87206586d81655f8bef4dba434d931288"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('libSM' 'libICE' 'libX11')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)

View File

@ -1,31 +0,0 @@
diff -ruN libXt-1.3.1/configure libXt-1.3.1-banan_os/configure
--- libXt-1.3.1/configure 2024-11-17 06:44:13.000000000 +0200
+++ libXt-1.3.1-banan_os/configure 2025-11-16 23:33:28.525874895 +0200
@@ -6313,6 +6313,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
;;
@@ -11695,6 +11699,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"

View File

@ -1,11 +0,0 @@
#!/bin/bash ../install.sh
NAME='libXtst'
VERSION='1.2.5'
DOWNLOAD_URL="https://xorg.freedesktop.org/archive/individual/lib/libXtst-$VERSION.tar.xz#b50d4c25b97009a744706c1039c598f4d8e64910c9fde381994e1cae235d9242"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('libX11' 'libXext' 'libXi')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)

View File

@ -1,31 +0,0 @@
diff -ruN libXtst-1.2.5/configure libXtst-1.2.5-banan_os/configure
--- libXtst-1.2.5/configure 2024-08-02 03:27:45.000000000 +0300
+++ libXtst-1.2.5-banan_os/configure 2026-02-21 23:29:27.999396388 +0200
@@ -6194,6 +6194,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
;;
@@ -11606,6 +11610,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"

View File

@ -1,26 +0,0 @@
#!/bin/bash ../install.sh
NAME='libatk'
VERSION='2.56.6'
DOWNLOAD_URL="https://gitlab.gnome.org/GNOME/at-spi2-core/-/archive/$VERSION/at-spi2-core-$VERSION.tar.gz#49b1a640d50a95389a31672a0a077f0c20e8e222322cbd0228d3fa597686819d"
TAR_CONTENT="at-spi2-core-$VERSION"
DEPENDENCIES=('glib' 'dbus' 'libxml2' 'libX11' 'libXtst')
CONFIGURE_OPTIONS=(
'-Dprefix=/usr'
)
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="$BANAN_SYSROOT" -C build || exit 1
}

View File

@ -1,27 +0,0 @@
#!/bin/bash ../install.sh
NAME='libepoxy'
VERSION='1.5.10'
DOWNLOAD_URL="https://download.gnome.org/sources/libepoxy/1.5/libepoxy-$VERSION.tar.xz#072cda4b59dd098bba8c2363a6247299db1fa89411dc221c8b81b8ee8192e623"
DEPENDENCIES=('mesa' 'libX11')
CONFIGURE_OPTIONS=(
'-Dprefix=/usr'
'-Dtests=false'
'-Degl=no'
)
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="$BANAN_SYSROOT" -C build || exit 1
}

View File

@ -1,23 +0,0 @@
--- libepoxy-1.5.10/src/dispatch_common.c 2022-02-17 14:56:12.000000000 +0200
+++ libepoxy-1.5.10-banan_os/src/dispatch_common.c 2025-11-11 18:35:23.194563757 +0200
@@ -164,7 +164,9 @@
#include <windows.h>
#else
#include <dlfcn.h>
+#ifndef __banan_os__
#include <err.h>
+#endif
#include <pthread.h>
#endif
#include <string.h>
@@ -306,8 +308,10 @@
pthread_mutex_lock(&api.mutex);
if (!*handle) {
int flags = RTLD_LAZY | RTLD_LOCAL;
+#ifdef RTLD_NOLOAD
if (!load)
flags |= RTLD_NOLOAD;
+#endif
*handle = dlopen(lib_name, flags);
if (!*handle) {

View File

@ -1,11 +0,0 @@
#!/bin/bash ../install.sh
NAME='libfontenc'
VERSION='1.1.8'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libfontenc-$VERSION.tar.xz#7b02c3d405236e0d86806b1de9d6868fe60c313628b38350b032914aa4fd14c6"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('zlib' 'xorgproto')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)

View File

@ -1,31 +0,0 @@
diff -ruN libfontenc-1.1.8/configure libfontenc-1.1.8-banan_os/configure
--- libfontenc-1.1.8/configure 2024-03-02 20:32:14.000000000 +0200
+++ libfontenc-1.1.8-banan_os/configure 2025-11-13 20:25:22.782104114 +0200
@@ -6145,6 +6145,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
;;
@@ -11527,6 +11531,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"

View File

@ -1,5 +0,0 @@
#!/bin/bash ../install.sh
NAME='libpthread-stubs'
VERSION='0.5'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libpthread-stubs-$VERSION.tar.xz#59da566decceba7c2a7970a4a03b48d9905f1262ff94410a649224e33d2442bc"

View File

@ -1,11 +0,0 @@
#!/bin/bash ../install.sh
NAME='libxcb'
VERSION='1.17.0'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libxcb-$VERSION.tar.xz#599ebf9996710fea71622e6e184f3a8ad5b43d0e5fa8c4e407123c88a59a6d55"
CONFIG_SUB=('config.sub' 'build-aux/config.sub')
DEPENDENCIES=('xcb-proto' 'libXau' 'libXdmcp' 'libpthread-stubs')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)

View File

@ -1,31 +0,0 @@
diff -ruN libxcb-1.17.0/configure libxcb-1.17.0-banan_os/configure
--- libxcb-1.17.0/configure 2024-04-15 18:09:34.000000000 +0300
+++ libxcb-1.17.0-banan_os/configure 2025-11-13 19:58:33.829610129 +0200
@@ -6886,6 +6886,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
;;
@@ -12538,6 +12542,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"

View File

@ -1,11 +0,0 @@
#!/bin/bash ../install.sh
NAME='libxkbfile'
VERSION='1.1.3'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libxkbfile-$VERSION.tar.xz#a9b63eea997abb9ee6a8b4fbb515831c841f471af845a09de443b28003874bec"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('libX11' 'xkeyboard-config')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)

View File

@ -1,31 +0,0 @@
diff -ruN libxkbfile-1.1.3/configure libxkbfile-1.1.3-banan_os/configure
--- libxkbfile-1.1.3/configure 2024-02-05 00:14:27.000000000 +0200
+++ libxkbfile-1.1.3-banan_os/configure 2025-11-13 20:14:55.314294954 +0200
@@ -5944,6 +5944,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
;;
@@ -11356,6 +11360,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"

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