diff options
Diffstat (limited to 'mdk-stage1/insmod-modutils/util/sys_cm.c')
-rw-r--r-- | mdk-stage1/insmod-modutils/util/sys_cm.c | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/mdk-stage1/insmod-modutils/util/sys_cm.c b/mdk-stage1/insmod-modutils/util/sys_cm.c new file mode 100644 index 000000000..851fb709e --- /dev/null +++ b/mdk-stage1/insmod-modutils/util/sys_cm.c @@ -0,0 +1,88 @@ +/* Functions for the Linux module syscall interface. + Copyright 1996, 1997 Linux International. + Contributed by Richard Henderson <rth@tamu.edu> + + This file is part of the Linux modutils. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ident "$Id$" + +#include <stdlib.h> +#include <errno.h> + +#include "module.h" + +/* Kernel headers before 2.1.mumble need this on the Alpha to get + _syscall* defined. */ +#define __LIBRARY__ + +#include <asm/unistd.h> + + +/*======================================================================*/ + +#if defined(__i386__) || defined(__m68k__) || defined(__arm__) + +#define __NR__create_module __NR_create_module +static inline _syscall2(long, _create_module, const char *, name, size_t, size) + +unsigned long create_module(const char *name, size_t size) +{ + /* Why all this fuss? + + In linux 2.1, the address returned by create module point in + kernel space which is now mapped at the top of user space (at + 0xc0000000 on i386). This looks like a negative number for a + long. The normal syscall macro of linux 2.0 (and all libc compile + with linux 2.0 or below) consider that the return value is a + negative number and consider it is an error number (A kernel + convention, return value are positive or negative, indicating the + error number). + + By checking the value of errno, we know if we have been fooled by + the syscall2 macro and we fix it. */ + + long ret = _create_module(name, size); + if (ret == -1 && errno > 125) + { + ret = -errno; + errno = 0; + } + return ret; +} + +#elif defined(__alpha__) + +/* Alpha doesn't have the same problem, exactly, but a bug in older + kernels fails to clear the error flag. Clear it here explicitly. */ + +#define __NR__create_module __NR_create_module +static inline _syscall4(unsigned long, _create_module, const char *, name, + size_t, size, size_t, dummy, size_t, err); + +unsigned long create_module(const char *name, size_t size) +{ + return _create_module(name, size, 0, 0); +} + +#else + +/* Sparc, MIPS, (and Alpha, but that's another problem) don't mistake + return values for errors due to the nature of the system call. */ + +_syscall2(unsigned long, create_module, const char *, name, size_t, size) + +#endif |