-
Notifications
You must be signed in to change notification settings - Fork 7
syscall
System calls are the interface between user space and kernel space, these are some kernel functions that are securely available to all programs.
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
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.
The list represents them in the form of a C function prototype but they are all callable in assembler with their ID...
Note
File system syscalls are really low-level, you should probably use the filesys kernel module or a part of libC instead.
Returns a pointer to the default file system structure.
filesys_t *syscall_fs_get_default (void);
- Returns: Pointer to the structure.
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.
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.
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.
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
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.
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
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)
Note
The libC functions provide a more user-friendly way to allocate memory.
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 |
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
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
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
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
|
Returns the number of milliseconds since the system started.
uint32_t syscall_timer_get_ms (void);
- Returns: Number of milliseconds
Returns the current time in a tm_t
structure.
int syscall_time_get (
tm_t *tm
);
-
tm
: Pointer to thetm_t
structure
Returns a pointer to the raw kernel font data.
uint8_t *syscall_font_get (void);
- Returns: Pointer to the font data
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
Returns the current position of the kernel cursor on the screen.
int syscall_get_cursor (void);
- Returns: Cursor position :)
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)
The following defines are available to use the serial ports:
#define SERIAL_PORT_A 0x3F8
#define SERIAL_PORT_B 0x2F8
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
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
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
Get the oldest scancode from the keyboard buffer.
int syscall_sc_get (void);
- Returns: Scancode
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)
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
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 |
Get information about the kernel version.
char *syscall_sys_kinfo (void);
- Returns: Kernel version
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
profanOS processes management functions are a bit different from the standard POSIX functions, some of the POSIX functions are available in the libC too.
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
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.
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
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.
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
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 toWNOHANG
) - Returns: Process ID of the finished process
Note
The sys/wait.h
header is available to use wait functions
in a more POSIX way.
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)
Get the PID of the current process.
uint32_t syscall_process_pid (void);
- Returns: Process ID
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) |
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
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 |
Unload a kernel module
int syscall_pok_unload (
uint32_t id
);
-
id
: ID of the module -
Returns:
0
on success,1
on error
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
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
Unmap a virtual page.
int syscall_scuba_unmap(void *virt);
-
virt
: Virtual address -
Returns:
0
on success,1
on error
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
Happy Halloween profanOS! by @louisraverdy.
-
Getting Started
- Compiling profanOS
- Running profanOS
-
User Guide
-
Development Guide
-
Library Documentation