DEADSOFTWARE

4637982a894c559e4b9713b97b84f7a86f4b872e
[bbcp.git] / BlackBox / _Linux_ / Lin / Rsrc / blackbox.c
2 /*
3 * C-startup and loader for BlackBox
4 * Implemented as the StdLoader.
5 */
8 #include <sys/mman.h>
10 #include <dlfcn.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 /* #include <malloc.h> */
15 #include <errno.h>
16 #include <fcntl.h>
18 /* the exact size (in bytes) of the executable part of the file. */
19 /* this constant needs to be updated everytime a change is made to this file */
20 #define exeSize 17028
23 #define pageSize 4096
25 /* fixup types */
26 #define absolute 100
27 #define relative 101
28 #define copy 102
29 #define table 103
30 #define tableend 104
31 #define deref 105
32 #define halfword 106
34 /* import types */
35 #define mConst 0x1
36 #define mTyp 0x2
37 #define mVar 0x3
38 #define mProc 0x4
39 #define mExported 4
41 #define any 1000000
43 #define init 0x10000
45 /* set to printf to debug and donothing to avoid debugging */
46 #define dprintf donothing
48 typedef void (*BodyProc)();
49 typedef char String[256];
51 typedef struct Type {
52 int size;
53 struct Module* mod;
54 int id;
55 int base[16]; /* should be ARRAY 16 OF TYPE */
56 int fields; /* should be Directory* */
57 int ptroffs[any];
58 } Type;
60 typedef struct Object{
61 int fprint;
62 int offs;
63 int id;
64 Type* ostruct;
65 } Object;
67 typedef struct Directory{
68 int num;
69 Object obj[any];
70 } Directory;
72 typedef struct Module{ /* has to be exact copy of Kernel.Module */
73 struct Module *next;
74 int opts;
75 int refcnt;
76 short compTime[6], loadTime[6];
77 int ext;
78 int term; /* actually a pointer to type Command */
79 int nofimps, nofptrs;
80 int csize, dsize, rsize;
81 int code, data, refs;
82 int procBase, varBase; /* meta base addresses */
83 char* names; /* names[0] = 0X */
84 int* ptrs;
85 struct Module* imports;
86 Directory* export;
87 char name[256];
88 } Module;
90 typedef struct ImpList
91 {
92 struct ImpList* next;
93 String name;
94 } ImpList;
96 typedef struct ModSpec
97 {
98 ImpList* imp;
99 String name;
100 int start, hs, ms, ds, cs, vs, mad, dad;
101 } ModSpec;
103 typedef struct BootInfo
105 Module* modList;
106 int argc;
107 char** argv;
108 } BootInfo;
110 const char bbfile[] = "./bb.boot";
112 FILE* f;
113 int nofMods;
114 String kernel, mainmod;
115 ModSpec mod;
116 Module *modlist;
117 BootInfo* bootInfo;
118 int newRecAdr, newArrAdr;
119 int newRecFP, newArrFP;
121 int zerofd;
123 int donothing(char* fmt, ...)
127 void DumpMod()
128 {
129 dprintf("\n\n---- Mod info:\n");
130 dprintf(" hs, ms, ds, cs, vs = %d, %d, %d, %d, %d\n",
131 mod.hs, mod.ms, mod.ds, mod.cs, mod.vs);
132 dprintf(" mad, dad = %d, %d\n\n", mod.mad, mod.dad);
136 void RegisterModule()
138 Module* m;
139 m = (Module*)mod.dad;
140 m->next = modlist;
141 modlist = m;
142 /*
143 if (modlist == NULL){
144 modlist = m;
145 } else {
146 last->next = m;
147 last = m;
149 last->next = NULL;
150 */
151 dprintf("Registred module %s\n", mod.name);
154 void PrintMods()
156 Module* ml;
157 ml = modlist;
158 dprintf("Loaded Modules\n");
159 while (ml != NULL){
160 dprintf("mod name: %s\n", ml->name);
161 ml = ml->next;
163 dprintf("end of list\n");
167 Module* ThisModule(char* name)
169 Module* ml;
170 ml = modlist;
171 while ((ml != NULL) && (strcmp(ml->name, name) != 0)){
172 ml = ml->next;
174 return ml;
177 Object* ThisObject(Module* mod, char* name)
179 int l, r, m;
180 char* p;
181 l = 0; r = mod->export->num;
182 while (l < r){
183 m = (l + r) / 2;
184 p = (char*) &(mod->names[mod->export->obj[m].id / 256]);
185 if (strcmp(p, name) == 0)
186 return (Object*)&(mod->export->obj[m]);
187 if (strcmp(p, name) < 0)
188 l = m + 1;
189 else
190 r = m;
192 return NULL;
195 Object* ThisDesc(Module* mod, int fprint)
197 int i, n;
198 i = 0; n = mod->export->num;
199 while ((i < n) && (mod->export->obj[i].id / 256 == 0))
201 if (mod->export->obj[i].offs == fprint)
202 return (Object*)&(mod->export->obj[i]);
203 i++;
205 return NULL;
208 int LoadDll (char* name)
211 void *handle;
212 dprintf("loading: %s\n", name);
213 if ((handle = dlopen(name, RTLD_LAZY + RTLD_GLOBAL)) == NULL) {
214 printf("LoadDll: failed to load lib %s\n", name);
215 printf(" - dlerror: %s\n", dlerror());
216 exit(-1);
218 return handle != NULL;
222 int ThisDllObj (int mode, int fprint, char* dll, char* name)
224 void *handle;
225 int ad = 0;
226 if ((mode == mVar) || (mode == mProc)){
227 if ((handle = dlopen(dll, RTLD_LAZY + RTLD_GLOBAL)) == NULL) {
228 printf("ThisDllObj: lib %s not found\n", dll);
229 printf(" - dlerror: %s\n", dlerror());
230 exit(-1);
231 } else {
232 ad = (int)dlsym((void *) handle, name);
233 if (ad == 0) {
234 printf("ThisDllObj: symbol %s not found\n", name); exit(-1);
238 return ad;
241 int Read4 ()
243 unsigned char b;
244 int w;
245 b = fgetc(f); w = b % 256;
246 b = fgetc(f); w = w + 0x100 * (b % 256);
247 b = fgetc(f); w = w + 0x10000 * (b % 256);
248 b = fgetc(f); w = w + 0x1000000 * b;
249 return w;
252 int RNum()
254 char b;
255 int s, y;
256 s = 0; y = 0;
257 b = fgetc(f);
258 while (b < 0)
260 y = y + ((b + 128) << s);
261 s = s + 7;
262 b = fgetc(f);
264 return (((b + 64) % 128 - 64) << s) + y;
267 void ReadName (char* str)
269 unsigned char b;
270 int i;
271 i = 0; b = fgetc(f);
272 while (b != 0)
274 str[i] = b; i++; b = fgetc(f);
276 str[i] = 0;
279 void Fixup (int adr)
281 int link, offset, linkadr, n, x, t;
283 dprintf("fixup: %X ", adr);
284 link = RNum();
285 while (link != 0)
287 offset = RNum();
288 dprintf("+%d: ", offset);
289 while (link != 0)
291 if (link > 0)
293 dprintf("c");
294 linkadr = mod.mad + mod.ms + link;
296 else
298 dprintf("d");
299 link = -link;
300 if (link < mod.ms)
301 linkadr = mod.mad + link;
302 else
303 linkadr = mod.dad + link - mod.ms;
305 dprintf("%X ", link);
307 /*
308 t = *(char*)(linkadr + 3);
309 n = *(int*)linkadr;
310 n = n << 8; n = n >> 8;
311 */
312 x = *(int*)linkadr;
313 t = x / 0x1000000;
314 n = (x + 0x800000) % 0x1000000 - 0x800000;
316 switch (t) {
317 case absolute: x = adr + offset; break;
318 case relative: x = adr + offset - linkadr -4; break;
319 case copy: x = *(int*)(adr + offset); break;
320 case table: x = adr + n; n = link + 4; break;
321 case tableend: x = adr + n; n = 0; break;
322 case deref: x = *(int*)(adr + 2); x = x + offset; break;
323 case halfword:
324 printf("fixup: halfword not implemented\n");
325 break;
326 default:
327 printf("fixup error(link=%d, offset=%d, linkadr=%d, t=%d, x=%d)\n",
328 link, offset, linkadr, t, x);
329 return;
330 }
331 *(int*)linkadr = x;
332 link = n;
334 link = RNum();
336 dprintf("\n");
339 int ReadBootHeader()
341 int tag, version;
343 fseek(f, exeSize, SEEK_SET);
344 tag = Read4();
345 version = Read4();
346 if ((tag != 0x3A4B5C6D) || (version != 0))
348 return 0;
350 nofMods = Read4();
351 dprintf("Linked modules: %d\n", nofMods);
352 ReadName(kernel);
353 dprintf("kernel: %s\n", kernel);
354 ReadName(mainmod);
355 dprintf("main: %s\n", mainmod);
356 newRecFP = Read4(); newRecAdr = 0;
357 newArrFP = Read4(); newArrAdr = 0;
358 mod.start = ftell(f);
359 return 1;
362 void * MEMALLOC (size_t len)
364 void * res;
366 res = mmap(0, len, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANON, zerofd, 0);
367 if (res == MAP_FAILED) {
368 res = NULL;
369 } else {
370 bzero(res, len);
372 return res;
375 int ReadHeader ()
377 int ofTag, i, nofImps, processor;
378 char str[80];
379 ImpList *imp, *last;
380 char* n;
382 ofTag = Read4();
383 if (ofTag != 0x6F4F4346)
385 printf("wrong object file version\n");
386 return 0;
388 processor = Read4();
389 mod.hs = Read4();
390 mod.ms = Read4();
391 mod.ds = Read4();
392 mod.cs = Read4();
393 mod.vs = Read4();
394 dprintf("File tag: %d ", ofTag); dprintf("Processor: %d\n", processor);
395 dprintf("Header size: %d ", mod.hs);
396 dprintf("Meta size: %d ", mod.ms);
397 dprintf("Desc size: %d ", mod.ds );
398 dprintf("Code size: %d ", mod.cs);
399 dprintf("Data size: %d\n", mod.vs);
400 nofImps = RNum(); dprintf("Nof imports: %d\n", nofImps);
401 ReadName(mod.name); dprintf("Module name: %s\n", mod.name);
402 mod.imp = NULL;
403 for (i = 0; i < nofImps; i++)
405 imp = (ImpList*)MEMALLOC(sizeof(ImpList));
406 ReadName(imp->name);
407 if (mod.imp == NULL)
408 mod.imp = imp;
409 else
410 last->next = imp;
411 last = imp;
412 last->next = NULL;
413 dprintf("Import %d: %s\n", i, imp->name);
414 if ((imp->name[0] == '$') && (imp->name[1] == '$'))
415 strcpy(imp->name, "Kernel");
416 if (imp->name[0] == '$'){
417 n = imp->name;
418 n++;
419 if (!LoadDll(n)){
420 printf("Could not load lib: %s\n", (char *)(&(imp->name[1])));
421 return 0;
425 dprintf("Pos: %d\n", ftell(f));
426 return 1;
429 int ReadModule ()
431 char *dp, *mp;
432 unsigned int cnt;
433 ImpList* imp;
434 int x, fp, opt, link, ofp, imptab, a;
435 Module *desc, *k;
436 String name;
437 Object* obj;
438 int isLib;
439 char* im;
441 mod.dad = (int) MEMALLOC(mod.ds);
442 mod.mad = (int) MEMALLOC(mod.ms + mod.cs + mod.vs);
443 if ((mod.dad == 0) || (mod.mad == 0))
445 printf("BootLoader: Couldn't initalize heap\n");
446 free((void*)mod.dad);
447 free((void*)mod.mad);
448 return 0;
450 dp = (char*) mod.dad;
451 mp = (char*) mod.mad;
452 fseek(f, mod.start + mod.hs, SEEK_SET);
453 dprintf("ReadModule after fseek pos: %d\n", ftell(f));
454 cnt = fread(mp, 1, mod.ms, f);
455 dprintf("Read meta bulk (%d bytes. New pos: %d)\n", cnt, ftell(f));
456 cnt = fread(dp, 1, mod.ds, f);
457 dprintf("Read desc bulk (%d bytes. New pos: %d)\n", cnt, ftell(f));
458 mp = (char*)(mod.mad + mod.ms);
459 cnt = fread(mp, 1, mod.cs, f);
460 dprintf("Read code bulk (%d bytes. New pos: %d)\n", cnt, ftell(f));
462 DumpMod();
464 dprintf("before fixup: pos = %d\n", ftell(f));
466 if ((!newRecAdr) || (!newArrAdr)){
467 k = ThisModule(kernel);
468 if (k != NULL){
469 /* obj = ThisDesc(k, newRecFP);*/
470 obj = ThisObject(k, "NewRec");
471 if (obj != NULL)
472 newRecAdr = k->procBase + obj->offs;
473 /* obj = ThisDesc(k, newArrFP);*/
474 obj = ThisObject(k, "NewArr");
475 if (obj != NULL)
476 newArrAdr = k->procBase + obj->offs;
477 dprintf("newRecFP: %X newArrFP: %X\n", newRecFP, newArrFP);
478 dprintf("newRecAdr: %X newArrAdr: %X\n", newRecAdr, newArrAdr);
479 } else {
480 dprintf("no kernel before %s.\n", mod.name);
483 Fixup(newRecAdr);
484 Fixup(newArrAdr);
485 Fixup(mod.mad);
486 Fixup(mod.dad);
487 Fixup(mod.mad + mod.ms);
488 Fixup(mod.mad + mod.ms + mod.cs);
489 dprintf("after fixup: pos = %d\n", ftell(f));
490 imp = mod.imp; imptab = (int)((Module*)(mod.dad))->imports;
491 while (imp != NULL){
492 x = RNum();
493 if ((imp->name[0] == '$') && (imp->name[1] == '$'))
494 printf("should be Kerneln");
495 if (imp->name[0] == '$')
496 isLib = 1;
497 else{
498 isLib = 0;
499 desc = ThisModule(imp->name);
500 if (desc == NULL){
501 printf("invalid import list\n");
502 return 0;
505 while (x != 0) {
506 ReadName(name); fp = RNum(); opt = 0;
507 if (!isLib) {
508 if (name[0] == 0)
509 obj = ThisDesc(desc, fp);
510 else
511 obj = ThisObject(desc, name);
512 if ((obj != NULL) && (obj->id % 16 == x)){
513 ofp = obj->fprint;
514 switch (x){
515 case mTyp:
516 opt = RNum();
517 if (opt % 2 == 1) ofp = obj->offs;
518 if ((opt > 1) && ((obj->id / 16) % 16 != mExported)){
519 printf("object not found (%s)\n", imp->name);
520 return 0;
522 Fixup((int)obj->ostruct);
523 break;
524 case mVar:
525 Fixup(desc->varBase + obj->offs);
526 break;
527 case mProc:
528 Fixup(desc->procBase + obj->offs);
530 if (ofp != fp){
531 printf("illigal foot print (%s)\n", imp->name);
532 return 0;
534 } else {
535 if (obj == NULL) printf("obj == NULL\n");
536 printf("descriptor not found (%s, x: %d, id: %d)\n", name, x, obj->id);
537 return 0;
539 }else{
540 if ((x == mVar) || (x == mProc)){
541 im = imp->name;
542 im++;
543 a = ThisDllObj(x, fp, im, name);
544 if (a != 0)
545 Fixup(a);
546 else{
547 printf("ReadModule: Object not found: %s\n", name);
548 return 0;
550 } else {
551 if (x == mTyp) {
552 opt = RNum();
553 x = RNum();
554 if (x != 0) {
555 printf("ReadModule: Object not found: %s\n", name);
556 return 0;
561 x = RNum();
563 *(int*)imptab = (int)desc; imptab += 4;
564 imp = imp->next;
567 mod.start = ftell(f);
568 return 1;
571 int MOD (int x, int y)
573 int res;
575 if (x >= 0) {
576 res = x % y;
577 } else {
578 res = x - y * ((x + 1) / y - 1);
580 return res;
583 int main (int argc, char *argv[])
585 int i, ok;
586 BodyProc body;
587 int callBackAdr;
588 Module *k, *m;
590 zerofd = open("/dev/zero", O_RDWR);
591 if (zerofd == -1) {
592 printf("open /dev/zero failed: %s\n", strerror(errno));
593 return 101;
596 modlist = NULL;
597 dprintf("initializing BlackBox for Linux...\n");
599 /*f = fopen(bbfile, "rb");*/
600 f = fopen(argv[0], "r");
601 if (f != NULL)
603 if (ReadBootHeader())
605 i = 0; ok = 1;
606 while ((i < nofMods) && (ok)){
607 ok = ReadHeader();
608 if (ok) {
609 ok = ReadModule();
610 if (ok)
611 RegisterModule();
612 else
613 printf("Incorrect module: %s\n", mod.name);
614 } else
615 printf("Incorrect header: %s\n", mod.name);
616 i++;
618 fclose(f);
619 if (ok) {
620 k = ThisModule(kernel);
621 m = ThisModule(mainmod);
622 if (k == NULL)
623 printf("no kernel\n");
624 else
626 if (m == NULL)
627 printf("no main module");
628 else
630 /* assign the boot info to first variable in Kernel */
631 bootInfo = MEMALLOC(sizeof(BootInfo));
632 bootInfo->modList = modlist;
633 bootInfo->argc = argc;
634 bootInfo->argv = argv;
635 *((int*)(k->varBase)) = (int)bootInfo;
636 dprintf("before body\n");
637 body = (BodyProc)(m->code);
638 k->opts = k->opts | init; /* include init in opts */
639 /*
640 ok = mprotect(
641 (void *)(((m->code) / pageSize) * pageSize),
642 (((m->csize) + MOD(m->code, pageSize) - 1) / pageSize) * pageSize + pageSize,
643 PROT_READ|PROT_WRITE|PROT_EXEC);
644 if (ok != 0){
645 printf("mprotect failed: %s\n", strerror(errno));
646 return 100;
648 */
649 body();
650 dprintf("after body\n");
653 PrintMods();
655 } else
656 printf("Invalid BlackBox executable, make sure that the constant exeSize is correctly set\n");
658 } else
659 printf("Couldn't find file: %s\n", bbfile);