UbixOS  2.0
kmod.c
Go to the documentation of this file.
1 /*-
2  * Copyright (c) 2002-2018 The UbixOS Project.
3  * All rights reserved.
4  *
5  * This was developed by Christopher W. Olsen for the UbixOS Project.
6  *
7  * Redistribution and use in source and binary forms, with or without modification, are permitted
8  * provided that the following conditions are met:
9  *
10  * 1) Redistributions of source code must retain the above copyright notice, this list of
11  * conditions, the following disclaimer and the list of authors.
12  * 2) Redistributions in binary form must reproduce the above copyright notice, this list of
13  * conditions, the following disclaimer and the list of authors in the documentation and/or
14  * other materials provided with the distribution.
15  * 3) Neither the name of the UbixOS Project nor the names of its contributors may be used to
16  * endorse or promote products derived from this software without specific prior written
17  * permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
20  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
22  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
24  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <sys/types.h>
30 #include <ubixos/kmod.h>
31 #include <ubixos/sched.h>
32 #include <sys/elf.h>
33 #include <ubixos/kpanic.h>
34 #include <ubixos/lists.h>
35 #include <ubixos/spinlock.h>
36 #include <lib/kprintf.h>
37 #include <lib/kmalloc.h>
38 #include <vfs/vfs.h>
39 #include <vmm/vmm.h>
40 #include <string.h>
41 #include <assert.h>
42 
43 List_t *List = 0x0;
44 
45 uInt32 kmod_add(const char *kmod_file, const char *name) {
46  uInt32 addr = 0x0;
47  Item_t *tmp;
48  kmod_t *kmods;
49 
50  addr = kmod_load(kmod_file);
51  if (addr == 0x0)
52  return 0x0;
53 
54  if (List == 0x0) {
55  List = InitializeList();
56  }
57 
58  tmp = CreateItem();
59  InsertItemAtFront(List, tmp);
60  kmods = kmalloc(sizeof *kmods);
61  tmp->data = kmods;
62  if (kmods == NULL) {
63  kprintf("kmod_add: unable to allocate memory!\n");
64  return 0x0;
65  }
66 
67  return 0x0;
68 }
69 
70 uInt32 kmod_load(const char *kmod_file) {
71  int i = 0x0;
72  int x = 0x0;
73  int rel = 0x0;
74  int sym = 0x0;
75  char *newLoc = 0x0;
76  char *shStr = 0x0;
77  char *dynStr = 0x0;
78  uInt32 *reMap = 0x0;
79  fileDescriptor *kmod_fd = 0x0;
80  elfHeader *binaryHeader = 0x0;
81  elfProgramHeader *programHeader = 0x0;
82  elfSectionHeader *sectionHeader = 0x0;
83  elfDynSym *relSymTab = 0x0;
84  elfPltInfo *elfRel = 0x0;
85 
86  /* Open kernel module */
87  kmod_fd = fopen(kmod_file, "rb");
88  if (kmod_fd == 0x0) {
89  kprintf("Can not open %s\n", kmod_file);
90  return 0x0;
91  }
92 
93  /* load module header */
94  fseek(kmod_fd, 0x0, 0x0);
95  binaryHeader = (elfHeader *) kmalloc(sizeof(elfHeader));
96  if (binaryHeader == 0x0) {
97  kprintf("kmod: out of memory\n");
98  return 0x0;
99  }
100 
101  assert(binaryHeader);
102  fread(binaryHeader, sizeof(elfHeader), 1, kmod_fd);
103 
104  programHeader = (elfProgramHeader *) kmalloc(sizeof(elfProgramHeader) * binaryHeader->ePhnum);
105  assert(programHeader);
106  fseek(kmod_fd, binaryHeader->ePhoff, 0);
107  fread(programHeader, sizeof(elfSectionHeader), binaryHeader->ePhnum, kmod_fd);
108 
109  sectionHeader = (elfSectionHeader *) kmalloc(sizeof(elfSectionHeader) * binaryHeader->eShnum);
110  assert(sectionHeader);
111  fseek(kmod_fd, binaryHeader->eShoff, 0);
112  fread(sectionHeader, sizeof(elfSectionHeader), binaryHeader->eShnum, kmod_fd);
113 
114  shStr = (char *) kmalloc(sectionHeader[binaryHeader->eShstrndx].shSize);
115  fseek(kmod_fd, sectionHeader[binaryHeader->eShstrndx].shOffset, 0);
116  fread(shStr, sectionHeader[binaryHeader->eShstrndx].shSize, 1, kmod_fd);
117 
118  for (i = 0; i < binaryHeader->ePhnum; i++) {
119  switch (programHeader[i].phType) {
120  case PT_LOAD:
121  case PT_DYNAMIC:
122  newLoc = (char *) programHeader[i].phVaddr + LD_START;
123  /*
124  Allocate Memory Im Going To Have To Make This Load Memory With Correct
125  Settings so it helps us in the future
126  */
127  for (x = 0; x < ((programHeader[i].phMemsz) + 4095); x += 0x1000) {
128  /* make r/w or ro */
129  if ((vmm_remapPage(vmm_findFreePage(_current->id), ((programHeader[i].phVaddr & 0xFFFFF000) + x + LD_START), PAGE_DEFAULT)) == 0x0)
130  kpanic("vmmRemapPage: ld\n");
131  memset((void *) ((programHeader[i].phVaddr & 0xFFFFF000) + x + LD_START), 0x0, 0x1000);
132  }
133  /* Now Load Section To Memory */
134  fseek(kmod_fd, programHeader[i].phOffset, 0x0);
135  fread(newLoc, programHeader[i].phFilesz, 1, kmod_fd);
136  break;
137  case PT_GNU_STACK:
138  /* Tells us if the stack should be executable. Failsafe to executable
139  until we add checking */
140  break;
141 #ifdef _IGNORE
142  case PT_PAX_FLAGS:
143  /* Not sure... */
144  break;
145 #endif
146  default:
147  kprintf("Unhandled Header : %08x\n", programHeader[i].phType);
148  break;
149  }
150  }
151 
152  for (i = 0x0; i < binaryHeader->eShnum; i++) {
153  switch (sectionHeader[i].shType) {
154  case 3:
155  if (!strcmp((shStr + sectionHeader[i].shName), ".dynstr")) {
156  dynStr = (char *) kmalloc(sectionHeader[i].shSize);
157  fseek(kmod_fd, sectionHeader[i].shOffset, 0x0);
158  fread(dynStr, sectionHeader[i].shSize, 1, kmod_fd);
159  }
160  break;
161  case 9:
162  elfRel = (elfPltInfo *) kmalloc(sectionHeader[i].shSize);
163  fseek(kmod_fd, sectionHeader[i].shOffset, 0x0);
164  fread(elfRel, sectionHeader[i].shSize, 1, kmod_fd);
165 
166  for (x = 0x0; x < sectionHeader[i].shSize / sizeof(elfPltInfo); x++) {
167  rel = ELF32_R_SYM(elfRel[x].pltInfo);
168  reMap = (uInt32 *) ((uInt32) LD_START + elfRel[x].pltOffset);
169  switch (ELF32_R_TYPE(elfRel[x].pltInfo)) {
170  case R_386_32:
171  *reMap += ((uInt32) LD_START + relSymTab[rel].dynValue);
172  break;
173  case R_386_PC32:
174  *reMap += ((uInt32) LD_START + relSymTab[rel].dynValue) - (uInt32) reMap;
175  break;
176  case R_386_RELATIVE:
177  *reMap += (uInt32) LD_START;
178  break;
179  default:
180  kprintf("[0x%X][0x%X](%i)[%s]\n", elfRel[x].pltOffset, elfRel[x].pltInfo, rel, elfGetRelType(ELF32_R_TYPE(elfRel[x].pltInfo)));
181  kprintf("relTab [%s][0x%X][0x%X]\n", dynStr + relSymTab[rel].dynName, relSymTab[rel].dynValue, relSymTab[rel].dynName);
182  break;
183  }
184  }
185  kfree(elfRel);
186  break;
187  case 11:
188  relSymTab = (elfDynSym *) kmalloc(sectionHeader[i].shSize);
189  fseek(kmod_fd, sectionHeader[i].shOffset, 0x0);
190  fread(relSymTab, sectionHeader[i].shSize, 1, kmod_fd);
191  sym = i;
192  break;
193  }
194  }
195 
196  i = binaryHeader->eEntry + LD_START;
197 
198  kfree(dynStr);
199  kfree(shStr);
200  kfree(relSymTab);
201  kfree(sectionHeader);
202  kfree(programHeader);
203  kfree(binaryHeader);
204  fclose(kmod_fd);
205 
206  return ((uInt32) i);
207 }
208 
209 /***
210  END
211  ***/
List
List_t * List
Definition: kmod.c:43
ELF32_R_TYPE
#define ELF32_R_TYPE(info)
Definition: elf32.h:148
spinlock.h
uInt32
unsigned long int uInt32
Definition: objgfx30.h:49
_item_t
Definition: lists.h:35
fopen
fileDescriptor_t * fopen(const char *file, const char *flags)
Definition: file.c:395
vfs.h
kmod_load
uInt32 kmod_load(const char *kmod_file)
Definition: kmod.c:70
lists.h
string.h
PT_GNU_STACK
#define PT_GNU_STACK
Definition: elf_common.h:502
fileDescriptor
Definition: file.h:62
PT_DYNAMIC
#define PT_DYNAMIC
Definition: elf_common.h:493
fread
size_t fread(void *ptr, size_t size, size_t nmemb, fileDescriptor_t *fd)
Definition: file.c:297
kfree
void kfree(void *baseAddr)
Definition: kmalloc.c:342
_list_t
Definition: lists.h:41
strcmp
int strcmp(const char *str1, const char *str2)
assert
#define assert(e)
Definition: assert.h:64
assert.h
kmod_struct
Definition: kmod.h:36
vmm.h
PT_LOAD
#define PT_LOAD
Definition: elf_common.h:492
sched.h
kpanic
void kpanic(const char *fmt,...)
print panic message and halt system
Definition: kpanic.c:41
types.h
LD_START
#define LD_START
Definition: kmod.h:34
kpanic.h
taskStruct::id
pidType id
Definition: sched.h:63
vmm_findFreePage
uint32_t vmm_findFreePage(pidType pid)
Definition: vmm_memory.c:221
InsertItemAtFront
int InsertItemAtFront(List_t *TList, Item_t *kItem)
ELF32_R_SYM
#define ELF32_R_SYM(info)
Definition: elf32.h:147
R_386_32
#define R_386_32
Definition: elf_common.h:867
fclose
int fclose(fileDescriptor_t *fd)
Definition: file.c:533
kprintf.h
R_386_PC32
#define R_386_PC32
Definition: elf_common.h:868
InitializeList
List_t * InitializeList()
kmod.h
PAGE_DEFAULT
#define PAGE_DEFAULT
Definition: paging.h:68
vmm_remapPage
int vmm_remapPage(uint32_t, uint32_t, uint16_t, pidType, int haveLock)
Definition: paging.c:199
elfGetRelType
char * elfGetRelType(int)
Definition: elf.c:167
_current
kTask_t * _current
Definition: sched.c:50
_item_t::data
void * data
Definition: lists.h:38
name
const char * name
Definition: pci.c:37
CreateItem
Item_t * CreateItem()
kmalloc
void * kmalloc(uInt32 len)
Definition: kmalloc.c:241
memset
void * memset(void *dst, int c, size_t length)
kmod_add
uInt32 kmod_add(const char *kmod_file, const char *name)
Definition: kmod.c:45
kprintf
int kprintf(const char *,...)
Definition: kprintf.c:259
elf.h
kmalloc.h
R_386_RELATIVE
#define R_386_RELATIVE
Definition: elf_common.h:874
fseek
int fseek(fileDescriptor_t *tmpFd, long offset, int whence)
Definition: file.c:332
NULL
#define NULL
Definition: fat_string.h:17