99 lines
2.6 KiB
C
99 lines
2.6 KiB
C
// SPDX-License-Identifier: ISC
|
|
|
|
#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) \
|
|
[[__used, __section(".mod." name)]] \
|
|
static const char UNIQUE_IDENT(_name)[] = data
|
|
|
|
#define MODULE_AUTHOR(author) MODULE_PROPERTY("author", author)
|
|
#define MODULE_DESC(desc) MODULE_PROPERTY("desc", desc)
|
|
#define MODULE_VERSION(version) MODULE_PROPERTY("version", version)
|
|
#define MODULE_LICENSE(license) MODULE_PROPERTY("license", license)
|
|
|
|
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, __visibility("hidden")]] \
|
|
errno_t __module_entry(struct module* __module) { \
|
|
return func(__module); \
|
|
}
|
|
#else
|
|
#define MODULE_ENTRY(func) \
|
|
[[__used, __section(".mod.entry")]] \
|
|
static errno_t (*const UNIQUE_IDENT(module_entry))(struct module*) = &(func)
|
|
#endif
|
|
|
|
#ifdef __IN_MODULE
|
|
#define MODULE_EXIT(func) \
|
|
[[__used, __visibility("hidden")]] \
|
|
errno_t __module_exit(struct module* __module) { \
|
|
return func(__module); \
|
|
} \
|
|
[[__used, __section(".mod.exit")]] \
|
|
static errno_t (*const __exit_fn)(struct module*) = &__module_exit
|
|
#else
|
|
// 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();
|
|
|
|
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);
|