Chromium Code Reviews| Index: components/nacl/loader/bare_metal/bare_metal_main.c |
| diff --git a/components/nacl/loader/bare_metal/bare_metal_main.c b/components/nacl/loader/bare_metal/bare_metal_main.c |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..65abff8d717fcef1e129e0ae25e0b60c8db999d7 |
| --- /dev/null |
| +++ b/components/nacl/loader/bare_metal/bare_metal_main.c |
| @@ -0,0 +1,280 @@ |
| +/* |
|
Mark Seaborn
2013/12/06 03:21:16
Can you make these .cc files rather than .c files?
hidehiko
2013/12/06 17:40:02
I see. I fully rewrote the code with C++. Along th
|
| + * Copyright 2013 The Native Client Authors. All rights reserved. |
| + * Use of this source code is governed by a BSD-style license that can be |
| + * found in the LICENSE file. |
| + */ |
| + |
| +#include "components/nacl/loader/bare_metal/bare_metal_main.h" |
| + |
| +#include "components/nacl/loader/bare_metal/bare_metal_error_code.h" |
| +#include "components/nacl/loader/bare_metal/elf_util.h" |
| +#include "native_client/src/include/elf_auxv.h" |
| +#include "native_client/src/public/secure_service.h" |
| +#include "native_client/src/shared/platform/nacl_log.h" |
| +#include "native_client/src/shared/srpc/nacl_srpc.h" |
| +#include "native_client/src/trusted/desc/nacl_desc_base.h" |
| +#include "native_client/src/trusted/desc/nrd_xfer.h" |
| +#include "native_client/src/trusted/fault_injection/fault_injection.h" |
| +#include "native_client/src/trusted/desc/nacl_desc_imc.h" |
| +#include "native_client/src/include/nacl_macros.h" |
| +#include "native_client/src/trusted/desc/nrd_all_modules.h" |
| + |
| +/* Copied from native_client/src/trusted/service_runtime/include/sys/errno.h */ |
| +#define NACL_ABI_EINVAL 22 |
| + |
| +#define NOTIMPLEMENTED() NaClLog(LOG_FATAL, "%s: Not Implemented\n", __func__) |
| + |
| +static void NaClBareMetalLoadModuleRpc( |
| + struct NaClSrpcRpc *rpc, |
| + struct NaClSrpcArg **in_args, |
| + struct NaClSrpcArg **out_args, |
| + struct NaClSrpcClosure *done_cls) { |
| + struct NaClDesc *desc = in_args[0]->u.hval; |
| + NaClBareMetalErrorCode error = BARE_METAL_LOAD_INTERNAL; |
| + struct NaClBareMetalElfImage *image = NULL; |
| + uintptr_t entry_point; |
| + uintptr_t *info; |
| + int j; |
| + UNREFERENCED_PARAMETER(out_args); |
| + |
| + NaClLog(4, "NaClBareMetalLoadModuleRpc: loading module\n"); |
| + rpc->result = NACL_SRPC_RESULT_INTERNAL; |
| + |
| + image = NaClBareMetalElfImageNew(desc, &error); |
| + if (NULL == image || BARE_METAL_LOAD_OK != error) { |
| + NaClLog(4, "NaClBareMetalLoadModuleRpc: Failed to read binary.\n"); |
| + goto cleanup; |
| + } |
| + |
| + if (NaClBareMetalElfImageLoad(image, desc) != BARE_METAL_LOAD_OK) { |
| + NaClLog(4, "NaClBareMetalLoadModuleRpc: Failed to load the image.\n"); |
| + goto cleanup; |
| + } |
| + |
| + entry_point = NaClBareMetalElfImageGetEntryPoint(image); |
| + NaClLog(4, "NaClBareMetalLoadModuleRpc: Load is done %"NACL_PRIuPTR"\n", |
| + entry_point); |
| + rpc->result = NACL_SRPC_RESULT_OK; |
| + |
| + /* Run for testing. TODO(hidehiko): Remove this */ |
| + info = (uintptr_t*) alloca(sizeof(uintptr_t) * 7); |
| + j = 0; |
| + info[j++] = 0; /* Do not use fini. */ |
| + info[j++] = 0; /* envc. */ |
| + info[j++] = 0; /* argc. */ |
| + info[j++] = 0; /* Null terminate for argv. */ |
| + info[j++] = 0; /* Null terminate for envv. */ |
| + info[j++] = AT_NULL; |
| + info[j++] = 0; /* Null terminate for auxv. */ |
| + ((void (*)(uintptr_t *info)) entry_point)(info); |
| + cleanup: |
| + NaClBareMetalElfImageDelete(image); |
| + NaClDescUnref(desc); |
| +} |
| + |
| +static void NaClBareMetalReverseSetupRpc( |
| + struct NaClSrpcRpc *rpc, |
| + struct NaClSrpcArg **in_args, |
| + struct NaClSrpcArg **out_args, |
| + struct NaClSrpcClosure *done_cls) { |
| + NaClLog(4, "NaClBareMetalReverseSetupRpc\n"); |
| + NOTIMPLEMENTED(); |
| +} |
| + |
| +static void NaClBareMetalStartModuleRpc( |
| + struct NaClSrpcRpc *rpc, |
| + struct NaClSrpcArg **in_args, |
| + struct NaClSrpcArg **out_args, |
| + struct NaClSrpcClosure *done_cls) { |
| + NaClLog(4, "NaClBareMetalStartModuleRpc\n"); |
| + NOTIMPLEMENTED(); |
| +} |
| + |
| +static void NaClBareMetalLogRpc( |
| + struct NaClSrpcRpc *rpc, |
| + struct NaClSrpcArg **in_args, |
| + struct NaClSrpcArg **out_args, |
| + struct NaClSrpcClosure *done_cls) { |
| + int severity = in_args[0]->u.ival; |
| + char *msg = in_args[1]->arrays.str; |
| + UNREFERENCED_PARAMETER(out_args); |
| + |
| + NaClLog(5, "NaClSecureChannelLogRpc\n"); |
| + NaClLog(severity, "%s\n", msg); |
| + NaClLog(5, "NaClSecureChannelLogRpc\n"); |
| + rpc->result = NACL_SRPC_RESULT_OK; |
| + (*done_cls->Run)(done_cls); |
| +} |
| + |
| +static void NaClBareMetalShutdownRpc( |
| + struct NaClSrpcRpc *rpc, |
| + struct NaClSrpcArg **in_args, |
| + struct NaClSrpcArg **out_args, |
| + struct NaClSrpcClosure *done_cls) { |
| + NaClLog(4, "NaClBareMetalShutdownRpc\n"); |
| + NOTIMPLEMENTED(); |
| +} |
| + |
| +const static struct NaClSrpcHandlerDesc kBareMetalServiceHandlers[] = { |
| + { NACL_SECURE_SERVICE_LOAD_MODULE, NaClBareMetalLoadModuleRpc, }, |
| + { NACL_SECURE_SERVICE_REVERSE_SETUP, NaClBareMetalReverseSetupRpc, }, |
| + { NACL_SECURE_SERVICE_START_MODULE, NaClBareMetalStartModuleRpc, }, |
| + { NACL_SECURE_SERVICE_LOG, NaClBareMetalLogRpc, }, |
| + { NACL_SECURE_SERVICE_HARD_SHUTDOWN, NaClBareMetalShutdownRpc, }, |
| + { (char const *) NULL, (NaClSrpcMethod) NULL, }, |
| +}; |
| + |
| +/* Creates two socketpairs to communicate with the host process. */ |
| +static void NaClBareMetalCreateSecureSocketPair( |
| + struct NaClDesc *secure_pair[2], |
| + struct NaClDesc *pair[2]) { |
| + NaClLog(3, "Entered NaClBareMetalCreateSecureSocketPair\n"); |
| + |
| + if (NACL_FI_ERROR_COND( |
| + "NaClBareMetalCreateSecureSocketPair__secure_boundsock", |
| + 0 != NaClCommonDescMakeBoundSock(secure_pair))) { |
| + NaClLog(LOG_FATAL, "Cound not create secure service socket\n"); |
| + } |
| + NaClLog(4, |
| + "got bound socket at 0x%08"NACL_PRIxPTR", " |
| + "addr at 0x%08"NACL_PRIxPTR"\n", |
| + (uintptr_t) secure_pair[0], |
| + (uintptr_t) secure_pair[1]); |
| + |
| + if (NACL_FI_ERROR_COND("NaClBareMetalCreateSecureSocketPair__boundsock", |
| + 0 != NaClCommonDescMakeBoundSock(pair))) { |
| + NaClLog(LOG_FATAL, "Cound not create service socket\n"); |
| + } |
| + NaClLog(4, |
| + "got bound socket at 0x%08"NACL_PRIxPTR", " |
| + "addr at 0x%08"NACL_PRIxPTR"\n", |
| + (uintptr_t) pair[0], |
| + (uintptr_t) pair[1]); |
| + NaClDescRef(pair[0]); |
| + NaClDescRef(pair[1]); |
| + |
| + NaClLog(4, "Leaving NaClCreateServiceSocket\n"); |
| +} |
| + |
| + |
| +static struct NaClDesc *NaClBareMetalSetUpBootstrapChannel( |
| + NaClHandle handle, |
| + struct NaClDesc *secure_service_address, |
| + struct NaClDesc *service_address) { |
| + struct NaClDescImcDesc *channel; |
| + struct NaClImcTypedMsgHdr hdr; |
| + struct NaClDesc *descs[2]; |
| + ssize_t error; |
| + |
| + NaClLog(3, "Entered NaClBareMetalSetUpBootstrapChannel\n"); |
| + |
| + if (NULL == secure_service_address) { |
| + NaClLog(LOG_FATAL, |
| + ("NaClBareMetalSetUpBootstrapChannel: secure_service_address" |
| + " is not set\n")); |
| + return NULL; |
| + } |
| + |
| + if (NULL == service_address) { |
| + NaClLog( |
| + LOG_FATAL, |
| + "NaClBareMetalSetUpBootstrapChannel: service_address is not set\n"); |
| + return NULL; |
| + } |
| + |
| + /* Create a NaClDesc by wrapping the given handle. */ |
| + channel = (struct NaClDescImcDesc *) malloc(sizeof *channel); |
| + if (NULL == channel) { |
| + NaClLog(LOG_FATAL, "NaClBareMetalSetUpBootstrapChannel: no memory\n"); |
| + return NULL; |
| + } |
| + if (!NaClDescImcDescCtor(channel, handle)) { |
| + NaClLog(LOG_FATAL, |
| + ("NaClBareMetalSetUpBootstrapChannel:" |
| + " cannot construct IMC descriptor" |
| + " object for inherited descriptor %"NACL_PRIdPTR"\n"), |
| + (uintptr_t) handle); |
| + free(channel); |
| + return NULL; |
| + } |
| + |
| + /* Send the descriptors to the host. */ |
| + descs[0] = secure_service_address; |
| + descs[1] = service_address; |
| + |
| + hdr.iov = (struct NaClImcMsgIoVec *) NULL; |
| + hdr.iov_length = 0; |
| + hdr.ndescv = descs; |
| + hdr.ndesc_length = NACL_ARRAY_SIZE(descs); |
| + |
| + error = (*NACL_VTBL(NaClDesc, channel)->SendMsg)( |
| + (struct NaClDesc *) channel, |
| + &hdr, |
| + 0); |
| + NaClLog(1, |
| + ("NaClBareMetalSetUpBootstrapChannel: descriptor %"NACL_PRIdPTR", " |
| + "error %"NACL_PRIdS"\n"), |
| + (uintptr_t) handle, |
| + error); |
| + if (NACL_FI_ERROR_COND("NaClBareMetalSetUpBootstrapChannel__SendMsg", |
| + 0 != error)) { |
| + NaClLog(LOG_FATAL, |
| + ("NaClBareMetalSetUpBootstrapChannel: SendMsg failed, " |
| + "error = %"NACL_PRIdS"\n"), |
| + error); |
| + } |
| + |
| + return (struct NaClDesc *) channel; |
| +} |
| + |
| +static void NaClBareMetalServiceAccept(struct NaClDesc *port) { |
| + int status = -NACL_ABI_EINVAL; |
| + struct NaClDesc *connected_desc = NULL; |
| + |
| + NaClLog(3, "Entered NaClBareMetalServiceAccept\n"); |
| + |
| + status = (*NACL_VTBL(NaClDesc, port)->AcceptConn)(port, &connected_desc); |
| + if (0 != status) { |
| + NaClLog(4, "NaClBareMetalServiceAccept: Failed to accept %d\n", status); |
| + return; |
| + } |
| + |
| + NaClLog(4, "NaClBareMetalServiceAccept: Start server loop.\n"); |
| + NaClSrpcServerLoop(connected_desc, kBareMetalServiceHandlers, NULL); |
| +} |
| + |
| +static void NaClBareMetalAllModulesInit(void) { |
| + NaClNrdAllModulesInit(); |
| + NaClFaultInjectionModuleInit(); |
| + NaClSrpcModuleInit(); |
| +} |
| + |
| +void NaClBareMetalMainStart(NaClHandle imc_bootstrap_handle) { |
|
Mark Seaborn
2013/12/06 03:21:16
Can you hook this up so that it's called by nacl_l
hidehiko
2013/12/06 17:40:02
Done. Note that the flag is added to content_switc
|
| + struct NaClDesc *secure_pair[2] = { NULL, NULL }; |
| + struct NaClDesc *pair[2] = { NULL, NULL }; |
| + struct NaClDesc *channel = NULL; |
| + |
| + NaClLog(3, "NaClBareMetalMainStart\n"); |
| + |
| + NaClBareMetalAllModulesInit(); |
| + NaClBareMetalCreateSecureSocketPair(secure_pair, pair); |
| + channel = NaClBareMetalSetUpBootstrapChannel( |
| + imc_bootstrap_handle, secure_pair[1], pair[1]); |
| + if (NULL == channel) { |
| + NaClLog(4, |
| + "NaClBareMetalMainStart: Failed to set up bootstrap channel.\n"); |
| + goto cleanup; |
| + } |
| + |
| + /* Start the SRPC server loop. */ |
| + NaClLog(4, "NaClBareMetalMainStart: Start server loop.\n"); |
| + NaClBareMetalServiceAccept(secure_pair[0]); |
| + |
| + cleanup: |
| + NaClLog(4, "NaClBareMetalMainStart: Clean up.\n"); |
| + NaClDescSafeUnref(channel); |
| + NaClDescSafeUnref(pair[0]); |
| + NaClDescSafeUnref(pair[1]); |
| + NaClDescSafeUnref(secure_pair[0]); |
| + NaClDescSafeUnref(secure_pair[1]); |
| +} |