Back to home page

Quest Cross Reference

 
 

    


Warning, cross-references for /kernel/module/loader.c need to be fixed.

0001 /*                    The Quest Operating System
0002  *  Copyright (C) 2005-2010  Richard West, Boston University
0003  *
0004  *  This program is free software: you can redistribute it and/or modify
0005  *  it under the terms of the GNU General Public License as published by
0006  *  the Free Software Foundation, either version 3 of the License, or
0007  *  (at your option) any later version.
0008  *
0009  *  This program is distributed in the hope that it will be useful,
0010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
0011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0012  *  GNU General Public License for more details.
0013  *
0014  *  You should have received a copy of the GNU General Public License
0015  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
0016  */
0017 
0018 #include "types.h"
0019 #include "mem/physical.h"
0020 #include "mem/virtual.h"
0021 #include "module/header.h"
0022 #include "util/debug.h"
0023 #include "arch/i386.h"
0024 
0025 #define DEBUG_MODULE
0026 
0027 #ifdef DEBUG_MODULE
0028 #define DLOG(fmt,...) DLOG_PREFIX("module",fmt,##__VA_ARGS__)
0029 #else
0030 #define DLOG(fmt,...) ;
0031 #endif
0032 
0033 extern const struct module *_module_ptr_list;
0034 
0035 typedef struct modruntime {
0036   const struct module *mod;
0037   union {
0038     u32 flags;
0039     struct {
0040       u32 loaded:1;
0041     };
0042   };
0043 } modruntime_t;
0044 
0045 typedef struct modsystem {
0046   modruntime_t *mr;
0047   u32 cnt;
0048 } modsystem_t;
0049 
0050 static modsystem_t module_system;
0051 
0052 static bool module_load_i (const int);
0053 
0054 /* Initialize a module by name, or a whole subtree of modules by
0055  * prefix (indicated by trailing "___"). */
0056 static int
0057 module_load_name (const char *name, int i, int j)
0058 {
0059   bool subtree = FALSE, success = FALSE;
0060   if (name[j-1] == '_' && name[j-2] == '_' && name[j-3] == '_')
0061     subtree = TRUE;
0062   int n;
0063   for (n=0; n<module_system.cnt; n++) {
0064     const char *modname = module_system.mr[n].mod->name;
0065     if ((subtree || strlen (modname) == j - i) &&
0066         strncmp (modname, name + i, j - i) == 0) {
0067       success |= module_load_i (n);
0068       if (!subtree) return success;
0069     }
0070   }
0071   return success;
0072 }
0073 
0074 /* Initialize a single disjunction of modules by |-separated names.
0075  * Iff any succeeds, then return TRUE.  Try them all, regardless. */
0076 static bool
0077 module_load_disj (const char *names)
0078 {
0079   int i, j;
0080   bool success = FALSE;
0081   for (i=0, j=0; names[j]; i=j+1) {
0082     j=i;
0083     while (names[j] && names[j]!='|') j++;
0084     success |= module_load_name (names, i, j);
0085   }
0086   return success;
0087 }
0088 
0089 /* Initialize a single module by index */
0090 static bool
0091 module_load_i (const int modi)
0092 {
0093   int depi;
0094   modruntime_t *mr = module_system.mr;
0095 
0096   if (modi < 0) return FALSE;
0097   if (mr[modi].loaded) return TRUE;
0098   for (depi=0; depi<mr[modi].mod->num_dependencies; depi++)
0099     if (!module_load_disj (mr[modi].mod->dependencies[depi]))
0100       return FALSE;
0101   if (mr[modi].mod->ops->init ()) {
0102     mr[modi].loaded = 1;
0103     DLOG ("initialized module \"%s\"", mr[modi].mod->name);
0104     return TRUE;
0105   } else {
0106     DLOG ("failed to initialize module \"%s\"", mr[modi].mod->name);
0107     return FALSE;
0108   }
0109 }
0110 
0111 /* Initialize module runtime information and load all modules */
0112 extern bool
0113 module_load_all (void)
0114 {
0115   u32 count = 0, pages = 0, i;
0116   u32 phys;
0117   modruntime_t *mr;
0118   DLOG ("loading all modules");
0119   const struct module **mod;
0120   for (mod = &_module_ptr_list; *mod; mod++) {
0121     DLOG ("found name=\"%s\" desc: %s", (*mod)->name, (*mod)->desc);
0122     count++;
0123   }
0124   if (!count) return TRUE;
0125   pages = ((count * sizeof (modruntime_t) - 1) >> 12) + 1;
0126   phys = alloc_phys_frames (pages);
0127   if (phys == (u32) -1) goto abort;
0128   mr = map_contiguous_virtual_pages (phys | 3, pages);
0129   if (!mr) goto abort_phys;
0130   memset (mr, 0, pages << 12);
0131 
0132   module_system.mr = mr;
0133   module_system.cnt = count;
0134   for (i=0, mod = &_module_ptr_list; *mod; i++, mod++) {
0135     mr[i].mod = *mod;
0136   }
0137 
0138   for (i=0; i<count; i++)
0139     module_load_i (i);
0140 
0141   return TRUE;
0142  abort_phys:
0143   free_phys_frames (phys, pages);
0144  abort:
0145   return FALSE;
0146 }
0147 
0148 /*
0149  * Local Variables:
0150  * indent-tabs-mode: nil
0151  * mode: C
0152  * c-file-style: "gnu"
0153  * c-basic-offset: 2
0154  * End:
0155  */
0156 
0157 /* vi: set et sw=2 sts=2: */