Serenity Operating System
1/*
2 * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <Kernel/API/POSIX/fcntl.h>
8#include <Kernel/API/Syscall.h>
9#include <arpa/inet.h>
10#include <errno.h>
11#include <serenity.h>
12#include <string.h>
13#include <syscall.h>
14
15extern "C" {
16
17int disown(pid_t pid)
18{
19 int rc = syscall(SC_disown, pid);
20 __RETURN_WITH_ERRNO(rc, rc, -1);
21}
22
23int profiling_enable(pid_t pid, uint64_t event_mask)
24{
25 int rc = syscall(SC_profiling_enable, pid, &event_mask);
26 __RETURN_WITH_ERRNO(rc, rc, -1);
27}
28
29int profiling_disable(pid_t pid)
30{
31 int rc = syscall(SC_profiling_disable, pid);
32 __RETURN_WITH_ERRNO(rc, rc, -1);
33}
34
35int profiling_free_buffer(pid_t pid)
36{
37 int rc = syscall(SC_profiling_free_buffer, pid);
38 __RETURN_WITH_ERRNO(rc, rc, -1);
39}
40
41int futex(uint32_t* userspace_address, int futex_op, uint32_t value, const struct timespec* timeout, uint32_t* userspace_address2, uint32_t value3)
42{
43 int rc;
44 switch (futex_op & FUTEX_CMD_MASK) {
45 case FUTEX_WAKE_OP: {
46 // These interpret timeout as a u32 value for val2
47 Syscall::SC_futex_params params {
48 .userspace_address = userspace_address,
49 .futex_op = futex_op,
50 .val = value,
51 .val2 = (FlatPtr)timeout,
52 .userspace_address2 = userspace_address2,
53 .val3 = value3
54 };
55 rc = syscall(SC_futex, ¶ms);
56 break;
57 }
58 default: {
59 Syscall::SC_futex_params params {
60 .userspace_address = userspace_address,
61 .futex_op = futex_op,
62 .val = value,
63 .timeout = timeout,
64 .userspace_address2 = userspace_address2,
65 .val3 = value3
66 };
67 rc = syscall(SC_futex, ¶ms);
68 break;
69 }
70 }
71 __RETURN_WITH_ERRNO(rc, rc, -1);
72}
73
74int purge(int mode)
75{
76 int rc = syscall(SC_purge, mode);
77 __RETURN_WITH_ERRNO(rc, rc, -1);
78}
79
80int perf_event(int type, uintptr_t arg1, FlatPtr arg2)
81{
82 int rc = syscall(SC_perf_event, type, arg1, arg2);
83 __RETURN_WITH_ERRNO(rc, rc, -1);
84}
85
86int perf_register_string(char const* string, size_t string_length)
87{
88 int rc = syscall(SC_perf_register_string, string, string_length);
89 __RETURN_WITH_ERRNO(rc, rc, -1);
90}
91
92int get_stack_bounds(uintptr_t* user_stack_base, size_t* user_stack_size)
93{
94 int rc = syscall(SC_get_stack_bounds, user_stack_base, user_stack_size);
95 __RETURN_WITH_ERRNO(rc, rc, -1);
96}
97
98int anon_create(size_t size, int options)
99{
100 int rc = syscall(SC_anon_create, size, options);
101 __RETURN_WITH_ERRNO(rc, rc, -1);
102}
103
104int serenity_readlink(char const* path, size_t path_length, char* buffer, size_t buffer_size)
105{
106 Syscall::SC_readlink_params small_params {
107 { path, path_length },
108 { buffer, buffer_size },
109 AT_FDCWD
110 };
111 int rc = syscall(SC_readlink, &small_params);
112 __RETURN_WITH_ERRNO(rc, rc, -1);
113}
114
115int setkeymap(char const* name, u32 const* map, u32* const shift_map, u32 const* alt_map, u32 const* altgr_map, u32 const* shift_altgr_map)
116{
117 Syscall::SC_setkeymap_params params { map, shift_map, alt_map, altgr_map, shift_altgr_map, { name, strlen(name) } };
118 return syscall(SC_setkeymap, ¶ms);
119}
120
121int getkeymap(char* name_buffer, size_t name_buffer_size, u32* map, u32* shift_map, u32* alt_map, u32* altgr_map, u32* shift_altgr_map)
122{
123 Syscall::SC_getkeymap_params params {
124 map,
125 shift_map,
126 alt_map,
127 altgr_map,
128 shift_altgr_map,
129 { name_buffer, name_buffer_size }
130 };
131 int rc = syscall(SC_getkeymap, ¶ms);
132 __RETURN_WITH_ERRNO(rc, rc, -1);
133}
134
135u16 internet_checksum(void const* ptr, size_t count)
136{
137 u32 checksum = 0;
138 auto* w = (u16 const*)ptr;
139 while (count > 1) {
140 checksum += ntohs(*w++);
141 if (checksum & 0x80000000)
142 checksum = (checksum & 0xffff) | (checksum >> 16);
143 count -= 2;
144 }
145 while (checksum >> 16)
146 checksum = (checksum & 0xffff) + (checksum >> 16);
147 return htons(~checksum);
148}
149
150int emuctl(uintptr_t command, uintptr_t arg0, uintptr_t arg1)
151{
152 return syscall(SC_emuctl, command, arg0, arg1);
153}
154
155int serenity_open(char const* path, size_t path_length, int options, ...)
156{
157 if (!path) {
158 errno = EFAULT;
159 return -1;
160 }
161
162 if (path_length > INT32_MAX) {
163 errno = EINVAL;
164 return -1;
165 }
166
167 va_list ap;
168 va_start(ap, options);
169 auto mode = (mode_t)va_arg(ap, unsigned);
170 va_end(ap);
171
172 Syscall::SC_open_params params { AT_FDCWD, { path, path_length }, options, mode };
173 int rc = syscall(SC_open, ¶ms);
174
175 __RETURN_WITH_ERRNO(rc, rc, -1);
176}
177}