DEADSOFTWARE

add 'chmod +x' and remove 'run' in new linker
[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 <errno.h>
15 #include <fcntl.h>
17 /* the exact size (in bytes) of the executable part of the file. */
18 /* this constant needs to be updated everytime a change is made to this file */
19 #define exeSize 17008
22 /* fixup types */
23 #define absolute 100
24 #define relative 101
25 #define copy 102
26 #define table 103
27 #define tableend 104
28 #define deref 105
29 #define halfword 106
31 /* import types */
32 #define mConst 0x1
33 #define mTyp 0x2
34 #define mVar 0x3
35 #define mProc 0x4
36 #define mExported 4
38 #define any 1000000
40 #define init 0x10000
42 /* set to printf to debug and donothing to avoid debugging */
43 #define dprintf donothing
45 typedef void (*BodyProc)();
46 typedef char String[256];
48 typedef struct Type {
49 int size;
50 struct Module* mod;
51 int id;
52 int base[16]; /* should be ARRAY 16 OF TYPE */
53 int fields; /* should be Directory* */
54 int ptroffs[any];
55 } Type;
57 typedef struct Object{
58 int fprint;
59 int offs;
60 int id;
61 Type* ostruct;
62 } Object;
64 typedef struct Directory{
65 int num;
66 Object obj[any];
67 } Directory;
69 typedef struct Module{ /* has to be exact copy of Kernel.Module */
70 struct Module *next;
71 int opts;
72 int refcnt;
73 short compTime[6], loadTime[6];
74 int ext;
75 int term; /* actually a pointer to type Command */
76 int nofimps, nofptrs;
77 int csize, dsize, rsize;
78 int code, data, refs;
79 int procBase, varBase; /* meta base addresses */
80 char* names; /* names[0] = 0X */
81 int* ptrs;
82 struct Module* imports;
83 Directory* export;
84 char name[256];
85 } Module;
87 typedef struct ImpList
88 {
89 struct ImpList* next;
90 String name;
91 } ImpList;
93 typedef struct ModSpec
94 {
95 ImpList* imp;
96 String name;
97 int start, hs, ms, ds, cs, vs, mad, dad;
98 } ModSpec;
100 typedef struct BootInfo
102 Module* modList;
103 int argc;
104 char** argv;
105 } BootInfo;
107 const char bbfile[] = "./bb.boot";
109 FILE* f;
110 int nofMods;
111 String kernel, mainmod;
112 ModSpec mod;
113 Module *modlist;
114 BootInfo* bootInfo;
115 int newRecAdr, newArrAdr;
116 int newRecFP, newArrFP;
118 int zerofd;
120 int donothing(char* fmt, ...)
124 void DumpMod()
125 {
126 dprintf("\n\n---- Mod info:\n");
127 dprintf(" hs, ms, ds, cs, vs = %d, %d, %d, %d, %d\n",
128 mod.hs, mod.ms, mod.ds, mod.cs, mod.vs);
129 dprintf(" mad, dad = %d, %d\n\n", mod.mad, mod.dad);
133 void RegisterModule()
135 Module* m;
136 m = (Module*)mod.dad;
137 m->next = modlist;
138 modlist = m;
139 /*
140 if (modlist == NULL){
141 modlist = m;
142 } else {
143 last->next = m;
144 last = m;
146 last->next = NULL;
147 */
148 dprintf("Registred module %s\n", mod.name);
151 void PrintMods()
153 Module* ml;
154 ml = modlist;
155 dprintf("Loaded Modules\n");
156 while (ml != NULL){
157 dprintf("mod name: %s\n", ml->name);
158 ml = ml->next;
160 dprintf("end of list\n");
164 Module* ThisModule(char* name)
166 Module* ml;
167 ml = modlist;
168 while ((ml != NULL) && (strcmp(ml->name, name) != 0)){
169 ml = ml->next;
171 return ml;
174 Object* ThisObject(Module* mod, char* name)
176 int l, r, m;
177 char* p;
178 l = 0; r = mod->export->num;
179 while (l < r){
180 m = (l + r) / 2;
181 p = (char*) &(mod->names[mod->export->obj[m].id / 256]);
182 if (strcmp(p, name) == 0)
183 return (Object*)&(mod->export->obj[m]);
184 if (strcmp(p, name) < 0)
185 l = m + 1;
186 else
187 r = m;
189 return NULL;
192 Object* ThisDesc(Module* mod, int fprint)
194 int i, n;
195 i = 0; n = mod->export->num;
196 while ((i < n) && (mod->export->obj[i].id / 256 == 0))
198 if (mod->export->obj[i].offs == fprint)
199 return (Object*)&(mod->export->obj[i]);
200 i++;
202 return NULL;
205 int LoadDll (char* name)
208 void *handle;
209 dprintf("loading: %s\n", name);
210 if ((handle = dlopen(name, RTLD_LAZY + RTLD_GLOBAL)) == NULL) {
211 printf("LoadDll: failed to load lib %s\n", name);
212 printf(" - dlerror: %s\n", dlerror());
213 exit(-1);
215 return handle != NULL;
219 int ThisDllObj (int mode, int fprint, char* dll, char* name)
221 void *handle;
222 int ad = 0;
223 if ((mode == mVar) || (mode == mProc)){
224 if ((handle = dlopen(dll, RTLD_LAZY + RTLD_GLOBAL)) == NULL) {
225 printf("ThisDllObj: lib %s not found\n", dll);
226 printf(" - dlerror: %s\n", dlerror());
227 exit(-1);
228 } else {
229 ad = (int)dlsym((void *) handle, name);
230 if (ad == 0) {
231 printf("ThisDllObj: symbol %s not found\n", name); exit(-1);
235 return ad;
238 int Read4 ()
240 unsigned char b;
241 int w;
242 b = fgetc(f); w = b % 256;
243 b = fgetc(f); w = w + 0x100 * (b % 256);
244 b = fgetc(f); w = w + 0x10000 * (b % 256);
245 b = fgetc(f); w = w + 0x1000000 * b;
246 return w;
249 int RNum()
251 char b;
252 int s, y;
253 s = 0; y = 0;
254 b = fgetc(f);
255 while (b < 0)
257 y = y + ((b + 128) << s);
258 s = s + 7;
259 b = fgetc(f);
261 return (((b + 64) % 128 - 64) << s) + y;
264 void ReadName (char* str)
266 unsigned char b;
267 int i;
268 i = 0; b = fgetc(f);
269 while (b != 0)
271 str[i] = b; i++; b = fgetc(f);
273 str[i] = 0;
276 void Fixup (int adr)
278 int link, offset, linkadr, n, x, t;
280 dprintf("fixup: %X ", adr);
281 link = RNum();
282 while (link != 0)
284 offset = RNum();
285 dprintf("+%d: ", offset);
286 while (link != 0)
288 if (link > 0)
290 dprintf("c");
291 linkadr = mod.mad + mod.ms + link;
293 else
295 dprintf("d");
296 link = -link;
297 if (link < mod.ms)
298 linkadr = mod.mad + link;
299 else
300 linkadr = mod.dad + link - mod.ms;
302 dprintf("%X ", link);
304 /*
305 t = *(char*)(linkadr + 3);
306 n = *(int*)linkadr;
307 n = n << 8; n = n >> 8;
308 */
309 x = *(int*)linkadr;
310 t = x / 0x1000000;
311 n = (x + 0x800000) % 0x1000000 - 0x800000;
313 switch (t) {
314 case absolute: x = adr + offset; break;
315 case relative: x = adr + offset - linkadr -4; break;
316 case copy: x = *(int*)(adr + offset); break;
317 case table: x = adr + n; n = link + 4; break;
318 case tableend: x = adr + n; n = 0; break;
319 case deref: x = *(int*)(adr + 2); x = x + offset; break;
320 case halfword:
321 printf("fixup: halfword not implemented\n");
322 break;
323 default:
324 printf("fixup error(link=%d, offset=%d, linkadr=%d, t=%d, x=%d)\n",
325 link, offset, linkadr, t, x);
326 return;
327 }
328 *(int*)linkadr = x;
329 link = n;
331 link = RNum();
333 dprintf("\n");
336 int ReadBootHeader()
338 int tag, version;
340 fseek(f, exeSize, SEEK_SET);
341 tag = Read4();
342 version = Read4();
343 if ((tag != 0x3A4B5C6D) || (version != 0))
345 return 0;
347 nofMods = Read4();
348 dprintf("Linked modules: %d\n", nofMods);
349 ReadName(kernel);
350 dprintf("kernel: %s\n", kernel);
351 ReadName(mainmod);
352 dprintf("main: %s\n", mainmod);
353 newRecFP = Read4(); newRecAdr = 0;
354 newArrFP = Read4(); newArrAdr = 0;
355 mod.start = ftell(f);
356 return 1;
359 void * MemAlloc (size_t len)
361 void * res;
363 res = mmap(0, len, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANON, zerofd, 0);
364 if (res == MAP_FAILED) {
365 res = NULL;
366 } else {
367 bzero(res, len);
369 return res;
372 int ReadHeader ()
374 int ofTag, i, nofImps, processor;
375 char str[80];
376 ImpList *imp, *last;
377 char* n;
379 ofTag = Read4();
380 if (ofTag != 0x6F4F4346)
382 printf("wrong object file version\n");
383 return 0;
385 processor = Read4();
386 mod.hs = Read4();
387 mod.ms = Read4();
388 mod.ds = Read4();
389 mod.cs = Read4();
390 mod.vs = Read4();
391 dprintf("File tag: %d ", ofTag); dprintf("Processor: %d\n", processor);
392 dprintf("Header size: %d ", mod.hs);
393 dprintf("Meta size: %d ", mod.ms);
394 dprintf("Desc size: %d ", mod.ds );
395 dprintf("Code size: %d ", mod.cs);
396 dprintf("Data size: %d\n", mod.vs);
397 nofImps = RNum(); dprintf("Nof imports: %d\n", nofImps);
398 ReadName(mod.name); dprintf("Module name: %s\n", mod.name);
399 mod.imp = NULL;
400 for (i = 0; i < nofImps; i++)
402 imp = (ImpList*)MemAlloc(sizeof(ImpList));
403 ReadName(imp->name);
404 if (mod.imp == NULL)
405 mod.imp = imp;
406 else
407 last->next = imp;
408 last = imp;
409 last->next = NULL;
410 dprintf("Import %d: %s\n", i, imp->name);
411 if ((imp->name[0] == '$') && (imp->name[1] == '$'))
412 strcpy(imp->name, "Kernel");
413 if (imp->name[0] == '$'){
414 n = imp->name;
415 n++;
416 if (!LoadDll(n)){
417 printf("Could not load lib: %s\n", (char *)(&(imp->name[1])));
418 return 0;
422 dprintf("Pos: %d\n", ftell(f));
423 return 1;
426 int ReadModule ()
428 char *dp, *mp;
429 unsigned int cnt;
430 ImpList* imp;
431 int x, fp, opt, link, ofp, imptab, a;
432 Module *desc, *k;
433 String name;
434 Object* obj;
435 int isLib;
436 char* im;
438 mod.dad = (int) MemAlloc(mod.ds);
439 mod.mad = (int) MemAlloc(mod.ms + mod.cs + mod.vs);
440 if ((mod.dad == 0) || (mod.mad == 0))
442 printf("BootLoader: Couldn't initalize heap\n");
443 free((void*)mod.dad);
444 free((void*)mod.mad);
445 return 0;
447 dp = (char*) mod.dad;
448 mp = (char*) mod.mad;
449 fseek(f, mod.start + mod.hs, SEEK_SET);
450 dprintf("ReadModule after fseek pos: %d\n", ftell(f));
451 cnt = fread(mp, 1, mod.ms, f);
452 dprintf("Read meta bulk (%d bytes. New pos: %d)\n", cnt, ftell(f));
453 cnt = fread(dp, 1, mod.ds, f);
454 dprintf("Read desc bulk (%d bytes. New pos: %d)\n", cnt, ftell(f));
455 mp = (char*)(mod.mad + mod.ms);
456 cnt = fread(mp, 1, mod.cs, f);
457 dprintf("Read code bulk (%d bytes. New pos: %d)\n", cnt, ftell(f));
459 DumpMod();
461 dprintf("before fixup: pos = %d\n", ftell(f));
463 if ((!newRecAdr) || (!newArrAdr)){
464 k = ThisModule(kernel);
465 if (k != NULL){
466 /* obj = ThisDesc(k, newRecFP);*/
467 obj = ThisObject(k, "NewRec");
468 if (obj != NULL)
469 newRecAdr = k->procBase + obj->offs;
470 /* obj = ThisDesc(k, newArrFP);*/
471 obj = ThisObject(k, "NewArr");
472 if (obj != NULL)
473 newArrAdr = k->procBase + obj->offs;
474 dprintf("newRecFP: %X newArrFP: %X\n", newRecFP, newArrFP);
475 dprintf("newRecAdr: %X newArrAdr: %X\n", newRecAdr, newArrAdr);
476 } else {
477 dprintf("no kernel before %s.\n", mod.name);
480 Fixup(newRecAdr);
481 Fixup(newArrAdr);
482 Fixup(mod.mad);
483 Fixup(mod.dad);
484 Fixup(mod.mad + mod.ms);
485 Fixup(mod.mad + mod.ms + mod.cs);
486 dprintf("after fixup: pos = %d\n", ftell(f));
487 imp = mod.imp; imptab = (int)((Module*)(mod.dad))->imports;
488 while (imp != NULL){
489 x = RNum();
490 if ((imp->name[0] == '$') && (imp->name[1] == '$'))
491 printf("should be Kerneln");
492 if (imp->name[0] == '$')
493 isLib = 1;
494 else{
495 isLib = 0;
496 desc = ThisModule(imp->name);
497 if (desc == NULL){
498 printf("invalid import list\n");
499 return 0;
502 while (x != 0) {
503 ReadName(name); fp = RNum(); opt = 0;
504 if (!isLib) {
505 if (name[0] == 0)
506 obj = ThisDesc(desc, fp);
507 else
508 obj = ThisObject(desc, name);
509 if ((obj != NULL) && (obj->id % 16 == x)){
510 ofp = obj->fprint;
511 switch (x){
512 case mTyp:
513 opt = RNum();
514 if (opt % 2 == 1) ofp = obj->offs;
515 if ((opt > 1) && ((obj->id / 16) % 16 != mExported)){
516 printf("object not found (%s)\n", imp->name);
517 return 0;
519 Fixup((int)obj->ostruct);
520 break;
521 case mVar:
522 Fixup(desc->varBase + obj->offs);
523 break;
524 case mProc:
525 Fixup(desc->procBase + obj->offs);
527 if (ofp != fp){
528 printf("illigal foot print (%s)\n", imp->name);
529 return 0;
531 } else {
532 if (obj == NULL) printf("obj == NULL\n");
533 printf("descriptor not found (%s, x: %d, id: %d)\n", name, x, obj->id);
534 return 0;
536 }else{
537 if ((x == mVar) || (x == mProc)){
538 im = imp->name;
539 im++;
540 a = ThisDllObj(x, fp, im, name);
541 if (a != 0)
542 Fixup(a);
543 else{
544 printf("ReadModule: Object not found: %s\n", name);
545 return 0;
547 } else {
548 if (x == mTyp) {
549 opt = RNum();
550 x = RNum();
551 if (x != 0) {
552 printf("ReadModule: Object not found: %s\n", name);
553 return 0;
558 x = RNum();
560 *(int*)imptab = (int)desc; imptab += 4;
561 imp = imp->next;
564 mod.start = ftell(f);
565 return 1;
568 int main (int argc, char *argv[])
570 int i, ok;
571 BodyProc body;
572 int callBackAdr;
573 Module *k, *m;
575 zerofd = open("/dev/zero", O_RDWR);
576 if (zerofd == -1) {
577 printf("open /dev/zero failed: %s\n", strerror(errno));
578 return 101;
581 modlist = NULL;
582 dprintf("initializing BlackBox for Linux...\n");
583 /*f = fopen(bbfile, "rb");*/
584 f = fopen(argv[0], "r");
585 if (f != NULL)
587 if (ReadBootHeader())
589 i = 0; ok = 1;
590 while ((i < nofMods) && (ok)){
591 ok = ReadHeader();
592 if (ok) {
593 ok = ReadModule();
594 if (ok)
595 RegisterModule();
596 else
597 printf("Incorrect module: %s\n", mod.name);
598 } else
599 printf("Incorrect header: %s\n", mod.name);
600 i++;
602 fclose(f);
603 if (ok) {
604 k = ThisModule(kernel);
605 m = ThisModule(mainmod);
606 if (k == NULL)
607 printf("no kernel\n");
608 else
610 if (m == NULL)
611 printf("no main module");
612 else
614 /* assign the boot info to first variable in Kernel */
615 bootInfo = MemAlloc(sizeof(BootInfo));
616 bootInfo->modList = modlist;
617 bootInfo->argc = argc;
618 bootInfo->argv = argv;
619 *((int*)(k->varBase)) = (int)bootInfo;
620 dprintf("before body\n");
621 body = (BodyProc)(m->code);
622 k->opts = k->opts | init; /* include init in opts */
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);