OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [rc203soc/] [sw/] [uClinux/] [kernel/] [module.c] - Diff between revs 1634 and 1765

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 1634 Rev 1765
#include <linux/errno.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <asm/segment.h>
#include <asm/segment.h>
#include <linux/mm.h>           /* defines GFP_KERNEL */
#include <linux/mm.h>           /* defines GFP_KERNEL */
#include <linux/string.h>
#include <linux/string.h>
#include <linux/module.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/malloc.h>
#include <linux/malloc.h>
#include <linux/config.h>
#include <linux/config.h>
#include <asm/pgtable.h>
#include <asm/pgtable.h>
/*
/*
 * Originally by Anonymous (as far as I know...)
 * Originally by Anonymous (as far as I know...)
 * Linux version by Bas Laarhoven <bas@vimec.nl>
 * Linux version by Bas Laarhoven <bas@vimec.nl>
 * 0.99.14 version by Jon Tombs <jon@gtex02.us.es>,
 * 0.99.14 version by Jon Tombs <jon@gtex02.us.es>,
 *
 *
 * Heavily modified by Bjorn Ekwall <bj0rn@blox.se> May 1994 (C)
 * Heavily modified by Bjorn Ekwall <bj0rn@blox.se> May 1994 (C)
 * This source is covered by the GNU GPL, the same as all kernel sources.
 * This source is covered by the GNU GPL, the same as all kernel sources.
 *
 *
 * Features:
 * Features:
 *      - Supports stacked modules (removable only of there are no dependents).
 *      - Supports stacked modules (removable only of there are no dependents).
 *      - Supports table of symbols defined by the modules.
 *      - Supports table of symbols defined by the modules.
 *      - Supports /proc/ksyms, showing value, name and owner of all
 *      - Supports /proc/ksyms, showing value, name and owner of all
 *        the symbols defined by all modules (in stack order).
 *        the symbols defined by all modules (in stack order).
 *      - Added module dependencies information into /proc/modules
 *      - Added module dependencies information into /proc/modules
 *      - Supports redefines of all symbols, for streams-like behaviour.
 *      - Supports redefines of all symbols, for streams-like behaviour.
 *      - Compatible with older versions of insmod.
 *      - Compatible with older versions of insmod.
 *
 *
 * New addition in December 1994: (Bjorn Ekwall, idea from Jacques Gelinas)
 * New addition in December 1994: (Bjorn Ekwall, idea from Jacques Gelinas)
 *      - Externally callable function:
 *      - Externally callable function:
 *
 *
 *              "int register_symtab(struct symbol_table *)"
 *              "int register_symtab(struct symbol_table *)"
 *
 *
 *        This function can be called from within the kernel,
 *        This function can be called from within the kernel,
 *        and ALSO from loadable modules.
 *        and ALSO from loadable modules.
 *        The goal is to assist in modularizing the kernel even more,
 *        The goal is to assist in modularizing the kernel even more,
 *        and finally: reducing the number of entries in ksyms.c
 *        and finally: reducing the number of entries in ksyms.c
 *        since every subsystem should now be able to decide and
 *        since every subsystem should now be able to decide and
 *        control exactly what symbols it wants to export, locally!
 *        control exactly what symbols it wants to export, locally!
 *
 *
 * On 1-Aug-95:  <Matti.Aarnio@utu.fi>  altered code to use same style as
 * On 1-Aug-95:  <Matti.Aarnio@utu.fi>  altered code to use same style as
 *               do  /proc/net/XXX  "files".  Namely allow more than 4kB
 *               do  /proc/net/XXX  "files".  Namely allow more than 4kB
 *               (or what the block size is) output.
 *               (or what the block size is) output.
 *
 *
 *      - Use dummy syscall functions for users who disable all
 *      - Use dummy syscall functions for users who disable all
 *        module support. Similar to kernel/sys.c (Paul Gortmaker)
 *        module support. Similar to kernel/sys.c (Paul Gortmaker)
 */
 */
 
 
#ifdef CONFIG_MODULES           /* a *big* #ifdef block... */
#ifdef CONFIG_MODULES           /* a *big* #ifdef block... */
 
 
static struct module kernel_module;
static struct module kernel_module;
static struct module *module_list = &kernel_module;
static struct module *module_list = &kernel_module;
 
 
static int freeing_modules; /* true if some modules are marked for deletion */
static int freeing_modules; /* true if some modules are marked for deletion */
 
 
static struct module *find_module( const char *name);
static struct module *find_module( const char *name);
static int get_mod_name( char *user_name, char *buf);
static int get_mod_name( char *user_name, char *buf);
static int free_modules( void);
static int free_modules( void);
 
 
extern struct symbol_table symbol_table; /* in kernel/ksyms.c */
extern struct symbol_table symbol_table; /* in kernel/ksyms.c */
 
 
/*
/*
 * Called at boot time
 * Called at boot time
 */
 */
void init_modules(void) {
void init_modules(void) {
        struct internal_symbol *sym;
        struct internal_symbol *sym;
        int i;
        int i;
 
 
        for (i = 0, sym = symbol_table.symbol; sym->name; ++sym, ++i)
        for (i = 0, sym = symbol_table.symbol; sym->name; ++sym, ++i)
                ;
                ;
        symbol_table.n_symbols = i;
        symbol_table.n_symbols = i;
 
 
        kernel_module.symtab = &symbol_table;
        kernel_module.symtab = &symbol_table;
        kernel_module.state = MOD_RUNNING; /* Hah! */
        kernel_module.state = MOD_RUNNING; /* Hah! */
        kernel_module.name = "";
        kernel_module.name = "";
}
}
 
 
/*
/*
 * Allocate space for a module.
 * Allocate space for a module.
 */
 */
asmlinkage unsigned long
asmlinkage unsigned long
sys_create_module(char *module_name, unsigned long size)
sys_create_module(char *module_name, unsigned long size)
{
{
        struct module *mp;
        struct module *mp;
        void* addr;
        void* addr;
        int error;
        int error;
        int npages;
        int npages;
        int sspace = sizeof(struct module) + MOD_MAX_NAME;
        int sspace = sizeof(struct module) + MOD_MAX_NAME;
        char name[MOD_MAX_NAME];
        char name[MOD_MAX_NAME];
 
 
        if (!suser() || securelevel > 0)
        if (!suser() || securelevel > 0)
                return -EPERM;
                return -EPERM;
        if (module_name == NULL || size == 0)
        if (module_name == NULL || size == 0)
                return -EINVAL;
                return -EINVAL;
        if ((error = get_mod_name(module_name, name)) != 0)
        if ((error = get_mod_name(module_name, name)) != 0)
                return error;
                return error;
        if (find_module(name) != NULL) {
        if (find_module(name) != NULL) {
                return -EEXIST;
                return -EEXIST;
        }
        }
 
 
        if ((mp = (struct module*) kmalloc(sspace, GFP_KERNEL)) == NULL) {
        if ((mp = (struct module*) kmalloc(sspace, GFP_KERNEL)) == NULL) {
                return -ENOMEM;
                return -ENOMEM;
        }
        }
        strcpy((char *)(mp + 1), name); /* why not? */
        strcpy((char *)(mp + 1), name); /* why not? */
 
 
        npages = (size + sizeof (long) + PAGE_SIZE - 1) / PAGE_SIZE;
        npages = (size + sizeof (long) + PAGE_SIZE - 1) / PAGE_SIZE;
        if ((addr = vmalloc(npages * PAGE_SIZE)) == 0) {
        if ((addr = vmalloc(npages * PAGE_SIZE)) == 0) {
                kfree_s(mp, sspace);
                kfree_s(mp, sspace);
                return -ENOMEM;
                return -ENOMEM;
        }
        }
 
 
        mp->next = module_list;
        mp->next = module_list;
        mp->ref = NULL;
        mp->ref = NULL;
        mp->symtab = NULL;
        mp->symtab = NULL;
        mp->name = (char *)(mp + 1);
        mp->name = (char *)(mp + 1);
        mp->size = npages;
        mp->size = npages;
        mp->addr = addr;
        mp->addr = addr;
        mp->state = MOD_UNINITIALIZED;
        mp->state = MOD_UNINITIALIZED;
        mp->cleanup = NULL;
        mp->cleanup = NULL;
 
 
        * (long *) addr = 0;     /* set use count to zero */
        * (long *) addr = 0;     /* set use count to zero */
        module_list = mp;       /* link it in */
        module_list = mp;       /* link it in */
 
 
        pr_debug("module `%s' (%lu pages @ 0x%08lx) created\n",
        pr_debug("module `%s' (%lu pages @ 0x%08lx) created\n",
                mp->name, (unsigned long) mp->size, (unsigned long) mp->addr);
                mp->name, (unsigned long) mp->size, (unsigned long) mp->addr);
        return (unsigned long) addr;
        return (unsigned long) addr;
}
}
 
 
/*
/*
 * Initialize a module.
 * Initialize a module.
 */
 */
asmlinkage int
asmlinkage int
sys_init_module(char *module_name, char *code, unsigned codesize,
sys_init_module(char *module_name, char *code, unsigned codesize,
                struct mod_routines *routines,
                struct mod_routines *routines,
                struct symbol_table *symtab)
                struct symbol_table *symtab)
{
{
        struct module *mp;
        struct module *mp;
        struct symbol_table *newtab;
        struct symbol_table *newtab;
        char name[MOD_MAX_NAME];
        char name[MOD_MAX_NAME];
        int error;
        int error;
        struct mod_routines rt;
        struct mod_routines rt;
 
 
        if (!suser() || securelevel > 0)
        if (!suser() || securelevel > 0)
                return -EPERM;
                return -EPERM;
 
 
#ifdef __i386__
#ifdef __i386__
        /* A little bit of protection... we "know" where the user stack is... */
        /* A little bit of protection... we "know" where the user stack is... */
 
 
        if (symtab && ((unsigned long)symtab > 0xb0000000)) {
        if (symtab && ((unsigned long)symtab > 0xb0000000)) {
                printk(KERN_WARNING "warning: you are using an old insmod, no symbols will be inserted!\n");
                printk(KERN_WARNING "warning: you are using an old insmod, no symbols will be inserted!\n");
                symtab = NULL;
                symtab = NULL;
        }
        }
#endif
#endif
        if ((error = get_mod_name(module_name, name)) != 0)
        if ((error = get_mod_name(module_name, name)) != 0)
                return error;
                return error;
        pr_debug("initializing module `%s', %d (0x%x) bytes\n",
        pr_debug("initializing module `%s', %d (0x%x) bytes\n",
                name, codesize, codesize);
                name, codesize, codesize);
        memcpy_fromfs(&rt, routines, sizeof rt);
        memcpy_fromfs(&rt, routines, sizeof rt);
        if ((mp = find_module(name)) == NULL)
        if ((mp = find_module(name)) == NULL)
                return -ENOENT;
                return -ENOENT;
        if (codesize & MOD_AUTOCLEAN) {
        if (codesize & MOD_AUTOCLEAN) {
                /*
                /*
                 * set autoclean marker from codesize...
                 * set autoclean marker from codesize...
                 * set usage count to "zero"
                 * set usage count to "zero"
                 */
                 */
                codesize &= ~MOD_AUTOCLEAN;
                codesize &= ~MOD_AUTOCLEAN;
                GET_USE_COUNT(mp) = MOD_AUTOCLEAN;
                GET_USE_COUNT(mp) = MOD_AUTOCLEAN;
        }
        }
        if ((codesize + sizeof (long) + PAGE_SIZE - 1) / PAGE_SIZE > mp->size)
        if ((codesize + sizeof (long) + PAGE_SIZE - 1) / PAGE_SIZE > mp->size)
                return -EINVAL;
                return -EINVAL;
        memcpy_fromfs((char *)mp->addr + sizeof (long), code, codesize);
        memcpy_fromfs((char *)mp->addr + sizeof (long), code, codesize);
        memset((char *)mp->addr + sizeof (long) + codesize, 0,
        memset((char *)mp->addr + sizeof (long) + codesize, 0,
                mp->size * PAGE_SIZE - (codesize + sizeof (long)));
                mp->size * PAGE_SIZE - (codesize + sizeof (long)));
        pr_debug("module init entry = 0x%08lx, cleanup entry = 0x%08lx\n",
        pr_debug("module init entry = 0x%08lx, cleanup entry = 0x%08lx\n",
                (unsigned long) rt.init, (unsigned long) rt.cleanup);
                (unsigned long) rt.init, (unsigned long) rt.cleanup);
        mp->cleanup = rt.cleanup;
        mp->cleanup = rt.cleanup;
 
 
        /* update kernel symbol table */
        /* update kernel symbol table */
        if (symtab) { /* symtab == NULL means no new entries to handle */
        if (symtab) { /* symtab == NULL means no new entries to handle */
                struct internal_symbol *sym;
                struct internal_symbol *sym;
                struct module_ref *ref;
                struct module_ref *ref;
                int size;
                int size;
                int i;
                int i;
                int legal_start;
                int legal_start;
 
 
                if ((error = verify_area(VERIFY_READ, &symtab->size, sizeof(symtab->size))))
                if ((error = verify_area(VERIFY_READ, &symtab->size, sizeof(symtab->size))))
                        return error;
                        return error;
                size = get_user(&symtab->size);
                size = get_user(&symtab->size);
 
 
                if ((newtab = (struct symbol_table*) kmalloc(size, GFP_KERNEL)) == NULL) {
                if ((newtab = (struct symbol_table*) kmalloc(size, GFP_KERNEL)) == NULL) {
                        return -ENOMEM;
                        return -ENOMEM;
                }
                }
 
 
                if ((error = verify_area(VERIFY_READ, symtab, size))) {
                if ((error = verify_area(VERIFY_READ, symtab, size))) {
                        kfree_s(newtab, size);
                        kfree_s(newtab, size);
                        return error;
                        return error;
                }
                }
                memcpy_fromfs((char *)(newtab), symtab, size);
                memcpy_fromfs((char *)(newtab), symtab, size);
 
 
                /* sanity check */
                /* sanity check */
                legal_start = sizeof(struct symbol_table) +
                legal_start = sizeof(struct symbol_table) +
                        newtab->n_symbols * sizeof(struct internal_symbol) +
                        newtab->n_symbols * sizeof(struct internal_symbol) +
                        newtab->n_refs * sizeof(struct module_ref);
                        newtab->n_refs * sizeof(struct module_ref);
 
 
                if ((newtab->n_symbols < 0) || (newtab->n_refs < 0) || (legal_start > size)) {
                if ((newtab->n_symbols < 0) || (newtab->n_refs < 0) || (legal_start > size)) {
                        printk(KERN_WARNING "Rejecting illegal symbol table (n_symbols=%d,n_refs=%d)\n",
                        printk(KERN_WARNING "Rejecting illegal symbol table (n_symbols=%d,n_refs=%d)\n",
                               newtab->n_symbols, newtab->n_refs);
                               newtab->n_symbols, newtab->n_refs);
                        kfree_s(newtab, size);
                        kfree_s(newtab, size);
                        return -EINVAL;
                        return -EINVAL;
                }
                }
 
 
                /* relocate name pointers, index referred from start of table */
                /* relocate name pointers, index referred from start of table */
                for (sym = &(newtab->symbol[0]), i = 0; i < newtab->n_symbols; ++sym, ++i) {
                for (sym = &(newtab->symbol[0]), i = 0; i < newtab->n_symbols; ++sym, ++i) {
                        if ((unsigned long)sym->name < legal_start || size <= (unsigned long)sym->name) {
                        if ((unsigned long)sym->name < legal_start || size <= (unsigned long)sym->name) {
                                printk(KERN_WARNING "Rejecting illegal symbol table\n");
                                printk(KERN_WARNING "Rejecting illegal symbol table\n");
                                kfree_s(newtab, size);
                                kfree_s(newtab, size);
                                return -EINVAL;
                                return -EINVAL;
                        }
                        }
                        /* else */
                        /* else */
                        sym->name += (long)newtab;
                        sym->name += (long)newtab;
                }
                }
                mp->symtab = newtab;
                mp->symtab = newtab;
 
 
                /* Update module references.
                /* Update module references.
                 * On entry, from "insmod", ref->module points to
                 * On entry, from "insmod", ref->module points to
                 * the referenced module!
                 * the referenced module!
                 * Now it will point to the current module instead!
                 * Now it will point to the current module instead!
                 * The ref structure becomes the first link in the linked
                 * The ref structure becomes the first link in the linked
                 * list of references to the referenced module.
                 * list of references to the referenced module.
                 * Also, "sym" from above, points to the first ref entry!!!
                 * Also, "sym" from above, points to the first ref entry!!!
                 */
                 */
                for (ref = (struct module_ref *)sym, i = 0;
                for (ref = (struct module_ref *)sym, i = 0;
                        i < newtab->n_refs; ++ref, ++i) {
                        i < newtab->n_refs; ++ref, ++i) {
 
 
                        /* Check for valid reference */
                        /* Check for valid reference */
                        struct module *link = module_list;
                        struct module *link = module_list;
                        while (link && (ref->module != link))
                        while (link && (ref->module != link))
                                link = link->next;
                                link = link->next;
 
 
                        if (link == (struct module *)0) {
                        if (link == (struct module *)0) {
                                printk(KERN_WARNING "Non-module reference! Rejected!\n");
                                printk(KERN_WARNING "Non-module reference! Rejected!\n");
                                return -EINVAL;
                                return -EINVAL;
                        }
                        }
 
 
                        ref->next = ref->module->ref;
                        ref->next = ref->module->ref;
                        ref->module->ref = ref;
                        ref->module->ref = ref;
                        ref->module = mp;
                        ref->module = mp;
                }
                }
        }
        }
 
 
        flush_pages_to_ram((unsigned long)mp->addr,
        flush_pages_to_ram((unsigned long)mp->addr,
                           (codesize+sizeof(long)+PAGE_SIZE-1)/PAGE_SIZE);
                           (codesize+sizeof(long)+PAGE_SIZE-1)/PAGE_SIZE);
 
 
        GET_USE_COUNT(mp) += 1;
        GET_USE_COUNT(mp) += 1;
        if ((*rt.init)() != 0) {
        if ((*rt.init)() != 0) {
                GET_USE_COUNT(mp) = 0;
                GET_USE_COUNT(mp) = 0;
                return -EBUSY;
                return -EBUSY;
        }
        }
        GET_USE_COUNT(mp) -= 1;
        GET_USE_COUNT(mp) -= 1;
        mp->state = MOD_RUNNING;
        mp->state = MOD_RUNNING;
 
 
        return 0;
        return 0;
}
}
 
 
asmlinkage int
asmlinkage int
sys_delete_module(char *module_name)
sys_delete_module(char *module_name)
{
{
        struct module *mp;
        struct module *mp;
        char name[MOD_MAX_NAME];
        char name[MOD_MAX_NAME];
        int error;
        int error;
 
 
        if (!suser() || securelevel > 0)
        if (!suser() || securelevel > 0)
                return -EPERM;
                return -EPERM;
        /* else */
        /* else */
        if (module_name != NULL) {
        if (module_name != NULL) {
                if ((error = get_mod_name(module_name, name)) != 0)
                if ((error = get_mod_name(module_name, name)) != 0)
                        return error;
                        return error;
                if ((mp = find_module(name)) == NULL)
                if ((mp = find_module(name)) == NULL)
                        return -ENOENT;
                        return -ENOENT;
                if ((mp->ref != NULL) ||
                if ((mp->ref != NULL) ||
                    ((GET_USE_COUNT(mp) & ~(MOD_AUTOCLEAN | MOD_VISITED)) != 0))
                    ((GET_USE_COUNT(mp) & ~(MOD_AUTOCLEAN | MOD_VISITED)) != 0))
                        return -EBUSY;
                        return -EBUSY;
                GET_USE_COUNT(mp) &= ~(MOD_AUTOCLEAN | MOD_VISITED);
                GET_USE_COUNT(mp) &= ~(MOD_AUTOCLEAN | MOD_VISITED);
                if (mp->state == MOD_RUNNING)
                if (mp->state == MOD_RUNNING)
                        (*mp->cleanup)();
                        (*mp->cleanup)();
                mp->state = MOD_DELETED;
                mp->state = MOD_DELETED;
                free_modules();
                free_modules();
        }
        }
        /* for automatic reaping */
        /* for automatic reaping */
        else {
        else {
                struct module *mp_next;
                struct module *mp_next;
                for (mp = module_list; mp != &kernel_module; mp = mp_next) {
                for (mp = module_list; mp != &kernel_module; mp = mp_next) {
                        mp_next = mp->next;
                        mp_next = mp->next;
                        if ((mp->ref == NULL) && (mp->state == MOD_RUNNING) &&
                        if ((mp->ref == NULL) && (mp->state == MOD_RUNNING) &&
                            ((GET_USE_COUNT(mp) & ~MOD_VISITED) == MOD_AUTOCLEAN)) {
                            ((GET_USE_COUNT(mp) & ~MOD_VISITED) == MOD_AUTOCLEAN)) {
                                if ((GET_USE_COUNT(mp) & MOD_VISITED)) {
                                if ((GET_USE_COUNT(mp) & MOD_VISITED)) {
                                        /* Don't reap until one "cycle" after last _use_ */
                                        /* Don't reap until one "cycle" after last _use_ */
                                        GET_USE_COUNT(mp) &= ~MOD_VISITED;
                                        GET_USE_COUNT(mp) &= ~MOD_VISITED;
                                }
                                }
                                else {
                                else {
                                        GET_USE_COUNT(mp) &= ~(MOD_AUTOCLEAN | MOD_VISITED);
                                        GET_USE_COUNT(mp) &= ~(MOD_AUTOCLEAN | MOD_VISITED);
                                        (*mp->cleanup)();
                                        (*mp->cleanup)();
                                        mp->state = MOD_DELETED;
                                        mp->state = MOD_DELETED;
                                        free_modules();
                                        free_modules();
                                }
                                }
                        }
                        }
                }
                }
        }
        }
        return 0;
        return 0;
}
}
 
 
 
 
/*
/*
 * Copy the kernel symbol table to user space.  If the argument is null,
 * Copy the kernel symbol table to user space.  If the argument is null,
 * just return the size of the table.
 * just return the size of the table.
 *
 *
 * Note that the transient module symbols are copied _first_,
 * Note that the transient module symbols are copied _first_,
 * in lifo order!!!
 * in lifo order!!!
 *
 *
 * The symbols to "insmod" are according to the "old" format: struct kernel_sym,
 * The symbols to "insmod" are according to the "old" format: struct kernel_sym,
 * which is actually quite handy for this purpose.
 * which is actually quite handy for this purpose.
 * Note that insmod inserts a struct symbol_table later on...
 * Note that insmod inserts a struct symbol_table later on...
 * (as that format is quite handy for the kernel...)
 * (as that format is quite handy for the kernel...)
 *
 *
 * For every module, the first (pseudo)symbol copied is the module name
 * For every module, the first (pseudo)symbol copied is the module name
 * and the address of the module struct.
 * and the address of the module struct.
 * This lets "insmod" keep track of references, and build the array of
 * This lets "insmod" keep track of references, and build the array of
 * struct module_refs in the symbol table.
 * struct module_refs in the symbol table.
 * The format of the module name is "#module", so that "insmod" can easily
 * The format of the module name is "#module", so that "insmod" can easily
 * notice when a module name comes along. Also, this will make it possible
 * notice when a module name comes along. Also, this will make it possible
 * to use old versions of "insmod", albeit with reduced functionality...
 * to use old versions of "insmod", albeit with reduced functionality...
 * The "kernel" module has an empty name.
 * The "kernel" module has an empty name.
 */
 */
asmlinkage int
asmlinkage int
sys_get_kernel_syms(struct kernel_sym *table)
sys_get_kernel_syms(struct kernel_sym *table)
{
{
        struct internal_symbol *from;
        struct internal_symbol *from;
        struct kernel_sym isym;
        struct kernel_sym isym;
        struct kernel_sym *to;
        struct kernel_sym *to;
        struct module *mp = module_list;
        struct module *mp = module_list;
        int i;
        int i;
        int nmodsyms = 0;
        int nmodsyms = 0;
 
 
        for (mp = module_list; mp; mp = mp->next) {
        for (mp = module_list; mp; mp = mp->next) {
                if (mp->symtab && mp->symtab->n_symbols) {
                if (mp->symtab && mp->symtab->n_symbols) {
                        /* include the count for the module name! */
                        /* include the count for the module name! */
                        nmodsyms += mp->symtab->n_symbols + 1;
                        nmodsyms += mp->symtab->n_symbols + 1;
                }
                }
                else
                else
                        /* include the count for the module name! */
                        /* include the count for the module name! */
                        nmodsyms += 1; /* return modules without symbols too */
                        nmodsyms += 1; /* return modules without symbols too */
        }
        }
 
 
        if (table != NULL) {
        if (table != NULL) {
                to = table;
                to = table;
 
 
                if ((i = verify_area(VERIFY_WRITE, to, nmodsyms * sizeof(*table))))
                if ((i = verify_area(VERIFY_WRITE, to, nmodsyms * sizeof(*table))))
                        return i;
                        return i;
 
 
                /* copy all module symbols first (always LIFO order) */
                /* copy all module symbols first (always LIFO order) */
                for (mp = module_list; mp; mp = mp->next) {
                for (mp = module_list; mp; mp = mp->next) {
                        if (mp->state == MOD_RUNNING) {
                        if (mp->state == MOD_RUNNING) {
                                /* magic: write module info as a pseudo symbol */
                                /* magic: write module info as a pseudo symbol */
                                isym.value = (unsigned long)mp;
                                isym.value = (unsigned long)mp;
                                sprintf(isym.name, "#%s", mp->name);
                                sprintf(isym.name, "#%s", mp->name);
                                memcpy_tofs(to, &isym, sizeof isym);
                                memcpy_tofs(to, &isym, sizeof isym);
                                ++to;
                                ++to;
 
 
                                if (mp->symtab != NULL) {
                                if (mp->symtab != NULL) {
                                        for (i = mp->symtab->n_symbols,
                                        for (i = mp->symtab->n_symbols,
                                                from = mp->symtab->symbol;
                                                from = mp->symtab->symbol;
                                                i > 0; --i, ++from, ++to) {
                                                i > 0; --i, ++from, ++to) {
 
 
                                                isym.value = (unsigned long)from->addr;
                                                isym.value = (unsigned long)from->addr;
                                                strncpy(isym.name, from->name, sizeof isym.name);
                                                strncpy(isym.name, from->name, sizeof isym.name);
                                                memcpy_tofs(to, &isym, sizeof isym);
                                                memcpy_tofs(to, &isym, sizeof isym);
                                        }
                                        }
                                }
                                }
                        }
                        }
                }
                }
        }
        }
 
 
        return nmodsyms;
        return nmodsyms;
}
}
 
 
 
 
/*
/*
 * Copy the name of a module from user space.
 * Copy the name of a module from user space.
 */
 */
int
int
get_mod_name(char *user_name, char *buf)
get_mod_name(char *user_name, char *buf)
{
{
        int i;
        int i;
 
 
        i = 0;
        i = 0;
        for (i = 0 ; (buf[i] = get_user(user_name + i)) != '\0' ; ) {
        for (i = 0 ; (buf[i] = get_user(user_name + i)) != '\0' ; ) {
                if (++i >= MOD_MAX_NAME)
                if (++i >= MOD_MAX_NAME)
                        return -E2BIG;
                        return -E2BIG;
        }
        }
        return 0;
        return 0;
}
}
 
 
 
 
/*
/*
 * Look for a module by name, ignoring modules marked for deletion.
 * Look for a module by name, ignoring modules marked for deletion.
 */
 */
struct module *
struct module *
find_module( const char *name)
find_module( const char *name)
{
{
        struct module *mp;
        struct module *mp;
 
 
        for (mp = module_list ; mp ; mp = mp->next) {
        for (mp = module_list ; mp ; mp = mp->next) {
                if (mp->state == MOD_DELETED)
                if (mp->state == MOD_DELETED)
                        continue;
                        continue;
                if (!strcmp(mp->name, name))
                if (!strcmp(mp->name, name))
                        break;
                        break;
        }
        }
        return mp;
        return mp;
}
}
 
 
static void
static void
drop_refs(struct module *mp)
drop_refs(struct module *mp)
{
{
        struct module *step;
        struct module *step;
        struct module_ref *prev;
        struct module_ref *prev;
        struct module_ref *ref;
        struct module_ref *ref;
 
 
        for (step = module_list; step; step = step->next) {
        for (step = module_list; step; step = step->next) {
                for (prev = ref = step->ref; ref; ref = prev->next) {
                for (prev = ref = step->ref; ref; ref = prev->next) {
                        if (ref->module == mp) {
                        if (ref->module == mp) {
                                if (ref == step->ref)
                                if (ref == step->ref)
                                        step->ref = ref->next;
                                        step->ref = ref->next;
                                else
                                else
                                        prev->next = ref->next;
                                        prev->next = ref->next;
                                break; /* every module only references once! */
                                break; /* every module only references once! */
                        }
                        }
                        else
                        else
                                prev = ref;
                                prev = ref;
                }
                }
        }
        }
}
}
 
 
/*
/*
 * Try to free modules which have been marked for deletion.  Returns nonzero
 * Try to free modules which have been marked for deletion.  Returns nonzero
 * if a module was actually freed.
 * if a module was actually freed.
 */
 */
int
int
free_modules( void)
free_modules( void)
{
{
        struct module *mp;
        struct module *mp;
        struct module **mpp;
        struct module **mpp;
        int did_deletion;
        int did_deletion;
 
 
        did_deletion = 0;
        did_deletion = 0;
        freeing_modules = 0;
        freeing_modules = 0;
        mpp = &module_list;
        mpp = &module_list;
        while ((mp = *mpp) != NULL) {
        while ((mp = *mpp) != NULL) {
                if (mp->state != MOD_DELETED) {
                if (mp->state != MOD_DELETED) {
                        mpp = &mp->next;
                        mpp = &mp->next;
                } else {
                } else {
                        if ((GET_USE_COUNT(mp) != 0) || (mp->ref != NULL)) {
                        if ((GET_USE_COUNT(mp) != 0) || (mp->ref != NULL)) {
                                freeing_modules = 1;
                                freeing_modules = 1;
                                mpp = &mp->next;
                                mpp = &mp->next;
                        } else {        /* delete it */
                        } else {        /* delete it */
                                *mpp = mp->next;
                                *mpp = mp->next;
                                if (mp->symtab) {
                                if (mp->symtab) {
                                        if (mp->symtab->n_refs)
                                        if (mp->symtab->n_refs)
                                                drop_refs(mp);
                                                drop_refs(mp);
                                        if (mp->symtab->size)
                                        if (mp->symtab->size)
                                                kfree_s(mp->symtab, mp->symtab->size);
                                                kfree_s(mp->symtab, mp->symtab->size);
                                }
                                }
                                vfree(mp->addr);
                                vfree(mp->addr);
                                kfree_s(mp, sizeof(struct module) + MOD_MAX_NAME);
                                kfree_s(mp, sizeof(struct module) + MOD_MAX_NAME);
                                did_deletion = 1;
                                did_deletion = 1;
                        }
                        }
                }
                }
        }
        }
        return did_deletion;
        return did_deletion;
}
}
 
 
 
 
/*
/*
 * Called by the /proc file system to return a current list of modules.
 * Called by the /proc file system to return a current list of modules.
 */
 */
int get_module_list(char *buf)
int get_module_list(char *buf)
{
{
        char *p;
        char *p;
        const char *q;
        const char *q;
        int i;
        int i;
        struct module *mp;
        struct module *mp;
        struct module_ref *ref;
        struct module_ref *ref;
        char size[32];
        char size[32];
 
 
        p = buf;
        p = buf;
        /* Do not show the kernel pseudo module */
        /* Do not show the kernel pseudo module */
        for (mp = module_list ; mp && mp->next; mp = mp->next) {
        for (mp = module_list ; mp && mp->next; mp = mp->next) {
                if (p - buf > 4096 - 100)
                if (p - buf > 4096 - 100)
                        break;                  /* avoid overflowing buffer */
                        break;                  /* avoid overflowing buffer */
                q = mp->name;
                q = mp->name;
                if (*q == '\0' && mp->size == 0 && mp->ref == NULL)
                if (*q == '\0' && mp->size == 0 && mp->ref == NULL)
                        continue; /* don't list modules for kernel syms */
                        continue; /* don't list modules for kernel syms */
                i = 20;
                i = 20;
                while (*q) {
                while (*q) {
                        *p++ = *q++;
                        *p++ = *q++;
                        i--;
                        i--;
                }
                }
                sprintf(size, "%d", mp->size);
                sprintf(size, "%d", mp->size);
                i -= strlen(size);
                i -= strlen(size);
                if (i <= 0)
                if (i <= 0)
                        i = 1;
                        i = 1;
                while (--i >= 0)
                while (--i >= 0)
                        *p++ = ' ';
                        *p++ = ' ';
                q = size;
                q = size;
                while (*q)
                while (*q)
                        *p++ = *q++;
                        *p++ = *q++;
                if (mp->state == MOD_UNINITIALIZED)
                if (mp->state == MOD_UNINITIALIZED)
                        q = "  (uninitialized)";
                        q = "  (uninitialized)";
                else if (mp->state == MOD_RUNNING)
                else if (mp->state == MOD_RUNNING)
                        q = "";
                        q = "";
                else if (mp->state == MOD_DELETED)
                else if (mp->state == MOD_DELETED)
                        q = "  (deleted)";
                        q = "  (deleted)";
                else
                else
                        q = "  (bad state)";
                        q = "  (bad state)";
                while (*q)
                while (*q)
                        *p++ = *q++;
                        *p++ = *q++;
 
 
                *p++ = '\t';
                *p++ = '\t';
                if ((ref = mp->ref) != NULL) {
                if ((ref = mp->ref) != NULL) {
                        *p++ = '[';
                        *p++ = '[';
                        for (; ref; ref = ref->next) {
                        for (; ref; ref = ref->next) {
                                q = ref->module->name;
                                q = ref->module->name;
                                while (*q)
                                while (*q)
                                        *p++ = *q++;
                                        *p++ = *q++;
                                if (ref->next)
                                if (ref->next)
                                        *p++ = ' ';
                                        *p++ = ' ';
                        }
                        }
                        *p++ = ']';
                        *p++ = ']';
                }
                }
                if (mp->state == MOD_RUNNING) {
                if (mp->state == MOD_RUNNING) {
                        sprintf(size,"\t%ld%s",
                        sprintf(size,"\t%ld%s",
                                GET_USE_COUNT(mp) & ~(MOD_AUTOCLEAN | MOD_VISITED),
                                GET_USE_COUNT(mp) & ~(MOD_AUTOCLEAN | MOD_VISITED),
                                ((GET_USE_COUNT(mp) & MOD_AUTOCLEAN)?
                                ((GET_USE_COUNT(mp) & MOD_AUTOCLEAN)?
                                        " (autoclean)":""));
                                        " (autoclean)":""));
                        q = size;
                        q = size;
                        while (*q)
                        while (*q)
                                *p++ = *q++;
                                *p++ = *q++;
                }
                }
                *p++ = '\n';
                *p++ = '\n';
        }
        }
        return p - buf;
        return p - buf;
}
}
 
 
 
 
/*
/*
 * Called by the /proc file system to return a current list of ksyms.
 * Called by the /proc file system to return a current list of ksyms.
 */
 */
int get_ksyms_list(char *buf, char **start, off_t offset, int length)
int get_ksyms_list(char *buf, char **start, off_t offset, int length)
{
{
        struct module *mp;
        struct module *mp;
        struct internal_symbol *sym;
        struct internal_symbol *sym;
        int i;
        int i;
        char *p = buf;
        char *p = buf;
        int len     = 0; /* code from  net/ipv4/proc.c */
        int len     = 0; /* code from  net/ipv4/proc.c */
        off_t pos   = 0;
        off_t pos   = 0;
        off_t begin = 0;
        off_t begin = 0;
 
 
        for (mp = module_list; mp; mp = mp->next) {
        for (mp = module_list; mp; mp = mp->next) {
                if ((mp->state == MOD_RUNNING) &&
                if ((mp->state == MOD_RUNNING) &&
                    (mp->symtab != NULL) &&
                    (mp->symtab != NULL) &&
                    (mp->symtab->n_symbols > 0)) {
                    (mp->symtab->n_symbols > 0)) {
                        for (i = mp->symtab->n_symbols,
                        for (i = mp->symtab->n_symbols,
                                sym = mp->symtab->symbol;
                                sym = mp->symtab->symbol;
                                i > 0; --i, ++sym) {
                                i > 0; --i, ++sym) {
 
 
                                p = buf + len;
                                p = buf + len;
                                if (mp->name[0]) {
                                if (mp->name[0]) {
                                        len += sprintf(p, "%08lx %s\t[%s]\n",
                                        len += sprintf(p, "%08lx %s\t[%s]\n",
                                                       (long)sym->addr,
                                                       (long)sym->addr,
                                                       sym->name, mp->name);
                                                       sym->name, mp->name);
                                } else {
                                } else {
                                        len += sprintf(p, "%08lx %s\n",
                                        len += sprintf(p, "%08lx %s\n",
                                                       (long)sym->addr,
                                                       (long)sym->addr,
                                                       sym->name);
                                                       sym->name);
                                }
                                }
                                pos = begin + len;
                                pos = begin + len;
                                if (pos < offset) {
                                if (pos < offset) {
                                        len   = 0;
                                        len   = 0;
                                        begin = pos;
                                        begin = pos;
                                }
                                }
                                pos = begin + len;
                                pos = begin + len;
                                if (pos > offset+length)
                                if (pos > offset+length)
                                        goto leave_the_loop;
                                        goto leave_the_loop;
                        }
                        }
                }
                }
        }
        }
    leave_the_loop:
    leave_the_loop:
        *start = buf + (offset - begin);
        *start = buf + (offset - begin);
        len -= (offset - begin);
        len -= (offset - begin);
        if (len > length)
        if (len > length)
                len = length;
                len = length;
        return len;
        return len;
}
}
 
 
/*
/*
 * Gets the address for a symbol in the given module.  If modname is
 * Gets the address for a symbol in the given module.  If modname is
 * NULL, it looks for the name in any registered symbol table.  If the
 * NULL, it looks for the name in any registered symbol table.  If the
 * modname is an empty string, it looks for the symbol in kernel exported
 * modname is an empty string, it looks for the symbol in kernel exported
 * symbol tables.
 * symbol tables.
 */
 */
void *get_module_symbol(char *modname, char *symname)
void *get_module_symbol(char *modname, char *symname)
{
{
        struct module *mp;
        struct module *mp;
        struct internal_symbol *sym;
        struct internal_symbol *sym;
        int i;
        int i;
 
 
        for (mp = module_list; mp; mp = mp->next) {
        for (mp = module_list; mp; mp = mp->next) {
                if (((modname == NULL) || (strcmp(mp->name, modname) == 0)) &&
                if (((modname == NULL) || (strcmp(mp->name, modname) == 0)) &&
                        (mp->state == MOD_RUNNING) &&
                        (mp->state == MOD_RUNNING) &&
                    (mp->symtab != NULL) &&
                    (mp->symtab != NULL) &&
                    (mp->symtab->n_symbols > 0)) {
                    (mp->symtab->n_symbols > 0)) {
                        for (i = mp->symtab->n_symbols,
                        for (i = mp->symtab->n_symbols,
                                sym = mp->symtab->symbol;
                                sym = mp->symtab->symbol;
                                i > 0; --i, ++sym) {
                                i > 0; --i, ++sym) {
 
 
                                if (strcmp(sym->name, symname) == 0) {
                                if (strcmp(sym->name, symname) == 0) {
                                        return sym->addr;
                                        return sym->addr;
                                }
                                }
                        }
                        }
                }
                }
        }
        }
        return NULL;
        return NULL;
}
}
 
 
/*
/*
 * Rules:
 * Rules:
 * - The new symbol table should be statically allocated, or else you _have_
 * - The new symbol table should be statically allocated, or else you _have_
 *   to set the "size" field of the struct to the number of bytes allocated.
 *   to set the "size" field of the struct to the number of bytes allocated.
 *
 *
 * - The strings that name the symbols will not be copied, maybe the pointers
 * - The strings that name the symbols will not be copied, maybe the pointers
 *
 *
 * - For a loadable module, the function should only be called in the
 * - For a loadable module, the function should only be called in the
 *   context of init_module
 *   context of init_module
 *
 *
 * Those are the only restrictions! (apart from not being reentrant...)
 * Those are the only restrictions! (apart from not being reentrant...)
 *
 *
 * If you want to remove a symbol table for a loadable module,
 * If you want to remove a symbol table for a loadable module,
 * the call looks like: "register_symtab(0)".
 * the call looks like: "register_symtab(0)".
 *
 *
 * The look of the code is mostly dictated by the format of
 * The look of the code is mostly dictated by the format of
 * the frozen struct symbol_table, due to compatibility demands.
 * the frozen struct symbol_table, due to compatibility demands.
 */
 */
#define INTSIZ sizeof(struct internal_symbol)
#define INTSIZ sizeof(struct internal_symbol)
#define REFSIZ sizeof(struct module_ref)
#define REFSIZ sizeof(struct module_ref)
#define SYMSIZ sizeof(struct symbol_table)
#define SYMSIZ sizeof(struct symbol_table)
#define MODSIZ sizeof(struct module)
#define MODSIZ sizeof(struct module)
static struct symbol_table nulltab;
static struct symbol_table nulltab;
 
 
int
int
register_symtab_from(struct symbol_table *intab, long *from)
register_symtab_from(struct symbol_table *intab, long *from)
{
{
        struct module *mp;
        struct module *mp;
        struct module *link;
        struct module *link;
        struct symbol_table *oldtab;
        struct symbol_table *oldtab;
        struct symbol_table *newtab;
        struct symbol_table *newtab;
        struct module_ref *newref;
        struct module_ref *newref;
        int size;
        int size;
 
 
        if (intab && (intab->n_symbols == 0)) {
        if (intab && (intab->n_symbols == 0)) {
                struct internal_symbol *sym;
                struct internal_symbol *sym;
                /* How many symbols, really? */
                /* How many symbols, really? */
 
 
                for (sym = intab->symbol; sym->name; ++sym)
                for (sym = intab->symbol; sym->name; ++sym)
                        intab->n_symbols +=1;
                        intab->n_symbols +=1;
        }
        }
 
 
        for (mp = module_list; mp != &kernel_module; mp = mp->next) {
        for (mp = module_list; mp != &kernel_module; mp = mp->next) {
                /*
                /*
                 * "from" points to "mod_use_count_" (== start of module)
                 * "from" points to "mod_use_count_" (== start of module)
                 * or is == 0 if called from a non-module
                 * or is == 0 if called from a non-module
                 */
                 */
                if ((unsigned long)(mp->addr) == (unsigned long)from)
                if ((unsigned long)(mp->addr) == (unsigned long)from)
                        break;
                        break;
        }
        }
 
 
        if (mp == &kernel_module) {
        if (mp == &kernel_module) {
                /* Aha! Called from an "internal" module */
                /* Aha! Called from an "internal" module */
                if (!intab)
                if (!intab)
                        return 0; /* or -ESILLY_PROGRAMMER :-) */
                        return 0; /* or -ESILLY_PROGRAMMER :-) */
 
 
                /* create a pseudo module! */
                /* create a pseudo module! */
                if (!(mp = (struct module*) kmalloc(MODSIZ, GFP_KERNEL))) {
                if (!(mp = (struct module*) kmalloc(MODSIZ, GFP_KERNEL))) {
                        /* panic time! */
                        /* panic time! */
                        printk(KERN_ERR "Out of memory for new symbol table!\n");
                        printk(KERN_ERR "Out of memory for new symbol table!\n");
                        return -ENOMEM;
                        return -ENOMEM;
                }
                }
                /* else  OK */
                /* else  OK */
                memset(mp, 0, MODSIZ);
                memset(mp, 0, MODSIZ);
                mp->state = MOD_RUNNING; /* Since it is resident... */
                mp->state = MOD_RUNNING; /* Since it is resident... */
                mp->name = ""; /* This is still the "kernel" symbol table! */
                mp->name = ""; /* This is still the "kernel" symbol table! */
                mp->symtab = intab;
                mp->symtab = intab;
 
 
                /* link it in _after_ the resident symbol table */
                /* link it in _after_ the resident symbol table */
                mp->next = kernel_module.next;
                mp->next = kernel_module.next;
                kernel_module.next = mp;
                kernel_module.next = mp;
 
 
                return 0;
                return 0;
        }
        }
 
 
        /* else ******** Called from a loadable module **********/
        /* else ******** Called from a loadable module **********/
 
 
        /*
        /*
         * This call should _only_ be done in the context of the
         * This call should _only_ be done in the context of the
         * call to  init_module  i.e. when loading the module!!
         * call to  init_module  i.e. when loading the module!!
         * Or else...
         * Or else...
         */
         */
 
 
        /* Any table there before? */
        /* Any table there before? */
        if ((oldtab = mp->symtab) == (struct symbol_table*)0) {
        if ((oldtab = mp->symtab) == (struct symbol_table*)0) {
                /* No, just insert it! */
                /* No, just insert it! */
                mp->symtab = intab;
                mp->symtab = intab;
                return 0;
                return 0;
        }
        }
 
 
        /* else  ****** we have to replace the module symbol table ******/
        /* else  ****** we have to replace the module symbol table ******/
 
 
        if (oldtab->n_refs == 0) { /* no problems! */
        if (oldtab->n_refs == 0) { /* no problems! */
                mp->symtab = intab;
                mp->symtab = intab;
                /* if the old table was kmalloc-ed, drop it */
                /* if the old table was kmalloc-ed, drop it */
                if (oldtab->size > 0)
                if (oldtab->size > 0)
                        kfree_s(oldtab, oldtab->size);
                        kfree_s(oldtab, oldtab->size);
 
 
                return 0;
                return 0;
        }
        }
 
 
        /* else */
        /* else */
        /***** The module references other modules... insmod said so! *****/
        /***** The module references other modules... insmod said so! *****/
        /* We have to allocate a new symbol table, or we lose them! */
        /* We have to allocate a new symbol table, or we lose them! */
        if (intab == (struct symbol_table*)0)
        if (intab == (struct symbol_table*)0)
                intab = &nulltab; /* easier code with zeroes in place */
                intab = &nulltab; /* easier code with zeroes in place */
 
 
        /* the input symbol table space does not include the string table */
        /* the input symbol table space does not include the string table */
        /* (it does for symbol tables that insmod creates) */
        /* (it does for symbol tables that insmod creates) */
 
 
        if (!(newtab = (struct symbol_table*)kmalloc(
        if (!(newtab = (struct symbol_table*)kmalloc(
                size = SYMSIZ + intab->n_symbols * INTSIZ +
                size = SYMSIZ + intab->n_symbols * INTSIZ +
                        oldtab->n_refs * REFSIZ,
                        oldtab->n_refs * REFSIZ,
                GFP_KERNEL))) {
                GFP_KERNEL))) {
                /* panic time! */
                /* panic time! */
                printk(KERN_ERR "Out of memory for new symbol table!\n");
                printk(KERN_ERR "Out of memory for new symbol table!\n");
                return -ENOMEM;
                return -ENOMEM;
        }
        }
 
 
        /* copy up to, and including, the new symbols */
        /* copy up to, and including, the new symbols */
        memcpy(newtab, intab, SYMSIZ + intab->n_symbols * INTSIZ);
        memcpy(newtab, intab, SYMSIZ + intab->n_symbols * INTSIZ);
 
 
        newtab->size = size;
        newtab->size = size;
        newtab->n_refs = oldtab->n_refs;
        newtab->n_refs = oldtab->n_refs;
 
 
        /* copy references */
        /* copy references */
        memcpy( ((char *)newtab) + SYMSIZ + intab->n_symbols * INTSIZ,
        memcpy( ((char *)newtab) + SYMSIZ + intab->n_symbols * INTSIZ,
                ((char *)oldtab) + SYMSIZ + oldtab->n_symbols * INTSIZ,
                ((char *)oldtab) + SYMSIZ + oldtab->n_symbols * INTSIZ,
                oldtab->n_refs * REFSIZ);
                oldtab->n_refs * REFSIZ);
 
 
        /* relink references from the old table to the new one */
        /* relink references from the old table to the new one */
 
 
        /* pointer to the first reference entry in newtab! Really! */
        /* pointer to the first reference entry in newtab! Really! */
        newref = (struct module_ref*) &(newtab->symbol[newtab->n_symbols]);
        newref = (struct module_ref*) &(newtab->symbol[newtab->n_symbols]);
 
 
        /* check for reference links from previous modules */
        /* check for reference links from previous modules */
        for (   link = module_list;
        for (   link = module_list;
                link && (link != &kernel_module);
                link && (link != &kernel_module);
                link = link->next) {
                link = link->next) {
 
 
                if (link->ref && (link->ref->module == mp))
                if (link->ref && (link->ref->module == mp))
                        link->ref = newref++;
                        link->ref = newref++;
        }
        }
 
 
        mp->symtab = newtab;
        mp->symtab = newtab;
 
 
        /* all references (if any) have been handled */
        /* all references (if any) have been handled */
 
 
        /* if the old table was kmalloc-ed, drop it */
        /* if the old table was kmalloc-ed, drop it */
        if (oldtab->size > 0)
        if (oldtab->size > 0)
                kfree_s(oldtab, oldtab->size);
                kfree_s(oldtab, oldtab->size);
 
 
        return 0;
        return 0;
}
}
 
 
#else           /* CONFIG_MODULES */
#else           /* CONFIG_MODULES */
 
 
/* Dummy syscalls for people who don't want modules */
/* Dummy syscalls for people who don't want modules */
 
 
asmlinkage unsigned long sys_create_module(void)
asmlinkage unsigned long sys_create_module(void)
{
{
        return -ENOSYS;
        return -ENOSYS;
}
}
 
 
asmlinkage int sys_init_module(void)
asmlinkage int sys_init_module(void)
{
{
        return -ENOSYS;
        return -ENOSYS;
}
}
 
 
asmlinkage int sys_delete_module(void)
asmlinkage int sys_delete_module(void)
{
{
        return -ENOSYS;
        return -ENOSYS;
}
}
 
 
asmlinkage int sys_get_kernel_syms(void)
asmlinkage int sys_get_kernel_syms(void)
{
{
        return -ENOSYS;
        return -ENOSYS;
}
}
 
 
int register_symtab_from(struct symbol_table *intab, long *from)
int register_symtab_from(struct symbol_table *intab, long *from)
{
{
        return 0;
        return 0;
}
}
 
 
#endif  /* CONFIG_MODULES */
#endif  /* CONFIG_MODULES */
 
 
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.