-
Notifications
You must be signed in to change notification settings - Fork 0
Driver API
NtinosTheGamer2324 edited this page Dec 28, 2025
·
3 revisions
API for developing hardware drivers in ModuOS.
ModuOS supports third‑party loadable kernel modules called SQRM modules. These are ELF64 ET_DYN shared-object style binaries (file extension .sqrm) that are loaded by the kernel module loader at boot.
Modules are searched under:
-
/ModuOS/System64/md/(on the selected boot filesystem)
On the ISO this corresponds to:
targets/AMD64/iso/ModuOS/System64/md/
A valid module must export:
- A module descriptor symbol named
sqrm_module_desc
#include "sdk/sqrm_sdk.h" // or "moduos/kernel/sqrm.h" in-tree
SQRM_DEFINE_MODULE(SQRM_TYPE_USB, "hello");- An entry point:
int sqrm_module_init(const sqrm_kernel_api_t *api);The kernel passes a pointer to a kernel API table (sqrm_kernel_api_t) containing function pointers you can call (logging, driver registration, etc.). Always check ABI compatibility:
if (!api || api->abi_version != SQRM_ABI_VERSION) return -1;Common module types:
-
SQRM_TYPE_FS– filesystem drivers (example:modules/ext2_sqrm.c) -
SQRM_TYPE_AUDIO– audio drivers (example:modules/ac97_audio_sqrm.c) -
SQRM_TYPE_USB– USB class/device drivers
You can build third‑party modules out-of-tree using the SDK in sdk/.
Minimal build flags (from sdk/template_hello/build.sh):
x86_64-elf-gcc -I sdk -ffreestanding -fPIC -mno-red-zone -nostdlib \
-Wl,-shared -Wl,-e,sqrm_module_init \
hello_sqrm.c -o hello.sqrmNotes:
-
-fPICis required. -
-mno-red-zoneis required for interrupt-safe kernel code. - The link must produce
ET_DYN(-shared). - The entry point must be
sqrm_module_init.
- Copy your module into the ISO tree:
targets/AMD64/iso/ModuOS/System64/md/<name>.sqrm
-
Rebuild the ISO.
-
Boot and check COM logs for module loader output:
[SQRM] Loading module: ...
- In-tree minimal module:
modules/hello_sqrm.c - SDK template:
sdk/template_hello/hello_sqrm.c - Filesystem module:
modules/ext2_sqrm.c
typedef struct {
const char *name;
int (*init)(void);
int (*probe)(void);
void (*remove)(void);
} driver_t;typedef struct {
uint8_t bus;
uint8_t device;
uint8_t function;
uint16_t vendor_id;
uint16_t device_id;
uint8_t class_code;
uint8_t subclass;
uint32_t bar[6];
} pci_device_t;// Find device by vendor/device ID
pci_device_t* pci_find_device(uint16_t vendor_id, uint16_t device_id);
// Find device by class
pci_device_t* pci_find_class(uint8_t class_code, uint8_t subclass);
// Enable bus mastering
void pci_enable_bus_mastering(pci_device_t *dev);
// Read BAR
uint32_t pci_read_bar(pci_device_t *dev, int bar_num);int mydriver_init(void) {
// Find device
pci_device_t *dev = pci_find_device(VENDOR_ID, DEVICE_ID);
if (!dev) {
return -1;
}
// Enable device
pci_enable_bus_mastering(dev);
pci_enable_memory_space(dev);
// Map BARs
uint32_t bar0 = pci_read_bar(dev, 0);
// Initialize hardware
// ...
return 0;
}void irq_register_handler(int irq, irq_handler_t handler);
void my_irq_handler(registers_t *regs) {
// Handle interrupt
// ...
}
// In driver init:
irq_register_handler(IRQ_NUM, my_irq_handler);// Read from I/O port
uint8_t inb(uint16_t port);
uint16_t inw(uint16_t port);
uint32_t inl(uint16_t port);
// Write to I/O port
void outb(uint16_t port, uint8_t value);
void outw(uint16_t port, uint16_t value);
void outl(uint16_t port, uint32_t value);// Map physical address to virtual
void *ioremap(uint64_t phys_addr, size_t size);
// Access memory-mapped registers
volatile uint32_t *regs = (volatile uint32_t*)ioremap(bar0, 0x1000);
uint32_t status = regs[0];
regs[1] = command;- Device Drivers - Driver overview
- PCI Subsystem - PCI details