Skip to content

Driver API

NtinosTheGamer2324 edited this page Dec 28, 2025 · 3 revisions

Driver API

API for developing hardware drivers in ModuOS.

SQRM Third‑Party Driver SDK (Loadable Kernel Modules)

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.

Where modules live

Modules are searched under:

  • /ModuOS/System64/md/ (on the selected boot filesystem)

On the ISO this corresponds to:

  • targets/AMD64/iso/ModuOS/System64/md/

Required symbols / entry points

A valid module must export:

  1. 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");
  1. 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;

Module types

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

Building a .sqrm

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.sqrm

Notes:

  • -fPIC is required.
  • -mno-red-zone is required for interrupt-safe kernel code.
  • The link must produce ET_DYN (-shared).
  • The entry point must be sqrm_module_init.

Installing / testing

  1. Copy your module into the ISO tree:
  • targets/AMD64/iso/ModuOS/System64/md/<name>.sqrm
  1. Rebuild the ISO.

  2. Boot and check COM logs for module loader output:

  • [SQRM] Loading module: ...

Examples

  • In-tree minimal module: modules/hello_sqrm.c
  • SDK template: sdk/template_hello/hello_sqrm.c
  • Filesystem module: modules/ext2_sqrm.c

Driver Structure

typedef struct {
    const char *name;
    int (*init)(void);
    int (*probe)(void);
    void (*remove)(void);
} driver_t;

PCI Driver

PCI Device Structure

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;

PCI Functions

// 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);

Example PCI Driver

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;
}

IRQ Handling

Register IRQ Handler

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);

I/O Operations

Port I/O

// 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);

Memory-Mapped I/O

// 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;

Next Steps

Clone this wiki locally