2 Copyright © 1995-2016, The AROS Development Team. All rights reserved.
14 /* These macros are defined in both UNIX and AROS headers. Get rid of warnings. */
20 #include <aros/kernel.h>
24 #include "kickstart.h"
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 */
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
)
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
)
73 /* Let the Java part to do the work */
74 (*Java_Env
)->CallVoidMethod(Java_Env
, Java_Object
, HandleExit_mid
, WEXITSTATUS(i
));
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 successfully. 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
90 int kick(int (*addr
)(), struct TagItem
*msg
)
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 successfully 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
)
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
116 jfieldID field_fd
= (*env
)->GetFieldID(env
, class_fdesc
, "descriptor", "I");
120 DisplayError("Failed to set up pipe descriptor objects");
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
));
139 close(displaypipe
[0]);
140 close(displaypipe
[1]);
142 DisplayError("Failed to create input pipe: %s", strerror(errno
));
146 D(kprintf("[Bootstrap] Launching kickstart...\n"));
152 close(displaypipe
[0]);
153 close(displaypipe
[1]);
157 DisplayError("Failed to run kickstart!");
161 /* Set up client side of pipes */
162 DisplayPipe
= displaypipe
[1];
163 InputPipe
= inputpipe
[0];
164 close(displaypipe
[0]);
167 D(kprintf("[Bootstrap] entering kernel at %p...\n", EntryPoint
));
168 i
= EntryPoint(BootMsg
, AROS_BOOT_MAGIC
);
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]);
180 /* Return to JVM with success indication */
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
));