DEADSOFTWARE

50dab7321053814bd9b0aada642cf4cec58c964c
[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>
16 /* the exact size (in bytes) of the executable part of the file. */
17 /* this constant needs to be updated everytime a change is made to this file */
18 #define exeSize 16860
21 #define pageSize 4096
23 /* fixup types */
24 #define absolute 100
25 #define relative 101
26 #define copy 102
27 #define table 103
28 #define tableend 104
29 #define deref 105
30 #define halfword 106
32 /* import types */
33 #define mConst 0x1
34 #define mTyp 0x2
35 #define mVar 0x3
36 #define mProc 0x4
37 #define mExported 4
39 #define any 1000000
41 #define init 0x10000
43 /* set to printf to debug and donothing to avoid debugging */
44 #define dprintf donothing
46 typedef void (*BodyProc)();
47 typedef char String[256];
49 typedef struct Type {
50 int size;
51 struct Module* mod;
52 int id;
53 int base[16]; /* should be ARRAY 16 OF TYPE */
54 int fields; /* should be Directory* */
55 int ptroffs[any];
56 } Type;
58 typedef struct Object{
59 int fprint;
60 int offs;
61 int id;
62 Type* ostruct;
63 } Object;
65 typedef struct Directory{
66 int num;
67 Object obj[any];
68 } Directory;
70 typedef struct Module{ /* has to be exact copy of Kernel.Module */
71 struct Module *next;
72 int opts;
73 int refcnt;
74 short compTime[6], loadTime[6];
75 int ext;
76 int term; /* actually a pointer to type Command */
77 int nofimps, nofptrs;
78 int csize, dsize, rsize;
79 int code, data, refs;
80 int procBase, varBase; /* meta base addresses */
81 char* names; /* names[0] = 0X */
82 int* ptrs;
83 struct Module* imports;
84 Directory* export;
85 char name[256];
86 } Module;
88 typedef struct ImpList
89 {
90 struct ImpList* next;
91 String name;
92 } ImpList;
94 typedef struct ModSpec
95 {
96 ImpList* imp;
97 String name;
98 int start, hs, ms, ds, cs, vs, mad, dad;
99 } ModSpec;
101 typedef struct BootInfo
103 Module* modList;
104 int argc;
105 char** argv;
106 } BootInfo;
108 const char bbfile[] = "./bb.boot";
110 FILE* f;
111 int nofMods;
112 String kernel, mainmod;
113 ModSpec mod;
114 Module *modlist;
115 BootInfo* bootInfo;
116 int newRecAdr, newArrAdr;
117 int newRecFP, newArrFP;
119 int donothing(char* fmt, ...)
123 void DumpMod()
124 {
125 dprintf("\n\n---- Mod info:\n");
126 dprintf(" hs, ms, ds, cs, vs = %d, %d, %d, %d, %d\n",
127 mod.hs, mod.ms, mod.ds, mod.cs, mod.vs);
128 dprintf(" mad, dad = %d, %d\n\n", mod.mad, mod.dad);
132 void RegisterModule()
134 Module* m;
135 m = (Module*)mod.dad;
136 m->next = modlist;
137 modlist = m;
138 /*
139 if (modlist == NULL){
140 modlist = m;
141 } else {
142 last->next = m;
143 last = m;
145 last->next = NULL;
146 */
147 dprintf("Registred module %s\n", mod.name);
150 void PrintMods()
152 Module* ml;
153 ml = modlist;
154 dprintf("Loaded Modules\n");
155 while (ml != NULL){
156 dprintf("mod name: %s\n", ml->name);
157 ml = ml->next;
159 dprintf("end of list\n");
163 Module* ThisModule(char* name)
165 Module* ml;
166 ml = modlist;
167 while ((ml != NULL) && (strcmp(ml->name, name) != 0)){
168 ml = ml->next;
170 return ml;
173 Object* ThisObject(Module* mod, char* name)
175 int l, r, m;
176 char* p;
177 l = 0; r = mod->export->num;
178 while (l < r){
179 m = (l + r) / 2;
180 p = (char*) &(mod->names[mod->export->obj[m].id / 256]);
181 if (strcmp(p, name) == 0)
182 return (Object*)&(mod->export->obj[m]);
183 if (strcmp(p, name) < 0)
184 l = m + 1;
185 else
186 r = m;
188 return NULL;
191 Object* ThisDesc(Module* mod, int fprint)
193 int i, n;
194 i = 0; n = mod->export->num;
195 while ((i < n) && (mod->export->obj[i].id / 256 == 0))
197 if (mod->export->obj[i].offs == fprint)
198 return (Object*)&(mod->export->obj[i]);
199 i++;
201 return NULL;
204 int LoadDll (char* name)
207 void *handle;
208 dprintf("loading: %s\n", name);
209 if ((handle = dlopen(name, RTLD_LAZY + RTLD_GLOBAL)) == NULL) {
210 printf("LoadDll: failed to load lib %s\n", name);
211 printf(" - dlerror: %s\n", dlerror());
212 exit(-1);
214 return handle != NULL;
218 int ThisDllObj (int mode, int fprint, char* dll, char* name)
220 void *handle;
221 int ad = 0;
222 if ((mode == mVar) || (mode == mProc)){
223 if ((handle = dlopen(dll, RTLD_LAZY + RTLD_GLOBAL)) == NULL) {
224 printf("ThisDllObj: lib %s not found\n", dll);
225 printf(" - dlerror: %s\n", dlerror());
226 exit(-1);
227 } else {
228 ad = (int)dlsym((void *) handle, name);
229 if (ad == 0) {
230 printf("ThisDllObj: symbol %s not found\n", name); exit(-1);
234 return ad;
237 int Read4 ()
239 unsigned char b;
240 int w;
241 b = fgetc(f); w = b % 256;
242 b = fgetc(f); w = w + 0x100 * (b % 256);
243 b = fgetc(f); w = w + 0x10000 * (b % 256);
244 b = fgetc(f); w = w + 0x1000000 * b;
245 return w;
248 int RNum()
250 char b;
251 int s, y;
252 s = 0; y = 0;
253 b = fgetc(f);
254 while (b < 0)
256 y = y + ((b + 128) << s);
257 s = s + 7;
258 b = fgetc(f);
260 return (((b + 64) % 128 - 64) << s) + y;
263 void ReadName (char* str)
265 unsigned char b;
266 int i;
267 i = 0; b = fgetc(f);
268 while (b != 0)
270 str[i] = b; i++; b = fgetc(f);
272 str[i] = 0;
275 void Fixup (int adr)
277 int link, offset, linkadr, n, x, t;
279 dprintf("fixup: %X ", adr);
280 link = RNum();
281 while (link != 0)
283 offset = RNum();
284 dprintf("+%d: ", offset);
285 while (link != 0)
287 if (link > 0)
289 dprintf("c");
290 linkadr = mod.mad + mod.ms + link;
292 else
294 dprintf("d");
295 link = -link;
296 if (link < mod.ms)
297 linkadr = mod.mad + link;
298 else
299 linkadr = mod.dad + link - mod.ms;
301 dprintf("%X ", link);
303 /*
304 t = *(char*)(linkadr + 3);
305 n = *(int*)linkadr;
306 n = n << 8; n = n >> 8;
307 */
308 x = *(int*)linkadr;
309 t = x / 0x1000000;
310 n = (x + 0x800000) % 0x1000000 - 0x800000;
312 switch (t) {
313 case absolute: x = adr + offset; break;
314 case relative: x = adr + offset - linkadr -4; break;
315 case copy: x = *(int*)(adr + offset); break;
316 case table: x = adr + n; n = link + 4; break;
317 case tableend: x = adr + n; n = 0; break;
318 case deref: x = *(int*)(adr + 2); x = x + offset; break;
319 case halfword:
320 printf("fixup: halfword not implemented\n");
321 break;
322 default:
323 printf("fixup error(link=%d, offset=%d, linkadr=%d, t=%d, x=%d)\n",
324 link, offset, linkadr, t, x);
325 return;
326 }
327 *(int*)linkadr = x;
328 link = n;
330 link = RNum();
332 dprintf("\n");
335 int ReadBootHeader()
337 int tag, version;
339 fseek(f, exeSize, SEEK_SET);
340 tag = Read4();
341 version = Read4();
342 if ((tag != 0x3A4B5C6D) || (version != 0))
344 return 0;
346 nofMods = Read4();
347 dprintf("Linked modules: %d\n", nofMods);
348 ReadName(kernel);
349 dprintf("kernel: %s\n", kernel);
350 ReadName(mainmod);
351 dprintf("main: %s\n", mainmod);
352 newRecFP = Read4(); newRecAdr = 0;
353 newArrFP = Read4(); newArrAdr = 0;
354 mod.start = ftell(f);
355 return 1;
358 int ReadHeader ()
360 int ofTag, i, nofImps, processor;
361 char str[80];
362 ImpList *imp, *last;
363 char* n;
365 ofTag = Read4();
366 if (ofTag != 0x6F4F4346)
368 printf("wrong object file version\n");
369 return 0;
371 processor = Read4();
372 mod.hs = Read4();
373 mod.ms = Read4();
374 mod.ds = Read4();
375 mod.cs = Read4();
376 mod.vs = Read4();
377 dprintf("File tag: %d ", ofTag); dprintf("Processor: %d\n", processor);
378 dprintf("Header size: %d ", mod.hs);
379 dprintf("Meta size: %d ", mod.ms);
380 dprintf("Desc size: %d ", mod.ds );
381 dprintf("Code size: %d ", mod.cs);
382 dprintf("Data size: %d\n", mod.vs);
383 nofImps = RNum(); dprintf("Nof imports: %d\n", nofImps);
384 ReadName(mod.name); dprintf("Module name: %s\n", mod.name);
385 mod.imp = NULL;
386 for (i = 0; i < nofImps; i++)
388 imp = (ImpList*)calloc(1, sizeof(ImpList));
389 ReadName(imp->name);
390 if (mod.imp == NULL)
391 mod.imp = imp;
392 else
393 last->next = imp;
394 last = imp;
395 last->next = NULL;
396 dprintf("Import %d: %s\n", i, imp->name);
397 if ((imp->name[0] == '$') && (imp->name[1] == '$'))
398 strcpy(imp->name, "Kernel");
399 if (imp->name[0] == '$'){
400 n = imp->name;
401 n++;
402 if (!LoadDll(n)){
403 printf("Could not load lib: %s\n", (char *)(&(imp->name[1])));
404 return 0;
408 dprintf("Pos: %d\n", ftell(f));
409 return 1;
412 int ReadModule ()
414 char *dp, *mp;
415 unsigned int cnt;
416 ImpList* imp;
417 int x, fp, opt, link, ofp, imptab, a;
418 Module *desc, *k;
419 String name;
420 Object* obj;
421 int isLib;
422 char* im;
424 mod.dad = (int) calloc(1, mod.ds);
425 mod.mad = (int) calloc(1, mod.ms + mod.cs + mod.vs);
426 if ((mod.dad == 0) || (mod.mad == 0))
428 printf("BootLoader: Couldn't initalize heap\n");
429 free((void*)mod.dad);
430 free((void*)mod.mad);
431 return 0;
433 dp = (char*) mod.dad;
434 mp = (char*) mod.mad;
435 fseek(f, mod.start + mod.hs, SEEK_SET);
436 dprintf("ReadModule after fseek pos: %d\n", ftell(f));
437 cnt = fread(mp, 1, mod.ms, f);
438 dprintf("Read meta bulk (%d bytes. New pos: %d)\n", cnt, ftell(f));
439 cnt = fread(dp, 1, mod.ds, f);
440 dprintf("Read desc bulk (%d bytes. New pos: %d)\n", cnt, ftell(f));
441 mp = (char*)(mod.mad + mod.ms);
442 cnt = fread(mp, 1, mod.cs, f);
443 dprintf("Read code bulk (%d bytes. New pos: %d)\n", cnt, ftell(f));
445 DumpMod();
447 dprintf("before fixup: pos = %d\n", ftell(f));
449 if ((!newRecAdr) || (!newArrAdr)){
450 k = ThisModule(kernel);
451 if (k != NULL){
452 /* obj = ThisDesc(k, newRecFP);*/
453 obj = ThisObject(k, "NewRec");
454 if (obj != NULL)
455 newRecAdr = k->procBase + obj->offs;
456 /* obj = ThisDesc(k, newArrFP);*/
457 obj = ThisObject(k, "NewArr");
458 if (obj != NULL)
459 newArrAdr = k->procBase + obj->offs;
460 dprintf("newRecFP: %X newArrFP: %X\n", newRecFP, newArrFP);
461 dprintf("newRecAdr: %X newArrAdr: %X\n", newRecAdr, newArrAdr);
462 } else {
463 dprintf("no kernel before %s.\n", mod.name);
466 Fixup(newRecAdr);
467 Fixup(newArrAdr);
468 Fixup(mod.mad);
469 Fixup(mod.dad);
470 Fixup(mod.mad + mod.ms);
471 Fixup(mod.mad + mod.ms + mod.cs);
472 dprintf("after fixup: pos = %d\n", ftell(f));
473 imp = mod.imp; imptab = (int)((Module*)(mod.dad))->imports;
474 while (imp != NULL){
475 x = RNum();
476 if ((imp->name[0] == '$') && (imp->name[1] == '$'))
477 printf("should be Kerneln");
478 if (imp->name[0] == '$')
479 isLib = 1;
480 else{
481 isLib = 0;
482 desc = ThisModule(imp->name);
483 if (desc == NULL){
484 printf("invalid import list\n");
485 return 0;
488 while (x != 0) {
489 ReadName(name); fp = RNum(); opt = 0;
490 if (!isLib) {
491 if (name[0] == 0)
492 obj = ThisDesc(desc, fp);
493 else
494 obj = ThisObject(desc, name);
495 if ((obj != NULL) && (obj->id % 16 == x)){
496 ofp = obj->fprint;
497 switch (x){
498 case mTyp:
499 opt = RNum();
500 if (opt % 2 == 1) ofp = obj->offs;
501 if ((opt > 1) && ((obj->id / 16) % 16 != mExported)){
502 printf("object not found (%s)\n", imp->name);
503 return 0;
505 Fixup((int)obj->ostruct);
506 break;
507 case mVar:
508 Fixup(desc->varBase + obj->offs);
509 break;
510 case mProc:
511 Fixup(desc->procBase + obj->offs);
513 if (ofp != fp){
514 printf("illigal foot print (%s)\n", imp->name);
515 return 0;
517 } else {
518 if (obj == NULL) printf("obj == NULL\n");
519 printf("descriptor not found (%s, x: %d, id: %d)\n", name, x, obj->id);
520 return 0;
522 }else{
523 if ((x == mVar) || (x == mProc)){
524 im = imp->name;
525 im++;
526 a = ThisDllObj(x, fp, im, name);
527 if (a != 0)
528 Fixup(a);
529 else{
530 printf("ReadModule: Object not found: %s\n", name);
531 return 0;
533 } else {
534 if (x == mTyp) {
535 opt = RNum();
536 x = RNum();
537 if (x != 0) {
538 printf("ReadModule: Object not found: %s\n", name);
539 return 0;
544 x = RNum();
546 *(int*)imptab = (int)desc; imptab += 4;
547 imp = imp->next;
550 mod.start = ftell(f);
551 return 1;
554 int MOD (int x, int y)
556 int res;
558 if (x >= 0) {
559 res = x % y;
560 } else {
561 res = x - y * ((x + 1) / y - 1);
563 return res;
566 int main (int argc, char *argv[])
568 int i, ok;
569 BodyProc body;
570 int callBackAdr;
571 Module *k, *m;
573 modlist = NULL;
574 dprintf("initializing BlackBox for Linux...\n");
575 /*f = fopen(bbfile, "rb");*/
576 f = fopen(argv[0], "r");
577 if (f != NULL)
579 if (ReadBootHeader())
581 i = 0; ok = 1;
582 while ((i < nofMods) && (ok)){
583 ok = ReadHeader();
584 if (ok) {
585 ok = ReadModule();
586 if (ok)
587 RegisterModule();
588 else
589 printf("Incorrect module: %s\n", mod.name);
590 } else
591 printf("Incorrect header: %s\n", mod.name);
592 i++;
594 fclose(f);
595 if (ok) {
596 k = ThisModule(kernel);
597 m = ThisModule(mainmod);
598 if (k == NULL)
599 printf("no kernel\n");
600 else
602 if (m == NULL)
603 printf("no main module");
604 else
606 /* assign the boot info to first variable in Kernel */
607 bootInfo = calloc(1, sizeof(BootInfo));
608 bootInfo->modList = modlist;
609 bootInfo->argc = argc;
610 bootInfo->argv = argv;
611 *((int*)(k->varBase)) = (int)bootInfo;
612 dprintf("before body\n");
613 body = (BodyProc)(m->code);
614 k->opts = k->opts | init; /* include init in opts */
615 ok = mprotect(
616 (void *)(((m->code) / pageSize) * pageSize),
617 (((m->csize) + MOD(m->code, pageSize) - 1) / pageSize) * pageSize + pageSize,
618 PROT_READ|PROT_WRITE|PROT_EXEC);
619 if (ok != 0){
620 printf("mprotect failed!\n");
621 return 100;
623 body();
624 dprintf("after body\n");
627 PrintMods();
629 } else
630 printf("Invalid BlackBox executable, make sure that the constant exeSize is correctly set\n");
632 } else
633 printf("Couldn't find file: %s\n", bbfile);