Listtree.mcc: use internal inherited class of NListtree
[AROS.git] / arch / all-android / bootstrap / kickstart.c
bloba31e71b1888367b17726bdc6272b2a3b8d66dc65
1 /*
2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <sys/wait.h>
8 #include <errno.h>
9 #include <signal.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <unistd.h>
14 /* These macros are defined in both UNIX and AROS headers. Get rid of warnings. */
15 #undef __pure
16 #undef __const
17 #undef __pure2
18 #undef __deprecated
20 #include <aros/kernel.h>
21 #include <runtime.h>
23 #include "android.h"
24 #include "kickstart.h"
25 #include "platform.h"
27 #define D(x) x
30 * This is Android-hosted kicker.
31 * Android environment is the most alien one to AROS. It's proved to be impossible
32 * to run AROS inside JNI because AROS task switching is no friend to threads.
33 * However it's possible to run AROS as a separate process. This way it will be
34 * completely detached and live on its own.
36 * The bootstrap itself still runs in JVM context, this makes it easier to
37 * implement DisplayError().
40 /* Interface with the display driver */
41 int DisplayPipe;
42 int InputPipe;
44 /* This is where we remember our data */
45 static int (*EntryPoint)() = NULL;
46 static struct TagItem *BootMsg = NULL;
47 static pid_t AROS_pid = -1;
50 * Our SIGCHLD handler.
51 * It will notify Java side when AROS process exits. Additionally it will free allocated memory
52 * before performing a cold reboot.
54 static void childHandler(int sig)
56 int i;
58 wait(&i);
60 if (WIFEXITED(i))
62 int code = WEXITSTATUS(i);
64 D(kprintf("[Bootstrap] AROS process exited with code 0x%08X\n", code));
67 * If the requested action is not a warm reboot, free all the RAM.
68 * On cold reboot we will reload the kickstart from scratch.
70 if (code != STATUS_WARM_REBOOT)
71 Host_FreeMem();
73 /* Let the Java part to do the work */
74 (*Java_Env)->CallVoidMethod(Java_Env, Java_Object, HandleExit_mid, WEXITSTATUS(i));
76 else
78 DisplayError("AROS process terminated, status 0x%08X\n", i);
83 * Just remember arguments and return with zero returncode.
84 * This will signal to Java side that preparation (Load() method)
85 * completed succesfully. Next Java side can execute Kick() method
86 * in order to actually run AROS.
87 * This separation helps to implement warm restart. Kick() can be executed
88 * multiple times.
90 int kick(int (*addr)(), struct TagItem *msg)
92 EntryPoint = addr;
93 BootMsg = msg;
95 return 0;
98 /*
99 * The actual kicker.
100 * Similar to generic UNIX one, but uses SIGCHILD handler instead of waitpid()
101 * in order to detect when AROS exits.
102 * When this method succesfully exits, a display pipe server is run on Java side.
104 int Java_org_aros_bootstrap_AROSBootstrap_Kick(JNIEnv* env, jobject this, jobject readfd, jobject writefd)
106 struct sigaction sa;
107 int displaypipe[2];
108 int inputpipe[2];
109 int i;
110 jclass *class_fdesc = (*env)->GetObjectClass(env, readfd);
112 * In Sun JVM this is 'fd' field, in Android it's 'descriptor'.
113 * This is the only place which can be considered a hack. I hope Android guys
114 * won't change this.
116 jfieldID field_fd = (*env)->GetFieldID(env, class_fdesc, "descriptor", "I");
118 if (!field_fd)
120 DisplayError("Failed to set up pipe descriptor objects");
121 return -1;
124 sigemptyset(&sa.sa_mask);
125 sa.sa_flags = SA_RESTART;
126 sa.sa_restorer = NULL;
127 sa.sa_handler = childHandler;
129 sigaction(SIGCHLD, &sa, NULL);
131 if (pipe(displaypipe))
133 DisplayError("Failed to create display pipe: %s", strerror(errno));
134 return -1;
137 if (pipe(inputpipe))
139 close(displaypipe[0]);
140 close(displaypipe[1]);
142 DisplayError("Failed to create input pipe: %s", strerror(errno));
143 return -1;
146 D(kprintf("[Bootstrap] Launching kickstart...\n"));
147 AROS_pid = fork();
149 switch (AROS_pid)
151 case -1:
152 close(displaypipe[0]);
153 close(displaypipe[1]);
154 close(inputpipe[0]);
155 close(inputpipe[1]);
157 DisplayError("Failed to run kickstart!");
158 return -1;
160 case 0:
161 /* Set up client side of pipes */
162 DisplayPipe = displaypipe[1];
163 InputPipe = inputpipe[0];
164 close(displaypipe[0]);
165 close(inputpipe[1]);
167 D(kprintf("[Bootstrap] entering kernel at %p...\n", EntryPoint));
168 i = EntryPoint(BootMsg, AROS_BOOT_MAGIC);
169 exit(i);
172 D(kprintf("[Bootstrap] AROS PID %d, bootstrap PID %d\n", AROS_pid, getpid()));
174 /* Set up server side of pipes */
175 (*env)->SetIntField(env, readfd, field_fd, displaypipe[0]);
176 (*env)->SetIntField(env, writefd, field_fd, inputpipe[1]);
177 close(displaypipe[1]);
178 close(inputpipe[0]);
180 /* Return to JVM with success indication */
181 return 0;
184 /* A small method which allows display server to send signals to AROS process */
185 int Java_org_aros_bootstrap_AROSBootstrap_Kill(JNIEnv* env, jobject this, jint signal)
187 int res = kill(AROS_pid, signal);
189 D(kprintf("[Bootstrap] kill(%d, %d) returned %d, errno %d\n", AROS_pid, signal, res, errno));
190 return res;