aos.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. /*------------------------------------------------------
  2. * Oberon Boot File Loader RC, JS 27.4.93/2.12.93, HP-UX 9.0 Version
  3. *
  4. * Oberon Boot File Loader for Linux
  5. * derived from HP and Windows Boot Loader
  6. * MAD, 23.05.94
  7. * PR, 01.02.95 support for sockets added
  8. * PR, 05.02.95 support for V24 added
  9. * PR, 23.12.95 migration to shared ELF libraries
  10. * g.f. 01.11.99 added InstallTrap
  11. * added Threads support
  12. * removed cmd line parameter evaluation
  13. * g.f. 22.11.04 call to mprotect added
  14. * g.f. 03.04.07 Darwin/Intel version
  15. *
  16. *-----------------------------------------------------------*/
  17. #ifdef DARWIN
  18. # undef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
  19. # define __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ 1059
  20. #endif
  21. #ifdef LINUX
  22. # define _use_valloc /* use the obsolete valloc function instead of posix_memalign */
  23. #endif
  24. #include <sys/types.h>
  25. #include <fcntl.h>
  26. #include <dlfcn.h>
  27. #include <unistd.h>
  28. #include <stdlib.h>
  29. #include <stdio.h>
  30. #include <string.h>
  31. #include <errno.h>
  32. #include <sys/stat.h>
  33. #include <setjmp.h>
  34. #ifdef DARWIN
  35. # include <sys/ucontext.h>
  36. # include <sys/_types.h>
  37. # include <sys/signal.h>
  38. #endif
  39. #include <signal.h>
  40. #include <limits.h>
  41. #include "Threads.h"
  42. #include <sys/mman.h>
  43. #include <X11/Xlib.h>
  44. #define true 1
  45. #define false 0
  46. typedef void (*OberonProc)();
  47. typedef void* address;
  48. typedef unsigned int ADDR32;
  49. FILE *fd;
  50. char *AOSPATH;
  51. char path[4096];
  52. char *dirs[255];
  53. char fullname[512];
  54. int nofdir;
  55. char defaultpath[] = ".:/usr/aos/obj:/usr/aos/system:/usr/aos/fonts/Oberon";
  56. #ifdef SOLARIS
  57. char bootname[64] = "SolarisAosCore";
  58. #endif
  59. #ifdef LINUX
  60. char bootname[64] = "LinuxAosCore";
  61. #endif
  62. #ifdef DARWIN
  63. char bootname[64] = "DarwinAosCore";
  64. #endif
  65. size_t heapSize = 0x200000;
  66. size_t codeSize;
  67. address heapAdr, maxHeapAdr;
  68. int addrshift;
  69. unsigned int startOffset;
  70. int Argc;
  71. char **Argv;
  72. int debug;
  73. static stack_t sigstk;
  74. #define BLSIZE 4096
  75. #define SIGSTACKSIZE 64*BLSIZE
  76. typedef void(*trap_t)(long, void*, void*, int);
  77. static trap_t AosTrap;
  78. static void sighandler( int sig, siginfo_t *scp, void *ucp ) {
  79. if (debug | (AosTrap == NULL)) {
  80. printf("\nhandler for signal %d got called, ucp = %p\n", sig, ucp);
  81. if (AosTrap == NULL) exit(1);
  82. }
  83. AosTrap(0, ucp, scp, sig); /* rev. order: Oberon <--> C */
  84. }
  85. static void installHandler(int sig) {
  86. struct sigaction act;
  87. sigset_t mask;
  88. sigemptyset(&mask);
  89. act.sa_mask = mask;
  90. if (sig == SIGSEGV)
  91. act.sa_flags = SA_SIGINFO|SA_ONSTACK|SA_NODEFER;
  92. else
  93. act.sa_flags = SA_SIGINFO|SA_NODEFER;
  94. act.sa_sigaction = sighandler;
  95. if (sigaction( sig, &act, NULL ) != 0) {
  96. perror("sigaction");
  97. }
  98. }
  99. void InitSignalHandler() {
  100. int i;
  101. for (i = 1; i <= 15; i++) {
  102. if (i != 9) installHandler( i );
  103. }
  104. }
  105. static void InstallTrap(trap_t p) {
  106. if (debug)
  107. printf("Installing Aos Trap\n");
  108. AosTrap = p;
  109. }
  110. void SetSigaltstack() {
  111. if (sigaltstack(&sigstk, NULL) < 0)
  112. perror("sigaltstack");
  113. }
  114. static void CreateSignalstack() {
  115. sigstk.ss_sp = mmap( NULL, SIGSTACKSIZE,
  116. PROT_READ | PROT_WRITE,
  117. MAP_PRIVATE | MAP_ANON,
  118. -1, 0);
  119. if (sigstk.ss_sp == MAP_FAILED){
  120. printf("mmap for signalstack failed\n" );
  121. exit( 1 );
  122. }
  123. sigstk.ss_size = SIGSTACKSIZE;
  124. sigstk.ss_flags = 0;
  125. if (debug)
  126. printf( "Signalstack created [%p ... %p]\n",
  127. sigstk.ss_sp, sigstk.ss_sp + SIGSTACKSIZE );
  128. SetSigaltstack();
  129. }
  130. void* o_dlopen(char *lib, int mode) {
  131. void* handle;
  132. if (debug&1) printf("o_dlopen: %s\n", lib);
  133. if ((handle = dlopen(lib, mode)) == NULL) {
  134. if (debug&1)
  135. printf("o_dlopen: %s not loaded, error = %s\n", lib, dlerror());
  136. }
  137. if (debug&1) printf("o_dlopen: handle = %p\n", handle);
  138. return handle;
  139. }
  140. void o_dlclose(void* handle) /* not necessary */
  141. {
  142. dlclose(handle);
  143. }
  144. static int o_errno() {
  145. return errno;
  146. }
  147. int o_stat(char* name, void* buf) {
  148. return stat(name, (struct stat *) buf);
  149. }
  150. int o_lstat(char* name, void* buf) {
  151. return lstat(name, (struct stat *) buf);
  152. }
  153. int o_fstat(int fd, void* buf) {
  154. return fstat(fd, (struct stat *) buf);
  155. }
  156. int o_open(char* name, int flags, int mode) {
  157. return open(name, flags, mode);
  158. }
  159. void *o_malloc( long size ) {
  160. return malloc( size );
  161. }
  162. int o_posix_memalign(void** buf, long alignment, long size ) {
  163. #ifdef _use_valloc
  164. *buf = valloc( size );
  165. if (*buf != NULL) return 0; else return -1;
  166. #else
  167. return posix_memalign( buf, alignment, size );
  168. #endif
  169. }
  170. int o_mprotect( void* addr, long len, int prot ) {
  171. return mprotect( addr, len, prot );
  172. }
  173. int o_lseek( int fd, long pos, int whence ) {
  174. return lseek( fd, pos, whence );
  175. }
  176. int o_cout( char c ) {
  177. printf( "%c", c );
  178. }
  179. address o_paramtest(int p1, int p2, int p3, int p4, int p5, int p6, int p7, address p8){
  180. printf("parameter test, p7=%d, p8=%p\n", p7, p8);
  181. return (address)-8;
  182. }
  183. static void (*oberonXErrorHandler) (long p4, long p3, long err, long displ );
  184. static void (*oberonXIOErrorHandler) (long p4, long p3, long p2, long displ );
  185. static int X11ErrorHandler( Display *d, XErrorEvent *err ) {
  186. printf( "X11ErrorHandler called\n" );
  187. oberonXErrorHandler( 0, 0, (long)err, (long)d );
  188. }
  189. static int X11IOErrorHandler( Display *d ) {
  190. printf( "X11IOErrorHandler called\n" );
  191. oberonXIOErrorHandler( 0, 0, 0, (long)d );
  192. }
  193. void SetupXErrHandlers( void* XE, void* XIOE ) {
  194. if (debug)
  195. printf( "Setup X11 ErrorHandlers\n" );
  196. oberonXErrorHandler = XE;
  197. oberonXIOErrorHandler = XIOE;
  198. XSetErrorHandler(X11ErrorHandler);
  199. XSetIOErrorHandler(X11IOErrorHandler);
  200. }
  201. void o_dlsym(void* handle, char* symbol, void** adr)
  202. {
  203. if (strcmp("dlopen", symbol) == 0) *adr = o_dlopen;
  204. else if (strcmp("dlclose", symbol) == 0) *adr = o_dlclose;
  205. else if (strcmp("debug", symbol) == 0) *(int*)adr = debug;
  206. else if (strcmp("heapAdr", symbol) == 0) *adr = heapAdr;
  207. else if (strcmp("heapSize", symbol) == 0) *(size_t*)adr = heapSize;
  208. else if (strcmp("argc", symbol) == 0) *adr = &Argc;
  209. else if (strcmp("argv", symbol) == 0) *adr = Argv;
  210. else if (strcmp("errno", symbol) == 0) *adr = o_errno;
  211. else if (strcmp("cout", symbol) == 0) *adr = o_cout;
  212. else if (strcmp("paramtest", symbol) == 0) *adr = o_paramtest;
  213. else if (strcmp("open", symbol) == 0) *adr = o_open;
  214. else if (strcmp("stat", symbol) == 0) *adr = o_stat;
  215. else if (strcmp("lstat", symbol) == 0) *adr = o_lstat;
  216. else if (strcmp("fstat", symbol) == 0) *adr = o_fstat;
  217. else if (strcmp("lseek", symbol) == 0) *adr = o_lseek;
  218. else if (strcmp("malloc", symbol) == 0) *adr = o_malloc;
  219. else if (strcmp("posix_memalign", symbol) == 0) *adr = o_posix_memalign;
  220. else if (strcmp("mprotect", symbol) == 0) *adr = o_mprotect;
  221. else if (strcmp("InstallTrap", symbol) == 0) *adr = InstallTrap;
  222. else if (strcmp("InitXErrH", symbol) == 0) *adr = SetupXErrHandlers;
  223. #ifdef LINUX
  224. else if (strcmp("sigsetjmp", symbol) == 0) *adr = __sigsetjmp;
  225. else if (strcmp("setjmp", symbol) == 0) *adr = __sigsetjmp;
  226. #endif
  227. else if (strcmp("mtxInit", symbol) == 0) *adr = o_mtxInit;
  228. else if (strcmp("mtxDestroy", symbol) == 0) *adr = o_mtxDestroy;
  229. else if (strcmp("mtxLock", symbol) == 0) *adr = o_mtxLock;
  230. else if (strcmp("mtxUnlock", symbol) == 0) *adr = o_mtxUnlock;
  231. else if (strcmp("conInit", symbol) == 0) *adr = o_conInit;
  232. else if (strcmp("conDestroy", symbol) == 0) *adr = o_conDestroy;
  233. else if (strcmp("conWait", symbol) == 0) *adr = o_conWait;
  234. else if (strcmp("conSignal", symbol) == 0) *adr = o_conSignal;
  235. else if (strcmp("thrStart", symbol) == 0) *adr = o_thrStart;
  236. else if (strcmp("thrThis", symbol) == 0) *adr = o_thrThis;
  237. else if (strcmp("thrSleep", symbol) == 0) *adr = o_thrSleep;
  238. else if (strcmp("thrYield", symbol) == 0) *adr = o_thrYield;
  239. else if (strcmp("thrExit", symbol) == 0) *adr = o_thrExit;
  240. else if (strcmp("thrSuspend", symbol) == 0) *adr = o_thrSuspend;
  241. else if (strcmp("thrResume", symbol) == 0) *adr = o_thrResume;
  242. else if (strcmp("thrGetPriority", symbol) == 0) *adr = o_thrGetprio;
  243. else if (strcmp("thrSetPriority", symbol) == 0) *adr = o_thrSetprio;
  244. else if (strcmp("thrKill", symbol) == 0) *adr = o_thrKill;
  245. else if (strcmp("thrInitialize", symbol) == 0) *adr = o_thrInitialize;
  246. else {
  247. *adr = dlsym(handle, symbol);
  248. if (*adr == 0) {
  249. printf("o_dlsym: symbol %s not found\n", symbol);
  250. }
  251. }
  252. }
  253. /*----- Files Reading primitives -----*/
  254. int Rint() {
  255. unsigned char b[4]; int i;
  256. /* read little endian integer */
  257. for (i=0; i<4; i++) b[i] = fgetc(fd);
  258. return *((int*)b);
  259. }
  260. address RAddress() {
  261. unsigned char b[8]; int i;
  262. /* read little endian address */
  263. for (i=0; i<8; i++) b[i] = fgetc(fd);
  264. return *((address*)b);
  265. }
  266. int RNum() {
  267. int n, shift;
  268. unsigned char x;
  269. shift = 0; n = 0; x = fgetc(fd);
  270. while (x >= 128) {
  271. n += (x & 0x7f) << shift;
  272. shift += 7;
  273. x = fgetc(fd);
  274. }
  275. return n + (((x & 0x3f) - ((x >> 6) << 6)) << shift);
  276. }
  277. int CheckAddr( int no, int ofs, address adr ){
  278. if (adr >= heapAdr+startOffset & adr < maxHeapAdr) return 1;
  279. else {
  280. printf("bad relocation offset: no=%d, ofs=%x, pos=%p [%p...%p]\n",
  281. no, ofs, adr, heapAdr+startOffset, maxHeapAdr);
  282. return 0;
  283. }
  284. }
  285. void Assert( int no, int ofs, address adr ){
  286. if (adr < heapAdr+startOffset || adr > maxHeapAdr)
  287. printf("bad relocated pointer value: no=%d, ofs=%x, ptr=%p [%p...%p]\n",
  288. no, ofs, adr, heapAdr+startOffset, maxHeapAdr);
  289. }
  290. void Relocate() {
  291. int no, len, ofs; ADDR32 *adr; ADDR32 val;
  292. len = RNum(); no = 0;
  293. if (debug) printf("relocate %d pointers\n", len);
  294. while (len != 0) {
  295. ofs = RNum(); ++no;
  296. adr = heapAdr + ofs;
  297. if (CheckAddr(no, ofs, adr)) {
  298. val = *adr;
  299. val += addrshift;
  300. *adr = val;
  301. Assert(no, ofs, (address)val);
  302. }
  303. len--;
  304. }
  305. }
  306. void Boot() {
  307. address adr, fileHeapAdr, dlsymAdr;
  308. size_t len, fileHeapSize;
  309. int arch, d, notfound;
  310. OberonProc body;
  311. if (sizeof(address)==8) strcat(bootname, ".amd64");
  312. d = 0; notfound = 1;
  313. while ((d < nofdir) && notfound) {
  314. strcat(strcat(strcpy(fullname, dirs[d++]), "/"), bootname);
  315. fd = fopen(fullname, "r");
  316. if (fd != NULL) notfound = 0;
  317. }
  318. if (notfound) {
  319. printf("Aos BootLoader: boot file %s not found\n", bootname);
  320. exit(-1);
  321. }
  322. arch = Rint();
  323. if (arch != 8*sizeof(address)) {
  324. printf("bootfile %s has wrong architecture, got %d, expected %d\n",
  325. bootname, arch, (int)(8*sizeof(address)) );
  326. exit(-1);
  327. }
  328. fileHeapAdr = RAddress();
  329. fileHeapSize = Rint();
  330. if (fileHeapSize > heapSize) {
  331. printf("Aos BootLoader: heap too small\n");
  332. exit(-1);
  333. }
  334. adr = heapAdr; len = heapSize;
  335. while (len > 0) {
  336. *((int*)adr) = 0;
  337. len -= 4; adr += 4;
  338. }
  339. addrshift = heapAdr - fileHeapAdr;
  340. startOffset = Rint();
  341. len = Rint(); /* used heap */
  342. adr = heapAdr + startOffset;
  343. while (len > 0) {
  344. *(int*)adr = Rint(); adr += 4; len -= 4;
  345. }
  346. maxHeapAdr = adr - 32;
  347. if (debug) printf("code loading done [%p .. %p]\n", heapAdr, adr);
  348. body = (OberonProc)heapAdr + Rint();
  349. dlsymAdr = heapAdr + Rint();
  350. if (debug) printf("dlsymAdr, entrypoint: %p, %p\n", dlsymAdr, body);
  351. Relocate();
  352. *(address*)dlsymAdr = o_dlsym;
  353. fclose(fd);
  354. if(mprotect((void*)heapAdr, heapSize, PROT_READ|PROT_WRITE|PROT_EXEC) != 0)
  355. perror("mprotect");
  356. if (debug) printf("jump to AOS entrypoint\n");
  357. (*body)();
  358. }
  359. void InitPath() {
  360. int pos;
  361. char ch;
  362. if ((AOSPATH = getenv("AOSPATH")) == NULL) AOSPATH = defaultpath;
  363. strcpy(path, AOSPATH);
  364. pos = 0; nofdir = 0;
  365. ch = path[pos++];
  366. while (ch != '\0') {
  367. while ((ch == ' ') || (ch == ':')) ch = path[pos++];
  368. dirs[nofdir] = &path[pos-1];
  369. while ((ch > ' ') && (ch != ':')) ch = path[pos++];
  370. path[pos-1] = '\0';
  371. nofdir ++;
  372. }
  373. }
  374. int main(int argc, char *argv[])
  375. {
  376. char* p;
  377. void *a, *h;
  378. Argc = argc; Argv = argv;
  379. debug = 0;
  380. p = getenv("AOSDEBUG");
  381. if (p != NULL) debug = atoi(p);
  382. if (debug) {
  383. printf( "UnixAos Boot Loader 06.01.2016\n" );
  384. printf( "debug = %d\n", debug );
  385. }
  386. if (posix_memalign(&heapAdr, 4096, heapSize) != 0) {
  387. printf("Aos BootLoader: cannot allocate initial heap space\n");
  388. exit(-1);
  389. }
  390. InitPath();
  391. CreateSignalstack();
  392. InitSignalHandler();
  393. Boot();
  394. return 0;
  395. }