Create a file that looks something like
Code: Select all
DECLARE_FUNCTION(void, name, args)
DECLARE_FUNCTION(int, name2, args2)
DECLARE_FUNCTION(char, name3, arga, argb, arcg)
Don't put header guards in it.
Create a header file, say, kapistatic.h, for when linking statically. do something like
Code: Select all
#define DECLARE_FUNCTION(_type, _name, ...) \
extern _type _name(__VA_ARGS__);
#include "functionFile.h"
Create another header file, say, kapidynamic.h, for when linking dynamically. do something like
Code: Select all
#define DECLARE_FUNCTION(_type, _name, ...) \
_type (*_name)(__VA_ARGS__),
struct KernelInterface {
size_t numEntries;
#include "functionFile.h"
};
extern struct KernelInterface *ki;
#define DECLARE_FUNCTION(_type, _name, ...) \
extern _type _name(__VA_ARGS__); \
#include "functionFile.h"
In the kernel, create a source file somewhere similar to the following, which defines and fills your structure and builds your stubs:
Code: Select all
KernelInterface ki = {
#define DECLARE_FUNCTION(_type, _name, ...) \
._name = _name,
#include "functionFile.h"
};
Finally, create a stub file to be linked with the modules in order to configure them, and contain the function stubs:
Code: Select all
KernelInterface* ki;
void _start(KernelInterface* pki) {
ki = pki;
moduleMain();
}
asm(".extern ki");
#define STRIFY(_val) #_val
#define DECLARE_FUNCTION(_type, _name, ...) \
asm(\
".global " STRIFY(_name) ";" \
STRIFY(_name) ":" \
"movq ki, %rax;" \
"movq " STRIFY(offsetof(KernelInterface, _name)) "(%rax), %rax;" \
"jmpq *%rax" \
);
#include "functionFile.h"
Make _start the entry point of your module some how. When the kernel finds it, it should call it with it's own value of the kernel interface pointer. The module should then get a pointer to the structure containing all the user functions. We also define little assembly stubs which load the function address from the structure we defined and jump to it.
The only hurdle then is loading the drivers
Warning: The above code is untested