initgraph, whole lot of refactor
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
// SPDX-License-Identifier: ISC
|
||||
#pragma once
|
||||
|
||||
typedef __builtin_va_list va_list;
|
||||
|
||||
#undef va_start
|
||||
#define va_start(v, ...) __builtin_va_start(v, 0)
|
||||
|
||||
#undef va_end
|
||||
#define va_end(v) __builtin_va_end(v)
|
||||
|
||||
#undef va_arg
|
||||
#define va_arg(v, l) __builtin_va_arg(v, l)
|
||||
|
||||
#undef va_copy
|
||||
#define va_copy(d, s) __builtin_va_copy(d, s)
|
||||
@@ -0,0 +1,163 @@
|
||||
// SPDX-License-Identifier: ISC
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef enum memory_order {
|
||||
memory_order_relaxed = __ATOMIC_RELAXED,
|
||||
memory_order_consume = __ATOMIC_CONSUME,
|
||||
memory_order_acquire = __ATOMIC_ACQUIRE,
|
||||
memory_order_release = __ATOMIC_RELEASE,
|
||||
memory_order_acq_rel = __ATOMIC_ACQ_REL,
|
||||
memory_order_seq_cst = __ATOMIC_SEQ_CST,
|
||||
} memory_order;
|
||||
|
||||
#define atomic_thread_fence(order) __atomic_thread_fence(order)
|
||||
#define atomic_signal_fence(order) __atomic_signal_fence(order)
|
||||
|
||||
#ifdef __clang__
|
||||
|
||||
#define atomic_init(obj, value) __c11_atomic_init(obj, value)
|
||||
|
||||
#define atomic_store_explicit(obj, val, order) __c11_atomic_store(obj, val, order)
|
||||
#define atomic_load_explicit(obj, order) __c11_atomic_load(obj, order)
|
||||
|
||||
#define atomic_exchange_explicit(obj, val, order) __c11_atomic_exchange(obj, val, order)
|
||||
|
||||
#define atomic_compare_exchange_strong_explicit(obj, expected, desired, succ, fail) \
|
||||
__c11_atomic_compare_exchange_strong(obj, expected, desired, succ, fail)
|
||||
#define atomic_compare_exchange_weak_explicit(obj, expected, desired, succ, fail) \
|
||||
__c11_atomic_compare_exchange_weak(obj, expected, desired, succ, fail)
|
||||
|
||||
#define atomic_fetch_add_explicit(obj, arg, order) __c11_atomic_fetch_add(obj, arg, order)
|
||||
#define atomic_fetch_sub_explicit(obj, arg, order) __c11_atomic_fetch_sub(obj, arg, order)
|
||||
#define atomic_fetch_or_explicit(obj, arg, order) __c11_atomic_fetch_or(obj, arg, order)
|
||||
#define atomic_fetch_xor_explicit(obj, arg, order) __c11_atomic_fetch_xor(obj, arg, order)
|
||||
#define atomic_fetch_and_explicit(obj, arg, order) __c11_atomic_fetch_and(obj, arg, order)
|
||||
|
||||
#define atomic_is_lock_free(obj) __c11_atomic_is_lock_free(sizeof(*(obj)))
|
||||
|
||||
#else /* GCC */
|
||||
|
||||
#define atomic_init(obj, value) \
|
||||
do { \
|
||||
*(obj) = (value); \
|
||||
} while (0)
|
||||
|
||||
#define atomic_store_explicit(obj, val, order) \
|
||||
({ \
|
||||
auto __ao = (obj); \
|
||||
typeof(*__ao) __av = (val); \
|
||||
__atomic_store(__ao, &__av, order); \
|
||||
})
|
||||
|
||||
#define atomic_load_explicit(obj, order) \
|
||||
({ \
|
||||
auto __ao = (obj); \
|
||||
typeof(*__ao) __ar; \
|
||||
__atomic_load(__ao, &__ar, order); \
|
||||
__ar; \
|
||||
})
|
||||
|
||||
#define atomic_exchange_explicit(obj, val, order) \
|
||||
({ \
|
||||
auto __ao = (obj); \
|
||||
typeof(*__ao) __av = (val); \
|
||||
typeof(*__ao) __ar; \
|
||||
__atomic_exchange(__ao, &__av, &__ar, order); \
|
||||
__ar; \
|
||||
})
|
||||
|
||||
#define atomic_compare_exchange_strong_explicit(obj, expected, desired, succ, fail) \
|
||||
({ \
|
||||
auto __ao = (obj); \
|
||||
auto __ae = (expected); \
|
||||
typeof(*__ao) __ad = (desired); \
|
||||
__atomic_compare_exchange(__ao, __ae, &__ad, 0, succ, fail); \
|
||||
})
|
||||
|
||||
#define atomic_compare_exchange_weak_explicit(obj, expected, desired, succ, fail) \
|
||||
({ \
|
||||
auto __ao = (obj); \
|
||||
auto __ae = (expected); \
|
||||
typeof(*__ao) __ad = (desired); \
|
||||
__atomic_compare_exchange(__ao, __ae, &__ad, 1, succ, fail); \
|
||||
})
|
||||
|
||||
#define atomic_fetch_add_explicit(obj, arg, order) __atomic_fetch_add(obj, arg, order)
|
||||
#define atomic_fetch_sub_explicit(obj, arg, order) __atomic_fetch_sub(obj, arg, order)
|
||||
#define atomic_fetch_or_explicit(obj, arg, order) __atomic_fetch_or(obj, arg, order)
|
||||
#define atomic_fetch_xor_explicit(obj, arg, order) __atomic_fetch_xor(obj, arg, order)
|
||||
#define atomic_fetch_and_explicit(obj, arg, order) __atomic_fetch_and(obj, arg, order)
|
||||
|
||||
#define atomic_is_lock_free(obj) __atomic_is_lock_free(sizeof(*(obj)), (obj))
|
||||
|
||||
#endif
|
||||
|
||||
#define atomic_store(obj, val) atomic_store_explicit(obj, val, memory_order_seq_cst)
|
||||
#define atomic_load(obj) atomic_load_explicit(obj, memory_order_seq_cst)
|
||||
|
||||
#define atomic_exchange(obj, val) atomic_exchange_explicit(obj, val, memory_order_seq_cst)
|
||||
|
||||
#define atomic_compare_exchange_strong(obj, expected, desired) \
|
||||
atomic_compare_exchange_strong_explicit(obj, expected, desired, memory_order_seq_cst, memory_order_seq_cst)
|
||||
#define atomic_compare_exchange_weak(obj, expected, desired) \
|
||||
atomic_compare_exchange_weak_explicit(obj, expected, desired, memory_order_seq_cst, memory_order_seq_cst)
|
||||
|
||||
#define atomic_fetch_add(obj, arg) atomic_fetch_add_explicit(obj, arg, memory_order_seq_cst)
|
||||
#define atomic_fetch_sub(obj, arg) atomic_fetch_sub_explicit(obj, arg, memory_order_seq_cst)
|
||||
#define atomic_fetch_or(obj, arg) atomic_fetch_or_explicit(obj, arg, memory_order_seq_cst)
|
||||
#define atomic_fetch_xor(obj, arg) atomic_fetch_xor_explicit(obj, arg, memory_order_seq_cst)
|
||||
#define atomic_fetch_and(obj, arg) atomic_fetch_and_explicit(obj, arg, memory_order_seq_cst)
|
||||
|
||||
// atomic_flag
|
||||
typedef struct atomic_flag {
|
||||
_Atomic(bool) __val;
|
||||
} atomic_flag;
|
||||
|
||||
#define ATOMIC_FLAG_INIT {0}
|
||||
|
||||
#define atomic_flag_test_and_set_explicit(obj, order) atomic_exchange_explicit(&(obj)->__val, 1, order)
|
||||
#define atomic_flag_test_and_set(obj) atomic_flag_test_and_set_explicit(obj, memory_order_seq_cst)
|
||||
#define atomic_flag_clear_explicit(obj, order) atomic_store_explicit(&(obj)->__val, 0, order)
|
||||
#define atomic_flag_clear(obj) atomic_flag_clear_explicit(obj, memory_order_seq_cst)
|
||||
|
||||
typedef _Atomic(bool) atomic_bool;
|
||||
typedef _Atomic(char) atomic_char;
|
||||
typedef _Atomic(signed char) atomic_schar;
|
||||
typedef _Atomic(unsigned char) atomic_uchar;
|
||||
typedef _Atomic(short) atomic_short;
|
||||
typedef _Atomic(unsigned short) atomic_ushort;
|
||||
typedef _Atomic(int) atomic_int;
|
||||
typedef _Atomic(unsigned int) atomic_uint;
|
||||
typedef _Atomic(long) atomic_long;
|
||||
typedef _Atomic(unsigned long) atomic_ulong;
|
||||
typedef _Atomic(long long) atomic_llong;
|
||||
typedef _Atomic(unsigned long long) atomic_ullong;
|
||||
typedef _Atomic(__CHAR16_TYPE__) atomic_char16_t;
|
||||
typedef _Atomic(__CHAR32_TYPE__) atomic_char32_t;
|
||||
typedef _Atomic(__WCHAR_TYPE__) atomic_wchar_t;
|
||||
|
||||
typedef _Atomic(int_least8_t) atomic_int_least8_t;
|
||||
typedef _Atomic(uint_least8_t) atomic_uint_least8_t;
|
||||
typedef _Atomic(int_least16_t) atomic_int_least16_t;
|
||||
typedef _Atomic(uint_least16_t) atomic_uint_least16_t;
|
||||
typedef _Atomic(int_least32_t) atomic_int_least32_t;
|
||||
typedef _Atomic(uint_least32_t) atomic_uint_least32_t;
|
||||
typedef _Atomic(int_least64_t) atomic_int_least64_t;
|
||||
typedef _Atomic(uint_least64_t) atomic_uint_least64_t;
|
||||
typedef _Atomic(int_fast8_t) atomic_int_fast8_t;
|
||||
typedef _Atomic(uint_fast8_t) atomic_uint_fast8_t;
|
||||
typedef _Atomic(int_fast16_t) atomic_int_fast16_t;
|
||||
typedef _Atomic(uint_fast16_t) atomic_uint_fast16_t;
|
||||
typedef _Atomic(int_fast32_t) atomic_int_fast32_t;
|
||||
typedef _Atomic(uint_fast32_t) atomic_uint_fast32_t;
|
||||
typedef _Atomic(int_fast64_t) atomic_int_fast64_t;
|
||||
typedef _Atomic(uint_fast64_t) atomic_uint_fast64_t;
|
||||
typedef _Atomic(intptr_t) atomic_intptr_t;
|
||||
typedef _Atomic(uintptr_t) atomic_uintptr_t;
|
||||
typedef _Atomic(size_t) atomic_size_t;
|
||||
typedef _Atomic(ptrdiff_t) atomic_ptrdiff_t;
|
||||
typedef _Atomic(intmax_t) atomic_intmax_t;
|
||||
typedef _Atomic(uintmax_t) atomic_uintmax_t;
|
||||
@@ -0,0 +1,6 @@
|
||||
// SPDX-License-Identifier: ISC
|
||||
#pragma once
|
||||
|
||||
#define ckd_add(result, a, b) __builtin_add_overflow(a, b, result)
|
||||
#define ckd_sub(result, a, b) __builtin_sub_overflow(a, b, result)
|
||||
#define ckd_mul(result, a, b) __builtin_mul_overflow(a, b, result)
|
||||
@@ -0,0 +1,14 @@
|
||||
// SPDX-License-Identifier: ISC
|
||||
#pragma once
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
typedef __PTRDIFF_TYPE__ ptrdiff_t;
|
||||
|
||||
typedef __WCHAR_TYPE__ wchar_t;
|
||||
typedef typeof(nullptr) nullptr_t;
|
||||
|
||||
#undef offsetof
|
||||
#define offsetof(s, m) __builtin_offsetof(s, m)
|
||||
|
||||
#undef unreachable
|
||||
#define unreachable() __builtin_unreachable()
|
||||
@@ -0,0 +1,354 @@
|
||||
// SPDX-License-Identifier: ISC
|
||||
#pragma once
|
||||
|
||||
#ifdef __UINT8_TYPE__
|
||||
typedef __UINT8_TYPE__ uint8_t;
|
||||
#endif
|
||||
#ifdef __UINT16_TYPE__
|
||||
typedef __UINT16_TYPE__ uint16_t;
|
||||
#endif
|
||||
#ifdef __UINT32_TYPE__
|
||||
typedef __UINT32_TYPE__ uint32_t;
|
||||
#endif
|
||||
#ifdef __UINT64_TYPE__
|
||||
typedef __UINT64_TYPE__ uint64_t;
|
||||
#endif
|
||||
|
||||
typedef __UINT_LEAST8_TYPE__ uint_least8_t;
|
||||
typedef __UINT_LEAST16_TYPE__ uint_least16_t;
|
||||
typedef __UINT_LEAST32_TYPE__ uint_least32_t;
|
||||
typedef __UINT_LEAST64_TYPE__ uint_least64_t;
|
||||
|
||||
typedef __UINT_FAST8_TYPE__ uint_fast8_t;
|
||||
typedef __UINT_FAST16_TYPE__ uint_fast16_t;
|
||||
typedef __UINT_FAST32_TYPE__ uint_fast32_t;
|
||||
typedef __UINT_FAST64_TYPE__ uint_fast64_t;
|
||||
|
||||
#ifdef __INT8_TYPE__
|
||||
typedef __INT8_TYPE__ int8_t;
|
||||
#endif
|
||||
#ifdef __INT16_TYPE__
|
||||
typedef __INT16_TYPE__ int16_t;
|
||||
#endif
|
||||
#ifdef __INT32_TYPE__
|
||||
typedef __INT32_TYPE__ int32_t;
|
||||
#endif
|
||||
#ifdef __INT64_TYPE__
|
||||
typedef __INT64_TYPE__ int64_t;
|
||||
#endif
|
||||
|
||||
typedef __INT_LEAST8_TYPE__ int_least8_t;
|
||||
typedef __INT_LEAST16_TYPE__ int_least16_t;
|
||||
typedef __INT_LEAST32_TYPE__ int_least32_t;
|
||||
typedef __INT_LEAST64_TYPE__ int_least64_t;
|
||||
|
||||
typedef __INT_FAST8_TYPE__ int_fast8_t;
|
||||
typedef __INT_FAST16_TYPE__ int_fast16_t;
|
||||
typedef __INT_FAST32_TYPE__ int_fast32_t;
|
||||
typedef __INT_FAST64_TYPE__ int_fast64_t;
|
||||
|
||||
#ifdef __UINTPTR_TYPE__
|
||||
typedef __UINTPTR_TYPE__ uintptr_t;
|
||||
#endif
|
||||
#ifdef __INTPTR_TYPE__
|
||||
typedef __INTPTR_TYPE__ intptr_t;
|
||||
#endif
|
||||
|
||||
typedef __UINTMAX_TYPE__ uintmax_t;
|
||||
typedef __INTMAX_TYPE__ intmax_t;
|
||||
|
||||
// Clang and GCC have different mechanisms for INT32_C and friends.
|
||||
#ifdef __clang__
|
||||
#ifndef __FREESTANDING_C_HDRS_C_JOIN
|
||||
#define __FREESTANDING_C_HDRS_C_EXPAND_JOIN(x, suffix) x##suffix
|
||||
#define __FREESTANDING_C_HDRS_C_JOIN(x, suffix) __FREESTANDING_C_HDRS_C_EXPAND_JOIN(x, suffix)
|
||||
#endif
|
||||
|
||||
#undef INT8_C
|
||||
#define INT8_C(x) __FREESTANDING_C_HDRS_C_JOIN(x, __INT8_C_SUFFIX__)
|
||||
#undef INT16_C
|
||||
#define INT16_C(x) __FREESTANDING_C_HDRS_C_JOIN(x, __INT16_C_SUFFIX__)
|
||||
#undef INT32_C
|
||||
#define INT32_C(x) __FREESTANDING_C_HDRS_C_JOIN(x, __INT32_C_SUFFIX__)
|
||||
#undef INT64_C
|
||||
#define INT64_C(x) __FREESTANDING_C_HDRS_C_JOIN(x, __INT64_C_SUFFIX__)
|
||||
|
||||
#undef UINT8_C
|
||||
#define UINT8_C(x) __FREESTANDING_C_HDRS_C_JOIN(x, __UINT8_C_SUFFIX__)
|
||||
#undef UINT16_C
|
||||
#define UINT16_C(x) __FREESTANDING_C_HDRS_C_JOIN(x, __UINT16_C_SUFFIX__)
|
||||
#undef UINT32_C
|
||||
#define UINT32_C(x) __FREESTANDING_C_HDRS_C_JOIN(x, __UINT32_C_SUFFIX__)
|
||||
#undef UINT64_C
|
||||
#define UINT64_C(x) __FREESTANDING_C_HDRS_C_JOIN(x, __UINT64_C_SUFFIX__)
|
||||
|
||||
#undef INTMAX_C
|
||||
#define INTMAX_C(x) __FREESTANDING_C_HDRS_C_JOIN(x, __INTMAX_C_SUFFIX__)
|
||||
#undef UINTMAX_C
|
||||
#define UINTMAX_C(x) __FREESTANDING_C_HDRS_C_JOIN(x, __UINTMAX_C_SUFFIX__)
|
||||
#else
|
||||
#undef INT8_C
|
||||
#define INT8_C(x) __INT8_C(x)
|
||||
#undef INT16_C
|
||||
#define INT16_C(x) __INT16_C(x)
|
||||
#undef INT32_C
|
||||
#define INT32_C(x) __INT32_C(x)
|
||||
#undef INT64_C
|
||||
#define INT64_C(x) __INT64_C(x)
|
||||
|
||||
#undef UINT8_C
|
||||
#define UINT8_C(x) __UINT8_C(x)
|
||||
#undef UINT16_C
|
||||
#define UINT16_C(x) __UINT16_C(x)
|
||||
#undef UINT32_C
|
||||
#define UINT32_C(x) __UINT32_C(x)
|
||||
#undef UINT64_C
|
||||
#define UINT64_C(x) __UINT64_C(x)
|
||||
|
||||
#undef INTMAX_C
|
||||
#define INTMAX_C(x) __INTMAX_C(x)
|
||||
#undef UINTMAX_C
|
||||
#define UINTMAX_C(x) __UINTMAX_C(x)
|
||||
#endif
|
||||
|
||||
#ifdef __UINT8_MAX__
|
||||
#undef UINT8_MAX
|
||||
#define UINT8_MAX __UINT8_MAX__
|
||||
#endif
|
||||
#ifdef __UINT16_MAX__
|
||||
#undef UINT16_MAX
|
||||
#define UINT16_MAX __UINT16_MAX__
|
||||
#endif
|
||||
#ifdef __UINT32_MAX__
|
||||
#undef UINT32_MAX
|
||||
#define UINT32_MAX __UINT32_MAX__
|
||||
#endif
|
||||
#ifdef __UINT64_MAX__
|
||||
#undef UINT64_MAX
|
||||
#define UINT64_MAX __UINT64_MAX__
|
||||
#endif
|
||||
|
||||
#ifdef __INT8_MAX__
|
||||
#undef INT8_MAX
|
||||
#define INT8_MAX __INT8_MAX__
|
||||
#endif
|
||||
#ifdef __INT16_MAX__
|
||||
#undef INT16_MAX
|
||||
#define INT16_MAX __INT16_MAX__
|
||||
#endif
|
||||
#ifdef __INT32_MAX__
|
||||
#undef INT32_MAX
|
||||
#define INT32_MAX __INT32_MAX__
|
||||
#endif
|
||||
#ifdef __INT64_MAX__
|
||||
#undef INT64_MAX
|
||||
#define INT64_MAX __INT64_MAX__
|
||||
#endif
|
||||
|
||||
#ifdef __INT8_MAX__
|
||||
#undef INT8_MIN
|
||||
#define INT8_MIN (-INT8_MAX - 1)
|
||||
#endif
|
||||
#ifdef __INT16_MAX__
|
||||
#undef INT16_MIN
|
||||
#define INT16_MIN (-INT16_MAX - 1)
|
||||
#endif
|
||||
#ifdef __INT32_MAX__
|
||||
#undef INT32_MIN
|
||||
#define INT32_MIN (-INT32_MAX - 1)
|
||||
#endif
|
||||
#ifdef __INT64_MAX__
|
||||
#undef INT64_MIN
|
||||
#define INT64_MIN (-INT64_MAX - 1)
|
||||
#endif
|
||||
|
||||
#undef UINT_LEAST8_MAX
|
||||
#define UINT_LEAST8_MAX __UINT_LEAST8_MAX__
|
||||
#undef UINT_LEAST16_MAX
|
||||
#define UINT_LEAST16_MAX __UINT_LEAST16_MAX__
|
||||
#undef UINT_LEAST32_MAX
|
||||
#define UINT_LEAST32_MAX __UINT_LEAST32_MAX__
|
||||
#undef UINT_LEAST64_MAX
|
||||
#define UINT_LEAST64_MAX __UINT_LEAST64_MAX__
|
||||
|
||||
#undef INT_LEAST8_MAX
|
||||
#define INT_LEAST8_MAX __INT_LEAST8_MAX__
|
||||
#undef INT_LEAST16_MAX
|
||||
#define INT_LEAST16_MAX __INT_LEAST16_MAX__
|
||||
#undef INT_LEAST32_MAX
|
||||
#define INT_LEAST32_MAX __INT_LEAST32_MAX__
|
||||
#undef INT_LEAST64_MAX
|
||||
#define INT_LEAST64_MAX __INT_LEAST64_MAX__
|
||||
|
||||
#undef INT_LEAST8_MIN
|
||||
#define INT_LEAST8_MIN (-INT_LEAST8_MAX - 1)
|
||||
#undef INT_LEAST16_MIN
|
||||
#define INT_LEAST16_MIN (-INT_LEAST16_MAX - 1)
|
||||
#undef INT_LEAST32_MIN
|
||||
#define INT_LEAST32_MIN (-INT_LEAST32_MAX - 1)
|
||||
#undef INT_LEAST64_MIN
|
||||
#define INT_LEAST64_MIN (-INT_LEAST64_MAX - 1)
|
||||
|
||||
#undef UINT_FAST8_MAX
|
||||
#define UINT_FAST8_MAX __UINT_FAST8_MAX__
|
||||
#undef UINT_FAST16_MAX
|
||||
#define UINT_FAST16_MAX __UINT_FAST16_MAX__
|
||||
#undef UINT_FAST32_MAX
|
||||
#define UINT_FAST32_MAX __UINT_FAST32_MAX__
|
||||
#undef UINT_FAST64_MAX
|
||||
#define UINT_FAST64_MAX __UINT_FAST64_MAX__
|
||||
|
||||
#undef INT_FAST8_MAX
|
||||
#define INT_FAST8_MAX __INT_FAST8_MAX__
|
||||
#undef INT_FAST16_MAX
|
||||
#define INT_FAST16_MAX __INT_FAST16_MAX__
|
||||
#undef INT_FAST32_MAX
|
||||
#define INT_FAST32_MAX __INT_FAST32_MAX__
|
||||
#undef INT_FAST64_MAX
|
||||
#define INT_FAST64_MAX __INT_FAST64_MAX__
|
||||
|
||||
#undef INT_FAST8_MIN
|
||||
#define INT_FAST8_MIN (-INT_FAST8_MAX - 1)
|
||||
#undef INT_FAST16_MIN
|
||||
#define INT_FAST16_MIN (-INT_FAST16_MAX - 1)
|
||||
#undef INT_FAST32_MIN
|
||||
#define INT_FAST32_MIN (-INT_FAST32_MAX - 1)
|
||||
#undef INT_FAST64_MIN
|
||||
#define INT_FAST64_MIN (-INT_FAST64_MAX - 1)
|
||||
|
||||
#ifdef __UINTPTR_MAX__
|
||||
#undef UINTPTR_MAX
|
||||
#define UINTPTR_MAX __UINTPTR_MAX__
|
||||
#endif
|
||||
#ifdef __INTPTR_MAX__
|
||||
#undef INTPTR_MAX
|
||||
#define INTPTR_MAX __INTPTR_MAX__
|
||||
#undef INTPTR_MIN
|
||||
#define INTPTR_MIN (-INTPTR_MAX - 1)
|
||||
#endif
|
||||
|
||||
#undef UINTMAX_MAX
|
||||
#define UINTMAX_MAX __UINTMAX_MAX__
|
||||
#undef INTMAX_MAX
|
||||
#define INTMAX_MAX __INTMAX_MAX__
|
||||
#undef INTMAX_MIN
|
||||
#define INTMAX_MIN (-INTMAX_MAX - 1)
|
||||
|
||||
#undef PTRDIFF_MAX
|
||||
#define PTRDIFF_MAX __PTRDIFF_MAX__
|
||||
#undef PTRDIFF_MIN
|
||||
#define PTRDIFF_MIN (-PTRDIFF_MAX - 1)
|
||||
|
||||
#undef SIG_ATOMIC_MAX
|
||||
#define SIG_ATOMIC_MAX __SIG_ATOMIC_MAX__
|
||||
#undef SIG_ATOMIC_MIN
|
||||
#define SIG_ATOMIC_MIN (-SIG_ATOMIC_MAX - 1)
|
||||
|
||||
#undef SIZE_MAX
|
||||
#define SIZE_MAX __SIZE_MAX__
|
||||
|
||||
#undef WCHAR_MAX
|
||||
#define WCHAR_MAX __WCHAR_MAX__
|
||||
#undef WCHAR_MIN
|
||||
#define WCHAR_MIN (-WCHAR_MAX - 1)
|
||||
|
||||
#undef WINT_MAX
|
||||
#define WINT_MAX __WINT_MAX__
|
||||
#undef WINT_MIN
|
||||
#define WINT_MIN (-WINT_MAX - 1)
|
||||
|
||||
#ifdef __INT8_TYPE__
|
||||
#undef INT8_WIDTH
|
||||
#define INT8_WIDTH 8
|
||||
#endif
|
||||
#ifdef __UINT8_TYPE__
|
||||
#undef UINT8_WIDTH
|
||||
#define UINT8_WIDTH 8
|
||||
#endif
|
||||
#ifdef __INT16_TYPE__
|
||||
#undef INT16_WIDTH
|
||||
#define INT16_WIDTH 16
|
||||
#endif
|
||||
#ifdef __UINT16_TYPE__
|
||||
#undef UINT16_WIDTH
|
||||
#define UINT16_WIDTH 16
|
||||
#endif
|
||||
#ifdef __INT32_TYPE__
|
||||
#undef INT32_WIDTH
|
||||
#define INT32_WIDTH 32
|
||||
#endif
|
||||
#ifdef __UINT32_TYPE__
|
||||
#undef UINT32_WIDTH
|
||||
#define UINT32_WIDTH 32
|
||||
#endif
|
||||
#ifdef __INT64_TYPE__
|
||||
#undef INT64_WIDTH
|
||||
#define INT64_WIDTH 64
|
||||
#endif
|
||||
#ifdef __UINT64_TYPE__
|
||||
#undef UINT64_WIDTH
|
||||
#define UINT64_WIDTH 64
|
||||
#endif
|
||||
|
||||
#undef INT_LEAST8_WIDTH
|
||||
#define INT_LEAST8_WIDTH __INT_LEAST8_WIDTH__
|
||||
#undef UINT_LEAST8_WIDTH
|
||||
#define UINT_LEAST8_WIDTH __INT_LEAST8_WIDTH__
|
||||
#undef INT_LEAST16_WIDTH
|
||||
#define INT_LEAST16_WIDTH __INT_LEAST16_WIDTH__
|
||||
#undef UINT_LEAST16_WIDTH
|
||||
#define UINT_LEAST16_WIDTH __INT_LEAST16_WIDTH__
|
||||
#undef INT_LEAST32_WIDTH
|
||||
#define INT_LEAST32_WIDTH __INT_LEAST32_WIDTH__
|
||||
#undef UINT_LEAST32_WIDTH
|
||||
#define UINT_LEAST32_WIDTH __INT_LEAST32_WIDTH__
|
||||
#undef INT_LEAST64_WIDTH
|
||||
#define INT_LEAST64_WIDTH __INT_LEAST64_WIDTH__
|
||||
#undef UINT_LEAST64_WIDTH
|
||||
#define UINT_LEAST64_WIDTH __INT_LEAST64_WIDTH__
|
||||
|
||||
#undef INT_FAST8_WIDTH
|
||||
#define INT_FAST8_WIDTH __INT_FAST8_WIDTH__
|
||||
#undef UINT_FAST8_WIDTH
|
||||
#define UINT_FAST8_WIDTH __INT_FAST8_WIDTH__
|
||||
#undef INT_FAST16_WIDTH
|
||||
#define INT_FAST16_WIDTH __INT_FAST16_WIDTH__
|
||||
#undef UINT_FAST16_WIDTH
|
||||
#define UINT_FAST16_WIDTH __INT_FAST16_WIDTH__
|
||||
#undef INT_FAST32_WIDTH
|
||||
#define INT_FAST32_WIDTH __INT_FAST32_WIDTH__
|
||||
#undef UINT_FAST32_WIDTH
|
||||
#define UINT_FAST32_WIDTH __INT_FAST32_WIDTH__
|
||||
#undef INT_FAST64_WIDTH
|
||||
#define INT_FAST64_WIDTH __INT_FAST64_WIDTH__
|
||||
#undef UINT_FAST64_WIDTH
|
||||
#define UINT_FAST64_WIDTH __INT_FAST64_WIDTH__
|
||||
|
||||
#ifdef __INTPTR_TYPE__
|
||||
#undef INTPTR_WIDTH
|
||||
#define INTPTR_WIDTH __INTPTR_WIDTH__
|
||||
#endif
|
||||
#ifdef __UINTPTR_TYPE__
|
||||
#undef UINTPTR_WIDTH
|
||||
#define UINTPTR_WIDTH __INTPTR_WIDTH__
|
||||
#endif
|
||||
|
||||
#undef INTMAX_WIDTH
|
||||
#define INTMAX_WIDTH __INTMAX_WIDTH__
|
||||
#undef UINTMAX_WIDTH
|
||||
#define UINTMAX_WIDTH __INTMAX_WIDTH__
|
||||
|
||||
#undef PTRDIFF_WIDTH
|
||||
#define PTRDIFF_WIDTH __PTRDIFF_WIDTH__
|
||||
|
||||
#undef SIG_ATOMIC_WIDTH
|
||||
#define SIG_ATOMIC_WIDTH __SIG_ATOMIC_WIDTH__
|
||||
|
||||
#undef SIZE_WIDTH
|
||||
#define SIZE_WIDTH __SIZE_WIDTH__
|
||||
|
||||
#undef WCHAR_WIDTH
|
||||
#define WCHAR_WIDTH __WCHAR_WIDTH__
|
||||
|
||||
#undef WINT_WIDTH
|
||||
#define WINT_WIDTH __WINT_WIDTH__
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: ISC
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
@@ -11,4 +12,3 @@ void* memset(void* dest, int value, size_t n);
|
||||
char* strncpy(char* restrict dst, const char* restrict src, size_t len);
|
||||
int strcmp(const char* str1, const char* str2);
|
||||
int strncmp(const char* str1, const char* str2, size_t len);
|
||||
char* strchr(const char* c, int s);
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <zinnia/errno.h>
|
||||
#include <zinnia/initgraph.h>
|
||||
#include <zinnia/types.h>
|
||||
#include <arch/mem.h>
|
||||
#include <stddef.h>
|
||||
@@ -51,3 +52,5 @@ void mem_phys_init(struct phys_mem* map, size_t length);
|
||||
static inline size_t mem_high_shift() {
|
||||
return arch_mem_level_bits() * arch_mem_num_levels() + arch_mem_page_bits();
|
||||
}
|
||||
|
||||
INIT_EXTERN(mem_stage);
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <zinnia/mman.h>
|
||||
|
||||
// TODO
|
||||
|
||||
enum bio_type : uint8_t {
|
||||
BLOCK_READ,
|
||||
BLOCK_WRITE,
|
||||
};
|
||||
|
||||
struct bio {
|
||||
enum bio_type type;
|
||||
uint32_t num_lbas;
|
||||
uint64_t lba;
|
||||
};
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <zinnia/compiler.h>
|
||||
#include <zinnia/utils.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define _CMDLINE_OPTION(x, opt_name, opt_desc, opt_func) \
|
||||
@@ -48,3 +49,10 @@ struct cmdline_option {
|
||||
|
||||
// Parses the command line and invokes all options.
|
||||
void cmdline_parse(const char* cmdline);
|
||||
|
||||
void cmdline_parse_buf(
|
||||
char* buf,
|
||||
size_t len,
|
||||
const struct cmdline_option* const* start,
|
||||
const struct cmdline_option* const* end
|
||||
);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <zinnia/compiler.h>
|
||||
#include <zinnia/initgraph.h>
|
||||
#include <zinnia/utils.h>
|
||||
#include <stddef.h>
|
||||
|
||||
@@ -10,16 +11,16 @@ struct console {
|
||||
bool (*init)(struct console* con);
|
||||
// Writes to the console.
|
||||
void (*write)(struct console* con, const char* buf, size_t count);
|
||||
struct console* next;
|
||||
};
|
||||
|
||||
// Initializes a console for logging.
|
||||
void console_init();
|
||||
INIT_EXTERN(console_stage);
|
||||
|
||||
// Registers a console.
|
||||
bool console_register(struct console* con);
|
||||
|
||||
// Unregisters a regular console.
|
||||
void console_unregister(struct console* con);
|
||||
|
||||
// Writes a message to a console.
|
||||
void console_write(const char* buf, size_t len);
|
||||
|
||||
// Defines a new early console which can be used to log early boot messages.
|
||||
// An early console must not make any heap allocations.
|
||||
#define DEFINE_CONSOLE(con) \
|
||||
[[__used, __section(".console")]] \
|
||||
static struct console* UNIQUE_IDENT(console) = (con)
|
||||
|
||||
+56
-36
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <zinnia/errno.h>
|
||||
#include <zinnia/vfs.h>
|
||||
#include <bits/elf.h>
|
||||
#include <arch/elf.h>
|
||||
#include <stdint.h>
|
||||
|
||||
constexpr char ELF_MAG[4] = {0x7F, 'E', 'L', 'F'};
|
||||
@@ -74,6 +74,20 @@ enum : uint32_t {
|
||||
PT_TLS = 0x00000007,
|
||||
};
|
||||
|
||||
enum : uint32_t {
|
||||
PT_MOD_VERSION = 0x60000001,
|
||||
PT_MOD_AUTHOR = 0x60000002,
|
||||
PT_MOD_DESC = 0x60000003,
|
||||
PT_MOD_LICENSE = 0x60000004,
|
||||
PT_MOD_CMDLINE = 0x60000005,
|
||||
PT_MOD_EXIT = 0x60000006,
|
||||
PT_MOD_MATCH = 0x60000007,
|
||||
};
|
||||
|
||||
enum : uint16_t {
|
||||
SHN_UNDEF = 0,
|
||||
};
|
||||
|
||||
enum : uint32_t {
|
||||
PF_X = 0x00000001,
|
||||
PF_W = 0x00000002,
|
||||
@@ -110,6 +124,9 @@ enum : uint32_t {
|
||||
DT_FINI_ARRAY = 26,
|
||||
DT_INIT_ARRAYSZ = 27,
|
||||
DT_FINI_ARRAYSZ = 28,
|
||||
DT_RELRSZ = 35,
|
||||
DT_RELR = 36,
|
||||
DT_RELRENT = 37,
|
||||
DT_LOOS = 0x60000000,
|
||||
DT_HIOS = 0x6FFFFFFF,
|
||||
DT_LOPROC = 0x70000000,
|
||||
@@ -140,7 +157,7 @@ enum : uint32_t {
|
||||
AT_INIT_HANDLE = 0x1000,
|
||||
};
|
||||
|
||||
struct elf64_ehdr {
|
||||
typedef struct {
|
||||
uint8_t e_ident[EI_NIDENT];
|
||||
uint16_t e_type;
|
||||
uint16_t e_machine;
|
||||
@@ -155,9 +172,9 @@ struct elf64_ehdr {
|
||||
uint16_t e_shentsize;
|
||||
uint16_t e_shnum;
|
||||
uint16_t e_shstrndx;
|
||||
};
|
||||
} elf64_ehdr_t;
|
||||
|
||||
struct elf32_ehdr {
|
||||
typedef struct {
|
||||
uint8_t e_ident[EI_NIDENT];
|
||||
uint16_t e_type;
|
||||
uint16_t e_machine;
|
||||
@@ -172,9 +189,9 @@ struct elf32_ehdr {
|
||||
uint16_t e_shentsize;
|
||||
uint16_t e_shnum;
|
||||
uint16_t e_shstrndx;
|
||||
};
|
||||
} elf32_ehdr_t;
|
||||
|
||||
struct elf64_phdr {
|
||||
typedef struct {
|
||||
uint32_t p_type;
|
||||
uint32_t p_flags;
|
||||
elf64_off_t p_offset;
|
||||
@@ -183,9 +200,9 @@ struct elf64_phdr {
|
||||
uint64_t p_filesz;
|
||||
uint64_t p_memsz;
|
||||
uint64_t p_align;
|
||||
};
|
||||
} elf64_phdr_t;
|
||||
|
||||
struct elf32_phdr {
|
||||
typedef struct {
|
||||
uint32_t p_type;
|
||||
elf32_off_t p_offset;
|
||||
elf32_addr_t p_vaddr;
|
||||
@@ -194,68 +211,68 @@ struct elf32_phdr {
|
||||
uint32_t p_memsz;
|
||||
uint32_t p_flags;
|
||||
uint32_t p_align;
|
||||
};
|
||||
} elf32_phdr_t;
|
||||
|
||||
struct elf64_dyn {
|
||||
typedef struct {
|
||||
int64_t d_tag;
|
||||
union {
|
||||
uint64_t d_val;
|
||||
elf64_addr_t d_ptr;
|
||||
} d_un;
|
||||
};
|
||||
} elf64_dyn_t;
|
||||
|
||||
struct elf32_dyn {
|
||||
typedef struct {
|
||||
int32_t r_offset;
|
||||
union {
|
||||
uint32_t d_val;
|
||||
elf32_addr_t d_ptr;
|
||||
} d_un;
|
||||
};
|
||||
} elf32_dyn_t;
|
||||
|
||||
struct elf64_nhdr {
|
||||
typedef struct {
|
||||
uint64_t n_namesz;
|
||||
uint64_t n_descsz;
|
||||
uint64_t n_type;
|
||||
};
|
||||
} elf64_nhdr_t;
|
||||
|
||||
struct elf32_nhdr {
|
||||
typedef struct {
|
||||
uint32_t n_namesz;
|
||||
uint32_t n_descsz;
|
||||
uint32_t n_type;
|
||||
};
|
||||
} elf32_nhdr_t;
|
||||
|
||||
struct elf64_auxv {
|
||||
typedef struct {
|
||||
uint64_t atype;
|
||||
uint64_t avalue;
|
||||
};
|
||||
} elf64_auxv_t;
|
||||
|
||||
struct elf32_auxv {
|
||||
typedef struct {
|
||||
uint32_t atype;
|
||||
uint32_t avalue;
|
||||
};
|
||||
} elf32_auxv_t;
|
||||
|
||||
struct elf_hash {
|
||||
typedef struct {
|
||||
uint32_t n_buckets;
|
||||
uint32_t n_chain;
|
||||
};
|
||||
} elf_hash_t;
|
||||
|
||||
struct elf32_sym {
|
||||
typedef struct {
|
||||
elf32_off_t st_name;
|
||||
elf32_addr_t st_value;
|
||||
elf32_off_t st_size;
|
||||
uint8_t st_info;
|
||||
uint8_t st_other;
|
||||
uint16_t st_shndx;
|
||||
};
|
||||
} elf32_sym_t;
|
||||
|
||||
struct elf64_sym {
|
||||
typedef struct {
|
||||
uint32_t st_name;
|
||||
uint8_t st_info;
|
||||
uint8_t st_other;
|
||||
uint16_t st_shndx;
|
||||
uint64_t st_value;
|
||||
uint64_t st_size;
|
||||
};
|
||||
} elf64_sym_t;
|
||||
|
||||
static uint8_t ELF64_ST_BIND(uint8_t info) {
|
||||
return info >> 4;
|
||||
@@ -272,7 +289,7 @@ static inline uint8_t ELF64_ST_INFO(uint8_t bind, uint8_t type) {
|
||||
typedef struct {
|
||||
uint16_t si_boundto;
|
||||
uint16_t si_flags;
|
||||
} elf64_syminfo;
|
||||
} elf64_syminfo_t;
|
||||
|
||||
static inline uint8_t ELF32_ST_BIND(uint8_t info) {
|
||||
return info >> 4;
|
||||
@@ -304,27 +321,30 @@ enum {
|
||||
STT_HIPROC = 15
|
||||
};
|
||||
|
||||
struct elf32_rela {
|
||||
typedef struct {
|
||||
elf32_addr_t r_offset;
|
||||
uint32_t r_info;
|
||||
int32_t r_addend;
|
||||
};
|
||||
} elf32_rela_t;
|
||||
|
||||
struct elf64_rela {
|
||||
typedef struct {
|
||||
elf64_addr_t r_offset;
|
||||
uint64_t r_info;
|
||||
int64_t r_addend;
|
||||
};
|
||||
} elf64_rela_t;
|
||||
|
||||
struct elf32_rel {
|
||||
typedef uint64_t elf64_relr_t;
|
||||
typedef uint32_t elf32_relr_t;
|
||||
|
||||
typedef struct {
|
||||
elf32_addr_t r_offset;
|
||||
uint32_t r_info;
|
||||
};
|
||||
} elf32_rel_t;
|
||||
|
||||
struct elf64_rel {
|
||||
typedef struct {
|
||||
elf64_addr_t r_offset;
|
||||
uint64_t r_info;
|
||||
};
|
||||
} elf64_rel_t;
|
||||
|
||||
static inline uint32_t ELF32_R_SYM(uint32_t info) {
|
||||
return info >> 8;
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include <uapi/errno.h>
|
||||
|
||||
typedef enum : int32_t {
|
||||
EOK = 0, // Success! Not really an error though...
|
||||
EPERM = __EPERM,
|
||||
ENOENT = __ENOENT,
|
||||
ESRCH = __ESRCH,
|
||||
|
||||
@@ -21,8 +21,18 @@ constexpr uint32_t FDT_END_NODE = 0x00000002;
|
||||
constexpr uint32_t FDT_PROP = 0x00000003;
|
||||
constexpr uint32_t FDT_NOP = 0x00000004;
|
||||
constexpr uint32_t FDT_END = 0x00000009;
|
||||
constexpr uint32_t FDT_MAGIC = 0xD00DFEED;
|
||||
|
||||
struct fdt_match {
|
||||
const char* compatible;
|
||||
uintptr_t data;
|
||||
};
|
||||
|
||||
#define FDT_MATCH_COMPATIBLE(compat) .compatible = (compat)
|
||||
|
||||
struct fdt {
|
||||
const uint8_t* blob;
|
||||
size_t total_size;
|
||||
uint32_t version;
|
||||
uint32_t compat_version;
|
||||
uint32_t boot_cpuid;
|
||||
@@ -35,11 +45,23 @@ struct fdt {
|
||||
|
||||
struct fdt_node {
|
||||
struct fdt* tree;
|
||||
size_t offset;
|
||||
};
|
||||
|
||||
struct fdt_prop {
|
||||
struct fdt* tree;
|
||||
const void* data;
|
||||
size_t length;
|
||||
};
|
||||
|
||||
uint32_t fdt_read_u32(const void* data);
|
||||
uint64_t fdt_read_u64(const void* data);
|
||||
bool fdt_init(struct fdt* tree, const void* data, size_t length);
|
||||
struct fdt_node fdt_find(struct fdt* tree, const char* path);
|
||||
struct fdt_node fdt_find_compatible(struct fdt* tree, const char* compatible);
|
||||
struct fdt_prop fdt_property(struct fdt_node node, const char* name);
|
||||
bool fdt_property_u32(struct fdt_node node, const char* name, uint32_t* value);
|
||||
bool fdt_property_u64(struct fdt_node node, const char* name, uint64_t* value);
|
||||
|
||||
// Root of the device tree.
|
||||
struct fdt_node fdt_root(struct fdt* tree);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <zinnia/errno.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <zinnia/string.h>
|
||||
#include <string.h>
|
||||
|
||||
#define hashmap(K, V) \
|
||||
struct { \
|
||||
|
||||
@@ -38,6 +38,7 @@ struct boot_info {
|
||||
struct boot_file* files;
|
||||
size_t num_files;
|
||||
struct boot_framebuffer fb;
|
||||
struct boot_file kernel_file;
|
||||
void* dtb;
|
||||
size_t dtb_size;
|
||||
#if CONFIG_ACPI
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
#pragma once
|
||||
|
||||
#include <zinnia/compiler.h>
|
||||
#include <zinnia/utils.h>
|
||||
#include <stddef.h>
|
||||
|
||||
enum init_action {
|
||||
INIT_EMPTY,
|
||||
INIT_CALLBACK,
|
||||
INIT_GATE,
|
||||
};
|
||||
|
||||
struct boot_info;
|
||||
struct init_node;
|
||||
|
||||
struct init_edge {
|
||||
struct init_node* source;
|
||||
struct init_node* target;
|
||||
bool propagates_disable;
|
||||
struct init_edge* next_in;
|
||||
struct init_edge* next_out;
|
||||
};
|
||||
|
||||
struct init_edges {
|
||||
struct init_node* node;
|
||||
bool depends;
|
||||
size_t count;
|
||||
struct init_node* const* nodes;
|
||||
struct init_edge* edges;
|
||||
};
|
||||
|
||||
struct init_node {
|
||||
const char* name;
|
||||
enum init_action action;
|
||||
union {
|
||||
void (*callback)(struct boot_info* info);
|
||||
bool (*gate)(struct boot_info* info);
|
||||
void* func;
|
||||
};
|
||||
size_t unsatisfied;
|
||||
bool wanted;
|
||||
bool done;
|
||||
bool disabled;
|
||||
struct init_edge* in_edges;
|
||||
struct init_edge* out_edges;
|
||||
struct init_node* queue_next;
|
||||
};
|
||||
|
||||
#define INIT_EXTERN(node) extern struct init_node node[1]
|
||||
|
||||
#define INIT_TASK(node, display, ...) \
|
||||
struct init_node node[1] = {{ \
|
||||
.name = (display), \
|
||||
__VA_OPT__( \
|
||||
.action = _Generic( \
|
||||
(__VA_ARGS__), \
|
||||
void (*)(struct boot_info*): INIT_CALLBACK, \
|
||||
bool (*)(struct boot_info*): INIT_GATE \
|
||||
), \
|
||||
.func = (void*)(__VA_ARGS__), \
|
||||
) \
|
||||
}}; \
|
||||
[[__used, __section(".initgraph.nodes")]] \
|
||||
static struct init_node* const CONCAT(node, _initgraph_node) = node
|
||||
|
||||
#define _INIT_EDGES(x, from, is_depends, ...) \
|
||||
static struct init_node* const CONCAT(x, _nodes)[] = {__VA_ARGS__}; \
|
||||
static struct init_edge CONCAT(x, _edges)[ARRAY_SIZE(CONCAT(x, _nodes))]; \
|
||||
static const struct init_edges x = { \
|
||||
.node = (from), \
|
||||
.depends = (is_depends), \
|
||||
.count = ARRAY_SIZE(CONCAT(x, _nodes)), \
|
||||
.nodes = CONCAT(x, _nodes), \
|
||||
.edges = CONCAT(x, _edges), \
|
||||
}; \
|
||||
[[__used, __section(".initgraph.edges")]] \
|
||||
static const struct init_edges* const CONCAT(x, _ptr) = &x
|
||||
|
||||
#define INIT_DEPENDS(node, ...) _INIT_EDGES(UNIQUE_IDENT(init_edges), node, true, __VA_ARGS__)
|
||||
#define INIT_ENTAILS(node, ...) _INIT_EDGES(UNIQUE_IDENT(init_edges), node, false, __VA_ARGS__)
|
||||
|
||||
void initgraph_run(struct init_node* goal, struct boot_info* info);
|
||||
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <zinnia/errno.h>
|
||||
#include <zinnia/string.h>
|
||||
#include <zinnia/usercopy.h>
|
||||
#include <zinnia/utils.h>
|
||||
#include <stddef.h>
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <zinnia/initgraph.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void ksym_init();
|
||||
|
||||
// Finds the function containing `addr`. Returns false if no symbol is known.
|
||||
bool ksym_lookup(uintptr_t addr, const char** name, size_t* offset);
|
||||
|
||||
// Writes `name+0xoffset` for `addr` to `buf`, or `<???>` if the address can't be resolved.
|
||||
void ksym_format(uintptr_t addr, char* buf, size_t size);
|
||||
|
||||
bool ksym_find(const char* name, uintptr_t* addr);
|
||||
|
||||
const char* ksym_kernel_name();
|
||||
|
||||
INIT_EXTERN(ksyms_stage);
|
||||
+65
-14
@@ -1,7 +1,11 @@
|
||||
#pragma once
|
||||
#include <zinnia/compiler.h>
|
||||
#include <zinnia/errno.h>
|
||||
#include <zinnia/initgraph.h>
|
||||
#include <zinnia/tailq.h>
|
||||
#include <zinnia/types.h>
|
||||
#include <zinnia/utils.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define MODULE_PROPERTY(name, data) \
|
||||
@@ -13,36 +17,83 @@
|
||||
#define MODULE_VERSION(version) MODULE_PROPERTY("version", version)
|
||||
#define MODULE_LICENSE(license) MODULE_PROPERTY("license", license)
|
||||
|
||||
#ifdef IN_MODULE
|
||||
struct match_table {
|
||||
const char* name;
|
||||
const void* entries;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
#ifdef __IN_MODULE
|
||||
#define MATCH_TABLE(match_name, table) \
|
||||
[[__used, __section(".mod.match"), __aligned(8)]] \
|
||||
static const struct match_table CONCAT(table, _match_table) = { \
|
||||
.name = (match_name), \
|
||||
.entries = (table), \
|
||||
.size = ARRAY_SIZE(table), \
|
||||
}
|
||||
#else
|
||||
#define MATCH_TABLE(match_name, table) static_assert(true)
|
||||
#endif
|
||||
|
||||
// Module entries are used
|
||||
#ifdef __IN_MODULE
|
||||
#define MODULE_ENTRY(func) \
|
||||
[[__used]] \
|
||||
[[__used, __visibility("hidden")]] \
|
||||
errno_t __module_entry(struct module* __module) { \
|
||||
return func(__module); \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define MODULE_ENTRY(func) \
|
||||
[[__used, __section(".mod.entry")]] \
|
||||
static const void* __entry_fn = &__module_entry
|
||||
static errno_t (*const UNIQUE_IDENT(module_entry))(struct module*) = &(func)
|
||||
#endif
|
||||
|
||||
#ifdef __IN_MODULE
|
||||
#define MODULE_EXIT(func) \
|
||||
[[__used]] \
|
||||
[[__used, __visibility("hidden")]] \
|
||||
errno_t __module_exit(struct module* __module) { \
|
||||
return func(__module); \
|
||||
} \
|
||||
[[__used, __section(".mod.exit")]] \
|
||||
static const void* __exit_fn = &__module_exit
|
||||
static errno_t (*const __exit_fn)(struct module*) = &__module_exit
|
||||
#else
|
||||
#define MODULE_ENTRY(func) \
|
||||
[[__used, __section(".mod.entry")]] \
|
||||
static const void* UNIQUE_IDENT(module_entry) = &(func)
|
||||
|
||||
#define MODULE_EXIT(func) \
|
||||
[[__used, __section(".mod.exit")]] \
|
||||
static const void* UNIQUE_IDENT(module_exit) = &(func)
|
||||
// Built-in drivers can't be unloaded.
|
||||
#define MODULE_EXIT(func) static_assert(&(func) != nullptr)
|
||||
#endif
|
||||
|
||||
struct module_segment {
|
||||
phys_t phys;
|
||||
uintptr_t virt;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
struct module {
|
||||
const char* name;
|
||||
const char* version;
|
||||
const char* author;
|
||||
const char* desc;
|
||||
const char* license;
|
||||
uintptr_t base;
|
||||
size_t size;
|
||||
uintptr_t bias;
|
||||
const void* symtab;
|
||||
size_t num_syms;
|
||||
const char* strtab;
|
||||
size_t strtab_size;
|
||||
struct module_segment* segments;
|
||||
size_t num_segments;
|
||||
errno_t (*exit)(struct module*);
|
||||
char* cmdline;
|
||||
tailq_link(struct module) link;
|
||||
};
|
||||
|
||||
#define THIS_MODULE (struct module*)nullptr
|
||||
|
||||
void module_init();
|
||||
struct boot_info;
|
||||
void module_init(struct boot_info* info);
|
||||
|
||||
errno_t module_load(const void* data, size_t length, const char* cmdline, struct module** out);
|
||||
errno_t module_unload(struct module* mod);
|
||||
struct module* module_find(const char* name);
|
||||
|
||||
INIT_EXTERN(module_stage);
|
||||
|
||||
@@ -0,0 +1,187 @@
|
||||
#pragma once
|
||||
|
||||
#include <zinnia/alloc.h>
|
||||
#include <zinnia/compiler.h>
|
||||
#include <zinnia/errno.h>
|
||||
#include <zinnia/initgraph.h>
|
||||
#include <zinnia/print.h>
|
||||
#include <zinnia/types.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct pci_address {
|
||||
uint16_t domain;
|
||||
uint8_t bus;
|
||||
uint8_t device;
|
||||
uint8_t function;
|
||||
};
|
||||
|
||||
#define PCI_ADDR_FMT "%.4hx:%.2hhx:%.2hhx.%hhx"
|
||||
#define PCI_ADDR_ARGS(a) (a)->domain, (a)->bus, (a)->device, (a)->function
|
||||
|
||||
struct pci_id {
|
||||
uint16_t vendor_id;
|
||||
uint16_t device_id;
|
||||
uint16_t subvendor_id;
|
||||
uint16_t subdevice_id;
|
||||
};
|
||||
|
||||
struct pci_class {
|
||||
uint8_t class;
|
||||
uint8_t subclass;
|
||||
uint8_t prog_if;
|
||||
};
|
||||
|
||||
enum pci_cfg : uint16_t {
|
||||
PCI_VENDOR_ID = 0x00,
|
||||
PCI_DEVICE_ID = 0x02,
|
||||
PCI_COMMAND = 0x04,
|
||||
PCI_STATUS = 0x06,
|
||||
PCI_PROG_IF = 0x09,
|
||||
PCI_SUBCLASS = 0x0a,
|
||||
PCI_CLASS = 0x0b,
|
||||
PCI_HEADER_TYPE = 0x0e,
|
||||
PCI_BAR0 = 0x10,
|
||||
PCI_SECONDARY_BUS = 0x19,
|
||||
PCI_SUBSYS_VENDOR_ID = 0x2c,
|
||||
PCI_SUBSYS_ID = 0x2e,
|
||||
PCI_CAP_PTR = 0x34,
|
||||
PCI_INTERRUPT_LINE = 0x3c,
|
||||
PCI_INTERRUPT_PIN = 0x3d,
|
||||
};
|
||||
|
||||
enum pci_command : uint16_t {
|
||||
PCI_COMMAND_IO = 1 << 0,
|
||||
PCI_COMMAND_MEM = 1 << 1,
|
||||
PCI_COMMAND_MASTER = 1 << 2,
|
||||
PCI_COMMAND_INTX_DISABLE = 1 << 10,
|
||||
};
|
||||
|
||||
constexpr uint16_t PCI_STATUS_CAP_LIST = 1 << 4;
|
||||
|
||||
constexpr uint8_t PCI_HEADER_TYPE_MASK = 0x7f;
|
||||
constexpr uint8_t PCI_HEADER_TYPE_MULTIFUNCTION = 0x80;
|
||||
constexpr uint8_t PCI_HEADER_TYPE_BRIDGE = 0x01;
|
||||
|
||||
constexpr size_t PCI_NUM_BARS = 6;
|
||||
constexpr uint8_t PCI_NUM_SLOTS = 32;
|
||||
constexpr uint8_t PCI_NUM_FUNCTIONS = 8;
|
||||
|
||||
enum pci_cap_id : uint8_t {
|
||||
PCI_CAP_MSI = 0x05,
|
||||
PCI_CAP_PCIE = 0x10,
|
||||
PCI_CAP_MSIX = 0x11,
|
||||
};
|
||||
|
||||
struct pci_access {
|
||||
const char* name;
|
||||
uint16_t domain;
|
||||
uint8_t start_bus;
|
||||
uint8_t end_bus;
|
||||
uint8_t priority;
|
||||
uint32_t (*read32)(struct pci_access* self, const struct pci_address* addr, uint16_t offset);
|
||||
void (*write32)(struct pci_access* self, const struct pci_address* addr, uint16_t offset, uint32_t value);
|
||||
};
|
||||
|
||||
enum pci_access_priority : uint8_t {
|
||||
PCI_ACCESS_PRIO_LEGACY = 0,
|
||||
PCI_ACCESS_PRIO_ECAM = 128,
|
||||
};
|
||||
|
||||
static bool pci_access_decodes(const struct pci_access* access, const struct pci_address* addr);
|
||||
|
||||
errno_t pci_access_register(struct pci_access* access);
|
||||
struct pci_access* pci_access_find(const struct pci_address* addr);
|
||||
|
||||
errno_t pci_ecam_register(phys_t base, uint16_t domain, uint8_t start_bus, uint8_t end_bus);
|
||||
|
||||
struct pci_driver;
|
||||
|
||||
struct pci_device {
|
||||
struct pci_address address;
|
||||
struct pci_id id;
|
||||
struct pci_class class;
|
||||
struct pci_access* access;
|
||||
uint8_t header_type;
|
||||
struct pci_driver* driver;
|
||||
};
|
||||
|
||||
uint8_t pci_read8(struct pci_device* dev, uint16_t offset);
|
||||
uint16_t pci_read16(struct pci_device* dev, uint16_t offset);
|
||||
uint32_t pci_read32(struct pci_device* dev, uint16_t offset);
|
||||
void pci_write8(struct pci_device* dev, uint16_t offset, uint8_t value);
|
||||
void pci_write16(struct pci_device* dev, uint16_t offset, uint16_t value);
|
||||
void pci_write32(struct pci_device* dev, uint16_t offset, uint32_t value);
|
||||
|
||||
enum pci_bar_type : uint8_t {
|
||||
PCI_BAR_NONE,
|
||||
PCI_BAR_MMIO32,
|
||||
PCI_BAR_MMIO64,
|
||||
PCI_BAR_IO,
|
||||
};
|
||||
|
||||
struct pci_bar {
|
||||
enum pci_bar_type type;
|
||||
bool prefetchable;
|
||||
phys_t address;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
errno_t pci_bar_get(struct pci_device* dev, size_t index, struct pci_bar* out);
|
||||
|
||||
uint8_t pci_cap_next(struct pci_device* dev, uint8_t cur);
|
||||
uint8_t pci_cap_find(struct pci_device* dev, uint8_t id);
|
||||
|
||||
#define PCI_ANY_ID 0xffff
|
||||
#define PCI_ANY_CLASS 0xff
|
||||
|
||||
// Matches a device by ID and class.
|
||||
struct pci_match {
|
||||
uint16_t vendor_id;
|
||||
uint16_t device_id;
|
||||
uint8_t class;
|
||||
uint8_t subclass;
|
||||
uint8_t prog_if;
|
||||
|
||||
// Not used to match, but can be used to pass device-specific context data.
|
||||
uintptr_t data;
|
||||
};
|
||||
|
||||
#define PCI_MATCH_DEVICE(vendor, device) \
|
||||
.vendor_id = (vendor), .device_id = (device), .class = PCI_ANY_CLASS, .subclass = PCI_ANY_CLASS, \
|
||||
.prog_if = PCI_ANY_CLASS
|
||||
|
||||
#define PCI_MATCH_CLASS(c, sc, pi) \
|
||||
.vendor_id = PCI_ANY_ID, .device_id = PCI_ANY_ID, .class = (c), .subclass = (sc), .prog_if = (pi)
|
||||
|
||||
// Writes the address to `buf`.
|
||||
static void pci_device_name(const struct pci_device* dev, char buf[static 18]);
|
||||
|
||||
struct pci_driver {
|
||||
const char* name;
|
||||
|
||||
// Match table, array of `num_matches` entries, checked sequentially.
|
||||
// When writing a match table, the most specific matches should come first, then more generic cases.
|
||||
const struct pci_match* match;
|
||||
const size_t num_matches;
|
||||
|
||||
errno_t (*probe)(struct pci_device* dev, const struct pci_match* match);
|
||||
};
|
||||
|
||||
errno_t pci_driver_register(struct pci_driver* driver);
|
||||
|
||||
INIT_EXTERN(pci_stage);
|
||||
|
||||
#ifdef __MODULE_NAME
|
||||
#define PCI_LOG_NAME __MODULE_NAME
|
||||
#else
|
||||
#define PCI_LOG_NAME "pci"
|
||||
#endif
|
||||
|
||||
#define pci_log_level(level, dev, message, ...) \
|
||||
log_write(level, PCI_LOG_NAME " " PCI_ADDR_FMT ": " message, PCI_ADDR_ARGS(&(dev)->address), ##__VA_ARGS__)
|
||||
|
||||
#define pci_log_debug(dev, message, ...) pci_log_level(LOG_DEBUG, dev, message, ##__VA_ARGS__)
|
||||
#define pci_log(dev, message, ...) pci_log_level(LOG_INFO, dev, message, ##__VA_ARGS__)
|
||||
#define pci_log_warn(dev, message, ...) pci_log_level(LOG_WARN, dev, message, ##__VA_ARGS__)
|
||||
#define pci_log_err(dev, message, ...) pci_log_level(LOG_ERR, dev, message, ##__VA_ARGS__)
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <zinnia/compiler.h>
|
||||
#include <zinnia/initgraph.h>
|
||||
#include <zinnia/sched.h>
|
||||
#include <zinnia/usercopy.h>
|
||||
#include <stddef.h>
|
||||
@@ -40,7 +41,9 @@ struct percpu* percpu_new();
|
||||
size_t percpu_max_cpus();
|
||||
struct percpu* percpu_get();
|
||||
void percpu_bsp_init();
|
||||
void percpu_init();
|
||||
void percpu_init(struct boot_info* info);
|
||||
|
||||
INIT_EXTERN(percpu_stage);
|
||||
|
||||
// Per-CPU data for the bootstrap processor.
|
||||
extern struct percpu percpu_bsp;
|
||||
|
||||
+35
-9
@@ -2,19 +2,45 @@
|
||||
|
||||
#include <zinnia/compiler.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
|
||||
[[__format(printf, 1, 2)]]
|
||||
void kprintf(const char* message, ...);
|
||||
|
||||
void kvprintf(const char* message, va_list args);
|
||||
|
||||
#include <zinnia/clock.h>
|
||||
#include <zinnia/percpu.h>
|
||||
[[__format(printf, 3, 4)]]
|
||||
size_t ksnprintf(char* buf, size_t size, const char* format, ...);
|
||||
|
||||
#define log(message, ...) \
|
||||
do { \
|
||||
auto _time = clock_get_elapsed_ns(); \
|
||||
auto _cur = percpu_get()->sched.current; \
|
||||
auto _tid = _cur ? _cur->id : 0; \
|
||||
kprintf("[%5lu.%06lu] [%5lu] " message, _time / 1'000'000'000, _time / 1'000 % 1'000'000, _tid, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
size_t kvsnprintf(char* buf, size_t size, const char* format, va_list args);
|
||||
|
||||
typedef void (*log_fn_t)(void* ctx, const char* buf, size_t len);
|
||||
void print_fmt(log_fn_t callback, void* ctx, const char* restrict fmt, va_list args);
|
||||
|
||||
enum log_level {
|
||||
LOG_DEBUG,
|
||||
LOG_STATUS,
|
||||
LOG_INFO,
|
||||
LOG_WARN,
|
||||
LOG_ERR,
|
||||
LOG_PANIC,
|
||||
};
|
||||
|
||||
[[__format(printf, 2, 3)]]
|
||||
void log_write(enum log_level level, const char* message, ...);
|
||||
|
||||
void log_vwrite(enum log_level level, const char* message, va_list args);
|
||||
|
||||
// Like log_vwrite(), but prepends a `prefix` to the message.
|
||||
void log_vwrite_prefixed(enum log_level level, const char* prefix, const char* message, va_list args);
|
||||
|
||||
#ifndef pr_fmt
|
||||
#define pr_fmt(fmt) fmt
|
||||
#endif
|
||||
|
||||
#define log(message, ...) log_write(LOG_INFO, pr_fmt(message), ##__VA_ARGS__)
|
||||
#define log_debug(message, ...) log_write(LOG_DEBUG, pr_fmt(message), ##__VA_ARGS__)
|
||||
#define log_status(message, ...) log_write(LOG_STATUS, pr_fmt(message), ##__VA_ARGS__)
|
||||
#define log_warn(message, ...) log_write(LOG_WARN, pr_fmt(message), ##__VA_ARGS__)
|
||||
#define log_err(message, ...) log_write(LOG_ERR, pr_fmt(message), ##__VA_ARGS__)
|
||||
#define log_panic(message, ...) log_write(LOG_PANIC, pr_fmt(message), ##__VA_ARGS__)
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
|
||||
#include <zinnia/errno.h>
|
||||
#include <zinnia/init.h>
|
||||
#include <zinnia/initgraph.h>
|
||||
#include <zinnia/stack.h>
|
||||
#include <zinnia/tailq.h>
|
||||
#include <zinnia/types.h>
|
||||
#include <bits/sched.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -34,6 +36,7 @@ struct task {
|
||||
uintptr_t user_stack;
|
||||
size_t time_slice;
|
||||
int8_t priority;
|
||||
atomic_bool wake_pending;
|
||||
|
||||
tailq_link(struct task) next;
|
||||
};
|
||||
@@ -57,6 +60,13 @@ void sched_init(struct scheduler* sched);
|
||||
void sched_reschedule(struct scheduler* sched);
|
||||
void sched_yield(struct scheduler* sched);
|
||||
void sched_add_task(struct scheduler* sched, struct task* task);
|
||||
|
||||
// Blocks the current task until sched_wake() is called on it.
|
||||
// Returns immediately if a wake is already pending. Must not hold any spinlock.
|
||||
void sched_block(struct scheduler* sched);
|
||||
|
||||
// Makes a blocked task runnable again, or marks the wake as pending if it hasn't blocked yet.
|
||||
void sched_wake(struct task* task);
|
||||
[[noreturn]]
|
||||
void sched_to_user(uintptr_t ctx);
|
||||
[[noreturn]]
|
||||
@@ -68,3 +78,5 @@ struct task_start_info {
|
||||
uintptr_t sp;
|
||||
uintptr_t arg;
|
||||
};
|
||||
|
||||
INIT_EXTERN(sched_stage);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdatomic.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// Busy-waits in a loop until the lock is freed.
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define USB_ANY_ID 0xffff
|
||||
#define USB_ANY_CLASS 0xff
|
||||
|
||||
struct usb_match {
|
||||
uint16_t vendor_id;
|
||||
uint16_t product_id;
|
||||
uint8_t class;
|
||||
uint8_t subclass;
|
||||
uint8_t protocol;
|
||||
uintptr_t data;
|
||||
};
|
||||
|
||||
#define USB_MATCH_DEVICE(vendor, product) \
|
||||
.vendor_id = (vendor), .product_id = (product), .class = USB_ANY_CLASS, .subclass = USB_ANY_CLASS, \
|
||||
.protocol = USB_ANY_CLASS
|
||||
|
||||
#define USB_MATCH_CLASS(c, sc, p) \
|
||||
.vendor_id = USB_ANY_ID, .product_id = USB_ANY_ID, .class = (c), .subclass = (sc), .protocol = (p)
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <zinnia/alloc.h>
|
||||
#include <zinnia/errno.h>
|
||||
#include <stddef.h> // IWYU pragma: keep
|
||||
#include <zinnia/string.h> // IWYU pragma: keep
|
||||
#include <string.h> // IWYU pragma: keep
|
||||
|
||||
#define vec(T) \
|
||||
struct { \
|
||||
|
||||
Reference in New Issue
Block a user