Files
photon/photon/libc/sys/magenta/init.c
2020-12-21 13:06:40 +00:00

161 lines
3.9 KiB
C

#include <magenta/task.h>
#include <magenta/tunnel.h>
#include <magenta/bootstrap.h>
#include <magenta/errors.h>
#include <magenta/misc.h>
#include <stdio.h>
#include "sys/handles.h"
#include "__init.h"
#include "__heap.h"
#include "__fio.h"
struct handles {
mx_handle_t task_self;
mx_handle_t task_vmar;
mx_handle_t exec_vmar;
mx_handle_t stack_vmo;
mx_handle_t vdso_vmo;
mx_handle_t exec_vmo;
mx_handle_t ldsvc;
mx_handle_t bootstrap;
};
static struct handles rt_handles;
extern int main(int, const char **);
static void parse_args(
mx_bootstrap_msg_t *args, mx_handle_t *handles,
const char **argv, const char **envp, int hndc, struct handles *out)
{
if (args->args_num > 0) {
char *arg_buf = (char *)args + args->args_off;
int arg_i = 0;
int arg_off = 0;
for (int i = 0; ; i++) {
if (arg_buf[i] == '\0') {
argv[arg_i++] = arg_buf + arg_off;
arg_off = i + 1;
}
if (arg_i == (int)args->args_num) {
break;
}
}
}
if (args->environ_num > 0) {
char *env_buf = (char *)args + args->environ_off;
int env_i = 0;
int env_off = 0;
for (int i = 0; ; i++) {
if (env_buf[i] == '\0') {
envp[env_i++] = env_buf + env_off;
env_off = i + 1;
}
if (env_i == (int)args->environ_num) {
break;
}
}
}
uint32_t *hent = (uint32_t *)((char *)args + args->handle_info_off);
for (int i = 0; i < hndc; i++) {
switch (MX_B_HND_TYPE(hent[i])) {
case MX_B_TASK_SELF:
out->task_self = handles[i];
break;
case MX_B_VMO_VDSO:
out->vdso_vmo = handles[i];
break;
case MX_B_VMO_STACK:
out->stack_vmo = handles[i];
break;
case MX_B_VMAR_ROOT:
out->task_vmar = handles[i];
break;
case MX_B_VMAR_EXEC:
out->exec_vmar = handles[i];
break;
case MX_B_VMO_EXECUTABLE:
out->exec_vmo = handles[i];
break;
case MX_B_TUNNEL_LDSVC:
out->ldsvc = handles[i];
break;
#if 0
case MX_B_VMO_BOOTDATA:
out->bootfs_vmo = handles[i];
break;
#endif
default:
break;
}
}
}
static void hang()
{
while (1) {
mx_nanosleep(mx_deadline_after(MX_SEC(1)));
}
}
int __crt_init(mx_handle_t bootstrap)
{
size_t msg_size = 0;
size_t nr_handles = 0;
mx_status_t status = mx_tunnel_read(bootstrap, NULL, 0, NULL, 0, &msg_size, &nr_handles);
if (status != MX_OK) {
/* TODO replace with a better error handler */
printf("error: cannot read bootstrap message from handle %lx (error %d)\n",
bootstrap, status);
hang();
}
unsigned char msg_buf[msg_size];
mx_handle_t handles[nr_handles];
mx_tunnel_read(bootstrap, msg_buf, msg_size, handles, nr_handles, &msg_size, &nr_handles);
mx_bootstrap_msg_t *msg = (mx_bootstrap_msg_t *)msg_buf;
const char *argv[msg->args_num];
const char *envp[msg->environ_num];
parse_args(msg, handles, argv, envp, nr_handles, &rt_handles);
rt_handles.bootstrap = bootstrap;
int ret = main(msg->args_num, argv);
mx_task_kill(rt_handles.task_self, ret);
/* unreachable */
hang();
return 0;
}
mx_handle_t m_get_handle(unsigned int type)
{
switch (type) {
case M_HND_VMAR_ROOT:
return rt_handles.task_vmar;
case M_HND_VMAR_EXEC:
return rt_handles.exec_vmar;
case M_HND_VMO_EXEC:
return rt_handles.exec_vmo;
case M_HND_VMO_VDSO:
return rt_handles.vdso_vmo;
case M_HND_TNL_LDSVC:
return rt_handles.ldsvc;
case M_HND_TNL_BTSTP:
return rt_handles.bootstrap;
default:
return MX_NULL_HANDLE;
}
}