root / Whitix / branches / hybrid / kernel / module.c

Revision 538, 10.7 kB (checked in by mwhitworth, 5 months ago)

Create startup module.

Line 
1/*  This file is part of Whitix.
2 *
3 *  Whitix is free software; you can redistribute it and/or modify
4 *  it under the terms of the GNU General Public License as published by
5 *  the Free Software Foundation; either version 2 of the License, or
6 *  (at your option) any later version.
7 *
8 *  Whitix is distributed in the hope that it will be useful,
9 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 *  GNU General Public License for more details.
12 *
13 *  You should have received a copy of the GNU General Public License
14 *  along with Whitix; if not, write to the Free Software
15 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
16 *
17 */
18
19#include <config.h>
20#include <console.h>
21#include <elf.h>
22#include <error.h>
23#include <malloc.h>
24#include <module.h>
25#include <i386/i386.h>
26#include <i386/virtual.h>
27#include <sections.h>
28#include <slab.h>
29#include <sys.h>
30#include <task.h>
31#include <imports.h>
32
33LIST_HEAD(moduleList);
34
35static struct Module bootModules[20];
36int bootIndex=0;
37
38#define MODULE_START    0xD8000000
39#define MODULE_END              0xE0000000
40
41void* ModuleSymbolFind(struct Module* module, const char* symName, int type)
42{
43        DWORD i;
44        struct ElfSymbol* symbol;
45
46        for (i=1; i<module->symTableSize/(sizeof(struct ElfSymbol)); i++)
47        {
48                symbol=&module->symTable[i];
49
50                if (symbol->symIndex == STN_UNDEF)
51                        continue;
52
53                if (ELF_ST_TYPE(symbol->symInfo) != type)
54                        continue;
55
56                if (strcmp(symName, module->strTable+symbol->symName))
57                        continue;
58
59                /* Handle data? */
60                return (void*)(symbol->symValue);
61        }
62
63        return NULL;
64}
65
66#ifdef CONFIG_ALL_SYMBOLS
67
68void ModuleSymbolPrint(DWORD address)
69{
70        struct Module* curr, *module=NULL;
71
72        ListForEachEntry(curr, &moduleList, next)
73        {
74                if (address >= curr->textAddr && address < curr->textAddr+curr->textLength)
75                {
76                        module=curr;
77                        break;
78                }
79        }
80
81        if (module)
82        {
83                DWORD size, offset;
84                const char* SymbolLookup(char*, struct ElfSymbol*, int, DWORD, DWORD*, DWORD*);
85
86                const char* name=SymbolLookup(module->strTable, module->symTable, module->symTableSize, address, &size, &offset);
87
88                if (name)
89                        KePrint("%s+%#X/%#X\n", name, offset, size);
90                else
91                        KePrint("%#X\n", address);
92        }else
93                KePrint("%#X\n", address);
94}
95
96void ModuleSymbolAdd(struct Module* module)
97{
98        int length=module->symTableSize+module->strTableSize;
99        char* dest=(void*)VirtMapPhysRange(MODULE_START, MODULE_END, PAGE_ALIGN_UP(length) >> PAGE_SHIFT, 3);
100
101        memcpy(dest, module->symTable, module->symTableSize);
102        module->symTable=(struct ElfSymbol*)dest;
103
104        dest+=module->symTableSize;
105        memcpy(dest, module->strTable, module->strTableSize);
106        module->strTable=dest; 
107}
108
109#else
110void ModuleSymbolPrint(DWORD address)
111{
112        KePrint("%#X\n", address);
113}
114
115void ModuleSymbolAdd(struct Module* module)
116{
117}
118#endif
119
120DWORD ModuleResolveKernel(char* name)
121{
122        /* Look through the kernel symbol table. */
123        struct KernelSymbol* currSym=(struct KernelSymbol*)symtable_start;
124
125        while (currSym != ((struct KernelSymbol*)symtable_end))
126        {
127                if (!strcmp(currSym->name, name))
128                        return currSym->addr;
129
130                currSym++;
131        }
132
133        struct Module* curr;
134
135        /* Look through the kernel symbol table of different modules. */
136        ListForEachEntry(curr, &moduleList, next)
137        {
138                if (!curr->keSymTab)
139                        continue;
140
141                currSym=(struct KernelSymbol*)(curr->keSymTab);
142                int i=0;
143
144                while (i < curr->keSymTabSize)
145                {
146                        if (!strcmp(currSym->name, name))
147                                return currSym->addr;
148
149                        currSym++;
150                        i+=sizeof(struct KernelSymbol);
151                }
152        }
153
154        KePrint("Could not resolve %s\n", name);
155
156        return 0;
157}
158
159/***********************************************************************
160 *
161 * FUNCTION: ModuleSymbolPrepare
162 *
163 * DESCRIPTION: Iterate through the symbol table and relocate them to the
164 *                              base address by altering their symValue, ready for
165 *                              ModuleSymbolResolve to update the relocations.
166 *
167 * PARAMETERS: module - the module's whose symbols are to be relocated.
168 *
169 * RETURNS: 0 on success, -ENOENT on an invalid symbol.
170 *
171 ***********************************************************************/
172
173int ModuleSymbolPrepare(struct Module* module)
174{
175        DWORD i;
176        DWORD symSize=module->symTableSize/sizeof(struct ElfSymbol);
177
178        /* Iterate through all the symbols in the symbol table, skipping the first entry,
179         * which is a NULL symbol. */
180        for (i=1; i<symSize; i++)
181        {
182                struct ElfSymbol* symbol=&module->symTable[i];
183
184                /* Get the symbol's name in the string table. */
185                char* symName=module->strTable+symbol->symName;
186
187                switch (symbol->symIndex)
188                {
189                        /* The symbol is undefined, so we've got to look at the kernel
190                         * and module symbols to set its value. */
191                        case STN_UNDEF:
192                                symbol->symValue=ModuleResolveKernel(symName);
193
194                                if (symbol->symValue)
195                                        break;
196
197                                KePrint("Could not resolve %s\n", symName);
198                                return -ENOENT;
199
200                        /* Absolute symbol. No relocation needed. */
201                        case STN_ABS:
202                                break;
203
204                        /* Common symbols aren't supported by the module loading code. */
205                        case STN_COMMON:
206                                KePrint("Please recompile the module with -fno-common.\n");
207                                return -ENOENT;
208
209                        /* Just add the section base to the symbol value. */
210                        default:
211                                symbol->symValue+=module->sectionHeaders[symbol->symIndex].shAddr;
212                }
213        }
214
215        return 0;
216}
217
218void ModuleSymbolResolve(struct Module* module, char* file, int sec)
219{
220        DWORD i;
221        struct ElfReloc* reloc;
222        struct ElfReloc* relTable=(struct ElfReloc*)(file+module->sectionHeaders[sec].shOffset);
223        DWORD relSize=module->sectionHeaders[sec].shSize/sizeof(struct ElfReloc);
224
225        for (i=0; i<relSize; i++)
226        {
227                reloc=&relTable[i];
228                unsigned long* relAddr=(unsigned long*)(module->sectionHeaders[ module->sectionHeaders[sec].shInfo ].shAddr+reloc->addr);
229                int symTabIdx=ELF_R_SYM(reloc->info);
230                struct ElfSymbol* symbol=&module->symTable[symTabIdx];
231
232                switch (ELF_R_TYPE(reloc->info))
233                {
234                        case R_386_NONE:
235                                break;
236
237                        case R_386_32:
238                                *relAddr+=symbol->symValue;
239                                break;
240
241                        case R_386_PC32:
242                                *relAddr+=symbol->symValue-(DWORD)relAddr;
243                                break;
244
245                        default:
246                                KePrint("ModuleSymbolResolve: type = %u, %u\n", ELF_R_TYPE(reloc->info), symbol->symIndex);
247                }
248        }
249}
250
251/* TODO: Cleanup parameters. */
252void* ModuleSectionFind(struct Module* module, const char* sectionNames, const char* name, int total, int* size)
253{
254        int i;
255
256        for (i=0; i<total; i++)
257        {
258                /* If it's not allocated, it won't be in the final module image. */
259                if (!(module->sectionHeaders[i].shFlags & SEC_FLAGS_ALLOC))
260                        continue;
261
262                if (!strcmp(sectionNames+module->sectionHeaders[i].shName, name))
263                {
264                        if (size)
265                                *size=module->sectionHeaders[i].shSize;
266
267                        return (void*)(module->sectionHeaders[i].shAddr);
268                }
269        }
270
271        return NULL;
272}
273
274/* TODO: Move to generic typedefs.h file. */
275#define SIZE_ALIGN_UP(size, align) (((size)+(align-1)) & (~(align-1)))
276
277int ModuleAdd(void* file, void* image, unsigned long length, int flags)
278{
279        struct ElfHeader* elfHeader=(struct ElfHeader*)file;
280        struct Module* module;
281        struct ElfSectionHeader* sectionHeaders;
282        DWORD loadAddr=(DWORD)image;
283        int i, ret=0;
284
285        if (!ELF_HEAD_CHECK(elfHeader) || (elfHeader->fileType != ELF_REL) || (elfHeader->shEntrySize != sizeof(struct ElfSectionHeader)))
286                return -EINVAL;
287
288        /* Iterate through section headers. */
289        sectionHeaders=(struct ElfSectionHeader*)((char*)file+elfHeader->shOffset);
290
291        /* Get basic information about the module. */
292        if (MemAlloc)
293                module=(struct Module*)MemAlloc(sizeof(struct Module));
294        else
295                module=&bootModules[bootIndex++];
296
297        module->loadAddr=loadAddr;
298        module->sectionHeaders=sectionHeaders;
299
300        ZeroMemory(image, PAGE_ALIGN_UP(length));
301
302        for (i=0; i<elfHeader->shEntries; i++)
303        {
304                /* Save the symbol table off for resolving later. */
305                if (sectionHeaders[i].shType == SEC_TYPE_SYMTAB)
306                {
307                        module->symTable=(struct ElfSymbol*)(file+sectionHeaders[i].shOffset);
308                        module->symTableSize=sectionHeaders[i].shSize;
309                }
310
311                if (sectionHeaders[i].shType == SEC_TYPE_STRTAB)
312                {
313                        module->strTable=(char*)file+sectionHeaders[i].shOffset;
314                        module->strTableSize=sectionHeaders[i].shSize;
315                }
316
317                /* Align up sizes. */
318                sectionHeaders[i].shSize=SIZE_ALIGN_UP(sectionHeaders[i].shSize, sectionHeaders[i].shAddrAlign);
319        }
320
321        /* Copy over the module data into a new image. */
322        char* dest;
323        dest=(char*)module->loadAddr;
324
325        for (i=0; i<elfHeader->shEntries; i++)
326        {
327                if (!(sectionHeaders[i].shFlags & SEC_FLAGS_ALLOC))
328                        continue;
329
330                if (sectionHeaders[i].shFlags & SEC_FLAGS_EXEC)
331                {
332                        module->textAddr=(DWORD)dest;
333                        module->textLength=sectionHeaders[i].shSize;
334                }
335
336                sectionHeaders[i].shAddr=(DWORD)dest;
337
338                /* Unless it's a BSS section (or similar), copy the data over. */
339                if (sectionHeaders[i].shType != SEC_TYPE_NOBITS)
340                        memcpy(dest, (char*)(file+sectionHeaders[i].shOffset), sectionHeaders[i].shSize);
341
342                dest+=sectionHeaders[i].shSize;
343        }
344
345        if (ModuleSymbolPrepare(module))
346                return -ENOENT;
347
348        for (i=0; i<elfHeader->shEntries; i++)
349        {
350                if (sectionHeaders[i].shType == SEC_TYPE_REL)
351                        /* Resolve entries in the module. */
352                        ModuleSymbolResolve(module, file, i);
353        }
354
355        /* Find the init and exit functions, using the symbol and string table addresses. */
356        int (*modInit)(void);
357
358        modInit=ModuleSymbolFind(module, "_ModuleInit", STT_FUNC);
359
360        if (modInit)
361                /* Call ModuleInit */
362                ret=(*modInit)();
363
364        /* Get the symbol table and string table, so we can resolve other symbols later. */
365        module->keSymTab=ModuleSectionFind(module, (char*)file+sectionHeaders[elfHeader->strTabSectionIndex].shOffset, ".symtable", elfHeader->shEntries, &module->keSymTabSize);
366
367        ListAdd(&module->next, &moduleList);
368
369        return ret;
370}
371
372#define SYS_MODULE_BASE         51
373
374int SysModuleAdd(void* data, unsigned long length);
375int SysModuleRemove(const char* name);
376
377struct SysCall moduleSysCalls[]={
378        { SysModuleAdd, 8 },
379        { SysModuleRemove, 4},
380        { 0, 0 }
381};
382
383void ModulesBootLoad()
384{
385        /* The modules are located above the kernel in memory. */
386        BYTE* numModules=(BYTE*)0x2FFFF;
387        int i=0;
388        DWORD* length=(DWORD*)0x40000;
389        char* names=(char*)0x30000;
390
391        for (i=0; i<*numModules; i++)
392        {
393                /* Load each module, one at a time. */
394                BYTE* data=(BYTE*)(length+1);
395                void* kData=(void*)VirtMapPhysRange(MODULE_START, MODULE_END, PAGE_ALIGN_UP(*length) >> PAGE_SHIFT, 3);
396                char buf[32];
397
398                int j=0;
399
400                while (names[j] != '\n')
401                        j++;
402
403                names[j]='\0';
404
405                strcpy(buf, names);
406                strcat(buf, ".sys");
407
408                if (ModuleAdd(data, kData, *length, 0))
409                        KernelPanic("Could not initialize the kernel");
410
411                KePrint("MODULES: Loaded %s, %dkb\n", buf, (*length)/1024);
412
413                names+=strlen(names)+1;
414
415                length+=(*length/4)+1;
416        }
417
418        /* Free the low pages. */
419
420        /* Add the calls to the system table. */
421        SysRegisterRange(SYS_MODULE_BASE, moduleSysCalls);
422}
423
424int SysModuleAdd(void* data, unsigned long length)
425{
426        void* kData;
427
428        /* Check data is ok to access. */
429        kData=(void*)VirtMapPhysRange(MODULE_START, MODULE_END, PAGE_ALIGN_UP(length) >> PAGE_SHIFT, 3);
430
431        return ModuleAdd(data, kData, length, 0);
432}
433
434int SysModuleRemove(const char* name)
435{
436        KePrint("SysModuleRemove\n");
437        return 0;
438}
Note: See TracBrowser for help on using the browser.