Main Page   Modules   Alphabetical List   Data Structures   File List   Data Fields   Globals   Related Pages  

syscall.c

Go to the documentation of this file.
00001 /*!     \file kernel/syscall.c
00002  *      \brief System Calls.
00003  *      \author Andrea Righi <drizzt@inwind.it>
00004  *      \date Last update: 2004-01-03
00005  *      \note Copyright (&copy;) 2003 Andrea Righi
00006  */
00007 
00008 #include <const.h>
00009 
00010 #include <arch/i386.h>
00011 #include <arch/mem.h>
00012 
00013 #include <kernel/console.h>
00014 #include <kernel/keyboard.h>
00015 #include <kernel/kernel.h>
00016 #include <kernel/speaker.h>
00017 #include <kernel/task.h>
00018 #include <kernel/umalloc.h>
00019 
00020 #include <kernel/syscall.h>
00021 
00022 //! Total amount of system calls.
00023 #define SYS_CALL_NR     ( sizeof(syscall_table)/sizeof(dword) )
00024 
00025 //! System call entry.
00026 typedef struct syscall_t
00027 {
00028         //! The address of the procedure.
00029         addr_t address;
00030         //! How many arguments are passed to the procedure.
00031         addr_t paramcnt;
00032 } syscall_t;
00033 
00034 //! This is the array of the known system calls.
00035 static syscall_t syscall_table[] = {
00036 // ID           Routine Address         # of parameters
00037 /* 0 */ {       (size_t)&auto_kill,     1               },
00038 /* 1 */ {       (size_t)&kgetchar,      0               },
00039 /* 2 */ {       (size_t)&kputchar,      1               },
00040 /* 3 */ {       (size_t)&keyb_read,     0               },
00041 /* 4 */ {       (size_t)&umalloc,       1               },
00042 /* 5 */ {       (size_t)&ufree,         1               },
00043 };
00044 
00045 /*! \ingroup Handlers */
00046 //! \brief
00047 //!     This procedure execute every system call invoked by INT 0x80.
00048 //! \param eax
00049 //!     The EAX register of the calling procedure must contains the
00050 //!     syscall id. At the end of the syscall it contains the
00051 //!     returned value.
00052 //! \param ebp
00053 //!     The EBP register of the calling procedure. It must point
00054 //!     to the stack pointer of the calling procedure.
00055 //!
00056 /*!     Copy the stack parameters from the stack pointer of the
00057  *      calling procedure (pointed by \p ebp) to the current stack
00058  *      pointer. Then the opportune syscall is invoked.
00059  */
00060 void syscall_handler(dword *eax, dword *ebp)
00061 {
00062         // Function pointer.
00063         size_t (*p)() = (void *)syscall_table[*eax].address;
00064         // How many parameters.
00065         int paramcnt = syscall_table[*eax].paramcnt;
00066         // Start of parameters'address.
00067         size_t *args = (size_t *)(*ebp);
00068 
00069         register int i;
00070 
00071         // Check if the system call id does not exceed the syscall table.
00072         // NOTE: sycall id is 0-based!!!
00073         if ( *eax < SYS_CALL_NR )
00074         {
00075                 // Pass the parameters to the system call routine.
00076                 for( i=paramcnt; i; --i)
00077                         __asm__ __volatile__ ("pushl %0" : : "r"(*(args+i-1)));
00078                 // Execute the system call.
00079                 // The result will be returned into the task's eax register.
00080                 *eax = (*p)();
00081                 // Pop elements out of the stack.
00082                 __asm__ __volatile__ ("add %0, %%esp" : : "r"(paramcnt*sizeof(size_t)));
00083         }
00084         else
00085         {
00086                 // Invalid syscall id! => kill the task.
00087                 kprintf("\n\rsyscall: %u", *eax);
00088                 error("Invalid system call");
00089         }
00090 }

Generated on Fri Feb 20 15:32:16 2004 for Minirighi by doxygen1.2.18