Compare commits
100 Commits
84006e1e77
...
9d0990e5e8
| Author | SHA1 | Date |
|---|---|---|
|
|
9d0990e5e8 | |
|
|
3207f5d61f | |
|
|
c72b351bba | |
|
|
1f9b296ae7 | |
|
|
e3e2e7b4df | |
|
|
4ec8f4a4bf | |
|
|
05d59a05df | |
|
|
11ccbe6506 | |
|
|
673711a246 | |
|
|
fff5139d80 | |
|
|
812e70c626 | |
|
|
db7ffcf9d5 | |
|
|
8f6cb9c057 | |
|
|
291f298d19 | |
|
|
d60f12d3b8 | |
|
|
b8a2573bb4 | |
|
|
7ce8e610f5 | |
|
|
839b9c8f07 | |
|
|
db20801521 | |
|
|
160a9278c9 | |
|
|
ee507de154 | |
|
|
dc0fa49de2 | |
|
|
b678541427 | |
|
|
6c4cd0d8cb | |
|
|
c096d3cd42 | |
|
|
dcdab4df21 | |
|
|
9803209ba1 | |
|
|
f166cb09ec | |
|
|
2dd8b76289 | |
|
|
2bf7c67767 | |
|
|
dd636ffcb2 | |
|
|
a44c45ff9e | |
|
|
dc2a455395 | |
|
|
c700d9f714 | |
|
|
59cfc339b0 | |
|
|
e06c07ca89 | |
|
|
6facd54a7e | |
|
|
6f8d850726 | |
|
|
f3beee9874 | |
|
|
35e063bdaf | |
|
|
09175d1799 | |
|
|
46f9a9053f | |
|
|
bb86520094 | |
|
|
c1e2c660bf | |
|
|
89c0ff1a9d | |
|
|
7a68ce7e94 | |
|
|
9537922acc | |
|
|
a39aa73e21 | |
|
|
f1d12c330e | |
|
|
82c8eeb4be | |
|
|
3a951f4830 | |
|
|
998ea25fb9 | |
|
|
7b580b8f56 | |
|
|
641ccfdd47 | |
|
|
4288f70d04 | |
|
|
95fda5dfb7 | |
|
|
1903c5e0c6 | |
|
|
362501a097 | |
|
|
72982e3c2b | |
|
|
04d24bce70 | |
|
|
2f38306c6b | |
|
|
4b36e5197d | |
|
|
b755cf3e42 | |
|
|
3acad7c911 | |
|
|
f3319016c4 | |
|
|
4e14f7d483 | |
|
|
979059c804 | |
|
|
bdf4423512 | |
|
|
c6ef4b5840 | |
|
|
acd792d8b4 | |
|
|
fc730679ed | |
|
|
00e5749e20 | |
|
|
7b4d349574 | |
|
|
dc0cccfb6c | |
|
|
fdc1daefb6 | |
|
|
c9159b81c8 | |
|
|
9233049356 | |
|
|
bd9015e474 | |
|
|
3a79540d2d | |
|
|
9e500dc387 | |
|
|
e05a735589 | |
|
|
0be18c4a53 | |
|
|
e258fde25a | |
|
|
7367672570 | |
|
|
b822d42889 | |
|
|
10084ff1bb | |
|
|
c3c69ac727 | |
|
|
0cfda6f6a7 | |
|
|
dc51ce9e92 | |
|
|
aa0de2b00e | |
|
|
5f61581e1d | |
|
|
f519cb2cc0 | |
|
|
37aef630d2 | |
|
|
d93fcff5db | |
|
|
4952a82af5 | |
|
|
fecda6a034 | |
|
|
9f0addbd8b | |
|
|
7f8ea6b8e0 | |
|
|
9d3ea6fed7 | |
|
|
703b3eda56 |
|
|
@ -35,7 +35,7 @@ namespace BAN
|
|||
constexpr T& front();
|
||||
|
||||
Span<T> span() { return Span(m_data, size()); }
|
||||
const Span<T> span() const { return Span(m_data, size()); }
|
||||
Span<const T> span() const { return Span(m_data, size()); }
|
||||
|
||||
constexpr size_type size() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,90 @@
|
|||
#pragma once
|
||||
|
||||
#include <BAN/Iteration.h>
|
||||
#include <BAN/Swap.h>
|
||||
#include <BAN/Traits.h>
|
||||
#include <cstddef>
|
||||
|
||||
namespace BAN
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<typename It, typename Comp>
|
||||
void heapify_up(It begin, size_t index, Comp comp)
|
||||
{
|
||||
size_t parent = (index - 1) / 2;
|
||||
while (parent < index)
|
||||
{
|
||||
if (comp(*(begin + index), *(begin + parent)))
|
||||
break;
|
||||
swap(*(begin + parent), *(begin + index));
|
||||
index = parent;
|
||||
parent = (index - 1) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename It, typename Comp>
|
||||
void heapify_down(It begin, size_t index, size_t len, Comp comp)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
const size_t lchild = 2 * index + 1;
|
||||
const size_t rchild = 2 * index + 2;
|
||||
|
||||
size_t child = 0;
|
||||
if (lchild < len && !comp(*(begin + lchild), *(begin + index)))
|
||||
{
|
||||
if (rchild < len && !comp(*(begin + rchild), *(begin + lchild)))
|
||||
child = rchild;
|
||||
else
|
||||
child = lchild;
|
||||
}
|
||||
else if (rchild < len && !comp(*(begin + rchild), *(begin + index)))
|
||||
child = rchild;
|
||||
else
|
||||
break;
|
||||
|
||||
swap(*(begin + child), *(begin + index));
|
||||
index = child;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
||||
void make_heap(It begin, It end, Comp comp = {})
|
||||
{
|
||||
const size_t len = distance(begin, end);
|
||||
if (len <= 1)
|
||||
return;
|
||||
|
||||
size_t index = (len - 2) / 2;
|
||||
while (index < len)
|
||||
detail::heapify_down(begin, index--, len, comp);
|
||||
}
|
||||
|
||||
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
||||
void push_heap(It begin, It end, Comp comp = {})
|
||||
{
|
||||
const size_t len = distance(begin, end);
|
||||
detail::heapify_up(begin, len - 1, comp);
|
||||
}
|
||||
|
||||
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
||||
void pop_heap(It begin, It end, Comp comp = {})
|
||||
{
|
||||
const size_t len = distance(begin, end);
|
||||
swap(*begin, *(begin + len - 1));
|
||||
detail::heapify_down(begin, 0, len - 1, comp);
|
||||
}
|
||||
|
||||
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
||||
void sort_heap(It begin, It end, Comp comp = {})
|
||||
{
|
||||
while (begin != end)
|
||||
pop_heap(begin, end--, comp);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
#pragma once
|
||||
|
||||
#include "BAN/Errors.h"
|
||||
#include <BAN/Vector.h>
|
||||
#include <BAN/Heap.h>
|
||||
|
||||
namespace BAN
|
||||
{
|
||||
|
||||
template<typename T, typename Comp = less<T>>
|
||||
class PriorityQueue
|
||||
{
|
||||
public:
|
||||
PriorityQueue() = default;
|
||||
PriorityQueue(Comp comp)
|
||||
: m_comp(comp)
|
||||
{ }
|
||||
|
||||
ErrorOr<void> push(const T& value)
|
||||
{
|
||||
TRY(m_data.push_back(value));
|
||||
push_heap(m_data.begin(), m_data.end());
|
||||
return {};
|
||||
}
|
||||
|
||||
ErrorOr<void> push(T&& value)
|
||||
{
|
||||
TRY(m_data.push_back(move(value)));
|
||||
push_heap(m_data.begin(), m_data.end());
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
ErrorOr<void> emplace(Args&&... args) requires is_constructible_v<T, Args...>
|
||||
{
|
||||
TRY(m_data.emplace_back(forward<Args>(args)...));
|
||||
push_heap(m_data.begin(), m_data.end());
|
||||
return {};
|
||||
}
|
||||
|
||||
void pop()
|
||||
{
|
||||
pop_heap(m_data.begin(), m_data.end());
|
||||
m_data.pop_back();
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> reserve(Vector<T>::size_type size)
|
||||
{
|
||||
return m_data.reserve(size);
|
||||
}
|
||||
|
||||
T& top() { return m_data.front(); }
|
||||
const T& top() const { return m_data.front(); }
|
||||
|
||||
bool empty() const { return m_data.empty(); }
|
||||
Vector<T>::size_type size() const { return m_data.size(); }
|
||||
Vector<T>::size_type capacity() const { return m_data.capacity(); }
|
||||
|
||||
private:
|
||||
Comp m_comp;
|
||||
Vector<T> m_data;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <BAN/Heap.h>
|
||||
#include <BAN/Math.h>
|
||||
#include <BAN/Swap.h>
|
||||
#include <BAN/Traits.h>
|
||||
|
|
@ -8,7 +9,7 @@
|
|||
namespace BAN::sort
|
||||
{
|
||||
|
||||
template<typename It, typename Comp = less<typename It::value_type>>
|
||||
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
||||
void exchange_sort(It begin, It end, Comp comp = {})
|
||||
{
|
||||
for (It lhs = begin; lhs != end; ++lhs)
|
||||
|
|
@ -42,7 +43,7 @@ namespace BAN::sort
|
|||
|
||||
}
|
||||
|
||||
template<typename It, typename Comp = less<typename It::value_type>>
|
||||
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
||||
void quick_sort(It begin, It end, Comp comp = {})
|
||||
{
|
||||
if (distance(begin, end) <= 1)
|
||||
|
|
@ -52,14 +53,14 @@ namespace BAN::sort
|
|||
quick_sort(++mid, end, comp);
|
||||
}
|
||||
|
||||
template<typename It, typename Comp = less<typename It::value_type>>
|
||||
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
||||
void insertion_sort(It begin, It end, Comp comp = {})
|
||||
{
|
||||
if (distance(begin, end) <= 1)
|
||||
return;
|
||||
for (It it1 = next(begin, 1); it1 != end; ++it1)
|
||||
{
|
||||
typename It::value_type x = move(*it1);
|
||||
auto x = move(*it1);
|
||||
It it2 = it1;
|
||||
for (; it2 != begin && comp(x, *prev(it2, 1)); --it2)
|
||||
*it2 = move(*prev(it2, 1));
|
||||
|
|
@ -67,83 +68,7 @@ namespace BAN::sort
|
|||
}
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<typename It, typename Comp>
|
||||
void push_heap(It begin, size_t hole_index, size_t top_index, typename It::value_type value, Comp comp)
|
||||
{
|
||||
size_t parent = (hole_index - 1) / 2;
|
||||
while (hole_index > top_index && comp(*next(begin, parent), value))
|
||||
{
|
||||
*next(begin, hole_index) = move(*next(begin, parent));
|
||||
hole_index = parent;
|
||||
parent = (hole_index - 1) / 2;
|
||||
}
|
||||
*next(begin, hole_index) = move(value);
|
||||
}
|
||||
|
||||
template<typename It, typename Comp>
|
||||
void adjust_heap(It begin, size_t hole_index, size_t len, typename It::value_type value, Comp comp)
|
||||
{
|
||||
const size_t top_index = hole_index;
|
||||
size_t child = hole_index;
|
||||
while (child < (len - 1) / 2)
|
||||
{
|
||||
child = 2 * (child + 1);
|
||||
if (comp(*next(begin, child), *next(begin, child - 1)))
|
||||
child--;
|
||||
*next(begin, hole_index) = move(*next(begin, child));
|
||||
hole_index = child;
|
||||
}
|
||||
if (len % 2 == 0 && child == (len - 2) / 2)
|
||||
{
|
||||
child = 2 * (child + 1);
|
||||
*next(begin, hole_index) = move(*next(begin, child - 1));
|
||||
hole_index = child - 1;
|
||||
}
|
||||
push_heap(begin, hole_index, top_index, move(value), comp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename It, typename Comp = less<typename It::value_type>>
|
||||
void make_heap(It begin, It end, Comp comp = {})
|
||||
{
|
||||
const size_t len = distance(begin, end);
|
||||
if (len <= 1)
|
||||
return;
|
||||
|
||||
size_t parent = (len - 2) / 2;
|
||||
while (true)
|
||||
{
|
||||
detail::adjust_heap(begin, parent, len, move(*next(begin, parent)), comp);
|
||||
|
||||
if (parent == 0)
|
||||
break;
|
||||
|
||||
parent--;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename It, typename Comp = less<typename It::value_type>>
|
||||
void sort_heap(It begin, It end, Comp comp = {})
|
||||
{
|
||||
const size_t len = distance(begin, end);
|
||||
if (len <= 1)
|
||||
return;
|
||||
|
||||
size_t last = len;
|
||||
while (last > 1)
|
||||
{
|
||||
last--;
|
||||
typename It::value_type x = move(*next(begin, last));
|
||||
*next(begin, last) = move(*begin);
|
||||
detail::adjust_heap(begin, 0, last, move(x), comp);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename It, typename Comp = less<typename It::value_type>>
|
||||
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
||||
void heap_sort(It begin, It end, Comp comp = {})
|
||||
{
|
||||
make_heap(begin, end, comp);
|
||||
|
|
@ -167,7 +92,7 @@ namespace BAN::sort
|
|||
|
||||
}
|
||||
|
||||
template<typename It, typename Comp = less<typename It::value_type>>
|
||||
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
||||
void intro_sort(It begin, It end, Comp comp = {})
|
||||
{
|
||||
const size_t len = distance(begin, end);
|
||||
|
|
@ -190,10 +115,10 @@ namespace BAN::sort
|
|||
}
|
||||
|
||||
template<typename It, size_t radix = 256>
|
||||
requires is_unsigned_v<typename It::value_type> && (radix > 0 && (radix & (radix - 1)) == 0)
|
||||
requires is_unsigned_v<it_value_type_t<It>> && (radix > 0 && (radix & (radix - 1)) == 0)
|
||||
BAN::ErrorOr<void> radix_sort(It begin, It end)
|
||||
{
|
||||
using value_type = typename It::value_type;
|
||||
using value_type = it_value_type_t<It>;
|
||||
|
||||
const size_t len = distance(begin, end);
|
||||
if (len <= 1)
|
||||
|
|
@ -231,7 +156,7 @@ namespace BAN::sort
|
|||
return {};
|
||||
}
|
||||
|
||||
template<typename It, typename Comp = less<typename It::value_type>>
|
||||
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
||||
void sort(It begin, It end, Comp comp = {})
|
||||
{
|
||||
return intro_sort(begin, end, comp);
|
||||
|
|
|
|||
|
|
@ -139,6 +139,10 @@ namespace BAN
|
|||
template<typename T> using make_signed_t = typename make_signed<T>::type;
|
||||
#undef __BAN_TRAITS_MAKE_SIGNED_CV
|
||||
|
||||
template<typename T> struct it_value_type { using value_type = T::value_type; };
|
||||
template<typename T> struct it_value_type<T*> { using value_type = T; };
|
||||
template<typename T> using it_value_type_t = typename it_value_type<T>::value_type;
|
||||
|
||||
template<typename T> struct less { constexpr bool operator()(const T& lhs, const T& rhs) const { return lhs < rhs; } };
|
||||
template<typename T> struct equal { constexpr bool operator()(const T& lhs, const T& rhs) const { return lhs == rhs; } };
|
||||
template<typename T> struct greater { constexpr bool operator()(const T& lhs, const T& rhs) const { return lhs > rhs; } };
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ namespace BAN
|
|||
bool contains(const T&) const;
|
||||
|
||||
Span<T> span() { return Span(m_data, m_size); }
|
||||
const Span<T> span() const { return Span(m_data, m_size); }
|
||||
Span<const T> span() const { return Span(m_data, m_size); }
|
||||
|
||||
const T& operator[](size_type) const;
|
||||
T& operator[](size_type);
|
||||
|
|
|
|||
|
|
@ -165,6 +165,12 @@ set(KLIBC_SOURCES
|
|||
../userspace/libraries/LibC/arch/${BANAN_ARCH}/string.S
|
||||
)
|
||||
|
||||
set(LIBDEFLATE_SOURCE
|
||||
../userspace/libraries/LibDEFLATE/Compressor.cpp
|
||||
../userspace/libraries/LibDEFLATE/Decompressor.cpp
|
||||
../userspace/libraries/LibDEFLATE/HuffmanTree.cpp
|
||||
)
|
||||
|
||||
set(LIBFONT_SOURCES
|
||||
../userspace/libraries/LibFont/Font.cpp
|
||||
../userspace/libraries/LibFont/PSF.cpp
|
||||
|
|
@ -175,18 +181,25 @@ set(LIBINPUT_SOURCE
|
|||
../userspace/libraries/LibInput/KeyEvent.cpp
|
||||
)
|
||||
|
||||
set(LIBQR_SOURCE
|
||||
../userspace/libraries/LibQR/QRCode.cpp
|
||||
)
|
||||
|
||||
set(KERNEL_SOURCES
|
||||
${KERNEL_SOURCES}
|
||||
${BAN_SOURCES}
|
||||
${KLIBC_SOURCES}
|
||||
${LIBDEFLATE_SOURCE}
|
||||
${LIBFONT_SOURCES}
|
||||
${LIBINPUT_SOURCE}
|
||||
${LIBQR_SOURCE}
|
||||
)
|
||||
|
||||
add_executable(kernel ${KERNEL_SOURCES})
|
||||
|
||||
target_compile_definitions(kernel PRIVATE __is_kernel)
|
||||
target_compile_definitions(kernel PRIVATE __arch=${BANAN_ARCH})
|
||||
target_compile_definitions(kernel PRIVATE LIBDEFLATE_AVOID_STACK=1)
|
||||
|
||||
target_compile_options(kernel PRIVATE
|
||||
-O2 -g
|
||||
|
|
@ -240,9 +253,11 @@ add_custom_command(
|
|||
|
||||
banan_include_headers(kernel ban)
|
||||
banan_include_headers(kernel libc)
|
||||
banan_include_headers(kernel libfont)
|
||||
banan_include_headers(kernel libdeflate)
|
||||
banan_include_headers(kernel libelf)
|
||||
banan_include_headers(kernel libfont)
|
||||
banan_include_headers(kernel libinput)
|
||||
banan_include_headers(kernel libqr)
|
||||
|
||||
banan_install_headers(kernel)
|
||||
set_target_properties(kernel PROPERTIES OUTPUT_NAME banan-os.kernel)
|
||||
|
|
|
|||
|
|
@ -2,15 +2,41 @@
|
|||
|
||||
// stack contains
|
||||
// return address
|
||||
// return stack
|
||||
// return rflags
|
||||
// siginfo_t
|
||||
// signal number
|
||||
// signal handler
|
||||
|
||||
.global signal_trampoline
|
||||
signal_trampoline:
|
||||
pusha
|
||||
pushl %esi // gregs
|
||||
pushl %edi
|
||||
pushl %edx
|
||||
pushl %ecx
|
||||
pushl %ebx
|
||||
pushl %eax
|
||||
pushl %ebp
|
||||
|
||||
movl 40(%esp), %edi
|
||||
movl 36(%esp), %eax
|
||||
movl 76(%esp), %eax // return sp
|
||||
addl $4, %eax // return address
|
||||
movl 80(%esp), %ebx // return ip
|
||||
pushl %eax;
|
||||
pushl %ebx
|
||||
|
||||
// FIXME: populate these
|
||||
xorl %eax, %eax
|
||||
pushl %eax // stack
|
||||
pushl %eax
|
||||
pushl %eax
|
||||
pushl %eax // sigset
|
||||
pushl %eax
|
||||
pushl %eax // link
|
||||
|
||||
movl %esp, %edx // ucontext
|
||||
leal 68(%esp), %esi // siginfo
|
||||
movl 64(%esp), %edi // signal number
|
||||
movl 60(%esp), %eax // handlers
|
||||
|
||||
// align stack to 16 bytes
|
||||
movl %esp, %ebp
|
||||
|
|
@ -19,7 +45,9 @@ signal_trampoline:
|
|||
subl $512, %esp
|
||||
fxsave (%esp)
|
||||
|
||||
subl $12, %esp
|
||||
subl $4, %esp
|
||||
pushl %edx
|
||||
pushl %esi
|
||||
pushl %edi
|
||||
call *%eax
|
||||
addl $16, %esp
|
||||
|
|
@ -29,9 +57,21 @@ signal_trampoline:
|
|||
|
||||
// restore stack
|
||||
movl %ebp, %esp
|
||||
popa
|
||||
addl $32, %esp
|
||||
|
||||
addl $8, %esp
|
||||
// restore registers
|
||||
popl %ebp
|
||||
popl %eax
|
||||
popl %ebx
|
||||
popl %ecx
|
||||
popl %edx
|
||||
popl %edi
|
||||
popl %esi
|
||||
|
||||
// skip handler, number, siginfo_t
|
||||
addl $44, %esp
|
||||
|
||||
// restore flags
|
||||
popf
|
||||
|
||||
movl (%esp), %esp
|
||||
|
|
|
|||
|
|
@ -1,12 +1,6 @@
|
|||
// arguments in EAX, EBX, ECX, EDX, ESI, EDI
|
||||
.global asm_syscall_handler
|
||||
asm_syscall_handler:
|
||||
# save segment registers
|
||||
pushw %ds
|
||||
pushw %es
|
||||
pushw %fs
|
||||
pushw %gs
|
||||
|
||||
# save general purpose registers
|
||||
pushl %ebx
|
||||
pushl %ecx
|
||||
|
|
@ -18,13 +12,12 @@ asm_syscall_handler:
|
|||
|
||||
# align stack
|
||||
movl %esp, %ebp
|
||||
subl $15, %esp
|
||||
andl $0xFFFFFFF0, %esp
|
||||
andl $-16, %esp
|
||||
|
||||
# push arguments
|
||||
subl $4, %esp
|
||||
pushl %ebp
|
||||
addl $32, (%esp)
|
||||
addl $24, (%esp)
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
pushl %edx
|
||||
|
|
@ -44,6 +37,15 @@ asm_syscall_handler:
|
|||
|
||||
movl %ebp, %esp
|
||||
|
||||
# restore userspace segments
|
||||
movw $(0x20 | 3), %bx
|
||||
movw %bx, %ds
|
||||
movw %bx, %es
|
||||
movw $(0x30 | 3), %bx
|
||||
movw %bx, %fs
|
||||
movw $(0x38 | 3), %bx
|
||||
movw %bx, %gs
|
||||
|
||||
# restore general purpose registers
|
||||
popl %ebp
|
||||
popl %esi
|
||||
|
|
@ -52,12 +54,6 @@ asm_syscall_handler:
|
|||
popl %ecx
|
||||
popl %ebx
|
||||
|
||||
# restore segment registers
|
||||
popw %gs
|
||||
popw %fs
|
||||
popw %es
|
||||
popw %ds
|
||||
|
||||
iret
|
||||
|
||||
.global sys_fork_trampoline
|
||||
|
|
|
|||
|
|
@ -31,8 +31,6 @@ start_kernel_thread:
|
|||
subl $12, %esp
|
||||
pushl %edi
|
||||
call *%esi
|
||||
addl $16, %esp
|
||||
|
||||
|
||||
.global start_userspace_thread
|
||||
start_userspace_thread:
|
||||
|
|
@ -41,15 +39,12 @@ start_userspace_thread:
|
|||
call get_thread_start_sp
|
||||
movl %eax, %esp
|
||||
|
||||
# ds, es = user data
|
||||
movw $(0x20 | 3), %bx
|
||||
movw %bx, %ds
|
||||
movw %bx, %es
|
||||
# gs = thread local
|
||||
movw $(0x30 | 3), %bx
|
||||
movw %bx, %gs
|
||||
# fs = 0
|
||||
xorw %bx, %bx
|
||||
movw %bx, %fs
|
||||
movw $(0x38 | 3), %bx
|
||||
movw %bx, %gs
|
||||
|
||||
iret
|
||||
|
|
|
|||
|
|
@ -1,12 +1,7 @@
|
|||
.macro push_userspace
|
||||
pushw %gs
|
||||
pushw %fs
|
||||
pushw %es
|
||||
pushw %ds
|
||||
pushal
|
||||
.endm
|
||||
.macro maybe_load_kernel_segments, n
|
||||
cmpb $0x08, \n(%esp)
|
||||
je 1f
|
||||
|
||||
.macro load_kernel_segments
|
||||
movw $0x10, %ax
|
||||
movw %ax, %ds
|
||||
movw %ax, %es
|
||||
|
|
@ -14,19 +9,26 @@
|
|||
|
||||
movw $0x28, %ax
|
||||
movw %ax, %gs
|
||||
1:
|
||||
.endm
|
||||
|
||||
.macro pop_userspace
|
||||
popal
|
||||
popw %ds
|
||||
popw %es
|
||||
popw %fs
|
||||
popw %gs
|
||||
.macro maybe_load_userspace_segments, n
|
||||
cmpb $0x08, \n(%esp)
|
||||
je 1f
|
||||
|
||||
movw $(0x20 | 3), %bx
|
||||
movw %bx, %ds
|
||||
movw %bx, %es
|
||||
movw $(0x30 | 3), %bx
|
||||
movw %bx, %fs
|
||||
movw $(0x38 | 3), %bx
|
||||
movw %bx, %gs
|
||||
1:
|
||||
.endm
|
||||
|
||||
isr_stub:
|
||||
push_userspace
|
||||
load_kernel_segments
|
||||
pushal
|
||||
maybe_load_kernel_segments 44
|
||||
cld
|
||||
|
||||
movl %cr0, %eax; pushl %eax
|
||||
|
|
@ -34,33 +36,39 @@ isr_stub:
|
|||
movl %cr3, %eax; pushl %eax
|
||||
movl %cr4, %eax; pushl %eax
|
||||
|
||||
movl %esp, %eax // register ptr
|
||||
leal 64(%esp), %ebx // interrupt stack ptr
|
||||
movl 60(%esp), %ecx // error code
|
||||
movl 56(%esp), %edx // isr number
|
||||
movl 48(%esp), %edi // isr number
|
||||
movl 52(%esp), %esi // error code
|
||||
leal 56(%esp), %edx // interrupt stack ptr
|
||||
movl %esp, %ecx // register ptr
|
||||
|
||||
# stack frame for stack trace
|
||||
leal 56(%esp), %eax
|
||||
pushl (%eax)
|
||||
pushl %ebp
|
||||
|
||||
movl %esp, %ebp
|
||||
andl $-16, %esp
|
||||
|
||||
pushl %eax
|
||||
pushl %ebx
|
||||
pushl %ecx
|
||||
pushl %edx
|
||||
pushl %esi
|
||||
pushl %edi
|
||||
call cpp_isr_handler
|
||||
|
||||
movl %ebp, %esp
|
||||
addl $16, %esp
|
||||
addl $24, %esp
|
||||
|
||||
pop_userspace
|
||||
maybe_load_userspace_segments 44
|
||||
popal
|
||||
addl $8, %esp
|
||||
iret
|
||||
|
||||
irq_stub:
|
||||
push_userspace
|
||||
load_kernel_segments
|
||||
pushal
|
||||
maybe_load_kernel_segments 44
|
||||
cld
|
||||
|
||||
movl 40(%esp), %edi # interrupt number
|
||||
movl 32(%esp), %edi # interrupt number
|
||||
|
||||
movl %esp, %ebp
|
||||
andl $-16, %esp
|
||||
|
|
@ -71,7 +79,8 @@ irq_stub:
|
|||
|
||||
movl %ebp, %esp
|
||||
|
||||
pop_userspace
|
||||
maybe_load_userspace_segments 44
|
||||
popal
|
||||
addl $8, %esp
|
||||
iret
|
||||
|
||||
|
|
@ -99,8 +108,8 @@ asm_yield_handler:
|
|||
|
||||
.global asm_ipi_handler
|
||||
asm_ipi_handler:
|
||||
push_userspace
|
||||
load_kernel_segments
|
||||
pushal
|
||||
maybe_load_kernel_segments 36
|
||||
cld
|
||||
|
||||
movl %esp, %ebp
|
||||
|
|
@ -110,13 +119,14 @@ asm_ipi_handler:
|
|||
|
||||
movl %ebp, %esp
|
||||
|
||||
pop_userspace
|
||||
maybe_load_userspace_segments 36
|
||||
popal
|
||||
iret
|
||||
|
||||
.global asm_timer_handler
|
||||
asm_timer_handler:
|
||||
push_userspace
|
||||
load_kernel_segments
|
||||
pushal
|
||||
maybe_load_kernel_segments 36
|
||||
cld
|
||||
|
||||
movl %esp, %ebp
|
||||
|
|
@ -126,7 +136,8 @@ asm_timer_handler:
|
|||
|
||||
movl %ebp, %esp
|
||||
|
||||
pop_userspace
|
||||
maybe_load_userspace_segments 36
|
||||
popal
|
||||
iret
|
||||
|
||||
.macro isr n
|
||||
|
|
|
|||
|
|
@ -2,29 +2,48 @@
|
|||
|
||||
// stack contains
|
||||
// return address
|
||||
// return stack
|
||||
// return rflags
|
||||
// siginfo_t
|
||||
// signal number
|
||||
// signal handler
|
||||
|
||||
.global signal_trampoline
|
||||
signal_trampoline:
|
||||
pushq %rax
|
||||
pushq %rbx
|
||||
pushq %rcx
|
||||
pushq %rdx
|
||||
pushq %rbp
|
||||
pushq %rdi
|
||||
pushq %rsi
|
||||
pushq %r8
|
||||
pushq %r9
|
||||
pushq %r10
|
||||
pushq %r11
|
||||
pushq %r12
|
||||
pushq %r13
|
||||
pushq %r15 // gregs
|
||||
pushq %r14
|
||||
pushq %r15
|
||||
pushq %r13
|
||||
pushq %r12
|
||||
pushq %r11
|
||||
pushq %r10
|
||||
pushq %r9
|
||||
pushq %r8
|
||||
pushq %rsi
|
||||
pushq %rdi
|
||||
pushq %rdx
|
||||
pushq %rcx
|
||||
pushq %rbx
|
||||
pushq %rax
|
||||
pushq %rbp
|
||||
|
||||
movq 128(%rsp), %rdi
|
||||
movq 120(%rsp), %rax
|
||||
movq 200(%rsp), %rax // return sp
|
||||
addq $(128 + 8), %rax // red-zone and return address
|
||||
movq 208(%rsp), %rbx // return ip
|
||||
pushq %rax;
|
||||
pushq %rbx
|
||||
|
||||
// FIXME: populate these
|
||||
xorq %rax, %rax
|
||||
pushq %rax // stack
|
||||
pushq %rax
|
||||
pushq %rax
|
||||
pushq %rax // sigset
|
||||
pushq %rax // link
|
||||
|
||||
movq %rsp, %rdx // ucontext
|
||||
leaq 192(%rsp), %rsi // siginfo
|
||||
movq 184(%rsp), %rdi // signal number
|
||||
movq 176(%rsp), %rax // handler
|
||||
|
||||
// align stack to 16 bytes
|
||||
movq %rsp, %rbp
|
||||
|
|
@ -40,26 +59,32 @@ signal_trampoline:
|
|||
|
||||
// restore stack
|
||||
movq %rbp, %rsp
|
||||
popq %r15
|
||||
popq %r14
|
||||
popq %r13
|
||||
popq %r12
|
||||
popq %r11
|
||||
popq %r10
|
||||
popq %r9
|
||||
popq %r8
|
||||
popq %rsi
|
||||
popq %rdi
|
||||
popq %rbp
|
||||
popq %rdx
|
||||
popq %rcx
|
||||
popq %rbx
|
||||
popq %rax
|
||||
addq $56, %rsp
|
||||
|
||||
addq $16, %rsp
|
||||
// restore registers
|
||||
popq %rbp
|
||||
popq %rax
|
||||
popq %rbx
|
||||
popq %rcx
|
||||
popq %rdx
|
||||
popq %rdi
|
||||
popq %rsi
|
||||
popq %r8
|
||||
popq %r9
|
||||
popq %r10
|
||||
popq %r11
|
||||
popq %r12
|
||||
popq %r13
|
||||
popq %r14
|
||||
popq %r15
|
||||
|
||||
// skip handler, number, siginfo_t
|
||||
addq $72, %rsp
|
||||
|
||||
// restore flags
|
||||
popfq
|
||||
|
||||
movq (%rsp), %rsp
|
||||
|
||||
// return over red-zone
|
||||
// return over red-zone and siginfo_t
|
||||
ret $128
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// System V ABI: RDI, RSI, RDX, RCX, R8, R9
|
||||
.global asm_syscall_handler
|
||||
asm_syscall_handler:
|
||||
swapgs
|
||||
pushq %rbx
|
||||
pushq %rcx
|
||||
pushq %rdx
|
||||
|
|
@ -42,9 +43,9 @@ asm_syscall_handler:
|
|||
popq %rdx
|
||||
popq %rcx
|
||||
popq %rbx
|
||||
swapgs
|
||||
iretq
|
||||
|
||||
|
||||
.global sys_fork_trampoline
|
||||
sys_fork_trampoline:
|
||||
pushq %rbx
|
||||
|
|
|
|||
|
|
@ -32,4 +32,6 @@ start_userspace_thread:
|
|||
call get_thread_start_sp
|
||||
movq %rax, %rsp
|
||||
|
||||
swapgs
|
||||
|
||||
iretq
|
||||
|
|
|
|||
|
|
@ -1,4 +1,12 @@
|
|||
.macro pushaq
|
||||
.macro swapgs_if_necessary, n
|
||||
cmpb $0x08, \n(%rsp)
|
||||
je 1f
|
||||
swapgs
|
||||
1:
|
||||
.endm
|
||||
|
||||
.macro pushaq, n
|
||||
swapgs_if_necessary \n
|
||||
pushq %rax
|
||||
pushq %rcx
|
||||
pushq %rdx
|
||||
|
|
@ -16,7 +24,7 @@
|
|||
pushq %r15
|
||||
.endm
|
||||
|
||||
.macro popaq
|
||||
.macro popaq, n
|
||||
popq %r15
|
||||
popq %r14
|
||||
popq %r13
|
||||
|
|
@ -32,10 +40,11 @@
|
|||
popq %rdx
|
||||
popq %rcx
|
||||
popq %rax
|
||||
swapgs_if_necessary \n
|
||||
.endm
|
||||
|
||||
isr_stub:
|
||||
pushaq
|
||||
pushaq 24
|
||||
cld
|
||||
movq %cr0, %rax; pushq %rax
|
||||
movq %cr2, %rax; pushq %rax
|
||||
|
|
@ -49,43 +58,43 @@ isr_stub:
|
|||
call cpp_isr_handler
|
||||
addq $32, %rsp
|
||||
|
||||
popaq
|
||||
popaq 24
|
||||
addq $16, %rsp
|
||||
iretq
|
||||
|
||||
irq_stub:
|
||||
pushaq
|
||||
pushaq 24
|
||||
cld
|
||||
movq 120(%rsp), %rdi # irq number
|
||||
call cpp_irq_handler
|
||||
popaq
|
||||
popaq 24
|
||||
addq $16, %rsp
|
||||
iretq
|
||||
|
||||
.global asm_yield_handler
|
||||
asm_yield_handler:
|
||||
pushaq
|
||||
pushaq 8
|
||||
cld
|
||||
leaq 120(%rsp), %rdi # interrupt stack ptr
|
||||
movq %rsp, %rsi # interrupt register ptr
|
||||
call cpp_yield_handler
|
||||
popaq
|
||||
popaq 8
|
||||
iretq
|
||||
|
||||
.global asm_ipi_handler
|
||||
asm_ipi_handler:
|
||||
pushaq
|
||||
pushaq 8
|
||||
cld
|
||||
call cpp_ipi_handler
|
||||
popaq
|
||||
popaq 8
|
||||
iretq
|
||||
|
||||
.global asm_timer_handler
|
||||
asm_timer_handler:
|
||||
pushaq
|
||||
pushaq 8
|
||||
cld
|
||||
call cpp_timer_handler
|
||||
popaq
|
||||
popaq 8
|
||||
iretq
|
||||
|
||||
.macro isr n
|
||||
|
|
|
|||
|
|
@ -74,6 +74,8 @@
|
|||
namespace Debug
|
||||
{
|
||||
void dump_stack_trace();
|
||||
void dump_qr_code();
|
||||
|
||||
void putchar(char);
|
||||
void print_prefix(const char*, int);
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ namespace Kernel
|
|||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<FramebufferDevice>> create_from_boot_framebuffer();
|
||||
static BAN::RefPtr<FramebufferDevice> boot_framebuffer();
|
||||
~FramebufferDevice();
|
||||
|
||||
uint32_t width() const { return m_width; }
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ namespace Kernel
|
|||
virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) override;
|
||||
virtual BAN::ErrorOr<void> create_directory_impl(BAN::StringView, mode_t, uid_t, gid_t) override;
|
||||
virtual BAN::ErrorOr<void> link_inode_impl(BAN::StringView, BAN::RefPtr<Inode>) override;
|
||||
virtual BAN::ErrorOr<void> rename_inode_impl(BAN::RefPtr<Inode>, BAN::StringView, BAN::StringView) override;
|
||||
virtual BAN::ErrorOr<void> unlink_impl(BAN::StringView) override;
|
||||
|
||||
virtual BAN::ErrorOr<BAN::String> link_target_impl() override;
|
||||
|
|
@ -64,6 +65,7 @@ namespace Kernel
|
|||
BAN::ErrorOr<BAN::Optional<uint32_t>> fs_block_of_data_block_index(uint32_t data_block_index);
|
||||
|
||||
BAN::ErrorOr<void> link_inode_to_directory(Ext2Inode&, BAN::StringView name);
|
||||
BAN::ErrorOr<void> remove_inode_from_directory(BAN::StringView name, bool cleanup_directory);
|
||||
BAN::ErrorOr<bool> is_directory_empty();
|
||||
|
||||
BAN::ErrorOr<void> cleanup_indirect_block(uint32_t block, uint32_t depth);
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@ namespace Kernel
|
|||
BAN::ErrorOr<void> create_file(BAN::StringView, mode_t, uid_t, gid_t);
|
||||
BAN::ErrorOr<void> create_directory(BAN::StringView, mode_t, uid_t, gid_t);
|
||||
BAN::ErrorOr<void> link_inode(BAN::StringView, BAN::RefPtr<Inode>);
|
||||
BAN::ErrorOr<void> rename_inode(BAN::RefPtr<Inode>, BAN::StringView, BAN::StringView);
|
||||
BAN::ErrorOr<void> unlink(BAN::StringView);
|
||||
|
||||
// Link API
|
||||
|
|
@ -108,8 +109,8 @@ namespace Kernel
|
|||
BAN::ErrorOr<void> bind(const sockaddr* address, socklen_t address_len);
|
||||
BAN::ErrorOr<void> connect(const sockaddr* address, socklen_t address_len);
|
||||
BAN::ErrorOr<void> listen(int backlog);
|
||||
BAN::ErrorOr<size_t> sendto(BAN::ConstByteSpan message, const sockaddr* address, socklen_t address_len);
|
||||
BAN::ErrorOr<size_t> recvfrom(BAN::ByteSpan buffer, sockaddr* address, socklen_t* address_len);
|
||||
BAN::ErrorOr<size_t> sendmsg(const msghdr& message, int flags);
|
||||
BAN::ErrorOr<size_t> recvmsg(msghdr& message, int flags);
|
||||
BAN::ErrorOr<void> getsockname(sockaddr* address, socklen_t* address_len);
|
||||
BAN::ErrorOr<void> getpeername(sockaddr* address, socklen_t* address_len);
|
||||
|
||||
|
|
@ -144,6 +145,7 @@ namespace Kernel
|
|||
virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> create_directory_impl(BAN::StringView, mode_t, uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> link_inode_impl(BAN::StringView, BAN::RefPtr<Inode>) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> rename_inode_impl(BAN::RefPtr<Inode>, BAN::StringView, BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> unlink_impl(BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
|
||||
// Link API
|
||||
|
|
@ -155,8 +157,8 @@ namespace Kernel
|
|||
virtual BAN::ErrorOr<void> connect_impl(const sockaddr*, socklen_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> listen_impl(int) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> bind_impl(const sockaddr*, socklen_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<size_t> sendto_impl(BAN::ConstByteSpan, const sockaddr*, socklen_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<size_t> recvfrom_impl(BAN::ByteSpan, sockaddr*, socklen_t*) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<size_t> recvmsg_impl(msghdr&, int) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<size_t> sendmsg_impl(const msghdr&, int) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> getsockname_impl(sockaddr*, socklen_t*) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
|
||||
|
|
@ -187,7 +189,7 @@ namespace Kernel
|
|||
friend class Epoll;
|
||||
friend class FileBackedRegion;
|
||||
friend class OpenFileDescriptorSet;
|
||||
friend class SharedFileData;
|
||||
friend struct SharedFileData;
|
||||
friend class TTY;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -69,10 +69,6 @@ namespace Kernel
|
|||
protected:
|
||||
virtual BAN::ErrorOr<BAN::String> link_target_impl() override;
|
||||
|
||||
// You may not write here and this is always non blocking
|
||||
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override { return BAN::Error::from_errno(EINVAL); }
|
||||
virtual BAN::ErrorOr<void> truncate_impl(size_t) override { return BAN::Error::from_errno(EINVAL); }
|
||||
|
||||
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; }
|
||||
|
|
@ -114,27 +110,54 @@ namespace Kernel
|
|||
class ProcSymlinkInode final : public TmpInode
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<ProcSymlinkInode>> create_new(BAN::ErrorOr<BAN::String> (*)(void*), void* data, TmpFileSystem&, mode_t, uid_t, gid_t);
|
||||
~ProcSymlinkInode() = default;
|
||||
static BAN::ErrorOr<BAN::RefPtr<ProcSymlinkInode>> create_new(BAN::ErrorOr<BAN::String> (*)(void*), void (*)(void*), void* data, TmpFileSystem&, mode_t, uid_t, gid_t);
|
||||
~ProcSymlinkInode();
|
||||
|
||||
protected:
|
||||
virtual BAN::ErrorOr<BAN::String> link_target_impl() override;
|
||||
|
||||
// You may not write here and this is always non blocking
|
||||
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override { return BAN::Error::from_errno(EINVAL); }
|
||||
virtual BAN::ErrorOr<void> truncate_impl(size_t) override { return BAN::Error::from_errno(EINVAL); }
|
||||
|
||||
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:
|
||||
ProcSymlinkInode(BAN::ErrorOr<BAN::String> (*callback)(void*), void* data, TmpFileSystem&, const TmpInodeInfo&);
|
||||
ProcSymlinkInode(BAN::ErrorOr<BAN::String> (*callback)(void*), void (*destructor)(void*), void* data, TmpFileSystem&, const TmpInodeInfo&);
|
||||
|
||||
private:
|
||||
BAN::ErrorOr<BAN::String> (*m_callback)(void*);
|
||||
void (*m_destructor)(void*);
|
||||
void* m_data;
|
||||
};
|
||||
|
||||
class ProcFDDirectoryInode final : public TmpInode
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<ProcFDDirectoryInode>> create_new(Process&, TmpFileSystem&, mode_t);
|
||||
~ProcFDDirectoryInode() = default;
|
||||
|
||||
virtual uid_t uid() const override { return m_process.credentials().ruid(); }
|
||||
virtual gid_t gid() const override { return m_process.credentials().rgid(); }
|
||||
|
||||
protected:
|
||||
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_impl(BAN::StringView) override;
|
||||
virtual BAN::ErrorOr<size_t> list_next_inodes_impl(off_t, struct dirent*, size_t) override;
|
||||
virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) override { return BAN::Error::from_errno(EPERM); }
|
||||
virtual BAN::ErrorOr<void> create_directory_impl(BAN::StringView, mode_t, uid_t, gid_t) override { return BAN::Error::from_errno(EPERM); }
|
||||
virtual BAN::ErrorOr<void> link_inode_impl(BAN::StringView, BAN::RefPtr<Inode>) override { return BAN::Error::from_errno(EPERM); }
|
||||
virtual BAN::ErrorOr<void> rename_inode_impl(BAN::RefPtr<Inode>, BAN::StringView, BAN::StringView) override { return BAN::Error::from_errno(EPERM); }
|
||||
virtual BAN::ErrorOr<void> unlink_impl(BAN::StringView) override { return BAN::Error::from_errno(EPERM); }
|
||||
|
||||
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:
|
||||
ProcFDDirectoryInode(Process&, TmpFileSystem&, const TmpInodeInfo&);
|
||||
|
||||
private:
|
||||
Process& m_process;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,8 +51,6 @@ namespace Kernel
|
|||
: m_info(info)
|
||||
{}
|
||||
|
||||
BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan buffer) override { return recvfrom_impl(buffer, nullptr, nullptr); }
|
||||
BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan buffer) override { return sendto_impl(buffer, nullptr, 0); }
|
||||
BAN::ErrorOr<void> fsync_impl() final override { return {}; }
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -157,6 +157,7 @@ namespace Kernel
|
|||
virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) override final;
|
||||
virtual BAN::ErrorOr<void> create_directory_impl(BAN::StringView, mode_t, uid_t, gid_t) override final;
|
||||
virtual BAN::ErrorOr<void> link_inode_impl(BAN::StringView, BAN::RefPtr<Inode>) override final;
|
||||
virtual BAN::ErrorOr<void> rename_inode_impl(BAN::RefPtr<Inode>, BAN::StringView, BAN::StringView) override final;
|
||||
virtual BAN::ErrorOr<void> unlink_impl(BAN::StringView) override;
|
||||
|
||||
virtual bool can_read_impl() const override { return false; }
|
||||
|
|
@ -168,6 +169,8 @@ namespace Kernel
|
|||
template<TmpFuncs::for_each_valid_entry_callback F>
|
||||
void for_each_valid_entry(F callback);
|
||||
|
||||
BAN::ErrorOr<void> unlink_inode(BAN::StringView, bool cleanup);
|
||||
|
||||
friend class TmpInode;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -129,7 +129,8 @@ namespace Kernel
|
|||
}
|
||||
|
||||
#if ARCH(i686)
|
||||
void set_tls(uintptr_t addr);
|
||||
void set_fsbase(uintptr_t addr);
|
||||
void set_gsbase(uintptr_t addr);
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
|
@ -153,8 +154,8 @@ namespace Kernel
|
|||
BAN::Array<SegmentDescriptor, 7> m_gdt; // null, kernel code, kernel data, user code, user data, tss low, tss high
|
||||
static constexpr uint16_t m_tss_offset = 0x28;
|
||||
#elif ARCH(i686)
|
||||
BAN::Array<SegmentDescriptor, 8> m_gdt; // null, kernel code, kernel data, user code, user data, processor data, tls, tss
|
||||
static constexpr uint16_t m_tss_offset = 0x38;
|
||||
BAN::Array<SegmentDescriptor, 9> m_gdt; // null, kernel code, kernel data, user code, user data, processor data, fsbase, gsbase, tss
|
||||
static constexpr uint16_t m_tss_offset = 0x40;
|
||||
#endif
|
||||
TaskStateSegment m_tss;
|
||||
const GDTR m_gdtr {
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ namespace Kernel
|
|||
BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override;
|
||||
|
||||
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
|
||||
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> split(size_t offset) override;
|
||||
|
||||
protected:
|
||||
BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override;
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ namespace Kernel
|
|||
~MemoryBackedRegion();
|
||||
|
||||
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
|
||||
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> split(size_t offset) override;
|
||||
|
||||
BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override { return {}; }
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ namespace Kernel
|
|||
bool contains(vaddr_t address) const;
|
||||
bool contains_fully(vaddr_t address, size_t size) const;
|
||||
bool overlaps(vaddr_t address, size_t size) const;
|
||||
bool is_contained_by(vaddr_t address, size_t size) const;
|
||||
|
||||
bool writable() const { return m_flags & PageTable::Flags::ReadWrite; }
|
||||
|
||||
|
|
@ -59,6 +60,7 @@ namespace Kernel
|
|||
BAN::ErrorOr<bool> allocate_page_containing(vaddr_t address, bool wants_write);
|
||||
|
||||
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) = 0;
|
||||
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> split(size_t offset) = 0;
|
||||
|
||||
protected:
|
||||
MemoryRegion(PageTable&, size_t size, Type type, PageTable::flags_t flags, int status_flags);
|
||||
|
|
@ -68,7 +70,7 @@ namespace Kernel
|
|||
|
||||
protected:
|
||||
PageTable& m_page_table;
|
||||
const size_t m_size;
|
||||
size_t m_size { 0 };
|
||||
const Type m_type;
|
||||
PageTable::flags_t m_flags;
|
||||
const int m_status_flags;
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ namespace Kernel
|
|||
static BAN::ErrorOr<BAN::UniqPtr<SharedMemoryObject>> create(BAN::RefPtr<SharedMemoryObjectManager::Object>, PageTable&, AddressRange);
|
||||
|
||||
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
|
||||
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> split(size_t offset) override;
|
||||
|
||||
BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override { return {}; }
|
||||
|
||||
|
|
|
|||
|
|
@ -60,8 +60,8 @@ namespace Kernel
|
|||
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> sendto_impl(BAN::ConstByteSpan, const sockaddr*, socklen_t) override;
|
||||
virtual BAN::ErrorOr<size_t> recvfrom_impl(BAN::ByteSpan, 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<long> ioctl_impl(int, void*) override;
|
||||
|
|
|
|||
|
|
@ -33,9 +33,10 @@ namespace Kernel
|
|||
protected:
|
||||
virtual void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len) 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> sendto_impl(BAN::ConstByteSpan message, const sockaddr* address, socklen_t address_len) override;
|
||||
virtual BAN::ErrorOr<size_t> recvfrom_impl(BAN::ByteSpan buffer, 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<long> ioctl_impl(int, void*) override;
|
||||
|
|
@ -63,6 +64,9 @@ namespace Kernel
|
|||
SpinLock m_packet_lock;
|
||||
ThreadBlocker m_packet_thread_blocker;
|
||||
|
||||
sockaddr_storage m_peer_address {};
|
||||
socklen_t m_peer_address_len { 0 };
|
||||
|
||||
friend class BAN::RefPtr<UDPSocket>;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include <kernel/FS/TmpFS/Inode.h>
|
||||
#include <kernel/FS/VirtualFileSystem.h>
|
||||
#include <kernel/Lock/SpinLock.h>
|
||||
#include <kernel/OpenFileDescriptorSet.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
|
@ -16,6 +17,9 @@ namespace Kernel
|
|||
BAN_NON_COPYABLE(UnixDomainSocket);
|
||||
BAN_NON_MOVABLE(UnixDomainSocket);
|
||||
|
||||
public:
|
||||
using FDWrapper = OpenFileDescriptorSet::FDWrapper;
|
||||
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<UnixDomainSocket>> create(Socket::Type, const Socket::Info&);
|
||||
BAN::ErrorOr<void> make_socket_pair(UnixDomainSocket&);
|
||||
|
|
@ -25,8 +29,8 @@ namespace Kernel
|
|||
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> sendto_impl(BAN::ConstByteSpan, const sockaddr*, socklen_t) override;
|
||||
virtual BAN::ErrorOr<size_t> recvfrom_impl(BAN::ByteSpan, 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 bool can_read_impl() const override;
|
||||
|
|
@ -38,8 +42,6 @@ namespace Kernel
|
|||
UnixDomainSocket(Socket::Type, const Socket::Info&);
|
||||
~UnixDomainSocket();
|
||||
|
||||
BAN::ErrorOr<void> add_packet(BAN::ConstByteSpan);
|
||||
|
||||
bool is_bound() const { return !m_bound_file.canonical_path.empty(); }
|
||||
bool is_bound_to_unused() const { return !m_bound_file.inode; }
|
||||
|
||||
|
|
@ -54,7 +56,7 @@ namespace Kernel
|
|||
BAN::WeakPtr<UnixDomainSocket> connection;
|
||||
BAN::Queue<BAN::RefPtr<UnixDomainSocket>> pending_connections;
|
||||
ThreadBlocker pending_thread_blocker;
|
||||
SpinLock pending_lock;
|
||||
Mutex pending_lock;
|
||||
};
|
||||
|
||||
struct ConnectionlessInfo
|
||||
|
|
@ -62,16 +64,25 @@ namespace Kernel
|
|||
BAN::String peer_address;
|
||||
};
|
||||
|
||||
struct PacketInfo
|
||||
{
|
||||
size_t size;
|
||||
BAN::Vector<FDWrapper> fds;
|
||||
BAN::Optional<struct ucred> ucred;
|
||||
};
|
||||
|
||||
BAN::ErrorOr<void> add_packet(const msghdr&, PacketInfo&&);
|
||||
|
||||
private:
|
||||
const Socket::Type m_socket_type;
|
||||
VirtualFileSystem::File m_bound_file;
|
||||
|
||||
BAN::Variant<ConnectionInfo, ConnectionlessInfo> m_info;
|
||||
|
||||
BAN::CircularQueue<size_t, 128> m_packet_sizes;
|
||||
BAN::CircularQueue<PacketInfo, 512> m_packet_infos;
|
||||
size_t m_packet_size_total { 0 };
|
||||
BAN::UniqPtr<VirtualRange> m_packet_buffer;
|
||||
SpinLock m_packet_lock;
|
||||
Mutex m_packet_lock;
|
||||
ThreadBlocker m_packet_thread_blocker;
|
||||
|
||||
friend class BAN::RefPtr<UnixDomainSocket>;
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ namespace Kernel
|
|||
|
||||
BAN::ErrorOr<int> dup2(int, int);
|
||||
|
||||
BAN::ErrorOr<int> fcntl(int fd, int cmd, int extra);
|
||||
BAN::ErrorOr<int> fcntl(int fd, int cmd, uintptr_t extra);
|
||||
|
||||
BAN::ErrorOr<off_t> seek(int fd, off_t offset, int whence);
|
||||
BAN::ErrorOr<off_t> tell(int) const;
|
||||
|
|
@ -51,8 +51,8 @@ namespace Kernel
|
|||
|
||||
BAN::ErrorOr<size_t> read_dir_entries(int fd, struct dirent* list, size_t list_len);
|
||||
|
||||
BAN::ErrorOr<size_t> recvfrom(int fd, BAN::ByteSpan buffer, sockaddr* address, socklen_t* address_len);
|
||||
BAN::ErrorOr<size_t> sendto(int fd, BAN::ConstByteSpan buffer, const sockaddr* address, socklen_t address_len);
|
||||
BAN::ErrorOr<size_t> recvmsg(int socket, msghdr& message, int flags);
|
||||
BAN::ErrorOr<size_t> sendmsg(int socket, const msghdr& message, int flags);
|
||||
|
||||
BAN::ErrorOr<VirtualFileSystem::File> file_of(int) const;
|
||||
BAN::ErrorOr<BAN::String> path_of(int) const;
|
||||
|
|
@ -74,8 +74,8 @@ namespace Kernel
|
|||
|
||||
struct flock_t
|
||||
{
|
||||
bool locked;
|
||||
bool shared;
|
||||
bool locked { false };
|
||||
bool shared { false };
|
||||
ThreadBlocker thread_blocker;
|
||||
BAN::HashSet<pid_t> lockers;
|
||||
};
|
||||
|
|
@ -109,6 +109,32 @@ namespace Kernel
|
|||
BAN::ErrorOr<int> get_free_fd() const;
|
||||
BAN::ErrorOr<void> get_free_fd_pair(int fds[2]) const;
|
||||
|
||||
public:
|
||||
class FDWrapper
|
||||
{
|
||||
public:
|
||||
FDWrapper(BAN::RefPtr<OpenFileDescription>);
|
||||
FDWrapper(const FDWrapper& other) { *this = other; }
|
||||
FDWrapper(FDWrapper&& other) { *this = BAN::move(other); }
|
||||
~FDWrapper();
|
||||
|
||||
FDWrapper& operator=(const FDWrapper&);
|
||||
FDWrapper& operator=(FDWrapper&&);
|
||||
|
||||
int fd() const { return m_fd; }
|
||||
|
||||
void clear();
|
||||
|
||||
private:
|
||||
BAN::RefPtr<OpenFileDescription> m_description;
|
||||
int m_fd { -1 };
|
||||
|
||||
friend class OpenFileDescriptorSet;
|
||||
};
|
||||
|
||||
BAN::ErrorOr<FDWrapper> get_fd_wrapper(int fd);
|
||||
size_t open_all_fd_wrappers(BAN::Span<FDWrapper> fd_wrappers);
|
||||
|
||||
private:
|
||||
const Credentials& m_credentials;
|
||||
mutable Mutex m_mutex;
|
||||
|
|
|
|||
|
|
@ -19,15 +19,26 @@ namespace Kernel
|
|||
asm volatile("cli");
|
||||
|
||||
const bool had_debug_lock = Debug::s_debug_lock.current_processor_has_lock();
|
||||
|
||||
bool first_panic = false;
|
||||
|
||||
{
|
||||
SpinLockGuard _(Debug::s_debug_lock);
|
||||
derrorln("Kernel panic at {}", location);
|
||||
if (had_debug_lock)
|
||||
derrorln(" while having debug lock...");
|
||||
derrorln(message, BAN::forward<Args>(args)...);
|
||||
if (!g_paniced)
|
||||
{
|
||||
g_paniced = true;
|
||||
Debug::dump_stack_trace();
|
||||
g_paniced = true;
|
||||
first_panic = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (first_panic)
|
||||
Debug::dump_qr_code();
|
||||
|
||||
asm volatile("ud2");
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,9 +109,9 @@ namespace Kernel
|
|||
BAN::ErrorOr<long> sys_access(const char* path, int amode);
|
||||
BAN::ErrorOr<long> sys_create_dir(const char*, mode_t);
|
||||
BAN::ErrorOr<long> sys_hardlinkat(int fd1, const char* path1, int fd2, const char* path2, int flag);
|
||||
BAN::ErrorOr<long> sys_renameat(int oldfd, const char* old, int newfd, const char* _new);
|
||||
BAN::ErrorOr<long> sys_unlinkat(int fd, const char* path, int flag);
|
||||
BAN::ErrorOr<long> sys_readlinkat(int fd, const char* path, char* buffer, size_t bufsize);
|
||||
|
||||
BAN::ErrorOr<long> sys_symlinkat(const char* path1, int fd, const char* path2);
|
||||
|
||||
BAN::ErrorOr<long> sys_flock(int fd, int op);
|
||||
|
|
@ -134,8 +134,8 @@ namespace Kernel
|
|||
BAN::ErrorOr<long> sys_bind(int socket, const sockaddr* address, socklen_t address_len);
|
||||
BAN::ErrorOr<long> sys_connect(int socket, const sockaddr* address, socklen_t address_len);
|
||||
BAN::ErrorOr<long> sys_listen(int socket, int backlog);
|
||||
BAN::ErrorOr<long> sys_sendto(const sys_sendto_t*);
|
||||
BAN::ErrorOr<long> sys_recvfrom(sys_recvfrom_t*);
|
||||
BAN::ErrorOr<long> sys_recvmsg(int socket, msghdr* message, int flags);
|
||||
BAN::ErrorOr<long> sys_sendmsg(int socket, const msghdr* message, int flags);
|
||||
|
||||
BAN::ErrorOr<long> sys_ioctl(int fildes, int request, void* arg);
|
||||
|
||||
|
|
@ -149,7 +149,7 @@ namespace Kernel
|
|||
BAN::ErrorOr<long> sys_pipe(int fildes[2]);
|
||||
BAN::ErrorOr<long> sys_dup2(int fildes, int fildes2);
|
||||
|
||||
BAN::ErrorOr<long> sys_fcntl(int fildes, int cmd, int extra);
|
||||
BAN::ErrorOr<long> sys_fcntl(int fildes, int cmd, uintptr_t extra);
|
||||
|
||||
BAN::ErrorOr<long> sys_seek(int fd, off_t offset, int whence);
|
||||
BAN::ErrorOr<long> sys_tell(int fd);
|
||||
|
|
@ -172,6 +172,7 @@ namespace Kernel
|
|||
|
||||
BAN::ErrorOr<long> sys_readdir(int fd, struct dirent* list, size_t list_len);
|
||||
|
||||
BAN::ErrorOr<BAN::Vector<BAN::UniqPtr<MemoryRegion>>> split_memory_region(BAN::UniqPtr<MemoryRegion>&& region, vaddr_t base, size_t length);
|
||||
BAN::ErrorOr<long> sys_mmap(const sys_mmap_t*);
|
||||
BAN::ErrorOr<long> sys_munmap(void* addr, size_t len);
|
||||
BAN::ErrorOr<long> sys_mprotect(void* addr, size_t len, int prot);
|
||||
|
|
@ -191,7 +192,7 @@ namespace Kernel
|
|||
void set_stopped(bool stopped, int signal);
|
||||
void wait_while_stopped();
|
||||
|
||||
static BAN::ErrorOr<void> kill(pid_t pid, int signal);
|
||||
static BAN::ErrorOr<void> kill(pid_t pid, int signal, const siginfo_t& = {});
|
||||
BAN::ErrorOr<long> sys_kill(pid_t pid, int signal);
|
||||
BAN::ErrorOr<long> sys_sigaction(int signal, const struct sigaction* act, struct sigaction* oact);
|
||||
BAN::ErrorOr<long> sys_sigpending(sigset_t* set);
|
||||
|
|
@ -202,8 +203,12 @@ namespace Kernel
|
|||
|
||||
BAN::ErrorOr<long> sys_futex(int op, const uint32_t* addr, uint32_t val, const timespec* abstime);
|
||||
BAN::ErrorOr<long> sys_yield();
|
||||
BAN::ErrorOr<long> sys_set_tls(void*);
|
||||
BAN::ErrorOr<long> sys_get_tls();
|
||||
|
||||
BAN::ErrorOr<long> sys_set_fsbase(void*);
|
||||
BAN::ErrorOr<long> sys_get_fsbase();
|
||||
BAN::ErrorOr<long> sys_set_gsbase(void*);
|
||||
BAN::ErrorOr<long> sys_get_gsbase();
|
||||
|
||||
BAN::ErrorOr<long> sys_pthread_create(const pthread_attr_t* attr, void (*entry)(void*), void* arg);
|
||||
BAN::ErrorOr<long> sys_pthread_exit(void* value);
|
||||
BAN::ErrorOr<long> sys_pthread_join(pthread_t thread, void** value);
|
||||
|
|
@ -228,7 +233,8 @@ namespace Kernel
|
|||
size_t proc_meminfo(off_t offset, BAN::ByteSpan) const;
|
||||
size_t proc_cmdline(off_t offset, BAN::ByteSpan) const;
|
||||
size_t proc_environ(off_t offset, BAN::ByteSpan) const;
|
||||
BAN::ErrorOr<BAN::String> proc_executable() const;
|
||||
BAN::ErrorOr<BAN::String> proc_cwd() const;
|
||||
BAN::ErrorOr<BAN::String> proc_exe() const;
|
||||
|
||||
BAN::StringView executable() const { return m_executable; }
|
||||
|
||||
|
|
@ -240,6 +246,8 @@ namespace Kernel
|
|||
// FIXME: remove this API
|
||||
BAN::ErrorOr<BAN::String> absolute_path_of(BAN::StringView) const;
|
||||
|
||||
OpenFileDescriptorSet& open_file_descriptor_set() { return m_open_file_descriptors; }
|
||||
|
||||
// ONLY CALLED BY TIMER INTERRUPT
|
||||
static void update_alarm_queue();
|
||||
|
||||
|
|
@ -263,12 +271,17 @@ namespace Kernel
|
|||
BAN::StringView file_name;
|
||||
};
|
||||
|
||||
// Adds new region to the sorted array of mapped regions
|
||||
BAN::ErrorOr<void> add_mapped_region(BAN::UniqPtr<MemoryRegion>&&);
|
||||
// If address is contained by a region, returns the index of that.
|
||||
// Otherwise returns the address of the first region after this address.
|
||||
size_t find_mapped_region(vaddr_t) const;
|
||||
|
||||
BAN::ErrorOr<VirtualFileSystem::File> find_file(int fd, const char* path, int flags) const;
|
||||
BAN::ErrorOr<FileParent> find_parent_file(int fd, const char* path, int flags) const;
|
||||
BAN::ErrorOr<VirtualFileSystem::File> find_relative_parent(int fd, const char* path) const;
|
||||
|
||||
BAN::ErrorOr<void> validate_string_access(const char*);
|
||||
BAN::ErrorOr<void> validate_pointer_access_check(const void*, size_t, bool needs_write);
|
||||
BAN::ErrorOr<void> validate_pointer_access(const void*, size_t, bool needs_write);
|
||||
BAN::ErrorOr<MemoryRegion*> validate_and_pin_pointer_access(const void*, size_t, bool needs_write);
|
||||
|
||||
|
|
@ -278,7 +291,7 @@ namespace Kernel
|
|||
return m_signal_pending_mask;
|
||||
}
|
||||
|
||||
void add_pending_signal(uint8_t signal)
|
||||
void add_pending_signal(uint8_t signal, const siginfo_t& info)
|
||||
{
|
||||
ASSERT(signal >= _SIGMIN);
|
||||
ASSERT(signal <= _SIGMAX);
|
||||
|
|
@ -290,6 +303,7 @@ namespace Kernel
|
|||
if (handler == SIG_DFL && (signal == SIGCHLD || signal == SIGURG))
|
||||
return;
|
||||
m_signal_pending_mask |= 1ull << signal;
|
||||
m_signal_infos[signal] = info;
|
||||
}
|
||||
|
||||
void remove_pending_signal(uint8_t signal)
|
||||
|
|
@ -342,6 +356,7 @@ namespace Kernel
|
|||
uint64_t m_alarm_wake_time_ns { 0 };
|
||||
|
||||
mutable SpinLock m_signal_lock;
|
||||
siginfo_t m_signal_infos[_SIGMAX + 1] { };
|
||||
struct sigaction m_signal_handlers[_SIGMAX + 1] { };
|
||||
uint64_t m_signal_pending_mask { 0 };
|
||||
|
||||
|
|
|
|||
|
|
@ -112,7 +112,9 @@ namespace Kernel
|
|||
static void send_smp_message(ProcessorID, const SMPMessage&, bool send_ipi = true);
|
||||
static void broadcast_smp_message(const SMPMessage&);
|
||||
|
||||
static void load_tls();
|
||||
static void load_segments();
|
||||
static void load_fsbase();
|
||||
static void load_gsbase();
|
||||
|
||||
private:
|
||||
Processor() = default;
|
||||
|
|
|
|||
|
|
@ -59,8 +59,8 @@ namespace Kernel
|
|||
bool can_add_signal_to_execute() const;
|
||||
bool will_execute_signal() const;
|
||||
// Returns true if handled signal had SA_RESTART
|
||||
bool handle_signal(int signal = 0);
|
||||
void add_signal(int signal);
|
||||
bool handle_signal(int signal = 0, const siginfo_t& signal_info = {});
|
||||
void add_signal(int signal, const siginfo_t& info);
|
||||
void set_suspend_signal_mask(uint64_t sigmask);
|
||||
|
||||
static bool is_stopping_signal(int signal);
|
||||
|
|
@ -122,8 +122,10 @@ namespace Kernel
|
|||
void set_cpu_time_start();
|
||||
void set_cpu_time_stop();
|
||||
|
||||
void set_tls(vaddr_t tls) { m_tls = tls; }
|
||||
vaddr_t get_tls() const { return m_tls; }
|
||||
void set_fsbase(vaddr_t base) { m_fsbase = base; }
|
||||
vaddr_t get_fsbase() const { return m_fsbase; }
|
||||
void set_gsbase(vaddr_t base) { m_gsbase = base; }
|
||||
vaddr_t get_gsbase() const { return m_gsbase; }
|
||||
|
||||
size_t virtual_page_count() const { return (m_kernel_stack ? (m_kernel_stack->size() / PAGE_SIZE) : 0) + (m_userspace_stack ? (m_userspace_stack->size() / PAGE_SIZE) : 0); }
|
||||
size_t physical_page_count() const { return virtual_page_count(); }
|
||||
|
|
@ -164,13 +166,15 @@ namespace Kernel
|
|||
bool m_is_userspace { false };
|
||||
bool m_delete_process { false };
|
||||
|
||||
vaddr_t m_tls { 0 };
|
||||
vaddr_t m_fsbase { 0 };
|
||||
vaddr_t m_gsbase { 0 };
|
||||
|
||||
SchedulerQueue::Node* m_scheduler_node { nullptr };
|
||||
|
||||
InterruptStack m_interrupt_stack { };
|
||||
InterruptRegisters m_interrupt_registers { };
|
||||
|
||||
siginfo_t m_signal_infos[_SIGMAX + 1] { };
|
||||
uint64_t m_signal_pending_mask { 0 };
|
||||
uint64_t m_signal_block_mask { 0 };
|
||||
BAN::Optional<uint64_t> m_signal_suspend_mask;
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <BAN/Formatter.h>
|
||||
#include <kernel/Terminal/TTY.h>
|
||||
|
||||
#define kprint(...) BAN::Formatter::print(Kernel::TTY::putchar_current, __VA_ARGS__)
|
||||
#define kprintln(...) BAN::Formatter::println(Kernel::TTY::putchar_current, __VA_ARGS__)
|
||||
|
|
@ -856,7 +856,7 @@ acpi_release_global_lock:
|
|||
};
|
||||
|
||||
// TODO: EC can also reside in memory space
|
||||
auto crs_buffer = BAN::ConstByteSpan { crs.as.str_buf->bytes, crs.as.str_buf->size };
|
||||
auto crs_buffer = BAN::ConstByteSpan { crs.as.str_buf->bytes, static_cast<size_t>(crs.as.str_buf->size) };
|
||||
const auto data_port = TRY(extract_io_port(crs_buffer));
|
||||
const auto command_port = TRY(extract_io_port(crs_buffer));
|
||||
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ namespace Kernel::ACPI
|
|||
EmbeddedController::~EmbeddedController()
|
||||
{
|
||||
if (m_thread)
|
||||
m_thread->add_signal(SIGKILL);
|
||||
m_thread->add_signal(SIGKILL, {});
|
||||
m_thread = nullptr;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include <kernel/Debug.h>
|
||||
#include <kernel/Device/FramebufferDevice.h>
|
||||
#include <kernel/InterruptController.h>
|
||||
#include <kernel/Lock/SpinLock.h>
|
||||
#include <kernel/Memory/PageTable.h>
|
||||
|
|
@ -6,6 +7,9 @@
|
|||
#include <kernel/Terminal/TTY.h>
|
||||
#include <kernel/Timer/Timer.h>
|
||||
|
||||
#include <LibDEFLATE/Compressor.h>
|
||||
#include <LibQR/QRCode.h>
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
bool g_disable_debug = false;
|
||||
|
|
@ -15,6 +19,15 @@ namespace Debug
|
|||
|
||||
Kernel::RecursiveSpinLock s_debug_lock;
|
||||
|
||||
static constexpr char s_panic_url_prefix[] = "https://bananymous.com/panic#";
|
||||
static constexpr size_t s_qr_code_max_capacity { 2953 };
|
||||
static bool s_qr_code_shown { false };
|
||||
|
||||
static char s_debug_buffer[16 * 1024] {};
|
||||
static size_t s_debug_buffer_tail { 0 };
|
||||
static size_t s_debug_buffer_size { 0 };
|
||||
static uint8_t s_debug_ansi_state { 0 };
|
||||
|
||||
void dump_stack_trace()
|
||||
{
|
||||
using namespace Kernel;
|
||||
|
|
@ -72,17 +85,203 @@ namespace Debug
|
|||
BAN::Formatter::print(Debug::putchar, "\e[m");
|
||||
}
|
||||
|
||||
static void queue_debug_buffer(char ch)
|
||||
{
|
||||
switch (s_debug_ansi_state)
|
||||
{
|
||||
case 1:
|
||||
if (ch == '[')
|
||||
{
|
||||
s_debug_ansi_state = 2;
|
||||
break;
|
||||
}
|
||||
s_debug_ansi_state = 0;
|
||||
[[fallthrough]];
|
||||
case 0:
|
||||
if (ch == '\e')
|
||||
{
|
||||
s_debug_ansi_state = 1;
|
||||
break;
|
||||
}
|
||||
if (!isprint(ch) && ch != '\n')
|
||||
break;
|
||||
s_debug_buffer[(s_debug_buffer_tail + s_debug_buffer_size) % sizeof(s_debug_buffer)] = ch;
|
||||
if (s_debug_buffer_size < sizeof(s_debug_buffer))
|
||||
s_debug_buffer_size++;
|
||||
else
|
||||
s_debug_buffer_tail = (s_debug_buffer_tail + 1) % sizeof(s_debug_buffer);
|
||||
break;
|
||||
case 2:
|
||||
if (isalpha(ch))
|
||||
s_debug_ansi_state = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void reverse(char* first, char* last)
|
||||
{
|
||||
const size_t len = last - first;
|
||||
for (size_t i = 0; i < len / 2; i++)
|
||||
BAN::swap(first[i], first[len - i - 1]);
|
||||
}
|
||||
|
||||
static void rotate(char* first, char* middle, char* last)
|
||||
{
|
||||
reverse(first, middle);
|
||||
reverse(middle, last);
|
||||
reverse(first, last);
|
||||
}
|
||||
|
||||
static BAN::ErrorOr<BAN::Vector<uint8_t>> compress_kernel_logs()
|
||||
{
|
||||
constexpr size_t max_size = ((s_qr_code_max_capacity + 3) / 4 * 3) - sizeof(s_panic_url_prefix);
|
||||
|
||||
BAN::Vector<uint8_t> result;
|
||||
|
||||
size_t l = 0, r = s_debug_buffer_size;
|
||||
while (l + 50 < r)
|
||||
{
|
||||
const size_t middle = (l + r) / 2;
|
||||
const uint8_t* base = reinterpret_cast<const uint8_t*>(s_debug_buffer) + s_debug_buffer_size - middle;
|
||||
|
||||
auto compressed = TRY(LibDEFLATE::Compressor({ base, middle }, LibDEFLATE::StreamType::Zlib).compress());
|
||||
if (compressed.size() > max_size)
|
||||
r = middle;
|
||||
else
|
||||
{
|
||||
l = middle;
|
||||
result = BAN::move(compressed);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void dump_qr_code()
|
||||
{
|
||||
ASSERT(Kernel::g_paniced);
|
||||
|
||||
auto boot_framebuffer = Kernel::FramebufferDevice::boot_framebuffer();
|
||||
if (!boot_framebuffer)
|
||||
{
|
||||
derrorln("No boot framebuffer, not generating QR code");
|
||||
return;
|
||||
}
|
||||
if (boot_framebuffer->width() < 177 + 8 || boot_framebuffer->height() < 177 + 8)
|
||||
{
|
||||
derrorln("Boot framebuffer is too small for a qr code");
|
||||
return;
|
||||
}
|
||||
|
||||
// rotate logs to start from index 0 and be contiguous
|
||||
rotate(s_debug_buffer, s_debug_buffer + s_debug_buffer_tail, s_debug_buffer + sizeof(s_debug_buffer));
|
||||
|
||||
auto compressed_or_error = compress_kernel_logs();
|
||||
if (compressed_or_error.is_error())
|
||||
{
|
||||
// TODO: send uncompressed logs?
|
||||
derrorln("Failed to compress kernel logs: {}", compressed_or_error.error());
|
||||
return;
|
||||
}
|
||||
|
||||
auto compressed = compressed_or_error.release_value();
|
||||
|
||||
static uint8_t qr_code_data[s_qr_code_max_capacity];
|
||||
size_t qr_code_data_len = 0;
|
||||
|
||||
for (size_t i = 0; s_panic_url_prefix[i]; i++)
|
||||
qr_code_data[qr_code_data_len++] = s_panic_url_prefix[i];
|
||||
|
||||
constexpr char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
||||
for (size_t i = 0; i < compressed.size() / 3; i++)
|
||||
{
|
||||
const uint32_t bits =
|
||||
((compressed[3 * i + 0]) << 16) |
|
||||
((compressed[3 * i + 1]) << 8) |
|
||||
((compressed[3 * i + 2]) << 0);
|
||||
|
||||
qr_code_data[qr_code_data_len++] = alphabet[(bits >> 18) & 0x3F];
|
||||
qr_code_data[qr_code_data_len++] = alphabet[(bits >> 12) & 0x3F];
|
||||
qr_code_data[qr_code_data_len++] = alphabet[(bits >> 6) & 0x3F];
|
||||
qr_code_data[qr_code_data_len++] = alphabet[(bits >> 0) & 0x3F];
|
||||
}
|
||||
|
||||
switch (compressed.size() % 3)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
{
|
||||
const uint16_t bits =
|
||||
(compressed[compressed.size() - 1] << 4);
|
||||
qr_code_data[qr_code_data_len++] = alphabet[(bits >> 6) & 0x3F];
|
||||
qr_code_data[qr_code_data_len++] = alphabet[(bits >> 0) & 0x3F];
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
const uint32_t bits =
|
||||
(compressed[compressed.size() - 2] << 10) |
|
||||
(compressed[compressed.size() - 1] << 2);
|
||||
qr_code_data[qr_code_data_len++] = alphabet[(bits >> 12) & 0x3F];
|
||||
qr_code_data[qr_code_data_len++] = alphabet[(bits >> 6) & 0x3F];
|
||||
qr_code_data[qr_code_data_len++] = alphabet[(bits >> 0) & 0x3F];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto qr_or_error = LibQR::QRCode::generate({ qr_code_data, qr_code_data_len });
|
||||
if (qr_or_error.is_error())
|
||||
{
|
||||
derrorln("Failed to generate QR code");
|
||||
return;
|
||||
}
|
||||
|
||||
auto qr_code = qr_or_error.release_value();
|
||||
|
||||
// after this point no more logs are printed to framebuffer
|
||||
s_qr_code_shown = true;
|
||||
|
||||
const size_t min_framebuffer_dimension = BAN::Math::min(boot_framebuffer->width(), boot_framebuffer->height());
|
||||
const size_t module_size = min_framebuffer_dimension / (qr_code.size() + 8);
|
||||
|
||||
for (size_t y = 0; y < (qr_code.size() + 8) * module_size; y++)
|
||||
for (size_t x = 0; x < (qr_code.size() + 8) * module_size; x++)
|
||||
boot_framebuffer->set_pixel(x, y, 0xFFFFFF);
|
||||
|
||||
for (size_t y = 0; y < qr_code.size(); y++)
|
||||
{
|
||||
for (size_t x = 0; x < qr_code.size(); x++)
|
||||
{
|
||||
if (!qr_code.get(x, y))
|
||||
continue;
|
||||
for (size_t i = 0; i < module_size; i++)
|
||||
for (size_t j = 0; j < module_size; j++)
|
||||
boot_framebuffer->set_pixel((x + 4) * module_size + j, (y + 4) * module_size + i, 0x000000);
|
||||
}
|
||||
}
|
||||
|
||||
boot_framebuffer->sync_pixels_rectangle(0, 0, (qr_code.size() + 8) * module_size, (qr_code.size() + 8) * module_size);
|
||||
}
|
||||
|
||||
void putchar(char ch)
|
||||
{
|
||||
using namespace Kernel;
|
||||
|
||||
if (!g_paniced)
|
||||
queue_debug_buffer(ch);
|
||||
|
||||
if (g_disable_debug)
|
||||
return;
|
||||
|
||||
if (Kernel::Serial::has_devices())
|
||||
return Kernel::Serial::putchar_any(ch);
|
||||
if (Kernel::TTY::is_initialized())
|
||||
{
|
||||
if (s_qr_code_shown)
|
||||
return;
|
||||
return Kernel::TTY::putchar_current(ch);
|
||||
}
|
||||
|
||||
if (g_terminal_driver)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -12,12 +12,19 @@
|
|||
namespace Kernel
|
||||
{
|
||||
|
||||
static BAN::RefPtr<FramebufferDevice> s_boot_framebuffer;
|
||||
|
||||
static uint32_t get_framebuffer_device_index()
|
||||
{
|
||||
static uint32_t index = 0;
|
||||
return index++;
|
||||
}
|
||||
|
||||
BAN::RefPtr<FramebufferDevice> FramebufferDevice::boot_framebuffer()
|
||||
{
|
||||
return s_boot_framebuffer;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<FramebufferDevice>> FramebufferDevice::create_from_boot_framebuffer()
|
||||
{
|
||||
ASSERT(g_boot_info.framebuffer.type == FramebufferInfo::Type::RGB);
|
||||
|
|
@ -37,6 +44,7 @@ namespace Kernel
|
|||
auto device = BAN::RefPtr<FramebufferDevice>::adopt(device_ptr);
|
||||
TRY(device->initialize());
|
||||
DevFileSystem::get().add_device(device);
|
||||
s_boot_framebuffer = device;
|
||||
return device;
|
||||
}
|
||||
|
||||
|
|
@ -293,6 +301,13 @@ namespace Kernel
|
|||
return BAN::UniqPtr<MemoryRegion>(BAN::move(region));
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> split(size_t offset) override
|
||||
{
|
||||
(void)offset;
|
||||
dwarnln("TODO: FramebufferMemoryRegion::split");
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
}
|
||||
|
||||
protected:
|
||||
// Returns error if no memory was available
|
||||
// Returns true if page was succesfully allocated
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#include <BAN/ScopeGuard.h>
|
||||
#include <kernel/FS/Ext2/FileSystem.h>
|
||||
#include <kernel/FS/Ext2/Inode.h>
|
||||
#include <kernel/Lock/LockGuard.h>
|
||||
#include <kernel/Timer/Timer.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
|
@ -114,8 +115,11 @@ namespace Kernel
|
|||
TRY(result.append(BAN::StringView(reinterpret_cast<const char*>(m_inode.block), m_inode.size)));
|
||||
return result;
|
||||
}
|
||||
dwarnln("TODO: ext2 get symlink target from {} byte inode", m_inode.size);
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
|
||||
BAN::String result;
|
||||
TRY(result.resize(m_inode.size));
|
||||
TRY(read_impl(0, { reinterpret_cast<uint8_t*>(result.data()), result.size() }));
|
||||
return BAN::move(result);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Ext2Inode::set_link_target_impl(BAN::StringView target)
|
||||
|
|
@ -129,8 +133,10 @@ namespace Kernel
|
|||
TRY(sync());
|
||||
return {};
|
||||
}
|
||||
dwarnln("TODO: ext2 set symlink target to {} bytes from {} byte inode", target.size(), m_inode.size);
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
|
||||
TRY(truncate_impl(target.size()));
|
||||
TRY(write_impl(0, { reinterpret_cast<const uint8_t*>(target.data()), target.size() }));
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<size_t> Ext2Inode::read_impl(off_t offset, BAN::ByteSpan buffer)
|
||||
|
|
@ -580,6 +586,37 @@ done:
|
|||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Ext2Inode::rename_inode_impl(BAN::RefPtr<Inode> old_parent, BAN::StringView old_name, BAN::StringView new_name)
|
||||
{
|
||||
ASSERT(this->mode().ifdir());
|
||||
ASSERT(old_parent->mode().ifdir());
|
||||
ASSERT(&m_fs == old_parent->filesystem());
|
||||
|
||||
auto* ext2_parent = static_cast<Ext2Inode*>(old_parent.ptr());
|
||||
|
||||
// FIXME: possible deadlock :)
|
||||
LockGuard _(ext2_parent->m_mutex);
|
||||
|
||||
auto old_inode = TRY(ext2_parent->find_inode_impl(old_name));
|
||||
auto* ext2_inode = static_cast<Ext2Inode*>(old_inode.ptr());
|
||||
|
||||
if (auto replace_or_error = find_inode_impl(new_name); replace_or_error.is_error())
|
||||
{
|
||||
if (replace_or_error.error().get_error_code() != ENOENT)
|
||||
return replace_or_error.release_error();
|
||||
}
|
||||
else
|
||||
{
|
||||
TRY(unlink_impl(new_name));
|
||||
}
|
||||
|
||||
TRY(link_inode_to_directory(*ext2_inode, new_name));
|
||||
|
||||
TRY(ext2_parent->remove_inode_from_directory(old_name, false));
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Ext2Inode::link_inode_to_directory(Ext2Inode& inode, BAN::StringView name)
|
||||
{
|
||||
if (!this->mode().ifdir())
|
||||
|
|
@ -773,7 +810,7 @@ needs_new_block:
|
|||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Ext2Inode::unlink_impl(BAN::StringView name)
|
||||
BAN::ErrorOr<void> Ext2Inode::remove_inode_from_directory(BAN::StringView name, bool cleanup_directory)
|
||||
{
|
||||
ASSERT(mode().ifdir());
|
||||
if (m_inode.flags & Ext2::Enum::INDEX_FL)
|
||||
|
|
@ -797,7 +834,7 @@ needs_new_block:
|
|||
if (entry.inode && name == BAN::StringView(entry.name, entry.name_len))
|
||||
{
|
||||
auto inode = TRY(Ext2Inode::create(m_fs, entry.inode));
|
||||
if (inode->mode().ifdir())
|
||||
if (cleanup_directory && inode->mode().ifdir())
|
||||
{
|
||||
if (!TRY(inode->is_directory_empty()))
|
||||
return BAN::Error::from_errno(ENOTEMPTY);
|
||||
|
|
@ -831,6 +868,12 @@ needs_new_block:
|
|||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Ext2Inode::unlink_impl(BAN::StringView name)
|
||||
{
|
||||
TRY(remove_inode_from_directory(name, true));
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<uint32_t> Ext2Inode::allocate_new_block_to_indirect_block(uint32_t& block, uint32_t index, uint32_t depth)
|
||||
{
|
||||
const uint32_t inode_blocks_per_fs_block = blksize() / 512;
|
||||
|
|
|
|||
|
|
@ -114,6 +114,20 @@ namespace Kernel
|
|||
return link_inode_impl(name, inode);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Inode::rename_inode(BAN::RefPtr<Inode> old_parent, BAN::StringView old_name, BAN::StringView new_name)
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
if (!this->mode().ifdir())
|
||||
return BAN::Error::from_errno(ENOTDIR);
|
||||
if (!old_parent->mode().ifdir())
|
||||
return BAN::Error::from_errno(ENOTDIR);
|
||||
if (this->filesystem() != old_parent->filesystem())
|
||||
return BAN::Error::from_errno(EXDEV);
|
||||
if (auto* fs = filesystem(); fs && (fs->flag() & ST_RDONLY))
|
||||
return BAN::Error::from_errno(EROFS);
|
||||
return rename_inode_impl(old_parent, old_name, new_name);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Inode::unlink(BAN::StringView name)
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
|
|
@ -176,21 +190,21 @@ namespace Kernel
|
|||
return listen_impl(backlog);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<size_t> Inode::sendto(BAN::ConstByteSpan message, const sockaddr* address, socklen_t address_len)
|
||||
BAN::ErrorOr<size_t> Inode::recvmsg(msghdr& message, int flags)
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
if (!mode().ifsock())
|
||||
return BAN::Error::from_errno(ENOTSOCK);
|
||||
return sendto_impl(message, address, address_len);
|
||||
};
|
||||
return recvmsg_impl(message, flags);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<size_t> Inode::recvfrom(BAN::ByteSpan buffer, sockaddr* address, socklen_t* address_len)
|
||||
BAN::ErrorOr<size_t> Inode::sendmsg(const msghdr& message, int flags)
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
if (!mode().ifsock())
|
||||
return BAN::Error::from_errno(ENOTSOCK);
|
||||
return recvfrom_impl(buffer, address, address_len);
|
||||
};
|
||||
return sendmsg_impl(message, flags);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Inode::getsockname(sockaddr* address, socklen_t* address_len)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ namespace Kernel
|
|||
{
|
||||
if (m_reading_count == 0)
|
||||
{
|
||||
Thread::current().add_signal(SIGPIPE);
|
||||
Thread::current().add_signal(SIGPIPE, {});
|
||||
return BAN::Error::from_errno(EPIPE);
|
||||
}
|
||||
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker, &m_mutex));
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ namespace Kernel
|
|||
[](void*) -> BAN::ErrorOr<BAN::String> {
|
||||
return BAN::String::formatted("{}", Process::current().pid());
|
||||
},
|
||||
nullptr, *s_instance, 0444, 0, 0)
|
||||
nullptr, nullptr, *s_instance, 0444, 0, 0)
|
||||
);
|
||||
MUST(static_cast<TmpDirectoryInode*>(s_instance->root_inode().ptr())->link_inode(*self_inode, "self"_sv));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
#include <kernel/FS/ProcFS/Inode.h>
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
|
|
@ -15,9 +17,11 @@ namespace Kernel
|
|||
TRY(inode->link_inode(*inode, "."_sv));
|
||||
TRY(inode->link_inode(static_cast<TmpInode&>(*fs.root_inode()), ".."_sv));
|
||||
TRY(inode->link_inode(*MUST(ProcROProcessInode::create_new(process, &Process::proc_meminfo, fs, 0400)), "meminfo"_sv));
|
||||
TRY(inode->link_inode(*MUST(ProcROProcessInode::create_new(process, &Process::proc_cmdline, fs, 0400)), "cmdline"_sv));
|
||||
TRY(inode->link_inode(*MUST(ProcROProcessInode::create_new(process, &Process::proc_cmdline, fs, 0444)), "cmdline"_sv));
|
||||
TRY(inode->link_inode(*MUST(ProcROProcessInode::create_new(process, &Process::proc_environ, fs, 0400)), "environ"_sv));
|
||||
TRY(inode->link_inode(*MUST(ProcSymlinkProcessInode::create_new(process, &Process::proc_executable, fs, 0400)), "exe"_sv));
|
||||
TRY(inode->link_inode(*MUST(ProcSymlinkProcessInode::create_new(process, &Process::proc_cwd, fs, 0777)), "cwd"_sv));
|
||||
TRY(inode->link_inode(*MUST(ProcSymlinkProcessInode::create_new(process, &Process::proc_exe, fs, 0777)), "exe"_sv));
|
||||
TRY(inode->link_inode(*MUST(ProcFDDirectoryInode::create_new(process, fs, 0777)), "fd"_sv));
|
||||
|
||||
return inode;
|
||||
}
|
||||
|
|
@ -33,7 +37,9 @@ namespace Kernel
|
|||
(void)TmpDirectoryInode::unlink_impl("meminfo"_sv);
|
||||
(void)TmpDirectoryInode::unlink_impl("cmdline"_sv);
|
||||
(void)TmpDirectoryInode::unlink_impl("environ"_sv);
|
||||
(void)TmpDirectoryInode::unlink_impl("cwd"_sv);
|
||||
(void)TmpDirectoryInode::unlink_impl("exe"_sv);
|
||||
(void)TmpDirectoryInode::unlink_impl("fd"_sv);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<ProcROProcessInode>> ProcROProcessInode::create_new(Process& process, size_t (Process::*callback)(off_t, BAN::ByteSpan) const, TmpFileSystem& fs, mode_t mode)
|
||||
|
|
@ -108,27 +114,123 @@ namespace Kernel
|
|||
return m_callback(offset, buffer);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<ProcSymlinkInode>> ProcSymlinkInode::create_new(BAN::ErrorOr<BAN::String> (*callback)(void*), void* data, TmpFileSystem& fs, mode_t mode, uid_t uid, gid_t gid)
|
||||
BAN::ErrorOr<BAN::RefPtr<ProcSymlinkInode>> ProcSymlinkInode::create_new(BAN::ErrorOr<BAN::String> (*callback)(void*), void (*destructor)(void*), void* data, TmpFileSystem& fs, mode_t mode, uid_t uid, gid_t gid)
|
||||
{
|
||||
auto inode_info = create_inode_info(Mode::IFLNK | mode, uid, gid);
|
||||
|
||||
auto* inode_ptr = new ProcSymlinkInode(callback, data, fs, inode_info);
|
||||
auto* inode_ptr = new ProcSymlinkInode(callback, destructor, data, fs, inode_info);
|
||||
if (inode_ptr == nullptr)
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
return BAN::RefPtr<ProcSymlinkInode>::adopt(inode_ptr);
|
||||
}
|
||||
|
||||
ProcSymlinkInode::ProcSymlinkInode(BAN::ErrorOr<BAN::String> (*callback)(void*), void* data, TmpFileSystem& fs, const TmpInodeInfo& inode_info)
|
||||
ProcSymlinkInode::ProcSymlinkInode(BAN::ErrorOr<BAN::String> (*callback)(void*), void (*destructor)(void*), void* data, TmpFileSystem& fs, const TmpInodeInfo& inode_info)
|
||||
: TmpInode(fs, MUST(fs.allocate_inode(inode_info)), inode_info)
|
||||
, m_callback(callback)
|
||||
, m_destructor(destructor)
|
||||
, m_data(data)
|
||||
{
|
||||
m_inode_info.mode |= Inode::Mode::IFLNK;
|
||||
}
|
||||
|
||||
ProcSymlinkInode::~ProcSymlinkInode()
|
||||
{
|
||||
if (m_destructor)
|
||||
m_destructor(m_data);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::String> ProcSymlinkInode::link_target_impl()
|
||||
{
|
||||
return m_callback(m_data);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<ProcFDDirectoryInode>> ProcFDDirectoryInode::create_new(Process& process, TmpFileSystem& fs, mode_t mode)
|
||||
{
|
||||
auto inode_info = create_inode_info(Mode::IFDIR | mode, 0, 0);
|
||||
|
||||
auto* inode_ptr = new ProcFDDirectoryInode(process, fs, inode_info);
|
||||
if (inode_ptr == nullptr)
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
return BAN::RefPtr<ProcFDDirectoryInode>::adopt(inode_ptr);
|
||||
}
|
||||
|
||||
ProcFDDirectoryInode::ProcFDDirectoryInode(Process& process, TmpFileSystem& fs, const TmpInodeInfo& inode_info)
|
||||
: TmpInode(fs, MUST(fs.allocate_inode(inode_info)), inode_info)
|
||||
, m_process(process)
|
||||
{
|
||||
ASSERT(mode().ifdir());
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<Inode>> ProcFDDirectoryInode::find_inode_impl(BAN::StringView name)
|
||||
{
|
||||
int fd = 0;
|
||||
for (char ch : name)
|
||||
{
|
||||
if (!isdigit(ch))
|
||||
return BAN::Error::from_errno(ENOENT);
|
||||
fd = (fd * 10) + (ch - '0');
|
||||
if (fd > OPEN_MAX)
|
||||
return BAN::Error::from_errno(ENOENT);
|
||||
}
|
||||
|
||||
auto path_or_error = m_process.open_file_descriptor_set().path_of(fd);
|
||||
if (path_or_error.is_error())
|
||||
return BAN::Error::from_errno(ENOENT);
|
||||
|
||||
auto* data = new BAN::String();
|
||||
if (data == nullptr)
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
*data = BAN::move(path_or_error.release_value());
|
||||
|
||||
auto inode = TRY(ProcSymlinkInode::create_new(
|
||||
[](void* data) -> BAN::ErrorOr<BAN::String>
|
||||
{
|
||||
BAN::String result;
|
||||
TRY(result.append(*static_cast<BAN::String*>(data)));
|
||||
return result;
|
||||
},
|
||||
[](void* data) -> void
|
||||
{
|
||||
delete static_cast<BAN::String*>(data);
|
||||
},
|
||||
data, m_fs, 0777, uid(), gid()
|
||||
));
|
||||
|
||||
return BAN::RefPtr<Inode>(BAN::move(inode));
|
||||
}
|
||||
|
||||
BAN::ErrorOr<size_t> ProcFDDirectoryInode::list_next_inodes_impl(off_t offset, struct dirent* list, size_t list_len)
|
||||
{
|
||||
if (list_len == 0)
|
||||
return BAN::Error::from_errno(ENOBUFS);
|
||||
|
||||
auto& ofds = m_process.open_file_descriptor_set();
|
||||
|
||||
for (size_t fd = 0; fd < OPEN_MAX; fd++)
|
||||
{
|
||||
if (ofds.inode_of(fd).is_error())
|
||||
continue;
|
||||
if (offset-- > 0)
|
||||
continue;
|
||||
|
||||
list[0] = {
|
||||
.d_ino = 0,
|
||||
.d_type = DT_LNK,
|
||||
.d_name = {},
|
||||
};
|
||||
|
||||
size_t index = 0;
|
||||
BAN::Formatter::print(
|
||||
[&](char ch) {
|
||||
list[0].d_name[index++] = ch;
|
||||
list[0].d_name[index] = '\0';
|
||||
}, "{}", fd
|
||||
);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -669,7 +669,44 @@ namespace Kernel
|
|||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> TmpDirectoryInode::rename_inode_impl(BAN::RefPtr<Inode> old_parent, BAN::StringView old_name, BAN::StringView new_name)
|
||||
{
|
||||
ASSERT(this->mode().ifdir());
|
||||
ASSERT(old_parent->mode().ifdir());
|
||||
ASSERT(&m_fs == old_parent->filesystem());
|
||||
|
||||
auto* tmp_parent = static_cast<TmpDirectoryInode*>(old_parent.ptr());
|
||||
|
||||
// FIXME: possible deadlock :)
|
||||
LockGuard _(tmp_parent->m_mutex);
|
||||
|
||||
auto old_inode = TRY(tmp_parent->find_inode_impl(old_name));
|
||||
auto* tmp_inode = static_cast<TmpInode*>(old_inode.ptr());
|
||||
|
||||
if (auto replace_or_error = find_inode_impl(new_name); replace_or_error.is_error())
|
||||
{
|
||||
if (replace_or_error.error().get_error_code() != ENOENT)
|
||||
return replace_or_error.release_error();
|
||||
}
|
||||
else
|
||||
{
|
||||
TRY(unlink_impl(new_name));
|
||||
}
|
||||
|
||||
TRY(link_inode(*tmp_inode, new_name));
|
||||
|
||||
TRY(tmp_parent->unlink_inode(old_name, false));
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> TmpDirectoryInode::unlink_impl(BAN::StringView name)
|
||||
{
|
||||
TRY(unlink_inode(name, true));
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> TmpDirectoryInode::unlink_inode(BAN::StringView name, bool cleanup)
|
||||
{
|
||||
ino_t entry_ino = 0;
|
||||
|
||||
|
|
@ -687,6 +724,7 @@ namespace Kernel
|
|||
|
||||
ASSERT(inode->nlink() > 0);
|
||||
|
||||
if (cleanup)
|
||||
TRY(inode->prepare_unlink());
|
||||
inode->m_inode_info.nlink--;
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,8 @@ namespace Kernel
|
|||
gdt->write_entry(0x20, 0x00000000, 0xFFFFF, 0xF2, data_flags); // user data
|
||||
#if ARCH(i686)
|
||||
gdt->write_entry(0x28, reinterpret_cast<uint32_t>(processor), sizeof(Processor), 0x92, 0x4); // processor data
|
||||
gdt->write_entry(0x30, 0x00000000, 0x00000, 0x00, 0x0); // tls
|
||||
gdt->write_entry(0x30, 0x00000000, 0x00000, 0xF2, data_flags); // fsbase
|
||||
gdt->write_entry(0x38, 0x00000000, 0x00000, 0xF2, data_flags); // gsbase
|
||||
#endif
|
||||
gdt->write_tss();
|
||||
|
||||
|
|
@ -37,10 +38,14 @@ namespace Kernel
|
|||
}
|
||||
|
||||
#if ARCH(i686)
|
||||
void GDT::set_tls(uintptr_t addr)
|
||||
void GDT::set_fsbase(uintptr_t addr)
|
||||
{
|
||||
write_entry(0x30, addr, 0xFFFF, 0xF2, 0xC);
|
||||
}
|
||||
void GDT::set_gsbase(uintptr_t addr)
|
||||
{
|
||||
write_entry(0x38, addr, 0xFFFF, 0xF2, 0xC);
|
||||
}
|
||||
#endif
|
||||
|
||||
void GDT::write_entry(uint8_t offset, uint32_t base, uint32_t limit, uint8_t access, uint8_t flags)
|
||||
|
|
|
|||
|
|
@ -203,7 +203,7 @@ namespace Kernel
|
|||
if (result.is_error())
|
||||
{
|
||||
dwarnln("Demand paging: {}", result.error());
|
||||
Thread::current().handle_signal(SIGKILL);
|
||||
Thread::current().handle_signal(SIGKILL, {});
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
|
@ -236,11 +236,15 @@ namespace Kernel
|
|||
"Register dump\r\n"
|
||||
"rax=0x{16H}, rbx=0x{16H}, rcx=0x{16H}, rdx=0x{16H}\r\n"
|
||||
"rsp=0x{16H}, rbp=0x{16H}, rdi=0x{16H}, rsi=0x{16H}\r\n"
|
||||
" r8=0x{16H}, r9=0x{16H}, r10=0x{16H}, r11=0x{16H}\r\n"
|
||||
"r12=0x{16H}, r13=0x{16H}, r14=0x{16H}, r15=0x{16H}\r\n"
|
||||
"rip=0x{16H}, rflags=0x{16H}\r\n"
|
||||
"cr0=0x{16H}, cr2=0x{16H}, cr3=0x{16H}, cr4=0x{16H}",
|
||||
Processor::current_id(), isr_exceptions[isr], error, pid, tid, process_name,
|
||||
regs->rax, regs->rbx, regs->rcx, regs->rdx,
|
||||
interrupt_stack->sp, regs->rbp, regs->rdi, regs->rsi,
|
||||
regs->r8, regs->r9, regs->r10, regs->r11,
|
||||
regs->r12, regs->r13, regs->r14, regs->r15,
|
||||
interrupt_stack->ip, interrupt_stack->flags,
|
||||
regs->cr0, regs->cr2, regs->cr3, regs->cr4
|
||||
);
|
||||
|
|
@ -269,30 +273,48 @@ namespace Kernel
|
|||
{
|
||||
// TODO: Confirm and fix the exception to signal mappings
|
||||
|
||||
int signal = 0;
|
||||
siginfo_t signal_info {};
|
||||
switch (isr)
|
||||
{
|
||||
case ISR::DivisionError:
|
||||
signal_info.si_signo = SIGFPE;
|
||||
signal_info.si_code = FPE_INTDIV;
|
||||
break;
|
||||
case ISR::SIMDFloatingPointException:
|
||||
case ISR::x87FloatingPointException:
|
||||
signal = SIGFPE;
|
||||
// FIXME: this is probably not correct?
|
||||
signal_info.si_signo = SIGFPE;
|
||||
signal_info.si_code = FPE_FLTDIV;
|
||||
break;
|
||||
case ISR::AlignmentCheck:
|
||||
signal = SIGBUS;
|
||||
signal_info.si_signo = SIGBUS;
|
||||
signal_info.si_code = BUS_ADRALN;
|
||||
break;
|
||||
case ISR::GeneralProtectionFault:
|
||||
// TODO: this assumes unaligned operand but GP can be also caused by
|
||||
// a privileged instruction or uncanonical address in which case
|
||||
// the generated signal should be different
|
||||
signal_info.si_signo = SIGBUS;
|
||||
signal_info.si_code = BUS_ADRALN;
|
||||
break;
|
||||
case ISR::InvalidOpcode:
|
||||
signal = SIGILL;
|
||||
signal_info.si_signo = SIGILL;
|
||||
signal_info.si_code = ILL_ILLOPC;
|
||||
break;
|
||||
case ISR::PageFault:
|
||||
signal = SIGSEGV;
|
||||
signal_info.si_signo = SIGSEGV;
|
||||
if (PageTable::current().get_page_flags(regs->cr2 & PAGE_ADDR_MASK) & PageTable::Flags::Present)
|
||||
signal_info.si_code = SEGV_ACCERR;
|
||||
else
|
||||
signal_info.si_code = SEGV_MAPERR;
|
||||
break;
|
||||
default:
|
||||
dwarnln("Unhandled exception");
|
||||
signal = SIGABRT;
|
||||
signal_info.si_signo = SIGABRT;
|
||||
break;
|
||||
}
|
||||
|
||||
Thread::current().handle_signal(signal);
|
||||
Thread::current().handle_signal(signal_info.si_signo, signal_info);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -321,7 +321,7 @@ namespace Kernel::Input
|
|||
result.type = type;
|
||||
|
||||
BAN::Optional<ACPI::ResourceData> data;
|
||||
ACPI::ResourceParser parser({ crs_obj->node.as.str_buf->bytes, crs_obj->node.as.str_buf->size });
|
||||
ACPI::ResourceParser parser({ crs_obj->node.as.str_buf->bytes, static_cast<size_t>(crs_obj->node.as.str_buf->size) });
|
||||
while ((data = parser.get_next()).has_value())
|
||||
{
|
||||
switch (data->type)
|
||||
|
|
|
|||
|
|
@ -232,4 +232,33 @@ namespace Kernel
|
|||
return BAN::UniqPtr<MemoryRegion>(BAN::move(result));
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> FileBackedRegion::split(size_t offset)
|
||||
{
|
||||
ASSERT(offset && offset < m_size);
|
||||
ASSERT(offset % PAGE_SIZE == 0);
|
||||
|
||||
const bool has_dirty_pages = (m_type == Type::PRIVATE);
|
||||
|
||||
BAN::Vector<paddr_t> dirty_pages;
|
||||
if (has_dirty_pages)
|
||||
{
|
||||
TRY(dirty_pages.resize(BAN::Math::div_round_up<size_t>(m_size - offset, PAGE_SIZE)));
|
||||
for (size_t i = 0; i < dirty_pages.size(); i++)
|
||||
dirty_pages[i] = m_dirty_pages[i + offset / PAGE_SIZE];
|
||||
}
|
||||
|
||||
auto* new_region = new FileBackedRegion(m_inode, m_page_table, m_offset + offset, m_size - offset, m_type, m_flags, m_status_flags);
|
||||
if (new_region == nullptr)
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
new_region->m_vaddr = m_vaddr + offset;
|
||||
new_region->m_shared_data = m_shared_data;
|
||||
new_region->m_dirty_pages = BAN::move(dirty_pages);
|
||||
|
||||
m_size = offset;
|
||||
if (has_dirty_pages)
|
||||
MUST(m_dirty_pages.resize(offset / PAGE_SIZE));
|
||||
|
||||
return BAN::UniqPtr<MemoryRegion>::adopt(new_region);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,6 +82,21 @@ namespace Kernel
|
|||
return BAN::UniqPtr<MemoryRegion>(BAN::move(result));
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> MemoryBackedRegion::split(size_t offset)
|
||||
{
|
||||
ASSERT(offset && offset < m_size);
|
||||
ASSERT(offset % PAGE_SIZE == 0);
|
||||
|
||||
auto* new_region = new MemoryBackedRegion(m_page_table, m_size - offset, m_type, m_flags, m_status_flags);
|
||||
if (new_region == nullptr)
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
new_region->m_vaddr = m_vaddr + offset;
|
||||
|
||||
m_size = offset;
|
||||
|
||||
return BAN::UniqPtr<MemoryRegion>::adopt(new_region);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> MemoryBackedRegion::copy_data_to_region(size_t offset_into_region, const uint8_t* buffer, size_t buffer_size)
|
||||
{
|
||||
ASSERT(offset_into_region + buffer_size <= m_size);
|
||||
|
|
|
|||
|
|
@ -50,6 +50,11 @@ namespace Kernel
|
|||
return true;
|
||||
}
|
||||
|
||||
bool MemoryRegion::is_contained_by(vaddr_t address, size_t size) const
|
||||
{
|
||||
return address <= m_vaddr && m_vaddr + m_size <= address + size;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> MemoryRegion::mprotect(PageTable::flags_t new_page_flags)
|
||||
{
|
||||
if (m_flags == new_page_flags)
|
||||
|
|
|
|||
|
|
@ -87,6 +87,13 @@ namespace Kernel
|
|||
return BAN::UniqPtr<MemoryRegion>(BAN::move(region));
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> SharedMemoryObject::split(size_t offset)
|
||||
{
|
||||
(void)offset;
|
||||
dwarnln("TODO: SharedMemoryObject::split");
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<bool> SharedMemoryObject::allocate_page_containing_impl(vaddr_t address, bool wants_write)
|
||||
{
|
||||
ASSERT(contains(address));
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
#include <BAN/Errors.h>
|
||||
#include <kernel/kprint.h>
|
||||
#include <kernel/BootInfo.h>
|
||||
#include <kernel/Memory/kmalloc.h>
|
||||
|
||||
|
|
@ -153,13 +152,13 @@ void kmalloc_dump_info()
|
|||
{
|
||||
Kernel::SpinLockGuard _(s_kmalloc_lock);
|
||||
|
||||
kprintln("kmalloc: 0x{8H}->0x{8H}", s_kmalloc_info.base, s_kmalloc_info.end);
|
||||
kprintln(" used: 0x{8H}", s_kmalloc_info.used);
|
||||
kprintln(" free: 0x{8H}", s_kmalloc_info.free);
|
||||
dprintln("kmalloc: 0x{8H}->0x{8H}", s_kmalloc_info.base, s_kmalloc_info.end);
|
||||
dprintln(" used: 0x{8H}", s_kmalloc_info.used);
|
||||
dprintln(" free: 0x{8H}", s_kmalloc_info.free);
|
||||
|
||||
kprintln("kmalloc fixed {} byte: 0x{8H}->0x{8H}", sizeof(kmalloc_fixed_info::node), s_kmalloc_fixed_info.base, s_kmalloc_fixed_info.end);
|
||||
kprintln(" used: 0x{8H}", s_kmalloc_fixed_info.used);
|
||||
kprintln(" free: 0x{8H}", s_kmalloc_fixed_info.free);
|
||||
dprintln("kmalloc fixed {} byte: 0x{8H}->0x{8H}", sizeof(kmalloc_fixed_info::node), s_kmalloc_fixed_info.base, s_kmalloc_fixed_info.end);
|
||||
dprintln(" used: 0x{8H}", s_kmalloc_fixed_info.used);
|
||||
dprintln(" free: 0x{8H}", s_kmalloc_fixed_info.free);
|
||||
}
|
||||
|
||||
static bool is_corrupted()
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ namespace Kernel
|
|||
ARPTable::~ARPTable()
|
||||
{
|
||||
if (m_thread)
|
||||
m_thread->add_signal(SIGKILL);
|
||||
m_thread->add_signal(SIGKILL, {});
|
||||
m_thread = nullptr;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ namespace Kernel
|
|||
IPv4Layer::~IPv4Layer()
|
||||
{
|
||||
if (m_thread)
|
||||
m_thread->add_signal(SIGKILL);
|
||||
m_thread->add_signal(SIGKILL, {});
|
||||
m_thread = nullptr;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -190,8 +190,21 @@ namespace Kernel
|
|||
return m_network_layer.bind_socket_to_address(this, address, address_len);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<size_t> TCPSocket::recvfrom_impl(BAN::ByteSpan buffer, sockaddr*, socklen_t*)
|
||||
BAN::ErrorOr<size_t> TCPSocket::recvmsg_impl(msghdr& message, int flags)
|
||||
{
|
||||
flags &= (MSG_OOB | MSG_PEEK | MSG_WAITALL);
|
||||
if (flags != 0)
|
||||
{
|
||||
dwarnln("TODO: recvmsg with flags 0x{H}", flags);
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
}
|
||||
|
||||
if (CMSG_FIRSTHDR(&message))
|
||||
{
|
||||
dwarnln("ignoring recvmsg control message");
|
||||
message.msg_controllen = 0;
|
||||
}
|
||||
|
||||
if (!m_has_connected)
|
||||
return BAN::Error::from_errno(ENOTCONN);
|
||||
|
||||
|
|
@ -202,26 +215,43 @@ namespace Kernel
|
|||
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker, &m_mutex));
|
||||
}
|
||||
|
||||
const uint32_t to_recv = BAN::Math::min<uint32_t>(buffer.size(), m_recv_window.data_size);
|
||||
message.msg_flags = 0;
|
||||
|
||||
size_t total_recv = 0;
|
||||
for (int i = 0; i < message.msg_iovlen; i++)
|
||||
{
|
||||
auto* recv_buffer = reinterpret_cast<uint8_t*>(m_recv_window.buffer->vaddr());
|
||||
memcpy(buffer.data(), recv_buffer, to_recv);
|
||||
|
||||
m_recv_window.data_size -= to_recv;
|
||||
m_recv_window.start_seq += to_recv;
|
||||
if (m_recv_window.data_size > 0)
|
||||
memmove(recv_buffer, recv_buffer + to_recv, m_recv_window.data_size);
|
||||
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);
|
||||
|
||||
return to_recv;
|
||||
total_recv += nrecv;
|
||||
m_recv_window.data_size -= nrecv;
|
||||
m_recv_window.start_seq += nrecv;
|
||||
if (m_recv_window.data_size == 0)
|
||||
break;
|
||||
|
||||
// TODO: use circular buffer to avoid this
|
||||
memmove(recv_buffer, recv_buffer + nrecv, m_recv_window.data_size);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<size_t> TCPSocket::sendto_impl(BAN::ConstByteSpan message, const sockaddr* address, socklen_t address_len)
|
||||
{
|
||||
(void)address;
|
||||
(void)address_len;
|
||||
return total_recv;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<size_t> TCPSocket::sendmsg_impl(const msghdr& message, int flags)
|
||||
{
|
||||
if (flags & MSG_NOSIGNAL)
|
||||
dwarnln("sendmsg ignoring MSG_NOSIGNAL");
|
||||
flags &= (MSG_EOR | MSG_OOB /* | MSG_NOSIGNAL */);
|
||||
if (flags != 0)
|
||||
{
|
||||
dwarnln("TODO: sendmsg with flags 0x{H}", flags);
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
}
|
||||
|
||||
if (CMSG_FIRSTHDR(&message))
|
||||
dwarnln("ignoring sendmsg control message");
|
||||
|
||||
if (address)
|
||||
return BAN::Error::from_errno(EISCONN);
|
||||
if (!m_has_connected)
|
||||
return BAN::Error::from_errno(ENOTCONN);
|
||||
|
||||
|
|
@ -232,17 +262,23 @@ namespace Kernel
|
|||
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker, &m_mutex));
|
||||
}
|
||||
|
||||
const size_t to_send = BAN::Math::min<size_t>(message.size(), m_send_window.buffer->size() - m_send_window.data_size);
|
||||
|
||||
size_t total_sent = 0;
|
||||
for (int i = 0; i < message.msg_iovlen; i++)
|
||||
{
|
||||
auto* buffer = reinterpret_cast<uint8_t*>(m_send_window.buffer->vaddr());
|
||||
memcpy(buffer + m_send_window.data_size, message.data(), to_send);
|
||||
m_send_window.data_size += to_send;
|
||||
auto* send_buffer = reinterpret_cast<uint8_t*>(m_send_window.buffer->vaddr());
|
||||
|
||||
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();
|
||||
|
||||
return to_send;
|
||||
return total_sent;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> TCPSocket::getpeername_impl(sockaddr* address, socklen_t* address_len)
|
||||
|
|
|
|||
|
|
@ -79,6 +79,15 @@ namespace Kernel
|
|||
m_packet_thread_blocker.unblock();
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> UDPSocket::connect_impl(const sockaddr* address, socklen_t address_len)
|
||||
{
|
||||
if (address_len > static_cast<socklen_t>(sizeof(m_peer_address)))
|
||||
address_len = sizeof(m_peer_address);
|
||||
memcpy(&m_peer_address, address, address_len);
|
||||
m_peer_address_len = address_len;
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> UDPSocket::bind_impl(const sockaddr* address, socklen_t address_len)
|
||||
{
|
||||
if (is_bound())
|
||||
|
|
@ -86,8 +95,21 @@ namespace Kernel
|
|||
return m_network_layer.bind_socket_to_address(this, address, address_len);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<size_t> UDPSocket::recvfrom_impl(BAN::ByteSpan buffer, sockaddr* address, socklen_t* address_len)
|
||||
BAN::ErrorOr<size_t> UDPSocket::recvmsg_impl(msghdr& message, int flags)
|
||||
{
|
||||
flags &= (MSG_OOB | MSG_PEEK | MSG_WAITALL);
|
||||
if (flags != 0)
|
||||
{
|
||||
dwarnln("TODO: recvmsg with flags 0x{H}", flags);
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
}
|
||||
|
||||
if (CMSG_FIRSTHDR(&message))
|
||||
{
|
||||
dwarnln("ignoring recvmsg control message");
|
||||
message.msg_controllen = 0;
|
||||
}
|
||||
|
||||
if (!is_bound())
|
||||
{
|
||||
dprintln("No interface bound");
|
||||
|
|
@ -106,14 +128,21 @@ namespace Kernel
|
|||
auto packet_info = m_packets.front();
|
||||
m_packets.pop();
|
||||
|
||||
size_t nread = BAN::Math::min<size_t>(packet_info.packet_size, buffer.size());
|
||||
auto* packet_buffer = reinterpret_cast<uint8_t*>(m_packet_buffer->vaddr());
|
||||
|
||||
message.msg_flags = 0;
|
||||
|
||||
size_t total_recv = 0;
|
||||
for (int i = 0; i < message.msg_iovlen; i++)
|
||||
{
|
||||
const size_t nrecv = BAN::Math::min<size_t>(message.msg_iov[i].iov_len, packet_info.packet_size - total_recv);
|
||||
memcpy(message.msg_iov[i].iov_base, packet_buffer + total_recv, nrecv);
|
||||
total_recv += nrecv;
|
||||
|
||||
if (nrecv < packet_info.packet_size)
|
||||
message.msg_flags |= MSG_TRUNC;
|
||||
}
|
||||
|
||||
uint8_t* packet_buffer = reinterpret_cast<uint8_t*>(m_packet_buffer->vaddr());
|
||||
memcpy(
|
||||
buffer.data(),
|
||||
packet_buffer,
|
||||
nread
|
||||
);
|
||||
memmove(
|
||||
packet_buffer,
|
||||
packet_buffer + packet_info.packet_size,
|
||||
|
|
@ -122,21 +151,67 @@ namespace Kernel
|
|||
|
||||
m_packet_total_size -= packet_info.packet_size;
|
||||
|
||||
if (address && address_len)
|
||||
if (message.msg_name && message.msg_namelen)
|
||||
{
|
||||
if (*address_len > (socklen_t)sizeof(sockaddr_storage))
|
||||
*address_len = sizeof(sockaddr_storage);
|
||||
memcpy(address, &packet_info.sender, *address_len);
|
||||
const size_t namelen = BAN::Math::min<size_t>(message.msg_namelen, sizeof(sockaddr_storage));
|
||||
memcpy(message.msg_name, &packet_info.sender, namelen);
|
||||
message.msg_namelen = namelen;
|
||||
}
|
||||
|
||||
return nread;
|
||||
return total_recv;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<size_t> UDPSocket::sendto_impl(BAN::ConstByteSpan message, const sockaddr* address, socklen_t address_len)
|
||||
BAN::ErrorOr<size_t> UDPSocket::sendmsg_impl(const msghdr& message, int flags)
|
||||
{
|
||||
if (flags & MSG_NOSIGNAL)
|
||||
dwarnln("sendmsg ignoring MSG_NOSIGNAL");
|
||||
flags &= (MSG_EOR | MSG_OOB /* | MSG_NOSIGNAL */);
|
||||
if (flags != 0)
|
||||
{
|
||||
dwarnln("TODO: sendmsg with flags 0x{H}", flags);
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
}
|
||||
|
||||
if (CMSG_FIRSTHDR(&message))
|
||||
dwarnln("ignoring sendmsg control message");
|
||||
|
||||
if (!is_bound())
|
||||
TRY(m_network_layer.bind_socket_to_unused(this, address, address_len));
|
||||
return TRY(m_network_layer.sendto(*this, message, address, address_len));
|
||||
TRY(m_network_layer.bind_socket_to_unused(this, static_cast<sockaddr*>(message.msg_name), message.msg_namelen));
|
||||
|
||||
const size_t total_send_size =
|
||||
[&message]() -> size_t {
|
||||
size_t result = 0;
|
||||
for (int i = 0; i < message.msg_iovlen; i++)
|
||||
result += message.msg_iov[i].iov_len;
|
||||
return result;
|
||||
}();
|
||||
|
||||
BAN::Vector<uint8_t> buffer;
|
||||
TRY(buffer.resize(total_send_size));
|
||||
|
||||
size_t offset = 0;
|
||||
for (int i = 0; i < message.msg_iovlen; i++)
|
||||
{
|
||||
memcpy(buffer.data() + offset, message.msg_iov[i].iov_base, message.msg_iov[i].iov_len);
|
||||
offset += message.msg_iov[i].iov_len;
|
||||
}
|
||||
|
||||
sockaddr* address;
|
||||
socklen_t address_len;
|
||||
if (!message.msg_name || message.msg_namelen == 0)
|
||||
{
|
||||
if (m_peer_address_len == 0)
|
||||
return BAN::Error::from_errno(EDESTADDRREQ);
|
||||
address = reinterpret_cast<sockaddr*>(&m_peer_address);
|
||||
address_len = m_peer_address_len;
|
||||
}
|
||||
else
|
||||
{
|
||||
address = static_cast<sockaddr*>(message.msg_name);
|
||||
address_len = message.msg_namelen;
|
||||
}
|
||||
|
||||
return TRY(m_network_layer.sendto(*this, buffer.span(), address, address_len));
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> UDPSocket::ioctl_impl(int request, void* argument)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include <BAN/HashMap.h>
|
||||
|
||||
#include <kernel/FS/VirtualFileSystem.h>
|
||||
#include <kernel/Lock/SpinLockAsMutex.h>
|
||||
#include <kernel/Lock/LockGuard.h>
|
||||
#include <kernel/Networking/NetworkManager.h>
|
||||
#include <kernel/Networking/UNIX/Socket.h>
|
||||
#include <kernel/Process.h>
|
||||
|
|
@ -22,10 +23,28 @@ namespace Kernel
|
|||
};
|
||||
|
||||
static BAN::HashMap<BAN::RefPtr<Inode>, BAN::WeakPtr<UnixDomainSocket>, UnixSocketHash> s_bound_sockets;
|
||||
static SpinLock s_bound_socket_lock;
|
||||
static Mutex s_bound_socket_lock;
|
||||
|
||||
static constexpr size_t s_packet_buffer_size = 10 * PAGE_SIZE;
|
||||
|
||||
static BAN::ErrorOr<BAN::StringView> validate_sockaddr_un(const sockaddr* address, socklen_t address_len)
|
||||
{
|
||||
if (address_len < static_cast<socklen_t>(sizeof(sa_family_t)))
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
if (address_len > static_cast<socklen_t>(sizeof(sockaddr_un)))
|
||||
address_len = sizeof(sockaddr_un);
|
||||
|
||||
const auto& sockaddr_un = *reinterpret_cast<const struct sockaddr_un*>(address);
|
||||
if (sockaddr_un.sun_family != AF_UNIX)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
|
||||
size_t length = 0;
|
||||
while (length < address_len - sizeof(sa_family_t) && sockaddr_un.sun_path[length])
|
||||
length++;
|
||||
|
||||
return BAN::StringView { sockaddr_un.sun_path, length };
|
||||
}
|
||||
|
||||
// FIXME: why is this using spinlocks instead of mutexes??
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<UnixDomainSocket>> UnixDomainSocket::create(Socket::Type socket_type, const Socket::Info& info)
|
||||
|
|
@ -64,7 +83,7 @@ namespace Kernel
|
|||
{
|
||||
if (is_bound() && !is_bound_to_unused())
|
||||
{
|
||||
SpinLockGuard _(s_bound_socket_lock);
|
||||
LockGuard _(s_bound_socket_lock);
|
||||
s_bound_sockets.remove(m_bound_file.inode);
|
||||
}
|
||||
if (m_info.has<ConnectionInfo>())
|
||||
|
|
@ -105,11 +124,9 @@ namespace Kernel
|
|||
BAN::RefPtr<UnixDomainSocket> pending;
|
||||
|
||||
{
|
||||
SpinLockGuard guard(connection_info.pending_lock);
|
||||
|
||||
SpinLockGuardAsMutex smutex(guard);
|
||||
LockGuard _(connection_info.pending_lock);
|
||||
while (connection_info.pending_connections.empty())
|
||||
TRY(Thread::current().block_or_eintr_indefinite(connection_info.pending_thread_blocker, &smutex));
|
||||
TRY(Thread::current().block_or_eintr_indefinite(connection_info.pending_thread_blocker, &connection_info.pending_lock));
|
||||
|
||||
pending = connection_info.pending_connections.front();
|
||||
connection_info.pending_connections.pop();
|
||||
|
|
@ -146,15 +163,11 @@ namespace Kernel
|
|||
|
||||
BAN::ErrorOr<void> UnixDomainSocket::connect_impl(const sockaddr* address, socklen_t address_len)
|
||||
{
|
||||
if (address_len != sizeof(sockaddr_un))
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
auto& sockaddr_un = *reinterpret_cast<const struct sockaddr_un*>(address);
|
||||
if (sockaddr_un.sun_family != AF_UNIX)
|
||||
return BAN::Error::from_errno(EAFNOSUPPORT);
|
||||
const auto sun_path = TRY(validate_sockaddr_un(address, address_len));
|
||||
if (!is_bound())
|
||||
TRY(m_bound_file.canonical_path.push_back('X'));
|
||||
|
||||
auto absolute_path = TRY(Process::current().absolute_path_of(sockaddr_un.sun_path));
|
||||
auto absolute_path = TRY(Process::current().absolute_path_of(sun_path));
|
||||
auto file = TRY(VirtualFileSystem::get().file_from_absolute_path(
|
||||
Process::current().root_file().inode,
|
||||
Process::current().credentials(),
|
||||
|
|
@ -165,7 +178,7 @@ namespace Kernel
|
|||
BAN::RefPtr<UnixDomainSocket> target;
|
||||
|
||||
{
|
||||
SpinLockGuard _(s_bound_socket_lock);
|
||||
LockGuard _(s_bound_socket_lock);
|
||||
auto it = s_bound_sockets.find(file.inode);
|
||||
if (it == s_bound_sockets.end())
|
||||
return BAN::Error::from_errno(ECONNREFUSED);
|
||||
|
|
@ -196,7 +209,7 @@ namespace Kernel
|
|||
{
|
||||
auto& target_info = target->m_info.get<ConnectionInfo>();
|
||||
|
||||
SpinLockGuard guard(target_info.pending_lock);
|
||||
LockGuard _(target_info.pending_lock);
|
||||
|
||||
if (target_info.pending_connections.size() < target_info.pending_connections.capacity())
|
||||
{
|
||||
|
|
@ -205,8 +218,7 @@ namespace Kernel
|
|||
break;
|
||||
}
|
||||
|
||||
SpinLockGuardAsMutex smutex(guard);
|
||||
TRY(Thread::current().block_or_eintr_indefinite(target_info.pending_thread_blocker, &smutex));
|
||||
TRY(Thread::current().block_or_eintr_indefinite(target_info.pending_thread_blocker, &target_info.pending_lock));
|
||||
}
|
||||
|
||||
target->epoll_notify(EPOLLIN);
|
||||
|
|
@ -236,21 +248,16 @@ namespace Kernel
|
|||
{
|
||||
if (is_bound())
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
if (address_len != sizeof(sockaddr_un))
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
auto& sockaddr_un = *reinterpret_cast<const struct sockaddr_un*>(address);
|
||||
if (sockaddr_un.sun_family != AF_UNIX)
|
||||
return BAN::Error::from_errno(EAFNOSUPPORT);
|
||||
|
||||
auto bind_path = BAN::StringView(sockaddr_un.sun_path);
|
||||
if (bind_path.empty())
|
||||
const auto sun_path = TRY(validate_sockaddr_un(address, address_len));
|
||||
if (sun_path.empty())
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
|
||||
// FIXME: This feels sketchy
|
||||
auto parent_file = bind_path.front() == '/'
|
||||
auto parent_file = sun_path.front() == '/'
|
||||
? TRY(Process::current().root_file().clone())
|
||||
: TRY(Process::current().working_directory().clone());
|
||||
if (auto ret = Process::current().create_file_or_dir(AT_FDCWD, bind_path.data(), 0755 | S_IFSOCK); ret.is_error())
|
||||
if (auto ret = Process::current().create_file_or_dir(AT_FDCWD, sun_path.data(), 0755 | S_IFSOCK); ret.is_error())
|
||||
{
|
||||
if (ret.error().get_error_code() == EEXIST)
|
||||
return BAN::Error::from_errno(EADDRINUSE);
|
||||
|
|
@ -260,11 +267,11 @@ namespace Kernel
|
|||
Process::current().root_file().inode,
|
||||
parent_file,
|
||||
Process::current().credentials(),
|
||||
bind_path,
|
||||
sun_path,
|
||||
O_RDWR
|
||||
));
|
||||
|
||||
SpinLockGuard _(s_bound_socket_lock);
|
||||
LockGuard _(s_bound_socket_lock);
|
||||
if (s_bound_sockets.contains(file.inode))
|
||||
return BAN::Error::from_errno(EADDRINUSE);
|
||||
TRY(s_bound_sockets.emplace(file.inode, TRY(get_weak_ptr())));
|
||||
|
|
@ -287,21 +294,25 @@ namespace Kernel
|
|||
}
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> UnixDomainSocket::add_packet(BAN::ConstByteSpan packet)
|
||||
BAN::ErrorOr<void> UnixDomainSocket::add_packet(const msghdr& packet, PacketInfo&& packet_info)
|
||||
{
|
||||
SpinLockGuard guard(m_packet_lock);
|
||||
while (m_packet_sizes.full() || m_packet_size_total + packet.size() > s_packet_buffer_size)
|
||||
{
|
||||
SpinLockGuardAsMutex smutex(guard);
|
||||
TRY(Thread::current().block_or_eintr_indefinite(m_packet_thread_blocker, &smutex));
|
||||
}
|
||||
LockGuard _(m_packet_lock);
|
||||
|
||||
while (m_packet_infos.full() || m_packet_size_total + packet_info.size > s_packet_buffer_size)
|
||||
TRY(Thread::current().block_or_eintr_indefinite(m_packet_thread_blocker, &m_packet_lock));
|
||||
|
||||
uint8_t* packet_buffer = reinterpret_cast<uint8_t*>(m_packet_buffer->vaddr() + m_packet_size_total);
|
||||
memcpy(packet_buffer, packet.data(), packet.size());
|
||||
m_packet_size_total += packet.size();
|
||||
|
||||
if (!is_streaming())
|
||||
m_packet_sizes.push(packet.size());
|
||||
size_t offset = 0;
|
||||
for (int i = 0; i < packet.msg_iovlen; i++)
|
||||
{
|
||||
memcpy(packet_buffer + offset, packet.msg_iov[i].iov_base, packet.msg_iov[i].iov_len);
|
||||
offset += packet.msg_iov[i].iov_len;
|
||||
}
|
||||
|
||||
ASSERT(offset == packet_info.size);
|
||||
m_packet_size_total += packet_info.size;
|
||||
m_packet_infos.emplace(BAN::move(packet_info));
|
||||
|
||||
m_packet_thread_blocker.unblock();
|
||||
|
||||
|
|
@ -315,10 +326,10 @@ namespace Kernel
|
|||
if (m_info.has<ConnectionInfo>())
|
||||
{
|
||||
auto& connection_info = m_info.get<ConnectionInfo>();
|
||||
if (connection_info.listening)
|
||||
return !connection_info.pending_connections.empty();
|
||||
if (connection_info.target_closed)
|
||||
return true;
|
||||
if (!connection_info.pending_connections.empty())
|
||||
return true;
|
||||
if (!connection_info.connection)
|
||||
return false;
|
||||
}
|
||||
|
|
@ -331,7 +342,13 @@ namespace Kernel
|
|||
if (m_info.has<ConnectionInfo>())
|
||||
{
|
||||
auto& connection_info = m_info.get<ConnectionInfo>();
|
||||
return connection_info.connection.valid();
|
||||
auto connection = connection_info.connection.lock();
|
||||
if (!connection)
|
||||
return false;
|
||||
if (connection->m_packet_infos.full())
|
||||
return false;
|
||||
if (connection->m_packet_size_total >= s_packet_buffer_size)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -348,27 +365,257 @@ namespace Kernel
|
|||
return false;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<size_t> UnixDomainSocket::sendto_impl(BAN::ConstByteSpan message, const sockaddr* address, socklen_t address_len)
|
||||
BAN::ErrorOr<size_t> UnixDomainSocket::recvmsg_impl(msghdr& message, int flags)
|
||||
{
|
||||
if (message.size() > s_packet_buffer_size)
|
||||
flags &= (MSG_OOB | MSG_PEEK | MSG_WAITALL);
|
||||
if (flags != 0)
|
||||
{
|
||||
dwarnln("TODO: recvmsg with flags 0x{H}", flags);
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
}
|
||||
|
||||
LockGuard _(m_packet_lock);
|
||||
while (m_packet_size_total == 0)
|
||||
{
|
||||
if (m_info.has<ConnectionInfo>())
|
||||
{
|
||||
auto& connection_info = m_info.get<ConnectionInfo>();
|
||||
bool expected = true;
|
||||
if (connection_info.target_closed.compare_exchange(expected, false))
|
||||
return 0;
|
||||
if (!connection_info.connection)
|
||||
return BAN::Error::from_errno(ENOTCONN);
|
||||
}
|
||||
|
||||
TRY(Thread::current().block_or_eintr_indefinite(m_packet_thread_blocker, &m_packet_lock));
|
||||
}
|
||||
|
||||
auto* cheader = CMSG_FIRSTHDR(&message);
|
||||
if (cheader != nullptr)
|
||||
cheader->cmsg_len = message.msg_controllen;
|
||||
size_t cheader_len = 0;
|
||||
|
||||
uint8_t* packet_buffer = reinterpret_cast<uint8_t*>(m_packet_buffer->vaddr());
|
||||
|
||||
message.msg_flags = 0;
|
||||
|
||||
int iov_index = 0;
|
||||
size_t iov_offset = 0;
|
||||
size_t total_recv = 0;
|
||||
|
||||
while (!m_packet_infos.empty() && iov_index < message.msg_iovlen)
|
||||
{
|
||||
auto& packet_info = m_packet_infos.front();
|
||||
|
||||
auto fds_to_open = BAN::move(packet_info.fds);
|
||||
auto ucred_to_recv = BAN::move(packet_info.ucred);
|
||||
const bool had_ancillary_data = !fds_to_open.empty() || ucred_to_recv.has_value();
|
||||
|
||||
if (!fds_to_open.empty()) do
|
||||
{
|
||||
if (cheader == nullptr)
|
||||
{
|
||||
dwarnln("no space to receive {} fds", fds_to_open.size());
|
||||
message.msg_flags |= MSG_CTRUNC;
|
||||
break;
|
||||
}
|
||||
|
||||
const size_t max_fd_count = (cheader->cmsg_len - sizeof(cmsghdr)) / sizeof(int);
|
||||
if (max_fd_count < fds_to_open.size())
|
||||
message.msg_flags |= MSG_CTRUNC;
|
||||
|
||||
const size_t fd_count = BAN::Math::min(fds_to_open.size(), max_fd_count);
|
||||
const size_t fds_opened = Process::current().open_file_descriptor_set().open_all_fd_wrappers(fds_to_open.span().slice(0, fd_count));
|
||||
|
||||
auto* fd_data = reinterpret_cast<int*>(CMSG_DATA(cheader));
|
||||
for (size_t i = 0; i < fds_opened; i++)
|
||||
fd_data[i] = fds_to_open[i].fd();
|
||||
|
||||
const size_t header_length = CMSG_LEN(fds_opened * sizeof(int));
|
||||
cheader->cmsg_level = SOL_SOCKET;
|
||||
cheader->cmsg_type = SCM_RIGHTS;
|
||||
cheader->cmsg_len = header_length;
|
||||
cheader = CMSG_NXTHDR(&message, cheader);
|
||||
if (cheader != nullptr)
|
||||
cheader->cmsg_len = message.msg_controllen - header_length;
|
||||
cheader_len += header_length;
|
||||
} while (false);
|
||||
|
||||
if (ucred_to_recv.has_value()) do
|
||||
{
|
||||
if (cheader == nullptr || cheader->cmsg_len - sizeof(cmsghdr) < sizeof(struct ucred))
|
||||
{
|
||||
dwarnln("no space to receive credentials");
|
||||
message.msg_flags |= MSG_CTRUNC;
|
||||
break;
|
||||
}
|
||||
|
||||
*reinterpret_cast<struct ucred*>(CMSG_DATA(cheader)) = ucred_to_recv.value();
|
||||
|
||||
const size_t header_length = CMSG_LEN(sizeof(struct ucred));
|
||||
cheader->cmsg_level = SOL_SOCKET;
|
||||
cheader->cmsg_type = SCM_CREDENTIALS;
|
||||
cheader->cmsg_len = header_length;
|
||||
cheader = CMSG_NXTHDR(&message, cheader);
|
||||
if (cheader != nullptr)
|
||||
cheader->cmsg_len = message.msg_controllen - header_length;
|
||||
cheader_len += header_length;
|
||||
} while (false);
|
||||
|
||||
size_t packet_received = 0;
|
||||
while (iov_index < message.msg_iovlen && packet_received < packet_info.size)
|
||||
{
|
||||
auto& iov = message.msg_iov[iov_index];
|
||||
uint8_t* iov_base = static_cast<uint8_t*>(iov.iov_base);
|
||||
|
||||
const size_t nrecv = BAN::Math::min<size_t>(iov.iov_len - iov_offset, packet_info.size - packet_received);
|
||||
memcpy(iov_base + iov_offset, packet_buffer + packet_received, nrecv);
|
||||
|
||||
packet_received += nrecv;
|
||||
|
||||
iov_offset += nrecv;
|
||||
if (iov_offset >= iov.iov_len)
|
||||
{
|
||||
iov_offset = 0;
|
||||
iov_index++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_streaming() && packet_received < packet_info.size)
|
||||
message.msg_flags |= MSG_TRUNC;
|
||||
|
||||
const size_t to_discard = is_streaming() ? packet_received : packet_info.size;
|
||||
|
||||
packet_info.size -= to_discard;
|
||||
if (packet_info.size == 0)
|
||||
m_packet_infos.pop();
|
||||
|
||||
// FIXME: get rid of this memmove :)
|
||||
memmove(packet_buffer, packet_buffer + to_discard, m_packet_size_total - to_discard);
|
||||
m_packet_size_total -= to_discard;
|
||||
|
||||
total_recv += packet_received;
|
||||
|
||||
// on linux ancillary data is a barrier on stream sockets, lets do the same
|
||||
if (!is_streaming() || had_ancillary_data)
|
||||
break;
|
||||
}
|
||||
|
||||
message.msg_controllen = cheader_len;
|
||||
|
||||
m_packet_thread_blocker.unblock();
|
||||
|
||||
epoll_notify(EPOLLOUT);
|
||||
|
||||
return total_recv;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<size_t> UnixDomainSocket::sendmsg_impl(const msghdr& message, int flags)
|
||||
{
|
||||
if (flags & MSG_NOSIGNAL)
|
||||
dwarnln("sendmsg ignoring MSG_NOSIGNAL");
|
||||
flags &= (MSG_EOR | MSG_OOB /* | MSG_NOSIGNAL */);
|
||||
if (flags != 0)
|
||||
{
|
||||
dwarnln("TODO: sendmsg with flags 0x{H}", flags);
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
}
|
||||
|
||||
const size_t total_message_size =
|
||||
[&message]() -> size_t {
|
||||
size_t result = 0;
|
||||
for (int i = 0; i < message.msg_iovlen; i++)
|
||||
result += message.msg_iov[i].iov_len;
|
||||
return result;
|
||||
}();
|
||||
|
||||
if (total_message_size > s_packet_buffer_size)
|
||||
return BAN::Error::from_errno(ENOBUFS);
|
||||
|
||||
PacketInfo packet_info {
|
||||
.size = total_message_size,
|
||||
.fds = {},
|
||||
.ucred = {},
|
||||
};
|
||||
|
||||
for (const auto* header = CMSG_FIRSTHDR(&message); header; header = CMSG_NXTHDR(&message, header))
|
||||
{
|
||||
if (header->cmsg_level != SOL_SOCKET)
|
||||
{
|
||||
dwarnln("ignoring control message with level {}", header->cmsg_level);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (header->cmsg_type)
|
||||
{
|
||||
case SCM_RIGHTS:
|
||||
{
|
||||
if (!packet_info.fds.empty())
|
||||
{
|
||||
dwarnln("multiple SCM_RIGHTS in one sendmsg");
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
}
|
||||
|
||||
const auto* fd_data = reinterpret_cast<const int*>(CMSG_DATA(header));
|
||||
const size_t fd_count = (header->cmsg_len - sizeof(cmsghdr)) / sizeof(int);
|
||||
for (size_t i = 0; i < fd_count; i++)
|
||||
TRY(packet_info.fds.push_back(TRY(Process::current().open_file_descriptor_set().get_fd_wrapper(fd_data[i]))));
|
||||
break;
|
||||
}
|
||||
case SCM_CREDENTIALS:
|
||||
{
|
||||
if (packet_info.ucred.has_value())
|
||||
{
|
||||
dwarnln("multiple SCM_CREDENTIALS in one sendmsg");
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
}
|
||||
|
||||
if (header->cmsg_len - sizeof(cmsghdr) < sizeof(struct ucred))
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
const ucred* ucred = reinterpret_cast<const struct ucred*>(CMSG_DATA(header));
|
||||
|
||||
const bool is_valid_ucred =
|
||||
[ucred]() -> bool
|
||||
{
|
||||
const auto& creds = Process::current().credentials();
|
||||
if (creds.is_superuser())
|
||||
return true;
|
||||
if (ucred->pid != Process::current().pid())
|
||||
return false;
|
||||
if (ucred->uid != creds.ruid() && ucred->uid != creds.euid() && ucred->uid != creds.suid())
|
||||
return false;
|
||||
if (ucred->gid != creds.rgid() && !creds.has_egid(ucred->gid) && ucred->gid != creds.sgid())
|
||||
return false;
|
||||
return true;
|
||||
}();
|
||||
|
||||
if (!is_valid_ucred)
|
||||
return BAN::Error::from_errno(EPERM);
|
||||
|
||||
packet_info.ucred = *ucred;
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
dwarnln("ignoring control message with type {}", header->cmsg_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_info.has<ConnectionInfo>())
|
||||
{
|
||||
auto& connection_info = m_info.get<ConnectionInfo>();
|
||||
if (address)
|
||||
return BAN::Error::from_errno(EISCONN);
|
||||
auto target = connection_info.connection.lock();
|
||||
if (!target)
|
||||
return BAN::Error::from_errno(ENOTCONN);
|
||||
TRY(target->add_packet(message));
|
||||
return message.size();
|
||||
TRY(target->add_packet(message, BAN::move(packet_info)));
|
||||
return total_message_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
BAN::RefPtr<Inode> target_inode;
|
||||
|
||||
if (!address)
|
||||
if (!message.msg_name || message.msg_namelen == 0)
|
||||
{
|
||||
auto& connectionless_info = m_info.get<ConnectionlessInfo>();
|
||||
if (connectionless_info.peer_address.empty())
|
||||
|
|
@ -384,13 +631,8 @@ namespace Kernel
|
|||
}
|
||||
else
|
||||
{
|
||||
if (address_len != sizeof(sockaddr_un))
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
auto& sockaddr_un = *reinterpret_cast<const struct sockaddr_un*>(address);
|
||||
if (sockaddr_un.sun_family != AF_UNIX)
|
||||
return BAN::Error::from_errno(EAFNOSUPPORT);
|
||||
|
||||
auto absolute_path = TRY(Process::current().absolute_path_of(sockaddr_un.sun_path));
|
||||
const auto sun_path = TRY(validate_sockaddr_un(static_cast<sockaddr*>(message.msg_name), message.msg_namelen));
|
||||
auto absolute_path = TRY(Process::current().absolute_path_of(sun_path));
|
||||
target_inode = TRY(VirtualFileSystem::get().file_from_absolute_path(
|
||||
Process::current().root_file().inode,
|
||||
Process::current().credentials(),
|
||||
|
|
@ -399,59 +641,23 @@ namespace Kernel
|
|||
)).inode;
|
||||
}
|
||||
|
||||
SpinLockGuard _(s_bound_socket_lock);
|
||||
BAN::RefPtr<UnixDomainSocket> target;
|
||||
{
|
||||
LockGuard _(s_bound_socket_lock);
|
||||
auto it = s_bound_sockets.find(target_inode);
|
||||
if (it == s_bound_sockets.end())
|
||||
return BAN::Error::from_errno(EDESTADDRREQ);
|
||||
auto target = it->value.lock();
|
||||
target = it->value.lock();
|
||||
}
|
||||
|
||||
if (!target)
|
||||
return BAN::Error::from_errno(EDESTADDRREQ);
|
||||
TRY(target->add_packet(message));
|
||||
return message.size();
|
||||
TRY(target->add_packet(message, BAN::move(packet_info)));
|
||||
|
||||
return total_message_size;
|
||||
}
|
||||
}
|
||||
|
||||
BAN::ErrorOr<size_t> UnixDomainSocket::recvfrom_impl(BAN::ByteSpan buffer, sockaddr*, socklen_t*)
|
||||
{
|
||||
SpinLockGuard guard(m_packet_lock);
|
||||
while (m_packet_size_total == 0)
|
||||
{
|
||||
if (m_info.has<ConnectionInfo>())
|
||||
{
|
||||
auto& connection_info = m_info.get<ConnectionInfo>();
|
||||
bool expected = true;
|
||||
if (connection_info.target_closed.compare_exchange(expected, false))
|
||||
return 0;
|
||||
if (!connection_info.connection)
|
||||
return BAN::Error::from_errno(ENOTCONN);
|
||||
}
|
||||
|
||||
SpinLockGuardAsMutex smutex(guard);
|
||||
TRY(Thread::current().block_or_eintr_indefinite(m_packet_thread_blocker, &smutex));
|
||||
}
|
||||
|
||||
uint8_t* packet_buffer = reinterpret_cast<uint8_t*>(m_packet_buffer->vaddr());
|
||||
|
||||
size_t nread = 0;
|
||||
if (is_streaming())
|
||||
nread = BAN::Math::min(buffer.size(), m_packet_size_total);
|
||||
else
|
||||
{
|
||||
nread = BAN::Math::min(buffer.size(), m_packet_sizes.front());
|
||||
m_packet_sizes.pop();
|
||||
}
|
||||
|
||||
memcpy(buffer.data(), packet_buffer, nread);
|
||||
memmove(packet_buffer, packet_buffer + nread, m_packet_size_total - nread);
|
||||
m_packet_size_total -= nread;
|
||||
|
||||
m_packet_thread_blocker.unblock();
|
||||
|
||||
epoll_notify(EPOLLOUT);
|
||||
|
||||
return nread;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> UnixDomainSocket::getpeername_impl(sockaddr* address, socklen_t* address_len)
|
||||
{
|
||||
if (!m_info.has<ConnectionInfo>())
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ namespace Kernel
|
|||
return fildes;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<int> OpenFileDescriptorSet::fcntl(int fd, int cmd, int extra)
|
||||
BAN::ErrorOr<int> OpenFileDescriptorSet::fcntl(int fd, int cmd, uintptr_t extra)
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
|
||||
|
|
@ -424,7 +424,24 @@ namespace Kernel
|
|||
}
|
||||
|
||||
if (inode->mode().ifsock())
|
||||
return recvfrom(fd, buffer, nullptr, nullptr);
|
||||
{
|
||||
iovec iov {
|
||||
.iov_base = buffer.data(),
|
||||
.iov_len = buffer.size(),
|
||||
};
|
||||
|
||||
msghdr message {
|
||||
.msg_name = nullptr,
|
||||
.msg_namelen = 0,
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1,
|
||||
.msg_control = nullptr,
|
||||
.msg_controllen = 0,
|
||||
.msg_flags = 0,
|
||||
};
|
||||
|
||||
return recvmsg(fd, message, 0);
|
||||
}
|
||||
|
||||
size_t nread;
|
||||
{
|
||||
|
|
@ -461,14 +478,31 @@ namespace Kernel
|
|||
}
|
||||
|
||||
if (inode->mode().ifsock())
|
||||
return sendto(fd, buffer, nullptr, 0);
|
||||
{
|
||||
iovec iov {
|
||||
.iov_base = const_cast<uint8_t*>(buffer.data()),
|
||||
.iov_len = buffer.size(),
|
||||
};
|
||||
|
||||
msghdr message {
|
||||
.msg_name = nullptr,
|
||||
.msg_namelen = 0,
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1,
|
||||
.msg_control = nullptr,
|
||||
.msg_controllen = 0,
|
||||
.msg_flags = 0,
|
||||
};
|
||||
|
||||
return sendmsg(fd, message, 0);
|
||||
}
|
||||
|
||||
size_t nwrite;
|
||||
{
|
||||
LockGuard _(inode->m_mutex);
|
||||
if (inode->has_error())
|
||||
{
|
||||
Thread::current().add_signal(SIGPIPE);
|
||||
Thread::current().add_signal(SIGPIPE, {});
|
||||
return BAN::Error::from_errno(EPIPE);
|
||||
}
|
||||
if (is_nonblock && !inode->can_write())
|
||||
|
|
@ -515,7 +549,7 @@ namespace Kernel
|
|||
}
|
||||
}
|
||||
|
||||
BAN::ErrorOr<size_t> OpenFileDescriptorSet::recvfrom(int fd, BAN::ByteSpan buffer, sockaddr* address, socklen_t* address_len)
|
||||
BAN::ErrorOr<size_t> OpenFileDescriptorSet::recvmsg(int fd, msghdr& message, int flags)
|
||||
{
|
||||
BAN::RefPtr<Inode> inode;
|
||||
bool is_nonblock;
|
||||
|
|
@ -533,10 +567,10 @@ namespace Kernel
|
|||
LockGuard _(inode->m_mutex);
|
||||
if (is_nonblock && !inode->can_read())
|
||||
return BAN::Error::from_errno(EWOULDBLOCK);
|
||||
return inode->recvfrom(buffer, address, address_len);
|
||||
return inode->recvmsg(message, flags);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<size_t> OpenFileDescriptorSet::sendto(int fd, BAN::ConstByteSpan buffer, const sockaddr* address, socklen_t address_len)
|
||||
BAN::ErrorOr<size_t> OpenFileDescriptorSet::sendmsg(int fd, const msghdr& message, int flags)
|
||||
{
|
||||
BAN::RefPtr<Inode> inode;
|
||||
bool is_nonblock;
|
||||
|
|
@ -554,12 +588,12 @@ namespace Kernel
|
|||
LockGuard _(inode->m_mutex);
|
||||
if (inode->has_hungup())
|
||||
{
|
||||
Thread::current().add_signal(SIGPIPE);
|
||||
Thread::current().add_signal(SIGPIPE, {});
|
||||
return BAN::Error::from_errno(EPIPE);
|
||||
}
|
||||
if (is_nonblock && !inode->can_write())
|
||||
return BAN::Error::from_errno(EWOULDBLOCK);
|
||||
return inode->sendto(buffer, address, address_len);
|
||||
return inode->sendmsg(message, flags);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<VirtualFileSystem::File> OpenFileDescriptorSet::file_of(int fd) const
|
||||
|
|
@ -625,4 +659,66 @@ namespace Kernel
|
|||
return BAN::Error::from_errno(EMFILE);
|
||||
}
|
||||
|
||||
using FDWrapper = OpenFileDescriptorSet::FDWrapper;
|
||||
|
||||
FDWrapper::FDWrapper(BAN::RefPtr<OpenFileDescription> description)
|
||||
: m_description(description)
|
||||
{
|
||||
if (m_description)
|
||||
m_description->file.inode->on_clone(m_description->status_flags);
|
||||
}
|
||||
|
||||
FDWrapper::~FDWrapper()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
FDWrapper& FDWrapper::operator=(const FDWrapper& other)
|
||||
{
|
||||
clear();
|
||||
m_description = other.m_description;
|
||||
if (m_description)
|
||||
m_description->file.inode->on_clone(m_description->status_flags);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FDWrapper& FDWrapper::operator=(FDWrapper&& other)
|
||||
{
|
||||
clear();
|
||||
m_description = BAN::move(other.m_description);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void FDWrapper::clear()
|
||||
{
|
||||
if (m_description)
|
||||
m_description->file.inode->on_close(m_description->status_flags);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<FDWrapper> OpenFileDescriptorSet::get_fd_wrapper(int fd)
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
TRY(validate_fd(fd));
|
||||
return FDWrapper { m_open_files[fd].description };
|
||||
}
|
||||
|
||||
size_t OpenFileDescriptorSet::open_all_fd_wrappers(BAN::Span<FDWrapper> fd_wrappers)
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
|
||||
for (size_t i = 0; i < fd_wrappers.size(); i++)
|
||||
{
|
||||
auto fd_or_error = get_free_fd();
|
||||
if (fd_or_error.is_error())
|
||||
return i;
|
||||
|
||||
const int fd = fd_or_error.release_value();
|
||||
m_open_files[fd].description = BAN::move(fd_wrappers[i].m_description);
|
||||
m_open_files[fd].descriptor_flags = 0;
|
||||
fd_wrappers[i].m_fd = fd;
|
||||
}
|
||||
|
||||
return fd_wrappers.size();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ namespace Kernel
|
|||
if (executable.master_tls.has_value())
|
||||
{
|
||||
auto tls_result = TRY(process->initialize_thread_local_storage(process->page_table(), *executable.master_tls));
|
||||
TRY(process->m_mapped_regions.emplace_back(BAN::move(tls_result.region)));
|
||||
TRY(process->add_mapped_region(BAN::move(tls_result.region)));
|
||||
tls_addr = tls_result.addr;
|
||||
}
|
||||
|
||||
|
|
@ -173,7 +173,15 @@ namespace Kernel
|
|||
auxiliary_vector.span()
|
||||
));
|
||||
if (tls_addr.has_value())
|
||||
thread->set_tls(*tls_addr);
|
||||
{
|
||||
#if ARCH(x86_64)
|
||||
thread->set_fsbase(*tls_addr);
|
||||
#elif ARCH(i686)
|
||||
thread->set_gsbase(*tls_addr);
|
||||
#else
|
||||
#error
|
||||
#endif
|
||||
}
|
||||
|
||||
process->add_thread(thread);
|
||||
process->register_to_scheduler();
|
||||
|
|
@ -305,7 +313,17 @@ namespace Kernel
|
|||
|
||||
child.status = __WGENEXITCODE(status, signal);
|
||||
|
||||
parent_process->add_pending_signal(SIGCHLD);
|
||||
parent_process->add_pending_signal(SIGCHLD, {
|
||||
.si_signo = SIGCHLD,
|
||||
.si_code = signal ? CLD_KILLED : CLD_EXITED,
|
||||
.si_errno = 0,
|
||||
.si_pid = pid(),
|
||||
.si_uid = m_credentials.ruid(),
|
||||
.si_addr = nullptr,
|
||||
.si_status = __WGENEXITCODE(status, signal),
|
||||
.si_band = 0,
|
||||
.si_value = {},
|
||||
});
|
||||
if (!parent_process->m_threads.empty())
|
||||
Processor::scheduler().unblock_thread(parent_process->m_threads.front());
|
||||
|
||||
|
|
@ -320,7 +338,7 @@ namespace Kernel
|
|||
LockGuard _(m_process_lock);
|
||||
for (auto* thread : m_threads)
|
||||
if (thread != &Thread::current())
|
||||
thread->add_signal(SIGKILL);
|
||||
thread->add_signal(SIGKILL, {});
|
||||
}
|
||||
|
||||
while (m_threads.size() > 1)
|
||||
|
|
@ -397,6 +415,33 @@ namespace Kernel
|
|||
return result;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Process::add_mapped_region(BAN::UniqPtr<MemoryRegion>&& region)
|
||||
{
|
||||
const size_t index = find_mapped_region(region->vaddr());
|
||||
TRY(m_mapped_regions.insert(index, BAN::move(region)));
|
||||
return {};
|
||||
}
|
||||
|
||||
size_t Process::find_mapped_region(vaddr_t address) const
|
||||
{
|
||||
size_t l = 0, r = m_mapped_regions.size();
|
||||
|
||||
while (l < r)
|
||||
{
|
||||
const size_t mid = (l + r) / 2;
|
||||
|
||||
if (m_mapped_regions[mid]->contains(address))
|
||||
return mid;
|
||||
|
||||
if (m_mapped_regions[mid]->vaddr() < address)
|
||||
l = mid + 1;
|
||||
else
|
||||
r = mid;
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
size_t Process::proc_meminfo(off_t offset, BAN::ByteSpan buffer) const
|
||||
{
|
||||
ASSERT(offset >= 0);
|
||||
|
|
@ -463,7 +508,15 @@ namespace Kernel
|
|||
return read_from_vec_of_str(m_environ, offset, buffer);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::String> Process::proc_executable() const
|
||||
BAN::ErrorOr<BAN::String> Process::proc_cwd() const
|
||||
{
|
||||
LockGuard _(m_process_lock);
|
||||
BAN::String result;
|
||||
TRY(result.append(m_working_directory.canonical_path));
|
||||
return result;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::String> Process::proc_exe() const
|
||||
{
|
||||
LockGuard _(m_process_lock);
|
||||
BAN::String result;
|
||||
|
|
@ -487,7 +540,7 @@ namespace Kernel
|
|||
{
|
||||
ASSERT(m_process_lock.is_locked());
|
||||
|
||||
if (path[0] == '\0')
|
||||
if (path && path[0] == '\0')
|
||||
return BAN::Error::from_errno(ENOENT);
|
||||
|
||||
auto relative_parent = TRY(find_relative_parent(fd, path));
|
||||
|
|
@ -730,7 +783,13 @@ namespace Kernel
|
|||
{
|
||||
auto tls_result = TRY(initialize_thread_local_storage(*new_page_table, *executable.master_tls));
|
||||
TRY(new_mapped_regions.emplace_back(BAN::move(tls_result.region)));
|
||||
new_thread->set_tls(tls_result.addr);
|
||||
#if ARCH(x86_64)
|
||||
new_thread->set_fsbase(tls_result.addr);
|
||||
#elif ARCH(i686)
|
||||
new_thread->set_gsbase(tls_result.addr);
|
||||
#else
|
||||
#error
|
||||
#endif
|
||||
}
|
||||
|
||||
// NOTE: this is done before disabling interrupts and moving the threads as
|
||||
|
|
@ -1013,7 +1072,17 @@ namespace Kernel
|
|||
if (current_ns < process->m_alarm_wake_time_ns)
|
||||
break;
|
||||
|
||||
process->add_pending_signal(SIGALRM);
|
||||
process->add_pending_signal(SIGALRM, {
|
||||
.si_signo = SIGALRM,
|
||||
.si_code = SI_TIMER,
|
||||
.si_errno = 0,
|
||||
.si_pid = 0,
|
||||
.si_uid = 0,
|
||||
.si_addr = nullptr,
|
||||
.si_status = 0,
|
||||
.si_band = 0,
|
||||
.si_value = {},
|
||||
});
|
||||
|
||||
ASSERT(!process->m_threads.empty());
|
||||
Processor::scheduler().unblock_thread(process->m_threads.front());
|
||||
|
|
@ -1077,14 +1146,15 @@ namespace Kernel
|
|||
if (Thread::current().userspace_stack().contains(address))
|
||||
return Thread::current().userspace_stack().allocate_page_for_demand_paging(address);
|
||||
|
||||
for (auto& region : m_mapped_regions)
|
||||
{
|
||||
if (!region->contains(address))
|
||||
continue;
|
||||
return region->allocate_page_containing(address, wants_write);
|
||||
}
|
||||
|
||||
const size_t index = find_mapped_region(address);
|
||||
if (index >= m_mapped_regions.size())
|
||||
return false;
|
||||
|
||||
auto& region = m_mapped_regions[index];
|
||||
if (!region->contains(address))
|
||||
return false;
|
||||
|
||||
return region->allocate_page_containing(address, wants_write);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::open_inode(VirtualFileSystem::File&& file, int flags)
|
||||
|
|
@ -1232,6 +1302,27 @@ namespace Kernel
|
|||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_renameat(int oldfd, const char* old, int newfd, const char* _new)
|
||||
{
|
||||
LockGuard _(m_process_lock);
|
||||
if (old != nullptr)
|
||||
TRY(validate_string_access(old));
|
||||
if (_new != nullptr)
|
||||
TRY(validate_string_access(_new));
|
||||
|
||||
auto [old_parent, old_name] = TRY(find_parent_file(oldfd, old, O_WRONLY));
|
||||
if (!old_parent.inode->mode().ifdir())
|
||||
return BAN::Error::from_errno(ENOTDIR);
|
||||
|
||||
auto [new_parent, new_name] = TRY(find_parent_file(newfd, _new, O_WRONLY));
|
||||
if (!new_parent.inode->mode().ifdir())
|
||||
return BAN::Error::from_errno(ENOTDIR);
|
||||
|
||||
TRY(new_parent.inode->rename_inode(old_parent.inode, old_name, new_name));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_unlinkat(int fd, const char* path, int flag)
|
||||
{
|
||||
if (flag && flag != AT_REMOVEDIR)
|
||||
|
|
@ -1243,9 +1334,15 @@ namespace Kernel
|
|||
|
||||
auto [parent, file_name] = TRY(find_parent_file(fd, path, O_WRONLY));
|
||||
|
||||
if (TRY(parent.inode->find_inode(file_name))->mode().ifdir() != (flag == AT_REMOVEDIR))
|
||||
const auto inode = TRY(parent.inode->find_inode(file_name));
|
||||
|
||||
if (inode->mode().ifdir() != (flag == AT_REMOVEDIR))
|
||||
return BAN::Error::from_errno(flag ? EPERM : ENOTDIR);
|
||||
|
||||
if (parent.inode->mode().mode & Inode::Mode::ISVTX)
|
||||
if (m_credentials.ruid() != parent.inode->uid() && m_credentials.ruid() != inode->uid())
|
||||
return BAN::Error::from_errno(EPERM);
|
||||
|
||||
TRY(parent.inode->unlink(file_name));
|
||||
|
||||
return 0;
|
||||
|
|
@ -1569,73 +1666,72 @@ namespace Kernel
|
|||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_sendto(const sys_sendto_t* _arguments)
|
||||
BAN::ErrorOr<long> Process::sys_recvmsg(int socket, msghdr* _message, int flags)
|
||||
{
|
||||
sys_sendto_t arguments;
|
||||
msghdr message;
|
||||
{
|
||||
LockGuard _(m_process_lock);
|
||||
TRY(validate_pointer_access(_arguments, sizeof(sys_sendto_t), false));
|
||||
arguments = *_arguments;
|
||||
TRY(validate_pointer_access(_message, sizeof(msghdr), true));
|
||||
message = *_message;
|
||||
}
|
||||
|
||||
if (arguments.length == 0)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
|
||||
MemoryRegion* message_region = nullptr;
|
||||
MemoryRegion* address_region = nullptr;
|
||||
|
||||
BAN::ScopeGuard _([&] {
|
||||
if (message_region)
|
||||
message_region->unpin();
|
||||
if (address_region)
|
||||
address_region->unpin();
|
||||
BAN::Vector<MemoryRegion*> regions;
|
||||
BAN::ScopeGuard _([®ions] {
|
||||
for (auto* region : regions)
|
||||
if (region != nullptr)
|
||||
region->unpin();
|
||||
});
|
||||
|
||||
message_region = TRY(validate_and_pin_pointer_access(arguments.message, arguments.length, false));
|
||||
if (arguments.dest_addr)
|
||||
address_region = TRY(validate_and_pin_pointer_access(arguments.dest_addr, arguments.dest_len, false));
|
||||
|
||||
auto message = BAN::ConstByteSpan(static_cast<const uint8_t*>(arguments.message), arguments.length);
|
||||
return TRY(m_open_file_descriptors.sendto(arguments.socket, message, arguments.dest_addr, arguments.dest_len));
|
||||
if (message.msg_name)
|
||||
TRY(regions.push_back(TRY(validate_and_pin_pointer_access(message.msg_name, message.msg_namelen, true))));
|
||||
if (message.msg_control)
|
||||
TRY(regions.push_back(TRY(validate_and_pin_pointer_access(message.msg_control, message.msg_controllen, true))));
|
||||
if (message.msg_iov)
|
||||
{
|
||||
TRY(regions.push_back(TRY(validate_and_pin_pointer_access(message.msg_iov, message.msg_iovlen * sizeof(iovec), true))));
|
||||
for (int i = 0; i < message.msg_iovlen; i++)
|
||||
TRY(regions.push_back(TRY(validate_and_pin_pointer_access(message.msg_iov[i].iov_base, message.msg_iov[i].iov_len, true))));
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_recvfrom(sys_recvfrom_t* _arguments)
|
||||
{
|
||||
sys_recvfrom_t arguments;
|
||||
auto ret = TRY(m_open_file_descriptors.recvmsg(socket, message, flags));
|
||||
|
||||
{
|
||||
LockGuard _(m_process_lock);
|
||||
TRY(validate_pointer_access(_arguments, sizeof(sys_sendto_t), false));
|
||||
arguments = *_arguments;
|
||||
TRY(validate_pointer_access(_message, sizeof(msghdr), true));
|
||||
*_message = message;
|
||||
}
|
||||
|
||||
if (!arguments.address != !arguments.address_len)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
if (arguments.length == 0)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
MemoryRegion* buffer_region = nullptr;
|
||||
MemoryRegion* address_region1 = nullptr;
|
||||
MemoryRegion* address_region2 = nullptr;
|
||||
BAN::ErrorOr<long> Process::sys_sendmsg(int socket, const msghdr* _message, int flags)
|
||||
{
|
||||
msghdr message;
|
||||
{
|
||||
LockGuard _(m_process_lock);
|
||||
TRY(validate_pointer_access(_message, sizeof(msghdr), false));
|
||||
message = *_message;
|
||||
}
|
||||
|
||||
BAN::ScopeGuard _([&] {
|
||||
if (buffer_region)
|
||||
buffer_region->unpin();
|
||||
if (address_region1)
|
||||
address_region1->unpin();
|
||||
if (address_region2)
|
||||
address_region2->unpin();
|
||||
BAN::Vector<MemoryRegion*> regions;
|
||||
BAN::ScopeGuard _([®ions] {
|
||||
for (auto* region : regions)
|
||||
if (region != nullptr)
|
||||
region->unpin();
|
||||
});
|
||||
|
||||
buffer_region = TRY(validate_and_pin_pointer_access(arguments.buffer, arguments.length, true));
|
||||
|
||||
if (arguments.address_len)
|
||||
if (message.msg_name)
|
||||
TRY(regions.push_back(TRY(validate_and_pin_pointer_access(message.msg_name, message.msg_namelen, false))));
|
||||
if (message.msg_control)
|
||||
TRY(regions.push_back(TRY(validate_and_pin_pointer_access(message.msg_control, message.msg_controllen, false))));
|
||||
if (message.msg_iov)
|
||||
{
|
||||
address_region1 = TRY(validate_and_pin_pointer_access(arguments.address_len, sizeof(*arguments.address_len), true));
|
||||
address_region2 = TRY(validate_and_pin_pointer_access(arguments.address, *arguments.address_len, true));
|
||||
TRY(regions.push_back(TRY(validate_and_pin_pointer_access(message.msg_iov, message.msg_iovlen * sizeof(iovec), false))));
|
||||
for (int i = 0; i < message.msg_iovlen; i++)
|
||||
TRY(regions.push_back(TRY(validate_and_pin_pointer_access(message.msg_iov[i].iov_base, message.msg_iov[i].iov_len, false))));
|
||||
}
|
||||
|
||||
auto message = BAN::ByteSpan(static_cast<uint8_t*>(arguments.buffer), arguments.length);
|
||||
return TRY(m_open_file_descriptors.recvfrom(arguments.socket, message, arguments.address, arguments.address_len));
|
||||
return TRY(m_open_file_descriptors.sendmsg(socket, message, flags));
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_ioctl(int fildes, int request, void* arg)
|
||||
|
|
@ -1998,7 +2094,7 @@ namespace Kernel
|
|||
return TRY(m_open_file_descriptors.dup2(fildes, fildes2));
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_fcntl(int fildes, int cmd, int extra)
|
||||
BAN::ErrorOr<long> Process::sys_fcntl(int fildes, int cmd, uintptr_t extra)
|
||||
{
|
||||
return TRY(m_open_file_descriptors.fcntl(fildes, cmd, extra));
|
||||
}
|
||||
|
|
@ -2190,6 +2286,38 @@ namespace Kernel
|
|||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::Vector<BAN::UniqPtr<MemoryRegion>>> Process::split_memory_region(BAN::UniqPtr<MemoryRegion>&& region, vaddr_t base, size_t length)
|
||||
{
|
||||
ASSERT(base % PAGE_SIZE == 0);
|
||||
ASSERT(base < region->vaddr() + region->size());
|
||||
|
||||
if (auto rem = length % PAGE_SIZE)
|
||||
length += PAGE_SIZE - rem;
|
||||
if (base + length > region->vaddr() + region->size())
|
||||
length = region->vaddr() + region->size() - base;
|
||||
|
||||
BAN::Vector<BAN::UniqPtr<MemoryRegion>> result;
|
||||
TRY(result.reserve(3));
|
||||
|
||||
if (region->vaddr() < base)
|
||||
{
|
||||
auto temp = TRY(region->split(base - region->vaddr()));
|
||||
MUST(result.push_back(BAN::move(region)));
|
||||
region = BAN::move(temp);
|
||||
}
|
||||
|
||||
if (base + length < region->vaddr() + region->size())
|
||||
{
|
||||
auto temp = TRY(region->split(base + length - region->vaddr()));
|
||||
MUST(result.push_back(BAN::move(region)));
|
||||
region = BAN::move(temp);
|
||||
}
|
||||
|
||||
MUST(result.push_back(BAN::move(region)));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_mmap(const sys_mmap_t* user_args)
|
||||
{
|
||||
sys_mmap_t args;
|
||||
|
|
@ -2202,6 +2330,9 @@ namespace Kernel
|
|||
if (args.prot != PROT_NONE && (args.prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)))
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
|
||||
if (!(args.flags & MAP_ANONYMOUS) && (args.off % PAGE_SIZE))
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
|
||||
if (!(args.flags & MAP_PRIVATE) == !(args.flags & MAP_SHARED))
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
auto region_type = (args.flags & MAP_PRIVATE) ? MemoryRegion::Type::PRIVATE : MemoryRegion::Type::SHARED;
|
||||
|
|
@ -2219,30 +2350,67 @@ namespace Kernel
|
|||
else
|
||||
page_flags |= PageTable::Flags::UserSupervisor;
|
||||
|
||||
LockGuard _(m_process_lock);
|
||||
|
||||
AddressRange address_range { .start = 0x400000, .end = USERSPACE_END };
|
||||
if (args.flags & MAP_FIXED)
|
||||
if (args.flags & (MAP_FIXED | MAP_FIXED_NOREPLACE))
|
||||
{
|
||||
vaddr_t base_addr = reinterpret_cast<vaddr_t>(args.addr);
|
||||
address_range.start = BAN::Math::div_round_up<vaddr_t>(base_addr, PAGE_SIZE) * PAGE_SIZE;
|
||||
address_range.end = BAN::Math::div_round_up<vaddr_t>(base_addr + args.len, PAGE_SIZE) * PAGE_SIZE;
|
||||
const vaddr_t vaddr = reinterpret_cast<vaddr_t>(args.addr);
|
||||
if (vaddr == 0 || vaddr % PAGE_SIZE)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
if (!PageTable::is_valid_pointer(vaddr))
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
if (!PageTable::is_valid_pointer(vaddr + args.len))
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
address_range = {
|
||||
.start = vaddr,
|
||||
.end = vaddr + args.len,
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < m_mapped_regions.size(); i++)
|
||||
if (args.flags & MAP_FIXED_NOREPLACE)
|
||||
;
|
||||
else
|
||||
{
|
||||
if (!m_mapped_regions[i]->overlaps(base_addr, args.len))
|
||||
continue;
|
||||
if (!m_mapped_regions[i]->contains_fully(base_addr, args.len))
|
||||
derrorln("VERY BROKEN MAP_FIXED UNMAP");
|
||||
const size_t first_index = find_mapped_region(vaddr);
|
||||
for (size_t i = first_index; i < m_mapped_regions.size(); i++)
|
||||
{
|
||||
if (!m_mapped_regions[i]->overlaps(vaddr, args.len))
|
||||
break;
|
||||
|
||||
m_mapped_regions[i]->wait_not_pinned();
|
||||
auto temp = BAN::move(m_mapped_regions[i]);
|
||||
m_mapped_regions.remove(i--);
|
||||
}
|
||||
|
||||
if (temp->is_contained_by(vaddr, args.len))
|
||||
continue;
|
||||
|
||||
auto new_regions = TRY(split_memory_region(BAN::move(temp), vaddr, args.len));
|
||||
for (auto& new_region : new_regions)
|
||||
if (!new_region->overlaps(vaddr, args.len))
|
||||
TRY(m_mapped_regions.insert(++i, BAN::move(new_region)));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (const vaddr_t vaddr = reinterpret_cast<vaddr_t>(args.addr); vaddr == 0)
|
||||
;
|
||||
else if (vaddr % PAGE_SIZE)
|
||||
;
|
||||
else if (!PageTable::is_valid_pointer(vaddr))
|
||||
;
|
||||
else if (!PageTable::is_valid_pointer(vaddr + args.len))
|
||||
;
|
||||
else if (!page_table().is_range_free(vaddr, args.len))
|
||||
;
|
||||
else
|
||||
{
|
||||
address_range = {
|
||||
.start = vaddr,
|
||||
.end = vaddr + args.len,
|
||||
};
|
||||
}
|
||||
|
||||
if (args.flags & MAP_ANONYMOUS)
|
||||
{
|
||||
if (args.off != 0)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
|
||||
auto region = TRY(MemoryBackedRegion::create(
|
||||
page_table(),
|
||||
args.len,
|
||||
|
|
@ -2251,13 +2419,11 @@ namespace Kernel
|
|||
O_EXEC | O_RDWR
|
||||
));
|
||||
|
||||
LockGuard _(m_process_lock);
|
||||
TRY(m_mapped_regions.push_back(BAN::move(region)));
|
||||
return m_mapped_regions.back()->vaddr();
|
||||
const vaddr_t region_vaddr = region->vaddr();
|
||||
TRY(add_mapped_region(BAN::move(region)));
|
||||
return region_vaddr;
|
||||
}
|
||||
|
||||
LockGuard _(m_process_lock);
|
||||
|
||||
auto inode = TRY(m_open_file_descriptors.inode_of(args.fildes));
|
||||
|
||||
const auto status_flags = TRY(m_open_file_descriptors.status_flags_of(args.fildes));
|
||||
|
|
@ -2267,10 +2433,10 @@ namespace Kernel
|
|||
if ((args.prot & PROT_WRITE) && !(status_flags & O_WRONLY))
|
||||
return BAN::Error::from_errno(EACCES);
|
||||
|
||||
BAN::UniqPtr<MemoryRegion> memory_region;
|
||||
BAN::UniqPtr<MemoryRegion> region;
|
||||
if (inode->mode().ifreg())
|
||||
{
|
||||
memory_region = TRY(FileBackedRegion::create(
|
||||
region = TRY(FileBackedRegion::create(
|
||||
inode,
|
||||
page_table(),
|
||||
args.off, args.len,
|
||||
|
|
@ -2281,7 +2447,7 @@ namespace Kernel
|
|||
}
|
||||
else if (inode->is_device())
|
||||
{
|
||||
memory_region = TRY(static_cast<Device&>(*inode).mmap_region(
|
||||
region = TRY(static_cast<Device&>(*inode).mmap_region(
|
||||
page_table(),
|
||||
args.off, args.len,
|
||||
address_range,
|
||||
|
|
@ -2290,11 +2456,12 @@ namespace Kernel
|
|||
));
|
||||
}
|
||||
|
||||
if (!memory_region)
|
||||
if (!region)
|
||||
return BAN::Error::from_errno(ENODEV);
|
||||
|
||||
TRY(m_mapped_regions.push_back(BAN::move(memory_region)));
|
||||
return m_mapped_regions.back()->vaddr();
|
||||
const vaddr_t region_vaddr = region->vaddr();
|
||||
TRY(add_mapped_region(BAN::move(region)));
|
||||
return region_vaddr;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_munmap(void* addr, size_t len)
|
||||
|
|
@ -2302,31 +2469,35 @@ namespace Kernel
|
|||
if (len == 0)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
|
||||
const vaddr_t vaddr = reinterpret_cast<vaddr_t>(addr);
|
||||
if (vaddr % PAGE_SIZE != 0)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
vaddr_t vaddr = reinterpret_cast<vaddr_t>(addr);
|
||||
if (auto rem = vaddr % PAGE_SIZE)
|
||||
{
|
||||
vaddr -= rem;
|
||||
len += rem;
|
||||
}
|
||||
|
||||
if (auto rem = len % PAGE_SIZE)
|
||||
len += PAGE_SIZE - rem;
|
||||
|
||||
LockGuard _(m_process_lock);
|
||||
|
||||
// FIXME: We should unmap partial regions.
|
||||
// This is a hack to only unmap if the whole mmap region
|
||||
// is contained within [addr, addr + len]
|
||||
for (size_t i = 0; i < m_mapped_regions.size(); i++)
|
||||
const size_t first_index = find_mapped_region(vaddr);
|
||||
for (size_t i = first_index; i < m_mapped_regions.size(); i++)
|
||||
{
|
||||
auto& region = m_mapped_regions[i];
|
||||
if (!m_mapped_regions[i]->overlaps(vaddr, len))
|
||||
break;
|
||||
|
||||
const vaddr_t region_s = region->vaddr();
|
||||
const vaddr_t region_e = region->vaddr() + region->size();
|
||||
if (vaddr <= region_s && region_e <= vaddr + len)
|
||||
{
|
||||
region->wait_not_pinned();
|
||||
m_mapped_regions[i]->wait_not_pinned();
|
||||
auto temp = BAN::move(m_mapped_regions[i]);
|
||||
m_mapped_regions.remove(i--);
|
||||
}
|
||||
else if (region->overlaps(vaddr, len))
|
||||
dwarnln("TODO: partial region munmap");
|
||||
|
||||
if (temp->is_contained_by(vaddr, len))
|
||||
continue;
|
||||
|
||||
auto new_regions = TRY(split_memory_region(BAN::move(temp), vaddr, len));
|
||||
for (auto& new_region : new_regions)
|
||||
if (!new_region->overlaps(vaddr, len))
|
||||
TRY(m_mapped_regions.insert(++i, BAN::move(new_region)));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -2359,39 +2530,36 @@ namespace Kernel
|
|||
|
||||
LockGuard _(m_process_lock);
|
||||
|
||||
// FIXME: We should protect partial regions.
|
||||
// This is a hack to only protect if the whole mmap region
|
||||
// is contained within [addr, addr + len]
|
||||
for (size_t i = 0; i < m_mapped_regions.size(); i++)
|
||||
const size_t first_index = find_mapped_region(vaddr);
|
||||
for (size_t i = first_index; i < m_mapped_regions.size(); i++)
|
||||
{
|
||||
if (!m_mapped_regions[i]->overlaps(vaddr, len))
|
||||
break;
|
||||
|
||||
if (!m_mapped_regions[i]->is_contained_by(vaddr, len))
|
||||
{
|
||||
m_mapped_regions[i]->wait_not_pinned();
|
||||
auto temp = BAN::move(m_mapped_regions[i]);
|
||||
m_mapped_regions.remove(i--);
|
||||
|
||||
auto new_regions = TRY(split_memory_region(BAN::move(temp), vaddr, len));
|
||||
for (size_t j = 0; j < new_regions.size(); j++)
|
||||
TRY(m_mapped_regions.insert(i + j + 1, BAN::move(new_regions[j])));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
auto& region = m_mapped_regions[i];
|
||||
|
||||
const vaddr_t region_s = region->vaddr();
|
||||
const vaddr_t region_e = region->vaddr() + region->size();
|
||||
if (vaddr <= region_s && region_e <= vaddr + len)
|
||||
{
|
||||
const bool is_shared = (region->type() == MemoryRegion::Type::SHARED);
|
||||
const bool is_writable = (region->status_flags() & O_WRONLY);
|
||||
const bool want_write = (prot & PROT_WRITE);
|
||||
if (is_shared && want_write && !is_writable)
|
||||
return BAN::Error::from_errno(EACCES);
|
||||
|
||||
// FIXME: if the region is pinned writable, this may
|
||||
// cause some problems :D
|
||||
// NOTE: don't change protection of regions in use
|
||||
region->wait_not_pinned();
|
||||
TRY(region->mprotect(flags));
|
||||
}
|
||||
else if (region->overlaps(vaddr, len))
|
||||
{
|
||||
const bool is_shared = (region->type() == MemoryRegion::Type::SHARED);
|
||||
const bool is_writable = (region->status_flags() & O_WRONLY);
|
||||
const bool want_write = (prot & PROT_WRITE);
|
||||
if (is_shared && want_write && !is_writable)
|
||||
return BAN::Error::from_errno(EACCES);
|
||||
|
||||
dwarnln("TODO: partial region mprotect");
|
||||
TRY(region->mprotect(flags | region->flags()));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2404,9 +2572,16 @@ namespace Kernel
|
|||
LockGuard _(m_process_lock);
|
||||
|
||||
const vaddr_t vaddr = reinterpret_cast<vaddr_t>(addr);
|
||||
for (auto& mapped_region : m_mapped_regions)
|
||||
if (mapped_region->overlaps(vaddr, len))
|
||||
TRY(mapped_region->msync(vaddr, len, flags));
|
||||
|
||||
const size_t first_index = find_mapped_region(vaddr);
|
||||
for (size_t i = first_index; i < m_mapped_regions.size(); i++)
|
||||
{
|
||||
auto& region = *m_mapped_regions[i];
|
||||
if (vaddr >= region.vaddr() + region.size())
|
||||
break;
|
||||
if (region.overlaps(vaddr, len))
|
||||
TRY(region.msync(vaddr, len, flags));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2448,8 +2623,9 @@ namespace Kernel
|
|||
auto region = TRY(SharedMemoryObjectManager::get().map_object(key, page_table(), { .start = 0x400000, .end = USERSPACE_END }));
|
||||
|
||||
LockGuard _(m_process_lock);
|
||||
TRY(m_mapped_regions.push_back(BAN::move(region)));
|
||||
return m_mapped_regions.back()->vaddr();
|
||||
const vaddr_t region_vaddr = region->vaddr();
|
||||
TRY(add_mapped_region(BAN::move(region)));
|
||||
return region_vaddr;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_ttyname(int fildes, char* name, size_t namesize)
|
||||
|
|
@ -2644,7 +2820,18 @@ namespace Kernel
|
|||
|
||||
if (!(m_signal_handlers[SIGCHLD].sa_flags & SA_NOCLDSTOP))
|
||||
{
|
||||
parent->add_pending_signal(SIGCHLD);
|
||||
parent->add_pending_signal(SIGCHLD, {
|
||||
.si_signo = SIGCHLD,
|
||||
.si_code = stopped ? CLD_STOPPED : CLD_CONTINUED,
|
||||
.si_errno = 0,
|
||||
.si_pid = pid(),
|
||||
.si_uid = m_credentials.ruid(),
|
||||
.si_addr = nullptr,
|
||||
.si_status = __WGENEXITCODE(0, signal),
|
||||
.si_band = 0,
|
||||
.si_value = { .sival_int = 0 },
|
||||
});
|
||||
|
||||
if (!parent->m_threads.empty())
|
||||
Processor::scheduler().unblock_thread(parent->m_threads.front());
|
||||
}
|
||||
|
|
@ -2670,7 +2857,7 @@ namespace Kernel
|
|||
}
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Process::kill(pid_t pid, int signal)
|
||||
BAN::ErrorOr<void> Process::kill(pid_t pid, int signal, const siginfo_t& signal_info)
|
||||
{
|
||||
if (pid == 0 || pid == -1)
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
|
|
@ -2694,7 +2881,7 @@ namespace Kernel
|
|||
process.set_stopped(false, signal);
|
||||
else
|
||||
{
|
||||
process.add_pending_signal(signal);
|
||||
process.add_pending_signal(signal, signal_info);
|
||||
if (!process.m_threads.empty())
|
||||
Processor::scheduler().unblock_thread(process.m_threads.front());
|
||||
process.m_stop_blocker.unblock();
|
||||
|
|
@ -2716,6 +2903,18 @@ namespace Kernel
|
|||
if (signal != 0 && (signal < _SIGMIN || signal > _SIGMAX))
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
|
||||
const siginfo_t signal_info {
|
||||
.si_signo = signal,
|
||||
.si_code = SI_USER,
|
||||
.si_errno = 0,
|
||||
.si_pid = this->pid(),
|
||||
.si_uid = m_credentials.ruid(),
|
||||
.si_addr = nullptr,
|
||||
.si_status = 0,
|
||||
.si_band = 0,
|
||||
.si_value = {},
|
||||
};
|
||||
|
||||
if (pid == m_pid)
|
||||
{
|
||||
if (signal == 0)
|
||||
|
|
@ -2726,13 +2925,13 @@ namespace Kernel
|
|||
set_stopped(false, signal);
|
||||
else
|
||||
{
|
||||
add_pending_signal(signal);
|
||||
add_pending_signal(signal, signal_info);
|
||||
m_stop_blocker.unblock();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
TRY(kill(pid, signal));
|
||||
TRY(kill(pid, signal, signal_info));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -2953,16 +3152,28 @@ namespace Kernel
|
|||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_set_tls(void* addr)
|
||||
BAN::ErrorOr<long> Process::sys_set_fsbase(void* addr)
|
||||
{
|
||||
Thread::current().set_tls(reinterpret_cast<vaddr_t>(addr));
|
||||
Processor::load_tls();
|
||||
Thread::current().set_fsbase(reinterpret_cast<vaddr_t>(addr));
|
||||
Processor::load_fsbase();
|
||||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_get_tls()
|
||||
BAN::ErrorOr<long> Process::sys_get_fsbase()
|
||||
{
|
||||
return Thread::current().get_tls();
|
||||
return Thread::current().get_fsbase();
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_set_gsbase(void* addr)
|
||||
{
|
||||
Thread::current().set_gsbase(reinterpret_cast<vaddr_t>(addr));
|
||||
Processor::load_gsbase();
|
||||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_get_gsbase()
|
||||
{
|
||||
return Thread::current().get_gsbase();
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_pthread_create(const pthread_attr_t* attr, void (*entry)(void*), void* arg)
|
||||
|
|
@ -3063,8 +3274,19 @@ namespace Kernel
|
|||
{
|
||||
if (thread->tid() != tid)
|
||||
continue;
|
||||
if (signal != 0)
|
||||
thread->add_signal(signal);
|
||||
if (signal == 0)
|
||||
return 0;
|
||||
thread->add_signal(signal, {
|
||||
.si_signo = signal,
|
||||
.si_code = SI_USER,
|
||||
.si_errno = 0,
|
||||
.si_pid = pid(),
|
||||
.si_uid = m_credentials.ruid(),
|
||||
.si_addr = nullptr,
|
||||
.si_status = 0,
|
||||
.si_band = 0,
|
||||
.si_value = {},
|
||||
});
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -3474,62 +3696,64 @@ namespace Kernel
|
|||
return validate_pointer_access(str, strlen(str) + 1, false);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Process::validate_pointer_access_check(const void* ptr, size_t size, bool needs_write)
|
||||
{
|
||||
ASSERT(&Process::current() == this);
|
||||
|
||||
const vaddr_t vaddr = reinterpret_cast<vaddr_t>(ptr);
|
||||
|
||||
// NOTE: detect overflow
|
||||
if (vaddr + size < vaddr)
|
||||
goto unauthorized_access;
|
||||
|
||||
// trying to access kernel space memory
|
||||
if (vaddr + size > USERSPACE_END)
|
||||
goto unauthorized_access;
|
||||
|
||||
for (const auto* thread : m_threads)
|
||||
if (vaddr >= thread->userspace_stack_bottom() && vaddr + size <= thread->userspace_stack_top())
|
||||
return {};
|
||||
|
||||
// FIXME: should we allow cross mapping access?
|
||||
for (const auto& mapped_region : m_mapped_regions)
|
||||
{
|
||||
if (!mapped_region->contains_fully(vaddr, size))
|
||||
continue;
|
||||
if (needs_write && !mapped_region->writable())
|
||||
goto unauthorized_access;
|
||||
return {};
|
||||
}
|
||||
|
||||
unauthorized_access:
|
||||
dwarnln("process {}, thread {} attempted to make an invalid pointer access to 0x{H}->0x{H}", pid(), Thread::current().tid(), vaddr, vaddr + size);
|
||||
Debug::dump_stack_trace();
|
||||
MUST(sys_kill(pid(), SIGSEGV));
|
||||
return BAN::Error::from_errno(EINTR);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Process::validate_pointer_access(const void* ptr, size_t size, bool needs_write)
|
||||
{
|
||||
// TODO: This seems very slow as we loop over the range twice
|
||||
|
||||
if (size == 0)
|
||||
return {};
|
||||
|
||||
TRY(validate_pointer_access_check(ptr, size, needs_write));
|
||||
|
||||
const vaddr_t vaddr = reinterpret_cast<vaddr_t>(ptr);
|
||||
const auto page_flags = (needs_write ? PageTable::Flags::ReadWrite : 0) | PageTable::Flags::Present;
|
||||
|
||||
// Make sure all of the pages are mapped here, so demand paging does not happen
|
||||
// while processing syscall.
|
||||
|
||||
const vaddr_t vaddr = reinterpret_cast<vaddr_t>(ptr);
|
||||
const vaddr_t page_start = vaddr & PAGE_ADDR_MASK;
|
||||
const size_t page_count = range_page_count(vaddr, size);
|
||||
for (size_t i = 0; i < page_count; i++)
|
||||
{
|
||||
const vaddr_t current = page_start + i * PAGE_SIZE;
|
||||
if (page_table().get_page_flags(current) & PageTable::Flags::Present)
|
||||
if ((page_table().get_page_flags(current) & page_flags) == page_flags)
|
||||
continue;
|
||||
TRY(Process::allocate_page_for_demand_paging(current, needs_write, false));
|
||||
if (!TRY(Process::allocate_page_for_demand_paging(current, needs_write, false)))
|
||||
{
|
||||
const MemoryRegion* region_ptr = nullptr;
|
||||
for (const auto& region : m_mapped_regions)
|
||||
{
|
||||
if (!region->contains(vaddr + i * PAGE_SIZE))
|
||||
continue;
|
||||
region_ptr = region.ptr();
|
||||
break;
|
||||
}
|
||||
|
||||
dwarnln("{} pid {}, tid {} made an invalid {} access to 0x{h}",
|
||||
name(),
|
||||
pid(),
|
||||
Thread::current().tid(),
|
||||
needs_write ? "write" : "read",
|
||||
vaddr + i * PAGE_SIZE
|
||||
);
|
||||
|
||||
dwarnln(" 0x{h}->0x{h}", vaddr, vaddr + size);
|
||||
|
||||
if (region_ptr == nullptr)
|
||||
dwarnln(" no mapping covers this page");
|
||||
else
|
||||
{
|
||||
dwarnln(" inside region 0x{h}->0x{h} {}{}{}",
|
||||
region_ptr->vaddr(),
|
||||
region_ptr->vaddr() + region_ptr->size(),
|
||||
(region_ptr->flags() & PageTable::Flags::Present) ? 'r' : '-',
|
||||
(region_ptr->flags() & PageTable::Flags::ReadWrite) ? 'w' : '-',
|
||||
(region_ptr->flags() & PageTable::Flags::Execute) ? 'x' : '-'
|
||||
);
|
||||
}
|
||||
|
||||
page_table().debug_dump();
|
||||
|
||||
Debug::dump_stack_trace();
|
||||
MUST(sys_kill(pid(), SIGSEGV));
|
||||
return BAN::Error::from_errno(EINTR);
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
|
|
@ -3539,14 +3763,24 @@ unauthorized_access:
|
|||
{
|
||||
LockGuard _(m_process_lock);
|
||||
TRY(validate_pointer_access(ptr, size, needs_write));
|
||||
for (auto& region : m_mapped_regions)
|
||||
|
||||
// FIXME: make stack MemoryRegion?
|
||||
// FIXME: allow pinning multiple regions
|
||||
|
||||
const vaddr_t vaddr = reinterpret_cast<vaddr_t>(ptr);
|
||||
|
||||
const size_t first_index = find_mapped_region(vaddr);
|
||||
for (size_t i = first_index; i < m_mapped_regions.size(); i++)
|
||||
{
|
||||
if (!region->contains_fully(reinterpret_cast<vaddr_t>(ptr), size))
|
||||
auto& region = m_mapped_regions[i];
|
||||
if (vaddr >= region->vaddr() + region->size())
|
||||
break;
|
||||
if (!region->contains_fully(vaddr, size))
|
||||
continue;
|
||||
region->pin();
|
||||
return region.ptr();
|
||||
}
|
||||
// FIXME: Make stack MemoryRegion?
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ namespace Kernel
|
|||
#if ARCH(x86_64)
|
||||
static constexpr uint32_t MSR_IA32_FS_BASE = 0xC0000100;
|
||||
static constexpr uint32_t MSR_IA32_GS_BASE = 0xC0000101;
|
||||
static constexpr uint32_t MSR_IA32_KERNEL_GS_BASE = 0xC0000102;
|
||||
#endif
|
||||
|
||||
ProcessorID Processor::s_bsp_id { PROCESSOR_NONE };
|
||||
|
|
@ -265,15 +266,52 @@ namespace Kernel
|
|||
set_interrupt_state(state);
|
||||
}
|
||||
|
||||
void Processor::load_tls()
|
||||
void Processor::load_segments()
|
||||
{
|
||||
const auto addr = scheduler().current_thread().get_tls();
|
||||
{
|
||||
const auto addr = scheduler().current_thread().get_fsbase();
|
||||
#if ARCH(x86_64)
|
||||
uint32_t ptr_hi = addr >> 32;
|
||||
uint32_t ptr_lo = addr & 0xFFFFFFFF;
|
||||
asm volatile("wrmsr" :: "d"(ptr_hi), "a"(ptr_lo), "c"(MSR_IA32_FS_BASE));
|
||||
#elif ARCH(i686)
|
||||
gdt().set_tls(addr);
|
||||
gdt().set_fsbase(addr);
|
||||
#endif
|
||||
}
|
||||
|
||||
{
|
||||
const auto addr = scheduler().current_thread().get_gsbase();
|
||||
#if ARCH(x86_64)
|
||||
uint32_t ptr_hi = addr >> 32;
|
||||
uint32_t ptr_lo = addr & 0xFFFFFFFF;
|
||||
asm volatile("wrmsr" :: "d"(ptr_hi), "a"(ptr_lo), "c"(MSR_IA32_KERNEL_GS_BASE));
|
||||
#elif ARCH(i686)
|
||||
gdt().set_gsbase(addr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void Processor::load_fsbase()
|
||||
{
|
||||
const auto addr = scheduler().current_thread().get_fsbase();
|
||||
#if ARCH(x86_64)
|
||||
uint32_t ptr_hi = addr >> 32;
|
||||
uint32_t ptr_lo = addr & 0xFFFFFFFF;
|
||||
asm volatile("wrmsr" :: "d"(ptr_hi), "a"(ptr_lo), "c"(MSR_IA32_FS_BASE));
|
||||
#elif ARCH(i686)
|
||||
gdt().set_fsbase(addr);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Processor::load_gsbase()
|
||||
{
|
||||
const auto addr = scheduler().current_thread().get_gsbase();
|
||||
#if ARCH(x86_64)
|
||||
uint32_t ptr_hi = addr >> 32;
|
||||
uint32_t ptr_lo = addr & 0xFFFFFFFF;
|
||||
asm volatile("wrmsr" :: "d"(ptr_hi), "a"(ptr_lo), "c"(MSR_IA32_KERNEL_GS_BASE));
|
||||
#elif ARCH(i686)
|
||||
gdt().set_gsbase(addr);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -282,7 +282,8 @@ namespace Kernel
|
|||
}
|
||||
|
||||
Processor::gdt().set_tss_stack(thread->kernel_stack_top());
|
||||
Processor::load_tls();
|
||||
if (thread->is_userspace())
|
||||
Processor::load_segments();
|
||||
*interrupt_stack = thread->interrupt_stack();
|
||||
*interrupt_registers = thread->interrupt_registers();
|
||||
|
||||
|
|
|
|||
|
|
@ -124,8 +124,8 @@ namespace Kernel
|
|||
case SYS_WAIT:
|
||||
case SYS_ACCEPT:
|
||||
case SYS_CONNECT:
|
||||
case SYS_RECVFROM:
|
||||
case SYS_SENDTO:
|
||||
case SYS_RECVMSG:
|
||||
case SYS_SENDMSG:
|
||||
case SYS_FLOCK:
|
||||
return true;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -417,6 +417,11 @@ namespace Kernel
|
|||
m_cursor_shown = (ch == 'h');
|
||||
return reset_ansi();
|
||||
}
|
||||
if (m_ansi_state.question && m_ansi_state.nums[0] == 2004)
|
||||
{
|
||||
// bracketed paste mode, there is no pasting so this is a no-op
|
||||
return reset_ansi();
|
||||
}
|
||||
reset_ansi();
|
||||
dprintln_if(DEBUG_VTTY, "Unsupported ANSI CSI character {}", static_cast<char>(ch));
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -328,7 +328,8 @@ namespace Kernel
|
|||
thread->m_kernel_stack = TRY(m_kernel_stack->clone(new_process->page_table()));
|
||||
thread->m_userspace_stack = TRY(m_userspace_stack->clone(new_process->page_table()));
|
||||
|
||||
thread->m_tls = m_tls;
|
||||
thread->m_fsbase = m_fsbase;
|
||||
thread->m_gsbase = m_gsbase;
|
||||
|
||||
thread->m_state = State::NotStarted;
|
||||
|
||||
|
|
@ -385,7 +386,7 @@ namespace Kernel
|
|||
|
||||
vaddr_t vaddr = userspace_stack_top() - needed_size;
|
||||
|
||||
const size_t page_count = BAN::Math::div_round_up(needed_size, PAGE_SIZE);
|
||||
const size_t page_count = BAN::Math::div_round_up<size_t>(needed_size, PAGE_SIZE);
|
||||
for (size_t i = 0; i < page_count; i++)
|
||||
TRY(m_userspace_stack->allocate_page_for_demand_paging(vaddr + i * PAGE_SIZE));
|
||||
|
||||
|
|
@ -549,12 +550,14 @@ namespace Kernel
|
|||
vaddr_t signal_handler;
|
||||
{
|
||||
SpinLockGuard _(m_process->m_signal_lock);
|
||||
ASSERT(!(m_process->m_signal_handlers[i].sa_flags & SA_SIGINFO));
|
||||
signal_handler = (vaddr_t)m_process->m_signal_handlers[i].sa_handler;
|
||||
const auto& handler = m_process->m_signal_handlers[i];
|
||||
signal_handler = (handler.sa_flags & SA_SIGINFO)
|
||||
? reinterpret_cast<vaddr_t>(handler.sa_sigaction)
|
||||
: reinterpret_cast<vaddr_t>(handler.sa_handler);
|
||||
}
|
||||
if (signal_handler == (vaddr_t)SIG_IGN)
|
||||
if (signal_handler == reinterpret_cast<vaddr_t>(SIG_IGN))
|
||||
continue;
|
||||
if (signal_handler == (vaddr_t)SIG_DFL && is_default_ignored_signal(i))
|
||||
if (signal_handler == reinterpret_cast<vaddr_t>(SIG_DFL) && is_default_ignored_signal(i))
|
||||
continue;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -585,7 +588,7 @@ namespace Kernel
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Thread::handle_signal(int signal)
|
||||
bool Thread::handle_signal(int signal, const siginfo_t& _signal_info)
|
||||
{
|
||||
ASSERT(&Thread::current() == this);
|
||||
ASSERT(is_userspace());
|
||||
|
|
@ -595,16 +598,23 @@ namespace Kernel
|
|||
auto& interrupt_stack = *reinterpret_cast<InterruptStack*>(kernel_stack_top() - sizeof(InterruptStack));
|
||||
ASSERT(GDT::is_user_segment(interrupt_stack.cs));
|
||||
|
||||
auto signal_info = _signal_info;
|
||||
|
||||
if (signal == 0)
|
||||
{
|
||||
uint64_t full_pending_mask = m_signal_pending_mask | process().signal_pending_mask();
|
||||
const uint64_t process_signal_pending_mask = process().signal_pending_mask();
|
||||
const uint64_t full_pending_mask = m_signal_pending_mask | process_signal_pending_mask;
|
||||
for (signal = _SIGMIN; signal <= _SIGMAX; signal++)
|
||||
{
|
||||
uint64_t mask = 1ull << signal;
|
||||
const uint64_t mask = 1ull << signal;
|
||||
if ((full_pending_mask & mask) && !(m_signal_block_mask & mask))
|
||||
break;
|
||||
}
|
||||
ASSERT(signal <= _SIGMAX);
|
||||
if (process_signal_pending_mask & (1ull << signal))
|
||||
signal_info = process().m_signal_infos[signal];
|
||||
else
|
||||
signal_info = m_signal_infos[signal];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -615,19 +625,20 @@ namespace Kernel
|
|||
vaddr_t signal_handler;
|
||||
bool has_sa_restart;
|
||||
vaddr_t signal_stack_top = 0;
|
||||
|
||||
{
|
||||
SpinLockGuard _(m_process->m_signal_lock);
|
||||
|
||||
auto& handler = m_process->m_signal_handlers[signal];
|
||||
|
||||
ASSERT(!(handler.sa_flags & SA_SIGINFO));
|
||||
|
||||
signal_handler = reinterpret_cast<vaddr_t>(handler.sa_handler);
|
||||
if (handler.sa_flags & SA_RESETHAND)
|
||||
handler.sa_handler = SIG_DFL;
|
||||
|
||||
signal_handler = (handler.sa_flags & SA_SIGINFO)
|
||||
? reinterpret_cast<vaddr_t>(handler.sa_sigaction)
|
||||
: reinterpret_cast<vaddr_t>(handler.sa_handler);
|
||||
has_sa_restart = !!(handler.sa_flags & SA_RESTART);
|
||||
|
||||
if (handler.sa_flags & SA_RESETHAND)
|
||||
handler = { .sa_handler = SIG_DFL, .sa_mask = 0, .sa_flags = 0 };
|
||||
|
||||
const auto& alt_stack = m_signal_alt_stack;
|
||||
if (alt_stack.ss_flags != SS_DISABLE && (handler.sa_flags & SA_ONSTACK) && !currently_on_alternate_stack())
|
||||
signal_stack_top = reinterpret_cast<vaddr_t>(alt_stack.ss_sp) + alt_stack.ss_size;
|
||||
|
|
@ -661,15 +672,15 @@ namespace Kernel
|
|||
|
||||
if (signal_stack_top == 0)
|
||||
{
|
||||
pages[0] = (interrupt_stack.sp - 1 * sizeof(uintptr_t)) & PAGE_ADDR_MASK;
|
||||
pages[1] = (interrupt_stack.sp - 5 * sizeof(uintptr_t)) & PAGE_ADDR_MASK;
|
||||
pages[0] = (interrupt_stack.sp - 1 * sizeof(uintptr_t) ) & PAGE_ADDR_MASK;
|
||||
pages[1] = (interrupt_stack.sp - 5 * sizeof(uintptr_t) - sizeof(siginfo_t)) & PAGE_ADDR_MASK;
|
||||
page_count = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
pages[0] = (interrupt_stack.sp - sizeof(uintptr_t)) & PAGE_ADDR_MASK;
|
||||
pages[1] = (signal_stack_top - 4 * sizeof(uintptr_t)) & PAGE_ADDR_MASK;
|
||||
pages[2] = (signal_stack_top - 1 * sizeof(uintptr_t)) & PAGE_ADDR_MASK;
|
||||
pages[0] = (interrupt_stack.sp - 1 * sizeof(uintptr_t) ) & PAGE_ADDR_MASK;
|
||||
pages[2] = (signal_stack_top - 1 * sizeof(uintptr_t) ) & PAGE_ADDR_MASK;
|
||||
pages[1] = (signal_stack_top - 4 * sizeof(uintptr_t) - sizeof(siginfo_t)) & PAGE_ADDR_MASK;
|
||||
page_count = 3;
|
||||
}
|
||||
|
||||
|
|
@ -690,6 +701,16 @@ namespace Kernel
|
|||
interrupt_stack.sp = signal_stack_top;
|
||||
write_to_stack(interrupt_stack.sp, old_stack);
|
||||
write_to_stack(interrupt_stack.sp, interrupt_stack.flags);
|
||||
|
||||
{
|
||||
signal_info.si_signo = signal;
|
||||
signal_info.si_addr = reinterpret_cast<void*>(interrupt_stack.ip);
|
||||
|
||||
interrupt_stack.sp -= sizeof(siginfo_t);
|
||||
*reinterpret_cast<siginfo_t*>(interrupt_stack.sp) = signal_info;
|
||||
static_assert(sizeof(siginfo_t) % sizeof(uintptr_t) == 0);
|
||||
}
|
||||
|
||||
write_to_stack(interrupt_stack.sp, signal);
|
||||
write_to_stack(interrupt_stack.sp, signal_handler);
|
||||
interrupt_stack.ip = (uintptr_t)signal_trampoline;
|
||||
|
|
@ -727,25 +748,29 @@ namespace Kernel
|
|||
return has_sa_restart;
|
||||
}
|
||||
|
||||
void Thread::add_signal(int signal)
|
||||
void Thread::add_signal(int signal, const siginfo_t& info)
|
||||
{
|
||||
SpinLockGuard _(m_signal_lock);
|
||||
|
||||
if (m_process)
|
||||
{
|
||||
vaddr_t signal_handler;
|
||||
{
|
||||
SpinLockGuard _(m_process->m_signal_lock);
|
||||
ASSERT(!(m_process->m_signal_handlers[signal].sa_flags & SA_SIGINFO));
|
||||
signal_handler = (vaddr_t)m_process->m_signal_handlers[signal].sa_handler;
|
||||
const auto& handler = m_process->m_signal_handlers[signal];
|
||||
signal_handler = (handler.sa_flags & SA_SIGINFO)
|
||||
? reinterpret_cast<vaddr_t>(handler.sa_sigaction)
|
||||
: reinterpret_cast<vaddr_t>(handler.sa_handler);
|
||||
}
|
||||
if (signal_handler == (vaddr_t)SIG_IGN)
|
||||
if (signal_handler == reinterpret_cast<vaddr_t>(SIG_IGN))
|
||||
return;
|
||||
if (signal_handler == (vaddr_t)SIG_DFL && is_default_ignored_signal(signal))
|
||||
if (signal_handler == reinterpret_cast<vaddr_t>(SIG_DFL) && is_default_ignored_signal(signal))
|
||||
return;
|
||||
}
|
||||
|
||||
const uint64_t mask = 1ull << signal;
|
||||
m_signal_pending_mask |= mask;
|
||||
m_signal_infos[signal] = info;
|
||||
|
||||
if (this != &Thread::current())
|
||||
Processor::scheduler().unblock_thread(this);
|
||||
|
|
|
|||
|
|
@ -113,6 +113,18 @@ namespace Kernel
|
|||
|
||||
auto& operational = operational_regs();
|
||||
|
||||
if (auto page_size_bits = operational.pagesize & 0xFFFF; page_size_bits != 1)
|
||||
{
|
||||
dwarnln("XHCI does not support 4096 byte pages");
|
||||
dwarnln(" supported page sizes:");
|
||||
for (size_t i = 0; i < 16; i++)
|
||||
if (page_size_bits & (1 << i))
|
||||
dwarnln(" {} bytes", 1 << (12 + i));
|
||||
if (__builtin_popcount(page_size_bits) != 1)
|
||||
dwarnln(" ... XHCI spec only allows a single supported page size???");
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
}
|
||||
|
||||
// allocate and program dcbaa
|
||||
m_dcbaa_region = TRY(DMARegion::create(capabilities.hcsparams1.max_slots * 8));
|
||||
memset(reinterpret_cast<void*>(m_dcbaa_region->vaddr()), 0, m_dcbaa_region->size());
|
||||
|
|
@ -289,6 +301,9 @@ namespace Kernel
|
|||
const paddr_t paddr = Heap::get().take_free_page();
|
||||
if (paddr == 0)
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
PageTable::with_fast_page(paddr, [] {
|
||||
memset(PageTable::fast_page_as_ptr(), 0, PAGE_SIZE);
|
||||
});
|
||||
m_scratchpad_buffers[i] = paddr;
|
||||
scratchpad_buffer_array[i] = paddr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@
|
|||
#include <kernel/IDT.h>
|
||||
#include <kernel/Input/PS2/Controller.h>
|
||||
#include <kernel/InterruptController.h>
|
||||
#include <kernel/kprint.h>
|
||||
#include <kernel/Memory/Heap.h>
|
||||
#include <kernel/Memory/kmalloc.h>
|
||||
#include <kernel/Memory/PageTable.h>
|
||||
|
|
|
|||
|
|
@ -179,6 +179,7 @@ const char* strerrordesc_np(int error)
|
|||
case EWOULDBLOCK: return "Operation would block.";
|
||||
case EXDEV: return "Cross-device link.";
|
||||
case ENOTBLK: return "Block device required";
|
||||
case ESHUTDOWN: return "Cannot send after transport endpoint shutdown.";
|
||||
case EUNKNOWN: return "Unknown error";
|
||||
}
|
||||
return nullptr;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
*/*
|
||||
!*/patches/
|
||||
!*/build.sh
|
||||
.installed_ports
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
diff -ruN SDL2-2.32.8/cmake/sdlplatform.cmake SDL2-2.32.8-banan_os/cmake/sdlplatform.cmake
|
||||
--- SDL2-2.32.8/cmake/sdlplatform.cmake 2024-08-14 13:35:43.000000000 +0300
|
||||
+++ SDL2-2.32.8-banan_os/cmake/sdlplatform.cmake 2025-08-06 02:07:18.347821313 +0300
|
||||
+++ SDL2-2.32.8-banan_os/cmake/sdlplatform.cmake 2025-11-22 00:45:00.922311100 +0200
|
||||
@@ -28,6 +28,8 @@
|
||||
set(SDL_CMAKE_PLATFORM AIX)
|
||||
elseif(CMAKE_SYSTEM_NAME MATCHES "Minix.*")
|
||||
|
|
@ -12,7 +12,7 @@ diff -ruN SDL2-2.32.8/cmake/sdlplatform.cmake SDL2-2.32.8-banan_os/cmake/sdlplat
|
|||
endif()
|
||||
diff -ruN SDL2-2.32.8/CMakeLists.txt SDL2-2.32.8-banan_os/CMakeLists.txt
|
||||
--- SDL2-2.32.8/CMakeLists.txt 2025-06-03 02:00:39.000000000 +0300
|
||||
+++ SDL2-2.32.8-banan_os/CMakeLists.txt 2025-08-06 02:19:44.864415796 +0300
|
||||
+++ SDL2-2.32.8-banan_os/CMakeLists.txt 2025-11-22 00:45:00.923441418 +0200
|
||||
@@ -14,7 +14,7 @@
|
||||
set(SDL2_SUBPROJECT ON)
|
||||
endif()
|
||||
|
|
@ -55,7 +55,7 @@ diff -ruN SDL2-2.32.8/CMakeLists.txt SDL2-2.32.8-banan_os/CMakeLists.txt
|
|||
+ file(GLOB VIDEO_SOURCES ${SDL2_SOURCE_DIR}/src/video/banan_os/*.cpp)
|
||||
+ list(APPEND SOURCE_FILES ${VIDEO_SOURCES})
|
||||
+ set(HAVE_SDL_VIDEO TRUE)
|
||||
+ list(APPEND EXTRA_LIBS gui input)
|
||||
+ list(APPEND EXTRA_LIBS gui input clipboard)
|
||||
+
|
||||
+ if(SDL_OPENGL)
|
||||
+ set(SDL_VIDEO_OPENGL 1)
|
||||
|
|
@ -91,7 +91,7 @@ diff -ruN SDL2-2.32.8/CMakeLists.txt SDL2-2.32.8-banan_os/CMakeLists.txt
|
|||
file(GLOB MISC_SOURCES ${SDL2_SOURCE_DIR}/src/misc/riscos/*.c)
|
||||
diff -ruN SDL2-2.32.8/include/SDL_config.h.cmake SDL2-2.32.8-banan_os/include/SDL_config.h.cmake
|
||||
--- SDL2-2.32.8/include/SDL_config.h.cmake 2025-01-01 17:47:53.000000000 +0200
|
||||
+++ SDL2-2.32.8-banan_os/include/SDL_config.h.cmake 2025-08-06 02:01:21.085539504 +0300
|
||||
+++ SDL2-2.32.8-banan_os/include/SDL_config.h.cmake 2025-11-22 00:45:00.924001549 +0200
|
||||
@@ -307,6 +307,7 @@
|
||||
#cmakedefine SDL_AUDIO_DRIVER_FUSIONSOUND @SDL_AUDIO_DRIVER_FUSIONSOUND@
|
||||
#cmakedefine SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC @SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC@
|
||||
|
|
@ -110,7 +110,7 @@ diff -ruN SDL2-2.32.8/include/SDL_config.h.cmake SDL2-2.32.8-banan_os/include/SD
|
|||
#cmakedefine SDL_VIDEO_DRIVER_DIRECTFB @SDL_VIDEO_DRIVER_DIRECTFB@
|
||||
diff -ruN SDL2-2.32.8/include/SDL_platform.h SDL2-2.32.8-banan_os/include/SDL_platform.h
|
||||
--- SDL2-2.32.8/include/SDL_platform.h 2025-01-01 17:47:53.000000000 +0200
|
||||
+++ SDL2-2.32.8-banan_os/include/SDL_platform.h 2025-08-06 02:01:21.085701327 +0300
|
||||
+++ SDL2-2.32.8-banan_os/include/SDL_platform.h 2025-11-22 00:45:00.924303894 +0200
|
||||
@@ -36,6 +36,10 @@
|
||||
#undef __HAIKU__
|
||||
#define __HAIKU__ 1
|
||||
|
|
@ -124,7 +124,7 @@ diff -ruN SDL2-2.32.8/include/SDL_platform.h SDL2-2.32.8-banan_os/include/SDL_pl
|
|||
#define __BSDI__ 1
|
||||
diff -ruN SDL2-2.32.8/src/audio/banan_os/SDL_banan_os_audio.cpp SDL2-2.32.8-banan_os/src/audio/banan_os/SDL_banan_os_audio.cpp
|
||||
--- SDL2-2.32.8/src/audio/banan_os/SDL_banan_os_audio.cpp 1970-01-01 02:00:00.000000000 +0200
|
||||
+++ SDL2-2.32.8-banan_os/src/audio/banan_os/SDL_banan_os_audio.cpp 2025-08-06 02:01:21.085876490 +0300
|
||||
+++ SDL2-2.32.8-banan_os/src/audio/banan_os/SDL_banan_os_audio.cpp 2025-11-22 00:45:00.924702550 +0200
|
||||
@@ -0,0 +1,150 @@
|
||||
+/*
|
||||
+ Simple DirectMedia Layer
|
||||
|
|
@ -278,7 +278,7 @@ diff -ruN SDL2-2.32.8/src/audio/banan_os/SDL_banan_os_audio.cpp SDL2-2.32.8-bana
|
|||
+#endif
|
||||
diff -ruN SDL2-2.32.8/src/audio/banan_os/SDL_banan_os_audio.h SDL2-2.32.8-banan_os/src/audio/banan_os/SDL_banan_os_audio.h
|
||||
--- SDL2-2.32.8/src/audio/banan_os/SDL_banan_os_audio.h 1970-01-01 02:00:00.000000000 +0200
|
||||
+++ SDL2-2.32.8-banan_os/src/audio/banan_os/SDL_banan_os_audio.h 2025-08-06 02:01:21.085937043 +0300
|
||||
+++ SDL2-2.32.8-banan_os/src/audio/banan_os/SDL_banan_os_audio.h 2025-11-22 00:45:00.924820303 +0200
|
||||
@@ -0,0 +1,34 @@
|
||||
+/*
|
||||
+ Simple DirectMedia Layer
|
||||
|
|
@ -316,7 +316,7 @@ diff -ruN SDL2-2.32.8/src/audio/banan_os/SDL_banan_os_audio.h SDL2-2.32.8-banan_
|
|||
+};
|
||||
diff -ruN SDL2-2.32.8/src/audio/SDL_audio.c SDL2-2.32.8-banan_os/src/audio/SDL_audio.c
|
||||
--- SDL2-2.32.8/src/audio/SDL_audio.c 2025-01-01 17:47:53.000000000 +0200
|
||||
+++ SDL2-2.32.8-banan_os/src/audio/SDL_audio.c 2025-08-06 02:01:21.086082872 +0300
|
||||
+++ SDL2-2.32.8-banan_os/src/audio/SDL_audio.c 2025-11-22 00:45:00.925178591 +0200
|
||||
@@ -87,6 +87,9 @@
|
||||
#ifdef SDL_AUDIO_DRIVER_HAIKU
|
||||
&HAIKUAUDIO_bootstrap,
|
||||
|
|
@ -329,7 +329,7 @@ diff -ruN SDL2-2.32.8/src/audio/SDL_audio.c SDL2-2.32.8-banan_os/src/audio/SDL_a
|
|||
#endif
|
||||
diff -ruN SDL2-2.32.8/src/audio/SDL_sysaudio.h SDL2-2.32.8-banan_os/src/audio/SDL_sysaudio.h
|
||||
--- SDL2-2.32.8/src/audio/SDL_sysaudio.h 2025-01-01 17:47:53.000000000 +0200
|
||||
+++ SDL2-2.32.8-banan_os/src/audio/SDL_sysaudio.h 2025-08-06 02:01:21.086309718 +0300
|
||||
+++ SDL2-2.32.8-banan_os/src/audio/SDL_sysaudio.h 2025-11-22 00:45:00.925759535 +0200
|
||||
@@ -196,6 +196,7 @@
|
||||
extern AudioBootStrap WINMM_bootstrap;
|
||||
extern AudioBootStrap PAUDIO_bootstrap;
|
||||
|
|
@ -340,7 +340,7 @@ diff -ruN SDL2-2.32.8/src/audio/SDL_sysaudio.h SDL2-2.32.8-banan_os/src/audio/SD
|
|||
extern AudioBootStrap DUMMYAUDIO_bootstrap;
|
||||
diff -ruN SDL2-2.32.8/src/misc/banan_os/SDL_sysurl.cpp SDL2-2.32.8-banan_os/src/misc/banan_os/SDL_sysurl.cpp
|
||||
--- SDL2-2.32.8/src/misc/banan_os/SDL_sysurl.cpp 1970-01-01 02:00:00.000000000 +0200
|
||||
+++ SDL2-2.32.8-banan_os/src/misc/banan_os/SDL_sysurl.cpp 2025-08-06 02:01:21.086457363 +0300
|
||||
+++ SDL2-2.32.8-banan_os/src/misc/banan_os/SDL_sysurl.cpp 2025-11-22 00:45:00.926117334 +0200
|
||||
@@ -0,0 +1,30 @@
|
||||
+/*
|
||||
+ Simple DirectMedia Layer
|
||||
|
|
@ -372,9 +372,111 @@ diff -ruN SDL2-2.32.8/src/misc/banan_os/SDL_sysurl.cpp SDL2-2.32.8-banan_os/src/
|
|||
+
|
||||
+/* vi: set ts=4 sw=4 expandtab: */
|
||||
+
|
||||
diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_clipboard.cpp SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_clipboard.cpp
|
||||
--- SDL2-2.32.8/src/video/banan_os/SDL_banan_os_clipboard.cpp 1970-01-01 02:00:00.000000000 +0200
|
||||
+++ SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_clipboard.cpp 2025-11-22 01:10:01.840984523 +0200
|
||||
@@ -0,0 +1,51 @@
|
||||
+/*
|
||||
+ Simple DirectMedia Layer
|
||||
+ Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
+
|
||||
+ This software is provided 'as-is', without any express or implied
|
||||
+ warranty. In no event will the authors be held liable for any damages
|
||||
+ arising from the use of this software.
|
||||
+
|
||||
+ Permission is granted to anyone to use this software for any purpose,
|
||||
+ including commercial applications, and to alter it and redistribute it
|
||||
+ freely, subject to the following restrictions:
|
||||
+
|
||||
+ 1. The origin of this software must not be misrepresented; you must not
|
||||
+ claim that you wrote the original software. If you use this software
|
||||
+ in a product, an acknowledgment in the product documentation would be
|
||||
+ appreciated but is not required.
|
||||
+ 2. Altered source versions must be plainly marked as such, and must not be
|
||||
+ misrepresented as being the original software.
|
||||
+ 3. This notice may not be removed or altered from any source distribution.
|
||||
+*/
|
||||
+#include "../../SDL_internal.h"
|
||||
+
|
||||
+#ifdef SDL_VIDEO_DRIVER_BANANOS
|
||||
+
|
||||
+#include "SDL_banan_os_clipboard.h"
|
||||
+
|
||||
+#include <LibClipboard/Clipboard.h>
|
||||
+
|
||||
+int BANANOS_SetClipboardText(_THIS, const char *text) {
|
||||
+ if (LibClipboard::Clipboard::set_clipboard_text(text).is_error())
|
||||
+ return -1;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+char *BANANOS_GetClipboardText(_THIS) {
|
||||
+ auto text_or_error = LibClipboard::Clipboard::get_clipboard_text();
|
||||
+ if (text_or_error.is_error())
|
||||
+ return NULL;
|
||||
+ return SDL_strdup(text_or_error.value().data());
|
||||
+}
|
||||
+
|
||||
+SDL_bool BANANOS_HasClipboardText(_THIS) {
|
||||
+ auto text_or_error = LibClipboard::Clipboard::get_clipboard_text();
|
||||
+ if (text_or_error.is_error())
|
||||
+ return SDL_FALSE;
|
||||
+ return text_or_error.value().empty() ? SDL_FALSE : SDL_TRUE;
|
||||
+}
|
||||
+
|
||||
+#endif /* SDL_VIDEO_DRIVER_BANANOS */
|
||||
+
|
||||
+/* vi: set ts=4 sw=4 expandtab: */
|
||||
diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_clipboard.h SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_clipboard.h
|
||||
--- SDL2-2.32.8/src/video/banan_os/SDL_banan_os_clipboard.h 1970-01-01 02:00:00.000000000 +0200
|
||||
+++ SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_clipboard.h 2025-11-22 01:10:16.932880273 +0200
|
||||
@@ -0,0 +1,43 @@
|
||||
+/*
|
||||
+ Simple DirectMedia Layer
|
||||
+ Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
+
|
||||
+ This software is provided 'as-is', without any express or implied
|
||||
+ warranty. In no event will the authors be held liable for any damages
|
||||
+ arising from the use of this software.
|
||||
+
|
||||
+ Permission is granted to anyone to use this software for any purpose,
|
||||
+ including commercial applications, and to alter it and redistribute it
|
||||
+ freely, subject to the following restrictions:
|
||||
+
|
||||
+ 1. The origin of this software must not be misrepresented; you must not
|
||||
+ claim that you wrote the original software. If you use this software
|
||||
+ in a product, an acknowledgment in the product documentation would be
|
||||
+ appreciated but is not required.
|
||||
+ 2. Altered source versions must be plainly marked as such, and must not be
|
||||
+ misrepresented as being the original software.
|
||||
+ 3. This notice may not be removed or altered from any source distribution.
|
||||
+*/
|
||||
+
|
||||
+#ifndef SDL_BANANOS_CLIPBOARD_H
|
||||
+#define SDL_BANANOS_CLIPBOARD_H
|
||||
+
|
||||
+#include "../../SDL_internal.h"
|
||||
+
|
||||
+#include "../SDL_sysvideo.h"
|
||||
+
|
||||
+#ifdef __cplusplus
|
||||
+extern "C" {
|
||||
+#endif
|
||||
+
|
||||
+extern int BANANOS_SetClipboardText(_THIS, const char *text);
|
||||
+extern char *BANANOS_GetClipboardText(_THIS);
|
||||
+extern SDL_bool BANANOS_HasClipboardText(_THIS);
|
||||
+
|
||||
+#ifdef __cplusplus
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+#endif
|
||||
+
|
||||
+/* vi: set ts=4 sw=4 expandtab: */
|
||||
diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_message_box.cpp SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_message_box.cpp
|
||||
--- SDL2-2.32.8/src/video/banan_os/SDL_banan_os_message_box.cpp 1970-01-01 02:00:00.000000000 +0200
|
||||
+++ SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_message_box.cpp 2025-08-06 02:01:21.086557935 +0300
|
||||
+++ SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_message_box.cpp 2025-11-22 00:45:00.926337964 +0200
|
||||
@@ -0,0 +1,60 @@
|
||||
+/*
|
||||
+ Simple DirectMedia Layer
|
||||
|
|
@ -438,7 +540,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_message_box.cpp SDL2-2.32.
|
|||
+/* vi: set ts=4 sw=4 expandtab: */
|
||||
diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_message_box.h SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_message_box.h
|
||||
--- SDL2-2.32.8/src/video/banan_os/SDL_banan_os_message_box.h 1970-01-01 02:00:00.000000000 +0200
|
||||
+++ SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_message_box.h 2025-08-06 02:01:21.086603053 +0300
|
||||
+++ SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_message_box.h 2025-11-22 00:45:00.926434625 +0200
|
||||
@@ -0,0 +1,45 @@
|
||||
+/*
|
||||
+ Simple DirectMedia Layer
|
||||
|
|
@ -487,8 +589,8 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_message_box.h SDL2-2.32.8-
|
|||
+/* vi: set ts=4 sw=4 expandtab: */
|
||||
diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_video.cpp
|
||||
--- SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp 1970-01-01 02:00:00.000000000 +0200
|
||||
+++ SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_video.cpp 2025-08-21 02:32:59.649175565 +0300
|
||||
@@ -0,0 +1,724 @@
|
||||
+++ SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_video.cpp 2025-11-22 01:08:26.204647073 +0200
|
||||
@@ -0,0 +1,729 @@
|
||||
+/*
|
||||
+ Simple DirectMedia Layer
|
||||
+ Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
|
|
@ -518,6 +620,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-bana
|
|||
+#include "../../events/SDL_events_c.h"
|
||||
+}
|
||||
+
|
||||
+#include "SDL_banan_os_clipboard.h"
|
||||
+#include "SDL_banan_os_message_box.h"
|
||||
+
|
||||
+#include <BAN/Debug.h>
|
||||
|
|
@ -1199,6 +1302,10 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-bana
|
|||
+ device->GL_MakeCurrent = BANANOS_GL_MakeCurrent;
|
||||
+ device->GL_SwapWindow = BANANOS_GL_SwapWindow;
|
||||
+
|
||||
+ device->SetClipboardText = BANANOS_SetClipboardText;
|
||||
+ device->GetClipboardText = BANANOS_GetClipboardText;
|
||||
+ device->HasClipboardText = BANANOS_HasClipboardText;
|
||||
+
|
||||
+ device->free = BANANOS_free;
|
||||
+
|
||||
+ return device;
|
||||
|
|
@ -1215,7 +1322,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-bana
|
|||
+/* vi: set ts=4 sw=4 expandtab: */
|
||||
diff -ruN SDL2-2.32.8/src/video/SDL_sysvideo.h SDL2-2.32.8-banan_os/src/video/SDL_sysvideo.h
|
||||
--- SDL2-2.32.8/src/video/SDL_sysvideo.h 2025-05-20 00:24:41.000000000 +0300
|
||||
+++ SDL2-2.32.8-banan_os/src/video/SDL_sysvideo.h 2025-08-06 02:01:21.086873550 +0300
|
||||
+++ SDL2-2.32.8-banan_os/src/video/SDL_sysvideo.h 2025-11-22 00:45:00.927152737 +0200
|
||||
@@ -462,6 +462,7 @@
|
||||
extern VideoBootStrap WINDOWS_bootstrap;
|
||||
extern VideoBootStrap WINRT_bootstrap;
|
||||
|
|
@ -1226,7 +1333,7 @@ diff -ruN SDL2-2.32.8/src/video/SDL_sysvideo.h SDL2-2.32.8-banan_os/src/video/SD
|
|||
extern VideoBootStrap Android_bootstrap;
|
||||
diff -ruN SDL2-2.32.8/src/video/SDL_video.c SDL2-2.32.8-banan_os/src/video/SDL_video.c
|
||||
--- SDL2-2.32.8/src/video/SDL_video.c 2025-05-20 00:24:41.000000000 +0300
|
||||
+++ SDL2-2.32.8-banan_os/src/video/SDL_video.c 2025-08-06 02:01:21.087224294 +0300
|
||||
+++ SDL2-2.32.8-banan_os/src/video/SDL_video.c 2025-11-22 00:45:00.928264617 +0200
|
||||
@@ -96,6 +96,9 @@
|
||||
#ifdef SDL_VIDEO_DRIVER_HAIKU
|
||||
&HAIKU_bootstrap,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
#!/bin/bash ../install.sh
|
||||
|
||||
NAME='SDL2_image'
|
||||
VERSION='2.8.8'
|
||||
DOWNLOAD_URL="https://github.com/libsdl-org/SDL_image/releases/download/release-$VERSION/SDL2_image-$VERSION.tar.gz#2213b56fdaff2220d0e38c8e420cbe1a83c87374190cba8c70af2156097ce30a"
|
||||
DEPENDENCIES=('SDL2' 'libpng' 'libjpeg' 'libtiff' 'libwebp')
|
||||
|
||||
configure() {
|
||||
$BANAN_CMAKE --fresh -S . -B build -G Ninja \
|
||||
--toolchain="$BANAN_TOOLCHAIN_DIR/Toolchain.txt" \
|
||||
-DCMAKE_INSTALL_PREFIX='/usr' \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DSDL2IMAGE_AVIF=OFF \
|
||||
|| exit 1
|
||||
}
|
||||
|
||||
build() {
|
||||
$BANAN_CMAKE --build build || exit 1
|
||||
}
|
||||
|
||||
install() {
|
||||
$BANAN_CMAKE --install build || exit 1
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
#!/bin/bash ../install.sh
|
||||
|
||||
NAME='SDL_mixer'
|
||||
VERSION='1.2.12'
|
||||
DOWNLOAD_URL="https://github.com/libsdl-org/SDL_mixer/archive/refs/tags/release-$VERSION.tar.gz#4176dfc887664419bfd16c41013c6cf0c48eca6b95ae3c34205630e8a7a94faa"
|
||||
TAR_CONTENT="SDL_mixer-release-$VERSION"
|
||||
CONFIG_SUB=('build-scripts/config.sub')
|
||||
DEPENDENCIES=('libmikmod' 'libiconv' 'sdl12-compat')
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
diff -ruN SDL_mixer-1.2.12/configure SDL_mixer-1.2.12-banan_os/configure
|
||||
--- SDL_mixer-1.2.12/configure 2012-01-16 00:00:28.000000000 +0200
|
||||
+++ SDL_mixer-1.2.12-banan_os/configure 2025-11-16 03:27:17.615555034 +0200
|
||||
@@ -4073,6 +4073,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
|
||||
;;
|
||||
@@ -9083,6 +9087,16 @@
|
||||
esac
|
||||
;;
|
||||
|
||||
+banan_os*)
|
||||
+ version_type=linux # correct to gnu/linux during the next big refactor
|
||||
+ need_lib_prefix=no
|
||||
+ need_version=no
|
||||
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
|
||||
+ soname_spec='$libname$release$shared_ext$major'
|
||||
+ dynamic_linker="$host_os DynamicLoader.so"
|
||||
+ shlibpath_var=LD_LIBRARY_PATH
|
||||
+ ;;
|
||||
+
|
||||
beos*)
|
||||
library_names_spec='${libname}${shared_ext}'
|
||||
dynamic_linker="$host_os ld.so"
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
#!/bin/bash ../install.sh
|
||||
|
||||
NAME='SuperTux'
|
||||
VERSION='0.6.3'
|
||||
DOWNLOAD_URL="https://github.com/SuperTux/supertux/releases/download/v$VERSION/SuperTux-v$VERSION-Source.tar.gz#f7940e6009c40226eb34ebab8ffb0e3a894892d891a07b35d0e5762dd41c79f6"
|
||||
TAR_CONTENT="SuperTux-v$VERSION-Source"
|
||||
DEPENDENCIES=('boost' 'SDL2' 'SDL2_image' 'curl' 'openal-soft' 'libvorbis' 'freetype' 'physfs' 'glm')
|
||||
|
||||
configure() {
|
||||
mkdir -p build
|
||||
pushd build
|
||||
$BANAN_CMAKE \
|
||||
--toolchain="$BANAN_TOOLCHAIN_DIR/Toolchain.txt" \
|
||||
-G Ninja --fresh .. \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DINSTALL_SUBDIR_BIN=bin \
|
||||
-DBUILD_DOCUMENTATION=OFF \
|
||||
-DENABLE_OPENGL=OFF \
|
||||
-DENABLE_BOOST_STATIC_LIBS=ON \
|
||||
|| exit 1
|
||||
popd
|
||||
# crashes in `std::ostream::sentry::sentry(std::ostream&)` with shared boost
|
||||
}
|
||||
|
||||
build() {
|
||||
$BANAN_CMAKE --build build || exit 1
|
||||
}
|
||||
|
||||
install() {
|
||||
$BANAN_CMAKE --install build || exit 1
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
diff -ruN SuperTux-0.6.3/CMakeLists.txt SuperTux-0.6.3-banan_os/CMakeLists.txt
|
||||
--- SuperTux-0.6.3/CMakeLists.txt 2021-12-23 01:01:57.000000000 +0200
|
||||
+++ SuperTux-0.6.3-banan_os/CMakeLists.txt 2025-11-02 20:57:03.725932455 +0200
|
||||
@@ -171,7 +171,7 @@
|
||||
else(ENABLE_BOOST_STATIC_LIBS)
|
||||
set(Boost_USE_STATIC_LIBS FALSE)
|
||||
endif(ENABLE_BOOST_STATIC_LIBS)
|
||||
-find_package(Boost REQUIRED COMPONENTS filesystem system date_time locale)
|
||||
+find_package(Boost REQUIRED COMPONENTS filesystem date_time locale)
|
||||
include_directories(SYSTEM ${Boost_INCLUDE_DIR})
|
||||
link_directories(${Boost_LIBRARY_DIRS})
|
||||
|
||||
@@ -507,6 +507,7 @@
|
||||
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
|
||||
-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}
|
||||
-DCMAKE_INSTALL_PREFIX=${SQUIRREL_PREFIX}
|
||||
+ -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}
|
||||
-DINSTALL_INC_DIR=include
|
||||
-DCMAKE_POSITION_INDEPENDENT_CODE=ON)
|
||||
|
||||
@@ -966,7 +967,7 @@
|
||||
endif()
|
||||
endif()
|
||||
target_include_directories(supertux2_lib SYSTEM PUBLIC ${SDL_TTF_PREFIX}/include/SDL2)
|
||||
-target_link_libraries(supertux2_lib PUBLIC SDL_ttf_lib)
|
||||
+target_link_libraries(supertux2_lib PUBLIC libSDL2_ttf.a)
|
||||
if(VCPKG_BUILD)
|
||||
target_link_libraries(supertux2_lib PUBLIC freetype)
|
||||
else()
|
||||
@@ -977,9 +978,10 @@
|
||||
target_link_libraries(supertux2_lib PUBLIC ${HARFBUZZ_LIBRARY} ${FRIBIDI_LIBRARY} ${RAQM_LIBRARY})
|
||||
endif()
|
||||
|
||||
-target_link_libraries(supertux2_lib PUBLIC squirrel_lib)
|
||||
-target_link_libraries(supertux2_lib PUBLIC sqstdlib_lib)
|
||||
-target_link_libraries(supertux2_lib PUBLIC tinygettext_lib)
|
||||
+target_link_libraries(supertux2_lib PUBLIC libsquirrel_static.a)
|
||||
+target_link_libraries(supertux2_lib PUBLIC libsqstdlib_static.a)
|
||||
+target_link_libraries(supertux2_lib PUBLIC libtinygettext.a)
|
||||
+
|
||||
target_link_libraries(supertux2_lib PUBLIC sexp)
|
||||
target_link_libraries(supertux2_lib PUBLIC savepng)
|
||||
target_link_libraries(supertux2_lib PUBLIC partio_zip_lib)
|
||||
@@ -1025,7 +1027,7 @@
|
||||
if(VCPKG_BUILD)
|
||||
target_link_libraries(supertux2_lib PUBLIC ${CURL_LIBRARIES})
|
||||
else()
|
||||
- target_link_libraries(supertux2_lib PUBLIC ${CURL_LIBRARY})
|
||||
+ target_link_libraries(supertux2_lib PUBLIC ${CURL_LIBRARY} ssl crypto zstd z)
|
||||
endif()
|
||||
endif(HAVE_LIBCURL)
|
||||
endif(NOT EMSCRIPTEN)
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
diff -ruN SuperTux-0.6.3/external/partio_zip/zip_manager.hpp SuperTux-0.6.3-banan_os/external/partio_zip/zip_manager.hpp
|
||||
--- SuperTux-0.6.3/external/partio_zip/zip_manager.hpp 2021-12-23 01:01:58.000000000 +0200
|
||||
+++ SuperTux-0.6.3-banan_os/external/partio_zip/zip_manager.hpp 2025-11-02 20:16:29.691656288 +0200
|
||||
@@ -44,6 +44,7 @@
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
+#include <memory>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
#!/bin/bash ../install.sh
|
||||
|
||||
NAME='binutils'
|
||||
VERSION='2.44'
|
||||
DOWNLOAD_URL="https://ftpmirror.gnu.org/gnu/binutils/binutils-$VERSION.tar.gz#0cdd76777a0dfd3dd3a63f215f030208ddb91c2361d2bcc02acec0f1c16b6a2e"
|
||||
VERSION='2.45'
|
||||
DOWNLOAD_URL="https://ftpmirror.gnu.org/gnu/binutils/binutils-$VERSION.tar.gz#8a3eb4b10e7053312790f21ee1a38f7e2bbd6f4096abb590d3429e5119592d96"
|
||||
DEPENDENCIES=('zlib' 'zstd')
|
||||
MAKE_INSTALL_TARGETS=('install-strip')
|
||||
CONFIGURE_OPTIONS=(
|
||||
|
|
@ -22,12 +22,3 @@ pre_configure() {
|
|||
unset PKG_CONFIG_LIBDIR
|
||||
unset PKG_CONFIG_PATH
|
||||
}
|
||||
|
||||
post_install() {
|
||||
# remove libtool files
|
||||
rm -f $BANAN_SYSROOT/usr/lib/libbfd.la
|
||||
rm -f $BANAN_SYSROOT/usr/lib/libctf.la
|
||||
rm -f $BANAN_SYSROOT/usr/lib/libctf-nobfd.la
|
||||
rm -f $BANAN_SYSROOT/usr/lib/libopcodes.la
|
||||
rm -f $BANAN_SYSROOT/usr/lib/libsframe.la
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
../../../toolchain/binutils-2.44.patch
|
||||
|
|
@ -0,0 +1 @@
|
|||
../../../toolchain/binutils-2.45.patch
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#!/bin/bash ../install.sh
|
||||
|
||||
NAME='boost'
|
||||
VERSION='1.89.0'
|
||||
DOWNLOAD_URL="https://archives.boost.io/release/$VERSION/source/boost_${VERSION//./_}.tar.gz#9de758db755e8330a01d995b0a24d09798048400ac25c03fc5ea9be364b13c93"
|
||||
TAR_CONTENT="boost_${VERSION//./_}"
|
||||
DEPENDENCIES=('zlib' 'zstd' 'libiconv')
|
||||
|
||||
configure() {
|
||||
# stacktrace fails on multiple definition of __cxa_allocate_exception because our libstdc++ is static
|
||||
./bootstrap.sh \
|
||||
--prefix="$BANAN_SYSROOT/usr" \
|
||||
--without-icu \
|
||||
--without-libraries='python,stacktrace' \
|
||||
|| exit 1
|
||||
echo "using gcc : : $CXX ;" > user-config.jam
|
||||
}
|
||||
|
||||
build() {
|
||||
./b2 --user-config=user-config.jam toolset=gcc target-os=banan_os || exit 1
|
||||
}
|
||||
|
||||
install() {
|
||||
./b2 --user-config=user-config.jam toolset=gcc target-os=banan_os install || exit 1
|
||||
}
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
diff -ruN boost_1_89_0/boost/config/detail/select_platform_config.hpp boost_1_89_0-banan_os/boost/config/detail/select_platform_config.hpp
|
||||
--- boost_1_89_0/boost/config/detail/select_platform_config.hpp 2025-08-06 21:49:08.000000000 +0300
|
||||
+++ boost_1_89_0-banan_os/boost/config/detail/select_platform_config.hpp 2025-10-29 21:16:39.964658105 +0200
|
||||
@@ -93,6 +93,10 @@
|
||||
// Web assembly:
|
||||
# define BOOST_PLATFORM_CONFIG "boost/config/platform/wasm.hpp"
|
||||
|
||||
+#elif defined (__banan_os__)
|
||||
+// banan-os:
|
||||
+# define BOOST_PLATFORM_CONFIG "boost/config/platform/banan-os.hpp"
|
||||
+
|
||||
#else
|
||||
|
||||
# if defined(unix) \
|
||||
@@ -139,6 +143,7 @@
|
||||
# include "boost/config/platform/symbian.hpp"
|
||||
# include "boost/config/platform/cray.hpp"
|
||||
# include "boost/config/platform/vms.hpp"
|
||||
+# include "boost/config/platform/banan-os.hpp"
|
||||
# include <boost/config/detail/posix_features.hpp>
|
||||
|
||||
|
||||
diff -ruN boost_1_89_0/boost/config/platform/banan-os.hpp boost_1_89_0-banan_os/boost/config/platform/banan-os.hpp
|
||||
--- boost_1_89_0/boost/config/platform/banan-os.hpp 1970-01-01 02:00:00.000000000 +0200
|
||||
+++ boost_1_89_0-banan_os/boost/config/platform/banan-os.hpp 2025-10-29 21:21:58.791813238 +0200
|
||||
@@ -0,0 +1,29 @@
|
||||
+// (C) Copyright Oskari Alaranta 2025.
|
||||
+// Use, modification and distribution are subject to the
|
||||
+// Boost Software License, Version 1.0. (See accompanying file
|
||||
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
+
|
||||
+// See http://www.boost.org for most recent version.
|
||||
+
|
||||
+// banan-os specific config options:
|
||||
+
|
||||
+#define BOOST_PLATFORM "banan-os"
|
||||
+
|
||||
+#define BOOST_HAS_UNISTD_H
|
||||
+#define BOOST_HAS_STDINT_H
|
||||
+
|
||||
+#ifndef BOOST_DISABLE_THREADS
|
||||
+# define BOOST_HAS_THREADS
|
||||
+#endif
|
||||
+
|
||||
+//
|
||||
+// thread API's not auto detected:
|
||||
+//
|
||||
+#define BOOST_HAS_SCHED_YIELD
|
||||
+#define BOOST_HAS_GETTIMEOFDAY
|
||||
+
|
||||
+// boilerplate code:
|
||||
+#include <boost/config/detail/posix_features.hpp>
|
||||
+
|
||||
+
|
||||
+
|
||||
diff -ruN boost_1_89_0/tools/build/src/tools/features/os-feature.jam boost_1_89_0-banan_os/tools/build/src/tools/features/os-feature.jam
|
||||
--- boost_1_89_0/tools/build/src/tools/features/os-feature.jam 2025-08-06 21:49:15.000000000 +0300
|
||||
+++ boost_1_89_0-banan_os/tools/build/src/tools/features/os-feature.jam 2025-10-29 21:14:14.978467634 +0200
|
||||
@@ -11,7 +11,7 @@
|
||||
none
|
||||
aix android appletv bsd cygwin darwin freebsd haiku hpux iphone linux
|
||||
netbsd openbsd osf qnx qnxnto sgi solaris unix unixware windows vms vxworks
|
||||
- freertos
|
||||
+ freertos banan_os
|
||||
|
||||
# Not actually an OS -- used for targeting bare metal where object
|
||||
# format is ELF. This catches both -elf and -eabi gcc targets as well
|
||||
@@ -80,7 +80,7 @@
|
||||
*Allowed values:* `aix`, `android`, `appletv`, `bsd`, `cygwin`, `darwin`,
|
||||
`freebsd`, `haiku`, `hpux`, `iphone`, `linux`, `netbsd`, `openbsd`, `osf`,
|
||||
`qnx`, `qnxnto`, `sgi`, `solaris`, `unix`, `unixware`, `windows`, `vms`,
|
||||
-`vxworks`, `freertos`.
|
||||
+`vxworks`, `freertos`, `banan_os`.
|
||||
+
|
||||
Specifies the operating system for which the code is to be generated. The
|
||||
compiler you used should be the compiler for that operating system. This option
|
||||
diff -ruN boost_1_89_0/tools/build/src/tools/gcc.jam boost_1_89_0-banan_os/tools/build/src/tools/gcc.jam
|
||||
--- boost_1_89_0/tools/build/src/tools/gcc.jam 2025-08-06 21:49:15.000000000 +0300
|
||||
+++ boost_1_89_0-banan_os/tools/build/src/tools/gcc.jam 2025-10-29 21:12:59.730889504 +0200
|
||||
@@ -204,6 +204,7 @@
|
||||
case *linux* : target-os ?= linux ;
|
||||
case *aix* : target-os ?= aix ;
|
||||
case *hpux* : target-os ?= hpux ;
|
||||
+ case *banan_os* : target-os ?= banan_os ;
|
||||
# TODO: finish this list.
|
||||
}
|
||||
}
|
||||
@@ -406,6 +407,7 @@
|
||||
threading-flags <target-os>cygwin/<threadapi>pthread : -pthread ;
|
||||
threading-flags <target-os>solaris : -pthreads : rt ;
|
||||
threading-flags <target-os>qnx : -pthread ;
|
||||
+ threading-flags <target-os>banan_os : -pthread ;
|
||||
|
||||
local bsd = [ MATCH ^(.*bsd)$ : $(all-os) ] ;
|
||||
threading-flags <target-os>$(bsd) : -pthread ;
|
||||
@@ -413,7 +415,7 @@
|
||||
# iOS doesn't need pthread flag according to the https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/pthread.3.html
|
||||
# The default system libraries include pthread functions. No additional libraries or CFLAGS are necessary to use this API.
|
||||
local no-threading = android beos haiku sgi darwin vxworks iphone appletv ;
|
||||
- local threading-generic-os = [ set.difference $(all-os) : $(no-threading) $(bsd) windows cygwin solaris qnx ] ;
|
||||
+ local threading-generic-os = [ set.difference $(all-os) : $(no-threading) $(bsd) windows cygwin solaris qnx banan_os ] ;
|
||||
threading-flags <target-os>$(threading-generic-os) : -pthread : rt ;
|
||||
}
|
||||
|
||||
diff -ruN boost_1_89_0/tools/build/src/tools/python.jam boost_1_89_0-banan_os/tools/build/src/tools/python.jam
|
||||
--- boost_1_89_0/tools/build/src/tools/python.jam 2025-08-06 21:49:15.000000000 +0300
|
||||
+++ boost_1_89_0-banan_os/tools/build/src/tools/python.jam 2025-10-29 21:09:10.276185725 +0200
|
||||
@@ -667,6 +667,7 @@
|
||||
case darwin : return ;
|
||||
case windows : return ;
|
||||
case haiku : return ;
|
||||
+ case banan_os : return ;
|
||||
|
||||
case hpux : return <library>rt ;
|
||||
case *bsd : return <library>pthread <toolset>gcc:<library>util ;
|
||||
|
|
@ -18,8 +18,3 @@ CONFIGURE_OPTIONS=(
|
|||
'--with-ca-bundle=/etc/ssl/certs/ca-certificates.crt'
|
||||
'--without-ca-path'
|
||||
)
|
||||
|
||||
post_install() {
|
||||
# remove libtool file
|
||||
rm -f $BANAN_SYSROOT/usr/lib/libcurl.la
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,8 +4,3 @@ NAME='expat'
|
|||
VERSION='2.7.1'
|
||||
DOWNLOAD_URL="https://github.com/libexpat/libexpat/releases/download/R_2_7_1/expat-$VERSION.tar.gz#0cce2e6e69b327fc607b8ff264f4b66bdf71ead55a87ffd5f3143f535f15cfa2"
|
||||
CONFIG_SUB=('conftools/config.sub')
|
||||
|
||||
post_install() {
|
||||
# remove libtool file
|
||||
rm -f $BANAN_SYSROOT/usr/lib/libexpat.la
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,13 +3,8 @@
|
|||
NAME='freetype'
|
||||
VERSION='2.13.3'
|
||||
DOWNLOAD_URL="https://download.savannah.gnu.org/releases/freetype/freetype-$VERSION.tar.gz#5c3a8e78f7b24c20b25b54ee575d6daa40007a5f4eea2845861c3409b3021747"
|
||||
DEPENDENCIES=('zlib' 'libpng')
|
||||
CONFIG_SUB=('builds/unix/config.sub')
|
||||
|
||||
CONFIGURE_OPTIONS=(
|
||||
'lt_cv_deplibs_check_method=pass_all'
|
||||
)
|
||||
|
||||
post_install() {
|
||||
# remove libtool file
|
||||
rm -f $BANAN_SYSROOT/usr/lib/libfreetype.la
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,10 +27,3 @@ build() {
|
|||
make -j$(nproc) all-target-libgcc CFLAGS_FOR_TARGET="$xcflags" || exit 1
|
||||
make -j$(nproc) all-target-libstdc++-v3 || exit 1
|
||||
}
|
||||
|
||||
post_install() {
|
||||
# remove libtool files
|
||||
rm -f $BANAN_SYSROOT/usr/lib/libstdc++.la
|
||||
rm -f $BANAN_SYSROOT/usr/lib/libstdc++exp.la
|
||||
rm -f $BANAN_SYSROOT/usr/lib/libsupc++.la
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
#!/bin/bash ../install.sh
|
||||
|
||||
NAME='glm'
|
||||
VERSION='1.0.2'
|
||||
DOWNLOAD_URL="https://github.com/g-truc/glm/archive/refs/tags/$VERSION.tar.gz#19edf2e860297efab1c74950e6076bf4dad9de483826bc95e2e0f2c758a43f65"
|
||||
|
||||
configure() {
|
||||
$BANAN_CMAKE \
|
||||
--toolchain="$BANAN_TOOLCHAIN_DIR/Toolchain.txt" \
|
||||
-B build -G Ninja --fresh . \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DGLM_BUILD_TESTS=OFF \
|
||||
|| exit 1
|
||||
}
|
||||
|
||||
build() {
|
||||
$BANAN_CMAKE --build build || exit 1
|
||||
}
|
||||
|
||||
install() {
|
||||
$BANAN_CMAKE --install build || exit 1
|
||||
}
|
||||
|
|
@ -7,8 +7,3 @@ CONFIG_SUB=('configfsf.sub')
|
|||
CONFIGURE_OPTIONS=(
|
||||
'CFLAGS=-std=c17'
|
||||
)
|
||||
|
||||
post_install() {
|
||||
# remove libtool file
|
||||
rm -f $BANAN_SYSROOT/usr/lib/libgmp.la
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,12 @@ fi
|
|||
|
||||
source "$BANAN_ROOT_DIR/script/config.sh"
|
||||
|
||||
installed_file="$BANAN_PORT_DIR/.installed_ports"
|
||||
if [ -z $DONT_REMOVE_INSTALLED ]; then
|
||||
export DONT_REMOVE_INSTALLED=1
|
||||
rm -f "$installed_file"
|
||||
fi
|
||||
|
||||
export PATH="$BANAN_TOOLCHAIN_PREFIX/bin:$PATH"
|
||||
|
||||
export PKG_CONFIG_DIR=''
|
||||
|
|
@ -29,10 +35,6 @@ export OBJDUMP="$BANAN_TOOLCHAIN_TRIPLE-objdump"
|
|||
export STRIP="$BANAN_TOOLCHAIN_TRIPLE-strip"
|
||||
export CXXFILT="$BANAN_TOOLCHAIN_TRIPLE-c++filt"
|
||||
|
||||
pushd "$BANAN_ROOT_DIR" >/dev/null
|
||||
./bos all && ./bos install || exit 1
|
||||
popd >/dev/null
|
||||
|
||||
if [ "$BANAN_ARCH" = "i686" ]; then
|
||||
export LDFLAGS="-shared-libgcc"
|
||||
fi
|
||||
|
|
@ -78,13 +80,17 @@ post_configure() {
|
|||
}
|
||||
|
||||
configure() {
|
||||
pre_configure
|
||||
|
||||
configure_options=("--host=$BANAN_ARCH-pc-banan_os" '--prefix=/usr')
|
||||
configure_options+=("${CONFIGURE_OPTIONS[@]}")
|
||||
./configure "${configure_options[@]}" || exit 1
|
||||
}
|
||||
|
||||
post_configure
|
||||
pre_build() {
|
||||
:
|
||||
}
|
||||
|
||||
post_build() {
|
||||
:
|
||||
}
|
||||
|
||||
build() {
|
||||
|
|
@ -102,13 +108,9 @@ post_install() {
|
|||
}
|
||||
|
||||
install() {
|
||||
pre_install
|
||||
|
||||
for target in "${MAKE_INSTALL_TARGETS[@]}"; do
|
||||
make $target "DESTDIR=$BANAN_SYSROOT" || exit 1
|
||||
done
|
||||
|
||||
post_install
|
||||
}
|
||||
|
||||
source $1
|
||||
|
|
@ -118,7 +120,30 @@ if [ -z $NAME ] || [ -z $VERSION ] || [ -z $DOWNLOAD_URL ]; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
build_dir="$NAME-$VERSION-$BANAN_ARCH"
|
||||
|
||||
if [ ! -d "$build_dir" ]; then
|
||||
rm -f '.compile_hash'
|
||||
fi
|
||||
|
||||
if [ ! -f '.compile_hash' ] && [ -f "$installed_file" ]; then
|
||||
sed -i "/^$NAME-$VERSION$/d" "$installed_file"
|
||||
fi
|
||||
|
||||
if grep -qsxF "$NAME-$VERSION" "$installed_file"; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
pushd "$BANAN_ROOT_DIR" >/dev/null
|
||||
./bos all && ./bos install || exit 1
|
||||
popd >/dev/null
|
||||
|
||||
for dependency in "${DEPENDENCIES[@]}"; do
|
||||
if [ ! -d "../$dependency" ]; then
|
||||
echo "Could not find dependency '$dependency' or port '$NAME'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
pushd "../$dependency" >/dev/null
|
||||
pwd
|
||||
if ! ./build.sh; then
|
||||
|
|
@ -128,12 +153,6 @@ for dependency in "${DEPENDENCIES[@]}"; do
|
|||
popd >/dev/null
|
||||
done
|
||||
|
||||
build_dir="$NAME-$VERSION-$BANAN_ARCH"
|
||||
|
||||
if [ ! -d "$build_dir" ]; then
|
||||
rm -f ".compile_hash"
|
||||
fi
|
||||
|
||||
if [ "$VERSION" = "git" ]; then
|
||||
regex="(.*/.*\.git)#(.*)"
|
||||
|
||||
|
|
@ -186,7 +205,7 @@ else
|
|||
exit 1
|
||||
fi
|
||||
|
||||
regex='(.*\.tar\..*)'
|
||||
regex='(.*\.tar\..*|.*\.tgz)'
|
||||
if [[ $FILE_NAME =~ $regex ]] && [ ! -d "$build_dir" ]; then
|
||||
tar xf "$FILE_NAME" || exit 1
|
||||
|
||||
|
|
@ -219,9 +238,20 @@ cd "$build_dir"
|
|||
|
||||
if (( $needs_compile )); then
|
||||
config_sub_update
|
||||
|
||||
pre_configure
|
||||
configure
|
||||
post_configure
|
||||
|
||||
pre_build
|
||||
build
|
||||
post_build
|
||||
|
||||
sha256sum "$BANAN_SYSROOT/usr/lib/libc.a" > "../.compile_hash"
|
||||
fi
|
||||
|
||||
pre_install
|
||||
install
|
||||
grep -qsxF "$NAME-$VERSION" "$installed_file" || echo "$NAME-$VERSION" >> "$installed_file"
|
||||
post_install
|
||||
find "$BANAN_SYSROOT/usr/lib" -name '*.la' -delete
|
||||
|
|
|
|||
|
|
@ -4,8 +4,3 @@ NAME='libffi'
|
|||
VERSION='3.5.2'
|
||||
DOWNLOAD_URL="https://github.com/libffi/libffi/releases/download/v$VERSION/libffi-$VERSION.tar.gz#f3a3082a23b37c293a4fcd1053147b371f2ff91fa7ea1b2a52e335676bac82dc"
|
||||
CONFIG_SUB=('config.sub')
|
||||
|
||||
post_install() {
|
||||
# remove libtool file
|
||||
rm -f $BANAN_SYSROOT/usr/lib/libffi.la
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,9 +12,3 @@ CONFIGURE_OPTIONS=(
|
|||
pre_configure() {
|
||||
echo '#include_next <sys/types.h>' > srclib/sys_types.in.h
|
||||
}
|
||||
|
||||
post_install() {
|
||||
# remove libtool file
|
||||
rm -f $BANAN_SYSROOT/usr/lib/libcharset.la
|
||||
rm -f $BANAN_SYSROOT/usr/lib/libiconv.la
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,8 +5,3 @@ VERSION='9f'
|
|||
DOWNLOAD_URL="https://www.ijg.org/files/jpegsrc.v9f.tar.gz#04705c110cb2469caa79fb71fba3d7bf834914706e9641a4589485c1f832565b"
|
||||
TAR_CONTENT="jpeg-$VERSION"
|
||||
CONFIG_SUB=('config.sub')
|
||||
|
||||
post_install() {
|
||||
# remove libtool files
|
||||
rm -f $BANAN_SYSROOT/usr/lib/libjpeg.la
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
#!/bin/bash ../install.sh
|
||||
|
||||
NAME='libmikmod'
|
||||
VERSION='3.3.13'
|
||||
DOWNLOAD_URL="https://sourceforge.net/projects/mikmod/files/libmikmod/$VERSION/libmikmod-$VERSION.tar.gz#9fc1799f7ea6a95c7c5882de98be85fc7d20ba0a4a6fcacae11c8c6b382bb207"
|
||||
CONFIG_SUB=('autotools/config.sub')
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
diff -ruN libmikmod-3.3.13/configure libmikmod-3.3.13-banan_os/configure
|
||||
--- libmikmod-3.3.13/configure 2025-04-20 04:55:10.000000000 +0300
|
||||
+++ libmikmod-3.3.13-banan_os/configure 2025-11-16 03:32:52.087690874 +0200
|
||||
@@ -5962,6 +5962,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
|
||||
;;
|
||||
@@ -11733,6 +11737,16 @@
|
||||
esac
|
||||
;;
|
||||
|
||||
+banan_os*)
|
||||
+ version_type=linux # correct to gnu/linux during the next big refactor
|
||||
+ need_lib_prefix=no
|
||||
+ need_version=no
|
||||
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
|
||||
+ soname_spec='$libname$release$shared_ext$major'
|
||||
+ dynamic_linker="$host_os DynamicLoader.so"
|
||||
+ shlibpath_var=LD_LIBRARY_PATH
|
||||
+ ;;
|
||||
+
|
||||
beos*)
|
||||
library_names_spec='$libname$shared_ext'
|
||||
dynamic_linker="$host_os ld.so"
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
#!/bin/bash ../install.sh
|
||||
|
||||
NAME='libogg'
|
||||
VERSION='1.3.6'
|
||||
DOWNLOAD_URL="https://github.com/xiph/ogg/releases/download/v$VERSION/libogg-$VERSION.tar.gz#83e6704730683d004d20e21b8f7f55dcb3383cdf84c0daedf30bde175f774638"
|
||||
CONFIG_SUB=('config.sub')
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
diff -ruN libogg-1.3.6/configure libogg-1.3.6-banan_os/configure
|
||||
--- libogg-1.3.6/configure 2025-06-16 19:02:25.000000000 +0300
|
||||
+++ libogg-1.3.6-banan_os/configure 2025-10-31 22:25:25.050050235 +0200
|
||||
@@ -10622,6 +10622,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"
|
||||
|
|
@ -5,9 +5,3 @@ VERSION='1.6.48'
|
|||
DOWNLOAD_URL="https://download.sourceforge.net/libpng/libpng-$VERSION.tar.gz#68f3d83a79d81dfcb0a439d62b411aa257bb4973d7c67cd1ff8bdf8d011538cd"
|
||||
DEPENDENCIES=('zlib')
|
||||
CONFIG_SUB=('config.sub')
|
||||
|
||||
post_install() {
|
||||
# remove libtool files
|
||||
rm -f $BANAN_SYSROOT/usr/lib/libpng.la
|
||||
rm -f $BANAN_SYSROOT/usr/lib/libpng16.la
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
#!/bin/bash ../install.sh
|
||||
|
||||
NAME='libsndfile'
|
||||
VERSION='1.2.2'
|
||||
DOWNLOAD_URL="https://github.com/libsndfile/libsndfile/releases/download/$VERSION/libsndfile-$VERSION.tar.xz#3799ca9924d3125038880367bf1468e53a1b7e3686a934f098b7e1d286cdb80e"
|
||||
_DEPENDENCIES=('ca-certificates' 'openssl' 'zlib' 'zstd')
|
||||
CONFIG_SUB=('build-aux/config.sub')
|
||||
CONFIGURE_OPTIONS=(
|
||||
'CFLAGS=-std=c11'
|
||||
)
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
diff -ruN libsndfile-1.2.2/configure libsndfile-1.2.2-banan_os/configure
|
||||
--- libsndfile-1.2.2/configure 2023-08-13 12:22:03.000000000 +0300
|
||||
+++ libsndfile-1.2.2-banan_os/configure 2025-08-09 21:50:50.046135494 +0300
|
||||
@@ -10059,6 +10059,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
|
||||
;;
|
||||
@@ -15720,6 +15724,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"
|
||||
@@ -19754,6 +19768,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"
|
||||
|
|
@ -6,9 +6,3 @@ DOWNLOAD_URL="https://download.osgeo.org/libtiff/tiff-$VERSION.tar.gz#67160e3457
|
|||
TAR_CONTENT="tiff-$VERSION"
|
||||
DEPENDENCIES=('zlib' 'zstd' 'libjpeg')
|
||||
CONFIG_SUB=('config/config.sub')
|
||||
|
||||
post_install() {
|
||||
# remove libtool files
|
||||
rm -f $BANAN_SYSROOT/usr/lib/libtiff.la
|
||||
rm -f $BANAN_SYSROOT/usr/lib/libtiffxx.la
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue