DEADSOFTWARE

moved to wiki
[bbcp.git] / ubuntu / Lin / Rsrc / blackbox.c
2 /*
3 * C-startup and loader for BlackBox
4 * Implemented as the StdLoader.
5 */
8 #include <dlfcn.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <malloc.h>
14 /* the exact size (in bytes) of the executable part of the file. */
15 /* this constant needs to be updated everytime a change is made to this file */
16 #define exeSize 21399
19 /* fixup types */
20 #define absolute 100
21 #define relative 101
22 #define copy 102
23 #define table 103
24 #define tableend 104
25 #define deref 105
26 #define halfword 106
28 /* import types */
29 #define mConst 0x1
30 #define mTyp 0x2
31 #define mVar 0x3
32 #define mProc 0x4
33 #define mExported 4
35 #define any 1000000
37 #define init 0x10000
39 /* set to printf to debug and donothing to avoid debugging */
40 #define dprintf donothing
42 typedef void (*BodyProc)();
43 typedef char String[256];
45 typedef struct Type {
46 int size;
47 struct Module* mod;
48 int id;
49 int base[16]; /* should be ARRAY 16 OF TYPE */
50 int fields; /* should be Directory* */
51 int ptroffs[any];
52 } Type;
54 typedef struct Object{
55 int fprint;
56 int offs;
57 int id;
58 Type* ostruct;
59 } Object;
61 typedef struct Directory{
62 int num;
63 Object obj[any];
64 } Directory;
66 typedef struct Module{ /* has to be exact copy of Kernel.Module */
67 struct Module *next;
68 int opts;
69 int refcnt;
70 short compTime[6], loadTime[6];
71 int ext;
72 int term; /* actually a pointer to type Command */
73 int nofimps, nofptrs;
74 int csize, dsize, rsize;
75 int code, data, refs;
76 int procBase, varBase; /* meta base addresses */
77 char* names; /* names[0] = 0X */
78 int* ptrs;
79 struct Module* imports;
80 Directory* export;
81 char name[256];
82 } Module;
84 typedef struct ImpList
85 {
86 struct ImpList* next;
87 String name;
88 } ImpList;
90 typedef struct ModSpec
91 {
92 ImpList* imp;
93 String name;
94 int start, hs, ms, ds, cs, vs, mad, dad;
95 } ModSpec;
97 typedef struct BootInfo
98 {
99 Module* modList;
100 int argc;
101 char** argv;
102 } BootInfo;
104 const char bbfile[] = "./bb.boot";
106 FILE* f;
107 int nofMods;
108 String kernel, mainmod;
109 ModSpec mod;
110 Module *modlist;
111 BootInfo* bootInfo;
112 int newRecAdr, newArrAdr;
113 int newRecFP, newArrFP;
115 int donothing(char* fmt, ...)
119 void DumpMod()
120 {
121 dprintf("\n\n---- Mod info:\n");
122 dprintf(" hs, ms, ds, cs, vs = %d, %d, %d, %d, %d\n",
123 mod.hs, mod.ms, mod.ds, mod.cs, mod.vs);
124 dprintf(" mad, dad = %d, %d\n\n", mod.mad, mod.dad);
128 void RegisterModule()
130 Module* m;
131 m = (Module*)mod.dad;
132 m->next = modlist;
133 modlist = m;
134 /*
135 if (modlist == NULL){
136 modlist = m;
137 } else {
138 last->next = m;
139 last = m;
141 last->next = NULL;
142 */
143 dprintf("Registred module %s\n", mod.name);
146 void PrintMods()
148 Module* ml;
149 ml = modlist;
150 dprintf("Loaded Modules\n");
151 while (ml != NULL){
152 dprintf("mod name: %s\n", ml->name);
153 ml = ml->next;
155 dprintf("end of list\n");
159 Module* ThisModule(char* name)
161 Module* ml;
162 ml = modlist;
163 while ((ml != NULL) && (strcmp(ml->name, name) != 0)){
164 ml = ml->next;
166 return ml;
169 Object* ThisObject(Module* mod, char* name)
171 int l, r, m;
172 char* p;
173 l = 0; r = mod->export->num;
174 while (l < r){
175 m = (l + r) / 2;
176 p = (char*) &(mod->names[mod->export->obj[m].id / 256]);
177 if (strcmp(p, name) == 0)
178 return (Object*)&(mod->export->obj[m]);
179 if (strcmp(p, name) < 0)
180 l = m + 1;
181 else
182 r = m;
184 return NULL;
187 Object* ThisDesc(Module* mod, int fprint)
189 int i, n;
190 i = 0; n = mod->export->num;
191 while ((i < n) && (mod->export->obj[i].id / 256 == 0))
193 if (mod->export->obj[i].offs == fprint)
194 return (Object*)&(mod->export->obj[i]);
195 i++;
197 return NULL;
200 int LoadDll (char* name)
203 void *handle;
204 dprintf("loading: %s\n", name);
205 if ((handle = dlopen(name, RTLD_LAZY + RTLD_GLOBAL)) == NULL) {
206 printf("LoadDll: failed to load lib %s\n", name);
207 printf(" - dlerror: %s\n", dlerror());
208 exit(-1);
210 return handle != NULL;
214 int ThisDllObj (int mode, int fprint, char* dll, char* name)
216 void *handle;
217 int ad = 0;
218 if ((mode == mVar) || (mode == mProc)){
219 if ((handle = dlopen(dll, RTLD_LAZY + RTLD_GLOBAL)) == NULL) {
220 printf("ThisDllObj: lib %s not found\n", dll);
221 printf(" - dlerror: %s\n", dlerror());
222 exit(-1);
223 } else {
224 ad = (int)dlsym((void *) handle, name);
225 if (ad == 0) {
226 printf("ThisDllObj: symbol %s not found\n", name); exit(-1);
230 return ad;
233 int Read4 ()
235 unsigned char b;
236 int w;
237 b = fgetc(f); w = b % 256;
238 b = fgetc(f); w = w + 0x100 * (b % 256);
239 b = fgetc(f); w = w + 0x10000 * (b % 256);
240 b = fgetc(f); w = w + 0x1000000 * b;
241 return w;
244 int RNum()
246 char b;
247 int s, y;
248 s = 0; y = 0;
249 b = fgetc(f);
250 while (b < 0)
252 y = y + ((b + 128) << s);
253 s = s + 7;
254 b = fgetc(f);
256 return (((b + 64) % 128 - 64) << s) + y;
259 void ReadName (char* str)
261 unsigned char b;
262 int i;
263 i = 0; b = fgetc(f);
264 while (b != 0)
266 str[i] = b; i++; b = fgetc(f);
268 str[i] = 0;
271 void Fixup (int adr)
273 int link, offset, linkadr, n, x, t;
275 dprintf("fixup: %X ", adr);
276 link = RNum();
277 while (link != 0)
279 offset = RNum();
280 dprintf("+%d: ", offset);
281 while (link != 0)
283 if (link > 0)
285 dprintf("c");
286 linkadr = mod.mad + mod.ms + link;
288 else
290 dprintf("d");
291 link = -link;
292 if (link < mod.ms)
293 linkadr = mod.mad + link;
294 else
295 linkadr = mod.dad + link - mod.ms;
297 dprintf("%X ", link);
299 /*
300 t = *(char*)(linkadr + 3);
301 n = *(int*)linkadr;
302 n = n << 8; n = n >> 8;
303 */
304 x = *(int*)linkadr;
305 t = x / 0x1000000;
306 n = (x + 0x800000) % 0x1000000 - 0x800000;
308 switch (t) {
309 case absolute: x = adr + offset; break;
310 case relative: x = adr + offset - linkadr -4; break;
311 case copy: x = *(int*)(adr + offset); break;
312 case table: x = adr + n; n = link + 4; break;
313 case tableend: x = adr + n; n = 0; break;
314 case deref: x = *(int*)(adr + 2); x = x + offset; break;
315 case halfword:
316 printf("fixup: halfword not implemented\n");
317 break;
318 default:
319 printf("fixup error(link=%d, offset=%d, linkadr=%d, t=%d, x=%d)\n",
320 link, offset, linkadr, t, x);
321 return;
322 }
323 *(int*)linkadr = x;
324 link = n;
326 link = RNum();
328 dprintf("\n");
331 int ReadBootHeader()
333 int tag, version;
335 fseek(f, exeSize, SEEK_SET);
336 tag = Read4();
337 version = Read4();
338 if ((tag != 0x3A4B5C6D) || (version != 0))
340 return 0;
342 nofMods = Read4();
343 dprintf("Linked modules: %d\n", nofMods);
344 ReadName(kernel);
345 dprintf("kernel: %s\n", kernel);
346 ReadName(mainmod);
347 dprintf("main: %s\n", mainmod);
348 newRecFP = Read4(); newRecAdr = 0;
349 newArrFP = Read4(); newArrAdr = 0;
350 mod.start = ftell(f);
351 return 1;
354 int ReadHeader ()
356 int ofTag, i, nofImps, processor;
357 char str[80];
358 ImpList *imp, *last;
359 char* n;
361 ofTag = Read4();
362 if (ofTag != 0x6F4F4346)
364 printf("wrong object file version\n");
365 return 0;
367 processor = Read4();
368 mod.hs = Read4();
369 mod.ms = Read4();
370 mod.ds = Read4();
371 mod.cs = Read4();
372 mod.vs = Read4();
373 dprintf("File tag: %d ", ofTag); dprintf("Processor: %d\n", processor);
374 dprintf("Header size: %d ", mod.hs);
375 dprintf("Meta size: %d ", mod.ms);
376 dprintf("Desc size: %d ", mod.ds );
377 dprintf("Code size: %d ", mod.cs);
378 dprintf("Data size: %d\n", mod.vs);
379 nofImps = RNum(); dprintf("Nof imports: %d\n", nofImps);
380 ReadName(mod.name); dprintf("Module name: %s\n", mod.name);
381 mod.imp = NULL;
382 for (i = 0; i < nofImps; i++)
384 imp = (ImpList*)calloc(1, sizeof(ImpList));
385 ReadName(imp->name);
386 if (mod.imp == NULL)
387 mod.imp = imp;
388 else
389 last->next = imp;
390 last = imp;
391 last->next = NULL;
392 dprintf("Import %d: %s\n", i, imp->name);
393 if ((imp->name[0] == '$') && (imp->name[1] == '$'))
394 strcpy(imp->name, "Kernel");
395 if (imp->name[0] == '$'){
396 n = imp->name;
397 n++;
398 if (!LoadDll(n)){
399 printf("Could not load lib: %s\n", imp->name[1]);
400 return 0;
404 dprintf("Pos: %d\n", ftell(f));
405 return 1;
408 int ReadModule ()
410 char *dp, *mp;
411 unsigned int cnt;
412 ImpList* imp;
413 int x, fp, opt, link, ofp, imptab, a;
414 Module *desc, *k;
415 String name;
416 Object* obj;
417 int isLib;
418 char* im;
420 mod.dad = (int) calloc(1, mod.ds);
421 mod.mad = (int) calloc(1, mod.ms + mod.cs + mod.vs);
422 if ((mod.dad == 0) || (mod.mad == 0))
424 printf("BootLoader: Couldn't initalize heap\n");
425 free((void*)mod.dad);
426 free((void*)mod.mad);
427 return 0;
429 dp = (char*) mod.dad;
430 mp = (char*) mod.mad;
431 fseek(f, mod.start + mod.hs, SEEK_SET);
432 dprintf("ReadModule after fseek pos: %d\n", ftell(f));
433 cnt = fread(mp, 1, mod.ms, f);
434 dprintf("Read meta bulk (%d bytes. New pos: %d)\n", cnt, ftell(f));
435 cnt = fread(dp, 1, mod.ds, f);
436 dprintf("Read desc bulk (%d bytes. New pos: %d)\n", cnt, ftell(f));
437 mp = (char*)(mod.mad + mod.ms);
438 cnt = fread(mp, 1, mod.cs, f);
439 dprintf("Read code bulk (%d bytes. New pos: %d)\n", cnt, ftell(f));
441 DumpMod();
443 dprintf("before fixup: pos = %d\n", ftell(f));
445 if ((!newRecAdr) || (!newArrAdr)){
446 k = ThisModule(kernel);
447 if (k != NULL){
448 /* obj = ThisDesc(k, newRecFP);*/
449 obj = ThisObject(k, "NewRec");
450 if (obj != NULL)
451 newRecAdr = k->procBase + obj->offs;
452 /* obj = ThisDesc(k, newArrFP);*/
453 obj = ThisObject(k, "NewArr");
454 if (obj != NULL)
455 newArrAdr = k->procBase + obj->offs;
456 dprintf("newRecFP: %X newArrFP: %X\n", newRecFP, newArrFP);
457 dprintf("newRecAdr: %X newArrAdr: %X\n", newRecAdr, newArrAdr);
458 } else {
459 dprintf("no kernel before %s.\n", mod.name);
462 Fixup(newRecAdr);
463 Fixup(newArrAdr);
464 Fixup(mod.mad);
465 Fixup(mod.dad);
466 Fixup(mod.mad + mod.ms);
467 Fixup(mod.mad + mod.ms + mod.cs);
468 dprintf("after fixup: pos = %d\n", ftell(f));
469 imp = mod.imp; imptab = (int)((Module*)(mod.dad))->imports;
470 while (imp != NULL){
471 x = RNum();
472 if ((imp->name[0] == '$') && (imp->name[1] == '$'))
473 printf("should be Kerneln");
474 if (imp->name[0] == '$')
475 isLib = 1;
476 else{
477 isLib = 0;
478 desc = ThisModule(imp->name);
479 if (desc == NULL){
480 printf("invalid import list\n");
481 return 0;
484 while (x != 0) {
485 ReadName(name); fp = RNum(); opt = 0;
486 if (!isLib) {
487 if (name[0] == 0)
488 obj = ThisDesc(desc, fp);
489 else
490 obj = ThisObject(desc, name);
491 if ((obj != NULL) && (obj->id % 16 == x)){
492 ofp = obj->fprint;
493 switch (x){
494 case mTyp:
495 opt = RNum();
496 if (opt % 2 == 1) ofp = obj->offs;
497 if ((opt > 1) && ((obj->id / 16) % 16 != mExported)){
498 printf("object not found (%s)\n", imp->name);
499 return 0;
501 Fixup((int)obj->ostruct);
502 break;
503 case mVar:
504 Fixup(desc->varBase + obj->offs);
505 break;
506 case mProc:
507 Fixup(desc->procBase + obj->offs);
509 if (ofp != fp){
510 printf("illigal foot print (%s)\n", imp->name);
511 return 0;
513 } else {
514 if (obj == NULL) printf("obj == NULL\n");
515 printf("descriptor not found (%s, x: %d, id: %d)\n", name, x, obj->id);
516 return 0;
518 }else{
519 if ((x == mVar) || (x == mProc)){
520 im = imp->name;
521 im++;
522 a = ThisDllObj(x, fp, im, name);
523 if (a != 0)
524 Fixup(a);
525 else{
526 printf("ReadModule: Object not found: %s\n", name);
527 return 0;
529 } else {
530 if (x == mTyp) {
531 opt = RNum();
532 x = RNum();
533 if (x != 0) {
534 printf("ReadModule: Object not found: %s\n", name);
535 return 0;
540 x = RNum();
542 *(int*)imptab = (int)desc; imptab += 4;
543 imp = imp->next;
546 mod.start = ftell(f);
547 return 1;
550 int main (int argc, char *argv[])
552 int i, ok;
553 BodyProc body;
554 int callBackAdr;
555 Module *k, *m;
557 modlist = NULL;
558 dprintf("initializing BlackBox for Linux...\n");
559 /*f = fopen(bbfile, "rb");*/
560 f = fopen(argv[0], "r");
561 if (f != NULL)
563 if (ReadBootHeader())
565 i = 0; ok = 1;
566 while ((i < nofMods) && (ok)){
567 ok = ReadHeader();
568 if (ok) {
569 ok = ReadModule();
570 if (ok)
571 RegisterModule();
572 else
573 printf("Incorrect module: %s\n", mod.name);
574 } else
575 printf("Incorrect header: %s\n", mod.name);
576 i++;
578 fclose(f);
579 if (ok) {
580 k = ThisModule(kernel);
581 m = ThisModule(mainmod);
582 if (k == NULL)
583 printf("no kernel\n");
584 else
586 if (m == NULL)
587 printf("no main module");
588 else
590 /* assign the boot info to first variable in Kernel */
591 bootInfo = calloc(1, sizeof(BootInfo));
592 bootInfo->modList = modlist;
593 bootInfo->argc = argc;
594 bootInfo->argv = argv;
595 *((int*)(k->varBase)) = (int)bootInfo;
596 dprintf("before body\n");
597 body = (BodyProc)(m->code);
598 k->opts = k->opts | init; /* include init in opts */
599 body();
600 dprintf("after body\n");
603 PrintMods();
605 } else
606 printf("Invalid BlackBox executable, make sure that the constant exeSize is correctly set\n");
608 } else
609 printf("Couldn't find file: %s\n", bbfile);