Skip to content

syscall

pf4 edited this page Dec 14, 2024 · 13 revisions

System Calls

System calls are the interface between user space and kernel space, these are some kernel functions that are securely available to all programs.

Related files

Index

Use System Calls

Usage in Assembly

To trigger a system call, you need to use the int 0x80 interrupt. The system call number is passed in the eax register, and the arguments are passed in the ebx, ecx, edx, esi, and edi registers. The return value is stored in the eax register.

mov eax, 0x0 ; syscall number
mov ebx, 0x1 ; arg1

int 0x80     ; trigger syscall

; return value is in eax

C headers usage

A ready-to-use C header is available in the profan/syscall.h file to use the system calls as functions.

#include <profan/syscall.h>
#include <string.h>
#include <stdio.h>

int main(void) {
    char *msg = "Hello, World!\n";
    uint32_t len = strlen(msg);

    // call the syscall
    int ret = syscall_serial_write(SERIAL_PORT_A, msg, len);

    printf("Serial write returned: %d\n", ret);

    return 0;
}

By default the header only contains the function prototypes, the functions are in the libC which dynamically links to each program. It is possible to declare them locally with the following defines:

// static functions declaration
#define _SYSCALL_CREATE_STATIC
#include <profan/syscall.h>

/* OR */

// global functions declaration
#define _SYSCALL_CREATE_FUNCS
#include <profan/syscall.h>

The #define _SYSCALL_CREATE_STATIC will create static functions that can be used in the current file only. The #define _SYSCALL_CREATE_FUNCS will create global functions that can be used in the whole program.

Note

You can also use asm volatile to call the system calls directly in C.

Syscalls List

The list represents them in the form of a C function prototype but they are all callable in assembler with their ID...

File System

Note

File system syscalls are really low-level, you should probably use the filesys kernel module or a part of libC instead.

0: fs_get_default

Returns a pointer to the default file system structure.

filesys_t *syscall_fs_get_default (void);
  • Returns: Pointer to the structure.

1: fs_read

Reads data from a container. Reading is static, you have to use the offset (not like read).

int syscall_fs_read (
    filesys_t *fs,
    uint32_t   sid,
    void      *buf,
    uint32_t   offset,
    uint32_t   size
);
  • fs: File system pointer (NULL for default)
  • sid: Container sector ID
  • buf: Buffer to store the data
  • offset: Offset to start reading
  • size: Number of bytes to read
  • Returns: 0 on success, 1 on error.

2: fs_write

Writes data to a container. Writing is static, you have to use the offset (not like write).

int syscall_fs_write (
    filesys_t *fs,
    uint32_t   sid,
    void      *buf,
    uint32_t   offset,
    uint32_t   size
);
  • fs: File system pointer (NULL for default)
  • sid: Container sector ID
  • buf: Buffer to write
  • offset: Offset to start writing
  • size: Number of bytes to write
  • Returns: 0 on success, 1 on error.

3: fs_set_size

Sets the size of a container. And cuts the data if the size is smaller.

int syscall_fs_set_size (
    filesys_t *fs,
    uint32_t   sid,
    uint32_t   size
);
  • fs: File system pointer (NULL for default)
  • sid: Container sector ID
  • size: New size of the container
  • Returns: 0 on success, 1 on error.

4: fs_get_size

Returns the size of a container.

uint32_t syscall_fs_get_size (
    filesys_t *fs,
    uint32_t   sid
);
  • fs: File system pointer (NULL for default)
  • sid: Container sector ID
  • Returns: Size of the container

5: fs_delete

Deletes a container and all its data.

int syscall_fs_delete (
    filesys_t *fs,
    uint32_t   sid
);
  • fs: File system pointer (NULL for default)
  • sid: Container sector ID
  • Returns: 0 on success, 1 on error.

6: fs_init

Initializes a new container.

uint32_t syscall_fs_init (
    filesys_t *fs,
    uint32_t   device_id,
    char      *meta
);
  • fs: File system pointer (NULL for default)
  • device_id: ID of the device to use
  • meta: Metadata of the container
  • Returns: Sector ID of the new container

7: fs_meta

Get or set the metadata of a container.

char *syscall_fs_meta (
    filesys_t *fs,
    uint32_t   sid,
    char      *meta
);
  • fs: File system pointer (NULL for default)
  • sid: Container sector ID
  • meta: Metadata to set (NULL to get)
  • Returns: Metadata of the container (NULL on error)

Kernel Memory Allocation

Note

The libC functions provide a more user-friendly way to allocate memory.

8: mem_alloc

Use kernel memory allocation to allocate memory.

uint32_t syscall_mem_alloc (
    uint32_t size,
    uint32_t align,
    int     state
);
  • size: Size of the memory to allocate
  • align: Alignment of the memory
  • state: Type of allocation
  • Returns: Address of the allocated memory

State as no impact on the allocation, it is just a way to categorize the memory allocation to track it and free it later.

State Description
0 free
1 simple alloc
2 initial block
3 mm struct
4 scuba page
5 loaded lib
6 as kernel

9: mem_free

Free a memory block allocated by mem_alloc.

int syscall_mem_free (
    uint32_t addr
);
  • addr: Address of the memory block to free
  • Returns: 0 on success, 1 on error

10: mem_free_all

Free all memory blocks allocated by a process.

Warning

This function is dangerous, it will free all memory blocks allocated by the process, including the dynamic linker! Use profan_cleanup of the profan.h header instead.

int syscall_mem_free_all (
    int pid
);
  • pid: Process ID
  • Returns: number of freed blocks

11: mem_get_alloc_size

Get the size of an allocated memory block.

uint32_t syscall_mem_get_alloc_size (
    uint32_t addr
);
  • addr: Address of the memory block
  • Returns: Size of the memory block

12: mem_info

Get information about memory and memory allocation.

int syscall_mem_info (
    int mode,
    int arg
);
  • mode: Information to get
  • arg: Argument for the information
  • Returns: Information
Mode Description
0 physical memory size
1 base address
2 MEM_PARTS size
3 MEM_PARTS addr
4 total alloc count
5 total free count
6 used memory size
07 simple alloc count of pid arg
08 simple alloc size of pid arg
09 alloc count of type arg
10 alloc size of type arg
11 all alloc count of pid arg
12 all alloc size of pid arg

Clock and Timer

13: timer_get_ms

Returns the number of milliseconds since the system started.

uint32_t syscall_timer_get_ms (void);
  • Returns: Number of milliseconds

14: time_get

Returns the current time in a tm_t structure.

int syscall_time_get (
    tm_t *tm
);
  • tm: Pointer to the tm_t structure

Console and Display

15: font_get

Returns a pointer to the raw kernel font data.

uint8_t *syscall_font_get (void);
  • Returns: Pointer to the font data

16: kcnprint

Prints a string to the kernel console, ANSI codes are supported.

int syscall_kcnprint (
    char *str,
    int   len,
    char  color
);
  • str: String to print
  • len: Length of the string
  • color: Color of the beginning of the string
  • Returns: Number of printed characters

17: get_cursor

Returns the current position of the kernel cursor on the screen.

int syscall_get_cursor (void);
  • Returns: Cursor position :)

18: vesa_info

Get information about the VESA mode.

int syscall_vesa_info (
    int mode
);
  • mode: Information to get
Mode Description
0 width
1 height
2 pitch
3 framebuffer address
4 state (active or not)

The following defines are available to get the information:

#define syscall_vesa_width()   syscall_vesa_info(0)
#define syscall_vesa_height()  syscall_vesa_info(1)
#define syscall_vesa_pitch()   syscall_vesa_info(2)
#define syscall_vesa_fb() ((void *) syscall_vesa_info(3))
#define syscall_vesa_state()   syscall_vesa_info(4)

Serial I/O

The following defines are available to use the serial ports:

#define SERIAL_PORT_A 0x3F8
#define SERIAL_PORT_B 0x2F8

19: serial_read

Reads data from a serial port.

int syscall_serial_read(
    int      port,
    char    *buf,
    uint32_t size
);
  • port: Serial port address
  • buf: Buffer to store the data
  • size: Number of bytes to read
  • Returns: Number of bytes read

20: serial_write

Writes data to a serial port.

int syscall_serial_write(
    int      port,
    char    *buf,
    uint32_t size
);
  • port: Serial port address
  • buf: Buffer to write
  • size: Number of bytes to write
  • Returns: Number of bytes written

Keyboard and Mouse

21: sc_to_char

Use the kernel keymap to convert a scancode to a character.

Note

the profan_kb_get_char function of the profan.h header follows the current loaded keymap and is more user-friendly.

char syscall_sc_to_char (
    int scancode,
    int shift
);
  • scancode: Scancode to convert
  • shift: Shift state
  • Returns: Converted character

22: sc_get

Get the oldest scancode from the keyboard buffer.

int syscall_sc_get (void);
  • Returns: Scancode

23: mouse_call

Get information about the mouse.

int syscall_mouse_call (
    int mode,
    int arg
);
Mode Description
0 get x position
1 get y position
2 get button state
3 set x position
4 set y position
5 reset mouse

The following defines are available in the profan/mouse.h header to use the mouse call function:

#define mouse_get_x() syscall_mouse_call(0, 0)
#define mouse_get_y() syscall_mouse_call(1, 0)

#define mouse_get_button(button) syscall_mouse_call(2, button)

#define mouse_set_x(x) syscall_mouse_call(3, x)
#define mouse_set_y(y) syscall_mouse_call(4, y)

#define mouse_reset() syscall_mouse_call(5, 0)

System Management

24: sys_set_reporter

Map a function to the kernel reporter or reset it.

int syscall_sys_set_reporter (
    void *func
);
  • func: Function pointer (NULL to reset)
  • Returns: 0 on success, 1 on error

25: sys_power

Reboot or shutdown the system.

int syscall_sys_power (
    int mode
);
  • mode: Action to do
  • Returns: 0 on success, 1 on error
Mode Description
0 reboot
1 shutdown

26: sys_kinfo

Get information about the kernel version.

char *syscall_sys_kinfo (void);
  • Returns: Kernel version

27: binary_exec

Execute a binary file with arguments and environment variables. The function will replace the current page directory with a new one and jump to the binary file (similar to the execve function).

Warning

The libC or run_ifexist function is probably a better way to run a program safely.

int syscall_binary_exec(
    uint32_t sid,
    int      argc,
    char   **argv,
    char   **envp
);
  • sid: Sector ID of the binary file
  • argc: Number of arguments
  • argv: Arguments
  • envp: Environment variables
  • Returns: 0 on success, 1 on error

Process Management

profanOS processes management functions are a bit different from the standard POSIX functions, some of the POSIX functions are available in the libC too.

28: process_auto_schedule

Disable or enable the automatic process scheduling, if disabled, the kernel will not automatically switch to the next process.

Note

If the scheduling is disabled twice, it should be enabled twice to work again.

int syscall_process_auto_schedule (
    int enable
);
  • enable: Enable or disable
  • Returns: 0 on success, 1 on error

29: process_create

Create a new process with a function pointer.

int syscall_process_create (
    void     *func,
    int       copy_page,
    char     *name,
    int       argc,
    uint32_t *argv
);
  • func: Function pointer
  • copy_page: Copy the parent page directory
  • name: Name of the process
  • argc: Number of arguments
  • argv: Arguments (32bit numbers pushed on the stack)
  • Returns: Process ID

Note

To push a struct on the stack, you should cut it into 32bit numbers and increment the argument count.

30: process_fork

Fork the current process (exactly like the fork function) but don't wake up the child process.

int syscall_process_fork (void);
  • Returns: Process ID of the child process

31: process_sleep

Put a process to sleep for a number of milliseconds. The process will not be scheduled until the time is over.

int syscall_process_sleep (
    uint32_t pid,
    uint32_t ms
);
  • pid: Process ID
  • ms: Number of milliseconds

Note

ms can be 0 to switch to the next process immediately (like yield), UINT32_MAX to sleep forever or any other value to sleep for a number of milliseconds.

32: process_wakeup

Wakeup a sleeping process. The process will be scheduled again. The handover parameter is used to automatically wait for pid to finish before waking up the current process.

int syscall_process_wakeup (
    uint32_t pid
    int      handover
);
  • pid: Process ID
  • handover: Handover the process
  • Returns: 0 on success, 1 on error

33: process_wait

Wait for a process to finish. The function will put the current process to sleep until the process with the given PID finishes.

int syscall_process_wait (
    int      pid,
    uint8_t *retcode
    int      block
);
  • pid: Process ID (-1 to wait for any child)
  • retcode: pointer to an u8 to store the return code
  • block: Block the current process (similar to WNOHANG)
  • Returns: Process ID of the finished process

Note

The sys/wait.h header is available to use wait functions in a more POSIX way.

34: process_kill

Kill a process and free its memory.

int syscall_process_kill (
    uint32_t pid,
    int      retcode,
);
  • pid: Process ID
  • retcode: Return code of the process
  • Returns: 1 on error (no return on success)

35: process_pid

Get the PID of the current process.

uint32_t syscall_process_pid (void);
  • Returns: Process ID

36: process_info

Get information about a process.

uint32_t syscall_process_info (
    uint32_t pid,
    int      mode
    void    *ptr
);
  • pid: Process ID
  • mode: Information to get
  • ptr: Pointer to store the information
Mode Description
0 parent PID
1 state
2 sleep timeout
3 run time
4 name
5 stack pointer
6 comm structure
7 SET name (in ptr)

The following defines are available to get the information:

#define PROC_INFO_PPID     0
#define PROC_INFO_STATE    1
#define PROC_INFO_SLEEP_TO 2
#define PROC_INFO_RUN_TIME 3
#define PROC_INFO_NAME     4
#define PROC_INFO_STACK    5
#define PROC_INFO_COMM     6
#define PROC_INFO_SET_NAME 7
State Description
0 free
1 zombie
2 sleeping
3 in queue
4 running
5 idle (pid 1 only)

37: process_list_all

List all the alive processes.

int syscall_process_list_all (
    uint32_t *buf,
    int       max
);
  • buf: Buffer to store the PIDs
  • max: Size of the buffer
  • Returns: Number of PIDs

Kernel Modules

38: pok_load

Load a kernel module from a path

int syscall_pok_load (
    char    *path,
    uint32_t id
);
  • path: Path to the module
  • id: ID of the module
  • Returns: function count or error code
Error code Description
-1 file not found
-2 invalid module id range
-3 file is not a dynamic ELF
-4 ELF relocation failed
-5 failed to read functions
-6 init function exited with error

39: pok_unload

Unload a kernel module

int syscall_pok_unload (
    uint32_t id
);
  • id: ID of the module
  • Returns: 0 on success, 1 on error

Virtual Memory

40: scuba_generate

Allocate and map virtual page(s) to physical memory.

void *syscall_scuba_generate(void *virt, uint32_t count);
  • virt: Virtual address
  • count: Number of following pages
  • Returns: physical address

41: scuba_map

Map a virtual page to physical memory.

int syscall_scuba_map(void *virt, void *phys, int child_copy);
  • virt: Virtual address
  • phys: Physical address
  • child_copy: Copy the page in future children
  • Returns: 0 on success, 1 on error

42: scuba_unmap

Unmap a virtual page.

int syscall_scuba_unmap(void *virt);
  • virt: Virtual address
  • Returns: 0 on success, 1 on error

43: scuba_phys

Get the physical address of a virtual address.

void *syscall_scuba_phys(void *virt);
  • virt: Virtual address
  • Returns: Physical address

Updated for generic kernel 1.2.1


Halloween Happy Halloween profanOS! by @louisraverdy.