syscall.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754
  1. /* vim: tabstop=4 shiftwidth=4 noexpandtab
  2. * This file is part of ToaruOS and is released under the terms
  3. * of the NCSA / University of Illinois License - see LICENSE.md
  4. * Copyright (C) 2011-2014 Kevin Lange
  5. * Copyright (C) 2012 Markus Schober
  6. *
  7. * Syscall Tables
  8. *
  9. */
  10. #include <system.h>
  11. #include <process.h>
  12. #include <logging.h>
  13. #include <fs.h>
  14. #include <pipe.h>
  15. #include <version.h>
  16. #include <shm.h>
  17. #include <utsname.h>
  18. #include <printf.h>
  19. #include <syscall_nums.h>
  20. static char hostname[256];
  21. static size_t hostname_len = 0;
  22. static int RESERVED(void) {
  23. return -1;
  24. }
  25. /*
  26. * System calls themselves
  27. */
  28. #define FD_INRANGE(FD) \
  29. ((FD) < (int)current_process->fds->length && (FD) > 0)
  30. #define FD_ENTRY(FD) \
  31. (current_process->fds->entries[(FD)])
  32. #define FD_CHECK(FD) \
  33. (FD_INRANGE(FD) && FD_ENTRY(FD))
  34. #define PTR_INRANGE(PTR) \
  35. (!(PTR) || (uintptr_t)(PTR) >= current_process->image.entry)
  36. #define PTR_VALIDATE(PTR) \
  37. ptr_validate((void *)(PTR), __func__)
  38. static void ptr_validate(void * ptr, const char * syscall) {
  39. if (PTR_INRANGE(ptr))
  40. return;
  41. debug_print(ERROR, "SEGFAULT: invalid pointer passed to %s. (0x%x < 0x%x)",
  42. syscall, (uintptr_t)ptr, current_process->image.entry);
  43. HALT_AND_CATCH_FIRE("Segmentation fault", NULL);
  44. }
  45. void validate(void * ptr) {
  46. ptr_validate(ptr, "syscall");
  47. }
  48. /*
  49. * Exit the current task.
  50. * DOES NOT RETURN!
  51. */
  52. static int __attribute__((noreturn)) sys_exit(int retval) {
  53. /* Deschedule the current task */
  54. task_exit(retval);
  55. for (;;) ;
  56. }
  57. static int sys_read(int fd, char * ptr, int len) {
  58. if (FD_CHECK(fd)) {
  59. PTR_VALIDATE(ptr);
  60. fs_node_t * node = FD_ENTRY(fd);
  61. uint32_t out = read_fs(node, node->offset, len, (uint8_t *)ptr);
  62. node->offset += out;
  63. return (int)out;
  64. }
  65. return -1;
  66. }
  67. static int sys_ioctl(int fd, int request, void * argp) {
  68. if (FD_CHECK(fd)) {
  69. PTR_VALIDATE(argp);
  70. return ioctl_fs(FD_ENTRY(fd), request, argp);
  71. }
  72. return -1;
  73. }
  74. static int sys_readdir(int fd, int index, struct dirent * entry) {
  75. if (FD_CHECK(fd)) {
  76. PTR_VALIDATE(entry);
  77. struct dirent * kentry = readdir_fs(FD_ENTRY(fd), (uint32_t)index);
  78. if (kentry) {
  79. memcpy(entry, kentry, sizeof *entry);
  80. free(kentry);
  81. return 0;
  82. } else {
  83. return 1;
  84. }
  85. }
  86. return -1;
  87. }
  88. static int sys_write(int fd, char * ptr, int len) {
  89. if (FD_CHECK(fd)) {
  90. PTR_VALIDATE(ptr);
  91. fs_node_t * node = FD_ENTRY(fd);
  92. uint32_t out = write_fs(node, node->offset, len, (uint8_t *)ptr);
  93. node->offset += out;
  94. return out;
  95. }
  96. return -1;
  97. }
  98. static int sys_waitpid(int pid, int * status, int options) {
  99. if (PTR_INRANGE(status))
  100. return waitpid(pid, status, options);
  101. return -EINVAL;
  102. }
  103. static int sys_open(const char * file, int flags, int mode) {
  104. PTR_VALIDATE(file);
  105. debug_print(NOTICE, "open(%s) flags=0x%x; mode=0x%x", file, flags, mode);
  106. fs_node_t * node = kopen((char *)file, flags);
  107. if (!node && (flags & O_CREAT)) {
  108. debug_print(NOTICE, "- file does not exist and create was requested.");
  109. /* Um, make one */
  110. if (!create_file_fs((char *)file, mode)) {
  111. node = kopen((char *)file, flags);
  112. }
  113. }
  114. if (!node) {
  115. debug_print(NOTICE, "File does not exist; someone should be setting errno?");
  116. return -1;
  117. }
  118. node->offset = 0;
  119. int fd = process_append_fd((process_t *)current_process, node);
  120. debug_print(INFO, "[open] pid=%d %s -> %d", getpid(), file, fd);
  121. return fd;
  122. }
  123. static int sys_access(const char * file, int flags) {
  124. PTR_VALIDATE(file);
  125. debug_print(INFO, "access(%s, 0x%x) from pid=%d", file, flags, getpid());
  126. fs_node_t * node = kopen((char *)file, 0);
  127. if (!node) return -1;
  128. close_fs(node);
  129. return 0;
  130. }
  131. static int sys_close(int fd) {
  132. if (FD_CHECK(fd)) {
  133. close_fs(FD_ENTRY(fd));
  134. FD_ENTRY(fd) = NULL;
  135. return 0;
  136. }
  137. return -1;
  138. }
  139. static int sys_sbrk(int size) {
  140. process_t * proc = (process_t *)current_process;
  141. if (proc->group != 0) {
  142. proc = process_from_pid(proc->group);
  143. }
  144. spin_lock(&proc->image.lock);
  145. uintptr_t ret = proc->image.heap;
  146. uintptr_t i_ret = ret;
  147. while (ret % 0x1000) {
  148. ret++;
  149. }
  150. proc->image.heap += (ret - i_ret) + size;
  151. while (proc->image.heap > proc->image.heap_actual) {
  152. proc->image.heap_actual += 0x1000;
  153. assert(proc->image.heap_actual % 0x1000 == 0);
  154. alloc_frame(get_page(proc->image.heap_actual, 1, current_directory), 0, 1);
  155. invalidate_tables_at(proc->image.heap_actual);
  156. }
  157. spin_unlock(&proc->image.lock);
  158. return ret;
  159. }
  160. static int sys_getpid(void) {
  161. /* The user actually wants the pid of the originating thread (which can be us). */
  162. if (current_process->group) {
  163. return current_process->group;
  164. } else {
  165. /* We are the leader */
  166. return current_process->id;
  167. }
  168. }
  169. /* Actual getpid() */
  170. static int sys_gettid(void) {
  171. return getpid();
  172. }
  173. static int sys_execve(const char * filename, char *const argv[], char *const envp[]) {
  174. PTR_VALIDATE(argv);
  175. PTR_VALIDATE(filename);
  176. PTR_VALIDATE(envp);
  177. debug_print(NOTICE, "%d = exec(%s, ...)", current_process->id, filename);
  178. int argc = 0;
  179. int envc = 0;
  180. while (argv[argc]) {
  181. PTR_VALIDATE(argv[argc]);
  182. ++argc;
  183. }
  184. if (envp) {
  185. while (envp[envc]) {
  186. PTR_VALIDATE(envp[envc]);
  187. ++envc;
  188. }
  189. }
  190. debug_print(INFO, "Allocating space for arguments...");
  191. char ** argv_ = malloc(sizeof(char *) * (argc + 1));
  192. for (int j = 0; j < argc; ++j) {
  193. argv_[j] = malloc((strlen(argv[j]) + 1) * sizeof(char));
  194. memcpy(argv_[j], argv[j], strlen(argv[j]) + 1);
  195. }
  196. argv_[argc] = 0;
  197. char ** envp_;
  198. if (envp && envc) {
  199. envp_ = malloc(sizeof(char *) * (envc + 1));
  200. for (int j = 0; j < envc; ++j) {
  201. envp_[j] = malloc((strlen(envp[j]) + 1) * sizeof(char));
  202. memcpy(envp_[j], envp[j], strlen(envp[j]) + 1);
  203. }
  204. envp_[envc] = 0;
  205. } else {
  206. envp_ = malloc(sizeof(char *));
  207. envp_[0] = NULL;
  208. }
  209. debug_print(INFO,"Releasing all shmem regions...");
  210. shm_release_all((process_t *)current_process);
  211. debug_print(INFO,"Executing...");
  212. /* Discard envp */
  213. exec((char *)filename, argc, (char **)argv_, (char **)envp_);
  214. return -1;
  215. }
  216. static int sys_seek(int fd, int offset, int whence) {
  217. if (FD_CHECK(fd)) {
  218. if (fd < 3) {
  219. return 0;
  220. }
  221. switch (whence) {
  222. case 0:
  223. FD_ENTRY(fd)->offset = offset;
  224. break;
  225. case 1:
  226. FD_ENTRY(fd)->offset += offset;
  227. break;
  228. case 2:
  229. FD_ENTRY(fd)->offset = FD_ENTRY(fd)->length + offset;
  230. break;
  231. }
  232. return FD_ENTRY(fd)->offset;
  233. }
  234. return -1;
  235. }
  236. static int stat_node(fs_node_t * fn, uintptr_t st) {
  237. struct stat * f = (struct stat *)st;
  238. PTR_VALIDATE(fn);
  239. PTR_VALIDATE(f);
  240. if (!fn) {
  241. memset(f, 0x00, sizeof(struct stat));
  242. debug_print(INFO, "stat: This file doesn't exist");
  243. return -1;
  244. }
  245. f->st_dev = 0;
  246. f->st_ino = fn->inode;
  247. uint32_t flags = 0;
  248. if (fn->flags & FS_FILE) { flags |= _IFREG; }
  249. if (fn->flags & FS_DIRECTORY) { flags |= _IFDIR; }
  250. if (fn->flags & FS_CHARDEVICE) { flags |= _IFCHR; }
  251. if (fn->flags & FS_BLOCKDEVICE) { flags |= _IFBLK; }
  252. if (fn->flags & FS_PIPE) { flags |= _IFIFO; }
  253. if (fn->flags & FS_SYMLINK) { flags |= _IFLNK; }
  254. f->st_mode = fn->mask | flags;
  255. f->st_nlink = fn->nlink;
  256. f->st_uid = fn->uid;
  257. f->st_gid = fn->gid;
  258. f->st_rdev = 0;
  259. f->st_size = fn->length;
  260. f->st_atime = fn->atime;
  261. f->st_mtime = fn->mtime;
  262. f->st_ctime = fn->ctime;
  263. if (fn->get_size) {
  264. f->st_size = fn->get_size(fn);
  265. }
  266. return 0;
  267. }
  268. static int sys_statf(char * file, uintptr_t st) {
  269. int result;
  270. PTR_VALIDATE(file);
  271. PTR_VALIDATE(st);
  272. fs_node_t * fn = kopen(file, 0);
  273. result = stat_node(fn, st);
  274. if (fn) {
  275. close_fs(fn);
  276. }
  277. return result;
  278. }
  279. static int sys_chmod(char * file, int mode) {
  280. int result;
  281. PTR_VALIDATE(file);
  282. fs_node_t * fn = kopen(file, 0);
  283. if (fn) {
  284. result = chmod_fs(fn, mode);
  285. close_fs(fn);
  286. return result;
  287. } else {
  288. return -1;
  289. }
  290. }
  291. static int sys_stat(int fd, uintptr_t st) {
  292. PTR_VALIDATE(st);
  293. if (FD_CHECK(fd)) {
  294. return stat_node(FD_ENTRY(fd), st);
  295. }
  296. return -1;
  297. }
  298. static int sys_mkpipe(void) {
  299. fs_node_t * node = make_pipe(4096 * 2);
  300. open_fs(node, 0);
  301. return process_append_fd((process_t *)current_process, node);
  302. }
  303. static int sys_dup2(int old, int new) {
  304. process_move_fd((process_t *)current_process, old, new);
  305. return new;
  306. }
  307. static int sys_getuid(void) {
  308. return current_process->user;
  309. }
  310. static int sys_setuid(user_t new_uid) {
  311. if (current_process->user == USER_ROOT_UID) {
  312. current_process->user = new_uid;
  313. return 0;
  314. }
  315. return -1;
  316. }
  317. static int sys_uname(struct utsname * name) {
  318. PTR_VALIDATE(name);
  319. char version_number[256];
  320. sprintf(version_number, __kernel_version_format,
  321. __kernel_version_major,
  322. __kernel_version_minor,
  323. __kernel_version_lower,
  324. __kernel_version_suffix);
  325. char version_string[256];
  326. sprintf(version_string, "%s %s %s",
  327. __kernel_version_codename,
  328. __kernel_build_date,
  329. __kernel_build_time);
  330. strcpy(name->sysname, __kernel_name);
  331. strcpy(name->nodename, hostname);
  332. strcpy(name->release, version_number);
  333. strcpy(name->version, version_string);
  334. strcpy(name->machine, __kernel_arch);
  335. strcpy(name->domainname, "");
  336. return 0;
  337. }
  338. static int sys_signal(uint32_t signum, uintptr_t handler) {
  339. if (signum > NUMSIGNALS) {
  340. return -1;
  341. }
  342. uintptr_t old = current_process->signals.functions[signum];
  343. current_process->signals.functions[signum] = handler;
  344. return (int)old;
  345. }
  346. /*
  347. static void inspect_memory (uintptr_t vaddr) {
  348. // Please use this scary hack of a function as infrequently as possible.
  349. shmem_debug_frame(vaddr);
  350. }
  351. */
  352. static int sys_reboot(void) {
  353. debug_print(NOTICE, "[kernel] Reboot requested from process %d by user #%d", current_process->id, current_process->user);
  354. if (current_process->user != USER_ROOT_UID) {
  355. return -1;
  356. } else {
  357. debug_print(NOTICE, "[kernel] Good bye!");
  358. /* Goodbye, cruel world */
  359. IRQ_OFF;
  360. uint8_t out = 0x02;
  361. while ((out & 0x02) != 0) {
  362. out = inportb(0x64);
  363. }
  364. outportb(0x64, 0xFE); /* Reset */
  365. STOP;
  366. }
  367. return 0;
  368. }
  369. static int sys_chdir(char * newdir) {
  370. PTR_VALIDATE(newdir);
  371. char * path = canonicalize_path(current_process->wd_name, newdir);
  372. fs_node_t * chd = kopen(path, 0);
  373. if (chd) {
  374. if ((chd->flags & FS_DIRECTORY) == 0) {
  375. close_fs(chd);
  376. return -1;
  377. }
  378. close_fs(chd);
  379. free(current_process->wd_name);
  380. current_process->wd_name = malloc(strlen(path) + 1);
  381. memcpy(current_process->wd_name, path, strlen(path) + 1);
  382. return 0;
  383. } else {
  384. return -1;
  385. }
  386. }
  387. static int sys_getcwd(char * buf, size_t size) {
  388. if (buf) {
  389. PTR_VALIDATE(buf);
  390. return (int)memcpy(buf, current_process->wd_name, min(size, strlen(current_process->wd_name) + 1));
  391. }
  392. return 0;
  393. }
  394. static int sys_sethostname(char * new_hostname) {
  395. if (current_process->user == USER_ROOT_UID) {
  396. PTR_VALIDATE(new_hostname);
  397. size_t len = strlen(new_hostname) + 1;
  398. if (len > 256) {
  399. return 1;
  400. }
  401. hostname_len = len;
  402. memcpy(hostname, new_hostname, hostname_len);
  403. return 0;
  404. } else {
  405. return 1;
  406. }
  407. }
  408. static int sys_gethostname(char * buffer) {
  409. PTR_VALIDATE(buffer);
  410. memcpy(buffer, hostname, hostname_len);
  411. return hostname_len;
  412. }
  413. extern int mkdir_fs(char *name, uint16_t permission);
  414. static int sys_mkdir(char * path, uint32_t mode) {
  415. return mkdir_fs(path, 0777);
  416. }
  417. /*
  418. * Yield the rest of the quantum;
  419. * useful for busy waiting and other such things
  420. */
  421. static int sys_yield(void) {
  422. switch_task(1);
  423. return 1;
  424. }
  425. /*
  426. * System Function
  427. */
  428. static int sys_sysfunc(int fn, char ** args) {
  429. /* System Functions are special debugging system calls */
  430. if (current_process->user == USER_ROOT_UID) {
  431. switch (fn) {
  432. case 3:
  433. debug_print(ERROR, "sync is currently unimplemented");
  434. //ext2_disk_sync();
  435. return 0;
  436. case 4:
  437. /* Request kernel output to file descriptor in arg0*/
  438. debug_print(NOTICE, "Setting output to file object in process %d's fd=%d!", getpid(), (int)args);
  439. debug_file = current_process->fds->entries[(int)args];
  440. break;
  441. case 5:
  442. {
  443. char *arg;
  444. PTR_VALIDATE(args);
  445. for (arg = args[0]; arg; arg++)
  446. PTR_VALIDATE(arg);
  447. debug_print(NOTICE, "Replacing process %d's file descriptors with pointers to %s", getpid(), (char *)args);
  448. fs_node_t * repdev = kopen((char *)args, 0);
  449. while (current_process->fds->length < 3) {
  450. process_append_fd((process_t *)current_process, repdev);
  451. }
  452. FD_ENTRY(0) = repdev;
  453. FD_ENTRY(1) = repdev;
  454. FD_ENTRY(2) = repdev;
  455. }
  456. break;
  457. case 6:
  458. debug_print(WARNING, "writing contents of file %s to sdb", args[0]);
  459. {
  460. PTR_VALIDATE(args);
  461. PTR_VALIDATE(args[0]);
  462. fs_node_t * file = kopen((char *)args[0], 0);
  463. if (!file) {
  464. return -1;
  465. }
  466. size_t length = file->length;
  467. uint8_t * buffer = malloc(length);
  468. read_fs(file, 0, length, (uint8_t *)buffer);
  469. close_fs(file);
  470. debug_print(WARNING, "Finished reading file, going to write it now.");
  471. fs_node_t * f = kopen("/dev/sdb", 0);
  472. if (!f) {
  473. return 1;
  474. }
  475. write_fs(f, 0, length, buffer);
  476. free(buffer);
  477. return 0;
  478. }
  479. case 7:
  480. debug_print(NOTICE, "Spawning debug hook as child of process %d.", getpid());
  481. if (debug_hook) {
  482. fs_node_t * tty = FD_ENTRY(0);
  483. return create_kernel_tasklet(debug_hook, "[kttydebug]", tty);
  484. } else {
  485. return -1;
  486. }
  487. default:
  488. debug_print(ERROR, "Bad system function %d", fn);
  489. break;
  490. }
  491. }
  492. return -1; /* Bad system function or access failure */
  493. }
  494. static int sys_sleepabs(unsigned long seconds, unsigned long subseconds) {
  495. /* Mark us as asleep until <some time period> */
  496. sleep_until((process_t *)current_process, seconds, subseconds);
  497. /* Switch without adding us to the queue */
  498. switch_task(0);
  499. if (seconds > timer_ticks || (seconds == timer_ticks && subseconds >= timer_subticks)) {
  500. return 0;
  501. } else {
  502. return 1;
  503. }
  504. }
  505. static int sys_sleep(unsigned long seconds, unsigned long subseconds) {
  506. unsigned long s, ss;
  507. relative_time(seconds, subseconds * 10, &s, &ss);
  508. return sys_sleepabs(s, ss);
  509. }
  510. static int sys_umask(int mode) {
  511. current_process->mask = mode & 0777;
  512. return 0;
  513. }
  514. static int sys_unlink(char * file) {
  515. PTR_VALIDATE(file);
  516. return unlink_fs(file);
  517. }
  518. static int sys_fork(void) {
  519. return (int)fork();
  520. }
  521. static int sys_clone(uintptr_t new_stack, uintptr_t thread_func, uintptr_t arg) {
  522. if (PTR_INRANGE(new_stack) && PTR_INRANGE(thread_func)) {
  523. return (int)clone(new_stack, thread_func, arg);
  524. }
  525. return -1;
  526. }
  527. static int sys_shm_obtain(char * path, size_t * size) {
  528. PTR_VALIDATE(path);
  529. PTR_VALIDATE(size);
  530. return (int)shm_obtain(path, size);
  531. }
  532. static int sys_shm_release(char * path) {
  533. PTR_VALIDATE(path);
  534. return shm_release(path);
  535. }
  536. static int sys_kill(pid_t process, uint32_t signal) {
  537. return send_signal(process, signal);
  538. }
  539. static int sys_gettimeofday(struct timeval * tv, void * tz) {
  540. PTR_VALIDATE(tv);
  541. PTR_VALIDATE(tz);
  542. return gettimeofday(tv, tz);
  543. }
  544. static int sys_openpty(int * master, int * slave, char * name, void * _ign0, void * size) {
  545. /* We require a place to put these when we are done. */
  546. if (!master || !slave) return -1;
  547. if (PTR_INRANGE(master) && PTR_INRANGE(slave) && PTR_INRANGE(size)) {
  548. /* Create a new pseudo terminal */
  549. fs_node_t * fs_master;
  550. fs_node_t * fs_slave;
  551. pty_create(size, &fs_master, &fs_slave);
  552. /* Append the master and slave to the calling process */
  553. *master = process_append_fd((process_t *)current_process, fs_master);
  554. *slave = process_append_fd((process_t *)current_process, fs_slave);
  555. open_fs(fs_master, 0);
  556. open_fs(fs_slave, 0);
  557. /* Return success */
  558. return 0;
  559. }
  560. return -1;
  561. }
  562. static int sys_pipe(int pipes[2]) {
  563. if (PTR_INRANGE(pipes)) {
  564. fs_node_t * outpipes[2];
  565. make_unix_pipe(outpipes);
  566. open_fs(outpipes[0], 0);
  567. open_fs(outpipes[1], 0);
  568. pipes[0] = process_append_fd((process_t *)current_process, outpipes[0]);
  569. pipes[1] = process_append_fd((process_t *)current_process, outpipes[1]);
  570. return 0;
  571. }
  572. return -EFAULT;
  573. }
  574. static int sys_mount(char * arg, char * mountpoint, char * type, unsigned long flags, void * data) {
  575. (void)flags;
  576. (void)data;
  577. if (current_process->user != USER_ROOT_UID)
  578. return -EPERM;
  579. if (PTR_INRANGE(arg) && PTR_INRANGE(mountpoint) && PTR_INRANGE(type)) {
  580. return vfs_mount_type(type, arg, mountpoint);
  581. }
  582. return -EFAULT;
  583. }
  584. /*
  585. * System Call Internals
  586. */
  587. static int (*syscalls[])() = {
  588. /* System Call Table */
  589. [SYS_EXT] = sys_exit,
  590. [SYS_OPEN] = sys_open,
  591. [SYS_READ] = sys_read,
  592. [SYS_WRITE] = sys_write,
  593. [SYS_CLOSE] = sys_close,
  594. [SYS_GETTIMEOFDAY] = sys_gettimeofday,
  595. [SYS_EXECVE] = sys_execve,
  596. [SYS_FORK] = sys_fork,
  597. [SYS_GETPID] = sys_getpid,
  598. [SYS_SBRK] = sys_sbrk,
  599. [SYS_UNAME] = sys_uname,
  600. [SYS_OPENPTY] = sys_openpty,
  601. [SYS_SEEK] = sys_seek,
  602. [SYS_STAT] = sys_stat,
  603. [SYS_MKPIPE] = sys_mkpipe,
  604. [SYS_DUP2] = sys_dup2,
  605. [SYS_GETUID] = sys_getuid,
  606. [SYS_SETUID] = sys_setuid,
  607. [SYS_REBOOT] = sys_reboot,
  608. [SYS_READDIR] = sys_readdir,
  609. [SYS_CHDIR] = sys_chdir,
  610. [SYS_GETCWD] = sys_getcwd,
  611. [SYS_CLONE] = sys_clone,
  612. [SYS_SETHOSTNAME] = sys_sethostname,
  613. [SYS_GETHOSTNAME] = sys_gethostname,
  614. [SYS_MKDIR] = sys_mkdir,
  615. [SYS_SHM_OBTAIN] = sys_shm_obtain,
  616. [SYS_SHM_RELEASE] = sys_shm_release,
  617. [SYS_KILL] = sys_kill,
  618. [SYS_SIGNAL] = sys_signal,
  619. [SYS_GETTID] = sys_gettid,
  620. [SYS_YIELD] = sys_yield,
  621. [SYS_SYSFUNC] = sys_sysfunc,
  622. [SYS_SLEEPABS] = sys_sleepabs,
  623. [SYS_SLEEP] = sys_sleep,
  624. [SYS_IOCTL] = sys_ioctl,
  625. [SYS_ACCESS] = sys_access,
  626. [SYS_STATF] = sys_statf,
  627. [SYS_CHMOD] = sys_chmod,
  628. [SYS_UMASK] = sys_umask,
  629. [SYS_UNLINK] = sys_unlink,
  630. [SYS_WAITPID] = sys_waitpid,
  631. [SYS_PIPE] = sys_pipe,
  632. [SYS_MOUNT] = sys_mount,
  633. };
  634. uint32_t num_syscalls = sizeof(syscalls) / sizeof(int (*)());
  635. typedef uint32_t (*scall_func)(unsigned int, ...);
  636. void syscall_handler(struct regs * r) {
  637. if (r->eax >= num_syscalls) {
  638. return;
  639. }
  640. uintptr_t location = (uintptr_t)syscalls[r->eax];
  641. if (!location) {
  642. return;
  643. }
  644. /* Update the syscall registers for this process */
  645. current_process->syscall_registers = r;
  646. /* Call the syscall function */
  647. scall_func func = (scall_func)location;
  648. uint32_t ret = func(r->ebx, r->ecx, r->edx, r->esi, r->edi);
  649. if ((current_process->syscall_registers == r) ||
  650. (location != (uintptr_t)&fork && location != (uintptr_t)&clone)) {
  651. r->eax = ret;
  652. }
  653. }
  654. void syscalls_install(void) {
  655. debug_print(NOTICE, "Initializing syscall table with %d functions", num_syscalls);
  656. isrs_install_handler(0x7F, &syscall_handler);
  657. }