home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.0 / LINUX-1.0 / LINUX-1 / linux / kernel / module.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-11  |  5.8 KB  |  277 lines

  1. #include <linux/errno.h>
  2. #include <linux/kernel.h>
  3. #include <asm/segment.h>
  4. #include <linux/mm.h>        /* defines GFP_KERNEL */
  5. #include <linux/string.h>
  6. #include <linux/module.h>
  7. #include <linux/sched.h>
  8. #include <linux/malloc.h>
  9.  
  10. struct module *module_list = NULL;
  11. int freeing_modules;        /* true if some modules are marked for deletion */
  12.  
  13. struct module *find_module( const char *name);
  14. int get_mod_name( char *user_name, char *buf);
  15. int free_modules( void);
  16.  
  17. /*
  18.  * Allocate space for a module.
  19.  */
  20. asmlinkage int
  21. sys_create_module(char *module_name, unsigned long size)
  22. {
  23.     int npages;
  24.     void* addr;
  25.     int len;
  26.     char name[MOD_MAX_NAME];
  27.     char *savename;
  28.     struct module *mp;
  29.     int error;
  30.  
  31.     if (!suser())
  32.         return -EPERM;
  33.     if (module_name == NULL || size == 0)
  34.         return -EINVAL;
  35.     if ((error = get_mod_name(module_name, name)) != 0)
  36.         return error;
  37.     if (find_module(name) != NULL) {
  38.         return -EEXIST;
  39.     }
  40.     len = strlen(name) + 1;
  41.     if ((savename = (char*) kmalloc(len, GFP_KERNEL)) == NULL)
  42.         return -ENOMEM;
  43.     memcpy(savename, name, len);
  44.     if ((mp = (struct module*) kmalloc(sizeof *mp, GFP_KERNEL)) == NULL) {
  45.         kfree(savename);
  46.         return -ENOMEM;
  47.     }
  48.     npages = (size + sizeof (int) + 4095) / 4096;
  49.     if ((addr = vmalloc(npages * 4096)) == 0) {
  50.         kfree_s(mp, sizeof *mp);
  51.         kfree(savename);
  52.         return -ENOMEM;
  53.     }
  54.     mp->name = savename;
  55.     mp->size = npages;
  56.     mp->addr = addr;
  57.     mp->state = MOD_UNINITIALIZED;
  58.     * (int *) addr = 0;        /* set use count to zero */
  59.     mp->cleanup = NULL;
  60.     mp->next = module_list;
  61.     module_list = mp;
  62.     printk("module `%s' (%lu pages @ 0x%08lx) created\n",
  63.         mp->name, (unsigned long) mp->size, (unsigned long) mp->addr);
  64.     return (int) addr;
  65. }
  66.  
  67. /*
  68.  * Initialize a module.
  69.  */
  70. asmlinkage int
  71. sys_init_module(char *module_name, char *code, unsigned codesize,
  72.         struct mod_routines *routines)
  73. {
  74.     struct module *mp;
  75.     char name[MOD_MAX_NAME];
  76.     int error;
  77.     struct mod_routines rt;
  78.  
  79.     if (!suser())
  80.         return -EPERM;
  81.     /*
  82.      * First reclaim any memory from dead modules that where not
  83.      * freed when deleted. Should I think be done by timers when
  84.      * the module was deleted - Jon.
  85.      */
  86.     free_modules();
  87.  
  88.     if ((error = get_mod_name(module_name, name)) != 0)
  89.         return error;
  90.     printk( "initializing module `%s', %d (0x%x) bytes\n",
  91.         name, codesize, codesize);
  92.     memcpy_fromfs(&rt, routines, sizeof rt);
  93.     if ((mp = find_module(name)) == NULL)
  94.         return -ENOENT;
  95.     if ((codesize + sizeof (int) + 4095) / 4096 > mp->size)
  96.         return -EINVAL;
  97.     memcpy_fromfs((char *)mp->addr + sizeof (int), code, codesize);
  98.     memset((char *)mp->addr + sizeof (int) + codesize, 0,
  99.         mp->size * 4096 - (codesize + sizeof (int)));
  100.     printk( "  init entry @ 0x%08lx, cleanup entry @ 0x%08lx\n",
  101.         (unsigned long) rt.init, (unsigned long) rt.cleanup);
  102.     mp->cleanup = rt.cleanup;
  103.     if ((*rt.init)() != 0)
  104.         return -EBUSY;
  105.     mp->state = MOD_RUNNING;
  106.     return 0;
  107. }
  108.  
  109. asmlinkage int
  110. sys_delete_module(char *module_name)
  111. {
  112.     struct module *mp;
  113.     char name[MOD_MAX_NAME];
  114.     int error;
  115.  
  116.     if (!suser())
  117.         return -EPERM;
  118.     if (module_name != NULL) {
  119.         if ((error = get_mod_name(module_name, name)) != 0)
  120.             return error;
  121.         if ((mp = find_module(name)) == NULL)
  122.             return -ENOENT;
  123.         if (mp->state == MOD_RUNNING)
  124.             (*mp->cleanup)();
  125.         mp->state = MOD_DELETED;
  126.     }
  127.     free_modules();
  128.     return 0;
  129. }
  130.  
  131. /*
  132.  * Copy the kernel symbol table to user space.  If the argument is null,
  133.  * just return the size of the table.
  134.  */
  135. asmlinkage int
  136. sys_get_kernel_syms(struct kernel_sym *table)
  137. {
  138.     struct symbol {
  139.         unsigned long addr;
  140.         char *name;
  141.     };
  142.     extern int symbol_table_size;
  143.     extern struct symbol symbol_table[];
  144.     int i;
  145.     struct symbol *from;
  146.     struct kernel_sym *to;
  147.     struct kernel_sym sym;
  148.  
  149.     if (table != NULL) {
  150.         from = symbol_table;
  151.         to = table;
  152.         i = verify_area(VERIFY_WRITE, to, symbol_table_size * sizeof *table);
  153.         if (i)
  154.             return i;
  155.         for (i = symbol_table_size ; --i >= 0 ; ) {
  156.             sym.value = from->addr;
  157.             strncpy(sym.name, from->name, sizeof sym.name);
  158.             memcpy_tofs(to, &sym, sizeof sym);
  159.             from++, to++;
  160.         }
  161.     }
  162.     return symbol_table_size;
  163. }
  164.  
  165.  
  166. /*
  167.  * Copy the name of a module from user space.
  168.  */
  169. int
  170. get_mod_name(char *user_name, char *buf)
  171. {
  172.     int i;
  173.  
  174.     i = 0;
  175.     for (i = 0 ; (buf[i] = get_fs_byte(user_name + i)) != '\0' ; ) {
  176.         if (++i >= MOD_MAX_NAME)
  177.             return -E2BIG;
  178.     }
  179.     return 0;
  180. }
  181.  
  182.  
  183. /*
  184.  * Look for a module by name, ignoring modules marked for deletion.
  185.  */
  186. struct module *
  187. find_module( const char *name)
  188. {
  189.     struct module *mp;
  190.  
  191.     for (mp = module_list ; mp ; mp = mp->next) {
  192.         if (mp->state == MOD_DELETED)
  193.             continue;
  194.         if (!strcmp(mp->name, name))
  195.             break;
  196.     }
  197.     return mp;
  198. }
  199.  
  200.  
  201. /*
  202.  * Try to free modules which have been marked for deletion.  Returns nonzero
  203.  * if a module was actually freed.
  204.  */
  205. int
  206. free_modules( void)
  207. {
  208.     struct module *mp;
  209.     struct module **mpp;
  210.     int did_deletion;
  211.  
  212.     did_deletion = 0;
  213.     freeing_modules = 0;
  214.     mpp = &module_list;
  215.     while ((mp = *mpp) != NULL) {
  216.         if (mp->state != MOD_DELETED) {
  217.             mpp = &mp->next;
  218.         } else if (GET_USE_COUNT(mp) != 0) {
  219.             freeing_modules = 1;
  220.             mpp = &mp->next;
  221.         } else {    /* delete it */
  222.             *mpp = mp->next;
  223.             vfree(mp->addr);
  224.             kfree(mp->name);
  225.             kfree_s(mp, sizeof *mp);
  226.             did_deletion = 1;
  227.         }
  228.     }
  229.     return did_deletion;
  230. }
  231.  
  232.  
  233. /*
  234.  * Called by the /proc file system to return a current list of modules.
  235.  */
  236. int get_module_list(char *buf)
  237. {
  238.     char *p;
  239.     char *q;
  240.     int i;
  241.     struct module *mp;
  242.     char size[32];
  243.  
  244.     p = buf;
  245.     for (mp = module_list ; mp ; mp = mp->next) {
  246.         if (p - buf > 4096 - 100)
  247.             break;            /* avoid overflowing buffer */
  248.         q = mp->name;
  249.         i = 20;
  250.         while (*q) {
  251.             *p++ = *q++;
  252.             i--;
  253.         }
  254.         sprintf(size, "%d", mp->size);
  255.         i -= strlen(size);
  256.         if (i <= 0)
  257.             i = 1;
  258.         while (--i >= 0)
  259.             *p++ = ' ';
  260.         q = size;
  261.         while (*q)
  262.             *p++ = *q++;
  263.         if (mp->state == MOD_UNINITIALIZED)
  264.             q = "  (uninitialized)";
  265.         else if (mp->state == MOD_RUNNING)
  266.             q = "";
  267.         else if (mp->state == MOD_DELETED)
  268.             q = "  (deleted)";
  269.         else
  270.             q = "  (bad state)";
  271.         while (*q)
  272.             *p++ = *q++;
  273.         *p++ = '\n';
  274.     }
  275.     return p - buf;
  276. }
  277.