/*- * Copyright (c) 2002-2018 The UbixOS Project. * All rights reserved. * * This was developed by Christopher W. Olsen for the UbixOS Project. * * Redistribution and use in source and binary forms, with or without modification, are permitted * provided that the following conditions are met: * * 1) Redistributions of source code must retain the above copyright notice, this list of * conditions, the following disclaimer and the list of authors. * 2) Redistributions in binary form must reproduce the above copyright notice, this list of * conditions, the following disclaimer and the list of authors in the documentation and/or * other materials provided with the distribution. * 3) Neither the name of the UbixOS Project nor the names of its contributors may be used to * endorse or promote products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <sys/types.h> #include <ubixos/kmod.h> #include <ubixos/sched.h> #include <sys/elf.h> #include <ubixos/kpanic.h> #include <ubixos/lists.h> #include <ubixos/spinlock.h> #include <lib/kprintf.h> #include <lib/kmalloc.h> #include <vfs/vfs.h> #include <vmm/vmm.h> #include <string.h> #include <assert.h> List_t *List = 0x0; uInt32 kmod_add(const char *kmod_file, const char *name) { uInt32 addr = 0x0; Item_t *tmp; kmod_t *kmods; addr = kmod_load(kmod_file); if (addr == 0x0) return 0x0; if (List == 0x0) { List = InitializeList(); } tmp = CreateItem(); InsertItemAtFront(List, tmp); kmods = kmalloc(sizeof *kmods); tmp->data = kmods; if (kmods == NULL) { kprintf("kmod_add: unable to allocate memory!\n"); return 0x0; } return 0x0; } uInt32 kmod_load(const char *kmod_file) { int i = 0x0; int x = 0x0; int rel = 0x0; int sym = 0x0; char *newLoc = 0x0; char *shStr = 0x0; char *dynStr = 0x0; uInt32 *reMap = 0x0; fileDescriptor *kmod_fd = 0x0; elfHeader *binaryHeader = 0x0; elfProgramHeader *programHeader = 0x0; elfSectionHeader *sectionHeader = 0x0; elfDynSym *relSymTab = 0x0; elfPltInfo *elfRel = 0x0; /* Open kernel module */ kmod_fd = fopen(kmod_file, "rb"); if (kmod_fd == 0x0) { kprintf("Can not open %s\n", kmod_file); return 0x0; } /* load module header */ kern_fseek(kmod_fd, 0x0, 0x0); binaryHeader = (elfHeader *) kmalloc(sizeof(elfHeader)); if (binaryHeader == 0x0) { kprintf("kmod: out of memory\n"); return 0x0; } assert(binaryHeader); fread(binaryHeader, sizeof(elfHeader), 1, kmod_fd); programHeader = (elfProgramHeader *) kmalloc(sizeof(elfProgramHeader) * binaryHeader->ePhnum); assert(programHeader); kern_fseek(kmod_fd, binaryHeader->ePhoff, 0); fread(programHeader, sizeof(elfSectionHeader), binaryHeader->ePhnum, kmod_fd); sectionHeader = (elfSectionHeader *) kmalloc(sizeof(elfSectionHeader) * binaryHeader->eShnum); assert(sectionHeader); kern_fseek(kmod_fd, binaryHeader->eShoff, 0); fread(sectionHeader, sizeof(elfSectionHeader), binaryHeader->eShnum, kmod_fd); shStr = (char *) kmalloc(sectionHeader[binaryHeader->eShstrndx].shSize); kern_fseek(kmod_fd, sectionHeader[binaryHeader->eShstrndx].shOffset, 0); fread(shStr, sectionHeader[binaryHeader->eShstrndx].shSize, 1, kmod_fd); for (i = 0; i < binaryHeader->ePhnum; i++) { switch (programHeader[i].phType) { case PT_LOAD: case PT_DYNAMIC: newLoc = (char *) programHeader[i].phVaddr + LD_START; /* Allocate Memory Im Going To Have To Make This Load Memory With Correct Settings so it helps us in the future */ for (x = 0; x < ((programHeader[i].phMemsz) + 4095); x += 0x1000) { /* make r/w or ro */ if ((vmm_remapPage(vmm_findFreePage(_current->id), ((programHeader[i].phVaddr & 0xFFFFF000) + x + LD_START), PAGE_DEFAULT)) == 0x0) kpanic("vmmRemapPage: ld\n"); memset((void *) ((programHeader[i].phVaddr & 0xFFFFF000) + x + LD_START), 0x0, 0x1000); } /* Now Load Section To Memory */ kern_fseek(kmod_fd, programHeader[i].phOffset, 0x0); fread(newLoc, programHeader[i].phFilesz, 1, kmod_fd); break; case PT_GNU_STACK: /* Tells us if the stack should be executable. Failsafe to executable until we add checking */ break; #ifdef _IGNORE case PT_PAX_FLAGS: /* Not sure... */ break; #endif default: kprintf("Unhandled Header : %08x\n", programHeader[i].phType); break; } } for (i = 0x0; i < binaryHeader->eShnum; i++) { switch (sectionHeader[i].shType) { case 3: if (!strcmp((shStr + sectionHeader[i].shName), ".dynstr")) { dynStr = (char *) kmalloc(sectionHeader[i].shSize); kern_fseek(kmod_fd, sectionHeader[i].shOffset, 0x0); fread(dynStr, sectionHeader[i].shSize, 1, kmod_fd); } break; case 9: elfRel = (elfPltInfo *) kmalloc(sectionHeader[i].shSize); kern_fseek(kmod_fd, sectionHeader[i].shOffset, 0x0); fread(elfRel, sectionHeader[i].shSize, 1, kmod_fd); for (x = 0x0; x < sectionHeader[i].shSize / sizeof(elfPltInfo); x++) { rel = ELF32_R_SYM(elfRel[x].pltInfo); reMap = (uInt32 *) ((uInt32) LD_START + elfRel[x].pltOffset); switch (ELF32_R_TYPE(elfRel[x].pltInfo)) { case R_386_32: *reMap += ((uInt32) LD_START + relSymTab[rel].dynValue); break; case R_386_PC32: *reMap += ((uInt32) LD_START + relSymTab[rel].dynValue) - (uInt32) reMap; break; case R_386_RELATIVE: *reMap += (uInt32) LD_START; break; default: kprintf("[0x%X][0x%X](%i)[%s]\n", elfRel[x].pltOffset, elfRel[x].pltInfo, rel, elfGetRelType(ELF32_R_TYPE(elfRel[x].pltInfo))); kprintf("relTab [%s][0x%X][0x%X]\n", dynStr + relSymTab[rel].dynName, relSymTab[rel].dynValue, relSymTab[rel].dynName); break; } } kfree(elfRel); break; case 11: relSymTab = (elfDynSym *) kmalloc(sectionHeader[i].shSize); kern_fseek(kmod_fd, sectionHeader[i].shOffset, 0x0); fread(relSymTab, sectionHeader[i].shSize, 1, kmod_fd); sym = i; break; } } i = binaryHeader->eEntry + LD_START; kfree(dynStr); kfree(shStr); kfree(relSymTab); kfree(sectionHeader); kfree(programHeader); kfree(binaryHeader); fclose(kmod_fd); return ((uInt32) i); } /*** END ***/